aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CREDITS34
-rw-r--r--Documentation/DMA-API.txt49
-rw-r--r--Documentation/DMA-mapping.txt28
-rw-r--r--Documentation/DocBook/Makefile2
-rw-r--r--Documentation/DocBook/kernel-api.tmpl1
-rw-r--r--Documentation/DocBook/libata.tmpl49
-rw-r--r--Documentation/HOWTO3
-rw-r--r--Documentation/RCU/whatisRCU.txt2
-rw-r--r--Documentation/acpi-hotkey.txt2
-rw-r--r--Documentation/arm/SA1100/Assabet2
-rw-r--r--Documentation/arm/SA1100/LART2
-rw-r--r--Documentation/block/biodoc.txt14
-rw-r--r--Documentation/block/switching-sched.txt22
-rw-r--r--Documentation/cpu-freq/index.txt2
-rw-r--r--Documentation/cpu-hotplug.txt4
-rw-r--r--Documentation/cputopology.txt4
-rw-r--r--Documentation/devices.txt5
-rw-r--r--Documentation/dvb/get_dvb_firmware8
-rw-r--r--Documentation/feature-removal-schedule.txt41
-rw-r--r--Documentation/filesystems/00-INDEX54
-rw-r--r--Documentation/filesystems/sysfs.txt5
-rw-r--r--Documentation/filesystems/vfs.txt12
-rw-r--r--Documentation/firmware_class/README17
-rw-r--r--Documentation/firmware_class/firmware_sample_driver.c11
-rw-r--r--Documentation/fujitsu/frv/kernel-ABI.txt192
-rw-r--r--Documentation/i2c/busses/i2c-parport16
-rw-r--r--Documentation/input/joystick-parport.txt11
-rw-r--r--Documentation/ioctl-number.txt2
-rw-r--r--Documentation/isdn/README.gigaset286
-rw-r--r--Documentation/kbuild/modules.txt2
-rw-r--r--Documentation/kernel-parameters.txt34
-rw-r--r--Documentation/laptop-mode.txt10
-rw-r--r--Documentation/leds-class.txt71
-rw-r--r--Documentation/m68k/README.buddha2
-rw-r--r--Documentation/memory-barriers.txt2133
-rw-r--r--Documentation/mtrr.txt23
-rw-r--r--Documentation/networking/TODO18
-rw-r--r--Documentation/networking/bcm43xx.txt36
-rw-r--r--Documentation/networking/ifenslave.c2
-rw-r--r--Documentation/networking/operstates.txt161
-rw-r--r--Documentation/networking/packet_mmap.txt2
-rw-r--r--Documentation/networking/tuntap.txt2
-rw-r--r--Documentation/networking/xfrm_sync.txt166
-rw-r--r--Documentation/pci.txt12
-rw-r--r--Documentation/pcmcia/driver-changes.txt6
-rw-r--r--Documentation/pnp.txt3
-rw-r--r--Documentation/power/video.txt2
-rw-r--r--Documentation/powerpc/booting-without-of.txt5
-rw-r--r--Documentation/robust-futex-ABI.txt182
-rw-r--r--Documentation/robust-futexes.txt218
-rw-r--r--Documentation/rpc-cache.txt121
-rw-r--r--Documentation/scsi/ChangeLog.megaraid25
-rw-r--r--Documentation/scsi/scsi_eh.txt14
-rw-r--r--Documentation/scsi/scsi_mid_low_api.txt19
-rw-r--r--Documentation/serial/driver31
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt69
-rw-r--r--Documentation/sound/alsa/Audiophile-Usb.txt81
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl20
-rw-r--r--Documentation/spi/pxa2xx234
-rw-r--r--Documentation/spi/spi-summary34
-rw-r--r--Documentation/video4linux/CARDLIST.saa71345
-rw-r--r--Documentation/video4linux/et61x251.txt (renamed from Documentation/usb/et61x251.txt)0
-rw-r--r--Documentation/video4linux/ibmcam.txt (renamed from Documentation/usb/ibmcam.txt)2
-rw-r--r--Documentation/video4linux/ov511.txt (renamed from Documentation/usb/ov511.txt)11
-rw-r--r--Documentation/video4linux/se401.txt (renamed from Documentation/usb/se401.txt)0
-rw-r--r--Documentation/video4linux/sn9c102.txt (renamed from Documentation/usb/sn9c102.txt)16
-rw-r--r--Documentation/video4linux/stv680.txt (renamed from Documentation/usb/stv680.txt)26
-rw-r--r--Documentation/video4linux/w9968cf.txt (renamed from Documentation/usb/w9968cf.txt)36
-rw-r--r--Documentation/video4linux/zc0301.txt (renamed from Documentation/usb/zc0301.txt)0
-rw-r--r--Documentation/vm/hugetlbpage.txt31
-rw-r--r--Documentation/watchdog/watchdog-api.txt3
-rw-r--r--Documentation/x86_64/boot-options.txt5
-rw-r--r--Kbuild2
-rw-r--r--MAINTAINERS118
-rw-r--r--Makefile80
-rw-r--r--README23
-rw-r--r--arch/alpha/Kconfig7
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c4
-rw-r--r--arch/alpha/kernel/core_marvel.c2
-rw-r--r--arch/alpha/kernel/process.c6
-rw-r--r--arch/alpha/kernel/setup.c47
-rw-r--r--arch/alpha/kernel/smp.c16
-rw-r--r--arch/alpha/kernel/sys_titan.c2
-rw-r--r--arch/alpha/kernel/time.c3
-rw-r--r--arch/alpha/lib/strncpy.S8
-rw-r--r--arch/alpha/mm/numa.c4
-rw-r--r--arch/arm/Kconfig32
-rw-r--r--arch/arm/Kconfig-nommu44
-rw-r--r--arch/arm/Kconfig.debug2
-rw-r--r--arch/arm/Makefile13
-rw-r--r--arch/arm/boot/compressed/Makefile4
-rw-r--r--arch/arm/boot/compressed/head.S106
-rw-r--r--arch/arm/boot/compressed/ice-dcc.S17
-rw-r--r--arch/arm/boot/compressed/misc.c41
-rw-r--r--arch/arm/boot/compressed/vmlinux.lds.in1
-rw-r--r--arch/arm/common/rtctime.c108
-rw-r--r--arch/arm/common/scoop.c12
-rw-r--r--arch/arm/common/sharpsl_pm.c10
-rw-r--r--arch/arm/configs/at91rm9200dk_defconfig2
-rw-r--r--arch/arm/configs/at91rm9200ek_defconfig2
-rw-r--r--arch/arm/configs/collie_defconfig430
-rw-r--r--arch/arm/configs/ep93xx_defconfig79
-rw-r--r--arch/arm/configs/ixp2000_defconfig59
-rw-r--r--arch/arm/configs/ixp23xx_defconfig1304
-rw-r--r--arch/arm/configs/versatile_defconfig390
-rw-r--r--arch/arm/kernel/Makefile2
-rw-r--r--arch/arm/kernel/armksyms.c14
-rw-r--r--arch/arm/kernel/asm-offsets.c8
-rw-r--r--arch/arm/kernel/dma-isa.c23
-rw-r--r--arch/arm/kernel/entry-armv.S2
-rw-r--r--arch/arm/kernel/head-common.S217
-rw-r--r--arch/arm/kernel/head-nommu.S83
-rw-r--r--arch/arm/kernel/head.S215
-rw-r--r--arch/arm/kernel/process.c38
-rw-r--r--arch/arm/kernel/setup.c17
-rw-r--r--arch/arm/kernel/signal.h2
-rw-r--r--arch/arm/kernel/traps.c9
-rw-r--r--arch/arm/lib/Makefile2
-rw-r--r--arch/arm/lib/backtrace.S4
-rw-r--r--arch/arm/lib/copy_template.S2
-rw-r--r--arch/arm/lib/div64.S4
-rw-r--r--arch/arm/mach-aaec2000/aaed2000.c7
-rw-r--r--arch/arm/mach-aaec2000/core.c5
-rw-r--r--arch/arm/mach-aaec2000/core.h1
-rw-r--r--arch/arm/mach-at91rm9200/Makefile9
-rw-r--r--arch/arm/mach-at91rm9200/board-csb337.c3
-rw-r--r--arch/arm/mach-at91rm9200/board-csb637.c3
-rw-r--r--arch/arm/mach-at91rm9200/board-dk.c10
-rw-r--r--arch/arm/mach-at91rm9200/board-ek.c10
-rw-r--r--arch/arm/mach-at91rm9200/devices.c166
-rw-r--r--arch/arm/mach-at91rm9200/leds.c100
-rw-r--r--arch/arm/mach-ep93xx/core.c78
-rw-r--r--arch/arm/mach-ep93xx/ts72xx.c39
-rw-r--r--arch/arm/mach-footbridge/time.c17
-rw-r--r--arch/arm/mach-imx/dma.c511
-rw-r--r--arch/arm/mach-imx/generic.c63
-rw-r--r--arch/arm/mach-imx/irq.c2
-rw-r--r--arch/arm/mach-imx/mx1ads.c94
-rw-r--r--arch/arm/mach-integrator/core.c46
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c5
-rw-r--r--arch/arm/mach-integrator/time.c16
-rw-r--r--arch/arm/mach-ixp23xx/Kconfig25
-rw-r--r--arch/arm/mach-ixp23xx/Makefile11
-rw-r--r--arch/arm/mach-ixp23xx/Makefile.boot2
-rw-r--r--arch/arm/mach-ixp23xx/core.c443
-rw-r--r--arch/arm/mach-ixp23xx/espresso.c78
-rw-r--r--arch/arm/mach-ixp23xx/ixdp2351.c325
-rw-r--r--arch/arm/mach-ixp23xx/pci.c291
-rw-r--r--arch/arm/mach-ixp23xx/roadrunner.c164
-rw-r--r--arch/arm/mach-ixp4xx/Kconfig17
-rw-r--r--arch/arm/mach-ixp4xx/Makefile3
-rw-r--r--arch/arm/mach-ixp4xx/common.c2
-rw-r--r--arch/arm/mach-omap1/Kconfig20
-rw-r--r--arch/arm/mach-omap1/Makefile11
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c116
-rw-r--r--arch/arm/mach-omap1/board-generic.c2
-rw-r--r--arch/arm/mach-omap1/board-h2.c200
-rw-r--r--arch/arm/mach-omap1/board-h3.c277
-rw-r--r--arch/arm/mach-omap1/board-innovator.c56
-rw-r--r--arch/arm/mach-omap1/board-netstar.c160
-rw-r--r--arch/arm/mach-omap1/board-nokia770.c268
-rw-r--r--arch/arm/mach-omap1/board-osk.c95
-rw-r--r--arch/arm/mach-omap1/board-palmte.c12
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c123
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c6
-rw-r--r--arch/arm/mach-omap1/clock.c9
-rw-r--r--arch/arm/mach-omap1/clock.h91
-rw-r--r--arch/arm/mach-omap1/devices.c45
-rw-r--r--arch/arm/mach-omap1/io.c4
-rw-r--r--arch/arm/mach-omap1/irq.c18
-rw-r--r--arch/arm/mach-omap1/mux.c30
-rw-r--r--arch/arm/mach-omap1/pm.c770
-rw-r--r--arch/arm/mach-omap1/serial.c6
-rw-r--r--arch/arm/mach-omap1/sleep.S (renamed from arch/arm/plat-omap/sleep.S)111
-rw-r--r--arch/arm/mach-omap1/time.c197
-rw-r--r--arch/arm/mach-omap2/Kconfig3
-rw-r--r--arch/arm/mach-omap2/Makefile6
-rw-r--r--arch/arm/mach-omap2/board-apollon.c285
-rw-r--r--arch/arm/mach-omap2/board-h4.c174
-rw-r--r--arch/arm/mach-omap2/clock.c79
-rw-r--r--arch/arm/mach-omap2/clock.h37
-rw-r--r--arch/arm/mach-omap2/devices.c46
-rw-r--r--arch/arm/mach-omap2/io.c21
-rw-r--r--arch/arm/mach-omap2/memory.c102
-rw-r--r--arch/arm/mach-omap2/memory.h34
-rw-r--r--arch/arm/mach-omap2/mux.c45
-rw-r--r--arch/arm/mach-omap2/pm.c149
-rw-r--r--arch/arm/mach-omap2/prcm-regs.h (renamed from arch/arm/mach-omap2/prcm.h)188
-rw-r--r--arch/arm/mach-omap2/prcm.c40
-rw-r--r--arch/arm/mach-omap2/sleep.S144
-rw-r--r--arch/arm/mach-omap2/sram-fn.S4
-rw-r--r--arch/arm/mach-pxa/Kconfig5
-rw-r--r--arch/arm/mach-pxa/Makefile1
-rw-r--r--arch/arm/mach-pxa/corgi.c11
-rw-r--r--arch/arm/mach-pxa/corgi_ssp.c9
-rw-r--r--arch/arm/mach-pxa/dma.c17
-rw-r--r--arch/arm/mach-pxa/generic.c6
-rw-r--r--arch/arm/mach-pxa/lpd270.c393
-rw-r--r--arch/arm/mach-pxa/mainstone.c6
-rw-r--r--arch/arm/mach-pxa/poodle.c4
-rw-r--r--arch/arm/mach-pxa/spitz.c14
-rw-r--r--arch/arm/mach-pxa/tosa.c9
-rw-r--r--arch/arm/mach-realview/realview_eb.c5
-rw-r--r--arch/arm/mach-s3c2410/Kconfig9
-rw-r--r--arch/arm/mach-s3c2410/Makefile2
-rw-r--r--arch/arm/mach-s3c2410/clock.c6
-rw-r--r--arch/arm/mach-s3c2410/common-smdk.c135
-rw-r--r--arch/arm/mach-s3c2410/common-smdk.h15
-rw-r--r--arch/arm/mach-s3c2410/mach-anubis.c4
-rw-r--r--arch/arm/mach-s3c2410/mach-rx3715.c35
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c13
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2440.c17
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-clock.c2
-rw-r--r--arch/arm/mach-s3c2410/sleep.S6
-rw-r--r--arch/arm/mach-sa1100/Kconfig2
-rw-r--r--arch/arm/mach-sa1100/collie.c72
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1100.c2
-rw-r--r--arch/arm/mach-sa1100/generic.c6
-rw-r--r--arch/arm/mach-sa1100/irq.c16
-rw-r--r--arch/arm/mach-sa1100/neponset.c8
-rw-r--r--arch/arm/mach-versatile/core.c5
-rw-r--r--arch/arm/mm/Kconfig19
-rw-r--r--arch/arm/mm/Makefile2
-rw-r--r--arch/arm/mm/cache-v4wb.S26
-rw-r--r--arch/arm/mm/consistent.c17
-rw-r--r--arch/arm/mm/copypage-xsc3.S97
-rw-r--r--arch/arm/mm/init.c7
-rw-r--r--arch/arm/mm/ioremap.c4
-rw-r--r--arch/arm/mm/mm-armv.c18
-rw-r--r--arch/arm/mm/proc-sa110.S25
-rw-r--r--arch/arm/mm/proc-sa1100.S37
-rw-r--r--arch/arm/mm/proc-v6.S16
-rw-r--r--arch/arm/mm/proc-xsc3.S500
-rw-r--r--arch/arm/plat-omap/Kconfig4
-rw-r--r--arch/arm/plat-omap/Makefile6
-rw-r--r--arch/arm/plat-omap/clock.c68
-rw-r--r--arch/arm/plat-omap/devices.c159
-rw-r--r--arch/arm/plat-omap/dma.c6
-rw-r--r--arch/arm/plat-omap/dmtimer.c26
-rw-r--r--arch/arm/plat-omap/fb.c80
-rw-r--r--arch/arm/plat-omap/gpio.c86
-rw-r--r--arch/arm/plat-omap/mcbsp.c345
-rw-r--r--arch/arm/plat-omap/ocpi.c3
-rw-r--r--arch/arm/plat-omap/pm.c1
-rw-r--r--arch/arm/plat-omap/sram.c143
-rw-r--r--arch/arm/plat-omap/timer32k.c325
-rw-r--r--arch/arm/tools/mach-types89
-rw-r--r--arch/arm/vfp/vfpdouble.c31
-rw-r--r--arch/arm/vfp/vfphw.S6
-rw-r--r--arch/arm/vfp/vfpmodule.c4
-rw-r--r--arch/arm/vfp/vfpsingle.c11
-rw-r--r--arch/arm26/kernel/armksyms.c3
-rw-r--r--arch/arm26/mm/init.c7
-rw-r--r--arch/cris/kernel/crisksyms.c1
-rw-r--r--arch/cris/kernel/setup.c5
-rw-r--r--arch/frv/kernel/entry.S26
-rw-r--r--arch/frv/kernel/frv_ksyms.c3
-rw-r--r--arch/h8300/kernel/h8300_ksyms.c3
-rw-r--r--arch/i386/Kconfig92
-rw-r--r--arch/i386/Kconfig.cpu2
-rw-r--r--arch/i386/Kconfig.debug9
-rw-r--r--arch/i386/boot/video.S7
-rw-r--r--arch/i386/kernel/Makefile2
-rw-r--r--arch/i386/kernel/acpi/boot.c7
-rw-r--r--arch/i386/kernel/acpi/earlyquirk.c23
-rw-r--r--arch/i386/kernel/apic.c57
-rw-r--r--arch/i386/kernel/apm.c2
-rw-r--r--arch/i386/kernel/cpu/amd.c4
-rw-r--r--arch/i386/kernel/cpu/common.c10
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c29
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.h4
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c79
-rw-r--r--arch/i386/kernel/cpu/mcheck/mce.c4
-rw-r--r--arch/i386/kernel/cpuid.c2
-rw-r--r--arch/i386/kernel/crash.c2
-rw-r--r--arch/i386/kernel/i386_ksyms.c1
-rw-r--r--arch/i386/kernel/io_apic.c11
-rw-r--r--arch/i386/kernel/kprobes.c39
-rw-r--r--arch/i386/kernel/microcode.c17
-rw-r--r--arch/i386/kernel/mpparse.c55
-rw-r--r--arch/i386/kernel/msr.c2
-rw-r--r--arch/i386/kernel/nmi.c9
-rw-r--r--arch/i386/kernel/process.c1
-rw-r--r--arch/i386/kernel/ptrace.c7
-rw-r--r--arch/i386/kernel/reboot_fixups.c2
-rw-r--r--arch/i386/kernel/setup.c70
-rw-r--r--arch/i386/kernel/smpboot.c28
-rw-r--r--arch/i386/kernel/syscall_table.S6
-rw-r--r--arch/i386/kernel/timers/timer_pm.c104
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c4
-rw-r--r--arch/i386/kernel/traps.c39
-rw-r--r--arch/i386/kernel/vm86.c2
-rw-r--r--arch/i386/kernel/vsyscall-sigreturn.S2
-rw-r--r--arch/i386/mach-generic/probe.c16
-rw-r--r--arch/i386/mach-voyager/voyager_cat.c11
-rw-r--r--arch/i386/mach-voyager/voyager_smp.c2
-rw-r--r--arch/i386/mm/discontig.c12
-rw-r--r--arch/i386/mm/init.c2
-rw-r--r--arch/i386/mm/pgtable.c2
-rw-r--r--arch/i386/oprofile/nmi_int.c9
-rw-r--r--arch/i386/pci/direct.c13
-rw-r--r--arch/i386/pci/irq.c2
-rw-r--r--arch/i386/pci/mmconfig.c67
-rw-r--r--arch/i386/power/cpu.c2
-rw-r--r--arch/ia64/Kconfig22
-rw-r--r--arch/ia64/configs/sn2_defconfig78
-rw-r--r--arch/ia64/hp/common/sba_iommu.c2
-rw-r--r--arch/ia64/ia32/binfmt_elf32.c3
-rw-r--r--arch/ia64/ia32/ia32_entry.S2
-rw-r--r--arch/ia64/kernel/Makefile3
-rw-r--r--arch/ia64/kernel/acpi-ext.c143
-rw-r--r--arch/ia64/kernel/entry.S6
-rw-r--r--arch/ia64/kernel/gate.lds.S1
-rw-r--r--arch/ia64/kernel/iosapic.c269
-rw-r--r--arch/ia64/kernel/irq.c1
-rw-r--r--arch/ia64/kernel/kprobes.c10
-rw-r--r--arch/ia64/kernel/mca.c43
-rw-r--r--arch/ia64/kernel/mca_asm.S10
-rw-r--r--arch/ia64/kernel/mca_drv.c54
-rw-r--r--arch/ia64/kernel/module.c2
-rw-r--r--arch/ia64/kernel/palinfo.c10
-rw-r--r--arch/ia64/kernel/ptrace.c4
-rw-r--r--arch/ia64/kernel/salinfo.c2
-rw-r--r--arch/ia64/kernel/time.c2
-rw-r--r--arch/ia64/kernel/topology.c364
-rw-r--r--arch/ia64/kernel/traps.c6
-rw-r--r--arch/ia64/kernel/vmlinux.lds.S18
-rw-r--r--arch/ia64/lib/memcpy_mck.S9
-rw-r--r--arch/ia64/mm/discontig.c99
-rw-r--r--arch/ia64/mm/fault.c3
-rw-r--r--arch/ia64/mm/init.c10
-rw-r--r--arch/ia64/mm/ioremap.c6
-rw-r--r--arch/ia64/mm/tlb.c12
-rw-r--r--arch/ia64/pci/pci.c3
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c16
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_proc_fs.c39
-rw-r--r--arch/ia64/sn/kernel/xpc_channel.c2
-rw-r--r--arch/ia64/sn/kernel/xpc_partition.c8
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c6
-rw-r--r--arch/m32r/Kconfig5
-rw-r--r--arch/m32r/kernel/entry.S55
-rw-r--r--arch/m32r/kernel/m32r_ksyms.c29
-rw-r--r--arch/m32r/kernel/process.c4
-rw-r--r--arch/m32r/kernel/setup.c13
-rw-r--r--arch/m32r/kernel/signal.c4
-rw-r--r--arch/m32r/kernel/smpboot.c19
-rw-r--r--arch/m32r/lib/Makefile4
-rw-r--r--arch/m32r/lib/getuser.S88
-rw-r--r--arch/m32r/lib/putuser.S84
-rw-r--r--arch/m32r/mm/discontig.c7
-rw-r--r--arch/m32r/mm/init.c3
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c2
-rw-r--r--arch/m68k/mvme16x/rtc.c4
-rw-r--r--arch/m68knommu/kernel/m68k_ksyms.c3
-rw-r--r--arch/mips/Kconfig182
-rw-r--r--arch/mips/Kconfig.debug8
-rw-r--r--arch/mips/Makefile17
-rw-r--r--arch/mips/au1000/common/Makefile2
-rw-r--r--arch/mips/au1000/common/int-handler.S68
-rw-r--r--arch/mips/au1000/common/irq.c21
-rw-r--r--arch/mips/au1000/common/prom.c24
-rw-r--r--arch/mips/au1000/common/setup.c2
-rw-r--r--arch/mips/au1000/common/sleeper.S5
-rw-r--r--arch/mips/au1000/common/time.c1
-rw-r--r--arch/mips/cobalt/Makefile2
-rw-r--r--arch/mips/cobalt/int-handler.S25
-rw-r--r--arch/mips/cobalt/irq.c6
-rw-r--r--arch/mips/configs/atlas_defconfig83
-rw-r--r--arch/mips/configs/bigsur_defconfig64
-rw-r--r--arch/mips/configs/capcella_defconfig143
-rw-r--r--arch/mips/configs/cobalt_defconfig68
-rw-r--r--arch/mips/configs/db1000_defconfig70
-rw-r--r--arch/mips/configs/db1100_defconfig71
-rw-r--r--arch/mips/configs/db1200_defconfig68
-rw-r--r--arch/mips/configs/db1500_defconfig105
-rw-r--r--arch/mips/configs/db1550_defconfig73
-rw-r--r--arch/mips/configs/ddb5476_defconfig69
-rw-r--r--arch/mips/configs/ddb5477_defconfig67
-rw-r--r--arch/mips/configs/decstation_defconfig69
-rw-r--r--arch/mips/configs/e55_defconfig288
-rw-r--r--arch/mips/configs/ev64120_defconfig67
-rw-r--r--arch/mips/configs/ev96100_defconfig64
-rw-r--r--arch/mips/configs/ip22_defconfig77
-rw-r--r--arch/mips/configs/ip27_defconfig54
-rw-r--r--arch/mips/configs/ip32_defconfig67
-rw-r--r--arch/mips/configs/it8172_defconfig66
-rw-r--r--arch/mips/configs/ivr_defconfig67
-rw-r--r--arch/mips/configs/jaguar-atx_defconfig56
-rw-r--r--arch/mips/configs/jmr3927_defconfig72
-rw-r--r--arch/mips/configs/lasat200_defconfig69
-rw-r--r--arch/mips/configs/malta_defconfig86
-rw-r--r--arch/mips/configs/mipssim_defconfig64
-rw-r--r--arch/mips/configs/mpc30x_defconfig95
-rw-r--r--arch/mips/configs/ocelot_3_defconfig72
-rw-r--r--arch/mips/configs/ocelot_c_defconfig66
-rw-r--r--arch/mips/configs/ocelot_defconfig64
-rw-r--r--arch/mips/configs/ocelot_g_defconfig66
-rw-r--r--arch/mips/configs/pb1100_defconfig70
-rw-r--r--arch/mips/configs/pb1500_defconfig73
-rw-r--r--arch/mips/configs/pb1550_defconfig73
-rw-r--r--arch/mips/configs/pnx8550-jbs_defconfig76
-rw-r--r--arch/mips/configs/pnx8550-v2pci_defconfig85
-rw-r--r--arch/mips/configs/qemu_defconfig48
-rw-r--r--arch/mips/configs/rbhma4500_defconfig95
-rw-r--r--arch/mips/configs/rm200_defconfig121
-rw-r--r--arch/mips/configs/sb1250-swarm_defconfig63
-rw-r--r--arch/mips/configs/sead_defconfig50
-rw-r--r--arch/mips/configs/tb0226_defconfig218
-rw-r--r--arch/mips/configs/tb0229_defconfig282
-rw-r--r--arch/mips/configs/tb0287_defconfig1132
-rw-r--r--arch/mips/configs/workpad_defconfig185
-rw-r--r--arch/mips/configs/yosemite_defconfig54
-rw-r--r--arch/mips/ddb5xxx/common/rtc_ds1386.c4
-rw-r--r--arch/mips/ddb5xxx/ddb5074/Makefile2
-rw-r--r--arch/mips/ddb5xxx/ddb5074/int-handler.S120
-rw-r--r--arch/mips/ddb5xxx/ddb5074/irq.c26
-rw-r--r--arch/mips/ddb5xxx/ddb5476/Makefile2
-rw-r--r--arch/mips/ddb5xxx/ddb5476/dbg_io.c2
-rw-r--r--arch/mips/ddb5xxx/ddb5476/int-handler.S112
-rw-r--r--arch/mips/ddb5xxx/ddb5476/irq.c30
-rw-r--r--arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c6
-rw-r--r--arch/mips/ddb5xxx/ddb5477/Makefile2
-rw-r--r--arch/mips/ddb5xxx/ddb5477/int-handler.S75
-rw-r--r--arch/mips/ddb5xxx/ddb5477/irq.c24
-rw-r--r--arch/mips/ddb5xxx/ddb5477/kgdb_io.c2
-rw-r--r--arch/mips/dec/boot/decstation.c3
-rw-r--r--arch/mips/dec/int-handler.S14
-rw-r--r--arch/mips/dec/setup.c3
-rw-r--r--arch/mips/dec/time.c51
-rw-r--r--arch/mips/defconfig77
-rw-r--r--arch/mips/galileo-boards/ev96100/Makefile2
-rw-r--r--arch/mips/galileo-boards/ev96100/int-handler.S33
-rw-r--r--arch/mips/galileo-boards/ev96100/irq.c19
-rw-r--r--arch/mips/gt64120/ev64120/Makefile2
-rw-r--r--arch/mips/gt64120/ev64120/int-handler.S113
-rw-r--r--arch/mips/gt64120/ev64120/irq.c27
-rw-r--r--arch/mips/gt64120/ev64120/serialGT.c2
-rw-r--r--arch/mips/gt64120/momenco_ocelot/Makefile2
-rw-r--r--arch/mips/gt64120/momenco_ocelot/dbg_io.c2
-rw-r--r--arch/mips/gt64120/momenco_ocelot/int-handler.S131
-rw-r--r--arch/mips/gt64120/momenco_ocelot/irq.c36
-rw-r--r--arch/mips/ite-boards/generic/Makefile2
-rw-r--r--arch/mips/ite-boards/generic/dbg_io.c2
-rw-r--r--arch/mips/ite-boards/generic/int-handler.S63
-rw-r--r--arch/mips/ite-boards/generic/irq.c18
-rw-r--r--arch/mips/ite-boards/generic/time.c5
-rw-r--r--arch/mips/ite-boards/ivr/init.c5
-rw-r--r--arch/mips/ite-boards/qed-4n-s01b/init.c5
-rw-r--r--arch/mips/jazz/Makefile2
-rw-r--r--arch/mips/jazz/int-handler.S282
-rw-r--r--arch/mips/jazz/irq.c78
-rw-r--r--arch/mips/jmr3927/common/rtc_ds1742.c64
-rw-r--r--arch/mips/jmr3927/rbhma3100/Makefile2
-rw-r--r--arch/mips/jmr3927/rbhma3100/int-handler.S74
-rw-r--r--arch/mips/jmr3927/rbhma3100/irq.c6
-rw-r--r--arch/mips/kernel/Makefile7
-rw-r--r--arch/mips/kernel/asm-offsets.c7
-rw-r--r--arch/mips/kernel/branch.c2
-rw-r--r--arch/mips/kernel/cpu-bugs64.c8
-rw-r--r--arch/mips/kernel/cpu-probe.c15
-rw-r--r--arch/mips/kernel/entry.S69
-rw-r--r--arch/mips/kernel/gdb-low.S32
-rw-r--r--arch/mips/kernel/gdb-stub.c61
-rw-r--r--arch/mips/kernel/genex.S43
-rw-r--r--arch/mips/kernel/head.S57
-rw-r--r--arch/mips/kernel/i8253.c28
-rw-r--r--arch/mips/kernel/i8259.c4
-rw-r--r--arch/mips/kernel/irixsig.c4
-rw-r--r--arch/mips/kernel/irq-msc01.c9
-rw-r--r--arch/mips/kernel/irq.c18
-rw-r--r--arch/mips/kernel/kspd.c398
-rw-r--r--arch/mips/kernel/linux32.c74
-rw-r--r--arch/mips/kernel/mips-mt.c449
-rw-r--r--arch/mips/kernel/mips_ksyms.c16
-rw-r--r--arch/mips/kernel/module.c6
-rw-r--r--arch/mips/kernel/proc.c2
-rw-r--r--arch/mips/kernel/process.c22
-rw-r--r--arch/mips/kernel/ptrace.c18
-rw-r--r--arch/mips/kernel/ptrace32.c14
-rw-r--r--arch/mips/kernel/r4k_switch.S34
-rw-r--r--arch/mips/kernel/rtlx.c518
-rw-r--r--arch/mips/kernel/scall32-o32.S13
-rw-r--r--arch/mips/kernel/scall64-64.S2
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S4
-rw-r--r--arch/mips/kernel/setup.c32
-rw-r--r--arch/mips/kernel/signal-common.h30
-rw-r--r--arch/mips/kernel/smp-mt.c (renamed from arch/mips/kernel/smp_mt.c)44
-rw-r--r--arch/mips/kernel/smp.c17
-rw-r--r--arch/mips/kernel/smtc-asm.S130
-rw-r--r--arch/mips/kernel/smtc-proc.c93
-rw-r--r--arch/mips/kernel/smtc.c1322
-rw-r--r--arch/mips/kernel/syscall.c27
-rw-r--r--arch/mips/kernel/time.c25
-rw-r--r--arch/mips/kernel/traps.c232
-rw-r--r--arch/mips/kernel/vmlinux.lds.S22
-rw-r--r--arch/mips/kernel/vpe.c665
-rw-r--r--arch/mips/lasat/Makefile2
-rw-r--r--arch/mips/lasat/interrupt.c14
-rw-r--r--arch/mips/lasat/lasatIRQ.S69
-rw-r--r--arch/mips/lasat/setup.c7
-rw-r--r--arch/mips/math-emu/dp_fint.c4
-rw-r--r--arch/mips/math-emu/dp_flong.c4
-rw-r--r--arch/mips/math-emu/sp_fint.c4
-rw-r--r--arch/mips/math-emu/sp_flong.c4
-rw-r--r--arch/mips/mips-boards/atlas/atlas_int.c92
-rw-r--r--arch/mips/mips-boards/atlas/atlas_setup.c2
-rw-r--r--arch/mips/mips-boards/generic/Makefile4
-rw-r--r--arch/mips/mips-boards/generic/gdb_hook.c2
-rw-r--r--arch/mips/mips-boards/generic/init.c2
-rw-r--r--arch/mips/mips-boards/generic/memory.c10
-rw-r--r--arch/mips/mips-boards/generic/mipsIRQ.S155
-rw-r--r--arch/mips/mips-boards/generic/pci.c1
-rw-r--r--arch/mips/mips-boards/generic/time.c68
-rw-r--r--arch/mips/mips-boards/malta/Makefile1
-rw-r--r--arch/mips/mips-boards/malta/malta_int.c105
-rw-r--r--arch/mips/mips-boards/malta/malta_setup.c2
-rw-r--r--arch/mips/mips-boards/malta/malta_smp.c128
-rw-r--r--arch/mips/mips-boards/sead/sead_int.c86
-rw-r--r--arch/mips/mips-boards/sim/cmdline.c59
-rw-r--r--arch/mips/mips-boards/sim/sim_cmdline.c6
-rw-r--r--arch/mips/mips-boards/sim/sim_int.c64
-rw-r--r--arch/mips/mips-boards/sim/sim_irq.S4
-rw-r--r--arch/mips/mips-boards/sim/sim_mem.c8
-rw-r--r--arch/mips/mips-boards/sim/sim_smp.c14
-rw-r--r--arch/mips/mm/c-r3k.c5
-rw-r--r--arch/mips/mm/c-r4k.c98
-rw-r--r--arch/mips/mm/c-sb1.c1
-rw-r--r--arch/mips/mm/c-tx39.c7
-rw-r--r--arch/mips/mm/cache.c1
-rw-r--r--arch/mips/mm/fault.c13
-rw-r--r--arch/mips/mm/highmem.c2
-rw-r--r--arch/mips/mm/init.c54
-rw-r--r--arch/mips/mm/pg-r4k.c1
-rw-r--r--arch/mips/mm/sc-rm7k.c2
-rw-r--r--arch/mips/mm/tlb-r4k.c85
-rw-r--r--arch/mips/mm/tlbex.c89
-rw-r--r--arch/mips/momentum/jaguar_atx/Makefile2
-rw-r--r--arch/mips/momentum/jaguar_atx/dbg_io.c2
-rw-r--r--arch/mips/momentum/jaguar_atx/int-handler.S128
-rw-r--r--arch/mips/momentum/jaguar_atx/irq.c35
-rw-r--r--arch/mips/momentum/jaguar_atx/setup.c40
-rw-r--r--arch/mips/momentum/ocelot_3/Makefile2
-rw-r--r--arch/mips/momentum/ocelot_3/int-handler.S137
-rw-r--r--arch/mips/momentum/ocelot_3/irq.c38
-rw-r--r--arch/mips/momentum/ocelot_3/setup.c62
-rw-r--r--arch/mips/momentum/ocelot_c/Makefile2
-rw-r--r--arch/mips/momentum/ocelot_c/dbg_io.c2
-rw-r--r--arch/mips/momentum/ocelot_c/int-handler.S102
-rw-r--r--arch/mips/momentum/ocelot_c/irq.c30
-rw-r--r--arch/mips/momentum/ocelot_c/setup.c4
-rw-r--r--arch/mips/momentum/ocelot_g/Makefile2
-rw-r--r--arch/mips/momentum/ocelot_g/dbg_io.c2
-rw-r--r--arch/mips/momentum/ocelot_g/int-handler.S131
-rw-r--r--arch/mips/momentum/ocelot_g/irq.c38
-rw-r--r--arch/mips/oprofile/common.c14
-rw-r--r--arch/mips/oprofile/op_model_mipsxx.c34
-rw-r--r--arch/mips/oprofile/op_model_rm9000.c2
-rw-r--r--arch/mips/philips/pnx8550/common/Makefile2
-rw-r--r--arch/mips/philips/pnx8550/common/int.c23
-rw-r--r--arch/mips/philips/pnx8550/common/mipsIRQ.S76
-rw-r--r--arch/mips/philips/pnx8550/common/platform.c1
-rw-r--r--arch/mips/pmc-sierra/yosemite/Makefile2
-rw-r--r--arch/mips/pmc-sierra/yosemite/irq-handler.S93
-rw-r--r--arch/mips/pmc-sierra/yosemite/irq.c33
-rw-r--r--arch/mips/pmc-sierra/yosemite/setup.c4
-rw-r--r--arch/mips/qemu/Makefile2
-rw-r--r--arch/mips/qemu/q-int.S17
-rw-r--r--arch/mips/qemu/q-irq.c3
-rw-r--r--arch/mips/sgi-ip22/Makefile2
-rw-r--r--arch/mips/sgi-ip22/ip22-int.c59
-rw-r--r--arch/mips/sgi-ip22/ip22-irq.S118
-rw-r--r--arch/mips/sgi-ip22/ip22-reset.c2
-rw-r--r--arch/mips/sgi-ip22/ip22-time.c4
-rw-r--r--arch/mips/sgi-ip27/Makefile2
-rw-r--r--arch/mips/sgi-ip27/TODO4
-rw-r--r--arch/mips/sgi-ip27/ip27-irq-glue.S45
-rw-r--r--arch/mips/sgi-ip27/ip27-irq.c27
-rw-r--r--arch/mips/sgi-ip27/ip27-memory.c3
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c2
-rw-r--r--arch/mips/sgi-ip32/Makefile2
-rw-r--r--arch/mips/sgi-ip32/ip32-irq-glue.S86
-rw-r--r--arch/mips/sgi-ip32/ip32-irq.c44
-rw-r--r--arch/mips/sgi-ip32/ip32-reset.c2
-rw-r--r--arch/mips/sgi-ip32/ip32-setup.c4
-rw-r--r--arch/mips/sibyte/bcm1480/Makefile2
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c77
-rw-r--r--arch/mips/sibyte/bcm1480/irq_handler.S165
-rw-r--r--arch/mips/sibyte/sb1250/Makefile2
-rw-r--r--arch/mips/sibyte/sb1250/irq.c78
-rw-r--r--arch/mips/sibyte/sb1250/irq_handler.S147
-rw-r--r--arch/mips/sibyte/swarm/setup.c8
-rw-r--r--arch/mips/sni/Makefile2
-rw-r--r--arch/mips/sni/int-handler.S106
-rw-r--r--arch/mips/sni/irq.c37
-rw-r--r--arch/mips/sni/setup.c4
-rw-r--r--arch/mips/tx4927/common/Makefile2
-rw-r--r--arch/mips/tx4927/common/tx4927_irq.c30
-rw-r--r--arch/mips/tx4927/common/tx4927_irq_handler.S103
-rw-r--r--arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c4
-rw-r--r--arch/mips/tx4938/common/Makefile2
-rw-r--r--arch/mips/tx4938/common/irq.c21
-rw-r--r--arch/mips/tx4938/common/irq_handler.S84
-rw-r--r--arch/mips/tx4938/common/rtc_rx5c348.c16
-rw-r--r--arch/mips/vr41xx/Kconfig13
-rw-r--r--arch/mips/vr41xx/common/Makefile2
-rw-r--r--arch/mips/vr41xx/common/int-handler.S114
-rw-r--r--arch/mips/vr41xx/common/irq.c29
-rw-r--r--arch/parisc/Kconfig42
-rw-r--r--arch/parisc/configs/712_defconfig160
-rw-r--r--arch/parisc/configs/a500_defconfig4
-rw-r--r--arch/parisc/configs/b180_defconfig12
-rw-r--r--arch/parisc/configs/c3000_defconfig252
-rw-r--r--arch/parisc/defconfig641
-rw-r--r--arch/parisc/kernel/asm-offsets.c3
-rw-r--r--arch/parisc/kernel/cache.c10
-rw-r--r--arch/parisc/kernel/entry.S75
-rw-r--r--arch/parisc/kernel/head.S15
-rw-r--r--arch/parisc/kernel/init_task.c10
-rw-r--r--arch/parisc/kernel/pacache.S29
-rw-r--r--arch/parisc/kernel/parisc_ksyms.c20
-rw-r--r--arch/parisc/kernel/pdc_chassis.c8
-rw-r--r--arch/parisc/kernel/perf.c2
-rw-r--r--arch/parisc/kernel/sys_parisc.c8
-rw-r--r--arch/parisc/kernel/syscall.S10
-rw-r--r--arch/parisc/kernel/syscall_table.S10
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S54
-rw-r--r--arch/parisc/lib/iomap.c4
-rw-r--r--arch/parisc/mm/fault.c2
-rw-r--r--arch/parisc/mm/init.c35
-rw-r--r--arch/parisc/mm/ioremap.c57
-rw-r--r--arch/powerpc/Kconfig15
-rw-r--r--arch/powerpc/Kconfig.debug5
-rw-r--r--arch/powerpc/Makefile11
-rw-r--r--arch/powerpc/configs/cell_defconfig171
-rw-r--r--arch/powerpc/configs/g5_defconfig58
-rw-r--r--arch/powerpc/configs/iseries_defconfig43
-rw-r--r--arch/powerpc/configs/mpc8540_ads_defconfig43
-rw-r--r--arch/powerpc/configs/pseries_defconfig54
-rw-r--r--arch/powerpc/kernel/Makefile13
-rw-r--r--arch/powerpc/kernel/asm-offsets.c3
-rw-r--r--arch/powerpc/kernel/cpu_setup_6xx.S (renamed from arch/ppc/kernel/cpu_setup_6xx.S)0
-rw-r--r--arch/powerpc/kernel/cputable.c16
-rw-r--r--arch/powerpc/kernel/crash_dump.c4
-rw-r--r--arch/powerpc/kernel/entry_32.S35
-rw-r--r--arch/powerpc/kernel/entry_64.S6
-rw-r--r--arch/powerpc/kernel/firmware.c4
-rw-r--r--arch/powerpc/kernel/head_64.S81
-rw-r--r--arch/powerpc/kernel/idle.c (renamed from arch/powerpc/kernel/idle_64.c)79
-rw-r--r--arch/powerpc/kernel/idle_6xx.S81
-rw-r--r--arch/powerpc/kernel/idle_power4.S48
-rw-r--r--arch/powerpc/kernel/iommu.c36
-rw-r--r--arch/powerpc/kernel/irq.c38
-rw-r--r--arch/powerpc/kernel/kprobes.c28
-rw-r--r--arch/powerpc/kernel/l2cr_6xx.S (renamed from arch/ppc/kernel/l2cr.S)0
-rw-r--r--arch/powerpc/kernel/legacy_serial.c42
-rw-r--r--arch/powerpc/kernel/lparcfg.c35
-rw-r--r--arch/powerpc/kernel/module_32.c (renamed from arch/ppc/kernel/module.c)0
-rw-r--r--arch/powerpc/kernel/module_64.c16
-rw-r--r--arch/powerpc/kernel/nvram_64.c7
-rw-r--r--arch/powerpc/kernel/paca.c21
-rw-r--r--arch/powerpc/kernel/pci_32.c4
-rw-r--r--arch/powerpc/kernel/pci_64.c1
-rw-r--r--arch/powerpc/kernel/pci_iommu.c40
-rw-r--r--arch/powerpc/kernel/perfmon_fsl_booke.c (renamed from arch/ppc/kernel/perfmon_fsl_booke.c)0
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c1
-rw-r--r--arch/powerpc/kernel/proc_ppc64.c3
-rw-r--r--arch/powerpc/kernel/process.c12
-rw-r--r--arch/powerpc/kernel/prom.c224
-rw-r--r--arch/powerpc/kernel/prom_init.c235
-rw-r--r--arch/powerpc/kernel/ptrace.c5
-rw-r--r--arch/powerpc/kernel/rtas-proc.c6
-rw-r--r--arch/powerpc/kernel/rtas.c20
-rw-r--r--arch/powerpc/kernel/setup-common.c102
-rw-r--r--arch/powerpc/kernel/setup_32.c73
-rw-r--r--arch/powerpc/kernel/setup_64.c97
-rw-r--r--arch/powerpc/kernel/signal_32.c12
-rw-r--r--arch/powerpc/kernel/signal_64.c5
-rw-r--r--arch/powerpc/kernel/smp.c2
-rw-r--r--arch/powerpc/kernel/swsusp_32.S (renamed from arch/ppc/kernel/swsusp.S)0
-rw-r--r--arch/powerpc/kernel/syscalls.c1
-rw-r--r--arch/powerpc/kernel/sysfs.c34
-rw-r--r--arch/powerpc/kernel/systbl.S23
-rw-r--r--arch/powerpc/kernel/tau_6xx.c (renamed from arch/ppc/kernel/temp.c)0
-rw-r--r--arch/powerpc/kernel/time.c4
-rw-r--r--arch/powerpc/kernel/traps.c60
-rw-r--r--arch/powerpc/kernel/vdso.c9
-rw-r--r--arch/powerpc/kernel/vdso32/sigtramp.S2
-rw-r--r--arch/powerpc/kernel/vdso64/sigtramp.S2
-rw-r--r--arch/powerpc/kernel/vio.c6
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S381
-rw-r--r--arch/powerpc/lib/sstep.c2
-rw-r--r--arch/powerpc/math-emu/Makefile (renamed from arch/ppc/math-emu/Makefile)0
-rw-r--r--arch/powerpc/math-emu/double.h (renamed from arch/ppc/math-emu/double.h)0
-rw-r--r--arch/powerpc/math-emu/fabs.c (renamed from arch/ppc/math-emu/fabs.c)0
-rw-r--r--arch/powerpc/math-emu/fadd.c (renamed from arch/ppc/math-emu/fadd.c)0
-rw-r--r--arch/powerpc/math-emu/fadds.c (renamed from arch/ppc/math-emu/fadds.c)0
-rw-r--r--arch/powerpc/math-emu/fcmpo.c (renamed from arch/ppc/math-emu/fcmpo.c)0
-rw-r--r--arch/powerpc/math-emu/fcmpu.c (renamed from arch/ppc/math-emu/fcmpu.c)0
-rw-r--r--arch/powerpc/math-emu/fctiw.c (renamed from arch/ppc/math-emu/fctiw.c)0
-rw-r--r--arch/powerpc/math-emu/fctiwz.c (renamed from arch/ppc/math-emu/fctiwz.c)0
-rw-r--r--arch/powerpc/math-emu/fdiv.c (renamed from arch/ppc/math-emu/fdiv.c)0
-rw-r--r--arch/powerpc/math-emu/fdivs.c (renamed from arch/ppc/math-emu/fdivs.c)0
-rw-r--r--arch/powerpc/math-emu/fmadd.c (renamed from arch/ppc/math-emu/fmadd.c)0
-rw-r--r--arch/powerpc/math-emu/fmadds.c (renamed from arch/ppc/math-emu/fmadds.c)0
-rw-r--r--arch/powerpc/math-emu/fmr.c (renamed from arch/ppc/math-emu/fmr.c)0
-rw-r--r--arch/powerpc/math-emu/fmsub.c (renamed from arch/ppc/math-emu/fmsub.c)0
-rw-r--r--arch/powerpc/math-emu/fmsubs.c (renamed from arch/ppc/math-emu/fmsubs.c)0
-rw-r--r--arch/powerpc/math-emu/fmul.c (renamed from arch/ppc/math-emu/fmul.c)0
-rw-r--r--arch/powerpc/math-emu/fmuls.c (renamed from arch/ppc/math-emu/fmuls.c)0
-rw-r--r--arch/powerpc/math-emu/fnabs.c (renamed from arch/ppc/math-emu/fnabs.c)0
-rw-r--r--arch/powerpc/math-emu/fneg.c (renamed from arch/ppc/math-emu/fneg.c)0
-rw-r--r--arch/powerpc/math-emu/fnmadd.c (renamed from arch/ppc/math-emu/fnmadd.c)0
-rw-r--r--arch/powerpc/math-emu/fnmadds.c (renamed from arch/ppc/math-emu/fnmadds.c)0
-rw-r--r--arch/powerpc/math-emu/fnmsub.c (renamed from arch/ppc/math-emu/fnmsub.c)0
-rw-r--r--arch/powerpc/math-emu/fnmsubs.c (renamed from arch/ppc/math-emu/fnmsubs.c)0
-rw-r--r--arch/powerpc/math-emu/fres.c (renamed from arch/ppc/math-emu/fres.c)0
-rw-r--r--arch/powerpc/math-emu/frsp.c (renamed from arch/ppc/math-emu/frsp.c)0
-rw-r--r--arch/powerpc/math-emu/frsqrte.c (renamed from arch/ppc/math-emu/frsqrte.c)0
-rw-r--r--arch/powerpc/math-emu/fsel.c (renamed from arch/ppc/math-emu/fsel.c)0
-rw-r--r--arch/powerpc/math-emu/fsqrt.c (renamed from arch/ppc/math-emu/fsqrt.c)0
-rw-r--r--arch/powerpc/math-emu/fsqrts.c (renamed from arch/ppc/math-emu/fsqrts.c)0
-rw-r--r--arch/powerpc/math-emu/fsub.c (renamed from arch/ppc/math-emu/fsub.c)0
-rw-r--r--arch/powerpc/math-emu/fsubs.c (renamed from arch/ppc/math-emu/fsubs.c)0
-rw-r--r--arch/powerpc/math-emu/lfd.c (renamed from arch/ppc/math-emu/lfd.c)0
-rw-r--r--arch/powerpc/math-emu/lfs.c (renamed from arch/ppc/math-emu/lfs.c)0
-rw-r--r--arch/powerpc/math-emu/math.c (renamed from arch/ppc/math-emu/math.c)0
-rw-r--r--arch/powerpc/math-emu/mcrfs.c (renamed from arch/ppc/math-emu/mcrfs.c)0
-rw-r--r--arch/powerpc/math-emu/mffs.c (renamed from arch/ppc/math-emu/mffs.c)0
-rw-r--r--arch/powerpc/math-emu/mtfsb0.c (renamed from arch/ppc/math-emu/mtfsb0.c)0
-rw-r--r--arch/powerpc/math-emu/mtfsb1.c (renamed from arch/ppc/math-emu/mtfsb1.c)0
-rw-r--r--arch/powerpc/math-emu/mtfsf.c (renamed from arch/ppc/math-emu/mtfsf.c)0
-rw-r--r--arch/powerpc/math-emu/mtfsfi.c (renamed from arch/ppc/math-emu/mtfsfi.c)0
-rw-r--r--arch/powerpc/math-emu/op-1.h (renamed from arch/ppc/math-emu/op-1.h)0
-rw-r--r--arch/powerpc/math-emu/op-2.h (renamed from arch/ppc/math-emu/op-2.h)0
-rw-r--r--arch/powerpc/math-emu/op-4.h (renamed from arch/ppc/math-emu/op-4.h)0
-rw-r--r--arch/powerpc/math-emu/op-common.h (renamed from arch/ppc/math-emu/op-common.h)0
-rw-r--r--arch/powerpc/math-emu/sfp-machine.h (renamed from arch/ppc/math-emu/sfp-machine.h)0
-rw-r--r--arch/powerpc/math-emu/single.h (renamed from arch/ppc/math-emu/single.h)0
-rw-r--r--arch/powerpc/math-emu/soft-fp.h (renamed from arch/ppc/math-emu/soft-fp.h)0
-rw-r--r--arch/powerpc/math-emu/stfd.c (renamed from arch/ppc/math-emu/stfd.c)0
-rw-r--r--arch/powerpc/math-emu/stfiwx.c (renamed from arch/ppc/math-emu/stfiwx.c)0
-rw-r--r--arch/powerpc/math-emu/stfs.c (renamed from arch/ppc/math-emu/stfs.c)0
-rw-r--r--arch/powerpc/math-emu/types.c (renamed from arch/ppc/math-emu/types.c)0
-rw-r--r--arch/powerpc/math-emu/udivmodti4.c (renamed from arch/ppc/math-emu/udivmodti4.c)0
-rw-r--r--arch/powerpc/mm/fault.c36
-rw-r--r--arch/powerpc/mm/hash_utils_64.c7
-rw-r--r--arch/powerpc/mm/hugetlbpage.c295
-rw-r--r--arch/powerpc/mm/init_64.c7
-rw-r--r--arch/powerpc/mm/mem.c6
-rw-r--r--arch/powerpc/mm/numa.c34
-rw-r--r--arch/powerpc/mm/pgtable_32.c6
-rw-r--r--arch/powerpc/mm/stab.c2
-rw-r--r--arch/powerpc/oprofile/Makefile2
-rw-r--r--arch/powerpc/oprofile/backtrace.c126
-rw-r--r--arch/powerpc/oprofile/common.c9
-rw-r--r--arch/powerpc/oprofile/op_model_7450.c4
-rw-r--r--arch/powerpc/oprofile/op_model_fsl_booke.c4
-rw-r--r--arch/powerpc/oprofile/op_model_power4.c45
-rw-r--r--arch/powerpc/oprofile/op_model_rs64.c5
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_sys.c40
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig1
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c40
-rw-r--r--arch/powerpc/platforms/cell/Kconfig6
-rw-r--r--arch/powerpc/platforms/cell/Makefile10
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c133
-rw-r--r--arch/powerpc/platforms/cell/interrupt.h2
-rw-r--r--arch/powerpc/platforms/cell/iommu.c16
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c4
-rw-r--r--arch/powerpc/platforms/cell/setup.c92
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c108
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c116
-rw-r--r--arch/powerpc/platforms/cell/spu_callbacks.c362
-rw-r--r--arch/powerpc/platforms/cell/spufs/backing_ops.c47
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c24
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c523
-rw-r--r--arch/powerpc/platforms/cell/spufs/hw_ops.c57
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c8
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c92
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h28
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c5
-rw-r--r--arch/powerpc/platforms/chrp/chrp.h3
-rw-r--r--arch/powerpc/platforms/chrp/pci.c6
-rw-r--r--arch/powerpc/platforms/chrp/setup.c121
-rw-r--r--arch/powerpc/platforms/chrp/time.c22
-rw-r--r--arch/powerpc/platforms/iseries/setup.c20
-rw-r--r--arch/powerpc/platforms/maple/setup.c10
-rw-r--r--arch/powerpc/platforms/maple/time.c24
-rw-r--r--arch/powerpc/platforms/powermac/bootx_init.c6
-rw-r--r--arch/powerpc/platforms/powermac/feature.c2
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c93
-rw-r--r--arch/powerpc/platforms/powermac/nvram.c14
-rw-r--r--arch/powerpc/platforms/powermac/pci.c7
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_base.c2
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_core.c18
-rw-r--r--arch/powerpc/platforms/powermac/setup.c86
-rw-r--r--arch/powerpc/platforms/powermac/time.c4
-rw-r--r--arch/powerpc/platforms/powermac/udbg_scc.c2
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c70
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c29
-rw-r--r--arch/powerpc/platforms/pseries/eeh_event.c38
-rw-r--r--arch/powerpc/platforms/pseries/firmware.c2
-rw-r--r--arch/powerpc/platforms/pseries/hvCall.S100
-rw-r--r--arch/powerpc/platforms/pseries/hvconsole.c11
-rw-r--r--arch/powerpc/platforms/pseries/hvcserver.c22
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c31
-rw-r--r--arch/powerpc/platforms/pseries/pci.c2
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c11
-rw-r--r--arch/powerpc/platforms/pseries/ras.c2
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c15
-rw-r--r--arch/powerpc/platforms/pseries/rtasd.c5
-rw-r--r--arch/powerpc/platforms/pseries/setup.c239
-rw-r--r--arch/powerpc/platforms/pseries/vio.c4
-rw-r--r--arch/powerpc/platforms/pseries/xics.c12
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c12
-rw-r--r--arch/ppc/Kconfig93
-rw-r--r--arch/ppc/Kconfig.debug7
-rw-r--r--arch/ppc/Makefile6
-rw-r--r--arch/ppc/boot/Makefile7
-rw-r--r--arch/ppc/boot/lib/Makefile2
-rw-r--r--arch/ppc/boot/openfirmware/Makefile109
-rw-r--r--arch/ppc/boot/openfirmware/chrpmain.c101
-rw-r--r--arch/ppc/boot/openfirmware/common.c146
-rw-r--r--arch/ppc/boot/openfirmware/dummy.c4
-rw-r--r--arch/ppc/boot/openfirmware/misc.S67
-rw-r--r--arch/ppc/boot/openfirmware/start.c172
-rw-r--r--arch/ppc/boot/simple/mpc10x_memory.c4
-rw-r--r--arch/ppc/boot/simple/relocate.S2
-rw-r--r--arch/ppc/boot/utils/addnote.c175
-rw-r--r--arch/ppc/boot/utils/hack-coff.c84
-rw-r--r--arch/ppc/boot/utils/mknote.c44
-rw-r--r--arch/ppc/configs/ibmchrp_defconfig875
-rw-r--r--arch/ppc/configs/pmac_defconfig1591
-rw-r--r--arch/ppc/configs/power3_defconfig1035
-rw-r--r--arch/ppc/configs/prep_defconfig (renamed from arch/ppc/configs/common_defconfig)0
-rw-r--r--arch/ppc/kernel/Makefile28
-rw-r--r--arch/ppc/kernel/asm-offsets.c1
-rw-r--r--arch/ppc/kernel/entry.S87
-rw-r--r--arch/ppc/kernel/head.S183
-rw-r--r--arch/ppc/kernel/head_8xx.S4
-rw-r--r--arch/ppc/kernel/idle.c112
-rw-r--r--arch/ppc/kernel/idle_6xx.S233
-rw-r--r--arch/ppc/kernel/idle_power4.S91
-rw-r--r--arch/ppc/kernel/pci.c396
-rw-r--r--arch/ppc/kernel/ppc_htab.c10
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c27
-rw-r--r--arch/ppc/kernel/setup.c256
-rw-r--r--arch/ppc/kernel/smp.c2
-rw-r--r--arch/ppc/lib/strcase.c3
-rw-r--r--arch/ppc/mm/fault.c30
-rw-r--r--arch/ppc/mm/hashtable.S34
-rw-r--r--arch/ppc/mm/init.c13
-rw-r--r--arch/ppc/mm/mmu_context.c2
-rw-r--r--arch/ppc/mm/pgtable.c8
-rw-r--r--arch/ppc/mm/ppc_mmu.c28
-rw-r--r--arch/ppc/platforms/4xx/ocotea.c2
-rw-r--r--arch/ppc/platforms/Makefile12
-rw-r--r--arch/ppc/platforms/chrp_nvram.c83
-rw-r--r--arch/ppc/platforms/chrp_pci.c309
-rw-r--r--arch/ppc/platforms/chrp_pegasos_eth.c211
-rw-r--r--arch/ppc/platforms/chrp_setup.c669
-rw-r--r--arch/ppc/platforms/chrp_smp.c99
-rw-r--r--arch/ppc/platforms/chrp_time.c251
-rw-r--r--arch/ppc/platforms/lite5200.c71
-rw-r--r--arch/ppc/platforms/mpc8272ads_setup.c116
-rw-r--r--arch/ppc/platforms/mpc866ads_setup.c140
-rw-r--r--arch/ppc/platforms/mpc885ads_setup.c131
-rw-r--r--arch/ppc/platforms/pq2ads.c31
-rw-r--r--arch/ppc/platforms/prep_setup.c14
-rw-r--r--arch/ppc/syslib/Makefile2
-rw-r--r--arch/ppc/syslib/ibm440gx_common.c13
-rw-r--r--arch/ppc/syslib/ibm440gx_common.h4
-rw-r--r--arch/ppc/syslib/mpc52xx_pci.c3
-rw-r--r--arch/ppc/syslib/mpc52xx_setup.c48
-rw-r--r--arch/ppc/syslib/mpc8xx_devices.c25
-rw-r--r--arch/ppc/syslib/open_pic.c2
-rw-r--r--arch/ppc/syslib/ppc_sys.c13
-rw-r--r--arch/ppc/syslib/pq2_devices.c16
-rw-r--r--arch/ppc/syslib/pq2_sys.c16
-rw-r--r--arch/ppc/syslib/prom.c1429
-rw-r--r--arch/ppc/syslib/prom_init.c1011
-rw-r--r--arch/ppc/xmon/start.c2
-rw-r--r--arch/s390/Makefile1
-rw-r--r--arch/s390/appldata/appldata_base.c2
-rw-r--r--arch/s390/defconfig48
-rw-r--r--arch/s390/kernel/compat_signal.c2
-rw-r--r--arch/s390/kernel/compat_wrapper.S50
-rw-r--r--arch/s390/kernel/process.c11
-rw-r--r--arch/s390/kernel/ptrace.c5
-rw-r--r--arch/s390/kernel/signal.c5
-rw-r--r--arch/s390/kernel/smp.c6
-rw-r--r--arch/s390/kernel/syscalls.S6
-rw-r--r--arch/s390/kernel/time.c9
-rw-r--r--arch/s390/kernel/vmlinux.lds.S4
-rw-r--r--arch/s390/mm/extmem.c19
-rw-r--r--arch/sh/Kconfig5
-rw-r--r--arch/sh/boards/mpc1211/rtc.c50
-rw-r--r--arch/sh/boards/sh03/rtc.c13
-rw-r--r--arch/sh/kernel/cpu/init.c2
-rw-r--r--arch/sh/kernel/cpu/rtc.c10
-rw-r--r--arch/sh/kernel/setup.c7
-rw-r--r--arch/sh/kernel/sh_ksyms.c1
-rw-r--r--arch/sh64/kernel/setup.c1
-rw-r--r--arch/sh64/kernel/sh_ksyms.c1
-rw-r--r--arch/sh64/kernel/time.c9
-rw-r--r--arch/sparc/kernel/ioport.c5
-rw-r--r--arch/sparc/kernel/module.c1
-rw-r--r--arch/sparc/kernel/smp.c13
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c14
-rw-r--r--arch/sparc/kernel/systbls.S11
-rw-r--r--arch/sparc/math-emu/Makefile2
-rw-r--r--arch/sparc64/Kconfig5
-rw-r--r--arch/sparc64/defconfig39
-rw-r--r--arch/sparc64/kernel/head.S30
-rw-r--r--arch/sparc64/kernel/kprobes.c12
-rw-r--r--arch/sparc64/kernel/module.c5
-rw-r--r--arch/sparc64/kernel/pci.c1
-rw-r--r--arch/sparc64/kernel/pci_iommu.c4
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c130
-rw-r--r--arch/sparc64/kernel/ptrace.c28
-rw-r--r--arch/sparc64/kernel/setup.c25
-rw-r--r--arch/sparc64/kernel/smp.c101
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c2
-rw-r--r--arch/sparc64/kernel/sys32.S4
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c8
-rw-r--r--arch/sparc64/kernel/systbls.S24
-rw-r--r--arch/sparc64/kernel/time.c16
-rw-r--r--arch/sparc64/kernel/traps.c32
-rw-r--r--arch/sparc64/lib/checksum.S5
-rw-r--r--arch/sparc64/lib/csum_copy.S5
-rw-r--r--arch/sparc64/mm/fault.c10
-rw-r--r--arch/sparc64/mm/hugetlbpage.c7
-rw-r--r--arch/sparc64/mm/tlb.c5
-rw-r--r--arch/um/Kconfig17
-rw-r--r--arch/um/Kconfig.i38619
-rw-r--r--arch/um/Makefile29
-rw-r--r--arch/um/Makefile-i3864
-rw-r--r--arch/um/Makefile-x86_642
-rw-r--r--arch/um/defconfig240
-rw-r--r--arch/um/drivers/cow.h2
-rw-r--r--arch/um/drivers/cow_sys.h2
-rw-r--r--arch/um/drivers/cow_user.c94
-rw-r--r--arch/um/drivers/daemon_kern.c13
-rw-r--r--arch/um/drivers/harddog_kern.c8
-rw-r--r--arch/um/drivers/hostaudio_kern.c10
-rw-r--r--arch/um/drivers/mcast_kern.c13
-rw-r--r--arch/um/drivers/mconsole_kern.c147
-rw-r--r--arch/um/drivers/net_user.c4
-rw-r--r--arch/um/drivers/pcap_kern.c13
-rw-r--r--arch/um/drivers/slip_kern.c13
-rw-r--r--arch/um/drivers/slirp_kern.c15
-rw-r--r--arch/um/drivers/slirp_user.c2
-rw-r--r--arch/um/drivers/ubd_kern.c78
-rw-r--r--arch/um/include/irq_user.h15
-rw-r--r--arch/um/include/kern.h2
-rw-r--r--arch/um/include/kern_util.h15
-rw-r--r--arch/um/include/line.h18
-rw-r--r--arch/um/include/longjmp.h4
-rw-r--r--arch/um/include/mem_user.h1
-rw-r--r--arch/um/include/misc_constants.h6
-rw-r--r--arch/um/include/os.h46
-rw-r--r--arch/um/include/sigio.h3
-rw-r--r--arch/um/include/skas/mode-skas.h1
-rw-r--r--arch/um/include/skas/skas.h1
-rw-r--r--arch/um/include/sysdep-i386/checksum.h5
-rw-r--r--arch/um/include/sysdep-i386/kernel-offsets.h2
-rw-r--r--arch/um/include/sysdep-i386/ptrace.h5
-rw-r--r--arch/um/include/sysdep-i386/tls.h32
-rw-r--r--arch/um/include/sysdep-x86_64/kernel-offsets.h2
-rw-r--r--arch/um/include/sysdep-x86_64/tls.h29
-rw-r--r--arch/um/include/tt/tt.h3
-rw-r--r--arch/um/include/user.h6
-rw-r--r--arch/um/include/user_util.h9
-rw-r--r--arch/um/kernel/Makefile9
-rw-r--r--arch/um/kernel/exec_kern.c18
-rw-r--r--arch/um/kernel/irq.c315
-rw-r--r--arch/um/kernel/irq_user.c412
-rw-r--r--arch/um/kernel/ksyms.c5
-rw-r--r--arch/um/kernel/mem.c2
-rw-r--r--arch/um/kernel/physmem.c5
-rw-r--r--arch/um/kernel/process_kern.c26
-rw-r--r--arch/um/kernel/ptrace.c50
-rw-r--r--arch/um/kernel/sigio_kern.c10
-rw-r--r--arch/um/kernel/skas/Makefile10
-rw-r--r--arch/um/kernel/skas/process_kern.c11
-rw-r--r--arch/um/kernel/smp.c15
-rw-r--r--arch/um/kernel/syscall_kern.c4
-rw-r--r--arch/um/kernel/time_kern.c12
-rw-r--r--arch/um/kernel/trap_kern.c8
-rw-r--r--arch/um/kernel/tt/process_kern.c10
-rw-r--r--arch/um/kernel/um_arch.c12
-rw-r--r--arch/um/os-Linux/Makefile16
-rw-r--r--arch/um/os-Linux/drivers/ethertap_kern.c13
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_kern.c13
-rw-r--r--arch/um/os-Linux/file.c2
-rw-r--r--arch/um/os-Linux/helper.c10
-rw-r--r--arch/um/os-Linux/irq.c159
-rw-r--r--arch/um/os-Linux/main.c32
-rw-r--r--arch/um/os-Linux/mem.c168
-rw-r--r--arch/um/os-Linux/process.c55
-rw-r--r--arch/um/os-Linux/sigio.c (renamed from arch/um/kernel/sigio_user.c)231
-rw-r--r--arch/um/os-Linux/skas/mem.c4
-rw-r--r--arch/um/os-Linux/skas/process.c46
-rw-r--r--arch/um/os-Linux/start_up.c170
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile2
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c4
-rw-r--r--arch/um/os-Linux/sys-i386/tls.c34
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c4
-rw-r--r--arch/um/os-Linux/time.c10
-rw-r--r--arch/um/os-Linux/tls.c76
-rw-r--r--arch/um/os-Linux/trap.c4
-rw-r--r--arch/um/os-Linux/tt.c10
-rw-r--r--arch/um/os-Linux/tty_log.c (renamed from arch/um/kernel/tty_log.c)18
-rw-r--r--arch/um/os-Linux/uaccess.c4
-rw-r--r--arch/um/os-Linux/umid.c52
-rw-r--r--arch/um/os-Linux/user_syms.c16
-rw-r--r--arch/um/os-Linux/util.c2
-rw-r--r--arch/um/scripts/Makefile.rules44
-rw-r--r--arch/um/scripts/Makefile.unmap22
-rw-r--r--arch/um/sys-i386/Makefile28
-rw-r--r--arch/um/sys-i386/ksyms.c4
-rw-r--r--arch/um/sys-i386/ptrace.c60
-rw-r--r--arch/um/sys-i386/ptrace_user.c12
-rw-r--r--arch/um/sys-i386/signal.c107
-rw-r--r--arch/um/sys-i386/stub_segv.c4
-rw-r--r--arch/um/sys-i386/sys_call_table.S2
-rw-r--r--arch/um/sys-i386/syscalls.c25
-rw-r--r--arch/um/sys-i386/tls.c384
-rw-r--r--arch/um/sys-i386/user-offsets.c10
-rw-r--r--arch/um/sys-x86_64/Makefile39
-rw-r--r--arch/um/sys-x86_64/ptrace.c22
-rw-r--r--arch/um/sys-x86_64/signal.c80
-rw-r--r--arch/um/sys-x86_64/stub_segv.c10
-rw-r--r--arch/um/sys-x86_64/syscalls.c2
-rw-r--r--arch/um/sys-x86_64/tls.c14
-rw-r--r--arch/um/sys-x86_64/user-offsets.c6
-rw-r--r--arch/v850/kernel/v850_ksyms.c1
-rw-r--r--arch/x86_64/Kconfig24
-rw-r--r--arch/x86_64/Makefile24
-rw-r--r--arch/x86_64/boot/video.S5
-rw-r--r--arch/x86_64/defconfig57
-rw-r--r--arch/x86_64/ia32/Makefile4
-rw-r--r--arch/x86_64/ia32/ia32_binfmt.c4
-rw-r--r--arch/x86_64/ia32/ia32entry.S27
-rw-r--r--arch/x86_64/ia32/vsyscall-sigreturn.S23
-rw-r--r--arch/x86_64/kernel/Makefile4
-rw-r--r--arch/x86_64/kernel/aperture.c2
-rw-r--r--arch/x86_64/kernel/apic.c14
-rw-r--r--arch/x86_64/kernel/e820.c44
-rw-r--r--arch/x86_64/kernel/early_printk.c2
-rw-r--r--arch/x86_64/kernel/entry.S35
-rw-r--r--arch/x86_64/kernel/io_apic.c35
-rw-r--r--arch/x86_64/kernel/kprobes.c16
-rw-r--r--arch/x86_64/kernel/mce.c14
-rw-r--r--arch/x86_64/kernel/mce_amd.c2
-rw-r--r--arch/x86_64/kernel/mpparse.c12
-rw-r--r--arch/x86_64/kernel/nmi.c7
-rw-r--r--arch/x86_64/kernel/pci-dma.c6
-rw-r--r--arch/x86_64/kernel/pci-gart.c18
-rw-r--r--arch/x86_64/kernel/pci-nommu.c7
-rw-r--r--arch/x86_64/kernel/pmtimer.c4
-rw-r--r--arch/x86_64/kernel/process.c31
-rw-r--r--arch/x86_64/kernel/ptrace.c11
-rw-r--r--arch/x86_64/kernel/setup.c64
-rw-r--r--arch/x86_64/kernel/setup64.c4
-rw-r--r--arch/x86_64/kernel/smpboot.c26
-rw-r--r--arch/x86_64/kernel/time.c49
-rw-r--r--arch/x86_64/kernel/traps.c60
-rw-r--r--arch/x86_64/kernel/vmlinux.lds.S2
-rw-r--r--arch/x86_64/kernel/x8664_ksyms.c5
-rw-r--r--arch/x86_64/mm/fault.c2
-rw-r--r--arch/x86_64/mm/init.c39
-rw-r--r--arch/x86_64/mm/numa.c63
-rw-r--r--arch/x86_64/mm/srat.c183
-rw-r--r--arch/x86_64/pci/mmconfig.c53
-rw-r--r--arch/xtensa/kernel/xtensa_ksyms.c3
-rw-r--r--arch/xtensa/platform-iss/setup.c2
-rw-r--r--block/Kconfig9
-rw-r--r--block/as-iosched.c18
-rw-r--r--block/cfq-iosched.c466
-rw-r--r--block/deadline-iosched.c13
-rw-r--r--block/elevator.c67
-rw-r--r--block/genhd.c109
-rw-r--r--block/ll_rw_blk.c71
-rw-r--r--block/noop-iosched.c7
-rw-r--r--block/scsi_ioctl.c101
-rw-r--r--drivers/Kconfig6
-rw-r--r--drivers/Makefile7
-rw-r--r--drivers/acpi/Kconfig5
-rw-r--r--drivers/acpi/acpi_memhotplug.c12
-rw-r--r--drivers/acpi/asus_acpi.c12
-rw-r--r--drivers/acpi/bus.c8
-rw-r--r--drivers/acpi/dispatcher/dsfield.c13
-rw-r--r--drivers/acpi/dispatcher/dsinit.c6
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c232
-rw-r--r--drivers/acpi/dispatcher/dsmthdat.c43
-rw-r--r--drivers/acpi/dispatcher/dsobject.c25
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c63
-rw-r--r--drivers/acpi/dispatcher/dsutils.c25
-rw-r--r--drivers/acpi/dispatcher/dswexec.c26
-rw-r--r--drivers/acpi/dispatcher/dswload.c67
-rw-r--r--drivers/acpi/dispatcher/dswscope.c10
-rw-r--r--drivers/acpi/dispatcher/dswstate.c72
-rw-r--r--drivers/acpi/ec.c25
-rw-r--r--drivers/acpi/events/evevent.c10
-rw-r--r--drivers/acpi/events/evgpe.c85
-rw-r--r--drivers/acpi/events/evgpeblk.c96
-rw-r--r--drivers/acpi/events/evmisc.c41
-rw-r--r--drivers/acpi/events/evregion.c115
-rw-r--r--drivers/acpi/events/evrgnini.c48
-rw-r--r--drivers/acpi/events/evsci.c8
-rw-r--r--drivers/acpi/events/evxface.c49
-rw-r--r--drivers/acpi/events/evxfevnt.c67
-rw-r--r--drivers/acpi/events/evxfregn.c15
-rw-r--r--drivers/acpi/executer/exconfig.c54
-rw-r--r--drivers/acpi/executer/exconvrt.c12
-rw-r--r--drivers/acpi/executer/excreate.c25
-rw-r--r--drivers/acpi/executer/exdump.c36
-rw-r--r--drivers/acpi/executer/exfield.c18
-rw-r--r--drivers/acpi/executer/exfldio.c67
-rw-r--r--drivers/acpi/executer/exmisc.c25
-rw-r--r--drivers/acpi/executer/exmutex.c15
-rw-r--r--drivers/acpi/executer/exnames.c28
-rw-r--r--drivers/acpi/executer/exoparg1.c101
-rw-r--r--drivers/acpi/executer/exoparg2.c89
-rw-r--r--drivers/acpi/executer/exoparg3.c17
-rw-r--r--drivers/acpi/executer/exoparg6.c3
-rw-r--r--drivers/acpi/executer/exprep.c45
-rw-r--r--drivers/acpi/executer/exregion.c40
-rw-r--r--drivers/acpi/executer/exresnte.c17
-rw-r--r--drivers/acpi/executer/exresolv.c77
-rw-r--r--drivers/acpi/executer/exresop.c12
-rw-r--r--drivers/acpi/executer/exstore.c15
-rw-r--r--drivers/acpi/executer/exstoren.c7
-rw-r--r--drivers/acpi/executer/exstorob.c17
-rw-r--r--drivers/acpi/executer/exsystem.c12
-rw-r--r--drivers/acpi/executer/exutils.c17
-rw-r--r--drivers/acpi/hardware/hwacpi.c6
-rw-r--r--drivers/acpi/hardware/hwgpe.c8
-rw-r--r--drivers/acpi/hardware/hwregs.c146
-rw-r--r--drivers/acpi/hardware/hwsleep.c31
-rw-r--r--drivers/acpi/hardware/hwtimer.c20
-rw-r--r--drivers/acpi/motherboard.c61
-rw-r--r--drivers/acpi/namespace/nsaccess.c46
-rw-r--r--drivers/acpi/namespace/nsalloc.c118
-rw-r--r--drivers/acpi/namespace/nsdump.c15
-rw-r--r--drivers/acpi/namespace/nsdumpdv.c6
-rw-r--r--drivers/acpi/namespace/nseval.c484
-rw-r--r--drivers/acpi/namespace/nsinit.c298
-rw-r--r--drivers/acpi/namespace/nsload.c27
-rw-r--r--drivers/acpi/namespace/nsnames.c14
-rw-r--r--drivers/acpi/namespace/nsobject.c15
-rw-r--r--drivers/acpi/namespace/nsparse.c6
-rw-r--r--drivers/acpi/namespace/nssearch.c148
-rw-r--r--drivers/acpi/namespace/nsutils.c104
-rw-r--r--drivers/acpi/namespace/nswalk.c6
-rw-r--r--drivers/acpi/namespace/nsxfeval.c203
-rw-r--r--drivers/acpi/namespace/nsxfname.c22
-rw-r--r--drivers/acpi/namespace/nsxfobj.c11
-rw-r--r--drivers/acpi/osl.c159
-rw-r--r--drivers/acpi/parser/psargs.c25
-rw-r--r--drivers/acpi/parser/psloop.c25
-rw-r--r--drivers/acpi/parser/psopcode.c6
-rw-r--r--drivers/acpi/parser/psparse.c35
-rw-r--r--drivers/acpi/parser/psscope.c17
-rw-r--r--drivers/acpi/parser/pstree.c8
-rw-r--r--drivers/acpi/parser/psutils.c5
-rw-r--r--drivers/acpi/parser/pswalk.c5
-rw-r--r--drivers/acpi/parser/psxface.c46
-rw-r--r--drivers/acpi/processor_core.c10
-rw-r--r--drivers/acpi/processor_perflib.c5
-rw-r--r--drivers/acpi/resources/rscalc.c108
-rw-r--r--drivers/acpi/resources/rscreate.c33
-rw-r--r--drivers/acpi/resources/rsdump.c42
-rw-r--r--drivers/acpi/resources/rsinfo.c1
-rw-r--r--drivers/acpi/resources/rslist.c102
-rw-r--r--drivers/acpi/resources/rsmisc.c12
-rw-r--r--drivers/acpi/resources/rsutils.c155
-rw-r--r--drivers/acpi/resources/rsxface.c395
-rw-r--r--drivers/acpi/scan.c41
-rw-r--r--drivers/acpi/sleep/wakeup.c3
-rw-r--r--drivers/acpi/system.c6
-rw-r--r--drivers/acpi/tables.c4
-rw-r--r--drivers/acpi/tables/tbconvrt.c46
-rw-r--r--drivers/acpi/tables/tbget.c65
-rw-r--r--drivers/acpi/tables/tbgetall.c11
-rw-r--r--drivers/acpi/tables/tbinstal.c50
-rw-r--r--drivers/acpi/tables/tbrsdt.c46
-rw-r--r--drivers/acpi/tables/tbutils.c149
-rw-r--r--drivers/acpi/tables/tbxface.c42
-rw-r--r--drivers/acpi/tables/tbxfroot.c82
-rw-r--r--drivers/acpi/thermal.c3
-rw-r--r--drivers/acpi/utilities/utalloc.c634
-rw-r--r--drivers/acpi/utilities/utcache.c18
-rw-r--r--drivers/acpi/utilities/utcopy.c41
-rw-r--r--drivers/acpi/utilities/utdebug.c65
-rw-r--r--drivers/acpi/utilities/utdelete.c62
-rw-r--r--drivers/acpi/utilities/uteval.c141
-rw-r--r--drivers/acpi/utilities/utglobal.c62
-rw-r--r--drivers/acpi/utilities/utinit.c26
-rw-r--r--drivers/acpi/utilities/utmath.c8
-rw-r--r--drivers/acpi/utilities/utmisc.c293
-rw-r--r--drivers/acpi/utilities/utmutex.c42
-rw-r--r--drivers/acpi/utilities/utobject.c23
-rw-r--r--drivers/acpi/utilities/utresrc.c256
-rw-r--r--drivers/acpi/utilities/utstate.c36
-rw-r--r--drivers/acpi/utilities/utxface.c44
-rw-r--r--drivers/atm/lanai.c2
-rw-r--r--drivers/base/bus.c5
-rw-r--r--drivers/base/class.c45
-rw-r--r--drivers/base/dd.c2
-rw-r--r--drivers/base/firmware_class.c39
-rw-r--r--drivers/base/memory.c8
-rw-r--r--drivers/base/node.c2
-rw-r--r--drivers/base/power/suspend.c17
-rw-r--r--drivers/base/topology.c2
-rw-r--r--drivers/block/DAC960.c24
-rw-r--r--drivers/block/Kconfig3
-rw-r--r--drivers/block/acsi_slm.c2
-rw-r--r--drivers/block/amiflop.c1
-rw-r--r--drivers/block/cciss.c108
-rw-r--r--drivers/block/cciss_scsi.c3
-rw-r--r--drivers/block/floppy.c11
-rw-r--r--drivers/block/paride/bpck6.c3
-rw-r--r--drivers/block/paride/pd.c3
-rw-r--r--drivers/block/paride/pg.c8
-rw-r--r--drivers/block/paride/pt.c8
-rw-r--r--drivers/block/ub.c18
-rw-r--r--drivers/block/umem.c5
-rw-r--r--drivers/bluetooth/bluecard_cs.c119
-rw-r--r--drivers/bluetooth/bt3c_cs.c130
-rw-r--r--drivers/bluetooth/btuart_cs.c130
-rw-r--r--drivers/bluetooth/dtl1_cs.c120
-rw-r--r--drivers/cdrom/aztcd.c2
-rw-r--r--drivers/char/Kconfig25
-rw-r--r--drivers/char/Makefile5
-rw-r--r--drivers/char/agp/Kconfig2
-rw-r--r--drivers/char/agp/amd64-agp.c3
-rw-r--r--drivers/char/agp/efficeon-agp.c8
-rw-r--r--drivers/char/agp/hp-agp.c2
-rw-r--r--drivers/char/agp/nvidia-agp.c3
-rw-r--r--drivers/char/agp/via-agp.c7
-rw-r--r--drivers/char/applicom.c2
-rw-r--r--drivers/char/cs5535_gpio.c5
-rw-r--r--drivers/char/drm/drmP.h21
-rw-r--r--drivers/char/drm/drm_agpsupport.c2
-rw-r--r--drivers/char/drm/drm_bufs.c25
-rw-r--r--drivers/char/drm/drm_dma.c4
-rw-r--r--drivers/char/drm/drm_drv.c4
-rw-r--r--drivers/char/drm/drm_fops.c2
-rw-r--r--drivers/char/drm/drm_memory.c173
-rw-r--r--drivers/char/drm/drm_memory.h128
-rw-r--r--drivers/char/drm/drm_memory_debug.h72
-rw-r--r--drivers/char/drm/drm_pci.c30
-rw-r--r--drivers/char/drm/drm_pciids.h116
-rw-r--r--drivers/char/drm/drm_stub.c2
-rw-r--r--drivers/char/drm/i810_dma.c2
-rw-r--r--drivers/char/drm/i830_dma.c2
-rw-r--r--drivers/char/drm/i915_dma.c2
-rw-r--r--drivers/char/drm/i915_irq.c2
-rw-r--r--drivers/char/drm/r300_cmdbuf.c86
-rw-r--r--drivers/char/drm/r300_reg.h39
-rw-r--r--drivers/char/drm/radeon_cp.c151
-rw-r--r--drivers/char/drm/radeon_drm.h5
-rw-r--r--drivers/char/drm/radeon_drv.h25
-rw-r--r--drivers/char/drm/radeon_state.c105
-rw-r--r--drivers/char/drm/sis_mm.c2
-rw-r--r--drivers/char/drm/via_irq.c12
-rw-r--r--drivers/char/dtlk.c2
-rw-r--r--drivers/char/generic_nvram.c5
-rw-r--r--drivers/char/genrtc.c8
-rw-r--r--drivers/char/hpet.c5
-rw-r--r--drivers/char/hvc_console.c101
-rw-r--r--drivers/char/hvc_console.h63
-rw-r--r--drivers/char/hvc_rtas.c138
-rw-r--r--drivers/char/hvc_vio.c11
-rw-r--r--drivers/char/hvcs.c3
-rw-r--r--drivers/char/ipmi/ipmi_bt_sm.c2
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c18
-rw-r--r--drivers/char/ipmi/ipmi_kcs_sm.c8
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c86
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c2
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c134
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c67
-rw-r--r--drivers/char/istallion.c32
-rw-r--r--drivers/char/keyboard.c136
-rw-r--r--drivers/char/mem.c16
-rw-r--r--drivers/char/misc.c2
-rw-r--r--drivers/char/mwave/mwavedd.c2
-rw-r--r--drivers/char/mxser.h2
-rw-r--r--drivers/char/n_tty.c4
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c131
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c144
-rw-r--r--drivers/char/pcmcia/synclink_cs.c116
-rw-r--r--drivers/char/random.c1
-rw-r--r--drivers/char/rio/host.h9
-rw-r--r--drivers/char/rio/rioboot.c1
-rw-r--r--drivers/char/rio/rioctrl.c43
-rw-r--r--drivers/char/rio/rioioctl.h56
-rw-r--r--drivers/char/snsc.c3
-rw-r--r--drivers/char/sonypi.c3
-rw-r--r--drivers/char/stallion.c46
-rw-r--r--drivers/char/synclink.c33
-rw-r--r--drivers/char/synclink_gt.c250
-rw-r--r--drivers/char/tipar.c2
-rw-r--r--drivers/char/tlclk.c36
-rw-r--r--drivers/char/tpm/Kconfig11
-rw-r--r--drivers/char/tpm/Makefile1
-rw-r--r--drivers/char/tpm/tpm.c786
-rw-r--r--drivers/char/tpm/tpm.h39
-rw-r--r--drivers/char/tpm/tpm_atmel.c58
-rw-r--r--drivers/char/tpm/tpm_atmel.h25
-rw-r--r--drivers/char/tpm/tpm_bios.c137
-rw-r--r--drivers/char/tpm/tpm_infineon.c61
-rw-r--r--drivers/char/tpm/tpm_nsc.c49
-rw-r--r--drivers/char/tpm/tpm_tis.c665
-rw-r--r--drivers/char/tty_io.c60
-rw-r--r--drivers/char/vt.c12
-rw-r--r--drivers/char/watchdog/Kconfig7
-rw-r--r--drivers/char/watchdog/Makefile1
-rw-r--r--drivers/char/watchdog/at91_wdt.c228
-rw-r--r--drivers/char/watchdog/i8xx_tco.c16
-rw-r--r--drivers/char/watchdog/pcwd.c137
-rw-r--r--drivers/char/watchdog/pcwd_usb.c3
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c6
-rw-r--r--drivers/char/watchdog/sc1200wdt.c2
-rw-r--r--drivers/cpufreq/Kconfig2
-rw-r--r--drivers/cpufreq/cpufreq.c88
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c157
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c39
-rw-r--r--drivers/edac/Kconfig2
-rw-r--r--drivers/edac/e752x_edac.c17
-rw-r--r--drivers/edac/edac_mc.c2
-rw-r--r--drivers/firmware/Makefile3
-rw-r--r--drivers/firmware/dcdbas.c19
-rw-r--r--drivers/firmware/dmi_scan.c (renamed from arch/i386/kernel/dmi_scan.c)12
-rw-r--r--drivers/hwmon/hdaps.c51
-rw-r--r--drivers/hwmon/w83792d.c5
-rw-r--r--drivers/i2c/busses/Kconfig5
-rw-r--r--drivers/i2c/busses/i2c-i801.c5
-rw-r--r--drivers/i2c/busses/i2c-parport-light.c9
-rw-r--r--drivers/i2c/busses/i2c-parport.c9
-rw-r--r--drivers/i2c/busses/i2c-parport.h2
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c8
-rw-r--r--drivers/i2c/busses/scx200_acb.c18
-rw-r--r--drivers/i2c/chips/Kconfig18
-rw-r--r--drivers/i2c/chips/Makefile2
-rw-r--r--drivers/i2c/chips/ds1374.c16
-rw-r--r--drivers/i2c/chips/m41t00.c24
-rw-r--r--drivers/i2c/chips/rtc8564.c385
-rw-r--r--drivers/i2c/chips/rtc8564.h78
-rw-r--r--drivers/ide/ide-cd.c1
-rw-r--r--drivers/ide/ide-disk.c3
-rw-r--r--drivers/ide/ide-tape.c5
-rw-r--r--drivers/ide/ide-taskfile.c8
-rw-r--r--drivers/ide/legacy/ide-cs.c128
-rw-r--r--drivers/ide/pci/alim15x3.c2
-rw-r--r--drivers/ide/pci/amd74xx.c8
-rw-r--r--drivers/ide/pci/atiixp.c1
-rw-r--r--drivers/ide/pci/generic.c3
-rw-r--r--drivers/ide/pci/pdc202xx_old.c2
-rw-r--r--drivers/ide/pci/sgiioc4.c16
-rw-r--r--drivers/ide/pci/sis5513.c2
-rw-r--r--drivers/ide/pci/via82cxxx.c2
-rw-r--r--drivers/ide/ppc/pmac.c4
-rw-r--r--drivers/ide/setup-pci.c13
-rw-r--r--drivers/ieee1394/dv1394.c41
-rw-r--r--drivers/ieee1394/ieee1394_core.c16
-rw-r--r--drivers/ieee1394/ieee1394_core.h3
-rw-r--r--drivers/ieee1394/ohci1394.c53
-rw-r--r--drivers/ieee1394/raw1394.c6
-rw-r--r--drivers/ieee1394/sbp2.c380
-rw-r--r--drivers/ieee1394/sbp2.h18
-rw-r--r--drivers/ieee1394/video1394.c16
-rw-r--r--drivers/infiniband/Kconfig1
-rw-r--r--drivers/infiniband/Makefile1
-rw-r--r--drivers/infiniband/core/cache.c2
-rw-r--r--drivers/infiniband/core/cm.c12
-rw-r--r--drivers/infiniband/core/mad.c158
-rw-r--r--drivers/infiniband/core/mad_priv.h8
-rw-r--r--drivers/infiniband/core/mad_rmpp.c74
-rw-r--r--drivers/infiniband/core/sysfs.c2
-rw-r--r--drivers/infiniband/core/ucm.c12
-rw-r--r--drivers/infiniband/core/user_mad.c30
-rw-r--r--drivers/infiniband/core/uverbs_mem.c4
-rw-r--r--drivers/infiniband/core/verbs.c34
-rw-r--r--drivers/infiniband/hw/ipath/Kconfig16
-rw-r--r--drivers/infiniband/hw/ipath/Makefile36
-rw-r--r--drivers/infiniband/hw/ipath/ipath_common.h616
-rw-r--r--drivers/infiniband/hw/ipath/ipath_cq.c295
-rw-r--r--drivers/infiniband/hw/ipath/ipath_debug.h97
-rw-r--r--drivers/infiniband/hw/ipath/ipath_diag.c368
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c1992
-rw-r--r--drivers/infiniband/hw/ipath/ipath_eeprom.c612
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c1914
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c605
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ht400.c1603
-rw-r--r--drivers/infiniband/hw/ipath/ipath_init_chip.c958
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c854
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h883
-rw-r--r--drivers/infiniband/hw/ipath/ipath_keys.c230
-rw-r--r--drivers/infiniband/hw/ipath/ipath_layer.c1521
-rw-r--r--drivers/infiniband/hw/ipath/ipath_layer.h181
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mad.c1352
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mr.c383
-rw-r--r--drivers/infiniband/hw/ipath/ipath_pe800.c1253
-rw-r--r--drivers/infiniband/hw/ipath/ipath_qp.c913
-rw-r--r--drivers/infiniband/hw/ipath/ipath_rc.c1856
-rw-r--r--drivers/infiniband/hw/ipath/ipath_registers.h453
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ruc.c545
-rw-r--r--drivers/infiniband/hw/ipath/ipath_srq.c273
-rw-r--r--drivers/infiniband/hw/ipath/ipath_stats.c303
-rw-r--r--drivers/infiniband/hw/ipath/ipath_sysfs.c790
-rw-r--r--drivers/infiniband/hw/ipath/ipath_uc.c645
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ud.c623
-rw-r--r--drivers/infiniband/hw/ipath/ipath_user_pages.c207
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c1204
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.h693
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs_mcast.c333
-rw-r--r--drivers/infiniband/hw/ipath/ipath_wc_x86_64.c157
-rw-r--r--drivers/infiniband/hw/ipath/ips_common.h263
-rw-r--r--drivers/infiniband/hw/ipath/verbs_debug.h107
-rw-r--r--drivers/infiniband/hw/mthca/Kconfig11
-rw-r--r--drivers/infiniband/hw/mthca/Makefile4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c102
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c6
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.h1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c43
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h25
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c6
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mad.c44
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c28
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mcg.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c19
-rw-r--r--drivers/infiniband/hw/mthca/mthca_pd.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.h25
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c114
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c95
-rw-r--r--drivers/infiniband/ulp/ipoib/Kconfig3
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h7
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_fs.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c23
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c90
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c58
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_vlan.c4
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c200
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.h4
-rw-r--r--drivers/input/evbug.c3
-rw-r--r--drivers/input/evdev.c27
-rw-r--r--drivers/input/gameport/gameport.c30
-rw-r--r--drivers/input/gameport/ns558.c13
-rw-r--r--drivers/input/input.c435
-rw-r--r--drivers/input/joydev.c6
-rw-r--r--drivers/input/joystick/amijoy.c11
-rw-r--r--drivers/input/joystick/db9.c13
-rw-r--r--drivers/input/joystick/gamecon.c96
-rw-r--r--drivers/input/joystick/iforce/iforce-ff.c24
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c2
-rw-r--r--drivers/input/joystick/iforce/iforce.h5
-rw-r--r--drivers/input/joystick/sidewinder.c11
-rw-r--r--drivers/input/joystick/turbografx.c13
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/keyboard/atkbd.c24
-rw-r--r--drivers/input/keyboard/corgikbd.c43
-rw-r--r--drivers/input/keyboard/hil_kbd.c65
-rw-r--r--drivers/input/keyboard/hilkbd.c53
-rw-r--r--drivers/input/keyboard/spitzkbd.c22
-rw-r--r--drivers/input/misc/pcspkr.c27
-rw-r--r--drivers/input/misc/uinput.c14
-rw-r--r--drivers/input/misc/wistron_btns.c49
-rw-r--r--drivers/input/mouse/alps.c4
-rw-r--r--drivers/input/mouse/hil_ptr.c93
-rw-r--r--drivers/input/mouse/lifebook.c24
-rw-r--r--drivers/input/mouse/logips2pp.c6
-rw-r--r--drivers/input/mouse/psmouse-base.c42
-rw-r--r--drivers/input/mouse/synaptics.c18
-rw-r--r--drivers/input/mousedev.c6
-rw-r--r--drivers/input/power.c3
-rw-r--r--drivers/input/serio/gscps2.c4
-rw-r--r--drivers/input/serio/hil_mlc.c3
-rw-r--r--drivers/input/serio/i8042-io.h4
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h26
-rw-r--r--drivers/input/serio/libps2.c10
-rw-r--r--drivers/input/serio/parkbd.c3
-rw-r--r--drivers/input/serio/rpckbd.c3
-rw-r--r--drivers/input/serio/serio.c48
-rw-r--r--drivers/input/serio/serio_raw.c29
-rw-r--r--drivers/input/touchscreen/ads7846.c445
-rw-r--r--drivers/input/touchscreen/corgi_ts.c2
-rw-r--r--drivers/input/tsdev.c6
-rw-r--r--drivers/isdn/capi/capi.c7
-rw-r--r--drivers/isdn/capi/kcapi_proc.c2
-rw-r--r--drivers/isdn/gigaset/Kconfig4
-rw-r--r--drivers/isdn/gigaset/asyncdata.c132
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c1321
-rw-r--r--drivers/isdn/gigaset/common.c504
-rw-r--r--drivers/isdn/gigaset/ev-layer.c670
-rw-r--r--drivers/isdn/gigaset/gigaset.h601
-rw-r--r--drivers/isdn/gigaset/i4l.c229
-rw-r--r--drivers/isdn/gigaset/interface.c235
-rw-r--r--drivers/isdn/gigaset/isocdata.c139
-rw-r--r--drivers/isdn/gigaset/proc.c51
-rw-r--r--drivers/isdn/gigaset/usb-gigaset.c459
-rw-r--r--drivers/isdn/hardware/avm/avm_cs.c185
-rw-r--r--drivers/isdn/hisax/avma1_cs.c182
-rw-r--r--drivers/isdn/hisax/elsa_cs.c112
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c143
-rw-r--r--drivers/isdn/hisax/teles_cs.c121
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c20
-rw-r--r--drivers/isdn/i4l/isdn_tty.c2
-rw-r--r--drivers/isdn/sc/ioctl.c9
-rw-r--r--drivers/leds/Kconfig91
-rw-r--r--drivers/leds/Makefile17
-rw-r--r--drivers/leds/led-class.c172
-rw-r--r--drivers/leds/led-core.c25
-rw-r--r--drivers/leds/led-triggers.c239
-rw-r--r--drivers/leds/leds-corgi.c121
-rw-r--r--drivers/leds/leds-ixp4xx-gpio.c215
-rw-r--r--drivers/leds/leds-locomo.c95
-rw-r--r--drivers/leds/leds-s3c24xx.c163
-rw-r--r--drivers/leds/leds-spitz.c125
-rw-r--r--drivers/leds/leds-tosa.c131
-rw-r--r--drivers/leds/leds.h44
-rw-r--r--drivers/leds/ledtrig-ide-disk.c62
-rw-r--r--drivers/leds/ledtrig-timer.c179
-rw-r--r--drivers/macintosh/adb.c14
-rw-r--r--drivers/macintosh/adbhid.c7
-rw-r--r--drivers/macintosh/mediabay.c4
-rw-r--r--drivers/macintosh/therm_adt746x.c4
-rw-r--r--drivers/macintosh/via-pmu.c2
-rw-r--r--drivers/macintosh/via-pmu68k.c7
-rw-r--r--drivers/macintosh/windfarm_core.c8
-rw-r--r--drivers/md/Kconfig27
-rw-r--r--drivers/md/dm-crypt.c11
-rw-r--r--drivers/md/dm-ioctl.c100
-rw-r--r--drivers/md/dm-linear.c8
-rw-r--r--drivers/md/dm-raid1.c29
-rw-r--r--drivers/md/dm-snap.c409
-rw-r--r--drivers/md/dm-stripe.c13
-rw-r--r--drivers/md/dm-table.c53
-rw-r--r--drivers/md/dm-target.c3
-rw-r--r--drivers/md/dm.c88
-rw-r--r--drivers/md/dm.h23
-rw-r--r--drivers/md/kcopyd.c28
-rw-r--r--drivers/md/md.c281
-rw-r--r--drivers/md/raid0.c5
-rw-r--r--drivers/md/raid1.c75
-rw-r--r--drivers/md/raid10.c52
-rw-r--r--drivers/md/raid5.c753
-rw-r--r--drivers/md/raid6main.c45
-rw-r--r--drivers/media/Kconfig69
-rw-r--r--drivers/media/common/Kconfig3
-rw-r--r--drivers/media/dvb/Kconfig10
-rw-r--r--drivers/media/dvb/b2c2/Kconfig6
-rw-r--r--drivers/media/dvb/bt8xx/Kconfig4
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c6
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c5
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c12
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c30
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h2
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c6
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig2
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c71
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c47
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h2
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x-fe.c5
-rw-r--r--drivers/media/dvb/frontends/Kconfig12
-rw-r--r--drivers/media/dvb/frontends/cx24123.c565
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c4
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c12
-rw-r--r--drivers/media/dvb/pluto2/Kconfig3
-rw-r--r--drivers/media/dvb/pluto2/Makefile2
-rw-r--r--drivers/media/dvb/ttpci/Kconfig12
-rw-r--r--drivers/media/dvb/ttpci/av7110.c8
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c2
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c19
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c105
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c78
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c24
-rw-r--r--drivers/media/dvb/ttpci/budget.h13
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c6
-rw-r--r--drivers/media/radio/Kconfig30
-rw-r--r--drivers/media/video/Kconfig306
-rw-r--r--drivers/media/video/Makefile18
-rw-r--r--drivers/media/video/bt8xx/Kconfig2
-rw-r--r--drivers/media/video/bt8xx/Makefile4
-rw-r--r--drivers/media/video/bt8xx/bttv-cards.c4
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c170
-rw-r--r--drivers/media/video/bt8xx/bttv-risc.c14
-rw-r--r--drivers/media/video/bt8xx/bttv-vbi.c2
-rw-r--r--drivers/media/video/cpia.c13
-rw-r--r--drivers/media/video/cpia2/cpia2.h2
-rw-r--r--drivers/media/video/cpia_pp.c2
-rw-r--r--drivers/media/video/cx25840/Makefile2
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c3
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c24
-rw-r--r--drivers/media/video/cx25840/cx25840-core.h (renamed from drivers/media/video/cx25840/cx25840.h)46
-rw-r--r--drivers/media/video/cx25840/cx25840-firmware.c64
-rw-r--r--drivers/media/video/cx25840/cx25840-vbi.c9
-rw-r--r--drivers/media/video/cx88/Kconfig15
-rw-r--r--drivers/media/video/cx88/Makefile6
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c2
-rw-r--r--drivers/media/video/cx88/cx88-cards.c2
-rw-r--r--drivers/media/video/cx88/cx88-core.c16
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c2
-rw-r--r--drivers/media/video/cx88/cx88-video.c2
-rw-r--r--drivers/media/video/em28xx/Kconfig2
-rw-r--r--drivers/media/video/em28xx/Makefile2
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c4
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c43
-rw-r--r--drivers/media/video/et61x251/Kconfig14
-rw-r--r--drivers/media/video/ir-kbd-i2c.c3
-rw-r--r--drivers/media/video/msp3400-driver.c91
-rw-r--r--drivers/media/video/msp3400-driver.h6
-rw-r--r--drivers/media/video/msp3400-kthreads.c121
-rw-r--r--drivers/media/video/planb.c2
-rw-r--r--drivers/media/video/pwc/Kconfig28
-rw-r--r--drivers/media/video/pwc/Makefile17
-rw-r--r--drivers/media/video/saa7115.c65
-rw-r--r--drivers/media/video/saa7127.c44
-rw-r--r--drivers/media/video/saa7134/Kconfig1
-rw-r--r--drivers/media/video/saa7134/Makefile6
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c67
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c9
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c4
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c2
-rw-r--r--drivers/media/video/saa7134/saa7134.h1
-rw-r--r--drivers/media/video/sn9c102/Kconfig11
-rw-r--r--drivers/media/video/tuner-core.c12
-rw-r--r--drivers/media/video/tuner-types.c4
-rw-r--r--drivers/media/video/tvaudio.c15
-rw-r--r--drivers/media/video/tveeprom.c8
-rw-r--r--drivers/media/video/tvp5150.c140
-rw-r--r--drivers/media/video/upd64031a.c286
-rw-r--r--drivers/media/video/upd64083.c262
-rw-r--r--drivers/media/video/usbvideo/Kconfig38
-rw-r--r--drivers/media/video/usbvideo/Makefile8
-rw-r--r--drivers/media/video/v4l2-common.c8
-rw-r--r--drivers/media/video/video-buf.c14
-rw-r--r--drivers/media/video/videodev.c2
-rw-r--r--drivers/media/video/vivi.c5
-rw-r--r--drivers/media/video/wm8739.c355
-rw-r--r--drivers/media/video/zc0301/Kconfig11
-rw-r--r--drivers/message/fusion/mptbase.c90
-rw-r--r--drivers/message/fusion/mptbase.h10
-rw-r--r--drivers/message/fusion/mptfc.c134
-rw-r--r--drivers/message/fusion/mptsas.c109
-rw-r--r--drivers/message/fusion/mptscsih.c50
-rw-r--r--drivers/message/fusion/mptspi.c70
-rw-r--r--drivers/message/i2o/exec-osm.c72
-rw-r--r--drivers/message/i2o/i2o_proc.c2
-rw-r--r--drivers/message/i2o/iop.c4
-rw-r--r--drivers/misc/ibmasm/heartbeat.c5
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c2
-rw-r--r--drivers/mmc/Kconfig31
-rw-r--r--drivers/mmc/Makefile7
-rw-r--r--drivers/mmc/at91_mci.c985
-rw-r--r--drivers/mmc/au1xmmc.c27
-rw-r--r--drivers/mmc/imxmmc.c1128
-rw-r--r--drivers/mmc/imxmmc.h67
-rw-r--r--drivers/mmc/mmc.c70
-rw-r--r--drivers/mmc/mmc_block.c9
-rw-r--r--drivers/mmc/mmci.c7
-rw-r--r--drivers/mmc/omap.c1226
-rw-r--r--drivers/mmc/omap.h55
-rw-r--r--drivers/mmc/pxamci.c37
-rw-r--r--drivers/mmc/sdhci.c10
-rw-r--r--drivers/mmc/wbsd.c21
-rw-r--r--drivers/mtd/chips/Kconfig21
-rw-r--r--drivers/mtd/chips/amd_flash.c4
-rw-r--r--drivers/mtd/chips/jedec_probe.c19
-rw-r--r--drivers/mtd/chips/sharp.c7
-rw-r--r--drivers/mtd/cmdlinepart.c7
-rw-r--r--drivers/mtd/devices/Kconfig13
-rw-r--r--drivers/mtd/devices/Makefile1
-rw-r--r--drivers/mtd/devices/blkmtd.c820
-rw-r--r--drivers/mtd/devices/block2mtd.c13
-rw-r--r--drivers/mtd/devices/doc2000.c37
-rw-r--r--drivers/mtd/devices/lart.c10
-rw-r--r--drivers/mtd/devices/m25p80.c2
-rw-r--r--drivers/mtd/devices/ms02-nv.c2
-rw-r--r--drivers/mtd/inftlcore.c7
-rw-r--r--drivers/mtd/maps/alchemy-flash.c4
-rw-r--r--drivers/mtd/maps/cfi_flagadm.c2
-rw-r--r--drivers/mtd/maps/dbox2-flash.c2
-rw-r--r--drivers/mtd/maps/dilnetpc.c4
-rw-r--r--drivers/mtd/maps/dmv182.c2
-rw-r--r--drivers/mtd/maps/h720x-flash.c2
-rw-r--r--drivers/mtd/maps/netsc520.c4
-rw-r--r--drivers/mtd/maps/nettel.c3
-rw-r--r--drivers/mtd/maps/ocotea.c6
-rw-r--r--drivers/mtd/maps/pci.c3
-rw-r--r--drivers/mtd/maps/pcmciamtd.c117
-rw-r--r--drivers/mtd/maps/redwood.c3
-rw-r--r--drivers/mtd/maps/sbc8240.c8
-rw-r--r--drivers/mtd/maps/sc520cdp.c2
-rw-r--r--drivers/mtd/maps/scx200_docflash.c2
-rw-r--r--drivers/mtd/maps/sharpsl-flash.c4
-rw-r--r--drivers/mtd/maps/ts5500_flash.c2
-rw-r--r--drivers/mtd/maps/uclinux.c2
-rw-r--r--drivers/mtd/maps/vmax301.c2
-rw-r--r--drivers/mtd/mtd_blkdevs.c32
-rw-r--r--drivers/mtd/mtdblock.c14
-rw-r--r--drivers/mtd/mtdcore.c45
-rw-r--r--drivers/mtd/nand/Kconfig17
-rw-r--r--drivers/mtd/nand/au1550nd.c4
-rw-r--r--drivers/mtd/nand/nand_base.c26
-rw-r--r--drivers/mtd/redboot.c6
-rw-r--r--drivers/net/3c59x.c33
-rw-r--r--drivers/net/8139cp.c12
-rw-r--r--drivers/net/8390.h2
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/acenic_firmware.h10
-rw-r--r--drivers/net/arcnet/arcnet.c3
-rw-r--r--drivers/net/arcnet/com90xx.c4
-rw-r--r--drivers/net/au1000_eth.c18
-rw-r--r--drivers/net/b44.c105
-rw-r--r--drivers/net/bnx2.c22
-rw-r--r--drivers/net/bonding/bond_3ad.c28
-rw-r--r--drivers/net/bonding/bond_3ad.h1
-rw-r--r--drivers/net/bonding/bond_main.c99
-rw-r--r--drivers/net/bonding/bonding.h4
-rw-r--r--drivers/net/chelsio/Makefile2
-rw-r--r--drivers/net/chelsio/sge.c3
-rw-r--r--drivers/net/dl2k.c13
-rw-r--r--drivers/net/e1000/e1000_ethtool.c5
-rw-r--r--drivers/net/e1000/e1000_main.c22
-rw-r--r--drivers/net/eql.c3
-rw-r--r--drivers/net/forcedeth.c476
-rw-r--r--drivers/net/gianfar.c56
-rw-r--r--drivers/net/gianfar.h67
-rw-r--r--drivers/net/gianfar_ethtool.c20
-rw-r--r--drivers/net/gianfar_sysfs.c24
-rw-r--r--drivers/net/hamradio/dmascc.c1
-rw-r--r--drivers/net/hamradio/scc.c1
-rw-r--r--drivers/net/hamradio/yam.c1
-rw-r--r--drivers/net/hydra.h177
-rw-r--r--drivers/net/ibmveth.c30
-rw-r--r--drivers/net/ioc3-eth.c7
-rw-r--r--drivers/net/irda/Kconfig20
-rw-r--r--drivers/net/irda/Makefile2
-rw-r--r--drivers/net/irda/irda-usb.c365
-rw-r--r--drivers/net/irda/irda-usb.h43
-rw-r--r--drivers/net/irda/nsc-ircc.c4
-rw-r--r--drivers/net/irda/sa1100_ir.c3
-rw-r--r--drivers/net/irda/sir-dev.h13
-rw-r--r--drivers/net/irda/sir_dev.c315
-rw-r--r--drivers/net/irda/sir_kthread.c508
-rw-r--r--drivers/net/irda/smsc-ircc2.c537
-rw-r--r--drivers/net/ixgb/ixgb_main.c13
-rw-r--r--drivers/net/ixp2000/enp2611.c13
-rw-r--r--drivers/net/ixp2000/ixpdev.c5
-rw-r--r--drivers/net/ixp2000/pm3386.c30
-rw-r--r--drivers/net/ixp2000/pm3386.h1
-rw-r--r--drivers/net/loopback.c2
-rw-r--r--drivers/net/mv643xx_eth.c21
-rw-r--r--drivers/net/natsemi.c20
-rw-r--r--drivers/net/ne.c33
-rw-r--r--drivers/net/ne2k-pci.c4
-rw-r--r--drivers/net/netconsole.c5
-rw-r--r--drivers/net/ns83820.c9
-rw-r--r--drivers/net/pcmcia/3c574_cs.c115
-rw-r--r--drivers/net/pcmcia/3c589_cs.c122
-rw-r--r--drivers/net/pcmcia/axnet_cs.c180
-rw-r--r--drivers/net/pcmcia/com20020_cs.c127
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c166
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c121
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c128
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c162
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c235
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c187
-rw-r--r--drivers/net/pcnet32.c6
-rw-r--r--drivers/net/phy/mdio_bus.c4
-rw-r--r--drivers/net/pppoe.c3
-rw-r--r--drivers/net/sis900.c3
-rw-r--r--drivers/net/skge.c6
-rw-r--r--drivers/net/sky2.c324
-rw-r--r--drivers/net/sky2.h9
-rw-r--r--drivers/net/spider_net.c16
-rw-r--r--drivers/net/spider_net.h2
-rw-r--r--drivers/net/starfire.c5
-rw-r--r--drivers/net/sungem_phy.c56
-rw-r--r--drivers/net/sungem_phy.h1
-rw-r--r--drivers/net/tg3.c397
-rw-r--r--drivers/net/tg3.h7
-rw-r--r--drivers/net/tokenring/Kconfig2
-rw-r--r--drivers/net/tokenring/abyss.c3
-rw-r--r--drivers/net/tokenring/madgemc.c3
-rw-r--r--drivers/net/tulip/de4x5.c4
-rw-r--r--drivers/net/tulip/pnic2.c2
-rw-r--r--drivers/net/tulip/winbond-840.c4
-rw-r--r--drivers/net/typhoon.c6
-rw-r--r--drivers/net/via-rhine.c60
-rw-r--r--drivers/net/wan/Kconfig97
-rw-r--r--drivers/net/wan/Makefile13
-rw-r--r--drivers/net/wan/sdla_chdlc.c4428
-rw-r--r--drivers/net/wan/sdla_fr.c5061
-rw-r--r--drivers/net/wan/sdla_ft1.c345
-rw-r--r--drivers/net/wan/sdla_ppp.c3430
-rw-r--r--drivers/net/wan/sdla_x25.c5497
-rw-r--r--drivers/net/wan/sdladrv.c2314
-rw-r--r--drivers/net/wan/sdlamain.c1346
-rw-r--r--drivers/net/wan/wanpipe_multppp.c2358
-rw-r--r--drivers/net/wan/wanxl.c4
-rw-r--r--drivers/net/wireless/Kconfig11
-rw-r--r--drivers/net/wireless/Makefile1
-rw-r--r--drivers/net/wireless/airo.c46
-rw-r--r--drivers/net/wireless/airo_cs.c158
-rw-r--r--drivers/net/wireless/arlan-main.c4
-rw-r--r--drivers/net/wireless/atmel.c11
-rw-r--r--drivers/net/wireless/atmel_cs.c162
-rw-r--r--drivers/net/wireless/bcm43xx/Kconfig65
-rw-r--r--drivers/net/wireless/bcm43xx/Makefile12
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h937
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c499
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h117
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.c982
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.h226
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c50
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h8
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_ilt.c337
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_ilt.h32
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_leds.c293
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_leds.h56
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c3984
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.h170
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.c2346
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.h74
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.c638
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.h150
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_power.c379
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_power.h56
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_radio.c2026
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_radio.h99
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c341
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h9
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.c1005
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.h36
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.c582
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.h156
-rw-r--r--drivers/net/wireless/hostap/hostap_80211.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c9
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c198
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c4
-rw-r--r--drivers/net/wireless/ipw2200.c9
-rw-r--r--drivers/net/wireless/netwave_cs.c127
-rw-r--r--drivers/net/wireless/orinoco.c8
-rw-r--r--drivers/net/wireless/orinoco_cs.c187
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c2
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c3
-rw-r--r--drivers/net/wireless/ray_cs.c279
-rw-r--r--drivers/net/wireless/ray_cs.h2
-rw-r--r--drivers/net/wireless/spectrum_cs.c173
-rw-r--r--drivers/net/wireless/wavelan.c2
-rw-r--r--drivers/net/wireless/wavelan_cs.c189
-rw-r--r--drivers/net/wireless/wavelan_cs.p.h6
-rw-r--r--drivers/net/wireless/wl3501.h1
-rw-r--r--drivers/net/wireless/wl3501_cs.c178
-rw-r--r--drivers/net/yellowfin.c3
-rw-r--r--drivers/oprofile/cpu_buffer.c13
-rw-r--r--drivers/oprofile/oprofile_stats.c4
-rw-r--r--drivers/oprofile/oprofilefs.c6
-rw-r--r--drivers/parisc/ccio-dma.c2
-rw-r--r--drivers/parisc/dino.c5
-rw-r--r--drivers/parisc/eisa.c2
-rw-r--r--drivers/parisc/iosapic.c2
-rw-r--r--drivers/parisc/lba_pci.c8
-rw-r--r--drivers/parisc/led.c14
-rw-r--r--drivers/parisc/pdc_stable.c7
-rw-r--r--drivers/parisc/power.c6
-rw-r--r--drivers/parisc/sba_iommu.c51
-rw-r--r--drivers/parisc/superio.c52
-rw-r--r--drivers/parport/parport_cs.c129
-rw-r--r--drivers/parport/parport_pc.c51
-rw-r--r--drivers/parport/parport_serial.c2
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c3
-rw-r--r--drivers/pci/msi.c231
-rw-r--r--drivers/pci/pci-acpi.c60
-rw-r--r--drivers/pci/pci-driver.c19
-rw-r--r--drivers/pci/pci.c30
-rw-r--r--drivers/pci/pci.h11
-rw-r--r--drivers/pci/quirks.c55
-rw-r--r--drivers/pcmcia/Kconfig9
-rw-r--r--drivers/pcmcia/Makefile3
-rw-r--r--drivers/pcmcia/at91_cf.c376
-rw-r--r--drivers/pcmcia/cistpl.c1
-rw-r--r--drivers/pcmcia/cs.c43
-rw-r--r--drivers/pcmcia/cs_internal.h19
-rw-r--r--drivers/pcmcia/ds.c267
-rw-r--r--drivers/pcmcia/ds_internal.h4
-rw-r--r--drivers/pcmcia/i82092.c1
-rw-r--r--drivers/pcmcia/i82365.c8
-rw-r--r--drivers/pcmcia/pcmcia_compat.c65
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c92
-rw-r--r--drivers/pcmcia/pcmcia_resource.c232
-rw-r--r--drivers/pcmcia/pd6729.c3
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c8
-rw-r--r--drivers/pcmcia/rsrc_mgr.c5
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c41
-rw-r--r--drivers/pcmcia/sa1100_cerf.c1
-rw-r--r--drivers/pcmcia/socket_sysfs.c10
-rw-r--r--drivers/pcmcia/ti113x.h1
-rw-r--r--drivers/pcmcia/vrc4171_card.c12
-rw-r--r--drivers/pcmcia/vrc4173_cardu.c8
-rw-r--r--drivers/pnp/card.c16
-rw-r--r--drivers/pnp/driver.c19
-rw-r--r--drivers/pnp/manager.c4
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c199
-rw-r--r--drivers/rtc/Kconfig175
-rw-r--r--drivers/rtc/Makefile22
-rw-r--r--drivers/rtc/class.c147
-rw-r--r--drivers/rtc/hctosys.c69
-rw-r--r--drivers/rtc/interface.c277
-rw-r--r--drivers/rtc/rtc-dev.c387
-rw-r--r--drivers/rtc/rtc-ds1672.c277
-rw-r--r--drivers/rtc/rtc-ep93xx.c160
-rw-r--r--drivers/rtc/rtc-lib.c101
-rw-r--r--drivers/rtc/rtc-m48t86.c204
-rw-r--r--drivers/rtc/rtc-pcf8563.c342
-rw-r--r--drivers/rtc/rtc-proc.c164
-rw-r--r--drivers/rtc/rtc-rs5c372.c290
-rw-r--r--drivers/rtc/rtc-sa1100.c384
-rw-r--r--drivers/rtc/rtc-sysfs.c124
-rw-r--r--drivers/rtc/rtc-test.c201
-rw-r--r--drivers/rtc/rtc-vr41xx.c (renamed from drivers/char/vr41xx_rtc.c)406
-rw-r--r--drivers/rtc/rtc-x1205.c (renamed from drivers/i2c/chips/x1205.c)448
-rw-r--r--drivers/s390/block/dasd.c50
-rw-r--r--drivers/s390/block/dasd_devmap.c102
-rw-r--r--drivers/s390/block/dasd_eckd.c51
-rw-r--r--drivers/s390/block/dasd_eckd.h46
-rw-r--r--drivers/s390/block/dasd_erp.c8
-rw-r--r--drivers/s390/block/dasd_int.h12
-rw-r--r--drivers/s390/block/dasd_proc.c17
-rw-r--r--drivers/s390/char/keyboard.c2
-rw-r--r--drivers/s390/char/sclp_rw.c2
-rw-r--r--drivers/s390/char/tape_3590.c22
-rw-r--r--drivers/s390/char/tape_block.c17
-rw-r--r--drivers/s390/char/tape_core.c10
-rw-r--r--drivers/s390/char/tape_std.h1
-rw-r--r--drivers/s390/cio/blacklist.c4
-rw-r--r--drivers/s390/cio/chsc.c30
-rw-r--r--drivers/s390/cio/cio.c2
-rw-r--r--drivers/s390/cio/cio_debug.h22
-rw-r--r--drivers/s390/cio/css.h4
-rw-r--r--drivers/s390/cio/device_fsm.c2
-rw-r--r--drivers/s390/cio/qdio.c36
-rw-r--r--drivers/s390/net/ctcmain.c26
-rw-r--r--drivers/s390/net/ctctty.c10
-rw-r--r--drivers/s390/net/cu3088.c10
-rw-r--r--drivers/s390/net/iucv.c36
-rw-r--r--drivers/s390/net/iucv.h622
-rw-r--r--drivers/s390/net/lcs.c334
-rw-r--r--drivers/s390/net/lcs.h14
-rw-r--r--drivers/s390/net/netiucv.c36
-rw-r--r--drivers/s390/net/qeth.h18
-rw-r--r--drivers/s390/net/qeth_eddp.c18
-rw-r--r--drivers/s390/net/qeth_fs.h2
-rw-r--r--drivers/s390/net/qeth_main.c108
-rw-r--r--drivers/s390/net/qeth_mpc.h4
-rw-r--r--drivers/s390/net/qeth_proc.c8
-rw-r--r--drivers/s390/net/qeth_sys.c6
-rw-r--r--drivers/s390/net/qeth_tso.h4
-rw-r--r--drivers/s390/s390mach.c34
-rw-r--r--drivers/sbus/char/openprom.c15
-rw-r--r--drivers/scsi/3w-9xxx.c11
-rw-r--r--drivers/scsi/3w-xxxx.c3
-rw-r--r--drivers/scsi/BusLogic.c10
-rw-r--r--drivers/scsi/Kconfig28
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/a100u2w.c3
-rw-r--r--drivers/scsi/aacraid/aachba.c95
-rw-r--r--drivers/scsi/aacraid/aacraid.h11
-rw-r--r--drivers/scsi/aacraid/commctrl.c12
-rw-r--r--drivers/scsi/aacraid/commsup.c41
-rw-r--r--drivers/scsi/aacraid/linit.c69
-rw-r--r--drivers/scsi/aacraid/rkt.c4
-rw-r--r--drivers/scsi/aacraid/rx.c4
-rw-r--r--drivers/scsi/aacraid/sa.c2
-rw-r--r--drivers/scsi/advansys.c2
-rw-r--r--drivers/scsi/ahci.c5
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic7xxx2
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h4
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c166
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c1
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.c12
-rw-r--r--drivers/scsi/ata_piix.c5
-rw-r--r--drivers/scsi/atp870u.c3
-rw-r--r--drivers/scsi/dpt_i2o.c5
-rw-r--r--drivers/scsi/eata.c3
-rw-r--r--drivers/scsi/gdth.c16
-rw-r--r--drivers/scsi/hosts.c12
-rw-r--r--drivers/scsi/ibmmca.c2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c281
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h2
-rw-r--r--drivers/scsi/ibmvscsi/rpa_vscsi.c11
-rw-r--r--drivers/scsi/ibmvscsi/srp.h227
-rw-r--r--drivers/scsi/ibmvscsi/viosrp.h17
-rw-r--r--drivers/scsi/initio.c3
-rw-r--r--drivers/scsi/ipr.c122
-rw-r--r--drivers/scsi/ipr.h46
-rw-r--r--drivers/scsi/ips.c5
-rw-r--r--drivers/scsi/lasi700.c2
-rw-r--r--drivers/scsi/libata-bmdma.c26
-rw-r--r--drivers/scsi/libata-core.c209
-rw-r--r--drivers/scsi/libata-scsi.c16
-rw-r--r--drivers/scsi/libata.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c95
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c18
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c22
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c33
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c134
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c68
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/megaraid.c8
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c59
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.h7
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.c6
-rw-r--r--drivers/scsi/mesh.c2
-rw-r--r--drivers/scsi/nsp32.c3
-rw-r--r--drivers/scsi/osst.c5
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c112
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c155
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c136
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.h8
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c127
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c124
-rw-r--r--drivers/scsi/pdc_adma.c1
-rw-r--r--drivers/scsi/ppa.c10
-rw-r--r--drivers/scsi/qla1280.c5
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c19
-rw-r--r--drivers/scsi/qlogicfc.c2226
-rw-r--r--drivers/scsi/qlogicfc_asm.c9751
-rw-r--r--drivers/scsi/qlogicpti.c3
-rw-r--r--drivers/scsi/sata_mv.c178
-rw-r--r--drivers/scsi/sata_nv.c1
-rw-r--r--drivers/scsi/sata_promise.c1
-rw-r--r--drivers/scsi/sata_qstor.c1
-rw-r--r--drivers/scsi/sata_sil.c1
-rw-r--r--drivers/scsi/sata_sil24.c7
-rw-r--r--drivers/scsi/sata_sis.c1
-rw-r--r--drivers/scsi/sata_svw.c1
-rw-r--r--drivers/scsi/sata_sx4.c1
-rw-r--r--drivers/scsi/sata_uli.c1
-rw-r--r--drivers/scsi/sata_via.c1
-rw-r--r--drivers/scsi/sata_vsc.c1
-rw-r--r--drivers/scsi/scsi.c5
-rw-r--r--drivers/scsi/scsi_devinfo.c7
-rw-r--r--drivers/scsi/scsi_error.c4
-rw-r--r--drivers/scsi/scsi_ioctl.c176
-rw-r--r--drivers/scsi/scsi_lib.c44
-rw-r--r--drivers/scsi/scsi_sas_internal.h38
-rw-r--r--drivers/scsi/scsi_scan.c19
-rw-r--r--drivers/scsi/scsi_transport_fc.c466
-rw-r--r--drivers/scsi/scsi_transport_sas.c71
-rw-r--r--drivers/scsi/sg.c7
-rw-r--r--drivers/scsi/sim710.c2
-rw-r--r--drivers/scsi/st.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_defs.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c205
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c113
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h2
-rw-r--r--drivers/scsi/zalon.c2
-rw-r--r--drivers/serial/8250.c76
-rw-r--r--drivers/serial/8250_au1x00.c7
-rw-r--r--drivers/serial/8250_gsc.c15
-rw-r--r--drivers/serial/Kconfig43
-rw-r--r--drivers/serial/Makefile13
-rw-r--r--drivers/serial/amba-pl010.c160
-rw-r--r--drivers/serial/au1x00_uart.c1287
-rw-r--r--drivers/serial/cpm_uart/cpm_uart.h58
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c309
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm1.c56
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c16
-rw-r--r--drivers/serial/imx.c40
-rw-r--r--drivers/serial/jsm/jsm.h2
-rw-r--r--drivers/serial/jsm/jsm_driver.c2
-rw-r--r--drivers/serial/jsm/jsm_neo.c2
-rw-r--r--drivers/serial/jsm/jsm_tty.c29
-rw-r--r--drivers/serial/m32r_sio.c1
-rw-r--r--drivers/serial/mux.c4
-rw-r--r--drivers/serial/serial_core.c123
-rw-r--r--drivers/serial/serial_cs.c229
-rw-r--r--drivers/serial/serial_txx9.c2
-rw-r--r--drivers/serial/sunsu.c3
-rw-r--r--drivers/sn/ioc3.c7
-rw-r--r--drivers/sn/ioc4.c2
-rw-r--r--drivers/spi/Kconfig34
-rw-r--r--drivers/spi/Makefile4
-rw-r--r--drivers/spi/pxa2xx_spi.c1486
-rw-r--r--drivers/spi/spi.c13
-rw-r--r--drivers/spi/spi_bitbang.c104
-rw-r--r--drivers/spi/spi_butterfly.c1
-rw-r--r--drivers/spi/spi_mpc83xx.c483
-rw-r--r--drivers/spi/spi_s3c24xx.c453
-rw-r--r--drivers/spi/spi_s3c24xx_gpio.c188
-rw-r--r--drivers/telephony/ixj_pcmcia.c119
-rw-r--r--drivers/telephony/phonedev.c2
-rw-r--r--drivers/usb/atm/speedtch.c2
-rw-r--r--drivers/usb/atm/ueagle-atm.c52
-rw-r--r--drivers/usb/atm/usbatm.c8
-rw-r--r--drivers/usb/core/Kconfig7
-rw-r--r--drivers/usb/core/file.c6
-rw-r--r--drivers/usb/core/hcd-pci.c11
-rw-r--r--drivers/usb/core/hcd.c13
-rw-r--r--drivers/usb/core/hub.c31
-rw-r--r--drivers/usb/core/notify.c65
-rw-r--r--drivers/usb/core/usb.c2
-rw-r--r--drivers/usb/gadget/Kconfig4
-rw-r--r--drivers/usb/gadget/at91_udc.c4
-rw-r--r--drivers/usb/gadget/ether.c6
-rw-r--r--drivers/usb/gadget/file_storage.c38
-rw-r--r--drivers/usb/gadget/gadget_chips.h6
-rw-r--r--drivers/usb/gadget/inode.c31
-rw-r--r--drivers/usb/gadget/net2280.c108
-rw-r--r--drivers/usb/gadget/net2280.h415
-rw-r--r--drivers/usb/gadget/zero.c7
-rw-r--r--drivers/usb/host/ehci-pci.c2
-rw-r--r--drivers/usb/host/ohci-at91.c35
-rw-r--r--drivers/usb/host/ohci-hcd.c2
-rw-r--r--drivers/usb/host/ohci-pci.c2
-rw-r--r--drivers/usb/host/ohci-pxa27x.c3
-rw-r--r--drivers/usb/host/ohci-s3c2410.c43
-rw-r--r--drivers/usb/host/pci-quirks.c1
-rw-r--r--drivers/usb/host/pci-quirks.h7
-rw-r--r--drivers/usb/host/sl811_cs.c119
-rw-r--r--drivers/usb/host/uhci-hcd.c9
-rw-r--r--drivers/usb/host/uhci-hcd.h1
-rw-r--r--drivers/usb/host/uhci-hub.c18
-rw-r--r--drivers/usb/input/Kconfig56
-rw-r--r--drivers/usb/input/Makefile1
-rw-r--r--drivers/usb/input/hid-core.c18
-rw-r--r--drivers/usb/input/hid-ff.c6
-rw-r--r--drivers/usb/input/hid-input.c2
-rw-r--r--drivers/usb/input/hid.h5
-rw-r--r--drivers/usb/input/hiddev.c1
-rw-r--r--drivers/usb/input/keyspan_remote.c2
-rw-r--r--drivers/usb/input/usbtouchscreen.c605
-rw-r--r--drivers/usb/input/wacom.c136
-rw-r--r--drivers/usb/misc/emi26.c4
-rw-r--r--drivers/usb/misc/emi62.c4
-rw-r--r--drivers/usb/misc/usbtest.c13
-rw-r--r--drivers/usb/net/asix.c327
-rw-r--r--drivers/usb/net/pegasus.c22
-rw-r--r--drivers/usb/net/rndis_host.c28
-rw-r--r--drivers/usb/net/zaurus.c2
-rw-r--r--drivers/usb/net/zd1201.c2
-rw-r--r--drivers/usb/serial/Kconfig19
-rw-r--r--drivers/usb/serial/Makefile2
-rw-r--r--drivers/usb/serial/airprime.c1
-rw-r--r--drivers/usb/serial/ark3116.c465
-rw-r--r--drivers/usb/serial/console.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c7
-rw-r--r--drivers/usb/serial/ftdi_sio.h37
-rw-r--r--drivers/usb/serial/funsoft.c65
-rw-r--r--drivers/usb/serial/generic.c1
-rw-r--r--drivers/usb/serial/omninet.c12
-rw-r--r--drivers/usb/serial/option.c5
-rw-r--r--drivers/usb/serial/pl2303.c2
-rw-r--r--drivers/usb/serial/pl2303.h5
-rw-r--r--drivers/usb/serial/usb-serial.c31
-rw-r--r--drivers/usb/serial/usb-serial.h6
-rw-r--r--drivers/usb/serial/whiteheat.c1
-rw-r--r--drivers/usb/storage/Kconfig3
-rw-r--r--drivers/usb/storage/unusual_devs.h9
-rw-r--r--drivers/video/Kconfig43
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/acornfb.c8
-rw-r--r--drivers/video/asiliantfb.c14
-rw-r--r--drivers/video/aty/aty128fb.c11
-rw-r--r--drivers/video/aty/atyfb_base.c23
-rw-r--r--drivers/video/aty/mach64_gx.c3
-rw-r--r--drivers/video/aty/radeon_base.c8
-rw-r--r--drivers/video/aty/radeon_pm.c4
-rw-r--r--drivers/video/au1100fb.c21
-rw-r--r--drivers/video/au1200fb.c1922
-rw-r--r--drivers/video/au1200fb.h572
-rw-r--r--drivers/video/backlight/Kconfig4
-rw-r--r--drivers/video/backlight/backlight.c98
-rw-r--r--drivers/video/backlight/corgi_bl.c124
-rw-r--r--drivers/video/backlight/hp680_bl.c139
-rw-r--r--drivers/video/backlight/lcd.c32
-rw-r--r--drivers/video/cfbimgblt.c2
-rw-r--r--drivers/video/chipsfb.c14
-rw-r--r--drivers/video/cirrusfb.c4
-rw-r--r--drivers/video/console/Kconfig24
-rw-r--r--drivers/video/console/fbcon.c15
-rw-r--r--drivers/video/console/fonts.c2
-rw-r--r--drivers/video/console/newport_con.c4
-rw-r--r--drivers/video/console/sticore.c22
-rw-r--r--drivers/video/console/vgacon.c271
-rw-r--r--drivers/video/fbcmap.c4
-rw-r--r--drivers/video/fbmem.c52
-rw-r--r--drivers/video/fbmon.c6
-rw-r--r--drivers/video/fbsysfs.c92
-rw-r--r--drivers/video/geode/Kconfig17
-rw-r--r--drivers/video/geode/Makefile4
-rw-r--r--drivers/video/geode/display_gx.c156
-rw-r--r--drivers/video/geode/display_gx.h96
-rw-r--r--drivers/video/geode/gxfb_core.c423
-rw-r--r--drivers/video/geode/video_gx.c262
-rw-r--r--drivers/video/geode/video_gx.h47
-rw-r--r--drivers/video/i810/i810-i2c.c3
-rw-r--r--drivers/video/i810/i810_main.c4
-rw-r--r--drivers/video/imsttfb.c32
-rw-r--r--drivers/video/logo/Makefile2
-rw-r--r--drivers/video/macmodes.c2
-rw-r--r--drivers/video/matrox/g450_pll.c23
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.h2
-rw-r--r--drivers/video/matrox/matroxfb_base.c3
-rw-r--r--drivers/video/matrox/matroxfb_base.h2
-rw-r--r--drivers/video/matrox/matroxfb_g450.c2
-rw-r--r--drivers/video/matrox/matroxfb_maven.c78
-rw-r--r--drivers/video/maxinefb.c4
-rw-r--r--drivers/video/modedb.c6
-rw-r--r--drivers/video/neofb.c8
-rw-r--r--drivers/video/nvidia/nv_accel.c12
-rw-r--r--drivers/video/nvidia/nv_i2c.c3
-rw-r--r--drivers/video/nvidia/nv_type.h1
-rw-r--r--drivers/video/nvidia/nvidia.c124
-rw-r--r--drivers/video/pm2fb.c4
-rw-r--r--drivers/video/pmagb-b-fb.c2
-rw-r--r--drivers/video/pxafb.c8
-rw-r--r--drivers/video/radeonfb.c3167
-rw-r--r--drivers/video/riva/fbdev.c11
-rw-r--r--drivers/video/savage/savagefb-i2c.c3
-rw-r--r--drivers/video/savage/savagefb_driver.c8
-rw-r--r--drivers/video/sis/init301.c11
-rw-r--r--drivers/video/sstfb.c11
-rw-r--r--drivers/video/sticore.h37
-rw-r--r--drivers/video/stifb.c95
-rw-r--r--drivers/video/vesafb.c27
-rw-r--r--drivers/video/virgefb.c3
-rw-r--r--drivers/video/w100fb.c162
-rw-r--r--drivers/video/w100fb.h748
-rw-r--r--fs/9p/fcall.c21
-rw-r--r--fs/9p/mux.c222
-rw-r--r--fs/9p/mux.h4
-rw-r--r--fs/9p/v9fs_vfs.h4
-rw-r--r--fs/9p/vfs_dir.c2
-rw-r--r--fs/9p/vfs_file.c15
-rw-r--r--fs/9p/vfs_inode.c19
-rw-r--r--fs/9p/vfs_super.c13
-rw-r--r--fs/Kconfig9
-rw-r--r--fs/Makefile4
-rw-r--r--fs/adfs/adfs.h4
-rw-r--r--fs/adfs/dir.c2
-rw-r--r--fs/adfs/file.c2
-rw-r--r--fs/affs/affs.h6
-rw-r--r--fs/affs/dir.c2
-rw-r--r--fs/affs/file.c2
-rw-r--r--fs/affs/namei.c3
-rw-r--r--fs/afs/dir.c2
-rw-r--r--fs/afs/internal.h4
-rw-r--r--fs/afs/mntpt.c2
-rw-r--r--fs/afs/proc.c10
-rw-r--r--fs/autofs/autofs_i.h2
-rw-r--r--fs/autofs/dirhash.c2
-rw-r--r--fs/autofs/root.c2
-rw-r--r--fs/autofs4/autofs_i.h57
-rw-r--r--fs/autofs4/expire.c292
-rw-r--r--fs/autofs4/inode.c103
-rw-r--r--fs/autofs4/root.c324
-rw-r--r--fs/autofs4/waitq.c172
-rw-r--r--fs/bad_inode.c2
-rw-r--r--fs/befs/linuxvfs.c2
-rw-r--r--fs/bfs/bfs.h4
-rw-r--r--fs/bfs/dir.c2
-rw-r--r--fs/bfs/file.c2
-rw-r--r--fs/binfmt_flat.c30
-rw-r--r--fs/binfmt_misc.c6
-rw-r--r--fs/bio.c3
-rw-r--r--fs/block_dev.c301
-rw-r--r--fs/buffer.c2
-rw-r--r--fs/char_dev.c93
-rw-r--r--fs/cifs/CHANGES29
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/README15
-rw-r--r--fs/cifs/cifsencrypt.c42
-rw-r--r--fs/cifs/cifsfs.c114
-rw-r--r--fs/cifs/cifsfs.h12
-rw-r--r--fs/cifs/cifsglob.h11
-rw-r--r--fs/cifs/cifspdu.h13
-rw-r--r--fs/cifs/cifsproto.h15
-rw-r--r--fs/cifs/cifssmb.c167
-rw-r--r--fs/cifs/connect.c202
-rw-r--r--fs/cifs/dir.c25
-rw-r--r--fs/cifs/fcntl.c2
-rw-r--r--fs/cifs/file.c134
-rw-r--r--fs/cifs/inode.c28
-rw-r--r--fs/cifs/link.c8
-rw-r--r--fs/cifs/misc.c46
-rw-r--r--fs/cifs/ntlmssp.c143
-rw-r--r--fs/cifs/ntlmssp.h2
-rw-r--r--fs/cifs/readdir.c52
-rw-r--r--fs/cifs/transport.c22
-rw-r--r--fs/cifs/xattr.c8
-rw-r--r--fs/coda/dir.c2
-rw-r--r--fs/coda/file.c2
-rw-r--r--fs/coda/pioctl.c2
-rw-r--r--fs/coda/psdev.c2
-rw-r--r--fs/compat.c214
-rw-r--r--fs/configfs/configfs_internal.h6
-rw-r--r--fs/configfs/dir.c141
-rw-r--r--fs/configfs/file.c2
-rw-r--r--fs/cramfs/inode.c4
-rw-r--r--fs/dcache.c50
-rw-r--r--fs/debugfs/file.c4
-rw-r--r--fs/debugfs/inode.c5
-rw-r--r--fs/devfs/base.c12
-rw-r--r--fs/direct-io.c10
-rw-r--r--fs/dquot.c6
-rw-r--r--fs/efs/dir.c2
-rw-r--r--fs/eventpoll.c6
-rw-r--r--fs/exec.c70
-rw-r--r--fs/exportfs/expfs.c2
-rw-r--r--fs/ext2/dir.c2
-rw-r--r--fs/ext2/ext2.h6
-rw-r--r--fs/ext2/file.c6
-rw-r--r--fs/ext3/dir.c2
-rw-r--r--fs/ext3/file.c4
-rw-r--r--fs/ext3/inode.c13
-rw-r--r--fs/ext3/ioctl.c18
-rw-r--r--fs/ext3/resize.c3
-rw-r--r--fs/fat/dir.c2
-rw-r--r--fs/fat/file.c2
-rw-r--r--fs/fat/inode.c3
-rw-r--r--fs/fcntl.c3
-rw-r--r--fs/fifo.c67
-rw-r--r--fs/file.c2
-rw-r--r--fs/freevxfs/vxfs_extern.h2
-rw-r--r--fs/freevxfs/vxfs_lookup.c2
-rw-r--r--fs/freevxfs/vxfs_olt.c9
-rw-r--r--fs/fuse/dev.c281
-rw-r--r--fs/fuse/dir.c120
-rw-r--r--fs/fuse/file.c72
-rw-r--r--fs/fuse/fuse_i.h66
-rw-r--r--fs/fuse/inode.c138
-rw-r--r--fs/hfs/dir.c2
-rw-r--r--fs/hfs/hfs_fs.h2
-rw-r--r--fs/hfs/inode.c4
-rw-r--r--fs/hfsplus/bnode.c6
-rw-r--r--fs/hfsplus/btree.c3
-rw-r--r--fs/hfsplus/dir.c2
-rw-r--r--fs/hfsplus/inode.c2
-rw-r--r--fs/hostfs/hostfs_kern.c4
-rw-r--r--fs/hostfs/hostfs_user.c1
-rw-r--r--fs/hpfs/dir.c2
-rw-r--r--fs/hpfs/file.c2
-rw-r--r--fs/hpfs/hpfs_fn.h4
-rw-r--r--fs/hppfs/hppfs_kern.c18
-rw-r--r--fs/hugetlbfs/inode.c4
-rw-r--r--fs/inode.c17
-rw-r--r--fs/inotify.c13
-rw-r--r--fs/isofs/dir.c2
-rw-r--r--fs/isofs/isofs.h2
-rw-r--r--fs/jffs/inode-v23.c8
-rw-r--r--fs/jffs2/background.c3
-rw-r--r--fs/jffs2/dir.c2
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jffs2/nodelist.c6
-rw-r--r--fs/jffs2/os-linux.h4
-rw-r--r--fs/jfs/file.c2
-rw-r--r--fs/jfs/jfs_inode.h4
-rw-r--r--fs/jfs/jfs_metapage.c20
-rw-r--r--fs/jfs/namei.c2
-rw-r--r--fs/libfs.c2
-rw-r--r--fs/lockd/svclock.c2
-rw-r--r--fs/locks.c75
-rw-r--r--fs/mbcache.c2
-rw-r--r--fs/minix/dir.c2
-rw-r--r--fs/minix/file.c2
-rw-r--r--fs/minix/minix.h4
-rw-r--r--fs/msdos/namei.c15
-rw-r--r--fs/namei.c61
-rw-r--r--fs/namespace.c8
-rw-r--r--fs/ncpfs/dir.c2
-rw-r--r--fs/ncpfs/file.c2
-rw-r--r--fs/nfs/dir.c7
-rw-r--r--fs/nfs/direct.c8
-rw-r--r--fs/nfs/file.c7
-rw-r--r--fs/nfs/inode.c5
-rw-r--r--fs/nfs/nfs4proc.c10
-rw-r--r--fs/nfsd/auth.c46
-rw-r--r--fs/nfsd/export.c373
-rw-r--r--fs/nfsd/nfs3proc.c2
-rw-r--r--fs/nfsd/nfs4acl.c8
-rw-r--r--fs/nfsd/nfs4callback.c6
-rw-r--r--fs/nfsd/nfs4idmap.c146
-rw-r--r--fs/nfsd/nfs4proc.c4
-rw-r--r--fs/nfsd/nfs4state.c150
-rw-r--r--fs/nfsd/nfs4xdr.c62
-rw-r--r--fs/nfsd/nfsctl.c4
-rw-r--r--fs/nfsd/nfsfh.c2
-rw-r--r--fs/nfsd/nfsproc.c2
-rw-r--r--fs/nfsd/stats.c2
-rw-r--r--fs/nfsd/vfs.c15
-rw-r--r--fs/ntfs/dir.c2
-rw-r--r--fs/ntfs/file.c4
-rw-r--r--fs/ntfs/ntfs.h6
-rw-r--r--fs/ocfs2/aops.c46
-rw-r--r--fs/ocfs2/aops.h4
-rw-r--r--fs/ocfs2/cluster/heartbeat.c40
-rw-r--r--fs/ocfs2/dlm/userdlm.c74
-rw-r--r--fs/ocfs2/dlmglue.c2
-rw-r--r--fs/ocfs2/extent_map.c6
-rw-r--r--fs/ocfs2/file.c109
-rw-r--r--fs/ocfs2/file.h4
-rw-r--r--fs/ocfs2/journal.c8
-rw-r--r--fs/ocfs2/uptodate.c4
-rw-r--r--fs/ocfs2/vote.c6
-rw-r--r--fs/open.c25
-rw-r--r--fs/openpromfs/inode.c6
-rw-r--r--fs/partitions/check.c73
-rw-r--r--fs/partitions/mac.c3
-rw-r--r--fs/pipe.c482
-rw-r--r--fs/proc/base.c34
-rw-r--r--fs/proc/generic.c2
-rw-r--r--fs/proc/internal.h2
-rw-r--r--fs/proc/kcore.c2
-rw-r--r--fs/proc/kmsg.c2
-rw-r--r--fs/proc/proc_devtree.c103
-rw-r--r--fs/proc/proc_misc.c167
-rw-r--r--fs/proc/vmcore.c6
-rw-r--r--fs/qnx4/dir.c2
-rw-r--r--fs/qnx4/file.c2
-rw-r--r--fs/ramfs/file-mmu.c2
-rw-r--r--fs/ramfs/file-nommu.c2
-rw-r--r--fs/ramfs/internal.h2
-rw-r--r--fs/read_write.c4
-rw-r--r--fs/reiserfs/dir.c2
-rw-r--r--fs/reiserfs/file.c4
-rw-r--r--fs/reiserfs/procfs.c2
-rw-r--r--fs/reiserfs/xattr_acl.c5
-rw-r--r--fs/romfs/inode.c2
-rw-r--r--fs/select.c144
-rw-r--r--fs/smbfs/dir.c7
-rw-r--r--fs/smbfs/file.c8
-rw-r--r--fs/smbfs/proto.h4
-rw-r--r--fs/smbfs/request.c4
-rw-r--r--fs/splice.c1490
-rw-r--r--fs/stat.c2
-rw-r--r--fs/sync.c164
-rw-r--r--fs/sysfs/bin.c2
-rw-r--r--fs/sysfs/dir.c5
-rw-r--r--fs/sysfs/file.c80
-rw-r--r--fs/sysfs/inode.c3
-rw-r--r--fs/sysfs/sysfs.h7
-rw-r--r--fs/sysv/dir.c8
-rw-r--r--fs/sysv/file.c2
-rw-r--r--fs/sysv/sysv.h4
-rw-r--r--fs/udf/dir.c2
-rw-r--r--fs/udf/file.c2
-rw-r--r--fs/udf/inode.c6
-rw-r--r--fs/udf/udfdecl.h4
-rw-r--r--fs/ufs/dir.c2
-rw-r--r--fs/ufs/file.c2
-rw-r--r--fs/vfat/namei.c18
-rw-r--r--fs/xfs/linux-2.6/mrlock.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c85
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_export.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c123
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c22
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c124
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.h11
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c11
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h12
-rw-r--r--fs/xfs/quota/xfs_dquot_item.c2
-rw-r--r--fs/xfs/quota/xfs_qm.c31
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c2
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c70
-rw-r--r--fs/xfs/xfs_acl.c2
-rw-r--r--fs/xfs/xfs_ag.h2
-rw-r--r--fs/xfs/xfs_alloc.c11
-rw-r--r--fs/xfs/xfs_alloc.h2
-rw-r--r--fs/xfs/xfs_attr.c6
-rw-r--r--fs/xfs/xfs_attr_leaf.c4
-rw-r--r--fs/xfs/xfs_behavior.c4
-rw-r--r--fs/xfs/xfs_behavior.h4
-rw-r--r--fs/xfs/xfs_bmap.c118
-rw-r--r--fs/xfs/xfs_bmap.h17
-rw-r--r--fs/xfs/xfs_buf_item.c4
-rw-r--r--fs/xfs/xfs_cap.h2
-rw-r--r--fs/xfs/xfs_clnt.h1
-rw-r--r--fs/xfs/xfs_da_btree.c2
-rw-r--r--fs/xfs/xfs_dir2_block.c2
-rw-r--r--fs/xfs/xfs_dir2_leaf.c2
-rw-r--r--fs/xfs/xfs_dir2_node.c2
-rw-r--r--fs/xfs/xfs_dir_leaf.c2
-rw-r--r--fs/xfs/xfs_error.h3
-rw-r--r--fs/xfs/xfs_fsops.c2
-rw-r--r--fs/xfs/xfs_ialloc.c111
-rw-r--r--fs/xfs/xfs_iget.c31
-rw-r--r--fs/xfs/xfs_inode.c41
-rw-r--r--fs/xfs/xfs_inode.h1
-rw-r--r--fs/xfs/xfs_inode_item.c2
-rw-r--r--fs/xfs/xfs_itable.c4
-rw-r--r--fs/xfs/xfs_itable.h2
-rw-r--r--fs/xfs/xfs_log.c22
-rw-r--r--fs/xfs/xfs_log.h2
-rw-r--r--fs/xfs/xfs_log_recover.c4
-rw-r--r--fs/xfs/xfs_mount.c77
-rw-r--r--fs/xfs/xfs_mount.h7
-rw-r--r--fs/xfs/xfs_quota.h9
-rw-r--r--fs/xfs/xfs_rename.c12
-rw-r--r--fs/xfs/xfs_trans.c6
-rw-r--r--fs/xfs/xfs_trans.h2
-rw-r--r--fs/xfs/xfs_trans_inode.c2
-rw-r--r--fs/xfs/xfs_vfsops.c47
-rw-r--r--fs/xfs/xfs_vnodeops.c18
-rw-r--r--include/acpi/acconfig.h18
-rw-r--r--include/acpi/acdisasm.h173
-rw-r--r--include/acpi/acdispat.h6
-rw-r--r--include/acpi/acevents.h4
-rw-r--r--include/acpi/acexcep.h6
-rw-r--r--include/acpi/acglobal.h29
-rw-r--r--include/acpi/aclocal.h284
-rw-r--r--include/acpi/acmacros.h81
-rw-r--r--include/acpi/acnamesp.h28
-rw-r--r--include/acpi/acobject.h188
-rw-r--r--include/acpi/acopcode.h2
-rw-r--r--include/acpi/acoutput.h10
-rw-r--r--include/acpi/acparser.h4
-rw-r--r--include/acpi/acpi_bus.h2
-rw-r--r--include/acpi/acpiosxf.h35
-rw-r--r--include/acpi/acpixf.h4
-rw-r--r--include/acpi/acresrc.h20
-rw-r--r--include/acpi/acstruct.h121
-rw-r--r--include/acpi/actables.h6
-rw-r--r--include/acpi/actbl.h400
-rw-r--r--include/acpi/actbl1.h639
-rw-r--r--include/acpi/actbl2.h230
-rw-r--r--include/acpi/actypes.h88
-rw-r--r--include/acpi/acutils.h95
-rw-r--r--include/acpi/amlcode.h6
-rw-r--r--include/acpi/amlresrc.h85
-rw-r--r--include/acpi/platform/acenv.h47
-rw-r--r--include/acpi/platform/aclinux.h23
-rw-r--r--include/asm-alpha/mmzone.h19
-rw-r--r--include/asm-alpha/numnodes.h7
-rw-r--r--include/asm-alpha/page.h4
-rw-r--r--include/asm-alpha/poll.h4
-rw-r--r--include/asm-alpha/smp.h4
-rw-r--r--include/asm-alpha/termbits.h1
-rw-r--r--include/asm-arm/arch-aaec2000/debug-macro.S1
-rw-r--r--include/asm-arm/arch-aaec2000/entry-macro.S1
-rw-r--r--include/asm-arm/arch-aaec2000/uncompress.h23
-rw-r--r--include/asm-arm/arch-at91rm9200/at91rm9200_mci.h104
-rw-r--r--include/asm-arm/arch-at91rm9200/board.h24
-rw-r--r--include/asm-arm/arch-at91rm9200/hardware.h3
-rw-r--r--include/asm-arm/arch-at91rm9200/uncompress.h23
-rw-r--r--include/asm-arm/arch-cl7500/hardware.h4
-rw-r--r--include/asm-arm/arch-cl7500/memory.h6
-rw-r--r--include/asm-arm/arch-cl7500/uncompress.h18
-rw-r--r--include/asm-arm/arch-clps711x/uncompress.h21
-rw-r--r--include/asm-arm/arch-ebsa110/debug-macro.S2
-rw-r--r--include/asm-arm/arch-ebsa110/hardware.h3
-rw-r--r--include/asm-arm/arch-ebsa110/memory.h6
-rw-r--r--include/asm-arm/arch-ebsa110/uncompress.h47
-rw-r--r--include/asm-arm/arch-ebsa285/hardware.h7
-rw-r--r--include/asm-arm/arch-ebsa285/memory.h12
-rw-r--r--include/asm-arm/arch-ebsa285/uncompress.h16
-rw-r--r--include/asm-arm/arch-ep93xx/ts72xx.h11
-rw-r--r--include/asm-arm/arch-ep93xx/uncompress.h50
-rw-r--r--include/asm-arm/arch-h720x/uncompress.h24
-rw-r--r--include/asm-arm/arch-imx/debug-macro.S2
-rw-r--r--include/asm-arm/arch-imx/dma.h17
-rw-r--r--include/asm-arm/arch-imx/imx-dma.h90
-rw-r--r--include/asm-arm/arch-imx/imx-uart.h10
-rw-r--r--include/asm-arm/arch-imx/mmc.h12
-rw-r--r--include/asm-arm/arch-imx/uncompress.h21
-rw-r--r--include/asm-arm/arch-integrator/uncompress.h21
-rw-r--r--include/asm-arm/arch-iop3xx/uncompress.h16
-rw-r--r--include/asm-arm/arch-ixp2000/uncompress.h15
-rw-r--r--include/asm-arm/arch-ixp23xx/debug-macro.S26
-rw-r--r--include/asm-arm/arch-ixp23xx/dma.h3
-rw-r--r--include/asm-arm/arch-ixp23xx/entry-macro.S31
-rw-r--r--include/asm-arm/arch-ixp23xx/hardware.h37
-rw-r--r--include/asm-arm/arch-ixp23xx/io.h54
-rw-r--r--include/asm-arm/arch-ixp23xx/irqs.h223
-rw-r--r--include/asm-arm/arch-ixp23xx/ixdp2351.h89
-rw-r--r--include/asm-arm/arch-ixp23xx/ixp23xx.h306
-rw-r--r--include/asm-arm/arch-ixp23xx/memory.h63
-rw-r--r--include/asm-arm/arch-ixp23xx/platform.h32
-rw-r--r--include/asm-arm/arch-ixp23xx/system.h33
-rw-r--r--include/asm-arm/arch-ixp23xx/time.h3
-rw-r--r--include/asm-arm/arch-ixp23xx/timex.h7
-rw-r--r--include/asm-arm/arch-ixp23xx/uncompress.h40
-rw-r--r--include/asm-arm/arch-ixp23xx/vmalloc.h10
-rw-r--r--include/asm-arm/arch-ixp4xx/io.h7
-rw-r--r--include/asm-arm/arch-ixp4xx/memory.h2
-rw-r--r--include/asm-arm/arch-ixp4xx/uncompress.h18
-rw-r--r--include/asm-arm/arch-l7200/hardware.h3
-rw-r--r--include/asm-arm/arch-l7200/memory.h6
-rw-r--r--include/asm-arm/arch-l7200/serial_l7200.h2
-rw-r--r--include/asm-arm/arch-l7200/uncompress.h17
-rw-r--r--include/asm-arm/arch-lh7a40x/memory.h2
-rw-r--r--include/asm-arm/arch-lh7a40x/uncompress.h11
-rw-r--r--include/asm-arm/arch-omap/aic23.h4
-rw-r--r--include/asm-arm/arch-omap/board-ams-delta.h65
-rw-r--r--include/asm-arm/arch-omap/board-apollon.h45
-rw-r--r--include/asm-arm/arch-omap/board-h2.h4
-rw-r--r--include/asm-arm/arch-omap/board-h3.h4
-rw-r--r--include/asm-arm/arch-omap/board-h4.h8
-rw-r--r--include/asm-arm/arch-omap/board-netstar.h19
-rw-r--r--include/asm-arm/arch-omap/board-nokia.h54
-rw-r--r--include/asm-arm/arch-omap/board-perseus2.h4
-rw-r--r--include/asm-arm/arch-omap/board.h30
-rw-r--r--include/asm-arm/arch-omap/clock.h13
-rw-r--r--include/asm-arm/arch-omap/dma.h1
-rw-r--r--include/asm-arm/arch-omap/dmtimer.h1
-rw-r--r--include/asm-arm/arch-omap/dsp.h6
-rw-r--r--include/asm-arm/arch-omap/dsp_common.h13
-rw-r--r--include/asm-arm/arch-omap/gpioexpander.h24
-rw-r--r--include/asm-arm/arch-omap/hardware.h8
-rw-r--r--include/asm-arm/arch-omap/irda.h36
-rw-r--r--include/asm-arm/arch-omap/irqs.h5
-rw-r--r--include/asm-arm/arch-omap/keypad.h36
-rw-r--r--include/asm-arm/arch-omap/lcd_lph8923.h14
-rw-r--r--include/asm-arm/arch-omap/mcbsp.h65
-rw-r--r--include/asm-arm/arch-omap/mcspi.h16
-rw-r--r--include/asm-arm/arch-omap/menelaus.h2
-rw-r--r--include/asm-arm/arch-omap/mux.h54
-rw-r--r--include/asm-arm/arch-omap/omap-alsa.h124
-rw-r--r--include/asm-arm/arch-omap/omapfb.h98
-rw-r--r--include/asm-arm/arch-omap/param.h8
-rw-r--r--include/asm-arm/arch-omap/pm.h81
-rw-r--r--include/asm-arm/arch-omap/prcm.h404
-rw-r--r--include/asm-arm/arch-omap/sram.h2
-rw-r--r--include/asm-arm/arch-omap/system.h17
-rw-r--r--include/asm-arm/arch-omap/uncompress.h20
-rw-r--r--include/asm-arm/arch-pxa/dma.h26
-rw-r--r--include/asm-arm/arch-pxa/irqs.h6
-rw-r--r--include/asm-arm/arch-pxa/lpd270.h38
-rw-r--r--include/asm-arm/arch-pxa/ohci.h2
-rw-r--r--include/asm-arm/arch-pxa/pxa-regs.h2
-rw-r--r--include/asm-arm/arch-pxa/pxa2xx_spi.h71
-rw-r--r--include/asm-arm/arch-pxa/sharpsl.h2
-rw-r--r--include/asm-arm/arch-pxa/uncompress.h13
-rw-r--r--include/asm-arm/arch-realview/uncompress.h20
-rw-r--r--include/asm-arm/arch-rpc/hardware.h3
-rw-r--r--include/asm-arm/arch-rpc/memory.h6
-rw-r--r--include/asm-arm/arch-rpc/uncompress.h27
-rw-r--r--include/asm-arm/arch-s3c2410/entry-macro.S167
-rw-r--r--include/asm-arm/arch-s3c2410/leds-gpio.h28
-rw-r--r--include/asm-arm/arch-s3c2410/spi-gpio.h31
-rw-r--r--include/asm-arm/arch-s3c2410/spi.h29
-rw-r--r--include/asm-arm/arch-s3c2410/uncompress.h15
-rw-r--r--include/asm-arm/arch-sa1100/hardware.h4
-rw-r--r--include/asm-arm/arch-sa1100/memory.h7
-rw-r--r--include/asm-arm/arch-sa1100/uncompress.h21
-rw-r--r--include/asm-arm/arch-shark/hardware.h6
-rw-r--r--include/asm-arm/arch-shark/memory.h6
-rw-r--r--include/asm-arm/arch-shark/uncompress.h13
-rw-r--r--include/asm-arm/arch-versatile/uncompress.h20
-rw-r--r--include/asm-arm/bug.h1
-rw-r--r--include/asm-arm/cacheflush.h8
-rw-r--r--include/asm-arm/dma-mapping.h22
-rw-r--r--include/asm-arm/domain.h18
-rw-r--r--include/asm-arm/fpstate.h2
-rw-r--r--include/asm-arm/memory.h25
-rw-r--r--include/asm-arm/numnodes.h26
-rw-r--r--include/asm-arm/page.h9
-rw-r--r--include/asm-arm/pgtable-hwdef.h1
-rw-r--r--include/asm-arm/pgtable.h1
-rw-r--r--include/asm-arm/proc-fns.h8
-rw-r--r--include/asm-arm/procinfo.h2
-rw-r--r--include/asm-arm/rtc.h3
-rw-r--r--include/asm-arm/spinlock.h6
-rw-r--r--include/asm-arm/system.h25
-rw-r--r--include/asm-arm/unistd.h50
-rw-r--r--include/asm-arm/vfpmacros.h8
-rw-r--r--include/asm-arm26/memory.h4
-rw-r--r--include/asm-cris/page.h4
-rw-r--r--include/asm-cris/system.h1
-rw-r--r--include/asm-cris/unistd.h2
-rw-r--r--include/asm-frv/futex.h6
-rw-r--r--include/asm-frv/page.h7
-rw-r--r--include/asm-frv/system.h2
-rw-r--r--include/asm-frv/unistd.h2
-rw-r--r--include/asm-generic/futex.h6
-rw-r--r--include/asm-generic/local.h91
-rw-r--r--include/asm-generic/memory_model.h77
-rw-r--r--include/asm-generic/mutex-dec.h30
-rw-r--r--include/asm-generic/mutex-xchg.h33
-rw-r--r--include/asm-generic/percpu.h2
-rw-r--r--include/asm-generic/pgtable.h11
-rw-r--r--include/asm-h8300/page.h4
-rw-r--r--include/asm-h8300/system.h2
-rw-r--r--include/asm-h8300/unistd.h2
-rw-r--r--include/asm-i386/apic.h2
-rw-r--r--include/asm-i386/apicdef.h2
-rw-r--r--include/asm-i386/atomic.h5
-rw-r--r--include/asm-i386/cpufeature.h1
-rw-r--r--include/asm-i386/e820.h4
-rw-r--r--include/asm-i386/floppy.h34
-rw-r--r--include/asm-i386/futex.h27
-rw-r--r--include/asm-i386/hpet.h1
-rw-r--r--include/asm-i386/i387.h30
-rw-r--r--include/asm-i386/io_apic.h1
-rw-r--r--include/asm-i386/kdebug.h10
-rw-r--r--include/asm-i386/local.h6
-rw-r--r--include/asm-i386/mach-default/mach_time.h37
-rw-r--r--include/asm-i386/mmzone.h17
-rw-r--r--include/asm-i386/mpspec.h1
-rw-r--r--include/asm-i386/numnodes.h18
-rw-r--r--include/asm-i386/page.h3
-rw-r--r--include/asm-i386/pgtable-2level.h3
-rw-r--r--include/asm-i386/pgtable-3level.h20
-rw-r--r--include/asm-i386/pgtable.h4
-rw-r--r--include/asm-i386/processor.h7
-rw-r--r--include/asm-i386/setup.h4
-rw-r--r--include/asm-i386/topology.h2
-rw-r--r--include/asm-i386/unistd.h10
-rw-r--r--include/asm-ia64/acpi-ext.h11
-rw-r--r--include/asm-ia64/acpi.h5
-rw-r--r--include/asm-ia64/asmmacro.h4
-rw-r--r--include/asm-ia64/bitops.h1
-rw-r--r--include/asm-ia64/compat.h6
-rw-r--r--include/asm-ia64/kdebug.h6
-rw-r--r--include/asm-ia64/machvec.h2
-rw-r--r--include/asm-ia64/mca.h5
-rw-r--r--include/asm-ia64/mutex.h2
-rw-r--r--include/asm-ia64/numnodes.h20
-rw-r--r--include/asm-ia64/page.h18
-rw-r--r--include/asm-ia64/pal.h34
-rw-r--r--include/asm-ia64/sn/sn2/sn_hwperf.h6
-rw-r--r--include/asm-ia64/sn/sn_sal.h17
-rw-r--r--include/asm-ia64/thread_info.h2
-rw-r--r--include/asm-ia64/topology.h5
-rw-r--r--include/asm-ia64/unistd.h8
-rw-r--r--include/asm-ia64/vga.h2
-rw-r--r--include/asm-m32r/assembler.h5
-rw-r--r--include/asm-m32r/mappi3/mappi3_pld.h22
-rw-r--r--include/asm-m32r/mmzone.h14
-rw-r--r--include/asm-m32r/numnodes.h15
-rw-r--r--include/asm-m32r/page.h5
-rw-r--r--include/asm-m32r/ptrace.h25
-rw-r--r--include/asm-m32r/semaphore.h64
-rw-r--r--include/asm-m32r/setup.h4
-rw-r--r--include/asm-m32r/sigcontext.h2
-rw-r--r--include/asm-m32r/smp.h3
-rw-r--r--include/asm-m32r/system.h71
-rw-r--r--include/asm-m32r/uaccess.h266
-rw-r--r--include/asm-m32r/unistd.h2
-rw-r--r--include/asm-mips/addrspace.h1
-rw-r--r--include/asm-mips/asmmacro.h47
-rw-r--r--include/asm-mips/bitops.h56
-rw-r--r--include/asm-mips/cacheflush.h1
-rw-r--r--include/asm-mips/compat.h5
-rw-r--r--include/asm-mips/cpu-features.h2
-rw-r--r--include/asm-mips/cpu-info.h10
-rw-r--r--include/asm-mips/cpu.h6
-rw-r--r--include/asm-mips/delay.h22
-rw-r--r--include/asm-mips/ds1742.h13
-rw-r--r--include/asm-mips/elf.h45
-rw-r--r--include/asm-mips/fpu.h4
-rw-r--r--include/asm-mips/futex.h145
-rw-r--r--include/asm-mips/hazards.h2
-rw-r--r--include/asm-mips/inst.h33
-rw-r--r--include/asm-mips/interrupt.h65
-rw-r--r--include/asm-mips/irq.h30
-rw-r--r--include/asm-mips/kspd.h36
-rw-r--r--include/asm-mips/mach-generic/ide.h46
-rw-r--r--include/asm-mips/mach-jmr3927/ds1742.h4
-rw-r--r--include/asm-mips/mach-mips/param.h13
-rw-r--r--include/asm-mips/marvell.h2
-rw-r--r--include/asm-mips/mc146818-time.h33
-rw-r--r--include/asm-mips/mips-boards/atlas.h18
-rw-r--r--include/asm-mips/mips-boards/atlasint.h19
-rw-r--r--include/asm-mips/mips-boards/generic.h1
-rw-r--r--include/asm-mips/mips_mt.h15
-rw-r--r--include/asm-mips/mipsmtregs.h16
-rw-r--r--include/asm-mips/mipsregs.h138
-rw-r--r--include/asm-mips/mmu_context.h112
-rw-r--r--include/asm-mips/mmzone.h14
-rw-r--r--include/asm-mips/numnodes.h7
-rw-r--r--include/asm-mips/page.h5
-rw-r--r--include/asm-mips/pgtable-32.h61
-rw-r--r--include/asm-mips/pgtable-64.h13
-rw-r--r--include/asm-mips/pgtable.h103
-rw-r--r--include/asm-mips/processor.h22
-rw-r--r--include/asm-mips/ptrace.h4
-rw-r--r--include/asm-mips/r4kcache.h130
-rw-r--r--include/asm-mips/rtc.h4
-rw-r--r--include/asm-mips/rtlx.h38
-rw-r--r--include/asm-mips/serial.h97
-rw-r--r--include/asm-mips/sigcontext.h10
-rw-r--r--include/asm-mips/smp.h5
-rw-r--r--include/asm-mips/smtc.h55
-rw-r--r--include/asm-mips/smtc_ipi.h118
-rw-r--r--include/asm-mips/smtc_proc.h23
-rw-r--r--include/asm-mips/sparsemem.h14
-rw-r--r--include/asm-mips/stackframe.h187
-rw-r--r--include/asm-mips/system.h34
-rw-r--r--include/asm-mips/time.h12
-rw-r--r--include/asm-mips/unistd.h18
-rw-r--r--include/asm-mips/vpe.h37
-rw-r--r--include/asm-parisc/atomic.h3
-rw-r--r--include/asm-parisc/cache.h2
-rw-r--r--include/asm-parisc/cacheflush.h17
-rw-r--r--include/asm-parisc/compat.h5
-rw-r--r--include/asm-parisc/io.h112
-rw-r--r--include/asm-parisc/local.h16
-rw-r--r--include/asm-parisc/mmzone.h17
-rw-r--r--include/asm-parisc/numnodes.h7
-rw-r--r--include/asm-parisc/page.h86
-rw-r--r--include/asm-parisc/pci.h5
-rw-r--r--include/asm-parisc/pdc.h2
-rw-r--r--include/asm-parisc/pdc_chassis.h5
-rw-r--r--include/asm-parisc/pgtable.h63
-rw-r--r--include/asm-parisc/spinlock.h16
-rw-r--r--include/asm-parisc/thread_info.h3
-rw-r--r--include/asm-parisc/unistd.h8
-rw-r--r--include/asm-powerpc/bug.h36
-rw-r--r--include/asm-powerpc/cputable.h305
-rw-r--r--include/asm-powerpc/eeh.h20
-rw-r--r--include/asm-powerpc/firmware.h10
-rw-r--r--include/asm-powerpc/floppy.h5
-rw-r--r--include/asm-powerpc/futex.h6
-rw-r--r--include/asm-powerpc/hvcall.h184
-rw-r--r--include/asm-powerpc/hvconsole.h26
-rw-r--r--include/asm-powerpc/io.h6
-rw-r--r--include/asm-powerpc/iommu.h7
-rw-r--r--include/asm-powerpc/irq.h7
-rw-r--r--include/asm-powerpc/kdebug.h12
-rw-r--r--include/asm-powerpc/machdep.h47
-rw-r--r--include/asm-powerpc/numnodes.h9
-rw-r--r--include/asm-powerpc/oprofile_impl.h17
-rw-r--r--include/asm-powerpc/paca.h2
-rw-r--r--include/asm-powerpc/page.h3
-rw-r--r--include/asm-powerpc/page_64.h1
-rw-r--r--include/asm-powerpc/percpu.h2
-rw-r--r--include/asm-powerpc/pgalloc.h2
-rw-r--r--include/asm-powerpc/pmac_feature.h2
-rw-r--r--include/asm-powerpc/processor.h43
-rw-r--r--include/asm-powerpc/prom.h14
-rw-r--r--include/asm-powerpc/reg.h4
-rw-r--r--include/asm-powerpc/smp.h2
-rw-r--r--include/asm-powerpc/spu.h12
-rw-r--r--include/asm-powerpc/syscalls.h58
-rw-r--r--include/asm-powerpc/system.h5
-rw-r--r--include/asm-powerpc/termbits.h1
-rw-r--r--include/asm-powerpc/thread_info.h8
-rw-r--r--include/asm-powerpc/topology.h24
-rw-r--r--include/asm-powerpc/uaccess.h19
-rw-r--r--include/asm-powerpc/unistd.h60
-rw-r--r--include/asm-powerpc/vdso_datapage.h3
-rw-r--r--include/asm-ppc/commproc.h1
-rw-r--r--include/asm-ppc/cpm2.h2
-rw-r--r--include/asm-ppc/machdep.h17
-rw-r--r--include/asm-ppc/mpc52xx.h4
-rw-r--r--include/asm-ppc/page.h5
-rw-r--r--include/asm-ppc/pgtable.h3
-rw-r--r--include/asm-ppc/ppc_sys.h2
-rw-r--r--include/asm-ppc/prom.h156
-rw-r--r--include/asm-ppc/reg_booke.h1
-rw-r--r--include/asm-ppc/serial.h7
-rw-r--r--include/asm-s390/atomic.h2
-rw-r--r--include/asm-s390/cache.h2
-rw-r--r--include/asm-s390/compat.h5
-rw-r--r--include/asm-s390/ebcdic.h12
-rw-r--r--include/asm-s390/futex.h124
-rw-r--r--include/asm-s390/lowcore.h4
-rw-r--r--include/asm-s390/page.h3
-rw-r--r--include/asm-s390/percpu.h2
-rw-r--r--include/asm-s390/unistd.h8
-rw-r--r--include/asm-sh/addrspace.h2
-rw-r--r--include/asm-sh/numnodes.h7
-rw-r--r--include/asm-sh/page.h5
-rw-r--r--include/asm-sh/unistd.h2
-rw-r--r--include/asm-sh64/page.h5
-rw-r--r--include/asm-sh64/platform.h5
-rw-r--r--include/asm-sh64/unistd.h2
-rw-r--r--include/asm-sparc/page.h4
-rw-r--r--include/asm-sparc/unistd.h18
-rw-r--r--include/asm-sparc/vga.h33
-rw-r--r--include/asm-sparc64/dma-mapping.h141
-rw-r--r--include/asm-sparc64/floppy.h2
-rw-r--r--include/asm-sparc64/futex.h24
-rw-r--r--include/asm-sparc64/kdebug.h11
-rw-r--r--include/asm-sparc64/page.h2
-rw-r--r--include/asm-sparc64/pci.h4
-rw-r--r--include/asm-sparc64/percpu.h2
-rw-r--r--include/asm-sparc64/pgtable.h17
-rw-r--r--include/asm-sparc64/tlbflush.h2
-rw-r--r--include/asm-sparc64/unistd.h16
-rw-r--r--include/asm-um/desc.h12
-rw-r--r--include/asm-um/host_ldt-i386.h34
-rw-r--r--include/asm-um/host_ldt-x86_64.h (renamed from include/asm-um/ldt-x86_64.h)39
-rw-r--r--include/asm-um/irqflags.h6
-rw-r--r--include/asm-um/ldt-i386.h69
-rw-r--r--include/asm-um/ldt.h41
-rw-r--r--include/asm-um/page.h4
-rw-r--r--include/asm-um/processor-i386.h35
-rw-r--r--include/asm-um/processor-x86_64.h9
-rw-r--r--include/asm-um/ptrace-generic.h16
-rw-r--r--include/asm-um/ptrace-i386.h44
-rw-r--r--include/asm-um/ptrace-x86_64.h35
-rw-r--r--include/asm-um/segment.h6
-rw-r--r--include/asm-um/thread_info.h16
-rw-r--r--include/asm-um/uaccess.h35
-rw-r--r--include/asm-v850/page.h4
-rw-r--r--include/asm-v850/system.h2
-rw-r--r--include/asm-x86_64/apicdef.h2
-rw-r--r--include/asm-x86_64/cache.h4
-rw-r--r--include/asm-x86_64/cpufeature.h1
-rw-r--r--include/asm-x86_64/e820.h5
-rw-r--r--include/asm-x86_64/elf.h2
-rw-r--r--include/asm-x86_64/futex.h27
-rw-r--r--include/asm-x86_64/hpet.h2
-rw-r--r--include/asm-x86_64/i387.h20
-rw-r--r--include/asm-x86_64/ia32_unistd.h2
-rw-r--r--include/asm-x86_64/io.h2
-rw-r--r--include/asm-x86_64/io_apic.h1
-rw-r--r--include/asm-x86_64/kdebug.h23
-rw-r--r--include/asm-x86_64/local.h10
-rw-r--r--include/asm-x86_64/mce.h7
-rw-r--r--include/asm-x86_64/mmzone.h7
-rw-r--r--include/asm-x86_64/numa.h3
-rw-r--r--include/asm-x86_64/numnodes.h12
-rw-r--r--include/asm-x86_64/page.h3
-rw-r--r--include/asm-x86_64/percpu.h2
-rw-r--r--include/asm-x86_64/processor.h7
-rw-r--r--include/asm-x86_64/smp.h1
-rw-r--r--include/asm-x86_64/timex.h2
-rw-r--r--include/asm-x86_64/topology.h2
-rw-r--r--include/asm-x86_64/unistd.h16
-rw-r--r--include/asm-xtensa/ioctls.h2
-rw-r--r--include/asm-xtensa/page.h6
-rw-r--r--include/asm-xtensa/signal.h2
-rw-r--r--include/asm-xtensa/system.h2
-rw-r--r--include/linux/adb.h2
-rw-r--r--include/linux/amba/serial.h6
-rw-r--r--include/linux/audit.h22
-rw-r--r--include/linux/auto_fs4.h51
-rw-r--r--include/linux/backlight.h25
-rw-r--r--include/linux/blkdev.h26
-rw-r--r--include/linux/bootmem.h2
-rw-r--r--include/linux/cdev.h4
-rw-r--r--include/linux/coda_linux.h6
-rw-r--r--include/linux/compat.h18
-rw-r--r--include/linux/compat_ioctl.h2
-rw-r--r--include/linux/cpumask.h5
-rw-r--r--include/linux/crash_dump.h2
-rw-r--r--include/linux/dcache.h1
-rw-r--r--include/linux/debugfs.h7
-rw-r--r--include/linux/device-mapper.h1
-rw-r--r--include/linux/device.h2
-rw-r--r--include/linux/dm-ioctl.h17
-rw-r--r--include/linux/dma-mapping.h2
-rw-r--r--include/linux/efs_fs.h2
-rw-r--r--include/linux/elevator.h2
-rw-r--r--include/linux/ext3_fs.h4
-rw-r--r--include/linux/fadvise.h6
-rw-r--r--include/linux/fb.h4
-rw-r--r--include/linux/firmware.h1
-rw-r--r--include/linux/fs.h74
-rw-r--r--include/linux/fs_uart_pd.h60
-rw-r--r--include/linux/fsl_devices.h11
-rw-r--r--include/linux/futex.h89
-rw-r--r--include/linux/gameport.h7
-rw-r--r--include/linux/genhd.h20
-rw-r--r--include/linux/gfp.h2
-rw-r--r--include/linux/hrtimer.h18
-rw-r--r--include/linux/hugetlb.h2
-rw-r--r--include/linux/i2c-id.h4
-rw-r--r--include/linux/i2o.h5
-rw-r--r--include/linux/ide.h1
-rw-r--r--include/linux/init.h3
-rw-r--r--include/linux/init_task.h2
-rw-r--r--include/linux/input.h129
-rw-r--r--include/linux/ipmi_smi.h16
-rw-r--r--include/linux/jiffies.h6
-rw-r--r--include/linux/kbd_kern.h2
-rw-r--r--include/linux/kernel.h5
-rw-r--r--include/linux/kernel_stat.h2
-rw-r--r--include/linux/keyboard.h13
-rw-r--r--include/linux/kobject.h5
-rw-r--r--include/linux/leds.h110
-rw-r--r--include/linux/libata.h11
-rw-r--r--include/linux/libps2.h2
-rw-r--r--include/linux/list.h2
-rw-r--r--include/linux/m48t86.h16
-rw-r--r--include/linux/memory.h1
-rw-r--r--include/linux/memory_hotplug.h11
-rw-r--r--include/linux/mempolicy.h1
-rw-r--r--include/linux/migrate.h5
-rw-r--r--include/linux/miscdevice.h2
-rw-r--r--include/linux/mm.h5
-rw-r--r--include/linux/mmc/card.h1
-rw-r--r--include/linux/mmc/mmc.h1
-rw-r--r--include/linux/mmzone.h93
-rw-r--r--include/linux/mod_devicetable.h48
-rw-r--r--include/linux/msdos_fs.h7
-rw-r--r--include/linux/mtd/blktrans.h4
-rw-r--r--include/linux/mtd/doc2000.h4
-rw-r--r--include/linux/mtd/inftl.h5
-rw-r--r--include/linux/mv643xx.h2
-rw-r--r--include/linux/namei.h1
-rw-r--r--include/linux/ncp_fs.h4
-rw-r--r--include/linux/netdevice.h60
-rw-r--r--include/linux/netfilter.h42
-rw-r--r--include/linux/netfilter/x_tables.h79
-rw-r--r--include/linux/netfilter/xt_esp.h14
-rw-r--r--include/linux/netfilter/xt_multiport.h30
-rw-r--r--include/linux/netfilter_ipv4.h2
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack.h17
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_h323.h52
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h (renamed from net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h)2
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h (renamed from net/ipv4/netfilter/ip_conntrack_helper_h323_types.h)0
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h18
-rw-r--r--include/linux/netfilter_ipv4/ipt_esp.h14
-rw-r--r--include/linux/netfilter_ipv4/ipt_multiport.h31
-rw-r--r--include/linux/netfilter_ipv6.h3
-rw-r--r--include/linux/netfilter_ipv6/ip6t_esp.h12
-rw-r--r--include/linux/netfilter_ipv6/ip6t_multiport.h25
-rw-r--r--include/linux/netlink.h1
-rw-r--r--include/linux/nfs_fs.h4
-rw-r--r--include/linux/nfsd/export.h29
-rw-r--r--include/linux/nodemask.h4
-rw-r--r--include/linux/notifier.h96
-rw-r--r--include/linux/numa.h8
-rw-r--r--include/linux/oprofile.h14
-rw-r--r--include/linux/page-flags.h24
-rw-r--r--include/linux/pagemap.h6
-rw-r--r--include/linux/pci-acpi.h2
-rw-r--r--include/linux/pci.h33
-rw-r--r--include/linux/pci_ids.h11
-rw-r--r--include/linux/pfn.h9
-rw-r--r--include/linux/pid.h98
-rw-r--r--include/linux/pipe_fs_i.h77
-rw-r--r--include/linux/pm.h8
-rw-r--r--include/linux/pm_legacy.h7
-rw-r--r--include/linux/poll.h17
-rw-r--r--include/linux/proc_fs.h12
-rw-r--r--include/linux/qnx4_fs.h4
-rw-r--r--include/linux/raid/md.h3
-rw-r--r--include/linux/raid/md_k.h21
-rw-r--r--include/linux/raid/md_p.h32
-rw-r--r--include/linux/raid/raid5.h25
-rw-r--r--include/linux/ramfs.h2
-rw-r--r--include/linux/rcupdate.h1
-rw-r--r--include/linux/reiserfs_fs.h4
-rw-r--r--include/linux/relayfs_fs.h287
-rw-r--r--include/linux/rtc.h92
-rw-r--r--include/linux/sched.h86
-rw-r--r--include/linux/screen_info.h3
-rw-r--r--include/linux/sdla_asy.h226
-rw-r--r--include/linux/sdla_chdlc.h813
-rw-r--r--include/linux/sdla_ppp.h575
-rw-r--r--include/linux/sdla_x25.h772
-rw-r--r--include/linux/sdladrv.h66
-rw-r--r--include/linux/sdlapci.h72
-rw-r--r--include/linux/sdlasfm.h104
-rw-r--r--include/linux/security.h16
-rw-r--r--include/linux/selinux.h177
-rw-r--r--include/linux/seqlock.h4
-rw-r--r--include/linux/serial_core.h1
-rw-r--r--include/linux/serio.h9
-rw-r--r--include/linux/signal.h6
-rw-r--r--include/linux/skbuff.h36
-rw-r--r--include/linux/slab.h2
-rw-r--r--include/linux/sound.h12
-rw-r--r--include/linux/spi/ads7846.h7
-rw-r--r--include/linux/spi/spi.h45
-rw-r--r--include/linux/spi/spi_bitbang.h8
-rw-r--r--include/linux/string.h17
-rw-r--r--include/linux/sunrpc/cache.h145
-rw-r--r--include/linux/sunrpc/metrics.h12
-rw-r--r--include/linux/sunrpc/stats.h4
-rw-r--r--include/linux/sunrpc/svc.h9
-rw-r--r--include/linux/sunrpc/svcauth.h12
-rw-r--r--include/linux/sunrpc/xprt.h1
-rw-r--r--include/linux/swap.h3
-rw-r--r--include/linux/synclink.h11
-rw-r--r--include/linux/syscalls.h18
-rw-r--r--include/linux/sysfs.h6
-rw-r--r--include/linux/threads.h3
-rw-r--r--include/linux/timer.h8
-rw-r--r--include/linux/tiocl.h1
-rw-r--r--include/linux/topology.h9
-rw-r--r--include/linux/tty_flip.h25
-rw-r--r--include/linux/ufs_fs.h4
-rw-r--r--include/linux/uinput.h4
-rw-r--r--include/linux/usb.h2
-rw-r--r--include/linux/usb/net2280.h444
-rw-r--r--include/linux/vermagic.h7
-rw-r--r--include/linux/videodev2.h68
-rw-r--r--include/linux/vt_kern.h5
-rw-r--r--include/linux/wanpipe.h483
-rw-r--r--include/linux/x1205.h31
-rw-r--r--include/media/cx25840.h64
-rw-r--r--include/media/msp3400.h60
-rw-r--r--include/media/saa7115.h37
-rw-r--r--include/media/saa7127.h41
-rw-r--r--include/media/upd64031a.h40
-rw-r--r--include/media/upd64083.h58
-rw-r--r--include/net/arp.h2
-rw-r--r--include/net/ax25.h10
-rw-r--r--include/net/compat.h3
-rw-r--r--include/net/ieee80211.h6
-rw-r--r--include/net/ieee80211softmac.h11
-rw-r--r--include/net/inet6_hashtables.h70
-rw-r--r--include/net/inet_timewait_sock.h2
-rw-r--r--include/net/ip.h1
-rw-r--r--include/net/ipv6.h2
-rw-r--r--include/net/irda/irlmp.h2
-rw-r--r--include/net/neighbour.h1
-rw-r--r--include/net/netfilter/nf_conntrack.h17
-rw-r--r--include/net/netrom.h8
-rw-r--r--include/net/request_sock.h2
-rw-r--r--include/net/rose.h14
-rw-r--r--include/net/sctp/command.h1
-rw-r--r--include/net/sctp/sctp.h6
-rw-r--r--include/net/sctp/structs.h1
-rw-r--r--include/net/sock.h94
-rw-r--r--include/net/tcp.h3
-rw-r--r--include/net/x25device.h1
-rw-r--r--include/net/xfrm.h43
-rw-r--r--include/pcmcia/bulkmem.h4
-rw-r--r--include/pcmcia/ciscode.h5
-rw-r--r--include/pcmcia/cistpl.h21
-rw-r--r--include/pcmcia/cs.h34
-rw-r--r--include/pcmcia/ds.h80
-rw-r--r--include/pcmcia/ss.h11
-rw-r--r--include/rdma/ib_mad.h27
-rw-r--r--include/rdma/ib_sa.h28
-rw-r--r--include/rdma/ib_verbs.h28
-rw-r--r--include/scsi/scsi_devinfo.h1
-rw-r--r--include/scsi/scsi_host.h1
-rw-r--r--include/scsi/scsi_ioctl.h2
-rw-r--r--include/scsi/scsi_transport.h5
-rw-r--r--include/scsi/scsi_transport_fc.h41
-rw-r--r--include/scsi/srp.h23
-rw-r--r--include/sound/core.h10
-rw-r--r--include/sound/pcm.h24
-rw-r--r--include/sound/pcm_oss.h5
-rw-r--r--init/do_mounts.c5
-rw-r--r--init/initramfs.c8
-rw-r--r--init/main.c4
-rw-r--r--ipc/mqueue.c2
-rw-r--r--ipc/msg.c11
-rw-r--r--ipc/sem.c11
-rw-r--r--ipc/shm.c36
-rw-r--r--ipc/util.c16
-rw-r--r--kernel/Makefile3
-rw-r--r--kernel/acct.c12
-rw-r--r--kernel/audit.c162
-rw-r--r--kernel/audit.h10
-rw-r--r--kernel/auditfilter.c289
-rw-r--r--kernel/auditsc.c269
-rw-r--r--kernel/compat.c23
-rw-r--r--kernel/cpu.c29
-rw-r--r--kernel/cpuset.c92
-rw-r--r--kernel/exit.c151
-rw-r--r--kernel/extable.c2
-rw-r--r--kernel/fork.c151
-rw-r--r--kernel/futex.c174
-rw-r--r--kernel/futex_compat.c144
-rw-r--r--kernel/hrtimer.c60
-rw-r--r--kernel/irq/Makefile3
-rw-r--r--kernel/irq/manage.c6
-rw-r--r--kernel/irq/migration.c5
-rw-r--r--kernel/kmod.c2
-rw-r--r--kernel/kprobes.c3
-rw-r--r--kernel/module.c35
-rw-r--r--kernel/panic.c5
-rw-r--r--kernel/params.c2
-rw-r--r--kernel/pid.c250
-rw-r--r--kernel/power/Kconfig2
-rw-r--r--kernel/power/main.c2
-rw-r--r--kernel/power/pm.c20
-rw-r--r--kernel/power/process.c3
-rw-r--r--kernel/power/snapshot.c9
-rw-r--r--kernel/printk.c6
-rw-r--r--kernel/profile.c55
-rw-r--r--kernel/ptrace.c75
-rw-r--r--kernel/rcupdate.c23
-rw-r--r--kernel/rcutorture.c4
-rw-r--r--kernel/sched.c240
-rw-r--r--kernel/signal.c356
-rw-r--r--kernel/softirq.c4
-rw-r--r--kernel/softlockup.c6
-rw-r--r--kernel/sys.c419
-rw-r--r--kernel/sys_ni.c16
-rw-r--r--kernel/time.c8
-rw-r--r--kernel/timer.c146
-rw-r--r--kernel/uid16.c59
-rw-r--r--kernel/workqueue.c2
-rw-r--r--lib/Kconfig.debug19
-rw-r--r--lib/kobject.c14
-rw-r--r--lib/kobject_uevent.c8
-rw-r--r--lib/string.c5
-rw-r--r--mm/Makefile2
-rw-r--r--mm/bootmem.c48
-rw-r--r--mm/fadvise.c20
-rw-r--r--mm/filemap.c32
-rw-r--r--mm/highmem.c15
-rw-r--r--mm/hugetlb.c6
-rw-r--r--mm/madvise.c3
-rw-r--r--mm/memory.c2
-rw-r--r--mm/memory_hotplug.c14
-rw-r--r--mm/mempolicy.c3
-rw-r--r--mm/migrate.c19
-rw-r--r--mm/mmap.c43
-rw-r--r--mm/mmzone.c50
-rw-r--r--mm/nommu.c18
-rw-r--r--mm/oom_kill.c71
-rw-r--r--mm/page-writeback.c7
-rw-r--r--mm/page_alloc.c168
-rw-r--r--mm/shmem.c5
-rw-r--r--mm/slab.c103
-rw-r--r--mm/slob.c10
-rw-r--r--mm/sparse.c16
-rw-r--r--mm/swap.c2
-rw-r--r--mm/swap_state.c3
-rw-r--r--mm/swapfile.c14
-rw-r--r--mm/vmalloc.c3
-rw-r--r--mm/vmscan.c10
-rw-r--r--net/802/tr.c1
-rw-r--r--net/appletalk/ddp.c19
-rw-r--r--net/atm/clip.c462
-rw-r--r--net/ax25/af_ax25.c93
-rw-r--r--net/ax25/ax25_addr.c9
-rw-r--r--net/ax25/ax25_ds_timer.c3
-rw-r--r--net/ax25/ax25_iface.c13
-rw-r--r--net/ax25/ax25_ip.c3
-rw-r--r--net/ax25/ax25_out.c3
-rw-r--r--net/ax25/ax25_route.c2
-rw-r--r--net/ax25/ax25_timer.c3
-rw-r--r--net/ax25/ax25_uid.c4
-rw-r--r--net/ax25/sysctl_net_ax25.c10
-rw-r--r--net/bluetooth/hci_core.c8
-rw-r--r--net/bluetooth/sco.c2
-rw-r--r--net/bridge/br.c3
-rw-r--r--net/bridge/br_forward.c8
-rw-r--r--net/bridge/br_if.c28
-rw-r--r--net/bridge/br_input.c4
-rw-r--r--net/bridge/br_netfilter.c13
-rw-r--r--net/bridge/netfilter/ebt_802_3.c8
-rw-r--r--net/bridge/netfilter/ebt_among.c8
-rw-r--r--net/bridge/netfilter/ebt_arp.c8
-rw-r--r--net/bridge/netfilter/ebt_arpreply.c8
-rw-r--r--net/bridge/netfilter/ebt_dnat.c8
-rw-r--r--net/bridge/netfilter/ebt_ip.c8
-rw-r--r--net/bridge/netfilter/ebt_limit.c8
-rw-r--r--net/bridge/netfilter/ebt_log.c10
-rw-r--r--net/bridge/netfilter/ebt_mark.c8
-rw-r--r--net/bridge/netfilter/ebt_mark_m.c8
-rw-r--r--net/bridge/netfilter/ebt_pkttype.c8
-rw-r--r--net/bridge/netfilter/ebt_redirect.c8
-rw-r--r--net/bridge/netfilter/ebt_snat.c8
-rw-r--r--net/bridge/netfilter/ebt_stp.c8
-rw-r--r--net/bridge/netfilter/ebt_ulog.c8
-rw-r--r--net/bridge/netfilter/ebt_vlan.c8
-rw-r--r--net/bridge/netfilter/ebtable_broute.c8
-rw-r--r--net/bridge/netfilter/ebtable_filter.c8
-rw-r--r--net/bridge/netfilter/ebtable_nat.c8
-rw-r--r--net/bridge/netfilter/ebtables.c46
-rw-r--r--net/compat.c3
-rw-r--r--net/core/dev.c197
-rw-r--r--net/core/dv.c5
-rw-r--r--net/core/filter.c5
-rw-r--r--net/core/flow.c8
-rw-r--r--net/core/gen_estimator.c3
-rw-r--r--net/core/link_watch.c10
-rw-r--r--net/core/neighbour.c37
-rw-r--r--net/core/net-sysfs.c51
-rw-r--r--net/core/request_sock.c6
-rw-r--r--net/core/skbuff.c8
-rw-r--r--net/core/sock.c109
-rw-r--r--net/core/stream.c1
-rw-r--r--net/core/utils.c4
-rw-r--r--net/core/wireless.c8
-rw-r--r--net/dccp/ackvec.c1
-rw-r--r--net/dccp/feat.c6
-rw-r--r--net/dccp/ipv4.c2
-rw-r--r--net/dccp/proto.c13
-rw-r--r--net/decnet/dn_dev.c12
-rw-r--r--net/decnet/dn_neigh.c5
-rw-r--r--net/decnet/netfilter/dn_rtmsg.c8
-rw-r--r--net/econet/af_econet.c124
-rw-r--r--net/ethernet/Makefile1
-rw-r--r--net/ethernet/sysctl_net_ether.c14
-rw-r--r--net/ieee80211/ieee80211_wx.c4
-rw-r--r--net/ieee80211/softmac/Kconfig1
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c42
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_auth.c16
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_event.c40
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_io.c18
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_module.c23
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_priv.h2
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_scan.c10
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_wx.c49
-rw-r--r--net/ipv4/Kconfig17
-rw-r--r--net/ipv4/Makefile3
-rw-r--r--net/ipv4/af_inet.c2
-rw-r--r--net/ipv4/ah4.c2
-rw-r--r--net/ipv4/arp.c4
-rw-r--r--net/ipv4/devinet.c17
-rw-r--r--net/ipv4/esp4.c5
-rw-r--r--net/ipv4/fib_frontend.c1
-rw-r--r--net/ipv4/fib_trie.c14
-rw-r--r--net/ipv4/icmp.c2
-rw-r--r--net/ipv4/inet_hashtables.c4
-rw-r--r--net/ipv4/ip_forward.c1
-rw-r--r--net/ipv4/ip_fragment.c15
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/ip_input.c2
-rw-r--r--net/ipv4/ip_options.c2
-rw-r--r--net/ipv4/ip_output.c8
-rw-r--r--net/ipv4/ipcomp.c18
-rw-r--r--net/ipv4/ipip.c83
-rw-r--r--net/ipv4/netfilter.c58
-rw-r--r--net/ipv4/netfilter/Kconfig25
-rw-r--r--net/ipv4/netfilter/Makefile3
-rw-r--r--net/ipv4/netfilter/arp_tables.c14
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c8
-rw-r--r--net/ipv4/netfilter/arptable_filter.c27
-rw-r--r--net/ipv4/netfilter/ip_conntrack_amanda.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c9
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c10
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c68
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c48
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_pptp.c12
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c12
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netbios_ns.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_icmp.c23
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_sctp.c19
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_udp.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c272
-rw-r--r--net/ipv4/netfilter/ip_conntrack_tftp.c10
-rw-r--r--net/ipv4/netfilter/ip_nat_amanda.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_ftp.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_h323.c71
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_pptp.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_irc.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_gre.c12
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c24
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c167
-rw-r--r--net/ipv4/netfilter/ip_nat_tftp.c8
-rw-r--r--net/ipv4/netfilter/ip_queue.c35
-rw-r--r--net/ipv4/netfilter/ip_tables.c1145
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c46
-rw-r--r--net/ipv4/netfilter/ipt_DSCP.c8
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c8
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c10
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c8
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c8
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c8
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c17
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c8
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c8
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c8
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c8
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c8
-rw-r--r--net/ipv4/netfilter/ipt_addrtype.c8
-rw-r--r--net/ipv4/netfilter/ipt_ah.c8
-rw-r--r--net/ipv4/netfilter/ipt_dscp.c8
-rw-r--r--net/ipv4/netfilter/ipt_ecn.c8
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c8
-rw-r--r--net/ipv4/netfilter/ipt_iprange.c8
-rw-r--r--net/ipv4/netfilter/ipt_multiport.c195
-rw-r--r--net/ipv4/netfilter/ipt_owner.c8
-rw-r--r--net/ipv4/netfilter/ipt_recent.c10
-rw-r--r--net/ipv4/netfilter/ipt_tos.c8
-rw-r--r--net/ipv4/netfilter/ipt_ttl.c8
-rw-r--r--net/ipv4/netfilter/iptable_filter.c29
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c41
-rw-r--r--net/ipv4/netfilter/iptable_raw.c43
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c230
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c20
-rw-r--r--net/ipv4/proc.c4
-rw-r--r--net/ipv4/route.c7
-rw-r--r--net/ipv4/tcp.c13
-rw-r--r--net/ipv4/tcp_cong.c2
-rw-r--r--net/ipv4/tcp_highspeed.c5
-rw-r--r--net/ipv4/tcp_input.c3
-rw-r--r--net/ipv4/tcp_ipv4.c1
-rw-r--r--net/ipv4/tcp_output.c25
-rw-r--r--net/ipv4/tunnel4.c121
-rw-r--r--net/ipv4/xfrm4_input.c17
-rw-r--r--net/ipv4/xfrm4_output.c2
-rw-r--r--net/ipv4/xfrm4_policy.c2
-rw-r--r--net/ipv4/xfrm4_tunnel.c81
-rw-r--r--net/ipv6/Kconfig19
-rw-r--r--net/ipv6/Makefile3
-rw-r--r--net/ipv6/addrconf.c10
-rw-r--r--net/ipv6/ah6.c2
-rw-r--r--net/ipv6/esp6.c2
-rw-r--r--net/ipv6/exthdrs.c16
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/inet6_connection_sock.c2
-rw-r--r--net/ipv6/inet6_hashtables.c80
-rw-r--r--net/ipv6/ip6_input.c3
-rw-r--r--net/ipv6/ip6_tunnel.c57
-rw-r--r--net/ipv6/ipcomp6.c17
-rw-r--r--net/ipv6/netfilter.c52
-rw-r--r--net/ipv6/netfilter/Kconfig16
-rw-r--r--net/ipv6/netfilter/Makefile3
-rw-r--r--net/ipv6/netfilter/ip6_queue.c35
-rw-r--r--net/ipv6/netfilter/ip6_tables.c27
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c8
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c10
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c8
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c8
-rw-r--r--net/ipv6/netfilter/ip6t_dst.c8
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c115
-rw-r--r--net/ipv6/netfilter/ip6t_eui64.c10
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c8
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c8
-rw-r--r--net/ipv6/netfilter/ip6t_hl.c8
-rw-r--r--net/ipv6/netfilter/ip6t_multiport.c125
-rw-r--r--net/ipv6/netfilter/ip6t_owner.c8
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c8
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c29
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c41
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c23
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c185
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c12
-rw-r--r--net/ipv6/proc.c4
-rw-r--r--net/ipv6/reassembly.c18
-rw-r--r--net/ipv6/route.c21
-rw-r--r--net/ipv6/sit.c2
-rw-r--r--net/ipv6/tunnel6.c139
-rw-r--r--net/ipv6/xfrm6_input.c16
-rw-r--r--net/ipv6/xfrm6_policy.c8
-rw-r--r--net/ipv6/xfrm6_tunnel.c83
-rw-r--r--net/ipx/af_ipx.c30
-rw-r--r--net/ipx/ipx_route.c2
-rw-r--r--net/irda/af_irda.c31
-rw-r--r--net/irda/iriap.c3
-rw-r--r--net/irda/irias_object.c3
-rw-r--r--net/irda/irlap.c3
-rw-r--r--net/llc/llc_input.c3
-rw-r--r--net/netfilter/Kconfig19
-rw-r--r--net/netfilter/Makefile2
-rw-r--r--net/netfilter/core.c51
-rw-r--r--net/netfilter/nf_conntrack_core.c23
-rw-r--r--net/netfilter/nf_conntrack_ftp.c10
-rw-r--r--net/netfilter/nf_conntrack_l3proto_generic.c1
-rw-r--r--net/netfilter/nf_conntrack_netlink.c6
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c19
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c50
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c50
-rw-r--r--net/netfilter/nf_conntrack_standalone.c123
-rw-r--r--net/netfilter/nf_queue.c49
-rw-r--r--net/netfilter/nfnetlink_log.c35
-rw-r--r--net/netfilter/nfnetlink_queue.c33
-rw-r--r--net/netfilter/x_tables.c119
-rw-r--r--net/netfilter/xt_CLASSIFY.c8
-rw-r--r--net/netfilter/xt_CONNMARK.c8
-rw-r--r--net/netfilter/xt_MARK.c8
-rw-r--r--net/netfilter/xt_NFQUEUE.c8
-rw-r--r--net/netfilter/xt_NOTRACK.c8
-rw-r--r--net/netfilter/xt_comment.c8
-rw-r--r--net/netfilter/xt_connbytes.c8
-rw-r--r--net/netfilter/xt_connmark.c8
-rw-r--r--net/netfilter/xt_conntrack.c8
-rw-r--r--net/netfilter/xt_dccp.c8
-rw-r--r--net/netfilter/xt_esp.c (renamed from net/ipv4/netfilter/ipt_esp.c)81
-rw-r--r--net/netfilter/xt_helper.c8
-rw-r--r--net/netfilter/xt_length.c8
-rw-r--r--net/netfilter/xt_limit.c8
-rw-r--r--net/netfilter/xt_mac.c8
-rw-r--r--net/netfilter/xt_mark.c8
-rw-r--r--net/netfilter/xt_multiport.c314
-rw-r--r--net/netfilter/xt_physdev.c8
-rw-r--r--net/netfilter/xt_pkttype.c8
-rw-r--r--net/netfilter/xt_policy.c2
-rw-r--r--net/netfilter/xt_realm.c8
-rw-r--r--net/netfilter/xt_sctp.c8
-rw-r--r--net/netfilter/xt_state.c8
-rw-r--r--net/netfilter/xt_string.c8
-rw-r--r--net/netfilter/xt_tcpmss.c8
-rw-r--r--net/netfilter/xt_tcpudp.c8
-rw-r--r--net/netlink/af_netlink.c12
-rw-r--r--net/netrom/af_netrom.c18
-rw-r--r--net/netrom/nr_dev.c1
-rw-r--r--net/nonet.c2
-rw-r--r--net/rose/af_rose.c13
-rw-r--r--net/rose/rose_dev.c1
-rw-r--r--net/rose/rose_link.c6
-rw-r--r--net/rose/rose_route.c7
-rw-r--r--net/sched/act_ipt.c5
-rw-r--r--net/sched/act_police.c8
-rw-r--r--net/sched/sch_generic.c6
-rw-r--r--net/sched/sch_hfsc.c6
-rw-r--r--net/sched/sch_netem.c2
-rw-r--r--net/sctp/input.c144
-rw-r--r--net/sctp/inqueue.c1
-rw-r--r--net/sctp/proc.c2
-rw-r--r--net/sctp/sm_sideeffect.c16
-rw-r--r--net/sctp/sm_statefuns.c140
-rw-r--r--net/sctp/sm_statetable.c10
-rw-r--r--net/sctp/socket.c29
-rw-r--r--net/sctp/ulpqueue.c27
-rw-r--r--net/socket.c18
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c1
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_crypto.c11
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c196
-rw-r--r--net/sunrpc/cache.c164
-rw-r--r--net/sunrpc/rpc_pipe.c2
-rw-r--r--net/sunrpc/stats.c7
-rw-r--r--net/sunrpc/sunrpc_syms.c6
-rw-r--r--net/sunrpc/svcauth.c122
-rw-r--r--net/sunrpc/svcauth_unix.c229
-rw-r--r--net/sysctl_net.c8
-rw-r--r--net/tipc/name_distr.c3
-rw-r--r--net/wanrouter/af_wanpipe.c2
-rw-r--r--net/x25/x25_timer.c4
-rw-r--r--net/xfrm/xfrm_input.c6
-rw-r--r--net/xfrm/xfrm_policy.c26
-rw-r--r--net/xfrm/xfrm_state.c33
-rw-r--r--scripts/Kbuild.include5
-rw-r--r--scripts/Makefile.lib5
-rwxr-xr-x[-rw-r--r--]scripts/bloat-o-meter0
-rwxr-xr-x[-rw-r--r--]scripts/checkstack.pl0
-rw-r--r--scripts/gen_initramfs_list.sh229
-rw-r--r--scripts/kconfig/conf.c24
-rw-r--r--scripts/kconfig/confdata.c2
-rw-r--r--scripts/kconfig/lxdialog/checklist.c19
-rw-r--r--scripts/kconfig/lxdialog/menubox.c19
-rw-r--r--scripts/mkmakefile5
-rw-r--r--scripts/mod/file2alias.c36
-rw-r--r--scripts/mod/modpost.c107
-rw-r--r--scripts/mod/modpost.h23
-rwxr-xr-x[-rw-r--r--]scripts/namespace.pl0
-rwxr-xr-x[-rw-r--r--]scripts/show_delta0
-rwxr-xr-xscripts/ver_linux4
-rw-r--r--security/dummy.c6
-rw-r--r--security/keys/key.c4
-rw-r--r--security/keys/keyring.c1
-rw-r--r--security/keys/process_keys.c41
-rw-r--r--security/selinux/Makefile2
-rw-r--r--security/selinux/avc.c13
-rw-r--r--security/selinux/exports.c74
-rw-r--r--security/selinux/hooks.c19
-rw-r--r--security/selinux/include/security.h5
-rw-r--r--security/selinux/ss/mls.c32
-rw-r--r--security/selinux/ss/mls.h4
-rw-r--r--security/selinux/ss/services.c239
-rw-r--r--security/selinux/xfrm.c4
-rw-r--r--sound/core/Kconfig17
-rw-r--r--sound/core/control.c6
-rw-r--r--sound/core/control_compat.c6
-rw-r--r--sound/core/init.c12
-rw-r--r--sound/core/oss/pcm_oss.c297
-rw-r--r--sound/core/pcm.c28
-rw-r--r--sound/core/pcm_lib.c55
-rw-r--r--sound/core/pcm_memory.c8
-rw-r--r--sound/core/pcm_native.c159
-rw-r--r--sound/core/rawmidi.c6
-rw-r--r--sound/core/sound.c4
-rw-r--r--sound/core/sound_oss.c2
-rw-r--r--sound/drivers/dummy.c14
-rw-r--r--sound/drivers/mpu401/mpu401.c32
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c42
-rw-r--r--sound/drivers/serial-u16550.c14
-rw-r--r--sound/drivers/virmidi.c14
-rw-r--r--sound/isa/Kconfig23
-rw-r--r--sound/isa/Makefile2
-rw-r--r--sound/isa/ad1816a/ad1816a.c12
-rw-r--r--sound/isa/ad1848/ad1848.c16
-rw-r--r--sound/isa/adlib.c164
-rw-r--r--sound/isa/als100.c14
-rw-r--r--sound/isa/azt2320.c12
-rw-r--r--sound/isa/cmi8330.c35
-rw-r--r--sound/isa/cs423x/cs4231.c16
-rw-r--r--sound/isa/cs423x/cs4236.c41
-rw-r--r--sound/isa/dt019x.c12
-rw-r--r--sound/isa/es1688/es1688.c16
-rw-r--r--sound/isa/es18xx.c31
-rw-r--r--sound/isa/gus/gusclassic.c16
-rw-r--r--sound/isa/gus/gusextreme.c16
-rw-r--r--sound/isa/gus/gusmax.c16
-rw-r--r--sound/isa/gus/interwave.c28
-rw-r--r--sound/isa/opl3sa2.c33
-rw-r--r--sound/isa/opti9xx/Makefile2
-rw-r--r--sound/isa/opti9xx/miro.c1455
-rw-r--r--sound/isa/opti9xx/miro.h73
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c7
-rw-r--r--sound/isa/sb/es968.c12
-rw-r--r--sound/isa/sb/sb16.c30
-rw-r--r--sound/isa/sb/sb8.c16
-rw-r--r--sound/isa/sgalaxy.c16
-rw-r--r--sound/isa/sscape.c20
-rw-r--r--sound/isa/wavefront/wavefront.c26
-rw-r--r--sound/oss/Kconfig306
-rw-r--r--sound/oss/ad1848.c10
-rw-r--r--sound/oss/ad1889.c198
-rw-r--r--sound/oss/ad1889.h101
-rw-r--r--sound/oss/cs4232.c15
-rw-r--r--sound/oss/dmasound/dmasound_awacs.c4
-rw-r--r--sound/oss/dmasound/tas_common.c4
-rw-r--r--sound/oss/emu10k1/main.c3
-rw-r--r--sound/oss/emu10k1/midi.c9
-rw-r--r--sound/oss/esssolo1.c2
-rw-r--r--sound/oss/maestro3.c10
-rw-r--r--sound/oss/msnd.c6
-rw-r--r--sound/oss/nm256_audio.c6
-rw-r--r--sound/oss/sb_card.c35
-rw-r--r--sound/oss/sequencer.c13
-rw-r--r--sound/oss/sh_dac_audio.c2
-rw-r--r--sound/oss/sonicvibes.c3
-rw-r--r--sound/pci/Kconfig30
-rw-r--r--sound/pci/Makefile3
-rw-r--r--sound/pci/ac97/ac97_codec.c1
-rw-r--r--sound/pci/ad1889.c2
-rw-r--r--sound/pci/ali5451/ali5451.c7
-rw-r--r--sound/pci/als300.c867
-rw-r--r--sound/pci/als4000.c7
-rw-r--r--sound/pci/atiixp.c2
-rw-r--r--sound/pci/atiixp_modem.c2
-rw-r--r--sound/pci/au88x0/au8810.c2
-rw-r--r--sound/pci/au88x0/au8820.c2
-rw-r--r--sound/pci/au88x0/au8830.c2
-rw-r--r--sound/pci/au88x0/au88x0.h13
-rw-r--r--sound/pci/au88x0/au88x0_core.c2
-rw-r--r--sound/pci/au88x0/au88x0_eq.c2
-rw-r--r--sound/pci/au88x0/au88x0_pcm.c2
-rw-r--r--sound/pci/azt3328.c7
-rw-r--r--sound/pci/bt87x.c4
-rw-r--r--sound/pci/ca0106/ca0106_main.c2
-rw-r--r--sound/pci/cmipci.c2
-rw-r--r--sound/pci/cs4281.c30
-rw-r--r--sound/pci/cs46xx/cs46xx.c2
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c2
-rw-r--r--sound/pci/emu10k1/emu10k1.c2
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c5
-rw-r--r--sound/pci/emu10k1/emu10k1x.c2
-rw-r--r--sound/pci/ens1370.c2
-rw-r--r--sound/pci/es1938.c7
-rw-r--r--sound/pci/es1968.c2
-rw-r--r--sound/pci/fm801.c2
-rw-r--r--sound/pci/hda/hda_codec.c2
-rw-r--r--sound/pci/hda/hda_intel.c4
-rw-r--r--sound/pci/hda/patch_analog.c24
-rw-r--r--sound/pci/hda/patch_realtek.c299
-rw-r--r--sound/pci/hda/patch_sigmatel.c60
-rw-r--r--sound/pci/ice1712/aureon.c163
-rw-r--r--sound/pci/ice1712/ice1712.c5
-rw-r--r--sound/pci/ice1712/ice1712.h1
-rw-r--r--sound/pci/ice1712/ice1724.c2
-rw-r--r--sound/pci/intel8x0.c8
-rw-r--r--sound/pci/intel8x0m.c2
-rw-r--r--sound/pci/korg1212/korg1212.c2
-rw-r--r--sound/pci/maestro3.c59
-rw-r--r--sound/pci/mixart/mixart.c3
-rw-r--r--sound/pci/nm256/nm256.c2
-rw-r--r--sound/pci/pcxhr/pcxhr.c2
-rw-r--r--sound/pci/pcxhr/pcxhr_core.c9
-rw-r--r--sound/pci/pcxhr/pcxhr_hwdep.c4
-rw-r--r--sound/pci/riptide/Makefile3
-rw-r--r--sound/pci/riptide/riptide.c2223
-rw-r--r--sound/pci/rme32.c10
-rw-r--r--sound/pci/rme96.c10
-rw-r--r--sound/pci/rme9652/hdsp.c2
-rw-r--r--sound/pci/rme9652/hdspm.c4
-rw-r--r--sound/pci/rme9652/rme9652.c2
-rw-r--r--sound/pci/sonicvibes.c7
-rw-r--r--sound/pci/trident/trident.c2
-rw-r--r--sound/pci/trident/trident_main.c5
-rw-r--r--sound/pci/via82xx.c20
-rw-r--r--sound/pci/via82xx_modem.c2
-rw-r--r--sound/pci/vx222/vx222.c2
-rw-r--r--sound/pci/ymfpci/ymfpci.c2
-rw-r--r--sound/pcmcia/Kconfig4
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c86
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.h2
-rw-r--r--sound/pcmcia/vx/vxpocket.c94
-rw-r--r--sound/pcmcia/vx/vxpocket.h2
-rw-r--r--sound/ppc/daca.c2
-rw-r--r--sound/ppc/pmac.c2
-rw-r--r--sound/ppc/toonie.c2
-rw-r--r--sound/ppc/tumbler.c2
-rw-r--r--sound/sound_core.c22
-rw-r--r--sound/usb/usbmixer.c37
-rw-r--r--sound/usb/usbquirks.h9
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c2
-rw-r--r--usr/Makefile91
-rw-r--r--usr/gen_init_cpio.c4
3700 files changed, 153714 insertions, 108636 deletions
diff --git a/CREDITS b/CREDITS
index c6d69bf10e1..9bf714a1c7d 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1127,8 +1127,10 @@ S: Carnegie, Pennsylvania 15106-4304
S: USA
N: Philip Gladstone
-E: philip@raptor.com
+E: philip@gladstonefamily.net
D: Kernel / timekeeping stuff
+S: Carlisle, MA 01741
+S: USA
N: Jan-Benedict Glaw
E: jbglaw@lug-owl.de
@@ -1192,15 +1194,9 @@ S: Brecksville, OH 44141-1334
S: USA
N: Tristan Greaves
-E: Tristan.Greaves@icl.com
-E: tmg296@ecs.soton.ac.uk
-W: http://www.ecs.soton.ac.uk/~tmg296
+E: tristan@extricate.org
+W: http://www.extricate.org/
D: Miscellaneous ipv4 sysctl patches
-S: 15 Little Mead
-S: Denmead
-S: Hampshire
-S: PO7 6HS
-S: United Kingdom
N: Michael A. Griffith
E: grif@cs.ucr.edu
@@ -3245,14 +3241,9 @@ S: 12725 SW Millikan Way, Suite 400
S: Beaverton, Oregon 97005
S: USA
-N: Marcelo W. Tosatti
-E: marcelo.tosatti@cyclades.com
-D: Miscellaneous kernel hacker
+N: Marcelo Tosatti
+E: marcelo@kvack.org
D: v2.4 kernel maintainer
-D: Current pc300/cyclades maintainer
-S: Cyclades Corporation
-S: Av Cristovao Colombo, 462. Floresta.
-S: Porto Alegre
S: Brazil
N: Stefan Traby
@@ -3380,7 +3371,7 @@ S: Germany
N: Geert Uytterhoeven
E: geert@linux-m68k.org
-W: http://home.tvd.be/cr26864/
+W: http://users.telenet.be/geertu/
P: 1024/862678A6 C51D 361C 0BD1 4C90 B275 C553 6EEA 11BA 8626 78A6
D: m68k/Amiga and PPC/CHRP Longtrail coordinator
D: Frame buffer device and XF68_FBDev maintainer
@@ -3390,8 +3381,8 @@ D: Amiga Buddha and Catweasel chipset IDE
D: Atari Falcon chipset IDE
D: Amiga Gayle chipset IDE
D: mipsel NEC DDB Vrc-5074
-S: Emiel Vlieberghlaan 2A/21
-S: B-3010 Kessel-Lo
+S: Haterbeekstraat 55B
+S: B-3200 Aarschot
S: Belgium
N: Chris Vance
@@ -3741,10 +3732,11 @@ D: Mylex DAC960 PCI RAID driver
D: Miscellaneous kernel fixes
N: Alessandro Zummo
-E: azummo@ita.flashnet.it
-W: http://freepage.logicom.it/azummo/
+E: a.zummo@towertech.it
D: CMI8330 support is sb_card.c
D: ISAPnP fixes in sb_card.c
+D: ZyXEL omni.net lcd plus driver
+D: RTC subsystem
S: Italy
N: Marc Zyngier
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 1af0f2d5022..2ffb0d62f0f 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -33,7 +33,9 @@ pci_alloc_consistent(struct pci_dev *dev, size_t size,
Consistent memory is memory for which a write by either the device or
the processor can immediately be read by the processor or device
-without having to worry about caching effects.
+without having to worry about caching effects. (You may however need
+to make sure to flush the processor's write buffers before telling
+devices to read that memory.)
This routine allocates a region of <size> bytes of consistent memory.
it also returns a <dma_handle> which may be cast to an unsigned
@@ -304,12 +306,12 @@ dma address with dma_mapping_error(). A non zero return value means the mapping
could not be created and the driver should take appropriate action (eg
reduce current DMA mapping usage or delay and try again later).
-int
-dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction direction)
-int
-pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
- int nents, int direction)
+ int
+ dma_map_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction)
+ int
+ pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+ int nents, int direction)
Maps a scatter gather list from the block layer.
@@ -327,12 +329,33 @@ critical that the driver do something, in the case of a block driver
aborting the request or even oopsing is better than doing nothing and
corrupting the filesystem.
-void
-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
- enum dma_data_direction direction)
-void
-pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
- int nents, int direction)
+With scatterlists, you use the resulting mapping like this:
+
+ int i, count = dma_map_sg(dev, sglist, nents, direction);
+ struct scatterlist *sg;
+
+ for (i = 0, sg = sglist; i < count; i++, sg++) {
+ hw_address[i] = sg_dma_address(sg);
+ hw_len[i] = sg_dma_len(sg);
+ }
+
+where nents is the number of entries in the sglist.
+
+The implementation is free to merge several consecutive sglist entries
+into one (e.g. with an IOMMU, or if several pages just happen to be
+physically contiguous) and returns the actual number of sg entries it
+mapped them to. On failure 0, is returned.
+
+Then you should loop count times (note: this can be less than nents times)
+and use sg_dma_address() and sg_dma_len() macros where you previously
+accessed sg->address and sg->length as shown above.
+
+ void
+ dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+ int nhwentries, enum dma_data_direction direction)
+ void
+ pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+ int nents, int direction)
unmap the previously mapped scatter/gather list. All the parameters
must be the same as those and passed in to the scatter/gather mapping
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index 684557474c1..7c717699032 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -58,11 +58,15 @@ translating each of those pages back to a kernel address using
something like __va(). [ EDIT: Update this when we integrate
Gerd Knorr's generic code which does this. ]
-This rule also means that you may not use kernel image addresses
-(ie. items in the kernel's data/text/bss segment, or your driver's)
-nor may you use kernel stack addresses for DMA. Both of these items
-might be mapped somewhere entirely different than the rest of physical
-memory.
+This rule also means that you may use neither kernel image addresses
+(items in data/text/bss segments), nor module image addresses, nor
+stack addresses for DMA. These could all be mapped somewhere entirely
+different than the rest of physical memory. Even if those classes of
+memory could physically work with DMA, you'd need to ensure the I/O
+buffers were cacheline-aligned. Without that, you'd see cacheline
+sharing problems (data corruption) on CPUs with DMA-incoherent caches.
+(The CPU could write to one word, DMA would write to a different one
+in the same cache line, and one of them could be overwritten.)
Also, this means that you cannot take the return of a kmap()
call and DMA to/from that. This is similar to vmalloc().
@@ -194,11 +198,13 @@ document for how to handle this case.
Finally, if your device can only drive the low 24-bits of
address during PCI bus mastering you might do something like:
- if (pci_set_dma_mask(pdev, 0x00ffffff)) {
+ if (pci_set_dma_mask(pdev, DMA_24BIT_MASK)) {
printk(KERN_WARNING
"mydev: 24-bit DMA addressing not available.\n");
goto ignore_this_device;
}
+[Better use DMA_24BIT_MASK instead of 0x00ffffff.
+See linux/include/dma-mapping.h for reference.]
When pci_set_dma_mask() is successful, and returns zero, the PCI layer
saves away this mask you have provided. The PCI layer will use this
@@ -210,7 +216,7 @@ functions (for example a sound card provides playback and record
functions) and the various different functions have _different_
DMA addressing limitations, you may wish to probe each mask and
only provide the functionality which the machine can handle. It
-is important that the last call to pci_set_dma_mask() be for the
+is important that the last call to pci_set_dma_mask() be for the
most specific mask.
Here is pseudo-code showing how this might be done:
@@ -282,6 +288,11 @@ There are two types of DMA mappings:
in order to get correct behavior on all platforms.
+ Also, on some platforms your driver may need to flush CPU write
+ buffers in much the same way as it needs to flush write buffers
+ found in PCI bridges (such as by reading a register's value
+ after writing it).
+
- Streaming DMA mappings which are usually mapped for one DMA transfer,
unmapped right after it (unless you use pci_dma_sync_* below) and for which
hardware can optimize for sequential accesses.
@@ -301,6 +312,9 @@ There are two types of DMA mappings:
Neither type of DMA mapping has alignment restrictions that come
from PCI, although some devices may have such restrictions.
+Also, systems with caches that aren't DMA-coherent will work better
+when the underlying buffers don't share cache lines with other data.
+
Using Consistent DMA mappings.
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 7d87dd73cbe..5a2882d275b 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -2,7 +2,7 @@
# This makefile is used to generate the kernel documentation,
# primarily based on in-line comments in various source files.
# See Documentation/kernel-doc-nano-HOWTO.txt for instruction in how
-# to ducument the SRC - and how to read it.
+# to document the SRC - and how to read it.
# To add a new book the only step required is to add the book to the
# list of DOCBOOKS.
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 8c9c6704e85..ca02e04a906 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -322,7 +322,6 @@ X!Earch/i386/kernel/mca.c
<chapter id="sysfs">
<title>The Filesystem for Exporting Kernel Objects</title>
!Efs/sysfs/file.c
-!Efs/sysfs/dir.c
!Efs/sysfs/symlink.c
!Efs/sysfs/bin.c
</chapter>
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
index d260d92089a..f869b03929d 100644
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -120,14 +120,27 @@ void (*dev_config) (struct ata_port *, struct ata_device *);
<programlisting>
void (*set_piomode) (struct ata_port *, struct ata_device *);
void (*set_dmamode) (struct ata_port *, struct ata_device *);
-void (*post_set_mode) (struct ata_port *ap);
+void (*post_set_mode) (struct ata_port *);
+unsigned int (*mode_filter) (struct ata_port *, struct ata_device *, unsigned int);
</programlisting>
<para>
Hooks called prior to the issue of SET FEATURES - XFER MODE
- command. dev->pio_mode is guaranteed to be valid when
- ->set_piomode() is called, and dev->dma_mode is guaranteed to be
- valid when ->set_dmamode() is called. ->post_set_mode() is
+ command. The optional ->mode_filter() hook is called when libata
+ has built a mask of the possible modes. This is passed to the
+ ->mode_filter() function which should return a mask of valid modes
+ after filtering those unsuitable due to hardware limits. It is not
+ valid to use this interface to add modes.
+ </para>
+ <para>
+ dev->pio_mode and dev->dma_mode are guaranteed to be valid when
+ ->set_piomode() and when ->set_dmamode() is called. The timings for
+ any other drive sharing the cable will also be valid at this point.
+ That is the library records the decisions for the modes of each
+ drive on a channel before it attempts to set any of them.
+ </para>
+ <para>
+ ->post_set_mode() is
called unconditionally, after the SET FEATURES - XFER MODE
command completes successfully.
</para>
@@ -230,6 +243,32 @@ void (*dev_select)(struct ata_port *ap, unsigned int device);
</sect2>
+ <sect2><title>Private tuning method</title>
+ <programlisting>
+void (*set_mode) (struct ata_port *ap);
+ </programlisting>
+
+ <para>
+ By default libata performs drive and controller tuning in
+ accordance with the ATA timing rules and also applies blacklists
+ and cable limits. Some controllers need special handling and have
+ custom tuning rules, typically raid controllers that use ATA
+ commands but do not actually do drive timing.
+ </para>
+
+ <warning>
+ <para>
+ This hook should not be used to replace the standard controller
+ tuning logic when a controller has quirks. Replacing the default
+ tuning logic in that case would bypass handling for drive and
+ bridge quirks that may be important to data reliability. If a
+ controller needs to filter the mode selection it should use the
+ mode_filter hook instead.
+ </para>
+ </warning>
+
+ </sect2>
+
<sect2><title>Reset ATA bus</title>
<programlisting>
void (*phy_reset) (struct ata_port *ap);
@@ -666,7 +705,7 @@ and other resources, etc.
<sect1><title>ata_scsi_error()</title>
<para>
- ata_scsi_error() is the current hostt->eh_strategy_handler()
+ ata_scsi_error() is the current transportt->eh_strategy_handler()
for libata. As discussed above, this will be entered in two
cases - timeout and ATAPI error completion. This function
calls low level libata driver's eng_timeout() callback, the
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index 6c9e746267d..915ae8c986c 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -603,7 +603,8 @@ start exactly where you are now.
----------
-Thanks to Paolo Ciarrocchi who allowed the "Development Process" section
+Thanks to Paolo Ciarrocchi who allowed the "Development Process"
+(http://linux.tar.bz/articles/2.6-development_process) section
to be based on text he had written, and to Randy Dunlap and Gerrit
Huizenga for some of the list of things you should and should not say.
Also thanks to Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers,
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index b4ea51ad361..07cb93b82ba 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -605,7 +605,7 @@ are the same as those shown in the preceding section, so they are omitted.
{
int cpu;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
run_on(cpu);
}
diff --git a/Documentation/acpi-hotkey.txt b/Documentation/acpi-hotkey.txt
index 744f1aec655..38040fa3764 100644
--- a/Documentation/acpi-hotkey.txt
+++ b/Documentation/acpi-hotkey.txt
@@ -30,7 +30,7 @@ specific hotkey(event))
echo "event_num:event_type:event_argument" >
/proc/acpi/hotkey/action.
The result of the execution of this aml method is
-attached to /proc/acpi/hotkey/poll_method, which is dnyamically
+attached to /proc/acpi/hotkey/poll_method, which is dynamically
created. Please use command "cat /proc/acpi/hotkey/polling_method"
to retrieve it.
diff --git a/Documentation/arm/SA1100/Assabet b/Documentation/arm/SA1100/Assabet
index cbbe5587c78..78bc1c1b04e 100644
--- a/Documentation/arm/SA1100/Assabet
+++ b/Documentation/arm/SA1100/Assabet
@@ -26,7 +26,7 @@ Installing a bootloader
A couple of bootloaders able to boot Linux on Assabet are available:
-BLOB (http://www.lart.tudelft.nl/lartware/blob/)
+BLOB (http://www.lartmaker.nl/lartware/blob/)
BLOB is a bootloader used within the LART project. Some contributed
patches were merged into BLOB to add support for Assabet.
diff --git a/Documentation/arm/SA1100/LART b/Documentation/arm/SA1100/LART
index 2f73f513e16..6d412b68559 100644
--- a/Documentation/arm/SA1100/LART
+++ b/Documentation/arm/SA1100/LART
@@ -11,4 +11,4 @@ is under development, with plenty of others in different stages of
planning.
The hardware designs for this board have been released under an open license;
-see the LART page at http://www.lart.tudelft.nl/ for more information.
+see the LART page at http://www.lartmaker.nl/ for more information.
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index 8e63831971d..f989a9e839b 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -132,8 +132,18 @@ Some new queue property settings:
limit. No highmem default.
blk_queue_max_sectors(q, max_sectors)
- Maximum size request you can handle in units of 512 byte
- sectors. 255 default.
+ Sets two variables that limit the size of the request.
+
+ - The request queue's max_sectors, which is a soft size in
+ in units of 512 byte sectors, and could be dynamically varied
+ by the core kernel.
+
+ - The request queue's max_hw_sectors, which is a hard limit
+ and reflects the maximum size request a driver can handle
+ in units of 512 byte sectors.
+
+ The default for both max_sectors and max_hw_sectors is
+ 255. The upper limit of max_sectors is 1024.
blk_queue_max_phys_segments(q, max_segments)
Maximum physical segments you can handle in a request. 128
diff --git a/Documentation/block/switching-sched.txt b/Documentation/block/switching-sched.txt
new file mode 100644
index 00000000000..5fa130a6753
--- /dev/null
+++ b/Documentation/block/switching-sched.txt
@@ -0,0 +1,22 @@
+As of the Linux 2.6.10 kernel, it is now possible to change the
+IO scheduler for a given block device on the fly (thus making it possible,
+for instance, to set the CFQ scheduler for the system default, but
+set a specific device to use the anticipatory or noop schedulers - which
+can improve that device's throughput).
+
+To set a specific scheduler, simply do this:
+
+echo SCHEDNAME > /sys/block/DEV/queue/scheduler
+
+where SCHEDNAME is the name of a defined IO scheduler, and DEV is the
+device name (hda, hdb, sga, or whatever you happen to have).
+
+The list of defined schedulers can be found by simply doing
+a "cat /sys/block/DEV/queue/scheduler" - the list of valid names
+will be displayed, with the currently selected scheduler in brackets:
+
+# cat /sys/block/hda/queue/scheduler
+noop anticipatory deadline [cfq]
+# echo anticipatory > /sys/block/hda/queue/scheduler
+# cat /sys/block/hda/queue/scheduler
+noop [anticipatory] deadline cfq
diff --git a/Documentation/cpu-freq/index.txt b/Documentation/cpu-freq/index.txt
index 5009805f937..ffdb5323df3 100644
--- a/Documentation/cpu-freq/index.txt
+++ b/Documentation/cpu-freq/index.txt
@@ -53,4 +53,4 @@ the CPUFreq Mailing list:
* http://lists.linux.org.uk/mailman/listinfo/cpufreq
Clock and voltage scaling for the SA-1100:
-* http://www.lart.tudelft.nl/projects/scaling
+* http://www.lartmaker.nl/projects/scaling
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt
index 57a09f99ecb..1bcf69996c9 100644
--- a/Documentation/cpu-hotplug.txt
+++ b/Documentation/cpu-hotplug.txt
@@ -97,13 +97,13 @@ at which time hotplug is disabled.
You really dont need to manipulate any of the system cpu maps. They should
be read-only for most use. When setting up per-cpu resources almost always use
-cpu_possible_map/for_each_cpu() to iterate.
+cpu_possible_map/for_each_possible_cpu() to iterate.
Never use anything other than cpumask_t to represent bitmap of CPUs.
#include <linux/cpumask.h>
-for_each_cpu - Iterate over cpu_possible_map
+for_each_possible_cpu - Iterate over cpu_possible_map
for_each_online_cpu - Iterate over cpu_online_map
for_each_present_cpu - Iterate over cpu_present_map
for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask.
diff --git a/Documentation/cputopology.txt b/Documentation/cputopology.txt
index ff280e2e161..2b28e9ec4e3 100644
--- a/Documentation/cputopology.txt
+++ b/Documentation/cputopology.txt
@@ -1,5 +1,5 @@
-Export cpu topology info by sysfs. Items (attributes) are similar
+Export cpu topology info via sysfs. Items (attributes) are similar
to /proc/cpuinfo.
1) /sys/devices/system/cpu/cpuX/topology/physical_package_id:
@@ -12,7 +12,7 @@ represent the thread siblings to cpu X in the same core;
represent the thread siblings to cpu X in the same physical package;
To implement it in an architecture-neutral way, a new source file,
-driver/base/topology.c, is to export the 5 attributes.
+drivers/base/topology.c, is to export the 4 attributes.
If one architecture wants to support this feature, it just needs to
implement 4 defines, typically in file include/asm-XXX/topology.h.
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 3c406acd4df..b369a8c46a7 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -1721,11 +1721,6 @@ Your cooperation is appreciated.
These devices support the same API as the generic SCSI
devices.
- 97 block Packet writing for CD/DVD devices
- 0 = /dev/pktcdvd0 First packet-writing module
- 1 = /dev/pktcdvd1 Second packet-writing module
- ...
-
98 char Control and Measurement Device (comedi)
0 = /dev/comedi0 First comedi device
1 = /dev/comedi1 Second comedi device
diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware
index 15fc8fbef67..4820366b6ae 100644
--- a/Documentation/dvb/get_dvb_firmware
+++ b/Documentation/dvb/get_dvb_firmware
@@ -259,9 +259,9 @@ sub dibusb {
}
sub nxt2002 {
- my $sourcefile = "Broadband4PC_4_2_11.zip";
+ my $sourcefile = "Technisat_DVB-PC_4_4_COMPACT.zip";
my $url = "http://www.bbti.us/download/windows/$sourcefile";
- my $hash = "c6d2ea47a8f456d887ada0cfb718ff2a";
+ my $hash = "476befae8c7c1bb9648954060b1eec1f";
my $outfile = "dvb-fe-nxt2002.fw";
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
@@ -269,8 +269,8 @@ sub nxt2002 {
wgetfile($sourcefile, $url);
unzip($sourcefile, $tmpdir);
- verify("$tmpdir/SkyNETU.sys", $hash);
- extract("$tmpdir/SkyNETU.sys", 375832, 5908, $outfile);
+ verify("$tmpdir/SkyNET.sys", $hash);
+ extract("$tmpdir/SkyNET.sys", 331624, 5908, $outfile);
$outfile;
}
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 495858b236b..43ab119963d 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -25,8 +25,9 @@ Who: Adrian Bunk <bunk@stusta.de>
---------------------------
-What: drivers depending on OBSOLETE_OSS_DRIVER
-When: January 2006
+What: drivers that were depending on OBSOLETE_OSS_DRIVER
+ (config options already removed)
+When: before 2.6.19
Why: OSS drivers with ALSA replacements
Who: Adrian Bunk <bunk@stusta.de>
@@ -56,6 +57,15 @@ Who: Jody McIntyre <scjody@steamballoon.com>
---------------------------
+What: sbp2: module parameter "force_inquiry_hack"
+When: July 2006
+Why: Superceded by parameter "workarounds". Both parameters are meant to be
+ used ad-hoc and for single devices only, i.e. not in modprobe.conf,
+ therefore the impact of this feature replacement should be low.
+Who: Stefan Richter <stefanr@s5r6.in-berlin.de>
+
+---------------------------
+
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
When: July 2006
Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
@@ -71,14 +81,6 @@ Who: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
---------------------------
-What: remove EXPORT_SYMBOL(panic_timeout)
-When: April 2006
-Files: kernel/panic.c
-Why: No modular usage in the kernel.
-Who: Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
What: remove EXPORT_SYMBOL(insert_resource)
When: April 2006
Files: kernel/resource.c
@@ -127,13 +129,6 @@ Who: Christoph Hellwig <hch@lst.de>
---------------------------
-What: EXPORT_SYMBOL(lookup_hash)
-When: January 2006
-Why: Too low-level interface. Use lookup_one_len or lookup_create instead.
-Who: Christoph Hellwig <hch@lst.de>
-
----------------------------
-
What: CONFIG_FORCED_INLINING
When: June 2006
Why: Config option is there to see if gcc is good enough. (in january
@@ -241,3 +236,15 @@ Why: The USB subsystem has changed a lot over time, and it has been
Who: Greg Kroah-Hartman <gregkh@suse.de>
---------------------------
+
+What: find_trylock_page
+When: January 2007
+Why: The interface no longer has any callers left in the kernel. It
+ is an odd interface (compared with other find_*_page functions), in
+ that it does not take a refcount to the page, only the page lock.
+ It should be replaced with find_get_page or find_lock_page if possible.
+ This feature removal can be reevaluated if users of the interface
+ cannot cleanly use something else.
+Who: Nick Piggin <npiggin@suse.de>
+
+---------------------------
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index 74052d22d86..66fdc0744fe 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -1,27 +1,47 @@
00-INDEX
- this file (info on some of the filesystems supported by linux).
+Exporting
+ - explanation of how to make filesystems exportable.
Locking
- info on locking rules as they pertain to Linux VFS.
adfs.txt
- info and mount options for the Acorn Advanced Disc Filing System.
+afs.txt
+ - info and examples for the distributed AFS (Andrew File System) fs.
affs.txt
- info and mount options for the Amiga Fast File System.
+automount-support.txt
+ - information about filesystem automount support.
+befs.txt
+ - information about the BeOS filesystem for Linux.
bfs.txt
- info for the SCO UnixWare Boot Filesystem (BFS).
cifs.txt
- - description of the CIFS filesystem
+ - description of the CIFS filesystem.
coda.txt
- description of the CODA filesystem.
configfs/
- directory containing configfs documentation and example code.
cramfs.txt
- - info on the cram filesystem for small storage (ROMs etc)
+ - info on the cram filesystem for small storage (ROMs etc).
+dentry-locking.txt
+ - info on the RCU-based dcache locking model.
devfs/
- directory containing devfs documentation.
+directory-locking
+ - info about the locking scheme used for directory operations.
dlmfs.txt
- info on the userspace interface to the OCFS2 DLM.
ext2.txt
- info, mount options and specifications for the Ext2 filesystem.
+ext3.txt
+ - info, mount options and specifications for the Ext3 filesystem.
+files.txt
+ - info on file management in the Linux kernel.
+fuse.txt
+ - info on the Filesystem in User SpacE including mount options.
+hfs.txt
+ - info on the Macintosh HFS Filesystem for Linux.
hpfs.txt
- info and mount options for the OS/2 HPFS.
isofs.txt
@@ -32,23 +52,43 @@ ncpfs.txt
- info on Novell Netware(tm) filesystem using NCP protocol.
ntfs.txt
- info and mount options for the NTFS filesystem (Windows NT).
-proc.txt
- - info on Linux's /proc filesystem.
ocfs2.txt
- info and mount options for the OCFS2 clustered filesystem.
+porting
+ - various information on filesystem porting.
+proc.txt
+ - info on Linux's /proc filesystem.
+ramfs-rootfs-initramfs.txt
+ - info on the 'in memory' filesystems ramfs, rootfs and initramfs.
+reiser4.txt
+ - info on the Reiser4 filesystem based on dancing tree algorithms.
+relayfs.txt
+ - info on relayfs, for efficient streaming from kernel to user space.
romfs.txt
- - Description of the ROMFS filesystem.
+ - description of the ROMFS filesystem.
smbfs.txt
- - info on using filesystems with the SMB protocol (Windows 3.11 and NT)
+ - info on using filesystems with the SMB protocol (Win 3.11 and NT).
+spufs.txt
+ - info and mount options for the SPU filesystem used on Cell.
+sysfs-pci.txt
+ - info on accessing PCI device resources through sysfs.
+sysfs.txt
+ - info on sysfs, a ram-based filesystem for exporting kernel objects.
sysv-fs.txt
- info on the SystemV/V7/Xenix/Coherent filesystem.
+tmpfs.txt
+ - info on tmpfs, a filesystem that holds all files in virtual memory.
udf.txt
- info and mount options for the UDF filesystem.
ufs.txt
- info on the ufs filesystem.
+v9fs.txt
+ - v9fs is a Unix implementation of the Plan 9 9p remote fs protocol.
vfat.txt
- info on using the VFAT filesystem used in Windows NT and Windows 95
vfs.txt
- - Overview of the Virtual File System
+ - overview of the Virtual File System
xfs.txt
- info and mount options for the XFS filesystem.
+xip.txt
+ - info on execute-in-place for file mappings.
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index c8bce82ddca..89b1d196ca8 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -246,6 +246,7 @@ class/
devices/
firmware/
net/
+fs/
devices/ contains a filesystem representation of the device tree. It maps
directly to the internal kernel device tree, which is a hierarchy of
@@ -264,6 +265,10 @@ drivers/ contains a directory for each device driver that is loaded
for devices on that particular bus (this assumes that drivers do not
span multiple bus types).
+fs/ contains a directory for some filesystems. Currently each
+filesystem wanting to export attributes must create its own hierarchy
+below fs/ (see ./fuse.txt for an example).
+
More information can driver-model specific features can be found in
Documentation/driver-model/.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index adaa899e5c9..3a2e5520c1e 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -694,7 +694,7 @@ struct file_operations
----------------------
This describes how the VFS can manipulate an open file. As of kernel
-2.6.13, the following members are defined:
+2.6.17, the following members are defined:
struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
@@ -723,6 +723,10 @@ 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);
};
Again, all methods are called without any locks being held, unless
@@ -790,6 +794,12 @@ otherwise noted.
flock: called by the flock(2) system call
+ splice_write: called by the VFS to splice data from a pipe to a file. This
+ method is used by the splice(2) system call
+
+ splice_read: called by the VFS to splice data from file to a pipe. This
+ method is used by the splice(2) system call
+
Note that the file operations are implemented by the specific
filesystem in which the inode resides. When opening a device node
(character or block special) most filesystems will call special
diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README
index 43e836c07ae..e9cc8bb26f7 100644
--- a/Documentation/firmware_class/README
+++ b/Documentation/firmware_class/README
@@ -105,20 +105,3 @@
on the setup, so I think that the choice on what firmware to make
persistent should be left to userspace.
- - Why register_firmware()+__init can be useful:
- - For boot devices needing firmware.
- - To make the transition easier:
- The firmware can be declared __init and register_firmware()
- called on module_init. Then the firmware is warranted to be
- there even if "firmware hotplug userspace" is not there yet or
- it doesn't yet provide the needed firmware.
- Once the firmware is widely available in userspace, it can be
- removed from the kernel. Or made optional (CONFIG_.*_FIRMWARE).
-
- In either case, if firmware hotplug support is there, it can move the
- firmware out of kernel memory into the real filesystem for later
- usage.
-
- Note: If persistence is implemented on top of initramfs,
- register_firmware() may not be appropriate.
-
diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c
index ad3edaba453..87feccdb5c9 100644
--- a/Documentation/firmware_class/firmware_sample_driver.c
+++ b/Documentation/firmware_class/firmware_sample_driver.c
@@ -5,8 +5,6 @@
*
* Sample code on how to use request_firmware() from drivers.
*
- * Note that register_firmware() is currently useless.
- *
*/
#include <linux/module.h>
@@ -17,11 +15,6 @@
#include "linux/firmware.h"
-#define WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE
-#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE
-char __init inkernel_firmware[] = "let's say that this is firmware\n";
-#endif
-
static struct device ghost_device = {
.bus_id = "ghost0",
};
@@ -104,10 +97,6 @@ static void sample_probe_async(void)
static int sample_init(void)
{
-#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE
- register_firmware("sample_driver_fw", inkernel_firmware,
- sizeof(inkernel_firmware));
-#endif
device_initialize(&ghost_device);
/* since there is no real hardware insertion I just call the
* sample probe functions here */
diff --git a/Documentation/fujitsu/frv/kernel-ABI.txt b/Documentation/fujitsu/frv/kernel-ABI.txt
index 0ed9b0a779b..8b0a5fc8bfd 100644
--- a/Documentation/fujitsu/frv/kernel-ABI.txt
+++ b/Documentation/fujitsu/frv/kernel-ABI.txt
@@ -1,17 +1,19 @@
- =================================
- INTERNAL KERNEL ABI FOR FR-V ARCH
- =================================
-
-The internal FRV kernel ABI is not quite the same as the userspace ABI. A number of the registers
-are used for special purposed, and the ABI is not consistent between modules vs core, and MMU vs
-no-MMU.
-
-This partly stems from the fact that FRV CPUs do not have a separate supervisor stack pointer, and
-most of them do not have any scratch registers, thus requiring at least one general purpose
-register to be clobbered in such an event. Also, within the kernel core, it is possible to simply
-jump or call directly between functions using a relative offset. This cannot be extended to modules
-for the displacement is likely to be too far. Thus in modules the address of a function to call
-must be calculated in a register and then used, requiring two extra instructions.
+ =================================
+ INTERNAL KERNEL ABI FOR FR-V ARCH
+ =================================
+
+The internal FRV kernel ABI is not quite the same as the userspace ABI. A
+number of the registers are used for special purposed, and the ABI is not
+consistent between modules vs core, and MMU vs no-MMU.
+
+This partly stems from the fact that FRV CPUs do not have a separate
+supervisor stack pointer, and most of them do not have any scratch
+registers, thus requiring at least one general purpose register to be
+clobbered in such an event. Also, within the kernel core, it is possible to
+simply jump or call directly between functions using a relative offset.
+This cannot be extended to modules for the displacement is likely to be too
+far. Thus in modules the address of a function to call must be calculated
+in a register and then used, requiring two extra instructions.
This document has the following sections:
@@ -39,7 +41,8 @@ When a system call is made, the following registers are effective:
CPU OPERATING MODES
===================
-The FR-V CPU has three basic operating modes. In order of increasing capability:
+The FR-V CPU has three basic operating modes. In order of increasing
+capability:
(1) User mode.
@@ -47,42 +50,46 @@ The FR-V CPU has three basic operating modes. In order of increasing capability:
(2) Kernel mode.
- Normal kernel mode. There are many additional control registers available that may be
- accessed in this mode, in addition to all the stuff available to user mode. This has two
- submodes:
+ Normal kernel mode. There are many additional control registers
+ available that may be accessed in this mode, in addition to all the
+ stuff available to user mode. This has two submodes:
(a) Exceptions enabled (PSR.T == 1).
- Exceptions will invoke the appropriate normal kernel mode handler. On entry to the
- handler, the PSR.T bit will be cleared.
+ Exceptions will invoke the appropriate normal kernel mode
+ handler. On entry to the handler, the PSR.T bit will be cleared.
(b) Exceptions disabled (PSR.T == 0).
- No exceptions or interrupts may happen. Any mandatory exceptions will cause the CPU to
- halt unless the CPU is told to jump into debug mode instead.
+ No exceptions or interrupts may happen. Any mandatory exceptions
+ will cause the CPU to halt unless the CPU is told to jump into
+ debug mode instead.
(3) Debug mode.
- No exceptions may happen in this mode. Memory protection and management exceptions will be
- flagged for later consideration, but the exception handler won't be invoked. Debugging traps
- such as hardware breakpoints and watchpoints will be ignored. This mode is entered only by
- debugging events obtained from the other two modes.
+ No exceptions may happen in this mode. Memory protection and
+ management exceptions will be flagged for later consideration, but
+ the exception handler won't be invoked. Debugging traps such as
+ hardware breakpoints and watchpoints will be ignored. This mode is
+ entered only by debugging events obtained from the other two modes.
- All kernel mode registers may be accessed, plus a few extra debugging specific registers.
+ All kernel mode registers may be accessed, plus a few extra debugging
+ specific registers.
=================================
INTERNAL KERNEL-MODE REGISTER ABI
=================================
-There are a number of permanent register assignments that are set up by entry.S in the exception
-prologue. Note that there is a complete set of exception prologues for each of user->kernel
-transition and kernel->kernel transition. There are also user->debug and kernel->debug mode
-transition prologues.
+There are a number of permanent register assignments that are set up by
+entry.S in the exception prologue. Note that there is a complete set of
+exception prologues for each of user->kernel transition and kernel->kernel
+transition. There are also user->debug and kernel->debug mode transition
+prologues.
REGISTER FLAVOUR USE
- =============== ======= ====================================================
+ =============== ======= ==============================================
GR1 Supervisor stack pointer
GR15 Current thread info pointer
GR16 GP-Rel base register for small data
@@ -92,10 +99,12 @@ transition prologues.
GR31 NOMMU Destroyed by debug mode entry
GR31 MMU Destroyed by TLB miss kernel mode entry
CCR.ICC2 Virtual interrupt disablement tracking
- CCCR.CC3 Cleared by exception prologue (atomic op emulation)
+ CCCR.CC3 Cleared by exception prologue
+ (atomic op emulation)
SCR0 MMU See mmu-layout.txt.
SCR1 MMU See mmu-layout.txt.
- SCR2 MMU Save for EAR0 (destroyed by icache insns in debug mode)
+ SCR2 MMU Save for EAR0 (destroyed by icache insns
+ in debug mode)
SCR3 MMU Save for GR31 during debug exceptions
DAMR/IAMR NOMMU Fixed memory protection layout.
DAMR/IAMR MMU See mmu-layout.txt.
@@ -104,18 +113,21 @@ transition prologues.
Certain registers are also used or modified across function calls:
REGISTER CALL RETURN
- =============== =============================== ===============================
+ =============== =============================== ======================
GR0 Fixed Zero -
GR2 Function call frame pointer
GR3 Special Preserved
GR3-GR7 - Clobbered
- GR8 Function call arg #1 Return value (or clobbered)
- GR9 Function call arg #2 Return value MSW (or clobbered)
+ GR8 Function call arg #1 Return value
+ (or clobbered)
+ GR9 Function call arg #2 Return value MSW
+ (or clobbered)
GR10-GR13 Function call arg #3-#6 Clobbered
GR14 - Clobbered
GR15-GR16 Special Preserved
GR17-GR27 - Preserved
- GR28-GR31 Special Only accessed explicitly
+ GR28-GR31 Special Only accessed
+ explicitly
LR Return address after CALL Clobbered
CCR/CCCR - Mostly Clobbered
@@ -124,46 +136,53 @@ Certain registers are also used or modified across function calls:
INTERNAL DEBUG-MODE REGISTER ABI
================================
-This is the same as the kernel-mode register ABI for functions calls. The difference is that in
-debug-mode there's a different stack and a different exception frame. Almost all the global
-registers from kernel-mode (including the stack pointer) may be changed.
+This is the same as the kernel-mode register ABI for functions calls. The
+difference is that in debug-mode there's a different stack and a different
+exception frame. Almost all the global registers from kernel-mode
+(including the stack pointer) may be changed.
REGISTER FLAVOUR USE
- =============== ======= ====================================================
+ =============== ======= ==============================================
GR1 Debug stack pointer
GR16 GP-Rel base register for small data
- GR31 Current debug exception frame pointer (__debug_frame)
+ GR31 Current debug exception frame pointer
+ (__debug_frame)
SCR3 MMU Saved value of GR31
-Note that debug mode is able to interfere with the kernel's emulated atomic ops, so it must be
-exceedingly careful not to do any that would interact with the main kernel in this regard. Hence
-the debug mode code (gdbstub) is almost completely self-contained. The only external code used is
-the sprintf family of functions.
+Note that debug mode is able to interfere with the kernel's emulated atomic
+ops, so it must be exceedingly careful not to do any that would interact
+with the main kernel in this regard. Hence the debug mode code (gdbstub) is
+almost completely self-contained. The only external code used is the
+sprintf family of functions.
-Futhermore, break.S is so complicated because single-step mode does not switch off on entry to an
-exception. That means unless manually disabled, single-stepping will blithely go on stepping into
-things like interrupts. See gdbstub.txt for more information.
+Futhermore, break.S is so complicated because single-step mode does not
+switch off on entry to an exception. That means unless manually disabled,
+single-stepping will blithely go on stepping into things like interrupts.
+See gdbstub.txt for more information.
==========================
VIRTUAL INTERRUPT HANDLING
==========================
-Because accesses to the PSR is so slow, and to disable interrupts we have to access it twice (once
-to read and once to write), we don't actually disable interrupts at all if we don't have to. What
-we do instead is use the ICC2 condition code flags to note virtual disablement, such that if we
-then do take an interrupt, we note the flag, really disable interrupts, set another flag and resume
-execution at the point the interrupt happened. Setting condition flags as a side effect of an
-arithmetic or logical instruction is really fast. This use of the ICC2 only occurs within the
+Because accesses to the PSR is so slow, and to disable interrupts we have
+to access it twice (once to read and once to write), we don't actually
+disable interrupts at all if we don't have to. What we do instead is use
+the ICC2 condition code flags to note virtual disablement, such that if we
+then do take an interrupt, we note the flag, really disable interrupts, set
+another flag and resume execution at the point the interrupt happened.
+Setting condition flags as a side effect of an arithmetic or logical
+instruction is really fast. This use of the ICC2 only occurs within the
kernel - it does not affect userspace.
The flags we use are:
(*) CCR.ICC2.Z [Zero flag]
- Set to virtually disable interrupts, clear when interrupts are virtually enabled. Can be
- modified by logical instructions without affecting the Carry flag.
+ Set to virtually disable interrupts, clear when interrupts are
+ virtually enabled. Can be modified by logical instructions without
+ affecting the Carry flag.
(*) CCR.ICC2.C [Carry flag]
@@ -176,8 +195,9 @@ What happens is this:
ICC2.Z is 0, ICC2.C is 1.
- (2) An interrupt occurs. The exception prologue examines ICC2.Z and determines that nothing needs
- doing. This is done simply with an unlikely BEQ instruction.
+ (2) An interrupt occurs. The exception prologue examines ICC2.Z and
+ determines that nothing needs doing. This is done simply with an
+ unlikely BEQ instruction.
(3) The interrupts are disabled (local_irq_disable)
@@ -187,48 +207,56 @@ What happens is this:
ICC2.Z would be set to 0.
- A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would be used to trap if
- interrupts were now virtually enabled, but physically disabled - which they're not, so the
- trap isn't taken. The kernel would then be back to state (1).
+ A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would
+ be used to trap if interrupts were now virtually enabled, but
+ physically disabled - which they're not, so the trap isn't taken. The
+ kernel would then be back to state (1).
- (5) An interrupt occurs. The exception prologue examines ICC2.Z and determines that the interrupt
- shouldn't actually have happened. It jumps aside, and there disabled interrupts by setting
- PSR.PIL to 14 and then it clears ICC2.C.
+ (5) An interrupt occurs. The exception prologue examines ICC2.Z and
+ determines that the interrupt shouldn't actually have happened. It
+ jumps aside, and there disabled interrupts by setting PSR.PIL to 14
+ and then it clears ICC2.C.
(6) If interrupts were then saved and disabled again (local_irq_save):
- ICC2.Z would be shifted into the save variable and masked off (giving a 1).
+ ICC2.Z would be shifted into the save variable and masked off
+ (giving a 1).
- ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be unaffected (ie: 0).
+ ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be
+ unaffected (ie: 0).
(7) If interrupts were then restored from state (6) (local_irq_restore):
- ICC2.Z would be set to indicate the result of XOR'ing the saved value (ie: 1) with 1, which
- gives a result of 0 - thus leaving ICC2.Z set.
+ ICC2.Z would be set to indicate the result of XOR'ing the saved
+ value (ie: 1) with 1, which gives a result of 0 - thus leaving
+ ICC2.Z set.
ICC2.C would remain unaffected (ie: 0).
- A TIHI #2 instruction would be used to again assay the current state, but this would do
- nothing as Z==1.
+ A TIHI #2 instruction would be used to again assay the current state,
+ but this would do nothing as Z==1.
(8) If interrupts were then enabled (local_irq_enable):
- ICC2.Z would be cleared. ICC2.C would be left unaffected. Both flags would now be 0.
+ ICC2.Z would be cleared. ICC2.C would be left unaffected. Both
+ flags would now be 0.
- A TIHI #2 instruction again issued to assay the current state would then trap as both Z==0
- [interrupts virtually enabled] and C==0 [interrupts really disabled] would then be true.
+ A TIHI #2 instruction again issued to assay the current state would
+ then trap as both Z==0 [interrupts virtually enabled] and C==0
+ [interrupts really disabled] would then be true.
- (9) The trap #2 handler would simply enable hardware interrupts (set PSR.PIL to 0), set ICC2.C to
- 1 and return.
+ (9) The trap #2 handler would simply enable hardware interrupts
+ (set PSR.PIL to 0), set ICC2.C to 1 and return.
(10) Immediately upon returning, the pending interrupt would be taken.
-(11) The interrupt handler would take the path of actually processing the interrupt (ICC2.Z is
- clear, BEQ fails as per step (2)).
+(11) The interrupt handler would take the path of actually processing the
+ interrupt (ICC2.Z is clear, BEQ fails as per step (2)).
-(12) The interrupt handler would then set ICC2.C to 1 since hardware interrupts are definitely
- enabled - or else the kernel wouldn't be here.
+(12) The interrupt handler would then set ICC2.C to 1 since hardware
+ interrupts are definitely enabled - or else the kernel wouldn't be here.
(13) On return from the interrupt handler, things would be back to state (1).
-This trap (#2) is only available in kernel mode. In user mode it will result in SIGILL.
+This trap (#2) is only available in kernel mode. In user mode it will
+result in SIGILL.
diff --git a/Documentation/i2c/busses/i2c-parport b/Documentation/i2c/busses/i2c-parport
index d9f23c0763f..77b995dfca2 100644
--- a/Documentation/i2c/busses/i2c-parport
+++ b/Documentation/i2c/busses/i2c-parport
@@ -12,18 +12,22 @@ meant as a replacement for the older, individual drivers:
teletext adapters)
It currently supports the following devices:
- * Philips adapter
- * home brew teletext adapter
- * Velleman K8000 adapter
- * ELV adapter
- * Analog Devices evaluation boards (ADM1025, ADM1030, ADM1031, ADM1032)
- * Barco LPT->DVI (K5800236) adapter
+ * (type=0) Philips adapter
+ * (type=1) home brew teletext adapter
+ * (type=2) Velleman K8000 adapter
+ * (type=3) ELV adapter
+ * (type=4) Analog Devices ADM1032 evaluation board
+ * (type=5) Analog Devices evaluation boards: ADM1025, ADM1030, ADM1031
+ * (type=6) Barco LPT->DVI (K5800236) adapter
These devices use different pinout configurations, so you have to tell
the driver what you have, using the type module parameter. There is no
way to autodetect the devices. Support for different pinout configurations
can be easily added when needed.
+Earlier kernels defaulted to type=0 (Philips). But now, if the type
+parameter is missing, the driver will simply fail to initialize.
+
Building your own adapter
-------------------------
diff --git a/Documentation/input/joystick-parport.txt b/Documentation/input/joystick-parport.txt
index 88a011c9f98..d537c48cc6d 100644
--- a/Documentation/input/joystick-parport.txt
+++ b/Documentation/input/joystick-parport.txt
@@ -36,12 +36,12 @@ with them.
All NES and SNES use the same synchronous serial protocol, clocked from
the computer's side (and thus timing insensitive). To allow up to 5 NES
-and/or SNES gamepads connected to the parallel port at once, the output
-lines of the parallel port are shared, while one of 5 available input lines
-is assigned to each gamepad.
+and/or SNES gamepads and/or SNES mice connected to the parallel port at once,
+the output lines of the parallel port are shared, while one of 5 available
+input lines is assigned to each gamepad.
This protocol is handled by the gamecon.c driver, so that's the one
-you'll use for NES and SNES gamepads.
+you'll use for NES, SNES gamepads and SNES mice.
The main problem with PC parallel ports is that they don't have +5V power
source on any of their pins. So, if you want a reliable source of power
@@ -106,7 +106,7 @@ A, Turbo B, Select and Start, and is connected through 5 wires, then it is
either a NES or NES clone and will work with this connection. SNES gamepads
also use 5 wires, but have more buttons. They will work as well, of course.
-Pinout for NES gamepads Pinout for SNES gamepads
+Pinout for NES gamepads Pinout for SNES gamepads and mice
+----> Power +-----------------------\
| 7 | o o o o | x x o | 1
@@ -454,6 +454,7 @@ uses the following kernel/module command line:
6 | N64 pad
7 | Sony PSX controller
8 | Sony PSX DDR controller
+ 9 | SNES mouse
The exact type of the PSX controller type is autoprobed when used so
hot swapping should work (but is not recomended).
diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
index aa7ba00ec08..171a44ebd93 100644
--- a/Documentation/ioctl-number.txt
+++ b/Documentation/ioctl-number.txt
@@ -78,8 +78,6 @@ Code Seq# Include File Comments
'#' 00-3F IEEE 1394 Subsystem Block for the entire subsystem
'1' 00-1F <linux/timepps.h> PPS kit from Ulrich Windl
<ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/>
-'6' 00-10 <asm-i386/processor.h> Intel IA32 microcode update driver
- <mailto:tigran@veritas.com>
'8' all SNP8023 advanced NIC card
<mailto:mcr@solidum.com>
'A' 00-1F linux/apm_bios.h
diff --git a/Documentation/isdn/README.gigaset b/Documentation/isdn/README.gigaset
new file mode 100644
index 00000000000..85a64defd38
--- /dev/null
+++ b/Documentation/isdn/README.gigaset
@@ -0,0 +1,286 @@
+GigaSet 307x Device Driver
+==========================
+
+1. Requirements
+ ------------
+1.1. Hardware
+ --------
+ This release supports the connection of the Gigaset 307x/417x family of
+ ISDN DECT bases via Gigaset M101 Data, Gigaset M105 Data or direct USB
+ connection. The following devices are reported to be compatible:
+ 307x/417x:
+ Gigaset SX255isdn
+ Gigaset SX353isdn
+ Sinus 45 [AB] isdn (Deutsche Telekom)
+ Sinus 721X/XA
+ Vox Chicago 390 ISDN (KPN Telecom)
+ M101:
+ Sinus 45 Data 1 (Telekom)
+ M105:
+ Gigaset USB Adapter DECT
+ Sinus 45 Data 2 (Telekom)
+ Sinus 721 data
+ Chicago 390 USB (KPN)
+ See also http://www.erbze.info/sinus_gigaset.htm and
+ http://gigaset307x.sourceforge.net/
+
+ We had also reports from users of Gigaset M105 who could use the drivers
+ with SX 100 and CX 100 ISDN bases (only in unimodem mode, see section 2.4.)
+ If you have another device that works with our driver, please let us know.
+ For example, Gigaset SX205isdn/Sinus 721 X SE and Gigaset SX303isdn bases
+ are just versions without answering machine of models known to work, so
+ they should work just as well; but so far we are lacking positive reports
+ on these.
+
+ Chances of getting an USB device to work are good if the output of
+ lsusb
+ at the command line contains one of the following:
+ ID 0681:0001
+ ID 0681:0002
+ ID 0681:0009
+ ID 0681:0021
+ ID 0681:0022
+
+1.2. Software
+ --------
+ The driver works with ISDN4linux and so can be used with any software
+ which is able to use ISDN4linux for ISDN connections (voice or data).
+ CAPI4Linux support is planned but not yet available.
+
+ There are some user space tools available at
+ http://sourceforge.net/projects/gigaset307x/
+ which provide access to additional device specific functions like SMS,
+ phonebook or call journal.
+
+
+2. How to use the driver
+ ---------------------
+2.1. Modules
+ -------
+ To get the device working, you have to load the proper kernel module. You
+ can do this using
+ modprobe modulename
+ where modulename is usb_gigaset (M105) or bas_gigaset (direct USB
+ connection to the base).
+
+2.2. Device nodes for user space programs
+ ------------------------------------
+ The device can be accessed from user space (eg. by the user space tools
+ mentioned in 1.2.) through the device nodes:
+
+ - /dev/ttyGU0 for M105 (USB data boxes)
+ - /dev/ttyGB0 for the base driver (direct USB connection)
+
+ You can also select a "default device" which is used by the frontends when
+ no device node is given as parameter, by creating a symlink /dev/ttyG to
+ one of them, eg.:
+
+ ln -s /dev/ttyGB0 /dev/ttyG
+
+2.3. ISDN4linux
+ ----------
+ This is the "normal" mode of operation. After loading the module you can
+ set up the ISDN system just as you'd do with any ISDN card.
+ Your distribution should provide some configuration utility.
+ If not, you can use some HOWTOs like
+ http://www.linuxhaven.de/dlhp/HOWTO/DE-ISDN-HOWTO-5.html
+ If this doesn't work, because you have some recent device like SX100 where
+ debug output (see section 3.2.) shows something like this when dialing
+ CMD Received: ERROR
+ Available Params: 0
+ Connection State: 0, Response: -1
+ gigaset_process_response: resp_code -1 in ConState 0 !
+ Timeout occurred
+ you might need to use unimodem mode:
+
+2.4. Unimodem mode
+ -------------
+ This is needed for some devices [e.g. SX100] as they have problems with
+ the "normal" commands.
+
+ If you have installed the command line tool gigacontr, you can enter
+ unimodem mode using
+ gigacontr --mode unimodem
+ You can switch back using
+ gigacontr --mode isdn
+
+ You can also load the driver using e.g.
+ modprobe usb_gigaset startmode=0
+ to prevent the driver from starting in "isdn4linux mode".
+
+ In this mode the device works like a modem connected to a serial port
+ (the /dev/ttyGU0, ... mentioned above) which understands the commands
+ ATZ init, reset
+ => OK or ERROR
+ ATD
+ ATDT dial
+ => OK, CONNECT,
+ BUSY,
+ NO DIAL TONE,
+ NO CARRIER,
+ NO ANSWER
+ <pause>+++<pause> change to command mode when connected
+ ATH hangup
+
+ You can use some configuration tool of your distribution to configure this
+ "modem" or configure pppd/wvdial manually. There are some example ppp
+ configuration files and chat scripts in the gigaset-VERSION/ppp directory.
+ Please note that the USB drivers are not able to change the state of the
+ control lines (the M105 driver can be configured to use some undocumented
+ control requests, if you really need the control lines, though). This means
+ you must use "Stupid Mode" if you are using wvdial or you should use the
+ nocrtscts option of pppd.
+ You must also assure that the ppp_async module is loaded with the parameter
+ flag_time=0. You can do this e.g. by adding a line like
+
+ options ppp_async flag_time=0
+
+ to /etc/modprobe.conf. If your distribution has some local module
+ configuration file like /etc/modprobe.conf.local,
+ using that should be preferred.
+
+2.5. Call-ID (CID) mode
+ ------------------
+ Call-IDs are numbers used to tag commands to, and responses from, the
+ Gigaset base in order to support the simultaneous handling of multiple
+ ISDN calls. Their use can be enabled ("CID mode") or disabled ("Unimodem
+ mode"). Without Call-IDs (in Unimodem mode), only a very limited set of
+ functions is available. It allows outgoing data connections only, but
+ does not signal incoming calls or other base events.
+
+ DECT cordless data devices (M10x) permanently occupy the cordless
+ connection to the base while Call-IDs are activated. As the Gigaset
+ bases only support one DECT data connection at a time, this prevents
+ other DECT cordless data devices from accessing the base.
+
+ During active operation, the driver switches to the necessary mode
+ automatically. However, for the reasons above, the mode chosen when
+ the device is not in use (idle) can be selected by the user.
+ - If you want to receive incoming calls, you can use the default
+ settings (CID mode).
+ - If you have several DECT data devices (M10x) which you want to use
+ in turn, select Unimodem mode by passing the parameter "cidmode=0" to
+ the driver ("modprobe usb_gigaset cidmode=0" or modprobe.conf).
+
+ If you want both of these at once, you are out of luck.
+
+ You can also use /sys/module/<name>/parameters/cidmode for changing
+ the CID mode setting (<name> is usb_gigaset or bas_gigaset).
+
+
+3. Troubleshooting
+ ---------------
+3.1. Solutions to frequently reported problems
+ -----------------------------------------
+ Problem:
+ You have a slow provider and isdn4linux gives up dialing too early.
+ Solution:
+ Load the isdn module using the dialtimeout option. You can do this e.g.
+ by adding a line like
+
+ options isdn dialtimeout=15
+
+ to /etc/modprobe.conf. If your distribution has some local module
+ configuration file like /etc/modprobe.conf.local,
+ using that should be preferred.
+
+ Problem:
+ Your isdn script aborts with a message about isdnlog.
+ Solution:
+ Try deactivating (or commenting out) isdnlog. This driver does not
+ support it.
+
+ Problem:
+ You have two or more DECT data adapters (M101/M105) and only the
+ first one you turn on works.
+ Solution:
+ Select Unimodem mode for all DECT data adapters. (see section 2.4.)
+
+3.2. Telling the driver to provide more information
+ ----------------------------------------------
+ Building the driver with the "Gigaset debugging" kernel configuration
+ option (CONFIG_GIGASET_DEBUG) gives it the ability to produce additional
+ information useful for debugging.
+
+ You can control the amount of debugging information the driver produces by
+ writing an appropriate value to /sys/module/gigaset/parameters/debug, e.g.
+ echo 0 > /sys/module/gigaset/parameters/debug
+ switches off debugging output completely,
+ echo 0x10a020 > /sys/module/gigaset/parameters/debug
+ enables the standard set of debugging output messages. These values are
+ bit patterns where every bit controls a certain type of debugging output.
+ See the constants DEBUG_* in the source file gigaset.h for details.
+
+ The initial value can be set using the debug parameter when loading the
+ module "gigaset", e.g. by adding a line
+ options gigaset debug=0
+ to /etc/modprobe.conf, ...
+
+ Generated debugging information can be found
+ - as output of the command
+ dmesg
+ - in system log files written by your syslog daemon, usually
+ in /var/log/, e.g. /var/log/messages.
+
+3.3. Reporting problems and bugs
+ ---------------------------
+ If you can't solve problems with the driver on your own, feel free to
+ use one of the forums, bug trackers, or mailing lists on
+ http://sourceforge.net/projects/gigaset307x
+ or write an electronic mail to the maintainers.
+
+ Try to provide as much information as possible, such as
+ - distribution
+ - kernel version (uname -r)
+ - gcc version (gcc --version)
+ - hardware architecture (uname -m, ...)
+ - type and firmware version of your device (base and wireless module,
+ if any)
+ - output of "lsusb -v" (if using an USB device)
+ - error messages
+ - relevant system log messages (it would help if you activate debug
+ output as described in 3.2.)
+
+ For help with general configuration problems not specific to our driver,
+ such as isdn4linux and network configuration issues, please refer to the
+ appropriate forums and newsgroups.
+
+3.4. Reporting problem solutions
+ ---------------------------
+ If you solved a problem with our drivers, wrote startup scripts for your
+ distribution, ... feel free to contact us (using one of the places
+ mentioned in 3.3.). We'd like to add scripts, hints, documentation
+ to the driver and/or the project web page.
+
+
+4. Links, other software
+ ---------------------
+ - Sourceforge project developing this driver and associated tools
+ http://sourceforge.net/projects/gigaset307x
+ - Yahoo! Group on the Siemens Gigaset family of devices
+ http://de.groups.yahoo.com/group/Siemens-Gigaset
+ - Siemens Gigaset/T-Sinus compatibility table
+ http://www.erbze.info/sinus_gigaset.htm
+
+
+5. Credits
+ -------
+ Thanks to
+
+ Karsten Keil
+ for his help with isdn4linux
+ Deti Fliegl
+ for his base driver code
+ Dennis Dietrich
+ for his kernel 2.6 patches
+ Andreas Rummel
+ for his work and logs to get unimodem mode working
+ Andreas Degert
+ for his logs and patches to get cx 100 working
+ Dietrich Feist
+ for his generous donation of one M105 and two M101 cordless adapters
+ Christoph Schweers
+ for his generous donation of a M34 device
+
+ and all the other people who sent logs and other information.
+
diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt
index fcccf2432f9..61fc079eb96 100644
--- a/Documentation/kbuild/modules.txt
+++ b/Documentation/kbuild/modules.txt
@@ -44,7 +44,7 @@ What is covered within this file is mainly information to authors
of modules. The author of an external modules should supply
a makefile that hides most of the complexity so one only has to type
'make' to build the module. A complete example will be present in
-chapter ¤. Creating a kbuild file for an external module".
+chapter 4, "Creating a kbuild file for an external module".
=== 2. How to build external modules
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f8cb55c30b0..b3a6187e530 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1,4 +1,4 @@
-February 2003 Kernel Parameters v2.5.59
+ Kernel Parameters
~~~~~~~~~~~~~~~~~
The following is a consolidated list of the kernel parameters as implemented
@@ -17,9 +17,17 @@ are specified on the kernel command line with the module name plus
usbcore.blinkenlights=1
-The text in square brackets at the beginning of the description states the
-restrictions on the kernel for the said kernel parameter to be valid. The
-restrictions referred to are that the relevant option is valid if:
+This document may not be entirely up to date and comprehensive. The command
+"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
+module. Loadable modules, after being loaded into the running kernel, also
+reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
+parameters may be changed at runtime by the command
+"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
+
+The parameters listed below are only valid if certain kernel build options were
+enabled and if respective hardware is present. The text in square brackets at
+the beginning of each description states the restrictions within which a
+parameter is applicable:
ACPI ACPI support is enabled.
ALSA ALSA sound support is enabled.
@@ -1046,10 +1054,10 @@ running once the system is up.
noltlbs [PPC] Do not use large page/tlb entries for kernel
lowmem mapping on PPC40x.
- nomce [IA-32] Machine Check Exception
-
nomca [IA-64] Disable machine check abort handling
+ nomce [IA-32] Machine Check Exception
+
noresidual [PPC] Don't use residual data on PReP machines.
noresume [SWSUSP] Disables resume and restores original swap
@@ -1682,20 +1690,6 @@ running once the system is up.
______________________________________________________________________
-Changelog:
-
-2000-06-?? Mr. Unknown
- The last known update (for 2.4.0) - the changelog was not kept before.
-
-2002-11-24 Petr Baudis <pasky@ucw.cz>
- Randy Dunlap <randy.dunlap@verizon.net>
- Update for 2.5.49, description for most of the options introduced,
- references to other documentation (C files, READMEs, ..), added S390,
- PPC, SPARC, MTD, ALSA and OSS category. Minor corrections and
- reformatting.
-
-2005-10-19 Randy Dunlap <rdunlap@xenotime.net>
- Lots of typos, whitespace, some reformatting.
TODO:
diff --git a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt
index b18e2167590..5696e879449 100644
--- a/Documentation/laptop-mode.txt
+++ b/Documentation/laptop-mode.txt
@@ -919,11 +919,11 @@ int main(int argc, char **argv)
int settle_time = 60;
/* Parse the simple command-line */
- if (ac == 2)
- disk = av[1];
- else if (ac == 4) {
- settle_time = atoi(av[2]);
- disk = av[3];
+ if (argc == 2)
+ disk = argv[1];
+ else if (argc == 4) {
+ settle_time = atoi(argv[2]);
+ disk = argv[3];
} else
usage();
diff --git a/Documentation/leds-class.txt b/Documentation/leds-class.txt
new file mode 100644
index 00000000000..8c35c042611
--- /dev/null
+++ b/Documentation/leds-class.txt
@@ -0,0 +1,71 @@
+LED handling under Linux
+========================
+
+If you're reading this and thinking about keyboard leds, these are
+handled by the input subsystem and the led class is *not* needed.
+
+In its simplest form, the LED class just allows control of LEDs from
+userspace. LEDs appear in /sys/class/leds/. The brightness file will
+set the brightness of the LED (taking a value 0-255). Most LEDs don't
+have hardware brightness support so will just be turned on for non-zero
+brightness settings.
+
+The class also introduces the optional concept of an LED trigger. A trigger
+is a kernel based source of led events. Triggers can either be simple or
+complex. A simple trigger isn't configurable and is designed to slot into
+existing subsystems with minimal additional code. Examples are the ide-disk,
+nand-disk and sharpsl-charge triggers. With led triggers disabled, the code
+optimises away.
+
+Complex triggers whilst available to all LEDs have LED specific
+parameters and work on a per LED basis. The timer trigger is an example.
+
+You can change triggers in a similar manner to the way an IO scheduler
+is chosen (via /sys/class/leds/<device>/trigger). Trigger specific
+parameters can appear in /sys/class/leds/<device> once a given trigger is
+selected.
+
+
+Design Philosophy
+=================
+
+The underlying design philosophy is simplicity. LEDs are simple devices
+and the aim is to keep a small amount of code giving as much functionality
+as possible. Please keep this in mind when suggesting enhancements.
+
+
+LED Device Naming
+=================
+
+Is currently of the form:
+
+"devicename:colour"
+
+There have been calls for LED properties such as colour to be exported as
+individual led class attributes. As a solution which doesn't incur as much
+overhead, I suggest these become part of the device name. The naming scheme
+above leaves scope for further attributes should they be needed.
+
+
+Known Issues
+============
+
+The LED Trigger core cannot be a module as the simple trigger functions
+would cause nightmare dependency issues. I see this as a minor issue
+compared to the benefits the simple trigger functionality brings. The
+rest of the LED subsystem can be modular.
+
+Some leds can be programmed to flash in hardware. As this isn't a generic
+LED device property, this should be exported as a device specific sysfs
+attribute rather than part of the class if this functionality is required.
+
+
+Future Development
+==================
+
+At the moment, a trigger can't be created specifically for a single LED.
+There are a number of cases where a trigger might only be mappable to a
+particular LED (ACPI?). The addition of triggers provided by the LED driver
+should cover this option and be possible to add without breaking the
+current interface.
+
diff --git a/Documentation/m68k/README.buddha b/Documentation/m68k/README.buddha
index bf802ffc98a..ef484a719bb 100644
--- a/Documentation/m68k/README.buddha
+++ b/Documentation/m68k/README.buddha
@@ -29,7 +29,7 @@ address is written to $4a, then the whole Byte is written to
$48, while it doesn't matter how often you're writing to $4a
as long as $48 is not touched. After $48 has been written,
the whole card disappears from $e8 and is mapped to the new
-address just written. Make shure $4a is written before $48,
+address just written. Make sure $4a is written before $48,
otherwise your chance is only 1:16 to find the board :-).
The local memory-map is even active when mapped to $e8:
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
new file mode 100644
index 00000000000..4710845dbac
--- /dev/null
+++ b/Documentation/memory-barriers.txt
@@ -0,0 +1,2133 @@
+ ============================
+ LINUX KERNEL MEMORY BARRIERS
+ ============================
+
+By: David Howells <dhowells@redhat.com>
+
+Contents:
+
+ (*) Abstract memory access model.
+
+ - Device operations.
+ - Guarantees.
+
+ (*) What are memory barriers?
+
+ - Varieties of memory barrier.
+ - What may not be assumed about memory barriers?
+ - Data dependency barriers.
+ - Control dependencies.
+ - SMP barrier pairing.
+ - Examples of memory barrier sequences.
+ - Read memory barriers vs load speculation.
+
+ (*) Explicit kernel barriers.
+
+ - Compiler barrier.
+ - The CPU memory barriers.
+ - MMIO write barrier.
+
+ (*) Implicit kernel memory barriers.
+
+ - Locking functions.
+ - Interrupt disabling functions.
+ - Miscellaneous functions.
+
+ (*) Inter-CPU locking barrier effects.
+
+ - Locks vs memory accesses.
+ - Locks vs I/O accesses.
+
+ (*) Where are memory barriers needed?
+
+ - Interprocessor interaction.
+ - Atomic operations.
+ - Accessing devices.
+ - Interrupts.
+
+ (*) Kernel I/O barrier effects.
+
+ (*) Assumed minimum execution ordering model.
+
+ (*) The effects of the cpu cache.
+
+ - Cache coherency.
+ - Cache coherency vs DMA.
+ - Cache coherency vs MMIO.
+
+ (*) The things CPUs get up to.
+
+ - And then there's the Alpha.
+
+ (*) References.
+
+
+============================
+ABSTRACT MEMORY ACCESS MODEL
+============================
+
+Consider the following abstract model of the system:
+
+ : :
+ : :
+ : :
+ +-------+ : +--------+ : +-------+
+ | | : | | : | |
+ | | : | | : | |
+ | CPU 1 |<----->| Memory |<----->| CPU 2 |
+ | | : | | : | |
+ | | : | | : | |
+ +-------+ : +--------+ : +-------+
+ ^ : ^ : ^
+ | : | : |
+ | : | : |
+ | : v : |
+ | : +--------+ : |
+ | : | | : |
+ | : | | : |
+ +---------->| Device |<----------+
+ : | | :
+ : | | :
+ : +--------+ :
+ : :
+
+Each CPU executes a program that generates memory access operations. In the
+abstract CPU, memory operation ordering is very relaxed, and a CPU may actually
+perform the memory operations in any order it likes, provided program causality
+appears to be maintained. Similarly, the compiler may also arrange the
+instructions it emits in any order it likes, provided it doesn't affect the
+apparent operation of the program.
+
+So in the above diagram, the effects of the memory operations performed by a
+CPU are perceived by the rest of the system as the operations cross the
+interface between the CPU and rest of the system (the dotted lines).
+
+
+For example, consider the following sequence of events:
+
+ CPU 1 CPU 2
+ =============== ===============
+ { A == 1; B == 2 }
+ A = 3; x = A;
+ B = 4; y = B;
+
+The set of accesses as seen by the memory system in the middle can be arranged
+in 24 different combinations:
+
+ STORE A=3, STORE B=4, x=LOAD A->3, y=LOAD B->4
+ STORE A=3, STORE B=4, y=LOAD B->4, x=LOAD A->3
+ STORE A=3, x=LOAD A->3, STORE B=4, y=LOAD B->4
+ STORE A=3, x=LOAD A->3, y=LOAD B->2, STORE B=4
+ STORE A=3, y=LOAD B->2, STORE B=4, x=LOAD A->3
+ STORE A=3, y=LOAD B->2, x=LOAD A->3, STORE B=4
+ STORE B=4, STORE A=3, x=LOAD A->3, y=LOAD B->4
+ STORE B=4, ...
+ ...
+
+and can thus result in four different combinations of values:
+
+ x == 1, y == 2
+ x == 1, y == 4
+ x == 3, y == 2
+ x == 3, y == 4
+
+
+Furthermore, the stores committed by a CPU to the memory system may not be
+perceived by the loads made by another CPU in the same order as the stores were
+committed.
+
+
+As a further example, consider this sequence of events:
+
+ CPU 1 CPU 2
+ =============== ===============
+ { A == 1, B == 2, C = 3, P == &A, Q == &C }
+ B = 4; Q = P;
+ P = &B D = *Q;
+
+There is an obvious data dependency here, as the value loaded into D depends on
+the address retrieved from P by CPU 2. At the end of the sequence, any of the
+following results are possible:
+
+ (Q == &A) and (D == 1)
+ (Q == &B) and (D == 2)
+ (Q == &B) and (D == 4)
+
+Note that CPU 2 will never try and load C into D because the CPU will load P
+into Q before issuing the load of *Q.
+
+
+DEVICE OPERATIONS
+-----------------
+
+Some devices present their control interfaces as collections of memory
+locations, but the order in which the control registers are accessed is very
+important. For instance, imagine an ethernet card with a set of internal
+registers that are accessed through an address port register (A) and a data
+port register (D). To read internal register 5, the following code might then
+be used:
+
+ *A = 5;
+ x = *D;
+
+but this might show up as either of the following two sequences:
+
+ STORE *A = 5, x = LOAD *D
+ x = LOAD *D, STORE *A = 5
+
+the second of which will almost certainly result in a malfunction, since it set
+the address _after_ attempting to read the register.
+
+
+GUARANTEES
+----------
+
+There are some minimal guarantees that may be expected of a CPU:
+
+ (*) On any given CPU, dependent memory accesses will be issued in order, with
+ respect to itself. This means that for:
+
+ Q = P; D = *Q;
+
+ the CPU will issue the following memory operations:
+
+ Q = LOAD P, D = LOAD *Q
+
+ and always in that order.
+
+ (*) Overlapping loads and stores within a particular CPU will appear to be
+ ordered within that CPU. This means that for:
+
+ a = *X; *X = b;
+
+ the CPU will only issue the following sequence of memory operations:
+
+ a = LOAD *X, STORE *X = b
+
+ And for:
+
+ *X = c; d = *X;
+
+ the CPU will only issue:
+
+ STORE *X = c, d = LOAD *X
+
+ (Loads and stores overlap if they are targetted at overlapping pieces of
+ memory).
+
+And there are a number of things that _must_ or _must_not_ be assumed:
+
+ (*) It _must_not_ be assumed that independent loads and stores will be issued
+ in the order given. This means that for:
+
+ X = *A; Y = *B; *D = Z;
+
+ we may get any of the following sequences:
+
+ X = LOAD *A, Y = LOAD *B, STORE *D = Z
+ X = LOAD *A, STORE *D = Z, Y = LOAD *B
+ Y = LOAD *B, X = LOAD *A, STORE *D = Z
+ Y = LOAD *B, STORE *D = Z, X = LOAD *A
+ STORE *D = Z, X = LOAD *A, Y = LOAD *B
+ STORE *D = Z, Y = LOAD *B, X = LOAD *A
+
+ (*) It _must_ be assumed that overlapping memory accesses may be merged or
+ discarded. This means that for:
+
+ X = *A; Y = *(A + 4);
+
+ we may get any one of the following sequences:
+
+ X = LOAD *A; Y = LOAD *(A + 4);
+ Y = LOAD *(A + 4); X = LOAD *A;
+ {X, Y} = LOAD {*A, *(A + 4) };
+
+ And for:
+
+ *A = X; Y = *A;
+
+ we may get either of:
+
+ STORE *A = X; Y = LOAD *A;
+ STORE *A = Y = X;
+
+
+=========================
+WHAT ARE MEMORY BARRIERS?
+=========================
+
+As can be seen above, independent memory operations are effectively performed
+in random order, but this can be a problem for CPU-CPU interaction and for I/O.
+What is required is some way of intervening to instruct the compiler and the
+CPU to restrict the order.
+
+Memory barriers are such interventions. They impose a perceived partial
+ordering between the memory operations specified on either side of the barrier.
+They request that the sequence of memory events generated appears to other
+parts of the system as if the barrier is effective on that CPU.
+
+
+VARIETIES OF MEMORY BARRIER
+---------------------------
+
+Memory barriers come in four basic varieties:
+
+ (1) Write (or store) memory barriers.
+
+ A write memory barrier gives a guarantee that all the STORE operations
+ specified before the barrier will appear to happen before all the STORE
+ operations specified after the barrier with respect to the other
+ components of the system.
+
+ A write barrier is a partial ordering on stores only; it is not required
+ to have any effect on loads.
+
+ A CPU can be viewed as as commiting a sequence of store operations to the
+ memory system as time progresses. All stores before a write barrier will
+ occur in the sequence _before_ all the stores after the write barrier.
+
+ [!] Note that write barriers should normally be paired with read or data
+ dependency barriers; see the "SMP barrier pairing" subsection.
+
+
+ (2) Data dependency barriers.
+
+ A data dependency barrier is a weaker form of read barrier. In the case
+ where two loads are performed such that the second depends on the result
+ of the first (eg: the first load retrieves the address to which the second
+ load will be directed), a data dependency barrier would be required to
+ make sure that the target of the second load is updated before the address
+ obtained by the first load is accessed.
+
+ A data dependency barrier is a partial ordering on interdependent loads
+ only; it is not required to have any effect on stores, independent loads
+ or overlapping loads.
+
+ As mentioned in (1), the other CPUs in the system can be viewed as
+ committing sequences of stores to the memory system that the CPU being
+ considered can then perceive. A data dependency barrier issued by the CPU
+ under consideration guarantees that for any load preceding it, if that
+ load touches one of a sequence of stores from another CPU, then by the
+ time the barrier completes, the effects of all the stores prior to that
+ touched by the load will be perceptible to any loads issued after the data
+ dependency barrier.
+
+ See the "Examples of memory barrier sequences" subsection for diagrams
+ showing the ordering constraints.
+
+ [!] Note that the first load really has to have a _data_ dependency and
+ not a control dependency. If the address for the second load is dependent
+ on the first load, but the dependency is through a conditional rather than
+ actually loading the address itself, then it's a _control_ dependency and
+ a full read barrier or better is required. See the "Control dependencies"
+ subsection for more information.
+
+ [!] Note that data dependency barriers should normally be paired with
+ write barriers; see the "SMP barrier pairing" subsection.
+
+
+ (3) Read (or load) memory barriers.
+
+ A read barrier is a data dependency barrier plus a guarantee that all the
+ LOAD operations specified before the barrier will appear to happen before
+ all the LOAD operations specified after the barrier with respect to the
+ other components of the system.
+
+ A read barrier is a partial ordering on loads only; it is not required to
+ have any effect on stores.
+
+ Read memory barriers imply data dependency barriers, and so can substitute
+ for them.
+
+ [!] Note that read barriers should normally be paired with write barriers;
+ see the "SMP barrier pairing" subsection.
+
+
+ (4) General memory barriers.
+
+ A general memory barrier gives a guarantee that all the LOAD and STORE
+ operations specified before the barrier will appear to happen before all
+ the LOAD and STORE operations specified after the barrier with respect to
+ the other components of the system.
+
+ A general memory barrier is a partial ordering over both loads and stores.
+
+ General memory barriers imply both read and write memory barriers, and so
+ can substitute for either.
+
+
+And a couple of implicit varieties:
+
+ (5) LOCK operations.
+
+ This acts as a one-way permeable barrier. It guarantees that all memory
+ operations after the LOCK operation will appear to happen after the LOCK
+ operation with respect to the other components of the system.
+
+ Memory operations that occur before a LOCK operation may appear to happen
+ after it completes.
+
+ A LOCK operation should almost always be paired with an UNLOCK operation.
+
+
+ (6) UNLOCK operations.
+
+ This also acts as a one-way permeable barrier. It guarantees that all
+ memory operations before the UNLOCK operation will appear to happen before
+ the UNLOCK operation with respect to the other components of the system.
+
+ Memory operations that occur after an UNLOCK operation may appear to
+ happen before it completes.
+
+ LOCK and UNLOCK operations are guaranteed to appear with respect to each
+ other strictly in the order specified.
+
+ The use of LOCK and UNLOCK operations generally precludes the need for
+ other sorts of memory barrier (but note the exceptions mentioned in the
+ subsection "MMIO write barrier").
+
+
+Memory barriers are only required where there's a possibility of interaction
+between two CPUs or between a CPU and a device. If it can be guaranteed that
+there won't be any such interaction in any particular piece of code, then
+memory barriers are unnecessary in that piece of code.
+
+
+Note that these are the _minimum_ guarantees. Different architectures may give
+more substantial guarantees, but they may _not_ be relied upon outside of arch
+specific code.
+
+
+WHAT MAY NOT BE ASSUMED ABOUT MEMORY BARRIERS?
+----------------------------------------------
+
+There are certain things that the Linux kernel memory barriers do not guarantee:
+
+ (*) There is no guarantee that any of the memory accesses specified before a
+ memory barrier will be _complete_ by the completion of a memory barrier
+ instruction; the barrier can be considered to draw a line in that CPU's
+ access queue that accesses of the appropriate type may not cross.
+
+ (*) There is no guarantee that issuing a memory barrier on one CPU will have
+ any direct effect on another CPU or any other hardware in the system. The
+ indirect effect will be the order in which the second CPU sees the effects
+ of the first CPU's accesses occur, but see the next point:
+
+ (*) There is no guarantee that the a CPU will see the correct order of effects
+ from a second CPU's accesses, even _if_ the second CPU uses a memory
+ barrier, unless the first CPU _also_ uses a matching memory barrier (see
+ the subsection on "SMP Barrier Pairing").
+
+ (*) There is no guarantee that some intervening piece of off-the-CPU
+ hardware[*] will not reorder the memory accesses. CPU cache coherency
+ mechanisms should propagate the indirect effects of a memory barrier
+ between CPUs, but might not do so in order.
+
+ [*] For information on bus mastering DMA and coherency please read:
+
+ Documentation/pci.txt
+ Documentation/DMA-mapping.txt
+ Documentation/DMA-API.txt
+
+
+DATA DEPENDENCY BARRIERS
+------------------------
+
+The usage requirements of data dependency barriers are a little subtle, and
+it's not always obvious that they're needed. To illustrate, consider the
+following sequence of events:
+
+ CPU 1 CPU 2
+ =============== ===============
+ { A == 1, B == 2, C = 3, P == &A, Q == &C }
+ B = 4;
+ <write barrier>
+ P = &B
+ Q = P;
+ D = *Q;
+
+There's a clear data dependency here, and it would seem that by the end of the
+sequence, Q must be either &A or &B, and that:
+
+ (Q == &A) implies (D == 1)
+ (Q == &B) implies (D == 4)
+
+But! CPU 2's perception of P may be updated _before_ its perception of B, thus
+leading to the following situation:
+
+ (Q == &B) and (D == 2) ????
+
+Whilst this may seem like a failure of coherency or causality maintenance, it
+isn't, and this behaviour can be observed on certain real CPUs (such as the DEC
+Alpha).
+
+To deal with this, a data dependency barrier must be inserted between the
+address load and the data load:
+
+ CPU 1 CPU 2
+ =============== ===============
+ { A == 1, B == 2, C = 3, P == &A, Q == &C }
+ B = 4;
+ <write barrier>
+ P = &B
+ Q = P;
+ <data dependency barrier>
+ D = *Q;
+
+This enforces the occurrence of one of the two implications, and prevents the
+third possibility from arising.
+
+[!] Note that this extremely counterintuitive situation arises most easily on
+machines with split caches, so that, for example, one cache bank processes
+even-numbered cache lines and the other bank processes odd-numbered cache
+lines. The pointer P might be stored in an odd-numbered cache line, and the
+variable B might be stored in an even-numbered cache line. Then, if the
+even-numbered bank of the reading CPU's cache is extremely busy while the
+odd-numbered bank is idle, one can see the new value of the pointer P (&B),
+but the old value of the variable B (1).
+
+
+Another example of where data dependency barriers might by required is where a
+number is read from memory and then used to calculate the index for an array
+access:
+
+ CPU 1 CPU 2
+ =============== ===============
+ { M[0] == 1, M[1] == 2, M[3] = 3, P == 0, Q == 3 }
+ M[1] = 4;
+ <write barrier>
+ P = 1
+ Q = P;
+ <data dependency barrier>
+ D = M[Q];
+
+
+The data dependency barrier is very important to the RCU system, for example.
+See rcu_dereference() in include/linux/rcupdate.h. This permits the current
+target of an RCU'd pointer to be replaced with a new modified target, without
+the replacement target appearing to be incompletely initialised.
+
+See also the subsection on "Cache Coherency" for a more thorough example.
+
+
+CONTROL DEPENDENCIES
+--------------------
+
+A control dependency requires a full read memory barrier, not simply a data
+dependency barrier to make it work correctly. Consider the following bit of
+code:
+
+ q = &a;
+ if (p)
+ q = &b;
+ <data dependency barrier>
+ x = *q;
+
+This will not have the desired effect because there is no actual data
+dependency, but rather a control dependency that the CPU may short-circuit by
+attempting to predict the outcome in advance. In such a case what's actually
+required is:
+
+ q = &a;
+ if (p)
+ q = &b;
+ <read barrier>
+ x = *q;
+
+
+SMP BARRIER PAIRING
+-------------------
+
+When dealing with CPU-CPU interactions, certain types of memory barrier should
+always be paired. A lack of appropriate pairing is almost certainly an error.
+
+A write barrier should always be paired with a data dependency barrier or read
+barrier, though a general barrier would also be viable. Similarly a read
+barrier or a data dependency barrier should always be paired with at least an
+write barrier, though, again, a general barrier is viable:
+
+ CPU 1 CPU 2
+ =============== ===============
+ a = 1;
+ <write barrier>
+ b = 2; x = b;
+ <read barrier>
+ y = a;
+
+Or:
+
+ CPU 1 CPU 2
+ =============== ===============================
+ a = 1;
+ <write barrier>
+ b = &a; x = b;
+ <data dependency barrier>
+ y = *x;
+
+Basically, the read barrier always has to be there, even though it can be of
+the "weaker" type.
+
+[!] Note that the stores before the write barrier would normally be expected to
+match the loads after the read barrier or data dependency barrier, and vice
+versa:
+
+ CPU 1 CPU 2
+ =============== ===============
+ a = 1; }---- --->{ v = c
+ b = 2; } \ / { w = d
+ <write barrier> \ <read barrier>
+ c = 3; } / \ { x = a;
+ d = 4; }---- --->{ y = b;
+
+
+EXAMPLES OF MEMORY BARRIER SEQUENCES
+------------------------------------
+
+Firstly, write barriers act as a partial orderings on store operations.
+Consider the following sequence of events:
+
+ CPU 1
+ =======================
+ STORE A = 1
+ STORE B = 2
+ STORE C = 3
+ <write barrier>
+ STORE D = 4
+ STORE E = 5
+
+This sequence of events is committed to the memory coherence system in an order
+that the rest of the system might perceive as the unordered set of { STORE A,
+STORE B, STORE C } all occuring before the unordered set of { STORE D, STORE E
+}:
+
+ +-------+ : :
+ | | +------+
+ | |------>| C=3 | } /\
+ | | : +------+ }----- \ -----> Events perceptible
+ | | : | A=1 | } \/ to rest of system
+ | | : +------+ }
+ | CPU 1 | : | B=2 | }
+ | | +------+ }
+ | | wwwwwwwwwwwwwwww } <--- At this point the write barrier
+ | | +------+ } requires all stores prior to the
+ | | : | E=5 | } barrier to be committed before
+ | | : +------+ } further stores may be take place.
+ | |------>| D=4 | }
+ | | +------+
+ +-------+ : :
+ |
+ | Sequence in which stores are committed to the
+ | memory system by CPU 1
+ V
+
+
+Secondly, data dependency barriers act as a partial orderings on data-dependent
+loads. Consider the following sequence of events:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ { B = 7; X = 9; Y = 8; C = &Y }
+ STORE A = 1
+ STORE B = 2
+ <write barrier>
+ STORE C = &B LOAD X
+ STORE D = 4 LOAD C (gets &B)
+ LOAD *C (reads B)
+
+Without intervention, CPU 2 may perceive the events on CPU 1 in some
+effectively random order, despite the write barrier issued by CPU 1:
+
+ +-------+ : : : :
+ | | +------+ +-------+ | Sequence of update
+ | |------>| B=2 |----- --->| Y->8 | | of perception on
+ | | : +------+ \ +-------+ | CPU 2
+ | CPU 1 | : | A=1 | \ --->| C->&Y | V
+ | | +------+ | +-------+
+ | | wwwwwwwwwwwwwwww | : :
+ | | +------+ | : :
+ | | : | C=&B |--- | : : +-------+
+ | | : +------+ \ | +-------+ | |
+ | |------>| D=4 | ----------->| C->&B |------>| |
+ | | +------+ | +-------+ | |
+ +-------+ : : | : : | |
+ | : : | |
+ | : : | CPU 2 |
+ | +-------+ | |
+ Apparently incorrect ---> | | B->7 |------>| |
+ perception of B (!) | +-------+ | |
+ | : : | |
+ | +-------+ | |
+ The load of X holds ---> \ | X->9 |------>| |
+ up the maintenance \ +-------+ | |
+ of coherence of B ----->| B->2 | +-------+
+ +-------+
+ : :
+
+
+In the above example, CPU 2 perceives that B is 7, despite the load of *C
+(which would be B) coming after the the LOAD of C.
+
+If, however, a data dependency barrier were to be placed between the load of C
+and the load of *C (ie: B) on CPU 2:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ { B = 7; X = 9; Y = 8; C = &Y }
+ STORE A = 1
+ STORE B = 2
+ <write barrier>
+ STORE C = &B LOAD X
+ STORE D = 4 LOAD C (gets &B)
+ <data dependency barrier>
+ LOAD *C (reads B)
+
+then the following will occur:
+
+ +-------+ : : : :
+ | | +------+ +-------+
+ | |------>| B=2 |----- --->| Y->8 |
+ | | : +------+ \ +-------+
+ | CPU 1 | : | A=1 | \ --->| C->&Y |
+ | | +------+ | +-------+
+ | | wwwwwwwwwwwwwwww | : :
+ | | +------+ | : :
+ | | : | C=&B |--- | : : +-------+
+ | | : +------+ \ | +-------+ | |
+ | |------>| D=4 | ----------->| C->&B |------>| |
+ | | +------+ | +-------+ | |
+ +-------+ : : | : : | |
+ | : : | |
+ | : : | CPU 2 |
+ | +-------+ | |
+ | | X->9 |------>| |
+ | +-------+ | |
+ Makes sure all effects ---> \ ddddddddddddddddd | |
+ prior to the store of C \ +-------+ | |
+ are perceptible to ----->| B->2 |------>| |
+ subsequent loads +-------+ | |
+ : : +-------+
+
+
+And thirdly, a read barrier acts as a partial order on loads. Consider the
+following sequence of events:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ { A = 0, B = 9 }
+ STORE A=1
+ <write barrier>
+ STORE B=2
+ LOAD B
+ LOAD A
+
+Without intervention, CPU 2 may then choose to perceive the events on CPU 1 in
+some effectively random order, despite the write barrier issued by CPU 1:
+
+ +-------+ : : : :
+ | | +------+ +-------+
+ | |------>| A=1 |------ --->| A->0 |
+ | | +------+ \ +-------+
+ | CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
+ | | +------+ | +-------+
+ | |------>| B=2 |--- | : :
+ | | +------+ \ | : : +-------+
+ +-------+ : : \ | +-------+ | |
+ ---------->| B->2 |------>| |
+ | +-------+ | CPU 2 |
+ | | A->0 |------>| |
+ | +-------+ | |
+ | : : +-------+
+ \ : :
+ \ +-------+
+ ---->| A->1 |
+ +-------+
+ : :
+
+
+If, however, a read barrier were to be placed between the load of E and the
+load of A on CPU 2:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ { A = 0, B = 9 }
+ STORE A=1
+ <write barrier>
+ STORE B=2
+ LOAD B
+ <read barrier>
+ LOAD A
+
+then the partial ordering imposed by CPU 1 will be perceived correctly by CPU
+2:
+
+ +-------+ : : : :
+ | | +------+ +-------+
+ | |------>| A=1 |------ --->| A->0 |
+ | | +------+ \ +-------+
+ | CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
+ | | +------+ | +-------+
+ | |------>| B=2 |--- | : :
+ | | +------+ \ | : : +-------+
+ +-------+ : : \ | +-------+ | |
+ ---------->| B->2 |------>| |
+ | +-------+ | CPU 2 |
+ | : : | |
+ | : : | |
+ At this point the read ----> \ rrrrrrrrrrrrrrrrr | |
+ barrier causes all effects \ +-------+ | |
+ prior to the storage of B ---->| A->1 |------>| |
+ to be perceptible to CPU 2 +-------+ | |
+ : : +-------+
+
+
+To illustrate this more completely, consider what could happen if the code
+contained a load of A either side of the read barrier:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ { A = 0, B = 9 }
+ STORE A=1
+ <write barrier>
+ STORE B=2
+ LOAD B
+ LOAD A [first load of A]
+ <read barrier>
+ LOAD A [second load of A]
+
+Even though the two loads of A both occur after the load of B, they may both
+come up with different values:
+
+ +-------+ : : : :
+ | | +------+ +-------+
+ | |------>| A=1 |------ --->| A->0 |
+ | | +------+ \ +-------+
+ | CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
+ | | +------+ | +-------+
+ | |------>| B=2 |--- | : :
+ | | +------+ \ | : : +-------+
+ +-------+ : : \ | +-------+ | |
+ ---------->| B->2 |------>| |
+ | +-------+ | CPU 2 |
+ | : : | |
+ | : : | |
+ | +-------+ | |
+ | | A->0 |------>| 1st |
+ | +-------+ | |
+ At this point the read ----> \ rrrrrrrrrrrrrrrrr | |
+ barrier causes all effects \ +-------+ | |
+ prior to the storage of B ---->| A->1 |------>| 2nd |
+ to be perceptible to CPU 2 +-------+ | |
+ : : +-------+
+
+
+But it may be that the update to A from CPU 1 becomes perceptible to CPU 2
+before the read barrier completes anyway:
+
+ +-------+ : : : :
+ | | +------+ +-------+
+ | |------>| A=1 |------ --->| A->0 |
+ | | +------+ \ +-------+
+ | CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
+ | | +------+ | +-------+
+ | |------>| B=2 |--- | : :
+ | | +------+ \ | : : +-------+
+ +-------+ : : \ | +-------+ | |
+ ---------->| B->2 |------>| |
+ | +-------+ | CPU 2 |
+ | : : | |
+ \ : : | |
+ \ +-------+ | |
+ ---->| A->1 |------>| 1st |
+ +-------+ | |
+ rrrrrrrrrrrrrrrrr | |
+ +-------+ | |
+ | A->1 |------>| 2nd |
+ +-------+ | |
+ : : +-------+
+
+
+The guarantee is that the second load will always come up with A == 1 if the
+load of B came up with B == 2. No such guarantee exists for the first load of
+A; that may come up with either A == 0 or A == 1.
+
+
+READ MEMORY BARRIERS VS LOAD SPECULATION
+----------------------------------------
+
+Many CPUs speculate with loads: that is they see that they will need to load an
+item from memory, and they find a time where they're not using the bus for any
+other loads, and so do the load in advance - even though they haven't actually
+got to that point in the instruction execution flow yet. This permits the
+actual load instruction to potentially complete immediately because the CPU
+already has the value to hand.
+
+It may turn out that the CPU didn't actually need the value - perhaps because a
+branch circumvented the load - in which case it can discard the value or just
+cache it for later use.
+
+Consider:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ LOAD B
+ DIVIDE } Divide instructions generally
+ DIVIDE } take a long time to perform
+ LOAD A
+
+Which might appear as this:
+
+ : : +-------+
+ +-------+ | |
+ --->| B->2 |------>| |
+ +-------+ | CPU 2 |
+ : :DIVIDE | |
+ +-------+ | |
+ The CPU being busy doing a ---> --->| A->0 |~~~~ | |
+ division speculates on the +-------+ ~ | |
+ LOAD of A : : ~ | |
+ : :DIVIDE | |
+ : : ~ | |
+ Once the divisions are complete --> : : ~-->| |
+ the CPU can then perform the : : | |
+ LOAD with immediate effect : : +-------+
+
+
+Placing a read barrier or a data dependency barrier just before the second
+load:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ LOAD B
+ DIVIDE
+ DIVIDE
+ <read barrier>
+ LOAD A
+
+will force any value speculatively obtained to be reconsidered to an extent
+dependent on the type of barrier used. If there was no change made to the
+speculated memory location, then the speculated value will just be used:
+
+ : : +-------+
+ +-------+ | |
+ --->| B->2 |------>| |
+ +-------+ | CPU 2 |
+ : :DIVIDE | |
+ +-------+ | |
+ The CPU being busy doing a ---> --->| A->0 |~~~~ | |
+ division speculates on the +-------+ ~ | |
+ LOAD of A : : ~ | |
+ : :DIVIDE | |
+ : : ~ | |
+ : : ~ | |
+ rrrrrrrrrrrrrrrr~ | |
+ : : ~ | |
+ : : ~-->| |
+ : : | |
+ : : +-------+
+
+
+but if there was an update or an invalidation from another CPU pending, then
+the speculation will be cancelled and the value reloaded:
+
+ : : +-------+
+ +-------+ | |
+ --->| B->2 |------>| |
+ +-------+ | CPU 2 |
+ : :DIVIDE | |
+ +-------+ | |
+ The CPU being busy doing a ---> --->| A->0 |~~~~ | |
+ division speculates on the +-------+ ~ | |
+ LOAD of A : : ~ | |
+ : :DIVIDE | |
+ : : ~ | |
+ : : ~ | |
+ rrrrrrrrrrrrrrrrr | |
+ +-------+ | |
+ The speculation is discarded ---> --->| A->1 |------>| |
+ and an updated value is +-------+ | |
+ retrieved : : +-------+
+
+
+========================
+EXPLICIT KERNEL BARRIERS
+========================
+
+The Linux kernel has a variety of different barriers that act at different
+levels:
+
+ (*) Compiler barrier.
+
+ (*) CPU memory barriers.
+
+ (*) MMIO write barrier.
+
+
+COMPILER BARRIER
+----------------
+
+The Linux kernel has an explicit compiler barrier function that prevents the
+compiler from moving the memory accesses either side of it to the other side:
+
+ barrier();
+
+This a general barrier - lesser varieties of compiler barrier do not exist.
+
+The compiler barrier has no direct effect on the CPU, which may then reorder
+things however it wishes.
+
+
+CPU MEMORY BARRIERS
+-------------------
+
+The Linux kernel has eight basic CPU memory barriers:
+
+ TYPE MANDATORY SMP CONDITIONAL
+ =============== ======================= ===========================
+ GENERAL mb() smp_mb()
+ WRITE wmb() smp_wmb()
+ READ rmb() smp_rmb()
+ DATA DEPENDENCY read_barrier_depends() smp_read_barrier_depends()
+
+
+All CPU memory barriers unconditionally imply compiler barriers.
+
+SMP memory barriers are reduced to compiler barriers on uniprocessor compiled
+systems because it is assumed that a CPU will be appear to be self-consistent,
+and will order overlapping accesses correctly with respect to itself.
+
+[!] Note that SMP memory barriers _must_ be used to control the ordering of
+references to shared memory on SMP systems, though the use of locking instead
+is sufficient.
+
+Mandatory barriers should not be used to control SMP effects, since mandatory
+barriers unnecessarily impose overhead on UP systems. They may, however, be
+used to control MMIO effects on accesses through relaxed memory I/O windows.
+These are required even on non-SMP systems as they affect the order in which
+memory operations appear to a device by prohibiting both the compiler and the
+CPU from reordering them.
+
+
+There are some more advanced barrier functions:
+
+ (*) set_mb(var, value)
+ (*) set_wmb(var, value)
+
+ These assign the value to the variable and then insert at least a write
+ barrier after it, depending on the function. They aren't guaranteed to
+ insert anything more than a compiler barrier in a UP compilation.
+
+
+ (*) smp_mb__before_atomic_dec();
+ (*) smp_mb__after_atomic_dec();
+ (*) smp_mb__before_atomic_inc();
+ (*) smp_mb__after_atomic_inc();
+
+ These are for use with atomic add, subtract, increment and decrement
+ functions that don't return a value, especially when used for reference
+ counting. These functions do not imply memory barriers.
+
+ As an example, consider a piece of code that marks an object as being dead
+ and then decrements the object's reference count:
+
+ obj->dead = 1;
+ smp_mb__before_atomic_dec();
+ atomic_dec(&obj->ref_count);
+
+ This makes sure that the death mark on the object is perceived to be set
+ *before* the reference counter is decremented.
+
+ See Documentation/atomic_ops.txt for more information. See the "Atomic
+ operations" subsection for information on where to use these.
+
+
+ (*) smp_mb__before_clear_bit(void);
+ (*) smp_mb__after_clear_bit(void);
+
+ These are for use similar to the atomic inc/dec barriers. These are
+ typically used for bitwise unlocking operations, so care must be taken as
+ there are no implicit memory barriers here either.
+
+ Consider implementing an unlock operation of some nature by clearing a
+ locking bit. The clear_bit() would then need to be barriered like this:
+
+ smp_mb__before_clear_bit();
+ clear_bit( ... );
+
+ This prevents memory operations before the clear leaking to after it. See
+ the subsection on "Locking Functions" with reference to UNLOCK operation
+ implications.
+
+ See Documentation/atomic_ops.txt for more information. See the "Atomic
+ operations" subsection for information on where to use these.
+
+
+MMIO WRITE BARRIER
+------------------
+
+The Linux kernel also has a special barrier for use with memory-mapped I/O
+writes:
+
+ mmiowb();
+
+This is a variation on the mandatory write barrier that causes writes to weakly
+ordered I/O regions to be partially ordered. Its effects may go beyond the
+CPU->Hardware interface and actually affect the hardware at some level.
+
+See the subsection "Locks vs I/O accesses" for more information.
+
+
+===============================
+IMPLICIT KERNEL MEMORY BARRIERS
+===============================
+
+Some of the other functions in the linux kernel imply memory barriers, amongst
+which are locking and scheduling functions.
+
+This specification is a _minimum_ guarantee; any particular architecture may
+provide more substantial guarantees, but these may not be relied upon outside
+of arch specific code.
+
+
+LOCKING FUNCTIONS
+-----------------
+
+The Linux kernel has a number of locking constructs:
+
+ (*) spin locks
+ (*) R/W spin locks
+ (*) mutexes
+ (*) semaphores
+ (*) R/W semaphores
+ (*) RCU
+
+In all cases there are variants on "LOCK" operations and "UNLOCK" operations
+for each construct. These operations all imply certain barriers:
+
+ (1) LOCK operation implication:
+
+ Memory operations issued after the LOCK will be completed after the LOCK
+ operation has completed.
+
+ Memory operations issued before the LOCK may be completed after the LOCK
+ operation has completed.
+
+ (2) UNLOCK operation implication:
+
+ Memory operations issued before the UNLOCK will be completed before the
+ UNLOCK operation has completed.
+
+ Memory operations issued after the UNLOCK may be completed before the
+ UNLOCK operation has completed.
+
+ (3) LOCK vs LOCK implication:
+
+ All LOCK operations issued before another LOCK operation will be completed
+ before that LOCK operation.
+
+ (4) LOCK vs UNLOCK implication:
+
+ All LOCK operations issued before an UNLOCK operation will be completed
+ before the UNLOCK operation.
+
+ All UNLOCK operations issued before a LOCK operation will be completed
+ before the LOCK operation.
+
+ (5) Failed conditional LOCK implication:
+
+ Certain variants of the LOCK operation may fail, either due to being
+ unable to get the lock immediately, or due to receiving an unblocked
+ signal whilst asleep waiting for the lock to become available. Failed
+ locks do not imply any sort of barrier.
+
+Therefore, from (1), (2) and (4) an UNLOCK followed by an unconditional LOCK is
+equivalent to a full barrier, but a LOCK followed by an UNLOCK is not.
+
+[!] Note: one of the consequence of LOCKs and UNLOCKs being only one-way
+ barriers is that the effects instructions outside of a critical section may
+ seep into the inside of the critical section.
+
+A LOCK followed by an UNLOCK may not be assumed to be full memory barrier
+because it is possible for an access preceding the LOCK to happen after the
+LOCK, and an access following the UNLOCK to happen before the UNLOCK, and the
+two accesses can themselves then cross:
+
+ *A = a;
+ LOCK
+ UNLOCK
+ *B = b;
+
+may occur as:
+
+ LOCK, STORE *B, STORE *A, UNLOCK
+
+Locks and semaphores may not provide any guarantee of ordering on UP compiled
+systems, and so cannot be counted on in such a situation to actually achieve
+anything at all - especially with respect to I/O accesses - unless combined
+with interrupt disabling operations.
+
+See also the section on "Inter-CPU locking barrier effects".
+
+
+As an example, consider the following:
+
+ *A = a;
+ *B = b;
+ LOCK
+ *C = c;
+ *D = d;
+ UNLOCK
+ *E = e;
+ *F = f;
+
+The following sequence of events is acceptable:
+
+ LOCK, {*F,*A}, *E, {*C,*D}, *B, UNLOCK
+
+ [+] Note that {*F,*A} indicates a combined access.
+
+But none of the following are:
+
+ {*F,*A}, *B, LOCK, *C, *D, UNLOCK, *E
+ *A, *B, *C, LOCK, *D, UNLOCK, *E, *F
+ *A, *B, LOCK, *C, UNLOCK, *D, *E, *F
+ *B, LOCK, *C, *D, UNLOCK, {*F,*A}, *E
+
+
+
+INTERRUPT DISABLING FUNCTIONS
+-----------------------------
+
+Functions that disable interrupts (LOCK equivalent) and enable interrupts
+(UNLOCK equivalent) will act as compiler barriers only. So if memory or I/O
+barriers are required in such a situation, they must be provided from some
+other means.
+
+
+MISCELLANEOUS FUNCTIONS
+-----------------------
+
+Other functions that imply barriers:
+
+ (*) schedule() and similar imply full memory barriers.
+
+
+=================================
+INTER-CPU LOCKING BARRIER EFFECTS
+=================================
+
+On SMP systems locking primitives give a more substantial form of barrier: one
+that does affect memory access ordering on other CPUs, within the context of
+conflict on any particular lock.
+
+
+LOCKS VS MEMORY ACCESSES
+------------------------
+
+Consider the following: the system has a pair of spinlocks (M) and (Q), and
+three CPUs; then should the following sequence of events occur:
+
+ CPU 1 CPU 2
+ =============================== ===============================
+ *A = a; *E = e;
+ LOCK M LOCK Q
+ *B = b; *F = f;
+ *C = c; *G = g;
+ UNLOCK M UNLOCK Q
+ *D = d; *H = h;
+
+Then there is no guarantee as to what order CPU #3 will see the accesses to *A
+through *H occur in, other than the constraints imposed by the separate locks
+on the separate CPUs. It might, for example, see:
+
+ *E, LOCK M, LOCK Q, *G, *C, *F, *A, *B, UNLOCK Q, *D, *H, UNLOCK M
+
+But it won't see any of:
+
+ *B, *C or *D preceding LOCK M
+ *A, *B or *C following UNLOCK M
+ *F, *G or *H preceding LOCK Q
+ *E, *F or *G following UNLOCK Q
+
+
+However, if the following occurs:
+
+ CPU 1 CPU 2
+ =============================== ===============================
+ *A = a;
+ LOCK M [1]
+ *B = b;
+ *C = c;
+ UNLOCK M [1]
+ *D = d; *E = e;
+ LOCK M [2]
+ *F = f;
+ *G = g;
+ UNLOCK M [2]
+ *H = h;
+
+CPU #3 might see:
+
+ *E, LOCK M [1], *C, *B, *A, UNLOCK M [1],
+ LOCK M [2], *H, *F, *G, UNLOCK M [2], *D
+
+But assuming CPU #1 gets the lock first, it won't see any of:
+
+ *B, *C, *D, *F, *G or *H preceding LOCK M [1]
+ *A, *B or *C following UNLOCK M [1]
+ *F, *G or *H preceding LOCK M [2]
+ *A, *B, *C, *E, *F or *G following UNLOCK M [2]
+
+
+LOCKS VS I/O ACCESSES
+---------------------
+
+Under certain circumstances (especially involving NUMA), I/O accesses within
+two spinlocked sections on two different CPUs may be seen as interleaved by the
+PCI bridge, because the PCI bridge does not necessarily participate in the
+cache-coherence protocol, and is therefore incapable of issuing the required
+read memory barriers.
+
+For example:
+
+ CPU 1 CPU 2
+ =============================== ===============================
+ spin_lock(Q)
+ writel(0, ADDR)
+ writel(1, DATA);
+ spin_unlock(Q);
+ spin_lock(Q);
+ writel(4, ADDR);
+ writel(5, DATA);
+ spin_unlock(Q);
+
+may be seen by the PCI bridge as follows:
+
+ STORE *ADDR = 0, STORE *ADDR = 4, STORE *DATA = 1, STORE *DATA = 5
+
+which would probably cause the hardware to malfunction.
+
+
+What is necessary here is to intervene with an mmiowb() before dropping the
+spinlock, for example:
+
+ CPU 1 CPU 2
+ =============================== ===============================
+ spin_lock(Q)
+ writel(0, ADDR)
+ writel(1, DATA);
+ mmiowb();
+ spin_unlock(Q);
+ spin_lock(Q);
+ writel(4, ADDR);
+ writel(5, DATA);
+ mmiowb();
+ spin_unlock(Q);
+
+this will ensure that the two stores issued on CPU #1 appear at the PCI bridge
+before either of the stores issued on CPU #2.
+
+
+Furthermore, following a store by a load to the same device obviates the need
+for an mmiowb(), because the load forces the store to complete before the load
+is performed:
+
+ CPU 1 CPU 2
+ =============================== ===============================
+ spin_lock(Q)
+ writel(0, ADDR)
+ a = readl(DATA);
+ spin_unlock(Q);
+ spin_lock(Q);
+ writel(4, ADDR);
+ b = readl(DATA);
+ spin_unlock(Q);
+
+
+See Documentation/DocBook/deviceiobook.tmpl for more information.
+
+
+=================================
+WHERE ARE MEMORY BARRIERS NEEDED?
+=================================
+
+Under normal operation, memory operation reordering is generally not going to
+be a problem as a single-threaded linear piece of code will still appear to
+work correctly, even if it's in an SMP kernel. There are, however, three
+circumstances in which reordering definitely _could_ be a problem:
+
+ (*) Interprocessor interaction.
+
+ (*) Atomic operations.
+
+ (*) Accessing devices (I/O).
+
+ (*) Interrupts.
+
+
+INTERPROCESSOR INTERACTION
+--------------------------
+
+When there's a system with more than one processor, more than one CPU in the
+system may be working on the same data set at the same time. This can cause
+synchronisation problems, and the usual way of dealing with them is to use
+locks. Locks, however, are quite expensive, and so it may be preferable to
+operate without the use of a lock if at all possible. In such a case
+operations that affect both CPUs may have to be carefully ordered to prevent
+a malfunction.
+
+Consider, for example, the R/W semaphore slow path. Here a waiting process is
+queued on the semaphore, by virtue of it having a piece of its stack linked to
+the semaphore's list of waiting processes:
+
+ struct rw_semaphore {
+ ...
+ spinlock_t lock;
+ struct list_head waiters;
+ };
+
+ struct rwsem_waiter {
+ struct list_head list;
+ struct task_struct *task;
+ };
+
+To wake up a particular waiter, the up_read() or up_write() functions have to:
+
+ (1) read the next pointer from this waiter's record to know as to where the
+ next waiter record is;
+
+ (4) read the pointer to the waiter's task structure;
+
+ (3) clear the task pointer to tell the waiter it has been given the semaphore;
+
+ (4) call wake_up_process() on the task; and
+
+ (5) release the reference held on the waiter's task struct.
+
+In otherwords, it has to perform this sequence of events:
+
+ LOAD waiter->list.next;
+ LOAD waiter->task;
+ STORE waiter->task;
+ CALL wakeup
+ RELEASE task
+
+and if any of these steps occur out of order, then the whole thing may
+malfunction.
+
+Once it has queued itself and dropped the semaphore lock, the waiter does not
+get the lock again; it instead just waits for its task pointer to be cleared
+before proceeding. Since the record is on the waiter's stack, this means that
+if the task pointer is cleared _before_ the next pointer in the list is read,
+another CPU might start processing the waiter and might clobber the waiter's
+stack before the up*() function has a chance to read the next pointer.
+
+Consider then what might happen to the above sequence of events:
+
+ CPU 1 CPU 2
+ =============================== ===============================
+ down_xxx()
+ Queue waiter
+ Sleep
+ up_yyy()
+ LOAD waiter->task;
+ STORE waiter->task;
+ Woken up by other event
+ <preempt>
+ Resume processing
+ down_xxx() returns
+ call foo()
+ foo() clobbers *waiter
+ </preempt>
+ LOAD waiter->list.next;
+ --- OOPS ---
+
+This could be dealt with using the semaphore lock, but then the down_xxx()
+function has to needlessly get the spinlock again after being woken up.
+
+The way to deal with this is to insert a general SMP memory barrier:
+
+ LOAD waiter->list.next;
+ LOAD waiter->task;
+ smp_mb();
+ STORE waiter->task;
+ CALL wakeup
+ RELEASE task
+
+In this case, the barrier makes a guarantee that all memory accesses before the
+barrier will appear to happen before all the memory accesses after the barrier
+with respect to the other CPUs on the system. It does _not_ guarantee that all
+the memory accesses before the barrier will be complete by the time the barrier
+instruction itself is complete.
+
+On a UP system - where this wouldn't be a problem - the smp_mb() is just a
+compiler barrier, thus making sure the compiler emits the instructions in the
+right order without actually intervening in the CPU. Since there there's only
+one CPU, that CPU's dependency ordering logic will take care of everything
+else.
+
+
+ATOMIC OPERATIONS
+-----------------
+
+Whilst they are technically interprocessor interaction considerations, atomic
+operations are noted specially as some of them imply full memory barriers and
+some don't, but they're very heavily relied on as a group throughout the
+kernel.
+
+Any atomic operation that modifies some state in memory and returns information
+about the state (old or new) implies an SMP-conditional general memory barrier
+(smp_mb()) on each side of the actual operation. These include:
+
+ xchg();
+ cmpxchg();
+ atomic_cmpxchg();
+ atomic_inc_return();
+ atomic_dec_return();
+ atomic_add_return();
+ atomic_sub_return();
+ atomic_inc_and_test();
+ atomic_dec_and_test();
+ atomic_sub_and_test();
+ atomic_add_negative();
+ atomic_add_unless();
+ test_and_set_bit();
+ test_and_clear_bit();
+ test_and_change_bit();
+
+These are used for such things as implementing LOCK-class and UNLOCK-class
+operations and adjusting reference counters towards object destruction, and as
+such the implicit memory barrier effects are necessary.
+
+
+The following operation are potential problems as they do _not_ imply memory
+barriers, but might be used for implementing such things as UNLOCK-class
+operations:
+
+ atomic_set();
+ set_bit();
+ clear_bit();
+ change_bit();
+
+With these the appropriate explicit memory barrier should be used if necessary
+(smp_mb__before_clear_bit() for instance).
+
+
+The following also do _not_ imply memory barriers, and so may require explicit
+memory barriers under some circumstances (smp_mb__before_atomic_dec() for
+instance)):
+
+ atomic_add();
+ atomic_sub();
+ atomic_inc();
+ atomic_dec();
+
+If they're used for statistics generation, then they probably don't need memory
+barriers, unless there's a coupling between statistical data.
+
+If they're used for reference counting on an object to control its lifetime,
+they probably don't need memory barriers because either the reference count
+will be adjusted inside a locked section, or the caller will already hold
+sufficient references to make the lock, and thus a memory barrier unnecessary.
+
+If they're used for constructing a lock of some description, then they probably
+do need memory barriers as a lock primitive generally has to do things in a
+specific order.
+
+
+Basically, each usage case has to be carefully considered as to whether memory
+barriers are needed or not.
+
+[!] Note that special memory barrier primitives are available for these
+situations because on some CPUs the atomic instructions used imply full memory
+barriers, and so barrier instructions are superfluous in conjunction with them,
+and in such cases the special barrier primitives will be no-ops.
+
+See Documentation/atomic_ops.txt for more information.
+
+
+ACCESSING DEVICES
+-----------------
+
+Many devices can be memory mapped, and so appear to the CPU as if they're just
+a set of memory locations. To control such a device, the driver usually has to
+make the right memory accesses in exactly the right order.
+
+However, having a clever CPU or a clever compiler creates a potential problem
+in that the carefully sequenced accesses in the driver code won't reach the
+device in the requisite order if the CPU or the compiler thinks it is more
+efficient to reorder, combine or merge accesses - something that would cause
+the device to malfunction.
+
+Inside of the Linux kernel, I/O should be done through the appropriate accessor
+routines - such as inb() or writel() - which know how to make such accesses
+appropriately sequential. Whilst this, for the most part, renders the explicit
+use of memory barriers unnecessary, there are a couple of situations where they
+might be needed:
+
+ (1) On some systems, I/O stores are not strongly ordered across all CPUs, and
+ so for _all_ general drivers locks should be used and mmiowb() must be
+ issued prior to unlocking the critical section.
+
+ (2) If the accessor functions are used to refer to an I/O memory window with
+ relaxed memory access properties, then _mandatory_ memory barriers are
+ required to enforce ordering.
+
+See Documentation/DocBook/deviceiobook.tmpl for more information.
+
+
+INTERRUPTS
+----------
+
+A driver may be interrupted by its own interrupt service routine, and thus the
+two parts of the driver may interfere with each other's attempts to control or
+access the device.
+
+This may be alleviated - at least in part - by disabling local interrupts (a
+form of locking), such that the critical operations are all contained within
+the interrupt-disabled section in the driver. Whilst the driver's interrupt
+routine is executing, the driver's core may not run on the same CPU, and its
+interrupt is not permitted to happen again until the current interrupt has been
+handled, thus the interrupt handler does not need to lock against that.
+
+However, consider a driver that was talking to an ethernet card that sports an
+address register and a data register. If that driver's core talks to the card
+under interrupt-disablement and then the driver's interrupt handler is invoked:
+
+ LOCAL IRQ DISABLE
+ writew(ADDR, 3);
+ writew(DATA, y);
+ LOCAL IRQ ENABLE
+ <interrupt>
+ writew(ADDR, 4);
+ q = readw(DATA);
+ </interrupt>
+
+The store to the data register might happen after the second store to the
+address register if ordering rules are sufficiently relaxed:
+
+ STORE *ADDR = 3, STORE *ADDR = 4, STORE *DATA = y, q = LOAD *DATA
+
+
+If ordering rules are relaxed, it must be assumed that accesses done inside an
+interrupt disabled section may leak outside of it and may interleave with
+accesses performed in an interrupt - and vice versa - unless implicit or
+explicit barriers are used.
+
+Normally this won't be a problem because the I/O accesses done inside such
+sections will include synchronous load operations on strictly ordered I/O
+registers that form implicit I/O barriers. If this isn't sufficient then an
+mmiowb() may need to be used explicitly.
+
+
+A similar situation may occur between an interrupt routine and two routines
+running on separate CPUs that communicate with each other. If such a case is
+likely, then interrupt-disabling locks should be used to guarantee ordering.
+
+
+==========================
+KERNEL I/O BARRIER EFFECTS
+==========================
+
+When accessing I/O memory, drivers should use the appropriate accessor
+functions:
+
+ (*) inX(), outX():
+
+ These are intended to talk to I/O space rather than memory space, but
+ that's primarily a CPU-specific concept. The i386 and x86_64 processors do
+ indeed have special I/O space access cycles and instructions, but many
+ CPUs don't have such a concept.
+
+ The PCI bus, amongst others, defines an I/O space concept - which on such
+ CPUs as i386 and x86_64 cpus readily maps to the CPU's concept of I/O
+ space. However, it may also mapped as a virtual I/O space in the CPU's
+ memory map, particularly on those CPUs that don't support alternate
+ I/O spaces.
+
+ Accesses to this space may be fully synchronous (as on i386), but
+ intermediary bridges (such as the PCI host bridge) may not fully honour
+ that.
+
+ They are guaranteed to be fully ordered with respect to each other.
+
+ They are not guaranteed to be fully ordered with respect to other types of
+ memory and I/O operation.
+
+ (*) readX(), writeX():
+
+ Whether these are guaranteed to be fully ordered and uncombined with
+ respect to each other on the issuing CPU depends on the characteristics
+ defined for the memory window through which they're accessing. On later
+ i386 architecture machines, for example, this is controlled by way of the
+ MTRR registers.
+
+ Ordinarily, these will be guaranteed to be fully ordered and uncombined,,
+ provided they're not accessing a prefetchable device.
+
+ However, intermediary hardware (such as a PCI bridge) may indulge in
+ deferral if it so wishes; to flush a store, a load from the same location
+ is preferred[*], but a load from the same device or from configuration
+ space should suffice for PCI.
+
+ [*] NOTE! attempting to load from the same location as was written to may
+ cause a malfunction - consider the 16550 Rx/Tx serial registers for
+ example.
+
+ Used with prefetchable I/O memory, an mmiowb() barrier may be required to
+ force stores to be ordered.
+
+ Please refer to the PCI specification for more information on interactions
+ between PCI transactions.
+
+ (*) readX_relaxed()
+
+ These are similar to readX(), but are not guaranteed to be ordered in any
+ way. Be aware that there is no I/O read barrier available.
+
+ (*) ioreadX(), iowriteX()
+
+ These will perform as appropriate for the type of access they're actually
+ doing, be it inX()/outX() or readX()/writeX().
+
+
+========================================
+ASSUMED MINIMUM EXECUTION ORDERING MODEL
+========================================
+
+It has to be assumed that the conceptual CPU is weakly-ordered but that it will
+maintain the appearance of program causality with respect to itself. Some CPUs
+(such as i386 or x86_64) are more constrained than others (such as powerpc or
+frv), and so the most relaxed case (namely DEC Alpha) must be assumed outside
+of arch-specific code.
+
+This means that it must be considered that the CPU will execute its instruction
+stream in any order it feels like - or even in parallel - provided that if an
+instruction in the stream depends on the an earlier instruction, then that
+earlier instruction must be sufficiently complete[*] before the later
+instruction may proceed; in other words: provided that the appearance of
+causality is maintained.
+
+ [*] Some instructions have more than one effect - such as changing the
+ condition codes, changing registers or changing memory - and different
+ instructions may depend on different effects.
+
+A CPU may also discard any instruction sequence that winds up having no
+ultimate effect. For example, if two adjacent instructions both load an
+immediate value into the same register, the first may be discarded.
+
+
+Similarly, it has to be assumed that compiler might reorder the instruction
+stream in any way it sees fit, again provided the appearance of causality is
+maintained.
+
+
+============================
+THE EFFECTS OF THE CPU CACHE
+============================
+
+The way cached memory operations are perceived across the system is affected to
+a certain extent by the caches that lie between CPUs and memory, and by the
+memory coherence system that maintains the consistency of state in the system.
+
+As far as the way a CPU interacts with another part of the system through the
+caches goes, the memory system has to include the CPU's caches, and memory
+barriers for the most part act at the interface between the CPU and its cache
+(memory barriers logically act on the dotted line in the following diagram):
+
+ <--- CPU ---> : <----------- Memory ----------->
+ :
+ +--------+ +--------+ : +--------+ +-----------+
+ | | | | : | | | | +--------+
+ | CPU | | Memory | : | CPU | | | | |
+ | Core |--->| Access |----->| Cache |<-->| | | |
+ | | | Queue | : | | | |--->| Memory |
+ | | | | : | | | | | |
+ +--------+ +--------+ : +--------+ | | | |
+ : | Cache | +--------+
+ : | Coherency |
+ : | Mechanism | +--------+
+ +--------+ +--------+ : +--------+ | | | |
+ | | | | : | | | | | |
+ | CPU | | Memory | : | CPU | | |--->| Device |
+ | Core |--->| Access |----->| Cache |<-->| | | |
+ | | | Queue | : | | | | | |
+ | | | | : | | | | +--------+
+ +--------+ +--------+ : +--------+ +-----------+
+ :
+ :
+
+Although any particular load or store may not actually appear outside of the
+CPU that issued it since it may have been satisfied within the CPU's own cache,
+it will still appear as if the full memory access had taken place as far as the
+other CPUs are concerned since the cache coherency mechanisms will migrate the
+cacheline over to the accessing CPU and propagate the effects upon conflict.
+
+The CPU core may execute instructions in any order it deems fit, provided the
+expected program causality appears to be maintained. Some of the instructions
+generate load and store operations which then go into the queue of memory
+accesses to be performed. The core may place these in the queue in any order
+it wishes, and continue execution until it is forced to wait for an instruction
+to complete.
+
+What memory barriers are concerned with is controlling the order in which
+accesses cross from the CPU side of things to the memory side of things, and
+the order in which the effects are perceived to happen by the other observers
+in the system.
+
+[!] Memory barriers are _not_ needed within a given CPU, as CPUs always see
+their own loads and stores as if they had happened in program order.
+
+[!] MMIO or other device accesses may bypass the cache system. This depends on
+the properties of the memory window through which devices are accessed and/or
+the use of any special device communication instructions the CPU may have.
+
+
+CACHE COHERENCY
+---------------
+
+Life isn't quite as simple as it may appear above, however: for while the
+caches are expected to be coherent, there's no guarantee that that coherency
+will be ordered. This means that whilst changes made on one CPU will
+eventually become visible on all CPUs, there's no guarantee that they will
+become apparent in the same order on those other CPUs.
+
+
+Consider dealing with a system that has pair of CPUs (1 & 2), each of which has
+a pair of parallel data caches (CPU 1 has A/B, and CPU 2 has C/D):
+
+ :
+ : +--------+
+ : +---------+ | |
+ +--------+ : +--->| Cache A |<------->| |
+ | | : | +---------+ | |
+ | CPU 1 |<---+ | |
+ | | : | +---------+ | |
+ +--------+ : +--->| Cache B |<------->| |
+ : +---------+ | |
+ : | Memory |
+ : +---------+ | System |
+ +--------+ : +--->| Cache C |<------->| |
+ | | : | +---------+ | |
+ | CPU 2 |<---+ | |
+ | | : | +---------+ | |
+ +--------+ : +--->| Cache D |<------->| |
+ : +---------+ | |
+ : +--------+
+ :
+
+Imagine the system has the following properties:
+
+ (*) an odd-numbered cache line may be in cache A, cache C or it may still be
+ resident in memory;
+
+ (*) an even-numbered cache line may be in cache B, cache D or it may still be
+ resident in memory;
+
+ (*) whilst the CPU core is interrogating one cache, the other cache may be
+ making use of the bus to access the rest of the system - perhaps to
+ displace a dirty cacheline or to do a speculative load;
+
+ (*) each cache has a queue of operations that need to be applied to that cache
+ to maintain coherency with the rest of the system;
+
+ (*) the coherency queue is not flushed by normal loads to lines already
+ present in the cache, even though the contents of the queue may
+ potentially effect those loads.
+
+Imagine, then, that two writes are made on the first CPU, with a write barrier
+between them to guarantee that they will appear to reach that CPU's caches in
+the requisite order:
+
+ CPU 1 CPU 2 COMMENT
+ =============== =============== =======================================
+ u == 0, v == 1 and p == &u, q == &u
+ v = 2;
+ smp_wmb(); Make sure change to v visible before
+ change to p
+ <A:modify v=2> v is now in cache A exclusively
+ p = &v;
+ <B:modify p=&v> p is now in cache B exclusively
+
+The write memory barrier forces the other CPUs in the system to perceive that
+the local CPU's caches have apparently been updated in the correct order. But
+now imagine that the second CPU that wants to read those values:
+
+ CPU 1 CPU 2 COMMENT
+ =============== =============== =======================================
+ ...
+ q = p;
+ x = *q;
+
+The above pair of reads may then fail to happen in expected order, as the
+cacheline holding p may get updated in one of the second CPU's caches whilst
+the update to the cacheline holding v is delayed in the other of the second
+CPU's caches by some other cache event:
+
+ CPU 1 CPU 2 COMMENT
+ =============== =============== =======================================
+ u == 0, v == 1 and p == &u, q == &u
+ v = 2;
+ smp_wmb();
+ <A:modify v=2> <C:busy>
+ <C:queue v=2>
+ p = &v; q = p;
+ <D:request p>
+ <B:modify p=&v> <D:commit p=&v>
+ <D:read p>
+ x = *q;
+ <C:read *q> Reads from v before v updated in cache
+ <C:unbusy>
+ <C:commit v=2>
+
+Basically, whilst both cachelines will be updated on CPU 2 eventually, there's
+no guarantee that, without intervention, the order of update will be the same
+as that committed on CPU 1.
+
+
+To intervene, we need to interpolate a data dependency barrier or a read
+barrier between the loads. This will force the cache to commit its coherency
+queue before processing any further requests:
+
+ CPU 1 CPU 2 COMMENT
+ =============== =============== =======================================
+ u == 0, v == 1 and p == &u, q == &u
+ v = 2;
+ smp_wmb();
+ <A:modify v=2> <C:busy>
+ <C:queue v=2>
+ p = &b; q = p;
+ <D:request p>
+ <B:modify p=&v> <D:commit p=&v>
+ <D:read p>
+ smp_read_barrier_depends()
+ <C:unbusy>
+ <C:commit v=2>
+ x = *q;
+ <C:read *q> Reads from v after v updated in cache
+
+
+This sort of problem can be encountered on DEC Alpha processors as they have a
+split cache that improves performance by making better use of the data bus.
+Whilst most CPUs do imply a data dependency barrier on the read when a memory
+access depends on a read, not all do, so it may not be relied on.
+
+Other CPUs may also have split caches, but must coordinate between the various
+cachelets for normal memory accesss. The semantics of the Alpha removes the
+need for coordination in absence of memory barriers.
+
+
+CACHE COHERENCY VS DMA
+----------------------
+
+Not all systems maintain cache coherency with respect to devices doing DMA. In
+such cases, a device attempting DMA may obtain stale data from RAM because
+dirty cache lines may be resident in the caches of various CPUs, and may not
+have been written back to RAM yet. To deal with this, the appropriate part of
+the kernel must flush the overlapping bits of cache on each CPU (and maybe
+invalidate them as well).
+
+In addition, the data DMA'd to RAM by a device may be overwritten by dirty
+cache lines being written back to RAM from a CPU's cache after the device has
+installed its own data, or cache lines simply present in a CPUs cache may
+simply obscure the fact that RAM has been updated, until at such time as the
+cacheline is discarded from the CPU's cache and reloaded. To deal with this,
+the appropriate part of the kernel must invalidate the overlapping bits of the
+cache on each CPU.
+
+See Documentation/cachetlb.txt for more information on cache management.
+
+
+CACHE COHERENCY VS MMIO
+-----------------------
+
+Memory mapped I/O usually takes place through memory locations that are part of
+a window in the CPU's memory space that have different properties assigned than
+the usual RAM directed window.
+
+Amongst these properties is usually the fact that such accesses bypass the
+caching entirely and go directly to the device buses. This means MMIO accesses
+may, in effect, overtake accesses to cached memory that were emitted earlier.
+A memory barrier isn't sufficient in such a case, but rather the cache must be
+flushed between the cached memory write and the MMIO access if the two are in
+any way dependent.
+
+
+=========================
+THE THINGS CPUS GET UP TO
+=========================
+
+A programmer might take it for granted that the CPU will perform memory
+operations in exactly the order specified, so that if a CPU is, for example,
+given the following piece of code to execute:
+
+ a = *A;
+ *B = b;
+ c = *C;
+ d = *D;
+ *E = e;
+
+They would then expect that the CPU will complete the memory operation for each
+instruction before moving on to the next one, leading to a definite sequence of
+operations as seen by external observers in the system:
+
+ LOAD *A, STORE *B, LOAD *C, LOAD *D, STORE *E.
+
+
+Reality is, of course, much messier. With many CPUs and compilers, the above
+assumption doesn't hold because:
+
+ (*) loads are more likely to need to be completed immediately to permit
+ execution progress, whereas stores can often be deferred without a
+ problem;
+
+ (*) loads may be done speculatively, and the result discarded should it prove
+ to have been unnecessary;
+
+ (*) loads may be done speculatively, leading to the result having being
+ fetched at the wrong time in the expected sequence of events;
+
+ (*) the order of the memory accesses may be rearranged to promote better use
+ of the CPU buses and caches;
+
+ (*) loads and stores may be combined to improve performance when talking to
+ memory or I/O hardware that can do batched accesses of adjacent locations,
+ thus cutting down on transaction setup costs (memory and PCI devices may
+ both be able to do this); and
+
+ (*) the CPU's data cache may affect the ordering, and whilst cache-coherency
+ mechanisms may alleviate this - once the store has actually hit the cache
+ - there's no guarantee that the coherency management will be propagated in
+ order to other CPUs.
+
+So what another CPU, say, might actually observe from the above piece of code
+is:
+
+ LOAD *A, ..., LOAD {*C,*D}, STORE *E, STORE *B
+
+ (Where "LOAD {*C,*D}" is a combined load)
+
+
+However, it is guaranteed that a CPU will be self-consistent: it will see its
+_own_ accesses appear to be correctly ordered, without the need for a memory
+barrier. For instance with the following code:
+
+ U = *A;
+ *A = V;
+ *A = W;
+ X = *A;
+ *A = Y;
+ Z = *A;
+
+and assuming no intervention by an external influence, it can be assumed that
+the final result will appear to be:
+
+ U == the original value of *A
+ X == W
+ Z == Y
+ *A == Y
+
+The code above may cause the CPU to generate the full sequence of memory
+accesses:
+
+ U=LOAD *A, STORE *A=V, STORE *A=W, X=LOAD *A, STORE *A=Y, Z=LOAD *A
+
+in that order, but, without intervention, the sequence may have almost any
+combination of elements combined or discarded, provided the program's view of
+the world remains consistent.
+
+The compiler may also combine, discard or defer elements of the sequence before
+the CPU even sees them.
+
+For instance:
+
+ *A = V;
+ *A = W;
+
+may be reduced to:
+
+ *A = W;
+
+since, without a write barrier, it can be assumed that the effect of the
+storage of V to *A is lost. Similarly:
+
+ *A = Y;
+ Z = *A;
+
+may, without a memory barrier, be reduced to:
+
+ *A = Y;
+ Z = Y;
+
+and the LOAD operation never appear outside of the CPU.
+
+
+AND THEN THERE'S THE ALPHA
+--------------------------
+
+The DEC Alpha CPU is one of the most relaxed CPUs there is. Not only that,
+some versions of the Alpha CPU have a split data cache, permitting them to have
+two semantically related cache lines updating at separate times. This is where
+the data dependency barrier really becomes necessary as this synchronises both
+caches with the memory coherence system, thus making it seem like pointer
+changes vs new data occur in the right order.
+
+The Alpha defines the Linux's kernel's memory barrier model.
+
+See the subsection on "Cache Coherency" above.
+
+
+==========
+REFERENCES
+==========
+
+Alpha AXP Architecture Reference Manual, Second Edition (Sites & Witek,
+Digital Press)
+ Chapter 5.2: Physical Address Space Characteristics
+ Chapter 5.4: Caches and Write Buffers
+ Chapter 5.5: Data Sharing
+ Chapter 5.6: Read/Write Ordering
+
+AMD64 Architecture Programmer's Manual Volume 2: System Programming
+ Chapter 7.1: Memory-Access Ordering
+ Chapter 7.4: Buffering and Combining Memory Writes
+
+IA-32 Intel Architecture Software Developer's Manual, Volume 3:
+System Programming Guide
+ Chapter 7.1: Locked Atomic Operations
+ Chapter 7.2: Memory Ordering
+ Chapter 7.4: Serializing Instructions
+
+The SPARC Architecture Manual, Version 9
+ Chapter 8: Memory Models
+ Appendix D: Formal Specification of the Memory Models
+ Appendix J: Programming with the Memory Models
+
+UltraSPARC Programmer Reference Manual
+ Chapter 5: Memory Accesses and Cacheability
+ Chapter 15: Sparc-V9 Memory Models
+
+UltraSPARC III Cu User's Manual
+ Chapter 9: Memory Models
+
+UltraSPARC IIIi Processor User's Manual
+ Chapter 8: Memory Models
+
+UltraSPARC Architecture 2005
+ Chapter 9: Memory
+ Appendix D: Formal Specifications of the Memory Models
+
+UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005
+ Chapter 8: Memory Models
+ Appendix F: Caches and Cache Coherency
+
+Solaris Internals, Core Kernel Architecture, p63-68:
+ Chapter 3.3: Hardware Considerations for Locks and
+ Synchronization
+
+Unix Systems for Modern Architectures, Symmetric Multiprocessing and Caching
+for Kernel Programmers:
+ Chapter 13: Other Memory Models
+
+Intel Itanium Architecture Software Developer's Manual: Volume 1:
+ Section 2.6: Speculation
+ Section 4.4: Memory Access
diff --git a/Documentation/mtrr.txt b/Documentation/mtrr.txt
index b78af1c3299..c39ac395970 100644
--- a/Documentation/mtrr.txt
+++ b/Documentation/mtrr.txt
@@ -138,19 +138,29 @@ Reading MTRRs from a C program using ioctl()'s:
*/
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
-#define MTRR_NEED_STRINGS
#include <asm/mtrr.h>
#define TRUE 1
#define FALSE 0
#define ERRSTRING strerror (errno)
+static char *mtrr_strings[MTRR_NUM_TYPES] =
+{
+ "uncachable", /* 0 */
+ "write-combining", /* 1 */
+ "?", /* 2 */
+ "?", /* 3 */
+ "write-through", /* 4 */
+ "write-protect", /* 5 */
+ "write-back", /* 6 */
+};
int main ()
{
@@ -232,13 +242,22 @@ Creating MTRRs from a C programme using ioctl()'s:
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
-#define MTRR_NEED_STRINGS
#include <asm/mtrr.h>
#define TRUE 1
#define FALSE 0
#define ERRSTRING strerror (errno)
+static char *mtrr_strings[MTRR_NUM_TYPES] =
+{
+ "uncachable", /* 0 */
+ "write-combining", /* 1 */
+ "?", /* 2 */
+ "?", /* 3 */
+ "write-through", /* 4 */
+ "write-protect", /* 5 */
+ "write-back", /* 6 */
+};
int main (int argc, char **argv)
{
diff --git a/Documentation/networking/TODO b/Documentation/networking/TODO
deleted file mode 100644
index 66d36ff14ba..00000000000
--- a/Documentation/networking/TODO
+++ /dev/null
@@ -1,18 +0,0 @@
-To-do items for network drivers
--------------------------------
-
-* Move ethernet crc routine to generic code
-
-* (for 2.5) Integrate Jamal Hadi Salim's netdev Rx polling API change
-
-* Audit all net drivers to make sure magic packet / wake-on-lan /
- similar features are disabled in the driver by default.
-
-* Audit all net drivers to make sure the module always prints out a
- version string when loaded as a module, but only prints a version
- string when built into the kernel if a device is detected.
-
-* Add ETHTOOL_GDRVINFO ioctl support to all ethernet drivers.
-
-* dmfe PCI DMA is totally wrong and only works on x86
-
diff --git a/Documentation/networking/bcm43xx.txt b/Documentation/networking/bcm43xx.txt
new file mode 100644
index 00000000000..28541d2bee1
--- /dev/null
+++ b/Documentation/networking/bcm43xx.txt
@@ -0,0 +1,36 @@
+
+ BCM43xx Linux Driver Project
+ ============================
+
+About this software
+-------------------
+
+The goal of this project is to develop a linux driver for Broadcom
+BCM43xx chips, based on the specification at
+http://bcm-specs.sipsolutions.net/
+
+The project page is http://bcm43xx.berlios.de/
+
+
+Requirements
+------------
+
+1) Linux Kernel 2.6.16 or later
+ http://www.kernel.org/
+
+ You may want to configure your kernel with:
+
+ CONFIG_DEBUG_FS (optional):
+ -> Kernel hacking
+ -> Debug Filesystem
+
+2) SoftMAC IEEE 802.11 Networking Stack extension and patched ieee80211
+ modules:
+ http://softmac.sipsolutions.net/
+
+3) Firmware Files
+
+ Please try fwcutter. Fwcutter can extract the firmware from various
+ binary driver files. It supports driver files from Windows, MacOS and
+ Linux. You can get fwcutter from http://bcm43xx.berlios.de/.
+ Also, fwcutter comes with a README file for further instructions.
diff --git a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c
index 545447ac503..a1205988675 100644
--- a/Documentation/networking/ifenslave.c
+++ b/Documentation/networking/ifenslave.c
@@ -87,7 +87,7 @@
* would fail and generate an error message in the system log.
* - For opt_c: slave should not be set to the master's setting
* while it is running. It was already set during enslave. To
- * simplify things, it is now handeled separately.
+ * simplify things, it is now handled separately.
*
* - 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
* - Code cleanup and style changes
diff --git a/Documentation/networking/operstates.txt b/Documentation/networking/operstates.txt
new file mode 100644
index 00000000000..4a21d9bb836
--- /dev/null
+++ b/Documentation/networking/operstates.txt
@@ -0,0 +1,161 @@
+
+1. Introduction
+
+Linux distinguishes between administrative and operational state of an
+interface. Admininstrative state is the result of "ip link set dev
+<dev> up or down" and reflects whether the administrator wants to use
+the device for traffic.
+
+However, an interface is not usable just because the admin enabled it
+- ethernet requires to be plugged into the switch and, depending on
+a site's networking policy and configuration, an 802.1X authentication
+to be performed before user data can be transferred. Operational state
+shows the ability of an interface to transmit this user data.
+
+Thanks to 802.1X, userspace must be granted the possibility to
+influence operational state. To accommodate this, operational state is
+split into two parts: Two flags that can be set by the driver only, and
+a RFC2863 compatible state that is derived from these flags, a policy,
+and changeable from userspace under certain rules.
+
+
+2. Querying from userspace
+
+Both admin and operational state can be queried via the netlink
+operation RTM_GETLINK. It is also possible to subscribe to RTMGRP_LINK
+to be notified of updates. This is important for setting from userspace.
+
+These values contain interface state:
+
+ifinfomsg::if_flags & IFF_UP:
+ Interface is admin up
+ifinfomsg::if_flags & IFF_RUNNING:
+ Interface is in RFC2863 operational state UP or UNKNOWN. This is for
+ backward compatibility, routing daemons, dhcp clients can use this
+ flag to determine whether they should use the interface.
+ifinfomsg::if_flags & IFF_LOWER_UP:
+ Driver has signaled netif_carrier_on()
+ifinfomsg::if_flags & IFF_DORMANT:
+ Driver has signaled netif_dormant_on()
+
+These interface flags can also be queried without netlink using the
+SIOCGIFFLAGS ioctl.
+
+TLV IFLA_OPERSTATE
+
+contains RFC2863 state of the interface in numeric representation:
+
+IF_OPER_UNKNOWN (0):
+ Interface is in unknown state, neither driver nor userspace has set
+ operational state. Interface must be considered for user data as
+ setting operational state has not been implemented in every driver.
+IF_OPER_NOTPRESENT (1):
+ Unused in current kernel (notpresent interfaces normally disappear),
+ just a numerical placeholder.
+IF_OPER_DOWN (2):
+ Interface is unable to transfer data on L1, f.e. ethernet is not
+ plugged or interface is ADMIN down.
+IF_OPER_LOWERLAYERDOWN (3):
+ Interfaces stacked on an interface that is IF_OPER_DOWN show this
+ state (f.e. VLAN).
+IF_OPER_TESTING (4):
+ Unused in current kernel.
+IF_OPER_DORMANT (5):
+ Interface is L1 up, but waiting for an external event, f.e. for a
+ protocol to establish. (802.1X)
+IF_OPER_UP (6):
+ Interface is operational up and can be used.
+
+This TLV can also be queried via sysfs.
+
+TLV IFLA_LINKMODE
+
+contains link policy. This is needed for userspace interaction
+described below.
+
+This TLV can also be queried via sysfs.
+
+
+3. Kernel driver API
+
+Kernel drivers have access to two flags that map to IFF_LOWER_UP and
+IFF_DORMANT. These flags can be set from everywhere, even from
+interrupts. It is guaranteed that only the driver has write access,
+however, if different layers of the driver manipulate the same flag,
+the driver has to provide the synchronisation needed.
+
+__LINK_STATE_NOCARRIER, maps to !IFF_LOWER_UP:
+
+The driver uses netif_carrier_on() to clear and netif_carrier_off() to
+set this flag. On netif_carrier_off(), the scheduler stops sending
+packets. The name 'carrier' and the inversion are historical, think of
+it as lower layer.
+
+netif_carrier_ok() can be used to query that bit.
+
+__LINK_STATE_DORMANT, maps to IFF_DORMANT:
+
+Set by the driver to express that the device cannot yet be used
+because some driver controlled protocol establishment has to
+complete. Corresponding functions are netif_dormant_on() to set the
+flag, netif_dormant_off() to clear it and netif_dormant() to query.
+
+On device allocation, networking core sets the flags equivalent to
+netif_carrier_ok() and !netif_dormant().
+
+
+Whenever the driver CHANGES one of these flags, a workqueue event is
+scheduled to translate the flag combination to IFLA_OPERSTATE as
+follows:
+
+!netif_carrier_ok():
+ IF_OPER_LOWERLAYERDOWN if the interface is stacked, IF_OPER_DOWN
+ otherwise. Kernel can recognise stacked interfaces because their
+ ifindex != iflink.
+
+netif_carrier_ok() && netif_dormant():
+ IF_OPER_DORMANT
+
+netif_carrier_ok() && !netif_dormant():
+ IF_OPER_UP if userspace interaction is disabled. Otherwise
+ IF_OPER_DORMANT with the possibility for userspace to initiate the
+ IF_OPER_UP transition afterwards.
+
+
+4. Setting from userspace
+
+Applications have to use the netlink interface to influence the
+RFC2863 operational state of an interface. Setting IFLA_LINKMODE to 1
+via RTM_SETLINK instructs the kernel that an interface should go to
+IF_OPER_DORMANT instead of IF_OPER_UP when the combination
+netif_carrier_ok() && !netif_dormant() is set by the
+driver. Afterwards, the userspace application can set IFLA_OPERSTATE
+to IF_OPER_DORMANT or IF_OPER_UP as long as the driver does not set
+netif_carrier_off() or netif_dormant_on(). Changes made by userspace
+are multicasted on the netlink group RTMGRP_LINK.
+
+So basically a 802.1X supplicant interacts with the kernel like this:
+
+-subscribe to RTMGRP_LINK
+-set IFLA_LINKMODE to 1 via RTM_SETLINK
+-query RTM_GETLINK once to get initial state
+-if initial flags are not (IFF_LOWER_UP && !IFF_DORMANT), wait until
+ netlink multicast signals this state
+-do 802.1X, eventually abort if flags go down again
+-send RTM_SETLINK to set operstate to IF_OPER_UP if authentication
+ succeeds, IF_OPER_DORMANT otherwise
+-see how operstate and IFF_RUNNING is echoed via netlink multicast
+-set interface back to IF_OPER_DORMANT if 802.1X reauthentication
+ fails
+-restart if kernel changes IFF_LOWER_UP or IFF_DORMANT flag
+
+if supplicant goes down, bring back IFLA_LINKMODE to 0 and
+IFLA_OPERSTATE to a sane value.
+
+A routing daemon or dhcp client just needs to care for IFF_RUNNING or
+waiting for operstate to go IF_OPER_UP/IF_OPER_UNKNOWN before
+considering the interface / querying a DHCP address.
+
+
+For technical questions and/or comments please e-mail to Stefan Rompf
+(stefan at loplof.de).
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt
index 4fc8e987432..aaf99d5f0da 100644
--- a/Documentation/networking/packet_mmap.txt
+++ b/Documentation/networking/packet_mmap.txt
@@ -254,7 +254,7 @@ and, the number of frames be
<block number> * <block size> / <frame size>
-Suposse the following parameters, which apply for 2.6 kernel and an
+Suppose the following parameters, which apply for 2.6 kernel and an
i386 architecture:
<size-max> = 131072 bytes
diff --git a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt
index ec3d109d787..76750fb9151 100644
--- a/Documentation/networking/tuntap.txt
+++ b/Documentation/networking/tuntap.txt
@@ -138,7 +138,7 @@ This means that you have to read/write IP packets when you are using tun and
ethernet frames when using tap.
5. What is the difference between BPF and TUN/TAP driver?
-BFP is an advanced packet filter. It can be attached to existing
+BPF is an advanced packet filter. It can be attached to existing
network interface. It does not provide a virtual network interface.
A TUN/TAP driver does provide a virtual network interface and it is possible
to attach BPF to this interface.
diff --git a/Documentation/networking/xfrm_sync.txt b/Documentation/networking/xfrm_sync.txt
new file mode 100644
index 00000000000..8be626f7c0b
--- /dev/null
+++ b/Documentation/networking/xfrm_sync.txt
@@ -0,0 +1,166 @@
+
+The sync patches work is based on initial patches from
+Krisztian <hidden@balabit.hu> and others and additional patches
+from Jamal <hadi@cyberus.ca>.
+
+The end goal for syncing is to be able to insert attributes + generate
+events so that the an SA can be safely moved from one machine to another
+for HA purposes.
+The idea is to synchronize the SA so that the takeover machine can do
+the processing of the SA as accurate as possible if it has access to it.
+
+We already have the ability to generate SA add/del/upd events.
+These patches add ability to sync and have accurate lifetime byte (to
+ensure proper decay of SAs) and replay counters to avoid replay attacks
+with as minimal loss at failover time.
+This way a backup stays as closely uptodate as an active member.
+
+Because the above items change for every packet the SA receives,
+it is possible for a lot of the events to be generated.
+For this reason, we also add a nagle-like algorithm to restrict
+the events. i.e we are going to set thresholds to say "let me
+know if the replay sequence threshold is reached or 10 secs have passed"
+These thresholds are set system-wide via sysctls or can be updated
+per SA.
+
+The identified items that need to be synchronized are:
+- the lifetime byte counter
+note that: lifetime time limit is not important if you assume the failover
+machine is known ahead of time since the decay of the time countdown
+is not driven by packet arrival.
+- the replay sequence for both inbound and outbound
+
+1) Message Structure
+----------------------
+
+nlmsghdr:aevent_id:optional-TLVs.
+
+The netlink message types are:
+
+XFRM_MSG_NEWAE and XFRM_MSG_GETAE.
+
+A XFRM_MSG_GETAE does not have TLVs.
+A XFRM_MSG_NEWAE will have at least two TLVs (as is
+discussed further below).
+
+aevent_id structure looks like:
+
+ struct xfrm_aevent_id {
+ struct xfrm_usersa_id sa_id;
+ __u32 flags;
+ };
+
+xfrm_usersa_id in this message layout identifies the SA.
+
+flags are used to indicate different things. The possible
+flags are:
+ XFRM_AE_RTHR=1, /* replay threshold*/
+ XFRM_AE_RVAL=2, /* replay value */
+ XFRM_AE_LVAL=4, /* lifetime value */
+ XFRM_AE_ETHR=8, /* expiry timer threshold */
+ XFRM_AE_CR=16, /* Event cause is replay update */
+ XFRM_AE_CE=32, /* Event cause is timer expiry */
+ XFRM_AE_CU=64, /* Event cause is policy update */
+
+How these flags are used is dependent on the direction of the
+message (kernel<->user) as well the cause (config, query or event).
+This is described below in the different messages.
+
+The pid will be set appropriately in netlink to recognize direction
+(0 to the kernel and pid = processid that created the event
+when going from kernel to user space)
+
+A program needs to subscribe to multicast group XFRMNLGRP_AEVENTS
+to get notified of these events.
+
+2) TLVS reflect the different parameters:
+-----------------------------------------
+
+a) byte value (XFRMA_LTIME_VAL)
+This TLV carries the running/current counter for byte lifetime since
+last event.
+
+b)replay value (XFRMA_REPLAY_VAL)
+This TLV carries the running/current counter for replay sequence since
+last event.
+
+c)replay threshold (XFRMA_REPLAY_THRESH)
+This TLV carries the threshold being used by the kernel to trigger events
+when the replay sequence is exceeded.
+
+d) expiry timer (XFRMA_ETIMER_THRESH)
+This is a timer value in milliseconds which is used as the nagle
+value to rate limit the events.
+
+3) Default configurations for the parameters:
+----------------------------------------------
+
+By default these events should be turned off unless there is
+at least one listener registered to listen to the multicast
+group XFRMNLGRP_AEVENTS.
+
+Programs installing SAs will need to specify the two thresholds, however,
+in order to not change existing applications such as racoon
+we also provide default threshold values for these different parameters
+in case they are not specified.
+
+the two sysctls/proc entries are:
+a) /proc/sys/net/core/sysctl_xfrm_aevent_etime
+used to provide default values for the XFRMA_ETIMER_THRESH in incremental
+units of time of 100ms. The default is 10 (1 second)
+
+b) /proc/sys/net/core/sysctl_xfrm_aevent_rseqth
+used to provide default values for XFRMA_REPLAY_THRESH parameter
+in incremental packet count. The default is two packets.
+
+4) Message types
+----------------
+
+a) XFRM_MSG_GETAE issued by user-->kernel.
+XFRM_MSG_GETAE does not carry any TLVs.
+The response is a XFRM_MSG_NEWAE which is formatted based on what
+XFRM_MSG_GETAE queried for.
+The response will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
+*if XFRM_AE_RTHR flag is set, then XFRMA_REPLAY_THRESH is also retrieved
+*if XFRM_AE_ETHR flag is set, then XFRMA_ETIMER_THRESH is also retrieved
+
+b) XFRM_MSG_NEWAE is issued by either user space to configure
+or kernel to announce events or respond to a XFRM_MSG_GETAE.
+
+i) user --> kernel to configure a specific SA.
+any of the values or threshold parameters can be updated by passing the
+appropriate TLV.
+A response is issued back to the sender in user space to indicate success
+or failure.
+In the case of success, additionally an event with
+XFRM_MSG_NEWAE is also issued to any listeners as described in iii).
+
+ii) kernel->user direction as a response to XFRM_MSG_GETAE
+The response will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
+The threshold TLVs will be included if explicitly requested in
+the XFRM_MSG_GETAE message.
+
+iii) kernel->user to report as event if someone sets any values or
+thresholds for an SA using XFRM_MSG_NEWAE (as described in #i above).
+In such a case XFRM_AE_CU flag is set to inform the user that
+the change happened as a result of an update.
+The message will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
+
+iv) kernel->user to report event when replay threshold or a timeout
+is exceeded.
+In such a case either XFRM_AE_CR (replay exceeded) or XFRM_AE_CE (timeout
+happened) is set to inform the user what happened.
+Note the two flags are mutually exclusive.
+The message will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
+
+Exceptions to threshold settings
+--------------------------------
+
+If you have an SA that is getting hit by traffic in bursts such that
+there is a period where the timer threshold expires with no packets
+seen, then an odd behavior is seen as follows:
+The first packet arrival after a timer expiry will trigger a timeout
+aevent; i.e we dont wait for a timeout period or a packet threshold
+to be reached. This is done for simplicity and efficiency reasons.
+
+-JHS
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 711210b38f5..66bbbf1d1ef 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -259,7 +259,17 @@ on the bus need to be capable of doing it, so this is something which needs
to be handled by platform and generic code, not individual drivers.
-8. Obsolete functions
+8. Vendor and device identifications
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+For the future, let's avoid adding device ids to include/linux/pci_ids.h.
+
+PCI_VENDOR_ID_xxx for vendors, and a hex constant for device ids.
+
+Rationale: PCI_VENDOR_ID_xxx constants are re-used, but device ids are not.
+ Further, device ids are arbitrary hex numbers, normally used only in a
+ single location, the pci_device_id table.
+
+9. Obsolete functions
~~~~~~~~~~~~~~~~~~~~~
There are several functions which you might come across when trying to
port an old driver to the new PCI interface. They are no longer present
diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index 97420f08c78..4739c5c3fac 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -1,5 +1,11 @@
This file details changes in 2.6 which affect PCMCIA card driver authors:
+* New release helper (as of 2.6.17)
+ Instead of calling pcmcia_release_{configuration,io,irq,win}, all that's
+ necessary now is calling pcmcia_disable_device. As there is no valid
+ reason left to call pcmcia_release_io and pcmcia_release_irq, the
+ exports for them were removed.
+
* Unify detach and REMOVAL event code, as well as attach and INSERTION
code (as of 2.6.16)
void (*remove) (struct pcmcia_device *dev);
diff --git a/Documentation/pnp.txt b/Documentation/pnp.txt
index af0f6eabfa1..9529c9c9fd5 100644
--- a/Documentation/pnp.txt
+++ b/Documentation/pnp.txt
@@ -115,6 +115,9 @@ pnp_unregister_protocol
pnp_register_driver
- adds a PnP driver to the Plug and Play Layer
- this includes driver model integration
+- returns zero for success or a negative error number for failure; count
+ calls to the .add() method if you need to know how many devices bind to
+ the driver
pnp_unregister_driver
- removes a PnP driver from the Plug and Play Layer
diff --git a/Documentation/power/video.txt b/Documentation/power/video.txt
index d18a57d1a53..43a889f8f08 100644
--- a/Documentation/power/video.txt
+++ b/Documentation/power/video.txt
@@ -140,7 +140,7 @@ IBM TP T41p s3_bios (2), switch to X after resume
IBM TP T42 s3_bios (2)
IBM ThinkPad T42p (2373-GTG) s3_bios (2)
IBM TP X20 ??? (*)
-IBM TP X30 s3_bios (2)
+IBM TP X30 s3_bios, s3_mode (4)
IBM TP X31 / Type 2672-XXH none (1), use radeontool (http://fdd.com/software/radeon/) to turn off backlight.
IBM TP X32 none (1), but backlight is on and video is trashed after long suspend. s3_bios,s3_mode (4) works too. Perhaps that gets better results?
IBM Thinkpad X40 Type 2371-7JG s3_bios,s3_mode (4)
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index ee551c6ea23..217e51768b8 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -719,6 +719,11 @@ address which can extend beyond that limit.
- model : this is your board name/model
- #address-cells : address representation for "root" devices
- #size-cells: the size representation for "root" devices
+ - device_type : This property shouldn't be necessary. However, if
+ you decide to create a device_type for your root node, make sure it
+ is _not_ "chrp" unless your platform is a pSeries or PAPR compliant
+ one for 64-bit, or a CHRP-type machine for 32-bit as this will
+ matched by the kernel this way.
Additionally, some recommended properties are:
diff --git a/Documentation/robust-futex-ABI.txt b/Documentation/robust-futex-ABI.txt
new file mode 100644
index 00000000000..8529a17ffaa
--- /dev/null
+++ b/Documentation/robust-futex-ABI.txt
@@ -0,0 +1,182 @@
+Started by Paul Jackson <pj@sgi.com>
+
+The robust futex ABI
+--------------------
+
+Robust_futexes provide a mechanism that is used in addition to normal
+futexes, for kernel assist of cleanup of held locks on task exit.
+
+The interesting data as to what futexes a thread is holding is kept on a
+linked list in user space, where it can be updated efficiently as locks
+are taken and dropped, without kernel intervention. The only additional
+kernel intervention required for robust_futexes above and beyond what is
+required for futexes is:
+
+ 1) a one time call, per thread, to tell the kernel where its list of
+ held robust_futexes begins, and
+ 2) internal kernel code at exit, to handle any listed locks held
+ by the exiting thread.
+
+The existing normal futexes already provide a "Fast Userspace Locking"
+mechanism, which handles uncontested locking without needing a system
+call, and handles contested locking by maintaining a list of waiting
+threads in the kernel. Options on the sys_futex(2) system call support
+waiting on a particular futex, and waking up the next waiter on a
+particular futex.
+
+For robust_futexes to work, the user code (typically in a library such
+as glibc linked with the application) has to manage and place the
+necessary list elements exactly as the kernel expects them. If it fails
+to do so, then improperly listed locks will not be cleaned up on exit,
+probably causing deadlock or other such failure of the other threads
+waiting on the same locks.
+
+A thread that anticipates possibly using robust_futexes should first
+issue the system call:
+
+ asmlinkage long
+ sys_set_robust_list(struct robust_list_head __user *head, size_t len);
+
+The pointer 'head' points to a structure in the threads address space
+consisting of three words. Each word is 32 bits on 32 bit arch's, or 64
+bits on 64 bit arch's, and local byte order. Each thread should have
+its own thread private 'head'.
+
+If a thread is running in 32 bit compatibility mode on a 64 native arch
+kernel, then it can actually have two such structures - one using 32 bit
+words for 32 bit compatibility mode, and one using 64 bit words for 64
+bit native mode. The kernel, if it is a 64 bit kernel supporting 32 bit
+compatibility mode, will attempt to process both lists on each task
+exit, if the corresponding sys_set_robust_list() call has been made to
+setup that list.
+
+ The first word in the memory structure at 'head' contains a
+ pointer to a single linked list of 'lock entries', one per lock,
+ as described below. If the list is empty, the pointer will point
+ to itself, 'head'. The last 'lock entry' points back to the 'head'.
+
+ The second word, called 'offset', specifies the offset from the
+ address of the associated 'lock entry', plus or minus, of what will
+ be called the 'lock word', from that 'lock entry'. The 'lock word'
+ is always a 32 bit word, unlike the other words above. The 'lock
+ word' holds 3 flag bits in the upper 3 bits, and the thread id (TID)
+ of the thread holding the lock in the bottom 29 bits. See further
+ below for a description of the flag bits.
+
+ The third word, called 'list_op_pending', contains transient copy of
+ the address of the 'lock entry', during list insertion and removal,
+ and is needed to correctly resolve races should a thread exit while
+ in the middle of a locking or unlocking operation.
+
+Each 'lock entry' on the single linked list starting at 'head' consists
+of just a single word, pointing to the next 'lock entry', or back to
+'head' if there are no more entries. In addition, nearby to each 'lock
+entry', at an offset from the 'lock entry' specified by the 'offset'
+word, is one 'lock word'.
+
+The 'lock word' is always 32 bits, and is intended to be the same 32 bit
+lock variable used by the futex mechanism, in conjunction with
+robust_futexes. The kernel will only be able to wakeup the next thread
+waiting for a lock on a threads exit if that next thread used the futex
+mechanism to register the address of that 'lock word' with the kernel.
+
+For each futex lock currently held by a thread, if it wants this
+robust_futex support for exit cleanup of that lock, it should have one
+'lock entry' on this list, with its associated 'lock word' at the
+specified 'offset'. Should a thread die while holding any such locks,
+the kernel will walk this list, mark any such locks with a bit
+indicating their holder died, and wakeup the next thread waiting for
+that lock using the futex mechanism.
+
+When a thread has invoked the above system call to indicate it
+anticipates using robust_futexes, the kernel stores the passed in 'head'
+pointer for that task. The task may retrieve that value later on by
+using the system call:
+
+ asmlinkage long
+ sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr,
+ size_t __user *len_ptr);
+
+It is anticipated that threads will use robust_futexes embedded in
+larger, user level locking structures, one per lock. The kernel
+robust_futex mechanism doesn't care what else is in that structure, so
+long as the 'offset' to the 'lock word' is the same for all
+robust_futexes used by that thread. The thread should link those locks
+it currently holds using the 'lock entry' pointers. It may also have
+other links between the locks, such as the reverse side of a double
+linked list, but that doesn't matter to the kernel.
+
+By keeping its locks linked this way, on a list starting with a 'head'
+pointer known to the kernel, the kernel can provide to a thread the
+essential service available for robust_futexes, which is to help clean
+up locks held at the time of (a perhaps unexpectedly) exit.
+
+Actual locking and unlocking, during normal operations, is handled
+entirely by user level code in the contending threads, and by the
+existing futex mechanism to wait for, and wakeup, locks. The kernels
+only essential involvement in robust_futexes is to remember where the
+list 'head' is, and to walk the list on thread exit, handling locks
+still held by the departing thread, as described below.
+
+There may exist thousands of futex lock structures in a threads shared
+memory, on various data structures, at a given point in time. Only those
+lock structures for locks currently held by that thread should be on
+that thread's robust_futex linked lock list a given time.
+
+A given futex lock structure in a user shared memory region may be held
+at different times by any of the threads with access to that region. The
+thread currently holding such a lock, if any, is marked with the threads
+TID in the lower 29 bits of the 'lock word'.
+
+When adding or removing a lock from its list of held locks, in order for
+the kernel to correctly handle lock cleanup regardless of when the task
+exits (perhaps it gets an unexpected signal 9 in the middle of
+manipulating this list), the user code must observe the following
+protocol on 'lock entry' insertion and removal:
+
+On insertion:
+ 1) set the 'list_op_pending' word to the address of the 'lock word'
+ to be inserted,
+ 2) acquire the futex lock,
+ 3) add the lock entry, with its thread id (TID) in the bottom 29 bits
+ of the 'lock word', to the linked list starting at 'head', and
+ 4) clear the 'list_op_pending' word.
+
+On removal:
+ 1) set the 'list_op_pending' word to the address of the 'lock word'
+ to be removed,
+ 2) remove the lock entry for this lock from the 'head' list,
+ 2) release the futex lock, and
+ 2) clear the 'lock_op_pending' word.
+
+On exit, the kernel will consider the address stored in
+'list_op_pending' and the address of each 'lock word' found by walking
+the list starting at 'head'. For each such address, if the bottom 29
+bits of the 'lock word' at offset 'offset' from that address equals the
+exiting threads TID, then the kernel will do two things:
+
+ 1) if bit 31 (0x80000000) is set in that word, then attempt a futex
+ wakeup on that address, which will waken the next thread that has
+ used to the futex mechanism to wait on that address, and
+ 2) atomically set bit 30 (0x40000000) in the 'lock word'.
+
+In the above, bit 31 was set by futex waiters on that lock to indicate
+they were waiting, and bit 30 is set by the kernel to indicate that the
+lock owner died holding the lock.
+
+The kernel exit code will silently stop scanning the list further if at
+any point:
+
+ 1) the 'head' pointer or an subsequent linked list pointer
+ is not a valid address of a user space word
+ 2) the calculated location of the 'lock word' (address plus
+ 'offset') is not the valud address of a 32 bit user space
+ word
+ 3) if the list contains more than 1 million (subject to
+ future kernel configuration changes) elements.
+
+When the kernel sees a list entry whose 'lock word' doesn't have the
+current threads TID in the lower 29 bits, it does nothing with that
+entry, and goes on to the next entry.
+
+Bit 29 (0x20000000) of the 'lock word' is reserved for future use.
diff --git a/Documentation/robust-futexes.txt b/Documentation/robust-futexes.txt
new file mode 100644
index 00000000000..df82d75245a
--- /dev/null
+++ b/Documentation/robust-futexes.txt
@@ -0,0 +1,218 @@
+Started by: Ingo Molnar <mingo@redhat.com>
+
+Background
+----------
+
+what are robust futexes? To answer that, we first need to understand
+what futexes are: normal futexes are special types of locks that in the
+noncontended case can be acquired/released from userspace without having
+to enter the kernel.
+
+A futex is in essence a user-space address, e.g. a 32-bit lock variable
+field. If userspace notices contention (the lock is already owned and
+someone else wants to grab it too) then the lock is marked with a value
+that says "there's a waiter pending", and the sys_futex(FUTEX_WAIT)
+syscall is used to wait for the other guy to release it. The kernel
+creates a 'futex queue' internally, so that it can later on match up the
+waiter with the waker - without them having to know about each other.
+When the owner thread releases the futex, it notices (via the variable
+value) that there were waiter(s) pending, and does the
+sys_futex(FUTEX_WAKE) syscall to wake them up. Once all waiters have
+taken and released the lock, the futex is again back to 'uncontended'
+state, and there's no in-kernel state associated with it. The kernel
+completely forgets that there ever was a futex at that address. This
+method makes futexes very lightweight and scalable.
+
+"Robustness" is about dealing with crashes while holding a lock: if a
+process exits prematurely while holding a pthread_mutex_t lock that is
+also shared with some other process (e.g. yum segfaults while holding a
+pthread_mutex_t, or yum is kill -9-ed), then waiters for that lock need
+to be notified that the last owner of the lock exited in some irregular
+way.
+
+To solve such types of problems, "robust mutex" userspace APIs were
+created: pthread_mutex_lock() returns an error value if the owner exits
+prematurely - and the new owner can decide whether the data protected by
+the lock can be recovered safely.
+
+There is a big conceptual problem with futex based mutexes though: it is
+the kernel that destroys the owner task (e.g. due to a SEGFAULT), but
+the kernel cannot help with the cleanup: if there is no 'futex queue'
+(and in most cases there is none, futexes being fast lightweight locks)
+then the kernel has no information to clean up after the held lock!
+Userspace has no chance to clean up after the lock either - userspace is
+the one that crashes, so it has no opportunity to clean up. Catch-22.
+
+In practice, when e.g. yum is kill -9-ed (or segfaults), a system reboot
+is needed to release that futex based lock. This is one of the leading
+bugreports against yum.
+
+To solve this problem, the traditional approach was to extend the vma
+(virtual memory area descriptor) concept to have a notion of 'pending
+robust futexes attached to this area'. This approach requires 3 new
+syscall variants to sys_futex(): FUTEX_REGISTER, FUTEX_DEREGISTER and
+FUTEX_RECOVER. At do_exit() time, all vmas are searched to see whether
+they have a robust_head set. This approach has two fundamental problems
+left:
+
+ - it has quite complex locking and race scenarios. The vma-based
+ approach had been pending for years, but they are still not completely
+ reliable.
+
+ - they have to scan _every_ vma at sys_exit() time, per thread!
+
+The second disadvantage is a real killer: pthread_exit() takes around 1
+microsecond on Linux, but with thousands (or tens of thousands) of vmas
+every pthread_exit() takes a millisecond or more, also totally
+destroying the CPU's L1 and L2 caches!
+
+This is very much noticeable even for normal process sys_exit_group()
+calls: the kernel has to do the vma scanning unconditionally! (this is
+because the kernel has no knowledge about how many robust futexes there
+are to be cleaned up, because a robust futex might have been registered
+in another task, and the futex variable might have been simply mmap()-ed
+into this process's address space).
+
+This huge overhead forced the creation of CONFIG_FUTEX_ROBUST so that
+normal kernels can turn it off, but worse than that: the overhead makes
+robust futexes impractical for any type of generic Linux distribution.
+
+So something had to be done.
+
+New approach to robust futexes
+------------------------------
+
+At the heart of this new approach there is a per-thread private list of
+robust locks that userspace is holding (maintained by glibc) - which
+userspace list is registered with the kernel via a new syscall [this
+registration happens at most once per thread lifetime]. At do_exit()
+time, the kernel checks this user-space list: are there any robust futex
+locks to be cleaned up?
+
+In the common case, at do_exit() time, there is no list registered, so
+the cost of robust futexes is just a simple current->robust_list != NULL
+comparison. If the thread has registered a list, then normally the list
+is empty. If the thread/process crashed or terminated in some incorrect
+way then the list might be non-empty: in this case the kernel carefully
+walks the list [not trusting it], and marks all locks that are owned by
+this thread with the FUTEX_OWNER_DEAD bit, and wakes up one waiter (if
+any).
+
+The list is guaranteed to be private and per-thread at do_exit() time,
+so it can be accessed by the kernel in a lockless way.
+
+There is one race possible though: since adding to and removing from the
+list is done after the futex is acquired by glibc, there is a few
+instructions window for the thread (or process) to die there, leaving
+the futex hung. To protect against this possibility, userspace (glibc)
+also maintains a simple per-thread 'list_op_pending' field, to allow the
+kernel to clean up if the thread dies after acquiring the lock, but just
+before it could have added itself to the list. Glibc sets this
+list_op_pending field before it tries to acquire the futex, and clears
+it after the list-add (or list-remove) has finished.
+
+That's all that is needed - all the rest of robust-futex cleanup is done
+in userspace [just like with the previous patches].
+
+Ulrich Drepper has implemented the necessary glibc support for this new
+mechanism, which fully enables robust mutexes.
+
+Key differences of this userspace-list based approach, compared to the
+vma based method:
+
+ - it's much, much faster: at thread exit time, there's no need to loop
+ over every vma (!), which the VM-based method has to do. Only a very
+ simple 'is the list empty' op is done.
+
+ - no VM changes are needed - 'struct address_space' is left alone.
+
+ - no registration of individual locks is needed: robust mutexes dont
+ need any extra per-lock syscalls. Robust mutexes thus become a very
+ lightweight primitive - so they dont force the application designer
+ to do a hard choice between performance and robustness - robust
+ mutexes are just as fast.
+
+ - no per-lock kernel allocation happens.
+
+ - no resource limits are needed.
+
+ - no kernel-space recovery call (FUTEX_RECOVER) is needed.
+
+ - the implementation and the locking is "obvious", and there are no
+ interactions with the VM.
+
+Performance
+-----------
+
+I have benchmarked the time needed for the kernel to process a list of 1
+million (!) held locks, using the new method [on a 2GHz CPU]:
+
+ - with FUTEX_WAIT set [contended mutex]: 130 msecs
+ - without FUTEX_WAIT set [uncontended mutex]: 30 msecs
+
+I have also measured an approach where glibc does the lock notification
+[which it currently does for !pshared robust mutexes], and that took 256
+msecs - clearly slower, due to the 1 million FUTEX_WAKE syscalls
+userspace had to do.
+
+(1 million held locks are unheard of - we expect at most a handful of
+locks to be held at a time. Nevertheless it's nice to know that this
+approach scales nicely.)
+
+Implementation details
+----------------------
+
+The patch adds two new syscalls: one to register the userspace list, and
+one to query the registered list pointer:
+
+ asmlinkage long
+ sys_set_robust_list(struct robust_list_head __user *head,
+ size_t len);
+
+ asmlinkage long
+ sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr,
+ size_t __user *len_ptr);
+
+List registration is very fast: the pointer is simply stored in
+current->robust_list. [Note that in the future, if robust futexes become
+widespread, we could extend sys_clone() to register a robust-list head
+for new threads, without the need of another syscall.]
+
+So there is virtually zero overhead for tasks not using robust futexes,
+and even for robust futex users, there is only one extra syscall per
+thread lifetime, and the cleanup operation, if it happens, is fast and
+straightforward. The kernel doesnt have any internal distinction between
+robust and normal futexes.
+
+If a futex is found to be held at exit time, the kernel sets the
+following bit of the futex word:
+
+ #define FUTEX_OWNER_DIED 0x40000000
+
+and wakes up the next futex waiter (if any). User-space does the rest of
+the cleanup.
+
+Otherwise, robust futexes are acquired by glibc by putting the TID into
+the futex field atomically. Waiters set the FUTEX_WAITERS bit:
+
+ #define FUTEX_WAITERS 0x80000000
+
+and the remaining bits are for the TID.
+
+Testing, architecture support
+-----------------------------
+
+i've tested the new syscalls on x86 and x86_64, and have made sure the
+parsing of the userspace list is robust [ ;-) ] even if the list is
+deliberately corrupted.
+
+i386 and x86_64 syscalls are wired up at the moment, and Ulrich has
+tested the new glibc code (on x86_64 and i386), and it works for his
+robust-mutex testcases.
+
+All other architectures should build just fine too - but they wont have
+the new syscalls yet.
+
+Architectures need to implement the new futex_atomic_cmpxchg_inatomic()
+inline function before writing up the syscalls (that function returns
+-ENOSYS right now).
diff --git a/Documentation/rpc-cache.txt b/Documentation/rpc-cache.txt
index 2b5d4434fa5..5f757c8cf97 100644
--- a/Documentation/rpc-cache.txt
+++ b/Documentation/rpc-cache.txt
@@ -1,4 +1,4 @@
-This document gives a brief introduction to the caching
+ This document gives a brief introduction to the caching
mechanisms in the sunrpc layer that is used, in particular,
for NFS authentication.
@@ -25,25 +25,17 @@ The common code handles such things as:
- supporting 'NEGATIVE' as well as positive entries
- allowing an EXPIRED time on cache items, and removing
items after they expire, and are no longe in-use.
-
- Future code extensions are expect to handle
- making requests to user-space to fill in cache entries
- allowing user-space to directly set entries in the cache
- delaying RPC requests that depend on as-yet incomplete
cache entries, and replaying those requests when the cache entry
is complete.
- - maintaining last-access times on cache entries
- - clean out old entries when the caches become full
-
-The code for performing a cache lookup is also common, but in the form
-of a template. i.e. a #define.
-Each cache defines a lookup function by using the DefineCacheLookup
-macro, or the simpler DefineSimpleCacheLookup macro
+ - clean out old entries as they expire.
Creating a Cache
----------------
-1/ A cache needs a datum to cache. This is in the form of a
+1/ A cache needs a datum to store. This is in the form of a
structure definition that must contain a
struct cache_head
as an element, usually the first.
@@ -51,35 +43,69 @@ Creating a Cache
Each cache element is reference counted and contains
expiry and update times for use in cache management.
2/ A cache needs a "cache_detail" structure that
- describes the cache. This stores the hash table, and some
- parameters for cache management.
-3/ A cache needs a lookup function. This is created using
- the DefineCacheLookup macro. This lookup function is used both
- to find entries and to update entries. The normal mode for
- updating an entry is to replace the old entry with a new
- entry. However it is possible to allow update-in-place
- for those caches where it makes sense (no atomicity issues
- or indirect reference counting issue)
-4/ A cache needs to be registered using cache_register(). This
- includes in on a list of caches that will be regularly
- cleaned to discard old data. For this to work, some
- thread must periodically call cache_clean
-
+ describes the cache. This stores the hash table, some
+ parameters for cache management, and some operations detailing how
+ to work with particular cache items.
+ The operations requires are:
+ struct cache_head *alloc(void)
+ This simply allocates appropriate memory and returns
+ a pointer to the cache_detail embedded within the
+ structure
+ void cache_put(struct kref *)
+ This is called when the last reference to an item is
+ is dropped. The pointer passed is to the 'ref' field
+ in the cache_head. cache_put should release any
+ references create by 'cache_init' and, if CACHE_VALID
+ is set, any references created by cache_update.
+ It should then release the memory allocated by
+ 'alloc'.
+ int match(struct cache_head *orig, struct cache_head *new)
+ test if the keys in the two structures match. Return
+ 1 if they do, 0 if they don't.
+ void init(struct cache_head *orig, struct cache_head *new)
+ Set the 'key' fields in 'new' from 'orig'. This may
+ include taking references to shared objects.
+ void update(struct cache_head *orig, struct cache_head *new)
+ Set the 'content' fileds in 'new' from 'orig'.
+ int cache_show(struct seq_file *m, struct cache_detail *cd,
+ struct cache_head *h)
+ Optional. Used to provide a /proc file that lists the
+ contents of a cache. This should show one item,
+ usually on just one line.
+ int cache_request(struct cache_detail *cd, struct cache_head *h,
+ char **bpp, int *blen)
+ Format a request to be send to user-space for an item
+ to be instantiated. *bpp is a buffer of size *blen.
+ bpp should be moved forward over the encoded message,
+ and *blen should be reduced to show how much free
+ space remains. Return 0 on success or <0 if not
+ enough room or other problem.
+ int cache_parse(struct cache_detail *cd, char *buf, int len)
+ A message from user space has arrived to fill out a
+ cache entry. It is in 'buf' of length 'len'.
+ cache_parse should parse this, find the item in the
+ cache with sunrpc_cache_lookup, and update the item
+ with sunrpc_cache_update.
+
+
+3/ A cache needs to be registered using cache_register(). This
+ includes it on a list of caches that will be regularly
+ cleaned to discard old data.
+
Using a cache
-------------
-To find a value in a cache, call the lookup function passing it a the
-datum which contains key, and possibly content, and a flag saying
-whether to update the cache with new data from the datum. Depending
-on how the cache lookup function was defined, it may take an extra
-argument to identify the particular cache in question.
+To find a value in a cache, call sunrpc_cache_lookup passing a pointer
+to the cache_head in a sample item with the 'key' fields filled in.
+This will be passed to ->match to identify the target entry. If no
+entry is found, a new entry will be create, added to the cache, and
+marked as not containing valid data.
-Except in cases of kmalloc failure, the lookup function
-will return a new datum which will store the key and
-may contain valid content, or may not.
-This datum is typically passed to cache_check which determines the
-validity of the datum and may later initiate an upcall to fill
-in the data.
+The item returned is typically passed to cache_check which will check
+if the data is valid, and may initiate an up-call to get fresh data.
+cache_check will return -ENOENT in the entry is negative or if an up
+call is needed but not possible, -EAGAIN if an upcall is pending,
+or 0 if the data is valid;
cache_check can be passed a "struct cache_req *". This structure is
typically embedded in the actual request and can be used to create a
@@ -90,6 +116,13 @@ item does become valid, the deferred copy of the request will be
revisited (->revisit). It is expected that this method will
reschedule the request for processing.
+The value returned by sunrpc_cache_lookup can also be passed to
+sunrpc_cache_update to set the content for the item. A second item is
+passed which should hold the content. If the item found by _lookup
+has valid data, then it is discarded and a new item is created. This
+saves any user of an item from worrying about content changing while
+it is being inspected. If the item found by _lookup does not contain
+valid data, then the content is copied across and CACHE_VALID is set.
Populating a cache
------------------
@@ -114,8 +147,8 @@ should be create or updated to have the given content, and the
expiry time should be set on that item.
Reading from a channel is a bit more interesting. When a cache
-lookup fail, or when it suceeds but finds an entry that may soon
-expiry, a request is lodged for that cache item to be updated by
+lookup fails, or when it succeeds but finds an entry that may soon
+expire, a request is lodged for that cache item to be updated by
user-space. These requests appear in the channel file.
Successive reads will return successive requests.
@@ -130,7 +163,7 @@ Thus a user-space helper is likely to:
write a response
loop.
-If it dies and needs to be restarted, any requests that have not be
+If it dies and needs to be restarted, any requests that have not been
answered will still appear in the file and will be read by the new
instance of the helper.
@@ -142,10 +175,9 @@ Each cache should also define a "cache_request" method which
takes a cache item and encodes a request into the buffer
provided.
-
Note: If a cache has no active readers on the channel, and has had not
active readers for more than 60 seconds, further requests will not be
-added to the channel but instead all looks that do not find a valid
+added to the channel but instead all lookups that do not find a valid
entry will fail. This is partly for backward compatibility: The
previous nfs exports table was deemed to be authoritative and a
failed lookup meant a definite 'no'.
@@ -154,18 +186,17 @@ request/response format
-----------------------
While each cache is free to use it's own format for requests
-and responses over channel, the following is recommended are
+and responses over channel, the following is recommended as
appropriate and support routines are available to help:
Each request or response record should be printable ASCII
with precisely one newline character which should be at the end.
Fields within the record should be separated by spaces, normally one.
If spaces, newlines, or nul characters are needed in a field they
-much be quotes. two mechanisms are available:
+much be quoted. two mechanisms are available:
1/ If a field begins '\x' then it must contain an even number of
hex digits, and pairs of these digits provide the bytes in the
field.
2/ otherwise a \ in the field must be followed by 3 octal digits
which give the code for a byte. Other characters are treated
- as them selves. At the very least, space, newlines nul, and
+ as them selves. At the very least, space, newline, nul, and
'\' must be quoted in this way.
-
diff --git a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid
index 09f6300eda4..c173806c91f 100644
--- a/Documentation/scsi/ChangeLog.megaraid
+++ b/Documentation/scsi/ChangeLog.megaraid
@@ -1,3 +1,28 @@
+Release Date : Mon Apr 11 12:27:22 EST 2006 - Seokmann Ju <sju@lsil.com>
+Current Version : 2.20.4.8 (scsi module), 2.20.2.6 (cmm module)
+Older Version : 2.20.4.7 (scsi module), 2.20.2.6 (cmm module)
+
+1. Fixed a bug in megaraid_reset_handler().
+ Customer reported "Unable to handle kernel NULL pointer dereference
+ at virtual address 00000000" when system goes to reset condition
+ for some reason. It happened randomly.
+ Root Cause: in the megaraid_reset_handler(), there is possibility not
+ returning pending packets in the pend_list if there are multiple
+ pending packets.
+ Fix: Made the change in the driver so that it will return all packets
+ in the pend_list.
+
+2. Added change request.
+ As found in the following URL, rmb() only didn't help the
+ problem. I had to increase the loop counter to 0xFFFFFF. (6 F's)
+ http://marc.theaimsgroup.com/?l=linux-scsi&m=110971060502497&w=2
+
+ I attached a patch for your reference, too.
+ Could you check and get this fix in your driver?
+
+ Best Regards,
+ Jun'ichi Nomura
+
Release Date : Fri Nov 11 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
Current Version : 2.20.4.7 (scsi module), 2.20.2.6 (cmm module)
Older Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt
index 331afd791cb..ce767b90bb0 100644
--- a/Documentation/scsi/scsi_eh.txt
+++ b/Documentation/scsi/scsi_eh.txt
@@ -19,9 +19,9 @@ TABLE OF CONTENTS
[2-1-1] Overview
[2-1-2] Flow of scmds through EH
[2-1-3] Flow of control
- [2-2] EH through hostt->eh_strategy_handler()
- [2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions
- [2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions
+ [2-2] EH through transportt->eh_strategy_handler()
+ [2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions
+ [2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions
[2-2-3] Things to consider
@@ -413,9 +413,9 @@ scmd->allowed.
layer of failure of the scmds.
-[2-2] EH through hostt->eh_strategy_handler()
+[2-2] EH through transportt->eh_strategy_handler()
- hostt->eh_strategy_handler() is invoked in the place of
+ transportt->eh_strategy_handler() is invoked in the place of
scsi_unjam_host() and it is responsible for whole recovery process.
On completion, the handler should have made lower layers forget about
all failed scmds and either ready for new commands or offline. Also,
@@ -424,7 +424,7 @@ SCSI midlayer. IOW, of the steps described in [2-1-2], all steps
except for #1 must be implemented by eh_strategy_handler().
-[2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions
+[2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions
The following conditions are true on entry to the handler.
@@ -437,7 +437,7 @@ except for #1 must be implemented by eh_strategy_handler().
- shost->host_failed == shost->host_busy
-[2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions
+[2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions
The following conditions must be true on exit from the handler.
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index 8bbae3e1abd..75a535a975c 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -804,7 +804,6 @@ Summary:
eh_bus_reset_handler - issue SCSI bus reset
eh_device_reset_handler - issue SCSI device reset
eh_host_reset_handler - reset host (host bus adapter)
- eh_strategy_handler - driver supplied alternate to scsi_unjam_host()
info - supply information about given host
ioctl - driver can respond to ioctls
proc_info - supports /proc/scsi/{driver_name}/{host_no}
@@ -970,24 +969,6 @@ Details:
/**
- * eh_strategy_handler - driver supplied alternate to scsi_unjam_host()
- * @shp: host on which error has occurred
- *
- * Returns TRUE if host unjammed, else FALSE.
- *
- * Locks: none
- *
- * Calling context: kernel thread
- *
- * Notes: Invoked from scsi_eh thread. LLD supplied alternate to
- * scsi_unjam_host() found in scsi_error.c
- *
- * Optionally defined in: LLD
- **/
- int eh_strategy_handler(struct Scsi_Host * shp)
-
-
-/**
* info - supply information about given host: driver name plus data
* to distinguish given host
* @shp: host to supply information about
diff --git a/Documentation/serial/driver b/Documentation/serial/driver
index 42ef9970bc8..88ad615dd33 100644
--- a/Documentation/serial/driver
+++ b/Documentation/serial/driver
@@ -3,14 +3,11 @@
--------------------
- $Id: driver,v 1.10 2002/07/22 15:27:30 rmk Exp $
-
-
This document is meant as a brief overview of some aspects of the new serial
driver. It is not complete, any questions you have should be directed to
<rmk@arm.linux.org.uk>
-The reference implementation is contained within serial_amba.c.
+The reference implementation is contained within amba_pl011.c.
@@ -31,6 +28,11 @@ The serial core provides a few helper functions. This includes identifing
the correct port structure (via uart_get_console) and decoding command line
arguments (uart_parse_options).
+There is also a helper function (uart_write_console) which performs a
+character by character write, translating newlines to CRLF sequences.
+Driver writers are recommended to use this function rather than implementing
+their own version.
+
Locking
-------
@@ -86,6 +88,7 @@ hardware.
- TIOCM_DTR DTR signal.
- TIOCM_OUT1 OUT1 signal.
- TIOCM_OUT2 OUT2 signal.
+ - TIOCM_LOOP Set the port into loopback mode.
If the appropriate bit is set, the signal should be driven
active. If the bit is clear, the signal should be driven
inactive.
@@ -141,6 +144,10 @@ hardware.
enable_ms(port)
Enable the modem status interrupts.
+ This method may be called multiple times. Modem status
+ interrupts should be disabled when the shutdown method is
+ called.
+
Locking: port->lock taken.
Interrupts: locally disabled.
This call must not sleep
@@ -160,6 +167,8 @@ hardware.
state. Enable the port for reception. It should not activate
RTS nor DTR; this will be done via a separate call to set_mctrl.
+ This method will only be called when the port is initially opened.
+
Locking: port_sem taken.
Interrupts: globally disabled.
@@ -169,6 +178,11 @@ hardware.
RTS nor DTR; this will have already been done via a separate
call to set_mctrl.
+ Drivers must not access port->info once this call has completed.
+
+ This method will only be called when there are no more users of
+ this port.
+
Locking: port_sem taken.
Interrupts: caller dependent.
@@ -200,12 +214,13 @@ hardware.
The interaction of the iflag bits is as follows (parity error
given as an example):
Parity error INPCK IGNPAR
- None n/a n/a character received
- Yes n/a 0 character discarded
- Yes 0 1 character received, marked as
+ n/a 0 n/a character received, marked as
+ TTY_NORMAL
+ None 1 n/a character received, marked as
TTY_NORMAL
- Yes 1 1 character received, marked as
+ Yes 1 0 character received, marked as
TTY_PARITY
+ Yes 1 1 character discarded
Other flags may be used (eg, xon/xoff characters) if your
hardware supports hardware "soft" flow control.
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 1def6049784..0ee2c7dfc48 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -120,6 +120,34 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
enable - enable card
- Default: enabled, for PCI and ISA PnP cards
+ Module snd-adlib
+ ----------------
+
+ Module for AdLib FM cards.
+
+ port - port # for OPL chip
+
+ This module supports multiple cards. It does not support autoprobe, so
+ the port must be specified. For actual AdLib FM cards it will be 0x388.
+ Note that this card does not have PCM support and no mixer; only FM
+ synthesis.
+
+ Make sure you have "sbiload" from the alsa-tools package available and,
+ after loading the module, find out the assigned ALSA sequencer port
+ number through "sbiload -l". Example output:
+
+ Port Client name Port name
+ 64:0 OPL2 FM synth OPL2 FM Port
+
+ Load the std.sb and drums.sb patches also supplied by sbiload:
+
+ sbiload -p 64:0 std.sb drums.sb
+
+ If you use this driver to drive an OPL3, you can use std.o3 and drums.o3
+ instead. To have the card produce sound, use aplaymidi from alsa-utils:
+
+ aplaymidi -p 64:0 foo.mid
+
Module snd-ad1816a
------------------
@@ -190,6 +218,15 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
The power-management is supported.
+ Module snd-als300
+ -----------------
+
+ Module for Avance Logic ALS300 and ALS300+
+
+ This module supports multiple cards.
+
+ The power-management is supported.
+
Module snd-als4000
------------------
@@ -701,6 +738,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
uniwill 3-jack
F1734 2-jack
lg LG laptop (m1 express dual)
+ lg-lw LG LW20 laptop
test for testing/debugging purpose, almost all controls can be
adjusted. Appearing only when compiled with
$CONFIG_SND_DEBUG=y
@@ -1013,6 +1051,23 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
The power-management is supported.
+ Module snd-miro
+ ---------------
+
+ Module for Miro soundcards: miroSOUND PCM 1 pro,
+ miroSOUND PCM 12,
+ miroSOUND PCM 20 Radio.
+
+ port - Port # (0x530,0x604,0xe80,0xf40)
+ irq - IRQ # (5,7,9,10,11)
+ dma1 - 1st dma # (0,1,3)
+ dma2 - 2nd dma # (0,1)
+ mpu_port - MPU-401 port # (0x300,0x310,0x320,0x330)
+ mpu_irq - MPU-401 irq # (5,7,9,10)
+ fm_port - FM Port # (0x388)
+ wss - enable WSS mode
+ ide - enable onboard ide support
+
Module snd-mixart
-----------------
@@ -1202,6 +1257,20 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
The power-management is supported.
+ Module snd-riptide
+ ------------------
+
+ Module for Conexant Riptide chip
+
+ joystick_port - Joystick port # (default: 0x200)
+ mpu_port - MPU401 port # (default: 0x330)
+ opl3_port - OPL3 port # (default: 0x388)
+
+ This module supports multiple cards.
+ The driver requires the firmware loader support on kernel.
+ You need to install the firmware file "riptide.hex" to the standard
+ firmware path (e.g. /lib/firmware).
+
Module snd-rme32
----------------
diff --git a/Documentation/sound/alsa/Audiophile-Usb.txt b/Documentation/sound/alsa/Audiophile-Usb.txt
index 4692c8e77dc..b535c2a198f 100644
--- a/Documentation/sound/alsa/Audiophile-Usb.txt
+++ b/Documentation/sound/alsa/Audiophile-Usb.txt
@@ -1,4 +1,4 @@
- Guide to using M-Audio Audiophile USB with ALSA and Jack v1.2
+ Guide to using M-Audio Audiophile USB with ALSA and Jack v1.3
========================================================
Thibault Le Meur <Thibault.LeMeur@supelec.fr>
@@ -22,16 +22,16 @@ The device has 4 audio interfaces, and 2 MIDI ports:
* Midi In (Mi)
* Midi Out (Mo)
-The internal DAC/ADC has the following caracteristics:
+The internal DAC/ADC has the following characteristics:
* sample depth of 16 or 24 bits
* sample rate from 8kHz to 96kHz
-* Two ports can't use different sample depths at the same time.Moreover, the
+* Two ports can't use different sample depths at the same time. Moreover, the
Audiophile USB documentation gives the following Warning: "Please exit any
audio application running before switching between bit depths"
Due to the USB 1.1 bandwidth limitation, a limited number of interfaces can be
activated at the same time depending on the audio mode selected:
- * 16-bit/48kHz ==> 4 channels in/ 4 channels out
+ * 16-bit/48kHz ==> 4 channels in/4 channels out
- Ai+Ao+Di+Do
* 24-bit/48kHz ==> 4 channels in/2 channels out,
or 2 channels in/4 channels out
@@ -41,8 +41,8 @@ activated at the same time depending on the audio mode selected:
Important facts about the Digital interface:
--------------------------------------------
- * The Do port additionnaly supports surround-encoded AC-3 and DTS passthrough,
-though I haven't tested it under linux
+ * The Do port additionally supports surround-encoded AC-3 and DTS passthrough,
+though I haven't tested it under Linux
- Note that in this setup only the Do interface can be enabled
* Apart from recording an audio digital stream, enabling the Di port is a way
to synchronize the device to an external sample clock
@@ -60,24 +60,23 @@ synchronization error (for instance sound played at an odd sample rate)
The Audiophile USB MIDI ports will be automatically supported once the
following modules have been loaded:
* snd-usb-audio
- * snd-seq
* snd-seq-midi
-No additionnal setting is required.
+No additional setting is required.
2.2 - Audio ports
-----------------
Audio functions of the Audiophile USB device are handled by the snd-usb-audio
module. This module can work in a default mode (without any device-specific
-parameter), or in an advanced mode with the device-specific parameter called
+parameter), or in an "advanced" mode with the device-specific parameter called
"device_setup".
2.2.1 - Default Alsa driver mode
-The default behaviour of the snd-usb-audio driver is to parse the device
+The default behavior of the snd-usb-audio driver is to parse the device
capabilities at startup and enable all functions inside the device (including
-all ports at any sample rates and any sample depths supported). This approach
+all ports at any supported sample rates and sample depths). This approach
has the advantage to let the driver easily switch from sample rates/depths
automatically according to the need of the application claiming the device.
@@ -114,9 +113,9 @@ gain).
For people having this problem, the snd-usb-audio module has a new module
parameter called "device_setup".
-2.2.2.1 - Initializing the working mode of the Audiohile USB
+2.2.2.1 - Initializing the working mode of the Audiophile USB
-As far as the Audiohile USB device is concerned, this value let the user
+As far as the Audiophile USB device is concerned, this value let the user
specify:
* the sample depth
* the sample rate
@@ -174,20 +173,20 @@ The parameter can be given:
IMPORTANT NOTE WHEN SWITCHING CONFIGURATION:
-------------------------------------------
- * You may need to _first_ intialize the module with the correct device_setup
+ * You may need to _first_ initialize the module with the correct device_setup
parameter and _only_after_ turn on the Audiophile USB device
* This is especially true when switching the sample depth:
- - first trun off the device
- - de-register the snd-usb-audio module
- - change the device_setup parameter (by either manually reprobing the module
- or changing modprobe.conf)
+ - first turn off the device
+ - de-register the snd-usb-audio module (modprobe -r)
+ - change the device_setup parameter by changing the device_setup
+ option in /etc/modprobe.conf
- turn on the device
2.2.2.3 - Audiophile USB's device_setup structure
If you want to understand the device_setup magic numbers for the Audiophile
USB, you need some very basic understanding of binary computation. However,
-this is not required to use the parameter and you may skip thi section.
+this is not required to use the parameter and you may skip this section.
The device_setup is one byte long and its structure is the following:
@@ -231,11 +230,11 @@ Caution:
2.2.3 - USB implementation details for this device
-You may safely skip this section if you're not interrested in driver
+You may safely skip this section if you're not interested in driver
development.
-This section describes some internals aspect of the device and summarize the
-data I got by usb-snooping the windows and linux drivers.
+This section describes some internal aspects of the device and summarize the
+data I got by usb-snooping the windows and Linux drivers.
The M-Audio Audiophile USB has 7 USB Interfaces:
a "USB interface":
@@ -277,9 +276,9 @@ Here is a short description of the AltSettings capabilities:
- 16-bit depth, 8-48kHz sample mode
- Synch playback (Do), audio format type III IEC1937_AC-3
-In order to ensure a correct intialization of the device, the driver
+In order to ensure a correct initialization of the device, the driver
_must_know_ how the device will be used:
- * if DTS is choosen, only Interface 2 with AltSet nb.6 must be
+ * if DTS is chosen, only Interface 2 with AltSet nb.6 must be
registered
* if 96KHz only AltSets nb.1 of each interface must be selected
* if samples are using 24bits/48KHz then AltSet 2 must me used if
@@ -290,7 +289,7 @@ _must_know_ how the device will be used:
is not connected
When device_setup is given as a parameter to the snd-usb-audio module, the
-parse_audio_enpoint function uses a quirk called
+parse_audio_endpoints function uses a quirk called
"audiophile_skip_setting_quirk" in order to prevent AltSettings not
corresponding to device_setup from being registered in the driver.
@@ -317,9 +316,8 @@ However you may see the following warning message:
using the "default" ALSA device. This is less efficient than it could be.
Consider using a hardware device instead rather than using the plug layer."
-
3.2 - Patching alsa to use direct pcm device
--------------------------------------------
+--------------------------------------------
A patch for Jack by Andreas Steinmetz adds support for Big Endian devices.
However it has not been included in the CVS tree.
@@ -331,3 +329,32 @@ After having applied the patch you can run jackd with the following command
line:
% jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1
+3.2 - Getting 2 input and/or output interfaces in Jack
+------------------------------------------------------
+
+As you can see, starting the Jack server this way will only enable 1 stereo
+input (Di or Ai) and 1 stereo output (Ao or Do).
+
+This is due to the following restrictions:
+* Jack can only open one capture device and one playback device at a time
+* The Audiophile USB is seen as 2 (or three) Alsa devices: hw:1,0, hw:1,1
+ (and optionally hw:1,2)
+If you want to get Ai+Di and/or Ao+Do support with Jack, you would need to
+combine the Alsa devices into one logical "complex" device.
+
+If you want to give it a try, I recommend reading the information from
+this page: http://www.sound-man.co.uk/linuxaudio/ice1712multi.html
+It is related to another device (ice1712) but can be adapted to suit
+the Audiophile USB.
+
+Enabling multiple Audiophile USB interfaces for Jackd will certainly require:
+* patching Jack with the previously mentioned "Big Endian" patch
+* patching Jackd with the MMAP_COMPLEX patch (see the ice1712 page)
+* patching the alsa-lib/src/pcm/pcm_multi.c file (see the ice1712 page)
+* define a multi device (combination of hw:1,0 and hw:1,1) in your .asoundrc
+ file
+* start jackd with this device
+
+I had no success in testing this for now, but this may be due to my OS
+configuration. If you have any success with this kind of setup, please
+drop me an email.
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 6feef9e82b6..1faf76383ba 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -1123,8 +1123,8 @@
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check PCI availability (28bit DMA) */
- if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
printk(KERN_ERR "error to set 28bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO;
@@ -1172,7 +1172,7 @@
}
/* PCI IDs */
- static struct pci_device_id snd_mychip_ids[] = {
+ static struct pci_device_id snd_mychip_ids[] __devinitdata = {
{ PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
....
@@ -1216,7 +1216,7 @@
The allocation of PCI resources is done in the
<function>probe()</function> function, and usually an extra
<function>xxx_create()</function> function is written for this
- purpose.
+ purpose.
</para>
<para>
@@ -1225,7 +1225,7 @@
allocating resources. Also, you need to set the proper PCI DMA
mask to limit the accessed i/o range. In some cases, you might
need to call <function>pci_set_master()</function> function,
- too.
+ too.
</para>
<para>
@@ -1236,8 +1236,8 @@
<![CDATA[
if ((err = pci_enable_device(pci)) < 0)
return err;
- if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
printk(KERN_ERR "error to set 28bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO;
@@ -1256,13 +1256,13 @@
functions. Unlike ALSA ver.0.5.x., there are no helpers for
that. And these resources must be released in the destructor
function (see below). Also, on ALSA 0.9.x, you don't need to
- allocate (pseudo-)DMA for PCI like ALSA 0.5.x.
+ allocate (pseudo-)DMA for PCI like ALSA 0.5.x.
</para>
<para>
Now assume that this PCI device has an I/O port with 8 bytes
and an interrupt. Then struct <structname>mychip</structname> will have the
- following fields:
+ following fields:
<informalexample>
<programlisting>
@@ -1565,7 +1565,7 @@
<informalexample>
<programlisting>
<![CDATA[
- static struct pci_device_id snd_mychip_ids[] = {
+ static struct pci_device_id snd_mychip_ids[] __devinitdata = {
{ PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
....
diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx
new file mode 100644
index 00000000000..9c45f3df2e1
--- /dev/null
+++ b/Documentation/spi/pxa2xx
@@ -0,0 +1,234 @@
+PXA2xx SPI on SSP driver HOWTO
+===================================================
+This a mini howto on the pxa2xx_spi driver. The driver turns a PXA2xx
+synchronous serial port into a SPI master controller
+(see Documentation/spi/spi_summary). The driver has the following features
+
+- Support for any PXA2xx SSP
+- SSP PIO and SSP DMA data transfers.
+- External and Internal (SSPFRM) chip selects.
+- Per slave device (chip) configuration.
+- Full suspend, freeze, resume support.
+
+The driver is built around a "spi_message" fifo serviced by workqueue and a
+tasklet. The workqueue, "pump_messages", drives message fifo and the tasklet
+(pump_transfer) is responsible for queuing SPI transactions and setting up and
+launching the dma/interrupt driven transfers.
+
+Declaring PXA2xx Master Controllers
+-----------------------------------
+Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a
+"platform device". The master configuration is passed to the driver via a table
+found in include/asm-arm/arch-pxa/pxa2xx_spi.h:
+
+struct pxa2xx_spi_master {
+ enum pxa_ssp_type ssp_type;
+ u32 clock_enable;
+ u16 num_chipselect;
+ u8 enable_dma;
+};
+
+The "pxa2xx_spi_master.ssp_type" field must have a value between 1 and 3 and
+informs the driver which features a particular SSP supports.
+
+The "pxa2xx_spi_master.clock_enable" field is used to enable/disable the
+corresponding SSP peripheral block in the "Clock Enable Register (CKEN"). See
+the "PXA2xx Developer Manual" section "Clocks and Power Management".
+
+The "pxa2xx_spi_master.num_chipselect" field is used to determine the number of
+slave device (chips) attached to this SPI master.
+
+The "pxa2xx_spi_master.enable_dma" field informs the driver that SSP DMA should
+be used. This caused the driver to acquire two DMA channels: rx_channel and
+tx_channel. The rx_channel has a higher DMA service priority the tx_channel.
+See the "PXA2xx Developer Manual" section "DMA Controller".
+
+NSSP MASTER SAMPLE
+------------------
+Below is a sample configuration using the PXA255 NSSP.
+
+static struct resource pxa_spi_nssp_resources[] = {
+ [0] = {
+ .start = __PREG(SSCR0_P(2)), /* Start address of NSSP */
+ .end = __PREG(SSCR0_P(2)) + 0x2c, /* Range of registers */
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_NSSP, /* NSSP IRQ */
+ .end = IRQ_NSSP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct pxa2xx_spi_master pxa_nssp_master_info = {
+ .ssp_type = PXA25x_NSSP, /* Type of SSP */
+ .clock_enable = CKEN9_NSSP, /* NSSP Peripheral clock */
+ .num_chipselect = 1, /* Matches the number of chips attached to NSSP */
+ .enable_dma = 1, /* Enables NSSP DMA */
+};
+
+static struct platform_device pxa_spi_nssp = {
+ .name = "pxa2xx-spi", /* MUST BE THIS VALUE, so device match driver */
+ .id = 2, /* Bus number, MUST MATCH SSP number 1..n */
+ .resource = pxa_spi_nssp_resources,
+ .num_resources = ARRAY_SIZE(pxa_spi_nssp_resources),
+ .dev = {
+ .platform_data = &pxa_nssp_master_info, /* Passed to driver */
+ },
+};
+
+static struct platform_device *devices[] __initdata = {
+ &pxa_spi_nssp,
+};
+
+static void __init board_init(void)
+{
+ (void)platform_add_device(devices, ARRAY_SIZE(devices));
+}
+
+Declaring Slave Devices
+-----------------------
+Typically each SPI slave (chip) is defined in the arch/.../mach-*/board-*.c
+using the "spi_board_info" structure found in "linux/spi/spi.h". See
+"Documentation/spi/spi_summary" for additional information.
+
+Each slave device attached to the PXA must provide slave specific configuration
+information via the structure "pxa2xx_spi_chip" found in
+"include/asm-arm/arch-pxa/pxa2xx_spi.h". The pxa2xx_spi master controller driver
+will uses the configuration whenever the driver communicates with the slave
+device.
+
+struct pxa2xx_spi_chip {
+ u8 tx_threshold;
+ u8 rx_threshold;
+ u8 dma_burst_size;
+ u32 timeout_microsecs;
+ u8 enable_loopback;
+ void (*cs_control)(u32 command);
+};
+
+The "pxa2xx_spi_chip.tx_threshold" and "pxa2xx_spi_chip.rx_threshold" fields are
+used to configure the SSP hardware fifo. These fields are critical to the
+performance of pxa2xx_spi driver and misconfiguration will result in rx
+fifo overruns (especially in PIO mode transfers). Good default values are
+
+ .tx_threshold = 12,
+ .rx_threshold = 4,
+
+The "pxa2xx_spi_chip.dma_burst_size" field is used to configure PXA2xx DMA
+engine and is related the "spi_device.bits_per_word" field. Read and understand
+the PXA2xx "Developer Manual" sections on the DMA controller and SSP Controllers
+to determine the correct value. An SSP configured for byte-wide transfers would
+use a value of 8.
+
+The "pxa2xx_spi_chip.timeout_microsecs" fields is used to efficiently handle
+trailing bytes in the SSP receiver fifo. The correct value for this field is
+dependent on the SPI bus speed ("spi_board_info.max_speed_hz") and the specific
+slave device. Please note the the PXA2xx SSP 1 does not support trailing byte
+timeouts and must busy-wait any trailing bytes.
+
+The "pxa2xx_spi_chip.enable_loopback" field is used to place the SSP porting
+into internal loopback mode. In this mode the SSP controller internally
+connects the SSPTX pin the the SSPRX pin. This is useful for initial setup
+testing.
+
+The "pxa2xx_spi_chip.cs_control" field is used to point to a board specific
+function for asserting/deasserting a slave device chip select. If the field is
+NULL, the pxa2xx_spi master controller driver assumes that the SSP port is
+configured to use SSPFRM instead.
+
+NSSP SALVE SAMPLE
+-----------------
+The pxa2xx_spi_chip structure is passed to the pxa2xx_spi driver in the
+"spi_board_info.controller_data" field. Below is a sample configuration using
+the PXA255 NSSP.
+
+/* Chip Select control for the CS8415A SPI slave device */
+static void cs8415a_cs_control(u32 command)
+{
+ if (command & PXA2XX_CS_ASSERT)
+ GPCR(2) = GPIO_bit(2);
+ else
+ GPSR(2) = GPIO_bit(2);
+}
+
+/* Chip Select control for the CS8405A SPI slave device */
+static void cs8405a_cs_control(u32 command)
+{
+ if (command & PXA2XX_CS_ASSERT)
+ GPCR(3) = GPIO_bit(3);
+ else
+ GPSR(3) = GPIO_bit(3);
+}
+
+static struct pxa2xx_spi_chip cs8415a_chip_info = {
+ .tx_threshold = 12, /* SSP hardward FIFO threshold */
+ .rx_threshold = 4, /* SSP hardward FIFO threshold */
+ .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
+ .timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */
+ .cs_control = cs8415a_cs_control, /* Use external chip select */
+};
+
+static struct pxa2xx_spi_chip cs8405a_chip_info = {
+ .tx_threshold = 12, /* SSP hardward FIFO threshold */
+ .rx_threshold = 4, /* SSP hardward FIFO threshold */
+ .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
+ .timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */
+ .cs_control = cs8405a_cs_control, /* Use external chip select */
+};
+
+static struct spi_board_info streetracer_spi_board_info[] __initdata = {
+ {
+ .modalias = "cs8415a", /* Name of spi_driver for this device */
+ .max_speed_hz = 3686400, /* Run SSP as fast a possbile */
+ .bus_num = 2, /* Framework bus number */
+ .chip_select = 0, /* Framework chip select */
+ .platform_data = NULL; /* No spi_driver specific config */
+ .controller_data = &cs8415a_chip_info, /* Master chip config */
+ .irq = STREETRACER_APCI_IRQ, /* Slave device interrupt */
+ },
+ {
+ .modalias = "cs8405a", /* Name of spi_driver for this device */
+ .max_speed_hz = 3686400, /* Run SSP as fast a possbile */
+ .bus_num = 2, /* Framework bus number */
+ .chip_select = 1, /* Framework chip select */
+ .controller_data = &cs8405a_chip_info, /* Master chip config */
+ .irq = STREETRACER_APCI_IRQ, /* Slave device interrupt */
+ },
+};
+
+static void __init streetracer_init(void)
+{
+ spi_register_board_info(streetracer_spi_board_info,
+ ARRAY_SIZE(streetracer_spi_board_info));
+}
+
+
+DMA and PIO I/O Support
+-----------------------
+The pxa2xx_spi driver support both DMA and interrupt driven PIO message
+transfers. The driver defaults to PIO mode and DMA transfers must enabled by
+setting the "enable_dma" flag in the "pxa2xx_spi_master" structure and and
+ensuring that the "pxa2xx_spi_chip.dma_burst_size" field is non-zero. The DMA
+mode support both coherent and stream based DMA mappings.
+
+The following logic is used to determine the type of I/O to be used on
+a per "spi_transfer" basis:
+
+if !enable_dma or dma_burst_size == 0 then
+ always use PIO transfers
+
+if spi_message.is_dma_mapped and rx_dma_buf != 0 and tx_dma_buf != 0 then
+ use coherent DMA mode
+
+if rx_buf and tx_buf are aligned on 8 byte boundary then
+ use streaming DMA mode
+
+otherwise
+ use PIO transfer
+
+THANKS TO
+---------
+
+David Brownell and others for mentoring the development of this driver.
+
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
index a5ffba33a35..068732d3227 100644
--- a/Documentation/spi/spi-summary
+++ b/Documentation/spi/spi-summary
@@ -414,7 +414,33 @@ to get the driver-private data allocated for that device.
The driver will initialize the fields of that spi_master, including the
bus number (maybe the same as the platform device ID) and three methods
used to interact with the SPI core and SPI protocol drivers. It will
-also initialize its own internal state.
+also initialize its own internal state. (See below about bus numbering
+and those methods.)
+
+After you initialize the spi_master, then use spi_register_master() to
+publish it to the rest of the system. At that time, device nodes for
+the controller and any predeclared spi devices will be made available,
+and the driver model core will take care of binding them to drivers.
+
+If you need to remove your SPI controller driver, spi_unregister_master()
+will reverse the effect of spi_register_master().
+
+
+BUS NUMBERING
+
+Bus numbering is important, since that's how Linux identifies a given
+SPI bus (shared SCK, MOSI, MISO). Valid bus numbers start at zero. On
+SOC systems, the bus numbers should match the numbers defined by the chip
+manufacturer. For example, hardware controller SPI2 would be bus number 2,
+and spi_board_info for devices connected to it would use that number.
+
+If you don't have such hardware-assigned bus number, and for some reason
+you can't just assign them, then provide a negative bus number. That will
+then be replaced by a dynamically assigned number. You'd then need to treat
+this as a non-static configuration (see above).
+
+
+SPI MASTER METHODS
master->setup(struct spi_device *spi)
This sets up the device clock rate, SPI mode, and word sizes.
@@ -431,6 +457,9 @@ also initialize its own internal state.
state it dynamically associates with that device. If you do that,
be sure to provide the cleanup() method to free that state.
+
+SPI MESSAGE QUEUE
+
The bulk of the driver will be managing the I/O queue fed by transfer().
That queue could be purely conceptual. For example, a driver used only
@@ -440,6 +469,9 @@ But the queue will probably be very real, using message->queue, PIO,
often DMA (especially if the root filesystem is in SPI flash), and
execution contexts like IRQ handlers, tasklets, or workqueues (such
as keventd). Your driver can be as fancy, or as simple, as you need.
+Such a transfer() method would normally just add the message to a
+queue, and then start some asynchronous transfer engine (unless it's
+already running).
THANKS TO
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index 8c719545596..bca50903233 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -52,7 +52,7 @@
51 -> ProVideo PV952 [1540:9524]
52 -> AverMedia AverTV/305 [1461:2108]
53 -> ASUS TV-FM 7135 [1043:4845]
- 54 -> LifeView FlyTV Platinum FM [5168:0214,1489:0214]
+ 54 -> LifeView FlyTV Platinum FM / Gold [5168:0214,1489:0214,5168:0304]
55 -> LifeView FlyDVB-T DUO [5168:0306]
56 -> Avermedia AVerTV 307 [1461:a70a]
57 -> Avermedia AVerTV GO 007 FM [1461:f31f]
@@ -84,7 +84,7 @@
83 -> Terratec Cinergy 250 PCI TV [153b:1160]
84 -> LifeView FlyDVB Trio [5168:0319]
85 -> AverTV DVB-T 777 [1461:2c05]
- 86 -> LifeView FlyDVB-T [5168:0301]
+ 86 -> LifeView FlyDVB-T / Genius VideoWonder DVB-T [5168:0301,1489:0301]
87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421]
88 -> Tevion/KWorld DVB-T 220RF [17de:7201]
89 -> ELSA EX-VISION 700TV [1048:226c]
@@ -92,3 +92,4 @@
91 -> AVerMedia A169 B [1461:7360]
92 -> AVerMedia A169 B1 [1461:6360]
93 -> Medion 7134 Bridge #2 [16be:0005]
+ 94 -> LifeView FlyDVB-T Hybrid Cardbus [5168:3306,5168:3502]
diff --git a/Documentation/usb/et61x251.txt b/Documentation/video4linux/et61x251.txt
index 29340282ab5..29340282ab5 100644
--- a/Documentation/usb/et61x251.txt
+++ b/Documentation/video4linux/et61x251.txt
diff --git a/Documentation/usb/ibmcam.txt b/Documentation/video4linux/ibmcam.txt
index c2500364413..4a40a2e9945 100644
--- a/Documentation/usb/ibmcam.txt
+++ b/Documentation/video4linux/ibmcam.txt
@@ -122,7 +122,7 @@ WHAT YOU NEED:
- A Linux box with USB support (2.3/2.4; 2.2 w/backport may work)
- A Video4Linux compatible frame grabber program such as xawtv.
-
+
HOW TO COMPILE THE DRIVER:
You need to compile the driver only if you are a developer
diff --git a/Documentation/usb/ov511.txt b/Documentation/video4linux/ov511.txt
index a7fc0432bff..142741e3c57 100644
--- a/Documentation/usb/ov511.txt
+++ b/Documentation/video4linux/ov511.txt
@@ -9,7 +9,7 @@ INTRODUCTION:
This is a driver for the OV511, a USB-only chip used in many "webcam" devices.
Any camera using the OV511/OV511+ and the OV6620/OV7610/20/20AE should work.
-Video capture devices that use the Philips SAA7111A decoder also work. It
+Video capture devices that use the Philips SAA7111A decoder also work. It
supports streaming and capture of color or monochrome video via the Video4Linux
API. Most V4L apps are compatible with it. Most resolutions with a width and
height that are a multiple of 8 are supported.
@@ -52,15 +52,15 @@ from it:
chmod 666 /dev/video
chmod 666 /dev/video0 (if necessary)
-
+
Now you are ready to run a video app! Both vidcat and xawtv work well for me
at 640x480.
-
+
[Using vidcat:]
vidcat -s 640x480 -p c > test.jpg
xview test.jpg
-
+
[Using xawtv:]
From the main xawtv directory:
@@ -70,7 +70,7 @@ From the main xawtv directory:
make
make install
-Now you should be able to run xawtv. Right click for the options dialog.
+Now you should be able to run xawtv. Right click for the options dialog.
MODULE PARAMETERS:
@@ -286,4 +286,3 @@ Randy Dunlap, and others. Big thanks to them for their pioneering work on that
and the USB stack. Thanks to Bret Wallach for getting camera reg IO, ISOC, and
image capture working. Thanks to Orion Sky Lawlor, Kevin Moore, and Claudio
Matsuoka for their work as well.
-
diff --git a/Documentation/usb/se401.txt b/Documentation/video4linux/se401.txt
index 7b9d1c960a1..7b9d1c960a1 100644
--- a/Documentation/usb/se401.txt
+++ b/Documentation/video4linux/se401.txt
diff --git a/Documentation/usb/sn9c102.txt b/Documentation/video4linux/sn9c102.txt
index b957beae560..142920bc011 100644
--- a/Documentation/usb/sn9c102.txt
+++ b/Documentation/video4linux/sn9c102.txt
@@ -174,7 +174,7 @@ Module parameters are listed below:
-------------------------------------------------------------------------------
Name: video_nr
Type: short array (min = 0, max = 64)
-Syntax: <-1|n[,...]>
+Syntax: <-1|n[,...]>
Description: Specify V4L2 minor mode number:
-1 = use next available
n = use minor number n
@@ -187,7 +187,7 @@ Default: -1
-------------------------------------------------------------------------------
Name: force_munmap
Type: bool array (min = 0, max = 64)
-Syntax: <0|1[,...]>
+Syntax: <0|1[,...]>
Description: Force the application to unmap previously mapped buffer memory
before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
all the applications support this feature. This parameter is
@@ -206,7 +206,7 @@ Default: 2
-------------------------------------------------------------------------------
Name: debug
Type: ushort
-Syntax: <n>
+Syntax: <n>
Description: Debugging information level, from 0 to 3:
0 = none (use carefully)
1 = critical errors
@@ -267,7 +267,7 @@ The sysfs interface also provides the "frame_header" entry, which exports the
frame header of the most recent requested and captured video frame. The header
is always 18-bytes long and is appended to every video frame by the SN9C10x
controllers. As an example, this additional information can be used by the user
-application for implementing auto-exposure features via software.
+application for implementing auto-exposure features via software.
The following table describes the frame header:
@@ -441,7 +441,7 @@ blue pixels in one video frame. Each pixel is associated with a 8-bit long
value and is disposed in memory according to the pattern shown below:
B[0] G[1] B[2] G[3] ... B[m-2] G[m-1]
-G[m] R[m+1] G[m+2] R[m+2] ... G[2m-2] R[2m-1]
+G[m] R[m+1] G[m+2] R[m+2] ... G[2m-2] R[2m-1]
...
... B[(n-1)(m-2)] G[(n-1)(m-1)]
... G[n(m-2)] R[n(m-1)]
@@ -472,12 +472,12 @@ The pixel reference value is calculated as follows:
The algorithm purely describes the conversion from compressed Bayer code used
in the SN9C10x chips to uncompressed Bayer. Additional steps are required to
convert this to a color image (i.e. a color interpolation algorithm).
-
+
The following Huffman codes have been found:
-0: +0 (relative to reference pixel value)
+0: +0 (relative to reference pixel value)
100: +4
101: -4?
-1110xxxx: set absolute value to xxxx.0000
+1110xxxx: set absolute value to xxxx.0000
1101: +11
1111: -11
11001: +20
diff --git a/Documentation/usb/stv680.txt b/Documentation/video4linux/stv680.txt
index 6448041e7a3..4f8946f32f5 100644
--- a/Documentation/usb/stv680.txt
+++ b/Documentation/video4linux/stv680.txt
@@ -5,15 +5,15 @@ Copyright, 2001, Kevin Sisson
INTRODUCTION:
-STMicroelectronics produces the STV0680B chip, which comes in two
-types, -001 and -003. The -003 version allows the recording and downloading
-of sound clips from the camera, and allows a flash attachment. Otherwise,
-it uses the same commands as the -001 version. Both versions support a
-variety of SDRAM sizes and sensors, allowing for a maximum of 26 VGA or 20
-CIF pictures. The STV0680 supports either a serial or a usb interface, and
+STMicroelectronics produces the STV0680B chip, which comes in two
+types, -001 and -003. The -003 version allows the recording and downloading
+of sound clips from the camera, and allows a flash attachment. Otherwise,
+it uses the same commands as the -001 version. Both versions support a
+variety of SDRAM sizes and sensors, allowing for a maximum of 26 VGA or 20
+CIF pictures. The STV0680 supports either a serial or a usb interface, and
video is possible through the usb interface.
-The following cameras are known to work with this driver, although any
+The following cameras are known to work with this driver, although any
camera with Vendor/Product codes of 0553/0202 should work:
Aiptek Pencam (various models)
@@ -34,15 +34,15 @@ http://www.linux-usb.org
MODULE OPTIONS:
When the driver is compiled as a module, you can set a "swapRGB=1"
-option, if necessary, for those applications that require it
-(such as xawtv). However, the driver should detect and set this
+option, if necessary, for those applications that require it
+(such as xawtv). However, the driver should detect and set this
automatically, so this option should not normally be used.
KNOWN PROBLEMS:
-The driver seems to work better with the usb-ohci than the usb-uhci host
-controller driver.
+The driver seems to work better with the usb-ohci than the usb-uhci host
+controller driver.
HELP:
@@ -50,6 +50,4 @@ The latest info on this driver can be found at:
http://personal.clt.bellsouth.net/~kjsisson or at
http://stv0680-usb.sourceforge.net
-Any questions to me can be send to: kjsisson@bellsouth.net
-
-
+Any questions to me can be send to: kjsisson@bellsouth.net \ No newline at end of file
diff --git a/Documentation/usb/w9968cf.txt b/Documentation/video4linux/w9968cf.txt
index 9d46cd0b19e..3b704f2aae6 100644
--- a/Documentation/usb/w9968cf.txt
+++ b/Documentation/video4linux/w9968cf.txt
@@ -1,5 +1,5 @@
- W996[87]CF JPEG USB Dual Mode Camera Chip
+ W996[87]CF JPEG USB Dual Mode Camera Chip
Driver for Linux 2.6 (basic version)
=========================================
@@ -115,7 +115,7 @@ additional testing and full support, would be much appreciated.
======================
For it to work properly, the driver needs kernel support for Video4Linux, USB
and I2C, and the "ovcamchip" module for the image sensor. Make sure you are not
-actually using any external "ovcamchip" module, given that the W996[87]CF
+actually using any external "ovcamchip" module, given that the W996[87]CF
driver depends on the version of the module present in the official kernels.
The following options of the kernel configuration file must be enabled and
@@ -197,16 +197,16 @@ Note: The kernel must be compiled with the CONFIG_KMOD option
enabled for the 'ovcamchip' module to be loaded and for
this parameter to be present.
-------------------------------------------------------------------------------
-Name: simcams
-Type: int
-Syntax: <n>
+Name: simcams
+Type: int
+Syntax: <n>
Description: Number of cameras allowed to stream simultaneously.
n may vary from 0 to 32.
Default: 32
-------------------------------------------------------------------------------
Name: video_nr
Type: int array (min = 0, max = 32)
-Syntax: <-1|n[,...]>
+Syntax: <-1|n[,...]>
Description: Specify V4L minor mode number.
-1 = use next available
n = use minor number n
@@ -219,7 +219,7 @@ Default: -1
-------------------------------------------------------------------------------
Name: packet_size
Type: int array (min = 0, max = 32)
-Syntax: <n[,...]>
+Syntax: <n[,...]>
Description: Specify the maximum data payload size in bytes for alternate
settings, for each device. n is scaled between 63 and 1023.
Default: 1023
@@ -234,7 +234,7 @@ Default: 2
-------------------------------------------------------------------------------
Name: double_buffer
Type: bool array (min = 0, max = 32)
-Syntax: <0|1[,...]>
+Syntax: <0|1[,...]>
Description: Hardware double buffering: 0 disabled, 1 enabled.
It should be enabled if you want smooth video output: if you
obtain out of sync. video, disable it, or try to
@@ -243,13 +243,13 @@ Default: 1 for every device.
-------------------------------------------------------------------------------
Name: clamping
Type: bool array (min = 0, max = 32)
-Syntax: <0|1[,...]>
+Syntax: <0|1[,...]>
Description: Video data clamping: 0 disabled, 1 enabled.
Default: 0 for every device.
-------------------------------------------------------------------------------
Name: filter_type
Type: int array (min = 0, max = 32)
-Syntax: <0|1|2[,...]>
+Syntax: <0|1|2[,...]>
Description: Video filter type.
0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter.
The filter is used to reduce noise and aliasing artifacts
@@ -258,13 +258,13 @@ Default: 0 for every device.
-------------------------------------------------------------------------------
Name: largeview
Type: bool array (min = 0, max = 32)
-Syntax: <0|1[,...]>
+Syntax: <0|1[,...]>
Description: Large view: 0 disabled, 1 enabled.
Default: 1 for every device.
-------------------------------------------------------------------------------
Name: upscaling
Type: bool array (min = 0, max = 32)
-Syntax: <0|1[,...]>
+Syntax: <0|1[,...]>
Description: Software scaling (for non-compressed video only):
0 disabled, 1 enabled.
Disable it if you have a slow CPU or you don't have enough
@@ -341,8 +341,8 @@ Default: 50 for every device.
-------------------------------------------------------------------------------
Name: bandingfilter
Type: bool array (min = 0, max = 32)
-Syntax: <0|1[,...]>
-Description: Banding filter to reduce effects of fluorescent
+Syntax: <0|1[,...]>
+Description: Banding filter to reduce effects of fluorescent
lighting:
0 disabled, 1 enabled.
This filter tries to reduce the pattern of horizontal
@@ -374,7 +374,7 @@ Default: 0 for every device.
-------------------------------------------------------------------------------
Name: monochrome
Type: bool array (min = 0, max = 32)
-Syntax: <0|1[,...]>
+Syntax: <0|1[,...]>
Description: The image sensor is monochrome:
0 = no, 1 = yes
Default: 0 for every device.
@@ -400,19 +400,19 @@ Default: 32768 for every device.
-------------------------------------------------------------------------------
Name: contrast
Type: long array (min = 0, max = 32)
-Syntax: <n[,...]>
+Syntax: <n[,...]>
Description: Set picture contrast (0-65535).
Default: 50000 for every device.
-------------------------------------------------------------------------------
Name: whiteness
Type: long array (min = 0, max = 32)
-Syntax: <n[,...]>
+Syntax: <n[,...]>
Description: Set picture whiteness (0-65535).
Default: 32768 for every device.
-------------------------------------------------------------------------------
Name: debug
Type: int
-Syntax: <n>
+Syntax: <n>
Description: Debugging information level, from 0 to 6:
0 = none (use carefully)
1 = critical errors
diff --git a/Documentation/usb/zc0301.txt b/Documentation/video4linux/zc0301.txt
index f55262c6733..f55262c6733 100644
--- a/Documentation/usb/zc0301.txt
+++ b/Documentation/video4linux/zc0301.txt
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index 1ad9af1ca4d..687104bfd09 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -27,12 +27,21 @@ number of free hugetlb pages at any time. It also displays information about
the configured hugepage size - this is needed for generating the proper
alignment and size of the arguments to the above system calls.
-The output of "cat /proc/meminfo" will have output like:
+The output of "cat /proc/meminfo" will have lines like:
.....
HugePages_Total: xxx
HugePages_Free: yyy
-Hugepagesize: zzz KB
+HugePages_Rsvd: www
+Hugepagesize: zzz kB
+
+where:
+HugePages_Total is the size of the pool of hugepages.
+HugePages_Free is the number of hugepages in the pool that are not yet
+allocated.
+HugePages_Rsvd is short for "reserved," and is the number of hugepages
+for which a commitment to allocate from the pool has been made, but no
+allocation has yet been made. It's vaguely analogous to overcommit.
/proc/filesystems should also show a filesystem of type "hugetlbfs" configured
in the kernel.
@@ -42,11 +51,11 @@ pages in the kernel. Super user can dynamically request more (or free some
pre-configured) hugepages.
The allocation (or deallocation) of hugetlb pages is possible only if there are
enough physically contiguous free pages in system (freeing of hugepages is
-possible only if there are enough hugetlb pages free that can be transfered
+possible only if there are enough hugetlb pages free that can be transferred
back to regular memory pool).
-Pages that are used as hugetlb pages are reserved inside the kernel and can
-not be used for other purposes.
+Pages that are used as hugetlb pages are reserved inside the kernel and cannot
+be used for other purposes.
Once the kernel with Hugetlb page support is built and running, a user can
use either the mmap system call or shared memory system calls to start using
@@ -60,7 +69,7 @@ Use the following command to dynamically allocate/deallocate hugepages:
This command will try to configure 20 hugepages in the system. The success
or failure of allocation depends on the amount of physically contiguous
memory that is preset in system at this time. System administrators may want
-to put this command in one of the local rc init file. This will enable the
+to put this command in one of the local rc init files. This will enable the
kernel to request huge pages early in the boot process (when the possibility
of getting physical contiguous pages is still very high).
@@ -78,8 +87,8 @@ the uid and gid of the current process are taken. The mode option sets the
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_inode sets the maximum number of
-inodes that /mnt/huge can use. If the size or nr_inode options are not
+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
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
@@ -88,7 +97,7 @@ the end of this document.
read and write system calls are not supported on files that reside on hugetlb
file systems.
-A regular chown, chgrp and chmod commands (with right permissions) could be
+Regular chown, chgrp, and chmod commands (with right permissions) could be
used to change the file attributes on hugetlbfs.
Also, it is important to note that no such mount command is required if the
@@ -96,8 +105,8 @@ applications are going to use only shmat/shmget system calls. Users who
wish to use hugetlb page via shared memory segment should be a member of
a supplementary group and system admin needs to configure that gid into
/proc/sys/vm/hugetlb_shm_group. It is possible for same or different
-applications to use any combination of mmaps and shm* calls. Though the
-mount of filesystem will be required for using mmaps.
+applications to use any combination of mmaps and shm* calls, though the
+mount of filesystem will be required for using mmap calls.
*******************************************************************
diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt
index c5beb548cfc..21ed5117366 100644
--- a/Documentation/watchdog/watchdog-api.txt
+++ b/Documentation/watchdog/watchdog-api.txt
@@ -36,6 +36,9 @@ timeout or margin. The simplest way to ping the watchdog is to write
some data to the device. So a very simple watchdog daemon would look
like this:
+#include <stdlib.h>
+#include <fcntl.h>
+
int main(int argc, const char *argv[]) {
int fd=open("/dev/watchdog",O_WRONLY);
if (fd==-1) {
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index 1921353259a..f2cd6ef53ff 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -151,6 +151,11 @@ NUMA
numa=fake=X Fake X nodes and ignore NUMA setup of the actual machine.
+ numa=hotadd=percent
+ Only allow hotadd memory to preallocate page structures upto
+ percent of already available memory.
+ numa=hotadd=0 will disable hotadd memory.
+
ACPI
acpi=off Don't enable ACPI
diff --git a/Kbuild b/Kbuild
index 95d6a00bace..2d4f95e4b89 100644
--- a/Kbuild
+++ b/Kbuild
@@ -18,7 +18,7 @@ define sed-y
"/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"
endef
# Override default regexp for specific architectures
-sed-$(CONFIG_MIPS) := "/^@@@/s///p"
+sed-$(CONFIG_MIPS) := "/^@@@/{s/^@@@//; s/ \#.*\$$//; p;}"
quiet_cmd_offsets = GEN $@
define cmd_offsets
diff --git a/MAINTAINERS b/MAINTAINERS
index f27846734b0..c3c5842402d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -40,11 +40,20 @@ trivial patch so apply some common sense.
PLEASE document known bugs. If it doesn't work for everything
or does something very odd once a month document it.
+ PLEASE remember that submissions must be made under the terms
+ of the OSDL certificate of contribution
+ (http://www.osdl.org/newsroom/press_releases/2004/2004_05_24_dco.html)
+ and should include a Signed-off-by: line.
+
6. Make sure you have the right to send any changes you make. If you
do changes at work you may find your employer owns the patch
not you.
-7. Happy hacking.
+7. When sending security related changes or reports to a maintainer
+ please Cc: security@kernel.org, especially if the maintainer
+ does not respond.
+
+8. Happy hacking.
-----------------------------------
@@ -411,6 +420,7 @@ AX.25 NETWORK LAYER
P: Ralf Baechle
M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org
+W: http://www.linux-ax25.org/
S: Maintained
BAYCOM/HDLCDRV DRIVERS FOR AX.25
@@ -420,6 +430,14 @@ L: linux-hams@vger.kernel.org
W: http://www.baycom.org/~tom/ham/ham.html
S: Maintained
+BCM43XX WIRELESS DRIVER
+P: Michael Buesch
+M: mb@bu3sch.de
+P: Stefano Brivio
+M: st3@riseup.net
+W: http://bcm43xx.berlios.de/
+S: Maintained
+
BEFS FILE SYSTEM
P: Sergey S. Kostyliov
M: rathamahata@php4.ru
@@ -547,7 +565,19 @@ BROADBAND PROCESSOR ARCHITECTURE
P: Arnd Bergmann
M: arnd@arndb.de
L: linuxppc-dev@ozlabs.org
-W: http://linuxppc64.org
+W: http://www.penguinppc.org/ppc64/
+S: Supported
+
+BROADCOM BNX2 GIGABIT ETHERNET DRIVER
+P: Michael Chan
+M: mchan@broadcom.com
+L: netdev@vger.kernel.org
+S: Supported
+
+BROADCOM TG3 GIGABIT ETHERNET DRIVER
+P: Michael Chan
+M: mchan@broadcom.com
+L: netdev@vger.kernel.org
S: Supported
BTTV VIDEO4LINUX DRIVER
@@ -960,7 +990,7 @@ S: Maintained
EXT3 FILE SYSTEM
P: Stephen Tweedie, Andrew Morton
M: sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com
-L: ext3-users@redhat.com
+L: ext2-devel@lists.sourceforge.net
S: Maintained
F71805F HARDWARE MONITORING DRIVER
@@ -1451,6 +1481,19 @@ P: Juanjo Ciarlante
M: jjciarla@raiz.uncu.edu.ar
S: Maintained
+IPATH DRIVER:
+P: Bryan O'Sullivan
+M: support@pathscale.com
+L: openib-general@openib.org
+S: Supported
+
+IPMI SUBSYSTEM
+P: Corey Minyard
+M: minyard@acm.org
+L: openipmi-developer@lists.sourceforge.net
+W: http://openipmi.sourceforge.net/
+S: Supported
+
IPX NETWORK LAYER
P: Arnaldo Carvalho de Melo
M: acme@conectiva.com.br
@@ -1458,10 +1501,11 @@ L: netdev@vger.kernel.org
S: Maintained
IRDA SUBSYSTEM
-P: Jean Tourrilhes
+P: Samuel Ortiz
+M: samuel@sortiz.org
L: irda-users@lists.sourceforge.net (subscribers-only)
W: http://irda.sourceforge.net/
-S: Odd Fixes
+S: Maintained
ISAPNP
P: Jaroslav Kysela
@@ -1507,12 +1551,28 @@ W: http://jfs.sourceforge.net/
T: git kernel.org:/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git
S: Supported
+JOURNALLING LAYER FOR BLOCK DEVICS (JBD)
+P: Stephen Tweedie, Andrew Morton
+M: sct@redhat.com, akpm@osdl.org
+L: ext2-devel@lists.sourceforge.net
+S: Maintained
+
KCONFIG
P: Roman Zippel
M: zippel@linux-m68k.org
L: kbuild-devel@lists.sourceforge.net
S: Maintained
+KDUMP
+P: Vivek Goyal
+M: vgoyal@in.ibm.com
+P: Haren Myneni
+M: hbabu@us.ibm.com
+L: fastboot@lists.osdl.org
+L: linux-kernel@vger.kernel.org
+W: http://lse.sourceforge.net/kdump/
+S: Maintained
+
KERNEL AUTOMOUNTER (AUTOFS)
P: H. Peter Anvin
M: hpa@zytor.com
@@ -1550,9 +1610,7 @@ S: Maintained
KEXEC
P: Eric Biederman
-P: Randy Dunlap
M: ebiederm@xmission.com
-M: rdunlap@xenotime.net
W: http://www.xmission.com/~ebiederm/files/kexec/
L: linux-kernel@vger.kernel.org
L: fastboot@osdl.org
@@ -1582,6 +1640,11 @@ M: James.Bottomley@HansenPartnership.com
L: linux-scsi@vger.kernel.org
S: Maintained
+LED SUBSYSTEM
+P: Richard Purdie
+M: rpurdie@rpsys.net
+S: Maintained
+
LEGO USB Tower driver
P: Juergen Stuber
M: starblue@users.sourceforge.net
@@ -1641,7 +1704,7 @@ S: Maintained
LINUX FOR POWERPC EMBEDDED PPC8XX
P: Marcelo Tosatti
-M: marcelo.tosatti@cyclades.com
+M: marcelo@kvack.org
W: http://www.penguinppc.org/
L: linuxppc-embedded@ozlabs.org
S: Maintained
@@ -1665,7 +1728,7 @@ M: paulus@au.ibm.com
P: Anton Blanchard
M: anton@samba.org
M: anton@au.ibm.com
-W: http://linuxppc64.org
+W: http://www.penguinppc.org/ppc64/
L: linuxppc-dev@ozlabs.org
S: Supported
@@ -1826,6 +1889,11 @@ L: linux-kernel@vger.kernel.org
W: http://www.atnf.csiro.au/~rgooch/linux/kernel-patches.html
S: Maintained
+MULTIMEDIA CARD SUBSYSTEM
+P: Russell King
+M: rmk+mmc@arm.linux.org.uk
+S: Maintained
+
MULTISOUND SOUND DRIVER
P: Andrew Veliath
M: andrewtv@usa.net
@@ -1848,6 +1916,12 @@ M: James.Bottomley@HansenPartnership.com
L: linux-scsi@vger.kernel.org
S: Maintained
+NETEM NETWORK EMULATOR
+P: Stephen Hemminger
+M: shemminger@osdl.org
+L: netem@osdl.org
+S: Maintained
+
NETFILTER/IPTABLES/IPCHAINS
P: Rusty Russell
P: Marc Boucher
@@ -1865,6 +1939,7 @@ NETROM NETWORK LAYER
P: Ralf Baechle
M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org
+W: http://www.linux-ax25.org/
S: Maintained
NETWORK BLOCK DEVICE
@@ -1885,6 +1960,7 @@ NETWORKING [GENERAL]
P: Networking Team
M: netdev@vger.kernel.org
L: netdev@vger.kernel.org
+W: http://linux-net.osdl.org/
S: Maintained
NETWORKING [IPv4/IPv6]
@@ -2051,8 +2127,12 @@ P: Matthew Wilcox
M: matthew@wil.cx
P: Grant Grundler
M: grundler@parisc-linux.org
+P: Kyle McMartin
+M: kyle@parisc-linux.org
L: parisc-linux@parisc-linux.org
W: http://www.parisc-linux.org/
+T: git kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6.git
+T: cvs cvs.parisc-linux.org:/var/cvs/linux-2.6
S: Maintained
PCI ERROR RECOVERY
@@ -2233,6 +2313,12 @@ M: p_gortmaker@yahoo.com
L: linux-kernel@vger.kernel.org
S: Maintained
+REAL TIME CLOCK (RTC) SUBSYSTEM
+P: Alessandro Zummo
+M: a.zummo@towertech.it
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
REISERFS FILE SYSTEM
P: Hans Reiser
M: reiserfs-dev@namesys.com
@@ -2249,6 +2335,7 @@ ROSE NETWORK LAYER
P: Ralf Baechle
M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org
+W: http://www.linux-ax25.org/
S: Maintained
RISCOM8 DRIVER
@@ -2479,6 +2566,12 @@ M: perex@suse.cz
L: alsa-devel@alsa-project.org
S: Maintained
+SPI SUBSYSTEM
+P: David Brownell
+M: dbrownell@users.sourceforge.net
+L: spi-devel-general@lists.sourceforge.net
+S: Maintained
+
TPM DEVICE DRIVER
P: Kylene Hall
M: kjhall@us.ibm.com
@@ -3047,13 +3140,6 @@ M: khali@linux-fr.org
L: lm-sensors@lm-sensors.org
S: Odd Fixes
-WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC)
-P: Nenad Corbic
-M: ncorbic@sangoma.com
-M: dm@sangoma.com
-W: http://www.sangoma.com
-S: Supported
-
WATCHDOG DEVICE DRIVERS
P: Wim Van Sebroeck
M: wim@iguana.be
diff --git a/Makefile b/Makefile
index af6210d4883..a3a7baad855 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
VERSION = 2
PATCHLEVEL = 6
-SUBLEVEL = 16
-EXTRAVERSION =
-NAME=Sliding Snow Leopard
+SUBLEVEL = 17
+EXTRAVERSION =-rc6
+NAME=Crazed Snow-Weasel
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
@@ -344,16 +344,14 @@ scripts_basic:
scripts/basic/%: scripts_basic ;
PHONY += outputmakefile
-# outputmakefile generate a Makefile to be placed in output directory, if
-# using a seperate output directory. This allows convinient use
-# of make in output directory
+# outputmakefile generates a Makefile in the output directory, if using a
+# separate output directory. This allows convenient use of make in the
+# output directory.
outputmakefile:
- $(Q)if test ! $(srctree) -ef $(objtree); then \
- $(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
- $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) \
- > $(objtree)/Makefile; \
- echo ' GEN $(objtree)/Makefile'; \
- fi
+ifneq ($(KBUILD_SRC),)
+ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
+ $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
+endif
# To make sure we do not include .config for any of the *config targets
# catch them early, and hand them over to scripts/kconfig/Makefile
@@ -796,8 +794,8 @@ prepare2: prepare3 outputmakefile
prepare1: prepare2 include/linux/version.h include/asm \
include/config/MARKER
ifneq ($(KBUILD_MODULES),)
- $(Q)rm -rf $(MODVERDIR)
$(Q)mkdir -p $(MODVERDIR)
+ $(Q)rm -f $(MODVERDIR)/*
endif
archprepare: prepare1 scripts_basic
@@ -1086,8 +1084,8 @@ else # KBUILD_EXTMOD
KBUILD_MODULES := 1
PHONY += crmodverdir
crmodverdir:
- $(Q)rm -rf $(MODVERDIR)
$(Q)mkdir -p $(MODVERDIR)
+ $(Q)rm -f $(MODVERDIR)/*
PHONY += $(objtree)/Module.symvers
$(objtree)/Module.symvers:
@@ -1112,7 +1110,6 @@ modules_install: _emodinst_ _emodinst_post
install-dir := $(if $(INSTALL_MOD_DIR),$(INSTALL_MOD_DIR),extra)
PHONY += _emodinst_
_emodinst_:
- $(Q)rm -rf $(MODLIB)/$(install-dir)
$(Q)mkdir -p $(MODLIB)/$(install-dir)
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst
@@ -1275,40 +1272,43 @@ kernelversion:
# Single targets
# ---------------------------------------------------------------------------
-# The directory part is taken from first prerequisite, so this
-# works even with external modules
+# Single targets are compatible with:
+# - build whith mixed source and output
+# - build with separate output dir 'make O=...'
+# - external modules
+#
+# target-dir => where to store outputfile
+# build-dir => directory in kernel source tree to use
+
+ifeq ($(KBUILD_EXTMOD),)
+ build-dir = $(patsubst %/,%,$(dir $@))
+ target-dir = $(dir $@)
+else
+ zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
+ build-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
+ target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@))
+endif
+
%.s: %.c prepare scripts FORCE
- $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.i: %.c prepare scripts FORCE
- $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.o: %.c prepare scripts FORCE
- $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.lst: %.c prepare scripts FORCE
- $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.s: %.S prepare scripts FORCE
- $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.o: %.S prepare scripts FORCE
- $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
-
-# For external modules we shall include any directory of the target,
-# but usual case there is no directory part.
-# make M=`pwd` module.o => $(dir $@)=./
-# make M=`pwd` foo/module.o => $(dir $@)=foo/
-# make M=`pwd` / => $(dir $@)=/
-
-ifeq ($(KBUILD_EXTMOD),)
- target-dir = $(@D)
-else
- zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
- target-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
-endif
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
-/ %/: scripts prepare FORCE
+# Modules
+/ %/: prepare scripts FORCE
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
- $(build)=$(target-dir)
-%.ko: scripts FORCE
+ $(build)=$(build-dir)
+%.ko: prepare scripts FORCE
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
- $(build)=$(target-dir) $(@:.ko=.o)
+ $(build)=$(build-dir) $(@:.ko=.o)
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
# FIXME Should go into a make.lib or something
diff --git a/README b/README
index 05e055530bb..3e264723b86 100644
--- a/README
+++ b/README
@@ -165,10 +165,31 @@ CONFIGURING the kernel:
"make xconfig" X windows (Qt) based configuration tool.
"make gconfig" X windows (Gtk) based configuration tool.
"make oldconfig" Default all questions based on the contents of
- your existing ./.config file.
+ your existing ./.config file and asking about
+ new config symbols.
"make silentoldconfig"
Like above, but avoids cluttering the screen
with questions already answered.
+ "make defconfig" Create a ./.config file by using the default
+ symbol values from arch/$ARCH/defconfig.
+ "make allyesconfig"
+ Create a ./.config file by setting symbol
+ values to 'y' as much as possible.
+ "make allmodconfig"
+ Create a ./.config file by setting symbol
+ values to 'm' as much as possible.
+ "make allnoconfig" Create a ./.config file by setting symbol
+ values to 'n' as much as possible.
+ "make randconfig" Create a ./.config file by setting symbol
+ values to random values.
+
+ The allyesconfig/allmodconfig/allnoconfig/randconfig variants can
+ also use the environment variable KCONFIG_ALLCONFIG to specify a
+ filename that contains config options that the user requires to be
+ set to a specific value. If KCONFIG_ALLCONFIG=filename is not used,
+ "make *config" checks for a file named "all{yes/mod/no/random}.config"
+ for symbol values that are to be forced. If this file is not found,
+ it checks for a file named "all.config" to contain forced values.
NOTES on "make config":
- having unnecessary drivers will make the kernel bigger, and can
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 9bef61b3036..213c7850d5f 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -453,7 +453,7 @@ config ALPHA_IRONGATE
config GENERIC_HWEIGHT
bool
- default y if !ALPHA_EV6 && !ALPHA_EV67
+ default y if !ALPHA_EV67
config ALPHA_AVANTI
bool
@@ -549,6 +549,11 @@ config NUMA
Access). This option is for configuring high-end multiprocessor
server machines. If in doubt, say N.
+config NODES_SHIFT
+ int
+ default "7"
+ depends on NEED_MULTIPLE_NODES
+
# LARGE_VMALLOC is racy, if you *really* need it then fix it first
config ALPHA_LARGE_VMALLOC
bool
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 1898ea79d0e..2b245ad731e 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -76,7 +76,6 @@ EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strncat);
EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strchr);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(memcmp);
@@ -183,7 +182,6 @@ EXPORT_SYMBOL(smp_num_cpus);
EXPORT_SYMBOL(smp_call_function);
EXPORT_SYMBOL(smp_call_function_on_cpu);
EXPORT_SYMBOL(_atomic_dec_and_lock);
-EXPORT_SYMBOL(cpu_present_mask);
#endif /* CONFIG_SMP */
/*
@@ -216,8 +214,6 @@ EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memchr);
-EXPORT_SYMBOL(get_wchan);
-
#ifdef CONFIG_ALPHA_IRONGATE
EXPORT_SYMBOL(irongate_ioremap);
EXPORT_SYMBOL(irongate_iounmap);
diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
index 44866cb26a8..7f6a98455e7 100644
--- a/arch/alpha/kernel/core_marvel.c
+++ b/arch/alpha/kernel/core_marvel.c
@@ -435,7 +435,7 @@ marvel_specify_io7(char *str)
str = pchar;
} while(*str);
- return 0;
+ return 1;
}
__setup("io7=", marvel_specify_io7);
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 9924fd07743..c760a831fd1 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -94,7 +94,7 @@ common_shutdown_1(void *generic_ptr)
if (cpuid != boot_cpuid) {
flags |= 0x00040000UL; /* "remain halted" */
*pflags = flags;
- clear_bit(cpuid, &cpu_present_mask);
+ cpu_clear(cpuid, cpu_present_map);
halt();
}
#endif
@@ -120,8 +120,8 @@ common_shutdown_1(void *generic_ptr)
#ifdef CONFIG_SMP
/* Wait for the secondaries to halt. */
- cpu_clear(boot_cpuid, cpu_possible_map);
- while (cpus_weight(cpu_possible_map))
+ cpu_clear(boot_cpuid, cpu_present_map);
+ while (cpus_weight(cpu_present_map))
barrier();
#endif
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index b4e5f8ff2b2..558b8336855 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -24,16 +24,19 @@
#include <linux/config.h> /* CONFIG_ALPHA_LCA etc */
#include <linux/mc146818rtc.h>
#include <linux/console.h>
+#include <linux/cpu.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/ioport.h>
+#include <linux/platform_device.h>
#include <linux/bootmem.h>
#include <linux/pci.h>
#include <linux/seq_file.h>
#include <linux/root_dev.h>
#include <linux/initrd.h>
#include <linux/eisa.h>
+#include <linux/pfn.h>
#ifdef CONFIG_MAGIC_SYSRQ
#include <linux/sysrq.h>
#include <linux/reboot.h>
@@ -42,7 +45,7 @@
#include <asm/setup.h>
#include <asm/io.h>
-extern struct notifier_block *panic_notifier_list;
+extern struct atomic_notifier_head panic_notifier_list;
static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
static struct notifier_block alpha_panic_block = {
alpha_panic_event,
@@ -241,9 +244,6 @@ reserve_std_resources(void)
request_resource(io, standard_io_resources+i);
}
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
#define PFN_MAX PFN_DOWN(0x80000000)
#define for_each_mem_cluster(memdesc, cluster, i) \
for ((cluster) = (memdesc)->cluster, (i) = 0; \
@@ -472,10 +472,21 @@ page_is_ram(unsigned long pfn)
return 0;
}
-#undef PFN_UP
-#undef PFN_DOWN
-#undef PFN_PHYS
-#undef PFN_MAX
+static int __init
+register_cpus(void)
+{
+ int i;
+
+ for_each_possible_cpu(i) {
+ struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+ register_cpu(p, i, NULL);
+ }
+ return 0;
+}
+
+arch_initcall(register_cpus);
void __init
setup_arch(char **cmdline_p)
@@ -507,7 +518,8 @@ setup_arch(char **cmdline_p)
}
/* Register a call for panic conditions. */
- notifier_chain_register(&panic_notifier_list, &alpha_panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &alpha_panic_block);
#ifdef CONFIG_ALPHA_GENERIC
/* Assume that we've booted from SRM if we haven't booted from MILO.
@@ -1484,3 +1496,20 @@ alpha_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
#endif
return NOTIFY_DONE;
}
+
+static __init int add_pcspkr(void)
+{
+ struct platform_device *pd;
+ int ret;
+
+ pd = platform_device_alloc("pcspkr", -1);
+ if (!pd)
+ return -ENOMEM;
+
+ ret = platform_device_add(pd);
+ if (ret)
+ platform_device_put(pd);
+
+ return ret;
+}
+device_initcall(add_pcspkr);
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 02c2db08114..4dc273e537f 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -68,7 +68,6 @@ enum ipi_message_type {
static int smp_secondary_alive __initdata = 0;
/* Which cpus ids came online. */
-cpumask_t cpu_present_mask;
cpumask_t cpu_online_map;
EXPORT_SYMBOL(cpu_online_map);
@@ -439,7 +438,7 @@ setup_smp(void)
if ((cpu->flags & 0x1cc) == 0x1cc) {
smp_num_probed++;
/* Assume here that "whami" == index */
- cpu_set(i, cpu_possible_map);
+ cpu_set(i, cpu_present_map);
cpu->pal_revision = boot_cpu_palrev;
}
@@ -450,12 +449,10 @@ setup_smp(void)
}
} else {
smp_num_probed = 1;
- cpu_set(boot_cpuid, cpu_possible_map);
}
- cpu_present_mask = cpumask_of_cpu(boot_cpuid);
- printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
- smp_num_probed, cpu_possible_map.bits[0]);
+ printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_map = %lx\n",
+ smp_num_probed, cpu_present_map.bits[0]);
}
/*
@@ -474,7 +471,7 @@ smp_prepare_cpus(unsigned int max_cpus)
/* Nothing to do on a UP box, or when told not to. */
if (smp_num_probed == 1 || max_cpus == 0) {
- cpu_present_mask = cpumask_of_cpu(boot_cpuid);
+ cpu_present_map = cpumask_of_cpu(boot_cpuid);
printk(KERN_INFO "SMP mode deactivated.\n");
return;
}
@@ -487,11 +484,6 @@ smp_prepare_cpus(unsigned int max_cpus)
void __devinit
smp_prepare_boot_cpu(void)
{
- /*
- * Mark the boot cpu (current cpu) as both present and online
- */
- cpu_set(smp_processor_id(), cpu_present_mask);
- cpu_set(smp_processor_id(), cpu_online_map);
}
int __devinit
diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c
index 5f84417eeb7..2551fb49ae0 100644
--- a/arch/alpha/kernel/sys_titan.c
+++ b/arch/alpha/kernel/sys_titan.c
@@ -66,7 +66,7 @@ titan_update_irq_hw(unsigned long mask)
register int bcpu = boot_cpuid;
#ifdef CONFIG_SMP
- cpumask_t cpm = cpu_present_mask;
+ cpumask_t cpm = cpu_present_map;
volatile unsigned long *dim0, *dim1, *dim2, *dim3;
unsigned long mask0, mask1, mask2, mask3, dummy;
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 6b2921be190..3859749810b 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -314,10 +314,11 @@ time_init(void)
if (!est_cycle_freq)
est_cycle_freq = validate_cc_value(calibrate_cc_with_pit());
- cc1 = rpcc_after_update_in_progress();
+ cc1 = rpcc();
/* Calibrate CPU clock -- attempt #2. */
if (!est_cycle_freq) {
+ cc1 = rpcc_after_update_in_progress();
cc2 = rpcc_after_update_in_progress();
est_cycle_freq = validate_cc_value(cc2 - cc1);
cc1 = cc2;
diff --git a/arch/alpha/lib/strncpy.S b/arch/alpha/lib/strncpy.S
index 338551c7113..bbdef1be5f9 100644
--- a/arch/alpha/lib/strncpy.S
+++ b/arch/alpha/lib/strncpy.S
@@ -43,8 +43,8 @@ strncpy:
.align 4
$multiword:
- subq $24, 1, $2 # clear the final bits in the prev word
- or $2, $24, $2
+ subq $27, 1, $2 # clear the final bits in the prev word
+ or $2, $27, $2
zapnot $1, $2, $1
subq $18, 1, $18
@@ -70,8 +70,8 @@ $multiword:
bne $18, 0b
1: ldq_u $1, 0($16) # clear the leading bits in the final word
- subq $27, 1, $2
- or $2, $27, $2
+ subq $24, 1, $2
+ or $2, $24, $2
zap $1, $2, $1
stq_u $1, 0($16)
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
index 6d5251254f6..bf6b65c81be 100644
--- a/arch/alpha/mm/numa.c
+++ b/arch/alpha/mm/numa.c
@@ -13,6 +13,7 @@
#include <linux/bootmem.h>
#include <linux/swap.h>
#include <linux/initrd.h>
+#include <linux/pfn.h>
#include <asm/hwrpb.h>
#include <asm/pgalloc.h>
@@ -27,9 +28,6 @@ bootmem_data_t node_bdata[MAX_NUMNODES];
#define DBGDCONT(args...)
#endif
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
#define for_each_mem_cluster(memdesc, cluster, i) \
for ((cluster) = (memdesc)->cluster, (i) = 0; \
(i) < (memdesc)->numclusters; (i)++, (cluster)++)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index bf2e72698d0..08b7cc900ca 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -8,6 +8,7 @@ mainmenu "Linux Kernel Configuration"
config ARM
bool
default y
+ select RTC_LIB
help
The ARM series is a line of low-power-consumption RISC chip designs
licensed by ARM Ltd and targeted at embedded applications and
@@ -76,6 +77,14 @@ config FIQ
config ARCH_MTD_XIP
bool
+config VECTORS_BASE
+ hex
+ default 0xffff0000 if MMU
+ default DRAM_BASE if REMAP_VECTORS_TO_RAM
+ default 0x00000000
+ help
+ The base address of exception vectors.
+
source "init/Kconfig"
menu "System Type"
@@ -141,8 +150,6 @@ config ARCH_IOP3XX
config ARCH_IXP4XX
bool "IXP4xx-based"
- select DMABOUNCE
- select PCI
help
Support for Intel's IXP4XX (XScale) family of processors.
@@ -152,6 +159,12 @@ config ARCH_IXP2000
help
Support for Intel's IXP2400/2800 (XScale) family of processors.
+config ARCH_IXP23XX
+ bool "IXP23XX-based"
+ select PCI
+ help
+ Support for Intel's IXP23xx (XScale) family of processors.
+
config ARCH_L7200
bool "LinkUp-L7200"
select FIQ
@@ -273,6 +286,8 @@ source "arch/arm/mach-ixp4xx/Kconfig"
source "arch/arm/mach-ixp2000/Kconfig"
+source "arch/arm/mach-ixp23xx/Kconfig"
+
source "arch/arm/mach-pxa/Kconfig"
source "arch/arm/mach-sa1100/Kconfig"
@@ -495,6 +510,12 @@ config ARCH_DISCONTIGMEM_ENABLE
or have huge holes in the physical address space for other reasons.
See <file:Documentation/vm/numa> for more.
+config NODES_SHIFT
+ int
+ default "4" if ARCH_LH7A40X
+ default "2"
+ depends on NEED_MULTIPLE_NODES
+
source "mm/Kconfig"
config LEDS
@@ -791,7 +812,8 @@ source "drivers/acorn/block/Kconfig"
if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
|| ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
- || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
+ || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
+ || ARCH_IXP23XX
source "drivers/ide/Kconfig"
endif
@@ -829,6 +851,8 @@ source "drivers/misc/Kconfig"
source "drivers/mfd/Kconfig"
+source "drivers/leds/Kconfig"
+
source "drivers/media/Kconfig"
source "drivers/video/Kconfig"
@@ -839,6 +863,8 @@ source "drivers/usb/Kconfig"
source "drivers/mmc/Kconfig"
+source "drivers/rtc/Kconfig"
+
endmenu
source "fs/Kconfig"
diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu
new file mode 100644
index 00000000000..e1574be2ded
--- /dev/null
+++ b/arch/arm/Kconfig-nommu
@@ -0,0 +1,44 @@
+#
+# Kconfig for uClinux(non-paged MM) depend configurations
+# Hyok S. Choi <hyok.choi@samsung.com>
+#
+
+config SET_MEM_PARAM
+ bool "Set flash/sdram size and base addr"
+ help
+ Say Y to manually set the base addresses and sizes.
+ otherwise, the default values are assigned.
+
+config DRAM_BASE
+ hex '(S)DRAM Base Address' if SET_MEM_PARAM
+ default 0x00800000
+
+config DRAM_SIZE
+ hex '(S)DRAM SIZE' if SET_MEM_PARAM
+ default 0x00800000
+
+config FLASH_MEM_BASE
+ hex 'FLASH Base Address' if SET_MEM_PARAM
+ default 0x00400000
+
+config FLASH_SIZE
+ hex 'FLASH Size' if SET_MEM_PARAM
+ default 0x00400000
+
+config REMAP_VECTORS_TO_RAM
+ bool 'Install vectors to the begining of RAM' if DRAM_BASE
+ depends on DRAM_BASE
+ help
+ The kernel needs to change the hardware exception vectors.
+ In nommu mode, the hardware exception vectors are normally
+ placed at address 0x00000000. However, this region may be
+ occupied by read-only memory depending on H/W design.
+
+ If the region contains read-write memory, say 'n' here.
+
+ If your CPU provides a remap facility which allows the exception
+ vectors to be mapped to writable memory, say 'n' here.
+
+ Otherwise, say 'y' here. In this case, the kernel will require
+ external support to redirect the hardware exception vectors to
+ the writable versions located at DRAM_BASE.
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 5d3acff8c59..d22f38b957d 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -101,7 +101,7 @@ config DEBUG_S3C2410_UART
help
Choice for UART for kernel low-level using S3C2410 UARTS,
should be between zero and two. The port must have been
- initalised by the boot-loader before use.
+ initialised by the boot-loader before use.
The uncompressor code port configuration is now handled
by CONFIG_S3C2410_LOWLEVEL_UART_PORT.
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 99c0d323719..6f8e84c1c1f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -20,6 +20,11 @@ GZFLAGS :=-9
# Select a platform tht is kept up-to-date
KBUILD_DEFCONFIG := versatile_defconfig
+# defines filename extension depending memory manement type.
+ifeq ($(CONFIG_MMU),)
+MMUEXT := -nommu
+endif
+
ifeq ($(CONFIG_FRAME_POINTER),y)
CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
endif
@@ -57,10 +62,11 @@ tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi
tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
+tune-$(CONFIG_CPU_XSC3) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
ifeq ($(CONFIG_AEABI),y)
-CFLAGS_ABI :=-mabi=aapcs -mno-thumb-interwork
+CFLAGS_ABI :=-mabi=aapcs-linux -mno-thumb-interwork
else
CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
endif
@@ -72,7 +78,7 @@ AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float
CHECKFLAGS += -D__arm__
#Default value
-head-y := arch/arm/kernel/head.o arch/arm/kernel/init_task.o
+head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
textofs-y := 0x00008000
machine-$(CONFIG_ARCH_RPC) := rpc
@@ -97,6 +103,7 @@ endif
machine-$(CONFIG_ARCH_IOP3XX) := iop3xx
machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx
machine-$(CONFIG_ARCH_IXP2000) := ixp2000
+ machine-$(CONFIG_ARCH_IXP23XX) := ixp23xx
machine-$(CONFIG_ARCH_OMAP1) := omap1
machine-$(CONFIG_ARCH_OMAP2) := omap2
incdir-$(CONFIG_ARCH_OMAP) := omap
@@ -131,7 +138,7 @@ else
MACHINE :=
endif
-export TEXT_OFFSET GZFLAGS
+export TEXT_OFFSET GZFLAGS MMUEXT
# Do we have FASTFPE?
FASTFPE :=arch/arm/fastfpe
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 35ffe0f4ece..2adc1527e0e 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -50,10 +50,6 @@ ifeq ($(CONFIG_ARCH_AT91RM9200),y)
OBJS += head-at91rm9200.o
endif
-ifeq ($(CONFIG_DEBUG_ICEDCC),y)
-OBJS += ice-dcc.o
-endif
-
ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
OBJS += big-endian.o
endif
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 491c7e4c9ac..b56f5e691d6 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -2,6 +2,7 @@
* linux/arch/arm/boot/compressed/head.S
*
* Copyright (C) 1996-2002 Russell King
+ * Copyright (C) 2004 Hyok S. Choi (MPU support)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -320,6 +321,62 @@ params: ldr r0, =params_phys
cache_on: mov r3, #8 @ cache_on function
b call_cache_fn
+/*
+ * Initialize the highest priority protection region, PR7
+ * to cover all 32bit address and cacheable and bufferable.
+ */
+__armv4_mpu_cache_on:
+ mov r0, #0x3f @ 4G, the whole
+ mcr p15, 0, r0, c6, c7, 0 @ PR7 Area Setting
+ mcr p15, 0, r0, c6, c7, 1
+
+ mov r0, #0x80 @ PR7
+ mcr p15, 0, r0, c2, c0, 0 @ D-cache on
+ mcr p15, 0, r0, c2, c0, 1 @ I-cache on
+ mcr p15, 0, r0, c3, c0, 0 @ write-buffer on
+
+ mov r0, #0xc000
+ mcr p15, 0, r0, c5, c0, 1 @ I-access permission
+ mcr p15, 0, r0, c5, c0, 0 @ D-access permission
+
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
+ mcr p15, 0, r0, c7, c5, 0 @ flush(inval) I-Cache
+ mcr p15, 0, r0, c7, c6, 0 @ flush(inval) D-Cache
+ mrc p15, 0, r0, c1, c0, 0 @ read control reg
+ @ ...I .... ..D. WC.M
+ orr r0, r0, #0x002d @ .... .... ..1. 11.1
+ orr r0, r0, #0x1000 @ ...1 .... .... ....
+
+ mcr p15, 0, r0, c1, c0, 0 @ write control reg
+
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ flush(inval) I-Cache
+ mcr p15, 0, r0, c7, c6, 0 @ flush(inval) D-Cache
+ mov pc, lr
+
+__armv3_mpu_cache_on:
+ mov r0, #0x3f @ 4G, the whole
+ mcr p15, 0, r0, c6, c7, 0 @ PR7 Area Setting
+
+ mov r0, #0x80 @ PR7
+ mcr p15, 0, r0, c2, c0, 0 @ cache on
+ mcr p15, 0, r0, c3, c0, 0 @ write-buffer on
+
+ mov r0, #0xc000
+ mcr p15, 0, r0, c5, c0, 0 @ access permission
+
+ mov r0, #0
+ mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
+ mrc p15, 0, r0, c1, c0, 0 @ read control reg
+ @ .... .... .... WC.M
+ orr r0, r0, #0x000d @ .... .... .... 11.1
+ mov r0, #0
+ mcr p15, 0, r0, c1, c0, 0 @ write control reg
+
+ mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
+ mov pc, lr
+
__setup_mmu: sub r3, r4, #16384 @ Page directory size
bic r3, r3, #0xff @ Align the pointer
bic r3, r3, #0x3f00
@@ -496,6 +553,18 @@ proc_types:
b __armv4_mmu_cache_off
mov pc, lr
+ .word 0x41007400 @ ARM74x
+ .word 0xff00ff00
+ b __armv3_mpu_cache_on
+ b __armv3_mpu_cache_off
+ b __armv3_mpu_cache_flush
+
+ .word 0x41009400 @ ARM94x
+ .word 0xff00ff00
+ b __armv4_mpu_cache_on
+ b __armv4_mpu_cache_off
+ b __armv4_mpu_cache_flush
+
.word 0x00007000 @ ARM7 IDs
.word 0x0000f000
mov pc, lr
@@ -562,6 +631,24 @@ proc_types:
cache_off: mov r3, #12 @ cache_off function
b call_cache_fn
+__armv4_mpu_cache_off:
+ mrc p15, 0, r0, c1, c0
+ bic r0, r0, #0x000d
+ mcr p15, 0, r0, c1, c0 @ turn MPU and cache off
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
+ mcr p15, 0, r0, c7, c6, 0 @ flush D-Cache
+ mcr p15, 0, r0, c7, c5, 0 @ flush I-Cache
+ mov pc, lr
+
+__armv3_mpu_cache_off:
+ mrc p15, 0, r0, c1, c0
+ bic r0, r0, #0x000d
+ mcr p15, 0, r0, c1, c0, 0 @ turn MPU and cache off
+ mov r0, #0
+ mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
+ mov pc, lr
+
__armv4_mmu_cache_off:
mrc p15, 0, r0, c1, c0
bic r0, r0, #0x000d
@@ -601,6 +688,24 @@ cache_clean_flush:
mov r3, #16
b call_cache_fn
+__armv4_mpu_cache_flush:
+ mov r2, #1
+ mov r3, #0
+ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
+ mov r1, #7 << 5 @ 8 segments
+1: orr r3, r1, #63 << 26 @ 64 entries
+2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index
+ subs r3, r3, #1 << 26
+ bcs 2b @ entries 63 to 0
+ subs r1, r1, #1 << 5
+ bcs 1b @ segments 7 to 0
+
+ teq r2, #0
+ mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+
__armv6_mmu_cache_flush:
mov r1, #0
mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D
@@ -638,6 +743,7 @@ no_cache_id:
mov pc, lr
__armv3_mmu_cache_flush:
+__armv3_mpu_cache_flush:
mov r1, #0
mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
mov pc, lr
diff --git a/arch/arm/boot/compressed/ice-dcc.S b/arch/arm/boot/compressed/ice-dcc.S
deleted file mode 100644
index 104377a199b..00000000000
--- a/arch/arm/boot/compressed/ice-dcc.S
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- .text
-
- .global icedcc_putc
-
-icedcc_putc:
- mov r2, #0x4000000
-1:
- subs r2, r2, #1
- movlt pc, r14
- mrc p14, 0, r1, c0, c0, 0
- tst r1, #2
- bne 1b
-
- mcr p14, 0, r0, c1, c0, 0
- mov pc, r14
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 5ab94584bae..ace3fb5835d 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -20,24 +20,45 @@ unsigned int __machine_arch_type;
#include <linux/string.h>
-#include <asm/arch/uncompress.h>
-
#ifdef STANDALONE_DEBUG
#define putstr printf
-#endif
+#else
+
+static void putstr(const char *ptr);
+
+#include <linux/compiler.h>
+#include <asm/arch/uncompress.h>
#ifdef CONFIG_DEBUG_ICEDCC
-#define putstr icedcc_putstr
-#define putc icedcc_putc
+static void icedcc_putc(int ch)
+{
+ int status, i = 0x4000000;
-extern void icedcc_putc(int ch);
+ do {
+ if (--i < 0)
+ return;
-static void
-icedcc_putstr(const char *ptr)
+ asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
+ } while (status & 2);
+
+ asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
+}
+
+#define putc(ch) icedcc_putc(ch)
+#define flush() do { } while (0)
+#endif
+
+static void putstr(const char *ptr)
{
- for (; *ptr != '\0'; ptr++) {
- icedcc_putc(*ptr);
+ char c;
+
+ while ((c = *ptr++) != '\0') {
+ if (c == '\n')
+ putc('\r');
+ putc(c);
}
+
+ flush();
}
#endif
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in
index eed616113e4..153a07e7222 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.in
@@ -18,6 +18,7 @@ SECTIONS
_start = .;
*(.start)
*(.text)
+ *(.text.*)
*(.fixup)
*(.gnu.warning)
*(.rodata)
diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
index e851d86c212..35c9a64ac14 100644
--- a/arch/arm/common/rtctime.c
+++ b/arch/arm/common/rtctime.c
@@ -20,6 +20,7 @@
#include <linux/capability.h>
#include <linux/device.h>
#include <linux/mutex.h>
+#include <linux/rtc.h>
#include <asm/rtc.h>
#include <asm/semaphore.h>
@@ -42,89 +43,6 @@ static struct rtc_ops *rtc_ops;
#define rtc_epoch 1900UL
-static const unsigned char days_in_month[] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
-#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400))
-
-static int month_days(unsigned int month, unsigned int year)
-{
- return days_in_month[month] + (LEAP_YEAR(year) && month == 1);
-}
-
-/*
- * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
- */
-void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
-{
- int days, month, year;
-
- days = time / 86400;
- time -= days * 86400;
-
- tm->tm_wday = (days + 4) % 7;
-
- year = 1970 + days / 365;
- days -= (year - 1970) * 365
- + LEAPS_THRU_END_OF(year - 1)
- - LEAPS_THRU_END_OF(1970 - 1);
- if (days < 0) {
- year -= 1;
- days += 365 + LEAP_YEAR(year);
- }
- tm->tm_year = year - 1900;
- tm->tm_yday = days + 1;
-
- for (month = 0; month < 11; month++) {
- int newdays;
-
- newdays = days - month_days(month, year);
- if (newdays < 0)
- break;
- days = newdays;
- }
- tm->tm_mon = month;
- tm->tm_mday = days + 1;
-
- tm->tm_hour = time / 3600;
- time -= tm->tm_hour * 3600;
- tm->tm_min = time / 60;
- tm->tm_sec = time - tm->tm_min * 60;
-}
-EXPORT_SYMBOL(rtc_time_to_tm);
-
-/*
- * Does the rtc_time represent a valid date/time?
- */
-int rtc_valid_tm(struct rtc_time *tm)
-{
- if (tm->tm_year < 70 ||
- tm->tm_mon >= 12 ||
- tm->tm_mday < 1 ||
- tm->tm_mday > month_days(tm->tm_mon, tm->tm_year + 1900) ||
- tm->tm_hour >= 24 ||
- tm->tm_min >= 60 ||
- tm->tm_sec >= 60)
- return -EINVAL;
-
- return 0;
-}
-EXPORT_SYMBOL(rtc_valid_tm);
-
-/*
- * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
- */
-int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
-{
- *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
-
- return 0;
-}
-EXPORT_SYMBOL(rtc_tm_to_time);
-
/*
* Calculate the next alarm time given the requested alarm time mask
* and the current time.
@@ -151,13 +69,13 @@ void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc
}
}
-static inline int rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm)
+static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm)
{
memset(tm, 0, sizeof(struct rtc_time));
return ops->read_time(tm);
}
-static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm)
+static inline int rtc_arm_set_time(struct rtc_ops *ops, struct rtc_time *tm)
{
int ret;
@@ -168,7 +86,7 @@ static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm)
return ret;
}
-static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
+static inline int rtc_arm_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
{
int ret = -EINVAL;
if (ops->read_alarm) {
@@ -178,7 +96,7 @@ static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
return ret;
}
-static inline int rtc_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
+static inline int rtc_arm_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
{
int ret = -EINVAL;
if (ops->set_alarm)
@@ -266,7 +184,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
switch (cmd) {
case RTC_ALM_READ:
- ret = rtc_read_alarm(ops, &alrm);
+ ret = rtc_arm_read_alarm(ops, &alrm);
if (ret)
break;
ret = copy_to_user(uarg, &alrm.time, sizeof(tm));
@@ -288,11 +206,11 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
alrm.time.tm_wday = -1;
alrm.time.tm_yday = -1;
alrm.time.tm_isdst = -1;
- ret = rtc_set_alarm(ops, &alrm);
+ ret = rtc_arm_set_alarm(ops, &alrm);
break;
case RTC_RD_TIME:
- ret = rtc_read_time(ops, &tm);
+ ret = rtc_arm_read_time(ops, &tm);
if (ret)
break;
ret = copy_to_user(uarg, &tm, sizeof(tm));
@@ -310,7 +228,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
ret = -EFAULT;
break;
}
- ret = rtc_set_time(ops, &tm);
+ ret = rtc_arm_set_time(ops, &tm);
break;
case RTC_EPOCH_SET:
@@ -341,11 +259,11 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
ret = -EFAULT;
break;
}
- ret = rtc_set_alarm(ops, &alrm);
+ ret = rtc_arm_set_alarm(ops, &alrm);
break;
case RTC_WKALM_RD:
- ret = rtc_read_alarm(ops, &alrm);
+ ret = rtc_arm_read_alarm(ops, &alrm);
if (ret)
break;
ret = copy_to_user(uarg, &alrm, sizeof(alrm));
@@ -435,7 +353,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo
struct rtc_time tm;
char *p = page;
- if (rtc_read_time(ops, &tm) == 0) {
+ if (rtc_arm_read_time(ops, &tm) == 0) {
p += sprintf(p,
"rtc_time\t: %02d:%02d:%02d\n"
"rtc_date\t: %04d-%02d-%02d\n"
@@ -445,7 +363,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo
rtc_epoch);
}
- if (rtc_read_alarm(ops, &alrm) == 0) {
+ if (rtc_arm_read_alarm(ops, &alrm) == 0) {
p += sprintf(p, "alrm_time\t: ");
if ((unsigned int)alrm.time.tm_hour <= 24)
p += sprintf(p, "%02d:", alrm.time.tm_hour);
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 5e830f444c6..314ebd3a1d7 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -18,6 +18,18 @@
#include <asm/io.h>
#include <asm/hardware/scoop.h>
+/* PCMCIA to Scoop linkage
+
+ There is no easy way to link multiple scoop devices into one
+ single entity for the pxa2xx_pcmcia device so this structure
+ is used which is setup by the platform code.
+
+ This file is never modular so this symbol is always
+ accessile to the board support files.
+*/
+struct scoop_pcmcia_config *platform_scoop_config;
+EXPORT_SYMBOL(platform_scoop_config);
+
#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
struct scoop_dev {
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index 978d32e82d3..3cd8c9ee451 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/leds.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -75,6 +76,7 @@ static void sharpsl_battery_thread(void *private_);
struct sharpsl_pm_status sharpsl_pm;
DECLARE_WORK(toggle_charger, sharpsl_charge_toggle, NULL);
DECLARE_WORK(sharpsl_bat, sharpsl_battery_thread, NULL);
+DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger);
static int get_percentage(int voltage)
@@ -190,10 +192,10 @@ void sharpsl_pm_led(int val)
dev_err(sharpsl_pm.dev, "Charging Error!\n");
} else if (val == SHARPSL_LED_ON) {
dev_dbg(sharpsl_pm.dev, "Charge LED On\n");
-
+ led_trigger_event(sharpsl_charge_led_trigger, LED_FULL);
} else {
dev_dbg(sharpsl_pm.dev, "Charge LED Off\n");
-
+ led_trigger_event(sharpsl_charge_led_trigger, LED_OFF);
}
}
@@ -786,6 +788,8 @@ static int __init sharpsl_pm_probe(struct platform_device *pdev)
init_timer(&sharpsl_pm.chrg_full_timer);
sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer;
+ led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger);
+
sharpsl_pm.machinfo->init();
device_create_file(&pdev->dev, &dev_attr_battery_percentage);
@@ -807,6 +811,8 @@ static int sharpsl_pm_remove(struct platform_device *pdev)
device_remove_file(&pdev->dev, &dev_attr_battery_percentage);
device_remove_file(&pdev->dev, &dev_attr_battery_voltage);
+ led_trigger_unregister_simple(sharpsl_charge_led_trigger);
+
sharpsl_pm.machinfo->exit();
del_timer_sync(&sharpsl_pm.chrg_full_timer);
diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig
index 1fe73d19888..9e1c1cceb73 100644
--- a/arch/arm/configs/at91rm9200dk_defconfig
+++ b/arch/arm/configs/at91rm9200dk_defconfig
@@ -379,7 +379,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
CONFIG_MTD_AT91_DATAFLASH=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
#
# NAND Flash Device Drivers
diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig
index b7d934cdb1b..6e0805a971d 100644
--- a/arch/arm/configs/at91rm9200ek_defconfig
+++ b/arch/arm/configs/at91rm9200ek_defconfig
@@ -370,7 +370,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
CONFIG_MTD_AT91_DATAFLASH=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
#
# NAND Flash Device Drivers
diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig
index c9aa878e610..074c47a4fb2 100644
--- a/arch/arm/configs/collie_defconfig
+++ b/arch/arm/configs/collie_defconfig
@@ -1,21 +1,21 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc3
-# Sun Oct 9 16:55:14 2005
+# Linux kernel version: 2.6.17-rc1
+# Fri Apr 14 19:09:52 2006
#
CONFIG_ARM=y
CONFIG_MMU=y
-CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
-CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
#
@@ -23,45 +23,58 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
#
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
+# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_BASE_FULL=y
+CONFIG_ELF_CORE=y
+# CONFIG_BASE_FULL is not set
CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EPOLL is not set
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_SLAB is not set
+CONFIG_DOUBLEFAULT=y
# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
+CONFIG_BASE_SMALL=1
+CONFIG_SLOB=y
+CONFIG_OBSOLETE_INTERMODULE=y
#
# Loadable module support
#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
#
# System Type
@@ -70,11 +83,13 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
# CONFIG_ARCH_L7200 is not set
# CONFIG_ARCH_PXA is not set
# CONFIG_ARCH_RPC is not set
@@ -84,9 +99,11 @@ CONFIG_ARCH_SA1100=y
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_H720X is not set
# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
#
# SA11x0 Implementations
@@ -128,20 +145,32 @@ CONFIG_SHARP_SCOOP=y
# Bus support
#
CONFIG_ISA=y
-CONFIG_ISA_DMA_API=y
#
# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_PCCARD is not set
+CONFIG_PCCARD=y
+CONFIG_PCMCIA_DEBUG=y
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_SA1100=y
#
# Kernel Features
#
-# CONFIG_SMP is not set
-CONFIG_PREEMPT=y
+# CONFIG_PREEMPT is not set
# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_NODES_SHIFT=2
CONFIG_SELECT_MEMORY_MODEL=y
# CONFIG_FLATMEM_MANUAL is not set
CONFIG_DISCONTIGMEM_MANUAL=y
@@ -150,6 +179,7 @@ CONFIG_DISCONTIGMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
# CONFIG_LEDS is not set
CONFIG_ALIGNMENT_TRAP=y
@@ -158,7 +188,7 @@ CONFIG_ALIGNMENT_TRAP=y
#
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2 debug"
+CONFIG_CMDLINE="noinitrd root=/dev/mtdblock2 rootfstype=jffs2 fbcon=rotate:1"
# CONFIG_XIP_KERNEL is not set
#
@@ -181,14 +211,16 @@ CONFIG_FPE_NWFPE=y
# Userspace binary formats
#
CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=m
-CONFIG_BINFMT_MISC=m
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
# CONFIG_ARTHUR is not set
#
# Power management options
#
CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
CONFIG_APM=y
#
@@ -199,6 +231,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -211,16 +244,19 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -232,6 +268,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -244,8 +285,11 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -265,10 +309,15 @@ CONFIG_TCP_CONG_BIC=y
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
+CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
@@ -287,32 +336,49 @@ CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
#
# RAM/ROM/Flash chip drivers
#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
CONFIG_MTD_MAP_BANK_WIDTH_4=y
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I1 is not set
+# CONFIG_MTD_CFI_I2 is not set
+CONFIG_MTD_CFI_I4=y
# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
CONFIG_MTD_OBSOLETE_CHIPS=y
CONFIG_MTD_SHARP=y
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_SA1100=y
+# CONFIG_MTD_IMPA7 is not set
# CONFIG_MTD_PLATRAM is not set
#
@@ -321,7 +387,6 @@ CONFIG_MTD_SHARP=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -337,6 +402,11 @@ CONFIG_MTD_SHARP=y
# CONFIG_MTD_NAND is not set
#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
# Parallel port support
#
# CONFIG_PARPORT is not set
@@ -349,7 +419,6 @@ CONFIG_MTD_SHARP=y
#
# Block devices
#
-# CONFIG_BLK_DEV_XD is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -359,20 +428,35 @@ CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=1024
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
#
-# IO Schedulers
+# ATA/ATAPI/MFM/RLL support
#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_ATA_OVER_ETH=m
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
#
-# ATA/ATAPI/MFM/RLL support
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
#
-# CONFIG_IDE is not set
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
#
# SCSI device support
@@ -402,6 +486,39 @@ CONFIG_ATA_OVER_ETH=m
# Network device support
#
# CONFIG_NETDEVICES is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=y
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -424,7 +541,7 @@ CONFIG_INPUT_TSDEV=y
CONFIG_INPUT_TSDEV_SCREEN_X=240
CONFIG_INPUT_TSDEV_SCREEN_Y=320
CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_EVBUG=y
+# CONFIG_INPUT_EVBUG is not set
#
# Input Device Drivers
@@ -438,7 +555,11 @@ CONFIG_KEYBOARD_LOCOMO=y
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
# CONFIG_INPUT_MISC is not set
#
@@ -461,7 +582,16 @@ CONFIG_HW_CONSOLE=y
#
# Serial drivers
#
-# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_CS=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
#
# Non-8250 serial port support
@@ -483,94 +613,48 @@ CONFIG_UNIX98_PTYS=y
#
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
-# CONFIG_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
+# PCMCIA character devices
#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
#
-# I2C support
+# TPM devices
#
-CONFIG_I2C=m
-# CONFIG_I2C_CHARDEV is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
#
-# I2C Algorithms
+# I2C support
#
-CONFIG_I2C_ALGOBIT=m
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
+# CONFIG_I2C is not set
#
-# I2C Hardware Bus support
+# SPI support
#
-# CONFIG_I2C_ELEKTOR is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_PCA_ISA is not set
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
#
-# Miscellaneous I2C Chip support
+# Dallas's 1-wire bus
#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 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_RTC8564 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
#
-CONFIG_HWMON=y
+# CONFIG_HWMON is not set
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@@ -579,42 +663,33 @@ CONFIG_HWMON=y
#
# Multimedia Capabilities Port drivers
#
-# CONFIG_MCP_SA11X0 is not set
+CONFIG_MCP=y
+CONFIG_MCP_SA11X0=y
+CONFIG_MCP_UCB1200=y
+CONFIG_MCP_UCB1200_TS=y
#
-# Multimedia devices
+# LED devices
#
-CONFIG_VIDEO_DEV=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
#
-# Video For Linux
+# LED drivers
#
+CONFIG_LEDS_LOCOMO=y
#
-# Video Adapters
+# LED Triggers
#
-# CONFIG_VIDEO_PMS is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_SAA5246A is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_TUNER_3036 is not set
-# CONFIG_VIDEO_OVCAMCHIP is not set
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
#
-# Radio Adapters
+# Multimedia devices
#
-# CONFIG_RADIO_CADET is not set
-# CONFIG_RADIO_RTRACK is not set
-# CONFIG_RADIO_RTRACK2 is not set
-# CONFIG_RADIO_AZTECH is not set
-# CONFIG_RADIO_GEMTEK is not set
-# CONFIG_RADIO_MAESTRO is not set
-# CONFIG_RADIO_SF16FMI is not set
-# CONFIG_RADIO_SF16FMR2 is not set
-# CONFIG_RADIO_TERRATEC is not set
-# CONFIG_RADIO_TRUST is not set
-# CONFIG_RADIO_TYPHOON is not set
-# CONFIG_RADIO_ZOLTRIX is not set
+# CONFIG_VIDEO_DEV is not set
#
# Digital Video Broadcasting Devices
@@ -628,8 +703,8 @@ CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_FIRMWARE_EDID is not set
CONFIG_FB_MODE_HELPERS=y
# CONFIG_FB_TILEBLITTING is not set
CONFIG_FB_SA1100=y
@@ -643,14 +718,15 @@ CONFIG_FB_SA1100=y
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x8 is not set
# CONFIG_FONT_8x16 is not set
# CONFIG_FONT_6x11 is not set
# CONFIG_FONT_7x14 is not set
# CONFIG_FONT_PEARL_8x8 is not set
# CONFIG_FONT_ACORN_8x8 is not set
-# CONFIG_FONT_MINI_4x6 is not set
+CONFIG_FONT_MINI_4x6=y
# CONFIG_FONT_SUN8x16 is not set
# CONFIG_FONT_SUN12x22 is not set
# CONFIG_FONT_10x18 is not set
@@ -659,7 +735,11 @@ CONFIG_FONT_8x8=y
# Logo configuration
#
# CONFIG_LOGO is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
#
# Sound
@@ -671,20 +751,17 @@ CONFIG_FONT_8x8=y
#
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB is not set
#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
# USB Gadget Support
#
-CONFIG_USB_GADGET=y
-# CONFIG_USB_GADGET_DEBUG_FILES is not set
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_PXA2XX is not set
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_LH7A40X is not set
-# CONFIG_USB_GADGET_OMAP is not set
-# CONFIG_USB_GADGET_DUMMY_HCD is not set
-# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_GADGET is not set
#
# MMC/SD Card support
@@ -692,23 +769,24 @@ CONFIG_USB_GADGET=y
# CONFIG_MMC is not set
#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
# File systems
#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_JBD 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_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
-CONFIG_INOTIFY=y
+# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
@@ -725,7 +803,7 @@ CONFIG_INOTIFY=y
# DOS/FAT/NT Filesystems
#
CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
+# CONFIG_MSDOS_FS is not set
CONFIG_VFAT_FS=y
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
@@ -739,7 +817,7 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -755,11 +833,12 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
-CONFIG_CRAMFS=y
+# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
@@ -789,7 +868,7 @@ CONFIG_MSDOS_PARTITION=y
#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="cp437"
-CONFIG_NLS_CODEPAGE_437=m
+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
@@ -813,7 +892,7 @@ CONFIG_NLS_CODEPAGE_437=m
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
@@ -826,7 +905,7 @@ CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
-CONFIG_NLS_UTF8=m
+# CONFIG_NLS_UTF8 is not set
#
# Profiling support
@@ -837,20 +916,23 @@ CONFIG_NLS_UTF8=m
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUG_USER is not set
# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
@@ -874,7 +956,7 @@ CONFIG_DEBUG_ERRORS=y
#
# Library routines
#
-# CONFIG_CRC_CCITT is not set
+CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index 8dcc8e8ec81..b69e88bbc90 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -1,12 +1,14 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16
-# Mon Mar 20 14:54:51 2006
+# Linux kernel version: 2.6.17-rc2
+# Wed Apr 19 21:21:01 2006
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
#
# Code maturity level options
@@ -28,6 +30,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -43,10 +46,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -59,7 +58,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -67,6 +65,7 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -94,6 +93,7 @@ CONFIG_ARCH_EP93XX=y
# CONFIG_ARCH_IOP3XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
# CONFIG_ARCH_L7200 is not set
# CONFIG_ARCH_PXA is not set
# CONFIG_ARCH_RPC is not set
@@ -112,7 +112,6 @@ CONFIG_ARCH_EP93XX=y
#
# Cirrus EP93xx Implementation Options
#
-CONFIG_CRUNCH=y
#
# EP93xx Platforms
@@ -232,12 +231,15 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -346,7 +348,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_OTP is not set
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -371,7 +372,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -412,7 +412,7 @@ CONFIG_MTD_NAND_IDS=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_UB is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -576,13 +576,13 @@ CONFIG_WATCHDOG=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_EP93XX_WATCHDOG=y
#
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
@@ -626,9 +626,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
CONFIG_I2C_DEBUG_CORE=y
CONFIG_I2C_DEBUG_ALGO=y
CONFIG_I2C_DEBUG_BUS=y
@@ -690,7 +688,16 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
#
#
@@ -702,6 +709,7 @@ CONFIG_HWMON=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -718,6 +726,7 @@ CONFIG_HWMON=y
#
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
CONFIG_USB=y
CONFIG_USB_DEBUG=y
@@ -776,15 +785,6 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -813,6 +813,7 @@ CONFIG_USB_SERIAL_CONSOLE=y
# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
# CONFIG_USB_SERIAL_EMPEG is not set
# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
# CONFIG_USB_SERIAL_VISOR is not set
# CONFIG_USB_SERIAL_IPAQ is not set
# CONFIG_USB_SERIAL_IR is not set
@@ -825,6 +826,7 @@ CONFIG_USB_SERIAL_CONSOLE=y
# CONFIG_USB_SERIAL_KLSI is not set
# CONFIG_USB_SERIAL_KOBIL_SCT is not set
# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
CONFIG_USB_SERIAL_PL2303=y
# CONFIG_USB_SERIAL_HP4X is not set
# CONFIG_USB_SERIAL_SAFE is not set
@@ -865,6 +867,32 @@ CONFIG_USB_SERIAL_PL2303=y
# CONFIG_MMC is not set
#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+CONFIG_RTC_DRV_M48T86=y
+CONFIG_RTC_DRV_EP93XX=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -912,7 +940,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1044,6 +1071,7 @@ CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
@@ -1053,6 +1081,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/ixp2000_defconfig b/arch/arm/configs/ixp2000_defconfig
index 7b02ca04c3e..e6f3e4873d6 100644
--- a/arch/arm/configs/ixp2000_defconfig
+++ b/arch/arm/configs/ixp2000_defconfig
@@ -1,18 +1,19 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Wed Feb 8 04:49:11 2006
+# Linux kernel version: 2.6.17-rc2
+# Wed Apr 19 21:12:49 2006
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -29,6 +30,7 @@ CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -44,10 +46,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -60,7 +58,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -68,6 +65,7 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -89,11 +87,13 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
# CONFIG_ARCH_IXP4XX is not set
CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_IXP23XX is not set
# CONFIG_ARCH_L7200 is not set
# CONFIG_ARCH_PXA is not set
# CONFIG_ARCH_RPC is not set
@@ -123,6 +123,7 @@ CONFIG_ARCH_IXDP2800=y
CONFIG_ARCH_IXDP2X00=y
CONFIG_ARCH_IXDP2401=y
CONFIG_ARCH_IXDP2801=y
+CONFIG_MACH_IXDP28X5=y
CONFIG_ARCH_IXDP2X01=y
# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
@@ -147,7 +148,6 @@ CONFIG_XSCALE_PMU=y
# Bus support
#
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -160,6 +160,7 @@ CONFIG_PCI_LEGACY_PROC=y
#
# CONFIG_PREEMPT is not set
# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
# CONFIG_AEABI is not set
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -213,6 +214,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -232,12 +234,15 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -347,7 +352,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -366,7 +370,6 @@ CONFIG_MTD_IXP2000=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -614,8 +617,9 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=3
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
# CONFIG_SERIAL_8250_EXTENDED is not set
#
@@ -623,6 +627,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -650,7 +655,6 @@ CONFIG_IXP2000_WATCHDOG=y
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -696,7 +700,6 @@ CONFIG_I2C_IXP2000=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -715,9 +718,7 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -730,6 +731,11 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_SPI_MASTER is not set
#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
# Hardware Monitoring support
#
CONFIG_HWMON=y
@@ -742,6 +748,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
@@ -776,7 +783,16 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
#
#
@@ -804,6 +820,7 @@ CONFIG_HWMON=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -821,6 +838,12 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -870,7 +893,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -972,6 +994,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/ixp23xx_defconfig b/arch/arm/configs/ixp23xx_defconfig
new file mode 100644
index 00000000000..9ce898a6cf8
--- /dev/null
+++ b/arch/arm/configs/ixp23xx_defconfig
@@ -0,0 +1,1304 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc2
+# Wed Apr 19 21:13:50 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# 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_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+CONFIG_ARCH_IXP23XX=y
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP23xx Implementation Options
+#
+
+#
+# IXP23xx Platforms
+#
+CONFIG_MACH_ESPRESSO=y
+CONFIG_MACH_IXDP2351=y
+CONFIG_MACH_ROADRUNNER=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSC3=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_IO_36=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# 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=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_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_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_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_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_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
+
+#
+# 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_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=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
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 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 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_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000_NAPI=y
+# 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 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# 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
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM 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
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# 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_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND 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=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY 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_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_VFAT_FS is not set
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig
index 2687a225aa6..96b7a776242 100644
--- a/arch/arm/configs/versatile_defconfig
+++ b/arch/arm/configs/versatile_defconfig
@@ -1,50 +1,55 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Mon Mar 28 00:20:50 2005
+# Linux kernel version: 2.6.17-rc3
+# Mon May 8 20:15:57 2006
#
CONFIG_ARM=y
CONFIG_MMU=y
-CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
+CONFIG_VECTORS_BASE=0xffff0000
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
#
CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED 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=y
CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
#
# Loadable module support
@@ -52,23 +57,42 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
# System Type
#
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
# CONFIG_ARCH_L7200 is not set
# CONFIG_ARCH_PXA is not set
# CONFIG_ARCH_RPC is not set
@@ -78,14 +102,17 @@ CONFIG_KMOD=y
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
CONFIG_ARCH_VERSATILE=y
+# CONFIG_ARCH_REALVIEW is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
#
# Versatile platform type
#
CONFIG_ARCH_VERSATILE_PB=y
-# CONFIG_MACH_VERSATILE_AB is not set
+CONFIG_MACH_VERSATILE_AB=y
#
# Processor Type
@@ -106,12 +133,14 @@ CONFIG_ARM_THUMB=y
# CONFIG_CPU_DCACHE_DISABLE is not set
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+CONFIG_ARM_VIC=y
CONFIG_ICST307=y
#
# Bus support
#
CONFIG_ARM_AMBA=y
+# CONFIG_PCI is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -122,6 +151,18 @@ CONFIG_ARM_AMBA=y
# Kernel Features
#
# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
CONFIG_LEDS=y
CONFIG_LEDS_TIMER=y
CONFIG_LEDS_CPU=y
@@ -145,7 +186,7 @@ CONFIG_CMDLINE="root=1f03 mem=32M"
CONFIG_FPE_NWFPE=y
# CONFIG_FPE_NWFPE_XP is not set
# CONFIG_FPE_FASTFPE is not set
-# CONFIG_VFP is not set
+CONFIG_VFP=y
#
# Userspace binary formats
@@ -159,9 +200,92 @@ CONFIG_BINFMT_ELF=y
# Power management options
#
CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
# CONFIG_APM is not set
#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
# Device Drivers
#
@@ -174,6 +298,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_DEBUG_DRIVER is not set
#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
@@ -192,6 +321,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
#
# RAM/ROM/Flash chip drivers
@@ -214,6 +344,7 @@ CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
@@ -221,7 +352,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -229,7 +360,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
CONFIG_MTD_ARM_INTEGRATOR=y
-# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
@@ -237,7 +368,6 @@ CONFIG_MTD_ARM_INTEGRATOR=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -253,6 +383,11 @@ CONFIG_MTD_ARM_INTEGRATOR=y
# CONFIG_MTD_NAND is not set
#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
# Parallel port support
#
# CONFIG_PARPORT is not set
@@ -264,7 +399,6 @@ CONFIG_MTD_ARM_INTEGRATOR=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
@@ -272,21 +406,13 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_ATA_OVER_ETH is not set
#
# SCSI device support
#
+# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
#
@@ -297,6 +423,7 @@ CONFIG_IOSCHED_CFQ=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -307,71 +434,8 @@ CONFIG_IOSCHED_CFQ=y
#
#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
+# Network device support
#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
@@ -379,11 +443,17 @@ CONFIG_NETDEVICES=y
# CONFIG_TUN is not set
#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
#
# Ethernet (1000 Mbit)
@@ -410,6 +480,8 @@ CONFIG_SMC91X=y
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@@ -459,7 +531,6 @@ CONFIG_SERIO_AMBAKMI=y
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
@@ -474,17 +545,16 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=m
CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-CONFIG_SERIAL_8250_MULTIPORT=y
CONFIG_SERIAL_8250_RSA=y
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_AMBA_PL010 is not set
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_SERIAL_CORE=y
@@ -503,20 +573,19 @@ CONFIG_LEGACY_PTY_COUNT=16
#
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
# TPM devices
#
# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -534,60 +603,60 @@ CONFIG_I2C_ALGOBIT=y
#
# I2C Hardware Bus support
#
-# CONFIG_I2C_ISA is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_STUB is not set
# CONFIG_I2C_PCA_ISA is not set
#
-# Hardware Sensors Chip support
-#
-CONFIG_I2C_SENSOR=m
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
+# Miscellaneous I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
CONFIG_SENSORS_EEPROM=m
# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
# Misc devices
#
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -604,27 +673,31 @@ CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_FIRMWARE_EDID is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
CONFIG_FB_ARMCLCD=y
+# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
#
# Console display driver support
#
-# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_FONTS=y
# CONFIG_FONT_8x8 is not set
# CONFIG_FONT_8x16 is not set
# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
# CONFIG_FONT_PEARL_8x8 is not set
CONFIG_FONT_ACORN_8x8=y
# CONFIG_FONT_MINI_4x6 is not set
# CONFIG_FONT_SUN8x16 is not set
# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
#
# Logo configuration
@@ -647,12 +720,18 @@ CONFIG_SND_PCM=m
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
#
# Generic devices
#
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_SERIAL_U16550 is not set
@@ -661,6 +740,7 @@ CONFIG_SND_PCM_OSS=m
#
# ALSA ARM devices
#
+CONFIG_SND_ARMAACI=m
#
# Open Sound System
@@ -672,9 +752,14 @@ CONFIG_SND_PCM_OSS=m
#
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB is not set
#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -688,25 +773,31 @@ CONFIG_MMC_BLOCK=y
CONFIG_MMC_ARMMMCI=m
#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
CONFIG_MINIX_FS=y
CONFIG_ROMFS_FS=y
+# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
@@ -729,11 +820,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -748,8 +838,8 @@ CONFIG_RAMFS=y
# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -766,16 +856,19 @@ CONFIG_CRAMFS=y
#
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
CONFIG_NFSD=y
CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
# CONFIG_NFSD_V4 is not set
# CONFIG_NFSD_TCP is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -784,6 +877,7 @@ 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
@@ -803,6 +897,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
#
@@ -858,18 +953,24 @@ CONFIG_NLS_ISO8859_1=m
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
@@ -895,6 +996,7 @@ CONFIG_DEBUG_LL=y
# Library routines
#
# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 2ce0e3a27a4..a601b8b55f3 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -29,7 +29,7 @@ ifneq ($(CONFIG_ARCH_EBSA110),y)
obj-y += io.o
endif
-head-y := head.o
+head-y := head$(MMUEXT).o
obj-$(CONFIG_DEBUG_LL) += debug.o
extra-y := $(head-y) init_task.o vmlinux.lds
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 1574941ebfe..c49b5d4d7fc 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -100,23 +100,11 @@ EXPORT_SYMBOL(__raw_writesl);
#endif
/* string / mem functions */
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(__memzero);
@@ -190,8 +178,6 @@ EXPORT_SYMBOL(_find_next_bit_be);
/* syscalls */
EXPORT_SYMBOL(sys_write);
-EXPORT_SYMBOL(sys_read);
EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_open);
EXPORT_SYMBOL(sys_exit);
EXPORT_SYMBOL(sys_wait4);
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index b324dcac1c5..396efba9bac 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -95,5 +95,13 @@ int main(void)
DEFINE(SYS_ERROR0, 0x9f0000);
BLANK();
DEFINE(SIZEOF_MACHINE_DESC, sizeof(struct machine_desc));
+ DEFINE(MACHINFO_TYPE, offsetof(struct machine_desc, nr));
+ DEFINE(MACHINFO_NAME, offsetof(struct machine_desc, name));
+ DEFINE(MACHINFO_PHYSIO, offsetof(struct machine_desc, phys_io));
+ DEFINE(MACHINFO_PGOFFIO, offsetof(struct machine_desc, io_pg_offst));
+ BLANK();
+ DEFINE(PROC_INFO_SZ, sizeof(struct proc_info_list));
+ DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush));
+ DEFINE(PROCINFO_MMUFLAGS, offsetof(struct proc_info_list, __cpu_mmu_flags));
return 0;
}
diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
index 03532769a97..0a3e9ad297d 100644
--- a/arch/arm/kernel/dma-isa.c
+++ b/arch/arm/kernel/dma-isa.c
@@ -143,12 +143,23 @@ static struct dma_ops isa_dma_ops = {
.residue = isa_get_dma_residue,
};
-static struct resource dma_resources[] = {
- { "dma1", 0x0000, 0x000f },
- { "dma low page", 0x0080, 0x008f },
- { "dma2", 0x00c0, 0x00df },
- { "dma high page", 0x0480, 0x048f }
-};
+static struct resource dma_resources[] = { {
+ .name = "dma1",
+ .start = 0x0000,
+ .end = 0x000f
+}, {
+ .name = "dma low page",
+ .start = 0x0080,
+ .end = 0x008f
+}, {
+ .name = "dma2",
+ .start = 0x00c0,
+ .end = 0x00df
+}, {
+ .name = "dma high page",
+ .start = 0x0480,
+ .end = 0x048f
+} };
void __init isa_init_dma(dma_t *dma)
{
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 355914ffb19..ab8e600c18c 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -666,7 +666,7 @@ __kuser_helper_start:
*
* #define __kernel_dmb() \
* asm volatile ( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #95" \
- * : : : "lr","cc" )
+ * : : : "r0", "lr","cc" )
*/
__kuser_memory_barrier: @ 0xffff0fa0
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
new file mode 100644
index 00000000000..a52da0ddb43
--- /dev/null
+++ b/arch/arm/kernel/head-common.S
@@ -0,0 +1,217 @@
+/*
+ * linux/arch/arm/kernel/head-common.S
+ *
+ * Copyright (C) 1994-2002 Russell King
+ * Copyright (c) 2003 ARM Limited
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+ .type __switch_data, %object
+__switch_data:
+ .long __mmap_switched
+ .long __data_loc @ r4
+ .long __data_start @ r5
+ .long __bss_start @ r6
+ .long _end @ r7
+ .long processor_id @ r4
+ .long __machine_arch_type @ r5
+ .long cr_alignment @ r6
+ .long init_thread_union + THREAD_START_SP @ sp
+
+/*
+ * The following fragment of code is executed with the MMU on in MMU mode,
+ * and uses absolute addresses; this is not position independent.
+ *
+ * r0 = cp#15 control register
+ * r1 = machine ID
+ * r9 = processor ID
+ */
+ .type __mmap_switched, %function
+__mmap_switched:
+ adr r3, __switch_data + 4
+
+ ldmia r3!, {r4, r5, r6, r7}
+ cmp r4, r5 @ Copy data segment if needed
+1: cmpne r5, r6
+ ldrne fp, [r4], #4
+ strne fp, [r5], #4
+ bne 1b
+
+ mov fp, #0 @ Clear BSS (and zero fp)
+1: cmp r6, r7
+ strcc fp, [r6],#4
+ bcc 1b
+
+ ldmia r3, {r4, r5, r6, sp}
+ str r9, [r4] @ Save processor ID
+ str r1, [r5] @ Save machine type
+ bic r4, r0, #CR_A @ Clear 'A' bit
+ stmia r6, {r0, r4} @ Save control register values
+ b start_kernel
+
+/*
+ * Exception handling. Something went wrong and we can't proceed. We
+ * ought to tell the user, but since we don't have any guarantee that
+ * we're even running on the right architecture, we do virtually nothing.
+ *
+ * If CONFIG_DEBUG_LL is set we try to print out something about the error
+ * and hope for the best (useful if bootloader fails to pass a proper
+ * machine ID for example).
+ */
+
+ .type __error_p, %function
+__error_p:
+#ifdef CONFIG_DEBUG_LL
+ adr r0, str_p1
+ bl printascii
+ b __error
+str_p1: .asciz "\nError: unrecognized/unsupported processor variant.\n"
+ .align
+#endif
+
+ .type __error_a, %function
+__error_a:
+#ifdef CONFIG_DEBUG_LL
+ mov r4, r1 @ preserve machine ID
+ adr r0, str_a1
+ bl printascii
+ mov r0, r4
+ bl printhex8
+ adr r0, str_a2
+ bl printascii
+ adr r3, 3f
+ ldmia r3, {r4, r5, r6} @ get machine desc list
+ sub r4, r3, r4 @ get offset between virt&phys
+ add r5, r5, r4 @ convert virt addresses to
+ add r6, r6, r4 @ physical address space
+1: ldr r0, [r5, #MACHINFO_TYPE] @ get machine type
+ bl printhex8
+ mov r0, #'\t'
+ bl printch
+ ldr r0, [r5, #MACHINFO_NAME] @ get machine name
+ add r0, r0, r4
+ bl printascii
+ mov r0, #'\n'
+ bl printch
+ add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
+ cmp r5, r6
+ blo 1b
+ adr r0, str_a3
+ bl printascii
+ b __error
+str_a1: .asciz "\nError: unrecognized/unsupported machine ID (r1 = 0x"
+str_a2: .asciz ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n"
+str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n"
+ .align
+#endif
+
+ .type __error, %function
+__error:
+#ifdef CONFIG_ARCH_RPC
+/*
+ * Turn the screen red on a error - RiscPC only.
+ */
+ mov r0, #0x02000000
+ mov r3, #0x11
+ orr r3, r3, r3, lsl #8
+ orr r3, r3, r3, lsl #16
+ str r3, [r0], #4
+ str r3, [r0], #4
+ str r3, [r0], #4
+ str r3, [r0], #4
+#endif
+1: mov r0, r0
+ b 1b
+
+
+/*
+ * Read processor ID register (CP#15, CR0), and look up in the linker-built
+ * supported processor list. Note that we can't use the absolute addresses
+ * for the __proc_info lists since we aren't running with the MMU on
+ * (and therefore, we are not in the correct address space). We have to
+ * calculate the offset.
+ *
+ * r9 = cpuid
+ * Returns:
+ * r3, r4, r6 corrupted
+ * r5 = proc_info pointer in physical address space
+ * r9 = cpuid (preserved)
+ */
+ .type __lookup_processor_type, %function
+__lookup_processor_type:
+ adr r3, 3f
+ ldmda r3, {r5 - r7}
+ sub r3, r3, r7 @ get offset between virt&phys
+ add r5, r5, r3 @ convert virt addresses to
+ add r6, r6, r3 @ physical address space
+1: ldmia r5, {r3, r4} @ value, mask
+ and r4, r4, r9 @ mask wanted bits
+ teq r3, r4
+ beq 2f
+ add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
+ cmp r5, r6
+ blo 1b
+ mov r5, #0 @ unknown processor
+2: mov pc, lr
+
+/*
+ * This provides a C-API version of the above function.
+ */
+ENTRY(lookup_processor_type)
+ stmfd sp!, {r4 - r7, r9, lr}
+ mov r9, r0
+ bl __lookup_processor_type
+ mov r0, r5
+ ldmfd sp!, {r4 - r7, r9, pc}
+
+/*
+ * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for
+ * more information about the __proc_info and __arch_info structures.
+ */
+ .long __proc_info_begin
+ .long __proc_info_end
+3: .long .
+ .long __arch_info_begin
+ .long __arch_info_end
+
+/*
+ * Lookup machine architecture in the linker-build list of architectures.
+ * Note that we can't use the absolute addresses for the __arch_info
+ * lists since we aren't running with the MMU on (and therefore, we are
+ * not in the correct address space). We have to calculate the offset.
+ *
+ * r1 = machine architecture number
+ * Returns:
+ * r3, r4, r6 corrupted
+ * r5 = mach_info pointer in physical address space
+ */
+ .type __lookup_machine_type, %function
+__lookup_machine_type:
+ adr r3, 3b
+ ldmia r3, {r4, r5, r6}
+ sub r3, r3, r4 @ get offset between virt&phys
+ add r5, r5, r3 @ convert virt addresses to
+ add r6, r6, r3 @ physical address space
+1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type
+ teq r3, r1 @ matches loader number?
+ beq 2f @ found
+ add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
+ cmp r5, r6
+ blo 1b
+ mov r5, #0 @ unknown machine
+2: mov pc, lr
+
+/*
+ * This provides a C-API version of the above function.
+ */
+ENTRY(lookup_machine_type)
+ stmfd sp!, {r4 - r6, lr}
+ mov r1, r0
+ bl __lookup_machine_type
+ mov r0, r5
+ ldmfd sp!, {r4 - r6, pc}
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
new file mode 100644
index 00000000000..adf62e5eaad
--- /dev/null
+++ b/arch/arm/kernel/head-nommu.S
@@ -0,0 +1,83 @@
+/*
+ * linux/arch/arm/kernel/head-nommu.S
+ *
+ * Copyright (C) 1994-2002 Russell King
+ * Copyright (C) 2003-2006 Hyok S. Choi
+ *
+ * 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.
+ *
+ * Common kernel startup code (non-paged MM)
+ * for 32-bit CPUs which has a process ID register(CP15).
+ *
+ */
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/assembler.h>
+#include <asm/mach-types.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/system.h>
+
+/*
+ * Kernel startup entry point.
+ * ---------------------------
+ *
+ * This is normally called from the decompressor code. The requirements
+ * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
+ * r1 = machine nr.
+ *
+ * See linux/arch/arm/tools/mach-types for the complete list of machine
+ * numbers for r1.
+ *
+ */
+ __INIT
+ .type stext, %function
+ENTRY(stext)
+ msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode
+ @ and irqs disabled
+ mrc p15, 0, r9, c0, c0 @ get processor id
+ bl __lookup_processor_type @ r5=procinfo r9=cpuid
+ movs r10, r5 @ invalid processor (r5=0)?
+ beq __error_p @ yes, error 'p'
+ bl __lookup_machine_type @ r5=machinfo
+ movs r8, r5 @ invalid machine (r5=0)?
+ beq __error_a @ yes, error 'a'
+
+ ldr r13, __switch_data @ address to jump to after
+ @ the initialization is done
+ adr lr, __after_proc_init @ return (PIC) address
+ add pc, r10, #PROCINFO_INITFUNC
+
+/*
+ * Set the Control Register and Read the process ID.
+ */
+ .type __after_proc_init, %function
+__after_proc_init:
+ mrc p15, 0, r0, c1, c0, 0 @ read control reg
+#ifdef CONFIG_ALIGNMENT_TRAP
+ orr r0, r0, #CR_A
+#else
+ bic r0, r0, #CR_A
+#endif
+#ifdef CONFIG_CPU_DCACHE_DISABLE
+ bic r0, r0, #CR_C
+#endif
+#ifdef CONFIG_CPU_BPREDICT_DISABLE
+ bic r0, r0, #CR_Z
+#endif
+#ifdef CONFIG_CPU_ICACHE_DISABLE
+ bic r0, r0, #CR_I
+#endif
+ mcr p15, 0, r0, c1, c0, 0 @ write control reg
+
+ mov pc, r13 @ clear the BSS and jump
+ @ to start_kernel
+ .ltorg
+
+#include "head-common.S"
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 53b6901f70a..04f7344e356 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -24,14 +24,6 @@
#include <asm/thread_info.h>
#include <asm/system.h>
-#define PROCINFO_MMUFLAGS 8
-#define PROCINFO_INITFUNC 12
-
-#define MACHINFO_TYPE 0
-#define MACHINFO_PHYSIO 4
-#define MACHINFO_PGOFFIO 8
-#define MACHINFO_NAME 12
-
#define KERNEL_RAM_ADDR (PAGE_OFFSET + TEXT_OFFSET)
/*
@@ -102,49 +94,6 @@ ENTRY(stext)
adr lr, __enable_mmu @ return (PIC) address
add pc, r10, #PROCINFO_INITFUNC
- .type __switch_data, %object
-__switch_data:
- .long __mmap_switched
- .long __data_loc @ r4
- .long __data_start @ r5
- .long __bss_start @ r6
- .long _end @ r7
- .long processor_id @ r4
- .long __machine_arch_type @ r5
- .long cr_alignment @ r6
- .long init_thread_union + THREAD_START_SP @ sp
-
-/*
- * The following fragment of code is executed with the MMU on, and uses
- * absolute addresses; this is not position independent.
- *
- * r0 = cp#15 control register
- * r1 = machine ID
- * r9 = processor ID
- */
- .type __mmap_switched, %function
-__mmap_switched:
- adr r3, __switch_data + 4
-
- ldmia r3!, {r4, r5, r6, r7}
- cmp r4, r5 @ Copy data segment if needed
-1: cmpne r5, r6
- ldrne fp, [r4], #4
- strne fp, [r5], #4
- bne 1b
-
- mov fp, #0 @ Clear BSS (and zero fp)
-1: cmp r6, r7
- strcc fp, [r6],#4
- bcc 1b
-
- ldmia r3, {r4, r5, r6, sp}
- str r9, [r4] @ Save processor ID
- str r1, [r5] @ Save machine type
- bic r4, r0, #CR_A @ Clear 'A' bit
- stmia r6, {r0, r4} @ Save control register values
- b start_kernel
-
#if defined(CONFIG_SMP)
.type secondary_startup, #function
ENTRY(secondary_startup)
@@ -367,166 +316,4 @@ __create_page_tables:
mov pc, lr
.ltorg
-
-
-/*
- * Exception handling. Something went wrong and we can't proceed. We
- * ought to tell the user, but since we don't have any guarantee that
- * we're even running on the right architecture, we do virtually nothing.
- *
- * If CONFIG_DEBUG_LL is set we try to print out something about the error
- * and hope for the best (useful if bootloader fails to pass a proper
- * machine ID for example).
- */
-
- .type __error_p, %function
-__error_p:
-#ifdef CONFIG_DEBUG_LL
- adr r0, str_p1
- bl printascii
- b __error
-str_p1: .asciz "\nError: unrecognized/unsupported processor variant.\n"
- .align
-#endif
-
- .type __error_a, %function
-__error_a:
-#ifdef CONFIG_DEBUG_LL
- mov r4, r1 @ preserve machine ID
- adr r0, str_a1
- bl printascii
- mov r0, r4
- bl printhex8
- adr r0, str_a2
- bl printascii
- adr r3, 3f
- ldmia r3, {r4, r5, r6} @ get machine desc list
- sub r4, r3, r4 @ get offset between virt&phys
- add r5, r5, r4 @ convert virt addresses to
- add r6, r6, r4 @ physical address space
-1: ldr r0, [r5, #MACHINFO_TYPE] @ get machine type
- bl printhex8
- mov r0, #'\t'
- bl printch
- ldr r0, [r5, #MACHINFO_NAME] @ get machine name
- add r0, r0, r4
- bl printascii
- mov r0, #'\n'
- bl printch
- add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
- cmp r5, r6
- blo 1b
- adr r0, str_a3
- bl printascii
- b __error
-str_a1: .asciz "\nError: unrecognized/unsupported machine ID (r1 = 0x"
-str_a2: .asciz ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n"
-str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n"
- .align
-#endif
-
- .type __error, %function
-__error:
-#ifdef CONFIG_ARCH_RPC
-/*
- * Turn the screen red on a error - RiscPC only.
- */
- mov r0, #0x02000000
- mov r3, #0x11
- orr r3, r3, r3, lsl #8
- orr r3, r3, r3, lsl #16
- str r3, [r0], #4
- str r3, [r0], #4
- str r3, [r0], #4
- str r3, [r0], #4
-#endif
-1: mov r0, r0
- b 1b
-
-
-/*
- * Read processor ID register (CP#15, CR0), and look up in the linker-built
- * supported processor list. Note that we can't use the absolute addresses
- * for the __proc_info lists since we aren't running with the MMU on
- * (and therefore, we are not in the correct address space). We have to
- * calculate the offset.
- *
- * r9 = cpuid
- * Returns:
- * r3, r4, r6 corrupted
- * r5 = proc_info pointer in physical address space
- * r9 = cpuid (preserved)
- */
- .type __lookup_processor_type, %function
-__lookup_processor_type:
- adr r3, 3f
- ldmda r3, {r5 - r7}
- sub r3, r3, r7 @ get offset between virt&phys
- add r5, r5, r3 @ convert virt addresses to
- add r6, r6, r3 @ physical address space
-1: ldmia r5, {r3, r4} @ value, mask
- and r4, r4, r9 @ mask wanted bits
- teq r3, r4
- beq 2f
- add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
- cmp r5, r6
- blo 1b
- mov r5, #0 @ unknown processor
-2: mov pc, lr
-
-/*
- * This provides a C-API version of the above function.
- */
-ENTRY(lookup_processor_type)
- stmfd sp!, {r4 - r7, r9, lr}
- mov r9, r0
- bl __lookup_processor_type
- mov r0, r5
- ldmfd sp!, {r4 - r7, r9, pc}
-
-/*
- * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for
- * more information about the __proc_info and __arch_info structures.
- */
- .long __proc_info_begin
- .long __proc_info_end
-3: .long .
- .long __arch_info_begin
- .long __arch_info_end
-
-/*
- * Lookup machine architecture in the linker-build list of architectures.
- * Note that we can't use the absolute addresses for the __arch_info
- * lists since we aren't running with the MMU on (and therefore, we are
- * not in the correct address space). We have to calculate the offset.
- *
- * r1 = machine architecture number
- * Returns:
- * r3, r4, r6 corrupted
- * r5 = mach_info pointer in physical address space
- */
- .type __lookup_machine_type, %function
-__lookup_machine_type:
- adr r3, 3b
- ldmia r3, {r4, r5, r6}
- sub r3, r3, r4 @ get offset between virt&phys
- add r5, r5, r3 @ convert virt addresses to
- add r6, r6, r3 @ physical address space
-1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type
- teq r3, r1 @ matches loader number?
- beq 2f @ found
- add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
- cmp r5, r6
- blo 1b
- mov r5, #0 @ unknown machine
-2: mov pc, lr
-
-/*
- * This provides a C-API version of the above function.
- */
-ENTRY(lookup_machine_type)
- stmfd sp!, {r4 - r6, lr}
- mov r1, r0
- bl __lookup_machine_type
- mov r0, r5
- ldmfd sp!, {r4 - r6, pc}
+#include "head-common.S"
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 489c069e5c3..7df6e1aaa32 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -264,8 +264,12 @@ void show_fpregs(struct user_fp *regs)
/*
* Task structure and kernel stack allocation.
*/
-static unsigned long *thread_info_head;
-static unsigned int nr_thread_info;
+struct thread_info_list {
+ unsigned long *head;
+ unsigned int nr;
+};
+
+static DEFINE_PER_CPU(struct thread_info_list, thread_info_list) = { NULL, 0 };
#define EXTRA_TASK_STRUCT 4
@@ -274,12 +278,15 @@ struct thread_info *alloc_thread_info(struct task_struct *task)
struct thread_info *thread = NULL;
if (EXTRA_TASK_STRUCT) {
- unsigned long *p = thread_info_head;
+ struct thread_info_list *th = &get_cpu_var(thread_info_list);
+ unsigned long *p = th->head;
if (p) {
- thread_info_head = (unsigned long *)p[0];
- nr_thread_info -= 1;
+ th->head = (unsigned long *)p[0];
+ th->nr -= 1;
}
+ put_cpu_var(thread_info_list);
+
thread = (struct thread_info *)p;
}
@@ -300,13 +307,19 @@ struct thread_info *alloc_thread_info(struct task_struct *task)
void free_thread_info(struct thread_info *thread)
{
- if (EXTRA_TASK_STRUCT && nr_thread_info < EXTRA_TASK_STRUCT) {
- unsigned long *p = (unsigned long *)thread;
- p[0] = (unsigned long)thread_info_head;
- thread_info_head = p;
- nr_thread_info += 1;
- } else
- free_pages((unsigned long)thread, THREAD_SIZE_ORDER);
+ if (EXTRA_TASK_STRUCT) {
+ struct thread_info_list *th = &get_cpu_var(thread_info_list);
+ if (th->nr < EXTRA_TASK_STRUCT) {
+ unsigned long *p = (unsigned long *)thread;
+ p[0] = (unsigned long)th->head;
+ th->head = p;
+ th->nr += 1;
+ put_cpu_var(thread_info_list);
+ return;
+ }
+ put_cpu_var(thread_info_list);
+ }
+ free_pages((unsigned long)thread, THREAD_SIZE_ORDER);
}
/*
@@ -474,4 +487,3 @@ unsigned long get_wchan(struct task_struct *p)
} while (count ++ < 16);
return 0;
}
-EXPORT_SYMBOL(get_wchan);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b7cd280bfd6..9fc9af88c60 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -252,6 +252,9 @@ static void __init dump_cpu_info(int cpu)
dump_cache("cache", cpu, CACHE_ISIZE(info));
}
}
+
+ if (arch_is_coherent())
+ printk("Cache coherency enabled\n");
}
int cpu_architecture(void)
@@ -319,6 +322,12 @@ static void __init setup_processor(void)
sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
elf_hwcap = list->elf_hwcap;
+#ifndef CONFIG_ARM_THUMB
+ elf_hwcap &= ~HWCAP_THUMB;
+#endif
+#ifndef CONFIG_VFP
+ elf_hwcap &= ~HWCAP_VFP;
+#endif
cpu_proc_init();
}
@@ -398,7 +407,7 @@ static void __init early_initrd(char **p)
}
__early_param("initrd=", early_initrd);
-static void __init add_memory(unsigned long start, unsigned long size)
+static void __init arm_add_memory(unsigned long start, unsigned long size)
{
/*
* Ensure that start/size are aligned to a page boundary.
@@ -436,7 +445,7 @@ static void __init early_mem(char **p)
if (**p == '@')
start = memparse(*p + 1, p);
- add_memory(start, size);
+ arm_add_memory(start, size);
}
__early_param("mem=", early_mem);
@@ -578,7 +587,7 @@ static int __init parse_tag_mem32(const struct tag *tag)
tag->u.mem.start, tag->u.mem.size / 1024);
return -EINVAL;
}
- add_memory(tag->u.mem.start, tag->u.mem.size);
+ arm_add_memory(tag->u.mem.start, tag->u.mem.size);
return 0;
}
@@ -798,7 +807,7 @@ static int __init topology_init(void)
{
int cpu;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu, NULL);
return 0;
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
index 9991049c522..27beece1550 100644
--- a/arch/arm/kernel/signal.h
+++ b/arch/arm/kernel/signal.h
@@ -7,6 +7,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#define KERN_SIGRETURN_CODE 0xffff0500
+#define KERN_SIGRETURN_CODE (CONFIG_VECTORS_BASE + 0x00000500)
extern const unsigned long sigreturn_codes[7];
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index d566d5f4574..35230a06010 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -688,6 +688,7 @@ EXPORT_SYMBOL(abort);
void __init trap_init(void)
{
+ unsigned long vectors = CONFIG_VECTORS_BASE;
extern char __stubs_start[], __stubs_end[];
extern char __vectors_start[], __vectors_end[];
extern char __kuser_helper_start[], __kuser_helper_end[];
@@ -698,9 +699,9 @@ void __init trap_init(void)
* into the vector page, mapped at 0xffff0000, and ensure these
* are visible to the instruction stream.
*/
- memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start);
- memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start);
- memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz);
+ memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
+ memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
+ memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
/*
* Copy signal return handlers into the vector page, and
@@ -709,6 +710,6 @@ void __init trap_init(void)
memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
sizeof(sigreturn_codes));
- flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE);
+ flush_icache_range(vectors, vectors + PAGE_SIZE);
modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
}
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 391f3ab3ff3..7b726b627ea 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -18,7 +18,7 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
# the code in uaccess.S is not preemption safe and
# probably faster on ARMv3 only
-ifeq ($CONFIG_PREEMPT,y)
+ifeq ($(CONFIG_PREEMPT),y)
lib-y += copy_from_user.o copy_to_user.o
else
ifneq ($(CONFIG_CPU_32v3),y)
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index 3bdc8c6949c..16153c86c3f 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -122,7 +122,7 @@ ENTRY(c_backtrace)
#define reg r5
#define stack r6
-.Ldumpstm: stmfd sp!, {instr, reg, stack, r7, lr}
+.Ldumpstm: stmfd sp!, {instr, reg, stack, r7, r8, lr}
mov stack, r0
mov instr, r1
mov reg, #9
@@ -145,7 +145,7 @@ ENTRY(c_backtrace)
adrne r0, .Lcr
blne printk
mov r0, stack
- LOADREGS(fd, sp!, {instr, reg, stack, r7, pc})
+ LOADREGS(fd, sp!, {instr, reg, stack, r7, r8, pc})
.Lfp: .asciz " r%d = %08X%c"
.Lcr: .asciz "\n"
diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S
index 838e435e492..cab355c0c1f 100644
--- a/arch/arm/lib/copy_template.S
+++ b/arch/arm/lib/copy_template.S
@@ -236,7 +236,7 @@
/*
- * Abort preanble and completion macros.
+ * Abort preamble and completion macros.
* If a fixup handler is required then those macros must surround it.
* It is assumed that the fixup code will handle the private part of
* the exit macro.
diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S
index ec9a1cd6176..58eef660762 100644
--- a/arch/arm/lib/div64.S
+++ b/arch/arm/lib/div64.S
@@ -189,12 +189,12 @@ ENTRY(__do_div64)
moveq pc, lr
@ Division by 0:
- str lr, [sp, #-4]!
+ str lr, [sp, #-8]!
bl __div0
@ as wrong as it could be...
mov yl, #0
mov yh, #0
mov xh, #0
- ldr pc, [sp], #4
+ ldr pc, [sp], #8
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
index dc5fa8e5ebe..83f57da3184 100644
--- a/arch/arm/mach-aaec2000/aaed2000.c
+++ b/arch/arm/mach-aaec2000/aaed2000.c
@@ -79,7 +79,12 @@ static void __init aaed2000_init(void)
}
static struct map_desc aaed2000_io_desc[] __initdata = {
- { EXT_GPIO_VBASE, EXT_GPIO_PBASE, EXT_GPIO_LENGTH, MT_DEVICE }, /* Ext GPIO */
+ {
+ .virtual = EXT_GPIO_VBASE,
+ .pfn = __phys_to_pfn(EXT_GPIO_PBASE),
+ .length = EXT_GPIO_LENGTH,
+ .type = MT_DEVICE
+ },
};
static void __init aaed2000_map_io(void)
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c
index dce4815cf53..65be5efd633 100644
--- a/arch/arm/mach-aaec2000/core.c
+++ b/arch/arm/mach-aaec2000/core.c
@@ -20,7 +20,6 @@
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/signal.h>
-#include <linux/amba/bus.h>
#include <asm/hardware.h>
#include <asm/irq.h>
@@ -50,12 +49,12 @@
static struct map_desc standard_io_desc[] __initdata = {
{
.virtual = VIO_APB_BASE,
- .physical = __phys_to_pfn(PIO_APB_BASE),
+ .pfn = __phys_to_pfn(PIO_APB_BASE),
.length = IO_APB_LENGTH,
.type = MT_DEVICE
}, {
.virtual = VIO_AHB_BASE,
- .physical = __phys_to_pfn(PIO_AHB_BASE),
+ .pfn = __phys_to_pfn(PIO_AHB_BASE),
.length = IO_AHB_LENGTH,
.type = MT_DEVICE
}
diff --git a/arch/arm/mach-aaec2000/core.h b/arch/arm/mach-aaec2000/core.h
index b6029a95f19..59501b57316 100644
--- a/arch/arm/mach-aaec2000/core.h
+++ b/arch/arm/mach-aaec2000/core.h
@@ -9,6 +9,7 @@
*
*/
+#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
struct sys_timer;
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile
index 75e6ee318de..ef88c4128ed 100644
--- a/arch/arm/mach-at91rm9200/Makefile
+++ b/arch/arm/mach-at91rm9200/Makefile
@@ -16,11 +16,12 @@ obj-$(CONFIG_MACH_CSB637) += board-csb637.o
#obj-$(CONFIG_MACH_KB9200) += board-kb9202.o
# LEDs support
-#led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o
-#led-$(CONFIG_MACH_AT91RM9200EK) += leds.o
-#led-$(CONFIG_MACH_CSB337) += leds.o
-#led-$(CONFIG_MACH_CSB637) += leds.o
+led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o
+led-$(CONFIG_MACH_AT91RM9200EK) += leds.o
+led-$(CONFIG_MACH_CSB337) += leds.o
+led-$(CONFIG_MACH_CSB637) += leds.o
#led-$(CONFIG_MACH_KB9200) += leds.o
+#led-$(CONFIG_MACH_KAFA) += leds.o
obj-$(CONFIG_LEDS) += $(led-y)
# VGA support
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c
index 54022e58d50..f45104ceea8 100644
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ b/arch/arm/mach-at91rm9200/board-csb337.c
@@ -67,6 +67,9 @@ static void __init csb337_map_io(void)
/* Initialize clocks: 3.6864 MHz crystal */
at91_clock_init(3686400);
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
#ifdef CONFIG_SERIAL_AT91
at91_console_port = CSB337_SERIAL_CONSOLE;
memcpy(at91_serial_map, serial, sizeof(serial));
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c
index 8195f9d919e..f2c2d6e79bc 100644
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ b/arch/arm/mach-at91rm9200/board-csb637.c
@@ -67,6 +67,9 @@ static void __init csb637_map_io(void)
/* Initialize clocks: 3.6864 MHz crystal */
at91_clock_init(3686400);
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
#ifdef CONFIG_SERIAL_AT91
at91_console_port = CSB637_SERIAL_CONSOLE;
memcpy(at91_serial_map, serial, sizeof(serial));
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c
index 8a783368366..2d7200ed66e 100644
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ b/arch/arm/mach-at91rm9200/board-dk.c
@@ -70,6 +70,9 @@ static void __init dk_map_io(void)
/* Initialize clocks: 18.432 MHz crystal */
at91_clock_init(18432000);
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
#ifdef CONFIG_SERIAL_AT91
at91_console_port = DK_SERIAL_CONSOLE;
memcpy(at91_serial_map, serial, sizeof(serial));
@@ -118,9 +121,14 @@ static void __init dk_board_init(void)
at91_add_device_udc(&dk_udc_data);
/* Compact Flash */
at91_add_device_cf(&dk_cf_data);
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+ /* DataFlash card */
+ at91_set_gpio_output(AT91_PIN_PB7, 0);
+#else
/* MMC */
- at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */
+ at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
at91_add_device_mmc(&dk_mmc_data);
+#endif
/* VGA */
// dk_add_device_video();
}
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c
index fd0752eba89..80d90f5135a 100644
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ b/arch/arm/mach-at91rm9200/board-ek.c
@@ -70,6 +70,9 @@ static void __init ek_map_io(void)
/* Initialize clocks: 18.432 MHz crystal */
at91_clock_init(18432000);
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
+
#ifdef CONFIG_SERIAL_AT91
at91_console_port = EK_SERIAL_CONSOLE;
memcpy(at91_serial_map, serial, sizeof(serial));
@@ -111,9 +114,14 @@ static void __init ek_board_init(void)
at91_add_device_usbh(&ek_usbh_data);
/* USB Device */
at91_add_device_udc(&ek_udc_data);
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+ /* DataFlash card */
+ at91_set_gpio_output(AT91_PIN_PB22, 0);
+#else
/* MMC */
- at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */
+ at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
at91_add_device_mmc(&ek_mmc_data);
+#endif
/* VGA */
// ek_add_device_video();
}
diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c
index 57eedd5beaf..bfe47bd6e50 100644
--- a/arch/arm/mach-at91rm9200/devices.c
+++ b/arch/arm/mach-at91rm9200/devices.c
@@ -28,10 +28,10 @@
static u64 ohci_dmamask = 0xffffffffUL;
static struct at91_usbh_data usbh_data;
-static struct resource at91rm9200_usbh_resource[] = {
+static struct resource at91_usbh_resource[] = {
[0] = {
.start = AT91_UHP_BASE,
- .end = AT91_UHP_BASE + SZ_1M -1,
+ .end = AT91_UHP_BASE + SZ_1M - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -49,8 +49,8 @@ static struct platform_device at91rm9200_usbh_device = {
.coherent_dma_mask = 0xffffffff,
.platform_data = &usbh_data,
},
- .resource = at91rm9200_usbh_resource,
- .num_resources = ARRAY_SIZE(at91rm9200_usbh_resource),
+ .resource = at91_usbh_resource,
+ .num_resources = ARRAY_SIZE(at91_usbh_resource),
};
void __init at91_add_device_usbh(struct at91_usbh_data *data)
@@ -121,6 +121,19 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
static u64 eth_dmamask = 0xffffffffUL;
static struct at91_eth_data eth_data;
+static struct resource at91_eth_resources[] = {
+ [0] = {
+ .start = AT91_BASE_EMAC,
+ .end = AT91_BASE_EMAC + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91_ID_EMAC,
+ .end = AT91_ID_EMAC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
static struct platform_device at91rm9200_eth_device = {
.name = "at91_ether",
.id = -1,
@@ -129,7 +142,8 @@ static struct platform_device at91rm9200_eth_device = {
.coherent_dma_mask = 0xffffffff,
.platform_data = &eth_data,
},
- .num_resources = 0,
+ .resource = at91_eth_resources,
+ .num_resources = ARRAY_SIZE(at91_eth_resources),
};
void __init at91_add_device_eth(struct at91_eth_data *data)
@@ -180,13 +194,23 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {}
#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
static struct at91_cf_data cf_data;
+static struct resource at91_cf_resources[] = {
+ [0] = {
+ .start = AT91_CF_BASE,
+ /* ties up CS4, CS5, and CS6 */
+ .end = AT91_CF_BASE + (0x30000000 - 1),
+ .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+ },
+};
+
static struct platform_device at91rm9200_cf_device = {
.name = "at91_cf",
.id = -1,
.dev = {
.platform_data = &cf_data,
},
- .num_resources = 0,
+ .resource = at91_cf_resources,
+ .num_resources = ARRAY_SIZE(at91_cf_resources),
};
void __init at91_add_device_cf(struct at91_cf_data *data)
@@ -224,15 +248,20 @@ static u64 mmc_dmamask = 0xffffffffUL;
static struct at91_mmc_data mmc_data;
static struct resource at91_mmc_resources[] = {
- {
+ [0] = {
.start = AT91_BASE_MCI,
.end = AT91_BASE_MCI + SZ_16K - 1,
.flags = IORESOURCE_MEM,
- }
+ },
+ [1] = {
+ .start = AT91_ID_MCI,
+ .end = AT91_ID_MCI,
+ .flags = IORESOURCE_IRQ,
+ },
};
static struct platform_device at91rm9200_mmc_device = {
- .name = "at91rm9200_mci",
+ .name = "at91_mci",
.id = -1,
.dev = {
.dma_mask = &mmc_dmamask,
@@ -290,4 +319,123 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
#endif
+/* --------------------------------------------------------------------
+ * NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+static struct resource at91_nand_resources[] = {
+ {
+ .start = AT91_SMARTMEDIA_BASE,
+ .end = AT91_SMARTMEDIA_BASE + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device at91_nand_device = {
+ .name = "at91_nand",
+ .id = -1,
+ .dev = {
+ .platform_data = &nand_data,
+ },
+ .resource = at91_nand_resources,
+ .num_resources = ARRAY_SIZE(at91_nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+ if (!data)
+ return;
+
+ /* enable pin */
+ if (data->enable_pin)
+ at91_set_gpio_output(data->enable_pin, 1);
+
+ /* ready/busy pin */
+ if (data->rdy_pin)
+ at91_set_gpio_input(data->rdy_pin, 1);
+
+ /* card detect pin */
+ if (data->det_pin)
+ at91_set_gpio_input(data->det_pin, 1);
+
+ at91_set_A_periph(AT91_PIN_PC1, 0); /* SMOE */
+ at91_set_A_periph(AT91_PIN_PC3, 0); /* SMWE */
+
+ nand_data = *data;
+ platform_device_register(&at91_nand_device);
+}
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+static struct platform_device at91rm9200_twi_device = {
+ .name = "at91_i2c",
+ .id = -1,
+ .num_resources = 0,
+};
+
+void __init at91_add_device_i2c(void)
+{
+ /* pins used for TWI interface */
+ at91_set_A_periph(AT91_PIN_PA25, 0); /* TWD */
+ at91_set_multi_drive(AT91_PIN_PA25, 1);
+
+ at91_set_A_periph(AT91_PIN_PA26, 0); /* TWCK */
+ at91_set_multi_drive(AT91_PIN_PA26, 1);
+
+ platform_device_register(&at91rm9200_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * RTC
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_RTC) || defined(CONFIG_AT91_RTC_MODULE)
+static struct platform_device at91rm9200_rtc_device = {
+ .name = "at91_rtc",
+ .id = -1,
+ .num_resources = 0,
+};
+
+void __init at91_add_device_rtc(void)
+{
+ platform_device_register(&at91rm9200_rtc_device);
+}
+#else
+void __init at91_add_device_rtc(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+ at91_leds_cpu = cpu_led;
+ at91_leds_timer = timer_led;
+}
+
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
/* -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91rm9200/leds.c b/arch/arm/mach-at91rm9200/leds.c
new file mode 100644
index 00000000000..28150e8905b
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/leds.c
@@ -0,0 +1,100 @@
+/*
+ * LED driver for Atmel AT91-based boards.
+ *
+ * Copyright (C) SAN People (Pty) Ltd
+ *
+ * This program is free software; 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/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/mach-types.h>
+#include <asm/leds.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+
+static inline void at91_led_on(unsigned int led)
+{
+ at91_set_gpio_value(led, 0);
+}
+
+static inline void at91_led_off(unsigned int led)
+{
+ at91_set_gpio_value(led, 1);
+}
+
+static inline void at91_led_toggle(unsigned int led)
+{
+ unsigned long is_off = at91_get_gpio_value(led);
+ if (is_off)
+ at91_led_on(led);
+ else
+ at91_led_off(led);
+}
+
+
+/*
+ * Handle LED events.
+ */
+static void at91_leds_event(led_event_t evt)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ switch(evt) {
+ case led_start: /* System startup */
+ at91_led_on(at91_leds_cpu);
+ break;
+
+ case led_stop: /* System stop / suspend */
+ at91_led_off(at91_leds_cpu);
+ break;
+
+#ifdef CONFIG_LEDS_TIMER
+ case led_timer: /* Every 50 timer ticks */
+ at91_led_toggle(at91_leds_timer);
+ break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+ case led_idle_start: /* Entering idle state */
+ at91_led_off(at91_leds_cpu);
+ break;
+
+ case led_idle_end: /* Exit idle state */
+ at91_led_on(at91_leds_cpu);
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ local_irq_restore(flags);
+}
+
+
+static int __init leds_init(void)
+{
+ if (!at91_leds_timer || !at91_leds_cpu)
+ return -ENODEV;
+
+ /* Enable PIO to access the LEDs */
+ at91_set_gpio_output(at91_leds_timer, 1);
+ at91_set_gpio_output(at91_leds_cpu, 1);
+
+ leds_event = at91_leds_event;
+
+ leds_event(led_start);
+ return 0;
+}
+
+__initcall(leds_init);
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 865427bfad7..dcd41762538 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -30,7 +30,9 @@
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/delay.h>
+#include <linux/termios.h>
#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -360,6 +362,76 @@ void __init ep93xx_init_irq(void)
/*************************************************************************
* EP93xx peripheral handling
*************************************************************************/
+#define EP93XX_UART_MCR_OFFSET (0x0100)
+
+static void ep93xx_uart_set_mctrl(struct amba_device *dev,
+ void __iomem *base, unsigned int mctrl)
+{
+ unsigned int mcr;
+
+ mcr = 0;
+ if (!(mctrl & TIOCM_RTS))
+ mcr |= 2;
+ if (!(mctrl & TIOCM_DTR))
+ mcr |= 1;
+
+ __raw_writel(mcr, base + EP93XX_UART_MCR_OFFSET);
+}
+
+static struct amba_pl010_data ep93xx_uart_data = {
+ .set_mctrl = ep93xx_uart_set_mctrl,
+};
+
+static struct amba_device uart1_device = {
+ .dev = {
+ .bus_id = "apb:uart1",
+ .platform_data = &ep93xx_uart_data,
+ },
+ .res = {
+ .start = EP93XX_UART1_PHYS_BASE,
+ .end = EP93XX_UART1_PHYS_BASE + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_EP93XX_UART1, NO_IRQ },
+ .periphid = 0x00041010,
+};
+
+static struct amba_device uart2_device = {
+ .dev = {
+ .bus_id = "apb:uart2",
+ .platform_data = &ep93xx_uart_data,
+ },
+ .res = {
+ .start = EP93XX_UART2_PHYS_BASE,
+ .end = EP93XX_UART2_PHYS_BASE + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_EP93XX_UART2, NO_IRQ },
+ .periphid = 0x00041010,
+};
+
+static struct amba_device uart3_device = {
+ .dev = {
+ .bus_id = "apb:uart3",
+ .platform_data = &ep93xx_uart_data,
+ },
+ .res = {
+ .start = EP93XX_UART3_PHYS_BASE,
+ .end = EP93XX_UART3_PHYS_BASE + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_EP93XX_UART3, NO_IRQ },
+ .periphid = 0x00041010,
+};
+
+
+static struct platform_device ep93xx_rtc_device = {
+ .name = "ep93xx-rtc",
+ .id = -1,
+ .num_resources = 0,
+};
+
+
void __init ep93xx_init_devices(void)
{
unsigned int v;
@@ -371,4 +443,10 @@ void __init ep93xx_init_devices(void)
v &= ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE;
__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
__raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG);
+
+ amba_device_register(&uart1_device, &iomem_resource);
+ amba_device_register(&uart2_device, &iomem_resource);
+ amba_device_register(&uart3_device, &iomem_resource);
+
+ platform_device_register(&ep93xx_rtc_device);
}
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 777e75daa8a..e24566b88a7 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -17,6 +17,8 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/m48t86.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -39,6 +41,16 @@ static struct map_desc ts72xx_io_desc[] __initdata = {
.pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
.length = TS72XX_OPTIONS2_SIZE,
.type = MT_DEVICE,
+ }, {
+ .virtual = TS72XX_RTC_INDEX_VIRT_BASE,
+ .pfn = __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE),
+ .length = TS72XX_RTC_INDEX_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = TS72XX_RTC_DATA_VIRT_BASE,
+ .pfn = __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
+ .length = TS72XX_RTC_DATA_SIZE,
+ .type = MT_DEVICE,
}
};
@@ -99,11 +111,38 @@ static void __init ts72xx_map_io(void)
}
}
+static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
+{
+ __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+ return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE);
+}
+
+static void ts72xx_rtc_writebyte(unsigned char value, unsigned long addr)
+{
+ __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+ __raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE);
+}
+
+static struct m48t86_ops ts72xx_rtc_ops = {
+ .readbyte = ts72xx_rtc_readbyte,
+ .writebyte = ts72xx_rtc_writebyte,
+};
+
+static struct platform_device ts72xx_rtc_device = {
+ .name = "rtc-m48t86",
+ .id = -1,
+ .dev = {
+ .platform_data = &ts72xx_rtc_ops,
+ },
+ .num_resources = 0,
+};
+
static void __init ts72xx_init_machine(void)
{
ep93xx_init_devices();
if (board_is_ts7200())
physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL);
+ platform_device_register(&ts72xx_rtc_device);
}
MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
diff --git a/arch/arm/mach-footbridge/time.c b/arch/arm/mach-footbridge/time.c
index 2c64a0b0502..5d02e95dede 100644
--- a/arch/arm/mach-footbridge/time.c
+++ b/arch/arm/mach-footbridge/time.c
@@ -34,27 +34,12 @@ static int rtc_base;
static unsigned long __init get_isa_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- int i;
// check to see if the RTC makes sense.....
if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
return mktime(1970, 1, 1, 0, 0, 0);
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
-
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
-
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
+ do {
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
hour = CMOS_READ(RTC_HOURS);
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
index 71a59e19616..4ca51dcf13a 100644
--- a/arch/arm/mach-imx/dma.c
+++ b/arch/arm/mach-imx/dma.c
@@ -7,11 +7,18 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * 03/03/2004 Sascha Hauer <sascha@saschahauer.de>
+ * 2004-03-03 Sascha Hauer <sascha@saschahauer.de>
* initial version heavily inspired by
* linux/arch/arm/mach-pxa/dma.c
+ *
+ * 2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ * Changed to support scatter gather DMA
+ * by taking Russell's code from RiscPC
+ *
*/
+#undef DEBUG
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -22,69 +29,368 @@
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/dma.h>
+#include <asm/arch/imx-dma.h>
+
+struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
+
+/*
+ * imx_dma_sg_next - prepare next chunk for scatter-gather DMA emulation
+ * @dma_ch: i.MX DMA channel number
+ * @lastcount: number of bytes transferred during last transfer
+ *
+ * Functions prepares DMA controller for next sg data chunk transfer.
+ * The @lastcount argument informs function about number of bytes transferred
+ * during last block. Zero value can be used for @lastcount to setup DMA
+ * for the first chunk.
+ */
+static inline int imx_dma_sg_next(imx_dmach_t dma_ch, unsigned int lastcount)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+ unsigned int nextcount;
+ unsigned int nextaddr;
+
+ if (!imxdma->name) {
+ printk(KERN_CRIT "%s: called for not allocated channel %d\n",
+ __FUNCTION__, dma_ch);
+ return 0;
+ }
+
+ imxdma->resbytes -= lastcount;
+
+ if (!imxdma->sg) {
+ pr_debug("imxdma%d: no sg data\n", dma_ch);
+ return 0;
+ }
+
+ imxdma->sgbc += lastcount;
+ if ((imxdma->sgbc >= imxdma->sg->length) || !imxdma->resbytes) {
+ if ((imxdma->sgcount <= 1) || !imxdma->resbytes) {
+ pr_debug("imxdma%d: sg transfer limit reached\n",
+ dma_ch);
+ imxdma->sgcount=0;
+ imxdma->sg = NULL;
+ return 0;
+ } else {
+ imxdma->sgcount--;
+ imxdma->sg++;
+ imxdma->sgbc = 0;
+ }
+ }
+ nextcount = imxdma->sg->length - imxdma->sgbc;
+ nextaddr = imxdma->sg->dma_address + imxdma->sgbc;
-static struct dma_channel {
- char *name;
- void (*irq_handler) (int, void *, struct pt_regs *);
- void (*err_handler) (int, void *, struct pt_regs *);
- void *data;
-} dma_channels[11];
+ if(imxdma->resbytes < nextcount)
+ nextcount = imxdma->resbytes;
-/* set err_handler to NULL to have the standard info-only error handler */
+ if ((imxdma->dma_mode & DMA_MODE_MASK) == DMA_MODE_READ)
+ DAR(dma_ch) = nextaddr;
+ else
+ SAR(dma_ch) = nextaddr;
+
+ CNTR(dma_ch) = nextcount;
+ pr_debug("imxdma%d: next sg chunk dst 0x%08x, src 0x%08x, size 0x%08x\n",
+ dma_ch, DAR(dma_ch), SAR(dma_ch), CNTR(dma_ch));
+
+ return nextcount;
+}
+
+/*
+ * imx_dma_setup_sg_base - scatter-gather DMA emulation
+ * @dma_ch: i.MX DMA channel number
+ * @sg: pointer to the scatter-gather list/vector
+ * @sgcount: scatter-gather list hungs count
+ *
+ * Functions sets up i.MX DMA state for emulated scatter-gather transfer
+ * and sets up channel registers to be ready for the first chunk
+ */
+static int
+imx_dma_setup_sg_base(imx_dmach_t dma_ch,
+ struct scatterlist *sg, unsigned int sgcount)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+ imxdma->sg = sg;
+ imxdma->sgcount = sgcount;
+ imxdma->sgbc = 0;
+ return imx_dma_sg_next(dma_ch, 0);
+}
+
+/**
+ * imx_dma_setup_single - setup i.MX DMA channel for linear memory to/from device transfer
+ * @dma_ch: i.MX DMA channel number
+ * @dma_address: the DMA/physical memory address of the linear data block
+ * to transfer
+ * @dma_length: length of the data block in bytes
+ * @dev_addr: physical device port address
+ * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
+ * or %DMA_MODE_WRITE from memory to the device
+ *
+ * The function setups DMA channel source and destination addresses for transfer
+ * specified by provided parameters. The scatter-gather emulation is disabled,
+ * because linear data block
+ * form the physical address range is transfered.
+ * Return value: if incorrect parameters are provided -%EINVAL.
+ * Zero indicates success.
+ */
int
-imx_request_dma(char *name, imx_dma_prio prio,
- void (*irq_handler) (int, void *, struct pt_regs *),
- void (*err_handler) (int, void *, struct pt_regs *), void *data)
+imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address,
+ unsigned int dma_length, unsigned int dev_addr,
+ dmamode_t dmamode)
{
- unsigned long flags;
- int i, found = 0;
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
- /* basic sanity checks */
- if (!name || !irq_handler)
+ imxdma->sg = NULL;
+ imxdma->sgcount = 0;
+ imxdma->dma_mode = dmamode;
+ imxdma->resbytes = dma_length;
+
+ if (!dma_address) {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_single null address\n",
+ dma_ch);
return -EINVAL;
+ }
- local_irq_save(flags);
+ if (!dma_length) {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_single zero length\n",
+ dma_ch);
+ return -EINVAL;
+ }
- /* try grabbing a DMA channel with the requested priority */
- for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) {
- if (!dma_channels[i].name) {
- found = 1;
- break;
- }
+ if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
+ pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for read\n",
+ dma_ch, (unsigned int)dma_address, dma_length,
+ dev_addr);
+ SAR(dma_ch) = dev_addr;
+ DAR(dma_ch) = (unsigned int)dma_address;
+ } else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
+ pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for write\n",
+ dma_ch, (unsigned int)dma_address, dma_length,
+ dev_addr);
+ SAR(dma_ch) = (unsigned int)dma_address;
+ DAR(dma_ch) = dev_addr;
+ } else {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_single bad dmamode\n",
+ dma_ch);
+ return -EINVAL;
}
- if (!found) {
- /* requested prio group is full, try hier priorities */
- for (i = prio - 1; i >= 0; i--) {
- if (!dma_channels[i].name) {
- found = 1;
- break;
- }
- }
+ CNTR(dma_ch) = dma_length;
+
+ return 0;
+}
+
+/**
+ * imx_dma_setup_sg - setup i.MX DMA channel SG list to/from device transfer
+ * @dma_ch: i.MX DMA channel number
+ * @sg: pointer to the scatter-gather list/vector
+ * @sgcount: scatter-gather list hungs count
+ * @dma_length: total length of the transfer request in bytes
+ * @dev_addr: physical device port address
+ * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
+ * or %DMA_MODE_WRITE from memory to the device
+ *
+ * The function setups DMA channel state and registers to be ready for transfer
+ * specified by provided parameters. The scatter-gather emulation is set up
+ * according to the parameters.
+ *
+ * The full preparation of the transfer requires setup of more register
+ * by the caller before imx_dma_enable() can be called.
+ *
+ * %BLR(dma_ch) holds transfer burst length in bytes, 0 means 64 bytes
+ *
+ * %RSSR(dma_ch) has to be set to the DMA request line source %DMA_REQ_xxx
+ *
+ * %CCR(dma_ch) has to specify transfer parameters, the next settings is typical
+ * for linear or simple scatter-gather transfers if %DMA_MODE_READ is specified
+ *
+ * %CCR_DMOD_LINEAR | %CCR_DSIZ_32 | %CCR_SMOD_FIFO | %CCR_SSIZ_x
+ *
+ * The typical setup for %DMA_MODE_WRITE is specified by next options combination
+ *
+ * %CCR_SMOD_LINEAR | %CCR_SSIZ_32 | %CCR_DMOD_FIFO | %CCR_DSIZ_x
+ *
+ * Be carefull there and do not mistakenly mix source and target device
+ * port sizes constants, they are really different:
+ * %CCR_SSIZ_8, %CCR_SSIZ_16, %CCR_SSIZ_32,
+ * %CCR_DSIZ_8, %CCR_DSIZ_16, %CCR_DSIZ_32
+ *
+ * Return value: if incorrect parameters are provided -%EINVAL.
+ * Zero indicates success.
+ */
+int
+imx_dma_setup_sg(imx_dmach_t dma_ch,
+ struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length,
+ unsigned int dev_addr, dmamode_t dmamode)
+{
+ int res;
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+ imxdma->sg = NULL;
+ imxdma->sgcount = 0;
+ imxdma->dma_mode = dmamode;
+ imxdma->resbytes = dma_length;
+
+ if (!sg || !sgcount) {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_sg epty sg list\n",
+ dma_ch);
+ return -EINVAL;
+ }
+
+ if (!sg->length) {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_sg zero length\n",
+ dma_ch);
+ return -EINVAL;
}
- if (found) {
- DIMR &= ~(1 << i);
- dma_channels[i].name = name;
- dma_channels[i].irq_handler = irq_handler;
- dma_channels[i].err_handler = err_handler;
- dma_channels[i].data = data;
+ if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
+ pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for read\n",
+ dma_ch, sg, sgcount, dma_length, dev_addr);
+ SAR(dma_ch) = dev_addr;
+ } else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
+ pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for write\n",
+ dma_ch, sg, sgcount, dma_length, dev_addr);
+ DAR(dma_ch) = dev_addr;
} else {
- printk(KERN_WARNING "No more available DMA channels for %s\n",
- name);
- i = -ENODEV;
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_sg bad dmamode\n",
+ dma_ch);
+ return -EINVAL;
+ }
+
+ res = imx_dma_setup_sg_base(dma_ch, sg, sgcount);
+ if (res <= 0) {
+ printk(KERN_ERR "imxdma%d: no sg chunk ready\n", dma_ch);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * imx_dma_setup_handlers - setup i.MX DMA channel end and error notification handlers
+ * @dma_ch: i.MX DMA channel number
+ * @irq_handler: the pointer to the function called if the transfer
+ * ends successfully
+ * @err_handler: the pointer to the function called if the premature
+ * end caused by error occurs
+ * @data: user specified value to be passed to the handlers
+ */
+int
+imx_dma_setup_handlers(imx_dmach_t dma_ch,
+ void (*irq_handler) (int, void *, struct pt_regs *),
+ void (*err_handler) (int, void *, struct pt_regs *),
+ void *data)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+ unsigned long flags;
+
+ if (!imxdma->name) {
+ printk(KERN_CRIT "%s: called for not allocated channel %d\n",
+ __FUNCTION__, dma_ch);
+ return -ENODEV;
+ }
+
+ local_irq_save(flags);
+ DISR = (1 << dma_ch);
+ imxdma->irq_handler = irq_handler;
+ imxdma->err_handler = err_handler;
+ imxdma->data = data;
+ local_irq_restore(flags);
+ return 0;
+}
+
+/**
+ * imx_dma_enable - function to start i.MX DMA channel operation
+ * @dma_ch: i.MX DMA channel number
+ *
+ * The channel has to be allocated by driver through imx_dma_request()
+ * or imx_dma_request_by_prio() function.
+ * The transfer parameters has to be set to the channel registers through
+ * call of the imx_dma_setup_single() or imx_dma_setup_sg() function
+ * and registers %BLR(dma_ch), %RSSR(dma_ch) and %CCR(dma_ch) has to
+ * be set prior this function call by the channel user.
+ */
+void imx_dma_enable(imx_dmach_t dma_ch)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+ unsigned long flags;
+
+ pr_debug("imxdma%d: imx_dma_enable\n", dma_ch);
+
+ if (!imxdma->name) {
+ printk(KERN_CRIT "%s: called for not allocated channel %d\n",
+ __FUNCTION__, dma_ch);
+ return;
+ }
+
+ local_irq_save(flags);
+ DISR = (1 << dma_ch);
+ DIMR &= ~(1 << dma_ch);
+ CCR(dma_ch) |= CCR_CEN;
+ local_irq_restore(flags);
+}
+
+/**
+ * imx_dma_disable - stop, finish i.MX DMA channel operatin
+ * @dma_ch: i.MX DMA channel number
+ */
+void imx_dma_disable(imx_dmach_t dma_ch)
+{
+ unsigned long flags;
+
+ pr_debug("imxdma%d: imx_dma_disable\n", dma_ch);
+
+ local_irq_save(flags);
+ DIMR |= (1 << dma_ch);
+ CCR(dma_ch) &= ~CCR_CEN;
+ DISR = (1 << dma_ch);
+ local_irq_restore(flags);
+}
+
+/**
+ * imx_dma_request - request/allocate specified channel number
+ * @dma_ch: i.MX DMA channel number
+ * @name: the driver/caller own non-%NULL identification
+ */
+int imx_dma_request(imx_dmach_t dma_ch, const char *name)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+ unsigned long flags;
+
+ /* basic sanity checks */
+ if (!name)
+ return -EINVAL;
+
+ if (dma_ch >= IMX_DMA_CHANNELS) {
+ printk(KERN_CRIT "%s: called for non-existed channel %d\n",
+ __FUNCTION__, dma_ch);
+ return -EINVAL;
}
+ local_irq_save(flags);
+ if (imxdma->name) {
+ local_irq_restore(flags);
+ return -ENODEV;
+ }
+
+ imxdma->name = name;
+ imxdma->irq_handler = NULL;
+ imxdma->err_handler = NULL;
+ imxdma->data = NULL;
+ imxdma->sg = NULL;
local_irq_restore(flags);
- return i;
+ return 0;
}
-void
-imx_free_dma(int dma_ch)
+/**
+ * imx_dma_free - release previously acquired channel
+ * @dma_ch: i.MX DMA channel number
+ */
+void imx_dma_free(imx_dmach_t dma_ch)
{
unsigned long flags;
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
- if (!dma_channels[dma_ch].name) {
+ if (!imxdma->name) {
printk(KERN_CRIT
"%s: trying to free channel %d which is already freed\n",
__FUNCTION__, dma_ch);
@@ -92,27 +398,84 @@ imx_free_dma(int dma_ch)
}
local_irq_save(flags);
- DIMR &= ~(1 << dma_ch);
- dma_channels[dma_ch].name = NULL;
+ /* Disable interrupts */
+ DIMR |= (1 << dma_ch);
+ CCR(dma_ch) &= ~CCR_CEN;
+ imxdma->name = NULL;
local_irq_restore(flags);
}
-static irqreturn_t
-dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
+/**
+ * imx_dma_request_by_prio - find and request some of free channels best suiting requested priority
+ * @dma_ch: i.MX DMA channel number
+ * @name: the driver/caller own non-%NULL identification
+ * @prio: one of the hardware distinguished priority level:
+ * %DMA_PRIO_HIGH, %DMA_PRIO_MEDIUM, %DMA_PRIO_LOW
+ *
+ * This function tries to find free channel in the specified priority group
+ * if the priority cannot be achieved it tries to look for free channel
+ * in the higher and then even lower priority groups.
+ *
+ * Return value: If there is no free channel to allocate, -%ENODEV is returned.
+ * Zero value indicates successful channel allocation.
+ */
+int
+imx_dma_request_by_prio(imx_dmach_t * pdma_ch, const char *name,
+ imx_dma_prio prio)
+{
+ int i;
+ int best;
+
+ switch (prio) {
+ case (DMA_PRIO_HIGH):
+ best = 8;
+ break;
+ case (DMA_PRIO_MEDIUM):
+ best = 4;
+ break;
+ case (DMA_PRIO_LOW):
+ default:
+ best = 0;
+ break;
+ }
+
+ for (i = best; i < IMX_DMA_CHANNELS; i++) {
+ if (!imx_dma_request(i, name)) {
+ *pdma_ch = i;
+ return 0;
+ }
+ }
+
+ for (i = best - 1; i >= 0; i--) {
+ if (!imx_dma_request(i, name)) {
+ *pdma_ch = i;
+ return 0;
+ }
+ }
+
+ printk(KERN_ERR "%s: no free DMA channel found\n", __FUNCTION__);
+
+ return -ENODEV;
+}
+
+static irqreturn_t dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i, disr = DISR;
- struct dma_channel *channel;
+ struct imx_dma_channel *channel;
unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
DISR = disr;
- for (i = 0; i < 11; i++) {
- channel = &dma_channels[i];
+ for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+ channel = &imx_dma_channels[i];
- if ( (err_mask & 1<<i) && channel->name && channel->err_handler) {
+ if ((err_mask & 1 << i) && channel->name
+ && channel->err_handler) {
channel->err_handler(i, channel->data, regs);
continue;
}
+ imx_dma_channels[i].sg = NULL;
+
if (DBTOSR & (1 << i)) {
printk(KERN_WARNING
"Burst timeout on channel %d (%s)\n",
@@ -141,17 +504,27 @@ dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-static irqreturn_t
-dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i, disr = DISR;
+ pr_debug("imxdma: dma_irq_handler called, disr=0x%08x\n",
+ disr);
+
DISR = disr;
- for (i = 0; i < 11; i++) {
+ for (i = 0; i < IMX_DMA_CHANNELS; i++) {
if (disr & (1 << i)) {
- struct dma_channel *channel = &dma_channels[i];
- if (channel->name && channel->irq_handler) {
- channel->irq_handler(i, channel->data, regs);
+ struct imx_dma_channel *channel = &imx_dma_channels[i];
+ if (channel->name) {
+ if (imx_dma_sg_next(i, CNTR(i))) {
+ CCR(i) &= ~CCR_CEN;
+ mb();
+ CCR(i) |= CCR_CEN;
+ } else {
+ if (channel->irq_handler)
+ channel->irq_handler(i,
+ channel->data, regs);
+ }
} else {
/*
* IRQ for an unregistered DMA channel:
@@ -165,10 +538,10 @@ dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-static int __init
-imx_dma_init(void)
+static int __init imx_dma_init(void)
{
int ret;
+ int i;
/* reset DMA module */
DCR = DCR_DRST;
@@ -189,15 +562,27 @@ imx_dma_init(void)
DCR = DCR_DEN;
/* clear all interrupts */
- DISR = 0x3ff;
+ DISR = (1 << IMX_DMA_CHANNELS) - 1;
/* enable interrupts */
- DIMR = 0;
+ DIMR = (1 << IMX_DMA_CHANNELS) - 1;
+
+ for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+ imx_dma_channels[i].sg = NULL;
+ imx_dma_channels[i].dma_num = i;
+ }
return ret;
}
arch_initcall(imx_dma_init);
-EXPORT_SYMBOL(imx_request_dma);
-EXPORT_SYMBOL(imx_free_dma);
+EXPORT_SYMBOL(imx_dma_setup_single);
+EXPORT_SYMBOL(imx_dma_setup_sg);
+EXPORT_SYMBOL(imx_dma_setup_handlers);
+EXPORT_SYMBOL(imx_dma_enable);
+EXPORT_SYMBOL(imx_dma_disable);
+EXPORT_SYMBOL(imx_dma_request);
+EXPORT_SYMBOL(imx_dma_free);
+EXPORT_SYMBOL(imx_dma_request_by_prio);
+EXPORT_SYMBOL(imx_dma_channels);
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 37613ad6836..12ea58a3b84 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -33,6 +33,7 @@
#include <asm/arch/imx-regs.h>
#include <asm/mach/map.h>
+#include <asm/arch/mmc.h>
void imx_gpio_mode(int gpio_mode)
{
@@ -175,62 +176,24 @@ static struct resource imx_mmc_resources[] = {
},
};
+static u64 imxmmmc_dmamask = 0xffffffffUL;
+
static struct platform_device imx_mmc_device = {
.name = "imx-mmc",
.id = 0,
+ .dev = {
+ .dma_mask = &imxmmmc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
.num_resources = ARRAY_SIZE(imx_mmc_resources),
.resource = imx_mmc_resources,
};
-static struct resource imx_uart1_resources[] = {
- [0] = {
- .start = 0x00206000,
- .end = 0x002060FF,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = (UART1_MINT_RX),
- .end = (UART1_MINT_RX),
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = (UART1_MINT_TX),
- .end = (UART1_MINT_TX),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device imx_uart1_device = {
- .name = "imx-uart",
- .id = 0,
- .num_resources = ARRAY_SIZE(imx_uart1_resources),
- .resource = imx_uart1_resources,
-};
-
-static struct resource imx_uart2_resources[] = {
- [0] = {
- .start = 0x00207000,
- .end = 0x002070FF,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = (UART2_MINT_RX),
- .end = (UART2_MINT_RX),
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = (UART2_MINT_TX),
- .end = (UART2_MINT_TX),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device imx_uart2_device = {
- .name = "imx-uart",
- .id = 1,
- .num_resources = ARRAY_SIZE(imx_uart2_resources),
- .resource = imx_uart2_resources,
-};
+void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
+{
+ imx_mmc_device.dev.platform_data = info;
+}
+EXPORT_SYMBOL(imx_set_mmc_info);
static struct imxfb_mach_info imx_fb_info;
@@ -270,8 +233,6 @@ static struct platform_device imxfb_device = {
static struct platform_device *devices[] __initdata = {
&imx_mmc_device,
&imxfb_device,
- &imx_uart1_device,
- &imx_uart2_device,
};
static struct map_desc imx_io_desc[] __initdata = {
diff --git a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c
index eeb8a6d4a39..a5de5f1da9f 100644
--- a/arch/arm/mach-imx/irq.c
+++ b/arch/arm/mach-imx/irq.c
@@ -127,7 +127,7 @@ static void
imx_gpio_ack_irq(unsigned int irq)
{
DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
- ISR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32);
+ ISR(IRQ_TO_REG(irq)) = 1 << ((irq - IRQ_GPIOA(0)) % 32);
}
static void
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
index 8ab1b040288..da893c80d47 100644
--- a/arch/arm/mach-imx/mx1ads.c
+++ b/arch/arm/mach-imx/mx1ads.c
@@ -25,6 +25,8 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/imx-uart.h>
#include <linux/interrupt.h>
#include "generic.h"
@@ -47,9 +49,83 @@ static struct platform_device cs89x0_device = {
.resource = cs89x0_resources,
};
+static struct imxuart_platform_data uart_pdata = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct resource imx_uart1_resources[] = {
+ [0] = {
+ .start = 0x00206000,
+ .end = 0x002060FF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = (UART1_MINT_RX),
+ .end = (UART1_MINT_RX),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = (UART1_MINT_TX),
+ .end = (UART1_MINT_TX),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device imx_uart1_device = {
+ .name = "imx-uart",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(imx_uart1_resources),
+ .resource = imx_uart1_resources,
+ .dev = {
+ .platform_data = &uart_pdata,
+ }
+};
+
+static struct resource imx_uart2_resources[] = {
+ [0] = {
+ .start = 0x00207000,
+ .end = 0x002070FF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = (UART2_MINT_RX),
+ .end = (UART2_MINT_RX),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = (UART2_MINT_TX),
+ .end = (UART2_MINT_TX),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device imx_uart2_device = {
+ .name = "imx-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(imx_uart2_resources),
+ .resource = imx_uart2_resources,
+ .dev = {
+ .platform_data = &uart_pdata,
+ }
+};
+
static struct platform_device *devices[] __initdata = {
&cs89x0_device,
+ &imx_uart1_device,
+ &imx_uart2_device,
+};
+
+#ifdef CONFIG_MMC_IMX
+static int mx1ads_mmc_card_present(void)
+{
+ /* MMC/SD Card Detect is PB 20 on MX1ADS V1.0.7 */
+ return (SSR(1) & (1 << 20) ? 0 : 1);
+}
+
+static struct imxmmc_platform_data mx1ads_mmc_info = {
+ .card_present = mx1ads_mmc_card_present,
};
+#endif
static void __init
mx1ads_init(void)
@@ -57,6 +133,22 @@ mx1ads_init(void)
#ifdef CONFIG_LEDS
imx_gpio_mode(GPIO_PORTA | GPIO_OUT | 2);
#endif
+#ifdef CONFIG_MMC_IMX
+ /* SD/MMC card detect */
+ imx_gpio_mode(GPIO_PORTB | GPIO_GIUS | GPIO_IN | 20);
+ imx_set_mmc_info(&mx1ads_mmc_info);
+#endif
+
+ imx_gpio_mode(PC9_PF_UART1_CTS);
+ imx_gpio_mode(PC10_PF_UART1_RTS);
+ imx_gpio_mode(PC11_PF_UART1_TXD);
+ imx_gpio_mode(PC12_PF_UART1_RXD);
+
+ imx_gpio_mode(PB28_PF_UART2_CTS);
+ imx_gpio_mode(PB29_PF_UART2_RTS);
+ imx_gpio_mode(PB30_PF_UART2_TXD);
+ imx_gpio_mode(PB31_PF_UART2_RXD);
+
platform_add_devices(devices, ARRAY_SIZE(devices));
}
@@ -69,7 +161,7 @@ mx1ads_map_io(void)
MACHINE_START(MX1ADS, "Motorola MX1ADS")
/* Maintainer: Sascha Hauer, Pengutronix */
.phys_io = 0x00200000,
- .io_pg_offst = ((0xe0200000) >> 18) & 0xfffc,
+ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
.boot_params = 0x08000100,
.map_io = mx1ads_map_io,
.init_irq = imx_init_irq,
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index 20071a2767c..576a5e979c0 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -15,7 +15,9 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/smp.h>
+#include <linux/termios.h>
#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
#include <asm/hardware.h>
#include <asm/irq.h>
@@ -28,6 +30,8 @@
#include "common.h"
+static struct amba_pl010_data integrator_uart_data;
+
static struct amba_device rtc_device = {
.dev = {
.bus_id = "mb:15",
@@ -44,6 +48,7 @@ static struct amba_device rtc_device = {
static struct amba_device uart0_device = {
.dev = {
.bus_id = "mb:16",
+ .platform_data = &integrator_uart_data,
},
.res = {
.start = INTEGRATOR_UART0_BASE,
@@ -57,6 +62,7 @@ static struct amba_device uart0_device = {
static struct amba_device uart1_device = {
.dev = {
.bus_id = "mb:17",
+ .platform_data = &integrator_uart_data,
},
.res = {
.start = INTEGRATOR_UART1_BASE,
@@ -115,6 +121,46 @@ static int __init integrator_init(void)
arch_initcall(integrator_init);
+/*
+ * On the Integrator platform, the port RTS and DTR are provided by
+ * bits in the following SC_CTRLS register bits:
+ * RTS DTR
+ * UART0 7 6
+ * UART1 5 4
+ */
+#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
+#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
+
+static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl)
+{
+ unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
+
+ if (dev == &uart0_device) {
+ rts_mask = 1 << 4;
+ dtr_mask = 1 << 5;
+ } else {
+ rts_mask = 1 << 6;
+ dtr_mask = 1 << 7;
+ }
+
+ if (mctrl & TIOCM_RTS)
+ ctrlc |= rts_mask;
+ else
+ ctrls |= rts_mask;
+
+ if (mctrl & TIOCM_DTR)
+ ctrlc |= dtr_mask;
+ else
+ ctrls |= dtr_mask;
+
+ __raw_writel(ctrls, SC_CTRLS);
+ __raw_writel(ctrlc, SC_CTRLC);
+}
+
+static struct amba_pl010_data integrator_uart_data = {
+ .set_mctrl = integrator_uart_set_mctrl,
+};
+
#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_CTRL_OFFSET
static DEFINE_SPINLOCK(cm_lock);
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index a0724f2b24c..9f55f5ae104 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -232,8 +232,6 @@ static void __init intcp_init_irq(void)
for (i = IRQ_PIC_START; i <= IRQ_PIC_END; i++) {
if (i == 11)
i = 22;
- if (i == IRQ_CP_CPPLDINT)
- i++;
if (i == 29)
break;
set_irq_chip(i, &pic_chip);
@@ -259,8 +257,7 @@ static void __init intcp_init_irq(void)
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
- set_irq_handler(IRQ_CP_CPPLDINT, sic_handle_irq);
- pic_unmask_irq(IRQ_CP_CPPLDINT);
+ set_irq_chained_handler(IRQ_CP_CPPLDINT, sic_handle_irq);
}
/*
diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c
index 3c22c16b38b..bc07f52a6fd 100644
--- a/arch/arm/mach-integrator/time.c
+++ b/arch/arm/mach-integrator/time.c
@@ -40,13 +40,13 @@ static int integrator_set_rtc(void)
return 1;
}
-static int rtc_read_alarm(struct rtc_wkalrm *alrm)
+static int integrator_rtc_read_alarm(struct rtc_wkalrm *alrm)
{
rtc_time_to_tm(readl(rtc_base + RTC_MR), &alrm->time);
return 0;
}
-static inline int rtc_set_alarm(struct rtc_wkalrm *alrm)
+static inline int integrator_rtc_set_alarm(struct rtc_wkalrm *alrm)
{
unsigned long time;
int ret;
@@ -62,7 +62,7 @@ static inline int rtc_set_alarm(struct rtc_wkalrm *alrm)
return ret;
}
-static int rtc_read_time(struct rtc_time *tm)
+static int integrator_rtc_read_time(struct rtc_time *tm)
{
rtc_time_to_tm(readl(rtc_base + RTC_DR), tm);
return 0;
@@ -76,7 +76,7 @@ static int rtc_read_time(struct rtc_time *tm)
* edge of the 1Hz clock, we must write the time one second
* in advance.
*/
-static inline int rtc_set_time(struct rtc_time *tm)
+static inline int integrator_rtc_set_time(struct rtc_time *tm)
{
unsigned long time;
int ret;
@@ -90,10 +90,10 @@ static inline int rtc_set_time(struct rtc_time *tm)
static struct rtc_ops rtc_ops = {
.owner = THIS_MODULE,
- .read_time = rtc_read_time,
- .set_time = rtc_set_time,
- .read_alarm = rtc_read_alarm,
- .set_alarm = rtc_set_alarm,
+ .read_time = integrator_rtc_read_time,
+ .set_time = integrator_rtc_set_time,
+ .read_alarm = integrator_rtc_read_alarm,
+ .set_alarm = integrator_rtc_set_alarm,
};
static irqreturn_t arm_rtc_interrupt(int irq, void *dev_id,
diff --git a/arch/arm/mach-ixp23xx/Kconfig b/arch/arm/mach-ixp23xx/Kconfig
new file mode 100644
index 00000000000..982670ec386
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/Kconfig
@@ -0,0 +1,25 @@
+if ARCH_IXP23XX
+
+config ARCH_SUPPORTS_BIG_ENDIAN
+ bool
+ default y
+
+menu "Intel IXP23xx Implementation Options"
+
+comment "IXP23xx Platforms"
+
+config MACH_ESPRESSO
+ bool "Support IP Fabrics Double Espresso platform"
+ help
+
+config MACH_IXDP2351
+ bool "Support Intel IXDP2351 platform"
+ help
+
+config MACH_ROADRUNNER
+ bool "Support ADI RoadRunner platform"
+ help
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-ixp23xx/Makefile b/arch/arm/mach-ixp23xx/Makefile
new file mode 100644
index 00000000000..288b371b6d0
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the linux kernel.
+#
+obj-y := core.o pci.o
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-$(CONFIG_MACH_ESPRESSO) += espresso.o
+obj-$(CONFIG_MACH_IXDP2351) += ixdp2351.o
+obj-$(CONFIG_MACH_ROADRUNNER) += roadrunner.o
diff --git a/arch/arm/mach-ixp23xx/Makefile.boot b/arch/arm/mach-ixp23xx/Makefile.boot
new file mode 100644
index 00000000000..d5561ad15ba
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/Makefile.boot
@@ -0,0 +1,2 @@
+ zreladdr-y := 0x00008000
+params_phys-y := 0x00000100
diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c
new file mode 100644
index 00000000000..affd1d5d744
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/core.c
@@ -0,0 +1,443 @@
+/*
+ * arch/arm/mach-ixp23xx/core.c
+ *
+ * Core routines for IXP23xx chips
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * Based on 2.4 code Copyright 2004 (c) Intel Corporation
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/bitops.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/arch.h>
+
+
+/*************************************************************************
+ * Chip specific mappings shared by all IXP23xx systems
+ *************************************************************************/
+static struct map_desc ixp23xx_io_desc[] __initdata = {
+ { /* XSI-CPP CSRs */
+ .virtual = IXP23XX_XSI2CPP_CSR_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_XSI2CPP_CSR_PHYS),
+ .length = IXP23XX_XSI2CPP_CSR_SIZE,
+ .type = MT_DEVICE,
+ }, { /* Expansion Bus Config */
+ .virtual = IXP23XX_EXP_CFG_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_EXP_CFG_PHYS),
+ .length = IXP23XX_EXP_CFG_SIZE,
+ .type = MT_DEVICE,
+ }, { /* UART, Interrupt ctrl, GPIO, timers, NPEs, MACS,.... */
+ .virtual = IXP23XX_PERIPHERAL_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_PERIPHERAL_PHYS),
+ .length = IXP23XX_PERIPHERAL_SIZE,
+ .type = MT_DEVICE,
+ }, { /* CAP CSRs */
+ .virtual = IXP23XX_CAP_CSR_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_CAP_CSR_PHYS),
+ .length = IXP23XX_CAP_CSR_SIZE,
+ .type = MT_DEVICE,
+ }, { /* MSF CSRs */
+ .virtual = IXP23XX_MSF_CSR_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_MSF_CSR_PHYS),
+ .length = IXP23XX_MSF_CSR_SIZE,
+ .type = MT_DEVICE,
+ }, { /* PCI I/O Space */
+ .virtual = IXP23XX_PCI_IO_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_PCI_IO_PHYS),
+ .length = IXP23XX_PCI_IO_SIZE,
+ .type = MT_DEVICE,
+ }, { /* PCI Config Space */
+ .virtual = IXP23XX_PCI_CFG_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_PCI_CFG_PHYS),
+ .length = IXP23XX_PCI_CFG_SIZE,
+ .type = MT_DEVICE,
+ }, { /* PCI local CFG CSRs */
+ .virtual = IXP23XX_PCI_CREG_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_PCI_CREG_PHYS),
+ .length = IXP23XX_PCI_CREG_SIZE,
+ .type = MT_DEVICE,
+ }, { /* PCI MEM Space */
+ .virtual = IXP23XX_PCI_MEM_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_PCI_MEM_PHYS),
+ .length = IXP23XX_PCI_MEM_SIZE,
+ .type = MT_DEVICE,
+ }
+};
+
+void __init ixp23xx_map_io(void)
+{
+ iotable_init(ixp23xx_io_desc, ARRAY_SIZE(ixp23xx_io_desc));
+}
+
+
+/***************************************************************************
+ * IXP23xx Interrupt Handling
+ ***************************************************************************/
+enum ixp23xx_irq_type {
+ IXP23XX_IRQ_LEVEL, IXP23XX_IRQ_EDGE
+};
+
+static void ixp23xx_config_irq(unsigned int, enum ixp23xx_irq_type);
+
+static int ixp23xx_irq_set_type(unsigned int irq, unsigned int type)
+{
+ int line = irq - IRQ_IXP23XX_GPIO6 + 6;
+ u32 int_style;
+ enum ixp23xx_irq_type irq_type;
+ volatile u32 *int_reg;
+
+ /*
+ * Only GPIOs 6-15 are wired to interrupts on IXP23xx
+ */
+ if (line < 6 || line > 15)
+ return -EINVAL;
+
+ switch (type) {
+ case IRQT_BOTHEDGE:
+ int_style = IXP23XX_GPIO_STYLE_TRANSITIONAL;
+ irq_type = IXP23XX_IRQ_EDGE;
+ break;
+ case IRQT_RISING:
+ int_style = IXP23XX_GPIO_STYLE_RISING_EDGE;
+ irq_type = IXP23XX_IRQ_EDGE;
+ break;
+ case IRQT_FALLING:
+ int_style = IXP23XX_GPIO_STYLE_FALLING_EDGE;
+ irq_type = IXP23XX_IRQ_EDGE;
+ break;
+ case IRQT_HIGH:
+ int_style = IXP23XX_GPIO_STYLE_ACTIVE_HIGH;
+ irq_type = IXP23XX_IRQ_LEVEL;
+ break;
+ case IRQT_LOW:
+ int_style = IXP23XX_GPIO_STYLE_ACTIVE_LOW;
+ irq_type = IXP23XX_IRQ_LEVEL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ixp23xx_config_irq(irq, irq_type);
+
+ if (line >= 8) { /* pins 8-15 */
+ line -= 8;
+ int_reg = (volatile u32 *)IXP23XX_GPIO_GPIT2R;
+ } else { /* pins 0-7 */
+ int_reg = (volatile u32 *)IXP23XX_GPIO_GPIT1R;
+ }
+
+ /*
+ * Clear pending interrupts
+ */
+ *IXP23XX_GPIO_GPISR = (1 << line);
+
+ /* Clear the style for the appropriate pin */
+ *int_reg &= ~(IXP23XX_GPIO_STYLE_MASK <<
+ (line * IXP23XX_GPIO_STYLE_SIZE));
+
+ /* Set the new style */
+ *int_reg |= (int_style << (line * IXP23XX_GPIO_STYLE_SIZE));
+
+ return 0;
+}
+
+static void ixp23xx_irq_mask(unsigned int irq)
+{
+ volatile unsigned long *intr_reg;
+
+ if (irq >= 56)
+ irq += 8;
+
+ intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
+ *intr_reg &= ~(1 << (irq % 32));
+}
+
+static void ixp23xx_irq_ack(unsigned int irq)
+{
+ int line = irq - IRQ_IXP23XX_GPIO6 + 6;
+
+ if ((line < 6) || (line > 15))
+ return;
+
+ *IXP23XX_GPIO_GPISR = (1 << line);
+}
+
+/*
+ * Level triggered interrupts on GPIO lines can only be cleared when the
+ * interrupt condition disappears.
+ */
+static void ixp23xx_irq_level_unmask(unsigned int irq)
+{
+ volatile unsigned long *intr_reg;
+
+ ixp23xx_irq_ack(irq);
+
+ if (irq >= 56)
+ irq += 8;
+
+ intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
+ *intr_reg |= (1 << (irq % 32));
+}
+
+static void ixp23xx_irq_edge_unmask(unsigned int irq)
+{
+ volatile unsigned long *intr_reg;
+
+ if (irq >= 56)
+ irq += 8;
+
+ intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
+ *intr_reg |= (1 << (irq % 32));
+}
+
+static struct irqchip ixp23xx_irq_level_chip = {
+ .ack = ixp23xx_irq_mask,
+ .mask = ixp23xx_irq_mask,
+ .unmask = ixp23xx_irq_level_unmask,
+ .set_type = ixp23xx_irq_set_type
+};
+
+static struct irqchip ixp23xx_irq_edge_chip = {
+ .ack = ixp23xx_irq_ack,
+ .mask = ixp23xx_irq_mask,
+ .unmask = ixp23xx_irq_edge_unmask,
+ .set_type = ixp23xx_irq_set_type
+};
+
+static void ixp23xx_pci_irq_mask(unsigned int irq)
+{
+ *IXP23XX_PCI_XSCALE_INT_ENABLE &= ~(1 << (IRQ_IXP23XX_INTA + 27 - irq));
+}
+
+static void ixp23xx_pci_irq_unmask(unsigned int irq)
+{
+ *IXP23XX_PCI_XSCALE_INT_ENABLE |= (1 << (IRQ_IXP23XX_INTA + 27 - irq));
+}
+
+/*
+ * TODO: Should this just be done at ASM level?
+ */
+static void pci_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+ u32 pci_interrupt;
+ unsigned int irqno;
+ struct irqdesc *int_desc;
+
+ pci_interrupt = *IXP23XX_PCI_XSCALE_INT_STATUS;
+
+ desc->chip->ack(irq);
+
+ /* See which PCI_INTA, or PCI_INTB interrupted */
+ if (pci_interrupt & (1 << 26)) {
+ irqno = IRQ_IXP23XX_INTB;
+ } else if (pci_interrupt & (1 << 27)) {
+ irqno = IRQ_IXP23XX_INTA;
+ } else {
+ BUG();
+ }
+
+ int_desc = irq_desc + irqno;
+ int_desc->handle(irqno, int_desc, regs);
+
+ desc->chip->unmask(irq);
+}
+
+static struct irqchip ixp23xx_pci_irq_chip = {
+ .ack = ixp23xx_pci_irq_mask,
+ .mask = ixp23xx_pci_irq_mask,
+ .unmask = ixp23xx_pci_irq_unmask
+};
+
+static void ixp23xx_config_irq(unsigned int irq, enum ixp23xx_irq_type type)
+{
+ switch (type) {
+ case IXP23XX_IRQ_LEVEL:
+ set_irq_chip(irq, &ixp23xx_irq_level_chip);
+ set_irq_handler(irq, do_level_IRQ);
+ break;
+ case IXP23XX_IRQ_EDGE:
+ set_irq_chip(irq, &ixp23xx_irq_edge_chip);
+ set_irq_handler(irq, do_edge_IRQ);
+ break;
+ }
+ set_irq_flags(irq, IRQF_VALID);
+}
+
+void __init ixp23xx_init_irq(void)
+{
+ int irq;
+
+ /* Route everything to IRQ */
+ *IXP23XX_INTR_SEL1 = 0x0;
+ *IXP23XX_INTR_SEL2 = 0x0;
+ *IXP23XX_INTR_SEL3 = 0x0;
+ *IXP23XX_INTR_SEL4 = 0x0;
+
+ /* Mask all sources */
+ *IXP23XX_INTR_EN1 = 0x0;
+ *IXP23XX_INTR_EN2 = 0x0;
+ *IXP23XX_INTR_EN3 = 0x0;
+ *IXP23XX_INTR_EN4 = 0x0;
+
+ /*
+ * Configure all IRQs for level-sensitive operation
+ */
+ for (irq = 0; irq <= NUM_IXP23XX_RAW_IRQS; irq++) {
+ ixp23xx_config_irq(irq, IXP23XX_IRQ_LEVEL);
+ }
+
+ for (irq = IRQ_IXP23XX_INTA; irq <= IRQ_IXP23XX_INTB; irq++) {
+ set_irq_chip(irq, &ixp23xx_pci_irq_chip);
+ set_irq_handler(irq, do_level_IRQ);
+ set_irq_flags(irq, IRQF_VALID);
+ }
+
+ set_irq_chained_handler(IRQ_IXP23XX_PCI_INT_RPH, pci_handler);
+}
+
+
+/*************************************************************************
+ * Timer-tick functions for IXP23xx
+ *************************************************************************/
+#define CLOCK_TICKS_PER_USEC CLOCK_TICK_RATE / (USEC_PER_SEC)
+
+static unsigned long next_jiffy_time;
+
+static unsigned long
+ixp23xx_gettimeoffset(void)
+{
+ unsigned long elapsed;
+
+ elapsed = *IXP23XX_TIMER_CONT - (next_jiffy_time - LATCH);
+
+ return elapsed / CLOCK_TICKS_PER_USEC;
+}
+
+static irqreturn_t
+ixp23xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ /* Clear Pending Interrupt by writing '1' to it */
+ *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND;
+ while ((*IXP23XX_TIMER_CONT - next_jiffy_time) > LATCH) {
+ timer_tick(regs);
+ next_jiffy_time += LATCH;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction ixp23xx_timer_irq = {
+ .name = "IXP23xx Timer Tick",
+ .handler = ixp23xx_timer_interrupt,
+ .flags = SA_INTERRUPT | SA_TIMER,
+};
+
+void __init ixp23xx_init_timer(void)
+{
+ /* Clear Pending Interrupt by writing '1' to it */
+ *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND;
+
+ /* Setup the Timer counter value */
+ *IXP23XX_TIMER1_RELOAD =
+ (LATCH & ~IXP23XX_TIMER_RELOAD_MASK) | IXP23XX_TIMER_ENABLE;
+
+ *IXP23XX_TIMER_CONT = 0;
+ next_jiffy_time = LATCH;
+
+ /* Connect the interrupt handler and enable the interrupt */
+ setup_irq(IRQ_IXP23XX_TIMER1, &ixp23xx_timer_irq);
+}
+
+struct sys_timer ixp23xx_timer = {
+ .init = ixp23xx_init_timer,
+ .offset = ixp23xx_gettimeoffset,
+};
+
+
+/*************************************************************************
+ * IXP23xx Platform Initializaion
+ *************************************************************************/
+static struct resource ixp23xx_uart_resources[] = {
+ {
+ .start = IXP23XX_UART1_PHYS,
+ .end = IXP23XX_UART1_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM
+ }, {
+ .start = IXP23XX_UART2_PHYS,
+ .end = IXP23XX_UART2_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM
+ }
+};
+
+static struct plat_serial8250_port ixp23xx_uart_data[] = {
+ {
+ .mapbase = IXP23XX_UART1_PHYS,
+ .membase = (char *)(IXP23XX_UART1_VIRT + 3),
+ .irq = IRQ_IXP23XX_UART1,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP23XX_UART_XTAL,
+ }, {
+ .mapbase = IXP23XX_UART2_PHYS,
+ .membase = (char *)(IXP23XX_UART2_VIRT + 3),
+ .irq = IRQ_IXP23XX_UART2,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP23XX_UART_XTAL,
+ },
+ { },
+};
+
+static struct platform_device ixp23xx_uart = {
+ .name = "serial8250",
+ .id = 0,
+ .dev.platform_data = ixp23xx_uart_data,
+ .num_resources = 2,
+ .resource = ixp23xx_uart_resources,
+};
+
+static struct platform_device *ixp23xx_devices[] __initdata = {
+ &ixp23xx_uart,
+};
+
+void __init ixp23xx_sys_init(void)
+{
+ platform_add_devices(ixp23xx_devices, ARRAY_SIZE(ixp23xx_devices));
+}
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
new file mode 100644
index 00000000000..bf688c12863
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/espresso.c
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-ixp23xx/espresso.c
+ *
+ * Double Espresso-specific routines
+ *
+ * Author: Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/bitops.h>
+#include <linux/ioport.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/pci.h>
+
+static int __init espresso_pci_init(void)
+{
+ if (machine_is_espresso())
+ ixp23xx_pci_slave_init();
+
+ return 0;
+};
+subsys_initcall(espresso_pci_init);
+
+static void __init espresso_init(void)
+{
+ physmap_configure(0x90000000, 0x02000000, 2, NULL);
+
+ /*
+ * Mark flash as writeable.
+ */
+ IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE;
+
+ ixp23xx_sys_init();
+}
+
+MACHINE_START(ESPRESSO, "IP Fabrics Double Espresso")
+ /* Maintainer: Lennert Buytenhek */
+ .phys_io = IXP23XX_PERIPHERAL_PHYS,
+ .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
+ .map_io = ixp23xx_map_io,
+ .init_irq = ixp23xx_init_irq,
+ .timer = &ixp23xx_timer,
+ .boot_params = 0x00000100,
+ .init_machine = espresso_init,
+MACHINE_END
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
new file mode 100644
index 00000000000..00146c35daa
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -0,0 +1,325 @@
+/*
+ * arch/arm/mach-ixp23xx/ixdp2351.c
+ *
+ * IXDP2351 board-specific routines
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * Based on 2.4 code Copyright 2004 (c) Intel Corporation
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/bitops.h>
+#include <linux/ioport.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/pci.h>
+
+/*
+ * IXDP2351 Interrupt Handling
+ */
+static void ixdp2351_inta_mask(unsigned int irq)
+{
+ *IXDP2351_CPLD_INTA_MASK_SET_REG = IXDP2351_INTA_IRQ_MASK(irq);
+}
+
+static void ixdp2351_inta_unmask(unsigned int irq)
+{
+ *IXDP2351_CPLD_INTA_MASK_CLR_REG = IXDP2351_INTA_IRQ_MASK(irq);
+}
+
+static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+ u16 ex_interrupt =
+ *IXDP2351_CPLD_INTA_STAT_REG & IXDP2351_INTA_IRQ_VALID;
+ int i;
+
+ desc->chip->mask(irq);
+
+ for (i = 0; i < IXDP2351_INTA_IRQ_NUM; i++) {
+ if (ex_interrupt & (1 << i)) {
+ struct irqdesc *cpld_desc;
+ int cpld_irq =
+ IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i);
+ cpld_desc = irq_desc + cpld_irq;
+ cpld_desc->handle(cpld_irq, cpld_desc, regs);
+ }
+ }
+
+ desc->chip->unmask(irq);
+}
+
+static struct irqchip ixdp2351_inta_chip = {
+ .ack = ixdp2351_inta_mask,
+ .mask = ixdp2351_inta_mask,
+ .unmask = ixdp2351_inta_unmask
+};
+
+static void ixdp2351_intb_mask(unsigned int irq)
+{
+ *IXDP2351_CPLD_INTB_MASK_SET_REG = IXDP2351_INTB_IRQ_MASK(irq);
+}
+
+static void ixdp2351_intb_unmask(unsigned int irq)
+{
+ *IXDP2351_CPLD_INTB_MASK_CLR_REG = IXDP2351_INTB_IRQ_MASK(irq);
+}
+
+static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+ u16 ex_interrupt =
+ *IXDP2351_CPLD_INTB_STAT_REG & IXDP2351_INTB_IRQ_VALID;
+ int i;
+
+ desc->chip->ack(irq);
+
+ for (i = 0; i < IXDP2351_INTB_IRQ_NUM; i++) {
+ if (ex_interrupt & (1 << i)) {
+ struct irqdesc *cpld_desc;
+ int cpld_irq =
+ IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i);
+ cpld_desc = irq_desc + cpld_irq;
+ cpld_desc->handle(cpld_irq, cpld_desc, regs);
+ }
+ }
+
+ desc->chip->unmask(irq);
+}
+
+static struct irqchip ixdp2351_intb_chip = {
+ .ack = ixdp2351_intb_mask,
+ .mask = ixdp2351_intb_mask,
+ .unmask = ixdp2351_intb_unmask
+};
+
+void ixdp2351_init_irq(void)
+{
+ int irq;
+
+ /* Mask all interrupts from CPLD, disable simulation */
+ *IXDP2351_CPLD_INTA_MASK_SET_REG = (u16) -1;
+ *IXDP2351_CPLD_INTB_MASK_SET_REG = (u16) -1;
+ *IXDP2351_CPLD_INTA_SIM_REG = 0;
+ *IXDP2351_CPLD_INTB_SIM_REG = 0;
+
+ ixp23xx_init_irq();
+
+ for (irq = IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE);
+ irq <
+ IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + IXDP2351_INTA_IRQ_NUM);
+ irq++) {
+ if (IXDP2351_INTA_IRQ_MASK(irq) & IXDP2351_INTA_IRQ_VALID) {
+ set_irq_flags(irq, IRQF_VALID);
+ set_irq_handler(irq, do_level_IRQ);
+ set_irq_chip(irq, &ixdp2351_inta_chip);
+ }
+ }
+
+ for (irq = IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE);
+ irq <
+ IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + IXDP2351_INTB_IRQ_NUM);
+ irq++) {
+ if (IXDP2351_INTB_IRQ_MASK(irq) & IXDP2351_INTB_IRQ_VALID) {
+ set_irq_flags(irq, IRQF_VALID);
+ set_irq_handler(irq, do_level_IRQ);
+ set_irq_chip(irq, &ixdp2351_intb_chip);
+ }
+ }
+
+ set_irq_chained_handler(IRQ_IXP23XX_INTA, &ixdp2351_inta_handler);
+ set_irq_chained_handler(IRQ_IXP23XX_INTB, &ixdp2351_intb_handler);
+}
+
+/*
+ * IXDP2351 PCI
+ */
+
+/*
+ * This board does not do normal PCI IRQ routing, or any
+ * sort of swizzling, so we just need to check where on the
+ * bus the device is and figure out what CPLD pin it is
+ * being routed to.
+ */
+#define DEVPIN(dev, pin) ((pin) | ((dev) << 3))
+
+static int __init ixdp2351_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ u8 bus = dev->bus->number;
+ u32 devpin = DEVPIN(PCI_SLOT(dev->devfn), pin);
+ struct pci_bus *tmp_bus = dev->bus;
+
+ /* Primary bus, no interrupts here */
+ if (!bus)
+ return -1;
+
+ /* Lookup first leaf in bus tree */
+ while ((tmp_bus->parent != NULL) && (tmp_bus->parent->parent != NULL))
+ tmp_bus = tmp_bus->parent;
+
+ /* Select between known bridges */
+ switch (tmp_bus->self->devfn | (tmp_bus->self->bus->number << 8)) {
+ /* Device is located after first bridge */
+ case 0x0008:
+ if (tmp_bus == dev->bus) {
+ /* Device is located directy after first bridge */
+ switch (devpin) {
+ /* Onboard 82546 */
+ case DEVPIN(1, 1): /* Onboard 82546 ch 0 */
+ return IRQ_IXDP2351_INTA_82546;
+ case DEVPIN(1, 2): /* Onboard 82546 ch 1 */
+ return IRQ_IXDP2351_INTB_82546;
+ /* PMC SLOT */
+ case DEVPIN(0, 1): /* PMCP INTA# */
+ case DEVPIN(2, 4): /* PMCS INTD# */
+ return IRQ_IXDP2351_SPCI_PMC_INTA;
+ case DEVPIN(0, 2): /* PMCP INTB# */
+ case DEVPIN(2, 1): /* PMCS INTA# */
+ return IRQ_IXDP2351_SPCI_PMC_INTB;
+ case DEVPIN(0, 3): /* PMCP INTC# */
+ case DEVPIN(2, 2): /* PMCS INTB# */
+ return IRQ_IXDP2351_SPCI_PMC_INTC;
+ case DEVPIN(0, 4): /* PMCP INTD# */
+ case DEVPIN(2, 3): /* PMCS INTC# */
+ return IRQ_IXDP2351_SPCI_PMC_INTD;
+ }
+ } else {
+ /* Device is located indirectly after first bridge */
+ /* Not supported now */
+ return -1;
+ }
+ break;
+ case 0x0010:
+ if (tmp_bus == dev->bus) {
+ /* Device is located directy after second bridge */
+ /* Secondary bus of second bridge */
+ switch (devpin) {
+ case DEVPIN(0, 1): /* DB#0 */
+ case DEVPIN(0, 2):
+ case DEVPIN(0, 3):
+ case DEVPIN(0, 4):
+ return IRQ_IXDP2351_SPCI_DB_0;
+ case DEVPIN(1, 1): /* DB#1 */
+ case DEVPIN(1, 2):
+ case DEVPIN(1, 3):
+ case DEVPIN(1, 4):
+ return IRQ_IXDP2351_SPCI_DB_1;
+ case DEVPIN(2, 1): /* FIC1 */
+ case DEVPIN(2, 2):
+ case DEVPIN(2, 3):
+ case DEVPIN(2, 4):
+ case DEVPIN(3, 1): /* FIC2 */
+ case DEVPIN(3, 2):
+ case DEVPIN(3, 3):
+ case DEVPIN(3, 4):
+ return IRQ_IXDP2351_SPCI_FIC;
+ }
+ } else {
+ /* Device is located indirectly after second bridge */
+ /* Not supported now */
+ return -1;
+ }
+ break;
+ }
+
+ return -1;
+}
+
+struct hw_pci ixdp2351_pci __initdata = {
+ .nr_controllers = 1,
+ .preinit = ixp23xx_pci_preinit,
+ .setup = ixp23xx_pci_setup,
+ .scan = ixp23xx_pci_scan_bus,
+ .map_irq = ixdp2351_map_irq,
+};
+
+int __init ixdp2351_pci_init(void)
+{
+ if (machine_is_ixdp2351())
+ pci_common_init(&ixdp2351_pci);
+
+ return 0;
+}
+
+subsys_initcall(ixdp2351_pci_init);
+
+/*
+ * IXDP2351 Static Mapped I/O
+ */
+static struct map_desc ixdp2351_io_desc[] __initdata = {
+ {
+ .virtual = IXDP2351_NP_VIRT_BASE,
+ .pfn = __phys_to_pfn((u64)IXDP2351_NP_PHYS_BASE),
+ .length = IXDP2351_NP_PHYS_SIZE,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IXDP2351_BB_BASE_VIRT,
+ .pfn = __phys_to_pfn((u64)IXDP2351_BB_BASE_PHYS),
+ .length = IXDP2351_BB_SIZE,
+ .type = MT_DEVICE
+ }
+};
+
+static void __init ixdp2351_map_io(void)
+{
+ ixp23xx_map_io();
+ iotable_init(ixdp2351_io_desc, ARRAY_SIZE(ixdp2351_io_desc));
+}
+
+static void __init ixdp2351_init(void)
+{
+ physmap_configure(0x90000000, 0x04000000, 1, NULL);
+
+ /*
+ * Mark flash as writeable
+ */
+ IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[2] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[3] |= IXP23XX_FLASH_WRITABLE;
+
+ ixp23xx_sys_init();
+}
+
+MACHINE_START(IXDP2351, "Intel IXDP2351 Development Platform")
+ /* Maintainer: MontaVista Software, Inc. */
+ .phys_io = IXP23XX_PERIPHERAL_PHYS,
+ .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
+ .map_io = ixdp2351_map_io,
+ .init_irq = ixdp2351_init_irq,
+ .timer = &ixp23xx_timer,
+ .boot_params = 0x00000100,
+ .init_machine = ixdp2351_init,
+MACHINE_END
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
new file mode 100644
index 00000000000..ac72f94c5b4
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/pci.c
@@ -0,0 +1,291 @@
+/*
+ * arch/arm/mach-ixp23xx/pci.c
+ *
+ * PCI routines for IXP23XX based systems
+ *
+ * Copyright (c) 2005 MontaVista Software, Inc.
+ *
+ * based on original code:
+ *
+ * Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Copyright 2002-2005 Intel 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/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+extern int (*external_fault) (unsigned long, struct pt_regs *);
+
+static int pci_master_aborts = 0;
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+int clear_master_aborts(void);
+
+static u32
+*ixp23xx_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where)
+{
+ u32 *paddress;
+
+ /*
+ * Must be dword aligned
+ */
+ where &= ~3;
+
+ /*
+ * For top bus, generate type 0, else type 1
+ */
+ if (!bus_nr) {
+ if (PCI_SLOT(devfn) >= 8)
+ return 0;
+
+ paddress = (u32 *) (IXP23XX_PCI_CFG0_VIRT
+ | (1 << (PCI_SLOT(devfn) + 16))
+ | (PCI_FUNC(devfn) << 8) | where);
+ } else {
+ paddress = (u32 *) (IXP23XX_PCI_CFG1_VIRT
+ | (bus_nr << 16)
+ | (PCI_SLOT(devfn) << 11)
+ | (PCI_FUNC(devfn) << 8) | where);
+ }
+
+ return paddress;
+}
+
+/*
+ * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes.
+ * 0 and 3 are not valid indexes...
+ */
+static u32 bytemask[] = {
+ /*0*/ 0,
+ /*1*/ 0xff,
+ /*2*/ 0xffff,
+ /*3*/ 0,
+ /*4*/ 0xffffffff,
+};
+
+static int ixp23xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *value)
+{
+ u32 n;
+ u32 *addr;
+
+ n = where % 4;
+
+ DBG("In config_read(%d) %d from dev %d:%d:%d\n", size, where,
+ bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+ addr = ixp23xx_pci_config_addr(bus->number, devfn, where);
+ if (!addr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ pci_master_aborts = 0;
+ *value = (*addr >> (8*n)) & bytemask[size];
+ if (pci_master_aborts) {
+ pci_master_aborts = 0;
+ *value = 0xffffffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * We don't do error checking on the address for writes.
+ * It's assumed that the user checked for the device existing first
+ * by doing a read first.
+ */
+static int ixp23xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 value)
+{
+ u32 mask;
+ u32 *addr;
+ u32 temp;
+
+ mask = ~(bytemask[size] << ((where % 0x4) * 8));
+ addr = ixp23xx_pci_config_addr(bus->number, devfn, where);
+ if (!addr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ temp = (u32) (value) << ((where % 0x4) * 8);
+ *addr = (*addr & mask) | temp;
+
+ clear_master_aborts();
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops ixp23xx_pci_ops = {
+ .read = ixp23xx_pci_read_config,
+ .write = ixp23xx_pci_write_config,
+};
+
+struct pci_bus *ixp23xx_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
+{
+ return pci_scan_bus(sysdata->busnr, &ixp23xx_pci_ops, sysdata);
+}
+
+int ixp23xx_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+ volatile unsigned long temp;
+ unsigned long flags;
+
+ pci_master_aborts = 1;
+
+ local_irq_save(flags);
+ temp = *IXP23XX_PCI_CONTROL;
+
+ /*
+ * master abort and cmd tgt err
+ */
+ if (temp & ((1 << 8) | (1 << 5)))
+ *IXP23XX_PCI_CONTROL = temp;
+
+ temp = *IXP23XX_PCI_CMDSTAT;
+
+ if (temp & (1 << 29))
+ *IXP23XX_PCI_CMDSTAT = temp;
+ local_irq_restore(flags);
+
+ /*
+ * If it was an imprecise abort, then we need to correct the
+ * return address to be _after_ the instruction.
+ */
+ if (fsr & (1 << 10))
+ regs->ARM_pc += 4;
+
+ return 0;
+}
+
+int clear_master_aborts(void)
+{
+ volatile u32 temp;
+
+ temp = *IXP23XX_PCI_CONTROL;
+
+ /*
+ * master abort and cmd tgt err
+ */
+ if (temp & ((1 << 8) | (1 << 5)))
+ *IXP23XX_PCI_CONTROL = temp;
+
+ temp = *IXP23XX_PCI_CMDSTAT;
+
+ if (temp & (1 << 29))
+ *IXP23XX_PCI_CMDSTAT = temp;
+
+ return 0;
+}
+
+static void __init ixp23xx_pci_common_init(void)
+{
+#ifdef __ARMEB__
+ *IXP23XX_PCI_CONTROL |= 0x20000; /* set I/O swapping */
+#endif
+ /*
+ * ADDR_31 needs to be clear for PCI memory access to CPP memory
+ */
+ *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_ADDR_31;
+ *IXP23XX_CPP2XSI_CURR_XFER_REG3 |= IXP23XX_CPP2XSI_PSH_OFF;
+
+ /*
+ * Select correct memory for PCI inbound transactions
+ */
+ if (ixp23xx_cpp_boot()) {
+ *IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1);
+ } else {
+ *IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1);
+
+ /*
+ * Enable coherency on A2 silicon.
+ */
+ if (arch_is_coherent())
+ *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_COH_OFF;
+ }
+}
+
+void __init ixp23xx_pci_preinit(void)
+{
+ ixp23xx_pci_common_init();
+
+ hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS,
+ "PCI config cycle to non-existent device");
+
+ *IXP23XX_PCI_ADDR_EXT = 0x0000e000;
+}
+
+/*
+ * Prevent PCI layer from seeing the inbound host-bridge resources
+ */
+static void __devinit pci_fixup_ixp23xx(struct pci_dev *dev)
+{
+ int i;
+
+ dev->class &= 0xff;
+ dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ dev->resource[i].start = 0;
+ dev->resource[i].end = 0;
+ dev->resource[i].flags = 0;
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9002, pci_fixup_ixp23xx);
+
+/*
+ * IXP2300 systems often have large resource requirements, so we just
+ * use our own resource space.
+ */
+static struct resource ixp23xx_pci_mem_space = {
+ .start = IXP23XX_PCI_MEM_START,
+ .end = IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "PCI Mem Space"
+};
+
+static struct resource ixp23xx_pci_io_space = {
+ .start = 0x00000100,
+ .end = 0x01ffffff,
+ .flags = IORESOURCE_IO,
+ .name = "PCI I/O Space"
+};
+
+int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys)
+{
+ if (nr >= 1)
+ return 0;
+
+ sys->resource[0] = &ixp23xx_pci_io_space;
+ sys->resource[1] = &ixp23xx_pci_mem_space;
+ sys->resource[2] = NULL;
+
+ return 1;
+}
+
+void ixp23xx_pci_slave_init(void)
+{
+ ixp23xx_pci_common_init();
+}
diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c
new file mode 100644
index 00000000000..43c14e74079
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/roadrunner.c
@@ -0,0 +1,164 @@
+/*
+ * arch/arm/mach-ixp23xx/roadrunner.c
+ *
+ * RoadRunner board-specific routines
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * Based on 2.4 code Copyright 2005 (c) ADI Engineering Corporation
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/bitops.h>
+#include <linux/ioport.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/pci.h>
+
+/*
+ * Interrupt mapping
+ */
+#define INTA IRQ_ROADRUNNER_PCI_INTA
+#define INTB IRQ_ROADRUNNER_PCI_INTB
+#define INTC IRQ_ROADRUNNER_PCI_INTC
+#define INTD IRQ_ROADRUNNER_PCI_INTD
+
+#define INTC_PIN IXP23XX_GPIO_PIN_11
+#define INTD_PIN IXP23XX_GPIO_PIN_12
+
+static int __init roadrunner_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+{
+ static int pci_card_slot_irq[] = {INTB, INTC, INTD, INTA};
+ static int pmc_card_slot_irq[] = {INTA, INTB, INTC, INTD};
+ static int usb_irq[] = {INTB, INTC, INTD, -1};
+ static int mini_pci_1_irq[] = {INTB, INTC, -1, -1};
+ static int mini_pci_2_irq[] = {INTC, INTD, -1, -1};
+
+ switch(dev->bus->number) {
+ case 0:
+ switch(dev->devfn) {
+ case 0x0: // PCI-PCI bridge
+ break;
+ case 0x8: // PCI Card Slot
+ return pci_card_slot_irq[pin - 1];
+ case 0x10: // PMC Slot
+ return pmc_card_slot_irq[pin - 1];
+ case 0x18: // PMC Slot Secondary Agent
+ break;
+ case 0x20: // IXP Processor
+ break;
+ default:
+ return NO_IRQ;
+ }
+ break;
+
+ case 1:
+ switch(dev->devfn) {
+ case 0x0: // IDE Controller
+ return (pin == 1) ? INTC : -1;
+ case 0x8: // USB fun 0
+ case 0x9: // USB fun 1
+ case 0xa: // USB fun 2
+ return usb_irq[pin - 1];
+ case 0x10: // Mini PCI 1
+ return mini_pci_1_irq[pin-1];
+ case 0x18: // Mini PCI 2
+ return mini_pci_2_irq[pin-1];
+ case 0x20: // MEM slot
+ return (pin == 1) ? INTA : -1;
+ default:
+ return NO_IRQ;
+ }
+ break;
+
+ default:
+ return NO_IRQ;
+ }
+
+ return NO_IRQ;
+}
+
+static void roadrunner_pci_preinit(void)
+{
+ set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQT_LOW);
+ set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQT_LOW);
+
+ ixp23xx_pci_preinit();
+}
+
+static struct hw_pci roadrunner_pci __initdata = {
+ .nr_controllers = 1,
+ .preinit = roadrunner_pci_preinit,
+ .setup = ixp23xx_pci_setup,
+ .scan = ixp23xx_pci_scan_bus,
+ .map_irq = roadrunner_map_irq,
+};
+
+static int __init roadrunner_pci_init(void)
+{
+ if (machine_is_roadrunner())
+ pci_common_init(&roadrunner_pci);
+
+ return 0;
+};
+
+subsys_initcall(roadrunner_pci_init);
+
+static void __init roadrunner_init(void)
+{
+ physmap_configure(0x90000000, 0x04000000, 2, NULL);
+
+ /*
+ * Mark flash as writeable
+ */
+ IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[2] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[3] |= IXP23XX_FLASH_WRITABLE;
+
+ ixp23xx_sys_init();
+}
+
+MACHINE_START(ROADRUNNER, "ADI Engineering RoadRunner Development Platform")
+ /* Maintainer: Deepak Saxena */
+ .phys_io = IXP23XX_PERIPHERAL_PHYS,
+ .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
+ .map_io = ixp23xx_map_io,
+ .init_irq = ixp23xx_init_irq,
+ .timer = &ixp23xx_timer,
+ .boot_params = 0x00000100,
+ .init_machine = roadrunner_init,
+MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 5bf50a2a737..3b23f43cb16 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -11,6 +11,7 @@ comment "IXP4xx Platforms"
config MACH_NSLU2
bool
prompt "Linksys NSLU2"
+ select PCI
help
Say 'Y' here if you want your kernel to support Linksys's
NSLU2 NAS device. For more information on this platform,
@@ -18,6 +19,7 @@ config MACH_NSLU2
config ARCH_AVILA
bool "Avila"
+ select PCI
help
Say 'Y' here if you want your kernel to support the Gateworks
Avila Network Platform. For more information on this platform,
@@ -25,6 +27,7 @@ config ARCH_AVILA
config ARCH_ADI_COYOTE
bool "Coyote"
+ select PCI
help
Say 'Y' here if you want your kernel to support the ADI
Engineering Coyote Gateway Reference Platform. For more
@@ -32,6 +35,7 @@ config ARCH_ADI_COYOTE
config ARCH_IXDP425
bool "IXDP425"
+ select PCI
help
Say 'Y' here if you want your kernel to support Intel's
IXDP425 Development Platform (Also known as Richfield).
@@ -39,6 +43,7 @@ config ARCH_IXDP425
config MACH_IXDPG425
bool "IXDPG425"
+ select PCI
help
Say 'Y' here if you want your kernel to support Intel's
IXDPG425 Development Platform (Also known as Montajade).
@@ -46,6 +51,7 @@ config MACH_IXDPG425
config MACH_IXDP465
bool "IXDP465"
+ select PCI
help
Say 'Y' here if you want your kernel to support Intel's
IXDP465 Development Platform (Also known as BMP).
@@ -72,6 +78,7 @@ config ARCH_PRPMC1100
config MACH_NAS100D
bool
prompt "NAS100D"
+ select PCI
help
Say 'Y' here if you want your kernel to support Iomega's
NAS 100d device. For more information on this platform,
@@ -96,6 +103,7 @@ config CPU_IXP46X
config MACH_GTWX5715
bool "Gemtek WX5715 (Linksys WRV54G)"
depends on ARCH_IXP4XX
+ select PCI
help
This board is currently inside the Linksys WRV54G Gateways.
@@ -110,11 +118,16 @@ config MACH_GTWX5715
"High Speed" UART is n/c (as far as I can tell)
20 Pin ARM/Xscale JTAG interface on J2
-
comment "IXP4xx Options"
+config DMABOUNCE
+ bool
+ default y
+ depends on PCI
+
config IXP4XX_INDIRECT_PCI
bool "Use indirect PCI memory access"
+ depends on PCI
help
IXP4xx provides two methods of accessing PCI memory space:
@@ -128,7 +141,7 @@ config IXP4XX_INDIRECT_PCI
2) If > 64MB of memory space is required, the IXP4xx can be
configured to use indirect registers to access PCI This allows
for up to 128MB (0x48000000 to 0x4fffffff) of memory on the bus.
- The disadvantadge of this is that every PCI access requires
+ The disadvantage of this is that every PCI access requires
three local register accesses plus a spinlock, but in some
cases the performance hit is acceptable. In addition, you cannot
mmap() PCI devices in this case due to the indirect nature
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 0471044fa17..5a4aaa0e0a0 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -2,8 +2,9 @@
# Makefile for the linux kernel.
#
-obj-y += common.o common-pci.o
+obj-y += common.o
+obj-$(CONFIG_PCI) += common-pci.o
obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o ixdp425-setup.o
obj-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o coyote-setup.o
obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o coyote-setup.o
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index a0888e160e3..00b761ff0f9 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -91,7 +91,7 @@ static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type);
/*
* IRQ -> GPIO mapping table
*/
-static char irq2gpio[32] = {
+static signed char irq2gpio[32] = {
-1, -1, -1, -1, -1, -1, 0, 1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 2, 3, 4, 5, 6,
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 86a0f0d1434..f8d716ccc1d 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -69,12 +69,6 @@ config MACH_VOICEBLUE
Support for Voiceblue GSM/VoIP gateway. Say Y here if you have
such a board.
-config MACH_NETSTAR
- bool "NetStar"
- depends on ARCH_OMAP1 && ARCH_OMAP15XX
- help
- Support for NetStar PBX. Say Y here if you have such a board.
-
config MACH_OMAP_PALMTE
bool "Palm Tungsten E"
depends on ARCH_OMAP1 && ARCH_OMAP15XX
@@ -85,6 +79,20 @@ config MACH_OMAP_PALMTE
informations.
Say Y here if you have such a PDA, say NO otherwise.
+config MACH_NOKIA770
+ bool "Nokia 770"
+ depends on ARCH_OMAP1 && ARCH_OMAP16XX
+ help
+ Support for the Nokia 770 Internet Tablet. Say Y here if you
+ have such a device.
+
+config MACH_AMS_DELTA
+ bool "Amstrad E3 (Delta)"
+ depends on ARCH_OMAP1 && ARCH_OMAP15XX
+ help
+ Support for the Amstrad E3 (codename Delta) videophone. Say Y here
+ if you have such a device.
+
config MACH_OMAP_GENERIC
bool "Generic OMAP board"
depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index b0b00156faa..9ea719550ad 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -3,7 +3,13 @@
#
# Common support
-obj-y := io.o id.o clock.o irq.o time.o mux.o serial.o devices.o
+obj-y := io.o id.o clock.o irq.o mux.o serial.o devices.o
+
+obj-$(CONFIG_OMAP_MPU_TIMER) += time.o
+
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
led-y := leds.o
# Specific board support
@@ -14,8 +20,9 @@ obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o
-obj-$(CONFIG_MACH_NETSTAR) += board-netstar.o
obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o
+obj-$(CONFIG_MACH_NOKIA770) += board-nokia770.o
+obj-$(CONFIG_MACH_AMS_DELTA) += board-ams-delta.o
ifeq ($(CONFIG_ARCH_OMAP15XX),y)
# Innovator-1510 FPGA
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
new file mode 100644
index 00000000000..6178f046f12
--- /dev/null
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -0,0 +1,116 @@
+/*
+ * linux/arch/arm/mach-omap1/board-ams-delta.c
+ *
+ * Modified from board-generic.c
+ *
+ * Board specific inits for the Amstrad E3 (codename Delta) videophone
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/board-ams-delta.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+
+static u8 ams_delta_latch1_reg;
+static u16 ams_delta_latch2_reg;
+
+void ams_delta_latch1_write(u8 mask, u8 value)
+{
+ ams_delta_latch1_reg &= ~mask;
+ ams_delta_latch1_reg |= value;
+ *(volatile __u8 *) AMS_DELTA_LATCH1_VIRT = ams_delta_latch1_reg;
+}
+
+void ams_delta_latch2_write(u16 mask, u16 value)
+{
+ ams_delta_latch2_reg &= ~mask;
+ ams_delta_latch2_reg |= value;
+ *(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = ams_delta_latch2_reg;
+}
+
+static void __init ams_delta_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+ omap_gpio_init();
+}
+
+static struct map_desc ams_delta_io_desc[] __initdata = {
+ // AMS_DELTA_LATCH1
+ {
+ .virtual = AMS_DELTA_LATCH1_VIRT,
+ .pfn = __phys_to_pfn(AMS_DELTA_LATCH1_PHYS),
+ .length = 0x01000000,
+ .type = MT_DEVICE
+ },
+ // AMS_DELTA_LATCH2
+ {
+ .virtual = AMS_DELTA_LATCH2_VIRT,
+ .pfn = __phys_to_pfn(AMS_DELTA_LATCH2_PHYS),
+ .length = 0x01000000,
+ .type = MT_DEVICE
+ },
+ // AMS_DELTA_MODEM
+ {
+ .virtual = AMS_DELTA_MODEM_VIRT,
+ .pfn = __phys_to_pfn(AMS_DELTA_MODEM_PHYS),
+ .length = 0x01000000,
+ .type = MT_DEVICE
+ }
+};
+
+static struct omap_uart_config ams_delta_uart_config __initdata = {
+ .enabled_uarts = 1,
+};
+
+static struct omap_board_config_kernel ams_delta_config[] = {
+ { OMAP_TAG_UART, &ams_delta_uart_config },
+};
+
+static void __init ams_delta_init(void)
+{
+ iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
+
+ omap_board_config = ams_delta_config;
+ omap_board_config_size = ARRAY_SIZE(ams_delta_config);
+ omap_serial_init();
+
+ /* Clear latch2 (NAND, LCD, modem enable) */
+ ams_delta_latch2_write(~0, 0);
+}
+
+static void __init ams_delta_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
+ /* Maintainer: Jonathan McDowell <noodles@earth.li> */
+ .phys_io = 0xfff00000,
+ .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
+ .boot_params = 0x10000100,
+ .map_io = ams_delta_map_io,
+ .init_irq = ams_delta_init_irq,
+ .init_machine = ams_delta_init,
+ .timer = &omap_timer,
+MACHINE_END
+
+EXPORT_SYMBOL(ams_delta_latch1_write);
+EXPORT_SYMBOL(ams_delta_latch2_write);
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index a177e78b2b8..33d01adab1e 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -88,7 +88,7 @@ static struct omap_board_config_kernel generic_config[] = {
static void __init omap_generic_init(void)
{
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
generic_config[0].data = &generic1510_usb_config;
}
#endif
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 89f0cc74a51..cd3a06dfc0a 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -24,7 +24,9 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -35,12 +37,55 @@
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/irda.h>
#include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
extern int omap_gpio_init(void);
-static struct mtd_partition h2_partitions[] = {
+static int h2_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(0, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_3),
+ KEY(0, 3, KEY_F10),
+ KEY(0, 4, KEY_F5),
+ KEY(0, 5, KEY_9),
+ KEY(1, 0, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(1, 2, KEY_2),
+ KEY(1, 3, KEY_F9),
+ KEY(1, 4, KEY_F7),
+ KEY(1, 5, KEY_0),
+ KEY(2, 0, KEY_ENTER),
+ KEY(2, 1, KEY_6),
+ KEY(2, 2, KEY_1),
+ KEY(2, 3, KEY_F2),
+ KEY(2, 4, KEY_F6),
+ KEY(2, 5, KEY_HOME),
+ KEY(3, 0, KEY_8),
+ KEY(3, 1, KEY_5),
+ KEY(3, 2, KEY_F12),
+ KEY(3, 3, KEY_F3),
+ KEY(3, 4, KEY_F8),
+ KEY(3, 5, KEY_END),
+ KEY(4, 0, KEY_7),
+ KEY(4, 1, KEY_4),
+ KEY(4, 2, KEY_F11),
+ KEY(4, 3, KEY_F1),
+ KEY(4, 4, KEY_F4),
+ KEY(4, 5, KEY_ESC),
+ KEY(5, 0, KEY_F13),
+ KEY(5, 1, KEY_F14),
+ KEY(5, 2, KEY_F15),
+ KEY(5, 3, KEY_F16),
+ KEY(5, 4, KEY_SLEEP),
+ 0
+};
+
+static struct mtd_partition h2_nor_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
.name = "bootloader",
@@ -71,26 +116,26 @@ static struct mtd_partition h2_partitions[] = {
}
};
-static struct flash_platform_data h2_flash_data = {
+static struct flash_platform_data h2_nor_data = {
.map_name = "cfi_probe",
.width = 2,
- .parts = h2_partitions,
- .nr_parts = ARRAY_SIZE(h2_partitions),
+ .parts = h2_nor_partitions,
+ .nr_parts = ARRAY_SIZE(h2_nor_partitions),
};
-static struct resource h2_flash_resource = {
+static struct resource h2_nor_resource = {
/* This is on CS3, wherever it's mapped */
.flags = IORESOURCE_MEM,
};
-static struct platform_device h2_flash_device = {
+static struct platform_device h2_nor_device = {
.name = "omapflash",
.id = 0,
.dev = {
- .platform_data = &h2_flash_data,
+ .platform_data = &h2_nor_data,
},
.num_resources = 1,
- .resource = &h2_flash_resource,
+ .resource = &h2_nor_resource,
};
static struct resource h2_smc91x_resources[] = {
@@ -113,9 +158,119 @@ static struct platform_device h2_smc91x_device = {
.resource = h2_smc91x_resources,
};
+static struct resource h2_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data h2_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = h2_keymap,
+ .rep = 1,
+};
+
+static struct platform_device h2_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &h2_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(h2_kp_resources),
+ .resource = h2_kp_resources,
+};
+
+#define H2_IRDA_FIRSEL_GPIO_PIN 17
+
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+static int h2_transceiver_mode(struct device *dev, int state)
+{
+ if (state & IR_SIRMODE)
+ omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 0);
+ else /* MIR/FIR */
+ omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 1);
+
+ return 0;
+}
+#endif
+
+static struct omap_irda_config h2_irda_data = {
+ .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+ .rx_channel = OMAP_DMA_UART3_RX,
+ .tx_channel = OMAP_DMA_UART3_TX,
+ .dest_start = UART3_THR,
+ .src_start = UART3_RHR,
+ .tx_trigger = 0,
+ .rx_trigger = 0,
+};
+
+static struct resource h2_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct platform_device h2_irda_device = {
+ .name = "omapirda",
+ .id = 0,
+ .dev = {
+ .platform_data = &h2_irda_data,
+ },
+ .num_resources = ARRAY_SIZE(h2_irda_resources),
+ .resource = h2_irda_resources,
+};
+
+static struct platform_device h2_lcd_device = {
+ .name = "lcd_h2",
+ .id = -1,
+};
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+ .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+ .spcr1 = RINTM(3) | RRST,
+ .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+ RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
+ .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+ .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+ XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
+ .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+ .srgr1 = FWID(15),
+ .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
+
+ .pcr0 = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
+ //.pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+ .name = "H2 TSC2101",
+ .mcbsp_regs_alsa = &mcbsp_regs,
+ .codec_configure_dev = NULL, // tsc2101_configure,
+ .codec_set_samplerate = NULL, // tsc2101_set_samplerate,
+ .codec_clock_setup = NULL, // tsc2101_clock_setup,
+ .codec_clock_on = NULL, // tsc2101_clock_on,
+ .codec_clock_off = NULL, // tsc2101_clock_off,
+ .get_default_samplerate = NULL, // tsc2101_get_default_samplerate,
+};
+
+static struct platform_device h2_mcbsp1_device = {
+ .name = "omap_alsa_mcbsp",
+ .id = 1,
+ .dev = {
+ .platform_data = &alsa_config,
+ },
+};
+
static struct platform_device *h2_devices[] __initdata = {
- &h2_flash_device,
+ &h2_nor_device,
&h2_smc91x_device,
+ &h2_irda_device,
+ &h2_kp_device,
+ &h2_lcd_device,
+ &h2_mcbsp1_device,
};
static void __init h2_init_smc91x(void)
@@ -164,7 +319,6 @@ static struct omap_uart_config h2_uart_config __initdata = {
};
static struct omap_lcd_config h2_lcd_config __initdata = {
- .panel_name = "h2",
.ctrl_name = "internal",
};
@@ -177,16 +331,34 @@ static struct omap_board_config_kernel h2_config[] = {
static void __init h2_init(void)
{
- /* NOTE: revC boards support NAND-boot, which can put NOR on CS2B
- * and NAND (either 16bit or 8bit) on CS3.
+ /* Here we assume the NOR boot config: NOR on CS3 (possibly swapped
+ * to address 0 by a dip switch), NAND on CS2B. The NAND driver will
+ * notice whether a NAND chip is enabled at probe time.
+ *
+ * FIXME revC boards (and H3) support NAND-boot, with a dip switch to
+ * put NOR on CS2B and NAND (which on H2 may be 16bit) on CS3. Try
+ * detecting that in code here, to avoid probing every possible flash
+ * configuration...
*/
- h2_flash_resource.end = h2_flash_resource.start = omap_cs3_phys();
- h2_flash_resource.end += SZ_32M - 1;
+ h2_nor_resource.end = h2_nor_resource.start = omap_cs3_phys();
+ h2_nor_resource.end += SZ_32M - 1;
+
+ omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+ omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
/* MMC: card detect and WP */
// omap_cfg_reg(U19_ARMIO1); /* CD */
omap_cfg_reg(BALLOUT_V8_ARMIO3); /* WP */
+ /* Irda */
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+ omap_writel(omap_readl(FUNC_MUX_CTRL_A) | 7, FUNC_MUX_CTRL_A);
+ if (!(omap_request_gpio(H2_IRDA_FIRSEL_GPIO_PIN))) {
+ omap_set_gpio_direction(H2_IRDA_FIRSEL_GPIO_PIN, 0);
+ h2_irda_data.transceiver_mode = h2_transceiver_mode;
+ }
+#endif
+
platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
omap_board_config = h2_config;
omap_board_config_size = ARRAY_SIZE(h2_config);
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index d9f38626599..4b8d0ec73cb 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -21,8 +21,11 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
+#include <linux/workqueue.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/setup.h>
#include <asm/page.h>
@@ -33,15 +36,59 @@
#include <asm/mach/map.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/gpioexpander.h>
#include <asm/arch/irqs.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/irda.h>
#include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/dma.h>
#include <asm/arch/common.h>
extern int omap_gpio_init(void);
-static struct mtd_partition h3_partitions[] = {
+static int h3_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(0, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_3),
+ KEY(0, 3, KEY_F10),
+ KEY(0, 4, KEY_F5),
+ KEY(0, 5, KEY_9),
+ KEY(1, 0, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(1, 2, KEY_2),
+ KEY(1, 3, KEY_F9),
+ KEY(1, 4, KEY_F7),
+ KEY(1, 5, KEY_0),
+ KEY(2, 0, KEY_ENTER),
+ KEY(2, 1, KEY_6),
+ KEY(2, 2, KEY_1),
+ KEY(2, 3, KEY_F2),
+ KEY(2, 4, KEY_F6),
+ KEY(2, 5, KEY_HOME),
+ KEY(3, 0, KEY_8),
+ KEY(3, 1, KEY_5),
+ KEY(3, 2, KEY_F12),
+ KEY(3, 3, KEY_F3),
+ KEY(3, 4, KEY_F8),
+ KEY(3, 5, KEY_END),
+ KEY(4, 0, KEY_7),
+ KEY(4, 1, KEY_4),
+ KEY(4, 2, KEY_F11),
+ KEY(4, 3, KEY_F1),
+ KEY(4, 4, KEY_F4),
+ KEY(4, 5, KEY_ESC),
+ KEY(5, 0, KEY_F13),
+ KEY(5, 1, KEY_F14),
+ KEY(5, 2, KEY_F15),
+ KEY(5, 3, KEY_F16),
+ KEY(5, 4, KEY_SLEEP),
+ 0
+};
+
+
+static struct mtd_partition nor_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
.name = "bootloader",
@@ -72,26 +119,80 @@ static struct mtd_partition h3_partitions[] = {
}
};
-static struct flash_platform_data h3_flash_data = {
+static struct flash_platform_data nor_data = {
.map_name = "cfi_probe",
.width = 2,
- .parts = h3_partitions,
- .nr_parts = ARRAY_SIZE(h3_partitions),
+ .parts = nor_partitions,
+ .nr_parts = ARRAY_SIZE(nor_partitions),
};
-static struct resource h3_flash_resource = {
+static struct resource nor_resource = {
/* This is on CS3, wherever it's mapped */
.flags = IORESOURCE_MEM,
};
-static struct platform_device flash_device = {
+static struct platform_device nor_device = {
.name = "omapflash",
.id = 0,
.dev = {
- .platform_data = &h3_flash_data,
+ .platform_data = &nor_data,
+ },
+ .num_resources = 1,
+ .resource = &nor_resource,
+};
+
+static struct mtd_partition nand_partitions[] = {
+#if 0
+ /* REVISIT: enable these partitions if you make NAND BOOT work */
+ {
+ .name = "xloader",
+ .offset = 0,
+ .size = 64 * 1024,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "bootloader",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 256 * 1024,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 192 * 1024,
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 2 * SZ_1M,
+ },
+#endif
+ {
+ .name = "filesystem",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ },
+};
+
+/* dip switches control NAND chip access: 8 bit, 16 bit, or neither */
+static struct nand_platform_data nand_data = {
+ .options = NAND_SAMSUNG_LP_OPTIONS,
+ .parts = nand_partitions,
+ .nr_parts = ARRAY_SIZE(nand_partitions),
+};
+
+static struct resource nand_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+ .name = "omapnand",
+ .id = 0,
+ .dev = {
+ .platform_data = &nand_data,
},
.num_resources = 1,
- .resource = &h3_flash_resource,
+ .resource = &nand_resource,
};
static struct resource smc91x_resources[] = {
@@ -138,10 +239,136 @@ static struct platform_device intlat_device = {
.resource = intlat_resources,
};
+static struct resource h3_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data h3_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = h3_keymap,
+ .rep = 1,
+};
+
+static struct platform_device h3_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &h3_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(h3_kp_resources),
+ .resource = h3_kp_resources,
+};
+
+
+/* Select between the IrDA and aGPS module
+ */
+static int h3_select_irda(struct device *dev, int state)
+{
+ unsigned char expa;
+ int err = 0;
+
+ if ((err = read_gpio_expa(&expa, 0x26))) {
+ printk(KERN_ERR "Error reading from I/O EXPANDER \n");
+ return err;
+ }
+
+ /* 'P6' enable/disable IRDA_TX and IRDA_RX */
+ if (state & IR_SEL) { /* IrDA */
+ if ((err = write_gpio_expa(expa | 0x40, 0x26))) {
+ printk(KERN_ERR "Error writing to I/O EXPANDER \n");
+ return err;
+ }
+ } else {
+ if ((err = write_gpio_expa(expa & ~0x40, 0x26))) {
+ printk(KERN_ERR "Error writing to I/O EXPANDER \n");
+ return err;
+ }
+ }
+ return err;
+}
+
+static void set_trans_mode(void *data)
+{
+ int *mode = data;
+ unsigned char expa;
+ int err = 0;
+
+ if ((err = read_gpio_expa(&expa, 0x27)) != 0) {
+ printk(KERN_ERR "Error reading from I/O expander\n");
+ }
+
+ expa &= ~0x03;
+
+ if (*mode & IR_SIRMODE) {
+ expa |= 0x01;
+ } else { /* MIR/FIR */
+ expa |= 0x03;
+ }
+
+ if ((err = write_gpio_expa(expa, 0x27)) != 0) {
+ printk(KERN_ERR "Error writing to I/O expander\n");
+ }
+}
+
+static int h3_transceiver_mode(struct device *dev, int mode)
+{
+ struct omap_irda_config *irda_config = dev->platform_data;
+
+ cancel_delayed_work(&irda_config->gpio_expa);
+ PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
+ schedule_work(&irda_config->gpio_expa);
+
+ return 0;
+}
+
+static struct omap_irda_config h3_irda_data = {
+ .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+ .transceiver_mode = h3_transceiver_mode,
+ .select_irda = h3_select_irda,
+ .rx_channel = OMAP_DMA_UART3_RX,
+ .tx_channel = OMAP_DMA_UART3_TX,
+ .dest_start = UART3_THR,
+ .src_start = UART3_RHR,
+ .tx_trigger = 0,
+ .rx_trigger = 0,
+};
+
+static struct resource h3_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device h3_irda_device = {
+ .name = "omapirda",
+ .id = 0,
+ .dev = {
+ .platform_data = &h3_irda_data,
+ },
+ .num_resources = ARRAY_SIZE(h3_irda_resources),
+ .resource = h3_irda_resources,
+};
+
+static struct platform_device h3_lcd_device = {
+ .name = "lcd_h3",
+ .id = -1,
+};
+
static struct platform_device *devices[] __initdata = {
- &flash_device,
+ &nor_device,
+ &nand_device,
&smc91x_device,
&intlat_device,
+ &h3_irda_device,
+ &h3_kp_device,
+ &h3_lcd_device,
};
static struct omap_usb_config h3_usb_config __initdata = {
@@ -171,7 +398,6 @@ static struct omap_uart_config h3_uart_config __initdata = {
};
static struct omap_lcd_config h3_lcd_config __initdata = {
- .panel_name = "h3",
.ctrl_name = "internal",
};
@@ -182,11 +408,36 @@ static struct omap_board_config_kernel h3_config[] = {
{ OMAP_TAG_LCD, &h3_lcd_config },
};
+#define H3_NAND_RB_GPIO_PIN 10
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+ return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN);
+}
+
static void __init h3_init(void)
{
- h3_flash_resource.end = h3_flash_resource.start = omap_cs3_phys();
- h3_flash_resource.end += OMAP_CS3_SIZE - 1;
- (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+ /* Here we assume the NOR boot config: NOR on CS3 (possibly swapped
+ * to address 0 by a dip switch), NAND on CS2B. The NAND driver will
+ * notice whether a NAND chip is enabled at probe time.
+ *
+ * H3 support NAND-boot, with a dip switch to put NOR on CS2B and NAND
+ * (which on H2 may be 16bit) on CS3. Try detecting that in code here,
+ * to avoid probing every possible flash configuration...
+ */
+ nor_resource.end = nor_resource.start = omap_cs3_phys();
+ nor_resource.end += SZ_32M - 1;
+
+ nand_resource.end = nand_resource.start = OMAP_CS2B_PHYS;
+ nand_resource.end += SZ_4K - 1;
+ if (!(omap_request_gpio(H3_NAND_RB_GPIO_PIN)))
+ nand_data.dev_ready = nand_dev_ready;
+
+ /* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */
+ /* GPIO10 pullup/down register, Enable pullup on GPIO10 */
+ omap_cfg_reg(V2_1710_GPIO10);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
omap_board_config = h3_config;
omap_board_config_size = ARRAY_SIZE(h3_config);
omap_serial_init();
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index a04e4332915..e90c137a4cf 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -34,8 +35,22 @@
#include <asm/arch/gpio.h>
#include <asm/arch/tc.h>
#include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
+static int innovator_keymap[] = {
+ KEY(0, 0, KEY_F1),
+ KEY(0, 3, KEY_DOWN),
+ KEY(1, 1, KEY_F2),
+ KEY(1, 2, KEY_RIGHT),
+ KEY(2, 0, KEY_F3),
+ KEY(2, 1, KEY_F4),
+ KEY(2, 2, KEY_UP),
+ KEY(3, 2, KEY_ENTER),
+ KEY(3, 3, KEY_LEFT),
+ 0
+};
+
static struct mtd_partition innovator_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
@@ -97,6 +112,31 @@ static struct platform_device innovator_flash_device = {
.resource = &innovator_flash_resource,
};
+static struct resource innovator_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data innovator_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = innovator_keymap,
+};
+
+static struct platform_device innovator_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &innovator_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(innovator_kp_resources),
+ .resource = innovator_kp_resources,
+};
+
+
#ifdef CONFIG_ARCH_OMAP15XX
/* Only FPGA needs to be mapped here. All others are done with ioremap */
@@ -129,9 +169,16 @@ static struct platform_device innovator1510_smc91x_device = {
.resource = innovator1510_smc91x_resources,
};
+static struct platform_device innovator1510_lcd_device = {
+ .name = "lcd_inn1510",
+ .id = -1,
+};
+
static struct platform_device *innovator1510_devices[] __initdata = {
&innovator_flash_device,
&innovator1510_smc91x_device,
+ &innovator_kp_device,
+ &innovator1510_lcd_device,
};
#endif /* CONFIG_ARCH_OMAP15XX */
@@ -158,9 +205,16 @@ static struct platform_device innovator1610_smc91x_device = {
.resource = innovator1610_smc91x_resources,
};
+static struct platform_device innovator1610_lcd_device = {
+ .name = "inn1610_lcd",
+ .id = -1,
+};
+
static struct platform_device *innovator1610_devices[] __initdata = {
&innovator_flash_device,
&innovator1610_smc91x_device,
+ &innovator_kp_device,
+ &innovator1610_lcd_device,
};
#endif /* CONFIG_ARCH_OMAP16XX */
@@ -206,7 +260,6 @@ static struct omap_usb_config innovator1510_usb_config __initdata = {
};
static struct omap_lcd_config innovator1510_lcd_config __initdata = {
- .panel_name = "inn1510",
.ctrl_name = "internal",
};
#endif
@@ -228,7 +281,6 @@ static struct omap_usb_config h2_usb_config __initdata = {
};
static struct omap_lcd_config innovator1610_lcd_config __initdata = {
- .panel_name = "inn1610",
.ctrl_name = "internal",
};
#endif
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c
deleted file mode 100644
index 60d5f8a3339..00000000000
--- a/arch/arm/mach-omap1/board-netstar.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Modified from board-generic.c
- *
- * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
- *
- * Code for Netstar OMAP board.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <asm/arch/gpio.h>
-#include <asm/arch/mux.h>
-#include <asm/arch/usb.h>
-#include <asm/arch/common.h>
-
-extern void __init omap_init_time(void);
-extern int omap_gpio_init(void);
-
-static struct resource netstar_smc91x_resources[] = {
- [0] = {
- .start = OMAP_CS1_PHYS + 0x300,
- .end = OMAP_CS1_PHYS + 0x300 + 16,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = OMAP_GPIO_IRQ(8),
- .end = OMAP_GPIO_IRQ(8),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device netstar_smc91x_device = {
- .name = "smc91x",
- .id = 0,
- .num_resources = ARRAY_SIZE(netstar_smc91x_resources),
- .resource = netstar_smc91x_resources,
-};
-
-static struct platform_device *netstar_devices[] __initdata = {
- &netstar_smc91x_device,
-};
-
-static struct omap_uart_config netstar_uart_config __initdata = {
- .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
-};
-
-static struct omap_board_config_kernel netstar_config[] = {
- { OMAP_TAG_UART, &netstar_uart_config },
-};
-
-static void __init netstar_init_irq(void)
-{
- omap1_init_common_hw();
- omap_init_irq();
- omap_gpio_init();
-}
-
-static void __init netstar_init(void)
-{
- /* green LED */
- omap_request_gpio(4);
- omap_set_gpio_direction(4, 0);
- /* smc91x reset */
- omap_request_gpio(7);
- omap_set_gpio_direction(7, 0);
- omap_set_gpio_dataout(7, 1);
- udelay(2); /* wait at least 100ns */
- omap_set_gpio_dataout(7, 0);
- mdelay(50); /* 50ms until PHY ready */
- /* smc91x interrupt pin */
- omap_request_gpio(8);
-
- omap_request_gpio(12);
- omap_request_gpio(13);
- omap_request_gpio(14);
- omap_request_gpio(15);
- set_irq_type(OMAP_GPIO_IRQ(12), IRQT_FALLING);
- set_irq_type(OMAP_GPIO_IRQ(13), IRQT_FALLING);
- set_irq_type(OMAP_GPIO_IRQ(14), IRQT_FALLING);
- set_irq_type(OMAP_GPIO_IRQ(15), IRQT_FALLING);
-
- platform_add_devices(netstar_devices, ARRAY_SIZE(netstar_devices));
-
- /* Switch on green LED */
- omap_set_gpio_dataout(4, 0);
- /* Switch off red LED */
- omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */
- omap_writeb(0x80, OMAP_LPG1_LCR);
-
- omap_board_config = netstar_config;
- omap_board_config_size = ARRAY_SIZE(netstar_config);
- omap_serial_init();
-}
-
-static void __init netstar_map_io(void)
-{
- omap1_map_common_io();
-}
-
-#define MACHINE_PANICED 1
-#define MACHINE_REBOOTING 2
-#define MACHINE_REBOOT 4
-static unsigned long machine_state;
-
-static int panic_event(struct notifier_block *this, unsigned long event,
- void *ptr)
-{
- if (test_and_set_bit(MACHINE_PANICED, &machine_state))
- return NOTIFY_DONE;
-
- /* Switch off green LED */
- omap_set_gpio_dataout(4, 1);
- /* Flash red LED */
- omap_writeb(0x78, OMAP_LPG1_LCR);
- omap_writeb(0x01, OMAP_LPG1_PMR); /* Enable clock */
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block panic_block = {
- .notifier_call = panic_event,
-};
-
-static int __init netstar_late_init(void)
-{
- /* TODO: Setup front panel switch here */
-
- /* Setup panic notifier */
- notifier_chain_register(&panic_notifier_list, &panic_block);
-
- return 0;
-}
-
-postcore_initcall(netstar_late_init);
-
-MACHINE_START(NETSTAR, "NetStar OMAP5910")
- /* Maintainer: Ladislav Michl <michl@2n.cz> */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
- .boot_params = 0x10000100,
- .map_io = netstar_map_io,
- .init_irq = netstar_init_irq,
- .init_machine = netstar_init,
- .timer = &omap_timer,
-MACHINE_END
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
new file mode 100644
index 00000000000..02b980d77b1
--- /dev/null
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -0,0 +1,268 @@
+/*
+ * linux/arch/arm/mach-omap1/board-nokia770.c
+ *
+ * Modified from board-generic.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/common.h>
+#include <asm/arch/dsp_common.h>
+#include <asm/arch/aic23.h>
+#include <asm/arch/gpio.h>
+
+static void __init omap_nokia770_init_irq(void)
+{
+ /* On Nokia 770, the SleepX signal is masked with an
+ * MPUIO line by default. It has to be unmasked for it
+ * to become functional */
+
+ /* SleepX mask direction */
+ omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
+ /* Unmask SleepX signal */
+ omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
+
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+static int nokia770_keymap[] = {
+ KEY(0, 1, GROUP_0 | KEY_UP),
+ KEY(0, 2, GROUP_1 | KEY_F5),
+ KEY(1, 0, GROUP_0 | KEY_LEFT),
+ KEY(1, 1, GROUP_0 | KEY_ENTER),
+ KEY(1, 2, GROUP_0 | KEY_RIGHT),
+ KEY(2, 0, GROUP_1 | KEY_ESC),
+ KEY(2, 1, GROUP_0 | KEY_DOWN),
+ KEY(2, 2, GROUP_1 | KEY_F4),
+ KEY(3, 0, GROUP_2 | KEY_F7),
+ KEY(3, 1, GROUP_2 | KEY_F8),
+ KEY(3, 2, GROUP_2 | KEY_F6),
+ 0
+};
+
+static struct resource nokia770_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data nokia770_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = nokia770_keymap
+};
+
+static struct platform_device nokia770_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &nokia770_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(nokia770_kp_resources),
+ .resource = nokia770_kp_resources,
+};
+
+static struct platform_device *nokia770_devices[] __initdata = {
+ &nokia770_kp_device,
+};
+
+static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata = {
+ .x_max = 0x0fff,
+ .y_max = 0x0fff,
+ .x_plate_ohms = 180,
+ .pressure_max = 255,
+ .debounce_max = 10,
+ .debounce_tol = 3,
+};
+
+static struct spi_board_info nokia770_spi_board_info[] __initdata = {
+ [0] = {
+ .modalias = "lcd_lph8923",
+ .bus_num = 2,
+ .chip_select = 3,
+ .max_speed_hz = 12000000,
+ },
+ [1] = {
+ .modalias = "ads7846",
+ .bus_num = 2,
+ .chip_select = 0,
+ .max_speed_hz = 2500000,
+ .irq = OMAP_GPIO_IRQ(15),
+ .platform_data = &nokia770_ads7846_platform_data,
+ },
+};
+
+
+/* assume no Mini-AB port */
+
+static struct omap_usb_config nokia770_usb_config __initdata = {
+ .otg = 1,
+ .register_host = 1,
+ .register_dev = 1,
+ .hmc_mode = 16,
+ .pins[0] = 6,
+};
+
+static struct omap_mmc_config nokia770_mmc_config __initdata = {
+ .mmc[0] = {
+ .enabled = 0,
+ .wire4 = 0,
+ .wp_pin = -1,
+ .power_pin = -1,
+ .switch_pin = -1,
+ },
+ .mmc[1] = {
+ .enabled = 0,
+ .wire4 = 0,
+ .wp_pin = -1,
+ .power_pin = -1,
+ .switch_pin = -1,
+ },
+};
+
+static struct omap_board_config_kernel nokia770_config[] = {
+ { OMAP_TAG_USB, NULL },
+ { OMAP_TAG_MMC, &nokia770_mmc_config },
+};
+
+/*
+ * audio power control
+ */
+#define HEADPHONE_GPIO 14
+#define AMPLIFIER_CTRL_GPIO 58
+
+static struct clk *dspxor_ck;
+static DECLARE_MUTEX(audio_pwr_sem);
+/*
+ * audio_pwr_state
+ * +--+-------------------------+---------------------------------------+
+ * |-1|down |power-up request -> 0 |
+ * +--+-------------------------+---------------------------------------+
+ * | 0|up |power-down(1) request -> 1 |
+ * | | |power-down(2) request -> (ignore) |
+ * +--+-------------------------+---------------------------------------+
+ * | 1|up, |power-up request -> 0 |
+ * | |received down(1) request |power-down(2) request -> -1 |
+ * +--+-------------------------+---------------------------------------+
+ */
+static int audio_pwr_state = -1;
+
+/*
+ * audio_pwr_up / down should be called under audio_pwr_sem
+ */
+static void nokia770_audio_pwr_up(void)
+{
+ clk_enable(dspxor_ck);
+
+ /* Turn on codec */
+ tlv320aic23_power_up();
+
+ if (omap_get_gpio_datain(HEADPHONE_GPIO))
+ /* HP not connected, turn on amplifier */
+ omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 1);
+ else
+ /* HP connected, do not turn on amplifier */
+ printk("HP connected\n");
+}
+
+static void codec_delayed_power_down(void *arg)
+{
+ down(&audio_pwr_sem);
+ if (audio_pwr_state == -1)
+ tlv320aic23_power_down();
+ clk_disable(dspxor_ck);
+ up(&audio_pwr_sem);
+}
+
+static DECLARE_WORK(codec_power_down_work, codec_delayed_power_down, NULL);
+
+static void nokia770_audio_pwr_down(void)
+{
+ /* Turn off amplifier */
+ omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 0);
+
+ /* Turn off codec: schedule delayed work */
+ schedule_delayed_work(&codec_power_down_work, HZ / 20); /* 50ms */
+}
+
+void nokia770_audio_pwr_up_request(int stage)
+{
+ down(&audio_pwr_sem);
+ if (audio_pwr_state == -1)
+ nokia770_audio_pwr_up();
+ /* force audio_pwr_state = 0, even if it was 1. */
+ audio_pwr_state = 0;
+ up(&audio_pwr_sem);
+}
+
+void nokia770_audio_pwr_down_request(int stage)
+{
+ down(&audio_pwr_sem);
+ switch (stage) {
+ case 1:
+ if (audio_pwr_state == 0)
+ audio_pwr_state = 1;
+ break;
+ case 2:
+ if (audio_pwr_state == 1) {
+ nokia770_audio_pwr_down();
+ audio_pwr_state = -1;
+ }
+ break;
+ }
+ up(&audio_pwr_sem);
+}
+
+static void __init omap_nokia770_init(void)
+{
+ nokia770_config[0].data = &nokia770_usb_config;
+
+ platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices));
+ spi_register_board_info(nokia770_spi_board_info,
+ ARRAY_SIZE(nokia770_spi_board_info));
+ omap_board_config = nokia770_config;
+ omap_board_config_size = ARRAY_SIZE(nokia770_config);
+ omap_serial_init();
+ omap_dsp_audio_pwr_up_request = nokia770_audio_pwr_up_request;
+ omap_dsp_audio_pwr_down_request = nokia770_audio_pwr_down_request;
+ dspxor_ck = clk_get(0, "dspxor_ck");
+}
+
+static void __init omap_nokia770_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(NOKIA770, "Nokia 770")
+ .phys_io = 0xfff00000,
+ .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
+ .boot_params = 0x10000100,
+ .map_io = omap_nokia770_map_io,
+ .init_irq = omap_nokia770_init_irq,
+ .init_machine = omap_nokia770_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 543fa136106..1160093e8ef 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -33,6 +33,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -44,7 +45,24 @@
#include <asm/arch/usb.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
+
+static int osk_keymap[] = {
+ KEY(0, 0, KEY_F1),
+ KEY(0, 3, KEY_UP),
+ KEY(1, 1, KEY_LEFTCTRL),
+ KEY(1, 2, KEY_LEFT),
+ KEY(2, 0, KEY_SPACE),
+ KEY(2, 1, KEY_ESC),
+ KEY(2, 2, KEY_DOWN),
+ KEY(3, 2, KEY_ENTER),
+ KEY(3, 3, KEY_RIGHT),
+ 0
+};
+
static struct mtd_partition osk_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
@@ -133,9 +151,69 @@ static struct platform_device osk5912_cf_device = {
.resource = osk5912_cf_resources,
};
+#define DEFAULT_BITPERSAMPLE 16
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+ .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+ .spcr1 = RINTM(3) | RRST,
+ .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+ RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
+ .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+ .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+ XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
+ .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+ .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
+ .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
+ /*.pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,*/ /* mcbsp: master */
+ .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+ .name = "OSK AIC23",
+ .mcbsp_regs_alsa = &mcbsp_regs,
+ .codec_configure_dev = NULL, // aic23_configure,
+ .codec_set_samplerate = NULL, // aic23_set_samplerate,
+ .codec_clock_setup = NULL, // aic23_clock_setup,
+ .codec_clock_on = NULL, // aic23_clock_on,
+ .codec_clock_off = NULL, // aic23_clock_off,
+ .get_default_samplerate = NULL, // aic23_get_default_samplerate,
+};
+
static struct platform_device osk5912_mcbsp1_device = {
- .name = "omap_mcbsp",
- .id = 1,
+ .name = "omap_alsa_mcbsp",
+ .id = 1,
+ .dev = {
+ .platform_data = &alsa_config,
+ },
+};
+
+static struct resource osk5912_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data osk_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = osk_keymap,
+};
+
+static struct platform_device osk5912_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &osk_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(osk5912_kp_resources),
+ .resource = osk5912_kp_resources,
+};
+
+static struct platform_device osk5912_lcd_device = {
+ .name = "lcd_osk",
+ .id = -1,
};
static struct platform_device *osk5912_devices[] __initdata = {
@@ -143,6 +221,8 @@ static struct platform_device *osk5912_devices[] __initdata = {
&osk5912_smc91x_device,
&osk5912_cf_device,
&osk5912_mcbsp1_device,
+ &osk5912_kp_device,
+ &osk5912_lcd_device,
};
static void __init osk_init_smc91x(void)
@@ -197,7 +277,6 @@ static struct omap_uart_config osk_uart_config __initdata = {
};
static struct omap_lcd_config osk_lcd_config __initdata = {
- .panel_name = "osk",
.ctrl_name = "internal",
};
@@ -255,8 +334,18 @@ static void __init osk_mistral_init(void)
static void __init osk_mistral_init(void) { }
#endif
+#define EMIFS_CS3_VAL (0x88013141)
+
static void __init osk_init(void)
{
+ /* Workaround for wrong CS3 (NOR flash) timing
+ * There are some U-Boot versions out there which configure
+ * wrong CS3 memory timings. This mainly leads to CRC
+ * or similiar errors if you use NOR flash (e.g. with JFFS2)
+ */
+ if (EMIFS_CCS(3) != EMIFS_CS3_VAL)
+ EMIFS_CCS(3) = EMIFS_CS3_VAL;
+
osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys();
osk_flash_resource.end += SZ_32M - 1;
platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices));
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index e488f723677..4bc8a62909b 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -38,6 +38,15 @@ static void __init omap_generic_init_irq(void)
omap_init_irq();
}
+static struct platform_device palmte_lcd_device = {
+ .name = "lcd_palmte",
+ .id = -1,
+};
+
+static struct platform_device *devices[] __initdata = {
+ &palmte_lcd_device,
+};
+
static struct omap_usb_config palmte_usb_config __initdata = {
.register_dev = 1,
.hmc_mode = 0,
@@ -55,7 +64,6 @@ static struct omap_mmc_config palmte_mmc_config __initdata = {
};
static struct omap_lcd_config palmte_lcd_config __initdata = {
- .panel_name = "palmte",
.ctrl_name = "internal",
};
@@ -69,6 +77,8 @@ static void __init omap_generic_init(void)
{
omap_board_config = palmte_config;
omap_board_config_size = ARRAY_SIZE(palmte_config);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
}
static void __init omap_generic_map_io(void)
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 3913a3cc0ce..64b45d8ae35 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -16,7 +16,9 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -28,9 +30,44 @@
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/fpga.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
#include <asm/arch/board.h>
+static int p2_keymap[] = {
+ KEY(0,0,KEY_UP),
+ KEY(0,1,KEY_RIGHT),
+ KEY(0,2,KEY_LEFT),
+ KEY(0,3,KEY_DOWN),
+ KEY(0,4,KEY_CENTER),
+ KEY(0,5,KEY_0_5),
+ KEY(1,0,KEY_SOFT2),
+ KEY(1,1,KEY_SEND),
+ KEY(1,2,KEY_END),
+ KEY(1,3,KEY_VOLUMEDOWN),
+ KEY(1,4,KEY_VOLUMEUP),
+ KEY(1,5,KEY_RECORD),
+ KEY(2,0,KEY_SOFT1),
+ KEY(2,1,KEY_3),
+ KEY(2,2,KEY_6),
+ KEY(2,3,KEY_9),
+ KEY(2,4,KEY_SHARP),
+ KEY(2,5,KEY_2_5),
+ KEY(3,0,KEY_BACK),
+ KEY(3,1,KEY_2),
+ KEY(3,2,KEY_5),
+ KEY(3,3,KEY_8),
+ KEY(3,4,KEY_0),
+ KEY(3,5,KEY_HEADSETHOOK),
+ KEY(4,0,KEY_HOME),
+ KEY(4,1,KEY_1),
+ KEY(4,2,KEY_4),
+ KEY(4,3,KEY_7),
+ KEY(4,4,KEY_STAR),
+ KEY(4,5,KEY_POWER),
+ 0
+};
+
static struct resource smc91x_resources[] = {
[0] = {
.start = H2P2_DBG_FPGA_ETHR_START, /* Physical */
@@ -44,7 +81,7 @@ static struct resource smc91x_resources[] = {
},
};
-static struct mtd_partition p2_partitions[] = {
+static struct mtd_partition nor_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
.name = "bootloader",
@@ -75,27 +112,47 @@ static struct mtd_partition p2_partitions[] = {
},
};
-static struct flash_platform_data p2_flash_data = {
+static struct flash_platform_data nor_data = {
.map_name = "cfi_probe",
.width = 2,
- .parts = p2_partitions,
- .nr_parts = ARRAY_SIZE(p2_partitions),
+ .parts = nor_partitions,
+ .nr_parts = ARRAY_SIZE(nor_partitions),
};
-static struct resource p2_flash_resource = {
+static struct resource nor_resource = {
.start = OMAP_CS0_PHYS,
.end = OMAP_CS0_PHYS + SZ_32M - 1,
.flags = IORESOURCE_MEM,
};
-static struct platform_device p2_flash_device = {
+static struct platform_device nor_device = {
.name = "omapflash",
.id = 0,
.dev = {
- .platform_data = &p2_flash_data,
+ .platform_data = &nor_data,
+ },
+ .num_resources = 1,
+ .resource = &nor_resource,
+};
+
+static struct nand_platform_data nand_data = {
+ .options = NAND_SAMSUNG_LP_OPTIONS,
+};
+
+static struct resource nand_resource = {
+ .start = OMAP_CS3_PHYS,
+ .end = OMAP_CS3_PHYS + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+ .name = "omapnand",
+ .id = 0,
+ .dev = {
+ .platform_data = &nand_data,
},
.num_resources = 1,
- .resource = &p2_flash_resource,
+ .resource = &nand_resource,
};
static struct platform_device smc91x_device = {
@@ -105,17 +162,55 @@ static struct platform_device smc91x_device = {
.resource = smc91x_resources,
};
+static struct resource kp_resources[] = {
+ [0] = {
+ .start = INT_730_MPUIO_KEYPAD,
+ .end = INT_730_MPUIO_KEYPAD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = p2_keymap,
+};
+
+static struct platform_device kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &kp_data,
+ },
+ .num_resources = ARRAY_SIZE(kp_resources),
+ .resource = kp_resources,
+};
+
+static struct platform_device lcd_device = {
+ .name = "lcd_p2",
+ .id = -1,
+};
+
static struct platform_device *devices[] __initdata = {
- &p2_flash_device,
+ &nor_device,
+ &nand_device,
&smc91x_device,
+ &kp_device,
+ &lcd_device,
};
+#define P2_NAND_RB_GPIO_PIN 62
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+ return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN);
+}
+
static struct omap_uart_config perseus2_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1)),
};
static struct omap_lcd_config perseus2_lcd_config __initdata = {
- .panel_name = "p2",
.ctrl_name = "internal",
};
@@ -126,7 +221,13 @@ static struct omap_board_config_kernel perseus2_config[] = {
static void __init omap_perseus2_init(void)
{
- (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+ if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN)))
+ nand_data.dev_ready = nand_dev_ready;
+
+ omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+ omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
omap_board_config = perseus2_config;
omap_board_config_size = ARRAY_SIZE(perseus2_config);
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index bfd5fdd1a87..447a586eb33 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -155,9 +155,9 @@ static struct omap_uart_config voiceblue_uart_config __initdata = {
};
static struct omap_board_config_kernel voiceblue_config[] = {
- { OMAP_TAG_USB, &voiceblue_usb_config },
- { OMAP_TAG_MMC, &voiceblue_mmc_config },
- { OMAP_TAG_UART, &voiceblue_uart_config },
+ { OMAP_TAG_USB, &voiceblue_usb_config },
+ { OMAP_TAG_MMC, &voiceblue_mmc_config },
+ { OMAP_TAG_UART, &voiceblue_uart_config },
};
static void __init voiceblue_init_irq(void)
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 75110ba1042..619db18144e 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -345,7 +345,7 @@ static unsigned calc_ext_dsor(unsigned long rate)
*/
for (dsor = 2; dsor < 96; ++dsor) {
if ((dsor & 1) && dsor > 8)
- continue;
+ continue;
if (rate >= 96000000 / dsor)
break;
}
@@ -687,6 +687,11 @@ int __init omap1_clk_init(void)
clk_register(*clkp);
continue;
}
+
+ if (((*clkp)->flags &CLOCK_IN_OMAP310) && cpu_is_omap310()) {
+ clk_register(*clkp);
+ continue;
+ }
}
info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
@@ -784,7 +789,7 @@ int __init omap1_clk_init(void)
clk_enable(&armxor_ck.clk);
clk_enable(&armtim_ck.clk); /* This should be done by timer code */
- if (cpu_is_omap1510())
+ if (cpu_is_omap15xx())
clk_enable(&arm_gpio_ck);
return 0;
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index 4f18d1b9444..b7c68819c4e 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -151,7 +151,7 @@ static struct clk ck_ref = {
.name = "ck_ref",
.rate = 12000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
};
@@ -160,7 +160,7 @@ static struct clk ck_dpll1 = {
.name = "ck_dpll1",
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_PROPAGATES | ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | RATE_PROPAGATES | ALWAYS_ENABLED,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
};
@@ -183,7 +183,8 @@ static struct clk arm_ck = {
.name = "arm_ck",
.parent = &ck_dpll1,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES |
+ ALWAYS_ENABLED,
.rate_offset = CKCTL_ARMDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
.enable = &omap1_clk_enable_generic,
@@ -195,7 +196,8 @@ static struct arm_idlect1_clk armper_ck = {
.name = "armper_ck",
.parent = &ck_dpll1,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_CKCTL | CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | RATE_CKCTL |
+ CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_PERCK,
.rate_offset = CKCTL_PERDIV_OFFSET,
@@ -209,7 +211,7 @@ static struct arm_idlect1_clk armper_ck = {
static struct clk arm_gpio_ck = {
.name = "arm_gpio_ck",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP1510,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_GPIOCK,
.recalc = &followparent_recalc,
@@ -222,7 +224,7 @@ static struct arm_idlect1_clk armxor_ck = {
.name = "armxor_ck",
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_XORPCK,
.recalc = &followparent_recalc,
@@ -237,7 +239,7 @@ static struct arm_idlect1_clk armtim_ck = {
.name = "armtim_ck",
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_TIMCK,
.recalc = &followparent_recalc,
@@ -252,7 +254,7 @@ static struct arm_idlect1_clk armwdt_ck = {
.name = "armwdt_ck",
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_WDTCK,
.recalc = &omap1_watchdog_recalc,
@@ -344,9 +346,9 @@ static struct arm_idlect1_clk tc_ck = {
.name = "tc_ck",
.parent = &ck_dpll1,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IN_OMAP730 | RATE_CKCTL |
- RATE_PROPAGATES | ALWAYS_ENABLED |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 |
+ RATE_CKCTL | RATE_PROPAGATES |
+ ALWAYS_ENABLED | CLOCK_IDLE_CONTROL,
.rate_offset = CKCTL_TCDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
.enable = &omap1_clk_enable_generic,
@@ -358,7 +360,8 @@ static struct arm_idlect1_clk tc_ck = {
static struct clk arminth_ck1510 = {
.name = "arminth_ck",
.parent = &tc_ck.clk,
- .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ ALWAYS_ENABLED,
.recalc = &followparent_recalc,
/* Note: On 1510 the frequency follows TC_CK
*
@@ -372,7 +375,8 @@ static struct clk tipb_ck = {
/* No-idle controlled by "tc_ck" */
.name = "tibp_ck",
.parent = &tc_ck.clk,
- .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ ALWAYS_ENABLED,
.recalc = &followparent_recalc,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
@@ -417,7 +421,7 @@ static struct clk dma_ck = {
.name = "dma_ck",
.parent = &tc_ck.clk,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
.recalc = &followparent_recalc,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
@@ -437,7 +441,7 @@ static struct arm_idlect1_clk api_ck = {
.name = "api_ck",
.parent = &tc_ck.clk,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_APICK,
.recalc = &followparent_recalc,
@@ -451,7 +455,8 @@ static struct arm_idlect1_clk lb_ck = {
.clk = {
.name = "lb_ck",
.parent = &tc_ck.clk,
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IDLE_CONTROL,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_LBCK,
.recalc = &followparent_recalc,
@@ -495,8 +500,8 @@ static struct arm_idlect1_clk lcd_ck_1510 = {
.clk = {
.name = "lcd_ck",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP1510 | RATE_CKCTL |
- CLOCK_IDLE_CONTROL,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ RATE_CKCTL | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_LCDCK,
.rate_offset = CKCTL_LCDDIV_OFFSET,
@@ -512,8 +517,9 @@ static struct clk uart1_1510 = {
/* Direct from ULPD, no real parent */
.parent = &armper_ck.clk,
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT |
- ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ ENABLE_REG_32BIT | ALWAYS_ENABLED |
+ CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 29, /* Chooses between 12MHz and 48MHz */
.set_rate = &omap1_set_uart_rate,
@@ -544,8 +550,8 @@ static struct clk uart2_ck = {
.parent = &armper_ck.clk,
.rate = 12000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- ENABLE_REG_32BIT | ALWAYS_ENABLED |
- CLOCK_NO_IDLE_PARENT,
+ CLOCK_IN_OMAP310 | ENABLE_REG_32BIT |
+ ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 30, /* Chooses between 12MHz and 48MHz */
.set_rate = &omap1_set_uart_rate,
@@ -559,8 +565,9 @@ static struct clk uart3_1510 = {
/* Direct from ULPD, no real parent */
.parent = &armper_ck.clk,
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT |
- ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ ENABLE_REG_32BIT | ALWAYS_ENABLED |
+ CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 31, /* Chooses between 12MHz and 48MHz */
.set_rate = &omap1_set_uart_rate,
@@ -590,7 +597,7 @@ static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */
/* Direct from ULPD, no parent */
.rate = 6000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_FIXED | ENABLE_REG_32BIT,
+ CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = (void __iomem *)ULPD_CLOCK_CTRL,
.enable_bit = USB_MCLK_EN_BIT,
.enable = &omap1_clk_enable_generic,
@@ -601,7 +608,7 @@ static struct clk usb_hhc_ck1510 = {
.name = "usb_hhc_ck",
/* Direct from ULPD, no parent */
.rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
- .flags = CLOCK_IN_OMAP1510 |
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = USB_HOST_HHC_UHOST_EN,
@@ -637,7 +644,9 @@ static struct clk mclk_1510 = {
.name = "mclk",
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
+ .enable_reg = (void __iomem *)SOFT_REQ_REG,
+ .enable_bit = 6,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
};
@@ -659,7 +668,7 @@ static struct clk bclk_1510 = {
.name = "bclk",
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
};
@@ -678,12 +687,14 @@ static struct clk bclk_16xx = {
};
static struct clk mmc1_ck = {
- .name = "mmc1_ck",
+ .name = "mmc_ck",
+ .id = 1,
/* Functional clock is direct from ULPD, interface clock is ARMPER */
.parent = &armper_ck.clk,
.rate = 48000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+ CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT |
+ CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 23,
.enable = &omap1_clk_enable_generic,
@@ -691,7 +702,8 @@ static struct clk mmc1_ck = {
};
static struct clk mmc2_ck = {
- .name = "mmc2_ck",
+ .name = "mmc_ck",
+ .id = 2,
/* Functional clock is direct from ULPD, interface clock is ARMPER */
.parent = &armper_ck.clk,
.rate = 48000000,
@@ -706,7 +718,7 @@ static struct clk mmc2_ck = {
static struct clk virtual_ck_mpu = {
.name = "mpu",
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- VIRTUAL_CLOCK | ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | VIRTUAL_CLOCK | ALWAYS_ENABLED,
.parent = &arm_ck, /* Is smarter alias for */
.recalc = &followparent_recalc,
.set_rate = &omap1_select_table_rate,
@@ -715,6 +727,20 @@ static struct clk virtual_ck_mpu = {
.disable = &omap1_clk_disable_generic,
};
+/* virtual functional clock domain for I2C. Just for making sure that ARMXOR_CK
+remains active during MPU idle whenever this is enabled */
+static struct clk i2c_fck = {
+ .name = "i2c_fck",
+ .id = 1,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT |
+ ALWAYS_ENABLED,
+ .parent = &armxor_ck.clk,
+ .recalc = &followparent_recalc,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
+};
+
static struct clk * onchip_clks[] = {
/* non-ULPD clocks */
&ck_ref,
@@ -763,6 +789,7 @@ static struct clk * onchip_clks[] = {
&mmc2_ck,
/* Virtual clocks */
&virtual_ck_mpu,
+ &i2c_fck,
};
#endif
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index ecbc47514ad..847329cafc5 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -25,10 +25,6 @@
#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
-extern void omap_nop_release(struct device *dev);
-
-/*-------------------------------------------------------------------------*/
-
#if defined(CONFIG_OMAP1610_IR) || defined(CONFIG_OMAP161O_IR_MODULE)
static u64 irda_dmamask = 0xffffffff;
@@ -37,7 +33,6 @@ static struct platform_device omap1610ir_device = {
.name = "omap1610-ir",
.id = -1,
.dev = {
- .release = omap_nop_release,
.dma_mask = &irda_dmamask,
},
};
@@ -84,9 +79,6 @@ static struct resource rtc_resources[] = {
static struct platform_device omap_rtc_device = {
.name = "omap_rtc",
.id = -1,
- .dev = {
- .release = omap_nop_release,
- },
.num_resources = ARRAY_SIZE(rtc_resources),
.resource = rtc_resources,
};
@@ -99,6 +91,42 @@ static void omap_init_rtc(void)
static inline void omap_init_rtc(void) {}
#endif
+#if defined(CONFIG_OMAP_STI)
+
+#define OMAP1_STI_BASE IO_ADDRESS(0xfffea000)
+#define OMAP1_STI_CHANNEL_BASE (OMAP1_STI_BASE + 0x400)
+
+static struct resource sti_resources[] = {
+ {
+ .start = OMAP1_STI_BASE,
+ .end = OMAP1_STI_BASE + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = OMAP1_STI_CHANNEL_BASE,
+ .end = OMAP1_STI_CHANNEL_BASE + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_1610_STI,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device sti_device = {
+ .name = "sti",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(sti_resources),
+ .resource = sti_resources,
+};
+
+static inline void omap_init_sti(void)
+{
+ platform_device_register(&sti_device);
+}
+#else
+static inline void omap_init_sti(void) {}
+#endif
/*-------------------------------------------------------------------------*/
@@ -129,6 +157,7 @@ static int __init omap1_init_devices(void)
*/
omap_init_irda();
omap_init_rtc();
+ omap_init_sti();
return 0;
}
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 82d556be79c..be3a2a4ee2b 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -18,6 +18,7 @@
#include <asm/io.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/omapfb.h>
extern int omap1_clk_init(void);
extern void omap_check_revision(void);
@@ -110,7 +111,7 @@ void __init omap1_map_common_io(void)
}
#endif
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
}
#endif
@@ -121,6 +122,7 @@ void __init omap1_map_common_io(void)
#endif
omap_sram_init();
+ omapfb_reserve_mem();
}
/*
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index ed65a7d2e94..a0431c00fa8 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -60,7 +60,7 @@ struct omap_irq_bank {
unsigned long wake_enable;
};
-static unsigned int irq_bank_count = 0;
+static unsigned int irq_bank_count;
static struct omap_irq_bank *irq_banks;
static inline unsigned int irq_bank_readl(int bank, int offset)
@@ -142,28 +142,28 @@ static void omap_irq_set_cfg(int irq, int fiq, int priority, int trigger)
#ifdef CONFIG_ARCH_OMAP730
static struct omap_irq_bank omap730_irq_banks[] = {
- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f },
- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 },
+ { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f },
+ { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 },
{ .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0x800040f3 },
};
#endif
#ifdef CONFIG_ARCH_OMAP15XX
static struct omap_irq_bank omap1510_irq_banks[] = {
- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff },
- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xffbfffed },
+ { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff },
+ { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xffbfffed },
};
static struct omap_irq_bank omap310_irq_banks[] = {
- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3faefc3 },
- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0x65b3c061 },
+ { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3faefc3 },
+ { .base_reg = OMAP_IH2_BASE, .trigger_map = 0x65b3c061 },
};
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
static struct omap_irq_bank omap1610_irq_banks[] = {
- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3fefe8f },
- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb7c1fd },
+ { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3fefe8f },
+ { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb7c1fd },
{ .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0xffffb7ff },
{ .base_reg = OMAP_IH2_BASE + 0x200, .trigger_map = 0xffffffff },
};
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
index d4b8d624e74..10fe0b3efca 100644
--- a/arch/arm/mach-omap1/mux.c
+++ b/arch/arm/mach-omap1/mux.c
@@ -35,16 +35,20 @@
#ifdef CONFIG_ARCH_OMAP730
struct pin_config __initdata_or_module omap730_pins[] = {
-MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 0, 20, 1, NA, 0, 0)
-MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 0, 24, 1, NA, 0, 0)
-MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 0, 28, 1, NA, 0, 0)
-MUX_CFG_730("F3_730_KBR3", 13, 1, 0, 0, 0, 1, NA, 0, 0)
-MUX_CFG_730("D2_730_KBR4", 13, 5, 0, 0, 4, 1, NA, 0, 0)
-MUX_CFG_730("C2_730_KBC0", 13, 9, 0, 0, 8, 1, NA, 0, 0)
-MUX_CFG_730("D3_730_KBC1", 13, 13, 0, 0, 12, 1, NA, 0, 0)
-MUX_CFG_730("E4_730_KBC2", 13, 17, 0, 0, 16, 1, NA, 0, 0)
-MUX_CFG_730("F4_730_KBC3", 13, 21, 0, 0, 20, 1, NA, 0, 0)
-MUX_CFG_730("E3_730_KBC4", 13, 25, 0, 0, 24, 1, NA, 0, 0)
+MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 20, 1, 0)
+MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 24, 1, 0)
+MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 28, 1, 0)
+MUX_CFG_730("F3_730_KBR3", 13, 1, 0, 0, 1, 0)
+MUX_CFG_730("D2_730_KBR4", 13, 5, 0, 4, 1, 0)
+MUX_CFG_730("C2_730_KBC0", 13, 9, 0, 8, 1, 0)
+MUX_CFG_730("D3_730_KBC1", 13, 13, 0, 12, 1, 0)
+MUX_CFG_730("E4_730_KBC2", 13, 17, 0, 16, 1, 0)
+MUX_CFG_730("F4_730_KBC3", 13, 21, 0, 20, 1, 0)
+MUX_CFG_730("E3_730_KBC4", 13, 25, 0, 24, 1, 0)
+
+MUX_CFG_730("AA17_730_USB_DM", 2, 21, 0, 20, 0, 0)
+MUX_CFG_730("W16_730_USB_PU_EN", 2, 25, 0, 24, 0, 0)
+MUX_CFG_730("W17_730_USB_VBUSI", 2, 29, 0, 28, 0, 0)
};
#endif
@@ -73,8 +77,8 @@ MUX_CFG("UART3_BCLK", A, 0, 0, 2, 6, 0, NA, 0, 0)
MUX_CFG("Y15_1610_UART3_RTS", A, 0, 1, 2, 6, 0, NA, 0, 0)
/* PWT & PWL, conflicts with UART3 */
-MUX_CFG("PWT", 6, 0, 2, 0, 30, 0, NA, 0, 0)
-MUX_CFG("PWL", 6, 3, 1, 0, 31, 1, NA, 0, 0)
+MUX_CFG("PWT", 6, 0, 2, 0, 30, 0, NA, 0, 0)
+MUX_CFG("PWL", 6, 3, 1, 0, 31, 1, NA, 0, 0)
/* USB internal master generic */
MUX_CFG("R18_USB_VBUS", 7, 9, 2, 1, 11, 0, NA, 0, 1)
@@ -151,7 +155,7 @@ MUX_CFG("MCBSP3_CLKX", 9, 3, 1, 1, 29, 0, NA, 0, 1)
/* Misc ballouts */
MUX_CFG("BALLOUT_V8_ARMIO3", B, 18, 0, 2, 25, 1, NA, 0, 1)
-MUX_CFG("N20_HDQ", 6, 18, 1, 1, 4, 0, 1, 4, 0)
+MUX_CFG("N20_HDQ", 6, 18, 1, 1, 4, 0, 1, 4, 0)
/* OMAP-1610 MMC2 */
MUX_CFG("W8_1610_MMC2_DAT0", B, 21, 6, 2, 23, 1, 2, 1, 1)
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
new file mode 100644
index 00000000000..ddf6b07dc9c
--- /dev/null
+++ b/arch/arm/mach-omap1/pm.c
@@ -0,0 +1,770 @@
+/*
+ * linux/arch/arm/mach-omap1/pm.c
+ *
+ * OMAP Power Management Routines
+ *
+ * Original code for the SA11x0:
+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
+ *
+ * Modified for the PXA250 by Nicolas Pitre:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Modified for the OMAP1510 by David Singleton:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/tps65010.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/dsp_common.h>
+#include <asm/arch/dmtimer.h>
+
+static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
+static unsigned short dsp_sleep_save[DSP_SLEEP_SAVE_SIZE];
+static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
+static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE];
+static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
+static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
+
+static unsigned short enable_dyn_sleep = 1;
+
+static ssize_t omap_pm_sleep_while_idle_show(struct subsystem * subsys, char *buf)
+{
+ return sprintf(buf, "%hu\n", enable_dyn_sleep);
+}
+
+static ssize_t omap_pm_sleep_while_idle_store(struct subsystem * subsys,
+ const char * buf,
+ size_t n)
+{
+ unsigned short value;
+ if (sscanf(buf, "%hu", &value) != 1 ||
+ (value != 0 && value != 1)) {
+ printk(KERN_ERR "idle_sleep_store: Invalid value\n");
+ return -EINVAL;
+ }
+ enable_dyn_sleep = value;
+ return n;
+}
+
+static struct subsys_attribute sleep_while_idle_attr = {
+ .attr = {
+ .name = __stringify(sleep_while_idle),
+ .mode = 0644,
+ },
+ .show = omap_pm_sleep_while_idle_show,
+ .store = omap_pm_sleep_while_idle_store,
+};
+
+extern struct subsystem power_subsys;
+static void (*omap_sram_idle)(void) = NULL;
+static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
+
+/*
+ * Let's power down on idle, but only if we are really
+ * idle, because once we start down the path of
+ * going idle we continue to do idle even if we get
+ * a clock tick interrupt . .
+ */
+void omap_pm_idle(void)
+{
+ extern __u32 arm_idlect1_mask;
+ __u32 use_idlect1 = arm_idlect1_mask;
+#ifndef CONFIG_OMAP_MPU_TIMER
+ int do_sleep;
+#endif
+
+ local_irq_disable();
+ local_fiq_disable();
+ if (need_resched()) {
+ local_fiq_enable();
+ local_irq_enable();
+ return;
+ }
+
+ /*
+ * Since an interrupt may set up a timer, we don't want to
+ * reprogram the hardware timer with interrupts enabled.
+ * Re-enable interrupts only after returning from idle.
+ */
+ timer_dyn_reprogram();
+
+#ifdef CONFIG_OMAP_MPU_TIMER
+#warning Enable 32kHz OS timer in order to allow sleep states in idle
+ use_idlect1 = use_idlect1 & ~(1 << 9);
+#else
+
+ do_sleep = 0;
+ while (enable_dyn_sleep) {
+
+#ifdef CONFIG_CBUS_TAHVO_USB
+ extern int vbus_active;
+ /* Clock requirements? */
+ if (vbus_active)
+ break;
+#endif
+ do_sleep = 1;
+ break;
+ }
+
+#ifdef CONFIG_OMAP_DM_TIMER
+ use_idlect1 = omap_dm_timer_modify_idlect_mask(use_idlect1);
+#endif
+
+ if (omap_dma_running()) {
+ use_idlect1 &= ~(1 << 6);
+ if (omap_lcd_dma_ext_running())
+ use_idlect1 &= ~(1 << 12);
+ }
+
+ /* We should be able to remove the do_sleep variable and multiple
+ * tests above as soon as drivers, timer and DMA code have been fixed.
+ * Even the sleep block count should become obsolete. */
+ if ((use_idlect1 != ~0) || !do_sleep) {
+
+ __u32 saved_idlect1 = omap_readl(ARM_IDLECT1);
+ if (cpu_is_omap15xx())
+ use_idlect1 &= OMAP1510_BIG_SLEEP_REQUEST;
+ else
+ use_idlect1 &= OMAP1610_IDLECT1_SLEEP_VAL;
+ omap_writel(use_idlect1, ARM_IDLECT1);
+ __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
+ omap_writel(saved_idlect1, ARM_IDLECT1);
+
+ local_fiq_enable();
+ local_irq_enable();
+ return;
+ }
+ omap_sram_suspend(omap_readl(ARM_IDLECT1),
+ omap_readl(ARM_IDLECT2));
+#endif
+
+ local_fiq_enable();
+ local_irq_enable();
+}
+
+/*
+ * Configuration of the wakeup event is board specific. For the
+ * moment we put it into this helper function. Later it may move
+ * to board specific files.
+ */
+static void omap_pm_wakeup_setup(void)
+{
+ u32 level1_wake = 0;
+ u32 level2_wake = OMAP_IRQ_BIT(INT_UART2);
+
+ /*
+ * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
+ * and the L2 wakeup interrupts: keypad and UART2. Note that the
+ * drivers must still separately call omap_set_gpio_wakeup() to
+ * wake up to a GPIO interrupt.
+ */
+ if (cpu_is_omap730())
+ level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) |
+ OMAP_IRQ_BIT(INT_730_IH2_IRQ);
+ else if (cpu_is_omap15xx())
+ level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
+ OMAP_IRQ_BIT(INT_1510_IH2_IRQ);
+ else if (cpu_is_omap16xx())
+ level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
+ OMAP_IRQ_BIT(INT_1610_IH2_IRQ);
+
+ omap_writel(~level1_wake, OMAP_IH1_MIR);
+
+ if (cpu_is_omap730()) {
+ omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+ omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) |
+ OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)),
+ OMAP_IH2_1_MIR);
+ } else if (cpu_is_omap15xx()) {
+ level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
+ omap_writel(~level2_wake, OMAP_IH2_MIR);
+ } else if (cpu_is_omap16xx()) {
+ level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
+ omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+
+ /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
+ omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ),
+ OMAP_IH2_1_MIR);
+ omap_writel(~0x0, OMAP_IH2_2_MIR);
+ omap_writel(~0x0, OMAP_IH2_3_MIR);
+ }
+
+ /* New IRQ agreement, recalculate in cascade order */
+ omap_writel(1, OMAP_IH2_CONTROL);
+ omap_writel(1, OMAP_IH1_CONTROL);
+}
+
+#define EN_DSPCK 13 /* ARM_CKCTL */
+#define EN_APICK 6 /* ARM_IDLECT2 */
+#define DSP_EN 1 /* ARM_RSTCT1 */
+
+void omap_pm_suspend(void)
+{
+ unsigned long arg0 = 0, arg1 = 0;
+
+ printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev);
+
+ omap_serial_wake_trigger(1);
+
+ if (machine_is_omap_osk()) {
+ /* Stop LED1 (D9) blink */
+ tps65010_set_led(LED1, OFF);
+ }
+
+ omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
+
+ /*
+ * Step 1: turn off interrupts (FIXME: NOTE: already disabled)
+ */
+
+ local_irq_disable();
+ local_fiq_disable();
+
+ /*
+ * Step 2: save registers
+ *
+ * The omap is a strange/beautiful device. The caches, memory
+ * and register state are preserved across power saves.
+ * We have to save and restore very little register state to
+ * idle the omap.
+ *
+ * Save interrupt, MPUI, ARM and UPLD control registers.
+ */
+
+ if (cpu_is_omap730()) {
+ MPUI730_SAVE(OMAP_IH1_MIR);
+ MPUI730_SAVE(OMAP_IH2_0_MIR);
+ MPUI730_SAVE(OMAP_IH2_1_MIR);
+ MPUI730_SAVE(MPUI_CTRL);
+ MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI730_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI730_SAVE(EMIFS_CONFIG);
+ MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
+
+ } else if (cpu_is_omap15xx()) {
+ MPUI1510_SAVE(OMAP_IH1_MIR);
+ MPUI1510_SAVE(OMAP_IH2_MIR);
+ MPUI1510_SAVE(MPUI_CTRL);
+ MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI1510_SAVE(EMIFS_CONFIG);
+ MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
+ } else if (cpu_is_omap16xx()) {
+ MPUI1610_SAVE(OMAP_IH1_MIR);
+ MPUI1610_SAVE(OMAP_IH2_0_MIR);
+ MPUI1610_SAVE(OMAP_IH2_1_MIR);
+ MPUI1610_SAVE(OMAP_IH2_2_MIR);
+ MPUI1610_SAVE(OMAP_IH2_3_MIR);
+ MPUI1610_SAVE(MPUI_CTRL);
+ MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI1610_SAVE(EMIFS_CONFIG);
+ MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
+ }
+
+ ARM_SAVE(ARM_CKCTL);
+ ARM_SAVE(ARM_IDLECT1);
+ ARM_SAVE(ARM_IDLECT2);
+ if (!(cpu_is_omap15xx()))
+ ARM_SAVE(ARM_IDLECT3);
+ ARM_SAVE(ARM_EWUPCT);
+ ARM_SAVE(ARM_RSTCT1);
+ ARM_SAVE(ARM_RSTCT2);
+ ARM_SAVE(ARM_SYSST);
+ ULPD_SAVE(ULPD_CLOCK_CTRL);
+ ULPD_SAVE(ULPD_STATUS_REQ);
+
+ /* (Step 3 removed - we now allow deep sleep by default) */
+
+ /*
+ * Step 4: OMAP DSP Shutdown
+ */
+
+ /* stop DSP */
+ omap_writew(omap_readw(ARM_RSTCT1) & ~(1 << DSP_EN), ARM_RSTCT1);
+
+ /* shut down dsp_ck */
+ omap_writew(omap_readw(ARM_CKCTL) & ~(1 << EN_DSPCK), ARM_CKCTL);
+
+ /* temporarily enabling api_ck to access DSP registers */
+ omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2);
+
+ /* save DSP registers */
+ DSP_SAVE(DSP_IDLECT2);
+
+ /* Stop all DSP domain clocks */
+ __raw_writew(0, DSP_IDLECT2);
+
+ /*
+ * Step 5: Wakeup Event Setup
+ */
+
+ omap_pm_wakeup_setup();
+
+ /*
+ * Step 6: ARM and Traffic controller shutdown
+ */
+
+ /* disable ARM watchdog */
+ omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
+ omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
+
+ /*
+ * Step 6b: ARM and Traffic controller shutdown
+ *
+ * Step 6 continues here. Prepare jump to power management
+ * assembly code in internal SRAM.
+ *
+ * Since the omap_cpu_suspend routine has been copied to
+ * SRAM, we'll do an indirect procedure call to it and pass the
+ * contents of arm_idlect1 and arm_idlect2 so it can restore
+ * them when it wakes up and it will return.
+ */
+
+ arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
+ arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
+
+ /*
+ * Step 6c: ARM and Traffic controller shutdown
+ *
+ * Jump to assembly code. The processor will stay there
+ * until wake up.
+ */
+ omap_sram_suspend(arg0, arg1);
+
+ /*
+ * If we are here, processor is woken up!
+ */
+
+ /*
+ * Restore DSP clocks
+ */
+
+ /* again temporarily enabling api_ck to access DSP registers */
+ omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2);
+
+ /* Restore DSP domain clocks */
+ DSP_RESTORE(DSP_IDLECT2);
+
+ /*
+ * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
+ */
+
+ if (!(cpu_is_omap15xx()))
+ ARM_RESTORE(ARM_IDLECT3);
+ ARM_RESTORE(ARM_CKCTL);
+ ARM_RESTORE(ARM_EWUPCT);
+ ARM_RESTORE(ARM_RSTCT1);
+ ARM_RESTORE(ARM_RSTCT2);
+ ARM_RESTORE(ARM_SYSST);
+ ULPD_RESTORE(ULPD_CLOCK_CTRL);
+ ULPD_RESTORE(ULPD_STATUS_REQ);
+
+ if (cpu_is_omap730()) {
+ MPUI730_RESTORE(EMIFS_CONFIG);
+ MPUI730_RESTORE(EMIFF_SDRAM_CONFIG);
+ MPUI730_RESTORE(OMAP_IH1_MIR);
+ MPUI730_RESTORE(OMAP_IH2_0_MIR);
+ MPUI730_RESTORE(OMAP_IH2_1_MIR);
+ } else if (cpu_is_omap15xx()) {
+ MPUI1510_RESTORE(MPUI_CTRL);
+ MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
+ MPUI1510_RESTORE(EMIFS_CONFIG);
+ MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG);
+ MPUI1510_RESTORE(OMAP_IH1_MIR);
+ MPUI1510_RESTORE(OMAP_IH2_MIR);
+ } else if (cpu_is_omap16xx()) {
+ MPUI1610_RESTORE(MPUI_CTRL);
+ MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1610_RESTORE(MPUI_DSP_API_CONFIG);
+ MPUI1610_RESTORE(EMIFS_CONFIG);
+ MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG);
+
+ MPUI1610_RESTORE(OMAP_IH1_MIR);
+ MPUI1610_RESTORE(OMAP_IH2_0_MIR);
+ MPUI1610_RESTORE(OMAP_IH2_1_MIR);
+ MPUI1610_RESTORE(OMAP_IH2_2_MIR);
+ MPUI1610_RESTORE(OMAP_IH2_3_MIR);
+ }
+
+ omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
+
+ /*
+ * Reenable interrupts
+ */
+
+ local_irq_enable();
+ local_fiq_enable();
+
+ omap_serial_wake_trigger(0);
+
+ printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
+
+ if (machine_is_omap_osk()) {
+ /* Let LED1 (D9) blink again */
+ tps65010_set_led(LED1, BLINK);
+ }
+}
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+static int g_read_completed;
+
+/*
+ * Read system PM registers for debugging
+ */
+static int omap_pm_read_proc(
+ char *page_buffer,
+ char **my_first_byte,
+ off_t virtual_start,
+ int length,
+ int *eof,
+ void *data)
+{
+ int my_buffer_offset = 0;
+ char * const my_base = page_buffer;
+
+ ARM_SAVE(ARM_CKCTL);
+ ARM_SAVE(ARM_IDLECT1);
+ ARM_SAVE(ARM_IDLECT2);
+ if (!(cpu_is_omap15xx()))
+ ARM_SAVE(ARM_IDLECT3);
+ ARM_SAVE(ARM_EWUPCT);
+ ARM_SAVE(ARM_RSTCT1);
+ ARM_SAVE(ARM_RSTCT2);
+ ARM_SAVE(ARM_SYSST);
+
+ ULPD_SAVE(ULPD_IT_STATUS);
+ ULPD_SAVE(ULPD_CLOCK_CTRL);
+ ULPD_SAVE(ULPD_SOFT_REQ);
+ ULPD_SAVE(ULPD_STATUS_REQ);
+ ULPD_SAVE(ULPD_DPLL_CTRL);
+ ULPD_SAVE(ULPD_POWER_CTRL);
+
+ if (cpu_is_omap730()) {
+ MPUI730_SAVE(MPUI_CTRL);
+ MPUI730_SAVE(MPUI_DSP_STATUS);
+ MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI730_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
+ MPUI730_SAVE(EMIFS_CONFIG);
+ } else if (cpu_is_omap15xx()) {
+ MPUI1510_SAVE(MPUI_CTRL);
+ MPUI1510_SAVE(MPUI_DSP_STATUS);
+ MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
+ MPUI1510_SAVE(EMIFS_CONFIG);
+ } else if (cpu_is_omap16xx()) {
+ MPUI1610_SAVE(MPUI_CTRL);
+ MPUI1610_SAVE(MPUI_DSP_STATUS);
+ MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
+ MPUI1610_SAVE(EMIFS_CONFIG);
+ }
+
+ if (virtual_start == 0) {
+ g_read_completed = 0;
+
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "ARM_CKCTL_REG: 0x%-8x \n"
+ "ARM_IDLECT1_REG: 0x%-8x \n"
+ "ARM_IDLECT2_REG: 0x%-8x \n"
+ "ARM_IDLECT3_REG: 0x%-8x \n"
+ "ARM_EWUPCT_REG: 0x%-8x \n"
+ "ARM_RSTCT1_REG: 0x%-8x \n"
+ "ARM_RSTCT2_REG: 0x%-8x \n"
+ "ARM_SYSST_REG: 0x%-8x \n"
+ "ULPD_IT_STATUS_REG: 0x%-4x \n"
+ "ULPD_CLOCK_CTRL_REG: 0x%-4x \n"
+ "ULPD_SOFT_REQ_REG: 0x%-4x \n"
+ "ULPD_DPLL_CTRL_REG: 0x%-4x \n"
+ "ULPD_STATUS_REQ_REG: 0x%-4x \n"
+ "ULPD_POWER_CTRL_REG: 0x%-4x \n",
+ ARM_SHOW(ARM_CKCTL),
+ ARM_SHOW(ARM_IDLECT1),
+ ARM_SHOW(ARM_IDLECT2),
+ ARM_SHOW(ARM_IDLECT3),
+ ARM_SHOW(ARM_EWUPCT),
+ ARM_SHOW(ARM_RSTCT1),
+ ARM_SHOW(ARM_RSTCT2),
+ ARM_SHOW(ARM_SYSST),
+ ULPD_SHOW(ULPD_IT_STATUS),
+ ULPD_SHOW(ULPD_CLOCK_CTRL),
+ ULPD_SHOW(ULPD_SOFT_REQ),
+ ULPD_SHOW(ULPD_DPLL_CTRL),
+ ULPD_SHOW(ULPD_STATUS_REQ),
+ ULPD_SHOW(ULPD_POWER_CTRL));
+
+ if (cpu_is_omap730()) {
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "MPUI730_CTRL_REG 0x%-8x \n"
+ "MPUI730_DSP_STATUS_REG: 0x%-8x \n"
+ "MPUI730_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+ "MPUI730_DSP_API_CONFIG_REG: 0x%-8x \n"
+ "MPUI730_SDRAM_CONFIG_REG: 0x%-8x \n"
+ "MPUI730_EMIFS_CONFIG_REG: 0x%-8x \n",
+ MPUI730_SHOW(MPUI_CTRL),
+ MPUI730_SHOW(MPUI_DSP_STATUS),
+ MPUI730_SHOW(MPUI_DSP_BOOT_CONFIG),
+ MPUI730_SHOW(MPUI_DSP_API_CONFIG),
+ MPUI730_SHOW(EMIFF_SDRAM_CONFIG),
+ MPUI730_SHOW(EMIFS_CONFIG));
+ } else if (cpu_is_omap15xx()) {
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "MPUI1510_CTRL_REG 0x%-8x \n"
+ "MPUI1510_DSP_STATUS_REG: 0x%-8x \n"
+ "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+ "MPUI1510_DSP_API_CONFIG_REG: 0x%-8x \n"
+ "MPUI1510_SDRAM_CONFIG_REG: 0x%-8x \n"
+ "MPUI1510_EMIFS_CONFIG_REG: 0x%-8x \n",
+ MPUI1510_SHOW(MPUI_CTRL),
+ MPUI1510_SHOW(MPUI_DSP_STATUS),
+ MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG),
+ MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
+ MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
+ MPUI1510_SHOW(EMIFS_CONFIG));
+ } else if (cpu_is_omap16xx()) {
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "MPUI1610_CTRL_REG 0x%-8x \n"
+ "MPUI1610_DSP_STATUS_REG: 0x%-8x \n"
+ "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+ "MPUI1610_DSP_API_CONFIG_REG: 0x%-8x \n"
+ "MPUI1610_SDRAM_CONFIG_REG: 0x%-8x \n"
+ "MPUI1610_EMIFS_CONFIG_REG: 0x%-8x \n",
+ MPUI1610_SHOW(MPUI_CTRL),
+ MPUI1610_SHOW(MPUI_DSP_STATUS),
+ MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG),
+ MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
+ MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
+ MPUI1610_SHOW(EMIFS_CONFIG));
+ }
+
+ g_read_completed++;
+ } else if (g_read_completed >= 1) {
+ *eof = 1;
+ return 0;
+ }
+ g_read_completed++;
+
+ *my_first_byte = page_buffer;
+ return my_buffer_offset;
+}
+
+static void omap_pm_init_proc(void)
+{
+ struct proc_dir_entry *entry;
+
+ entry = create_proc_read_entry("driver/omap_pm",
+ S_IWUSR | S_IRUGO, NULL,
+ omap_pm_read_proc, NULL);
+}
+
+#endif /* DEBUG && CONFIG_PROC_FS */
+
+static void (*saved_idle)(void) = NULL;
+
+/*
+ * omap_pm_prepare - Do preliminary suspend work.
+ * @state: suspend state we're entering.
+ *
+ */
+static int omap_pm_prepare(suspend_state_t state)
+{
+ int error = 0;
+
+ /* We cannot sleep in idle until we have resumed */
+ saved_idle = pm_idle;
+ pm_idle = NULL;
+
+ switch (state)
+ {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ break;
+
+ case PM_SUSPEND_DISK:
+ return -ENOTSUPP;
+
+ default:
+ return -EINVAL;
+ }
+
+ return error;
+}
+
+
+/*
+ * omap_pm_enter - Actually enter a sleep state.
+ * @state: State we're entering.
+ *
+ */
+
+static int omap_pm_enter(suspend_state_t state)
+{
+ switch (state)
+ {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ omap_pm_suspend();
+ break;
+
+ case PM_SUSPEND_DISK:
+ return -ENOTSUPP;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+/**
+ * omap_pm_finish - Finish up suspend sequence.
+ * @state: State we're coming out of.
+ *
+ * This is called after we wake back up (or if entering the sleep state
+ * failed).
+ */
+
+static int omap_pm_finish(suspend_state_t state)
+{
+ pm_idle = saved_idle;
+ return 0;
+}
+
+
+static irqreturn_t omap_wakeup_interrupt(int irq, void * dev,
+ struct pt_regs * regs)
+{
+ return IRQ_HANDLED;
+}
+
+static struct irqaction omap_wakeup_irq = {
+ .name = "peripheral wakeup",
+ .flags = SA_INTERRUPT,
+ .handler = omap_wakeup_interrupt
+};
+
+
+
+static struct pm_ops omap_pm_ops ={
+ .pm_disk_mode = 0,
+ .prepare = omap_pm_prepare,
+ .enter = omap_pm_enter,
+ .finish = omap_pm_finish,
+};
+
+static int __init omap_pm_init(void)
+{
+ printk("Power Management for TI OMAP.\n");
+
+ /*
+ * We copy the assembler sleep/wakeup routines to SRAM.
+ * These routines need to be in SRAM as that's the only
+ * memory the MPU can see when it wakes up.
+ */
+ if (cpu_is_omap730()) {
+ omap_sram_idle = omap_sram_push(omap730_idle_loop_suspend,
+ omap730_idle_loop_suspend_sz);
+ omap_sram_suspend = omap_sram_push(omap730_cpu_suspend,
+ omap730_cpu_suspend_sz);
+ } else if (cpu_is_omap15xx()) {
+ omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
+ omap1510_idle_loop_suspend_sz);
+ omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
+ omap1510_cpu_suspend_sz);
+ } else if (cpu_is_omap16xx()) {
+ omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
+ omap1610_idle_loop_suspend_sz);
+ omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
+ omap1610_cpu_suspend_sz);
+ }
+
+ if (omap_sram_idle == NULL || omap_sram_suspend == NULL) {
+ printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
+ return -ENODEV;
+ }
+
+ pm_idle = omap_pm_idle;
+
+ if (cpu_is_omap730())
+ setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq);
+ else if (cpu_is_omap16xx())
+ setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
+
+ /* Program new power ramp-up time
+ * (0 for most boards since we don't lower voltage when in deep sleep)
+ */
+ omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3);
+
+ /* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */
+ omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL);
+
+ /* Configure IDLECT3 */
+ if (cpu_is_omap730())
+ omap_writel(OMAP730_IDLECT3_VAL, OMAP730_IDLECT3);
+ else if (cpu_is_omap16xx())
+ omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
+
+ pm_set_ops(&omap_pm_ops);
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+ omap_pm_init_proc();
+#endif
+
+ subsys_create_file(&power_subsys, &sleep_while_idle_attr);
+
+ if (cpu_is_omap16xx()) {
+ /* configure LOW_PWR pin */
+ omap_cfg_reg(T20_1610_LOW_PWR);
+ }
+
+ return 0;
+}
+__initcall(omap_pm_init);
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index e924e0c6a4c..9b4cd698bec 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -30,9 +30,9 @@
#include <asm/arch/pm.h>
#endif
-static struct clk * uart1_ck = NULL;
-static struct clk * uart2_ck = NULL;
-static struct clk * uart3_ck = NULL;
+static struct clk * uart1_ck;
+static struct clk * uart2_ck;
+static struct clk * uart3_ck;
static inline unsigned int omap_serial_in(struct plat_serial8250_port *up,
int offset)
diff --git a/arch/arm/plat-omap/sleep.S b/arch/arm/mach-omap1/sleep.S
index 4cd7d292f85..e58295e2d3b 100644
--- a/arch/arm/plat-omap/sleep.S
+++ b/arch/arm/mach-omap1/sleep.S
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/plat-omap/sleep.S
+ * linux/arch/arm/mach-omap1/sleep.S
*
* Low-level OMAP730/1510/1610 sleep/wakeUp support
*
@@ -383,60 +383,133 @@ ENTRY(omap1610_cpu_suspend)
mcr p15, 0, r0, c7, c10, 4
nop
- @ load base address of Traffic Controller
+ @ Load base address of Traffic Controller
mov r6, #TCMIF_ASM_BASE & 0xff000000
orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
- @ prepare to put SDRAM into self-refresh manually
+ @ Prepare to put SDRAM into self-refresh manually
ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
orr r9, r7, #SELF_REFRESH_MODE & 0xff000000
orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff
str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
- @ prepare to put EMIFS to Sleep
+ @ Prepare to put EMIFS to Sleep
ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff
str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
- @ load base address of ARM_IDLECT1 and ARM_IDLECT2
+ @ Load base address of ARM_IDLECT1 and ARM_IDLECT2
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
- @ turn off clock domains
- @ do not disable PERCK (0x04)
+ @ Turn off clock domains
+ @ Do not disable PERCK (0x04)
mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
- @ request ARM idle
+ @ Request ARM idle
mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
- @ disable instruction cache
- mrc p15, 0, r9, c1, c0, 0
- bic r2, r9, #0x1000
- mcr p15, 0, r2, c1, c0, 0
- nop
-
/*
* Let's wait for the next wake up event to wake us up. r0 can't be
* used here because r0 holds ARM_IDLECT1
*/
mov r2, #0
mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
+
+ @ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions
+ @ according to this formula:
+ @ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV
+ @ Max DPLL_MULT = 18
+ @ DPLL_DIV = 1
+ @ ARMDIV = 1
+ @ => 74 nop-instructions
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @10
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @20
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @30
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @40
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @50
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @60
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @70
+ nop
+ nop
+ nop
+ nop @74
/*
* omap1610_cpu_suspend()'s resume point.
*
* It will just start executing here, so we'll restore stuff from the
* stack.
*/
- @ re-enable Icache
- mcr p15, 0, r9, c1, c0, 0
-
- @ reset the ARM_IDLECT1 and ARM_IDLECT2.
+ @ Restore the ARM_IDLECT1 and ARM_IDLECT2.
strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
@@ -444,7 +517,7 @@ ENTRY(omap1610_cpu_suspend)
str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
- @ restore regs and return
+ @ Restore regs and return
ldmfd sp!, {r0 - r12, pc}
ENTRY(omap1610_cpu_suspend_sz)
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index cdbf4d7620c..a85fe6066bc 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -51,8 +51,6 @@
struct sys_timer omap_timer;
-#ifdef CONFIG_OMAP_MPU_TIMER
-
/*
* ---------------------------------------------------------------------------
* MPU timer
@@ -222,195 +220,6 @@ unsigned long long sched_clock(void)
return cycles_2_ns(ticks64);
}
-#endif /* CONFIG_OMAP_MPU_TIMER */
-
-#ifdef CONFIG_OMAP_32K_TIMER
-
-#ifdef CONFIG_ARCH_OMAP15XX
-#error OMAP 32KHz timer does not currently work on 15XX!
-#endif
-
-/*
- * ---------------------------------------------------------------------------
- * 32KHz OS timer
- *
- * This currently works only on 16xx, as 1510 does not have the continuous
- * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
- * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
- * on 1510 would be possible, but the timer would not be as accurate as
- * with the 32KHz synchronized timer.
- * ---------------------------------------------------------------------------
- */
-#define OMAP_32K_TIMER_BASE 0xfffb9000
-#define OMAP_32K_TIMER_CR 0x08
-#define OMAP_32K_TIMER_TVR 0x00
-#define OMAP_32K_TIMER_TCR 0x04
-
-#define OMAP_32K_TICKS_PER_HZ (32768 / HZ)
-
-/*
- * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
- * so with HZ = 100, TVR = 327.68.
- */
-#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1)
-#define TIMER_32K_SYNCHRONIZED 0xfffbc410
-
-#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
- (((nr_jiffies) * (clock_rate)) / HZ)
-
-static inline void omap_32k_timer_write(int val, int reg)
-{
- omap_writew(val, reg + OMAP_32K_TIMER_BASE);
-}
-
-static inline unsigned long omap_32k_timer_read(int reg)
-{
- return omap_readl(reg + OMAP_32K_TIMER_BASE) & 0xffffff;
-}
-
-/*
- * The 32KHz synchronized timer is an additional timer on 16xx.
- * It is always running.
- */
-static inline unsigned long omap_32k_sync_timer_read(void)
-{
- return omap_readl(TIMER_32K_SYNCHRONIZED);
-}
-
-static inline void omap_32k_timer_start(unsigned long load_val)
-{
- omap_32k_timer_write(load_val, OMAP_32K_TIMER_TVR);
- omap_32k_timer_write(0x0f, OMAP_32K_TIMER_CR);
-}
-
-static inline void omap_32k_timer_stop(void)
-{
- omap_32k_timer_write(0x0, OMAP_32K_TIMER_CR);
-}
-
-/*
- * Rounds down to nearest usec. Note that this will overflow for larger values.
- */
-static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
-{
- return (ticks_32k * 5*5*5*5*5*5) >> 9;
-}
-
-/*
- * Rounds down to nearest nsec.
- */
-static inline unsigned long long
-omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
-{
- return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9;
-}
-
-static unsigned long omap_32k_last_tick = 0;
-
-/*
- * Returns elapsed usecs since last 32k timer interrupt
- */
-static unsigned long omap_32k_timer_gettimeoffset(void)
-{
- unsigned long now = omap_32k_sync_timer_read();
- return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
-}
-
-/*
- * Returns current time from boot in nsecs. It's OK for this to wrap
- * around for now, as it's just a relative time stamp.
- */
-unsigned long long sched_clock(void)
-{
- return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
-}
-
-/*
- * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
- * function is also called from other interrupts to remove latency
- * issues with dynamic tick. In the dynamic tick case, we need to lock
- * with irqsave.
- */
-static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
-{
- unsigned long flags;
- unsigned long now;
-
- write_seqlock_irqsave(&xtime_lock, flags);
- now = omap_32k_sync_timer_read();
-
- while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
- omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
- timer_tick(regs);
- }
-
- /* Restart timer so we don't drift off due to modulo or dynamic tick.
- * By default we program the next timer to be continuous to avoid
- * latencies during high system load. During dynamic tick operation the
- * continuous timer can be overridden from pm_idle to be longer.
- */
- omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
- write_sequnlock_irqrestore(&xtime_lock, flags);
-
- return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NO_IDLE_HZ
-/*
- * Programs the next timer interrupt needed. Called when dynamic tick is
- * enabled, and to reprogram the ticks to skip from pm_idle. Note that
- * we can keep the timer continuous, and don't need to set it to run in
- * one-shot mode. This is because the timer will get reprogrammed again
- * after next interrupt.
- */
-void omap_32k_timer_reprogram(unsigned long next_tick)
-{
- omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
-}
-
-static struct irqaction omap_32k_timer_irq;
-extern struct timer_update_handler timer_update;
-
-static int omap_32k_timer_enable_dyn_tick(void)
-{
- /* No need to reprogram timer, just use the next interrupt */
- return 0;
-}
-
-static int omap_32k_timer_disable_dyn_tick(void)
-{
- omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
- return 0;
-}
-
-static struct dyn_tick_timer omap_dyn_tick_timer = {
- .enable = omap_32k_timer_enable_dyn_tick,
- .disable = omap_32k_timer_disable_dyn_tick,
- .reprogram = omap_32k_timer_reprogram,
- .handler = omap_32k_timer_interrupt,
-};
-#endif /* CONFIG_NO_IDLE_HZ */
-
-static struct irqaction omap_32k_timer_irq = {
- .name = "32KHz timer",
- .flags = SA_INTERRUPT | SA_TIMER,
- .handler = omap_32k_timer_interrupt,
-};
-
-static __init void omap_init_32k_timer(void)
-{
-
-#ifdef CONFIG_NO_IDLE_HZ
- omap_timer.dyn_tick = &omap_dyn_tick_timer;
-#endif
-
- setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
- omap_timer.offset = omap_32k_timer_gettimeoffset;
- omap_32k_last_tick = omap_32k_sync_timer_read();
- omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
-}
-#endif /* CONFIG_OMAP_32K_TIMER */
/*
* ---------------------------------------------------------------------------
@@ -419,13 +228,7 @@ static __init void omap_init_32k_timer(void)
*/
static void __init omap_timer_init(void)
{
-#if defined(CONFIG_OMAP_MPU_TIMER)
omap_init_mpu_timer();
-#elif defined(CONFIG_OMAP_32K_TIMER)
- omap_init_32k_timer();
-#else
-#error No system timer selected in Kconfig!
-#endif
}
struct sys_timer omap_timer = {
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 578880943cf..537dd2e6d38 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -20,3 +20,6 @@ config MACH_OMAP_H4
bool "OMAP 2420 H4 board"
depends on ARCH_OMAP2 && ARCH_OMAP24XX
+config MACH_OMAP_APOLLON
+ bool "OMAP 2420 Apollon board"
+ depends on ARCH_OMAP2 && ARCH_OMAP24XX
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 42041166435..111eaa64258 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,11 +3,15 @@
#
# Common support
-obj-y := irq.o id.o io.o sram-fn.o clock.o mux.o devices.o serial.o
+obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o serial.o
obj-$(CONFIG_OMAP_MPU_TIMER) += timer-gp.o
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
# Specific board support
obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o
+obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
new file mode 100644
index 00000000000..6c6ba172cdf
--- /dev/null
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -0,0 +1,285 @@
+/*
+ * linux/arch/arm/mach-omap/omap2/board-apollon.c
+ *
+ * Copyright (C) 2005,2006 Samsung Electronics
+ * Author: Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * Modified from mach-omap/omap2/board-h4.c
+ *
+ * Code for apollon OMAP2 board. Should work on many OMAP2 systems where
+ * the bootloader passes the board-specific data to the kernel.
+ * Do not put any board specific code to this file; create a new machine
+ * type if you need custom low-level initializations.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/onenand.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+#include "prcm-regs.h"
+
+/* LED & Switch macros */
+#define LED0_GPIO13 13
+#define LED1_GPIO14 14
+#define LED2_GPIO15 15
+#define SW_ENTER_GPIO16 16
+#define SW_UP_GPIO17 17
+#define SW_DOWN_GPIO58 58
+
+static struct mtd_partition apollon_partitions[] = {
+ {
+ .name = "X-Loader + U-Boot",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ },
+ {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_16M,
+ },
+ {
+ .name = "filesystem00",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_32M,
+ },
+ {
+ .name = "filesystem01",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data apollon_flash_data = {
+ .parts = apollon_partitions,
+ .nr_parts = ARRAY_SIZE(apollon_partitions),
+};
+
+static struct resource apollon_flash_resource = {
+ .start = APOLLON_CS0_BASE,
+ .end = APOLLON_CS0_BASE + SZ_128K,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device apollon_onenand_device = {
+ .name = "onenand",
+ .id = -1,
+ .dev = {
+ .platform_data = &apollon_flash_data,
+ },
+ .num_resources = ARRAY_SIZE(&apollon_flash_resource),
+ .resource = &apollon_flash_resource,
+};
+
+static struct resource apollon_smc91x_resources[] = {
+ [0] = {
+ .start = APOLLON_ETHR_START, /* Physical */
+ .end = APOLLON_ETHR_START + 0xf,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
+ .end = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device apollon_smc91x_device = {
+ .name = "smc91x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(apollon_smc91x_resources),
+ .resource = apollon_smc91x_resources,
+};
+
+static struct platform_device apollon_lcd_device = {
+ .name = "apollon_lcd",
+ .id = -1,
+};
+
+static struct platform_device *apollon_devices[] __initdata = {
+ &apollon_onenand_device,
+ &apollon_smc91x_device,
+ &apollon_lcd_device,
+};
+
+static inline void __init apollon_init_smc91x(void)
+{
+ /* Make sure CS1 timings are correct */
+ GPMC_CONFIG1_1 = 0x00011203;
+ GPMC_CONFIG2_1 = 0x001f1f01;
+ GPMC_CONFIG3_1 = 0x00080803;
+ GPMC_CONFIG4_1 = 0x1c091c09;
+ GPMC_CONFIG5_1 = 0x041f1f1f;
+ GPMC_CONFIG6_1 = 0x000004c4;
+ GPMC_CONFIG7_1 = 0x00000f40 | (APOLLON_CS1_BASE >> 24);
+ udelay(100);
+
+ omap_cfg_reg(W4__24XX_GPIO74);
+ if (omap_request_gpio(APOLLON_ETHR_GPIO_IRQ) < 0) {
+ printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
+ APOLLON_ETHR_GPIO_IRQ);
+ return;
+ }
+ omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1);
+}
+
+static void __init omap_apollon_init_irq(void)
+{
+ omap2_init_common_hw();
+ omap_init_irq();
+ omap_gpio_init();
+ apollon_init_smc91x();
+}
+
+static struct omap_uart_config apollon_uart_config __initdata = {
+ .enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2),
+};
+
+static struct omap_mmc_config apollon_mmc_config __initdata = {
+ .mmc [0] = {
+ .enabled = 0,
+ .wire4 = 0,
+ .wp_pin = -1,
+ .power_pin = -1,
+ .switch_pin = -1,
+ },
+};
+
+static struct omap_lcd_config apollon_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_board_config_kernel apollon_config[] = {
+ { OMAP_TAG_UART, &apollon_uart_config },
+ { OMAP_TAG_MMC, &apollon_mmc_config },
+ { OMAP_TAG_LCD, &apollon_lcd_config },
+};
+
+static void __init apollon_led_init(void)
+{
+ /* LED0 - AA10 */
+ omap_cfg_reg(AA10_242X_GPIO13);
+ omap_request_gpio(LED0_GPIO13);
+ omap_set_gpio_direction(LED0_GPIO13, 0);
+ omap_set_gpio_dataout(LED0_GPIO13, 0);
+ /* LED1 - AA6 */
+ omap_cfg_reg(AA6_242X_GPIO14);
+ omap_request_gpio(LED1_GPIO14);
+ omap_set_gpio_direction(LED1_GPIO14, 0);
+ omap_set_gpio_dataout(LED1_GPIO14, 0);
+ /* LED2 - AA4 */
+ omap_cfg_reg(AA4_242X_GPIO15);
+ omap_request_gpio(LED2_GPIO15);
+ omap_set_gpio_direction(LED2_GPIO15, 0);
+ omap_set_gpio_dataout(LED2_GPIO15, 0);
+}
+
+static irqreturn_t apollon_sw_interrupt(int irq, void *ignored, struct pt_regs *regs)
+{
+ static unsigned int led0, led1, led2;
+
+ if (irq == OMAP_GPIO_IRQ(SW_ENTER_GPIO16))
+ omap_set_gpio_dataout(LED0_GPIO13, led0 ^= 1);
+ else if (irq == OMAP_GPIO_IRQ(SW_UP_GPIO17))
+ omap_set_gpio_dataout(LED1_GPIO14, led1 ^= 1);
+ else if (irq == OMAP_GPIO_IRQ(SW_DOWN_GPIO58))
+ omap_set_gpio_dataout(LED2_GPIO15, led2 ^= 1);
+
+ return IRQ_HANDLED;
+}
+
+static void __init apollon_sw_init(void)
+{
+ /* Enter SW - Y11 */
+ omap_cfg_reg(Y11_242X_GPIO16);
+ omap_request_gpio(SW_ENTER_GPIO16);
+ omap_set_gpio_direction(SW_ENTER_GPIO16, 1);
+ /* Up SW - AA12 */
+ omap_cfg_reg(AA12_242X_GPIO17);
+ omap_request_gpio(SW_UP_GPIO17);
+ omap_set_gpio_direction(SW_UP_GPIO17, 1);
+ /* Down SW - AA8 */
+ omap_cfg_reg(AA8_242X_GPIO58);
+ omap_request_gpio(SW_DOWN_GPIO58);
+ omap_set_gpio_direction(SW_DOWN_GPIO58, 1);
+
+ set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQT_RISING);
+ if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt,
+ SA_SHIRQ, "enter sw",
+ &apollon_sw_interrupt))
+ return;
+ set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQT_RISING);
+ if (request_irq(OMAP_GPIO_IRQ(SW_UP_GPIO17), &apollon_sw_interrupt,
+ SA_SHIRQ, "up sw",
+ &apollon_sw_interrupt))
+ return;
+ set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQT_RISING);
+ if (request_irq(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), &apollon_sw_interrupt,
+ SA_SHIRQ, "down sw",
+ &apollon_sw_interrupt))
+ return;
+}
+
+static void __init omap_apollon_init(void)
+{
+ apollon_led_init();
+ apollon_sw_init();
+
+ /* REVISIT: where's the correct place */
+ omap_cfg_reg(W19_24XX_SYS_NIRQ);
+
+ /*
+ * Make sure the serial ports are muxed on at this point.
+ * You have to mux them off in device drivers later on
+ * if not needed.
+ */
+ platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
+ omap_board_config = apollon_config;
+ omap_board_config_size = ARRAY_SIZE(apollon_config);
+ omap_serial_init();
+}
+
+static void __init omap_apollon_map_io(void)
+{
+ omap2_map_common_io();
+}
+
+MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
+ /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+ .phys_io = 0x48000000,
+ .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
+ .boot_params = 0x80000100,
+ .map_io = omap_apollon_map_io,
+ .init_irq = omap_apollon_init_irq,
+ .init_machine = omap_apollon_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index a300d634d8a..4933fce766c 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -17,6 +17,8 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -25,15 +27,57 @@
#include <asm/mach/flash.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/gpioexpander.h>
#include <asm/arch/mux.h>
#include <asm/arch/usb.h>
+#include <asm/arch/irda.h>
#include <asm/arch/board.h>
#include <asm/arch/common.h>
-#include <asm/arch/prcm.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/menelaus.h>
+#include <asm/arch/dma.h>
+#include "prcm-regs.h"
#include <asm/io.h>
#include <asm/delay.h>
+static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
+static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
+
+static int h4_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(0, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_A),
+ KEY(0, 3, KEY_B),
+ KEY(0, 4, KEY_C),
+ KEY(1, 0, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(1, 2, KEY_E),
+ KEY(1, 3, KEY_F),
+ KEY(1, 4, KEY_G),
+ KEY(2, 0, KEY_ENTER),
+ KEY(2, 1, KEY_I),
+ KEY(2, 2, KEY_J),
+ KEY(2, 3, KEY_K),
+ KEY(2, 4, KEY_3),
+ KEY(3, 0, KEY_M),
+ KEY(3, 1, KEY_N),
+ KEY(3, 2, KEY_O),
+ KEY(3, 3, KEY_P),
+ KEY(3, 4, KEY_Q),
+ KEY(4, 0, KEY_R),
+ KEY(4, 1, KEY_4),
+ KEY(4, 2, KEY_T),
+ KEY(4, 3, KEY_U),
+ KEY(4, 4, KEY_ENTER),
+ KEY(5, 0, KEY_V),
+ KEY(5, 1, KEY_W),
+ KEY(5, 2, KEY_L),
+ KEY(5, 3, KEY_S),
+ KEY(5, 4, KEY_ENTER),
+ 0
+};
+
static struct mtd_partition h4_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
@@ -108,9 +152,123 @@ static struct platform_device h4_smc91x_device = {
.resource = h4_smc91x_resources,
};
+/* Select between the IrDA and aGPS module
+ */
+static int h4_select_irda(struct device *dev, int state)
+{
+ unsigned char expa;
+ int err = 0;
+
+ if ((err = read_gpio_expa(&expa, 0x21))) {
+ printk(KERN_ERR "Error reading from I/O expander\n");
+ return err;
+ }
+
+ /* 'P6' enable/disable IRDA_TX and IRDA_RX */
+ if (state & IR_SEL) { /* IrDa */
+ if ((err = write_gpio_expa(expa | 0x01, 0x21))) {
+ printk(KERN_ERR "Error writing to I/O expander\n");
+ return err;
+ }
+ } else {
+ if ((err = write_gpio_expa(expa & ~0x01, 0x21))) {
+ printk(KERN_ERR "Error writing to I/O expander\n");
+ return err;
+ }
+ }
+ return err;
+}
+
+static void set_trans_mode(void *data)
+{
+ int *mode = data;
+ unsigned char expa;
+ int err = 0;
+
+ if ((err = read_gpio_expa(&expa, 0x20)) != 0) {
+ printk(KERN_ERR "Error reading from I/O expander\n");
+ }
+
+ expa &= ~0x01;
+
+ if (!(*mode & IR_SIRMODE)) { /* MIR/FIR */
+ expa |= 0x01;
+ }
+
+ if ((err = write_gpio_expa(expa, 0x20)) != 0) {
+ printk(KERN_ERR "Error writing to I/O expander\n");
+ }
+}
+
+static int h4_transceiver_mode(struct device *dev, int mode)
+{
+ struct omap_irda_config *irda_config = dev->platform_data;
+
+ cancel_delayed_work(&irda_config->gpio_expa);
+ PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
+ schedule_work(&irda_config->gpio_expa);
+
+ return 0;
+}
+
+static struct omap_irda_config h4_irda_data = {
+ .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+ .transceiver_mode = h4_transceiver_mode,
+ .select_irda = h4_select_irda,
+ .rx_channel = OMAP24XX_DMA_UART3_RX,
+ .tx_channel = OMAP24XX_DMA_UART3_TX,
+ .dest_start = OMAP_UART3_BASE,
+ .src_start = OMAP_UART3_BASE,
+ .tx_trigger = OMAP24XX_DMA_UART3_TX,
+ .rx_trigger = OMAP24XX_DMA_UART3_RX,
+};
+
+static struct resource h4_irda_resources[] = {
+ [0] = {
+ .start = INT_24XX_UART3_IRQ,
+ .end = INT_24XX_UART3_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device h4_irda_device = {
+ .name = "omapirda",
+ .id = -1,
+ .dev = {
+ .platform_data = &h4_irda_data,
+ },
+ .num_resources = 1,
+ .resource = h4_irda_resources,
+};
+
+static struct omap_kp_platform_data h4_kp_data = {
+ .rows = 6,
+ .cols = 7,
+ .keymap = h4_keymap,
+ .rep = 1,
+ .row_gpios = row_gpios,
+ .col_gpios = col_gpios,
+};
+
+static struct platform_device h4_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &h4_kp_data,
+ },
+};
+
+static struct platform_device h4_lcd_device = {
+ .name = "lcd_h4",
+ .id = -1,
+};
+
static struct platform_device *h4_devices[] __initdata = {
&h4_smc91x_device,
&h4_flash_device,
+ &h4_irda_device,
+ &h4_kp_device,
+ &h4_lcd_device,
};
static inline void __init h4_init_smc91x(void)
@@ -157,7 +315,6 @@ static struct omap_mmc_config h4_mmc_config __initdata = {
};
static struct omap_lcd_config h4_lcd_config __initdata = {
- .panel_name = "h4",
.ctrl_name = "internal",
};
@@ -174,6 +331,19 @@ static void __init omap_h4_init(void)
* You have to mux them off in device drivers later on
* if not needed.
*/
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+ omap_cfg_reg(K15_24XX_UART3_TX);
+ omap_cfg_reg(K14_24XX_UART3_RX);
+#endif
+
+#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+ if (omap_has_menelaus()) {
+ row_gpios[5] = 0;
+ col_gpios[2] = 15;
+ col_gpios[6] = 18;
+ }
+#endif
+
platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
omap_board_config = h4_config;
omap_board_config_size = ARRAY_SIZE(h4_config);
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 180f675c906..72eb4bf571a 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -28,14 +28,14 @@
#include <asm/arch/clock.h>
#include <asm/arch/sram.h>
-#include <asm/arch/prcm.h>
+#include "prcm-regs.h"
+#include "memory.h"
#include "clock.h"
//#define DOWN_VARIABLE_DPLL 1 /* Experimental */
static struct prcm_config *curr_prcm_set;
-static struct memory_timings mem_timings;
static u32 curr_perf_level = PRCM_FULL_SPEED;
/*-------------------------------------------------------------------------
@@ -54,11 +54,13 @@ static void omap2_sys_clk_recalc(struct clk * clk)
static u32 omap2_get_dpll_rate(struct clk * tclk)
{
- int dpll_clk, dpll_mult, dpll_div, amult;
+ long long dpll_clk;
+ int dpll_mult, dpll_div, amult;
dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff; /* 10 bits */
dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f; /* 4 bits */
- dpll_clk = (tclk->parent->rate * dpll_mult) / (dpll_div + 1);
+ dpll_clk = (long long)tclk->parent->rate * dpll_mult;
+ do_div(dpll_clk, dpll_div + 1);
amult = CM_CLKSEL2_PLL & 0x3;
dpll_clk *= amult;
@@ -385,75 +387,23 @@ static u32 omap2_dll_force_needed(void)
return 0;
}
-static void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
-{
- unsigned long dll_cnt;
- u32 fast_dll = 0;
-
- mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
-
- /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
- * In the case of 2422, its ok to use CS1 instead of CS0.
- */
-
-#if 0 /* FIXME: Enable after 24xx cpu detection works */
- ctype = get_cpu_type();
- if (cpu_is_omap2422())
- mem_timings.base_cs = 1;
- else
-#endif
- mem_timings.base_cs = 0;
-
- if (mem_timings.m_type != M_DDR)
- return;
-
- /* With DDR we need to determine the low frequency DLL value */
- if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL))
- mem_timings.dll_mode = M_UNLOCK;
- else
- mem_timings.dll_mode = M_LOCK;
-
- if (mem_timings.base_cs == 0) {
- fast_dll = SDRC_DLLA_CTRL;
- dll_cnt = SDRC_DLLA_STATUS & 0xff00;
- } else {
- fast_dll = SDRC_DLLB_CTRL;
- dll_cnt = SDRC_DLLB_STATUS & 0xff00;
- }
- if (force_lock_to_unlock_mode) {
- fast_dll &= ~0xff00;
- fast_dll |= dll_cnt; /* Current lock mode */
- }
- mem_timings.fast_dll_ctrl = fast_dll;
-
- /* No disruptions, DDR will be offline & C-ABI not followed */
- omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl,
- mem_timings.fast_dll_ctrl,
- mem_timings.base_cs,
- force_lock_to_unlock_mode);
- mem_timings.slow_dll_ctrl &= 0xff00; /* Keep lock value */
-
- /* Turn status into unlock ctrl */
- mem_timings.slow_dll_ctrl |=
- ((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2));
-
- /* 90 degree phase for anything below 133Mhz */
- mem_timings.slow_dll_ctrl |= (1 << 1);
-}
-
static u32 omap2_reprogram_sdrc(u32 level, u32 force)
{
+ u32 slow_dll_ctrl, fast_dll_ctrl, m_type;
u32 prev = curr_perf_level, flags;
if ((curr_perf_level == level) && !force)
return prev;
+ m_type = omap2_memory_get_type();
+ slow_dll_ctrl = omap2_memory_get_slow_dll_ctrl();
+ fast_dll_ctrl = omap2_memory_get_fast_dll_ctrl();
+
if (level == PRCM_HALF_SPEED) {
local_irq_save(flags);
PRCM_VOLTSETUP = 0xffff;
omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED,
- mem_timings.slow_dll_ctrl,
- mem_timings.m_type);
+ slow_dll_ctrl, m_type);
curr_perf_level = PRCM_HALF_SPEED;
local_irq_restore(flags);
}
@@ -461,8 +411,7 @@ static u32 omap2_reprogram_sdrc(u32 level, u32 force)
local_irq_save(flags);
PRCM_VOLTSETUP = 0xffff;
omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED,
- mem_timings.fast_dll_ctrl,
- mem_timings.m_type);
+ fast_dll_ctrl, m_type);
curr_perf_level = PRCM_FULL_SPEED;
local_irq_restore(flags);
}
@@ -650,7 +599,7 @@ static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask,
case 13: /* dss2 */
mask = 0x1; break;
case 25: /* usb */
- mask = 0xf; break;
+ mask = 0x7; break;
}
}
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 6cab20b1d3c..6c78d471fab 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -33,20 +33,6 @@ static u32 omap2_clksel_get_divisor(struct clk *clk);
#define RATE_IN_242X (1 << 0)
#define RATE_IN_243X (1 << 1)
-/* Memory timings */
-#define M_DDR 1
-#define M_LOCK_CTRL (1 << 2)
-#define M_UNLOCK 0
-#define M_LOCK 1
-
-struct memory_timings {
- u32 m_type; /* ddr = 1, sdr = 0 */
- u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */
- u32 slow_dll_ctrl; /* unlock mode, dll value for slow speed */
- u32 fast_dll_ctrl; /* unlock mode, dll value for fast speed */
- u32 base_cs; /* base chip select to use for calculations */
-};
-
/* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
* xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
* CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM
@@ -731,6 +717,16 @@ static struct clk sys_clkout2 = {
.recalc = &omap2_clksel_recalc,
};
+static struct clk emul_ck = {
+ .name = "emul_ck",
+ .parent = &func_54m_ck,
+ .flags = CLOCK_IN_OMAP242X,
+ .enable_reg = (void __iomem *)&PRCM_CLKEMUL_CTRL,
+ .enable_bit = 0,
+ .recalc = &omap2_propagate_rate,
+
+};
+
/*
* MPU clock domain
* Clocks:
@@ -1702,7 +1698,8 @@ static struct clk hdq_fck = {
};
static struct clk i2c2_ick = {
- .name = "i2c2_ick",
+ .name = "i2c_ick",
+ .id = 2,
.parent = &l4_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1711,7 +1708,8 @@ static struct clk i2c2_ick = {
};
static struct clk i2c2_fck = {
- .name = "i2c2_fck",
+ .name = "i2c_fck",
+ .id = 2,
.parent = &func_12m_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1729,7 +1727,8 @@ static struct clk i2chs2_fck = {
};
static struct clk i2c1_ick = {
- .name = "i2c1_ick",
+ .name = "i2c_ick",
+ .id = 1,
.parent = &l4_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1738,7 +1737,8 @@ static struct clk i2c1_ick = {
};
static struct clk i2c1_fck = {
- .name = "i2c1_fck",
+ .name = "i2c_fck",
+ .id = 1,
.parent = &func_12m_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1971,6 +1971,7 @@ static struct clk *onchip_clks[] = {
&wdt1_osc_ck,
&sys_clkout,
&sys_clkout2,
+ &emul_ck,
/* mpu domain clocks */
&mpu_ck,
/* dsp domain clocks */
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 7181edb8935..fb7f91da1aa 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -25,10 +25,6 @@
#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
-extern void omap_nop_release(struct device *dev);
-
-/*-------------------------------------------------------------------------*/
-
#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
#define OMAP2_I2C_BASE2 0x48072000
@@ -49,9 +45,6 @@ static struct resource i2c_resources2[] = {
static struct platform_device omap_i2c_device2 = {
.name = "i2c_omap",
.id = 2,
- .dev = {
- .release = omap_nop_release,
- },
.num_resources = ARRAY_SIZE(i2c_resources2),
.resource = i2c_resources2,
};
@@ -74,6 +67,44 @@ static void omap_init_i2c(void) {}
#endif
+#if defined(CONFIG_OMAP_STI)
+
+#define OMAP2_STI_BASE IO_ADDRESS(0x48068000)
+#define OMAP2_STI_CHANNEL_BASE 0x54000000
+#define OMAP2_STI_IRQ 4
+
+static struct resource sti_resources[] = {
+ {
+ .start = OMAP2_STI_BASE,
+ .end = OMAP2_STI_BASE + 0x7ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = OMAP2_STI_CHANNEL_BASE,
+ .end = OMAP2_STI_CHANNEL_BASE + SZ_64K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = OMAP2_STI_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device sti_device = {
+ .name = "sti",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(sti_resources),
+ .resource = sti_resources,
+};
+
+static inline void omap_init_sti(void)
+{
+ platform_device_register(&sti_device);
+}
+#else
+static inline void omap_init_sti(void) {}
+#endif
+
/*-------------------------------------------------------------------------*/
static int __init omap2_init_devices(void)
@@ -82,6 +113,7 @@ static int __init omap2_init_devices(void)
* in alphabetical order so they're easier to sort through.
*/
omap_init_i2c();
+ omap_init_sti();
return 0;
}
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 8ea67bf196a..7d5711611f2 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -16,9 +16,13 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <asm/mach/map.h>
+#include <asm/tlb.h>
#include <asm/io.h>
+
+#include <asm/mach/map.h>
+
#include <asm/arch/mux.h>
+#include <asm/arch/omapfb.h>
extern void omap_sram_init(void);
extern int omap2_clk_init(void);
@@ -43,11 +47,24 @@ static struct map_desc omap2_io_desc[] __initdata = {
}
};
-void __init omap_map_common_io(void)
+void __init omap2_map_common_io(void)
{
iotable_init(omap2_io_desc, ARRAY_SIZE(omap2_io_desc));
+
+ /* Normally devicemaps_init() would flush caches and tlb after
+ * mdesc->map_io(), but we must also do it here because of the CPU
+ * revision check below.
+ */
+ local_flush_tlb_all();
+ flush_cache_all();
+
omap2_check_revision();
omap_sram_init();
+ omapfb_reserve_mem();
+}
+
+void __init omap2_init_common_hw(void)
+{
omap2_mux_init();
omap2_clk_init();
}
diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/memory.c
new file mode 100644
index 00000000000..1d925d69fc3
--- /dev/null
+++ b/arch/arm/mach-omap2/memory.c
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/arm/mach-omap2/memory.c
+ *
+ * Memory timing related functions for OMAP24XX
+ *
+ * Copyright (C) 2005 Texas Instruments Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Tony Lindgren <tony@atomide.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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+
+#include "prcm-regs.h"
+#include "memory.h"
+
+static struct memory_timings mem_timings;
+
+u32 omap2_memory_get_slow_dll_ctrl(void)
+{
+ return mem_timings.slow_dll_ctrl;
+}
+
+u32 omap2_memory_get_fast_dll_ctrl(void)
+{
+ return mem_timings.fast_dll_ctrl;
+}
+
+u32 omap2_memory_get_type(void)
+{
+ return mem_timings.m_type;
+}
+
+void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+{
+ unsigned long dll_cnt;
+ u32 fast_dll = 0;
+
+ mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
+
+ /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
+ * In the case of 2422, its ok to use CS1 instead of CS0.
+ */
+ if (cpu_is_omap2422())
+ mem_timings.base_cs = 1;
+ else
+ mem_timings.base_cs = 0;
+
+ if (mem_timings.m_type != M_DDR)
+ return;
+
+ /* With DDR we need to determine the low frequency DLL value */
+ if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL))
+ mem_timings.dll_mode = M_UNLOCK;
+ else
+ mem_timings.dll_mode = M_LOCK;
+
+ if (mem_timings.base_cs == 0) {
+ fast_dll = SDRC_DLLA_CTRL;
+ dll_cnt = SDRC_DLLA_STATUS & 0xff00;
+ } else {
+ fast_dll = SDRC_DLLB_CTRL;
+ dll_cnt = SDRC_DLLB_STATUS & 0xff00;
+ }
+ if (force_lock_to_unlock_mode) {
+ fast_dll &= ~0xff00;
+ fast_dll |= dll_cnt; /* Current lock mode */
+ }
+ /* set fast timings with DLL filter disabled */
+ mem_timings.fast_dll_ctrl = (fast_dll | (3 << 8));
+
+ /* No disruptions, DDR will be offline & C-ABI not followed */
+ omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl,
+ mem_timings.fast_dll_ctrl,
+ mem_timings.base_cs,
+ force_lock_to_unlock_mode);
+ mem_timings.slow_dll_ctrl &= 0xff00; /* Keep lock value */
+
+ /* Turn status into unlock ctrl */
+ mem_timings.slow_dll_ctrl |=
+ ((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2));
+
+ /* 90 degree phase for anything below 133Mhz + disable DLL filter */
+ mem_timings.slow_dll_ctrl |= ((1 << 1) | (3 << 8));
+}
diff --git a/arch/arm/mach-omap2/memory.h b/arch/arm/mach-omap2/memory.h
new file mode 100644
index 00000000000..d212eea83a0
--- /dev/null
+++ b/arch/arm/mach-omap2/memory.h
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/arm/mach-omap2/memory.h
+ *
+ * Interface for memory timing related functions for OMAP24XX
+ *
+ * Copyright (C) 2005 Texas Instruments Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Tony Lindgren <tony@atomide.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.
+ */
+
+/* Memory timings */
+#define M_DDR 1
+#define M_LOCK_CTRL (1 << 2)
+#define M_UNLOCK 0
+#define M_LOCK 1
+
+struct memory_timings {
+ u32 m_type; /* ddr = 1, sdr = 0 */
+ u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */
+ u32 slow_dll_ctrl; /* unlock mode, dll value for slow speed */
+ u32 fast_dll_ctrl; /* unlock mode, dll value for fast speed */
+ u32 base_cs; /* base chip select to use for calculations */
+};
+
+extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode);
+extern u32 omap2_memory_get_slow_dll_ctrl(void);
+extern u32 omap2_memory_get_fast_dll_ctrl(void);
+extern u32 omap2_memory_get_type(void);
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index ea4654815dd..1197dc38c20 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -50,9 +50,54 @@ MUX_CFG_24XX("H19_24XX_I2C2_SDA", 0x114, 0, 0, 0, 1)
/* Menelaus interrupt */
MUX_CFG_24XX("W19_24XX_SYS_NIRQ", 0x12c, 0, 1, 1, 1)
+/* 24xx clocks */
+MUX_CFG_24XX("W14_24XX_SYS_CLKOUT", 0x137, 0, 1, 1, 1)
+
+/* 24xx McBSP */
+MUX_CFG_24XX("Y15_24XX_MCBSP2_CLKX", 0x124, 1, 1, 0, 1)
+MUX_CFG_24XX("R14_24XX_MCBSP2_FSX", 0x125, 1, 1, 0, 1)
+MUX_CFG_24XX("W15_24XX_MCBSP2_DR", 0x126, 1, 1, 0, 1)
+MUX_CFG_24XX("V15_24XX_MCBSP2_DX", 0x127, 1, 1, 0, 1)
+
/* 24xx GPIO */
+MUX_CFG_24XX("M21_242X_GPIO11", 0x0c9, 3, 1, 1, 1)
+MUX_CFG_24XX("AA10_242X_GPIO13", 0x0e5, 3, 0, 0, 1)
+MUX_CFG_24XX("AA6_242X_GPIO14", 0x0e6, 3, 0, 0, 1)
+MUX_CFG_24XX("AA4_242X_GPIO15", 0x0e7, 3, 0, 0, 1)
+MUX_CFG_24XX("Y11_242X_GPIO16", 0x0e8, 3, 0, 0, 1)
+MUX_CFG_24XX("AA12_242X_GPIO17", 0x0e9, 3, 0, 0, 1)
+MUX_CFG_24XX("AA8_242X_GPIO58", 0x0ea, 3, 0, 0, 1)
MUX_CFG_24XX("Y20_24XX_GPIO60", 0x12c, 3, 0, 0, 1)
+MUX_CFG_24XX("W4__24XX_GPIO74", 0x0f2, 3, 0, 0, 1)
MUX_CFG_24XX("M15_24XX_GPIO92", 0x10a, 3, 0, 0, 1)
+MUX_CFG_24XX("V14_24XX_GPIO117", 0x128, 3, 1, 0, 1)
+
+/* TSC IRQ */
+MUX_CFG_24XX("P20_24XX_TSC_IRQ", 0x108, 0, 0, 0, 1)
+
+/* UART3 */
+MUX_CFG_24XX("K15_24XX_UART3_TX", 0x118, 0, 0, 0, 1)
+MUX_CFG_24XX("K14_24XX_UART3_RX", 0x119, 0, 0, 0, 1)
+
+/* Keypad GPIO*/
+MUX_CFG_24XX("T19_24XX_KBR0", 0x106, 3, 1, 1, 1)
+MUX_CFG_24XX("R19_24XX_KBR1", 0x107, 3, 1, 1, 1)
+MUX_CFG_24XX("V18_24XX_KBR2", 0x139, 3, 1, 1, 1)
+MUX_CFG_24XX("M21_24XX_KBR3", 0xc9, 3, 1, 1, 1)
+MUX_CFG_24XX("E5__24XX_KBR4", 0x138, 3, 1, 1, 1)
+MUX_CFG_24XX("M18_24XX_KBR5", 0x10e, 3, 1, 1, 1)
+MUX_CFG_24XX("R20_24XX_KBC0", 0x108, 3, 0, 0, 1)
+MUX_CFG_24XX("M14_24XX_KBC1", 0x109, 3, 0, 0, 1)
+MUX_CFG_24XX("H19_24XX_KBC2", 0x114, 3, 0, 0, 1)
+MUX_CFG_24XX("V17_24XX_KBC3", 0x135, 3, 0, 0, 1)
+MUX_CFG_24XX("P21_24XX_KBC4", 0xca, 3, 0, 0, 1)
+MUX_CFG_24XX("L14_24XX_KBC5", 0x10f, 3, 0, 0, 1)
+MUX_CFG_24XX("N19_24XX_KBC6", 0x110, 3, 0, 0, 1)
+
+/* 24xx Menelaus Keypad GPIO */
+MUX_CFG_24XX("B3__24XX_KBR5", 0x30, 3, 1, 1, 1)
+MUX_CFG_24XX("AA4_24XX_KBC2", 0xe7, 3, 0, 0, 1)
+MUX_CFG_24XX("B13_24XX_KBC6", 0x110, 3, 0, 0, 1)
};
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
new file mode 100644
index 00000000000..562168fa2b1
--- /dev/null
+++ b/arch/arm/mach-omap2/pm.c
@@ -0,0 +1,149 @@
+/*
+ * linux/arch/arm/mach-omap2/pm.c
+ *
+ * OMAP2 Power Management Routines
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Based on pm.c for omap1
+ *
+ * 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/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/pm.h>
+
+static struct clk *vclk;
+static void (*omap2_sram_idle)(void);
+static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
+static void (*saved_idle)(void);
+
+void omap2_pm_idle(void)
+{
+ local_irq_disable();
+ local_fiq_disable();
+ if (need_resched()) {
+ local_fiq_enable();
+ local_irq_enable();
+ return;
+ }
+
+ /*
+ * Since an interrupt may set up a timer, we don't want to
+ * reprogram the hardware timer with interrupts enabled.
+ * Re-enable interrupts only after returning from idle.
+ */
+ timer_dyn_reprogram();
+
+ omap2_sram_idle();
+ local_fiq_enable();
+ local_irq_enable();
+}
+
+static int omap2_pm_prepare(suspend_state_t state)
+{
+ int error = 0;
+
+ /* We cannot sleep in idle until we have resumed */
+ saved_idle = pm_idle;
+ pm_idle = NULL;
+
+ switch (state)
+ {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ break;
+
+ case PM_SUSPEND_DISK:
+ return -ENOTSUPP;
+
+ default:
+ return -EINVAL;
+ }
+
+ return error;
+}
+
+static int omap2_pm_enter(suspend_state_t state)
+{
+ switch (state)
+ {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ /* FIXME: Add suspend */
+ break;
+
+ case PM_SUSPEND_DISK:
+ return -ENOTSUPP;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int omap2_pm_finish(suspend_state_t state)
+{
+ pm_idle = saved_idle;
+ return 0;
+}
+
+static struct pm_ops omap_pm_ops = {
+ .pm_disk_mode = 0,
+ .prepare = omap2_pm_prepare,
+ .enter = omap2_pm_enter,
+ .finish = omap2_pm_finish,
+};
+
+int __init omap2_pm_init(void)
+{
+ printk("Power Management for TI OMAP.\n");
+
+ vclk = clk_get(NULL, "virt_prcm_set");
+ if (IS_ERR(vclk)) {
+ printk(KERN_ERR "Could not get PM vclk\n");
+ return -ENODEV;
+ }
+
+ /*
+ * We copy the assembler sleep/wakeup routines to SRAM.
+ * These routines need to be in SRAM as that's the only
+ * memory the MPU can see when it wakes up.
+ */
+ omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
+ omap24xx_idle_loop_suspend_sz);
+
+ omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
+ omap24xx_cpu_suspend_sz);
+
+ pm_set_ops(&omap_pm_ops);
+ pm_idle = omap2_pm_idle;
+
+ return 0;
+}
+
+__initcall(omap2_pm_init);
diff --git a/arch/arm/mach-omap2/prcm.h b/arch/arm/mach-omap2/prcm-regs.h
index 2eb89b936c8..22ac7be4f78 100644
--- a/arch/arm/mach-omap2/prcm.h
+++ b/arch/arm/mach-omap2/prcm-regs.h
@@ -1,5 +1,7 @@
/*
- * prcm.h - Access definations for use in OMAP24XX clock and power management
+ * linux/arch/arm/mach-omap2/prcm-reg.h
+ *
+ * OMAP24XX Power Reset and Clock Management (PRCM) registers
*
* Copyright (C) 2005 Texas Instruments, Inc.
*
@@ -18,8 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __ASM_ARM_ARCH_DPM_PRCM_H
-#define __ASM_ARM_ARCH_DPM_PRCM_H
+#ifndef __ARCH_ARM_MACH_OMAP2_PRCM_H
+#define __ARCH_ARM_MACH_OMAP2_PRCM_H
/* SET_PERFORMANCE_LEVEL PARAMETERS */
#define PRCM_HALF_SPEED 1
@@ -159,54 +161,63 @@
#define CM_FCLKEN_MDM PRCM_REG32(0xC00)
#define CM_ICLKEN_MDM PRCM_REG32(0xC10)
#define CM_IDLEST_MDM PRCM_REG32(0xC20)
+#define CM_AUTOIDLE_MDM PRCM_REG32(0xC30)
#define CM_CLKSEL_MDM PRCM_REG32(0xC40)
-
-/* FIXME: Move to header for 2430 */
-#define DISP_BASE (OMAP24XX_L4_IO_BASE+0x50000)
+#define CM_CLKSTCTRL_MDM PRCM_REG32(0xC48)
+#define RM_RSTCTRL_MDM PRCM_REG32(0xC50)
+#define RM_RSTST_MDM PRCM_REG32(0xC58)
+#define PM_WKEN_MDM PRCM_REG32(0xCA0)
+#define PM_WKST_MDM PRCM_REG32(0xCB0)
+#define PM_WKDEP_MDM PRCM_REG32(0xCC8)
+#define PM_PWSTCTRL_MDM PRCM_REG32(0xCE0)
+#define PM_PWSTST_MDM PRCM_REG32(0xCE4)
+
+#define OMAP24XX_L4_IO_BASE 0x48000000
+
+#define DISP_BASE (OMAP24XX_L4_IO_BASE + 0x50000)
#define DISP_REG32(offset) __REG32(DISP_BASE + (offset))
-#define GPMC_BASE (OMAP24XX_GPMC_BASE)
-#define GPMC_REG32(offset) __REG32(GPMC_BASE + (offset))
+#define OMAP24XX_GPMC_BASE (L3_24XX_BASE + 0xa000)
+#define GPMC_REG32(offset) __REG32(OMAP24XX_GPMC_BASE + (offset))
-#define GPT1_BASE (OMAP24XX_GPT1)
+/* FIXME: Move these to timer code */
+#define GPT1_BASE (0x48028000)
#define GPT1_REG32(offset) __REG32(GPT1_BASE + (offset))
/* Misc sysconfig */
#define DISPC_SYSCONFIG DISP_REG32(0x410)
-#define SPI_BASE (OMAP24XX_L4_IO_BASE+0x98000)
+#define SPI_BASE (OMAP24XX_L4_IO_BASE + 0x98000)
#define MCSPI1_SYSCONFIG __REG32(SPI_BASE + 0x10)
-#define MCSPI2_SYSCONFIG __REG32(SPI_BASE+0x2000 + 0x10)
-
-//#define DSP_MMU_SYSCONFIG 0x5A000010
-#define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE+0x2C10)
-//#define IVA_MMU_SYSCONFIG 0x5D000010
-//#define DSP_DMA_SYSCONFIG 0x00FCC02C
-#define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE+0x282C)
-#define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE+0x602C)
+#define MCSPI2_SYSCONFIG __REG32(SPI_BASE + 0x2000 + 0x10)
+#define MCSPI3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0xb8010)
+
+#define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE + 0x2C10)
+#define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE + 0x282C)
+#define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE + 0x602C)
#define GPMC_SYSCONFIG GPMC_REG32(0x010)
-#define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x94010)
-#define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6A054)
-#define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6C054)
-#define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6E054)
-//#define IVA_SYSCONFIG 0x5C060010
-#define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE+0x10)
-#define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE+0x10)
-#define SSI_SYSCONFIG __REG32(DISP_BASE+0x8010)
-//#define VLYNQ_SYSCONFIG 0x67FFFE10
+#define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x94010)
+#define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6A054)
+#define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6C054)
+#define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6E054)
+#define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE + 0x10)
+#define OMAP24XX_SMS_BASE (L3_24XX_BASE + 0x8000)
+#define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE + 0x10)
+#define SSI_SYSCONFIG __REG32(DISP_BASE + 0x8010)
/* rkw - good cannidates for PM_ to start what nm was trying */
-#define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE+0x2A000)
-#define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE+0x78000)
-#define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE+0x7A000)
-#define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE+0x7C000)
-#define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE+0x7E000)
-#define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE+0x80000)
-#define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE+0x82000)
-#define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE+0x84000)
-#define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE+0x86000)
-#define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE+0x88000)
-#define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE+0x8A000)
-
+#define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE + 0x2A000)
+#define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE + 0x78000)
+#define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE + 0x7A000)
+#define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE + 0x7C000)
+#define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE + 0x7E000)
+#define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE + 0x80000)
+#define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE + 0x82000)
+#define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE + 0x84000)
+#define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE + 0x86000)
+#define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE + 0x88000)
+#define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE + 0x8A000)
+
+/* FIXME: Move these to timer code */
#define GPTIMER1_SYSCONFIG GPT1_REG32(0x010)
#define GPTIMER2_SYSCONFIG __REG32(OMAP24XX_GPT2 + 0x10)
#define GPTIMER3_SYSCONFIG __REG32(OMAP24XX_GPT3 + 0x10)
@@ -220,12 +231,18 @@
#define GPTIMER11_SYSCONFIG __REG32(OMAP24XX_GPT11 + 0x10)
#define GPTIMER12_SYSCONFIG __REG32(OMAP24XX_GPT12 + 0x10)
-#define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE+(0x2000*((X)-1)))
+/* FIXME: Move these to gpio code */
+#define OMAP24XX_GPIO_BASE 0x48018000
+#define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE + (0x2000 * ((X) - 1)))
+
+#define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1) + 0x10))
+#define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2) + 0x10))
+#define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3) + 0x10))
+#define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4) + 0x10))
-#define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1)+0x10))
-#define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2)+0x10))
-#define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3)+0x10))
-#define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4)+0x10))
+#if defined(CONFIG_ARCH_OMAP243X)
+#define GPIO5_SYSCONFIG __REG32((OMAP24XX_GPIO5_BASE + 0x10))
+#endif
/* GP TIMER 1 */
#define GPTIMER1_TISTAT GPT1_REG32(0x014)
@@ -243,15 +260,15 @@
#define GPTIMER1_TCAR2 GPT1_REG32(0x044)
/* rkw -- base fix up please... */
-#define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE+0x78018)
+#define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE + 0x78018)
/* SDRC */
-#define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE+0x060)
-#define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE+0x064)
-#define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE+0x068)
-#define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE+0x06C)
-#define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE+0x070)
-#define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE+0x084)
+#define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE + 0x060)
+#define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE + 0x064)
+#define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE + 0x068)
+#define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE + 0x06C)
+#define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE + 0x070)
+#define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE + 0x084)
/* GPIO 1 */
#define GPIO1_BASE GPIOX_BASE(1)
@@ -278,6 +295,8 @@
#define GPIO2_DATAIN GPIO2_REG32(0x038)
#define GPIO2_OE GPIO2_REG32(0x034)
#define GPIO2_DATAOUT GPIO2_REG32(0x03C)
+#define GPIO2_DEBOUNCENABLE GPIO2_REG32(0x050)
+#define GPIO2_DEBOUNCINGTIME GPIO2_REG32(0x054)
/* GPIO 3 */
#define GPIO3_BASE GPIOX_BASE(3)
@@ -294,6 +313,8 @@
#define GPIO3_DATAOUT GPIO3_REG32(0x03C)
#define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050)
#define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054)
+#define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050)
+#define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054)
/* GPIO 4 */
#define GPIO4_BASE GPIOX_BASE(4)
@@ -311,10 +332,26 @@
#define GPIO4_DEBOUNCENABLE GPIO4_REG32(0x050)
#define GPIO4_DEBOUNCINGTIME GPIO4_REG32(0x054)
+#if defined(CONFIG_ARCH_OMAP243X)
+/* GPIO 5 */
+#define GPIO5_REG32(offset) __REG32((OMAP24XX_GPIO5_BASE + (offset)))
+#define GPIO5_IRQENABLE1 GPIO5_REG32(0x01C)
+#define GPIO5_IRQSTATUS1 GPIO5_REG32(0x018)
+#define GPIO5_IRQENABLE2 GPIO5_REG32(0x02C)
+#define GPIO5_IRQSTATUS2 GPIO5_REG32(0x028)
+#define GPIO5_WAKEUPENABLE GPIO5_REG32(0x020)
+#define GPIO5_RISINGDETECT GPIO5_REG32(0x048)
+#define GPIO5_FALLINGDETECT GPIO5_REG32(0x04C)
+#define GPIO5_DATAIN GPIO5_REG32(0x038)
+#define GPIO5_OE GPIO5_REG32(0x034)
+#define GPIO5_DATAOUT GPIO5_REG32(0x03C)
+#define GPIO5_DEBOUNCENABLE GPIO5_REG32(0x050)
+#define GPIO5_DEBOUNCINGTIME GPIO5_REG32(0x054)
+#endif
/* IO CONFIG */
-#define CONTROL_BASE (OMAP24XX_CTRL_BASE)
-#define CONTROL_REG32(offset) __REG32(CONTROL_BASE + (offset))
+#define OMAP24XX_CTRL_BASE (L4_24XX_BASE)
+#define CONTROL_REG32(offset) __REG32(OMAP24XX_CTRL_BASE + (offset))
#define CONTROL_PADCONF_SPI1_NCS2 CONTROL_REG32(0x104)
#define CONTROL_PADCONF_SYS_XTALOUT CONTROL_REG32(0x134)
@@ -322,15 +359,18 @@
#define CONTROL_PADCONF_MCBSP1_DX CONTROL_REG32(0x10C)
#define CONTROL_PADCONF_GPMC_NCS4 CONTROL_REG32(0x090)
#define CONTROL_PADCONF_DSS_D5 CONTROL_REG32(0x0B8)
-#define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC)
+#define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC) /* 2420 */
#define CONTROL_PADCONF_DSS_D13 CONTROL_REG32(0x0C0)
#define CONTROL_PADCONF_DSS_VSYNC CONTROL_REG32(0x0CC)
+#define CONTROL_PADCONF_SYS_NIRQW0 CONTROL_REG32(0x0BC) /* 2430 */
+#define CONTROL_PADCONF_SSI1_FLAG_TX CONTROL_REG32(0x108) /* 2430 */
/* CONTROL */
#define CONTROL_DEVCONF CONTROL_REG32(0x274)
+#define CONTROL_DEVCONF1 CONTROL_REG32(0x2E8)
/* INTERRUPT CONTROLLER */
-#define INTC_BASE (OMAP24XX_L4_IO_BASE+0xfe000)
+#define INTC_BASE ((L4_24XX_BASE) + 0xfe000)
#define INTC_REG32(offset) __REG32(INTC_BASE + (offset))
#define INTC1_U_BASE INTC_REG32(0x000)
@@ -348,10 +388,12 @@
#define INTC_ISR_CLEAR2 INTC_REG32(0x0D4)
#define INTC_SIR_IRQ INTC_REG32(0x040)
#define INTC_CONTROL INTC_REG32(0x048)
-#define INTC_ILR11 INTC_REG32(0x12C)
+#define INTC_ILR11 INTC_REG32(0x12C) /* PRCM on MPU PIC */
+#define INTC_ILR30 INTC_REG32(0x178)
+#define INTC_ILR31 INTC_REG32(0x17C)
#define INTC_ILR32 INTC_REG32(0x180)
-#define INTC_ILR37 INTC_REG32(0x194)
-#define INTC_SYSCONFIG INTC_REG32(0x010)
+#define INTC_ILR37 INTC_REG32(0x194) /* GPIO4 on MPU PIC */
+#define INTC_SYSCONFIG INTC_REG32(0x010) /* GPT1 on MPU PIC */
/* RAM FIREWALL */
#define RAMFW_BASE (0x68005000)
@@ -373,6 +415,24 @@
#define GPMC_CONFIG6_0 GPMC_REG32(0x074)
#define GPMC_CONFIG7_0 GPMC_REG32(0x078)
+/* GPMC CS1 */
+#define GPMC_CONFIG1_1 GPMC_REG32(0x090)
+#define GPMC_CONFIG2_1 GPMC_REG32(0x094)
+#define GPMC_CONFIG3_1 GPMC_REG32(0x098)
+#define GPMC_CONFIG4_1 GPMC_REG32(0x09C)
+#define GPMC_CONFIG5_1 GPMC_REG32(0x0a0)
+#define GPMC_CONFIG6_1 GPMC_REG32(0x0a4)
+#define GPMC_CONFIG7_1 GPMC_REG32(0x0a8)
+
+/* GPMC CS3 */
+#define GPMC_CONFIG1_3 GPMC_REG32(0x0F0)
+#define GPMC_CONFIG2_3 GPMC_REG32(0x0F4)
+#define GPMC_CONFIG3_3 GPMC_REG32(0x0F8)
+#define GPMC_CONFIG4_3 GPMC_REG32(0x0FC)
+#define GPMC_CONFIG5_3 GPMC_REG32(0x100)
+#define GPMC_CONFIG6_3 GPMC_REG32(0x104)
+#define GPMC_CONFIG7_3 GPMC_REG32(0x108)
+
/* DSS */
#define DSS_CONTROL DISP_REG32(0x040)
#define DISPC_CONTROL DISP_REG32(0x440)
@@ -405,11 +465,15 @@
#define DISPC_DATA_CYCLE2 DISP_REG32(0x5D8)
#define DISPC_DATA_CYCLE3 DISP_REG32(0x5DC)
-/* Wake up define for board */
-#define GPIO97 (1 << 1)
-#define GPIO88 (1 << 24)
+/* HSUSB Suspend */
+#define HSUSB_CTRL __REG8(0x480AC001)
+#define USBOTG_POWER __REG32(0x480AC000)
+
+/* HS MMC */
+#define MMCHS1_SYSCONFIG __REG32(0x4809C010)
+#define MMCHS2_SYSCONFIG __REG32(0x480b4010)
-#endif /* __ASSEMBLER__ */
+#endif /* __ASSEMBLER__ */
#endif
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
new file mode 100644
index 00000000000..8893479dc7e
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm.c
@@ -0,0 +1,40 @@
+/*
+ * linux/arch/arm/mach-omap2/prcm.c
+ *
+ * OMAP 24xx Power Reset and Clock Management (PRCM) functions
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ *
+ * Written by Tony Lindgren <tony.lindgren@nokia.com>
+ *
+ * Some pieces of code Copyright (C) 2005 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include "prcm-regs.h"
+
+u32 omap_prcm_get_reset_sources(void)
+{
+ return RM_RSTST_WKUP & 0x7f;
+}
+EXPORT_SYMBOL(omap_prcm_get_reset_sources);
+
+/* Resets clock rates and reboots the system. Only called from system.h */
+void omap_prcm_arch_reset(char mode)
+{
+ u32 rate;
+ struct clk *vclk, *sclk;
+
+ vclk = clk_get(NULL, "virt_prcm_set");
+ sclk = clk_get(NULL, "sys_ck");
+ rate = clk_get_rate(sclk);
+ clk_set_rate(vclk, rate); /* go to bypass for OMAP limitation */
+ RM_RSTCTRL_WKUP |= 2;
+}
diff --git a/arch/arm/mach-omap2/sleep.S b/arch/arm/mach-omap2/sleep.S
new file mode 100644
index 00000000000..00299cbeb91
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep.S
@@ -0,0 +1,144 @@
+/*
+ * linux/arch/arm/mach-omap2/sleep.S
+ *
+ * (C) Copyright 2004
+ * Texas Instruments, <www.ti.com>
+ * Richard Woodruff <r-woodruff2@ti.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/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/arch/io.h>
+#include <asm/arch/pm.h>
+
+#define A_32KSYNC_CR_V IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
+#define A_PRCM_VOLTCTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
+#define A_PRCM_CLKCFG_CTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
+#define A_CM_CLKEN_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
+#define A_CM_IDLEST_CKGEN_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
+#define A_CM_CLKSEL1_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
+#define A_CM_CLKSEL2_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
+
+#define A_SDRC_DLLA_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
+#define A_SDRC_POWER_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
+#define A_SDRC_RFR_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
+#define A_SDRC0_V (0xC0000000)
+#define A_SDRC_MANUAL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA8)
+
+ .text
+
+/*
+ * Forces OMAP into idle state
+ *
+ * omap24xx_idle_loop_suspend() - This bit of code just executes the WFI
+ * for normal idles.
+ *
+ * Note: This code get's copied to internal SRAM at boot. When the OMAP
+ * wakes up it continues execution at the point it went to sleep.
+ */
+ENTRY(omap24xx_idle_loop_suspend)
+ stmfd sp!, {r0, lr} @ save registers on stack
+ mov r0, #0 @ clear for mcr setup
+ mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
+ ldmfd sp!, {r0, pc} @ restore regs and return
+
+ENTRY(omap24xx_idle_loop_suspend_sz)
+ .word . - omap24xx_idle_loop_suspend
+
+/*
+ * omap242x_cpu_suspend() - Forces OMAP into deep sleep state by completing
+ * SDRC shutdown then ARM shutdown. Upon wake MPU is back on so just restore
+ * SDRC.
+ *
+ * Input:
+ * R0 : DLL ctrl value pre-Sleep
+ * R1 : Processor+Revision
+ * 2420: 0x21 = 242xES1, 0x26 = 242xES2.2
+ * 2430: 0x31 = 2430ES1, 0x32 = 2430ES2
+ *
+ * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
+ * when we get called, but the DLL probably isn't. We will wait a bit more in
+ * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
+ * if in unlocked mode.
+ *
+ * For less than 242x-ES2.2 upon wake from a sleep mode where the external
+ * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
+ * clock can pass into the PRCM can cause problems at DSP and IVA.
+ * To work around this the code will switch to the 32kHz source prior to sleep.
+ * Post sleep we will shift back to using the DPLL. Apparently,
+ * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
+ * 3x12MHz + 3x32kHz clocks for a full switch.
+ *
+ * The DLL load value is not kept in RETENTION or OFF. It needs to be restored
+ * at wake
+ */
+ENTRY(omap24xx_cpu_suspend)
+ stmfd sp!, {r0 - r12, lr} @ save registers on stack
+ mov r3, #0x0 @ clear for mrc call
+ mcr p15, 0, r3, c7, c10, 4 @ memory barrier, hope SDR/DDR finished
+ nop
+ nop
+ ldr r3, A_SDRC_POWER @ addr of sdrc power
+ ldr r4, [r3] @ value of sdrc power
+ orr r4, r4, #0x40 @ enable self refresh on idle req
+ mov r5, #0x2000 @ set delay (DPLL relock + DLL relock)
+ str r4, [r3] @ make it so
+ mov r2, #0
+ nop
+ mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
+ nop
+loop:
+ subs r5, r5, #0x1 @ awake, wait just a bit
+ bne loop
+
+ /* The DPLL has on before we take the DDR out of self refresh */
+ bic r4, r4, #0x40 @ now clear self refresh bit.
+ str r4, [r3] @ put vlaue back.
+ ldr r4, A_SDRC0 @ make a clock happen
+ ldr r4, [r4]
+ nop @ start auto refresh only after clk ok
+ movs r0, r0 @ see if DDR or SDR
+ ldrne r1, A_SDRC_DLLA_CTRL_S @ get addr of DLL ctrl
+ strne r0, [r1] @ rewrite DLLA to force DLL reload
+ addne r1, r1, #0x8 @ move to DLLB
+ strne r0, [r1] @ rewrite DLLB to force DLL reload
+
+ mov r5, #0x1000
+loop2:
+ subs r5, r5, #0x1
+ bne loop2
+ /* resume*/
+ ldmfd sp!, {r0 - r12, pc} @ restore regs and return
+
+A_SDRC_POWER:
+ .word A_SDRC_POWER_V
+A_SDRC0:
+ .word A_SDRC0_V
+A_CM_CLKSEL2_PLL_S:
+ .word A_CM_CLKSEL2_PLL_V
+A_CM_CLKEN_PLL:
+ .word A_CM_CLKEN_PLL_V
+A_SDRC_DLLA_CTRL_S:
+ .word A_SDRC_DLLA_CTRL_V
+A_SDRC_MANUAL_S:
+ .word A_SDRC_MANUAL_V
+
+ENTRY(omap24xx_cpu_suspend_sz)
+ .word . - omap24xx_cpu_suspend
+
diff --git a/arch/arm/mach-omap2/sram-fn.S b/arch/arm/mach-omap2/sram-fn.S
index 2a869e20334..d261e4ff4d9 100644
--- a/arch/arm/mach-omap2/sram-fn.S
+++ b/arch/arm/mach-omap2/sram-fn.S
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-omap1/sram.S
+ * linux/arch/arm/mach-omap2/sram.S
*
* Omap2 specific functions that need to be run in internal SRAM
*
@@ -28,7 +28,7 @@
#include <asm/arch/io.h>
#include <asm/hardware.h>
-#include <asm/arch/prcm.h>
+#include "prcm-regs.h"
#define TIMER_32KSYNCT_CR_V IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010)
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index c1d77f5b382..0104fd142e7 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -10,6 +10,11 @@ config ARCH_LUBBOCK
select PXA25x
select SA1111
+config MACH_LOGICPD_PXA270
+ bool "LogicPD PXA270 Card Engine Development Platform"
+ select PXA27x
+ select IWMMXT
+
config MACH_MAINSTONE
bool "Intel HCDDBBVA0 Development Platform"
select PXA27x
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 382644401a4..4e8a983e2b8 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_PXA27x) += pxa27x.o
# Specific board support
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
+obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 68923b1d2b6..d6d72603636 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -141,6 +141,8 @@ struct corgissp_machinfo corgi_ssp_machinfo = {
*/
static struct corgibl_machinfo corgi_bl_machinfo = {
.max_intensity = 0x2f,
+ .default_intensity = 0x1f,
+ .limit_mask = 0x0b,
.set_bl_intensity = corgi_bl_set_intensity,
};
@@ -164,6 +166,14 @@ static struct platform_device corgikbd_device = {
/*
+ * Corgi LEDs
+ */
+static struct platform_device corgiled_device = {
+ .name = "corgi-led",
+ .id = -1,
+};
+
+/*
* Corgi Touch Screen Device
*/
static struct resource corgits_resources[] = {
@@ -297,6 +307,7 @@ static struct platform_device *devices[] __initdata = {
&corgikbd_device,
&corgibl_device,
&corgits_device,
+ &corgiled_device,
};
static void __init corgi_init(void)
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index b371d723635..8a25a1c8019 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -196,12 +196,9 @@ static int __init corgi_ssp_probe(struct platform_device *dev)
int ret;
/* Chip Select - Disable All */
- GPDR(ssp_machinfo->cs_lcdcon) |= GPIO_bit(ssp_machinfo->cs_lcdcon); /* output */
- GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */
- GPDR(ssp_machinfo->cs_max1111) |= GPIO_bit(ssp_machinfo->cs_max1111); /* output */
- GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
- GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846); /* output */
- GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
+ pxa_gpio_mode(ssp_machinfo->cs_lcdcon | GPIO_OUT | GPIO_DFLT_HIGH);
+ pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH);
+ pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH);
ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0);
diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
index 458112b21e2..7d8c85486c6 100644
--- a/arch/arm/mach-pxa/dma.c
+++ b/arch/arm/mach-pxa/dma.c
@@ -45,23 +45,16 @@ int pxa_request_dma (char *name, pxa_dma_prio prio,
local_irq_save(flags);
- /* try grabbing a DMA channel with the requested priority */
- for (i = prio; i < prio + PXA_DMA_NBCH(prio); i++) {
- if (!dma_channels[i].name) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- /* requested prio group is full, try hier priorities */
- for (i = prio-1; i >= 0; i--) {
+ do {
+ /* try grabbing a DMA channel with the requested priority */
+ pxa_for_each_dma_prio (i, prio) {
if (!dma_channels[i].name) {
found = 1;
break;
}
}
- }
+ /* if requested prio group is full, try a hier priority */
+ } while (!found && prio--);
if (found) {
DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 9b48a90aefc..5efa84749f3 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -319,6 +319,11 @@ void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
pxaficp_device.dev.platform_data = info;
}
+static struct platform_device pxartc_device = {
+ .name = "sa1100-rtc",
+ .id = -1,
+};
+
static struct platform_device *devices[] __initdata = {
&pxamci_device,
&udc_device,
@@ -329,6 +334,7 @@ static struct platform_device *devices[] __initdata = {
&pxaficp_device,
&i2c_device,
&i2s_device,
+ &pxartc_device,
};
static int __init pxa_init(void)
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
new file mode 100644
index 00000000000..ec0f43a102c
--- /dev/null
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -0,0 +1,393 @@
+/*
+ * linux/arch/arm/mach-pxa/lpd270.c
+ *
+ * Support for the LogicPD PXA270 Card Engine.
+ * Derived from the mainstone code, which carries these notices:
+ *
+ * Author: Nicolas Pitre
+ * Created: Nov 05, 2002
+ * Copyright: MontaVista Software 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 <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/lpd270.h>
+#include <asm/arch/audio.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/ohci.h>
+
+#include "generic.h"
+
+
+static unsigned int lpd270_irq_enabled;
+
+static void lpd270_mask_irq(unsigned int irq)
+{
+ int lpd270_irq = irq - LPD270_IRQ(0);
+
+ __raw_writew(~(1 << lpd270_irq), LPD270_INT_STATUS);
+
+ lpd270_irq_enabled &= ~(1 << lpd270_irq);
+ __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
+}
+
+static void lpd270_unmask_irq(unsigned int irq)
+{
+ int lpd270_irq = irq - LPD270_IRQ(0);
+
+ lpd270_irq_enabled |= 1 << lpd270_irq;
+ __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
+}
+
+static struct irqchip lpd270_irq_chip = {
+ .ack = lpd270_mask_irq,
+ .mask = lpd270_mask_irq,
+ .unmask = lpd270_unmask_irq,
+};
+
+static void lpd270_irq_handler(unsigned int irq, struct irqdesc *desc,
+ struct pt_regs *regs)
+{
+ unsigned long pending;
+
+ pending = __raw_readw(LPD270_INT_STATUS) & lpd270_irq_enabled;
+ do {
+ GEDR(0) = GPIO_bit(0); /* clear useless edge notification */
+ if (likely(pending)) {
+ irq = LPD270_IRQ(0) + __ffs(pending);
+ desc = irq_desc + irq;
+ desc_handle_irq(irq, desc, regs);
+
+ pending = __raw_readw(LPD270_INT_STATUS) &
+ lpd270_irq_enabled;
+ }
+ } while (pending);
+}
+
+static void __init lpd270_init_irq(void)
+{
+ int irq;
+
+ pxa_init_irq();
+
+ __raw_writew(0, LPD270_INT_MASK);
+ __raw_writew(0, LPD270_INT_STATUS);
+
+ /* setup extra LogicPD PXA270 irqs */
+ for (irq = LPD270_IRQ(2); irq <= LPD270_IRQ(4); irq++) {
+ set_irq_chip(irq, &lpd270_irq_chip);
+ set_irq_handler(irq, do_level_IRQ);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
+ set_irq_chained_handler(IRQ_GPIO(0), lpd270_irq_handler);
+ set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
+}
+
+
+#ifdef CONFIG_PM
+static int lpd270_irq_resume(struct sys_device *dev)
+{
+ __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
+ return 0;
+}
+
+static struct sysdev_class lpd270_irq_sysclass = {
+ set_kset_name("cpld_irq"),
+ .resume = lpd270_irq_resume,
+};
+
+static struct sys_device lpd270_irq_device = {
+ .cls = &lpd270_irq_sysclass,
+};
+
+static int __init lpd270_irq_device_init(void)
+{
+ int ret = sysdev_class_register(&lpd270_irq_sysclass);
+ if (ret == 0)
+ ret = sysdev_register(&lpd270_irq_device);
+ return ret;
+}
+
+device_initcall(lpd270_irq_device_init);
+#endif
+
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = LPD270_ETH_PHYS,
+ .end = (LPD270_ETH_PHYS + 0xfffff),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = LPD270_ETHERNET_IRQ,
+ .end = LPD270_ETHERNET_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static struct platform_device lpd270_audio_device = {
+ .name = "pxa2xx-ac97",
+ .id = -1,
+};
+
+static struct resource lpd270_flash_resources[] = {
+ [0] = {
+ .start = PXA_CS0_PHYS,
+ .end = PXA_CS0_PHYS + SZ_64M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = PXA_CS1_PHYS,
+ .end = PXA_CS1_PHYS + SZ_64M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct mtd_partition lpd270_flash0_partitions[] = {
+ {
+ .name = "Bootloader",
+ .size = 0x00040000,
+ .offset = 0,
+ .mask_flags = MTD_WRITEABLE /* force read-only */
+ }, {
+ .name = "Kernel",
+ .size = 0x00400000,
+ .offset = 0x00040000,
+ }, {
+ .name = "Filesystem",
+ .size = MTDPART_SIZ_FULL,
+ .offset = 0x00440000
+ },
+};
+
+static struct flash_platform_data lpd270_flash_data[2] = {
+ {
+ .name = "processor-flash",
+ .map_name = "cfi_probe",
+ .parts = lpd270_flash0_partitions,
+ .nr_parts = ARRAY_SIZE(lpd270_flash0_partitions),
+ }, {
+ .name = "mainboard-flash",
+ .map_name = "cfi_probe",
+ .parts = NULL,
+ .nr_parts = 0,
+ }
+};
+
+static struct platform_device lpd270_flash_device[2] = {
+ {
+ .name = "pxa2xx-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &lpd270_flash_data[0],
+ },
+ .resource = &lpd270_flash_resources[0],
+ .num_resources = 1,
+ }, {
+ .name = "pxa2xx-flash",
+ .id = 1,
+ .dev = {
+ .platform_data = &lpd270_flash_data[1],
+ },
+ .resource = &lpd270_flash_resources[1],
+ .num_resources = 1,
+ },
+};
+
+static void lpd270_backlight_power(int on)
+{
+ if (on) {
+ pxa_gpio_mode(GPIO16_PWM0_MD);
+ pxa_set_cken(CKEN0_PWM0, 1);
+ PWM_CTRL0 = 0;
+ PWM_PWDUTY0 = 0x3ff;
+ PWM_PERVAL0 = 0x3ff;
+ } else {
+ PWM_CTRL0 = 0;
+ PWM_PWDUTY0 = 0x0;
+ PWM_PERVAL0 = 0x3FF;
+ pxa_set_cken(CKEN0_PWM0, 0);
+ }
+}
+
+/* 5.7" TFT QVGA (LoLo display number 1) */
+static struct pxafb_mach_info sharp_lq057q3dc02 __initdata = {
+ .pixclock = 100000,
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .hsync_len = 64,
+ .left_margin = 0x27,
+ .right_margin = 0x09,
+ .vsync_len = 0x04,
+ .upper_margin = 0x08,
+ .lower_margin = 0x14,
+ .sync = 0,
+ .lccr0 = 0x07800080,
+ .lccr3 = 0x04400007,
+ .pxafb_backlight_power = lpd270_backlight_power,
+};
+
+/* 6.4" TFT VGA (LoLo display number 5) */
+static struct pxafb_mach_info sharp_lq64d343 __initdata = {
+ .pixclock = 20000,
+ .xres = 640,
+ .yres = 480,
+ .bpp = 16,
+ .hsync_len = 49,
+ .left_margin = 0x89,
+ .right_margin = 0x19,
+ .vsync_len = 18,
+ .upper_margin = 0x22,
+ .lower_margin = 0,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .lccr0 = 0x07800080,
+ .lccr3 = 0x04400001,
+ .pxafb_backlight_power = lpd270_backlight_power,
+};
+
+/* 3.5" TFT QVGA (LoLo display number 8) */
+static struct pxafb_mach_info sharp_lq035q7db02_20 __initdata = {
+ .pixclock = 100000,
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .hsync_len = 0x34,
+ .left_margin = 0x09,
+ .right_margin = 0x09,
+ .vsync_len = 0x08,
+ .upper_margin = 0x05,
+ .lower_margin = 0x14,
+ .sync = 0,
+ .lccr0 = 0x07800080,
+ .lccr3 = 0x04400007,
+ .pxafb_backlight_power = lpd270_backlight_power,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+ &smc91x_device,
+ &lpd270_audio_device,
+ &lpd270_flash_device[0],
+ &lpd270_flash_device[1],
+};
+
+static int lpd270_ohci_init(struct device *dev)
+{
+ /* setup Port1 GPIO pin. */
+ pxa_gpio_mode(88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */
+ pxa_gpio_mode(89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
+
+ /* Set the Power Control Polarity Low and Power Sense
+ Polarity Low to active low. */
+ UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
+ ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+
+ return 0;
+}
+
+static struct pxaohci_platform_data lpd270_ohci_platform_data = {
+ .port_mode = PMM_PERPORT_MODE,
+ .init = lpd270_ohci_init,
+};
+
+static void __init lpd270_init(void)
+{
+ lpd270_flash_data[0].width = (BOOT_DEF & 1) ? 2 : 4;
+ lpd270_flash_data[1].width = 4;
+
+ /*
+ * System bus arbiter setting:
+ * - Core_Park
+ * - LCD_wt:DMA_wt:CORE_Wt = 2:3:4
+ */
+ ARB_CNTRL = ARB_CORE_PARK | 0x234;
+
+ /*
+ * On LogicPD PXA270, we route AC97_SYSCLK via GPIO45.
+ */
+ pxa_gpio_mode(GPIO45_SYSCLK_AC97_MD);
+
+ platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+ // set_pxa_fb_info(&sharp_lq057q3dc02);
+ set_pxa_fb_info(&sharp_lq64d343);
+ // set_pxa_fb_info(&sharp_lq035q7db02_20);
+
+ pxa_set_ohci_info(&lpd270_ohci_platform_data);
+}
+
+
+static struct map_desc lpd270_io_desc[] __initdata = {
+ {
+ .virtual = LPD270_CPLD_VIRT,
+ .pfn = __phys_to_pfn(LPD270_CPLD_PHYS),
+ .length = LPD270_CPLD_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+static void __init lpd270_map_io(void)
+{
+ pxa_map_io();
+ iotable_init(lpd270_io_desc, ARRAY_SIZE(lpd270_io_desc));
+
+ /* initialize sleep mode regs (wake-up sources, etc) */
+ PGSR0 = 0x00008800;
+ PGSR1 = 0x00000002;
+ PGSR2 = 0x0001FC00;
+ PGSR3 = 0x00001F81;
+ PWER = 0xC0000002;
+ PRER = 0x00000002;
+ PFER = 0x00000002;
+
+ /* for use I SRAM as framebuffer. */
+ PSLR |= 0x00000F04;
+ PCFR = 0x00000066;
+}
+
+MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
+ /* Maintainer: Peter Barada */
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .boot_params = 0xa0000100,
+ .map_io = lpd270_map_io,
+ .init_irq = lpd270_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = lpd270_init,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 98356f81000..b307f11951d 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -95,7 +95,10 @@ static void __init mainstone_init_irq(void)
for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
set_irq_chip(irq, &mainstone_irq_chip);
set_irq_handler(irq, do_level_IRQ);
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ if (irq == MAINSTONE_IRQ(10) || irq == MAINSTONE_IRQ(14))
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN);
+ else
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
set_irq_flags(MAINSTONE_IRQ(8), 0);
set_irq_flags(MAINSTONE_IRQ(12), 0);
@@ -490,6 +493,7 @@ static void __init mainstone_map_io(void)
MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
/* Maintainer: MontaVista Software Inc. */
.phys_io = 0x40000000,
+ .boot_params = 0xa0000100, /* BLOB boot parameter setting */
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = mainstone_map_io,
.init_irq = mainstone_init_irq,
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index b45560a8f6c..a042473deed 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -307,6 +307,10 @@ static void __init fixup_poodle(struct machine_desc *desc,
struct tag *tags, char **cmdline, struct meminfo *mi)
{
sharpsl_save_param();
+ mi->nr_banks=1;
+ mi->bank[0].start = 0xa0000000;
+ mi->bank[0].node = 0;
+ mi->bank[0].size = (32*1024*1024);
}
MACHINE_START(POODLE, "SHARP Poodle")
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 30ec317bbb9..44bcb8097c7 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -220,6 +220,8 @@ struct corgissp_machinfo spitz_ssp_machinfo = {
* Spitz Backlight Device
*/
static struct corgibl_machinfo spitz_bl_machinfo = {
+ .default_intensity = 0x1f,
+ .limit_mask = 0x0b,
.max_intensity = 0x2f,
};
@@ -242,6 +244,14 @@ static struct platform_device spitzkbd_device = {
/*
+ * Spitz LEDs
+ */
+static struct platform_device spitzled_device = {
+ .name = "spitz-led",
+ .id = -1,
+};
+
+/*
* Spitz Touch Screen Device
*/
static struct resource spitzts_resources[] = {
@@ -361,6 +371,7 @@ static int spitz_ohci_init(struct device *dev)
static struct pxaohci_platform_data spitz_ohci_platform_data = {
.port_mode = PMM_NPS_MODE,
.init = spitz_ohci_init,
+ .power_budget = 150,
};
@@ -418,6 +429,7 @@ static struct platform_device *devices[] __initdata = {
&spitzkbd_device,
&spitzts_device,
&spitzbl_device,
+ &spitzled_device,
};
static void __init common_init(void)
@@ -467,6 +479,8 @@ struct platform_device akitaioexp_device = {
.id = -1,
};
+EXPORT_SYMBOL_GPL(akitaioexp_device);
+
static void __init akita_init(void)
{
spitz_ficp_platform_data.transceiver_mode = akita_irda_transceiver_mode;
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 66ec71756d0..76c0e7f0a21 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -251,10 +251,19 @@ static struct platform_device tosakbd_device = {
.id = -1,
};
+/*
+ * Tosa LEDs
+ */
+static struct platform_device tosaled_device = {
+ .name = "tosa-led",
+ .id = -1,
+};
+
static struct platform_device *devices[] __initdata = {
&tosascoop_device,
&tosascoop_jc_device,
&tosakbd_device,
+ &tosaled_device,
};
static void __init tosa_init(void)
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index d4a586e38d5..693fb1e396e 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -137,8 +137,11 @@ static struct amba_device *amba_devs[] __initdata = {
static void __init gic_init_irq(void)
{
#ifdef CONFIG_REALVIEW_MPCORE
+ unsigned int pldctrl;
writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
- writel(0x008003c0, __io_address(REALVIEW_SYS_BASE) + 0xd8);
+ pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + 0xd8);
+ pldctrl |= 0x00800000; /* New irq mode */
+ writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + 0xd8);
writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
#endif
gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE));
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index ed07c4149d8..970f98dadff 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -50,9 +50,15 @@ config MACH_N30
<http://zoo.weinigel.se/n30>.
+config MACH_SMDK
+ bool
+ help
+ Common machine code for SMDK2410 and SMDK2440
+
config ARCH_SMDK2410
bool "SMDK2410/A9M2410"
select CPU_S3C2410
+ select MACH_SMDK
help
Say Y here if you are using the SMDK2410 or the derived module A9M2410
<http://www.fsforth.de>
@@ -60,6 +66,7 @@ config ARCH_SMDK2410
config ARCH_S3C2440
bool "SMDK2440"
select CPU_S3C2440
+ select MACH_SMDK
help
Say Y here if you are using the SMDK2440.
@@ -163,7 +170,7 @@ config S3C2410_PM_DEBUG
depends on ARCH_S3C2410 && PM
help
Say Y here if you want verbose debugging from the PM Suspend and
- Resume code. See `Documentation/arm/Samsing-S3C24XX/Suspend.txt`
+ Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
for more information.
config S3C2410_PM_CHECK
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 1b3b476e563..3e5712db6b5 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -48,3 +48,5 @@ obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
obj-$(CONFIG_MACH_OTOM) += mach-otom.o
obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
+
+obj-$(CONFIG_MACH_SMDK) += common-smdk.o \ No newline at end of file
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index fec02c92f95..6de713ad319 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -249,7 +249,7 @@ static int s3c24xx_upll_enable(struct clk *clk, int enable)
/* if we started the UPLL, then allow to settle */
- if (enable && !(orig & S3C2410_CLKSLOW_UCLK_OFF))
+ if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
udelay(200);
return 0;
@@ -367,6 +367,8 @@ static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
source = S3C2410_MISCCR_CLK0_UPLL;
else if (parent == &clk_f)
source = S3C2410_MISCCR_CLK0_FCLK;
+ else if (parent == &clk_h)
+ source = S3C2410_MISCCR_CLK0_HCLK;
else if (parent == &clk_p)
source = S3C2410_MISCCR_CLK0_PCLK;
else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0)
@@ -376,6 +378,8 @@ static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
else
return -EINVAL;
+ clk->parent = parent;
+
if (clk == &s3c24xx_dclk0)
mask = S3C2410_MISCCR_CLK0_MASK;
else {
diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/mach-s3c2410/common-smdk.c
new file mode 100644
index 00000000000..c940890f621
--- /dev/null
+++ b/arch/arm/mach-s3c2410/common-smdk.c
@@ -0,0 +1,135 @@
+/* linux/arch/arm/mach-s3c2410/common-smdk.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * 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/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/arch/nand.h>
+
+#include "common-smdk.h"
+#include "devs.h"
+#include "pm.h"
+
+/* NAND parititon from 2.4.18-swl5 */
+
+static struct mtd_partition smdk_default_nand_part[] = {
+ [0] = {
+ .name = "Boot Agent",
+ .size = SZ_16K,
+ .offset = 0,
+ },
+ [1] = {
+ .name = "S3C2410 flash partition 1",
+ .offset = 0,
+ .size = SZ_2M,
+ },
+ [2] = {
+ .name = "S3C2410 flash partition 2",
+ .offset = SZ_4M,
+ .size = SZ_4M,
+ },
+ [3] = {
+ .name = "S3C2410 flash partition 3",
+ .offset = SZ_8M,
+ .size = SZ_2M,
+ },
+ [4] = {
+ .name = "S3C2410 flash partition 4",
+ .offset = SZ_1M * 10,
+ .size = SZ_4M,
+ },
+ [5] = {
+ .name = "S3C2410 flash partition 5",
+ .offset = SZ_1M * 14,
+ .size = SZ_1M * 10,
+ },
+ [6] = {
+ .name = "S3C2410 flash partition 6",
+ .offset = SZ_1M * 24,
+ .size = SZ_1M * 24,
+ },
+ [7] = {
+ .name = "S3C2410 flash partition 7",
+ .offset = SZ_1M * 48,
+ .size = SZ_16M,
+ }
+};
+
+static struct s3c2410_nand_set smdk_nand_sets[] = {
+ [0] = {
+ .name = "NAND",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(smdk_default_nand_part),
+ .partitions = smdk_default_nand_part,
+ },
+};
+
+/* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+*/
+
+static struct s3c2410_platform_nand smdk_nand_info = {
+ .tacls = 20,
+ .twrph0 = 60,
+ .twrph1 = 20,
+ .nr_sets = ARRAY_SIZE(smdk_nand_sets),
+ .sets = smdk_nand_sets,
+};
+
+/* devices we initialise */
+
+static struct platform_device __initdata *smdk_devs[] = {
+ &s3c_device_nand,
+};
+
+void __init smdk_machine_init(void)
+{
+ /* Configure the LEDs (even if we have no LED support)*/
+
+ s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
+ s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
+ s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
+ s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
+
+ s3c2410_gpio_setpin(S3C2410_GPF4, 1);
+ s3c2410_gpio_setpin(S3C2410_GPF5, 1);
+ s3c2410_gpio_setpin(S3C2410_GPF6, 1);
+ s3c2410_gpio_setpin(S3C2410_GPF7, 1);
+
+ s3c_device_nand.dev.platform_data = &smdk_nand_info;
+
+ platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
+
+ s3c2410_pm_init();
+}
diff --git a/arch/arm/mach-s3c2410/common-smdk.h b/arch/arm/mach-s3c2410/common-smdk.h
new file mode 100644
index 00000000000..0e3a3be330a
--- /dev/null
+++ b/arch/arm/mach-s3c2410/common-smdk.h
@@ -0,0 +1,15 @@
+/* linux/arch/arm/mach-s3c2410/common-smdk.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * 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.
+*/
+
+extern void smdk_machine_init(void);
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index 3e327b8e46b..cc97fbf6629 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -232,8 +232,8 @@ static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
static struct s3c2410_platform_nand anubis_nand_info = {
.tacls = 25,
- .twrph0 = 80,
- .twrph1 = 80,
+ .twrph0 = 55,
+ .twrph1 = 40,
.nr_sets = ARRAY_SIZE(anubis_nand_sets),
.sets = anubis_nand_sets,
.select_chip = anubis_nand_select,
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
index 0260ed5ab94..306afc1d7cd 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2410/mach-rx3715.c
@@ -32,6 +32,11 @@
#include <linux/serial_core.h>
#include <linux/serial.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
@@ -46,6 +51,7 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-lcd.h>
+#include <asm/arch/nand.h>
#include <asm/arch/fb.h>
#include "clock.h"
@@ -170,12 +176,39 @@ static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = {
},
};
+static struct mtd_partition rx3715_nand_part[] = {
+ [0] = {
+ .name = "Whole Flash",
+ .offset = 0,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = MTD_WRITEABLE,
+ }
+};
+
+static struct s3c2410_nand_set rx3715_nand_sets[] = {
+ [0] = {
+ .name = "Internal",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(rx3715_nand_part),
+ .partitions = rx3715_nand_part,
+ },
+};
+
+static struct s3c2410_platform_nand rx3715_nand_info = {
+ .tacls = 25,
+ .twrph0 = 50,
+ .twrph1 = 15,
+ .nr_sets = ARRAY_SIZE(rx3715_nand_sets),
+ .sets = rx3715_nand_sets,
+};
+
static struct platform_device *rx3715_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
+ &s3c_device_nand,
};
static struct s3c24xx_board rx3715_board __initdata = {
@@ -185,6 +218,8 @@ static struct s3c24xx_board rx3715_board __initdata = {
static void __init rx3715_map_io(void)
{
+ s3c_device_nand.dev.platform_data = &rx3715_nand_info;
+
s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
s3c24xx_init_clocks(16934000);
s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 1e76e1fdfce..2db932d72c5 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -28,7 +28,8 @@
* Ben Dooks <ben@simtec.co.uk>
*
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
- * 20-Sep-2005 BJD Added static to non-exported items
+ * 20-Sep-2005 BJD Added static to non-exported items
+ * 01-Apr-2006 BJD Moved init code to common smdk
*
***********************************************************************/
@@ -54,6 +55,8 @@
#include "devs.h"
#include "cpu.h"
+#include "common-smdk.h"
+
static struct map_desc smdk2410_iodesc[] __initdata = {
/* nothing here yet */
};
@@ -107,11 +110,6 @@ static void __init smdk2410_map_io(void)
s3c24xx_set_board(&smdk2410_board);
}
-static void __init smdk2410_init_irq(void)
-{
- s3c24xx_init_irq();
-}
-
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
* to SMDK2410 */
/* Maintainer: Jonas Dietsche */
@@ -119,7 +117,8 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = smdk2410_map_io,
- .init_irq = smdk2410_init_irq,
+ .init_irq = s3c24xx_init_irq,
+ .init_machine = smdk_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index f4315721c3b..5fffd1d5104 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -53,7 +53,8 @@
#include "clock.h"
#include "devs.h"
#include "cpu.h"
-#include "pm.h"
+
+#include "common-smdk.h"
static struct map_desc smdk2440_iodesc[] __initdata = {
/* ISA IO Space map (memory space selected by A24) */
@@ -197,21 +198,9 @@ static void __init smdk2440_map_io(void)
static void __init smdk2440_machine_init(void)
{
- /* Configure the LEDs (even if we have no LED support)*/
-
- s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
- s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
- s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
- s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
-
- s3c2410_gpio_setpin(S3C2410_GPF4, 0);
- s3c2410_gpio_setpin(S3C2410_GPF5, 0);
- s3c2410_gpio_setpin(S3C2410_GPF6, 0);
- s3c2410_gpio_setpin(S3C2410_GPF7, 0);
-
s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
- s3c2410_pm_init();
+ smdk_machine_init();
}
MACHINE_START(S3C2440, "SMDK2440")
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c
index 57a15974d4b..d7a30ed6c32 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2440-clock.c
@@ -139,7 +139,7 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
clkdivn = __raw_readl(S3C2410_CLKDIVN);
clkdivn |= S3C2440_CLKDIVN_UCLK;
- __raw_writel(camdivn, S3C2410_CLKDIVN);
+ __raw_writel(clkdivn, S3C2410_CLKDIVN);
mutex_unlock(&clocks_mutex);
}
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S
index 832fb86a03b..73de2eaca22 100644
--- a/arch/arm/mach-s3c2410/sleep.S
+++ b/arch/arm/mach-s3c2410/sleep.S
@@ -59,8 +59,7 @@ ENTRY(s3c2410_cpu_suspend)
mrc p15, 0, r5, c13, c0, 0 @ PID
mrc p15, 0, r6, c3, c0, 0 @ Domain ID
mrc p15, 0, r7, c2, c0, 0 @ translation table base address
- mrc p15, 0, r8, c2, c0, 0 @ auxiliary control register
- mrc p15, 0, r9, c1, c0, 0 @ control register
+ mrc p15, 0, r8, c1, c0, 0 @ control register
stmia r0, { r4 - r13 }
@@ -165,7 +164,6 @@ ENTRY(s3c2410_cpu_resume)
mcr p15, 0, r5, c13, c0, 0 @ PID
mcr p15, 0, r6, c3, c0, 0 @ Domain ID
mcr p15, 0, r7, c2, c0, 0 @ translation table base
- mcr p15, 0, r8, c1, c1, 0 @ auxilliary control
#ifdef CONFIG_DEBUG_RESUME
mov r3, #'R'
@@ -173,7 +171,7 @@ ENTRY(s3c2410_cpu_resume)
#endif
ldr r2, =resume_with_mmu
- mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc
+ mcr p15, 0, r8, c1, c0, 0 @ turn on MMU, etc
nop @ second-to-last before mmu
mov pc, r2 @ go back to virtual address
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index 6923316b3d0..cd67ab1b217 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -111,7 +111,7 @@ config SA1100_LART
bool "LART"
help
Say Y here if you are using the Linux Advanced Radio Terminal
- (also known as the LART). See <http://www.lart.tudelft.nl/> for
+ (also known as the LART). See <http://www.lartmaker.nl/> for
information on the LART.
config SA1100_PLEB
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 10245408247..676b5c5b75b 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -11,7 +11,8 @@
* published by the Free Software Foundation.
*
* ChangeLog:
- * 03-06-2004 John Lenz <jelenz@wisc.edu>
+ * 2006 Pavel Machek <pavel@suse.cz>
+ * 03-06-2004 John Lenz <lenz@cs.wisc.edu>
* 06-04-2002 Chris Larson <kergoth@digitalnemesis.net>
* 04-16-2001 Lineo Japan,Inc. ...
*/
@@ -87,12 +88,75 @@ static struct mcp_plat_data collie_mcp_data = {
.sclk_rate = 11981000,
};
+#ifdef CONFIG_SHARP_LOCOMO
+/*
+ * low-level UART features.
+ */
+static struct locomo_dev *uart_dev = NULL;
+
+static void collie_uart_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ if (!uart_dev) return;
+
+ if (mctrl & TIOCM_RTS)
+ locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 0);
+ else
+ locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 1);
+
+ if (mctrl & TIOCM_DTR)
+ locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 0);
+ else
+ locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 1);
+}
+
+static u_int collie_uart_get_mctrl(struct uart_port *port)
+{
+ int ret = TIOCM_CD;
+ unsigned int r;
+ if (!uart_dev) return ret;
+
+ r = locomo_gpio_read_output(uart_dev, LOCOMO_GPIO_CTS & LOCOMO_GPIO_DSR);
+ if (r & LOCOMO_GPIO_CTS)
+ ret |= TIOCM_CTS;
+ if (r & LOCOMO_GPIO_DSR)
+ ret |= TIOCM_DSR;
+
+ return ret;
+}
static struct sa1100_port_fns collie_port_fns __initdata = {
.set_mctrl = collie_uart_set_mctrl,
.get_mctrl = collie_uart_get_mctrl,
};
+static int collie_uart_probe(struct locomo_dev *dev)
+{
+ uart_dev = dev;
+ return 0;
+}
+
+static int collie_uart_remove(struct locomo_dev *dev)
+{
+ uart_dev = NULL;
+ return 0;
+}
+
+static struct locomo_driver collie_uart_driver = {
+ .drv = {
+ .name = "collie_uart",
+ },
+ .devid = LOCOMO_DEVID_UART,
+ .probe = collie_uart_probe,
+ .remove = collie_uart_remove,
+};
+
+static int __init collie_uart_init(void) {
+ return locomo_driver_register(&collie_uart_driver);
+}
+device_initcall(collie_uart_init);
+
+#endif
+
static struct resource locomo_resources[] = {
[0] = {
@@ -218,6 +282,12 @@ static void __init collie_map_io(void)
{
sa1100_map_io();
iotable_init(collie_io_desc, ARRAY_SIZE(collie_io_desc));
+
+#ifdef CONFIG_SHARP_LOCOMO
+ sa1100_register_uart_fns(&collie_port_fns);
+#endif
+ sa1100_register_uart(0, 3);
+ sa1100_register_uart(1, 1);
}
MACHINE_START(COLLIE, "Sharp-Collie")
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index 6435b2e48ff..d68630b74d7 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -11,7 +11,7 @@
* linux-2.4.5-rmk1
*
* This software has been developed while working on the LART
- * computing board (http://www.lart.tudelft.nl/), which is
+ * computing board (http://www.lartmaker.nl/), which is
* sponsored by the Mobile Multi-media Communications
* (http://www.mmc.tudelft.nl/) and Ubiquitous Communications
* (http://www.ubicom.tudelft.nl/) projects.
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 2abdc419e98..9ea71551fc0 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -324,6 +324,11 @@ void sa11x0_set_irda_data(struct irda_platform_data *irda)
sa11x0ir_device.dev.platform_data = irda;
}
+static struct platform_device sa11x0rtc_device = {
+ .name = "sa1100-rtc",
+ .id = -1,
+};
+
static struct platform_device *sa11x0_devices[] __initdata = {
&sa11x0udc_device,
&sa11x0uart1_device,
@@ -333,6 +338,7 @@ static struct platform_device *sa11x0_devices[] __initdata = {
&sa11x0pcmcia_device,
&sa11x0fb_device,
&sa11x0mtd_device,
+ &sa11x0rtc_device,
};
static int __init sa1100_init(void)
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index c131a5201b5..b3a56024182 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -199,10 +199,26 @@ static void sa1100_unmask_irq(unsigned int irq)
ICMR |= (1 << irq);
}
+/*
+ * Apart form GPIOs, only the RTC alarm can be a wakeup event.
+ */
+static int sa1100_set_wake(unsigned int irq, unsigned int on)
+{
+ if (irq == IRQ_RTCAlrm) {
+ if (on)
+ PWER |= PWER_RTC;
+ else
+ PWER &= ~PWER_RTC;
+ return 0;
+ }
+ return -EINVAL;
+}
+
static struct irqchip sa1100_normal_chip = {
.ack = sa1100_mask_irq,
.mask = sa1100_mask_irq,
.unmask = sa1100_unmask_irq,
+ .set_wake = sa1100_set_wake,
};
static struct resource irq_resource = {
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index 9e02bc3712a..af6d2775cf8 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -59,6 +59,14 @@ neponset_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
if (irr & (IRR_ETHERNET | IRR_USAR)) {
desc->chip->mask(irq);
+ /*
+ * Ack the interrupt now to prevent re-entering
+ * this neponset handler. Again, this is safe
+ * since we'll check the IRR register prior to
+ * leaving.
+ */
+ desc->chip->ack(irq);
+
if (irr & IRR_ETHERNET) {
d = irq_desc + IRQ_NEPONSET_SMC9196;
desc_handle_irq(IRQ_NEPONSET_SMC9196, d, regs);
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 799697d32de..cebd48a3dae 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -112,10 +112,9 @@ void __init versatile_init_irq(void)
{
unsigned int i;
- vic_init(VA_VIC_BASE, IRQ_VIC_START, ~(1 << 31));
+ vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0);
- set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq);
- enable_irq(IRQ_VICSOURCE31);
+ set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq);
/* Do second interrupt controller */
writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index e680c5fd93b..c55b739e10b 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -239,6 +239,17 @@ config CPU_XSCALE
select CPU_CACHE_VIVT
select CPU_TLB_V4WBI
+# XScale Core Version 3
+config CPU_XSC3
+ bool
+ depends on ARCH_IXP23XX
+ default y
+ select CPU_32v5
+ select CPU_ABRT_EV5T
+ select CPU_CACHE_VIVT
+ select CPU_TLB_V4WBI
+ select IO_36
+
# ARMv6
config CPU_V6
bool "Support ARM V6 processor"
@@ -361,11 +372,17 @@ config CPU_TLB_V4WBI
config CPU_TLB_V6
bool
+#
+# CPU supports 36-bit I/O
+#
+config IO_36
+ bool
+
comment "Processor Features"
config ARM_THUMB
bool "Support Thumb user binaries"
- depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_V6
+ depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6
default y
help
Say Y if you want to include kernel support for running user space
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index ffe73ba2bf1..07a53850578 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_CPU_COPY_V4WB) += copypage-v4wb.o
obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o mmu.o
obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o
obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o
+obj-$(CONFIG_CPU_XSC3) += copypage-xsc3.o
obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o
obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o
@@ -51,4 +52,5 @@ obj-$(CONFIG_CPU_ARM1026) += proc-arm1026.o
obj-$(CONFIG_CPU_SA110) += proc-sa110.o
obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o
obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o
+obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o
obj-$(CONFIG_CPU_V6) += proc-v6.o
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
index 5c4055b62d9..54e3c5bb518 100644
--- a/arch/arm/mm/cache-v4wb.S
+++ b/arch/arm/mm/cache-v4wb.S
@@ -10,7 +10,7 @@
#include <linux/config.h>
#include <linux/linkage.h>
#include <linux/init.h>
-#include <asm/hardware.h>
+#include <asm/memory.h>
#include <asm/page.h>
#include "proc-macros.S"
@@ -46,6 +46,11 @@
*/
#define CACHE_DLIMIT (CACHE_DSIZE * 4)
+ .data
+flush_base:
+ .long FLUSH_BASE
+ .text
+
/*
* flush_user_cache_all()
*
@@ -63,11 +68,21 @@ ENTRY(v4wb_flush_kern_cache_all)
mov ip, #0
mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
__flush_whole_cache:
- mov r0, #FLUSH_BASE
- add r1, r0, #CACHE_DSIZE
-1: ldr r2, [r0], #32
- cmp r0, r1
+ ldr r3, =flush_base
+ ldr r1, [r3, #0]
+ eor r1, r1, #CACHE_DSIZE
+ str r1, [r3, #0]
+ add r2, r1, #CACHE_DSIZE
+1: ldr r3, [r1], #32
+ cmp r1, r2
+ blo 1b
+#ifdef FLUSH_BASE_MINICACHE
+ add r2, r2, #FLUSH_BASE_MINICACHE - FLUSH_BASE
+ sub r1, r2, #512 @ only 512 bytes
+1: ldr r3, [r1], #32
+ cmp r1, r2
blo 1b
+#endif
mcr p15, 0, ip, c7, c10, 4 @ drain write buffer
mov pc, lr
@@ -82,6 +97,7 @@ __flush_whole_cache:
* - flags - vma_area_struct flags describing address space
*/
ENTRY(v4wb_flush_user_cache_range)
+ mov ip, #0
sub r3, r1, r0 @ calculate total size
tst r2, #VM_EXEC @ executable region?
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 8a1bfcd5008..50e6b6bfb2e 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -18,6 +18,7 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <asm/memory.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/sizes.h>
@@ -272,6 +273,17 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
{
+ if (arch_is_coherent()) {
+ void *virt;
+
+ virt = kmalloc(size, gfp);
+ if (!virt)
+ return NULL;
+ *handle = virt_to_dma(dev, virt);
+
+ return virt;
+ }
+
return __dma_alloc(dev, size, handle, gfp,
pgprot_noncached(pgprot_kernel));
}
@@ -350,6 +362,11 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
WARN_ON(irqs_disabled());
+ if (arch_is_coherent()) {
+ kfree(cpu_addr);
+ return;
+ }
+
size = PAGE_ALIGN(size);
spin_lock_irqsave(&consistent_lock, flags);
diff --git a/arch/arm/mm/copypage-xsc3.S b/arch/arm/mm/copypage-xsc3.S
new file mode 100644
index 00000000000..9a2cb4332b4
--- /dev/null
+++ b/arch/arm/mm/copypage-xsc3.S
@@ -0,0 +1,97 @@
+/*
+ * linux/arch/arm/lib/copypage-xsc3.S
+ *
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * 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.
+ *
+ * Adapted for 3rd gen XScale core, no more mini-dcache
+ * Author: Matt Gilbert (matthew.m.gilbert@intel.com)
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+
+/*
+ * General note:
+ * We don't really want write-allocate cache behaviour for these functions
+ * since that will just eat through 8K of the cache.
+ */
+
+ .text
+ .align 5
+/*
+ * XSC3 optimised copy_user_page
+ * r0 = destination
+ * r1 = source
+ * r2 = virtual user address of ultimate destination page
+ *
+ * The source page may have some clean entries in the cache already, but we
+ * can safely ignore them - break_cow() will flush them out of the cache
+ * if we eventually end up using our copied page.
+ *
+ */
+ENTRY(xsc3_mc_copy_user_page)
+ stmfd sp!, {r4, r5, lr}
+ mov lr, #PAGE_SZ/64-1
+
+ pld [r1, #0]
+ pld [r1, #32]
+1: pld [r1, #64]
+ pld [r1, #96]
+
+2: ldrd r2, [r1], #8
+ mov ip, r0
+ ldrd r4, [r1], #8
+ mcr p15, 0, ip, c7, c6, 1 @ invalidate
+ strd r2, [r0], #8
+ ldrd r2, [r1], #8
+ strd r4, [r0], #8
+ ldrd r4, [r1], #8
+ strd r2, [r0], #8
+ strd r4, [r0], #8
+ ldrd r2, [r1], #8
+ mov ip, r0
+ ldrd r4, [r1], #8
+ mcr p15, 0, ip, c7, c6, 1 @ invalidate
+ strd r2, [r0], #8
+ ldrd r2, [r1], #8
+ subs lr, lr, #1
+ strd r4, [r0], #8
+ ldrd r4, [r1], #8
+ strd r2, [r0], #8
+ strd r4, [r0], #8
+ bgt 1b
+ beq 2b
+
+ ldmfd sp!, {r4, r5, pc}
+
+ .align 5
+/*
+ * XScale optimised clear_user_page
+ * r0 = destination
+ * r1 = virtual user address of ultimate destination page
+ */
+ENTRY(xsc3_mc_clear_user_page)
+ mov r1, #PAGE_SZ/32
+ mov r2, #0
+ mov r3, #0
+1: mcr p15, 0, r0, c7, c6, 1 @ invalidate line
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ subs r1, r1, #1
+ bne 1b
+ mov pc, lr
+
+ __INITDATA
+
+ .type xsc3_mc_user_fns, #object
+ENTRY(xsc3_mc_user_fns)
+ .long xsc3_mc_clear_user_page
+ .long xsc3_mc_copy_user_page
+ .size xsc3_mc_user_fns, . - xsc3_mc_user_fns
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 88279124317..9ea1f87a707 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -20,6 +20,7 @@
#include <asm/mach-types.h>
#include <asm/setup.h>
+#include <asm/sizes.h>
#include <asm/tlb.h>
#include <asm/mach/arch.h>
@@ -455,14 +456,14 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
#ifdef FLUSH_BASE
map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS);
map.virtual = FLUSH_BASE;
- map.length = PGDIR_SIZE;
+ map.length = SZ_1M;
map.type = MT_CACHECLEAN;
create_mapping(&map);
#endif
#ifdef FLUSH_BASE_MINICACHE
- map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + PGDIR_SIZE);
+ map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + SZ_1M);
map.virtual = FLUSH_BASE_MINICACHE;
- map.length = PGDIR_SIZE;
+ map.length = SZ_1M;
map.type = MT_MINICLEAN;
create_mapping(&map);
#endif
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 25e0ca3e598..c1f7180c7be 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -141,7 +141,7 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
return NULL;
addr = (unsigned long)area->addr;
if (remap_area_pages(addr, pfn, size, flags)) {
- vfree((void *)addr);
+ vunmap((void *)addr);
return NULL;
}
return (void __iomem *) (offset + (char *)addr);
@@ -173,7 +173,7 @@ EXPORT_SYMBOL(__ioremap);
void __iounmap(void __iomem *addr)
{
- vfree((void *) (PAGE_MASK & (unsigned long) addr));
+ vunmap((void *)(PAGE_MASK & (unsigned long)addr));
}
EXPORT_SYMBOL(__iounmap);
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index ef8d30a185a..95273de4f77 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -376,7 +376,7 @@ void __init build_mem_type_table(void)
ecc_mask = 0;
}
- if (cpu_arch <= CPU_ARCH_ARMv5TEJ) {
+ if (cpu_arch <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) {
for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
if (mem_types[i].prot_l1)
mem_types[i].prot_l1 |= PMD_BIT4;
@@ -389,6 +389,17 @@ void __init build_mem_type_table(void)
kern_pgprot = user_pgprot = cp->pte;
/*
+ * Enable CPU-specific coherency if supported.
+ * (Only available on XSC3 at the moment.)
+ */
+ if (arch_is_coherent()) {
+ if (cpu_is_xsc3()) {
+ mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+ mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT;
+ }
+ }
+
+ /*
* ARMv6 and above have extended page tables.
*/
if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
@@ -557,7 +568,8 @@ void __init create_mapping(struct map_desc *md)
* supersections are only allocated for domain 0 regardless
* of the actual domain assignments in use.
*/
- if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) {
+ if ((cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())
+ && domain == 0) {
/*
* Align to supersection boundary if !high pages.
* High pages have already been checked for proper
@@ -619,7 +631,7 @@ void setup_mm_for_reboot(char mode)
pgd = init_mm.pgd;
base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
- if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ)
+ if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
base_pmdval |= PMD_BIT4;
for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index c916a6cae40..a2dd5ae1077 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -26,22 +26,7 @@
* the cache line size of the I and D cache
*/
#define DCACHELINESIZE 32
-#define FLUSH_OFFSET 32768
- .macro flush_110_dcache rd, ra, re
- ldr \rd, =flush_base
- ldr \ra, [\rd]
- eor \ra, \ra, #FLUSH_OFFSET
- str \ra, [\rd]
- add \re, \ra, #16384 @ only necessary for 16k
-1001: ldr \rd, [\ra], #DCACHELINESIZE
- teq \re, \ra
- bne 1001b
- .endm
-
- .data
-flush_base:
- .long FLUSH_BASE
.text
/*
@@ -145,13 +130,11 @@ ENTRY(cpu_sa110_dcache_clean_area)
*/
.align 5
ENTRY(cpu_sa110_switch_mm)
- flush_110_dcache r3, ip, r1
- mov r1, #0
- mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache
- mcr p15, 0, r1, c7, c10, 4 @ drain WB
+ str lr, [sp, #-4]!
+ bl v4wb_flush_kern_cache_all @ clears IP
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
- mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
- mov pc, lr
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ ldr pc, [sp], #4
/*
* cpu_sa110_set_pte(ptep, pte)
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 41f21f2dd8f..777ad99c143 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -30,30 +30,6 @@
* the cache line size of the I and D cache
*/
#define DCACHELINESIZE 32
-#define FLUSH_OFFSET 32768
-
- .macro flush_1100_dcache rd, ra, re
- ldr \rd, =flush_base
- ldr \ra, [\rd]
- eor \ra, \ra, #FLUSH_OFFSET
- str \ra, [\rd]
- add \re, \ra, #8192 @ only necessary for 8k
-1001: ldr \rd, [\ra], #DCACHELINESIZE
- teq \re, \ra
- bne 1001b
-#ifdef FLUSH_BASE_MINICACHE
- add \ra, \ra, #FLUSH_BASE_MINICACHE - FLUSH_BASE
- add \re, \ra, #512 @ only 512 bytes
-1002: ldr \rd, [\ra], #DCACHELINESIZE
- teq \re, \ra
- bne 1002b
-#endif
- .endm
-
- .data
-flush_base:
- .long FLUSH_BASE
- .text
__INIT
@@ -79,9 +55,8 @@ ENTRY(cpu_sa1100_proc_fin)
stmfd sp!, {lr}
mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
msr cpsr_c, ip
- flush_1100_dcache r0, r1, r2 @ clean caches
- mov r0, #0
- mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching
+ bl v4wb_flush_kern_cache_all
+ mcr p15, 0, ip, c15, c2, 2 @ Disable clock switching
mrc p15, 0, r0, c1, c0, 0 @ ctrl register
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
@@ -167,14 +142,12 @@ ENTRY(cpu_sa1100_dcache_clean_area)
*/
.align 5
ENTRY(cpu_sa1100_switch_mm)
- flush_1100_dcache r3, ip, r1
- mov ip, #0
- mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
+ str lr, [sp, #-4]!
+ bl v4wb_flush_kern_cache_all @ clears IP
mcr p15, 0, ip, c9, c0, 0 @ invalidate RB
- mcr p15, 0, ip, c7, c10, 4 @ drain WB
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
- mov pc, lr
+ ldr pc, [sp], #4
/*
* cpu_sa1100_set_pte(ptep, pte)
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 9a7e7c096aa..ee6f1529873 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -21,6 +21,14 @@
#define D_CACHE_LINE_SIZE 32
+#define TTB_C (1 << 0)
+#define TTB_S (1 << 1)
+#define TTB_IMP (1 << 2)
+#define TTB_RGN_NC (0 << 3)
+#define TTB_RGN_WBWA (1 << 3)
+#define TTB_RGN_WT (2 << 3)
+#define TTB_RGN_WB (3 << 3)
+
.macro cpsie, flags
.ifc \flags, f
.long 0xf1080040
@@ -115,7 +123,7 @@ ENTRY(cpu_v6_switch_mm)
mov r2, #0
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
#ifdef CONFIG_SMP
- orr r0, r0, #2 @ set shared pgtable
+ orr r0, r0, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable
#endif
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
mcr p15, 0, r2, c7, c10, 4 @ drain write buffer
@@ -161,8 +169,8 @@ ENTRY(cpu_v6_set_pte)
tst r1, #L_PTE_YOUNG
biceq r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK
-@ tst r1, #L_PTE_EXEC
-@ orreq r2, r2, #PTE_EXT_XN
+ tst r1, #L_PTE_EXEC
+ orreq r2, r2, #PTE_EXT_XN
tst r1, #L_PTE_PRESENT
moveq r2, #0
@@ -221,7 +229,7 @@ __v6_setup:
mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
mcr p15, 0, r0, c2, c0, 2 @ TTB control register
#ifdef CONFIG_SMP
- orr r4, r4, #2 @ set shared pgtable
+ orr r4, r4, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable
#endif
mcr p15, 0, r4, c2, c0, 1 @ load TTB1
#ifdef CONFIG_VFP
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
new file mode 100644
index 00000000000..8d32e21fe15
--- /dev/null
+++ b/arch/arm/mm/proc-xsc3.S
@@ -0,0 +1,500 @@
+/*
+ * linux/arch/arm/mm/proc-xsc3.S
+ *
+ * Original Author: Matthew Gilbert
+ * Current Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (C) Intel Corp.
+ * Copyright 2005 (c) MontaVista Software, 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.
+ *
+ * MMU functions for the Intel XScale3 Core (XSC3). The XSC3 core is an
+ * extension to Intel's original XScale core that adds the following
+ * features:
+ *
+ * - ARMv6 Supersections
+ * - Low Locality Reference pages (replaces mini-cache)
+ * - 36-bit addressing
+ * - L2 cache
+ * - Cache-coherency if chipset supports it
+ *
+ * Based on orignal XScale code by Nicolas Pitre
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/procinfo.h>
+#include <asm/hardware.h>
+#include <asm/pgtable.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include "proc-macros.S"
+
+/*
+ * This is the maximum size of an area which will be flushed. If the
+ * area is larger than this, then we flush the whole cache.
+ */
+#define MAX_AREA_SIZE 32768
+
+/*
+ * The cache line size of the I and D cache.
+ */
+#define CACHELINESIZE 32
+
+/*
+ * The size of the data cache.
+ */
+#define CACHESIZE 32768
+
+/*
+ * Run with L2 enabled.
+ */
+#define L2_CACHE_ENABLE 1
+
+/*
+ * Enable the Branch Target Buffer (can cause crashes, see erratum #42.)
+ */
+#define BTB_ENABLE 0
+
+/*
+ * This macro is used to wait for a CP15 write and is needed
+ * when we have to ensure that the last operation to the co-pro
+ * was completed before continuing with operation.
+ */
+ .macro cpwait_ret, lr, rd
+ mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15
+ sub pc, \lr, \rd, LSR #32 @ wait for completion and
+ @ flush instruction pipeline
+ .endm
+
+/*
+ * This macro cleans & invalidates the entire xsc3 dcache by set & way.
+ */
+
+ .macro clean_d_cache rd, rs
+ mov \rd, #0x1f00
+ orr \rd, \rd, #0x00e0
+1: mcr p15, 0, \rd, c7, c14, 2 @ clean/inv set/way
+ adds \rd, \rd, #0x40000000
+ bcc 1b
+ subs \rd, \rd, #0x20
+ bpl 1b
+ .endm
+
+ .text
+
+/*
+ * cpu_xsc3_proc_init()
+ *
+ * Nothing too exciting at the moment
+ */
+ENTRY(cpu_xsc3_proc_init)
+ mov pc, lr
+
+/*
+ * cpu_xsc3_proc_fin()
+ */
+ENTRY(cpu_xsc3_proc_fin)
+ str lr, [sp, #-4]!
+ mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
+ msr cpsr_c, r0
+ bl xsc3_flush_kern_cache_all @ clean caches
+ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
+ bic r0, r0, #0x1800 @ ...IZ...........
+ bic r0, r0, #0x0006 @ .............CA.
+ mcr p15, 0, r0, c1, c0, 0 @ disable caches
+ ldr pc, [sp], #4
+
+/*
+ * cpu_xsc3_reset(loc)
+ *
+ * Perform a soft reset of the system. Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * loc: location to jump to for soft reset
+ */
+ .align 5
+ENTRY(cpu_xsc3_reset)
+ mov r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
+ msr cpsr_c, r1 @ reset CPSR
+ mrc p15, 0, r1, c1, c0, 0 @ ctrl register
+ bic r1, r1, #0x0086 @ ........B....CA.
+ bic r1, r1, #0x3900 @ ..VIZ..S........
+ mcr p15, 0, r1, c1, c0, 0 @ ctrl register
+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB
+ bic r1, r1, #0x0001 @ ...............M
+ mcr p15, 0, r1, c1, c0, 0 @ ctrl register
+ @ CAUTION: MMU turned off from this point. We count on the pipeline
+ @ already containing those two last instructions to survive.
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ mov pc, r0
+
+/*
+ * cpu_xsc3_do_idle()
+ *
+ * Cause the processor to idle
+ *
+ * For now we do nothing but go to idle mode for every case
+ *
+ * XScale supports clock switching, but using idle mode support
+ * allows external hardware to react to system state changes.
+
+ MMG: Come back to this one.
+ */
+ .align 5
+
+ENTRY(cpu_xsc3_do_idle)
+ mov r0, #1
+ mcr p14, 0, r0, c7, c0, 0 @ Go to IDLE
+ mov pc, lr
+
+/* ================================= CACHE ================================ */
+
+/*
+ * flush_user_cache_all()
+ *
+ * Invalidate all cache entries in a particular address
+ * space.
+ */
+ENTRY(xsc3_flush_user_cache_all)
+ /* FALLTHROUGH */
+
+/*
+ * flush_kern_cache_all()
+ *
+ * Clean and invalidate the entire cache.
+ */
+ENTRY(xsc3_flush_kern_cache_all)
+ mov r2, #VM_EXEC
+ mov ip, #0
+__flush_whole_cache:
+ clean_d_cache r0, r1
+ tst r2, #VM_EXEC
+ mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
+ mcrne p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
+ mcrne p15, 0, ip, c7, c5, 4 @ Prefetch Flush
+ mov pc, lr
+
+/*
+ * flush_user_cache_range(start, end, vm_flags)
+ *
+ * Invalidate a range of cache entries in the specified
+ * address space.
+ *
+ * - start - start address (may not be aligned)
+ * - end - end address (exclusive, may not be aligned)
+ * - vma - vma_area_struct describing address space
+ */
+ .align 5
+ENTRY(xsc3_flush_user_cache_range)
+ mov ip, #0
+ sub r3, r1, r0 @ calculate total size
+ cmp r3, #MAX_AREA_SIZE
+ bhs __flush_whole_cache
+
+1: tst r2, #VM_EXEC
+ mcrne p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
+ mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate D cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ tst r2, #VM_EXEC
+ mcrne p15, 0, ip, c7, c5, 6 @ Invalidate BTB
+ mcrne p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
+ mcrne p15, 0, ip, c7, c5, 4 @ Prefetch Flush
+ mov pc, lr
+
+/*
+ * coherent_kern_range(start, end)
+ *
+ * Ensure coherency between the Icache and the Dcache in the
+ * region described by start. If you have non-snooping
+ * Harvard caches, you need to implement this function.
+ *
+ * - start - virtual start address
+ * - end - virtual end address
+ *
+ * Note: single I-cache line invalidation isn't used here since
+ * it also trashes the mini I-cache used by JTAG debuggers.
+ */
+ENTRY(xsc3_coherent_kern_range)
+/* FALLTHROUGH */
+ENTRY(xsc3_coherent_user_range)
+ bic r0, r0, #CACHELINESIZE - 1
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB
+ mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mcr p15, 0, r0, c7, c5, 4 @ Prefetch Flush
+ mov pc, lr
+
+/*
+ * flush_kern_dcache_page(void *page)
+ *
+ * Ensure no D cache aliasing occurs, either with itself or
+ * the I cache
+ *
+ * - addr - page aligned address
+ */
+ENTRY(xsc3_flush_kern_dcache_page)
+ add r1, r0, #PAGE_SZ
+1: mcr p15, 0, r0, c7, c14, 1 @ Clean/Invalidate D Cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB
+ mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mcr p15, 0, r0, c7, c5, 4 @ Prefetch Flush
+ mov pc, lr
+
+/*
+ * dma_inv_range(start, end)
+ *
+ * Invalidate (discard) the specified virtual address range.
+ * May not write back any entries. If 'start' or 'end'
+ * are not cache line aligned, those lines must be written
+ * back.
+ *
+ * - start - virtual start address
+ * - end - virtual end address
+ */
+ENTRY(xsc3_dma_inv_range)
+ tst r0, #CACHELINESIZE - 1
+ bic r0, r0, #CACHELINESIZE - 1
+ mcrne p15, 0, r0, c7, c10, 1 @ clean L1 D entry
+ mcrne p15, 1, r0, c7, c11, 1 @ clean L2 D entry
+ tst r1, #CACHELINESIZE - 1
+ mcrne p15, 0, r1, c7, c10, 1 @ clean L1 D entry
+ mcrne p15, 1, r1, c7, c11, 1 @ clean L2 D entry
+1: mcr p15, 0, r0, c7, c6, 1 @ invalidate L1 D entry
+ mcr p15, 1, r0, c7, c7, 1 @ Invalidate L2 D cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mov pc, lr
+
+/*
+ * dma_clean_range(start, end)
+ *
+ * Clean the specified virtual address range.
+ *
+ * - start - virtual start address
+ * - end - virtual end address
+ */
+ENTRY(xsc3_dma_clean_range)
+ bic r0, r0, #CACHELINESIZE - 1
+1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D entry
+ mcr p15, 1, r0, c7, c11, 1 @ clean L2 D entry
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mov pc, lr
+
+/*
+ * dma_flush_range(start, end)
+ *
+ * Clean and invalidate the specified virtual address range.
+ *
+ * - start - virtual start address
+ * - end - virtual end address
+ */
+ENTRY(xsc3_dma_flush_range)
+ bic r0, r0, #CACHELINESIZE - 1
+1: mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate L1 D cache line
+ mcr p15, 1, r0, c7, c11, 1 @ Clean L2 D cache line
+ mcr p15, 1, r0, c7, c7, 1 @ Invalidate L2 D cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mov pc, lr
+
+ENTRY(xsc3_cache_fns)
+ .long xsc3_flush_kern_cache_all
+ .long xsc3_flush_user_cache_all
+ .long xsc3_flush_user_cache_range
+ .long xsc3_coherent_kern_range
+ .long xsc3_coherent_user_range
+ .long xsc3_flush_kern_dcache_page
+ .long xsc3_dma_inv_range
+ .long xsc3_dma_clean_range
+ .long xsc3_dma_flush_range
+
+ENTRY(cpu_xsc3_dcache_clean_area)
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #CACHELINESIZE
+ subs r1, r1, #CACHELINESIZE
+ bhi 1b
+ mov pc, lr
+
+/* =============================== PageTable ============================== */
+
+/*
+ * cpu_xsc3_switch_mm(pgd)
+ *
+ * Set the translation base pointer to be as described by pgd.
+ *
+ * pgd: new page tables
+ */
+ .align 5
+ENTRY(cpu_xsc3_switch_mm)
+ clean_d_cache r1, r2
+ mcr p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
+ mcr p15, 0, ip, c7, c5, 4 @ Prefetch Flush
+#ifdef L2_CACHE_ENABLE
+ orr r0, r0, #0x18 @ cache the page table in L2
+#endif
+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ cpwait_ret lr, ip
+
+/*
+ * cpu_xsc3_set_pte(ptep, pte)
+ *
+ * Set a PTE and flush it out
+ *
+ */
+ .align 5
+ENTRY(cpu_xsc3_set_pte)
+ str r1, [r0], #-2048 @ linux version
+
+ bic r2, r1, #0xdf0 @ Keep C, B, coherency bits
+ orr r2, r2, #PTE_TYPE_EXT @ extended page
+
+ eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
+
+ tst r3, #L_PTE_USER @ User?
+ orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w
+
+ tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty?
+ orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w
+ @ combined with user -> user r/w
+
+#if L2_CACHE_ENABLE
+ @ If its cacheable it needs to be in L2 also.
+ eor ip, r1, #L_PTE_CACHEABLE
+ tst ip, #L_PTE_CACHEABLE
+ orreq r2, r2, #PTE_EXT_TEX(0x5)
+#endif
+
+ tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young?
+ movne r2, #0 @ no -> fault
+
+ str r2, [r0] @ hardware version
+ mov ip, #0
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line mcr
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
+ mov pc, lr
+
+ .ltorg
+
+ .align
+
+ __INIT
+
+ .type __xsc3_setup, #function
+__xsc3_setup:
+ mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
+ msr cpsr_c, r0
+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
+ mcr p15, 0, ip, c7, c5, 4 @ Prefetch Flush
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs
+#if L2_CACHE_ENABLE
+ orr r4, r4, #0x18 @ cache the page table in L2
+#endif
+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
+ mov r0, #1 @ Allow access to CP0 and CP13
+ orr r0, r0, #1 << 13 @ Its undefined whether this
+ mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes
+ mrc p15, 0, r0, c1, c0, 1 @ get auxiliary control reg
+ and r0, r0, #2 @ preserve bit P bit setting
+#if L2_CACHE_ENABLE
+ orr r0, r0, #(1 << 10) @ enable L2 for LLR cache
+#endif
+ mcr p15, 0, r0, c1, c0, 1 @ set auxiliary control reg
+ mrc p15, 0, r0, c1, c0, 0 @ get control register
+ bic r0, r0, #0x0002 @ .... .... .... ..A.
+ orr r0, r0, #0x0005 @ .... .... .... .C.M
+#if BTB_ENABLE
+ bic r0, r0, #0x0200 @ .... ..R. .... ....
+ orr r0, r0, #0x3900 @ ..VI Z..S .... ....
+#else
+ bic r0, r0, #0x0a00 @ .... Z.R. .... ....
+ orr r0, r0, #0x3100 @ ..VI ...S .... ....
+#endif
+#if L2_CACHE_ENABLE
+ orr r0, r0, #0x4000000 @ L2 enable
+#endif
+ mov pc, lr
+
+ .size __xsc3_setup, . - __xsc3_setup
+
+ __INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ * come through these
+ */
+
+ .type xsc3_processor_functions, #object
+ENTRY(xsc3_processor_functions)
+ .word v5t_early_abort
+ .word cpu_xsc3_proc_init
+ .word cpu_xsc3_proc_fin
+ .word cpu_xsc3_reset
+ .word cpu_xsc3_do_idle
+ .word cpu_xsc3_dcache_clean_area
+ .word cpu_xsc3_switch_mm
+ .word cpu_xsc3_set_pte
+ .size xsc3_processor_functions, . - xsc3_processor_functions
+
+ .section ".rodata"
+
+ .type cpu_arch_name, #object
+cpu_arch_name:
+ .asciz "armv5te"
+ .size cpu_arch_name, . - cpu_arch_name
+
+ .type cpu_elf_name, #object
+cpu_elf_name:
+ .asciz "v5"
+ .size cpu_elf_name, . - cpu_elf_name
+
+ .type cpu_xsc3_name, #object
+cpu_xsc3_name:
+ .asciz "XScale-Core3"
+ .size cpu_xsc3_name, . - cpu_xsc3_name
+
+ .align
+
+ .section ".proc.info.init", #alloc, #execinstr
+
+ .type __xsc3_proc_info,#object
+__xsc3_proc_info:
+ .long 0x69056000
+ .long 0xffffe000
+ .long 0x00000c0e
+ b __xsc3_setup
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+ .long cpu_xsc3_name
+ .long xsc3_processor_functions
+ .long v4wbi_tlb_fns
+ .long xsc3_mc_user_fns
+ .long xsc3_cache_fns
+ .size __xsc3_proc_info, . - __xsc3_proc_info
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 0887bb2a255..ec49495e651 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -70,13 +70,13 @@ config OMAP_MPU_TIMER
config OMAP_32K_TIMER
bool "Use 32KHz timer"
- depends on ARCH_OMAP16XX
+ depends on ARCH_OMAP16XX || ARCH_OMAP24XX
help
Select this option if you want to enable the OMAP 32KHz timer.
This timer saves power compared to the OMAP_MPU_TIMER, and has
support for no tick during idle. The 32KHz timer provides less
intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
- currently only available for OMAP-16xx.
+ currently only available for OMAP16XX and 24XX.
endchoice
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 9ccf1943fc9..2896b454641 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -3,16 +3,16 @@
#
# Common support
-obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o
+obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o
obj-m :=
obj-n :=
obj- :=
+obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
+
# OCPI interconnect support for 1710, 1610 and 5912
obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
-# Power Management
-obj-$(CONFIG_PM) += pm.o sleep.o
obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 3c2bfc0efda..32ec04c58bc 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -21,6 +21,7 @@
#include <linux/string.h>
#include <linux/clk.h>
#include <linux/mutex.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/semaphore.h>
@@ -37,17 +38,38 @@ static struct clk_functions *arch_clock;
* Standard clock functions defined in include/linux/clk.h
*-------------------------------------------------------------------------*/
+/*
+ * Returns a clock. Note that we first try to use device id on the bus
+ * and clock name. If this fails, we try to use clock name only.
+ */
struct clk * clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
+ int idno;
+
+ if (dev == NULL || dev->bus != &platform_bus_type)
+ idno = -1;
+ else
+ idno = to_platform_device(dev)->id;
mutex_lock(&clocks_mutex);
+
+ list_for_each_entry(p, &clocks, node) {
+ if (p->id == idno &&
+ strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+ clk = p;
+ goto found;
+ }
+ }
+
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
+
+found:
mutex_unlock(&clocks_mutex);
return clk;
@@ -59,6 +81,9 @@ int clk_enable(struct clk *clk)
unsigned long flags;
int ret = 0;
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_enable)
ret = arch_clock->clk_enable(clk);
@@ -72,6 +97,9 @@ void clk_disable(struct clk *clk)
{
unsigned long flags;
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_disable)
arch_clock->clk_disable(clk);
@@ -84,6 +112,9 @@ int clk_get_usecount(struct clk *clk)
unsigned long flags;
int ret = 0;
+ if (clk == NULL || IS_ERR(clk))
+ return 0;
+
spin_lock_irqsave(&clockfw_lock, flags);
ret = clk->usecount;
spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -97,6 +128,9 @@ unsigned long clk_get_rate(struct clk *clk)
unsigned long flags;
unsigned long ret = 0;
+ if (clk == NULL || IS_ERR(clk))
+ return 0;
+
spin_lock_irqsave(&clockfw_lock, flags);
ret = clk->rate;
spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -121,6 +155,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
unsigned long flags;
long ret = 0;
+ if (clk == NULL || IS_ERR(clk))
+ return ret;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_round_rate)
ret = arch_clock->clk_round_rate(clk, rate);
@@ -133,7 +170,10 @@ EXPORT_SYMBOL(clk_round_rate);
int clk_set_rate(struct clk *clk, unsigned long rate)
{
unsigned long flags;
- int ret = 0;
+ int ret = -EINVAL;
+
+ if (clk == NULL || IS_ERR(clk))
+ return ret;
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_set_rate)
@@ -147,7 +187,10 @@ EXPORT_SYMBOL(clk_set_rate);
int clk_set_parent(struct clk *clk, struct clk *parent)
{
unsigned long flags;
- int ret = 0;
+ int ret = -EINVAL;
+
+ if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
+ return ret;
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_set_parent)
@@ -163,6 +206,9 @@ struct clk *clk_get_parent(struct clk *clk)
unsigned long flags;
struct clk * ret = NULL;
+ if (clk == NULL || IS_ERR(clk))
+ return ret;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_get_parent)
ret = arch_clock->clk_get_parent(clk);
@@ -199,6 +245,9 @@ __setup("mpurate=", omap_clk_setup);
/* Used for clocks that always have same value as the parent clock */
void followparent_recalc(struct clk *clk)
{
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
clk->rate = clk->parent->rate;
}
@@ -207,6 +256,9 @@ void propagate_rate(struct clk * tclk)
{
struct clk *clkp;
+ if (tclk == NULL || IS_ERR(tclk))
+ return;
+
list_for_each_entry(clkp, &clocks, node) {
if (likely(clkp->parent != tclk))
continue;
@@ -217,6 +269,9 @@ void propagate_rate(struct clk * tclk)
int clk_register(struct clk *clk)
{
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
if (clk->init)
@@ -229,6 +284,9 @@ EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
{
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
mutex_lock(&clocks_mutex);
list_del(&clk->node);
mutex_unlock(&clocks_mutex);
@@ -239,6 +297,9 @@ void clk_deny_idle(struct clk *clk)
{
unsigned long flags;
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_deny_idle)
arch_clock->clk_deny_idle(clk);
@@ -250,6 +311,9 @@ void clk_allow_idle(struct clk *clk)
{
unsigned long flags;
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_allow_idle)
arch_clock->clk_allow_idle(clk);
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index 9dcce904b60..5d5d6eb222d 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -24,14 +24,7 @@
#include <asm/arch/board.h>
#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
-
-
-void omap_nop_release(struct device *dev)
-{
- /* Nothing */
-}
-
-/*-------------------------------------------------------------------------*/
+#include <asm/arch/menelaus.h>
#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
@@ -58,9 +51,6 @@ static struct resource i2c_resources1[] = {
static struct platform_device omap_i2c_device1 = {
.name = "i2c_omap",
.id = 1,
- .dev = {
- .release = omap_nop_release,
- },
.num_resources = ARRAY_SIZE(i2c_resources1),
.resource = i2c_resources1,
};
@@ -98,6 +88,62 @@ static inline void omap_init_i2c(void) {}
#endif
/*-------------------------------------------------------------------------*/
+#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+
+static void omap_init_kp(void)
+{
+ if (machine_is_omap_h2() || machine_is_omap_h3()) {
+ omap_cfg_reg(F18_1610_KBC0);
+ omap_cfg_reg(D20_1610_KBC1);
+ omap_cfg_reg(D19_1610_KBC2);
+ omap_cfg_reg(E18_1610_KBC3);
+ omap_cfg_reg(C21_1610_KBC4);
+
+ omap_cfg_reg(G18_1610_KBR0);
+ omap_cfg_reg(F19_1610_KBR1);
+ omap_cfg_reg(H14_1610_KBR2);
+ omap_cfg_reg(E20_1610_KBR3);
+ omap_cfg_reg(E19_1610_KBR4);
+ omap_cfg_reg(N19_1610_KBR5);
+ } else if (machine_is_omap_perseus2()) {
+ omap_cfg_reg(E2_730_KBR0);
+ omap_cfg_reg(J7_730_KBR1);
+ omap_cfg_reg(E1_730_KBR2);
+ omap_cfg_reg(F3_730_KBR3);
+ omap_cfg_reg(D2_730_KBR4);
+
+ omap_cfg_reg(C2_730_KBC0);
+ omap_cfg_reg(D3_730_KBC1);
+ omap_cfg_reg(E4_730_KBC2);
+ omap_cfg_reg(F4_730_KBC3);
+ omap_cfg_reg(E3_730_KBC4);
+ } else if (machine_is_omap_h4()) {
+ omap_cfg_reg(T19_24XX_KBR0);
+ omap_cfg_reg(R19_24XX_KBR1);
+ omap_cfg_reg(V18_24XX_KBR2);
+ omap_cfg_reg(M21_24XX_KBR3);
+ omap_cfg_reg(E5__24XX_KBR4);
+ if (omap_has_menelaus()) {
+ omap_cfg_reg(B3__24XX_KBR5);
+ omap_cfg_reg(AA4_24XX_KBC2);
+ omap_cfg_reg(B13_24XX_KBC6);
+ } else {
+ omap_cfg_reg(M18_24XX_KBR5);
+ omap_cfg_reg(H19_24XX_KBC2);
+ omap_cfg_reg(N19_24XX_KBC6);
+ }
+ omap_cfg_reg(R20_24XX_KBC0);
+ omap_cfg_reg(M14_24XX_KBC1);
+ omap_cfg_reg(V17_24XX_KBC3);
+ omap_cfg_reg(P21_24XX_KBC4);
+ omap_cfg_reg(L14_24XX_KBC5);
+ }
+}
+#else
+static inline void omap_init_kp(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
@@ -130,7 +176,6 @@ static struct platform_device mmc_omap_device1 = {
.name = "mmci-omap",
.id = 1,
.dev = {
- .release = omap_nop_release,
.dma_mask = &mmc1_dmamask,
.platform_data = &mmc1_conf,
},
@@ -160,7 +205,6 @@ static struct platform_device mmc_omap_device2 = {
.name = "mmci-omap",
.id = 2,
.dev = {
- .release = omap_nop_release,
.dma_mask = &mmc2_dmamask,
.platform_data = &mmc2_conf,
},
@@ -240,6 +284,52 @@ static void __init omap_init_mmc(void)
static inline void omap_init_mmc(void) {}
#endif
+/*-------------------------------------------------------------------------*/
+
+/* Numbering for the SPI-capable controllers when used for SPI:
+ * spi = 1
+ * uwire = 2
+ * mmc1..2 = 3..4
+ * mcbsp1..3 = 5..7
+ */
+
+#if defined(CONFIG_SPI_OMAP_UWIRE) || defined(CONFIG_SPI_OMAP_UWIRE_MODULE)
+
+#define OMAP_UWIRE_BASE 0xfffb3000
+
+static struct resource uwire_resources[] = {
+ {
+ .start = OMAP_UWIRE_BASE,
+ .end = OMAP_UWIRE_BASE + 0x20,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device omap_uwire_device = {
+ .name = "omap_uwire",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(uwire_resources),
+ .resource = uwire_resources,
+};
+
+static void omap_init_uwire(void)
+{
+ /* FIXME define and use a boot tag; not all boards will be hooking
+ * up devices to the microwire controller, and multi-board configs
+ * mean that CONFIG_SPI_OMAP_UWIRE may be configured anyway...
+ */
+
+ /* board-specific code must configure chipselects (only a few
+ * are normally used) and SCLK/SDI/SDO (each has two choices).
+ */
+ (void) platform_device_register(&omap_uwire_device);
+}
+#else
+static inline void omap_init_uwire(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
#ifdef CONFIG_ARCH_OMAP24XX
@@ -259,9 +349,6 @@ static struct resource wdt_resources[] = {
static struct platform_device omap_wdt_device = {
.name = "omap_wdt",
.id = -1,
- .dev = {
- .release = omap_nop_release,
- },
.num_resources = ARRAY_SIZE(wdt_resources),
.resource = wdt_resources,
};
@@ -295,9 +382,6 @@ static struct resource rng_resources[] = {
static struct platform_device omap_rng_device = {
.name = "omap_rng",
.id = -1,
- .dev = {
- .release = omap_nop_release,
- },
.num_resources = ARRAY_SIZE(rng_resources),
.resource = rng_resources,
};
@@ -310,40 +394,6 @@ static void omap_init_rng(void)
static inline void omap_init_rng(void) {}
#endif
-#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
-
-static struct omap_lcd_config omap_fb_conf;
-
-static u64 omap_fb_dma_mask = ~(u32)0;
-
-static struct platform_device omap_fb_device = {
- .name = "omapfb",
- .id = -1,
- .dev = {
- .release = omap_nop_release,
- .dma_mask = &omap_fb_dma_mask,
- .coherent_dma_mask = ~(u32)0,
- .platform_data = &omap_fb_conf,
- },
- .num_resources = 0,
-};
-
-static inline void omap_init_fb(void)
-{
- const struct omap_lcd_config *conf;
-
- conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
- if (conf != NULL)
- omap_fb_conf = *conf;
- platform_device_register(&omap_fb_device);
-}
-
-#else
-
-static inline void omap_init_fb(void) {}
-
-#endif
-
/*
* This gets called after board-specific INIT_MACHINE, and initializes most
* on-chip peripherals accessible on this board (except for few like USB):
@@ -369,9 +419,10 @@ static int __init omap_init_devices(void)
/* please keep these calls, and their implementations above,
* in alphabetical order so they're easier to sort through.
*/
- omap_init_fb();
omap_init_i2c();
+ omap_init_kp();
omap_init_mmc();
+ omap_init_uwire();
omap_init_wdt();
omap_init_rng();
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index a4e5ac77f6d..5dac4230360 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -1258,6 +1258,11 @@ void omap_stop_lcd_dma(void)
omap_writew(w, OMAP1610_DMA_LCD_CTRL);
}
+int omap_lcd_dma_ext_running(void)
+{
+ return lcd_dma.ext_ctrl && lcd_dma.active;
+}
+
/*----------------------------------------------------------------------------*/
static int __init omap_init_dma(void)
@@ -1389,6 +1394,7 @@ EXPORT_SYMBOL(omap_free_lcd_dma);
EXPORT_SYMBOL(omap_enable_lcd_dma);
EXPORT_SYMBOL(omap_setup_lcd_dma);
EXPORT_SYMBOL(omap_stop_lcd_dma);
+EXPORT_SYMBOL(omap_lcd_dma_ext_running);
EXPORT_SYMBOL(omap_set_lcd_dma_b1);
EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer);
EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 38d7ebf8792..eba3cb52ad8 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -97,6 +97,32 @@ int omap_dm_timers_active(void)
}
+/**
+ * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
+ * @inputmask: current value of idlect mask
+ */
+__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
+{
+ int n;
+
+ /* If ARMXOR cannot be idled this function call is unnecessary */
+ if (!(inputmask & (1 << 1)))
+ return inputmask;
+
+ /* If any active timer is using ARMXOR return modified mask */
+ for (n = 0; dm_timers[n].base; ++n)
+ if (omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG)&
+ OMAP_TIMER_CTRL_ST) {
+ if (((omap_readl(MOD_CONF_CTRL_1)>>(n*2)) & 0x03) == 0)
+ inputmask &= ~(1 << 1);
+ else
+ inputmask &= ~(1 << 2);
+ }
+
+ return inputmask;
+}
+
+
void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
int n = (timer - dm_timers) << 1;
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
new file mode 100644
index 00000000000..305e9b990b7
--- /dev/null
+++ b/arch/arm/plat-omap/fb.c
@@ -0,0 +1,80 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/omapfb.h>
+
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
+
+static struct omapfb_platform_data omapfb_config;
+
+static u64 omap_fb_dma_mask = ~(u32)0;
+
+static struct platform_device omap_fb_device = {
+ .name = "omapfb",
+ .id = -1,
+ .dev = {
+ .dma_mask = &omap_fb_dma_mask,
+ .coherent_dma_mask = ~(u32)0,
+ .platform_data = &omapfb_config,
+ },
+ .num_resources = 0,
+};
+
+/* called from map_io */
+void omapfb_reserve_mem(void)
+{
+ const struct omap_fbmem_config *fbmem_conf;
+
+ omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start;
+ omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size;
+
+ fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
+
+ if (fbmem_conf != NULL) {
+ /* indicate that the bootloader already initialized the
+ * fb device, so we'll skip that part in the fb driver
+ */
+ omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start;
+ omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size;
+ if (fbmem_conf->fb_sdram_size) {
+ pr_info("Reserving %u bytes SDRAM for frame buffer\n",
+ fbmem_conf->fb_sdram_size);
+ reserve_bootmem(fbmem_conf->fb_sdram_start,
+ fbmem_conf->fb_sdram_size);
+ }
+ }
+}
+
+static inline int omap_init_fb(void)
+{
+ const struct omap_lcd_config *conf;
+
+ conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
+ if (conf == NULL)
+ return 0;
+
+ omapfb_config.lcd = *conf;
+
+ return platform_device_register(&omap_fb_device);
+}
+
+arch_initcall(omap_init_fb);
+
+#else
+
+void omapfb_reserve_mem(void) {}
+
+#endif
+
+
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index b4d5b9e4bfc..d3c8ea7eecf 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -174,7 +174,7 @@ static int gpio_bank_count;
static inline struct gpio_bank *get_gpio_bank(int gpio)
{
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
if (OMAP_GPIO_IS_MPUIO(gpio))
return &gpio_bank[0];
return &gpio_bank[1];
@@ -223,7 +223,7 @@ static inline int gpio_valid(int gpio)
return 0;
}
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510() && gpio < 16)
+ if (cpu_is_omap15xx() && gpio < 16)
return 0;
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
@@ -402,13 +402,13 @@ static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int tr
u32 gpio_bit = 1 << gpio;
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
- trigger & IRQT_LOW);
+ trigger & __IRQT_LOWLVL);
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
- trigger & IRQT_HIGH);
+ trigger & __IRQT_HIGHLVL);
MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
- trigger & IRQT_RISING);
+ trigger & __IRQT_RISEDGE);
MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
- trigger & IRQT_FALLING);
+ trigger & __IRQT_FALEDGE);
/* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
* triggering requested. */
}
@@ -422,9 +422,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
case METHOD_MPUIO:
reg += OMAP_MPUIO_GPIO_INT_EDGE;
l = __raw_readl(reg);
- if (trigger == IRQT_RISING)
+ if (trigger & __IRQT_RISEDGE)
l |= 1 << gpio;
- else if (trigger == IRQT_FALLING)
+ else if (trigger & __IRQT_FALEDGE)
l &= ~(1 << gpio);
else
goto bad;
@@ -432,9 +432,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
case METHOD_GPIO_1510:
reg += OMAP1510_GPIO_INT_CONTROL;
l = __raw_readl(reg);
- if (trigger == IRQT_RISING)
+ if (trigger & __IRQT_RISEDGE)
l |= 1 << gpio;
- else if (trigger == IRQT_FALLING)
+ else if (trigger & __IRQT_FALEDGE)
l &= ~(1 << gpio);
else
goto bad;
@@ -446,20 +446,21 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
reg += OMAP1610_GPIO_EDGE_CTRL1;
gpio &= 0x07;
/* We allow only edge triggering, i.e. two lowest bits */
- if (trigger & ~IRQT_BOTHEDGE)
+ if (trigger & (__IRQT_LOWLVL | __IRQT_HIGHLVL))
BUG();
- /* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */
- trigger &= 0x03;
l = __raw_readl(reg);
l &= ~(3 << (gpio << 1));
- l |= trigger << (gpio << 1);
+ if (trigger & __IRQT_RISEDGE)
+ l |= 2 << (gpio << 1);
+ if (trigger & __IRQT_FALEDGE)
+ l |= 1 << (gpio << 1);
break;
case METHOD_GPIO_730:
reg += OMAP730_GPIO_INT_CONTROL;
l = __raw_readl(reg);
- if (trigger == IRQT_RISING)
+ if (trigger & __IRQT_RISEDGE)
l |= 1 << gpio;
- else if (trigger == IRQT_FALLING)
+ else if (trigger & __IRQT_FALEDGE)
l &= ~(1 << gpio);
else
goto bad;
@@ -491,7 +492,9 @@ static int gpio_irq_type(unsigned irq, unsigned type)
if (check_gpio(gpio) < 0)
return -EINVAL;
- if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE))
+ if (type & IRQT_PROBE)
+ return -EINVAL;
+ if (!cpu_is_omap24xx() && (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL)))
return -EINVAL;
bank = get_gpio_bank(gpio);
@@ -755,13 +758,32 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
if (bank->method == METHOD_GPIO_24XX)
isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
#endif
-
while(1) {
- isr = __raw_readl(isr_reg);
- _enable_gpio_irqbank(bank, isr, 0);
- _clear_gpio_irqbank(bank, isr);
- _enable_gpio_irqbank(bank, isr, 1);
- desc->chip->unmask(irq);
+ u32 isr_saved, level_mask = 0;
+
+ isr_saved = isr = __raw_readl(isr_reg);
+
+ if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
+ isr &= 0x0000ffff;
+
+ if (cpu_is_omap24xx())
+ level_mask =
+ __raw_readl(bank->base +
+ OMAP24XX_GPIO_LEVELDETECT0) |
+ __raw_readl(bank->base +
+ OMAP24XX_GPIO_LEVELDETECT1);
+
+ /* clear edge sensitive interrupts before handler(s) are
+ called so that we don't miss any interrupt occurred while
+ executing them */
+ _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
+ _clear_gpio_irqbank(bank, isr_saved & ~level_mask);
+ _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
+
+ /* if there is only edge sensitive GPIO pin interrupts
+ configured, we could unmask GPIO bank interrupt immediately */
+ if (!level_mask)
+ desc->chip->unmask(irq);
if (!isr)
break;
@@ -774,6 +796,20 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
d = irq_desc + gpio_irq;
desc_handle_irq(gpio_irq, d, regs);
}
+
+ if (cpu_is_omap24xx()) {
+ /* clear level sensitive interrupts after handler(s) */
+ _enable_gpio_irqbank(bank, isr_saved & level_mask, 0);
+ _clear_gpio_irqbank(bank, isr_saved & level_mask);
+ _enable_gpio_irqbank(bank, isr_saved & level_mask, 1);
+ }
+
+ /* if bank has any level sensitive GPIO pin interrupt
+ configured, we must unmask the bank interrupt only after
+ handler(s) are executed in order to avoid spurious bank
+ interrupt */
+ if (level_mask)
+ desc->chip->unmask(irq);
}
}
@@ -848,7 +884,7 @@ static int __init _omap_gpio_init(void)
initialized = 1;
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
gpio_ick = clk_get(NULL, "arm_gpio_ck");
if (IS_ERR(gpio_ick))
printk("Could not get arm_gpio_ck\n");
@@ -869,7 +905,7 @@ static int __init _omap_gpio_init(void)
}
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
printk(KERN_INFO "OMAP1510 GPIO hardware\n");
gpio_bank_count = 2;
gpio_bank = gpio_bank_1510;
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 1cd2cace7e1..196aac3ac32 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -34,7 +34,7 @@
#ifdef CONFIG_MCBSP_DEBUG
#define DBG(x...) printk(x)
#else
-#define DBG(x...) do { } while (0)
+#define DBG(x...) do { } while (0)
#endif
struct omap_mcbsp {
@@ -44,6 +44,7 @@ struct omap_mcbsp {
omap_mcbsp_word_length rx_word_length;
omap_mcbsp_word_length tx_word_length;
+ omap_mcbsp_io_type_t io_type; /* IRQ or poll */
/* IRQ based TX/RX */
int rx_irq;
int tx_irq;
@@ -64,10 +65,19 @@ struct omap_mcbsp {
};
static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
+#ifdef CONFIG_ARCH_OMAP1
static struct clk *mcbsp_dsp_ck = 0;
static struct clk *mcbsp_api_ck = 0;
static struct clk *mcbsp_dspxor_ck = 0;
-
+#endif
+#ifdef CONFIG_ARCH_OMAP2
+static struct clk *mcbsp1_ick = 0;
+static struct clk *mcbsp1_fck = 0;
+static struct clk *mcbsp2_ick = 0;
+static struct clk *mcbsp2_fck = 0;
+static struct clk *sys_ck = 0;
+static struct clk *sys_clkout = 0;
+#endif
static void omap_mcbsp_dump_reg(u8 id)
{
@@ -88,7 +98,6 @@ static void omap_mcbsp_dump_reg(u8 id)
DBG("***********************\n");
}
-
static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
@@ -109,7 +118,6 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_re
return IRQ_HANDLED;
}
-
static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
{
struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data);
@@ -176,7 +184,7 @@ static int omap_mcbsp_check(unsigned int id)
return 0;
}
- if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+ if (cpu_is_omap15xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) {
if (id > OMAP_MAX_MCBSP_COUNT) {
printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
return -1;
@@ -187,9 +195,10 @@ static int omap_mcbsp_check(unsigned int id)
return -1;
}
+#ifdef CONFIG_ARCH_OMAP1
static void omap_mcbsp_dsp_request(void)
{
- if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+ if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
clk_enable(mcbsp_dsp_ck);
clk_enable(mcbsp_api_ck);
@@ -207,12 +216,49 @@ static void omap_mcbsp_dsp_request(void)
static void omap_mcbsp_dsp_free(void)
{
- if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+ if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
clk_disable(mcbsp_dspxor_ck);
clk_disable(mcbsp_dsp_ck);
clk_disable(mcbsp_api_ck);
}
}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+static void omap2_mcbsp2_mux_setup(void)
+{
+ omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
+ omap_cfg_reg(R14_24XX_MCBSP2_FSX);
+ omap_cfg_reg(W15_24XX_MCBSP2_DR);
+ omap_cfg_reg(V15_24XX_MCBSP2_DX);
+ omap_cfg_reg(V14_24XX_GPIO117);
+ omap_cfg_reg(W14_24XX_SYS_CLKOUT);
+}
+#endif
+
+/*
+ * We can choose between IRQ based or polled IO.
+ * This needs to be called before omap_mcbsp_request().
+ */
+int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type)
+{
+ if (omap_mcbsp_check(id) < 0)
+ return -EINVAL;
+
+ spin_lock(&mcbsp[id].lock);
+
+ if (!mcbsp[id].free) {
+ printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
+ spin_unlock(&mcbsp[id].lock);
+ return -EINVAL;
+ }
+
+ mcbsp[id].io_type = io_type;
+
+ spin_unlock(&mcbsp[id].lock);
+
+ return 0;
+}
int omap_mcbsp_request(unsigned int id)
{
@@ -221,12 +267,26 @@ int omap_mcbsp_request(unsigned int id)
if (omap_mcbsp_check(id) < 0)
return -EINVAL;
+#ifdef CONFIG_ARCH_OMAP1
/*
* On 1510, 1610 and 1710, McBSP1 and McBSP3
* are DSP public peripherals.
*/
if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
omap_mcbsp_dsp_request();
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+ if (cpu_is_omap24xx()) {
+ if (id == OMAP_MCBSP1) {
+ clk_enable(mcbsp1_ick);
+ clk_enable(mcbsp1_fck);
+ } else {
+ clk_enable(mcbsp2_ick);
+ clk_enable(mcbsp2_fck);
+ }
+ }
+#endif
spin_lock(&mcbsp[id].lock);
if (!mcbsp[id].free) {
@@ -238,30 +298,33 @@ int omap_mcbsp_request(unsigned int id)
mcbsp[id].free = 0;
spin_unlock(&mcbsp[id].lock);
- /* We need to get IRQs here */
- err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
- "McBSP",
- (void *) (&mcbsp[id]));
- if (err != 0) {
- printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
- mcbsp[id].tx_irq, mcbsp[id].id);
- return err;
- }
+ if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
+ /* We need to get IRQs here */
+ err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
+ "McBSP",
+ (void *) (&mcbsp[id]));
+ if (err != 0) {
+ printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
+ mcbsp[id].tx_irq, mcbsp[id].id);
+ return err;
+ }
- init_completion(&(mcbsp[id].tx_irq_completion));
+ init_completion(&(mcbsp[id].tx_irq_completion));
- err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
- "McBSP",
- (void *) (&mcbsp[id]));
- if (err != 0) {
- printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
- mcbsp[id].rx_irq, mcbsp[id].id);
- free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
- return err;
+ err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
+ "McBSP",
+ (void *) (&mcbsp[id]));
+ if (err != 0) {
+ printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
+ mcbsp[id].rx_irq, mcbsp[id].id);
+ free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+ return err;
+ }
+
+ init_completion(&(mcbsp[id].rx_irq_completion));
}
- init_completion(&(mcbsp[id].rx_irq_completion));
return 0;
}
@@ -271,8 +334,24 @@ void omap_mcbsp_free(unsigned int id)
if (omap_mcbsp_check(id) < 0)
return;
- if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
- omap_mcbsp_dsp_free();
+#ifdef CONFIG_ARCH_OMAP1
+ if (cpu_class_is_omap1()) {
+ if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
+ omap_mcbsp_dsp_free();
+ }
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+ if (cpu_is_omap24xx()) {
+ if (id == OMAP_MCBSP1) {
+ clk_disable(mcbsp1_ick);
+ clk_disable(mcbsp1_fck);
+ } else {
+ clk_disable(mcbsp2_ick);
+ clk_disable(mcbsp2_fck);
+ }
+ }
+#endif
spin_lock(&mcbsp[id].lock);
if (mcbsp[id].free) {
@@ -284,9 +363,11 @@ void omap_mcbsp_free(unsigned int id)
mcbsp[id].free = 1;
spin_unlock(&mcbsp[id].lock);
- /* Free IRQs */
- free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
- free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+ if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
+ /* Free IRQs */
+ free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
+ free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+ }
}
/*
@@ -461,6 +542,115 @@ u32 omap_mcbsp_recv_word(unsigned int id)
}
+int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
+{
+ u32 io_base = mcbsp[id].io_base;
+ omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;
+ omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;
+ u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
+
+ if (tx_word_length != rx_word_length)
+ return -EINVAL;
+
+ /* First we wait for the transmitter to be ready */
+ spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+ while (!(spcr2 & XRDY)) {
+ spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+ if (attempts++ > 1000) {
+ /* We must reset the transmitter */
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST));
+ udelay(10);
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
+ udelay(10);
+ printk("McBSP transmitter not ready\n");
+ return -EAGAIN;
+ }
+ }
+
+ /* Now we can push the data */
+ if (tx_word_length > OMAP_MCBSP_WORD_16)
+ OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
+ OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
+
+ /* We wait for the receiver to be ready */
+ spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+ while (!(spcr1 & RRDY)) {
+ spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+ if (attempts++ > 1000) {
+ /* We must reset the receiver */
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST));
+ udelay(10);
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
+ udelay(10);
+ printk("McBSP receiver not ready\n");
+ return -EAGAIN;
+ }
+ }
+
+ /* Receiver is ready, let's read the dummy data */
+ if (rx_word_length > OMAP_MCBSP_WORD_16)
+ word_msb = OMAP_MCBSP_READ(io_base, DRR2);
+ word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
+
+ return 0;
+}
+
+int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word)
+{
+ u32 io_base = mcbsp[id].io_base, clock_word = 0;
+ omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;
+ omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;
+ u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
+
+ if (tx_word_length != rx_word_length)
+ return -EINVAL;
+
+ /* First we wait for the transmitter to be ready */
+ spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+ while (!(spcr2 & XRDY)) {
+ spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+ if (attempts++ > 1000) {
+ /* We must reset the transmitter */
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST));
+ udelay(10);
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
+ udelay(10);
+ printk("McBSP transmitter not ready\n");
+ return -EAGAIN;
+ }
+ }
+
+ /* We first need to enable the bus clock */
+ if (tx_word_length > OMAP_MCBSP_WORD_16)
+ OMAP_MCBSP_WRITE(io_base, DXR2, clock_word >> 16);
+ OMAP_MCBSP_WRITE(io_base, DXR1, clock_word & 0xffff);
+
+ /* We wait for the receiver to be ready */
+ spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+ while (!(spcr1 & RRDY)) {
+ spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+ if (attempts++ > 1000) {
+ /* We must reset the receiver */
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST));
+ udelay(10);
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
+ udelay(10);
+ printk("McBSP receiver not ready\n");
+ return -EAGAIN;
+ }
+ }
+
+ /* Receiver is ready, there is something for us */
+ if (rx_word_length > OMAP_MCBSP_WORD_16)
+ word_msb = OMAP_MCBSP_READ(io_base, DRR2);
+ word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
+
+ word[0] = (word_lsb | (word_msb << 16));
+
+ return 0;
+}
+
+
/*
* Simple DMA based buffer rx/tx routines.
* Nothing fancy, just a single buffer tx/rx through DMA.
@@ -471,6 +661,9 @@ u32 omap_mcbsp_recv_word(unsigned int id)
int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
{
int dma_tx_ch;
+ int src_port = 0;
+ int dest_port = 0;
+ int sync_dev = 0;
if (omap_mcbsp_check(id) < 0)
return -EINVAL;
@@ -487,20 +680,27 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
init_completion(&(mcbsp[id].tx_dma_completion));
+ if (cpu_class_is_omap1()) {
+ src_port = OMAP_DMA_PORT_TIPB;
+ dest_port = OMAP_DMA_PORT_EMIFF;
+ }
+ if (cpu_is_omap24xx())
+ sync_dev = mcbsp[id].dma_tx_sync;
+
omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
OMAP_DMA_DATA_TYPE_S16,
length >> 1, 1,
OMAP_DMA_SYNC_ELEMENT,
- 0, 0);
+ sync_dev, 0);
omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
- OMAP_DMA_PORT_TIPB,
+ src_port,
OMAP_DMA_AMODE_CONSTANT,
mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
0, 0);
omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
- OMAP_DMA_PORT_EMIFF,
+ dest_port,
OMAP_DMA_AMODE_POST_INC,
buffer,
0, 0);
@@ -514,6 +714,9 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
{
int dma_rx_ch;
+ int src_port = 0;
+ int dest_port = 0;
+ int sync_dev = 0;
if (omap_mcbsp_check(id) < 0)
return -EINVAL;
@@ -530,20 +733,27 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
init_completion(&(mcbsp[id].rx_dma_completion));
+ if (cpu_class_is_omap1()) {
+ src_port = OMAP_DMA_PORT_TIPB;
+ dest_port = OMAP_DMA_PORT_EMIFF;
+ }
+ if (cpu_is_omap24xx())
+ sync_dev = mcbsp[id].dma_rx_sync;
+
omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
OMAP_DMA_DATA_TYPE_S16,
length >> 1, 1,
OMAP_DMA_SYNC_ELEMENT,
- 0, 0);
+ sync_dev, 0);
omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
- OMAP_DMA_PORT_TIPB,
+ src_port,
OMAP_DMA_AMODE_CONSTANT,
mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
0, 0);
omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
- OMAP_DMA_PORT_EMIFF,
+ dest_port,
OMAP_DMA_AMODE_POST_INC,
buffer,
0, 0);
@@ -688,6 +898,23 @@ static const struct omap_mcbsp_info mcbsp_1610[] = {
};
#endif
+#if defined(CONFIG_ARCH_OMAP24XX)
+static const struct omap_mcbsp_info mcbsp_24xx[] = {
+ [0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),
+ .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
+ .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
+ .rx_irq = INT_24XX_MCBSP1_IRQ_RX,
+ .tx_irq = INT_24XX_MCBSP1_IRQ_TX,
+ },
+ [1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),
+ .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
+ .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
+ .rx_irq = INT_24XX_MCBSP2_IRQ_RX,
+ .tx_irq = INT_24XX_MCBSP2_IRQ_TX,
+ },
+};
+#endif
+
static int __init omap_mcbsp_init(void)
{
int mcbsp_count = 0, i;
@@ -695,6 +922,7 @@ static int __init omap_mcbsp_init(void)
printk("Initializing OMAP McBSP system\n");
+#ifdef CONFIG_ARCH_OMAP1
mcbsp_dsp_ck = clk_get(0, "dsp_ck");
if (IS_ERR(mcbsp_dsp_ck)) {
printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");
@@ -710,6 +938,29 @@ static int __init omap_mcbsp_init(void)
printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n");
return PTR_ERR(mcbsp_dspxor_ck);
}
+#endif
+#ifdef CONFIG_ARCH_OMAP2
+ mcbsp1_ick = clk_get(0, "mcbsp1_ick");
+ if (IS_ERR(mcbsp1_ick)) {
+ printk(KERN_ERR "mcbsp: could not acquire mcbsp1_ick handle.\n");
+ return PTR_ERR(mcbsp1_ick);
+ }
+ mcbsp1_fck = clk_get(0, "mcbsp1_fck");
+ if (IS_ERR(mcbsp1_fck)) {
+ printk(KERN_ERR "mcbsp: could not acquire mcbsp1_fck handle.\n");
+ return PTR_ERR(mcbsp1_fck);
+ }
+ mcbsp2_ick = clk_get(0, "mcbsp2_ick");
+ if (IS_ERR(mcbsp2_ick)) {
+ printk(KERN_ERR "mcbsp: could not acquire mcbsp2_ick handle.\n");
+ return PTR_ERR(mcbsp2_ick);
+ }
+ mcbsp2_fck = clk_get(0, "mcbsp2_fck");
+ if (IS_ERR(mcbsp2_fck)) {
+ printk(KERN_ERR "mcbsp: could not acquire mcbsp2_fck handle.\n");
+ return PTR_ERR(mcbsp2_fck);
+ }
+#endif
#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730()) {
@@ -718,7 +969,7 @@ static int __init omap_mcbsp_init(void)
}
#endif
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
mcbsp_info = mcbsp_1510;
mcbsp_count = ARRAY_SIZE(mcbsp_1510);
}
@@ -729,6 +980,19 @@ static int __init omap_mcbsp_init(void)
mcbsp_count = ARRAY_SIZE(mcbsp_1610);
}
#endif
+#if defined(CONFIG_ARCH_OMAP24XX)
+ if (cpu_is_omap24xx()) {
+ mcbsp_info = mcbsp_24xx;
+ mcbsp_count = ARRAY_SIZE(mcbsp_24xx);
+
+ /* REVISIT: where's the right place? */
+ omap2_mcbsp2_mux_setup();
+ sys_ck = clk_get(0, "sys_ck");
+ sys_clkout = clk_get(0, "sys_clkout");
+ clk_set_parent(sys_clkout, sys_ck);
+ clk_enable(sys_clkout);
+ }
+#endif
for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
if (i >= mcbsp_count) {
mcbsp[i].io_base = 0;
@@ -741,6 +1005,7 @@ static int __init omap_mcbsp_init(void)
mcbsp[i].dma_rx_lch = -1;
mcbsp[i].io_base = mcbsp_info[i].virt_base;
+ mcbsp[i].io_type = OMAP_MCBSP_IRQ_IO; /* Default I/O is IRQ based */
mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
@@ -751,11 +1016,11 @@ static int __init omap_mcbsp_init(void)
return 0;
}
-
arch_initcall(omap_mcbsp_init);
EXPORT_SYMBOL(omap_mcbsp_config);
EXPORT_SYMBOL(omap_mcbsp_request);
+EXPORT_SYMBOL(omap_mcbsp_set_io_type);
EXPORT_SYMBOL(omap_mcbsp_free);
EXPORT_SYMBOL(omap_mcbsp_start);
EXPORT_SYMBOL(omap_mcbsp_stop);
@@ -763,4 +1028,6 @@ EXPORT_SYMBOL(omap_mcbsp_xmit_word);
EXPORT_SYMBOL(omap_mcbsp_recv_word);
EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
+EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll);
+EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll);
EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c
index 5cc6775c789..37792d43738 100644
--- a/arch/arm/plat-omap/ocpi.c
+++ b/arch/arm/plat-omap/ocpi.c
@@ -62,9 +62,6 @@ int ocpi_enable(void)
if (!cpu_is_omap16xx())
return -ENODEV;
- /* Make sure there's clock for OCPI */
- clk_enable(ocpi_ck);
-
/* Enable access for OHCI in OCPI */
val = omap_readl(OCPI_PROT);
val &= ~0xff;
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c
index 093efd786f2..1a24e2c1071 100644
--- a/arch/arm/plat-omap/pm.c
+++ b/arch/arm/plat-omap/pm.c
@@ -38,6 +38,7 @@
#include <linux/pm.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
+#include <linux/pm.h>
#include <linux/interrupt.h>
#include <asm/io.h>
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index ee82763b02b..b7bf09b1b41 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -16,24 +16,94 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <asm/mach/map.h>
#include <asm/tlb.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
+#include <asm/mach/map.h>
+
#include <asm/arch/sram.h>
+#include <asm/arch/board.h>
#define OMAP1_SRAM_PA 0x20000000
#define OMAP1_SRAM_VA 0xd0000000
#define OMAP2_SRAM_PA 0x40200000
+#define OMAP2_SRAM_PUB_PA 0x4020f800
#define OMAP2_SRAM_VA 0xd0000000
+#define OMAP2_SRAM_PUB_VA 0xd0000800
+#if defined(CONFIG_ARCH_OMAP24XX)
+#define SRAM_BOOTLOADER_SZ 0x00
+#else
#define SRAM_BOOTLOADER_SZ 0x80
+#endif
+
+#define VA_REQINFOPERM0 IO_ADDRESS(0x68005048)
+#define VA_READPERM0 IO_ADDRESS(0x68005050)
+#define VA_WRITEPERM0 IO_ADDRESS(0x68005058)
+#define VA_CONTROL_STAT IO_ADDRESS(0x480002F8)
+#define GP_DEVICE 0x300
+#define TYPE_MASK 0x700
+
+#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1)))
static unsigned long omap_sram_base;
static unsigned long omap_sram_size;
static unsigned long omap_sram_ceil;
+unsigned long omap_fb_sram_start;
+unsigned long omap_fb_sram_size;
+
+/* Depending on the target RAMFS firewall setup, the public usable amount of
+ * SRAM varies. The default accessable size for all device types is 2k. A GP
+ * device allows ARM11 but not other initators for full size. This
+ * functionality seems ok until some nice security API happens.
+ */
+static int is_sram_locked(void)
+{
+ int type = 0;
+
+ if (cpu_is_omap242x())
+ type = __raw_readl(VA_CONTROL_STAT) & TYPE_MASK;
+
+ if (type == GP_DEVICE) {
+ /* RAMFW: R/W access to all initators for all qualifier sets */
+ if (cpu_is_omap242x()) {
+ __raw_writel(0xFF, VA_REQINFOPERM0); /* all q-vects */
+ __raw_writel(0xCFDE, VA_READPERM0); /* all i-read */
+ __raw_writel(0xCFDE, VA_WRITEPERM0); /* all i-write */
+ }
+ return 0;
+ } else
+ return 1; /* assume locked with no PPA or security driver */
+}
+
+void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail,
+ unsigned long *start, unsigned long *size)
+{
+ const struct omap_fbmem_config *fbmem_conf;
+
+ fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
+ if (fbmem_conf != NULL) {
+ *start = fbmem_conf->fb_sram_start;
+ *size = fbmem_conf->fb_sram_size;
+ } else {
+ *size = 0;
+ *start = 0;
+ }
+
+ if (*size && (
+ *start < start_avail ||
+ *start + *size > start_avail + size_avail)) {
+ printk(KERN_ERR "invalid FB SRAM configuration\n");
+ *start = start_avail;
+ *size = size_avail;
+ }
+
+ if (*size)
+ pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size);
+}
+
/*
* The amount of SRAM depends on the core type.
* Note that we cannot try to test for SRAM here because writes
@@ -42,26 +112,45 @@ static unsigned long omap_sram_ceil;
*/
void __init omap_detect_sram(void)
{
- if (!cpu_is_omap24xx())
+ unsigned long sram_start;
+
+ if (cpu_is_omap24xx()) {
+ if (is_sram_locked()) {
+ omap_sram_base = OMAP2_SRAM_PUB_VA;
+ sram_start = OMAP2_SRAM_PUB_PA;
+ omap_sram_size = 0x800; /* 2K */
+ } else {
+ omap_sram_base = OMAP2_SRAM_VA;
+ sram_start = OMAP2_SRAM_PA;
+ if (cpu_is_omap242x())
+ omap_sram_size = 0xa0000; /* 640K */
+ else if (cpu_is_omap243x())
+ omap_sram_size = 0x10000; /* 64K */
+ }
+ } else {
omap_sram_base = OMAP1_SRAM_VA;
- else
- omap_sram_base = OMAP2_SRAM_VA;
-
- if (cpu_is_omap730())
- omap_sram_size = 0x32000; /* 200K */
- else if (cpu_is_omap15xx())
- omap_sram_size = 0x30000; /* 192K */
- else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710())
- omap_sram_size = 0x4000; /* 16K */
- else if (cpu_is_omap1611())
- omap_sram_size = 0x3e800; /* 250K */
- else if (cpu_is_omap2420())
- omap_sram_size = 0xa0014; /* 640K */
- else {
- printk(KERN_ERR "Could not detect SRAM size\n");
- omap_sram_size = 0x4000;
+ sram_start = OMAP1_SRAM_PA;
+
+ if (cpu_is_omap730())
+ omap_sram_size = 0x32000; /* 200K */
+ else if (cpu_is_omap15xx())
+ omap_sram_size = 0x30000; /* 192K */
+ else if (cpu_is_omap1610() || cpu_is_omap1621() ||
+ cpu_is_omap1710())
+ omap_sram_size = 0x4000; /* 16K */
+ else if (cpu_is_omap1611())
+ omap_sram_size = 0x3e800; /* 250K */
+ else {
+ printk(KERN_ERR "Could not detect SRAM size\n");
+ omap_sram_size = 0x4000;
+ }
}
-
+ get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ,
+ omap_sram_size - SRAM_BOOTLOADER_SZ,
+ &omap_fb_sram_start, &omap_fb_sram_size);
+ if (omap_fb_sram_size)
+ omap_sram_size -= sram_start + omap_sram_size -
+ omap_fb_sram_start;
omap_sram_ceil = omap_sram_base + omap_sram_size;
}
@@ -80,12 +169,20 @@ static struct map_desc omap_sram_io_desc[] __initdata = {
*/
void __init omap_map_sram(void)
{
+ unsigned long base;
+
if (omap_sram_size == 0)
return;
if (cpu_is_omap24xx()) {
omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA;
- omap_sram_io_desc[0].pfn = __phys_to_pfn(OMAP2_SRAM_PA);
+
+ if (is_sram_locked())
+ base = OMAP2_SRAM_PUB_PA;
+ else
+ base = OMAP2_SRAM_PA;
+ base = ROUND_DOWN(base, PAGE_SIZE);
+ omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
}
omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE;
@@ -93,7 +190,8 @@ void __init omap_map_sram(void)
iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n",
- omap_sram_io_desc[0].pfn, omap_sram_io_desc[0].virtual,
+ __pfn_to_phys(omap_sram_io_desc[0].pfn),
+ omap_sram_io_desc[0].virtual,
omap_sram_io_desc[0].length);
/*
@@ -118,8 +216,9 @@ void * omap_sram_push(void * start, unsigned long size)
printk(KERN_ERR "Not enough space in SRAM\n");
return NULL;
}
+
omap_sram_ceil -= size;
- omap_sram_ceil &= ~0x3;
+ omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *));
memcpy((void *)omap_sram_ceil, start, size);
return (void *)omap_sram_ceil;
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
new file mode 100644
index 00000000000..b2a943bf11e
--- /dev/null
+++ b/arch/arm/plat-omap/timer32k.c
@@ -0,0 +1,325 @@
+/*
+ * linux/arch/arm/plat-omap/timer32k.c
+ *
+ * OMAP 32K Timer
+ *
+ * Copyright (C) 2004 - 2005 Nokia Corporation
+ * Partial timer rewrite and additional dynamic tick timer support by
+ * Tony Lindgen <tony@atomide.com> and
+ * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *
+ * MPU timer code based on the older MPU timer code for OMAP
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+struct sys_timer omap_timer;
+
+/*
+ * ---------------------------------------------------------------------------
+ * 32KHz OS timer
+ *
+ * This currently works only on 16xx, as 1510 does not have the continuous
+ * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
+ * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
+ * on 1510 would be possible, but the timer would not be as accurate as
+ * with the 32KHz synchronized timer.
+ * ---------------------------------------------------------------------------
+ */
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+#define TIMER_32K_SYNCHRONIZED 0xfffbc410
+#elif defined(CONFIG_ARCH_OMAP24XX)
+#define TIMER_32K_SYNCHRONIZED 0x48004010
+#else
+#error OMAP 32KHz timer does not currently work on 15XX!
+#endif
+
+/* 16xx specific defines */
+#define OMAP1_32K_TIMER_BASE 0xfffb9000
+#define OMAP1_32K_TIMER_CR 0x08
+#define OMAP1_32K_TIMER_TVR 0x00
+#define OMAP1_32K_TIMER_TCR 0x04
+
+/* 24xx specific defines */
+#define OMAP2_GP_TIMER_BASE 0x48028000
+#define CM_CLKSEL_WKUP 0x48008440
+#define GP_TIMER_TIDR 0x00
+#define GP_TIMER_TISR 0x18
+#define GP_TIMER_TIER 0x1c
+#define GP_TIMER_TCLR 0x24
+#define GP_TIMER_TCRR 0x28
+#define GP_TIMER_TLDR 0x2c
+#define GP_TIMER_TTGR 0x30
+#define GP_TIMER_TSICR 0x40
+
+#define OMAP_32K_TICKS_PER_HZ (32768 / HZ)
+
+/*
+ * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
+ * so with HZ = 128, TVR = 255.
+ */
+#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1)
+
+#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
+ (((nr_jiffies) * (clock_rate)) / HZ)
+
+static inline void omap_32k_timer_write(int val, int reg)
+{
+ if (cpu_class_is_omap1())
+ omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
+
+ if (cpu_is_omap24xx())
+ omap_writel(val, OMAP2_GP_TIMER_BASE + reg);
+}
+
+static inline unsigned long omap_32k_timer_read(int reg)
+{
+ if (cpu_class_is_omap1())
+ return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff;
+
+ if (cpu_is_omap24xx())
+ return omap_readl(OMAP2_GP_TIMER_BASE + reg);
+}
+
+/*
+ * The 32KHz synchronized timer is an additional timer on 16xx.
+ * It is always running.
+ */
+static inline unsigned long omap_32k_sync_timer_read(void)
+{
+ return omap_readl(TIMER_32K_SYNCHRONIZED);
+}
+
+static inline void omap_32k_timer_start(unsigned long load_val)
+{
+ if (cpu_class_is_omap1()) {
+ omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
+ omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
+ }
+
+ if (cpu_is_omap24xx()) {
+ omap_32k_timer_write(0xffffffff - load_val, GP_TIMER_TCRR);
+ omap_32k_timer_write((1 << 1), GP_TIMER_TIER);
+ omap_32k_timer_write((1 << 1) | 1, GP_TIMER_TCLR);
+ }
+}
+
+static inline void omap_32k_timer_stop(void)
+{
+ if (cpu_class_is_omap1())
+ omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR);
+
+ if (cpu_is_omap24xx())
+ omap_32k_timer_write(0x0, GP_TIMER_TCLR);
+}
+
+/*
+ * Rounds down to nearest usec. Note that this will overflow for larger values.
+ */
+static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
+{
+ return (ticks_32k * 5*5*5*5*5*5) >> 9;
+}
+
+/*
+ * Rounds down to nearest nsec.
+ */
+static inline unsigned long long
+omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
+{
+ return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9;
+}
+
+static unsigned long omap_32k_last_tick = 0;
+
+/*
+ * Returns elapsed usecs since last 32k timer interrupt
+ */
+static unsigned long omap_32k_timer_gettimeoffset(void)
+{
+ unsigned long now = omap_32k_sync_timer_read();
+ return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
+}
+
+/*
+ * Returns current time from boot in nsecs. It's OK for this to wrap
+ * around for now, as it's just a relative time stamp.
+ */
+unsigned long long sched_clock(void)
+{
+ return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
+}
+
+/*
+ * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
+ * function is also called from other interrupts to remove latency
+ * issues with dynamic tick. In the dynamic tick case, we need to lock
+ * with irqsave.
+ */
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ unsigned long flags;
+ unsigned long now;
+
+ write_seqlock_irqsave(&xtime_lock, flags);
+
+ if (cpu_is_omap24xx()) {
+ u32 status = omap_32k_timer_read(GP_TIMER_TISR);
+ omap_32k_timer_write(status, GP_TIMER_TISR);
+ }
+
+ now = omap_32k_sync_timer_read();
+
+ while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
+ omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
+ timer_tick(regs);
+ }
+
+ /* Restart timer so we don't drift off due to modulo or dynamic tick.
+ * By default we program the next timer to be continuous to avoid
+ * latencies during high system load. During dynamic tick operation the
+ * continuous timer can be overridden from pm_idle to be longer.
+ */
+ omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+/*
+ * Programs the next timer interrupt needed. Called when dynamic tick is
+ * enabled, and to reprogram the ticks to skip from pm_idle. Note that
+ * we can keep the timer continuous, and don't need to set it to run in
+ * one-shot mode. This is because the timer will get reprogrammed again
+ * after next interrupt.
+ */
+void omap_32k_timer_reprogram(unsigned long next_tick)
+{
+ omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
+}
+
+static struct irqaction omap_32k_timer_irq;
+extern struct timer_update_handler timer_update;
+
+static int omap_32k_timer_enable_dyn_tick(void)
+{
+ /* No need to reprogram timer, just use the next interrupt */
+ return 0;
+}
+
+static int omap_32k_timer_disable_dyn_tick(void)
+{
+ omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+ return 0;
+}
+
+static struct dyn_tick_timer omap_dyn_tick_timer = {
+ .enable = omap_32k_timer_enable_dyn_tick,
+ .disable = omap_32k_timer_disable_dyn_tick,
+ .reprogram = omap_32k_timer_reprogram,
+ .handler = omap_32k_timer_interrupt,
+};
+#endif /* CONFIG_NO_IDLE_HZ */
+
+static struct irqaction omap_32k_timer_irq = {
+ .name = "32KHz timer",
+ .flags = SA_INTERRUPT | SA_TIMER,
+ .handler = omap_32k_timer_interrupt,
+};
+
+static struct clk * gpt1_ick;
+static struct clk * gpt1_fck;
+
+static __init void omap_init_32k_timer(void)
+{
+#ifdef CONFIG_NO_IDLE_HZ
+ omap_timer.dyn_tick = &omap_dyn_tick_timer;
+#endif
+
+ if (cpu_class_is_omap1())
+ setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
+ if (cpu_is_omap24xx())
+ setup_irq(37, &omap_32k_timer_irq);
+ omap_timer.offset = omap_32k_timer_gettimeoffset;
+ omap_32k_last_tick = omap_32k_sync_timer_read();
+
+ /* REVISIT: Check 24xx TIOCP_CFG settings after idle works */
+ if (cpu_is_omap24xx()) {
+ omap_32k_timer_write(0, GP_TIMER_TCLR);
+ omap_writel(0, CM_CLKSEL_WKUP); /* 32KHz clock source */
+
+ gpt1_ick = clk_get(NULL, "gpt1_ick");
+ if (IS_ERR(gpt1_ick))
+ printk(KERN_ERR "Could not get gpt1_ick\n");
+ else
+ clk_enable(gpt1_ick);
+
+ gpt1_fck = clk_get(NULL, "gpt1_fck");
+ if (IS_ERR(gpt1_fck))
+ printk(KERN_ERR "Could not get gpt1_fck\n");
+ else
+ clk_enable(gpt1_fck);
+
+ mdelay(100); /* Wait for clocks to stabilize */
+
+ omap_32k_timer_write(0x7, GP_TIMER_TISR);
+ }
+
+ omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+ * ---------------------------------------------------------------------------
+ */
+static void __init omap_timer_init(void)
+{
+ omap_init_32k_timer();
+}
+
+struct sys_timer omap_timer = {
+ .init = omap_timer_init,
+ .offset = NULL, /* Initialized later */
+};
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 8ab5300dcb9..6d7de9c0412 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
#
# http://www.arm.linux.org.uk/developer/machines/?action=new
#
-# Last update: Mon Feb 20 10:18:02 2006
+# Last update: Mon May 8 20:11:05 2006
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -566,8 +566,8 @@ switchgrass MACH_SWITCHGRASS SWITCHGRASS 549
ens_cmu MACH_ENS_CMU ENS_CMU 550
mm6_sdb MACH_MM6_SDB MM6_SDB 551
saturn MACH_SATURN SATURN 552
-argonplusevb MACH_ARGONPLUSEVB ARGONPLUSEVB 553
-scma11evb MACH_SCMA11EVB SCMA11EVB 554
+i30030evb MACH_ARGONPLUSEVB ARGONPLUSEVB 553
+mxc27530evb MACH_SCMA11EVB SCMA11EVB 554
smdk2800 MACH_SMDK2800 SMDK2800 555
mtwilson MACH_MTWILSON MTWILSON 556
ziti MACH_ZITI ZITI 557
@@ -647,7 +647,7 @@ sendt MACH_SENDT SENDT 630
mx2jazz MACH_MX2JAZZ MX2JAZZ 631
multiio MACH_MULTIIO MULTIIO 632
hrdisplay MACH_HRDISPLAY HRDISPLAY 633
-scma11bb MACH_SCMA11BB SCMA11BB 634
+mxc27530ads MACH_SCMA11BB SCMA11BB 634
trizeps3 MACH_TRIZEPS3 TRIZEPS3 635
zefeerdza MACH_ZEFEERDZA ZEFEERDZA 636
zefeerdzb MACH_ZEFEERDZB ZEFEERDZB 637
@@ -721,7 +721,7 @@ gp32 MACH_GP32 GP32 706
gem MACH_GEM GEM 707
i858 MACH_I858 I858 708
hx2750 MACH_HX2750 HX2750 709
-zeusevb MACH_ZEUSEVB ZEUSEVB 710
+mxc91131evb MACH_ZEUSEVB ZEUSEVB 710
p700 MACH_P700 P700 711
cpe MACH_CPE CPE 712
spitz MACH_SPITZ SPITZ 713
@@ -802,7 +802,7 @@ cpuat91 MACH_CPUAT91 CPUAT91 787
rea9200 MACH_REA9200 REA9200 788
acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789
ixp425 MACH_IXP425 IXP425 790
-argonplusodyssey MACH_ARGONPLUSODYSSEY ARGONPLUSODYSSEY 791
+i30030ads MACH_ARGONPLUSODYSSEY ARGONPLUSODYSSEY 791
perch MACH_PERCH PERCH 792
eis05r1 MACH_EIS05R1 EIS05R1 793
pepperpad MACH_PEPPERPAD PEPPERPAD 794
@@ -827,7 +827,7 @@ micro9l MACH_MICRO9L MICRO9L 812
uc5471dsp MACH_UC5471DSP UC5471DSP 813
sj5471eng MACH_SJ5471ENG SJ5471ENG 814
none MACH_CMPXA26X CMPXA26X 815
-nc MACH_NC NC 816
+nc1 MACH_NC NC 816
omap_palmte MACH_OMAP_PALMTE OMAP_PALMTE 817
ajax52x MACH_AJAX52X AJAX52X 818
siriustar MACH_SIRIUSTAR SIRIUSTAR 819
@@ -930,7 +930,7 @@ netclient MACH_NETCLIENT NETCLIENT 916
xscale_palmtt5 MACH_XSCALE_PALMTT5 XSCALE_PALMTT5 917
xscale_palmtc MACH_OMAP_PALMTC OMAP_PALMTC 918
omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919
-argonlvevb MACH_ARGONLVEVB ARGONLVEVB 920
+mxc30030evb MACH_ARGONLVEVB ARGONLVEVB 920
rea_2d MACH_REA_2D REA_2D 921
eti3e524 MACH_TI3E524 TI3E524 922
ateb9200 MACH_ATEB9200 ATEB9200 923
@@ -965,7 +965,78 @@ sisteron MACH_SISTERON SISTERON 951
rx1950 MACH_RX1950 RX1950 952
tsc_venus MACH_TSC_VENUS TSC_VENUS 953
ds101j MACH_DS101J DS101J 954
-mxc300_30ads MACH_MXC30030ADS MXC30030ADS 955
+mxc30030ads MACH_MXC30030ADS MXC30030ADS 955
fujitsu_wimaxsoc MACH_FUJITSU_WIMAXSOC FUJITSU_WIMAXSOC 956
dualpcmodem MACH_DUALPCMODEM DUALPCMODEM 957
gesbc9312 MACH_GESBC9312 GESBC9312 958
+htcapache MACH_HTCAPACHE HTCAPACHE 959
+ixdp435 MACH_IXDP435 IXDP435 960
+catprovt100 MACH_CATPROVT100 CATPROVT100 961
+picotux1xx MACH_PICOTUX1XX PICOTUX1XX 962
+picotux2xx MACH_PICOTUX2XX PICOTUX2XX 963
+dsmg600 MACH_DSMG600 DSMG600 964
+empc2 MACH_EMPC2 EMPC2 965
+ventura MACH_VENTURA VENTURA 966
+phidget_sbc MACH_PHIDGET_SBC PHIDGET_SBC 967
+ij3k MACH_IJ3K IJ3K 968
+pisgah MACH_PISGAH PISGAH 969
+omap_fsample MACH_OMAP_FSAMPLE OMAP_FSAMPLE 970
+sg720 MACH_SG720 SG720 971
+redfox MACH_REDFOX REDFOX 972
+mysh_ep9315_1 MACH_MYSH_EP9315_1 MYSH_EP9315_1 973
+tpf106 MACH_TPF106 TPF106 974
+at91rm9200kg MACH_AT91RM9200KG AT91RM9200KG 975
+racemt2 MACH_SLEDB SLEDB 976
+ontrack MACH_ONTRACK ONTRACK 977
+pm1200 MACH_PM1200 PM1200 978
+ess24562 MACH_ESS24XXX ESS24XXX 979
+coremp7 MACH_COREMP7 COREMP7 980
+nexcoder_6446 MACH_NEXCODER_6446 NEXCODER_6446 981
+stvc8380 MACH_STVC8380 STVC8380 982
+teklynx MACH_TEKLYNX TEKLYNX 983
+carbonado MACH_CARBONADO CARBONADO 984
+sysmos_mp730 MACH_SYSMOS_MP730 SYSMOS_MP730 985
+snapper_cl15 MACH_SNAPPER_CL15 SNAPPER_CL15 986
+pgigim MACH_PGIGIM PGIGIM 987
+ptx9160p2 MACH_PTX9160P2 PTX9160P2 988
+dcore1 MACH_DCORE1 DCORE1 989
+victorpxa MACH_VICTORPXA VICTORPXA 990
+mx2dtb MACH_MX2DTB MX2DTB 991
+pxa_irex_er0100 MACH_PXA_IREX_ER0100 PXA_IREX_ER0100 992
+omap_palmz71 MACH_OMAP_PALMZ71 OMAP_PALMZ71 993
+bartec_deg MACH_BARTEC_DEG BARTEC_DEG 994
+hw50251 MACH_HW50251 HW50251 995
+ibox MACH_IBOX IBOX 996
+atlaslh7a404 MACH_ATLASLH7A404 ATLASLH7A404 997
+pt2026 MACH_PT2026 PT2026 998
+htcalpine MACH_HTCALPINE HTCALPINE 999
+bartec_vtu MACH_BARTEC_VTU BARTEC_VTU 1000
+vcoreii MACH_VCOREII VCOREII 1001
+pdnb3 MACH_PDNB3 PDNB3 1002
+htcbeetles MACH_HTCBEETLES HTCBEETLES 1003
+s3c6400 MACH_S3C6400 S3C6400 1004
+s3c2443 MACH_S3C2443 S3C2443 1005
+omap_ldk MACH_OMAP_LDK OMAP_LDK 1006
+smdk2460 MACH_SMDK2460 SMDK2460 1007
+smdk2440 MACH_SMDK2440 SMDK2440 1008
+smdk2412 MACH_SMDK2412 SMDK2412 1009
+webbox MACH_WEBBOX WEBBOX 1010
+cwwndp MACH_CWWNDP CWWNDP 1011
+dragon MACH_DRAGON DRAGON 1012
+opendo_cpu_board MACH_OPENDO_CPU_BOARD OPENDO_CPU_BOARD 1013
+ccm2200 MACH_CCM2200 CCM2200 1014
+etwarm MACH_ETWARM ETWARM 1015
+m93030 MACH_M93030 M93030 1016
+cc7u MACH_CC7U CC7U 1017
+mtt_ranger MACH_MTT_RANGER MTT_RANGER 1018
+nexus MACH_NEXUS NEXUS 1019
+desman MACH_DESMAN DESMAN 1020
+bkde303 MACH_BKDE303 BKDE303 1021
+smdk2413 MACH_SMDK2413 SMDK2413 1022
+aml_m7200 MACH_AML_M7200 AML_M7200 1023
+aml_m5900 MACH_AML_M5900 AML_M5900 1024
+sg640 MACH_SG640 SG640 1025
+edg79524 MACH_EDG79524 EDG79524 1026
+ai2410 MACH_AI2410 AI2410 1027
+ixp465 MACH_IXP465 IXP465 1028
+balloon3 MACH_BALLOON3 BALLOON3 1029
diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index 9b367a65cb4..009038c8113 100644
--- a/arch/arm/vfp/vfpdouble.c
+++ b/arch/arm/vfp/vfpdouble.c
@@ -197,7 +197,7 @@ u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exce
dd, d, exceptions);
vfp_put_double(dd, d);
}
- return exceptions & ~VFP_NAN_FLAG;
+ return exceptions;
}
/*
@@ -588,6 +588,7 @@ static u32 vfp_double_ftosi(int sd, int unused, int dm, u32 fpscr)
struct vfp_double vdm;
u32 d, exceptions = 0;
int rmode = fpscr & FPSCR_RMODE_MASK;
+ int tm;
vfp_double_unpack(&vdm, vfp_get_double(dm));
vfp_double_dump("VDM", &vdm);
@@ -595,10 +596,14 @@ static u32 vfp_double_ftosi(int sd, int unused, int dm, u32 fpscr)
/*
* Do we have denormalised number?
*/
- if (vfp_double_type(&vdm) & VFP_DENORMAL)
+ tm = vfp_double_type(&vdm);
+ if (tm & VFP_DENORMAL)
exceptions |= FPSCR_IDC;
- if (vdm.exponent >= 1023 + 32) {
+ if (tm & VFP_NAN) {
+ d = 0;
+ exceptions |= FPSCR_IOC;
+ } else if (vdm.exponent >= 1023 + 32) {
d = 0x7fffffff;
if (vdm.sign)
d = ~d;
@@ -1122,9 +1127,9 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
{
u32 op = inst & FOP_MASK;
u32 exceptions = 0;
- unsigned int dd = vfp_get_sd(inst);
- unsigned int dn = vfp_get_sn(inst);
- unsigned int dm = vfp_get_sm(inst);
+ unsigned int dd = vfp_get_dd(inst);
+ unsigned int dn = vfp_get_dn(inst);
+ unsigned int dm = vfp_get_dm(inst);
unsigned int vecitr, veclen, vecstride;
u32 (*fop)(int, int, s32, u32);
@@ -1141,7 +1146,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
(veclen >> FPSCR_LENGTH_BIT) + 1);
- fop = (op == FOP_EXT) ? fop_extfns[dn] : fop_fns[FOP_TO_IDX(op)];
+ fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)];
if (!fop)
goto invalid;
@@ -1149,17 +1154,13 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
u32 except;
if (op == FOP_EXT)
- pr_debug("VFP: itr%d (d%u.%u) = op[%u] (d%u.%u)\n",
+ pr_debug("VFP: itr%d (d%u) = op[%u] (d%u)\n",
vecitr >> FPSCR_LENGTH_BIT,
- dd >> 1, dd & 1, dn,
- dm >> 1, dm & 1);
+ dd, dn, dm);
else
- pr_debug("VFP: itr%d (d%u.%u) = (d%u.%u) op[%u] (d%u.%u)\n",
+ pr_debug("VFP: itr%d (d%u) = (d%u) op[%u] (d%u)\n",
vecitr >> FPSCR_LENGTH_BIT,
- dd >> 1, dd & 1,
- dn >> 1, dn & 1,
- FOP_TO_IDX(op),
- dm >> 1, dm & 1);
+ dd, dn, FOP_TO_IDX(op), dm);
except = fop(dd, dn, dm, fpscr);
pr_debug("VFP: itr%d: exceptions=%08x\n",
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index b7ed57e00cd..a3f65b47aea 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -189,11 +189,10 @@ vfp_put_float:
.globl vfp_get_double
vfp_get_double:
- mov r0, r0, lsr #1
add pc, pc, r0, lsl #3
mov r0, r0
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
- mrrc p10, 1, r0, r1, c\dr @ fmrrd r0, r1, d\dr
+ mrrc p11, 1, r0, r1, c\dr @ fmrrd r0, r1, d\dr
mov pc, lr
.endr
@@ -204,10 +203,9 @@ vfp_get_double:
.globl vfp_put_double
vfp_put_double:
- mov r0, r0, lsr #1
add pc, pc, r0, lsl #3
mov r0, r0
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
- mcrr p10, 1, r1, r2, c\dr @ fmrrd r1, r2, d\dr
+ mcrr p11, 1, r1, r2, c\dr @ fmdrr r1, r2, d\dr
mov pc, lr
.endr
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 22f3da4e082..03486be0419 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -180,7 +180,7 @@ static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
* emulate it.
*/
}
- return exceptions;
+ return exceptions & ~VFP_NAN_FLAG;
}
/*
@@ -245,7 +245,7 @@ void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
*/
barrier();
trigger = fmrx(FPINST2);
- fpscr = fmrx(FPSCR);
+ orig_fpscr = fpscr = fmrx(FPSCR);
emulate:
exceptions = vfp_emulate_instruction(trigger, fpscr, regs);
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
index 14dd696ddeb..dae2c2f4605 100644
--- a/arch/arm/vfp/vfpsingle.c
+++ b/arch/arm/vfp/vfpsingle.c
@@ -203,7 +203,7 @@ u32 vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exce
vfp_put_float(sd, d);
}
- return exceptions & ~VFP_NAN_FLAG;
+ return exceptions;
}
/*
@@ -632,6 +632,7 @@ static u32 vfp_single_ftosi(int sd, int unused, s32 m, u32 fpscr)
struct vfp_single vsm;
u32 d, exceptions = 0;
int rmode = fpscr & FPSCR_RMODE_MASK;
+ int tm;
vfp_single_unpack(&vsm, m);
vfp_single_dump("VSM", &vsm);
@@ -639,10 +640,14 @@ static u32 vfp_single_ftosi(int sd, int unused, s32 m, u32 fpscr)
/*
* Do we have a denormalised number?
*/
+ tm = vfp_single_type(&vsm);
if (vfp_single_type(&vsm) & VFP_DENORMAL)
exceptions |= FPSCR_IDC;
- if (vsm.exponent >= 127 + 32) {
+ if (tm & VFP_NAN) {
+ d = 0;
+ exceptions |= FPSCR_IOC;
+ } else if (vsm.exponent >= 127 + 32) {
/*
* m >= 2^31-2^7: invalid
*/
@@ -1188,7 +1193,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
(veclen >> FPSCR_LENGTH_BIT) + 1);
- fop = (op == FOP_EXT) ? fop_extfns[sn] : fop_fns[FOP_TO_IDX(op)];
+ fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)];
if (!fop)
goto invalid;
diff --git a/arch/arm26/kernel/armksyms.c b/arch/arm26/kernel/armksyms.c
index 811a6376c62..9d66c27f272 100644
--- a/arch/arm26/kernel/armksyms.c
+++ b/arch/arm26/kernel/armksyms.c
@@ -152,7 +152,6 @@ EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(strchr);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(memset);
@@ -212,8 +211,6 @@ EXPORT_SYMBOL(sys_open);
EXPORT_SYMBOL(sys_exit);
EXPORT_SYMBOL(sys_wait4);
-EXPORT_SYMBOL(get_wchan);
-
#ifdef CONFIG_PREEMPT
EXPORT_SYMBOL(kernel_flag);
#endif
diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c
index e3ecaa45374..7da8a520567 100644
--- a/arch/arm26/mm/init.c
+++ b/arch/arm26/mm/init.c
@@ -23,6 +23,7 @@
#include <linux/initrd.h>
#include <linux/bootmem.h>
#include <linux/blkdev.h>
+#include <linux/pfn.h>
#include <asm/segment.h>
#include <asm/mach-types.h>
@@ -101,12 +102,6 @@ struct node_info {
int bootmap_pages;
};
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT)
-#define PFN_SIZE(x) ((x) >> PAGE_SHIFT)
-#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \
- (((unsigned long)(s)) & PAGE_MASK))
-
/*
* FIXME: We really want to avoid allocating the bootmap bitmap
* over the top of the initrd. Hopefully, this is located towards
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
index de39725da92..d57859053ce 100644
--- a/arch/cris/kernel/crisksyms.c
+++ b/arch/cris/kernel/crisksyms.c
@@ -39,7 +39,6 @@ EXPORT_SYMBOL(loops_per_usec);
/* String functions */
EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strchr);
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index 1ba57efff60..619a6eefd89 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -18,6 +18,7 @@
#include <linux/seq_file.h>
#include <linux/tty.h>
#include <linux/utsname.h>
+#include <linux/pfn.h>
#include <asm/setup.h>
@@ -88,10 +89,6 @@ setup_arch(char **cmdline_p)
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) &_end;
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
-
/* min_low_pfn points to the start of DRAM, start_pfn points
* to the first DRAM pages after the kernel, and max_low_pfn
* to the end of DRAM.
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index 1d21c8d34d8..a9b59527a74 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -1170,12 +1170,6 @@ __syscall_badsys:
# syscall vector table
#
###############################################################################
-#ifdef CONFIG_MMU
-#define __MMU(X) X
-#else
-#define __MMU(X) sys_ni_syscall
-#endif
-
.section .rodata
ALIGN
.globl sys_call_table
@@ -1305,7 +1299,7 @@ sys_call_table:
.long sys_newuname
.long sys_ni_syscall /* old "cacheflush" */
.long sys_adjtimex
- .long __MMU(sys_mprotect) /* 125 */
+ .long sys_mprotect /* 125 */
.long sys_sigprocmask
.long sys_ni_syscall /* old "create_module" */
.long sys_init_module
@@ -1324,16 +1318,16 @@ sys_call_table:
.long sys_getdents
.long sys_select
.long sys_flock
- .long __MMU(sys_msync)
+ .long sys_msync
.long sys_readv /* 145 */
.long sys_writev
.long sys_getsid
.long sys_fdatasync
.long sys_sysctl
- .long __MMU(sys_mlock) /* 150 */
- .long __MMU(sys_munlock)
- .long __MMU(sys_mlockall)
- .long __MMU(sys_munlockall)
+ .long sys_mlock /* 150 */
+ .long sys_munlock
+ .long sys_mlockall
+ .long sys_munlockall
.long sys_sched_setparam
.long sys_sched_getparam /* 155 */
.long sys_sched_setscheduler
@@ -1343,7 +1337,7 @@ sys_call_table:
.long sys_sched_get_priority_min /* 160 */
.long sys_sched_rr_get_interval
.long sys_nanosleep
- .long __MMU(sys_mremap)
+ .long sys_mremap
.long sys_setresuid16
.long sys_getresuid16 /* 165 */
.long sys_ni_syscall /* for vm86 */
@@ -1398,8 +1392,8 @@ sys_call_table:
.long sys_setfsuid /* 215 */
.long sys_setfsgid
.long sys_pivot_root
- .long __MMU(sys_mincore)
- .long __MMU(sys_madvise)
+ .long sys_mincore
+ .long sys_madvise
.long sys_getdents64 /* 220 */
.long sys_fcntl64
.long sys_ni_syscall /* reserved for TUX */
@@ -1437,7 +1431,7 @@ sys_call_table:
.long sys_epoll_create
.long sys_epoll_ctl /* 255 */
.long sys_epoll_wait
- .long __MMU(sys_remap_file_pages)
+ .long sys_remap_file_pages
.long sys_set_tid_address
.long sys_timer_create
.long sys_timer_settime /* 260 */
diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
index aa6b7d0a210..0f273a7aca5 100644
--- a/arch/frv/kernel/frv_ksyms.c
+++ b/arch/frv/kernel/frv_ksyms.c
@@ -27,7 +27,6 @@ EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strchr);
@@ -79,8 +78,6 @@ EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(__outsl_ns);
EXPORT_SYMBOL(__insl_ns);
-EXPORT_SYMBOL(get_wchan);
-
#ifdef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
EXPORT_SYMBOL(atomic_test_and_ANDNOT_mask);
EXPORT_SYMBOL(atomic_test_and_OR_mask);
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
index 69d6ad32d56..f8d6dee8478 100644
--- a/arch/h8300/kernel/h8300_ksyms.c
+++ b/arch/h8300/kernel/h8300_ksyms.c
@@ -25,7 +25,6 @@ extern char h8300_debug_device[];
/* platform dependent support */
EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strchr);
@@ -55,8 +54,6 @@ EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(get_wchan);
-
/*
* libgcc functions - functions that are used internally by the
* compiler... (prototypes are not correct though, but that
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index f7db71d0b91..8dfa3054f10 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -53,6 +53,35 @@ source "init/Kconfig"
menu "Processor type and features"
+config SMP
+ bool "Symmetric multi-processing support"
+ ---help---
+ This enables support for systems with more than one CPU. If you have
+ a system with only one CPU, like most personal computers, say N. If
+ you have a system with more than one CPU, say Y.
+
+ If you say N here, the kernel will run on single and multiprocessor
+ machines, but will use only one CPU of a multiprocessor machine. If
+ you say Y here, the kernel will run on many, but not all,
+ singleprocessor machines. On a singleprocessor machine, the kernel
+ will run faster if you say N here.
+
+ Note that if you say Y here and choose architecture "586" or
+ "Pentium" under "Processor family", the kernel will not work on 486
+ architectures. Similarly, multiprocessor kernels for the "PPro"
+ architecture may not work on all Pentium based boards.
+
+ People using multiprocessor machines who say Y here should also say
+ Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
+ Management" code will be disabled if you say Y here.
+
+ See also the <file:Documentation/smp.txt>,
+ <file:Documentation/i386/IO-APIC.txt>,
+ <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+ <http://www.tldp.org/docs.html#howto>.
+
+ If you don't know what to do here, say N.
+
choice
prompt "Subarchitecture Type"
default X86_PC
@@ -178,35 +207,6 @@ config HPET_EMULATE_RTC
depends on HPET_TIMER && RTC=y
default y
-config SMP
- bool "Symmetric multi-processing support"
- ---help---
- This enables support for systems with more than one CPU. If you have
- a system with only one CPU, like most personal computers, say N. If
- you have a system with more than one CPU, say Y.
-
- If you say N here, the kernel will run on single and multiprocessor
- machines, but will use only one CPU of a multiprocessor machine. If
- you say Y here, the kernel will run on many, but not all,
- singleprocessor machines. On a singleprocessor machine, the kernel
- will run faster if you say N here.
-
- Note that if you say Y here and choose architecture "586" or
- "Pentium" under "Processor family", the kernel will not work on 486
- architectures. Similarly, multiprocessor kernels for the "PPro"
- architecture may not work on all Pentium based boards.
-
- People using multiprocessor machines who say Y here should also say
- Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
- Management" code will be disabled if you say Y here.
-
- See also the <file:Documentation/smp.txt>,
- <file:Documentation/i386/IO-APIC.txt>,
- <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
- <http://www.tldp.org/docs.html#howto>.
-
- If you don't know what to do here, say N.
-
config NR_CPUS
int "Maximum number of CPUs (2-255)"
range 2 255
@@ -231,6 +231,15 @@ config SCHED_SMT
cost of slightly increased overhead in some places. If unsure say
N here.
+config SCHED_MC
+ bool "Multi-core scheduler support"
+ depends on SMP
+ default y
+ help
+ Multi-core scheduler support improves the CPU scheduler's decision
+ making when dealing with multi-core CPU chips at a cost of slightly
+ increased overhead in some places. If unsure say N here.
+
source "kernel/Kconfig.preempt"
config X86_UP_APIC
@@ -458,7 +467,7 @@ endchoice
choice
depends on EXPERIMENTAL && !X86_PAE
- prompt "Memory split"
+ prompt "Memory split" if EMBEDDED
default VMSPLIT_3G
help
Select the desired split between kernel and user memory.
@@ -513,6 +522,12 @@ config NUMA
comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI)
+config NODES_SHIFT
+ int
+ default "4" if X86_NUMAQ
+ default "3"
+ depends on NEED_MULTIPLE_NODES
+
config HAVE_ARCH_BOOTMEM_NODE
bool
depends on NUMA
@@ -741,21 +756,12 @@ config PHYSICAL_START
config HOTPLUG_CPU
bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
- depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER && !X86_PC
+ depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER
---help---
- Say Y here to experiment with turning CPUs off and on. CPUs
- can be controlled through /sys/devices/system/cpu.
-
- Say N.
+ Say Y here to experiment with turning CPUs off and on, and to
+ enable suspend on SMP systems. CPUs can be controlled through
+ /sys/devices/system/cpu.
-config DOUBLEFAULT
- default y
- bool "Enable doublefault exception handler" if EMBEDDED
- help
- This option allows trapping of rare doublefault exceptions that
- would otherwise cause a system to silently reboot. Disabling this
- option saves about 4k and might cause you much additional grey
- hair.
endmenu
diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
index 79603b3471f..eb130482ba1 100644
--- a/arch/i386/Kconfig.cpu
+++ b/arch/i386/Kconfig.cpu
@@ -311,5 +311,5 @@ config X86_OOSTORE
config X86_TSC
bool
- depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ
+ depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX) && !X86_NUMAQ
default y
diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
index 6e97df6979e..c92191b1fb6 100644
--- a/arch/i386/Kconfig.debug
+++ b/arch/i386/Kconfig.debug
@@ -81,4 +81,13 @@ config X86_MPPARSE
depends on X86_LOCAL_APIC && !X86_VISWS
default y
+config DOUBLEFAULT
+ default y
+ bool "Enable doublefault exception handler" if EMBEDDED
+ help
+ This option allows trapping of rare doublefault exceptions that
+ would otherwise cause a system to silently reboot. Disabling this
+ option saves about 4k and might cause you much additional grey
+ hair.
+
endmenu
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
index 2ac40c8244c..c9343c3a808 100644
--- a/arch/i386/boot/video.S
+++ b/arch/i386/boot/video.S
@@ -97,6 +97,7 @@
#define PARAM_VESAPM_OFF 0x30
#define PARAM_LFB_PAGES 0x32
#define PARAM_VESA_ATTRIB 0x34
+#define PARAM_CAPABILITIES 0x36
/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
#ifdef CONFIG_VIDEO_RETAIN
@@ -233,6 +234,10 @@ mopar_gr:
movw 18(%di), %ax
movl %eax, %fs:(PARAM_LFB_SIZE)
+# store mode capabilities
+ movl 10(%di), %eax
+ movl %eax, %fs:(PARAM_CAPABILITIES)
+
# switching the DAC to 8-bit is for <= 8 bpp only
movw %fs:(PARAM_LFB_DEPTH), %ax
cmpw $8, %ax
@@ -1924,6 +1929,7 @@ skip10: movb %ah, %al
ret
store_edid:
+#ifdef CONFIG_FB_FIRMWARE_EDID
pushw %es # just save all registers
pushw %ax
pushw %bx
@@ -1954,6 +1960,7 @@ store_edid:
popw %bx
popw %ax
popw %es
+#endif
ret
# VIDEO_SELECT-only variables
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 5b9ed21216c..96fb8a020af 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
- pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \
+ pci-dma.o i386_ksyms.o i387.o bootflag.o \
quirks.o i8237.o topology.o alternative.o
obj-y += cpu/
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index d0980c79a5d..5ccbf58ec94 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -621,9 +621,9 @@ extern u32 pmtmr_ioport;
static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
{
- struct fadt_descriptor_rev2 *fadt = NULL;
+ struct fadt_descriptor *fadt = NULL;
- fadt = (struct fadt_descriptor_rev2 *)__acpi_map_table(phys, size);
+ fadt = (struct fadt_descriptor *)__acpi_map_table(phys, size);
if (!fadt) {
printk(KERN_WARNING PREFIX "Unable to map FADT\n");
return 0;
@@ -693,6 +693,9 @@ static int __init acpi_parse_madt_lapic_entries(void)
{
int count;
+ if (!cpu_has_apic)
+ return -ENODEV;
+
/*
* Note that the LAPIC address is obtained from the MADT (32-bit value)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c
index 2e3b643a4dc..1649a175a20 100644
--- a/arch/i386/kernel/acpi/earlyquirk.c
+++ b/arch/i386/kernel/acpi/earlyquirk.c
@@ -5,17 +5,34 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/pci.h>
+#include <linux/acpi.h>
+
#include <asm/pci-direct.h>
#include <asm/acpi.h>
#include <asm/apic.h>
+#ifdef CONFIG_ACPI
+
+static int nvidia_hpet_detected __initdata;
+
+static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
+{
+ nvidia_hpet_detected = 1;
+ return 0;
+}
+#endif
+
static int __init check_bridge(int vendor, int device)
{
#ifdef CONFIG_ACPI
- /* According to Nvidia all timer overrides are bogus. Just ignore
- them all. */
+ /* According to Nvidia all timer overrides are bogus unless HPET
+ is enabled. */
if (vendor == PCI_VENDOR_ID_NVIDIA) {
- acpi_skip_timer_override = 1;
+ nvidia_hpet_detected = 0;
+ acpi_table_parse(ACPI_HPET, nvidia_hpet_check);
+ if (nvidia_hpet_detected == 0) {
+ acpi_skip_timer_override = 1;
+ }
}
#endif
if (vendor == PCI_VENDOR_ID_ATI && timer_over_8254 == 1) {
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index eb5279d23b7..3d4b2f3d116 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -62,6 +62,18 @@ int apic_verbosity;
static void apic_pm_activate(void);
+int modern_apic(void)
+{
+ unsigned int lvr, version;
+ /* AMD systems use old APIC versions, so check the CPU */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+ boot_cpu_data.x86 >= 0xf)
+ return 1;
+ lvr = apic_read(APIC_LVR);
+ version = GET_APIC_VERSION(lvr);
+ return version >= 0x14;
+}
+
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
* each architecture has to answer this themselves.
@@ -119,10 +131,7 @@ void enable_NMI_through_LVT0 (void * dummy)
int get_physical_broadcast(void)
{
- unsigned int lvr, version;
- lvr = apic_read(APIC_LVR);
- version = GET_APIC_VERSION(lvr);
- if (!APIC_INTEGRATED(version) || version >= 0x14)
+ if (modern_apic())
return 0xff;
else
return 0xf;
@@ -349,9 +358,9 @@ int __init verify_local_APIC(void)
void __init sync_Arb_IDs(void)
{
- /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
- unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
- if (ver >= 0x14) /* P4 or higher */
+ /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1
+ And not needed on AMD */
+ if (modern_apic())
return;
/*
* Wait for idle.
@@ -415,6 +424,7 @@ void __init init_bsp_APIC(void)
void __devinit setup_local_APIC(void)
{
unsigned long oldvalue, value, ver, maxlvt;
+ int i, j;
/* Pound the ESR really hard over the head with a big hammer - mbligh */
if (esr_disable) {
@@ -452,6 +462,25 @@ void __devinit setup_local_APIC(void)
apic_write_around(APIC_TASKPRI, value);
/*
+ * After a crash, we no longer service the interrupts and a pending
+ * interrupt from previous kernel might still have ISR bit set.
+ *
+ * Most probably by now CPU has serviced that pending interrupt and
+ * it might not have done the ack_APIC_irq() because it thought,
+ * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it
+ * does not clear the ISR bit and cpu thinks it has already serivced
+ * the interrupt. Hence a vector might get locked. It was noticed
+ * for timer irq (vector 0x31). Issue an extra EOI to clear ISR.
+ */
+ for (i = APIC_ISR_NR - 1; i >= 0; i--) {
+ value = apic_read(APIC_ISR + i*0x10);
+ for (j = 31; j >= 0; j--) {
+ if (value & (1<<j))
+ ack_APIC_irq();
+ }
+ }
+
+ /*
* Now that we are all set up, enable the APIC
*/
value = apic_read(APIC_SPIV);
@@ -728,11 +757,7 @@ static int __init apic_set_verbosity(char *str)
apic_verbosity = APIC_DEBUG;
else if (strcmp("verbose", str) == 0)
apic_verbosity = APIC_VERBOSE;
- else
- printk(KERN_WARNING "APIC Verbosity level %s not recognised"
- " use apic=verbose or apic=debug\n", str);
-
- return 0;
+ return 1;
}
__setup("apic=", apic_set_verbosity);
@@ -1316,6 +1341,14 @@ int __init APIC_init_uniprocessor (void)
connect_bsp_APIC();
+ /*
+ * Hack: In case of kdump, after a crash, kernel might be booting
+ * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
+ * might be zero if read from MP tables. Get it from LAPIC.
+ */
+#ifdef CONFIG_CRASH_DUMP
+ boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
+#endif
phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
setup_local_APIC();
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index da30a374dd4..df0e1745f18 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -1079,7 +1079,7 @@ static int apm_console_blank(int blank)
break;
}
- if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) {
+ if (error == APM_NOT_ENGAGED) {
static int tried;
int eng_error;
if (tried++ == 0) {
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 0810f81f2a0..786d1a57048 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -207,13 +207,13 @@ static void __init init_amd(struct cpuinfo_x86 *c)
set_bit(X86_FEATURE_K7, c->x86_capability);
break;
}
+ if (c->x86 >= 6)
+ set_bit(X86_FEATURE_FXSAVE_LEAK, c->x86_capability);
display_cacheinfo(c);
if (cpuid_eax(0x80000000) >= 0x80000008) {
c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
- if (c->x86_max_cores & (c->x86_max_cores - 1))
- c->x86_max_cores = 1;
}
if (cpuid_eax(0x80000000) >= 0x80000007) {
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 7e3d6b6a4e9..a06a49075f1 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -266,7 +266,7 @@ static void __init early_cpu_detect(void)
void __cpuinit generic_identify(struct cpuinfo_x86 * c)
{
u32 tfms, xlvl;
- int junk;
+ int ebx;
if (have_cpuid_p()) {
/* Get vendor name */
@@ -282,7 +282,7 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c)
/* Intel-defined flags: level 0x00000001 */
if ( c->cpuid_level >= 0x00000001 ) {
u32 capability, excap;
- cpuid(0x00000001, &tfms, &junk, &excap, &capability);
+ cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
c->x86_capability[0] = capability;
c->x86_capability[4] = excap;
c->x86 = (tfms >> 8) & 15;
@@ -292,6 +292,11 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c)
if (c->x86 >= 0x6)
c->x86_model += ((tfms >> 16) & 0xF) << 4;
c->x86_mask = tfms & 15;
+#ifdef CONFIG_SMP
+ c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
+#else
+ c->apicid = (ebx >> 24) & 0xFF;
+#endif
} else {
/* Have CPUID level 0 only - unheard of */
c->x86 = 4;
@@ -474,7 +479,6 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
cpuid(1, &eax, &ebx, &ecx, &edx);
- c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
return;
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 1e70823e1cb..71fffa17442 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -46,7 +46,7 @@
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
-#define VERSION "version 1.60.1"
+#define VERSION "version 1.60.2"
#include "powernow-k8.h"
/* serialize freq changes */
@@ -55,7 +55,7 @@ static DEFINE_MUTEX(fidvid_mutex);
static struct powernow_k8_data *powernow_data[NR_CPUS];
#ifndef CONFIG_SMP
-static cpumask_t cpu_core_map[1] = { CPU_MASK_ALL };
+static cpumask_t cpu_core_map[1];
#endif
/* Return a frequency in MHz, given an input fid */
@@ -905,11 +905,17 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
{
cpumask_t oldmask = CPU_MASK_ALL;
struct powernow_k8_data *data = powernow_data[pol->cpu];
- u32 checkfid = data->currfid;
- u32 checkvid = data->currvid;
+ u32 checkfid;
+ u32 checkvid;
unsigned int newstate;
int ret = -EIO;
+ if (!data)
+ return -EINVAL;
+
+ checkfid = data->currfid;
+ checkvid = data->currvid;
+
/* only run on specific CPU from here on */
oldmask = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
@@ -969,6 +975,9 @@ static int powernowk8_verify(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data = powernow_data[pol->cpu];
+ if (!data)
+ return -EINVAL;
+
return cpufreq_frequency_table_verify(pol, data->powernow_table);
}
@@ -977,7 +986,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data;
cpumask_t oldmask = CPU_MASK_ALL;
- int rc, i;
+ int rc;
if (!cpu_online(pol->cpu))
return -ENODEV;
@@ -1063,8 +1072,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
printk("cpu_init done, current fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid);
- for_each_cpu_mask(i, cpu_core_map[pol->cpu])
- powernow_data[i] = data;
+ powernow_data[pol->cpu] = data;
return 0;
@@ -1095,10 +1103,15 @@ static int __devexit powernowk8_cpu_exit (struct cpufreq_policy *pol)
static unsigned int powernowk8_get (unsigned int cpu)
{
- struct powernow_k8_data *data = powernow_data[cpu];
+ struct powernow_k8_data *data;
cpumask_t oldmask = current->cpus_allowed;
unsigned int khz = 0;
+ data = powernow_data[first_cpu(cpu_core_map[cpu])];
+
+ if (!data)
+ return -EINVAL;
+
set_cpus_allowed(current, cpumask_of_cpu(cpu));
if (smp_processor_id() != cpu) {
printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu);
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
index 00ea899c17e..79a7c5c87ed 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -182,10 +182,6 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);
static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
-#ifndef for_each_cpu_mask
-#define for_each_cpu_mask(i,mask) for (i=0;i<1;i++)
-#endif
-
#ifdef CONFIG_SMP
static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
{
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index ce61921369e..c8547a6fa7e 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -173,6 +173,10 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
+ unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
+#ifdef CONFIG_SMP
+ unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data);
+#endif
if (c->cpuid_level > 3) {
static int is_initialized;
@@ -205,9 +209,15 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
break;
case 2:
new_l2 = this_leaf.size/1024;
+ num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
+ index_msb = get_count_order(num_threads_sharing);
+ l2_id = c->apicid >> index_msb;
break;
case 3:
new_l3 = this_leaf.size/1024;
+ num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
+ index_msb = get_count_order(num_threads_sharing);
+ l3_id = c->apicid >> index_msb;
break;
default:
break;
@@ -215,11 +225,19 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
}
}
}
- if (c->cpuid_level > 1) {
+ /*
+ * Don't use cpuid2 if cpuid4 is supported. For P4, we use cpuid2 for
+ * trace cache
+ */
+ if ((num_cache_leaves == 0 || c->x86 == 15) && c->cpuid_level > 1) {
/* supports eax=2 call */
int i, j, n;
int regs[4];
unsigned char *dp = (unsigned char *)regs;
+ int only_trace = 0;
+
+ if (num_cache_leaves != 0 && c->x86 == 15)
+ only_trace = 1;
/* Number of times to iterate */
n = cpuid_eax(2) & 0xFF;
@@ -241,6 +259,8 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
while (cache_table[k].descriptor != 0)
{
if (cache_table[k].descriptor == des) {
+ if (only_trace && cache_table[k].cache_type != LVL_TRACE)
+ break;
switch (cache_table[k].cache_type) {
case LVL_1_INST:
l1i += cache_table[k].size;
@@ -266,34 +286,45 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
}
}
}
+ }
- if (new_l1d)
- l1d = new_l1d;
+ if (new_l1d)
+ l1d = new_l1d;
- if (new_l1i)
- l1i = new_l1i;
+ if (new_l1i)
+ l1i = new_l1i;
- if (new_l2)
- l2 = new_l2;
+ if (new_l2) {
+ l2 = new_l2;
+#ifdef CONFIG_SMP
+ cpu_llc_id[cpu] = l2_id;
+#endif
+ }
- if (new_l3)
- l3 = new_l3;
+ if (new_l3) {
+ l3 = new_l3;
+#ifdef CONFIG_SMP
+ cpu_llc_id[cpu] = l3_id;
+#endif
+ }
- if ( trace )
- printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
- else if ( l1i )
- printk (KERN_INFO "CPU: L1 I cache: %dK", l1i);
- if ( l1d )
- printk(", L1 D cache: %dK\n", l1d);
- else
- printk("\n");
- if ( l2 )
- printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
- if ( l3 )
- printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
+ if (trace)
+ printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
+ else if ( l1i )
+ printk (KERN_INFO "CPU: L1 I cache: %dK", l1i);
- c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d));
- }
+ if (l1d)
+ printk(", L1 D cache: %dK\n", l1d);
+ else
+ printk("\n");
+
+ if (l2)
+ printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
+
+ if (l3)
+ printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
+
+ c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d));
return l2;
}
@@ -611,7 +642,7 @@ static void __cpuexit cache_remove_dev(struct sys_device * sys_dev)
return;
}
-static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
+static int cacheinfo_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c
index 6170af3c271..afa0888f9a1 100644
--- a/arch/i386/kernel/cpu/mcheck/mce.c
+++ b/arch/i386/kernel/cpu/mcheck/mce.c
@@ -64,13 +64,13 @@ void mcheck_init(struct cpuinfo_x86 *c)
static int __init mcheck_disable(char *str)
{
mce_disabled = 1;
- return 0;
+ return 1;
}
static int __init mcheck_enable(char *str)
{
mce_disabled = -1;
- return 0;
+ return 1;
}
__setup("nomce", mcheck_disable);
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 006141d1c12..1d9a4abcdfc 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -168,7 +168,7 @@ static int cpuid_class_device_create(int i)
return err;
}
-static int __devinit cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
index e3c5fca0aa8..2b0cfce24a6 100644
--- a/arch/i386/kernel/crash.c
+++ b/arch/i386/kernel/crash.c
@@ -69,7 +69,7 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
* for the data I pass, and I need tags
* on the data to indicate what information I have
* squirrelled away. ELF notes happen to provide
- * all of that that no need to invent something new.
+ * all of that, so there is no need to invent something new.
*/
buf = (u32*)per_cpu_ptr(crash_notes, cpu);
if (!buf)
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 055325056a7..036a9857936 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -19,7 +19,6 @@ EXPORT_SYMBOL(__put_user_2);
EXPORT_SYMBOL(__put_user_4);
EXPORT_SYMBOL(__put_user_8);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
#ifdef CONFIG_SMP
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 311b4e7266f..d70f2ade5cd 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -381,7 +381,7 @@ static void do_irq_balance(void)
unsigned long imbalance = 0;
cpumask_t allowed_mask, target_cpu_mask, tmp;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
int package_index;
CPU_IRQ(i) = 0;
if (!cpu_online(i))
@@ -632,7 +632,7 @@ static int __init balanced_irq_init(void)
else
printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
failed:
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
kfree(irq_cpu_data[i].irq_delta);
irq_cpu_data[i].irq_delta = NULL;
kfree(irq_cpu_data[i].last_irq);
@@ -644,7 +644,7 @@ failed:
int __init irqbalance_disable(char *str)
{
irqbalance_disabled = 1;
- return 0;
+ return 1;
}
__setup("noirqbalance", irqbalance_disable);
@@ -2238,6 +2238,8 @@ static inline void unlock_ExtINT_logic(void)
spin_unlock_irqrestore(&ioapic_lock, flags);
}
+int timer_uses_ioapic_pin_0;
+
/*
* This code may look a bit paranoid, but it's supposed to cooperate with
* a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
@@ -2274,6 +2276,9 @@ static inline void check_timer(void)
pin2 = ioapic_i8259.pin;
apic2 = ioapic_i8259.apic;
+ if (pin1 == 0)
+ timer_uses_ioapic_pin_0 = 1;
+
printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
vector, apic1, pin1, apic2, pin2);
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index f19768789e8..38806f42784 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -43,7 +43,7 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
/* insert a jmp code */
-static inline void set_jmp_op(void *from, void *to)
+static __always_inline void set_jmp_op(void *from, void *to)
{
struct __arch_jmp_op {
char op;
@@ -57,7 +57,7 @@ static inline void set_jmp_op(void *from, void *to)
/*
* returns non-zero if opcodes can be boosted.
*/
-static inline int can_boost(kprobe_opcode_t opcode)
+static __always_inline int can_boost(kprobe_opcode_t opcode)
{
switch (opcode & 0xf0 ) {
case 0x70:
@@ -88,7 +88,7 @@ static inline int can_boost(kprobe_opcode_t opcode)
/*
* returns non-zero if opcode modifies the interrupt flag.
*/
-static inline int is_IF_modifier(kprobe_opcode_t opcode)
+static int __kprobes is_IF_modifier(kprobe_opcode_t opcode)
{
switch (opcode) {
case 0xfa: /* cli */
@@ -138,7 +138,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
mutex_unlock(&kprobe_mutex);
}
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -146,7 +146,7 @@ static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->prev_kprobe.saved_eflags = kcb->kprobe_saved_eflags;
}
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -154,7 +154,7 @@ static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->kprobe_saved_eflags = kcb->prev_kprobe.saved_eflags;
}
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = p;
@@ -164,7 +164,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
kcb->kprobe_saved_eflags &= ~IF_MASK;
}
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
regs->eflags |= TF_MASK;
regs->eflags &= ~IF_MASK;
@@ -242,10 +242,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
kcb->kprobe_status = KPROBE_REENTER;
return 1;
} else {
- if (regs->eflags & VM_MASK) {
- /* We are in virtual-8086 mode. Return 0 */
- goto no_kprobe;
- }
if (*addr != BREAKPOINT_INSTRUCTION) {
/* The breakpoint instruction was removed by
* another cpu right after we hit, no further
@@ -265,11 +261,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
p = get_kprobe(addr);
if (!p) {
- if (regs->eflags & VM_MASK) {
- /* We are in virtual-8086 mode. Return 0 */
- goto no_kprobe;
- }
-
if (*addr != BREAKPOINT_INSTRUCTION) {
/*
* The breakpoint instruction was removed right
@@ -452,10 +443,11 @@ static void __kprobes resume_execution(struct kprobe *p,
*tos &= ~(TF_MASK | IF_MASK);
*tos |= kcb->kprobe_old_eflags;
break;
- case 0xc3: /* ret/lret */
- case 0xcb:
- case 0xc2:
+ case 0xc2: /* iret/ret/lret */
+ case 0xc3:
case 0xca:
+ case 0xcb:
+ case 0xcf:
case 0xea: /* jmp absolute -- eip is correct */
/* eip is already adjusted, no more changes required */
p->ainsn.boostable = 1;
@@ -463,10 +455,13 @@ static void __kprobes resume_execution(struct kprobe *p,
case 0xe8: /* call relative - Fix return addr */
*tos = orig_eip + (*tos - copy_eip);
break;
+ case 0x9a: /* call absolute -- same as call absolute, indirect */
+ *tos = orig_eip + (*tos - copy_eip);
+ goto no_change;
case 0xff:
if ((p->ainsn.insn[1] & 0x30) == 0x10) {
- /* call absolute, indirect */
/*
+ * call absolute, indirect
* Fix return addr; eip is correct.
* But this is not boostable
*/
@@ -507,7 +502,7 @@ no_change:
* Interrupts are disabled on entry as trap1 is an interrupt gate and they
* remain disabled thoroughout this function.
*/
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -543,7 +538,7 @@ out:
return 1;
}
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index dd780a00553..e7c138f66c5 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -459,26 +459,9 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
return ret;
}
-static int microcode_ioctl (struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- switch (cmd) {
- /*
- * XXX: will be removed after microcode_ctl
- * is updated to ignore failure of this ioctl()
- */
- case MICROCODE_IOCFREE:
- return 0;
- default:
- return -EINVAL;
- }
- return -EINVAL;
-}
-
static struct file_operations microcode_fops = {
.owner = THIS_MODULE,
.write = microcode_write,
- .ioctl = microcode_ioctl,
.open = microcode_open,
};
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 8d8aa9d1796..6b1392d33ed 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -38,12 +38,6 @@
int smp_found_config;
unsigned int __initdata maxcpus = NR_CPUS;
-#ifdef CONFIG_HOTPLUG_CPU
-#define CPU_HOTPLUG_ENABLED (1)
-#else
-#define CPU_HOTPLUG_ENABLED (0)
-#endif
-
/*
* Various Linux-internal data structures created from the
* MP-table.
@@ -110,21 +104,6 @@ static int __init mpf_checksum(unsigned char *mp, int len)
static int mpc_record;
static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
-#ifdef CONFIG_X86_NUMAQ
-static int MP_valid_apicid(int apicid, int version)
-{
- return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf;
-}
-#else
-static int MP_valid_apicid(int apicid, int version)
-{
- if (version >= 0x14)
- return apicid < 0xff;
- else
- return apicid < 0xf;
-}
-#endif
-
static void __devinit MP_processor_info (struct mpc_config_processor *m)
{
int ver, apicid;
@@ -190,12 +169,6 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m)
ver = m->mpc_apicver;
- if (!MP_valid_apicid(apicid, ver)) {
- printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
- m->mpc_apicid, MAX_APICS);
- return;
- }
-
/*
* Validate version
*/
@@ -225,7 +198,14 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m)
cpu_set(num_processors, cpu_possible_map);
num_processors++;
- if (CPU_HOTPLUG_ENABLED || (num_processors > 8)) {
+ /*
+ * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
+ * but we need to work other dependencies like SMP_SUSPEND etc
+ * before this can be done without some confusion.
+ * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
+ * - Ashok Raj <ashok.raj@intel.com>
+ */
+ if (num_processors > 8) {
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_INTEL:
if (!APIC_XAPIC(ver)) {
@@ -249,6 +229,13 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
mpc_oem_bus_info(m, str, translation_table[mpc_record]);
+ if (m->mpc_busid >= MAX_MP_BUSSES) {
+ printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
+ " is too large, max. supported is %d\n",
+ m->mpc_busid, str, MAX_MP_BUSSES - 1);
+ return;
+ }
+
if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
@@ -1143,7 +1130,17 @@ int mp_register_gsi (u32 gsi, int triggering, int polarity)
*/
int irq = gsi;
if (gsi < MAX_GSI_NUM) {
- if (gsi > 15)
+ /*
+ * Retain the VIA chipset work-around (gsi > 15), but
+ * avoid a problem where the 8254 timer (IRQ0) is setup
+ * via an override (so it's not on pin 0 of the ioapic),
+ * and at the same time, the pin 0 interrupt is a PCI
+ * type. The gsi > 15 test could cause these two pins
+ * to be shared as IRQ0, and they are not shareable.
+ * So test for this condition, and if necessary, avoid
+ * the pin collision.
+ */
+ if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0))
gsi = pci_irq++;
/*
* Don't assign IRQ used by ACPI SCI
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 1d0a55e6876..7a328230e54 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -251,7 +251,7 @@ static int msr_class_device_create(int i)
return err;
}
-static int __devinit msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 9074818b947..d43b498ec74 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -138,12 +138,12 @@ static int __init check_nmi_watchdog(void)
if (nmi_watchdog == NMI_LOCAL_APIC)
smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0);
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count;
local_irq_enable();
mdelay((10*1000)/nmi_hz); // wait 10 ticks
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
#ifdef CONFIG_SMP
/* Check cpu_callin_map here because that is set
after the timer is started. */
@@ -510,7 +510,7 @@ void touch_nmi_watchdog (void)
* Just reset the alert counters, (other CPUs might be
* spinning on locks we hold):
*/
- for_each_cpu(i)
+ for_each_possible_cpu(i)
alert_counter[i] = 0;
/*
@@ -529,7 +529,8 @@ void nmi_watchdog_tick (struct pt_regs * regs)
* always switch the stack NMI-atomically, it's safe to use
* smp_processor_id().
*/
- int sum, cpu = smp_processor_id();
+ unsigned int sum;
+ int cpu = smp_processor_id();
sum = per_cpu(irq_stat, cpu).apic_timer_irqs;
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 24b3e745478..6259afea46d 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -781,7 +781,6 @@ unsigned long get_wchan(struct task_struct *p)
} while (count++ < 16);
return 0;
}
-EXPORT_SYMBOL(get_wchan);
/*
* sys_alloc_thread_area: get a yet unused TLS descriptor index.
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 506462ef36a..fd7eaf7866e 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -671,7 +671,7 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit)
if (unlikely(current->audit_context)) {
if (entryexit)
- audit_syscall_exit(current, AUDITSC_RESULT(regs->eax),
+ audit_syscall_exit(AUDITSC_RESULT(regs->eax),
regs->eax);
/* Debug traps, when using PTRACE_SINGLESTEP, must be sent only
* on the syscall exit path. Normally, when TIF_SYSCALL_AUDIT is
@@ -720,14 +720,13 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit)
ret = is_sysemu;
out:
if (unlikely(current->audit_context) && !entryexit)
- audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax,
+ audit_syscall_entry(AUDIT_ARCH_I386, regs->orig_eax,
regs->ebx, regs->ecx, regs->edx, regs->esi);
if (ret == 0)
return 0;
regs->orig_eax = -1; /* force skip of syscall restarting */
if (unlikely(current->audit_context))
- audit_syscall_exit(current, AUDITSC_RESULT(regs->eax),
- regs->eax);
+ audit_syscall_exit(AUDITSC_RESULT(regs->eax), regs->eax);
return 1;
}
diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c
index 10e21a4773d..99aab41a05b 100644
--- a/arch/i386/kernel/reboot_fixups.c
+++ b/arch/i386/kernel/reboot_fixups.c
@@ -51,7 +51,5 @@ void mach_reboot_fixups(void)
cur->reboot_fixup(dev);
}
-
- printk(KERN_WARNING "No reboot fixup found for your hardware\n");
}
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 6917daa159a..dd6b0e3386c 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -34,6 +34,7 @@
#include <linux/initrd.h>
#include <linux/bootmem.h>
#include <linux/seq_file.h>
+#include <linux/platform_device.h>
#include <linux/console.h>
#include <linux/mca.h>
#include <linux/root_dev.h>
@@ -46,6 +47,7 @@
#include <linux/kexec.h>
#include <linux/crash_dump.h>
#include <linux/dmi.h>
+#include <linux/pfn.h>
#include <video/edid.h>
@@ -961,6 +963,38 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
return 0;
}
+ /*
+ * This function checks if the entire range <start,end> is mapped with type.
+ *
+ * Note: this function only works correct if the e820 table is sorted and
+ * not-overlapping, which is the case
+ */
+int __init
+e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
+{
+ u64 start = s;
+ u64 end = e;
+ int i;
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+ if (type && ei->type != type)
+ continue;
+ /* is the region (part) in overlap with the current region ?*/
+ if (ei->addr >= end || ei->addr + ei->size <= start)
+ continue;
+ /* if the region is at the beginning of <start,end> we move
+ * start to the end of the region since it's ok until there
+ */
+ if (ei->addr <= start)
+ start = ei->addr + ei->size;
+ /* if start is now at or beyond end, we're done, full
+ * coverage */
+ if (start >= end)
+ return 1; /* we're done */
+ }
+ return 0;
+}
+
/*
* Find the highest page frame number we have available
*/
@@ -1286,6 +1320,8 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
probe_roms();
for (i = 0; i < e820.nr_map; i++) {
struct resource *res;
+ if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
+ continue;
res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
switch (e820.map[i].type) {
case E820_RAM: res->name = "System RAM"; break;
@@ -1315,8 +1351,8 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
/*
* Request address space for all standard resources
*
- * This is called just before pcibios_assign_resources(), which is also
- * an fs_initcall, but is linked in later (in arch/i386/pci/i386.c).
+ * This is called just before pcibios_init(), which is also a
+ * subsys_initcall, but is linked in later (in arch/i386/pci/common.c).
*/
static int __init request_standard_resources(void)
{
@@ -1337,7 +1373,7 @@ static int __init request_standard_resources(void)
return 0;
}
-fs_initcall(request_standard_resources);
+subsys_initcall(request_standard_resources);
static void __init register_memory(void)
{
@@ -1511,15 +1547,18 @@ void __init setup_arch(char **cmdline_p)
if (efi_enabled)
efi_map_memmap();
-#ifdef CONFIG_X86_IO_APIC
- check_acpi_pci(); /* Checks more than just ACPI actually */
-#endif
-
#ifdef CONFIG_ACPI
/*
* Parse the ACPI tables for possible boot-time SMP configuration.
*/
acpi_boot_table_init();
+#endif
+
+#ifdef CONFIG_X86_IO_APIC
+ check_acpi_pci(); /* Checks more than just ACPI actually */
+#endif
+
+#ifdef CONFIG_ACPI
acpi_boot_init();
#if defined(CONFIG_SMP) && defined(CONFIG_X86_PC)
@@ -1546,6 +1585,23 @@ void __init setup_arch(char **cmdline_p)
#endif
}
+static __init int add_pcspkr(void)
+{
+ struct platform_device *pd;
+ int ret;
+
+ pd = platform_device_alloc("pcspkr", -1);
+ if (!pd)
+ return -ENOMEM;
+
+ ret = platform_device_add(pd);
+ if (ret)
+ platform_device_put(pd);
+
+ return ret;
+}
+device_initcall(add_pcspkr);
+
#include "setup_arch_post.h"
/*
* Local Variables:
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 82371d83bfa..825b2b4ca72 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -72,6 +72,9 @@ int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
/* Core ID of each logical CPU */
int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
+/* Last level cache ID of each logical CPU */
+int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID};
+
/* representing HT siblings of each logical CPU */
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_sibling_map);
@@ -310,7 +313,9 @@ static void __init synchronize_tsc_bp (void)
if (tsc_values[i] < avg)
realdelta = -realdelta;
- printk(KERN_INFO "CPU#%d had %ld usecs TSC skew, fixed it up.\n", i, realdelta);
+ if (realdelta > 0)
+ printk(KERN_INFO "CPU#%d had %ld usecs TSC "
+ "skew, fixed it up.\n", i, realdelta);
}
sum += delta;
@@ -440,6 +445,18 @@ static void __devinit smp_callin(void)
static int cpucount;
+/* maps the cpu to the sched domain representing multi-core */
+cpumask_t cpu_coregroup_map(int cpu)
+{
+ struct cpuinfo_x86 *c = cpu_data + cpu;
+ /*
+ * For perf, we return last level cache shared map.
+ * TBD: when power saving sched policy is added, we will return
+ * cpu_core_map when power saving policy is enabled
+ */
+ return c->llc_shared_map;
+}
+
/* representing cpus for which sibling maps can be computed */
static cpumask_t cpu_sibling_setup_map;
@@ -459,12 +476,16 @@ set_cpu_sibling_map(int cpu)
cpu_set(cpu, cpu_sibling_map[i]);
cpu_set(i, cpu_core_map[cpu]);
cpu_set(cpu, cpu_core_map[i]);
+ cpu_set(i, c[cpu].llc_shared_map);
+ cpu_set(cpu, c[i].llc_shared_map);
}
}
} else {
cpu_set(cpu, cpu_sibling_map[cpu]);
}
+ cpu_set(cpu, c[cpu].llc_shared_map);
+
if (current_cpu_data.x86_max_cores == 1) {
cpu_core_map[cpu] = cpu_sibling_map[cpu];
c[cpu].booted_cores = 1;
@@ -472,6 +493,11 @@ set_cpu_sibling_map(int cpu)
}
for_each_cpu_mask(i, cpu_sibling_setup_map) {
+ if (cpu_llc_id[cpu] != BAD_APICID &&
+ cpu_llc_id[cpu] == cpu_llc_id[i]) {
+ cpu_set(i, c[cpu].llc_shared_map);
+ cpu_set(cpu, c[i].llc_shared_map);
+ }
if (phys_proc_id[cpu] == phys_proc_id[i]) {
cpu_set(i, cpu_core_map[cpu]);
cpu_set(cpu, cpu_core_map[i]);
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index ac687d00a1c..af56987f69b 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -310,3 +310,9 @@ ENTRY(sys_call_table)
.long sys_pselect6
.long sys_ppoll
.long sys_unshare /* 310 */
+ .long sys_set_robust_list
+ .long sys_get_robust_list
+ .long sys_splice
+ .long sys_sync_file_range
+ .long sys_tee /* 315 */
+ .long sys_vmsplice
diff --git a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c
index 264edaaac31..144e94a0493 100644
--- a/arch/i386/kernel/timers/timer_pm.c
+++ b/arch/i386/kernel/timers/timer_pm.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/init.h>
+#include <linux/pci.h>
#include <asm/types.h>
#include <asm/timer.h>
#include <asm/smp.h>
@@ -45,24 +46,31 @@ static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
+static int pmtmr_need_workaround __read_mostly = 1;
+
/*helper function to safely read acpi pm timesource*/
static inline u32 read_pmtmr(void)
{
- u32 v1=0,v2=0,v3=0;
- /* It has been reported that because of various broken
- * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time
- * source is not latched, so you must read it multiple
- * times to insure a safe value is read.
- */
- do {
- v1 = inl(pmtmr_ioport);
- v2 = inl(pmtmr_ioport);
- v3 = inl(pmtmr_ioport);
- } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
- || (v3 > v1 && v3 < v2));
-
- /* mask the output to 24 bits */
- return v2 & ACPI_PM_MASK;
+ if (pmtmr_need_workaround) {
+ u32 v1, v2, v3;
+
+ /* It has been reported that because of various broken
+ * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time
+ * source is not latched, so you must read it multiple
+ * times to insure a safe value is read.
+ */
+ do {
+ v1 = inl(pmtmr_ioport);
+ v2 = inl(pmtmr_ioport);
+ v3 = inl(pmtmr_ioport);
+ } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
+ || (v3 > v1 && v3 < v2));
+
+ /* mask the output to 24 bits */
+ return v2 & ACPI_PM_MASK;
+ }
+
+ return inl(pmtmr_ioport) & ACPI_PM_MASK;
}
@@ -263,6 +271,72 @@ struct init_timer_opts __initdata timer_pmtmr_init = {
.opts = &timer_pmtmr,
};
+#ifdef CONFIG_PCI
+/*
+ * PIIX4 Errata:
+ *
+ * The power management timer may return improper results when read.
+ * Although the timer value settles properly after incrementing,
+ * while incrementing there is a 3 ns window every 69.8 ns where the
+ * timer value is indeterminate (a 4.2% chance that the data will be
+ * incorrect when read). As a result, the ACPI free running count up
+ * timer specification is violated due to erroneous reads.
+ */
+static int __init pmtmr_bug_check(void)
+{
+ static struct pci_device_id gray_list[] __initdata = {
+ /* these chipsets may have bug. */
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82801DB_0) },
+ { },
+ };
+ struct pci_dev *dev;
+ int pmtmr_has_bug = 0;
+ u8 rev;
+
+ if (cur_timer != &timer_pmtmr || !pmtmr_need_workaround)
+ return 0;
+
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
+ if (dev) {
+ pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+ /* the bug has been fixed in PIIX4M */
+ if (rev < 3) {
+ printk(KERN_WARNING "* Found PM-Timer Bug on this "
+ "chipset. Due to workarounds for a bug,\n"
+ "* this time source is slow. Consider trying "
+ "other time sources (clock=)\n");
+ pmtmr_has_bug = 1;
+ }
+ pci_dev_put(dev);
+ }
+
+ if (pci_dev_present(gray_list)) {
+ printk(KERN_WARNING "* This chipset may have PM-Timer Bug. Due"
+ " to workarounds for a bug,\n"
+ "* this time source is slow. If you are sure your timer"
+ " does not have\n"
+ "* this bug, please use \"pmtmr_good\" to disable the "
+ "workaround\n");
+ pmtmr_has_bug = 1;
+ }
+
+ if (!pmtmr_has_bug)
+ pmtmr_need_workaround = 0;
+
+ return 0;
+}
+device_initcall(pmtmr_bug_check);
+#endif
+
+static int __init pmtr_good_setup(char *__str)
+{
+ pmtmr_need_workaround = 0;
+ return 1;
+}
+__setup("pmtmr_good", pmtr_good_setup);
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION("Power Management Timer (PMTMR) as primary timing source for x86");
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 5e41ee29c8c..f1187ddb0d0 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -279,7 +279,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
{
struct cpufreq_freqs *freq = data;
- if (val != CPUFREQ_RESUMECHANGE)
+ if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
write_seqlock_irq(&xtime_lock);
if (!ref_freq) {
if (!freq->old){
@@ -312,7 +312,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
}
end:
- if (val != CPUFREQ_RESUMECHANGE)
+ if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
write_sequnlock_irq(&xtime_lock);
return 0;
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 4624f8ca245..0e498369f35 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -92,22 +92,21 @@ asmlinkage void spurious_interrupt_bug(void);
asmlinkage void machine_check(void);
static int kstack_depth_to_print = 24;
-struct notifier_block *i386die_chain;
-static DEFINE_SPINLOCK(die_notifier_lock);
+ATOMIC_NOTIFIER_HEAD(i386die_chain);
int register_die_notifier(struct notifier_block *nb)
{
- int err = 0;
- unsigned long flags;
-
vmalloc_sync_all();
- spin_lock_irqsave(&die_notifier_lock, flags);
- err = notifier_chain_register(&i386die_chain, nb);
- spin_unlock_irqrestore(&die_notifier_lock, flags);
- return err;
+ return atomic_notifier_chain_register(&i386die_chain, nb);
}
EXPORT_SYMBOL(register_die_notifier);
+int unregister_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&i386die_chain, nb);
+}
+EXPORT_SYMBOL(unregister_die_notifier);
+
static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
{
return p > (void *)tinfo &&
@@ -131,9 +130,8 @@ static inline int print_addr_and_symbol(unsigned long addr, char *log_lvl,
print_symbol("%s", addr);
printed = (printed + 1) % CONFIG_STACK_BACKTRACE_COLS;
-
if (printed)
- printk(" ");
+ printk(" ");
else
printk("\n");
@@ -213,7 +211,6 @@ static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp,
}
stack = esp;
- printk(log_lvl);
for(i = 0; i < kstack_depth_to_print; i++) {
if (kstack_end(stack))
break;
@@ -366,6 +363,9 @@ void die(const char * str, struct pt_regs * regs, long err)
if (++die.lock_owner_depth < 3) {
int nl = 0;
+ unsigned long esp;
+ unsigned short ss;
+
handle_BUG(regs);
printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
#ifdef CONFIG_PREEMPT
@@ -388,8 +388,19 @@ void die(const char * str, struct pt_regs * regs, long err)
printk("\n");
if (notify_die(DIE_OOPS, str, regs, err,
current->thread.trap_no, SIGSEGV) !=
- NOTIFY_STOP)
+ NOTIFY_STOP) {
show_registers(regs);
+ /* Executive summary in case the oops scrolled away */
+ esp = (unsigned long) (&regs->esp);
+ savesegment(ss, ss);
+ if (user_mode(regs)) {
+ esp = regs->esp;
+ ss = regs->xss & 0xffff;
+ }
+ printk(KERN_EMERG "EIP: [<%08lx>] ", regs->eip);
+ print_symbol("%s", regs->eip);
+ printk(" SS:ESP %04x:%08lx\n", ss, esp);
+ }
else
regs = NULL;
} else
@@ -1194,6 +1205,6 @@ void __init trap_init(void)
static int __init kstack_setup(char *s)
{
kstack_depth_to_print = simple_strtoul(s, NULL, 0);
- return 0;
+ return 1;
}
__setup("kstack=", kstack_setup);
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index aee14fafd13..00e0118e717 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -312,7 +312,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
/*call audit_syscall_exit since we do not exit via the normal paths */
if (unlikely(current->audit_context))
- audit_syscall_exit(current, AUDITSC_RESULT(eax), eax);
+ audit_syscall_exit(AUDITSC_RESULT(eax), eax);
__asm__ __volatile__(
"movl %0,%%esp\n\t"
diff --git a/arch/i386/kernel/vsyscall-sigreturn.S b/arch/i386/kernel/vsyscall-sigreturn.S
index fadb5bc3c37..a92262f4165 100644
--- a/arch/i386/kernel/vsyscall-sigreturn.S
+++ b/arch/i386/kernel/vsyscall-sigreturn.S
@@ -44,7 +44,7 @@ __kernel_rt_sigreturn:
.LSTARTCIEDLSI1:
.long 0 /* CIE ID */
.byte 1 /* Version number */
- .string "zR" /* NUL-terminated augmentation string */
+ .string "zRS" /* NUL-terminated augmentation string */
.uleb128 1 /* Code alignment factor */
.sleb128 -4 /* Data alignment factor */
.byte 8 /* Return address register column */
diff --git a/arch/i386/mach-generic/probe.c b/arch/i386/mach-generic/probe.c
index cea5b3ce4b5..d55fa7b187a 100644
--- a/arch/i386/mach-generic/probe.c
+++ b/arch/i386/mach-generic/probe.c
@@ -93,9 +93,11 @@ int __init mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid
int i;
for (i = 0; apic_probe[i]; ++i) {
if (apic_probe[i]->mps_oem_check(mpc,oem,productid)) {
- genapic = apic_probe[i];
- printk(KERN_INFO "Switched to APIC driver `%s'.\n",
- genapic->name);
+ if (!cmdline_apic) {
+ genapic = apic_probe[i];
+ printk(KERN_INFO "Switched to APIC driver `%s'.\n",
+ genapic->name);
+ }
return 1;
}
}
@@ -107,9 +109,11 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
int i;
for (i = 0; apic_probe[i]; ++i) {
if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
- genapic = apic_probe[i];
- printk(KERN_INFO "Switched to APIC driver `%s'.\n",
- genapic->name);
+ if (!cmdline_apic) {
+ genapic = apic_probe[i];
+ printk(KERN_INFO "Switched to APIC driver `%s'.\n",
+ genapic->name);
+ }
return 1;
}
}
diff --git a/arch/i386/mach-voyager/voyager_cat.c b/arch/i386/mach-voyager/voyager_cat.c
index 23967fe658d..10d21df1453 100644
--- a/arch/i386/mach-voyager/voyager_cat.c
+++ b/arch/i386/mach-voyager/voyager_cat.c
@@ -106,15 +106,20 @@ voyager_module_t *voyager_cat_list;
/* the I/O port assignments for the VIC and QIC */
static struct resource vic_res = {
- "Voyager Interrupt Controller", 0xFC00, 0xFC6F };
+ .name = "Voyager Interrupt Controller",
+ .start = 0xFC00,
+ .end = 0xFC6F
+};
static struct resource qic_res = {
- "Quad Interrupt Controller", 0xFC70, 0xFCFF };
+ .name = "Quad Interrupt Controller",
+ .start = 0xFC70,
+ .end = 0xFCFF
+};
/* This function is used to pack a data bit stream inside a message.
* It writes num_bits of the data buffer in msg starting at start_bit.
* Note: This function assumes that any unused bit in the data stream
* is set to zero so that the ors will work correctly */
-#define BITS_PER_BYTE 8
static void
cat_pack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits)
{
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 8165626a5c3..70e560a1b79 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -1700,7 +1700,7 @@ after_handle_vic_irq(unsigned int irq)
printk("VOYAGER SMP: CPU%d lost interrupt %d\n",
cpu, irq);
- for_each_cpu(real_cpu, mask) {
+ for_each_possible_cpu(real_cpu, mask) {
outb(VIC_CPU_MASQUERADE_ENABLE | real_cpu,
VIC_PROCESSOR_ID);
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index c4af9638dbf..fe6eb901326 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -31,6 +31,7 @@
#include <linux/nodemask.h>
#include <linux/module.h>
#include <linux/kexec.h>
+#include <linux/pfn.h>
#include <asm/e820.h>
#include <asm/setup.h>
@@ -352,17 +353,6 @@ void __init zone_sizes_init(void)
{
int nid;
- /*
- * Insert nodes into pgdat_list backward so they appear in order.
- * Clobber node 0's links and NULL out pgdat_list before starting.
- */
- pgdat_list = NULL;
- for (nid = MAX_NUMNODES - 1; nid >= 0; nid--) {
- if (!node_online(nid))
- continue;
- NODE_DATA(nid)->pgdat_next = pgdat_list;
- pgdat_list = NODE_DATA(nid);
- }
for_each_online_node(nid) {
unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 9f66ac582a8..3df1371d452 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -651,6 +651,7 @@ void __init mem_init(void)
* Specifically, in the case of x86, we will always add
* memory to the highmem for now.
*/
+#ifdef CONFIG_MEMORY_HOTPLUG
#ifndef CONFIG_NEED_MULTIPLE_NODES
int add_memory(u64 start, u64 size)
{
@@ -667,6 +668,7 @@ int remove_memory(u64 start, u64 size)
return -EINVAL;
}
#endif
+#endif
kmem_cache_t *pgd_cache;
kmem_cache_t *pmd_cache;
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
index 9db3242103b..2889567e21a 100644
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -36,7 +36,7 @@ void show_mem(void)
printk(KERN_INFO "Mem-info:\n");
show_free_areas();
printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
pgdat_resize_lock(pgdat, &flags);
for (i = 0; i < pgdat->node_spanned_pages; ++i) {
page = pgdat_page_nr(pgdat, i);
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
index 1accce50c2c..ec0fd3cfa77 100644
--- a/arch/i386/oprofile/nmi_int.c
+++ b/arch/i386/oprofile/nmi_int.c
@@ -122,7 +122,7 @@ static void nmi_save_registers(void * dummy)
static void free_msrs(void)
{
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
kfree(cpu_msrs[i].counters);
cpu_msrs[i].counters = NULL;
kfree(cpu_msrs[i].controls);
@@ -332,10 +332,11 @@ static int __init ppro_init(char ** cpu_type)
{
__u8 cpu_model = boot_cpu_data.x86_model;
- if (cpu_model > 0xd)
+ if (cpu_model == 14)
+ *cpu_type = "i386/core";
+ else if (cpu_model > 0xd)
return 0;
-
- if (cpu_model == 9) {
+ else if (cpu_model == 9) {
*cpu_type = "i386/p6_mobile";
} else if (cpu_model > 5) {
*cpu_type = "i386/piii";
diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
index 99012b93bd1..5d81fb51037 100644
--- a/arch/i386/pci/direct.c
+++ b/arch/i386/pci/direct.c
@@ -4,6 +4,7 @@
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/dmi.h>
#include "pci.h"
/*
@@ -18,8 +19,10 @@ int pci_conf1_read(unsigned int seg, unsigned int bus,
{
unsigned long flags;
- if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
+ if ((bus > 255) || (devfn > 255) || (reg > 255)) {
+ *value = -1;
return -EINVAL;
+ }
spin_lock_irqsave(&pci_config_lock, flags);
@@ -91,8 +94,10 @@ static int pci_conf2_read(unsigned int seg, unsigned int bus,
unsigned long flags;
int dev, fn;
- if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
+ if ((bus > 255) || (devfn > 255) || (reg > 255)) {
+ *value = -1;
return -EINVAL;
+ }
dev = PCI_SLOT(devfn);
fn = PCI_FUNC(devfn);
@@ -188,6 +193,10 @@ static int __init pci_sanity_check(struct pci_raw_ops *o)
if (pci_probe & PCI_NO_CHECKS)
return 1;
+ /* Assume Type 1 works for newer systems.
+ This handles machines that don't have anything on PCI Bus 0. */
+ if (dmi_get_year(DMI_BIOS_DATE) >= 2001)
+ return 1;
for (devfn = 0; devfn < 0x100; devfn++) {
if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x))
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 3ca59cad05f..06dab00aaad 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -588,7 +588,9 @@ static __init int via_router_probe(struct irq_router *r,
case PCI_DEVICE_ID_VIA_82C596:
case PCI_DEVICE_ID_VIA_82C686:
case PCI_DEVICE_ID_VIA_8231:
+ case PCI_DEVICE_ID_VIA_8233A:
case PCI_DEVICE_ID_VIA_8235:
+ case PCI_DEVICE_ID_VIA_8237:
/* FIXME: add new ones for 8233/5 */
r->name = "VIA";
r->get = pirq_via_get;
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 613789071f3..6b1ea0c9a57 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -12,14 +12,20 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <asm/e820.h>
#include "pci.h"
+#define MMCONFIG_APER_SIZE (256*1024*1024)
+
+/* Assume systems with more busses have correct MCFG */
+#define MAX_CHECK_BUS 16
+
#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
/* The base address of the last MMCONFIG device accessed */
static u32 mmcfg_last_accessed_device;
-static DECLARE_BITMAP(fallback_slots, 32);
+static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
/*
* Functions for accessing PCI configuration space with MMCONFIG accesses
@@ -29,8 +35,8 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
int cfg_num = -1;
struct acpi_table_mcfg_config *cfg;
- if (seg == 0 && bus == 0 &&
- test_bit(PCI_SLOT(devfn), fallback_slots))
+ if (seg == 0 && bus < MAX_CHECK_BUS &&
+ test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
return 0;
while (1) {
@@ -74,8 +80,10 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
unsigned long flags;
u32 base;
- if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
+ if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
+ *value = -1;
return -EINVAL;
+ }
base = get_base_addr(seg, bus, devfn);
if (!base)
@@ -146,29 +154,34 @@ static struct pci_raw_ops pci_mmcfg = {
Normally this can be expressed in the MCFG by not listing them
and assigning suitable _SEGs, but this isn't implemented in some BIOS.
Instead try to discover all devices on bus 0 that are unreachable using MM
- and fallback for them.
- We only do this for bus 0/seg 0 */
+ and fallback for them. */
static __init void unreachable_devices(void)
{
- int i;
+ int i, k;
unsigned long flags;
- for (i = 0; i < 32; i++) {
- u32 val1;
- u32 addr;
-
- pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1);
- if (val1 == 0xffffffff)
- continue;
-
- /* Locking probably not needed, but safer */
- spin_lock_irqsave(&pci_config_lock, flags);
- addr = get_base_addr(0, 0, PCI_DEVFN(i, 0));
- if (addr != 0)
- pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0));
- if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1)
- set_bit(i, fallback_slots);
- spin_unlock_irqrestore(&pci_config_lock, flags);
+ for (k = 0; k < MAX_CHECK_BUS; k++) {
+ for (i = 0; i < 32; i++) {
+ u32 val1;
+ u32 addr;
+
+ pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
+ if (val1 == 0xffffffff)
+ continue;
+
+ /* Locking probably not needed, but safer */
+ spin_lock_irqsave(&pci_config_lock, flags);
+ addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
+ if (addr != 0)
+ pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
+ if (addr == 0 ||
+ readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
+ set_bit(i, fallback_slots);
+ printk(KERN_NOTICE
+ "PCI: No mmconfig possible on %x:%x\n", k, i);
+ }
+ spin_unlock_irqrestore(&pci_config_lock, flags);
+ }
}
}
@@ -183,6 +196,14 @@ void __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0))
return;
+ if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
+ pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
+ E820_RESERVED)) {
+ printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
+ printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+ return;
+ }
+
printk(KERN_INFO "PCI: Using MMCONFIG\n");
raw_pci_ops = &pci_mmcfg;
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
index 50a0bef8c85..79b2370c7fa 100644
--- a/arch/i386/power/cpu.c
+++ b/arch/i386/power/cpu.c
@@ -92,7 +92,7 @@ void __restore_processor_state(struct saved_context *ctxt)
write_cr4(ctxt->cr4);
write_cr3(ctxt->cr3);
write_cr2(ctxt->cr2);
- write_cr2(ctxt->cr0);
+ write_cr0(ctxt->cr0);
/*
* now restore the descriptor tables to their proper values
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index edffe25a477..f0252eda12a 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -77,6 +77,7 @@ choice
config IA64_GENERIC
bool "generic"
select ACPI
+ select PCI
select NUMA
select ACPI_NUMA
help
@@ -260,15 +261,6 @@ config NR_CPUS
than 64 will cause the use of a CPU mask array, causing a small
performance hit.
-config IA64_NR_NODES
- int "Maximum number of NODEs (256-1024)" if (IA64_SGI_SN2 || IA64_GENERIC)
- range 256 1024
- depends on IA64_SGI_SN2 || IA64_GENERIC
- default "256"
- help
- This option specifies the maximum number of nodes in your SSI system.
- If in doubt, use the default.
-
config HOTPLUG_CPU
bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
depends on SMP && EXPERIMENTAL
@@ -352,6 +344,16 @@ config NUMA
Access). This option is for configuring high-end multiprocessor
server systems. If in doubt, say N.
+config NODES_SHIFT
+ int "Max num nodes shift(3-10)"
+ range 3 10
+ default "8"
+ depends on NEED_MULTIPLE_NODES
+ help
+ This option specifies the maximum number of nodes in your SSI system.
+ MAX_NUMNODES will be 2^(This value).
+ If in doubt, use the default.
+
# VIRTUAL_MEM_MAP and FLAT_NODE_MEM_MAP are functionally equivalent.
# VIRTUAL_MEM_MAP has been retained for historical reasons.
config VIRTUAL_MEM_MAP
@@ -412,6 +414,8 @@ config IA64_PALINFO
config SGI_SN
def_bool y if (IA64_SGI_SN2 || IA64_GENERIC)
+source "drivers/sn/Kconfig"
+
source "drivers/firmware/Kconfig"
source "fs/Kconfig.binfmt"
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index a718034d68d..9ea35398e10 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc5
-# Mon Feb 27 16:06:38 2006
+# Linux kernel version: 2.6.17-rc3
+# Thu Apr 27 11:48:23 2006
#
#
@@ -24,6 +24,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_CPUSETS=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
@@ -38,10 +39,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -53,7 +50,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -62,6 +58,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -84,8 +81,10 @@ CONFIG_64BIT=y
CONFIG_MMU=y
CONFIG_SWIOTLB=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_TIME_INTERPOLATION=y
+CONFIG_DMI=y
CONFIG_EFI=y
CONFIG_GENERIC_IOMAP=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
@@ -116,7 +115,6 @@ CONFIG_IA64_SGI_SN_XP=m
CONFIG_FORCE_MAX_ZONEORDER=17
CONFIG_SMP=y
CONFIG_NR_CPUS=1024
-CONFIG_IA64_NR_NODES=256
# CONFIG_HOTPLUG_CPU is not set
CONFIG_SCHED_SMT=y
CONFIG_PREEMPT=y
@@ -136,6 +134,7 @@ CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=10
CONFIG_VIRTUAL_MEM_MAP=y
CONFIG_HOLES_IN_ZONE=y
CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
@@ -187,7 +186,6 @@ CONFIG_ACPI_SYSTEM=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -231,6 +229,7 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=m
CONFIG_INET_TCP_DIAG=m
@@ -238,9 +237,11 @@ CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=m
# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_NETFILTER is not set
@@ -468,9 +469,14 @@ CONFIG_SCSI_SATA_VITESSE=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
CONFIG_SCSI_QLOGIC_1280=y
-# CONFIG_SCSI_QLA_FC is not set
+CONFIG_SCSI_QLA_FC=y
+CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y
+# CONFIG_SCSI_QLA21XX is not set
+CONFIG_SCSI_QLA22XX=y
+CONFIG_SCSI_QLA2300=y
+CONFIG_SCSI_QLA2322=y
+# CONFIG_SCSI_QLA24XX is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
@@ -486,6 +492,7 @@ CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
# CONFIG_MD_RAID6 is not set
CONFIG_MD_MULTIPATH=y
# CONFIG_MD_FAULTY is not set
@@ -694,6 +701,7 @@ CONFIG_EFI_RTC=y
# Ftape, the floppy tape device driver
#
CONFIG_AGP=y
+# CONFIG_AGP_VIA is not set
CONFIG_AGP_SGI_TIOCA=y
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=m
@@ -735,10 +743,6 @@ CONFIG_MMTIMER=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -747,6 +751,7 @@ CONFIG_MMTIMER=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -757,6 +762,7 @@ CONFIG_MMTIMER=y
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
CONFIG_DUMMY_CONSOLE=y
#
@@ -769,6 +775,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=m
# CONFIG_USB_DEBUG is not set
@@ -829,9 +836,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -846,15 +851,6 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -905,15 +901,29 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
CONFIG_INFINIBAND=m
# CONFIG_INFINIBAND_USER_MAD is not set
CONFIG_INFINIBAND_USER_ACCESS=m
CONFIG_INFINIBAND_MTHCA=m
-# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
CONFIG_INFINIBAND_IPOIB=m
-# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
CONFIG_INFINIBAND_SRP=m
#
@@ -923,8 +933,13 @@ CONFIG_SGI_IOC4=y
CONFIG_SGI_IOC3=y
#
-# EDAC - error detection and reporting (RAS)
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -997,7 +1012,6 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1145,7 +1159,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
CONFIG_DEBUG_PREEMPT=y
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index bdccd0b1eb6..dd4a2f79263 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1999,7 +1999,7 @@ acpi_sba_ioc_add(struct acpi_device *device)
if (!iovp_shift)
iovp_shift = min(PAGE_SHIFT, 16);
}
- ACPI_MEM_FREE(dev_info);
+ kfree(dev_info);
/*
* default anything not caught above or specified on cmdline to 4k
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
index 4e7a6a1ec6c..da03c06744f 100644
--- a/arch/ia64/ia32/binfmt_elf32.c
+++ b/arch/ia64/ia32/binfmt_elf32.c
@@ -35,6 +35,9 @@ extern void ia64_elf32_init (struct pt_regs *regs);
static void elf32_set_personality (void);
+static unsigned long __attribute ((unused))
+randomize_stack_top(unsigned long stack_top);
+
#define setup_arg_pages(bprm,tos,exec) ia32_setup_arg_pages(bprm,exec)
#define elf_map elf32_map
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 95fe04400f6..a32cd59b81e 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -334,7 +334,7 @@ ia32_syscall_table:
data8 sys_setdomainname
data8 sys32_newuname
data8 sys32_modify_ldt
- data8 sys_ni_syscall /* adjtimex */
+ data8 compat_sys_adjtimex
data8 sys32_mprotect /* 125 */
data8 compat_sys_sigprocmask
data8 sys_ni_syscall /* create_module */
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 59e871dae74..09a0dbc17fb 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := head.o init_task.o vmlinux.lds
obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \
irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \
salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
- unwind.o mca.o mca_asm.o topology.o dmi_scan.o
+ unwind.o mca.o mca_asm.o topology.o
obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o
@@ -30,7 +30,6 @@ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
mca_recovery-y += mca_drv.o mca_drv_asm.o
-dmi_scan-y += ../../i386/kernel/dmi_scan.o
# The gate DSO image is built using a special linker script.
targets += gate.so gate-syms.o
diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c
index 4a5574ff007..fff82929d22 100644
--- a/arch/ia64/kernel/acpi-ext.c
+++ b/arch/ia64/kernel/acpi-ext.c
@@ -1,105 +1,104 @@
/*
- * arch/ia64/kernel/acpi-ext.c
+ * (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P.
+ * Alex Williamson <alex.williamson@hp.com>
+ * Bjorn Helgaas <bjorn.helgaas@hp.com>
*
- * Copyright (C) 2003 Hewlett-Packard
- * Copyright (C) Alex Williamson
- * Copyright (C) Bjorn Helgaas
- *
- * Vendor specific extensions to ACPI.
+ * 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/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/acpi.h>
-#include <linux/efi.h>
#include <asm/acpi-ext.h>
-struct acpi_vendor_descriptor {
- u8 guid_id;
- efi_guid_t guid;
-};
+/*
+ * Device CSRs that do not appear in PCI config space should be described
+ * via ACPI. This would normally be done with Address Space Descriptors
+ * marked as "consumer-only," but old versions of Windows and Linux ignore
+ * the producer/consumer flag, so HP invented a vendor-defined resource to
+ * describe the location and size of CSR space.
+ */
-struct acpi_vendor_info {
- struct acpi_vendor_descriptor *descriptor;
- u8 *data;
- u32 length;
+struct acpi_vendor_uuid hp_ccsr_uuid = {
+ .subtype = 2,
+ .data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
+ 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
};
-acpi_status
-acpi_vendor_resource_match(struct acpi_resource *resource, void *context)
+static acpi_status hp_ccsr_locate(acpi_handle obj, u64 *base, u64 *length)
{
- struct acpi_vendor_info *info = (struct acpi_vendor_info *)context;
- struct acpi_resource_vendor *vendor;
- struct acpi_vendor_descriptor *descriptor;
- u32 byte_length;
-
- if (resource->type != ACPI_RESOURCE_TYPE_VENDOR)
- return AE_OK;
-
- vendor = (struct acpi_resource_vendor *)&resource->data;
- descriptor = (struct acpi_vendor_descriptor *)vendor->byte_data;
- if (vendor->byte_length <= sizeof(*info->descriptor) ||
- descriptor->guid_id != info->descriptor->guid_id ||
- efi_guidcmp(descriptor->guid, info->descriptor->guid))
- return AE_OK;
-
- byte_length = vendor->byte_length - sizeof(struct acpi_vendor_descriptor);
- info->data = acpi_os_allocate(byte_length);
- if (!info->data)
- return AE_NO_MEMORY;
-
- memcpy(info->data,
- vendor->byte_data + sizeof(struct acpi_vendor_descriptor),
- byte_length);
- info->length = byte_length;
- return AE_CTRL_TERMINATE;
-}
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_resource *resource;
+ struct acpi_resource_vendor_typed *vendor;
-acpi_status
-acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor * id,
- u8 ** data, u32 * byte_length)
-{
- struct acpi_vendor_info info;
+ status = acpi_get_vendor_resource(obj, METHOD_NAME__CRS, &hp_ccsr_uuid,
+ &buffer);
- info.descriptor = id;
- info.data = NULL;
+ resource = buffer.pointer;
+ vendor = &resource->data.vendor_typed;
- acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match,
- &info);
- if (!info.data)
- return AE_NOT_FOUND;
+ if (ACPI_FAILURE(status) || vendor->byte_length < 16) {
+ status = AE_NOT_FOUND;
+ goto exit;
+ }
- *data = info.data;
- *byte_length = info.length;
- return AE_OK;
+ memcpy(base, vendor->byte_data, sizeof(*base));
+ memcpy(length, vendor->byte_data + 8, sizeof(*length));
+
+ exit:
+ acpi_os_free(buffer.pointer);
+ return status;
}
-struct acpi_vendor_descriptor hp_ccsr_descriptor = {
- .guid_id = 2,
- .guid =
- EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, 0xf6, 0x4a, 0x24, 0xd2, 0x01,
- 0x37, 0x0e, 0xad)
+struct csr_space {
+ u64 base;
+ u64 length;
};
-acpi_status hp_acpi_csr_space(acpi_handle obj, u64 * csr_base, u64 * csr_length)
+static acpi_status find_csr_space(struct acpi_resource *resource, void *data)
{
+ struct csr_space *space = data;
+ struct acpi_resource_address64 addr;
acpi_status status;
- u8 *data;
- u32 length;
- status =
- acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length);
+ status = acpi_resource_to_address64(resource, &addr);
+ if (ACPI_SUCCESS(status) &&
+ addr.resource_type == ACPI_MEMORY_RANGE &&
+ addr.address_length &&
+ addr.producer_consumer == ACPI_CONSUMER) {
+ space->base = addr.minimum;
+ space->length = addr.address_length;
+ return AE_CTRL_TERMINATE;
+ }
+ return AE_OK; /* keep looking */
+}
- if (ACPI_FAILURE(status) || length != 16)
- return AE_NOT_FOUND;
+static acpi_status hp_crs_locate(acpi_handle obj, u64 *base, u64 *length)
+{
+ struct csr_space space = { 0, 0 };
- memcpy(csr_base, data, sizeof(*csr_base));
- memcpy(csr_length, data + 8, sizeof(*csr_length));
- acpi_os_free(data);
+ acpi_walk_resources(obj, METHOD_NAME__CRS, find_csr_space, &space);
+ if (!space.length)
+ return AE_NOT_FOUND;
+ *base = space.base;
+ *length = space.length;
return AE_OK;
}
+acpi_status hp_acpi_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
+{
+ acpi_status status;
+
+ status = hp_ccsr_locate(obj, csr_base, csr_length);
+ if (ACPI_SUCCESS(status))
+ return status;
+
+ return hp_crs_locate(obj, csr_base, csr_length);
+}
EXPORT_SYMBOL(hp_acpi_csr_space);
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 0e3eda99e54..bcb80ca5cf4 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1605,5 +1605,11 @@ sys_call_table:
data8 sys_ni_syscall // reserved for pselect
data8 sys_ni_syscall // 1295 reserved for ppoll
data8 sys_unshare
+ data8 sys_splice
+ data8 sys_set_robust_list
+ data8 sys_get_robust_list
+ data8 sys_sync_file_range // 1300
+ data8 sys_tee
+ data8 sys_vmsplice
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S
index e1e4aba9ecd..7c99e6ec3da 100644
--- a/arch/ia64/kernel/gate.lds.S
+++ b/arch/ia64/kernel/gate.lds.S
@@ -59,6 +59,7 @@ SECTIONS
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(__ex_table)
+ *(__mca_table)
}
}
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 8832c553230..d58c1c5c903 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -9,54 +9,65 @@
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
*
- * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O APIC code.
- * In particular, we now have separate handlers for edge
- * and level triggered interrupts.
- * 00/10/27 Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector allocation
- * PCI to vector mapping, shared PCI interrupts.
- * 00/10/27 D. Mosberger Document things a bit more to make them more understandable.
- * Clean up much of the old IOSAPIC cruft.
- * 01/07/27 J.I. Lee PCI irq routing, Platform/Legacy interrupts and fixes for
- * ACPI S5(SoftOff) support.
+ * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O
+ * APIC code. In particular, we now have separate
+ * handlers for edge and level triggered
+ * interrupts.
+ * 00/10/27 Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector
+ * allocation PCI to vector mapping, shared PCI
+ * interrupts.
+ * 00/10/27 D. Mosberger Document things a bit more to make them more
+ * understandable. Clean up much of the old
+ * IOSAPIC cruft.
+ * 01/07/27 J.I. Lee PCI irq routing, Platform/Legacy interrupts
+ * and fixes for ACPI S5(SoftOff) support.
* 02/01/23 J.I. Lee iosapic pgm fixes for PCI irq routing from _PRT
- * 02/01/07 E. Focht <efocht@ess.nec.de> Redirectable interrupt vectors in
- * iosapic_set_affinity(), initializations for
- * /proc/irq/#/smp_affinity
+ * 02/01/07 E. Focht <efocht@ess.nec.de> Redirectable interrupt
+ * vectors in iosapic_set_affinity(),
+ * initializations for /proc/irq/#/smp_affinity
* 02/04/02 P. Diefenbaugh Cleaned up ACPI PCI IRQ routing.
* 02/04/18 J.I. Lee bug fix in iosapic_init_pci_irq
- * 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to IOSAPIC mapping
- * error
+ * 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to
+ * IOSAPIC mapping error
* 02/07/29 T. Kochi Allocate interrupt vectors dynamically
- * 02/08/04 T. Kochi Cleaned up terminology (irq, global system interrupt, vector, etc.)
- * 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's pci_irq code.
+ * 02/08/04 T. Kochi Cleaned up terminology (irq, global system
+ * interrupt, vector, etc.)
+ * 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's
+ * pci_irq code.
* 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC.
- * Remove iosapic_address & gsi_base from external interfaces.
- * Rationalize __init/__devinit attributes.
+ * Remove iosapic_address & gsi_base from
+ * external interfaces. Rationalize
+ * __init/__devinit attributes.
* 04/12/04 Ashok Raj <ashok.raj@intel.com> Intel Corporation 2004
- * Updated to work with irq migration necessary for CPU Hotplug
+ * Updated to work with irq migration necessary
+ * for CPU Hotplug
*/
/*
- * Here is what the interrupt logic between a PCI device and the kernel looks like:
+ * Here is what the interrupt logic between a PCI device and the kernel looks
+ * like:
*
- * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC, INTD). The
- * device is uniquely identified by its bus--, and slot-number (the function
- * number does not matter here because all functions share the same interrupt
- * lines).
+ * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC,
+ * INTD). The device is uniquely identified by its bus-, and slot-number
+ * (the function number does not matter here because all functions share
+ * the same interrupt lines).
*
- * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC controller.
- * Multiple interrupt lines may have to share the same IOSAPIC pin (if they're level
- * triggered and use the same polarity). Each interrupt line has a unique Global
- * System Interrupt (GSI) number which can be calculated as the sum of the controller's
- * base GSI number and the IOSAPIC pin number to which the line connects.
+ * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC
+ * controller. Multiple interrupt lines may have to share the same
+ * IOSAPIC pin (if they're level triggered and use the same polarity).
+ * Each interrupt line has a unique Global System Interrupt (GSI) number
+ * which can be calculated as the sum of the controller's base GSI number
+ * and the IOSAPIC pin number to which the line connects.
*
- * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the IOSAPIC pin
- * into the IA-64 interrupt vector. This interrupt vector is then sent to the CPU.
+ * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the
+ * IOSAPIC pin into the IA-64 interrupt vector. This interrupt vector is then
+ * sent to the CPU.
*
- * (4) The kernel recognizes an interrupt as an IRQ. The IRQ interface is used as
- * architecture-independent interrupt handling mechanism in Linux. As an
- * IRQ is a number, we have to have IA-64 interrupt vector number <-> IRQ number
- * mapping. On smaller systems, we use one-to-one mapping between IA-64 vector and
- * IRQ. A platform can implement platform_irq_to_vector(irq) and
+ * (4) The kernel recognizes an interrupt as an IRQ. The IRQ interface is
+ * used as architecture-independent interrupt handling mechanism in Linux.
+ * As an IRQ is a number, we have to have
+ * IA-64 interrupt vector number <-> IRQ number mapping. On smaller
+ * systems, we use one-to-one mapping between IA-64 vector and IRQ. A
+ * platform can implement platform_irq_to_vector(irq) and
* platform_local_vector_to_irq(vector) APIs to differentiate the mapping.
* Please see also include/asm-ia64/hw_irq.h for those APIs.
*
@@ -64,9 +75,9 @@
*
* PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ
*
- * Note: The term "IRQ" is loosely used everywhere in Linux kernel to describe interrupts.
- * Now we use "IRQ" only for Linux IRQ's. ISA IRQ (isa_irq) is the only exception in this
- * source code.
+ * Note: The term "IRQ" is loosely used everywhere in Linux kernel to
+ * describeinterrupts. Now we use "IRQ" only for Linux IRQ's. ISA IRQ
+ * (isa_irq) is the only exception in this source code.
*/
#include <linux/config.h>
@@ -90,7 +101,6 @@
#include <asm/ptrace.h>
#include <asm/system.h>
-
#undef DEBUG_INTERRUPT_ROUTING
#ifdef DEBUG_INTERRUPT_ROUTING
@@ -99,36 +109,46 @@
#define DBG(fmt...)
#endif
-#define NR_PREALLOCATE_RTE_ENTRIES (PAGE_SIZE / sizeof(struct iosapic_rte_info))
+#define NR_PREALLOCATE_RTE_ENTRIES \
+ (PAGE_SIZE / sizeof(struct iosapic_rte_info))
#define RTE_PREALLOCATED (1)
static DEFINE_SPINLOCK(iosapic_lock);
-/* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */
+/*
+ * These tables map IA-64 vectors to the IOSAPIC pin that generates this
+ * vector.
+ */
struct iosapic_rte_info {
- struct list_head rte_list; /* node in list of RTEs sharing the same vector */
+ struct list_head rte_list; /* node in list of RTEs sharing the
+ * same vector */
char __iomem *addr; /* base address of IOSAPIC */
- unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */
+ unsigned int gsi_base; /* first GSI assigned to this
+ * IOSAPIC */
char rte_index; /* IOSAPIC RTE index */
int refcnt; /* reference counter */
unsigned int flags; /* flags */
} ____cacheline_aligned;
static struct iosapic_intr_info {
- struct list_head rtes; /* RTEs using this vector (empty => not an IOSAPIC interrupt) */
+ struct list_head rtes; /* RTEs using this vector (empty =>
+ * not an IOSAPIC interrupt) */
int count; /* # of RTEs that shares this vector */
- u32 low32; /* current value of low word of Redirection table entry */
+ u32 low32; /* current value of low word of
+ * Redirection table entry */
unsigned int dest; /* destination CPU physical ID */
unsigned char dmode : 3; /* delivery mode (see iosapic.h) */
- unsigned char polarity: 1; /* interrupt polarity (see iosapic.h) */
+ unsigned char polarity: 1; /* interrupt polarity
+ * (see iosapic.h) */
unsigned char trigger : 1; /* trigger mode (see iosapic.h) */
} iosapic_intr_info[IA64_NUM_VECTORS];
static struct iosapic {
char __iomem *addr; /* base address of IOSAPIC */
- unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */
- unsigned short num_rte; /* number of RTE in this IOSAPIC */
+ unsigned int gsi_base; /* first GSI assigned to this
+ * IOSAPIC */
+ unsigned short num_rte; /* # of RTEs on this IOSAPIC */
int rtes_inuse; /* # of RTEs in use on this IOSAPIC */
#ifdef CONFIG_NUMA
unsigned short node; /* numa node association via pxm */
@@ -149,7 +169,8 @@ find_iosapic (unsigned int gsi)
int i;
for (i = 0; i < NR_IOSAPICS; i++) {
- if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte)
+ if ((unsigned) (gsi - iosapic_lists[i].gsi_base) <
+ iosapic_lists[i].num_rte)
return i;
}
@@ -162,7 +183,8 @@ _gsi_to_vector (unsigned int gsi)
struct iosapic_intr_info *info;
struct iosapic_rte_info *rte;
- for (info = iosapic_intr_info; info < iosapic_intr_info + IA64_NUM_VECTORS; ++info)
+ for (info = iosapic_intr_info; info <
+ iosapic_intr_info + IA64_NUM_VECTORS; ++info)
list_for_each_entry(rte, &info->rtes, rte_list)
if (rte->gsi_base + rte->rte_index == gsi)
return info - iosapic_intr_info;
@@ -185,8 +207,8 @@ gsi_to_irq (unsigned int gsi)
unsigned long flags;
int irq;
/*
- * XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq
- * numbers...
+ * XXX fix me: this assumes an identity mapping between IA-64 vector
+ * and Linux irq numbers...
*/
spin_lock_irqsave(&iosapic_lock, flags);
{
@@ -197,7 +219,8 @@ gsi_to_irq (unsigned int gsi)
return irq;
}
-static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, unsigned int vec)
+static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi,
+ unsigned int vec)
{
struct iosapic_rte_info *rte;
@@ -237,7 +260,9 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask)
for (irq = 0; irq < NR_IRQS; ++irq)
if (irq_to_vector(irq) == vector) {
- set_irq_affinity_info(irq, (int)(dest & 0xffff), redir);
+ set_irq_affinity_info(irq,
+ (int)(dest & 0xffff),
+ redir);
break;
}
}
@@ -259,7 +284,7 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask)
}
static void
-nop (unsigned int vector)
+nop (unsigned int irq)
{
/* do nothing... */
}
@@ -281,7 +306,8 @@ mask_irq (unsigned int irq)
{
/* set only the mask bit */
low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK;
- list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
+ list_for_each_entry(rte, &iosapic_intr_info[vec].rtes,
+ rte_list) {
addr = rte->addr;
rte_index = rte->rte_index;
iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
@@ -306,7 +332,8 @@ unmask_irq (unsigned int irq)
spin_lock_irqsave(&iosapic_lock, flags);
{
low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK;
- list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
+ list_for_each_entry(rte, &iosapic_intr_info[vec].rtes,
+ rte_list) {
addr = rte->addr;
rte_index = rte->rte_index;
iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
@@ -346,21 +373,25 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
spin_lock_irqsave(&iosapic_lock, flags);
{
- low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT);
+ low32 = iosapic_intr_info[vec].low32 &
+ ~(7 << IOSAPIC_DELIVERY_SHIFT);
if (redir)
/* change delivery mode to lowest priority */
- low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
+ low32 |= (IOSAPIC_LOWEST_PRIORITY <<
+ IOSAPIC_DELIVERY_SHIFT);
else
/* change delivery mode to fixed */
low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
iosapic_intr_info[vec].low32 = low32;
iosapic_intr_info[vec].dest = dest;
- list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
+ list_for_each_entry(rte, &iosapic_intr_info[vec].rtes,
+ rte_list) {
addr = rte->addr;
rte_index = rte->rte_index;
- iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32);
+ iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index),
+ high32);
iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
}
}
@@ -385,7 +416,7 @@ iosapic_end_level_irq (unsigned int irq)
ia64_vector vec = irq_to_vector(irq);
struct iosapic_rte_info *rte;
- move_irq(irq);
+ move_native_irq(irq);
list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list)
iosapic_eoi(rte->addr, vec);
}
@@ -427,13 +458,14 @@ iosapic_ack_edge_irq (unsigned int irq)
{
irq_desc_t *idesc = irq_descp(irq);
- move_irq(irq);
+ move_native_irq(irq);
/*
* Once we have recorded IRQ_PENDING already, we can mask the
* interrupt for real. This prevents IRQ storms from unhandled
* devices.
*/
- if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) == (IRQ_PENDING|IRQ_DISABLED))
+ if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) ==
+ (IRQ_PENDING|IRQ_DISABLED))
mask_irq(irq);
}
@@ -467,7 +499,8 @@ iosapic_version (char __iomem *addr)
return iosapic_read(addr, IOSAPIC_VERSION);
}
-static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long pol)
+static int iosapic_find_sharable_vector (unsigned long trigger,
+ unsigned long pol)
{
int i, vector = -1, min_count = -1;
struct iosapic_intr_info *info;
@@ -482,7 +515,8 @@ static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long po
for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) {
info = &iosapic_intr_info[i];
if (info->trigger == trigger && info->polarity == pol &&
- (info->dmode == IOSAPIC_FIXED || info->dmode == IOSAPIC_LOWEST_PRIORITY)) {
+ (info->dmode == IOSAPIC_FIXED || info->dmode ==
+ IOSAPIC_LOWEST_PRIORITY)) {
if (min_count == -1 || info->count < min_count) {
vector = i;
min_count = info->count;
@@ -506,12 +540,15 @@ iosapic_reassign_vector (int vector)
new_vector = assign_irq_vector(AUTO_ASSIGN);
if (new_vector < 0)
panic("%s: out of interrupt vectors!\n", __FUNCTION__);
- printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector);
+ printk(KERN_INFO "Reassigning vector %d to %d\n",
+ vector, new_vector);
memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector],
sizeof(struct iosapic_intr_info));
INIT_LIST_HEAD(&iosapic_intr_info[new_vector].rtes);
- list_move(iosapic_intr_info[vector].rtes.next, &iosapic_intr_info[new_vector].rtes);
- memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
+ list_move(iosapic_intr_info[vector].rtes.next,
+ &iosapic_intr_info[new_vector].rtes);
+ memset(&iosapic_intr_info[vector], 0,
+ sizeof(struct iosapic_intr_info));
iosapic_intr_info[vector].low32 = IOSAPIC_MASK;
INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);
}
@@ -524,7 +561,8 @@ static struct iosapic_rte_info *iosapic_alloc_rte (void)
int preallocated = 0;
if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) {
- rte = alloc_bootmem(sizeof(struct iosapic_rte_info) * NR_PREALLOCATE_RTE_ENTRIES);
+ rte = alloc_bootmem(sizeof(struct iosapic_rte_info) *
+ NR_PREALLOCATE_RTE_ENTRIES);
if (!rte)
return NULL;
for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++)
@@ -532,7 +570,8 @@ static struct iosapic_rte_info *iosapic_alloc_rte (void)
}
if (!list_empty(&free_rte_list)) {
- rte = list_entry(free_rte_list.next, struct iosapic_rte_info, rte_list);
+ rte = list_entry(free_rte_list.next, struct iosapic_rte_info,
+ rte_list);
list_del(&rte->rte_list);
preallocated++;
} else {
@@ -575,7 +614,8 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
index = find_iosapic(gsi);
if (index < 0) {
- printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", __FUNCTION__, gsi);
+ printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",
+ __FUNCTION__, gsi);
return -ENODEV;
}
@@ -586,7 +626,8 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
if (!rte) {
rte = iosapic_alloc_rte();
if (!rte) {
- printk(KERN_WARNING "%s: cannot allocate memory\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: cannot allocate memory\n",
+ __FUNCTION__);
return -ENOMEM;
}
@@ -602,7 +643,9 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
else if (vector_is_shared(vector)) {
struct iosapic_intr_info *info = &iosapic_intr_info[vector];
if (info->trigger != trigger || info->polarity != polarity) {
- printk (KERN_WARNING "%s: cannot override the interrupt\n", __FUNCTION__);
+ printk (KERN_WARNING
+ "%s: cannot override the interrupt\n",
+ __FUNCTION__);
return -EINVAL;
}
}
@@ -619,8 +662,10 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
idesc = irq_descp(vector);
if (idesc->handler != irq_type) {
if (idesc->handler != &no_irq_type)
- printk(KERN_WARNING "%s: changing vector %d from %s to %s\n",
- __FUNCTION__, vector, idesc->handler->typename, irq_type->typename);
+ printk(KERN_WARNING
+ "%s: changing vector %d from %s to %s\n",
+ __FUNCTION__, vector,
+ idesc->handler->typename, irq_type->typename);
idesc->handler = irq_type;
}
return 0;
@@ -681,7 +726,7 @@ get_target_cpu (unsigned int gsi, int vector)
if (!num_cpus)
goto skip_numa_setup;
- /* Use vector assigment to distribute across cpus in node */
+ /* Use vector assignment to distribute across cpus in node */
cpu_index = vector % num_cpus;
for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++)
@@ -703,7 +748,7 @@ skip_numa_setup:
} while (!cpu_online(cpu));
return cpu_physical_id(cpu);
-#else
+#else /* CONFIG_SMP */
return cpu_physical_id(smp_processor_id());
#endif
}
@@ -755,7 +800,8 @@ again:
if (list_empty(&iosapic_intr_info[vector].rtes))
free_irq_vector(vector);
spin_unlock(&iosapic_lock);
- spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);
+ spin_unlock_irqrestore(&irq_descp(vector)->lock,
+ flags);
goto again;
}
@@ -764,7 +810,8 @@ again:
polarity, trigger);
if (err < 0) {
spin_unlock(&iosapic_lock);
- spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);
+ spin_unlock_irqrestore(&irq_descp(vector)->lock,
+ flags);
return err;
}
@@ -806,7 +853,8 @@ iosapic_unregister_intr (unsigned int gsi)
*/
irq = gsi_to_irq(gsi);
if (irq < 0) {
- printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi);
+ printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n",
+ gsi);
WARN_ON(1);
return;
}
@@ -817,7 +865,9 @@ iosapic_unregister_intr (unsigned int gsi)
spin_lock(&iosapic_lock);
{
if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) {
- printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi);
+ printk(KERN_ERR
+ "iosapic_unregister_intr(%u) unbalanced\n",
+ gsi);
WARN_ON(1);
goto out;
}
@@ -827,7 +877,8 @@ iosapic_unregister_intr (unsigned int gsi)
/* Mask the interrupt */
low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK;
- iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), low32);
+ iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index),
+ low32);
/* Remove the rte entry from the list */
list_del(&rte->rte_list);
@@ -840,7 +891,9 @@ iosapic_unregister_intr (unsigned int gsi)
trigger = iosapic_intr_info[vector].trigger;
polarity = iosapic_intr_info[vector].polarity;
dest = iosapic_intr_info[vector].dest;
- printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n",
+ printk(KERN_INFO
+ "GSI %u (%s, %s) -> CPU %d (0x%04x)"
+ " vector %d unregistered\n",
gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
(polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
cpu_logical_id(dest), dest, vector);
@@ -853,12 +906,15 @@ iosapic_unregister_intr (unsigned int gsi)
idesc->handler = &no_irq_type;
/* Clear the interrupt information */
- memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
+ memset(&iosapic_intr_info[vector], 0,
+ sizeof(struct iosapic_intr_info));
iosapic_intr_info[vector].low32 |= IOSAPIC_MASK;
INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);
if (idesc->action) {
- printk(KERN_ERR "interrupt handlers still exist on IRQ %u\n", irq);
+ printk(KERN_ERR
+ "interrupt handlers still exist on"
+ "IRQ %u\n", irq);
WARN_ON(1);
}
@@ -873,7 +929,6 @@ iosapic_unregister_intr (unsigned int gsi)
/*
* ACPI calls this when it finds an entry for a platform interrupt.
- * Note that the irq_base and IOSAPIC address must be set in iosapic_init().
*/
int __init
iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
@@ -907,13 +962,16 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
mask = 1;
break;
default:
- printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type 0x%x\n", int_type);
+ printk(KERN_ERR "%s: invalid int type 0x%x\n", __FUNCTION__,
+ int_type);
return -1;
}
register_intr(gsi, vector, delivery, polarity, trigger);
- printk(KERN_INFO "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
+ printk(KERN_INFO
+ "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)"
+ " vector %d\n",
int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown",
int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
(polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
@@ -923,10 +981,8 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
return vector;
}
-
/*
* ACPI calls this when it finds an entry for a legacy ISA IRQ override.
- * Note that the gsi_base and IOSAPIC address must be set in iosapic_init().
*/
void __init
iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
@@ -955,16 +1011,19 @@ iosapic_system_init (int system_pcat_compat)
for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) {
iosapic_intr_info[vector].low32 = IOSAPIC_MASK;
- INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); /* mark as unused */
+ /* mark as unused */
+ INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);
}
pcat_compat = system_pcat_compat;
if (pcat_compat) {
/*
- * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
- * enabled.
+ * Disable the compatibility mode interrupts (8259 style),
+ * needs IN/OUT support enabled.
*/
- printk(KERN_INFO "%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__);
+ printk(KERN_INFO
+ "%s: Disabling PC-AT compatible 8259 interrupts\n",
+ __FUNCTION__);
outb(0xff, 0xA1);
outb(0xff, 0x21);
}
@@ -1004,10 +1063,7 @@ iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver)
base = iosapic_lists[index].gsi_base;
end = base + iosapic_lists[index].num_rte - 1;
- if (gsi_base < base && gsi_end < base)
- continue;/* OK */
-
- if (gsi_base > end && gsi_end > end)
+ if (gsi_end < base || end < gsi_base)
continue; /* OK */
return -EBUSY;
@@ -1053,12 +1109,14 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
if ((gsi_base == 0) && pcat_compat) {
/*
- * Map the legacy ISA devices into the IOSAPIC data. Some of these may
- * get reprogrammed later on with data from the ACPI Interrupt Source
- * Override table.
+ * Map the legacy ISA devices into the IOSAPIC data. Some of
+ * these may get reprogrammed later on with data from the ACPI
+ * Interrupt Source Override table.
*/
for (isa_irq = 0; isa_irq < 16; ++isa_irq)
- iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
+ iosapic_override_isa_irq(isa_irq, isa_irq,
+ IOSAPIC_POL_HIGH,
+ IOSAPIC_EDGE);
}
return 0;
}
@@ -1081,7 +1139,8 @@ iosapic_remove (unsigned int gsi_base)
if (iosapic_lists[index].rtes_inuse) {
err = -EBUSY;
- printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n",
+ printk(KERN_WARNING
+ "%s: IOSAPIC for GSI base %u is busy\n",
__FUNCTION__, gsi_base);
goto out;
}
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 5ce908ef9c9..9c72ea3f643 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -101,7 +101,6 @@ void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
if (irq < NR_IRQS) {
irq_affinity[irq] = mask;
- set_irq_info(irq, mask);
irq_redir[irq] = (char) (redir & 0xff);
}
}
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 789881ca83d..f9039f88d01 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -251,7 +251,7 @@ static void __kprobes prepare_break_inst(uint template, uint slot,
update_kprobe_inst_flag(template, slot, major_opcode, kprobe_inst, p);
}
-static inline void get_kprobe_inst(bundle_t *bundle, uint slot,
+static void __kprobes get_kprobe_inst(bundle_t *bundle, uint slot,
unsigned long *kprobe_inst, uint *major_opcode)
{
unsigned long kprobe_inst_p0, kprobe_inst_p1;
@@ -278,7 +278,7 @@ static inline void get_kprobe_inst(bundle_t *bundle, uint slot,
}
/* Returns non-zero if the addr is in the Interrupt Vector Table */
-static inline int in_ivt_functions(unsigned long addr)
+static int __kprobes in_ivt_functions(unsigned long addr)
{
return (addr >= (unsigned long)__start_ivt_text
&& addr < (unsigned long)__end_ivt_text);
@@ -308,19 +308,19 @@ static int __kprobes valid_kprobe_addr(int template, int slot,
return 0;
}
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status;
}
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status;
}
-static inline void set_current_kprobe(struct kprobe *p,
+static void __kprobes set_current_kprobe(struct kprobe *p,
struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = p;
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 8963171788d..6a0880639bc 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -581,10 +581,12 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs)
{
unsigned long flags;
int cpu = smp_processor_id();
+ struct ia64_mca_notify_die nd =
+ { .sos = NULL, .monarch_cpu = &monarch_cpu };
/* Mask all interrupts */
local_irq_save(flags);
- if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", regs, 0, 0, 0)
+ if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
@@ -594,7 +596,7 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs)
*/
ia64_sal_mc_rendez();
- if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", regs, 0, 0, 0)
+ if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
@@ -602,7 +604,7 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs)
while (monarch_cpu != -1)
cpu_relax(); /* spin until monarch leaves */
- if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", regs, 0, 0, 0)
+ if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
@@ -961,7 +963,7 @@ no_mod:
*/
static void
-ia64_wait_for_slaves(int monarch)
+ia64_wait_for_slaves(int monarch, const char *type)
{
int c, wait = 0, missing = 0;
for_each_online_cpu(c) {
@@ -987,7 +989,7 @@ ia64_wait_for_slaves(int monarch)
}
if (!missing)
goto all_in;
- printk(KERN_INFO "OS MCA slave did not rendezvous on cpu");
+ printk(KERN_INFO "OS %s slave did not rendezvous on cpu", type);
for_each_online_cpu(c) {
if (c == monarch)
continue;
@@ -998,7 +1000,7 @@ ia64_wait_for_slaves(int monarch)
return;
all_in:
- printk(KERN_INFO "All OS MCA slaves have reached rendezvous\n");
+ printk(KERN_INFO "All OS %s slaves have reached rendezvous\n", type);
return;
}
@@ -1023,6 +1025,8 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
&sos->proc_state_param;
int recover, cpu = smp_processor_id();
task_t *previous_current;
+ struct ia64_mca_notify_die nd =
+ { .sos = sos, .monarch_cpu = &monarch_cpu };
oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */
console_loglevel = 15; /* make sure printks make it to console */
@@ -1031,10 +1035,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
monarch_cpu = cpu;
- if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0)
+ if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
- ia64_wait_for_slaves(cpu);
+ ia64_wait_for_slaves(cpu, "MCA");
/* Wakeup all the processors which are spinning in the rendezvous loop.
* They will leave SAL, then spin in the OS with interrupts disabled
@@ -1043,7 +1047,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
* spinning in SAL does not work.
*/
ia64_mca_wakeup_all();
- if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, 0, 0, 0)
+ if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
@@ -1064,7 +1068,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA);
sos->os_status = IA64_MCA_CORRECTED;
}
- if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, 0, 0, recover)
+ if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
@@ -1351,10 +1355,14 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
static atomic_t monarchs;
task_t *previous_current;
int cpu = smp_processor_id();
+ struct ia64_mca_notify_die nd =
+ { .sos = sos, .monarch_cpu = &monarch_cpu };
oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */
console_loglevel = 15; /* make sure printks make it to console */
+ (void) notify_die(DIE_INIT_ENTER, "INIT", regs, (long)&nd, 0, 0);
+
printk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
sos->proc_state_param, cpu, sos->monarch);
salinfo_log_wakeup(SAL_INFO_TYPE_INIT, NULL, 0, 0);
@@ -1390,15 +1398,15 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT;
while (monarch_cpu == -1)
cpu_relax(); /* spin until monarch enters */
- if (notify_die(DIE_INIT_SLAVE_ENTER, "INIT", regs, 0, 0, 0)
+ if (notify_die(DIE_INIT_SLAVE_ENTER, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
- if (notify_die(DIE_INIT_SLAVE_PROCESS, "INIT", regs, 0, 0, 0)
+ if (notify_die(DIE_INIT_SLAVE_PROCESS, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
while (monarch_cpu != -1)
cpu_relax(); /* spin until monarch leaves */
- if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, 0, 0, 0)
+ if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
printk("Slave on cpu %d returning to normal service.\n", cpu);
@@ -1409,7 +1417,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
}
monarch_cpu = cpu;
- if (notify_die(DIE_INIT_MONARCH_ENTER, "INIT", regs, 0, 0, 0)
+ if (notify_die(DIE_INIT_MONARCH_ENTER, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
@@ -1421,15 +1429,15 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
*/
printk("Delaying for 5 seconds...\n");
udelay(5*1000000);
- ia64_wait_for_slaves(cpu);
+ ia64_wait_for_slaves(cpu, "INIT");
/* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through
* to default_monarch_init_process() above and just print all the
* tasks.
*/
- if (notify_die(DIE_INIT_MONARCH_PROCESS, "INIT", regs, 0, 0, 0)
+ if (notify_die(DIE_INIT_MONARCH_PROCESS, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
- if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, 0, 0, 0)
+ if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
printk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu);
@@ -1631,6 +1639,7 @@ ia64_mca_init(void)
printk(KERN_INFO "Increasing MCA rendezvous timeout from "
"%ld to %ld milliseconds\n", timeout, isrv.v0);
timeout = isrv.v0;
+ (void) notify_die(DIE_MCA_NEW_TIMEOUT, "MCA", NULL, timeout, 0, 0);
continue;
}
printk(KERN_ERR "Failed to register rendezvous interrupt "
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 60a464bfd9e..6dff024cd62 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -827,7 +827,7 @@ ia64_state_restore:
ld8 r9=[temp2],16 // sal_gp
;;
ld8 r22=[temp1],16 // pal_min_state, virtual
- ld8 r21=[temp2],16 // prev_IA64_KR_CURRENT
+ ld8 r13=[temp2],16 // prev_IA64_KR_CURRENT
;;
ld8 r16=[temp1],16 // prev_IA64_KR_CURRENT_STACK
ld8 r20=[temp2],16 // prev_task
@@ -848,7 +848,7 @@ ia64_state_restore:
mov cr.iim=temp3
mov cr.iha=temp4
dep r22=0,r22,62,1 // pal_min_state, physical, uncached
- mov IA64_KR(CURRENT)=r21
+ mov IA64_KR(CURRENT)=r13
ld8 r8=[temp1] // os_status
ld8 r10=[temp2] // context
@@ -856,7 +856,7 @@ ia64_state_restore:
* avoid any dependencies on the algorithm in ia64_switch_to(), just
* purge any existing CURRENT_STACK mapping and insert the new one.
*
- * r16 contains prev_IA64_KR_CURRENT_STACK, r21 contains
+ * r16 contains prev_IA64_KR_CURRENT_STACK, r13 contains
* prev_IA64_KR_CURRENT, these values may have been changed by the C
* code. Do not use r8, r9, r10, r22, they contain values ready for
* the return to SAL.
@@ -873,7 +873,7 @@ ia64_state_restore:
;;
srlz.d
- extr.u r19=r21,61,3 // r21 = prev_IA64_KR_CURRENT
+ extr.u r19=r13,61,3 // r13 = prev_IA64_KR_CURRENT
shl r20=r16,IA64_GRANULE_SHIFT // r16 = prev_IA64_KR_CURRENT_STACK
movl r21=PAGE_KERNEL // page properties
;;
@@ -883,7 +883,7 @@ ia64_state_restore:
(p6) br.spnt 1f // the dreaded cpu 0 idle task in region 5:(
;;
mov cr.itir=r18
- mov cr.ifa=r21
+ mov cr.ifa=r13
mov r20=IA64_TR_CURRENT_STACK
;;
itr.d dtr[r20]=r21
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index 37c88eb5587..ca6666b51cc 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -62,6 +62,11 @@ typedef enum {
ISOLATE_NONE
} isolate_status_t;
+typedef enum {
+ MCA_NOT_RECOVERED = 0,
+ MCA_RECOVERED = 1
+} recovery_status_t;
+
/*
* This pool keeps pointers to the section part of SAL error record
*/
@@ -71,6 +76,18 @@ static struct {
int max_idx; /* Maximum index of section pointer list pool */
} slidx_pool;
+static int
+fatal_mca(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vprintk(fmt, args);
+ va_end(args);
+
+ return MCA_NOT_RECOVERED;
+}
+
/**
* mca_page_isolate - isolate a poisoned page in order not to use it later
* @paddr: poisoned memory location
@@ -424,7 +441,7 @@ recover_from_read_error(slidx_table_t *slidx,
/* Is target address valid? */
if (!pbci->tv)
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: target address not valid\n");
/*
* cpu read or memory-mapped io read
@@ -442,7 +459,7 @@ recover_from_read_error(slidx_table_t *slidx,
/* Is minstate valid? */
if (!peidx_bottom(peidx) || !(peidx_bottom(peidx)->valid.minstate))
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: minstate not valid\n");
psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr);
psr2 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_xpsr);
@@ -476,12 +493,13 @@ recover_from_read_error(slidx_table_t *slidx,
psr2->bn = 1;
psr2->i = 0;
- return 1;
+ return MCA_RECOVERED;
}
}
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: kernel context not recovered,"
+ " iip 0x%lx\n", pmsa->pmsa_iip);
}
/**
@@ -567,13 +585,13 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
* The machine check is corrected.
*/
if (psp->cm == 1)
- return 1;
+ return MCA_RECOVERED;
/*
* The error was not contained. Software must be reset.
*/
if (psp->us || psp->ci == 0)
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: error not contained\n");
/*
* The cache check and bus check bits have four possible states
@@ -584,20 +602,22 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
* 1 1 Memory error, attempt recovery
*/
if (psp->bc == 0 || pbci == NULL)
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: No bus check\n");
/*
* Sorry, we cannot handle so many.
*/
if (peidx_bus_check_num(peidx) > 1)
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: Too many bus checks\n");
/*
* Well, here is only one bus error.
*/
- if (pbci->ib || pbci->cc)
- return 0;
+ if (pbci->ib)
+ return fatal_mca(KERN_ALERT "MCA: Internal Bus error\n");
+ if (pbci->cc)
+ return fatal_mca(KERN_ALERT "MCA: Cache-cache error\n");
if (pbci->eb && pbci->bsi > 0)
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: External bus check fatal status\n");
/*
* This is a local MCA and estimated as recoverble external bus error.
@@ -609,7 +629,7 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
/*
* On account of strange SAL error record, we cannot recover.
*/
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: Strange SAL record\n");
}
/**
@@ -638,12 +658,10 @@ mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
/* Now, OS can recover when there is one processor error section */
if (n_proc_err > 1)
- return 0;
- else if (n_proc_err == 0) {
+ return fatal_mca(KERN_ALERT "MCA: Too Many Errors\n");
+ else if (n_proc_err == 0)
/* Weird SAL record ... We need not to recover */
-
- return 1;
- }
+ return fatal_mca(KERN_ALERT "MCA: Weird SAL record\n");
/* Make index of processor error section */
mca_make_peidx((sal_log_processor_info_t*)
@@ -654,7 +672,7 @@ mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
/* Check whether MCA is global or not */
if (is_mca_global(&peidx, &pbci, sos))
- return 0;
+ return fatal_mca(KERN_ALERT "MCA: global MCA\n");
/* Try to recover a processor error */
return recover_from_processor_error(platform_err, &slidx, &peidx,
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index 7a2f0a798d1..3a30cfc9574 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -947,7 +947,7 @@ void
percpu_modcopy (void *pcpudst, const void *src, unsigned long size)
{
unsigned int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
memcpy(pcpudst + __per_cpu_offset[i], src, size);
}
}
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 89faa603c6b..859fb37ff49 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -240,7 +240,7 @@ cache_info(char *page)
}
p += sprintf(p,
"%s Cache level %lu:\n"
- "\tSize : %lu bytes\n"
+ "\tSize : %u bytes\n"
"\tAttributes : ",
cache_types[j+cci.pcci_unified], i+1,
cci.pcci_cache_size);
@@ -648,9 +648,9 @@ frequency_info(char *page)
if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0;
p += sprintf(p,
- "Processor/Clock ratio : %ld/%ld\n"
- "Bus/Clock ratio : %ld/%ld\n"
- "ITC/Clock ratio : %ld/%ld\n",
+ "Processor/Clock ratio : %d/%d\n"
+ "Bus/Clock ratio : %d/%d\n"
+ "ITC/Clock ratio : %d/%d\n",
proc.num, proc.den, bus.num, bus.den, itc.num, itc.den);
return p - page;
@@ -959,7 +959,7 @@ remove_palinfo_proc_entries(unsigned int hcpu)
}
}
-static int __devinit palinfo_cpu_callback(struct notifier_block *nfb,
+static int palinfo_cpu_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
{
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 9887c8787e7..e61e15e28d8 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -1644,7 +1644,7 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3,
arch = AUDIT_ARCH_IA64;
}
- audit_syscall_entry(current, arch, syscall, arg0, arg1, arg2, arg3);
+ audit_syscall_entry(arch, syscall, arg0, arg1, arg2, arg3);
}
}
@@ -1662,7 +1662,7 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
if (success != AUDITSC_SUCCESS)
result = -result;
- audit_syscall_exit(current, success, result);
+ audit_syscall_exit(success, result);
}
if (test_thread_flag(TIF_SYSCALL_TRACE)
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index 9d5a823479a..663a186ad19 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -572,7 +572,7 @@ static struct file_operations salinfo_data_fops = {
};
#ifdef CONFIG_HOTPLUG_CPU
-static int __devinit
+static int
salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
{
unsigned int i, cpu = (unsigned long)hcpu;
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index ac167436e93..49958904045 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -188,7 +188,7 @@ ia64_init_itm (void)
itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den;
local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ;
- printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, "
+ printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%u/%u, "
"ITC freq=%lu.%03luMHz", smp_processor_id(),
platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000,
itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000);
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index 3b6fd798c4d..4f3a16b37f8 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -9,6 +9,8 @@
* 2002/08/07 Erich Focht <efocht@ess.nec.de>
* Populate cpu entries in sysfs for non-numa systems as well
* Intel Corporation - Ashok Raj
+ * 02/27/2006 Zhang, Yanmin
+ * Populate cpu cache entries in sysfs for cpu cache info
*/
#include <linux/config.h>
@@ -19,6 +21,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/nodemask.h>
+#include <linux/notifier.h>
#include <asm/mmzone.h>
#include <asm/numa.h>
#include <asm/cpu.h>
@@ -101,3 +104,364 @@ out:
}
subsys_initcall(topology_init);
+
+
+/*
+ * Export cpu cache information through sysfs
+ */
+
+/*
+ * A bunch of string array to get pretty printing
+ */
+static const char *cache_types[] = {
+ "", /* not used */
+ "Instruction",
+ "Data",
+ "Unified" /* unified */
+};
+
+static const char *cache_mattrib[]={
+ "WriteThrough",
+ "WriteBack",
+ "", /* reserved */
+ "" /* reserved */
+};
+
+struct cache_info {
+ pal_cache_config_info_t cci;
+ cpumask_t shared_cpu_map;
+ int level;
+ int type;
+ struct kobject kobj;
+};
+
+struct cpu_cache_info {
+ struct cache_info *cache_leaves;
+ int num_cache_leaves;
+ struct kobject kobj;
+};
+
+static struct cpu_cache_info all_cpu_cache_info[NR_CPUS];
+#define LEAF_KOBJECT_PTR(x,y) (&all_cpu_cache_info[x].cache_leaves[y])
+
+#ifdef CONFIG_SMP
+static void cache_shared_cpu_map_setup( unsigned int cpu,
+ struct cache_info * this_leaf)
+{
+ pal_cache_shared_info_t csi;
+ int num_shared, i = 0;
+ unsigned int j;
+
+ if (cpu_data(cpu)->threads_per_core <= 1 &&
+ cpu_data(cpu)->cores_per_socket <= 1) {
+ cpu_set(cpu, this_leaf->shared_cpu_map);
+ return;
+ }
+
+ if (ia64_pal_cache_shared_info(this_leaf->level,
+ this_leaf->type,
+ 0,
+ &csi) != PAL_STATUS_SUCCESS)
+ return;
+
+ num_shared = (int) csi.num_shared;
+ do {
+ for_each_cpu(j)
+ if (cpu_data(cpu)->socket_id == cpu_data(j)->socket_id
+ && cpu_data(j)->core_id == csi.log1_cid
+ && cpu_data(j)->thread_id == csi.log1_tid)
+ cpu_set(j, this_leaf->shared_cpu_map);
+
+ i++;
+ } while (i < num_shared &&
+ ia64_pal_cache_shared_info(this_leaf->level,
+ this_leaf->type,
+ i,
+ &csi) == PAL_STATUS_SUCCESS);
+}
+#else
+static void cache_shared_cpu_map_setup(unsigned int cpu,
+ struct cache_info * this_leaf)
+{
+ cpu_set(cpu, this_leaf->shared_cpu_map);
+ return;
+}
+#endif
+
+static ssize_t show_coherency_line_size(struct cache_info *this_leaf,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", 1 << this_leaf->cci.pcci_line_size);
+}
+
+static ssize_t show_ways_of_associativity(struct cache_info *this_leaf,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", this_leaf->cci.pcci_assoc);
+}
+
+static ssize_t show_attributes(struct cache_info *this_leaf, char *buf)
+{
+ return sprintf(buf,
+ "%s\n",
+ cache_mattrib[this_leaf->cci.pcci_cache_attr]);
+}
+
+static ssize_t show_size(struct cache_info *this_leaf, char *buf)
+{
+ return sprintf(buf, "%uK\n", this_leaf->cci.pcci_cache_size / 1024);
+}
+
+static ssize_t show_number_of_sets(struct cache_info *this_leaf, char *buf)
+{
+ unsigned number_of_sets = this_leaf->cci.pcci_cache_size;
+ number_of_sets /= this_leaf->cci.pcci_assoc;
+ number_of_sets /= 1 << this_leaf->cci.pcci_line_size;
+
+ return sprintf(buf, "%u\n", number_of_sets);
+}
+
+static ssize_t show_shared_cpu_map(struct cache_info *this_leaf, char *buf)
+{
+ ssize_t len;
+ cpumask_t shared_cpu_map;
+
+ cpus_and(shared_cpu_map, this_leaf->shared_cpu_map, cpu_online_map);
+ len = cpumask_scnprintf(buf, NR_CPUS+1, shared_cpu_map);
+ len += sprintf(buf+len, "\n");
+ return len;
+}
+
+static ssize_t show_type(struct cache_info *this_leaf, char *buf)
+{
+ int type = this_leaf->type + this_leaf->cci.pcci_unified;
+ return sprintf(buf, "%s\n", cache_types[type]);
+}
+
+static ssize_t show_level(struct cache_info *this_leaf, char *buf)
+{
+ return sprintf(buf, "%u\n", this_leaf->level);
+}
+
+struct cache_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct cache_info *, char *);
+ ssize_t (*store)(struct cache_info *, const char *, size_t count);
+};
+
+#ifdef define_one_ro
+ #undef define_one_ro
+#endif
+#define define_one_ro(_name) \
+ static struct cache_attr _name = \
+__ATTR(_name, 0444, show_##_name, NULL)
+
+define_one_ro(level);
+define_one_ro(type);
+define_one_ro(coherency_line_size);
+define_one_ro(ways_of_associativity);
+define_one_ro(size);
+define_one_ro(number_of_sets);
+define_one_ro(shared_cpu_map);
+define_one_ro(attributes);
+
+static struct attribute * cache_default_attrs[] = {
+ &type.attr,
+ &level.attr,
+ &coherency_line_size.attr,
+ &ways_of_associativity.attr,
+ &attributes.attr,
+ &size.attr,
+ &number_of_sets.attr,
+ &shared_cpu_map.attr,
+ NULL
+};
+
+#define to_object(k) container_of(k, struct cache_info, kobj)
+#define to_attr(a) container_of(a, struct cache_attr, attr)
+
+static ssize_t cache_show(struct kobject * kobj, struct attribute * attr, char * buf)
+{
+ struct cache_attr *fattr = to_attr(attr);
+ struct cache_info *this_leaf = to_object(kobj);
+ ssize_t ret;
+
+ ret = fattr->show ? fattr->show(this_leaf, buf) : 0;
+ return ret;
+}
+
+static struct sysfs_ops cache_sysfs_ops = {
+ .show = cache_show
+};
+
+static struct kobj_type cache_ktype = {
+ .sysfs_ops = &cache_sysfs_ops,
+ .default_attrs = cache_default_attrs,
+};
+
+static struct kobj_type cache_ktype_percpu_entry = {
+ .sysfs_ops = &cache_sysfs_ops,
+};
+
+static void __cpuinit cpu_cache_sysfs_exit(unsigned int cpu)
+{
+ kfree(all_cpu_cache_info[cpu].cache_leaves);
+ all_cpu_cache_info[cpu].cache_leaves = NULL;
+ all_cpu_cache_info[cpu].num_cache_leaves = 0;
+ memset(&all_cpu_cache_info[cpu].kobj, 0, sizeof(struct kobject));
+ return;
+}
+
+static int __cpuinit cpu_cache_sysfs_init(unsigned int cpu)
+{
+ u64 i, levels, unique_caches;
+ pal_cache_config_info_t cci;
+ int j;
+ s64 status;
+ struct cache_info *this_cache;
+ int num_cache_leaves = 0;
+
+ if ((status = ia64_pal_cache_summary(&levels, &unique_caches)) != 0) {
+ printk(KERN_ERR "ia64_pal_cache_summary=%ld\n", status);
+ return -1;
+ }
+
+ this_cache=kzalloc(sizeof(struct cache_info)*unique_caches,
+ GFP_KERNEL);
+ if (this_cache == NULL)
+ return -ENOMEM;
+
+ for (i=0; i < levels; i++) {
+ for (j=2; j >0 ; j--) {
+ if ((status=ia64_pal_cache_config_info(i,j, &cci)) !=
+ PAL_STATUS_SUCCESS)
+ continue;
+
+ this_cache[num_cache_leaves].cci = cci;
+ this_cache[num_cache_leaves].level = i + 1;
+ this_cache[num_cache_leaves].type = j;
+
+ cache_shared_cpu_map_setup(cpu,
+ &this_cache[num_cache_leaves]);
+ num_cache_leaves ++;
+ }
+ }
+
+ all_cpu_cache_info[cpu].cache_leaves = this_cache;
+ all_cpu_cache_info[cpu].num_cache_leaves = num_cache_leaves;
+
+ memset(&all_cpu_cache_info[cpu].kobj, 0, sizeof(struct kobject));
+
+ return 0;
+}
+
+/* Add cache interface for CPU device */
+static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
+{
+ unsigned int cpu = sys_dev->id;
+ unsigned long i, j;
+ struct cache_info *this_object;
+ int retval = 0;
+ cpumask_t oldmask;
+
+ if (all_cpu_cache_info[cpu].kobj.parent)
+ return 0;
+
+ oldmask = current->cpus_allowed;
+ retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ if (unlikely(retval))
+ return retval;
+
+ retval = cpu_cache_sysfs_init(cpu);
+ set_cpus_allowed(current, oldmask);
+ if (unlikely(retval < 0))
+ return retval;
+
+ all_cpu_cache_info[cpu].kobj.parent = &sys_dev->kobj;
+ kobject_set_name(&all_cpu_cache_info[cpu].kobj, "%s", "cache");
+ all_cpu_cache_info[cpu].kobj.ktype = &cache_ktype_percpu_entry;
+ retval = kobject_register(&all_cpu_cache_info[cpu].kobj);
+
+ for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++) {
+ this_object = LEAF_KOBJECT_PTR(cpu,i);
+ this_object->kobj.parent = &all_cpu_cache_info[cpu].kobj;
+ kobject_set_name(&(this_object->kobj), "index%1lu", i);
+ this_object->kobj.ktype = &cache_ktype;
+ retval = kobject_register(&(this_object->kobj));
+ if (unlikely(retval)) {
+ for (j = 0; j < i; j++) {
+ kobject_unregister(
+ &(LEAF_KOBJECT_PTR(cpu,j)->kobj));
+ }
+ kobject_unregister(&all_cpu_cache_info[cpu].kobj);
+ cpu_cache_sysfs_exit(cpu);
+ break;
+ }
+ }
+ return retval;
+}
+
+/* Remove cache interface for CPU device */
+static int __cpuinit cache_remove_dev(struct sys_device * sys_dev)
+{
+ unsigned int cpu = sys_dev->id;
+ unsigned long i;
+
+ for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++)
+ kobject_unregister(&(LEAF_KOBJECT_PTR(cpu,i)->kobj));
+
+ if (all_cpu_cache_info[cpu].kobj.parent) {
+ kobject_unregister(&all_cpu_cache_info[cpu].kobj);
+ memset(&all_cpu_cache_info[cpu].kobj,
+ 0,
+ sizeof(struct kobject));
+ }
+
+ cpu_cache_sysfs_exit(cpu);
+
+ return 0;
+}
+
+/*
+ * When a cpu is hot-plugged, do a check and initiate
+ * cache kobject if necessary
+ */
+static int cache_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+ struct sys_device *sys_dev;
+
+ sys_dev = get_cpu_sysdev(cpu);
+ switch (action) {
+ case CPU_ONLINE:
+ cache_add_dev(sys_dev);
+ break;
+ case CPU_DEAD:
+ cache_remove_dev(sys_dev);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block cache_cpu_notifier =
+{
+ .notifier_call = cache_cpu_callback
+};
+
+static int __cpuinit cache_sysfs_init(void)
+{
+ int i;
+
+ for_each_online_cpu(i) {
+ cache_cpu_callback(&cache_cpu_notifier, CPU_ONLINE,
+ (void *)(long)i);
+ }
+
+ register_cpu_notifier(&cache_cpu_notifier);
+
+ return 0;
+}
+
+device_initcall(cache_sysfs_init);
+
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index dabd6c32641..7c1ddc8ac44 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -30,19 +30,19 @@ extern spinlock_t timerlist_lock;
fpswa_interface_t *fpswa_interface;
EXPORT_SYMBOL(fpswa_interface);
-struct notifier_block *ia64die_chain;
+ATOMIC_NOTIFIER_HEAD(ia64die_chain);
int
register_die_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&ia64die_chain, nb);
+ return atomic_notifier_chain_register(&ia64die_chain, nb);
}
EXPORT_SYMBOL_GPL(register_die_notifier);
int
unregister_die_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&ia64die_chain, nb);
+ return atomic_notifier_chain_unregister(&ia64die_chain, nb);
}
EXPORT_SYMBOL_GPL(unregister_die_notifier);
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 0b9e56dd7f0..783600fe52b 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -70,6 +70,15 @@ SECTIONS
__stop___ex_table = .;
}
+ /* MCA table */
+ . = ALIGN(16);
+ __mca_table : AT(ADDR(__mca_table) - LOAD_OFFSET)
+ {
+ __start___mca_table = .;
+ *(__mca_table)
+ __stop___mca_table = .;
+ }
+
/* Global data */
_data = .;
@@ -130,15 +139,6 @@ SECTIONS
__initcall_end = .;
}
- /* MCA table */
- . = ALIGN(16);
- __mca_table : AT(ADDR(__mca_table) - LOAD_OFFSET)
- {
- __start___mca_table = .;
- *(__mca_table)
- __stop___mca_table = .;
- }
-
.data.patch.vtop : AT(ADDR(.data.patch.vtop) - LOAD_OFFSET)
{
__start___vtop_patchlist = .;
diff --git a/arch/ia64/lib/memcpy_mck.S b/arch/ia64/lib/memcpy_mck.S
index 46c9331e7ab..9e534d52b1d 100644
--- a/arch/ia64/lib/memcpy_mck.S
+++ b/arch/ia64/lib/memcpy_mck.S
@@ -6,7 +6,9 @@
* in1: source address
* in2: number of bytes to copy
* Output:
- * 0 if success, or number of byte NOT copied if error occurred.
+ * for memcpy: return dest
+ * for copy_user: return 0 if success,
+ * or number of byte NOT copied if error occurred.
*
* Copyright (C) 2002 Intel Corp.
* Copyright (C) 2002 Ken Chen <kenneth.w.chen@intel.com>
@@ -73,6 +75,7 @@ GLOBAL_ENTRY(memcpy)
and r28=0x7,in0
and r29=0x7,in1
mov f6=f0
+ mov retval=in0
br.cond.sptk .common_code
;;
END(memcpy)
@@ -84,7 +87,7 @@ GLOBAL_ENTRY(__copy_user)
mov f6=f1
mov saved_in0=in0 // save dest pointer
mov saved_in1=in1 // save src pointer
- mov saved_in2=in2 // save len
+ mov retval=r0 // initialize return value
;;
.common_code:
cmp.gt p15,p0=8,in2 // check for small size
@@ -92,7 +95,7 @@ GLOBAL_ENTRY(__copy_user)
cmp.ne p14,p0=0,r29 // check src alignment
add src0=0,in1
sub r30=8,r28 // for .align_dest
- mov retval=r0 // initialize return value
+ mov saved_in2=in2 // save len
;;
add dst0=0,in0
add dst1=1,in0 // dest odd index
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 2f5e44862e9..b6bcc9fa360 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -379,31 +379,6 @@ static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize)
}
/**
- * pgdat_insert - insert the pgdat into global pgdat_list
- * @pgdat: the pgdat for a node.
- */
-static void __init pgdat_insert(pg_data_t *pgdat)
-{
- pg_data_t *prev = NULL, *next;
-
- for_each_pgdat(next)
- if (pgdat->node_id < next->node_id)
- break;
- else
- prev = next;
-
- if (prev) {
- prev->pgdat_next = pgdat;
- pgdat->pgdat_next = next;
- } else {
- pgdat->pgdat_next = pgdat_list;
- pgdat_list = pgdat;
- }
-
- return;
-}
-
-/**
* memory_less_nodes - allocate and initialize CPU only nodes pernode
* information.
*/
@@ -544,6 +519,68 @@ void __cpuinit *per_cpu_init(void)
}
#endif /* CONFIG_SMP */
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i)
+{
+ unsigned long end_address, hole_next_pfn;
+ unsigned long stop_address;
+
+ end_address = (unsigned long) &vmem_map[pgdat->node_start_pfn + i];
+ end_address = PAGE_ALIGN(end_address);
+
+ stop_address = (unsigned long) &vmem_map[
+ pgdat->node_start_pfn + pgdat->node_spanned_pages];
+
+ do {
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ pgd = pgd_offset_k(end_address);
+ if (pgd_none(*pgd)) {
+ end_address += PGDIR_SIZE;
+ continue;
+ }
+
+ pud = pud_offset(pgd, end_address);
+ if (pud_none(*pud)) {
+ end_address += PUD_SIZE;
+ continue;
+ }
+
+ pmd = pmd_offset(pud, end_address);
+ if (pmd_none(*pmd)) {
+ end_address += PMD_SIZE;
+ continue;
+ }
+
+ pte = pte_offset_kernel(pmd, end_address);
+retry_pte:
+ if (pte_none(*pte)) {
+ end_address += PAGE_SIZE;
+ pte++;
+ if ((end_address < stop_address) &&
+ (end_address != ALIGN(end_address, 1UL << PMD_SHIFT)))
+ goto retry_pte;
+ continue;
+ }
+ /* Found next valid vmem_map page */
+ break;
+ } while (end_address < stop_address);
+
+ end_address = min(end_address, stop_address);
+ end_address = end_address - (unsigned long) vmem_map + sizeof(struct page) - 1;
+ hole_next_pfn = end_address / sizeof(struct page);
+ return hole_next_pfn - pgdat->node_start_pfn;
+}
+#else
+static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i)
+{
+ return i + 1;
+}
+#endif
+
/**
* show_mem - give short summary of memory stats
*
@@ -560,7 +597,7 @@ void show_mem(void)
printk("Mem-info:\n");
show_free_areas();
printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
unsigned long present;
unsigned long flags;
int shared = 0, cached = 0, reserved = 0;
@@ -572,8 +609,10 @@ void show_mem(void)
struct page *page;
if (pfn_valid(pgdat->node_start_pfn + i))
page = pfn_to_page(pgdat->node_start_pfn + i);
- else
+ else {
+ i = find_next_valid_pfn_for_pgdat(pgdat, i) - 1;
continue;
+ }
if (PageReserved(page))
reserved++;
else if (PageSwapCache(page))
@@ -745,11 +784,5 @@ void __init paging_init(void)
pfn_offset, zholes_size);
}
- /*
- * Make memory less nodes become a member of the known nodes.
- */
- for_each_node_mask(node, memory_less_mask)
- pgdat_insert(mem_data[node].pgdat);
-
zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
}
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index af7eb087dca..d98ec49570b 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -60,6 +60,9 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
struct siginfo si;
unsigned long mask;
+ /* mmap_sem is performance critical.... */
+ prefetchw(&mm->mmap_sem);
+
/*
* If we're in an interrupt or have no user context, we must not take the fault..
*/
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index ff4f31fcd33..cafa8776a53 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -109,6 +109,7 @@ lazy_mmu_prot_update (pte_t pte)
{
unsigned long addr;
struct page *page;
+ unsigned long order;
if (!pte_exec(pte))
return; /* not an executable page... */
@@ -119,7 +120,12 @@ lazy_mmu_prot_update (pte_t pte)
if (test_bit(PG_arch_1, &page->flags))
return; /* i-cache is already coherent with d-cache */
- flush_icache_range(addr, addr + PAGE_SIZE);
+ if (PageCompound(page)) {
+ order = (unsigned long) (page[1].lru.prev);
+ flush_icache_range(addr, addr + (1UL << order << PAGE_SHIFT));
+ }
+ else
+ flush_icache_range(addr, addr + PAGE_SIZE);
set_bit(PG_arch_1, &page->flags); /* mark page as clean */
}
@@ -600,7 +606,7 @@ mem_init (void)
kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START);
kclist_add(&kcore_kernel, _stext, _end - _stext);
- for_each_pgdat(pgdat)
+ for_each_online_pgdat(pgdat)
if (pgdat->bdata->node_bootmem_map)
totalram_pages += free_all_bootmem_node(pgdat);
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
index 62328621f99..643ccc6960c 100644
--- a/arch/ia64/mm/ioremap.c
+++ b/arch/ia64/mm/ioremap.c
@@ -21,12 +21,12 @@ __ioremap (unsigned long offset, unsigned long size)
void __iomem *
ioremap (unsigned long offset, unsigned long size)
{
- if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC))
- return __ioremap(offset, size);
-
if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB))
return phys_to_virt(offset);
+ if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC))
+ return __ioremap(offset, size);
+
/*
* Someday this should check ACPI resources so we
* can do the right thing for hot-plugged regions.
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index 6a4eec9113e..4dbbca0b5e9 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -156,17 +156,19 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start,
nbits = purge.max_bits;
start &= ~((1UL << nbits) - 1);
-# ifdef CONFIG_SMP
- platform_global_tlb_purge(mm, start, end, nbits);
-# else
preempt_disable();
+#ifdef CONFIG_SMP
+ if (mm != current->active_mm || cpus_weight(mm->cpu_vm_mask) != 1) {
+ platform_global_tlb_purge(mm, start, end, nbits);
+ preempt_enable();
+ return;
+ }
+#endif
do {
ia64_ptcl(start, (nbits<<2));
start += (1UL << nbits);
} while (start < end);
preempt_enable();
-# endif
-
ia64_srlz_i(); /* srlz.i implies srlz.d */
}
EXPORT_SYMBOL(flush_tlb_range);
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 9ba32b2d96d..ab829a22f8a 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -31,7 +31,6 @@
#include <asm/irq.h>
#include <asm/hw_irq.h>
-
/*
* Low-level SAL-based PCI configuration access functions. Note that SAL
* calls are already serialized (via sal_lock), so we don't need another
@@ -707,7 +706,7 @@ int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
*
* Simply writes @size bytes of @val to @port.
*/
-int ia64_pci_legacy_write(struct pci_dev *bus, u16 port, u32 val, u8 size)
+int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
{
int ret = size;
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 70db21f3df2..739c948dc50 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -110,7 +110,11 @@ static int sn_hwperf_geoid_to_cnode(char *location)
if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab))
return -1;
- for_each_node(cnode) {
+ /*
+ * FIXME: replace with cleaner for_each_XXX macro which addresses
+ * both compute and IO nodes once ACPI3.0 is available.
+ */
+ for (cnode = 0; cnode < num_cnodes; cnode++) {
geoid = cnodeid_get_geoid(cnode);
module_id = geo_module(geoid);
this_rack = MODULE_GET_RACK(module_id);
@@ -280,6 +284,8 @@ static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objb
/* find nearest node with cpus and nearest memory */
for (router=NULL, j=0; j < op->ports; j++) {
dest = sn_hwperf_findobj_id(objbuf, nobj, ptdata[j].conn_id);
+ if (dest && SN_HWPERF_IS_ROUTER(dest))
+ router = dest;
if (!dest || SN_HWPERF_FOREIGN(dest) ||
!SN_HWPERF_IS_NODE(dest) || SN_HWPERF_IS_IONODE(dest)) {
continue;
@@ -295,8 +301,6 @@ static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objb
*near_mem_node = c;
found_mem++;
}
- if (SN_HWPERF_IS_ROUTER(dest))
- router = dest;
}
if (router && (!found_cpu || !found_mem)) {
@@ -489,7 +493,7 @@ static int sn_topology_show(struct seq_file *s, void *d)
* numalink ports
*/
sz = obj->ports * sizeof(struct sn_hwperf_port_info);
- if ((ptdata = vmalloc(sz)) == NULL)
+ if ((ptdata = kmalloc(sz, GFP_KERNEL)) == NULL)
return -ENOMEM;
e = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
SN_HWPERF_ENUM_PORTS, obj->id, sz,
@@ -537,7 +541,7 @@ static int sn_topology_show(struct seq_file *s, void *d)
(SN_HWPERF_IS_NL3ROUTER(obj) ||
SN_HWPERF_IS_NL3ROUTER(p)) ? "LLP3" : "LLP4");
}
- vfree(ptdata);
+ kfree(ptdata);
}
return 0;
@@ -605,7 +609,7 @@ static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info)
op_info->a->arg &= SN_HWPERF_ARG_OBJID_MASK;
if (cpu != SN_HWPERF_ARG_ANY_CPU) {
- if (cpu >= num_online_cpus() || !cpu_online(cpu)) {
+ if (cpu >= NR_CPUS || !cpu_online(cpu)) {
r = -EINVAL;
goto out;
}
diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
index c686d9c12f7..5100261310f 100644
--- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
@@ -93,19 +93,22 @@ static int coherence_id_open(struct inode *inode, struct file *file)
static struct proc_dir_entry
*sn_procfs_create_entry(const char *name, struct proc_dir_entry *parent,
int (*openfunc)(struct inode *, struct file *),
- int (*releasefunc)(struct inode *, struct file *))
+ int (*releasefunc)(struct inode *, struct file *),
+ ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *))
{
struct proc_dir_entry *e = create_proc_entry(name, 0444, parent);
if (e) {
- e->proc_fops = (struct file_operations *)kmalloc(
- sizeof(struct file_operations), GFP_KERNEL);
- if (e->proc_fops) {
- memset(e->proc_fops, 0, sizeof(struct file_operations));
- e->proc_fops->open = openfunc;
- e->proc_fops->read = seq_read;
- e->proc_fops->llseek = seq_lseek;
- e->proc_fops->release = releasefunc;
+ struct file_operations *f;
+
+ f = kzalloc(sizeof(*f), GFP_KERNEL);
+ if (f) {
+ f->open = openfunc;
+ f->read = seq_read;
+ f->llseek = seq_lseek;
+ f->release = releasefunc;
+ f->write = write;
+ e->proc_fops = f;
}
}
@@ -119,31 +122,29 @@ extern int sn_topology_release(struct inode *, struct file *);
void register_sn_procfs(void)
{
static struct proc_dir_entry *sgi_proc_dir = NULL;
- struct proc_dir_entry *e;
BUG_ON(sgi_proc_dir != NULL);
if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL)))
return;
sn_procfs_create_entry("partition_id", sgi_proc_dir,
- partition_id_open, single_release);
+ partition_id_open, single_release, NULL);
sn_procfs_create_entry("system_serial_number", sgi_proc_dir,
- system_serial_number_open, single_release);
+ system_serial_number_open, single_release, NULL);
sn_procfs_create_entry("licenseID", sgi_proc_dir,
- licenseID_open, single_release);
+ licenseID_open, single_release, NULL);
- e = sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir,
- sn_force_interrupt_open, single_release);
- if (e)
- e->proc_fops->write = sn_force_interrupt_write_proc;
+ sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir,
+ sn_force_interrupt_open, single_release,
+ sn_force_interrupt_write_proc);
sn_procfs_create_entry("coherence_id", sgi_proc_dir,
- coherence_id_open, single_release);
+ coherence_id_open, single_release, NULL);
sn_procfs_create_entry("sn_topology", sgi_proc_dir,
- sn_topology_open, sn_topology_release);
+ sn_topology_open, sn_topology_release, NULL);
}
#endif /* CONFIG_PROC_FS */
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index d0abddd9ffe..8255a9be463 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -1831,7 +1831,7 @@ xpc_initiate_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
{
struct xpc_partition *part = &xpc_partitions[partid];
enum xpc_retval ret = xpcUnknownReason;
- struct xpc_msg *msg;
+ struct xpc_msg *msg = NULL;
DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
index 94211429fd0..2a89cfce495 100644
--- a/arch/ia64/sn/kernel/xpc_partition.c
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -136,9 +136,7 @@ xpc_get_rsvd_page_pa(int nasid)
}
if (L1_CACHE_ALIGN(len) > buf_len) {
- if (buf_base != NULL) {
- kfree(buf_base);
- }
+ kfree(buf_base);
buf_len = L1_CACHE_ALIGN(len);
buf = (u64) xpc_kmalloc_cacheline_aligned(buf_len,
GFP_KERNEL, &buf_base);
@@ -159,9 +157,7 @@ xpc_get_rsvd_page_pa(int nasid)
}
}
- if (buf_base != NULL) {
- kfree(buf_base);
- }
+ kfree(buf_base);
if (status != SALRET_OK) {
rp_pa = 0;
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index fa073cc4b56..833295624e5 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -682,9 +682,6 @@ tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit)
int ate_index, last_ate, ps;
struct tioce *ce_mmr;
- if (!TIOCE_M32_ADDR(base))
- return;
-
ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base;
ps = ce_kern->ce_ate3240_pagesize;
ate_index = ATE_PAGE(base, ps);
@@ -693,6 +690,9 @@ tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit)
if (ate_index < 64)
ate_index = 64;
+ if (last_ate >= TIOCE_NUM_M3240_ATES)
+ last_ate = TIOCE_NUM_M3240_ATES - 1;
+
while (ate_index <= last_ate) {
u64 ate;
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 05c864c6c2d..41fd490af3b 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -285,6 +285,11 @@ config NUMA
depends on SMP && BROKEN
default n
+config NODES_SHIFT
+ int
+ default "1"
+ depends on NEED_MULTIPLE_NODES
+
# turning this on wastes a bunch of space.
# Summit needs it only when NUMA is on
config BOOT_IOREMAP
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index 3871b65f0c8..920bb742b7a 100644
--- a/arch/m32r/kernel/entry.S
+++ b/arch/m32r/kernel/entry.S
@@ -20,7 +20,7 @@
* Stack layout in 'ret_from_system_call':
* ptrace needs to have all regs on the stack.
* if the order here is changed, it needs to be
- * updated in fork.c:copy_process, signal.c:do_signal,
+ * updated in fork.c:copy_thread, signal.c:do_signal,
* ptrace.c and ptrace.h
*
* M32Rx/M32R2 M32R
@@ -41,18 +41,17 @@
* @(0x38,sp) - syscall_nr ditto
* @(0x3c,sp) - acc0h @(0x3c,sp) - acch
* @(0x40,sp) - acc0l @(0x40,sp) - accl
- * @(0x44,sp) - acc1h @(0x44,sp) - psw
- * @(0x48,sp) - acc1l @(0x48,sp) - bpc
- * @(0x4c,sp) - psw @(0x4c,sp) - bbpsw
- * @(0x50,sp) - bpc @(0x50,sp) - bbpc
- * @(0x54,sp) - bbpsw @(0x54,sp) - spu (cr3)
- * @(0x58,sp) - bbpc @(0x58,sp) - fp (r13)
- * @(0x5c,sp) - spu (cr3) @(0x5c,sp) - lr (r14)
- * @(0x60,sp) - fp (r13) @(0x60,sp) - spi (cr12)
- * @(0x64,sp) - lr (r14) @(0x64,sp) - orig_r0
- * @(0x68,sp) - spi (cr2)
- * @(0x6c,sp) - orig_r0
- *
+ * @(0x44,sp) - acc1h @(0x44,sp) - dummy_acc1h
+ * @(0x48,sp) - acc1l @(0x48,sp) - dummy_acc1l
+ * @(0x4c,sp) - psw ditto
+ * @(0x50,sp) - bpc ditto
+ * @(0x54,sp) - bbpsw ditto
+ * @(0x58,sp) - bbpc ditto
+ * @(0x5c,sp) - spu (cr3) ditto
+ * @(0x60,sp) - fp (r13) ditto
+ * @(0x64,sp) - lr (r14) ditto
+ * @(0x68,sp) - spi (cr2) ditto
+ * @(0x6c,sp) - orig_r0 ditto
*/
#include <linux/config.h>
@@ -102,6 +101,12 @@
#define ACC0L(reg) @(0x40,reg)
#define ACC1H(reg) @(0x44,reg)
#define ACC1L(reg) @(0x48,reg)
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define ACCH(reg) @(0x3C,reg)
+#define ACCL(reg) @(0x40,reg)
+#else
+#error unknown isa configuration
+#endif
#define PSW(reg) @(0x4C,reg)
#define BPC(reg) @(0x50,reg)
#define BBPSW(reg) @(0x54,reg)
@@ -111,21 +116,6 @@
#define LR(reg) @(0x64,reg)
#define SP(reg) @(0x68,reg)
#define ORIG_R0(reg) @(0x6C,reg)
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define ACCH(reg) @(0x3C,reg)
-#define ACCL(reg) @(0x40,reg)
-#define PSW(reg) @(0x44,reg)
-#define BPC(reg) @(0x48,reg)
-#define BBPSW(reg) @(0x4C,reg)
-#define BBPC(reg) @(0x50,reg)
-#define SPU(reg) @(0x54,reg)
-#define FP(reg) @(0x58,reg) /* FP = R13 */
-#define LR(reg) @(0x5C,reg)
-#define SP(reg) @(0x60,reg)
-#define ORIG_R0(reg) @(0x64,reg)
-#else
-#error unknown isa configuration
-#endif
CF_MASK = 0x00000001
TF_MASK = 0x00000100
@@ -142,7 +132,7 @@ VM_MASK = 0x00020000
#endif
ENTRY(ret_from_fork)
- ld r0, @sp+
+ pop r0
bl schedule_tail
GET_THREAD_INFO(r8)
bra syscall_exit
@@ -231,7 +221,7 @@ restore_all:
RESTORE_ALL
# perform work that needs to be done immediately before resumption
- # r9 : frags
+ # r9 : flags
ALIGN
work_pending:
and3 r4, r9, #_TIF_NEED_RESCHED
@@ -320,7 +310,7 @@ ENTRY(ei_handler)
; GET_ICU_STATUS;
seth r0, #shigh(M32R_ICU_ISTS_ADDR)
ld r0, @(low(M32R_ICU_ISTS_ADDR),r0)
- st r0, @-sp
+ push r0
#if defined(CONFIG_SMP)
/*
* If IRQ == 0 --> Nothing to do, Not write IMASK
@@ -557,7 +547,7 @@ check_end:
#endif /* CONFIG_PLAT_M32104UT */
bl do_IRQ
#endif /* CONFIG_SMP */
- ld r14, @sp+
+ pop r14
seth r0, #shigh(M32R_ICU_IMASK_ADDR)
st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
#else
@@ -1015,4 +1005,3 @@ ENTRY(sys_call_table)
.long sys_waitid
syscall_table_size=(.-sys_call_table)
-
diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
index be8b711367e..c50330fa83b 100644
--- a/arch/m32r/kernel/m32r_ksyms.c
+++ b/arch/m32r/kernel/m32r_ksyms.c
@@ -23,9 +23,6 @@ EXPORT_SYMBOL(boot_cpu_data);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(disable_irq_nosync);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(__down);
EXPORT_SYMBOL(__down_interruptible);
@@ -38,13 +35,6 @@ EXPORT_SYMBOL(__udelay);
EXPORT_SYMBOL(__delay);
EXPORT_SYMBOL(__const_udelay);
-EXPORT_SYMBOL(__get_user_1);
-EXPORT_SYMBOL(__get_user_2);
-EXPORT_SYMBOL(__get_user_4);
-
-EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strstr);
-
EXPORT_SYMBOL(strncpy_from_user);
EXPORT_SYMBOL(__strncpy_from_user);
EXPORT_SYMBOL(clear_user);
@@ -59,11 +49,8 @@ extern void *dcache_dummy;
EXPORT_SYMBOL(dcache_dummy);
#endif
EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(cpu_callout_map);
/* Global SMP stuff */
-EXPORT_SYMBOL(synchronize_irq);
EXPORT_SYMBOL(smp_call_function);
/* TLB flushing */
@@ -83,27 +70,11 @@ EXPORT_SYMBOL(__lshrdi3);
EXPORT_SYMBOL(__muldi3);
/* memory and string operations */
-EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(memcpy);
-/* EXPORT_SYMBOL(memcpy_fromio); // not implement yet */
-/* EXPORT_SYMBOL(memcpy_toio); // not implement yet */
EXPORT_SYMBOL(memset);
-/* EXPORT_SYMBOL(memset_io); // not implement yet */
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(copy_page);
EXPORT_SYMBOL(clear_page);
-
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(_inb);
EXPORT_SYMBOL(_inw);
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index 5dfc7ea45cf..065f5e71905 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -116,6 +116,10 @@ void cpu_idle (void)
void machine_restart(char *__unused)
{
+#if defined(CONFIG_PLAT_MAPPI3)
+ outw(1, (unsigned long)PLD_REBOOT);
+#endif
+
printk("Please push reset button!\n");
while (1)
cpu_relax();
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index d742037a7cc..3cd3c2988a4 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -9,6 +9,7 @@
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/stddef.h>
#include <linux/fs.h>
#include <linux/sched.h>
@@ -24,6 +25,7 @@
#include <linux/tty.h>
#include <linux/cpu.h>
#include <linux/nodemask.h>
+#include <linux/pfn.h>
#include <asm/processor.h>
#include <asm/pgtable.h>
@@ -218,8 +220,6 @@ static unsigned long __init setup_memory(void)
extern unsigned long setup_memory(void);
#endif /* CONFIG_DISCONTIGMEM */
-#define M32R_PCC_PCATCR 0x00ef7014 /* will move to m32r.h */
-
void __init setup_arch(char **cmdline_p)
{
ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
@@ -268,15 +268,14 @@ void __init setup_arch(char **cmdline_p)
paging_init();
}
-static struct cpu cpu[NR_CPUS];
+static struct cpu cpu_devices[NR_CPUS];
static int __init topology_init(void)
{
- int cpu_id;
+ int i;
- for (cpu_id = 0; cpu_id < NR_CPUS; cpu_id++)
- if (cpu_possible(cpu_id))
- register_cpu(&cpu[cpu_id], cpu_id, NULL);
+ for_each_present_cpu(i)
+ register_cpu(&cpu_devices[i], i, NULL);
return 0;
}
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index cb33097fefc..6498ee70bb7 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -118,6 +118,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
COPY(acch);
COPY(accl);
+ COPY(dummy_acc1h);
+ COPY(dummy_acc1l);
#else
#error unknown isa configuration
#endif
@@ -203,6 +205,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
COPY(acch);
COPY(accl);
+ COPY(dummy_acc1h);
+ COPY(dummy_acc1l);
#else
#error unknown isa configuration
#endif
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
index d7ec16e7fb2..840b4348bf0 100644
--- a/arch/m32r/kernel/smpboot.c
+++ b/arch/m32r/kernel/smpboot.c
@@ -39,8 +39,10 @@
* Martin J. Bligh : Added support for multi-quad systems
*/
+#include <linux/module.h>
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp_lock.h>
#include <linux/irq.h>
@@ -72,11 +74,15 @@ physid_mask_t phys_cpu_present_map;
/* Bitmask of currently online CPUs */
cpumask_t cpu_online_map;
+EXPORT_SYMBOL(cpu_online_map);
cpumask_t cpu_bootout_map;
cpumask_t cpu_bootin_map;
-cpumask_t cpu_callout_map;
static cpumask_t cpu_callin_map;
+cpumask_t cpu_callout_map;
+EXPORT_SYMBOL(cpu_callout_map);
+cpumask_t cpu_possible_map = CPU_MASK_ALL;
+EXPORT_SYMBOL(cpu_possible_map);
/* Per CPU bogomips and other parameters */
struct cpuinfo_m32r cpu_data[NR_CPUS] __cacheline_aligned;
@@ -110,7 +116,6 @@ static unsigned int calibration_result;
void smp_prepare_boot_cpu(void);
void smp_prepare_cpus(unsigned int);
-static void smp_tune_scheduling(void);
static void init_ipi_lock(void);
static void do_boot_cpu(int);
int __cpu_up(unsigned int);
@@ -177,6 +182,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
for (phys_id = 0 ; phys_id < nr_cpu ; phys_id++)
physid_set(phys_id, phys_cpu_present_map);
+#ifndef CONFIG_HOTPLUG_CPU
+ cpu_present_map = cpu_possible_map;
+#endif
show_mp_info(nr_cpu);
@@ -186,7 +194,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
* Setup boot CPU information
*/
smp_store_cpu_info(0); /* Final full version of the data */
- smp_tune_scheduling();
/*
* If SMP should be disabled, then really disable it!
@@ -230,11 +237,6 @@ smp_done:
Dprintk("Boot done.\n");
}
-static void __init smp_tune_scheduling(void)
-{
- /* Nothing to do. */
-}
-
/*
* init_ipi_lock : Initialize IPI locks.
*/
@@ -629,4 +631,3 @@ static void __init unmap_cpu_to_physid(int cpu_id, int phys_id)
physid_2_cpu[phys_id] = -1;
cpu_2_physid[cpu_id] = -1;
}
-
diff --git a/arch/m32r/lib/Makefile b/arch/m32r/lib/Makefile
index e632d10c7d7..d16b4e40d1a 100644
--- a/arch/m32r/lib/Makefile
+++ b/arch/m32r/lib/Makefile
@@ -2,6 +2,6 @@
# Makefile for M32R-specific library files..
#
-lib-y := checksum.o ashxdi3.o memset.o memcpy.o getuser.o \
- putuser.o delay.o strlen.o usercopy.o csum_partial_copy.o
+lib-y := checksum.o ashxdi3.o memset.o memcpy.o \
+ delay.o strlen.o usercopy.o csum_partial_copy.o
diff --git a/arch/m32r/lib/getuser.S b/arch/m32r/lib/getuser.S
deleted file mode 100644
index 58a0db055c5..00000000000
--- a/arch/m32r/lib/getuser.S
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * __get_user functions.
- *
- * (C) Copyright 2001 Hirokazu Takata
- *
- * These functions have a non-standard call interface
- * to make them more efficient, especially as they
- * return an error value in addition to the "real"
- * return value.
- */
-
-#include <linux/config.h>
-
-/*
- * __get_user_X
- *
- * Inputs: r0 contains the address
- *
- * Outputs: r0 is error code (0 or -EFAULT)
- * r1 contains zero-extended value
- *
- * These functions should not modify any other registers,
- * as they get called from within inline assembly.
- */
-
-#ifdef CONFIG_ISA_DUAL_ISSUE
-
- .text
- .balign 4
- .globl __get_user_1
-__get_user_1:
-1: ldub r1, @r0 || ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __get_user_2
-__get_user_2:
-2: lduh r1, @r0 || ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __get_user_4
-__get_user_4:
-3: ld r1, @r0 || ldi r0, #0
- jmp r14
-
-bad_get_user:
- ldi r1, #0 || ldi r0, #-14
- jmp r14
-
-#else /* not CONFIG_ISA_DUAL_ISSUE */
-
- .text
- .balign 4
- .globl __get_user_1
-__get_user_1:
-1: ldub r1, @r0
- ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __get_user_2
-__get_user_2:
-2: lduh r1, @r0
- ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __get_user_4
-__get_user_4:
-3: ld r1, @r0
- ldi r0, #0
- jmp r14
-
-bad_get_user:
- ldi r1, #0
- ldi r0, #-14
- jmp r14
-
-#endif /* not CONFIG_ISA_DUAL_ISSUE */
-
-.section __ex_table,"a"
- .long 1b,bad_get_user
- .long 2b,bad_get_user
- .long 3b,bad_get_user
-.previous
-
- .end
diff --git a/arch/m32r/lib/putuser.S b/arch/m32r/lib/putuser.S
deleted file mode 100644
index 218154cc389..00000000000
--- a/arch/m32r/lib/putuser.S
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * __put_user functions.
- *
- * (C) Copyright 1998 Linus Torvalds
- * (C) Copyright 2001 Hirokazu Takata
- *
- * These functions have a non-standard call interface
- * to make them more efficient.
- */
-
-#include <linux/config.h>
-
-/*
- * __put_user_X
- *
- * Inputs: r0 contains the address
- * r1 contains the value
- *
- * Outputs: r0 is error code (0 or -EFAULT)
- * r1 is corrupted (will contain "current_task").
- *
- * These functions should not modify any other registers,
- * as they get called from within inline assembly.
- */
-
-#ifdef CONFIG_ISA_DUAL_ISSUE
-
- .text
- .balign 4
- .globl __put_user_1
-__put_user_1:
-1: stb r1, @r0 || ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __put_user_2
-__put_user_2:
-2: sth r1, @r0 || ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __put_user_4
-__put_user_4:
-3: st r1, @r0 || ldi r0, #0
- jmp r14
-
-bad_put_user:
- ldi r0, #-14 || jmp r14
-
-#else /* not CONFIG_ISA_DUAL_ISSUE */
-
- .text
- .balign 4
- .globl __put_user_1
-__put_user_1:
-1: stb r1, @r0
- ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __put_user_2
-__put_user_2:
-2: sth r1, @r0
- ldi r0, #0
- jmp r14
-
- .balign 4
- .globl __put_user_4
-__put_user_4:
-3: st r1, @r0
- ldi r0, #0
- jmp r14
-
-bad_put_user:
- ldi r0, #-14
- jmp r14
-
-#endif /* not CONFIG_ISA_DUAL_ISSUE */
-
-.section __ex_table,"a"
- .long 1b,bad_put_user
- .long 2b,bad_put_user
- .long 3b,bad_put_user
-.previous
diff --git a/arch/m32r/mm/discontig.c b/arch/m32r/mm/discontig.c
index 08e72795555..cf610a7c5ff 100644
--- a/arch/m32r/mm/discontig.c
+++ b/arch/m32r/mm/discontig.c
@@ -13,6 +13,7 @@
#include <linux/initrd.h>
#include <linux/nodemask.h>
#include <linux/module.h>
+#include <linux/pfn.h>
#include <asm/setup.h>
@@ -137,12 +138,6 @@ unsigned long __init zone_sizes_init(void)
int nid, i;
mem_prof_t *mp;
- pgdat_list = NULL;
- for (nid = num_online_nodes() - 1 ; nid >= 0 ; nid--) {
- NODE_DATA(nid)->pgdat_next = pgdat_list;
- pgdat_list = NODE_DATA(nid);
- }
-
for_each_online_node(nid) {
mp = &mem_prof[nid];
for (i = 0 ; i < MAX_NR_ZONES ; i++) {
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
index c9e7dad860b..b71348fec1f 100644
--- a/arch/m32r/mm/init.c
+++ b/arch/m32r/mm/init.c
@@ -18,6 +18,7 @@
#include <linux/highmem.h>
#include <linux/bitops.h>
#include <linux/nodemask.h>
+#include <linux/pfn.h>
#include <asm/types.h>
#include <asm/processor.h>
#include <asm/page.h>
@@ -47,7 +48,7 @@ void show_mem(void)
printk("Mem-info:\n");
show_free_areas();
printk("Free swap: %6ldkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
unsigned long flags;
pgdat_resize_lock(pgdat, &flags);
for (i = 0; i < pgdat->node_spanned_pages; ++i) {
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 3d7f2000b71..5b7952ea2ba 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -57,7 +57,6 @@ EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(kernel_thread);
@@ -79,4 +78,3 @@ EXPORT_SYMBOL(__down_failed_interruptible);
EXPORT_SYMBOL(__down_failed_trylock);
EXPORT_SYMBOL(__up_wakeup);
-EXPORT_SYMBOL(get_wchan);
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
index a69fe3048ed..b0e4c084df8 100644
--- a/arch/m68k/mvme16x/rtc.c
+++ b/arch/m68k/mvme16x/rtc.c
@@ -17,6 +17,7 @@
#include <linux/poll.h>
#include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */
#include <linux/smp_lock.h>
+#include <linux/bcd.h>
#include <asm/mvme16xhw.h>
#include <asm/io.h>
@@ -31,9 +32,6 @@
* ioctls.
*/
-#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10)
-#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10)
-
static const unsigned char days_in_mo[] =
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
index d844c755945..4320d5dcc9c 100644
--- a/arch/m68knommu/kernel/m68k_ksyms.c
+++ b/arch/m68knommu/kernel/m68k_ksyms.c
@@ -26,7 +26,6 @@ EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strchr);
@@ -57,8 +56,6 @@ EXPORT_SYMBOL(__down_failed_interruptible);
EXPORT_SYMBOL(__down_failed_trylock);
EXPORT_SYMBOL(__up_wakeup);
-EXPORT_SYMBOL(get_wchan);
-
/*
* libgcc functions - functions that are used internally by the
* compiler... (prototypes are not correct though, but that
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 5080ea1799a..e8ff09fe73d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -13,7 +13,7 @@ choice
default SGI_IP22
config MIPS_MTX1
- bool "Support for 4G Systems MTX-1 board"
+ bool "4G Systems MTX-1 board"
select DMA_NONCOHERENT
select HW_HAS_PCI
select SOC_AU1500
@@ -120,7 +120,7 @@ config MIPS_MIRAGE
select SYS_SUPPORTS_LITTLE_ENDIAN
config MIPS_COBALT
- bool "Support for Cobalt Server"
+ bool "Cobalt Server"
select DMA_NONCOHERENT
select HW_HAS_PCI
select I8259
@@ -132,7 +132,7 @@ config MIPS_COBALT
select SYS_SUPPORTS_LITTLE_ENDIAN
config MACH_DECSTATION
- bool "Support for DECstations"
+ bool "DECstations"
select BOOT_ELF32
select DMA_NONCOHERENT
select EARLY_PRINTK
@@ -158,7 +158,7 @@ config MACH_DECSTATION
otherwise choose R3000.
config MIPS_EV64120
- bool "Support for Galileo EV64120 Evaluation board (EXPERIMENTAL)"
+ bool "Galileo EV64120 Evaluation board (EXPERIMENTAL)"
depends on EXPERIMENTAL
select DMA_NONCOHERENT
select HW_HAS_PCI
@@ -175,7 +175,7 @@ config MIPS_EV64120
kernel for this platform.
config MIPS_EV96100
- bool "Support for Galileo EV96100 Evaluation board (EXPERIMENTAL)"
+ bool "Galileo EV96100 Evaluation board (EXPERIMENTAL)"
depends on EXPERIMENTAL
select DMA_NONCOHERENT
select HW_HAS_PCI
@@ -195,7 +195,7 @@ config MIPS_EV96100
here if you wish to build a kernel for this platform.
config MIPS_IVR
- bool "Support for Globespan IVR board"
+ bool "Globespan IVR board"
select DMA_NONCOHERENT
select HW_HAS_PCI
select ITE_BOARD_GEN
@@ -211,7 +211,7 @@ config MIPS_IVR
build a kernel for this platform.
config MIPS_ITE8172
- bool "Support for ITE 8172G board"
+ bool "ITE 8172G board"
select DMA_NONCOHERENT
select HW_HAS_PCI
select ITE_BOARD_GEN
@@ -228,11 +228,12 @@ config MIPS_ITE8172
a kernel for this platform.
config MACH_JAZZ
- bool "Support for the Jazz family of machines"
+ bool "Jazz family of machines"
select ARC
select ARC32
select ARCH_MAY_HAVE_PC_FDC
select GENERIC_ISA_DMA
+ select I8253
select I8259
select ISA
select SYS_HAS_CPU_R4X00
@@ -245,7 +246,7 @@ config MACH_JAZZ
Olivetti M700-10 workstations.
config LASAT
- bool "Support for LASAT Networks platforms"
+ bool "LASAT Networks platforms"
select DMA_NONCOHERENT
select HW_HAS_PCI
select MIPS_GT64120
@@ -257,7 +258,7 @@ config LASAT
select SYS_SUPPORTS_LITTLE_ENDIAN
config MIPS_ATLAS
- bool "Support for MIPS Atlas board"
+ bool "MIPS Atlas board"
select BOOT_ELF32
select DMA_NONCOHERENT
select IRQ_CPU
@@ -282,7 +283,7 @@ config MIPS_ATLAS
board.
config MIPS_MALTA
- bool "Support for MIPS Malta board"
+ bool "MIPS Malta board"
select ARCH_MAY_HAVE_PC_FDC
select BOOT_ELF32
select HAVE_STD_PC_SERIAL_PORT
@@ -310,7 +311,7 @@ config MIPS_MALTA
board.
config MIPS_SEAD
- bool "Support for MIPS SEAD board (EXPERIMENTAL)"
+ bool "MIPS SEAD board (EXPERIMENTAL)"
depends on EXPERIMENTAL
select IRQ_CPU
select DMA_NONCOHERENT
@@ -327,7 +328,7 @@ config MIPS_SEAD
board.
config MIPS_SIM
- bool 'Support for MIPS simulator (MIPSsim)'
+ bool 'MIPS simulator (MIPSsim)'
select DMA_NONCOHERENT
select IRQ_CPU
select SYS_HAS_CPU_MIPS32_R1
@@ -340,7 +341,7 @@ config MIPS_SIM
emulator.
config MOMENCO_JAGUAR_ATX
- bool "Support for Momentum Jaguar board"
+ bool "Momentum Jaguar board"
select BOOT_ELF32
select DMA_NONCOHERENT
select HW_HAS_PCI
@@ -360,7 +361,7 @@ config MOMENCO_JAGUAR_ATX
Momentum Computer <http://www.momenco.com/>.
config MOMENCO_OCELOT
- bool "Support for Momentum Ocelot board"
+ bool "Momentum Ocelot board"
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
@@ -377,7 +378,7 @@ config MOMENCO_OCELOT
Momentum Computer <http://www.momenco.com/>.
config MOMENCO_OCELOT_3
- bool "Support for Momentum Ocelot-3 board"
+ bool "Momentum Ocelot-3 board"
select BOOT_ELF32
select DMA_NONCOHERENT
select HW_HAS_PCI
@@ -396,7 +397,7 @@ config MOMENCO_OCELOT_3
PMC-Sierra Rm79000 core.
config MOMENCO_OCELOT_C
- bool "Support for Momentum Ocelot-C board"
+ bool "Momentum Ocelot-C board"
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
@@ -413,7 +414,7 @@ config MOMENCO_OCELOT_C
Momentum Computer <http://www.momenco.com/>.
config MOMENCO_OCELOT_G
- bool "Support for Momentum Ocelot-G board"
+ bool "Momentum Ocelot-G board"
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
@@ -430,23 +431,23 @@ config MOMENCO_OCELOT_G
Momentum Computer <http://www.momenco.com/>.
config MIPS_XXS1500
- bool "Support for MyCable XXS1500 board"
+ bool "MyCable XXS1500 board"
select DMA_NONCOHERENT
select SOC_AU1500
select SYS_SUPPORTS_LITTLE_ENDIAN
config PNX8550_V2PCI
- bool "Support for Philips PNX8550 based Viper2-PCI board"
+ bool "Philips PNX8550 based Viper2-PCI board"
select PNX8550
select SYS_SUPPORTS_LITTLE_ENDIAN
config PNX8550_JBS
- bool "Support for Philips PNX8550 based JBS board"
+ bool "Philips PNX8550 based JBS board"
select PNX8550
select SYS_SUPPORTS_LITTLE_ENDIAN
config DDB5074
- bool "Support for NEC DDB Vrc-5074 (EXPERIMENTAL)"
+ bool "NEC DDB Vrc-5074 (EXPERIMENTAL)"
depends on EXPERIMENTAL
select DDB5XXX_COMMON
select DMA_NONCOHERENT
@@ -464,7 +465,7 @@ config DDB5074
evaluation board.
config DDB5476
- bool "Support for NEC DDB Vrc-5476"
+ bool "NEC DDB Vrc-5476"
select DDB5XXX_COMMON
select DMA_NONCOHERENT
select HAVE_STD_PC_SERIAL_PORT
@@ -485,7 +486,7 @@ config DDB5476
IDE controller, PS2 keyboard, PS2 mouse, etc.
config DDB5477
- bool "Support for NEC DDB Vrc-5477"
+ bool "NEC DDB Vrc-5477"
select DDB5XXX_COMMON
select DMA_NONCOHERENT
select HW_HAS_PCI
@@ -503,13 +504,13 @@ config DDB5477
ether port USB, AC97, PCI, etc.
config MACH_VR41XX
- bool "Support for NEC VR4100 series based machines"
+ bool "NEC VR41XX-based machines"
select SYS_HAS_CPU_VR41XX
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
config PMC_YOSEMITE
- bool "Support for PMC-Sierra Yosemite eval board"
+ bool "PMC-Sierra Yosemite eval board"
select DMA_COHERENT
select HW_HAS_PCI
select IRQ_CPU
@@ -526,10 +527,11 @@ config PMC_YOSEMITE
manufactured by PMC-Sierra.
config QEMU
- bool "Support for Qemu"
+ bool "Qemu"
select DMA_COHERENT
select GENERIC_ISA_DMA
select HAVE_STD_PC_SERIAL_PORT
+ select I8253
select I8259
select ISA
select SWAP_IO_SPACE
@@ -545,7 +547,7 @@ config QEMU
can be found at http://www.linux-mips.org/wiki/Qemu.
config SGI_IP22
- bool "Support for SGI IP22 (Indy/Indigo2)"
+ bool "SGI IP22 (Indy/Indigo2)"
select ARC
select ARC32
select BOOT_ELF32
@@ -565,7 +567,7 @@ config SGI_IP22
that runs on these, say Y here.
config SGI_IP27
- bool "Support for SGI IP27 (Origin200/2000)"
+ bool "SGI IP27 (Origin200/2000)"
select ARC
select ARC64
select BOOT_ELF64
@@ -581,7 +583,7 @@ config SGI_IP27
here.
config SGI_IP32
- bool "Support for SGI IP32 (O2) (EXPERIMENTAL)"
+ bool "SGI IP32 (O2) (EXPERIMENTAL)"
depends on EXPERIMENTAL
select ARC
select ARC32
@@ -602,7 +604,7 @@ config SGI_IP32
If you want this kernel to run on SGI O2 workstation, say Y here.
config SIBYTE_BIGSUR
- bool "Support for Sibyte BCM91480B-BigSur"
+ bool "Sibyte BCM91480B-BigSur"
select BOOT_ELF32
select DMA_COHERENT
select PCI_DOMAINS
@@ -613,7 +615,7 @@ config SIBYTE_BIGSUR
select SYS_SUPPORTS_LITTLE_ENDIAN
config SIBYTE_SWARM
- bool "Support for Sibyte BCM91250A-SWARM"
+ bool "Sibyte BCM91250A-SWARM"
select BOOT_ELF32
select DMA_COHERENT
select SIBYTE_SB1250
@@ -624,7 +626,7 @@ config SIBYTE_SWARM
select SYS_SUPPORTS_LITTLE_ENDIAN
config SIBYTE_SENTOSA
- bool "Support for Sibyte BCM91250E-Sentosa"
+ bool "Sibyte BCM91250E-Sentosa"
depends on EXPERIMENTAL
select BOOT_ELF32
select DMA_COHERENT
@@ -635,7 +637,7 @@ config SIBYTE_SENTOSA
select SYS_SUPPORTS_LITTLE_ENDIAN
config SIBYTE_RHONE
- bool "Support for Sibyte BCM91125E-Rhone"
+ bool "Sibyte BCM91125E-Rhone"
depends on EXPERIMENTAL
select BOOT_ELF32
select DMA_COHERENT
@@ -646,7 +648,7 @@ config SIBYTE_RHONE
select SYS_SUPPORTS_LITTLE_ENDIAN
config SIBYTE_CARMEL
- bool "Support for Sibyte BCM91120x-Carmel"
+ bool "Sibyte BCM91120x-Carmel"
depends on EXPERIMENTAL
select BOOT_ELF32
select DMA_COHERENT
@@ -657,7 +659,7 @@ config SIBYTE_CARMEL
select SYS_SUPPORTS_LITTLE_ENDIAN
config SIBYTE_PTSWARM
- bool "Support for Sibyte BCM91250PT-PTSWARM"
+ bool "Sibyte BCM91250PT-PTSWARM"
depends on EXPERIMENTAL
select BOOT_ELF32
select DMA_COHERENT
@@ -669,7 +671,7 @@ config SIBYTE_PTSWARM
select SYS_SUPPORTS_LITTLE_ENDIAN
config SIBYTE_LITTLESUR
- bool "Support for Sibyte BCM91250C2-LittleSur"
+ bool "Sibyte BCM91250C2-LittleSur"
depends on EXPERIMENTAL
select BOOT_ELF32
select DMA_COHERENT
@@ -681,7 +683,7 @@ config SIBYTE_LITTLESUR
select SYS_SUPPORTS_LITTLE_ENDIAN
config SIBYTE_CRHINE
- bool "Support for Sibyte BCM91120C-CRhine"
+ bool "Sibyte BCM91120C-CRhine"
depends on EXPERIMENTAL
select BOOT_ELF32
select DMA_COHERENT
@@ -692,7 +694,7 @@ config SIBYTE_CRHINE
select SYS_SUPPORTS_LITTLE_ENDIAN
config SIBYTE_CRHONE
- bool "Support for Sibyte BCM91125C-CRhone"
+ bool "Sibyte BCM91125C-CRhone"
depends on EXPERIMENTAL
select BOOT_ELF32
select DMA_COHERENT
@@ -704,7 +706,7 @@ config SIBYTE_CRHONE
select SYS_SUPPORTS_LITTLE_ENDIAN
config SNI_RM200_PCI
- bool "Support for SNI RM200 PCI"
+ bool "SNI RM200 PCI"
select ARC
select ARC32
select ARCH_MAY_HAVE_PC_FDC
@@ -714,6 +716,7 @@ config SNI_RM200_PCI
select HAVE_STD_PC_SERIAL_PORT
select HW_HAS_EISA
select HW_HAS_PCI
+ select I8253
select I8259
select ISA
select SYS_HAS_CPU_R4X00
@@ -729,7 +732,7 @@ config SNI_RM200_PCI
support this machine type.
config TOSHIBA_JMR3927
- bool "Support for Toshiba JMR-TX3927 board"
+ bool "Toshiba JMR-TX3927 board"
select DMA_NONCOHERENT
select HW_HAS_PCI
select MIPS_TX3927
@@ -740,7 +743,7 @@ config TOSHIBA_JMR3927
select TOSHIBA_BOARDS
config TOSHIBA_RBTX4927
- bool "Support for Toshiba TBTX49[23]7 board"
+ bool "Toshiba TBTX49[23]7 board"
select DMA_NONCOHERENT
select HAS_TXX9_SERIAL
select HW_HAS_PCI
@@ -757,7 +760,7 @@ config TOSHIBA_RBTX4927
support this machine type
config TOSHIBA_RBTX4938
- bool "Support for Toshiba RBTX4938 board"
+ bool "Toshiba RBTX4938 board"
select HAVE_STD_PC_SERIAL_PORT
select DMA_NONCOHERENT
select GENERIC_ISA_DMA
@@ -813,6 +816,10 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
+config SCHED_NO_NO_OMIT_FRAME_POINTER
+ bool
+ default y
+
#
# Select some configuration options automatically based on user selections.
#
@@ -1060,6 +1067,7 @@ choice
config CPU_MIPS32_R1
bool "MIPS32 Release 1"
depends on SYS_HAS_CPU_MIPS32_R1
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
@@ -1077,6 +1085,7 @@ config CPU_MIPS32_R1
config CPU_MIPS32_R2
bool "MIPS32 Release 2"
depends on SYS_HAS_CPU_MIPS32_R2
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
@@ -1090,6 +1099,7 @@ config CPU_MIPS32_R2
config CPU_MIPS64_R1
bool "MIPS64 Release 1"
depends on SYS_HAS_CPU_MIPS64_R1
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
@@ -1108,6 +1118,7 @@ config CPU_MIPS64_R1
config CPU_MIPS64_R2
bool "MIPS64 Release 2"
depends on SYS_HAS_CPU_MIPS64_R2
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
@@ -1122,6 +1133,7 @@ config CPU_MIPS64_R2
config CPU_R3000
bool "R3000"
depends on SYS_HAS_CPU_R3000
+ select CPU_HAS_WB
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
help
@@ -1151,6 +1163,7 @@ config CPU_VR41XX
config CPU_R4300
bool "R4300"
depends on SYS_HAS_CPU_R4300
+ select CPU_HAS_LLSC
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
help
@@ -1159,6 +1172,7 @@ config CPU_R4300
config CPU_R4X00
bool "R4x00"
depends on SYS_HAS_CPU_R4X00
+ select CPU_HAS_LLSC
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
help
@@ -1168,6 +1182,7 @@ config CPU_R4X00
config CPU_TX49XX
bool "R49XX"
depends on SYS_HAS_CPU_TX49XX
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
@@ -1175,6 +1190,7 @@ config CPU_TX49XX
config CPU_R5000
bool "R5000"
depends on SYS_HAS_CPU_R5000
+ select CPU_HAS_LLSC
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
help
@@ -1183,12 +1199,14 @@ config CPU_R5000
config CPU_R5432
bool "R5432"
depends on SYS_HAS_CPU_R5432
+ select CPU_HAS_LLSC
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
config CPU_R6000
bool "R6000"
depends on EXPERIMENTAL
+ select CPU_HAS_LLSC
depends on SYS_HAS_CPU_R6000
select CPU_SUPPORTS_32BIT_KERNEL
help
@@ -1198,6 +1216,7 @@ config CPU_R6000
config CPU_NEVADA
bool "RM52xx"
depends on SYS_HAS_CPU_NEVADA
+ select CPU_HAS_LLSC
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
help
@@ -1207,6 +1226,7 @@ config CPU_R8000
bool "R8000"
depends on EXPERIMENTAL
depends on SYS_HAS_CPU_R8000
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_64BIT_KERNEL
help
@@ -1216,6 +1236,7 @@ config CPU_R8000
config CPU_R10000
bool "R10000"
depends on SYS_HAS_CPU_R10000
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
@@ -1226,6 +1247,7 @@ config CPU_R10000
config CPU_RM7000
bool "RM7000"
depends on SYS_HAS_CPU_RM7000
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
@@ -1234,6 +1256,7 @@ config CPU_RM7000
config CPU_RM9000
bool "RM9000"
depends on SYS_HAS_CPU_RM9000
+ select CPU_HAS_LLSC
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
@@ -1242,6 +1265,7 @@ config CPU_RM9000
config CPU_SB1
bool "SB1"
depends on SYS_HAS_CPU_SB1
+ select CPU_HAS_LLSC
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_64BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
@@ -1387,13 +1411,12 @@ config PAGE_SIZE_8KB
config PAGE_SIZE_16KB
bool "16kB"
- depends on EXPERIMENTAL && !CPU_R3000 && !CPU_TX39XX
+ depends on !CPU_R3000 && !CPU_TX39XX
help
Using 16kB page size will result in higher performance kernel at
the price of higher memory consumption. This option is available on
- all non-R3000 family processor. Not that at the time of this
- writing this option is still high experimental; there are also
- issues with compatibility of user applications.
+ all non-R3000 family processors. Note that you will need a suitable
+ Linux distribution to support this.
config PAGE_SIZE_64KB
bool "64kB"
@@ -1402,8 +1425,7 @@ config PAGE_SIZE_64KB
Using 64kB page size will result in higher performance kernel at
the price of higher memory consumption. This option is available on
all non-R3000 family processor. Not that at the time of this
- writing this option is still high experimental; there are also
- issues with compatibility of user applications.
+ writing this option is still high experimental.
endchoice
@@ -1440,6 +1462,12 @@ choice
prompt "MIPS MT options"
depends on MIPS_MT
+config MIPS_MT_SMTC
+ bool "SMTC: Use all TCs on all VPEs for SMP"
+ select CPU_MIPSR2_IRQ_VI
+ select CPU_MIPSR2_SRS
+ select SMP
+
config MIPS_MT_SMP
bool "Use 1 TC on each available VPE for SMP"
select SMP
@@ -1453,6 +1481,11 @@ config MIPS_VPE_LOADER
endchoice
+config MIPS_MT_FPAFF
+ bool "Dynamic FPU affinity for FP-intensive threads"
+ depends on MIPS_MT
+ default y
+
config MIPS_VPE_LOADER_TOM
bool "Load VPE program into memory hidden from linux"
depends on MIPS_VPE_LOADER
@@ -1469,6 +1502,16 @@ config MIPS_VPE_APSP_API
depends on MIPS_VPE_LOADER
help
+config MIPS_APSP_KSPD
+ bool "Enable KSPD"
+ depends on MIPS_VPE_APSP_API
+ default y
+ help
+ KSPD is a kernel daemon that accepts syscall requests from the SP
+ side, actions them and returns the results. It also handles the
+ "exit" syscall notifying other kernel modules the SP program is
+ exiting. You probably want to say yes here.
+
config SB1_PASS_1_WORKAROUNDS
bool
depends on CPU_SB1_PASS_1
@@ -1488,38 +1531,15 @@ config 64BIT_PHYS_ADDR
bool "Support for 64-bit physical address space"
depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_RM9000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32 || CPU_MIPS64) && 32BIT
-config CPU_ADVANCED
- bool "Override CPU Options"
- depends on 32BIT
- help
- Saying yes here allows you to select support for various features
- your CPU may or may not have. Most people should say N here.
-
config CPU_HAS_LLSC
- bool "ll/sc Instructions available" if CPU_ADVANCED
- default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX && !CPU_TX39XX
- help
- MIPS R4000 series and later provide the Load Linked (ll)
- and Store Conditional (sc) instructions. More information is
- available at <http://www.go-ecs.com/mips/miptek1.htm>.
-
- Say Y here if your CPU has the ll and sc instructions. Say Y here
- for better performance, N if you don't know. You must say Y here
- for multiprocessor machines.
+ bool
config CPU_HAS_WB
- bool "Writeback Buffer available" if CPU_ADVANCED
- default y if !CPU_ADVANCED && CPU_R3000 && MACH_DECSTATION
- help
- Say N here for slightly better performance. You must say Y here for
- machines which require flushing of write buffers in software. Saying
- Y is the safe option; N may result in kernel malfunction and crashes.
-
-menu "MIPSR2 Interrupt handling"
- depends on CPU_MIPSR2 && CPU_ADVANCED
+ bool
config CPU_MIPSR2_IRQ_VI
bool "Vectored interrupt mode"
+ depends on CPU_MIPSR2
help
Vectored interrupt mode allowing faster dispatching of interrupts.
The board support code needs to be written to take advantage of this
@@ -1529,6 +1549,7 @@ config CPU_MIPSR2_IRQ_VI
config CPU_MIPSR2_IRQ_EI
bool "External interrupt controller mode"
+ depends on CPU_MIPSR2
help
Extended interrupt mode takes advantage of an external interrupt
controller to allow fast dispatching from many possible interrupt
@@ -1542,7 +1563,6 @@ config CPU_MIPSR2_SRS
Allow the kernel to use shadow register sets for fast interrupts.
Interrupt handlers must be specially written to use shadow sets.
Say N unless you know that shadow register set upport is needed.
-endmenu
config CPU_HAS_SYNC
bool
@@ -1587,11 +1607,16 @@ config ARCH_FLATMEM_ENABLE
def_bool y
depends on !NUMA
+config NODES_SHIFT
+ int
+ default "6"
+ depends on NEED_MULTIPLE_NODES
+
source "mm/Kconfig"
config SMP
bool "Multi-Processing support"
- depends on CPU_RM9000 || ((SIBYTE_BCM1x80 || SIBYTE_BCM1x55 || SIBYTE_SB1250 || QEMU) && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP
+ depends on CPU_RM9000 || ((SIBYTE_BCM1x80 || SIBYTE_BCM1x55 || SIBYTE_SB1250 || QEMU) && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP || MIPS_MT_SMTC
---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
@@ -1721,6 +1746,9 @@ config MMU
bool
default y
+config I8253
+ bool
+
source "drivers/pcmcia/Kconfig"
source "drivers/pci/hotplug/Kconfig"
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index d3c5cc3b9c9..515f9e61130 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -6,7 +6,13 @@ config CROSSCOMPILE
bool "Are you using a crosscompiler"
help
Say Y here if you are compiling the kernel on a different
- architecture than the one it is intended to run on.
+ architecture than the one it is intended to run on. This is just a
+ convenience option which will select the appropriate value for
+ the CROSS_COMPILE make variable which otherwise has to be passed on
+ the command line from mips-linux-, mipsel-linux-, mips64-linux- and
+ mips64el-linux- as appropriate for a particular kernel configuration.
+ You will have to pass the value for CROSS_COMPILE manually if the
+ name prefix for your tools is different.
config CMDLINE
string "Default kernel command string"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 9a69e0f0ab7..133900aca99 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -105,18 +105,18 @@ cflags-$(CONFIG_CPU_R4300) += -march=r4300 -Wa,--trap
cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap
cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap
cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips2 -mtune=r4600) \
+cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
-Wa,-mips32 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips2 -mtune=r4600) \
+cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
-Wa,-mips32r2 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips2 -mtune=r4600) \
+cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
-Wa,-mips64 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips2 -mtune=r4600 ) \
+cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
-Wa,-mips64r2 -Wa,--trap
cflags-$(CONFIG_CPU_R5000) += -march=r5000 -Wa,--trap
-cflags-$(CONFIG_CPU_R5432) += $(call cc-options,-march=r5400,-march=r5000) \
+cflags-$(CONFIG_CPU_R5432) += $(call cc-option,-march=r5400,-march=r5000) \
-Wa,--trap
-cflags-$(CONFIG_CPU_NEVADA) += $(call cc-options,-march=rm5200,-march=r5000) \
+cflags-$(CONFIG_CPU_NEVADA) += $(call cc-option,-march=rm5200,-march=r5000) \
-Wa,--trap
cflags-$(CONFIG_CPU_RM7000) += $(call cc-option,-march=rm7000,-march=r5000) \
-Wa,--trap
@@ -615,7 +615,10 @@ LDFLAGS += -m $(ld-emul)
ifdef CONFIG_MIPS
CHECKFLAGS += $(shell $(CC) $(CFLAGS) -dM -E -xc /dev/null | \
egrep -vw '__GNUC_(MAJOR|MINOR|PATCHLEVEL)__' | \
- sed -e 's/^\#define /-D/' -e 's/ /="/' -e 's/$$/"/')
+ sed -e 's/^\#define /-D/' -e "s/ /='/" -e "s/$$/'/")
+ifdef CONFIG_64BIT
+CHECKFLAGS += -m64
+endif
endif
OBJCOPYFLAGS += --remove-section=.reginfo
diff --git a/arch/mips/au1000/common/Makefile b/arch/mips/au1000/common/Makefile
index a1edfd1f643..bf682f50b85 100644
--- a/arch/mips/au1000/common/Makefile
+++ b/arch/mips/au1000/common/Makefile
@@ -6,7 +6,7 @@
# Makefile for the Alchemy Au1000 CPU, generic files.
#
-obj-y += prom.o int-handler.o irq.o puts.o time.o reset.o \
+obj-y += prom.o irq.o puts.o time.o reset.o \
au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
sleeper.o cputable.o dma.o dbdma.o gpio.o
diff --git a/arch/mips/au1000/common/int-handler.S b/arch/mips/au1000/common/int-handler.S
deleted file mode 100644
index 1c4ca883321..00000000000
--- a/arch/mips/au1000/common/int-handler.S
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: ppopov@mvista.com
- *
- * Interrupt dispatcher for Au1000 boards.
- *
- * This program is free software; 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .text
- .set macro
- .set noat
- .align 5
-
-NESTED(au1000_IRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI # Important: mark KERNEL mode !
-
- mfc0 t0,CP0_CAUSE # get pending interrupts
- mfc0 t1,CP0_STATUS # get enabled interrupts
- and t0,t1 # isolate allowed ones
-
- andi t0,0xff00 # isolate pending bits
- beqz t0, 3f # spurious interrupt
-
- andi a0, t0, CAUSEF_IP7
- beq a0, zero, 1f
- move a0, sp
- jal mips_timer_interrupt
- j ret_from_irq
-
-1:
- andi a0, t0, CAUSEF_IP2 # Interrupt Controller 0, Request 0
- beq a0, zero, 2f
- move a0,sp
- jal intc0_req0_irqdispatch
- j ret_from_irq
-2:
- andi a0, t0, CAUSEF_IP3 # Interrupt Controller 0, Request 1
- beq a0, zero, 3f
- move a0,sp
- jal intc0_req1_irqdispatch
- j ret_from_irq
-3:
- andi a0, t0, CAUSEF_IP4 # Interrupt Controller 1, Request 0
- beq a0, zero, 4f
- move a0,sp
- jal intc1_req0_irqdispatch
- j ret_from_irq
-4:
- andi a0, t0, CAUSEF_IP5 # Interrupt Controller 1, Request 1
- beq a0, zero, 5f
- move a0, sp
- jal intc1_req1_irqdispatch
- j ret_from_irq
-
-5:
- move a0, sp
- j spurious_interrupt
-END(au1000_IRQ)
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
index 1339a0979f6..afe05ec12c2 100644
--- a/arch/mips/au1000/common/irq.c
+++ b/arch/mips/au1000/common/irq.c
@@ -66,9 +66,9 @@
#define EXT_INTC1_REQ1 5 /* IP 5 */
#define MIPS_TIMER_IP 7 /* IP 7 */
-extern asmlinkage void au1000_IRQ(void);
extern void set_debug_traps(void);
extern irq_cpustat_t irq_stat [NR_CPUS];
+extern void mips_timer_interrupt(struct pt_regs *regs);
static void setup_local_irq(unsigned int irq, int type, int int_req);
static unsigned int startup_irq(unsigned int irq);
@@ -446,7 +446,6 @@ void __init arch_init_irq(void)
extern int au1xxx_ic0_nr_irqs;
cp0_status = read_c0_status();
- set_except_vector(0, au1000_IRQ);
/* Initialize interrupt controllers to a safe state.
*/
@@ -661,3 +660,21 @@ restore_au1xxx_intctl(void)
au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
}
#endif /* CONFIG_PM */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+
+ if (pending & CAUSEF_IP7)
+ mips_timer_interrupt(regs);
+ else if (pending & CAUSEF_IP2)
+ intc0_req0_irqdispatch(regs);
+ else if (pending & CAUSEF_IP3)
+ intc0_req1_irqdispatch(regs);
+ else if (pending & CAUSEF_IP4)
+ intc1_req0_irqdispatch(regs);
+ else if (pending & CAUSEF_IP5)
+ intc1_req1_irqdispatch(regs);
+ else
+ spurious_interrupt(regs);
+}
diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c
index 9c171afd9a5..ae7d8c57bf3 100644
--- a/arch/mips/au1000/common/prom.c
+++ b/arch/mips/au1000/common/prom.c
@@ -1,10 +1,9 @@
/*
*
* BRIEF MODULE DESCRIPTION
- * PROM library initialisation code, assuming a version of
- * pmon is the boot code.
+ * PROM library initialisation code, assuming YAMON is the boot loader.
*
- * Copyright 2000,2001 MontaVista Software Inc.
+ * Copyright 2000, 2001, 2006 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
@@ -49,9 +48,9 @@ extern char **prom_argv, **prom_envp;
typedef struct
{
- char *name;
-/* char *val; */
-}t_env_var;
+ char *name;
+ char *val;
+} t_env_var;
char * prom_getcmdline(void)
@@ -85,21 +84,16 @@ char *prom_getenv(char *envname)
{
/*
* Return a pointer to the given environment variable.
- * Environment variables are stored in the form of "memsize=64".
*/
t_env_var *env = (t_env_var *)prom_envp;
- int i;
-
- i = strlen(envname);
- while(env->name) {
- if(strncmp(envname, env->name, i) == 0) {
- return(env->name + strlen(envname) + 1);
- }
+ while (env->name) {
+ if (strcmp(envname, env->name) == 0)
+ return env->val;
env++;
}
- return(NULL);
+ return NULL;
}
inline unsigned char str2hexnum(unsigned char c)
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
index 1080558c810..307e98c29dd 100644
--- a/arch/mips/au1000/common/setup.c
+++ b/arch/mips/au1000/common/setup.c
@@ -94,7 +94,7 @@ void __init plat_setup(void)
argptr = prom_getcmdline();
-#if defined(CONFIG_SERIAL_AU1X00_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
+#ifdef CONFIG_SERIAL_8250_CONSOLE
if ((argptr = strstr(argptr, "console=")) == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
diff --git a/arch/mips/au1000/common/sleeper.S b/arch/mips/au1000/common/sleeper.S
index 44dac3b0df3..683d9da84b6 100644
--- a/arch/mips/au1000/common/sleeper.S
+++ b/arch/mips/au1000/common/sleeper.S
@@ -112,6 +112,11 @@ sdsleep:
mtc0 k0, CP0_PAGEMASK
lw k0, 0x14(sp)
mtc0 k0, CP0_CONFIG
+
+ /* We need to catch the ealry Alchemy SOCs with
+ * the write-only Config[OD] bit and set it back to one...
+ */
+ jal au1x00_fixup_config_od
lw $1, PT_R1(sp)
lw $2, PT_R2(sp)
lw $3, PT_R3(sp)
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index f85f1524b36..f74d66a58a2 100644
--- a/arch/mips/au1000/common/time.c
+++ b/arch/mips/au1000/common/time.c
@@ -116,6 +116,7 @@ void mips_timer_interrupt(struct pt_regs *regs)
null:
ack_r4ktimer(0);
+ irq_exit();
}
#ifdef CONFIG_PM
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index 720e757b2b6..225ac8f34cc 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -2,7 +2,7 @@
# Makefile for the Cobalt micro systems family specific parts of the kernel
#
-obj-y := irq.o int-handler.o reset.o setup.o
+obj-y := irq.o reset.o setup.o
obj-$(CONFIG_EARLY_PRINTK) += console.o
diff --git a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S
deleted file mode 100644
index e75d5e3ca86..00000000000
--- a/arch/mips/cobalt/int-handler.S
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
- * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/mach-cobalt/cobalt.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .text
- .align 5
- NESTED(cobalt_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
-
- PTR_LA ra, ret_from_irq
- move a0, sp
- j cobalt_irq
-
- END(cobalt_handle_int)
diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c
index f9a108820d6..0b75f4fb719 100644
--- a/arch/mips/cobalt/irq.c
+++ b/arch/mips/cobalt/irq.c
@@ -20,8 +20,6 @@
#include <asm/mach-cobalt/cobalt.h>
-extern void cobalt_handle_int(void);
-
/*
* We have two types of interrupts that we handle, ones that come in through
* the CPU interrupt lines, and ones that come in on the via chip. The CPU
@@ -79,7 +77,7 @@ static inline void via_pic_irq(struct pt_regs *regs)
do_IRQ(irq, regs);
}
-asmlinkage void cobalt_irq(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned pending;
@@ -122,8 +120,6 @@ void __init arch_init_irq(void)
*/
GALILEO_OUTL(0, GT_INTRMASK_OFS);
- set_except_vector(0, cobalt_handle_int);
-
init_i8259_irqs(); /* 0 ... 15 */
mips_cpu_irq_init(COBALT_CPU_IRQ); /* 16 ... 23 */
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index 9e1ae953e96..4b080bcb258 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:52 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:55 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_ATLAS=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -127,11 +129,11 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -149,7 +151,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -165,6 +166,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -178,10 +180,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -193,7 +191,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -202,6 +199,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -221,7 +220,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -249,6 +247,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -281,6 +280,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -322,9 +322,12 @@ CONFIG_IP_VS_NQ=m
CONFIG_IP_VS_FTP=m
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -348,11 +351,14 @@ CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
@@ -376,20 +382,19 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_MATCH_OWNER=m
CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -407,6 +412,7 @@ CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_NAT_TFTP=m
CONFIG_IP_NF_NAT_AMANDA=m
CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
@@ -427,12 +433,10 @@ CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
CONFIG_IP6_NF_MATCH_OWNER=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_TARGET_REJECT=m
@@ -478,6 +482,11 @@ CONFIG_IP_SCTP=m
# 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=m
CONFIG_VLAN_8021Q=m
@@ -492,11 +501,6 @@ CONFIG_IPDDP_ENCAP=y
CONFIG_IPDDP_DECAP=y
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
CONFIG_NET_DIVERT=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -556,6 +560,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -694,9 +701,8 @@ CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -715,6 +721,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=m
+CONFIG_MD_RAID5_RESHAPE=y
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -921,6 +928,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=m
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -930,6 +938,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -988,10 +997,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -1022,6 +1027,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -1039,13 +1045,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1120,7 +1144,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1140,7 +1163,6 @@ CONFIG_VXFS_FS=m
# CONFIG_QNX4FS_FS is not set
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
@@ -1232,6 +1254,7 @@ CONFIG_NLS_UTF8=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 32984100a75..d85cda58d65 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:53 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:55 2006
#
CONFIG_MIPS=y
@@ -80,6 +80,8 @@ CONFIG_SIBYTE_CFE=y
# CONFIG_SIBYTE_SB1250_PROF is not set
# CONFIG_SIBYTE_TBPROF is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_COHERENT=y
CONFIG_CPU_BIG_ENDIAN=y
@@ -154,7 +156,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -172,6 +173,7 @@ CONFIG_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -186,10 +188,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -201,7 +199,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -210,6 +207,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -230,7 +228,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_DEBUG=y
CONFIG_MMU=y
@@ -249,6 +246,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_BUILD_ELF64=y
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
@@ -263,6 +261,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -284,12 +283,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -301,6 +303,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -310,11 +317,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -377,7 +379,7 @@ CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -575,6 +577,7 @@ CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -637,7 +640,6 @@ CONFIG_I2C_ALGO_SIBYTE=y
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
CONFIG_I2C_SIBYTE=y
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -656,9 +658,7 @@ CONFIG_SENSORS_EEPROM=y
CONFIG_SENSORS_PCF8574=y
CONFIG_SENSORS_PCA9539=y
CONFIG_SENSORS_PCF8591=y
-CONFIG_SENSORS_RTC8564=y
CONFIG_SENSORS_MAX6875=y
-# CONFIG_RTC_X1205_I2C is not set
CONFIG_I2C_DEBUG_CORE=y
CONFIG_I2C_DEBUG_ALGO=y
CONFIG_I2C_DEBUG_BUS=y
@@ -686,10 +686,6 @@ CONFIG_I2C_DEBUG_CHIP=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -714,6 +710,7 @@ CONFIG_I2C_DEBUG_CHIP=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -731,13 +728,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -785,7 +800,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index 6c2961affbd..ca0af1683a0 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:54 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:08:06 2006
#
CONFIG_MIPS=y
@@ -72,6 +72,8 @@ CONFIG_ZAO_CAPCELLA=y
CONFIG_PCI_VR41XX=y
# CONFIG_VRC4173 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -90,7 +92,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_MIPS64_R2 is not set
# CONFIG_CPU_R3000 is not set
# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
+CONFIG_CPU_VR41XX=y
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
@@ -103,18 +105,21 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
#
-# CONFIG_32BIT is not set
+CONFIG_32BIT=y
# CONFIG_64BIT is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -135,7 +140,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -151,6 +155,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -164,10 +169,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -179,7 +180,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -187,6 +187,9 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -206,7 +209,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -224,6 +226,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
#
# Networking
@@ -233,6 +236,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -255,12 +259,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -272,6 +279,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -281,11 +293,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -302,10 +309,7 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
+# CONFIG_IEEE80211 is not set
#
# Device Drivers
@@ -348,10 +352,12 @@ CONFIG_CONNECTOR=m
# 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 is not set
+CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -578,6 +584,11 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -601,6 +612,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# Ftape, the floppy tape device driver
#
# CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
# CONFIG_RAW_DRIVER is not set
#
@@ -636,10 +648,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -670,6 +678,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -687,13 +696,48 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# 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"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
#
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_VR41XX=y
+# CONFIG_RTC_DRV_TEST is not set
#
# File systems
@@ -712,7 +756,7 @@ CONFIG_EXT2_FS=y
CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=m
@@ -735,10 +779,9 @@ CONFIG_FUSE_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -805,44 +848,20 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="mem=32M console=ttyVR0,38400"
#
# Security options
#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
#
# Hardware crypto devices
@@ -852,8 +871,6 @@ CONFIG_CRYPTO_CRC32C=m
# Library routines
#
# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 8336b21d3db..7d269e60928 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:55 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:57 2006
#
CONFIG_MIPS=y
@@ -63,7 +63,10 @@ CONFIG_MIPS_COBALT=y
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_EARLY_PRINTK=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -113,7 +116,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -135,7 +137,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -151,6 +152,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -164,10 +166,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -182,6 +180,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -201,7 +201,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -229,6 +228,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -247,12 +247,15 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -264,6 +267,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -273,11 +281,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -298,6 +301,9 @@ CONFIG_IEEE80211=y
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=y
CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -343,7 +349,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -593,6 +599,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -602,6 +609,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -660,10 +668,6 @@ CONFIG_COBALT_LCD=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -694,6 +698,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -711,13 +716,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -765,7 +788,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -828,6 +850,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 7f071403c8e..579b665e333 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:56 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:57 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_DB1000=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,11 +116,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -136,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -152,6 +153,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -165,10 +167,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -181,7 +179,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -190,6 +187,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -245,6 +244,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -267,7 +267,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -278,6 +279,8 @@ CONFIG_TCP_CONG_BIC=y
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -294,10 +297,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -321,6 +327,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -330,11 +341,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -356,6 +362,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -412,7 +421,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -434,7 +442,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -471,7 +478,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -722,10 +729,6 @@ CONFIG_SYNCLINK_CS=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -756,6 +759,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB is not set
#
@@ -773,12 +777,30 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -836,7 +858,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -945,6 +966,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 98590cac1ec..e5eb5386742 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:57 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:58 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_DB1100=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,11 +116,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -136,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -152,6 +153,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -165,10 +167,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -181,7 +179,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -190,6 +187,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -234,6 +233,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -256,7 +256,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -267,6 +268,8 @@ CONFIG_TCP_CONG_BIC=y
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -283,10 +286,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -310,6 +316,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -319,11 +330,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -345,6 +351,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -401,7 +410,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -423,7 +431,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -460,7 +467,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -690,10 +697,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -711,6 +714,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_S1D13XXX is not set
@@ -755,6 +759,7 @@ CONFIG_LOGO_LINUX_CLUT224=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB is not set
#
@@ -772,12 +777,30 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -835,7 +858,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -944,6 +966,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index 92888472dca..a43fb2329fd 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:58 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:58 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_DB1200=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_COHERENT=y
CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
@@ -114,11 +116,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -136,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +154,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -166,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -182,7 +180,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -191,6 +188,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -244,6 +243,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -263,7 +263,8 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -274,6 +275,8 @@ CONFIG_TCP_CONG_BIC=y
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -288,10 +291,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -315,6 +321,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -324,11 +335,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -403,7 +409,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -425,7 +430,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -763,10 +767,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -784,6 +784,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_S1D13XXX is not set
@@ -794,6 +795,7 @@ CONFIG_FB_AU1200=y
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
CONFIG_DUMMY_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE is not set
@@ -816,6 +818,7 @@ CONFIG_LOGO_LINUX_CLUT224=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -832,6 +835,7 @@ CONFIG_USB_GADGET=m
# CONFIG_USB_GADGET_GOKU is not set
# CONFIG_USB_GADGET_LH7A40X is not set
# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_AT91 is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
# CONFIG_USB_GADGET_DUALSPEED is not set
@@ -844,12 +848,30 @@ CONFIG_MMC_BLOCK=y
CONFIG_MMC_AU1X=y
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -913,7 +935,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1027,6 +1048,7 @@ CONFIG_NLS_UTF8=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="mem=48M"
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 5a415b1d4af..ad632d87c4e 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:59 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:59 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_DB1500=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -116,11 +118,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -138,7 +140,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -154,6 +155,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +169,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -183,7 +181,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -192,6 +189,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -211,7 +210,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -253,6 +251,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -275,7 +274,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -286,6 +286,8 @@ CONFIG_TCP_CONG_BIC=y
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -302,10 +304,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -329,6 +334,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -338,11 +348,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -364,6 +369,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -420,7 +428,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -443,7 +450,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -486,7 +492,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -714,6 +720,7 @@ CONFIG_SERIO_RAW=m
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
# CONFIG_SERIAL_8250_CS is not set
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -725,6 +732,7 @@ CONFIG_SERIAL_8250_AU1X00=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
@@ -790,10 +798,6 @@ CONFIG_SYNCLINK_CS=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -802,6 +806,7 @@ CONFIG_SYNCLINK_CS=m
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -825,9 +830,11 @@ CONFIG_SND_SEQ_DUMMY=m
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
@@ -846,6 +853,7 @@ CONFIG_SND_MTPAV=m
# PCI devices
#
# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ATIIXP is not set
# CONFIG_SND_ATIIXP_MODEM is not set
@@ -877,6 +885,7 @@ CONFIG_SND_MTPAV=m
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
# CONFIG_SND_RME32 is not set
# CONFIG_SND_RME96 is not set
# CONFIG_SND_RME9652 is not set
@@ -905,34 +914,22 @@ CONFIG_SND_AU1X00=m
# Open Sound System
#
CONFIG_SOUND_PRIME=y
-CONFIG_OBSOLETE_OSS_DRIVER=y
# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_EMU10K1 is not set
# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_AU1000 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
-# CONFIG_SOUND_ALI5455 is not set
-# CONFIG_SOUND_FORTE is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_AD1980 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=y
# CONFIG_USB_DEBUG is not set
@@ -958,7 +955,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
#
# USB Device Class drivers
#
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
@@ -985,9 +981,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
CONFIG_USB_YEALINK=m
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -1001,15 +995,6 @@ CONFIG_USB_YEALINK=m
# CONFIG_USB_MDC800 is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1059,13 +1044,31 @@ CONFIG_USB_LD=m
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1123,7 +1126,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1232,6 +1234,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 8dc1f18badf..8130e23dc25 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:00 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:00 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_DB1550=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -115,11 +117,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -137,7 +139,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +154,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -166,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -182,7 +180,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -191,6 +188,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -210,7 +209,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -252,6 +250,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -274,7 +273,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -285,6 +285,8 @@ CONFIG_TCP_CONG_BIC=y
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -301,10 +303,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -328,6 +333,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -337,11 +347,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -363,6 +368,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -419,7 +427,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -442,7 +449,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -489,7 +495,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -754,6 +760,7 @@ CONFIG_SERIO_RAW=m
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
# CONFIG_SERIAL_8250_CS is not set
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -765,6 +772,7 @@ CONFIG_SERIAL_8250_AU1X00=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
@@ -830,10 +838,6 @@ CONFIG_SYNCLINK_CS=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -858,6 +862,7 @@ CONFIG_SYNCLINK_CS=m
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -875,13 +880,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -939,7 +962,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1048,6 +1070,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ddb5476_defconfig b/arch/mips/configs/ddb5476_defconfig
index 8fae63e47e5..8d88ac1bbfe 100644
--- a/arch/mips/configs/ddb5476_defconfig
+++ b/arch/mips/configs/ddb5476_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:02 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:00 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_DDB5476=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,7 +116,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -136,7 +137,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -152,6 +152,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -165,10 +166,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -183,6 +180,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -202,7 +201,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_ISA=y
CONFIG_MMU=y
@@ -231,6 +229,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -252,12 +251,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -269,6 +271,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -278,11 +285,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -303,6 +305,9 @@ CONFIG_IEEE80211=y
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=y
CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -348,7 +353,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -571,6 +576,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -580,6 +586,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -638,10 +645,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -659,6 +662,7 @@ CONFIG_FB=y
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_CIRRUS is not set
@@ -670,7 +674,6 @@ CONFIG_FB=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
@@ -708,6 +711,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -725,13 +729,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -776,7 +798,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -840,6 +861,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="ip=any"
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index a0fcd44e770..8c911b67141 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:02 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:01 2006
#
CONFIG_MIPS=y
@@ -65,6 +65,8 @@ CONFIG_DDB5477=y
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_DDB5477_BUS_FREQUENCY=0
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,7 +116,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -136,7 +137,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -152,6 +152,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -165,10 +166,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -183,6 +180,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -202,7 +201,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -230,6 +228,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -251,12 +250,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -268,6 +270,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -277,11 +284,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -302,6 +304,9 @@ CONFIG_IEEE80211=y
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=y
CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -346,7 +351,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -556,6 +561,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -565,6 +571,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -623,10 +630,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -657,6 +660,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -674,13 +678,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -725,7 +747,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -792,6 +813,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="ip=any"
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 5a181eadd43..d838496e114 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:03 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:01 2006
#
CONFIG_MIPS=y
@@ -63,11 +63,13 @@ CONFIG_MACH_DECSTATION=y
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_EARLY_PRINTK=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_EARLY_PRINTK=y
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
@@ -113,7 +115,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_WB=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -135,7 +136,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -151,6 +151,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -165,10 +166,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -180,7 +177,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -189,6 +185,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -233,11 +231,10 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -254,12 +251,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -271,6 +271,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -280,11 +285,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -305,6 +305,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -345,7 +348,7 @@ CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -567,10 +570,6 @@ CONFIG_RTC=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -588,6 +587,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_S1D13XXX is not set
@@ -617,6 +617,7 @@ CONFIG_LOGO_DEC_CLUT224=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -633,12 +634,30 @@ CONFIG_LOGO_DEC_CLUT224=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -686,7 +705,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -705,7 +723,6 @@ CONFIG_RELAYFS_FS=m
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
CONFIG_UFS_FS=y
-CONFIG_UFS_FS_WRITE=y
#
# Network File Systems
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index 8fbfc06a6a2..0760f431891 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:04 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:08:20 2006
#
CONFIG_MIPS=y
@@ -70,6 +70,8 @@ CONFIG_CASIO_E55=y
# CONFIG_VICTOR_MPC30X is not set
# CONFIG_ZAO_CAPCELLA is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -88,7 +90,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_MIPS64_R2 is not set
# CONFIG_CPU_R3000 is not set
# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
+CONFIG_CPU_VR41XX=y
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
@@ -101,18 +103,21 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
#
-# CONFIG_32BIT is not set
+CONFIG_32BIT=y
# CONFIG_64BIT is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -133,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -144,11 +148,10 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -162,10 +165,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -177,7 +176,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -185,6 +183,9 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -219,85 +220,12 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
#
# Networking
#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD 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_TUNNEL=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 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
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
+# CONFIG_NET is not set
#
# Device Drivers
@@ -313,7 +241,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Connector - unified userspace <-> kernelspace linker
#
-CONFIG_CONNECTOR=m
#
# Memory Technology Devices (MTD)
@@ -335,11 +262,11 @@ CONFIG_CONNECTOR=m
#
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# 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
@@ -398,81 +325,8 @@ CONFIG_IDE_GENERIC=y
#
#
-# 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
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_DM9000 is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
# ISDN subsystem
#
-# CONFIG_ISDN is not set
#
# Telephony Support
@@ -508,11 +362,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
@@ -531,6 +381,10 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -565,6 +419,7 @@ CONFIG_WATCHDOG=y
#
# Ftape, the floppy tape device driver
#
+CONFIG_GPIO_VR41XX=y
# CONFIG_RAW_DRIVER is not set
#
@@ -600,10 +455,6 @@ CONFIG_WATCHDOG=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -611,7 +462,6 @@ CONFIG_WATCHDOG=y
#
# Digital Video Broadcasting Devices
#
-# CONFIG_DVB is not set
#
# Graphics support
@@ -635,6 +485,7 @@ CONFIG_DUMMY_CONSOLE=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -651,12 +502,30 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -669,13 +538,12 @@ CONFIG_EXT2_FS=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
-# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=m
@@ -698,10 +566,9 @@ CONFIG_FUSE_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -722,29 +589,6 @@ CONFIG_RELAYFS_FS=m
# CONFIG_UFS_FS is not set
#
-# Network File Systems
-#
-CONFIG_NFS_FS=m
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=m
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_LOCKD=m
-CONFIG_EXPORTFS=m
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=m
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
@@ -767,44 +611,20 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="console=ttyVR0,19200 mem=8M"
#
# Security options
#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
#
# Hardware crypto devices
@@ -814,8 +634,6 @@ CONFIG_CRYPTO_CRC32C=m
# Library routines
#
# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
index f2d43be6900..7067f608b22 100644
--- a/arch/mips/configs/ev64120_defconfig
+++ b/arch/mips/configs/ev64120_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:05 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:02 2006
#
CONFIG_MIPS=y
@@ -65,6 +65,8 @@ CONFIG_MIPS_EV64120=y
# CONFIG_TOSHIBA_RBTX4938 is not set
# CONFIG_EVB_PCI1 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -116,7 +118,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -138,7 +139,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -154,6 +154,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -182,7 +179,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
# CONFIG_KMOD is not set
@@ -191,6 +187,8 @@ CONFIG_MODULE_SRCVERSION_ALL=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -210,7 +208,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -238,6 +235,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -258,12 +256,15 @@ CONFIG_IP_PNP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -275,6 +276,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -284,11 +290,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -309,6 +310,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -352,7 +356,7 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -550,6 +554,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -559,6 +564,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -617,10 +623,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -651,6 +653,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -668,13 +671,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -719,7 +740,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -783,6 +803,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal ip=192.168.1.211:192.168.1.1:::gt::"
diff --git a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig
index ac5841c4b69..00b56ed0e63 100644
--- a/arch/mips/configs/ev96100_defconfig
+++ b/arch/mips/configs/ev96100_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:06 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:03 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_EV96100=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -119,7 +121,6 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -142,7 +143,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -158,6 +158,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -171,10 +172,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -186,7 +183,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
# CONFIG_KMOD is not set
@@ -195,6 +191,8 @@ CONFIG_MODULE_SRCVERSION_ALL=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -240,6 +238,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -260,12 +259,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -277,6 +279,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -286,11 +293,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -311,6 +313,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -349,7 +354,7 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -567,10 +572,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -601,6 +602,7 @@ CONFIG_DUMMY_CONSOLE=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -617,12 +619,30 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -667,7 +687,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -731,6 +750,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 42d5cd7927c..607e2985ffe 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:51 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:54 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_SGI_IP22=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARC=y
CONFIG_DMA_NONCOHERENT=y
@@ -121,7 +123,6 @@ CONFIG_BOARD_SCACHE=y
CONFIG_IP22_CPU_SCACHE=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -143,7 +144,6 @@ CONFIG_PREEMPT_VOLUNTARY=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -160,6 +160,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -173,10 +174,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -188,7 +185,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -197,6 +193,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -242,6 +240,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -264,6 +263,7 @@ CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -305,9 +305,12 @@ CONFIG_IP_VS_NQ=m
CONFIG_IP_VS_FTP=m
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -330,11 +333,14 @@ CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -357,20 +363,19 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_MATCH_OWNER=m
CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -388,6 +393,7 @@ CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_NAT_TFTP=m
CONFIG_IP_NF_NAT_AMANDA=m
CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
@@ -408,12 +414,10 @@ CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
CONFIG_IP6_NF_MATCH_OWNER=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_TARGET_REJECT=m
@@ -435,6 +439,11 @@ CONFIG_IP_SCTP=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -444,11 +453,6 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
CONFIG_NET_DIVERT=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -508,6 +512,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -546,7 +553,7 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -812,10 +819,6 @@ CONFIG_MAX_RAW_DEVS=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -857,6 +860,7 @@ CONFIG_LOGO_SGI_CLUT224=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -873,12 +877,30 @@ CONFIG_LOGO_SGI_CLUT224=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -944,7 +966,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -963,7 +984,6 @@ CONFIG_EFS_FS=m
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
@@ -1078,6 +1098,7 @@ CONFIG_NLS_UTF8=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 8c40590737e..f724b4b2ecf 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc4
-# Tue Feb 21 13:44:31 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:04 2006
#
CONFIG_MIPS=y
@@ -70,6 +70,8 @@ CONFIG_NUMA=y
# CONFIG_REPLICATE_KTEXT is not set
# CONFIG_REPLICATE_EXHANDLERS is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARC=y
CONFIG_DMA_IP27=y
@@ -123,6 +125,7 @@ CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_NODES_SHIFT=6
CONFIG_SELECT_MEMORY_MODEL=y
# CONFIG_FLATMEM_MANUAL is not set
CONFIG_DISCONTIGMEM_MANUAL=y
@@ -162,6 +165,7 @@ CONFIG_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CPUSETS=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -175,10 +179,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -190,7 +190,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -199,6 +198,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -219,7 +219,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -237,6 +236,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
@@ -274,12 +274,15 @@ CONFIG_IP_PNP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -363,6 +366,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -407,7 +413,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -473,7 +479,6 @@ CONFIG_SCSI_SAS_ATTRS=m
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
CONFIG_SCSI_QLOGIC_1280=y
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -491,6 +496,7 @@ CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=y
+CONFIG_MD_RAID5_RESHAPE=y
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -654,6 +660,7 @@ CONFIG_SERIO_RAW=m
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
@@ -727,10 +734,6 @@ CONFIG_SGI_IP27_RTC=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -755,6 +758,7 @@ CONFIG_SGI_IP27_RTC=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -772,17 +776,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -840,7 +858,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -922,6 +939,7 @@ CONFIG_SGI_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 7fdcaf51fac..8f11d3565b2 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:09 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:05 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_SGI_IP32=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARC=y
CONFIG_DMA_IP32=y
@@ -142,7 +144,6 @@ CONFIG_PREEMPT_VOLUNTARY=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -159,6 +160,7 @@ CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -172,10 +174,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -189,6 +187,7 @@ CONFIG_BASE_SMALL=0
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -208,7 +207,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -226,6 +224,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
+# CONFIG_BUILD_ELF64 is not set
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
@@ -240,6 +239,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -261,12 +261,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -278,6 +281,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -287,11 +295,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -312,6 +315,9 @@ CONFIG_IEEE80211=y
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=y
CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -357,7 +363,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -428,7 +434,6 @@ CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -615,6 +620,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -624,6 +630,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -682,10 +689,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -716,6 +719,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -733,13 +737,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -784,7 +806,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -861,6 +882,8 @@ CONFIG_SGI_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig
index c716996d9ec..757adf23853 100644
--- a/arch/mips/configs/it8172_defconfig
+++ b/arch/mips/configs/it8172_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:10 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:05 2006
#
CONFIG_MIPS=y
@@ -65,6 +65,8 @@ CONFIG_MIPS_ITE8172=y
# CONFIG_TOSHIBA_RBTX4938 is not set
# CONFIG_IT8172_REVC is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -115,7 +117,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -137,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -154,6 +154,7 @@ CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -183,7 +180,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -192,6 +188,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -237,6 +235,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -258,12 +257,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -275,6 +277,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -284,11 +291,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -309,6 +311,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -387,7 +392,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -424,7 +428,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -666,10 +670,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -704,7 +704,6 @@ CONFIG_SOUND=y
# Open Sound System
#
CONFIG_SOUND_PRIME=y
-# CONFIG_OBSOLETE_OSS_DRIVER is not set
CONFIG_SOUND_IT8172=y
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
@@ -714,6 +713,7 @@ CONFIG_SOUND_IT8172=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -730,12 +730,30 @@ CONFIG_SOUND_IT8172=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -780,7 +798,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -846,6 +863,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig
index a8376d125e1..021761a8a23 100644
--- a/arch/mips/configs/ivr_defconfig
+++ b/arch/mips/configs/ivr_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:11 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:06 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_IVR=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -112,7 +114,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -134,7 +135,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -151,6 +151,7 @@ CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -164,10 +165,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -179,7 +176,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -188,6 +184,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -207,7 +205,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -235,6 +232,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -256,12 +254,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -273,6 +274,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -282,11 +288,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -307,6 +308,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -350,7 +354,7 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -565,6 +569,7 @@ CONFIG_IT8172_SCR1=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -574,6 +579,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -631,10 +637,6 @@ CONFIG_RTC=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -665,6 +667,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -682,13 +685,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -733,7 +754,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -797,6 +817,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
index 316015379db..08f6c30b0ab 100644
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ b/arch/mips/configs/jaguar-atx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:12 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:06 2006
#
CONFIG_MIPS=y
@@ -65,6 +65,8 @@ CONFIG_MOMENCO_JAGUAR_ATX=y
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_JAGUAR_DMALOW=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -122,7 +124,6 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -144,7 +145,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -160,6 +160,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
@@ -172,10 +173,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -186,7 +183,6 @@ CONFIG_BASE_SMALL=0
#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -195,6 +191,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -214,7 +212,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -241,6 +238,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -260,16 +258,19 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
# CONFIG_NETFILTER is not set
@@ -338,10 +339,9 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
CONFIG_ATA_OVER_ETH=m
#
@@ -423,6 +423,7 @@ CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_FORCEDETH is not set
# CONFIG_DGRS is not set
CONFIG_EEPRO100=y
# CONFIG_E100 is not set
@@ -446,6 +447,7 @@ CONFIG_EEPRO100=y
# CONFIG_HAMACHI is not set
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
@@ -514,6 +516,7 @@ CONFIG_MV643XX_ETH_2=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -523,6 +526,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -579,10 +583,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -607,6 +607,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -624,12 +625,29 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
#
@@ -672,7 +690,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
#
# Miscellaneous filesystems
@@ -718,6 +735,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 53fbef1ac25..38b1e026e10 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:13 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:07 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_TOSHIBA_JMR3927=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -111,7 +113,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -133,7 +134,6 @@ CONFIG_RTC_DS1742=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -149,6 +149,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -162,10 +163,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -180,6 +177,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -199,7 +198,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -227,6 +225,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -248,12 +247,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -265,6 +267,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -274,11 +281,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -299,6 +301,9 @@ CONFIG_IEEE80211=y
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=y
CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -343,7 +348,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -551,7 +556,12 @@ CONFIG_SERIAL_NONSTANDARD=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_TXX9=y
CONFIG_HAS_TXX9_SERIAL=y
+# CONFIG_SERIAL_TXX9_CONSOLE is not set
+# CONFIG_SERIAL_TXX9_STDSERIAL is not set
+# CONFIG_SERIAL_JSM is not set
# CONFIG_UNIX98_PTYS is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -610,10 +620,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -631,6 +637,7 @@ CONFIG_FB=y
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_CIRRUS is not set
@@ -642,7 +649,6 @@ CONFIG_FB=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
@@ -679,6 +685,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -696,13 +703,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -745,7 +770,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -809,6 +833,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
index ef0fa9fc79d..4d25990a0a0 100644
--- a/arch/mips/configs/lasat200_defconfig
+++ b/arch/mips/configs/lasat200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:14 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:07 2006
#
CONFIG_MIPS=y
@@ -68,6 +68,8 @@ CONFIG_PICVUE_PROC=y
CONFIG_DS1603=y
CONFIG_LASAT_SYSCTL=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -119,7 +121,6 @@ CONFIG_BOARD_SCACHE=y
CONFIG_R5000_CPU_SCACHE=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -141,7 +142,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -157,6 +157,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -170,10 +171,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -186,7 +183,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -195,6 +191,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -214,7 +212,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -242,6 +239,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -259,12 +257,15 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -276,6 +277,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -285,11 +291,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -310,6 +311,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -366,7 +370,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -389,7 +392,6 @@ CONFIG_MTD_LASAT=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -430,7 +432,7 @@ CONFIG_MTD_LASAT=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -672,6 +674,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -681,6 +684,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -739,10 +743,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -773,6 +773,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -790,13 +791,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -847,7 +866,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -914,6 +932,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 367d279efdd..977f52be51d 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:15 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:08 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_MALTA=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_DMA_NONCOHERENT=y
@@ -128,16 +130,21 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_MIPS_MT=y
+# CONFIG_MIPS_MT_SMTC is not set
# CONFIG_MIPS_MT_SMP is not set
CONFIG_MIPS_VPE_LOADER=y
+CONFIG_MIPS_MT_FPAFF=y
CONFIG_MIPS_VPE_LOADER_TOM=y
CONFIG_MIPS_VPE_APSP_API=y
+CONFIG_MIPS_APSP_KSPD=y
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_MIPSR2_IRQ_VI is not set
+# CONFIG_CPU_MIPSR2_IRQ_EI is not set
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -155,7 +162,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -171,6 +177,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -184,10 +191,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -199,7 +202,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -208,6 +210,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -227,7 +231,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -255,6 +258,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -287,6 +291,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -328,9 +333,12 @@ CONFIG_IP_VS_NQ=m
CONFIG_IP_VS_FTP=m
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -354,11 +362,14 @@ CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
@@ -382,20 +393,19 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_MATCH_OWNER=m
CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -413,6 +423,7 @@ CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_NAT_TFTP=m
CONFIG_IP_NF_NAT_AMANDA=m
CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
@@ -433,12 +444,10 @@ CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
CONFIG_IP6_NF_MATCH_OWNER=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_TARGET_REJECT=m
@@ -484,6 +493,11 @@ CONFIG_IP_SCTP=m
# 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=m
CONFIG_VLAN_8021Q=m
@@ -498,11 +512,6 @@ CONFIG_IPDDP_ENCAP=y
CONFIG_IPDDP_DECAP=y
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
CONFIG_NET_DIVERT=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -562,6 +571,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -734,7 +746,6 @@ CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -753,6 +764,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=m
+CONFIG_MD_RAID5_RESHAPE=y
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -956,6 +968,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -965,6 +978,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -1022,10 +1036,6 @@ CONFIG_RTC=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -1056,6 +1066,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -1073,13 +1084,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1154,7 +1183,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1174,7 +1202,6 @@ CONFIG_VXFS_FS=m
# CONFIG_QNX4FS_FS is not set
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
@@ -1266,6 +1293,7 @@ CONFIG_NLS_UTF8=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index fe78961762b..00560e0143f 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:16 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:09 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_SIM=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,16 +116,19 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_MIPS_MT=y
+# CONFIG_MIPS_MT_SMTC is not set
# CONFIG_MIPS_MT_SMP is not set
CONFIG_MIPS_VPE_LOADER=y
+CONFIG_MIPS_MT_FPAFF=y
CONFIG_MIPS_VPE_LOADER_TOM=y
CONFIG_MIPS_VPE_APSP_API=y
+CONFIG_MIPS_APSP_KSPD=y
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -141,7 +146,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -157,6 +161,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -171,10 +176,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -186,7 +187,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -195,6 +195,7 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -238,6 +239,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -268,12 +270,15 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -290,6 +295,11 @@ CONFIG_IP_SCTP=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -299,11 +309,6 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
CONFIG_NET_DIVERT=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -397,7 +402,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=y
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -532,7 +537,7 @@ CONFIG_SERIO_SERPORT=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=1
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
# CONFIG_SERIAL_8250_EXTENDED is not set
#
@@ -596,10 +601,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -624,6 +625,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# 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'
@@ -640,12 +642,30 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -690,8 +710,6 @@ CONFIG_PROC_FS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
-# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index e4620e7f0a5..286a018375b 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:17 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:09 2006
#
CONFIG_MIPS=y
@@ -72,6 +72,8 @@ CONFIG_VICTOR_MPC30X=y
CONFIG_PCI_VR41XX=y
CONFIG_VRC4173=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -90,7 +92,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_MIPS64_R2 is not set
# CONFIG_CPU_R3000 is not set
# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
+CONFIG_CPU_VR41XX=y
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
@@ -103,18 +105,21 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
#
-# CONFIG_32BIT is not set
+CONFIG_32BIT=y
# CONFIG_64BIT is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -135,7 +140,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -151,6 +155,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -164,10 +169,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -179,7 +180,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -187,6 +187,9 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -206,7 +209,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -225,6 +227,7 @@ CONFIG_PCMCIA_IOCTL=y
# CONFIG_YENTA is not set
# CONFIG_PD6729 is not set
# CONFIG_I82092 is not set
+# CONFIG_PCMCIA_VRC4173 is not set
#
# PCI Hotplug Support
@@ -236,6 +239,7 @@ CONFIG_PCMCIA_IOCTL=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
#
# Networking
@@ -245,6 +249,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -264,12 +269,15 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -281,6 +289,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -290,11 +303,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -316,6 +324,9 @@ CONFIG_IEEE80211=m
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -360,7 +371,7 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
CONFIG_ATA_OVER_ETH=m
@@ -475,6 +486,7 @@ CONFIG_MII=m
# Wireless LAN (non-hamradio)
#
CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
#
# Obsolete Wireless cards support (pre-802.11)
@@ -513,6 +525,7 @@ CONFIG_PCMCIA_HERMES=m
#
# CONFIG_PRISM54 is not set
# CONFIG_HOSTAP is not set
+# CONFIG_BCM43XX is not set
CONFIG_NET_WIRELESS=y
#
@@ -604,6 +617,8 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_VR41XX is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -634,6 +649,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_SYNCLINK_CS is not set
# CONFIG_CARDMAN_4000 is not set
# CONFIG_CARDMAN_4040 is not set
+# CONFIG_GPIO_VR41XX is not set
# CONFIG_RAW_DRIVER is not set
#
@@ -669,10 +685,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -681,6 +693,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -703,6 +716,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=m
# CONFIG_USB_DEBUG is not set
@@ -756,9 +770,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -772,15 +784,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_MDC800 is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -832,13 +835,31 @@ CONFIG_USB_PEGASUS=m
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -883,7 +904,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -946,6 +966,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="mem=32M console=ttyVR0,19200"
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
index 925d8adef88..1ce4310fd92 100644
--- a/arch/mips/configs/ocelot_3_defconfig
+++ b/arch/mips/configs/ocelot_3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:18 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:10 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MOMENCO_OCELOT_3=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -120,7 +122,6 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -144,7 +145,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -161,6 +161,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -174,10 +175,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -189,7 +186,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -198,6 +194,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -217,7 +215,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -245,6 +242,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -266,6 +264,7 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -278,9 +277,12 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_IP_VS is not set
CONFIG_IPV6=m
# CONFIG_IPV6_PRIVACY is not set
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
CONFIG_NETFILTER=y
@@ -299,10 +301,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -332,6 +337,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -341,11 +351,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -367,6 +372,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -411,7 +419,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
CONFIG_ATA_OVER_ETH=m
@@ -475,7 +483,6 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -690,6 +697,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -699,6 +707,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -756,10 +765,6 @@ CONFIG_RTC=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -777,6 +782,7 @@ CONFIG_FB=y
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
CONFIG_FB_MODE_HELPERS=y
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_CIRRUS is not set
@@ -788,7 +794,6 @@ CONFIG_FB_MODE_HELPERS=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
@@ -832,6 +837,7 @@ CONFIG_LOGO_LINUX_CLUT224=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -849,13 +855,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -914,7 +938,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1025,6 +1048,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="ip=any root=nfs"
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
index ee1cf9b9eb9..8a6aa5012f8 100644
--- a/arch/mips/configs/ocelot_c_defconfig
+++ b/arch/mips/configs/ocelot_c_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:19 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:10 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MOMENCO_OCELOT_C=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -139,7 +141,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -155,6 +156,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -168,10 +170,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -185,6 +183,7 @@ CONFIG_BASE_SMALL=0
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -204,7 +203,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -222,6 +220,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
@@ -236,6 +235,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -256,12 +256,15 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -273,6 +276,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -282,11 +290,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -307,6 +310,9 @@ CONFIG_IEEE80211=y
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=y
CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -351,7 +357,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -542,6 +548,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -551,6 +558,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -609,10 +617,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -643,6 +647,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -660,13 +665,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -711,7 +734,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -778,6 +800,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index d80ff278f2a..f9ee35eeb76 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:20 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:11 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MOMENCO_OCELOT=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -121,7 +123,6 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -144,7 +145,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -160,6 +160,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -173,10 +174,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -191,6 +188,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -236,6 +235,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -256,12 +256,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -273,6 +276,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -282,11 +290,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -307,6 +310,9 @@ CONFIG_IEEE80211=y
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=y
CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -346,7 +352,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -563,10 +569,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -597,6 +599,7 @@ CONFIG_DUMMY_CONSOLE=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -613,12 +616,30 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -663,7 +684,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -730,6 +750,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig
index c0f508d180c..b48bdee2411 100644
--- a/arch/mips/configs/ocelot_g_defconfig
+++ b/arch/mips/configs/ocelot_g_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:21 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:11 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MOMENCO_OCELOT_G=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -142,7 +144,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -158,6 +159,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -171,10 +173,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -188,6 +186,7 @@ CONFIG_BASE_SMALL=0
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -207,7 +206,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -225,6 +223,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
@@ -239,6 +238,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -259,12 +259,15 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -276,6 +279,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -285,11 +293,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -310,6 +313,9 @@ CONFIG_IEEE80211=y
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=y
CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -354,7 +360,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -545,6 +551,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -554,6 +561,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -612,10 +620,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -646,6 +650,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -663,13 +668,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -714,7 +737,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -781,6 +803,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 194b3c772bb..01aac40634b 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:22 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:12 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_PB1100=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -116,11 +118,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -138,7 +140,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -154,6 +155,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +169,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -183,7 +181,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -192,6 +189,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -247,6 +246,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -269,7 +269,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -280,6 +281,8 @@ CONFIG_TCP_CONG_BIC=y
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -296,10 +299,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -323,6 +329,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -332,11 +343,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -358,6 +364,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -414,7 +423,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -436,7 +444,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -473,7 +480,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -716,10 +723,6 @@ CONFIG_SYNCLINK_CS=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -750,6 +753,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB is not set
#
@@ -767,12 +771,30 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -830,7 +852,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -939,6 +960,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index 8985725e6a9..398c3c265b9 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:24 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:13 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_PB1500=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -115,11 +117,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -137,7 +139,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +154,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -166,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -182,7 +180,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -191,6 +188,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -210,7 +209,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -253,6 +251,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -275,7 +274,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -286,6 +286,8 @@ CONFIG_TCP_CONG_BIC=y
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -302,10 +304,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -329,6 +334,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -338,11 +348,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -364,6 +369,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -420,7 +428,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -443,7 +450,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -485,7 +491,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -750,6 +756,7 @@ CONFIG_SERIO_RAW=m
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
# CONFIG_SERIAL_8250_CS is not set
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -761,6 +768,7 @@ CONFIG_SERIAL_8250_AU1X00=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
@@ -826,10 +834,6 @@ CONFIG_SYNCLINK_CS=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -854,6 +858,7 @@ CONFIG_SYNCLINK_CS=m
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -871,13 +876,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -935,7 +958,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1044,6 +1066,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index adbf997b540..ea282a53bb6 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:25 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:13 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_PB1550=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -115,11 +117,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -137,7 +139,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +154,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -166,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -182,7 +180,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -191,6 +188,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -210,7 +209,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -253,6 +251,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -275,7 +274,8 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -286,6 +286,8 @@ CONFIG_TCP_CONG_BIC=y
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -302,10 +304,13 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -329,6 +334,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -338,11 +348,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -364,6 +369,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -420,7 +428,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -443,7 +450,6 @@ CONFIG_MTD_ALCHEMY=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -485,7 +491,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -742,6 +748,7 @@ CONFIG_SERIO_RAW=m
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
# CONFIG_SERIAL_8250_CS is not set
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -753,6 +760,7 @@ CONFIG_SERIAL_8250_AU1X00=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
@@ -818,10 +826,6 @@ CONFIG_SYNCLINK_CS=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -846,6 +850,7 @@ CONFIG_SYNCLINK_CS=m
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -863,13 +868,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -927,7 +950,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1036,6 +1058,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index b5db700450b..4c57e564db0 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:26 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:14 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_PNX8550_JBS=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,11 +116,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -136,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +154,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +169,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -181,7 +179,6 @@ CONFIG_BASE_SMALL=0
#
CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -190,6 +187,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -209,7 +208,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_DEBUG is not set
CONFIG_MMU=y
@@ -238,6 +236,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -257,12 +256,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -274,6 +276,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -283,11 +290,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -469,7 +471,6 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -671,6 +672,7 @@ CONFIG_HW_CONSOLE=y
# Non-8250 serial port support
#
# CONFIG_SERIAL_IP3106 is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -723,6 +725,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
@@ -730,10 +733,6 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -742,6 +741,7 @@ CONFIG_HWMON=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -764,6 +764,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -827,9 +828,7 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -844,15 +843,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -902,13 +892,31 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -956,7 +964,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1067,6 +1074,7 @@ CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig
index 4187287f076..3c8f35162fe 100644
--- a/arch/mips/configs/pnx8550-v2pci_defconfig
+++ b/arch/mips/configs/pnx8550-v2pci_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:28 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:14 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_PNX8550_V2PCI=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,12 +116,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_ADVANCED=y
CONFIG_CPU_HAS_LLSC=y
-# CONFIG_CPU_HAS_WB is not set
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -137,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -154,6 +154,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +168,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -181,7 +178,6 @@ CONFIG_BASE_SMALL=0
#
CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -190,6 +186,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -209,7 +207,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
CONFIG_MMU=y
#
@@ -237,6 +234,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -256,6 +254,7 @@ CONFIG_IP_PNP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -268,9 +267,12 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_IP_VS is not set
CONFIG_IPV6=m
# CONFIG_IPV6_PRIVACY is not set
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
CONFIG_NETFILTER=y
@@ -287,10 +289,12 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -320,6 +324,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -329,11 +338,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -521,7 +525,6 @@ CONFIG_AIC7XXX_DEBUG_MASK=0
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -757,6 +760,7 @@ CONFIG_SERIAL_NONSTANDARD=y
# Non-8250 serial port support
#
# CONFIG_SERIAL_IP3106 is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -816,7 +820,6 @@ CONFIG_I2C_ALGOBIT=m
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -835,9 +838,7 @@ CONFIG_I2C_ALGOBIT=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -867,6 +868,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
@@ -901,10 +903,6 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -913,6 +911,7 @@ CONFIG_HWMON=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -922,6 +921,7 @@ CONFIG_FB=y
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_CIRRUS is not set
@@ -933,7 +933,6 @@ CONFIG_FB=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
@@ -970,6 +969,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -1030,9 +1030,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -1047,15 +1045,6 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1106,13 +1095,31 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1171,7 +1178,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1280,6 +1286,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index 31f5afabafa..4bcc01dea04 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Sun Feb 12 19:18:55 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:15 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_QEMU=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_COHERENT=y
CONFIG_GENERIC_ISA_DMA=y
@@ -115,16 +117,17 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_SMP is not set
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
@@ -147,6 +150,7 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
@@ -159,10 +163,6 @@ CONFIG_ELF_CORE=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SHMEM is not set
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=1
@@ -177,6 +177,8 @@ CONFIG_BASE_SMALL=1
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -196,6 +198,7 @@ CONFIG_DEFAULT_IOSCHED="noop"
#
CONFIG_ISA=y
CONFIG_MMU=y
+CONFIG_I8253=y
#
# PCCARD (PCMCIA/CardBus) support
@@ -241,12 +244,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
@@ -308,7 +314,7 @@ CONFIG_PROC_EVENTS=y
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -530,10 +536,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -552,6 +554,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
@@ -565,6 +568,7 @@ CONFIG_DUMMY_CONSOLE=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -581,15 +585,28 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
#
#
@@ -632,7 +649,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
#
# Miscellaneous filesystems
@@ -680,6 +696,8 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index b126f763cf5..3d441932e43 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:30 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:16 2006
#
CONFIG_MIPS=y
@@ -71,6 +71,8 @@ CONFIG_TOSHIBA_RBTX4938_MPLEX_PIO58_61=y
# CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND is not set
# CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -121,10 +123,9 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
-CONFIG_CPU_ADVANCED=y
CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_WB=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -145,7 +146,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -162,6 +162,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -175,10 +176,6 @@ CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -190,7 +187,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
#
CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -199,6 +195,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -218,7 +216,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
CONFIG_ISA=y
CONFIG_MMU=y
@@ -247,6 +244,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -267,6 +265,7 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -279,9 +278,12 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_IP_VS is not set
CONFIG_IPV6=m
# CONFIG_IPV6_PRIVACY is not set
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
CONFIG_NETFILTER=y
@@ -300,10 +302,12 @@ CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -333,6 +337,11 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -342,11 +351,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -369,6 +373,9 @@ CONFIG_IEEE80211=m
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -425,7 +432,6 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
@@ -447,7 +453,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -702,6 +707,7 @@ CONFIG_NET_PCI=y
# Wireless LAN (non-hamradio)
#
CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
#
# Obsolete Wireless cards support (pre-802.11)
@@ -715,6 +721,8 @@ CONFIG_NET_RADIO=y
#
# CONFIG_IPW2100 is not set
CONFIG_IPW2200=m
+# CONFIG_IPW2200_MONITOR is not set
+# CONFIG_IPW_QOS is not set
# CONFIG_IPW2200_DEBUG is not set
# CONFIG_HERMES is not set
# CONFIG_ATMEL is not set
@@ -724,6 +732,7 @@ CONFIG_IPW2200=m
#
# CONFIG_PRISM54 is not set
# CONFIG_HOSTAP is not set
+# CONFIG_BCM43XX is not set
CONFIG_NET_WIRELESS=y
#
@@ -821,7 +830,12 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_TXX9=y
CONFIG_HAS_TXX9_SERIAL=y
+# CONFIG_SERIAL_TXX9_CONSOLE is not set
+# CONFIG_SERIAL_TXX9_STDSERIAL is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -874,6 +888,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
@@ -881,10 +896,6 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -893,6 +904,7 @@ CONFIG_HWMON=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -902,6 +914,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_CIRRUS is not set
@@ -913,7 +926,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
CONFIG_FB_ATY=y
@@ -934,6 +946,7 @@ CONFIG_FB_ATY_CT=y
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE is not set
@@ -954,6 +967,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -1003,9 +1017,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
CONFIG_USB_YEALINK=m
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -1019,15 +1031,6 @@ CONFIG_USB_YEALINK=m
# CONFIG_USB_MDC800 is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1078,13 +1081,31 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1148,7 +1169,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1266,6 +1286,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 463ed3dbf6a..edfb9679a25 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:31 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:16 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_SNI_RM200_PCI=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARC=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
@@ -122,7 +124,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -145,7 +146,6 @@ CONFIG_PREEMPT_VOLUNTARY=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -163,6 +163,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -176,10 +177,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -191,7 +188,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -200,6 +196,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -220,10 +218,10 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_HW_HAS_EISA=y
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_ISA=y
# CONFIG_EISA is not set
CONFIG_MMU=y
+CONFIG_I8253=y
#
# PCCARD (PCMCIA/CardBus) support
@@ -250,6 +248,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=m
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -272,6 +271,7 @@ CONFIG_IP_PIMSM_V2=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
CONFIG_INET_TUNNEL=m
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -284,9 +284,12 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_IP_VS is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -309,11 +312,14 @@ CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
@@ -337,20 +343,19 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_MATCH_OWNER=m
CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -368,6 +373,7 @@ CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_NAT_TFTP=m
CONFIG_IP_NF_NAT_AMANDA=m
CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
@@ -388,12 +394,10 @@ CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
CONFIG_IP6_NF_MATCH_OWNER=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_TARGET_REJECT=m
@@ -439,21 +443,22 @@ CONFIG_BRIDGE_EBT_ULOG=m
# 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
# CONFIG_VLAN_8021Q is not set
CONFIG_DECNET=m
# CONFIG_DECNET_ROUTER 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
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -533,6 +538,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -620,6 +628,7 @@ CONFIG_BLK_DEV_UB=m
CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -700,12 +709,11 @@ CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -731,6 +739,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=m
+CONFIG_MD_RAID5_RESHAPE=y
# CONFIG_MD_RAID6 is not set
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -965,6 +974,7 @@ CONFIG_HW_CONSOLE=y
# Serial drivers
#
CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_PCI=m
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
@@ -977,6 +987,7 @@ CONFIG_SERIAL_8250_RSA=y
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=m
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -1027,12 +1038,19 @@ CONFIG_RTC=m
# Dallas's 1-wire bus
#
CONFIG_W1=m
-CONFIG_W1_MATROX=m
-CONFIG_W1_DS9490=m
-# CONFIG_W1_DS9490_BRIDGE is not set
-CONFIG_W1_THERM=m
-CONFIG_W1_SMEM=m
-# CONFIG_W1_DS2433 is not set
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_MATROX is not set
+# CONFIG_W1_MASTER_DS9490 is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
#
# Hardware Monitoring support
@@ -1045,10 +1063,6 @@ CONFIG_W1_SMEM=m
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -1057,6 +1071,7 @@ CONFIG_W1_SMEM=m
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+CONFIG_USB_DABUSB=m
#
# Graphics support
@@ -1067,6 +1082,7 @@ CONFIG_W1_SMEM=m
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
@@ -1080,6 +1096,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=m
# CONFIG_USB_DEBUG is not set
@@ -1151,9 +1168,7 @@ CONFIG_USB_WACOM=m
# CONFIG_USB_ACECAD is not set
CONFIG_USB_KBTAB=m
CONFIG_USB_POWERMATE=m
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-CONFIG_USB_EGALAX=m
+# CONFIG_USB_TOUCHSCREEN is not set
CONFIG_USB_YEALINK=m
CONFIG_USB_XPAD=m
# CONFIG_USB_ATI_REMOTE is not set
@@ -1168,15 +1183,6 @@ CONFIG_USB_MDC800=m
CONFIG_USB_MICROTEK=m
#
-# USB Multimedia devices
-#
-CONFIG_USB_DABUSB=m
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
CONFIG_USB_CATC=m
@@ -1213,6 +1219,7 @@ CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
CONFIG_USB_SERIAL_CYPRESS_M8=m
CONFIG_USB_SERIAL_EMPEG=m
CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
CONFIG_USB_SERIAL_VISOR=m
CONFIG_USB_SERIAL_IPAQ=m
CONFIG_USB_SERIAL_IR=m
@@ -1237,6 +1244,7 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
CONFIG_USB_SERIAL_KLSI=m
CONFIG_USB_SERIAL_KOBIL_SCT=m
CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
CONFIG_USB_SERIAL_PL2303=m
CONFIG_USB_SERIAL_HP4X=m
CONFIG_USB_SERIAL_SAFE=m
@@ -1281,13 +1289,31 @@ CONFIG_USB_TEST=m
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1358,7 +1384,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -1379,7 +1404,6 @@ CONFIG_HPFS_FS=m
CONFIG_QNX4FS_FS=m
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
@@ -1500,6 +1524,7 @@ CONFIG_NLS_UTF8=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index da68c3f7205..e388a3dae0a 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:32 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:17 2006
#
CONFIG_MIPS=y
@@ -81,6 +81,8 @@ CONFIG_SIBYTE_CFE=y
# CONFIG_SIBYTE_SB1250_PROF is not set
# CONFIG_SIBYTE_TBPROF is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_COHERENT=y
CONFIG_CPU_BIG_ENDIAN=y
@@ -158,7 +160,6 @@ CONFIG_PREEMPT_BKL=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -175,6 +176,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_CPUSETS=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -188,10 +190,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -203,7 +201,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -212,6 +209,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -231,7 +229,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
CONFIG_MMU=y
#
@@ -249,6 +246,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
CONFIG_MIPS32_COMPAT=y
CONFIG_COMPAT=y
CONFIG_MIPS32_O32=y
@@ -263,6 +261,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -284,12 +283,15 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -301,6 +303,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -310,11 +317,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -335,6 +337,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -589,6 +594,7 @@ CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -647,10 +653,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -675,6 +677,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -692,13 +695,31 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -746,7 +767,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -812,6 +832,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
# CONFIG_SB1XXX_CORELIS is not set
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index 9a936d7b7c0..6b8a6a416a2 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:33 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:17 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_MIPS_SEAD=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -118,11 +120,11 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -140,7 +142,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -154,6 +155,7 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -167,10 +169,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -185,6 +183,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -296,12 +296,6 @@ CONFIG_RAID_ATTRS=y
#
#
-# Network device support
-#
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
# ISDN subsystem
#
@@ -397,10 +391,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -424,6 +414,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# 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'
@@ -440,12 +431,30 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -489,7 +498,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -543,6 +551,8 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index c2dee0d1c72..dba0bdcdcf2 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:34 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:08:41 2006
#
CONFIG_MIPS=y
@@ -68,12 +68,14 @@ CONFIG_MACH_VR41XX=y
# CONFIG_NEC_CMBVR4133 is not set
CONFIG_TANBAC_TB022X=y
CONFIG_TANBAC_TB0226=y
-CONFIG_TANBAC_TB0287=y
+# CONFIG_TANBAC_TB0287 is not set
# CONFIG_VICTOR_MPC30X is not set
# CONFIG_ZAO_CAPCELLA is not set
CONFIG_PCI_VR41XX=y
# CONFIG_VRC4173 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -92,7 +94,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_MIPS64_R2 is not set
# CONFIG_CPU_R3000 is not set
# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
+CONFIG_CPU_VR41XX=y
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
@@ -105,18 +107,21 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
#
-# CONFIG_32BIT is not set
+CONFIG_32BIT=y
# CONFIG_64BIT is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -137,7 +142,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +157,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -166,10 +171,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -181,7 +182,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -189,6 +189,9 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -208,7 +211,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
CONFIG_MMU=y
#
@@ -226,6 +228,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
#
# Networking
@@ -235,11 +238,10 @@ 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=m
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -263,12 +265,15 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -280,6 +285,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -289,11 +299,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -310,10 +315,7 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
+# CONFIG_IEEE80211 is not set
#
# Device Drivers
@@ -358,11 +360,12 @@ CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -397,14 +400,14 @@ CONFIG_SCSI_MULTI_LUN=y
# SCSI Transport Attributes
#
# CONFIG_SCSI_SPI_ATTRS is not set
-CONFIG_SCSI_FC_ATTRS=y
-CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
#
# SCSI low-level drivers
#
-CONFIG_ISCSI_TCP=m
+# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -424,7 +427,6 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -507,8 +509,8 @@ CONFIG_NET_PCI=y
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_E100 is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
@@ -625,6 +627,11 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -685,10 +692,6 @@ CONFIG_GPIO_VR41XX=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -697,6 +700,7 @@ CONFIG_GPIO_VR41XX=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -719,6 +723,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -756,7 +761,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
#
# may also be needed; see USB_STORAGE Help for more information
#
-CONFIG_USB_STORAGE=m
+CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
@@ -783,9 +788,7 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -800,15 +803,6 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -816,7 +810,7 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET is not set
-CONFIG_USB_MON=y
+# CONFIG_USB_MON is not set
#
# USB port drivers
@@ -860,13 +854,48 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# 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"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
#
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_VR41XX=y
+# CONFIG_RTC_DRV_TEST is not set
#
# File systems
@@ -911,7 +940,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -952,9 +980,7 @@ CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp932"
+# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -970,46 +996,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 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=m
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+# CONFIG_NLS is not set
#
# Profiling support
@@ -1023,44 +1010,20 @@ CONFIG_NLS_ISO8859_1=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="mem=32M console=ttyVR0,115200"
#
# Security options
#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
#
# Hardware crypto devices
@@ -1069,9 +1032,8 @@ CONFIG_CRYPTO_CRC32C=m
#
# Library routines
#
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig
index be99261d799..5a924c1a580 100644
--- a/arch/mips/configs/tb0229_defconfig
+++ b/arch/mips/configs/tb0229_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:35 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:08:59 2006
#
CONFIG_MIPS=y
@@ -68,12 +68,14 @@ CONFIG_MACH_VR41XX=y
# CONFIG_NEC_CMBVR4133 is not set
CONFIG_TANBAC_TB022X=y
# CONFIG_TANBAC_TB0226 is not set
-CONFIG_TANBAC_TB0287=y
+# CONFIG_TANBAC_TB0287 is not set
# CONFIG_VICTOR_MPC30X is not set
# CONFIG_ZAO_CAPCELLA is not set
CONFIG_PCI_VR41XX=y
# CONFIG_VRC4173 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -92,7 +94,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_MIPS64_R2 is not set
# CONFIG_CPU_R3000 is not set
# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
+CONFIG_CPU_VR41XX=y
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
@@ -105,18 +107,21 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
#
-# CONFIG_32BIT is not set
+CONFIG_32BIT=y
# CONFIG_64BIT is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -137,7 +142,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -153,6 +157,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -166,10 +171,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -181,7 +182,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -189,6 +189,9 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -208,7 +211,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
CONFIG_MMU=y
#
@@ -226,6 +228,7 @@ CONFIG_MMU=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
#
# Networking
@@ -235,11 +238,10 @@ 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=m
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -264,12 +266,15 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
CONFIG_INET_TUNNEL=m
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -281,6 +286,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -290,11 +300,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -311,10 +316,7 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
+# CONFIG_IEEE80211 is not set
#
# Device Drivers
@@ -325,12 +327,12 @@ CONFIG_IEEE80211_CRYPT_CCMP=m
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
+# CONFIG_FW_LOADER is not set
#
# Connector - unified userspace <-> kernelspace linker
#
-CONFIG_CONNECTOR=m
+# CONFIG_CONNECTOR is not set
#
# Memory Technology Devices (MTD)
@@ -363,10 +365,8 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -443,30 +443,7 @@ CONFIG_MII=y
#
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-CONFIG_8139TOO=y
-CONFIG_8139TOO_PIO=y
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_PCI is not set
#
# Ethernet (1000 Mbit)
@@ -483,7 +460,6 @@ 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
@@ -510,19 +486,8 @@ CONFIG_R8169=y
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
@@ -583,6 +548,11 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -607,6 +577,7 @@ CONFIG_TANBAC_TB0219=y
# Ftape, the floppy tape device driver
#
# CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
# CONFIG_RAW_DRIVER is not set
#
@@ -642,10 +613,6 @@ CONFIG_TANBAC_TB0219=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -654,6 +621,7 @@ CONFIG_TANBAC_TB0219=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -676,6 +644,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=m
# CONFIG_USB_DEBUG is not set
@@ -731,9 +700,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -747,15 +714,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_MDC800 is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -807,13 +765,48 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# 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"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
#
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_VR41XX=y
+# CONFIG_RTC_DRV_TEST is not set
#
# File systems
@@ -821,32 +814,16 @@ CONFIG_USB_MON=y
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
+# CONFIG_EXT3_FS is not set
# CONFIG_REISERFS_FS is not set
-CONFIG_JFS_FS=m
-# CONFIG_JFS_POSIX_ACL is not set
-# CONFIG_JFS_SECURITY is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
+# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
-CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-CONFIG_XFS_QUOTA=y
-# CONFIG_XFS_SECURITY is not set
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_XFS_RT is not set
+# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=m
CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
-CONFIG_QUOTACTL=y
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
@@ -855,20 +832,14 @@ CONFIG_FUSE_FS=m
#
# CD-ROM/DVD Filesystems
#
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
+# CONFIG_ISO9660_FS is not set
# CONFIG_UDF_FS is not set
#
# DOS/FAT/NT Filesystems
#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -880,7 +851,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -921,9 +891,7 @@ CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp932"
+# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -939,46 +907,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 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=m
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+# CONFIG_NLS is not set
#
# Profiling support
@@ -992,44 +921,20 @@ CONFIG_NLS_ISO8859_1=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
#
# Security options
#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
#
# Hardware crypto devices
@@ -1038,9 +943,8 @@ CONFIG_CRYPTO_CRC32C=m
#
# Library routines
#
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
new file mode 100644
index 00000000000..9f215ea350d
--- /dev/null
+++ b/arch/mips/configs/tb0287_defconfig
@@ -0,0 +1,1132 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:09:17 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_NEC_CMBVR4133 is not set
+CONFIG_TANBAC_TB022X=y
+# CONFIG_TANBAC_TB0226 is not set
+CONFIG_TANBAC_TB0287=y
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+CONFIG_PCI_VR41XX=y
+# CONFIG_VRC4173 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+CONFIG_CPU_VR41XX=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_MMU=y
+
+#
+# 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_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_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_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_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_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_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
+
+#
+# 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_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+# CONFIG_IEEE1394_OUI_DB is not set
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+
+#
+# Texas Instruments PCILynx requires I2C
+#
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# 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
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI 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=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_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# 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
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_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
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_TANBAC_TB0219 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_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_SMIVGX=y
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND 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=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# 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_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_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=y
+CONFIG_XFS_QUOTA=y
+# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_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_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index 7132e296d40..ac7765eb8da 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:36 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:09:33 2006
#
CONFIG_MIPS=y
@@ -70,6 +70,8 @@ CONFIG_IBM_WORKPAD=y
# CONFIG_VICTOR_MPC30X is not set
# CONFIG_ZAO_CAPCELLA is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -88,7 +90,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_MIPS64_R2 is not set
# CONFIG_CPU_R3000 is not set
# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
+CONFIG_CPU_VR41XX=y
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_TX49XX is not set
@@ -101,18 +103,21 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
#
-# CONFIG_32BIT is not set
+CONFIG_32BIT=y
# CONFIG_64BIT is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -133,7 +138,6 @@ CONFIG_PREEMPT_NONE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -149,6 +153,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -162,10 +167,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -177,7 +178,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -185,6 +185,9 @@ CONFIG_KMOD=y
#
# Block layer
#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -220,6 +223,7 @@ CONFIG_PCMCIA_IOCTL=y
# CONFIG_I82365 is not set
# CONFIG_TCIC is not set
CONFIG_PCMCIA_PROBE=y
+CONFIG_PCMCIA_VRC4171=y
#
# PCI Hotplug Support
@@ -230,6 +234,7 @@ CONFIG_PCMCIA_PROBE=y
#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
#
# Networking
@@ -239,6 +244,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -258,12 +264,15 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
@@ -275,6 +284,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -284,11 +298,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -305,10 +314,8 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
+# CONFIG_IEEE80211 is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -347,10 +354,12 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -468,7 +477,38 @@ CONFIG_MII=m
#
# Wireless LAN (non-hamradio)
#
-# CONFIG_NET_RADIO is not set
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+# CONFIG_PCMCIA_SPECTRUM is not set
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
#
# PCMCIA network device support
@@ -512,10 +552,7 @@ CONFIG_INPUT=y
#
# Userland interfaces
#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
@@ -533,11 +570,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
@@ -556,6 +589,10 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -568,20 +605,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Watchdog Cards
#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-
-#
-# ISA-based Watchdog Cards
-#
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_WDT is not set
+# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
@@ -597,6 +621,7 @@ CONFIG_WATCHDOG=y
# CONFIG_SYNCLINK_CS is not set
# CONFIG_CARDMAN_4000 is not set
# CONFIG_CARDMAN_4040 is not set
+# CONFIG_GPIO_VR41XX is not set
# CONFIG_RAW_DRIVER is not set
#
@@ -632,10 +657,6 @@ CONFIG_WATCHDOG=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -667,6 +688,7 @@ CONFIG_DUMMY_CONSOLE=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -683,12 +705,30 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -710,7 +750,7 @@ CONFIG_FS_POSIX_ACL=y
CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=m
@@ -733,10 +773,9 @@ CONFIG_FUSE_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -802,44 +841,20 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE="console=ttyVR0,19200 mem=16M"
#
# Security options
#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
#
# Hardware crypto devices
@@ -849,8 +864,6 @@ CONFIG_CRYPTO_CRC32C=m
# Library routines
#
# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 67457850941..b52d709de96 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:37 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:20 2006
#
CONFIG_MIPS=y
@@ -65,6 +65,8 @@ CONFIG_PMC_YOSEMITE=y
# CONFIG_TOSHIBA_RBTX4938 is not set
# CONFIG_HYPERTRANSPORT is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DMA_COHERENT=y
CONFIG_CPU_BIG_ENDIAN=y
@@ -116,7 +118,6 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -140,7 +141,6 @@ CONFIG_PREEMPT_BKL=y
# Code maturity level options
#
# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -157,6 +157,7 @@ CONFIG_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
@@ -170,10 +171,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -184,7 +181,6 @@ CONFIG_BASE_SMALL=0
#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -194,6 +190,8 @@ CONFIG_STOP_MACHINE=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -213,7 +211,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
CONFIG_MMU=y
@@ -241,6 +238,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=m
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -261,16 +259,19 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
# CONFIG_NETFILTER is not set
@@ -340,10 +341,9 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
CONFIG_ATA_OVER_ETH=m
#
@@ -433,6 +433,7 @@ CONFIG_MII=y
# CONFIG_HAMACHI is not set
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
@@ -497,6 +498,7 @@ CONFIG_TITAN_GE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -506,6 +508,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
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
@@ -563,10 +566,6 @@ CONFIG_GEN_RTC_X=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -591,6 +590,7 @@ CONFIG_GEN_RTC_X=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -608,12 +608,29 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
#
@@ -656,7 +673,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
#
# Miscellaneous filesystems
diff --git a/arch/mips/ddb5xxx/common/rtc_ds1386.c b/arch/mips/ddb5xxx/common/rtc_ds1386.c
index 995896ac0e3..5dc34daa715 100644
--- a/arch/mips/ddb5xxx/common/rtc_ds1386.c
+++ b/arch/mips/ddb5xxx/common/rtc_ds1386.c
@@ -165,6 +165,6 @@ rtc_ds1386_init(unsigned long base)
WRITE_RTC(0xB, byte);
/* set the function pointers */
- rtc_get_time = rtc_ds1386_get_time;
- rtc_set_time = rtc_ds1386_set_time;
+ rtc_mips_get_time = rtc_ds1386_get_time;
+ rtc_mips_set_time = rtc_ds1386_set_time;
}
diff --git a/arch/mips/ddb5xxx/ddb5074/Makefile b/arch/mips/ddb5xxx/ddb5074/Makefile
index 488206b8d94..304c02107b4 100644
--- a/arch/mips/ddb5xxx/ddb5074/Makefile
+++ b/arch/mips/ddb5xxx/ddb5074/Makefile
@@ -3,6 +3,6 @@
# under Linux.
#
-obj-y += setup.o irq.o int-handler.o nile4_pic.o
+obj-y += setup.o irq.o nile4_pic.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5074/int-handler.S b/arch/mips/ddb5xxx/ddb5074/int-handler.S
deleted file mode 100644
index a78644150b3..00000000000
--- a/arch/mips/ddb5xxx/ddb5074/int-handler.S
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
- *
- * Based on arch/mips/sgi/kernel/indyIRQ.S
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- * Sony Software Development Center Europe (SDCE), Brussels
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- * all the pending IRQ bits in the cause register is _NOT_ the answer, the
- * common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- * would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- * between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the INDY look basically (barring software IRQs
- * which we don't use at all) like:
- *
- * MIPS IRQ Source
- * -------- ------
- * 0 Software (ignored)
- * 1 Software (ignored)
- * 2 Local IRQ level zero
- * 3 Local IRQ level one
- * 4 8254 Timer zero
- * 5 8254 Timer one
- * 6 Bus Error
- * 7 R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ---- R4k Timer
- * Local IRQ zero
- * Local IRQ one
- * Bus Error
- * 8254 Timer zero
- * Lowest ---- 8254 Timer one
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
- .text
- .set noreorder
- .set noat
- .align 5
- NESTED(ddbIRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 s0, CP0_CAUSE # get irq mask
-
-#if 1
- mfc0 t2,CP0_STATUS # get enabled interrupts
- and s0,t2 # isolate allowed ones
-#endif
- /* First we check for r4k counter/timer IRQ. */
- andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero
- beq a0, zero, 1f
- andi a0, s0, CAUSEF_IP3 # delay slot, check local level one
-
- /* Wheee, local level zero interrupt. */
- jal ddb_local0_irqdispatch
- move a0, sp # delay slot
-
- j ret_from_irq
- nop # delay slot
-
-1:
- beq a0, zero, 1f
- andi a0, s0, CAUSEF_IP6 # delay slot, check bus error
-
- /* Wheee, local level one interrupt. */
- move a0, sp
- jal ddb_local1_irqdispatch
- nop
-
- j ret_from_irq
- nop
-
-1:
- beq a0, zero, 1f
- nop
-
- /* Wheee, an asynchronous bus error... */
- move a0, sp
- jal ddb_buserror_irq
- nop
-
- j ret_from_irq
- nop
-
-1:
- /* Here by mistake? This is possible, what can happen
- * is that by the time we take the exception the IRQ
- * pin goes low, so just leave if this is the case.
- */
- andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
- beq a0, zero, 1f
-
- /* Must be one of the 8254 timers... */
- move a0, sp
- jal ddb_8254timer_irq
- nop
-1:
- j ret_from_irq
- nop
- END(ddbIRQ)
diff --git a/arch/mips/ddb5xxx/ddb5074/irq.c b/arch/mips/ddb5xxx/ddb5074/irq.c
index 45088a1be41..60c087b7738 100644
--- a/arch/mips/ddb5xxx/ddb5074/irq.c
+++ b/arch/mips/ddb5xxx/ddb5074/irq.c
@@ -21,8 +21,6 @@
#include <asm/ddb5xxx/ddb5074.h>
-extern asmlinkage void ddbIRQ(void);
-
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */
@@ -90,7 +88,7 @@ static void m1543_irq_setup(void)
}
-void ddb_local0_irqdispatch(struct pt_regs *regs)
+static void ddb_local0_irqdispatch(struct pt_regs *regs)
{
u32 mask;
int nile4_irq;
@@ -118,29 +116,41 @@ void ddb_local0_irqdispatch(struct pt_regs *regs)
}
}
-void ddb_local1_irqdispatch(void)
+static void ddb_local1_irqdispatch(void)
{
printk("ddb_local1_irqdispatch called\n");
}
-void ddb_buserror_irq(void)
+static void ddb_buserror_irq(void)
{
printk("ddb_buserror_irq called\n");
}
-void ddb_8254timer_irq(void)
+static void ddb_8254timer_irq(void)
{
printk("ddb_8254timer_irq called\n");
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & CAUSEF_IP2)
+ ddb_local0_irqdispatch(regs);
+ else if (pending & CAUSEF_IP3)
+ ddb_local1_irqdispatch();
+ else if (pending & CAUSEF_IP6)
+ ddb_buserror_irq();
+ else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
+ ddb_8254timer_irq();
+}
+
void __init arch_init_irq(void)
{
/* setup cascade interrupts */
setup_irq(NILE4_IRQ_BASE + NILE4_INT_INTE, &irq_cascade);
setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade);
- set_except_vector(0, ddbIRQ);
-
nile4_irq_setup(NILE4_IRQ_BASE);
m1543_irq_setup();
init_i8259_irqs();
diff --git a/arch/mips/ddb5xxx/ddb5476/Makefile b/arch/mips/ddb5xxx/ddb5476/Makefile
index 61eec363cb0..ab0312cb47b 100644
--- a/arch/mips/ddb5xxx/ddb5476/Makefile
+++ b/arch/mips/ddb5xxx/ddb5476/Makefile
@@ -3,7 +3,7 @@
# under Linux.
#
-obj-y += setup.o irq.o int-handler.o nile4_pic.o vrc5476_irq.o
+obj-y += setup.o irq.o nile4_pic.o vrc5476_irq.o
obj-$(CONFIG_KGDB) += dbg_io.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5476/dbg_io.c b/arch/mips/ddb5xxx/ddb5476/dbg_io.c
index 85e9e501367..f2296a99995 100644
--- a/arch/mips/ddb5xxx/ddb5476/dbg_io.c
+++ b/arch/mips/ddb5xxx/ddb5476/dbg_io.c
@@ -86,7 +86,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
/* disable interrupts */
UART16550_WRITE(OFS_INTR_ENABLE, 0);
- /* set up buad rate */
+ /* set up baud rate */
{
uint32 divisor;
diff --git a/arch/mips/ddb5xxx/ddb5476/int-handler.S b/arch/mips/ddb5xxx/ddb5476/int-handler.S
deleted file mode 100644
index 12c292e189b..00000000000
--- a/arch/mips/ddb5xxx/ddb5476/int-handler.S
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ddb5476
- *
- * This program is free software; 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#include <asm/ddb5xxx/ddb5476.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
- .align 5
- NESTED(ddb5476_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- .set noreorder
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cpu_ip7
- andi t1, t0, STATUSF_IP2 /* vrc5476 & i8259 */
- bnez t1, ll_cpu_ip2
- andi t1, t0, STATUSF_IP3
- bnez t1, ll_cpu_ip3
- andi t1, t0, STATUSF_IP4
- bnez t1, ll_cpu_ip4
- andi t1, t0, STATUSF_IP5
- bnez t1, ll_cpu_ip5
- andi t1, t0, STATUSF_IP6
- bnez t1, ll_cpu_ip6
- andi t1, t0, STATUSF_IP0 /* software int 0 */
- bnez t1, ll_cpu_ip0
- andi t1, t0, STATUSF_IP1 /* software int 1 */
- bnez t1, ll_cpu_ip1
- nop
-
- .set reorder
-
- /* wrong alarm or masked ... */
- // j spurious_interrupt
- move a0, sp
- jal vrc5476_irq_dispatch
- j ret_from_irq
- nop
-
- .align 5
-
-ll_cpu_ip0:
- li a0, CPU_IRQ_BASE + 0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip1:
- li a0, CPU_IRQ_BASE + 1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip2: /* jump to second-level dispatching */
- move a0, sp
- jal vrc5476_irq_dispatch
- j ret_from_irq
-
-ll_cpu_ip3:
- li a0, CPU_IRQ_BASE + 3
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip4:
- li a0, CPU_IRQ_BASE + 4
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip5:
- li a0, CPU_IRQ_BASE + 5
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip6:
- li a0, CPU_IRQ_BASE + 6
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip7:
- li a0, CPU_IRQ_BASE + 7
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
- END(ddb5476_handle_int)
diff --git a/arch/mips/ddb5xxx/ddb5476/irq.c b/arch/mips/ddb5xxx/ddb5476/irq.c
index 5388b5868c4..7583a1f3071 100644
--- a/arch/mips/ddb5xxx/ddb5476/irq.c
+++ b/arch/mips/ddb5xxx/ddb5476/irq.c
@@ -110,11 +110,36 @@ static void nile4_irq_setup(void)
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL };
-extern asmlinkage void ddb5476_handle_int(void);
extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
extern void mips_cpu_irq_init(u32 irq_base);
extern void vrc5476_irq_init(u32 irq_base);
+extern void vrc5476_irq_dispatch(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP7)
+ do_IRQ(CPU_IRQ_BASE + 7, regs);
+ else if (pending & STATUSF_IP2)
+ vrc5476_irq_dispatch(regs);
+ else if (pending & STATUSF_IP3)
+ do_IRQ(CPU_IRQ_BASE + 3, regs);
+ else if (pending & STATUSF_IP4)
+ do_IRQ(CPU_IRQ_BASE + 4, regs);
+ else if (pending & STATUSF_IP5)
+ do_IRQ(CPU_IRQ_BASE + 5, regs);
+ else if (pending & STATUSF_IP6)
+ do_IRQ(CPU_IRQ_BASE + 6, regs);
+ else if (pending & STATUSF_IP0)
+ do_IRQ(CPU_IRQ_BASE, regs);
+ else if (pending & STATUSF_IP1)
+ do_IRQ(CPU_IRQ_BASE + 1, regs);
+
+ vrc5476_irq_dispatch(regs);
+}
+
void __init arch_init_irq(void)
{
/* hardware initialization */
@@ -137,7 +162,4 @@ void __init arch_init_irq(void)
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error);
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error);
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error);
-
- /* setup the grandpa intr vector */
- set_except_vector(0, ddb5476_handle_int);
}
diff --git a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
index f66fe5b5863..a3c5e7b1801 100644
--- a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
+++ b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
@@ -77,11 +77,9 @@ vrc5476_irq_init(u32 base)
}
-asmlinkage void
+void
vrc5476_irq_dispatch(struct pt_regs *regs)
{
- extern void spurious_interrupt(void);
-
u32 mask;
int nile4_irq;
@@ -107,5 +105,5 @@ vrc5476_irq_dispatch(struct pt_regs *regs)
return;
}
}
- spurious_interrupt();
+ spurious_interrupt(regs);
}
diff --git a/arch/mips/ddb5xxx/ddb5477/Makefile b/arch/mips/ddb5xxx/ddb5477/Makefile
index b79b43c9f93..ea68815ad17 100644
--- a/arch/mips/ddb5xxx/ddb5477/Makefile
+++ b/arch/mips/ddb5xxx/ddb5477/Makefile
@@ -2,7 +2,7 @@
# Makefile for NEC DDB-Vrc5477 board
#
-obj-y += int-handler.o irq.o irq_5477.o setup.o lcd44780.o
+obj-y += irq.o irq_5477.o setup.o lcd44780.o
obj-$(CONFIG_RUNTIME_DEBUG) += debug.o
obj-$(CONFIG_KGDB) += kgdb_io.o
diff --git a/arch/mips/ddb5xxx/ddb5477/int-handler.S b/arch/mips/ddb5xxx/ddb5477/int-handler.S
deleted file mode 100644
index a2502a14400..00000000000
--- a/arch/mips/ddb5xxx/ddb5477/int-handler.S
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ddb5477
- *
- * This program is free software; 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/ddb5xxx/ddb5477.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
- .align 5
- NESTED(ddb5477_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- .set noreorder
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cputimer_irq
- andi t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
- bnez t1, ll_vrc5477_irq
- andi t1, t0, STATUSF_IP0 /* software int 0 */
- bnez t1, ll_cpu_ip0
- andi t1, t0, STATUSF_IP1 /* software int 1 */
- bnez t1, ll_cpu_ip1
- nop
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(ddb5477_handle_int)
-
- .align 5
-
-ll_vrc5477_irq:
- move a0, sp
- jal vrc5477_irq_dispatch
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, CPU_IRQ_BASE + 7
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-
-ll_cpu_ip0:
- li a0, CPU_IRQ_BASE + 0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip1:
- li a0, CPU_IRQ_BASE + 1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
diff --git a/arch/mips/ddb5xxx/ddb5477/irq.c b/arch/mips/ddb5xxx/ddb5477/irq.c
index 9ffe1a9142c..de433cf9fb5 100644
--- a/arch/mips/ddb5xxx/ddb5477/irq.c
+++ b/arch/mips/ddb5xxx/ddb5477/irq.c
@@ -75,7 +75,6 @@ set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger)
extern void vrc5477_irq_init(u32 base);
extern void mips_cpu_irq_init(u32 base);
-extern asmlinkage void ddb5477_handle_int(void);
extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
@@ -135,9 +134,6 @@ void __init arch_init_irq(void)
/* setup cascade interrupts */
setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade);
setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);
-
- /* hook up the first-level interrupt handler */
- set_except_vector(0, ddb5477_handle_int);
}
u8 i8259_interrupt_ack(void)
@@ -159,7 +155,7 @@ u8 i8259_interrupt_ack(void)
* the first level int-handler will jump here if it is a vrc5477 irq
*/
#define NUM_5477_IRQS 32
-asmlinkage void
+static void
vrc5477_irq_dispatch(struct pt_regs *regs)
{
u32 intStatus;
@@ -197,3 +193,21 @@ vrc5477_irq_dispatch(struct pt_regs *regs)
}
}
}
+
+#define VR5477INTS (STATUSF_IP2|STATUSF_IP3|STATUSF_IP4|STATUSF_IP5|STATUSF_IP6)
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP7)
+ do_IRQ(CPU_IRQ_BASE + 7, regs);
+ else if (pending & VR5477INTS)
+ vrc5477_irq_dispatch(regs);
+ else if (pending & STATUSF_IP0)
+ do_IRQ(CPU_IRQ_BASE, regs);
+ else if (pending & STATUSF_IP1)
+ do_IRQ(CPU_IRQ_BASE + 1, regs);
+ else
+ spurious_interrupt(regs);
+}
diff --git a/arch/mips/ddb5xxx/ddb5477/kgdb_io.c b/arch/mips/ddb5xxx/ddb5477/kgdb_io.c
index 1d18d590495..385bbdb1017 100644
--- a/arch/mips/ddb5xxx/ddb5477/kgdb_io.c
+++ b/arch/mips/ddb5xxx/ddb5477/kgdb_io.c
@@ -86,7 +86,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
/* disable interrupts */
UART16550_WRITE(OFS_INTR_ENABLE, 0);
- /* set up buad rate */
+ /* set up baud rate */
{
uint32 divisor;
diff --git a/arch/mips/dec/boot/decstation.c b/arch/mips/dec/boot/decstation.c
index 56fd4277555..4db8bacaf22 100644
--- a/arch/mips/dec/boot/decstation.c
+++ b/arch/mips/dec/boot/decstation.c
@@ -1,6 +1,7 @@
/*
* arch/mips/dec/decstation.c
*/
+#include <asm/sections.h>
#define RELOC
#define INITRD
@@ -24,7 +25,7 @@
#define INITRD_START (*(unsigned long *) (PARAM+0x218))
#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
-extern int _ftext, _end; /* begin and end of kernel image */
+extern int _ftext; /* begin and end of kernel image */
extern void kernel_entry(int, char **, unsigned long, int *);
void * memcpy(void * dest, const void *src, unsigned int count)
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index 41fa372007b..e8ec93e33fe 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -36,7 +36,7 @@
.text
.set noreorder
/*
- * decstation_handle_int: Interrupt handler for DECstations
+ * plat_irq_dispatch: Interrupt handler for DECstations
*
* We follow the model in the Indy interrupt code by David Miller, where he
* says: a lot of complication here is taken away because:
@@ -125,11 +125,7 @@
* just take another exception, big deal.
*/
.align 5
- NESTED(decstation_handle_int, PT_SIZE, ra)
- .set noat
- SAVE_ALL
- CLI # TEST: interrupts should be off
- .set at
+ NESTED(plat_irq_dispatch, PT_SIZE, ra)
.set noreorder
/*
@@ -282,9 +278,11 @@ fpu:
#endif
spurious:
- j spurious_interrupt
+ jal spurious_interrupt
nop
- END(decstation_handle_int)
+ j ret_from_irq
+ nop
+ END(plat_irq_dispatch)
/*
* Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 7c1ca8f6330..ad5d436d80c 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -48,8 +48,6 @@ extern void dec_machine_halt(void);
extern void dec_machine_power_off(void);
extern irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs);
-extern asmlinkage void decstation_handle_int(void);
-
unsigned long dec_kn_slot_base, dec_kn_slot_size;
EXPORT_SYMBOL(dec_kn_slot_base);
@@ -744,7 +742,6 @@ void __init arch_init_irq(void)
panic("Don't know how to set this up!");
break;
}
- set_except_vector(0, decstation_handle_int);
/* Free the FPU interrupt if the exception is present. */
if (!cpu_has_nofpuex) {
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
index 17482234413..74cb055d4bf 100644
--- a/arch/mips/dec/time.c
+++ b/arch/mips/dec/time.c
@@ -36,41 +36,13 @@
#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/machtype.h>
-
-/*
- * Returns true if a clock update is in progress
- */
-static inline unsigned char dec_rtc_is_updating(void)
-{
- unsigned char uip;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
- spin_unlock_irqrestore(&rtc_lock, flags);
- return uip;
-}
-
static unsigned long dec_rtc_get_time(void)
{
unsigned int year, mon, day, hour, min, sec, real_year;
- int i;
unsigned long flags;
- /* The Linux interpretation of the DS1287 clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
- /* read RTC exactly on falling edge of update flag */
- for (i = 0; i < 1000000; i++) /* may take up to 1 second... */
- if (dec_rtc_is_updating())
- break;
- for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */
- if (!dec_rtc_is_updating())
- break;
spin_lock_irqsave(&rtc_lock, flags);
- /* Isn't this overkill? UIP above should guarantee consistency */
+
do {
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
@@ -78,7 +50,16 @@ static unsigned long dec_rtc_get_time(void)
day = CMOS_READ(RTC_DAY_OF_MONTH);
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
+ /*
+ * The PROM will reset the year to either '72 or '73.
+ * Therefore we store the real year separately, in one
+ * of unused BBU RAM locations.
+ */
+ real_year = CMOS_READ(RTC_DEC_YEAR);
} while (sec != CMOS_READ(RTC_SECONDS));
+
+ spin_unlock_irqrestore(&rtc_lock, flags);
+
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
sec = BCD2BIN(sec);
min = BCD2BIN(min);
@@ -87,13 +68,7 @@ static unsigned long dec_rtc_get_time(void)
mon = BCD2BIN(mon);
year = BCD2BIN(year);
}
- /*
- * The PROM will reset the year to either '72 or '73.
- * Therefore we store the real year separately, in one
- * of unused BBU RAM locations.
- */
- real_year = CMOS_READ(RTC_DEC_YEAR);
- spin_unlock_irqrestore(&rtc_lock, flags);
+
year += real_year - 72 + 2000;
return mktime(year, mon, day, hour, min, sec);
@@ -193,8 +168,8 @@ static void dec_ioasic_hpt_init(unsigned int count)
void __init dec_time_init(void)
{
- rtc_get_time = dec_rtc_get_time;
- rtc_set_mmss = dec_rtc_set_mmss;
+ rtc_mips_get_time = dec_rtc_get_time;
+ rtc_mips_set_mmss = dec_rtc_set_mmss;
mips_timer_state = dec_timer_state;
mips_timer_ack = dec_timer_ack;
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 42d5cd7927c..607e2985ffe 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:51 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:54 2006
#
CONFIG_MIPS=y
@@ -64,6 +64,8 @@ CONFIG_SGI_IP22=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARC=y
CONFIG_DMA_NONCOHERENT=y
@@ -121,7 +123,6 @@ CONFIG_BOARD_SCACHE=y
CONFIG_IP22_CPU_SCACHE=y
# CONFIG_MIPS_MT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
@@ -143,7 +144,6 @@ CONFIG_PREEMPT_VOLUNTARY=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -160,6 +160,7 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -173,10 +174,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -188,7 +185,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -197,6 +193,8 @@ CONFIG_KMOD=y
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -242,6 +240,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -264,6 +263,7 @@ CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=m
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -305,9 +305,12 @@ CONFIG_IP_VS_NQ=m
CONFIG_IP_VS_FTP=m
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -330,11 +333,14 @@ CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -357,20 +363,19 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_MATCH_OWNER=m
CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -388,6 +393,7 @@ CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_NAT_TFTP=m
CONFIG_IP_NF_NAT_AMANDA=m
CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
@@ -408,12 +414,10 @@ CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
CONFIG_IP6_NF_MATCH_OWNER=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_LOG=m
CONFIG_IP6_NF_TARGET_REJECT=m
@@ -435,6 +439,11 @@ CONFIG_IP_SCTP=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -444,11 +453,6 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
CONFIG_NET_DIVERT=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -508,6 +512,9 @@ CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
#
# Device Drivers
@@ -546,7 +553,7 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -812,10 +819,6 @@ CONFIG_MAX_RAW_DEVS=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -857,6 +860,7 @@ CONFIG_LOGO_SGI_CLUT224=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -873,12 +877,30 @@ CONFIG_LOGO_SGI_CLUT224=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -944,7 +966,6 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
@@ -963,7 +984,6 @@ CONFIG_EFS_FS=m
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
@@ -1078,6 +1098,7 @@ CONFIG_NLS_UTF8=m
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
diff --git a/arch/mips/galileo-boards/ev96100/Makefile b/arch/mips/galileo-boards/ev96100/Makefile
index 58c02f9db69..cd868ec78cb 100644
--- a/arch/mips/galileo-boards/ev96100/Makefile
+++ b/arch/mips/galileo-boards/ev96100/Makefile
@@ -6,4 +6,4 @@
# Makefile for the Galileo EV96100 board.
#
-obj-y += init.o irq.o puts.o reset.o time.o int-handler.o setup.o
+obj-y += init.o irq.o puts.o reset.o time.o setup.o
diff --git a/arch/mips/galileo-boards/ev96100/int-handler.S b/arch/mips/galileo-boards/ev96100/int-handler.S
deleted file mode 100644
index ff4d10a3885..00000000000
--- a/arch/mips/galileo-boards/ev96100/int-handler.S
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .set noat
- .align 5
-
-NESTED(ev96100IRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI # Important: mark KERNEL mode !
-
- mfc0 t0, CP0_CAUSE # get pending interrupts
- mfc0 t1, CP0_STATUS # get enabled interrupts
- and t0, t1 # isolate allowed ones
-
- # FIX ME add R7000 extensions
- andi t0,0xff00 # isolate pending bits
- andi a0, t0, CAUSEF_IP7
- beq a0, zero, 1f
- move a0, sp
- jal mips_timer_interrupt
- j ret_from_irq
-
-1: beqz t0, 3f # spurious interrupt
-
- move a0, t0
- move a1, sp
- jal ev96100_cpu_irq
- j ret_from_irq
-
-3: j spurious_interrupt
- END(ev96100IRQ)
diff --git a/arch/mips/galileo-boards/ev96100/irq.c b/arch/mips/galileo-boards/ev96100/irq.c
index 97bf094da4f..ee5d6720f23 100644
--- a/arch/mips/galileo-boards/ev96100/irq.c
+++ b/arch/mips/galileo-boards/ev96100/irq.c
@@ -40,8 +40,6 @@
#include <linux/interrupt.h>
#include <asm/irq_cpu.h>
-extern asmlinkage void ev96100IRQ(void);
-
static inline unsigned int ffz8(unsigned int word)
{
unsigned long k;
@@ -54,13 +52,26 @@ static inline unsigned int ffz8(unsigned int word)
return k;
}
-asmlinkage void ev96100_cpu_irq(unsigned int pendin)
+extern void mips_timer_interrupt(struct pt_regs *regs);
+
+asmlinkage void ev96100_cpu_irq(unsigned int pending, struct pt_regs *regs)
{
do_IRQ(ffz8(pending >> 8), regs);
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (pending & CAUSEF_IP7)
+ mips_timer_interrupt(regs);
+ else if (pending)
+ ev96100_cpu_irq(pending, regs);
+ else
+ spurious_interrupt(regs);
+}
+
void __init arch_init_irq(void)
{
- set_except_vector(0, ev96100IRQ);
mips_cpu_irq_init(0);
}
diff --git a/arch/mips/gt64120/ev64120/Makefile b/arch/mips/gt64120/ev64120/Makefile
index ebe91c57e17..b2c53a8f871 100644
--- a/arch/mips/gt64120/ev64120/Makefile
+++ b/arch/mips/gt64120/ev64120/Makefile
@@ -6,6 +6,6 @@
# Makefile for the Galileo EV64120 board.
#
-obj-y += int-handler.o irq.o promcon.o reset.o serialGT.o setup.o
+obj-y += irq.o promcon.o reset.o serialGT.o setup.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/gt64120/ev64120/int-handler.S b/arch/mips/gt64120/ev64120/int-handler.S
deleted file mode 100644
index 752435faf2d..00000000000
--- a/arch/mips/gt64120/ev64120/int-handler.S
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * int-handler.S
- *
- * Based on the cobalt handler.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * galileo_handle_int -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
- .align 5
- .set reorder
- .set noat
- NESTED(galileo_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 t0,CP0_CAUSE
- mfc0 t2,CP0_STATUS
-
- and t0,t2
-
- andi t1,t0,STATUSF_IP4 /* int2 hardware line (timer) */
- bnez t1,ll_gt64120_irq
- andi t1,t0,STATUSF_IP2 /* int0 hardware line */
- bnez t1,ll_pci_intA
- andi t1,t0,STATUSF_IP5 /* int3 hardware line */
- bnez t1,ll_pci_intD
- andi t1,t0,STATUSF_IP6 /* int4 hardware line */
- bnez t1,ll_serial_irq
- andi t1,t0,STATUSF_IP7 /* compare int */
- bnez t1,ll_compare_irq
- nop
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(galileo_handle_int)
-
-
- .align 5
- .set reorder
-ll_gt64120_irq:
- li a0,4
- move a1,sp
- jal do_IRQ
- nop
- j ret_from_irq
- nop
-
- .align 5
- .set reorder
-ll_compare_irq:
- li a0,7
- move a1,sp
- jal do_IRQ
- nop
- j ret_from_irq
- nop
-
- .align 5
- .set reorder
-ll_pci_intA:
- move a0,sp
- jal pci_intA
- nop
- j ret_from_irq
- nop
-
-#if 0
- .align 5
- .set reorder
-ll_pci_intB:
- move a0,sp
- jal pci_intB
- nop
- j ret_from_irq
- nop
-
- .align 5
- .set reorder
-ll_pci_intC:
- move a0,sp
- jal pci_intC
- nop
- j ret_from_irq
- nop
-#endif
-
- .align 5
- .set reorder
-ll_pci_intD:
- move a0,sp
- jal pci_intD
- nop
- j ret_from_irq
- nop
-
- .align 5
- .set reorder
-ll_serial_irq:
- li a0,6
- move a1,sp
- jal do_IRQ
- nop
- j ret_from_irq
- nop
diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c
index 3b186159b21..46c468b26b3 100644
--- a/arch/mips/gt64120/ev64120/irq.c
+++ b/arch/mips/gt64120/ev64120/irq.c
@@ -46,14 +46,22 @@
#include <asm/system.h>
#include <asm/gt64120.h>
-asmlinkage inline void pci_intA(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
- do_IRQ(GT_INTA, regs);
-}
-
-asmlinkage inline void pci_intD(struct pt_regs *regs)
-{
- do_IRQ(GT_INTD, regs);
+ unsigned int pending = read_c0_status() & read_c0_cause();
+
+ if (pending & STATUSF_IP4) /* int2 hardware line (timer) */
+ do_IRQ(4, regs);
+ else if (pending & STATUSF_IP2) /* int0 hardware line */
+ do_IRQ(GT_INTA, regs);
+ else if (pending & STATUSF_IP5) /* int3 hardware line */
+ do_IRQ(GT_INTD, regs);
+ else if (pending & STATUSF_IP6) /* int4 hardware line */
+ do_IRQ(6, regs);
+ else if (pending & STATUSF_IP7) /* compare int */
+ do_IRQ(7, regs);
+ else
+ spurious_interrupt(regs);
}
static void disable_ev64120_irq(unsigned int irq_nr)
@@ -109,16 +117,11 @@ static struct hw_interrupt_type ev64120_irq_type = {
void gt64120_irq_setup(void)
{
- extern asmlinkage void galileo_handle_int(void);
-
/*
* Clear all of the interrupts while we change the able around a bit.
*/
clear_c0_status(ST0_IM);
- /* Sets the exception_handler array. */
- set_except_vector(0, galileo_handle_int);
-
local_irq_disable();
/*
diff --git a/arch/mips/gt64120/ev64120/serialGT.c b/arch/mips/gt64120/ev64120/serialGT.c
index 16e34a546e5..8f0d835491f 100644
--- a/arch/mips/gt64120/ev64120/serialGT.c
+++ b/arch/mips/gt64120/ev64120/serialGT.c
@@ -149,7 +149,7 @@ void serial_set(int channel, unsigned long baud)
#else
/*
* Note: Set baud rate, hardcoded here for rate of 115200
- * since became unsure of above "buad rate" algorithm (??).
+ * since became unsure of above "baud rate" algorithm (??).
*/
outreg(channel, LCR, 0x83);
outreg(channel, DLM, 0x00); // See note above
diff --git a/arch/mips/gt64120/momenco_ocelot/Makefile b/arch/mips/gt64120/momenco_ocelot/Makefile
index 7b59c6567c7..6f708df8373 100644
--- a/arch/mips/gt64120/momenco_ocelot/Makefile
+++ b/arch/mips/gt64120/momenco_ocelot/Makefile
@@ -2,7 +2,7 @@
# Makefile for Momentum's Ocelot board.
#
-obj-y += int-handler.o irq.o prom.o reset.o setup.o
+obj-y += irq.o prom.o reset.o setup.o
obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/gt64120/momenco_ocelot/dbg_io.c b/arch/mips/gt64120/momenco_ocelot/dbg_io.c
index 8720bccfdea..f0a6a38fcf4 100644
--- a/arch/mips/gt64120/momenco_ocelot/dbg_io.c
+++ b/arch/mips/gt64120/momenco_ocelot/dbg_io.c
@@ -73,7 +73,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
/* disable interrupts */
UART16550_WRITE(OFS_INTR_ENABLE, 0);
- /* set up buad rate */
+ /* set up baud rate */
{
uint32 divisor;
diff --git a/arch/mips/gt64120/momenco_ocelot/int-handler.S b/arch/mips/gt64120/momenco_ocelot/int-handler.S
deleted file mode 100644
index 808acef248c..00000000000
--- a/arch/mips/gt64120/momenco_ocelot/int-handler.S
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ocelot board.
- *
- * This program is free software; 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
- .align 5
- NESTED(ocelot_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP2 /* int0 hardware line */
- bnez t1, ll_pri_enet_irq
- andi t1, t0, STATUSF_IP3 /* int1 hardware line */
- bnez t1, ll_sec_enet_irq
- andi t1, t0, STATUSF_IP4 /* int2 hardware line */
- bnez t1, ll_uart1_irq
- andi t1, t0, STATUSF_IP5 /* int3 hardware line */
- bnez t1, ll_cpci_irq
- andi t1, t0, STATUSF_IP6 /* int4 hardware line */
- bnez t1, ll_galileo_irq
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cputimer_irq
-
- /* now look at the extended interrupts */
- mfc0 t0, CP0_CAUSE
- cfc0 t1, CP0_S1_INTCONTROL
-
- /* shift the mask 8 bits left to line up the bits */
- sll t2, t1, 8
-
- and t0, t2
- srl t0, t0, 16
-
- andi t1, t0, STATUSF_IP8 /* int6 hardware line */
- bnez t1, ll_pmc1_irq
- andi t1, t0, STATUSF_IP9 /* int7 hardware line */
- bnez t1, ll_pmc2_irq
- andi t1, t0, STATUSF_IP10 /* int8 hardware line */
- bnez t1, ll_cpci_abcd_irq
- andi t1, t0, STATUSF_IP11 /* int9 hardware line */
- bnez t1, ll_uart2_irq
-
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(ocelot_handle_int)
-
- .align 5
-ll_pri_enet_irq:
- li a0, 2
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_sec_enet_irq:
- li a0, 3
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_uart1_irq:
- li a0, 4
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpci_irq:
- li a0, 5
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_galileo_irq:
- li a0, 6
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, 7
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pmc1_irq:
- li a0, 8
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pmc2_irq:
- li a0, 9
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpci_abcd_irq:
- li a0, 10
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_uart2_irq:
- li a0, 11
- move a1, sp
- jal do_IRQ
- j ret_from_irq
diff --git a/arch/mips/gt64120/momenco_ocelot/irq.c b/arch/mips/gt64120/momenco_ocelot/irq.c
index 4f108da71b2..885f67f32ea 100644
--- a/arch/mips/gt64120/momenco_ocelot/irq.c
+++ b/arch/mips/gt64120/momenco_ocelot/irq.c
@@ -48,7 +48,38 @@
#include <asm/mipsregs.h>
#include <asm/system.h>
-extern asmlinkage void ocelot_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause();
+
+ if (pending & STATUSF_IP2) /* int0 hardware line */
+ do_IRQ(2, regs);
+ else if (pending & STATUSF_IP3) /* int1 hardware line */
+ do_IRQ(3, regs);
+ else if (pending & STATUSF_IP4) /* int2 hardware line */
+ do_IRQ(4, regs);
+ else if (pending & STATUSF_IP5) /* int3 hardware line */
+ do_IRQ(5, regs);
+ else if (pending & STATUSF_IP6) /* int4 hardware line */
+ do_IRQ(6, regs);
+ else if (pending & STATUSF_IP7) /* cpu timer */
+ do_IRQ(7, regs);
+ else {
+ /*
+ * Now look at the extended interrupts
+ */
+ pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+ if (pending & STATUSF_IP8) /* int6 hardware line */
+ do_IRQ(8, regs);
+ else if (pending & STATUSF_IP9) /* int7 hardware line */
+ do_IRQ(9, regs);
+ else if (pending & STATUSF_IP10) /* int8 hardware line */
+ do_IRQ(10, regs);
+ else if (pending & STATUSF_IP11) /* int9 hardware line */
+ do_IRQ(11, regs);
+ }
+}
void __init arch_init_irq(void)
{
@@ -59,9 +90,6 @@ void __init arch_init_irq(void)
clear_c0_status(ST0_IM);
local_irq_disable();
- /* Sets the first-level interrupt dispatcher. */
- set_except_vector(0, ocelot_handle_int);
-
mips_cpu_irq_init(0);
rm7k_cpu_irq_init(8);
}
diff --git a/arch/mips/ite-boards/generic/Makefile b/arch/mips/ite-boards/generic/Makefile
index 0e7853f4398..63431538d0e 100644
--- a/arch/mips/ite-boards/generic/Makefile
+++ b/arch/mips/ite-boards/generic/Makefile
@@ -6,7 +6,7 @@
# Makefile for the ITE 8172 (qed-4n-s01b) board, generic files.
#
-obj-y += it8172_setup.o irq.o int-handler.o pmon_prom.o \
+obj-y += it8172_setup.o irq.o pmon_prom.o \
time.o lpc.o puts.o reset.o
obj-$(CONFIG_IT8172_CIR)+= it8172_cir.o
diff --git a/arch/mips/ite-boards/generic/dbg_io.c b/arch/mips/ite-boards/generic/dbg_io.c
index c4f8530fd07..6a7ccaf9350 100644
--- a/arch/mips/ite-boards/generic/dbg_io.c
+++ b/arch/mips/ite-boards/generic/dbg_io.c
@@ -72,7 +72,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
/* disable interrupts */
UART16550_WRITE(OFS_INTR_ENABLE, 0);
- /* set up buad rate */
+ /* set up baud rate */
{
uint32 divisor;
diff --git a/arch/mips/ite-boards/generic/int-handler.S b/arch/mips/ite-boards/generic/int-handler.S
deleted file mode 100644
index d190d8add9c..00000000000
--- a/arch/mips/ite-boards/generic/int-handler.S
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .text
- .set macro
- .set noat
- .align 5
-
-NESTED(it8172_IRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI # Important: mark KERNEL mode !
-
- /* We're working with 'reorder' set at this point. */
- /*
- * Get pending interrupts
- */
-
- mfc0 t0,CP0_CAUSE # get pending interrupts
- mfc0 t1,CP0_STATUS # get enabled interrupts
- and t0,t1 # isolate allowed ones
-
- andi t0,0xff00 # isolate pending bits
- beqz t0, 3f # spurious interrupt
-
- andi a0, t0, CAUSEF_IP7
- beq a0, zero, 1f
-
- li a0, 127 # MIPS_CPU_TIMER_IRQ = (NR_IRQS-1)
- move a1, sp
- jal ll_timer_interrupt
- j ret_from_irq
- nop
-
-1:
- andi a0, t0, CAUSEF_IP2 # the only int we expect at this time
- beq a0, zero, 3f
- move a0,sp
- jal it8172_hw0_irqdispatch
-
- mfc0 t0,CP0_STATUS # disable interrupts
- ori t0,1
- xori t0,1
- mtc0 t0,CP0_STATUS
- nop
- nop
- nop
-
- la a1, ret_from_irq
- jr a1
- nop
-
-3:
- move a0, sp
- jal mips_spurious_interrupt
- nop
- la a1, ret_from_irq
- jr a1
- nop
-
-END(it8172_IRQ)
-
diff --git a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c
index e67f9612949..77be7216bdd 100644
--- a/arch/mips/ite-boards/generic/irq.c
+++ b/arch/mips/ite-boards/generic/irq.c
@@ -62,12 +62,8 @@
#define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
-void disable_it8172_irq(unsigned int irq_nr);
-void enable_it8172_irq(unsigned int irq_nr);
-
extern void set_debug_traps(void);
extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
-extern asmlinkage void it8172_IRQ(void);
struct it8172_intc_regs volatile *it8172_hw0_icregs =
(struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE));
@@ -181,8 +177,6 @@ void __init arch_init_irq(void)
int i;
unsigned long flags;
- set_except_vector(0, it8172_IRQ);
-
/* mask all interrupts */
it8172_hw0_icregs->lb_mask = 0xffff;
it8172_hw0_icregs->lpc_mask = 0xffff;
@@ -282,6 +276,18 @@ void it8172_hw0_irqdispatch(struct pt_regs *regs)
do_IRQ(irq, regs);
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (!pending)
+ mips_spurious_interrupt(regs);
+ else if (pending & CAUSEF_IP7)
+ ll_timer_interrupt(127, regs);
+ else if (pending & CAUSEF_IP2)
+ it8172_hw0_irqdispatch(regs);
+}
+
void show_pending_irqs(void)
{
fputs("intstatus: ");
diff --git a/arch/mips/ite-boards/generic/time.c b/arch/mips/ite-boards/generic/time.c
index f5d67ee21ac..dee497a9180 100644
--- a/arch/mips/ite-boards/generic/time.c
+++ b/arch/mips/ite-boards/generic/time.c
@@ -29,6 +29,7 @@
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/spinlock.h>
+#include <linux/mc146818rtc.h>
#include <asm/time.h>
#include <asm/mipsregs.h>
@@ -227,8 +228,8 @@ void __init it8172_time_init(void)
local_irq_restore(flags);
- rtc_get_time = it8172_rtc_get_time;
- rtc_set_time = it8172_rtc_set_time;
+ rtc_mips_get_time = it8172_rtc_get_time;
+ rtc_mips_set_time = it8172_rtc_set_time;
}
#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
diff --git a/arch/mips/ite-boards/ivr/init.c b/arch/mips/ite-boards/ivr/init.c
index ea4e1935fec..05cf9218c43 100644
--- a/arch/mips/ite-boards/ivr/init.c
+++ b/arch/mips/ite-boards/ivr/init.c
@@ -34,20 +34,17 @@
#include <asm/bootinfo.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <asm/sections.h>
#include <asm/it8172/it8172.h>
#include <asm/it8172/it8172_dbg.h>
int prom_argc;
char **prom_argv, **prom_envp;
-extern char _end;
extern void __init prom_init_cmdline(void);
extern unsigned long __init prom_get_memsize(void);
extern void __init it8172_init_ram_resource(unsigned long memsize);
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
const char *get_system_type(void)
{
return "Globespan IVR";
diff --git a/arch/mips/ite-boards/qed-4n-s01b/init.c b/arch/mips/ite-boards/qed-4n-s01b/init.c
index 56dca7e0c21..ea2a754cafe 100644
--- a/arch/mips/ite-boards/qed-4n-s01b/init.c
+++ b/arch/mips/ite-boards/qed-4n-s01b/init.c
@@ -34,20 +34,17 @@
#include <asm/bootinfo.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <asm/sections.h>
#include <asm/it8172/it8172.h>
#include <asm/it8172/it8172_dbg.h>
int prom_argc;
char **prom_argv, **prom_envp;
-extern char _end;
extern void __init prom_init_cmdline(void);
extern unsigned long __init prom_get_memsize(void);
extern void __init it8172_init_ram_resource(unsigned long memsize);
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
const char *get_system_type(void)
{
return "ITE QED-4N-S01B";
diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile
index 85749246a67..02bd39add89 100644
--- a/arch/mips/jazz/Makefile
+++ b/arch/mips/jazz/Makefile
@@ -2,6 +2,6 @@
# Makefile for the Jazz family specific parts of the kernel
#
-obj-y := int-handler.o irq.o jazzdma.o reset.o setup.o
+obj-y := irq.o jazzdma.o reset.o setup.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/jazz/int-handler.S b/arch/mips/jazz/int-handler.S
deleted file mode 100644
index dc752c67b52..00000000000
--- a/arch/mips/jazz/int-handler.S
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle and Andreas Busse
- *
- * Jazz family specific interrupt stuff
- *
- * To do: On Jazz machines we remap some non-ISA interrupts to ISA
- * interrupts. These interrupts should use their own vectors.
- * Squeeze the last cycles out of the handlers. Only a dead
- * cycle is a good cycle.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/jazz.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * jazz_handle_int: Interrupt handler for the ACER Pica-61 boards
- */
- .set noreorder
-
- NESTED(jazz_handle_int, PT_SIZE, ra)
- .set noat
- SAVE_ALL
- CLI
- .set at
-
- /*
- * Get pending interrupts
- */
- mfc0 t0,CP0_CAUSE # get pending interrupts
- mfc0 t1,CP0_STATUS # get enabled interrupts
- and t0,t1 # isolate allowed ones
- andi t0,0xff00 # isolate pending bits
- beqz t0,3f
- sll t0,16 # delay slot
-
- /*
- * Find irq with highest priority
- * FIXME: This is slow - use binary search
- */
- la t1,ll_vectors
-1: bltz t0,2f # found pending irq
- sll t0,1
- b 1b
- subu t1,PTRSIZE # delay slot
-
- /*
- * Do the low-level stuff
- */
-2: lw t0,(t1)
- jr t0
- nop # delay slot
- END(jazz_handle_int)
-
-ll_sw0: li s1,~IE_SW0
- mfc0 t0,CP0_CAUSE
- and t0,s1
- mtc0 t0,CP0_CAUSE
- PANIC("Unimplemented sw0 handler")
-
-ll_sw1: li s1,~IE_SW1
- mfc0 t0,CP0_CAUSE
- and t0,s1
- mtc0 t0,CP0_CAUSE
- PANIC("Unimplemented sw1 handler")
-
-ll_local_dma: li s1,~IE_IRQ0
- PANIC("Unimplemented local_dma handler")
-
-ll_local_dev: lbu t0,JAZZ_IO_IRQ_SOURCE
-#if PTRSIZE == 8 /* True 64 bit kernel */
- dsll t0,1
-#endif
- .set reorder
- LONG_L t0,local_vector(t0)
- jr t0
- .set noreorder
-
-/*
- * The braindead PICA hardware gives us no way to distinguish if we really
- * received interrupt 7 from the (E)ISA bus or if we just received an
- * interrupt with no findable cause. This sometimes happens with braindead
- * cards. Oh well - for all the Jazz boxes slots are more or less just
- * whistles and bells and we're aware of the problem.
- */
-ll_isa_irq: lw a0, JAZZ_EISA_IRQ_ACK
-
- jal do_IRQ
- move a1,sp
-
- j ret_from_irq
- nop
-
-/*
- * Hmm... This is not just a plain PC clone so the question is
- * which devices on Jazz machines can generate an (E)ISA NMI?
- * (Writing to nonexistent memory?)
- */
-ll_isa_nmi: li s1,~IE_IRQ3
- PANIC("Unimplemented isa_nmi handler")
-
-/*
- * Timer IRQ - remapped to be more similar to an IBM compatible.
- *
- * The timer interrupt is handled specially to ensure that the jiffies
- * variable is updated at all times. Specifically, the timer interrupt is
- * just like the complete handlers except that it is invoked with interrupts
- * disabled and should never re-enable them. If other interrupts were
- * allowed to be processed while the timer interrupt is active, then the
- * other interrupts would have to avoid using the jiffies variable for delay
- * and interval timing operations to avoid hanging the system.
- */
-ll_timer: lw zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
- li s1,~IE_IRQ4
-
- li a0, JAZZ_TIMER_IRQ
- jal do_IRQ
- move a1,sp
-
- mfc0 t0,CP0_STATUS # disable interrupts again
- ori t0,1
- xori t0,1
- mtc0 t0,CP0_STATUS
-
- j ret_from_irq
- nop
-
-/*
- * CPU count/compare IRQ (unused)
- */
-ll_count: j ret_from_irq
- mtc0 zero,CP0_COMPARE
-
-#if 0
-/*
- * Call the handler for the interrupt
- * (Currently unused)
- */
-call_real: /*
- * temporarily disable interrupt
- */
- mfc0 t2,CP0_STATUS
- and t2,s1
- mtc0 t2,CP0_STATUS
- nor s1,zero,s1
- jal do_IRQ
-
- /*
- * reenable interrupt
- */
- mfc0 t2,CP0_STATUS
- or t2,s1
- mtc0 t2,CP0_STATUS
- j ret_from_irq
-#endif
-
- .data
- PTR ll_sw0 # SW0
- PTR ll_sw1 # SW1
- PTR ll_local_dma # Local DMA
- PTR ll_local_dev # Local devices
- PTR ll_isa_irq # ISA IRQ
- PTR ll_isa_nmi # ISA NMI
- PTR ll_timer # Timer
-ll_vectors: PTR ll_count # Count/Compare IRQ
-
- /*
- * Interrupt handlers for local devices.
- */
- .text
- .set reorder
-loc_no_irq: PANIC("Unimplemented loc_no_irq handler")
-/*
- * Parallel port IRQ
- */
-loc_parallel: li s1,~JAZZ_IE_PARALLEL
- li a0,JAZZ_PARALLEL_IRQ
- b loc_call
-
-/*
- * Floppy IRQ
- */
-loc_floppy: li s1,~JAZZ_IE_FLOPPY
- li a0,JAZZ_FLOPPY_IRQ
- b loc_call
-
-/*
- * Sound IRQ
- */
-loc_sound: PANIC("Unimplemented loc_sound handler")
-loc_video: PANIC("Unimplemented loc_video handler")
-
-/*
- * Ethernet interrupt handler
- */
-loc_ethernet: li s1,~JAZZ_IE_ETHERNET
- li a0,JAZZ_ETHERNET_IRQ
- b loc_call
-
-/*
- * SCSI interrupt handler
- */
-loc_scsi: li s1,~JAZZ_IE_SCSI
- li a0,JAZZ_SCSI_IRQ
- b loc_call
-
-/*
- * Keyboard interrupt handler
- */
-loc_keyboard: li s1,~JAZZ_IE_KEYBOARD
- li a0,JAZZ_KEYBOARD_IRQ
- b loc_call
-
-/*
- * Mouse interrupt handler
- */
-loc_mouse: li s1,~JAZZ_IE_MOUSE
- li a0,JAZZ_MOUSE_IRQ
- b loc_call
-
-/*
- * Serial port 1 IRQ
- */
-loc_serial1: li s1,~JAZZ_IE_SERIAL1
- li a0,JAZZ_SERIAL1_IRQ
- b loc_call
-
-/*
- * Serial port 2 IRQ
- */
-loc_serial2: li s1,~JAZZ_IE_SERIAL2
- li a0,JAZZ_SERIAL2_IRQ
- b loc_call
-
-/*
- * Call the interrupt handler for an interrupt generated by a
- * local device.
- */
-loc_call: /*
- * Temporarily disable interrupt source
- */
- lhu t2,JAZZ_IO_IRQ_ENABLE
- and t2,s1
- sh t2,JAZZ_IO_IRQ_ENABLE
-
- nor s1,zero,s1
- jal do_IRQ
-
- /*
- * Reenable interrupt
- */
- lhu t2,JAZZ_IO_IRQ_ENABLE
- or t2,s1
- sh t2,JAZZ_IO_IRQ_ENABLE
-
- j ret_from_irq
-
-/*
- * "Jump extender" to reach spurious_interrupt
- */
-3: j spurious_interrupt
-
-/*
- * Vectors for interrupts generated by local devices
- */
- .data
-local_vector: PTR loc_no_irq
- PTR loc_parallel
- PTR loc_floppy
- PTR loc_sound
- PTR loc_video
- PTR loc_ethernet
- PTR loc_scsi
- PTR loc_keyboard
- PTR loc_mouse
- PTR loc_serial1
- PTR loc_serial2
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index b309b1bcf2e..becc9accd49 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -15,8 +15,6 @@
#include <asm/io.h>
#include <asm/jazz.h>
-extern asmlinkage void jazz_handle_int(void);
-
static DEFINE_SPINLOCK(r4030_lock);
static void enable_r4030_irq(unsigned int irq)
@@ -90,10 +88,82 @@ void __init init_r4030_ints(void)
*/
void __init arch_init_irq(void)
{
- set_except_vector(0, jazz_handle_int);
-
init_i8259_irqs(); /* Integrated i8259 */
init_r4030_ints();
change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
}
+
+static void loc_call(unsigned int irq, struct pt_regs *regs, unsigned int mask)
+{
+ r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+ r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask);
+ do_IRQ(irq, regs);
+ r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+ r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask);
+}
+
+static void ll_local_dev(struct pt_regs *regs)
+{
+ switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) {
+ case 0:
+ panic("Unimplemented loc_no_irq handler");
+ break;
+ case 4:
+ loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_PARALLEL);
+ break;
+ case 8:
+ loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_FLOPPY);
+ break;
+ case 12:
+ panic("Unimplemented loc_sound handler");
+ break;
+ case 16:
+ panic("Unimplemented loc_video handler");
+ break;
+ case 20:
+ loc_call(JAZZ_ETHERNET_IRQ, regs, JAZZ_IE_ETHERNET);
+ break;
+ case 24:
+ loc_call(JAZZ_SCSI_IRQ, regs, JAZZ_IE_SCSI);
+ break;
+ case 28:
+ loc_call(JAZZ_KEYBOARD_IRQ, regs, JAZZ_IE_KEYBOARD);
+ break;
+ case 32:
+ loc_call(JAZZ_MOUSE_IRQ, regs, JAZZ_IE_MOUSE);
+ break;
+ case 36:
+ loc_call(JAZZ_SERIAL1_IRQ, regs, JAZZ_IE_SERIAL1);
+ break;
+ case 40:
+ loc_call(JAZZ_SERIAL2_IRQ, regs, JAZZ_IE_SERIAL2);
+ break;
+ }
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (pending & IE_IRQ5)
+ write_c0_compare(0);
+ else if (pending & IE_IRQ4) {
+ r4030_read_reg32(JAZZ_TIMER_REGISTER);
+ do_IRQ(JAZZ_TIMER_IRQ, regs);
+ } else if (pending & IE_IRQ3)
+ panic("Unimplemented ISA NMI handler");
+ else if (pending & IE_IRQ2)
+ do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK), regs);
+ else if (pending & IE_IRQ1) {
+ ll_local_dev(regs);
+ } else if (unlikely(pending & IE_IRQ0))
+ panic("Unimplemented local_dma handler");
+ else if (pending & IE_SW1) {
+ clear_c0_cause(IE_SW1);
+ panic("Unimplemented sw1 handler");
+ } else if (pending & IE_SW0) {
+ clear_c0_cause(IE_SW0);
+ panic("Unimplemented sw0 handler");
+ }
+}
diff --git a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c
index 9a8bff153d8..e6561345d12 100644
--- a/arch/mips/jmr3927/common/rtc_ds1742.c
+++ b/arch/mips/jmr3927/common/rtc_ds1742.c
@@ -60,15 +60,15 @@ rtc_ds1742_get_time(void)
unsigned long flags;
spin_lock_irqsave(&rtc_lock, flags);
- CMOS_WRITE(RTC_READ, RTC_CONTROL);
- second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
- minute = BCD2BIN(CMOS_READ(RTC_MINUTES));
- hour = BCD2BIN(CMOS_READ(RTC_HOURS));
- day = BCD2BIN(CMOS_READ(RTC_DATE));
- month = BCD2BIN(CMOS_READ(RTC_MONTH));
- year = BCD2BIN(CMOS_READ(RTC_YEAR));
- century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK);
- CMOS_WRITE(0, RTC_CONTROL);
+ rtc_write(RTC_READ, RTC_CONTROL);
+ second = BCD2BIN(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
+ minute = BCD2BIN(rtc_read(RTC_MINUTES));
+ hour = BCD2BIN(rtc_read(RTC_HOURS));
+ day = BCD2BIN(rtc_read(RTC_DATE));
+ month = BCD2BIN(rtc_read(RTC_MONTH));
+ year = BCD2BIN(rtc_read(RTC_YEAR));
+ century = BCD2BIN(rtc_read(RTC_CENTURY) & RTC_CENTURY_MASK);
+ rtc_write(0, RTC_CONTROL);
spin_unlock_irqrestore(&rtc_lock, flags);
year += century * 100;
@@ -87,16 +87,16 @@ rtc_ds1742_set_time(unsigned long t)
unsigned long flags;
spin_lock_irqsave(&rtc_lock, flags);
- CMOS_WRITE(RTC_READ, RTC_CONTROL);
- cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
- cmos_minute = (u8)CMOS_READ(RTC_MINUTES);
- cmos_hour = (u8)CMOS_READ(RTC_HOURS);
- cmos_day = (u8)CMOS_READ(RTC_DATE);
- cmos_month = (u8)CMOS_READ(RTC_MONTH);
- cmos_year = (u8)CMOS_READ(RTC_YEAR);
- cmos_century = CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK;
+ rtc_write(RTC_READ, RTC_CONTROL);
+ cmos_second = (u8)(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
+ cmos_minute = (u8)rtc_read(RTC_MINUTES);
+ cmos_hour = (u8)rtc_read(RTC_HOURS);
+ cmos_day = (u8)rtc_read(RTC_DATE);
+ cmos_month = (u8)rtc_read(RTC_MONTH);
+ cmos_year = (u8)rtc_read(RTC_YEAR);
+ cmos_century = rtc_read(RTC_CENTURY) & RTC_CENTURY_MASK;
- CMOS_WRITE(RTC_WRITE, RTC_CONTROL);
+ rtc_write(RTC_WRITE, RTC_CONTROL);
/* convert */
to_tm(t, &tm);
@@ -104,18 +104,18 @@ rtc_ds1742_set_time(unsigned long t)
/* check each field one by one */
year = BIN2BCD(tm.tm_year - EPOCH);
if (year != cmos_year) {
- CMOS_WRITE(year,RTC_YEAR);
+ rtc_write(year,RTC_YEAR);
}
month = BIN2BCD(tm.tm_mon);
if (month != (cmos_month & 0x1f)) {
- CMOS_WRITE((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH);
+ rtc_write((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH);
}
day = BIN2BCD(tm.tm_mday);
if (day != cmos_day) {
- CMOS_WRITE(day, RTC_DATE);
+ rtc_write(day, RTC_DATE);
}
if (cmos_hour & 0x40) {
@@ -130,20 +130,20 @@ rtc_ds1742_set_time(unsigned long t)
/* 24 hour format */
hour = BIN2BCD(tm.tm_hour) & 0x3f;
}
- if (hour != cmos_hour) CMOS_WRITE(hour, RTC_HOURS);
+ if (hour != cmos_hour) rtc_write(hour, RTC_HOURS);
minute = BIN2BCD(tm.tm_min);
if (minute != cmos_minute) {
- CMOS_WRITE(minute, RTC_MINUTES);
+ rtc_write(minute, RTC_MINUTES);
}
second = BIN2BCD(tm.tm_sec);
if (second != cmos_second) {
- CMOS_WRITE(second & RTC_SECONDS_MASK,RTC_SECONDS);
+ rtc_write(second & RTC_SECONDS_MASK,RTC_SECONDS);
}
/* RTC_CENTURY and RTC_CONTROL share same address... */
- CMOS_WRITE(cmos_century, RTC_CONTROL);
+ rtc_write(cmos_century, RTC_CONTROL);
spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
@@ -159,13 +159,13 @@ rtc_ds1742_init(unsigned long base)
db_assert((rtc_base & 0xe0000000) == KSEG1);
/* set the function pointers */
- rtc_get_time = rtc_ds1742_get_time;
- rtc_set_time = rtc_ds1742_set_time;
+ rtc_mips_get_time = rtc_ds1742_get_time;
+ rtc_mips_set_time = rtc_ds1742_set_time;
/* clear oscillator stop bit */
- CMOS_WRITE(RTC_READ, RTC_CONTROL);
- cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
- CMOS_WRITE(RTC_WRITE, RTC_CONTROL);
- CMOS_WRITE(cmos_second, RTC_SECONDS); /* clear msb */
- CMOS_WRITE(0, RTC_CONTROL);
+ rtc_write(RTC_READ, RTC_CONTROL);
+ cmos_second = (u8)(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
+ rtc_write(RTC_WRITE, RTC_CONTROL);
+ rtc_write(cmos_second, RTC_SECONDS); /* clear msb */
+ rtc_write(0, RTC_CONTROL);
}
diff --git a/arch/mips/jmr3927/rbhma3100/Makefile b/arch/mips/jmr3927/rbhma3100/Makefile
index 75bf418b94c..baf5077813c 100644
--- a/arch/mips/jmr3927/rbhma3100/Makefile
+++ b/arch/mips/jmr3927/rbhma3100/Makefile
@@ -2,7 +2,7 @@
# Makefile for TOSHIBA JMR-TX3927 board
#
-obj-y += init.o int-handler.o irq.o setup.o
+obj-y += init.o irq.o setup.o
obj-$(CONFIG_RUNTIME_DEBUG) += debug.o
obj-$(CONFIG_KGDB) += kgdb_io.o
diff --git a/arch/mips/jmr3927/rbhma3100/int-handler.S b/arch/mips/jmr3927/rbhma3100/int-handler.S
deleted file mode 100644
index f85bbf40754..00000000000
--- a/arch/mips/jmr3927/rbhma3100/int-handler.S
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ahennessy@mvista.com
- *
- * Based on arch/mips/tsdb/kernel/int-handler.S
- *
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/jmr3927/jmr3927.h>
-
- /* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop
- * and moving across all the pending IRQ bits in the cause
- * register is _NOT_ the answer, the common case is one
- * pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register
- * IRQ mask, that would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs
- * off, nothing in between like BSD spl() brain-damage.
- *
- */
-
-/* Flush write buffer (needed?)
- * NOTE: TX39xx performs "non-blocking load", so explicitly use the target
- * register of LBU to flush immediately.
- */
-#define FLUSH_WB(tmp) \
- la tmp, JMR3927_IOC_REV_ADDR; \
- lbu tmp, (tmp); \
- move tmp, zero;
-
- .text
- .set noreorder
- .set noat
- .align 5
- NESTED(jmr3927_IRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- jal jmr3927_irc_irqdispatch
- move a0, sp
- FLUSH_WB(t0)
- j ret_from_irq
- nop
- END(jmr3927_IRQ)
diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c
index 2810727f1d4..11304d1354f 100644
--- a/arch/mips/jmr3927/rbhma3100/irq.c
+++ b/arch/mips/jmr3927/rbhma3100/irq.c
@@ -77,8 +77,6 @@ static int jmr3927_gen_iack(void)
}
#endif
-extern asmlinkage void jmr3927_IRQ(void);
-
#define irc_dlevel 0
#define irc_elevel 1
@@ -262,7 +260,7 @@ void jmr3927_spurious(struct pt_regs *regs)
regs->cp0_cause, regs->cp0_epc, regs->regs[31]);
}
-void jmr3927_irc_irqdispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
int irq;
@@ -398,8 +396,6 @@ void __init arch_init_irq(void)
jmr3927_irq_init(NR_ISA_IRQS);
- set_except_vector(0, jmr3927_IRQ);
-
/* setup irq space */
add_tb_irq_space(&jmr3927_isac_irqspace);
add_tb_irq_space(&jmr3927_ioc_irqspace);
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index f36c4f20ee8..34e8a256765 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -34,8 +34,11 @@ obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_MIPS_MT_SMP) += smp_mt.o
+obj-$(CONFIG_MIPS_MT) += mips-mt.o
+obj-$(CONFIG_MIPS_MT_SMTC) += smtc.o smtc-asm.o smtc-proc.o
+obj-$(CONFIG_MIPS_MT_SMP) += smp-mt.o
+obj-$(CONFIG_MIPS_APSP_KSPD) += kspd.o
obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o
obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o
@@ -59,6 +62,8 @@ obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_64BIT) += cpu-bugs64.o
+obj-$(CONFIG_I8253) += i8253.o
+
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index ca6b03c773b..0facfaf4e95 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -69,6 +69,9 @@ void output_ptreg_defines(void)
offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr);
offset("#define PT_STATUS ", struct pt_regs, cp0_status);
offset("#define PT_CAUSE ", struct pt_regs, cp0_cause);
+#ifdef CONFIG_MIPS_MT_SMTC
+ offset("#define PT_TCSTATUS ", struct pt_regs, cp0_tcstatus);
+#endif /* CONFIG_MIPS_MT_SMTC */
size("#define PT_SIZE ", struct pt_regs);
linefeed;
}
@@ -269,8 +272,8 @@ void output_sc_defines(void)
text("/* Linux sigcontext offsets. */");
offset("#define SC_REGS ", struct sigcontext, sc_regs);
offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs);
- offset("#define SC_MDHI ", struct sigcontext, sc_hi);
- offset("#define SC_MDLO ", struct sigcontext, sc_lo);
+ offset("#define SC_MDHI ", struct sigcontext, sc_mdhi);
+ offset("#define SC_MDLO ", struct sigcontext, sc_mdlo);
offset("#define SC_PC ", struct sigcontext, sc_pc);
offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
linefeed;
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 374de839558..b6232d9033c 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -184,7 +184,7 @@ int __compute_return_epc(struct pt_regs *regs)
bit = (insn.i_format.rt >> 2);
bit += (bit != 0);
bit += 23;
- switch (insn.i_format.rt) {
+ switch (insn.i_format.rt & 3) {
case 0: /* bc1f */
case 2: /* bc1fl */
if (~fcr31 & (1 << bit))
diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c
index 47a087b6c11..d268827c62b 100644
--- a/arch/mips/kernel/cpu-bugs64.c
+++ b/arch/mips/kernel/cpu-bugs64.c
@@ -206,7 +206,7 @@ static inline void check_daddi(void)
"daddi %0, %1, %3\n\t"
".set pop"
: "=r" (v), "=&r" (tmp)
- : "I" (0xffffffffffffdb9a), "I" (0x1234));
+ : "I" (0xffffffffffffdb9aUL), "I" (0x1234));
set_except_vector(12, handler);
local_irq_restore(flags);
@@ -224,7 +224,7 @@ static inline void check_daddi(void)
"dsrl %1, %1, 1\n\t"
"daddi %0, %1, %3"
: "=r" (v), "=&r" (tmp)
- : "I" (0xffffffffffffdb9a), "I" (0x1234));
+ : "I" (0xffffffffffffdb9aUL), "I" (0x1234));
set_except_vector(12, handler);
local_irq_restore(flags);
@@ -280,7 +280,7 @@ static inline void check_daddiu(void)
"daddu %1, %2\n\t"
".set pop"
: "=&r" (v), "=&r" (w), "=&r" (tmp)
- : "I" (0xffffffffffffdb9a), "I" (0x1234));
+ : "I" (0xffffffffffffdb9aUL), "I" (0x1234));
if (v == w) {
printk("no.\n");
@@ -296,7 +296,7 @@ static inline void check_daddiu(void)
"addiu %1, $0, %4\n\t"
"daddu %1, %2"
: "=&r" (v), "=&r" (w), "=&r" (tmp)
- : "I" (0xffffffffffffdb9a), "I" (0x1234));
+ : "I" (0xffffffffffffdb9aUL), "I" (0x1234));
if (v == w) {
printk("yes.\n");
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 58b3b14873c..8c2c359a05f 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -121,6 +121,7 @@ static inline void check_wait(void)
case CPU_24K:
case CPU_25KF:
case CPU_34K:
+ case CPU_74K:
case CPU_PR4450:
cpu_wait = r4k_wait;
printk(" available.\n");
@@ -432,6 +433,15 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
MIPS_CPU_LLSC;
c->tlbsize = 64;
break;
+ case PRID_IMP_R14000:
+ c->cputype = CPU_R14000;
+ c->isa_level = MIPS_CPU_ISA_IV;
+ c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
+ MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
+ MIPS_CPU_LLSC;
+ c->tlbsize = 64;
+ break;
}
}
@@ -593,6 +603,9 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c)
case PRID_IMP_34K:
c->cputype = CPU_34K;
break;
+ case PRID_IMP_74K:
+ c->cputype = CPU_74K;
+ break;
}
}
@@ -642,7 +655,7 @@ static inline void cpu_probe_sibyte(struct cpuinfo_mips *c)
case PRID_IMP_SB1:
c->cputype = CPU_SB1;
/* FPU in pass1 is known to have issues. */
- if ((c->processor_id & 0xff) < 0x20)
+ if ((c->processor_id & 0xff) < 0x02)
c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
break;
case PRID_IMP_SB1A:
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 83c87fe4ee4..a9c6de1b954 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -17,6 +17,9 @@
#include <asm/isadep.h>
#include <asm/thread_info.h>
#include <asm/war.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif
#ifdef CONFIG_PREEMPT
.macro preempt_stop
@@ -75,6 +78,37 @@ FEXPORT(syscall_exit)
bnez t0, syscall_exit_work
FEXPORT(restore_all) # restore full frame
+#ifdef CONFIG_MIPS_MT_SMTC
+/* Detect and execute deferred IPI "interrupts" */
+ move a0,sp
+ jal deferred_smtc_ipi
+/* Re-arm any temporarily masked interrupts not explicitly "acked" */
+ mfc0 v0, CP0_TCSTATUS
+ ori v1, v0, TCSTATUS_IXMT
+ mtc0 v1, CP0_TCSTATUS
+ andi v0, TCSTATUS_IXMT
+ ehb
+ mfc0 t0, CP0_TCCONTEXT
+ DMT 9 # dmt t1
+ jal mips_ihb
+ mfc0 t2, CP0_STATUS
+ andi t3, t0, 0xff00
+ or t2, t2, t3
+ mtc0 t2, CP0_STATUS
+ ehb
+ andi t1, t1, VPECONTROL_TE
+ beqz t1, 1f
+ EMT
+1:
+ mfc0 v1, CP0_TCSTATUS
+ /* We set IXMT above, XOR should clear it here */
+ xori v1, v1, TCSTATUS_IXMT
+ or v1, v0, v1
+ mtc0 v1, CP0_TCSTATUS
+ ehb
+ xor t0, t0, t3
+ mtc0 t0, CP0_TCCONTEXT
+#endif /* CONFIG_MIPS_MT_SMTC */
.set noat
RESTORE_TEMP
RESTORE_AT
@@ -120,28 +154,17 @@ syscall_exit_work:
jal do_syscall_trace
b resume_userspace
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT)
+
/*
- * Common spurious interrupt handler.
+ * MIPS32R2 Instruction Hazard Barrier - must be called
+ *
+ * For C code use the inline version named instruction_hazard().
*/
-LEAF(spurious_interrupt)
- /*
- * Someone tried to fool us by sending an interrupt but we
- * couldn't find a cause for it.
- */
- PTR_LA t1, irq_err_count
-#ifdef CONFIG_SMP
-1: ll t0, (t1)
- addiu t0, 1
- sc t0, (t1)
-#if R10000_LLSC_WAR
- beqzl t0, 1b
-#else
- beqz t0, 1b
-#endif
-#else
- lw t0, (t1)
- addiu t0, 1
- sw t0, (t1)
-#endif
- j ret_from_irq
- END(spurious_interrupt)
+LEAF(mips_ihb)
+ .set mips32r2
+ jr.hb ra
+ nop
+ END(mips_ihb)
+
+#endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */
diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S
index 235ad9f6bd3..5fd7a8af0c6 100644
--- a/arch/mips/kernel/gdb-low.S
+++ b/arch/mips/kernel/gdb-low.S
@@ -54,9 +54,11 @@
*/
mfc0 k0, CP0_CAUSE
andi k0, k0, 0x7c
- add k1, k1, k0
- PTR_L k0, saved_vectors(k1)
- jr k0
+#ifdef CONFIG_64BIT
+ dsll k0, k0, 1
+#endif
+ PTR_L k1, saved_vectors(k0)
+ jr k1
nop
1:
move k0, sp
@@ -283,11 +285,33 @@
*/
3:
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* Read-modify write of Status must be atomic */
+ mfc0 t2, CP0_TCSTATUS
+ ori t1, t2, TCSTATUS_IXMT
+ mtc0 t1, CP0_TCSTATUS
+ andi t2, t2, TCSTATUS_IXMT
+ ehb
+ DMT 9 # dmt t1
+ jal mips_ihb
+ nop
+#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t0, CP0_STATUS
ori t0, 0x1f
xori t0, 0x1f
mtc0 t0, CP0_STATUS
-
+#ifdef CONFIG_MIPS_MT_SMTC
+ andi t1, t1, VPECONTROL_TE
+ beqz t1, 9f
+ nop
+ EMT # emt
+9:
+ mfc0 t1, CP0_TCSTATUS
+ xori t1, t1, TCSTATUS_IXMT
+ or t1, t1, t2
+ mtc0 t1, CP0_TCSTATUS
+ ehb
+#endif /* CONFIG_MIPS_MT_SMTC */
LONG_L v0, GDB_FR_STATUS(sp)
LONG_L v1, GDB_FR_EPC(sp)
mtc0 v0, CP0_STATUS
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
index d4f88e0af24..6ecbdc1fefd 100644
--- a/arch/mips/kernel/gdb-stub.c
+++ b/arch/mips/kernel/gdb-stub.c
@@ -140,6 +140,7 @@
#include <asm/system.h>
#include <asm/gdb-stub.h>
#include <asm/inst.h>
+#include <asm/smp.h>
/*
* external low-level support routines
@@ -669,6 +670,64 @@ static void kgdb_wait(void *arg)
local_irq_restore(flags);
}
+/*
+ * GDB stub needs to call kgdb_wait on all processor with interrupts
+ * disabled, so it uses it's own special variant.
+ */
+static int kgdb_smp_call_kgdb_wait(void)
+{
+#ifdef CONFIG_SMP
+ struct call_data_struct data;
+ int i, cpus = num_online_cpus() - 1;
+ int cpu = smp_processor_id();
+
+ /*
+ * Can die spectacularly if this CPU isn't yet marked online
+ */
+ BUG_ON(!cpu_online(cpu));
+
+ if (!cpus)
+ return 0;
+
+ if (spin_is_locked(&smp_call_lock)) {
+ /*
+ * Some other processor is trying to make us do something
+ * but we're not going to respond... give up
+ */
+ return -1;
+ }
+
+ /*
+ * We will continue here, accepting the fact that
+ * the kernel may deadlock if another CPU attempts
+ * to call smp_call_function now...
+ */
+
+ data.func = kgdb_wait;
+ data.info = NULL;
+ atomic_set(&data.started, 0);
+ data.wait = 0;
+
+ spin_lock(&smp_call_lock);
+ call_data = &data;
+ mb();
+
+ /* Send a message to all other CPUs and wait for them to respond */
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i) && i != cpu)
+ core_send_ipi(i, SMP_CALL_FUNCTION);
+
+ /* Wait for response */
+ /* FIXME: lock-up detection, backtrace on lock-up */
+ while (atomic_read(&data.started) != cpus)
+ barrier();
+
+ call_data = NULL;
+ spin_unlock(&smp_call_lock);
+#endif
+
+ return 0;
+}
/*
* This function does all command processing for interfacing to gdb. It
@@ -718,7 +777,7 @@ void handle_exception (struct gdb_regs *regs)
/*
* force other cpus to enter kgdb
*/
- smp_call_function(kgdb_wait, NULL, 0, 0);
+ kgdb_smp_call_kgdb_wait();
/*
* If we're in breakpoint() increment the PC
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 13f22d1d0e8..ff7af369f28 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <asm/asm.h>
+#include <asm/asmmacro.h>
#include <asm/cacheops.h>
#include <asm/regdef.h>
#include <asm/fpregdef.h>
@@ -122,6 +123,20 @@ handle_vcei:
.set pop
END(except_vec3_r4000)
+ __FINIT
+
+ .align 5
+NESTED(handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+
+ PTR_LA ra, ret_from_irq
+ move a0, sp
+ j plat_irq_dispatch
+ END(handle_int)
+
+ __INIT
+
/*
* Special interrupt vector for MIPS64 ISA & embedded MIPS processors.
* This is a dedicated interrupt exception vector which reduces the
@@ -157,6 +172,15 @@ NESTED(except_vec_vi, 0, sp)
SAVE_AT
.set push
.set noreorder
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * To keep from blindly blocking *all* interrupts
+ * during service by SMTC kernel, we also want to
+ * pass the IM value to be cleared.
+ */
+EXPORT(except_vec_vi_mori)
+ ori a0, $0, 0
+#endif /* CONFIG_MIPS_MT_SMTC */
EXPORT(except_vec_vi_lui)
lui v0, 0 /* Patched */
j except_vec_vi_handler
@@ -173,6 +197,25 @@ EXPORT(except_vec_vi_end)
NESTED(except_vec_vi_handler, 0, sp)
SAVE_TEMP
SAVE_STATIC
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * SMTC has an interesting problem that interrupts are level-triggered,
+ * and the CLI macro will clear EXL, potentially causing a duplicate
+ * interrupt service invocation. So we need to clear the associated
+ * IM bit of Status prior to doing CLI, and restore it after the
+ * service routine has been invoked - we must assume that the
+ * service routine will have cleared the state, and any active
+ * level represents a new or otherwised unserviced event...
+ */
+ mfc0 t1, CP0_STATUS
+ and t0, a0, t1
+ mfc0 t2, CP0_TCCONTEXT
+ or t0, t0, t2
+ mtc0 t0, CP0_TCCONTEXT
+ xor t1, t1, t0
+ mtc0 t1, CP0_STATUS
+ ehb
+#endif /* CONFIG_MIPS_MT_SMTC */
CLI
move a0, sp
jalr v0
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 2e9122a4213..bdf6f6eff72 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -18,6 +18,7 @@
#include <linux/threads.h>
#include <asm/asm.h>
+#include <asm/asmmacro.h>
#include <asm/regdef.h>
#include <asm/page.h>
#include <asm/mipsregs.h>
@@ -82,12 +83,33 @@
*/
.macro setup_c0_status set clr
.set push
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * For SMTC, we need to set privilege and disable interrupts only for
+ * the current TC, using the TCStatus register.
+ */
+ mfc0 t0, CP0_TCSTATUS
+ /* Fortunately CU 0 is in the same place in both registers */
+ /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
+ li t1, ST0_CU0 | 0x08001c00
+ or t0, t1
+ /* Clear TKSU, leave IXMT */
+ xori t0, 0x00001800
+ mtc0 t0, CP0_TCSTATUS
+ ehb
+ /* We need to leave the global IE bit set, but clear EXL...*/
+ mfc0 t0, CP0_STATUS
+ or t0, ST0_CU0 | ST0_EXL | ST0_ERL | \set | \clr
+ xor t0, ST0_EXL | ST0_ERL | \clr
+ mtc0 t0, CP0_STATUS
+#else
mfc0 t0, CP0_STATUS
or t0, ST0_CU0|\set|0x1f|\clr
xor t0, 0x1f|\clr
mtc0 t0, CP0_STATUS
.set noreorder
sll zero,3 # ehb
+#endif
.set pop
.endm
@@ -134,6 +156,24 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
ARC64_TWIDDLE_PC
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * In SMTC kernel, "CLI" is thread-specific, in TCStatus.
+ * We still need to enable interrupts globally in Status,
+ * and clear EXL/ERL.
+ *
+ * TCContext is used to track interrupt levels under
+ * service in SMTC kernel. Clear for boot TC before
+ * allowing any interrupts.
+ */
+ mtc0 zero, CP0_TCCONTEXT
+
+ mfc0 t0, CP0_STATUS
+ ori t0, t0, 0xff1f
+ xori t0, t0, 0x001e
+ mtc0 t0, CP0_STATUS
+#endif /* CONFIG_MIPS_MT_SMTC */
+
PTR_LA t0, __bss_start # clear .bss
LONG_S zero, (t0)
PTR_LA t1, __bss_stop - LONGSIZE
@@ -166,8 +206,25 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
* function after setting up the stack and gp registers.
*/
NESTED(smp_bootstrap, 16, sp)
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * Read-modify-writes of Status must be atomic, and this
+ * is one case where CLI is invoked without EXL being
+ * necessarily set. The CLI and setup_c0_status will
+ * in fact be redundant for all but the first TC of
+ * each VPE being booted.
+ */
+ DMT 10 # dmt t2 /* t0, t1 are used by CLI and setup_c0_status() */
+ jal mips_ihb
+#endif /* CONFIG_MIPS_MT_SMTC */
setup_c0_status_sec
smp_slave_setup
+#ifdef CONFIG_MIPS_MT_SMTC
+ andi t2, t2, VPECONTROL_TE
+ beqz t2, 2f
+ EMT # emt
+2:
+#endif /* CONFIG_MIPS_MT_SMTC */
j start_secondary
END(smp_bootstrap)
#endif /* CONFIG_SMP */
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
new file mode 100644
index 00000000000..475df690421
--- /dev/null
+++ b/arch/mips/kernel/i8253.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2006 IBM Corporation
+ *
+ * Implements device information for i8253 timer chip
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation
+ */
+
+#include <linux/platform_device.h>
+
+static __init int add_pcspkr(void)
+{
+ struct platform_device *pd;
+ int ret;
+
+ pd = platform_device_alloc("pcspkr", -1);
+ if (!pd)
+ return -ENOMEM;
+
+ ret = platform_device_add(pd);
+ if (ret)
+ platform_device_put(pd);
+
+ return ret;
+}
+device_initcall(add_pcspkr);
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index b974ac9057f..2125ba5f1d9 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -187,6 +187,10 @@ handle_real_irq:
outb(cached_21,0x21);
outb(0x60+irq,0x20); /* 'Specific EOI' to master */
}
+#ifdef CONFIG_MIPS_MT_SMTC
+ if (irq_hwmask[irq] & ST0_IM)
+ set_c0_status(irq_hwmask[irq] & ST0_IM);
+#endif /* CONFIG_MIPS_MT_SMTC */
spin_unlock_irqrestore(&i8259A_lock, flags);
return;
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 08273a2a501..8150f071f80 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -603,7 +603,7 @@ repeat:
/* move to end of parent's list to avoid starvation */
write_lock_irq(&tasklist_lock);
remove_parent(p);
- add_parent(p, p->parent);
+ add_parent(p);
write_unlock_irq(&tasklist_lock);
retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
if (retval)
@@ -643,7 +643,7 @@ repeat:
write_lock_irq(&tasklist_lock);
remove_parent(p);
p->parent = p->real_parent;
- add_parent(p, p->parent);
+ add_parent(p);
do_notify_parent(p, SIGCHLD);
write_unlock_irq(&tasklist_lock);
} else
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index 3f653c7cfbf..97ebdc754b9 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -76,6 +76,11 @@ static void level_mask_and_ack_msc_irq(unsigned int irq)
mask_msc_irq(irq);
if (!cpu_has_veic)
MSCIC_WRITE(MSC01_IC_EOI, 0);
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* This actually needs to be a call into platform code */
+ if (irq_hwmask[irq] & ST0_IM)
+ set_c0_status(irq_hwmask[irq] & ST0_IM);
+#endif /* CONFIG_MIPS_MT_SMTC */
}
/*
@@ -92,6 +97,10 @@ static void edge_mask_and_ack_msc_irq(unsigned int irq)
MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
}
+#ifdef CONFIG_MIPS_MT_SMTC
+ if (irq_hwmask[irq] & ST0_IM)
+ set_c0_status(irq_hwmask[irq] & ST0_IM);
+#endif /* CONFIG_MIPS_MT_SMTC */
}
/*
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 3dd76b3d296..3dce742e716 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -38,6 +38,15 @@ void ack_bad_irq(unsigned int irq)
atomic_t irq_err_count;
+#ifdef CONFIG_MIPS_MT_SMTC
+/*
+ * SMTC Kernel needs to manipulate low-level CPU interrupt mask
+ * in do_IRQ. These are passed in setup_irq_smtc() and stored
+ * in this table.
+ */
+unsigned long irq_hwmask[NR_IRQS];
+#endif /* CONFIG_MIPS_MT_SMTC */
+
#undef do_IRQ
/*
@@ -49,6 +58,7 @@ asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs)
{
irq_enter();
+ __DO_IRQ_SMTC_HOOK();
__do_IRQ(irq, regs);
irq_exit();
@@ -101,6 +111,11 @@ skip:
return 0;
}
+asmlinkage void spurious_interrupt(struct pt_regs *regs)
+{
+ atomic_inc(&irq_err_count);
+}
+
#ifdef CONFIG_KGDB
extern void breakpoint(void);
extern void set_debug_traps(void);
@@ -124,6 +139,9 @@ void __init init_IRQ(void)
irq_desc[i].depth = 1;
irq_desc[i].handler = &no_irq_type;
spin_lock_init(&irq_desc[i].lock);
+#ifdef CONFIG_MIPS_MT_SMTC
+ irq_hwmask[i] = 0;
+#endif /* CONFIG_MIPS_MT_SMTC */
}
arch_init_irq();
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
new file mode 100644
index 00000000000..f06a144c788
--- /dev/null
+++ b/arch/mips/kernel/kspd.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/unistd.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
+#include <linux/workqueue.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+
+#include <asm/vpe.h>
+#include <asm/rtlx.h>
+#include <asm/kspd.h>
+
+static struct workqueue_struct *workqueue = NULL;
+static struct work_struct work;
+
+extern unsigned long cpu_khz;
+
+struct mtsp_syscall {
+ int cmd;
+ unsigned char abi;
+ unsigned char size;
+};
+
+struct mtsp_syscall_ret {
+ int retval;
+ int errno;
+};
+
+struct mtsp_syscall_generic {
+ int arg0;
+ int arg1;
+ int arg2;
+ int arg3;
+ int arg4;
+ int arg5;
+ int arg6;
+};
+
+static struct list_head kspd_notifylist;
+static int sp_stopping = 0;
+
+/* these should match with those in the SDE kit */
+#define MTSP_SYSCALL_BASE 0
+#define MTSP_SYSCALL_EXIT (MTSP_SYSCALL_BASE + 0)
+#define MTSP_SYSCALL_OPEN (MTSP_SYSCALL_BASE + 1)
+#define MTSP_SYSCALL_READ (MTSP_SYSCALL_BASE + 2)
+#define MTSP_SYSCALL_WRITE (MTSP_SYSCALL_BASE + 3)
+#define MTSP_SYSCALL_CLOSE (MTSP_SYSCALL_BASE + 4)
+#define MTSP_SYSCALL_LSEEK32 (MTSP_SYSCALL_BASE + 5)
+#define MTSP_SYSCALL_ISATTY (MTSP_SYSCALL_BASE + 6)
+#define MTSP_SYSCALL_GETTIME (MTSP_SYSCALL_BASE + 7)
+#define MTSP_SYSCALL_PIPEFREQ (MTSP_SYSCALL_BASE + 8)
+#define MTSP_SYSCALL_GETTOD (MTSP_SYSCALL_BASE + 9)
+
+#define MTSP_O_RDONLY 0x0000
+#define MTSP_O_WRONLY 0x0001
+#define MTSP_O_RDWR 0x0002
+#define MTSP_O_NONBLOCK 0x0004
+#define MTSP_O_APPEND 0x0008
+#define MTSP_O_SHLOCK 0x0010
+#define MTSP_O_EXLOCK 0x0020
+#define MTSP_O_ASYNC 0x0040
+#define MTSP_O_FSYNC O_SYNC
+#define MTSP_O_NOFOLLOW 0x0100
+#define MTSP_O_SYNC 0x0080
+#define MTSP_O_CREAT 0x0200
+#define MTSP_O_TRUNC 0x0400
+#define MTSP_O_EXCL 0x0800
+#define MTSP_O_BINARY 0x8000
+
+#define SP_VPE 1
+
+struct apsp_table {
+ int sp;
+ int ap;
+};
+
+/* we might want to do the mode flags too */
+struct apsp_table open_flags_table[] = {
+ { MTSP_O_RDWR, O_RDWR },
+ { MTSP_O_WRONLY, O_WRONLY },
+ { MTSP_O_CREAT, O_CREAT },
+ { MTSP_O_TRUNC, O_TRUNC },
+ { MTSP_O_NONBLOCK, O_NONBLOCK },
+ { MTSP_O_APPEND, O_APPEND },
+ { MTSP_O_NOFOLLOW, O_NOFOLLOW }
+};
+
+struct apsp_table syscall_command_table[] = {
+ { MTSP_SYSCALL_OPEN, __NR_open },
+ { MTSP_SYSCALL_CLOSE, __NR_close },
+ { MTSP_SYSCALL_READ, __NR_read },
+ { MTSP_SYSCALL_WRITE, __NR_write },
+ { MTSP_SYSCALL_LSEEK32, __NR_lseek }
+};
+
+static int sp_syscall(int num, int arg0, int arg1, int arg2, int arg3)
+{
+ register long int _num __asm__ ("$2") = num;
+ register long int _arg0 __asm__ ("$4") = arg0;
+ register long int _arg1 __asm__ ("$5") = arg1;
+ register long int _arg2 __asm__ ("$6") = arg2;
+ register long int _arg3 __asm__ ("$7") = arg3;
+
+ mm_segment_t old_fs;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ __asm__ __volatile__ (
+ " syscall \n"
+ : "=r" (_num), "=r" (_arg3)
+ : "r" (_num), "r" (_arg0), "r" (_arg1), "r" (_arg2), "r" (_arg3));
+
+ set_fs(old_fs);
+
+ /* $a3 is error flag */
+ if (_arg3)
+ return -_num;
+
+ return _num;
+}
+
+static int translate_syscall_command(int cmd)
+{
+ int i;
+ int ret = -1;
+
+ for (i = 0; i < ARRAY_SIZE(syscall_command_table); i++) {
+ if ((cmd == syscall_command_table[i].sp))
+ return syscall_command_table[i].ap;
+ }
+
+ return ret;
+}
+
+static unsigned int translate_open_flags(int flags)
+{
+ int i;
+ unsigned int ret = 0;
+
+ for (i = 0; i < (sizeof(open_flags_table) / sizeof(struct apsp_table));
+ i++) {
+ if( (flags & open_flags_table[i].sp) ) {
+ ret |= open_flags_table[i].ap;
+ }
+ }
+
+ return ret;
+}
+
+
+static void sp_setfsuidgid( uid_t uid, gid_t gid)
+{
+ current->fsuid = uid;
+ current->fsgid = gid;
+
+ key_fsuid_changed(current);
+ key_fsgid_changed(current);
+}
+
+/*
+ * Expects a request to be on the sysio channel. Reads it. Decides whether
+ * its a linux syscall and runs it, or whatever. Puts the return code back
+ * into the request and sends the whole thing back.
+ */
+void sp_work_handle_request(void)
+{
+ struct mtsp_syscall sc;
+ struct mtsp_syscall_generic generic;
+ struct mtsp_syscall_ret ret;
+ struct kspd_notifications *n;
+ struct timeval tv;
+ struct timezone tz;
+ int cmd;
+
+ char *vcwd;
+ mm_segment_t old_fs;
+ int size;
+
+ ret.retval = -1;
+
+ if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall), 0)) {
+ printk(KERN_ERR "Expected request but nothing to read\n");
+ return;
+ }
+
+ size = sc.size;
+
+ if (size) {
+ if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size, 0)) {
+ printk(KERN_ERR "Expected request but nothing to read\n");
+ return;
+ }
+ }
+
+ /* Run the syscall at the priviledge of the user who loaded the
+ SP program */
+
+ if (vpe_getuid(SP_VPE))
+ sp_setfsuidgid( vpe_getuid(SP_VPE), vpe_getgid(SP_VPE));
+
+ switch (sc.cmd) {
+ /* needs the flags argument translating from SDE kit to
+ linux */
+ case MTSP_SYSCALL_PIPEFREQ:
+ ret.retval = cpu_khz * 1000;
+ ret.errno = 0;
+ break;
+
+ case MTSP_SYSCALL_GETTOD:
+ memset(&tz, 0, sizeof(tz));
+ if ((ret.retval = sp_syscall(__NR_gettimeofday, (int)&tv,
+ (int)&tz, 0,0)) == 0)
+ ret.retval = tv.tv_sec;
+
+ ret.errno = errno;
+ break;
+
+ case MTSP_SYSCALL_EXIT:
+ list_for_each_entry(n, &kspd_notifylist, list)
+ n->kspd_sp_exit(SP_VPE);
+ sp_stopping = 1;
+
+ printk(KERN_DEBUG "KSPD got exit syscall from SP exitcode %d\n",
+ generic.arg0);
+ break;
+
+ case MTSP_SYSCALL_OPEN:
+ generic.arg1 = translate_open_flags(generic.arg1);
+
+ vcwd = vpe_getcwd(SP_VPE);
+
+ /* change to the cwd of the process that loaded the SP program */
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ sys_chdir(vcwd);
+ set_fs(old_fs);
+
+ sc.cmd = __NR_open;
+
+ /* fall through */
+
+ default:
+ if ((sc.cmd >= __NR_Linux) &&
+ (sc.cmd <= (__NR_Linux + __NR_Linux_syscalls)) )
+ cmd = sc.cmd;
+ else
+ cmd = translate_syscall_command(sc.cmd);
+
+ if (cmd >= 0) {
+ ret.retval = sp_syscall(cmd, generic.arg0, generic.arg1,
+ generic.arg2, generic.arg3);
+ ret.errno = errno;
+ } else
+ printk(KERN_WARNING
+ "KSPD: Unknown SP syscall number %d\n", sc.cmd);
+ break;
+ } /* switch */
+
+ if (vpe_getuid(SP_VPE))
+ sp_setfsuidgid( 0, 0);
+
+ if ((rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(struct mtsp_syscall_ret), 0))
+ < sizeof(struct mtsp_syscall_ret))
+ printk("KSPD: sp_work_handle_request failed to send to SP\n");
+}
+
+static void sp_cleanup(void)
+{
+ struct files_struct *files = current->files;
+ int i, j;
+ struct fdtable *fdt;
+
+ j = 0;
+
+ /*
+ * It is safe to dereference the fd table without RCU or
+ * ->file_lock
+ */
+ fdt = files_fdtable(files);
+ for (;;) {
+ unsigned long set;
+ i = j * __NFDBITS;
+ if (i >= fdt->max_fdset || i >= fdt->max_fds)
+ break;
+ set = fdt->open_fds->fds_bits[j++];
+ while (set) {
+ if (set & 1) {
+ struct file * file = xchg(&fdt->fd[i], NULL);
+ if (file)
+ filp_close(file, files);
+ }
+ i++;
+ set >>= 1;
+ }
+ }
+}
+
+static int channel_open = 0;
+
+/* the work handler */
+static void sp_work(void *data)
+{
+ if (!channel_open) {
+ if( rtlx_open(RTLX_CHANNEL_SYSIO, 1) != 0) {
+ printk("KSPD: unable to open sp channel\n");
+ sp_stopping = 1;
+ } else {
+ channel_open++;
+ printk(KERN_DEBUG "KSPD: SP channel opened\n");
+ }
+ } else {
+ /* wait for some data, allow it to sleep */
+ rtlx_read_poll(RTLX_CHANNEL_SYSIO, 1);
+
+ /* Check we haven't been woken because we are stopping */
+ if (!sp_stopping)
+ sp_work_handle_request();
+ }
+
+ if (!sp_stopping)
+ queue_work(workqueue, &work);
+ else
+ sp_cleanup();
+}
+
+static void startwork(int vpe)
+{
+ sp_stopping = channel_open = 0;
+
+ if (workqueue == NULL) {
+ if ((workqueue = create_singlethread_workqueue("kspd")) == NULL) {
+ printk(KERN_ERR "unable to start kspd\n");
+ return;
+ }
+
+ INIT_WORK(&work, sp_work, NULL);
+ queue_work(workqueue, &work);
+ } else
+ queue_work(workqueue, &work);
+
+}
+
+static void stopwork(int vpe)
+{
+ sp_stopping = 1;
+
+ printk(KERN_DEBUG "KSPD: SP stopping\n");
+}
+
+void kspd_notify(struct kspd_notifications *notify)
+{
+ list_add(&notify->list, &kspd_notifylist);
+}
+
+static struct vpe_notifications notify;
+static int kspd_module_init(void)
+{
+ INIT_LIST_HEAD(&kspd_notifylist);
+
+ notify.start = startwork;
+ notify.stop = stopwork;
+ vpe_notify(SP_VPE, &notify);
+
+ return 0;
+}
+
+static void kspd_module_exit(void)
+{
+
+}
+
+module_init(kspd_module_init);
+module_exit(kspd_module_exit);
+
+MODULE_DESCRIPTION("MIPS KSPD");
+MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 3f40c37a9ee..a7d2bb3cf83 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -356,73 +356,13 @@ asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
asmlinkage ssize_t sys32_pread(unsigned int fd, char __user * buf,
size_t count, u32 unused, u64 a4, u64 a5)
{
- ssize_t ret;
- struct file * file;
- ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
- loff_t pos;
-
- ret = -EBADF;
- file = fget(fd);
- if (!file)
- goto bad_file;
- if (!(file->f_mode & FMODE_READ))
- goto out;
- pos = merge_64(a4, a5);
- ret = rw_verify_area(READ, file, &pos, count);
- if (ret < 0)
- goto out;
- ret = -EINVAL;
- if (!file->f_op || !(read = file->f_op->read))
- goto out;
- if (pos < 0)
- goto out;
- ret = -ESPIPE;
- if (!(file->f_mode & FMODE_PREAD))
- goto out;
- ret = read(file, buf, count, &pos);
- if (ret > 0)
- dnotify_parent(file->f_dentry, DN_ACCESS);
-out:
- fput(file);
-bad_file:
- return ret;
+ return sys_pread64(fd, buf, count, merge_64(a4, a5));
}
asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char __user * buf,
size_t count, u32 unused, u64 a4, u64 a5)
{
- ssize_t ret;
- struct file * file;
- ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
- loff_t pos;
-
- ret = -EBADF;
- file = fget(fd);
- if (!file)
- goto bad_file;
- if (!(file->f_mode & FMODE_WRITE))
- goto out;
- pos = merge_64(a4, a5);
- ret = rw_verify_area(WRITE, file, &pos, count);
- if (ret < 0)
- goto out;
- ret = -EINVAL;
- if (!file->f_op || !(write = file->f_op->write))
- goto out;
- if (pos < 0)
- goto out;
-
- ret = -ESPIPE;
- if (!(file->f_mode & FMODE_PWRITE))
- goto out;
-
- ret = write(file, buf, count, &pos);
- if (ret > 0)
- dnotify_parent(file->f_dentry, DN_MODIFY);
-out:
- fput(file);
-bad_file:
- return ret;
+ return sys_pwrite64(fd, buf, count, merge_64(a4, a5));
}
asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
@@ -1182,6 +1122,16 @@ asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,
return sys_readahead(fd, merge_64(a2, a3), count);
}
+asmlinkage long sys32_sync_file_range(int fd, int __pad,
+ unsigned long a2, unsigned long a3,
+ unsigned long a4, unsigned long a5,
+ int flags)
+{
+ return sys_sync_file_range(fd,
+ merge_64(a2, a3), merge_64(a4, a5),
+ flags);
+}
+
/* Argument list sizes for sys_socketcall */
#define AL(x) ((x) * sizeof(unsigned int))
static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
new file mode 100644
index 00000000000..02237a685ec
--- /dev/null
+++ b/arch/mips/kernel/mips-mt.c
@@ -0,0 +1,449 @@
+/*
+ * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels
+ * Copyright (C) 2005 Mips Technologies, Inc
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/mipsmtregs.h>
+#include <asm/r4kcache.h>
+#include <asm/cacheflush.h>
+
+/*
+ * CPU mask used to set process affinity for MT VPEs/TCs with FPUs
+ */
+
+cpumask_t mt_fpu_cpumask;
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+unsigned long mt_fpemul_threshold = 0;
+
+/*
+ * Replacement functions for the sys_sched_setaffinity() and
+ * sys_sched_getaffinity() system calls, so that we can integrate
+ * FPU affinity with the user's requested processor affinity.
+ * This code is 98% identical with the sys_sched_setaffinity()
+ * and sys_sched_getaffinity() system calls, and should be
+ * updated when kernel/sched.c changes.
+ */
+
+/*
+ * find_process_by_pid - find a process with a matching PID value.
+ * used in sys_sched_set/getaffinity() in kernel/sched.c, so
+ * cloned here.
+ */
+static inline task_t *find_process_by_pid(pid_t pid)
+{
+ return pid ? find_task_by_pid(pid) : current;
+}
+
+
+/*
+ * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
+ unsigned long __user *user_mask_ptr)
+{
+ cpumask_t new_mask;
+ cpumask_t effective_mask;
+ int retval;
+ task_t *p;
+
+ if (len < sizeof(new_mask))
+ return -EINVAL;
+
+ if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
+ return -EFAULT;
+
+ lock_cpu_hotplug();
+ read_lock(&tasklist_lock);
+
+ p = find_process_by_pid(pid);
+ if (!p) {
+ read_unlock(&tasklist_lock);
+ unlock_cpu_hotplug();
+ return -ESRCH;
+ }
+
+ /*
+ * It is not safe to call set_cpus_allowed with the
+ * tasklist_lock held. We will bump the task_struct's
+ * usage count and drop tasklist_lock before invoking
+ * set_cpus_allowed.
+ */
+ get_task_struct(p);
+
+ retval = -EPERM;
+ if ((current->euid != p->euid) && (current->euid != p->uid) &&
+ !capable(CAP_SYS_NICE)) {
+ read_unlock(&tasklist_lock);
+ goto out_unlock;
+ }
+
+ /* Record new user-specified CPU set for future reference */
+ p->thread.user_cpus_allowed = new_mask;
+
+ /* Unlock the task list */
+ read_unlock(&tasklist_lock);
+
+ /* Compute new global allowed CPU set if necessary */
+ if( (p->thread.mflags & MF_FPUBOUND)
+ && cpus_intersects(new_mask, mt_fpu_cpumask)) {
+ cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
+ retval = set_cpus_allowed(p, effective_mask);
+ } else {
+ p->thread.mflags &= ~MF_FPUBOUND;
+ retval = set_cpus_allowed(p, new_mask);
+ }
+
+
+out_unlock:
+ put_task_struct(p);
+ unlock_cpu_hotplug();
+ return retval;
+}
+
+/*
+ * mipsmt_sys_sched_getaffinity - get the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
+ unsigned long __user *user_mask_ptr)
+{
+ unsigned int real_len;
+ cpumask_t mask;
+ int retval;
+ task_t *p;
+
+ real_len = sizeof(mask);
+ if (len < real_len)
+ return -EINVAL;
+
+ lock_cpu_hotplug();
+ read_lock(&tasklist_lock);
+
+ retval = -ESRCH;
+ p = find_process_by_pid(pid);
+ if (!p)
+ goto out_unlock;
+
+ retval = 0;
+
+ cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
+
+out_unlock:
+ read_unlock(&tasklist_lock);
+ unlock_cpu_hotplug();
+ if (retval)
+ return retval;
+ if (copy_to_user(user_mask_ptr, &mask, real_len))
+ return -EFAULT;
+ return real_len;
+}
+
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+/*
+ * Dump new MIPS MT state for the core. Does not leave TCs halted.
+ * Takes an argument which taken to be a pre-call MVPControl value.
+ */
+
+void mips_mt_regdump(unsigned long mvpctl)
+{
+ unsigned long flags;
+ unsigned long vpflags;
+ unsigned long mvpconf0;
+ int nvpe;
+ int ntc;
+ int i;
+ int tc;
+ unsigned long haltval;
+ unsigned long tcstatval;
+#ifdef CONFIG_MIPS_MT_SMTC
+ void smtc_soft_dump(void);
+#endif /* CONFIG_MIPT_MT_SMTC */
+
+ local_irq_save(flags);
+ vpflags = dvpe();
+ printk("=== MIPS MT State Dump ===\n");
+ printk("-- Global State --\n");
+ printk(" MVPControl Passed: %08lx\n", mvpctl);
+ printk(" MVPControl Read: %08lx\n", vpflags);
+ printk(" MVPConf0 : %08lx\n", (mvpconf0 = read_c0_mvpconf0()));
+ nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+ ntc = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+ printk("-- per-VPE State --\n");
+ for(i = 0; i < nvpe; i++) {
+ for(tc = 0; tc < ntc; tc++) {
+ settc(tc);
+ if((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
+ printk(" VPE %d\n", i);
+ printk(" VPEControl : %08lx\n", read_vpe_c0_vpecontrol());
+ printk(" VPEConf0 : %08lx\n", read_vpe_c0_vpeconf0());
+ printk(" VPE%d.Status : %08lx\n",
+ i, read_vpe_c0_status());
+ printk(" VPE%d.EPC : %08lx\n", i, read_vpe_c0_epc());
+ printk(" VPE%d.Cause : %08lx\n", i, read_vpe_c0_cause());
+ printk(" VPE%d.Config7 : %08lx\n",
+ i, read_vpe_c0_config7());
+ break; /* Next VPE */
+ }
+ }
+ }
+ printk("-- per-TC State --\n");
+ for(tc = 0; tc < ntc; tc++) {
+ settc(tc);
+ if(read_tc_c0_tcbind() == read_c0_tcbind()) {
+ /* Are we dumping ourself? */
+ haltval = 0; /* Then we're not halted, and mustn't be */
+ tcstatval = flags; /* And pre-dump TCStatus is flags */
+ printk(" TC %d (current TC with VPE EPC above)\n", tc);
+ } else {
+ haltval = read_tc_c0_tchalt();
+ write_tc_c0_tchalt(1);
+ tcstatval = read_tc_c0_tcstatus();
+ printk(" TC %d\n", tc);
+ }
+ printk(" TCStatus : %08lx\n", tcstatval);
+ printk(" TCBind : %08lx\n", read_tc_c0_tcbind());
+ printk(" TCRestart : %08lx\n", read_tc_c0_tcrestart());
+ printk(" TCHalt : %08lx\n", haltval);
+ printk(" TCContext : %08lx\n", read_tc_c0_tccontext());
+ if (!haltval)
+ write_tc_c0_tchalt(0);
+ }
+#ifdef CONFIG_MIPS_MT_SMTC
+ smtc_soft_dump();
+#endif /* CONFIG_MIPT_MT_SMTC */
+ printk("===========================\n");
+ evpe(vpflags);
+ local_irq_restore(flags);
+}
+
+static int mt_opt_norps = 0;
+static int mt_opt_rpsctl = -1;
+static int mt_opt_nblsu = -1;
+static int mt_opt_forceconfig7 = 0;
+static int mt_opt_config7 = -1;
+
+static int __init rps_disable(char *s)
+{
+ mt_opt_norps = 1;
+ return 1;
+}
+__setup("norps", rps_disable);
+
+static int __init rpsctl_set(char *str)
+{
+ get_option(&str, &mt_opt_rpsctl);
+ return 1;
+}
+__setup("rpsctl=", rpsctl_set);
+
+static int __init nblsu_set(char *str)
+{
+ get_option(&str, &mt_opt_nblsu);
+ return 1;
+}
+__setup("nblsu=", nblsu_set);
+
+static int __init config7_set(char *str)
+{
+ get_option(&str, &mt_opt_config7);
+ mt_opt_forceconfig7 = 1;
+ return 1;
+}
+__setup("config7=", config7_set);
+
+/* Experimental cache flush control parameters that should go away some day */
+int mt_protiflush = 0;
+int mt_protdflush = 0;
+int mt_n_iflushes = 1;
+int mt_n_dflushes = 1;
+
+static int __init set_protiflush(char *s)
+{
+ mt_protiflush = 1;
+ return 1;
+}
+__setup("protiflush", set_protiflush);
+
+static int __init set_protdflush(char *s)
+{
+ mt_protdflush = 1;
+ return 1;
+}
+__setup("protdflush", set_protdflush);
+
+static int __init niflush(char *s)
+{
+ get_option(&s, &mt_n_iflushes);
+ return 1;
+}
+__setup("niflush=", niflush);
+
+static int __init ndflush(char *s)
+{
+ get_option(&s, &mt_n_dflushes);
+ return 1;
+}
+__setup("ndflush=", ndflush);
+#ifdef CONFIG_MIPS_MT_FPAFF
+static int fpaff_threshold = -1;
+
+static int __init fpaff_thresh(char *str)
+{
+ get_option(&str, &fpaff_threshold);
+ return 1;
+}
+
+__setup("fpaff=", fpaff_thresh);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+static unsigned int itc_base = 0;
+
+static int __init set_itc_base(char *str)
+{
+ get_option(&str, &itc_base);
+ return 1;
+}
+
+__setup("itcbase=", set_itc_base);
+
+void mips_mt_set_cpuoptions(void)
+{
+ unsigned int oconfig7 = read_c0_config7();
+ unsigned int nconfig7 = oconfig7;
+
+ if (mt_opt_norps) {
+ printk("\"norps\" option deprectated: use \"rpsctl=\"\n");
+ }
+ if (mt_opt_rpsctl >= 0) {
+ printk("34K return prediction stack override set to %d.\n",
+ mt_opt_rpsctl);
+ if (mt_opt_rpsctl)
+ nconfig7 |= (1 << 2);
+ else
+ nconfig7 &= ~(1 << 2);
+ }
+ if (mt_opt_nblsu >= 0) {
+ printk("34K ALU/LSU sync override set to %d.\n", mt_opt_nblsu);
+ if (mt_opt_nblsu)
+ nconfig7 |= (1 << 5);
+ else
+ nconfig7 &= ~(1 << 5);
+ }
+ if (mt_opt_forceconfig7) {
+ printk("CP0.Config7 forced to 0x%08x.\n", mt_opt_config7);
+ nconfig7 = mt_opt_config7;
+ }
+ if (oconfig7 != nconfig7) {
+ __asm__ __volatile("sync");
+ write_c0_config7(nconfig7);
+ ehb ();
+ printk("Config7: 0x%08x\n", read_c0_config7());
+ }
+
+ /* Report Cache management debug options */
+ if (mt_protiflush)
+ printk("I-cache flushes single-threaded\n");
+ if (mt_protdflush)
+ printk("D-cache flushes single-threaded\n");
+ if (mt_n_iflushes != 1)
+ printk("I-Cache Flushes Repeated %d times\n", mt_n_iflushes);
+ if (mt_n_dflushes != 1)
+ printk("D-Cache Flushes Repeated %d times\n", mt_n_dflushes);
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+ /* FPU Use Factor empirically derived from experiments on 34K */
+#define FPUSEFACTOR 333
+
+ if (fpaff_threshold >= 0) {
+ mt_fpemul_threshold = fpaff_threshold;
+ } else {
+ mt_fpemul_threshold =
+ (FPUSEFACTOR * (loops_per_jiffy/(500000/HZ))) / HZ;
+ }
+ printk("FPU Affinity set after %ld emulations\n",
+ mt_fpemul_threshold);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+ if (itc_base != 0) {
+ /*
+ * Configure ITC mapping. This code is very
+ * specific to the 34K core family, which uses
+ * a special mode bit ("ITC") in the ErrCtl
+ * register to enable access to ITC control
+ * registers via cache "tag" operations.
+ */
+ unsigned long ectlval;
+ unsigned long itcblkgrn;
+
+ /* ErrCtl register is known as "ecc" to Linux */
+ ectlval = read_c0_ecc();
+ write_c0_ecc(ectlval | (0x1 << 26));
+ ehb();
+#define INDEX_0 (0x80000000)
+#define INDEX_8 (0x80000008)
+ /* Read "cache tag" for Dcache pseudo-index 8 */
+ cache_op(Index_Load_Tag_D, INDEX_8);
+ ehb();
+ itcblkgrn = read_c0_dtaglo();
+ itcblkgrn &= 0xfffe0000;
+ /* Set for 128 byte pitch of ITC cells */
+ itcblkgrn |= 0x00000c00;
+ /* Stage in Tag register */
+ write_c0_dtaglo(itcblkgrn);
+ ehb();
+ /* Write out to ITU with CACHE op */
+ cache_op(Index_Store_Tag_D, INDEX_8);
+ /* Now set base address, and turn ITC on with 0x1 bit */
+ write_c0_dtaglo((itc_base & 0xfffffc00) | 0x1 );
+ ehb();
+ /* Write out to ITU with CACHE op */
+ cache_op(Index_Store_Tag_D, INDEX_0);
+ write_c0_ecc(ectlval);
+ ehb();
+ printk("Mapped %ld ITC cells starting at 0x%08x\n",
+ ((itcblkgrn & 0x7fe00000) >> 20), itc_base);
+ }
+}
+
+/*
+ * Function to protect cache flushes from concurrent execution
+ * depends on MP software model chosen.
+ */
+
+void mt_cflush_lockdown(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ void smtc_cflush_lockdown(void);
+
+ smtc_cflush_lockdown();
+#endif /* CONFIG_MIPS_MT_SMTC */
+ /* FILL IN VSMP and AP/SP VERSIONS HERE */
+}
+
+void mt_cflush_release(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ void smtc_cflush_release(void);
+
+ smtc_cflush_release();
+#endif /* CONFIG_MIPS_MT_SMTC */
+ /* FILL IN VSMP and AP/SP VERSIONS HERE */
+}
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 86e42c633f7..0a71a4c3371 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -28,22 +28,9 @@ extern long __strnlen_user_asm(const char *s);
/*
* String functions
*/
-EXPORT_SYMBOL(memchr);
-EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strchr);
-#ifdef CONFIG_64BIT
-EXPORT_SYMBOL(strncmp);
-#endif
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(kernel_thread);
@@ -62,6 +49,3 @@ EXPORT_SYMBOL(__strnlen_user_asm);
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(invalid_pte_table);
-#ifdef CONFIG_GENERIC_IRQ_PROBE
-EXPORT_SYMBOL(probe_irq_mask);
-#endif
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index e54a7f442f8..d7bf0215bc1 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -288,6 +288,9 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
sym = (Elf_Sym *)sechdrs[symindex].sh_addr
+ ELF_MIPS_R_SYM(rel[i]);
if (!sym->st_value) {
+ /* Ignore unresolved weak symbol */
+ if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
+ continue;
printk(KERN_WARNING "%s: Unknown symbol %s\n",
me->name, strtab + sym->st_name);
return -ENOENT;
@@ -325,6 +328,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
sym = (Elf_Sym *)sechdrs[symindex].sh_addr
+ ELF_MIPS_R_SYM(rel[i]);
if (!sym->st_value) {
+ /* Ignore unresolved weak symbol */
+ if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
+ continue;
printk(KERN_WARNING "%s: Unknown symbol %s\n",
me->name, strtab + sym->st_name);
return -ENOENT;
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 84ab959f924..9def554f335 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -42,6 +42,7 @@ static const char *cpu_name[] = {
[CPU_R8000] = "R8000",
[CPU_R10000] = "R10000",
[CPU_R12000] = "R12000",
+ [CPU_R14000] = "R14000",
[CPU_R4300] = "R4300",
[CPU_R4650] = "R4650",
[CPU_R4700] = "R4700",
@@ -74,6 +75,7 @@ static const char *cpu_name[] = {
[CPU_24K] = "MIPS 24K",
[CPU_25KF] = "MIPS 25Kf",
[CPU_34K] = "MIPS 34K",
+ [CPU_74K] = "MIPS 74K",
[CPU_VR4111] = "NEC VR4111",
[CPU_VR4121] = "NEC VR4121",
[CPU_VR4122] = "NEC VR4122",
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index a8f435d8294..199a06e873c 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -41,6 +41,10 @@
#include <asm/elf.h>
#include <asm/isadep.h>
#include <asm/inst.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+extern void smtc_idle_loop_hook(void);
+#endif /* CONFIG_MIPS_MT_SMTC */
/*
* The idle thread. There's no useful work to be done, so just try to conserve
@@ -51,9 +55,13 @@ ATTRIB_NORET void cpu_idle(void)
{
/* endless idle loop with no priority at all */
while (1) {
- while (!need_resched())
+ while (!need_resched()) {
+#ifdef CONFIG_MIPS_MT_SMTC
+ smtc_idle_loop_hook();
+#endif /* CONFIG_MIPS_MT_SMTC */
if (cpu_wait)
(*cpu_wait)();
+ }
preempt_enable_no_resched();
schedule();
preempt_disable();
@@ -177,6 +185,17 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
clear_tsk_thread_flag(p, TIF_USEDFPU);
+#ifdef CONFIG_MIPS_MT_FPAFF
+ /*
+ * FPU affinity support is cleaner if we track the
+ * user-visible CPU affinity from the very beginning.
+ * The generic cpus_allowed mask will already have
+ * been copied from the parent before copy_thread
+ * is invoked.
+ */
+ p->thread.user_cpus_allowed = p->cpus_allowed;
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
if (clone_flags & CLONE_SETTLS)
ti->tp_value = regs->regs[7];
@@ -419,4 +438,3 @@ unsigned long get_wchan(struct task_struct *p)
return pc;
}
-EXPORT_SYMBOL(get_wchan);
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index f838b36cc76..9b4733c1239 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -248,10 +248,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
case FPC_EIR: { /* implementation / version register */
unsigned int flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned int irqflags;
+ unsigned int mtflags;
+#endif /* CONFIG_MIPS_MT_SMTC */
if (!cpu_has_fpu)
break;
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* Read-modify-write of Status must be atomic */
+ local_irq_save(irqflags);
+ mtflags = dmt();
+#endif /* CONFIG_MIPS_MT_SMTC */
+
preempt_disable();
if (cpu_has_mipsmt) {
unsigned int vpflags = dvpe();
@@ -266,6 +276,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
write_c0_status(flags);
}
+#ifdef CONFIG_MIPS_MT_SMTC
+ emt(mtflags);
+ local_irq_restore(irqflags);
+#endif /* CONFIG_MIPS_MT_SMTC */
preempt_enable();
break;
}
@@ -469,7 +483,7 @@ static inline int audit_arch(void)
asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
{
if (unlikely(current->audit_context) && entryexit)
- audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]),
+ audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]),
regs->regs[2]);
if (!(current->ptrace & PT_PTRACED))
@@ -493,7 +507,7 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
}
out:
if (unlikely(current->audit_context) && !entryexit)
- audit_syscall_entry(current, audit_arch(), regs->regs[2],
+ audit_syscall_entry(audit_arch(), regs->regs[2],
regs->regs[4], regs->regs[5],
regs->regs[6], regs->regs[7]);
}
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 0d5cf97af72..8704dc0496e 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -173,12 +173,22 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
break;
case FPC_EIR: { /* implementation / version register */
unsigned int flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned int irqflags;
+ unsigned int mtflags;
+#endif /* CONFIG_MIPS_MT_SMTC */
if (!cpu_has_fpu) {
tmp = 0;
break;
}
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* Read-modify-write of Status must be atomic */
+ local_irq_save(irqflags);
+ mtflags = dmt();
+#endif /* CONFIG_MIPS_MT_SMTC */
+
preempt_disable();
if (cpu_has_mipsmt) {
unsigned int vpflags = dvpe();
@@ -193,6 +203,10 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
write_c0_status(flags);
}
+#ifdef CONFIG_MIPS_MT_SMTC
+ emt(mtflags);
+ local_irq_restore(irqflags);
+#endif /* CONFIG_MIPS_MT_SMTC */
preempt_enable();
break;
}
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index d2afbd19a9c..0b1b54acee9 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -88,7 +88,18 @@
PTR_ADDIU t0, $28, _THREAD_SIZE - 32
set_saved_sp t0, t1, t2
-
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* Read-modify-writes of Status must be atomic on a VPE */
+ mfc0 t2, CP0_TCSTATUS
+ ori t1, t2, TCSTATUS_IXMT
+ mtc0 t1, CP0_TCSTATUS
+ andi t2, t2, TCSTATUS_IXMT
+ ehb
+ DMT 8 # dmt t0
+ move t1,ra
+ jal mips_ihb
+ move ra,t1
+#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t1, CP0_STATUS /* Do we really need this? */
li a3, 0xff01
and t1, a3
@@ -97,6 +108,18 @@
and a2, a3
or a2, t1
mtc0 a2, CP0_STATUS
+#ifdef CONFIG_MIPS_MT_SMTC
+ ehb
+ andi t0, t0, VPECONTROL_TE
+ beqz t0, 1f
+ emt
+1:
+ mfc0 t1, CP0_TCSTATUS
+ xori t1, t1, TCSTATUS_IXMT
+ or t1, t1, t2
+ mtc0 t1, CP0_TCSTATUS
+ ehb
+#endif /* CONFIG_MIPS_MT_SMTC */
move v0, a0
jr ra
END(resume)
@@ -131,10 +154,19 @@ LEAF(_restore_fp)
#define FPU_DEFAULT 0x00000000
LEAF(_init_fpu)
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* Rather than manipulate per-VPE Status, set per-TC bit in TCStatus */
+ mfc0 t0, CP0_TCSTATUS
+ /* Bit position is the same for Status, TCStatus */
+ li t1, ST0_CU1
+ or t0, t1
+ mtc0 t0, CP0_TCSTATUS
+#else /* Normal MIPS CU1 enable */
mfc0 t0, CP0_STATUS
li t1, ST0_CU1
or t0, t1
mtc0 t0, CP0_STATUS
+#endif /* CONFIG_MIPS_MT_SMTC */
fpu_enable_hazard
li t1, FPU_DEFAULT
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 986a9cf2306..caf777f8328 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -21,45 +21,44 @@
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/elf.h>
+#include <linux/seq_file.h>
+#include <linux/syscalls.h>
+#include <linux/moduleloader.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/wait.h>
-
#include <asm/mipsmtregs.h>
-#include <asm/bitops.h>
+#include <asm/cacheflush.h>
+#include <asm/atomic.h>
#include <asm/cpu.h>
#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/vpe.h>
#include <asm/rtlx.h>
-#include <asm/uaccess.h>
#define RTLX_TARG_VPE 1
static struct rtlx_info *rtlx;
static int major;
static char module_name[] = "rtlx";
-static struct irqaction irq;
-static int irq_num;
-
-static inline int spacefree(int read, int write, int size)
-{
- if (read == write) {
- /*
- * never fill the buffer completely, so indexes are always
- * equal if empty and only empty, or !equal if data available
- */
- return size - 1;
- }
-
- return ((read + size - write) % size) - 1;
-}
static struct chan_waitqueues {
wait_queue_head_t rt_queue;
wait_queue_head_t lx_queue;
+ int in_open;
} channel_wqs[RTLX_CHANNELS];
+static struct irqaction irq;
+static int irq_num;
+static struct vpe_notifications notify;
+static int sp_stopping = 0;
+
extern void *vpe_get_shared(int index);
static void rtlx_dispatch(struct pt_regs *regs)
@@ -67,174 +66,298 @@ static void rtlx_dispatch(struct pt_regs *regs)
do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ, regs);
}
+
+/* Interrupt handler may be called before rtlx_init has otherwise had
+ a chance to run.
+*/
static irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int i;
for (i = 0; i < RTLX_CHANNELS; i++) {
- struct rtlx_channel *chan = &rtlx->channel[i];
-
- if (chan->lx_read != chan->lx_write)
- wake_up_interruptible(&channel_wqs[i].lx_queue);
+ wake_up(&channel_wqs[i].lx_queue);
+ wake_up(&channel_wqs[i].rt_queue);
}
return IRQ_HANDLED;
}
-/* call when we have the address of the shared structure from the SP side. */
-static int rtlx_init(struct rtlx_info *rtlxi)
+static __attribute_used__ void dump_rtlx(void)
{
int i;
- if (rtlxi->id != RTLX_ID) {
- printk(KERN_WARNING "no valid RTLX id at 0x%p\n", rtlxi);
- return -ENOEXEC;
- }
+ printk("id 0x%lx state %d\n", rtlx->id, rtlx->state);
- /* initialise the wait queues */
for (i = 0; i < RTLX_CHANNELS; i++) {
- init_waitqueue_head(&channel_wqs[i].rt_queue);
- init_waitqueue_head(&channel_wqs[i].lx_queue);
- }
+ struct rtlx_channel *chan = &rtlx->channel[i];
- /* set up for interrupt handling */
- memset(&irq, 0, sizeof(struct irqaction));
+ printk(" rt_state %d lx_state %d buffer_size %d\n",
+ chan->rt_state, chan->lx_state, chan->buffer_size);
- if (cpu_has_vint)
- set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
+ printk(" rt_read %d rt_write %d\n",
+ chan->rt_read, chan->rt_write);
+
+ printk(" lx_read %d lx_write %d\n",
+ chan->lx_read, chan->lx_write);
- irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ;
- irq.handler = rtlx_interrupt;
- irq.flags = SA_INTERRUPT;
- irq.name = "RTLX";
- irq.dev_id = rtlx;
- setup_irq(irq_num, &irq);
+ printk(" rt_buffer <%s>\n", chan->rt_buffer);
+ printk(" lx_buffer <%s>\n", chan->lx_buffer);
+ }
+}
+
+/* call when we have the address of the shared structure from the SP side. */
+static int rtlx_init(struct rtlx_info *rtlxi)
+{
+ if (rtlxi->id != RTLX_ID) {
+ printk(KERN_ERR "no valid RTLX id at 0x%p 0x%x\n", rtlxi, rtlxi->id);
+ return -ENOEXEC;
+ }
rtlx = rtlxi;
return 0;
}
-/* only allow one open process at a time to open each channel */
-static int rtlx_open(struct inode *inode, struct file *filp)
+/* notifications */
+static void starting(int vpe)
+{
+ int i;
+ sp_stopping = 0;
+
+ /* force a reload of rtlx */
+ rtlx=NULL;
+
+ /* wake up any sleeping rtlx_open's */
+ for (i = 0; i < RTLX_CHANNELS; i++)
+ wake_up_interruptible(&channel_wqs[i].lx_queue);
+}
+
+static void stopping(int vpe)
{
- int minor, ret;
+ int i;
+
+ sp_stopping = 1;
+ for (i = 0; i < RTLX_CHANNELS; i++)
+ wake_up_interruptible(&channel_wqs[i].lx_queue);
+}
+
+
+int rtlx_open(int index, int can_sleep)
+{
+ int ret;
struct rtlx_channel *chan;
+ volatile struct rtlx_info **p;
- /* assume only 1 device at the mo. */
- minor = MINOR(inode->i_rdev);
+ if (index >= RTLX_CHANNELS) {
+ printk(KERN_DEBUG "rtlx_open index out of range\n");
+ return -ENOSYS;
+ }
+
+ if (channel_wqs[index].in_open) {
+ printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index);
+ return -EBUSY;
+ }
+
+ channel_wqs[index].in_open++;
if (rtlx == NULL) {
- struct rtlx_info **p;
if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
- printk(KERN_ERR "vpe_get_shared is NULL. "
- "Has an SP program been loaded?\n");
- return -EFAULT;
+ if (can_sleep) {
+ DECLARE_WAITQUEUE(wait, current);
+
+ /* go to sleep */
+ add_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ while ((p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
+ schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+ /* back running */
+ } else {
+ printk( KERN_DEBUG "No SP program loaded, and device "
+ "opened with O_NONBLOCK\n");
+ channel_wqs[index].in_open = 0;
+ return -ENOSYS;
+ }
}
if (*p == NULL) {
- printk(KERN_ERR "vpe_shared %p %p\n", p, *p);
- return -EFAULT;
+ if (can_sleep) {
+ DECLARE_WAITQUEUE(wait, current);
+
+ /* go to sleep */
+ add_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ while (*p == NULL) {
+ schedule();
+
+ /* reset task state to interruptable otherwise
+ we'll whizz round here like a very fast loopy
+ thing. schedule() appears to return with state
+ set to TASK_RUNNING.
+
+ If the loaded SP program, for whatever reason,
+ doesn't set up the shared structure *p will never
+ become true. So whoever connected to either /dev/rt?
+ or if it was kspd, will then take up rather a lot of
+ processor cycles.
+ */
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+ /* back running */
+ }
+ else {
+ printk(" *vpe_get_shared is NULL. "
+ "Has an SP program been loaded?\n");
+ channel_wqs[index].in_open = 0;
+ return -ENOSYS;
+ }
}
- if ((ret = rtlx_init(*p)) < 0)
- return ret;
+ if ((unsigned int)*p < KSEG0) {
+ printk(KERN_WARNING "vpe_get_shared returned an invalid pointer "
+ "maybe an error code %d\n", (int)*p);
+ channel_wqs[index].in_open = 0;
+ return -ENOSYS;
+ }
+
+ if ((ret = rtlx_init(*p)) < 0) {
+ channel_wqs[index].in_open = 0;
+ return ret;
+ }
}
- chan = &rtlx->channel[minor];
+ chan = &rtlx->channel[index];
- if (test_and_set_bit(RTLX_STATE_OPENED, &chan->lx_state))
- return -EBUSY;
+ if (chan->lx_state == RTLX_STATE_OPENED) {
+ channel_wqs[index].in_open = 0;
+ return -EBUSY;
+ }
+ chan->lx_state = RTLX_STATE_OPENED;
+ channel_wqs[index].in_open = 0;
return 0;
}
-static int rtlx_release(struct inode *inode, struct file *filp)
+int rtlx_release(int index)
{
- int minor = MINOR(inode->i_rdev);
-
- clear_bit(RTLX_STATE_OPENED, &rtlx->channel[minor].lx_state);
- smp_mb__after_clear_bit();
-
+ rtlx->channel[index].lx_state = RTLX_STATE_UNUSED;
return 0;
}
-static unsigned int rtlx_poll(struct file *file, poll_table * wait)
+unsigned int rtlx_read_poll(int index, int can_sleep)
{
- int minor;
- unsigned int mask = 0;
- struct rtlx_channel *chan;
+ struct rtlx_channel *chan;
- minor = MINOR(file->f_dentry->d_inode->i_rdev);
- chan = &rtlx->channel[minor];
+ if (rtlx == NULL)
+ return 0;
- poll_wait(file, &channel_wqs[minor].rt_queue, wait);
- poll_wait(file, &channel_wqs[minor].lx_queue, wait);
+ chan = &rtlx->channel[index];
/* data available to read? */
- if (chan->lx_read != chan->lx_write)
- mask |= POLLIN | POLLRDNORM;
+ if (chan->lx_read == chan->lx_write) {
+ if (can_sleep) {
+ DECLARE_WAITQUEUE(wait, current);
- /* space to write */
- if (spacefree(chan->rt_read, chan->rt_write, chan->buffer_size))
- mask |= POLLOUT | POLLWRNORM;
+ /* go to sleep */
+ add_wait_queue(&channel_wqs[index].lx_queue, &wait);
- return mask;
+ set_current_state(TASK_INTERRUPTIBLE);
+ while (chan->lx_read == chan->lx_write) {
+ schedule();
+
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (sp_stopping) {
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+ return 0;
+ }
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+ /* back running */
+ }
+ else
+ return 0;
+ }
+
+ return (chan->lx_write + chan->buffer_size - chan->lx_read)
+ % chan->buffer_size;
}
-static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count,
- loff_t * ppos)
+static inline int write_spacefree(int read, int write, int size)
{
- unsigned long failed;
- size_t fl = 0L;
- int minor;
- struct rtlx_channel *lx;
- DECLARE_WAITQUEUE(wait, current);
+ if (read == write) {
+ /*
+ * Never fill the buffer completely, so indexes are always
+ * equal if empty and only empty, or !equal if data available
+ */
+ return size - 1;
+ }
- minor = MINOR(file->f_dentry->d_inode->i_rdev);
- lx = &rtlx->channel[minor];
+ return ((read + size - write) % size) - 1;
+}
- /* data available? */
- if (lx->lx_write == lx->lx_read) {
- if (file->f_flags & O_NONBLOCK)
- return 0; /* -EAGAIN makes cat whinge */
+unsigned int rtlx_write_poll(int index)
+{
+ struct rtlx_channel *chan = &rtlx->channel[index];
+ return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size);
+}
- /* go to sleep */
- add_wait_queue(&channel_wqs[minor].lx_queue, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
+static inline void copy_to(void *dst, void *src, size_t count, int user)
+{
+ if (user)
+ copy_to_user(dst, src, count);
+ else
+ memcpy(dst, src, count);
+}
- while (lx->lx_write == lx->lx_read)
- schedule();
+static inline void copy_from(void *dst, void *src, size_t count, int user)
+{
+ if (user)
+ copy_from_user(dst, src, count);
+ else
+ memcpy(dst, src, count);
+}
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&channel_wqs[minor].lx_queue, &wait);
+ssize_t rtlx_read(int index, void *buff, size_t count, int user)
+{
+ size_t fl = 0L;
+ struct rtlx_channel *lx;
- /* back running */
- }
+ if (rtlx == NULL)
+ return -ENOSYS;
+
+ lx = &rtlx->channel[index];
/* find out how much in total */
count = min(count,
- (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size);
+ (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read)
+ % lx->buffer_size);
/* then how much from the read pointer onwards */
- fl = min(count, (size_t)lx->buffer_size - lx->lx_read);
+ fl = min( count, (size_t)lx->buffer_size - lx->lx_read);
- failed = copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl);
- if (failed) {
- count = fl - failed;
- goto out;
- }
+ copy_to(buff, &lx->lx_buffer[lx->lx_read], fl, user);
/* and if there is anything left at the beginning of the buffer */
- if (count - fl) {
- failed = copy_to_user (buffer + fl, lx->lx_buffer, count - fl);
- if (failed) {
- count -= failed;
- goto out;
- }
- }
+ if ( count - fl )
+ copy_to (buff + fl, lx->lx_buffer, count - fl, user);
-out:
/* update the index */
lx->lx_read += count;
lx->lx_read %= lx->buffer_size;
@@ -242,20 +365,100 @@ out:
return count;
}
-static ssize_t rtlx_write(struct file *file, const char __user * buffer,
+ssize_t rtlx_write(int index, void *buffer, size_t count, int user)
+{
+ struct rtlx_channel *rt;
+ size_t fl;
+
+ if (rtlx == NULL)
+ return(-ENOSYS);
+
+ rt = &rtlx->channel[index];
+
+ /* total number of bytes to copy */
+ count = min(count,
+ (size_t)write_spacefree(rt->rt_read, rt->rt_write,
+ rt->buffer_size));
+
+ /* first bit from write pointer to the end of the buffer, or count */
+ fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
+
+ copy_from (&rt->rt_buffer[rt->rt_write], buffer, fl, user);
+
+ /* if there's any left copy to the beginning of the buffer */
+ if( count - fl )
+ copy_from (rt->rt_buffer, buffer + fl, count - fl, user);
+
+ rt->rt_write += count;
+ rt->rt_write %= rt->buffer_size;
+
+ return(count);
+}
+
+
+static int file_open(struct inode *inode, struct file *filp)
+{
+ int minor = iminor(inode);
+
+ return rtlx_open(minor, (filp->f_flags & O_NONBLOCK) ? 0 : 1);
+}
+
+static int file_release(struct inode *inode, struct file *filp)
+{
+ int minor = iminor(inode);
+
+ return rtlx_release(minor);
+}
+
+static unsigned int file_poll(struct file *file, poll_table * wait)
+{
+ int minor;
+ unsigned int mask = 0;
+
+ minor = iminor(file->f_dentry->d_inode);
+
+ poll_wait(file, &channel_wqs[minor].rt_queue, wait);
+ poll_wait(file, &channel_wqs[minor].lx_queue, wait);
+
+ if (rtlx == NULL)
+ return 0;
+
+ /* data available to read? */
+ if (rtlx_read_poll(minor, 0))
+ mask |= POLLIN | POLLRDNORM;
+
+ /* space to write */
+ if (rtlx_write_poll(minor))
+ mask |= POLLOUT | POLLWRNORM;
+
+ return mask;
+}
+
+static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
+ loff_t * ppos)
+{
+ int minor = iminor(file->f_dentry->d_inode);
+
+ /* data available? */
+ if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) {
+ return 0; // -EAGAIN makes cat whinge
+ }
+
+ return rtlx_read(minor, buffer, count, 1);
+}
+
+static ssize_t file_write(struct file *file, const char __user * buffer,
size_t count, loff_t * ppos)
{
- unsigned long failed;
int minor;
struct rtlx_channel *rt;
- size_t fl;
DECLARE_WAITQUEUE(wait, current);
- minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ minor = iminor(file->f_dentry->d_inode);
rt = &rtlx->channel[minor];
/* any space left... */
- if (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size)) {
+ if (!rtlx_write_poll(minor)) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
@@ -263,61 +466,64 @@ static ssize_t rtlx_write(struct file *file, const char __user * buffer,
add_wait_queue(&channel_wqs[minor].rt_queue, &wait);
set_current_state(TASK_INTERRUPTIBLE);
- while (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size))
+ while (!rtlx_write_poll(minor))
schedule();
set_current_state(TASK_RUNNING);
remove_wait_queue(&channel_wqs[minor].rt_queue, &wait);
}
- /* total number of bytes to copy */
- count = min(count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) );
-
- /* first bit from write pointer to the end of the buffer, or count */
- fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
-
- failed = copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl);
- if (failed) {
- count = fl - failed;
- goto out;
- }
-
- /* if there's any left copy to the beginning of the buffer */
- if (count - fl) {
- failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl);
- if (failed) {
- count -= failed;
- goto out;
- }
- }
-
-out:
- rt->rt_write += count;
- rt->rt_write %= rt->buffer_size;
-
- return count;
+ return rtlx_write(minor, (void *)buffer, count, 1);
}
static struct file_operations rtlx_fops = {
- .owner = THIS_MODULE,
- .open = rtlx_open,
- .release = rtlx_release,
- .write = rtlx_write,
- .read = rtlx_read,
- .poll = rtlx_poll
+ .owner = THIS_MODULE,
+ .open = file_open,
+ .release = file_release,
+ .write = file_write,
+ .read = file_read,
+ .poll = file_poll
+};
+
+static struct irqaction rtlx_irq = {
+ .handler = rtlx_interrupt,
+ .flags = SA_INTERRUPT,
+ .name = "RTLX",
};
+static int rtlx_irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ;
+
static char register_chrdev_failed[] __initdata =
KERN_ERR "rtlx_module_init: unable to register device\n";
-static int __init rtlx_module_init(void)
+static int rtlx_module_init(void)
{
+ int i;
+
major = register_chrdev(0, module_name, &rtlx_fops);
if (major < 0) {
printk(register_chrdev_failed);
return major;
}
+ /* initialise the wait queues */
+ for (i = 0; i < RTLX_CHANNELS; i++) {
+ init_waitqueue_head(&channel_wqs[i].rt_queue);
+ init_waitqueue_head(&channel_wqs[i].lx_queue);
+ channel_wqs[i].in_open = 0;
+ }
+
+ /* set up notifiers */
+ notify.start = starting;
+ notify.stop = stopping;
+ vpe_notify(RTLX_TARG_VPE, &notify);
+
+ if (cpu_has_vint)
+ set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
+
+ rtlx_irq.dev_id = rtlx;
+ setup_irq(rtlx_irq_num, &rtlx_irq);
+
return 0;
}
@@ -330,5 +536,5 @@ module_init(rtlx_module_init);
module_exit(rtlx_module_exit);
MODULE_DESCRIPTION("MIPS RTLX");
-MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc.");
+MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 2f2dc54b2e2..a0ac0e5f61a 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -569,8 +569,19 @@ einval: li v0, -EINVAL
sys sys_tkill 2
sys sys_sendfile64 5
sys sys_futex 6
+#ifdef CONFIG_MIPS_MT_FPAFF
+ /*
+ * For FPU affinity scheduling on MIPS MT processors, we need to
+ * intercept sys_sched_xxxaffinity() calls until we get a proper hook
+ * in kernel/sched.c. Considered only temporary we only support these
+ * hooks for the 32-bit kernel - there is no MIPS64 MT processor atm.
+ */
+ sys mipsmt_sys_sched_setaffinity 3
+ sys mipsmt_sys_sched_getaffinity 3
+#else
sys sys_sched_setaffinity 3
sys sys_sched_getaffinity 3 /* 4240 */
+#endif /* CONFIG_MIPS_MT_FPAFF */
sys sys_io_setup 2
sys sys_io_destroy 1
sys sys_io_getevents 5
@@ -634,6 +645,8 @@ einval: li v0, -EINVAL
sys sys_pselect6 6
sys sys_ppoll 5
sys sys_unshare 1
+ sys sys_splice 4
+ sys sys_sync_file_range 7 /* 4305 */
.endm
/* We pre-compute the number of _instruction_ bytes needed to
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 98bf25df56f..9ba75088737 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -460,3 +460,5 @@ sys_call_table:
PTR sys_pselect6 /* 5260 */
PTR sys_ppoll
PTR sys_unshare
+ PTR sys_splice
+ PTR sys_sync_file_range
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 05a2c0567da..942aca26f9c 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -386,3 +386,5 @@ EXPORT(sysn32_call_table)
PTR sys_pselect6
PTR sys_ppoll /* 6265 */
PTR sys_unshare
+ PTR sys_splice
+ PTR sys_sync_file_range
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 19c4ca481b0..8efb23a8413 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -209,7 +209,7 @@ sys_call_table:
PTR sys_fork
PTR sys_read
PTR sys_write
- PTR sys_open /* 4005 */
+ PTR compat_sys_open /* 4005 */
PTR sys_close
PTR sys_waitpid
PTR sys_creat
@@ -508,4 +508,6 @@ sys_call_table:
PTR sys_pselect6
PTR sys_ppoll
PTR sys_unshare
+ PTR sys_splice
+ PTR sys32_sync_file_range /* 4305 */
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 0cb3b6097e0..397a70e651b 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -34,6 +34,7 @@
#include <linux/highmem.h>
#include <linux/console.h>
#include <linux/mmzone.h>
+#include <linux/pfn.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
@@ -245,7 +246,7 @@ static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_en
#ifdef CONFIG_64BIT
/* HACK: Guess if the sign extension was forgotten */
if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
- start |= 0xffffffff00000000;
+ start |= 0xffffffff00000000UL;
#endif
end = start + size;
@@ -257,10 +258,6 @@ static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_en
return 0;
}
-#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
-
#define MAXMEM HIGHMEM_START
#define MAXMEM_PFN PFN_DOWN(MAXMEM)
@@ -358,8 +355,6 @@ static inline void bootmem_init(void)
}
#endif
- memory_present(0, first_usable_pfn, max_low_pfn);
-
/* Initialize the boot-time allocator with low memory only. */
bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn);
@@ -413,6 +408,7 @@ static inline void bootmem_init(void)
/* Register lowmem ranges */
free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+ memory_present(0, curr_pfn, curr_pfn + size - 1);
}
/* Reserve the bootmap memory. */
@@ -422,17 +418,20 @@ static inline void bootmem_init(void)
#ifdef CONFIG_BLK_DEV_INITRD
initrd_below_start_ok = 1;
if (initrd_start) {
- unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start);
+ unsigned long initrd_size = ((unsigned char *)initrd_end) -
+ ((unsigned char *)initrd_start);
+ const int width = sizeof(long) * 2;
+
printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
(void *)initrd_start, initrd_size);
if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
printk("initrd extends beyond end of memory "
"(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n",
- sizeof(long) * 2,
- (unsigned long long)CPHYSADDR(initrd_end),
- sizeof(long) * 2,
- (unsigned long long)PFN_PHYS(max_low_pfn));
+ width,
+ (unsigned long long) CPHYSADDR(initrd_end),
+ width,
+ (unsigned long long) PFN_PHYS(max_low_pfn));
initrd_start = initrd_end = 0;
initrd_reserve_bootmem = 0;
}
@@ -493,10 +492,6 @@ static inline void resource_init(void)
}
}
-#undef PFN_UP
-#undef PFN_DOWN
-#undef PFN_PHYS
-
#undef MAXMEM
#undef MAXMEM_PFN
@@ -536,7 +531,10 @@ void __init setup_arch(char **cmdline_p)
int __init fpu_disable(char *s)
{
- cpu_data[0].options &= ~MIPS_CPU_FPU;
+ int i;
+
+ for (i = 0; i < NR_CPUS; i++)
+ cpu_data[i].options &= ~MIPS_CPU_FPU;
return 1;
}
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h
index 3ca786215d4..ce6cb915c0a 100644
--- a/arch/mips/kernel/signal-common.h
+++ b/arch/mips/kernel/signal-common.h
@@ -31,7 +31,6 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
save_gp_reg(31);
#undef save_gp_reg
-#ifdef CONFIG_32BIT
err |= __put_user(regs->hi, &sc->sc_mdhi);
err |= __put_user(regs->lo, &sc->sc_mdlo);
if (cpu_has_dsp) {
@@ -43,20 +42,6 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
err |= __put_user(mflo3(), &sc->sc_lo3);
err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
}
-#endif
-#ifdef CONFIG_64BIT
- err |= __put_user(regs->hi, &sc->sc_hi[0]);
- err |= __put_user(regs->lo, &sc->sc_lo[0]);
- if (cpu_has_dsp) {
- err |= __put_user(mfhi1(), &sc->sc_hi[1]);
- err |= __put_user(mflo1(), &sc->sc_lo[1]);
- err |= __put_user(mfhi2(), &sc->sc_hi[2]);
- err |= __put_user(mflo2(), &sc->sc_lo[2]);
- err |= __put_user(mfhi3(), &sc->sc_hi[3]);
- err |= __put_user(mflo3(), &sc->sc_lo[3]);
- err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
- }
-#endif
err |= __put_user(!!used_math(), &sc->sc_used_math);
@@ -92,7 +77,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
current_thread_info()->restart_block.fn = do_no_restart_syscall;
err |= __get_user(regs->cp0_epc, &sc->sc_pc);
-#ifdef CONFIG_32BIT
err |= __get_user(regs->hi, &sc->sc_mdhi);
err |= __get_user(regs->lo, &sc->sc_mdlo);
if (cpu_has_dsp) {
@@ -104,20 +88,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
}
-#endif
-#ifdef CONFIG_64BIT
- err |= __get_user(regs->hi, &sc->sc_hi[0]);
- err |= __get_user(regs->lo, &sc->sc_lo[0]);
- if (cpu_has_dsp) {
- err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
- err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
- err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
- err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
- err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
- err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
- err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
- }
-#endif
#define restore_gp_reg(i) do { \
err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
diff --git a/arch/mips/kernel/smp_mt.c b/arch/mips/kernel/smp-mt.c
index 993b8bf56aa..57770902b9a 100644
--- a/arch/mips/kernel/smp_mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -1,8 +1,4 @@
/*
- * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved.
- *
- * Elizabeth Clarke (beth@mips.com)
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -16,6 +12,10 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
+ * Copyright (C) 2004, 05, 06 MIPS Technologies, Inc.
+ * Elizabeth Clarke (beth@mips.com)
+ * Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
*/
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -24,6 +24,7 @@
#include <linux/compiler.h>
#include <asm/atomic.h>
+#include <asm/cacheflush.h>
#include <asm/cpu.h>
#include <asm/processor.h>
#include <asm/system.h>
@@ -33,8 +34,8 @@
#include <asm/time.h>
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
-#include <asm/cacheflush.h>
-#include <asm/mips-boards/maltaint.h>
+#include <asm/mips_mt.h>
+#include <asm/mips-boards/maltaint.h> /* This is f*cking wrong */
#define MIPS_CPU_IPI_RESCHED_IRQ 0
#define MIPS_CPU_IPI_CALL_IRQ 1
@@ -66,6 +67,7 @@ void __init sanitize_tlb_entries(void)
if (!cpu_has_mipsmt)
return;
+ /* Enable VPC */
set_c0_mvpcontrol(MVPCONTROL_VPC);
back_to_back_c0_hazard();
@@ -106,12 +108,12 @@ void __init sanitize_tlb_entries(void)
static void ipi_resched_dispatch (struct pt_regs *regs)
{
- do_IRQ(MIPS_CPU_IPI_RESCHED_IRQ, regs);
+ do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ, regs);
}
static void ipi_call_dispatch (struct pt_regs *regs)
{
- do_IRQ(MIPS_CPU_IPI_CALL_IRQ, regs);
+ do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ, regs);
}
irqreturn_t ipi_resched_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -148,6 +150,11 @@ void plat_smp_setup(void)
unsigned long val;
int i, num;
+#ifdef CONFIG_MIPS_MT_FPAFF
+ /* If we have an FPU, enroll ourselves in the FPU-full mask */
+ if (cpu_has_fpu)
+ cpu_set(0, mt_fpu_cpumask);
+#endif /* CONFIG_MIPS_MT_FPAFF */
if (!cpu_has_mipsmt)
return;
@@ -155,6 +162,8 @@ void plat_smp_setup(void)
dvpe();
dmt();
+ mips_mt_set_cpuoptions();
+
/* Put MVPE's into 'configuration state' */
set_c0_mvpcontrol(MVPCONTROL_VPC);
@@ -189,11 +198,13 @@ void plat_smp_setup(void)
if (i != 0) {
write_vpe_c0_status((read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0);
- write_vpe_c0_cause(read_vpe_c0_cause() & ~CAUSEF_IP);
/* set config to be the same as vpe0, particularly kseg0 coherency alg */
write_vpe_c0_config( read_c0_config());
+ /* make sure there are no software interrupts pending */
+ write_vpe_c0_cause(read_vpe_c0_cause() & ~(C_SW1|C_SW0));
+
/* Propagate Config7 */
write_vpe_c0_config7(read_c0_config7());
}
@@ -233,16 +244,16 @@ void plat_smp_setup(void)
/* We'll wait until starting the secondaries before starting MVPE */
printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num);
+}
+void __init plat_prepare_cpus(unsigned int max_cpus)
+{
/* set up ipi interrupts */
if (cpu_has_vint) {
set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
}
-}
-void __init plat_prepare_cpus(unsigned int max_cpus)
-{
cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ;
@@ -287,7 +298,8 @@ void prom_boot_secondary(int cpu, struct task_struct *idle)
/* global pointer */
write_tc_gpr_gp((unsigned long)gp);
- flush_icache_range((unsigned long)gp, (unsigned long)(gp + 1));
+ flush_icache_range((unsigned long)gp,
+ (unsigned long)(gp + sizeof(struct thread_info)));
/* finally out of configuration and into chaos */
clear_c0_mvpcontrol(MVPCONTROL_VPC);
@@ -305,6 +317,12 @@ void prom_smp_finish(void)
{
write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ));
+#ifdef CONFIG_MIPS_MT_FPAFF
+ /* If we have an FPU, enroll ourselves in the FPU-full mask */
+ if (cpu_has_fpu)
+ cpu_set(smp_processor_id(), mt_fpu_cpumask);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
local_irq_enable();
}
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 78d171bfa33..298f82fe844 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -38,6 +38,10 @@
#include <asm/mmu_context.h>
#include <asm/smp.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
cpumask_t phys_cpu_present_map; /* Bitmask of available CPUs */
volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */
cpumask_t cpu_online_map; /* Bitmask of currently online CPUs */
@@ -85,6 +89,10 @@ asmlinkage void start_secondary(void)
{
unsigned int cpu;
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* Only do cpu_probe for first TC of CPU */
+ if ((read_c0_tcbind() & TCBIND_CURTC) == 0)
+#endif /* CONFIG_MIPS_MT_SMTC */
cpu_probe();
cpu_report();
per_cpu_trap_init();
@@ -179,11 +187,13 @@ int smp_call_function (void (*func) (void *info), void *info, int retry,
if (wait)
while (atomic_read(&data.finished) != cpus)
barrier();
+ call_data = NULL;
spin_unlock(&smp_call_lock);
return 0;
}
+
void smp_call_function_interrupt(void)
{
void (*func) (void *info) = call_data->func;
@@ -237,6 +247,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
current_thread_info()->cpu = 0;
smp_tune_scheduling();
plat_prepare_cpus(max_cpus);
+#ifndef CONFIG_HOTPLUG_CPU
+ cpu_present_map = cpu_possible_map;
+#endif
}
/* preload SMP state for boot cpu */
@@ -432,7 +445,7 @@ static int __init topology_init(void)
int cpu;
int ret;
- for_each_cpu(cpu) {
+ for_each_present_cpu(cpu) {
ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL);
if (ret)
printk(KERN_WARNING "topology_init: register_cpu %d "
@@ -446,5 +459,3 @@ subsys_initcall(topology_init);
EXPORT_SYMBOL(flush_tlb_page);
EXPORT_SYMBOL(flush_tlb_one);
-EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(synchronize_irq);
diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S
new file mode 100644
index 00000000000..c9d65196d91
--- /dev/null
+++ b/arch/mips/kernel/smtc-asm.S
@@ -0,0 +1,130 @@
+/*
+ * Assembly Language Functions for MIPS MT SMTC support
+ */
+
+/*
+ * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. */
+
+#include <asm/regdef.h>
+#include <asm/asmmacro.h>
+#include <asm/stackframe.h>
+#include <asm/stackframe.h>
+
+/*
+ * "Software Interrupt" linkage.
+ *
+ * This is invoked when an "Interrupt" is sent from one TC to another,
+ * where the TC to be interrupted is halted, has it's Restart address
+ * and Status values saved by the "remote control" thread, then modified
+ * to cause execution to begin here, in kenel mode. This code then
+ * disguises the TC state as that of an exception and transfers
+ * control to the general exception or vectored interrupt handler.
+ */
+ .set noreorder
+
+/*
+The __smtc_ipi_vector would use k0 and k1 as temporaries and
+1) Set EXL (this is per-VPE, so this can't be done by proxy!)
+2) Restore the K/CU and IXMT bits to the pre "exception" state
+ (EXL means no interrupts and access to the kernel map).
+3) Set EPC to be the saved value of TCRestart.
+4) Jump to the exception handler entry point passed by the sender.
+
+CAN WE PROVE THAT WE WON'T DO THIS IF INTS DISABLED??
+*/
+
+/*
+ * Reviled and slandered vision: Set EXL and restore K/CU/IXMT
+ * state of pre-halt thread, then save everything and call
+ * thought some function pointer to imaginary_exception, which
+ * will parse a register value or memory message queue to
+ * deliver things like interprocessor interrupts. On return
+ * from that function, jump to the global ret_from_irq code
+ * to invoke the scheduler and return as appropriate.
+ */
+
+#define PT_PADSLOT4 (PT_R0-8)
+#define PT_PADSLOT5 (PT_R0-4)
+
+ .text
+ .align 5
+FEXPORT(__smtc_ipi_vector)
+ .set noat
+ /* Disable thread scheduling to make Status update atomic */
+ DMT 27 # dmt k1
+ ehb
+ /* Set EXL */
+ mfc0 k0,CP0_STATUS
+ ori k0,k0,ST0_EXL
+ mtc0 k0,CP0_STATUS
+ ehb
+ /* Thread scheduling now inhibited by EXL. Restore TE state. */
+ andi k1,k1,VPECONTROL_TE
+ beqz k1,1f
+ emt
+1:
+ /*
+ * The IPI sender has put some information on the anticipated
+ * kernel stack frame. If we were in user mode, this will be
+ * built above the saved kernel SP. If we were already in the
+ * kernel, it will be built above the current CPU SP.
+ *
+ * Were we in kernel mode, as indicated by CU0?
+ */
+ sll k1,k0,3
+ .set noreorder
+ bltz k1,2f
+ move k1,sp
+ .set reorder
+ /*
+ * If previously in user mode, set CU0 and use kernel stack.
+ */
+ li k1,ST0_CU0
+ or k1,k1,k0
+ mtc0 k1,CP0_STATUS
+ ehb
+ get_saved_sp
+ /* Interrupting TC will have pre-set values in slots in the new frame */
+2: subu k1,k1,PT_SIZE
+ /* Load TCStatus Value */
+ lw k0,PT_TCSTATUS(k1)
+ /* Write it to TCStatus to restore CU/KSU/IXMT state */
+ mtc0 k0,$2,1
+ ehb
+ lw k0,PT_EPC(k1)
+ mtc0 k0,CP0_EPC
+ /* Save all will redundantly recompute the SP, but use it for now */
+ SAVE_ALL
+ CLI
+ move a0,sp
+ /* Function to be invoked passed stack pad slot 5 */
+ lw t0,PT_PADSLOT5(sp)
+ /* Argument from sender passed in stack pad slot 4 */
+ lw a1,PT_PADSLOT4(sp)
+ jalr t0
+ nop
+ j ret_from_irq
+ nop
+
+/*
+ * Called from idle loop to provoke processing of queued IPIs
+ * First IPI message in queue passed as argument.
+ */
+
+LEAF(self_ipi)
+ /* Before anything else, block interrupts */
+ mfc0 t0,CP0_TCSTATUS
+ ori t1,t0,TCSTATUS_IXMT
+ mtc0 t1,CP0_TCSTATUS
+ ehb
+ /* We know we're in kernel mode, so prepare stack frame */
+ subu t1,sp,PT_SIZE
+ sw ra,PT_EPC(t1)
+ sw a0,PT_PADSLOT4(t1)
+ la t2,ipi_decode
+ sw t2,PT_PADSLOT5(t1)
+ /* Save pre-disable value of TCStatus */
+ sw t0,PT_TCSTATUS(t1)
+ j __smtc_ipi_vector
+ nop
+END(self_ipi)
diff --git a/arch/mips/kernel/smtc-proc.c b/arch/mips/kernel/smtc-proc.c
new file mode 100644
index 00000000000..6f370999617
--- /dev/null
+++ b/arch/mips/kernel/smtc-proc.c
@@ -0,0 +1,93 @@
+/*
+ * /proc hooks for SMTC kernel
+ * Copyright (C) 2005 Mips Technologies, Inc
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/mipsregs.h>
+#include <asm/cacheflush.h>
+#include <linux/proc_fs.h>
+
+#include <asm/smtc_proc.h>
+
+/*
+ * /proc diagnostic and statistics hooks
+ */
+
+/*
+ * Statistics gathered
+ */
+unsigned long selfipis[NR_CPUS];
+
+struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS];
+
+static struct proc_dir_entry *smtc_stats;
+
+atomic_t smtc_fpu_recoveries;
+
+static int proc_read_smtc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int totalen = 0;
+ int len;
+ int i;
+ extern unsigned long ebase;
+
+ len = sprintf(page, "SMTC Status Word: 0x%08x\n", smtc_status);
+ totalen += len;
+ page += len;
+ len = sprintf(page, "Config7: 0x%08x\n", read_c0_config7());
+ totalen += len;
+ page += len;
+ len = sprintf(page, "EBASE: 0x%08lx\n", ebase);
+ totalen += len;
+ page += len;
+ len = sprintf(page, "Counter Interrupts taken per CPU (TC)\n");
+ totalen += len;
+ page += len;
+ for (i=0; i < NR_CPUS; i++) {
+ len = sprintf(page, "%d: %ld\n", i, smtc_cpu_stats[i].timerints);
+ totalen += len;
+ page += len;
+ }
+ len = sprintf(page, "Self-IPIs by CPU:\n");
+ totalen += len;
+ page += len;
+ for(i = 0; i < NR_CPUS; i++) {
+ len = sprintf(page, "%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
+ totalen += len;
+ page += len;
+ }
+ len = sprintf(page, "%d Recoveries of \"stolen\" FPU\n",
+ atomic_read(&smtc_fpu_recoveries));
+ totalen += len;
+ page += len;
+
+ return totalen;
+}
+
+void init_smtc_stats(void)
+{
+ int i;
+
+ for (i=0; i<NR_CPUS; i++) {
+ smtc_cpu_stats[i].timerints = 0;
+ smtc_cpu_stats[i].selfipis = 0;
+ }
+
+ atomic_set(&smtc_fpu_recoveries, 0);
+
+ smtc_stats = create_proc_read_entry("smtc", 0444, NULL,
+ proc_read_smtc, NULL);
+}
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
new file mode 100644
index 00000000000..2e8e52c135e
--- /dev/null
+++ b/arch/mips/kernel/smtc.c
@@ -0,0 +1,1322 @@
+/* Copyright (C) 2004 Mips Technologies, Inc */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/hazards.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/mipsregs.h>
+#include <asm/cacheflush.h>
+#include <asm/time.h>
+#include <asm/addrspace.h>
+#include <asm/smtc.h>
+#include <asm/smtc_ipi.h>
+#include <asm/smtc_proc.h>
+
+/*
+ * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set.
+ */
+
+/*
+ * MIPSCPU_INT_BASE is identically defined in both
+ * asm-mips/mips-boards/maltaint.h and asm-mips/mips-boards/simint.h,
+ * but as yet there's no properly organized include structure that
+ * will ensure that the right *int.h file will be included for a
+ * given platform build.
+ */
+
+#define MIPSCPU_INT_BASE 16
+
+#define MIPS_CPU_IPI_IRQ 1
+
+#define LOCK_MT_PRA() \
+ local_irq_save(flags); \
+ mtflags = dmt()
+
+#define UNLOCK_MT_PRA() \
+ emt(mtflags); \
+ local_irq_restore(flags)
+
+#define LOCK_CORE_PRA() \
+ local_irq_save(flags); \
+ mtflags = dvpe()
+
+#define UNLOCK_CORE_PRA() \
+ evpe(mtflags); \
+ local_irq_restore(flags)
+
+/*
+ * Data structures purely associated with SMTC parallelism
+ */
+
+
+/*
+ * Table for tracking ASIDs whose lifetime is prolonged.
+ */
+
+asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
+
+/*
+ * Clock interrupt "latch" buffers, per "CPU"
+ */
+
+unsigned int ipi_timer_latch[NR_CPUS];
+
+/*
+ * Number of InterProcessor Interupt (IPI) message buffers to allocate
+ */
+
+#define IPIBUF_PER_CPU 4
+
+struct smtc_ipi_q IPIQ[NR_CPUS];
+struct smtc_ipi_q freeIPIq;
+
+
+/* Forward declarations */
+
+void ipi_decode(struct pt_regs *, struct smtc_ipi *);
+void post_direct_ipi(int cpu, struct smtc_ipi *pipi);
+void setup_cross_vpe_interrupts(void);
+void init_smtc_stats(void);
+
+/* Global SMTC Status */
+
+unsigned int smtc_status = 0;
+
+/* Boot command line configuration overrides */
+
+static int vpelimit = 0;
+static int tclimit = 0;
+static int ipibuffers = 0;
+static int nostlb = 0;
+static int asidmask = 0;
+unsigned long smtc_asid_mask = 0xff;
+
+static int __init maxvpes(char *str)
+{
+ get_option(&str, &vpelimit);
+ return 1;
+}
+
+static int __init maxtcs(char *str)
+{
+ get_option(&str, &tclimit);
+ return 1;
+}
+
+static int __init ipibufs(char *str)
+{
+ get_option(&str, &ipibuffers);
+ return 1;
+}
+
+static int __init stlb_disable(char *s)
+{
+ nostlb = 1;
+ return 1;
+}
+
+static int __init asidmask_set(char *str)
+{
+ get_option(&str, &asidmask);
+ switch(asidmask) {
+ case 0x1:
+ case 0x3:
+ case 0x7:
+ case 0xf:
+ case 0x1f:
+ case 0x3f:
+ case 0x7f:
+ case 0xff:
+ smtc_asid_mask = (unsigned long)asidmask;
+ break;
+ default:
+ printk("ILLEGAL ASID mask 0x%x from command line\n", asidmask);
+ }
+ return 1;
+}
+
+__setup("maxvpes=", maxvpes);
+__setup("maxtcs=", maxtcs);
+__setup("ipibufs=", ipibufs);
+__setup("nostlb", stlb_disable);
+__setup("asidmask=", asidmask_set);
+
+/* Enable additional debug checks before going into CPU idle loop */
+#define SMTC_IDLE_HOOK_DEBUG
+
+#ifdef SMTC_IDLE_HOOK_DEBUG
+
+static int hang_trig = 0;
+
+static int __init hangtrig_enable(char *s)
+{
+ hang_trig = 1;
+ return 1;
+}
+
+
+__setup("hangtrig", hangtrig_enable);
+
+#define DEFAULT_BLOCKED_IPI_LIMIT 32
+
+static int timerq_limit = DEFAULT_BLOCKED_IPI_LIMIT;
+
+static int __init tintq(char *str)
+{
+ get_option(&str, &timerq_limit);
+ return 1;
+}
+
+__setup("tintq=", tintq);
+
+int imstuckcount[2][8];
+/* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */
+int vpemask[2][8] = {{0,1,1,0,0,0,0,1},{0,1,0,0,0,0,0,1}};
+int tcnoprog[NR_CPUS];
+static atomic_t idle_hook_initialized = {0};
+static int clock_hang_reported[NR_CPUS];
+
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+
+/* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */
+
+void __init sanitize_tlb_entries(void)
+{
+ printk("Deprecated sanitize_tlb_entries() invoked\n");
+}
+
+
+/*
+ * Configure shared TLB - VPC configuration bit must be set by caller
+ */
+
+void smtc_configure_tlb(void)
+{
+ int i,tlbsiz,vpes;
+ unsigned long mvpconf0;
+ unsigned long config1val;
+
+ /* Set up ASID preservation table */
+ for (vpes=0; vpes<MAX_SMTC_TLBS; vpes++) {
+ for(i = 0; i < MAX_SMTC_ASIDS; i++) {
+ smtc_live_asid[vpes][i] = 0;
+ }
+ }
+ mvpconf0 = read_c0_mvpconf0();
+
+ if ((vpes = ((mvpconf0 & MVPCONF0_PVPE)
+ >> MVPCONF0_PVPE_SHIFT) + 1) > 1) {
+ /* If we have multiple VPEs, try to share the TLB */
+ if ((mvpconf0 & MVPCONF0_TLBS) && !nostlb) {
+ /*
+ * If TLB sizing is programmable, shared TLB
+ * size is the total available complement.
+ * Otherwise, we have to take the sum of all
+ * static VPE TLB entries.
+ */
+ if ((tlbsiz = ((mvpconf0 & MVPCONF0_PTLBE)
+ >> MVPCONF0_PTLBE_SHIFT)) == 0) {
+ /*
+ * If there's more than one VPE, there had better
+ * be more than one TC, because we need one to bind
+ * to each VPE in turn to be able to read
+ * its configuration state!
+ */
+ settc(1);
+ /* Stop the TC from doing anything foolish */
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+ /* No need to un-Halt - that happens later anyway */
+ for (i=0; i < vpes; i++) {
+ write_tc_c0_tcbind(i);
+ /*
+ * To be 100% sure we're really getting the right
+ * information, we exit the configuration state
+ * and do an IHB after each rebinding.
+ */
+ write_c0_mvpcontrol(
+ read_c0_mvpcontrol() & ~ MVPCONTROL_VPC );
+ mips_ihb();
+ /*
+ * Only count if the MMU Type indicated is TLB
+ */
+ if(((read_vpe_c0_config() & MIPS_CONF_MT) >> 7) == 1) {
+ config1val = read_vpe_c0_config1();
+ tlbsiz += ((config1val >> 25) & 0x3f) + 1;
+ }
+
+ /* Put core back in configuration state */
+ write_c0_mvpcontrol(
+ read_c0_mvpcontrol() | MVPCONTROL_VPC );
+ mips_ihb();
+ }
+ }
+ write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB);
+
+ /*
+ * Setup kernel data structures to use software total,
+ * rather than read the per-VPE Config1 value. The values
+ * for "CPU 0" gets copied to all the other CPUs as part
+ * of their initialization in smtc_cpu_setup().
+ */
+
+ tlbsiz = tlbsiz & 0x3f; /* MIPS32 limits TLB indices to 64 */
+ cpu_data[0].tlbsize = tlbsiz;
+ smtc_status |= SMTC_TLB_SHARED;
+
+ printk("TLB of %d entry pairs shared by %d VPEs\n",
+ tlbsiz, vpes);
+ } else {
+ printk("WARNING: TLB Not Sharable on SMTC Boot!\n");
+ }
+ }
+}
+
+
+/*
+ * Incrementally build the CPU map out of constituent MIPS MT cores,
+ * using the specified available VPEs and TCs. Plaform code needs
+ * to ensure that each MIPS MT core invokes this routine on reset,
+ * one at a time(!).
+ *
+ * This version of the build_cpu_map and prepare_cpus routines assumes
+ * that *all* TCs of a MIPS MT core will be used for Linux, and that
+ * they will be spread across *all* available VPEs (to minimise the
+ * loss of efficiency due to exception service serialization).
+ * An improved version would pick up configuration information and
+ * possibly leave some TCs/VPEs as "slave" processors.
+ *
+ * Use c0_MVPConf0 to find out how many TCs are available, setting up
+ * phys_cpu_present_map and the logical/physical mappings.
+ */
+
+int __init mipsmt_build_cpu_map(int start_cpu_slot)
+{
+ int i, ntcs;
+
+ /*
+ * The CPU map isn't actually used for anything at this point,
+ * so it's not clear what else we should do apart from set
+ * everything up so that "logical" = "physical".
+ */
+ ntcs = ((read_c0_mvpconf0() & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+ for (i=start_cpu_slot; i<NR_CPUS && i<ntcs; i++) {
+ cpu_set(i, phys_cpu_present_map);
+ __cpu_number_map[i] = i;
+ __cpu_logical_map[i] = i;
+ }
+ /* Initialize map of CPUs with FPUs */
+ cpus_clear(mt_fpu_cpumask);
+
+ /* One of those TC's is the one booting, and not a secondary... */
+ printk("%i available secondary CPU TC(s)\n", i - 1);
+
+ return i;
+}
+
+/*
+ * Common setup before any secondaries are started
+ * Make sure all CPU's are in a sensible state before we boot any of the
+ * secondaries.
+ *
+ * For MIPS MT "SMTC" operation, we set up all TCs, spread as evenly
+ * as possible across the available VPEs.
+ */
+
+static void smtc_tc_setup(int vpe, int tc, int cpu)
+{
+ settc(tc);
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+ write_tc_c0_tcstatus((read_tc_c0_tcstatus()
+ & ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT))
+ | TCSTATUS_A);
+ write_tc_c0_tccontext(0);
+ /* Bind tc to vpe */
+ write_tc_c0_tcbind(vpe);
+ /* In general, all TCs should have the same cpu_data indications */
+ memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));
+ /* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */
+ if (cpu_data[0].cputype == CPU_34K)
+ cpu_data[cpu].options &= ~MIPS_CPU_FPU;
+ cpu_data[cpu].vpe_id = vpe;
+ cpu_data[cpu].tc_id = tc;
+}
+
+
+void mipsmt_prepare_cpus(void)
+{
+ int i, vpe, tc, ntc, nvpe, tcpervpe, slop, cpu;
+ unsigned long flags;
+ unsigned long val;
+ int nipi;
+ struct smtc_ipi *pipi;
+
+ /* disable interrupts so we can disable MT */
+ local_irq_save(flags);
+ /* disable MT so we can configure */
+ dvpe();
+ dmt();
+
+ freeIPIq.lock = SPIN_LOCK_UNLOCKED;
+
+ /*
+ * We probably don't have as many VPEs as we do SMP "CPUs",
+ * but it's possible - and in any case we'll never use more!
+ */
+ for (i=0; i<NR_CPUS; i++) {
+ IPIQ[i].head = IPIQ[i].tail = NULL;
+ IPIQ[i].lock = SPIN_LOCK_UNLOCKED;
+ IPIQ[i].depth = 0;
+ ipi_timer_latch[i] = 0;
+ }
+
+ /* cpu_data index starts at zero */
+ cpu = 0;
+ cpu_data[cpu].vpe_id = 0;
+ cpu_data[cpu].tc_id = 0;
+ cpu++;
+
+ /* Report on boot-time options */
+ mips_mt_set_cpuoptions ();
+ if (vpelimit > 0)
+ printk("Limit of %d VPEs set\n", vpelimit);
+ if (tclimit > 0)
+ printk("Limit of %d TCs set\n", tclimit);
+ if (nostlb) {
+ printk("Shared TLB Use Inhibited - UNSAFE for Multi-VPE Operation\n");
+ }
+ if (asidmask)
+ printk("ASID mask value override to 0x%x\n", asidmask);
+
+ /* Temporary */
+#ifdef SMTC_IDLE_HOOK_DEBUG
+ if (hang_trig)
+ printk("Logic Analyser Trigger on suspected TC hang\n");
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+
+ /* Put MVPE's into 'configuration state' */
+ write_c0_mvpcontrol( read_c0_mvpcontrol() | MVPCONTROL_VPC );
+
+ val = read_c0_mvpconf0();
+ nvpe = ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+ if (vpelimit > 0 && nvpe > vpelimit)
+ nvpe = vpelimit;
+ ntc = ((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+ if (ntc > NR_CPUS)
+ ntc = NR_CPUS;
+ if (tclimit > 0 && ntc > tclimit)
+ ntc = tclimit;
+ tcpervpe = ntc / nvpe;
+ slop = ntc % nvpe; /* Residual TCs, < NVPE */
+
+ /* Set up shared TLB */
+ smtc_configure_tlb();
+
+ for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) {
+ /*
+ * Set the MVP bits.
+ */
+ settc(tc);
+ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_MVP);
+ if (vpe != 0)
+ printk(", ");
+ printk("VPE %d: TC", vpe);
+ for (i = 0; i < tcpervpe; i++) {
+ /*
+ * TC 0 is bound to VPE 0 at reset,
+ * and is presumably executing this
+ * code. Leave it alone!
+ */
+ if (tc != 0) {
+ smtc_tc_setup(vpe,tc, cpu);
+ cpu++;
+ }
+ printk(" %d", tc);
+ tc++;
+ }
+ if (slop) {
+ if (tc != 0) {
+ smtc_tc_setup(vpe,tc, cpu);
+ cpu++;
+ }
+ printk(" %d", tc);
+ tc++;
+ slop--;
+ }
+ if (vpe != 0) {
+ /*
+ * Clear any stale software interrupts from VPE's Cause
+ */
+ write_vpe_c0_cause(0);
+
+ /*
+ * Clear ERL/EXL of VPEs other than 0
+ * and set restricted interrupt enable/mask.
+ */
+ write_vpe_c0_status((read_vpe_c0_status()
+ & ~(ST0_BEV | ST0_ERL | ST0_EXL | ST0_IM))
+ | (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP7
+ | ST0_IE));
+ /*
+ * set config to be the same as vpe0,
+ * particularly kseg0 coherency alg
+ */
+ write_vpe_c0_config(read_c0_config());
+ /* Clear any pending timer interrupt */
+ write_vpe_c0_compare(0);
+ /* Propagate Config7 */
+ write_vpe_c0_config7(read_c0_config7());
+ }
+ /* enable multi-threading within VPE */
+ write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE);
+ /* enable the VPE */
+ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
+ }
+
+ /*
+ * Pull any physically present but unused TCs out of circulation.
+ */
+ while (tc < (((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1)) {
+ cpu_clear(tc, phys_cpu_present_map);
+ cpu_clear(tc, cpu_present_map);
+ tc++;
+ }
+
+ /* release config state */
+ write_c0_mvpcontrol( read_c0_mvpcontrol() & ~ MVPCONTROL_VPC );
+
+ printk("\n");
+
+ /* Set up coprocessor affinity CPU mask(s) */
+
+ for (tc = 0; tc < ntc; tc++) {
+ if(cpu_data[tc].options & MIPS_CPU_FPU)
+ cpu_set(tc, mt_fpu_cpumask);
+ }
+
+ /* set up ipi interrupts... */
+
+ /* If we have multiple VPEs running, set up the cross-VPE interrupt */
+
+ if (nvpe > 1)
+ setup_cross_vpe_interrupts();
+
+ /* Set up queue of free IPI "messages". */
+ nipi = NR_CPUS * IPIBUF_PER_CPU;
+ if (ipibuffers > 0)
+ nipi = ipibuffers;
+
+ pipi = kmalloc(nipi *sizeof(struct smtc_ipi), GFP_KERNEL);
+ if (pipi == NULL)
+ panic("kmalloc of IPI message buffers failed\n");
+ else
+ printk("IPI buffer pool of %d buffers\n", nipi);
+ for (i = 0; i < nipi; i++) {
+ smtc_ipi_nq(&freeIPIq, pipi);
+ pipi++;
+ }
+
+ /* Arm multithreading and enable other VPEs - but all TCs are Halted */
+ emt(EMT_ENABLE);
+ evpe(EVPE_ENABLE);
+ local_irq_restore(flags);
+ /* Initialize SMTC /proc statistics/diagnostics */
+ init_smtc_stats();
+}
+
+
+/*
+ * Setup the PC, SP, and GP of a secondary processor and start it
+ * running!
+ * smp_bootstrap is the place to resume from
+ * __KSTK_TOS(idle) is apparently the stack pointer
+ * (unsigned long)idle->thread_info the gp
+ *
+ */
+void smtc_boot_secondary(int cpu, struct task_struct *idle)
+{
+ extern u32 kernelsp[NR_CPUS];
+ long flags;
+ int mtflags;
+
+ LOCK_MT_PRA();
+ if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+ dvpe();
+ }
+ settc(cpu_data[cpu].tc_id);
+
+ /* pc */
+ write_tc_c0_tcrestart((unsigned long)&smp_bootstrap);
+
+ /* stack pointer */
+ kernelsp[cpu] = __KSTK_TOS(idle);
+ write_tc_gpr_sp(__KSTK_TOS(idle));
+
+ /* global pointer */
+ write_tc_gpr_gp((unsigned long)idle->thread_info);
+
+ smtc_status |= SMTC_MTC_ACTIVE;
+ write_tc_c0_tchalt(0);
+ if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+ evpe(EVPE_ENABLE);
+ }
+ UNLOCK_MT_PRA();
+}
+
+void smtc_init_secondary(void)
+{
+ /*
+ * Start timer on secondary VPEs if necessary.
+ * mips_timer_setup should already have been invoked by init/main
+ * on "boot" TC. Like per_cpu_trap_init() hack, this assumes that
+ * SMTC init code assigns TCs consdecutively and in ascending order
+ * to across available VPEs.
+ */
+ if(((read_c0_tcbind() & TCBIND_CURTC) != 0)
+ && ((read_c0_tcbind() & TCBIND_CURVPE)
+ != cpu_data[smp_processor_id() - 1].vpe_id)){
+ write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
+ }
+
+ local_irq_enable();
+}
+
+void smtc_smp_finish(void)
+{
+ printk("TC %d going on-line as CPU %d\n",
+ cpu_data[smp_processor_id()].tc_id, smp_processor_id());
+}
+
+void smtc_cpus_done(void)
+{
+}
+
+/*
+ * Support for SMTC-optimized driver IRQ registration
+ */
+
+/*
+ * SMTC Kernel needs to manipulate low-level CPU interrupt mask
+ * in do_IRQ. These are passed in setup_irq_smtc() and stored
+ * in this table.
+ */
+
+int setup_irq_smtc(unsigned int irq, struct irqaction * new,
+ unsigned long hwmask)
+{
+ irq_hwmask[irq] = hwmask;
+
+ return setup_irq(irq, new);
+}
+
+/*
+ * IPI model for SMTC is tricky, because interrupts aren't TC-specific.
+ * Within a VPE one TC can interrupt another by different approaches.
+ * The easiest to get right would probably be to make all TCs except
+ * the target IXMT and set a software interrupt, but an IXMT-based
+ * scheme requires that a handler must run before a new IPI could
+ * be sent, which would break the "broadcast" loops in MIPS MT.
+ * A more gonzo approach within a VPE is to halt the TC, extract
+ * its Restart, Status, and a couple of GPRs, and program the Restart
+ * address to emulate an interrupt.
+ *
+ * Within a VPE, one can be confident that the target TC isn't in
+ * a critical EXL state when halted, since the write to the Halt
+ * register could not have issued on the writing thread if the
+ * halting thread had EXL set. So k0 and k1 of the target TC
+ * can be used by the injection code. Across VPEs, one can't
+ * be certain that the target TC isn't in a critical exception
+ * state. So we try a two-step process of sending a software
+ * interrupt to the target VPE, which either handles the event
+ * itself (if it was the target) or injects the event within
+ * the VPE.
+ */
+
+void smtc_ipi_qdump(void)
+{
+ int i;
+
+ for (i = 0; i < NR_CPUS ;i++) {
+ printk("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n",
+ i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail,
+ IPIQ[i].depth);
+ }
+}
+
+/*
+ * The standard atomic.h primitives don't quite do what we want
+ * here: We need an atomic add-and-return-previous-value (which
+ * could be done with atomic_add_return and a decrement) and an
+ * atomic set/zero-and-return-previous-value (which can't really
+ * be done with the atomic.h primitives). And since this is
+ * MIPS MT, we can assume that we have LL/SC.
+ */
+static __inline__ int atomic_postincrement(unsigned int *pv)
+{
+ unsigned long result;
+
+ unsigned long temp;
+
+ __asm__ __volatile__(
+ "1: ll %0, %2 \n"
+ " addu %1, %0, 1 \n"
+ " sc %1, %2 \n"
+ " beqz %1, 1b \n"
+ " sync \n"
+ : "=&r" (result), "=&r" (temp), "=m" (*pv)
+ : "m" (*pv)
+ : "memory");
+
+ return result;
+}
+
+/* No longer used in IPI dispatch, but retained for future recycling */
+
+static __inline__ int atomic_postclear(unsigned int *pv)
+{
+ unsigned long result;
+
+ unsigned long temp;
+
+ __asm__ __volatile__(
+ "1: ll %0, %2 \n"
+ " or %1, $0, $0 \n"
+ " sc %1, %2 \n"
+ " beqz %1, 1b \n"
+ " sync \n"
+ : "=&r" (result), "=&r" (temp), "=m" (*pv)
+ : "m" (*pv)
+ : "memory");
+
+ return result;
+}
+
+
+void smtc_send_ipi(int cpu, int type, unsigned int action)
+{
+ int tcstatus;
+ struct smtc_ipi *pipi;
+ long flags;
+ int mtflags;
+
+ if (cpu == smp_processor_id()) {
+ printk("Cannot Send IPI to self!\n");
+ return;
+ }
+ /* Set up a descriptor, to be delivered either promptly or queued */
+ pipi = smtc_ipi_dq(&freeIPIq);
+ if (pipi == NULL) {
+ bust_spinlocks(1);
+ mips_mt_regdump(dvpe());
+ panic("IPI Msg. Buffers Depleted\n");
+ }
+ pipi->type = type;
+ pipi->arg = (void *)action;
+ pipi->dest = cpu;
+ if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+ /* If not on same VPE, enqueue and send cross-VPE interupt */
+ smtc_ipi_nq(&IPIQ[cpu], pipi);
+ LOCK_CORE_PRA();
+ settc(cpu_data[cpu].tc_id);
+ write_vpe_c0_cause(read_vpe_c0_cause() | C_SW1);
+ UNLOCK_CORE_PRA();
+ } else {
+ /*
+ * Not sufficient to do a LOCK_MT_PRA (dmt) here,
+ * since ASID shootdown on the other VPE may
+ * collide with this operation.
+ */
+ LOCK_CORE_PRA();
+ settc(cpu_data[cpu].tc_id);
+ /* Halt the targeted TC */
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+
+ /*
+ * Inspect TCStatus - if IXMT is set, we have to queue
+ * a message. Otherwise, we set up the "interrupt"
+ * of the other TC
+ */
+ tcstatus = read_tc_c0_tcstatus();
+
+ if ((tcstatus & TCSTATUS_IXMT) != 0) {
+ /*
+ * Spin-waiting here can deadlock,
+ * so we queue the message for the target TC.
+ */
+ write_tc_c0_tchalt(0);
+ UNLOCK_CORE_PRA();
+ /* Try to reduce redundant timer interrupt messages */
+ if(type == SMTC_CLOCK_TICK) {
+ if(atomic_postincrement(&ipi_timer_latch[cpu])!=0) {
+ smtc_ipi_nq(&freeIPIq, pipi);
+ return;
+ }
+ }
+ smtc_ipi_nq(&IPIQ[cpu], pipi);
+ } else {
+ post_direct_ipi(cpu, pipi);
+ write_tc_c0_tchalt(0);
+ UNLOCK_CORE_PRA();
+ }
+ }
+}
+
+/*
+ * Send IPI message to Halted TC, TargTC/TargVPE already having been set
+ */
+void post_direct_ipi(int cpu, struct smtc_ipi *pipi)
+{
+ struct pt_regs *kstack;
+ unsigned long tcstatus;
+ unsigned long tcrestart;
+ extern u32 kernelsp[NR_CPUS];
+ extern void __smtc_ipi_vector(void);
+
+ /* Extract Status, EPC from halted TC */
+ tcstatus = read_tc_c0_tcstatus();
+ tcrestart = read_tc_c0_tcrestart();
+ /* If TCRestart indicates a WAIT instruction, advance the PC */
+ if ((tcrestart & 0x80000000)
+ && ((*(unsigned int *)tcrestart & 0xfe00003f) == 0x42000020)) {
+ tcrestart += 4;
+ }
+ /*
+ * Save on TC's future kernel stack
+ *
+ * CU bit of Status is indicator that TC was
+ * already running on a kernel stack...
+ */
+ if(tcstatus & ST0_CU0) {
+ /* Note that this "- 1" is pointer arithmetic */
+ kstack = ((struct pt_regs *)read_tc_gpr_sp()) - 1;
+ } else {
+ kstack = ((struct pt_regs *)kernelsp[cpu]) - 1;
+ }
+
+ kstack->cp0_epc = (long)tcrestart;
+ /* Save TCStatus */
+ kstack->cp0_tcstatus = tcstatus;
+ /* Pass token of operation to be performed kernel stack pad area */
+ kstack->pad0[4] = (unsigned long)pipi;
+ /* Pass address of function to be called likewise */
+ kstack->pad0[5] = (unsigned long)&ipi_decode;
+ /* Set interrupt exempt and kernel mode */
+ tcstatus |= TCSTATUS_IXMT;
+ tcstatus &= ~TCSTATUS_TKSU;
+ write_tc_c0_tcstatus(tcstatus);
+ ehb();
+ /* Set TC Restart address to be SMTC IPI vector */
+ write_tc_c0_tcrestart(__smtc_ipi_vector);
+}
+
+void ipi_resched_interrupt(struct pt_regs *regs)
+{
+ /* Return from interrupt should be enough to cause scheduler check */
+}
+
+
+void ipi_call_interrupt(struct pt_regs *regs)
+{
+ /* Invoke generic function invocation code in smp.c */
+ smp_call_function_interrupt();
+}
+
+void ipi_decode(struct pt_regs *regs, struct smtc_ipi *pipi)
+{
+ void *arg_copy = pipi->arg;
+ int type_copy = pipi->type;
+ int dest_copy = pipi->dest;
+
+ smtc_ipi_nq(&freeIPIq, pipi);
+ switch (type_copy) {
+ case SMTC_CLOCK_TICK:
+ /* Invoke Clock "Interrupt" */
+ ipi_timer_latch[dest_copy] = 0;
+#ifdef SMTC_IDLE_HOOK_DEBUG
+ clock_hang_reported[dest_copy] = 0;
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+ local_timer_interrupt(0, NULL, regs);
+ break;
+ case LINUX_SMP_IPI:
+ switch ((int)arg_copy) {
+ case SMP_RESCHEDULE_YOURSELF:
+ ipi_resched_interrupt(regs);
+ break;
+ case SMP_CALL_FUNCTION:
+ ipi_call_interrupt(regs);
+ break;
+ default:
+ printk("Impossible SMTC IPI Argument 0x%x\n",
+ (int)arg_copy);
+ break;
+ }
+ break;
+ default:
+ printk("Impossible SMTC IPI Type 0x%x\n", type_copy);
+ break;
+ }
+}
+
+void deferred_smtc_ipi(struct pt_regs *regs)
+{
+ struct smtc_ipi *pipi;
+ unsigned long flags;
+/* DEBUG */
+ int q = smp_processor_id();
+
+ /*
+ * Test is not atomic, but much faster than a dequeue,
+ * and the vast majority of invocations will have a null queue.
+ */
+ if(IPIQ[q].head != NULL) {
+ while((pipi = smtc_ipi_dq(&IPIQ[q])) != NULL) {
+ /* ipi_decode() should be called with interrupts off */
+ local_irq_save(flags);
+ ipi_decode(regs, pipi);
+ local_irq_restore(flags);
+ }
+ }
+}
+
+/*
+ * Send clock tick to all TCs except the one executing the funtion
+ */
+
+void smtc_timer_broadcast(int vpe)
+{
+ int cpu;
+ int myTC = cpu_data[smp_processor_id()].tc_id;
+ int myVPE = cpu_data[smp_processor_id()].vpe_id;
+
+ smtc_cpu_stats[smp_processor_id()].timerints++;
+
+ for_each_online_cpu(cpu) {
+ if (cpu_data[cpu].vpe_id == myVPE &&
+ cpu_data[cpu].tc_id != myTC)
+ smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
+ }
+}
+
+/*
+ * Cross-VPE interrupts in the SMTC prototype use "software interrupts"
+ * set via cross-VPE MTTR manipulation of the Cause register. It would be
+ * in some regards preferable to have external logic for "doorbell" hardware
+ * interrupts.
+ */
+
+static int cpu_ipi_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_IRQ;
+
+static irqreturn_t ipi_interrupt(int irq, void *dev_idm, struct pt_regs *regs)
+{
+ int my_vpe = cpu_data[smp_processor_id()].vpe_id;
+ int my_tc = cpu_data[smp_processor_id()].tc_id;
+ int cpu;
+ struct smtc_ipi *pipi;
+ unsigned long tcstatus;
+ int sent;
+ long flags;
+ unsigned int mtflags;
+ unsigned int vpflags;
+
+ /*
+ * So long as cross-VPE interrupts are done via
+ * MFTR/MTTR read-modify-writes of Cause, we need
+ * to stop other VPEs whenever the local VPE does
+ * anything similar.
+ */
+ local_irq_save(flags);
+ vpflags = dvpe();
+ clear_c0_cause(0x100 << MIPS_CPU_IPI_IRQ);
+ set_c0_status(0x100 << MIPS_CPU_IPI_IRQ);
+ irq_enable_hazard();
+ evpe(vpflags);
+ local_irq_restore(flags);
+
+ /*
+ * Cross-VPE Interrupt handler: Try to directly deliver IPIs
+ * queued for TCs on this VPE other than the current one.
+ * Return-from-interrupt should cause us to drain the queue
+ * for the current TC, so we ought not to have to do it explicitly here.
+ */
+
+ for_each_online_cpu(cpu) {
+ if (cpu_data[cpu].vpe_id != my_vpe)
+ continue;
+
+ pipi = smtc_ipi_dq(&IPIQ[cpu]);
+ if (pipi != NULL) {
+ if (cpu_data[cpu].tc_id != my_tc) {
+ sent = 0;
+ LOCK_MT_PRA();
+ settc(cpu_data[cpu].tc_id);
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+ tcstatus = read_tc_c0_tcstatus();
+ if ((tcstatus & TCSTATUS_IXMT) == 0) {
+ post_direct_ipi(cpu, pipi);
+ sent = 1;
+ }
+ write_tc_c0_tchalt(0);
+ UNLOCK_MT_PRA();
+ if (!sent) {
+ smtc_ipi_req(&IPIQ[cpu], pipi);
+ }
+ } else {
+ /*
+ * ipi_decode() should be called
+ * with interrupts off
+ */
+ local_irq_save(flags);
+ ipi_decode(regs, pipi);
+ local_irq_restore(flags);
+ }
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void ipi_irq_dispatch(struct pt_regs *regs)
+{
+ do_IRQ(cpu_ipi_irq, regs);
+}
+
+static struct irqaction irq_ipi;
+
+void setup_cross_vpe_interrupts(void)
+{
+ if (!cpu_has_vint)
+ panic("SMTC Kernel requires Vectored Interupt support");
+
+ set_vi_handler(MIPS_CPU_IPI_IRQ, ipi_irq_dispatch);
+
+ irq_ipi.handler = ipi_interrupt;
+ irq_ipi.flags = SA_INTERRUPT;
+ irq_ipi.name = "SMTC_IPI";
+
+ setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ));
+
+ irq_desc[cpu_ipi_irq].status |= IRQ_PER_CPU;
+}
+
+/*
+ * SMTC-specific hacks invoked from elsewhere in the kernel.
+ */
+
+void smtc_idle_loop_hook(void)
+{
+#ifdef SMTC_IDLE_HOOK_DEBUG
+ int im;
+ int flags;
+ int mtflags;
+ int bit;
+ int vpe;
+ int tc;
+ int hook_ntcs;
+ /*
+ * printk within DMT-protected regions can deadlock,
+ * so buffer diagnostic messages for later output.
+ */
+ char *pdb_msg;
+ char id_ho_db_msg[768]; /* worst-case use should be less than 700 */
+
+ if (atomic_read(&idle_hook_initialized) == 0) { /* fast test */
+ if (atomic_add_return(1, &idle_hook_initialized) == 1) {
+ int mvpconf0;
+ /* Tedious stuff to just do once */
+ mvpconf0 = read_c0_mvpconf0();
+ hook_ntcs = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+ if (hook_ntcs > NR_CPUS)
+ hook_ntcs = NR_CPUS;
+ for (tc = 0; tc < hook_ntcs; tc++) {
+ tcnoprog[tc] = 0;
+ clock_hang_reported[tc] = 0;
+ }
+ for (vpe = 0; vpe < 2; vpe++)
+ for (im = 0; im < 8; im++)
+ imstuckcount[vpe][im] = 0;
+ printk("Idle loop test hook initialized for %d TCs\n", hook_ntcs);
+ atomic_set(&idle_hook_initialized, 1000);
+ } else {
+ /* Someone else is initializing in parallel - let 'em finish */
+ while (atomic_read(&idle_hook_initialized) < 1000)
+ ;
+ }
+ }
+
+ /* Have we stupidly left IXMT set somewhere? */
+ if (read_c0_tcstatus() & 0x400) {
+ write_c0_tcstatus(read_c0_tcstatus() & ~0x400);
+ ehb();
+ printk("Dangling IXMT in cpu_idle()\n");
+ }
+
+ /* Have we stupidly left an IM bit turned off? */
+#define IM_LIMIT 2000
+ local_irq_save(flags);
+ mtflags = dmt();
+ pdb_msg = &id_ho_db_msg[0];
+ im = read_c0_status();
+ vpe = cpu_data[smp_processor_id()].vpe_id;
+ for (bit = 0; bit < 8; bit++) {
+ /*
+ * In current prototype, I/O interrupts
+ * are masked for VPE > 0
+ */
+ if (vpemask[vpe][bit]) {
+ if (!(im & (0x100 << bit)))
+ imstuckcount[vpe][bit]++;
+ else
+ imstuckcount[vpe][bit] = 0;
+ if (imstuckcount[vpe][bit] > IM_LIMIT) {
+ set_c0_status(0x100 << bit);
+ ehb();
+ imstuckcount[vpe][bit] = 0;
+ pdb_msg += sprintf(pdb_msg,
+ "Dangling IM %d fixed for VPE %d\n", bit,
+ vpe);
+ }
+ }
+ }
+
+ /*
+ * Now that we limit outstanding timer IPIs, check for hung TC
+ */
+ for (tc = 0; tc < NR_CPUS; tc++) {
+ /* Don't check ourself - we'll dequeue IPIs just below */
+ if ((tc != smp_processor_id()) &&
+ ipi_timer_latch[tc] > timerq_limit) {
+ if (clock_hang_reported[tc] == 0) {
+ pdb_msg += sprintf(pdb_msg,
+ "TC %d looks hung with timer latch at %d\n",
+ tc, ipi_timer_latch[tc]);
+ clock_hang_reported[tc]++;
+ }
+ }
+ }
+ emt(mtflags);
+ local_irq_restore(flags);
+ if (pdb_msg != &id_ho_db_msg[0])
+ printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+ /*
+ * To the extent that we've ever turned interrupts off,
+ * we may have accumulated deferred IPIs. This is subtle.
+ * If we use the smtc_ipi_qdepth() macro, we'll get an
+ * exact number - but we'll also disable interrupts
+ * and create a window of failure where a new IPI gets
+ * queued after we test the depth but before we re-enable
+ * interrupts. So long as IXMT never gets set, however,
+ * we should be OK: If we pick up something and dispatch
+ * it here, that's great. If we see nothing, but concurrent
+ * with this operation, another TC sends us an IPI, IXMT
+ * is clear, and we'll handle it as a real pseudo-interrupt
+ * and not a pseudo-pseudo interrupt.
+ */
+ if (IPIQ[smp_processor_id()].depth > 0) {
+ struct smtc_ipi *pipi;
+ extern void self_ipi(struct smtc_ipi *);
+
+ if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) {
+ self_ipi(pipi);
+ smtc_cpu_stats[smp_processor_id()].selfipis++;
+ }
+ }
+}
+
+void smtc_soft_dump(void)
+{
+ int i;
+
+ printk("Counter Interrupts taken per CPU (TC)\n");
+ for (i=0; i < NR_CPUS; i++) {
+ printk("%d: %ld\n", i, smtc_cpu_stats[i].timerints);
+ }
+ printk("Self-IPI invocations:\n");
+ for (i=0; i < NR_CPUS; i++) {
+ printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
+ }
+ smtc_ipi_qdump();
+ printk("Timer IPI Backlogs:\n");
+ for (i=0; i < NR_CPUS; i++) {
+ printk("%d: %d\n", i, ipi_timer_latch[i]);
+ }
+ printk("%d Recoveries of \"stolen\" FPU\n",
+ atomic_read(&smtc_fpu_recoveries));
+}
+
+
+/*
+ * TLB management routines special to SMTC
+ */
+
+void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
+{
+ unsigned long flags, mtflags, tcstat, prevhalt, asid;
+ int tlb, i;
+
+ /*
+ * It would be nice to be able to use a spinlock here,
+ * but this is invoked from within TLB flush routines
+ * that protect themselves with DVPE, so if a lock is
+ * held by another TC, it'll never be freed.
+ *
+ * DVPE/DMT must not be done with interrupts enabled,
+ * so even so most callers will already have disabled
+ * them, let's be really careful...
+ */
+
+ local_irq_save(flags);
+ if (smtc_status & SMTC_TLB_SHARED) {
+ mtflags = dvpe();
+ tlb = 0;
+ } else {
+ mtflags = dmt();
+ tlb = cpu_data[cpu].vpe_id;
+ }
+ asid = asid_cache(cpu);
+
+ do {
+ if (!((asid += ASID_INC) & ASID_MASK) ) {
+ if (cpu_has_vtag_icache)
+ flush_icache_all();
+ /* Traverse all online CPUs (hack requires contigous range) */
+ for (i = 0; i < num_online_cpus(); i++) {
+ /*
+ * We don't need to worry about our own CPU, nor those of
+ * CPUs who don't share our TLB.
+ */
+ if ((i != smp_processor_id()) &&
+ ((smtc_status & SMTC_TLB_SHARED) ||
+ (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))) {
+ settc(cpu_data[i].tc_id);
+ prevhalt = read_tc_c0_tchalt() & TCHALT_H;
+ if (!prevhalt) {
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+ }
+ tcstat = read_tc_c0_tcstatus();
+ smtc_live_asid[tlb][(tcstat & ASID_MASK)] |= (asiduse)(0x1 << i);
+ if (!prevhalt)
+ write_tc_c0_tchalt(0);
+ }
+ }
+ if (!asid) /* fix version if needed */
+ asid = ASID_FIRST_VERSION;
+ local_flush_tlb_all(); /* start new asid cycle */
+ }
+ } while (smtc_live_asid[tlb][(asid & ASID_MASK)]);
+
+ /*
+ * SMTC shares the TLB within VPEs and possibly across all VPEs.
+ */
+ for (i = 0; i < num_online_cpus(); i++) {
+ if ((smtc_status & SMTC_TLB_SHARED) ||
+ (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
+ cpu_context(i, mm) = asid_cache(i) = asid;
+ }
+
+ if (smtc_status & SMTC_TLB_SHARED)
+ evpe(mtflags);
+ else
+ emt(mtflags);
+ local_irq_restore(flags);
+}
+
+/*
+ * Invoked from macros defined in mmu_context.h
+ * which must already have disabled interrupts
+ * and done a DVPE or DMT as appropriate.
+ */
+
+void smtc_flush_tlb_asid(unsigned long asid)
+{
+ int entry;
+ unsigned long ehi;
+
+ entry = read_c0_wired();
+
+ /* Traverse all non-wired entries */
+ while (entry < current_cpu_data.tlbsize) {
+ write_c0_index(entry);
+ ehb();
+ tlb_read();
+ ehb();
+ ehi = read_c0_entryhi();
+ if((ehi & ASID_MASK) == asid) {
+ /*
+ * Invalidate only entries with specified ASID,
+ * makiing sure all entries differ.
+ */
+ write_c0_entryhi(CKSEG0 + (entry << (PAGE_SHIFT + 1)));
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+ }
+ entry++;
+ }
+ write_c0_index(PARKED_INDEX);
+ tlbw_use_hazard();
+}
+
+/*
+ * Support for single-threading cache flush operations.
+ */
+
+int halt_state_save[NR_CPUS];
+
+/*
+ * To really, really be sure that nothing is being done
+ * by other TCs, halt them all. This code assumes that
+ * a DVPE has already been done, so while their Halted
+ * state is theoretically architecturally unstable, in
+ * practice, it's not going to change while we're looking
+ * at it.
+ */
+
+void smtc_cflush_lockdown(void)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ if (cpu != smp_processor_id()) {
+ settc(cpu_data[cpu].tc_id);
+ halt_state_save[cpu] = read_tc_c0_tchalt();
+ write_tc_c0_tchalt(TCHALT_H);
+ }
+ }
+ mips_ihb();
+}
+
+/* It would be cheating to change the cpu_online states during a flush! */
+
+void smtc_cflush_release(void)
+{
+ int cpu;
+
+ /*
+ * Start with a hazard barrier to ensure
+ * that all CACHE ops have played through.
+ */
+ mips_ihb();
+
+ for_each_online_cpu(cpu) {
+ if (cpu != smp_processor_id()) {
+ settc(cpu_data[cpu].tc_id);
+ write_tc_c0_tchalt(halt_state_save[cpu]);
+ }
+ }
+ mips_ihb();
+}
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 2aeaa2fd4b3..5e8a18a8e2b 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -276,31 +276,9 @@ void sys_set_thread_area(unsigned long addr)
asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
{
- int tmp, len;
- char __user *name;
+ int tmp;
switch(cmd) {
- case SETNAME: {
- char nodename[__NEW_UTS_LEN + 1];
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- name = (char __user *) arg1;
-
- len = strncpy_from_user(nodename, name, __NEW_UTS_LEN);
- if (len < 0)
- return -EFAULT;
-
- down_write(&uts_sem);
- strncpy(system_utsname.nodename, nodename, len);
- nodename[__NEW_UTS_LEN] = '\0';
- strlcpy(system_utsname.nodename, nodename,
- sizeof(system_utsname.nodename));
- up_write(&uts_sem);
- return 0;
- }
-
case MIPS_ATOMIC_SET:
printk(KERN_CRIT "How did I get here?\n");
return -EINVAL;
@@ -313,9 +291,6 @@ asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
case FLUSH_CACHE:
__flush_cache_all();
return 0;
-
- case MIPS_RDNVRAM:
- return -EIO;
}
return -EINVAL;
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 51273b7297a..13ff4da598c 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -65,9 +65,9 @@ static int null_rtc_set_time(unsigned long sec)
return 0;
}
-unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
-int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
-int (*rtc_set_mmss)(unsigned long);
+unsigned long (*rtc_mips_get_time)(void) = null_rtc_get_time;
+int (*rtc_mips_set_time)(unsigned long) = null_rtc_set_time;
+int (*rtc_mips_set_mmss)(unsigned long);
/* usecs per counter cycle, shifted to left by 32 bits */
@@ -116,8 +116,7 @@ static void c0_timer_ack(void)
write_c0_compare(expirelo);
/* Check to see if we have missed any timer interrupts. */
- count = read_c0_count();
- if ((count - expirelo) < 0x7fffffff) {
+ while (((count = read_c0_count()) - expirelo) < 0x7fffffff) {
/* missed_timer_count++; */
expirelo = count + cycles_per_jiffy;
write_c0_compare(expirelo);
@@ -440,14 +439,14 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
* If we have an externally synchronized Linux clock, then update
- * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be
+ * CMOS clock accordingly every ~11 minutes. rtc_mips_set_time() has to be
* called as close as possible to 500 ms before the new second starts.
*/
if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
- if (rtc_set_mmss(xtime.tv_sec) == 0) {
+ if (rtc_mips_set_mmss(xtime.tv_sec) == 0) {
last_rtc_update = xtime.tv_sec;
} else {
/* do it again in 60 s */
@@ -565,7 +564,7 @@ asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs)
* b) (optional) calibrate and set the mips_hpt_frequency
* (only needed if you intended to use fixed_rate_gettimeoffset
* or use cpu counter as timer interrupt source)
- * 2) setup xtime based on rtc_get_time().
+ * 2) setup xtime based on rtc_mips_get_time().
* 3) choose a appropriate gettimeoffset routine.
* 4) calculate a couple of cached variables for later usage
* 5) board_timer_setup() -
@@ -633,10 +632,10 @@ void __init time_init(void)
if (board_time_init)
board_time_init();
- if (!rtc_set_mmss)
- rtc_set_mmss = rtc_set_time;
+ if (!rtc_mips_set_mmss)
+ rtc_mips_set_mmss = rtc_mips_set_time;
- xtime.tv_sec = rtc_get_time();
+ xtime.tv_sec = rtc_mips_get_time();
xtime.tv_nsec = 0;
set_normalized_timespec(&wall_to_monotonic,
@@ -772,8 +771,8 @@ void to_tm(unsigned long tim, struct rtc_time *tm)
EXPORT_SYMBOL(rtc_lock);
EXPORT_SYMBOL(to_tm);
-EXPORT_SYMBOL(rtc_set_time);
-EXPORT_SYMBOL(rtc_get_time);
+EXPORT_SYMBOL(rtc_mips_set_time);
+EXPORT_SYMBOL(rtc_mips_get_time);
unsigned long long sched_clock(void)
{
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index bed0eb6cf55..a7564b08eb4 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -42,6 +42,7 @@
#include <asm/watch.h>
#include <asm/types.h>
+extern asmlinkage void handle_int(void);
extern asmlinkage void handle_tlbm(void);
extern asmlinkage void handle_tlbl(void);
extern asmlinkage void handle_tlbs(void);
@@ -279,9 +280,16 @@ static DEFINE_SPINLOCK(die_lock);
NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs)
{
static int die_counter;
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned long dvpret = dvpe();
+#endif /* CONFIG_MIPS_MT_SMTC */
console_verbose();
spin_lock_irq(&die_lock);
+ bust_spinlocks(1);
+#ifdef CONFIG_MIPS_MT_SMTC
+ mips_mt_regdump(dvpret);
+#endif /* CONFIG_MIPS_MT_SMTC */
printk("%s[#%d]:\n", str, ++die_counter);
show_registers(regs);
spin_unlock_irq(&die_lock);
@@ -750,12 +758,43 @@ asmlinkage void do_cpu(struct pt_regs *regs)
&current->thread.fpu.soft);
if (sig)
force_sig(sig, current);
+#ifdef CONFIG_MIPS_MT_FPAFF
+ else {
+ /*
+ * MIPS MT processors may have fewer FPU contexts
+ * than CPU threads. If we've emulated more than
+ * some threshold number of instructions, force
+ * migration to a "CPU" that has FP support.
+ */
+ if(mt_fpemul_threshold > 0
+ && ((current->thread.emulated_fp++
+ > mt_fpemul_threshold))) {
+ /*
+ * If there's no FPU present, or if the
+ * application has already restricted
+ * the allowed set to exclude any CPUs
+ * with FPUs, we'll skip the procedure.
+ */
+ if (cpus_intersects(current->cpus_allowed,
+ mt_fpu_cpumask)) {
+ cpumask_t tmask;
+
+ cpus_and(tmask,
+ current->thread.user_cpus_allowed,
+ mt_fpu_cpumask);
+ set_cpus_allowed(current, tmask);
+ current->thread.mflags |= MF_FPUBOUND;
+ }
+ }
+ }
+#endif /* CONFIG_MIPS_MT_FPAFF */
}
return;
case 2:
case 3:
+ die_if_kernel("do_cpu invoked from kernel context!", regs);
break;
}
@@ -780,19 +819,64 @@ asmlinkage void do_watch(struct pt_regs *regs)
asmlinkage void do_mcheck(struct pt_regs *regs)
{
+ const int field = 2 * sizeof(unsigned long);
+ int multi_match = regs->cp0_status & ST0_TS;
+
show_regs(regs);
- dump_tlb_all();
+
+ if (multi_match) {
+ printk("Index : %0x\n", read_c0_index());
+ printk("Pagemask: %0x\n", read_c0_pagemask());
+ printk("EntryHi : %0*lx\n", field, read_c0_entryhi());
+ printk("EntryLo0: %0*lx\n", field, read_c0_entrylo0());
+ printk("EntryLo1: %0*lx\n", field, read_c0_entrylo1());
+ printk("\n");
+ dump_tlb_all();
+ }
+
+ show_code((unsigned int *) regs->cp0_epc);
+
/*
* Some chips may have other causes of machine check (e.g. SB1
* graduation timer)
*/
panic("Caught Machine Check exception - %scaused by multiple "
"matching entries in the TLB.",
- (regs->cp0_status & ST0_TS) ? "" : "not ");
+ (multi_match) ? "" : "not ");
}
asmlinkage void do_mt(struct pt_regs *regs)
{
+ int subcode;
+
+ die_if_kernel("MIPS MT Thread exception in kernel", regs);
+
+ subcode = (read_vpe_c0_vpecontrol() & VPECONTROL_EXCPT)
+ >> VPECONTROL_EXCPT_SHIFT;
+ switch (subcode) {
+ case 0:
+ printk(KERN_ERR "Thread Underflow\n");
+ break;
+ case 1:
+ printk(KERN_ERR "Thread Overflow\n");
+ break;
+ case 2:
+ printk(KERN_ERR "Invalid YIELD Qualifier\n");
+ break;
+ case 3:
+ printk(KERN_ERR "Gating Storage Exception\n");
+ break;
+ case 4:
+ printk(KERN_ERR "YIELD Scheduler Exception\n");
+ break;
+ case 5:
+ printk(KERN_ERR "Gating Storage Schedulier Exception\n");
+ break;
+ default:
+ printk(KERN_ERR "*** UNKNOWN THREAD EXCEPTION %d ***\n",
+ subcode);
+ break;
+ }
die_if_kernel("MIPS MT Thread exception in kernel", regs);
force_sig(SIGILL, current);
@@ -833,6 +917,7 @@ static inline void parity_protection_init(void)
{
switch (current_cpu_data.cputype) {
case CPU_24K:
+ case CPU_34K:
case CPU_5KC:
write_c0_ecc(0x80000000);
back_to_back_c0_hazard();
@@ -928,7 +1013,15 @@ void ejtag_exception_handler(struct pt_regs *regs)
*/
void nmi_exception_handler(struct pt_regs *regs)
{
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned long dvpret = dvpe();
+ bust_spinlocks(1);
printk("NMI taken!!!!\n");
+ mips_mt_regdump(dvpret);
+#else
+ bust_spinlocks(1);
+ printk("NMI taken!!!!\n");
+#endif /* CONFIG_MIPS_MT_SMTC */
die("NMI", regs);
while(1) ;
}
@@ -960,27 +1053,29 @@ void *set_except_vector(int n, void *addr)
#ifdef CONFIG_CPU_MIPSR2
/*
- * Shadow register allocation
+ * MIPSR2 shadow register set allocation
* FIXME: SMP...
*/
-/* MIPSR2 shadow register sets */
-struct shadow_registers {
- spinlock_t sr_lock; /* */
- int sr_supported; /* Number of shadow register sets supported */
- int sr_allocated; /* Bitmap of allocated shadow registers */
+static struct shadow_registers {
+ /*
+ * Number of shadow register sets supported
+ */
+ unsigned long sr_supported;
+ /*
+ * Bitmap of allocated shadow registers
+ */
+ unsigned long sr_allocated;
} shadow_registers;
-void mips_srs_init(void)
+static void mips_srs_init(void)
{
#ifdef CONFIG_CPU_MIPSR2_SRS
shadow_registers.sr_supported = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
- printk ("%d MIPSR2 register sets available\n", shadow_registers.sr_supported);
-#else
- shadow_registers.sr_supported = 1;
+ printk(KERN_INFO "%d MIPSR2 register sets available\n",
+ shadow_registers.sr_supported);
#endif
shadow_registers.sr_allocated = 1; /* Set 0 used by kernel */
- spin_lock_init(&shadow_registers.sr_lock);
}
int mips_srs_max(void)
@@ -988,38 +1083,30 @@ int mips_srs_max(void)
return shadow_registers.sr_supported;
}
-int mips_srs_alloc (void)
+int mips_srs_alloc(void)
{
struct shadow_registers *sr = &shadow_registers;
- unsigned long flags;
int set;
- spin_lock_irqsave(&sr->sr_lock, flags);
+again:
+ set = find_first_zero_bit(&sr->sr_allocated, sr->sr_supported);
+ if (set >= sr->sr_supported)
+ return -1;
- for (set = 0; set < sr->sr_supported; set++) {
- if ((sr->sr_allocated & (1 << set)) == 0) {
- sr->sr_allocated |= 1 << set;
- spin_unlock_irqrestore(&sr->sr_lock, flags);
- return set;
- }
- }
+ if (test_and_set_bit(set, &sr->sr_allocated))
+ goto again;
- /* None available */
- spin_unlock_irqrestore(&sr->sr_lock, flags);
- return -1;
+ return set;
}
-void mips_srs_free (int set)
+void mips_srs_free(int set)
{
struct shadow_registers *sr = &shadow_registers;
- unsigned long flags;
- spin_lock_irqsave(&sr->sr_lock, flags);
- sr->sr_allocated &= ~(1 << set);
- spin_unlock_irqrestore(&sr->sr_lock, flags);
+ clear_bit(set, &sr->sr_allocated);
}
-void *set_vi_srs_handler (int n, void *addr, int srs)
+static void *set_vi_srs_handler(int n, void *addr, int srs)
{
unsigned long handler;
unsigned long old_handler = vi_handlers[n];
@@ -1032,8 +1119,7 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
if (addr == NULL) {
handler = (unsigned long) do_default_vi;
srs = 0;
- }
- else
+ } else
handler = (unsigned long) addr;
vi_handlers[n] = (unsigned long) addr;
@@ -1045,8 +1131,7 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
if (cpu_has_veic) {
if (board_bind_eic_interrupt)
board_bind_eic_interrupt (n, srs);
- }
- else if (cpu_has_vint) {
+ } else if (cpu_has_vint) {
/* SRSMap is only defined if shadow sets are implemented */
if (mips_srs_max() > 1)
change_c0_srsmap (0xf << n*4, srs << n*4);
@@ -1060,6 +1145,15 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
extern char except_vec_vi, except_vec_vi_lui;
extern char except_vec_vi_ori, except_vec_vi_end;
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * We need to provide the SMTC vectored interrupt handler
+ * not only with the address of the handler, but with the
+ * Status.IM bit to be masked before going there.
+ */
+ extern char except_vec_vi_mori;
+ const int mori_offset = &except_vec_vi_mori - &except_vec_vi;
+#endif /* CONFIG_MIPS_MT_SMTC */
const int handler_len = &except_vec_vi_end - &except_vec_vi;
const int lui_offset = &except_vec_vi_lui - &except_vec_vi;
const int ori_offset = &except_vec_vi_ori - &except_vec_vi;
@@ -1073,6 +1167,12 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
}
memcpy (b, &except_vec_vi, handler_len);
+#ifdef CONFIG_MIPS_MT_SMTC
+ if (n > 7)
+ printk("Vector index %d exceeds SMTC maximum\n", n);
+ w = (u32 *)(b + mori_offset);
+ *w = (*w & 0xffff0000) | (0x100 << n);
+#endif /* CONFIG_MIPS_MT_SMTC */
w = (u32 *)(b + lui_offset);
*w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);
w = (u32 *)(b + ori_offset);
@@ -1095,9 +1195,9 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
return (void *)old_handler;
}
-void *set_vi_handler (int n, void *addr)
+void *set_vi_handler(int n, void *addr)
{
- return set_vi_srs_handler (n, addr, 0);
+ return set_vi_srs_handler(n, addr, 0);
}
#endif
@@ -1113,8 +1213,29 @@ extern asmlinkage int _restore_fp_context(struct sigcontext *sc);
extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);
extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);
+#ifdef CONFIG_SMP
+static int smp_save_fp_context(struct sigcontext *sc)
+{
+ return cpu_has_fpu
+ ? _save_fp_context(sc)
+ : fpu_emulator_save_context(sc);
+}
+
+static int smp_restore_fp_context(struct sigcontext *sc)
+{
+ return cpu_has_fpu
+ ? _restore_fp_context(sc)
+ : fpu_emulator_restore_context(sc);
+}
+#endif
+
static inline void signal_init(void)
{
+#ifdef CONFIG_SMP
+ /* For now just do the cpu_has_fpu check when the functions are invoked */
+ save_fp_context = smp_save_fp_context;
+ restore_fp_context = smp_restore_fp_context;
+#else
if (cpu_has_fpu) {
save_fp_context = _save_fp_context;
restore_fp_context = _restore_fp_context;
@@ -1122,6 +1243,7 @@ static inline void signal_init(void)
save_fp_context = fpu_emulator_save_context;
restore_fp_context = fpu_emulator_restore_context;
}
+#endif
}
#ifdef CONFIG_MIPS32_COMPAT
@@ -1158,6 +1280,20 @@ void __init per_cpu_trap_init(void)
{
unsigned int cpu = smp_processor_id();
unsigned int status_set = ST0_CU0;
+#ifdef CONFIG_MIPS_MT_SMTC
+ int secondaryTC = 0;
+ int bootTC = (cpu == 0);
+
+ /*
+ * Only do per_cpu_trap_init() for first TC of Each VPE.
+ * Note that this hack assumes that the SMTC init code
+ * assigns TCs consecutively and in ascending order.
+ */
+
+ if (((read_c0_tcbind() & TCBIND_CURTC) != 0) &&
+ ((read_c0_tcbind() & TCBIND_CURVPE) == cpu_data[cpu - 1].vpe_id))
+ secondaryTC = 1;
+#endif /* CONFIG_MIPS_MT_SMTC */
/*
* Disable coprocessors and select 32-bit or 64-bit addressing
@@ -1180,6 +1316,10 @@ void __init per_cpu_trap_init(void)
write_c0_hwrena (0x0000000f); /* Allow rdhwr to all registers */
#endif
+#ifdef CONFIG_MIPS_MT_SMTC
+ if (!secondaryTC) {
+#endif /* CONFIG_MIPS_MT_SMTC */
+
/*
* Interrupt handling.
*/
@@ -1196,6 +1336,9 @@ void __init per_cpu_trap_init(void)
} else
set_c0_cause(CAUSEF_IV);
}
+#ifdef CONFIG_MIPS_MT_SMTC
+ }
+#endif /* CONFIG_MIPS_MT_SMTC */
cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
TLBMISS_HANDLER_SETUP();
@@ -1205,8 +1348,14 @@ void __init per_cpu_trap_init(void)
BUG_ON(current->mm);
enter_lazy_tlb(&init_mm, current);
- cpu_cache_init();
- tlb_init();
+#ifdef CONFIG_MIPS_MT_SMTC
+ if (bootTC) {
+#endif /* CONFIG_MIPS_MT_SMTC */
+ cpu_cache_init();
+ tlb_init();
+#ifdef CONFIG_MIPS_MT_SMTC
+ }
+#endif /* CONFIG_MIPS_MT_SMTC */
}
/* Install CPU exception handler */
@@ -1278,7 +1427,7 @@ void __init trap_init(void)
if (cpu_has_veic || cpu_has_vint) {
int nvec = cpu_has_veic ? 64 : 8;
for (i = 0; i < nvec; i++)
- set_vi_handler (i, NULL);
+ set_vi_handler(i, NULL);
}
else if (cpu_has_divec)
set_handler(0x200, &except_vec4, 0x8);
@@ -1297,6 +1446,7 @@ void __init trap_init(void)
if (board_be_init)
board_be_init();
+ set_except_vector(0, handle_int);
set_except_vector(1, handle_tlbm);
set_except_vector(2, handle_tlbl);
set_except_vector(3, handle_tlbs);
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 2ad0cedf29f..b84d1f9ce28 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -2,7 +2,7 @@
#include <asm/asm-offsets.h>
#include <asm-generic/vmlinux.lds.h>
-#undef mips /* CPP really sucks for this job */
+#undef mips
#define mips mips
OUTPUT_ARCH(mips)
ENTRY(kernel_entry)
@@ -151,23 +151,13 @@ SECTIONS
/* This is the MIPS specific mdebug section. */
.mdebug : { *(.mdebug) }
- /* These are needed for ELF backends which have not yet been
- converted to the new style linker. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- /* DWARF debug sections.
- Symbols in the .debug DWARF section are relative to the beginning of the
- section so we begin .debug at 0. It's not clear yet what needs to happen
- for the others. */
- .debug 0 : { *(.debug) }
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- .line 0 : { *(.line) }
+
+ STABS_DEBUG
+
+ DWARF_DEBUG
+
/* These must appear regardless of . */
.gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
.gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
- .comment : { *(.comment) }
.note : { *(.note) }
}
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index ae83b755cf4..85d7df7b18e 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -13,7 +13,6 @@
* 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.
- *
*/
/*
@@ -27,11 +26,8 @@
*
* To load and run, simply cat a SP 'program file' to /dev/vpe1.
* i.e cat spapp >/dev/vpe1.
- *
- * You'll need to have the following device files.
- * mknod /dev/vpe0 c 63 0
- * mknod /dev/vpe1 c 63 1
*/
+
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -55,6 +51,8 @@
#include <asm/cpu.h>
#include <asm/processor.h>
#include <asm/system.h>
+#include <asm/vpe.h>
+#include <asm/kspd.h>
typedef void *vpe_handle;
@@ -68,6 +66,11 @@ typedef void *vpe_handle;
static char module_name[] = "vpe";
static int major;
+#ifdef CONFIG_MIPS_APSP_KSPD
+ static struct kspd_notifications kspd_events;
+static int kspd_events_reqd = 0;
+#endif
+
/* grab the likely amount of memory we will need. */
#ifdef CONFIG_MIPS_VPE_LOADER_TOM
#define P_SIZE (2 * 1024 * 1024)
@@ -76,7 +79,10 @@ static int major;
#define P_SIZE (256 * 1024)
#endif
+extern unsigned long physical_memsize;
+
#define MAX_VPES 16
+#define VPE_PATH_MAX 256
enum vpe_state {
VPE_STATE_UNUSED = 0,
@@ -102,6 +108,8 @@ struct vpe {
unsigned long len;
char *pbuffer;
unsigned long plen;
+ unsigned int uid, gid;
+ char cwd[VPE_PATH_MAX];
unsigned long __start;
@@ -113,6 +121,9 @@ struct vpe {
/* shared symbol address */
void *shared_ptr;
+
+ /* the list of who wants to know when something major happens */
+ struct list_head notify;
};
struct tc {
@@ -138,7 +149,7 @@ struct vpecontrol_ {
} vpecontrol;
static void release_progmem(void *ptr);
-static void dump_vpe(struct vpe * v);
+/* static __attribute_used__ void dump_vpe(struct vpe * v); */
extern void save_gp_address(unsigned int secbase, unsigned int rel);
/* get the vpe associated with this minor */
@@ -146,12 +157,14 @@ struct vpe *get_vpe(int minor)
{
struct vpe *v;
+ if (!cpu_has_mipsmt)
+ return NULL;
+
list_for_each_entry(v, &vpecontrol.vpe_list, list) {
if (v->minor == minor)
return v;
}
- printk(KERN_DEBUG "VPE: get_vpe minor %d not found\n", minor);
return NULL;
}
@@ -165,8 +178,6 @@ struct tc *get_tc(int index)
return t;
}
- printk(KERN_DEBUG "VPE: get_tc index %d not found\n", index);
-
return NULL;
}
@@ -179,8 +190,6 @@ struct tc *get_tc_unused(void)
return t;
}
- printk(KERN_DEBUG "VPE: All TC's are in use\n");
-
return NULL;
}
@@ -190,13 +199,13 @@ struct vpe *alloc_vpe(int minor)
struct vpe *v;
if ((v = kzalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING "VPE: alloc_vpe no mem\n");
return NULL;
}
INIT_LIST_HEAD(&v->tc);
list_add_tail(&v->list, &vpecontrol.vpe_list);
+ INIT_LIST_HEAD(&v->notify);
v->minor = minor;
return v;
}
@@ -207,7 +216,6 @@ struct tc *alloc_tc(int index)
struct tc *t;
if ((t = kzalloc(sizeof(struct tc), GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING "VPE: alloc_tc no mem\n");
return NULL;
}
@@ -236,20 +244,16 @@ void dump_mtregs(void)
printk("config3 0x%lx MT %ld\n", val,
(val & CONFIG3_MT) >> CONFIG3_MT_SHIFT);
- val = read_c0_mvpconf0();
- printk("mvpconf0 0x%lx, PVPE %ld PTC %ld M %ld\n", val,
- (val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT,
- val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT);
-
val = read_c0_mvpcontrol();
printk("MVPControl 0x%lx, STLB %ld VPC %ld EVP %ld\n", val,
(val & MVPCONTROL_STLB) >> MVPCONTROL_STLB_SHIFT,
(val & MVPCONTROL_VPC) >> MVPCONTROL_VPC_SHIFT,
(val & MVPCONTROL_EVP));
- val = read_c0_vpeconf0();
- printk("VPEConf0 0x%lx MVP %ld\n", val,
- (val & VPECONF0_MVP) >> VPECONF0_MVP_SHIFT);
+ val = read_c0_mvpconf0();
+ printk("mvpconf0 0x%lx, PVPE %ld PTC %ld M %ld\n", val,
+ (val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT,
+ val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT);
}
/* Find some VPE program space */
@@ -354,9 +358,9 @@ static int apply_r_mips_gprel16(struct module *me, uint32_t *location,
}
if( (rel > 32768) || (rel < -32768) ) {
- printk(KERN_ERR
- "apply_r_mips_gprel16: relative address out of range 0x%x %d\n",
- rel, rel);
+ printk(KERN_DEBUG "VPE loader: apply_r_mips_gprel16: "
+ "relative address 0x%x out of range of gp register\n",
+ rel);
return -ENOEXEC;
}
@@ -374,8 +378,8 @@ static int apply_r_mips_pc16(struct module *me, uint32_t *location,
rel -= 1; // and one instruction less due to the branch delay slot.
if( (rel > 32768) || (rel < -32768) ) {
- printk(KERN_ERR
- "apply_r_mips_pc16: relative address out of range 0x%x\n", rel);
+ printk(KERN_DEBUG "VPE loader: "
+ "apply_r_mips_pc16: relative address out of range 0x%x\n", rel);
return -ENOEXEC;
}
@@ -396,7 +400,8 @@ static int apply_r_mips_26(struct module *me, uint32_t *location,
Elf32_Addr v)
{
if (v % 4) {
- printk(KERN_ERR "module %s: dangerous relocation mod4\n", me->name);
+ printk(KERN_DEBUG "VPE loader: apply_r_mips_26 "
+ " unaligned relocation\n");
return -ENOEXEC;
}
@@ -459,12 +464,13 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location,
/*
* The value for the HI16 had best be the same.
*/
- if (v != l->value) {
- printk("%d != %d\n", v, l->value);
- goto out_danger;
+ if (v != l->value) {
+ printk(KERN_DEBUG "VPE loader: "
+ "apply_r_mips_lo16/hi16: "
+ "inconsistent value information\n");
+ return -ENOEXEC;
}
-
/*
* Do the HI16 relocation. Note that we actually don't
* need to know anything about the LO16 itself, except
@@ -500,11 +506,6 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location,
*location = insnlo;
return 0;
-
-out_danger:
- printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
-
- return -ENOEXEC;
}
static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
@@ -518,6 +519,15 @@ static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
[R_MIPS_PC16] = apply_r_mips_pc16
};
+static char *rstrs[] = {
+ [R_MIPS_NONE] = "MIPS_NONE",
+ [R_MIPS_32] = "MIPS_32",
+ [R_MIPS_26] = "MIPS_26",
+ [R_MIPS_HI16] = "MIPS_HI16",
+ [R_MIPS_LO16] = "MIPS_LO16",
+ [R_MIPS_GPREL16] = "MIPS_GPREL16",
+ [R_MIPS_PC16] = "MIPS_PC16"
+};
int apply_relocations(Elf32_Shdr *sechdrs,
const char *strtab,
@@ -552,15 +562,13 @@ int apply_relocations(Elf32_Shdr *sechdrs,
res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v);
if( res ) {
- printk(KERN_DEBUG
- "relocation error 0x%x sym refer <%s> value 0x%x "
- "type 0x%x r_info 0x%x\n",
- (unsigned int)location, strtab + sym->st_name, v,
- r_info, ELF32_R_TYPE(r_info));
- }
-
- if (res)
+ char *r = rstrs[ELF32_R_TYPE(r_info)];
+ printk(KERN_WARNING "VPE loader: .text+0x%x "
+ "relocation type %s for symbol \"%s\" failed\n",
+ rel[i].r_offset, r ? r : "UNKNOWN",
+ strtab + sym->st_name);
return res;
+ }
}
return 0;
@@ -576,7 +584,7 @@ void save_gp_address(unsigned int secbase, unsigned int rel)
/* Change all symbols so that sh_value encodes the pointer directly. */
-static int simplify_symbols(Elf_Shdr * sechdrs,
+static void simplify_symbols(Elf_Shdr * sechdrs,
unsigned int symindex,
const char *strtab,
const char *secstrings,
@@ -585,18 +593,21 @@ static int simplify_symbols(Elf_Shdr * sechdrs,
Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
unsigned long secbase, bssbase = 0;
unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
- int ret = 0, size;
+ int size;
/* find the .bss section for COMMON symbols */
for (i = 0; i < nsecs; i++) {
- if (strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) == 0)
+ if (strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) == 0) {
bssbase = sechdrs[i].sh_addr;
+ break;
+ }
}
for (i = 1; i < n; i++) {
switch (sym[i].st_shndx) {
case SHN_COMMON:
- /* Allocate space for the symbol in the .bss section. st_value is currently size.
+ /* Allocate space for the symbol in the .bss section.
+ st_value is currently size.
We want it to have the address of the symbol. */
size = sym[i].st_value;
@@ -614,11 +625,9 @@ static int simplify_symbols(Elf_Shdr * sechdrs,
break;
case SHN_MIPS_SCOMMON:
-
- printk(KERN_DEBUG
- "simplify_symbols: ignoring SHN_MIPS_SCOMMON symbol <%s> st_shndx %d\n",
- strtab + sym[i].st_name, sym[i].st_shndx);
-
+ printk(KERN_DEBUG "simplify_symbols: ignoring SHN_MIPS_SCOMMON"
+ "symbol <%s> st_shndx %d\n", strtab + sym[i].st_name,
+ sym[i].st_shndx);
// .sbss section
break;
@@ -632,10 +641,7 @@ static int simplify_symbols(Elf_Shdr * sechdrs,
sym[i].st_value += secbase;
break;
}
-
}
-
- return ret;
}
#ifdef DEBUG_ELFLOADER
@@ -655,9 +661,26 @@ static void dump_elfsymbols(Elf_Shdr * sechdrs, unsigned int symindex,
static void dump_tc(struct tc *t)
{
- printk(KERN_WARNING "VPE: TC index %d TCStatus 0x%lx halt 0x%lx\n",
- t->index, read_tc_c0_tcstatus(), read_tc_c0_tchalt());
- printk(KERN_WARNING "VPE: tcrestart 0x%lx\n", read_tc_c0_tcrestart());
+ unsigned long val;
+
+ settc(t->index);
+ printk(KERN_DEBUG "VPE loader: TC index %d targtc %ld "
+ "TCStatus 0x%lx halt 0x%lx\n",
+ t->index, read_c0_vpecontrol() & VPECONTROL_TARGTC,
+ read_tc_c0_tcstatus(), read_tc_c0_tchalt());
+
+ printk(KERN_DEBUG " tcrestart 0x%lx\n", read_tc_c0_tcrestart());
+ printk(KERN_DEBUG " tcbind 0x%lx\n", read_tc_c0_tcbind());
+
+ val = read_c0_vpeconf0();
+ printk(KERN_DEBUG " VPEConf0 0x%lx MVP %ld\n", val,
+ (val & VPECONF0_MVP) >> VPECONF0_MVP_SHIFT);
+
+ printk(KERN_DEBUG " c0 status 0x%lx\n", read_vpe_c0_status());
+ printk(KERN_DEBUG " c0 cause 0x%lx\n", read_vpe_c0_cause());
+
+ printk(KERN_DEBUG " c0 badvaddr 0x%lx\n", read_vpe_c0_badvaddr());
+ printk(KERN_DEBUG " c0 epc 0x%lx\n", read_vpe_c0_epc());
}
static void dump_tclist(void)
@@ -672,96 +695,108 @@ static void dump_tclist(void)
/* We are prepared so configure and start the VPE... */
int vpe_run(struct vpe * v)
{
- unsigned long val;
+ struct vpe_notifications *n;
+ unsigned long val, dmt_flag;
struct tc *t;
/* check we are the Master VPE */
val = read_c0_vpeconf0();
if (!(val & VPECONF0_MVP)) {
printk(KERN_WARNING
- "VPE: only Master VPE's are allowed to configure MT\n");
+ "VPE loader: only Master VPE's are allowed to configure MT\n");
return -1;
}
/* disable MT (using dvpe) */
dvpe();
+ if (!list_empty(&v->tc)) {
+ if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
+ printk(KERN_WARNING "VPE loader: TC %d is already in use.\n",
+ t->index);
+ return -ENOEXEC;
+ }
+ } else {
+ printk(KERN_WARNING "VPE loader: No TC's associated with VPE %d\n",
+ v->minor);
+ return -ENOEXEC;
+ }
+
/* Put MVPE's into 'configuration state' */
set_c0_mvpcontrol(MVPCONTROL_VPC);
- if (!list_empty(&v->tc)) {
- if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
- printk(KERN_WARNING "VPE: TC %d is already in use.\n",
- t->index);
- return -ENOEXEC;
- }
- } else {
- printk(KERN_WARNING "VPE: No TC's associated with VPE %d\n",
- v->minor);
- return -ENOEXEC;
- }
-
settc(t->index);
- val = read_vpe_c0_vpeconf0();
-
/* should check it is halted, and not activated */
if ((read_tc_c0_tcstatus() & TCSTATUS_A) || !(read_tc_c0_tchalt() & TCHALT_H)) {
- printk(KERN_WARNING "VPE: TC %d is already doing something!\n",
+ printk(KERN_WARNING "VPE loader: TC %d is already doing something!\n",
t->index);
-
dump_tclist();
return -ENOEXEC;
}
+ /*
+ * Disable multi-threaded execution whilst we activate, clear the
+ * halt bit and bound the tc to the other VPE...
+ */
+ dmt_flag = dmt();
+
/* Write the address we want it to start running from in the TCPC register. */
write_tc_c0_tcrestart((unsigned long)v->__start);
-
- /* write the sivc_info address to tccontext */
write_tc_c0_tccontext((unsigned long)0);
-
- /* Set up the XTC bit in vpeconf0 to point at our tc */
- write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | (t->index << VPECONF0_XTC_SHIFT));
-
- /* mark the TC as activated, not interrupt exempt and not dynamically allocatable */
+ /*
+ * Mark the TC as activated, not interrupt exempt and not dynamically
+ * allocatable
+ */
val = read_tc_c0_tcstatus();
val = (val & ~(TCSTATUS_DA | TCSTATUS_IXMT)) | TCSTATUS_A;
write_tc_c0_tcstatus(val);
write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
- /* set up VPE1 */
- write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE); // no multiple TC's
- write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA); // enable this VPE
-
/*
* The sde-kit passes 'memsize' to __start in $a3, so set something
- * here...
- * Or set $a3 (register 7) to zero and define DFLT_STACK_SIZE and
+ * here... Or set $a3 to zero and define DFLT_STACK_SIZE and
* DFLT_HEAP_SIZE when you compile your program
*/
+ mttgpr(7, physical_memsize);
+
+
+ /* set up VPE1 */
+ /*
+ * bind the TC to VPE 1 as late as possible so we only have the final
+ * VPE registers to set up, and so an EJTAG probe can trigger on it
+ */
+ write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | v->minor);
- mttgpr(7, 0);
+ /* Set up the XTC bit in vpeconf0 to point at our tc */
+ write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
+ | (t->index << VPECONF0_XTC_SHIFT));
- /* set config to be the same as vpe0, particularly kseg0 coherency alg */
- write_vpe_c0_config(read_c0_config());
+ /* enable this VPE */
+ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
/* clear out any left overs from a previous program */
+ write_vpe_c0_status(0);
write_vpe_c0_cause(0);
/* take system out of configuration state */
clear_c0_mvpcontrol(MVPCONTROL_VPC);
- /* clear interrupts enabled IE, ERL, EXL, and KSU from c0 status */
- write_vpe_c0_status(read_vpe_c0_status() & ~(ST0_ERL | ST0_KSU | ST0_IE | ST0_EXL));
+ /* now safe to re-enable multi-threading */
+ emt(dmt_flag);
/* set it running */
evpe(EVPE_ENABLE);
+ list_for_each_entry(n, &v->notify, list) {
+ n->start(v->minor);
+ }
+
return 0;
}
-static unsigned long find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
+static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
unsigned int symindex, const char *strtab,
struct module *mod)
{
@@ -778,26 +813,28 @@ static unsigned long find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
}
}
+ if ( (v->__start == 0) || (v->shared_ptr == NULL))
+ return -1;
+
return 0;
}
/*
- * Allocates a VPE with some program code space(the load address), copies
- * the contents of the program (p)buffer performing relocatations/etc,
- * free's it when finished.
-*/
+ * Allocates a VPE with some program code space(the load address), copies the
+ * contents of the program (p)buffer performing relocatations/etc, free's it
+ * when finished.
+ */
int vpe_elfload(struct vpe * v)
{
Elf_Ehdr *hdr;
Elf_Shdr *sechdrs;
long err = 0;
char *secstrings, *strtab = NULL;
- unsigned int len, i, symindex = 0, strindex = 0;
-
+ unsigned int len, i, symindex = 0, strindex = 0, relocate = 0;
struct module mod; // so we can re-use the relocations code
memset(&mod, 0, sizeof(struct module));
- strcpy(mod.name, "VPE dummy prog module");
+ strcpy(mod.name, "VPE loader");
hdr = (Elf_Ehdr *) v->pbuffer;
len = v->plen;
@@ -805,16 +842,22 @@ int vpe_elfload(struct vpe * v)
/* Sanity checks against insmoding binaries or wrong arch,
weird elf version */
if (memcmp(hdr->e_ident, ELFMAG, 4) != 0
- || hdr->e_type != ET_REL || !elf_check_arch(hdr)
+ || (hdr->e_type != ET_REL && hdr->e_type != ET_EXEC)
+ || !elf_check_arch(hdr)
|| hdr->e_shentsize != sizeof(*sechdrs)) {
printk(KERN_WARNING
- "VPE program, wrong arch or weird elf version\n");
+ "VPE loader: program wrong arch or weird elf version\n");
return -ENOEXEC;
}
+ if (hdr->e_type == ET_REL)
+ relocate = 1;
+
if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr)) {
- printk(KERN_ERR "VPE program length %u truncated\n", len);
+ printk(KERN_ERR "VPE loader: program length %u truncated\n",
+ len);
+
return -ENOEXEC;
}
@@ -826,82 +869,126 @@ int vpe_elfload(struct vpe * v)
/* And these should exist, but gcc whinges if we don't init them */
symindex = strindex = 0;
- for (i = 1; i < hdr->e_shnum; i++) {
-
- if (sechdrs[i].sh_type != SHT_NOBITS
- && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) {
- printk(KERN_ERR "VPE program length %u truncated\n",
- len);
- return -ENOEXEC;
- }
+ if (relocate) {
+ for (i = 1; i < hdr->e_shnum; i++) {
+ if (sechdrs[i].sh_type != SHT_NOBITS
+ && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) {
+ printk(KERN_ERR "VPE program length %u truncated\n",
+ len);
+ return -ENOEXEC;
+ }
- /* Mark all sections sh_addr with their address in the
- temporary image. */
- sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
+ /* Mark all sections sh_addr with their address in the
+ temporary image. */
+ sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
- /* Internal symbols and strings. */
- if (sechdrs[i].sh_type == SHT_SYMTAB) {
- symindex = i;
- strindex = sechdrs[i].sh_link;
- strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+ /* Internal symbols and strings. */
+ if (sechdrs[i].sh_type == SHT_SYMTAB) {
+ symindex = i;
+ strindex = sechdrs[i].sh_link;
+ strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+ }
}
+ layout_sections(&mod, hdr, sechdrs, secstrings);
}
- layout_sections(&mod, hdr, sechdrs, secstrings);
-
v->load_addr = alloc_progmem(mod.core_size);
memset(v->load_addr, 0, mod.core_size);
- printk("VPE elf_loader: loading to %p\n", v->load_addr);
+ printk("VPE loader: loading to %p\n", v->load_addr);
- for (i = 0; i < hdr->e_shnum; i++) {
- void *dest;
+ if (relocate) {
+ for (i = 0; i < hdr->e_shnum; i++) {
+ void *dest;
- if (!(sechdrs[i].sh_flags & SHF_ALLOC))
- continue;
+ if (!(sechdrs[i].sh_flags & SHF_ALLOC))
+ continue;
- dest = v->load_addr + sechdrs[i].sh_entsize;
+ dest = v->load_addr + sechdrs[i].sh_entsize;
- if (sechdrs[i].sh_type != SHT_NOBITS)
- memcpy(dest, (void *)sechdrs[i].sh_addr,
- sechdrs[i].sh_size);
- /* Update sh_addr to point to copy in image. */
- sechdrs[i].sh_addr = (unsigned long)dest;
- }
+ if (sechdrs[i].sh_type != SHT_NOBITS)
+ memcpy(dest, (void *)sechdrs[i].sh_addr,
+ sechdrs[i].sh_size);
+ /* Update sh_addr to point to copy in image. */
+ sechdrs[i].sh_addr = (unsigned long)dest;
- /* Fix up syms, so that st_value is a pointer to location. */
- err =
- simplify_symbols(sechdrs, symindex, strtab, secstrings,
- hdr->e_shnum, &mod);
- if (err < 0) {
- printk(KERN_WARNING "VPE: unable to simplify symbols\n");
- goto cleanup;
- }
+ printk(KERN_DEBUG " section sh_name %s sh_addr 0x%x\n",
+ secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr);
+ }
- /* Now do relocations. */
- for (i = 1; i < hdr->e_shnum; i++) {
- const char *strtab = (char *)sechdrs[strindex].sh_addr;
- unsigned int info = sechdrs[i].sh_info;
-
- /* Not a valid relocation section? */
- if (info >= hdr->e_shnum)
- continue;
-
- /* Don't bother with non-allocated sections */
- if (!(sechdrs[info].sh_flags & SHF_ALLOC))
- continue;
-
- if (sechdrs[i].sh_type == SHT_REL)
- err =
- apply_relocations(sechdrs, strtab, symindex, i, &mod);
- else if (sechdrs[i].sh_type == SHT_RELA)
- err = apply_relocate_add(sechdrs, strtab, symindex, i,
- &mod);
- if (err < 0) {
- printk(KERN_WARNING
- "vpe_elfload: error in relocations err %ld\n",
- err);
- goto cleanup;
+ /* Fix up syms, so that st_value is a pointer to location. */
+ simplify_symbols(sechdrs, symindex, strtab, secstrings,
+ hdr->e_shnum, &mod);
+
+ /* Now do relocations. */
+ for (i = 1; i < hdr->e_shnum; i++) {
+ const char *strtab = (char *)sechdrs[strindex].sh_addr;
+ unsigned int info = sechdrs[i].sh_info;
+
+ /* Not a valid relocation section? */
+ if (info >= hdr->e_shnum)
+ continue;
+
+ /* Don't bother with non-allocated sections */
+ if (!(sechdrs[info].sh_flags & SHF_ALLOC))
+ continue;
+
+ if (sechdrs[i].sh_type == SHT_REL)
+ err = apply_relocations(sechdrs, strtab, symindex, i,
+ &mod);
+ else if (sechdrs[i].sh_type == SHT_RELA)
+ err = apply_relocate_add(sechdrs, strtab, symindex, i,
+ &mod);
+ if (err < 0)
+ return err;
+
+ }
+ } else {
+ for (i = 0; i < hdr->e_shnum; i++) {
+
+ /* Internal symbols and strings. */
+ if (sechdrs[i].sh_type == SHT_SYMTAB) {
+ symindex = i;
+ strindex = sechdrs[i].sh_link;
+ strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+
+ /* mark the symtab's address for when we try to find the
+ magic symbols */
+ sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
+ }
+
+ /* filter sections we dont want in the final image */
+ if (!(sechdrs[i].sh_flags & SHF_ALLOC) ||
+ (sechdrs[i].sh_type == SHT_MIPS_REGINFO)) {
+ printk( KERN_DEBUG " ignoring section, "
+ "name %s type %x address 0x%x \n",
+ secstrings + sechdrs[i].sh_name,
+ sechdrs[i].sh_type, sechdrs[i].sh_addr);
+ continue;
+ }
+
+ if (sechdrs[i].sh_addr < (unsigned int)v->load_addr) {
+ printk( KERN_WARNING "VPE loader: "
+ "fully linked image has invalid section, "
+ "name %s type %x address 0x%x, before load "
+ "address of 0x%x\n",
+ secstrings + sechdrs[i].sh_name,
+ sechdrs[i].sh_type, sechdrs[i].sh_addr,
+ (unsigned int)v->load_addr);
+ return -ENOEXEC;
+ }
+
+ printk(KERN_DEBUG " copying section sh_name %s, sh_addr 0x%x "
+ "size 0x%x0 from x%p\n",
+ secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr,
+ sechdrs[i].sh_size, hdr + sechdrs[i].sh_offset);
+
+ if (sechdrs[i].sh_type != SHT_NOBITS)
+ memcpy((void *)sechdrs[i].sh_addr,
+ (char *)hdr + sechdrs[i].sh_offset,
+ sechdrs[i].sh_size);
+ else
+ memset((void *)sechdrs[i].sh_addr, 0, sechdrs[i].sh_size);
}
}
@@ -910,71 +997,104 @@ int vpe_elfload(struct vpe * v)
(unsigned long)v->load_addr + v->len);
if ((find_vpe_symbols(v, sechdrs, symindex, strtab, &mod)) < 0) {
+ if (v->__start == 0) {
+ printk(KERN_WARNING "VPE loader: program does not contain "
+ "a __start symbol\n");
+ return -ENOEXEC;
+ }
- printk(KERN_WARNING
- "VPE: program doesn't contain __start or vpe_shared symbols\n");
- err = -ENOEXEC;
+ if (v->shared_ptr == NULL)
+ printk(KERN_WARNING "VPE loader: "
+ "program does not contain vpe_shared symbol.\n"
+ " Unable to use AMVP (AP/SP) facilities.\n");
}
printk(" elf loaded\n");
-
-cleanup:
- return err;
+ return 0;
}
-static void dump_vpe(struct vpe * v)
+__attribute_used__ void dump_vpe(struct vpe * v)
{
struct tc *t;
+ settc(v->minor);
+
printk(KERN_DEBUG "VPEControl 0x%lx\n", read_vpe_c0_vpecontrol());
printk(KERN_DEBUG "VPEConf0 0x%lx\n", read_vpe_c0_vpeconf0());
- list_for_each_entry(t, &vpecontrol.tc_list, list) {
+ list_for_each_entry(t, &vpecontrol.tc_list, list)
dump_tc(t);
- }
}
-/* checks for VPE is unused and gets ready to load program */
+static void cleanup_tc(struct tc *tc)
+{
+ int tmp;
+
+ /* Put MVPE's into 'configuration state' */
+ set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+ settc(tc->index);
+ tmp = read_tc_c0_tcstatus();
+
+ /* mark not allocated and not dynamically allocatable */
+ tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
+ tmp |= TCSTATUS_IXMT; /* interrupt exempt */
+ write_tc_c0_tcstatus(tmp);
+
+ write_tc_c0_tchalt(TCHALT_H);
+
+ /* bind it to anything other than VPE1 */
+ write_tc_c0_tcbind(read_tc_c0_tcbind() & ~TCBIND_CURVPE); // | TCBIND_CURVPE
+
+ clear_c0_mvpcontrol(MVPCONTROL_VPC);
+}
+
+static int getcwd(char *buff, int size)
+{
+ mm_segment_t old_fs;
+ int ret;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ ret = sys_getcwd(buff,size);
+
+ set_fs(old_fs);
+
+ return ret;
+}
+
+/* checks VPE is unused and gets ready to load program */
static int vpe_open(struct inode *inode, struct file *filp)
{
- int minor;
+ int minor, ret;
struct vpe *v;
+ struct vpe_notifications *not;
/* assume only 1 device at the mo. */
- if ((minor = MINOR(inode->i_rdev)) != 1) {
- printk(KERN_WARNING "VPE: only vpe1 is supported\n");
+ if ((minor = iminor(inode)) != 1) {
+ printk(KERN_WARNING "VPE loader: only vpe1 is supported\n");
return -ENODEV;
}
if ((v = get_vpe(minor)) == NULL) {
- printk(KERN_WARNING "VPE: unable to get vpe\n");
+ printk(KERN_WARNING "VPE loader: unable to get vpe\n");
return -ENODEV;
}
if (v->state != VPE_STATE_UNUSED) {
- unsigned long tmp;
- struct tc *t;
-
- printk(KERN_WARNING "VPE: device %d already in use\n", minor);
-
dvpe();
- dump_vpe(v);
-
- printk(KERN_WARNING "VPE: re-initialising %d\n", minor);
-
- release_progmem(v->load_addr);
- t = get_tc(minor);
- settc(minor);
- tmp = read_tc_c0_tcstatus();
+ printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n");
- /* mark not allocated and not dynamically allocatable */
- tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
- tmp |= TCSTATUS_IXMT; /* interrupt exempt */
- write_tc_c0_tcstatus(tmp);
+ dump_tc(get_tc(minor));
- write_tc_c0_tchalt(TCHALT_H);
+ list_for_each_entry(not, &v->notify, list) {
+ not->stop(minor);
+ }
+ release_progmem(v->load_addr);
+ cleanup_tc(get_tc(minor));
}
// allocate it so when we get write ops we know it's expected.
@@ -986,6 +1106,24 @@ static int vpe_open(struct inode *inode, struct file *filp)
v->load_addr = NULL;
v->len = 0;
+ v->uid = filp->f_uid;
+ v->gid = filp->f_gid;
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+ /* get kspd to tell us when a syscall_exit happens */
+ if (!kspd_events_reqd) {
+ kspd_notify(&kspd_events);
+ kspd_events_reqd++;
+ }
+#endif
+
+ v->cwd[0] = 0;
+ ret = getcwd(v->cwd, VPE_PATH_MAX);
+ if (ret < 0)
+ printk(KERN_WARNING "VPE loader: open, getcwd returned %d\n", ret);
+
+ v->shared_ptr = NULL;
+ v->__start = 0;
return 0;
}
@@ -995,7 +1133,7 @@ static int vpe_release(struct inode *inode, struct file *filp)
struct vpe *v;
Elf_Ehdr *hdr;
- minor = MINOR(inode->i_rdev);
+ minor = iminor(inode);
if ((v = get_vpe(minor)) == NULL)
return -ENODEV;
@@ -1006,14 +1144,22 @@ static int vpe_release(struct inode *inode, struct file *filp)
if (vpe_elfload(v) >= 0)
vpe_run(v);
else {
- printk(KERN_WARNING "VPE: ELF load failed.\n");
+ printk(KERN_WARNING "VPE loader: ELF load failed.\n");
ret = -ENOEXEC;
}
} else {
- printk(KERN_WARNING "VPE: only elf files are supported\n");
+ printk(KERN_WARNING "VPE loader: only elf files are supported\n");
ret = -ENOEXEC;
}
+ /* It's good to be able to run the SP and if it chokes have a look at
+ the /dev/rt?. But if we reset the pointer to the shared struct we
+ loose what has happened. So perhaps if garbage is sent to the vpe
+ device, use it as a trigger for the reset. Hopefully a nice
+ executable will be along shortly. */
+ if (ret < 0)
+ v->shared_ptr = NULL;
+
// cleanup any temp buffers
if (v->pbuffer)
vfree(v->pbuffer);
@@ -1028,26 +1174,24 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
size_t ret = count;
struct vpe *v;
- minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ minor = iminor(file->f_dentry->d_inode);
if ((v = get_vpe(minor)) == NULL)
return -ENODEV;
if (v->pbuffer == NULL) {
- printk(KERN_ERR "vpe_write: no pbuffer\n");
+ printk(KERN_ERR "VPE loader: no buffer for program\n");
return -ENOMEM;
}
if ((count + v->len) > v->plen) {
printk(KERN_WARNING
- "VPE Loader: elf size too big. Perhaps strip uneeded symbols\n");
+ "VPE loader: elf size too big. Perhaps strip uneeded symbols\n");
return -ENOMEM;
}
count -= copy_from_user(v->pbuffer + v->len, buffer, count);
- if (!count) {
- printk("vpe_write: copy_to_user failed\n");
+ if (!count)
return -EFAULT;
- }
v->len += count;
return ret;
@@ -1149,16 +1293,70 @@ void *vpe_get_shared(int index)
{
struct vpe *v;
- if ((v = get_vpe(index)) == NULL) {
- printk(KERN_WARNING "vpe: invalid vpe index %d\n", index);
+ if ((v = get_vpe(index)) == NULL)
return NULL;
- }
return v->shared_ptr;
}
EXPORT_SYMBOL(vpe_get_shared);
+int vpe_getuid(int index)
+{
+ struct vpe *v;
+
+ if ((v = get_vpe(index)) == NULL)
+ return -1;
+
+ return v->uid;
+}
+
+EXPORT_SYMBOL(vpe_getuid);
+
+int vpe_getgid(int index)
+{
+ struct vpe *v;
+
+ if ((v = get_vpe(index)) == NULL)
+ return -1;
+
+ return v->gid;
+}
+
+EXPORT_SYMBOL(vpe_getgid);
+
+int vpe_notify(int index, struct vpe_notifications *notify)
+{
+ struct vpe *v;
+
+ if ((v = get_vpe(index)) == NULL)
+ return -1;
+
+ list_add(&notify->list, &v->notify);
+ return 0;
+}
+
+EXPORT_SYMBOL(vpe_notify);
+
+char *vpe_getcwd(int index)
+{
+ struct vpe *v;
+
+ if ((v = get_vpe(index)) == NULL)
+ return NULL;
+
+ return v->cwd;
+}
+
+EXPORT_SYMBOL(vpe_getcwd);
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+static void kspd_sp_exit( int sp_id)
+{
+ cleanup_tc(get_tc(sp_id));
+}
+#endif
+
static int __init vpe_module_init(void)
{
struct vpe *v = NULL;
@@ -1201,7 +1399,8 @@ static int __init vpe_module_init(void)
return -ENODEV;
}
- list_add(&t->tc, &v->tc); /* add the tc to the list of this vpe's tc's. */
+ /* add the tc to the list of this vpe's tc's. */
+ list_add(&t->tc, &v->tc);
/* deactivate all but vpe0 */
if (i != 0) {
@@ -1222,10 +1421,12 @@ static int __init vpe_module_init(void)
~(ST0_IM | ST0_IE | ST0_KSU))
| ST0_CU0);
- /* set config to be the same as vpe0, particularly kseg0 coherency alg */
+ /*
+ * Set config to be the same as vpe0,
+ * particularly kseg0 coherency alg
+ */
write_vpe_c0_config(read_c0_config());
}
-
}
/* TC's */
@@ -1234,23 +1435,28 @@ static int __init vpe_module_init(void)
if (i != 0) {
unsigned long tmp;
- /* tc 0 will of course be running.... */
- if (i == 0)
- t->state = TC_STATE_RUNNING;
-
settc(i);
- /* bind a TC to each VPE, May as well put all excess TC's
- on the last VPE */
- if (i >= (((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1))
- write_tc_c0_tcbind(read_tc_c0_tcbind() |
- ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT));
- else
- write_tc_c0_tcbind(read_tc_c0_tcbind() | i);
+ /* Any TC that is bound to VPE0 gets left as is - in case
+ we are running SMTC on VPE0. A TC that is bound to any
+ other VPE gets bound to VPE0, ideally I'd like to make
+ it homeless but it doesn't appear to let me bind a TC
+ to a non-existent VPE. Which is perfectly reasonable.
+
+ The (un)bound state is visible to an EJTAG probe so may
+ notify GDB...
+ */
+
+ if (((tmp = read_tc_c0_tcbind()) & TCBIND_CURVPE)) {
+ /* tc is bound >vpe0 */
+ write_tc_c0_tcbind(tmp & ~TCBIND_CURVPE);
+
+ t->pvpe = get_vpe(0); /* set the parent vpe */
+ }
tmp = read_tc_c0_tcstatus();
- /* mark not allocated and not dynamically allocatable */
+ /* mark not activated and not dynamically allocatable */
tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
tmp |= TCSTATUS_IXMT; /* interrupt exempt */
write_tc_c0_tcstatus(tmp);
@@ -1262,6 +1468,9 @@ static int __init vpe_module_init(void)
/* release config state */
clear_c0_mvpcontrol(MVPCONTROL_VPC);
+#ifdef CONFIG_MIPS_APSP_KSPD
+ kspd_events.kspd_sp_exit = kspd_sp_exit;
+#endif
return 0;
}
@@ -1281,5 +1490,5 @@ static void __exit vpe_module_exit(void)
module_init(vpe_module_init);
module_exit(vpe_module_exit);
MODULE_DESCRIPTION("MIPS VPE Loader");
-MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc");
+MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile
index 0d5aec43672..99f5046fdf4 100644
--- a/arch/mips/lasat/Makefile
+++ b/arch/mips/lasat/Makefile
@@ -3,7 +3,7 @@
#
obj-y += reset.o setup.o prom.o lasat_board.o \
- at93c.o interrupt.o lasatIRQ.o
+ at93c.o interrupt.o
obj-$(CONFIG_LASAT_SYSCTL) += sysctl.o
obj-$(CONFIG_DS1603) += ds1603.o
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
index 852a41901a5..2d3472b21eb 100644
--- a/arch/mips/lasat/interrupt.c
+++ b/arch/mips/lasat/interrupt.c
@@ -27,14 +27,13 @@
#include <asm/bootinfo.h>
#include <asm/irq.h>
#include <asm/lasat/lasatint.h>
+#include <asm/time.h>
#include <asm/gdb-stub.h>
static volatile int *lasat_int_status = NULL;
static volatile int *lasat_int_mask = NULL;
static volatile int lasat_int_mask_shift;
-extern asmlinkage void lasatIRQ(void);
-
void disable_lasat_irq(unsigned int irq_nr)
{
unsigned long flags;
@@ -109,11 +108,17 @@ static unsigned long get_int_status_200(void)
return int_status;
}
-void lasat_hw0_irqdispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned long int_status;
+ unsigned int cause = read_c0_cause();
int irq;
+ if (cause & CAUSEF_IP7) { /* R4000 count / compare IRQ */
+ ll_timer_interrupt(7, regs);
+ return;
+ }
+
int_status = get_int_status();
/* if int_status == 0, then the interrupt has already been cleared */
@@ -147,9 +152,6 @@ void __init arch_init_irq(void)
panic("arch_init_irq: mips_machtype incorrect");
}
- /* Now safe to set the exception vector. */
- set_except_vector(0, lasatIRQ);
-
for (i = 0; i <= LASATINT_END; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = 0;
diff --git a/arch/mips/lasat/lasatIRQ.S b/arch/mips/lasat/lasatIRQ.S
deleted file mode 100644
index 2a2b0d05656..00000000000
--- a/arch/mips/lasat/lasatIRQ.S
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Interrupt exception dispatch code.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .text
- .set noreorder
- .align 5
- NESTED(lasatIRQ, PT_SIZE, sp)
- .set noat
- SAVE_ALL
- CLI
- .set at
- .set noreorder
-
- mfc0 s0, CP0_CAUSE # get irq mask
-
- /* First we check for r4k counter/timer IRQ. */
- andi a0, s0, CAUSEF_IP7
- beq a0, zero, 1f
- andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt
-
- /* Wheee, a timer interrupt. */
- li a0, 7
- jal ll_timer_interrupt
- move a1, sp
-
- j ret_from_irq
- nop
-
-1:
- /* Wheee, combined hardware level zero interrupt. */
- jal lasat_hw0_irqdispatch
- move a0, sp # delay slot
-
- j ret_from_irq
- nop # delay slot
-
-1:
- /*
- * Here by mistake? This is possible, what can happen is that by the
- * time we take the exception the IRQ pin goes low, so just leave if
- * this is the case.
- */
- move a1,s0
- mfc0 a1, CP0_EPC
-
- j ret_from_irq
- nop
- END(lasatIRQ)
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
index 83eb08b7a07..bb70a8240e6 100644
--- a/arch/mips/lasat/setup.c
+++ b/arch/mips/lasat/setup.c
@@ -165,7 +165,8 @@ void __init plat_setup(void)
/* Set up panic notifier */
for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++)
- notifier_chain_register(&panic_notifier_list, &lasat_panic_block[i]);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &lasat_panic_block[i]);
lasat_reboot_setup();
@@ -174,8 +175,8 @@ void __init plat_setup(void)
#ifdef CONFIG_DS1603
ds1603 = &ds_defs[mips_machtype];
- rtc_get_time = ds1603_read;
- rtc_set_time = ds1603_set;
+ rtc_mips_get_time = ds1603_read;
+ rtc_mips_set_time = ds1603_set;
#endif
#ifdef DYNAMIC_SERIAL_INIT
diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c
index a1962eb460f..39a71de16f4 100644
--- a/arch/mips/math-emu/dp_fint.c
+++ b/arch/mips/math-emu/dp_fint.c
@@ -29,7 +29,9 @@
ieee754dp ieee754dp_fint(int x)
{
- COMPXDP;
+ u64 xm;
+ int xe;
+ int xs;
CLEARCX;
diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c
index eae90a866aa..f08f223e488 100644
--- a/arch/mips/math-emu/dp_flong.c
+++ b/arch/mips/math-emu/dp_flong.c
@@ -29,7 +29,9 @@
ieee754dp ieee754dp_flong(s64 x)
{
- COMPXDP;
+ u64 xm;
+ int xe;
+ int xs;
CLEARCX;
diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c
index 7aac13afb09..e88e125e01c 100644
--- a/arch/mips/math-emu/sp_fint.c
+++ b/arch/mips/math-emu/sp_fint.c
@@ -29,7 +29,9 @@
ieee754sp ieee754sp_fint(int x)
{
- COMPXSP;
+ unsigned xm;
+ int xe;
+ int xs;
CLEARCX;
diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c
index 3d6c1d11c17..26d6919a269 100644
--- a/arch/mips/math-emu/sp_flong.c
+++ b/arch/mips/math-emu/sp_flong.c
@@ -29,7 +29,9 @@
ieee754sp ieee754sp_flong(s64 x)
{
- COMPXDP; /* <--- need 64-bit mantissa temp */
+ u64 xm; /* <--- need 64-bit mantissa temp */
+ int xe;
+ int xs;
CLEARCX;
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index bc0ebc69bfb..db53950b7cf 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -39,8 +39,6 @@
static struct atlas_ictrl_regs *atlas_hw0_icregs;
-extern asmlinkage void mipsIRQ(void);
-
#if 0
#define DEBUG_INT(x...) printk(x)
#else
@@ -98,7 +96,7 @@ static inline int ls1bit32(unsigned int x)
return b;
}
-void atlas_hw0_irqdispatch(struct pt_regs *regs)
+static inline void atlas_hw0_irqdispatch(struct pt_regs *regs)
{
unsigned long int_status;
int irq;
@@ -116,6 +114,91 @@ void atlas_hw0_irqdispatch(struct pt_regs *regs)
do_IRQ(irq, regs);
}
+static inline int clz(unsigned long x)
+{
+ __asm__ (
+ " .set push \n"
+ " .set mips32 \n"
+ " clz %0, %1 \n"
+ " .set pop \n"
+ : "=r" (x)
+ : "r" (x));
+
+ return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+ return -clz(pending) + 31 - CAUSEB_IP;
+#else
+ unsigned int a0 = 7;
+ unsigned int t0;
+
+ t0 = s0 & 0xf000;
+ t0 = t0 < 1;
+ t0 = t0 << 2;
+ a0 = a0 - t0;
+ s0 = s0 << t0;
+
+ t0 = s0 & 0xc000;
+ t0 = t0 < 1;
+ t0 = t0 << 1;
+ a0 = a0 - t0;
+ s0 = s0 << t0;
+
+ t0 = s0 & 0x8000;
+ t0 = t0 < 1;
+ //t0 = t0 << 2;
+ a0 = a0 - t0;
+ //s0 = s0 << t0;
+
+ return a0;
+#endif
+}
+
+/*
+ * IRQs on the Atlas board look basically (barring software IRQs which we
+ * don't use at all and all external interrupt sources are combined together
+ * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 Combined hardware interrupt (hw0)
+ * 3 Hardware (ignored)
+ * 4 Hardware (ignored)
+ * 5 Hardware (ignored)
+ * 6 Hardware (ignored)
+ * 7 R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Lowest ---- Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+ int irq;
+
+ irq = irq_ffs(pending);
+
+ if (irq == MIPSCPU_INT_ATLAS)
+ atlas_hw0_irqdispatch(regs);
+ else if (irq > 0)
+ do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+ else
+ spurious_interrupt(regs);
+}
+
void __init arch_init_irq(void)
{
int i;
@@ -128,9 +211,6 @@ void __init arch_init_irq(void)
*/
atlas_hw0_icregs->intrsten = 0xffffffff;
- /* Now safe to set the exception vector. */
- set_except_vector(0, mipsIRQ);
-
for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = 0;
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
index 873cf3141a3..c20d401ecf8 100644
--- a/arch/mips/mips-boards/atlas/atlas_setup.c
+++ b/arch/mips/mips-boards/atlas/atlas_setup.c
@@ -65,7 +65,7 @@ void __init plat_setup(void)
board_time_init = mips_time_init;
board_timer_setup = mips_timer_setup;
- rtc_get_time = mips_rtc_get_time;
+ rtc_mips_get_time = mips_rtc_get_time;
}
static void __init serial_init(void)
diff --git a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile
index b21bc6887fa..be47c1c2bc8 100644
--- a/arch/mips/mips-boards/generic/Makefile
+++ b/arch/mips/mips-boards/generic/Makefile
@@ -18,8 +18,8 @@
# Makefile for the MIPS boards generic routines under Linux.
#
-obj-y := mipsIRQ.o reset.o display.o init.o memory.o \
- printf.o cmdline.o time.o
+obj-y := reset.o display.o init.o memory.o printf.o \
+ cmdline.o time.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_KGDB) += gdb_hook.o
diff --git a/arch/mips/mips-boards/generic/gdb_hook.c b/arch/mips/mips-boards/generic/gdb_hook.c
index 91a2ccbe373..6a1854de457 100644
--- a/arch/mips/mips-boards/generic/gdb_hook.c
+++ b/arch/mips/mips-boards/generic/gdb_hook.c
@@ -25,7 +25,7 @@
#include <asm/serial.h>
#include <asm/io.h>
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
+static struct serial_state rs_table[] = {
SERIAL_PORT_DFNS /* Defined in serial.h */
};
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
index eab5a705e98..df4e9473560 100644
--- a/arch/mips/mips-boards/generic/init.c
+++ b/arch/mips/mips-boards/generic/init.c
@@ -220,7 +220,6 @@ void __init kgdb_config (void)
generic_putDebugChar (*s++);
}
- kgdb_enabled = 1;
/* Breakpoint is invoked after interrupts are initialised */
}
}
@@ -338,6 +337,7 @@ void __init prom_init(void)
case MIPS_REVISION_CORID_CORE_MSC:
case MIPS_REVISION_CORID_CORE_FPGA2:
case MIPS_REVISION_CORID_CORE_FPGA3:
+ case MIPS_REVISION_CORID_CORE_24K:
case MIPS_REVISION_CORID_CORE_EMUL_MSC:
_pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
index ee5e70c95cf..bc4d093685b 100644
--- a/arch/mips/mips-boards/generic/memory.c
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -22,10 +22,12 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
+#include <linux/pfn.h>
#include <linux/string.h>
#include <asm/bootinfo.h>
#include <asm/page.h>
+#include <asm/sections.h>
#include <asm/mips-boards/prom.h>
@@ -46,12 +48,6 @@ static char *mtypes[3] = {
};
#endif
-/* References to section boundaries */
-extern char _end;
-
-#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
-
struct prom_pmemblock * __init prom_getmdesc(void)
{
char *memsize_str;
@@ -109,7 +105,7 @@ struct prom_pmemblock * __init prom_getmdesc(void)
mdesc[3].type = yamon_dontuse;
mdesc[3].base = 0x00100000;
- mdesc[3].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base;
+ mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - mdesc[3].base;
mdesc[4].type = yamon_free;
mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
diff --git a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S
deleted file mode 100644
index ddd5c73a297..00000000000
--- a/arch/mips/mips-boards/generic/mipsIRQ.S
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- * Interrupt exception dispatch code.
- *
- */
-#include <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#ifdef CONFIG_MIPS_ATLAS
-#include <asm/mips-boards/atlasint.h>
-#define CASCADE_IRQ MIPSCPU_INT_ATLAS
-#define CASCADE_DISPATCH atlas_hw0_irqdispatch
-#endif
-#ifdef CONFIG_MIPS_MALTA
-#include <asm/mips-boards/maltaint.h>
-#define CASCADE_IRQ MIPSCPU_INT_I8259A
-#define CASCADE_DISPATCH malta_hw0_irqdispatch
-#endif
-#ifdef CONFIG_MIPS_SEAD
-#include <asm/mips-boards/seadint.h>
-#endif
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- * all the pending IRQ bits in the cause register is _NOT_ the answer, the
- * common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- * would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- * between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the MIPS board look basically (barring software
- * IRQs which we don't use at all and all external interrupt sources are
- * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
- *
- * MIPS IRQ Source
- * -------- ------
- * 0 Software (ignored)
- * 1 Software (ignored)
- * 2 Combined hardware interrupt (hw0)
- * 3 Hardware (ignored)
- * 4 Hardware (ignored)
- * 5 Hardware (ignored)
- * 6 Hardware (ignored)
- * 7 R4k timer (what we use)
- *
- * Note: On the SEAD board thing are a little bit different.
- * Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
- * wired to UART1.
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ---- R4k Timer
- * Lowest ---- Combined hardware interrupt
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
- .text
- .set noreorder
- .set noat
- .align 5
- NESTED(mipsIRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
-
- mfc0 s0, CP0_CAUSE # get irq bits
- mfc0 s1, CP0_STATUS # get irq mask
- andi s0, ST0_IM # CAUSE.CE may be non-zero!
- and s0, s1
-
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
- .set mips32
- clz a0, s0
- .set mips0
- negu a0
- addu a0, 31-CAUSEB_IP
- bltz a0, spurious
-#else
- beqz s0, spurious
- li a0, 7
-
- and t0, s0, 0xf000
- sltiu t0, t0, 1
- sll t0, 2
- subu a0, t0
- sll s0, t0
-
- and t0, s0, 0xc000
- sltiu t0, t0, 1
- sll t0, 1
- subu a0, t0
- sll s0, t0
-
- and t0, s0, 0x8000
- sltiu t0, t0, 1
- # sll t0, 0
- subu a0, t0
- # sll s0, t0
-#endif
-
-#ifdef CASCADE_IRQ
- li a1, CASCADE_IRQ
- bne a0, a1, 1f
- addu a0, MIPSCPU_INT_BASE
-
- jal CASCADE_DISPATCH
- move a0, sp
-
- j ret_from_irq
- nop
-1:
-#else
- addu a0, MIPSCPU_INT_BASE
-#endif
-
- jal do_IRQ
- move a1, sp
-
- j ret_from_irq
- nop
-
-
-spurious:
- j spurious_interrupt
- nop
- END(mipsIRQ)
diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c
index 1f6f9df74ab..9337f6c8873 100644
--- a/arch/mips/mips-boards/generic/pci.c
+++ b/arch/mips/mips-boards/generic/pci.c
@@ -198,6 +198,7 @@ void __init mips_pcibios_init(void)
case MIPS_REVISION_CORID_CORE_MSC:
case MIPS_REVISION_CORID_CORE_FPGA2:
case MIPS_REVISION_CORID_CORE_FPGA3:
+ case MIPS_REVISION_CORID_CORE_24K:
case MIPS_REVISION_CORID_CORE_EMUL_MSC:
/* Set up resource ranges from the controller's registers. */
MSC_READ(MSC01_PCI_SC2PMBASL, start);
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 93f3bf2c2b2..a9f6124b3a2 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -30,6 +30,7 @@
#include <linux/mc146818rtc.h>
#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
#include <asm/ptrace.h>
#include <asm/hardirq.h>
#include <asm/irq.h>
@@ -50,16 +51,23 @@ unsigned long cpu_khz;
static char display_string[] = " LINUX ON ATLAS ";
#endif
#if defined(CONFIG_MIPS_MALTA)
+#if defined(CONFIG_MIPS_MT_SMTC)
+static char display_string[] = " SMTC LINUX ON MALTA ";
+#else
static char display_string[] = " LINUX ON MALTA ";
+#endif /* CONFIG_MIPS_MT_SMTC */
#endif
#if defined(CONFIG_MIPS_SEAD)
static char display_string[] = " LINUX ON SEAD ";
#endif
-static unsigned int display_count = 0;
+static unsigned int display_count;
#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
-static unsigned int timer_tick_count=0;
+#define CPUCTR_IMASKBIT (0x100 << MIPSCPU_INT_CPUCTR)
+
+static unsigned int timer_tick_count;
static int mips_cpu_timer_irq;
+extern void smtc_timer_broadcast(int);
static inline void scroll_display_message(void)
{
@@ -75,15 +83,55 @@ static void mips_timer_dispatch (struct pt_regs *regs)
do_IRQ (mips_cpu_timer_irq, regs);
}
+/*
+ * Redeclare until I get around mopping the timer code insanity on MIPS.
+ */
extern int null_perf_irq(struct pt_regs *regs);
extern int (*perf_irq)(struct pt_regs *regs);
irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- int r2 = cpu_has_mips_r2;
int cpu = smp_processor_id();
+ int r2 = cpu_has_mips_r2;
+
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * In an SMTC system, one Count/Compare set exists per VPE.
+ * Which TC within a VPE gets the interrupt is essentially
+ * random - we only know that it shouldn't be one with
+ * IXMT set. Whichever TC gets the interrupt needs to
+ * send special interprocessor interrupts to the other
+ * TCs to make sure that they schedule, etc.
+ *
+ * That code is specific to the SMTC kernel, not to
+ * the a particular platform, so it's invoked from
+ * the general MIPS timer_interrupt routine.
+ */
+
+ /*
+ * DVPE is necessary so long as cross-VPE interrupts
+ * are done via read-modify-write of Cause register.
+ */
+ int vpflags = dvpe();
+ write_c0_compare (read_c0_count() - 1);
+ clear_c0_cause(CPUCTR_IMASKBIT);
+ evpe(vpflags);
+
+ if (cpu_data[cpu].vpe_id == 0) {
+ timer_interrupt(irq, dev_id, regs);
+ scroll_display_message();
+ } else
+ write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+ smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+ if (cpu != 0)
+ /*
+ * Other CPUs should do profiling and process accounting
+ */
+ local_timer_interrupt(irq, dev_id, regs);
+
+#else /* CONFIG_MIPS_MT_SMTC */
if (cpu == 0) {
/*
* CPU 0 handles the global timer interrupt job and process
@@ -107,12 +155,14 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* More support needs to be added to kernel/time for
* counter/timer interrupts on multiple CPU's
*/
- write_c0_compare (read_c0_count() + (mips_hpt_frequency/HZ));
+ write_c0_compare(read_c0_count() + (mips_hpt_frequency/HZ));
+
/*
- * other CPUs should do profiling and process accounting
+ * Other CPUs should do profiling and process accounting
*/
- local_timer_interrupt (irq, dev_id, regs);
+ local_timer_interrupt(irq, dev_id, regs);
}
+#endif /* CONFIG_MIPS_MT_SMTC */
out:
return IRQ_HANDLED;
@@ -126,7 +176,7 @@ static unsigned int __init estimate_cpu_frequency(void)
unsigned int prid = read_c0_prid() & 0xffff00;
unsigned int count;
-#ifdef CONFIG_MIPS_SEAD
+#if defined(CONFIG_MIPS_SEAD) || defined(CONFIG_MIPS_SIM)
/*
* The SEAD board doesn't have a real time clock, so we can't
* really calculate the timer frequency
@@ -211,7 +261,11 @@ void __init mips_timer_setup(struct irqaction *irq)
/* we are using the cpu counter for timer interrupts */
irq->handler = mips_timer_interrupt; /* we use our own handler */
+#ifdef CONFIG_MIPS_MT_SMTC
+ setup_irq_smtc(mips_cpu_timer_irq, irq, CPUCTR_IMASKBIT);
+#else
setup_irq(mips_cpu_timer_irq, irq);
+#endif /* CONFIG_MIPS_MT_SMTC */
#ifdef CONFIG_SMP
/* irq_desc(riptor) is a global resource, when the interrupt overlaps
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
index fd4c143c0e2..77ee5c6d33c 100644
--- a/arch/mips/mips-boards/malta/Makefile
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -20,3 +20,4 @@
#
obj-y := malta_int.o malta_setup.o
+obj-$(CONFIG_SMP) += malta_smp.o
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index d06dc5ad6c9..7cc0ba4f553 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -40,7 +40,6 @@
#include <asm/mips-boards/msc01_pci.h>
#include <asm/msc01_ic.h>
-extern asmlinkage void mipsIRQ(void);
extern void mips_timer_interrupt(void);
static DEFINE_SPINLOCK(mips_irq_lock);
@@ -58,6 +57,7 @@ static inline int mips_pcibios_iack(void)
case MIPS_REVISION_CORID_CORE_MSC:
case MIPS_REVISION_CORID_CORE_FPGA2:
case MIPS_REVISION_CORID_CORE_FPGA3:
+ case MIPS_REVISION_CORID_CORE_24K:
case MIPS_REVISION_CORID_CORE_EMUL_MSC:
MSC_READ(MSC01_PCI_IACK, irq);
irq &= 0xff;
@@ -114,13 +114,14 @@ static inline int get_int(void)
return irq;
}
-void malta_hw0_irqdispatch(struct pt_regs *regs)
+static void malta_hw0_irqdispatch(struct pt_regs *regs)
{
int irq;
irq = get_int();
- if (irq < 0)
+ if (irq < 0) {
return; /* interrupt has already been cleared */
+ }
do_IRQ(MALTA_INT_BASE+irq, regs);
}
@@ -143,6 +144,7 @@ void corehi_irqdispatch(struct pt_regs *regs)
case MIPS_REVISION_CORID_CORE_MSC:
case MIPS_REVISION_CORID_CORE_FPGA2:
case MIPS_REVISION_CORID_CORE_FPGA3:
+ case MIPS_REVISION_CORID_CORE_24K:
case MIPS_REVISION_CORID_CORE_EMUL_MSC:
ll_msc_irq(regs);
break;
@@ -182,6 +184,92 @@ void corehi_irqdispatch(struct pt_regs *regs)
die("CoreHi interrupt", regs);
}
+static inline int clz(unsigned long x)
+{
+ __asm__ (
+ " .set push \n"
+ " .set mips32 \n"
+ " clz %0, %1 \n"
+ " .set pop \n"
+ : "=r" (x)
+ : "r" (x));
+
+ return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+ return -clz(pending) + 31 - CAUSEB_IP;
+#else
+ unsigned int a0 = 7;
+ unsigned int t0;
+
+ t0 = s0 & 0xf000;
+ t0 = t0 < 1;
+ t0 = t0 << 2;
+ a0 = a0 - t0;
+ s0 = s0 << t0;
+
+ t0 = s0 & 0xc000;
+ t0 = t0 < 1;
+ t0 = t0 << 1;
+ a0 = a0 - t0;
+ s0 = s0 << t0;
+
+ t0 = s0 & 0x8000;
+ t0 = t0 < 1;
+ //t0 = t0 << 2;
+ a0 = a0 - t0;
+ //s0 = s0 << t0;
+
+ return a0;
+#endif
+}
+
+/*
+ * IRQs on the Malta board look basically (barring software IRQs which we
+ * don't use at all and all external interrupt sources are combined together
+ * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 Combined hardware interrupt (hw0)
+ * 3 Hardware (ignored)
+ * 4 Hardware (ignored)
+ * 5 Hardware (ignored)
+ * 6 Hardware (ignored)
+ * 7 R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Lowest ---- Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+ int irq;
+
+ irq = irq_ffs(pending);
+
+ if (irq == MIPSCPU_INT_I8259A)
+ malta_hw0_irqdispatch(regs);
+ else if (irq > 0)
+ do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+ else
+ spurious_interrupt(regs);
+}
+
static struct irqaction i8259irq = {
.handler = no_action,
.name = "XT-PIC cascade"
@@ -214,7 +302,6 @@ int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap)/sizeof(msc_irqmap_t);
void __init arch_init_irq(void)
{
- set_except_vector(0, mipsIRQ);
init_i8259_irqs();
if (!cpu_has_veic)
@@ -224,6 +311,7 @@ void __init arch_init_irq(void)
case MIPS_REVISION_CORID_CORE_MSC:
case MIPS_REVISION_CORID_CORE_FPGA2:
case MIPS_REVISION_CORID_CORE_FPGA3:
+ case MIPS_REVISION_CORID_CORE_24K:
case MIPS_REVISION_CORID_CORE_EMUL_MSC:
if (cpu_has_veic)
init_msc_irqs (MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs);
@@ -240,12 +328,17 @@ void __init arch_init_irq(void)
else if (cpu_has_vint) {
set_vi_handler (MIPSCPU_INT_I8259A, malta_hw0_irqdispatch);
set_vi_handler (MIPSCPU_INT_COREHI, corehi_irqdispatch);
-
+#ifdef CONFIG_MIPS_MT_SMTC
+ setup_irq_smtc (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq,
+ (0x100 << MIPSCPU_INT_I8259A));
+ setup_irq_smtc (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI,
+ &corehi_irqaction, (0x100 << MIPSCPU_INT_COREHI));
+#else /* Not SMTC */
setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
+#endif /* CONFIG_MIPS_MT_SMTC */
}
else {
- set_except_vector(0, mipsIRQ);
setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
}
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
index 2209e8a9de3..b8488aab6df 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -225,5 +225,5 @@ void __init plat_setup(void)
board_time_init = mips_time_init;
board_timer_setup = mips_timer_setup;
- rtc_get_time = mips_rtc_get_time;
+ rtc_mips_get_time = mips_rtc_get_time;
}
diff --git a/arch/mips/mips-boards/malta/malta_smp.c b/arch/mips/mips-boards/malta/malta_smp.c
new file mode 100644
index 00000000000..6c6c8eeedbc
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_smp.c
@@ -0,0 +1,128 @@
+/*
+ * Malta Platform-specific hooks for SMP operation
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/atomic.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/smtc_ipi.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
+/* VPE/SMP Prototype implements platform interfaces directly */
+#if !defined(CONFIG_MIPS_MT_SMP)
+
+/*
+ * Cause the specified action to be performed on a targeted "CPU"
+ */
+
+void core_send_ipi(int cpu, unsigned int action)
+{
+/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
+#ifdef CONFIG_MIPS_MT_SMTC
+ smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map
+ */
+
+void __init prom_build_cpu_map(void)
+{
+ int nextslot;
+
+ /*
+ * As of November, 2004, MIPSsim only simulates one core
+ * at a time. However, that core may be a MIPS MT core
+ * with multiple virtual processors and thread contexts.
+ */
+
+ if (read_c0_config3() & (1<<2)) {
+ nextslot = mipsmt_build_cpu_map(1);
+ }
+}
+
+/*
+ * Platform "CPU" startup hook
+ */
+
+void prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ smtc_boot_secondary(cpu, idle);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Post-config but pre-boot cleanup entry point
+ */
+
+void prom_init_secondary(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ void smtc_init_secondary(void);
+ int myvpe;
+
+ /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */
+ myvpe = read_c0_tcbind() & TCBIND_CURVPE;
+ if (myvpe != 0) {
+ /* Ideally, this should be done only once per VPE, but... */
+ clear_c0_status(STATUSF_IP2);
+ set_c0_status(STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP3
+ | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6
+ | STATUSF_IP7);
+ }
+
+ smtc_init_secondary();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Platform SMP pre-initialization
+ *
+ * As noted above, we can assume a single CPU for now
+ * but it may be multithreaded.
+ */
+
+void plat_smp_setup(void)
+{
+ if (read_c0_config3() & (1<<2))
+ mipsmt_build_cpu_map(0);
+}
+
+void __init plat_prepare_cpus(unsigned int max_cpus)
+{
+ if (read_c0_config3() & (1<<2))
+ mipsmt_prepare_cpus();
+}
+
+/*
+ * SMP initialization finalization entry point
+ */
+
+void prom_smp_finish(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ smtc_smp_finish();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Hook for after all CPUs are online
+ */
+
+void prom_cpus_done(void)
+{
+}
+
+#endif /* CONFIG_MIPS32R2_MT_SMP */
diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c
index 90fda0d9915..9168d934c66 100644
--- a/arch/mips/mips-boards/sead/sead_int.c
+++ b/arch/mips/mips-boards/sead/sead_int.c
@@ -24,16 +24,94 @@
#include <linux/irq.h>
#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
#include <asm/system.h>
#include <asm/mips-boards/seadint.h>
-extern asmlinkage void mipsIRQ(void);
+static inline int clz(unsigned long x)
+{
+ __asm__ (
+ " .set push \n"
+ " .set mips32 \n"
+ " clz %0, %1 \n"
+ " .set pop \n"
+ : "=r" (x)
+ : "r" (x));
+
+ return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+ return -clz(pending) + 31 - CAUSEB_IP;
+#else
+ unsigned int a0 = 7;
+ unsigned int t0;
+
+ t0 = s0 & 0xf000;
+ t0 = t0 < 1;
+ t0 = t0 << 2;
+ a0 = a0 - t0;
+ s0 = s0 << t0;
+
+ t0 = s0 & 0xc000;
+ t0 = t0 < 1;
+ t0 = t0 << 1;
+ a0 = a0 - t0;
+ s0 = s0 << t0;
+
+ t0 = s0 & 0x8000;
+ t0 = t0 < 1;
+ //t0 = t0 << 2;
+ a0 = a0 - t0;
+ //s0 = s0 << t0;
+
+ return a0;
+#endif
+}
+
+/*
+ * IRQs on the SEAD board look basically are combined together on hardware
+ * interrupt 0 (MIPS IRQ 2)) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 UART0 (hw0)
+ * 3 UART1 (hw1)
+ * 4 Hardware (ignored)
+ * 5 Hardware (ignored)
+ * 6 Hardware (ignored)
+ * 7 R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Lowest ---- Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+ int irq;
+
+ irq = irq_ffs(pending);
+
+ if (irq >= 0)
+ do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+ else
+ spurious_interrupt(regs);
+}
void __init arch_init_irq(void)
{
mips_cpu_irq_init(MIPSCPU_INT_BASE);
-
- /* Now safe to set the exception vector. */
- set_except_vector(0, mipsIRQ);
}
diff --git a/arch/mips/mips-boards/sim/cmdline.c b/arch/mips/mips-boards/sim/cmdline.c
deleted file mode 100644
index fef9fbd8e71..00000000000
--- a/arch/mips/mips-boards/sim/cmdline.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Kernel command line creation using the prom monitor (YAMON) argc/argv.
- */
-#include <linux/init.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-
-extern int prom_argc;
-extern int *_prom_argv;
-
-/*
- * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
- * This macro take care of sign extension.
- */
-#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)]))
-
-char arcs_cmdline[CL_SIZE];
-
-char * __init prom_getcmdline(void)
-{
- return &(arcs_cmdline[0]);
-}
-
-
-void __init prom_init_cmdline(void)
-{
- char *cp;
- int actr;
-
- actr = 1; /* Always ignore argv[0] */
-
- cp = &(arcs_cmdline[0]);
- while(actr < prom_argc) {
- strcpy(cp, prom_argv(actr));
- cp += strlen(prom_argv(actr));
- *cp++ = ' ';
- actr++;
- }
- if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
- --cp;
- *cp = '\0';
-}
diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mips-boards/sim/sim_cmdline.c
index 9df37c6fca3..c63021a5dc6 100644
--- a/arch/mips/mips-boards/sim/sim_cmdline.c
+++ b/arch/mips/mips-boards/sim/sim_cmdline.c
@@ -26,8 +26,10 @@ char * __init prom_getcmdline(void)
return arcs_cmdline;
}
-
void __init prom_init_cmdline(void)
{
- /* nothing to do */
+ char *cp;
+ cp = arcs_cmdline;
+ /* Get boot line from environment? */
+ *cp = '\0';
}
diff --git a/arch/mips/mips-boards/sim/sim_int.c b/arch/mips/mips-boards/sim/sim_int.c
index a4d0a2c0503..2c15c8efec4 100644
--- a/arch/mips/mips-boards/sim/sim_int.c
+++ b/arch/mips/mips-boards/sim/sim_int.c
@@ -25,17 +25,71 @@
extern void mips_cpu_irq_init(int);
-extern asmlinkage void simIRQ(void);
+static inline int clz(unsigned long x)
+{
+ __asm__ (
+ " .set push \n"
+ " .set mips32 \n"
+ " clz %0, %1 \n"
+ " .set pop \n"
+ : "=r" (x)
+ : "r" (x));
+
+ return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+ return -clz(pending) + 31 - CAUSEB_IP;
+#else
+ unsigned int a0 = 7;
+ unsigned int t0;
+
+ t0 = s0 & 0xf000;
+ t0 = t0 < 1;
+ t0 = t0 << 2;
+ a0 = a0 - t0;
+ s0 = s0 << t0;
+
+ t0 = s0 & 0xc000;
+ t0 = t0 < 1;
+ t0 = t0 << 1;
+ a0 = a0 - t0;
+ s0 = s0 << t0;
-asmlinkage void sim_hw0_irqdispatch(struct pt_regs *regs)
+ t0 = s0 & 0x8000;
+ t0 = t0 < 1;
+ //t0 = t0 << 2;
+ a0 = a0 - t0;
+ //s0 = s0 << t0;
+
+ return a0;
+#endif
+}
+
+static inline void sim_hw0_irqdispatch(struct pt_regs *regs)
{
do_IRQ(2, regs);
}
-void __init arch_init_irq(void)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
- /* Now safe to set the exception vector. */
- set_except_vector(0, simIRQ);
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+ int irq;
+
+ irq = irq_ffs(pending);
+ if (irq > 0)
+ do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+ else
+ spurious_interrupt(regs);
+}
+
+void __init arch_init_irq(void)
+{
mips_cpu_irq_init(MIPSCPU_INT_BASE);
}
diff --git a/arch/mips/mips-boards/sim/sim_irq.S b/arch/mips/mips-boards/sim/sim_irq.S
index da52297a221..d16cf382207 100644
--- a/arch/mips/mips-boards/sim/sim_irq.S
+++ b/arch/mips/mips-boards/sim/sim_irq.S
@@ -94,6 +94,8 @@
spurious:
- j spurious_interrupt
+ jal spurious_interrupt
+ nop
+ j ret_from_irq
nop
END(simIRQ)
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c
index 1ec4e75656b..f7ce7698332 100644
--- a/arch/mips/mips-boards/sim/sim_mem.c
+++ b/arch/mips/mips-boards/sim/sim_mem.c
@@ -18,9 +18,11 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
+#include <linux/pfn.h>
#include <asm/bootinfo.h>
#include <asm/page.h>
+#include <asm/sections.h>
#include <asm/mips-boards/prom.h>
@@ -39,12 +41,6 @@ static char *mtypes[3] = {
};
#endif
-/* References to section boundaries */
-extern char _end;
-
-#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
-
struct prom_pmemblock * __init prom_getmdesc(void)
{
unsigned int memsize;
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mips-boards/sim/sim_smp.c
index a9f0c2bfe4a..b7084e7c4bf 100644
--- a/arch/mips/mips-boards/sim/sim_smp.c
+++ b/arch/mips/mips-boards/sim/sim_smp.c
@@ -44,8 +44,6 @@
void core_send_ipi(int cpu, unsigned int action)
{
#ifdef CONFIG_MIPS_MT_SMTC
- void smtc_send_ipi(int, int, unsigned int);
-
smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
#endif /* CONFIG_MIPS_MT_SMTC */
/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
@@ -59,15 +57,8 @@ void core_send_ipi(int cpu, unsigned int action)
void __init prom_build_cpu_map(void)
{
#ifdef CONFIG_MIPS_MT_SMTC
- extern int mipsmt_build_cpu_map(int startslot);
int nextslot;
- cpus_clear(phys_cpu_present_map);
-
- /* Register the boot CPU */
-
- smp_prepare_boot_cpu();
-
/*
* As of November, 2004, MIPSsim only simulates one core
* at a time. However, that core may be a MIPS MT core
@@ -87,8 +78,6 @@ void __init prom_build_cpu_map(void)
void prom_boot_secondary(int cpu, struct task_struct *idle)
{
#ifdef CONFIG_MIPS_MT_SMTC
- extern void smtc_boot_secondary(int cpu, struct task_struct *t);
-
smtc_boot_secondary(cpu, idle);
#endif /* CONFIG_MIPS_MT_SMTC */
}
@@ -113,7 +102,6 @@ void prom_init_secondary(void)
void prom_prepare_cpus(unsigned int max_cpus)
{
#ifdef CONFIG_MIPS_MT_SMTC
- void mipsmt_prepare_cpus(int c);
/*
* As noted above, we can assume a single CPU for now
* but it may be multithreaded.
@@ -132,8 +120,6 @@ void prom_prepare_cpus(unsigned int max_cpus)
void prom_smp_finish(void)
{
#ifdef CONFIG_MIPS_MT_SMTC
- void smtc_smp_finish(void);
-
smtc_smp_finish();
#endif /* CONFIG_MIPS_MT_SMTC */
}
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index 9dd1352d574..bb041a22f20 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -260,6 +260,10 @@ static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page,
{
}
+static void local_r3k_flush_data_cache_page(unsigned long addr)
+{
+}
+
static void r3k_flush_data_cache_page(unsigned long addr)
{
}
@@ -335,6 +339,7 @@ void __init r3k_cache_init(void)
flush_icache_range = r3k_flush_icache_range;
flush_cache_sigtramp = r3k_flush_cache_sigtramp;
+ local_flush_data_cache_page = local_r3k_flush_data_cache_page;
flush_data_cache_page = r3k_flush_data_cache_page;
_dma_cache_wback_inv = r3k_dma_cache_wback_inv;
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 32b7f6aeb98..4a43924cd4f 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -29,6 +29,27 @@
#include <asm/war.h>
#include <asm/cacheflush.h> /* for run_uncached() */
+
+/*
+ * Special Variant of smp_call_function for use by cache functions:
+ *
+ * o No return value
+ * o collapses to normal function call on UP kernels
+ * o collapses to normal function call on systems with a single shared
+ * primary cache.
+ */
+static inline void r4k_on_each_cpu(void (*func) (void *info), void *info,
+ int retry, int wait)
+{
+ preempt_disable();
+
+#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
+ smp_call_function(func, info, retry, wait);
+#endif
+ func(info);
+ preempt_enable();
+}
+
/*
* Must die.
*/
@@ -154,7 +175,8 @@ static inline void blast_icache32_r4600_v1_page_indexed(unsigned long page)
static inline void tx49_blast_icache32_page_indexed(unsigned long page)
{
- unsigned long start = page;
+ unsigned long indexmask = current_cpu_data.icache.waysize - 1;
+ unsigned long start = INDEX_BASE + (page & indexmask);
unsigned long end = start + PAGE_SIZE;
unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
unsigned long ws_end = current_cpu_data.icache.ways <<
@@ -298,7 +320,7 @@ static void r4k_flush_cache_all(void)
if (!cpu_has_dc_aliases)
return;
- on_each_cpu(local_r4k_flush_cache_all, NULL, 1, 1);
+ r4k_on_each_cpu(local_r4k_flush_cache_all, NULL, 1, 1);
}
static inline void local_r4k___flush_cache_all(void * args)
@@ -313,13 +335,14 @@ static inline void local_r4k___flush_cache_all(void * args)
case CPU_R4400MC:
case CPU_R10000:
case CPU_R12000:
+ case CPU_R14000:
r4k_blast_scache();
}
}
static void r4k___flush_cache_all(void)
{
- on_each_cpu(local_r4k___flush_cache_all, NULL, 1, 1);
+ r4k_on_each_cpu(local_r4k___flush_cache_all, NULL, 1, 1);
}
static inline void local_r4k_flush_cache_range(void * args)
@@ -340,7 +363,7 @@ static inline void local_r4k_flush_cache_range(void * args)
static void r4k_flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
- on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1);
+ r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1);
}
static inline void local_r4k_flush_cache_mm(void * args)
@@ -369,7 +392,7 @@ static void r4k_flush_cache_mm(struct mm_struct *mm)
if (!cpu_has_dc_aliases)
return;
- on_each_cpu(local_r4k_flush_cache_mm, mm, 1, 1);
+ r4k_on_each_cpu(local_r4k_flush_cache_mm, mm, 1, 1);
}
struct flush_cache_page_args {
@@ -460,7 +483,7 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma,
args.addr = addr;
args.pfn = pfn;
- on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
+ r4k_on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
}
static inline void local_r4k_flush_data_cache_page(void * addr)
@@ -470,7 +493,7 @@ static inline void local_r4k_flush_data_cache_page(void * addr)
static void r4k_flush_data_cache_page(unsigned long addr)
{
- on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, 1, 1);
+ r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, 1, 1);
}
struct flush_icache_range_args {
@@ -513,7 +536,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
args.start = start;
args.end = end;
- on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1);
+ r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1);
instruction_hazard();
}
@@ -589,7 +612,7 @@ static void r4k_flush_icache_page(struct vm_area_struct *vma,
args.vma = vma;
args.page = page;
- on_each_cpu(local_r4k_flush_icache_page, &args, 1, 1);
+ r4k_on_each_cpu(local_r4k_flush_icache_page, &args, 1, 1);
}
@@ -688,7 +711,7 @@ static void local_r4k_flush_cache_sigtramp(void * arg)
static void r4k_flush_cache_sigtramp(unsigned long addr)
{
- on_each_cpu(local_r4k_flush_cache_sigtramp, (void *) addr, 1, 1);
+ r4k_on_each_cpu(local_r4k_flush_cache_sigtramp, (void *) addr, 1, 1);
}
static void r4k_flush_icache_all(void)
@@ -749,12 +772,12 @@ static void __init probe_pcache(void)
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
c->icache.ways = 2;
- c->icache.waybit = ffs(icache_size/2) - 1;
+ c->icache.waybit = __ffs(icache_size/2);
dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 2;
- c->dcache.waybit= ffs(dcache_size/2) - 1;
+ c->dcache.waybit= __ffs(dcache_size/2);
c->options |= MIPS_CPU_CACHE_CDEX_P;
break;
@@ -811,6 +834,7 @@ static void __init probe_pcache(void)
case CPU_R10000:
case CPU_R12000:
+ case CPU_R14000:
icache_size = 1 << (12 + ((config & R10K_CONF_IC) >> 29));
c->icache.linesz = 64;
c->icache.ways = 2;
@@ -837,12 +861,12 @@ static void __init probe_pcache(void)
icache_size = 1 << (10 + ((config & CONF_IC) >> 9));
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
c->icache.ways = 2;
- c->icache.waybit = ffs(icache_size/2) - 1;
+ c->icache.waybit = __ffs(icache_size/2);
dcache_size = 1 << (10 + ((config & CONF_DC) >> 6));
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 2;
- c->dcache.waybit = ffs(dcache_size/2) - 1;
+ c->dcache.waybit = __ffs(dcache_size/2);
c->options |= MIPS_CPU_CACHE_CDEX_P;
break;
@@ -873,12 +897,12 @@ static void __init probe_pcache(void)
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
c->icache.ways = 4;
- c->icache.waybit = ffs(icache_size / c->icache.ways) - 1;
+ c->icache.waybit = __ffs(icache_size / c->icache.ways);
dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
c->dcache.ways = 4;
- c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1;
+ c->dcache.waybit = __ffs(dcache_size / c->dcache.ways);
#if !defined(CONFIG_SMP) || !defined(RM9000_CDEX_SMP_WAR)
c->options |= MIPS_CPU_CACHE_CDEX_P;
@@ -906,7 +930,7 @@ static void __init probe_pcache(void)
icache_size = c->icache.sets *
c->icache.ways *
c->icache.linesz;
- c->icache.waybit = ffs(icache_size/c->icache.ways) - 1;
+ c->icache.waybit = __ffs(icache_size/c->icache.ways);
if (config & 0x8) /* VI bit */
c->icache.flags |= MIPS_CACHE_VTAG;
@@ -926,7 +950,7 @@ static void __init probe_pcache(void)
dcache_size = c->dcache.sets *
c->dcache.ways *
c->dcache.linesz;
- c->dcache.waybit = ffs(dcache_size/c->dcache.ways) - 1;
+ c->dcache.waybit = __ffs(dcache_size/c->dcache.ways);
c->options |= MIPS_CPU_PREFETCH;
break;
@@ -964,9 +988,11 @@ static void __init probe_pcache(void)
c->dcache.flags |= MIPS_CACHE_PINDEX;
case CPU_R10000:
case CPU_R12000:
+ case CPU_R14000:
case CPU_SB1:
break;
case CPU_24K:
+ case CPU_34K:
if (!(read_c0_config7() & (1 << 16)))
default:
if (c->dcache.waysize > PAGE_SIZE)
@@ -1090,6 +1116,7 @@ static void __init setup_scache(void)
case CPU_R10000:
case CPU_R12000:
+ case CPU_R14000:
scache_size = 0x80000 << ((config & R10K_CONF_SS) >> 16);
c->scache.linesz = 64 << ((config >> 13) & 1);
c->scache.ways = 2;
@@ -1134,6 +1161,31 @@ static void __init setup_scache(void)
c->options |= MIPS_CPU_SUBSET_CACHES;
}
+void au1x00_fixup_config_od(void)
+{
+ /*
+ * c0_config.od (bit 19) was write only (and read as 0)
+ * on the early revisions of Alchemy SOCs. It disables the bus
+ * transaction overlapping and needs to be set to fix various errata.
+ */
+ switch (read_c0_prid()) {
+ case 0x00030100: /* Au1000 DA */
+ case 0x00030201: /* Au1000 HA */
+ case 0x00030202: /* Au1000 HB */
+ case 0x01030200: /* Au1500 AB */
+ /*
+ * Au1100 errata actually keeps silence about this bit, so we set it
+ * just in case for those revisions that require it to be set according
+ * to arch/mips/au1000/common/cputable.c
+ */
+ case 0x02030200: /* Au1100 AB */
+ case 0x02030201: /* Au1100 BA */
+ case 0x02030202: /* Au1100 BC */
+ set_c0_config(1 << 19);
+ break;
+ }
+}
+
static inline void coherency_setup(void)
{
change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
@@ -1154,6 +1206,15 @@ static inline void coherency_setup(void)
case CPU_R4400MC:
clear_c0_config(CONF_CU);
break;
+ /*
+ * We need to catch the ealry Alchemy SOCs with
+ * the write-only co_config.od bit and set it back to one...
+ */
+ case CPU_AU1000: /* rev. DA, HA, HB */
+ case CPU_AU1100: /* rev. AB, BA, BC ?? */
+ case CPU_AU1500: /* rev. AB */
+ au1x00_fixup_config_od();
+ break;
}
}
@@ -1198,6 +1259,7 @@ void __init r4k_cache_init(void)
flush_cache_sigtramp = r4k_flush_cache_sigtramp;
flush_icache_all = r4k_flush_icache_all;
+ local_flush_data_cache_page = local_r4k_flush_data_cache_page;
flush_data_cache_page = r4k_flush_data_cache_page;
flush_icache_range = r4k_flush_icache_range;
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 2f08b535f20..f9b129491b1 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -528,6 +528,7 @@ void sb1_cache_init(void)
flush_cache_page = sb1_flush_cache_page;
flush_cache_sigtramp = sb1_flush_cache_sigtramp;
+ local_flush_data_cache_page = (void *) sb1_nop;
flush_data_cache_page = (void *) sb1_nop;
/* Full flush */
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
index fe232e3988e..5dfc9b1901f 100644
--- a/arch/mips/mm/c-tx39.c
+++ b/arch/mips/mm/c-tx39.c
@@ -216,6 +216,11 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page
tx39_blast_icache_page_indexed(page);
}
+static void local_tx39_flush_data_cache_page(void * addr)
+{
+ tx39_blast_dcache_page(addr);
+}
+
static void tx39_flush_data_cache_page(unsigned long addr)
{
tx39_blast_dcache_page(addr);
@@ -381,6 +386,7 @@ void __init tx39_cache_init(void)
flush_icache_range = (void *) tx39h_flush_icache_all;
flush_cache_sigtramp = (void *) tx39h_flush_icache_all;
+ local_flush_data_cache_page = (void *) tx39h_flush_icache_all;
flush_data_cache_page = (void *) tx39h_flush_icache_all;
_dma_cache_wback_inv = tx39h_dma_cache_wback_inv;
@@ -406,6 +412,7 @@ void __init tx39_cache_init(void)
flush_icache_range = tx39_flush_icache_range;
flush_cache_sigtramp = tx39_flush_cache_sigtramp;
+ local_flush_data_cache_page = local_tx39_flush_data_cache_page;
flush_data_cache_page = tx39_flush_data_cache_page;
_dma_cache_wback_inv = tx39_dma_cache_wback_inv;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 591c22b080e..83a56296be8 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -30,6 +30,7 @@ void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
/* MIPS specific cache operations */
void (*flush_cache_sigtramp)(unsigned long addr);
+void (*local_flush_data_cache_page)(void * addr);
void (*flush_data_cache_page)(unsigned long addr);
void (*flush_icache_all)(void);
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 2d9624fd10e..e3a61722486 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -157,7 +157,6 @@ no_context:
* Oops. The kernel tried to access some bad page. We'll have to
* terminate things with extreme prejudice.
*/
-
bust_spinlocks(1);
printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at "
@@ -188,11 +187,20 @@ do_sigbus:
/* Kernel mode? Handle exceptions or die */
if (!user_mode(regs))
goto no_context;
-
+ else
/*
* Send a sigbus, regardless of whether we were in kernel
* or user mode.
*/
+#if 0
+ printk("do_page_fault() #3: sending SIGBUS to %s for "
+ "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
+ tsk->comm,
+ write ? "write access to" : "read access from",
+ field, address,
+ field, (unsigned long) regs->cp0_epc,
+ field, (unsigned long) regs->regs[31]);
+#endif
tsk->thread.cp0_badvaddr = address;
info.si_signo = SIGBUS;
info.si_errno = 0;
@@ -201,7 +209,6 @@ do_sigbus:
force_sig_info(SIGBUS, &info, tsk);
return;
-
vmalloc_fault:
{
/*
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
index 1f7b37b38f5..0c544375b85 100644
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -83,6 +83,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type)
preempt_check_resched();
}
+#ifndef CONFIG_LIMITED_DMA
/*
* This is the same as kmap_atomic() but can map memory that doesn't
* have a struct page associated with it.
@@ -101,6 +102,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
return (void*) vaddr;
}
+#endif /* CONFIG_LIMITED_DMA */
struct page *__kmap_atomic_to_page(void *ptr)
{
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 52f7d59fe61..33f6e1cdfd5 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -25,6 +25,7 @@
#include <linux/highmem.h>
#include <linux/swap.h>
#include <linux/proc_fs.h>
+#include <linux/pfn.h>
#include <asm/bootinfo.h>
#include <asm/cachectl.h>
@@ -177,9 +178,6 @@ void __init paging_init(void)
free_area_init(zones_size);
}
-#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-
static inline int page_is_ram(unsigned long pagenr)
{
int i;
@@ -229,7 +227,7 @@ void __init mem_init(void)
for (tmp = 0; tmp < max_low_pfn; tmp++)
if (page_is_ram(tmp)) {
ram++;
- if (PageReserved(mem_map+tmp))
+ if (PageReserved(pfn_to_page(tmp)))
reservedpages++;
}
@@ -278,6 +276,20 @@ void __init mem_init(void)
}
#endif /* !CONFIG_NEED_MULTIPLE_NODES */
+void free_init_pages(char *what, unsigned long begin, unsigned long end)
+{
+ unsigned long addr;
+
+ for (addr = begin; addr < end; addr += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ init_page_count(virt_to_page(addr));
+ memset((void *)addr, 0xcc, PAGE_SIZE);
+ free_page(addr);
+ totalram_pages++;
+ }
+ printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
+}
+
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
@@ -286,16 +298,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
start = (unsigned long)phys_to_virt(CPHYSADDR(start));
end = (unsigned long)phys_to_virt(CPHYSADDR(end));
#endif
- if (start < end)
- printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
- (end - start) >> 10);
-
- for (; start < end; start += PAGE_SIZE) {
- ClearPageReserved(virt_to_page(start));
- init_page_count(virt_to_page(start));
- free_page(start);
- totalram_pages++;
- }
+ free_init_pages("initrd memory", start, end);
}
#endif
@@ -303,24 +306,17 @@ extern unsigned long prom_free_prom_memory(void);
void free_initmem(void)
{
- unsigned long addr, page, freed;
+ unsigned long start, end, freed;
freed = prom_free_prom_memory();
+ if (freed)
+ printk(KERN_INFO "Freeing firmware memory: %ldk freed\n",freed);
- addr = (unsigned long) &__init_begin;
- while (addr < (unsigned long) &__init_end) {
+ start = (unsigned long)(&__init_begin);
+ end = (unsigned long)(&__init_end);
#ifdef CONFIG_64BIT
- page = PAGE_OFFSET | CPHYSADDR(addr);
-#else
- page = addr;
+ start = PAGE_OFFSET | CPHYSADDR(start);
+ end = PAGE_OFFSET | CPHYSADDR(end);
#endif
- ClearPageReserved(virt_to_page(page));
- init_page_count(virt_to_page(page));
- free_page(page);
- totalram_pages++;
- freed += PAGE_SIZE;
- addr += PAGE_SIZE;
- }
- printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n",
- freed >> 10);
+ free_init_pages("unused kernel memory", start, end);
}
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c
index e4390dc3eb4..b7c749232ff 100644
--- a/arch/mips/mm/pg-r4k.c
+++ b/arch/mips/mm/pg-r4k.c
@@ -357,6 +357,7 @@ void __init build_clear_page(void)
case CPU_R10000:
case CPU_R12000:
+ case CPU_R14000:
pref_src_mode = Pref_LoadStreamed;
pref_dst_mode = Pref_StoreStreamed;
break;
diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c
index 3b6cc9ba1b0..31ec7305242 100644
--- a/arch/mips/mm/sc-rm7k.c
+++ b/arch/mips/mm/sc-rm7k.c
@@ -138,7 +138,7 @@ void __init rm7k_sc_init(void)
c->scache.linesz = sc_lsize;
c->scache.ways = 4;
- c->scache.waybit= ffs(scache_size / c->scache.ways) - 1;
+ c->scache.waybit= __ffs(scache_size / c->scache.ways);
c->scache.waysize = scache_size / c->scache.ways;
c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n",
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index a865f2394cb..9dca099ba16 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -32,13 +32,35 @@ extern void build_tlb_refill_handler(void);
"nop; nop; nop; nop; nop; nop;\n\t" \
".set reorder\n\t")
+/* Atomicity and interruptability */
+#ifdef CONFIG_MIPS_MT_SMTC
+
+#include <asm/smtc.h>
+#include <asm/mipsmtregs.h>
+
+#define ENTER_CRITICAL(flags) \
+ { \
+ unsigned int mvpflags; \
+ local_irq_save(flags);\
+ mvpflags = dvpe()
+#define EXIT_CRITICAL(flags) \
+ evpe(mvpflags); \
+ local_irq_restore(flags); \
+ }
+#else
+
+#define ENTER_CRITICAL(flags) local_irq_save(flags)
+#define EXIT_CRITICAL(flags) local_irq_restore(flags)
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+
void local_flush_tlb_all(void)
{
unsigned long flags;
unsigned long old_ctx;
int entry;
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
/* Save old context and create impossible VPN2 value */
old_ctx = read_c0_entryhi();
write_c0_entrylo0(0);
@@ -57,7 +79,7 @@ void local_flush_tlb_all(void)
}
tlbw_use_hazard();
write_c0_entryhi(old_ctx);
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
/* All entries common to a mm share an asid. To effectively flush
@@ -87,6 +109,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long flags;
int size;
+ ENTER_CRITICAL(flags);
size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
size = (size + 1) >> 1;
local_irq_save(flags);
@@ -120,7 +143,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
} else {
drop_mmu_context(mm, cpu);
}
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
}
@@ -129,9 +152,9 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
unsigned long flags;
int size;
+ ENTER_CRITICAL(flags);
size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
size = (size + 1) >> 1;
- local_irq_save(flags);
if (size <= current_cpu_data.tlbsize / 2) {
int pid = read_c0_entryhi();
@@ -162,7 +185,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
} else {
local_flush_tlb_all();
}
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
@@ -175,7 +198,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
newpid = cpu_asid(cpu, vma->vm_mm);
page &= (PAGE_MASK << 1);
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
oldpid = read_c0_entryhi();
write_c0_entryhi(page | newpid);
mtc0_tlbw_hazard();
@@ -194,7 +217,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
finish:
write_c0_entryhi(oldpid);
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
}
@@ -207,7 +230,7 @@ void local_flush_tlb_one(unsigned long page)
unsigned long flags;
int oldpid, idx;
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
oldpid = read_c0_entryhi();
page &= (PAGE_MASK << 1);
write_c0_entryhi(page);
@@ -226,7 +249,7 @@ void local_flush_tlb_one(unsigned long page)
}
write_c0_entryhi(oldpid);
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
/*
@@ -249,7 +272,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
if (current->active_mm != vma->vm_mm)
return;
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
pid = read_c0_entryhi() & ASID_MASK;
address &= (PAGE_MASK << 1);
@@ -277,7 +300,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
else
tlb_write_indexed();
tlbw_use_hazard();
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
#if 0
@@ -291,7 +314,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
pte_t *ptep;
int idx;
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
address &= (PAGE_MASK << 1);
asid = read_c0_entryhi() & ASID_MASK;
write_c0_entryhi(address | asid);
@@ -310,7 +333,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
else
tlb_write_indexed();
tlbw_use_hazard();
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
#endif
@@ -322,7 +345,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
unsigned long old_pagemask;
unsigned long old_ctx;
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
/* Save old context and create impossible VPN2 value */
old_ctx = read_c0_entryhi();
old_pagemask = read_c0_pagemask();
@@ -342,7 +365,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
BARRIER;
write_c0_pagemask(old_pagemask);
local_flush_tlb_all();
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
}
/*
@@ -362,7 +385,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
unsigned long old_pagemask;
unsigned long old_ctx;
- local_irq_save(flags);
+ ENTER_CRITICAL(flags);
/* Save old context and create impossible VPN2 value */
old_ctx = read_c0_entryhi();
old_pagemask = read_c0_pagemask();
@@ -386,10 +409,11 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
write_c0_entryhi(old_ctx);
write_c0_pagemask(old_pagemask);
out:
- local_irq_restore(flags);
+ EXIT_CRITICAL(flags);
return ret;
}
+extern void __init sanitize_tlb_entries(void);
static void __init probe_tlb(unsigned long config)
{
struct cpuinfo_mips *c = &current_cpu_data;
@@ -402,6 +426,14 @@ static void __init probe_tlb(unsigned long config)
*/
if ((c->processor_id & 0xff0000) == PRID_COMP_LEGACY)
return;
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * If TLB is shared in SMTC system, total size already
+ * has been calculated and written into cpu_data tlbsize
+ */
+ if((smtc_status & SMTC_TLB_SHARED) == SMTC_TLB_SHARED)
+ return;
+#endif /* CONFIG_MIPS_MT_SMTC */
reg = read_c0_config1();
if (!((config >> 7) & 3))
@@ -410,6 +442,15 @@ static void __init probe_tlb(unsigned long config)
c->tlbsize = ((reg >> 25) & 0x3f) + 1;
}
+static int __initdata ntlb = 0;
+static int __init set_ntlb(char *str)
+{
+ get_option(&str, &ntlb);
+ return 1;
+}
+
+__setup("ntlb=", set_ntlb);
+
void __init tlb_init(void)
{
unsigned int config = read_c0_config();
@@ -432,5 +473,15 @@ void __init tlb_init(void)
/* Did I tell you that ARC SUCKS? */
+ if (ntlb) {
+ if (ntlb > 1 && ntlb <= current_cpu_data.tlbsize) {
+ int wired = current_cpu_data.tlbsize - ntlb;
+ write_c0_wired(wired);
+ write_c0_index(wired-1);
+ printk ("Restricting TLB to %d entries\n", ntlb);
+ } else
+ printk("Ignoring invalid argument ntlb=%d\n", ntlb);
+ }
+
build_tlb_refill_handler();
}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 599b3c29718..54507be2ab5 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -7,6 +7,16 @@
*
* Copyright (C) 2004,2005 by Thiemo Seufer
* Copyright (C) 2005 Maciej W. Rozycki
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * ... and the days got worse and worse and now you see
+ * I've gone completly out of my mind.
+ *
+ * They're coming to take me a away haha
+ * they're coming to take me a away hoho hihi haha
+ * to the funny farm where code is beautiful all the time ...
+ *
+ * (Condolences to Napoleon XIV)
*/
#include <stdarg.h>
@@ -68,6 +78,7 @@ enum fields
BIMM = 0x040,
JIMM = 0x080,
FUNC = 0x100,
+ SET = 0x200
};
#define OP_MASK 0x2f
@@ -86,6 +97,8 @@ enum fields
#define JIMM_SH 0
#define FUNC_MASK 0x2f
#define FUNC_SH 0
+#define SET_MASK 0x7
+#define SET_SH 0
enum opcode {
insn_invalid,
@@ -129,8 +142,8 @@ static __initdata struct insn insn_table[] = {
{ insn_bne, M(bne_op,0,0,0,0,0), RS | RT | BIMM },
{ insn_daddiu, M(daddiu_op,0,0,0,0,0), RS | RT | SIMM },
{ insn_daddu, M(spec_op,0,0,0,0,daddu_op), RS | RT | RD },
- { insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD },
- { insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD },
+ { insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD | SET},
+ { insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD | SET},
{ insn_dsll, M(spec_op,0,0,0,0,dsll_op), RT | RD | RE },
{ insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE },
{ insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE },
@@ -145,8 +158,8 @@ static __initdata struct insn insn_table[] = {
{ insn_lld, M(lld_op,0,0,0,0,0), RS | RT | SIMM },
{ insn_lui, M(lui_op,0,0,0,0,0), RT | SIMM },
{ insn_lw, M(lw_op,0,0,0,0,0), RS | RT | SIMM },
- { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD },
- { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD },
+ { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD | SET},
+ { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD | SET},
{ insn_ori, M(ori_op,0,0,0,0,0), RS | RT | UIMM },
{ insn_rfe, M(cop0_op,cop_op,0,0,0,rfe_op), 0 },
{ insn_sc, M(sc_op,0,0,0,0,0), RS | RT | SIMM },
@@ -242,6 +255,14 @@ static __init u32 build_func(u32 arg)
return arg & FUNC_MASK;
}
+static __init u32 build_set(u32 arg)
+{
+ if (arg & ~SET_MASK)
+ printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+ return arg & SET_MASK;
+}
+
/*
* The order of opcode arguments is implicitly left to right,
* starting with RS and ending with FUNC or IMM.
@@ -273,6 +294,7 @@ static void __init build_insn(u32 **buf, enum opcode opc, ...)
if (ip->fields & BIMM) op |= build_bimm(va_arg(ap, s32));
if (ip->fields & JIMM) op |= build_jimm(va_arg(ap, u32));
if (ip->fields & FUNC) op |= build_func(va_arg(ap, u32));
+ if (ip->fields & SET) op |= build_set(va_arg(ap, u32));
va_end(ap);
**buf = op;
@@ -358,8 +380,8 @@ I_u1s2(_bgezl);
I_u1s2(_bltz);
I_u1s2(_bltzl);
I_u1u2s3(_bne);
-I_u1u2(_dmfc0);
-I_u1u2(_dmtc0);
+I_u1u2u3(_dmfc0);
+I_u1u2u3(_dmtc0);
I_u2u1s3(_daddiu);
I_u3u1u2(_daddu);
I_u2u1u3(_dsll);
@@ -376,8 +398,8 @@ I_u2s3u1(_ll);
I_u2s3u1(_lld);
I_u1s2(_lui);
I_u2s3u1(_lw);
-I_u1u2(_mfc0);
-I_u1u2(_mtc0);
+I_u1u2u3(_mfc0);
+I_u1u2u3(_mtc0);
I_u2u1u3(_ori);
I_0(_rfe);
I_u2s3u1(_sc);
@@ -451,8 +473,8 @@ L_LA(_r3000_write_probe_fail)
# define i_SLL(buf, rs, rt, sh) i_dsll(buf, rs, rt, sh)
# define i_SRA(buf, rs, rt, sh) i_dsra(buf, rs, rt, sh)
# define i_SRL(buf, rs, rt, sh) i_dsrl(buf, rs, rt, sh)
-# define i_MFC0(buf, rt, rd) i_dmfc0(buf, rt, rd)
-# define i_MTC0(buf, rt, rd) i_dmtc0(buf, rt, rd)
+# define i_MFC0(buf, rt, rd...) i_dmfc0(buf, rt, rd)
+# define i_MTC0(buf, rt, rd...) i_dmtc0(buf, rt, rd)
# define i_ADDIU(buf, rs, rt, val) i_daddiu(buf, rs, rt, val)
# define i_ADDU(buf, rs, rt, rd) i_daddu(buf, rs, rt, rd)
# define i_SUBU(buf, rs, rt, rd) i_dsubu(buf, rs, rt, rd)
@@ -464,8 +486,8 @@ L_LA(_r3000_write_probe_fail)
# define i_SLL(buf, rs, rt, sh) i_sll(buf, rs, rt, sh)
# define i_SRA(buf, rs, rt, sh) i_sra(buf, rs, rt, sh)
# define i_SRL(buf, rs, rt, sh) i_srl(buf, rs, rt, sh)
-# define i_MFC0(buf, rt, rd) i_mfc0(buf, rt, rd)
-# define i_MTC0(buf, rt, rd) i_mtc0(buf, rt, rd)
+# define i_MFC0(buf, rt, rd...) i_mfc0(buf, rt, rd)
+# define i_MTC0(buf, rt, rd...) i_mtc0(buf, rt, rd)
# define i_ADDIU(buf, rs, rt, val) i_addiu(buf, rs, rt, val)
# define i_ADDU(buf, rs, rt, rd) i_addu(buf, rs, rt, rd)
# define i_SUBU(buf, rs, rt, rd) i_subu(buf, rs, rt, rd)
@@ -670,14 +692,15 @@ static void __init il_bgezl(u32 **p, struct reloc **r, unsigned int reg,
#define K1 27
/* Some CP0 registers */
-#define C0_INDEX 0
-#define C0_ENTRYLO0 2
-#define C0_ENTRYLO1 3
-#define C0_CONTEXT 4
-#define C0_BADVADDR 8
-#define C0_ENTRYHI 10
-#define C0_EPC 14
-#define C0_XCONTEXT 20
+#define C0_INDEX 0, 0
+#define C0_ENTRYLO0 2, 0
+#define C0_TCBIND 2, 2
+#define C0_ENTRYLO1 3, 0
+#define C0_CONTEXT 4, 0
+#define C0_BADVADDR 8, 0
+#define C0_ENTRYHI 10, 0
+#define C0_EPC 14, 0
+#define C0_XCONTEXT 20, 0
#ifdef CONFIG_64BIT
# define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_XCONTEXT)
@@ -742,7 +765,7 @@ static void __init build_r3000_tlb_refill_handler(void)
}
#endif
- memcpy((void *)CAC_BASE, tlb_handler, 0x80);
+ memcpy((void *)ebase, tlb_handler, 0x80);
}
/*
@@ -852,6 +875,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
case CPU_R10000:
case CPU_R12000:
+ case CPU_R14000:
case CPU_4KC:
case CPU_SB1:
case CPU_SB1A:
@@ -883,6 +907,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
case CPU_4KEC:
case CPU_24K:
case CPU_34K:
+ case CPU_74K:
i_ehb(p);
tlbw(p);
break;
@@ -951,12 +976,20 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r,
/* No i_nop needed here, since the next insn doesn't touch TMP. */
#ifdef CONFIG_SMP
+# ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * SMTC uses TCBind value as "CPU" index
+ */
+ i_mfc0(p, ptr, C0_TCBIND);
+ i_dsrl(p, ptr, ptr, 19);
+# else
/*
* 64 bit SMP running in XKPHYS has smp_processor_id() << 3
* stored in CONTEXT.
*/
i_dmfc0(p, ptr, C0_CONTEXT);
i_dsrl(p, ptr, ptr, 23);
+#endif
i_LA_mostly(p, tmp, pgdc);
i_daddu(p, ptr, ptr, tmp);
i_dmfc0(p, tmp, C0_BADVADDR);
@@ -1014,9 +1047,21 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
#ifdef CONFIG_SMP
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * SMTC uses TCBind value as "CPU" index
+ */
+ i_mfc0(p, ptr, C0_TCBIND);
+ i_LA_mostly(p, tmp, pgdc);
+ i_srl(p, ptr, ptr, 19);
+#else
+ /*
+ * smp_processor_id() << 3 is stored in CONTEXT.
+ */
i_mfc0(p, ptr, C0_CONTEXT);
i_LA_mostly(p, tmp, pgdc);
i_srl(p, ptr, ptr, 23);
+#endif
i_addu(p, ptr, tmp, ptr);
#else
i_LA_mostly(p, ptr, pgdc);
@@ -1247,7 +1292,7 @@ static void __init build_r4000_tlb_refill_handler(void)
}
#endif
- memcpy((void *)CAC_BASE, final_handler, 0x100);
+ memcpy((void *)ebase, final_handler, 0x100);
}
/*
diff --git a/arch/mips/momentum/jaguar_atx/Makefile b/arch/mips/momentum/jaguar_atx/Makefile
index 20bbd3ea44a..67372f3f965 100644
--- a/arch/mips/momentum/jaguar_atx/Makefile
+++ b/arch/mips/momentum/jaguar_atx/Makefile
@@ -6,7 +6,7 @@
# unless it's something special (ie not a .c file).
#
-obj-y += int-handler.o irq.o prom.o reset.o setup.o
+obj-y += irq.o prom.o reset.o setup.o
obj-$(CONFIG_SERIAL_8250_CONSOLE) += ja-console.o
obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
diff --git a/arch/mips/momentum/jaguar_atx/dbg_io.c b/arch/mips/momentum/jaguar_atx/dbg_io.c
index 542eac82b63..d7dea0a136a 100644
--- a/arch/mips/momentum/jaguar_atx/dbg_io.c
+++ b/arch/mips/momentum/jaguar_atx/dbg_io.c
@@ -73,7 +73,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
/* disable interrupts */
UART16550_WRITE(OFS_INTR_ENABLE, 0);
- /* set up buad rate */
+ /* set up baud rate */
{
uint32 divisor;
diff --git a/arch/mips/momentum/jaguar_atx/int-handler.S b/arch/mips/momentum/jaguar_atx/int-handler.S
deleted file mode 100644
index 55bc789733f..00000000000
--- a/arch/mips/momentum/jaguar_atx/int-handler.S
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Based on work:
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for Jaguar-ATX board.
- *
- * This program is free software; 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * First level interrupt dispatcher for Ocelot-CS board
- */
- .align 5
- NESTED(jaguar_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP0 /* sw0 software interrupt */
- bnez t1, ll_sw0_irq
- andi t1, t0, STATUSF_IP1 /* sw1 software interrupt */
- bnez t1, ll_sw1_irq
- andi t1, t0, STATUSF_IP2 /* int0 hardware line */
- bnez t1, ll_pcixa_irq
- andi t1, t0, STATUSF_IP3 /* int1 hardware line */
- bnez t1, ll_pcixb_irq
- andi t1, t0, STATUSF_IP4 /* int2 hardware line */
- bnez t1, ll_pcia_irq
- andi t1, t0, STATUSF_IP5 /* int3 hardware line */
- bnez t1, ll_pcib_irq
- andi t1, t0, STATUSF_IP6 /* int4 hardware line */
- bnez t1, ll_uart_irq
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cputimer_irq
-
- nop
- nop
-
- /* now look at extended interrupts */
- mfc0 t0, CP0_CAUSE
- cfc0 t1, CP0_S1_INTCONTROL
-
- /* shift the mask 8 bits left to line up the bits */
- sll t2, t1, 8
-
- and t0, t2
- srl t0, t0, 16
-
- andi t1, t0, STATUSF_IP8 /* int6 hardware line */
- bnez t1, ll_mv64340_decode_irq
-
- nop
- nop
-
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(jaguar_handle_int)
-
- .align 5
-ll_sw0_irq:
- li a0, 0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-ll_sw1_irq:
- li a0, 1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-ll_pcixa_irq:
- li a0, 2
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pcixb_irq:
- li a0, 3
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pcia_irq:
- li a0, 4
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pcib_irq:
- li a0, 5
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_uart_irq:
- li a0, 6
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, 7
- move a1, sp
- jal ll_timer_interrupt
- j ret_from_irq
-
-ll_mv64340_decode_irq:
- move a0, sp
- jal ll_mv64340_irq
- j ret_from_irq
diff --git a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c
index 15588f91ace..ec4032b38f1 100644
--- a/arch/mips/momentum/jaguar_atx/irq.c
+++ b/arch/mips/momentum/jaguar_atx/irq.c
@@ -10,7 +10,7 @@
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*
- * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 2000, 01, 06 Ralf Baechle (ralf@linux-mips.org)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -38,8 +38,37 @@
#include <linux/types.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
+#include <asm/time.h>
-extern asmlinkage void jaguar_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP0)
+ do_IRQ(0, regs);
+ else if (pending & STATUSF_IP1)
+ do_IRQ(1, regs);
+ else if (pending & STATUSF_IP2)
+ do_IRQ(2, regs);
+ else if (pending & STATUSF_IP3)
+ do_IRQ(3, regs);
+ else if (pending & STATUSF_IP4)
+ do_IRQ(4, regs);
+ else if (pending & STATUSF_IP5)
+ do_IRQ(5, regs);
+ else if (pending & STATUSF_IP6)
+ do_IRQ(6, regs);
+ else if (pending & STATUSF_IP7)
+ ll_timer_interrupt(7, regs);
+ else {
+ /*
+ * Now look at the extended interrupts
+ */
+ pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+ if (pending & STATUSF_IP8)
+ ll_mv64340_irq(regs);
+ }
+}
static struct irqaction cascade_mv64340 = {
no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
@@ -53,8 +82,6 @@ void __init arch_init_irq(void)
*/
clear_c0_status(ST0_IM);
- /* Sets the first-level interrupt dispatcher. */
- set_except_vector(0, jaguar_handle_int);
mips_cpu_irq_init(0);
rm7k_cpu_irq_init(8);
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
index 3784c898db1..1379c76845d 100644
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ b/arch/mips/momentum/jaguar_atx/setup.c
@@ -229,8 +229,8 @@ void momenco_time_init(void)
mips_hpt_frequency = cpu_clock / 2;
board_timer_setup = momenco_timer_setup;
- rtc_get_time = m48t37y_get_time;
- rtc_set_time = m48t37y_set_time;
+ rtc_mips_get_time = m48t37y_get_time;
+ rtc_mips_set_time = m48t37y_set_time;
}
static struct resource mv_pci_io_mem0_resource = {
@@ -381,24 +381,24 @@ void __init plat_setup(void)
* shut down ethernet ports, just to be sure our memory doesn't get
* corrupted by random ethernet traffic.
*/
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8);
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8);
- while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
- while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
- while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff);
- while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
- while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
- while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff);
- MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0),
- MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
- MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1),
- MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
- MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2),
- MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1);
+ MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
+ MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
+ MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8);
+ MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
+ MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
+ MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8);
+ while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
+ while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
+ while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff);
+ while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
+ while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
+ while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff);
+ MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
+ MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
+ MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
+ MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
+ MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2),
+ MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1);
/* Turn off the Bit-Error LED */
JAGUAR_FPGA_WRITE(0x80, CLR);
diff --git a/arch/mips/momentum/ocelot_3/Makefile b/arch/mips/momentum/ocelot_3/Makefile
index aab8fd89f83..8bcea64dd27 100644
--- a/arch/mips/momentum/ocelot_3/Makefile
+++ b/arch/mips/momentum/ocelot_3/Makefile
@@ -5,4 +5,4 @@
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
-obj-y += int-handler.o irq.o prom.o reset.o setup.o
+obj-y += irq.o prom.o reset.o setup.o
diff --git a/arch/mips/momentum/ocelot_3/int-handler.S b/arch/mips/momentum/ocelot_3/int-handler.S
deleted file mode 100644
index 4522f09ed76..00000000000
--- a/arch/mips/momentum/ocelot_3/int-handler.S
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- * First-level interrupt dispatcher for Ocelot-3 board.
- *
- * This program is free software; 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * First level interrupt dispatcher for Ocelot-3 board
- */
- .align 5
- NESTED(ocelot3_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
-
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP0 /* sw0 software interrupt (IRQ0) */
- bnez t1, ll_sw0_irq
-
- andi t1, t0, STATUSF_IP1 /* sw1 software interrupt (IRQ1) */
- bnez t1, ll_sw1_irq
-
- andi t1, t0, STATUSF_IP2 /* int0 hardware line (IRQ2) */
- bnez t1, ll_pci0slot1_irq
-
- andi t1, t0, STATUSF_IP3 /* int1 hardware line (IRQ3) */
- bnez t1, ll_pci0slot2_irq
-
- andi t1, t0, STATUSF_IP4 /* int2 hardware line (IRQ4) */
- bnez t1, ll_pci1slot1_irq
-
- andi t1, t0, STATUSF_IP5 /* int3 hardware line (IRQ5) */
- bnez t1, ll_pci1slot2_irq
-
- andi t1, t0, STATUSF_IP6 /* int4 hardware line (IRQ6) */
- bnez t1, ll_uart_irq
-
- andi t1, t0, STATUSF_IP7 /* cpu timer (IRQ7) */
- bnez t1, ll_cputimer_irq
-
- /* now look at extended interrupts */
- mfc0 t0, CP0_CAUSE
- cfc0 t1, CP0_S1_INTCONTROL
-
- /* shift the mask 8 bits left to line up the bits */
- sll t2, t1, 8
-
- and t0, t2
- srl t0, t0, 16
-
- andi t1, t0, STATUSF_IP8 /* int6 hardware line (IRQ9) */
- bnez t1, ll_mv64340_decode_irq
-
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(ocelot3_handle_int)
-
- .align 5
-ll_sw0_irq:
- li a0, 0 /* IRQ 1 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-ll_sw1_irq:
- li a0, 1 /* IRQ 2 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pci0slot1_irq:
- li a0, 2 /* IRQ 3 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pci0slot2_irq:
- li a0, 3 /* IRQ 4 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pci1slot1_irq:
- li a0, 4 /* IRQ 5 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pci1slot2_irq:
- li a0, 5 /* IRQ 6 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_uart_irq:
- li a0, 6 /* IRQ 7 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, 7 /* IRQ 8 */
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_mv64340_decode_irq:
- move a0, sp
- jal ll_mv64340_irq
- j ret_from_irq
-
diff --git a/arch/mips/momentum/ocelot_3/irq.c b/arch/mips/momentum/ocelot_3/irq.c
index 42464dbd4ad..87c63c340ae 100644
--- a/arch/mips/momentum/ocelot_3/irq.c
+++ b/arch/mips/momentum/ocelot_3/irq.c
@@ -53,8 +53,6 @@
#include <asm/mipsregs.h>
#include <asm/system.h>
-extern asmlinkage void ocelot3_handle_int(void);
-
static struct irqaction cascade_mv64340 = {
no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
};
@@ -67,9 +65,6 @@ void __init arch_init_irq(void)
*/
clear_c0_status(ST0_IM | ST0_BEV);
- /* Sets the first-level interrupt dispatcher. */
- set_except_vector(0, ocelot3_handle_int);
- mips_cpu_irq_init(0);
rm7k_cpu_irq_init(8);
/* set up the cascading interrupts */
@@ -79,3 +74,36 @@ void __init arch_init_irq(void)
set_c0_status(ST0_IM); /* IE in the status register */
}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP0)
+ do_IRQ(0, regs);
+ else if (pending & STATUSF_IP1)
+ do_IRQ(1, regs);
+ else if (pending & STATUSF_IP2)
+ do_IRQ(2, regs);
+ else if (pending & STATUSF_IP3)
+ do_IRQ(3, regs);
+ else if (pending & STATUSF_IP4)
+ do_IRQ(4, regs);
+ else if (pending & STATUSF_IP5)
+ do_IRQ(5, regs);
+ else if (pending & STATUSF_IP6)
+ do_IRQ(6, regs);
+ else if (pending & STATUSF_IP7)
+ do_IRQ(7, regs);
+ else {
+ /*
+ * Now look at the extended interrupts
+ */
+ pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+ if (pending & STATUSF_IP8)
+ ll_mv64340_irq(regs);
+ else
+ spurious_interrupt(regs);
+ }
+}
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
index f95677f4f06..c6919523430 100644
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ b/arch/mips/momentum/ocelot_3/setup.c
@@ -58,6 +58,7 @@
#include <linux/bootmem.h>
#include <linux/mv643xx.h>
#include <linux/pm.h>
+#include <linux/bcd.h>
#include <asm/time.h>
#include <asm/page.h>
@@ -131,9 +132,6 @@ void setup_wired_tlb_entries(void)
add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), (signed)0xfc000000, PM_16M);
}
-#define CONV_BCD_TO_BIN(val) (((val) & 0xf) + (((val) >> 4) * 10))
-#define CONV_BIN_TO_BCD(val) (((val) % 10) + (((val) / 10) << 4))
-
unsigned long m48t37y_get_time(void)
{
unsigned int year, month, day, hour, min, sec;
@@ -143,16 +141,16 @@ unsigned long m48t37y_get_time(void)
/* stop the update */
rtc_base[0x7ff8] = 0x40;
- year = CONV_BCD_TO_BIN(rtc_base[0x7fff]);
- year += CONV_BCD_TO_BIN(rtc_base[0x7ff1]) * 100;
+ year = BCD2BIN(rtc_base[0x7fff]);
+ year += BCD2BIN(rtc_base[0x7ff1]) * 100;
- month = CONV_BCD_TO_BIN(rtc_base[0x7ffe]);
+ month = BCD2BIN(rtc_base[0x7ffe]);
- day = CONV_BCD_TO_BIN(rtc_base[0x7ffd]);
+ day = BCD2BIN(rtc_base[0x7ffd]);
- hour = CONV_BCD_TO_BIN(rtc_base[0x7ffb]);
- min = CONV_BCD_TO_BIN(rtc_base[0x7ffa]);
- sec = CONV_BCD_TO_BIN(rtc_base[0x7ff9]);
+ hour = BCD2BIN(rtc_base[0x7ffb]);
+ min = BCD2BIN(rtc_base[0x7ffa]);
+ sec = BCD2BIN(rtc_base[0x7ff9]);
/* start the update */
rtc_base[0x7ff8] = 0x00;
@@ -175,22 +173,22 @@ int m48t37y_set_time(unsigned long sec)
rtc_base[0x7ff8] = 0x80;
/* year */
- rtc_base[0x7fff] = CONV_BIN_TO_BCD(tm.tm_year % 100);
- rtc_base[0x7ff1] = CONV_BIN_TO_BCD(tm.tm_year / 100);
+ rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
+ rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
/* month */
- rtc_base[0x7ffe] = CONV_BIN_TO_BCD(tm.tm_mon);
+ rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
/* day */
- rtc_base[0x7ffd] = CONV_BIN_TO_BCD(tm.tm_mday);
+ rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
/* hour/min/sec */
- rtc_base[0x7ffb] = CONV_BIN_TO_BCD(tm.tm_hour);
- rtc_base[0x7ffa] = CONV_BIN_TO_BCD(tm.tm_min);
- rtc_base[0x7ff9] = CONV_BIN_TO_BCD(tm.tm_sec);
+ rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
+ rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
+ rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
/* day of week -- not really used, but let's keep it up-to-date */
- rtc_base[0x7ffc] = CONV_BIN_TO_BCD(tm.tm_wday + 1);
+ rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
/* disable writing */
rtc_base[0x7ff8] = 0x00;
@@ -215,8 +213,8 @@ void momenco_time_init(void)
mips_hpt_frequency = cpu_clock / 2;
board_timer_setup = momenco_timer_setup;
- rtc_get_time = m48t37y_get_time;
- rtc_set_time = m48t37y_set_time;
+ rtc_mips_get_time = m48t37y_get_time;
+ rtc_mips_set_time = m48t37y_set_time;
}
/*
@@ -331,22 +329,22 @@ void __init plat_setup(void)
/* shut down ethernet ports, just to be sure our memory doesn't get
* corrupted by random ethernet traffic.
*/
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
+ MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
+ MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
+ MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
+ MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
do {}
- while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
+ while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
do {}
- while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
+ while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
do {}
- while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
+ while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
do {}
- while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
- MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0),
- MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
- MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1),
- MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
+ while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
+ MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
+ MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
+ MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
+ MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
/* Turn off the Bit-Error LED */
OCELOT_FPGA_WRITE(0x80, CLR);
diff --git a/arch/mips/momentum/ocelot_c/Makefile b/arch/mips/momentum/ocelot_c/Makefile
index 91240777f97..94802b4db47 100644
--- a/arch/mips/momentum/ocelot_c/Makefile
+++ b/arch/mips/momentum/ocelot_c/Makefile
@@ -2,7 +2,7 @@
# Makefile for Momentum Computer's Ocelot-C and -CS boards.
#
-obj-y += cpci-irq.o int-handler.o irq.o prom.o reset.o \
+obj-y += cpci-irq.o irq.o prom.o reset.o \
setup.o uart-irq.o
obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/momentum/ocelot_c/dbg_io.c b/arch/mips/momentum/ocelot_c/dbg_io.c
index 8720bccfdea..f0a6a38fcf4 100644
--- a/arch/mips/momentum/ocelot_c/dbg_io.c
+++ b/arch/mips/momentum/ocelot_c/dbg_io.c
@@ -73,7 +73,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
/* disable interrupts */
UART16550_WRITE(OFS_INTR_ENABLE, 0);
- /* set up buad rate */
+ /* set up baud rate */
{
uint32 divisor;
diff --git a/arch/mips/momentum/ocelot_c/int-handler.S b/arch/mips/momentum/ocelot_c/int-handler.S
deleted file mode 100644
index 52349d9bf1b..00000000000
--- a/arch/mips/momentum/ocelot_c/int-handler.S
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for Ocelot-CS board.
- *
- * This program is free software; 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include "ocelot_c_fpga.h"
-
-/*
- * First level interrupt dispatcher for Ocelot-CS board
- */
- .align 5
- NESTED(ocelot_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP0 /* sw0 software interrupt */
- bnez t1, ll_sw0_irq
- andi t1, t0, STATUSF_IP1 /* sw1 software interrupt */
- bnez t1, ll_sw1_irq
- andi t1, t0, STATUSF_IP2 /* int0 hardware line */
- bnez t1, ll_scsi_irq
- andi t1, t0, STATUSF_IP3 /* int1 hardware line */
- bnez t1, ll_uart_decode_irq
- andi t1, t0, STATUSF_IP4 /* int2 hardware line */
- bnez t1, ll_pmc_irq
- andi t1, t0, STATUSF_IP5 /* int3 hardware line */
- bnez t1, ll_cpci_decode_irq
- andi t1, t0, STATUSF_IP6 /* int4 hardware line */
- bnez t1, ll_mv64340_decode_irq
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cputimer_irq
-
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(ocelot_handle_int)
-
- .align 5
-ll_sw0_irq:
- li a0, 0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-ll_sw1_irq:
- li a0, 1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-ll_scsi_irq:
- li a0, 2
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_uart_decode_irq:
- move a0, sp
- jal ll_uart_irq
- j ret_from_irq
-
-ll_pmc_irq:
- li a0, 4
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpci_decode_irq:
- move a0, sp
- jal ll_cpci_irq
- j ret_from_irq
-
-ll_mv64340_decode_irq:
- move a0, sp
- jal ll_mv64340_irq
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, 7
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c
index a5764bc20e3..86f61ce59e5 100644
--- a/arch/mips/momentum/ocelot_c/irq.c
+++ b/arch/mips/momentum/ocelot_c/irq.c
@@ -48,7 +48,6 @@
#include <asm/mipsregs.h>
#include <asm/system.h>
-extern asmlinkage void ocelot_handle_int(void);
extern void uart_irq_init(void);
extern void cpci_irq_init(void);
@@ -60,6 +59,33 @@ static struct irqaction cascade_mv64340 = {
no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL
};
+extern void ll_uart_irq(struct pt_regs *regs);
+extern void ll_cpci_irq(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP0)
+ do_IRQ(0, regs);
+ else if (pending & STATUSF_IP1)
+ do_IRQ(1, regs);
+ else if (pending & STATUSF_IP2)
+ do_IRQ(2, regs);
+ else if (pending & STATUSF_IP3)
+ ll_uart_irq(regs);
+ else if (pending & STATUSF_IP4)
+ do_IRQ(4, regs);
+ else if (pending & STATUSF_IP5)
+ ll_cpci_irq(regs);
+ else if (pending & STATUSF_IP6)
+ ll_mv64340_irq(regs);
+ else if (pending & STATUSF_IP7)
+ do_IRQ(7, regs);
+ else
+ spurious_interrupt(regs);
+}
+
void __init arch_init_irq(void)
{
/*
@@ -68,8 +94,6 @@ void __init arch_init_irq(void)
*/
clear_c0_status(ST0_IM);
- /* Sets the first-level interrupt dispatcher. */
- set_except_vector(0, ocelot_handle_int);
mips_cpu_irq_init(0);
/* set up the cascading interrupts */
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
index bd02e60d037..a3e6f557559 100644
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ b/arch/mips/momentum/ocelot_c/setup.c
@@ -227,8 +227,8 @@ void momenco_time_init(void)
printk("momenco_time_init cpu_clock=%d\n", cpu_clock);
board_timer_setup = momenco_timer_setup;
- rtc_get_time = m48t37y_get_time;
- rtc_set_time = m48t37y_set_time;
+ rtc_mips_get_time = m48t37y_get_time;
+ rtc_mips_set_time = m48t37y_set_time;
}
void __init plat_setup(void)
diff --git a/arch/mips/momentum/ocelot_g/Makefile b/arch/mips/momentum/ocelot_g/Makefile
index e5f1cb08697..adb5665d40a 100644
--- a/arch/mips/momentum/ocelot_g/Makefile
+++ b/arch/mips/momentum/ocelot_g/Makefile
@@ -2,7 +2,7 @@
# Makefile for Momentum Computer's Ocelot-G board.
#
-obj-y += int-handler.o irq.o gt-irq.o prom.o reset.o setup.o
+obj-y += irq.o gt-irq.o prom.o reset.o setup.o
obj-$(CONFIG_KGDB) += dbg_io.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/momentum/ocelot_g/dbg_io.c b/arch/mips/momentum/ocelot_g/dbg_io.c
index 8720bccfdea..f0a6a38fcf4 100644
--- a/arch/mips/momentum/ocelot_g/dbg_io.c
+++ b/arch/mips/momentum/ocelot_g/dbg_io.c
@@ -73,7 +73,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
/* disable interrupts */
UART16550_WRITE(OFS_INTR_ENABLE, 0);
- /* set up buad rate */
+ /* set up baud rate */
{
uint32 divisor;
diff --git a/arch/mips/momentum/ocelot_g/int-handler.S b/arch/mips/momentum/ocelot_g/int-handler.S
deleted file mode 100644
index 772e8f71317..00000000000
--- a/arch/mips/momentum/ocelot_g/int-handler.S
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ocelot board.
- *
- * This program is free software; 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
- .align 5
- NESTED(ocelot_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP2 /* int0 hardware line */
- bnez t1, ll_pri_enet_irq
- andi t1, t0, STATUSF_IP3 /* int1 hardware line */
- bnez t1, ll_sec_enet_irq
- andi t1, t0, STATUSF_IP4 /* int2 hardware line */
- bnez t1, ll_uart_irq
- andi t1, t0, STATUSF_IP5 /* int3 hardware line */
- bnez t1, ll_cpci_irq
- andi t1, t0, STATUSF_IP6 /* int4 hardware line */
- bnez t1, ll_galileo_p0_irq
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cputimer_irq
-
- /* now look at the extended interrupts */
- mfc0 t0, CP0_CAUSE
- cfc0 t1, CP0_S1_INTCONTROL
-
- /* shift the mask 8 bits left to line up the bits */
- sll t2, t1, 8
-
- and t0, t2
- srl t0, t0, 16
-
- andi t1, t0, STATUSF_IP8 /* int6 hardware line */
- bnez t1, ll_galileo_p1_irq
- andi t1, t0, STATUSF_IP9 /* int7 hardware line */
- bnez t1, ll_pmc_irq
- andi t1, t0, STATUSF_IP10 /* int8 hardware line */
- bnez t1, ll_cpci_abcd_irq
- andi t1, t0, STATUSF_IP11 /* int9 hardware line */
- bnez t1, ll_testpoint_irq
-
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(ocelot_handle_int)
-
- .align 5
-ll_pri_enet_irq:
- li a0, 2
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_sec_enet_irq:
- li a0, 3
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_uart_irq:
- li a0, 4
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpci_irq:
- li a0, 5
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_galileo_p0_irq:
- li a0, 6
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, 7
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_galileo_p1_irq:
- li a0, 8
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_pmc_irq:
- li a0, 9
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpci_abcd_irq:
- li a0, 10
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_testpoint_irq:
- li a0, 11
- move a1, sp
- jal do_IRQ
- j ret_from_irq
diff --git a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c
index 5eb85b16420..7a4a419804f 100644
--- a/arch/mips/momentum/ocelot_g/irq.c
+++ b/arch/mips/momentum/ocelot_g/irq.c
@@ -48,7 +48,41 @@
#include <asm/mipsregs.h>
#include <asm/system.h>
-extern asmlinkage void ocelot_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP2)
+ do_IRQ(2, regs);
+ else if (pending & STATUSF_IP3)
+ do_IRQ(3, regs);
+ else if (pending & STATUSF_IP4)
+ do_IRQ(4, regs);
+ else if (pending & STATUSF_IP5)
+ do_IRQ(5, regs);
+ else if (pending & STATUSF_IP6)
+ do_IRQ(6, regs);
+ else if (pending & STATUSF_IP7)
+ do_IRQ(7, regs);
+ else {
+ /*
+ * Now look at the extended interrupts
+ */
+ pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+ if (pending & STATUSF_IP8)
+ do_IRQ(8, regs);
+ else if (pending & STATUSF_IP9)
+ do_IRQ(9, regs);
+ else if (pending & STATUSF_IP10)
+ do_IRQ(10, regs);
+ else if (pending & STATUSF_IP11)
+ do_IRQ(11, regs);
+ else
+ spurious_interrupt(regs);
+ }
+}
+
extern void gt64240_irq_init(void);
void __init arch_init_irq(void)
@@ -60,8 +94,6 @@ void __init arch_init_irq(void)
clear_c0_status(ST0_IM);
local_irq_disable();
- /* Sets the first-level interrupt dispatcher. */
- set_except_vector(0, ocelot_handle_int);
mips_cpu_irq_init(0);
rm7k_cpu_irq_init(8);
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index 935dd851f48..c31e4cff64e 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -14,8 +14,8 @@
#include "op_impl.h"
-extern struct op_mips_model op_model_mipsxx __attribute__((weak));
-extern struct op_mips_model op_model_rm9000 __attribute__((weak));
+extern struct op_mips_model op_model_mipsxx_ops __attribute__((weak));
+extern struct op_mips_model op_model_rm9000_ops __attribute__((weak));
static struct op_mips_model *model;
@@ -27,7 +27,7 @@ static int op_mips_setup(void)
model->reg_setup(ctr);
/* Configure the registers on all cpus. */
- on_each_cpu(model->cpu_setup, 0, 0, 1);
+ on_each_cpu(model->cpu_setup, NULL, 0, 1);
return 0;
}
@@ -80,13 +80,14 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
case CPU_24K:
case CPU_25KF:
case CPU_34K:
+ case CPU_74K:
case CPU_SB1:
case CPU_SB1A:
- lmodel = &op_model_mipsxx;
+ lmodel = &op_model_mipsxx_ops;
break;
case CPU_RM9000:
- lmodel = &op_model_rm9000;
+ lmodel = &op_model_rm9000_ops;
break;
};
@@ -114,5 +115,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
void oprofile_arch_exit(void)
{
- model->exit();
+ if (model)
+ model->exit();
}
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 95d488ca075..f26a00e1320 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -23,7 +23,7 @@
#define M_COUNTER_OVERFLOW (1UL << 31)
-struct op_mips_model op_model_mipsxx;
+struct op_mips_model op_model_mipsxx_ops;
static struct mipsxx_register_config {
unsigned int control[4];
@@ -34,7 +34,7 @@ static struct mipsxx_register_config {
static void mipsxx_reg_setup(struct op_counter_config *ctr)
{
- unsigned int counters = op_model_mipsxx.num_counters;
+ unsigned int counters = op_model_mipsxx_ops.num_counters;
int i;
/* Compute the performance counter control word. */
@@ -62,7 +62,7 @@ static void mipsxx_reg_setup(struct op_counter_config *ctr)
static void mipsxx_cpu_setup (void *args)
{
- unsigned int counters = op_model_mipsxx.num_counters;
+ unsigned int counters = op_model_mipsxx_ops.num_counters;
switch (counters) {
case 4:
@@ -83,7 +83,7 @@ static void mipsxx_cpu_setup (void *args)
/* Start all counters on current CPU */
static void mipsxx_cpu_start(void *args)
{
- unsigned int counters = op_model_mipsxx.num_counters;
+ unsigned int counters = op_model_mipsxx_ops.num_counters;
switch (counters) {
case 4:
@@ -100,7 +100,7 @@ static void mipsxx_cpu_start(void *args)
/* Stop all counters on current CPU */
static void mipsxx_cpu_stop(void *args)
{
- unsigned int counters = op_model_mipsxx.num_counters;
+ unsigned int counters = op_model_mipsxx_ops.num_counters;
switch (counters) {
case 4:
@@ -116,7 +116,7 @@ static void mipsxx_cpu_stop(void *args)
static int mipsxx_perfcount_handler(struct pt_regs *regs)
{
- unsigned int counters = op_model_mipsxx.num_counters;
+ unsigned int counters = op_model_mipsxx_ops.num_counters;
unsigned int control;
unsigned int counter;
int handled = 0;
@@ -187,33 +187,37 @@ static int __init mipsxx_init(void)
reset_counters(counters);
- op_model_mipsxx.num_counters = counters;
+ op_model_mipsxx_ops.num_counters = counters;
switch (current_cpu_data.cputype) {
case CPU_20KC:
- op_model_mipsxx.cpu_type = "mips/20K";
+ op_model_mipsxx_ops.cpu_type = "mips/20K";
break;
case CPU_24K:
- op_model_mipsxx.cpu_type = "mips/24K";
+ op_model_mipsxx_ops.cpu_type = "mips/24K";
break;
case CPU_25KF:
- op_model_mipsxx.cpu_type = "mips/25K";
+ op_model_mipsxx_ops.cpu_type = "mips/25K";
break;
#ifndef CONFIG_SMP
case CPU_34K:
- op_model_mipsxx.cpu_type = "mips/34K";
+ op_model_mipsxx_ops.cpu_type = "mips/34K";
+ break;
+
+ case CPU_74K:
+ op_model_mipsxx_ops.cpu_type = "mips/74K";
break;
#endif
case CPU_5KC:
- op_model_mipsxx.cpu_type = "mips/5K";
+ op_model_mipsxx_ops.cpu_type = "mips/5K";
break;
case CPU_SB1:
case CPU_SB1A:
- op_model_mipsxx.cpu_type = "mips/sb1";
+ op_model_mipsxx_ops.cpu_type = "mips/sb1";
break;
default:
@@ -229,12 +233,12 @@ static int __init mipsxx_init(void)
static void mipsxx_exit(void)
{
- reset_counters(op_model_mipsxx.num_counters);
+ reset_counters(op_model_mipsxx_ops.num_counters);
perf_irq = null_perf_irq;
}
-struct op_mips_model op_model_mipsxx = {
+struct op_mips_model op_model_mipsxx_ops = {
.reg_setup = mipsxx_reg_setup,
.cpu_setup = mipsxx_cpu_setup,
.init = mipsxx_init,
diff --git a/arch/mips/oprofile/op_model_rm9000.c b/arch/mips/oprofile/op_model_rm9000.c
index 9b75e41c78e..b7063fefa65 100644
--- a/arch/mips/oprofile/op_model_rm9000.c
+++ b/arch/mips/oprofile/op_model_rm9000.c
@@ -126,7 +126,7 @@ static void rm9000_exit(void)
free_irq(rm9000_perfcount_irq, NULL);
}
-struct op_mips_model op_model_rm9000 = {
+struct op_mips_model op_model_rm9000_ops = {
.reg_setup = rm9000_reg_setup,
.cpu_setup = rm9000_cpu_setup,
.init = rm9000_init,
diff --git a/arch/mips/philips/pnx8550/common/Makefile b/arch/mips/philips/pnx8550/common/Makefile
index 6e38f3bc443..b7c638166e9 100644
--- a/arch/mips/philips/pnx8550/common/Makefile
+++ b/arch/mips/philips/pnx8550/common/Makefile
@@ -22,6 +22,6 @@
# under Linux.
#
-obj-y := setup.o prom.o mipsIRQ.o int.o reset.o time.o proc.o platform.o
+obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_KGDB) += gdb_hook.o
diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c
index c500e2d41f2..39ee6314f62 100644
--- a/arch/mips/philips/pnx8550/common/int.c
+++ b/arch/mips/philips/pnx8550/common/int.c
@@ -38,8 +38,6 @@
#include <int.h>
#include <uart.h>
-extern asmlinkage void cp0_irqdispatch(void);
-
static DEFINE_SPINLOCK(irq_lock);
/* default prio for interrupts */
@@ -55,7 +53,7 @@ static char gic_prio[PNX8550_INT_GIC_TOTINT] = {
1 // 70
};
-void hw0_irqdispatch(int irq, struct pt_regs *regs)
+static void hw0_irqdispatch(int irq, struct pt_regs *regs)
{
/* find out which interrupt */
irq = PNX8550_GIC_VECTOR_0 >> 3;
@@ -68,7 +66,7 @@ void hw0_irqdispatch(int irq, struct pt_regs *regs)
}
-void timer_irqdispatch(int irq, struct pt_regs *regs)
+static void timer_irqdispatch(int irq, struct pt_regs *regs)
{
irq = (0x01c0 & read_c0_config7()) >> 6;
@@ -88,6 +86,20 @@ void timer_irqdispatch(int irq, struct pt_regs *regs)
}
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause();
+
+ if (pending & STATUSF_IP2)
+ do_IRQ(2, regs);
+ else if (pending & STATUSF_IP7) {
+ if (read_c0_config7() & 0x01c0)
+ timer_irqdispatch(7, regs);
+ }
+
+ spurious_interrupt(regs);
+}
+
static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
{
unsigned long status = read_c0_status();
@@ -223,9 +235,6 @@ void __init arch_init_irq(void)
int i;
int configPR;
- /* init of cp0 interrupts */
- set_except_vector(0, cp0_irqdispatch);
-
for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) {
irq_desc[i].handler = &level_irq_type;
pnx8550_ack(i); /* mask the irq just in case */
diff --git a/arch/mips/philips/pnx8550/common/mipsIRQ.S b/arch/mips/philips/pnx8550/common/mipsIRQ.S
deleted file mode 100644
index 338bffda3fa..00000000000
--- a/arch/mips/philips/pnx8550/common/mipsIRQ.S
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2002 Philips, Inc. All rights.
- * Copyright (c) 2002 Red Hat, Inc. All rights.
- *
- * This software may be freely redistributed under the terms of the
- * GNU General Public 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Based upon arch/mips/galileo-boards/ev64240/int-handler.S
- *
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * cp0_irqdispatch
- *
- * Code to handle in-core interrupt exception.
- */
-
- .align 5
- .set reorder
- .set noat
- NESTED(cp0_irqdispatch, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 t0,CP0_CAUSE
- mfc0 t2,CP0_STATUS
-
- and t0,t2
-
- andi t1,t0,STATUSF_IP2 /* int0 hardware line */
- bnez t1,ll_hw0_irq
- nop
-
- andi t1,t0,STATUSF_IP7 /* int5 hardware line */
- bnez t1,ll_timer_irq
- nop
-
- /* wrong alarm or masked ... */
-
- j spurious_interrupt
- nop
- END(cp0_irqdispatch)
-
- .align 5
- .set reorder
-ll_hw0_irq:
- li a0,2
- move a1,sp
- jal hw0_irqdispatch
- nop
- j ret_from_irq
- nop
-
- .align 5
- .set reorder
-ll_timer_irq:
- mfc0 t3,CP0_CONFIG,7
- andi t4,t3,0x01c0
- beqz t4,ll_timer_out
- nop
- li a0,7
- move a1,sp
- jal timer_irqdispatch
- nop
-
-ll_timer_out: j ret_from_irq
- nop
diff --git a/arch/mips/philips/pnx8550/common/platform.c b/arch/mips/philips/pnx8550/common/platform.c
index a592260fd67..5436b4b9745 100644
--- a/arch/mips/philips/pnx8550/common/platform.c
+++ b/arch/mips/philips/pnx8550/common/platform.c
@@ -18,6 +18,7 @@
#include <linux/resource.h>
#include <linux/serial.h>
#include <linux/serial_ip3106.h>
+#include <linux/platform_device.h>
#include <int.h>
#include <usb.h>
diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile
index ae96a71a308..e931e0d4422 100644
--- a/arch/mips/pmc-sierra/yosemite/Makefile
+++ b/arch/mips/pmc-sierra/yosemite/Makefile
@@ -2,7 +2,7 @@
# Makefile for the PMC-Sierra Titan
#
-obj-y += irq-handler.o irq.o i2c-yosemite.o prom.o py-console.o setup.o
+obj-y += irq.o i2c-yosemite.o prom.o py-console.o setup.o
obj-$(CONFIG_KGDB) += dbg_io.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/mips/pmc-sierra/yosemite/irq-handler.S b/arch/mips/pmc-sierra/yosemite/irq-handler.S
deleted file mode 100644
index 33b9c40d4f5..00000000000
--- a/arch/mips/pmc-sierra/yosemite/irq-handler.S
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2003, 04 PMC-Sierra Inc.
- * Author: Manish Lachwani (lachwani@pmc-sierra.com
- * Copyright 2004 Ralf Baechle (ralf@linux-mips.org)
- *
- * First-level interrupt router for the PMC-Sierra Titan board
- *
- * This program is free software; 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.
- *
- * Titan supports Hypertransport or PCI but not both. Hence, one interrupt
- * line is shared between the PCI slot A and Hypertransport. This is the
- * Processor INTB #0.
- */
-
-#include <linux/config.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .align 5
- NESTED(titan_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- .set noreorder
- la ra, ret_from_irq
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t2, t0, STATUSF_IP7 /* INTB5 hardware line */
- bnez t2, ll_timer_irq /* Timer */
- andi t1, t0, STATUSF_IP2 /* INTB0 hardware line */
- bnez t1, ll_pcia_irq /* 64-bit PCI */
- andi t2, t0, STATUSF_IP3 /* INTB1 hardware line */
- bnez t2, ll_pcib_irq /* second 64-bit PCI slot */
- andi t1, t0, STATUSF_IP4 /* INTB2 hardware line */
- bnez t1, ll_duart_irq /* UART */
- andi t2, t0, STATUSF_IP5 /* SMP inter-core interrupts */
- bnez t2, ll_smp_irq
- andi t1, t0, STATUSF_IP6
- bnez t1, ll_ht_irq /* Hypertransport */
-
- move a0, sp
- j do_extended_irq
- END(titan_handle_int)
-
- .set reorder
- .align 5
-
-ll_pcia_irq:
- li a0, 2
- move a1, sp
-#ifdef CONFIG_HYPERTRANSPORT
- j ll_ht_smp_irq_handler
-#else
- j do_IRQ
-#endif
-
-ll_pcib_irq:
- li a0, 3
- move a1, sp
- j do_IRQ
-
-ll_duart_irq:
- li a0, 4
- move a1, sp
- j do_IRQ
-
-ll_smp_irq:
- li a0, 5
- move a1, sp
-#ifdef CONFIG_SMP
- j titan_mailbox_irq
-#else
- j do_IRQ
-#endif
-
-ll_ht_irq:
- li a0, 6
- move a1, sp
- j ll_ht_smp_irq_handler
-
-ll_timer_irq:
- li a0, 7
- move a1, sp
- j do_IRQ
diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c
index f4e2897d9bf..a1f524fc4c1 100644
--- a/arch/mips/pmc-sierra/yosemite/irq.c
+++ b/arch/mips/pmc-sierra/yosemite/irq.c
@@ -2,6 +2,8 @@
* Copyright (C) 2003 PMC-Sierra Inc.
* Author: Manish Lachwani (lachwani@pmc-sierra.com)
*
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
@@ -55,7 +57,6 @@
#define HYPERTRANSPORT_INTC 0x7a /* INTC# */
#define HYPERTRANSPORT_INTD 0x7b /* INTD# */
-extern asmlinkage void titan_handle_int(void);
extern void jaguar_mailbox_irq(struct pt_regs *);
/*
@@ -125,6 +126,35 @@ asmlinkage void do_extended_irq(struct pt_regs *regs)
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int cause = read_c0_cause();
+ unsigned int status = read_c0_status();
+ unsigned int pending = cause & status;
+
+ if (pending & STATUSF_IP7) {
+ do_IRQ(7, regs);
+ } else if (pending & STATUSF_IP2) {
+#ifdef CONFIG_HYPERTRANSPORT
+ ll_ht_smp_irq_handler(2, regs);
+#else
+ do_IRQ(2, regs);
+#endif
+ } else if (pending & STATUSF_IP3) {
+ do_IRQ(3, regs);
+ } else if (pending & STATUSF_IP4) {
+ do_IRQ(4, regs);
+ } else if (pending & STATUSF_IP5) {
+#ifdef CONFIG_SMP
+ titan_mailbox_irq(regs);
+#else
+ do_IRQ(5, regs);
+#endif
+ } else if (pending & STATUSF_IP6) {
+ do_IRQ(4, regs);
+ }
+}
+
#ifdef CONFIG_KGDB
extern void init_second_port(void);
#endif
@@ -136,7 +166,6 @@ void __init arch_init_irq(void)
{
clear_c0_status(ST0_IM);
- set_except_vector(0, titan_handle_int);
mips_cpu_irq_init(0);
rm7k_cpu_irq_init(8);
rm9k_cpu_irq_init(12);
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
index 8bce711575d..3f724d661bd 100644
--- a/arch/mips/pmc-sierra/yosemite/setup.c
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -198,8 +198,8 @@ static void __init py_rtc_setup(void)
if (!m48t37_base)
printk(KERN_ERR "Mapping the RTC failed\n");
- rtc_get_time = m48t37y_get_time;
- rtc_set_time = m48t37y_set_time;
+ rtc_mips_get_time = m48t37y_get_time;
+ rtc_mips_set_time = m48t37y_set_time;
write_seqlock(&xtime_lock);
xtime.tv_sec = m48t37y_get_time();
diff --git a/arch/mips/qemu/Makefile b/arch/mips/qemu/Makefile
index 6a8e8bcef55..730f459f3e9 100644
--- a/arch/mips/qemu/Makefile
+++ b/arch/mips/qemu/Makefile
@@ -2,6 +2,6 @@
# Makefile for Qemu specific kernel interface routines under Linux.
#
-obj-y = q-firmware.o q-int.o q-irq.o q-mem.o q-setup.o
+obj-y = q-firmware.o q-irq.o q-mem.o q-setup.o
obj-$(CONFIG_SMP) += q-smp.o
diff --git a/arch/mips/qemu/q-int.S b/arch/mips/qemu/q-int.S
deleted file mode 100644
index 6e3dfe5eb14..00000000000
--- a/arch/mips/qemu/q-int.S
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Qemu interrupt handler code.
- *
- * Copyright (C) 2005 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .align 5
- NESTED(qemu_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- move a0, sp
- PTR_LA ra, ret_from_irq
- j do_qemu_int
- END(qemu_handle_int)
diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c
index 2c4e0704ff1..3352374c4c7 100644
--- a/arch/mips/qemu/q-irq.c
+++ b/arch/mips/qemu/q-irq.c
@@ -9,7 +9,7 @@
extern asmlinkage void qemu_handle_int(void);
-asmlinkage void do_qemu_int(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned int pending = read_c0_status() & read_c0_cause();
@@ -29,7 +29,6 @@ asmlinkage void do_qemu_int(struct pt_regs *regs)
void __init arch_init_irq(void)
{
- set_except_vector(0, qemu_handle_int);
mips_hpt_frequency = QEMU_C0_COUNTER_CLOCK; /* 100MHz */
init_i8259_irqs();
diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
index eb0820fe50b..6aa4c0cd169 100644
--- a/arch/mips/sgi-ip22/Makefile
+++ b/arch/mips/sgi-ip22/Makefile
@@ -3,7 +3,7 @@
# under Linux.
#
-obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-irq.o ip22-berr.o \
+obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \
ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o
obj-$(CONFIG_EISA) += ip22-eisa.o
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index d16fb43b1a9..fc6a7e2b189 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -37,7 +37,6 @@ static char lc1msk_to_irqnr[256];
static char lc2msk_to_irqnr[256];
static char lc3msk_to_irqnr[256];
-extern asmlinkage void indyIRQ(void);
extern int ip22_eisa_init(void);
static void enable_local0_irq(unsigned int irq)
@@ -224,7 +223,7 @@ static struct hw_interrupt_type ip22_local3_irq_type = {
.end = end_local3_irq,
};
-void indy_local0_irqdispatch(struct pt_regs *regs)
+static void indy_local0_irqdispatch(struct pt_regs *regs)
{
u8 mask = sgint->istat0 & sgint->imask0;
u8 mask2;
@@ -242,7 +241,7 @@ void indy_local0_irqdispatch(struct pt_regs *regs)
return;
}
-void indy_local1_irqdispatch(struct pt_regs *regs)
+static void indy_local1_irqdispatch(struct pt_regs *regs)
{
u8 mask = sgint->istat1 & sgint->imask1;
u8 mask2;
@@ -262,7 +261,7 @@ void indy_local1_irqdispatch(struct pt_regs *regs)
extern void ip22_be_interrupt(int irq, struct pt_regs *regs);
-void indy_buserror_irq(struct pt_regs *regs)
+static void indy_buserror_irq(struct pt_regs *regs)
{
int irq = SGI_BUSERR_IRQ;
@@ -307,6 +306,56 @@ static struct irqaction map1_cascade = {
#define SGI_INTERRUPTS SGINT_LOCAL3
#endif
+extern void indy_r4k_timer_interrupt(struct pt_regs *regs);
+extern void indy_8254timer_irq(struct pt_regs *regs);
+
+/*
+ * IRQs on the INDY look basically (barring software IRQs which we don't use
+ * at all) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 Local IRQ level zero
+ * 3 Local IRQ level one
+ * 4 8254 Timer zero
+ * 5 8254 Timer one
+ * 6 Bus Error
+ * 7 R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Local IRQ zero
+ * Local IRQ one
+ * Bus Error
+ * 8254 Timer zero
+ * Lowest ---- 8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause();
+
+ /*
+ * First we check for r4k counter/timer IRQ.
+ */
+ if (pending & CAUSEF_IP7)
+ indy_r4k_timer_interrupt(regs);
+ else if (pending & CAUSEF_IP2)
+ indy_local0_irqdispatch(regs);
+ else if (pending & CAUSEF_IP3)
+ indy_local1_irqdispatch(regs);
+ else if (pending & CAUSEF_IP6)
+ indy_buserror_irq(regs);
+ else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
+ indy_8254timer_irq(regs);
+}
+
extern void mips_cpu_irq_init(unsigned int irq_base);
void __init arch_init_irq(void)
@@ -369,8 +418,6 @@ void __init arch_init_irq(void)
sgint->cmeimask0 = 0;
sgint->cmeimask1 = 0;
- set_except_vector(0, indyIRQ);
-
/* init CPU irqs */
mips_cpu_irq_init(SGINT_CPU);
diff --git a/arch/mips/sgi-ip22/ip22-irq.S b/arch/mips/sgi-ip22/ip22-irq.S
deleted file mode 100644
index 6ccbd9e1d96..00000000000
--- a/arch/mips/sgi-ip22/ip22-irq.S
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * ip22-irq.S: Interrupt exception dispatch code for FullHouse and
- * Guiness.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- */
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- * all the pending IRQ bits in the cause register is _NOT_ the answer, the
- * common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- * would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- * between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the INDY look basically (barring software IRQs
- * which we don't use at all) like:
- *
- * MIPS IRQ Source
- * -------- ------
- * 0 Software (ignored)
- * 1 Software (ignored)
- * 2 Local IRQ level zero
- * 3 Local IRQ level one
- * 4 8254 Timer zero
- * 5 8254 Timer one
- * 6 Bus Error
- * 7 R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ---- R4k Timer
- * Local IRQ zero
- * Local IRQ one
- * Bus Error
- * 8254 Timer zero
- * Lowest ---- 8254 Timer one
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
- .text
- .set noreorder
- .set noat
- .align 5
- NESTED(indyIRQ, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- mfc0 s0, CP0_CAUSE # get irq mask
-
- /* First we check for r4k counter/timer IRQ. */
- andi a0, s0, CAUSEF_IP7
- beq a0, zero, 1f
- andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero
-
- /* Wheee, a timer interrupt. */
- jal indy_r4k_timer_interrupt
- move a0, sp # delay slot
- j ret_from_irq
- nop # delay slot
-
-1:
- beq a0, zero, 1f
- andi a0, s0, CAUSEF_IP3 # delay slot, check local level one
-
- /* Wheee, local level zero interrupt. */
- jal indy_local0_irqdispatch
- move a0, sp # delay slot
-
- j ret_from_irq
- nop # delay slot
-
-1:
- beq a0, zero, 1f
- andi a0, s0, CAUSEF_IP6 # delay slot, check bus error
-
- /* Wheee, local level one interrupt. */
- jal indy_local1_irqdispatch
- move a0, sp # delay slot
- j ret_from_irq
- nop # delay slot
-
-1:
- beq a0, zero, 1f
- andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) # delay slot
-
- /* Wheee, an asynchronous bus error... */
- jal indy_buserror_irq
- move a0, sp # delay slot
- j ret_from_irq
- nop # delay slot
-
-1:
- /* Here by mistake? It is possible, that by the time we take
- * the exception the IRQ pin goes low, so just leave if this
- * is the case.
- */
- beq a0, zero, 1f
- nop # delay slot
-
- /* Must be one of the 8254 timers... */
- jal indy_8254timer_irq
- move a0, sp # delay slot
-1:
- j ret_from_irq
- nop # delay slot
- END(indyIRQ)
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index 92a3b3c15ed..a9c58e067b5 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -238,7 +238,7 @@ static int __init reboot_setup(void)
request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL);
init_timer(&blink_timer);
blink_timer.function = blink_timeout;
- notifier_chain_register(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
return 0;
}
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index b7300cc5c5a..cca688ad64a 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -212,8 +212,8 @@ static void indy_timer_setup(struct irqaction *irq)
void __init ip22_time_init(void)
{
/* setup hookup functions */
- rtc_get_time = indy_rtc_get_time;
- rtc_set_time = indy_rtc_set_time;
+ rtc_mips_get_time = indy_rtc_get_time;
+ rtc_mips_set_time = indy_rtc_set_time;
board_time_init = indy_time_init;
board_timer_setup = indy_timer_setup;
diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile
index 4ba340780c3..686ba14e288 100644
--- a/arch/mips/sgi-ip27/Makefile
+++ b/arch/mips/sgi-ip27/Makefile
@@ -2,7 +2,7 @@
# Makefile for the IP27 specific kernel interface routines under Linux.
#
-obj-y := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \
+obj-y := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o \
ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o \
ip27-timer.o ip27-hubio.o ip27-xtalk.o
diff --git a/arch/mips/sgi-ip27/TODO b/arch/mips/sgi-ip27/TODO
index 32106131b0d..19f1512c8f2 100644
--- a/arch/mips/sgi-ip27/TODO
+++ b/arch/mips/sgi-ip27/TODO
@@ -9,10 +9,6 @@ ip27-init.c:find_lbaord_real. DONE
in irix?
6. Investigate why things do not work without the setup_test() call
being invoked on all nodes in ip27-memory.c.
-7. Too many CLIs in the locore handlers :
-For the low level handlers set up by set_except_vector(),
-__tlb_refill_debug_tramp, __xtlb_refill_debug_tramp and cacheerror,
-investigate whether the code should do CLI, STI or KMODE.
8. Too many do_page_faults invoked - investigate.
9. start_thread must turn off UX64 ... and define tlb_refill_debug.
10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable
diff --git a/arch/mips/sgi-ip27/ip27-irq-glue.S b/arch/mips/sgi-ip27/ip27-irq-glue.S
deleted file mode 100644
index c304df715e0..00000000000
--- a/arch/mips/sgi-ip27/ip27-irq-glue.S
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1999 Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
- .text
- .align 5
-NESTED(ip27_irq, PT_SIZE, sp)
- SAVE_ALL
- CLI
-
- mfc0 s0, CP0_CAUSE
- mfc0 t0, CP0_STATUS
- and s0, t0
- move a0, sp
- PTR_LA ra, ret_from_irq
-
- /* First check for RT interrupt. */
- andi t0, s0, CAUSEF_IP4
- bnez t0, ip4
- andi t0, s0, CAUSEF_IP2
- bnez t0, ip2
- andi t0, s0, CAUSEF_IP3
- bnez t0, ip3
- andi t0, s0, CAUSEF_IP5
- bnez t0, ip5
- andi t0, s0, CAUSEF_IP6
- bnez t0, ip6
- j ra
-
-ip2: j ip27_do_irq_mask0 # PI_INT_PEND_0 or CC_PEND_{A|B}
-ip3: j ip27_do_irq_mask1 # PI_INT_PEND_1
-ip4: j ip27_rt_timer_interrupt
-ip5: j ip27_prof_timer
-ip6: j ip27_hub_error
-
- END(ip27_irq)
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 2854ac4c9be..2e643d2f51c 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -130,7 +130,7 @@ static int ms1bit(unsigned long x)
* Kanoj 05.13.00
*/
-void ip27_do_irq_mask0(struct pt_regs *regs)
+static void ip27_do_irq_mask0(struct pt_regs *regs)
{
int irq, swlevel;
hubreg_t pend0, mask0;
@@ -171,7 +171,7 @@ void ip27_do_irq_mask0(struct pt_regs *regs)
LOCAL_HUB_L(PI_INT_PEND0);
}
-void ip27_do_irq_mask1(struct pt_regs *regs)
+static void ip27_do_irq_mask1(struct pt_regs *regs)
{
int irq, swlevel;
hubreg_t pend1, mask1;
@@ -196,12 +196,12 @@ void ip27_do_irq_mask1(struct pt_regs *regs)
LOCAL_HUB_L(PI_INT_PEND1);
}
-void ip27_prof_timer(struct pt_regs *regs)
+static void ip27_prof_timer(struct pt_regs *regs)
{
panic("CPU %d got a profiling interrupt", smp_processor_id());
}
-void ip27_hub_error(struct pt_regs *regs)
+static void ip27_hub_error(struct pt_regs *regs)
{
panic("CPU %d got a hub error interrupt", smp_processor_id());
}
@@ -421,9 +421,26 @@ int __devinit request_bridge_irq(struct bridge_controller *bc)
return irq;
}
+extern void ip27_rt_timer_interrupt(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned long pending = read_c0_cause() & read_c0_status();
+
+ if (pending & CAUSEF_IP4)
+ ip27_rt_timer_interrupt(regs);
+ else if (pending & CAUSEF_IP2) /* PI_INT_PEND_0 or CC_PEND_{A|B} */
+ ip27_do_irq_mask0(regs);
+ else if (pending & CAUSEF_IP3) /* PI_INT_PEND_1 */
+ ip27_do_irq_mask1(regs);
+ else if (pending & CAUSEF_IP5)
+ ip27_prof_timer(regs);
+ else if (pending & CAUSEF_IP6)
+ ip27_hub_error(regs);
+}
+
void __init arch_init_irq(void)
{
- set_except_vector(0, ip27_irq);
}
void install_ipi(void)
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index e0d095daa5e..6c00dce9f73 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -19,6 +19,7 @@
#include <linux/nodemask.h>
#include <linux/swap.h>
#include <linux/bootmem.h>
+#include <linux/pfn.h>
#include <asm/page.h>
#include <asm/sections.h>
@@ -28,8 +29,6 @@
#include <asm/sn/sn_private.h>
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-
#define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT)
#define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT)
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index cddf1cedf00..36b662e27b6 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -122,7 +122,7 @@ again:
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
- if (rtc_set_time(xtime.tv_sec) == 0) {
+ if (rtc_mips_set_time(xtime.tv_sec) == 0) {
last_rtc_update = xtime.tv_sec;
} else {
last_rtc_update = xtime.tv_sec - 600;
diff --git a/arch/mips/sgi-ip32/Makefile b/arch/mips/sgi-ip32/Makefile
index 470898f4afe..530bf848c3d 100644
--- a/arch/mips/sgi-ip32/Makefile
+++ b/arch/mips/sgi-ip32/Makefile
@@ -3,7 +3,7 @@
# under Linux.
#
-obj-y += ip32-berr.o ip32-irq.o ip32-irq-glue.o ip32-setup.o ip32-reset.o \
+obj-y += ip32-berr.o ip32-irq.o ip32-setup.o ip32-reset.o \
crime.o ip32-memory.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sgi-ip32/ip32-irq-glue.S b/arch/mips/sgi-ip32/ip32-irq-glue.S
deleted file mode 100644
index 200924e1c4f..00000000000
--- a/arch/mips/sgi-ip32/ip32-irq-glue.S
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Low level interrupt handler for the SGI O2 aka IP32 aka Moosehead
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000 Harald Koerfgen
- * Copyright (C) 2001 Keith M Wesolowski
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-#include <asm/addrspace.h>
-
- .text
- .set noreorder
- .set noat
- .align 5
- NESTED(ip32_handle_int, PT_SIZE, ra)
- .set noat
- SAVE_ALL
- CLI # TEST: interrupts should be off
- .set at
- .set noreorder
-
- mfc0 s0,CP0_CAUSE
-
- andi t1, s0, IE_IRQ0
- bnez t1, handle_irq0
- andi t1, s0, IE_IRQ1
- bnez t1, handle_irq1
- andi t1, s0, IE_IRQ2
- bnez t1, handle_irq2
- andi t1, s0, IE_IRQ3
- bnez t1, handle_irq3
- andi t1, s0, IE_IRQ4
- bnez t1, handle_irq4
- andi t1, s0, IE_IRQ5
- bnez t1, handle_irq5
- nop
-
- /* Either someone has triggered the "software interrupts"
- * or we lost an interrupt somehow. Ignore it.
- */
- j ret_from_irq
- nop
-
-handle_irq0:
- jal ip32_irq0
- move a0, sp
- j ret_from_irq
- nop
-
-handle_irq1:
- jal ip32_irq1
- move a0, sp
- j ret_from_irq
- nop
-
-handle_irq2:
- jal ip32_irq2
- move a0, sp
- j ret_from_irq
- nop
-
-handle_irq3:
- jal ip32_irq3
- move a0, sp
- j ret_from_irq
- nop
-
-handle_irq4:
- jal ip32_irq4
- move a0, sp
- j ret_from_irq
- nop
-
-handle_irq5:
- jal ip32_irq5
- move a0, sp
- j ret_from_irq
- nop
-
- END(ip32_handle_int)
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c
index 2eb22d692ed..8ba08047d16 100644
--- a/arch/mips/sgi-ip32/ip32-irq.c
+++ b/arch/mips/sgi-ip32/ip32-irq.c
@@ -31,12 +31,12 @@
/* issue a PIO read to make sure no PIO writes are pending */
static void inline flush_crime_bus(void)
{
- volatile unsigned long junk = crime->control;
+ crime->control;
}
static void inline flush_mace_bus(void)
{
- volatile unsigned long junk = mace->perif.ctrl.misc;
+ mace->perif.ctrl.misc;
}
#undef DEBUG_IRQ
@@ -130,8 +130,6 @@ struct irqaction memerr_irq = { crime_memerr_intr, SA_INTERRUPT,
struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT,
CPU_MASK_NONE, "CRIME CPU error", NULL, NULL };
-extern void ip32_handle_int(void);
-
/*
* For interrupts wired from a single device to the CPU. Only the clock
* uses this it seems, which is IRQ 0 and IP7.
@@ -503,48 +501,67 @@ static void ip32_unknown_interrupt(struct pt_regs *regs)
/* CRIME 1.1 appears to deliver all interrupts to this one pin. */
/* change this to loop over all edge-triggered irqs, exception masked out ones */
-void ip32_irq0(struct pt_regs *regs)
+static void ip32_irq0(struct pt_regs *regs)
{
uint64_t crime_int;
int irq = 0;
crime_int = crime->istat & crime_mask;
- irq = ffs(crime_int);
- crime_int = 1 << (irq - 1);
+ irq = __ffs(crime_int);
+ crime_int = 1 << irq;
if (crime_int & CRIME_MACEISA_INT_MASK) {
unsigned long mace_int = mace->perif.ctrl.istat;
- irq = ffs(mace_int & maceisa_mask) + 32;
+ irq = __ffs(mace_int & maceisa_mask) + 32;
}
+ irq++;
DBG("*irq %u*\n", irq);
do_IRQ(irq, regs);
}
-void ip32_irq1(struct pt_regs *regs)
+static void ip32_irq1(struct pt_regs *regs)
{
ip32_unknown_interrupt(regs);
}
-void ip32_irq2(struct pt_regs *regs)
+static void ip32_irq2(struct pt_regs *regs)
{
ip32_unknown_interrupt(regs);
}
-void ip32_irq3(struct pt_regs *regs)
+static void ip32_irq3(struct pt_regs *regs)
{
ip32_unknown_interrupt(regs);
}
-void ip32_irq4(struct pt_regs *regs)
+static void ip32_irq4(struct pt_regs *regs)
{
ip32_unknown_interrupt(regs);
}
-void ip32_irq5(struct pt_regs *regs)
+static void ip32_irq5(struct pt_regs *regs)
{
ll_timer_interrupt(IP32_R4K_TIMER_IRQ, regs);
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause();
+
+ if (likely(pending & IE_IRQ0))
+ ip32_irq0(regs);
+ else if (unlikely(pending & IE_IRQ1))
+ ip32_irq1(regs);
+ else if (unlikely(pending & IE_IRQ2))
+ ip32_irq2(regs);
+ else if (unlikely(pending & IE_IRQ3))
+ ip32_irq3(regs);
+ else if (unlikely(pending & IE_IRQ4))
+ ip32_irq4(regs);
+ else if (likely(pending & IE_IRQ5))
+ ip32_irq5(regs);
+}
+
void __init arch_init_irq(void)
{
unsigned int irq;
@@ -556,7 +573,6 @@ void __init arch_init_irq(void)
crime->soft_int = 0;
mace->perif.ctrl.istat = 0;
mace->perif.ctrl.imask = 0;
- set_except_vector(0, ip32_handle_int);
for (irq = 0; irq <= IP32_IRQ_MAX; irq++) {
hw_irq_controller *controller;
diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c
index 0c948008b02..ab9d9cef089 100644
--- a/arch/mips/sgi-ip32/ip32-reset.c
+++ b/arch/mips/sgi-ip32/ip32-reset.c
@@ -193,7 +193,7 @@ static __init int ip32_reboot_setup(void)
init_timer(&blink_timer);
blink_timer.function = blink_timeout;
- notifier_chain_register(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL);
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index 2f50c79b788..a2dd8ae1ea8 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -91,8 +91,8 @@ void __init plat_setup(void)
{
board_be_init = ip32_be_init;
- rtc_get_time = mc146818_get_cmos_time;
- rtc_set_mmss = mc146818_set_rtc_mmss;
+ rtc_mips_get_time = mc146818_get_cmos_time;
+ rtc_mips_set_mmss = mc146818_set_rtc_mmss;
board_time_init = ip32_time_init;
board_timer_setup = ip32_timer_setup;
diff --git a/arch/mips/sibyte/bcm1480/Makefile b/arch/mips/sibyte/bcm1480/Makefile
index 538d5a51ae9..7b36ff3873b 100644
--- a/arch/mips/sibyte/bcm1480/Makefile
+++ b/arch/mips/sibyte/bcm1480/Makefile
@@ -1,4 +1,4 @@
-obj-y := setup.o irq.o irq_handler.o time.o
+obj-y := setup.o irq.o time.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 9cf7d713b13..e61760b14d9 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -187,9 +187,6 @@ static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
#endif
-/* Defined in arch/mips/sibyte/bcm1480/irq_handler.S */
-extern void bcm1480_irq_handler(void);
-
/*****************************************************************************/
static unsigned int startup_bcm1480_irq(unsigned int irq)
@@ -422,7 +419,6 @@ void __init arch_init_irq(void)
#endif
/* Enable necessary IPs, disable the rest */
change_c0_status(ST0_IM, imask);
- set_except_vector(0, bcm1480_irq_handler);
#ifdef CONFIG_KGDB
if (kgdb_flag) {
@@ -473,3 +469,76 @@ void bcm1480_kgdb_interrupt(struct pt_regs *regs)
}
#endif /* CONFIG_KGDB */
+
+static inline int dclz(unsigned long long x)
+{
+ int lz;
+
+ __asm__ (
+ " .set push \n"
+ " .set mips64 \n"
+ " dclz %0, %1 \n"
+ " .set pop \n"
+ : "=r" (lz)
+ : "r" (x));
+
+ return lz;
+}
+
+extern void bcm1480_timer_interrupt(struct pt_regs *regs);
+extern void bcm1480_mailbox_interrupt(struct pt_regs *regs);
+extern void bcm1480_kgdb_interrupt(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending;
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+ /* Set compare to count to silence count/compare timer interrupts */
+ write_c0_compare(read_c0_count());
+#endif
+
+ pending = read_c0_cause();
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+ if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */
+ sbprof_cpu_intr(exception_epc(regs));
+#endif
+
+ if (pending & CAUSEF_IP4)
+ bcm1480_timer_interrupt(regs);
+
+#ifdef CONFIG_SMP
+ if (pending & CAUSEF_IP3)
+ bcm1480_mailbox_interrupt(regs);
+#endif
+
+#ifdef CONFIG_KGDB
+ if (pending & CAUSEF_IP6)
+ bcm1480_kgdb_interrupt(regs); /* KGDB (uart 1) */
+#endif
+
+ if (pending & CAUSEF_IP2) {
+ unsigned long long mask_h, mask_l;
+ unsigned long base;
+
+ /*
+ * Default...we've hit an IP[2] interrupt, which means we've
+ * got to check the 1480 interrupt registers to figure out what
+ * to do. Need to detect which CPU we're on, now that
+ * smp_affinity is supported.
+ */
+ base = A_BCM1480_IMR_MAPPER(smp_processor_id());
+ mask_h = __raw_readq(
+ IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H));
+ mask_l = __raw_readq(
+ IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L));
+
+ if (!mask_h) {
+ if (mask_h ^ 1)
+ do_IRQ(63 - dclz(mask_h), regs);
+ else
+ do_IRQ(127 - dclz(mask_l), regs);
+ }
+ }
+}
diff --git a/arch/mips/sibyte/bcm1480/irq_handler.S b/arch/mips/sibyte/bcm1480/irq_handler.S
deleted file mode 100644
index 408db88d050..00000000000
--- a/arch/mips/sibyte/bcm1480/irq_handler.S
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.
- *
- * 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.
- */
-
-/*
- * bcm1480_irq_handler() is the routine that is actually called when an
- * interrupt occurs. It is installed as the exception vector handler in
- * init_IRQ() in arch/mips/sibyte/bcm1480/irq.c
- *
- * In the handle we figure out which interrupts need handling, and use that
- * to call the dispatcher, which will take care of actually calling
- * registered handlers
- *
- * Note that we take care of all raised interrupts in one go at the handler.
- * This is more BSDish than the Indy code, and also, IMHO, more sane.
- */
-#include <linux/config.h>
-
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/sibyte/sb1250_defs.h>
-#include <asm/sibyte/bcm1480_regs.h>
-#include <asm/sibyte/bcm1480_int.h>
-
-/*
- * What a pain. We have to be really careful saving the upper 32 bits of any
- * register across function calls if we don't want them trashed--since were
- * running in -o32, the calling routing never saves the full 64 bits of a
- * register across a function call. Being the interrupt handler, we're
- * guaranteed that interrupts are disabled during this code so we don't have
- * to worry about random interrupts blasting the high 32 bits.
- */
-
- .text
- .set push
- .set noreorder
- .set noat
- .set mips64
- #.set mips4
- .align 5
- NESTED(bcm1480_irq_handler, PT_SIZE, sp)
- SAVE_ALL
- CLI
-
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
- /* Set compare to count to silence count/compare timer interrupts */
- mfc0 t1, CP0_COUNT
- mtc0 t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
-#endif
- /* Read cause */
- mfc0 s0, CP0_CAUSE
-
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
- /* Cpu performance counter interrupt is routed to IP[7] */
- andi t1, s0, CAUSEF_IP7
- beqz t1, 0f
- srl t1, s0, (CAUSEB_BD-2) /* Shift BD bit to bit 2 */
- and t1, t1, 0x4 /* mask to get just BD bit */
-#ifdef CONFIG_MIPS64
- dmfc0 a0, CP0_EPC
- daddu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */
-#else
- mfc0 a0, CP0_EPC
- addu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */
-#endif
- jal sbprof_cpu_intr
- nop
- j ret_from_irq
- nop
-0:
-#endif
-
- /* Timer interrupt is routed to IP[4] */
- andi t1, s0, CAUSEF_IP4
- beqz t1, 1f
- nop
- jal bcm1480_timer_interrupt
- move a0, sp /* Pass the registers along */
- j ret_from_irq
- nop /* delay slot */
-1:
-
-#ifdef CONFIG_SMP
- /* Mailbox interrupt is routed to IP[3] */
- andi t1, s0, CAUSEF_IP3
- beqz t1, 2f
- nop
- jal bcm1480_mailbox_interrupt
- move a0, sp
- j ret_from_irq
- nop /* delay slot */
-2:
-#endif
-
-#ifdef CONFIG_KGDB
- /* KGDB (uart 1) interrupt is routed to IP[6] */
- andi t1, s0, CAUSEF_IP6
- beqz t1, 3f
- nop /* delay slot */
- jal bcm1480_kgdb_interrupt
- move a0, sp
- j ret_from_irq
- nop /* delay slot */
-3:
-#endif
-
- and t1, s0, CAUSEF_IP2
- beqz t1, 9f
- nop
-
- /*
- * Default...we've hit an IP[2] interrupt, which means we've got
- * to check the 1480 interrupt registers to figure out what to do
- * Need to detect which CPU we're on, now that smp_affinity is
- * supported.
- */
- PTR_LA v0, CKSEG1 + A_BCM1480_IMR_CPU0_BASE
-#ifdef CONFIG_SMP
- lw t1, TI_CPU($28)
- sll t1, t1, BCM1480_IMR_REGISTER_SPACING_SHIFT
- addu v0, v0, t1
-#endif
-
- /* Read IP[2] status (get both high and low halves of status) */
- ld s0, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H(v0)
- ld s1, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L(v0)
-
- move s2, zero /* intr number */
- li s3, 64
-
- beqz s0, 9f /* No interrupts. Return. */
- move a1, sp
-
- xori s4, s0, 1 /* if s0 (_H) == 1, it's a low intr, so... */
- movz s2, s3, s4 /* start the intr number at 64, and */
- movz s0, s1, s4 /* look at the low status value. */
-
- dclz s1, s0 /* Find the next interrupt. */
- dsubu a0, zero, s1
- daddiu a0, a0, 63
- jal do_IRQ
- daddu a0, a0, s2
-
-9: j ret_from_irq
- nop
-
- .set pop
- END(bcm1480_irq_handler)
diff --git a/arch/mips/sibyte/sb1250/Makefile b/arch/mips/sibyte/sb1250/Makefile
index a8af8469758..a2fdbd62f8a 100644
--- a/arch/mips/sibyte/sb1250/Makefile
+++ b/arch/mips/sibyte/sb1250/Makefile
@@ -1,4 +1,4 @@
-obj-y := setup.o irq.o irq_handler.o time.o
+obj-y := setup.o irq.o time.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SIBYTE_TBPROF) += bcm1250_tbprof.o
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 589537bfcc3..0f6e54db488 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -163,10 +163,6 @@ static void sb1250_set_affinity(unsigned int irq, cpumask_t mask)
}
#endif
-
-/* Defined in arch/mips/sibyte/sb1250/irq_handler.S */
-extern void sb1250_irq_handler(void);
-
/*****************************************************************************/
static unsigned int startup_sb1250_irq(unsigned int irq)
@@ -379,7 +375,6 @@ void __init arch_init_irq(void)
#endif
/* Enable necessary IPs, disable the rest */
change_c0_status(ST0_IM, imask);
- set_except_vector(0, sb1250_irq_handler);
#ifdef CONFIG_KGDB
if (kgdb_flag) {
@@ -409,7 +404,7 @@ void __init arch_init_irq(void)
#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
-void sb1250_kgdb_interrupt(struct pt_regs *regs)
+static void sb1250_kgdb_interrupt(struct pt_regs *regs)
{
/*
* Clear break-change status (allow some time for the remote
@@ -424,3 +419,74 @@ void sb1250_kgdb_interrupt(struct pt_regs *regs)
}
#endif /* CONFIG_KGDB */
+
+static inline int dclz(unsigned long long x)
+{
+ int lz;
+
+ __asm__ (
+ " .set push \n"
+ " .set mips64 \n"
+ " dclz %0, %1 \n"
+ " .set pop \n"
+ : "=r" (lz)
+ : "r" (x));
+
+ return lz;
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending;
+
+#ifdef CONFIG_SIBYTE_SB1250_PROF
+ /* Set compare to count to silence count/compare timer interrupts */
+ write_c0_count(read_c0_count());
+#endif
+
+ /*
+ * What a pain. We have to be really careful saving the upper 32 bits
+ * of any * register across function calls if we don't want them
+ * trashed--since were running in -o32, the calling routing never saves
+ * the full 64 bits of a register across a function call. Being the
+ * interrupt handler, we're guaranteed that interrupts are disabled
+ * during this code so we don't have to worry about random interrupts
+ * blasting the high 32 bits.
+ */
+
+ pending = read_c0_cause();
+
+#ifdef CONFIG_SIBYTE_SB1250_PROF
+ if (pending & CAUSEF_IP7) { /* Cpu performance counter interrupt */
+ sbprof_cpu_intr(exception_epc(regs));
+ }
+#endif
+
+ if (pending & CAUSEF_IP4)
+ sb1250_timer_interrupt(regs);
+
+#ifdef CONFIG_SMP
+ if (pending & CAUSEF_IP3)
+ sb1250_mailbox_interrupt(regs);
+#endif
+
+#ifdef CONFIG_KGDB
+ if (pending & CAUSEF_IP6) /* KGDB (uart 1) */
+ sb1250_kgdb_interrupt(regs);
+#endif
+
+ if (pending & CAUSEF_IP2) {
+ unsigned long long mask;
+
+ /*
+ * Default...we've hit an IP[2] interrupt, which means we've
+ * got to check the 1250 interrupt registers to figure out what
+ * to do. Need to detect which CPU we're on, now that
+ ~ smp_affinity is supported.
+ */
+ mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
+ R_IMR_INTERRUPT_STATUS_BASE)));
+ if (mask)
+ do_IRQ(63 - dclz(mask), regs);
+ }
+}
diff --git a/arch/mips/sibyte/sb1250/irq_handler.S b/arch/mips/sibyte/sb1250/irq_handler.S
deleted file mode 100644
index 60edc8fb302..00000000000
--- a/arch/mips/sibyte/sb1250/irq_handler.S
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
- * sb1250_handle_int() is the routine that is actually called when an interrupt
- * occurs. It is installed as the exception vector handler in arch_init_irq()
- * in arch/mips/sibyte/sb1250/irq.c
- *
- * In the handle we figure out which interrupts need handling, and use that to
- * call the dispatcher, which will take care of actually calling registered
- * handlers
- *
- * Note that we take care of all raised interrupts in one go at the handler.
- * This is more BSDish than the Indy code, and also, IMHO, more sane.
- */
-#include <linux/config.h>
-
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/sibyte/sb1250_defs.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_int.h>
-
-/*
- * What a pain. We have to be really careful saving the upper 32 bits of any
- * register across function calls if we don't want them trashed--since were
- * running in -o32, the calling routing never saves the full 64 bits of a
- * register across a function call. Being the interrupt handler, we're
- * guaranteed that interrupts are disabled during this code so we don't have
- * to worry about random interrupts blasting the high 32 bits.
- */
-
- .text
- .set push
- .set noreorder
- .set noat
- .set mips64
- .align 5
- NESTED(sb1250_irq_handler, PT_SIZE, sp)
- SAVE_ALL
- CLI
-
-#ifdef CONFIG_SIBYTE_SB1250_PROF
- /* Set compare to count to silence count/compare timer interrupts */
- mfc0 t1, CP0_COUNT
- mtc0 t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
-#endif
- /* Read cause */
- mfc0 s0, CP0_CAUSE
-
-#ifdef CONFIG_SIBYTE_SB1250_PROF
- /* Cpu performance counter interrupt is routed to IP[7] */
- andi t1, s0, CAUSEF_IP7
- beqz t1, 0f
- srl t1, s0, (CAUSEB_BD-2) /* Shift BD bit to bit 2 */
- and t1, t1, 0x4 /* mask to get just BD bit */
- mfc0 a0, CP0_EPC
- jal sbprof_cpu_intr
- addu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */
- j ret_from_irq
- nop
-0:
-#endif
-
- /* Timer interrupt is routed to IP[4] */
- andi t1, s0, CAUSEF_IP4
- beqz t1, 1f
- nop
- jal sb1250_timer_interrupt
- move a0, sp /* Pass the registers along */
- j ret_from_irq
- nop # delay slot
-1:
-
-#ifdef CONFIG_SMP
- /* Mailbox interrupt is routed to IP[3] */
- andi t1, s0, CAUSEF_IP3
- beqz t1, 2f
- nop
- jal sb1250_mailbox_interrupt
- move a0, sp
- j ret_from_irq
- nop # delay slot
-2:
-#endif
-
-#ifdef CONFIG_KGDB
- /* KGDB (uart 1) interrupt is routed to IP[6] */
- andi t1, s0, CAUSEF_IP6
- beqz t1, 1f
- nop # delay slot
- jal sb1250_kgdb_interrupt
- move a0, sp
- j ret_from_irq
- nop # delay slot
-1:
-#endif
-
- and t1, s0, CAUSEF_IP2
- beqz t1, 4f
- nop
-
- /*
- * Default...we've hit an IP[2] interrupt, which means we've got to
- * check the 1250 interrupt registers to figure out what to do
- * Need to detect which CPU we're on, now that smp_affinity is supported.
- */
- PTR_LA v0, CKSEG1 + A_IMR_CPU0_BASE
-#ifdef CONFIG_SMP
- lw t1, TI_CPU($28)
- sll t1, IMR_REGISTER_SPACING_SHIFT
- addu v0, t1
-#endif
- ld s0, R_IMR_INTERRUPT_STATUS_BASE(v0) /* read IP[2] status */
-
- beqz s0, 4f /* No interrupts. Return */
- move a1, sp
-
-3: dclz s1, s0 /* Find the next interrupt */
- dsubu a0, zero, s1
- daddiu a0, a0, 63
- jal do_IRQ
- nop
-
-4: j ret_from_irq
- nop
-
- .set pop
- END(sb1250_irq_handler)
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index b661d2425a3..4b5f74ff3ed 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -121,14 +121,14 @@ void __init plat_setup(void)
if (xicor_probe()) {
printk("swarm setup: Xicor 1241 RTC detected.\n");
- rtc_get_time = xicor_get_time;
- rtc_set_time = xicor_set_time;
+ rtc_mips_get_time = xicor_get_time;
+ rtc_mips_set_time = xicor_set_time;
}
if (m41t81_probe()) {
printk("swarm setup: M41T81 RTC detected.\n");
- rtc_get_time = m41t81_get_time;
- rtc_set_time = m41t81_set_time;
+ rtc_mips_get_time = m41t81_get_time;
+ rtc_mips_set_time = m41t81_set_time;
}
printk("This kernel optimized for "
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
index 1e5676e4be8..9c7eaa5fb21 100644
--- a/arch/mips/sni/Makefile
+++ b/arch/mips/sni/Makefile
@@ -2,6 +2,6 @@
# Makefile for the SNI specific part of the kernel
#
-obj-y += int-handler.o irq.o pcimt_scache.o reset.o setup.o
+obj-y += irq.o pcimt_scache.o reset.o setup.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sni/int-handler.S b/arch/mips/sni/int-handler.S
deleted file mode 100644
index 2cdc09f55f1..00000000000
--- a/arch/mips/sni/int-handler.S
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SNI RM200 PCI specific interrupt handler code.
- *
- * Copyright (C) 1994, 95, 96, 97, 98, 1999, 2000, 01 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/sni.h>
-#include <asm/stackframe.h>
-
-/*
- * The PCI ASIC has the nasty property that it may delay writes if it is busy.
- * As a consequence from writes that have not graduated when we exit from the
- * interrupt handler we might catch a spurious interrupt. To avoid this we
- * force the PCI ASIC to graduate all writes by executing a read from the
- * PCI bus.
- */
- .set noreorder
- .set noat
- .align 5
- NESTED(sni_rm200_pci_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
-
- /* Blinken light ... */
- lb t0, led_cache
- addiu t0, 1
- sb t0, led_cache
- sb t0, PCIMT_CSLED # write only register
- .data
-led_cache: .byte 0
- .text
-
- mfc0 t0, CP0_STATUS
- mfc0 t1, CP0_CAUSE
- and t0, t1
-
- andi t1, t0, 0x0800 # hardware interrupt 1
- bnez t1, _hwint1
- andi t1, t0, 0x4000 # hardware interrupt 4
- bnez t1, _hwint4
- andi t1, t0, 0x2000 # hardware interrupt 3
- bnez t1, _hwint3
- andi t1, t0, 0x1000 # hardware interrupt 2
- bnez t1, _hwint2
- andi t1, t0, 0x8000 # hardware interrupt 5
- bnez t1, _hwint5
- andi t1, t0, 0x0400 # hardware interrupt 0
- bnez t1, _hwint0
- nop
-
- j restore_all # spurious interrupt
- nop
-
- ##############################################################################
-
-/* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
- button interrupts. */
-_hwint0: jal pciasic_hwint0
- move a0, sp
- j ret_from_irq
- nop
-
-/*
- * hwint 1 deals with EISA and SCSI interrupts
- */
-_hwint1: jal pciasic_hwint1
- move a0, sp
- j ret_from_irq
- nop
-
-
-/*
- * This interrupt was used for the com1 console on the first prototypes;
- * it's unsed otherwise
- */
-_hwint2: jal pciasic_hwint2
- move a0, sp
- j ret_from_irq
- nop
-
-/*
- * hwint 3 are the PCI interrupts A - D
- */
-_hwint3: jal pciasic_hwint3
- move a0, sp
- j ret_from_irq
- nop
-
-/*
- * hwint 4 is used for only the onboard PCnet 32.
- */
-_hwint4: jal pciasic_hwint4
- move a0, sp
- j ret_from_irq
- nop
-
-/* hwint5 is the r4k count / compare interrupt */
-_hwint5: jal pciasic_hwint5
- move a0, sp
- j ret_from_irq
- nop
-
- END(sni_rm200_pci_handle_int)
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
index 952038aa4b9..7365b4853dd 100644
--- a/arch/mips/sni/irq.c
+++ b/arch/mips/sni/irq.c
@@ -19,8 +19,6 @@
DEFINE_SPINLOCK(pciasic_lock);
-extern asmlinkage void sni_rm200_pci_handle_int(void);
-
static void enable_pciasic_irq(unsigned int irq)
{
unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
@@ -71,20 +69,20 @@ static struct hw_interrupt_type pciasic_irq_type = {
* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
* button interrupts. Later ...
*/
-void pciasic_hwint0(struct pt_regs *regs)
+static void pciasic_hwint0(struct pt_regs *regs)
{
panic("Received int0 but no handler yet ...");
}
/* This interrupt was used for the com1 console on the first prototypes. */
-void pciasic_hwint2(struct pt_regs *regs)
+static void pciasic_hwint2(struct pt_regs *regs)
{
/* I think this shouldn't happen on production machines. */
panic("hwint2 and no handler yet");
}
/* hwint5 is the r4k count / compare interrupt */
-void pciasic_hwint5(struct pt_regs *regs)
+static void pciasic_hwint5(struct pt_regs *regs)
{
panic("hwint5 and no handler yet");
}
@@ -105,7 +103,7 @@ static unsigned int ls1bit8(unsigned int x)
*
* The EISA_INT bit in CSITPEND is high active, all others are low active.
*/
-void pciasic_hwint1(struct pt_regs *regs)
+static void pciasic_hwint1(struct pt_regs *regs)
{
u8 pend = *(volatile char *)PCIMT_CSITPEND;
unsigned long flags;
@@ -135,7 +133,7 @@ void pciasic_hwint1(struct pt_regs *regs)
/*
* hwint 3 should deal with the PCI A - D interrupts,
*/
-void pciasic_hwint3(struct pt_regs *regs)
+static void pciasic_hwint3(struct pt_regs *regs)
{
u8 pend = *(volatile char *)PCIMT_CSITPEND;
int irq;
@@ -150,13 +148,34 @@ void pciasic_hwint3(struct pt_regs *regs)
/*
* hwint 4 is used for only the onboard PCnet 32.
*/
-void pciasic_hwint4(struct pt_regs *regs)
+static void pciasic_hwint4(struct pt_regs *regs)
{
clear_c0_status(IE_IRQ4);
do_IRQ(PCIMT_IRQ_ETHERNET, regs);
set_c0_status(IE_IRQ4);
}
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause();
+ static unsigned char led_cache;
+
+ *(volatile unsigned char *) PCIMT_CSLED = ++led_cache;
+
+ if (pending & 0x0800)
+ pciasic_hwint1(regs);
+ else if (pending & 0x4000)
+ pciasic_hwint4(regs);
+ else if (pending & 0x2000)
+ pciasic_hwint3(regs);
+ else if (pending & 0x1000)
+ pciasic_hwint2(regs);
+ else if (pending & 0x8000)
+ pciasic_hwint5(regs);
+ else if (pending & 0x0400)
+ pciasic_hwint0(regs);
+}
+
void __init init_pciasic(void)
{
unsigned long flags;
@@ -176,8 +195,6 @@ void __init arch_init_irq(void)
{
int i;
- set_except_vector(0, sni_rm200_pci_handle_int);
-
init_i8259_irqs(); /* Integrated i8259 */
init_pciasic();
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index 1141fcd13a5..01ba6c581e3 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -164,8 +164,8 @@ static struct pci_controller sni_controller = {
static inline void sni_pcimt_time_init(void)
{
- rtc_get_time = mc146818_get_cmos_time;
- rtc_set_time = mc146818_set_rtc_mmss;
+ rtc_mips_get_time = mc146818_get_cmos_time;
+ rtc_mips_set_time = mc146818_set_rtc_mmss;
}
void __init plat_setup(void)
diff --git a/arch/mips/tx4927/common/Makefile b/arch/mips/tx4927/common/Makefile
index 8fa126b296e..9cb9535ebac 100644
--- a/arch/mips/tx4927/common/Makefile
+++ b/arch/mips/tx4927/common/Makefile
@@ -6,7 +6,7 @@
# unless it's something special (ie not a .c file).
#
-obj-y += tx4927_prom.o tx4927_setup.o tx4927_irq.o tx4927_irq_handler.o
+obj-y += tx4927_prom.o tx4927_setup.o tx4927_irq.o
obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o
obj-$(CONFIG_KGDB) += tx4927_dbgio.o
diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c
index 5ab2e2b7601..8ca68015cf4 100644
--- a/arch/mips/tx4927/common/tx4927_irq.c
+++ b/arch/mips/tx4927/common/tx4927_irq.c
@@ -525,8 +525,6 @@ static void tx4927_irq_pic_end(unsigned int irq)
*/
void __init tx4927_irq_init(void)
{
- extern asmlinkage void tx4927_irq_handler(void);
-
TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "-\n");
TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_cp0_init()\n");
@@ -535,16 +533,12 @@ void __init tx4927_irq_init(void)
TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_pic_init()\n");
tx4927_irq_pic_init();
- TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT,
- "=Calling set_except_vector(tx4927_irq_handler)\n");
- set_except_vector(0, tx4927_irq_handler);
-
TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "+\n");
return;
}
-int tx4927_irq_nested(void)
+static int tx4927_irq_nested(void)
{
int sw_irq = 0;
u32 level2;
@@ -582,3 +576,25 @@ int tx4927_irq_nested(void)
return (sw_irq);
}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause();
+
+ if (pending & STATUSF_IP7) /* cpu timer */
+ do_IRQ(TX4927_IRQ_CPU_TIMER, regs);
+ else if (pending & STATUSF_IP2) { /* tx4927 pic */
+ unsigned int irq = tx4927_irq_nested();
+
+ if (unlikely(irq == 0)) {
+ spurious_interrupt(regs);
+ return;
+ }
+ do_IRQ(irq, regs);
+ } else if (pending & STATUSF_IP0) /* user line 0 */
+ do_IRQ(TX4927_IRQ_USER0, regs);
+ else if (pending & STATUSF_IP1) /* user line 1 */
+ do_IRQ(TX4927_IRQ_USER1, regs);
+ else
+ spurious_interrupt(regs);
+}
diff --git a/arch/mips/tx4927/common/tx4927_irq_handler.S b/arch/mips/tx4927/common/tx4927_irq_handler.S
deleted file mode 100644
index dd3ceda9d71..00000000000
--- a/arch/mips/tx4927/common/tx4927_irq_handler.S
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * linux/arch/mips/tx4927/common/tx4927_irq_handler.S
- *
- * Primary interrupt handler for tx4927 based systems
- *
- * Author: MontaVista Software, Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- * source@mvista.com
- *
- * Copyright 2001-2002 MontaVista Software 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/tx4927/tx4927.h>
-
- .align 5
- NESTED(tx4927_irq_handler, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
-
- mfc0 t0, CP0_CAUSE
- mfc0 t1, CP0_STATUS
- and t0, t1
-
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_ip7
-
- /* IP6..IP3 multiplexed -- do not use */
-
- andi t1, t0, STATUSF_IP2 /* tx4927 pic */
- bnez t1, ll_ip2
-
- andi t1, t0, STATUSF_IP0 /* user line 0 */
- bnez t1, ll_ip0
-
- andi t1, t0, STATUSF_IP1 /* user line 1 */
- bnez t1, ll_ip1
-
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(tx4927_irq_handler)
-
- .align 5
-
-
-ll_ip7:
- li a0, TX4927_IRQ_CPU_TIMER
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_ip2:
- jal tx4927_irq_nested
- nop
- beqz v0, goto_spurious_interrupt
- nop
- move a0, v0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-goto_spurious_interrupt:
- j spurious_interrupt
- nop
-
-ll_ip1:
- li a0, TX4927_IRQ_USER1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_ip0:
- li a0, TX4927_IRQ_USER0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
index 2ad6401d2af..6dcf077f61a 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
@@ -1036,8 +1036,8 @@ toshiba_rbtx4927_time_init(void)
#ifdef CONFIG_RTC_DS1742
- rtc_get_time = rtc_ds1742_get_time;
- rtc_set_time = rtc_ds1742_set_time;
+ rtc_mips_get_time = rtc_ds1742_get_time;
+ rtc_mips_set_time = rtc_ds1742_set_time;
TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
":rtc_ds1742_init()-\n");
diff --git a/arch/mips/tx4938/common/Makefile b/arch/mips/tx4938/common/Makefile
index 74c95c5bcdb..2033ae77f63 100644
--- a/arch/mips/tx4938/common/Makefile
+++ b/arch/mips/tx4938/common/Makefile
@@ -6,6 +6,6 @@
# unless it's something special (ie not a .c file).
#
-obj-y += prom.o setup.o irq.o irq_handler.o rtc_rx5c348.o
+obj-y += prom.o setup.o irq.o rtc_rx5c348.o
obj-$(CONFIG_KGDB) += dbgio.o
diff --git a/arch/mips/tx4938/common/irq.c b/arch/mips/tx4938/common/irq.c
index 4f90d7faf63..873805178d8 100644
--- a/arch/mips/tx4938/common/irq.c
+++ b/arch/mips/tx4938/common/irq.c
@@ -392,11 +392,8 @@ tx4938_irq_pic_end(unsigned int irq)
void __init
tx4938_irq_init(void)
{
- extern asmlinkage void tx4938_irq_handler(void);
-
tx4938_irq_cp0_init();
tx4938_irq_pic_init();
- set_except_vector(0, tx4938_irq_handler);
return;
}
@@ -422,3 +419,21 @@ tx4938_irq_nested(void)
wbflush();
return (sw_irq);
}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status();
+
+ if (pending & STATUSF_IP7)
+ do_IRQ(TX4938_IRQ_CPU_TIMER, regs);
+ else if (pending & STATUSF_IP2) {
+ int irq = tx4938_irq_nested();
+ if (irq)
+ do_IRQ(irq, regs);
+ else
+ spurious_interrupt(regs);
+ } else if (pending & STATUSF_IP1)
+ do_IRQ(TX4938_IRQ_USER1, regs);
+ else if (pending & STATUSF_IP0)
+ do_IRQ(TX4938_IRQ_USER0, regs);
+}
diff --git a/arch/mips/tx4938/common/irq_handler.S b/arch/mips/tx4938/common/irq_handler.S
deleted file mode 100644
index 1b2f72bac42..00000000000
--- a/arch/mips/tx4938/common/irq_handler.S
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * linux/arch/mips/tx4938/common/handler.S
- *
- * Primary interrupt handler for tx4938 based systems
- * 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)
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/tx4938/rbtx4938.h>
-
-
- .align 5
- NESTED(tx4938_irq_handler, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
-
- mfc0 t0, CP0_CAUSE
- mfc0 t1, CP0_STATUS
- and t0, t1
-
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_ip7
-
- /* IP6..IP3 multiplexed -- do not use */
-
- andi t1, t0, STATUSF_IP2 /* tx4938 pic */
- bnez t1, ll_ip2
-
- andi t1, t0, STATUSF_IP1 /* user line 1 */
- bnez t1, ll_ip1
-
- andi t1, t0, STATUSF_IP0 /* user line 0 */
- bnez t1, ll_ip0
-
- .set reorder
-
- nop
- END(tx4938_irq_handler)
-
- .align 5
-
-
-ll_ip7:
- li a0, TX4938_IRQ_CPU_TIMER
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-
-ll_ip2:
- jal tx4938_irq_nested
- nop
- beqz v0, goto_spurious_interrupt
- nop
- move a0, v0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-goto_spurious_interrupt:
- j ret_from_irq
-
-ll_ip1:
- li a0, TX4938_IRQ_USER1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_ip0:
- li a0, TX4938_IRQ_USER0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
diff --git a/arch/mips/tx4938/common/rtc_rx5c348.c b/arch/mips/tx4938/common/rtc_rx5c348.c
index d249edbb6af..07f782fc072 100644
--- a/arch/mips/tx4938/common/rtc_rx5c348.c
+++ b/arch/mips/tx4938/common/rtc_rx5c348.c
@@ -14,6 +14,7 @@
#include <linux/string.h>
#include <linux/rtc.h>
#include <linux/time.h>
+#include <linux/bcd.h>
#include <asm/time.h>
#include <asm/tx4938/spi.h>
@@ -77,17 +78,6 @@ spi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count)
inbufs, incounts, outbufs, outcounts, 0);
}
-/*
- * Conversion between binary and BCD.
- */
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
/* RTC-dependent code for time.c */
static int
@@ -197,6 +187,6 @@ rtc_rx5c348_init(int chipid)
srtc_24h = 1;
/* set the function pointers */
- rtc_get_time = rtc_rx5c348_get_time;
- rtc_set_time = rtc_rx5c348_set_time;
+ rtc_mips_get_time = rtc_rx5c348_get_time;
+ rtc_mips_set_time = rtc_rx5c348_set_time;
}
diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig
index a7add16c9aa..055a2cdfc84 100644
--- a/arch/mips/vr41xx/Kconfig
+++ b/arch/mips/vr41xx/Kconfig
@@ -4,6 +4,8 @@ config CASIO_E55
select DMA_NONCOHERENT
select IRQ_CPU
select ISA
+ select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
config IBM_WORKPAD
@@ -12,6 +14,8 @@ config IBM_WORKPAD
select DMA_NONCOHERENT
select IRQ_CPU
select ISA
+ select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
config NEC_CMBVR4133
@@ -21,6 +25,9 @@ config NEC_CMBVR4133
select DMA_NONCOHERENT
select IRQ_CPU
select HW_HAS_PCI
+ select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
config ROCKHOPPER
bool "Support for Rockhopper baseboard"
@@ -34,6 +41,8 @@ config TANBAC_TB022X
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
+ select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
help
The TANBAC VR4131 multichip module(TB0225) and
@@ -65,6 +74,8 @@ config VICTOR_MPC30X
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
+ select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
config ZAO_CAPCELLA
@@ -73,6 +84,8 @@ config ZAO_CAPCELLA
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
+ select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
config PCI_VR41XX
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
index 9096302a7ec..aa373974c80 100644
--- a/arch/mips/vr41xx/common/Makefile
+++ b/arch/mips/vr41xx/common/Makefile
@@ -2,7 +2,7 @@
# Makefile for common code of the NEC VR4100 series.
#
-obj-y += bcu.o cmu.o icu.o init.o int-handler.o irq.o pmu.o type.o
+obj-y += bcu.o cmu.o icu.o init.o irq.o pmu.o type.o
obj-$(CONFIG_VRC4173) += vrc4173.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S
deleted file mode 100644
index 2b6043f16d0..00000000000
--- a/arch/mips/vr41xx/common/int-handler.S
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * FILE NAME
- * arch/mips/vr41xx/common/int-handler.S
- *
- * BRIEF MODULE DESCRIPTION
- * Interrupt dispatcher for the NEC VR4100 series.
- *
- * Author: Yoichi Yuasa
- * yyuasa@mvista.com or source@mvista.com
- *
- * Copyright 2001 MontaVista Software 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/*
- * Changes:
- * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- * - New creation, NEC VR4100 series are supported.
- *
- * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
- * - Coped with INTASSIGN of NEC VR4133.
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-
- .text
- .set noreorder
-
- .align 5
- NESTED(vr41xx_handle_interrupt, PT_SIZE, ra)
- .set noat
- SAVE_ALL
- CLI
- .set at
- .set noreorder
-
- /*
- * Get the pending interrupts
- */
- mfc0 t0, CP0_CAUSE
- mfc0 t1, CP0_STATUS
- andi t0, 0xff00
- and t0, t0, t1
-
- andi t1, t0, CAUSEF_IP7 # MIPS timer interrupt
- bnez t1, handle_irq
- li a0, 7
-
- andi t1, t0, 0x7800 # check for Int1-4
- beqz t1, 1f
-
- andi t1, t0, CAUSEF_IP3 # check for Int1
- bnez t1, handle_int
- li a0, 3
-
- andi t1, t0, CAUSEF_IP4 # check for Int2
- bnez t1, handle_int
- li a0, 4
-
- andi t1, t0, CAUSEF_IP5 # check for Int3
- bnez t1, handle_int
- li a0, 5
-
- andi t1, t0, CAUSEF_IP6 # check for Int4
- bnez t1, handle_int
- li a0, 6
-
-1:
- andi t1, t0, CAUSEF_IP2 # check for Int0
- bnez t1, handle_int
- li a0, 2
-
- andi t1, t0, CAUSEF_IP0 # check for IP0
- bnez t1, handle_irq
- li a0, 0
-
- andi t1, t0, CAUSEF_IP1 # check for IP1
- bnez t1, handle_irq
- li a0, 1
-
- j spurious_interrupt
- nop
-
-handle_int:
- jal irq_dispatch
- move a1, sp
- j ret_from_irq
- nop
-
-handle_irq:
- jal do_IRQ
- move a1, sp
- j ret_from_irq
- END(vr41xx_handle_interrupt)
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index 61aa264275f..86796bb63c3 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -59,7 +59,7 @@ int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int, struct pt_regs *)
EXPORT_SYMBOL_GPL(cascade_irq);
-asmlinkage void irq_dispatch(unsigned int irq, struct pt_regs *regs)
+static void irq_dispatch(unsigned int irq, struct pt_regs *regs)
{
irq_cascade_t *cascade;
irq_desc_t *desc;
@@ -84,11 +84,32 @@ asmlinkage void irq_dispatch(unsigned int irq, struct pt_regs *regs)
do_IRQ(irq, regs);
}
-extern asmlinkage void vr41xx_handle_interrupt(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (pending & CAUSEF_IP7)
+ do_IRQ(7, regs);
+ else if (pending & 0x7800) {
+ if (pending & CAUSEF_IP3)
+ irq_dispatch(3, regs);
+ else if (pending & CAUSEF_IP4)
+ irq_dispatch(4, regs);
+ else if (pending & CAUSEF_IP5)
+ irq_dispatch(5, regs);
+ else if (pending & CAUSEF_IP6)
+ irq_dispatch(6, regs);
+ } else if (pending & CAUSEF_IP2)
+ irq_dispatch(2, regs);
+ else if (pending & CAUSEF_IP0)
+ do_IRQ(0, regs);
+ else if (pending & CAUSEF_IP1)
+ do_IRQ(1, regs);
+ else
+ spurious_interrupt(regs);
+}
void __init arch_init_irq(void)
{
mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
-
- set_except_vector(0, vr41xx_handle_interrupt);
}
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 6b3c50964ca..910fb3afc0b 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -138,6 +138,37 @@ config 64BIT
enable this option otherwise. The 64bit kernel is significantly bigger
and slower than the 32bit one.
+choice
+ prompt "Kernel page size"
+ default PARISC_PAGE_SIZE_4KB if !64BIT
+ default PARISC_PAGE_SIZE_4KB if 64BIT
+# default PARISC_PAGE_SIZE_16KB if 64BIT
+
+config PARISC_PAGE_SIZE_4KB
+ bool "4KB"
+ help
+ This lets you select the page size of the kernel. For best
+ performance, a page size of 16KB is recommended. For best
+ compatibility with 32bit applications, a page size of 4KB should be
+ selected (the vast majority of 32bit binaries work perfectly fine
+ with a larger page size).
+
+ 4KB For best 32bit compatibility
+ 16KB For best performance
+ 64KB For best performance, might give more overhead.
+
+ If you don't know what to do, choose 4KB.
+
+config PARISC_PAGE_SIZE_16KB
+ bool "16KB (EXPERIMENTAL)"
+ depends on PA8X00 && EXPERIMENTAL
+
+config PARISC_PAGE_SIZE_64KB
+ bool "64KB (EXPERIMENTAL)"
+ depends on PA8X00 && EXPERIMENTAL
+
+endchoice
+
config SMP
bool "Symmetric multi-processing support"
---help---
@@ -177,14 +208,15 @@ config ARCH_DISCONTIGMEM_DEFAULT
def_bool y
depends on ARCH_DISCONTIGMEM_ENABLE
+config NODES_SHIFT
+ int
+ default "3"
+ depends on NEED_MULTIPLE_NODES
+
+source "kernel/Kconfig.preempt"
source "kernel/Kconfig.hz"
source "mm/Kconfig"
-config PREEMPT
- bool
-# bool "Preemptible Kernel"
- default n
-
config COMPAT
def_bool y
depends on 64BIT
diff --git a/arch/parisc/configs/712_defconfig b/arch/parisc/configs/712_defconfig
index 3e013f55df6..41fd0696bbe 100644
--- a/arch/parisc/configs/712_defconfig
+++ b/arch/parisc/configs/712_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc5-pa1
-# Fri Oct 21 23:04:34 2005
+# Linux kernel version: 2.6.16-pa6
+# Sun Mar 26 19:59:51 2006
#
CONFIG_PARISC=y
CONFIG_MMU=y
@@ -10,14 +10,11 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -32,17 +29,18 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
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_EPOLL=y
@@ -51,8 +49,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
#
# Loadable module support
@@ -66,6 +66,23 @@ CONFIG_OBSOLETE_MODPARM=y
CONFIG_KMOD=y
#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
# Processor type and features
#
# CONFIG_PA7000 is not set
@@ -75,6 +92,10 @@ CONFIG_PA7100LC=y
# CONFIG_PA8X00 is not set
CONFIG_PA11=y
# CONFIG_SMP is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
@@ -86,7 +107,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_PREEMPT is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
# CONFIG_HPUX is not set
#
@@ -130,6 +151,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -165,7 +187,12 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
#
# IP: Netfilter Configuration
@@ -182,64 +209,6 @@ CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
# CONFIG_IP_NF_PPTP is not set
CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_REALM is not set
-CONFIG_IP_NF_MATCH_SCTP=m
-# CONFIG_IP_NF_MATCH_DCCP is not set
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_CONNMARK=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-# CONFIG_IP_NF_MATCH_STRING is not set
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-# CONFIG_IP_NF_TARGET_NFQUEUE is not set
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-# CONFIG_IP_NF_TARGET_TTL is not set
-CONFIG_IP_NF_TARGET_CONNMARK=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
#
# DCCP Configuration (EXPERIMENTAL)
@@ -250,6 +219,11 @@ CONFIG_IP_NF_ARP_MANGLE=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -263,8 +237,11 @@ CONFIG_LLC2=m
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -304,6 +281,7 @@ CONFIG_PARPORT=y
CONFIG_PARPORT_PC=m
# CONFIG_PARPORT_PC_FIFO is not set
# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_NOT_PC=y
CONFIG_PARPORT_GSC=y
# CONFIG_PARPORT_1284 is not set
@@ -314,7 +292,6 @@ CONFIG_PARPORT_GSC=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
@@ -325,14 +302,6 @@ CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=6144
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_ATA_OVER_ETH=m
#
@@ -376,6 +345,7 @@ CONFIG_SCSI_ISCSI_ATTRS=m
#
# SCSI low-level drivers
#
+# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_PPA is not set
# CONFIG_SCSI_IMM is not set
@@ -407,7 +377,6 @@ CONFIG_MD_RAID1=m
#
# IEEE 1394 (FireWire) support
#
-# CONFIG_IEEE1394 is not set
#
# I2O device support
@@ -471,6 +440,7 @@ CONFIG_PPP_ASYNC=m
CONFIG_PPP_SYNC_TTY=m
CONFIG_PPP_DEFLATE=m
CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
CONFIG_PPPOE=m
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
@@ -516,8 +486,8 @@ CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_KEYBOARD_HIL_OLD=y
-# CONFIG_KEYBOARD_HIL is not set
+# CONFIG_KEYBOARD_HIL_OLD is not set
+CONFIG_KEYBOARD_HIL=y
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_SERIAL=m
@@ -554,6 +524,7 @@ CONFIG_HW_CONSOLE=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=17
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
@@ -598,6 +569,8 @@ CONFIG_MAX_RAW_DEVS=256
#
# TPM devices
#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -605,6 +578,12 @@ CONFIG_MAX_RAW_DEVS=256
# 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
@@ -640,7 +619,6 @@ CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
# CONFIG_FB_MACMODES is not set
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
@@ -655,6 +633,7 @@ CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=128
CONFIG_DUMMY_CONSOLE_ROWS=48
CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_STI_CONSOLE=y
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
@@ -695,6 +674,8 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
@@ -724,6 +705,10 @@ CONFIG_SND_HARMONY=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -736,10 +721,9 @@ CONFIG_SND_HARMONY=y
#
# InfiniBand support
#
-# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
@@ -765,6 +749,7 @@ CONFIG_XFS_EXPORT=y
# CONFIG_XFS_SECURITY is not set
# CONFIG_XFS_POSIX_ACL is not set
# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
@@ -800,10 +785,10 @@ CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -821,7 +806,6 @@ CONFIG_RAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
@@ -917,18 +901,22 @@ CONFIG_OPROFILE=m
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=16
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_IOREMAP is not set
# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_RODATA=y
#
# Security options
diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
index 959ad3c4e37..f3b812f0459 100644
--- a/arch/parisc/configs/a500_defconfig
+++ b/arch/parisc/configs/a500_defconfig
@@ -1031,8 +1031,8 @@ CONFIG_NLS_CODEPAGE_850=m
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
diff --git a/arch/parisc/configs/b180_defconfig b/arch/parisc/configs/b180_defconfig
index 37e98241ce4..35093612ad2 100644
--- a/arch/parisc/configs/b180_defconfig
+++ b/arch/parisc/configs/b180_defconfig
@@ -939,10 +939,10 @@ CONFIG_MSDOS_PARTITION=y
#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=m
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
+CONFIG_NLS_CODEPAGE_850=m
# CONFIG_NLS_CODEPAGE_852 is not set
# CONFIG_NLS_CODEPAGE_855 is not set
# CONFIG_NLS_CODEPAGE_857 is not set
@@ -962,8 +962,8 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
@@ -973,10 +973,10 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# 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_ISO8859_15=m
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_UTF8=m
#
# Kernel hacking
diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig
index 0b1c8c1fa8a..782906b644d 100644
--- a/arch/parisc/configs/c3000_defconfig
+++ b/arch/parisc/configs/c3000_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc5-pa1
-# Fri Oct 21 23:06:31 2005
+# Linux kernel version: 2.6.16-pa6
+# Sun Mar 26 20:03:29 2006
#
CONFIG_PARISC=y
CONFIG_MMU=y
@@ -10,14 +10,11 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -32,28 +29,30 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=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_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
#
# Loadable module support
@@ -67,6 +66,23 @@ CONFIG_OBSOLETE_MODPARM=y
CONFIG_KMOD=y
#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
# Processor type and features
#
# CONFIG_PA7000 is not set
@@ -78,6 +94,10 @@ CONFIG_PA20=y
CONFIG_PREFETCH=y
# CONFIG_64BIT is not set
# CONFIG_SMP is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
@@ -89,7 +109,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_PREEMPT is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_HPUX is not set
#
@@ -135,6 +155,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -175,7 +196,12 @@ CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
CONFIG_NETFILTER_DEBUG=y
+
+#
+# Core Netfilter Configuration
+#
# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
#
# IP: Netfilter Configuration
@@ -192,87 +218,11 @@ CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
# CONFIG_IP_NF_PPTP is not set
CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_REALM is not set
-# CONFIG_IP_NF_MATCH_SCTP is not set
-# CONFIG_IP_NF_MATCH_DCCP is not set
-# CONFIG_IP_NF_MATCH_COMMENT is not set
-# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
-# CONFIG_IP_NF_MATCH_STRING is not set
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-# CONFIG_IP_NF_TARGET_NFQUEUE is not set
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-# CONFIG_IP_NF_TARGET_TTL is not set
-# CONFIG_IP_NF_RAW is not set
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
#
# IPv6: Netfilter Configuration (EXPERIMENTAL)
#
# CONFIG_IP6_NF_QUEUE is not set
-CONFIG_IP6_NF_IPTABLES=m
-# CONFIG_IP6_NF_MATCH_LIMIT is not set
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_RT=m
-# CONFIG_IP6_NF_MATCH_OPTS is not set
-# CONFIG_IP6_NF_MATCH_FRAG is not set
-# CONFIG_IP6_NF_MATCH_HL is not set
-# CONFIG_IP6_NF_MATCH_MULTIPORT is not set
-CONFIG_IP6_NF_MATCH_OWNER=m
-# CONFIG_IP6_NF_MATCH_MARK is not set
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-# CONFIG_IP6_NF_MATCH_AHESP is not set
-CONFIG_IP6_NF_MATCH_LENGTH=m
-# CONFIG_IP6_NF_MATCH_EUI64 is not set
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_TARGET_REJECT=m
-# CONFIG_IP6_NF_TARGET_NFQUEUE is not set
-CONFIG_IP6_NF_MANGLE=m
-# CONFIG_IP6_NF_TARGET_MARK is not set
-# CONFIG_IP6_NF_TARGET_HL is not set
-# CONFIG_IP6_NF_RAW is not set
#
# DCCP Configuration (EXPERIMENTAL)
@@ -283,6 +233,11 @@ CONFIG_IP6_NF_MANGLE=m
# 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
# CONFIG_VLAN_8021Q is not set
@@ -295,8 +250,11 @@ CONFIG_IP6_NF_MANGLE=m
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -341,7 +299,6 @@ CONFIG_FW_LOADER=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
@@ -355,14 +312,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
# CONFIG_BLK_DEV_RAM is not set
CONFIG_BLK_DEV_RAM_COUNT=16
# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_ATA_OVER_ETH is not set
#
@@ -458,6 +407,7 @@ CONFIG_SCSI_ISCSI_ATTRS=m
#
# 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
@@ -466,7 +416,6 @@ CONFIG_SCSI_ISCSI_ATTRS=m
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
@@ -476,18 +425,18 @@ CONFIG_SCSI_SATA=y
CONFIG_SCSI_ATA_PIIX=m
# CONFIG_SCSI_SATA_MV is not set
# CONFIG_SCSI_SATA_NV is not set
-CONFIG_SCSI_SATA_PROMISE=m
+# CONFIG_SCSI_PDC_ADMA is not set
# CONFIG_SCSI_SATA_QSTOR is not set
+CONFIG_SCSI_SATA_PROMISE=m
# CONFIG_SCSI_SATA_SX4 is not set
CONFIG_SCSI_SATA_SIL=m
+# CONFIG_SCSI_SATA_SIL24 is not set
# CONFIG_SCSI_SATA_SIS is not set
# CONFIG_SCSI_SATA_ULI is not set
CONFIG_SCSI_SATA_VIA=m
# CONFIG_SCSI_SATA_VITESSE is not set
CONFIG_SCSI_SATA_INTEL_COMBINED=y
-# CONFIG_SCSI_CPQFCTS is not set
# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
@@ -496,18 +445,11 @@ CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
@@ -633,6 +575,7 @@ CONFIG_E1000=m
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=m
@@ -668,6 +611,7 @@ CONFIG_PPP_ASYNC=m
CONFIG_PPP_SYNC_TTY=m
CONFIG_PPP_DEFLATE=m
CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
CONFIG_PPPOE=m
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
@@ -744,6 +688,7 @@ CONFIG_HW_CONSOLE=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=13
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
@@ -753,7 +698,6 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_MUX is not set
# CONFIG_PDC_CONSOLE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
@@ -788,6 +732,7 @@ CONFIG_MAX_RAW_DEVS=256
# TPM devices
#
# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -795,6 +740,12 @@ CONFIG_MAX_RAW_DEVS=256
# 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
@@ -830,7 +781,6 @@ CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
@@ -840,6 +790,7 @@ CONFIG_FB_SOFT_CURSOR=y
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
CONFIG_FB_STI=y
+# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
@@ -853,10 +804,7 @@ CONFIG_FB_STI=y
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_CYBLA is not set
# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -866,6 +814,7 @@ CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=160
CONFIG_DUMMY_CONSOLE_ROWS=64
CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_STI_CONSOLE=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
@@ -898,23 +847,27 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
#
# Generic devices
#
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_VIRMIDI is not set
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_AC97_BUS=y
#
# PCI devices
#
+CONFIG_SND_AD1889=y
+# CONFIG_SND_AD1889_OPL3 is not set
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ATIIXP is not set
# CONFIG_SND_ATIIXP_MODEM is not set
@@ -923,39 +876,38 @@ CONFIG_SND_AC97_BUS=y
# CONFIG_SND_AU8830 is not set
# CONFIG_SND_AZT3328 is not set
# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
# CONFIG_SND_EMU10K1 is not set
# CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-CONFIG_SND_AD1889=y
-# CONFIG_SND_AD1889_OPL3 is not set
-# CONFIG_SND_CMIPCI is not set
# CONFIG_SND_ENS1370 is not set
# CONFIG_SND_ENS1371 is not set
# CONFIG_SND_ES1938 is not set
# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
# CONFIG_SND_ICE1712 is not set
# CONFIG_SND_ICE1724 is not set
# CONFIG_SND_INTEL8X0 is not set
# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
# CONFIG_SND_VIA82XX is not set
# CONFIG_SND_VIA82XX_MODEM is not set
# CONFIG_SND_VX222 is not set
-# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_YMFPCI is not set
#
# USB devices
@@ -998,12 +950,15 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# USB Device Class drivers
#
# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
-# CONFIG_USB_BLUETOOTH_TTY is not set
# CONFIG_USB_ACM is not set
CONFIG_USB_PRINTER=m
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1015,12 +970,15 @@ CONFIG_USB_STORAGE_USBAT=y
CONFIG_USB_STORAGE_SDDR09=y
CONFIG_USB_STORAGE_SDDR55=y
CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
#
# USB Input Devices
#
CONFIG_USB_HID=y
CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
# CONFIG_HID_FF is not set
CONFIG_USB_HIDDEV=y
# CONFIG_USB_AIPTEK is not set
@@ -1034,6 +992,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
# CONFIG_USB_KEYSPAN_REMOTE is not set
# CONFIG_USB_APPLETOUCH is not set
@@ -1108,7 +1067,7 @@ CONFIG_USB_LEGOTOWER=m
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
@@ -1130,6 +1089,7 @@ CONFIG_XFS_EXPORT=y
# CONFIG_XFS_SECURITY is not set
# CONFIG_XFS_POSIX_ACL is not set
# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
@@ -1164,10 +1124,10 @@ CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -1225,10 +1185,10 @@ CONFIG_MSDOS_PARTITION=y
#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=m
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
+CONFIG_NLS_CODEPAGE_850=m
# CONFIG_NLS_CODEPAGE_852 is not set
# CONFIG_NLS_CODEPAGE_855 is not set
# CONFIG_NLS_CODEPAGE_857 is not set
@@ -1248,8 +1208,8 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
@@ -1259,10 +1219,10 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# 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_ISO8859_15=m
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_UTF8=m
#
# Profiling support
@@ -1274,18 +1234,22 @@ CONFIG_OPROFILE=m
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=16
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_IOREMAP is not set
# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_RODATA=y
#
# Security options
diff --git a/arch/parisc/defconfig b/arch/parisc/defconfig
index f38a4620d24..b38b58eb9dc 100644
--- a/arch/parisc/defconfig
+++ b/arch/parisc/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc5-pa1
-# Fri Oct 21 23:01:33 2005
+# Linux kernel version: 2.6.16-pa10
+# Sun Apr 2 15:26:38 2006
#
CONFIG_PARISC=y
CONFIG_MMU=y
@@ -15,7 +15,6 @@ CONFIG_GENERIC_IRQ_PROBE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -26,21 +25,22 @@ CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_ALL is not set
+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_EPOLL=y
@@ -49,24 +49,56 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
#
# Loadable module support
#
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
#
# Processor type and features
#
-CONFIG_PA7000=y
-# CONFIG_PA7100LC is not set
+# CONFIG_PA7000 is not set
+CONFIG_PA7100LC=y
# CONFIG_PA7200 is not set
# CONFIG_PA7300LC is not set
# CONFIG_PA8X00 is not set
CONFIG_PA11=y
+CONFIG_PARISC_PAGE_SIZE_4KB=y
+# CONFIG_PARISC_PAGE_SIZE_16KB is not set
+# CONFIG_PARISC_PAGE_SIZE_64KB is not set
# CONFIG_SMP is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
@@ -78,14 +110,14 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_PREEMPT is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
# CONFIG_HPUX is not set
#
# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
#
CONFIG_GSC=y
-CONFIG_HPPB=y
+# CONFIG_HPPB is not set
CONFIG_IOMMU_CCIO=y
CONFIG_GSC_LASI=y
CONFIG_GSC_WAX=y
@@ -103,7 +135,25 @@ CONFIG_IOMMU_SBA=y
#
# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_PCCARD is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=y
+CONFIG_I82092=y
+CONFIG_PCCARD_NONSTATIC=y
#
# PCI Hotplug Support
@@ -122,7 +172,7 @@ CONFIG_PDC_STABLE=y
# Executable file formats
#
CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=m
#
# Networking
@@ -132,16 +182,19 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
@@ -149,19 +202,20 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_INET_DIAG is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_INET6_TUNNEL=y
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_NETFILTER is not set
@@ -174,11 +228,17 @@ CONFIG_IPV6=y
# 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
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
@@ -186,8 +246,11 @@ CONFIG_IPV6=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -205,9 +268,9 @@ CONFIG_IPV6=y
#
# Generic Driver Options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
#
@@ -224,12 +287,14 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Parallel port support
#
CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC=m
# CONFIG_PARPORT_SERIAL is not set
# CONFIG_PARPORT_PC_FIFO is not set
# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
CONFIG_PARPORT_GSC=y
-# CONFIG_PARPORT_1284 is not set
+CONFIG_PARPORT_1284=y
#
# Plug and Play support
@@ -251,23 +316,68 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y
# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_SIZE=6144
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
#
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+CONFIG_BLK_DEV_NS87415=y
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
#
# SCSI device support
@@ -305,6 +415,7 @@ CONFIG_SCSI_SPI_ATTRS=y
#
# 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
@@ -331,7 +442,7 @@ CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
# CONFIG_SCSI_IPR is not set
CONFIG_SCSI_ZALON=y
CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
@@ -340,13 +451,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_SIM710 is not set
# CONFIG_SCSI_DC395x is not set
@@ -355,6 +460,15 @@ CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_DEBUG is not set
#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
# Multi-device support (RAID and LVM)
#
CONFIG_MD=y
@@ -362,12 +476,17 @@ CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=y
CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID10=y
CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
+CONFIG_MD_RAID6=y
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
-# CONFIG_BLK_DEV_DM is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
#
# Fusion MPT device support
@@ -391,10 +510,10 @@ CONFIG_MD_RAID5=y
# Network device support
#
CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=m
#
# ARCnet devices
@@ -410,7 +529,7 @@ CONFIG_NETDEVICES=y
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=m
CONFIG_LASI_82596=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
@@ -431,6 +550,8 @@ CONFIG_TULIP=y
# CONFIG_WINBOND_840 is not set
# CONFIG_DM9102 is not set
# CONFIG_ULI526X is not set
+# CONFIG_PCMCIA_XIRCOM is not set
+# CONFIG_PCMCIA_XIRTULIP is not set
# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
CONFIG_NET_PCI=y
@@ -471,6 +592,7 @@ CONFIG_ACENIC=y
# 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=y
@@ -497,14 +619,33 @@ CONFIG_NET_RADIO=y
# Obsolete Wireless cards support (pre-802.11)
#
# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
#
# Wireless 802.11b ISA/PCI cards support
#
-# CONFIG_HERMES is not set
+CONFIG_HERMES=y
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_NORTEL_HERMES is not set
+# CONFIG_PCI_HERMES is not set
# CONFIG_ATMEL is not set
#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=y
+CONFIG_PCMCIA_SPECTRUM=y
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+
+#
# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
#
# CONFIG_PRISM54 is not set
@@ -512,13 +653,34 @@ CONFIG_NET_RADIO=y
CONFIG_NET_WIRELESS=y
#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
# Wan interfaces
#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
@@ -550,67 +712,42 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y
+# CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES 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_HIL_OLD=y
+# CONFIG_KEYBOARD_HIL_OLD is not set
CONFIG_KEYBOARD_HIL=y
CONFIG_INPUT_MOUSE=y
-# CONFIG_MOUSE_PS2 is not set
-# CONFIG_MOUSE_SERIAL is not set
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=y
# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_MOUSE_HIL 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_DB9 is not set
-# CONFIG_JOYSTICK_GAMECON is not set
-# CONFIG_JOYSTICK_TURBOGRAFX is not set
-# CONFIG_JOYSTICK_JOYDUMP is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_TOUCHSCREEN_GUNZE is not set
-# CONFIG_TOUCHSCREEN_ELO is not set
-# CONFIG_TOUCHSCREEN_MTOUCH is not set
-# CONFIG_TOUCHSCREEN_MK712 is not set
-CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_UINPUT is not set
-CONFIG_HP_SDC_RTC=y
+CONFIG_MOUSE_HIL=y
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
# Hardware I/O ports
#
CONFIG_SERIO=y
-# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_PARKBD is not set
CONFIG_SERIO_GSCPS2=y
CONFIG_HP_SDC=y
CONFIG_HIL_MLC=y
# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
@@ -627,7 +764,9 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=13
+CONFIG_SERIAL_8250_CS=y
+CONFIG_SERIAL_8250_NR_UARTS=17
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
@@ -644,10 +783,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_PRINTER=y
+CONFIG_LEGACY_PTY_COUNT=64
+CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
+CONFIG_PPDEV=m
# CONFIG_TIPAR is not set
#
@@ -660,7 +799,7 @@ CONFIG_PRINTER=y
#
# CONFIG_WATCHDOG is not set
CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
+CONFIG_GEN_RTC_X=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -669,12 +808,20 @@ CONFIG_GEN_RTC=y
# Ftape, the floppy tape device driver
#
# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
# CONFIG_RAW_DRIVER is not set
#
# TPM devices
#
# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -682,6 +829,12 @@ CONFIG_GEN_RTC=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
@@ -689,9 +842,8 @@ CONFIG_GEN_RTC=y
#
# Hardware Monitoring support
#
-CONFIG_HWMON=y
+# CONFIG_HWMON is not set
# CONFIG_HWMON_VID is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@@ -718,16 +870,16 @@ CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
CONFIG_FB_STI=y
+# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
@@ -741,27 +893,38 @@ CONFIG_FB_STI=y
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_CYBLA is not set
# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
#
# Console display driver support
#
CONFIG_DUMMY_CONSOLE=y
-CONFIG_DUMMY_CONSOLE_COLUMNS=160
-CONFIG_DUMMY_CONSOLE_ROWS=64
+CONFIG_DUMMY_CONSOLE_COLUMNS=128
+CONFIG_DUMMY_CONSOLE_ROWS=48
CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_STI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
#
# Logo configuration
#
-# CONFIG_LOGO is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_PARISC_CLUT224=y
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -775,29 +938,35 @@ CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_TIMER=y
CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
CONFIG_SND_SEQUENCER=y
# CONFIG_SND_SEQ_DUMMY is not set
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_SUPPORT_OLD_API=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
#
# Generic devices
#
+CONFIG_SND_OPL3_LIB=y
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_VIRMIDI is not set
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_AC97_BUS=y
#
# PCI devices
#
+CONFIG_SND_AD1889=y
+CONFIG_SND_AD1889_OPL3=y
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ATIIXP is not set
# CONFIG_SND_ATIIXP_MODEM is not set
@@ -806,39 +975,38 @@ CONFIG_SND_AC97_BUS=y
# CONFIG_SND_AU8830 is not set
# CONFIG_SND_AZT3328 is not set
# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
# CONFIG_SND_EMU10K1 is not set
# CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-CONFIG_SND_AD1889=y
-# CONFIG_SND_AD1889_OPL3 is not set
-# CONFIG_SND_CMIPCI is not set
# CONFIG_SND_ENS1370 is not set
# CONFIG_SND_ENS1371 is not set
# CONFIG_SND_ES1938 is not set
# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
# CONFIG_SND_ICE1712 is not set
# CONFIG_SND_ICE1724 is not set
# CONFIG_SND_INTEL8X0 is not set
# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
# CONFIG_SND_VIA82XX is not set
# CONFIG_SND_VIA82XX_MODEM is not set
# CONFIG_SND_VX222 is not set
-# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_YMFPCI is not set
#
# USB devices
@@ -846,6 +1014,10 @@ CONFIG_SND_AD1889=y
# CONFIG_SND_USB_AUDIO is not set
#
+# PCMCIA devices
+#
+
+#
# GSC devices
#
CONFIG_SND_HARMONY=y
@@ -861,12 +1033,12 @@ CONFIG_SND_HARMONY=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEBUG is not set
#
# Miscellaneous USB options
#
-# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
@@ -874,39 +1046,39 @@ CONFIG_USB_DEBUG=y
#
# USB Host Controller Drivers
#
-CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_SPLIT_ISO is not set
-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_OHCI_BIG_ENDIAN is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-# CONFIG_USB_UHCI_HCD is not set
+CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_SL811_HCD is not set
#
# USB Device Class drivers
#
# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
-# CONFIG_USB_BLUETOOTH_TTY is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
-# CONFIG_USB_STORAGE is not set
#
-# USB Input Devices
+# may also be needed; see USB_STORAGE Help for more information
#
-# CONFIG_USB_HID is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
#
-# USB HID Boot Protocol drivers
+# USB Input Devices
#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
# CONFIG_USB_AIPTEK is not set
# CONFIG_USB_WACOM is not set
# CONFIG_USB_ACECAD is not set
@@ -918,6 +1090,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
# CONFIG_USB_KEYSPAN_REMOTE is not set
# CONFIG_USB_APPLETOUCH is not set
@@ -971,8 +1144,8 @@ CONFIG_USB_MON=y
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
#
# USB DSL modem support
@@ -994,7 +1167,7 @@ CONFIG_USB_MON=y
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
@@ -1009,14 +1182,15 @@ CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -1031,8 +1205,11 @@ CONFIG_JOLIET=y
#
# DOS/FAT/NT Filesystems
#
+CONFIG_FAT_FS=y
# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
@@ -1045,6 +1222,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -1074,7 +1252,7 @@ CONFIG_NFS_V3=y
CONFIG_NFSD=y
CONFIG_NFSD_V3=y
# CONFIG_NFSD_V3_ACL is not set
-# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_V4=y
CONFIG_NFSD_TCP=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
@@ -1082,10 +1260,16 @@ CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -1102,102 +1286,107 @@ CONFIG_MSDOS_PARTITION=y
#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
#
# Profiling support
#
CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
+CONFIG_OPROFILE=m
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOG_BUF_SHIFT=15
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=16
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_IOREMAP is not set
# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_RODATA is not set
#
# Security options
#
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
CONFIG_CRYPTO=y
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_DES 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_TEST is not set
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
#
# Hardware crypto devices
@@ -1206,7 +1395,9 @@ CONFIG_CRYPTO=y
#
# Library routines
#
-# CONFIG_CRC_CCITT is not set
+CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
index e23c4e1e3a2..c11a5bc7c06 100644
--- a/arch/parisc/kernel/asm-offsets.c
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -288,8 +288,11 @@ int main(void)
DEFINE(ASM_PGD_ENTRY_SIZE, PGD_ENTRY_SIZE);
DEFINE(ASM_PMD_ENTRY_SIZE, PMD_ENTRY_SIZE);
DEFINE(ASM_PTE_ENTRY_SIZE, PTE_ENTRY_SIZE);
+ DEFINE(ASM_PFN_PTE_SHIFT, PFN_PTE_SHIFT);
DEFINE(ASM_PT_INITIAL, PT_INITIAL);
DEFINE(ASM_PAGE_SIZE, PAGE_SIZE);
+ DEFINE(ASM_PAGE_SIZE_DIV64, PAGE_SIZE/64);
+ DEFINE(ASM_PAGE_SIZE_DIV128, PAGE_SIZE/128);
BLANK();
DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index d8a4ca021aa..c057ad7605b 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -4,7 +4,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1999 Helge Deller (07-13-1999)
+ * Copyright (C) 1999-2006 Helge Deller <deller@gmx.de> (07-13-1999)
* Copyright (C) 1999 SuSE GmbH Nuernberg
* Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
*
@@ -89,7 +89,7 @@ update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
if (pfn_valid(page_to_pfn(page)) && page_mapping(page) &&
test_bit(PG_dcache_dirty, &page->flags)) {
- flush_kernel_dcache_page(page_address(page));
+ flush_kernel_dcache_page(page);
clear_bit(PG_dcache_dirty, &page->flags);
}
}
@@ -278,7 +278,7 @@ void flush_dcache_page(struct page *page)
return;
}
- flush_kernel_dcache_page(page_address(page));
+ flush_kernel_dcache_page(page);
if (!mapping)
return;
@@ -317,7 +317,7 @@ EXPORT_SYMBOL(flush_dcache_page);
/* Defined in arch/parisc/kernel/pacache.S */
EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
-EXPORT_SYMBOL(flush_kernel_dcache_page);
+EXPORT_SYMBOL(flush_kernel_dcache_page_asm);
EXPORT_SYMBOL(flush_data_cache_local);
EXPORT_SYMBOL(flush_kernel_icache_range_asm);
@@ -358,5 +358,5 @@ void parisc_setup_cache_timing(void)
if (!parisc_cache_flush_threshold)
parisc_cache_flush_threshold = FLUSH_THRESHOLD;
- printk("Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
+ printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
}
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 9af4b22a6d7..d9e53cf0372 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -502,18 +502,20 @@
* all ILP32 processes and all the kernel for machines with
* under 4GB of memory) */
.macro L3_ptep pgd,pte,index,va,fault
+#if PT_NLEVELS == 3 /* we might have a 2-Level scheme, e.g. with 16kb page size */
extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
copy %r0,\pte
- extrd,u,*= \va,31,32,%r0
+ extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
ldw,s \index(\pgd),\pgd
- extrd,u,*= \va,31,32,%r0
+ extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
bb,>=,n \pgd,_PxD_PRESENT_BIT,\fault
- extrd,u,*= \va,31,32,%r0
+ extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
shld \pgd,PxD_VALUE_SHIFT,\index
- extrd,u,*= \va,31,32,%r0
+ extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
copy \index,\pgd
- extrd,u,*<> \va,31,32,%r0
+ extrd,u,*<> \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
ldo ASM_PGD_PMD_OFFSET(\pgd),\pgd
+#endif
L2_ptep \pgd,\pte,\index,\va,\fault
.endm
@@ -563,10 +565,18 @@
extrd,u,*= \pte,_PAGE_GATEWAY_BIT+32,1,%r0
depd %r0,11,2,\prot /* If Gateway, Set PL2 to 0 */
- /* Get rid of prot bits and convert to page addr for iitlbt */
+ /* Enforce uncacheable pages.
+ * This should ONLY be use for MMIO on PA 2.0 machines.
+ * Memory/DMA is cache coherent on all PA2.0 machines we support
+ * (that means T-class is NOT supported) and the memory controllers
+ * on most of those machines only handles cache transactions.
+ */
+ extrd,u,*= \pte,_PAGE_NO_CACHE_BIT+32,1,%r0
+ depi 1,12,1,\prot
- depd %r0,63,PAGE_SHIFT,\pte
- extrd,u \pte,56,32,\pte
+ /* Drop prot bits and convert to page addr for iitlbt and idtlbt */
+ extrd,u \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58),64-PAGE_SHIFT,\pte
+ depdi _PAGE_SIZE_ENCODING_DEFAULT,63,63-58,\pte
.endm
/* Identical macro to make_insert_tlb above, except it
@@ -584,9 +594,8 @@
/* Get rid of prot bits and convert to page addr for iitlba */
- depi 0,31,12,\pte
+ depi _PAGE_SIZE_ENCODING_DEFAULT,31,ASM_PFN_PTE_SHIFT,\pte
extru \pte,24,25,\pte
-
.endm
/* This is for ILP32 PA2.0 only. The TLB insertion needs
@@ -1014,14 +1023,21 @@ intr_restore:
nop
nop
+#ifndef CONFIG_PREEMPT
+# define intr_do_preempt intr_restore
+#endif /* !CONFIG_PREEMPT */
+
.import schedule,code
intr_do_resched:
- /* Only do reschedule if we are returning to user space */
+ /* Only call schedule on return to userspace. If we're returning
+ * to kernel space, we may schedule if CONFIG_PREEMPT, otherwise
+ * we jump back to intr_restore.
+ */
LDREG PT_IASQ0(%r16), %r20
- CMPIB= 0,%r20,intr_restore /* backward */
+ CMPIB= 0, %r20, intr_do_preempt
nop
LDREG PT_IASQ1(%r16), %r20
- CMPIB= 0,%r20,intr_restore /* backward */
+ CMPIB= 0, %r20, intr_do_preempt
nop
#ifdef CONFIG_64BIT
@@ -1037,6 +1053,32 @@ intr_do_resched:
#endif
ldo R%intr_check_sig(%r2), %r2
+ /* preempt the current task on returning to kernel
+ * mode from an interrupt, iff need_resched is set,
+ * and preempt_count is 0. otherwise, we continue on
+ * our merry way back to the current running task.
+ */
+#ifdef CONFIG_PREEMPT
+ .import preempt_schedule_irq,code
+intr_do_preempt:
+ rsm PSW_SM_I, %r0 /* disable interrupts */
+
+ /* current_thread_info()->preempt_count */
+ mfctl %cr30, %r1
+ LDREG TI_PRE_COUNT(%r1), %r19
+ CMPIB<> 0, %r19, intr_restore /* if preempt_count > 0 */
+ nop /* prev insn branched backwards */
+
+ /* check if we interrupted a critical path */
+ LDREG PT_PSW(%r16), %r20
+ bb,<,n %r20, 31 - PSW_SM_I, intr_restore
+ nop
+
+ BL preempt_schedule_irq, %r2
+ nop
+
+ b intr_restore /* ssm PSW_SM_I done by intr_restore */
+#endif /* CONFIG_PREEMPT */
.import do_signal,code
intr_do_signal:
@@ -1168,10 +1210,9 @@ intr_save:
*/
/* adjust isr/ior. */
-
- extrd,u %r16,63,7,%r1 /* get high bits from isr for ior */
- depd %r1,31,7,%r17 /* deposit them into ior */
- depdi 0,63,7,%r16 /* clear them from isr */
+ extrd,u %r16,63,SPACEID_SHIFT,%r1 /* get high bits from isr for ior */
+ depd %r1,31,SPACEID_SHIFT,%r17 /* deposit them into ior */
+ depdi 0,63,SPACEID_SHIFT,%r16 /* clear them from isr */
#endif
STREG %r16, PT_ISR(%r29)
STREG %r17, PT_IOR(%r29)
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index 0b47afc2069..3e79e62f7b0 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -76,16 +76,16 @@ $bss_loop:
mtctl %r4,%cr24 /* Initialize kernel root pointer */
mtctl %r4,%cr25 /* Initialize user root pointer */
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
/* Set pmd in pgd */
load32 PA(pmd0),%r5
shrd %r5,PxD_VALUE_SHIFT,%r3
- ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
+ ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
stw %r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4)
ldo ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r4
#else
/* 2-level page table, so pmd == pgd */
- ldo ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
+ ldo ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
#endif
/* Fill in pmd with enough pte directories */
@@ -99,7 +99,7 @@ $bss_loop:
stw %r3,0(%r4)
ldo (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
addib,> -1,%r1,1b
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
ldo ASM_PMD_ENTRY_SIZE(%r4),%r4
#else
ldo ASM_PGD_ENTRY_SIZE(%r4),%r4
@@ -107,13 +107,14 @@ $bss_loop:
/* Now initialize the PTEs themselves */
- ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
+ ldo 0+_PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
+ ldi (1<<(KERNEL_INITIAL_ORDER-PAGE_SHIFT)),%r11 /* PFN count */
load32 PA(pg0),%r1
$pgt_fill_loop:
STREGM %r3,ASM_PTE_ENTRY_SIZE(%r1)
- ldo ASM_PAGE_SIZE(%r3),%r3
- bb,>= %r3,31-KERNEL_INITIAL_ORDER,$pgt_fill_loop
+ ldo (1<<PFN_PTE_SHIFT)(%r3),%r3 /* add one PFN */
+ addib,> -1,%r11,$pgt_fill_loop
nop
/* Load the return address...er...crash 'n burn */
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c
index 7e898fd6441..8384bf9cecd 100644
--- a/arch/parisc/kernel/init_task.c
+++ b/arch/parisc/kernel/init_task.c
@@ -53,17 +53,17 @@ union thread_union init_thread_union
__attribute__((aligned(128))) __attribute__((__section__(".data.init_task"))) =
{ INIT_THREAD_INFO(init_task) };
-#ifdef __LP64__
+#if PT_NLEVELS == 3
/* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
* with the first pmd adjacent to the pgd and below it. gcc doesn't actually
* guarantee that global objects will be laid out in memory in the same order
* as the order of declaration, so put these in different sections and use
* the linker script to order them. */
-pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pmd"))) = { {0}, };
-
+pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((__section__ (".data.vm0.pmd"), aligned(PAGE_SIZE)));
#endif
-pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pgd"))) = { {0}, };
-pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pte"))) = { {0}, };
+
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data.vm0.pgd"), aligned(PAGE_SIZE)));
+pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data.vm0.pte"), aligned(PAGE_SIZE)));
/*
* Initial task structure.
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index 9534ee17b9b..f600556414d 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -65,7 +65,7 @@ flush_tlb_all_local:
*/
/* pcxt_ssm_bug - relied upon translation! PA 2.0 Arch. F-4 and F-5 */
- rsm PSW_SM_I, %r19 /* save I-bit state */
+ rsm PSW_SM_I, %r19 /* save I-bit state */
load32 PA(1f), %r1
nop
nop
@@ -84,8 +84,7 @@ flush_tlb_all_local:
rfi
nop
-1: ldil L%PA(cache_info), %r1
- ldo R%PA(cache_info)(%r1), %r1
+1: load32 PA(cache_info), %r1
/* Flush Instruction Tlb */
@@ -212,8 +211,7 @@ flush_instruction_cache_local:
.entry
mtsp %r0, %sr1
- ldil L%cache_info, %r1
- ldo R%cache_info(%r1), %r1
+ load32 cache_info, %r1
/* Flush Instruction Cache */
@@ -254,8 +252,7 @@ flush_data_cache_local:
.entry
mtsp %r0, %sr1
- ldil L%cache_info, %r1
- ldo R%cache_info(%r1), %r1
+ load32 cache_info, %r1
/* Flush Data Cache */
@@ -303,7 +300,8 @@ copy_user_page_asm:
*/
ldd 0(%r25), %r19
- ldi 32, %r1 /* PAGE_SIZE/128 == 32 */
+ ldi ASM_PAGE_SIZE_DIV128, %r1
+
ldw 64(%r25), %r0 /* prefetch 1 cacheline ahead */
ldw 128(%r25), %r0 /* prefetch 2 */
@@ -368,7 +366,7 @@ copy_user_page_asm:
* use ldd/std on a 32 bit kernel.
*/
ldw 0(%r25), %r19
- ldi 64, %r1 /* PAGE_SIZE/64 == 64 */
+ ldi ASM_PAGE_SIZE_DIV64, %r1
1:
ldw 4(%r25), %r20
@@ -461,6 +459,7 @@ copy_user_page_asm:
sub %r25, %r1, %r23 /* move physical addr into non shadowed reg */
ldil L%(TMPALIAS_MAP_START), %r28
+ /* FIXME for different page sizes != 4k */
#ifdef CONFIG_64BIT
extrd,u %r26,56,32, %r26 /* convert phys addr to tlb insert format */
extrd,u %r23,56,32, %r23 /* convert phys addr to tlb insert format */
@@ -551,6 +550,7 @@ __clear_user_page_asm:
#ifdef CONFIG_64BIT
#if (TMPALIAS_MAP_START >= 0x80000000)
depdi 0, 31,32, %r28 /* clear any sign extension */
+ /* FIXME: page size dependend */
#endif
extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */
depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */
@@ -566,10 +566,10 @@ __clear_user_page_asm:
pdtlb 0(%r28)
#ifdef CONFIG_64BIT
- ldi 32, %r1 /* PAGE_SIZE/128 == 32 */
+ ldi ASM_PAGE_SIZE_DIV128, %r1
/* PREFETCH (Write) has not (yet) been proven to help here */
-/* #define PREFETCHW_OP ldd 256(%0), %r0 */
+ /* #define PREFETCHW_OP ldd 256(%0), %r0 */
1: std %r0, 0(%r28)
std %r0, 8(%r28)
@@ -591,8 +591,7 @@ __clear_user_page_asm:
ldo 128(%r28), %r28
#else /* ! CONFIG_64BIT */
-
- ldi 64, %r1 /* PAGE_SIZE/64 == 64 */
+ ldi ASM_PAGE_SIZE_DIV64, %r1
1:
stw %r0, 0(%r28)
@@ -621,9 +620,9 @@ __clear_user_page_asm:
.procend
- .export flush_kernel_dcache_page
+ .export flush_kernel_dcache_page_asm
-flush_kernel_dcache_page:
+flush_kernel_dcache_page_asm:
.proc
.callinfo NO_CALLS
.entry
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index 1d00c365f2b..fc107add627 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -30,23 +30,7 @@
#include <linux/syscalls.h>
#include <linux/string.h>
-EXPORT_SYMBOL(memchr);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strpbrk);
#include <asm/atomic.h>
EXPORT_SYMBOL(__xchg8);
@@ -82,16 +66,12 @@ EXPORT_SYMBOL($global$);
#endif
#include <asm/io.h>
-EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(memcpy_toio);
EXPORT_SYMBOL(memcpy_fromio);
EXPORT_SYMBOL(memset_io);
#include <asm/unistd.h>
-EXPORT_SYMBOL(sys_open);
EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_read);
EXPORT_SYMBOL(sys_write);
#include <asm/semaphore.h>
diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c
index 2a01fe1bdc9..a45e2e2ffd9 100644
--- a/arch/parisc/kernel/pdc_chassis.c
+++ b/arch/parisc/kernel/pdc_chassis.c
@@ -5,9 +5,8 @@
* Copyright (C) 2002-2004 Thibaut VARENE <varenet@parisc-linux.org>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -150,7 +149,8 @@ void __init parisc_pdc_chassis_init(void)
if (handle) {
/* initialize panic notifier chain */
- notifier_chain_register(&panic_notifier_list, &pdc_chassis_panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &pdc_chassis_panic_block);
/* initialize reboot notifier chain */
register_reboot_notifier(&pdc_chassis_reboot_block);
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index 53f861c82f9..ac8ee205c35 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -805,7 +805,7 @@ static int perf_write_image(uint64_t *memaddr)
return -1;
}
- runway = ioremap(cpu_device->hpa.start, 4096);
+ runway = ioremap_nocache(cpu_device->hpa.start, 4096);
/* Merge intrigue bits into Runway STATUS 0 */
tmp64 = __raw_readq(runway + RUNWAY_STATUS) & 0xffecfffffffffffful;
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index d15a1d53e10..8b5df98e2b3 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -231,6 +231,14 @@ asmlinkage long parisc_fadvise64_64(int fd,
(loff_t)high_len << 32 | low_len, advice);
}
+asmlinkage long parisc_sync_file_range(int fd,
+ u32 hi_off, u32 lo_off, u32 hi_nbytes, u32 lo_nbytes,
+ unsigned int flags)
+{
+ return sys_sync_file_range(fd, (loff_t)hi_off << 32 | lo_off,
+ (loff_t)hi_nbytes << 32 | lo_nbytes, flags);
+}
+
asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag)
{
return -ENOMEM;
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index af88afef41b..479d9a017cd 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -55,7 +55,7 @@
* pointers.
*/
- .align 4096
+ .align ASM_PAGE_SIZE
linux_gateway_page:
/* ADDRESS 0x00 to 0xb0 = 176 bytes / 4 bytes per insn = 44 insns */
@@ -632,7 +632,7 @@ cas_action:
end_compare_and_swap:
/* Make sure nothing else is placed on this page */
- .align 4096
+ .align ASM_PAGE_SIZE
.export end_linux_gateway_page
end_linux_gateway_page:
@@ -652,7 +652,7 @@ end_linux_gateway_page:
.section .rodata,"a"
- .align 4096
+ .align ASM_PAGE_SIZE
/* Light-weight-syscall table */
/* Start of lws table. */
.export lws_table
@@ -662,14 +662,14 @@ lws_table:
LWS_ENTRY(compare_and_swap64) /* 1 - ELF64 Atomic compare and swap */
/* End of lws table */
- .align 4096
+ .align ASM_PAGE_SIZE
.export sys_call_table
.Lsys_call_table:
sys_call_table:
#include "syscall_table.S"
#ifdef CONFIG_64BIT
- .align 4096
+ .align ASM_PAGE_SIZE
.export sys_call_table64
.Lsys_call_table64:
sys_call_table64:
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 89b6c56ea0a..e27b432f90a 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -13,7 +13,7 @@
* Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
* Copyright (C) 2000-2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
* Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
- *
+ * Copyright (C) 2005-2006 Kyle McMartin <kyle at parisc-linux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -287,7 +287,7 @@
ENTRY_SAME(chown) /* 180 */
/* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
ENTRY_COMP(setsockopt)
- ENTRY_SAME(getsockopt)
+ ENTRY_COMP(getsockopt)
ENTRY_COMP(sendmsg)
ENTRY_COMP(recvmsg)
ENTRY_SAME(semop) /* 185 */
@@ -393,5 +393,11 @@
ENTRY_SAME(readlinkat) /* 285 */
ENTRY_SAME(fchmodat)
ENTRY_SAME(faccessat)
+ ENTRY_SAME(unshare)
+ ENTRY_COMP(set_robust_list)
+ ENTRY_COMP(get_robust_list) /* 290 */
+ ENTRY_SAME(splice)
+ ENTRY_OURS(sync_file_range)
+ ENTRY_SAME(tee)
/* Nothing yet */
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 6d6436a6b62..94dcc03a28e 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -6,6 +6,7 @@
* Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
* Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
* Copyright (C) 2003 James Bottomley <jejb with parisc-linux.org>
+ * Copyright (C) 2006 Helge Deller <deller@gmx.de>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -27,6 +28,7 @@
/* needed for the processor specific cache alignment size */
#include <asm/cache.h>
#include <asm/page.h>
+#include <asm/asm-offsets.h>
/* ld script to make hppa Linux kernel */
#ifndef CONFIG_64BIT
@@ -68,7 +70,7 @@ SECTIONS
RODATA
/* writeable */
- . = ALIGN(4096); /* Make sure this is page aligned so
+ . = ALIGN(ASM_PAGE_SIZE); /* Make sure this is page aligned so
that we can properly leave these
as writable */
data_start = .;
@@ -81,23 +83,17 @@ SECTIONS
__start___unwind = .; /* unwind info */
.PARISC.unwind : { *(.PARISC.unwind) }
__stop___unwind = .;
-
+
+ /* rarely changed data like cpu maps */
+ . = ALIGN(16);
+ .data.read_mostly : { *(.data.read_mostly) }
+
+ . = ALIGN(L1_CACHE_BYTES);
.data : { /* Data */
*(.data)
- *(.data.vm0.pmd)
- *(.data.vm0.pgd)
- *(.data.vm0.pte)
CONSTRUCTORS
}
- . = ALIGN(4096);
- /* nosave data is really only used for software suspend...it's here
- * just in case we ever implement it */
- __nosave_begin = .;
- .data_nosave : { *(.data.nosave) }
- . = ALIGN(4096);
- __nosave_end = .;
-
. = ALIGN(L1_CACHE_BYTES);
.data.cacheline_aligned : { *(.data.cacheline_aligned) }
@@ -105,12 +101,29 @@ SECTIONS
. = ALIGN(16);
.data.lock_aligned : { *(.data.lock_aligned) }
- /* rarely changed data like cpu maps */
- . = ALIGN(16);
- .data.read_mostly : { *(.data.read_mostly) }
+ . = ALIGN(ASM_PAGE_SIZE);
+ /* nosave data is really only used for software suspend...it's here
+ * just in case we ever implement it */
+ __nosave_begin = .;
+ .data_nosave : { *(.data.nosave) }
+ . = ALIGN(ASM_PAGE_SIZE);
+ __nosave_end = .;
_edata = .; /* End of data section */
+ __bss_start = .; /* BSS */
+ /* page table entries need to be PAGE_SIZE aligned */
+ . = ALIGN(ASM_PAGE_SIZE);
+ .data.vmpages : {
+ *(.data.vm0.pmd)
+ *(.data.vm0.pgd)
+ *(.data.vm0.pte)
+ }
+ .bss : { *(.bss) *(COMMON) }
+ __bss_stop = .;
+
+
+ /* assembler code expects init_task to be 16k aligned */
. = ALIGN(16384); /* init_task */
.data.init_task : { *(.data.init_task) }
@@ -126,6 +139,7 @@ SECTIONS
.dlt : { *(.dlt) }
#endif
+ /* reserve space for interrupt stack by aligning __init* to 16k */
. = ALIGN(16384);
__init_begin = .;
.init.text : {
@@ -166,7 +180,7 @@ SECTIONS
from .altinstructions and .eh_frame */
.exit.text : { *(.exit.text) }
.exit.data : { *(.exit.data) }
- . = ALIGN(4096);
+ . = ALIGN(ASM_PAGE_SIZE);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
__initramfs_end = .;
@@ -174,14 +188,10 @@ SECTIONS
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }
__per_cpu_end = .;
- . = ALIGN(4096);
+ . = ALIGN(ASM_PAGE_SIZE);
__init_end = .;
/* freed after init ends here */
- __bss_start = .; /* BSS */
- .bss : { *(.bss) *(COMMON) }
- __bss_stop = .;
-
_end = . ;
/* Sections to be discarded */
diff --git a/arch/parisc/lib/iomap.c b/arch/parisc/lib/iomap.c
index 01bec8fcbd0..f4a811690ab 100644
--- a/arch/parisc/lib/iomap.c
+++ b/arch/parisc/lib/iomap.c
@@ -263,11 +263,7 @@ static const struct iomap_ops iomem_ops = {
const struct iomap_ops *iomap_ops[8] = {
[0] = &ioport_ops,
-#ifdef CONFIG_DEBUG_IOREMAP
- [6] = &iomem_ops,
-#else
[7] = &iomem_ops
-#endif
};
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 0ad945d4c0a..64785e46f93 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -186,7 +186,7 @@ good_area:
break;
case VM_FAULT_SIGBUS:
/*
- * We hit a hared mapping outside of the file, or some
+ * We hit a shared mapping outside of the file, or some
* other thing happened to us that made us unable to
* handle the page fault gracefully.
*/
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 852eda3953d..63171256265 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -6,6 +6,7 @@
* changed by Philipp Rumpf
* Copyright 1999 Philipp Rumpf (prumpf@tux.org)
* Copyright 2004 Randolph Chung (tausq@debian.org)
+ * Copyright 2006 Helge Deller (deller@gmx.de)
*
*/
@@ -371,8 +372,8 @@ static void __init setup_bootmem(void)
void free_initmem(void)
{
- unsigned long addr;
-
+ unsigned long addr, init_begin, init_end;
+
printk(KERN_INFO "Freeing unused kernel memory: ");
#ifdef CONFIG_DEBUG_KERNEL
@@ -395,8 +396,11 @@ void free_initmem(void)
local_irq_enable();
#endif
- addr = (unsigned long)(&__init_begin);
- for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+ /* align __init_begin and __init_end to page size,
+ ignoring linker script where we might have tried to save RAM */
+ init_begin = PAGE_ALIGN((unsigned long)(&__init_begin));
+ init_end = PAGE_ALIGN((unsigned long)(&__init_end));
+ for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
init_page_count(virt_to_page(addr));
free_page(addr);
@@ -407,7 +411,7 @@ void free_initmem(void)
/* set up a new led state on systems shipped LED State panel */
pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE);
- printk("%luk freed\n", (unsigned long)(&__init_end - &__init_begin) >> 10);
+ printk("%luk freed\n", (init_end - init_begin) >> 10);
}
@@ -639,11 +643,13 @@ static void __init map_pages(unsigned long start_vaddr, unsigned long start_padd
* Map the fault vector writable so we can
* write the HPMC checksum.
*/
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
if (address >= ro_start && address < ro_end
&& address != fv_addr
&& address != gw_addr)
pte = __mk_pte(address, PAGE_KERNEL_RO);
else
+#endif
pte = __mk_pte(address, pgprot);
if (address >= end_paddr)
@@ -874,8 +880,7 @@ unsigned long alloc_sid(void)
flush_tlb_all(); /* flush_tlb_all() calls recycle_sids() */
spin_lock(&sid_lock);
}
- if (free_space_ids == 0)
- BUG();
+ BUG_ON(free_space_ids == 0);
}
free_space_ids--;
@@ -899,8 +904,7 @@ void free_sid(unsigned long spaceid)
spin_lock(&sid_lock);
- if (*dirty_space_offset & (1L << index))
- BUG(); /* attempt to free space id twice */
+ BUG_ON(*dirty_space_offset & (1L << index)); /* attempt to free space id twice */
*dirty_space_offset |= (1L << index);
dirty_space_ids++;
@@ -975,7 +979,7 @@ static void recycle_sids(void)
static unsigned long recycle_ndirty;
static unsigned long recycle_dirty_array[SID_ARRAY_SIZE];
-static unsigned int recycle_inuse = 0;
+static unsigned int recycle_inuse;
void flush_tlb_all(void)
{
@@ -984,9 +988,7 @@ void flush_tlb_all(void)
do_recycle = 0;
spin_lock(&sid_lock);
if (dirty_space_ids > RECYCLE_THRESHOLD) {
- if (recycle_inuse) {
- BUG(); /* FIXME: Use a semaphore/wait queue here */
- }
+ BUG_ON(recycle_inuse); /* FIXME: Use a semaphore/wait queue here */
get_dirty_sids(&recycle_ndirty,recycle_dirty_array);
recycle_inuse++;
do_recycle++;
@@ -1013,9 +1015,9 @@ void flush_tlb_all(void)
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
-#if 0
- if (start < end)
- printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+ if (start >= end)
+ return;
+ printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
@@ -1023,6 +1025,5 @@ void free_initrd_mem(unsigned long start, unsigned long end)
num_physpages++;
totalram_pages++;
}
-#endif
}
#endif
diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c
index edd9a9559cb..27384567a1d 100644
--- a/arch/parisc/mm/ioremap.c
+++ b/arch/parisc/mm/ioremap.c
@@ -2,7 +2,7 @@
* arch/parisc/mm/ioremap.c
*
* (C) Copyright 1995 1996 Linus Torvalds
- * (C) Copyright 2001 Helge Deller <deller@gmx.de>
+ * (C) Copyright 2001-2006 Helge Deller <deller@gmx.de>
* (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org>
*/
@@ -72,7 +72,6 @@ remap_area_pmd(pmd_t *pmd, unsigned long address, unsigned long size,
return 0;
}
-#if USE_HPPA_IOREMAP
static int
remap_area_pages(unsigned long address, unsigned long phys_addr,
unsigned long size, unsigned long flags)
@@ -114,31 +113,6 @@ remap_area_pages(unsigned long address, unsigned long phys_addr,
return error;
}
-#endif /* USE_HPPA_IOREMAP */
-
-#ifdef CONFIG_DEBUG_IOREMAP
-static unsigned long last = 0;
-
-void gsc_bad_addr(unsigned long addr)
-{
- if (time_after(jiffies, last + HZ*10)) {
- printk("gsc_foo() called with bad address 0x%lx\n", addr);
- dump_stack();
- last = jiffies;
- }
-}
-EXPORT_SYMBOL(gsc_bad_addr);
-
-void __raw_bad_addr(const volatile void __iomem *addr)
-{
- if (time_after(jiffies, last + HZ*10)) {
- printk("__raw_foo() called with bad address 0x%p\n", addr);
- dump_stack();
- last = jiffies;
- }
-}
-EXPORT_SYMBOL(__raw_bad_addr);
-#endif
/*
* Generic mapping function (not visible outside):
@@ -154,26 +128,20 @@ EXPORT_SYMBOL(__raw_bad_addr);
*/
void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
{
-#if !(USE_HPPA_IOREMAP)
+ void *addr;
+ struct vm_struct *area;
+ unsigned long offset, last_addr;
+#ifdef CONFIG_EISA
unsigned long end = phys_addr + size - 1;
/* Support EISA addresses */
- if ((phys_addr >= 0x00080000 && end < 0x000fffff)
- || (phys_addr >= 0x00500000 && end < 0x03bfffff)) {
- phys_addr |= 0xfc000000;
+ if ((phys_addr >= 0x00080000 && end < 0x000fffff) ||
+ (phys_addr >= 0x00500000 && end < 0x03bfffff)) {
+ phys_addr |= F_EXTEND(0xfc000000);
+ flags |= _PAGE_NO_CACHE;
}
-
-#ifdef CONFIG_DEBUG_IOREMAP
- return (void __iomem *)(phys_addr - (0x1UL << NYBBLE_SHIFT));
-#else
- return (void __iomem *)phys_addr;
#endif
-#else
- void *addr;
- struct vm_struct *area;
- unsigned long offset, last_addr;
-
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
if (!size || last_addr < phys_addr)
@@ -217,15 +185,12 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
}
return (void __iomem *) (offset + (char *)addr);
-#endif
}
+EXPORT_SYMBOL(__ioremap);
void iounmap(void __iomem *addr)
{
-#if !(USE_HPPA_IOREMAP)
- return;
-#else
if (addr > high_memory)
return vfree((void *) (PAGE_MASK & (unsigned long __force) addr));
-#endif
}
+EXPORT_SYMBOL(iounmap);
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index a433b7126d3..6729c98b66f 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -366,6 +366,7 @@ config PPC_PMAC64
select U3_DART
select MPIC_BROKEN_U3
select GENERIC_TBSYNC
+ select PPC_970_NAP
default y
config PPC_PREP
@@ -383,6 +384,7 @@ config PPC_MAPLE
select MPIC_BROKEN_U3
select GENERIC_TBSYNC
select PPC_UDBG_16550
+ select PPC_970_NAP
default n
help
This option enables support for the Maple 970FX Evaluation Board.
@@ -457,6 +459,10 @@ config PPC_MPC106
bool
default n
+config PPC_970_NAP
+ bool
+ default n
+
source "drivers/cpufreq/Kconfig"
config CPU_FREQ_PMAC
@@ -491,7 +497,7 @@ config PPC601_SYNC_FIX
If in doubt, say Y here.
config TAU
- bool "Thermal Management Support"
+ bool "On-chip CPU temperature sensor support"
depends on 6xx
help
G3 and G4 processors have an on-chip temperature sensor called the
@@ -500,7 +506,7 @@ config TAU
on-die temperature in /proc/cpuinfo if the cpu supports it.
Unfortunately, on some chip revisions, this sensor is very inaccurate
- and in some cases, does not work at all, so don't assume the cpu
+ and in many cases, does not work at all, so don't assume the cpu
temp is actually what /proc/cpuinfo says it is.
config TAU_INT
@@ -649,6 +655,11 @@ config NUMA
depends on PPC64
default y if SMP && PPC_PSERIES
+config NODES_SHIFT
+ int
+ default "4"
+ depends on NEED_MULTIPLE_NODES
+
config ARCH_SELECT_MEMORY_MODEL
def_bool y
depends on PPC64
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 9254806f703..8d48e9e7162 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -110,11 +110,6 @@ config SERIAL_TEXT_DEBUG
depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \
PPC_GEN550 || PPC_MPC52xx
-config PPC_OCP
- bool
- depends on IBM_OCP || XILINX_OCP
- default y
-
choice
prompt "Early debugging (dangerous)"
bool
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 829e017b8a5..ed5b26aa8be 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -104,6 +104,10 @@ ifndef CONFIG_FSL_BOOKE
CFLAGS += -mstring
endif
+ifeq ($(CONFIG_6xx),y)
+CFLAGS += -mcpu=powerpc
+endif
+
cpu-as-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge
cpu-as-$(CONFIG_4xx) += -Wa,-m405
cpu-as-$(CONFIG_6xx) += -Wa,-maltivec
@@ -129,13 +133,8 @@ core-y += arch/powerpc/kernel/ \
arch/powerpc/lib/ \
arch/powerpc/sysdev/ \
arch/powerpc/platforms/
-core-$(CONFIG_PPC32) += arch/ppc/kernel/
-core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/
+core-$(CONFIG_MATH_EMULATION) += arch/powerpc/math-emu/
core-$(CONFIG_XMON) += arch/powerpc/xmon/
-core-$(CONFIG_APUS) += arch/ppc/amiga/
-drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/
-drivers-$(CONFIG_4xx) += arch/ppc/4xx_io/
-drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/
drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index 3c2acab6373..dbe421dc3c1 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc6
-# Wed Mar 15 16:19:48 2006
+# Linux kernel version: 2.6.16
+# Thu Mar 23 20:48:09 2006
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -30,6 +31,7 @@ CONFIG_POWER4=y
CONFIG_PPC_FPU=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=4
@@ -51,8 +53,10 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
@@ -67,10 +71,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -82,15 +82,15 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
+CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -124,13 +124,15 @@ CONFIG_RTAS_FLASH=y
CONFIG_MMIO_NVRAM=y
CONFIG_CELL_IIC=y
# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_WANT_EARLY_SERIAL is not set
#
# Cell Broadband Engine options
#
-CONFIG_SPU_FS=y
+CONFIG_SPU_FS=m
+CONFIG_SPUFS_MMAP=y
#
# Kernel options
@@ -144,7 +146,7 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT is not set
CONFIG_PREEMPT_BKL=y
CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=m
CONFIG_FORCE_MAX_ZONEORDER=13
# CONFIG_IOMMU_VMERGE is not set
CONFIG_KEXEC=y
@@ -155,12 +157,14 @@ CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
+# CONFIG_FLATMEM_MANUAL is not set
# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_EXTREME=y
+# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_PPC_64K_PAGES is not set
CONFIG_SCHED_SMT=y
@@ -178,7 +182,6 @@ CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -220,6 +223,7 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -232,9 +236,11 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_IP_VS is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -244,25 +250,7 @@ CONFIG_NETFILTER=y
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK is not set
-CONFIG_NETFILTER_XTABLES=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XTABLES is not set
#
# IP: Netfilter Configuration
@@ -278,51 +266,13 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
#
# IPv6: Netfilter Configuration (EXPERIMENTAL)
#
# CONFIG_IP6_NF_QUEUE is not set
-# CONFIG_IP6_NF_IPTABLES is not set
#
# DCCP Configuration (EXPERIMENTAL)
@@ -355,7 +305,6 @@ CONFIG_IP_NF_ARP_MANGLE=m
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
#
# Network testing
@@ -408,7 +357,7 @@ CONFIG_FW_LOADER=y
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
@@ -484,7 +433,23 @@ CONFIG_IDEDMA_AUTO=y
#
# Multi-device support (RAID and LVM)
#
-# CONFIG_MD is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_EMC is not set
#
# Fusion MPT device support
@@ -548,7 +513,7 @@ CONFIG_MII=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=m
-# CONFIG_E1000_NAPI is not set
+CONFIG_E1000_NAPI=y
# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
@@ -560,7 +525,7 @@ CONFIG_SKGE=m
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
-CONFIG_SPIDER_NET=y
+CONFIG_SPIDER_NET=m
# CONFIG_MV643XX_ETH is not set
#
@@ -666,6 +631,7 @@ CONFIG_SERIAL_NONSTANDARD=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -678,6 +644,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_RTAS=y
#
# IPMI
@@ -694,14 +662,13 @@ CONFIG_WATCHDOG=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WATCHDOG_RTAS is not set
+CONFIG_WATCHDOG_RTAS=y
#
# PCI-based Watchdog Cards
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
-# CONFIG_RTC is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
# CONFIG_DTLK is not set
@@ -750,7 +717,6 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -769,9 +735,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -799,10 +763,6 @@ CONFIG_I2C_ALGOBIT=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -833,6 +793,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -850,15 +811,40 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
-# CONFIG_INFINIBAND is not set
+CONFIG_INFINIBAND=y
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
#
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -914,7 +900,6 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -1037,10 +1022,6 @@ CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
#
# Instrumentation Support
@@ -1058,7 +1039,7 @@ CONFIG_LOG_BUF_SHIFT=15
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_MUTEXES is not set
+CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK is not set
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_KOBJECT is not set
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 2c3fd200767..a45627547d0 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Fri Feb 10 17:33:08 2006
+# Linux kernel version: 2.6.17-rc1
+# Wed Apr 19 13:24:37 2006
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -29,6 +30,7 @@ CONFIG_POWER4=y
CONFIG_PPC_FPU=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=4
@@ -53,6 +55,7 @@ CONFIG_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
@@ -67,10 +70,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -82,7 +81,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -91,6 +89,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -185,7 +184,6 @@ CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -227,6 +225,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -238,6 +237,8 @@ CONFIG_TCP_CONG_BIC=y
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -261,6 +262,7 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
CONFIG_IP_NF_QUEUE=m
#
@@ -513,6 +515,7 @@ CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -761,7 +764,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
# CONFIG_DTLK is not set
@@ -772,6 +774,7 @@ CONFIG_GEN_RTC=y
# Ftape, the floppy tape device driver
#
CONFIG_AGP=m
+# CONFIG_AGP_VIA is not set
CONFIG_AGP_UNINORTH=m
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=y
@@ -813,7 +816,6 @@ CONFIG_I2C_POWERMAC=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -832,9 +834,7 @@ CONFIG_I2C_POWERMAC=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -862,10 +862,6 @@ CONFIG_I2C_POWERMAC=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -874,6 +870,7 @@ CONFIG_I2C_POWERMAC=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -883,6 +880,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_MACMODES=y
+CONFIG_FB_FIRMWARE_EDID=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
@@ -901,7 +899,6 @@ CONFIG_FB_NVIDIA=y
CONFIG_FB_NVIDIA_I2C=y
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
CONFIG_FB_RADEON=y
CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_RADEON_DEBUG is not set
@@ -958,9 +955,11 @@ CONFIG_SND_SEQUENCER=m
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
@@ -977,6 +976,7 @@ CONFIG_SND_SUPPORT_OLD_API=y
# PCI devices
#
# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
# CONFIG_SND_ALS4000 is not set
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ATIIXP is not set
@@ -1009,6 +1009,7 @@ CONFIG_SND_SUPPORT_OLD_API=y
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
# CONFIG_SND_RME32 is not set
# CONFIG_SND_RME96 is not set
# CONFIG_SND_RME9652 is not set
@@ -1041,6 +1042,7 @@ CONFIG_SND_USB_AUDIO=m
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -1068,7 +1070,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
#
# USB Device Class drivers
#
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=y
@@ -1126,15 +1127,6 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
CONFIG_USB_CATC=m
@@ -1194,6 +1186,7 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
CONFIG_USB_SERIAL_KLSI=m
CONFIG_USB_SERIAL_KOBIL_SCT=m
CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
CONFIG_USB_SERIAL_PL2303=m
# CONFIG_USB_SERIAL_HP4X is not set
CONFIG_USB_SERIAL_SAFE=m
@@ -1237,17 +1230,23 @@ CONFIG_USB_EZUSB=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1319,7 +1318,6 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index 1816a46742f..a95e455a194 100644
--- a/arch/powerpc/configs/iseries_defconfig
+++ b/arch/powerpc/configs/iseries_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc6
-# Wed Mar 15 16:19:52 2006
+# Linux kernel version: 2.6.17-rc1
+# Wed Apr 19 11:46:44 2006
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -30,6 +31,7 @@ CONFIG_POWER4=y
CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=32
@@ -55,6 +57,7 @@ CONFIG_AUDITSYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
@@ -69,10 +72,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -84,7 +83,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -93,6 +91,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -165,7 +164,6 @@ CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -207,6 +205,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -218,6 +217,8 @@ CONFIG_TCP_CONG_BIC=y
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -236,11 +237,14 @@ CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -262,20 +266,19 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+# CONFIG_IP_NF_MATCH_AH is not set
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_MATCH_OWNER=m
CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -479,6 +482,7 @@ CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -702,7 +706,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
# CONFIG_DTLK is not set
@@ -751,10 +754,6 @@ CONFIG_MAX_RAW_DEVS=256
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -779,6 +778,7 @@ CONFIG_MAX_RAW_DEVS=256
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -796,6 +796,11 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
@@ -805,6 +810,11 @@ CONFIG_USB_ARCH_HAS_OHCI=y
#
#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -878,7 +888,6 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig
index 2a8290ee15c..7f0780f1aa3 100644
--- a/arch/powerpc/configs/mpc8540_ads_defconfig
+++ b/arch/powerpc/configs/mpc8540_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version:
-# Sat Jan 14 15:57:54 2006
+# Linux kernel version: 2.6.16
+# Mon Mar 27 23:37:36 2006
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -18,6 +19,7 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_DEFAULT_UIMAGE=y
#
# Processor support
@@ -42,7 +44,6 @@ CONFIG_SPE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -58,6 +59,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -72,10 +74,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -90,6 +88,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -183,6 +183,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -220,6 +221,11 @@ CONFIG_TCP_CONG_BIC=y
# 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
# CONFIG_VLAN_8021Q is not set
@@ -229,11 +235,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -487,6 +488,12 @@ CONFIG_GEN_RTC=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
@@ -496,6 +503,7 @@ CONFIG_GEN_RTC=y
#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
@@ -503,10 +511,6 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -531,6 +535,7 @@ CONFIG_HWMON=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -551,7 +556,7 @@ CONFIG_HWMON=y
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
@@ -603,7 +608,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -658,6 +662,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
#
@@ -695,6 +700,8 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index daaf038a1fa..58e68ce09b0 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Fri Feb 10 17:33:32 2006
+# Linux kernel version: 2.6.17-rc1
+# Wed Apr 19 11:48:00 2006
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -30,6 +31,7 @@ CONFIG_POWER4=y
CONFIG_PPC_FPU=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=128
@@ -55,6 +57,7 @@ CONFIG_AUDITSYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CPUSETS=y
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
@@ -69,10 +72,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -84,7 +83,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -93,6 +91,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -188,7 +187,6 @@ CONFIG_PPC_I8259=y
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -235,6 +233,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -246,6 +245,8 @@ CONFIG_TCP_CONG_BIC=y
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -272,6 +273,7 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
CONFIG_IP_NF_QUEUE=m
#
@@ -519,6 +521,7 @@ CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
@@ -750,6 +753,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -767,7 +771,9 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_PRINTER is not set
# CONFIG_PPDEV is not set
# CONFIG_TIPAR is not set
+CONFIG_HVC_DRIVER=y
CONFIG_HVC_CONSOLE=y
+# CONFIG_HVC_RTAS is not set
CONFIG_HVCS=m
#
@@ -779,7 +785,6 @@ CONFIG_HVCS=m
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
# CONFIG_DTLK is not set
@@ -830,7 +835,6 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -849,9 +853,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -879,10 +881,6 @@ CONFIG_I2C_ALGOBIT=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -891,6 +889,7 @@ CONFIG_I2C_ALGOBIT=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -900,6 +899,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_MACMODES=y
+CONFIG_FB_FIRMWARE_EDID=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
@@ -919,7 +919,6 @@ CONFIG_FB_MATROX_MYSTIQUE=y
CONFIG_FB_MATROX_G=y
# CONFIG_FB_MATROX_I2C is not set
CONFIG_FB_MATROX_MULTIHEAD=y
-# CONFIG_FB_RADEON_OLD is not set
CONFIG_FB_RADEON=y
CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_RADEON_DEBUG is not set
@@ -968,6 +967,7 @@ CONFIG_LCD_DEVICE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -1048,15 +1048,6 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1109,6 +1100,11 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
# InfiniBand support
#
CONFIG_INFINIBAND=m
@@ -1121,12 +1117,13 @@ CONFIG_INFINIBAND_IPOIB=m
# CONFIG_INFINIBAND_SRP is not set
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
#
+# CONFIG_RTC_CLASS is not set
#
# File systems
@@ -1202,7 +1199,6 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 80e9fe2632b..803858e8616 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -12,15 +12,15 @@ 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
+ init_task.o process.o systbl.o idle.o
obj-y += vdso32/
obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
signal_64.o ptrace32.o \
paca.o cpu_setup_power4.o \
- firmware.o sysfs.o idle_64.o
+ firmware.o sysfs.o
obj-$(CONFIG_PPC64) += vdso64/
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
-obj-$(CONFIG_POWER4) += idle_power4.o
+obj-$(CONFIG_PPC_970_NAP) += idle_power4.o
obj-$(CONFIG_PPC_OF) += of_device.o prom_parse.o
procfs-$(CONFIG_PPC64) := proc_ppc64.o
obj-$(CONFIG_PROC_FS) += $(procfs-y)
@@ -34,6 +34,11 @@ obj-$(CONFIG_IBMEBUS) += ibmebus.o
obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
+obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
+obj-$(CONFIG_TAU) += tau_6xx.o
+obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o
+obj32-$(CONFIG_MODULES) += module_32.o
+obj-$(CONFIG_E500) += perfmon_fsl_booke.o
ifeq ($(CONFIG_PPC_MERGE),y)
@@ -51,7 +56,6 @@ obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
obj-$(CONFIG_MODULES) += ppc_ksyms.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o
-obj-$(CONFIG_6xx) += idle_6xx.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
@@ -77,6 +81,7 @@ smpobj-$(CONFIG_SMP) += smp.o
endif
+obj-$(CONFIG_PPC32) += $(obj32-y)
obj-$(CONFIG_PPC64) += $(obj64-y)
extra-$(CONFIG_PPC_FPU) += fpu.o
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 882889b1592..8f85c5e8a55 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -91,6 +91,7 @@ int main(void)
#endif /* CONFIG_PPC64 */
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
DEFINE(TI_TASK, offsetof(struct thread_info, task));
#ifdef CONFIG_PPC32
@@ -105,8 +106,6 @@ int main(void)
DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size));
DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size));
DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page));
- DEFINE(PLATFORM_LPAR, PLATFORM_LPAR);
-
/* paca */
DEFINE(PACA_SIZE, sizeof(struct paca_struct));
DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index));
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S
index 55ed7716636..55ed7716636 100644
--- a/arch/ppc/kernel/cpu_setup_6xx.S
+++ b/arch/powerpc/kernel/cpu_setup_6xx.S
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 39e348a3ade..3f7182db9ed 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -57,6 +57,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
#define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\
PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
+#define COMMON_USER_POWER6 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\
+ PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
PPC_FEATURE_BOOKE)
@@ -263,6 +265,20 @@ struct cpu_spec cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_POWER4,
.platform = "power5+",
},
+ { /* Power6 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x003e0000,
+ .cpu_name = "POWER6",
+ .cpu_features = CPU_FTRS_POWER6,
+ .cpu_user_features = COMMON_USER_POWER6,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_power4,
+ .oprofile_cpu_type = "ppc64/power6",
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .platform = "power6",
+ },
{ /* Cell Broadband Engine */
.pvr_mask = 0xffff0000,
.pvr_value = 0x00700000,
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 211d72653ea..764d0732971 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -61,7 +61,7 @@ static int __init parse_elfcorehdr(char *p)
if (p)
elfcorehdr_addr = memparse(p, &p);
- return 0;
+ return 1;
}
__setup("elfcorehdr=", parse_elfcorehdr);
#endif
@@ -71,7 +71,7 @@ static int __init parse_savemaxmem(char *p)
if (p)
saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1;
- return 0;
+ return 1;
}
__setup("savemaxmem=", parse_savemaxmem);
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 4827ca1ec89..8866fd26c6b 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -128,45 +128,48 @@ transfer_to_handler:
stw r12,4(r11)
#endif
b 3f
+
2: /* if from kernel, check interrupted DOZE/NAP mode and
* check for stack overflow
*/
+ lwz r9,THREAD_INFO-THREAD(r12)
+ cmplw r1,r9 /* if r1 <= current->thread_info */
+ ble- stack_ovf /* then the kernel stack overflowed */
+5:
#ifdef CONFIG_6xx
- mfspr r11,SPRN_HID0
- mtcr r11
-BEGIN_FTR_SECTION
- bt- 8,power_save_6xx_restore /* Check DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-BEGIN_FTR_SECTION
- bt- 9,power_save_6xx_restore /* Check NAP */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+ tophys(r9,r9) /* check local flags */
+ lwz r12,TI_LOCAL_FLAGS(r9)
+ mtcrf 0x01,r12
+ bt- 31-TLF_NAPPING,4f
#endif /* CONFIG_6xx */
.globl transfer_to_handler_cont
transfer_to_handler_cont:
- lwz r11,THREAD_INFO-THREAD(r12)
- cmplw r1,r11 /* if r1 <= current->thread_info */
- ble- stack_ovf /* then the kernel stack overflowed */
3:
mflr r9
lwz r11,0(r9) /* virtual address of handler */
lwz r9,4(r9) /* where to go when done */
- FIX_SRR1(r10,r12)
mtspr SPRN_SRR0,r11
mtspr SPRN_SRR1,r10
mtlr r9
SYNC
RFI /* jump to handler, enable MMU */
+#ifdef CONFIG_6xx
+4: rlwinm r12,r12,0,~_TLF_NAPPING
+ stw r12,TI_LOCAL_FLAGS(r9)
+ b power_save_6xx_restore
+#endif
+
/*
* On kernel stack overflow, load up an initial stack pointer
* and call StackOverflow(regs), which should not return.
*/
stack_ovf:
/* sometimes we use a statically-allocated stack, which is OK. */
- lis r11,_end@h
- ori r11,r11,_end@l
- cmplw r1,r11
- ble 3b /* r1 <= &_end is OK */
+ lis r12,_end@h
+ ori r12,r12,_end@l
+ cmplw r1,r12
+ ble 5b /* r1 <= &_end is OK */
SAVE_NVGPRS(r11)
addi r3,r1,STACK_FRAME_OVERHEAD
lis r1,init_thread_union@ha
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 1060155d84c..19ad5c6b181 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -617,6 +617,12 @@ _GLOBAL(enter_rtas)
mfsrr1 r10
std r10,_SRR1(r1)
+ /* Temporary workaround to clear CR until RTAS can be modified to
+ * ignore all bits.
+ */
+ li r0,0
+ mtcr r0
+
/* There is no way it is acceptable to get here with interrupts enabled,
* check it with the asm equivalent of WARN_ON
*/
diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c
index 4d37a3cb80f..0bfe9061720 100644
--- a/arch/powerpc/kernel/firmware.c
+++ b/arch/powerpc/kernel/firmware.c
@@ -14,7 +14,9 @@
*/
#include <linux/config.h>
+#include <linux/module.h>
#include <asm/firmware.h>
-unsigned long ppc64_firmware_features;
+unsigned long powerpc_firmware_features;
+EXPORT_SYMBOL_GPL(powerpc_firmware_features);
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 35084f3a841..b7d140430a4 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -376,11 +376,28 @@ label##_common: \
bl hdlr; \
b .ret_from_except
+/*
+ * Like STD_EXCEPTION_COMMON, but for exceptions that can occur
+ * in the idle task and therefore need the special idle handling.
+ */
+#define STD_EXCEPTION_COMMON_IDLE(trap, label, hdlr) \
+ .align 7; \
+ .globl label##_common; \
+label##_common: \
+ EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \
+ FINISH_NAP; \
+ DISABLE_INTS; \
+ bl .save_nvgprs; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ bl hdlr; \
+ b .ret_from_except
+
#define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr) \
.align 7; \
.globl label##_common; \
label##_common: \
EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \
+ FINISH_NAP; \
DISABLE_INTS; \
bl .ppc64_runlatch_on; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
@@ -388,6 +405,25 @@ label##_common: \
b .ret_from_except_lite
/*
+ * When the idle code in power4_idle puts the CPU into NAP mode,
+ * it has to do so in a loop, and relies on the external interrupt
+ * and decrementer interrupt entry code to get it out of the loop.
+ * It sets the _TLF_NAPPING bit in current_thread_info()->local_flags
+ * to signal that it is in the loop and needs help to get out.
+ */
+#ifdef CONFIG_PPC_970_NAP
+#define FINISH_NAP \
+BEGIN_FTR_SECTION \
+ clrrdi r11,r1,THREAD_SHIFT; \
+ ld r9,TI_LOCAL_FLAGS(r11); \
+ andi. r10,r9,_TLF_NAPPING; \
+ bnel power4_fixup_nap; \
+END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+#else
+#define FINISH_NAP
+#endif
+
+/*
* Start of pSeries system interrupt routines
*/
. = 0x100
@@ -772,6 +808,7 @@ hardware_interrupt_iSeries_masked:
.globl machine_check_common
machine_check_common:
EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
+ FINISH_NAP
DISABLE_INTS
bl .save_nvgprs
addi r3,r1,STACK_FRAME_OVERHEAD
@@ -783,7 +820,7 @@ machine_check_common:
STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
- STD_EXCEPTION_COMMON(0xf00, performance_monitor, .performance_monitor_exception)
+ STD_EXCEPTION_COMMON_IDLE(0xf00, performance_monitor, .performance_monitor_exception)
STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
#ifdef CONFIG_ALTIVEC
STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
@@ -1034,6 +1071,7 @@ unrecov_slb:
.globl hardware_interrupt_entry
hardware_interrupt_common:
EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN)
+ FINISH_NAP
hardware_interrupt_entry:
DISABLE_INTS
bl .ppc64_runlatch_on
@@ -1041,6 +1079,15 @@ hardware_interrupt_entry:
bl .do_IRQ
b .ret_from_except_lite
+#ifdef CONFIG_PPC_970_NAP
+power4_fixup_nap:
+ andc r9,r9,r10
+ std r9,TI_LOCAL_FLAGS(r11)
+ ld r10,_LINK(r1) /* make idle task do the */
+ std r10,_NIP(r1) /* equivalent of a blr */
+ blr
+#endif
+
.align 7
.globl alignment_common
alignment_common:
@@ -1544,7 +1591,11 @@ _STATIC(__boot_from_prom)
mr r28,r6
mr r27,r7
- /* Align the stack to 16-byte boundary for broken yaboot */
+ /*
+ * Align the stack to 16-byte boundary
+ * Depending on the size and layout of the ELF sections in the initial
+ * boot binary, the stack pointer will be unalignet on PowerMac
+ */
rldicr r1,r1,0,59
/* Make sure we are running in 64 bits mode */
@@ -1847,21 +1898,6 @@ _STATIC(start_here_multiplatform)
bl .__save_cpu_setup
sync
- /* Setup a valid physical PACA pointer in SPRG3 for early_setup
- * note that boot_cpuid can always be 0 nowadays since there is
- * nowhere it can be initialized differently before we reach this
- * code
- */
- LOAD_REG_IMMEDIATE(r27, boot_cpuid)
- add r27,r27,r26
- lwz r27,0(r27)
-
- LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */
- mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */
- add r13,r13,r24 /* for this processor. */
- add r13,r13,r26 /* convert to physical addr */
- mtspr SPRN_SPRG3,r13
-
/* Do very early kernel initializations, including initial hash table,
* stab and slb setup before we turn on relocation. */
@@ -1930,6 +1966,17 @@ _STATIC(start_here_common)
/* Not reached */
BUG_OPCODE
+/* Put the paca pointer into r13 and SPRG3 */
+_GLOBAL(setup_boot_paca)
+ LOAD_REG_IMMEDIATE(r3, boot_cpuid)
+ lwz r3,0(r3)
+ LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */
+ mulli r3,r3,PACA_SIZE /* Calculate vaddr of right paca */
+ add r13,r3,r4 /* for this processor. */
+ mtspr SPRN_SPRG3,r13
+
+ blr
+
/*
* We put a few things here that have to be page-aligned.
* This stuff goes at the beginning of the bss, which is page-aligned.
diff --git a/arch/powerpc/kernel/idle_64.c b/arch/powerpc/kernel/idle.c
index b879d3057ef..d491052c8e0 100644
--- a/arch/powerpc/kernel/idle_64.c
+++ b/arch/powerpc/kernel/idle.c
@@ -2,13 +2,17 @@
* Idle daemon for PowerPC. Idle daemon will handle any action
* that needs to be taken when the system becomes idle.
*
- * Originally Written by Cort Dougan (cort@cs.nmt.edu)
+ * Originally written by Cort Dougan (cort@cs.nmt.edu).
+ * Subsequent 32-bit hacking by Tom Rini, Armin Kuster,
+ * Paul Mackerras and others.
*
* iSeries supported added by Mike Corrigan <mikejc@us.ibm.com>
*
* Additional shared processor, SMT, and firmware support
* Copyright (c) 2003 Dave Engebretsen <engebret@us.ibm.com>
*
+ * 32-bit and 64-bit versions merged by Paul Mackerras <paulus@samba.org>
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -29,18 +33,43 @@
#include <asm/machdep.h>
#include <asm/smp.h>
-extern void power4_idle(void);
+#ifdef CONFIG_HOTPLUG_CPU
+#define cpu_should_die() (cpu_is_offline(smp_processor_id()) && \
+ system_state == SYSTEM_RUNNING)
+#else
+#define cpu_should_die() 0
+#endif
-void default_idle(void)
+/*
+ * The body of the idle task.
+ */
+void cpu_idle(void)
{
- unsigned int cpu = smp_processor_id();
- set_thread_flag(TIF_POLLING_NRFLAG);
+ if (ppc_md.idle_loop)
+ ppc_md.idle_loop(); /* doesn't return */
+ set_thread_flag(TIF_POLLING_NRFLAG);
while (1) {
- if (!need_resched()) {
- while (!need_resched() && !cpu_is_offline(cpu)) {
- ppc64_runlatch_off();
+ while (!need_resched() && !cpu_should_die()) {
+ ppc64_runlatch_off();
+ if (ppc_md.power_save) {
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+ /*
+ * smp_mb is so clearing of TIF_POLLING_NRFLAG
+ * is ordered w.r.t. need_resched() test.
+ */
+ smp_mb();
+ local_irq_disable();
+
+ /* check again after disabling irqs */
+ if (!need_resched() && !cpu_should_die())
+ ppc_md.power_save();
+
+ local_irq_enable();
+ set_thread_flag(TIF_POLLING_NRFLAG);
+
+ } else {
/*
* Go into low thread priority and possibly
* low power mode.
@@ -48,46 +77,18 @@ void default_idle(void)
HMT_low();
HMT_very_low();
}
-
- HMT_medium();
}
+ HMT_medium();
ppc64_runlatch_on();
+ if (cpu_should_die())
+ cpu_die();
preempt_enable_no_resched();
schedule();
preempt_disable();
- if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
- cpu_die();
}
}
-void native_idle(void)
-{
- while (1) {
- ppc64_runlatch_off();
-
- if (!need_resched())
- power4_idle();
-
- if (need_resched()) {
- ppc64_runlatch_on();
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
- }
-
- if (cpu_is_offline(smp_processor_id()) &&
- system_state == SYSTEM_RUNNING)
- cpu_die();
- }
-}
-
-void cpu_idle(void)
-{
- BUG_ON(NULL == ppc_md.idle_loop);
- ppc_md.idle_loop();
-}
-
int powersave_nap;
#ifdef CONFIG_SYSCTL
diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S
index 444fdcc769f..b45fa0e3721 100644
--- a/arch/powerpc/kernel/idle_6xx.S
+++ b/arch/powerpc/kernel/idle_6xx.S
@@ -22,8 +22,6 @@
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
-#undef DEBUG
-
.text
/*
@@ -87,19 +85,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
cmpwi 0,r3,0
beqlr
- /* Clear MSR:EE */
- mfmsr r7
- rlwinm r0,r7,0,17,15
- mtmsr r0
-
- /* Check current_thread_info()->flags */
- rlwinm r4,r1,0,0,18
- lwz r4,TI_FLAGS(r4)
- andi. r0,r4,_TIF_NEED_RESCHED
- beq 1f
- mtmsr r7 /* out of line this ? */
- blr
-1:
/* Some pre-nap cleanups needed on some CPUs */
andis. r0,r3,HID0_NAP@h
beq 2f
@@ -122,12 +107,6 @@ BEGIN_FTR_SECTION
dcbf 0,r4
dcbf 0,r4
END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-#ifdef DEBUG
- lis r6,nap_enter_count@ha
- lwz r4,nap_enter_count@l(r6)
- addi r4,r4,1
- stw r4,nap_enter_count@l(r6)
-#endif
2:
BEGIN_FTR_SECTION
/* Go to low speed mode on some 750FX */
@@ -157,47 +136,42 @@ BEGIN_FTR_SECTION
DSSALL
sync
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
- ori r7,r7,MSR_EE /* Could be ommited (already set) */
+ rlwinm r9,r1,0,0,31-THREAD_SHIFT /* current thread_info */
+ lwz r8,TI_LOCAL_FLAGS(r9) /* set napping bit */
+ ori r8,r8,_TLF_NAPPING /* so when we take an exception */
+ stw r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */
+ mfmsr r7
+ ori r7,r7,MSR_EE
oris r7,r7,MSR_POW@h
- sync
- isync
+1: sync
mtmsr r7
isync
- sync
- blr
-
+ b 1b
+
/*
* Return from NAP/DOZE mode, restore some CPU specific registers,
* we are called with DR/IR still off and r2 containing physical
- * address of current.
+ * address of current. R11 points to the exception frame (physical
+ * address). We have to preserve r10.
*/
_GLOBAL(power_save_6xx_restore)
- mfspr r11,SPRN_HID0
- rlwinm. r11,r11,0,10,8 /* Clear NAP & copy NAP bit !state to cr1 EQ */
- cror 4*cr1+eq,4*cr0+eq,4*cr0+eq
-BEGIN_FTR_SECTION
- rlwinm r11,r11,0,9,7 /* Clear DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
- mtspr SPRN_HID0, r11
+ lwz r9,_LINK(r11) /* interrupted in ppc6xx_idle: */
+ stw r9,_NIP(r11) /* make it do a blr */
-#ifdef DEBUG
- beq cr1,1f
- lis r11,(nap_return_count-KERNELBASE)@ha
- lwz r9,nap_return_count@l(r11)
- addi r9,r9,1
- stw r9,nap_return_count@l(r11)
-1:
-#endif
-
- rlwinm r9,r1,0,0,18
- tophys(r9,r9)
- lwz r11,TI_CPU(r9)
+#ifdef CONFIG_SMP
+ mfspr r12,SPRN_SPRG3
+ lwz r11,TI_CPU(r12) /* get cpu number * 4 */
slwi r11,r11,2
+#else
+ li r11,0
+#endif
/* Todo make sure all these are in the same page
- * and load r22 (@ha part + CPU offset) only once
+ * and load r11 (@ha part + CPU offset) only once
*/
BEGIN_FTR_SECTION
- beq cr1,1f
+ mfspr r9,SPRN_HID0
+ andis. r9,r9,HID0_NAP@h
+ beq 1f
addis r9,r11,(nap_save_msscr0-KERNELBASE)@ha
lwz r9,nap_save_msscr0@l(r9)
mtspr SPRN_MSSCR0, r9
@@ -220,14 +194,5 @@ _GLOBAL(nap_save_msscr0)
_GLOBAL(nap_save_hid1)
.space 4*NR_CPUS
-_GLOBAL(powersave_nap)
- .long 0
_GLOBAL(powersave_lowspeed)
.long 0
-
-#ifdef DEBUG
-_GLOBAL(nap_enter_count)
- .space 4
-_GLOBAL(nap_return_count)
- .space 4
-#endif
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index c16b4afab58..d85c7c938ee 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -1,11 +1,5 @@
/*
- * This file contains the power_save function for 6xx & 7xxx CPUs
- * rewritten in assembler
- *
- * Warning ! This code assumes that if your machine has a 750fx
- * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
- * if this is not the case some additional changes will have to
- * be done to check a runtime var (a bit like powersave-nap)
+ * This file contains the power_save function for 970-family CPUs.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -26,53 +20,31 @@
.text
-/*
- * Here is the power_save_6xx function. This could eventually be
- * split into several functions & changing the function pointer
- * depending on the various features.
- */
_GLOBAL(power4_idle)
BEGIN_FTR_SECTION
blr
END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
- /* We must dynamically check for the NAP feature as it
- * can be cleared by CPU init after the fixups are done
- */
- LOAD_REG_ADDRBASE(r3,cur_cpu_spec)
- ld r4,ADDROFF(cur_cpu_spec)(r3)
- ld r4,CPU_SPEC_FEATURES(r4)
- andi. r0,r4,CPU_FTR_CAN_NAP
- beqlr
/* Now check if user or arch enabled NAP mode */
LOAD_REG_ADDRBASE(r3,powersave_nap)
lwz r4,ADDROFF(powersave_nap)(r3)
cmpwi 0,r4,0
beqlr
- /* Clear MSR:EE */
- mfmsr r7
- li r4,0
- ori r4,r4,MSR_EE
- andc r0,r7,r4
- mtmsrd r0
-
- /* Check current_thread_info()->flags */
- clrrdi r4,r1,THREAD_SHIFT
- ld r4,TI_FLAGS(r4)
- andi. r0,r4,_TIF_NEED_RESCHED
- beq 1f
- mtmsrd r7 /* out of line this ? */
- blr
-1:
/* Go to NAP now */
BEGIN_FTR_SECTION
DSSALL
sync
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ clrrdi r9,r1,THREAD_SHIFT /* current thread_info */
+ ld r8,TI_LOCAL_FLAGS(r9) /* set napping bit */
+ ori r8,r8,_TLF_NAPPING /* so when we take an exception */
+ std r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */
+ mfmsr r7
+ ori r7,r7,MSR_EE
oris r7,r7,MSR_POW@h
- sync
+1: sync
isync
mtmsrd r7
isync
- sync
- blr
+ b 1b
+
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index d9a7fdef59b..4eba60a3289 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -61,6 +61,7 @@ __setup("iommu=", setup_iommu);
static unsigned long iommu_range_alloc(struct iommu_table *tbl,
unsigned long npages,
unsigned long *handle,
+ unsigned long mask,
unsigned int align_order)
{
unsigned long n, end, i, start;
@@ -97,9 +98,21 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
*/
if (start >= limit)
start = largealloc ? tbl->it_largehint : tbl->it_hint;
-
+
again:
+ if (limit + tbl->it_offset > mask) {
+ limit = mask - tbl->it_offset + 1;
+ /* If we're constrained on address range, first try
+ * at the masked hint to avoid O(n) search complexity,
+ * but on second pass, start at 0.
+ */
+ if ((start & mask) >= limit || pass > 0)
+ start = 0;
+ else
+ start &= mask;
+ }
+
n = find_next_zero_bit(tbl->it_map, limit, start);
/* Align allocation */
@@ -150,14 +163,14 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page,
unsigned int npages, enum dma_data_direction direction,
- unsigned int align_order)
+ unsigned long mask, unsigned int align_order)
{
unsigned long entry, flags;
dma_addr_t ret = DMA_ERROR_CODE;
-
+
spin_lock_irqsave(&(tbl->it_lock), flags);
- entry = iommu_range_alloc(tbl, npages, NULL, align_order);
+ entry = iommu_range_alloc(tbl, npages, NULL, mask, align_order);
if (unlikely(entry == DMA_ERROR_CODE)) {
spin_unlock_irqrestore(&(tbl->it_lock), flags);
@@ -236,7 +249,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
struct scatterlist *sglist, int nelems,
- enum dma_data_direction direction)
+ unsigned long mask, enum dma_data_direction direction)
{
dma_addr_t dma_next = 0, dma_addr;
unsigned long flags;
@@ -274,7 +287,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
vaddr = (unsigned long)page_address(s->page) + s->offset;
npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK);
npages >>= PAGE_SHIFT;
- entry = iommu_range_alloc(tbl, npages, &handle, 0);
+ entry = iommu_range_alloc(tbl, npages, &handle, mask >> PAGE_SHIFT, 0);
DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen);
@@ -479,7 +492,8 @@ void iommu_free_table(struct device_node *dn)
* byte within the page as vaddr.
*/
dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
- size_t size, enum dma_data_direction direction)
+ size_t size, unsigned long mask,
+ enum dma_data_direction direction)
{
dma_addr_t dma_handle = DMA_ERROR_CODE;
unsigned long uaddr;
@@ -492,7 +506,8 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
npages >>= PAGE_SHIFT;
if (tbl) {
- dma_handle = iommu_alloc(tbl, vaddr, npages, direction, 0);
+ dma_handle = iommu_alloc(tbl, vaddr, npages, direction,
+ mask >> PAGE_SHIFT, 0);
if (dma_handle == DMA_ERROR_CODE) {
if (printk_ratelimit()) {
printk(KERN_INFO "iommu_alloc failed, "
@@ -521,7 +536,7 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
* to the dma address (mapping) of the first page.
*/
void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, unsigned long mask, gfp_t flag)
{
void *ret = NULL;
dma_addr_t mapping;
@@ -551,7 +566,8 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
memset(ret, 0, size);
/* Set up tces to cover the allocated range */
- mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL, order);
+ mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL,
+ mask >> PAGE_SHIFT, order);
if (mapping == DMA_ERROR_CODE) {
free_pages((unsigned long)ret, order);
ret = NULL;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 771a59cbd21..57d560c6889 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -272,18 +272,26 @@ unsigned int virt_irq_to_real_map[NR_IRQS];
* Don't use virtual irqs 0, 1, 2 for devices.
* The pcnet32 driver considers interrupt numbers < 2 to be invalid,
* and 2 is the XICS IPI interrupt.
- * We limit virtual irqs to 17 less than NR_IRQS so that when we
- * offset them by 16 (to reserve the first 16 for ISA interrupts)
- * we don't end up with an interrupt number >= NR_IRQS.
+ * We limit virtual irqs to __irq_offet_value less than virt_irq_max so
+ * that when we offset them we don't end up with an interrupt
+ * number >= virt_irq_max.
*/
#define MIN_VIRT_IRQ 3
-#define MAX_VIRT_IRQ (NR_IRQS - NUM_ISA_INTERRUPTS - 1)
-#define NR_VIRT_IRQS (MAX_VIRT_IRQ - MIN_VIRT_IRQ + 1)
+
+unsigned int virt_irq_max;
+static unsigned int max_virt_irq;
+static unsigned int nr_virt_irqs;
void
virt_irq_init(void)
{
int i;
+
+ if ((virt_irq_max == 0) || (virt_irq_max > (NR_IRQS - 1)))
+ virt_irq_max = NR_IRQS - 1;
+ max_virt_irq = virt_irq_max - __irq_offset_value;
+ nr_virt_irqs = max_virt_irq - MIN_VIRT_IRQ + 1;
+
for (i = 0; i < NR_IRQS; i++)
virt_irq_to_real_map[i] = UNDEFINED_IRQ;
}
@@ -308,17 +316,17 @@ int virt_irq_create_mapping(unsigned int real_irq)
return real_irq;
}
- /* map to a number between MIN_VIRT_IRQ and MAX_VIRT_IRQ */
+ /* map to a number between MIN_VIRT_IRQ and max_virt_irq */
virq = real_irq;
- if (virq > MAX_VIRT_IRQ)
- virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
+ if (virq > max_virt_irq)
+ virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ;
/* search for this number or a free slot */
first_virq = virq;
while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) {
if (virt_irq_to_real_map[virq] == real_irq)
return virq;
- if (++virq > MAX_VIRT_IRQ)
+ if (++virq > max_virt_irq)
virq = MIN_VIRT_IRQ;
if (virq == first_virq)
goto nospace; /* oops, no free slots */
@@ -330,8 +338,8 @@ int virt_irq_create_mapping(unsigned int real_irq)
nospace:
if (!warned) {
printk(KERN_CRIT "Interrupt table is full\n");
- printk(KERN_CRIT "Increase NR_IRQS (currently %d) "
- "in your kernel sources and rebuild.\n", NR_IRQS);
+ printk(KERN_CRIT "Increase virt_irq_max (currently %d) "
+ "in your kernel sources and rebuild.\n", virt_irq_max);
warned = 1;
}
return NO_IRQ;
@@ -349,8 +357,8 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq)
virq = real_irq;
- if (virq > MAX_VIRT_IRQ)
- virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
+ if (virq > max_virt_irq)
+ virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ;
first_virq = virq;
@@ -360,7 +368,7 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq)
virq++;
- if (virq >= MAX_VIRT_IRQ)
+ if (virq >= max_virt_irq)
virq = 0;
} while (first_virq != virq);
@@ -379,7 +387,7 @@ void irq_ctx_init(void)
struct thread_info *tp;
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
tp = softirq_ctx[i];
tp->cpu = i;
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index ad7a9021220..f78866367b7 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -88,34 +88,34 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
mutex_unlock(&kprobe_mutex);
}
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
- kprobe_opcode_t insn = *p->ainsn.insn;
-
regs->msr |= MSR_SE;
- /* single step inline if it is a trap variant */
- if (is_trap(insn))
- regs->nip = (unsigned long)p->addr;
- else
- regs->nip = (unsigned long)p->ainsn.insn;
+ /*
+ * On powerpc we should single step on the original
+ * instruction even if the probed insn is a trap
+ * variant as values in regs could play a part in
+ * if the trap is taken or not
+ */
+ regs->nip = (unsigned long)p->ainsn.insn;
}
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status;
kcb->prev_kprobe.saved_msr = kcb->kprobe_saved_msr;
}
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status;
kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr;
}
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = p;
@@ -141,7 +141,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
}
}
-static inline int kprobe_handler(struct pt_regs *regs)
+static int __kprobes kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
int ret = 0;
@@ -334,7 +334,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
regs->nip = (unsigned long)p->addr + 4;
}
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -370,7 +370,7 @@ out:
return 1;
}
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
diff --git a/arch/ppc/kernel/l2cr.S b/arch/powerpc/kernel/l2cr_6xx.S
index d7f4e982b53..d7f4e982b53 100644
--- a/arch/ppc/kernel/l2cr.S
+++ b/arch/powerpc/kernel/l2cr_6xx.S
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index c7a799a0951..6e67b5b49ba 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -37,7 +37,7 @@ static int legacy_serial_console = -1;
static int __init add_legacy_port(struct device_node *np, int want_index,
int iotype, phys_addr_t base,
phys_addr_t taddr, unsigned long irq,
- unsigned int flags)
+ upf_t flags)
{
u32 *clk, *spd, clock = BASE_BAUD * 16;
int index;
@@ -113,7 +113,7 @@ static int __init add_legacy_soc_port(struct device_node *np,
{
phys_addr_t addr;
u32 *addrp;
- unsigned int flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
+ upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
/* We only support ports that have a clock frequency properly
* encoded in the device-tree.
@@ -236,6 +236,23 @@ static int __init add_legacy_pci_port(struct device_node *np,
}
#endif
+static void __init setup_legacy_serial_console(int console)
+{
+ struct legacy_serial_info *info =
+ &legacy_serial_infos[console];
+ void __iomem *addr;
+
+ if (info->taddr == 0)
+ return;
+ addr = ioremap(info->taddr, 0x1000);
+ if (addr == NULL)
+ return;
+ if (info->speed == 0)
+ info->speed = udbg_probe_uart_speed(addr, info->clock);
+ DBG("default console speed = %d\n", info->speed);
+ udbg_init_uart(addr, info->speed, info->clock);
+}
+
/*
* This is called very early, as part of setup_system() or eventually
* setup_arch(), basically before anything else in this file. This function
@@ -318,25 +335,8 @@ void __init find_legacy_serial_ports(void)
#endif
DBG("legacy_serial_console = %d\n", legacy_serial_console);
-
- /* udbg is 64 bits only for now, that will change soon though ... */
- while (legacy_serial_console >= 0) {
- struct legacy_serial_info *info =
- &legacy_serial_infos[legacy_serial_console];
- void __iomem *addr;
-
- if (info->taddr == 0)
- break;
- addr = ioremap(info->taddr, 0x1000);
- if (addr == NULL)
- break;
- if (info->speed == 0)
- info->speed = udbg_probe_uart_speed(addr, info->clock);
- DBG("default console speed = %d\n", info->speed);
- udbg_init_uart(addr, info->speed, info->clock);
- break;
- }
-
+ if (legacy_serial_console >= 0)
+ setup_legacy_serial_console(legacy_serial_console);
DBG(" <- find_legacy_serial_port()\n");
}
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index e789fef4eb8..2cbde865d4f 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -37,7 +37,7 @@
#include <asm/prom.h>
#include <asm/vdso_datapage.h>
-#define MODULE_VERS "1.6"
+#define MODULE_VERS "1.7"
#define MODULE_NAME "lparcfg"
/* #define LPARCFG_DEBUG */
@@ -56,7 +56,7 @@ static unsigned long get_purr(void)
unsigned long sum_purr = 0;
int cpu;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
sum_purr += lppaca[cpu].emulated_time_base;
#ifdef PURR_DEBUG
@@ -149,17 +149,17 @@ static void log_plpar_hcall_return(unsigned long rc, char *tag)
if (rc == 0) /* success, return */
return;
/* check for null tag ? */
- if (rc == H_Hardware)
+ if (rc == H_HARDWARE)
printk(KERN_INFO
"plpar-hcall (%s) failed with hardware fault\n", tag);
- else if (rc == H_Function)
+ else if (rc == H_FUNCTION)
printk(KERN_INFO
"plpar-hcall (%s) failed; function not allowed\n", tag);
- else if (rc == H_Authority)
+ else if (rc == H_AUTHORITY)
printk(KERN_INFO
- "plpar-hcall (%s) failed; not authorized to this function\n",
- tag);
- else if (rc == H_Parameter)
+ "plpar-hcall (%s) failed; not authorized to this"
+ " function\n", tag);
+ else if (rc == H_PARAMETER)
printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n",
tag);
else
@@ -209,7 +209,7 @@ static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
unsigned long dummy;
rc = plpar_hcall(H_PIC, 0, 0, 0, 0, pool_idle_time, num_procs, &dummy);
- if (rc != H_Authority)
+ if (rc != H_AUTHORITY)
log_plpar_hcall_return(rc, "H_PIC");
}
@@ -222,7 +222,7 @@ static unsigned long get_purr(void)
int cpu;
struct cpu_usage *cu;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
cu = &per_cpu(cpu_usage_array, cpu);
sum_purr += cu->current_tb;
}
@@ -242,7 +242,7 @@ static void parse_system_parameter_string(struct seq_file *m)
{
int call_status;
- char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
+ unsigned char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
if (!local_buffer) {
printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
__FILE__, __FUNCTION__, __LINE__);
@@ -254,7 +254,8 @@ static void parse_system_parameter_string(struct seq_file *m)
call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
NULL,
SPLPAR_CHARACTERISTICS_TOKEN,
- __pa(rtas_data_buf));
+ __pa(rtas_data_buf),
+ RTAS_DATA_BUF_SIZE);
memcpy(local_buffer, rtas_data_buf, SPLPAR_MAXLENGTH);
spin_unlock(&rtas_data_buf_lock);
@@ -275,7 +276,7 @@ static void parse_system_parameter_string(struct seq_file *m)
#ifdef LPARCFG_DEBUG
printk(KERN_INFO "success calling get-system-parameter \n");
#endif
- splpar_strlen = local_buffer[0] * 16 + local_buffer[1];
+ splpar_strlen = local_buffer[0] * 256 + local_buffer[1];
local_buffer += 2; /* step over strlen value */
memset(workbuffer, 0, SPLPAR_MAXLENGTH);
@@ -529,13 +530,13 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
*new_weight_ptr);
- if (retval == H_Success || retval == H_Constrained) {
+ if (retval == H_SUCCESS || retval == H_CONSTRAINED) {
retval = count;
- } else if (retval == H_Busy) {
+ } else if (retval == H_BUSY) {
retval = -EBUSY;
- } else if (retval == H_Hardware) {
+ } else if (retval == H_HARDWARE) {
retval = -EIO;
- } else if (retval == H_Parameter) {
+ } else if (retval == H_PARAMETER) {
retval = -EINVAL;
} else {
printk(KERN_WARNING "%s: received unknown hv return code %ld",
diff --git a/arch/ppc/kernel/module.c b/arch/powerpc/kernel/module_32.c
index 92f4e5f64f0..92f4e5f64f0 100644
--- a/arch/ppc/kernel/module.c
+++ b/arch/powerpc/kernel/module_32.c
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 928b8581fcb..ba34001fca8 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -191,11 +191,19 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
(void *)hdr
+ sechdrs[sechdrs[i].sh_link].sh_offset);
}
- if (!me->arch.stubs_section || !me->arch.toc_section) {
- printk("%s: doesn't contain .toc or .stubs.\n", me->name);
+
+ if (!me->arch.stubs_section) {
+ printk("%s: doesn't contain .stubs.\n", me->name);
return -ENOEXEC;
}
+ /* If we don't have a .toc, just use .stubs. We need to set r2
+ to some reasonable value in case the module calls out to
+ other functions via a stub, or if a function pointer escapes
+ the module by some means. */
+ if (!me->arch.toc_section)
+ me->arch.toc_section = me->arch.stubs_section;
+
/* Override the stubs size */
sechdrs[me->arch.stubs_section].sh_size = get_stubs_size(hdr, sechdrs);
return 0;
@@ -342,7 +350,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
break;
case R_PPC64_TOC16:
- /* Subtact TOC pointer */
+ /* Subtract TOC pointer */
value -= my_r2(sechdrs, me);
if (value + 0x8000 > 0xffff) {
printk("%s: bad TOC16 relocation (%lu)\n",
@@ -355,7 +363,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
break;
case R_PPC64_TOC16_DS:
- /* Subtact TOC pointer */
+ /* Subtract TOC pointer */
value -= my_r2(sechdrs, me);
if ((value & 3) != 0 || value + 0x8000 > 0xffff) {
printk("%s: bad TOC16_DS relocation (%lu)\n",
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index fd7db8d542d..ada50aa5b60 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -160,7 +160,7 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file,
case IOC_NVRAM_GET_OFFSET: {
int part, offset;
- if (_machine != PLATFORM_POWERMAC)
+ if (!machine_is(powermac))
return -EINVAL;
if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0)
return -EFAULT;
@@ -174,8 +174,9 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file,
return 0;
}
#endif /* CONFIG_PPC_PMAC */
+ default:
+ return -EINVAL;
}
- return -EINVAL;
}
struct file_operations nvram_fops = {
@@ -443,7 +444,7 @@ static int nvram_setup_partition(void)
* in our nvram, as Apple defined partitions use pretty much
* all of the space
*/
- if (_machine == PLATFORM_POWERMAC)
+ if (machine_is(powermac))
return -ENOSPC;
/* see if we have an OS partition that meets our needs.
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 5d1b708086b..f505a8827e3 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -56,14 +56,11 @@ struct lppaca lppaca[] = {
* processors. The processor VPD array needs one entry per physical
* processor (not thread).
*/
-#define PACA_INIT_COMMON(number, start, asrr, asrv) \
+#define PACA_INIT_COMMON(number) \
.lppaca_ptr = &lppaca[number], \
.lock_token = 0x8000, \
.paca_index = (number), /* Paca Index */ \
.kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \
- .stab_real = (asrr), /* Real pointer to segment table */ \
- .stab_addr = (asrv), /* Virt pointer to segment table */ \
- .cpu_start = (start), /* Processor start */ \
.hw_cpu_id = 0xffff,
#ifdef CONFIG_PPC_ISERIES
@@ -72,30 +69,20 @@ struct lppaca lppaca[] = {
#define PACA_INIT(number) \
{ \
- PACA_INIT_COMMON(number, 0, 0, 0) \
- PACA_INIT_ISERIES(number) \
-}
-
-#define BOOTCPU_PACA_INIT(number) \
-{ \
- PACA_INIT_COMMON(number, 1, 0, (u64)&initial_stab) \
+ PACA_INIT_COMMON(number) \
PACA_INIT_ISERIES(number) \
}
#else
#define PACA_INIT(number) \
{ \
- PACA_INIT_COMMON(number, 0, 0, 0) \
+ PACA_INIT_COMMON(number) \
}
-#define BOOTCPU_PACA_INIT(number) \
-{ \
- PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, (u64)&initial_stab) \
-}
#endif
struct paca_struct paca[] = {
- BOOTCPU_PACA_INIT(0),
+ PACA_INIT(0),
#if NR_CPUS > 1
PACA_INIT( 1), PACA_INIT( 2), PACA_INIT( 3),
#if NR_CPUS > 4
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 704c846b2b0..b129d2e4b75 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -787,7 +787,7 @@ pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
* fix has to be done by making the remapping per-host and always
* filling the pci_to_OF map. --BenH
*/
- if (_machine == _MACH_Pmac && busnr >= 0xf0)
+ if (machine_is(powermac) && busnr >= 0xf0)
busnr -= 0xf0;
else
#endif
@@ -1728,7 +1728,7 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
* (bus 0 is HT root), we return the AGP one instead.
*/
#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4"))
+ if (machine_is(powermac) && machine_is_compatible("MacRISC4"))
if (bus == 0)
bus = 0xf0;
#endif /* CONFIG_PPC_PMAC */
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index ba92bab7cc2..4c4449be81c 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -78,6 +78,7 @@ int global_phb_number; /* Global phb counter */
/* Cached ISA bridge dev. */
struct pci_dev *ppc64_isabridge_dev = NULL;
+EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
static void fixup_broken_pcnet32(struct pci_dev* dev)
{
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c
index c336f3e31cf..c1d95e14bbe 100644
--- a/arch/powerpc/kernel/pci_iommu.c
+++ b/arch/powerpc/kernel/pci_iommu.c
@@ -59,6 +59,25 @@ static inline struct iommu_table *devnode_table(struct device *dev)
}
+static inline unsigned long device_to_mask(struct device *hwdev)
+{
+ struct pci_dev *pdev;
+
+ if (!hwdev) {
+ pdev = ppc64_isabridge_dev;
+ if (!pdev) /* This is the best guess we can do */
+ return 0xfffffffful;
+ } else
+ pdev = to_pci_dev(hwdev);
+
+ if (pdev->dma_mask)
+ return pdev->dma_mask;
+
+ /* Assume devices without mask can take 32 bit addresses */
+ return 0xfffffffful;
+}
+
+
/* Allocates a contiguous real buffer and creates mappings over it.
* Returns the virtual address of the buffer and sets dma_handle
* to the dma address (mapping) of the first page.
@@ -67,7 +86,7 @@ static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
- flag);
+ device_to_mask(hwdev), flag);
}
static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
@@ -85,7 +104,8 @@ static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
size_t size, enum dma_data_direction direction)
{
- return iommu_map_single(devnode_table(hwdev), vaddr, size, direction);
+ return iommu_map_single(devnode_table(hwdev), vaddr, size,
+ device_to_mask(hwdev), direction);
}
@@ -100,7 +120,7 @@ static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
return iommu_map_sg(pdev, devnode_table(pdev), sglist,
- nelems, direction);
+ nelems, device_to_mask(pdev), direction);
}
static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
@@ -112,7 +132,19 @@ static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
/* We support DMA to/from any memory page via the iommu */
static int pci_iommu_dma_supported(struct device *dev, u64 mask)
{
- return 1;
+ struct iommu_table *tbl = devnode_table(dev);
+
+ if (!tbl || tbl->it_offset > mask) {
+ printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");
+ if (tbl)
+ printk(KERN_INFO "mask: 0x%08lx, table offset: 0x%08lx\n",
+ mask, tbl->it_offset);
+ else
+ printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
+ mask);
+ return 0;
+ } else
+ return 1;
}
void pci_iommu_init(void)
diff --git a/arch/ppc/kernel/perfmon_fsl_booke.c b/arch/powerpc/kernel/perfmon_fsl_booke.c
index 32455dfcc36..32455dfcc36 100644
--- a/arch/ppc/kernel/perfmon_fsl_booke.c
+++ b/arch/powerpc/kernel/perfmon_fsl_booke.c
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index dfa5398ab3c..4b052ae5dc3 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -81,6 +81,7 @@ EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strcasecmp);
+EXPORT_SYMBOL(strncasecmp);
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_generic);
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
index 7ba42a405f4..3c2cf661f6d 100644
--- a/arch/powerpc/kernel/proc_ppc64.c
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/kernel.h>
+#include <asm/machdep.h>
#include <asm/vdso_datapage.h>
#include <asm/rtas.h>
#include <asm/uaccess.h>
@@ -51,7 +52,7 @@ static int __init proc_ppc64_create(void)
if (!root)
return 1;
- if (!(platform_is_pseries() || _machine == PLATFORM_CELL))
+ if (!machine_is(pseries) && !machine_is(cell))
return 0;
if (!proc_mkdir("rtas", root))
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index f698aa77127..2dd47d2dd99 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -45,6 +45,7 @@
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/time.h>
+#include <asm/syscalls.h>
#ifdef CONFIG_PPC64
#include <asm/firmware.h>
#endif
@@ -362,7 +363,11 @@ static void show_instructions(struct pt_regs *regs)
if (!(i % 8))
printk("\n");
- if (BAD_PC(pc) || __get_user(instr, (unsigned int *)pc)) {
+ /* We use __get_user here *only* to avoid an OOPS on a
+ * bad address because the pc *should* only be a
+ * kernel address.
+ */
+ if (BAD_PC(pc) || __get_user(instr, (unsigned int __user *)pc)) {
printk("XXXXXXXX ");
} else {
if (regs->nip == pc)
@@ -765,7 +770,7 @@ out:
return error;
}
-static int validate_sp(unsigned long sp, struct task_struct *p,
+int validate_sp(unsigned long sp, struct task_struct *p,
unsigned long nbytes)
{
unsigned long stack_page = (unsigned long)task_stack_page(p);
@@ -803,6 +808,8 @@ static int validate_sp(unsigned long sp, struct task_struct *p,
#define FRAME_MARKER 2
#endif
+EXPORT_SYMBOL(validate_sp);
+
unsigned long get_wchan(struct task_struct *p)
{
unsigned long ip, sp;
@@ -827,7 +834,6 @@ unsigned long get_wchan(struct task_struct *p)
} while (count++ < 16);
return 0;
}
-EXPORT_SYMBOL(get_wchan);
static int kstack_depth_to_print = 64;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index d63cd562d9d..9a07f97f071 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -62,7 +62,7 @@ static int __initdata dt_root_addr_cells;
static int __initdata dt_root_size_cells;
#ifdef CONFIG_PPC64
-static int __initdata iommu_is_off;
+int __initdata iommu_is_off;
int __initdata iommu_force_on;
unsigned long tce_alloc_start, tce_alloc_end;
#endif
@@ -383,14 +383,14 @@ static int __devinit finish_node_interrupts(struct device_node *np,
/* Apple uses bits in there in a different way, let's
* only keep the real sense bit on macs
*/
- if (_machine == PLATFORM_POWERMAC)
+ if (machine_is(powermac))
sense &= 0x1;
np->intrs[intrcount].sense = map_mpic_senses[sense];
}
#ifdef CONFIG_PPC64
/* We offset irq numbers for the u3 MPIC by 128 in PowerMac */
- if (_machine == PLATFORM_POWERMAC && ic && ic->parent) {
+ if (machine_is(powermac) && ic && ic->parent) {
char *name = get_property(ic->parent, "name", NULL);
if (name && !strcmp(name, "u3"))
np->intrs[intrcount].line += 128;
@@ -570,6 +570,18 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
return rc;
}
+unsigned long __init of_get_flat_dt_root(void)
+{
+ unsigned long p = ((unsigned long)initial_boot_params) +
+ initial_boot_params->off_dt_struct;
+
+ while(*((u32 *)p) == OF_DT_NOP)
+ p += 4;
+ BUG_ON (*((u32 *)p) != OF_DT_BEGIN_NODE);
+ p += 4;
+ return _ALIGN(p + strlen((char *)p) + 1, 4);
+}
+
/**
* This function can be used within scan_flattened_dt callback to get
* access to properties
@@ -612,6 +624,25 @@ void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
} while(1);
}
+int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
+{
+ const char* cp;
+ unsigned long cplen, l;
+
+ cp = of_get_flat_dt_prop(node, "compatible", &cplen);
+ if (cp == NULL)
+ return 0;
+ while (cplen > 0) {
+ if (strncasecmp(cp, compat, strlen(compat)) == 0)
+ return 1;
+ l = strlen(cp) + 1;
+ cp += l;
+ cplen -= l;
+ }
+
+ return 0;
+}
+
static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
unsigned long align)
{
@@ -686,7 +717,7 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
#ifdef DEBUG
if ((strlen(p) + l + 1) != allocl) {
DBG("%s: p: %d, l: %d, a: %d\n",
- pathp, strlen(p), l, allocl);
+ pathp, (int)strlen(p), l, allocl);
}
#endif
p += strlen(p);
@@ -854,35 +885,141 @@ void __init unflatten_device_tree(void)
DBG(" <- unflatten_device_tree()\n");
}
+/*
+ * ibm,pa-features is a per-cpu property that contains a string of
+ * attribute descriptors, each of which has a 2 byte header plus up
+ * to 254 bytes worth of processor attribute bits. First header
+ * byte specifies the number of bytes following the header.
+ * Second header byte is an "attribute-specifier" type, of which
+ * zero is the only currently-defined value.
+ * Implementation: Pass in the byte and bit offset for the feature
+ * that we are interested in. The function will return -1 if the
+ * pa-features property is missing, or a 1/0 to indicate if the feature
+ * is supported/not supported. Note that the bit numbers are
+ * big-endian to match the definition in PAPR.
+ */
+static struct ibm_pa_feature {
+ unsigned long cpu_features; /* CPU_FTR_xxx bit */
+ unsigned int cpu_user_ftrs; /* PPC_FEATURE_xxx bit */
+ unsigned char pabyte; /* byte number in ibm,pa-features */
+ unsigned char pabit; /* bit number (big-endian) */
+ unsigned char invert; /* if 1, pa bit set => clear feature */
+} ibm_pa_features[] __initdata = {
+ {0, PPC_FEATURE_HAS_MMU, 0, 0, 0},
+ {0, PPC_FEATURE_HAS_FPU, 0, 1, 0},
+ {CPU_FTR_SLB, 0, 0, 2, 0},
+ {CPU_FTR_CTRL, 0, 0, 3, 0},
+ {CPU_FTR_NOEXECUTE, 0, 0, 6, 0},
+ {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1},
+ {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0},
+};
+
+static void __init check_cpu_pa_features(unsigned long node)
+{
+ unsigned char *pa_ftrs;
+ unsigned long len, tablelen, i, bit;
+
+ pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);
+ if (pa_ftrs == NULL)
+ return;
+
+ /* find descriptor with type == 0 */
+ for (;;) {
+ if (tablelen < 3)
+ return;
+ len = 2 + pa_ftrs[0];
+ if (tablelen < len)
+ return; /* descriptor 0 not found */
+ if (pa_ftrs[1] == 0)
+ break;
+ tablelen -= len;
+ pa_ftrs += len;
+ }
+
+ /* loop over bits we know about */
+ for (i = 0; i < ARRAY_SIZE(ibm_pa_features); ++i) {
+ struct ibm_pa_feature *fp = &ibm_pa_features[i];
+
+ if (fp->pabyte >= pa_ftrs[0])
+ continue;
+ bit = (pa_ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1;
+ if (bit ^ fp->invert) {
+ cur_cpu_spec->cpu_features |= fp->cpu_features;
+ cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs;
+ } else {
+ cur_cpu_spec->cpu_features &= ~fp->cpu_features;
+ cur_cpu_spec->cpu_user_features &= ~fp->cpu_user_ftrs;
+ }
+ }
+}
static int __init early_init_dt_scan_cpus(unsigned long node,
- const char *uname, int depth, void *data)
+ const char *uname, int depth,
+ void *data)
{
+ static int logical_cpuid = 0;
+ char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+#ifdef CONFIG_ALTIVEC
u32 *prop;
- unsigned long size;
- char *type = of_get_flat_dt_prop(node, "device_type", &size);
+#endif
+ u32 *intserv;
+ int i, nthreads;
+ unsigned long len;
+ int found = 0;
/* We are scanning "cpu" nodes only */
if (type == NULL || strcmp(type, "cpu") != 0)
return 0;
- boot_cpuid = 0;
- boot_cpuid_phys = 0;
- if (initial_boot_params && initial_boot_params->version >= 2) {
- /* version 2 of the kexec param format adds the phys cpuid
- * of booted proc.
- */
- boot_cpuid_phys = initial_boot_params->boot_cpuid_phys;
+ /* Get physical cpuid */
+ intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len);
+ if (intserv) {
+ nthreads = len / sizeof(int);
} else {
- /* Check if it's the boot-cpu, set it's hw index now */
- if (of_get_flat_dt_prop(node,
+ intserv = of_get_flat_dt_prop(node, "reg", NULL);
+ nthreads = 1;
+ }
+
+ /*
+ * Now see if any of these threads match our boot cpu.
+ * NOTE: This must match the parsing done in smp_setup_cpu_maps.
+ */
+ for (i = 0; i < nthreads; i++) {
+ /*
+ * version 2 of the kexec param format adds the phys cpuid of
+ * booted proc.
+ */
+ if (initial_boot_params && initial_boot_params->version >= 2) {
+ if (intserv[i] ==
+ initial_boot_params->boot_cpuid_phys) {
+ found = 1;
+ break;
+ }
+ } else {
+ /*
+ * Check if it's the boot-cpu, set it's hw index now,
+ * unfortunately this format did not support booting
+ * off secondary threads.
+ */
+ if (of_get_flat_dt_prop(node,
"linux,boot-cpu", NULL) != NULL) {
- prop = of_get_flat_dt_prop(node, "reg", NULL);
- if (prop != NULL)
- boot_cpuid_phys = *prop;
+ found = 1;
+ break;
+ }
}
+
+#ifdef CONFIG_SMP
+ /* logical cpu id is always 0 on UP kernels */
+ logical_cpuid++;
+#endif
+ }
+
+ if (found) {
+ DBG("boot cpu: logical %d physical %d\n", logical_cpuid,
+ intserv[i]);
+ boot_cpuid = logical_cpuid;
+ set_hard_smp_processor_id(boot_cpuid, intserv[i]);
}
- set_hard_smp_processor_id(0, boot_cpuid_phys);
#ifdef CONFIG_ALTIVEC
/* Check if we have a VMX and eventually update CPU features */
@@ -900,17 +1037,13 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
}
#endif /* CONFIG_ALTIVEC */
+ check_cpu_pa_features(node);
+
#ifdef CONFIG_PPC_PSERIES
- /*
- * Check for an SMT capable CPU and set the CPU feature. We do
- * this by looking at the size of the ibm,ppc-interrupt-server#s
- * property
- */
- prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
- &size);
- cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
- if (prop && ((size / sizeof(u32)) > 1))
+ if (nthreads > 1)
cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
+ else
+ cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
#endif
return 0;
@@ -919,7 +1052,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
static int __init early_init_dt_scan_chosen(unsigned long node,
const char *uname, int depth, void *data)
{
- u32 *prop;
unsigned long *lprop;
unsigned long l;
char *p;
@@ -930,14 +1062,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
(strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
return 0;
- /* get platform type */
- prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL);
- if (prop == NULL)
- return 0;
-#ifdef CONFIG_PPC_MULTIPLATFORM
- _machine = *prop;
-#endif
-
#ifdef CONFIG_PPC64
/* check if iommu is forced on or off */
if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
@@ -964,15 +1088,15 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
* set of RTAS infos now if available
*/
{
- u64 *basep, *entryp;
+ u64 *basep, *entryp, *sizep;
basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
- prop = of_get_flat_dt_prop(node, "linux,rtas-size", NULL);
- if (basep && entryp && prop) {
+ sizep = of_get_flat_dt_prop(node, "linux,rtas-size", NULL);
+ if (basep && entryp && sizep) {
rtas.base = *basep;
rtas.entry = *entryp;
- rtas.size = *prop;
+ rtas.size = *sizep;
}
}
#endif /* CONFIG_PPC_RTAS */
@@ -1001,25 +1125,13 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
if (strstr(cmd_line, "mem=")) {
char *p, *q;
- unsigned long maxmem = 0;
for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
q = p + 4;
if (p > cmd_line && p[-1] != ' ')
continue;
- maxmem = simple_strtoul(q, &q, 0);
- if (*q == 'k' || *q == 'K') {
- maxmem <<= 10;
- ++q;
- } else if (*q == 'm' || *q == 'M') {
- maxmem <<= 20;
- ++q;
- } else if (*q == 'g' || *q == 'G') {
- maxmem <<= 30;
- ++q;
- }
+ memory_limit = memparse(q, &q);
}
- memory_limit = maxmem;
}
/* break now */
@@ -1755,7 +1867,7 @@ static int of_finish_dynamic_node(struct device_node *node)
/* We don't support that function on PowerMac, at least
* not yet
*/
- if (_machine == PLATFORM_POWERMAC)
+ if (machine_is(powermac))
return -ENODEV;
/* fix up new node's linux_phandle field */
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 813c2cd194c..f70bd090dac 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -180,6 +180,16 @@ static unsigned long __initdata prom_tce_alloc_start;
static unsigned long __initdata prom_tce_alloc_end;
#endif
+/* Platforms codes are now obsolete in the kernel. Now only used within this
+ * file and ultimately gone too. Feel free to change them if you need, they
+ * are not shared with anything outside of this file anymore
+ */
+#define PLATFORM_PSERIES 0x0100
+#define PLATFORM_PSERIES_LPAR 0x0101
+#define PLATFORM_LPAR 0x0001
+#define PLATFORM_POWERMAC 0x0400
+#define PLATFORM_GENERIC 0x0500
+
static int __initdata of_platform;
static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
@@ -397,6 +407,11 @@ static void __init __attribute__((noreturn)) prom_panic(const char *reason)
reason = PTRRELOC(reason);
#endif
prom_print(reason);
+ /* Do not call exit because it clears the screen on pmac
+ * it also causes some sort of double-fault on early pmacs */
+ if (RELOC(of_platform) == PLATFORM_POWERMAC)
+ asm("trap\n");
+
/* ToDo: should put up an SRC here on p/iSeries */
call_prom("exit", 0, 0);
@@ -621,10 +636,96 @@ static void __init early_cmdline_parse(void)
#ifdef CONFIG_PPC_PSERIES
/*
- * To tell the firmware what our capabilities are, we have to pass
- * it a fake 32-bit ELF header containing a couple of PT_NOTE sections
- * that contain structures that contain the actual values.
+ * There are two methods for telling firmware what our capabilities are.
+ * Newer machines have an "ibm,client-architecture-support" method on the
+ * root node. For older machines, we have to call the "process-elf-header"
+ * method in the /packages/elf-loader node, passing it a fake 32-bit
+ * ELF header containing a couple of PT_NOTE sections that contain
+ * structures that contain various information.
+ */
+
+/*
+ * New method - extensible architecture description vector.
+ *
+ * Because the description vector contains a mix of byte and word
+ * values, we declare it as an unsigned char array, and use this
+ * macro to put word values in.
+ */
+#define W(x) ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
+ ((x) >> 8) & 0xff, (x) & 0xff
+
+/* Option vector bits - generic bits in byte 1 */
+#define OV_IGNORE 0x80 /* ignore this vector */
+#define OV_CESSATION_POLICY 0x40 /* halt if unsupported option present*/
+
+/* Option vector 1: processor architectures supported */
+#define OV1_PPC_2_00 0x80 /* set if we support PowerPC 2.00 */
+#define OV1_PPC_2_01 0x40 /* set if we support PowerPC 2.01 */
+#define OV1_PPC_2_02 0x20 /* set if we support PowerPC 2.02 */
+#define OV1_PPC_2_03 0x10 /* set if we support PowerPC 2.03 */
+#define OV1_PPC_2_04 0x08 /* set if we support PowerPC 2.04 */
+#define OV1_PPC_2_05 0x04 /* set if we support PowerPC 2.05 */
+
+/* Option vector 2: Open Firmware options supported */
+#define OV2_REAL_MODE 0x20 /* set if we want OF in real mode */
+
+/* Option vector 3: processor options supported */
+#define OV3_FP 0x80 /* floating point */
+#define OV3_VMX 0x40 /* VMX/Altivec */
+
+/* Option vector 5: PAPR/OF options supported */
+#define OV5_LPAR 0x80 /* logical partitioning supported */
+#define OV5_SPLPAR 0x40 /* shared-processor LPAR supported */
+/* ibm,dynamic-reconfiguration-memory property supported */
+#define OV5_DRCONF_MEMORY 0x20
+#define OV5_LARGE_PAGES 0x10 /* large pages supported */
+
+/*
+ * The architecture vector has an array of PVR mask/value pairs,
+ * followed by # option vectors - 1, followed by the option vectors.
*/
+static unsigned char ibm_architecture_vec[] = {
+ W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */
+ W(0xffff0000), W(0x003e0000), /* POWER6 */
+ W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
+ 5 - 1, /* 5 option vectors */
+
+ /* option vector 1: processor architectures supported */
+ 3 - 1, /* length */
+ 0, /* don't ignore, don't halt */
+ OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
+ OV1_PPC_2_04 | OV1_PPC_2_05,
+
+ /* option vector 2: Open Firmware options supported */
+ 34 - 1, /* length */
+ OV2_REAL_MODE,
+ 0, 0,
+ W(0xffffffff), /* real_base */
+ W(0xffffffff), /* real_size */
+ W(0xffffffff), /* virt_base */
+ W(0xffffffff), /* virt_size */
+ W(0xffffffff), /* load_base */
+ W(64), /* 128MB min RMA */
+ W(0xffffffff), /* full client load */
+ 0, /* min RMA percentage of total RAM */
+ 48, /* max log_2(hash table size) */
+
+ /* option vector 3: processor options supported */
+ 3 - 1, /* length */
+ 0, /* don't ignore, don't halt */
+ OV3_FP | OV3_VMX,
+
+ /* option vector 4: IBM PAPR implementation */
+ 2 - 1, /* length */
+ 0, /* don't halt */
+
+ /* option vector 5: PAPR/OF options */
+ 3 - 1, /* length */
+ 0, /* don't ignore, don't halt */
+ OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES,
+};
+
+/* Old method - ELF header with PT_NOTE sections */
static struct fake_elf {
Elf32_Ehdr elfhdr;
Elf32_Phdr phdr[2];
@@ -713,8 +814,27 @@ static struct fake_elf {
static void __init prom_send_capabilities(void)
{
- ihandle elfloader;
+ ihandle elfloader, root;
+ prom_arg_t ret;
+
+ root = call_prom("open", 1, 1, ADDR("/"));
+ if (root != 0) {
+ /* try calling the ibm,client-architecture-support method */
+ if (call_prom_ret("call-method", 3, 2, &ret,
+ ADDR("ibm,client-architecture-support"),
+ root,
+ ADDR(ibm_architecture_vec)) == 0) {
+ /* the call exists... */
+ if (ret)
+ prom_printf("WARNING: ibm,client-architecture"
+ "-support call FAILED!\n");
+ call_prom("close", 1, 0, root);
+ return;
+ }
+ call_prom("close", 1, 0, root);
+ }
+ /* no ibm,client-architecture-support call, try the old way */
elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
if (elfloader == 0) {
prom_printf("couldn't open /packages/elf-loader\n");
@@ -1487,7 +1607,10 @@ static int __init prom_find_machine_type(void)
int len, i = 0;
#ifdef CONFIG_PPC64
phandle rtas;
+ int x;
#endif
+
+ /* Look for a PowerMac */
len = prom_getprop(_prom->root, "compatible",
compat, sizeof(compat)-1);
if (len > 0) {
@@ -1501,27 +1624,43 @@ static int __init prom_find_machine_type(void)
strstr(p, RELOC("MacRISC")))
return PLATFORM_POWERMAC;
#ifdef CONFIG_PPC64
- if (strstr(p, RELOC("Momentum,Maple")))
- return PLATFORM_MAPLE;
- if (strstr(p, RELOC("IBM,CPB")))
- return PLATFORM_CELL;
-#endif
+ /* We must make sure we don't detect the IBM Cell
+ * blades as pSeries due to some firmware issues,
+ * so we do it here.
+ */
+ if (strstr(p, RELOC("IBM,CBEA")) ||
+ strstr(p, RELOC("IBM,CPBW-1.0")))
+ return PLATFORM_GENERIC;
+#endif /* CONFIG_PPC64 */
i += sl + 1;
}
}
#ifdef CONFIG_PPC64
+ /* If not a mac, try to figure out if it's an IBM pSeries or any other
+ * PAPR compliant platform. We assume it is if :
+ * - /device_type is "chrp" (please, do NOT use that for future
+ * non-IBM designs !
+ * - it has /rtas
+ */
+ len = prom_getprop(_prom->root, "device_type",
+ compat, sizeof(compat)-1);
+ if (len <= 0)
+ return PLATFORM_GENERIC;
+ if (strcmp(compat, RELOC("chrp")))
+ return PLATFORM_GENERIC;
+
/* Default to pSeries. We need to know if we are running LPAR */
rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
- if (PHANDLE_VALID(rtas)) {
- int x = prom_getproplen(rtas, "ibm,hypertas-functions");
- if (x != PROM_ERROR) {
- prom_printf("Hypertas detected, assuming LPAR !\n");
- return PLATFORM_PSERIES_LPAR;
- }
+ if (!PHANDLE_VALID(rtas))
+ return PLATFORM_GENERIC;
+ x = prom_getproplen(rtas, "ibm,hypertas-functions");
+ if (x != PROM_ERROR) {
+ prom_printf("Hypertas detected, assuming LPAR !\n");
+ return PLATFORM_PSERIES_LPAR;
}
return PLATFORM_PSERIES;
#else
- return PLATFORM_CHRP;
+ return PLATFORM_GENERIC;
#endif
}
@@ -1928,10 +2067,45 @@ static void __init flatten_device_tree(void)
}
-
-static void __init fixup_device_tree(void)
+#ifdef CONFIG_PPC_MAPLE
+/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
+ * The values are bad, and it doesn't even have the right number of cells. */
+static void __init fixup_device_tree_maple(void)
{
+ phandle isa;
+ u32 isa_ranges[6];
+
+ isa = call_prom("finddevice", 1, 1, ADDR("/ht@0/isa@4"));
+ if (!PHANDLE_VALID(isa))
+ return;
+
+ if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
+ == PROM_ERROR)
+ return;
+
+ if (isa_ranges[0] != 0x1 ||
+ isa_ranges[1] != 0xf4000000 ||
+ isa_ranges[2] != 0x00010000)
+ return;
+
+ prom_printf("fixing up bogus ISA range on Maple...\n");
+
+ isa_ranges[0] = 0x1;
+ isa_ranges[1] = 0x0;
+ isa_ranges[2] = 0x01002000; /* IO space; PCI device = 4 */
+ isa_ranges[3] = 0x0;
+ isa_ranges[4] = 0x0;
+ isa_ranges[5] = 0x00010000;
+ prom_setprop(isa, "/ht@0/isa@4", "ranges",
+ isa_ranges, sizeof(isa_ranges));
+}
+#else
+#define fixup_device_tree_maple()
+#endif
+
#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
+static void __init fixup_device_tree_pmac(void)
+{
phandle u3, i2c, mpic;
u32 u3_rev;
u32 interrupts[2];
@@ -1968,9 +2142,16 @@ static void __init fixup_device_tree(void)
parent = (u32)mpic;
prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
&parent, sizeof(parent));
-#endif
}
+#else
+#define fixup_device_tree_pmac()
+#endif
+static void __init fixup_device_tree(void)
+{
+ fixup_device_tree_maple();
+ fixup_device_tree_pmac();
+}
static void __init prom_find_boot_cpu(void)
{
@@ -2029,7 +2210,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
{
struct prom_t *_prom;
unsigned long hdr;
- u32 getprop_rval;
unsigned long offset = reloc_offset();
#ifdef CONFIG_PPC32
@@ -2060,6 +2240,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*/
prom_init_stdout();
+ /*
+ * Get default machine type. At this point, we do not differentiate
+ * between pSeries SMP and pSeries LPAR
+ */
+ RELOC(of_platform) = prom_find_machine_type();
+
/* Bail if this is a kdump kernel. */
if (PHYSICAL_START > 0)
prom_panic("Error: You can't boot a kdump kernel from OF!\n");
@@ -2069,15 +2255,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*/
prom_check_initrd(r3, r4);
- /*
- * Get default machine type. At this point, we do not differentiate
- * between pSeries SMP and pSeries LPAR
- */
- RELOC(of_platform) = prom_find_machine_type();
- getprop_rval = RELOC(of_platform);
- prom_setprop(_prom->chosen, "/chosen", "linux,platform",
- &getprop_rval, sizeof(getprop_rval));
-
#ifdef CONFIG_PPC_PSERIES
/*
* On pSeries, inform the firmware about our capabilities
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index bcb83574335..4a677d1bd4e 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -538,7 +538,7 @@ void do_syscall_trace_enter(struct pt_regs *regs)
do_syscall_trace();
if (unlikely(current->audit_context))
- audit_syscall_entry(current,
+ audit_syscall_entry(
#ifdef CONFIG_PPC32
AUDIT_ARCH_PPC,
#else
@@ -556,8 +556,7 @@ void do_syscall_trace_leave(struct pt_regs *regs)
#endif
if (unlikely(current->audit_context))
- audit_syscall_exit(current,
- (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
+ audit_syscall_exit((regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
regs->result);
if ((test_thread_flag(TIF_SYSCALL_TRACE)
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index 1f03fb28cc0..9c9ad1fa9cc 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -257,12 +257,12 @@ static int __init proc_rtas_init(void)
{
struct proc_dir_entry *entry;
- if (_machine != PLATFORM_PSERIES && _machine != PLATFORM_PSERIES_LPAR)
- return 1;
+ if (!machine_is(pseries))
+ return -ENODEV;
rtas_node = of_find_node_by_name(NULL, "rtas");
if (rtas_node == NULL)
- return 1;
+ return -ENODEV;
entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL);
if (entry)
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index b5b2add7ad1..0112318213a 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -25,6 +25,7 @@
#include <asm/hvcall.h>
#include <asm/semaphore.h>
#include <asm/machdep.h>
+#include <asm/firmware.h>
#include <asm/page.h>
#include <asm/param.h>
#include <asm/system.h>
@@ -32,6 +33,7 @@
#include <asm/uaccess.h>
#include <asm/lmb.h>
#include <asm/udbg.h>
+#include <asm/syscalls.h>
struct rtas_t rtas = {
.lock = SPIN_LOCK_UNLOCKED
@@ -576,26 +578,26 @@ static void rtas_percpu_suspend_me(void *info)
* We use "waiting" to indicate our state. As long
* as it is >0, we are still trying to all join up.
* If it goes to 0, we have successfully joined up and
- * one thread got H_Continue. If any error happens,
+ * one thread got H_CONTINUE. If any error happens,
* we set it to <0.
*/
local_irq_save(flags);
do {
rc = plpar_hcall_norets(H_JOIN);
smp_rmb();
- } while (rc == H_Success && data->waiting > 0);
- if (rc == H_Success)
+ } while (rc == H_SUCCESS && data->waiting > 0);
+ if (rc == H_SUCCESS)
goto out;
- if (rc == H_Continue) {
+ if (rc == H_CONTINUE) {
data->waiting = 0;
data->args->args[data->args->nargs] =
rtas_call(ibm_suspend_me_token, 0, 1, NULL);
- for_each_cpu(i)
+ for_each_possible_cpu(i)
plpar_hcall_norets(H_PROD,i);
} else {
data->waiting = -EBUSY;
- printk(KERN_ERR "Error on H_Join hypervisor call\n");
+ printk(KERN_ERR "Error on H_JOIN hypervisor call\n");
}
out:
@@ -622,9 +624,9 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
printk(KERN_ERR "Error doing global join\n");
/* Prod each CPU. This won't hurt, and will wake
- * anyone we successfully put to sleep with H_Join
+ * anyone we successfully put to sleep with H_JOIN.
*/
- for_each_cpu(i)
+ for_each_possible_cpu(i)
plpar_hcall_norets(H_PROD, i);
return data.waiting;
@@ -767,7 +769,7 @@ void __init rtas_initialize(void)
* the stop-self token if any
*/
#ifdef CONFIG_PPC64
- if (_machine == PLATFORM_PSERIES_LPAR) {
+ if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) {
rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
ibm_suspend_me_token = rtas_token("ibm,suspend-me");
}
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index c1d62bf11f2..684ab1d49c6 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -9,6 +9,9 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+
+#undef DEBUG
+
#include <linux/config.h>
#include <linux/module.h>
#include <linux/string.h>
@@ -18,6 +21,7 @@
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/initrd.h>
+#include <linux/platform_device.h>
#include <linux/ide.h>
#include <linux/seq_file.h>
#include <linux/ioport.h>
@@ -41,6 +45,7 @@
#include <asm/time.h>
#include <asm/cputable.h>
#include <asm/sections.h>
+#include <asm/firmware.h>
#include <asm/btext.h>
#include <asm/nvram.h>
#include <asm/setup.h>
@@ -56,8 +61,6 @@
#include "setup.h"
-#undef DEBUG
-
#ifdef DEBUG
#include <asm/udbg.h>
#define DBG(fmt...) udbg_printf(fmt)
@@ -65,10 +68,12 @@
#define DBG(fmt...)
#endif
-#ifdef CONFIG_PPC_MULTIPLATFORM
-int _machine = 0;
-EXPORT_SYMBOL(_machine);
-#endif
+/* The main machine-dep calls structure
+ */
+struct machdep_calls ppc_md;
+EXPORT_SYMBOL(ppc_md);
+struct machdep_calls *machine_id;
+EXPORT_SYMBOL(machine_id);
unsigned long klimit = (unsigned long) _end;
@@ -168,7 +173,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
bogosum/(500000/HZ), bogosum/(5000/HZ) % 100);
#endif /* CONFIG_SMP && CONFIG_PPC32 */
seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
-
+ if (ppc_md.name)
+ seq_printf(m, "platform\t: %s\n", ppc_md.name);
if (ppc_md.show_cpuinfo != NULL)
ppc_md.show_cpuinfo(m);
@@ -352,12 +358,13 @@ void __init check_for_initrd(void)
* must be called before using this.
*
* While we're here, we may as well set the "physical" cpu ids in the paca.
+ *
+ * NOTE: This must match the parsing done in early_init_dt_scan_cpus.
*/
void __init smp_setup_cpu_maps(void)
{
struct device_node *dn = NULL;
int cpu = 0;
- int swap_cpuid = 0;
while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
int *intserv;
@@ -376,30 +383,17 @@ void __init smp_setup_cpu_maps(void)
for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
cpu_set(cpu, cpu_present_map);
set_hard_smp_processor_id(cpu, intserv[j]);
-
- if (intserv[j] == boot_cpuid_phys)
- swap_cpuid = cpu;
cpu_set(cpu, cpu_possible_map);
cpu++;
}
}
- /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that
- * boot cpu is logical 0.
- */
- if (boot_cpuid_phys != get_hard_smp_processor_id(0)) {
- u32 tmp;
- tmp = get_hard_smp_processor_id(0);
- set_hard_smp_processor_id(0, boot_cpuid_phys);
- set_hard_smp_processor_id(swap_cpuid, tmp);
- }
-
#ifdef CONFIG_PPC64
/*
* On pSeries LPAR, we need to know how many cpus
* could possibly be added to this partition.
*/
- if (_machine == PLATFORM_PSERIES_LPAR &&
+ if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR) &&
(dn = of_find_node_by_path("/rtas"))) {
int num_addr_cell, num_size_cell, maxcpus;
unsigned int *ireg;
@@ -438,7 +432,7 @@ void __init smp_setup_cpu_maps(void)
/*
* Do the sibling map; assume only two threads per processor.
*/
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
cpu_set(cpu, cpu_sibling_map[cpu]);
if (cpu_has_feature(CPU_FTR_SMT))
cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
@@ -468,3 +462,65 @@ static int __init early_xmon(char *p)
}
early_param("xmon", early_xmon);
#endif
+
+static __init int add_pcspkr(void)
+{
+ struct device_node *np;
+ struct platform_device *pd;
+ int ret;
+
+ np = of_find_compatible_node(NULL, NULL, "pnpPNP,100");
+ of_node_put(np);
+ if (!np)
+ return -ENODEV;
+
+ pd = platform_device_alloc("pcspkr", -1);
+ if (!pd)
+ return -ENOMEM;
+
+ ret = platform_device_add(pd);
+ if (ret)
+ platform_device_put(pd);
+
+ return ret;
+}
+device_initcall(add_pcspkr);
+
+void probe_machine(void)
+{
+ extern struct machdep_calls __machine_desc_start;
+ extern struct machdep_calls __machine_desc_end;
+
+ /*
+ * Iterate all ppc_md structures until we find the proper
+ * one for the current machine type
+ */
+ DBG("Probing machine type ...\n");
+
+ for (machine_id = &__machine_desc_start;
+ machine_id < &__machine_desc_end;
+ machine_id++) {
+ DBG(" %s ...", machine_id->name);
+ memcpy(&ppc_md, machine_id, sizeof(struct machdep_calls));
+ if (ppc_md.probe()) {
+ DBG(" match !\n");
+ break;
+ }
+ DBG("\n");
+ }
+ /* What can we do if we didn't find ? */
+ if (machine_id >= &__machine_desc_end) {
+ DBG("No suitable machine found !\n");
+ for (;;);
+ }
+
+ printk(KERN_INFO "Using %s machine description\n", ppc_md.name);
+}
+
+int check_legacy_ioport(unsigned long base_port)
+{
+ if (ppc_md.check_legacy_ioport == NULL)
+ return 0;
+ return ppc_md.check_legacy_ioport(base_port);
+}
+EXPORT_SYMBOL(check_legacy_ioport);
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index dc2770df25b..69ac2570134 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -50,12 +50,8 @@
#include <asm/kgdb.h>
#endif
-extern void platform_init(void);
extern void bootx_init(unsigned long r4, unsigned long phys);
-extern void ppc6xx_idle(void);
-extern void power4_idle(void);
-
boot_infos_t *boot_infos;
struct ide_machdep_calls ppc_ide_md;
@@ -70,10 +66,6 @@ unsigned int DMA_MODE_WRITE;
int have_of = 1;
#ifdef CONFIG_PPC_MULTIPLATFORM
-extern void prep_init(void);
-extern void pmac_init(void);
-extern void chrp_init(void);
-
dev_t boot_dev;
#endif /* CONFIG_PPC_MULTIPLATFORM */
@@ -85,9 +77,6 @@ unsigned long SYSRQ_KEY = 0x54;
unsigned long vgacon_remap_base;
#endif
-struct machdep_calls ppc_md;
-EXPORT_SYMBOL(ppc_md);
-
/*
* These are used in binfmt_elf.c to put aux entries on the stack
* for each elf executable being started.
@@ -111,7 +100,7 @@ unsigned long __init early_init(unsigned long dt_ptr)
/* First zero the BSS -- use memset_io, some platforms don't have
* caches on yet */
- memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start);
+ memset_io((void __iomem *)PTRRELOC(&__bss_start), 0, _end - __bss_start);
/*
* Identify the CPU type and fix up code sections
@@ -123,48 +112,6 @@ unsigned long __init early_init(unsigned long dt_ptr)
return KERNELBASE + offset;
}
-#ifdef CONFIG_PPC_MULTIPLATFORM
-/*
- * The PPC_MULTIPLATFORM version of platform_init...
- */
-void __init platform_init(void)
-{
- /* if we didn't get any bootinfo telling us what we are... */
- if (_machine == 0) {
- /* prep boot loader tells us if we're prep or not */
- if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
- _machine = _MACH_prep;
- }
-
-#ifdef CONFIG_PPC_PREP
- /* not much more to do here, if prep */
- if (_machine == _MACH_prep) {
- prep_init();
- return;
- }
-#endif
-
-#ifdef CONFIG_ADB
- if (strstr(cmd_line, "adb_sync")) {
- extern int __adb_probe_sync;
- __adb_probe_sync = 1;
- }
-#endif /* CONFIG_ADB */
-
- switch (_machine) {
-#ifdef CONFIG_PPC_PMAC
- case _MACH_Pmac:
- pmac_init();
- break;
-#endif
-#ifdef CONFIG_PPC_CHRP
- case _MACH_chrp:
- chrp_init();
- break;
-#endif
- }
-}
-#endif
/*
* Find out what kind of machine we're on and save any data we need
@@ -190,11 +137,12 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys)
strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
#endif /* CONFIG_CMDLINE */
- /* Base init based on machine type */
- platform_init();
+ probe_machine();
#ifdef CONFIG_6xx
- ppc_md.power_save = ppc6xx_idle;
+ if (cpu_has_feature(CPU_FTR_CAN_DOZE) ||
+ cpu_has_feature(CPU_FTR_CAN_NAP))
+ ppc_md.power_save = ppc6xx_idle;
#endif
if (ppc_md.progress)
@@ -272,7 +220,7 @@ int __init ppc_init(void)
if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
/* register CPU devices */
- for_each_cpu(i)
+ for_each_possible_cpu(i)
register_cpu(&cpu_devices[i], i, NULL);
/* call platform init */
@@ -352,12 +300,6 @@ void __init setup_arch(char **cmdline_p)
do_init_bootmem();
if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
-#ifdef CONFIG_PPC_OCP
- /* Initialize OCP device list */
- ocp_early_init();
- if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab);
-#endif
-
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
@@ -366,7 +308,4 @@ void __init setup_arch(char **cmdline_p)
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
paging_init();
-
- /* this is for modules since _machine can be a define -- Cort */
- ppc_md.ppc_machine = _machine;
}
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 2f3fdad3559..4467c49903b 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -73,7 +73,6 @@
int have_of = 1;
int boot_cpuid = 0;
-int boot_cpuid_phys = 0;
dev_t boot_dev;
u64 ppc64_pft_size;
@@ -96,11 +95,6 @@ int dcache_bsize;
int icache_bsize;
int ucache_bsize;
-/* The main machine-dep calls structure
- */
-struct machdep_calls ppc_md;
-EXPORT_SYMBOL(ppc_md);
-
#ifdef CONFIG_MAGIC_SYSRQ
unsigned long SYSRQ_KEY;
#endif /* CONFIG_MAGIC_SYSRQ */
@@ -161,32 +155,6 @@ early_param("smt-enabled", early_smt_enabled);
#define check_smt_enabled()
#endif /* CONFIG_SMP */
-extern struct machdep_calls pSeries_md;
-extern struct machdep_calls pmac_md;
-extern struct machdep_calls maple_md;
-extern struct machdep_calls cell_md;
-extern struct machdep_calls iseries_md;
-
-/* Ultimately, stuff them in an elf section like initcalls... */
-static struct machdep_calls __initdata *machines[] = {
-#ifdef CONFIG_PPC_PSERIES
- &pSeries_md,
-#endif /* CONFIG_PPC_PSERIES */
-#ifdef CONFIG_PPC_PMAC
- &pmac_md,
-#endif /* CONFIG_PPC_PMAC */
-#ifdef CONFIG_PPC_MAPLE
- &maple_md,
-#endif /* CONFIG_PPC_MAPLE */
-#ifdef CONFIG_PPC_CELL
- &cell_md,
-#endif
-#ifdef CONFIG_PPC_ISERIES
- &iseries_md,
-#endif
- NULL
-};
-
/*
* Early initialization entry point. This is called by head.S
* with MMU translation disabled. We rely on the "feature" of
@@ -208,13 +176,10 @@ static struct machdep_calls __initdata *machines[] = {
void __init early_setup(unsigned long dt_ptr)
{
- struct paca_struct *lpaca = get_paca();
- static struct machdep_calls **mach;
-
/* Enable early debugging if any specified (see udbg.h) */
udbg_early_init();
- DBG(" -> early_setup()\n");
+ DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr);
/*
* Do early initializations using the flattened device
@@ -223,22 +188,16 @@ void __init early_setup(unsigned long dt_ptr)
*/
early_init_devtree(__va(dt_ptr));
- /*
- * Iterate all ppc_md structures until we find the proper
- * one for the current machine type
- */
- DBG("Probing machine type for platform %x...\n", _machine);
+ /* Now we know the logical id of our boot cpu, setup the paca. */
+ setup_boot_paca();
- for (mach = machines; *mach; mach++) {
- if ((*mach)->probe(_machine))
- break;
- }
- /* What can we do if we didn't find ? */
- if (*mach == NULL) {
- DBG("No suitable machine found !\n");
- for (;;);
- }
- ppc_md = **mach;
+ /* Fix up paca fields required for the boot cpu */
+ get_paca()->cpu_start = 1;
+ get_paca()->stab_real = __pa((u64)&initial_stab);
+ get_paca()->stab_addr = (u64)&initial_stab;
+
+ /* Probe the machine type */
+ probe_machine();
#ifdef CONFIG_CRASH_DUMP
kdump_setup();
@@ -256,12 +215,10 @@ void __init early_setup(unsigned long dt_ptr)
/*
* Initialize stab / SLB management except on iSeries
*/
- if (!firmware_has_feature(FW_FEATURE_ISERIES)) {
- if (cpu_has_feature(CPU_FTR_SLB))
- slb_initialize();
- else
- stab_initialize(lpaca->stab_real);
- }
+ if (cpu_has_feature(CPU_FTR_SLB))
+ slb_initialize();
+ else if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ stab_initialize(get_paca()->stab_real);
DBG(" <- early_setup()\n");
}
@@ -340,7 +297,7 @@ static void __init initialize_cache_info(void)
const char *dc, *ic;
/* Then read cache informations */
- if (_machine == PLATFORM_POWERMAC) {
+ if (machine_is(powermac)) {
dc = "d-cache-block-size";
ic = "i-cache-block-size";
} else {
@@ -484,7 +441,6 @@ void __init setup_system(void)
printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
printk("ppc64_interrupt_controller = 0x%ld\n",
ppc64_interrupt_controller);
- printk("platform = 0x%x\n", _machine);
printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size());
printk("ppc64_caches.dcache_line_size = 0x%x\n",
ppc64_caches.dline_size);
@@ -516,7 +472,7 @@ static void __init irqstack_early_init(void)
* interrupt stacks must be under 256MB, we cannot afford to take
* SLB misses on them.
*/
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
softirq_ctx[i] = (struct thread_info *)
__va(lmb_alloc_base(THREAD_SIZE,
THREAD_SIZE, 0x10000000));
@@ -549,7 +505,7 @@ static void __init emergency_stack_init(void)
*/
limit = min(0x10000000UL, lmb.rmo_size);
- for_each_cpu(i)
+ for_each_possible_cpu(i)
paca[i].emergency_sp =
__va(lmb_alloc_base(HW_PAGE_SIZE, 128, limit)) + HW_PAGE_SIZE;
}
@@ -579,7 +535,8 @@ void __init setup_arch(char **cmdline_p)
panic_timeout = 180;
if (ppc_md.panic)
- notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &ppc64_panic_block);
init_mm.start_code = PAGE_OFFSET;
init_mm.end_code = (unsigned long) _etext;
@@ -601,12 +558,6 @@ void __init setup_arch(char **cmdline_p)
ppc_md.setup_arch();
- /* Use the default idle loop if the platform hasn't provided one. */
- if (NULL == ppc_md.idle_loop) {
- ppc_md.idle_loop = default_idle;
- printk(KERN_INFO "Using default idle loop\n");
- }
-
paging_init();
ppc64_boot_msg(0x15, "Setup Done");
}
@@ -643,14 +594,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg)
printk("[terminate]%04x %s\n", src, msg);
}
-int check_legacy_ioport(unsigned long base_port)
-{
- if (ppc_md.check_legacy_ioport == NULL)
- return 0;
- return ppc_md.check_legacy_ioport(base_port);
-}
-EXPORT_SYMBOL(check_legacy_ioport);
-
void cpu_die(void)
{
if (ppc_md.cpu_die)
@@ -671,7 +614,7 @@ void __init setup_per_cpu_areas(void)
size = PERCPU_ENOUGH_ROOM;
#endif
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size);
if (!ptr)
panic("Cannot allocate cpu data for CPU %d\n", i);
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index d7a4e814974..8fdeca2d459 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -42,6 +42,7 @@
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
+#include <asm/syscalls.h>
#include <asm/sigcontext.h>
#include <asm/vdso.h>
#ifdef CONFIG_PPC64
@@ -802,10 +803,13 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int
if (__get_user(cmcp, &ucp->uc_regs))
return -EFAULT;
mcp = (struct mcontext __user *)(u64)cmcp;
+ /* no need to check access_ok(mcp), since mcp < 4GB */
}
#else
if (__get_user(mcp, &ucp->uc_regs))
return -EFAULT;
+ if (!access_ok(VERIFY_READ, mcp, sizeof(*mcp)))
+ return -EFAULT;
#endif
restore_sigmask(&set);
if (restore_user_regs(regs, mcp, sig))
@@ -907,13 +911,14 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
{
struct sig_dbg_op op;
int i;
+ unsigned char tmp;
unsigned long new_msr = regs->msr;
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
unsigned long new_dbcr0 = current->thread.dbcr0;
#endif
for (i=0; i<ndbg; i++) {
- if (__copy_from_user(&op, dbg, sizeof(op)))
+ if (copy_from_user(&op, dbg + i, sizeof(op)))
return -EFAULT;
switch (op.dbg_type) {
case SIG_DBG_SINGLE_STEPPING:
@@ -958,6 +963,11 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
current->thread.dbcr0 = new_dbcr0;
#endif
+ if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx))
+ || __get_user(tmp, (u8 __user *) ctx)
+ || __get_user(tmp, (u8 __user *) (ctx + 1) - 1))
+ return -EFAULT;
+
/*
* If we get a fault copying the context into the kernel's
* image of the user's registers, we can't just return -EFAULT
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 47f910380a6..c2db642f4cd 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -33,6 +33,7 @@
#include <asm/pgtable.h>
#include <asm/unistd.h>
#include <asm/cacheflush.h>
+#include <asm/syscalls.h>
#include <asm/vdso.h>
#define DEBUG_SIG 0
@@ -181,6 +182,8 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
if (err)
return err;
+ if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128)))
+ return -EFAULT;
/* Copy 33 vec registers (vr0..31 and vscr) from the stack */
if (v_regs != 0 && (msr & MSR_VEC) != 0)
err |= __copy_from_user(current->thread.vr, v_regs,
@@ -211,7 +214,7 @@ static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs
/* Default to using normal stack */
newsp = regs->gpr[1];
- if (ka->sa.sa_flags & SA_ONSTACK) {
+ 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);
}
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 805eaedbc30..530f7dba0bd 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -362,7 +362,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
smp_space_timers(max_cpus);
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
if (cpu != boot_cpuid)
smp_create_idle(cpu);
}
diff --git a/arch/ppc/kernel/swsusp.S b/arch/powerpc/kernel/swsusp_32.S
index 69773cc1a85..69773cc1a85 100644
--- a/arch/ppc/kernel/swsusp.S
+++ b/arch/powerpc/kernel/swsusp_32.S
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
index ad895c99813..9b69d99a910 100644
--- a/arch/powerpc/kernel/syscalls.c
+++ b/arch/powerpc/kernel/syscalls.c
@@ -40,6 +40,7 @@
#include <asm/uaccess.h>
#include <asm/ipc.h>
#include <asm/semaphore.h>
+#include <asm/syscalls.h>
#include <asm/time.h>
#include <asm/unistd.h>
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 0f0c3a9ae2e..5bc2585c803 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -65,20 +65,20 @@ static int __init smt_setup(void)
unsigned int cpu;
if (!cpu_has_feature(CPU_FTR_SMT))
- return 1;
+ return -ENODEV;
options = find_path_device("/options");
if (!options)
- return 1;
+ return -ENODEV;
val = (unsigned int *)get_property(options, "ibm,smt-snooze-delay",
NULL);
if (!smt_snooze_cmdline && val) {
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
per_cpu(smt_snooze_delay, cpu) = *val;
}
- return 1;
+ return 0;
}
__initcall(smt_setup);
@@ -93,7 +93,7 @@ static int __init setup_smt_snooze_delay(char *str)
smt_snooze_cmdline = 1;
if (get_option(&str, &snooze)) {
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
per_cpu(smt_snooze_delay, cpu) = snooze;
}
@@ -279,7 +279,7 @@ static void unregister_cpu_online(unsigned int cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
-static int __devinit sysfs_cpu_notify(struct notifier_block *self,
+static int sysfs_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned int)(long)hcpu;
@@ -297,7 +297,7 @@ static int __devinit sysfs_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata sysfs_cpu_nb = {
+static struct notifier_block sysfs_cpu_nb = {
.notifier_call = sysfs_cpu_notify,
};
@@ -322,13 +322,31 @@ static void register_nodes(void)
}
}
}
+
+int sysfs_add_device_to_node(struct sys_device *dev, int nid)
+{
+ struct node *node = &node_devices[nid];
+ return sysfs_create_link(&node->sysdev.kobj, &dev->kobj,
+ kobject_name(&dev->kobj));
+}
+
+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));
+}
+
#else
static void register_nodes(void)
{
return;
}
+
#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)
{
@@ -347,7 +365,7 @@ static int __init topology_init(void)
register_cpu_notifier(&sysfs_cpu_nb);
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct cpu *c = &per_cpu(cpu_devices, cpu);
#ifdef CONFIG_NUMA
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 1ad55f0466f..26ed1f5ef16 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -322,3 +322,26 @@ SYSCALL(spu_create)
COMPAT_SYS(pselect6)
COMPAT_SYS(ppoll)
SYSCALL(unshare)
+SYSCALL(splice)
+SYSCALL(tee)
+SYSCALL(vmsplice)
+COMPAT_SYS(openat)
+SYSCALL(mkdirat)
+SYSCALL(mknodat)
+SYSCALL(fchownat)
+COMPAT_SYS(futimesat)
+SYSX(sys_newfstatat, sys_fstatat64, sys_fstatat64)
+SYSCALL(unlinkat)
+SYSCALL(renameat)
+SYSCALL(linkat)
+SYSCALL(symlinkat)
+SYSCALL(readlinkat)
+SYSCALL(fchmodat)
+SYSCALL(faccessat)
+COMPAT_SYS(get_robust_list)
+COMPAT_SYS(set_robust_list)
+
+/*
+ * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c
+ * as well when appropriate.
+ */
diff --git a/arch/ppc/kernel/temp.c b/arch/powerpc/kernel/tau_6xx.c
index 26bd8ea35a4..26bd8ea35a4 100644
--- a/arch/ppc/kernel/temp.c
+++ b/arch/powerpc/kernel/tau_6xx.c
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 4a27218a086..24e3ad756de 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -261,7 +261,7 @@ void snapshot_timebases(void)
if (!cpu_has_feature(CPU_FTR_PURR))
return;
- for_each_cpu(cpu)
+ 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);
}
@@ -751,7 +751,7 @@ void __init smp_space_timers(unsigned int max_cpus)
* systems works better if the two threads' timebase interrupts
* are staggered by half a jiffy with respect to each other.
*/
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
if (i == boot_cpuid)
continue;
if (i == (boot_cpuid ^ 1))
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 98660aedeeb..064a5256469 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -74,19 +74,19 @@ EXPORT_SYMBOL(__debugger_dabr_match);
EXPORT_SYMBOL(__debugger_fault_handler);
#endif
-struct notifier_block *powerpc_die_chain;
-static DEFINE_SPINLOCK(die_notifier_lock);
+ATOMIC_NOTIFIER_HEAD(powerpc_die_chain);
int register_die_notifier(struct notifier_block *nb)
{
- int err = 0;
- unsigned long flags;
+ return atomic_notifier_chain_register(&powerpc_die_chain, nb);
+}
+EXPORT_SYMBOL(register_die_notifier);
- spin_lock_irqsave(&die_notifier_lock, flags);
- err = notifier_chain_register(&powerpc_die_chain, nb);
- spin_unlock_irqrestore(&die_notifier_lock, flags);
- return err;
+int unregister_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&powerpc_die_chain, nb);
}
+EXPORT_SYMBOL(unregister_die_notifier);
/*
* Trap & Exception support
@@ -97,7 +97,6 @@ static DEFINE_SPINLOCK(die_lock);
int die(const char *str, struct pt_regs *regs, long err)
{
static int die_counter, crash_dump_start = 0;
- int nl = 0;
if (debugger(regs))
return 1;
@@ -106,7 +105,7 @@ int die(const char *str, struct pt_regs *regs, long err)
spin_lock_irq(&die_lock);
bust_spinlocks(1);
#ifdef CONFIG_PMAC_BACKLIGHT
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
set_backlight_enable(1);
set_backlight_level(BACKLIGHT_MAX);
}
@@ -114,46 +113,18 @@ int die(const char *str, struct pt_regs *regs, long err)
printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
#ifdef CONFIG_PREEMPT
printk("PREEMPT ");
- nl = 1;
#endif
#ifdef CONFIG_SMP
printk("SMP NR_CPUS=%d ", NR_CPUS);
- nl = 1;
#endif
#ifdef CONFIG_DEBUG_PAGEALLOC
printk("DEBUG_PAGEALLOC ");
- nl = 1;
#endif
#ifdef CONFIG_NUMA
printk("NUMA ");
- nl = 1;
#endif
-#ifdef CONFIG_PPC64
- switch (_machine) {
- case PLATFORM_PSERIES:
- printk("PSERIES ");
- nl = 1;
- break;
- case PLATFORM_PSERIES_LPAR:
- printk("PSERIES LPAR ");
- nl = 1;
- break;
- case PLATFORM_ISERIES_LPAR:
- printk("ISERIES LPAR ");
- nl = 1;
- break;
- case PLATFORM_POWERMAC:
- printk("POWERMAC ");
- nl = 1;
- break;
- case PLATFORM_CELL:
- printk("CELL ");
- nl = 1;
- break;
- }
-#endif
- if (nl)
- printk("\n");
+ printk("%s\n", ppc_md.name ? "" : ppc_md.name);
+
print_modules();
show_regs(regs);
bust_spinlocks(0);
@@ -257,7 +228,7 @@ void system_reset_exception(struct pt_regs *regs)
*/
static inline int check_io_access(struct pt_regs *regs)
{
-#ifdef CONFIG_PPC_PMAC
+#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
unsigned long msr = regs->msr;
const struct exception_table_entry *entry;
unsigned int *nip = (unsigned int *)regs->nip;
@@ -290,7 +261,7 @@ static inline int check_io_access(struct pt_regs *regs)
return 1;
}
}
-#endif /* CONFIG_PPC_PMAC */
+#endif /* CONFIG_PPC_PMAC && CONFIG_PPC32 */
return 0;
}
@@ -337,8 +308,8 @@ platform_machine_check(struct pt_regs *regs)
void machine_check_exception(struct pt_regs *regs)
{
-#ifdef CONFIG_PPC64
int recover = 0;
+ unsigned long reason = get_mc_reason(regs);
/* See if any machine dependent calls */
if (ppc_md.machine_check_exception)
@@ -346,8 +317,6 @@ void machine_check_exception(struct pt_regs *regs)
if (recover)
return;
-#else
- unsigned long reason = get_mc_reason(regs);
if (user_mode(regs)) {
regs->msr |= MSR_RI;
@@ -491,7 +460,6 @@ void machine_check_exception(struct pt_regs *regs)
* additional info, e.g. bus error registers.
*/
platform_machine_check(regs);
-#endif /* CONFIG_PPC64 */
if (debugger_fault_handler(regs))
return;
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index ec837036842..573afb68d69 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -33,6 +33,7 @@
#include <asm/machdep.h>
#include <asm/cputable.h>
#include <asm/sections.h>
+#include <asm/firmware.h>
#include <asm/vdso.h>
#include <asm/vdso_datapage.h>
@@ -667,7 +668,13 @@ void __init vdso_init(void)
vdso_data->version.major = SYSTEMCFG_MAJOR;
vdso_data->version.minor = SYSTEMCFG_MINOR;
vdso_data->processor = mfspr(SPRN_PVR);
- vdso_data->platform = _machine;
+ /*
+ * Fake the old platform number for pSeries and iSeries and add
+ * in LPAR bit if necessary
+ */
+ vdso_data->platform = machine_is(iseries) ? 0x200 : 0x100;
+ if (firmware_has_feature(FW_FEATURE_LPAR))
+ vdso_data->platform |= 1;
vdso_data->physicalMemorySize = lmb_phys_mem_size();
vdso_data->dcache_size = ppc64_caches.dsize;
vdso_data->dcache_line_size = ppc64_caches.dline_size;
diff --git a/arch/powerpc/kernel/vdso32/sigtramp.S b/arch/powerpc/kernel/vdso32/sigtramp.S
index e0464278191..0c6a37b29dd 100644
--- a/arch/powerpc/kernel/vdso32/sigtramp.S
+++ b/arch/powerpc/kernel/vdso32/sigtramp.S
@@ -261,7 +261,7 @@ V_FUNCTION_END(__kernel_sigtramp_rt32)
.Lcie_start:
.long 0 /* CIE ID */
.byte 1 /* Version number */
- .string "zR" /* NUL-terminated augmentation string */
+ .string "zRS" /* NUL-terminated augmentation string */
.uleb128 4 /* Code alignment factor */
.sleb128 -4 /* Data alignment factor */
.byte 67 /* Return address register column, ap */
diff --git a/arch/powerpc/kernel/vdso64/sigtramp.S b/arch/powerpc/kernel/vdso64/sigtramp.S
index 31b604ab56d..7479edb101b 100644
--- a/arch/powerpc/kernel/vdso64/sigtramp.S
+++ b/arch/powerpc/kernel/vdso64/sigtramp.S
@@ -263,7 +263,7 @@ V_FUNCTION_END(__kernel_sigtramp_rt64)
.Lcie_start:
.long 0 /* CIE ID */
.byte 1 /* Version number */
- .string "zR" /* NUL-terminated augmentation string */
+ .string "zRS" /* NUL-terminated augmentation string */
.uleb128 4 /* Code alignment factor */
.sleb128 -8 /* Data alignment factor */
.byte 67 /* Return address register column, ap */
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 13c655ba284..971020cf3f7 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -202,7 +202,7 @@ static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
size_t size, enum dma_data_direction direction)
{
return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
- direction);
+ ~0ul, direction);
}
static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
@@ -216,7 +216,7 @@ static int vio_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
- nelems, direction);
+ nelems, ~0ul, direction);
}
static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
@@ -229,7 +229,7 @@ static void *vio_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
- dma_handle, flag);
+ dma_handle, ~0ul, flag);
}
static void vio_free_coherent(struct device *dev, size_t size,
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7fa7b15fd8e..fe79c2584cb 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -1,9 +1,11 @@
#include <linux/config.h>
#ifdef CONFIG_PPC64
#include <asm/page.h>
+#define PROVIDE32(x) PROVIDE(__unused__##x)
#else
#define PAGE_SIZE 4096
#define KERNELBASE CONFIG_KERNEL_START
+#define PROVIDE32(x) PROVIDE(x)
#endif
#include <asm-generic/vmlinux.lds.h>
@@ -18,43 +20,42 @@ jiffies = jiffies_64 + 4;
#endif
SECTIONS
{
- /* Sections to be discarded. */
- /DISCARD/ : {
- *(.exitcall.exit)
- *(.exit.data)
- }
-
- . = KERNELBASE;
-
- /* Read-only sections, merged into text segment: */
- .text : {
- *(.text .text.*)
- SCHED_TEXT
- LOCK_TEXT
- KPROBES_TEXT
- *(.fixup)
-#ifdef CONFIG_PPC32
- *(.got1)
- __got2_start = .;
- *(.got2)
- __got2_end = .;
-#else
- . = ALIGN(PAGE_SIZE);
- _etext = .;
-#endif
- }
-#ifdef CONFIG_PPC32
- _etext = .;
- PROVIDE (etext = .);
+ /* Sections to be discarded. */
+ /DISCARD/ : {
+ *(.exitcall.exit)
+ *(.exit.data)
+ }
- RODATA
- .fini : { *(.fini) } =0
- .ctors : { *(.ctors) }
- .dtors : { *(.dtors) }
+ . = KERNELBASE;
- .fixup : { *(.fixup) }
-#endif
+/*
+ * Text, read only data and other permanent read-only sections
+ */
+
+ /* Text and gots */
+ .text : {
+ *(.text .text.*)
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ *(.fixup)
+#ifdef CONFIG_PPC32
+ *(.got1)
+ __got2_start = .;
+ *(.got2)
+ __got2_end = .;
+#endif /* CONFIG_PPC32 */
+
+ . = ALIGN(PAGE_SIZE);
+ _etext = .;
+ PROVIDE32 (etext = .);
+ }
+
+ /* Read-only data */
+ RODATA
+
+ /* Exception & bug tables */
__ex_table : {
__start___ex_table = .;
*(__ex_table)
@@ -67,192 +68,172 @@ SECTIONS
__stop___bug_table = .;
}
-#ifdef CONFIG_PPC64
+/*
+ * Init sections discarded at runtime
+ */
+ . = ALIGN(PAGE_SIZE);
+ __init_begin = .;
+
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
+
+ /* .exit.text is discarded at runtime, not link time,
+ * to deal with references from __bug_table
+ */
+ .exit.text : { *(.exit.text) }
+
+ .init.data : {
+ *(.init.data);
+ __vtop_table_begin = .;
+ *(.vtop_fixup);
+ __vtop_table_end = .;
+ __ptov_table_begin = .;
+ *(.ptov_fixup);
+ __ptov_table_end = .;
+ }
+
+ . = ALIGN(16);
+ .init.setup : {
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ }
+
+ .initcall.init : {
+ __initcall_start = .;
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ __initcall_end = .;
+ }
+
+ .con_initcall.init : {
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ }
+
+ SECURITY_INIT
+
+ . = ALIGN(8);
__ftr_fixup : {
__start___ftr_fixup = .;
*(__ftr_fixup)
__stop___ftr_fixup = .;
}
- RODATA
-#endif
+ . = ALIGN(PAGE_SIZE);
+ .init.ramfs : {
+ __initramfs_start = .;
+ *(.init.ramfs)
+ __initramfs_end = .;
+ }
#ifdef CONFIG_PPC32
- /* Read-write section, merged into data segment: */
- . = ALIGN(PAGE_SIZE);
- _sdata = .;
- .data :
- {
- *(.data)
- *(.data1)
- *(.sdata)
- *(.sdata2)
- *(.got.plt) *(.got)
- *(.dynamic)
- CONSTRUCTORS
- }
-
- . = ALIGN(PAGE_SIZE);
- __nosave_begin = .;
- .data_nosave : { *(.data.nosave) }
- . = ALIGN(PAGE_SIZE);
- __nosave_end = .;
-
- . = ALIGN(32);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
- _edata = .;
- PROVIDE (edata = .);
-
- . = ALIGN(8192);
- .data.init_task : { *(.data.init_task) }
+ . = ALIGN(32);
+#else
+ . = ALIGN(128);
#endif
+ .data.percpu : {
+ __per_cpu_start = .;
+ *(.data.percpu)
+ __per_cpu_end = .;
+ }
- /* will be freed after init */
- . = ALIGN(PAGE_SIZE);
- __init_begin = .;
- .init.text : {
- _sinittext = .;
- *(.init.text)
- _einittext = .;
- }
-#ifdef CONFIG_PPC32
- /* .exit.text is discarded at runtime, not link time,
- to deal with references from __bug_table */
- .exit.text : { *(.exit.text) }
-#endif
- .init.data : {
- *(.init.data);
- __vtop_table_begin = .;
- *(.vtop_fixup);
- __vtop_table_end = .;
- __ptov_table_begin = .;
- *(.ptov_fixup);
- __ptov_table_end = .;
- }
-
- . = ALIGN(16);
- .init.setup : {
- __setup_start = .;
- *(.init.setup)
- __setup_end = .;
- }
-
- .initcall.init : {
- __initcall_start = .;
- *(.initcall1.init)
- *(.initcall2.init)
- *(.initcall3.init)
- *(.initcall4.init)
- *(.initcall5.init)
- *(.initcall6.init)
- *(.initcall7.init)
- __initcall_end = .;
- }
-
- .con_initcall.init : {
- __con_initcall_start = .;
- *(.con_initcall.init)
- __con_initcall_end = .;
- }
-
- SECURITY_INIT
+ . = ALIGN(8);
+ .machine.desc : {
+ __machine_desc_start = . ;
+ *(.machine.desc)
+ __machine_desc_end = . ;
+ }
+
+ /* freed after init ends here */
+ . = ALIGN(PAGE_SIZE);
+ __init_end = .;
+
+/*
+ * And now the various read/write data
+ */
+
+ . = ALIGN(PAGE_SIZE);
+ _sdata = .;
#ifdef CONFIG_PPC32
- __start___ftr_fixup = .;
- __ftr_fixup : { *(__ftr_fixup) }
- __stop___ftr_fixup = .;
+ .data :
+ {
+ *(.data)
+ *(.sdata)
+ *(.got.plt) *(.got)
+ }
#else
- . = ALIGN(PAGE_SIZE);
- .init.ramfs : {
- __initramfs_start = .;
- *(.init.ramfs)
- __initramfs_end = .;
- }
-#endif
+ .data : {
+ *(.data .data.rel* .toc1)
+ *(.branch_lt)
+ }
-#ifdef CONFIG_PPC32
- . = ALIGN(32);
+ .opd : {
+ *(.opd)
+ }
+
+ .got : {
+ __toc_start = .;
+ *(.got)
+ *(.toc)
+ }
#endif
- .data.percpu : {
- __per_cpu_start = .;
- *(.data.percpu)
- __per_cpu_end = .;
- }
- . = ALIGN(PAGE_SIZE);
-#ifdef CONFIG_PPC64
- . = ALIGN(16384);
- __init_end = .;
- /* freed after init ends here */
-
- /* Read/write sections */
- . = ALIGN(PAGE_SIZE);
- . = ALIGN(16384);
- _sdata = .;
- /* The initial task and kernel stack */
- .data.init_task : {
- *(.data.init_task)
- }
-
- . = ALIGN(PAGE_SIZE);
- .data.page_aligned : {
- *(.data.page_aligned)
- }
-
- .data.cacheline_aligned : {
- *(.data.cacheline_aligned)
- }
-
- .data : {
- *(.data .data.rel* .toc1)
- *(.branch_lt)
- }
-
- .opd : {
- *(.opd)
- }
-
- .got : {
- __toc_start = .;
- *(.got)
- *(.toc)
- . = ALIGN(PAGE_SIZE);
- _edata = .;
- }
-
- . = ALIGN(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
+ _edata = .;
+ PROVIDE32 (edata = .);
+
+ /* The initial task and kernel stack */
+#ifdef CONFIG_PPC32
+ . = ALIGN(8192);
#else
- __initramfs_start = .;
- .init.ramfs : {
- *(.init.ramfs)
- }
- __initramfs_end = .;
+ . = ALIGN(16384);
+#endif
+ .data.init_task : {
+ *(.data.init_task)
+ }
- . = ALIGN(4096);
- __init_end = .;
+ . = ALIGN(PAGE_SIZE);
+ .data.page_aligned : {
+ *(.data.page_aligned)
+ }
- . = ALIGN(4096);
- _sextratext = .;
- _eextratext = .;
+ .data.cacheline_aligned : {
+ *(.data.cacheline_aligned)
+ }
- __bss_start = .;
-#endif
+ . = ALIGN(PAGE_SIZE);
+ __data_nosave : {
+ __nosave_begin = .;
+ *(.data.nosave)
+ . = ALIGN(PAGE_SIZE);
+ __nosave_end = .;
+ }
- .bss : {
- __bss_start = .;
- *(.sbss) *(.scommon)
- *(.dynbss)
- *(.bss)
- *(COMMON)
- __bss_stop = .;
- }
+/*
+ * And finally the bss
+ */
+
+ .bss : {
+ __bss_start = .;
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ __bss_stop = .;
+ }
-#ifdef CONFIG_PPC64
- . = ALIGN(PAGE_SIZE);
-#endif
- _end = . ;
-#ifdef CONFIG_PPC32
- PROVIDE (end = .);
-#endif
+ . = ALIGN(PAGE_SIZE);
+ _end = . ;
+ PROVIDE32 (end = .);
}
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 666c2aa5501..c251d993661 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -18,7 +18,7 @@ extern char system_call_common[];
#ifdef CONFIG_PPC64
/* Bits in SRR1 that are copied from MSR */
-#define MSR_MASK 0xffffffff87c0ffff
+#define MSR_MASK 0xffffffff87c0ffffUL
#else
#define MSR_MASK 0x87c0ffff
#endif
diff --git a/arch/ppc/math-emu/Makefile b/arch/powerpc/math-emu/Makefile
index 754143e8936..754143e8936 100644
--- a/arch/ppc/math-emu/Makefile
+++ b/arch/powerpc/math-emu/Makefile
diff --git a/arch/ppc/math-emu/double.h b/arch/powerpc/math-emu/double.h
index ffba8b67f05..ffba8b67f05 100644
--- a/arch/ppc/math-emu/double.h
+++ b/arch/powerpc/math-emu/double.h
diff --git a/arch/ppc/math-emu/fabs.c b/arch/powerpc/math-emu/fabs.c
index 41f0617f3d3..41f0617f3d3 100644
--- a/arch/ppc/math-emu/fabs.c
+++ b/arch/powerpc/math-emu/fabs.c
diff --git a/arch/ppc/math-emu/fadd.c b/arch/powerpc/math-emu/fadd.c
index fc8836488b6..fc8836488b6 100644
--- a/arch/ppc/math-emu/fadd.c
+++ b/arch/powerpc/math-emu/fadd.c
diff --git a/arch/ppc/math-emu/fadds.c b/arch/powerpc/math-emu/fadds.c
index 93025b6c8f3..93025b6c8f3 100644
--- a/arch/ppc/math-emu/fadds.c
+++ b/arch/powerpc/math-emu/fadds.c
diff --git a/arch/ppc/math-emu/fcmpo.c b/arch/powerpc/math-emu/fcmpo.c
index 4efac394b4c..4efac394b4c 100644
--- a/arch/ppc/math-emu/fcmpo.c
+++ b/arch/powerpc/math-emu/fcmpo.c
diff --git a/arch/ppc/math-emu/fcmpu.c b/arch/powerpc/math-emu/fcmpu.c
index b7e33176e61..b7e33176e61 100644
--- a/arch/ppc/math-emu/fcmpu.c
+++ b/arch/powerpc/math-emu/fcmpu.c
diff --git a/arch/ppc/math-emu/fctiw.c b/arch/powerpc/math-emu/fctiw.c
index 3b3c98b840c..3b3c98b840c 100644
--- a/arch/ppc/math-emu/fctiw.c
+++ b/arch/powerpc/math-emu/fctiw.c
diff --git a/arch/ppc/math-emu/fctiwz.c b/arch/powerpc/math-emu/fctiwz.c
index 7717eb6fcfb..7717eb6fcfb 100644
--- a/arch/ppc/math-emu/fctiwz.c
+++ b/arch/powerpc/math-emu/fctiwz.c
diff --git a/arch/ppc/math-emu/fdiv.c b/arch/powerpc/math-emu/fdiv.c
index f2fba825b2d..f2fba825b2d 100644
--- a/arch/ppc/math-emu/fdiv.c
+++ b/arch/powerpc/math-emu/fdiv.c
diff --git a/arch/ppc/math-emu/fdivs.c b/arch/powerpc/math-emu/fdivs.c
index b971196e317..b971196e317 100644
--- a/arch/ppc/math-emu/fdivs.c
+++ b/arch/powerpc/math-emu/fdivs.c
diff --git a/arch/ppc/math-emu/fmadd.c b/arch/powerpc/math-emu/fmadd.c
index 0a1dbce793e..0a1dbce793e 100644
--- a/arch/ppc/math-emu/fmadd.c
+++ b/arch/powerpc/math-emu/fmadd.c
diff --git a/arch/ppc/math-emu/fmadds.c b/arch/powerpc/math-emu/fmadds.c
index 0f70bba9445..0f70bba9445 100644
--- a/arch/ppc/math-emu/fmadds.c
+++ b/arch/powerpc/math-emu/fmadds.c
diff --git a/arch/ppc/math-emu/fmr.c b/arch/powerpc/math-emu/fmr.c
index 28df700c0c7..28df700c0c7 100644
--- a/arch/ppc/math-emu/fmr.c
+++ b/arch/powerpc/math-emu/fmr.c
diff --git a/arch/ppc/math-emu/fmsub.c b/arch/powerpc/math-emu/fmsub.c
index 203fd48a6fe..203fd48a6fe 100644
--- a/arch/ppc/math-emu/fmsub.c
+++ b/arch/powerpc/math-emu/fmsub.c
diff --git a/arch/ppc/math-emu/fmsubs.c b/arch/powerpc/math-emu/fmsubs.c
index 8ce68624c18..8ce68624c18 100644
--- a/arch/ppc/math-emu/fmsubs.c
+++ b/arch/powerpc/math-emu/fmsubs.c
diff --git a/arch/ppc/math-emu/fmul.c b/arch/powerpc/math-emu/fmul.c
index 66c7e79aae2..66c7e79aae2 100644
--- a/arch/ppc/math-emu/fmul.c
+++ b/arch/powerpc/math-emu/fmul.c
diff --git a/arch/ppc/math-emu/fmuls.c b/arch/powerpc/math-emu/fmuls.c
index 26bc4278271..26bc4278271 100644
--- a/arch/ppc/math-emu/fmuls.c
+++ b/arch/powerpc/math-emu/fmuls.c
diff --git a/arch/ppc/math-emu/fnabs.c b/arch/powerpc/math-emu/fnabs.c
index c6b913d179e..c6b913d179e 100644
--- a/arch/ppc/math-emu/fnabs.c
+++ b/arch/powerpc/math-emu/fnabs.c
diff --git a/arch/ppc/math-emu/fneg.c b/arch/powerpc/math-emu/fneg.c
index fe9a98deff6..fe9a98deff6 100644
--- a/arch/ppc/math-emu/fneg.c
+++ b/arch/powerpc/math-emu/fneg.c
diff --git a/arch/ppc/math-emu/fnmadd.c b/arch/powerpc/math-emu/fnmadd.c
index 7f312276d92..7f312276d92 100644
--- a/arch/ppc/math-emu/fnmadd.c
+++ b/arch/powerpc/math-emu/fnmadd.c
diff --git a/arch/ppc/math-emu/fnmadds.c b/arch/powerpc/math-emu/fnmadds.c
index 65454c9c70b..65454c9c70b 100644
--- a/arch/ppc/math-emu/fnmadds.c
+++ b/arch/powerpc/math-emu/fnmadds.c
diff --git a/arch/ppc/math-emu/fnmsub.c b/arch/powerpc/math-emu/fnmsub.c
index f1ca7482b5f..f1ca7482b5f 100644
--- a/arch/ppc/math-emu/fnmsub.c
+++ b/arch/powerpc/math-emu/fnmsub.c
diff --git a/arch/ppc/math-emu/fnmsubs.c b/arch/powerpc/math-emu/fnmsubs.c
index 5c9a09a87dc..5c9a09a87dc 100644
--- a/arch/ppc/math-emu/fnmsubs.c
+++ b/arch/powerpc/math-emu/fnmsubs.c
diff --git a/arch/ppc/math-emu/fres.c b/arch/powerpc/math-emu/fres.c
index ec11e46d20a..ec11e46d20a 100644
--- a/arch/ppc/math-emu/fres.c
+++ b/arch/powerpc/math-emu/fres.c
diff --git a/arch/ppc/math-emu/frsp.c b/arch/powerpc/math-emu/frsp.c
index d879b2a3d0c..d879b2a3d0c 100644
--- a/arch/ppc/math-emu/frsp.c
+++ b/arch/powerpc/math-emu/frsp.c
diff --git a/arch/ppc/math-emu/frsqrte.c b/arch/powerpc/math-emu/frsqrte.c
index a11ae182985..a11ae182985 100644
--- a/arch/ppc/math-emu/frsqrte.c
+++ b/arch/powerpc/math-emu/frsqrte.c
diff --git a/arch/ppc/math-emu/fsel.c b/arch/powerpc/math-emu/fsel.c
index e36e6e72819..e36e6e72819 100644
--- a/arch/ppc/math-emu/fsel.c
+++ b/arch/powerpc/math-emu/fsel.c
diff --git a/arch/ppc/math-emu/fsqrt.c b/arch/powerpc/math-emu/fsqrt.c
index 6f8319f64a8..6f8319f64a8 100644
--- a/arch/ppc/math-emu/fsqrt.c
+++ b/arch/powerpc/math-emu/fsqrt.c
diff --git a/arch/ppc/math-emu/fsqrts.c b/arch/powerpc/math-emu/fsqrts.c
index 3b2b1cf55c1..3b2b1cf55c1 100644
--- a/arch/ppc/math-emu/fsqrts.c
+++ b/arch/powerpc/math-emu/fsqrts.c
diff --git a/arch/ppc/math-emu/fsub.c b/arch/powerpc/math-emu/fsub.c
index 956679042bb..956679042bb 100644
--- a/arch/ppc/math-emu/fsub.c
+++ b/arch/powerpc/math-emu/fsub.c
diff --git a/arch/ppc/math-emu/fsubs.c b/arch/powerpc/math-emu/fsubs.c
index 3428117dfe8..3428117dfe8 100644
--- a/arch/ppc/math-emu/fsubs.c
+++ b/arch/powerpc/math-emu/fsubs.c
diff --git a/arch/ppc/math-emu/lfd.c b/arch/powerpc/math-emu/lfd.c
index 7d38101c329..7d38101c329 100644
--- a/arch/ppc/math-emu/lfd.c
+++ b/arch/powerpc/math-emu/lfd.c
diff --git a/arch/ppc/math-emu/lfs.c b/arch/powerpc/math-emu/lfs.c
index c86dee3d765..c86dee3d765 100644
--- a/arch/ppc/math-emu/lfs.c
+++ b/arch/powerpc/math-emu/lfs.c
diff --git a/arch/ppc/math-emu/math.c b/arch/powerpc/math-emu/math.c
index 58915347276..58915347276 100644
--- a/arch/ppc/math-emu/math.c
+++ b/arch/powerpc/math-emu/math.c
diff --git a/arch/ppc/math-emu/mcrfs.c b/arch/powerpc/math-emu/mcrfs.c
index 106dd912914..106dd912914 100644
--- a/arch/ppc/math-emu/mcrfs.c
+++ b/arch/powerpc/math-emu/mcrfs.c
diff --git a/arch/ppc/math-emu/mffs.c b/arch/powerpc/math-emu/mffs.c
index f477c9170e7..f477c9170e7 100644
--- a/arch/ppc/math-emu/mffs.c
+++ b/arch/powerpc/math-emu/mffs.c
diff --git a/arch/ppc/math-emu/mtfsb0.c b/arch/powerpc/math-emu/mtfsb0.c
index 99bfd80f4af..99bfd80f4af 100644
--- a/arch/ppc/math-emu/mtfsb0.c
+++ b/arch/powerpc/math-emu/mtfsb0.c
diff --git a/arch/ppc/math-emu/mtfsb1.c b/arch/powerpc/math-emu/mtfsb1.c
index 3d9e7ed92d2..3d9e7ed92d2 100644
--- a/arch/ppc/math-emu/mtfsb1.c
+++ b/arch/powerpc/math-emu/mtfsb1.c
diff --git a/arch/ppc/math-emu/mtfsf.c b/arch/powerpc/math-emu/mtfsf.c
index d70cf714994..d70cf714994 100644
--- a/arch/ppc/math-emu/mtfsf.c
+++ b/arch/powerpc/math-emu/mtfsf.c
diff --git a/arch/ppc/math-emu/mtfsfi.c b/arch/powerpc/math-emu/mtfsfi.c
index 71df854baa7..71df854baa7 100644
--- a/arch/ppc/math-emu/mtfsfi.c
+++ b/arch/powerpc/math-emu/mtfsfi.c
diff --git a/arch/ppc/math-emu/op-1.h b/arch/powerpc/math-emu/op-1.h
index c92fa95f562..c92fa95f562 100644
--- a/arch/ppc/math-emu/op-1.h
+++ b/arch/powerpc/math-emu/op-1.h
diff --git a/arch/ppc/math-emu/op-2.h b/arch/powerpc/math-emu/op-2.h
index b9b06b4c6ea..b9b06b4c6ea 100644
--- a/arch/ppc/math-emu/op-2.h
+++ b/arch/powerpc/math-emu/op-2.h
diff --git a/arch/ppc/math-emu/op-4.h b/arch/powerpc/math-emu/op-4.h
index fcdd6d064c5..fcdd6d064c5 100644
--- a/arch/ppc/math-emu/op-4.h
+++ b/arch/powerpc/math-emu/op-4.h
diff --git a/arch/ppc/math-emu/op-common.h b/arch/powerpc/math-emu/op-common.h
index afb82b6498c..afb82b6498c 100644
--- a/arch/ppc/math-emu/op-common.h
+++ b/arch/powerpc/math-emu/op-common.h
diff --git a/arch/ppc/math-emu/sfp-machine.h b/arch/powerpc/math-emu/sfp-machine.h
index 4b17d83cfcd..4b17d83cfcd 100644
--- a/arch/ppc/math-emu/sfp-machine.h
+++ b/arch/powerpc/math-emu/sfp-machine.h
diff --git a/arch/ppc/math-emu/single.h b/arch/powerpc/math-emu/single.h
index f19d9945181..f19d9945181 100644
--- a/arch/ppc/math-emu/single.h
+++ b/arch/powerpc/math-emu/single.h
diff --git a/arch/ppc/math-emu/soft-fp.h b/arch/powerpc/math-emu/soft-fp.h
index cca39598f87..cca39598f87 100644
--- a/arch/ppc/math-emu/soft-fp.h
+++ b/arch/powerpc/math-emu/soft-fp.h
diff --git a/arch/ppc/math-emu/stfd.c b/arch/powerpc/math-emu/stfd.c
index 3f8c2558a9e..3f8c2558a9e 100644
--- a/arch/ppc/math-emu/stfd.c
+++ b/arch/powerpc/math-emu/stfd.c
diff --git a/arch/ppc/math-emu/stfiwx.c b/arch/powerpc/math-emu/stfiwx.c
index 95caaeec6a0..95caaeec6a0 100644
--- a/arch/ppc/math-emu/stfiwx.c
+++ b/arch/powerpc/math-emu/stfiwx.c
diff --git a/arch/ppc/math-emu/stfs.c b/arch/powerpc/math-emu/stfs.c
index e87ca23c6dc..e87ca23c6dc 100644
--- a/arch/ppc/math-emu/stfs.c
+++ b/arch/powerpc/math-emu/stfs.c
diff --git a/arch/ppc/math-emu/types.c b/arch/powerpc/math-emu/types.c
index e1ed15d829d..e1ed15d829d 100644
--- a/arch/ppc/math-emu/types.c
+++ b/arch/powerpc/math-emu/types.c
diff --git a/arch/ppc/math-emu/udivmodti4.c b/arch/powerpc/math-emu/udivmodti4.c
index 7e112dc1e2f..7e112dc1e2f 100644
--- a/arch/ppc/math-emu/udivmodti4.c
+++ b/arch/powerpc/math-emu/udivmodti4.c
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index ec4adcb4bc2..fdbba4206d5 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -177,15 +177,15 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
/* When running in the kernel we expect faults to occur only to
* addresses in user space. All other faults represent errors in the
- * kernel and should generate an OOPS. Unfortunatly, in the case of an
- * erroneous fault occuring in a code path which already holds mmap_sem
+ * kernel and should generate an OOPS. Unfortunately, in the case of an
+ * erroneous fault occurring in a code path which already holds mmap_sem
* we will deadlock attempting to validate the fault against the
* address space. Luckily the kernel only validly references user
* space from well defined areas of code, which are listed in the
* exceptions table.
*
* As the vast majority of faults will be valid we will only perform
- * the source reference check when there is a possibilty of a deadlock.
+ * the source reference check when there is a possibility of a deadlock.
* Attempt to lock the address space, if we cannot we then validate the
* source. If this is invalid we can skip the address space check,
* thus avoiding the deadlock.
@@ -267,25 +267,29 @@ good_area:
#endif
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
pte_t *ptep;
+ pmd_t *pmdp;
/* Since 4xx/Book-E supports per-page execute permission,
* we lazily flush dcache to icache. */
ptep = NULL;
- if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) {
- struct page *page = pte_page(*ptep);
-
- if (! test_bit(PG_arch_1, &page->flags)) {
- flush_dcache_icache_page(page);
- set_bit(PG_arch_1, &page->flags);
+ if (get_pteptr(mm, address, &ptep, &pmdp)) {
+ spinlock_t *ptl = pte_lockptr(mm, pmdp);
+ spin_lock(ptl);
+ if (pte_present(*ptep)) {
+ struct page *page = pte_page(*ptep);
+
+ if (!test_bit(PG_arch_1, &page->flags)) {
+ flush_dcache_icache_page(page);
+ set_bit(PG_arch_1, &page->flags);
+ }
+ pte_update(ptep, 0, _PAGE_HWEXEC);
+ _tlbie(address);
+ pte_unmap_unlock(ptep, ptl);
+ up_read(&mm->mmap_sem);
+ return 0;
}
- pte_update(ptep, 0, _PAGE_HWEXEC);
- _tlbie(address);
- pte_unmap(ptep);
- up_read(&mm->mmap_sem);
- return 0;
+ pte_unmap_unlock(ptep, ptl);
}
- if (ptep != NULL)
- pte_unmap(ptep);
#endif
/* a write */
} else if (is_write) {
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 89b35c18131..c006d903963 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -167,7 +167,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
* normal insert callback here.
*/
#ifdef CONFIG_PPC_ISERIES
- if (_machine == PLATFORM_ISERIES_LPAR)
+ if (machine_is(iseries))
ret = iSeries_hpte_insert(hpteg, va,
paddr,
tmp_mode,
@@ -176,7 +176,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
else
#endif
#ifdef CONFIG_PPC_PSERIES
- if (_machine & PLATFORM_LPAR)
+ if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR))
ret = pSeries_lpar_hpte_insert(hpteg, va,
paddr,
tmp_mode,
@@ -295,8 +295,7 @@ static void __init htab_init_page_sizes(void)
* Not in the device-tree, let's fallback on known size
* list for 16M capable GP & GR
*/
- if ((_machine != PLATFORM_ISERIES_LPAR) &&
- cpu_has_feature(CPU_FTR_16M_PAGE))
+ if (cpu_has_feature(CPU_FTR_16M_PAGE) && !machine_is(iseries))
memcpy(mmu_psize_defs, mmu_psize_defaults_gp,
sizeof(mmu_psize_defaults_gp));
found:
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 7370f9f33e2..266b8b2ceac 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -30,13 +30,66 @@
#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)
#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT)
+#ifdef CONFIG_PPC_64K_PAGES
+#define HUGEPTE_INDEX_SIZE (PMD_SHIFT-HPAGE_SHIFT)
+#else
+#define HUGEPTE_INDEX_SIZE (PUD_SHIFT-HPAGE_SHIFT)
+#endif
+#define PTRS_PER_HUGEPTE (1 << HUGEPTE_INDEX_SIZE)
+#define HUGEPTE_TABLE_SIZE (sizeof(pte_t) << HUGEPTE_INDEX_SIZE)
+
+#define HUGEPD_SHIFT (HPAGE_SHIFT + HUGEPTE_INDEX_SIZE)
+#define HUGEPD_SIZE (1UL << HUGEPD_SHIFT)
+#define HUGEPD_MASK (~(HUGEPD_SIZE-1))
+
+#define huge_pgtable_cache (pgtable_cache[HUGEPTE_CACHE_NUM])
+
+/* Flag to mark huge PD pointers. This means pmd_bad() and pud_bad()
+ * will choke on pointers to hugepte tables, which is handy for
+ * catching screwups early. */
+#define HUGEPD_OK 0x1
+
+typedef struct { unsigned long pd; } hugepd_t;
+
+#define hugepd_none(hpd) ((hpd).pd == 0)
+
+static inline pte_t *hugepd_page(hugepd_t hpd)
+{
+ BUG_ON(!(hpd.pd & HUGEPD_OK));
+ return (pte_t *)(hpd.pd & ~HUGEPD_OK);
+}
+
+static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr)
+{
+ unsigned long idx = ((addr >> HPAGE_SHIFT) & (PTRS_PER_HUGEPTE-1));
+ pte_t *dir = hugepd_page(*hpdp);
+
+ return dir + idx;
+}
+
+static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
+ unsigned long address)
+{
+ pte_t *new = kmem_cache_alloc(huge_pgtable_cache,
+ GFP_KERNEL|__GFP_REPEAT);
+
+ if (! new)
+ return -ENOMEM;
+
+ spin_lock(&mm->page_table_lock);
+ if (!hugepd_none(*hpdp))
+ kmem_cache_free(huge_pgtable_cache, new);
+ else
+ hpdp->pd = (unsigned long)new | HUGEPD_OK;
+ spin_unlock(&mm->page_table_lock);
+ return 0;
+}
+
/* Modelled after find_linux_pte() */
pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pg;
pud_t *pu;
- pmd_t *pm;
- pte_t *pt;
BUG_ON(! in_hugepage_area(mm->context, addr));
@@ -46,26 +99,14 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
if (!pgd_none(*pg)) {
pu = pud_offset(pg, addr);
if (!pud_none(*pu)) {
- pm = pmd_offset(pu, addr);
#ifdef CONFIG_PPC_64K_PAGES
- /* Currently, we use the normal PTE offset within full
- * size PTE pages, thus our huge PTEs are scattered in
- * the PTE page and we do waste some. We may change
- * that in the future, but the current mecanism keeps
- * things much simpler
- */
- if (!pmd_none(*pm)) {
- /* Note: pte_offset_* are all equivalent on
- * ppc64 as we don't have HIGHMEM
- */
- pt = pte_offset_kernel(pm, addr);
- return pt;
- }
-#else /* CONFIG_PPC_64K_PAGES */
- /* On 4k pages, we put huge PTEs in the PMD page */
- pt = (pte_t *)pm;
- return pt;
-#endif /* CONFIG_PPC_64K_PAGES */
+ pmd_t *pm;
+ pm = pmd_offset(pu, addr);
+ if (!pmd_none(*pm))
+ return hugepte_offset((hugepd_t *)pm, addr);
+#else
+ return hugepte_offset((hugepd_t *)pu, addr);
+#endif
}
}
@@ -76,8 +117,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pg;
pud_t *pu;
- pmd_t *pm;
- pte_t *pt;
+ hugepd_t *hpdp = NULL;
BUG_ON(! in_hugepage_area(mm->context, addr));
@@ -87,23 +127,182 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
pu = pud_alloc(mm, pg, addr);
if (pu) {
+#ifdef CONFIG_PPC_64K_PAGES
+ pmd_t *pm;
pm = pmd_alloc(mm, pu, addr);
- if (pm) {
+ if (pm)
+ hpdp = (hugepd_t *)pm;
+#else
+ hpdp = (hugepd_t *)pu;
+#endif
+ }
+
+ if (! hpdp)
+ return NULL;
+
+ if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr))
+ return NULL;
+
+ return hugepte_offset(hpdp, addr);
+}
+
+static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp)
+{
+ pte_t *hugepte = hugepd_page(*hpdp);
+
+ hpdp->pd = 0;
+ tlb->need_flush = 1;
+ pgtable_free_tlb(tlb, pgtable_free_cache(hugepte, HUGEPTE_CACHE_NUM,
+ HUGEPTE_TABLE_SIZE-1));
+}
+
#ifdef CONFIG_PPC_64K_PAGES
- /* See comment in huge_pte_offset. Note that if we ever
- * want to put the page size in the PMD, we would have
- * to open code our own pte_alloc* function in order
- * to populate and set the size atomically
- */
- pt = pte_alloc_map(mm, pm, addr);
-#else /* CONFIG_PPC_64K_PAGES */
- pt = (pte_t *)pm;
-#endif /* CONFIG_PPC_64K_PAGES */
- return pt;
- }
+static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
+ unsigned long addr, unsigned long end,
+ unsigned long floor, unsigned long ceiling)
+{
+ pmd_t *pmd;
+ unsigned long next;
+ unsigned long start;
+
+ start = addr;
+ pmd = pmd_offset(pud, addr);
+ do {
+ next = pmd_addr_end(addr, end);
+ if (pmd_none(*pmd))
+ continue;
+ free_hugepte_range(tlb, (hugepd_t *)pmd);
+ } while (pmd++, addr = next, addr != end);
+
+ start &= PUD_MASK;
+ if (start < floor)
+ return;
+ if (ceiling) {
+ ceiling &= PUD_MASK;
+ if (!ceiling)
+ return;
}
+ if (end - 1 > ceiling - 1)
+ return;
- return NULL;
+ pmd = pmd_offset(pud, start);
+ pud_clear(pud);
+ pmd_free_tlb(tlb, pmd);
+}
+#endif
+
+static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
+ unsigned long addr, unsigned long end,
+ unsigned long floor, unsigned long ceiling)
+{
+ pud_t *pud;
+ unsigned long next;
+ unsigned long start;
+
+ start = addr;
+ pud = pud_offset(pgd, addr);
+ do {
+ next = pud_addr_end(addr, end);
+#ifdef CONFIG_PPC_64K_PAGES
+ if (pud_none_or_clear_bad(pud))
+ continue;
+ hugetlb_free_pmd_range(tlb, pud, addr, next, floor, ceiling);
+#else
+ if (pud_none(*pud))
+ continue;
+ free_hugepte_range(tlb, (hugepd_t *)pud);
+#endif
+ } while (pud++, addr = next, addr != end);
+
+ start &= PGDIR_MASK;
+ if (start < floor)
+ return;
+ if (ceiling) {
+ ceiling &= PGDIR_MASK;
+ if (!ceiling)
+ return;
+ }
+ if (end - 1 > ceiling - 1)
+ return;
+
+ pud = pud_offset(pgd, start);
+ pgd_clear(pgd);
+ pud_free_tlb(tlb, pud);
+}
+
+/*
+ * This function frees user-level page tables of a process.
+ *
+ * Must be called with pagetable lock held.
+ */
+void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+ unsigned long addr, unsigned long end,
+ unsigned long floor, unsigned long ceiling)
+{
+ pgd_t *pgd;
+ unsigned long next;
+ unsigned long start;
+
+ /*
+ * Comments below take from the normal free_pgd_range(). They
+ * apply here too. The tests against HUGEPD_MASK below are
+ * essential, because we *don't* test for this at the bottom
+ * level. Without them we'll attempt to free a hugepte table
+ * when we unmap just part of it, even if there are other
+ * active mappings using it.
+ *
+ * The next few lines have given us lots of grief...
+ *
+ * Why are we testing HUGEPD* at this top level? Because
+ * often there will be no work to do at all, and we'd prefer
+ * not to go all the way down to the bottom just to discover
+ * that.
+ *
+ * Why all these "- 1"s? Because 0 represents both the bottom
+ * of the address space and the top of it (using -1 for the
+ * top wouldn't help much: the masks would do the wrong thing).
+ * The rule is that addr 0 and floor 0 refer to the bottom of
+ * the address space, but end 0 and ceiling 0 refer to the top
+ * Comparisons need to use "end - 1" and "ceiling - 1" (though
+ * that end 0 case should be mythical).
+ *
+ * Wherever addr is brought up or ceiling brought down, we
+ * must be careful to reject "the opposite 0" before it
+ * confuses the subsequent tests. But what about where end is
+ * brought down by HUGEPD_SIZE below? no, end can't go down to
+ * 0 there.
+ *
+ * Whereas we round start (addr) and ceiling down, by different
+ * masks at different levels, in order to test whether a table
+ * now has no other vmas using it, so can be freed, we don't
+ * bother to round floor or end up - the tests don't need that.
+ */
+
+ addr &= HUGEPD_MASK;
+ if (addr < floor) {
+ addr += HUGEPD_SIZE;
+ if (!addr)
+ return;
+ }
+ if (ceiling) {
+ ceiling &= HUGEPD_MASK;
+ if (!ceiling)
+ return;
+ }
+ if (end - 1 > ceiling - 1)
+ end -= HUGEPD_SIZE;
+ if (addr > end - 1)
+ return;
+
+ start = addr;
+ pgd = pgd_offset((*tlb)->mm, addr);
+ do {
+ BUG_ON(! in_hugepage_area((*tlb)->mm->context, addr));
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ hugetlb_free_pud_range(*tlb, pgd, addr, next, floor, ceiling);
+ } while (pgd++, addr = next, addr != end);
}
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
@@ -841,3 +1040,27 @@ repeat:
out:
return err;
}
+
+static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
+{
+ memset(addr, 0, kmem_cache_size(cache));
+}
+
+static int __init hugetlbpage_init(void)
+{
+ if (!cpu_has_feature(CPU_FTR_16M_PAGE))
+ return -ENODEV;
+
+ huge_pgtable_cache = kmem_cache_create("hugepte_cache",
+ HUGEPTE_TABLE_SIZE,
+ HUGEPTE_TABLE_SIZE,
+ SLAB_HWCACHE_ALIGN |
+ SLAB_MUST_HWCACHE_ALIGN,
+ zero_ctor, NULL);
+ if (! huge_pgtable_cache)
+ panic("hugetlbpage_init(): could not create hugepte cache\n");
+
+ return 0;
+}
+
+module_init(hugetlbpage_init);
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index babebd15bdc..9e30f968c18 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -162,7 +162,14 @@ static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
};
#endif /* CONFIG_PPC_64K_PAGES */
+#ifdef CONFIG_HUGETLB_PAGE
+/* Hugepages need one extra cache, initialized in hugetlbpage.c. We
+ * can't put into the tables above, because HPAGE_SHIFT is not compile
+ * time constant. */
+kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+1];
+#else
kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
+#endif
void pgtable_cache_init(void)
{
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index badac10d700..741dd8802d4 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -195,7 +195,7 @@ void show_mem(void)
printk("Mem-info:\n");
show_free_areas();
printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
unsigned long flags;
pgdat_resize_lock(pgdat, &flags);
for (i = 0; i < pgdat->node_spanned_pages; i++) {
@@ -342,7 +342,7 @@ void __init mem_init(void)
#ifdef CONFIG_NEED_MULTIPLE_NODES
for_each_online_node(nid) {
if (NODE_DATA(nid)->node_spanned_pages != 0) {
- printk("freeing bootmem node %x\n", nid);
+ printk("freeing bootmem node %d\n", nid);
totalram_pages +=
free_all_bootmem_node(NODE_DATA(nid));
}
@@ -351,7 +351,7 @@ void __init mem_init(void)
max_mapnr = max_pfn;
totalram_pages += free_all_bootmem();
#endif
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
for (i = 0; i < pgdat->node_spanned_pages; i++) {
if (!pfn_valid(pgdat->node_start_pfn + i))
continue;
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index e89b22aa539..092355f3739 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -194,7 +194,7 @@ static int *of_get_associativity(struct device_node *dev)
/* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa
* info is found.
*/
-static int of_node_to_nid(struct device_node *device)
+static int of_node_to_nid_single(struct device_node *device)
{
int nid = -1;
unsigned int *tmp;
@@ -216,6 +216,28 @@ out:
return nid;
}
+/* Walk the device tree upwards, looking for an associativity id */
+int of_node_to_nid(struct device_node *device)
+{
+ struct device_node *tmp;
+ int nid = -1;
+
+ of_node_get(device);
+ while (device) {
+ nid = of_node_to_nid_single(device);
+ if (nid != -1)
+ break;
+
+ tmp = device;
+ device = of_get_parent(tmp);
+ of_node_put(tmp);
+ }
+ of_node_put(device);
+
+ return nid;
+}
+EXPORT_SYMBOL_GPL(of_node_to_nid);
+
/*
* In theory, the "ibm,associativity" property may contain multiple
* associativity lists because a resource may be multiply connected
@@ -300,7 +322,7 @@ static int __cpuinit numa_setup_cpu(unsigned long lcpu)
goto out;
}
- nid = of_node_to_nid(cpu);
+ nid = of_node_to_nid_single(cpu);
if (nid < 0 || !node_online(nid))
nid = any_online_node(NODE_MASK_ALL);
@@ -393,7 +415,7 @@ static int __init parse_numa_properties(void)
cpu = find_cpu_node(i);
BUG_ON(!cpu);
- nid = of_node_to_nid(cpu);
+ nid = of_node_to_nid_single(cpu);
of_node_put(cpu);
/*
@@ -437,7 +459,7 @@ new_range:
* have associativity properties. If none, then
* everything goes to default_nid.
*/
- nid = of_node_to_nid(memory);
+ nid = of_node_to_nid_single(memory);
if (nid < 0)
nid = default_nid;
node_set_online(nid);
@@ -756,6 +778,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
struct device_node *memory = NULL;
nodemask_t nodes;
int default_nid = any_online_node(NODE_MASK_ALL);
+ int nid;
if (!numa_enabled || (min_common_depth < 0))
return default_nid;
@@ -775,7 +798,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
ha_new_range:
start = read_n_cells(n_mem_addr_cells, &memcell_buf);
size = read_n_cells(n_mem_size_cells, &memcell_buf);
- nid = of_node_to_nid(memory);
+ nid = of_node_to_nid_single(memory);
/* Domains not present at boot default to 0 */
if (nid < 0 || !node_online(nid))
@@ -790,6 +813,7 @@ ha_new_range:
goto ha_new_range;
}
BUG(); /* section address should be found above */
+ return 0;
/* Temporary code to ensure that returned node is not empty */
got_nid:
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index d296eb6b454..90628601fac 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -372,7 +372,7 @@ void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
* the PTE pointer is unmodified if PTE is not found.
*/
int
-get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
+get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
{
pgd_t *pgd;
pmd_t *pmd;
@@ -387,6 +387,8 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
if (pte) {
retval = 1;
*ptep = pte;
+ if (pmdp)
+ *pmdp = pmd;
/* XXX caller needs to do pte_unmap, yuck */
}
}
@@ -424,7 +426,7 @@ unsigned long iopa(unsigned long addr)
mm = &init_mm;
pa = 0;
- if (get_pteptr(mm, addr, &pte)) {
+ if (get_pteptr(mm, addr, &pte, NULL)) {
pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
pte_unmap(pte);
}
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 91d25fb27f8..4a9291d9fef 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -239,7 +239,7 @@ void stabs_alloc(void)
if (cpu_has_feature(CPU_FTR_SLB))
return;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
unsigned long newstab;
if (cpu == 0)
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index 554cd7c7532..f5f9859a833 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -6,7 +6,7 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
oprofilefs.o oprofile_stats.o \
timer_int.o )
-oprofile-y := $(DRIVER_OBJS) common.o
+oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o
oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
oprofile-$(CONFIG_PPC32) += op_model_7450.o
diff --git a/arch/powerpc/oprofile/backtrace.c b/arch/powerpc/oprofile/backtrace.c
new file mode 100644
index 00000000000..75f57bc96b4
--- /dev/null
+++ b/arch/powerpc/oprofile/backtrace.c
@@ -0,0 +1,126 @@
+/**
+ * Copyright (C) 2005 Brian Rogan <bcr6@cornell.edu>, IBM
+ *
+ * This program is free software; 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/oprofile.h>
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#define STACK_SP(STACK) *(STACK)
+
+#define STACK_LR64(STACK) *((unsigned long *)(STACK) + 2)
+#define STACK_LR32(STACK) *((unsigned int *)(STACK) + 1)
+
+#ifdef CONFIG_PPC64
+#define STACK_LR(STACK) STACK_LR64(STACK)
+#else
+#define STACK_LR(STACK) STACK_LR32(STACK)
+#endif
+
+static unsigned int user_getsp32(unsigned int sp, int is_first)
+{
+ unsigned int stack_frame[2];
+
+ if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame)))
+ return 0;
+
+ /*
+ * The most likely reason for this is that we returned -EFAULT,
+ * which means that we've done all that we can do from
+ * interrupt context.
+ */
+ if (__copy_from_user_inatomic(stack_frame, (void *)(long)sp,
+ sizeof(stack_frame)))
+ return 0;
+
+ if (!is_first)
+ oprofile_add_trace(STACK_LR32(stack_frame));
+
+ /*
+ * We do not enforce increasing stack addresses here because
+ * we may transition to a different stack, eg a signal handler.
+ */
+ return STACK_SP(stack_frame);
+}
+
+#ifdef CONFIG_PPC64
+static unsigned long user_getsp64(unsigned long sp, int is_first)
+{
+ unsigned long stack_frame[3];
+
+ if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame)))
+ return 0;
+
+ if (__copy_from_user_inatomic(stack_frame, (void *)sp,
+ sizeof(stack_frame)))
+ return 0;
+
+ if (!is_first)
+ oprofile_add_trace(STACK_LR64(stack_frame));
+
+ return STACK_SP(stack_frame);
+}
+#endif
+
+static unsigned long kernel_getsp(unsigned long sp, int is_first)
+{
+ unsigned long *stack_frame = (unsigned long *)sp;
+
+ if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
+ return 0;
+
+ if (!is_first)
+ oprofile_add_trace(STACK_LR(stack_frame));
+
+ /*
+ * We do not enforce increasing stack addresses here because
+ * we might be transitioning from an interrupt stack to a kernel
+ * stack. validate_sp() is designed to understand this, so just
+ * use it.
+ */
+ return STACK_SP(stack_frame);
+}
+
+void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth)
+{
+ unsigned long sp = regs->gpr[1];
+ int first_frame = 1;
+
+ /* We ditch the top stackframe so need to loop through an extra time */
+ depth += 1;
+
+ if (!user_mode(regs)) {
+ while (depth--) {
+ sp = kernel_getsp(sp, first_frame);
+ if (!sp)
+ break;
+ first_frame = 0;
+ }
+ } else {
+#ifdef CONFIG_PPC64
+ if (!test_thread_flag(TIF_32BIT)) {
+ while (depth--) {
+ sp = user_getsp64(sp, first_frame);
+ if (!sp)
+ break;
+ first_frame = 0;
+ }
+
+ return;
+ }
+#endif
+
+ while (depth--) {
+ sp = user_getsp32(sp, first_frame);
+ if (!sp)
+ break;
+ first_frame = 0;
+ }
+ }
+}
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index cc2535be3a7..5b1de7e8041 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -117,18 +117,10 @@ static int op_powerpc_create_files(struct super_block *sb, struct dentry *root)
oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
-#ifdef CONFIG_PPC64
- oprofilefs_create_ulong(sb, root, "backtrace_spinlocks",
- &sys.backtrace_spinlocks);
-#endif
/* Default to tracing both kernel and user */
sys.enable_kernel = 1;
sys.enable_user = 1;
-#ifdef CONFIG_PPC64
- /* Turn on backtracing through spinlocks by default */
- sys.backtrace_spinlocks = 1;
-#endif
return 0;
}
@@ -168,6 +160,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
ops->shutdown = op_powerpc_shutdown;
ops->start = op_powerpc_start;
ops->stop = op_powerpc_stop;
+ ops->backtrace = op_powerpc_backtrace;
printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
ops->cpu_type);
diff --git a/arch/powerpc/oprofile/op_model_7450.c b/arch/powerpc/oprofile/op_model_7450.c
index 32abfdbb0eb..e0491c3c71f 100644
--- a/arch/powerpc/oprofile/op_model_7450.c
+++ b/arch/powerpc/oprofile/op_model_7450.c
@@ -176,13 +176,13 @@ static void fsl7450_handle_interrupt(struct pt_regs *regs,
mtmsr(mfmsr() | MSR_PMM);
pc = mfspr(SPRN_SIAR);
- is_kernel = (pc >= KERNELBASE);
+ is_kernel = is_kernel_addr(pc);
for (i = 0; i < NUM_CTRS; ++i) {
val = ctr_read(i);
if (val < 0) {
if (oprofile_running && ctr[i].enabled) {
- oprofile_add_pc(pc, is_kernel, i);
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c
index 26539cda602..93d63e62662 100644
--- a/arch/powerpc/oprofile/op_model_fsl_booke.c
+++ b/arch/powerpc/oprofile/op_model_fsl_booke.c
@@ -154,13 +154,13 @@ static void fsl_booke_handle_interrupt(struct pt_regs *regs,
mtmsr(mfmsr() | MSR_PMM);
pc = regs->nip;
- is_kernel = (pc >= KERNELBASE);
+ is_kernel = is_kernel_addr(pc);
for (i = 0; i < num_counters; ++i) {
val = ctr_read(i);
if (val < 0) {
if (oprofile_running && ctr[i].enabled) {
- oprofile_add_pc(pc, is_kernel, i);
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index 4b06e53eb9b..4c2beab1fdc 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -25,18 +25,14 @@ static unsigned long reset_value[OP_MAX_COUNTER];
static int oprofile_running;
static int mmcra_has_sihv;
+/* Unfortunately these bits vary between CPUs */
+static unsigned long mmcra_sihv = MMCRA_SIHV;
+static unsigned long mmcra_sipr = MMCRA_SIPR;
/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
static u32 mmcr0_val;
static u64 mmcr1_val;
-static u32 mmcra_val;
-
-/*
- * Since we do not have an NMI, backtracing through spinlocks is
- * only a best guess. In light of this, allow it to be disabled at
- * runtime.
- */
-static int backtrace_spinlocks;
+static u64 mmcra_val;
static void power4_reg_setup(struct op_counter_config *ctr,
struct op_system_config *sys,
@@ -63,8 +59,6 @@ static void power4_reg_setup(struct op_counter_config *ctr,
mmcr1_val = sys->mmcr1;
mmcra_val = sys->mmcra;
- backtrace_spinlocks = sys->backtrace_spinlocks;
-
for (i = 0; i < cur_cpu_spec->num_pmcs; ++i)
reset_value[i] = 0x80000000UL - ctr[i].count;
@@ -197,25 +191,6 @@ static void __attribute_used__ kernel_unknown_bucket(void)
{
}
-static unsigned long check_spinlock_pc(struct pt_regs *regs,
- unsigned long profile_pc)
-{
- unsigned long pc = instruction_pointer(regs);
-
- /*
- * If both the SIAR (sampled instruction) and the perfmon exception
- * occurred in a spinlock region then we account the sample to the
- * calling function. This isnt 100% correct, we really need soft
- * IRQ disable so we always get the perfmon exception at the
- * point at which the SIAR is set.
- */
- if (backtrace_spinlocks && in_lock_functions(pc) &&
- in_lock_functions(profile_pc))
- return regs->link;
- else
- return profile_pc;
-}
-
/*
* 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
@@ -228,17 +203,17 @@ static unsigned long get_pc(struct pt_regs *regs)
/* Cant do much about it */
if (!mmcra_has_sihv)
- return check_spinlock_pc(regs, pc);
+ return pc;
mmcra = mfspr(SPRN_MMCRA);
/* Were we in the hypervisor? */
- if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & MMCRA_SIHV))
+ if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv))
/* function descriptor madness */
return *((unsigned long *)hypervisor_bucket);
/* We were in userspace, nothing to do */
- if (mmcra & MMCRA_SIPR)
+ if (mmcra & mmcra_sipr)
return pc;
#ifdef CONFIG_PPC_RTAS
@@ -257,7 +232,7 @@ static unsigned long get_pc(struct pt_regs *regs)
/* function descriptor madness */
return *((unsigned long *)kernel_unknown_bucket);
- return check_spinlock_pc(regs, pc);
+ return pc;
}
static int get_kernel(unsigned long pc)
@@ -268,7 +243,7 @@ static int get_kernel(unsigned long pc)
is_kernel = is_kernel_addr(pc);
} else {
unsigned long mmcra = mfspr(SPRN_MMCRA);
- is_kernel = ((mmcra & MMCRA_SIPR) == 0);
+ is_kernel = ((mmcra & mmcra_sipr) == 0);
}
return is_kernel;
@@ -293,7 +268,7 @@ static void power4_handle_interrupt(struct pt_regs *regs,
val = ctr_read(i);
if (val < 0) {
if (oprofile_running && ctr[i].enabled) {
- oprofile_add_pc(pc, is_kernel, i);
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
diff --git a/arch/powerpc/oprofile/op_model_rs64.c b/arch/powerpc/oprofile/op_model_rs64.c
index 5c909ee609f..042f8f4867a 100644
--- a/arch/powerpc/oprofile/op_model_rs64.c
+++ b/arch/powerpc/oprofile/op_model_rs64.c
@@ -175,10 +175,13 @@ static void rs64_handle_interrupt(struct pt_regs *regs,
struct op_counter_config *ctr)
{
unsigned int mmcr0;
+ int is_kernel;
int val;
int i;
unsigned long pc = mfspr(SPRN_SIAR);
+ is_kernel = is_kernel_addr(pc);
+
/* set the PMM bit (see comment below) */
mtmsrd(mfmsr() | MSR_PMM);
@@ -186,7 +189,7 @@ static void rs64_handle_interrupt(struct pt_regs *regs,
val = ctr_read(i);
if (val < 0) {
if (ctr[i].enabled) {
- oprofile_add_pc(pc, is_kernel_addr(pc), i);
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c
index 7c18b4cd5db..7e789d2420b 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_sys.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c
@@ -158,25 +158,25 @@ static int __init mpc834x_rtc_hookup(void)
late_initcall(mpc834x_rtc_hookup);
#endif
-void __init platform_init(void)
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc834x_sys_probe(void)
{
- /* setup the PowerPC module struct */
- ppc_md.setup_arch = mpc834x_sys_setup_arch;
-
- ppc_md.init_IRQ = mpc834x_sys_init_IRQ;
- ppc_md.get_irq = ipic_get_irq;
-
- ppc_md.restart = mpc83xx_restart;
-
- ppc_md.time_init = mpc83xx_time_init;
- ppc_md.set_rtc_time = NULL;
- ppc_md.get_rtc_time = NULL;
- ppc_md.calibrate_decr = generic_calibrate_decr;
-
- ppc_md.progress = udbg_progress;
-
- if (ppc_md.progress)
- ppc_md.progress("mpc834x_sys_init(): exit", 0);
-
- return;
+ /* We always match for now, eventually we should look at the flat
+ dev tree to ensure this is the board we are suppose to run on
+ */
+ return 1;
}
+
+define_machine(mpc834x_sys) {
+ .name = "MPC834x SYS",
+ .probe = mpc834x_sys_probe,
+ .setup_arch = mpc834x_sys_setup_arch,
+ .init_IRQ = mpc834x_sys_init_IRQ,
+ .get_irq = ipic_get_irq,
+ .restart = mpc83xx_restart,
+ .time_init = mpc83xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index d3d0ff745e8..06e371282f5 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -7,6 +7,7 @@ choice
config MPC8540_ADS
bool "Freescale MPC8540 ADS"
+ select DEFAULT_UIMAGE
help
This option enables support for the MPC 8540 ADS board
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index b7821dbae00..5eeff370f5f 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -220,25 +220,25 @@ void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
}
-void __init platform_init(void)
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc85xx_ads_probe(void)
{
- ppc_md.setup_arch = mpc85xx_ads_setup_arch;
- ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo;
-
- ppc_md.init_IRQ = mpc85xx_ads_pic_init;
- ppc_md.get_irq = mpic_get_irq;
-
- ppc_md.restart = mpc85xx_restart;
- ppc_md.power_off = NULL;
- ppc_md.halt = NULL;
-
- ppc_md.time_init = NULL;
- ppc_md.set_rtc_time = NULL;
- ppc_md.get_rtc_time = NULL;
- ppc_md.calibrate_decr = generic_calibrate_decr;
-
- ppc_md.progress = udbg_progress;
-
- if (ppc_md.progress)
- ppc_md.progress("mpc85xx_ads platform_init(): exit", 0);
+ /* We always match for now, eventually we should look at the flat
+ dev tree to ensure this is the board we are suppose to run on
+ */
+ return 1;
}
+
+define_machine(mpc85xx_ads) {
+ .name = "MPC85xx ADS",
+ .probe = mpc85xx_ads_probe,
+ .setup_arch = mpc85xx_ads_setup_arch,
+ .init_IRQ = mpc85xx_ads_pic_init,
+ .show_cpuinfo = mpc85xx_ads_show_cpuinfo,
+ .get_irq = mpic_get_irq,
+ .restart = mpc85xx_restart,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 3157071e241..6a02d51086c 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -10,4 +10,10 @@ config SPU_FS
Units on machines implementing the Broadband Processor
Architecture.
+config SPUFS_MMAP
+ bool
+ depends on SPU_FS && SPARSEMEM
+ select MEMORY_HOTPLUG
+ default y
+
endmenu
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 3b998a393e3..e570bad0639 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -6,5 +6,11 @@ obj-$(CONFIG_SPU_FS) += spu-base.o spufs/
spu-base-y += spu_base.o spu_priv1.o
-builtin-spufs-$(CONFIG_SPU_FS) += spu_syscalls.o
-obj-y += $(builtin-spufs-m)
+# needed only when building loadable spufs.ko
+spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o
+obj-y += $(spufs-modular-m)
+
+# always needed in kernel
+spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o
+obj-y += $(spufs-builtin-y) $(spufs-builtin-m)
+
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 63aa52acf44..978be1c30c1 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -63,7 +63,24 @@ static DEFINE_PER_CPU(struct iic, iic);
void iic_local_enable(void)
{
- out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
+ struct iic *iic = &__get_cpu_var(iic);
+ u64 tmp;
+
+ /*
+ * There seems to be a bug that is present in DD2.x CPUs
+ * and still only partially fixed in DD3.1.
+ * This bug causes a value written to the priority register
+ * not to make it there, resulting in a system hang unless we
+ * write it again.
+ * Masking with 0xf0 is done because the Cell BE does not
+ * implement the lower four bits of the interrupt priority,
+ * they always read back as zeroes, although future CPUs
+ * might implement different bits.
+ */
+ do {
+ out_be64(&iic->regs->prio, 0xff);
+ tmp = in_be64(&iic->regs->prio);
+ } while ((tmp & 0xf0) != 0xf0);
}
void iic_local_disable(void)
@@ -123,7 +140,7 @@ static int iic_external_get_irq(struct iic_pending_bits pending)
pending.class != 2)
break;
irq = IIC_EXT_OFFSET
- + spider_get_irq(pending.prio + node * IIC_NODE_STRIDE)
+ + spider_get_irq(node)
+ node * IIC_NODE_STRIDE;
break;
case 0x01 ... 0x04:
@@ -174,38 +191,98 @@ int iic_get_irq(struct pt_regs *regs)
return irq;
}
-static int setup_iic(int cpu, struct iic *iic)
+/* hardcoded part to be compatible with older firmware */
+
+static int setup_iic_hardcoded(void)
{
struct device_node *np;
- int nodeid = cpu / 2;
+ int nodeid, cpu;
unsigned long regs;
+ struct iic *iic;
- for (np = of_find_node_by_type(NULL, "cpu");
- np;
- np = of_find_node_by_type(np, "cpu")) {
- if (nodeid == *(int *)get_property(np, "node-id", NULL))
- break;
+ for_each_cpu(cpu) {
+ iic = &per_cpu(iic, cpu);
+ nodeid = cpu/2;
+
+ for (np = of_find_node_by_type(NULL, "cpu");
+ np;
+ np = of_find_node_by_type(np, "cpu")) {
+ if (nodeid == *(int *)get_property(np, "node-id", NULL))
+ break;
+ }
+
+ if (!np) {
+ printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
+ iic->regs = NULL;
+ iic->target_id = 0xff;
+ return -ENODEV;
+ }
+
+ regs = *(long *)get_property(np, "iic", NULL);
+
+ /* hack until we have decided on the devtree info */
+ regs += 0x400;
+ if (cpu & 1)
+ regs += 0x20;
+
+ printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs);
+ iic->regs = ioremap(regs, sizeof(struct iic_regs));
+ iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
}
- if (!np) {
- printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
- iic->regs = NULL;
- iic->target_id = 0xff;
- return -ENODEV;
- }
+ return 0;
+}
- regs = *(long *)get_property(np, "iic", NULL);
+static int setup_iic(void)
+{
+ struct device_node *dn;
+ unsigned long *regs;
+ char *compatible;
+ unsigned *np, found = 0;
+ struct iic *iic = NULL;
+
+ for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
+ compatible = (char *)get_property(dn, "compatible", NULL);
+
+ if (!compatible) {
+ printk(KERN_WARNING "no compatible property found !\n");
+ continue;
+ }
- /* hack until we have decided on the devtree info */
- regs += 0x400;
- if (cpu & 1)
- regs += 0x20;
+ if (strstr(compatible, "IBM,CBEA-Internal-Interrupt-Controller"))
+ regs = (unsigned long *)get_property(dn,"reg", NULL);
+ else
+ continue;
- printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs);
- iic->regs = __ioremap(regs, sizeof(struct iic_regs),
- _PAGE_NO_CACHE);
- iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
- return 0;
+ if (!regs)
+ printk(KERN_WARNING "IIC: no reg property\n");
+
+ np = (unsigned int *)get_property(dn, "ibm,interrupt-server-ranges", NULL);
+
+ if (!np) {
+ printk(KERN_WARNING "IIC: CPU association not found\n");
+ iic->regs = NULL;
+ iic->target_id = 0xff;
+ return -ENODEV;
+ }
+
+ iic = &per_cpu(iic, np[0]);
+ iic->regs = ioremap(regs[0], sizeof(struct iic_regs));
+ iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe);
+ printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs);
+
+ iic = &per_cpu(iic, np[1]);
+ iic->regs = ioremap(regs[2], sizeof(struct iic_regs));
+ iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe);
+ printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs);
+
+ found++;
+ }
+
+ if (found)
+ return 0;
+ else
+ return -ENODEV;
}
#ifdef CONFIG_SMP
@@ -283,10 +360,12 @@ void iic_init_IRQ(void)
int cpu, irq_offset;
struct iic *iic;
+ if (setup_iic() < 0)
+ setup_iic_hardcoded();
+
irq_offset = 0;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
iic = &per_cpu(iic, cpu);
- setup_iic(cpu, iic);
if (iic->regs)
out_be64(&iic->regs->prio, 0xff);
}
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h
index a14bd38791c..799f77d98f9 100644
--- a/arch/powerpc/platforms/cell/interrupt.h
+++ b/arch/powerpc/platforms/cell/interrupt.h
@@ -57,7 +57,7 @@ extern void iic_local_disable(void);
extern u8 iic_get_target_id(int cpu);
extern void spider_init_IRQ(void);
-extern int spider_get_irq(unsigned long int_pending);
+extern int spider_get_irq(int node);
#endif
#endif /* ASM_CELL_PIC_H */
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 46e7cb9c3e6..a49ceb799a8 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -289,7 +289,7 @@ static void cell_do_map_iommu(struct cell_iommu *iommu,
ioc_base = iommu->mapped_base;
ioc_mmio_base = iommu->mapped_mmio_base;
- for (real_address = 0, io_address = 0;
+ for (real_address = 0, io_address = map_start;
io_address <= map_start + map_size;
real_address += io_page_size, io_address += io_page_size) {
ioste = get_iost_entry(fake_iopt, io_address, io_page_size);
@@ -302,7 +302,7 @@ static void cell_do_map_iommu(struct cell_iommu *iommu,
set_iopt_cache(ioc_mmio_base,
get_ioc_hash_1way(ioste, io_address),
get_ioc_tag(ioste, io_address),
- get_iopt_entry(real_address-map_start, ioid, IOPT_PROT_RW));
+ get_iopt_entry(real_address, ioid, IOPT_PROT_RW));
}
}
@@ -344,8 +344,8 @@ static int cell_map_iommu_hardcoded(int num_nodes)
/* node 0 */
iommu = &cell_iommus[0];
- iommu->mapped_base = __ioremap(0x20000511000, 0x1000, _PAGE_NO_CACHE);
- iommu->mapped_mmio_base = __ioremap(0x20000510000, 0x1000, _PAGE_NO_CACHE);
+ iommu->mapped_base = ioremap(0x20000511000, 0x1000);
+ iommu->mapped_mmio_base = ioremap(0x20000510000, 0x1000);
enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
@@ -357,8 +357,8 @@ static int cell_map_iommu_hardcoded(int num_nodes)
/* node 1 */
iommu = &cell_iommus[1];
- iommu->mapped_base = __ioremap(0x30000511000, 0x1000, _PAGE_NO_CACHE);
- iommu->mapped_mmio_base = __ioremap(0x30000510000, 0x1000, _PAGE_NO_CACHE);
+ iommu->mapped_base = ioremap(0x30000511000, 0x1000);
+ iommu->mapped_mmio_base = ioremap(0x30000510000, 0x1000);
enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
@@ -407,8 +407,8 @@ static int cell_map_iommu(void)
iommu->base = *base;
iommu->mmio_base = *mmio_base;
- iommu->mapped_base = __ioremap(*base, 0x1000, _PAGE_NO_CACHE);
- iommu->mapped_mmio_base = __ioremap(*mmio_base, 0x1000, _PAGE_NO_CACHE);
+ iommu->mapped_base = ioremap(*base, 0x1000);
+ iommu->mapped_mmio_base = ioremap(*mmio_base, 0x1000);
enable_mapping(iommu->mapped_base,
iommu->mapped_mmio_base);
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index e0e051c675d..7eed8c62451 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -203,7 +203,7 @@ found:
pr_debug("pervasive area for CPU %d at %lx, size %x\n",
cpu, real_address, size);
- p->regs = __ioremap(real_address, size, _PAGE_NO_CACHE);
+ p->regs = ioremap(real_address, size);
p->thread = thread;
return 0;
}
@@ -217,7 +217,7 @@ void __init cell_pervasive_init(void)
if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
return;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
p = &cbe_pervasive[cpu];
ret = cbe_find_pmd_mmio(cpu, p);
if (ret)
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index fec8e65b36e..fd3e5609e3e 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -29,6 +29,8 @@
#include <linux/seq_file.h>
#include <linux/root_dev.h>
#include <linux/console.h>
+#include <linux/mutex.h>
+#include <linux/memory_hotplug.h>
#include <asm/mmu.h>
#include <asm/processor.h>
@@ -46,6 +48,7 @@
#include <asm/cputable.h>
#include <asm/ppc-pci.h>
#include <asm/irq.h>
+#include <asm/spu.h>
#include "interrupt.h"
#include "iommu.h"
@@ -69,77 +72,6 @@ static void cell_show_cpuinfo(struct seq_file *m)
of_node_put(root);
}
-#ifdef CONFIG_SPARSEMEM
-static int __init find_spu_node_id(struct device_node *spe)
-{
- unsigned int *id;
-#ifdef CONFIG_NUMA
- struct device_node *cpu;
- cpu = spe->parent->parent;
- id = (unsigned int *)get_property(cpu, "node-id", NULL);
-#else
- id = NULL;
-#endif
- return id ? *id : 0;
-}
-
-static void __init cell_spuprop_present(struct device_node *spe,
- const char *prop, int early)
-{
- struct address_prop {
- unsigned long address;
- unsigned int len;
- } __attribute__((packed)) *p;
- int proplen;
-
- unsigned long start_pfn, end_pfn, pfn;
- int node_id;
-
- p = (void*)get_property(spe, prop, &proplen);
- WARN_ON(proplen != sizeof (*p));
-
- node_id = find_spu_node_id(spe);
-
- start_pfn = p->address >> PAGE_SHIFT;
- end_pfn = (p->address + p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
- /* We need to call memory_present *before* the call to sparse_init,
- but we can initialize the page structs only *after* that call.
- Thus, we're being called twice. */
- if (early)
- memory_present(node_id, start_pfn, end_pfn);
- else {
- /* As the pages backing SPU LS and I/O are outside the range
- of regular memory, their page structs were not initialized
- by free_area_init. Do it here instead. */
- for (pfn = start_pfn; pfn < end_pfn; pfn++) {
- struct page *page = pfn_to_page(pfn);
- set_page_links(page, ZONE_DMA, node_id, pfn);
- init_page_count(page);
- reset_page_mapcount(page);
- SetPageReserved(page);
- INIT_LIST_HEAD(&page->lru);
- }
- }
-}
-
-static void __init cell_spumem_init(int early)
-{
- struct device_node *node;
- for (node = of_find_node_by_type(NULL, "spe");
- node; node = of_find_node_by_type(node, "spe")) {
- cell_spuprop_present(node, "local-store", early);
- cell_spuprop_present(node, "problem", early);
- cell_spuprop_present(node, "priv1", early);
- cell_spuprop_present(node, "priv2", early);
- }
-}
-#else
-static void __init cell_spumem_init(int early)
-{
-}
-#endif
-
static void cell_progress(char *s, unsigned short hex)
{
printk("*** %04x : %s\n", hex, s ? s : "");
@@ -172,8 +104,6 @@ static void __init cell_setup_arch(void)
#endif
mmio_nvram_init();
-
- cell_spumem_init(0);
}
/*
@@ -189,18 +119,19 @@ static void __init cell_init_early(void)
ppc64_interrupt_controller = IC_CELL_PIC;
- cell_spumem_init(1);
-
DBG(" <- cell_init_early()\n");
}
-static int __init cell_probe(int platform)
+static int __init cell_probe(void)
{
- if (platform != PLATFORM_CELL)
- return 0;
+ unsigned long root = of_get_flat_dt_root();
+
+ if (of_flat_dt_is_compatible(root, "IBM,CBEA") ||
+ of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
+ return 1;
- return 1;
+ return 0;
}
/*
@@ -212,7 +143,8 @@ static int cell_check_legacy_ioport(unsigned int baseport)
return -ENODEV;
}
-struct machdep_calls __initdata cell_md = {
+define_machine(cell) {
+ .name = "Cell",
.probe = cell_probe,
.setup_arch = cell_setup_arch,
.init_early = cell_init_early,
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index e74132188bd..55cbdd77a62 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -84,10 +84,11 @@ static void __iomem *spider_get_irq_config(int irq)
static void spider_enable_irq(unsigned int irq)
{
+ int nodeid = (irq / IIC_NODE_STRIDE) * 0x10;
void __iomem *cfg = spider_get_irq_config(irq);
irq = spider_get_nr(irq);
- out_be32(cfg, in_be32(cfg) | 0x3107000eu);
+ out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid);
out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq);
}
@@ -131,61 +132,108 @@ static struct hw_interrupt_type spider_pic = {
.end = spider_end_irq,
};
-
-int spider_get_irq(unsigned long int_pending)
+int spider_get_irq(int node)
{
- void __iomem *regs = spider_get_pic(int_pending);
unsigned long cs;
- int irq;
-
- cs = in_be32(regs + TIR_CS);
+ void __iomem *regs = spider_pics[node];
- irq = cs >> 24;
- if (irq != 63)
- return irq;
+ cs = in_be32(regs + TIR_CS) >> 24;
- return -1;
+ if (cs == 63)
+ return -1;
+ else
+ return cs;
}
-
-void spider_init_IRQ(void)
+
+/* hardcoded part to be compatible with older firmware */
+
+void spider_init_IRQ_hardcoded(void)
{
int node;
- struct device_node *dn;
- unsigned int *property;
long spiderpic;
+ long pics[] = { 0x24000008000, 0x34000008000 };
int n;
-/* FIXME: detect multiple PICs as soon as the device tree has them */
- for (node = 0; node < 1; node++) {
- dn = of_find_node_by_path("/");
- n = prom_n_addr_cells(dn);
- property = (unsigned int *) get_property(dn,
- "platform-spider-pic", NULL);
+ pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__);
- if (!property)
- continue;
- for (spiderpic = 0; n > 0; --n)
- spiderpic = (spiderpic << 32) + *property++;
+ for (node = 0; node < num_present_cpus()/2; node++) {
+ spiderpic = pics[node];
printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic);
- spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE);
+ spider_pics[node] = ioremap(spiderpic, 0x800);
for (n = 0; n < IIC_NUM_EXT; n++) {
int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
get_irq_desc(irq)->handler = &spider_pic;
+ }
/* do not mask any interrupts because of level */
out_be32(spider_pics[node] + TIR_MSK, 0x0);
-
+
/* disable edge detection clear */
/* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
-
+
/* enable interrupt packets to be output */
out_be32(spider_pics[node] + TIR_PIEN,
in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
-
+
/* Enable the interrupt detection enable bit. Do this last! */
out_be32(spider_pics[node] + TIR_DEN,
- in_be32(spider_pics[node] +TIR_DEN) | 0x1);
+ in_be32(spider_pics[node] + TIR_DEN) | 0x1);
+ }
+}
+
+void spider_init_IRQ(void)
+{
+ long spider_reg;
+ struct device_node *dn;
+ char *compatible;
+ int n, node = 0;
+
+ for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
+ compatible = (char *)get_property(dn, "compatible", NULL);
+ if (!compatible)
+ continue;
+
+ if (strstr(compatible, "CBEA,platform-spider-pic"))
+ spider_reg = *(long *)get_property(dn,"reg", NULL);
+ else if (strstr(compatible, "sti,platform-spider-pic")) {
+ spider_init_IRQ_hardcoded();
+ return;
+ } else
+ continue;
+
+ if (!spider_reg)
+ printk("interrupt controller does not have reg property !\n");
+
+ n = prom_n_addr_cells(dn);
+
+ if ( n != 2)
+ printk("reg property with invalid number of elements \n");
+
+ spider_pics[node] = ioremap(spider_reg, 0x800);
+
+ printk("SPIDER addr: %lx with %i addr_cells mapped to %p\n",
+ spider_reg, n, spider_pics[node]);
+
+ for (n = 0; n < IIC_NUM_EXT; n++) {
+ int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
+ get_irq_desc(irq)->handler = &spider_pic;
}
+
+ /* do not mask any interrupts because of level */
+ out_be32(spider_pics[node] + TIR_MSK, 0x0);
+
+ /* disable edge detection clear */
+ /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
+
+ /* enable interrupt packets to be output */
+ out_be32(spider_pics[node] + TIR_PIEN,
+ in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
+
+ /* Enable the interrupt detection enable bit. Do this last! */
+ out_be32(spider_pics[node] + TIR_DEN,
+ in_be32(spider_pics[node] + TIR_DEN) | 0x1);
+
+ node++;
}
}
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index a8fa1eeeb17..ad141fe8d52 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -111,7 +111,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX
static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
{
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s, %lx, %lx\n", __FUNCTION__, dsisr, ea);
/* Handle kernel space hash faults immediately.
User hash faults need to be deferred to process context. */
@@ -168,7 +168,7 @@ static int __spu_trap_halt(struct spu *spu)
static int __spu_trap_tag_group(struct spu *spu)
{
pr_debug("%s\n", __FUNCTION__);
- /* wake_up(&spu->dma_wq); */
+ spu->mfc_callback(spu);
return 0;
}
@@ -242,6 +242,8 @@ spu_irq_class_1(int irq, void *data, struct pt_regs *regs)
spu_mfc_dsisr_set(spu, 0ul);
spu_int_stat_clear(spu, 1, stat);
spin_unlock(&spu->register_lock);
+ pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
+ dar, dsisr);
if (stat & 1) /* segment fault */
__spu_trap_data_seg(spu, dar);
@@ -304,19 +306,19 @@ spu_request_irqs(struct spu *spu)
snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0", spu->number);
ret = request_irq(irq_base + spu->isrc,
- spu_irq_class_0, 0, spu->irq_c0, spu);
+ spu_irq_class_0, SA_INTERRUPT, spu->irq_c0, spu);
if (ret)
goto out;
snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1", spu->number);
ret = request_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc,
- spu_irq_class_1, 0, spu->irq_c1, spu);
+ spu_irq_class_1, SA_INTERRUPT, spu->irq_c1, spu);
if (ret)
goto out1;
snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2", spu->number);
ret = request_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc,
- spu_irq_class_2, 0, spu->irq_c2, spu);
+ spu_irq_class_2, SA_INTERRUPT, spu->irq_c2, spu);
if (ret)
goto out2;
goto out;
@@ -484,14 +486,17 @@ int spu_irq_class_1_bottom(struct spu *spu)
ea = spu->dar;
dsisr = spu->dsisr;
- if (dsisr & MFC_DSISR_PTE_NOT_FOUND) {
+ if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) {
+ u64 flags;
+
access = (_PAGE_PRESENT | _PAGE_USER);
access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL;
+ local_irq_save(flags);
if (hash_page(ea, access, 0x300) != 0)
error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
+ local_irq_restore(flags);
}
- if ((error & CLASS1_ENABLE_STORAGE_FAULT_INTR) ||
- (dsisr & MFC_DSISR_ACCESS_DENIED)) {
+ if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) {
if ((ret = spu_handle_mm_fault(spu)) != 0)
error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
else
@@ -515,8 +520,50 @@ void spu_irq_setaffinity(struct spu *spu, int cpu)
}
EXPORT_SYMBOL_GPL(spu_irq_setaffinity);
-static void __iomem * __init map_spe_prop(struct device_node *n,
- const char *name)
+static int __init find_spu_node_id(struct device_node *spe)
+{
+ unsigned int *id;
+ struct device_node *cpu;
+ cpu = spe->parent->parent;
+ id = (unsigned int *)get_property(cpu, "node-id", NULL);
+ return id ? *id : 0;
+}
+
+static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe,
+ const char *prop)
+{
+ static DEFINE_MUTEX(add_spumem_mutex);
+
+ struct address_prop {
+ unsigned long address;
+ unsigned int len;
+ } __attribute__((packed)) *p;
+ int proplen;
+
+ unsigned long start_pfn, nr_pages;
+ struct pglist_data *pgdata;
+ struct zone *zone;
+ int ret;
+
+ p = (void*)get_property(spe, prop, &proplen);
+ WARN_ON(proplen != sizeof (*p));
+
+ start_pfn = p->address >> PAGE_SHIFT;
+ nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ pgdata = NODE_DATA(spu->nid);
+ zone = pgdata->node_zones;
+
+ /* XXX rethink locking here */
+ mutex_lock(&add_spumem_mutex);
+ ret = __add_pages(zone, start_pfn, nr_pages);
+ mutex_unlock(&add_spumem_mutex);
+
+ return ret;
+}
+
+static void __iomem * __init map_spe_prop(struct spu *spu,
+ struct device_node *n, const char *name)
{
struct address_prop {
unsigned long address;
@@ -525,6 +572,8 @@ static void __iomem * __init map_spe_prop(struct device_node *n,
void *p;
int proplen;
+ void* ret = NULL;
+ int err = 0;
p = get_property(n, name, &proplen);
if (proplen != sizeof (struct address_prop))
@@ -532,7 +581,14 @@ static void __iomem * __init map_spe_prop(struct device_node *n,
prop = p;
- return ioremap(prop->address, prop->len);
+ err = cell_spuprop_present(spu, n, name);
+ if (err && (err != -EEXIST))
+ goto out;
+
+ ret = ioremap(prop->address, prop->len);
+
+ out:
+ return ret;
}
static void spu_unmap(struct spu *spu)
@@ -543,39 +599,45 @@ static void spu_unmap(struct spu *spu)
iounmap((u8 __iomem *)spu->local_store);
}
-static int __init spu_map_device(struct spu *spu, struct device_node *spe)
+static int __init spu_map_device(struct spu *spu, struct device_node *node)
{
char *prop;
int ret;
ret = -ENODEV;
- prop = get_property(spe, "isrc", NULL);
+ prop = get_property(node, "isrc", NULL);
if (!prop)
goto out;
spu->isrc = *(unsigned int *)prop;
- spu->name = get_property(spe, "name", NULL);
+ spu->name = get_property(node, "name", NULL);
if (!spu->name)
goto out;
- prop = get_property(spe, "local-store", NULL);
+ prop = get_property(node, "local-store", NULL);
if (!prop)
goto out;
spu->local_store_phys = *(unsigned long *)prop;
/* we use local store as ram, not io memory */
- spu->local_store = (void __force *)map_spe_prop(spe, "local-store");
+ spu->local_store = (void __force *)
+ map_spe_prop(spu, node, "local-store");
if (!spu->local_store)
goto out;
- spu->problem= map_spe_prop(spe, "problem");
+ prop = get_property(node, "problem", NULL);
+ if (!prop)
+ goto out_unmap;
+ spu->problem_phys = *(unsigned long *)prop;
+
+ spu->problem= map_spe_prop(spu, node, "problem");
if (!spu->problem)
goto out_unmap;
- spu->priv1= map_spe_prop(spe, "priv1");
+ spu->priv1= map_spe_prop(spu, node, "priv1");
/* priv1 is not available on a hypervisor */
- spu->priv2= map_spe_prop(spe, "priv2");
+ spu->priv2= map_spe_prop(spu, node, "priv2");
if (!spu->priv2)
goto out_unmap;
ret = 0;
@@ -587,17 +649,6 @@ out:
return ret;
}
-static int __init find_spu_node_id(struct device_node *spe)
-{
- unsigned int *id;
- struct device_node *cpu;
-
- cpu = spe->parent->parent;
- id = (unsigned int *)get_property(cpu, "node-id", NULL);
-
- return id ? *id : 0;
-}
-
static int __init create_spu(struct device_node *spe)
{
struct spu *spu;
@@ -614,6 +665,10 @@ static int __init create_spu(struct device_node *spe)
goto out_free;
spu->node = find_spu_node_id(spe);
+ spu->nid = of_node_to_nid(spe);
+ if (spu->nid == -1)
+ spu->nid = 0;
+
spu->stop_code = 0;
spu->slb_replace = 0;
spu->mm = NULL;
@@ -632,6 +687,7 @@ static int __init create_spu(struct device_node *spe)
spu->ibox_callback = NULL;
spu->wbox_callback = NULL;
spu->stop_callback = NULL;
+ spu->mfc_callback = NULL;
mutex_lock(&spu_mutex);
spu->number = number++;
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
new file mode 100644
index 00000000000..b47fcc5ddb7
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_callbacks.c
@@ -0,0 +1,362 @@
+/*
+ * System call callback functions for SPUs
+ */
+
+#define DEBUG
+
+#include <linux/kallsyms.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+
+#include <asm/spu.h>
+#include <asm/syscalls.h>
+#include <asm/unistd.h>
+
+/*
+ * This table defines the system calls that an SPU can call.
+ * It is currently a subset of the 64 bit powerpc system calls,
+ * with the exact semantics.
+ *
+ * The reasons for disabling some of the system calls are:
+ * 1. They interact with the way SPU syscalls are handled
+ * and we can't let them execute ever:
+ * restart_syscall, exit, for, execve, ptrace, ...
+ * 2. They are deprecated and replaced by other means:
+ * uselib, pciconfig_*, sysfs, ...
+ * 3. They are somewhat interacting with the system in a way
+ * we don't want an SPU to:
+ * reboot, init_module, mount, kexec_load
+ * 4. They are optional and we can't rely on them being
+ * linked into the kernel. Unfortunately, the cond_syscall
+ * helper does not work here as it does not add the necessary
+ * opd symbols:
+ * mbind, mq_open, ipc, ...
+ */
+
+void *spu_syscall_table[] = {
+ [__NR_restart_syscall] sys_ni_syscall, /* sys_restart_syscall */
+ [__NR_exit] sys_ni_syscall, /* sys_exit */
+ [__NR_fork] sys_ni_syscall, /* ppc_fork */
+ [__NR_read] sys_read,
+ [__NR_write] sys_write,
+ [__NR_open] sys_open,
+ [__NR_close] sys_close,
+ [__NR_waitpid] sys_waitpid,
+ [__NR_creat] sys_creat,
+ [__NR_link] sys_link,
+ [__NR_unlink] sys_unlink,
+ [__NR_execve] sys_ni_syscall, /* sys_execve */
+ [__NR_chdir] sys_chdir,
+ [__NR_time] sys_time,
+ [__NR_mknod] sys_mknod,
+ [__NR_chmod] sys_chmod,
+ [__NR_lchown] sys_lchown,
+ [__NR_break] sys_ni_syscall,
+ [__NR_oldstat] sys_ni_syscall,
+ [__NR_lseek] sys_lseek,
+ [__NR_getpid] sys_getpid,
+ [__NR_mount] sys_ni_syscall, /* sys_mount */
+ [__NR_umount] sys_ni_syscall,
+ [__NR_setuid] sys_setuid,
+ [__NR_getuid] sys_getuid,
+ [__NR_stime] sys_stime,
+ [__NR_ptrace] sys_ni_syscall, /* sys_ptrace */
+ [__NR_alarm] sys_alarm,
+ [__NR_oldfstat] sys_ni_syscall,
+ [__NR_pause] sys_ni_syscall, /* sys_pause */
+ [__NR_utime] sys_ni_syscall, /* sys_utime */
+ [__NR_stty] sys_ni_syscall,
+ [__NR_gtty] sys_ni_syscall,
+ [__NR_access] sys_access,
+ [__NR_nice] sys_nice,
+ [__NR_ftime] sys_ni_syscall,
+ [__NR_sync] sys_sync,
+ [__NR_kill] sys_kill,
+ [__NR_rename] sys_rename,
+ [__NR_mkdir] sys_mkdir,
+ [__NR_rmdir] sys_rmdir,
+ [__NR_dup] sys_dup,
+ [__NR_pipe] sys_pipe,
+ [__NR_times] sys_times,
+ [__NR_prof] sys_ni_syscall,
+ [__NR_brk] sys_brk,
+ [__NR_setgid] sys_setgid,
+ [__NR_getgid] sys_getgid,
+ [__NR_signal] sys_ni_syscall, /* sys_signal */
+ [__NR_geteuid] sys_geteuid,
+ [__NR_getegid] sys_getegid,
+ [__NR_acct] sys_ni_syscall, /* sys_acct */
+ [__NR_umount2] sys_ni_syscall, /* sys_umount */
+ [__NR_lock] sys_ni_syscall,
+ [__NR_ioctl] sys_ioctl,
+ [__NR_fcntl] sys_fcntl,
+ [__NR_mpx] sys_ni_syscall,
+ [__NR_setpgid] sys_setpgid,
+ [__NR_ulimit] sys_ni_syscall,
+ [__NR_oldolduname] sys_ni_syscall,
+ [__NR_umask] sys_umask,
+ [__NR_chroot] sys_chroot,
+ [__NR_ustat] sys_ni_syscall, /* sys_ustat */
+ [__NR_dup2] sys_dup2,
+ [__NR_getppid] sys_getppid,
+ [__NR_getpgrp] sys_getpgrp,
+ [__NR_setsid] sys_setsid,
+ [__NR_sigaction] sys_ni_syscall,
+ [__NR_sgetmask] sys_sgetmask,
+ [__NR_ssetmask] sys_ssetmask,
+ [__NR_setreuid] sys_setreuid,
+ [__NR_setregid] sys_setregid,
+ [__NR_sigsuspend] sys_ni_syscall,
+ [__NR_sigpending] sys_ni_syscall,
+ [__NR_sethostname] sys_sethostname,
+ [__NR_setrlimit] sys_setrlimit,
+ [__NR_getrlimit] sys_ni_syscall,
+ [__NR_getrusage] sys_getrusage,
+ [__NR_gettimeofday] sys_gettimeofday,
+ [__NR_settimeofday] sys_settimeofday,
+ [__NR_getgroups] sys_getgroups,
+ [__NR_setgroups] sys_setgroups,
+ [__NR_select] sys_ni_syscall,
+ [__NR_symlink] sys_symlink,
+ [__NR_oldlstat] sys_ni_syscall,
+ [__NR_readlink] sys_readlink,
+ [__NR_uselib] sys_ni_syscall, /* sys_uselib */
+ [__NR_swapon] sys_ni_syscall, /* sys_swapon */
+ [__NR_reboot] sys_ni_syscall, /* sys_reboot */
+ [__NR_readdir] sys_ni_syscall,
+ [__NR_mmap] sys_mmap,
+ [__NR_munmap] sys_munmap,
+ [__NR_truncate] sys_truncate,
+ [__NR_ftruncate] sys_ftruncate,
+ [__NR_fchmod] sys_fchmod,
+ [__NR_fchown] sys_fchown,
+ [__NR_getpriority] sys_getpriority,
+ [__NR_setpriority] sys_setpriority,
+ [__NR_profil] sys_ni_syscall,
+ [__NR_statfs] sys_ni_syscall, /* sys_statfs */
+ [__NR_fstatfs] sys_ni_syscall, /* sys_fstatfs */
+ [__NR_ioperm] sys_ni_syscall,
+ [__NR_socketcall] sys_socketcall,
+ [__NR_syslog] sys_syslog,
+ [__NR_setitimer] sys_setitimer,
+ [__NR_getitimer] sys_getitimer,
+ [__NR_stat] sys_newstat,
+ [__NR_lstat] sys_newlstat,
+ [__NR_fstat] sys_newfstat,
+ [__NR_olduname] sys_ni_syscall,
+ [__NR_iopl] sys_ni_syscall,
+ [__NR_vhangup] sys_vhangup,
+ [__NR_idle] sys_ni_syscall,
+ [__NR_vm86] sys_ni_syscall,
+ [__NR_wait4] sys_wait4,
+ [__NR_swapoff] sys_ni_syscall, /* sys_swapoff */
+ [__NR_sysinfo] sys_sysinfo,
+ [__NR_ipc] sys_ni_syscall, /* sys_ipc */
+ [__NR_fsync] sys_fsync,
+ [__NR_sigreturn] sys_ni_syscall,
+ [__NR_clone] sys_ni_syscall, /* ppc_clone */
+ [__NR_setdomainname] sys_setdomainname,
+ [__NR_uname] ppc_newuname,
+ [__NR_modify_ldt] sys_ni_syscall,
+ [__NR_adjtimex] sys_adjtimex,
+ [__NR_mprotect] sys_mprotect,
+ [__NR_sigprocmask] sys_ni_syscall,
+ [__NR_create_module] sys_ni_syscall,
+ [__NR_init_module] sys_ni_syscall, /* sys_init_module */
+ [__NR_delete_module] sys_ni_syscall, /* sys_delete_module */
+ [__NR_get_kernel_syms] sys_ni_syscall,
+ [__NR_quotactl] sys_ni_syscall, /* sys_quotactl */
+ [__NR_getpgid] sys_getpgid,
+ [__NR_fchdir] sys_fchdir,
+ [__NR_bdflush] sys_bdflush,
+ [__NR_sysfs] sys_ni_syscall, /* sys_sysfs */
+ [__NR_personality] ppc64_personality,
+ [__NR_afs_syscall] sys_ni_syscall,
+ [__NR_setfsuid] sys_setfsuid,
+ [__NR_setfsgid] sys_setfsgid,
+ [__NR__llseek] sys_llseek,
+ [__NR_getdents] sys_getdents,
+ [__NR__newselect] sys_select,
+ [__NR_flock] sys_flock,
+ [__NR_msync] sys_msync,
+ [__NR_readv] sys_readv,
+ [__NR_writev] sys_writev,
+ [__NR_getsid] sys_getsid,
+ [__NR_fdatasync] sys_fdatasync,
+ [__NR__sysctl] sys_ni_syscall, /* sys_sysctl */
+ [__NR_mlock] sys_mlock,
+ [__NR_munlock] sys_munlock,
+ [__NR_mlockall] sys_mlockall,
+ [__NR_munlockall] sys_munlockall,
+ [__NR_sched_setparam] sys_sched_setparam,
+ [__NR_sched_getparam] sys_sched_getparam,
+ [__NR_sched_setscheduler] sys_sched_setscheduler,
+ [__NR_sched_getscheduler] sys_sched_getscheduler,
+ [__NR_sched_yield] sys_sched_yield,
+ [__NR_sched_get_priority_max] sys_sched_get_priority_max,
+ [__NR_sched_get_priority_min] sys_sched_get_priority_min,
+ [__NR_sched_rr_get_interval] sys_sched_rr_get_interval,
+ [__NR_nanosleep] sys_nanosleep,
+ [__NR_mremap] sys_mremap,
+ [__NR_setresuid] sys_setresuid,
+ [__NR_getresuid] sys_getresuid,
+ [__NR_query_module] sys_ni_syscall,
+ [__NR_poll] sys_poll,
+ [__NR_nfsservctl] sys_ni_syscall, /* sys_nfsservctl */
+ [__NR_setresgid] sys_setresgid,
+ [__NR_getresgid] sys_getresgid,
+ [__NR_prctl] sys_prctl,
+ [__NR_rt_sigreturn] sys_ni_syscall, /* ppc64_rt_sigreturn */
+ [__NR_rt_sigaction] sys_ni_syscall, /* sys_rt_sigaction */
+ [__NR_rt_sigprocmask] sys_ni_syscall, /* sys_rt_sigprocmask */
+ [__NR_rt_sigpending] sys_ni_syscall, /* sys_rt_sigpending */
+ [__NR_rt_sigtimedwait] sys_ni_syscall, /* sys_rt_sigtimedwait */
+ [__NR_rt_sigqueueinfo] sys_ni_syscall, /* sys_rt_sigqueueinfo */
+ [__NR_rt_sigsuspend] sys_ni_syscall, /* sys_rt_sigsuspend */
+ [__NR_pread64] sys_pread64,
+ [__NR_pwrite64] sys_pwrite64,
+ [__NR_chown] sys_chown,
+ [__NR_getcwd] sys_getcwd,
+ [__NR_capget] sys_capget,
+ [__NR_capset] sys_capset,
+ [__NR_sigaltstack] sys_ni_syscall, /* sys_sigaltstack */
+ [__NR_sendfile] sys_sendfile64,
+ [__NR_getpmsg] sys_ni_syscall,
+ [__NR_putpmsg] sys_ni_syscall,
+ [__NR_vfork] sys_ni_syscall, /* ppc_vfork */
+ [__NR_ugetrlimit] sys_getrlimit,
+ [__NR_readahead] sys_readahead,
+ [192] sys_ni_syscall,
+ [193] sys_ni_syscall,
+ [194] sys_ni_syscall,
+ [195] sys_ni_syscall,
+ [196] sys_ni_syscall,
+ [197] sys_ni_syscall,
+ [__NR_pciconfig_read] sys_ni_syscall, /* sys_pciconfig_read */
+ [__NR_pciconfig_write] sys_ni_syscall, /* sys_pciconfig_write */
+ [__NR_pciconfig_iobase] sys_ni_syscall, /* sys_pciconfig_iobase */
+ [__NR_multiplexer] sys_ni_syscall,
+ [__NR_getdents64] sys_getdents64,
+ [__NR_pivot_root] sys_pivot_root,
+ [204] sys_ni_syscall,
+ [__NR_madvise] sys_madvise,
+ [__NR_mincore] sys_mincore,
+ [__NR_gettid] sys_gettid,
+ [__NR_tkill] sys_tkill,
+ [__NR_setxattr] sys_setxattr,
+ [__NR_lsetxattr] sys_lsetxattr,
+ [__NR_fsetxattr] sys_fsetxattr,
+ [__NR_getxattr] sys_getxattr,
+ [__NR_lgetxattr] sys_lgetxattr,
+ [__NR_fgetxattr] sys_fgetxattr,
+ [__NR_listxattr] sys_listxattr,
+ [__NR_llistxattr] sys_llistxattr,
+ [__NR_flistxattr] sys_flistxattr,
+ [__NR_removexattr] sys_removexattr,
+ [__NR_lremovexattr] sys_lremovexattr,
+ [__NR_fremovexattr] sys_fremovexattr,
+ [__NR_futex] sys_futex,
+ [__NR_sched_setaffinity] sys_sched_setaffinity,
+ [__NR_sched_getaffinity] sys_sched_getaffinity,
+ [224] sys_ni_syscall,
+ [__NR_tuxcall] sys_ni_syscall,
+ [226] sys_ni_syscall,
+ [__NR_io_setup] sys_io_setup,
+ [__NR_io_destroy] sys_io_destroy,
+ [__NR_io_getevents] sys_io_getevents,
+ [__NR_io_submit] sys_io_submit,
+ [__NR_io_cancel] sys_io_cancel,
+ [__NR_set_tid_address] sys_ni_syscall, /* sys_set_tid_address */
+ [__NR_fadvise64] sys_fadvise64,
+ [__NR_exit_group] sys_ni_syscall, /* sys_exit_group */
+ [__NR_lookup_dcookie] sys_ni_syscall, /* sys_lookup_dcookie */
+ [__NR_epoll_create] sys_epoll_create,
+ [__NR_epoll_ctl] sys_epoll_ctl,
+ [__NR_epoll_wait] sys_epoll_wait,
+ [__NR_remap_file_pages] sys_remap_file_pages,
+ [__NR_timer_create] sys_timer_create,
+ [__NR_timer_settime] sys_timer_settime,
+ [__NR_timer_gettime] sys_timer_gettime,
+ [__NR_timer_getoverrun] sys_timer_getoverrun,
+ [__NR_timer_delete] sys_timer_delete,
+ [__NR_clock_settime] sys_clock_settime,
+ [__NR_clock_gettime] sys_clock_gettime,
+ [__NR_clock_getres] sys_clock_getres,
+ [__NR_clock_nanosleep] sys_clock_nanosleep,
+ [__NR_swapcontext] sys_ni_syscall, /* ppc64_swapcontext */
+ [__NR_tgkill] sys_tgkill,
+ [__NR_utimes] sys_utimes,
+ [__NR_statfs64] sys_statfs64,
+ [__NR_fstatfs64] sys_fstatfs64,
+ [254] sys_ni_syscall,
+ [__NR_rtas] ppc_rtas,
+ [256] sys_ni_syscall,
+ [257] sys_ni_syscall,
+ [258] sys_ni_syscall,
+ [__NR_mbind] sys_ni_syscall, /* sys_mbind */
+ [__NR_get_mempolicy] sys_ni_syscall, /* sys_get_mempolicy */
+ [__NR_set_mempolicy] sys_ni_syscall, /* sys_set_mempolicy */
+ [__NR_mq_open] sys_ni_syscall, /* sys_mq_open */
+ [__NR_mq_unlink] sys_ni_syscall, /* sys_mq_unlink */
+ [__NR_mq_timedsend] sys_ni_syscall, /* sys_mq_timedsend */
+ [__NR_mq_timedreceive] sys_ni_syscall, /* sys_mq_timedreceive */
+ [__NR_mq_notify] sys_ni_syscall, /* sys_mq_notify */
+ [__NR_mq_getsetattr] sys_ni_syscall, /* sys_mq_getsetattr */
+ [__NR_kexec_load] sys_ni_syscall, /* sys_kexec_load */
+ [__NR_add_key] sys_ni_syscall, /* sys_add_key */
+ [__NR_request_key] sys_ni_syscall, /* sys_request_key */
+ [__NR_keyctl] sys_ni_syscall, /* sys_keyctl */
+ [__NR_waitid] sys_ni_syscall, /* sys_waitid */
+ [__NR_ioprio_set] sys_ni_syscall, /* sys_ioprio_set */
+ [__NR_ioprio_get] sys_ni_syscall, /* sys_ioprio_get */
+ [__NR_inotify_init] sys_ni_syscall, /* sys_inotify_init */
+ [__NR_inotify_add_watch] sys_ni_syscall, /* sys_inotify_add_watch */
+ [__NR_inotify_rm_watch] sys_ni_syscall, /* sys_inotify_rm_watch */
+ [__NR_spu_run] sys_ni_syscall, /* sys_spu_run */
+ [__NR_spu_create] sys_ni_syscall, /* sys_spu_create */
+ [__NR_pselect6] sys_ni_syscall, /* sys_pselect */
+ [__NR_ppoll] sys_ni_syscall, /* sys_ppoll */
+ [__NR_unshare] sys_unshare,
+ [__NR_splice] sys_splice,
+ [__NR_tee] sys_tee,
+ [__NR_vmsplice] sys_vmsplice,
+ [__NR_openat] sys_openat,
+ [__NR_mkdirat] sys_mkdirat,
+ [__NR_mknodat] sys_mknodat,
+ [__NR_fchownat] sys_fchownat,
+ [__NR_futimesat] sys_futimesat,
+ [__NR_newfstatat] sys_newfstatat,
+ [__NR_unlinkat] sys_unlinkat,
+ [__NR_renameat] sys_renameat,
+ [__NR_linkat] sys_linkat,
+ [__NR_symlinkat] sys_symlinkat,
+ [__NR_readlinkat] sys_readlinkat,
+ [__NR_fchmodat] sys_fchmodat,
+ [__NR_faccessat] sys_faccessat,
+ [__NR_get_robust_list] sys_get_robust_list,
+ [__NR_set_robust_list] sys_set_robust_list,
+};
+
+long spu_sys_callback(struct spu_syscall_block *s)
+{
+ long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6);
+
+ if (s->nr_ret >= ARRAY_SIZE(spu_syscall_table)) {
+ pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret);
+ return -ENOSYS;
+ }
+
+ syscall = spu_syscall_table[s->nr_ret];
+
+#ifdef DEBUG
+ print_symbol(KERN_DEBUG "SPU-syscall %s:", (unsigned long)syscall);
+ printk("syscall%ld(%lx, %lx, %lx, %lx, %lx, %lx)\n",
+ s->nr_ret,
+ s->parm[0], s->parm[1], s->parm[2],
+ s->parm[3], s->parm[4], s->parm[5]);
+#endif
+
+ return syscall(s->parm[0], s->parm[1], s->parm[2],
+ s->parm[3], s->parm[4], s->parm[5]);
+}
+EXPORT_SYMBOL_GPL(spu_sys_callback);
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
index a5c489a53c6..f1d35ddc9df 100644
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -285,6 +285,49 @@ static void spu_backing_runcntl_stop(struct spu_context *ctx)
spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP);
}
+static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask,
+ u32 mode)
+{
+ struct spu_problem_collapsed *prob = &ctx->csa.prob;
+ int ret;
+
+ spin_lock(&ctx->csa.register_lock);
+ ret = -EAGAIN;
+ if (prob->dma_querytype_RW)
+ goto out;
+ ret = 0;
+ /* FIXME: what are the side-effects of this? */
+ prob->dma_querymask_RW = mask;
+ prob->dma_querytype_RW = mode;
+out:
+ spin_unlock(&ctx->csa.register_lock);
+
+ return ret;
+}
+
+static u32 spu_backing_read_mfc_tagstatus(struct spu_context * ctx)
+{
+ return ctx->csa.prob.dma_tagstatus_R;
+}
+
+static u32 spu_backing_get_mfc_free_elements(struct spu_context *ctx)
+{
+ return ctx->csa.prob.dma_qstatus_R;
+}
+
+static int spu_backing_send_mfc_command(struct spu_context *ctx,
+ struct mfc_dma_command *cmd)
+{
+ int ret;
+
+ spin_lock(&ctx->csa.register_lock);
+ ret = -EAGAIN;
+ /* FIXME: set up priv2->puq */
+ spin_unlock(&ctx->csa.register_lock);
+
+ return ret;
+}
+
struct spu_context_ops spu_backing_ops = {
.mbox_read = spu_backing_mbox_read,
.mbox_stat_read = spu_backing_mbox_stat_read,
@@ -305,4 +348,8 @@ struct spu_context_ops spu_backing_ops = {
.get_ls = spu_backing_get_ls,
.runcntl_write = spu_backing_runcntl_write,
.runcntl_stop = spu_backing_runcntl_stop,
+ .set_mfc_query = spu_backing_set_mfc_query,
+ .read_mfc_tagstatus = spu_backing_read_mfc_tagstatus,
+ .get_mfc_free_elements = spu_backing_get_mfc_free_elements,
+ .send_mfc_command = spu_backing_send_mfc_command,
};
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 336f238102f..8bb33abfad1 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -27,7 +27,7 @@
#include <asm/spu_csa.h>
#include "spufs.h"
-struct spu_context *alloc_spu_context(struct address_space *local_store)
+struct spu_context *alloc_spu_context(void)
{
struct spu_context *ctx;
ctx = kmalloc(sizeof *ctx, GFP_KERNEL);
@@ -47,10 +47,17 @@ struct spu_context *alloc_spu_context(struct address_space *local_store)
init_waitqueue_head(&ctx->ibox_wq);
init_waitqueue_head(&ctx->wbox_wq);
init_waitqueue_head(&ctx->stop_wq);
+ init_waitqueue_head(&ctx->mfc_wq);
ctx->ibox_fasync = NULL;
ctx->wbox_fasync = NULL;
+ ctx->mfc_fasync = NULL;
+ ctx->mfc = NULL;
+ ctx->tagwait = 0;
ctx->state = SPU_STATE_SAVED;
- ctx->local_store = local_store;
+ ctx->local_store = NULL;
+ ctx->cntl = NULL;
+ ctx->signal1 = NULL;
+ ctx->signal2 = NULL;
ctx->spu = NULL;
ctx->ops = &spu_backing_ops;
ctx->owner = get_task_mm(current);
@@ -68,8 +75,6 @@ void destroy_spu_context(struct kref *kref)
ctx = container_of(kref, struct spu_context, kref);
down_write(&ctx->state_sema);
spu_deactivate(ctx);
- ctx->ibox_fasync = NULL;
- ctx->wbox_fasync = NULL;
up_write(&ctx->state_sema);
spu_fini_csa(&ctx->csa);
kfree(ctx);
@@ -109,7 +114,16 @@ void spu_release(struct spu_context *ctx)
void spu_unmap_mappings(struct spu_context *ctx)
{
- unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
+ if (ctx->local_store)
+ unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
+ if (ctx->mfc)
+ unmap_mapping_range(ctx->mfc, 0, 0x4000, 1);
+ if (ctx->cntl)
+ unmap_mapping_range(ctx->cntl, 0, 0x4000, 1);
+ if (ctx->signal1)
+ unmap_mapping_range(ctx->signal1, 0, 0x4000, 1);
+ if (ctx->signal2)
+ unmap_mapping_range(ctx->signal2, 0, 0x4000, 1);
}
int spu_acquire_runnable(struct spu_context *ctx)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index dfa649c9b95..366185e9266 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#undef DEBUG
+
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/module.h>
@@ -39,8 +41,10 @@ static int
spufs_mem_open(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
- file->private_data = i->i_ctx;
- file->f_mapping = i->i_ctx->local_store;
+ struct spu_context *ctx = i->i_ctx;
+ file->private_data = ctx;
+ file->f_mapping = inode->i_mapping;
+ ctx->local_store = inode->i_mapping;
return 0;
}
@@ -84,7 +88,7 @@ spufs_mem_write(struct file *file, const char __user *buffer,
return ret;
}
-#ifdef CONFIG_SPARSEMEM
+#ifdef CONFIG_SPUFS_MMAP
static struct page *
spufs_mem_mmap_nopage(struct vm_area_struct *vma,
unsigned long address, int *type)
@@ -136,11 +140,113 @@ static struct file_operations spufs_mem_fops = {
.read = spufs_mem_read,
.write = spufs_mem_write,
.llseek = generic_file_llseek,
-#ifdef CONFIG_SPARSEMEM
+#ifdef CONFIG_SPUFS_MMAP
.mmap = spufs_mem_mmap,
#endif
};
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
+ unsigned long address,
+ int *type, unsigned long ps_offs)
+{
+ struct page *page = NOPAGE_SIGBUS;
+ int fault_type = VM_FAULT_SIGBUS;
+ struct spu_context *ctx = vma->vm_file->private_data;
+ unsigned long offset = address - vma->vm_start;
+ unsigned long area;
+ int ret;
+
+ offset += vma->vm_pgoff << PAGE_SHIFT;
+ if (offset >= 0x4000)
+ goto out;
+
+ ret = spu_acquire_runnable(ctx);
+ if (ret)
+ goto out;
+
+ area = ctx->spu->problem_phys + ps_offs;
+ page = pfn_to_page((area + offset) >> PAGE_SHIFT);
+ fault_type = VM_FAULT_MINOR;
+ page_cache_get(page);
+
+ spu_release(ctx);
+
+ out:
+ if (type)
+ *type = fault_type;
+
+ return page;
+}
+
+static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ return spufs_ps_nopage(vma, address, type, 0x4000);
+}
+
+static struct vm_operations_struct spufs_cntl_mmap_vmops = {
+ .nopage = spufs_cntl_mmap_nopage,
+};
+
+/*
+ * mmap support for problem state control area [0x4000 - 0x4fff].
+ * Mapping this area requires that the application have CAP_SYS_RAWIO,
+ * as these registers require special care when read/writing.
+ */
+static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ if (!(vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+ | _PAGE_NO_CACHE);
+
+ vma->vm_ops = &spufs_cntl_mmap_vmops;
+ return 0;
+}
+#endif
+
+static int spufs_cntl_open(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+
+ file->private_data = ctx;
+ file->f_mapping = inode->i_mapping;
+ ctx->cntl = inode->i_mapping;
+ return 0;
+}
+
+static ssize_t
+spufs_cntl_read(struct file *file, char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ /* FIXME: read from spu status */
+ return -EINVAL;
+}
+
+static ssize_t
+spufs_cntl_write(struct file *file, const char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ /* FIXME: write to runctl bit */
+ return -EINVAL;
+}
+
+static struct file_operations spufs_cntl_fops = {
+ .open = spufs_cntl_open,
+ .read = spufs_cntl_read,
+ .write = spufs_cntl_write,
+#ifdef CONFIG_SPUFS_MMAP
+ .mmap = spufs_cntl_mmap,
+#endif
+};
+
static int
spufs_regs_open(struct inode *inode, struct file *file)
{
@@ -501,6 +607,16 @@ static struct file_operations spufs_wbox_stat_fops = {
.read = spufs_wbox_stat_read,
};
+static int spufs_signal1_open(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+ file->private_data = ctx;
+ file->f_mapping = inode->i_mapping;
+ ctx->signal1 = inode->i_mapping;
+ return nonseekable_open(inode, file);
+}
+
static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
size_t len, loff_t *pos)
{
@@ -541,12 +657,50 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
return 4;
}
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ return spufs_ps_nopage(vma, address, type, 0x14000);
+}
+
+static struct vm_operations_struct spufs_signal1_mmap_vmops = {
+ .nopage = spufs_signal1_mmap_nopage,
+};
+
+static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ if (!(vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+ | _PAGE_NO_CACHE);
+
+ vma->vm_ops = &spufs_signal1_mmap_vmops;
+ return 0;
+}
+#endif
+
static struct file_operations spufs_signal1_fops = {
- .open = spufs_pipe_open,
+ .open = spufs_signal1_open,
.read = spufs_signal1_read,
.write = spufs_signal1_write,
+#ifdef CONFIG_SPUFS_MMAP
+ .mmap = spufs_signal1_mmap,
+#endif
};
+static int spufs_signal2_open(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+ file->private_data = ctx;
+ file->f_mapping = inode->i_mapping;
+ ctx->signal2 = inode->i_mapping;
+ return nonseekable_open(inode, file);
+}
+
static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
size_t len, loff_t *pos)
{
@@ -589,10 +743,39 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
return 4;
}
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ return spufs_ps_nopage(vma, address, type, 0x1c000);
+}
+
+static struct vm_operations_struct spufs_signal2_mmap_vmops = {
+ .nopage = spufs_signal2_mmap_nopage,
+};
+
+static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ if (!(vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ /* FIXME: */
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+ | _PAGE_NO_CACHE);
+
+ vma->vm_ops = &spufs_signal2_mmap_vmops;
+ return 0;
+}
+#endif
+
static struct file_operations spufs_signal2_fops = {
- .open = spufs_pipe_open,
+ .open = spufs_signal2_open,
.read = spufs_signal2_read,
.write = spufs_signal2_write,
+#ifdef CONFIG_SPUFS_MMAP
+ .mmap = spufs_signal2_mmap,
+#endif
};
static void spufs_signal1_type_set(void *data, u64 val)
@@ -641,6 +824,332 @@ static u64 spufs_signal2_type_get(void *data)
DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
spufs_signal2_type_set, "%llu");
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ return spufs_ps_nopage(vma, address, type, 0x3000);
+}
+
+static struct vm_operations_struct spufs_mfc_mmap_vmops = {
+ .nopage = spufs_mfc_mmap_nopage,
+};
+
+/*
+ * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
+ * Mapping this area requires that the application have CAP_SYS_RAWIO,
+ * as these registers require special care when read/writing.
+ */
+static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ if (!(vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+ | _PAGE_NO_CACHE);
+
+ vma->vm_ops = &spufs_mfc_mmap_vmops;
+ return 0;
+}
+#endif
+
+static int spufs_mfc_open(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+
+ /* we don't want to deal with DMA into other processes */
+ if (ctx->owner != current->mm)
+ return -EINVAL;
+
+ if (atomic_read(&inode->i_count) != 1)
+ return -EBUSY;
+
+ file->private_data = ctx;
+ return nonseekable_open(inode, file);
+}
+
+/* interrupt-level mfc callback function. */
+void spufs_mfc_callback(struct spu *spu)
+{
+ struct spu_context *ctx = spu->ctx;
+
+ wake_up_all(&ctx->mfc_wq);
+
+ pr_debug("%s %s\n", __FUNCTION__, spu->name);
+ if (ctx->mfc_fasync) {
+ u32 free_elements, tagstatus;
+ unsigned int mask;
+
+ /* no need for spu_acquire in interrupt context */
+ free_elements = ctx->ops->get_mfc_free_elements(ctx);
+ tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
+
+ mask = 0;
+ if (free_elements & 0xffff)
+ mask |= POLLOUT;
+ if (tagstatus & ctx->tagwait)
+ mask |= POLLIN;
+
+ kill_fasync(&ctx->mfc_fasync, SIGIO, mask);
+ }
+}
+
+static int spufs_read_mfc_tagstatus(struct spu_context *ctx, u32 *status)
+{
+ /* See if there is one tag group is complete */
+ /* FIXME we need locking around tagwait */
+ *status = ctx->ops->read_mfc_tagstatus(ctx) & ctx->tagwait;
+ ctx->tagwait &= ~*status;
+ if (*status)
+ return 1;
+
+ /* enable interrupt waiting for any tag group,
+ may silently fail if interrupts are already enabled */
+ ctx->ops->set_mfc_query(ctx, ctx->tagwait, 1);
+ return 0;
+}
+
+static ssize_t spufs_mfc_read(struct file *file, char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ int ret = -EINVAL;
+ u32 status;
+
+ if (size != 4)
+ goto out;
+
+ spu_acquire(ctx);
+ if (file->f_flags & O_NONBLOCK) {
+ status = ctx->ops->read_mfc_tagstatus(ctx);
+ if (!(status & ctx->tagwait))
+ ret = -EAGAIN;
+ else
+ ctx->tagwait &= ~status;
+ } else {
+ ret = spufs_wait(ctx->mfc_wq,
+ spufs_read_mfc_tagstatus(ctx, &status));
+ }
+ spu_release(ctx);
+
+ if (ret)
+ goto out;
+
+ ret = 4;
+ if (copy_to_user(buffer, &status, 4))
+ ret = -EFAULT;
+
+out:
+ return ret;
+}
+
+static int spufs_check_valid_dma(struct mfc_dma_command *cmd)
+{
+ pr_debug("queueing DMA %x %lx %x %x %x\n", cmd->lsa,
+ cmd->ea, cmd->size, cmd->tag, cmd->cmd);
+
+ switch (cmd->cmd) {
+ case MFC_PUT_CMD:
+ case MFC_PUTF_CMD:
+ case MFC_PUTB_CMD:
+ case MFC_GET_CMD:
+ case MFC_GETF_CMD:
+ case MFC_GETB_CMD:
+ break;
+ default:
+ pr_debug("invalid DMA opcode %x\n", cmd->cmd);
+ return -EIO;
+ }
+
+ if ((cmd->lsa & 0xf) != (cmd->ea &0xf)) {
+ pr_debug("invalid DMA alignment, ea %lx lsa %x\n",
+ cmd->ea, cmd->lsa);
+ return -EIO;
+ }
+
+ switch (cmd->size & 0xf) {
+ case 1:
+ break;
+ case 2:
+ if (cmd->lsa & 1)
+ goto error;
+ break;
+ case 4:
+ if (cmd->lsa & 3)
+ goto error;
+ break;
+ case 8:
+ if (cmd->lsa & 7)
+ goto error;
+ break;
+ case 0:
+ if (cmd->lsa & 15)
+ goto error;
+ break;
+ error:
+ default:
+ pr_debug("invalid DMA alignment %x for size %x\n",
+ cmd->lsa & 0xf, cmd->size);
+ return -EIO;
+ }
+
+ if (cmd->size > 16 * 1024) {
+ pr_debug("invalid DMA size %x\n", cmd->size);
+ return -EIO;
+ }
+
+ if (cmd->tag & 0xfff0) {
+ /* we reserve the higher tag numbers for kernel use */
+ pr_debug("invalid DMA tag\n");
+ return -EIO;
+ }
+
+ if (cmd->class) {
+ /* not supported in this version */
+ pr_debug("invalid DMA class\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int spu_send_mfc_command(struct spu_context *ctx,
+ struct mfc_dma_command cmd,
+ int *error)
+{
+ *error = ctx->ops->send_mfc_command(ctx, &cmd);
+ if (*error == -EAGAIN) {
+ /* wait for any tag group to complete
+ so we have space for the new command */
+ ctx->ops->set_mfc_query(ctx, ctx->tagwait, 1);
+ /* try again, because the queue might be
+ empty again */
+ *error = ctx->ops->send_mfc_command(ctx, &cmd);
+ if (*error == -EAGAIN)
+ return 0;
+ }
+ return 1;
+}
+
+static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ struct mfc_dma_command cmd;
+ int ret = -EINVAL;
+
+ if (size != sizeof cmd)
+ goto out;
+
+ ret = -EFAULT;
+ if (copy_from_user(&cmd, buffer, sizeof cmd))
+ goto out;
+
+ ret = spufs_check_valid_dma(&cmd);
+ if (ret)
+ goto out;
+
+ spu_acquire_runnable(ctx);
+ if (file->f_flags & O_NONBLOCK) {
+ ret = ctx->ops->send_mfc_command(ctx, &cmd);
+ } else {
+ int status;
+ ret = spufs_wait(ctx->mfc_wq,
+ spu_send_mfc_command(ctx, cmd, &status));
+ if (status)
+ ret = status;
+ }
+ spu_release(ctx);
+
+ if (ret)
+ goto out;
+
+ ctx->tagwait |= 1 << cmd.tag;
+
+out:
+ return ret;
+}
+
+static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait)
+{
+ struct spu_context *ctx = file->private_data;
+ u32 free_elements, tagstatus;
+ unsigned int mask;
+
+ 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;
+ if (tagstatus & ctx->tagwait)
+ mask |= POLLIN | POLLRDNORM;
+
+ pr_debug("%s: free %d tagstatus %d tagwait %d\n", __FUNCTION__,
+ free_elements, tagstatus, ctx->tagwait);
+
+ return mask;
+}
+
+static int spufs_mfc_flush(struct file *file)
+{
+ struct spu_context *ctx = file->private_data;
+ int ret;
+
+ spu_acquire(ctx);
+#if 0
+/* this currently hangs */
+ ret = spufs_wait(ctx->mfc_wq,
+ ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2));
+ if (ret)
+ goto out;
+ ret = spufs_wait(ctx->mfc_wq,
+ ctx->ops->read_mfc_tagstatus(ctx) == ctx->tagwait);
+out:
+#else
+ ret = 0;
+#endif
+ spu_release(ctx);
+
+ return ret;
+}
+
+static int spufs_mfc_fsync(struct file *file, struct dentry *dentry,
+ int datasync)
+{
+ return spufs_mfc_flush(file);
+}
+
+static int spufs_mfc_fasync(int fd, struct file *file, int on)
+{
+ struct spu_context *ctx = file->private_data;
+
+ return fasync_helper(fd, file, on, &ctx->mfc_fasync);
+}
+
+static struct file_operations spufs_mfc_fops = {
+ .open = spufs_mfc_open,
+ .read = spufs_mfc_read,
+ .write = spufs_mfc_write,
+ .poll = spufs_mfc_poll,
+ .flush = spufs_mfc_flush,
+ .fsync = spufs_mfc_fsync,
+ .fasync = spufs_mfc_fasync,
+#ifdef CONFIG_SPUFS_MMAP
+ .mmap = spufs_mfc_mmap,
+#endif
+};
+
static void spufs_npc_set(void *data, u64 val)
{
struct spu_context *ctx = data;
@@ -783,6 +1292,8 @@ struct tree_descr spufs_dir_contents[] = {
{ "signal2", &spufs_signal2_fops, 0666, },
{ "signal1_type", &spufs_signal1_type, 0666, },
{ "signal2_type", &spufs_signal2_type, 0666, },
+ { "mfc", &spufs_mfc_fops, 0666, },
+ { "cntl", &spufs_cntl_fops, 0666, },
{ "npc", &spufs_npc_ops, 0666, },
{ "fpcr", &spufs_fpcr_fops, 0666, },
{ "decr", &spufs_decr_ops, 0666, },
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index 5445719bff7..a13a8b5a014 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -232,6 +232,59 @@ static void spu_hw_runcntl_stop(struct spu_context *ctx)
spin_unlock_irq(&ctx->spu->register_lock);
}
+static int spu_hw_set_mfc_query(struct spu_context * ctx, u32 mask, u32 mode)
+{
+ struct spu_problem *prob = ctx->spu->problem;
+ int ret;
+
+ spin_lock_irq(&ctx->spu->register_lock);
+ ret = -EAGAIN;
+ if (in_be32(&prob->dma_querytype_RW))
+ goto out;
+ ret = 0;
+ out_be32(&prob->dma_querymask_RW, mask);
+ out_be32(&prob->dma_querytype_RW, mode);
+out:
+ spin_unlock_irq(&ctx->spu->register_lock);
+ return ret;
+}
+
+static u32 spu_hw_read_mfc_tagstatus(struct spu_context * ctx)
+{
+ return in_be32(&ctx->spu->problem->dma_tagstatus_R);
+}
+
+static u32 spu_hw_get_mfc_free_elements(struct spu_context *ctx)
+{
+ return in_be32(&ctx->spu->problem->dma_qstatus_R);
+}
+
+static int spu_hw_send_mfc_command(struct spu_context *ctx,
+ struct mfc_dma_command *cmd)
+{
+ u32 status;
+ struct spu_problem *prob = ctx->spu->problem;
+
+ spin_lock_irq(&ctx->spu->register_lock);
+ out_be32(&prob->mfc_lsa_W, cmd->lsa);
+ out_be64(&prob->mfc_ea_W, cmd->ea);
+ out_be32(&prob->mfc_union_W.by32.mfc_size_tag32,
+ cmd->size << 16 | cmd->tag);
+ out_be32(&prob->mfc_union_W.by32.mfc_class_cmd32,
+ cmd->class << 16 | cmd->cmd);
+ status = in_be32(&prob->mfc_union_W.by32.mfc_class_cmd32);
+ spin_unlock_irq(&ctx->spu->register_lock);
+
+ switch (status & 0xffff) {
+ case 0:
+ return 0;
+ case 2:
+ return -EAGAIN;
+ default:
+ return -EINVAL;
+ }
+}
+
struct spu_context_ops spu_hw_ops = {
.mbox_read = spu_hw_mbox_read,
.mbox_stat_read = spu_hw_mbox_stat_read,
@@ -252,4 +305,8 @@ struct spu_context_ops spu_hw_ops = {
.get_ls = spu_hw_get_ls,
.runcntl_write = spu_hw_runcntl_write,
.runcntl_stop = spu_hw_runcntl_stop,
+ .set_mfc_query = spu_hw_set_mfc_query,
+ .read_mfc_tagstatus = spu_hw_read_mfc_tagstatus,
+ .get_mfc_free_elements = spu_hw_get_mfc_free_elements,
+ .send_mfc_command = spu_hw_send_mfc_command,
};
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index b3962c3a034..d9554199afa 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -103,7 +103,7 @@ spufs_setattr(struct dentry *dentry, struct iattr *attr)
static int
spufs_new_file(struct super_block *sb, struct dentry *dentry,
- struct file_operations *fops, int mode,
+ const struct file_operations *fops, int mode,
struct spu_context *ctx)
{
static struct inode_operations spufs_file_iops = {
@@ -241,7 +241,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
inode->i_gid = dir->i_gid;
inode->i_mode &= S_ISGID;
}
- ctx = alloc_spu_context(inode->i_mapping);
+ ctx = alloc_spu_context();
SPUFS_I(inode)->i_ctx = ctx;
if (!ctx)
goto out_iput;
@@ -442,7 +442,7 @@ static struct file_system_type spufs_type = {
.kill_sb = kill_litter_super,
};
-static int spufs_init(void)
+static int __init spufs_init(void)
{
int ret;
ret = -ENOMEM;
@@ -472,7 +472,7 @@ out:
}
module_init(spufs_init);
-static void spufs_exit(void)
+static void __exit spufs_exit(void)
{
spu_sched_exit();
unregister_spu_syscalls(&spufs_calls);
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 18ea8866c61..483c8b76232 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -2,6 +2,7 @@
#include <linux/ptrace.h>
#include <asm/spu.h>
+#include <asm/unistd.h>
#include "spufs.h"
@@ -76,6 +77,90 @@ static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
return 0;
}
+/*
+ * SPU syscall restarting is tricky because we violate the basic
+ * assumption that the signal handler is running on the interrupted
+ * thread. Here instead, the handler runs on PowerPC user space code,
+ * while the syscall was called from the SPU.
+ * This means we can only do a very rough approximation of POSIX
+ * signal semantics.
+ */
+int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret,
+ unsigned int *npc)
+{
+ int ret;
+
+ switch (*spu_ret) {
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ /*
+ * Enter the regular syscall restarting for
+ * sys_spu_run, then restart the SPU syscall
+ * callback.
+ */
+ *npc -= 8;
+ ret = -ERESTARTSYS;
+ break;
+ case -ERESTARTNOHAND:
+ case -ERESTART_RESTARTBLOCK:
+ /*
+ * Restart block is too hard for now, just return -EINTR
+ * to the SPU.
+ * ERESTARTNOHAND comes from sys_pause, we also return
+ * -EINTR from there.
+ * Assume that we need to be restarted ourselves though.
+ */
+ *spu_ret = -EINTR;
+ ret = -ERESTARTSYS;
+ break;
+ default:
+ printk(KERN_WARNING "%s: unexpected return code %ld\n",
+ __FUNCTION__, *spu_ret);
+ ret = 0;
+ }
+ return ret;
+}
+
+int spu_process_callback(struct spu_context *ctx)
+{
+ struct spu_syscall_block s;
+ u32 ls_pointer, npc;
+ char *ls;
+ long spu_ret;
+ int ret;
+
+ /* get syscall block from local store */
+ npc = ctx->ops->npc_read(ctx);
+ ls = ctx->ops->get_ls(ctx);
+ ls_pointer = *(u32*)(ls + npc);
+ if (ls_pointer > (LS_SIZE - sizeof(s)))
+ return -EFAULT;
+ memcpy(&s, ls + ls_pointer, sizeof (s));
+
+ /* do actual syscall without pinning the spu */
+ ret = 0;
+ spu_ret = -ENOSYS;
+ npc += 4;
+
+ if (s.nr_ret < __NR_syscalls) {
+ spu_release(ctx);
+ /* do actual system call from here */
+ spu_ret = spu_sys_callback(&s);
+ if (spu_ret <= -ERESTARTSYS) {
+ ret = spu_handle_restartsys(ctx, &spu_ret, &npc);
+ }
+ spu_acquire(ctx);
+ if (ret == -ERESTARTSYS)
+ return ret;
+ }
+
+ /* write result, jump over indirect pointer */
+ memcpy(ls + ls_pointer, &spu_ret, sizeof (spu_ret));
+ ctx->ops->npc_write(ctx, npc);
+ ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
+ return ret;
+}
+
static inline int spu_process_events(struct spu_context *ctx)
{
struct spu *spu = ctx->spu;
@@ -107,6 +192,13 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
if (unlikely(ret))
break;
+ if ((*status & SPU_STATUS_STOPPED_BY_STOP) &&
+ (*status >> SPU_STOP_STATUS_SHIFT == 0x2104)) {
+ ret = spu_process_callback(ctx);
+ if (ret)
+ break;
+ *status &= ~SPU_STATUS_STOPPED_BY_STOP;
+ }
if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
ret = spu_reacquire_runnable(ctx, npc, status);
if (ret)
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 963182fbd1a..bf652cd7700 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -180,6 +180,7 @@ static inline void bind_context(struct spu *spu, struct spu_context *ctx)
spu->ibox_callback = spufs_ibox_callback;
spu->wbox_callback = spufs_wbox_callback;
spu->stop_callback = spufs_stop_callback;
+ spu->mfc_callback = spufs_mfc_callback;
mb();
spu_unmap_mappings(ctx);
spu_restore(&ctx->csa, spu);
@@ -197,6 +198,7 @@ static inline void unbind_context(struct spu *spu, struct spu_context *ctx)
spu->ibox_callback = NULL;
spu->wbox_callback = NULL;
spu->stop_callback = NULL;
+ spu->mfc_callback = NULL;
spu->mm = NULL;
spu->pid = 0;
spu->prio = MAX_PRIO;
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index db2601f0abd..4485738e210 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -43,7 +43,11 @@ struct spu_context {
struct spu *spu; /* pointer to a physical SPU */
struct spu_state csa; /* SPU context save area. */
spinlock_t mmio_lock; /* protects mmio access */
- struct address_space *local_store;/* local store backing store */
+ struct address_space *local_store; /* local store mapping. */
+ struct address_space *mfc; /* 'mfc' area mappings. */
+ struct address_space *cntl; /* 'control' area mappings. */
+ struct address_space *signal1; /* 'signal1' area mappings. */
+ struct address_space *signal2; /* 'signal2' area mappings. */
enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
struct rw_semaphore state_sema;
@@ -55,13 +59,27 @@ struct spu_context {
wait_queue_head_t ibox_wq;
wait_queue_head_t wbox_wq;
wait_queue_head_t stop_wq;
+ wait_queue_head_t mfc_wq;
struct fasync_struct *ibox_fasync;
struct fasync_struct *wbox_fasync;
+ struct fasync_struct *mfc_fasync;
+ u32 tagwait;
struct spu_context_ops *ops;
struct work_struct reap_work;
u64 flags;
};
+struct mfc_dma_command {
+ int32_t pad; /* reserved */
+ uint32_t lsa; /* local storage address */
+ uint64_t ea; /* effective address */
+ uint16_t size; /* transfer size */
+ uint16_t tag; /* command tag */
+ uint16_t class; /* class ID */
+ uint16_t cmd; /* command opcode */
+};
+
+
/* SPU context query/set operations. */
struct spu_context_ops {
int (*mbox_read) (struct spu_context * ctx, u32 * data);
@@ -84,6 +102,11 @@ struct spu_context_ops {
char*(*get_ls) (struct spu_context * ctx);
void (*runcntl_write) (struct spu_context * ctx, u32 data);
void (*runcntl_stop) (struct spu_context * ctx);
+ int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode);
+ u32 (*read_mfc_tagstatus)(struct spu_context * ctx);
+ u32 (*get_mfc_free_elements)(struct spu_context *ctx);
+ int (*send_mfc_command)(struct spu_context *ctx,
+ struct mfc_dma_command *cmd);
};
extern struct spu_context_ops spu_hw_ops;
@@ -106,7 +129,7 @@ long spufs_create_thread(struct nameidata *nd,
extern struct file_operations spufs_context_fops;
/* context management */
-struct spu_context * alloc_spu_context(struct address_space *local_store);
+struct spu_context * alloc_spu_context(void);
void destroy_spu_context(struct kref *kref);
struct spu_context * get_spu_context(struct spu_context *ctx);
int put_spu_context(struct spu_context *ctx);
@@ -159,5 +182,6 @@ size_t spu_ibox_read(struct spu_context *ctx, u32 *data);
void spufs_ibox_callback(struct spu *spu);
void spufs_wbox_callback(struct spu *spu);
void spufs_stop_callback(struct spu *spu);
+void spufs_mfc_callback(struct spu *spu);
#endif
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 212db28531f..1726bfe38ee 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -1297,7 +1297,7 @@ static inline void setup_decr(struct spu_state *csa, struct spu *spu)
cycles_t resume_time = get_cycles();
cycles_t delta_time = resume_time - csa->suspend_time;
- csa->lscsa->decr.slot[0] = delta_time;
+ csa->lscsa->decr.slot[0] -= delta_time;
}
}
@@ -2145,7 +2145,8 @@ static void init_priv1(struct spu_state *csa)
csa->priv1.int_mask_class1_RW = CLASS1_ENABLE_SEGMENT_FAULT_INTR |
CLASS1_ENABLE_STORAGE_FAULT_INTR;
csa->priv1.int_mask_class2_RW = CLASS2_ENABLE_SPU_STOP_INTR |
- CLASS2_ENABLE_SPU_HALT_INTR;
+ CLASS2_ENABLE_SPU_HALT_INTR |
+ CLASS2_ENABLE_SPU_DMA_TAG_GROUP_COMPLETE_INTR;
}
static void init_priv2(struct spu_state *csa)
diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h
index 814f54742e0..996c28744e9 100644
--- a/arch/powerpc/platforms/chrp/chrp.h
+++ b/arch/powerpc/platforms/chrp/chrp.h
@@ -8,4 +8,5 @@ extern int chrp_set_rtc_time(struct rtc_time *);
extern long chrp_time_init(void);
extern void chrp_find_bridges(void);
-extern void chrp_event_scan(void);
+extern void chrp_event_scan(unsigned long);
+extern void chrp_pcibios_fixup(void);
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 8ef279ad36a..ac224876ce5 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -23,6 +23,8 @@
#include <asm/grackle.h>
#include <asm/rtas.h>
+#include "chrp.h"
+
/* LongTrail */
void __iomem *gg2_pci_config_base;
@@ -314,6 +316,6 @@ chrp_find_bridges(void)
}
/* Do not fixup interrupts from OF tree on pegasos */
- if (is_pegasos == 0)
- ppc_md.pcibios_fixup = chrp_pcibios_fixup;
+ if (is_pegasos)
+ ppc_md.pcibios_fixup = NULL;
}
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 8bf4307e323..18d89f38796 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -35,6 +35,7 @@
#include <linux/root_dev.h>
#include <linux/initrd.h>
#include <linux/module.h>
+#include <linux/timer.h>
#include <asm/io.h>
#include <asm/pgtable.h>
@@ -61,6 +62,10 @@ EXPORT_SYMBOL(_chrp_type);
struct mpic *chrp_mpic;
+/* Used for doing CHRP event-scans */
+DEFINE_PER_CPU(struct timer_list, heartbeat_timer);
+unsigned long event_scan_interval;
+
/*
* XXX this should be in xmon.h, but putting it there means xmon.h
* has to include <linux/interrupt.h> (to get irqreturn_t), which
@@ -229,8 +234,6 @@ void __init chrp_setup_arch(void)
{
struct device_node *root = find_path_device ("/");
char *machine = NULL;
- struct device_node *device;
- unsigned int *p = NULL;
/* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000/HZ;
@@ -287,23 +290,12 @@ void __init chrp_setup_arch(void)
*/
sio_init();
- /* Get the event scan rate for the rtas so we know how
- * often it expects a heartbeat. -- Cort
- */
- device = find_devices("rtas");
- if (device)
- p = (unsigned int *) get_property
- (device, "rtas-event-scan-rate", NULL);
- if (p && *p) {
- ppc_md.heartbeat = chrp_event_scan;
- ppc_md.heartbeat_reset = HZ / (*p * 30) - 1;
- ppc_md.heartbeat_count = 1;
- printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
- *p, ppc_md.heartbeat_reset);
- }
-
pci_create_OF_bus_map();
+#ifdef CONFIG_SMP
+ smp_ops = &chrp_smp_ops;
+#endif /* CONFIG_SMP */
+
/*
* Print the banner, then scroll down so boot progress
* can be printed. -- Cort
@@ -312,7 +304,7 @@ void __init chrp_setup_arch(void)
}
void
-chrp_event_scan(void)
+chrp_event_scan(unsigned long unused)
{
unsigned char log[1024];
int ret = 0;
@@ -320,7 +312,8 @@ chrp_event_scan(void)
/* XXX: we should loop until the hardware says no more error logs -- Cort */
rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0,
__pa(log), 1024);
- ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+ mod_timer(&__get_cpu_var(heartbeat_timer),
+ jiffies + event_scan_interval);
}
/*
@@ -447,8 +440,6 @@ void __init chrp_init_IRQ(void)
if (_chrp_type == _CHRP_Pegasos)
ppc_md.get_irq = i8259_irq;
- else
- ppc_md.get_irq = mpic_get_irq;
#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
/* see if there is a keyboard in the device tree
@@ -465,6 +456,9 @@ void __init chrp_init_IRQ(void)
void __init
chrp_init2(void)
{
+ struct device_node *device;
+ unsigned int *p = NULL;
+
#ifdef CONFIG_NVRAM
chrp_nvram_init();
#endif
@@ -476,12 +470,53 @@ chrp_init2(void)
request_region(0x80,0x10,"dma page reg");
request_region(0xc0,0x20,"dma2");
+ /* Get the event scan rate for the rtas so we know how
+ * often it expects a heartbeat. -- Cort
+ */
+ device = find_devices("rtas");
+ if (device)
+ p = (unsigned int *) get_property
+ (device, "rtas-event-scan-rate", NULL);
+ if (p && *p) {
+ /*
+ * Arrange to call chrp_event_scan at least *p times
+ * per minute. We use 59 rather than 60 here so that
+ * the rate will be slightly higher than the minimum.
+ * This all assumes we don't do hotplug CPU on any
+ * machine that needs the event scans done.
+ */
+ unsigned long interval, offset;
+ int cpu, ncpus;
+ struct timer_list *timer;
+
+ interval = HZ * 59 / *p;
+ offset = HZ;
+ ncpus = num_online_cpus();
+ event_scan_interval = ncpus * interval;
+ for (cpu = 0; cpu < ncpus; ++cpu) {
+ timer = &per_cpu(heartbeat_timer, cpu);
+ setup_timer(timer, chrp_event_scan, 0);
+ timer->expires = jiffies + offset;
+ add_timer_on(timer, cpu);
+ offset += interval;
+ }
+ printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
+ *p, interval);
+ }
+
if (ppc_md.progress)
ppc_md.progress(" Have fun! ", 0x7777);
}
-void __init chrp_init(void)
+static int __init chrp_probe(void)
{
+ char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
+ "device_type", NULL);
+ if (dtype == NULL)
+ return 0;
+ if (strcmp(dtype, "chrp"))
+ return 0;
+
ISA_DMA_THRESHOLD = ~0L;
DMA_MODE_READ = 0x44;
DMA_MODE_WRITE = 0x48;
@@ -491,26 +526,24 @@ void __init chrp_init(void)
/* Assume we have an 8259... */
__irq_offset_value = NUM_ISA_INTERRUPTS;
- ppc_md.setup_arch = chrp_setup_arch;
- ppc_md.show_cpuinfo = chrp_show_cpuinfo;
-
- ppc_md.init_IRQ = chrp_init_IRQ;
- ppc_md.init = chrp_init2;
-
- ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
-
- ppc_md.restart = rtas_restart;
- ppc_md.power_off = rtas_power_off;
- ppc_md.halt = rtas_halt;
-
- ppc_md.time_init = chrp_time_init;
- ppc_md.calibrate_decr = generic_calibrate_decr;
-
- /* this may get overridden with rtas routines later... */
- ppc_md.set_rtc_time = chrp_set_rtc_time;
- ppc_md.get_rtc_time = chrp_get_rtc_time;
-
-#ifdef CONFIG_SMP
- smp_ops = &chrp_smp_ops;
-#endif /* CONFIG_SMP */
+ return 1;
}
+
+define_machine(chrp) {
+ .name = "CHRP",
+ .probe = chrp_probe,
+ .setup_arch = chrp_setup_arch,
+ .init = chrp_init2,
+ .show_cpuinfo = chrp_show_cpuinfo,
+ .init_IRQ = chrp_init_IRQ,
+ .get_irq = mpic_get_irq,
+ .pcibios_fixup = chrp_pcibios_fixup,
+ .restart = rtas_restart,
+ .power_off = rtas_power_off,
+ .halt = rtas_halt,
+ .time_init = chrp_time_init,
+ .set_rtc_time = chrp_set_rtc_time,
+ .get_rtc_time = chrp_get_rtc_time,
+ .calibrate_decr = generic_calibrate_decr,
+ .phys_mem_access_prot = pci_phys_mem_access_prot,
+};
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c
index 12c6f689b1a..7d788902693 100644
--- a/arch/powerpc/platforms/chrp/time.c
+++ b/arch/powerpc/platforms/chrp/time.c
@@ -120,33 +120,15 @@ int chrp_set_rtc_time(struct rtc_time *tmarg)
void chrp_get_rtc_time(struct rtc_time *tm)
{
unsigned int year, mon, day, hour, min, sec;
- int uip, i;
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
-
- /* Since the UIP flag is set for about 2.2 ms and the clock
- * is typically written with a precision of 1 jiffy, trying
- * to obtain a precision better than a few milliseconds is
- * an illusion. Only consistency is interesting, this also
- * allows to use the routine for /dev/rtc without a potential
- * 1 second kernel busy loop triggered by any reader of /dev/rtc.
- */
-
- for ( i = 0; i<1000000; i++) {
- uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
+ do {
sec = chrp_cmos_clock_read(RTC_SECONDS);
min = chrp_cmos_clock_read(RTC_MINUTES);
hour = chrp_cmos_clock_read(RTC_HOURS);
day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
mon = chrp_cmos_clock_read(RTC_MONTH);
year = chrp_cmos_clock_read(RTC_YEAR);
- uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
- if ((uip & RTC_UIP)==0) break;
- }
+ } while (sec != chrp_cmos_clock_read(RTC_SECONDS));
if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
BCD_TO_BIN(sec);
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index fa4550611c1..a6fd9bedb07 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -54,6 +54,7 @@
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/lpar_map.h>
#include <asm/udbg.h>
+#include <asm/irq.h>
#include "naca.h"
#include "setup.h"
@@ -675,18 +676,26 @@ static void iseries_dedicated_idle(void)
void __init iSeries_init_IRQ(void) { }
#endif
-static int __init iseries_probe(int platform)
+static int __init iseries_probe(void)
{
- if (PLATFORM_ISERIES_LPAR != platform)
+ unsigned long root = of_get_flat_dt_root();
+ if (!of_flat_dt_is_compatible(root, "IBM,iSeries"))
return 0;
- ppc64_firmware_features |= FW_FEATURE_ISERIES;
- ppc64_firmware_features |= FW_FEATURE_LPAR;
+ powerpc_firmware_features |= FW_FEATURE_ISERIES;
+ powerpc_firmware_features |= FW_FEATURE_LPAR;
+
+ /*
+ * The Hypervisor only allows us up to 256 interrupt
+ * sources (the irq number is passed in a u8).
+ */
+ virt_irq_max = 255;
return 1;
}
-struct machdep_calls __initdata iseries_md = {
+define_machine(iseries) {
+ .name = "iSeries",
.setup_arch = iSeries_setup_arch,
.show_cpuinfo = iSeries_show_cpuinfo,
.init_IRQ = iSeries_init_IRQ,
@@ -930,7 +939,6 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
/* /chosen */
dt_start_node(dt, "chosen");
- dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR);
dt_prop_str(dt, "bootargs", cmd_line);
if (cmd_mem_limit)
dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index ec5c1e10c40..24c0aef4ea3 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -259,9 +259,10 @@ static void __init maple_progress(char *s, unsigned short hex)
/*
* Called very early, MMU is off, device-tree isn't unflattened
*/
-static int __init maple_probe(int platform)
+static int __init maple_probe(void)
{
- if (platform != PLATFORM_MAPLE)
+ unsigned long root = of_get_flat_dt_root();
+ if (!of_flat_dt_is_compatible(root, "Momentum,Maple"))
return 0;
/*
* On U3, the DART (iommu) must be allocated now since it
@@ -274,7 +275,8 @@ static int __init maple_probe(int platform)
return 1;
}
-struct machdep_calls __initdata maple_md = {
+define_machine(maple_md) {
+ .name = "Maple",
.probe = maple_probe,
.setup_arch = maple_setup_arch,
.init_early = maple_init_early,
@@ -290,7 +292,7 @@ struct machdep_calls __initdata maple_md = {
.get_rtc_time = maple_get_rtc_time,
.calibrate_decr = generic_calibrate_decr,
.progress = maple_progress,
- .idle_loop = native_idle,
+ .power_save = power4_idle,
#ifdef CONFIG_KEXEC
.machine_kexec = default_machine_kexec,
.machine_kexec_prepare = default_machine_kexec_prepare,
diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c
index 5e6981d1737..b9a2b3d4bf3 100644
--- a/arch/powerpc/platforms/maple/time.c
+++ b/arch/powerpc/platforms/maple/time.c
@@ -60,34 +60,14 @@ static void maple_clock_write(unsigned long val, int addr)
void maple_get_rtc_time(struct rtc_time *tm)
{
- int uip, i;
-
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
-
- /* Since the UIP flag is set for about 2.2 ms and the clock
- * is typically written with a precision of 1 jiffy, trying
- * to obtain a precision better than a few milliseconds is
- * an illusion. Only consistency is interesting, this also
- * allows to use the routine for /dev/rtc without a potential
- * 1 second kernel busy loop triggered by any reader of /dev/rtc.
- */
-
- for (i = 0; i<1000000; i++) {
- uip = maple_clock_read(RTC_FREQ_SELECT);
+ do {
tm->tm_sec = maple_clock_read(RTC_SECONDS);
tm->tm_min = maple_clock_read(RTC_MINUTES);
tm->tm_hour = maple_clock_read(RTC_HOURS);
tm->tm_mday = maple_clock_read(RTC_DAY_OF_MONTH);
tm->tm_mon = maple_clock_read(RTC_MONTH);
tm->tm_year = maple_clock_read(RTC_YEAR);
- uip |= maple_clock_read(RTC_FREQ_SELECT);
- if ((uip & RTC_UIP)==0)
- break;
- }
+ } while (tm->tm_sec != maple_clock_read(RTC_SECONDS));
if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY)
|| RTC_ALWAYS_BCD) {
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c
index fa8b4d7b5de..eacbfd9beab 100644
--- a/arch/powerpc/platforms/powermac/bootx_init.c
+++ b/arch/powerpc/platforms/powermac/bootx_init.c
@@ -161,9 +161,7 @@ static void __init bootx_dt_add_prop(char *name, void *data, int size,
static void __init bootx_add_chosen_props(unsigned long base,
unsigned long *mem_end)
{
- u32 val = _MACH_Pmac;
-
- bootx_dt_add_prop("linux,platform", &val, 4, mem_end);
+ u32 val;
if (bootx_info->kernelParamsOffset) {
char *args = (char *)((unsigned long)bootx_info) +
@@ -493,7 +491,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4)
&& (strcmp(model, "iMac,1") == 0
|| strcmp(model, "PowerMac1,1") == 0)) {
bootx_printf("iMac,1 detected, shutting down USB \n");
- out_le32((unsigned *)0x80880008, 1); /* XXX */
+ out_le32((unsigned __iomem *)0x80880008, 1); /* XXX */
}
}
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index e49eddd5042..a5063cd675c 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -2951,7 +2951,7 @@ static void *pmac_early_vresume_data;
void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
{
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return;
preempt_disable();
pmac_early_vresume_proc = proc;
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 87eb6bb7f0e..c896ce83d41 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -231,6 +231,14 @@ static u8 kw_i2c_wait_interrupt(struct pmac_i2c_host_kw *host)
return isr;
}
+static void kw_i2c_do_stop(struct pmac_i2c_host_kw *host, int result)
+{
+ kw_write_reg(reg_control, KW_I2C_CTL_STOP);
+ host->state = state_stop;
+ host->result = result;
+}
+
+
static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr)
{
u8 ack;
@@ -246,42 +254,36 @@ static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr)
}
if (isr == 0) {
+ printk(KERN_WARNING "low_i2c: Timeout in i2c transfer"
+ " on keywest !\n");
if (host->state != state_stop) {
- DBG_LOW("KW: Timeout !\n");
- host->result = -EIO;
- goto stop;
- }
- if (host->state == state_stop) {
- ack = kw_read_reg(reg_status);
- if (ack & KW_I2C_STAT_BUSY)
- kw_write_reg(reg_status, 0);
- host->state = state_idle;
- kw_write_reg(reg_ier, 0x00);
- if (!host->polled)
- complete(&host->complete);
+ kw_i2c_do_stop(host, -EIO);
+ return;
}
+ ack = kw_read_reg(reg_status);
+ if (ack & KW_I2C_STAT_BUSY)
+ kw_write_reg(reg_status, 0);
+ host->state = state_idle;
+ kw_write_reg(reg_ier, 0x00);
+ if (!host->polled)
+ complete(&host->complete);
return;
}
if (isr & KW_I2C_IRQ_ADDR) {
ack = kw_read_reg(reg_status);
if (host->state != state_addr) {
- kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
WRONG_STATE("KW_I2C_IRQ_ADDR");
- host->result = -EIO;
- goto stop;
+ kw_i2c_do_stop(host, -EIO);
}
if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
- host->result = -ENODEV;
- DBG_LOW("KW: NAK on address\n");
+ host->result = -ENXIO;
host->state = state_stop;
- return;
+ DBG_LOW("KW: NAK on address\n");
} else {
- if (host->len == 0) {
- kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
- goto stop;
- }
- if (host->rw) {
+ if (host->len == 0)
+ kw_i2c_do_stop(host, 0);
+ else if (host->rw) {
host->state = state_read;
if (host->len > 1)
kw_write_reg(reg_control,
@@ -308,25 +310,19 @@ static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr)
ack = kw_read_reg(reg_status);
if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
DBG_LOW("KW: nack on data write\n");
- host->result = -EIO;
- goto stop;
+ host->result = -EFBIG;
+ host->state = state_stop;
} else if (host->len) {
kw_write_reg(reg_data, *(host->data++));
host->len--;
- } else {
- kw_write_reg(reg_control, KW_I2C_CTL_STOP);
- host->state = state_stop;
- host->result = 0;
- }
- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+ } else
+ kw_i2c_do_stop(host, 0);
} else {
- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
WRONG_STATE("KW_I2C_IRQ_DATA");
- if (host->state != state_stop) {
- host->result = -EIO;
- goto stop;
- }
+ if (host->state != state_stop)
+ kw_i2c_do_stop(host, -EIO);
}
+ kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
}
if (isr & KW_I2C_IRQ_STOP) {
@@ -340,14 +336,10 @@ static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr)
complete(&host->complete);
}
+ /* Below should only happen in manual mode which we don't use ... */
if (isr & KW_I2C_IRQ_START)
kw_write_reg(reg_isr, KW_I2C_IRQ_START);
- return;
- stop:
- kw_write_reg(reg_control, KW_I2C_CTL_STOP);
- host->state = state_stop;
- return;
}
/* Interrupt handler */
@@ -544,11 +536,11 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np)
return NULL;
}
- /* Make sure IRA is disabled */
+ /* Make sure IRQ is disabled */
kw_write_reg(reg_ier, 0);
/* Request chip interrupt */
- if (request_irq(host->irq, kw_i2c_irq, SA_SHIRQ, "keywest i2c", host))
+ if (request_irq(host->irq, kw_i2c_irq, 0, "keywest i2c", host))
host->irq = NO_IRQ;
printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %s\n",
@@ -1165,6 +1157,7 @@ EXPORT_SYMBOL_GPL(pmac_i2c_xfer);
/* some quirks for platform function decoding */
enum {
pmac_i2c_quirk_invmask = 0x00000001u,
+ pmac_i2c_quirk_skip = 0x00000002u,
};
static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
@@ -1180,6 +1173,15 @@ static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
/* XXX Study device-tree's & apple drivers are get the quirks
* right !
*/
+ /* Workaround: It seems that running the clockspreading
+ * properties on the eMac will cause lockups during boot.
+ * The machine seems to work fine without that. So for now,
+ * let's make sure i2c-hwclock doesn't match about "imic"
+ * clocks and we'll figure out if we really need to do
+ * something special about those later.
+ */
+ { "i2c-hwclock", "imic5002", pmac_i2c_quirk_skip },
+ { "i2c-hwclock", "imic5003", pmac_i2c_quirk_skip },
{ "i2c-hwclock", NULL, pmac_i2c_quirk_invmask },
{ "i2c-cpu-voltage", NULL, 0},
{ "temp-monitor", NULL, 0 },
@@ -1206,6 +1208,8 @@ static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
if (p->compatible &&
!device_is_compatible(np, p->compatible))
continue;
+ if (p->quirks & pmac_i2c_quirk_skip)
+ break;
callback(np, p->quirks);
break;
}
@@ -1457,6 +1461,9 @@ int __init pmac_i2c_init(void)
return 0;
i2c_inited = 1;
+ if (!machine_is(powermac))
+ return 0;
+
/* Probe keywest-i2c busses */
kw_i2c_probe();
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c
index 5fd28995c74..262f967b880 100644
--- a/arch/powerpc/platforms/powermac/nvram.c
+++ b/arch/powerpc/platforms/powermac/nvram.c
@@ -74,7 +74,7 @@ struct core99_header {
* Read and write the non-volatile RAM on PowerMacs and CHRP machines.
*/
static int nvram_naddrs;
-static volatile unsigned char *nvram_data;
+static volatile unsigned char __iomem *nvram_data;
static int is_core_99;
static int core99_bank = 0;
static int nvram_partitions[3];
@@ -148,7 +148,7 @@ static ssize_t core99_nvram_size(void)
}
#ifdef CONFIG_PPC32
-static volatile unsigned char *nvram_addr;
+static volatile unsigned char __iomem *nvram_addr;
static int nvram_mult;
static unsigned char direct_nvram_read_byte(int addr)
@@ -285,7 +285,7 @@ static int sm_erase_bank(int bank)
int stat, i;
unsigned long timeout;
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+ u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
@@ -317,7 +317,7 @@ static int sm_write_bank(int bank, u8* datas)
int i, stat = 0;
unsigned long timeout;
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+ u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
@@ -352,7 +352,7 @@ static int amd_erase_bank(int bank)
int i, stat = 0;
unsigned long timeout;
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+ u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
DBG("nvram: AMD Erasing bank %d...\n", bank);
@@ -399,7 +399,7 @@ static int amd_write_bank(int bank, u8* datas)
int i, stat = 0;
unsigned long timeout;
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+ u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
DBG("nvram: AMD Writing bank %d...\n", bank);
@@ -597,7 +597,7 @@ int __init pmac_nvram_init(void)
}
#ifdef CONFIG_PPC32
- if (_machine == _MACH_chrp && nvram_naddrs == 1) {
+ if (machine_is(chrp) && nvram_naddrs == 1) {
nvram_data = ioremap(r1.start, s1);
nvram_mult = 1;
ppc_md.nvram_read_val = direct_nvram_read_byte;
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index de3f30e6b33..ea179afea63 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -1097,7 +1097,7 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
* (iBook second controller)
*/
if (dev->vendor == PCI_VENDOR_ID_APPLE
- && (dev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10))
+ && dev->class == PCI_CLASS_SERIAL_USB_OHCI
&& !node) {
printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n",
pci_name(dev));
@@ -1201,7 +1201,7 @@ void __init pmac_pcibios_after_init(void)
#ifdef CONFIG_PPC32
void pmac_pci_fixup_cardbus(struct pci_dev* dev)
{
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return;
/*
* Fix the interrupt routing on the various cardbus bridges
@@ -1244,8 +1244,9 @@ void pmac_pci_fixup_pciata(struct pci_dev* dev)
* On PowerMacs, we try to switch any PCI ATA controller to
* fully native mode
*/
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return;
+
/* Some controllers don't have the class IDE */
if (dev->vendor == PCI_VENDOR_ID_PROMISE)
switch(dev->device) {
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c
index 9b7150f1041..a3bd3e728fa 100644
--- a/arch/powerpc/platforms/powermac/pfunc_base.c
+++ b/arch/powerpc/platforms/powermac/pfunc_base.c
@@ -336,6 +336,8 @@ int __init pmac_pfunc_base_install(void)
return 0;
pfbase_inited = 1;
+ if (!machine_is(powermac))
+ return 0;
DBG("Installing base platform functions...\n");
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index 4baa75b1d36..f08173b0f06 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <asm/semaphore.h>
#include <asm/prom.h>
@@ -546,6 +547,7 @@ struct pmf_device {
static LIST_HEAD(pmf_devices);
static spinlock_t pmf_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_MUTEX(pmf_irq_mutex);
static void pmf_release_device(struct kref *kref)
{
@@ -864,15 +866,17 @@ int pmf_register_irq_client(struct device_node *target,
spin_lock_irqsave(&pmf_lock, flags);
func = __pmf_find_function(target, name, PMF_FLAGS_INT_GEN);
- if (func == NULL) {
- spin_unlock_irqrestore(&pmf_lock, flags);
+ if (func)
+ func = pmf_get_function(func);
+ spin_unlock_irqrestore(&pmf_lock, flags);
+ if (func == NULL)
return -ENODEV;
- }
+ mutex_lock(&pmf_irq_mutex);
if (list_empty(&func->irq_clients))
func->dev->handlers->irq_enable(func);
list_add(&client->link, &func->irq_clients);
client->func = func;
- spin_unlock_irqrestore(&pmf_lock, flags);
+ mutex_unlock(&pmf_irq_mutex);
return 0;
}
@@ -881,16 +885,16 @@ EXPORT_SYMBOL_GPL(pmf_register_irq_client);
void pmf_unregister_irq_client(struct pmf_irq_client *client)
{
struct pmf_function *func = client->func;
- unsigned long flags;
BUG_ON(func == NULL);
- spin_lock_irqsave(&pmf_lock, flags);
+ mutex_lock(&pmf_irq_mutex);
client->func = NULL;
list_del(&client->link);
if (list_empty(&func->irq_clients))
func->dev->handlers->irq_disable(func);
- spin_unlock_irqrestore(&pmf_lock, flags);
+ mutex_unlock(&pmf_irq_mutex);
+ pmf_put_function(func);
}
EXPORT_SYMBOL_GPL(pmf_unregister_irq_client);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 385aab90c4d..b9200fb0781 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -350,6 +350,13 @@ static void __init pmac_setup_arch(void)
smp_ops = &psurge_smp_ops;
#endif
#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_ADB
+ if (strstr(cmd_line, "adb_sync")) {
+ extern int __adb_probe_sync;
+ __adb_probe_sync = 1;
+ }
+#endif /* CONFIG_ADB */
}
char *bootpath;
@@ -456,11 +463,23 @@ static int pmac_pm_finish(suspend_state_t state)
return 0;
}
+static int pmac_pm_valid(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_DISK:
+ return 1;
+ /* can't do any other states via generic mechanism yet */
+ default:
+ return 0;
+ }
+}
+
static struct pm_ops pmac_pm_ops = {
.pm_disk_mode = PM_DISK_SHUTDOWN,
.prepare = pmac_pm_prepare,
.enter = pmac_pm_enter,
.finish = pmac_pm_finish,
+ .valid = pmac_pm_valid,
};
#endif /* CONFIG_SOFTWARE_SUSPEND */
@@ -576,30 +595,6 @@ pmac_halt(void)
pmac_power_off();
}
-#ifdef CONFIG_PPC32
-void __init pmac_init(void)
-{
- /* isa_io_base gets set in pmac_pci_init */
- isa_mem_base = PMAC_ISA_MEM_BASE;
- pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
- ISA_DMA_THRESHOLD = ~0L;
- DMA_MODE_READ = 1;
- DMA_MODE_WRITE = 2;
-
- ppc_md = pmac_md;
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
- ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
- ppc_ide_md.default_io_base = pmac_ide_get_base;
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
-#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
-
- if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
-
-}
-#endif
-
/*
* Early initialization.
*/
@@ -646,6 +641,12 @@ static int __init pmac_declare_of_platform_devices(void)
{
struct device_node *np;
+ if (machine_is(chrp))
+ return -1;
+
+ if (!machine_is(powermac))
+ return 0;
+
np = of_find_node_by_name(NULL, "valkyrie");
if (np)
of_platform_device_create(np, "valkyrie", NULL);
@@ -666,12 +667,15 @@ device_initcall(pmac_declare_of_platform_devices);
/*
* Called very early, MMU is off, device-tree isn't unflattened
*/
-static int __init pmac_probe(int platform)
+static int __init pmac_probe(void)
{
-#ifdef CONFIG_PPC64
- if (platform != PLATFORM_POWERMAC)
+ unsigned long root = of_get_flat_dt_root();
+
+ if (!of_flat_dt_is_compatible(root, "Power Macintosh") &&
+ !of_flat_dt_is_compatible(root, "MacRISC"))
return 0;
+#ifdef CONFIG_PPC64
/*
* On U3, the DART (iommu) must be allocated now since it
* has an impact on htab_initialize (due to the large page it
@@ -681,6 +685,23 @@ static int __init pmac_probe(int platform)
alloc_dart_table();
#endif
+#ifdef CONFIG_PPC32
+ /* isa_io_base gets set in pmac_pci_init */
+ isa_mem_base = PMAC_ISA_MEM_BASE;
+ pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = ~0L;
+ DMA_MODE_READ = 1;
+ DMA_MODE_WRITE = 2;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
+ ppc_ide_md.default_io_base = pmac_ide_get_base;
+#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
+
+#endif /* CONFIG_PPC32 */
+
#ifdef CONFIG_PMAC_SMU
/*
* SMU based G5s need some memory below 2Gb, at least the current
@@ -709,10 +730,8 @@ static int pmac_pci_probe_mode(struct pci_bus *bus)
}
#endif
-struct machdep_calls __initdata pmac_md = {
-#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
- .cpu_die = generic_mach_cpu_die,
-#endif
+define_machine(powermac) {
+ .name = "PowerMac",
.probe = pmac_probe,
.setup_arch = pmac_setup_arch,
.init_early = pmac_init_early,
@@ -733,7 +752,7 @@ struct machdep_calls __initdata pmac_md = {
.progress = udbg_progress,
#ifdef CONFIG_PPC64
.pci_probe_mode = pmac_pci_probe_mode,
- .idle_loop = native_idle,
+ .power_save = power4_idle,
.enable_pmcs = power4_enable_pmcs,
#ifdef CONFIG_KEXEC
.machine_kexec = default_machine_kexec,
@@ -746,4 +765,7 @@ struct machdep_calls __initdata pmac_md = {
.pcibios_after_init = pmac_pcibios_after_init,
.phys_mem_access_prot = pci_phys_mem_access_prot,
#endif
+#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
+ .cpu_die = generic_mach_cpu_die,
+#endif
};
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index 5d9afa1fa02..890758aa966 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -336,10 +336,10 @@ static struct pmu_sleep_notifier time_sleep_notifier = {
*/
void __init pmac_calibrate_decr(void)
{
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && defined(CONFIG_ADB_PMU)
/* XXX why here? */
pmu_register_sleep_notifier(&time_sleep_notifier);
-#endif /* CONFIG_PM */
+#endif
generic_calibrate_decr();
diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c
index c4352a8db64..b4fa9f03b46 100644
--- a/arch/powerpc/platforms/powermac/udbg_scc.c
+++ b/arch/powerpc/platforms/powermac/udbg_scc.c
@@ -116,7 +116,7 @@ void udbg_scc_init(int force_scc)
/* Setup for 57600 8N1 */
if (ch == ch_a)
addr += 0x20;
- sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
+ sccc = ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
sccc += addr & ~PAGE_MASK;
sccd = sccc + 0x10;
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 2ab9dcdfb41..32eaddfa547 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -865,7 +865,7 @@ void __init eeh_init(void)
* on the CEC architecture, type of the device, on earlier boot
* command-line arguments & etc.
*/
-void eeh_add_device_early(struct device_node *dn)
+static void eeh_add_device_early(struct device_node *dn)
{
struct pci_controller *phb;
struct eeh_early_enable_info info;
@@ -882,7 +882,6 @@ void eeh_add_device_early(struct device_node *dn)
info.buid_lo = BUID_LO(phb->buid);
early_enable_eeh(dn, &info);
}
-EXPORT_SYMBOL_GPL(eeh_add_device_early);
void eeh_add_device_tree_early(struct device_node *dn)
{
@@ -893,20 +892,6 @@ void eeh_add_device_tree_early(struct device_node *dn)
}
EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
-void eeh_add_device_tree_late(struct pci_bus *bus)
-{
- struct pci_dev *dev;
-
- list_for_each_entry(dev, &bus->devices, bus_list) {
- eeh_add_device_late(dev);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- struct pci_bus *subbus = dev->subordinate;
- if (subbus)
- eeh_add_device_tree_late(subbus);
- }
- }
-}
-
/**
* eeh_add_device_late - perform EEH initialization for the indicated pci device
* @dev: pci device for which to set up EEH
@@ -914,7 +899,7 @@ void eeh_add_device_tree_late(struct pci_bus *bus)
* This routine must be used to complete EEH initialization for PCI
* devices that were added after system boot (e.g. hotplug, dlpar).
*/
-void eeh_add_device_late(struct pci_dev *dev)
+static void eeh_add_device_late(struct pci_dev *dev)
{
struct device_node *dn;
struct pci_dn *pdn;
@@ -933,16 +918,33 @@ void eeh_add_device_late(struct pci_dev *dev)
pci_addr_cache_insert_device (dev);
}
-EXPORT_SYMBOL_GPL(eeh_add_device_late);
+
+void eeh_add_device_tree_late(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ eeh_add_device_late(dev);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ struct pci_bus *subbus = dev->subordinate;
+ if (subbus)
+ eeh_add_device_tree_late(subbus);
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
/**
* eeh_remove_device - undo EEH setup for the indicated pci device
* @dev: pci device to be removed
*
- * This routine should be when a device is removed from a running
- * system (e.g. by hotplug or dlpar).
+ * This routine should be called when a device is removed from
+ * a running system (e.g. by hotplug or dlpar). It unregisters
+ * the PCI device from the EEH subsystem. I/O errors affecting
+ * this device will no longer be detected after this call; thus,
+ * i/o errors affecting this slot may leave this device unusable.
*/
-void eeh_remove_device(struct pci_dev *dev)
+static void eeh_remove_device(struct pci_dev *dev)
{
struct device_node *dn;
if (!dev || !eeh_subsystem_enabled)
@@ -955,24 +957,22 @@ void eeh_remove_device(struct pci_dev *dev)
pci_addr_cache_remove_device(dev);
dn = pci_device_to_OF_node(dev);
- PCI_DN(dn)->pcidev = NULL;
- pci_dev_put (dev);
+ if (PCI_DN(dn)->pcidev) {
+ PCI_DN(dn)->pcidev = NULL;
+ pci_dev_put (dev);
+ }
}
-EXPORT_SYMBOL_GPL(eeh_remove_device);
void eeh_remove_bus_device(struct pci_dev *dev)
{
+ struct pci_bus *bus = dev->subordinate;
+ struct pci_dev *child, *tmp;
+
eeh_remove_device(dev);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- struct pci_bus *bus = dev->subordinate;
- struct list_head *ln;
- if (!bus)
- return;
- for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
- struct pci_dev *pdev = pci_dev_b(ln);
- if (pdev)
- eeh_remove_bus_device(pdev);
- }
+
+ if (bus && dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
+ eeh_remove_bus_device(child);
}
}
EXPORT_SYMBOL_GPL(eeh_remove_bus_device);
@@ -1018,7 +1018,7 @@ static int __init eeh_init_proc(void)
{
struct proc_dir_entry *e;
- if (platform_is_pseries()) {
+ if (machine_is(pseries)) {
e = create_proc_entry("ppc64/eeh", 0, NULL);
if (e)
e->proc_fops = &proc_eeh_operations;
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index b811d5ff92f..1fba695e32e 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -257,6 +257,7 @@ void handle_eeh_events (struct eeh_event *event)
struct pci_bus *frozen_bus;
int rc = 0;
enum pci_ers_result result = PCI_ERS_RESULT_NONE;
+ const char *pci_str, *drv_str;
frozen_dn = find_device_pe(event->dn);
frozen_bus = pcibios_find_pci_bus(frozen_dn);
@@ -291,9 +292,17 @@ void handle_eeh_events (struct eeh_event *event)
frozen_pdn = PCI_DN(frozen_dn);
frozen_pdn->eeh_freeze_count++;
+
+ if (frozen_pdn->pcidev) {
+ pci_str = pci_name (frozen_pdn->pcidev);
+ drv_str = pcid_name (frozen_pdn->pcidev);
+ } else {
+ pci_str = pci_name (event->dev);
+ drv_str = pcid_name (event->dev);
+ }
if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
- goto hard_fail;
+ goto excess_failures;
/* If the reset state is a '5' and the time to reset is 0 (infinity)
* or is more then 15 seconds, then mark this as a permanent failure.
@@ -306,9 +315,7 @@ void handle_eeh_events (struct eeh_event *event)
eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */);
printk(KERN_WARNING
"EEH: This PCI device has failed %d times since last reboot: %s - %s\n",
- frozen_pdn->eeh_freeze_count,
- pci_name (frozen_pdn->pcidev),
- pcid_name(frozen_pdn->pcidev));
+ frozen_pdn->eeh_freeze_count, drv_str, pci_str);
/* Walk the various device drivers attached to this slot through
* a reset sequence, giving each an opportunity to do what it needs
@@ -350,7 +357,7 @@ void handle_eeh_events (struct eeh_event *event)
return;
-hard_fail:
+excess_failures:
/*
* About 90% of all real-life EEH failures in the field
* are due to poorly seated PCI cards. Only 10% or so are
@@ -360,10 +367,16 @@ hard_fail:
"EEH: PCI device %s - %s has failed %d times \n"
"and has been permanently disabled. Please try reseating\n"
"this device or replacing it.\n",
- pci_name (frozen_pdn->pcidev),
- pcid_name(frozen_pdn->pcidev),
- frozen_pdn->eeh_freeze_count);
+ drv_str, pci_str, frozen_pdn->eeh_freeze_count);
+ goto perm_error;
+
+hard_fail:
+ printk(KERN_ERR
+ "EEH: Unable to recover from failure of PCI device %s - %s\n"
+ "Please try reseating this device or replacing it.\n",
+ drv_str, pci_str);
+perm_error:
eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
/* Notify all devices that they're about to go down. */
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index 9a9961f2748..40020c65c89 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -19,7 +19,9 @@
*/
#include <linux/list.h>
+#include <linux/mutex.h>
#include <linux/pci.h>
+#include <linux/workqueue.h>
#include <asm/eeh_event.h>
#include <asm/ppc-pci.h>
@@ -37,14 +39,18 @@ LIST_HEAD(eeh_eventlist);
static void eeh_thread_launcher(void *);
DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL);
+/* Serialize reset sequences for a given pci device */
+DEFINE_MUTEX(eeh_event_mutex);
+
/**
- * eeh_event_handler - dispatch EEH events. The detection of a frozen
- * slot can occur inside an interrupt, where it can be hard to do
- * anything about it. The goal of this routine is to pull these
- * detection events out of the context of the interrupt handler, and
- * re-dispatch them for processing at a later time in a normal context.
- *
+ * eeh_event_handler - dispatch EEH events.
* @dummy - unused
+ *
+ * The detection of a frozen slot can occur inside an interrupt,
+ * where it can be hard to do anything about it. The goal of this
+ * routine is to pull these detection events out of the context
+ * of the interrupt handler, and re-dispatch them for processing
+ * at a later time in a normal context.
*/
static int eeh_event_handler(void * dummy)
{
@@ -64,23 +70,24 @@ static int eeh_event_handler(void * dummy)
event = list_entry(eeh_eventlist.next, struct eeh_event, list);
list_del(&event->list);
}
-
- if (event)
- eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
-
spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
+
if (event == NULL)
break;
+ /* Serialize processing of EEH events */
+ mutex_lock(&eeh_event_mutex);
+ eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
+
printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
pci_name(event->dev));
handle_eeh_events(event);
eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
-
pci_dev_put(event->dev);
kfree(event);
+ mutex_unlock(&eeh_event_mutex);
}
return 0;
@@ -88,7 +95,6 @@ static int eeh_event_handler(void * dummy)
/**
* eeh_thread_launcher
- *
* @dummy - unused
*/
static void eeh_thread_launcher(void *dummy)
@@ -112,7 +118,15 @@ int eeh_send_failure_event (struct device_node *dn,
{
unsigned long flags;
struct eeh_event *event;
+ char *location;
+ if (!mem_init_done) {
+ printk(KERN_ERR "EEH: event during early boot not handled\n");
+ location = (char *) get_property(dn, "ibm,loc-code", NULL);
+ printk(KERN_ERR "EEH: device node = %s\n", dn->full_name);
+ printk(KERN_ERR "EEH: PCI location = %s\n", location);
+ return 1;
+ }
event = kmalloc(sizeof(*event), GFP_ATOMIC);
if (event == NULL) {
printk (KERN_ERR "EEH: out of memory, event not handled\n");
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
index 989f4bc136c..c01d8f0cbe6 100644
--- a/arch/powerpc/platforms/pseries/firmware.c
+++ b/arch/powerpc/platforms/pseries/firmware.c
@@ -91,7 +91,7 @@ void __init fw_feature_init(void)
continue;
/* we have a match */
- ppc64_firmware_features |=
+ powerpc_firmware_features |=
firmware_features_table[i].val;
break;
}
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S
index db7c19fe929..c9ff547f9d2 100644
--- a/arch/powerpc/platforms/pseries/hvCall.S
+++ b/arch/powerpc/platforms/pseries/hvCall.S
@@ -127,3 +127,103 @@ _GLOBAL(plpar_hcall_4out)
mtcrf 0xff,r0
blr /* return r3 = status */
+
+/* plpar_hcall_7arg_7ret(unsigned long opcode, R3
+ unsigned long arg1, R4
+ unsigned long arg2, R5
+ unsigned long arg3, R6
+ unsigned long arg4, R7
+ unsigned long arg5, R8
+ unsigned long arg6, R9
+ unsigned long arg7, R10
+ unsigned long *out1, 112(R1)
+ unsigned long *out2, 110(R1)
+ unsigned long *out3, 108(R1)
+ unsigned long *out4, 106(R1)
+ unsigned long *out5, 104(R1)
+ unsigned long *out6, 102(R1)
+ unsigned long *out7); 100(R1)
+*/
+_GLOBAL(plpar_hcall_7arg_7ret)
+ HMT_MEDIUM
+
+ mfcr r0
+ stw r0,8(r1)
+
+ HVSC /* invoke the hypervisor */
+
+ lwz r0,8(r1)
+
+ ld r11,STK_PARM(r11)(r1) /* Fetch r4 ret arg */
+ std r4,0(r11)
+ ld r11,STK_PARM(r12)(r1) /* Fetch r5 ret arg */
+ std r5,0(r11)
+ ld r11,STK_PARM(r13)(r1) /* Fetch r6 ret arg */
+ std r6,0(r11)
+ ld r11,STK_PARM(r14)(r1) /* Fetch r7 ret arg */
+ std r7,0(r11)
+ ld r11,STK_PARM(r15)(r1) /* Fetch r8 ret arg */
+ std r8,0(r11)
+ ld r11,STK_PARM(r16)(r1) /* Fetch r9 ret arg */
+ std r9,0(r11)
+ ld r11,STK_PARM(r17)(r1) /* Fetch r10 ret arg */
+ std r10,0(r11)
+
+ mtcrf 0xff,r0
+
+ blr /* return r3 = status */
+
+/* plpar_hcall_9arg_9ret(unsigned long opcode, R3
+ unsigned long arg1, R4
+ unsigned long arg2, R5
+ unsigned long arg3, R6
+ unsigned long arg4, R7
+ unsigned long arg5, R8
+ unsigned long arg6, R9
+ unsigned long arg7, R10
+ unsigned long arg8, 112(R1)
+ unsigned long arg9, 110(R1)
+ unsigned long *out1, 108(R1)
+ unsigned long *out2, 106(R1)
+ unsigned long *out3, 104(R1)
+ unsigned long *out4, 102(R1)
+ unsigned long *out5, 100(R1)
+ unsigned long *out6, 98(R1)
+ unsigned long *out7); 96(R1)
+ unsigned long *out8, 94(R1)
+ unsigned long *out9, 92(R1)
+*/
+_GLOBAL(plpar_hcall_9arg_9ret)
+ HMT_MEDIUM
+
+ mfcr r0
+ stw r0,8(r1)
+
+ ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */
+ ld r12,STK_PARM(r12)(r1) /* put arg9 in R12 */
+
+ HVSC /* invoke the hypervisor */
+
+ ld r0,STK_PARM(r13)(r1) /* Fetch r4 ret arg */
+ stdx r4,r0,r0
+ ld r0,STK_PARM(r14)(r1) /* Fetch r5 ret arg */
+ stdx r5,r0,r0
+ ld r0,STK_PARM(r15)(r1) /* Fetch r6 ret arg */
+ stdx r6,r0,r0
+ ld r0,STK_PARM(r16)(r1) /* Fetch r7 ret arg */
+ stdx r7,r0,r0
+ ld r0,STK_PARM(r17)(r1) /* Fetch r8 ret arg */
+ stdx r8,r0,r0
+ ld r0,STK_PARM(r18)(r1) /* Fetch r9 ret arg */
+ stdx r9,r0,r0
+ ld r0,STK_PARM(r19)(r1) /* Fetch r10 ret arg */
+ stdx r10,r0,r0
+ ld r0,STK_PARM(r20)(r1) /* Fetch r11 ret arg */
+ stdx r11,r0,r0
+ ld r0,STK_PARM(r21)(r1) /* Fetch r12 ret arg */
+ stdx r12,r0,r0
+
+ lwz r0,8(r1)
+ mtcrf 0xff,r0
+
+ blr /* return r3 = status */
diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c
index 138e128a388..a72a987f1d4 100644
--- a/arch/powerpc/platforms/pseries/hvconsole.c
+++ b/arch/powerpc/platforms/pseries/hvconsole.c
@@ -41,7 +41,7 @@ int hvc_get_chars(uint32_t vtermno, char *buf, int count)
unsigned long got;
if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got,
- (unsigned long *)buf, (unsigned long *)buf+1) == H_Success)
+ (unsigned long *)buf, (unsigned long *)buf+1) == H_SUCCESS)
return got;
return 0;
}
@@ -62,11 +62,16 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
unsigned long *lbuf = (unsigned long *) buf;
long ret;
+
+ /* hcall will ret H_PARAMETER if 'count' exceeds firmware max.*/
+ if (count > MAX_VIO_PUT_CHARS)
+ count = MAX_VIO_PUT_CHARS;
+
ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0],
lbuf[1]);
- if (ret == H_Success)
+ if (ret == H_SUCCESS)
return count;
- if (ret == H_Busy)
+ if (ret == H_BUSY)
return 0;
return -EIO;
}
diff --git a/arch/powerpc/platforms/pseries/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c
index 22bfb5c89db..fcf4b4cbeaf 100644
--- a/arch/powerpc/platforms/pseries/hvcserver.c
+++ b/arch/powerpc/platforms/pseries/hvcserver.c
@@ -43,21 +43,21 @@ MODULE_VERSION(HVCS_ARCH_VERSION);
static int hvcs_convert(long to_convert)
{
switch (to_convert) {
- case H_Success:
+ case H_SUCCESS:
return 0;
- case H_Parameter:
+ case H_PARAMETER:
return -EINVAL;
- case H_Hardware:
+ case H_HARDWARE:
return -EIO;
- case H_Busy:
- case H_LongBusyOrder1msec:
- case H_LongBusyOrder10msec:
- case H_LongBusyOrder100msec:
- case H_LongBusyOrder1sec:
- case H_LongBusyOrder10sec:
- case H_LongBusyOrder100sec:
+ case H_BUSY:
+ case H_LONG_BUSY_ORDER_1_MSEC:
+ case H_LONG_BUSY_ORDER_10_MSEC:
+ case H_LONG_BUSY_ORDER_100_MSEC:
+ case H_LONG_BUSY_ORDER_1_SEC:
+ case H_LONG_BUSY_ORDER_10_SEC:
+ case H_LONG_BUSY_ORDER_100_SEC:
return -EBUSY;
- case H_Function: /* fall through */
+ case H_FUNCTION: /* fall through */
default:
return -EPERM;
}
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 8952528d31a..634b7d06d3c 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -54,7 +54,8 @@ EXPORT_SYMBOL(plpar_hcall);
EXPORT_SYMBOL(plpar_hcall_4out);
EXPORT_SYMBOL(plpar_hcall_norets);
EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
-
+EXPORT_SYMBOL(plpar_hcall_7arg_7ret);
+EXPORT_SYMBOL(plpar_hcall_9arg_9ret);
extern void pSeries_find_serial_port(void);
@@ -72,7 +73,7 @@ static void udbg_hvsi_putc(char c)
do {
rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
- } while (rc == H_Busy);
+ } while (rc == H_BUSY);
}
static long hvsi_udbg_buf_len;
@@ -85,7 +86,7 @@ static int udbg_hvsi_getc_poll(void)
if (hvsi_udbg_buf_len == 0) {
rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
- if (rc != H_Success || hvsi_udbg_buf[0] != 0xff) {
+ if (rc != H_SUCCESS || hvsi_udbg_buf[0] != 0xff) {
/* bad read or non-data packet */
hvsi_udbg_buf_len = 0;
} else {
@@ -139,7 +140,7 @@ static void udbg_putcLP(char c)
buf[0] = c;
do {
rc = plpar_put_term_char(vtermno, 1, buf);
- } while(rc == H_Busy);
+ } while(rc == H_BUSY);
}
/* Buffered chars getc */
@@ -158,7 +159,7 @@ static int udbg_getc_pollLP(void)
/* get some more chars. */
inbuflen = 0;
rc = plpar_get_term_char(vtermno, &inbuflen, buf);
- if (rc != H_Success)
+ if (rc != H_SUCCESS)
inbuflen = 0; /* otherwise inbuflen is garbage */
}
if (inbuflen <= 0 || inbuflen > 16) {
@@ -304,7 +305,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, hpte_v,
hpte_r, &slot, &dummy0, &dummy1);
- if (unlikely(lpar_rc == H_PTEG_Full)) {
+ if (unlikely(lpar_rc == H_PTEG_FULL)) {
if (!(vflags & HPTE_V_BOLTED))
DBG_LOW(" full\n");
return -1;
@@ -315,7 +316,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
* will fail. However we must catch the failure in hash_page
* or we will loop forever, so return -2 in this case.
*/
- if (unlikely(lpar_rc != H_Success)) {
+ if (unlikely(lpar_rc != H_SUCCESS)) {
if (!(vflags & HPTE_V_BOLTED))
DBG_LOW(" lpar err %d\n", lpar_rc);
return -2;
@@ -346,9 +347,9 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
/* don't remove a bolted entry */
lpar_rc = plpar_pte_remove(H_ANDCOND, hpte_group + slot_offset,
(0x1UL << 4), &dummy1, &dummy2);
- if (lpar_rc == H_Success)
+ if (lpar_rc == H_SUCCESS)
return i;
- BUG_ON(lpar_rc != H_Not_Found);
+ BUG_ON(lpar_rc != H_NOT_FOUND);
slot_offset++;
slot_offset &= 0x7;
@@ -391,14 +392,14 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot,
lpar_rc = plpar_pte_protect(flags, slot, want_v & HPTE_V_AVPN);
- if (lpar_rc == H_Not_Found) {
+ if (lpar_rc == H_NOT_FOUND) {
DBG_LOW("not found !\n");
return -1;
}
DBG_LOW("ok\n");
- BUG_ON(lpar_rc != H_Success);
+ BUG_ON(lpar_rc != H_SUCCESS);
return 0;
}
@@ -417,7 +418,7 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);
- BUG_ON(lpar_rc != H_Success);
+ BUG_ON(lpar_rc != H_SUCCESS);
return dword0;
}
@@ -468,7 +469,7 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
flags = newpp & 7;
lpar_rc = plpar_pte_protect(flags, slot, 0);
- BUG_ON(lpar_rc != H_Success);
+ BUG_ON(lpar_rc != H_SUCCESS);
}
static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
@@ -484,10 +485,10 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
want_v = hpte_encode_v(va, psize);
lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v & HPTE_V_AVPN,
&dummy1, &dummy2);
- if (lpar_rc == H_Not_Found)
+ if (lpar_rc == H_NOT_FOUND)
return;
- BUG_ON(lpar_rc != H_Success);
+ BUG_ON(lpar_rc != H_SUCCESS);
}
/*
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index 946ad59e335..e97e67f5e07 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -120,7 +120,7 @@ static void fixup_winbond_82c105(struct pci_dev* dev)
int i;
unsigned int reg;
- if (!platform_is_pseries())
+ if (!machine_is(pseries))
return;
printk("Using INTC for W82c105 IDE controller.\n");
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 44abdeb9ca0..6bfacc21708 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -28,6 +28,7 @@
#include <linux/pci.h>
#include <asm/pci-bridge.h>
#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
static struct pci_bus *
find_bus_among_children(struct pci_bus *bus,
@@ -152,20 +153,24 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
void
pcibios_add_pci_devices(struct pci_bus * bus)
{
- int slotno, num;
+ int slotno, num, mode;
struct pci_dev *dev;
struct device_node *dn = pci_bus_to_OF_node(bus);
eeh_add_device_tree_early(dn);
- if (_machine == PLATFORM_PSERIES_LPAR) {
+ mode = PCI_PROBE_NORMAL;
+ if (ppc_md.pci_probe_mode)
+ mode = ppc_md.pci_probe_mode(bus);
+
+ if (mode == PCI_PROBE_DEVTREE) {
/* use ofdt-based probe */
of_scan_bus(dn, bus);
if (!list_empty(&bus->devices)) {
pcibios_fixup_new_pci_devices(bus, 0);
pci_bus_add_devices(bus);
}
- } else {
+ } else if (mode == PCI_PROBE_NORMAL) {
/* use legacy probe */
slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index b046bcf7443..9639c66b453 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -132,7 +132,7 @@ static int __init init_ras_IRQ(void)
of_node_put(np);
}
- return 1;
+ return 0;
}
__initcall(init_ras_IRQ);
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 86cfa6ecdcf..1773103354b 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -17,8 +17,9 @@
#include <linux/proc_fs.h>
#include <asm/prom.h>
-#include <asm/pSeries_reconfig.h>
+#include <asm/machdep.h>
#include <asm/uaccess.h>
+#include <asm/pSeries_reconfig.h>
@@ -94,16 +95,16 @@ static struct device_node *derive_parent(const char *path)
return parent;
}
-static struct notifier_block *pSeries_reconfig_chain;
+static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
int pSeries_reconfig_notifier_register(struct notifier_block *nb)
{
- return notifier_chain_register(&pSeries_reconfig_chain, nb);
+ return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb);
}
void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
{
- notifier_chain_unregister(&pSeries_reconfig_chain, nb);
+ blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
}
static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
@@ -131,7 +132,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
goto out_err;
}
- err = notifier_call_chain(&pSeries_reconfig_chain,
+ err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
PSERIES_RECONFIG_ADD, np);
if (err == NOTIFY_BAD) {
printk(KERN_ERR "Failed to add device node %s\n", path);
@@ -171,7 +172,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
remove_node_proc_entries(np);
- notifier_call_chain(&pSeries_reconfig_chain,
+ blocking_notifier_call_chain(&pSeries_reconfig_chain,
PSERIES_RECONFIG_REMOVE, np);
of_detach_node(np);
@@ -508,7 +509,7 @@ static int proc_ppc64_create_ofdt(void)
{
struct proc_dir_entry *ent;
- if (!platform_is_pseries())
+ if (!machine_is(pseries))
return 0;
ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index a6f628d4c9d..e0000ce769e 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -27,6 +27,7 @@
#include <asm/prom.h>
#include <asm/nvram.h>
#include <asm/atomic.h>
+#include <asm/machdep.h>
#if 0
#define DEBUG(A...) printk(KERN_ERR A)
@@ -481,13 +482,13 @@ static int __init rtas_init(void)
{
struct proc_dir_entry *entry;
- if (!platform_is_pseries())
+ if (!machine_is(pseries))
return 0;
/* No RTAS */
if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
printk(KERN_INFO "rtasd: no event-scan on system\n");
- return 1;
+ return -ENODEV;
}
entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 44d5c7fdcd9..3ba87835757 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -81,8 +81,8 @@ extern void find_udbg_vterm(void);
int fwnmi_active; /* TRUE if an FWNMI handler is present */
-static void pseries_shared_idle(void);
-static void pseries_dedicated_idle(void);
+static void pseries_shared_idle_sleep(void);
+static void pseries_dedicated_idle_sleep(void);
struct mpic *pSeries_mpic;
@@ -236,14 +236,13 @@ static void __init pSeries_setup_arch(void)
vpa_init(boot_cpuid);
if (get_lppaca()->shared_proc) {
printk(KERN_INFO "Using shared processor idle loop\n");
- ppc_md.idle_loop = pseries_shared_idle;
+ ppc_md.power_save = pseries_shared_idle_sleep;
} else {
printk(KERN_INFO "Using dedicated idle loop\n");
- ppc_md.idle_loop = pseries_dedicated_idle;
+ ppc_md.power_save = pseries_dedicated_idle_sleep;
}
} else {
printk(KERN_INFO "Using default idle loop\n");
- ppc_md.idle_loop = default_idle;
}
if (firmware_has_feature(FW_FEATURE_LPAR))
@@ -256,7 +255,7 @@ static int __init pSeries_init_panel(void)
{
/* Manually leave the kernel version on the panel. */
ppc_md.progress("Linux ppc64\n", 0);
- ppc_md.progress(system_utsname.version, 0);
+ ppc_md.progress(system_utsname.release, 0);
return 0;
}
@@ -373,156 +372,131 @@ static int pSeries_check_legacy_ioport(unsigned int baseport)
/*
* Called very early, MMU is off, device-tree isn't unflattened
*/
-extern struct machdep_calls pSeries_md;
-static int __init pSeries_probe(int platform)
+static int __init pSeries_probe_hypertas(unsigned long node,
+ const char *uname, int depth,
+ void *data)
{
- if (platform != PLATFORM_PSERIES &&
- platform != PLATFORM_PSERIES_LPAR)
+ if (depth != 1 ||
+ (strcmp(uname, "rtas") != 0 && strcmp(uname, "rtas@0") != 0))
+ return 0;
+
+ if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL)
+ powerpc_firmware_features |= FW_FEATURE_LPAR;
+
+ return 1;
+}
+
+static int __init pSeries_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+ char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
+ "device_type", NULL);
+ if (dtype == NULL)
+ return 0;
+ if (strcmp(dtype, "chrp"))
return 0;
- /* if we have some ppc_md fixups for LPAR to do, do
- * it here ...
+ /* Cell blades firmware claims to be chrp while it's not. Until this
+ * is fixed, we need to avoid those here.
*/
+ if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0") ||
+ of_flat_dt_is_compatible(root, "IBM,CBEA"))
+ return 0;
- if (platform == PLATFORM_PSERIES_LPAR)
- ppc64_firmware_features |= FW_FEATURE_LPAR;
+ DBG("pSeries detected, looking for LPAR capability...\n");
+
+ /* Now try to figure out if we are running on LPAR */
+ of_scan_flat_dt(pSeries_probe_hypertas, NULL);
+
+ DBG("Machine is%s LPAR !\n",
+ (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
return 1;
}
-DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
-
-static inline void dedicated_idle_sleep(unsigned int cpu)
-{
- struct lppaca *plppaca = &lppaca[cpu ^ 1];
- /* Only sleep if the other thread is not idle */
- if (!(plppaca->idle)) {
- local_irq_disable();
-
- /*
- * We are about to sleep the thread and so wont be polling any
- * more.
- */
- clear_thread_flag(TIF_POLLING_NRFLAG);
- smp_mb__after_clear_bit();
-
- /*
- * SMT dynamic mode. Cede will result in this thread going
- * dormant, if the partner thread is still doing work. Thread
- * wakes up if partner goes idle, an interrupt is presented, or
- * a prod occurs. Returning from the cede enables external
- * interrupts.
- */
- if (!need_resched())
- cede_processor();
- else
- local_irq_enable();
- set_thread_flag(TIF_POLLING_NRFLAG);
- } else {
- /*
- * Give the HV an opportunity at the processor, since we are
- * not doing any work.
- */
- poll_pending();
- }
-}
+DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
-static void pseries_dedicated_idle(void)
+static void pseries_dedicated_idle_sleep(void)
{
unsigned int cpu = smp_processor_id();
unsigned long start_snooze;
unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
- set_thread_flag(TIF_POLLING_NRFLAG);
-
- while (1) {
- /*
- * Indicate to the HV that we are idle. Now would be
- * a good time to find other work to dispatch.
- */
- get_lppaca()->idle = 1;
-
- if (!need_resched()) {
- start_snooze = get_tb() +
- *smt_snooze_delay * tb_ticks_per_usec;
-
- while (!need_resched() && !cpu_is_offline(cpu)) {
- ppc64_runlatch_off();
-
- /*
- * Go into low thread priority and possibly
- * low power mode.
- */
- HMT_low();
- HMT_very_low();
-
- if (*smt_snooze_delay != 0 &&
- get_tb() > start_snooze) {
- HMT_medium();
- dedicated_idle_sleep(cpu);
- }
-
- }
-
- HMT_medium();
- }
-
- get_lppaca()->idle = 0;
- ppc64_runlatch_on();
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
+ /*
+ * Indicate to the HV that we are idle. Now would be
+ * a good time to find other work to dispatch.
+ */
+ get_lppaca()->idle = 1;
- if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
- cpu_die();
- }
-}
+ /*
+ * We come in with interrupts disabled, and need_resched()
+ * has been checked recently. If we should poll for a little
+ * while, do so.
+ */
+ if (*smt_snooze_delay) {
+ start_snooze = get_tb() +
+ *smt_snooze_delay * tb_ticks_per_usec;
+ local_irq_enable();
+ set_thread_flag(TIF_POLLING_NRFLAG);
-static void pseries_shared_idle(void)
-{
- unsigned int cpu = smp_processor_id();
+ while (get_tb() < start_snooze) {
+ if (need_resched() || cpu_is_offline(cpu))
+ goto out;
+ ppc64_runlatch_off();
+ HMT_low();
+ HMT_very_low();
+ }
- while (1) {
- /*
- * Indicate to the HV that we are idle. Now would be
- * a good time to find other work to dispatch.
- */
- get_lppaca()->idle = 1;
+ HMT_medium();
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+ smp_mb();
+ local_irq_disable();
+ if (need_resched() || cpu_is_offline(cpu))
+ goto out;
+ }
- while (!need_resched() && !cpu_is_offline(cpu)) {
- local_irq_disable();
- ppc64_runlatch_off();
+ /*
+ * Cede if the other thread is not idle, so that it can
+ * go single-threaded. If the other thread is idle,
+ * we ask the hypervisor if it has pending work it
+ * wants to do and cede if it does. Otherwise we keep
+ * polling in order to reduce interrupt latency.
+ *
+ * Doing the cede when the other thread is active will
+ * result in this thread going dormant, meaning the other
+ * thread gets to run in single-threaded (ST) mode, which
+ * is slightly faster than SMT mode with this thread at
+ * very low priority. The cede enables interrupts, which
+ * doesn't matter here.
+ */
+ if (!lppaca[cpu ^ 1].idle || poll_pending() == H_PENDING)
+ cede_processor();
- /*
- * Yield the processor to the hypervisor. We return if
- * an external interrupt occurs (which are driven prior
- * to returning here) or if a prod occurs from another
- * processor. When returning here, external interrupts
- * are enabled.
- *
- * Check need_resched() again with interrupts disabled
- * to avoid a race.
- */
- if (!need_resched())
- cede_processor();
- else
- local_irq_enable();
-
- HMT_medium();
- }
+out:
+ HMT_medium();
+ get_lppaca()->idle = 0;
+}
- get_lppaca()->idle = 0;
- ppc64_runlatch_on();
+static void pseries_shared_idle_sleep(void)
+{
+ /*
+ * Indicate to the HV that we are idle. Now would be
+ * a good time to find other work to dispatch.
+ */
+ get_lppaca()->idle = 1;
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
+ /*
+ * Yield the processor to the hypervisor. We return if
+ * an external interrupt occurs (which are driven prior
+ * to returning here) or if a prod occurs from another
+ * processor. When returning here, external interrupts
+ * are enabled.
+ */
+ cede_processor();
- if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
- cpu_die();
- }
+ get_lppaca()->idle = 0;
}
static int pSeries_pci_probe_mode(struct pci_bus *bus)
@@ -553,7 +527,8 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
}
#endif
-struct machdep_calls __initdata pSeries_md = {
+define_machine(pseries) {
+ .name = "pSeries",
.probe = pSeries_probe,
.setup_arch = pSeries_setup_arch,
.init_early = pSeries_init_early,
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c
index 866379b80c0..8e53e04ada8 100644
--- a/arch/powerpc/platforms/pseries/vio.c
+++ b/arch/powerpc/platforms/pseries/vio.c
@@ -258,7 +258,7 @@ EXPORT_SYMBOL(vio_find_node);
int vio_enable_interrupts(struct vio_dev *dev)
{
int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
- if (rc != H_Success)
+ if (rc != H_SUCCESS)
printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
return rc;
}
@@ -267,7 +267,7 @@ EXPORT_SYMBOL(vio_enable_interrupts);
int vio_disable_interrupts(struct vio_dev *dev)
{
int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
- if (rc != H_Success)
+ if (rc != H_SUCCESS)
printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
return rc;
}
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index eb86cdb9b80..2d60ea30fed 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -168,7 +168,7 @@ static int pSeriesLP_xirr_info_get(int n_cpu)
unsigned long return_value;
lpar_rc = plpar_xirr(&return_value);
- if (lpar_rc != H_Success)
+ if (lpar_rc != H_SUCCESS)
panic(" bad return code xirr - rc = %lx \n", lpar_rc);
return (int)return_value;
}
@@ -179,7 +179,7 @@ static void pSeriesLP_xirr_info_set(int n_cpu, int value)
unsigned long val64 = value & 0xffffffff;
lpar_rc = plpar_eoi(val64);
- if (lpar_rc != H_Success)
+ if (lpar_rc != H_SUCCESS)
panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc,
val64);
}
@@ -189,7 +189,7 @@ void pSeriesLP_cppr_info(int n_cpu, u8 value)
unsigned long lpar_rc;
lpar_rc = plpar_cppr(value);
- if (lpar_rc != H_Success)
+ if (lpar_rc != H_SUCCESS)
panic("bad return code cppr - rc = %lx\n", lpar_rc);
}
@@ -198,7 +198,7 @@ static void pSeriesLP_qirr_info(int n_cpu , u8 value)
unsigned long lpar_rc;
lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu), value);
- if (lpar_rc != H_Success)
+ if (lpar_rc != H_SUCCESS)
panic("bad return code qirr - rc = %lx\n", lpar_rc);
}
@@ -500,7 +500,7 @@ nextnode:
np;
np = of_find_node_by_type(np, "cpu")) {
ireg = (uint *)get_property(np, "reg", &ilen);
- if (ireg && ireg[0] == boot_cpuid_phys) {
+ if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) {
ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s",
&ilen);
i = ilen / sizeof(int);
@@ -541,7 +541,7 @@ nextnode:
ops = &pSeriesLP_ops;
else {
#ifdef CONFIG_SMP
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
int hard_id;
/* FIXME: Do this dynamically! --RR */
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 61d31742861..38087bd6e3c 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -49,6 +49,7 @@
#include "dart.h"
+extern int iommu_is_off;
extern int iommu_force_on;
/* Physical base address and size of the DART table */
@@ -329,10 +330,17 @@ void iommu_init_early_dart(void)
void __init alloc_dart_table(void)
{
- /* Only reserve DART space if machine has more than 2GB of RAM
+ /* Only reserve DART space if machine has more than 1GB of RAM
* or if requested with iommu=on on cmdline.
+ *
+ * 1GB of RAM is picked as limit because some default devices
+ * (i.e. Airport Extreme) have 30 bit address range limits.
*/
- if (lmb_end_of_DRAM() <= 0x80000000ull && !iommu_force_on)
+
+ if (iommu_is_off)
+ return;
+
+ if (!iommu_force_on && lmb_end_of_DRAM() <= 0x40000000ull)
return;
/* 512 pages (2MB) is max DART tablesize. */
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 3a3e302b4ea..e9a8f5d1dfc 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -61,15 +61,15 @@ config 6xx
select PPC_FPU
help
There are four types 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 IBM
- embedded versions (403 and 405) and the POWER3 processor.
- (For support for more recent 64-bit processors, set ARCH=powerpc.)
+ types (601, 603, 604, 740, 750, 7400), the older Freescale
+ (formerly Motorola) embedded versions (821, 823, 850, 855, 860,
+ 52xx, 82xx, 83xx), the IBM embedded versions (403 and 405) and
+ the Book E embedded processors from IBM (44x) and Freescale (85xx).
+ For support for 64-bit processors, set ARCH=powerpc.
Unless you are building a kernel for one of the embedded processor
- systems or a POWER3-based IBM RS/6000, choose 6xx.
- Note that the kernel runs in 32-bit mode even on 64-bit chips.
- Also note that because the 52xx, 82xx, & 83xx family has a 603e core,
- specific support for that chipset is asked later on.
+ systems, choose 6xx.
+ Also note that because the 52xx, 82xx, & 83xx family have a 603e
+ core, specific support for that chipset is asked later on.
config 40x
bool "40x"
@@ -77,10 +77,6 @@ config 40x
config 44x
bool "44x"
-config POWER3
- select PPC_FPU
- bool "POWER3"
-
config 8xx
bool "8xx"
@@ -252,14 +248,9 @@ config PPC601_SYNC_FIX
source arch/ppc/platforms/4xx/Kconfig
source arch/ppc/platforms/85xx/Kconfig
-config PPC64BRIDGE
- bool
- depends on POWER3
- default y
-
config PPC_STD_MMU
bool
- depends on 6xx || POWER3
+ depends on 6xx
default y
config NOT_COHERENT_CACHE
@@ -534,8 +525,8 @@ endmenu
choice
prompt "Machine Type"
- depends on 6xx || POWER3
- default PPC_MULTIPLATFORM
+ depends on 6xx
+ default PPC_PREP
---help---
Linux currently supports several different kinds of PowerPC-based
machines: Apple Power Macintoshes and clones (such as the Motorola
@@ -545,15 +536,14 @@ choice
Platform) machines (including all of the recent IBM RS/6000 and
pSeries machines), and several embedded PowerPC systems containing
4xx, 6xx, 7xx, 8xx, 74xx, and 82xx processors. Currently, the
- default option is to build a kernel which works on PReP and CHRP.
+ default option is to build a kernel which works on PReP.
- Note that support for Apple machines is now only available with
- ARCH=powerpc, and has been removed from this menu. If you wish
- to build a kernel for an Apple machine, exit this configuration
- process and re-run it with ARCH=powerpc.
+ Note that support for Apple and CHRP machines is now only available
+ with ARCH=powerpc, and has been removed from this menu. If you
+ wish to build a kernel for an Apple or CHRP machine, exit this
+ configuration process and re-run it with ARCH=powerpc.
- Select CHRP/PReP if configuring for an IBM RS/6000 or
- pSeries machine, or a PReP machine.
+ Select PReP if configuring for a PReP machine.
Select Gemini if configuring for a Synergy Microsystems' Gemini
series Single Board Computer. More information is available at:
@@ -562,8 +552,8 @@ choice
Select APUS if configuring for a PowerUP Amiga. More information is
available at: <http://linux-apus.sourceforge.net/>.
-config PPC_MULTIPLATFORM
- bool "CHRP/PReP"
+config PPC_PREP
+ bool "PReP"
config APUS
bool "Amiga-APUS"
@@ -715,6 +705,13 @@ config LITE5200
much but it's only been tested on this board version. I think this
board is also known as IceCube.
+config LITE5200B
+ bool "Freescale LITE5200B"
+ depends LITE5200
+ help
+ Support for the LITE5200B dev board for the MPC5200 from Freescale.
+ This is the new board with 2 PCI slots.
+
config MPC834x_SYS
bool "Freescale MPC834x SYS"
help
@@ -800,25 +797,6 @@ config CPM2
you wish to build a kernel for a machine with a CPM2 coprocessor
on it (826x, 827x, 8560).
-config PPC_CHRP
- bool "Support for CHRP (Common Hardware Reference Platform) machines"
- depends on PPC_MULTIPLATFORM
- select PPC_I8259
- select PPC_INDIRECT_PCI
- default y
-
-config PPC_PREP
- bool "Support for PReP (PowerPC Reference Platform) machines"
- depends on PPC_MULTIPLATFORM
- select PPC_I8259
- select PPC_INDIRECT_PCI
- default y
-
-config PPC_OF
- bool
- depends on PPC_CHRP
- default y
-
config PPC_GEN550
bool
depends on SANDPOINT || SPRUCE || PPLUS || \
@@ -977,14 +955,6 @@ source "mm/Kconfig"
source "fs/Kconfig.binfmt"
-config PROC_DEVICETREE
- bool "Support for Open Firmware device tree in /proc"
- depends on PPC_OF && PROC_FS
- help
- This option adds a device-tree directory under /proc which contains
- an image of the device tree that the kernel copies from Open
- Firmware. If unsure, say Y here.
-
config PREP_RESIDUAL
bool "Support for PReP Residual Data"
depends on PPC_PREP
@@ -1177,8 +1147,7 @@ menu "Bus options"
config ISA
bool "Support for ISA-bus hardware"
- depends on PPC_PREP || PPC_CHRP
- select PPC_I8259
+ depends on PPC_PREP
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
@@ -1188,18 +1157,18 @@ config ISA
config GENERIC_ISA_DMA
bool
- depends on POWER3 || 6xx && !CPM2
+ depends on 6xx && !CPM2
default y
config PPC_I8259
bool
- default y if 85xx
+ default y if 85xx || PPC_PREP
default n
config PPC_INDIRECT_PCI
bool
depends on PCI
- default y if 40x || 44x || 85xx || 83xx
+ default y if 40x || 44x || 85xx || 83xx || PPC_PREP
default n
config EISA
@@ -1390,7 +1359,7 @@ config CONSISTENT_SIZE
config BOOT_LOAD_BOOL
bool "Set the boot link/load address"
- depends on ADVANCED_OPTIONS && !PPC_MULTIPLATFORM
+ depends on ADVANCED_OPTIONS && !PPC_PREP
help
This option allows you to set the initial load address of the zImage
or zImage.initrd file. This can be useful if you are on a board
diff --git a/arch/ppc/Kconfig.debug b/arch/ppc/Kconfig.debug
index 8cc75abf3d8..f94b8774097 100644
--- a/arch/ppc/Kconfig.debug
+++ b/arch/ppc/Kconfig.debug
@@ -53,13 +53,6 @@ config BDI_SWITCH
Unless you are intending to debug the kernel with one of these
machines, say N here.
-config BOOTX_TEXT
- bool "Support for early boot text console (BootX or OpenFirmware only)"
- depends PPC_OF
- help
- Say Y here to see progress messages from the boot firmware in text
- mode. Requires either BootX or Open Firmware.
-
config SERIAL_TEXT_DEBUG
bool "Support for early boot texts over serial port"
depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 9fbdf54ba2b..0db66dcf072 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -40,10 +40,8 @@ ifndef CONFIG_FSL_BOOKE
CFLAGS += -mstring
endif
-cpu-as-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge
cpu-as-$(CONFIG_4xx) += -Wa,-m405
cpu-as-$(CONFIG_6xx) += -Wa,-maltivec
-cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec
cpu-as-$(CONFIG_E500) += -Wa,-me500
cpu-as-$(CONFIG_E200) += -Wa,-me200
@@ -59,8 +57,6 @@ head-$(CONFIG_4xx) := arch/ppc/kernel/head_4xx.o
head-$(CONFIG_44x) := arch/ppc/kernel/head_44x.o
head-$(CONFIG_FSL_BOOKE) := arch/ppc/kernel/head_fsl_booke.o
-head-$(CONFIG_6xx) += arch/ppc/kernel/idle_6xx.o
-head-$(CONFIG_POWER4) += arch/ppc/kernel/idle_power4.o
head-$(CONFIG_PPC_FPU) += arch/powerpc/kernel/fpu.o
core-y += arch/ppc/kernel/ arch/powerpc/kernel/ \
@@ -71,7 +67,7 @@ core-y += arch/ppc/kernel/ arch/powerpc/kernel/ \
core-$(CONFIG_4xx) += arch/ppc/platforms/4xx/
core-$(CONFIG_83xx) += arch/ppc/platforms/83xx/
core-$(CONFIG_85xx) += arch/ppc/platforms/85xx/
-core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/
+core-$(CONFIG_MATH_EMULATION) += arch/powerpc/math-emu/
core-$(CONFIG_XMON) += arch/ppc/xmon/
core-$(CONFIG_APUS) += arch/ppc/amiga/
drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/
diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile
index 84eec0bef93..b739e25d472 100644
--- a/arch/ppc/boot/Makefile
+++ b/arch/ppc/boot/Makefile
@@ -19,14 +19,13 @@ HOSTCFLAGS += -Iarch/$(ARCH)/boot/include
BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd
bootdir-y := simple
-bootdir-$(CONFIG_PPC_OF) += openfirmware
subdir-y := lib common images
-subdir-$(CONFIG_PPC_MULTIPLATFORM) += of1275
+subdir-$(CONFIG_PPC_PREP) += of1275
# for cleaning
-subdir- += simple openfirmware
+subdir- += simple
-hostprogs-y := $(addprefix utils/, addnote mknote hack-coff mkprep mkbugboot mktree)
+hostprogs-y := $(addprefix utils/, mkprep mkbugboot mktree)
PHONY += $(BOOT_TARGETS) $(bootdir-y)
diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile
index d4077e69086..80c84d562fa 100644
--- a/arch/ppc/boot/lib/Makefile
+++ b/arch/ppc/boot/lib/Makefile
@@ -3,7 +3,7 @@
#
CFLAGS_kbd.o := -Idrivers/char
-CFLAGS_vreset.o := -I$(srctree)/arch/ppc/boot/include
+CFLAGS_vreset.o := -Iarch/ppc/boot/include
zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile
deleted file mode 100644
index 66b73974375..00000000000
--- a/arch/ppc/boot/openfirmware/Makefile
+++ /dev/null
@@ -1,109 +0,0 @@
-# Makefile for making bootable images on various OpenFirmware machines.
-#
-# This file is included by the global makefile so that you can add your own
-# architecture-specific flags and dependencies.
-#
-# Paul Mackerras January 1997
-# XCOFF bootable images for PowerMacs
-# Geert Uytterhoeven September 1997
-# ELF bootable iamges for CHRP machines.
-# Tom Rini January 2001
-# Cleaned up, moved into arch/ppc/boot/pmac
-# Tom Rini July/August 2002
-# Merged 'chrp' and 'pmac' into 'openfirmware', and cleaned up the
-# rules.
-
-zImage.initrd znetboot.initrd: del-ramdisk-sec := -R .ramdisk
-zImage.initrd znetboot.initrd: initrd := .initrd
-
-
-boot := arch/ppc/boot
-common := $(boot)/common
-utils := $(boot)/utils
-bootlib := $(boot)/lib
-of1275 := $(boot)/of1275
-images := $(boot)/images
-
-CHRP_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00800000
-
-COMMONOBJS := start.o misc.o common.o
-CHRPOBJS := crt0.o $(COMMONOBJS) chrpmain.o
-
-targets := $(CHRPOBJS) dummy.o
-CHRPOBJS := $(addprefix $(obj)/, $(CHRPOBJS))
-
-LIBS := lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a
-
-ifdef CONFIG_SMP
-END := .smp
-endif
-ifdef CONFIG_PPC64BRIDGE
-END += .64
-endif
-
-
-$(images)/ramdisk.image.gz:
- @echo ' MISSING $@'
- @echo ' RAM disk image must be provided separately'
- @/bin/false
-
-quiet_cmd_genimage = GEN $@
- cmd_genimage = $(OBJCOPY) -R .comment \
- --add-section=.image=$(images)/vmlinux.gz \
- --set-section-flags=.image=contents,alloc,load,readonly,data $< $@
-
-targets += image.o
-$(obj)/image.o: $(obj)/dummy.o $(images)/vmlinux.gz FORCE
- $(call if_changed,genimage)
-
-# Place the ramdisk in the initrd image.
-quiet_cmd_genimage-initrd = GEN $@
- cmd_genimage-initrd = $(OBJCOPY) $< $@ \
- --add-section=.ramdisk=$(images)/ramdisk.image.gz \
- --set-section-flags=.ramdisk=contents,alloc,load,readonly,data
-targets += image.initrd.o
-$(obj)/image.initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz FORCE
- $(call if_changed,genimage-initrd)
-
-
-targets += crt0.o
-$(obj)/crt0.o: $(common)/crt0.S FORCE
- $(call if_changed_dep,as_o_S)
-
-quiet_cmd_gen-chrp = CHRP $@
- cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) $< $(LIBS) && \
- $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec)
-
-$(images)/zImage.chrp: $(obj)/image.o $(CHRPOBJS) $(LIBS) \
- $(srctree)/$(boot)/ld.script
- $(call cmd,gen-chrp)
-$(images)/zImage.initrd.chrp: $(obj)/image.initrd.o $(CHRPOBJS) $(LIBS) \
- $(srctree)/$(boot)/ld.script
- $(call cmd,gen-chrp)
-
-quiet_cmd_addnote = ADDNOTE $@
- cmd_addnote = cat $< > $@ && $(utils)/addnote $@
-$(images)/zImage.chrp-rs6k $(images)/zImage.initrd.chrp-rs6k: \
- %-rs6k: %
- $(call cmd,addnote)
-
-# The targets used on the make command-line
-
-PHONY += zImage zImage.initrd
-zImage: $(images)/zImage.chrp \
- $(images)/zImage.chrp-rs6k
- @echo ' kernel: $@ is ready ($<)'
-zImage.initrd: $(images)/zImage.initrd.chrp \
- $(images)/zImage.initrd.chrp-rs6k
- @echo ' kernel: $@ is ready ($<)'
-
-TFTPIMAGE := /tftpboot/zImage
-
-PHONY += znetboot znetboot.initrd
-znetboot: $(images)/zImage.chrp
- cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END)
- @echo ' kernel: $@ is ready ($<)'
-znetboot.initrd:$(images)/zImage.initrd.chrp
- cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END)
- @echo ' kernel: $@ is ready ($<)'
-
diff --git a/arch/ppc/boot/openfirmware/chrpmain.c b/arch/ppc/boot/openfirmware/chrpmain.c
deleted file mode 100644
index 245dbd9fc12..00000000000
--- a/arch/ppc/boot/openfirmware/chrpmain.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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 <linux/string.h>
-#include "nonstdio.h"
-#include "of1275.h"
-#include <asm/processor.h>
-#include <asm/page.h>
-
-/* Passed from the linker */
-extern char __image_begin, __image_end;
-extern char __ramdisk_begin, __ramdisk_end;
-extern char _start, _end;
-
-extern unsigned int heap_max;
-extern void flush_cache(void *, unsigned long);
-extern void gunzip(void *, int, unsigned char *, int *);
-extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
- unsigned int progend);
-
-char *avail_ram;
-char *begin_avail, *end_avail;
-char *avail_high;
-
-#define RAM_START 0x00000000
-#define RAM_END (64<<20)
-
-#define BOOT_START ((unsigned long)_start)
-#define BOOT_END ((unsigned long)(_end + 0xFFF) & ~0xFFF)
-
-#define RAM_FREE ((unsigned long)(_end+0x1000)&~0xFFF)
-#define PROG_START 0x00010000
-#define PROG_SIZE 0x007f0000 /* 8MB */
-
-#define SCRATCH_SIZE (128 << 10)
-
-static char scratch[SCRATCH_SIZE]; /* 128k of scratch space for gunzip */
-
-typedef void (*kernel_start_t)(int, int, void *, unsigned int, unsigned int);
-
-void
-boot(int a1, int a2, void *prom)
-{
- unsigned sa, len;
- void *dst;
- unsigned char *im;
- unsigned int initrd_size, initrd_start;
-
- printf("chrpboot starting: loaded at 0x%p\n\r", &_start);
-
- initrd_size = &__ramdisk_end - &__ramdisk_begin;
- if (initrd_size) {
- initrd_start = (RAM_END - initrd_size) & ~0xFFF;
- a1 = initrd_start;
- a2 = initrd_size;
- claim(initrd_start, RAM_END - initrd_start, 0);
- printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r",
- initrd_start, &__ramdisk_begin, initrd_size);
- memcpy((char *)initrd_start, &__ramdisk_begin, initrd_size);
- } else {
- initrd_start = 0;
- initrd_size = 0;
- a2 = 0xdeadbeef;
- }
-
- im = &__image_begin;
- len = &__image_end - &__image_begin;
- /* claim 4MB starting at PROG_START */
- claim(PROG_START, PROG_SIZE - PROG_START, 0);
- dst = (void *) PROG_START;
- if (im[0] == 0x1f && im[1] == 0x8b) {
- avail_ram = scratch;
- begin_avail = avail_high = avail_ram;
- end_avail = scratch + sizeof(scratch);
- printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
- gunzip(dst, PROG_SIZE - PROG_START, im, &len);
- printf("done %u bytes\n\r", len);
- printf("%u bytes of heap consumed, max in use %u\n\r",
- avail_high - begin_avail, heap_max);
- } else {
- memmove(dst, im, len);
- }
-
- flush_cache(dst, len);
- make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_chrp,
- (PROG_START + PROG_SIZE));
-
- sa = PROG_START;
- printf("start address = 0x%x\n\r", sa);
-
- (*(kernel_start_t)sa)(a1, a2, prom, initrd_start, initrd_size);
-
- printf("returned?\n\r");
-
- pause();
-}
diff --git a/arch/ppc/boot/openfirmware/common.c b/arch/ppc/boot/openfirmware/common.c
deleted file mode 100644
index 0f46756a903..00000000000
--- a/arch/ppc/boot/openfirmware/common.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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 "nonstdio.h"
-#include "of1275.h"
-#include <linux/string.h>
-#include <linux/zlib.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-
-/* Information from the linker */
-
-extern int strcmp(const char *s1, const char *s2);
-extern char *avail_ram, *avail_high;
-extern char *end_avail;
-
-unsigned int heap_use, heap_max;
-
-struct memchunk {
- unsigned int size;
- struct memchunk *next;
-};
-
-static struct memchunk *freechunks;
-
-static void *zalloc(unsigned size)
-{
- void *p;
- struct memchunk **mpp, *mp;
-
- size = (size + 7) & -8;
- heap_use += size;
- if (heap_use > heap_max)
- heap_max = heap_use;
- for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
- if (mp->size == size) {
- *mpp = mp->next;
- return mp;
- }
- }
- p = avail_ram;
- avail_ram += size;
- if (avail_ram > avail_high)
- avail_high = avail_ram;
- if (avail_ram > end_avail) {
- printf("oops... out of memory\n\r");
- pause();
- }
- return p;
-}
-
-#define HEAD_CRC 2
-#define EXTRA_FIELD 4
-#define ORIG_NAME 8
-#define COMMENT 0x10
-#define RESERVED 0xe0
-
-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
-{
- z_stream s;
- int r, i, flags;
-
- /* skip header */
- i = 10;
- flags = src[3];
- if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
- printf("bad gzipped data\n\r");
- exit();
- }
- if ((flags & EXTRA_FIELD) != 0)
- i = 12 + src[10] + (src[11] << 8);
- if ((flags & ORIG_NAME) != 0)
- while (src[i++] != 0)
- ;
- if ((flags & COMMENT) != 0)
- while (src[i++] != 0)
- ;
- if ((flags & HEAD_CRC) != 0)
- i += 2;
- if (i >= *lenp) {
- printf("gunzip: ran out of data in header\n\r");
- exit();
- }
-
- /* Initialize ourself. */
- s.workspace = zalloc(zlib_inflate_workspacesize());
- r = zlib_inflateInit2(&s, -MAX_WBITS);
- if (r != Z_OK) {
- printf("zlib_inflateInit2 returned %d\n\r", r);
- exit();
- }
- s.next_in = src + i;
- s.avail_in = *lenp - i;
- s.next_out = dst;
- s.avail_out = dstlen;
- r = zlib_inflate(&s, Z_FINISH);
- if (r != Z_OK && r != Z_STREAM_END) {
- printf("inflate returned %d msg: %s\n\r", r, s.msg);
- exit();
- }
- *lenp = s.next_out - (unsigned char *) dst;
- zlib_inflateEnd(&s);
-}
-
-/* Make a bi_rec in OF. We need to be passed a name for BI_BOOTLOADER_ID,
- * a machine type for BI_MACHTYPE, and the location where the end of the
- * bootloader is (PROG_START + PROG_SIZE)
- */
-void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
- unsigned long progend)
-{
- struct bi_record *rec;
-
-
- /* leave a 1MB gap then align to the next 1MB boundary */
- addr = _ALIGN(addr+ (1<<20) - 1, (1<<20));
- /* oldworld machine seem very unhappy about this. -- Tom */
- if (addr >= progend)
- claim(addr, 0x1000, 0);
-
- rec = (struct bi_record *)addr;
- rec->tag = BI_FIRST;
- rec->size = sizeof(struct bi_record);
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
- rec->tag = BI_BOOTLOADER_ID;
- sprintf( (char *)rec->data, name);
- rec->size = sizeof(struct bi_record) + strlen(name) + 1;
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
- rec->tag = BI_MACHTYPE;
- rec->data[0] = mach;
- rec->data[1] = 1;
- rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
- rec->tag = BI_LAST;
- rec->size = sizeof(struct bi_record);
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
-}
diff --git a/arch/ppc/boot/openfirmware/dummy.c b/arch/ppc/boot/openfirmware/dummy.c
deleted file mode 100644
index 31dbf45bf99..00000000000
--- a/arch/ppc/boot/openfirmware/dummy.c
+++ /dev/null
@@ -1,4 +0,0 @@
-int main(void)
-{
- return 0;
-}
diff --git a/arch/ppc/boot/openfirmware/misc.S b/arch/ppc/boot/openfirmware/misc.S
deleted file mode 100644
index ab9e897cadd..00000000000
--- a/arch/ppc/boot/openfirmware/misc.S
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- */
- .text
-
-/*
- * Use the BAT2 & 3 registers to map the 1st 16MB of RAM to
- * the address given as the 1st argument.
- */
- .globl setup_bats
-setup_bats:
- mfpvr 5
- rlwinm 5,5,16,16,31 /* r3 = 1 for 601, 4 for 604 */
- cmpwi 0,5,1
- li 0,0
- bne 4f
- mtibatl 3,0 /* invalidate BAT first */
- ori 3,3,4 /* set up BAT registers for 601 */
- li 4,0x7f
- mtibatu 2,3
- mtibatl 2,4
- oris 3,3,0x80
- oris 4,4,0x80
- mtibatu 3,3
- mtibatl 3,4
- b 5f
-4: mtdbatu 3,0 /* invalidate BATs first */
- mtibatu 3,0
- ori 3,3,0xff /* set up BAT registers for 604 */
- li 4,2
- mtdbatl 2,4
- mtdbatu 2,3
- mtibatl 2,4
- mtibatu 2,3
- oris 3,3,0x80
- oris 4,4,0x80
- mtdbatl 3,4
- mtdbatu 3,3
- mtibatl 3,4
- mtibatu 3,3
-5: sync
- isync
- blr
-
-/*
- * Flush the dcache and invalidate the icache for a range of addresses.
- *
- * flush_cache(addr, len)
- */
- .global flush_cache
-flush_cache:
- addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */
- rlwinm. 4,4,27,5,31
- mtctr 4
- beqlr
-1: dcbf 0,3
- icbi 0,3
- addi 3,3,0x20
- bdnz 1b
- sync
- isync
- blr
diff --git a/arch/ppc/boot/openfirmware/start.c b/arch/ppc/boot/openfirmware/start.c
deleted file mode 100644
index 1617a26956b..00000000000
--- a/arch/ppc/boot/openfirmware/start.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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 <stdarg.h>
-#include "of1275.h"
-
-extern int strlen(const char *s);
-extern void boot(int a1, int a2, void *prom);
-
-phandle stdin;
-phandle stdout;
-phandle stderr;
-
-void printk(char *fmt, ...);
-
-void
-start(int a1, int a2, void *promptr)
-{
- ofinit(promptr);
- if (ofstdio(&stdin, &stdout, &stderr))
- exit();
-
- boot(a1, a2, promptr);
- for (;;)
- exit();
-}
-
-int writestring(void *f, char *ptr, int nb)
-{
- int w = 0, i;
- char *ret = "\r";
-
- for (i = 0; i < nb; ++i) {
- if (ptr[i] == '\n') {
- if (i > w) {
- write(f, ptr + w, i - w);
- w = i;
- }
- write(f, ret, 1);
- }
- }
- if (w < nb)
- write(f, ptr + w, nb - w);
- return nb;
-}
-
-int
-putc(int c, void *f)
-{
- char ch = c;
-
- return writestring(f, &ch, 1) == 1? c: -1;
-}
-
-int
-putchar(int c)
-{
- return putc(c, stdout);
-}
-
-int
-fputs(char *str, void *f)
-{
- int n = strlen(str);
-
- return writestring(f, str, n) == n? 0: -1;
-}
-
-int
-readchar(void)
-{
- char ch;
-
- for (;;) {
- switch (read(stdin, &ch, 1)) {
- case 1:
- return ch;
- case -1:
- printk("read(stdin) returned -1\n");
- return -1;
- }
- }
-}
-
-static char line[256];
-static char *lineptr;
-static int lineleft;
-
-int
-getchar(void)
-{
- int c;
-
- if (lineleft == 0) {
- lineptr = line;
- for (;;) {
- c = readchar();
- if (c == -1 || c == 4)
- break;
- if (c == '\r' || c == '\n') {
- *lineptr++ = '\n';
- putchar('\n');
- break;
- }
- switch (c) {
- case 0177:
- case '\b':
- if (lineptr > line) {
- putchar('\b');
- putchar(' ');
- putchar('\b');
- --lineptr;
- }
- break;
- case 'U' & 0x1F:
- while (lineptr > line) {
- putchar('\b');
- putchar(' ');
- putchar('\b');
- --lineptr;
- }
- break;
- default:
- if (lineptr >= &line[sizeof(line) - 1])
- putchar('\a');
- else {
- putchar(c);
- *lineptr++ = c;
- }
- }
- }
- lineleft = lineptr - line;
- lineptr = line;
- }
- if (lineleft == 0)
- return -1;
- --lineleft;
- return *lineptr++;
-}
-
-extern int vsprintf(char *buf, const char *fmt, va_list args);
-static char sprint_buf[1024];
-
-void
-printk(char *fmt, ...)
-{
- va_list args;
- int n;
-
- va_start(args, fmt);
- n = vsprintf(sprint_buf, fmt, args);
- va_end(args);
- writestring(stdout, sprint_buf, n);
-}
-
-int
-printf(char *fmt, ...)
-{
- va_list args;
- int n;
-
- va_start(args, fmt);
- n = vsprintf(sprint_buf, fmt, args);
- va_end(args);
- writestring(stdout, sprint_buf, n);
- return n;
-}
diff --git a/arch/ppc/boot/simple/mpc10x_memory.c b/arch/ppc/boot/simple/mpc10x_memory.c
index c24290823f7..8da8f576031 100644
--- a/arch/ppc/boot/simple/mpc10x_memory.c
+++ b/arch/ppc/boot/simple/mpc10x_memory.c
@@ -50,10 +50,10 @@ MPC10X_PCI_OP(read, dword, u32 *, in_le32, 0)
* the system. This assumes that the firmware has correctly set up the memory
* controller registers. On CONFIG_PPC_PREP, we know we are being called
* under a PReP memory map. On all other machines, we assume we are under
- * a CHRP memory map. Further, on CONFIG_PPC_MULTIPLATFORM we must rename
+ * a CHRP memory map. Further, on CONFIG_PPC_PREP we must rename
* this function.
*/
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PREP
#define get_mem_size mpc10x_get_mem_size
#endif
unsigned long
diff --git a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S
index 7efddc50756..2533113c1cc 100644
--- a/arch/ppc/boot/simple/relocate.S
+++ b/arch/ppc/boot/simple/relocate.S
@@ -194,7 +194,7 @@ start_ldr:
/*
* Start at the begining.
*/
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PREP
li r9,0xc
mtlr r9
/* tell kernel we're prep, by putting 0xdeadc0de at KERNELLOAD,
diff --git a/arch/ppc/boot/utils/addnote.c b/arch/ppc/boot/utils/addnote.c
deleted file mode 100644
index 6c52b18f2d0..00000000000
--- a/arch/ppc/boot/utils/addnote.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Program to hack in a PT_NOTE program header entry in an ELF file.
- * This is needed for OF on RS/6000s to load an image correctly.
- * Note that OF needs a program header entry for the note, not an
- * ELF section.
- *
- * Copyright 2000 Paul Mackerras.
- *
- * This program is free software; 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.
- *
- * Usage: addnote zImage
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-
-char arch[] = "PowerPC";
-
-#define N_DESCR 6
-unsigned int descr[N_DESCR] = {
-#if 1
- /* values for IBM RS/6000 machines */
- 0xffffffff, /* real-mode = true */
- 0x00c00000, /* real-base, i.e. where we expect OF to be */
- 0xffffffff, /* real-size */
- 0xffffffff, /* virt-base */
- 0xffffffff, /* virt-size */
- 0x4000, /* load-base */
-#else
- /* values for longtrail CHRP */
- 0, /* real-mode = false */
- 0xffffffff, /* real-base */
- 0xffffffff, /* real-size */
- 0xffffffff, /* virt-base */
- 0xffffffff, /* virt-size */
- 0x00600000, /* load-base */
-#endif
-};
-
-unsigned char buf[512];
-
-#define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1]))
-#define GET_32BE(off) ((GET_16BE(off) << 16) + GET_16BE((off)+2))
-
-#define PUT_16BE(off, v) (buf[off] = ((v) >> 8) & 0xff, \
- buf[(off) + 1] = (v) & 0xff)
-#define PUT_32BE(off, v) (PUT_16BE((off), (v) >> 16), \
- PUT_16BE((off) + 2, (v)))
-
-/* Structure of an ELF file */
-#define E_IDENT 0 /* ELF header */
-#define E_PHOFF 28
-#define E_PHENTSIZE 42
-#define E_PHNUM 44
-#define E_HSIZE 52 /* size of ELF header */
-
-#define EI_MAGIC 0 /* offsets in E_IDENT area */
-#define EI_CLASS 4
-#define EI_DATA 5
-
-#define PH_TYPE 0 /* ELF program header */
-#define PH_OFFSET 4
-#define PH_FILESZ 16
-#define PH_HSIZE 32 /* size of program header */
-
-#define PT_NOTE 4 /* Program header type = note */
-
-#define ELFCLASS32 1
-#define ELFDATA2MSB 2
-
-unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
-
-int main(int ac, char **av)
-{
- int fd, n, i;
- int ph, ps, np;
- int nnote, ns;
-
- if (ac != 2) {
- fprintf(stderr, "Usage: %s elf-file\n", av[0]);
- exit(1);
- }
- fd = open(av[1], O_RDWR);
- if (fd < 0) {
- perror(av[1]);
- exit(1);
- }
-
- nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4;
-
- n = read(fd, buf, sizeof(buf));
- if (n < 0) {
- perror("read");
- exit(1);
- }
-
- if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0)
- goto notelf;
-
- if (buf[E_IDENT+EI_CLASS] != ELFCLASS32
- || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) {
- fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n",
- av[1]);
- exit(1);
- }
-
- ph = GET_32BE(E_PHOFF);
- ps = GET_16BE(E_PHENTSIZE);
- np = GET_16BE(E_PHNUM);
- if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
- goto notelf;
- if (ph + (np + 1) * ps + nnote > n)
- goto nospace;
-
- for (i = 0; i < np; ++i) {
- if (GET_32BE(ph + PH_TYPE) == PT_NOTE) {
- fprintf(stderr, "%s already has a note entry\n",
- av[1]);
- exit(0);
- }
- ph += ps;
- }
-
- /* XXX check that the area we want to use is all zeroes */
- for (i = 0; i < ps + nnote; ++i)
- if (buf[ph + i] != 0)
- goto nospace;
-
- /* fill in the program header entry */
- ns = ph + ps;
- PUT_32BE(ph + PH_TYPE, PT_NOTE);
- PUT_32BE(ph + PH_OFFSET, ns);
- PUT_32BE(ph + PH_FILESZ, nnote);
-
- /* fill in the note area we point to */
- /* XXX we should probably make this a proper section */
- PUT_32BE(ns, strlen(arch) + 1);
- PUT_32BE(ns + 4, N_DESCR * 4);
- PUT_32BE(ns + 8, 0x1275);
- strcpy(&buf[ns + 12], arch);
- ns += 12 + strlen(arch) + 1;
- for (i = 0; i < N_DESCR; ++i)
- PUT_32BE(ns + i * 4, descr[i]);
-
- /* Update the number of program headers */
- PUT_16BE(E_PHNUM, np + 1);
-
- /* write back */
- lseek(fd, (long) 0, SEEK_SET);
- i = write(fd, buf, n);
- if (i < 0) {
- perror("write");
- exit(1);
- }
- if (i < n) {
- fprintf(stderr, "%s: write truncated\n", av[1]);
- exit(1);
- }
-
- exit(0);
-
- notelf:
- fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]);
- exit(1);
-
- nospace:
- fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
- av[0]);
- exit(1);
-}
diff --git a/arch/ppc/boot/utils/hack-coff.c b/arch/ppc/boot/utils/hack-coff.c
deleted file mode 100644
index 5e5a6573a1e..00000000000
--- a/arch/ppc/boot/utils/hack-coff.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * hack-coff.c - hack the header of an xcoff file to fill in
- * a few fields needed by the Open Firmware xcoff loader on
- * Power Macs but not initialized by objcopy.
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include "rs6000.h"
-
-#define AOUT_MAGIC 0x010b
-
-#define get_16be(x) ((((unsigned char *)(x))[0] << 8) \
- + ((unsigned char *)(x))[1])
-#define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \
- ((unsigned char *)(x))[1] = (v) & 0xff)
-#define get_32be(x) ((((unsigned char *)(x))[0] << 24) \
- + (((unsigned char *)(x))[1] << 16) \
- + (((unsigned char *)(x))[2] << 8) \
- + ((unsigned char *)(x))[3])
-
-int
-main(int ac, char **av)
-{
- int fd;
- int i, nsect;
- int aoutsz;
- struct external_filehdr fhdr;
- AOUTHDR aout;
- struct external_scnhdr shdr;
-
- if (ac != 2) {
- fprintf(stderr, "Usage: hack-coff coff-file\n");
- exit(1);
- }
- if ((fd = open(av[1], 2)) == -1) {
- perror(av[2]);
- exit(1);
- }
- if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr))
- goto readerr;
- i = get_16be(fhdr.f_magic);
- if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) {
- fprintf(stderr, "%s: not an xcoff file\n", av[1]);
- exit(1);
- }
- aoutsz = get_16be(fhdr.f_opthdr);
- if (read(fd, &aout, aoutsz) != aoutsz)
- goto readerr;
- nsect = get_16be(fhdr.f_nscns);
- for (i = 0; i < nsect; ++i) {
- if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
- goto readerr;
- if (strcmp(shdr.s_name, ".text") == 0) {
- put_16be(aout.o_snentry, i+1);
- put_16be(aout.o_sntext, i+1);
- } else if (strcmp(shdr.s_name, ".data") == 0) {
- put_16be(aout.o_sndata, i+1);
- } else if (strcmp(shdr.s_name, ".bss") == 0) {
- put_16be(aout.o_snbss, i+1);
- }
- }
- put_16be(aout.magic, AOUT_MAGIC);
- if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1
- || write(fd, &aout, aoutsz) != aoutsz) {
- fprintf(stderr, "%s: write error\n", av[1]);
- exit(1);
- }
- close(fd);
- exit(0);
-
-readerr:
- fprintf(stderr, "%s: read error or file too short\n", av[1]);
- exit(1);
-}
diff --git a/arch/ppc/boot/utils/mknote.c b/arch/ppc/boot/utils/mknote.c
deleted file mode 100644
index b9fbb2cbfc8..00000000000
--- a/arch/ppc/boot/utils/mknote.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) Cort Dougan 1999.
- *
- * This program is free software; 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.
- *
- * Generate a note section as per the CHRP specification.
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff );
-
-int main(void)
-{
-/* header */
- /* namesz */
- PL(strlen("PowerPC")+1);
- /* descrsz */
- PL(6*4);
- /* type */
- PL(0x1275);
- /* name */
- printf("PowerPC"); printf("%c", 0);
-
-/* descriptor */
- /* real-mode */
- PL(0xffffffff);
- /* real-base */
- PL(0x00c00000);
- /* real-size */
- PL(0xffffffff);
- /* virt-base */
- PL(0xffffffff);
- /* virt-size */
- PL(0xffffffff);
- /* load-base */
- PL(0x4000);
- return 0;
-}
diff --git a/arch/ppc/configs/ibmchrp_defconfig b/arch/ppc/configs/ibmchrp_defconfig
deleted file mode 100644
index 27f3e69c1f9..00000000000
--- a/arch/ppc/configs/ibmchrp_defconfig
+++ /dev/null
@@ -1,875 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_GENERIC_NVRAM=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-# CONFIG_STANDALONE is not set
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Processor
-#
-CONFIG_6xx=y
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_POWER4 is not set
-# CONFIG_8xx is not set
-# CONFIG_ALTIVEC is not set
-# CONFIG_TAU is not set
-# CONFIG_CPU_FREQ is not set
-# CONFIG_PPC601_SYNC_FIX is not set
-CONFIG_PPC_STD_MMU=y
-
-#
-# Platform options
-#
-CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_APUS is not set
-# CONFIG_WILLOW is not set
-# CONFIG_PCORE is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_EV64260 is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX6 is not set
-# CONFIG_TQM8260 is not set
-CONFIG_PPC_CHRP=y
-CONFIG_PPC_PMAC=y
-CONFIG_PPC_PREP=y
-CONFIG_PPC_OF=y
-CONFIG_PPCBUG_NVRAM=y
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-CONFIG_HIGHMEM=y
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_PROC_DEVICETREE=y
-CONFIG_PPC_RTAS=y
-# CONFIG_PREP_RESIDUAL is not set
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# Bus options
-#
-CONFIG_ISA=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_HIGHMEM_START=0xfe000000
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE=0x80000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_LBD=y
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=y
-# CONFIG_SCSI_FC_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 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_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-# CONFIG_SCSI_MAC53C94 is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_ADB is not set
-# CONFIG_ADB_CUDA is not set
-# CONFIG_ADB_PMU is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_QUEUE is not set
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-# CONFIG_IP_NF_MATCH_PKTTYPE is not set
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_MANGLE is not set
-# CONFIG_IP_NF_TARGET_LOG is not set
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_RAW=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_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 testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=y
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_NET_POCKET 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_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# 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_RCPCI is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 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_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_INPORT is not set
-# CONFIG_MOUSE_LOGIBM is not set
-# CONFIG_MOUSE_PC110PAD is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-# CONFIG_SERIAL_8250_CONSOLE is not set
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-# CONFIG_SERIAL_PMACZILOG is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_OF=y
-# CONFIG_FB_CONTROL is not set
-# CONFIG_FB_PLATINUM is not set
-# CONFIG_FB_VALKYRIE is not set
-# CONFIG_FB_CT65550 is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_RIVA is not set
-CONFIG_FB_MATROX=y
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G450 is not set
-CONFIG_FB_MATROX_G100A=y
-CONFIG_FB_MATROX_G100=y
-# CONFIG_FB_MATROX_MULTIHEAD is not set
-# CONFIG_FB_RADEON_OLD is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-CONFIG_FB_3DFX=y
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# 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 is not set
-# CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_BOOTX_TEXT is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/pmac_defconfig b/arch/ppc/configs/pmac_defconfig
deleted file mode 100644
index a2db8b541c9..00000000000
--- a/arch/ppc/configs/pmac_defconfig
+++ /dev/null
@@ -1,1591 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc3
-# Wed Jul 13 14:13:13 2005
-#
-CONFIG_MMU=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_ALL is not set
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_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_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
-
-#
-# Processor
-#
-CONFIG_6xx=y
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_POWER4 is not set
-# CONFIG_8xx is not set
-# CONFIG_E200 is not set
-# CONFIG_E500 is not set
-CONFIG_PPC_FPU=y
-CONFIG_ALTIVEC=y
-CONFIG_TAU=y
-# CONFIG_TAU_INT is not set
-# CONFIG_TAU_AVERAGE is not set
-# CONFIG_KEXEC is not set
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_TABLE=y
-# CONFIG_CPU_FREQ_DEBUG is not set
-CONFIG_CPU_FREQ_STAT=m
-CONFIG_CPU_FREQ_STAT_DETAILS=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-CONFIG_CPU_FREQ_GOV_POWERSAVE=m
-CONFIG_CPU_FREQ_GOV_USERSPACE=m
-CONFIG_CPU_FREQ_GOV_ONDEMAND=m
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
-CONFIG_CPU_FREQ_PMAC=y
-CONFIG_PPC601_SYNC_FIX=y
-CONFIG_PM=y
-CONFIG_PPC_STD_MMU=y
-
-#
-# Platform options
-#
-CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_APUS is not set
-# CONFIG_KATANA is not set
-# CONFIG_WILLOW is not set
-# CONFIG_CPCI690 is not set
-# CONFIG_PCORE is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_CHESTNUT is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_HDPU is not set
-# CONFIG_EV64260 is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_RADSTONE_PPC7D is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBC82xx is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX8260 is not set
-# CONFIG_TQM8260 is not set
-# CONFIG_ADS8272 is not set
-# CONFIG_PQ2FADS is not set
-# CONFIG_LITE5200 is not set
-# CONFIG_MPC834x_SYS is not set
-CONFIG_PPC_CHRP=y
-CONFIG_PPC_PMAC=y
-CONFIG_PPC_PREP=y
-CONFIG_PPC_OF=y
-CONFIG_PPCBUG_NVRAM=y
-# CONFIG_SMP is not set
-# CONFIG_HIGHMEM is not set
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_PREP_RESIDUAL is not set
-# CONFIG_CMDLINE_BOOL is not set
-# CONFIG_PM_DEBUG is not set
-CONFIG_SOFTWARE_SUSPEND=y
-CONFIG_PM_STD_PARTITION=""
-# CONFIG_SECCOMP is not set
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-# CONFIG_ISA is not set
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-# CONFIG_PCI_DEBUG is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-CONFIG_PCCARD=m
-# CONFIG_PCMCIA_DEBUG is not set
-CONFIG_PCMCIA=m
-# CONFIG_PCMCIA_LOAD_CIS is not set
-# CONFIG_PCMCIA_IOCTL is not set
-CONFIG_CARDBUS=y
-
-#
-# PC-card bridges
-#
-CONFIG_YENTA=m
-# CONFIG_PD6729 is not set
-# CONFIG_I82092 is not set
-# CONFIG_TCIC is not set
-CONFIG_PCCARD_NONSTATIC=m
-
-#
-# Advanced setup
-#
-CONFIG_ADVANCED_OPTIONS=y
-CONFIG_HIGHMEM_START=0xfe000000
-# CONFIG_LOWMEM_SIZE_BOOL is not set
-CONFIG_LOWMEM_SIZE=0x30000000
-# CONFIG_KERNEL_START_BOOL is not set
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE_BOOL=y
-CONFIG_TASK_SIZE=0xc0000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-CONFIG_IP_NF_MATCH_SCTP=m
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_CONNMARK=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_CONNMARK=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
-CONFIG_NET_POLL_CONTROLLER=y
-# CONFIG_HAMRADIO is not set
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-# CONFIG_IRDA_ULTRA is not set
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-CONFIG_IRTTY_SIR=m
-
-#
-# Dongle support
-#
-# CONFIG_DONGLE is not set
-
-#
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
-# FIR device drivers
-#
-# CONFIG_USB_IRDA is not set
-# CONFIG_SIGMATEL_FIR is not set
-# CONFIG_NSC_FIR is not set
-# CONFIG_WINBOND_FIR is not set
-# CONFIG_TOSHIBA_FIR is not set
-# CONFIG_SMC_IRCC_FIR is not set
-# CONFIG_ALI_FIR is not set
-# CONFIG_VLSI_FIR is not set
-# CONFIG_VIA_FIR is not set
-# CONFIG_BT is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-# CONFIG_STANDALONE is not set
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-CONFIG_MAC_FLOPPY=m
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_LBD=y
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECS is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-CONFIG_BLK_DEV_IDESCSI=y
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_IDE_GENERIC is not set
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-CONFIG_BLK_DEV_GENERIC=y
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-CONFIG_BLK_DEV_PDC202XX_NEW=y
-# CONFIG_PDC202XX_FORCE is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_IDE_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
-CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_BLINK=y
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=y
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# 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=m
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-CONFIG_AIC7XXX_DEBUG_ENABLE=y
-CONFIG_AIC7XXX_DEBUG_MASK=0
-CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
-CONFIG_SCSI_AIC7XXX_OLD=m
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 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_MESH=y
-CONFIG_SCSI_MESH_SYNC_RATE=5
-CONFIG_SCSI_MESH_RESET_DELAY_MS=1000
-CONFIG_SCSI_MAC53C94=y
-
-#
-# PCMCIA SCSI adapter support
-#
-# CONFIG_PCMCIA_AHA152X is not set
-# CONFIG_PCMCIA_FDOMAIN is not set
-# CONFIG_PCMCIA_NINJA_SCSI is not set
-# CONFIG_PCMCIA_QLOGIC is not set
-# CONFIG_PCMCIA_SYM53C500 is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_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
-
-#
-# IEEE 1394 (FireWire) support
-#
-CONFIG_IEEE1394=m
-
-#
-# Subsystem Options
-#
-# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
-CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
-CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
-
-#
-# Device Drivers
-#
-# CONFIG_IEEE1394_PCILYNX is not set
-CONFIG_IEEE1394_OHCI1394=m
-
-#
-# Protocol Drivers
-#
-CONFIG_IEEE1394_VIDEO1394=m
-CONFIG_IEEE1394_SBP2=m
-# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
-CONFIG_IEEE1394_ETH1394=m
-CONFIG_IEEE1394_DV1394=m
-CONFIG_IEEE1394_RAWIO=m
-CONFIG_IEEE1394_CMP=m
-CONFIG_IEEE1394_AMDTP=m
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-CONFIG_ADB=y
-CONFIG_ADB_CUDA=y
-CONFIG_ADB_PMU=y
-CONFIG_PMAC_APM_EMU=y
-CONFIG_PMAC_MEDIABAY=y
-CONFIG_PMAC_BACKLIGHT=y
-CONFIG_ADB_MACIO=y
-CONFIG_INPUT_ADBHID=y
-CONFIG_MAC_EMUMOUSEBTN=y
-CONFIG_THERM_WINDTUNNEL=m
-CONFIG_THERM_ADT746X=m
-# CONFIG_ANSLCD 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=m
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACE=y
-# CONFIG_MACE_AAUI_PORT is not set
-CONFIG_BMAC=y
-# CONFIG_HAPPYMEAL is not set
-CONFIG_SUNGEM=y
-# 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
-CONFIG_PCNET32=y
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-
-#
-# 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_SKGE 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_MV643XX_ETH is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-# CONFIG_PCMCIA_WAVELAN is not set
-# CONFIG_PCMCIA_NETWAVE is not set
-
-#
-# Wireless 802.11 Frequency Hopping cards support
-#
-# CONFIG_PCMCIA_RAYCS is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-CONFIG_HERMES=m
-CONFIG_APPLE_AIRPORT=m
-# CONFIG_PLX_HERMES is not set
-# CONFIG_TMD_HERMES is not set
-# CONFIG_PCI_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Wireless 802.11b Pcmcia/Cardbus cards support
-#
-CONFIG_PCMCIA_HERMES=m
-# CONFIG_AIRO_CS is not set
-# CONFIG_PCMCIA_WL3501 is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-CONFIG_NETCONSOLE=m
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-# CONFIG_MOUSE_PS2 is not set
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=m
-CONFIG_SERIAL_8250_CS=m
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_SERIAL_PMACZILOG=y
-CONFIG_SERIAL_PMACZILOG_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
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-CONFIG_AGP=m
-CONFIG_AGP_UNINORTH=m
-CONFIG_DRM=m
-# CONFIG_DRM_TDFX is not set
-CONFIG_DRM_R128=m
-CONFIG_DRM_RADEON=m
-# CONFIG_DRM_MGA is not set
-# CONFIG_DRM_SIS is not set
-# CONFIG_DRM_VIA is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=m
-
-#
-# I2C Algorithms
-#
-CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_HYDRA is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_ISA is not set
-CONFIG_I2C_KEYWEST=m
-# CONFIG_I2C_MPC is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 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_RTC8564 is not set
-# CONFIG_SENSORS_M41T00 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
-CONFIG_FB_MACMODES=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_OF=y
-CONFIG_FB_CONTROL=y
-CONFIG_FB_PLATINUM=y
-CONFIG_FB_VALKYRIE=y
-CONFIG_FB_CT65550=y
-# CONFIG_FB_ASILIANT is not set
-CONFIG_FB_IMSTT=y
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-CONFIG_FB_MATROX=y
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G=y
-# CONFIG_FB_MATROX_I2C is not set
-# CONFIG_FB_MATROX_MULTIHEAD is not set
-# CONFIG_FB_RADEON_OLD is not set
-CONFIG_FB_RADEON=y
-CONFIG_FB_RADEON_I2C=y
-# CONFIG_FB_RADEON_DEBUG is not set
-CONFIG_FB_ATY128=y
-CONFIG_FB_ATY=y
-CONFIG_FB_ATY_CT=y
-CONFIG_FB_ATY_GENERIC_LCD=y
-# CONFIG_FB_ATY_XL_INIT is not set
-CONFIG_FB_ATY_GX=y
-# 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=y
-CONFIG_FB_3DFX_ACCEL=y
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_LCD_DEVICE=y
-
-#
-# Sound
-#
-CONFIG_SOUND=m
-CONFIG_DMASOUND_PMAC=m
-CONFIG_DMASOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=m
-CONFIG_SND_TIMER=m
-CONFIG_SND_PCM=m
-CONFIG_SND_HWDEP=m
-CONFIG_SND_RAWMIDI=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-CONFIG_SND_DUMMY=m
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# PCI devices
-#
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_ATIIXP is not set
-# CONFIG_SND_ATIIXP_MODEM is not set
-# CONFIG_SND_AU8810 is not set
-# CONFIG_SND_AU8820 is not set
-# CONFIG_SND_AU8830 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_FM801 is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_HDA_INTEL is not set
-
-#
-# ALSA PowerMac devices
-#
-CONFIG_SND_POWERMAC=m
-
-#
-# USB devices
-#
-CONFIG_SND_USB_AUDIO=m
-CONFIG_SND_USB_USX2Y=m
-
-#
-# PCMCIA devices
-#
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
-CONFIG_USB_DYNAMIC_MINORS=y
-CONFIG_USB_SUSPEND=y
-# CONFIG_USB_OTG is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_EHCI_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-# CONFIG_USB_UHCI_HCD is not set
-# CONFIG_USB_SL811_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-# CONFIG_USB_STORAGE is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-CONFIG_USB_PEGASUS=m
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_ZD1201 is not set
-# CONFIG_USB_MON is not set
-
-#
-# USB port drivers
-#
-
-#
-# USB Serial Converter support
-#
-CONFIG_USB_SERIAL=m
-# CONFIG_USB_SERIAL_GENERIC is not set
-# CONFIG_USB_SERIAL_AIRPRIME is not set
-# CONFIG_USB_SERIAL_BELKIN is not set
-# CONFIG_USB_SERIAL_WHITEHEAT is not set
-# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_CP2101 is not set
-# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
-# CONFIG_USB_SERIAL_EMPEG is not set
-# CONFIG_USB_SERIAL_FTDI_SIO is not set
-CONFIG_USB_SERIAL_VISOR=m
-# CONFIG_USB_SERIAL_IPAQ is not set
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
-# CONFIG_USB_SERIAL_GARMIN is not set
-# CONFIG_USB_SERIAL_IPW is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-CONFIG_USB_SERIAL_KEYSPAN=m
-CONFIG_USB_SERIAL_KEYSPAN_MPR=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19=y
-CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
-# CONFIG_USB_SERIAL_KLSI is not set
-# CONFIG_USB_SERIAL_KOBIL_SCT is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_PL2303 is not set
-# CONFIG_USB_SERIAL_HP4X is not set
-# CONFIG_USB_SERIAL_SAFE is not set
-# CONFIG_USB_SERIAL_TI is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-# CONFIG_USB_SERIAL_OPTION is not set
-# CONFIG_USB_SERIAL_OMNINET is not set
-CONFIG_USB_EZUSB=y
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# SN Devices
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-# CONFIG_EXT2_FS_POSIX_ACL is not set
-# CONFIG_EXT2_FS_SECURITY is not set
-# CONFIG_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_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
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_TMPFS_SECURITY=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_CRAMFS=m
-# 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=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V2_ACL=y
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_V3_ACL=y
-# CONFIG_NFSD_V4 is not set
-CONFIG_NFSD_TCP=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_ACL_SUPPORT=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-CONFIG_NLS_ISO8859_15=m
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-CONFIG_NLS_UTF8=m
-
-#
-# Library routines
-#
-CONFIG_CRC_CCITT=y
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOG_BUF_SHIFT=16
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_XMON is not set
-# CONFIG_BDI_SWITCH is not set
-CONFIG_BOOTX_TEXT=y
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/ppc/configs/power3_defconfig b/arch/ppc/configs/power3_defconfig
deleted file mode 100644
index a1ef929bca5..00000000000
--- a/arch/ppc/configs/power3_defconfig
+++ /dev/null
@@ -1,1035 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_GENERIC_NVRAM=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-# CONFIG_STANDALONE is not set
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=15
-# CONFIG_HOTPLUG is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-CONFIG_STOP_MACHINE=y
-
-#
-# Processor
-#
-# CONFIG_6xx is not set
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-CONFIG_POWER3=y
-# CONFIG_POWER4 is not set
-# CONFIG_8xx is not set
-# CONFIG_CPU_FREQ is not set
-CONFIG_PPC64BRIDGE=y
-CONFIG_PPC_STD_MMU=y
-
-#
-# Platform options
-#
-CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_APUS is not set
-# CONFIG_WILLOW is not set
-# CONFIG_PCORE is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_EV64260 is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX6 is not set
-# CONFIG_TQM8260 is not set
-CONFIG_PPC_CHRP=y
-CONFIG_PPC_PMAC=y
-CONFIG_PPC_PREP=y
-CONFIG_PPC_OF=y
-CONFIG_PPCBUG_NVRAM=y
-CONFIG_SMP=y
-# CONFIG_IRQ_ALL_CPUS is not set
-CONFIG_NR_CPUS=32
-# CONFIG_PREEMPT is not set
-CONFIG_HIGHMEM=y
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_PROC_DEVICETREE=y
-CONFIG_PPC_RTAS=y
-# CONFIG_PREP_RESIDUAL is not set
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# Bus options
-#
-CONFIG_ISA=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-
-#
-# Advanced setup
-#
-CONFIG_ADVANCED_OPTIONS=y
-# CONFIG_HIGHMEM_START_BOOL is not set
-CONFIG_HIGHMEM_START=0xfe000000
-# CONFIG_LOWMEM_SIZE_BOOL is not set
-CONFIG_LOWMEM_SIZE=0x30000000
-# CONFIG_KERNEL_START_BOOL is not set
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE_BOOL=y
-CONFIG_TASK_SIZE=0xc0000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-# CONFIG_PARPORT_SERIAL is not set
-CONFIG_PARPORT_PC_FIFO=y
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_OTHER is not set
-# CONFIG_PARPORT_1284 is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_LBD=y
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=y
-# CONFIG_SCSI_FC_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 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_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_NCR53C406A is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-# CONFIG_SCSI_MAC53C94 is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-CONFIG_MD_RAID5=y
-CONFIG_MD_RAID6=y
-# CONFIG_MD_MULTIPATH is not set
-CONFIG_BLK_DEV_DM=y
-CONFIG_DM_CRYPT=y
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_ADB is not set
-# CONFIG_ADB_CUDA is not set
-# CONFIG_ADB_PMU is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_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 testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=y
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-# 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 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-CONFIG_GAMEPORT=m
-CONFIG_SOUND_GAMEPORT=m
-# CONFIG_GAMEPORT_NS558 is not set
-# CONFIG_GAMEPORT_L4 is not set
-# CONFIG_GAMEPORT_EMU10K1 is not set
-# CONFIG_GAMEPORT_VORTEX is not set
-# CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461x is not set
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_PCIPS2 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_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_INPORT is not set
-# CONFIG_MOUSE_LOGIBM is not set
-# CONFIG_MOUSE_PC110PAD is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_PMACZILOG is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_PRINTER=m
-# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
-# CONFIG_TIPAR is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-CONFIG_I2C_ALGOBIT=y
-CONFIG_I2C_ALGOPCF=y
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_HYDRA is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_KEYWEST is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-
-#
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_OF=y
-# CONFIG_FB_CONTROL is not set
-# CONFIG_FB_PLATINUM is not set
-# CONFIG_FB_VALKYRIE is not set
-# CONFIG_FB_CT65550 is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_RIVA is not set
-CONFIG_FB_MATROX=y
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G450 is not set
-CONFIG_FB_MATROX_G100A=y
-CONFIG_FB_MATROX_G100=y
-CONFIG_FB_MATROX_I2C=y
-# CONFIG_FB_MATROX_MAVEN is not set
-CONFIG_FB_MATROX_MULTIHEAD=y
-# CONFIG_FB_RADEON_OLD is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_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_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-# CONFIG_DMASOUND_PMAC is not set
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=m
-CONFIG_SND_TIMER=m
-CONFIG_SND_PCM=m
-CONFIG_SND_HWDEP=m
-CONFIG_SND_RAWMIDI=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-CONFIG_SND_MPU401_UART=m
-CONFIG_SND_OPL3_LIB=m
-CONFIG_SND_DUMMY=m
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# ISA devices
-#
-# CONFIG_SND_AD1848 is not set
-# CONFIG_SND_CS4231 is not set
-CONFIG_SND_CS4232=m
-# CONFIG_SND_CS4236 is not set
-# CONFIG_SND_ES1688 is not set
-# CONFIG_SND_ES18XX is not set
-# CONFIG_SND_GUSCLASSIC is not set
-# CONFIG_SND_GUSEXTREME is not set
-# CONFIG_SND_GUSMAX is not set
-# CONFIG_SND_INTERWAVE is not set
-# CONFIG_SND_INTERWAVE_STB is not set
-# CONFIG_SND_OPTI92X_AD1848 is not set
-# CONFIG_SND_OPTI92X_CS4231 is not set
-# CONFIG_SND_OPTI93X is not set
-# CONFIG_SND_SB8 is not set
-# CONFIG_SND_SB16 is not set
-# CONFIG_SND_SBAWE is not set
-# CONFIG_SND_WAVEFRONT is not set
-# CONFIG_SND_CMI8330 is not set
-# CONFIG_SND_OPL3SA2 is not set
-# CONFIG_SND_SGALAXY is not set
-# CONFIG_SND_SSCAPE is not set
-
-#
-# PCI devices
-#
-CONFIG_SND_AC97_CODEC=m
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_ATIIXP is not set
-# CONFIG_SND_AU8810 is not set
-# CONFIG_SND_AU8820 is not set
-# CONFIG_SND_AU8830 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-CONFIG_SND_CS46XX=m
-# CONFIG_SND_CS46XX_NEW_DSP is not set
-CONFIG_SND_CS4281=m
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_FM801 is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VX222 is not set
-
-#
-# ALSA PowerMac devices
-#
-# CONFIG_SND_POWERMAC is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-# CONFIG_ZISOFS 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_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# 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 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_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
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_BOOTX_TEXT=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-# CONFIG_CRYPTO_SERPENT is not set
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_TEST is not set
diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/prep_defconfig
index 4d33bee23a8..4d33bee23a8 100644
--- a/arch/ppc/configs/common_defconfig
+++ b/arch/ppc/configs/prep_defconfig
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index e399bbb969a..466437f4bcb 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -1,48 +1,24 @@
#
# Makefile for the linux kernel.
#
-ifneq ($(CONFIG_PPC_MERGE),y)
-
extra-$(CONFIG_PPC_STD_MMU) := head.o
extra-$(CONFIG_40x) := head_4xx.o
extra-$(CONFIG_44x) := head_44x.o
extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o
extra-$(CONFIG_8xx) := head_8xx.o
-extra-$(CONFIG_6xx) += idle_6xx.o
extra-y += vmlinux.lds
-obj-y := entry.o traps.o idle.o time.o misc.o \
+obj-y := entry.o traps.o time.o misc.o \
setup.o \
ppc_htab.o
-obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
-obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
-obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
+obj-$(CONFIG_MODULES) += ppc_ksyms.o
obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_RAPIDIO) += rio.o
obj-$(CONFIG_KGDB) += ppc-stub.o
obj-$(CONFIG_SMP) += smp.o smp-tbsync.o
-obj-$(CONFIG_TAU) += temp.o
-ifndef CONFIG_E200
-obj-$(CONFIG_FSL_BOOKE) += perfmon_fsl_booke.o
-endif
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
ifndef CONFIG_MATH_EMULATION
obj-$(CONFIG_8xx) += softemu8xx.o
endif
-
-# These are here while we do the architecture merge
-
-else
-obj-y := idle.o
-obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
-obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
-obj-$(CONFIG_MODULES) += module.o
-obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o
-obj-$(CONFIG_KGDB) += ppc-stub.o
-obj-$(CONFIG_TAU) += temp.o
-ifndef CONFIG_E200
-obj-$(CONFIG_FSL_BOOKE) += perfmon_fsl_booke.o
-endif
-endif
diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
index 77e4dc780f8..2f5c5e15761 100644
--- a/arch/ppc/kernel/asm-offsets.c
+++ b/arch/ppc/kernel/asm-offsets.c
@@ -134,6 +134,7 @@ main(void)
DEFINE(TI_TASK, offsetof(struct thread_info, task));
DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 3a281597848..1adc9145516 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -128,45 +128,48 @@ transfer_to_handler:
stw r12,4(r11)
#endif
b 3f
+
2: /* if from kernel, check interrupted DOZE/NAP mode and
* check for stack overflow
*/
+ lwz r9,THREAD_INFO-THREAD(r12)
+ cmplw r1,r9 /* if r1 <= current->thread_info */
+ ble- stack_ovf /* then the kernel stack overflowed */
+5:
#ifdef CONFIG_6xx
- mfspr r11,SPRN_HID0
- mtcr r11
-BEGIN_FTR_SECTION
- bt- 8,power_save_6xx_restore /* Check DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-BEGIN_FTR_SECTION
- bt- 9,power_save_6xx_restore /* Check NAP */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+ tophys(r9,r9) /* check local flags */
+ lwz r12,TI_LOCAL_FLAGS(r9)
+ mtcrf 0x01,r12
+ bt- 31-TLF_NAPPING,4f
#endif /* CONFIG_6xx */
.globl transfer_to_handler_cont
transfer_to_handler_cont:
- lwz r11,THREAD_INFO-THREAD(r12)
- cmplw r1,r11 /* if r1 <= current->thread_info */
- ble- stack_ovf /* then the kernel stack overflowed */
3:
mflr r9
lwz r11,0(r9) /* virtual address of handler */
lwz r9,4(r9) /* where to go when done */
- FIX_SRR1(r10,r12)
mtspr SPRN_SRR0,r11
mtspr SPRN_SRR1,r10
mtlr r9
SYNC
RFI /* jump to handler, enable MMU */
+#ifdef CONFIG_6xx
+4: rlwinm r12,r12,0,~_TLF_NAPPING
+ stw r12,TI_LOCAL_FLAGS(r9)
+ b power_save_6xx_restore
+#endif
+
/*
* On kernel stack overflow, load up an initial stack pointer
* and call StackOverflow(regs), which should not return.
*/
stack_ovf:
/* sometimes we use a statically-allocated stack, which is OK. */
- lis r11,_end@h
- ori r11,r11,_end@l
- cmplw r1,r11
- ble 3b /* r1 <= &_end is OK */
+ lis r12,_end@h
+ ori r12,r12,_end@l
+ cmplw r1,r12
+ ble 5b /* r1 <= &_end is OK */
SAVE_NVGPRS(r11)
addi r3,r1,STACK_FRAME_OVERHEAD
lis r1,init_thread_union@ha
@@ -926,55 +929,3 @@ END_FTR_SECTION_IFSET(CPU_FTR_601)
b 4b
.comm ee_restarts,4
-
-/*
- * PROM code for specific machines follows. Put it
- * here so it's easy to add arch-specific sections later.
- * -- Cort
- */
-#ifdef CONFIG_PPC_OF
-/*
- * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
- * called with the MMU off.
- */
-_GLOBAL(enter_rtas)
- stwu r1,-INT_FRAME_SIZE(r1)
- mflr r0
- stw r0,INT_FRAME_SIZE+4(r1)
- lis r4,rtas_data@ha
- lwz r4,rtas_data@l(r4)
- lis r6,1f@ha /* physical return address for rtas */
- addi r6,r6,1f@l
- tophys(r6,r6)
- tophys(r7,r1)
- lis r8,rtas_entry@ha
- lwz r8,rtas_entry@l(r8)
- mfmsr r9
- stw r9,8(r1)
- LOAD_MSR_KERNEL(r0,MSR_KERNEL)
- SYNC /* disable interrupts so SRR0/1 */
- MTMSRD(r0) /* don't get trashed */
- li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
- mtlr r6
- CLR_TOP32(r7)
- mtspr SPRN_SPRG2,r7
- mtspr SPRN_SRR0,r8
- mtspr SPRN_SRR1,r9
- RFI
-1: tophys(r9,r1)
- lwz r8,INT_FRAME_SIZE+4(r9) /* get return address */
- lwz r9,8(r9) /* original msr value */
- FIX_SRR1(r9,r0)
- addi r1,r1,INT_FRAME_SIZE
- li r0,0
- mtspr SPRN_SPRG2,r0
- mtspr SPRN_SRR0,r8
- mtspr SPRN_SRR1,r9
- RFI /* return to caller */
-
- .globl machine_check_in_rtas
-machine_check_in_rtas:
- twi 31,0,0
- /* XXX load up BATs and panic */
-
-#endif /* CONFIG_PPC_OF */
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 53ea845fb91..01303efedda 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -37,19 +37,6 @@
#include <asm/amigappc.h>
#endif
-#ifdef CONFIG_PPC64BRIDGE
-#define LOAD_BAT(n, reg, RA, RB) \
- ld RA,(n*32)+0(reg); \
- ld RB,(n*32)+8(reg); \
- mtspr SPRN_IBAT##n##U,RA; \
- mtspr SPRN_IBAT##n##L,RB; \
- ld RA,(n*32)+16(reg); \
- ld RB,(n*32)+24(reg); \
- mtspr SPRN_DBAT##n##U,RA; \
- mtspr SPRN_DBAT##n##L,RB; \
-
-#else /* CONFIG_PPC64BRIDGE */
-
/* 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 */ \
@@ -66,7 +53,6 @@
mtspr SPRN_DBAT##n##U,RA; \
mtspr SPRN_DBAT##n##L,RB; \
1:
-#endif /* CONFIG_PPC64BRIDGE */
.text
.stabs "arch/ppc/kernel/",N_SO,0,0,0f
@@ -129,11 +115,6 @@ _start:
.globl __start
__start:
-/*
- * We have to do any OF calls before we map ourselves to KERNELBASE,
- * because OF may have I/O devices mapped into that area
- * (particularly on CHRP).
- */
mr r31,r3 /* save parameters */
mr r30,r4
mr r29,r5
@@ -148,14 +129,6 @@ __start:
*/
bl early_init
-/*
- * On POWER4, we first need to tweak some CPU configuration registers
- * like real mode cache inhibit or exception base
- */
-#ifdef CONFIG_POWER4
- bl __970_cpu_preinit
-#endif /* CONFIG_POWER4 */
-
#ifdef CONFIG_APUS
/* On APUS the __va/__pa constants need to be set to the correct
* values before continuing.
@@ -169,7 +142,6 @@ __start:
*/
bl mmu_off
__after_mmu_off:
-#ifndef CONFIG_POWER4
bl clear_bats
bl flush_tlbs
@@ -177,10 +149,6 @@ __after_mmu_off:
#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
bl setup_disp_bat
#endif
-#else /* CONFIG_POWER4 */
- bl reloc_offset
- bl initial_mm_power4
-#endif /* CONFIG_POWER4 */
/*
* Call setup_cpu for CPU 0 and initialize 6xx Idle
@@ -192,18 +160,11 @@ __after_mmu_off:
bl reloc_offset
bl init_idle_6xx
#endif /* CONFIG_6xx */
-#ifdef CONFIG_POWER4
- bl reloc_offset
- bl init_idle_power4
-#endif /* CONFIG_POWER4 */
#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
- * the exception vectors at 0 (and therefore this copy
- * overwrites OF's exception vectors with our own).
* If the MMU is already turned on, we copy stuff to KERNELBASE,
* otherwise we copy it to 0.
*/
@@ -358,51 +319,19 @@ i##n: \
#endif
/* Machine check */
-/*
- * On CHRP, this is complicated by the fact that we could get a
- * machine check inside RTAS, and we have no guarantee that certain
- * critical registers will have the values we expect. The set of
- * registers that might have bad values includes all the GPRs
- * and all the BATs. We indicate that we are in RTAS by putting
- * a non-zero value, the address of the exception frame to use,
- * in SPRG2. The machine check handler checks SPRG2 and uses its
- * value if it is non-zero. If we ever needed to free up SPRG2,
- * we could use a field in the thread_info or thread_struct instead.
- * (Other exception handlers assume that r1 is a valid kernel stack
- * pointer when we take an exception from supervisor mode.)
- * -- paulus.
- */
. = 0x200
mtspr SPRN_SPRG0,r10
mtspr SPRN_SPRG1,r11
mfcr r10
-#ifdef CONFIG_PPC_CHRP
- mfspr r11,SPRN_SPRG2
- cmpwi 0,r11,0
- bne 7f
-#endif /* CONFIG_PPC_CHRP */
EXCEPTION_PROLOG_1
7: EXCEPTION_PROLOG_2
addi r3,r1,STACK_FRAME_OVERHEAD
-#ifdef CONFIG_PPC_CHRP
- mfspr r4,SPRN_SPRG2
- cmpwi cr1,r4,0
- bne cr1,1f
-#endif
EXC_XFER_STD(0x200, machine_check_exception)
-#ifdef CONFIG_PPC_CHRP
-1: b machine_check_in_rtas
-#endif
/* Data access exception. */
. = 0x300
-#ifdef CONFIG_PPC64BRIDGE
- b DataAccess
-DataAccessCont:
-#else
DataAccess:
EXCEPTION_PROLOG
-#endif /* CONFIG_PPC64BRIDGE */
mfspr r10,SPRN_DSISR
andis. r0,r10,0xa470 /* weird error? */
bne 1f /* if not, try to put a PTE */
@@ -414,21 +343,10 @@ DataAccess:
mfspr r4,SPRN_DAR
EXC_XFER_EE_LITE(0x300, handle_page_fault)
-#ifdef CONFIG_PPC64BRIDGE
-/* SLB fault on data access. */
- . = 0x380
- b DataSegment
-#endif /* CONFIG_PPC64BRIDGE */
-
/* Instruction access exception. */
. = 0x400
-#ifdef CONFIG_PPC64BRIDGE
- b InstructionAccess
-InstructionAccessCont:
-#else
InstructionAccess:
EXCEPTION_PROLOG
-#endif /* CONFIG_PPC64BRIDGE */
andis. r0,r9,0x4000 /* no pte found? */
beq 1f /* if so, try to put a PTE */
li r3,0 /* into the hash table */
@@ -438,12 +356,6 @@ InstructionAccess:
mr r5,r9
EXC_XFER_EE_LITE(0x400, handle_page_fault)
-#ifdef CONFIG_PPC64BRIDGE
-/* SLB fault on instruction access. */
- . = 0x480
- b InstructionSegment
-#endif /* CONFIG_PPC64BRIDGE */
-
/* External interrupt */
EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
@@ -708,15 +620,9 @@ DataStoreTLBMiss:
EXCEPTION(0x1300, Trap_13, instruction_breakpoint_exception, EXC_XFER_EE)
EXCEPTION(0x1400, SMI, SMIException, EXC_XFER_EE)
EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
-#ifdef CONFIG_POWER4
- EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1700, Trap_17, altivec_assist_exception, EXC_XFER_EE)
- EXCEPTION(0x1800, Trap_18, TAUException, EXC_XFER_STD)
-#else /* !CONFIG_POWER4 */
EXCEPTION(0x1600, Trap_16, altivec_assist_exception, EXC_XFER_EE)
EXCEPTION(0x1700, Trap_17, TAUException, EXC_XFER_STD)
EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
-#endif /* CONFIG_POWER4 */
EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x1a00, Trap_1a, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x1b00, Trap_1b, unknown_exception, EXC_XFER_EE)
@@ -754,28 +660,6 @@ AltiVecUnavailable:
addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception)
-#ifdef CONFIG_PPC64BRIDGE
-DataAccess:
- EXCEPTION_PROLOG
- b DataAccessCont
-
-InstructionAccess:
- EXCEPTION_PROLOG
- b InstructionAccessCont
-
-DataSegment:
- EXCEPTION_PROLOG
- addi r3,r1,STACK_FRAME_OVERHEAD
- mfspr r4,SPRN_DAR
- stw r4,_DAR(r11)
- EXC_XFER_STD(0x380, unknown_exception)
-
-InstructionSegment:
- EXCEPTION_PROLOG
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_STD(0x480, unknown_exception)
-#endif /* CONFIG_PPC64BRIDGE */
-
#ifdef CONFIG_ALTIVEC
/* Note that the AltiVec support is closely modeled after the FP
* support. Changes to one are likely to be applicable to the
@@ -1048,13 +932,6 @@ __secondary_start_pmac_0:
.globl __secondary_start
__secondary_start:
-#ifdef CONFIG_PPC64BRIDGE
- mfmsr r0
- clrldi r0,r0,1 /* make sure it's in 32-bit mode */
- SYNC
- MTMSRD(r0)
- isync
-#endif
/* Copy some CPU settings from CPU 0 */
bl __restore_cpu_setup
@@ -1065,10 +942,6 @@ __secondary_start:
lis r3,-KERNELBASE@h
bl init_idle_6xx
#endif /* CONFIG_6xx */
-#ifdef CONFIG_POWER4
- lis r3,-KERNELBASE@h
- bl init_idle_power4
-#endif /* CONFIG_POWER4 */
/* get current_thread_info and current */
lis r1,secondary_ti@ha
@@ -1109,12 +982,12 @@ __secondary_start:
* Those generic dummy functions are kept for CPUs not
* included in CONFIG_6xx
*/
-#if !defined(CONFIG_6xx) && !defined(CONFIG_POWER4)
+#if !defined(CONFIG_6xx)
_GLOBAL(__save_cpu_setup)
blr
_GLOBAL(__restore_cpu_setup)
blr
-#endif /* !defined(CONFIG_6xx) && !defined(CONFIG_POWER4) */
+#endif /* !defined(CONFIG_6xx) */
/*
@@ -1132,11 +1005,6 @@ load_up_mmu:
tophys(r6,r6)
lwz r6,_SDR1@l(r6)
mtspr SPRN_SDR1,r6
-#ifdef CONFIG_PPC64BRIDGE
- /* clear the ASR so we only use the pseudo-segment registers. */
- li r6,0
- mtasr r6
-#endif /* CONFIG_PPC64BRIDGE */
li r0,16 /* load up segment register values */
mtctr r0 /* for context 0 */
lis r3,0x2000 /* Ku = 1, VSID = 0 */
@@ -1145,7 +1013,7 @@ load_up_mmu:
addi r3,r3,0x111 /* increment VSID */
addis r4,r4,0x1000 /* address of next segment */
bdnz 3b
-#ifndef CONFIG_POWER4
+
/* Load the BAT registers with the values set up by MMU_init.
MMU_init takes care of whether we're on a 601 or not. */
mfpvr r3
@@ -1158,7 +1026,7 @@ load_up_mmu:
LOAD_BAT(1,r3,r4,r5)
LOAD_BAT(2,r3,r4,r5)
LOAD_BAT(3,r3,r4,r5)
-#endif /* CONFIG_POWER4 */
+
blr
/*
@@ -1269,9 +1137,6 @@ _GLOBAL(set_context)
li r4,0
isync
3:
-#ifdef CONFIG_PPC64BRIDGE
- slbie r4
-#endif /* CONFIG_PPC64BRIDGE */
mtsrin r3,r4
addi r3,r3,0x111 /* next VSID */
rlwinm r3,r3,0,8,3 /* clear out any overflow from VSID field */
@@ -1358,7 +1223,6 @@ mmu_off:
sync
RFI
-#ifndef CONFIG_POWER4
/*
* Use the first pair of BAT registers to map the 1st 16MB
* of RAM to KERNELBASE. From this point on we can't safely
@@ -1366,7 +1230,6 @@ mmu_off:
*/
initial_bats:
lis r11,KERNELBASE@h
-#ifndef CONFIG_PPC64BRIDGE
mfspr r9,SPRN_PVR
rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
cmpwi 0,r9,1
@@ -1381,7 +1244,6 @@ initial_bats:
mtspr SPRN_IBAT1L,r10
isync
blr
-#endif /* CONFIG_PPC64BRIDGE */
4: tophys(r8,r11)
#ifdef CONFIG_SMP
@@ -1395,11 +1257,6 @@ initial_bats:
ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */
#endif /* CONFIG_APUS */
-#ifdef CONFIG_PPC64BRIDGE
- /* clear out the high 32 bits in the BAT */
- clrldi r11,r11,32
- clrldi r8,r8,32
-#endif /* CONFIG_PPC64BRIDGE */
mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */
mtspr SPRN_IBAT0L,r8
@@ -1432,38 +1289,6 @@ setup_disp_bat:
#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
-#else /* CONFIG_POWER4 */
-/*
- * Load up the SDR1 and segment register values now
- * since we don't have the BATs.
- * Also make sure we are running in 32-bit mode.
- */
-
-initial_mm_power4:
- addis r14,r3,_SDR1@ha /* get the value from _SDR1 */
- lwz r14,_SDR1@l(r14) /* assume hash table below 4GB */
- mtspr SPRN_SDR1,r14
- slbia
- lis r4,0x2000 /* set pseudo-segment reg 12 */
- ori r5,r4,0x0ccc
- mtsr 12,r5
-#if 0
- ori r5,r4,0x0888 /* set pseudo-segment reg 8 */
- mtsr 8,r5 /* (for access to serial port) */
-#endif
-#ifdef CONFIG_BOOTX_TEXT
- ori r5,r4,0x0999 /* set pseudo-segment reg 9 */
- mtsr 9,r5 /* (for access to screen) */
-#endif
- mfmsr r0
- clrldi r0,r0,1
- sync
- mtmsr r0
- isync
- blr
-
-#endif /* CONFIG_POWER4 */
-
#ifdef CONFIG_8260
/* Jump into the system reset for the rom.
* We first disable the MMU, and then jump to the ROM reset address.
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index ec53c7d65f2..7a2f20583be 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -355,9 +355,7 @@ InstructionTLBMiss:
. = 0x1200
DataStoreTLBMiss:
-#ifdef CONFIG_8xx_CPU6
stw r3, 8(r0)
-#endif
DO_8xx_CPU6(0x3f80, r3)
mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
mfcr r10
@@ -417,9 +415,7 @@ DataStoreTLBMiss:
lwz r11, 0(r0)
mtcr r11
lwz r11, 4(r0)
-#ifdef CONFIG_8xx_CPU6
lwz r3, 8(r0)
-#endif
rfi
/* This is an instruction TLB error on the MPC8xx. This could be due
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
deleted file mode 100644
index 1be3ca5bae4..00000000000
--- a/arch/ppc/kernel/idle.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Idle daemon for PowerPC. Idle daemon will handle any action
- * that needs to be taken when the system becomes idle.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu). Subsequently hacked
- * on by Tom Rini, Armin Kuster, Paul Mackerras and others.
- *
- * This program is free software; 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/config.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/sysctl.h>
-#include <linux/cpu.h>
-
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/mmu.h>
-#include <asm/cache.h>
-#include <asm/cputable.h>
-#include <asm/machdep.h>
-#include <asm/smp.h>
-
-void default_idle(void)
-{
- void (*powersave)(void);
-
- powersave = ppc_md.power_save;
-
- if (!need_resched()) {
- if (powersave != NULL)
- powersave();
-#ifdef CONFIG_SMP
- else {
- set_thread_flag(TIF_POLLING_NRFLAG);
- while (!need_resched() &&
- !cpu_is_offline(smp_processor_id()))
- barrier();
- clear_thread_flag(TIF_POLLING_NRFLAG);
- }
-#endif
- }
-}
-
-/*
- * The body of the idle task.
- */
-void cpu_idle(void)
-{
- int cpu = smp_processor_id();
-
- for (;;) {
- while (!need_resched()) {
- if (ppc_md.idle != NULL)
- ppc_md.idle();
- else
- default_idle();
- }
-
- if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
- cpu_die();
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
- }
-}
-
-#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx)
-/*
- * Register the sysctl to set/clear powersave_nap.
- */
-extern int powersave_nap;
-
-static ctl_table powersave_nap_ctl_table[]={
- {
- .ctl_name = KERN_PPC_POWERSAVE_NAP,
- .procname = "powersave-nap",
- .data = &powersave_nap,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- { 0, },
-};
-static ctl_table powersave_nap_sysctl_root[] = {
- { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
- { 0,},
-};
-
-static int __init
-register_powersave_nap_sysctl(void)
-{
- register_sysctl_table(powersave_nap_sysctl_root, 0);
-
- return 0;
-}
-
-__initcall(register_powersave_nap_sysctl);
-#endif
diff --git a/arch/ppc/kernel/idle_6xx.S b/arch/ppc/kernel/idle_6xx.S
deleted file mode 100644
index 1a2194cf682..00000000000
--- a/arch/ppc/kernel/idle_6xx.S
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * This file contains the power_save function for 6xx & 7xxx CPUs
- * rewritten in assembler
- *
- * Warning ! This code assumes that if your machine has a 750fx
- * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
- * if this is not the case some additional changes will have to
- * be done to check a runtime var (a bit like powersave-nap)
- *
- * This program is free software; 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/config.h>
-#include <linux/threads.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/cputable.h>
-#include <asm/thread_info.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-#undef DEBUG
-
- .text
-
-/*
- * Init idle, called at early CPU setup time from head.S for each CPU
- * Make sure no rest of NAP mode remains in HID0, save default
- * values for some CPU specific registers. Called with r24
- * containing CPU number and r3 reloc offset
- */
-_GLOBAL(init_idle_6xx)
-BEGIN_FTR_SECTION
- mfspr r4,SPRN_HID0
- rlwinm r4,r4,0,10,8 /* Clear NAP */
- mtspr SPRN_HID0, r4
- b 1f
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
- blr
-1:
- slwi r5,r24,2
- add r5,r5,r3
-BEGIN_FTR_SECTION
- mfspr r4,SPRN_MSSCR0
- addis r6,r5, nap_save_msscr0@ha
- stw r4,nap_save_msscr0@l(r6)
-END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-BEGIN_FTR_SECTION
- mfspr r4,SPRN_HID1
- addis r6,r5,nap_save_hid1@ha
- stw r4,nap_save_hid1@l(r6)
-END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
- blr
-
-/*
- * Here is the power_save_6xx function. This could eventually be
- * split into several functions & changing the function pointer
- * depending on the various features.
- */
-_GLOBAL(ppc6xx_idle)
- /* Check if we can nap or doze, put HID0 mask in r3
- */
- lis r3, 0
-BEGIN_FTR_SECTION
- lis r3,HID0_DOZE@h
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-BEGIN_FTR_SECTION
- /* We must dynamically check for the NAP feature as it
- * can be cleared by CPU init after the fixups are done
- */
- lis r4,cur_cpu_spec@ha
- lwz r4,cur_cpu_spec@l(r4)
- lwz r4,CPU_SPEC_FEATURES(r4)
- andi. r0,r4,CPU_FTR_CAN_NAP
- beq 1f
- /* Now check if user or arch enabled NAP mode */
- lis r4,powersave_nap@ha
- lwz r4,powersave_nap@l(r4)
- cmpwi 0,r4,0
- beq 1f
- lis r3,HID0_NAP@h
-1:
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
- cmpwi 0,r3,0
- beqlr
-
- /* Clear MSR:EE */
- mfmsr r7
- rlwinm r0,r7,0,17,15
- mtmsr r0
-
- /* Check current_thread_info()->flags */
- rlwinm r4,r1,0,0,18
- lwz r4,TI_FLAGS(r4)
- andi. r0,r4,_TIF_NEED_RESCHED
- beq 1f
- mtmsr r7 /* out of line this ? */
- blr
-1:
- /* Some pre-nap cleanups needed on some CPUs */
- andis. r0,r3,HID0_NAP@h
- beq 2f
-BEGIN_FTR_SECTION
- /* Disable L2 prefetch on some 745x and try to ensure
- * L2 prefetch engines are idle. As explained by errata
- * text, we can't be sure they are, we just hope very hard
- * that well be enough (sic !). At least I noticed Apple
- * doesn't even bother doing the dcbf's here...
- */
- mfspr r4,SPRN_MSSCR0
- rlwinm r4,r4,0,0,29
- sync
- mtspr SPRN_MSSCR0,r4
- sync
- isync
- lis r4,KERNELBASE@h
- dcbf 0,r4
- dcbf 0,r4
- dcbf 0,r4
- dcbf 0,r4
-END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-#ifdef DEBUG
- lis r6,nap_enter_count@ha
- lwz r4,nap_enter_count@l(r6)
- addi r4,r4,1
- stw r4,nap_enter_count@l(r6)
-#endif
-2:
-BEGIN_FTR_SECTION
- /* Go to low speed mode on some 750FX */
- lis r4,powersave_lowspeed@ha
- lwz r4,powersave_lowspeed@l(r4)
- cmpwi 0,r4,0
- beq 1f
- mfspr r4,SPRN_HID1
- oris r4,r4,0x0001
- mtspr SPRN_HID1,r4
-1:
-END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
-
- /* Go to NAP or DOZE now */
- mfspr r4,SPRN_HID0
- lis r5,(HID0_NAP|HID0_SLEEP)@h
-BEGIN_FTR_SECTION
- oris r5,r5,HID0_DOZE@h
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
- andc r4,r4,r5
- or r4,r4,r3
-BEGIN_FTR_SECTION
- oris r4,r4,HID0_DPM@h /* that should be done once for all */
-END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
- mtspr SPRN_HID0,r4
-BEGIN_FTR_SECTION
- DSSALL
- sync
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
- ori r7,r7,MSR_EE /* Could be ommited (already set) */
- oris r7,r7,MSR_POW@h
- sync
- isync
- mtmsr r7
- isync
- sync
- blr
-
-/*
- * Return from NAP/DOZE mode, restore some CPU specific registers,
- * we are called with DR/IR still off and r2 containing physical
- * address of current.
- */
-_GLOBAL(power_save_6xx_restore)
- mfspr r11,SPRN_HID0
- rlwinm. r11,r11,0,10,8 /* Clear NAP & copy NAP bit !state to cr1 EQ */
- cror 4*cr1+eq,4*cr0+eq,4*cr0+eq
-BEGIN_FTR_SECTION
- rlwinm r11,r11,0,9,7 /* Clear DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
- mtspr SPRN_HID0, r11
-
-#ifdef DEBUG
- beq cr1,1f
- lis r11,(nap_return_count-KERNELBASE)@ha
- lwz r9,nap_return_count@l(r11)
- addi r9,r9,1
- stw r9,nap_return_count@l(r11)
-1:
-#endif
-
- rlwinm r9,r1,0,0,18
- tophys(r9,r9)
- lwz r11,TI_CPU(r9)
- slwi r11,r11,2
- /* Todo make sure all these are in the same page
- * and load r22 (@ha part + CPU offset) only once
- */
-BEGIN_FTR_SECTION
- beq cr1,1f
- addis r9,r11,(nap_save_msscr0-KERNELBASE)@ha
- lwz r9,nap_save_msscr0@l(r9)
- mtspr SPRN_MSSCR0, r9
- sync
- isync
-1:
-END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-BEGIN_FTR_SECTION
- addis r9,r11,(nap_save_hid1-KERNELBASE)@ha
- lwz r9,nap_save_hid1@l(r9)
- mtspr SPRN_HID1, r9
-END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
- b transfer_to_handler_cont
-
- .data
-
-_GLOBAL(nap_save_msscr0)
- .space 4*NR_CPUS
-
-_GLOBAL(nap_save_hid1)
- .space 4*NR_CPUS
-
-_GLOBAL(powersave_nap)
- .long 0
-_GLOBAL(powersave_lowspeed)
- .long 0
-
-#ifdef DEBUG
-_GLOBAL(nap_enter_count)
- .space 4
-_GLOBAL(nap_return_count)
- .space 4
-#endif
diff --git a/arch/ppc/kernel/idle_power4.S b/arch/ppc/kernel/idle_power4.S
deleted file mode 100644
index cc0d535365c..00000000000
--- a/arch/ppc/kernel/idle_power4.S
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * This file contains the power_save function for 6xx & 7xxx CPUs
- * rewritten in assembler
- *
- * Warning ! This code assumes that if your machine has a 750fx
- * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
- * if this is not the case some additional changes will have to
- * be done to check a runtime var (a bit like powersave-nap)
- *
- * This program is free software; 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/config.h>
-#include <linux/threads.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/cputable.h>
-#include <asm/thread_info.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-#undef DEBUG
-
- .text
-
-/*
- * Init idle, called at early CPU setup time from head.S for each CPU
- * So nothing for now. Called with r24 containing CPU number and r3
- * reloc offset
- */
- .globl init_idle_power4
-init_idle_power4:
- blr
-
-/*
- * Here is the power_save_6xx function. This could eventually be
- * split into several functions & changing the function pointer
- * depending on the various features.
- */
- .globl power4_idle
-power4_idle:
-BEGIN_FTR_SECTION
- blr
-END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
- /* We must dynamically check for the NAP feature as it
- * can be cleared by CPU init after the fixups are done
- */
- lis r4,cur_cpu_spec@ha
- lwz r4,cur_cpu_spec@l(r4)
- lwz r4,CPU_SPEC_FEATURES(r4)
- andi. r0,r4,CPU_FTR_CAN_NAP
- beqlr
- /* Now check if user or arch enabled NAP mode */
- lis r4,powersave_nap@ha
- lwz r4,powersave_nap@l(r4)
- cmpwi 0,r4,0
- beqlr
-
- /* Clear MSR:EE */
- mfmsr r7
- rlwinm r0,r7,0,17,15
- mtmsr r0
-
- /* Check current_thread_info()->flags */
- rlwinm r4,r1,0,0,18
- lwz r4,TI_FLAGS(r4)
- andi. r0,r4,_TIF_NEED_RESCHED
- beq 1f
- mtmsr r7 /* out of line this ? */
- blr
-1:
- /* Go to NAP now */
-BEGIN_FTR_SECTION
- DSSALL
- sync
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
- ori r7,r7,MSR_EE /* Could be ommited (already set) */
- oris r7,r7,MSR_POW@h
- sync
- isync
- mtmsr r7
- isync
- sync
- blr
-
- .globl powersave_nap
-powersave_nap:
- .long 0
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 04d04c5bfdd..809673a36f7 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -46,9 +46,6 @@ static void pcibios_fixup_resources(struct pci_dev* dev);
static void fixup_broken_pcnet32(struct pci_dev* dev);
static int reparent_resources(struct resource *parent, struct resource *res);
static void fixup_cpc710_pci64(struct pci_dev* dev);
-#ifdef CONFIG_PPC_OF
-static u8* pci_to_OF_bus_map;
-#endif
/* By default, we don't re-assign bus numbers.
*/
@@ -625,406 +622,13 @@ pcibios_alloc_controller(void)
return hose;
}
-#ifdef CONFIG_PPC_OF
-/*
- * Functions below are used on OpenFirmware machines.
- */
-static void
-make_one_node_map(struct device_node* node, u8 pci_bus)
-{
- int *bus_range;
- int len;
-
- if (pci_bus >= pci_bus_count)
- return;
- bus_range = (int *) get_property(node, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s, "
- "assuming it starts at 0\n", node->full_name);
- pci_to_OF_bus_map[pci_bus] = 0;
- } else
- pci_to_OF_bus_map[pci_bus] = bus_range[0];
-
- for (node=node->child; node != 0;node = node->sibling) {
- struct pci_dev* dev;
- unsigned int *class_code, *reg;
-
- class_code = (unsigned int *) get_property(node, "class-code", NULL);
- if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
- continue;
- reg = (unsigned int *)get_property(node, "reg", NULL);
- if (!reg)
- continue;
- dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));
- if (!dev || !dev->subordinate)
- continue;
- make_one_node_map(node, dev->subordinate->number);
- }
-}
-
-void
-pcibios_make_OF_bus_map(void)
-{
- int i;
- struct pci_controller* hose;
- u8* of_prop_map;
-
- pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);
- if (!pci_to_OF_bus_map) {
- printk(KERN_ERR "Can't allocate OF bus map !\n");
- return;
- }
-
- /* We fill the bus map with invalid values, that helps
- * debugging.
- */
- for (i=0; i<pci_bus_count; i++)
- pci_to_OF_bus_map[i] = 0xff;
-
- /* For each hose, we begin searching bridges */
- for(hose=hose_head; hose; hose=hose->next) {
- struct device_node* node;
- node = (struct device_node *)hose->arch_data;
- if (!node)
- continue;
- make_one_node_map(node, hose->first_busno);
- }
- of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL);
- if (of_prop_map)
- memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count);
-#ifdef DEBUG
- printk("PCI->OF bus map:\n");
- for (i=0; i<pci_bus_count; i++) {
- if (pci_to_OF_bus_map[i] == 0xff)
- continue;
- printk("%d -> %d\n", i, pci_to_OF_bus_map[i]);
- }
-#endif
-}
-
-typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data);
-
-static struct device_node*
-scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data)
-{
- struct device_node* sub_node;
-
- for (; node != 0;node = node->sibling) {
- unsigned int *class_code;
-
- if (filter(node, data))
- return node;
-
- /* For PCI<->PCI bridges or CardBus bridges, we go down
- * Note: some OFs create a parent node "multifunc-device" as
- * a fake root for all functions of a multi-function device,
- * we go down them as well.
- */
- class_code = (unsigned int *) get_property(node, "class-code", NULL);
- if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
- strcmp(node->name, "multifunc-device"))
- continue;
- sub_node = scan_OF_pci_childs(node->child, filter, data);
- if (sub_node)
- return sub_node;
- }
- return NULL;
-}
-
-static int
-scan_OF_pci_childs_iterator(struct device_node* node, void* data)
-{
- unsigned int *reg;
- u8* fdata = (u8*)data;
-
- reg = (unsigned int *) get_property(node, "reg", NULL);
- if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]
- && ((reg[0] >> 16) & 0xff) == fdata[0])
- return 1;
- return 0;
-}
-
-static struct device_node*
-scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
-{
- u8 filter_data[2] = {bus, dev_fn};
-
- return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data);
-}
-
-/*
- * Scans the OF tree for a device node matching a PCI device
- */
-struct device_node *
-pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
-{
- struct pci_controller *hose;
- struct device_node *node;
- int busnr;
-
- if (!have_of)
- return NULL;
-
- /* Lookup the hose */
- busnr = bus->number;
- hose = pci_bus_to_hose(busnr);
- if (!hose)
- return NULL;
-
- /* Check it has an OF node associated */
- node = (struct device_node *) hose->arch_data;
- if (!node)
- return NULL;
-
- /* Fixup bus number according to what OF think it is. */
- if (pci_to_OF_bus_map)
- busnr = pci_to_OF_bus_map[busnr];
- if (busnr == 0xff)
- return NULL;
-
- /* Now, lookup childs of the hose */
- return scan_OF_childs_for_device(node->child, busnr, devfn);
-}
-EXPORT_SYMBOL(pci_busdev_to_OF_node);
-
-struct device_node*
-pci_device_to_OF_node(struct pci_dev *dev)
-{
- return pci_busdev_to_OF_node(dev->bus, dev->devfn);
-}
-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)
-{
- return ((void *)node == data);
-}
-
-/*
- * Returns the PCI device matching a given OF node
- */
-int
-pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
-{
- unsigned int *reg;
- struct pci_controller* hose;
- struct pci_dev* dev = NULL;
-
- if (!have_of)
- return -ENODEV;
- /* Make sure it's really a PCI device */
- hose = pci_find_hose_for_OF_device(node);
- if (!hose || !hose->arch_data)
- return -ENODEV;
- if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,
- find_OF_pci_device_filter, (void *)node))
- return -ENODEV;
- reg = (unsigned int *) get_property(node, "reg", NULL);
- if (!reg)
- return -ENODEV;
- *bus = (reg[0] >> 16) & 0xff;
- *devfn = ((reg[0] >> 8) & 0xff);
-
- /* Ok, here we need some tweak. If we have already renumbered
- * all busses, we can't rely on the OF bus number any more.
- * the pci_to_OF_bus_map is not enough as several PCI busses
- * may match the same OF bus number.
- */
- if (!pci_to_OF_bus_map)
- return 0;
-
- for_each_pci_dev(dev)
- if (pci_to_OF_bus_map[dev->bus->number] == *bus &&
- dev->devfn == *devfn) {
- *bus = dev->bus->number;
- pci_dev_put(dev);
- return 0;
- }
-
- return -ENODEV;
-}
-EXPORT_SYMBOL(pci_device_from_OF_node);
-
-void __init
-pci_process_bridge_OF_ranges(struct pci_controller *hose,
- struct device_node *dev, int primary)
-{
- static unsigned int static_lc_ranges[256] __initdata;
- unsigned int *dt_ranges, *lc_ranges, *ranges, *prev;
- unsigned int size;
- int rlen = 0, orig_rlen;
- int memno = 0;
- struct resource *res;
- int np, na = prom_n_addr_cells(dev);
- np = na + 5;
-
- /* First we try to merge ranges to fix a problem with some pmacs
- * that can have more than 3 ranges, fortunately using contiguous
- * addresses -- BenH
- */
- dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
- if (!dt_ranges)
- return;
- /* Sanity check, though hopefully that never happens */
- if (rlen > sizeof(static_lc_ranges)) {
- printk(KERN_WARNING "OF ranges property too large !\n");
- rlen = sizeof(static_lc_ranges);
- }
- lc_ranges = static_lc_ranges;
- memcpy(lc_ranges, dt_ranges, rlen);
- orig_rlen = rlen;
-
- /* Let's work on a copy of the "ranges" property instead of damaging
- * the device-tree image in memory
- */
- ranges = lc_ranges;
- prev = NULL;
- while ((rlen -= np * sizeof(unsigned int)) >= 0) {
- if (prev) {
- if (prev[0] == ranges[0] && prev[1] == ranges[1] &&
- (prev[2] + prev[na+4]) == ranges[2] &&
- (prev[na+2] + prev[na+4]) == ranges[na+2]) {
- prev[na+4] += ranges[na+4];
- ranges[0] = 0;
- ranges += np;
- continue;
- }
- }
- prev = ranges;
- ranges += np;
- }
-
- /*
- * The ranges property is laid out as an array of elements,
- * each of which comprises:
- * cells 0 - 2: a PCI address
- * cells 3 or 3+4: a CPU physical address
- * (size depending on dev->n_addr_cells)
- * cells 4+5 or 5+6: the size of the range
- */
- ranges = lc_ranges;
- rlen = orig_rlen;
- while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {
- res = NULL;
- size = ranges[na+4];
- switch ((ranges[0] >> 24) & 0x3) {
- case 1: /* I/O space */
- if (ranges[2] != 0)
- break;
- hose->io_base_phys = ranges[na+2];
- /* limit I/O space to 16MB */
- if (size > 0x01000000)
- size = 0x01000000;
- hose->io_base_virt = ioremap(ranges[na+2], size);
- if (primary)
- isa_io_base = (unsigned long) hose->io_base_virt;
- res = &hose->io_resource;
- res->flags = IORESOURCE_IO;
- res->start = ranges[2];
- DBG("PCI: IO 0x%lx -> 0x%lx\n",
- res->start, res->start + size - 1);
- break;
- case 2: /* memory space */
- memno = 0;
- if (ranges[1] == 0 && ranges[2] == 0
- && ranges[na+4] <= (16 << 20)) {
- /* 1st 16MB, i.e. ISA memory area */
- if (primary)
- isa_mem_base = ranges[na+2];
- memno = 1;
- }
- while (memno < 3 && hose->mem_resources[memno].flags)
- ++memno;
- if (memno == 0)
- hose->pci_mem_offset = ranges[na+2] - ranges[2];
- if (memno < 3) {
- res = &hose->mem_resources[memno];
- res->flags = IORESOURCE_MEM;
- if(ranges[0] & 0x40000000)
- res->flags |= IORESOURCE_PREFETCH;
- res->start = ranges[na+2];
- DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno,
- res->start, res->start + size - 1);
- }
- break;
- }
- if (res != NULL) {
- res->name = dev->full_name;
- res->end = res->start + size - 1;
- res->parent = NULL;
- res->sibling = NULL;
- res->child = NULL;
- }
- ranges += np;
- }
-}
-
-/* We create the "pci-OF-bus-map" property now so it appears in the
- * /proc device tree
- */
-void __init
-pci_create_OF_bus_map(void)
-{
- struct property* of_prop;
-
- of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256);
- if (of_prop && find_path_device("/")) {
- memset(of_prop, -1, sizeof(struct property) + 256);
- of_prop->name = "pci-OF-bus-map";
- of_prop->length = 256;
- of_prop->value = (unsigned char *)&of_prop[1];
- prom_add_property(find_path_device("/"), of_prop);
- }
-}
-
-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 */
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 */
}
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
index 2f5c7650274..75c64504374 100644
--- a/arch/ppc/kernel/ppc_htab.c
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -52,7 +52,7 @@ static int ppc_htab_open(struct inode *inode, struct file *file)
return single_open(file, ppc_htab_show, NULL);
}
-struct file_operations ppc_htab_operations = {
+const struct file_operations ppc_htab_operations = {
.open = ppc_htab_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -104,7 +104,7 @@ static char *pmc2_lookup(unsigned long mmcr0)
static int ppc_htab_show(struct seq_file *m, void *v)
{
unsigned long mmcr0 = 0, pmc1 = 0, pmc2 = 0;
-#if defined(CONFIG_PPC_STD_MMU) && !defined(CONFIG_PPC64BRIDGE)
+#if defined(CONFIG_PPC_STD_MMU)
unsigned int kptes = 0, uptes = 0;
PTE *ptr;
#endif /* CONFIG_PPC_STD_MMU */
@@ -133,7 +133,6 @@ static int ppc_htab_show(struct seq_file *m, void *v)
return 0;
}
-#ifndef CONFIG_PPC64BRIDGE
for (ptr = Hash; ptr < Hash_end; ptr++) {
unsigned int mctx, vsid;
@@ -147,7 +146,6 @@ static int ppc_htab_show(struct seq_file *m, void *v)
else
uptes++;
}
-#endif
seq_printf(m,
"PTE Hash Table Information\n"
@@ -155,20 +153,16 @@ static int ppc_htab_show(struct seq_file *m, void *v)
"Buckets\t\t: %lu\n"
"Address\t\t: %08lx\n"
"Entries\t\t: %lu\n"
-#ifndef CONFIG_PPC64BRIDGE
"User ptes\t: %u\n"
"Kernel ptes\t: %u\n"
"Percent full\t: %lu%%\n"
-#endif
, (unsigned long)(Hash_size>>10),
(Hash_size/(sizeof(PTE)*8)),
(unsigned long)Hash,
Hash_size/sizeof(PTE)
-#ifndef CONFIG_PPC64BRIDGE
, uptes,
kptes,
((kptes+uptes)*100) / (Hash_size/sizeof(PTE))
-#endif
);
seq_printf(m,
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 82adb460134..b250b1b539b 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -18,7 +18,6 @@
#include <linux/bitops.h>
#include <asm/page.h>
-#include <asm/semaphore.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -30,7 +29,6 @@
#include <linux/adb.h>
#include <linux/cuda.h>
#include <linux/pmu.h>
-#include <asm/prom.h>
#include <asm/system.h>
#include <asm/pci-bridge.h>
#include <asm/irq.h>
@@ -96,6 +94,7 @@ EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strcasecmp);
+EXPORT_SYMBOL(strncasecmp);
EXPORT_SYMBOL(__div64_32);
EXPORT_SYMBOL(csum_partial);
@@ -208,27 +207,6 @@ EXPORT_SYMBOL(adb_try_handler_change);
EXPORT_SYMBOL(cuda_request);
EXPORT_SYMBOL(cuda_poll);
#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_PPC_OF
-EXPORT_SYMBOL(find_devices);
-EXPORT_SYMBOL(find_type_devices);
-EXPORT_SYMBOL(find_compatible_devices);
-EXPORT_SYMBOL(find_path_device);
-EXPORT_SYMBOL(device_is_compatible);
-EXPORT_SYMBOL(machine_is_compatible);
-EXPORT_SYMBOL(find_all_nodes);
-EXPORT_SYMBOL(get_property);
-EXPORT_SYMBOL(request_OF_resource);
-EXPORT_SYMBOL(release_OF_resource);
-EXPORT_SYMBOL(of_find_node_by_name);
-EXPORT_SYMBOL(of_find_node_by_type);
-EXPORT_SYMBOL(of_find_compatible_node);
-EXPORT_SYMBOL(of_find_node_by_path);
-EXPORT_SYMBOL(of_find_all_nodes);
-EXPORT_SYMBOL(of_get_parent);
-EXPORT_SYMBOL(of_get_next_child);
-EXPORT_SYMBOL(of_node_get);
-EXPORT_SYMBOL(of_node_put);
-#endif /* CONFIG_PPC_OF */
#if defined(CONFIG_BOOTX_TEXT)
EXPORT_SYMBOL(btext_update_display);
#endif
@@ -262,9 +240,6 @@ EXPORT_SYMBOL(console_drivers);
EXPORT_SYMBOL(xmon);
EXPORT_SYMBOL(xmon_printf);
#endif
-EXPORT_SYMBOL(__up);
-EXPORT_SYMBOL(__down);
-EXPORT_SYMBOL(__down_interruptible);
#if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
extern void (*debugger)(struct pt_regs *regs);
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 53e9deacee8..1f79e84ab46 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -1,5 +1,5 @@
/*
- * Common prep/chrp boot and setup code.
+ * Common prep boot and setup code.
*/
#include <linux/config.h>
@@ -72,17 +72,12 @@ unsigned long ISA_DMA_THRESHOLD;
unsigned int DMA_MODE_READ;
unsigned int DMA_MODE_WRITE;
-#ifdef CONFIG_PPC_MULTIPLATFORM
-int _machine = 0;
-EXPORT_SYMBOL(_machine);
-
+#ifdef CONFIG_PPC_PREP
extern void prep_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7);
-extern void chrp_init(unsigned long r3, unsigned long r4,
- unsigned long r5, unsigned long r6, unsigned long r7);
dev_t boot_dev;
-#endif /* CONFIG_PPC_MULTIPLATFORM */
+#endif /* CONFIG_PPC_PREP */
int have_of;
EXPORT_SYMBOL(have_of);
@@ -319,72 +314,12 @@ early_init(int r3, int r4, int r5)
identify_cpu(offset, 0);
do_cpu_ftr_fixups(offset);
-#if defined(CONFIG_PPC_OF)
- reloc_got2(offset);
-
- /*
- * don't do anything on prep
- * for now, don't use bootinfo because it breaks yaboot 0.5
- * and assume that if we didn't find a magic number, we have OF
- */
- if (*(unsigned long *)(0) != 0xdeadc0de)
- phys = prom_init(r3, r4, (prom_entry)r5);
-
- reloc_got2(-offset);
-#endif
-
return phys;
}
-#ifdef CONFIG_PPC_OF
-/*
- * Assume here that all clock rates are the same in a
- * smp system. -- Cort
- */
-int
-of_show_percpuinfo(struct seq_file *m, int i)
-{
- struct device_node *cpu_node;
- u32 *fp;
- int s;
-
- cpu_node = find_type_devices("cpu");
- if (!cpu_node)
- return 0;
- for (s = 0; s < i && cpu_node->next; s++)
- cpu_node = cpu_node->next;
- fp = (u32 *)get_property(cpu_node, "clock-frequency", NULL);
- if (fp)
- seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);
- return 0;
-}
-
-void __init
-intuit_machine_type(void)
-{
- char *model;
- struct device_node *root;
-
- /* ask the OF info if we're a chrp or pmac */
- root = find_path_device("/");
- if (root != 0) {
- /* assume pmac unless proven to be chrp -- Cort */
- _machine = _MACH_Pmac;
- model = get_property(root, "device_type", NULL);
- if (model && !strncmp("chrp", model, 4))
- _machine = _MACH_chrp;
- else {
- model = get_property(root, "model", NULL);
- if (model && !strncmp(model, "IBM", 3))
- _machine = _MACH_chrp;
- }
- }
-}
-#endif
-
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PREP
/*
- * The PPC_MULTIPLATFORM version of platform_init...
+ * The PPC_PREP version of platform_init...
*/
void __init
platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
@@ -399,161 +334,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
parse_bootinfo(find_bootinfo());
- /* if we didn't get any bootinfo telling us what we are... */
- if (_machine == 0) {
- /* prep boot loader tells us if we're prep or not */
- if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
- _machine = _MACH_prep;
- }
-
-#ifdef CONFIG_PPC_PREP
- /* not much more to do here, if prep */
- if (_machine == _MACH_prep) {
- prep_init(r3, r4, r5, r6, r7);
- return;
- }
-#endif
-
-#ifdef CONFIG_PPC_OF
- have_of = 1;
-
- /* prom_init has already been called from __start */
- if (boot_infos)
- relocate_nodes();
-
- /* If we aren't PReP, we can find out if we're Pmac
- * or CHRP with this. */
- if (_machine == 0)
- intuit_machine_type();
-
- /* finish_device_tree may need _machine defined. */
- finish_device_tree();
-
- /*
- * If we were booted via quik, r3 points to the physical
- * address of the command-line parameters.
- * If we were booted from an xcoff image (i.e. netbooted or
- * booted from floppy), we get the command line from the
- * bootargs property of the /chosen node.
- * If an initial ramdisk is present, r3 and r4
- * are used for initrd_start and initrd_size,
- * otherwise they contain 0xdeadbeef.
- */
- if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
- strlcpy(cmd_line, (char *)r3 + KERNELBASE,
- sizeof(cmd_line));
- } else if (boot_infos != 0) {
- /* booted by BootX - check for ramdisk */
- if (boot_infos->kernelParamsOffset != 0)
- strlcpy(cmd_line, (char *) boot_infos
- + boot_infos->kernelParamsOffset,
- sizeof(cmd_line));
-#ifdef CONFIG_BLK_DEV_INITRD
- if (boot_infos->ramDisk) {
- initrd_start = (unsigned long) boot_infos
- + boot_infos->ramDisk;
- initrd_end = initrd_start + boot_infos->ramDiskSize;
- initrd_below_start_ok = 1;
- }
-#endif
- } else {
- struct device_node *chosen;
- char *p;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (r3 && r4 && r4 != 0xdeadbeef) {
- if (r3 < KERNELBASE)
- r3 += KERNELBASE;
- initrd_start = r3;
- initrd_end = r3 + r4;
- ROOT_DEV = Root_RAM0;
- initrd_below_start_ok = 1;
- }
-#endif
- chosen = find_devices("chosen");
- if (chosen != NULL) {
- p = get_property(chosen, "bootargs", NULL);
- if (p && *p) {
- strlcpy(cmd_line, p, sizeof(cmd_line));
- }
- }
- }
-#ifdef CONFIG_ADB
- if (strstr(cmd_line, "adb_sync")) {
- extern int __adb_probe_sync;
- __adb_probe_sync = 1;
- }
-#endif /* CONFIG_ADB */
-
- switch (_machine) {
-#ifdef CONFIG_PPC_CHRP
- case _MACH_chrp:
- chrp_init(r3, r4, r5, r6, r7);
- break;
-#endif
- }
-#endif /* CONFIG_PPC_OF */
+ prep_init(r3, r4, r5, r6, r7);
}
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
-#ifdef CONFIG_PPC_OF
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
-extern char *of_stdout_device;
-
-static int __init set_preferred_console(void)
-{
- struct device_node *prom_stdout;
- char *name;
- int offset = 0;
-
- if (of_stdout_device == NULL)
- return -ENODEV;
-
- /* The user has requested a console so this is already set up. */
- if (strstr(saved_command_line, "console="))
- return -EBUSY;
-
- prom_stdout = find_path_device(of_stdout_device);
- if (!prom_stdout)
- return -ENODEV;
-
- name = (char *)get_property(prom_stdout, "name", NULL);
- if (!name)
- return -ENODEV;
-
- if (strcmp(name, "serial") == 0) {
- int i;
- u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
- if (i > 8) {
- switch (reg[1]) {
- case 0x3f8:
- offset = 0;
- break;
- case 0x2f8:
- offset = 1;
- break;
- case 0x898:
- offset = 2;
- break;
- case 0x890:
- offset = 3;
- break;
- default:
- /* We dont recognise the serial port */
- return -ENODEV;
- }
- }
- } else if (strcmp(name, "ch-a") == 0)
- offset = 0;
- else if (strcmp(name, "ch-b") == 0)
- offset = 1;
- else
- return -ENODEV;
- return add_preferred_console("ttyS", offset, NULL);
-}
-console_initcall(set_preferred_console);
-#endif /* CONFIG_SERIAL_CORE_CONSOLE */
-#endif /* CONFIG_PPC_OF */
+#endif /* CONFIG_PPC_PREP */
struct bi_record *find_bootinfo(void)
{
@@ -589,23 +372,6 @@ void parse_bootinfo(struct bi_record *rec)
initrd_end = data[0] + data[1] + KERNELBASE;
break;
#endif /* CONFIG_BLK_DEV_INITRD */
-#ifdef CONFIG_PPC_MULTIPLATFORM
- case BI_MACHTYPE:
- /* Machine types changed with the merge. Since the
- * bootinfo are now deprecated, we can just hard code
- * the appropriate conversion here for when we are
- * called with yaboot which passes us a machine type
- * this way.
- */
- switch(data[0]) {
- case 1: _machine = _MACH_prep; break;
- case 2: _machine = _MACH_Pmac; break;
- case 4: _machine = _MACH_chrp; break;
- default:
- _machine = data[0];
- }
- break;
-#endif
case BI_MEMSIZE:
boot_mem_size = data[0];
break;
@@ -631,9 +397,6 @@ machine_init(unsigned long r3, unsigned long r4, unsigned long r5,
#ifdef CONFIG_6xx
ppc_md.power_save = ppc6xx_idle;
#endif
-#ifdef CONFIG_POWER4
- ppc_md.power_save = power4_idle;
-#endif
platform_init(r3, r4, r5, r6, r7);
@@ -711,7 +474,7 @@ int __init ppc_init(void)
if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
/* register CPU devices */
- for_each_cpu(i)
+ for_each_possible_cpu(i)
register_cpu(&cpu_devices[i], i, NULL);
/* call platform init */
@@ -799,7 +562,4 @@ void __init setup_arch(char **cmdline_p)
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
paging_init();
-
- /* this is for modules since _machine can be a define -- Cort */
- ppc_md.ppc_machine = _machine;
}
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index e55cdda6149..f77795a64da 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -311,7 +311,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
/* Backup CPU 0 state */
__save_cpu_setup();
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (cpu == smp_processor_id())
continue;
/* create a process for the processor */
diff --git a/arch/ppc/lib/strcase.c b/arch/ppc/lib/strcase.c
index 36b521091bb..3b0094cc2b5 100644
--- a/arch/ppc/lib/strcase.c
+++ b/arch/ppc/lib/strcase.c
@@ -1,4 +1,5 @@
#include <linux/ctype.h>
+#include <linux/types.h>
int strcasecmp(const char *s1, const char *s2)
{
@@ -11,7 +12,7 @@ int strcasecmp(const char *s1, const char *s2)
return c1 - c2;
}
-int strncasecmp(const char *s1, const char *s2, int n)
+int strncasecmp(const char *s1, const char *s2, size_t n)
{
int c1, c2;
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 0217188ef46..8e08ca32531 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -202,6 +202,7 @@ good_area:
/* an exec - 4xx/Book-E allows for per-page execute permission */
} else if (TRAP(regs) == 0x400) {
pte_t *ptep;
+ pmd_t *pmdp;
#if 0
/* It would be nice to actually enforce the VM execute
@@ -215,21 +216,24 @@ good_area:
/* Since 4xx/Book-E supports per-page execute permission,
* we lazily flush dcache to icache. */
ptep = NULL;
- if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) {
- struct page *page = pte_page(*ptep);
-
- if (! test_bit(PG_arch_1, &page->flags)) {
- flush_dcache_icache_page(page);
- set_bit(PG_arch_1, &page->flags);
+ if (get_pteptr(mm, address, &ptep, &pmdp)) {
+ spinlock_t *ptl = pte_lockptr(mm, pmdp);
+ spin_lock(ptl);
+ if (pte_present(*ptep)) {
+ struct page *page = pte_page(*ptep);
+
+ if (!test_bit(PG_arch_1, &page->flags)) {
+ flush_dcache_icache_page(page);
+ set_bit(PG_arch_1, &page->flags);
+ }
+ pte_update(ptep, 0, _PAGE_HWEXEC);
+ _tlbie(address);
+ pte_unmap_unlock(ptep, ptl);
+ up_read(&mm->mmap_sem);
+ return 0;
}
- pte_update(ptep, 0, _PAGE_HWEXEC);
- _tlbie(address);
- pte_unmap(ptep);
- up_read(&mm->mmap_sem);
- return 0;
+ pte_unmap_unlock(ptep, ptl);
}
- if (ptep != NULL)
- pte_unmap(ptep);
#endif
/* a read */
} else {
diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S
index f09fa88db35..31d0a924317 100644
--- a/arch/ppc/mm/hashtable.S
+++ b/arch/ppc/mm/hashtable.S
@@ -74,12 +74,6 @@ _GLOBAL(hash_page_sync)
*/
.text
_GLOBAL(hash_page)
-#ifdef CONFIG_PPC64BRIDGE
- mfmsr r0
- clrldi r0,r0,1 /* make sure it's in 32-bit mode */
- MTMSRD(r0)
- isync
-#endif
tophys(r7,0) /* gets -KERNELBASE into r7 */
#ifdef CONFIG_SMP
addis r8,r7,mmu_hash_lock@h
@@ -303,7 +297,6 @@ Hash_base = 0xc0180000
Hash_bits = 12 /* e.g. 256kB hash table */
Hash_msk = (((1 << Hash_bits) - 1) * 64)
-#ifndef CONFIG_PPC64BRIDGE
/* defines for the PTE format for 32-bit PPCs */
#define PTE_SIZE 8
#define PTEG_SIZE 64
@@ -317,21 +310,6 @@ Hash_msk = (((1 << Hash_bits) - 1) * 64)
#define SET_V(r) oris r,r,PTE_V@h
#define CLR_V(r,t) rlwinm r,r,0,1,31
-#else
-/* defines for the PTE format for 64-bit PPCs */
-#define PTE_SIZE 16
-#define PTEG_SIZE 128
-#define LG_PTEG_SIZE 7
-#define LDPTEu ldu
-#define STPTE std
-#define CMPPTE cmpd
-#define PTE_H 2
-#define PTE_V 1
-#define TST_V(r) andi. r,r,PTE_V
-#define SET_V(r) ori r,r,PTE_V
-#define CLR_V(r,t) li t,PTE_V; andc r,r,t
-#endif /* CONFIG_PPC64BRIDGE */
-
#define HASH_LEFT 31-(LG_PTEG_SIZE+Hash_bits-1)
#define HASH_RIGHT 31-LG_PTEG_SIZE
@@ -349,14 +327,8 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT)
/* Construct the high word of the PPC-style PTE (r5) */
-#ifndef CONFIG_PPC64BRIDGE
rlwinm r5,r3,7,1,24 /* put VSID in 0x7fffff80 bits */
rlwimi r5,r4,10,26,31 /* put in API (abbrev page index) */
-#else /* CONFIG_PPC64BRIDGE */
- clrlwi r3,r3,8 /* reduce vsid to 24 bits */
- sldi r5,r3,12 /* shift vsid into position */
- rlwimi r5,r4,16,20,24 /* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64BRIDGE */
SET_V(r5) /* set V (valid) bit */
/* Get the address of the primary PTE group in the hash table (r3) */
@@ -540,14 +512,8 @@ _GLOBAL(flush_hash_pages)
add r3,r3,r0 /* note code below trims to 24 bits */
/* Construct the high word of the PPC-style PTE (r11) */
-#ifndef CONFIG_PPC64BRIDGE
rlwinm r11,r3,7,1,24 /* put VSID in 0x7fffff80 bits */
rlwimi r11,r4,10,26,31 /* put in API (abbrev page index) */
-#else /* CONFIG_PPC64BRIDGE */
- clrlwi r3,r3,8 /* reduce vsid to 24 bits */
- sldi r11,r3,12 /* shift vsid into position */
- rlwimi r11,r4,16,20,24 /* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64BRIDGE */
SET_V(r11) /* set V (valid) bit */
#ifdef CONFIG_SMP
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index cb1c294fb93..386e000bcb7 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -412,14 +412,6 @@ void __init mem_init(void)
}
#endif /* CONFIG_BLK_DEV_INITRD */
-#ifdef CONFIG_PPC_OF
- /* mark the RTAS pages as reserved */
- if ( rtas_data )
- for (addr = (ulong)__va(rtas_data);
- addr < PAGE_ALIGN((ulong)__va(rtas_data)+rtas_size) ;
- addr += PAGE_SIZE)
- SetPageReserved(virt_to_page(addr));
-#endif
for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory;
addr += PAGE_SIZE) {
if (!PageReserved(virt_to_page(addr)))
@@ -494,11 +486,6 @@ set_phys_avail(unsigned long total_memory)
initrd_end - initrd_start, 1);
}
#endif /* CONFIG_BLK_DEV_INITRD */
-#ifdef CONFIG_PPC_OF
- /* remove the RTAS pages from the available memory */
- if (rtas_data)
- mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1);
-#endif
}
/* Mark some memory as reserved by removing it from phys_avail. */
diff --git a/arch/ppc/mm/mmu_context.c b/arch/ppc/mm/mmu_context.c
index a8816e0f6a8..b4a4b3f02a1 100644
--- a/arch/ppc/mm/mmu_context.c
+++ b/arch/ppc/mm/mmu_context.c
@@ -2,7 +2,7 @@
* This file contains the routines for handling the MMU on those
* PowerPC implementations where the MMU substantially follows the
* architecture specification. This includes the 6xx, 7xx, 7xxx,
- * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
+ * 8260, and 83xx implementations but excludes the 8xx and 4xx.
* -- paulus
*
* Derived from arch/ppc/mm/init.c:
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index 6ea9185fd12..706bca8eb14 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -39,7 +39,7 @@ unsigned long ioremap_base;
unsigned long ioremap_bot;
int io_bat_index;
-#if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
+#if defined(CONFIG_6xx)
#define HAVE_BATS 1
#endif
@@ -368,7 +368,7 @@ void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
* the PTE pointer is unmodified if PTE is not found.
*/
int
-get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
+get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
{
pgd_t *pgd;
pmd_t *pmd;
@@ -383,6 +383,8 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
if (pte) {
retval = 1;
*ptep = pte;
+ if (pmdp)
+ *pmdp = pmd;
/* XXX caller needs to do pte_unmap, yuck */
}
}
@@ -420,7 +422,7 @@ unsigned long iopa(unsigned long addr)
mm = &init_mm;
pa = 0;
- if (get_pteptr(mm, addr, &pte)) {
+ if (get_pteptr(mm, addr, &pte, NULL)) {
pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
pte_unmap(pte);
}
diff --git a/arch/ppc/mm/ppc_mmu.c b/arch/ppc/mm/ppc_mmu.c
index 9a381ed5eb2..25bb6f3347c 100644
--- a/arch/ppc/mm/ppc_mmu.c
+++ b/arch/ppc/mm/ppc_mmu.c
@@ -2,7 +2,7 @@
* This file contains the routines for handling the MMU on those
* PowerPC implementations where the MMU substantially follows the
* architecture specification. This includes the 6xx, 7xx, 7xxx,
- * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
+ * 8260, and 83xx implementations but excludes the 8xx and 4xx.
* -- paulus
*
* Derived from arch/ppc/mm/init.c:
@@ -42,11 +42,7 @@ unsigned long _SDR1;
union ubat { /* BAT register values to be loaded */
BAT bat;
-#ifdef CONFIG_PPC64BRIDGE
- u64 word[2];
-#else
u32 word[2];
-#endif
} BATS[4][2]; /* 4 pairs of IBAT, DBAT */
struct batrange { /* stores address ranges mapped by BATs */
@@ -83,9 +79,6 @@ unsigned long p_mapped_by_bats(unsigned long pa)
unsigned long __init mmu_mapin_ram(void)
{
-#ifdef CONFIG_POWER4
- return 0;
-#else
unsigned long tot, bl, done;
unsigned long max_size = (256<<20);
unsigned long align;
@@ -122,7 +115,6 @@ unsigned long __init mmu_mapin_ram(void)
}
return done;
-#endif
}
/*
@@ -205,27 +197,10 @@ void __init MMU_init_hw(void)
if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105);
-#ifdef CONFIG_PPC64BRIDGE
-#define LG_HPTEG_SIZE 7 /* 128 bytes per HPTEG */
-#define SDR1_LOW_BITS (lg_n_hpteg - 11)
-#define MIN_N_HPTEG 2048 /* min 256kB hash table */
-#else
#define LG_HPTEG_SIZE 6 /* 64 bytes per HPTEG */
#define SDR1_LOW_BITS ((n_hpteg - 1) >> 10)
#define MIN_N_HPTEG 1024 /* min 64kB hash table */
-#endif
-
-#ifdef CONFIG_POWER4
- /* The hash table has already been allocated and initialized
- in prom.c */
- n_hpteg = Hash_size >> LG_HPTEG_SIZE;
- lg_n_hpteg = __ilog2(n_hpteg);
-
- /* Remove the hash table from the available memory */
- if (Hash)
- reserve_phys_mem(__pa(Hash), Hash_size);
-#else /* CONFIG_POWER4 */
/*
* Allow 1 HPTE (1/8 HPTEG) for each page of memory.
* This is less than the recommended amount, but then
@@ -248,7 +223,6 @@ void __init MMU_init_hw(void)
Hash = mem_pieces_find(Hash_size, Hash_size);
cacheable_memzero(Hash, Hash_size);
_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
-#endif /* CONFIG_POWER4 */
Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
index f841972f1fa..554776d4b8a 100644
--- a/arch/ppc/platforms/4xx/ocotea.c
+++ b/arch/ppc/platforms/4xx/ocotea.c
@@ -331,7 +331,7 @@ static void __init ocotea_init(void)
void __init platform_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7)
{
- ibm44x_platform_init(r3, r4, r5, r6, r7);
+ ibm440gx_platform_init(r3, r4, r5, r6, r7);
ppc_md.setup_arch = ocotea_setup_arch;
ppc_md.show_cpuinfo = ocotea_show_cpuinfo;
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index e8b91a33ce9..90c62229442 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -2,18 +2,10 @@
# Makefile for the linux kernel.
#
-# Extra CFLAGS so we don't have to do relative includes
-CFLAGS_chrp_setup.o += -Iarch/$(ARCH)/mm
-
obj-$(CONFIG_APUS) += apus_setup.o
ifeq ($(CONFIG_APUS),y)
obj-$(CONFIG_PCI) += apus_pci.o
endif
-obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o \
- chrp_pegasos_eth.o
-ifeq ($(CONFIG_PPC_CHRP),y)
-obj-$(CONFIG_NVRAM) += chrp_nvram.o
-endif
obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o
obj-$(CONFIG_PREP_RESIDUAL) += residual.o
obj-$(CONFIG_PQ2ADS) += pq2ads.o
@@ -40,7 +32,3 @@ obj-$(CONFIG_EV64360) += ev64360.o
obj-$(CONFIG_MPC86XADS) += mpc866ads_setup.o
obj-$(CONFIG_MPC885ADS) += mpc885ads_setup.o
obj-$(CONFIG_ADS8272) += mpc8272ads_setup.o
-
-ifeq ($(CONFIG_SMP),y)
-obj-$(CONFIG_PPC_CHRP) += chrp_smp.o
-endif
diff --git a/arch/ppc/platforms/chrp_nvram.c b/arch/ppc/platforms/chrp_nvram.c
deleted file mode 100644
index 465ba9b090e..00000000000
--- a/arch/ppc/platforms/chrp_nvram.c
+++ /dev/null
@@ -1,83 +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.
- *
- * /dev/nvram driver for PPC
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <asm/uaccess.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-
-static unsigned int nvram_size;
-static unsigned char nvram_buf[4];
-static DEFINE_SPINLOCK(nvram_lock);
-
-static unsigned char chrp_nvram_read(int addr)
-{
- unsigned long done, flags;
- unsigned char ret;
-
- if (addr >= nvram_size) {
- printk(KERN_DEBUG "%s: read addr %d > nvram_size %u\n",
- current->comm, addr, nvram_size);
- return 0xff;
- }
- spin_lock_irqsave(&nvram_lock, flags);
- if ((call_rtas("nvram-fetch", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done)
- ret = 0xff;
- else
- ret = nvram_buf[0];
- spin_unlock_irqrestore(&nvram_lock, flags);
-
- return ret;
-}
-
-static void chrp_nvram_write(int addr, unsigned char val)
-{
- unsigned long done, flags;
-
- if (addr >= nvram_size) {
- printk(KERN_DEBUG "%s: write addr %d > nvram_size %u\n",
- current->comm, addr, nvram_size);
- return;
- }
- spin_lock_irqsave(&nvram_lock, flags);
- nvram_buf[0] = val;
- if ((call_rtas("nvram-store", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done)
- printk(KERN_DEBUG "rtas IO error storing 0x%02x at %d", val, addr);
- spin_unlock_irqrestore(&nvram_lock, flags);
-}
-
-void __init chrp_nvram_init(void)
-{
- struct device_node *nvram;
- unsigned int *nbytes_p, proplen;
-
- nvram = of_find_node_by_type(NULL, "nvram");
- if (nvram == NULL)
- return;
-
- nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen);
- if (nbytes_p == NULL || proplen != sizeof(unsigned int))
- return;
-
- nvram_size = *nbytes_p;
-
- printk(KERN_INFO "CHRP nvram contains %u bytes\n", nvram_size);
- of_node_put(nvram);
-
- ppc_md.nvram_read_val = chrp_nvram_read;
- ppc_md.nvram_write_val = chrp_nvram_write;
-
- return;
-}
diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c
deleted file mode 100644
index c7fe6182bb7..00000000000
--- a/arch/ppc/platforms/chrp_pci.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * CHRP pci routines.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/hydra.h>
-#include <asm/prom.h>
-#include <asm/gg2.h>
-#include <asm/machdep.h>
-#include <asm/sections.h>
-#include <asm/pci-bridge.h>
-#include <asm/open_pic.h>
-
-/* LongTrail */
-void __iomem *gg2_pci_config_base;
-
-/*
- * The VLSI Golden Gate II has only 512K of PCI configuration space, so we
- * limit the bus number to 3 bits
- */
-
-int gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off,
- int len, u32 *val)
-{
- volatile void __iomem *cfg_data;
- struct pci_controller *hose = bus->sysdata;
-
- if (bus->number > 7)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that off is
- * suitably aligned and that len is 1, 2 or 4.
- */
- cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
- 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;
-}
-
-int gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off,
- int len, u32 val)
-{
- volatile void __iomem *cfg_data;
- struct pci_controller *hose = bus->sysdata;
-
- if (bus->number > 7)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that off is
- * suitably aligned and that len is 1, 2 or 4.
- */
- cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
- 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 gg2_pci_ops =
-{
- gg2_read_config,
- gg2_write_config
-};
-
-/*
- * Access functions for PCI config space using RTAS calls.
- */
-int
-rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 *val)
-{
- struct pci_controller *hose = bus->sysdata;
- unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
- | (((bus->number - hose->first_busno) & 0xff) << 16)
- | (hose->index << 24);
- unsigned long ret = ~0UL;
- int rval;
-
- rval = call_rtas("read-pci-config", 2, 2, &ret, addr, len);
- *val = ret;
- return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
-}
-
-int
-rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 val)
-{
- struct pci_controller *hose = bus->sysdata;
- unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
- | (((bus->number - hose->first_busno) & 0xff) << 16)
- | (hose->index << 24);
- int rval;
-
- rval = call_rtas("write-pci-config", 3, 1, NULL, addr, len, val);
- return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops rtas_pci_ops =
-{
- rtas_read_config,
- rtas_write_config
-};
-
-volatile struct Hydra __iomem *Hydra = NULL;
-
-int __init
-hydra_init(void)
-{
- struct device_node *np;
-
- np = find_devices("mac-io");
- if (np == NULL || np->n_addrs == 0)
- return 0;
- Hydra = ioremap(np->addrs[0].address, np->addrs[0].size);
- printk("Hydra Mac I/O at %x\n", np->addrs[0].address);
- printk("Hydra Feature_Control was %x",
- in_le32(&Hydra->Feature_Control));
- out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
- HYDRA_FC_SCSI_CELL_EN |
- HYDRA_FC_SCCA_ENABLE |
- HYDRA_FC_SCCB_ENABLE |
- HYDRA_FC_ARB_BYPASS |
- HYDRA_FC_MPIC_ENABLE |
- HYDRA_FC_SLOW_SCC_PCLK |
- HYDRA_FC_MPIC_IS_MASTER));
- printk(", now %x\n", in_le32(&Hydra->Feature_Control));
- return 1;
-}
-
-void __init
-chrp_pcibios_fixup(void)
-{
- struct pci_dev *dev = NULL;
- struct device_node *np;
-
- /* PCI interrupts are controlled by the OpenPIC */
- for_each_pci_dev(dev) {
- np = pci_device_to_OF_node(dev);
- if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
- dev->irq = np->intrs[0].line;
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
- }
-}
-
-#define PRG_CL_RESET_VALID 0x00010000
-
-static void __init
-setup_python(struct pci_controller *hose, struct device_node *dev)
-{
- u32 __iomem *reg;
- u32 val;
- unsigned long addr = dev->addrs[0].address;
-
- setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010);
-
- /* Clear the magic go-slow bit */
- reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40);
- val = in_be32(&reg[12]);
- if (val & PRG_CL_RESET_VALID) {
- out_be32(&reg[12], val & ~PRG_CL_RESET_VALID);
- in_be32(&reg[12]);
- }
- iounmap(reg);
-}
-
-/* Marvell Discovery II based Pegasos 2 */
-static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev)
-{
- struct device_node *root = find_path_device("/");
- struct device_node *rtas;
-
- rtas = of_find_node_by_name (root, "rtas");
- if (rtas) {
- hose->ops = &rtas_pci_ops;
- } else {
- printk ("RTAS supporting Pegasos OF not found, please upgrade"
- " your firmware\n");
- }
- pci_assign_all_buses = 1;
-}
-
-void __init
-chrp_find_bridges(void)
-{
- struct device_node *dev;
- int *bus_range;
- int len, index = -1;
- struct pci_controller *hose;
- unsigned int *dma;
- char *model, *machine;
- int is_longtrail = 0, is_mot = 0, is_pegasos = 0;
- struct device_node *root = find_path_device("/");
-
- /*
- * The PCI host bridge nodes on some machines don't have
- * properties to adequately identify them, so we have to
- * look at what sort of machine this is as well.
- */
- machine = get_property(root, "model", NULL);
- if (machine != NULL) {
- is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0;
- is_mot = strncmp(machine, "MOT", 3) == 0;
- if (strncmp(machine, "Pegasos2", 8) == 0)
- is_pegasos = 2;
- else if (strncmp(machine, "Pegasos", 7) == 0)
- is_pegasos = 1;
- }
- for (dev = root->child; dev != NULL; dev = dev->sibling) {
- if (dev->type == NULL || strcmp(dev->type, "pci") != 0)
- continue;
- ++index;
- /* The GG2 bridge on the LongTrail doesn't have an address */
- if (dev->n_addrs < 1 && !is_longtrail) {
- printk(KERN_WARNING "Can't use %s: no address\n",
- dev->full_name);
- continue;
- }
- bus_range = (int *) get_property(dev, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s\n",
- dev->full_name);
- continue;
- }
- if (bus_range[1] == bus_range[0])
- printk(KERN_INFO "PCI bus %d", bus_range[0]);
- else
- printk(KERN_INFO "PCI buses %d..%d",
- bus_range[0], bus_range[1]);
- printk(" controlled by %s", dev->type);
- if (dev->n_addrs > 0)
- printk(" at %x", dev->addrs[0].address);
- printk("\n");
-
- hose = pcibios_alloc_controller();
- 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];
-
- model = get_property(dev, "model", NULL);
- if (model == NULL)
- model = "<none>";
- if (device_is_compatible(dev, "IBM,python")) {
- setup_python(hose, dev);
- } else if (is_mot
- || strncmp(model, "Motorola, Grackle", 17) == 0) {
- setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
- } else if (is_longtrail) {
- void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
- hose->ops = &gg2_pci_ops;
- hose->cfg_data = p;
- gg2_pci_config_base = p;
- } else if (is_pegasos == 1) {
- setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc);
- } else if (is_pegasos == 2) {
- setup_peg2(hose, dev);
- } else {
- printk("No methods for %s (model %s), using RTAS\n",
- dev->full_name, model);
- hose->ops = &rtas_pci_ops;
- }
-
- pci_process_bridge_OF_ranges(hose, dev, index == 0);
-
- /* check the first bridge for a property that we can
- use to set pci_dram_offset */
- dma = (unsigned int *)
- get_property(dev, "ibm,dma-ranges", &len);
- if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) {
- pci_dram_offset = dma[2] - dma[3];
- printk("pci_dram_offset = %lx\n", pci_dram_offset);
- }
- }
-
- /* Do not fixup interrupts from OF tree on pegasos */
- if (is_pegasos == 0)
- ppc_md.pcibios_fixup = chrp_pcibios_fixup;
-}
diff --git a/arch/ppc/platforms/chrp_pegasos_eth.c b/arch/ppc/platforms/chrp_pegasos_eth.c
deleted file mode 100644
index 9305c8aa137..00000000000
--- a/arch/ppc/platforms/chrp_pegasos_eth.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2005 Sven Luther <sl@bplan-gmbh.de>
- * Thanks to :
- * Dale Farnsworth <dale@farnsworth.org>
- * Mark A. Greer <mgreer@mvista.com>
- * Nicolas DET <nd@bplan-gmbh.de>
- * Benjamin Herrenschmidt <benh@kernel.crashing.org>
- * And anyone else who helped me on this.
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/mv643xx.h>
-#include <linux/pci.h>
-
-#define PEGASOS2_MARVELL_REGBASE (0xf1000000)
-#define PEGASOS2_MARVELL_REGSIZE (0x00004000)
-#define PEGASOS2_SRAM_BASE (0xf2000000)
-#define PEGASOS2_SRAM_SIZE (256*1024)
-
-#define PEGASOS2_SRAM_BASE_ETH0 (PEGASOS2_SRAM_BASE)
-#define PEGASOS2_SRAM_BASE_ETH1 (PEGASOS2_SRAM_BASE_ETH0 + (PEGASOS2_SRAM_SIZE / 2) )
-
-
-#define PEGASOS2_SRAM_RXRING_SIZE (PEGASOS2_SRAM_SIZE/4)
-#define PEGASOS2_SRAM_TXRING_SIZE (PEGASOS2_SRAM_SIZE/4)
-
-#undef BE_VERBOSE
-
-static struct resource mv643xx_eth_shared_resources[] = {
- [0] = {
- .name = "ethernet shared base",
- .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
- .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
- MV643XX_ETH_SHARED_REGS_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
- .name = MV643XX_ETH_SHARED_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources),
- .resource = mv643xx_eth_shared_resources,
-};
-
-static struct resource mv643xx_eth0_resources[] = {
- [0] = {
- .name = "eth0 irq",
- .start = 9,
- .end = 9,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-
-static struct mv643xx_eth_platform_data eth0_pd = {
- .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0,
- .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
- .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
-
- .rx_sram_addr = PEGASOS2_SRAM_BASE_ETH0 + PEGASOS2_SRAM_TXRING_SIZE,
- .rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
- .rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
-};
-
-static struct platform_device eth0_device = {
- .name = MV643XX_ETH_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv643xx_eth0_resources),
- .resource = mv643xx_eth0_resources,
- .dev = {
- .platform_data = &eth0_pd,
- },
-};
-
-static struct resource mv643xx_eth1_resources[] = {
- [0] = {
- .name = "eth1 irq",
- .start = 9,
- .end = 9,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
- .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1,
- .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
- .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
-
- .rx_sram_addr = PEGASOS2_SRAM_BASE_ETH1 + PEGASOS2_SRAM_TXRING_SIZE,
- .rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
- .rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
-};
-
-static struct platform_device eth1_device = {
- .name = MV643XX_ETH_NAME,
- .id = 1,
- .num_resources = ARRAY_SIZE(mv643xx_eth1_resources),
- .resource = mv643xx_eth1_resources,
- .dev = {
- .platform_data = &eth1_pd,
- },
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
- &mv643xx_eth_shared_device,
- &eth0_device,
- &eth1_device,
-};
-
-/***********/
-/***********/
-#define MV_READ(offset,val) { val = readl(mv643xx_reg_base + offset); }
-#define MV_WRITE(offset,data) writel(data, mv643xx_reg_base + offset)
-
-static void __iomem *mv643xx_reg_base;
-
-static int Enable_SRAM(void)
-{
- u32 ALong;
-
- if (mv643xx_reg_base == NULL)
- mv643xx_reg_base = ioremap(PEGASOS2_MARVELL_REGBASE,
- PEGASOS2_MARVELL_REGSIZE);
-
- if (mv643xx_reg_base == NULL)
- return -ENOMEM;
-
-#ifdef BE_VERBOSE
- printk("Pegasos II/Marvell MV64361: register remapped from %p to %p\n",
- (void *)PEGASOS2_MARVELL_REGBASE, (void *)mv643xx_reg_base);
-#endif
-
- MV_WRITE(MV64340_SRAM_CONFIG, 0);
-
- MV_WRITE(MV64340_INTEGRATED_SRAM_BASE_ADDR, PEGASOS2_SRAM_BASE >> 16);
-
- MV_READ(MV64340_BASE_ADDR_ENABLE, ALong);
- ALong &= ~(1 << 19);
- MV_WRITE(MV64340_BASE_ADDR_ENABLE, ALong);
-
- ALong = 0x02;
- ALong |= PEGASOS2_SRAM_BASE & 0xffff0000;
- MV_WRITE(MV643XX_ETH_BAR_4, ALong);
-
- MV_WRITE(MV643XX_ETH_SIZE_REG_4, (PEGASOS2_SRAM_SIZE-1) & 0xffff0000);
-
- MV_READ(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
- ALong &= ~(1 << 4);
- MV_WRITE(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
-
-#ifdef BE_VERBOSE
- printk("Pegasos II/Marvell MV64361: register unmapped\n");
- printk("Pegasos II/Marvell MV64361: SRAM at %p, size=%x\n", (void*) PEGASOS2_SRAM_BASE, PEGASOS2_SRAM_SIZE);
-#endif
-
- iounmap(mv643xx_reg_base);
- mv643xx_reg_base = NULL;
-
- return 1;
-}
-
-
-/***********/
-/***********/
-int mv643xx_eth_add_pds(void)
-{
- int ret = 0;
- static struct pci_device_id pci_marvell_mv64360[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360) },
- { }
- };
-
-#ifdef BE_VERBOSE
- printk("Pegasos II/Marvell MV64361: init\n");
-#endif
-
- if (pci_dev_present(pci_marvell_mv64360)) {
- ret = platform_add_devices(mv643xx_eth_pd_devs,
- ARRAY_SIZE(mv643xx_eth_pd_devs));
-
- if ( Enable_SRAM() < 0)
- {
- eth0_pd.tx_sram_addr = 0;
- eth0_pd.tx_sram_size = 0;
- eth0_pd.rx_sram_addr = 0;
- eth0_pd.rx_sram_size = 0;
-
- eth1_pd.tx_sram_addr = 0;
- eth1_pd.tx_sram_size = 0;
- eth1_pd.rx_sram_addr = 0;
- eth1_pd.rx_sram_size = 0;
-
-#ifdef BE_VERBOSE
- printk("Pegasos II/Marvell MV64361: Can't enable the "
- "SRAM\n");
-#endif
- }
- }
-
-#ifdef BE_VERBOSE
- printk("Pegasos II/Marvell MV64361: init is over\n");
-#endif
-
- return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
deleted file mode 100644
index f9fd3f4f8e2..00000000000
--- a/arch/ppc/platforms/chrp_setup.c
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * Copyright (C) 1995 Linus Torvalds
- * Adapted from 'alpha' version by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
- */
-
-/*
- * bootup setup stuff..
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/version.h>
-#include <linux/adb.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/console.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-#include <linux/initrd.h>
-#include <linux/module.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/prom.h>
-#include <asm/gg2.h>
-#include <asm/pci-bridge.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
-#include <asm/irq.h>
-#include <asm/hydra.h>
-#include <asm/sections.h>
-#include <asm/time.h>
-#include <asm/btext.h>
-#include <asm/i8259.h>
-#include <asm/open_pic.h>
-#include <asm/xmon.h>
-#include "mem_pieces.h"
-
-unsigned long chrp_get_rtc_time(void);
-int chrp_set_rtc_time(unsigned long nowtime);
-void chrp_calibrate_decr(void);
-long chrp_time_init(void);
-
-void chrp_find_bridges(void);
-void chrp_event_scan(void);
-void rtas_display_progress(char *, unsigned short);
-void rtas_indicator_progress(char *, unsigned short);
-void btext_progress(char *, unsigned short);
-
-extern int of_show_percpuinfo(struct seq_file *, int);
-
-int _chrp_type;
-EXPORT_SYMBOL(_chrp_type);
-
-/*
- * XXX this should be in xmon.h, but putting it there means xmon.h
- * has to include <linux/interrupt.h> (to get irqreturn_t), which
- * causes all sorts of problems. -- paulus
- */
-extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
-
-extern dev_t boot_dev;
-
-extern PTE *Hash, *Hash_end;
-extern unsigned long Hash_size, Hash_mask;
-extern int probingmem;
-extern unsigned long loops_per_jiffy;
-static int max_width;
-
-#ifdef CONFIG_SMP
-extern struct smp_ops_t chrp_smp_ops;
-#endif
-
-static const char *gg2_memtypes[4] = {
- "FPM", "SDRAM", "EDO", "BEDO"
-};
-static const char *gg2_cachesizes[4] = {
- "256 KB", "512 KB", "1 MB", "Reserved"
-};
-static const char *gg2_cachetypes[4] = {
- "Asynchronous", "Reserved", "Flow-Through Synchronous",
- "Pipelined Synchronous"
-};
-static const char *gg2_cachemodes[4] = {
- "Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
-};
-
-int
-chrp_show_cpuinfo(struct seq_file *m)
-{
- int i, sdramen;
- unsigned int t;
- struct device_node *root;
- const char *model = "";
-
- root = find_path_device("/");
- if (root)
- model = get_property(root, "model", NULL);
- seq_printf(m, "machine\t\t: CHRP %s\n", model);
-
- /* longtrail (goldengate) stuff */
- if (!strncmp(model, "IBM,LongTrail", 13)) {
- /* VLSI VAS96011/12 `Golden Gate 2' */
- /* Memory banks */
- sdramen = (in_le32(gg2_pci_config_base + GG2_PCI_DRAM_CTRL)
- >>31) & 1;
- for (i = 0; i < (sdramen ? 4 : 6); i++) {
- t = in_le32(gg2_pci_config_base+
- GG2_PCI_DRAM_BANK0+
- i*4);
- if (!(t & 1))
- continue;
- switch ((t>>8) & 0x1f) {
- case 0x1f:
- model = "4 MB";
- break;
- case 0x1e:
- model = "8 MB";
- break;
- case 0x1c:
- model = "16 MB";
- break;
- case 0x18:
- model = "32 MB";
- break;
- case 0x10:
- model = "64 MB";
- break;
- case 0x00:
- model = "128 MB";
- break;
- default:
- model = "Reserved";
- break;
- }
- seq_printf(m, "memory bank %d\t: %s %s\n", i, model,
- gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
- }
- /* L2 cache */
- t = in_le32(gg2_pci_config_base+GG2_PCI_CC_CTRL);
- seq_printf(m, "board l2\t: %s %s (%s)\n",
- gg2_cachesizes[(t>>7) & 3],
- gg2_cachetypes[(t>>2) & 3],
- gg2_cachemodes[t & 3]);
- }
- return 0;
-}
-
-/*
- * Fixes for the National Semiconductor PC78308VUL SuperI/O
- *
- * Some versions of Open Firmware incorrectly initialize the IRQ settings
- * for keyboard and mouse
- */
-static inline void __init sio_write(u8 val, u8 index)
-{
- outb(index, 0x15c);
- outb(val, 0x15d);
-}
-
-static inline u8 __init sio_read(u8 index)
-{
- outb(index, 0x15c);
- return inb(0x15d);
-}
-
-static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
- u8 type)
-{
- u8 level0, type0, active;
-
- /* select logical device */
- sio_write(device, 0x07);
- active = sio_read(0x30);
- level0 = sio_read(0x70);
- type0 = sio_read(0x71);
- if (level0 != level || type0 != type || !active) {
- printk(KERN_WARNING "sio: %s irq level %d, type %d, %sactive: "
- "remapping to level %d, type %d, active\n",
- name, level0, type0, !active ? "in" : "", level, type);
- sio_write(0x01, 0x30);
- sio_write(level, 0x70);
- sio_write(type, 0x71);
- }
-}
-
-static void __init sio_init(void)
-{
- struct device_node *root;
-
- if ((root = find_path_device("/")) &&
- !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
- /* logical device 0 (KBC/Keyboard) */
- sio_fixup_irq("keyboard", 0, 1, 2);
- /* select logical device 1 (KBC/Mouse) */
- sio_fixup_irq("mouse", 1, 12, 2);
- }
-}
-
-
-static void __init pegasos_set_l2cr(void)
-{
- struct device_node *np;
-
- /* On Pegasos, enable the l2 cache if needed, as the OF forgets it */
- if (_chrp_type != _CHRP_Pegasos)
- return;
-
- /* Enable L2 cache if needed */
- np = find_type_devices("cpu");
- if (np != NULL) {
- unsigned int *l2cr = (unsigned int *)
- get_property (np, "l2cr", NULL);
- if (l2cr == NULL) {
- printk ("Pegasos l2cr : no cpu l2cr property found\n");
- return;
- }
- if (!((*l2cr) & 0x80000000)) {
- printk ("Pegasos l2cr : L2 cache was not active, "
- "activating\n");
- _set_L2CR(0);
- _set_L2CR((*l2cr) | 0x80000000);
- }
- }
-}
-
-void __init chrp_setup_arch(void)
-{
- struct device_node *device;
-
- /* init to some ~sane value until calibrate_delay() runs */
- loops_per_jiffy = 50000000/HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- /* this is fine for chrp */
- initrd_below_start_ok = 1;
-
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
- ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
-
- /* On pegasos, enable the L2 cache if not already done by OF */
- pegasos_set_l2cr();
-
- /* Lookup PCI host bridges */
- chrp_find_bridges();
-
-#ifndef CONFIG_PPC64BRIDGE
- /*
- * Temporary fixes for PCI devices.
- * -- Geert
- */
- hydra_init(); /* Mac I/O */
-
-#endif /* CONFIG_PPC64BRIDGE */
-
- /*
- * Fix the Super I/O configuration
- */
- sio_init();
-
- /* Get the event scan rate for the rtas so we know how
- * often it expects a heartbeat. -- Cort
- */
- if ( rtas_data ) {
- struct property *p;
- device = find_devices("rtas");
- for ( p = device->properties;
- p && strncmp(p->name, "rtas-event-scan-rate", 20);
- p = p->next )
- /* nothing */ ;
- if ( p && *(unsigned long *)p->value ) {
- ppc_md.heartbeat = chrp_event_scan;
- ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1;
- ppc_md.heartbeat_count = 1;
- printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n",
- *(unsigned long *)p->value, ppc_md.heartbeat_reset );
- }
- }
-
- pci_create_OF_bus_map();
-}
-
-void
-chrp_event_scan(void)
-{
- unsigned char log[1024];
- unsigned long ret = 0;
- /* XXX: we should loop until the hardware says no more error logs -- Cort */
- call_rtas( "event-scan", 4, 1, &ret, 0xffffffff, 0,
- __pa(log), 1024 );
- ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
-}
-
-void
-chrp_restart(char *cmd)
-{
- printk("RTAS system-reboot returned %d\n",
- call_rtas("system-reboot", 0, 1, NULL));
- for (;;);
-}
-
-void
-chrp_power_off(void)
-{
- /* allow power on only with power button press */
- printk("RTAS power-off returned %d\n",
- call_rtas("power-off", 2, 1, NULL,0xffffffff,0xffffffff));
- for (;;);
-}
-
-void
-chrp_halt(void)
-{
- chrp_power_off();
-}
-
-/*
- * Finds the open-pic node and sets OpenPIC_Addr based on its reg property.
- * Then checks if it has an interrupt-ranges property. If it does then
- * we have a distributed open-pic, so call openpic_set_sources to tell
- * the openpic code where to find the interrupt source registers.
- */
-static void __init chrp_find_openpic(void)
-{
- struct device_node *np;
- int len, i;
- unsigned int *iranges;
- void __iomem *isu;
-
- np = find_type_devices("open-pic");
- if (np == NULL || np->n_addrs == 0)
- return;
- printk(KERN_INFO "OpenPIC at %x (size %x)\n",
- np->addrs[0].address, np->addrs[0].size);
- OpenPIC_Addr = ioremap(np->addrs[0].address, 0x40000);
- if (OpenPIC_Addr == NULL) {
- printk(KERN_ERR "Failed to map OpenPIC!\n");
- return;
- }
-
- iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
- if (iranges == NULL || len < 2 * sizeof(unsigned int))
- return; /* not distributed */
-
- /*
- * The first pair of cells in interrupt-ranges refers to the
- * IDU; subsequent pairs refer to the ISUs.
- */
- len /= 2 * sizeof(unsigned int);
- if (np->n_addrs < len) {
- printk(KERN_ERR "Insufficient addresses for distributed"
- " OpenPIC (%d < %d)\n", np->n_addrs, len);
- return;
- }
- if (iranges[1] != 0) {
- printk(KERN_INFO "OpenPIC irqs %d..%d in IDU\n",
- iranges[0], iranges[0] + iranges[1] - 1);
- openpic_set_sources(iranges[0], iranges[1], NULL);
- }
- for (i = 1; i < len; ++i) {
- iranges += 2;
- printk(KERN_INFO "OpenPIC irqs %d..%d in ISU at %x (%x)\n",
- iranges[0], iranges[0] + iranges[1] - 1,
- np->addrs[i].address, np->addrs[i].size);
- isu = ioremap(np->addrs[i].address, np->addrs[i].size);
- if (isu != NULL)
- openpic_set_sources(iranges[0], iranges[1], isu);
- else
- printk(KERN_ERR "Failed to map OpenPIC ISU at %x!\n",
- np->addrs[i].address);
- }
-}
-
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
-static struct irqaction xmon_irqaction = {
- .handler = xmon_irq,
- .mask = CPU_MASK_NONE,
- .name = "XMON break",
-};
-#endif
-
-void __init chrp_init_IRQ(void)
-{
- struct device_node *np;
- unsigned long chrp_int_ack = 0;
- unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
- struct device_node *kbd;
-#endif
-
- for (np = find_devices("pci"); np != NULL; np = np->next) {
- unsigned int *addrp = (unsigned int *)
- get_property(np, "8259-interrupt-acknowledge", NULL);
-
- if (addrp == NULL)
- continue;
- chrp_int_ack = addrp[prom_n_addr_cells(np)-1];
- break;
- }
- if (np == NULL)
- printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n");
-
- chrp_find_openpic();
-
- if (OpenPIC_Addr) {
- prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
- OpenPIC_InitSenses = init_senses;
- OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
-
- openpic_init(NUM_8259_INTERRUPTS);
- /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
- openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
- i8259_irq);
-
- }
- i8259_init(chrp_int_ack, 0);
-
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
- /* see if there is a keyboard in the device tree
- with a parent of type "adb" */
- for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
- if (kbd->parent && kbd->parent->type
- && strcmp(kbd->parent->type, "adb") == 0)
- break;
- if (kbd)
- setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction);
-#endif
-}
-
-void __init
-chrp_init2(void)
-{
-#ifdef CONFIG_NVRAM
- chrp_nvram_init();
-#endif
-
- request_region(0x20,0x20,"pic1");
- request_region(0xa0,0x20,"pic2");
- request_region(0x00,0x20,"dma1");
- request_region(0x40,0x20,"timer");
- request_region(0x80,0x10,"dma page reg");
- request_region(0xc0,0x20,"dma2");
-
- if (ppc_md.progress)
- ppc_md.progress(" Have fun! ", 0x7777);
-}
-
-static struct device_node *memory_node;
-
-static int __init get_mem_prop(char *name, struct mem_pieces *mp)
-{
- struct reg_property *rp;
- int i, s;
- unsigned int *ip;
- int nac = prom_n_addr_cells(memory_node);
- int nsc = prom_n_size_cells(memory_node);
-
- ip = (unsigned int *) get_property(memory_node, name, &s);
- if (ip == NULL) {
- printk(KERN_ERR "error: couldn't get %s property on /memory\n",
- name);
- return 0;
- }
- s /= (nsc + nac) * 4;
- rp = mp->regions;
- for (i = 0; i < s; ++i, ip += nac+nsc) {
- if (nac >= 2 && ip[nac-2] != 0)
- continue;
- rp->address = ip[nac-1];
- if (nsc >= 2 && ip[nac+nsc-2] != 0)
- rp->size = ~0U;
- else
- rp->size = ip[nac+nsc-1];
- ++rp;
- }
- mp->n_regions = rp - mp->regions;
-
- /* Make sure the pieces are sorted. */
- mem_pieces_sort(mp);
- mem_pieces_coalesce(mp);
- return 1;
-}
-
-static unsigned long __init chrp_find_end_of_memory(void)
-{
- unsigned long a, total;
- struct mem_pieces phys_mem;
-
- /*
- * Find out where physical memory is, and check that it
- * starts at 0 and is contiguous. It seems that RAM is
- * always physically contiguous on Power Macintoshes.
- *
- * Supporting discontiguous physical memory isn't hard,
- * it just makes the virtual <-> physical mapping functions
- * more complicated (or else you end up wasting space
- * in mem_map).
- */
- memory_node = find_devices("memory");
- if (memory_node == NULL || !get_mem_prop("reg", &phys_mem)
- || phys_mem.n_regions == 0)
- panic("No RAM??");
- a = phys_mem.regions[0].address;
- if (a != 0)
- panic("RAM doesn't start at physical address 0");
- total = phys_mem.regions[0].size;
-
- if (phys_mem.n_regions > 1) {
- printk("RAM starting at 0x%x is not contiguous\n",
- phys_mem.regions[1].address);
- printk("Using RAM from 0 to 0x%lx\n", total-1);
- }
-
- return total;
-}
-
-void __init
-chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- struct device_node *root = find_path_device ("/");
- char *machine = NULL;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- /* take care of initrd if we have one */
- if ( r6 )
- {
- initrd_start = r6 + KERNELBASE;
- initrd_end = r6 + r7 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- ISA_DMA_THRESHOLD = ~0L;
- DMA_MODE_READ = 0x44;
- DMA_MODE_WRITE = 0x48;
- isa_io_base = CHRP_ISA_IO_BASE; /* default value */
- ppc_do_canonicalize_irqs = 1;
-
- if (root)
- machine = get_property(root, "model", NULL);
- if (machine && strncmp(machine, "Pegasos", 7) == 0) {
- _chrp_type = _CHRP_Pegasos;
- } else if (machine && strncmp(machine, "IBM", 3) == 0) {
- _chrp_type = _CHRP_IBM;
- } else if (machine && strncmp(machine, "MOT", 3) == 0) {
- _chrp_type = _CHRP_Motorola;
- } else {
- /* Let's assume it is an IBM chrp if all else fails */
- _chrp_type = _CHRP_IBM;
- }
-
- ppc_md.setup_arch = chrp_setup_arch;
- ppc_md.show_percpuinfo = of_show_percpuinfo;
- ppc_md.show_cpuinfo = chrp_show_cpuinfo;
-
- ppc_md.init_IRQ = chrp_init_IRQ;
- if (_chrp_type == _CHRP_Pegasos)
- ppc_md.get_irq = i8259_irq;
- else
- ppc_md.get_irq = openpic_get_irq;
-
- ppc_md.init = chrp_init2;
-
- ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
-
- ppc_md.restart = chrp_restart;
- ppc_md.power_off = chrp_power_off;
- ppc_md.halt = chrp_halt;
-
- ppc_md.time_init = chrp_time_init;
- ppc_md.set_rtc_time = chrp_set_rtc_time;
- ppc_md.get_rtc_time = chrp_get_rtc_time;
- ppc_md.calibrate_decr = chrp_calibrate_decr;
-
- ppc_md.find_end_of_memory = chrp_find_end_of_memory;
-
- if (rtas_data) {
- struct device_node *rtas;
- unsigned int *p;
-
- rtas = find_devices("rtas");
- if (rtas != NULL) {
- if (get_property(rtas, "display-character", NULL)) {
- ppc_md.progress = rtas_display_progress;
- p = (unsigned int *) get_property
- (rtas, "ibm,display-line-length", NULL);
- if (p)
- max_width = *p;
- } else if (get_property(rtas, "set-indicator", NULL))
- ppc_md.progress = rtas_indicator_progress;
- }
- }
-#ifdef CONFIG_BOOTX_TEXT
- if (ppc_md.progress == NULL && boot_text_mapped)
- ppc_md.progress = btext_progress;
-#endif
-
-#ifdef CONFIG_SMP
- smp_ops = &chrp_smp_ops;
-#endif /* CONFIG_SMP */
-
- /*
- * Print the banner, then scroll down so boot progress
- * can be printed. -- Cort
- */
- if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
-}
-
-void
-rtas_display_progress(char *s, unsigned short hex)
-{
- int width;
- char *os = s;
-
- if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) )
- return;
-
- width = max_width;
- while ( *os )
- {
- if ( (*os == '\n') || (*os == '\r') )
- width = max_width;
- else
- width--;
- call_rtas( "display-character", 1, 1, NULL, *os++ );
- /* if we overwrite the screen length */
- if ( width == 0 )
- while ( (*os != 0) && (*os != '\n') && (*os != '\r') )
- os++;
- }
-
- /*while ( width-- > 0 )*/
- call_rtas( "display-character", 1, 1, NULL, ' ' );
-}
-
-void
-rtas_indicator_progress(char *s, unsigned short hex)
-{
- call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
-}
-
-#ifdef CONFIG_BOOTX_TEXT
-void
-btext_progress(char *s, unsigned short hex)
-{
- prom_print(s);
- prom_print("\n");
-}
-#endif /* CONFIG_BOOTX_TEXT */
diff --git a/arch/ppc/platforms/chrp_smp.c b/arch/ppc/platforms/chrp_smp.c
deleted file mode 100644
index 97e539557ec..00000000000
--- a/arch/ppc/platforms/chrp_smp.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Smp support for CHRP machines.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
- * deal of code from the sparc and intel versions.
- *
- * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/residual.h>
-#include <asm/time.h>
-#include <asm/open_pic.h>
-#include <asm/machdep.h>
-
-extern unsigned long smp_chrp_cpu_nr;
-
-static int __init
-smp_chrp_probe(void)
-{
- if (smp_chrp_cpu_nr > 1)
- openpic_request_IPIs();
-
- return smp_chrp_cpu_nr;
-}
-
-static void __devinit
-smp_chrp_kick_cpu(int nr)
-{
- *(unsigned long *)KERNELBASE = nr;
- asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
-}
-
-static void __devinit
-smp_chrp_setup_cpu(int cpu_nr)
-{
- if (OpenPIC_Addr)
- do_openpic_setup_cpu();
-}
-
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned int timebase_upper = 0, timebase_lower = 0;
-
-void __devinit
-smp_chrp_give_timebase(void)
-{
- spin_lock(&timebase_lock);
- call_rtas("freeze-time-base", 0, 1, NULL);
- timebase_upper = get_tbu();
- timebase_lower = get_tbl();
- spin_unlock(&timebase_lock);
-
- while (timebase_upper || timebase_lower)
- barrier();
- call_rtas("thaw-time-base", 0, 1, NULL);
-}
-
-void __devinit
-smp_chrp_take_timebase(void)
-{
- while (!(timebase_upper || timebase_lower))
- barrier();
- spin_lock(&timebase_lock);
- set_tb(timebase_upper, timebase_lower);
- timebase_upper = 0;
- timebase_lower = 0;
- spin_unlock(&timebase_lock);
- printk("CPU %i taken timebase\n", smp_processor_id());
-}
-
-/* CHRP with openpic */
-struct smp_ops_t chrp_smp_ops = {
- .message_pass = smp_openpic_message_pass,
- .probe = smp_chrp_probe,
- .kick_cpu = smp_chrp_kick_cpu,
- .setup_cpu = smp_chrp_setup_cpu,
- .give_timebase = smp_chrp_give_timebase,
- .take_timebase = smp_chrp_take_timebase,
-};
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c
deleted file mode 100644
index c8627770af1..00000000000
--- a/arch/ppc/platforms/chrp_time.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 1991, 1992, 1995 Linus Torvalds
- *
- * Adapted for PowerPC (PReP) by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu).
- * Copied and modified from arch/i386/kernel/time.c
- *
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/kernel_stat.h>
-#include <linux/mc146818rtc.h>
-#include <linux/init.h>
-#include <linux/bcd.h>
-
-#include <asm/io.h>
-#include <asm/nvram.h>
-#include <asm/prom.h>
-#include <asm/sections.h>
-#include <asm/time.h>
-
-extern spinlock_t rtc_lock;
-
-static int nvram_as1 = NVRAM_AS1;
-static int nvram_as0 = NVRAM_AS0;
-static int nvram_data = NVRAM_DATA;
-
-long __init chrp_time_init(void)
-{
- struct device_node *rtcs;
- int base;
-
- rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
- if (rtcs == NULL)
- rtcs = find_compatible_devices("rtc", "ds1385-rtc");
- if (rtcs == NULL || rtcs->addrs == NULL)
- return 0;
- base = rtcs->addrs[0].address;
- nvram_as1 = 0;
- nvram_as0 = base;
- nvram_data = base + 1;
-
- return 0;
-}
-
-int chrp_cmos_clock_read(int addr)
-{
- if (nvram_as1 != 0)
- outb(addr>>8, nvram_as1);
- outb(addr, nvram_as0);
- return (inb(nvram_data));
-}
-
-void chrp_cmos_clock_write(unsigned long val, int addr)
-{
- if (nvram_as1 != 0)
- outb(addr>>8, nvram_as1);
- outb(addr, nvram_as0);
- outb(val, nvram_data);
- return;
-}
-
-/*
- * Set the hardware clock. -- Cort
- */
-int chrp_set_rtc_time(unsigned long nowtime)
-{
- unsigned char save_control, save_freq_select;
- struct rtc_time tm;
-
- spin_lock(&rtc_lock);
- to_tm(nowtime, &tm);
-
- save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
-
- chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
-
- save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
-
- chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
- tm.tm_year -= 1900;
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BIN_TO_BCD(tm.tm_sec);
- BIN_TO_BCD(tm.tm_min);
- BIN_TO_BCD(tm.tm_hour);
- BIN_TO_BCD(tm.tm_mon);
- BIN_TO_BCD(tm.tm_mday);
- BIN_TO_BCD(tm.tm_year);
- }
- chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
- chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);
- chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS);
- chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH);
- chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
- chrp_cmos_clock_write(tm.tm_year,RTC_YEAR);
-
- /* The following flags have to be released exactly in this order,
- * otherwise the DS12887 (popular MC146818A clone with integrated
- * battery and quartz) will not reset the oscillator and will not
- * update precisely 500 ms later. You won't find this mentioned in
- * the Dallas Semiconductor data sheets, but who believes data
- * sheets anyway ... -- Markus Kuhn
- */
- chrp_cmos_clock_write(save_control, RTC_CONTROL);
- chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
-
- spin_unlock(&rtc_lock);
- return 0;
-}
-
-unsigned long chrp_get_rtc_time(void)
-{
- unsigned int year, mon, day, hour, min, sec;
- int uip, i;
-
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
-
- /* Since the UIP flag is set for about 2.2 ms and the clock
- * is typically written with a precision of 1 jiffy, trying
- * to obtain a precision better than a few milliseconds is
- * an illusion. Only consistency is interesting, this also
- * allows to use the routine for /dev/rtc without a potential
- * 1 second kernel busy loop triggered by any reader of /dev/rtc.
- */
-
- for ( i = 0; i<1000000; i++) {
- uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
- sec = chrp_cmos_clock_read(RTC_SECONDS);
- min = chrp_cmos_clock_read(RTC_MINUTES);
- hour = chrp_cmos_clock_read(RTC_HOURS);
- day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
- mon = chrp_cmos_clock_read(RTC_MONTH);
- year = chrp_cmos_clock_read(RTC_YEAR);
- uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
- if ((uip & RTC_UIP)==0) break;
- }
-
- if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
- if ((year += 1900) < 1970)
- year += 100;
- return mktime(year, mon, day, hour, min, sec);
-}
-
-/*
- * Calibrate the decrementer frequency with the VIA timer 1.
- */
-#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */
-
-/* VIA registers */
-#define RS 0x200 /* skip between registers */
-#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
-#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
-#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
-#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
-#define ACR (11*RS) /* Auxiliary control register */
-#define IFR (13*RS) /* Interrupt flag register */
-
-/* Bits in ACR */
-#define T1MODE 0xc0 /* Timer 1 mode */
-#define T1MODE_CONT 0x40 /* continuous interrupts */
-
-/* Bits in IFR and IER */
-#define T1_INT 0x40 /* Timer 1 interrupt */
-
-static int __init chrp_via_calibrate_decr(void)
-{
- struct device_node *vias;
- volatile unsigned char __iomem *via;
- int count = VIA_TIMER_FREQ_6 / 100;
- unsigned int dstart, dend;
-
- vias = find_devices("via-cuda");
- if (vias == 0)
- vias = find_devices("via");
- if (vias == 0 || vias->n_addrs == 0)
- return 0;
- via = ioremap(vias->addrs[0].address, vias->addrs[0].size);
-
- /* set timer 1 for continuous interrupts */
- out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
- /* set the counter to a small value */
- out_8(&via[T1CH], 2);
- /* set the latch to `count' */
- out_8(&via[T1LL], count);
- out_8(&via[T1LH], count >> 8);
- /* wait until it hits 0 */
- while ((in_8(&via[IFR]) & T1_INT) == 0)
- ;
- dstart = get_dec();
- /* clear the interrupt & wait until it hits 0 again */
- in_8(&via[T1CL]);
- while ((in_8(&via[IFR]) & T1_INT) == 0)
- ;
- dend = get_dec();
-
- tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100);
- tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
-
- printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
- tb_ticks_per_jiffy, dstart - dend);
-
- iounmap(via);
-
- return 1;
-}
-
-void __init chrp_calibrate_decr(void)
-{
- struct device_node *cpu;
- unsigned int freq, *fp;
-
- if (chrp_via_calibrate_decr())
- return;
-
- /*
- * The cpu node should have a timebase-frequency property
- * to tell us the rate at which the decrementer counts.
- */
- freq = 16666000; /* hardcoded default */
- cpu = find_type_devices("cpu");
- if (cpu != 0) {
- fp = (unsigned int *)
- get_property(cpu, "timebase-frequency", NULL);
- if (fp != 0)
- freq = *fp;
- }
- printk("time_init: decrementer frequency = %u.%.6u MHz\n",
- freq/1000000, freq%1000000);
- tb_ticks_per_jiffy = freq / HZ;
- tb_to_us = mulhwu_scale_factor(freq, 1000000);
-}
diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
index 5171b53bccb..fecbe9adc9e 100644
--- a/arch/ppc/platforms/lite5200.c
+++ b/arch/ppc/platforms/lite5200.c
@@ -34,8 +34,7 @@
#include <asm/mpc52xx.h>
#include <asm/ppc_sys.h>
#include <asm/machdep.h>
-
-#include <syslib/mpc52xx_pci.h>
+#include <asm/pci-bridge.h>
extern int powersave_nap;
@@ -68,44 +67,53 @@ lite5200_show_cpuinfo(struct seq_file *m)
}
#ifdef CONFIG_PCI
+#ifdef CONFIG_LITE5200B
+static int
+lite5200_map_irq(struct pci_dev *dev, unsigned char idsel,
+ unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {MPC52xx_IRQ0, MPC52xx_IRQ1, MPC52xx_IRQ2, MPC52xx_IRQ3},
+ {MPC52xx_IRQ1, MPC52xx_IRQ2, MPC52xx_IRQ3, MPC52xx_IRQ0},
+ };
+
+ const long min_idsel = 24, max_idsel = 25, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+#else /* Original Lite */
static int
lite5200_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
{
return (pin == 1) && (idsel==24) ? MPC52xx_IRQ0 : -1;
}
#endif
+#endif
static void __init
lite5200_setup_cpu(void)
{
- struct mpc52xx_cdm __iomem *cdm;
struct mpc52xx_gpio __iomem *gpio;
struct mpc52xx_intr __iomem *intr;
- struct mpc52xx_xlb __iomem *xlb;
u32 port_config;
u32 intr_ctrl;
/* Map zones */
- cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
- xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
- if (!cdm || !gpio || !xlb || !intr) {
- printk("lite5200.c: Error while mapping CDM/GPIO/XLB/INTR during"
- "lite5200_setup_cpu\n");
+ if (!gpio || !intr) {
+ printk(KERN_ERR __FILE__ ": "
+ "Error while mapping GPIO/INTR during "
+ "lite5200_setup_cpu\n");
goto unmap_regs;
}
- /* Use internal 48 Mhz */
- out_8(&cdm->ext_48mhz_en, 0x00);
- out_8(&cdm->fd_enable, 0x01);
- if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
- out_be16(&cdm->fd_counters, 0x0001);
- else
- out_be16(&cdm->fd_counters, 0x5555);
-
/* Get port mux config */
port_config = in_be32(&gpio->port_config);
@@ -116,29 +124,29 @@ lite5200_setup_cpu(void)
port_config &= ~0x00007000; /* Differential mode - USB1 only */
port_config |= 0x00001000;
+ /* ATA CS is on csb_4/5 */
+ port_config &= ~0x03000000;
+ port_config |= 0x01000000;
+
/* Commit port config */
out_be32(&gpio->port_config, port_config);
- /* Configure the XLB Arbiter */
- out_be32(&xlb->master_pri_enable, 0xff);
- out_be32(&xlb->master_priority, 0x11111111);
-
- /* Enable ram snooping for 1GB window */
- out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP);
- out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d);
-
- /* IRQ[0-3] setup : IRQ0 - Level Active Low */
- /* IRQ[1-3] - Level Active High */
+ /* IRQ[0-3] setup */
intr_ctrl = in_be32(&intr->ctrl);
intr_ctrl &= ~0x00ff0000;
- intr_ctrl |= 0x00c00000;
+#ifdef CONFIG_LITE5200B
+ /* IRQ[0-3] Level Active Low */
+ intr_ctrl |= 0x00ff0000;
+#else
+ /* IRQ0 Level Active Low
+ * IRQ[1-3] Level Active High */
+ intr_ctrl |= 0x00c00000;
+#endif
out_be32(&intr->ctrl, intr_ctrl);
/* Unmap reg zone */
unmap_regs:
- if (cdm) iounmap(cdm);
if (gpio) iounmap(gpio);
- if (xlb) iounmap(xlb);
if (intr) iounmap(intr);
}
@@ -146,7 +154,8 @@ static void __init
lite5200_setup_arch(void)
{
/* CPU & Port mux setup */
- lite5200_setup_cpu();
+ mpc52xx_setup_cpu(); /* Generic */
+ lite5200_setup_cpu(); /* Platform specific */
#ifdef CONFIG_PCI
/* PCI Bridge setup */
diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
index bc9b94f77e3..abb7154de2c 100644
--- a/arch/ppc/platforms/mpc8272ads_setup.c
+++ b/arch/ppc/platforms/mpc8272ads_setup.c
@@ -26,11 +26,35 @@
#include <asm/irq.h>
#include <asm/ppc_sys.h>
#include <asm/ppcboot.h>
+#include <linux/fs_uart_pd.h>
#include "pq2ads_pd.h"
static void init_fcc1_ioports(void);
static void init_fcc2_ioports(void);
+static void init_scc1_uart_ioports(void);
+static void init_scc4_uart_ioports(void);
+
+static struct fs_uart_platform_info mpc8272_uart_pdata[] = {
+ [fsid_scc1_uart] = {
+ .init_ioports = init_scc1_uart_ioports,
+ .fs_no = fsid_scc1_uart,
+ .brg = 1,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+ [fsid_scc4_uart] = {
+ .init_ioports = init_scc4_uart_ioports,
+ .fs_no = fsid_scc4_uart,
+ .brg = 4,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+};
static struct fs_mii_bus_info mii_bus_info = {
.method = fsmii_bitbang,
@@ -201,12 +225,65 @@ static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
}
}
+static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
+ int idx)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+ int num = ARRAY_SIZE(mpc8272_uart_pdata);
+ int id = fs_uart_id_scc2fsid(idx);
+
+ /* no need to alter anything if console */
+ if ((id <= num) && (!pdev->dev.platform_data)) {
+ pinfo = &mpc8272_uart_pdata[id];
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ }
+}
+
+static void init_scc1_uart_ioports(void)
+{
+ cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+
+ /* SCC1 is only on port D */
+ setbits32(&immap->im_ioport.iop_ppard,0x00000003);
+ clrbits32(&immap->im_ioport.iop_psord,0x00000001);
+ setbits32(&immap->im_ioport.iop_psord,0x00000002);
+ clrbits32(&immap->im_ioport.iop_pdird,0x00000001);
+ setbits32(&immap->im_ioport.iop_pdird,0x00000002);
+
+ /* Wire BRG1 to SCC1 */
+ clrbits32(&immap->im_cpmux.cmx_scr,0x00ffffff);
+
+ iounmap(immap);
+}
+
+static void init_scc4_uart_ioports(void)
+{
+ cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+
+ setbits32(&immap->im_ioport.iop_ppard,0x00000600);
+ clrbits32(&immap->im_ioport.iop_psord,0x00000600);
+ clrbits32(&immap->im_ioport.iop_pdird,0x00000200);
+ setbits32(&immap->im_ioport.iop_pdird,0x00000400);
+
+ /* Wire BRG4 to SCC4 */
+ clrbits32(&immap->im_cpmux.cmx_scr,0x000000ff);
+ setbits32(&immap->im_cpmux.cmx_scr,0x0000001b);
+
+ iounmap(immap);
+}
+
static int mpc8272ads_platform_notify(struct device *dev)
{
static const struct platform_notify_dev_map dev_map[] = {
{
.bus_id = "fsl-cpm-fcc",
- .rtn = mpc8272ads_fixup_enet_pdata
+ .rtn = mpc8272ads_fixup_enet_pdata,
+ },
+ {
+ .bus_id = "fsl-cpm-scc:uart",
+ .rtn = mpc8272ads_fixup_uart_pdata,
},
{
.bus_id = NULL
@@ -230,7 +307,44 @@ int __init mpc8272ads_init(void)
ppc_sys_device_enable(MPC82xx_CPM_FCC1);
ppc_sys_device_enable(MPC82xx_CPM_FCC2);
+ /* to be ready for console, let's attach pdata here */
+#ifdef CONFIG_SERIAL_CPM_SCC1
+ ppc_sys_device_setfunc(MPC82xx_CPM_SCC1, PPC_SYS_FUNC_UART);
+ ppc_sys_device_enable(MPC82xx_CPM_SCC1);
+
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC4
+ ppc_sys_device_setfunc(MPC82xx_CPM_SCC4, PPC_SYS_FUNC_UART);
+ ppc_sys_device_enable(MPC82xx_CPM_SCC4);
+#endif
+
+
return 0;
}
+/*
+ To prevent confusion, console selection is gross:
+ by 0 assumed SCC1 and by 1 assumed SCC4
+ */
+struct platform_device* early_uart_get_pdev(int index)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+
+ struct platform_device* pdev = NULL;
+ if(index) { /*assume SCC4 here*/
+ pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC4];
+ pinfo = &mpc8272_uart_pdata[fsid_scc4_uart];
+ } else { /*over SCC1*/
+ pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC1];
+ pinfo = &mpc8272_uart_pdata[fsid_scc1_uart];
+ }
+
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ ppc_sys_fixup_mem_resource(pdev, CPM_MAP_ADDR);
+ return NULL;
+}
+
arch_initcall(mpc8272ads_init);
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
index ac8fcc68afe..d919dab6134 100644
--- a/arch/ppc/platforms/mpc866ads_setup.c
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <linux/fs_enet_pd.h>
+#include <linux/fs_uart_pd.h>
#include <linux/mii.h>
#include <asm/delay.h>
@@ -37,6 +38,11 @@
extern unsigned char __res[];
+static void setup_fec1_ioports(void);
+static void setup_scc1_ioports(void);
+static void setup_smc1_ioports(void);
+static void setup_smc2_ioports(void);
+
static struct fs_mii_bus_info fec_mii_bus_info = {
.method = fsmii_fec,
.id = 0,
@@ -79,6 +85,28 @@ static struct fs_platform_info mpc8xx_scc_pdata = {
.phy_irq = -1,
.bus_info = &scc_mii_bus_info,
+
+};
+
+static struct fs_uart_platform_info mpc866_uart_pdata[] = {
+ [fsid_smc1_uart] = {
+ .brg = 1,
+ .fs_no = fsid_smc1_uart,
+ .init_ioports = setup_smc1_ioports,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+ [fsid_smc2_uart] = {
+ .brg = 2,
+ .fs_no = fsid_smc2_uart,
+ .init_ioports = setup_smc2_ioports,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
};
void __init board_init(void)
@@ -92,9 +120,12 @@ void __init board_init(void)
printk(KERN_CRIT "Could not remap BCSR1\n");
return;
}
+
#ifdef CONFIG_SERIAL_CPM_SMC1
cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
clrbits32(bcsr_io,(0x80000000 >> 7));
+ cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX);
+ cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
#else
setbits32(bcsr_io,(0x80000000 >> 7));
@@ -108,6 +139,8 @@ void __init board_init(void)
cp->cp_simode &= ~(0xe0000000 >> 1);
cp->cp_simode |= (0x20000000 >> 1); /* brg2 */
clrbits32(bcsr_io,(0x80000000 >> 13));
+ cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX);
+ cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
#else
clrbits32(bcsr_io,(0x80000000 >> 13));
cp->cp_pbpar &= ~(0x00000c00);
@@ -232,6 +265,74 @@ static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
}
+static void setup_smc1_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+ unsigned int iobits = 0x000000c0;
+
+ 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);
+
+ setbits32(&immap->im_cpm.cp_pbpar, iobits);
+ clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+ clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+
+}
+
+static void setup_smc2_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+ unsigned int iobits = 0x00000c00;
+
+ 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);
+
+#ifndef CONFIG_SERIAL_CPM_ALT_SMC2
+ setbits32(&immap->im_cpm.cp_pbpar, iobits);
+ clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+ clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+#else
+ setbits16(&immap->im_ioport.iop_papar, iobits);
+ clrbits16(&immap->im_ioport.iop_padir, iobits);
+ clrbits16(&immap->im_ioport.iop_paodr, iobits);
+#endif
+
+}
+
+static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev,
+ int idx)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+ int num = ARRAY_SIZE(mpc866_uart_pdata);
+
+ int id = fs_uart_id_smc2fsid(idx);
+
+ /* no need to alter anything if console */
+ if ((id <= num) && (!pdev->dev.platform_data)) {
+ pinfo = &mpc866_uart_pdata[id];
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ }
+}
+
static int mpc866ads_platform_notify(struct device *dev)
{
static const struct platform_notify_dev_map dev_map[] = {
@@ -244,6 +345,10 @@ static int mpc866ads_platform_notify(struct device *dev)
.rtn = mpc866ads_fixup_scc_enet_pdata,
},
{
+ .bus_id = "fsl-cpm-smc:uart",
+ .rtn = mpc866ads_fixup_uart_pdata
+ },
+ {
.bus_id = NULL
}
};
@@ -267,7 +372,42 @@ int __init mpc866ads_init(void)
#endif
ppc_sys_device_enable(MPC8xx_CPM_FEC1);
+/* Since either of the uarts could be used as console, they need to ready */
+#ifdef CONFIG_SERIAL_CPM_SMC1
+ ppc_sys_device_enable(MPC8xx_CPM_SMC1);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC
+ ppc_sys_device_enable(MPC8xx_CPM_SMC2);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
+#endif
+
return 0;
}
+/*
+ To prevent confusion, console selection is gross:
+ by 0 assumed SMC1 and by 1 assumed SMC2
+ */
+struct platform_device* early_uart_get_pdev(int index)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+
+ struct platform_device* pdev = NULL;
+ if(index) { /*assume SMC2 here*/
+ pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2];
+ pinfo = &mpc866_uart_pdata[1];
+ } else { /*over SMC1*/
+ pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1];
+ pinfo = &mpc866_uart_pdata[0];
+ }
+
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
+ return NULL;
+}
+
arch_initcall(mpc866ads_init);
diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c
index 50a99e5f7c6..4b88679cd31 100644
--- a/arch/ppc/platforms/mpc885ads_setup.c
+++ b/arch/ppc/platforms/mpc885ads_setup.c
@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <linux/fs_enet_pd.h>
+#include <linux/fs_uart_pd.h>
#include <linux/mii.h>
#include <asm/delay.h>
@@ -35,9 +36,32 @@
#include <asm/ppc_sys.h>
extern unsigned char __res[];
+static void setup_smc1_ioports(void);
+static void setup_smc2_ioports(void);
static void __init mpc885ads_scc_phy_init(char);
+static struct fs_uart_platform_info mpc885_uart_pdata[] = {
+ [fsid_smc1_uart] = {
+ .brg = 1,
+ .fs_no = fsid_smc1_uart,
+ .init_ioports = setup_smc1_ioports,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+ [fsid_smc2_uart] = {
+ .brg = 2,
+ .fs_no = fsid_smc2_uart,
+ .init_ioports = setup_smc2_ioports,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+};
+
static struct fs_mii_bus_info fec_mii_bus_info = {
.method = fsmii_fec,
.id = 0,
@@ -116,6 +140,8 @@ void __init board_init(void)
#ifdef CONFIG_SERIAL_CPM_SMC1
cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
clrbits32(bcsr_io, BCSR1_RS232EN_1);
+ cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX);
+ cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
#else
setbits32(bcsr_io,BCSR1_RS232EN_1);
cp->cp_smc[0].smc_smcmr = 0;
@@ -126,6 +152,8 @@ void __init board_init(void)
cp->cp_simode &= ~(0xe0000000 >> 1);
cp->cp_simode |= (0x20000000 >> 1); /* brg2 */
clrbits32(bcsr_io,BCSR1_RS232EN_2);
+ cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX);
+ cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
#else
setbits32(bcsr_io,BCSR1_RS232EN_2);
cp->cp_smc[1].smc_smcmr = 0;
@@ -343,6 +371,70 @@ static void mpc885ads_scc_phy_init(char phy_addr)
out_be32(&fecp->fec_mii_speed, 0);
}
+static void setup_smc1_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+ unsigned int iobits = 0x000000c0;
+
+ 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);
+
+ setbits32(&immap->im_cpm.cp_pbpar, iobits);
+ clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+ clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+}
+
+static void setup_smc2_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+ unsigned int iobits = 0x00000c00;
+
+ 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);
+
+#ifndef CONFIG_SERIAL_CPM_ALT_SMC2
+ setbits32(&immap->im_cpm.cp_pbpar, iobits);
+ clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+ clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+#else
+ setbits16(&immap->im_ioport.iop_papar, iobits);
+ clrbits16(&immap->im_ioport.iop_padir, iobits);
+ clrbits16(&immap->im_ioport.iop_paodr, iobits);
+#endif
+}
+
+static void __init mpc885ads_fixup_uart_pdata(struct platform_device *pdev,
+ int idx)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+ int num = ARRAY_SIZE(mpc885_uart_pdata);
+
+ int id = fs_uart_id_smc2fsid(idx);
+
+ /* no need to alter anything if console */
+ if ((id <= num) && (!pdev->dev.platform_data)) {
+ pinfo = &mpc885_uart_pdata[id];
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ }
+}
+
+
static int mpc885ads_platform_notify(struct device *dev)
{
@@ -356,12 +448,17 @@ static int mpc885ads_platform_notify(struct device *dev)
.rtn = mpc885ads_fixup_scc_enet_pdata,
},
{
+ .bus_id = "fsl-cpm-smc:uart",
+ .rtn = mpc885ads_fixup_uart_pdata
+ },
+ {
.bus_id = NULL
}
};
platform_notify_map(dev_map,dev);
+ return 0;
}
int __init mpc885ads_init(void)
@@ -383,7 +480,41 @@ int __init mpc885ads_init(void)
ppc_sys_device_enable(MPC8xx_CPM_FEC2);
#endif
+#ifdef CONFIG_SERIAL_CPM_SMC1
+ ppc_sys_device_enable(MPC8xx_CPM_SMC1);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC2
+ ppc_sys_device_enable(MPC8xx_CPM_SMC2);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
+#endif
return 0;
}
arch_initcall(mpc885ads_init);
+
+/*
+ To prevent confusion, console selection is gross:
+ by 0 assumed SMC1 and by 1 assumed SMC2
+ */
+struct platform_device* early_uart_get_pdev(int index)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+
+ struct platform_device* pdev = NULL;
+ if(index) { /*assume SMC2 here*/
+ pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2];
+ pinfo = &mpc885_uart_pdata[1];
+ } else { /*over SMC1*/
+ pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1];
+ pinfo = &mpc885_uart_pdata[0];
+ }
+
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
+ return NULL;
+}
+
diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c
index 3365fd788a7..7fc2e02f524 100644
--- a/arch/ppc/platforms/pq2ads.c
+++ b/arch/ppc/platforms/pq2ads.c
@@ -14,11 +14,40 @@
#include <linux/init.h>
+#include <asm/io.h>
#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+#include <asm/immap_cpm2.h>
void __init
m82xx_board_setup(void)
{
+ cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+ u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));
+
/* Enable the 2nd UART port */
- *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2;
+ clrbits32(bcsr, BCSR1_RS232_EN2);
+
+#ifdef CONFIG_SERIAL_CPM_SCC1
+ clrbits32((u32*)&immap->im_scc[0].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32*)&immap->im_scc[0].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC2
+ clrbits32((u32*)&immap->im_scc[1].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32*)&immap->im_scc[1].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC3
+ clrbits32((u32*)&immap->im_scc[2].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32*)&immap->im_scc[2].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC4
+ clrbits32((u32*)&immap->im_scc[3].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32*)&immap->im_scc[3].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+ iounmap(bcsr);
+ iounmap(immap);
}
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index a0fc628ffb1..e86f6156d58 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -736,7 +736,7 @@ ibm_statusled_progress(char *s, unsigned short hex)
hex = 0xfff;
if (!notifier_installed) {
++notifier_installed;
- notifier_chain_register(&panic_notifier_list,
+ atomic_notifier_chain_register(&panic_notifier_list,
&ibm_statusled_block);
}
}
@@ -1067,15 +1067,13 @@ prep_map_io(void)
static int __init
prep_request_io(void)
{
- if (_machine == _MACH_prep) {
#ifdef CONFIG_NVRAM
- request_region(PREP_NVRAM_AS0, 0x8, "nvram");
+ request_region(PREP_NVRAM_AS0, 0x8, "nvram");
#endif
- request_region(0x00,0x20,"dma1");
- request_region(0x40,0x20,"timer");
- request_region(0x80,0x10,"dma page reg");
- request_region(0xc0,0x20,"dma2");
- }
+ request_region(0x00,0x20,"dma1");
+ request_region(0x40,0x20,"timer");
+ request_region(0x80,0x10,"dma page reg");
+ request_region(0xc0,0x20,"dma2");
return 0;
}
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 5cb62c6a51c..490749ca88f 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -38,8 +38,6 @@ endif
obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \
ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o
obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o
-obj-$(CONFIG_PPC_OF) += prom_init.o prom.o
-obj-$(CONFIG_PPC_CHRP) += open_pic.o
obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o
obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o
obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o
diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c
index a7dd55f1c63..f6cc1688852 100644
--- a/arch/ppc/syslib/ibm440gx_common.c
+++ b/arch/ppc/syslib/ibm440gx_common.c
@@ -2,7 +2,7 @@
* PPC440GX system library
*
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
- * Copyright (c) 2003, 2004 Zultys Technologies
+ * Copyright (c) 2003 - 2006 Zultys Technologies
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -282,3 +282,14 @@ int ibm440gx_show_cpuinfo(struct seq_file *m){
return 0;
}
+void __init ibm440gx_platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6,
+ unsigned long r7)
+{
+ /* Erratum 440_43 workaround, disable L1 cache parity checking */
+ if (!strcmp(cur_cpu_spec->cpu_name, "440GX Rev. C") ||
+ !strcmp(cur_cpu_spec->cpu_name, "440GX Rev. F"))
+ mtspr(SPRN_CCR1, mfspr(SPRN_CCR1) | CCR1_DPC);
+
+ ibm44x_platform_init(r3, r4, r5, r6, r7);
+}
diff --git a/arch/ppc/syslib/ibm440gx_common.h b/arch/ppc/syslib/ibm440gx_common.h
index a2ab9fab8e3..a03ec6022e8 100644
--- a/arch/ppc/syslib/ibm440gx_common.h
+++ b/arch/ppc/syslib/ibm440gx_common.h
@@ -29,6 +29,10 @@
void ibm440gx_get_clocks(struct ibm44x_clocks*, unsigned int sys_clk,
unsigned int ser_clk) __init;
+/* common 440GX platform init */
+void ibm440gx_platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7) __init;
+
/* Enable L2 cache */
void ibm440gx_l2c_enable(void) __init;
diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c
index 9ec525f9fe9..5a5a7a9cd24 100644
--- a/arch/ppc/syslib/mpc52xx_pci.c
+++ b/arch/ppc/syslib/mpc52xx_pci.c
@@ -225,7 +225,8 @@ mpc52xx_pci_fixup_resources(struct pci_dev *dev)
/* The PCI Host bridge of MPC52xx has a prefetch memory resource
fixed to 1Gb. Doesn't fit in the resource system so we remove it */
if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
- (dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200) ) {
+ ( dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
+ || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
struct resource *res = &dev->resource[1];
res->start = res->end = res->flags = 0;
}
diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
index 2ee48ce0a51..ee6379bb415 100644
--- a/arch/ppc/syslib/mpc52xx_setup.c
+++ b/arch/ppc/syslib/mpc52xx_setup.c
@@ -24,6 +24,8 @@
#include <asm/pgtable.h>
#include <asm/ppcboot.h>
+#include <syslib/mpc52xx_pci.h>
+
extern bd_t __res;
static int core_mult[] = { /* CPU Frequency multiplier, taken */
@@ -216,6 +218,52 @@ mpc52xx_calibrate_decr(void)
tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
}
+
+void __init
+mpc52xx_setup_cpu(void)
+{
+ struct mpc52xx_cdm __iomem *cdm;
+ struct mpc52xx_xlb __iomem *xlb;
+
+ /* Map zones */
+ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
+ xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
+
+ if (!cdm || !xlb) {
+ printk(KERN_ERR __FILE__ ": "
+ "Error while mapping CDM/XLB during "
+ "mpc52xx_setup_cpu\n");
+ goto unmap_regs;
+ }
+
+ /* Use internal 48 Mhz */
+ out_8(&cdm->ext_48mhz_en, 0x00);
+ out_8(&cdm->fd_enable, 0x01);
+ if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
+ out_be16(&cdm->fd_counters, 0x0001);
+ else
+ out_be16(&cdm->fd_counters, 0x5555);
+
+ /* Configure the XLB Arbiter priorities */
+ out_be32(&xlb->master_pri_enable, 0xff);
+ out_be32(&xlb->master_priority, 0x11111111);
+
+ /* Enable ram snooping for 1GB window */
+ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP);
+ out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d);
+
+ /* Disable XLB pipelining */
+ /* (cfr errate 292. We could do this only just before ATA PIO
+ transaction and re-enable it after ...) */
+ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS);
+
+ /* Unmap reg zone */
+unmap_regs:
+ if (cdm) iounmap(cdm);
+ if (xlb) iounmap(xlb);
+}
+
+
int mpc52xx_match_psc_function(int psc_idx, const char *func)
{
struct mpc52xx_psc_func *cf = mpc52xx_psc_functions;
diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c
index bd41ed83beb..6f536383866 100644
--- a/arch/ppc/syslib/mpc8xx_devices.c
+++ b/arch/ppc/syslib/mpc8xx_devices.c
@@ -170,12 +170,18 @@ struct platform_device ppc_sys_platform_devices[] = {
[MPC8xx_CPM_SMC1] = {
.name = "fsl-cpm-smc",
.id = 1,
- .num_resources = 2,
+ .num_resources = 3,
.resource = (struct resource[]) {
{
.name = "regs",
- .start = 0xa82,
- .end = 0xa91,
+ .start = 0xa80,
+ .end = 0xa8f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "pram",
+ .start = 0x3e80,
+ .end = 0x3ebf,
.flags = IORESOURCE_MEM,
},
{
@@ -189,15 +195,22 @@ struct platform_device ppc_sys_platform_devices[] = {
[MPC8xx_CPM_SMC2] = {
.name = "fsl-cpm-smc",
.id = 2,
- .num_resources = 2,
+ .num_resources = 3,
.resource = (struct resource[]) {
{
.name = "regs",
- .start = 0xa92,
- .end = 0xaa1,
+ .start = 0xa90,
+ .end = 0xa9f,
.flags = IORESOURCE_MEM,
},
{
+ .name = "pram",
+ .start = 0x3f80,
+ .end = 0x3fbf,
+ .flags = IORESOURCE_MEM,
+
+ },
+ {
.name = "interrupt",
.start = MPC8xx_INT_SMC2,
.end = MPC8xx_INT_SMC2,
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index 38e5b93fbe4..70456c8f998 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -216,7 +216,7 @@ static void openpic_safe_writefield(volatile u_int __iomem *addr, u_int mask,
u_int openpic_read_IPI(volatile u_int __iomem * addr)
{
u_int val = 0;
-#if defined(OPENPIC_BIG_ENDIAN) || defined(CONFIG_POWER3)
+#if defined(OPENPIC_BIG_ENDIAN)
val = in_be32(addr);
#else
val = in_le32(addr);
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
index 60c724e1158..2d48018b71d 100644
--- a/arch/ppc/syslib/ppc_sys.c
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -109,9 +109,11 @@ ppc_sys_fixup_mem_resource(struct platform_device *pdev, phys_addr_t paddr)
int i;
for (i = 0; i < pdev->num_resources; i++) {
struct resource *r = &pdev->resource[i];
- if ((r->flags & IORESOURCE_MEM) == IORESOURCE_MEM) {
+ if (((r->flags & IORESOURCE_MEM) == IORESOURCE_MEM) &&
+ ((r->flags & PPC_SYS_IORESOURCE_FIXUPPED) != PPC_SYS_IORESOURCE_FIXUPPED)) {
r->start += paddr;
r->end += paddr;
+ r->flags |= PPC_SYS_IORESOURCE_FIXUPPED;
}
}
}
@@ -156,12 +158,13 @@ void platform_notify_map(const struct platform_notify_dev_map *map,
while (map->bus_id != NULL) {
idx = -1;
s = strrchr(dev->bus_id, '.');
- if (s != NULL)
+ if (s != NULL) {
idx = (int)simple_strtol(s + 1, NULL, 10);
- else
+ len = s - dev->bus_id;
+ } else {
s = dev->bus_id;
-
- len = s - dev->bus_id;
+ len = strlen(dev->bus_id);
+ }
if (!strncmp(dev->bus_id, map->bus_id, len)) {
pdev = container_of(dev, struct platform_device, dev);
diff --git a/arch/ppc/syslib/pq2_devices.c b/arch/ppc/syslib/pq2_devices.c
index 0636aed7b82..8692d00c08c 100644
--- a/arch/ppc/syslib/pq2_devices.c
+++ b/arch/ppc/syslib/pq2_devices.c
@@ -121,13 +121,13 @@ struct platform_device ppc_sys_platform_devices[] = {
.num_resources = 3,
.resource = (struct resource[]) {
{
- .name = "scc_mem",
+ .name = "regs",
.start = 0x11A00,
.end = 0x11A1F,
.flags = IORESOURCE_MEM,
},
{
- .name = "scc_pram",
+ .name = "pram",
.start = 0x8000,
.end = 0x80ff,
.flags = IORESOURCE_MEM,
@@ -145,13 +145,13 @@ struct platform_device ppc_sys_platform_devices[] = {
.num_resources = 3,
.resource = (struct resource[]) {
{
- .name = "scc_mem",
+ .name = "regs",
.start = 0x11A20,
.end = 0x11A3F,
.flags = IORESOURCE_MEM,
},
{
- .name = "scc_pram",
+ .name = "pram",
.start = 0x8100,
.end = 0x81ff,
.flags = IORESOURCE_MEM,
@@ -169,13 +169,13 @@ struct platform_device ppc_sys_platform_devices[] = {
.num_resources = 3,
.resource = (struct resource[]) {
{
- .name = "scc_mem",
+ .name = "regs",
.start = 0x11A40,
.end = 0x11A5F,
.flags = IORESOURCE_MEM,
},
{
- .name = "scc_pram",
+ .name = "pram",
.start = 0x8200,
.end = 0x82ff,
.flags = IORESOURCE_MEM,
@@ -193,13 +193,13 @@ struct platform_device ppc_sys_platform_devices[] = {
.num_resources = 3,
.resource = (struct resource[]) {
{
- .name = "scc_mem",
+ .name = "regs",
.start = 0x11A60,
.end = 0x11A7F,
.flags = IORESOURCE_MEM,
},
{
- .name = "scc_pram",
+ .name = "pram",
.start = 0x8300,
.end = 0x83ff,
.flags = IORESOURCE_MEM,
diff --git a/arch/ppc/syslib/pq2_sys.c b/arch/ppc/syslib/pq2_sys.c
index 75e64f1c144..fee8948162b 100644
--- a/arch/ppc/syslib/pq2_sys.c
+++ b/arch/ppc/syslib/pq2_sys.c
@@ -113,13 +113,13 @@ struct ppc_sys_spec ppc_sys_specs[] = {
.ppc_sys_name = "8248",
.mask = 0x0000ff00,
.value = 0x00000c00,
- .num_devices = 11,
+ .num_devices = 12,
.device_list = (enum ppc_sys_devices[])
{
MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1,
- MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SMC1,
- MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
- MPC82xx_CPM_USB, MPC82xx_SEC1,
+ MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4,
+ MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI,
+ MPC82xx_CPM_I2C, MPC82xx_CPM_USB, MPC82xx_SEC1,
},
},
{
@@ -139,13 +139,13 @@ struct ppc_sys_spec ppc_sys_specs[] = {
.ppc_sys_name = "8272",
.mask = 0x0000ff00,
.value = 0x00000c00,
- .num_devices = 11,
+ .num_devices = 12,
.device_list = (enum ppc_sys_devices[])
{
MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1,
- MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SMC1,
- MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
- MPC82xx_CPM_USB, MPC82xx_SEC1,
+ MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4,
+ MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI,
+ MPC82xx_CPM_I2C, MPC82xx_CPM_USB, MPC82xx_SEC1,
},
},
/* below is a list of the 8280 family of processors */
diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c
deleted file mode 100644
index 482f837fd37..00000000000
--- a/arch/ppc/syslib/prom.c
+++ /dev/null
@@ -1,1429 +0,0 @@
-/*
- * Procedures for interfacing to the Open Firmware PROM on
- * Power Macintosh computers.
- *
- * In particular, we are interested in the device tree
- * and in using some of its services (exit, write to stdout).
- *
- * Paul Mackerras August 1996.
- * Copyright (C) 1996 Paul Mackerras.
- */
-#include <stdarg.h>
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/threads.h>
-#include <linux/spinlock.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-
-#include <asm/sections.h>
-#include <asm/prom.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/bootx.h>
-#include <asm/system.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/bootinfo.h>
-#include <asm/btext.h>
-#include <asm/pci-bridge.h>
-#include <asm/open_pic.h>
-
-
-struct pci_address {
- unsigned a_hi;
- unsigned a_mid;
- unsigned a_lo;
-};
-
-struct pci_reg_property {
- struct pci_address addr;
- unsigned size_hi;
- unsigned size_lo;
-};
-
-struct isa_reg_property {
- unsigned space;
- unsigned address;
- unsigned size;
-};
-
-typedef unsigned long interpret_func(struct device_node *, unsigned long,
- int, int);
-static interpret_func interpret_pci_props;
-static interpret_func interpret_dbdma_props;
-static interpret_func interpret_isa_props;
-static interpret_func interpret_macio_props;
-static interpret_func interpret_root_props;
-
-extern char *klimit;
-
-/* Set for a newworld or CHRP machine */
-int use_of_interrupt_tree;
-struct device_node *dflt_interrupt_controller;
-int num_interrupt_controllers;
-
-extern unsigned int rtas_entry; /* physical pointer */
-
-extern struct device_node *allnodes;
-
-static unsigned long finish_node(struct device_node *, unsigned long,
- interpret_func *, int, int);
-static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
-static struct device_node *find_phandle(phandle);
-
-extern void enter_rtas(void *);
-void phys_call_rtas(int, int, int, ...);
-
-extern char cmd_line[512]; /* XXX */
-extern boot_infos_t *boot_infos;
-unsigned long dev_tree_size;
-
-void
-phys_call_rtas(int service, int nargs, int nret, ...)
-{
- va_list list;
- union {
- unsigned long words[16];
- double align;
- } u;
- void (*rtas)(void *, unsigned long);
- int i;
-
- u.words[0] = service;
- u.words[1] = nargs;
- u.words[2] = nret;
- va_start(list, nret);
- for (i = 0; i < nargs; ++i)
- u.words[i+3] = va_arg(list, unsigned long);
- va_end(list);
-
- rtas = (void (*)(void *, unsigned long)) rtas_entry;
- rtas(&u, rtas_data);
-}
-
-/*
- * finish_device_tree is called once things are running normally
- * (i.e. with text and data mapped to the address they were linked at).
- * It traverses the device tree and fills in the name, type,
- * {n_}addrs and {n_}intrs fields of each node.
- */
-void __init
-finish_device_tree(void)
-{
- unsigned long mem = (unsigned long) klimit;
- struct device_node *np;
-
- /* All CHRPs now use the interrupt tree */
- for (np = allnodes; np != NULL; np = np->allnext) {
- if (get_property(np, "interrupt-parent", NULL)) {
- use_of_interrupt_tree = 1;
- break;
- }
- }
-
- if (use_of_interrupt_tree) {
- /*
- * We want to find out here how many interrupt-controller
- * nodes there are, and if we are booted from BootX,
- * we need a pointer to the first (and hopefully only)
- * such node. But we can't use find_devices here since
- * np->name has not been set yet. -- paulus
- */
- int n = 0;
- char *name, *ic;
- int iclen;
-
- for (np = allnodes; np != NULL; np = np->allnext) {
- ic = get_property(np, "interrupt-controller", &iclen);
- name = get_property(np, "name", NULL);
- /* checking iclen makes sure we don't get a false
- match on /chosen.interrupt_controller */
- if ((name != NULL
- && strcmp(name, "interrupt-controller") == 0)
- || (ic != NULL && iclen == 0 && strcmp(name, "AppleKiwi"))) {
- if (n == 0)
- dflt_interrupt_controller = np;
- ++n;
- }
- }
- num_interrupt_controllers = n;
- }
-
- mem = finish_node(allnodes, mem, NULL, 1, 1);
- dev_tree_size = mem - (unsigned long) allnodes;
- klimit = (char *) mem;
-}
-
-static unsigned long __init
-finish_node(struct device_node *np, unsigned long mem_start,
- interpret_func *ifunc, int naddrc, int nsizec)
-{
- struct device_node *child;
- int *ip;
-
- np->name = get_property(np, "name", NULL);
- np->type = get_property(np, "device_type", NULL);
-
- if (!np->name)
- np->name = "<NULL>";
- if (!np->type)
- np->type = "<NULL>";
-
- /* get the device addresses and interrupts */
- if (ifunc != NULL)
- mem_start = ifunc(np, mem_start, naddrc, nsizec);
-
- if (use_of_interrupt_tree)
- mem_start = finish_node_interrupts(np, mem_start);
-
- /* Look for #address-cells and #size-cells properties. */
- ip = (int *) get_property(np, "#address-cells", NULL);
- if (ip != NULL)
- naddrc = *ip;
- ip = (int *) get_property(np, "#size-cells", NULL);
- if (ip != NULL)
- nsizec = *ip;
-
- if (np->parent == NULL)
- ifunc = interpret_root_props;
- else if (np->type == 0)
- ifunc = NULL;
- else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
- ifunc = interpret_pci_props;
- else if (!strcmp(np->type, "dbdma"))
- ifunc = interpret_dbdma_props;
- else if (!strcmp(np->type, "mac-io")
- || ifunc == interpret_macio_props)
- ifunc = interpret_macio_props;
- else if (!strcmp(np->type, "isa"))
- ifunc = interpret_isa_props;
- else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3"))
- ifunc = interpret_root_props;
- else if (!((ifunc == interpret_dbdma_props
- || ifunc == interpret_macio_props)
- && (!strcmp(np->type, "escc")
- || !strcmp(np->type, "media-bay"))))
- ifunc = NULL;
-
- /* if we were booted from BootX, convert the full name */
- if (boot_infos
- && strncmp(np->full_name, "Devices:device-tree", 19) == 0) {
- if (np->full_name[19] == 0) {
- strcpy(np->full_name, "/");
- } else if (np->full_name[19] == ':') {
- char *p = np->full_name + 19;
- np->full_name = p;
- for (; *p; ++p)
- if (*p == ':')
- *p = '/';
- }
- }
-
- for (child = np->child; child != NULL; child = child->sibling)
- mem_start = finish_node(child, mem_start, ifunc,
- naddrc, nsizec);
-
- return mem_start;
-}
-
-/*
- * Find the interrupt parent of a node.
- */
-static struct device_node * __init
-intr_parent(struct device_node *p)
-{
- phandle *parp;
-
- parp = (phandle *) get_property(p, "interrupt-parent", NULL);
- if (parp == NULL)
- return p->parent;
- p = find_phandle(*parp);
- if (p != NULL)
- return p;
- /*
- * On a powermac booted with BootX, we don't get to know the
- * phandles for any nodes, so find_phandle will return NULL.
- * Fortunately these machines only have one interrupt controller
- * so there isn't in fact any ambiguity. -- paulus
- */
- if (num_interrupt_controllers == 1)
- p = dflt_interrupt_controller;
- return p;
-}
-
-/*
- * Find out the size of each entry of the interrupts property
- * for a node.
- */
-static int __init
-prom_n_intr_cells(struct device_node *np)
-{
- struct device_node *p;
- unsigned int *icp;
-
- for (p = np; (p = intr_parent(p)) != NULL; ) {
- icp = (unsigned int *)
- get_property(p, "#interrupt-cells", NULL);
- if (icp != NULL)
- return *icp;
- if (get_property(p, "interrupt-controller", NULL) != NULL
- || get_property(p, "interrupt-map", NULL) != NULL) {
- printk("oops, node %s doesn't have #interrupt-cells\n",
- p->full_name);
- return 1;
- }
- }
- printk("prom_n_intr_cells failed for %s\n", np->full_name);
- return 1;
-}
-
-/*
- * Map an interrupt from a device up to the platform interrupt
- * descriptor.
- */
-static int __init
-map_interrupt(unsigned int **irq, struct device_node **ictrler,
- struct device_node *np, unsigned int *ints, int nintrc)
-{
- struct device_node *p, *ipar;
- unsigned int *imap, *imask, *ip;
- int i, imaplen, match;
- int newintrc = 1, newaddrc = 1;
- unsigned int *reg;
- int naddrc;
-
- reg = (unsigned int *) get_property(np, "reg", NULL);
- naddrc = prom_n_addr_cells(np);
- p = intr_parent(np);
- while (p != NULL) {
- if (get_property(p, "interrupt-controller", NULL) != NULL)
- /* this node is an interrupt controller, stop here */
- break;
- imap = (unsigned int *)
- get_property(p, "interrupt-map", &imaplen);
- if (imap == NULL) {
- p = intr_parent(p);
- continue;
- }
- imask = (unsigned int *)
- get_property(p, "interrupt-map-mask", NULL);
- if (imask == NULL) {
- printk("oops, %s has interrupt-map but no mask\n",
- p->full_name);
- return 0;
- }
- imaplen /= sizeof(unsigned int);
- match = 0;
- ipar = NULL;
- while (imaplen > 0 && !match) {
- /* check the child-interrupt field */
- match = 1;
- for (i = 0; i < naddrc && match; ++i)
- match = ((reg[i] ^ imap[i]) & imask[i]) == 0;
- for (; i < naddrc + nintrc && match; ++i)
- match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;
- imap += naddrc + nintrc;
- imaplen -= naddrc + nintrc;
- /* grab the interrupt parent */
- ipar = find_phandle((phandle) *imap++);
- --imaplen;
- if (ipar == NULL && num_interrupt_controllers == 1)
- /* cope with BootX not giving us phandles */
- ipar = dflt_interrupt_controller;
- if (ipar == NULL) {
- printk("oops, no int parent %x in map of %s\n",
- imap[-1], p->full_name);
- return 0;
- }
- /* find the parent's # addr and intr cells */
- ip = (unsigned int *)
- get_property(ipar, "#interrupt-cells", NULL);
- if (ip == NULL) {
- printk("oops, no #interrupt-cells on %s\n",
- ipar->full_name);
- return 0;
- }
- newintrc = *ip;
- ip = (unsigned int *)
- get_property(ipar, "#address-cells", NULL);
- newaddrc = (ip == NULL)? 0: *ip;
- imap += newaddrc + newintrc;
- imaplen -= newaddrc + newintrc;
- }
- if (imaplen < 0) {
- printk("oops, error decoding int-map on %s, len=%d\n",
- p->full_name, imaplen);
- return 0;
- }
- if (!match) {
- printk("oops, no match in %s int-map for %s\n",
- p->full_name, np->full_name);
- return 0;
- }
- p = ipar;
- naddrc = newaddrc;
- nintrc = newintrc;
- ints = imap - nintrc;
- reg = ints - naddrc;
- }
- if (p == NULL)
- printk("hmmm, int tree for %s doesn't have ctrler\n",
- np->full_name);
- *irq = ints;
- *ictrler = p;
- return nintrc;
-}
-
-/*
- * New version of finish_node_interrupts.
- */
-static unsigned long __init
-finish_node_interrupts(struct device_node *np, unsigned long mem_start)
-{
- unsigned int *ints;
- int intlen, intrcells;
- int i, j, n, offset;
- unsigned int *irq;
- struct device_node *ic;
-
- ints = (unsigned int *) get_property(np, "interrupts", &intlen);
- if (ints == NULL)
- return mem_start;
- intrcells = prom_n_intr_cells(np);
- intlen /= intrcells * sizeof(unsigned int);
- np->n_intrs = intlen;
- np->intrs = (struct interrupt_info *) mem_start;
- mem_start += intlen * sizeof(struct interrupt_info);
-
- for (i = 0; i < intlen; ++i) {
- np->intrs[i].line = 0;
- np->intrs[i].sense = 1;
- n = map_interrupt(&irq, &ic, np, ints, intrcells);
- if (n <= 0)
- continue;
- offset = 0;
- /*
- * On a CHRP we have an 8259 which is subordinate to
- * the openpic in the interrupt tree, but we want the
- * openpic's interrupt numbers offsetted, not the 8259's.
- * So we apply the offset if the controller is at the
- * root of the interrupt tree, i.e. has no interrupt-parent.
- * This doesn't cope with the general case of multiple
- * cascaded interrupt controllers, but then neither will
- * irq.c at the moment either. -- paulus
- * The G5 triggers that code, I add a machine test. On
- * those machines, we want to offset interrupts from the
- * second openpic by 128 -- BenH
- */
- if (num_interrupt_controllers > 1
- && ic != NULL
- && get_property(ic, "interrupt-parent", NULL) == NULL)
- offset = 16;
-
- np->intrs[i].line = irq[0] + offset;
- if (n > 1)
- np->intrs[i].sense = irq[1];
- if (n > 2) {
- printk("hmmm, got %d intr cells for %s:", n,
- np->full_name);
- for (j = 0; j < n; ++j)
- printk(" %d", irq[j]);
- printk("\n");
- }
- ints += intrcells;
- }
-
- return mem_start;
-}
-
-/*
- * When BootX makes a copy of the device tree from the MacOS
- * Name Registry, it is in the format we use but all of the pointers
- * are offsets from the start of the tree.
- * This procedure updates the pointers.
- */
-void __init
-relocate_nodes(void)
-{
- unsigned long base;
- struct device_node *np;
- struct property *pp;
-
-#define ADDBASE(x) (x = (typeof (x))((x)? ((unsigned long)(x) + base): 0))
-
- base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset;
- allnodes = (struct device_node *)(base + 4);
- for (np = allnodes; np != 0; np = np->allnext) {
- ADDBASE(np->full_name);
- ADDBASE(np->properties);
- ADDBASE(np->parent);
- ADDBASE(np->child);
- ADDBASE(np->sibling);
- ADDBASE(np->allnext);
- for (pp = np->properties; pp != 0; pp = pp->next) {
- ADDBASE(pp->name);
- ADDBASE(pp->value);
- ADDBASE(pp->next);
- }
- }
-}
-
-int
-prom_n_addr_cells(struct device_node* np)
-{
- int* ip;
- do {
- if (np->parent)
- np = np->parent;
- ip = (int *) get_property(np, "#address-cells", NULL);
- if (ip != NULL)
- return *ip;
- } while (np->parent);
- /* No #address-cells property for the root node, default to 1 */
- return 1;
-}
-
-int
-prom_n_size_cells(struct device_node* np)
-{
- int* ip;
- do {
- if (np->parent)
- np = np->parent;
- ip = (int *) get_property(np, "#size-cells", NULL);
- if (ip != NULL)
- return *ip;
- } while (np->parent);
- /* No #size-cells property for the root node, default to 1 */
- return 1;
-}
-
-static unsigned long __init
-map_addr(struct device_node *np, unsigned long space, unsigned long addr)
-{
- int na;
- unsigned int *ranges;
- int rlen = 0;
- unsigned int type;
-
- type = (space >> 24) & 3;
- if (type == 0)
- return addr;
-
- while ((np = np->parent) != NULL) {
- if (strcmp(np->type, "pci") != 0)
- continue;
- /* PCI bridge: map the address through the ranges property */
- na = prom_n_addr_cells(np);
- ranges = (unsigned int *) get_property(np, "ranges", &rlen);
- while ((rlen -= (na + 5) * sizeof(unsigned int)) >= 0) {
- if (((ranges[0] >> 24) & 3) == type
- && ranges[2] <= addr
- && addr - ranges[2] < ranges[na+4]) {
- /* ok, this matches, translate it */
- addr += ranges[na+2] - ranges[2];
- break;
- }
- ranges += na + 5;
- }
- }
- return addr;
-}
-
-static unsigned long __init
-interpret_pci_props(struct device_node *np, unsigned long mem_start,
- int naddrc, int nsizec)
-{
- struct address_range *adr;
- struct pci_reg_property *pci_addrs;
- int i, l, *ip;
-
- pci_addrs = (struct pci_reg_property *)
- get_property(np, "assigned-addresses", &l);
- if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {
- i = 0;
- adr = (struct address_range *) mem_start;
- while ((l -= sizeof(struct pci_reg_property)) >= 0) {
- adr[i].space = pci_addrs[i].addr.a_hi;
- adr[i].address = map_addr(np, pci_addrs[i].addr.a_hi,
- pci_addrs[i].addr.a_lo);
- adr[i].size = pci_addrs[i].size_lo;
- ++i;
- }
- np->addrs = adr;
- np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
- }
-
- if (use_of_interrupt_tree)
- return mem_start;
-
- ip = (int *) get_property(np, "AAPL,interrupts", &l);
- if (ip == 0 && np->parent)
- ip = (int *) get_property(np->parent, "AAPL,interrupts", &l);
- if (ip == 0)
- ip = (int *) get_property(np, "interrupts", &l);
- if (ip != 0) {
- np->intrs = (struct interrupt_info *) mem_start;
- np->n_intrs = l / sizeof(int);
- mem_start += np->n_intrs * sizeof(struct interrupt_info);
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = *ip++;
- np->intrs[i].sense = 1;
- }
- }
-
- return mem_start;
-}
-
-static unsigned long __init
-interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
- int naddrc, int nsizec)
-{
- struct reg_property *rp;
- struct address_range *adr;
- unsigned long base_address;
- int i, l, *ip;
- struct device_node *db;
-
- base_address = 0;
- for (db = np->parent; db != NULL; db = db->parent) {
- if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) {
- base_address = db->addrs[0].address;
- break;
- }
- }
-
- rp = (struct reg_property *) get_property(np, "reg", &l);
- if (rp != 0 && l >= sizeof(struct reg_property)) {
- i = 0;
- adr = (struct address_range *) mem_start;
- while ((l -= sizeof(struct reg_property)) >= 0) {
- adr[i].space = 2;
- adr[i].address = rp[i].address + base_address;
- adr[i].size = rp[i].size;
- ++i;
- }
- np->addrs = adr;
- np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
- }
-
- if (use_of_interrupt_tree)
- return mem_start;
-
- ip = (int *) get_property(np, "AAPL,interrupts", &l);
- if (ip == 0)
- ip = (int *) get_property(np, "interrupts", &l);
- if (ip != 0) {
- np->intrs = (struct interrupt_info *) mem_start;
- np->n_intrs = l / sizeof(int);
- mem_start += np->n_intrs * sizeof(struct interrupt_info);
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = *ip++;
- np->intrs[i].sense = 1;
- }
- }
-
- return mem_start;
-}
-
-static unsigned long __init
-interpret_macio_props(struct device_node *np, unsigned long mem_start,
- int naddrc, int nsizec)
-{
- struct reg_property *rp;
- struct address_range *adr;
- unsigned long base_address;
- int i, l, *ip;
- struct device_node *db;
-
- base_address = 0;
- for (db = np->parent; db != NULL; db = db->parent) {
- if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
- base_address = db->addrs[0].address;
- break;
- }
- }
-
- rp = (struct reg_property *) get_property(np, "reg", &l);
- if (rp != 0 && l >= sizeof(struct reg_property)) {
- i = 0;
- adr = (struct address_range *) mem_start;
- while ((l -= sizeof(struct reg_property)) >= 0) {
- adr[i].space = 2;
- adr[i].address = rp[i].address + base_address;
- adr[i].size = rp[i].size;
- ++i;
- }
- np->addrs = adr;
- np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
- }
-
- if (use_of_interrupt_tree)
- return mem_start;
-
- ip = (int *) get_property(np, "interrupts", &l);
- if (ip == 0)
- ip = (int *) get_property(np, "AAPL,interrupts", &l);
- if (ip != 0) {
- np->intrs = (struct interrupt_info *) mem_start;
- np->n_intrs = l / sizeof(int);
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = *ip++;
- np->intrs[i].sense = 1;
- }
- mem_start += np->n_intrs * sizeof(struct interrupt_info);
- }
-
- return mem_start;
-}
-
-static unsigned long __init
-interpret_isa_props(struct device_node *np, unsigned long mem_start,
- int naddrc, int nsizec)
-{
- struct isa_reg_property *rp;
- struct address_range *adr;
- int i, l, *ip;
-
- rp = (struct isa_reg_property *) get_property(np, "reg", &l);
- if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
- i = 0;
- adr = (struct address_range *) mem_start;
- while ((l -= sizeof(struct reg_property)) >= 0) {
- adr[i].space = rp[i].space;
- adr[i].address = rp[i].address
- + (adr[i].space? 0: _ISA_MEM_BASE);
- adr[i].size = rp[i].size;
- ++i;
- }
- np->addrs = adr;
- np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
- }
-
- if (use_of_interrupt_tree)
- return mem_start;
-
- ip = (int *) get_property(np, "interrupts", &l);
- if (ip != 0) {
- np->intrs = (struct interrupt_info *) mem_start;
- np->n_intrs = l / (2 * sizeof(int));
- mem_start += np->n_intrs * sizeof(struct interrupt_info);
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = *ip++;
- np->intrs[i].sense = *ip++;
- }
- }
-
- return mem_start;
-}
-
-static unsigned long __init
-interpret_root_props(struct device_node *np, unsigned long mem_start,
- int naddrc, int nsizec)
-{
- struct address_range *adr;
- int i, l, *ip;
- unsigned int *rp;
- int rpsize = (naddrc + nsizec) * sizeof(unsigned int);
-
- rp = (unsigned int *) get_property(np, "reg", &l);
- if (rp != 0 && l >= rpsize) {
- i = 0;
- adr = (struct address_range *) mem_start;
- while ((l -= rpsize) >= 0) {
- adr[i].space = (naddrc >= 2? rp[naddrc-2]: 2);
- adr[i].address = rp[naddrc - 1];
- adr[i].size = rp[naddrc + nsizec - 1];
- ++i;
- rp += naddrc + nsizec;
- }
- np->addrs = adr;
- np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
- }
-
- if (use_of_interrupt_tree)
- return mem_start;
-
- ip = (int *) get_property(np, "AAPL,interrupts", &l);
- if (ip == 0)
- ip = (int *) get_property(np, "interrupts", &l);
- if (ip != 0) {
- np->intrs = (struct interrupt_info *) mem_start;
- np->n_intrs = l / sizeof(int);
- mem_start += np->n_intrs * sizeof(struct interrupt_info);
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = *ip++;
- np->intrs[i].sense = 1;
- }
- }
-
- return mem_start;
-}
-
-/*
- * Work out the sense (active-low level / active-high edge)
- * of each interrupt from the device tree.
- */
-void __init
-prom_get_irq_senses(unsigned char *senses, int off, int max)
-{
- struct device_node *np;
- int i, j;
-
- /* default to level-triggered */
- memset(senses, 1, max - off);
- if (!use_of_interrupt_tree)
- return;
-
- for (np = allnodes; np != 0; np = np->allnext) {
- for (j = 0; j < np->n_intrs; j++) {
- i = np->intrs[j].line;
- if (i >= off && i < max) {
- if (np->intrs[j].sense == 1)
- senses[i-off] = (IRQ_SENSE_LEVEL
- | IRQ_POLARITY_NEGATIVE);
- else
- senses[i-off] = (IRQ_SENSE_EDGE
- | IRQ_POLARITY_POSITIVE);
- }
- }
- }
-}
-
-/*
- * Construct and return a list of the device_nodes with a given name.
- */
-struct device_node *
-find_devices(const char *name)
-{
- struct device_node *head, **prevp, *np;
-
- prevp = &head;
- for (np = allnodes; np != 0; np = np->allnext) {
- if (np->name != 0 && strcasecmp(np->name, name) == 0) {
- *prevp = np;
- prevp = &np->next;
- }
- }
- *prevp = NULL;
- return head;
-}
-
-/*
- * Construct and return a list of the device_nodes with a given type.
- */
-struct device_node *
-find_type_devices(const char *type)
-{
- struct device_node *head, **prevp, *np;
-
- prevp = &head;
- for (np = allnodes; np != 0; np = np->allnext) {
- if (np->type != 0 && strcasecmp(np->type, type) == 0) {
- *prevp = np;
- prevp = &np->next;
- }
- }
- *prevp = NULL;
- return head;
-}
-
-/*
- * Returns all nodes linked together
- */
-struct device_node *
-find_all_nodes(void)
-{
- struct device_node *head, **prevp, *np;
-
- prevp = &head;
- for (np = allnodes; np != 0; np = np->allnext) {
- *prevp = np;
- prevp = &np->next;
- }
- *prevp = NULL;
- return head;
-}
-
-/* Checks if the given "compat" string matches one of the strings in
- * the device's "compatible" property
- */
-int
-device_is_compatible(struct device_node *device, const char *compat)
-{
- const char* cp;
- int cplen, l;
-
- cp = (char *) get_property(device, "compatible", &cplen);
- if (cp == NULL)
- return 0;
- while (cplen > 0) {
- if (strncasecmp(cp, compat, strlen(compat)) == 0)
- return 1;
- l = strlen(cp) + 1;
- cp += l;
- cplen -= l;
- }
-
- return 0;
-}
-
-
-/*
- * Indicates whether the root node has a given value in its
- * compatible property.
- */
-int
-machine_is_compatible(const char *compat)
-{
- struct device_node *root;
-
- root = find_path_device("/");
- if (root == 0)
- return 0;
- return device_is_compatible(root, compat);
-}
-
-/*
- * Construct and return a list of the device_nodes with a given type
- * and compatible property.
- */
-struct device_node *
-find_compatible_devices(const char *type, const char *compat)
-{
- struct device_node *head, **prevp, *np;
-
- prevp = &head;
- for (np = allnodes; np != 0; np = np->allnext) {
- if (type != NULL
- && !(np->type != 0 && strcasecmp(np->type, type) == 0))
- continue;
- if (device_is_compatible(np, compat)) {
- *prevp = np;
- prevp = &np->next;
- }
- }
- *prevp = NULL;
- return head;
-}
-
-/*
- * Find the device_node with a given full_name.
- */
-struct device_node *
-find_path_device(const char *path)
-{
- struct device_node *np;
-
- for (np = allnodes; np != 0; np = np->allnext)
- if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
- return np;
- return NULL;
-}
-
-/*******
- *
- * New implementation of the OF "find" APIs, return a refcounted
- * object, call of_node_put() when done. Currently, still lacks
- * locking as old implementation, this is beeing done for ppc64.
- *
- * Note that property management will need some locking as well,
- * this isn't dealt with yet
- *
- *******/
-
-/**
- * of_find_node_by_name - Find a node by it's "name" property
- * @from: The node to start searching from or NULL, the node
- * you pass will not be searched, only the next one
- * will; typically, you pass what the previous call
- * returned. of_node_put() will be called on it
- * @name: The name string to match against
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_find_node_by_name(struct device_node *from,
- const char *name)
-{
- struct device_node *np = from ? from->allnext : allnodes;
-
- for (; np != 0; np = np->allnext)
- if (np->name != 0 && strcasecmp(np->name, name) == 0)
- break;
- if (from)
- of_node_put(from);
- return of_node_get(np);
-}
-
-/**
- * of_find_node_by_type - Find a node by it's "device_type" property
- * @from: The node to start searching from or NULL, the node
- * you pass will not be searched, only the next one
- * will; typically, you pass what the previous call
- * returned. of_node_put() will be called on it
- * @name: The type string to match against
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_find_node_by_type(struct device_node *from,
- const char *type)
-{
- struct device_node *np = from ? from->allnext : allnodes;
-
- for (; np != 0; np = np->allnext)
- if (np->type != 0 && strcasecmp(np->type, type) == 0)
- break;
- if (from)
- of_node_put(from);
- return of_node_get(np);
-}
-
-/**
- * of_find_compatible_node - Find a node based on type and one of the
- * tokens in it's "compatible" property
- * @from: The node to start searching from or NULL, the node
- * you pass will not be searched, only the next one
- * will; typically, you pass what the previous call
- * returned. of_node_put() will be called on it
- * @type: The type string to match "device_type" or NULL to ignore
- * @compatible: The string to match to one of the tokens in the device
- * "compatible" list.
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_find_compatible_node(struct device_node *from,
- const char *type, const char *compatible)
-{
- struct device_node *np = from ? from->allnext : allnodes;
-
- for (; np != 0; np = np->allnext) {
- if (type != NULL
- && !(np->type != 0 && strcasecmp(np->type, type) == 0))
- continue;
- if (device_is_compatible(np, compatible))
- break;
- }
- if (from)
- of_node_put(from);
- return of_node_get(np);
-}
-
-/**
- * of_find_node_by_path - Find a node matching a full OF path
- * @path: The full path to match
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_find_node_by_path(const char *path)
-{
- struct device_node *np = allnodes;
-
- for (; np != 0; np = np->allnext)
- if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
- break;
- return of_node_get(np);
-}
-
-/**
- * of_find_all_nodes - Get next node in global list
- * @prev: Previous node or NULL to start iteration
- * of_node_put() will be called on it
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_find_all_nodes(struct device_node *prev)
-{
- return of_node_get(prev ? prev->allnext : allnodes);
-}
-
-/**
- * of_get_parent - Get a node's parent if any
- * @node: Node to get parent
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_get_parent(const struct device_node *node)
-{
- return node ? of_node_get(node->parent) : NULL;
-}
-
-/**
- * of_get_next_child - Iterate a node childs
- * @node: parent node
- * @prev: previous child of the parent node, or NULL to get first
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_get_next_child(const struct device_node *node,
- struct device_node *prev)
-{
- struct device_node *next = prev ? prev->sibling : node->child;
-
- for (; next != 0; next = next->sibling)
- if (of_node_get(next))
- break;
- if (prev)
- of_node_put(prev);
- return next;
-}
-
-/**
- * of_node_get - Increment refcount of a node
- * @node: Node to inc refcount, NULL is supported to
- * simplify writing of callers
- *
- * Returns the node itself or NULL if gone. Current implementation
- * does nothing as we don't yet do dynamic node allocation on ppc32
- */
-struct device_node *of_node_get(struct device_node *node)
-{
- return node;
-}
-
-/**
- * of_node_put - Decrement refcount of a node
- * @node: Node to dec refcount, NULL is supported to
- * simplify writing of callers
- *
- * Current implementation does nothing as we don't yet do dynamic node
- * allocation on ppc32
- */
-void of_node_put(struct device_node *node)
-{
-}
-
-/*
- * Find the device_node with a given phandle.
- */
-static struct device_node * __init
-find_phandle(phandle ph)
-{
- struct device_node *np;
-
- for (np = allnodes; np != 0; np = np->allnext)
- if (np->node == ph)
- return np;
- return NULL;
-}
-
-/*
- * Find a property with a given name for a given node
- * and return the value.
- */
-unsigned char *
-get_property(struct device_node *np, const char *name, int *lenp)
-{
- struct property *pp;
-
- for (pp = np->properties; pp != 0; pp = pp->next)
- if (pp->name != NULL && strcmp(pp->name, name) == 0) {
- if (lenp != 0)
- *lenp = pp->length;
- return pp->value;
- }
- return NULL;
-}
-
-/*
- * Add a property to a node
- */
-int
-prom_add_property(struct device_node* np, struct property* prop)
-{
- struct property **next = &np->properties;
-
- prop->next = NULL;
- while (*next)
- next = &(*next)->next;
- *next = prop;
-
- return 0;
-}
-
-/* I quickly hacked that one, check against spec ! */
-static inline unsigned long
-bus_space_to_resource_flags(unsigned int bus_space)
-{
- u8 space = (bus_space >> 24) & 0xf;
- if (space == 0)
- space = 0x02;
- if (space == 0x02)
- return IORESOURCE_MEM;
- else if (space == 0x01)
- return IORESOURCE_IO;
- else {
- printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %x\n",
- bus_space);
- return 0;
- }
-}
-
-static struct resource*
-find_parent_pci_resource(struct pci_dev* pdev, struct address_range *range)
-{
- unsigned long mask;
- int i;
-
- /* Check this one */
- mask = bus_space_to_resource_flags(range->space);
- for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
- if ((pdev->resource[i].flags & mask) == mask &&
- pdev->resource[i].start <= range->address &&
- pdev->resource[i].end > range->address) {
- if ((range->address + range->size - 1) > pdev->resource[i].end) {
- /* Add better message */
- printk(KERN_WARNING "PCI/OF resource overlap !\n");
- return NULL;
- }
- break;
- }
- }
- if (i == DEVICE_COUNT_RESOURCE)
- return NULL;
- return &pdev->resource[i];
-}
-
-/*
- * Request an OF device resource. Currently handles child of PCI devices,
- * or other nodes attached to the root node. Ultimately, put some
- * link to resources in the OF node.
- */
-struct resource*
-request_OF_resource(struct device_node* node, int index, const char* name_postfix)
-{
- struct pci_dev* pcidev;
- u8 pci_bus, pci_devfn;
- unsigned long iomask;
- struct device_node* nd;
- struct resource* parent;
- struct resource *res = NULL;
- int nlen, plen;
-
- if (index >= node->n_addrs)
- goto fail;
-
- /* Sanity check on bus space */
- iomask = bus_space_to_resource_flags(node->addrs[index].space);
- if (iomask & IORESOURCE_MEM)
- parent = &iomem_resource;
- else if (iomask & IORESOURCE_IO)
- parent = &ioport_resource;
- else
- goto fail;
-
- /* Find a PCI parent if any */
- nd = node;
- pcidev = NULL;
- while(nd) {
- if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
- pcidev = pci_find_slot(pci_bus, pci_devfn);
- if (pcidev) break;
- nd = nd->parent;
- }
- if (pcidev)
- parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
- if (!parent) {
- printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",
- node->name);
- goto fail;
- }
-
- res = __request_region(parent, node->addrs[index].address, node->addrs[index].size, NULL);
- if (!res)
- goto fail;
- nlen = strlen(node->name);
- plen = name_postfix ? strlen(name_postfix) : 0;
- res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL);
- if (res->name) {
- strcpy((char *)res->name, node->name);
- if (plen)
- strcpy((char *)res->name+nlen, name_postfix);
- }
- return res;
-fail:
- return NULL;
-}
-
-int
-release_OF_resource(struct device_node* node, int index)
-{
- struct pci_dev* pcidev;
- u8 pci_bus, pci_devfn;
- unsigned long iomask, start, end;
- struct device_node* nd;
- struct resource* parent;
- struct resource *res = NULL;
-
- if (index >= node->n_addrs)
- return -EINVAL;
-
- /* Sanity check on bus space */
- iomask = bus_space_to_resource_flags(node->addrs[index].space);
- if (iomask & IORESOURCE_MEM)
- parent = &iomem_resource;
- else if (iomask & IORESOURCE_IO)
- parent = &ioport_resource;
- else
- return -EINVAL;
-
- /* Find a PCI parent if any */
- nd = node;
- pcidev = NULL;
- while(nd) {
- if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
- pcidev = pci_find_slot(pci_bus, pci_devfn);
- if (pcidev) break;
- nd = nd->parent;
- }
- if (pcidev)
- parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
- if (!parent) {
- printk(KERN_WARNING "release_OF_resource(%s), parent not found\n",
- node->name);
- return -ENODEV;
- }
-
- /* Find us in the parent and its childs */
- res = parent->child;
- start = node->addrs[index].address;
- end = start + node->addrs[index].size - 1;
- while (res) {
- if (res->start == start && res->end == end &&
- (res->flags & IORESOURCE_BUSY))
- break;
- if (res->start <= start && res->end >= end)
- res = res->child;
- else
- res = res->sibling;
- }
- if (!res)
- return -ENODEV;
-
- kfree(res->name);
- res->name = NULL;
- release_resource(res);
- kfree(res);
-
- return 0;
-}
-
-#if 0
-void
-print_properties(struct device_node *np)
-{
- struct property *pp;
- char *cp;
- int i, n;
-
- for (pp = np->properties; pp != 0; pp = pp->next) {
- printk(KERN_INFO "%s", pp->name);
- for (i = strlen(pp->name); i < 16; ++i)
- printk(" ");
- cp = (char *) pp->value;
- for (i = pp->length; i > 0; --i, ++cp)
- if ((i > 1 && (*cp < 0x20 || *cp > 0x7e))
- || (i == 1 && *cp != 0))
- break;
- if (i == 0 && pp->length > 1) {
- /* looks like a string */
- printk(" %s\n", (char *) pp->value);
- } else {
- /* dump it in hex */
- n = pp->length;
- if (n > 64)
- n = 64;
- if (pp->length % 4 == 0) {
- unsigned int *p = (unsigned int *) pp->value;
-
- n /= 4;
- for (i = 0; i < n; ++i) {
- if (i != 0 && (i % 4) == 0)
- printk("\n ");
- printk(" %08x", *p++);
- }
- } else {
- unsigned char *bp = pp->value;
-
- for (i = 0; i < n; ++i) {
- if (i != 0 && (i % 16) == 0)
- printk("\n ");
- printk(" %02x", *bp++);
- }
- }
- printk("\n");
- if (pp->length > 64)
- printk(" ... (length = %d)\n",
- pp->length);
- }
- }
-}
-#endif
-
-static DEFINE_SPINLOCK(rtas_lock);
-
-/* this can be called after setup -- Cort */
-int
-call_rtas(const char *service, int nargs, int nret,
- unsigned long *outputs, ...)
-{
- va_list list;
- int i;
- unsigned long s;
- struct device_node *rtas;
- int *tokp;
- union {
- unsigned long words[16];
- double align;
- } u;
-
- rtas = find_devices("rtas");
- if (rtas == NULL)
- return -1;
- tokp = (int *) get_property(rtas, service, NULL);
- if (tokp == NULL) {
- printk(KERN_ERR "No RTAS service called %s\n", service);
- return -1;
- }
- u.words[0] = *tokp;
- u.words[1] = nargs;
- u.words[2] = nret;
- va_start(list, outputs);
- for (i = 0; i < nargs; ++i)
- u.words[i+3] = va_arg(list, unsigned long);
- va_end(list);
-
- /*
- * RTAS doesn't use floating point.
- * Or at least, according to the CHRP spec we enter RTAS
- * with FP disabled, and it doesn't change the FP registers.
- * -- paulus.
- */
- spin_lock_irqsave(&rtas_lock, s);
- enter_rtas((void *)__pa(&u));
- spin_unlock_irqrestore(&rtas_lock, s);
-
- if (nret > 1 && outputs != NULL)
- for (i = 0; i < nret-1; ++i)
- outputs[i] = u.words[i+nargs+4];
- return u.words[nargs+3];
-}
diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c
deleted file mode 100644
index df14422ae1c..00000000000
--- a/arch/ppc/syslib/prom_init.c
+++ /dev/null
@@ -1,1011 +0,0 @@
-/*
- * Note that prom_init() and anything called from prom_init()
- * may be running at an address that is different from the address
- * that it was linked at. References to static data items are
- * handled by compiling this file with -mrelocatable-lib.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/threads.h>
-#include <linux/spinlock.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-
-#include <asm/sections.h>
-#include <asm/prom.h>
-#include <asm/page.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/bootx.h>
-#include <asm/system.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/bootinfo.h>
-#include <asm/btext.h>
-#include <asm/pci-bridge.h>
-#include <asm/open_pic.h>
-#include <asm/cacheflush.h>
-
-#ifdef CONFIG_LOGO_LINUX_CLUT224
-#include <linux/linux_logo.h>
-extern const struct linux_logo logo_linux_clut224;
-#endif
-
-/*
- * Properties whose value is longer than this get excluded from our
- * copy of the device tree. This way we don't waste space storing
- * things like "driver,AAPL,MacOS,PowerPC" properties. But this value
- * does need to be big enough to ensure that we don't lose things
- * like the interrupt-map property on a PCI-PCI bridge.
- */
-#define MAX_PROPERTY_LENGTH 4096
-
-#ifndef FB_MAX /* avoid pulling in all of the fb stuff */
-#define FB_MAX 8
-#endif
-
-#define ALIGNUL(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
-
-typedef u32 prom_arg_t;
-
-struct prom_args {
- const char *service;
- int nargs;
- int nret;
- prom_arg_t args[10];
-};
-
-struct pci_address {
- unsigned a_hi;
- unsigned a_mid;
- unsigned a_lo;
-};
-
-struct pci_reg_property {
- struct pci_address addr;
- unsigned size_hi;
- unsigned size_lo;
-};
-
-struct pci_range {
- struct pci_address addr;
- unsigned phys;
- unsigned size_hi;
- unsigned size_lo;
-};
-
-struct isa_reg_property {
- unsigned space;
- unsigned address;
- unsigned size;
-};
-
-struct pci_intr_map {
- struct pci_address addr;
- unsigned dunno;
- phandle int_ctrler;
- unsigned intr;
-};
-
-static void prom_exit(void);
-static int call_prom(const char *service, int nargs, int nret, ...);
-static int call_prom_ret(const char *service, int nargs, int nret,
- prom_arg_t *rets, ...);
-static void prom_print_hex(unsigned int v);
-static int prom_set_color(ihandle ih, int i, int r, int g, int b);
-static int prom_next_node(phandle *nodep);
-static unsigned long check_display(unsigned long mem);
-static void setup_disp_fake_bi(ihandle dp);
-static unsigned long copy_device_tree(unsigned long mem_start,
- unsigned long mem_end);
-static unsigned long inspect_node(phandle node, struct device_node *dad,
- unsigned long mem_start, unsigned long mem_end,
- struct device_node ***allnextpp);
-static void prom_hold_cpus(unsigned long mem);
-static void prom_instantiate_rtas(void);
-static void * early_get_property(unsigned long base, unsigned long node,
- char *prop);
-
-prom_entry prom __initdata;
-ihandle prom_chosen __initdata;
-ihandle prom_stdout __initdata;
-
-static char *prom_display_paths[FB_MAX] __initdata;
-static phandle prom_display_nodes[FB_MAX] __initdata;
-static unsigned int prom_num_displays __initdata;
-static ihandle prom_disp_node __initdata;
-char *of_stdout_device __initdata;
-
-unsigned int rtas_data; /* physical pointer */
-unsigned int rtas_entry; /* physical pointer */
-unsigned int rtas_size;
-unsigned int old_rtas;
-
-boot_infos_t *boot_infos;
-char *bootpath;
-char *bootdevice;
-struct device_node *allnodes;
-
-extern char *klimit;
-
-static void __init
-prom_exit(void)
-{
- struct prom_args args;
-
- args.service = "exit";
- args.nargs = 0;
- args.nret = 0;
- prom(&args);
- for (;;) /* should never get here */
- ;
-}
-
-static int __init
-call_prom(const char *service, int nargs, int nret, ...)
-{
- va_list list;
- int i;
- struct prom_args prom_args;
-
- prom_args.service = service;
- prom_args.nargs = nargs;
- prom_args.nret = nret;
- va_start(list, nret);
- for (i = 0; i < nargs; ++i)
- prom_args.args[i] = va_arg(list, prom_arg_t);
- va_end(list);
- for (i = 0; i < nret; ++i)
- prom_args.args[i + nargs] = 0;
- prom(&prom_args);
- return prom_args.args[nargs];
-}
-
-static int __init
-call_prom_ret(const char *service, int nargs, int nret, prom_arg_t *rets, ...)
-{
- va_list list;
- int i;
- struct prom_args prom_args;
-
- prom_args.service = service;
- prom_args.nargs = nargs;
- prom_args.nret = nret;
- va_start(list, rets);
- for (i = 0; i < nargs; ++i)
- prom_args.args[i] = va_arg(list, int);
- va_end(list);
- for (i = 0; i < nret; ++i)
- prom_args.args[i + nargs] = 0;
- prom(&prom_args);
- for (i = 1; i < nret; ++i)
- rets[i-1] = prom_args.args[nargs + i];
- return prom_args.args[nargs];
-}
-
-void __init
-prom_print(const char *msg)
-{
- const char *p, *q;
-
- if (prom_stdout == 0)
- return;
-
- for (p = msg; *p != 0; p = q) {
- for (q = p; *q != 0 && *q != '\n'; ++q)
- ;
- if (q > p)
- call_prom("write", 3, 1, prom_stdout, p, q - p);
- if (*q != 0) {
- ++q;
- call_prom("write", 3, 1, prom_stdout, "\r\n", 2);
- }
- }
-}
-
-static void __init
-prom_print_hex(unsigned int v)
-{
- char buf[16];
- int i, c;
-
- for (i = 0; i < 8; ++i) {
- c = (v >> ((7-i)*4)) & 0xf;
- c += (c >= 10)? ('a' - 10): '0';
- buf[i] = c;
- }
- buf[i] = ' ';
- buf[i+1] = 0;
- prom_print(buf);
-}
-
-static int __init
-prom_set_color(ihandle ih, int i, int r, int g, int b)
-{
- return call_prom("call-method", 6, 1, "color!", ih, i, b, g, r);
-}
-
-static int __init
-prom_next_node(phandle *nodep)
-{
- phandle node;
-
- if ((node = *nodep) != 0
- && (*nodep = call_prom("child", 1, 1, node)) != 0)
- return 1;
- if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
- return 1;
- for (;;) {
- if ((node = call_prom("parent", 1, 1, node)) == 0)
- return 0;
- if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
- return 1;
- }
-}
-
-#ifdef CONFIG_POWER4
-/*
- * Set up a hash table with a set of entries in it to map the
- * first 64MB of RAM. This is used on 64-bit machines since
- * some of them don't have BATs.
- */
-
-static inline void make_pte(unsigned long htab, unsigned int hsize,
- unsigned int va, unsigned int pa, int mode)
-{
- unsigned int *pteg;
- unsigned int hash, i, vsid;
-
- vsid = ((va >> 28) * 0x111) << 12;
- hash = ((va ^ vsid) >> 5) & 0x7fff80;
- pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
- for (i = 0; i < 8; ++i, pteg += 4) {
- if ((pteg[1] & 1) == 0) {
- pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
- pteg[3] = pa | mode;
- break;
- }
- }
-}
-
-extern unsigned long _SDR1;
-extern PTE *Hash;
-extern unsigned long Hash_size;
-
-static void __init
-prom_alloc_htab(void)
-{
- unsigned int hsize;
- unsigned long htab;
- unsigned int addr;
-
- /*
- * Because of OF bugs we can't use the "claim" client
- * interface to allocate memory for the hash table.
- * This code is only used on 64-bit PPCs, and the only
- * 64-bit PPCs at the moment are RS/6000s, and their
- * OF is based at 0xc00000 (the 12M point), so we just
- * arbitrarily use the 0x800000 - 0xc00000 region for the
- * hash table.
- * -- paulus.
- */
- hsize = 4 << 20; /* POWER4 has no BATs */
- htab = (8 << 20);
- call_prom("claim", 3, 1, htab, hsize, 0);
- Hash = (void *)(htab + KERNELBASE);
- Hash_size = hsize;
- _SDR1 = htab + __ilog2(hsize) - 18;
-
- /*
- * Put in PTEs for the first 64MB of RAM
- */
- memset((void *)htab, 0, hsize);
- for (addr = 0; addr < 0x4000000; addr += 0x1000)
- make_pte(htab, hsize, addr + KERNELBASE, addr,
- _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX);
-#if 0 /* DEBUG stuff mapping the SCC */
- make_pte(htab, hsize, 0x80013000, 0x80013000,
- _PAGE_ACCESSED | _PAGE_NO_CACHE | _PAGE_GUARDED | PP_RWXX);
-#endif
-}
-#endif /* CONFIG_POWER4 */
-
-
-/*
- * If we have a display that we don't know how to drive,
- * we will want to try to execute OF's open method for it
- * later. However, OF will probably fall over if we do that
- * we've taken over the MMU.
- * So we check whether we will need to open the display,
- * and if so, open it now.
- */
-static unsigned long __init
-check_display(unsigned long mem)
-{
- phandle node;
- ihandle ih;
- int i, j;
- char type[16], *path;
- static unsigned char default_colors[] = {
- 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xaa,
- 0x00, 0xaa, 0x00,
- 0x00, 0xaa, 0xaa,
- 0xaa, 0x00, 0x00,
- 0xaa, 0x00, 0xaa,
- 0xaa, 0xaa, 0x00,
- 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55,
- 0x55, 0x55, 0xff,
- 0x55, 0xff, 0x55,
- 0x55, 0xff, 0xff,
- 0xff, 0x55, 0x55,
- 0xff, 0x55, 0xff,
- 0xff, 0xff, 0x55,
- 0xff, 0xff, 0xff
- };
- const unsigned char *clut;
-
- prom_disp_node = 0;
-
- for (node = 0; prom_next_node(&node); ) {
- type[0] = 0;
- call_prom("getprop", 4, 1, node, "device_type",
- type, sizeof(type));
- if (strcmp(type, "display") != 0)
- continue;
- /* It seems OF doesn't null-terminate the path :-( */
- path = (char *) mem;
- memset(path, 0, 256);
- if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
- continue;
-
- /*
- * If this display is the device that OF is using for stdout,
- * move it to the front of the list.
- */
- mem += strlen(path) + 1;
- i = prom_num_displays++;
- if (of_stdout_device != 0 && i > 0
- && strcmp(of_stdout_device, path) == 0) {
- for (; i > 0; --i) {
- prom_display_paths[i]
- = prom_display_paths[i-1];
- prom_display_nodes[i]
- = prom_display_nodes[i-1];
- }
- }
- prom_display_paths[i] = path;
- prom_display_nodes[i] = node;
- if (i == 0)
- prom_disp_node = node;
- if (prom_num_displays >= FB_MAX)
- break;
- }
-
- for (j=0; j<prom_num_displays; j++) {
- path = prom_display_paths[j];
- node = prom_display_nodes[j];
- prom_print("opening display ");
- prom_print(path);
- ih = call_prom("open", 1, 1, path);
- if (ih == 0 || ih == (ihandle) -1) {
- prom_print("... failed\n");
- for (i=j+1; i<prom_num_displays; i++) {
- prom_display_paths[i-1] = prom_display_paths[i];
- prom_display_nodes[i-1] = prom_display_nodes[i];
- }
- if (--prom_num_displays > 0) {
- prom_disp_node = prom_display_nodes[j];
- j--;
- } else
- prom_disp_node = 0;
- continue;
- } else {
- prom_print("... ok\n");
- call_prom("setprop", 4, 1, node, "linux,opened", 0, 0);
-
- /*
- * Setup a usable color table when the appropriate
- * method is available.
- * Should update this to use set-colors.
- */
- clut = default_colors;
- for (i = 0; i < 32; i++, clut += 3)
- if (prom_set_color(ih, i, clut[0], clut[1],
- clut[2]) != 0)
- break;
-
-#ifdef CONFIG_LOGO_LINUX_CLUT224
- clut = PTRRELOC(logo_linux_clut224.clut);
- for (i = 0; i < logo_linux_clut224.clutsize;
- i++, clut += 3)
- if (prom_set_color(ih, i + 32, clut[0],
- clut[1], clut[2]) != 0)
- break;
-#endif /* CONFIG_LOGO_LINUX_CLUT224 */
- }
- }
-
- if (prom_stdout) {
- phandle p;
- p = call_prom("instance-to-package", 1, 1, prom_stdout);
- if (p && p != -1) {
- type[0] = 0;
- call_prom("getprop", 4, 1, p, "device_type",
- type, sizeof(type));
- if (strcmp(type, "display") == 0)
- call_prom("setprop", 4, 1, p, "linux,boot-display",
- 0, 0);
- }
- }
-
- return ALIGNUL(mem);
-}
-
-/* This function will enable the early boot text when doing OF booting. This
- * way, xmon output should work too
- */
-static void __init
-setup_disp_fake_bi(ihandle dp)
-{
-#ifdef CONFIG_BOOTX_TEXT
- int width = 640, height = 480, depth = 8, pitch;
- unsigned address;
- struct pci_reg_property addrs[8];
- int i, naddrs;
- char name[32];
- char *getprop = "getprop";
-
- prom_print("Initializing fake screen: ");
-
- memset(name, 0, sizeof(name));
- call_prom(getprop, 4, 1, dp, "name", name, sizeof(name));
- name[sizeof(name)-1] = 0;
- prom_print(name);
- prom_print("\n");
- call_prom(getprop, 4, 1, dp, "width", &width, sizeof(width));
- call_prom(getprop, 4, 1, dp, "height", &height, sizeof(height));
- call_prom(getprop, 4, 1, dp, "depth", &depth, sizeof(depth));
- pitch = width * ((depth + 7) / 8);
- call_prom(getprop, 4, 1, dp, "linebytes",
- &pitch, sizeof(pitch));
- if (pitch == 1)
- pitch = 0x1000; /* for strange IBM display */
- address = 0;
- call_prom(getprop, 4, 1, dp, "address",
- &address, sizeof(address));
- if (address == 0) {
- /* look for an assigned address with a size of >= 1MB */
- naddrs = call_prom(getprop, 4, 1, dp, "assigned-addresses",
- addrs, sizeof(addrs));
- naddrs /= sizeof(struct pci_reg_property);
- for (i = 0; i < naddrs; ++i) {
- if (addrs[i].size_lo >= (1 << 20)) {
- address = addrs[i].addr.a_lo;
- /* use the BE aperture if possible */
- if (addrs[i].size_lo >= (16 << 20))
- address += (8 << 20);
- break;
- }
- }
- if (address == 0) {
- prom_print("Failed to get address\n");
- return;
- }
- }
- /* kludge for valkyrie */
- if (strcmp(name, "valkyrie") == 0)
- address += 0x1000;
-
-#ifdef CONFIG_POWER4
-#if CONFIG_TASK_SIZE > 0x80000000
-#error CONFIG_TASK_SIZE cannot be above 0x80000000 with BOOTX_TEXT on G5
-#endif
- {
- extern boot_infos_t disp_bi;
- unsigned long va, pa, i, offset;
- va = 0x90000000;
- pa = address & 0xfffff000ul;
- offset = address & 0x00000fff;
-
- for (i=0; i<0x4000; i++) {
- make_pte((unsigned long)Hash - KERNELBASE, Hash_size, va, pa,
- _PAGE_ACCESSED | _PAGE_NO_CACHE |
- _PAGE_GUARDED | PP_RWXX);
- va += 0x1000;
- pa += 0x1000;
- }
- btext_setup_display(width, height, depth, pitch, 0x90000000 | offset);
- disp_bi.dispDeviceBase = (u8 *)address;
- }
-#else /* CONFIG_POWER4 */
- btext_setup_display(width, height, depth, pitch, address);
- btext_prepare_BAT();
-#endif /* CONFIG_POWER4 */
-#endif /* CONFIG_BOOTX_TEXT */
-}
-
-/*
- * Make a copy of the device tree from the PROM.
- */
-static unsigned long __init
-copy_device_tree(unsigned long mem_start, unsigned long mem_end)
-{
- phandle root;
- unsigned long new_start;
- struct device_node **allnextp;
-
- root = call_prom("peer", 1, 1, (phandle)0);
- if (root == (phandle)0) {
- prom_print("couldn't get device tree root\n");
- prom_exit();
- }
- allnextp = &allnodes;
- mem_start = ALIGNUL(mem_start);
- new_start = inspect_node(root, NULL, mem_start, mem_end, &allnextp);
- *allnextp = NULL;
- return new_start;
-}
-
-static unsigned long __init
-inspect_node(phandle node, struct device_node *dad,
- unsigned long mem_start, unsigned long mem_end,
- struct device_node ***allnextpp)
-{
- int l;
- phandle child;
- struct device_node *np;
- struct property *pp, **prev_propp;
- char *prev_name, *namep;
- unsigned char *valp;
-
- np = (struct device_node *) mem_start;
- mem_start += sizeof(struct device_node);
- memset(np, 0, sizeof(*np));
- np->node = node;
- **allnextpp = PTRUNRELOC(np);
- *allnextpp = &np->allnext;
- if (dad != 0) {
- np->parent = PTRUNRELOC(dad);
- /* we temporarily use the `next' field as `last_child'. */
- if (dad->next == 0)
- dad->child = PTRUNRELOC(np);
- else
- dad->next->sibling = PTRUNRELOC(np);
- dad->next = np;
- }
-
- /* get and store all properties */
- prev_propp = &np->properties;
- prev_name = "";
- for (;;) {
- pp = (struct property *) mem_start;
- namep = (char *) (pp + 1);
- pp->name = PTRUNRELOC(namep);
- if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0)
- break;
- mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
- prev_name = namep;
- valp = (unsigned char *) mem_start;
- pp->value = PTRUNRELOC(valp);
- pp->length = call_prom("getprop", 4, 1, node, namep,
- valp, mem_end - mem_start);
- if (pp->length < 0)
- continue;
-#ifdef MAX_PROPERTY_LENGTH
- if (pp->length > MAX_PROPERTY_LENGTH)
- continue; /* ignore this property */
-#endif
- mem_start = ALIGNUL(mem_start + pp->length);
- *prev_propp = PTRUNRELOC(pp);
- prev_propp = &pp->next;
- }
- if (np->node != 0) {
- /* Add a "linux,phandle" property" */
- pp = (struct property *) mem_start;
- *prev_propp = PTRUNRELOC(pp);
- prev_propp = &pp->next;
- namep = (char *) (pp + 1);
- pp->name = PTRUNRELOC(namep);
- strcpy(namep, "linux,phandle");
- mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
- pp->value = (unsigned char *) PTRUNRELOC(&np->node);
- pp->length = sizeof(np->node);
- }
- *prev_propp = NULL;
-
- /* get the node's full name */
- l = call_prom("package-to-path", 3, 1, node,
- mem_start, mem_end - mem_start);
- if (l >= 0) {
- char *p, *ep;
-
- np->full_name = PTRUNRELOC((char *) mem_start);
- *(char *)(mem_start + l) = 0;
- /* Fixup an Apple bug where they have bogus \0 chars in the
- * middle of the path in some properties
- */
- for (p = (char *)mem_start, ep = p + l; p < ep; p++)
- if ((*p) == '\0') {
- memmove(p, p+1, ep - p);
- ep--;
- }
- mem_start = ALIGNUL(mem_start + l + 1);
- }
-
- /* do all our children */
- child = call_prom("child", 1, 1, node);
- while (child != 0) {
- mem_start = inspect_node(child, np, mem_start, mem_end,
- allnextpp);
- child = call_prom("peer", 1, 1, child);
- }
-
- return mem_start;
-}
-
-unsigned long smp_chrp_cpu_nr __initdata = 0;
-
-/*
- * With CHRP SMP we need to use the OF to start the other
- * processors so we can't wait until smp_boot_cpus (the OF is
- * trashed by then) so we have to put the processors into
- * a holding pattern controlled by the kernel (not OF) before
- * we destroy the OF.
- *
- * This uses a chunk of high memory, puts some holding pattern
- * code there and sends the other processors off to there until
- * smp_boot_cpus tells them to do something. We do that by using
- * physical address 0x0. The holding pattern checks that address
- * until its cpu # is there, when it is that cpu jumps to
- * __secondary_start(). smp_boot_cpus() takes care of setting those
- * values.
- *
- * We also use physical address 0x4 here to tell when a cpu
- * is in its holding pattern code.
- *
- * -- Cort
- *
- * Note that we have to do this if we have more than one CPU,
- * even if this is a UP kernel. Otherwise when we trash OF
- * the other CPUs will start executing some random instructions
- * and crash the system. -- paulus
- */
-static void __init
-prom_hold_cpus(unsigned long mem)
-{
- extern void __secondary_hold(void);
- unsigned long i;
- int cpu;
- phandle node;
- char type[16], *path;
- unsigned int reg;
-
- /*
- * XXX: hack to make sure we're chrp, assume that if we're
- * chrp we have a device_type property -- Cort
- */
- node = call_prom("finddevice", 1, 1, "/");
- if (call_prom("getprop", 4, 1, node,
- "device_type", type, sizeof(type)) <= 0)
- return;
-
- /* copy the holding pattern code to someplace safe (0) */
- /* the holding pattern is now within the first 0x100
- bytes of the kernel image -- paulus */
- memcpy((void *)0, _stext, 0x100);
- flush_icache_range(0, 0x100);
-
- /* look for cpus */
- *(unsigned long *)(0x0) = 0;
- asm volatile("dcbf 0,%0": : "r" (0) : "memory");
- for (node = 0; prom_next_node(&node); ) {
- type[0] = 0;
- call_prom("getprop", 4, 1, node, "device_type",
- type, sizeof(type));
- if (strcmp(type, "cpu") != 0)
- continue;
- path = (char *) mem;
- memset(path, 0, 256);
- if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
- continue;
- reg = -1;
- call_prom("getprop", 4, 1, node, "reg", &reg, sizeof(reg));
- cpu = smp_chrp_cpu_nr++;
-#ifdef CONFIG_SMP
- smp_hw_index[cpu] = reg;
-#endif /* CONFIG_SMP */
- /* XXX: hack - don't start cpu 0, this cpu -- Cort */
- if (cpu == 0)
- continue;
- prom_print("starting cpu ");
- prom_print(path);
- *(ulong *)(0x4) = 0;
- call_prom("start-cpu", 3, 0, node,
- (char *)__secondary_hold - _stext, cpu);
- prom_print("...");
- for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ )
- ;
- if (*(ulong *)(0x4) == cpu)
- prom_print("ok\n");
- else {
- prom_print("failed: ");
- prom_print_hex(*(ulong *)0x4);
- prom_print("\n");
- }
- }
-}
-
-static void __init
-prom_instantiate_rtas(void)
-{
- ihandle prom_rtas;
- prom_arg_t result;
-
- prom_rtas = call_prom("finddevice", 1, 1, "/rtas");
- if (prom_rtas == -1)
- return;
-
- rtas_size = 0;
- call_prom("getprop", 4, 1, prom_rtas,
- "rtas-size", &rtas_size, sizeof(rtas_size));
- prom_print("instantiating rtas");
- if (rtas_size == 0) {
- rtas_data = 0;
- } else {
- /*
- * Ask OF for some space for RTAS.
- * Actually OF has bugs so we just arbitrarily
- * use memory at the 6MB point.
- */
- rtas_data = 6 << 20;
- prom_print(" at ");
- prom_print_hex(rtas_data);
- }
-
- prom_rtas = call_prom("open", 1, 1, "/rtas");
- prom_print("...");
- rtas_entry = 0;
- if (call_prom_ret("call-method", 3, 2, &result,
- "instantiate-rtas", prom_rtas, rtas_data) == 0)
- rtas_entry = result;
- if ((rtas_entry == -1) || (rtas_entry == 0))
- prom_print(" failed\n");
- else
- prom_print(" done\n");
-}
-
-/*
- * We enter here early on, when the Open Firmware prom is still
- * handling exceptions and the MMU hash table for us.
- */
-unsigned long __init
-prom_init(int r3, int r4, prom_entry pp)
-{
- unsigned long mem;
- ihandle prom_mmu;
- unsigned long offset = reloc_offset();
- int i, l;
- char *p, *d;
- unsigned long phys;
- prom_arg_t result[3];
- char model[32];
- phandle node;
- int rc;
-
- /* Default */
- phys = (unsigned long) &_stext;
-
- /* First get a handle for the stdout device */
- prom = pp;
- prom_chosen = call_prom("finddevice", 1, 1, "/chosen");
- if (prom_chosen == -1)
- prom_exit();
- if (call_prom("getprop", 4, 1, prom_chosen, "stdout",
- &prom_stdout, sizeof(prom_stdout)) <= 0)
- prom_exit();
-
- /* Get the full OF pathname of the stdout device */
- mem = (unsigned long) klimit + offset;
- p = (char *) mem;
- memset(p, 0, 256);
- call_prom("instance-to-path", 3, 1, prom_stdout, p, 255);
- of_stdout_device = p;
- mem += strlen(p) + 1;
-
- /* Get the boot device and translate it to a full OF pathname. */
- p = (char *) mem;
- l = call_prom("getprop", 4, 1, prom_chosen, "bootpath", p, 1<<20);
- if (l > 0) {
- p[l] = 0; /* should already be null-terminated */
- bootpath = PTRUNRELOC(p);
- mem += l + 1;
- d = (char *) mem;
- *d = 0;
- call_prom("canon", 3, 1, p, d, 1<<20);
- bootdevice = PTRUNRELOC(d);
- mem = ALIGNUL(mem + strlen(d) + 1);
- }
-
- prom_instantiate_rtas();
-
-#ifdef CONFIG_POWER4
- /*
- * Find out how much memory we have and allocate a
- * suitably-sized hash table.
- */
- prom_alloc_htab();
-#endif
- mem = check_display(mem);
-
- prom_print("copying OF device tree...");
- mem = copy_device_tree(mem, mem + (1<<20));
- prom_print("done\n");
-
- prom_hold_cpus(mem);
-
- klimit = (char *) (mem - offset);
-
- node = call_prom("finddevice", 1, 1, "/");
- rc = call_prom("getprop", 4, 1, node, "model", model, sizeof(model));
- if (rc > 0 && !strncmp (model, "Pegasos", 7)
- && strncmp (model, "Pegasos2", 8)) {
- /* Pegasos 1 has a broken translate method in the OF,
- * and furthermore the BATs are mapped 1:1 so the phys
- * address calculated above is correct, so let's use
- * it directly.
- */
- } else if (offset == 0) {
- /* If we are already running at 0xc0000000, we assume we were
- * loaded by an OF bootloader which did set a BAT for us.
- * This breaks OF translate so we force phys to be 0.
- */
- prom_print("(already at 0xc0000000) phys=0\n");
- phys = 0;
- } else if (call_prom("getprop", 4, 1, prom_chosen, "mmu",
- &prom_mmu, sizeof(prom_mmu)) <= 0) {
- prom_print(" no MMU found\n");
- } else if (call_prom_ret("call-method", 4, 4, result, "translate",
- prom_mmu, &_stext, 1) != 0) {
- prom_print(" (translate failed)\n");
- } else {
- /* We assume the phys. address size is 3 cells */
- phys = result[2];
- }
-
- if (prom_disp_node != 0)
- setup_disp_fake_bi(prom_disp_node);
-
- /* Use quiesce call to get OF to shut down any devices it's using */
- prom_print("Calling quiesce ...\n");
- call_prom("quiesce", 0, 0);
-
- /* Relocate various pointers which will be used once the
- kernel is running at the address it was linked at. */
- for (i = 0; i < prom_num_displays; ++i)
- prom_display_paths[i] = PTRUNRELOC(prom_display_paths[i]);
-
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
- /* Relocate the of stdout for console autodetection */
- of_stdout_device = PTRUNRELOC(of_stdout_device);
-#endif
-
- prom_print("returning 0x");
- prom_print_hex(phys);
- prom_print("from prom_init\n");
- prom_stdout = 0;
-
- return phys;
-}
-
-/*
- * early_get_property is used to access the device tree image prepared
- * by BootX very early on, before the pointers in it have been relocated.
- */
-static void * __init
-early_get_property(unsigned long base, unsigned long node, char *prop)
-{
- struct device_node *np = (struct device_node *)(base + node);
- struct property *pp;
-
- for (pp = np->properties; pp != 0; pp = pp->next) {
- pp = (struct property *) (base + (unsigned long)pp);
- if (strcmp((char *)((unsigned long)pp->name + base),
- prop) == 0) {
- return (void *)((unsigned long)pp->value + base);
- }
- }
- return NULL;
-}
-
-/* Is boot-info compatible ? */
-#define BOOT_INFO_IS_COMPATIBLE(bi) ((bi)->compatible_version <= BOOT_INFO_VERSION)
-#define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2)
-#define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4)
-
-void __init
-bootx_init(unsigned long r4, unsigned long phys)
-{
- boot_infos_t *bi = (boot_infos_t *) r4;
- unsigned long space;
- unsigned long ptr, x;
- char *model;
-
- boot_infos = PTRUNRELOC(bi);
- if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
- bi->logicalDisplayBase = NULL;
-
-#ifdef CONFIG_BOOTX_TEXT
- btext_init(bi);
-
- /*
- * Test if boot-info is compatible. Done only in config
- * CONFIG_BOOTX_TEXT since there is nothing much we can do
- * with an incompatible version, except display a message
- * and eventually hang the processor...
- *
- * I'll try to keep enough of boot-info compatible in the
- * future to always allow display of this message;
- */
- if (!BOOT_INFO_IS_COMPATIBLE(bi)) {
- btext_drawstring(" !!! WARNING - Incompatible version of BootX !!!\n\n\n");
- btext_flushscreen();
- }
-#endif /* CONFIG_BOOTX_TEXT */
-
- /* New BootX enters kernel with MMU off, i/os are not allowed
- here. This hack will have been done by the boostrap anyway.
- */
- if (bi->version < 4) {
- /*
- * XXX If this is an iMac, turn off the USB controller.
- */
- model = (char *) early_get_property
- (r4 + bi->deviceTreeOffset, 4, "model");
- if (model
- && (strcmp(model, "iMac,1") == 0
- || strcmp(model, "PowerMac1,1") == 0)) {
- out_le32((unsigned *)0x80880008, 1); /* XXX */
- }
- }
-
- /* Move klimit to enclose device tree, args, ramdisk, etc... */
- if (bi->version < 5) {
- space = bi->deviceTreeOffset + bi->deviceTreeSize;
- if (bi->ramDisk)
- space = bi->ramDisk + bi->ramDiskSize;
- } else
- space = bi->totalParamsSize;
- klimit = PTRUNRELOC((char *) bi + space);
-
- /* New BootX will have flushed all TLBs and enters kernel with
- MMU switched OFF, so this should not be useful anymore.
- */
- if (bi->version < 4) {
- /*
- * Touch each page to make sure the PTEs for them
- * are in the hash table - the aim is to try to avoid
- * getting DSI exceptions while copying the kernel image.
- */
- for (ptr = ((unsigned long) &_stext) & PAGE_MASK;
- ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
- x = *(volatile unsigned long *)ptr;
- }
-
-#ifdef CONFIG_BOOTX_TEXT
- /*
- * Note that after we call btext_prepare_BAT, we can't do
- * prom_draw*, flushscreen or clearscreen until we turn the MMU
- * on, since btext_prepare_BAT sets disp_bi.logicalDisplayBase
- * to a virtual address.
- */
- btext_prepare_BAT();
-#endif
-}
diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
index ff86b2d814c..cfc2d6ad464 100644
--- a/arch/ppc/xmon/start.c
+++ b/arch/ppc/xmon/start.c
@@ -58,7 +58,7 @@ static struct sysrq_key_op sysrq_xmon_op =
void
xmon_map_scc(void)
{
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PREP
volatile unsigned char *base;
#elif defined(CONFIG_GEMINI)
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 6c6b197898d..7bb16fb97d4 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -67,7 +67,6 @@ cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE)
endif
CFLAGS += -mbackchain -msoft-float $(cflags-y)
-CFLAGS += $(call cc-option,-finline-limit=10000)
CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare
AFLAGS += $(aflags-y)
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 54d35c13090..9a22434a580 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -652,7 +652,7 @@ appldata_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata appldata_nb = {
+static struct notifier_block appldata_nb = {
.notifier_call = appldata_cpu_notify,
};
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index f8d0cd540a0..f4dfc10026d 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,10 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Wed Feb 8 10:44:39 2006
+# Linux kernel version: 2.6.17-rc1
+# Mon Apr 3 14:34:15 2006
#
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_S390=y
@@ -30,8 +31,8 @@ CONFIG_AUDIT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
@@ -45,10 +46,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -60,7 +57,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -69,7 +65,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
-# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -91,17 +87,20 @@ CONFIG_DEFAULT_IOSCHED="deadline"
#
# Processor type and features
#
-# CONFIG_64BIT is not set
+CONFIG_64BIT=y
CONFIG_SMP=y
CONFIG_NR_CPUS=32
CONFIG_HOTPLUG_CPU=y
-CONFIG_MATHEMU=y
+CONFIG_DEFAULT_MIGRATION_COST=1000000
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_BINFMT_ELF32=y
#
# Code generation options
#
-CONFIG_MARCH_G5=y
-# CONFIG_MARCH_Z900 is not set
+# CONFIG_MARCH_G5 is not set
+CONFIG_MARCH_Z900=y
# CONFIG_MARCH_Z990 is not set
CONFIG_PACK_STACK=y
# CONFIG_SMALL_STACK is not set
@@ -143,7 +142,7 @@ CONFIG_VIRT_CPU_ACCOUNTING=y
# CONFIG_APPLDATA_BASE is not set
CONFIG_NO_IDLE_HZ=y
CONFIG_NO_IDLE_HZ_INIT=y
-# CONFIG_KEXEC is not set
+CONFIG_KEXEC=y
#
# Networking
@@ -173,6 +172,7 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -180,9 +180,11 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_NETFILTER is not set
@@ -276,6 +278,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_DEBUG_DRIVER is not set
#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
# SCSI device support
#
# CONFIG_RAID_ATTRS is not set
@@ -340,8 +347,7 @@ CONFIG_DASD_PROFILE=y
CONFIG_DASD_ECKD=y
CONFIG_DASD_FBA=y
CONFIG_DASD_DIAG=y
-CONFIG_DASD_EER=m
-# CONFIG_DASD_CMB is not set
+CONFIG_DASD_EER=y
# CONFIG_ATA_OVER_ETH is not set
#
@@ -354,6 +360,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID5_RESHAPE is not set
# CONFIG_MD_RAID6 is not set
CONFIG_MD_MULTIPATH=m
# CONFIG_MD_FAULTY is not set
@@ -404,6 +411,7 @@ CONFIG_S390_TAPE_BLOCK=y
# S/390 tape hardware support
#
CONFIG_S390_TAPE_34XX=m
+# CONFIG_S390_TAPE_3590 is not set
# CONFIG_VMLOGRDR is not set
# CONFIG_VMCP is not set
# CONFIG_MONREADER is not set
@@ -529,7 +537,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -619,14 +626,15 @@ CONFIG_LOG_BUF_SHIFT=17
# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_PREEMPT=y
CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 5291b5f8788..b4c815d8ef7 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -430,7 +430,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
- if (! on_sig_stack(sp))
+ if (! sas_ss_flags(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
}
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 199da68bd7b..4d53b273935 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1608,3 +1608,53 @@ compat_sys_ppoll_wrapper:
sys_unshare_wrapper:
llgfr %r2,%r2 # unsigned long
jg sys_unshare
+
+ .globl compat_sys_set_robust_list_wrapper
+compat_sys_set_robust_list_wrapper:
+ llgtr %r2,%r2 # struct compat_robust_list_head *
+ llgfr %r3,%r3 # size_t
+ jg compat_sys_set_robust_list
+
+ .globl compat_sys_get_robust_list_wrapper
+compat_sys_get_robust_list_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # compat_uptr_t_t *
+ llgtr %r4,%r4 # compat_size_t *
+ jg compat_sys_get_robust_list
+
+ .globl sys_splice_wrapper
+sys_splice_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # loff_t *
+ lgfr %r4,%r4 # int
+ llgtr %r5,%r5 # loff_t *
+ llgfr %r6,%r6 # size_t
+ llgf %r0,164(%r15) # unsigned int
+ stg %r0,160(%r15)
+ jg sys_splice
+
+ .globl sys_sync_file_range_wrapper
+sys_sync_file_range_wrapper:
+ lgfr %r2,%r2 # int
+ sllg %r3,%r3,32 # get high word of 64bit loff_t
+ or %r3,%r4 # get low word of 64bit loff_t
+ sllg %r4,%r5,32 # get high word of 64bit loff_t
+ or %r4,%r6 # get low word of 64bit loff_t
+ llgf %r5,164(%r15) # unsigned int
+ jg sys_sync_file_range
+
+ .globl sys_tee_wrapper
+sys_tee_wrapper:
+ lgfr %r2,%r2 # int
+ lgfr %r3,%r3 # int
+ llgfr %r4,%r4 # size_t
+ llgfr %r5,%r5 # unsigned int
+ jg sys_tee
+
+ .globl compat_sys_vmsplice_wrapper
+compat_sys_vmsplice_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # compat_iovec *
+ llgfr %r4,%r4 # unsigned int
+ llgfr %r5,%r5 # unsigned int
+ jg compat_sys_vmsplice
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 99182a415fe..4a0f5a1551e 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -76,17 +76,17 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
/*
* Need to know about CPUs going idle?
*/
-static struct notifier_block *idle_chain;
+static ATOMIC_NOTIFIER_HEAD(idle_chain);
int register_idle_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&idle_chain, nb);
+ return atomic_notifier_chain_register(&idle_chain, nb);
}
EXPORT_SYMBOL(register_idle_notifier);
int unregister_idle_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&idle_chain, nb);
+ return atomic_notifier_chain_unregister(&idle_chain, nb);
}
EXPORT_SYMBOL(unregister_idle_notifier);
@@ -95,7 +95,7 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code)
/* disable monitor call class 0 */
__ctl_clear_bit(8, 15);
- notifier_call_chain(&idle_chain, CPU_NOT_IDLE,
+ atomic_notifier_call_chain(&idle_chain, CPU_NOT_IDLE,
(void *)(long) smp_processor_id());
}
@@ -116,7 +116,8 @@ static void default_idle(void)
return;
}
- rc = notifier_call_chain(&idle_chain, CPU_IDLE, (void *)(long) cpu);
+ rc = atomic_notifier_call_chain(&idle_chain,
+ CPU_IDLE, (void *)(long) cpu);
if (rc != NOTIFY_OK && rc != NOTIFY_DONE)
BUG();
if (rc != NOTIFY_OK) {
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 37dfe33dab7..8f36504075e 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -734,7 +734,7 @@ asmlinkage void
syscall_trace(struct pt_regs *regs, int entryexit)
{
if (unlikely(current->audit_context) && entryexit)
- audit_syscall_exit(current, AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);
+ audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);
if (!test_thread_flag(TIF_SYSCALL_TRACE))
goto out;
@@ -761,8 +761,7 @@ syscall_trace(struct pt_regs *regs, int entryexit)
}
out:
if (unlikely(current->audit_context) && !entryexit)
- audit_syscall_entry(current,
- test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X,
+ audit_syscall_entry(test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X,
regs->gprs[2], regs->orig_gpr2, regs->gprs[3],
regs->gprs[4], regs->gprs[5]);
}
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index ae1927e48cf..d48cfc726b6 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -358,8 +358,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} else {
regs->gprs[14] = (unsigned long)
frame->retcode | PSW_ADDR_AMODE;
- err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
- (u16 __user *)(frame->retcode));
+ if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
+ (u16 __user *)(frame->retcode)))
+ goto give_sigsegv;
}
/* Set up backchain. */
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 2b8841f8553..343120c9223 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -801,7 +801,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
*/
print_cpu_info(&S390_lowcore.cpu_data);
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
lowcore_ptr[i] = (struct _lowcore *)
__get_free_pages(GFP_KERNEL|GFP_DMA,
sizeof(void*) == 8 ? 1 : 0);
@@ -831,7 +831,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
#endif
set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]);
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
if (cpu != smp_processor_id())
smp_create_idle(cpu);
}
@@ -868,7 +868,7 @@ static int __init topology_init(void)
int cpu;
int ret;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL);
if (ret)
printk(KERN_WARNING "topology_init: register_cpu %d "
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 2f56654da82..93be1d56c03 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -312,3 +312,9 @@ SYSCALL(sys_faccessat,sys_faccessat,sys_faccessat_wrapper) /* 300 */
SYSCALL(sys_pselect6,sys_pselect6,compat_sys_pselect6_wrapper)
SYSCALL(sys_ppoll,sys_ppoll,compat_sys_ppoll_wrapper)
SYSCALL(sys_unshare,sys_unshare,sys_unshare_wrapper)
+SYSCALL(sys_set_robust_list,sys_set_robust_list,compat_sys_set_robust_list_wrapper)
+SYSCALL(sys_get_robust_list,sys_get_robust_list,compat_sys_get_robust_list_wrapper)
+SYSCALL(sys_splice,sys_splice,sys_splice_wrapper)
+SYSCALL(sys_sync_file_range,sys_sync_file_range,sys_sync_file_range_wrapper)
+SYSCALL(sys_tee,sys_tee,sys_tee_wrapper)
+SYSCALL(sys_vmsplice,sys_vmsplice,compat_sys_vmsplice_wrapper)
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index fea043b69b9..2a6c6efb686 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -249,18 +249,19 @@ static inline void stop_hz_timer(void)
unsigned long flags;
unsigned long seq, next;
__u64 timer, todval;
+ int cpu = smp_processor_id();
if (sysctl_hz_timer != 0)
return;
- cpu_set(smp_processor_id(), nohz_cpu_mask);
+ cpu_set(cpu, nohz_cpu_mask);
/*
* Leave the clock comparator set up for the next timer
* tick if either rcu or a softirq is pending.
*/
- if (rcu_pending(smp_processor_id()) || local_softirq_pending()) {
- cpu_clear(smp_processor_id(), nohz_cpu_mask);
+ if (rcu_needs_cpu(cpu) || local_softirq_pending()) {
+ cpu_clear(cpu, nohz_cpu_mask);
return;
}
@@ -271,7 +272,7 @@ static inline void stop_hz_timer(void)
next = next_timer_interrupt();
do {
seq = read_seqbegin_irqsave(&xtime_lock, flags);
- timer = (__u64)(next - jiffies) + jiffies_64;
+ timer = ((__u64) next) - ((__u64) jiffies) + jiffies_64;
} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
todval = -1ULL;
/* Be careful about overflows. */
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 9289face302..9f34bb54c05 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -58,9 +58,11 @@ SECTIONS
. = ALIGN(4096);
.data.page_aligned : { *(.data.idt) }
- . = ALIGN(32);
+ . = ALIGN(256);
.data.cacheline_aligned : { *(.data.cacheline_aligned) }
+ . = ALIGN(256);
+ .data.read_mostly : { *(.data.read_mostly) }
_edata = .; /* End of data section */
. = ALIGN(8192); /* init_task */
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index a9566bcab68..9b11e3e2090 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -192,6 +192,7 @@ query_segment_type (struct dcss_segment *seg)
diag_cc = dcss_diag (DCSS_SEGEXT, qin, &dummy, &vmrc);
if (diag_cc > 1) {
+ PRINT_WARN ("segment_type: diag returned error %ld\n", vmrc);
rc = dcss_diag_translate_rc (vmrc);
goto out_free;
}
@@ -553,7 +554,7 @@ segment_save(char *name)
int endpfn = 0;
char cmd1[160];
char cmd2[80];
- int i;
+ int i, response;
if (!MACHINE_IS_VM)
return;
@@ -576,8 +577,20 @@ segment_save(char *name)
segtype_string[seg->range[i].start & 0xff]);
}
sprintf(cmd2, "SAVESEG %s", name);
- cpcmd(cmd1, NULL, 0, NULL);
- cpcmd(cmd2, NULL, 0, NULL);
+ response = 0;
+ cpcmd(cmd1, NULL, 0, &response);
+ if (response) {
+ PRINT_ERR("segment_save: DEFSEG failed with response code %i\n",
+ response);
+ goto out;
+ }
+ cpcmd(cmd2, NULL, 0, &response);
+ if (response) {
+ PRINT_ERR("segment_save: SAVESEG failed with response code %i\n",
+ response);
+ goto out;
+ }
+out:
spin_unlock(&dcss_lock);
}
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 58583f45947..2bcecf42257 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -527,6 +527,11 @@ config CPU_HAS_SR_RB
See <file:Documentation/sh/register-banks.txt> for further
information on SR.RB and register banking in the kernel in general.
+config NODES_SHIFT
+ int
+ default "1"
+ depends on NEED_MULTIPLE_NODES
+
endmenu
menu "Boot options"
diff --git a/arch/sh/boards/mpc1211/rtc.c b/arch/sh/boards/mpc1211/rtc.c
index 4d100f04807..a76c655dcee 100644
--- a/arch/sh/boards/mpc1211/rtc.c
+++ b/arch/sh/boards/mpc1211/rtc.c
@@ -9,36 +9,16 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/time.h>
+#include <linux/bcd.h>
#include <linux/mc146818rtc.h>
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
-/* arc/i386/kernel/time.c */
unsigned long get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- int i;
spin_lock(&rtc_lock);
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
+
+ do {
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
hour = CMOS_READ(RTC_HOURS);
@@ -46,18 +26,22 @@ unsigned long get_cmos_time(void)
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
} while (sec != CMOS_READ(RTC_SECONDS));
- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
+
+ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
+
spin_unlock(&rtc_lock);
- if ((year += 1900) < 1970)
+
+ year += 1900;
+ if (year < 1970)
year += 100;
+
return mktime(year, mon, day, hour, min, sec);
}
diff --git a/arch/sh/boards/sh03/rtc.c b/arch/sh/boards/sh03/rtc.c
index cbeca7037ba..d609863cfe5 100644
--- a/arch/sh/boards/sh03/rtc.c
+++ b/arch/sh/boards/sh03/rtc.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/time.h>
+#include <linux/bcd.h>
#include <asm/io.h>
#include <linux/rtc.h>
#include <linux/spinlock.h>
@@ -33,14 +34,6 @@
#define RTC_BUSY 1
#define RTC_STOP 2
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
extern void (*rtc_get_time)(struct timespec *);
extern int (*rtc_set_time)(const time_t);
extern spinlock_t rtc_lock;
@@ -48,13 +41,9 @@ extern spinlock_t rtc_lock;
unsigned long get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- int i;
spin_lock(&rtc_lock);
again:
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (!(ctrl_inb(RTC_CTL) & RTC_BUSY))
- break;
do {
sec = (ctrl_inb(RTC_SEC1) & 0xf) + (ctrl_inb(RTC_SEC10) & 0x7) * 10;
min = (ctrl_inb(RTC_MIN1) & 0xf) + (ctrl_inb(RTC_MIN10) & 0xf) * 10;
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index cf94e8ef17c..868e68b2888 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -30,7 +30,7 @@ static int x##_disabled __initdata = 0; \
static int __init x##_setup(char *opts) \
{ \
x##_disabled = 1; \
- return 0; \
+ return 1; \
} \
__setup("no" __stringify(x), x##_setup);
diff --git a/arch/sh/kernel/cpu/rtc.c b/arch/sh/kernel/cpu/rtc.c
index f8361f5e788..4304cf75cfa 100644
--- a/arch/sh/kernel/cpu/rtc.c
+++ b/arch/sh/kernel/cpu/rtc.c
@@ -9,18 +9,10 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/time.h>
-
+#include <linux/bcd.h>
#include <asm/io.h>
#include <asm/rtc.h>
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
void sh_rtc_gettimeofday(struct timespec *ts)
{
unsigned int sec128, sec, sec2, min, hr, wk, day, mon, yr, yr100, cf_bit;
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index c0e79843f58..bb229ef030f 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -20,6 +20,7 @@
#include <linux/root_dev.h>
#include <linux/utsname.h>
#include <linux/cpu.h>
+#include <linux/pfn.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/sections.h>
@@ -275,10 +276,6 @@ void __init setup_arch(char **cmdline_p)
sh_mv_setup(cmdline_p);
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
-
/*
* Find the highest page frame number we have available
*/
@@ -404,7 +401,7 @@ static int __init topology_init(void)
{
int cpu_id;
- for_each_cpu(cpu_id)
+ for_each_possible_cpu(cpu_id)
register_cpu(&cpu[cpu_id], cpu_id, NULL);
return 0;
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 1cf94a618be..d5d032533a8 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -37,7 +37,6 @@ EXPORT_SYMBOL(disable_irq_nosync);
EXPORT_SYMBOL(irq_desc);
EXPORT_SYMBOL(no_irq_type);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strnlen);
diff --git a/arch/sh64/kernel/setup.c b/arch/sh64/kernel/setup.c
index c7a7b816a30..d2711c9c9d1 100644
--- a/arch/sh64/kernel/setup.c
+++ b/arch/sh64/kernel/setup.c
@@ -48,6 +48,7 @@
#include <linux/root_dev.h>
#include <linux/cpu.h>
#include <linux/initrd.h>
+#include <linux/pfn.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/pgtable.h>
diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c
index de29c45f23a..6f3a1c94633 100644
--- a/arch/sh64/kernel/sh_ksyms.c
+++ b/arch/sh64/kernel/sh_ksyms.c
@@ -41,7 +41,6 @@ EXPORT_SYMBOL(kernel_thread);
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
#ifdef CONFIG_VT
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
index 0773c9f389f..6b8f4d22abc 100644
--- a/arch/sh64/kernel/time.c
+++ b/arch/sh64/kernel/time.c
@@ -30,6 +30,7 @@
#include <linux/profile.h>
#include <linux/smp.h>
#include <linux/module.h>
+#include <linux/bcd.h>
#include <asm/registers.h> /* required by inline __asm__ stmt. */
@@ -105,14 +106,6 @@
#define RCR1 rtc_base+0x38
#define RCR2 rtc_base+0x3c
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
#define TICK_SIZE (tick_nsec / 1000)
extern unsigned long wall_jiffies;
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 460f72e640e..f9ff2973484 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -274,6 +274,11 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp)
if (mmu_map_dma_area(dma_addrp, va, res->start, len_total) != 0)
goto err_noiommu;
+ /* Set the resource name, if known. */
+ if (sdev) {
+ res->name = sdev->prom_name;
+ }
+
return (void *)res->start;
err_noiommu:
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 787d5f1347e..598682f31eb 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -113,6 +113,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_SPARC_32:
+ case R_SPARC_UA32:
location[0] = v >> 24;
location[1] = v >> 16;
location[2] = v >> 8;
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 2be81211519..40b42c88e6a 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -69,6 +69,17 @@ void __init smp_store_cpu_info(int id)
"clock-frequency", 0);
cpu_data(id).prom_node = cpu_node;
cpu_data(id).mid = cpu_get_hwmid(cpu_node);
+
+ /* this is required to tune the scheduler correctly */
+ /* is it possible to have CPUs with different cache sizes? */
+ if (id == boot_cpu_id) {
+ int cache_line,cache_nlines;
+ cache_line = 0x20;
+ cache_line = prom_getintdefault(cpu_node, "ecache-line-size", cache_line);
+ cache_nlines = 0x8000;
+ cache_nlines = prom_getintdefault(cpu_node, "ecache-nlines", cache_nlines);
+ max_cache_size = cache_line * cache_nlines;
+ }
if (cpu_data(id).mid < 0)
panic("No MID found for CPU%d at node 0x%08d", id, cpu_node);
}
@@ -244,7 +255,7 @@ int setup_profiling_timer(unsigned int multiplier)
return -EINVAL;
spin_lock_irqsave(&prof_setup_lock, flags);
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
load_profile_irq(i, lvl14_resolution / multiplier);
prof_multiplier(i) = multiplier;
}
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 2c21d790763..4b376fae752 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -251,20 +251,9 @@ EXPORT_SYMBOL(__prom_getchild);
EXPORT_SYMBOL(__prom_getsibling);
/* sparc library symbols */
-EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(page_kernel);
/* Special internal versions of library functions. */
@@ -318,6 +307,3 @@ EXPORT_SYMBOL(do_BUG);
/* Sun Power Management Idle Handler */
EXPORT_SYMBOL(pm_idle);
-
-/* Binfmt_misc needs this */
-EXPORT_SYMBOL(sys_close);
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 768de64b371..2856551bddf 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -23,7 +23,7 @@ sys_call_table:
/*10*/ .long sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys_mknod
/*15*/ .long sys_chmod, sys_lchown16, sparc_brk, sys_nis_syscall, sys_lseek
/*20*/ .long sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
-/*25*/ .long sys_time, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause
+/*25*/ .long sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause
/*30*/ .long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice
/*35*/ .long sys_chown, sys_sync, sys_kill, sys_newstat, sys_sendfile
/*40*/ .long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_getuid
@@ -64,21 +64,22 @@ sys_call_table:
/*215*/ .long sys_ipc, sys_sigreturn, sys_clone, sys_ioprio_get, sys_adjtimex
/*220*/ .long sys_sigprocmask, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
/*225*/ .long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid16, sys_setfsgid16
-/*230*/ .long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_statfs64
+/*230*/ .long sys_select, sys_time, sys_splice, sys_stime, sys_statfs64
/* "We are the Knights of the Forest of Ni!!" */
/*235*/ .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
/*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
/*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
/*250*/ .long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
-/*255*/ .long sys_nis_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
+/*255*/ .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
/*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
/*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
+/*280*/ .long sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat
/*285*/ .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64
/*290*/ .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
+/*300*/ .long sys_set_robust_list, sys_get_robust_list
#ifdef CONFIG_SUNOS_EMUL
/* Now the SunOS syscall table. */
@@ -190,6 +191,6 @@ sunos_sys_table:
/*290*/ .long sunos_nosys, sunos_nosys, sunos_nosys
.long sunos_nosys, sunos_nosys, sunos_nosys
.long sunos_nosys, sunos_nosys, sunos_nosys
- .long sunos_nosys
+ .long sunos_nosys, sunos_nosys, sunos_nosys
#endif
diff --git a/arch/sparc/math-emu/Makefile b/arch/sparc/math-emu/Makefile
index f84a9a6162b..8136987977f 100644
--- a/arch/sparc/math-emu/Makefile
+++ b/arch/sparc/math-emu/Makefile
@@ -5,4 +5,4 @@
obj-y := math.o
EXTRA_AFLAGS := -ansi
-EXTRA_CFLAGS = -I. -I$(TOPDIR)/include/math-emu -w
+EXTRA_CFLAGS = -I. -Iinclude/math-emu -w
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index d1e2fc56648..43a66f5407f 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -187,13 +187,16 @@ config HUGETLB_PAGE_SIZE_512K
bool "512K"
config HUGETLB_PAGE_SIZE_64K
- depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB && !SPARC64_PAGE_SIZE_64K
+ depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB && !SPARC64_PAGE_SIZE_64KB
bool "64K"
endchoice
endmenu
+config ARCH_SELECT_MEMORY_MODEL
+ def_bool y
+
config ARCH_SPARSEMEM_ENABLE
def_bool y
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 900fb0b940d..f09a70b8aab 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.16
-# Sun Mar 26 14:58:11 2006
+# Linux kernel version: 2.6.17-rc3
+# Fri May 12 12:43:49 2006
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
@@ -114,6 +114,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HUGETLB_PAGE_SIZE_4MB=y
# CONFIG_HUGETLB_PAGE_SIZE_512K is not set
# CONFIG_HUGETLB_PAGE_SIZE_64K is not set
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
CONFIG_LARGE_ALLOCS=y
@@ -180,6 +181,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -203,6 +205,7 @@ CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
# CONFIG_NETFILTER is not set
@@ -308,7 +311,6 @@ CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_UB=m
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -429,7 +431,6 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLOGICPTI is not set
# CONFIG_SCSI_QLA_FC is not set
@@ -449,6 +450,7 @@ CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID5_RESHAPE is not set
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
# CONFIG_MD_FAULTY is not set
@@ -741,9 +743,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -826,6 +826,7 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_FIRMWARE_EDID is not set
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
@@ -837,7 +838,6 @@ CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
CONFIG_FB_RADEON=y
CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_RADEON_DEBUG is not set
@@ -923,6 +923,7 @@ CONFIG_SND_MTPAV=m
# PCI devices
#
# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
CONFIG_SND_ALI5451=m
# CONFIG_SND_ATIIXP is not set
# CONFIG_SND_ATIIXP_MODEM is not set
@@ -954,6 +955,7 @@ CONFIG_SND_ALI5451=m
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
# CONFIG_SND_RME32 is not set
# CONFIG_SND_RME96 is not set
# CONFIG_SND_RME9652 is not set
@@ -1040,9 +1042,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -1108,6 +1108,19 @@ CONFIG_USB_HIDDEV=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
@@ -1117,6 +1130,11 @@ CONFIG_USB_HIDDEV=y
#
#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
# Misc Linux/SPARC drivers
#
CONFIG_SUN_OPENPROMIO=m
@@ -1291,6 +1309,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUG_STACK_USAGE is not set
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 3eadac5e171..31c5892f5ac 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -10,6 +10,7 @@
#include <linux/config.h>
#include <linux/version.h>
#include <linux/errno.h>
+#include <linux/threads.h>
#include <asm/thread_info.h>
#include <asm/asi.h>
#include <asm/pstate.h>
@@ -493,6 +494,35 @@ tlb_fixup_done:
call prom_init
mov %l7, %o0 ! OpenPROM cif handler
+ /* Initialize current_thread_info()->cpu as early as possible.
+ * In order to do that accurately we have to patch up the get_cpuid()
+ * assembler sequences. And that, in turn, requires that we know
+ * if we are on a Starfire box or not. While we're here, patch up
+ * the sun4v sequences as well.
+ */
+ call check_if_starfire
+ nop
+ call per_cpu_patch
+ nop
+ call sun4v_patch
+ nop
+
+#ifdef CONFIG_SMP
+ call hard_smp_processor_id
+ nop
+ cmp %o0, NR_CPUS
+ blu,pt %xcc, 1f
+ nop
+ call boot_cpu_id_too_large
+ nop
+ /* Not reached... */
+
+1:
+#else
+ mov 0, %o0
+#endif
+ stb %o0, [%g6 + TI_CPU]
+
/* Off we go.... */
call start_kernel
nop
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index ffc7309e9f2..2e1c824c1cc 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -63,7 +63,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
flushi(p->addr);
}
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -71,7 +71,7 @@ static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->prev_kprobe.orig_tstate_pil = kcb->kprobe_orig_tstate_pil;
}
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -79,7 +79,7 @@ static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->kprobe_orig_tstate_pil = kcb->prev_kprobe.orig_tstate_pil;
}
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = p;
@@ -87,7 +87,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
kcb->kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
}
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
regs->tstate |= TSTATE_PIL;
@@ -273,7 +273,7 @@ static void __kprobes resume_execution(struct kprobe *p,
kcb->kprobe_orig_tstate_pil);
}
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -300,7 +300,7 @@ out:
return 1;
}
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
diff --git a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c
index 6c83e372f75..57987152769 100644
--- a/arch/sparc64/kernel/module.c
+++ b/arch/sparc64/kernel/module.c
@@ -143,6 +143,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
location[3] = v >> 0;
break;
+ case R_SPARC_DISP32:
+ v -= (Elf64_Addr) location;
+ *loc32 = v;
+ break;
+
case R_SPARC_WDISP30:
v -= (Elf64_Addr) location;
*loc32 = (*loc32 & ~0x3fffffff) |
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index dfccff29e18..f97ddeb105a 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -419,6 +419,7 @@ void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region
region->start = res->start - zero_res.start;
region->end = res->end - zero_res.start;
}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
struct pci_bus_region *region)
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
index 8efbc139769..82e5455134c 100644
--- a/arch/sparc64/kernel/pci_iommu.c
+++ b/arch/sparc64/kernel/pci_iommu.c
@@ -218,7 +218,7 @@ static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx)
* DMA for PCI device PDEV. Return non-NULL cpu-side address if
* successful and set *DMA_ADDRP to the PCI side dma address.
*/
-static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
+static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
@@ -232,7 +232,7 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
if (order >= 10)
return NULL;
- first_page = __get_free_pages(GFP_ATOMIC, order);
+ first_page = __get_free_pages(gfp, order);
if (first_page == 0UL)
return NULL;
memset((char *)first_page, 0, PAGE_SIZE << order);
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 9372d4f376d..0c089520297 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -154,7 +154,7 @@ static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, un
__clear_bit(i, arena->map);
}
-static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
+static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
@@ -169,7 +169,7 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
npages = size >> IO_PAGE_SHIFT;
- first_page = __get_free_pages(GFP_ATOMIC, order);
+ first_page = __get_free_pages(gfp, order);
if (unlikely(first_page == 0UL))
return NULL;
@@ -599,18 +599,128 @@ struct pci_iommu_ops pci_sun4v_iommu_ops = {
/* SUN4V PCI configuration space accessors. */
-static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
+struct pdev_entry {
+ struct pdev_entry *next;
+ u32 devhandle;
+ unsigned int bus;
+ unsigned int device;
+ unsigned int func;
+};
+
+#define PDEV_HTAB_SIZE 16
+#define PDEV_HTAB_MASK (PDEV_HTAB_SIZE - 1)
+static struct pdev_entry *pdev_htab[PDEV_HTAB_SIZE];
+
+static inline unsigned int pdev_hashfn(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
{
- if (bus == pbm->pci_first_busno) {
- if (device == 0 && func == 0)
- return 0;
- return 1;
+ unsigned int val;
+
+ val = (devhandle ^ (devhandle >> 4));
+ val ^= bus;
+ val ^= device;
+ val ^= func;
+
+ return val & PDEV_HTAB_MASK;
+}
+
+static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
+{
+ struct pdev_entry *p = kmalloc(sizeof(*p), GFP_KERNEL);
+ struct pdev_entry **slot;
+
+ if (!p)
+ return -ENOMEM;
+
+ slot = &pdev_htab[pdev_hashfn(devhandle, bus, device, func)];
+ p->next = *slot;
+ *slot = p;
+
+ p->devhandle = devhandle;
+ p->bus = bus;
+ p->device = device;
+ p->func = func;
+
+ return 0;
+}
+
+/* Recursively descend into the OBP device tree, rooted at toplevel_node,
+ * looking for a PCI device matching bus and devfn.
+ */
+static int obp_find(struct linux_prom_pci_registers *pregs, int toplevel_node, unsigned int bus, unsigned int devfn)
+{
+ toplevel_node = prom_getchild(toplevel_node);
+
+ while (toplevel_node != 0) {
+ int ret = obp_find(pregs, toplevel_node, bus, devfn);
+
+ if (ret != 0)
+ return ret;
+
+ ret = prom_getproperty(toplevel_node, "reg", (char *) pregs,
+ sizeof(*pregs) * PROMREG_MAX);
+ if (ret == 0 || ret == -1)
+ goto next_sibling;
+
+ if (((pregs[0].phys_hi >> 16) & 0xff) == bus &&
+ ((pregs[0].phys_hi >> 8) & 0xff) == devfn)
+ break;
+
+ next_sibling:
+ toplevel_node = prom_getsibling(toplevel_node);
+ }
+
+ return toplevel_node;
+}
+
+static int pdev_htab_populate(struct pci_pbm_info *pbm)
+{
+ struct linux_prom_pci_registers pr[PROMREG_MAX];
+ u32 devhandle = pbm->devhandle;
+ unsigned int bus;
+
+ for (bus = pbm->pci_first_busno; bus <= pbm->pci_last_busno; bus++) {
+ unsigned int devfn;
+
+ for (devfn = 0; devfn < 256; devfn++) {
+ unsigned int device = PCI_SLOT(devfn);
+ unsigned int func = PCI_FUNC(devfn);
+
+ if (obp_find(pr, pbm->prom_node, bus, devfn)) {
+ int err = pdev_htab_add(devhandle, bus,
+ device, func);
+ if (err)
+ return err;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static struct pdev_entry *pdev_find(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
+{
+ struct pdev_entry *p;
+
+ p = pdev_htab[pdev_hashfn(devhandle, bus, device, func)];
+ while (p) {
+ if (p->devhandle == devhandle &&
+ p->bus == bus &&
+ p->device == device &&
+ p->func == func)
+ break;
+
+ p = p->next;
}
+ return p;
+}
+
+static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
+{
if (bus < pbm->pci_first_busno ||
bus > pbm->pci_last_busno)
return 1;
- return 0;
+ return pdev_find(pbm->devhandle, bus, device, func) == NULL;
}
static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
@@ -1063,6 +1173,8 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
pci_sun4v_get_bus_range(pbm);
pci_sun4v_iommu_init(pbm);
+
+ pdev_htab_populate(pbm);
}
void sun4v_pci_init(int node, char *model_name)
@@ -1092,7 +1204,7 @@ void sun4v_pci_init(int node, char *model_name)
}
}
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
unsigned long page = get_zeroed_page(GFP_ATOMIC);
if (!page)
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index eb93e9c5284..d31975e6d6f 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -244,6 +244,13 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
}
switch(request) {
+ case PTRACE_PEEKUSR:
+ if (addr != 0)
+ pt_error_return(regs, EIO);
+ else
+ pt_succ_return(regs, 0);
+ goto out_tsk;
+
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp64;
@@ -602,6 +609,22 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
/* PTRACE_DUMPCORE unsupported... */
+ case PTRACE_GETEVENTMSG: {
+ int err;
+
+ if (test_thread_flag(TIF_32BIT))
+ err = put_user(child->ptrace_message,
+ (unsigned int __user *) data);
+ else
+ err = put_user(child->ptrace_message,
+ (unsigned long __user *) data);
+ if (err)
+ pt_error_return(regs, -err);
+ else
+ pt_succ_return(regs, 0);
+ break;
+ }
+
default: {
int err = ptrace_request(child, request, addr, data);
if (err)
@@ -630,7 +653,7 @@ asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
result = AUDITSC_FAILURE;
- audit_syscall_exit(current, result, regs->u_regs[UREG_I0]);
+ audit_syscall_exit(result, regs->u_regs[UREG_I0]);
}
if (!(current->ptrace & PT_PTRACED))
@@ -654,8 +677,7 @@ asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
out:
if (unlikely(current->audit_context) && !syscall_exit_p)
- audit_syscall_entry(current,
- (test_thread_flag(TIF_32BIT) ?
+ audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
AUDIT_ARCH_SPARC :
AUDIT_ARCH_SPARC64),
regs->u_regs[UREG_G1],
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 7d0e67c1ce5..9cf1c88cd77 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -220,7 +220,7 @@ char reboot_command[COMMAND_LINE_SIZE];
static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
-static void __init per_cpu_patch(void)
+void __init per_cpu_patch(void)
{
struct cpuid_patch_entry *p;
unsigned long ver;
@@ -280,7 +280,7 @@ static void __init per_cpu_patch(void)
}
}
-static void __init sun4v_patch(void)
+void __init sun4v_patch(void)
{
struct sun4v_1insn_patch_entry *p1;
struct sun4v_2insn_patch_entry *p2;
@@ -315,6 +315,15 @@ static void __init sun4v_patch(void)
}
}
+#ifdef CONFIG_SMP
+void __init boot_cpu_id_too_large(int cpu)
+{
+ prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n",
+ cpu, NR_CPUS);
+ prom_halt();
+}
+#endif
+
void __init setup_arch(char **cmdline_p)
{
/* Initialize PROM console and command line. */
@@ -332,16 +341,6 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &prom_con;
#endif
- /* Work out if we are starfire early on */
- check_if_starfire();
-
- /* Now we know enough to patch the get_cpuid sequences
- * used by trap code.
- */
- per_cpu_patch();
-
- sun4v_patch();
-
boot_flags_init(*cmdline_p);
idprom_init();
@@ -535,7 +534,7 @@ static int __init topology_init(void)
while (!cpu_find_by_instance(ncpus_probed, NULL, NULL))
ncpus_probed++;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
if (p) {
register_cpu(p, i, NULL);
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 7dc28a48426..f03d52d0b88 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -745,12 +745,21 @@ struct call_data_struct {
int wait;
};
-static DEFINE_SPINLOCK(call_lock);
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
static struct call_data_struct *call_data;
extern unsigned long xcall_call_function;
-/*
+/**
+ * smp_call_function(): Run a function on all other CPUs.
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @nonatomic: currently unused.
+ * @wait: If true, wait (atomically) until function has completed on other CPUs.
+ *
+ * Returns 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute <<func>> or are or have executed.
+ *
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler.
*/
@@ -759,7 +768,6 @@ static int smp_call_function_mask(void (*func)(void *info), void *info,
{
struct call_data_struct data;
int cpus;
- long timeout;
/* Can deadlock when called with interrupts disabled */
WARN_ON(irqs_disabled());
@@ -777,31 +785,18 @@ static int smp_call_function_mask(void (*func)(void *info), void *info,
goto out_unlock;
call_data = &data;
+ mb();
smp_cross_call_masked(&xcall_call_function, 0, 0, 0, mask);
- /*
- * Wait for other cpus to complete function or at
- * least snap the call data.
- */
- timeout = 1000000;
- while (atomic_read(&data.finished) != cpus) {
- if (--timeout <= 0)
- goto out_timeout;
- barrier();
- udelay(1);
- }
+ /* Wait for response */
+ while (atomic_read(&data.finished) != cpus)
+ cpu_relax();
out_unlock:
spin_unlock(&call_lock);
return 0;
-
-out_timeout:
- spin_unlock(&call_lock);
- printk("XCALL: Remote cpus not responding, ncpus=%d finished=%d\n",
- cpus, atomic_read(&data.finished));
- return 0;
}
int smp_call_function(void (*func)(void *info), void *info,
@@ -830,9 +825,16 @@ void smp_call_function_client(int irq, struct pt_regs *regs)
static void tsb_sync(void *info)
{
+ struct trap_per_cpu *tp = &trap_block[raw_smp_processor_id()];
struct mm_struct *mm = info;
- if (current->active_mm == mm)
+ /* It is not valid to test "currrent->active_mm == mm" here.
+ *
+ * The value of "current" is not changed atomically with
+ * switch_mm(). But that's OK, we just need to check the
+ * current cpu's trap block PGD physical address.
+ */
+ if (tp->pgd_paddr == __pa(mm->pgd))
tsb_context_switch(mm);
}
@@ -1262,7 +1264,6 @@ void __init smp_tick_init(void)
boot_cpu_id = hard_smp_processor_id();
current_tick_offset = timer_tick_offset;
- cpu_set(boot_cpu_id, cpu_online_map);
prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1;
}
@@ -1278,7 +1279,7 @@ int setup_profiling_timer(unsigned int multiplier)
return -EINVAL;
spin_lock_irqsave(&prof_setup_lock, flags);
- for_each_cpu(i)
+ for_each_possible_cpu(i)
prof_multiplier(i) = multiplier;
current_tick_offset = (timer_tick_offset / multiplier);
spin_unlock_irqrestore(&prof_setup_lock, flags);
@@ -1286,6 +1287,40 @@ int setup_profiling_timer(unsigned int multiplier)
return 0;
}
+static void __init smp_tune_scheduling(void)
+{
+ int instance, node;
+ unsigned int def, smallest = ~0U;
+
+ def = ((tlb_type == hypervisor) ?
+ (3 * 1024 * 1024) :
+ (4 * 1024 * 1024));
+
+ instance = 0;
+ while (!cpu_find_by_instance(instance, &node, NULL)) {
+ unsigned int val;
+
+ val = prom_getintdefault(node, "ecache-size", def);
+ if (val < smallest)
+ smallest = val;
+
+ instance++;
+ }
+
+ /* Any value less than 256K is nonsense. */
+ if (smallest < (256U * 1024U))
+ smallest = 256 * 1024;
+
+ max_cache_size = smallest;
+
+ if (smallest < 1U * 1024U * 1024U)
+ printk(KERN_INFO "Using max_cache_size of %uKB\n",
+ smallest / 1024U);
+ else
+ printk(KERN_INFO "Using max_cache_size of %uMB\n",
+ smallest / 1024U / 1024U);
+}
+
/* Constrain the number of cpus to max_cpus. */
void __init smp_prepare_cpus(unsigned int max_cpus)
{
@@ -1306,12 +1341,12 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
}
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
if (tlb_type == hypervisor) {
int j;
/* XXX get this mapping from machine description */
- for_each_cpu(j) {
+ for_each_possible_cpu(j) {
if ((j >> 2) == (i >> 2))
cpu_set(j, cpu_sibling_map[i]);
}
@@ -1321,6 +1356,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
smp_store_cpu_info(boot_cpu_id);
+ smp_tune_scheduling();
}
/* Set this up early so that things like the scheduler can init
@@ -1343,18 +1379,6 @@ void __init smp_setup_cpu_possible_map(void)
void __devinit smp_prepare_boot_cpu(void)
{
- int cpu = hard_smp_processor_id();
-
- if (cpu >= NR_CPUS) {
- prom_printf("Serious problem, boot cpu id >= NR_CPUS\n");
- prom_halt();
- }
-
- current_thread_info()->cpu = cpu;
- __local_per_cpu_offset = __per_cpu_offset(cpu);
-
- cpu_set(smp_processor_id(), cpu_online_map);
- cpu_set(smp_processor_id(), phys_cpu_present_map);
}
int __devinit __cpu_up(unsigned int cpu)
@@ -1431,4 +1455,7 @@ void __init setup_per_cpu_areas(void)
for (i = 0; i < NR_CPUS; i++, ptr += size)
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+
+ /* Setup %g5 for the boot cpu. */
+ __local_per_cpu_offset = __per_cpu_offset(smp_processor_id());
}
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index f5e8db1de76..38e569f786d 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -276,7 +276,6 @@ EXPORT_SYMBOL(__prom_getsibling);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(__strlen_user);
EXPORT_SYMBOL(__strnlen_user);
-EXPORT_SYMBOL(strpbrk);
#ifdef CONFIG_SOLARIS_EMUL_MODULE
EXPORT_SYMBOL(linux_sparc_syscall);
@@ -298,7 +297,6 @@ EXPORT_SYMBOL(svr4_getcontext);
EXPORT_SYMBOL(svr4_setcontext);
EXPORT_SYMBOL(compat_sys_ioctl);
EXPORT_SYMBOL(sparc32_open);
-EXPORT_SYMBOL(sys_close);
#endif
/* Special internal versions of library functions. */
diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
index c4a1cef4b1e..bdf1f4d02e3 100644
--- a/arch/sparc64/kernel/sys32.S
+++ b/arch/sparc64/kernel/sys32.S
@@ -136,6 +136,10 @@ SIGN1(sys32_getpeername, sys_getpeername, %o0)
SIGN1(sys32_getsockname, sys_getsockname, %o0)
SIGN2(sys32_ioprio_get, sys_ioprio_get, %o0, %o1)
SIGN3(sys32_ioprio_set, sys_ioprio_set, %o0, %o1, %o2)
+SIGN2(sys32_splice, sys_splice, %o0, %o1)
+SIGN2(sys32_sync_file_range, compat_sync_file_range, %o0, %o5)
+SIGN2(sys32_tee, sys_tee, %o0, %o1)
+SIGN1(sys32_vmsplice, compat_sys_vmsplice, %o0)
.globl sys32_mmap2
sys32_mmap2:
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 2e906bad56f..31030bf00f1 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1069,3 +1069,11 @@ long sys32_lookup_dcookie(unsigned long cookie_high,
return sys_lookup_dcookie((cookie_high << 32) | cookie_low,
buf, len);
}
+
+long compat_sync_file_range(int fd, unsigned long off_high, unsigned long off_low, unsigned long nb_high, unsigned long nb_low, int flags)
+{
+ return sys_sync_file_range(fd,
+ (off_high << 32) | off_low,
+ (nb_high << 32) | nb_low,
+ flags);
+}
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 3b250f2318f..1136fc465e3 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -25,7 +25,7 @@ sys_call_table32:
/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod
/*15*/ .word sys_chmod, sys32_lchown16, sparc_brk, sys32_perfctr, sys32_lseek
/*20*/ .word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16
-/*25*/ .word compat_sys_time, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
+/*25*/ .word sys32_vmsplice, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
/*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice
.word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile
/*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid
@@ -66,20 +66,21 @@ sys_call_table32:
.word sys32_ipc, sys32_sigreturn, sys_clone, sys32_ioprio_get, compat_sys_adjtimex
/*220*/ .word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys32_getpgid
.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16
-/*230*/ .word sys32_select, compat_sys_time, sys_nis_syscall, compat_sys_stime, compat_sys_statfs64
+/*230*/ .word sys32_select, compat_sys_time, sys32_splice, compat_sys_stime, compat_sys_statfs64
.word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
.word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
/*250*/ .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
- .word sys_ni_syscall, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
+ .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
-/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
+/*280*/ .word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
.word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64
-/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
+/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
+/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list
#endif /* CONFIG_COMPAT */
@@ -94,7 +95,7 @@ sys_call_table:
/*10*/ .word sys_unlink, sys_nis_syscall, sys_chdir, sys_chown, sys_mknod
/*15*/ .word sys_chmod, sys_lchown, sparc_brk, sys_perfctr, sys_lseek
/*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
-/*25*/ .word sys_nis_syscall, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
+/*25*/ .word sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
/*30*/ .word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
.word sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile64
/*40*/ .word sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall
@@ -135,20 +136,21 @@ sys_call_table:
.word sys_ipc, sys_nis_syscall, sys_clone, sys_ioprio_get, sys_adjtimex
/*220*/ .word sys_nis_syscall, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
.word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
-/*230*/ .word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_statfs64
+/*230*/ .word sys_select, sys_nis_syscall, sys_splice, sys_stime, sys_statfs64
.word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
/*250*/ .word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
- .word sys_ni_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
+ .word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
/*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
/*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
+/*280*/ .word sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat
.word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64
-/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
+/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
+/*300*/ .word sys_set_robust_list, sys_get_robust_list
#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
defined(CONFIG_SOLARIS_EMUL_MODULE)
@@ -261,5 +263,5 @@ sunos_sys_table:
/*290*/ .word sunos_nosys, sunos_nosys, sunos_nosys
.word sunos_nosys, sunos_nosys, sunos_nosys
.word sunos_nosys, sunos_nosys, sunos_nosys
- .word sunos_nosys
+ .word sunos_nosys, sunos_nosys, sunos_nosys
#endif
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 7d61f1bfd3d..e55b5c6ece0 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -641,23 +641,8 @@ static void __init set_system_time(void)
mon = MSTK_REG_MONTH(mregs);
year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
} else {
- int i;
-
/* Dallas 12887 RTC chip. */
- /* Stolen from arch/i386/kernel/time.c, see there for
- * credits and descriptive comments.
- */
- for (i = 0; i < 1000000; i++) {
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
- udelay(10);
- }
- for (i = 0; i < 1000000; i++) {
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
- udelay(10);
- }
do {
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
@@ -666,6 +651,7 @@ static void __init set_system_time(void)
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
} while (sec != CMOS_READ(RTC_SECONDS));
+
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
BCD_TO_BIN(sec);
BCD_TO_BIN(min);
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index df612e4f75f..563db528e03 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -43,18 +43,19 @@
#include <linux/kmod.h>
#endif
-struct notifier_block *sparc64die_chain;
-static DEFINE_SPINLOCK(die_notifier_lock);
+ATOMIC_NOTIFIER_HEAD(sparc64die_chain);
int register_die_notifier(struct notifier_block *nb)
{
- int err = 0;
- unsigned long flags;
- spin_lock_irqsave(&die_notifier_lock, flags);
- err = notifier_chain_register(&sparc64die_chain, nb);
- spin_unlock_irqrestore(&die_notifier_lock, flags);
- return err;
+ return atomic_notifier_chain_register(&sparc64die_chain, nb);
}
+EXPORT_SYMBOL(register_die_notifier);
+
+int unregister_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&sparc64die_chain, nb);
+}
+EXPORT_SYMBOL(unregister_die_notifier);
/* When an irrecoverable trap occurs at tl > 0, the trap entry
* code logs the trap state registers at every level in the trap
@@ -1129,9 +1130,9 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
afsr, afar,
(afsr & CHAFSR_TL1) ? 1 : 0);
- printk("%s" "ERROR(%d): TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n",
+ printk("%s" "ERROR(%d): TPC[%lx] TNPC[%lx] O7[%lx] TSTATE[%lx]\n",
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
- regs->tpc, regs->tnpc, regs->tstate);
+ regs->tpc, regs->tnpc, regs->u_regs[UREG_I7], regs->tstate);
printk("%s" "ERROR(%d): M_SYND(%lx), E_SYND(%lx)%s%s\n",
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
(afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT,
@@ -1796,7 +1797,9 @@ static const char *sun4v_err_type_to_str(u32 type)
};
}
-static void sun4v_log_error(struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt)
+extern void __show_regs(struct pt_regs * regs);
+
+static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt)
{
int cnt;
@@ -1829,6 +1832,8 @@ static void sun4v_log_error(struct sun4v_error_entry *ent, int cpu, const char *
pfx,
ent->err_raddr, ent->err_size, ent->err_cpu);
+ __show_regs(regs);
+
if ((cnt = atomic_read(ocnt)) != 0) {
atomic_set(ocnt, 0);
wmb();
@@ -1861,7 +1866,7 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset)
put_cpu();
- sun4v_log_error(&local_copy, cpu,
+ sun4v_log_error(regs, &local_copy, cpu,
KERN_ERR "RESUMABLE ERROR",
&sun4v_resum_oflow_cnt);
}
@@ -1909,7 +1914,7 @@ void sun4v_nonresum_error(struct pt_regs *regs, unsigned long offset)
}
#endif
- sun4v_log_error(&local_copy, cpu,
+ sun4v_log_error(regs, &local_copy, cpu,
KERN_EMERG "NON-RESUMABLE ERROR",
&sun4v_nonresum_oflow_cnt);
@@ -2199,7 +2204,6 @@ static inline struct reg_window *kernel_stack_up(struct reg_window *rw)
void die_if_kernel(char *str, struct pt_regs *regs)
{
static int die_counter;
- extern void __show_regs(struct pt_regs * regs);
extern void smp_report_regs(void);
int count = 0;
diff --git a/arch/sparc64/lib/checksum.S b/arch/sparc64/lib/checksum.S
index ba9cd3ccc2b..1d230f693dc 100644
--- a/arch/sparc64/lib/checksum.S
+++ b/arch/sparc64/lib/checksum.S
@@ -165,8 +165,9 @@ csum_partial_end_cruft:
sll %g1, 8, %g1
or %o5, %g1, %o4
-1: add %o2, %o4, %o2
+1: addcc %o2, %o4, %o2
+ addc %g0, %o2, %o2
csum_partial_finish:
retl
- mov %o2, %o0
+ srl %o2, 0, %o0
diff --git a/arch/sparc64/lib/csum_copy.S b/arch/sparc64/lib/csum_copy.S
index 71af4883906..e566c770a0f 100644
--- a/arch/sparc64/lib/csum_copy.S
+++ b/arch/sparc64/lib/csum_copy.S
@@ -221,11 +221,12 @@ FUNC_NAME: /* %o0=src, %o1=dst, %o2=len, %o3=sum */
sll %g1, 8, %g1
or %o5, %g1, %o4
-1: add %o3, %o4, %o3
+1: addcc %o3, %o4, %o3
+ addc %g0, %o3, %o3
70:
retl
- mov %o3, %o0
+ srl %o3, 0, %o0
95: mov 0, GLOBAL_SPARE
brlez,pn %o2, 4f
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index d21ff3230c0..6e002aacb96 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -327,8 +327,12 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
insn = get_fault_insn(regs, 0);
if (!insn)
goto continue_fault;
+ /* All loads, stores and atomics have bits 30 and 31 both set
+ * in the instruction. Bit 21 is set in all stores, but we
+ * have to avoid prefetches which also have bit 21 set.
+ */
if ((insn & 0xc0200000) == 0xc0200000 &&
- (insn & 0x1780000) != 0x1680000) {
+ (insn & 0x01780000) != 0x01680000) {
/* Don't bother updating thread struct value,
* because update_mmu_cache only cares which tlb
* the access came from.
@@ -413,12 +417,12 @@ good_area:
#ifdef CONFIG_HUGETLB_PAGE
mm_rss -= (mm->context.huge_pte_count * (HPAGE_SIZE / PAGE_SIZE));
#endif
- if (unlikely(mm_rss >=
+ if (unlikely(mm_rss >
mm->context.tsb_block[MM_TSB_BASE].tsb_rss_limit))
tsb_grow(mm, MM_TSB_BASE, mm_rss);
#ifdef CONFIG_HUGETLB_PAGE
mm_rss = mm->context.huge_pte_count;
- if (unlikely(mm_rss >=
+ if (unlikely(mm_rss >
mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit))
tsb_grow(mm, MM_TSB_HUGE, mm_rss);
#endif
diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c
index 074620d413d..fbbbebbad8a 100644
--- a/arch/sparc64/mm/hugetlbpage.c
+++ b/arch/sparc64/mm/hugetlbpage.c
@@ -198,6 +198,13 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
pmd_t *pmd;
pte_t *pte = NULL;
+ /* We must align the address, because our caller will run
+ * set_huge_pte_at() on whatever we return, which writes out
+ * all of the sub-ptes for the hugepage range. So we have
+ * to give it the first such sub-pte.
+ */
+ addr &= HPAGE_MASK;
+
pgd = pgd_offset(mm, addr);
pud = pud_alloc(mm, pgd, addr);
if (pud) {
diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c
index a079cf42505..3f10fc921b0 100644
--- a/arch/sparc64/mm/tlb.c
+++ b/arch/sparc64/mm/tlb.c
@@ -8,6 +8,7 @@
#include <linux/percpu.h>
#include <linux/mm.h>
#include <linux/swap.h>
+#include <linux/preempt.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -24,6 +25,8 @@ void flush_tlb_pending(void)
{
struct mmu_gather *mp = &__get_cpu_var(mmu_gathers);
+ preempt_disable();
+
if (mp->tlb_nr) {
flush_tsb_user(mp);
@@ -38,6 +41,8 @@ void flush_tlb_pending(void)
}
mp->tlb_nr = 0;
}
+
+ preempt_enable();
}
void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig)
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 5982fe2753e..76e85bbaea5 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -22,6 +22,9 @@ config SBUS
config PCI
bool
+config PCMCIA
+ bool
+
config GENERIC_CALIBRATE_DELAY
bool
default y
@@ -54,20 +57,6 @@ config STATIC_LINK
chroot, and you disable CONFIG_MODE_TT, you probably want to say Y
here.
-config HOST_2G_2G
- bool "2G/2G host address space split"
- default n
- depends on MODE_TT
- help
- This is needed when the host on which you run has a 2G/2G memory
- split, instead of the customary 3G/1G.
-
- Note that to enable such a host
- configuration, which makes sense only in some cases, you need special
- host patches.
-
- So, if you do not know what to do here, say 'N'.
-
config KERNEL_HALF_GIGS
int "Kernel address space size (in .5G units)"
default "1"
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index 85e6a55b3b5..f6eb72d117b 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -16,6 +16,19 @@ config SEMAPHORE_SLEEPERS
bool
default y
+config HOST_2G_2G
+ bool "2G/2G host address space split"
+ default n
+ help
+ This is needed when the host on which you run has a 2G/2G memory
+ split, instead of the customary 3G/1G.
+
+ Note that to enable such a host
+ configuration, which makes sense only in some cases, you need special
+ host patches.
+
+ So, if you do not know what to do here, say 'N'.
+
config TOP_ADDR
hex
default 0xc0000000 if !HOST_2G_2G
@@ -35,11 +48,13 @@ config 3_LEVEL_PGTABLES
config STUB_CODE
hex
- default 0xbfffe000
+ default 0xbfffe000 if !HOST_2G_2G
+ default 0x7fffe000 if HOST_2G_2G
config STUB_DATA
hex
- default 0xbffff000
+ default 0xbffff000 if !HOST_2G_2G
+ default 0x7ffff000 if HOST_2G_2G
config STUB_START
hex
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 8d14c7a831b..f6ad832faf1 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -20,7 +20,7 @@ core-y += $(ARCH_DIR)/kernel/ \
# Have to precede the include because the included Makefiles reference them.
SYMLINK_HEADERS := archparam.h system.h sigcontext.h processor.h ptrace.h \
- module.h vm-flags.h elf.h ldt.h
+ module.h vm-flags.h elf.h host_ldt.h
SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
# XXX: The "os" symlink is only used by arch/um/include/os.h, which includes
@@ -96,7 +96,8 @@ PHONY += linux
all: linux
linux: vmlinux
- ln -f $< $@
+ @echo ' LINK $@'
+ $(Q)ln -f $< $@
define archhelp
echo '* linux - Binary kernel image (./linux) - for backward'
@@ -117,6 +118,10 @@ prepare: $(ARCH_DIR)/include/kern_constants.h
LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
+CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,) \
+ $(call cc-option, -fno-stack-protector,) \
+ $(call cc-option, -fno-stack-protector-all,)
+
CPP_MODE-$(CONFIG_MODE_TT) := -DMODE_TT
CONFIG_KERNEL_STACK_ORDER ?= 2
STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
@@ -129,7 +134,7 @@ CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \
-DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
-DELF_FORMAT="$(ELF_FORMAT)" $(CPP_MODE-y) \
-DKERNEL_STACK_SIZE=$(STACK_SIZE) \
- -DUNMAP_PATH=arch/um/sys-$(SUBARCH)/unmap_fin.o
+ -DUNMAP_PATH=arch/um/sys-$(SUBARCH)/unmap.o
#The wrappers will select whether using "malloc" or the kernel allocator.
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
@@ -150,8 +155,7 @@ CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \
$(ARCH_DIR)/include/user_constants.h \
$(ARCH_DIR)/include/kern_constants.h $(ARCH_DIR)/Kconfig.arch
-MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \
- $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os
+MRPROPER_FILES += $(ARCH_SYMLINKS)
archclean:
@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
@@ -160,6 +164,7 @@ archclean:
$(SYMLINK_HEADERS):
@echo ' SYMLINK $@'
ifneq ($(KBUILD_SRC),)
+ $(Q)mkdir -p $(objtree)/include/asm-um
$(Q)ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@
else
$(Q)cd $(TOPDIR)/$(dir $@) ; \
@@ -169,7 +174,7 @@ endif
include/asm-um/arch:
@echo ' SYMLINK $@'
ifneq ($(KBUILD_SRC),)
- $(Q)mkdir -p include/asm-um
+ $(Q)mkdir -p $(objtree)/include/asm-um
$(Q)ln -fsn $(srctree)/include/asm-$(SUBARCH) include/asm-um/arch
else
$(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
@@ -203,8 +208,8 @@ endef
$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
$(call filechk,umlconfig)
-$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c
- $(CC) $(USER_CFLAGS) -S -o $@ $<
+$(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE
+ $(Q)$(MAKE) $(build)=$(ARCH_DIR)/sys-$(SUBARCH) $@
define filechk_gen-asm-offsets
(set -e; \
@@ -219,13 +224,11 @@ define filechk_gen-asm-offsets
echo ""; )
endef
-$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s
+$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s
$(call filechk,gen-asm-offsets)
-CLEAN_FILES += $(ARCH_DIR)/user-offsets.s
-
$(ARCH_DIR)/include/kern_constants.h: $(objtree)/$(ARCH_DIR)/include
@echo ' SYMLINK $@'
- $(Q) ln -sf ../../../include/asm-um/asm-offsets.h $@
+ $(Q)ln -sf ../../../include/asm-um/asm-offsets.h $@
-export SUBARCH USER_CFLAGS OS
+export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index 7a0e04e34bf..b65ca115ef7 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -33,5 +33,9 @@ include $(srctree)/arch/i386/Makefile.cpu
# prevent gcc from keeping the stack 16 byte aligned. Taken from i386.
cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
+# Prevent sprintf in nfsd from being converted to strcpy and resulting in
+# an unresolved reference.
+cflags-y += -ffreestanding
+
CFLAGS += $(cflags-y)
USER_CFLAGS += $(cflags-y)
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index 38df311e75d..dfd88b652fb 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -1,7 +1,7 @@
# Copyright 2003 - 2004 Pathscale, Inc
# Released under the GPL
-libs-y += arch/um/sys-x86_64/
+core-y += arch/um/sys-x86_64/
START := 0x60000000
#We #undef __x86_64__ for kernelspace, not for userspace where
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 80d30d19d75..402a74dc502 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -1,14 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc6-mm1
-# Tue Jun 14 18:22:21 2005
+# Linux kernel version: 2.6.17-rc3
+# Fri Apr 28 09:31:20 2006
#
CONFIG_GENERIC_HARDIRQS=y
CONFIG_UML=y
CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_IRQ_RELEASE_METHOD=y
#
# UML-specific options
@@ -16,8 +15,50 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
# CONFIG_MODE_TT is not set
# CONFIG_STATIC_LINK is not set
CONFIG_MODE_SKAS=y
+
+#
+# Host processor type and features
+#
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP2 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+# CONFIG_X86_GENERIC is not set
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=5
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
CONFIG_UML_X86=y
# CONFIG_64BIT is not set
+CONFIG_SEMAPHORE_SLEEPERS=y
+# CONFIG_HOST_2G_2G is not set
CONFIG_TOP_ADDR=0xc0000000
# CONFIG_3_LEVEL_PGTABLES is not set
CONFIG_STUB_CODE=0xbfffe000
@@ -25,22 +66,24 @@ CONFIG_STUB_DATA=0xbffff000
CONFIG_STUB_START=0xbfffe000
CONFIG_ARCH_HAS_SC_SIGNALS=y
CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_LD_SCRIPT_DYN=y
CONFIG_NET=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
# CONFIG_HOSTFS is not set
+# CONFIG_HPPFS is not set
CONFIG_MCONSOLE=y
# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_HOST_2G_2G is not set
CONFIG_NEST_LEVEL=0
-CONFIG_KERNEL_HALF_GIGS=1
# CONFIG_HIGHMEM is not set
CONFIG_KERNEL_STACK_ORDER=2
CONFIG_UML_REAL_TIME_CLOCK=y
@@ -49,7 +92,6 @@ CONFIG_UML_REAL_TIME_CLOCK=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -57,6 +99,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
# General setup
#
CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
@@ -64,26 +107,28 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
+CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
#
# Loadable module support
@@ -91,18 +136,43 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
-# Generic Driver Options
+# Block layer
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_UBD=y
+# CONFIG_BLK_DEV_UBD_SYNC is not set
+CONFIG_BLK_DEV_COW_COMMON=y
+# CONFIG_MMAPPER is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_ATA_OVER_ETH is not set
#
# Character Devices
@@ -127,50 +197,23 @@ CONFIG_UML_SOUND=m
CONFIG_SOUND=m
CONFIG_HOSTAUDIO=m
CONFIG_UML_RANDOM=y
-# CONFIG_MMAPPER is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_UBD=y
-CONFIG_BLK_DEV_UBD_SYNC=y
-CONFIG_BLK_DEV_COW_COMMON=y
-CONFIG_BLK_DEV_LOOP=m
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_LBD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-CONFIG_NETDEVICES=y
#
-# UML Network Devices
+# Generic Driver Options
#
-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_UML_NET_SLIRP=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
-# Networking support
+# Networking
#
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -178,6 +221,7 @@ CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
@@ -186,27 +230,31 @@ CONFIG_INET=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# TCP congestion control
-#
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
-CONFIG_TCP_CONG_WESTWOOD=y
-CONFIG_TCP_CONG_HTCP=y
-# CONFIG_TCP_CONG_HSTCP is not set
-# CONFIG_TCP_CONG_HYBLA is not set
-# CONFIG_TCP_CONG_VEGAS is not set
-# CONFIG_TCP_CONG_SCALABLE is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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
# CONFIG_VLAN_8021Q is not set
@@ -224,27 +272,47 @@ CONFIG_TCP_CONG_HTCP=y
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
-# CONFIG_KGDBOE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_IEEE80211 is not set
+
+#
+# UML Network Devices
+#
+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_UML_NET_PCAP is not set
+CONFIG_UML_NET_SLIRP=y
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
#
+# PHY device support
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
# Wan interfaces
#
# CONFIG_WAN is not set
@@ -263,6 +331,13 @@ CONFIG_SLIP=m
# CONFIG_SLIP_MODE_SLIP6 is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
#
# File systems
@@ -274,17 +349,14 @@ CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
-# CONFIG_REISER4_FS is not set
CONFIG_REISERFS_FS=y
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
# CONFIG_REISERFS_FS_XATTR is not set
# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
@@ -295,11 +367,6 @@ CONFIG_QUOTACTL=y
CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=m
CONFIG_AUTOFS4_FS=m
-
-#
-# Caches
-#
-# CONFIG_FSCACHE is not set
# CONFIG_FUSE_FS is not set
#
@@ -323,14 +390,10 @@ CONFIG_JOLIET=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
-# CONFIG_RELAYFS_FS is not set
#
# Miscellaneous filesystems
@@ -430,6 +493,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Library routines
#
# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=m
# CONFIG_LIBCRC32C is not set
@@ -448,12 +512,18 @@ CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
+# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_GPROF is not set
# CONFIG_GCOV is not set
# CONFIG_SYSCALL_DEBUG is not set
diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h
index 04e3958266e..dc36b222100 100644
--- a/arch/um/drivers/cow.h
+++ b/arch/um/drivers/cow.h
@@ -46,7 +46,7 @@ extern int file_reader(__u64 offset, char *buf, int len, void *arg);
extern int read_cow_header(int (*reader)(__u64, char *, int, void *),
void *arg, __u32 *version_out,
char **backing_file_out, time_t *mtime_out,
- __u64 *size_out, int *sectorsize_out,
+ unsigned long long *size_out, int *sectorsize_out,
__u32 *align_out, int *bitmap_offset_out);
extern int write_cow_header(char *cow_file, int fd, char *backing_file,
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index 94de4ead4f7..7a5b4afde69 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -28,7 +28,7 @@ static inline int cow_seek_file(int fd, __u64 offset)
return(os_seek_file(fd, offset));
}
-static inline int cow_file_size(char *file, __u64 *size_out)
+static inline int cow_file_size(char *file, unsigned long long *size_out)
{
return(os_file_size(file, size_out));
}
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 61951b72126..0ec4052db9c 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -17,30 +17,34 @@
#define PATH_LEN_V1 256
+typedef __u32 time32_t;
+
struct cow_header_v1 {
- int magic;
- int version;
+ __s32 magic;
+ __s32 version;
char backing_file[PATH_LEN_V1];
- time_t mtime;
+ time32_t mtime;
__u64 size;
- int sectorsize;
-};
+ __s32 sectorsize;
+} __attribute__((packed));
-#define PATH_LEN_V2 MAXPATHLEN
+/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
+ * case other systems have different values for MAXPATHLEN.
+ *
+ * The same must hold for V2 - we want file format compatibility, not anything
+ * else.
+ */
+#define PATH_LEN_V3 4096
+#define PATH_LEN_V2 PATH_LEN_V3
struct cow_header_v2 {
__u32 magic;
__u32 version;
char backing_file[PATH_LEN_V2];
- time_t mtime;
+ time32_t mtime;
__u64 size;
- int sectorsize;
-};
-
-/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
- * case other systems have different values for MAXPATHLEN
- */
-#define PATH_LEN_V3 4096
+ __s32 sectorsize;
+} __attribute__((packed));
/* Changes from V2 -
* PATH_LEN_V3 as described above
@@ -66,6 +70,15 @@ struct cow_header_v2 {
* Fixed (finally!) the rounding bug
*/
+/* Until Dec2005, __attribute__((packed)) was left out from the below
+ * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to
+ * align size to 8-byte alignment. This shifted all fields above (no padding
+ * was present on 32-bit, no other padding was added).
+ *
+ * However, this _can be detected_: it means that cow_format (always 0 until
+ * now) is shifted onto the first 4 bytes of backing_file, where it is otherwise
+ * impossible to find 4 zeros. -bb */
+
struct cow_header_v3 {
__u32 magic;
__u32 version;
@@ -75,6 +88,18 @@ struct cow_header_v3 {
__u32 alignment;
__u32 cow_format;
char backing_file[PATH_LEN_V3];
+} __attribute__((packed));
+
+/* This is the broken layout used by some 64-bit binaries. */
+struct cow_header_v3_broken {
+ __u32 magic;
+ __u32 version;
+ __s64 mtime;
+ __u64 size;
+ __u32 sectorsize;
+ __u32 alignment;
+ __u32 cow_format;
+ char backing_file[PATH_LEN_V3];
};
/* COW format definitions - for now, we have only the usual COW bitmap */
@@ -84,6 +109,7 @@ union cow_header {
struct cow_header_v1 v1;
struct cow_header_v2 v2;
struct cow_header_v3 v3;
+ struct cow_header_v3_broken v3_b;
};
#define COW_MAGIC 0x4f4f4f4d /* MOOO */
@@ -184,8 +210,9 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
err = -EINVAL;
if(strlen(backing_file) > sizeof(header->backing_file) - 1){
+ /* Below, %zd is for a size_t value */
cow_printf("Backing file name \"%s\" is too long - names are "
- "limited to %d characters\n", backing_file,
+ "limited to %zd characters\n", backing_file,
sizeof(header->backing_file) - 1);
goto out_free;
}
@@ -300,7 +327,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
*align_out = *sectorsize_out;
file = header->v2.backing_file;
}
- else if(version == 3){
+ /* This is very subtle - see above at union cow_header definition */
+ else if(version == 3 && (*((int*)header->v3.backing_file) != 0)){
if(n < sizeof(header->v3)){
cow_printf("read_cow_header - failed to read V3 "
"header\n");
@@ -310,9 +338,43 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
*size_out = ntohll(header->v3.size);
*sectorsize_out = ntohl(header->v3.sectorsize);
*align_out = ntohl(header->v3.alignment);
+ if (*align_out == 0) {
+ cow_printf("read_cow_header - invalid COW header, "
+ "align == 0\n");
+ }
*bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out);
file = header->v3.backing_file;
}
+ else if(version == 3){
+ cow_printf("read_cow_header - broken V3 file with"
+ " 64-bit layout - recovering content.\n");
+
+ if(n < sizeof(header->v3_b)){
+ cow_printf("read_cow_header - failed to read V3 "
+ "header\n");
+ goto out;
+ }
+
+ /* this was used until Dec2005 - 64bits are needed to represent
+ * 2038+. I.e. we can safely do this truncating cast.
+ *
+ * Additionally, we must use ntohl() instead of ntohll(), since
+ * the program used to use the former (tested - I got mtime
+ * mismatch "0 vs whatever").
+ *
+ * Ever heard about bug-to-bug-compatibility ? ;-) */
+ *mtime_out = (time32_t) ntohl(header->v3_b.mtime);
+
+ *size_out = ntohll(header->v3_b.size);
+ *sectorsize_out = ntohl(header->v3_b.sectorsize);
+ *align_out = ntohl(header->v3_b.alignment);
+ if (*align_out == 0) {
+ cow_printf("read_cow_header - invalid COW header, "
+ "align == 0\n");
+ }
+ *bitmap_offset_out = ROUND_UP(sizeof(header->v3_b), *align_out);
+ file = header->v3_b.backing_file;
+ }
else {
cow_printf("read_cow_header - invalid COW version\n");
goto out;
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c
index a61b7b46bc0..53d09ed78b4 100644
--- a/arch/um/drivers/daemon_kern.c
+++ b/arch/um/drivers/daemon_kern.c
@@ -95,18 +95,7 @@ static struct transport daemon_transport = {
static int register_daemon(void)
{
register_transport(&daemon_transport);
- return(1);
+ return 0;
}
__initcall(register_daemon);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c
index 49acb2badf3..d18a974735e 100644
--- a/arch/um/drivers/harddog_kern.c
+++ b/arch/um/drivers/harddog_kern.c
@@ -104,7 +104,7 @@ static int harddog_release(struct inode *inode, struct file *file)
extern int ping_watchdog(int fd);
-static ssize_t harddog_write(struct file *file, const char *data, size_t len,
+static ssize_t harddog_write(struct file *file, const char __user *data, size_t len,
loff_t *ppos)
{
/*
@@ -118,6 +118,7 @@ static ssize_t harddog_write(struct file *file, const char *data, size_t len,
static int harddog_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ void __user *argp= (void __user *)arg;
static struct watchdog_info ident = {
WDIOC_SETTIMEOUT,
0,
@@ -127,13 +128,12 @@ static int harddog_ioctl(struct inode *inode, struct file *file,
default:
return -ENOTTY;
case WDIOC_GETSUPPORT:
- if(copy_to_user((struct harddog_info *)arg, &ident,
- sizeof(ident)))
+ if(copy_to_user(argp, &ident, sizeof(ident)))
return -EFAULT;
return 0;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
- return put_user(0,(int *)arg);
+ return put_user(0,(int __user *)argp);
case WDIOC_KEEPALIVE:
return(ping_watchdog(harddog_out_fd));
}
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index 59602b81b24..37232f908cd 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -67,8 +67,8 @@ MODULE_PARM_DESC(mixer, MIXER_HELP);
/* /dev/dsp file operations */
-static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count,
- loff_t *ppos)
+static ssize_t hostaudio_read(struct file *file, char __user *buffer,
+ size_t count, loff_t *ppos)
{
struct hostaudio_state *state = file->private_data;
void *kbuf;
@@ -94,7 +94,7 @@ static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count,
return(err);
}
-static ssize_t hostaudio_write(struct file *file, const char *buffer,
+static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
struct hostaudio_state *state = file->private_data;
@@ -152,7 +152,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_CHANNELS:
case SNDCTL_DSP_SUBDIVIDE:
case SNDCTL_DSP_SETFRAGMENT:
- if(get_user(data, (int *) arg))
+ if(get_user(data, (int __user *) arg))
return(-EFAULT);
break;
default:
@@ -168,7 +168,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_CHANNELS:
case SNDCTL_DSP_SUBDIVIDE:
case SNDCTL_DSP_SETFRAGMENT:
- if(put_user(data, (int *) arg))
+ if(put_user(data, (int __user *) arg))
return(-EFAULT);
break;
default:
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
index c9b078fba03..3a7af18cf94 100644
--- a/arch/um/drivers/mcast_kern.c
+++ b/arch/um/drivers/mcast_kern.c
@@ -124,18 +124,7 @@ static struct transport mcast_transport = {
static int register_mcast(void)
{
register_transport(&mcast_transport);
- return(1);
+ return 0;
}
__initcall(register_mcast);
-
-/*
- * 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/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 54388d10bcf..6d7173fc55a 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -20,6 +20,8 @@
#include "linux/namei.h"
#include "linux/proc_fs.h"
#include "linux/syscalls.h"
+#include "linux/list.h"
+#include "linux/mm.h"
#include "linux/console.h"
#include "asm/irq.h"
#include "asm/uaccess.h"
@@ -60,7 +62,7 @@ static void mc_work_proc(void *unused)
unsigned long flags;
while(!list_empty(&mc_requests)){
- local_save_flags(flags);
+ local_irq_save(flags);
req = list_entry(mc_requests.next, struct mconsole_entry,
list);
list_del(&req->list);
@@ -85,7 +87,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id,
if(req.cmd->context == MCONSOLE_INTR)
(*req.cmd->handler)(&req);
else {
- new = kmalloc(sizeof(*new), GFP_ATOMIC);
+ new = kmalloc(sizeof(*new), GFP_NOWAIT);
if(new == NULL)
mconsole_reply(&req, "Out of memory", 1, 0);
else {
@@ -347,6 +349,141 @@ static struct mc_device *mconsole_find_dev(char *name)
return(NULL);
}
+#define UNPLUGGED_PER_PAGE \
+ ((PAGE_SIZE - sizeof(struct list_head)) / sizeof(unsigned long))
+
+struct unplugged_pages {
+ struct list_head list;
+ void *pages[UNPLUGGED_PER_PAGE];
+};
+
+static unsigned long long unplugged_pages_count = 0;
+static struct list_head unplugged_pages = LIST_HEAD_INIT(unplugged_pages);
+static int unplug_index = UNPLUGGED_PER_PAGE;
+
+static int mem_config(char *str)
+{
+ unsigned long long diff;
+ int err = -EINVAL, i, add;
+ char *ret;
+
+ if(str[0] != '=')
+ goto out;
+
+ str++;
+ if(str[0] == '-')
+ add = 0;
+ else if(str[0] == '+'){
+ add = 1;
+ }
+ else goto out;
+
+ str++;
+ diff = memparse(str, &ret);
+ if(*ret != '\0')
+ goto out;
+
+ diff /= PAGE_SIZE;
+
+ for(i = 0; i < diff; i++){
+ struct unplugged_pages *unplugged;
+ void *addr;
+
+ if(add){
+ if(list_empty(&unplugged_pages))
+ break;
+
+ unplugged = list_entry(unplugged_pages.next,
+ struct unplugged_pages, list);
+ if(unplug_index > 0)
+ addr = unplugged->pages[--unplug_index];
+ else {
+ list_del(&unplugged->list);
+ addr = unplugged;
+ unplug_index = UNPLUGGED_PER_PAGE;
+ }
+
+ free_page((unsigned long) addr);
+ unplugged_pages_count--;
+ }
+ else {
+ struct page *page;
+
+ page = alloc_page(GFP_ATOMIC);
+ if(page == NULL)
+ break;
+
+ unplugged = page_address(page);
+ if(unplug_index == UNPLUGGED_PER_PAGE){
+ list_add(&unplugged->list, &unplugged_pages);
+ unplug_index = 0;
+ }
+ else {
+ struct list_head *entry = unplugged_pages.next;
+ addr = unplugged;
+
+ unplugged = list_entry(entry,
+ struct unplugged_pages,
+ list);
+ unplugged->pages[unplug_index++] = addr;
+ err = os_drop_memory(addr, PAGE_SIZE);
+ if(err)
+ printk("Failed to release memory - "
+ "errno = %d\n", err);
+ }
+
+ unplugged_pages_count++;
+ }
+ }
+
+ err = 0;
+out:
+ return err;
+}
+
+static int mem_get_config(char *name, char *str, int size, char **error_out)
+{
+ char buf[sizeof("18446744073709551615")];
+ int len = 0;
+
+ sprintf(buf, "%ld", uml_physmem);
+ CONFIG_CHUNK(str, size, len, buf, 1);
+
+ return len;
+}
+
+static int mem_id(char **str, int *start_out, int *end_out)
+{
+ *start_out = 0;
+ *end_out = 0;
+
+ return 0;
+}
+
+static int mem_remove(int n)
+{
+ return -EBUSY;
+}
+
+static struct mc_device mem_mc = {
+ .name = "mem",
+ .config = mem_config,
+ .get_config = mem_get_config,
+ .id = mem_id,
+ .remove = mem_remove,
+};
+
+static int mem_mc_init(void)
+{
+ if(can_drop_memory())
+ mconsole_register_dev(&mem_mc);
+ else printk("Can't release memory to the host - memory hotplug won't "
+ "be supported\n");
+ return 0;
+}
+
+__initcall(mem_mc_init);
+
#define CONFIG_BUF_SIZE 64
static void mconsole_get_config(int (*get_config)(char *, char *, int,
@@ -478,7 +615,7 @@ static void console_write(struct console *console, const char *string,
return;
while(1){
- n = min(len, ARRAY_SIZE(console_buf) - console_index);
+ n = min((size_t) len, ARRAY_SIZE(console_buf) - console_index);
strncpy(&console_buf[console_index], string, n);
console_index += n;
string += n;
@@ -517,7 +654,6 @@ static void with_console(struct mc_request *req, void (*proc)(void *),
struct mconsole_entry entry;
unsigned long flags;
- INIT_LIST_HEAD(&entry.list);
entry.request = *req;
list_add(&entry.list, &clients);
spin_lock_irqsave(&console_lock, flags);
@@ -762,7 +898,8 @@ static struct notifier_block panic_exit_notifier = {
static int add_notifier(void)
{
- notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &panic_exit_notifier);
return(0);
}
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 0e2f06187ea..0a7786e00cf 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -182,7 +182,9 @@ static int change_tramp(char **argv, char *output, int output_len)
pe_data.stdout = fds[1];
pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
- read_output(fds[0], output, output_len);
+ if (pid > 0) /* Avoid hang as we won't get data in failure case. */
+ read_output(fds[0], output, output_len);
+
os_close_file(fds[0]);
os_close_file(fds[1]);
diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c
index 07c80f2156e..466ff2c2f91 100644
--- a/arch/um/drivers/pcap_kern.c
+++ b/arch/um/drivers/pcap_kern.c
@@ -106,18 +106,7 @@ static struct transport pcap_transport = {
static int register_pcap(void)
{
register_transport(&pcap_transport);
- return(1);
+ return 0;
}
__initcall(register_pcap);
-
-/*
- * 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_kern.c b/arch/um/drivers/slip_kern.c
index a62f5ef445c..163ee0d5f75 100644
--- a/arch/um/drivers/slip_kern.c
+++ b/arch/um/drivers/slip_kern.c
@@ -93,18 +93,7 @@ static struct transport slip_transport = {
static int register_slip(void)
{
register_transport(&slip_transport);
- return(1);
+ return 0;
}
__initcall(register_slip);
-
-/*
- * 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/slirp_kern.c b/arch/um/drivers/slirp_kern.c
index 33d7982be5d..95e50c943e1 100644
--- a/arch/um/drivers/slirp_kern.c
+++ b/arch/um/drivers/slirp_kern.c
@@ -77,7 +77,7 @@ static int slirp_setup(char *str, char **mac_out, void *data)
int i=0;
*init = ((struct slirp_init)
- { argw : { { "slirp", NULL } } });
+ { .argw = { { "slirp", NULL } } });
str = split_if_spec(str, mac_out, NULL);
@@ -116,18 +116,7 @@ static struct transport slirp_transport = {
static int register_slirp(void)
{
register_transport(&slirp_transport);
- return(1);
+ return 0;
}
__initcall(register_slirp);
-
-/*
- * 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/slirp_user.c b/arch/um/drivers/slirp_user.c
index b94c66114bc..33c5f6e625e 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -104,7 +104,7 @@ static void slirp_close(int fd, void *data)
}
if(err == 0) {
- printk("slirp_close: process %d has not exited\n");
+ printk("slirp_close: process %d has not exited\n", pri->pid);
return;
}
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index fa617e0719a..0897852b09a 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -71,7 +71,7 @@ struct io_thread_req {
int error;
};
-extern int open_ubd_file(char *file, struct openflags *openflags,
+extern int open_ubd_file(char *file, struct openflags *openflags, int shared,
char **backing_file_out, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out,
int *create_cow_out);
@@ -137,7 +137,7 @@ static int fake_major = MAJOR_NR;
static struct gendisk *ubd_gendisk[MAX_DEV];
static struct gendisk *fake_gendisk[MAX_DEV];
-
+
#ifdef CONFIG_BLK_DEV_UBD_SYNC
#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 1, .c = 0, \
.cl = 1 })
@@ -168,6 +168,7 @@ struct ubd {
__u64 size;
struct openflags boot_openflags;
struct openflags openflags;
+ int shared;
int no_cow;
struct cow cow;
struct platform_device pdev;
@@ -189,6 +190,7 @@ struct ubd {
.boot_openflags = OPEN_FLAGS, \
.openflags = OPEN_FLAGS, \
.no_cow = 0, \
+ .shared = 0, \
.cow = DEFAULT_COW, \
}
@@ -305,7 +307,7 @@ static int ubd_setup_common(char *str, int *index_out)
}
major = simple_strtoul(str, &end, 0);
if((*end != '\0') || (end == str)){
- printk(KERN_ERR
+ printk(KERN_ERR
"ubd_setup : didn't parse major number\n");
return(1);
}
@@ -316,7 +318,7 @@ static int ubd_setup_common(char *str, int *index_out)
printk(KERN_ERR "Can't assign a fake major twice\n");
goto out1;
}
-
+
fake_major = major;
printk(KERN_INFO "Setting extra ubd major number to %d\n",
@@ -351,7 +353,7 @@ static int ubd_setup_common(char *str, int *index_out)
if (index_out)
*index_out = n;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < sizeof("rscd="); i++) {
switch (*str) {
case 'r':
flags.w = 0;
@@ -362,11 +364,14 @@ static int ubd_setup_common(char *str, int *index_out)
case 'd':
dev->no_cow = 1;
break;
+ case 'c':
+ dev->shared = 1;
+ break;
case '=':
str++;
goto break_loop;
default:
- printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r,s or d)\n");
+ printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r, s, c, or d)\n");
goto out;
}
str++;
@@ -515,7 +520,7 @@ static void ubd_handler(void)
spin_unlock(&ubd_io_lock);
return;
}
-
+
ubd_finish(rq, req.error);
reactivate_fd(thread_fd, UBD_IRQ);
do_ubd_request(ubd_queue);
@@ -532,7 +537,7 @@ static int io_pid = -1;
void kill_io_thread(void)
{
- if(io_pid != -1)
+ if(io_pid != -1)
os_kill_process(io_pid, 1);
}
@@ -567,14 +572,15 @@ static int ubd_open_dev(struct ubd *dev)
create_cow = 0;
create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
back_ptr = dev->no_cow ? NULL : &dev->cow.file;
- dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr,
- &dev->cow.bitmap_offset, &dev->cow.bitmap_len,
- &dev->cow.data_offset, create_ptr);
+ dev->fd = open_ubd_file(dev->file, &dev->openflags, dev->shared,
+ back_ptr, &dev->cow.bitmap_offset,
+ &dev->cow.bitmap_len, &dev->cow.data_offset,
+ create_ptr);
if((dev->fd == -ENOENT) && create_cow){
- dev->fd = create_cow_file(dev->file, dev->cow.file,
+ dev->fd = create_cow_file(dev->file, dev->cow.file,
dev->openflags, 1 << 9, PAGE_SIZE,
- &dev->cow.bitmap_offset,
+ &dev->cow.bitmap_offset,
&dev->cow.bitmap_len,
&dev->cow.data_offset);
if(dev->fd >= 0){
@@ -598,16 +604,16 @@ static int ubd_open_dev(struct ubd *dev)
}
flush_tlb_kernel_vm();
- err = read_cow_bitmap(dev->fd, dev->cow.bitmap,
- dev->cow.bitmap_offset,
+ err = read_cow_bitmap(dev->fd, dev->cow.bitmap,
+ dev->cow.bitmap_offset,
dev->cow.bitmap_len);
if(err < 0)
goto error;
flags = dev->openflags;
flags.w = 0;
- err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL,
- NULL, NULL);
+ err = open_ubd_file(dev->cow.file, &flags, dev->shared, NULL,
+ NULL, NULL, NULL, NULL);
if(err < 0) goto error;
dev->cow.fd = err;
}
@@ -685,11 +691,11 @@ static int ubd_add(int n)
dev->size = ROUND_BLOCK(dev->size);
err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
- if(err)
+ if(err)
goto out_close;
-
+
if(fake_major != MAJOR_NR)
- ubd_new_disk(fake_major, dev->size, n,
+ ubd_new_disk(fake_major, dev->size, n,
&fake_gendisk[n]);
/* perhaps this should also be under the "if (fake_major)" above */
@@ -854,7 +860,7 @@ int ubd_init(void)
return -1;
}
platform_driver_register(&ubd_driver);
- for (i = 0; i < MAX_DEV; i++)
+ for (i = 0; i < MAX_DEV; i++)
ubd_add(i);
return 0;
}
@@ -872,20 +878,20 @@ int ubd_driver_init(void){
* enough. So use anyway the io thread. */
}
stack = alloc_stack(0, 0);
- io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
+ io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
&thread_fd);
if(io_pid < 0){
- printk(KERN_ERR
+ printk(KERN_ERR
"ubd : Failed to start I/O thread (errno = %d) - "
"falling back to synchronous I/O\n", -io_pid);
io_pid = -1;
return(0);
}
- err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
+ err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
SA_INTERRUPT, "ubd", ubd_dev);
if(err != 0)
printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
- return(err);
+ return 0;
}
device_initcall(ubd_driver_init);
@@ -978,7 +984,7 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
if(req->op == UBD_READ) {
for(i = 0; i < req->length >> 9; i++){
if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
- ubd_set_bit(i, (unsigned char *)
+ ubd_set_bit(i, (unsigned char *)
&req->sector_mask);
}
}
@@ -999,7 +1005,7 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
/* This should be impossible now */
if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
- printk("Write attempted on readonly ubd device %s\n",
+ printk("Write attempted on readonly ubd device %s\n",
disk->disk_name);
end_request(req, 0);
return(1);
@@ -1182,7 +1188,7 @@ int read_cow_bitmap(int fd, void *buf, int offset, int len)
return(0);
}
-int open_ubd_file(char *file, struct openflags *openflags,
+int open_ubd_file(char *file, struct openflags *openflags, int shared,
char **backing_file_out, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out,
int *create_cow_out)
@@ -1206,10 +1212,14 @@ int open_ubd_file(char *file, struct openflags *openflags,
return fd;
}
- err = os_lock_file(fd, openflags->w);
- if(err < 0){
- printk("Failed to lock '%s', err = %d\n", file, -err);
- goto out_close;
+ if(shared)
+ printk("Not locking \"%s\" on the host\n", file);
+ else {
+ err = os_lock_file(fd, openflags->w);
+ if(err < 0){
+ printk("Failed to lock '%s', err = %d\n", file, -err);
+ goto out_close;
+ }
}
/* Succesful return case! */
@@ -1260,7 +1270,7 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
int err, fd;
flags.c = 1;
- fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
+ fd = open_ubd_file(cow_file, &flags, 0, NULL, NULL, NULL, NULL, NULL);
if(fd < 0){
err = fd;
printk("Open of COW file '%s' failed, errno = %d\n", cow_file,
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index b61deb8b362..69a93c804f0 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -6,6 +6,17 @@
#ifndef __IRQ_USER_H__
#define __IRQ_USER_H__
+struct irq_fd {
+ struct irq_fd *next;
+ void *id;
+ int fd;
+ int type;
+ int irq;
+ int pid;
+ int events;
+ int current_events;
+};
+
enum { IRQ_READ, IRQ_WRITE };
extern void sigio_handler(int sig, union uml_pt_regs *regs);
@@ -16,8 +27,6 @@ extern void reactivate_fd(int fd, int irqnum);
extern void deactivate_fd(int fd, int irqnum);
extern int deactivate_all_fds(void);
extern void forward_interrupts(int pid);
-extern void init_irq_signals(int on_sigstack);
-extern void forward_ipi(int fd, int pid);
extern int activate_ipi(int fd, int pid);
extern unsigned long irq_lock(void);
extern void irq_unlock(unsigned long flags);
diff --git a/arch/um/include/kern.h b/arch/um/include/kern.h
index 7d223beccbc..4ce3fc650e5 100644
--- a/arch/um/include/kern.h
+++ b/arch/um/include/kern.h
@@ -29,7 +29,7 @@ extern int getuid(void);
extern int getgid(void);
extern int pause(void);
extern int write(int, const void *, int);
-extern int exit(int);
+extern void exit(int);
extern int close(int);
extern int read(unsigned int, char *, int);
extern int pipe(int *);
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 07176d92e1c..310980b3217 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -116,24 +116,15 @@ extern void *get_current(void);
extern struct task_struct *get_task(int pid, int require);
extern void machine_halt(void);
extern int is_syscall(unsigned long addr);
-extern void arch_switch(void);
+
extern void free_irq(unsigned int, void *);
extern int cpu(void);
+extern void time_init_kern(void);
+
/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
extern int __cant_sleep(void);
extern void segv_handler(int sig, union uml_pt_regs *regs);
extern void sigio_handler(int sig, union uml_pt_regs *regs);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 6f4d680dc1d..6ac0f8252e2 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -58,23 +58,17 @@ struct line {
};
#define LINE_INIT(str, d) \
- { init_str : str, \
- init_pri : INIT_STATIC, \
- valid : 1, \
- throttled : 0, \
- lock : SPIN_LOCK_UNLOCKED, \
- buffer : NULL, \
- head : NULL, \
- tail : NULL, \
- sigio : 0, \
- driver : d, \
- have_irq : 0 }
+ { .init_str = str, \
+ .init_pri = INIT_STATIC, \
+ .valid = 1, \
+ .lock = SPIN_LOCK_UNLOCKED, \
+ .driver = d }
struct lines {
int num;
};
-#define LINES_INIT(n) { num : n }
+#define LINES_INIT(n) { .num = n }
extern void line_close(struct tty_struct *tty, struct file * filp);
extern int line_open(struct line *lines, struct tty_struct *tty);
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
index 018b3819ab0..8e7053013f7 100644
--- a/arch/um/include/longjmp.h
+++ b/arch/um/include/longjmp.h
@@ -4,11 +4,11 @@
#include <setjmp.h>
#include "os.h"
-#define UML_SIGLONGJMP(buf, val) do { \
+#define UML_LONGJMP(buf, val) do { \
longjmp(*buf, val); \
} while(0)
-#define UML_SIGSETJMP(buf, enable) ({ \
+#define UML_SETJMP(buf, enable) ({ \
int n; \
enable = get_signals(); \
n = setjmp(*buf); \
diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
index a1064c5823b..a54514d2cc3 100644
--- a/arch/um/include/mem_user.h
+++ b/arch/um/include/mem_user.h
@@ -49,7 +49,6 @@ extern int iomem_size;
extern unsigned long host_task_size;
extern unsigned long task_size;
-extern void check_devanon(void);
extern int init_mem_user(void);
extern void setup_memory(void *entry);
extern unsigned long find_iomem(char *driver, unsigned long *len_out);
diff --git a/arch/um/include/misc_constants.h b/arch/um/include/misc_constants.h
new file mode 100644
index 00000000000..989bc08de36
--- /dev/null
+++ b/arch/um/include/misc_constants.h
@@ -0,0 +1,6 @@
+#ifndef __MISC_CONSTANT_H_
+#define __MISC_CONSTANT_H_
+
+#include <user_constants.h>
+
+#endif
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 2a1c64d8d0b..f88856c28a6 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -12,6 +12,8 @@
#include "sysdep/ptrace.h"
#include "kern_util.h"
#include "skas/mm_id.h"
+#include "irq_user.h"
+#include "sysdep/tls.h"
#define OS_TYPE_FILE 1
#define OS_TYPE_DIR 2
@@ -121,6 +123,7 @@ static inline struct openflags of_cloexec(struct openflags flags)
return(flags);
}
+/* file.c */
extern int os_stat_file(const char *file_name, struct uml_stat *buf);
extern int os_stat_fd(const int fd, struct uml_stat *buf);
extern int os_access(const char *file, int mode);
@@ -156,10 +159,21 @@ extern int os_connect_socket(char *name);
extern int os_file_type(char *file);
extern int os_file_mode(char *file, struct openflags *mode_out);
extern int os_lock_file(int fd, int excl);
+extern void os_flush_stdout(void);
+extern int os_stat_filesystem(char *path, long *bsize_out,
+ long long *blocks_out, long long *bfree_out,
+ long long *bavail_out, long long *files_out,
+ long long *ffree_out, void *fsid_out,
+ int fsid_size, long *namelen_out,
+ long *spare_out);
+extern int os_change_dir(char *dir);
+extern int os_fchange_dir(int fd);
/* start_up.c */
extern void os_early_checks(void);
extern int can_do_skas(void);
+extern void os_check_bugs(void);
+extern void check_host_supports_tls(int *supports_tls, int *tls_min);
/* Make sure they are clear when running in TT mode. Required by
* SEGV_MAYBE_FIXABLE */
@@ -193,11 +207,15 @@ extern int os_map_memory(void *virt, int fd, unsigned long long off,
extern int os_protect_memory(void *addr, unsigned long len,
int r, int w, int x);
extern int os_unmap_memory(void *addr, int len);
+extern int os_drop_memory(void *addr, int length);
+extern int can_drop_memory(void);
extern void os_flush_stdout(void);
/* tt.c
* for tt mode only (will be deleted in future...)
*/
+extern void forward_ipi(int fd, int pid);
+extern void kill_child_dead(int pid);
extern void stop(void);
extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
extern int protect_memory(unsigned long addr, unsigned long len,
@@ -220,8 +238,12 @@ extern int run_helper_thread(int (*proc)(void *), void *arg,
int stack_order);
extern int helper_wait(int pid);
-/* umid.c */
+/* tls.c */
+extern int os_set_thread_area(user_desc_t *info, int pid);
+extern int os_get_thread_area(user_desc_t *info, int pid);
+
+/* umid.c */
extern int umid_file_name(char *name, char *buf, int len);
extern int set_umid(char *name);
extern char *get_umid(void);
@@ -294,4 +316,26 @@ extern void initial_thread_cb_skas(void (*proc)(void *),
extern void halt_skas(void);
extern void reboot_skas(void);
+/* irq.c */
+extern int os_waiting_for_events(struct irq_fd *active_fds);
+extern int os_isatty(int fd);
+extern int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds);
+extern void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
+ struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2);
+extern void os_free_irq_later(struct irq_fd *active_fds,
+ int irq, void *dev_id);
+extern int os_get_pollfd(int i);
+extern void os_set_pollfd(int i, int fd);
+extern void os_set_ioignore(void);
+extern void init_irq_signals(int on_sigstack);
+
+/* sigio.c */
+extern void write_sigio_workaround(void);
+extern int add_sigio_fd(int fd, int read);
+extern int ignore_sigio_fd(int fd);
+
+/* skas/trap */
+extern void sig_handler_common_skas(int sig, void *sc_ptr);
+extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
+
#endif
diff --git a/arch/um/include/sigio.h b/arch/um/include/sigio.h
index 37d76e29a14..fe99ea163c2 100644
--- a/arch/um/include/sigio.h
+++ b/arch/um/include/sigio.h
@@ -8,9 +8,6 @@
extern int write_sigio_irq(int fd);
extern int register_sigio_fd(int fd);
-extern int read_sigio_fd(int fd);
-extern int add_sigio_fd(int fd, int read);
-extern int ignore_sigio_fd(int fd);
extern void sigio_lock(void);
extern void sigio_unlock(void);
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
index 260065cfeef..8bc6916bbbb 100644
--- a/arch/um/include/skas/mode-skas.h
+++ b/arch/um/include/skas/mode-skas.h
@@ -13,7 +13,6 @@ extern unsigned long exec_fp_regs[];
extern unsigned long exec_fpx_regs[];
extern int have_fpx_regs;
-extern void sig_handler_common_skas(int sig, void *sc_ptr);
extern void kill_off_processes_skas(void);
#endif
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h
index 86357282d68..853b26f148c 100644
--- a/arch/um/include/skas/skas.h
+++ b/arch/um/include/skas/skas.h
@@ -17,7 +17,6 @@ extern int user_thread(unsigned long stack, int flags);
extern void new_thread_proc(void *stack, void (*handler)(int sig));
extern void new_thread_handler(int sig);
extern void handle_syscall(union uml_pt_regs *regs);
-extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
extern int new_mm(unsigned long stack);
extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
extern long execute_syscall_skas(void *r);
diff --git a/arch/um/include/sysdep-i386/checksum.h b/arch/um/include/sysdep-i386/checksum.h
index 7d3d202d7ff..052bb061a97 100644
--- a/arch/um/include/sysdep-i386/checksum.h
+++ b/arch/um/include/sysdep-i386/checksum.h
@@ -48,7 +48,8 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
*/
static __inline__
-unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
+unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
+ unsigned char *dst,
int len, int sum, int *err_ptr)
{
if(copy_from_user(dst, src, len)){
@@ -192,7 +193,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
*/
#define HAVE_CSUM_COPY_USER
static __inline__ unsigned int csum_and_copy_to_user(const unsigned char *src,
- unsigned char *dst,
+ unsigned char __user *dst,
int len, int sum, int *err_ptr)
{
if (access_ok(VERIFY_WRITE, dst, len)){
diff --git a/arch/um/include/sysdep-i386/kernel-offsets.h b/arch/um/include/sysdep-i386/kernel-offsets.h
index 82f96c57414..2c13de321f2 100644
--- a/arch/um/include/sysdep-i386/kernel-offsets.h
+++ b/arch/um/include/sysdep-i386/kernel-offsets.h
@@ -1,6 +1,7 @@
#include <linux/stddef.h>
#include <linux/sched.h>
#include <linux/elf.h>
+#include <asm/mman.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -16,6 +17,7 @@
void foo(void)
{
OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs);
+ DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
#ifdef CONFIG_MODE_TT
OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
#endif
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index c8ee9559f3a..6670cc992ec 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -14,7 +14,12 @@
#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+#ifdef UML_CONFIG_PT_PROXY
extern void update_debugregs(int seq);
+#else
+static inline void update_debugregs(int seq) {}
+#endif
+
/* syscall emulation path in ptrace */
diff --git a/arch/um/include/sysdep-i386/tls.h b/arch/um/include/sysdep-i386/tls.h
new file mode 100644
index 00000000000..918fd3c5ff9
--- /dev/null
+++ b/arch/um/include/sysdep-i386/tls.h
@@ -0,0 +1,32 @@
+#ifndef _SYSDEP_TLS_H
+#define _SYSDEP_TLS_H
+
+# ifndef __KERNEL__
+
+/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
+ * may be named user_desc (but in 2.4 and in header matching its API was named
+ * modify_ldt_ldt_s). */
+
+typedef struct um_dup_user_desc {
+ unsigned int entry_number;
+ unsigned int base_addr;
+ unsigned int limit;
+ unsigned int seg_32bit:1;
+ unsigned int contents:2;
+ unsigned int read_exec_only:1;
+ unsigned int limit_in_pages:1;
+ unsigned int seg_not_present:1;
+ unsigned int useable:1;
+} user_desc_t;
+
+# else /* __KERNEL__ */
+
+# include <asm/ldt.h>
+typedef struct user_desc user_desc_t;
+
+# endif /* __KERNEL__ */
+
+#define GDT_ENTRY_TLS_MIN_I386 6
+#define GDT_ENTRY_TLS_MIN_X86_64 12
+
+#endif /* _SYSDEP_TLS_H */
diff --git a/arch/um/include/sysdep-x86_64/kernel-offsets.h b/arch/um/include/sysdep-x86_64/kernel-offsets.h
index 5ce93abd0b5..939cc475757 100644
--- a/arch/um/include/sysdep-x86_64/kernel-offsets.h
+++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
@@ -4,6 +4,7 @@
#include <linux/time.h>
#include <linux/elf.h>
#include <asm/page.h>
+#include <asm/mman.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -18,6 +19,7 @@
void foo(void)
{
+ DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
#ifdef CONFIG_MODE_TT
OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
#endif
diff --git a/arch/um/include/sysdep-x86_64/tls.h b/arch/um/include/sysdep-x86_64/tls.h
new file mode 100644
index 00000000000..35f19f25bd3
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/tls.h
@@ -0,0 +1,29 @@
+#ifndef _SYSDEP_TLS_H
+#define _SYSDEP_TLS_H
+
+# ifndef __KERNEL__
+
+/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
+ * may be named user_desc (but in 2.4 and in header matching its API was named
+ * modify_ldt_ldt_s). */
+
+typedef struct um_dup_user_desc {
+ unsigned int entry_number;
+ unsigned int base_addr;
+ unsigned int limit;
+ unsigned int seg_32bit:1;
+ unsigned int contents:2;
+ unsigned int read_exec_only:1;
+ unsigned int limit_in_pages:1;
+ unsigned int seg_not_present:1;
+ unsigned int useable:1;
+ unsigned int lm:1;
+} user_desc_t;
+
+# else /* __KERNEL__ */
+
+# include <asm/ldt.h>
+typedef struct user_desc user_desc_t;
+
+# endif /* __KERNEL__ */
+#endif /* _SYSDEP_TLS_H */
diff --git a/arch/um/include/tt/tt.h b/arch/um/include/tt/tt.h
index 80852198018..acb8356e1f9 100644
--- a/arch/um/include/tt/tt.h
+++ b/arch/um/include/tt/tt.h
@@ -19,7 +19,8 @@ extern int fork_tramp(void *sig_stack);
extern int do_proc_op(void *t, int proc_id);
extern int tracer(int (*init_proc)(void *), void *sp);
extern void attach_process(int pid);
-extern void tracer_panic(char *format, ...);
+extern void tracer_panic(char *format, ...)
+ __attribute__ ((format (printf, 1, 2)));
extern void set_init_pid(int pid);
extern int set_user_mode(void *task);
extern void set_tracing(void *t, int tracing);
diff --git a/arch/um/include/user.h b/arch/um/include/user.h
index 91b0ac4ad88..39f8c880107 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -6,8 +6,10 @@
#ifndef __USER_H__
#define __USER_H__
-extern void panic(const char *fmt, ...);
-extern int printk(const char *fmt, ...);
+extern void panic(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+extern int printk(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
extern void schedule(void);
extern void *um_kmalloc(int size);
extern void *um_kmalloc_atomic(int size);
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index a6f1f176cf8..802d7842514 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -8,6 +8,9 @@
#include "sysdep/ptrace.h"
+/* Copied from kernel.h */
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
#define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
extern int mode_tt;
@@ -31,7 +34,7 @@ extern unsigned long uml_physmem;
extern unsigned long uml_reserved;
extern unsigned long end_vm;
extern unsigned long start_vm;
-extern unsigned long highmem;
+extern unsigned long long highmem;
extern char host_info[];
@@ -52,13 +55,13 @@ extern int get_pty(void);
extern void *um_kmalloc(int size);
extern int switcheroo(int fd, int prot, void *from, void *to, int size);
extern void do_exec(int old_pid, int new_pid);
-extern void tracer_panic(char *msg, ...);
+extern void tracer_panic(char *msg, ...)
+ __attribute__ ((format (printf, 1, 2)));
extern int detach(int pid, int sig);
extern int attach(int pid);
extern void kill_child_dead(int pid);
extern int cont(int pid);
extern void check_sigio(void);
-extern void write_sigio_workaround(void);
extern void arch_check_bugs(void);
extern int cpu_feature(char *what, char *buf, int len);
extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 693018ba80f..fe08971b64c 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -7,23 +7,20 @@ extra-y := vmlinux.lds
clean-files :=
obj-y = config.o exec_kern.o exitcode.o \
- init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
- process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
+ init_task.o irq.o ksyms.o mem.o physmem.o \
+ process_kern.o ptrace.o reboot.o resource.o sigio_kern.o \
signal_kern.o smp.o syscall_kern.o sysrq.o \
time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o
obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
-obj-$(CONFIG_TTY_LOG) += tty_log.o
obj-$(CONFIG_SYSCALL_DEBUG) += syscall.o
obj-$(CONFIG_MODE_TT) += tt/
obj-$(CONFIG_MODE_SKAS) += skas/
-user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-
-USER_OBJS := $(user-objs-y) config.o tty_log.o
+USER_OBJS := config.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index c264e1c05ab..c0cb627bf59 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -22,6 +22,7 @@
void flush_thread(void)
{
+ arch_flush_thread(&current->thread.arch);
CHOOSE_MODE(flush_thread_tt(), flush_thread_skas());
}
@@ -30,8 +31,6 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
}
-extern void log_exec(char **argv, void *tty);
-
static long execve1(char *file, char __user * __user *argv,
char __user *__user *env)
{
@@ -60,14 +59,14 @@ long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
return(err);
}
-long sys_execve(char *file, char __user *__user *argv,
+long sys_execve(char __user *file, char __user *__user *argv,
char __user *__user *env)
{
long error;
char *filename;
lock_kernel();
- filename = getname((char __user *) file);
+ filename = getname(file);
error = PTR_ERR(filename);
if (IS_ERR(filename)) goto out;
error = execve1(filename, argv, env);
@@ -76,14 +75,3 @@ long sys_execve(char *file, char __user *__user *argv,
unlock_kernel();
return(error);
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index bbf94bf2921..2ffda012385 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -31,6 +31,8 @@
#include "irq_user.h"
#include "irq_kern.h"
#include "os.h"
+#include "sigio.h"
+#include "misc_constants.h"
/*
* Generic, controller-independent functions:
@@ -77,6 +79,299 @@ skip:
return 0;
}
+struct irq_fd *active_fds = NULL;
+static struct irq_fd **last_irq_ptr = &active_fds;
+
+extern void free_irqs(void);
+
+void sigio_handler(int sig, union uml_pt_regs *regs)
+{
+ struct irq_fd *irq_fd;
+ int n;
+
+ if (smp_sigio_handler())
+ return;
+
+ while (1) {
+ n = os_waiting_for_events(active_fds);
+ if (n <= 0) {
+ if(n == -EINTR) continue;
+ else break;
+ }
+
+ for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
+ if (irq_fd->current_events != 0) {
+ irq_fd->current_events = 0;
+ do_IRQ(irq_fd->irq, regs);
+ }
+ }
+ }
+
+ free_irqs();
+}
+
+static void maybe_sigio_broken(int fd, int type)
+{
+ if (os_isatty(fd)) {
+ if ((type == IRQ_WRITE) && !pty_output_sigio) {
+ write_sigio_workaround();
+ add_sigio_fd(fd, 0);
+ } else if ((type == IRQ_READ) && !pty_close_sigio) {
+ write_sigio_workaround();
+ add_sigio_fd(fd, 1);
+ }
+ }
+}
+
+int activate_fd(int irq, int fd, int type, void *dev_id)
+{
+ struct pollfd *tmp_pfd;
+ struct irq_fd *new_fd, *irq_fd;
+ unsigned long flags;
+ int pid, events, err, n;
+
+ pid = os_getpid();
+ err = os_set_fd_async(fd, pid);
+ if (err < 0)
+ goto out;
+
+ new_fd = um_kmalloc(sizeof(*new_fd));
+ err = -ENOMEM;
+ if (new_fd == NULL)
+ goto out;
+
+ if (type == IRQ_READ)
+ events = UM_POLLIN | UM_POLLPRI;
+ else
+ events = UM_POLLOUT;
+ *new_fd = ((struct irq_fd) { .next = NULL,
+ .id = dev_id,
+ .fd = fd,
+ .type = type,
+ .irq = irq,
+ .pid = pid,
+ .events = events,
+ .current_events = 0 } );
+
+ /* Critical section - locked by a spinlock because this stuff can
+ * be changed from interrupt handlers. The stuff above is done
+ * outside the lock because it allocates memory.
+ */
+
+ /* Actually, it only looks like it can be called from interrupt
+ * context. The culprit is reactivate_fd, which calls
+ * maybe_sigio_broken, which calls write_sigio_workaround,
+ * which calls activate_fd. However, write_sigio_workaround should
+ * only be called once, at boot time. That would make it clear that
+ * this is called only from process context, and can be locked with
+ * a semaphore.
+ */
+ flags = irq_lock();
+ for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
+ if ((irq_fd->fd == fd) && (irq_fd->type == type)) {
+ printk("Registering fd %d twice\n", fd);
+ printk("Irqs : %d, %d\n", irq_fd->irq, irq);
+ printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id);
+ goto out_unlock;
+ }
+ }
+
+ /*-------------*/
+ if (type == IRQ_WRITE)
+ fd = -1;
+
+ tmp_pfd = NULL;
+ n = 0;
+
+ while (1) {
+ n = os_create_pollfd(fd, events, tmp_pfd, n);
+ if (n == 0)
+ break;
+
+ /* n > 0
+ * It means we couldn't put new pollfd to current pollfds
+ * and tmp_fds is NULL or too small for new pollfds array.
+ * Needed size is equal to n as minimum.
+ *
+ * Here we have to drop the lock in order to call
+ * kmalloc, which might sleep.
+ * If something else came in and changed the pollfds array
+ * so we will not be able to put new pollfd struct to pollfds
+ * then we free the buffer tmp_fds and try again.
+ */
+ irq_unlock(flags);
+ kfree(tmp_pfd);
+ tmp_pfd = NULL;
+
+ tmp_pfd = um_kmalloc(n);
+ if (tmp_pfd == NULL)
+ goto out_kfree;
+
+ flags = irq_lock();
+ }
+ /*-------------*/
+
+ *last_irq_ptr = new_fd;
+ last_irq_ptr = &new_fd->next;
+
+ irq_unlock(flags);
+
+ /* This calls activate_fd, so it has to be outside the critical
+ * section.
+ */
+ maybe_sigio_broken(fd, type);
+
+ return(0);
+
+ out_unlock:
+ irq_unlock(flags);
+ out_kfree:
+ kfree(new_fd);
+ out:
+ return(err);
+}
+
+static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
+{
+ unsigned long flags;
+
+ flags = irq_lock();
+ os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr);
+ irq_unlock(flags);
+}
+
+struct irq_and_dev {
+ int irq;
+ void *dev;
+};
+
+static int same_irq_and_dev(struct irq_fd *irq, void *d)
+{
+ struct irq_and_dev *data = d;
+
+ return ((irq->irq == data->irq) && (irq->id == data->dev));
+}
+
+void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
+{
+ struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq,
+ .dev = dev });
+
+ free_irq_by_cb(same_irq_and_dev, &data);
+}
+
+static int same_fd(struct irq_fd *irq, void *fd)
+{
+ return (irq->fd == *((int *)fd));
+}
+
+void free_irq_by_fd(int fd)
+{
+ free_irq_by_cb(same_fd, &fd);
+}
+
+static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
+{
+ struct irq_fd *irq;
+ int i = 0;
+ int fdi;
+
+ for (irq = active_fds; irq != NULL; irq = irq->next) {
+ if ((irq->fd == fd) && (irq->irq == irqnum))
+ break;
+ i++;
+ }
+ if (irq == NULL) {
+ printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
+ goto out;
+ }
+ fdi = os_get_pollfd(i);
+ if ((fdi != -1) && (fdi != fd)) {
+ printk("find_irq_by_fd - mismatch between active_fds and "
+ "pollfds, fd %d vs %d, need %d\n", irq->fd,
+ fdi, fd);
+ irq = NULL;
+ goto out;
+ }
+ *index_out = i;
+ out:
+ return irq;
+}
+
+void reactivate_fd(int fd, int irqnum)
+{
+ struct irq_fd *irq;
+ unsigned long flags;
+ int i;
+
+ flags = irq_lock();
+ irq = find_irq_by_fd(fd, irqnum, &i);
+ if (irq == NULL) {
+ irq_unlock(flags);
+ return;
+ }
+ os_set_pollfd(i, irq->fd);
+ irq_unlock(flags);
+
+ /* This calls activate_fd, so it has to be outside the critical
+ * section.
+ */
+ maybe_sigio_broken(fd, irq->type);
+}
+
+void deactivate_fd(int fd, int irqnum)
+{
+ struct irq_fd *irq;
+ unsigned long flags;
+ int i;
+
+ flags = irq_lock();
+ irq = find_irq_by_fd(fd, irqnum, &i);
+ if (irq == NULL)
+ goto out;
+ os_set_pollfd(i, -1);
+ out:
+ irq_unlock(flags);
+}
+
+int deactivate_all_fds(void)
+{
+ struct irq_fd *irq;
+ int err;
+
+ for (irq = active_fds; irq != NULL; irq = irq->next) {
+ err = os_clear_fd_async(irq->fd);
+ if (err)
+ return err;
+ }
+ /* If there is a signal already queued, after unblocking ignore it */
+ os_set_ioignore();
+
+ return 0;
+}
+
+void forward_interrupts(int pid)
+{
+ struct irq_fd *irq;
+ unsigned long flags;
+ int err;
+
+ flags = irq_lock();
+ for (irq = active_fds; irq != NULL; irq = irq->next) {
+ err = os_set_owner(irq->fd, pid);
+ if (err < 0) {
+ /* XXX Just remove the irq rather than
+ * print out an infinite stream of these
+ */
+ printk("Failed to forward %d to pid %d, err = %d\n",
+ irq->fd, pid, -err);
+ }
+
+ irq->pid = pid;
+ }
+ irq_unlock(flags);
+}
+
/*
* do_IRQ handles all normal device IRQ's (the special
* SMP cross-CPU interrupts have their own specific
@@ -85,7 +380,7 @@ skip:
unsigned int do_IRQ(int irq, union uml_pt_regs *regs)
{
irq_enter();
- __do_IRQ(irq, (struct pt_regs *) regs);
+ __do_IRQ(irq, (struct pt_regs *)regs);
irq_exit();
return 1;
}
@@ -98,12 +393,12 @@ int um_request_irq(unsigned int irq, int fd, int type,
int err;
err = request_irq(irq, handler, irqflags, devname, dev_id);
- if(err)
- return(err);
+ if (err)
+ return err;
- if(fd != -1)
+ if (fd != -1)
err = activate_fd(irq, fd, type, dev_id);
- return(err);
+ return err;
}
EXPORT_SYMBOL(um_request_irq);
EXPORT_SYMBOL(reactivate_fd);
@@ -115,7 +410,7 @@ unsigned long irq_lock(void)
unsigned long flags;
spin_lock_irqsave(&irq_spinlock, flags);
- return(flags);
+ return flags;
}
void irq_unlock(unsigned long flags)
@@ -158,7 +453,7 @@ void __init init_IRQ(void)
irq_desc[TIMER_IRQ].depth = 1;
irq_desc[TIMER_IRQ].handler = &SIGVTALRM_irq_type;
enable_irq(TIMER_IRQ);
- for(i=1;i<NR_IRQS;i++){
+ for (i = 1; i < NR_IRQS; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = NULL;
irq_desc[i].depth = 1;
@@ -173,7 +468,7 @@ int init_aio_irq(int irq, char *name, irqreturn_t (*handler)(int, void *,
int fds[2], err;
err = os_pipe(fds, 1, 1);
- if(err){
+ if (err) {
printk("init_aio_irq - os_pipe failed, err = %d\n", -err);
goto out;
}
@@ -181,7 +476,7 @@ int init_aio_irq(int irq, char *name, irqreturn_t (*handler)(int, void *,
err = um_request_irq(irq, fds[0], IRQ_READ, handler,
SA_INTERRUPT | SA_SAMPLE_RANDOM, name,
(void *) (long) fds[0]);
- if(err){
+ if (err) {
printk("init_aio_irq - : um_request_irq failed, err = %d\n",
err);
goto out_close;
@@ -194,5 +489,5 @@ int init_aio_irq(int irq, char *name, irqreturn_t (*handler)(int, void *,
os_close_file(fds[0]);
os_close_file(fds[1]);
out:
- return(err);
+ return err;
}
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
deleted file mode 100644
index 0e32f5f4a88..00000000000
--- a/arch/um/kernel/irq_user.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "process.h"
-#include "sigio.h"
-#include "irq_user.h"
-#include "os.h"
-
-struct irq_fd {
- struct irq_fd *next;
- void *id;
- int fd;
- int type;
- int irq;
- int pid;
- int events;
- int current_events;
-};
-
-static struct irq_fd *active_fds = NULL;
-static struct irq_fd **last_irq_ptr = &active_fds;
-
-static struct pollfd *pollfds = NULL;
-static int pollfds_num = 0;
-static int pollfds_size = 0;
-
-extern int io_count, intr_count;
-
-extern void free_irqs(void);
-
-void sigio_handler(int sig, union uml_pt_regs *regs)
-{
- struct irq_fd *irq_fd;
- int i, n;
-
- if(smp_sigio_handler()) return;
- while(1){
- n = poll(pollfds, pollfds_num, 0);
- if(n < 0){
- if(errno == EINTR) continue;
- printk("sigio_handler : poll returned %d, "
- "errno = %d\n", n, errno);
- break;
- }
- if(n == 0) break;
-
- irq_fd = active_fds;
- for(i = 0; i < pollfds_num; i++){
- if(pollfds[i].revents != 0){
- irq_fd->current_events = pollfds[i].revents;
- pollfds[i].fd = -1;
- }
- irq_fd = irq_fd->next;
- }
-
- for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
- if(irq_fd->current_events != 0){
- irq_fd->current_events = 0;
- do_IRQ(irq_fd->irq, regs);
- }
- }
- }
-
- free_irqs();
-}
-
-int activate_ipi(int fd, int pid)
-{
- return(os_set_fd_async(fd, pid));
-}
-
-static void maybe_sigio_broken(int fd, int type)
-{
- if(isatty(fd)){
- if((type == IRQ_WRITE) && !pty_output_sigio){
- write_sigio_workaround();
- add_sigio_fd(fd, 0);
- }
- else if((type == IRQ_READ) && !pty_close_sigio){
- write_sigio_workaround();
- add_sigio_fd(fd, 1);
- }
- }
-}
-
-int activate_fd(int irq, int fd, int type, void *dev_id)
-{
- struct pollfd *tmp_pfd;
- struct irq_fd *new_fd, *irq_fd;
- unsigned long flags;
- int pid, events, err, n, size;
-
- pid = os_getpid();
- err = os_set_fd_async(fd, pid);
- if(err < 0)
- goto out;
-
- new_fd = um_kmalloc(sizeof(*new_fd));
- err = -ENOMEM;
- if(new_fd == NULL)
- goto out;
-
- if(type == IRQ_READ) events = POLLIN | POLLPRI;
- else events = POLLOUT;
- *new_fd = ((struct irq_fd) { .next = NULL,
- .id = dev_id,
- .fd = fd,
- .type = type,
- .irq = irq,
- .pid = pid,
- .events = events,
- .current_events = 0 } );
-
- /* Critical section - locked by a spinlock because this stuff can
- * be changed from interrupt handlers. The stuff above is done
- * outside the lock because it allocates memory.
- */
-
- /* Actually, it only looks like it can be called from interrupt
- * context. The culprit is reactivate_fd, which calls
- * maybe_sigio_broken, which calls write_sigio_workaround,
- * which calls activate_fd. However, write_sigio_workaround should
- * only be called once, at boot time. That would make it clear that
- * this is called only from process context, and can be locked with
- * a semaphore.
- */
- flags = irq_lock();
- for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
- if((irq_fd->fd == fd) && (irq_fd->type == type)){
- printk("Registering fd %d twice\n", fd);
- printk("Irqs : %d, %d\n", irq_fd->irq, irq);
- printk("Ids : 0x%x, 0x%x\n", irq_fd->id, dev_id);
- goto out_unlock;
- }
- }
-
- n = pollfds_num;
- if(n == pollfds_size){
- while(1){
- /* Here we have to drop the lock in order to call
- * kmalloc, which might sleep. If something else
- * came in and changed the pollfds array, we free
- * the buffer and try again.
- */
- irq_unlock(flags);
- size = (pollfds_num + 1) * sizeof(pollfds[0]);
- tmp_pfd = um_kmalloc(size);
- flags = irq_lock();
- if(tmp_pfd == NULL)
- goto out_unlock;
- if(n == pollfds_size)
- break;
- kfree(tmp_pfd);
- }
- if(pollfds != NULL){
- memcpy(tmp_pfd, pollfds,
- sizeof(pollfds[0]) * pollfds_size);
- kfree(pollfds);
- }
- pollfds = tmp_pfd;
- pollfds_size++;
- }
-
- if(type == IRQ_WRITE)
- fd = -1;
-
- pollfds[pollfds_num] = ((struct pollfd) { .fd = fd,
- .events = events,
- .revents = 0 });
- pollfds_num++;
-
- *last_irq_ptr = new_fd;
- last_irq_ptr = &new_fd->next;
-
- irq_unlock(flags);
-
- /* This calls activate_fd, so it has to be outside the critical
- * section.
- */
- maybe_sigio_broken(fd, type);
-
- return(0);
-
- out_unlock:
- irq_unlock(flags);
- kfree(new_fd);
- out:
- return(err);
-}
-
-static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
-{
- struct irq_fd **prev;
- unsigned long flags;
- int i = 0;
-
- flags = irq_lock();
- prev = &active_fds;
- while(*prev != NULL){
- if((*test)(*prev, arg)){
- struct irq_fd *old_fd = *prev;
- if((pollfds[i].fd != -1) &&
- (pollfds[i].fd != (*prev)->fd)){
- printk("free_irq_by_cb - mismatch between "
- "active_fds and pollfds, fd %d vs %d\n",
- (*prev)->fd, pollfds[i].fd);
- goto out;
- }
-
- pollfds_num--;
-
- /* This moves the *whole* array after pollfds[i] (though
- * it doesn't spot as such)! */
-
- memmove(&pollfds[i], &pollfds[i + 1],
- (pollfds_num - i) * sizeof(pollfds[0]));
-
- if(last_irq_ptr == &old_fd->next)
- last_irq_ptr = prev;
- *prev = (*prev)->next;
- if(old_fd->type == IRQ_WRITE)
- ignore_sigio_fd(old_fd->fd);
- kfree(old_fd);
- continue;
- }
- prev = &(*prev)->next;
- i++;
- }
- out:
- irq_unlock(flags);
-}
-
-struct irq_and_dev {
- int irq;
- void *dev;
-};
-
-static int same_irq_and_dev(struct irq_fd *irq, void *d)
-{
- struct irq_and_dev *data = d;
-
- return((irq->irq == data->irq) && (irq->id == data->dev));
-}
-
-void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
-{
- struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq,
- .dev = dev });
-
- free_irq_by_cb(same_irq_and_dev, &data);
-}
-
-static int same_fd(struct irq_fd *irq, void *fd)
-{
- return(irq->fd == *((int *) fd));
-}
-
-void free_irq_by_fd(int fd)
-{
- free_irq_by_cb(same_fd, &fd);
-}
-
-static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
-{
- struct irq_fd *irq;
- int i = 0;
-
- for(irq=active_fds; irq != NULL; irq = irq->next){
- if((irq->fd == fd) && (irq->irq == irqnum)) break;
- i++;
- }
- if(irq == NULL){
- printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
- goto out;
- }
- if((pollfds[i].fd != -1) && (pollfds[i].fd != fd)){
- printk("find_irq_by_fd - mismatch between active_fds and "
- "pollfds, fd %d vs %d, need %d\n", irq->fd,
- pollfds[i].fd, fd);
- irq = NULL;
- goto out;
- }
- *index_out = i;
- out:
- return(irq);
-}
-
-void reactivate_fd(int fd, int irqnum)
-{
- struct irq_fd *irq;
- unsigned long flags;
- int i;
-
- flags = irq_lock();
- irq = find_irq_by_fd(fd, irqnum, &i);
- if(irq == NULL){
- irq_unlock(flags);
- return;
- }
-
- pollfds[i].fd = irq->fd;
-
- irq_unlock(flags);
-
- /* This calls activate_fd, so it has to be outside the critical
- * section.
- */
- maybe_sigio_broken(fd, irq->type);
-}
-
-void deactivate_fd(int fd, int irqnum)
-{
- struct irq_fd *irq;
- unsigned long flags;
- int i;
-
- flags = irq_lock();
- irq = find_irq_by_fd(fd, irqnum, &i);
- if(irq == NULL)
- goto out;
- pollfds[i].fd = -1;
- out:
- irq_unlock(flags);
-}
-
-int deactivate_all_fds(void)
-{
- struct irq_fd *irq;
- int err;
-
- for(irq=active_fds;irq != NULL;irq = irq->next){
- err = os_clear_fd_async(irq->fd);
- if(err)
- return(err);
- }
- /* If there is a signal already queued, after unblocking ignore it */
- set_handler(SIGIO, SIG_IGN, 0, -1);
-
- return(0);
-}
-
-void forward_ipi(int fd, int pid)
-{
- int err;
-
- err = os_set_owner(fd, pid);
- if(err < 0)
- printk("forward_ipi: set_owner failed, fd = %d, me = %d, "
- "target = %d, err = %d\n", fd, os_getpid(), pid, -err);
-}
-
-void forward_interrupts(int pid)
-{
- struct irq_fd *irq;
- unsigned long flags;
- int err;
-
- flags = irq_lock();
- for(irq=active_fds;irq != NULL;irq = irq->next){
- err = os_set_owner(irq->fd, pid);
- if(err < 0){
- /* XXX Just remove the irq rather than
- * print out an infinite stream of these
- */
- printk("Failed to forward %d to pid %d, err = %d\n",
- irq->fd, pid, -err);
- }
-
- irq->pid = pid;
- }
- irq_unlock(flags);
-}
-
-void init_irq_signals(int on_sigstack)
-{
- __sighandler_t h;
- int flags;
-
- flags = on_sigstack ? SA_ONSTACK : 0;
- if(timer_irq_inited) h = (__sighandler_t) alarm_handler;
- else h = boot_timer_handler;
-
- set_handler(SIGVTALRM, h, flags | SA_RESTART,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
- set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- signal(SIGWINCH, SIG_IGN);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 7713e7a6f47..432cf0b97a1 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -39,7 +39,6 @@ EXPORT_SYMBOL(um_virt_to_phys);
EXPORT_SYMBOL(mode_tt);
EXPORT_SYMBOL(handle_page_fault);
EXPORT_SYMBOL(find_iomem);
-EXPORT_SYMBOL(end_iomem);
#ifdef CONFIG_MODE_TT
EXPORT_SYMBOL(strncpy_from_user_tt);
@@ -89,12 +88,10 @@ EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(do_gettimeofday);
EXPORT_SYMBOL(do_settimeofday);
-/* This is here because UML expands open to sys_open, not to a system
+/* This is here because UML expands lseek to sys_lseek, not to a system
* call instruction.
*/
-EXPORT_SYMBOL(sys_open);
EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_read);
EXPORT_SYMBOL(sys_wait4);
#ifdef CONFIG_SMP
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 92cce96b5e2..44e41a35f00 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -30,7 +30,7 @@ extern char __binary_start;
unsigned long *empty_zero_page = NULL;
unsigned long *empty_bad_page = NULL;
pgd_t swapper_pg_dir[PTRS_PER_PGD];
-unsigned long highmem;
+unsigned long long highmem;
int kmalloc_ok = 0;
static unsigned long brk_end;
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index 0e65340eee3..fc0f0b085ca 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -9,6 +9,7 @@
#include "linux/vmalloc.h"
#include "linux/bootmem.h"
#include "linux/module.h"
+#include "linux/pfn.h"
#include "asm/types.h"
#include "asm/pgtable.h"
#include "kern_util.h"
@@ -316,8 +317,6 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
}
}
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-
extern int __syscall_stub_start, __binary_start;
void setup_physmem(unsigned long start, unsigned long reserve_end,
@@ -408,6 +407,8 @@ unsigned long find_iomem(char *driver, unsigned long *len_out)
*len_out = region->size;
return(region->virt);
}
+
+ region = region->next;
}
return(0);
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 3113cab8675..f6a5a502120 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -156,9 +156,25 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
unsigned long stack_top, struct task_struct * p,
struct pt_regs *regs)
{
+ int ret;
+
p->thread = (struct thread_struct) INIT_THREAD;
- return(CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
- clone_flags, sp, stack_top, p, regs));
+ ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
+ clone_flags, sp, stack_top, p, regs);
+
+ if (ret || !current->thread.forking)
+ goto out;
+
+ clear_flushed_tls(p);
+
+ /*
+ * Set a new TLS for the child thread?
+ */
+ if (clone_flags & CLONE_SETTLS)
+ ret = arch_copy_tls(p);
+
+out:
+ return ret;
}
void initial_thread_cb(void (*proc)(void *), void *arg)
@@ -185,10 +201,6 @@ void default_idle(void)
{
CHOOSE_MODE(uml_idle_timer(), (void) 0);
- atomic_inc(&init_mm.mm_count);
- current->mm = &init_mm;
- current->active_mm = &init_mm;
-
while(1){
/* endless idle loop with no priority at all */
@@ -407,7 +419,7 @@ static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int
return strlen(buf);
}
-static int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data)
+static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data)
{
char tmp[2];
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 98e09395c09..9a77fb3c269 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -46,6 +46,7 @@ extern int poke_user(struct task_struct * child, long addr, long data);
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
int i, ret;
+ unsigned long __user *p = (void __user *)(unsigned long)data;
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
@@ -58,7 +59,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
if (copied != sizeof(tmp))
break;
- ret = put_user(tmp, (unsigned long __user *) data);
+ ret = put_user(tmp, p);
break;
}
@@ -136,15 +137,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#ifdef PTRACE_GETREGS
case PTRACE_GETREGS: { /* Get all gp regs from the child. */
- if (!access_ok(VERIFY_WRITE, (unsigned long *)data,
- MAX_REG_OFFSET)) {
+ if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) {
ret = -EIO;
break;
}
for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
- __put_user(getreg(child, i),
- (unsigned long __user *) data);
- data += sizeof(long);
+ __put_user(getreg(child, i), p);
+ p++;
}
ret = 0;
break;
@@ -153,15 +152,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#ifdef PTRACE_SETREGS
case PTRACE_SETREGS: { /* Set all gp regs in the child. */
unsigned long tmp = 0;
- if (!access_ok(VERIFY_READ, (unsigned *)data,
- MAX_REG_OFFSET)) {
+ if (!access_ok(VERIFY_READ, p, MAX_REG_OFFSET)) {
ret = -EIO;
break;
}
for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
- __get_user(tmp, (unsigned long __user *) data);
+ __get_user(tmp, p);
putreg(child, i, tmp);
- data += sizeof(long);
+ p++;
}
ret = 0;
break;
@@ -187,14 +185,23 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = set_fpxregs(data, child);
break;
#endif
+ case PTRACE_GET_THREAD_AREA:
+ ret = ptrace_get_thread_area(child, addr,
+ (struct user_desc __user *) data);
+ break;
+
+ case PTRACE_SET_THREAD_AREA:
+ ret = ptrace_set_thread_area(child, addr,
+ (struct user_desc __user *) data);
+ break;
+
case PTRACE_FAULTINFO: {
- /* Take the info from thread->arch->faultinfo,
- * but transfer max. sizeof(struct ptrace_faultinfo).
- * On i386, ptrace_faultinfo is smaller!
- */
- ret = copy_to_user((unsigned long __user *) data,
- &child->thread.arch.faultinfo,
- sizeof(struct ptrace_faultinfo));
+ /* Take the info from thread->arch->faultinfo,
+ * but transfer max. sizeof(struct ptrace_faultinfo).
+ * On i386, ptrace_faultinfo is smaller!
+ */
+ ret = copy_to_user(p, &child->thread.arch.faultinfo,
+ sizeof(struct ptrace_faultinfo));
if(ret)
break;
break;
@@ -204,8 +211,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_LDT: {
struct ptrace_ldt ldt;
- if(copy_from_user(&ldt, (unsigned long __user *) data,
- sizeof(ldt))){
+ if(copy_from_user(&ldt, p, sizeof(ldt))){
ret = -EIO;
break;
}
@@ -269,15 +275,13 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
if (unlikely(current->audit_context)) {
if (!entryexit)
- audit_syscall_entry(current,
- HOST_AUDIT_ARCH,
+ audit_syscall_entry(HOST_AUDIT_ARCH,
UPT_SYSCALL_NR(regs),
UPT_SYSCALL_ARG1(regs),
UPT_SYSCALL_ARG2(regs),
UPT_SYSCALL_ARG3(regs),
UPT_SYSCALL_ARG4(regs));
- else audit_syscall_exit(current,
- AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
+ else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
UPT_SYSCALL_RET(regs));
}
diff --git a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio_kern.c
index 229988463c4..1c1300fb1e9 100644
--- a/arch/um/kernel/sigio_kern.c
+++ b/arch/um/kernel/sigio_kern.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
@@ -12,13 +12,16 @@
#include "sigio.h"
#include "irq_user.h"
#include "irq_kern.h"
+#include "os.h"
/* Protected by sigio_lock() called from write_sigio_workaround */
static int sigio_irq_fd = -1;
static irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused)
{
- read_sigio_fd(sigio_irq_fd);
+ char c;
+
+ os_read_file(sigio_irq_fd, &c, sizeof(c));
reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
return(IRQ_HANDLED);
}
@@ -51,6 +54,9 @@ void sigio_unlock(void)
spin_unlock(&sigio_spinlock);
}
+extern void sigio_cleanup(void);
+__uml_exitcall(sigio_cleanup);
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 57181a920d4..ea3a8e409a6 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -6,9 +6,11 @@
obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \
syscall.o tlb.o uaccess.o
-USER_OBJS := clone.o
+# clone.o is in the stub, so it can't be built with profiling
+# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
+# disable it
-include arch/um/scripts/Makefile.rules
+CFLAGS_clone.o := $(CFLAGS_NO_HARDENING)
+UNPROFILE_OBJS := clone.o
-# clone.o is in the stub, so it can't be built with profiling
-$(obj)/clone.o : c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 3f70a2e12f0..2135eaf98a9 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -35,6 +35,8 @@ void switch_to_skas(void *prev, void *next)
switch_threads(&from->thread.mode.skas.switch_buf,
to->thread.mode.skas.switch_buf);
+ arch_switch_to_skas(current->thread.prev_sched, current);
+
if(current->pid == 0)
switch_timers(1);
}
@@ -89,10 +91,17 @@ void fork_handler(int sig)
panic("blech");
schedule_tail(current->thread.prev_sched);
+
+ /* XXX: if interrupt_end() calls schedule, this call to
+ * arch_switch_to_skas isn't needed. We could want to apply this to
+ * improve performance. -bb */
+ arch_switch_to_skas(current->thread.prev_sched, current);
+
current->thread.prev_sched = NULL;
/* Handle any immediate reschedules or signals */
interrupt_end();
+
userspace(&current->thread.regs.regs);
}
@@ -109,6 +118,8 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
handler = fork_handler;
+
+ arch_copy_thread(&current->thread.arch, &p->thread.arch);
}
else {
init_thread_registers(&p->thread.regs.regs);
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index 72113b0a96e..511116aebaf 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
@@ -77,9 +77,9 @@ static int idle_proc(void *cpup)
if(err < 0)
panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
- activate_ipi(cpu_data[cpu].ipi_pipe[0],
+ os_set_fd_async(cpu_data[cpu].ipi_pipe[0],
current->thread.mode.tt.extern_pid);
-
+
wmb();
if (cpu_test_and_set(cpu, cpu_callin_map)) {
printk("huh, CPU#%d already present??\n", cpu);
@@ -106,7 +106,7 @@ static struct task_struct *idle_thread(int cpu)
panic("copy_process failed in idle_thread, error = %ld",
PTR_ERR(new_task));
- cpu_tasks[cpu] = ((struct cpu_task)
+ cpu_tasks[cpu] = ((struct cpu_task)
{ .pid = new_task->thread.mode.tt.extern_pid,
.task = new_task } );
idle_threads[cpu] = new_task;
@@ -134,16 +134,15 @@ void smp_prepare_cpus(unsigned int maxcpus)
if(err < 0)
panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
- activate_ipi(cpu_data[me].ipi_pipe[0],
+ os_set_fd_async(cpu_data[me].ipi_pipe[0],
current->thread.mode.tt.extern_pid);
for(cpu = 1; cpu < ncpus; cpu++){
printk("Booting processor %d...\n", cpu);
-
+
idle = idle_thread(cpu);
init_idle(idle, cpu);
- unhash_process(idle);
waittime = 200000000;
while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
@@ -223,7 +222,7 @@ void smp_call_function_slave(int cpu)
atomic_inc(&scf_finished);
}
-int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
+int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
int wait)
{
int cpus = num_online_cpus() - 1;
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
index 8e1a3501ff4..37d3978337d 100644
--- a/arch/um/kernel/syscall_kern.c
+++ b/arch/um/kernel/syscall_kern.c
@@ -104,7 +104,7 @@ long sys_pipe(unsigned long __user * fildes)
}
-long sys_uname(struct old_utsname * name)
+long sys_uname(struct old_utsname __user * name)
{
long err;
if (!name)
@@ -115,7 +115,7 @@ long sys_uname(struct old_utsname * name)
return err?-EFAULT:0;
}
-long sys_olduname(struct oldold_utsname * name)
+long sys_olduname(struct oldold_utsname __user * name)
{
long error;
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 3c7626cdba4..86f51d04c98 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -84,6 +84,16 @@ void timer_irq(union uml_pt_regs *regs)
}
}
+
+void time_init_kern(void)
+{
+ unsigned long long nsecs;
+
+ nsecs = os_nsecs();
+ set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,
+ -nsecs % BILLION);
+}
+
void do_boot_timer_handler(struct sigcontext * sc)
{
struct pt_regs regs;
@@ -209,4 +219,4 @@ int __init timer_init(void)
return(0);
}
-__initcall(timer_init);
+arch_initcall(timer_init);
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index d56046c2aba..02f6d4d8dc3 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -198,7 +198,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
si.si_signo = SIGBUS;
si.si_errno = 0;
si.si_code = BUS_ADRERR;
- si.si_addr = (void *)address;
+ si.si_addr = (void __user *)address;
current->thread.arch.faultinfo = fi;
force_sig_info(SIGBUS, &si, current);
} else if (err == -ENOMEM) {
@@ -207,7 +207,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
} else {
BUG_ON(err != -EFAULT);
si.si_signo = SIGSEGV;
- si.si_addr = (void *) address;
+ si.si_addr = (void __user *) address;
current->thread.arch.faultinfo = fi;
force_sig_info(SIGSEGV, &si, current);
}
@@ -220,8 +220,8 @@ void bad_segv(struct faultinfo fi, unsigned long ip)
si.si_signo = SIGSEGV;
si.si_code = SEGV_ACCERR;
- si.si_addr = (void *) FAULT_ADDRESS(fi);
- current->thread.arch.faultinfo = fi;
+ si.si_addr = (void __user *) FAULT_ADDRESS(fi);
+ current->thread.arch.faultinfo = fi;
force_sig_info(SIGSEGV, &si, current);
}
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index 295c1ac817b..a9c1443fc54 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -51,6 +51,13 @@ void switch_to_tt(void *prev, void *next)
c = 0;
+ /* Notice that here we "up" the semaphore on which "to" is waiting, and
+ * below (the read) we wait on this semaphore (which is implemented by
+ * switch_pipe) and go sleeping. Thus, after that, we have resumed in
+ * "to", and can't use any more the value of "from" (which is outdated),
+ * nor the value in "to" (since it was the task which stole us the CPU,
+ * which we don't care about). */
+
err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
if(err != sizeof(c))
panic("write of switch_pipe failed, err = %d", -err);
@@ -77,7 +84,7 @@ void switch_to_tt(void *prev, void *next)
change_sig(SIGALRM, alrm);
change_sig(SIGPROF, prof);
- arch_switch();
+ arch_switch_to_tt(prev_sched, current);
flush_tlb_all();
local_irq_restore(flags);
@@ -141,7 +148,6 @@ static void new_thread_handler(int sig)
set_cmdline("(kernel thread)");
change_sig(SIGUSR1, 1);
- change_sig(SIGVTALRM, 1);
change_sig(SIGPROF, 1);
local_irq_enable();
if(!run_kernel_thread(fn, arg, &current->thread.exec_buf))
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 80c9c18aae9..7d51dd7201c 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -421,7 +421,7 @@ int linux_main(int argc, char **argv)
#ifndef CONFIG_HIGHMEM
highmem = 0;
printf("CONFIG_HIGHMEM not enabled - physical memory shrunk "
- "to %lu bytes\n", physmem_size);
+ "to %Lu bytes\n", physmem_size);
#endif
}
@@ -433,8 +433,8 @@ int linux_main(int argc, char **argv)
setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
if(init_maps(physmem_size, iomem_size, highmem)){
- printf("Failed to allocate mem_map for %lu bytes of physical "
- "memory and %lu bytes of highmem\n", physmem_size,
+ printf("Failed to allocate mem_map for %Lu bytes of physical "
+ "memory and %Lu bytes of highmem\n", physmem_size,
highmem);
exit(1);
}
@@ -477,7 +477,8 @@ static struct notifier_block panic_exit_notifier = {
void __init setup_arch(char **cmdline_p)
{
- notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &panic_exit_notifier);
paging_init();
strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
@@ -487,8 +488,7 @@ void __init setup_arch(char **cmdline_p)
void __init check_bugs(void)
{
arch_check_bugs();
- check_sigio();
- check_devanon();
+ os_check_bugs();
}
void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 08a4e628b24..f4bfc4c7cca 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,17 +3,17 @@
# Licensed under the GPL
#
-obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
- start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o user_syms.o \
- util.o drivers/ sys-$(SUBARCH)/
+obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \
+ signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o tls.o \
+ user_syms.o util.o drivers/ sys-$(SUBARCH)/
obj-$(CONFIG_MODE_SKAS) += skas/
+obj-$(CONFIG_TTY_LOG) += tty_log.o
+user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
- start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o util.o
-
-elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
-CFLAGS_elf_aux.o += -I$(objtree)/arch/um
+USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \
+ process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o tls.o \
+ uaccess.o umid.o util.o
CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c
index 6ae4b19d9f5..768606bec23 100644
--- a/arch/um/os-Linux/drivers/ethertap_kern.c
+++ b/arch/um/os-Linux/drivers/ethertap_kern.c
@@ -102,18 +102,7 @@ static struct transport ethertap_transport = {
static int register_ethertap(void)
{
register_transport(&ethertap_transport);
- return(1);
+ return 0;
}
__initcall(register_ethertap);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 901b85e8a1c..8f49507e64e 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -40,7 +40,7 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
int fd)
{
struct addr_change change;
- void *output;
+ char *output;
int n;
change.what = op;
diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c
index 4202b9ebad4..190009a6f89 100644
--- a/arch/um/os-Linux/drivers/tuntap_kern.c
+++ b/arch/um/os-Linux/drivers/tuntap_kern.c
@@ -87,18 +87,7 @@ static struct transport tuntap_transport = {
static int register_tuntap(void)
{
register_transport(&tuntap_transport);
- return(1);
+ return 0;
}
__initcall(register_tuntap);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 3bd10deea28..09251338d99 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -171,7 +171,7 @@ int os_sigio_async(int master, int slave)
flags = fcntl(master, F_GETFL);
if(flags < 0)
- return errno;
+ return -errno;
if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
(fcntl(master, F_SETOWN, os_getpid()) < 0))
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 6490a4ff40a..6987d1d247a 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -43,7 +43,7 @@ static int helper_child(void *arg)
(*data->pre_exec)(data->pre_data);
execvp(argv[0], argv);
errval = errno;
- printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
+ printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno);
os_write_file(data->fd, &errval, sizeof(errval));
kill(os_getpid(), SIGKILL);
return(0);
@@ -92,15 +92,15 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
close(fds[1]);
fds[1] = -1;
- /*Read the errno value from the child.*/
+ /* Read the errno value from the child, if the exec failed, or get 0 if
+ * the exec succeeded because the pipe fd was set as close-on-exec. */
n = os_read_file(fds[0], &ret, sizeof(ret));
- if(n < 0){
+ if (n < 0) {
printk("run_helper : read on pipe failed, ret = %d\n", -n);
ret = n;
kill(pid, SIGKILL);
CATCH_EINTR(waitpid(pid, NULL, 0));
- }
- else if(n != 0){
+ } else if(n != 0){
CATCH_EINTR(n = waitpid(pid, NULL, 0));
ret = -errno;
} else {
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
new file mode 100644
index 00000000000..3788d4568d3
--- /dev/null
+++ b/arch/um/os-Linux/irq.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include "user_util.h"
+#include "kern_util.h"
+#include "user.h"
+#include "process.h"
+#include "sigio.h"
+#include "irq_user.h"
+#include "os.h"
+
+static struct pollfd *pollfds = NULL;
+static int pollfds_num = 0;
+static int pollfds_size = 0;
+
+int os_waiting_for_events(struct irq_fd *active_fds)
+{
+ struct irq_fd *irq_fd;
+ int i, n, err;
+
+ n = poll(pollfds, pollfds_num, 0);
+ if (n < 0) {
+ err = -errno;
+ if (errno != EINTR)
+ printk("sigio_handler: os_waiting_for_events:"
+ " poll returned %d, errno = %d\n", n, errno);
+ return err;
+ }
+
+ if (n == 0)
+ return 0;
+
+ irq_fd = active_fds;
+
+ for (i = 0; i < pollfds_num; i++) {
+ if (pollfds[i].revents != 0) {
+ irq_fd->current_events = pollfds[i].revents;
+ pollfds[i].fd = -1;
+ }
+ irq_fd = irq_fd->next;
+ }
+ return n;
+}
+
+int os_isatty(int fd)
+{
+ return isatty(fd);
+}
+
+int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds)
+{
+ if (pollfds_num == pollfds_size) {
+ if (size_tmpfds <= pollfds_size * sizeof(pollfds[0])) {
+ /* return min size needed for new pollfds area */
+ return((pollfds_size + 1) * sizeof(pollfds[0]));
+ }
+
+ if (pollfds != NULL) {
+ memcpy(tmp_pfd, pollfds,
+ sizeof(pollfds[0]) * pollfds_size);
+ /* remove old pollfds */
+ kfree(pollfds);
+ }
+ pollfds = tmp_pfd;
+ pollfds_size++;
+ } else
+ kfree(tmp_pfd); /* remove not used tmp_pfd */
+
+ pollfds[pollfds_num] = ((struct pollfd) { .fd = fd,
+ .events = events,
+ .revents = 0 });
+ pollfds_num++;
+
+ return 0;
+}
+
+void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
+ struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2)
+{
+ struct irq_fd **prev;
+ int i = 0;
+
+ prev = &active_fds;
+ while (*prev != NULL) {
+ if ((*test)(*prev, arg)) {
+ struct irq_fd *old_fd = *prev;
+ if ((pollfds[i].fd != -1) &&
+ (pollfds[i].fd != (*prev)->fd)) {
+ printk("os_free_irq_by_cb - mismatch between "
+ "active_fds and pollfds, fd %d vs %d\n",
+ (*prev)->fd, pollfds[i].fd);
+ goto out;
+ }
+
+ pollfds_num--;
+
+ /* This moves the *whole* array after pollfds[i]
+ * (though it doesn't spot as such)!
+ */
+ memmove(&pollfds[i], &pollfds[i + 1],
+ (pollfds_num - i) * sizeof(pollfds[0]));
+ if(*last_irq_ptr2 == &old_fd->next)
+ *last_irq_ptr2 = prev;
+
+ *prev = (*prev)->next;
+ if(old_fd->type == IRQ_WRITE)
+ ignore_sigio_fd(old_fd->fd);
+ kfree(old_fd);
+ continue;
+ }
+ prev = &(*prev)->next;
+ i++;
+ }
+ out:
+ return;
+}
+
+int os_get_pollfd(int i)
+{
+ return pollfds[i].fd;
+}
+
+void os_set_pollfd(int i, int fd)
+{
+ pollfds[i].fd = fd;
+}
+
+void os_set_ioignore(void)
+{
+ set_handler(SIGIO, SIG_IGN, 0, -1);
+}
+
+void init_irq_signals(int on_sigstack)
+{
+ __sighandler_t h;
+ int flags;
+
+ flags = on_sigstack ? SA_ONSTACK : 0;
+ if (timer_irq_inited)
+ h = (__sighandler_t)alarm_handler;
+ else
+ h = boot_timer_handler;
+
+ set_handler(SIGVTALRM, h, flags | SA_RESTART,
+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
+ set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ signal(SIGWINCH, SIG_IGN);
+}
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 2878e89a674..90912aaca7a 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -59,7 +59,7 @@ static __init void do_uml_initcalls(void)
initcall_t *call;
call = &__uml_initcall_start;
- while (call < &__uml_initcall_end){;
+ while (call < &__uml_initcall_end){
(*call)();
call++;
}
@@ -74,6 +74,34 @@ static void last_ditch_exit(int sig)
exit(1);
}
+#define UML_LIB_PATH ":/usr/lib/uml"
+
+static void setup_env_path(void)
+{
+ char *new_path = NULL;
+ char *old_path = NULL;
+ int path_len = 0;
+
+ old_path = getenv("PATH");
+ /* if no PATH variable is set or it has an empty value
+ * just use the default + /usr/lib/uml
+ */
+ if (!old_path || (path_len = strlen(old_path)) == 0) {
+ putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH);
+ return;
+ }
+
+ /* append /usr/lib/uml to the existing path */
+ path_len += strlen("PATH=" UML_LIB_PATH) + 1;
+ new_path = malloc(path_len);
+ if (!new_path) {
+ perror("coudn't malloc to set a new PATH");
+ return;
+ }
+ snprintf(new_path, path_len, "PATH=%s" UML_LIB_PATH, old_path);
+ putenv(new_path);
+}
+
extern int uml_exitcode;
extern void scan_elf_aux( char **envp);
@@ -114,6 +142,8 @@ int main(int argc, char **argv, char **envp)
set_stklim();
+ setup_env_path();
+
new_argv = malloc((argc + 1) * sizeof(char *));
if(new_argv == NULL){
perror("Mallocing argv");
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 9d7d69a523b..c6432e72924 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -8,6 +8,7 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
+#include <sys/statfs.h>
#include "kern_util.h"
#include "user.h"
#include "user_util.h"
@@ -19,6 +20,7 @@
#include <sys/param.h>
+static char *default_tmpdir = "/tmp";
static char *tempdir = NULL;
static void __init find_tempdir(void)
@@ -34,7 +36,7 @@ static void __init find_tempdir(void)
break;
}
if((dir == NULL) || (*dir == '\0'))
- dir = "/tmp";
+ dir = default_tmpdir;
tempdir = malloc(strlen(dir) + 2);
if(tempdir == NULL){
@@ -46,6 +48,96 @@ static void __init find_tempdir(void)
strcat(tempdir, "/");
}
+/* This will return 1, with the first character in buf being the
+ * character following the next instance of c in the file. This will
+ * read the file as needed. If there's an error, -errno is returned;
+ * if the end of the file is reached, 0 is returned.
+ */
+static int next(int fd, char *buf, int size, char c)
+{
+ int n;
+ char *ptr;
+
+ while((ptr = strchr(buf, c)) == NULL){
+ n = read(fd, buf, size - 1);
+ if(n == 0)
+ return 0;
+ else if(n < 0)
+ return -errno;
+
+ buf[n] = '\0';
+ }
+
+ ptr++;
+ memmove(buf, ptr, strlen(ptr) + 1);
+ return 1;
+}
+
+static int checked_tmpdir = 0;
+
+/* Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner
+ * way to do this than to parse /proc/mounts. statfs will return the
+ * same filesystem magic number and fs id for both /dev and /dev/shm
+ * when they are both tmpfs, so you can't tell if they are different
+ * filesystems. Also, there seems to be no other way of finding the
+ * mount point of a filesystem from within it.
+ *
+ * If a /dev/shm tmpfs entry is found, then we switch to using it.
+ * Otherwise, we stay with the default /tmp.
+ */
+static void which_tmpdir(void)
+{
+ int fd, found;
+ char buf[128] = { '\0' };
+
+ if(checked_tmpdir)
+ return;
+
+ checked_tmpdir = 1;
+
+ printf("Checking for tmpfs mount on /dev/shm...");
+
+ fd = open("/proc/mounts", O_RDONLY);
+ if(fd < 0){
+ printf("failed to open /proc/mounts, errno = %d\n", errno);
+ return;
+ }
+
+ while(1){
+ found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+ if(found != 1)
+ break;
+
+ if(!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
+ goto found;
+
+ found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n');
+ if(found != 1)
+ break;
+ }
+
+err:
+ if(found == 0)
+ printf("nothing mounted on /dev/shm\n");
+ else if(found < 0)
+ printf("read returned errno %d\n", -found);
+
+ return;
+
+found:
+ found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+ if(found != 1)
+ goto err;
+
+ if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
+ printf("not tmpfs\n");
+ return;
+ }
+
+ printf("OK\n");
+ default_tmpdir = "/dev/shm";
+}
+
/*
* This proc still used in tt-mode
* (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
@@ -53,33 +145,37 @@ static void __init find_tempdir(void)
*/
int make_tempfile(const char *template, char **out_tempname, int do_unlink)
{
- char tempname[MAXPATHLEN];
+ char *tempname;
int fd;
+ which_tmpdir();
+ tempname = malloc(MAXPATHLEN);
+
find_tempdir();
- if (*template != '/')
+ if (template[0] != '/')
strcpy(tempname, tempdir);
else
- *tempname = 0;
+ tempname[0] = '\0';
strcat(tempname, template);
fd = mkstemp(tempname);
if(fd < 0){
fprintf(stderr, "open - cannot create %s: %s\n", tempname,
strerror(errno));
- return -1;
+ goto out;
}
if(do_unlink && (unlink(tempname) < 0)){
perror("unlink");
- return -1;
+ goto out;
}
if(out_tempname){
- *out_tempname = strdup(tempname);
- if(*out_tempname == NULL){
- perror("strdup");
- return -1;
- }
+ *out_tempname = tempname;
+ } else {
+ free(tempname);
}
return(fd);
+out:
+ free(tempname);
+ return -1;
}
#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
@@ -121,36 +217,11 @@ int create_tmp_file(unsigned long long len)
return(fd);
}
-static int create_anon_file(unsigned long long len)
-{
- void *addr;
- int fd;
-
- fd = open("/dev/anon", O_RDWR);
- if(fd < 0) {
- perror("opening /dev/anon");
- exit(1);
- }
-
- addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- if(addr == MAP_FAILED){
- perror("mapping physmem file");
- exit(1);
- }
- munmap(addr, len);
-
- return(fd);
-}
-
-extern int have_devanon;
-
int create_mem_file(unsigned long long len)
{
int err, fd;
- if(have_devanon)
- fd = create_anon_file(len);
- else fd = create_tmp_file(len);
+ fd = create_tmp_file(len);
err = os_set_exec_close(fd, 1);
if(err < 0){
@@ -159,3 +230,26 @@ int create_mem_file(unsigned long long len)
}
return(fd);
}
+
+
+void check_tmpexec(void)
+{
+ void *addr;
+ int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
+
+ addr = mmap(NULL, UM_KERN_PAGE_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
+ printf("Checking PROT_EXEC mmap in %s...",tempdir);
+ fflush(stdout);
+ if(addr == MAP_FAILED){
+ err = errno;
+ perror("failed");
+ if(err == EPERM)
+ printf("%s must be not mounted noexec\n",tempdir);
+ exit(1);
+ }
+ printf("OK\n");
+ munmap(addr, UM_KERN_PAGE_SIZE);
+
+ close(fd);
+}
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index d261888f39c..233be2f4f8c 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -11,6 +11,7 @@
#include <linux/unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
+#include <sys/mman.h>
#include "ptrace_user.h"
#include "os.h"
#include "user.h"
@@ -20,6 +21,7 @@
#include "kern_util.h"
#include "longjmp.h"
#include "skas_ptrace.h"
+#include "kern_constants.h"
#define ARBITRARY_ADDR -1
#define FAILURE_PID -1
@@ -187,6 +189,55 @@ int os_unmap_memory(void *addr, int len)
return(0);
}
+#ifndef MADV_REMOVE
+#define MADV_REMOVE KERNEL_MADV_REMOVE
+#endif
+
+int os_drop_memory(void *addr, int length)
+{
+ int err;
+
+ err = madvise(addr, length, MADV_REMOVE);
+ if(err < 0)
+ err = -errno;
+ return err;
+}
+
+int can_drop_memory(void)
+{
+ void *addr;
+ int fd, ok = 0;
+
+ printk("Checking host MADV_REMOVE support...");
+ fd = create_mem_file(UM_KERN_PAGE_SIZE);
+ if(fd < 0){
+ printk("Creating test memory file failed, err = %d\n", -fd);
+ goto out;
+ }
+
+ addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if(addr == MAP_FAILED){
+ printk("Mapping test memory file failed, err = %d\n", -errno);
+ goto out_close;
+ }
+
+ if(madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0){
+ printk("MADV_REMOVE failed, err = %d\n", -errno);
+ goto out_unmap;
+ }
+
+ printk("OK\n");
+ ok = 1;
+
+out_unmap:
+ munmap(addr, UM_KERN_PAGE_SIZE);
+out_close:
+ close(fd);
+out:
+ return ok;
+}
+
void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
{
int flags = 0, pages;
@@ -222,11 +273,11 @@ void init_new_thread_signals(int altstack)
int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
{
- sigjmp_buf buf;
+ jmp_buf buf;
int n, enable;
*jmp_ptr = &buf;
- n = UML_SIGSETJMP(&buf, enable);
+ n = UML_SETJMP(&buf, enable);
if(n != 0)
return(n);
(*fn)(arg);
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/os-Linux/sigio.c
index f7b18e157d3..00e9388e947 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/os-Linux/sigio.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -20,128 +20,7 @@
#include "sigio.h"
#include "os.h"
-/* Changed during early boot */
-int pty_output_sigio = 0;
-int pty_close_sigio = 0;
-
-/* Used as a flag during SIGIO testing early in boot */
-static volatile int got_sigio = 0;
-
-void __init handler(int sig)
-{
- got_sigio = 1;
-}
-
-struct openpty_arg {
- int master;
- int slave;
- int err;
-};
-
-static void openpty_cb(void *arg)
-{
- struct openpty_arg *info = arg;
-
- info->err = 0;
- if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
- info->err = -errno;
-}
-
-void __init check_one_sigio(void (*proc)(int, int))
-{
- struct sigaction old, new;
- struct openpty_arg pty = { .master = -1, .slave = -1 };
- int master, slave, err;
-
- initial_thread_cb(openpty_cb, &pty);
- if(pty.err){
- printk("openpty failed, errno = %d\n", -pty.err);
- return;
- }
-
- master = pty.master;
- slave = pty.slave;
-
- if((master == -1) || (slave == -1)){
- printk("openpty failed to allocate a pty\n");
- return;
- }
-
- /* Not now, but complain so we now where we failed. */
- err = raw(master);
- if (err < 0)
- panic("check_sigio : __raw failed, errno = %d\n", -err);
-
- err = os_sigio_async(master, slave);
- if(err < 0)
- panic("tty_fds : sigio_async failed, err = %d\n", -err);
-
- if(sigaction(SIGIO, NULL, &old) < 0)
- panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
- new = old;
- new.sa_handler = handler;
- if(sigaction(SIGIO, &new, NULL) < 0)
- panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
-
- got_sigio = 0;
- (*proc)(master, slave);
-
- os_close_file(master);
- os_close_file(slave);
-
- if(sigaction(SIGIO, &old, NULL) < 0)
- panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
-}
-
-static void tty_output(int master, int slave)
-{
- int n;
- char buf[512];
-
- printk("Checking that host ptys support output SIGIO...");
-
- memset(buf, 0, sizeof(buf));
-
- while(os_write_file(master, buf, sizeof(buf)) > 0) ;
- if(errno != EAGAIN)
- panic("check_sigio : write failed, errno = %d\n", errno);
- while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
-
- if (got_sigio) {
- printk("Yes\n");
- pty_output_sigio = 1;
- } else if (n == -EAGAIN) {
- printk("No, enabling workaround\n");
- } else {
- panic("check_sigio : read failed, err = %d\n", n);
- }
-}
-
-static void tty_close(int master, int slave)
-{
- printk("Checking that host ptys support SIGIO on close...");
-
- os_close_file(slave);
- if(got_sigio){
- printk("Yes\n");
- pty_close_sigio = 1;
- }
- else printk("No, enabling workaround\n");
-}
-
-void __init check_sigio(void)
-{
- if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
- (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
- printk("No pseudo-terminals available - skipping pty SIGIO "
- "check\n");
- return;
- }
- check_one_sigio(tty_output);
- check_one_sigio(tty_close);
-}
-
-/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
+/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
* exitcall.
*/
static int write_sigio_pid = -1;
@@ -150,8 +29,10 @@ static int write_sigio_pid = -1;
* the descriptors closed after it is killed. So, it can't see them change.
* On the UML side, they are changed under the sigio_lock.
*/
-static int write_sigio_fds[2] = { -1, -1 };
-static int sigio_private[2] = { -1, -1 };
+#define SIGIO_FDS_INIT {-1, -1}
+
+static int write_sigio_fds[2] = SIGIO_FDS_INIT;
+static int sigio_private[2] = SIGIO_FDS_INIT;
struct pollfds {
struct pollfd *poll;
@@ -264,13 +145,13 @@ 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);
write_sigio_pid = -1;
- os_close_file(sigio_private[0]);
- os_close_file(sigio_private[1]);
- os_close_file(write_sigio_fds[0]);
- os_close_file(write_sigio_fds[1]);
+ close(sigio_private[0]);
+ close(sigio_private[1]);
+ close(write_sigio_fds[0]);
+ close(write_sigio_fds[1]);
/* Critical section end */
set_signals(flags);
}
@@ -281,13 +162,13 @@ int add_sigio_fd(int fd, int read)
sigio_lock();
for(i = 0; i < current_poll.used; i++){
- if(current_poll.poll[i].fd == fd)
+ if(current_poll.poll[i].fd == fd)
goto out;
}
n = current_poll.used + 1;
err = need_poll(n);
- if(err)
+ if(err)
goto out;
for(i = 0; i < current_poll.used; i++)
@@ -316,7 +197,7 @@ int ignore_sigio_fd(int fd)
}
if(i == current_poll.used)
goto out;
-
+
err = need_poll(current_poll.used - 1);
if(err)
goto out;
@@ -337,7 +218,7 @@ int ignore_sigio_fd(int fd)
return(err);
}
-static struct pollfd* setup_initial_poll(int fd)
+static struct pollfd *setup_initial_poll(int fd)
{
struct pollfd *p;
@@ -377,7 +258,7 @@ void write_sigio_workaround(void)
}
err = os_pipe(l_sigio_private, 1, 1);
if(err < 0){
- printk("write_sigio_workaround - os_pipe 1 failed, "
+ printk("write_sigio_workaround - os_pipe 2 failed, "
"err = %d\n", -err);
goto out_close1;
}
@@ -391,76 +272,52 @@ void write_sigio_workaround(void)
/* Did we race? Don't try to optimize this, please, it's not so likely
* to happen, and no more than once at the boot. */
if(write_sigio_pid != -1)
- goto out_unlock;
-
- write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
- CLONE_FILES | CLONE_VM, &stack, 0);
+ goto out_free;
- if (write_sigio_pid < 0)
- goto out_clear;
+ current_poll = ((struct pollfds) { .poll = p,
+ .used = 1,
+ .size = 1 });
if (write_sigio_irq(l_write_sigio_fds[0]))
- goto out_kill;
+ goto out_clear_poll;
- /* Success, finally. */
memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
- current_poll = ((struct pollfds) { .poll = p,
- .used = 1,
- .size = 1 });
+ write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
+ CLONE_FILES | CLONE_VM, &stack, 0);
- sigio_unlock();
- return;
+ if (write_sigio_pid < 0)
+ goto out_clear;
- out_kill:
- l_write_sigio_pid = write_sigio_pid;
- write_sigio_pid = -1;
sigio_unlock();
- /* Going to call waitpid, avoid holding the lock. */
- os_kill_process(l_write_sigio_pid, 1);
- goto out_free;
+ return;
- out_clear:
+out_clear:
write_sigio_pid = -1;
- out_unlock:
+ write_sigio_fds[0] = -1;
+ write_sigio_fds[1] = -1;
+ sigio_private[0] = -1;
+ sigio_private[1] = -1;
+out_clear_poll:
+ current_poll = ((struct pollfds) { .poll = NULL,
+ .size = 0,
+ .used = 0 });
+out_free:
sigio_unlock();
- out_free:
kfree(p);
- out_close2:
- os_close_file(l_sigio_private[0]);
- os_close_file(l_sigio_private[1]);
- out_close1:
- os_close_file(l_write_sigio_fds[0]);
- os_close_file(l_write_sigio_fds[1]);
- return;
+out_close2:
+ close(l_sigio_private[0]);
+ close(l_sigio_private[1]);
+out_close1:
+ close(l_write_sigio_fds[0]);
+ close(l_write_sigio_fds[1]);
}
-int read_sigio_fd(int fd)
+void sigio_cleanup(void)
{
- int n;
- char c;
-
- n = os_read_file(fd, &c, sizeof(c));
- if(n != sizeof(c)){
- if(n < 0) {
- printk("read_sigio_fd - read failed, err = %d\n", -n);
- return(n);
- }
- else {
- printk("read_sigio_fd - short read, bytes = %d\n", n);
- return(-EIO);
- }
- }
- return(n);
-}
-
-static void sigio_cleanup(void)
-{
- if (write_sigio_pid != -1) {
+ if(write_sigio_pid != -1){
os_kill_process(write_sigio_pid, 1);
write_sigio_pid = -1;
}
}
-
-__uml_exitcall(sigio_cleanup);
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index fbb080c2fc2..b3c11cfa995 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -82,8 +82,8 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
if (offset) {
data = (unsigned long *)(mm_idp->stack +
offset - UML_CONFIG_STUB_DATA);
- printk("do_syscall_stub : ret = %d, offset = %d, "
- "data = 0x%x\n", ret, offset, data);
+ printk("do_syscall_stub : ret = %ld, offset = %ld, "
+ "data = %p\n", ret, offset, data);
syscall = (unsigned long *)((unsigned long)data + data[0]);
printk("do_syscall_stub: syscall %ld failed, return value = "
"0x%lx, expected return value = 0x%lx\n",
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index bbf34cb91ce..bd89c6b99d5 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -265,7 +265,7 @@ void userspace(union uml_pt_regs *regs)
if(err)
panic("userspace - could not resume userspace process, "
"pid=%d, ptrace operation = %d, errno = %d\n",
- op, errno);
+ pid, op, errno);
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
if(err < 0)
@@ -344,12 +344,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
err = ptrace_setregs(pid, regs);
if(err < 0)
panic("copy_context_skas0 : PTRACE_SETREGS failed, "
- "pid = %d, errno = %d\n", pid, errno);
+ "pid = %d, errno = %d\n", pid, -err);
err = ptrace_setfpregs(pid, fp_regs);
if(err < 0)
panic("copy_context_skas0 : PTRACE_SETFPREGS failed, "
- "pid = %d, errno = %d\n", pid, errno);
+ "pid = %d, errno = %d\n", pid, -err);
/* set a well known return code for detection of child write failure */
child_data->err = 12345678;
@@ -362,14 +362,14 @@ int copy_context_skas0(unsigned long new_stack, int pid)
pid = data->err;
if(pid < 0)
panic("copy_context_skas0 - stub-parent reports error %d\n",
- pid);
+ -pid);
/* Wait, until child has finished too: read child's result from
* child's stack and check it.
*/
wait_stub_done(pid, -1, "copy_context_skas0");
if (child_data->err != UML_CONFIG_STUB_DATA)
- panic("copy_context_skas0 - stub-child reports error %d\n",
+ panic("copy_context_skas0 - stub-child reports error %ld\n",
child_data->err);
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
@@ -434,7 +434,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
void (*handler)(int))
{
unsigned long flags;
- sigjmp_buf switch_buf, fork_buf;
+ jmp_buf switch_buf, fork_buf;
int enable;
*switch_buf_ptr = &switch_buf;
@@ -450,7 +450,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
*/
flags = get_signals();
block_signals();
- if(UML_SIGSETJMP(&fork_buf, enable) == 0)
+ if(UML_SETJMP(&fork_buf, enable) == 0)
new_thread_proc(stack, handler);
remove_sigstack();
@@ -466,35 +466,35 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
void thread_wait(void *sw, void *fb)
{
- sigjmp_buf buf, **switch_buf = sw, *fork_buf;
+ jmp_buf buf, **switch_buf = sw, *fork_buf;
int enable;
*switch_buf = &buf;
fork_buf = fb;
- if(UML_SIGSETJMP(&buf, enable) == 0)
+ if(UML_SETJMP(&buf, enable) == 0)
siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
}
void switch_threads(void *me, void *next)
{
- sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
+ jmp_buf my_buf, **me_ptr = me, *next_buf = next;
int enable;
*me_ptr = &my_buf;
- if(UML_SIGSETJMP(&my_buf, enable) == 0)
- UML_SIGLONGJMP(next_buf, 1);
+ if(UML_SETJMP(&my_buf, enable) == 0)
+ UML_LONGJMP(next_buf, 1);
}
-static sigjmp_buf initial_jmpbuf;
+static jmp_buf initial_jmpbuf;
/* XXX Make these percpu */
static void (*cb_proc)(void *arg);
static void *cb_arg;
-static sigjmp_buf *cb_back;
+static jmp_buf *cb_back;
int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
{
- sigjmp_buf **switch_buf = switch_buf_ptr;
+ jmp_buf **switch_buf = switch_buf_ptr;
int n, enable;
set_handler(SIGWINCH, (__sighandler_t) sig_handler,
@@ -502,7 +502,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
SIGVTALRM, -1);
*fork_buf_ptr = &initial_jmpbuf;
- n = UML_SIGSETJMP(&initial_jmpbuf, enable);
+ n = UML_SETJMP(&initial_jmpbuf, enable);
switch(n){
case INIT_JMP_NEW_THREAD:
new_thread_proc((void *) stack, new_thread_handler);
@@ -512,7 +512,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
break;
case INIT_JMP_CALLBACK:
(*cb_proc)(cb_arg);
- UML_SIGLONGJMP(cb_back, 1);
+ UML_LONGJMP(cb_back, 1);
break;
case INIT_JMP_HALT:
kmalloc_ok = 0;
@@ -523,12 +523,12 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
default:
panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
}
- UML_SIGLONGJMP(*switch_buf, 1);
+ UML_LONGJMP(*switch_buf, 1);
}
void initial_thread_cb_skas(void (*proc)(void *), void *arg)
{
- sigjmp_buf here;
+ jmp_buf here;
int enable;
cb_proc = proc;
@@ -536,8 +536,8 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
cb_back = &here;
block_signals();
- if(UML_SIGSETJMP(&here, enable) == 0)
- UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
+ if(UML_SETJMP(&here, enable) == 0)
+ UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
unblock_signals();
cb_proc = NULL;
@@ -548,13 +548,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
void halt_skas(void)
{
block_signals();
- UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
+ UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
}
void reboot_skas(void)
{
block_signals();
- UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
+ UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
}
void switch_mm_skas(struct mm_id *mm_idp)
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 829d6b0d8b0..50314850400 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -3,6 +3,7 @@
* Licensed under the GPL
*/
+#include <pty.h>
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
@@ -295,29 +296,7 @@ static void __init check_ptrace(void)
check_sysemu();
}
-extern int create_tmp_file(unsigned long long len);
-
-static void check_tmpexec(void)
-{
- void *addr;
- int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
-
- addr = mmap(NULL, UM_KERN_PAGE_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
- printf("Checking PROT_EXEC mmap in /tmp...");
- fflush(stdout);
- if(addr == MAP_FAILED){
- err = errno;
- perror("failed");
- if(err == EPERM)
- printf("/tmp must be not mounted noexec\n");
- exit(1);
- }
- printf("OK\n");
- munmap(addr, UM_KERN_PAGE_SIZE);
-
- close(fd);
-}
+extern void check_tmpexec(void);
void os_early_checks(void)
{
@@ -469,25 +448,6 @@ int can_do_skas(void)
}
#endif
-int have_devanon = 0;
-
-/* Runs on boot kernel stack - already safe to use printk. */
-
-void check_devanon(void)
-{
- int fd;
-
- printk("Checking for /dev/anon on the host...");
- fd = open("/dev/anon", O_RDWR);
- if(fd < 0){
- printk("Not available (open failed with errno %d)\n", errno);
- return;
- }
-
- printk("OK\n");
- have_devanon = 1;
-}
-
int __init parse_iomem(char *str, int *add)
{
struct iomem_region *new;
@@ -539,3 +499,129 @@ int __init parse_iomem(char *str, int *add)
return(1);
}
+
+/* Changed during early boot */
+int pty_output_sigio = 0;
+int pty_close_sigio = 0;
+
+/* Used as a flag during SIGIO testing early in boot */
+static volatile int got_sigio = 0;
+
+static void __init handler(int sig)
+{
+ got_sigio = 1;
+}
+
+struct openpty_arg {
+ int master;
+ int slave;
+ int err;
+};
+
+static void openpty_cb(void *arg)
+{
+ struct openpty_arg *info = arg;
+
+ info->err = 0;
+ if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
+ info->err = -errno;
+}
+
+static void __init check_one_sigio(void (*proc)(int, int))
+{
+ struct sigaction old, new;
+ struct openpty_arg pty = { .master = -1, .slave = -1 };
+ int master, slave, err;
+
+ initial_thread_cb(openpty_cb, &pty);
+ if(pty.err){
+ printk("openpty failed, errno = %d\n", -pty.err);
+ return;
+ }
+
+ master = pty.master;
+ slave = pty.slave;
+
+ if((master == -1) || (slave == -1)){
+ printk("openpty failed to allocate a pty\n");
+ return;
+ }
+
+ /* Not now, but complain so we now where we failed. */
+ err = raw(master);
+ if (err < 0)
+ panic("check_sigio : __raw failed, errno = %d\n", -err);
+
+ err = os_sigio_async(master, slave);
+ if(err < 0)
+ panic("tty_fds : sigio_async failed, err = %d\n", -err);
+
+ if(sigaction(SIGIO, NULL, &old) < 0)
+ panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
+ new = old;
+ new.sa_handler = handler;
+ if(sigaction(SIGIO, &new, NULL) < 0)
+ panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
+
+ got_sigio = 0;
+ (*proc)(master, slave);
+
+ close(master);
+ close(slave);
+
+ if(sigaction(SIGIO, &old, NULL) < 0)
+ panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
+}
+
+static void tty_output(int master, int slave)
+{
+ int n;
+ char buf[512];
+
+ printk("Checking that host ptys support output SIGIO...");
+
+ memset(buf, 0, sizeof(buf));
+
+ while(os_write_file(master, buf, sizeof(buf)) > 0) ;
+ if(errno != EAGAIN)
+ panic("check_sigio : write failed, errno = %d\n", errno);
+ while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
+
+ if(got_sigio){
+ printk("Yes\n");
+ pty_output_sigio = 1;
+ }
+ else if(n == -EAGAIN) printk("No, enabling workaround\n");
+ else panic("check_sigio : read failed, err = %d\n", n);
+}
+
+static void tty_close(int master, int slave)
+{
+ printk("Checking that host ptys support SIGIO on close...");
+
+ close(slave);
+ if(got_sigio){
+ printk("Yes\n");
+ pty_close_sigio = 1;
+ }
+ else printk("No, enabling workaround\n");
+}
+
+void __init check_sigio(void)
+{
+ if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
+ (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
+ printk("No pseudo-terminals available - skipping pty SIGIO "
+ "check\n");
+ return;
+ }
+ check_one_sigio(tty_output);
+ check_one_sigio(tty_close);
+}
+
+void os_check_bugs(void)
+{
+ check_ptrace();
+ check_sigio();
+}
+
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile
index 340ef26f594..b3213613c41 100644
--- a/arch/um/os-Linux/sys-i386/Makefile
+++ b/arch/um/os-Linux/sys-i386/Makefile
@@ -3,7 +3,7 @@
# Licensed under the GPL
#
-obj-$(CONFIG_MODE_SKAS) = registers.o
+obj-$(CONFIG_MODE_SKAS) = registers.o tls.o
USER_OBJS := $(obj-y)
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index 7a6f6b99cef..516f66dd87e 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -104,7 +104,7 @@ void init_registers(int pid)
err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
if(err)
panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
- err);
+ errno);
errno = 0;
err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
@@ -119,7 +119,7 @@ void init_registers(int pid)
err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
if(err)
panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
- err);
+ errno);
}
void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c
new file mode 100644
index 00000000000..120abbe4e3c
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/tls.c
@@ -0,0 +1,34 @@
+#include <errno.h>
+#include <linux/unistd.h>
+#include "sysdep/tls.h"
+#include "user_util.h"
+
+static _syscall1(int, get_thread_area, user_desc_t *, u_info);
+
+/* Checks whether host supports TLS, and sets *tls_min according to the value
+ * valid on the host.
+ * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */
+void check_host_supports_tls(int *supports_tls, int *tls_min) {
+ /* Values for x86 and x86_64.*/
+ int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64};
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(val); i++) {
+ user_desc_t info;
+ info.entry_number = val[i];
+
+ if (get_thread_area(&info) == 0) {
+ *tls_min = val[i];
+ *supports_tls = 1;
+ return;
+ } else {
+ if (errno == EINVAL)
+ continue;
+ else if (errno == ENOSYS)
+ *supports_tls = 0;
+ return;
+ }
+ }
+
+ *supports_tls = 0;
+}
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index 001941fa1a1..becd898d939 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -62,12 +62,12 @@ void init_registers(int pid)
err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
if(err)
panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
- err);
+ errno);
err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
if(err)
panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
- err);
+ errno);
}
void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 6f7626775ac..280c4fb9b58 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -81,20 +81,12 @@ void uml_idle_timer(void)
set_interval(ITIMER_REAL);
}
-extern void ktime_get_ts(struct timespec *ts);
-#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
-
void time_init(void)
{
- struct timespec now;
-
if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
panic("Couldn't set SIGVTALRM handler");
set_interval(ITIMER_VIRTUAL);
-
- do_posix_clock_monotonic_gettime(&now);
- wall_to_monotonic.tv_sec = -now.tv_sec;
- wall_to_monotonic.tv_nsec = -now.tv_nsec;
+ time_init_kern();
}
unsigned long long os_nsecs(void)
diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c
new file mode 100644
index 00000000000..9cb09a45546
--- /dev/null
+++ b/arch/um/os-Linux/tls.c
@@ -0,0 +1,76 @@
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <asm/ldt.h>
+#include "sysdep/tls.h"
+#include "uml-config.h"
+
+/* TLS support - we basically rely on the host's one.*/
+
+/* In TT mode, this should be called only by the tracing thread, and makes sense
+ * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally.
+ *
+ */
+
+#ifndef PTRACE_GET_THREAD_AREA
+#define PTRACE_GET_THREAD_AREA 25
+#endif
+
+#ifndef PTRACE_SET_THREAD_AREA
+#define PTRACE_SET_THREAD_AREA 26
+#endif
+
+int os_set_thread_area(user_desc_t *info, int pid)
+{
+ int ret;
+
+ ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
+ (unsigned long) info);
+ if (ret < 0)
+ ret = -errno;
+ return ret;
+}
+
+#ifdef UML_CONFIG_MODE_SKAS
+
+int os_get_thread_area(user_desc_t *info, int pid)
+{
+ int ret;
+
+ ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
+ (unsigned long) info);
+ if (ret < 0)
+ ret = -errno;
+ return ret;
+}
+
+#endif
+
+#ifdef UML_CONFIG_MODE_TT
+#include "linux/unistd.h"
+
+static _syscall1(int, get_thread_area, user_desc_t *, u_info);
+static _syscall1(int, set_thread_area, user_desc_t *, u_info);
+
+int do_set_thread_area_tt(user_desc_t *info)
+{
+ int ret;
+
+ ret = set_thread_area(info);
+ if (ret < 0) {
+ ret = -errno;
+ }
+ return ret;
+}
+
+int do_get_thread_area_tt(user_desc_t *info)
+{
+ int ret;
+
+ ret = get_thread_area(info);
+ if (ret < 0) {
+ ret = -errno;
+ }
+ return ret;
+}
+
+#endif /* UML_CONFIG_MODE_TT */
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index a9f6b26f982..90b29ae9af4 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -35,7 +35,7 @@ void os_fill_handlinfo(struct kern_handlers h)
void do_longjmp(void *b, int val)
{
- sigjmp_buf *buf = b;
+ jmp_buf *buf = b;
- UML_SIGLONGJMP(buf, val);
+ UML_LONGJMP(buf, val);
}
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
index 919d19f1153..5461a065bbb 100644
--- a/arch/um/os-Linux/tt.c
+++ b/arch/um/os-Linux/tt.c
@@ -110,6 +110,16 @@ int wait_for_stop(int pid, int sig, int cont_type, void *relay)
}
}
+void forward_ipi(int fd, int pid)
+{
+ int err;
+
+ err = os_set_owner(fd, pid);
+ if(err < 0)
+ printk("forward_ipi: set_owner failed, fd = %d, me = %d, "
+ "target = %d, err = %d\n", fd, os_getpid(), pid, -err);
+}
+
/*
*-------------------------
* only for tt mode (will be deleted in future...)
diff --git a/arch/um/kernel/tty_log.c b/arch/um/os-Linux/tty_log.c
index 9ada656f68c..c6ba56c1560 100644
--- a/arch/um/kernel/tty_log.c
+++ b/arch/um/os-Linux/tty_log.c
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and
* geoffrey hing <ghing@net.ohio-state.edu>
* Licensed under the GPL
*/
@@ -58,7 +58,7 @@ int open_tty_log(void *tty, void *current_tty)
return(tty_log_fd);
}
- sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
+ sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
(unsigned int) tv.tv_usec);
fd = os_open_file(buf, of_append(of_create(of_rdwr(OPENFLAGS()))),
@@ -216,15 +216,3 @@ __uml_setup("tty_log_fd=", set_tty_log_fd,
" tty data will be written. Preconfigure the descriptor with something\n"
" like '10>tty_log tty_log_fd=10'.\n\n"
);
-
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 166fb66995d..e523719330b 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -16,9 +16,9 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
unsigned long *faddrp = (unsigned long *) fault_addr, ret;
int enable;
- sigjmp_buf jbuf;
+ jmp_buf jbuf;
*fault_catcher = &jbuf;
- if(UML_SIGSETJMP(&jbuf, enable) == 0){
+ if(UML_SETJMP(&jbuf, enable) == 0){
(*op)(to, from, n);
ret = 0;
*faulted_out = 0;
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index ecf107ae5ac..362db059fe3 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -120,7 +120,8 @@ static int not_dead_yet(char *dir)
dead = 0;
fd = open(file, O_RDONLY);
- if(fd < 0){
+ if(fd < 0) {
+ fd = -errno;
if(fd != -ENOENT){
printk("not_dead_yet : couldn't open pid file '%s', "
"err = %d\n", file, -fd);
@@ -130,9 +131,13 @@ static int not_dead_yet(char *dir)
err = 0;
n = read(fd, pid, sizeof(pid));
- if(n <= 0){
+ if(n < 0){
+ printk("not_dead_yet : couldn't read pid file '%s', "
+ "err = %d\n", file, errno);
+ goto out_close;
+ } else if(n == 0){
printk("not_dead_yet : couldn't read pid file '%s', "
- "err = %d\n", file, -n);
+ "0-byte read\n", file);
goto out_close;
}
@@ -143,8 +148,10 @@ static int not_dead_yet(char *dir)
goto out_close;
}
- if((kill(p, 0) == 0) || (errno != ESRCH))
+ if((kill(p, 0) == 0) || (errno != ESRCH)){
+ printk("umid \"%s\" is already in use by pid %d\n", umid, p);
return 1;
+ }
err = actually_do_remove(dir);
if(err)
@@ -153,9 +160,9 @@ static int not_dead_yet(char *dir)
return err;
- out_close:
+out_close:
close(fd);
- out:
+out:
return 0;
}
@@ -171,14 +178,14 @@ static void __init create_pid_file(void)
fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644);
if(fd < 0){
printk("Open of machine pid file \"%s\" failed: %s\n",
- file, strerror(-fd));
+ file, strerror(errno));
return;
}
snprintf(pid, sizeof(pid), "%d\n", getpid());
n = write(fd, pid, strlen(pid));
if(n != strlen(pid))
- printk("Write of pid file failed - err = %d\n", -n);
+ printk("Write of pid file failed - err = %d\n", errno);
close(fd);
}
@@ -234,33 +241,44 @@ int __init make_umid(void)
err = mkdir(tmp, 0777);
if(err < 0){
err = -errno;
- if(errno != EEXIST)
+ if(err != -EEXIST)
goto err;
- if(not_dead_yet(tmp) < 0)
+ /* 1 -> this umid is already in use
+ * < 0 -> we couldn't remove the umid directory
+ * In either case, we can't use this umid, so return -EEXIST.
+ */
+ if(not_dead_yet(tmp) != 0)
goto err;
err = mkdir(tmp, 0777);
}
- if(err < 0){
- printk("Failed to create '%s' - err = %d\n", umid, err);
- goto err_rmdir;
+ if(err){
+ err = -errno;
+ printk("Failed to create '%s' - err = %d\n", umid, -errno);
+ goto err;
}
umid_setup = 1;
create_pid_file();
- return 0;
-
- err_rmdir:
- rmdir(tmp);
+ err = 0;
err:
return err;
}
static int __init make_umid_init(void)
{
+ if(!make_umid())
+ return 0;
+
+ /* If initializing with the given umid failed, then try again with
+ * a random one.
+ */
+ printk("Failed to initialize umid \"%s\", trying with a random umid\n",
+ umid);
+ *umid = '\0';
make_umid();
return 0;
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 8da6ab31152..3f33165ada6 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -18,14 +18,19 @@ extern void *memmove(void *, const void *, size_t);
extern void *memset(void *, int, size_t);
extern int printf(const char *, ...);
+/* If they're not defined, the export is included in lib/string.c.*/
+#ifdef __HAVE_ARCH_STRLEN
EXPORT_SYMBOL(strlen);
+#endif
+#ifdef __HAVE_ARCH_STRSTR
+EXPORT_SYMBOL(strstr);
+#endif
+
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(printf);
-EXPORT_SYMBOL(strstr);
-
/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
* However, the modules will use the CRC defined *here*, no matter if it is
* good; so the versions of these symbols will always match
@@ -91,6 +96,13 @@ EXPORT_SYMBOL_PROTO(getuid);
EXPORT_SYMBOL_PROTO(fsync);
EXPORT_SYMBOL_PROTO(fdatasync);
+/* Export symbols used by GCC for the stack protector. */
+extern void __stack_smash_handler(void *) __attribute__((weak));
+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
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index e32065e2fdc..c47a2a7ce70 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -104,7 +104,7 @@ void setup_hostinfo(void)
int setjmp_wrapper(void (*proc)(void *, void *), ...)
{
va_list args;
- sigjmp_buf buf;
+ jmp_buf buf;
int n;
n = sigsetjmp(buf, 1);
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 2e41cabd3d9..1347dc6d521 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -7,38 +7,26 @@ USER_SINGLE_OBJS := \
USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS))
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
-$(USER_OBJS) $(USER_OBJS:.o=.i) $(USER_OBJS:.o=.s) $(USER_OBJS:.o=.lst): \
- c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(notdir $@))
-$(USER_OBJS): cmd_checksrc =
-$(USER_OBJS): quiet_cmd_checksrc =
-$(USER_OBJS): cmd_force_checksrc =
-$(USER_OBJS): quiet_cmd_force_checksrc =
+$(USER_OBJS:.o=.%): \
+ c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(*F).o)
+$(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
+ -Dunix -D__unix__ -D__$(SUBARCH)__
+# These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of
+# using it directly.
+UNPROFILE_OBJS := $(foreach file,$(UNPROFILE_OBJS),$(obj)/$(file))
+
+$(UNPROFILE_OBJS:.o=.%): \
+ c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS)) $(CFLAGS_$(*F).o)
+$(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
+ -Dunix -D__unix__ -D__$(SUBARCH)__
# The stubs and unmap.o can't try to call mcount or update basic block data
define unprofile
$(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
endef
-
-# cmd_make_link checks to see if the $(foo-dir) variable starts with a /. If
-# so, it's considered to be a path relative to $(srcdir) rather than
-# $(srcdir)/arch/$(SUBARCH). This is because x86_64 wants to get ldt.c from
-# arch/um/sys-i386 rather than arch/i386 like the other borrowed files. So,
-# it sets $(ldt.c-dir) to /arch/um/sys-i386.
-quiet_cmd_make_link = SYMLINK $@
-cmd_make_link = rm -f $@; ln -sf $(srctree)$(if $(filter-out /%,$($(notdir $@)-dir)),/arch/$(SUBARCH))/$($(notdir $@)-dir)/$(notdir $@) $@
-
-# this needs to be before the foreach, because targets does not accept
-# complete paths like $(obj)/$(f). To make sure this works, use a := assignment
-# or we will get $(obj)/$(f) in the "targets" value.
-# Also, this forces you to use the := syntax when assigning to targets.
-# Otherwise the line below will cause an infinite loop (if you don't know why,
-# just do it).
-
-targets := $(targets) $(SYMLINKS)
-
-SYMLINKS := $(foreach f,$(SYMLINKS),$(obj)/$(f))
-
-$(SYMLINKS): FORCE
- $(call if_changed,make_link)
+ifdef subarch-obj-y
+obj-y += subarch.o
+subarch-y = $(addprefix ../../$(SUBARCH)/,$(subarch-obj-y))
+endif
diff --git a/arch/um/scripts/Makefile.unmap b/arch/um/scripts/Makefile.unmap
deleted file mode 100644
index b2165188d94..00000000000
--- a/arch/um/scripts/Makefile.unmap
+++ /dev/null
@@ -1,22 +0,0 @@
-clean-files += unmap_tmp.o unmap_fin.o unmap.o
-
-ifdef CONFIG_MODE_TT
-
-#Always build unmap_fin.o
-extra-y += unmap_fin.o
-#Do dependency tracking for unmap.o (it will be always built, but won't get the tracking unless we use this).
-targets += unmap.o
-
-#XXX: partially copied from arch/um/scripts/Makefile.rules
-$(obj)/unmap.o: _c_flags = $(call unprofile,$(CFLAGS))
-
-quiet_cmd_wrapld = LD $@
-define cmd_wrapld
- $(LD) $(LDFLAGS) -r -o $(obj)/unmap_tmp.o $< ; \
- $(OBJCOPY) $(UML_OBJCOPYFLAGS) $(obj)/unmap_tmp.o $@ -G switcheroo
-endef
-
-$(obj)/unmap_fin.o : $(obj)/unmap.o FORCE
- $(call if_changed,wrapld)
-
-endif
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index f5fd5b0156d..374d61a1943 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,23 +1,23 @@
-obj-y := bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
- ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o \
- sys_call_table.o
+obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
+ ptrace_user.o signal.o sigcontext.o syscalls.o sysrq.o \
+ sys_call_table.o tls.o
obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
-obj-$(CONFIG_HIGHMEM) += highmem.o
-obj-$(CONFIG_MODULES) += module.o
+subarch-obj-y = lib/bitops.o kernel/semaphore.o
+subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem.o
+subarch-obj-$(CONFIG_MODULES) += kernel/module.o
-USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o stub_segv.o
+USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
-SYMLINKS = bitops.c semaphore.c highmem.c module.c
+USER_OBJS += user-offsets.s
+extra-y += user-offsets.s
-include arch/um/scripts/Makefile.rules
+extra-$(CONFIG_MODE_TT) += unmap.o
-bitops.c-dir = lib
-semaphore.c-dir = kernel
-highmem.c-dir = mm
-module.c-dir = kernel
+UNPROFILE_OBJS := stub_segv.o
+CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
-$(obj)/stub_segv.o : _c_flags = $(call unprofile,$(CFLAGS))
+include arch/um/scripts/Makefile.rules
-include arch/um/scripts/Makefile.unmap
+$(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS))
diff --git a/arch/um/sys-i386/ksyms.c b/arch/um/sys-i386/ksyms.c
index db524ab3f74..2a1eac1859c 100644
--- a/arch/um/sys-i386/ksyms.c
+++ b/arch/um/sys-i386/ksyms.c
@@ -15,7 +15,3 @@ EXPORT_SYMBOL(__up_wakeup);
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial);
-
-/* delay core functions */
-EXPORT_SYMBOL(__const_udelay);
-EXPORT_SYMBOL(__udelay);
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index e839ce65ad2..6028bc7cc01 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -6,6 +6,7 @@
#include <linux/config.h>
#include <linux/compiler.h>
#include "linux/sched.h"
+#include "linux/mm.h"
#include "asm/elf.h"
#include "asm/ptrace.h"
#include "asm/uaccess.h"
@@ -14,9 +15,22 @@
#include "sysdep/sigcontext.h"
#include "sysdep/sc.h"
-void arch_switch(void)
+void arch_switch_to_tt(struct task_struct *from, struct task_struct *to)
{
- update_debugregs(current->thread.arch.debugregs_seq);
+ update_debugregs(to->thread.arch.debugregs_seq);
+ arch_switch_tls_tt(from, to);
+}
+
+void arch_switch_to_skas(struct task_struct *from, struct task_struct *to)
+{
+ int err = arch_switch_tls_skas(from, to);
+ if (!err)
+ return;
+
+ if (err != -EINVAL)
+ printk(KERN_WARNING "arch_switch_tls_skas failed, errno %d, not EINVAL\n", -err);
+ else
+ printk(KERN_WARNING "arch_switch_tls_skas failed, errno = EINVAL\n");
}
int is_syscall(unsigned long addr)
@@ -26,9 +40,17 @@ int is_syscall(unsigned long addr)
n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
if(n){
- printk("is_syscall : failed to read instruction from 0x%lx\n",
- addr);
- return(0);
+ /* access_process_vm() grants access to vsyscall and stub,
+ * while copy_from_user doesn't. Maybe access_process_vm is
+ * slow, but that doesn't matter, since it will be called only
+ * in case of singlestepping, if copy_from_user failed.
+ */
+ n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+ if(n != sizeof(instr)) {
+ printk("is_syscall : failed to read instruction from "
+ "0x%lx\n", addr);
+ return(1);
+ }
}
/* int 0x80 or sysenter */
return((instr == 0x80cd) || (instr == 0x340f));
@@ -115,22 +137,22 @@ unsigned long getreg(struct task_struct *child, int regno)
int peek_user(struct task_struct *child, long addr, long data)
{
/* read the word at location addr in the USER area. */
- unsigned long tmp;
+ unsigned long tmp;
- if ((addr & 3) || addr < 0)
- return -EIO;
+ if ((addr & 3) || addr < 0)
+ return -EIO;
- tmp = 0; /* Default return condition */
- if(addr < MAX_REG_OFFSET){
- tmp = getreg(child, addr);
- }
- else if((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
- addr -= offsetof(struct user, u_debugreg[0]);
- addr = addr >> 2;
- tmp = child->thread.arch.debugregs[addr];
- }
- return put_user(tmp, (unsigned long *) data);
+ tmp = 0; /* Default return condition */
+ if(addr < MAX_REG_OFFSET){
+ tmp = getreg(child, addr);
+ }
+ else if((addr >= offsetof(struct user, u_debugreg[0])) &&
+ (addr <= offsetof(struct user, u_debugreg[7]))){
+ addr -= offsetof(struct user, u_debugreg[0]);
+ addr = addr >> 2;
+ tmp = child->thread.arch.debugregs[addr];
+ }
+ return put_user(tmp, (unsigned long __user *) data);
}
struct i387_fxsave_struct {
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 7c376c95de5..40aa8853144 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -14,6 +14,7 @@
#include "sysdep/thread.h"
#include "user.h"
#include "os.h"
+#include "uml-config.h"
int ptrace_getregs(long pid, unsigned long *regs_out)
{
@@ -43,6 +44,7 @@ int ptrace_setfpregs(long pid, unsigned long *regs)
return 0;
}
+/* All the below stuff is of interest for TT mode only */
static void write_debugregs(int pid, unsigned long *regs)
{
struct user *dummy;
@@ -55,7 +57,7 @@ static void write_debugregs(int pid, unsigned long *regs)
if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
regs[i]) < 0)
printk("write_debugregs - ptrace failed on "
- "register %d, value = 0x%x, errno = %d\n", i,
+ "register %d, value = 0x%lx, errno = %d\n", i,
regs[i], errno);
}
}
@@ -75,7 +77,6 @@ static void read_debugregs(int pid, unsigned long *regs)
/* Accessed only by the tracing thread */
static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 };
-static int debugregs_seq = 0;
void arch_enter_kernel(void *task, int pid)
{
@@ -89,6 +90,11 @@ void arch_leave_kernel(void *task, int pid)
write_debugregs(pid, TASK_DEBUGREGS(task));
}
+#ifdef UML_CONFIG_PT_PROXY
+/* Accessed only by the tracing thread */
+static int debugregs_seq;
+
+/* Only called by the ptrace proxy */
void ptrace_pokeuser(unsigned long addr, unsigned long data)
{
if((addr < offsetof(struct user, u_debugreg[0])) ||
@@ -109,6 +115,7 @@ static void update_debugregs_cb(void *arg)
write_debugregs(pid, kernel_debugregs);
}
+/* Optimized out in its header when not defined */
void update_debugregs(int seq)
{
int me;
@@ -118,6 +125,7 @@ void update_debugregs(int seq)
me = os_getpid();
initial_thread_cb(update_debugregs_cb, &me);
}
+#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 7cd1a82dc8c..0709fc6670c 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -19,7 +19,7 @@
#include "skas.h"
static int copy_sc_from_user_skas(struct pt_regs *regs,
- struct sigcontext *from)
+ struct sigcontext __user *from)
{
struct sigcontext sc;
unsigned long fpregs[HOST_FP_SIZE];
@@ -57,8 +57,8 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
return(0);
}
-int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
- struct pt_regs *regs)
+int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp,
+ struct pt_regs *regs, unsigned long sp)
{
struct sigcontext sc;
unsigned long fpregs[HOST_FP_SIZE];
@@ -72,7 +72,7 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
sc.edi = REGS_EDI(regs->regs.skas.regs);
sc.esi = REGS_ESI(regs->regs.skas.regs);
sc.ebp = REGS_EBP(regs->regs.skas.regs);
- sc.esp = REGS_SP(regs->regs.skas.regs);
+ sc.esp = sp;
sc.ebx = REGS_EBX(regs->regs.skas.regs);
sc.edx = REGS_EDX(regs->regs.skas.regs);
sc.ecx = REGS_ECX(regs->regs.skas.regs);
@@ -92,7 +92,7 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
"errno = %d\n", err);
return(1);
}
- to_fp = (to_fp ? to_fp : (struct _fpstate *) (to + 1));
+ to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
sc.fpstate = to_fp;
if(err)
@@ -113,10 +113,11 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
* saved pointer is in the kernel, but the sigcontext is in userspace, so we
* copy_to_user it.
*/
-int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
+int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
int fpsize)
{
- struct _fpstate *to_fp, *from_fp;
+ struct _fpstate *to_fp;
+ struct _fpstate __user *from_fp;
unsigned long sigs;
int err;
@@ -131,20 +132,28 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
return(err);
}
-int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
- struct sigcontext *from, int fpsize)
+int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
+ struct sigcontext *from, int fpsize, unsigned long sp)
{
- struct _fpstate *to_fp, *from_fp;
+ struct _fpstate __user *to_fp;
+ struct _fpstate *from_fp;
int err;
- to_fp = (fp ? fp : (struct _fpstate *) (to + 1));
+ to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1));
from_fp = from->fpstate;
err = copy_to_user(to, from, sizeof(*to));
+
+ /* The SP in the sigcontext is the updated one for the signal
+ * delivery. The sp passed in is the original, and this needs
+ * to be restored, so we stick it in separately.
+ */
+ err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp));
+
if(from_fp != NULL){
err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
err |= copy_to_user(to_fp, from_fp, fpsize);
}
- return(err);
+ return err;
}
#endif
@@ -158,15 +167,15 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
return(ret);
}
-static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
- struct pt_regs *from)
+static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp,
+ struct pt_regs *from, unsigned long sp)
{
return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
- sizeof(*fp)),
- copy_sc_to_user_skas(to, fp, from)));
+ sizeof(*fp), sp),
+ copy_sc_to_user_skas(to, fp, from, sp)));
}
-static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp,
+static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp,
sigset_t *set, unsigned long sp)
{
int err = 0;
@@ -174,14 +183,14 @@ static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp,
err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
- err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs);
+ err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, sp);
err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
return(err);
}
struct sigframe
{
- char *pretcode;
+ char __user *pretcode;
int sig;
struct sigcontext sc;
struct _fpstate fpstate;
@@ -191,10 +200,10 @@ struct sigframe
struct rt_sigframe
{
- char *pretcode;
+ char __user *pretcode;
int sig;
- struct siginfo *pinfo;
- void *puc;
+ struct siginfo __user *pinfo;
+ void __user *puc;
struct siginfo info;
struct ucontext uc;
struct _fpstate fpstate;
@@ -206,21 +215,32 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
sigset_t *mask)
{
struct sigframe __user *frame;
- void *restorer;
+ void __user *restorer;
+ unsigned long save_sp = PT_REGS_SP(regs);
int err = 0;
stack_top &= -8UL;
- frame = (struct sigframe *) stack_top - 1;
+ frame = (struct sigframe __user *) stack_top - 1;
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
return 1;
- restorer = (void *) frame->retcode;
+ restorer = frame->retcode;
if(ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
+ /* Update SP now because the page fault handler refuses to extend
+ * the stack if the faulting address is too far below the current
+ * SP, which frame now certainly is. If there's an error, the original
+ * value is restored on the way out.
+ * When writing the sigcontext to the stack, we have to write the
+ * original value, so that's passed to copy_sc_to_user, which does
+ * the right thing with it.
+ */
+ PT_REGS_SP(regs) = (unsigned long) frame;
+
err |= __put_user(restorer, &frame->pretcode);
err |= __put_user(sig, &frame->sig);
- err |= copy_sc_to_user(&frame->sc, NULL, regs);
+ err |= copy_sc_to_user(&frame->sc, NULL, regs, save_sp);
err |= __put_user(mask->sig[0], &frame->sc.oldmask);
if (_NSIG_WORDS > 1)
err |= __copy_to_user(&frame->extramask, &mask->sig[1],
@@ -238,7 +258,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
if(err)
- return(err);
+ goto err;
PT_REGS_SP(regs) = (unsigned long) frame;
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
@@ -248,7 +268,11 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
ptrace_notify(SIGTRAP);
- return(0);
+ return 0;
+
+err:
+ PT_REGS_SP(regs) = save_sp;
+ return err;
}
int setup_signal_stack_si(unsigned long stack_top, int sig,
@@ -256,25 +280,29 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
siginfo_t *info, sigset_t *mask)
{
struct rt_sigframe __user *frame;
- void *restorer;
+ void __user *restorer;
+ unsigned long save_sp = PT_REGS_SP(regs);
int err = 0;
stack_top &= -8UL;
- frame = (struct rt_sigframe *) stack_top - 1;
+ frame = (struct rt_sigframe __user *) stack_top - 1;
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
return 1;
- restorer = (void *) frame->retcode;
+ restorer = frame->retcode;
if(ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
+ /* See comment above about why this is here */
+ PT_REGS_SP(regs) = (unsigned long) frame;
+
err |= __put_user(restorer, &frame->pretcode);
err |= __put_user(sig, &frame->sig);
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info);
err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
- PT_REGS_SP(regs));
+ save_sp);
/*
* This is movl $,%eax ; int $0x80
@@ -288,9 +316,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
if(err)
- return(err);
+ goto err;
- PT_REGS_SP(regs) = (unsigned long) frame;
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
PT_REGS_EAX(regs) = (unsigned long) sig;
PT_REGS_EDX(regs) = (unsigned long) &frame->info;
@@ -298,13 +325,17 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
ptrace_notify(SIGTRAP);
- return(0);
+ return 0;
+
+err:
+ PT_REGS_SP(regs) = save_sp;
+ return err;
}
long sys_sigreturn(struct pt_regs regs)
{
unsigned long sp = PT_REGS_SP(&current->thread.regs);
- struct sigframe __user *frame = (struct sigframe *)(sp - 8);
+ struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
sigset_t set;
struct sigcontext __user *sc = &frame->sc;
unsigned long __user *oldmask = &sc->oldmask;
@@ -336,8 +367,8 @@ long sys_sigreturn(struct pt_regs regs)
long sys_rt_sigreturn(struct pt_regs regs)
{
- unsigned long __user sp = PT_REGS_SP(&current->thread.regs);
- struct rt_sigframe __user *frame = (struct rt_sigframe *) (sp - 4);
+ unsigned long sp = PT_REGS_SP(&current->thread.regs);
+ struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (sp - 4);
sigset_t set;
struct ucontext __user *uc = &frame->uc;
int sig_size = _NSIG_WORDS * sizeof(unsigned long);
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
index a37f672ec96..2355dc19c46 100644
--- a/arch/um/sys-i386/stub_segv.c
+++ b/arch/um/sys-i386/stub_segv.c
@@ -27,6 +27,6 @@ stub_segv_handler(int sig)
* the stack in its original form when we do the sigreturn here, by
* hand.
*/
- __asm__("mov %0,%%esp ; movl %1, %%eax ; "
- "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
+ __asm__ __volatile__("mov %0,%%esp ; movl %1, %%eax ; "
+ "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
}
diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S
index ad75c27afe3..1ff61474b25 100644
--- a/arch/um/sys-i386/sys_call_table.S
+++ b/arch/um/sys-i386/sys_call_table.S
@@ -6,8 +6,6 @@
#define sys_vm86old sys_ni_syscall
#define sys_vm86 sys_ni_syscall
-#define sys_set_thread_area sys_ni_syscall
-#define sys_get_thread_area sys_ni_syscall
#define sys_stime um_stime
#define sys_time um_time
diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c
index 83e9be820a8..710d5fb807e 100644
--- a/arch/um/sys-i386/syscalls.c
+++ b/arch/um/sys-i386/syscalls.c
@@ -61,21 +61,27 @@ long old_select(struct sel_arg_struct __user *arg)
return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
}
-/* The i386 version skips reading from %esi, the fourth argument. So we must do
- * this, too.
+/*
+ * The prototype on i386 is:
+ *
+ * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
+ *
+ * and the "newtls" arg. on i386 is read by copy_thread directly from the
+ * register saved on the stack.
*/
long sys_clone(unsigned long clone_flags, unsigned long newsp,
- int __user *parent_tid, int unused, int __user *child_tid)
+ int __user *parent_tid, void *newtls, int __user *child_tid)
{
long ret;
if (!newsp)
newsp = UPT_SP(&current->thread.regs.regs);
+
current->thread.forking = 1;
ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
child_tid);
current->thread.forking = 0;
- return(ret);
+ return ret;
}
/*
@@ -93,18 +99,19 @@ long sys_ipc (uint call, int first, int second,
switch (call) {
case SEMOP:
- return sys_semtimedop(first, (struct sembuf *) ptr, second,
- NULL);
+ return sys_semtimedop(first, (struct sembuf __user *) ptr,
+ second, NULL);
case SEMTIMEDOP:
- return sys_semtimedop(first, (struct sembuf *) ptr, second,
- (const struct timespec *) fifth);
+ return sys_semtimedop(first, (struct sembuf __user *) ptr,
+ second,
+ (const struct timespec __user *) fifth);
case SEMGET:
return sys_semget (first, second, third);
case SEMCTL: {
union semun fourth;
if (!ptr)
return -EINVAL;
- if (get_user(fourth.__pad, (void **) ptr))
+ if (get_user(fourth.__pad, (void __user * __user *) ptr))
return -EFAULT;
return sys_semctl (first, second, third, fourth);
}
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c
new file mode 100644
index 00000000000..71b9796258e
--- /dev/null
+++ b/arch/um/sys-i386/tls.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
+ * Licensed under the GPL
+ */
+
+#include "linux/config.h"
+#include "linux/kernel.h"
+#include "linux/sched.h"
+#include "linux/slab.h"
+#include "linux/types.h"
+#include "asm/uaccess.h"
+#include "asm/ptrace.h"
+#include "asm/segment.h"
+#include "asm/smp.h"
+#include "asm/desc.h"
+#include "choose-mode.h"
+#include "kern.h"
+#include "kern_util.h"
+#include "mode_kern.h"
+#include "os.h"
+#include "mode.h"
+
+#ifdef CONFIG_MODE_SKAS
+#include "skas.h"
+#endif
+
+/* If needed we can detect when it's uninitialized. */
+static int host_supports_tls = -1;
+int host_gdt_entry_tls_min = -1;
+
+#ifdef CONFIG_MODE_SKAS
+int do_set_thread_area_skas(struct user_desc *info)
+{
+ int ret;
+ u32 cpu;
+
+ cpu = get_cpu();
+ ret = os_set_thread_area(info, userspace_pid[cpu]);
+ put_cpu();
+ return ret;
+}
+
+int do_get_thread_area_skas(struct user_desc *info)
+{
+ int ret;
+ u32 cpu;
+
+ cpu = get_cpu();
+ ret = os_get_thread_area(info, userspace_pid[cpu]);
+ put_cpu();
+ return ret;
+}
+#endif
+
+/*
+ * sys_get_thread_area: get a yet unused TLS descriptor index.
+ * XXX: Consider leaving one free slot for glibc usage at first place. This must
+ * be done here (and by changing GDT_ENTRY_TLS_* macros) and nowhere else.
+ *
+ * Also, this must be tested when compiling in SKAS mode with dinamic linking
+ * and running against NPTL.
+ */
+static int get_free_idx(struct task_struct* task)
+{
+ struct thread_struct *t = &task->thread;
+ int idx;
+
+ if (!t->arch.tls_array)
+ return GDT_ENTRY_TLS_MIN;
+
+ for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
+ if (!t->arch.tls_array[idx].present)
+ return idx + GDT_ENTRY_TLS_MIN;
+ return -ESRCH;
+}
+
+static inline void clear_user_desc(struct user_desc* info)
+{
+ /* Postcondition: LDT_empty(info) returns true. */
+ memset(info, 0, sizeof(*info));
+
+ /* Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
+ * indeed an empty user_desc.
+ */
+ info->read_exec_only = 1;
+ info->seg_not_present = 1;
+}
+
+#define O_FORCE 1
+
+static int load_TLS(int flags, struct task_struct *to)
+{
+ int ret = 0;
+ int idx;
+
+ for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
+ struct uml_tls_struct* curr = &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
+
+ /* Actually, now if it wasn't flushed it gets cleared and
+ * flushed to the host, which will clear it.*/
+ if (!curr->present) {
+ if (!curr->flushed) {
+ clear_user_desc(&curr->tls);
+ curr->tls.entry_number = idx;
+ } else {
+ WARN_ON(!LDT_empty(&curr->tls));
+ continue;
+ }
+ }
+
+ if (!(flags & O_FORCE) && curr->flushed)
+ continue;
+
+ ret = do_set_thread_area(&curr->tls);
+ if (ret)
+ goto out;
+
+ curr->flushed = 1;
+ }
+out:
+ return ret;
+}
+
+/* Verify if we need to do a flush for the new process, i.e. if there are any
+ * present desc's, only if they haven't been flushed.
+ */
+static inline int needs_TLS_update(struct task_struct *task)
+{
+ int i;
+ int ret = 0;
+
+ for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
+ struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
+
+ /* Can't test curr->present, we may need to clear a descriptor
+ * which had a value. */
+ if (curr->flushed)
+ continue;
+ ret = 1;
+ break;
+ }
+ return ret;
+}
+
+/* On a newly forked process, the TLS descriptors haven't yet been flushed. So
+ * we mark them as such and the first switch_to will do the job.
+ */
+void clear_flushed_tls(struct task_struct *task)
+{
+ int i;
+
+ for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
+ struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
+
+ /* Still correct to do this, if it wasn't present on the host it
+ * will remain as flushed as it was. */
+ if (!curr->present)
+ continue;
+
+ curr->flushed = 0;
+ }
+}
+
+/* In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
+ * common host process. So this is needed in SKAS0 too.
+ *
+ * However, if each thread had a different host process (and this was discussed
+ * for SMP support) this won't be needed.
+ *
+ * And this will not need be used when (and if) we'll add support to the host
+ * SKAS patch. */
+
+int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to)
+{
+ if (!host_supports_tls)
+ return 0;
+
+ /* We have no need whatsoever to switch TLS for kernel threads; beyond
+ * that, that would also result in us calling os_set_thread_area with
+ * userspace_pid[cpu] == 0, which gives an error. */
+ if (likely(to->mm))
+ return load_TLS(O_FORCE, to);
+
+ return 0;
+}
+
+int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to)
+{
+ if (!host_supports_tls)
+ return 0;
+
+ if (needs_TLS_update(to))
+ return load_TLS(0, to);
+
+ return 0;
+}
+
+static int set_tls_entry(struct task_struct* task, struct user_desc *info,
+ int idx, int flushed)
+{
+ struct thread_struct *t = &task->thread;
+
+ if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+ return -EINVAL;
+
+ t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls = *info;
+ t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present = 1;
+ t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed = flushed;
+
+ return 0;
+}
+
+int arch_copy_tls(struct task_struct *new)
+{
+ struct user_desc info;
+ int idx, ret = -EFAULT;
+
+ if (copy_from_user(&info,
+ (void __user *) UPT_ESI(&new->thread.regs.regs),
+ sizeof(info)))
+ goto out;
+
+ ret = -EINVAL;
+ if (LDT_empty(&info))
+ goto out;
+
+ idx = info.entry_number;
+
+ ret = set_tls_entry(new, &info, idx, 0);
+out:
+ return ret;
+}
+
+/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
+static int get_tls_entry(struct task_struct* task, struct user_desc *info, int idx)
+{
+ struct thread_struct *t = &task->thread;
+
+ if (!t->arch.tls_array)
+ goto clear;
+
+ if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+ return -EINVAL;
+
+ if (!t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present)
+ goto clear;
+
+ *info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls;
+
+out:
+ /* Temporary debugging check, to make sure that things have been
+ * flushed. This could be triggered if load_TLS() failed.
+ */
+ if (unlikely(task == current && !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
+ printk(KERN_ERR "get_tls_entry: task with pid %d got here "
+ "without flushed TLS.", current->pid);
+ }
+
+ return 0;
+clear:
+ /* When the TLS entry has not been set, the values read to user in the
+ * tls_array are 0 (because it's cleared at boot, see
+ * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
+ */
+ clear_user_desc(info);
+ info->entry_number = idx;
+ goto out;
+}
+
+asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
+{
+ struct user_desc info;
+ int idx, ret;
+
+ if (!host_supports_tls)
+ return -ENOSYS;
+
+ if (copy_from_user(&info, user_desc, sizeof(info)))
+ return -EFAULT;
+
+ idx = info.entry_number;
+
+ if (idx == -1) {
+ idx = get_free_idx(current);
+ if (idx < 0)
+ return idx;
+ info.entry_number = idx;
+ /* Tell the user which slot we chose for him.*/
+ if (put_user(idx, &user_desc->entry_number))
+ return -EFAULT;
+ }
+
+ ret = CHOOSE_MODE_PROC(do_set_thread_area_tt, do_set_thread_area_skas, &info);
+ if (ret)
+ return ret;
+ return set_tls_entry(current, &info, idx, 1);
+}
+
+/*
+ * Perform set_thread_area on behalf of the traced child.
+ * Note: error handling is not done on the deferred load, and this differ from
+ * i386. However the only possible error are caused by bugs.
+ */
+int ptrace_set_thread_area(struct task_struct *child, int idx,
+ struct user_desc __user *user_desc)
+{
+ struct user_desc info;
+
+ if (!host_supports_tls)
+ return -EIO;
+
+ if (copy_from_user(&info, user_desc, sizeof(info)))
+ return -EFAULT;
+
+ return set_tls_entry(child, &info, idx, 0);
+}
+
+asmlinkage int sys_get_thread_area(struct user_desc __user *user_desc)
+{
+ struct user_desc info;
+ int idx, ret;
+
+ if (!host_supports_tls)
+ return -ENOSYS;
+
+ if (get_user(idx, &user_desc->entry_number))
+ return -EFAULT;
+
+ ret = get_tls_entry(current, &info, idx);
+ if (ret < 0)
+ goto out;
+
+ if (copy_to_user(user_desc, &info, sizeof(info)))
+ ret = -EFAULT;
+
+out:
+ return ret;
+}
+
+/*
+ * Perform get_thread_area on behalf of the traced child.
+ */
+int ptrace_get_thread_area(struct task_struct *child, int idx,
+ struct user_desc __user *user_desc)
+{
+ struct user_desc info;
+ int ret;
+
+ if (!host_supports_tls)
+ return -EIO;
+
+ ret = get_tls_entry(child, &info, idx);
+ if (ret < 0)
+ goto out;
+
+ if (copy_to_user(user_desc, &info, sizeof(info)))
+ ret = -EFAULT;
+out:
+ return ret;
+}
+
+
+/* XXX: This part is probably common to i386 and x86-64. Don't create a common
+ * file for now, do that when implementing x86-64 support.*/
+static int __init __setup_host_supports_tls(void) {
+ check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
+ if (host_supports_tls) {
+ printk(KERN_INFO "Host TLS support detected\n");
+ printk(KERN_INFO "Detected host type: ");
+ switch (host_gdt_entry_tls_min) {
+ case GDT_ENTRY_TLS_MIN_I386:
+ printk("i386\n");
+ break;
+ case GDT_ENTRY_TLS_MIN_X86_64:
+ printk("x86_64\n");
+ break;
+ }
+ } else
+ printk(KERN_ERR " Host TLS support NOT detected! "
+ "TLS support inside UML will not work\n");
+ return 0;
+}
+
+__initcall(__setup_host_supports_tls);
diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c
index 26b68675053..6f4ef2b7fa4 100644
--- a/arch/um/sys-i386/user-offsets.c
+++ b/arch/um/sys-i386/user-offsets.c
@@ -3,12 +3,13 @@
#include <asm/ptrace.h>
#include <asm/user.h>
#include <linux/stddef.h>
+#include <sys/poll.h>
#define DEFINE(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define DEFINE_LONGS(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
#define OFFSET(sym, str, mem) \
DEFINE(sym, offsetof(struct str, mem));
@@ -67,4 +68,9 @@ void foo(void)
DEFINE(HOST_ES, ES);
DEFINE(HOST_GS, GS);
DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
+
+ /* XXX Duplicated between i386 and x86_64 */
+ DEFINE(UM_POLLIN, POLLIN);
+ DEFINE(UM_POLLPRI, POLLPRI);
+ DEFINE(UM_POLLOUT, POLLOUT);
}
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index a351091fbd9..c19794d435d 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -4,31 +4,28 @@
# Licensed under the GPL
#
-#XXX: why into lib-y?
-lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o ldt.o mem.o memcpy.o \
- ptrace.o ptrace_user.o sigcontext.o signal.o syscalls.o \
- syscall_table.o sysrq.o thunk.o
-lib-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
+obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
+ sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o ksyms.o \
+ tls.o
-obj-y := ksyms.o
-obj-$(CONFIG_MODULES) += module.o um_module.o
+obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
+obj-$(CONFIG_MODULES) += um_module.o
-USER_OBJS := ptrace_user.o sigcontext.o stub_segv.o
+subarch-obj-y = lib/bitops.o lib/csum-partial.o lib/memcpy.o lib/thunk.o
+subarch-obj-$(CONFIG_MODULES) += kernel/module.o
-SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c ldt.c memcpy.S \
- thunk.S module.c
+ldt-y = ../sys-i386/ldt.o
-include arch/um/scripts/Makefile.rules
+USER_OBJS := ptrace_user.o sigcontext.o
+
+USER_OBJS += user-offsets.s
+extra-y += user-offsets.s
-bitops.c-dir = lib
-csum-copy.S-dir = lib
-csum-partial.c-dir = lib
-csum-wrappers.c-dir = lib
-ldt.c-dir = /arch/um/sys-i386
-memcpy.S-dir = lib
-thunk.S-dir = lib
-module.c-dir = kernel
+extra-$(CONFIG_MODE_TT) += unmap.o
-$(obj)/stub_segv.o: _c_flags = $(call unprofile,$(CFLAGS))
+UNPROFILE_OBJS := stub_segv.o
+CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
+
+include arch/um/scripts/Makefile.rules
-include arch/um/scripts/Makefile.unmap
+$(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS))
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index 74eee5c7c6d..147bbf05cbc 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -8,6 +8,7 @@
#include <asm/ptrace.h>
#include <linux/sched.h>
#include <linux/errno.h>
+#include <linux/mm.h>
#include <asm/uaccess.h>
#include <asm/elf.h>
@@ -136,9 +137,28 @@ void arch_switch(void)
*/
}
+/* XXX Mostly copied from sys-i386 */
int is_syscall(unsigned long addr)
{
- panic("is_syscall");
+ unsigned short instr;
+ int n;
+
+ n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
+ if(n){
+ /* access_process_vm() grants access to vsyscall and stub,
+ * while copy_from_user doesn't. Maybe access_process_vm is
+ * slow, but that doesn't matter, since it will be called only
+ * in case of singlestepping, if copy_from_user failed.
+ */
+ n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+ if(n != sizeof(instr)) {
+ printk("is_syscall : failed to read instruction from "
+ "0x%lx\n", addr);
+ return(1);
+ }
+ }
+ /* sysenter */
+ return(instr == 0x050f);
}
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu )
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index fe1d065332b..9edf114faf7 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -21,7 +21,7 @@
#include "skas.h"
static int copy_sc_from_user_skas(struct pt_regs *regs,
- struct sigcontext *from)
+ struct sigcontext __user *from)
{
int err = 0;
@@ -54,8 +54,10 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
return(err);
}
-int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
- struct pt_regs *regs, unsigned long mask)
+int copy_sc_to_user_skas(struct sigcontext __user *to,
+ struct _fpstate __user *to_fp,
+ struct pt_regs *regs, unsigned long mask,
+ unsigned long sp)
{
struct faultinfo * fi = &current->thread.arch.faultinfo;
int err = 0;
@@ -70,7 +72,11 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
err |= PUTREG(regs, RDI, to, rdi);
err |= PUTREG(regs, RSI, to, rsi);
err |= PUTREG(regs, RBP, to, rbp);
- err |= PUTREG(regs, RSP, to, rsp);
+ /* Must use orignal RSP, which is passed in, rather than what's in
+ * the pt_regs, because that's already been updated to point at the
+ * signal frame.
+ */
+ err |= __put_user(sp, &to->rsp);
err |= PUTREG(regs, RBX, to, rbx);
err |= PUTREG(regs, RDX, to, rdx);
err |= PUTREG(regs, RCX, to, rcx);
@@ -101,10 +107,11 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
#endif
#ifdef CONFIG_MODE_TT
-int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
- int fpsize)
+int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
+ int fpsize)
{
- struct _fpstate *to_fp, *from_fp;
+ struct _fpstate *to_fp;
+ struct _fpstate __user *from_fp;
unsigned long sigs;
int err;
@@ -119,20 +126,27 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
return(err);
}
-int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
- struct sigcontext *from, int fpsize)
+int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
+ struct sigcontext *from, int fpsize, unsigned long sp)
{
- struct _fpstate *to_fp, *from_fp;
+ struct _fpstate __user *to_fp;
+ struct _fpstate *from_fp;
int err;
- to_fp = (fp ? fp : (struct _fpstate *) (to + 1));
+ to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1));
from_fp = from->fpstate;
err = copy_to_user(to, from, sizeof(*to));
+ /* The SP in the sigcontext is the updated one for the signal
+ * delivery. The sp passed in is the original, and this needs
+ * to be restored, so we stick it in separately.
+ */
+ err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp));
+
if(from_fp != NULL){
err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
err |= copy_to_user(to_fp, from_fp, fpsize);
}
- return(err);
+ return err;
}
#endif
@@ -147,17 +161,19 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
return(ret);
}
-static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
- struct pt_regs *from, unsigned long mask)
+static int copy_sc_to_user(struct sigcontext __user *to,
+ struct _fpstate __user *fp,
+ struct pt_regs *from, unsigned long mask,
+ unsigned long sp)
{
return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
- sizeof(*fp)),
- copy_sc_to_user_skas(to, fp, from, mask)));
+ sizeof(*fp), sp),
+ copy_sc_to_user_skas(to, fp, from, mask, sp)));
}
struct rt_sigframe
{
- char *pretcode;
+ char __user *pretcode;
struct ucontext uc;
struct siginfo info;
};
@@ -170,12 +186,13 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
{
struct rt_sigframe __user *frame;
struct _fpstate __user *fp = NULL;
+ unsigned long save_sp = PT_REGS_RSP(regs);
int err = 0;
struct task_struct *me = current;
frame = (struct rt_sigframe __user *)
round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8;
- frame = (struct rt_sigframe *) ((unsigned long) frame - 128);
+ frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128);
if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate)))
goto out;
@@ -193,14 +210,25 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
goto out;
}
+ /* Update SP now because the page fault handler refuses to extend
+ * the stack if the faulting address is too far below the current
+ * SP, which frame now certainly is. If there's an error, the original
+ * value is restored on the way out.
+ * When writing the sigcontext to the stack, we have to write the
+ * original value, so that's passed to copy_sc_to_user, which does
+ * the right thing with it.
+ */
+ PT_REGS_RSP(regs) = (unsigned long) frame;
+
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)),
+ err |= __put_user(sas_ss_flags(save_sp),
&frame->uc.uc_stack.ss_flags);
err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
- err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
+ err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0],
+ save_sp);
err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate);
if (sizeof(*set) == 16) {
__put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
@@ -217,10 +245,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
else
/* could use a vstub here */
- goto out;
+ goto restore_sp;
if (err)
- goto out;
+ goto restore_sp;
/* Set up registers for signal handler */
{
@@ -238,10 +266,12 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
PT_REGS_RSI(regs) = (unsigned long) &frame->info;
PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
-
- PT_REGS_RSP(regs) = (unsigned long) frame;
out:
- return(err);
+ return err;
+
+restore_sp:
+ PT_REGS_RSP(regs) = save_sp;
+ return err;
}
long sys_rt_sigreturn(struct pt_regs *regs)
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
index a2709953319..1c967026c95 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -33,7 +33,7 @@ stub_segv_handler(int sig)
struct ucontext *uc;
int pid;
- __asm__("movq %%rdx, %0" : "=g" (uc) :);
+ __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
&uc->uc_mcontext);
@@ -44,8 +44,8 @@ stub_segv_handler(int sig)
* the signal frame. So, we use the ucontext pointer, which we know
* already, to get the signal frame pointer, and add 8 to that.
*/
- __asm__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
- "g" ((unsigned long) container_of(uc, struct rt_sigframe,
- uc) + 8),
- "g" (__NR_rt_sigreturn));
+ __asm__ __volatile__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
+ "g" ((unsigned long)
+ container_of(uc, struct rt_sigframe, uc) + 8),
+ "g" (__NR_rt_sigreturn));
}
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index 6acee5c4ada..6fce9f45dfd 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -45,7 +45,7 @@ static long arch_prctl_tt(int code, unsigned long addr)
case ARCH_GET_GS:
ret = arch_prctl(code, (unsigned long) &tmp);
if(!ret)
- ret = put_user(tmp, &addr);
+ ret = put_user(tmp, (long __user *)addr);
break;
default:
ret = -EINVAL;
diff --git a/arch/um/sys-x86_64/tls.c b/arch/um/sys-x86_64/tls.c
new file mode 100644
index 00000000000..ce1bf1b81c4
--- /dev/null
+++ b/arch/um/sys-x86_64/tls.c
@@ -0,0 +1,14 @@
+#include "linux/sched.h"
+
+void debug_arch_force_load_TLS(void)
+{
+}
+
+void clear_flushed_tls(struct task_struct *task)
+{
+}
+
+int arch_copy_tls(struct task_struct *t)
+{
+ return 0;
+}
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c
index 7bd54a921cf..899cebb57c3 100644
--- a/arch/um/sys-x86_64/user-offsets.c
+++ b/arch/um/sys-x86_64/user-offsets.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stddef.h>
#include <signal.h>
+#include <sys/poll.h>
#define __FRAME_OFFSETS
#include <asm/ptrace.h>
#include <asm/types.h>
@@ -88,4 +89,9 @@ void foo(void)
DEFINE_LONGS(HOST_IP, RIP);
DEFINE_LONGS(HOST_SP, RSP);
DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
+
+ /* XXX Duplicated between i386 and x86_64 */
+ DEFINE(UM_POLLIN, POLLIN);
+ DEFINE(UM_POLLPRI, POLLPRI);
+ DEFINE(UM_POLLOUT, POLLOUT);
}
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
index 8ffc29c1c89..6bcfcfe8838 100644
--- a/arch/v850/kernel/v850_ksyms.c
+++ b/arch/v850/kernel/v850_ksyms.c
@@ -43,7 +43,6 @@ EXPORT_SYMBOL (strncmp);
EXPORT_SYMBOL (strchr);
EXPORT_SYMBOL (strlen);
EXPORT_SYMBOL (strnlen);
-EXPORT_SYMBOL (strpbrk);
EXPORT_SYMBOL (strrchr);
EXPORT_SYMBOL (strstr);
EXPORT_SYMBOL (memset);
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 45efe0ca88f..6527a368fb9 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -136,6 +136,11 @@ config X86_L1_CACHE_SHIFT
default "7" if GENERIC_CPU || MPSC
default "6" if MK8
+config X86_INTERNODE_CACHE_BYTES
+ int
+ default "4096" if X86_VSMP
+ default X86_L1_CACHE_BYTES if !X86_VSMP
+
config X86_TSC
bool
default y
@@ -250,6 +255,15 @@ config SCHED_SMT
cost of slightly increased overhead in some places. If unsure say
N here.
+config SCHED_MC
+ bool "Multi-core scheduler support"
+ depends on SMP
+ default y
+ help
+ Multi-core scheduler support improves the CPU scheduler's decision
+ making when dealing with multi-core CPU chips at a cost of slightly
+ increased overhead in some places. If unsure say N here.
+
source "kernel/Kconfig.preempt"
config NUMA
@@ -274,12 +288,18 @@ config K8_NUMA
Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA
instead, which also takes priority if both are compiled in.
+config NODES_SHIFT
+ int
+ default "6"
+ depends on NEED_MULTIPLE_NODES
+
# Dummy CONFIG option to select ACPI_NUMA from drivers/acpi/Kconfig.
config X86_64_ACPI_NUMA
bool "ACPI NUMA detection"
depends on NUMA
select ACPI
+ select PCI
select ACPI_NUMA
default y
help
@@ -325,6 +345,10 @@ config HAVE_ARCH_EARLY_PFN_TO_NID
def_bool y
depends on NUMA
+config OUT_OF_LINE_PFN_TO_PAGE
+ def_bool y
+ depends on DISCONTIGMEM
+
config NR_CPUS
int "Maximum number of CPUs (2-256)"
range 2 255
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index 585fd4a559c..e573e2ab551 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -24,37 +24,37 @@
LDFLAGS := -m elf_x86_64
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
LDFLAGS_vmlinux :=
-
CHECKFLAGS += -D__x86_64__ -m64
+cflags-y :=
cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic)
-CFLAGS += $(cflags-y)
-CFLAGS += -m64
-CFLAGS += -mno-red-zone
-CFLAGS += -mcmodel=kernel
-CFLAGS += -pipe
+cflags-y += -m64
+cflags-y += -mno-red-zone
+cflags-y += -mcmodel=kernel
+cflags-y += -pipe
cflags-$(CONFIG_REORDER) += -ffunction-sections
# this makes reading assembly source easier, but produces worse code
# actually it makes the kernel smaller too.
-CFLAGS += -fno-reorder-blocks
-CFLAGS += -Wno-sign-compare
+cflags-y += -fno-reorder-blocks
+cflags-y += -Wno-sign-compare
ifneq ($(CONFIG_UNWIND_INFO),y)
-CFLAGS += -fno-asynchronous-unwind-tables
+cflags-y += -fno-asynchronous-unwind-tables
endif
ifneq ($(CONFIG_DEBUG_INFO),y)
# -fweb shrinks the kernel a bit, but the difference is very small
# it also messes up debugging, so don't use it for now.
-#CFLAGS += $(call cc-option,-fweb)
+#cflags-y += $(call cc-option,-fweb)
endif
# -funit-at-a-time shrinks the kernel .text considerably
# unfortunately it makes reading oopses harder.
-CFLAGS += $(call cc-option,-funit-at-a-time)
+cflags-y += $(call cc-option,-funit-at-a-time)
# prevent gcc from generating any FP code by mistake
-CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+CFLAGS += $(cflags-y)
AFLAGS += -m64
head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
diff --git a/arch/x86_64/boot/video.S b/arch/x86_64/boot/video.S
index 0587477c99f..32327bb37af 100644
--- a/arch/x86_64/boot/video.S
+++ b/arch/x86_64/boot/video.S
@@ -97,6 +97,7 @@
#define PARAM_VESAPM_OFF 0x30
#define PARAM_LFB_PAGES 0x32
#define PARAM_VESA_ATTRIB 0x34
+#define PARAM_CAPABILITIES 0x36
/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
#ifdef CONFIG_VIDEO_RETAIN
@@ -233,6 +234,10 @@ mopar_gr:
movw 18(%di), %ax
movl %eax, %fs:(PARAM_LFB_SIZE)
+# store mode capabilities
+ movl 10(%di), %eax
+ movl %eax, %fs:(PARAM_CAPABILITIES)
+
# switching the DAC to 8-bit is for <= 8 bpp only
movw %fs:(PARAM_LFB_DEPTH), %ax
cmpw $8, %ax
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 566ecc97ee5..69db0c0721d 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-git9
-# Sat Mar 25 15:18:40 2006
+# Linux kernel version: 2.6.17-rc1-git11
+# Sun Apr 16 07:22:36 2006
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -9,6 +9,7 @@ CONFIG_X86=y
CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_MMU=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_X86_CMPXCHG=y
CONFIG_EARLY_PRINTK=y
@@ -55,11 +56,8 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
+CONFIG_DOUBLEFAULT=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -70,7 +68,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
@@ -81,6 +78,7 @@ CONFIG_STOP_MACHINE=y
#
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -105,6 +103,7 @@ CONFIG_X86_PC=y
CONFIG_GENERIC_CPU=y
CONFIG_X86_L1_CACHE_BYTES=128
CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_INTERNODE_CACHE_BYTES=128
CONFIG_X86_TSC=y
CONFIG_X86_GOOD_APIC=y
# CONFIG_MICROCODE is not set
@@ -116,12 +115,14 @@ CONFIG_X86_LOCAL_APIC=y
CONFIG_MTRR=y
CONFIG_SMP=y
CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
CONFIG_PREEMPT_BKL=y
CONFIG_NUMA=y
CONFIG_K8_NUMA=y
+CONFIG_NODES_SHIFT=6
CONFIG_X86_64_ACPI_NUMA=y
CONFIG_NUMA_EMU=y
CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
@@ -138,6 +139,7 @@ CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_OUT_OF_LINE_PFN_TO_PAGE=y
CONFIG_NR_CPUS=32
CONFIG_HOTPLUG_CPU=y
CONFIG_HPET_TIMER=y
@@ -289,6 +291,7 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -300,6 +303,7 @@ CONFIG_IPV6=y
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_NETFILTER is not set
@@ -542,7 +546,6 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
@@ -704,7 +707,6 @@ CONFIG_S2IO=m
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
#
# Wan interfaces
@@ -791,7 +793,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -921,6 +923,7 @@ CONFIG_HWMON=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -932,6 +935,8 @@ CONFIG_VIDEO_SELECT=y
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=256
CONFIG_DUMMY_CONSOLE=y
#
@@ -1041,9 +1046,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_ACECAD is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -1058,15 +1061,6 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1118,9 +1112,23 @@ CONFIG_USB_MON=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
+# CONFIG_IPATH_CORE is not set
#
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -1128,6 +1136,11 @@ CONFIG_USB_MON=y
# CONFIG_EDAC is not set
#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
# Firmware Drivers
#
# CONFIG_EDD is not set
diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
index 929e6b0771f..e9263b4975e 100644
--- a/arch/x86_64/ia32/Makefile
+++ b/arch/x86_64/ia32/Makefile
@@ -27,5 +27,5 @@ $(obj)/vsyscall-sysenter.so $(obj)/vsyscall-syscall.so: \
$(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
$(call if_changed,syscall)
-AFLAGS_vsyscall-sysenter.o = -m32
-AFLAGS_vsyscall-syscall.o = -m32
+AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32
+AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index e776139afb2..926c4743d13 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -339,7 +339,7 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top,
struct mm_struct *mm = current->mm;
int i, ret;
- stack_base = IA32_STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE;
+ stack_base = stack_top - MAX_ARG_PAGES * PAGE_SIZE;
mm->arg_start = bprm->p + stack_base;
bprm->p += stack_base;
@@ -357,7 +357,7 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top,
{
mpnt->vm_mm = mm;
mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
- mpnt->vm_end = IA32_STACK_TOP;
+ mpnt->vm_end = stack_top;
if (executable_stack == EXSTACK_ENABLE_X)
mpnt->vm_flags = VM_STACK_FLAGS | VM_EXEC;
else if (executable_stack == EXSTACK_DISABLE_X)
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 7549a4389fb..5a92fed2d1d 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -15,6 +15,8 @@
#include <asm/vsyscall32.h>
#include <linux/linkage.h>
+#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
+
.macro IA32_ARG_FIXUP noebp=0
movl %edi,%r8d
.if \noebp
@@ -109,8 +111,8 @@ ENTRY(ia32_sysenter_target)
CFI_REMEMBER_STATE
jnz sysenter_tracesys
sysenter_do_call:
- cmpl $(IA32_NR_syscalls),%eax
- jae ia32_badsys
+ cmpl $(IA32_NR_syscalls-1),%eax
+ ja ia32_badsys
IA32_ARG_FIXUP 1
call *ia32_sys_call_table(,%rax,8)
movq %rax,RAX-ARGOFFSET(%rsp)
@@ -210,8 +212,8 @@ ENTRY(ia32_cstar_target)
CFI_REMEMBER_STATE
jnz cstar_tracesys
cstar_do_call:
- cmpl $IA32_NR_syscalls,%eax
- jae ia32_badsys
+ cmpl $IA32_NR_syscalls-1,%eax
+ ja ia32_badsys
IA32_ARG_FIXUP 1
call *ia32_sys_call_table(,%rax,8)
movq %rax,RAX-ARGOFFSET(%rsp)
@@ -296,8 +298,8 @@ ENTRY(ia32_syscall)
testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
jnz ia32_tracesys
ia32_do_syscall:
- cmpl $(IA32_NR_syscalls),%eax
- jae ia32_badsys
+ cmpl $(IA32_NR_syscalls-1),%eax
+ ja ia32_badsys
IA32_ARG_FIXUP
call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
ia32_sysret:
@@ -685,10 +687,13 @@ ia32_sys_call_table:
.quad sys_readlinkat /* 305 */
.quad sys_fchmodat
.quad sys_faccessat
- .quad sys_ni_syscall /* pselect6 for now */
- .quad sys_ni_syscall /* ppoll for now */
+ .quad quiet_ni_syscall /* pselect6 for now */
+ .quad quiet_ni_syscall /* ppoll for now */
.quad sys_unshare /* 310 */
+ .quad compat_sys_set_robust_list
+ .quad compat_sys_get_robust_list
+ .quad sys_splice
+ .quad sys_sync_file_range
+ .quad sys_tee
+ .quad compat_sys_vmsplice
ia32_syscall_end:
- .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
- .quad ni_syscall
- .endr
diff --git a/arch/x86_64/ia32/vsyscall-sigreturn.S b/arch/x86_64/ia32/vsyscall-sigreturn.S
index d90321fe9bb..1384367cdbe 100644
--- a/arch/x86_64/ia32/vsyscall-sigreturn.S
+++ b/arch/x86_64/ia32/vsyscall-sigreturn.S
@@ -32,9 +32,28 @@ __kernel_rt_sigreturn:
.size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn
.section .eh_frame,"a",@progbits
+.LSTARTFRAMES:
+ .long .LENDCIES-.LSTARTCIES
+.LSTARTCIES:
+ .long 0 /* CIE ID */
+ .byte 1 /* Version number */
+ .string "zRS" /* NUL-terminated augmentation string */
+ .uleb128 1 /* Code alignment factor */
+ .sleb128 -4 /* Data alignment factor */
+ .byte 8 /* Return address register column */
+ .uleb128 1 /* Augmentation value length */
+ .byte 0x1b /* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */
+ .byte 0x0c /* DW_CFA_def_cfa */
+ .uleb128 4
+ .uleb128 4
+ .byte 0x88 /* DW_CFA_offset, column 0x8 */
+ .uleb128 1
+ .align 4
+.LENDCIES:
+
.long .LENDFDE2-.LSTARTFDE2 /* Length FDE */
.LSTARTFDE2:
- .long .LSTARTFDE2-.LSTARTFRAME /* CIE pointer */
+ .long .LSTARTFDE2-.LSTARTFRAMES /* CIE pointer */
/* HACK: The dwarf2 unwind routines will subtract 1 from the
return address to get an address in the middle of the
presumed call instruction. Since we didn't get here via
@@ -97,7 +116,7 @@ __kernel_rt_sigreturn:
.long .LENDFDE3-.LSTARTFDE3 /* Length FDE */
.LSTARTFDE3:
- .long .LSTARTFDE3-.LSTARTFRAME /* CIE pointer */
+ .long .LSTARTFDE3-.LSTARTFRAMES /* CIE pointer */
/* HACK: See above wrt unwind library assumptions. */
.long .LSTART_rt_sigreturn-1-. /* PC-relative start address */
.long .LEND_rt_sigreturn-.LSTART_rt_sigreturn+1
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index a098a11e775..059c88313f4 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -8,7 +8,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
x8664_ksyms.o i387.o syscall.o vsyscall.o \
setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \
- dmi_scan.o pci-dma.o pci-nommu.o
+ pci-dma.o pci-nommu.o
obj-$(CONFIG_X86_MCE) += mce.o
obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o
@@ -49,5 +49,3 @@ intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o
quirks-y += ../../i386/kernel/quirks.o
i8237-y += ../../i386/kernel/i8237.o
msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
-dmi_scan-y += ../../i386/kernel/dmi_scan.o
-
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index fffd6b0a2fa..70b9d21ed67 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -80,7 +80,7 @@ static int __init aperture_valid(char *name, u64 aper_base, u32 aper_size)
printk("Aperture from %s beyond 4GB. Ignoring.\n",name);
return 0;
}
- if (e820_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
+ if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name);
return 0;
}
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index d54620147e8..100a30c4004 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -615,7 +615,7 @@ static int __init apic_set_verbosity(char *str)
printk(KERN_WARNING "APIC Verbosity level %s not recognised"
" use apic=verbose or apic=debug", str);
- return 0;
+ return 1;
}
__setup("apic=", apic_set_verbosity);
@@ -1137,35 +1137,35 @@ int __init APIC_init_uniprocessor (void)
static __init int setup_disableapic(char *str)
{
disable_apic = 1;
- return 0;
+ return 1;
}
static __init int setup_nolapic(char *str)
{
disable_apic = 1;
- return 0;
+ return 1;
}
static __init int setup_noapictimer(char *str)
{
if (str[0] != ' ' && str[0] != 0)
- return -1;
+ return 0;
disable_apic_timer = 1;
- return 0;
+ return 1;
}
static __init int setup_apicmaintimer(char *str)
{
apic_runs_main_timer = 1;
nohpet = 1;
- return 0;
+ return 1;
}
__setup("apicmaintimer", setup_apicmaintimer);
static __init int setup_noapicmaintimer(char *str)
{
apic_runs_main_timer = -1;
- return 0;
+ return 1;
}
__setup("noapicmaintimer", setup_noapicmaintimer);
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 293cd71a266..1ef6028f721 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -76,11 +76,22 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
*addrp = __pa_symbol(&_end);
return 1;
}
+
+ if (last >= ebda_addr && addr < ebda_addr + ebda_size) {
+ *addrp = ebda_addr + ebda_size;
+ return 1;
+ }
+
/* XXX ramdisk image here? */
return 0;
}
-int __init e820_mapped(unsigned long start, unsigned long end, unsigned type)
+/*
+ * This function checks if any part of the range <start,end> is mapped
+ * with type.
+ */
+int __meminit
+e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
{
int i;
for (i = 0; i < e820.nr_map; i++) {
@@ -94,6 +105,35 @@ int __init e820_mapped(unsigned long start, unsigned long end, unsigned type)
return 0;
}
+/*
+ * This function checks if the entire range <start,end> is mapped with type.
+ *
+ * Note: this function only works correct if the e820 table is sorted and
+ * not-overlapping, which is the case
+ */
+int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
+{
+ int i;
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+ if (type && ei->type != type)
+ continue;
+ /* is the region (part) in overlap with the current region ?*/
+ if (ei->addr >= end || ei->addr + ei->size <= start)
+ continue;
+
+ /* if the region is at the beginning of <start,end> we move
+ * start to the end of the region since it's ok until there
+ */
+ if (ei->addr <= start)
+ start = ei->addr + ei->size;
+ /* if start is now at or beyond end, we're done, full coverage */
+ if (start >= end)
+ return 1; /* we're done */
+ }
+ return 0;
+}
+
/*
* Find a free area in a specific range.
*/
@@ -109,7 +149,7 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsi
addr = start;
if (addr > ei->addr + ei->size)
continue;
- while (bad_addr(&addr, size) && addr+size < ei->addr + ei->size)
+ while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
;
last = addr + size;
if (last > ei->addr + ei->size)
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index 13af920b659..b93ef5b5198 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -221,7 +221,7 @@ int __init setup_early_printk(char *opt)
char buf[256];
if (early_console_initialized)
- return -1;
+ return 1;
strlcpy(buf,opt,sizeof(buf));
space = strchr(buf, ' ');
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 8538bfea30e..586b34c00c4 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -180,6 +180,10 @@ rff_trace:
*
* XXX if we had a free scratch register we could save the RSP into the stack frame
* and report it properly in ps. Unfortunately we haven't.
+ *
+ * When user can change the frames always force IRET. That is because
+ * it deals with uncanonical addresses better. SYSRET has trouble
+ * with them due to bugs in both AMD and Intel CPUs.
*/
ENTRY(system_call)
@@ -254,7 +258,10 @@ sysret_signal:
xorl %esi,%esi # oldset -> arg2
call ptregscall_common
1: movl $_TIF_NEED_RESCHED,%edi
- jmp sysret_check
+ /* Use IRET because user could have changed frame. This
+ works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
+ cli
+ jmp int_with_check
badsys:
movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
@@ -274,13 +281,9 @@ tracesys:
ja 1f
movq %r10,%rcx /* fixup for C */
call *sys_call_table(,%rax,8)
- movq %rax,RAX-ARGOFFSET(%rsp)
-1: SAVE_REST
- movq %rsp,%rdi
- call syscall_trace_leave
- RESTORE_TOP_OF_STACK %rbx
- RESTORE_REST
- jmp ret_from_sys_call
+1: movq %rax,RAX-ARGOFFSET(%rsp)
+ /* Use IRET because user could have changed frame */
+ jmp int_ret_from_sys_call
CFI_ENDPROC
/*
@@ -408,25 +411,9 @@ ENTRY(stub_execve)
CFI_ADJUST_CFA_OFFSET -8
CFI_REGISTER rip, r11
SAVE_REST
- movq %r11, %r15
- CFI_REGISTER rip, r15
FIXUP_TOP_OF_STACK %r11
call sys_execve
- GET_THREAD_INFO(%rcx)
- bt $TIF_IA32,threadinfo_flags(%rcx)
- CFI_REMEMBER_STATE
- jc exec_32bit
RESTORE_TOP_OF_STACK %r11
- movq %r15, %r11
- CFI_REGISTER rip, r11
- RESTORE_REST
- pushq %r11
- CFI_ADJUST_CFA_OFFSET 8
- CFI_REL_OFFSET rip, 0
- ret
-
-exec_32bit:
- CFI_RESTORE_STATE
movq %rax,RAX(%rsp)
RESTORE_REST
jmp int_ret_from_sys_call
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 77b4c608cca..9cc7031b715 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -271,6 +271,18 @@ __setup("enable_8254_timer", setup_enable_8254_timer);
#include <linux/pci_ids.h>
#include <linux/pci.h>
+
+#ifdef CONFIG_ACPI
+
+static int nvidia_hpet_detected __initdata;
+
+static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
+{
+ nvidia_hpet_detected = 1;
+ return 0;
+}
+#endif
+
/* Temporary Hack. Nvidia and VIA boards currently only work with IO-APIC
off. Check for an Nvidia or VIA PCI bridge and turn it off.
Use pci direct infrastructure because this runs before the PCI subsystem.
@@ -317,11 +329,19 @@ void __init check_ioapic(void)
return;
case PCI_VENDOR_ID_NVIDIA:
#ifdef CONFIG_ACPI
- /* All timer overrides on Nvidia
- seem to be wrong. Skip them. */
- acpi_skip_timer_override = 1;
- printk(KERN_INFO
- "Nvidia board detected. Ignoring ACPI timer override.\n");
+ /*
+ * All timer overrides on Nvidia are
+ * wrong unless HPET is enabled.
+ */
+ nvidia_hpet_detected = 0;
+ acpi_table_parse(ACPI_HPET,
+ nvidia_hpet_check);
+ if (nvidia_hpet_detected == 0) {
+ acpi_skip_timer_override = 1;
+ printk(KERN_INFO "Nvidia board "
+ "detected. Ignoring ACPI "
+ "timer override.\n");
+ }
#endif
/* RED-PEN skip them on mptables too? */
return;
@@ -1777,6 +1797,8 @@ static inline void unlock_ExtINT_logic(void)
spin_unlock_irqrestore(&ioapic_lock, flags);
}
+int timer_uses_ioapic_pin_0;
+
/*
* This code may look a bit paranoid, but it's supposed to cooperate with
* a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
@@ -1814,6 +1836,9 @@ static inline void check_timer(void)
pin2 = ioapic_i8259.pin;
apic2 = ioapic_i8259.apic;
+ if (pin1 == 0)
+ timer_uses_ioapic_pin_0 = 1;
+
apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
vector, apic1, pin1, apic2, pin2);
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index accbff3fec4..fa1d19ca700 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -53,7 +53,7 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
/*
* returns non-zero if opcode modifies the interrupt flag.
*/
-static inline int is_IF_modifier(kprobe_opcode_t *insn)
+static __always_inline int is_IF_modifier(kprobe_opcode_t *insn)
{
switch (*insn) {
case 0xfa: /* cli */
@@ -84,7 +84,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
* If it does, return the address of the 32-bit displacement word.
* If not, return null.
*/
-static inline s32 *is_riprel(u8 *insn)
+static s32 __kprobes *is_riprel(u8 *insn)
{
#define W(row,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf) \
(((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \
@@ -229,7 +229,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
mutex_unlock(&kprobe_mutex);
}
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -237,7 +237,7 @@ static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->prev_kprobe.saved_rflags = kcb->kprobe_saved_rflags;
}
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -245,7 +245,7 @@ static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->kprobe_saved_rflags = kcb->prev_kprobe.saved_rflags;
}
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
__get_cpu_var(current_kprobe) = p;
@@ -514,13 +514,13 @@ static void __kprobes resume_execution(struct kprobe *p,
*tos = orig_rip + (*tos - copy_rip);
break;
case 0xff:
- if ((*insn & 0x30) == 0x10) {
+ if ((insn[1] & 0x30) == 0x10) {
/* call absolute, indirect */
/* Fix return addr; rip is correct. */
next_rip = regs->rip;
*tos = orig_rip + (*tos - copy_rip);
- } else if (((*insn & 0x31) == 0x20) || /* jmp near, absolute indirect */
- ((*insn & 0x31) == 0x21)) { /* jmp far, absolute indirect */
+ } else if (((insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
+ ((insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */
/* rip is correct. */
next_rip = regs->rip;
}
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 04282ef9fbd..c69fc43cee7 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -29,6 +29,8 @@
#define MISC_MCELOG_MINOR 227
#define NR_BANKS 6
+atomic_t mce_entry;
+
static int mce_dont_init;
/* 0: always panic, 1: panic if deadlock possible, 2: try to avoid panic,
@@ -172,10 +174,12 @@ void do_machine_check(struct pt_regs * regs, long error_code)
int i;
int panicm_found = 0;
+ atomic_inc(&mce_entry);
+
if (regs)
notify_die(DIE_NMI, "machine check", regs, error_code, 18, SIGKILL);
if (!banks)
- return;
+ goto out2;
memset(&m, 0, sizeof(struct mce));
m.cpu = safe_smp_processor_id();
@@ -266,6 +270,8 @@ void do_machine_check(struct pt_regs * regs, long error_code)
out:
/* Last thing done in the machine check exception to clear state. */
wrmsrl(MSR_IA32_MCG_STATUS, 0);
+ out2:
+ atomic_dec(&mce_entry);
}
/*
@@ -501,7 +507,7 @@ static struct miscdevice mce_log_device = {
static int __init mcheck_disable(char *str)
{
mce_dont_init = 1;
- return 0;
+ return 1;
}
/* mce=off disables machine check. Note you can reenable it later
@@ -521,7 +527,7 @@ static int __init mcheck_enable(char *str)
get_option(&str, &tolerant);
else
printk("mce= argument %s ignored. Please use /sys", str);
- return 0;
+ return 1;
}
__setup("nomce", mcheck_disable);
@@ -623,7 +629,7 @@ static __cpuinit void mce_remove_device(unsigned int cpu)
#endif
/* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static __cpuinit int
+static int
mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c
index d3ad7d81266..d13b241ad09 100644
--- a/arch/x86_64/kernel/mce_amd.c
+++ b/arch/x86_64/kernel/mce_amd.c
@@ -482,7 +482,7 @@ static void threshold_remove_device(unsigned int cpu)
#endif
/* get notified when a cpu comes on/off */
-static __cpuinit int threshold_cpu_callback(struct notifier_block *nfb,
+static int threshold_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
/* cpu was unsigned int to begin with */
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index b17cf3eba35..083da7e606b 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -968,7 +968,17 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
*/
int irq = gsi;
if (gsi < MAX_GSI_NUM) {
- if (gsi > 15)
+ /*
+ * Retain the VIA chipset work-around (gsi > 15), but
+ * avoid a problem where the 8254 timer (IRQ0) is setup
+ * via an override (so it's not on pin 0 of the ioapic),
+ * and at the same time, the pin 0 interrupt is a PCI
+ * type. The gsi > 15 test could cause these two pins
+ * to be shared as IRQ0, and they are not shareable.
+ * So test for this condition, and if necessary, avoid
+ * the pin collision.
+ */
+ if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0))
gsi = pci_irq++;
/*
* Don't assign IRQ used by ACPI SCI
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index d9e4067faf0..4e6357fe0ec 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -34,6 +34,7 @@
#include <asm/proto.h>
#include <asm/kdebug.h>
#include <asm/local.h>
+#include <asm/mce.h>
/*
* lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
@@ -480,6 +481,12 @@ void __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
__get_cpu_var(nmi_touch) = 0;
touched = 1;
}
+#ifdef CONFIG_X86_MCE
+ /* Could check oops_in_progress here too, but it's safer
+ not too */
+ if (atomic_read(&mce_entry) > 0)
+ touched = 1;
+#endif
if (!touched && __get_cpu_var(last_irq_sum) == sum) {
/*
* Ayiee, looks like this CPU is stuck ...
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
index 03c9eeedb0f..a9275c9557c 100644
--- a/arch/x86_64/kernel/pci-dma.c
+++ b/arch/x86_64/kernel/pci-dma.c
@@ -48,10 +48,16 @@ dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
{
struct page *page;
int node;
+#ifdef CONFIG_PCI
if (dev->bus == &pci_bus_type)
node = pcibus_to_node(to_pci_dev(dev)->bus);
else
+#endif
node = numa_node_id();
+
+ if (node < first_node(node_online_map))
+ node = first_node(node_online_map);
+
page = alloc_pages_node(node, gfp, order);
return page ? page_address(page) : NULL;
}
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index a6c01e12126..82a7c9bfdfa 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -112,10 +112,6 @@ static unsigned long alloc_iommu(int size)
static void free_iommu(unsigned long offset, int size)
{
unsigned long flags;
- if (size == 1) {
- clear_bit(offset, iommu_gart_bitmap);
- return;
- }
spin_lock_irqsave(&iommu_bitmap_lock, flags);
__clear_bit_string(iommu_gart_bitmap, offset, size);
spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
@@ -635,14 +631,20 @@ static int __init pci_iommu_init(void)
printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n");
if (end_pfn > MAX_DMA32_PFN) {
printk(KERN_ERR "WARNING more than 4GB of memory "
- "but IOMMU not compiled in.\n"
- KERN_ERR "WARNING 32bit PCI may malfunction.\n"
- KERN_ERR "You might want to enable "
- "CONFIG_GART_IOMMU\n");
+ "but IOMMU not available.\n"
+ KERN_ERR "WARNING 32bit PCI may malfunction.\n");
}
return -1;
}
+ i = 0;
+ for_all_nb(dev)
+ i++;
+ if (i > MAX_NB) {
+ printk(KERN_ERR "PCI-GART: Too many northbridges (%ld). Disabled\n", i);
+ return -1;
+ }
+
printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n");
aper_size = info.aper_size * 1024 * 1024;
iommu_size = check_iommu_size(info.aper_base, aper_size);
diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c
index 44adcc2d5e5..1f6ecc62061 100644
--- a/arch/x86_64/kernel/pci-nommu.c
+++ b/arch/x86_64/kernel/pci-nommu.c
@@ -12,9 +12,10 @@ static int
check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
{
if (hwdev && bus + size > *hwdev->dma_mask) {
- printk(KERN_ERR
- "nommu_%s: overflow %Lx+%lu of device mask %Lx\n",
- name, (long long)bus, size, (long long)*hwdev->dma_mask);
+ if (*hwdev->dma_mask >= 0xffffffffULL)
+ printk(KERN_ERR
+ "nommu_%s: overflow %Lx+%lu of device mask %Lx\n",
+ name, (long long)bus, size, (long long)*hwdev->dma_mask);
return 0;
}
return 1;
diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c
index ee5ee4891f3..bf421ed2680 100644
--- a/arch/x86_64/kernel/pmtimer.c
+++ b/arch/x86_64/kernel/pmtimer.c
@@ -68,7 +68,7 @@ int pmtimer_mark_offset(void)
offset_delay = delta % (USEC_PER_SEC / HZ);
rdtscll(tsc);
- vxtime.last_tsc = tsc - offset_delay * cpu_khz;
+ vxtime.last_tsc = tsc - offset_delay * (u64)cpu_khz / 1000;
/* don't calculate delay for first run,
or if we've got less then a tick */
@@ -121,7 +121,7 @@ unsigned int do_gettimeoffset_pm(void)
static int __init nopmtimer_setup(char *s)
{
pmtmr_ioport = 0;
- return 0;
+ return 1;
}
__setup("nopmtimer", nopmtimer_setup);
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 0370720515f..fb903e65e07 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -66,24 +66,17 @@ EXPORT_SYMBOL(boot_option_idle_override);
void (*pm_idle)(void);
static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
-static struct notifier_block *idle_notifier;
-static DEFINE_SPINLOCK(idle_notifier_lock);
+static ATOMIC_NOTIFIER_HEAD(idle_notifier);
void idle_notifier_register(struct notifier_block *n)
{
- unsigned long flags;
- spin_lock_irqsave(&idle_notifier_lock, flags);
- notifier_chain_register(&idle_notifier, n);
- spin_unlock_irqrestore(&idle_notifier_lock, flags);
+ atomic_notifier_chain_register(&idle_notifier, n);
}
EXPORT_SYMBOL_GPL(idle_notifier_register);
void idle_notifier_unregister(struct notifier_block *n)
{
- unsigned long flags;
- spin_lock_irqsave(&idle_notifier_lock, flags);
- notifier_chain_unregister(&idle_notifier, n);
- spin_unlock_irqrestore(&idle_notifier_lock, flags);
+ atomic_notifier_chain_unregister(&idle_notifier, n);
}
EXPORT_SYMBOL(idle_notifier_unregister);
@@ -93,13 +86,13 @@ static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE;
void enter_idle(void)
{
__get_cpu_var(idle_state) = CPU_IDLE;
- notifier_call_chain(&idle_notifier, IDLE_START, NULL);
+ atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
}
static void __exit_idle(void)
{
__get_cpu_var(idle_state) = CPU_NOT_IDLE;
- notifier_call_chain(&idle_notifier, IDLE_END, NULL);
+ atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
}
/* Called from interrupts to signify idle end */
@@ -582,8 +575,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
prev->userrsp = read_pda(oldrsp);
write_pda(oldrsp, next->userrsp);
write_pda(pcurrent, next_p);
+
/* This must be here to ensure both math_state_restore() and
- kernel_fpu_begin() work consistently. */
+ kernel_fpu_begin() work consistently.
+ And the AMD workaround requires it to be after DS reload. */
unlazy_fpu(prev_p);
write_pda(kernelstack,
task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
@@ -788,10 +783,16 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
}
case ARCH_GET_GS: {
unsigned long base;
+ unsigned gsindex;
if (task->thread.gsindex == GS_TLS_SEL)
base = read_32bit_tls(task, GS_TLS);
- else if (doit)
- rdmsrl(MSR_KERNEL_GS_BASE, base);
+ else if (doit) {
+ asm("movl %%gs,%0" : "=r" (gsindex));
+ if (gsindex)
+ rdmsrl(MSR_KERNEL_GS_BASE, base);
+ else
+ base = task->thread.gs;
+ }
else
base = task->thread.gs;
ret = put_user(base, (unsigned long __user *)addr);
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index d44b2c1e63a..2d50024c9f3 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -274,11 +274,6 @@ static int putreg(struct task_struct *child,
return -EIO;
value &= 0xffff;
break;
- case offsetof(struct user_regs_struct, rip):
- /* Check if the new RIP address is canonical */
- if (value >= TASK_SIZE_OF(child))
- return -EIO;
- break;
}
put_stack_long(child, regno - sizeof(struct pt_regs), value);
return 0;
@@ -605,12 +600,12 @@ asmlinkage void syscall_trace_enter(struct pt_regs *regs)
if (unlikely(current->audit_context)) {
if (test_thread_flag(TIF_IA32)) {
- audit_syscall_entry(current, AUDIT_ARCH_I386,
+ audit_syscall_entry(AUDIT_ARCH_I386,
regs->orig_rax,
regs->rbx, regs->rcx,
regs->rdx, regs->rsi);
} else {
- audit_syscall_entry(current, AUDIT_ARCH_X86_64,
+ audit_syscall_entry(AUDIT_ARCH_X86_64,
regs->orig_rax,
regs->rdi, regs->rsi,
regs->rdx, regs->r10);
@@ -621,7 +616,7 @@ asmlinkage void syscall_trace_enter(struct pt_regs *regs)
asmlinkage void syscall_trace_leave(struct pt_regs *regs)
{
if (unlikely(current->audit_context))
- audit_syscall_exit(current, AUDITSC_RESULT(regs->rax), regs->rax);
+ audit_syscall_exit(AUDITSC_RESULT(regs->rax), regs->rax);
if ((test_thread_flag(TIF_SYSCALL_TRACE)
|| test_thread_flag(TIF_SINGLESTEP))
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index a57eec8311a..655b9192eeb 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -353,8 +353,10 @@ static __init void parse_cmdline_early (char ** cmdline_p)
if (fullarg(from, "enable_timer_pin_1"))
disable_timer_pin_1 = -1;
- if (fullarg(from, "nolapic") || fullarg(from, "disableapic"))
+ if (fullarg(from, "nolapic") || fullarg(from, "disableapic")) {
+ clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
disable_apic = 1;
+ }
if (fullarg(from, "noapic"))
skip_ioapic_setup = 1;
@@ -540,7 +542,7 @@ void __init alternative_instructions(void)
static int __init noreplacement_setup(char *s)
{
no_replacement = 1;
- return 0;
+ return 1;
}
__setup("noreplacement", noreplacement_setup);
@@ -569,17 +571,28 @@ static inline void copy_edd(void)
#endif
#define EBDA_ADDR_POINTER 0x40E
-static void __init reserve_ebda_region(void)
+
+unsigned __initdata ebda_addr;
+unsigned __initdata ebda_size;
+
+static void discover_ebda(void)
{
- unsigned int addr;
- /**
+ /*
* there is a real-mode segmented pointer pointing to the
* 4K EBDA area at 0x40E
*/
- addr = *(unsigned short *)phys_to_virt(EBDA_ADDR_POINTER);
- addr <<= 4;
- if (addr)
- reserve_bootmem_generic(addr, PAGE_SIZE);
+ ebda_addr = *(unsigned short *)EBDA_ADDR_POINTER;
+ ebda_addr <<= 4;
+
+ ebda_size = *(unsigned short *)(unsigned long)ebda_addr;
+
+ /* Round EBDA up to pages */
+ if (ebda_size == 0)
+ ebda_size = 1;
+ ebda_size <<= 10;
+ ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
+ if (ebda_size > 64*1024)
+ ebda_size = 64*1024;
}
void __init setup_arch(char **cmdline_p)
@@ -625,6 +638,8 @@ void __init setup_arch(char **cmdline_p)
check_efer();
+ discover_ebda();
+
init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
dmi_scan_machine();
@@ -667,7 +682,8 @@ void __init setup_arch(char **cmdline_p)
reserve_bootmem_generic(0, PAGE_SIZE);
/* reserve ebda region */
- reserve_ebda_region();
+ if (ebda_addr)
+ reserve_bootmem_generic(ebda_addr, ebda_size);
#ifdef CONFIG_SMP
/*
@@ -928,6 +944,10 @@ static int __init init_amd(struct cpuinfo_x86 *c)
if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
+ /* Enable workaround for FXSAVE leak */
+ if (c->x86 >= 6)
+ set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability);
+
r = get_model_name(c);
if (!r) {
switch (c->x86) {
@@ -962,7 +982,6 @@ static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
cpuid(1, &eax, &ebx, &ecx, &edx);
- c->apicid = phys_pkg_id(0);
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
return;
@@ -1032,7 +1051,7 @@ static void srat_detect_node(void)
for now. */
node = apicid_to_node[hard_smp_processor_id()];
if (node == NUMA_NO_NODE)
- node = 0;
+ node = first_node(node_online_map);
numa_set_node(cpu, node);
if (acpi_numa > 0)
@@ -1171,6 +1190,8 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
c->x86_capability[2] = cpuid_edx(0x80860001);
}
+ c->apicid = phys_pkg_id(0);
+
/*
* Vendor-specific initialization. In this section we
* canonicalize the feature flags, meaning if there are
@@ -1419,3 +1440,22 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo,
};
+#ifdef CONFIG_INPUT_PCSPKR
+#include <linux/platform_device.h>
+static __init int add_pcspkr(void)
+{
+ struct platform_device *pd;
+ int ret;
+
+ pd = platform_device_alloc("pcspkr", -1);
+ if (!pd)
+ return -ENOMEM;
+
+ ret = platform_device_add(pd);
+ if (ret)
+ platform_device_put(pd);
+
+ return ret;
+}
+device_initcall(add_pcspkr);
+#endif
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index eabdb63fec3..8a691fa6d39 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -55,7 +55,7 @@ int __init nonx_setup(char *str)
do_not_nx = 1;
__supported_pte_mask &= ~_PAGE_NX;
}
- return 0;
+ return 1;
}
__setup("noexec=", nonx_setup); /* parsed early actually */
@@ -74,7 +74,7 @@ static int __init nonx32_setup(char *str)
force_personality32 &= ~READ_IMPLIES_EXEC;
else if (!strcmp(str, "off"))
force_personality32 |= READ_IMPLIES_EXEC;
- return 0;
+ return 1;
}
__setup("noexec32=", nonx32_setup);
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 66e98659d07..71a7222cf9c 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -68,6 +68,9 @@ u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
/* core ID of each logical CPU */
u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
+/* Last level cache ID of each logical CPU */
+u8 cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID};
+
/* Bitmask of currently online CPUs */
cpumask_t cpu_online_map __read_mostly;
@@ -350,7 +353,7 @@ static void __cpuinit tsc_sync_wait(void)
static __init int notscsync_setup(char *s)
{
notscsync = 1;
- return 0;
+ return 1;
}
__setup("notscsync", notscsync_setup);
@@ -445,6 +448,18 @@ void __cpuinit smp_callin(void)
cpu_set(cpuid, cpu_callin_map);
}
+/* maps the cpu to the sched domain representing multi-core */
+cpumask_t cpu_coregroup_map(int cpu)
+{
+ struct cpuinfo_x86 *c = cpu_data + cpu;
+ /*
+ * For perf, we return last level cache shared map.
+ * TBD: when power saving sched policy is added, we will return
+ * cpu_core_map when power saving policy is enabled
+ */
+ return c->llc_shared_map;
+}
+
/* representing cpus for which sibling maps can be computed */
static cpumask_t cpu_sibling_setup_map;
@@ -463,12 +478,16 @@ static inline void set_cpu_sibling_map(int cpu)
cpu_set(cpu, cpu_sibling_map[i]);
cpu_set(i, cpu_core_map[cpu]);
cpu_set(cpu, cpu_core_map[i]);
+ cpu_set(i, c[cpu].llc_shared_map);
+ cpu_set(cpu, c[i].llc_shared_map);
}
}
} else {
cpu_set(cpu, cpu_sibling_map[cpu]);
}
+ cpu_set(cpu, c[cpu].llc_shared_map);
+
if (current_cpu_data.x86_max_cores == 1) {
cpu_core_map[cpu] = cpu_sibling_map[cpu];
c[cpu].booted_cores = 1;
@@ -476,6 +495,11 @@ static inline void set_cpu_sibling_map(int cpu)
}
for_each_cpu_mask(i, cpu_sibling_setup_map) {
+ if (cpu_llc_id[cpu] != BAD_APICID &&
+ cpu_llc_id[cpu] == cpu_llc_id[i]) {
+ cpu_set(i, c[cpu].llc_shared_map);
+ cpu_set(cpu, c[i].llc_shared_map);
+ }
if (phys_proc_id[cpu] == phys_proc_id[i]) {
cpu_set(i, cpu_core_map[cpu]);
cpu_set(cpu, cpu_core_map[i]);
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 7f58fa68249..7392570f975 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -504,42 +504,25 @@ unsigned long long sched_clock(void)
static unsigned long get_cmos_time(void)
{
- unsigned int timeout = 1000000, year, mon, day, hour, min, sec;
- unsigned char uip = 0, this = 0;
+ unsigned int year, mon, day, hour, min, sec;
unsigned long flags;
unsigned extyear = 0;
-/*
- * The Linux interpretation of the CMOS clock register contents: When the
- * Update-In-Progress (UIP) flag goes from 1 to 0, the RTC registers show the
- * second which has precisely just started. Waiting for this can take up to 1
- * second, we timeout approximately after 2.4 seconds on a machine with
- * standard 8.3 MHz ISA bus.
- */
-
spin_lock_irqsave(&rtc_lock, flags);
- while (timeout && (!uip || this)) {
- uip |= this;
- this = CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP;
- timeout--;
- }
-
- /*
- * Here we are safe to assume the registers won't change for a whole
- * second, so we just go ahead and read them.
- */
- sec = CMOS_READ(RTC_SECONDS);
- min = CMOS_READ(RTC_MINUTES);
- hour = CMOS_READ(RTC_HOURS);
- day = CMOS_READ(RTC_DAY_OF_MONTH);
- mon = CMOS_READ(RTC_MONTH);
- year = CMOS_READ(RTC_YEAR);
-
+ do {
+ sec = CMOS_READ(RTC_SECONDS);
+ min = CMOS_READ(RTC_MINUTES);
+ hour = CMOS_READ(RTC_HOURS);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
#ifdef CONFIG_ACPI
- if (acpi_fadt.revision >= FADT2_REVISION_ID && acpi_fadt.century)
- extyear = CMOS_READ(acpi_fadt.century);
+ if (acpi_fadt.revision >= FADT2_REVISION_ID &&
+ acpi_fadt.century)
+ extyear = CMOS_READ(acpi_fadt.century);
#endif
+ } while (sec != CMOS_READ(RTC_SECONDS));
spin_unlock_irqrestore(&rtc_lock, flags);
@@ -743,7 +726,7 @@ static __init int late_hpet_init(void)
unsigned int ntimer;
if (!vxtime.hpet_address)
- return -1;
+ return 0;
memset(&hd, 0, sizeof (hd));
@@ -934,6 +917,8 @@ void __init time_init(void)
vxtime.hpet_address = 0;
if (hpet_use_timer) {
+ /* set tick_nsec to use the proper rate for HPET */
+ tick_nsec = TICK_NSEC_HPET;
cpu_khz = hpet_calibrate_tsc();
timename = "HPET";
#ifdef CONFIG_X86_PM_TIMER
@@ -1323,7 +1308,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static int __init nohpet_setup(char *s)
{
nohpet = 1;
- return 0;
+ return 1;
}
__setup("nohpet", nohpet_setup);
@@ -1331,7 +1316,7 @@ __setup("nohpet", nohpet_setup);
int __init notsc_setup(char *s)
{
notsc = 1;
- return 0;
+ return 1;
}
__setup("notsc", notsc_setup);
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 7b148309c52..cea335e8746 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -30,6 +30,7 @@
#include <linux/moduleparam.h>
#include <linux/nmi.h>
#include <linux/kprobes.h>
+#include <linux/kexec.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -69,20 +70,20 @@ asmlinkage void alignment_check(void);
asmlinkage void machine_check(void);
asmlinkage void spurious_interrupt_bug(void);
-struct notifier_block *die_chain;
-static DEFINE_SPINLOCK(die_notifier_lock);
+ATOMIC_NOTIFIER_HEAD(die_chain);
int register_die_notifier(struct notifier_block *nb)
{
- int err = 0;
- unsigned long flags;
-
vmalloc_sync_all();
- spin_lock_irqsave(&die_notifier_lock, flags);
- err = notifier_chain_register(&die_chain, nb);
- spin_unlock_irqrestore(&die_notifier_lock, flags);
- return err;
+ return atomic_notifier_chain_register(&die_chain, nb);
+}
+EXPORT_SYMBOL(register_die_notifier);
+
+int unregister_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&die_chain, nb);
}
+EXPORT_SYMBOL(unregister_die_notifier);
static inline void conditional_sti(struct pt_regs *regs)
{
@@ -101,6 +102,8 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
{
if (regs->eflags & X86_EFLAGS_IF)
local_irq_disable();
+ /* Make sure to not schedule here because we could be running
+ on an exception stack. */
preempt_enable_no_resched();
}
@@ -384,6 +387,7 @@ void out_of_line_bug(void)
static DEFINE_SPINLOCK(die_lock);
static int die_owner = -1;
+static unsigned int die_nest_count;
unsigned __kprobes long oops_begin(void)
{
@@ -398,6 +402,7 @@ unsigned __kprobes long oops_begin(void)
else
spin_lock(&die_lock);
}
+ die_nest_count++;
die_owner = cpu;
console_verbose();
bust_spinlocks(1);
@@ -408,7 +413,13 @@ void __kprobes oops_end(unsigned long flags)
{
die_owner = -1;
bust_spinlocks(0);
- spin_unlock_irqrestore(&die_lock, flags);
+ die_nest_count--;
+ if (die_nest_count)
+ /* We still own the lock */
+ local_irq_restore(flags);
+ else
+ /* Nest count reaches zero, release the lock. */
+ spin_unlock_irqrestore(&die_lock, flags);
if (panic_on_oops)
panic("Oops");
}
@@ -433,6 +444,8 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err)
printk(KERN_ALERT "RIP ");
printk_address(regs->rip);
printk(" RSP <%016lx>\n", regs->rsp);
+ if (kexec_should_crash(current))
+ crash_kexec(regs);
}
void die(const char * str, struct pt_regs * regs, long err)
@@ -455,10 +468,14 @@ void __kprobes die_nmi(char *str, struct pt_regs *regs)
*/
printk(str, safe_smp_processor_id());
show_registers(regs);
+ if (kexec_should_crash(current))
+ crash_kexec(regs);
if (panic_on_timeout || panic_on_oops)
panic("nmi watchdog");
printk("console shuts up ...\n");
oops_end(flags);
+ nmi_exit();
+ local_irq_enable();
do_exit(SIGSEGV);
}
@@ -468,8 +485,6 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
{
struct task_struct *tsk = current;
- conditional_sti(regs);
-
tsk->thread.error_code = error_code;
tsk->thread.trap_no = trapnr;
@@ -506,6 +521,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
== NOTIFY_STOP) \
return; \
+ conditional_sti(regs); \
do_trap(trapnr, signr, str, regs, error_code, NULL); \
}
@@ -520,6 +536,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
== NOTIFY_STOP) \
return; \
+ conditional_sti(regs); \
do_trap(trapnr, signr, str, regs, error_code, &info); \
}
@@ -533,7 +550,17 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
DO_ERROR(18, SIGSEGV, "reserved", reserved)
-DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
+
+/* Runs on IST stack */
+asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code)
+{
+ if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
+ 12, SIGBUS) == NOTIFY_STOP)
+ return;
+ preempt_conditional_sti(regs);
+ do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL);
+ preempt_conditional_cli(regs);
+}
asmlinkage void do_double_fault(struct pt_regs * regs, long error_code)
{
@@ -667,8 +694,9 @@ asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
return;
}
+ preempt_conditional_sti(regs);
do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
- return;
+ preempt_conditional_cli(regs);
}
/* Help handler running on IST stack to switch back to user stack
@@ -973,14 +1001,14 @@ void __init trap_init(void)
static int __init oops_dummy(char *s)
{
panic_on_oops = 1;
- return -1;
+ return 1;
}
__setup("oops=", oops_dummy);
static int __init kstack_setup(char *s)
{
kstack_depth_to_print = simple_strtoul(s,NULL,0);
- return 0;
+ return 1;
}
__setup("kstack=", kstack_setup);
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 39ff0708f80..b81f473c4a1 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -65,7 +65,7 @@ SECTIONS
.data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
*(.data.cacheline_aligned)
}
- . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+ . = ALIGN(CONFIG_X86_INTERNODE_CACHE_BYTES);
.data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
*(.data.read_mostly)
}
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index d96a9348e5a..1def21c9f7c 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -102,8 +102,6 @@ EXPORT_SYMBOL(cpu_callout_map);
EXPORT_SYMBOL(screen_info);
#endif
-EXPORT_SYMBOL(get_wchan);
-
EXPORT_SYMBOL(rtc_lock);
EXPORT_SYMBOL_GPL(set_nmi_callback);
@@ -114,7 +112,6 @@ EXPORT_SYMBOL_GPL(unset_nmi_callback);
#undef memcpy
#undef memset
#undef memmove
-#undef strlen
extern void * memset(void *,int,__kernel_size_t);
extern size_t strlen(const char *);
@@ -123,8 +120,6 @@ extern void * memcpy(void *,const void *,__kernel_size_t);
extern void * __memcpy(void *,const void *,__kernel_size_t);
EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(__memcpy);
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index 316c53de47b..55250593d8c 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -623,6 +623,6 @@ void vmalloc_sync_all(void)
static int __init enable_pagefaulttrace(char *str)
{
page_fault_trace = 1;
- return 0;
+ return 1;
}
__setup("pagefaulttrace", enable_pagefaulttrace);
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index b0441562544..4ba34e95d83 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -72,7 +72,7 @@ void show_mem(void)
show_free_areas();
printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
for (i = 0; i < pgdat->node_spanned_pages; ++i) {
page = pfn_to_page(pgdat->node_start_pfn + i);
total++;
@@ -305,7 +305,7 @@ static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned
if (paddr >= end)
break;
- if (!after_bootmem && !e820_mapped(paddr, paddr+PUD_SIZE, 0)) {
+ if (!after_bootmem && !e820_any_mapped(paddr, paddr+PUD_SIZE, 0)) {
set_pud(pud, __pud(0));
continue;
}
@@ -507,9 +507,8 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size)
/*
* Memory hotplug specific functions
- * These are only for non-NUMA machines right now.
*/
-#ifdef CONFIG_MEMORY_HOTPLUG
+#if defined(CONFIG_ACPI_HOTPLUG_MEMORY) || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
void online_page(struct page *page)
{
@@ -520,6 +519,38 @@ void online_page(struct page *page)
num_physpages++;
}
+#ifndef CONFIG_MEMORY_HOTPLUG
+/*
+ * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance,
+ * just online the pages.
+ */
+int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages)
+{
+ int err = -EIO;
+ unsigned long pfn;
+ unsigned long total = 0, mem = 0;
+ for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) {
+ if (pfn_valid(pfn)) {
+ online_page(pfn_to_page(pfn));
+ err = 0;
+ mem++;
+ }
+ total++;
+ }
+ if (!err) {
+ z->spanned_pages += total;
+ z->present_pages += mem;
+ z->zone_pgdat->node_spanned_pages += total;
+ z->zone_pgdat->node_present_pages += mem;
+ }
+ return err;
+}
+#endif
+
+/*
+ * Memory is added always to NORMAL zone. This means you will never get
+ * additional DMA/DMA32 memory.
+ */
int add_memory(u64 start, u64 size)
{
struct pglist_data *pgdat = NODE_DATA(0);
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 63c72641b73..b2fac14baac 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -100,11 +100,30 @@ int early_pfn_to_nid(unsigned long pfn)
}
#endif
+static void * __init
+early_node_mem(int nodeid, unsigned long start, unsigned long end,
+ unsigned long size)
+{
+ unsigned long mem = find_e820_area(start, end, size);
+ void *ptr;
+ if (mem != -1L)
+ return __va(mem);
+ ptr = __alloc_bootmem_nopanic(size,
+ SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS));
+ if (ptr == 0) {
+ printk(KERN_ERR "Cannot find %lu bytes in node %d\n",
+ size, nodeid);
+ return NULL;
+ }
+ return ptr;
+}
+
/* Initialize bootmem allocator for a node */
void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
{
unsigned long start_pfn, end_pfn, bootmap_pages, bootmap_size, bootmap_start;
unsigned long nodedata_phys;
+ void *bootmap;
const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE);
start = round_up(start, ZONE_ALIGN);
@@ -114,13 +133,11 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
start_pfn = start >> PAGE_SHIFT;
end_pfn = end >> PAGE_SHIFT;
- nodedata_phys = find_e820_area(start, end, pgdat_size);
- if (nodedata_phys == -1L)
- panic("Cannot find memory pgdat in node %d\n", nodeid);
-
- Dprintk("nodedata_phys %lx\n", nodedata_phys);
+ node_data[nodeid] = early_node_mem(nodeid, start, end, pgdat_size);
+ if (node_data[nodeid] == NULL)
+ return;
+ nodedata_phys = __pa(node_data[nodeid]);
- node_data[nodeid] = phys_to_virt(nodedata_phys);
memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t));
NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid];
NODE_DATA(nodeid)->node_start_pfn = start_pfn;
@@ -129,9 +146,15 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
/* Find a place for the bootmem map */
bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE);
- bootmap_start = find_e820_area(bootmap_start, end, bootmap_pages<<PAGE_SHIFT);
- if (bootmap_start == -1L)
- panic("Not enough continuous space for bootmap on node %d", nodeid);
+ bootmap = early_node_mem(nodeid, bootmap_start, end,
+ bootmap_pages<<PAGE_SHIFT);
+ if (bootmap == NULL) {
+ if (nodedata_phys < start || nodedata_phys >= end)
+ free_bootmem((unsigned long)node_data[nodeid],pgdat_size);
+ node_data[nodeid] = NULL;
+ return;
+ }
+ bootmap_start = __pa(bootmap);
Dprintk("bootmap start %lu pages %lu\n", bootmap_start, bootmap_pages);
bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
@@ -142,6 +165,9 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size);
reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages<<PAGE_SHIFT);
+#ifdef CONFIG_ACPI_NUMA
+ srat_reserve_add_area(nodeid);
+#endif
node_set_online(nodeid);
}
@@ -162,11 +188,13 @@ void __init setup_node_zones(int nodeid)
memory. */
memmapsize = sizeof(struct page) * (end_pfn-start_pfn);
limit = end_pfn << PAGE_SHIFT;
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
NODE_DATA(nodeid)->node_mem_map =
__alloc_bootmem_core(NODE_DATA(nodeid)->bdata,
memmapsize, SMP_CACHE_BYTES,
round_down(limit - memmapsize, PAGE_SIZE),
limit);
+#endif
size_zones(zones, holes, start_pfn, end_pfn);
free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
@@ -335,6 +363,8 @@ __init int numa_setup(char *opt)
#ifdef CONFIG_ACPI_NUMA
if (!strncmp(opt,"noacpi",6))
acpi_numa = -1;
+ if (!strncmp(opt,"hotadd=", 7))
+ hotadd_percent = simple_strtoul(opt+7, NULL, 10);
#endif
return 1;
}
@@ -377,21 +407,6 @@ EXPORT_SYMBOL(node_data);
* Should do that.
*/
-/* Requires pfn_valid(pfn) to be true */
-struct page *pfn_to_page(unsigned long pfn)
-{
- int nid = phys_to_nid(((unsigned long)(pfn)) << PAGE_SHIFT);
- return (pfn - node_start_pfn(nid)) + NODE_DATA(nid)->node_mem_map;
-}
-EXPORT_SYMBOL(pfn_to_page);
-
-unsigned long page_to_pfn(struct page *page)
-{
- return (long)(((page) - page_zone(page)->zone_mem_map) +
- page_zone(page)->zone_start_pfn);
-}
-EXPORT_SYMBOL(page_to_pfn);
-
int pfn_valid(unsigned long pfn)
{
unsigned nid;
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 2eb879590dc..474df22c6ed 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -15,15 +15,29 @@
#include <linux/bitmap.h>
#include <linux/module.h>
#include <linux/topology.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
#include <asm/proto.h>
#include <asm/numa.h>
#include <asm/e820.h>
+#if (defined(CONFIG_ACPI_HOTPLUG_MEMORY) || \
+ defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)) \
+ && !defined(CONFIG_MEMORY_HOTPLUG)
+#define RESERVE_HOTADD 1
+#endif
+
static struct acpi_table_slit *acpi_slit;
static nodemask_t nodes_parsed __initdata;
static nodemask_t nodes_found __initdata;
static struct bootnode nodes[MAX_NUMNODES] __initdata;
+static struct bootnode nodes_add[MAX_NUMNODES] __initdata;
+static int found_add_area __initdata;
+int hotadd_percent __initdata = 0;
+#ifndef RESERVE_HOTADD
+#define hotadd_percent 0 /* Ignore all settings */
+#endif
static u8 pxm2node[256] = { [0 ... 255] = 0xff };
/* Too small nodes confuse the VM badly. Usually they result
@@ -71,6 +85,10 @@ static __init int conflicting_nodes(unsigned long start, unsigned long end)
static __init void cutoff_node(int i, unsigned long start, unsigned long end)
{
struct bootnode *nd = &nodes[i];
+
+ if (found_add_area)
+ return;
+
if (nd->start < start) {
nd->start = start;
if (nd->end < nd->start)
@@ -88,8 +106,11 @@ static __init void bad_srat(void)
int i;
printk(KERN_ERR "SRAT: SRAT not used.\n");
acpi_numa = -1;
+ found_add_area = 0;
for (i = 0; i < MAX_LOCAL_APIC; i++)
apicid_to_node[i] = NUMA_NO_NODE;
+ for (i = 0; i < MAX_NUMNODES; i++)
+ nodes_add[i].start = nodes[i].end = 0;
}
static __init inline int srat_disabled(void)
@@ -137,7 +158,8 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
int pxm, node;
if (srat_disabled())
return;
- if (pa->header.length != sizeof(struct acpi_table_processor_affinity)) { bad_srat();
+ if (pa->header.length != sizeof(struct acpi_table_processor_affinity)) {
+ bad_srat();
return;
}
if (pa->flags.enabled == 0)
@@ -155,11 +177,116 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
pxm, pa->apic_id, node);
}
+#ifdef RESERVE_HOTADD
+/*
+ * Protect against too large hotadd areas that would fill up memory.
+ */
+static int hotadd_enough_memory(struct bootnode *nd)
+{
+ static unsigned long allocated;
+ static unsigned long last_area_end;
+ unsigned long pages = (nd->end - nd->start) >> PAGE_SHIFT;
+ long mem = pages * sizeof(struct page);
+ unsigned long addr;
+ unsigned long allowed;
+ unsigned long oldpages = pages;
+
+ if (mem < 0)
+ return 0;
+ allowed = (end_pfn - e820_hole_size(0, end_pfn)) * PAGE_SIZE;
+ allowed = (allowed / 100) * hotadd_percent;
+ if (allocated + mem > allowed) {
+ unsigned long range;
+ /* Give them at least part of their hotadd memory upto hotadd_percent
+ It would be better to spread the limit out
+ over multiple hotplug areas, but that is too complicated
+ right now */
+ if (allocated >= allowed)
+ return 0;
+ range = allowed - allocated;
+ pages = (range / PAGE_SIZE);
+ mem = pages * sizeof(struct page);
+ nd->end = nd->start + range;
+ }
+ /* Not completely fool proof, but a good sanity check */
+ addr = find_e820_area(last_area_end, end_pfn<<PAGE_SHIFT, mem);
+ if (addr == -1UL)
+ return 0;
+ if (pages != oldpages)
+ printk(KERN_NOTICE "SRAT: Hotadd area limited to %lu bytes\n",
+ pages << PAGE_SHIFT);
+ last_area_end = addr + mem;
+ allocated += mem;
+ return 1;
+}
+
+/*
+ * It is fine to add this area to the nodes data it will be used later
+ * This code supports one contigious hot add area per node.
+ */
+static int reserve_hotadd(int node, unsigned long start, unsigned long end)
+{
+ unsigned long s_pfn = start >> PAGE_SHIFT;
+ unsigned long e_pfn = end >> PAGE_SHIFT;
+ int changed = 0;
+ struct bootnode *nd = &nodes_add[node];
+
+ /* I had some trouble with strange memory hotadd regions breaking
+ the boot. Be very strict here and reject anything unexpected.
+ If you want working memory hotadd write correct SRATs.
+
+ The node size check is a basic sanity check to guard against
+ mistakes */
+ if ((signed long)(end - start) < NODE_MIN_SIZE) {
+ printk(KERN_ERR "SRAT: Hotplug area too small\n");
+ return -1;
+ }
+
+ /* This check might be a bit too strict, but I'm keeping it for now. */
+ if (e820_hole_size(s_pfn, e_pfn) != e_pfn - s_pfn) {
+ printk(KERN_ERR "SRAT: Hotplug area has existing memory\n");
+ return -1;
+ }
+
+ if (!hotadd_enough_memory(&nodes_add[node])) {
+ printk(KERN_ERR "SRAT: Hotplug area too large\n");
+ return -1;
+ }
+
+ /* Looks good */
+
+ found_add_area = 1;
+ if (nd->start == nd->end) {
+ nd->start = start;
+ nd->end = end;
+ changed = 1;
+ } else {
+ if (nd->start == end) {
+ nd->start = start;
+ changed = 1;
+ }
+ if (nd->end == start) {
+ nd->end = end;
+ changed = 1;
+ }
+ if (!changed)
+ printk(KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n");
+ }
+
+ if ((nd->end >> PAGE_SHIFT) > end_pfn)
+ end_pfn = nd->end >> PAGE_SHIFT;
+
+ if (changed)
+ printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n", nd->start, nd->end);
+ return 0;
+}
+#endif
+
/* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
void __init
acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
{
- struct bootnode *nd;
+ struct bootnode *nd, oldnode;
unsigned long start, end;
int node, pxm;
int i;
@@ -172,6 +299,8 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
}
if (ma->flags.enabled == 0)
return;
+ if (ma->flags.hot_pluggable && hotadd_percent == 0)
+ return;
start = ma->base_addr_lo | ((u64)ma->base_addr_hi << 32);
end = start + (ma->length_lo | ((u64)ma->length_hi << 32));
pxm = ma->proximity_domain;
@@ -181,10 +310,6 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
bad_srat();
return;
}
- /* It is fine to add this area to the nodes data it will be used later*/
- if (ma->flags.hot_pluggable == 1)
- printk(KERN_INFO "SRAT: hot plug zone found %lx - %lx \n",
- start, end);
i = conflicting_nodes(start, end);
if (i == node) {
printk(KERN_WARNING
@@ -199,6 +324,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
return;
}
nd = &nodes[node];
+ oldnode = *nd;
if (!node_test_and_set(node, nodes_parsed)) {
nd->start = start;
nd->end = end;
@@ -208,8 +334,19 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
if (nd->end < end)
nd->end = end;
}
+
printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm,
nd->start, nd->end);
+
+#ifdef RESERVE_HOTADD
+ if (ma->flags.hot_pluggable && reserve_hotadd(node, start, end) < 0) {
+ /* Ignore hotadd region. Undo damage */
+ printk(KERN_NOTICE "SRAT: Hotplug region ignored\n");
+ *nd = oldnode;
+ if ((nd->start | nd->end) == 0)
+ node_clear(node, nodes_parsed);
+ }
+#endif
}
/* Sanity check to catch more bad SRATs (they are amazingly common).
@@ -225,6 +362,9 @@ static int nodes_cover_memory(void)
unsigned long e = nodes[i].end >> PAGE_SHIFT;
pxmram += e - s;
pxmram -= e820_hole_size(s, e);
+ pxmram -= nodes_add[i].end - nodes_add[i].start;
+ if ((long)pxmram < 0)
+ pxmram = 0;
}
e820ram = end_pfn - e820_hole_size(0, end_pfn);
@@ -258,9 +398,11 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
/* First clean up the node list */
for (i = 0; i < MAX_NUMNODES; i++) {
- cutoff_node(i, start, end);
- if ((nodes[i].end - nodes[i].start) < NODE_MIN_SIZE)
+ cutoff_node(i, start, end);
+ if ((nodes[i].end - nodes[i].start) < NODE_MIN_SIZE) {
unparse_node(i);
+ node_set_offline(i);
+ }
}
if (acpi_numa <= 0)
@@ -282,6 +424,12 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
/* Finally register nodes */
for_each_node_mask(i, nodes_parsed)
setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+ /* Try again in case setup_node_bootmem missed one due
+ to missing bootmem */
+ for_each_node_mask(i, nodes_parsed)
+ if (!node_online(i))
+ setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+
for (i = 0; i < NR_CPUS; i++) {
if (cpu_to_node[i] == NUMA_NO_NODE)
continue;
@@ -303,6 +451,25 @@ static int node_to_pxm(int n)
return 0;
}
+void __init srat_reserve_add_area(int nodeid)
+{
+ if (found_add_area && nodes_add[nodeid].end) {
+ u64 total_mb;
+
+ printk(KERN_INFO "SRAT: Reserving hot-add memory space "
+ "for node %d at %Lx-%Lx\n",
+ nodeid, nodes_add[nodeid].start, nodes_add[nodeid].end);
+ total_mb = (nodes_add[nodeid].end - nodes_add[nodeid].start)
+ >> PAGE_SHIFT;
+ total_mb *= sizeof(struct page);
+ total_mb >>= 20;
+ printk(KERN_INFO "SRAT: This will cost you %Lu MB of "
+ "pre-allocated memory.\n", (unsigned long long)total_mb);
+ reserve_bootmem_node(NODE_DATA(nodeid), nodes_add[nodeid].start,
+ nodes_add[nodeid].end - nodes_add[nodeid].start);
+ }
+}
+
int __node_distance(int a, int b)
{
int index;
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index e616500207e..a2060e4d5de 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -9,11 +9,16 @@
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/bitmap.h>
+#include <asm/e820.h>
+
#include "pci.h"
#define MMCONFIG_APER_SIZE (256*1024*1024)
+/* Verify the first 16 busses. We assume that systems with more busses
+ get MCFG right. */
+#define MAX_CHECK_BUS 16
-static DECLARE_BITMAP(fallback_slots, 32);
+static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
/* Static virtual mapping of the MMCONFIG aperture */
struct mmcfg_virt {
@@ -55,7 +60,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
{
char __iomem *addr;
- if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), fallback_slots))
+ if (seg == 0 && bus < MAX_CHECK_BUS &&
+ test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
return NULL;
addr = get_virt(seg, bus);
if (!addr)
@@ -69,8 +75,10 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
char __iomem *addr;
/* Why do we have this when nobody checks it. How about a BUG()!? -AK */
- if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
+ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
+ *value = -1;
return -EINVAL;
+ }
addr = pci_dev_base(seg, bus, devfn);
if (!addr)
@@ -129,21 +137,26 @@ static struct pci_raw_ops pci_mmcfg = {
Normally this can be expressed in the MCFG by not listing them
and assigning suitable _SEGs, but this isn't implemented in some BIOS.
Instead try to discover all devices on bus 0 that are unreachable using MM
- and fallback for them.
- We only do this for bus 0/seg 0 */
+ and fallback for them. */
static __init void unreachable_devices(void)
{
- int i;
- for (i = 0; i < 32; i++) {
- u32 val1;
- char __iomem *addr;
-
- pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1);
- if (val1 == 0xffffffff)
- continue;
- addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0));
- if (addr == NULL|| readl(addr) != val1) {
- set_bit(i, fallback_slots);
+ int i, k;
+ /* Use the max bus number from ACPI here? */
+ for (k = 0; k < MAX_CHECK_BUS; k++) {
+ for (i = 0; i < 32; i++) {
+ u32 val1;
+ char __iomem *addr;
+
+ pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
+ if (val1 == 0xffffffff)
+ continue;
+ addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
+ if (addr == NULL|| readl(addr) != val1) {
+ set_bit(i + 32*k, fallback_slots);
+ printk(KERN_NOTICE
+ "PCI: No mmconfig possible on device %x:%x\n",
+ k, i);
+ }
}
}
}
@@ -161,6 +174,14 @@ void __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0))
return;
+ if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
+ pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
+ E820_RESERVED)) {
+ printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
+ printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+ return;
+ }
+
/* RED-PEN i386 doesn't do _nocache right now */
pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
if (pci_mmcfg_virt == NULL) {
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index efae56a5147..a15b6e3e72c 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -48,7 +48,6 @@ EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strchr);
EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strncat);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strrchr);
@@ -113,8 +112,6 @@ EXPORT_SYMBOL(__xtensa_copy_user);
// FIXME EXPORT_SYMBOL(screen_info);
#endif
-EXPORT_SYMBOL(get_wchan);
-
EXPORT_SYMBOL(outsb);
EXPORT_SYMBOL(outsw);
EXPORT_SYMBOL(outsl);
diff --git a/arch/xtensa/platform-iss/setup.c b/arch/xtensa/platform-iss/setup.c
index 2e6dcbf0cc0..23790a5610e 100644
--- a/arch/xtensa/platform-iss/setup.c
+++ b/arch/xtensa/platform-iss/setup.c
@@ -108,5 +108,5 @@ static struct notifier_block iss_panic_block = {
void __init platform_setup(char **p_cmdline)
{
- notifier_chain_register(&panic_notifier_list, &iss_panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block);
}
diff --git a/block/Kconfig b/block/Kconfig
index 43ca070dc0f..b6f5f0a7965 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -13,6 +13,7 @@ config LBD
config BLK_DEV_IO_TRACE
bool "Support for tracing block io actions"
+ depends on SYSFS
select RELAY
select DEBUG_FS
help
@@ -26,10 +27,10 @@ config BLK_DEV_IO_TRACE
config LSF
bool "Support for Large Single Files"
depends on X86 || (MIPS && 32BIT) || PPC32 || ARCH_S390_31 || SUPERH || UML
- default n
help
- When CONFIG_LBD is disabled, say Y here if you want to
- handle large file(bigger than 2TB), otherwise say N.
- When CONFIG_LBD is enabled, Y is set automatically.
+ Say Y here if you want to be able to handle very large files (bigger
+ than 2TB), otherwise say N.
+
+ If unsure, say Y.
source block/Kconfig.iosched
diff --git a/block/as-iosched.c b/block/as-iosched.c
index 296708ceceb..a7caf35ca0c 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -1648,17 +1648,17 @@ static void as_exit_queue(elevator_t *e)
* initialize elevator private data (as_data), and alloc a arq for
* each request on the free lists
*/
-static int as_init_queue(request_queue_t *q, elevator_t *e)
+static void *as_init_queue(request_queue_t *q, elevator_t *e)
{
struct as_data *ad;
int i;
if (!arq_pool)
- return -ENOMEM;
+ return NULL;
ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node);
if (!ad)
- return -ENOMEM;
+ return NULL;
memset(ad, 0, sizeof(*ad));
ad->q = q; /* Identify what queue the data belongs to */
@@ -1667,7 +1667,7 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
GFP_KERNEL, q->node);
if (!ad->hash) {
kfree(ad);
- return -ENOMEM;
+ return NULL;
}
ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
@@ -1675,7 +1675,7 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
if (!ad->arq_pool) {
kfree(ad->hash);
kfree(ad);
- return -ENOMEM;
+ return NULL;
}
/* anticipatory scheduling helpers */
@@ -1696,14 +1696,13 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
ad->antic_expire = default_antic_expire;
ad->batch_expire[REQ_SYNC] = default_read_batch_expire;
ad->batch_expire[REQ_ASYNC] = default_write_batch_expire;
- e->elevator_data = ad;
ad->current_batch_expires = jiffies + ad->batch_expire[REQ_SYNC];
ad->write_batch_count = ad->batch_expire[REQ_ASYNC] / 10;
if (ad->write_batch_count < 2)
ad->write_batch_count = 2;
- return 0;
+ return ad;
}
/*
@@ -1844,9 +1843,10 @@ static void __exit as_exit(void)
DECLARE_COMPLETION(all_gone);
elv_unregister(&iosched_as);
ioc_gone = &all_gone;
- barrier();
+ /* ioc_gone's update must be visible before reading ioc_count */
+ smp_wmb();
if (atomic_read(&ioc_count))
- complete(ioc_gone);
+ wait_for_completion(ioc_gone);
synchronize_rcu();
kmem_cache_destroy(arq_pool);
}
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index bde40a6ae66..052b1748762 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -26,20 +26,14 @@ static const int cfq_back_penalty = 2; /* penalty of a backwards seek */
static const int cfq_slice_sync = HZ / 10;
static int cfq_slice_async = HZ / 25;
static const int cfq_slice_async_rq = 2;
-static int cfq_slice_idle = HZ / 100;
+static int cfq_slice_idle = HZ / 70;
#define CFQ_IDLE_GRACE (HZ / 10)
#define CFQ_SLICE_SCALE (5)
#define CFQ_KEY_ASYNC (0)
-#define CFQ_KEY_ANY (0xffff)
-/*
- * disable queueing at the driver/hardware level
- */
-static const int cfq_max_depth = 2;
-
-static DEFINE_RWLOCK(cfq_exit_lock);
+static DEFINE_SPINLOCK(cfq_exit_lock);
/*
* for the hash of cfqq inside the cfqd
@@ -102,6 +96,8 @@ static struct completion *ioc_gone;
#define cfq_cfqq_sync(cfqq) \
(cfq_cfqq_class_sync(cfqq) || (cfqq)->on_dispatch[SYNC])
+#define sample_valid(samples) ((samples) > 80)
+
/*
* Per block device queue structure
*/
@@ -137,6 +133,7 @@ struct cfq_data {
mempool_t *crq_pool;
int rq_in_driver;
+ int hw_tag;
/*
* schedule slice state info
@@ -170,7 +167,6 @@ struct cfq_data {
unsigned int cfq_slice[2];
unsigned int cfq_slice_async_rq;
unsigned int cfq_slice_idle;
- unsigned int cfq_max_depth;
struct list_head cic_list;
};
@@ -343,17 +339,27 @@ static int cfq_queue_empty(request_queue_t *q)
return !cfqd->busy_queues;
}
+static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
+{
+ if (rw == READ || process_sync(task))
+ return task->pid;
+
+ return CFQ_KEY_ASYNC;
+}
+
/*
* Lifted from AS - choose which of crq1 and crq2 that is best served now.
* We choose the request that is closest to the head right now. Distance
- * behind the head are penalized and only allowed to a certain extent.
+ * behind the head is penalized and only allowed to a certain extent.
*/
static struct cfq_rq *
cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
{
sector_t last, s1, s2, d1 = 0, d2 = 0;
- int r1_wrap = 0, r2_wrap = 0; /* requests are behind the disk head */
unsigned long back_max;
+#define CFQ_RQ1_WRAP 0x01 /* request 1 wraps */
+#define CFQ_RQ2_WRAP 0x02 /* request 2 wraps */
+ unsigned wrap = 0; /* bit mask: requests behind the disk head? */
if (crq1 == NULL || crq1 == crq2)
return crq2;
@@ -385,35 +391,47 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
else if (s1 + back_max >= last)
d1 = (last - s1) * cfqd->cfq_back_penalty;
else
- r1_wrap = 1;
+ wrap |= CFQ_RQ1_WRAP;
if (s2 >= last)
d2 = s2 - last;
else if (s2 + back_max >= last)
d2 = (last - s2) * cfqd->cfq_back_penalty;
else
- r2_wrap = 1;
+ wrap |= CFQ_RQ2_WRAP;
/* Found required data */
- if (!r1_wrap && r2_wrap)
- return crq1;
- else if (!r2_wrap && r1_wrap)
- return crq2;
- else if (r1_wrap && r2_wrap) {
- /* both behind the head */
- if (s1 <= s2)
+
+ /*
+ * By doing switch() on the bit mask "wrap" we avoid having to
+ * check two variables for all permutations: --> faster!
+ */
+ switch (wrap) {
+ case 0: /* common case for CFQ: crq1 and crq2 not wrapped */
+ if (d1 < d2)
return crq1;
- else
+ else if (d2 < d1)
return crq2;
- }
+ else {
+ if (s1 >= s2)
+ return crq1;
+ else
+ return crq2;
+ }
- /* Both requests in front of the head */
- if (d1 < d2)
+ case CFQ_RQ2_WRAP:
return crq1;
- else if (d2 < d1)
+ case CFQ_RQ1_WRAP:
return crq2;
- else {
- if (s1 >= s2)
+ case (CFQ_RQ1_WRAP|CFQ_RQ2_WRAP): /* both crqs wrapped */
+ default:
+ /*
+ * Since both rqs are wrapped,
+ * start with the one that's further behind head
+ * (--> only *one* back seek required),
+ * since back seek takes more time than forward.
+ */
+ if (s1 <= s2)
return crq1;
else
return crq2;
@@ -483,10 +501,13 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
/*
* if queue was preempted, just add to front to be fair. busy_rr
- * isn't sorted.
+ * isn't sorted, but insert at the back for fairness.
*/
if (preempted || list == &cfqd->busy_rr) {
- list_add(&cfqq->cfq_list, list);
+ if (preempted)
+ list = list->prev;
+
+ list_add_tail(&cfqq->cfq_list, list);
return;
}
@@ -612,15 +633,20 @@ cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
cfq_add_crq_rb(crq);
}
-static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector)
-
+static struct request *
+cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
{
- struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->pid, CFQ_KEY_ANY);
+ struct task_struct *tsk = current;
+ pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio));
+ struct cfq_queue *cfqq;
struct rb_node *n;
+ sector_t sector;
+ cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio);
if (!cfqq)
goto out;
+ sector = bio->bi_sector + bio_sectors(bio);
n = cfqq->sort_list.rb_node;
while (n) {
struct cfq_rq *crq = rb_entry_crq(n);
@@ -642,6 +668,15 @@ static void cfq_activate_request(request_queue_t *q, struct request *rq)
struct cfq_data *cfqd = q->elevator->elevator_data;
cfqd->rq_in_driver++;
+
+ /*
+ * If the depth is larger 1, it really could be queueing. But lets
+ * make the mark a little higher - idling could still be good for
+ * low queueing, and a low queueing number could also just indicate
+ * a SCSI mid layer like behaviour where limit+1 is often seen.
+ */
+ if (!cfqd->hw_tag && cfqd->rq_in_driver > 4)
+ cfqd->hw_tag = 1;
}
static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
@@ -674,7 +709,7 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
goto out;
}
- __rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio));
+ __rq = cfq_find_rq_fmerge(cfqd, bio);
if (__rq && elv_rq_merge_ok(__rq, bio)) {
ret = ELEVATOR_FRONT_MERGE;
goto out;
@@ -857,6 +892,13 @@ static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
cfqq = list_entry_cfqq(cfqd->cur_rr.next);
/*
+ * If no new queues are available, check if the busy list has some
+ * before falling back to idle io.
+ */
+ if (!cfqq && !list_empty(&cfqd->busy_rr))
+ cfqq = list_entry_cfqq(cfqd->busy_rr.next);
+
+ /*
* if we have idle queues and no rt or be queues had pending
* requests, either allow immediate service if the grace period
* has passed or arm the idle grace timer
@@ -877,6 +919,7 @@ static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
{
+ struct cfq_io_context *cic;
unsigned long sl;
WARN_ON(!RB_EMPTY(&cfqq->sort_list));
@@ -892,13 +935,23 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
/*
* task has exited, don't wait
*/
- if (cfqd->active_cic && !cfqd->active_cic->ioc->task)
+ cic = cfqd->active_cic;
+ if (!cic || !cic->ioc->task)
return 0;
cfq_mark_cfqq_must_dispatch(cfqq);
cfq_mark_cfqq_wait_request(cfqq);
sl = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle);
+
+ /*
+ * we don't want to idle for seeks, but we do want to allow
+ * fair distribution of slice time for a process doing back-to-back
+ * seeks. so allow a little bit of time for him to submit a new rq
+ */
+ if (sample_valid(cic->seek_samples) && cic->seek_mean > 131072)
+ sl = 2;
+
mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
return 1;
}
@@ -1115,13 +1168,6 @@ cfq_dispatch_requests(request_queue_t *q, int force)
if (cfqq) {
int max_dispatch;
- /*
- * if idle window is disabled, allow queue buildup
- */
- if (!cfq_cfqq_idle_window(cfqq) &&
- cfqd->rq_in_driver >= cfqd->cfq_max_depth)
- return 0;
-
cfq_clear_cfqq_must_dispatch(cfqq);
cfq_clear_cfqq_wait_request(cfqq);
del_timer(&cfqd->idle_slice_timer);
@@ -1171,13 +1217,13 @@ __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio,
const int hashval)
{
struct hlist_head *hash_list = &cfqd->cfq_hash[hashval];
- struct hlist_node *entry, *next;
+ struct hlist_node *entry;
+ struct cfq_queue *__cfqq;
- hlist_for_each_safe(entry, next, hash_list) {
- struct cfq_queue *__cfqq = list_entry_qhash(entry);
+ hlist_for_each_entry(__cfqq, entry, hash_list, cfq_hash) {
const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->org_ioprio_class, __cfqq->org_ioprio);
- if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY))
+ if (__cfqq->key == key && (__p == prio || !prio))
return __cfqq;
}
@@ -1190,19 +1236,19 @@ cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned short prio)
return __cfq_find_cfq_hash(cfqd, key, prio, hash_long(key, CFQ_QHASH_SHIFT));
}
-static void cfq_free_io_context(struct cfq_io_context *cic)
+static void cfq_free_io_context(struct io_context *ioc)
{
struct cfq_io_context *__cic;
- struct list_head *entry, *next;
- int freed = 1;
+ struct rb_node *n;
+ int freed = 0;
- list_for_each_safe(entry, next, &cic->list) {
- __cic = list_entry(entry, struct cfq_io_context, list);
+ while ((n = rb_first(&ioc->cic_root)) != NULL) {
+ __cic = rb_entry(n, struct cfq_io_context, rb_node);
+ rb_erase(&__cic->rb_node, &ioc->cic_root);
kmem_cache_free(cfq_ioc_pool, __cic);
freed++;
}
- kmem_cache_free(cfq_ioc_pool, cic);
if (atomic_sub_and_test(freed, &ioc_count) && ioc_gone)
complete(ioc_gone);
}
@@ -1210,8 +1256,7 @@ static void cfq_free_io_context(struct cfq_io_context *cic)
static void cfq_trim(struct io_context *ioc)
{
ioc->set_ioprio = NULL;
- if (ioc->cic)
- cfq_free_io_context(ioc->cic);
+ cfq_free_io_context(ioc);
}
/*
@@ -1250,26 +1295,26 @@ static void cfq_exit_single_io_context(struct cfq_io_context *cic)
spin_unlock(q->queue_lock);
}
-static void cfq_exit_io_context(struct cfq_io_context *cic)
+static void cfq_exit_io_context(struct io_context *ioc)
{
struct cfq_io_context *__cic;
- struct list_head *entry;
unsigned long flags;
-
- local_irq_save(flags);
+ struct rb_node *n;
/*
* put the reference this task is holding to the various queues
*/
- read_lock(&cfq_exit_lock);
- list_for_each(entry, &cic->list) {
- __cic = list_entry(entry, struct cfq_io_context, list);
+ spin_lock_irqsave(&cfq_exit_lock, flags);
+
+ n = rb_first(&ioc->cic_root);
+ while (n != NULL) {
+ __cic = rb_entry(n, struct cfq_io_context, rb_node);
+
cfq_exit_single_io_context(__cic);
+ n = rb_next(n);
}
- cfq_exit_single_io_context(cic);
- read_unlock(&cfq_exit_lock);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&cfq_exit_lock, flags);
}
static struct cfq_io_context *
@@ -1278,17 +1323,12 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
if (cic) {
- INIT_LIST_HEAD(&cic->list);
- cic->cfqq[ASYNC] = NULL;
- cic->cfqq[SYNC] = NULL;
- cic->key = NULL;
+ memset(cic, 0, sizeof(*cic));
+ RB_CLEAR_COLOR(&cic->rb_node);
cic->last_end_request = jiffies;
- cic->ttime_total = 0;
- cic->ttime_samples = 0;
- cic->ttime_mean = 0;
+ INIT_LIST_HEAD(&cic->queue_list);
cic->dtor = cfq_free_io_context;
cic->exit = cfq_exit_io_context;
- INIT_LIST_HEAD(&cic->queue_list);
atomic_inc(&ioc_count);
}
@@ -1373,17 +1413,19 @@ static inline void changed_ioprio(struct cfq_io_context *cic)
static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
{
struct cfq_io_context *cic;
+ struct rb_node *n;
- write_lock(&cfq_exit_lock);
-
- cic = ioc->cic;
+ spin_lock(&cfq_exit_lock);
- changed_ioprio(cic);
+ n = rb_first(&ioc->cic_root);
+ while (n != NULL) {
+ cic = rb_entry(n, struct cfq_io_context, rb_node);
- list_for_each_entry(cic, &cic->list, list)
changed_ioprio(cic);
+ n = rb_next(n);
+ }
- write_unlock(&cfq_exit_lock);
+ spin_unlock(&cfq_exit_lock);
return 0;
}
@@ -1431,7 +1473,8 @@ retry:
* set ->slice_left to allow preemption for a new process
*/
cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
- cfq_mark_cfqq_idle_window(cfqq);
+ if (!cfqd->hw_tag)
+ cfq_mark_cfqq_idle_window(cfqq);
cfq_mark_cfqq_prio_changed(cfqq);
cfq_init_prio_data(cfqq);
}
@@ -1445,14 +1488,94 @@ out:
return cfqq;
}
+static void
+cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic)
+{
+ spin_lock(&cfq_exit_lock);
+ rb_erase(&cic->rb_node, &ioc->cic_root);
+ list_del_init(&cic->queue_list);
+ spin_unlock(&cfq_exit_lock);
+ kmem_cache_free(cfq_ioc_pool, cic);
+ atomic_dec(&ioc_count);
+}
+
+static struct cfq_io_context *
+cfq_cic_rb_lookup(struct cfq_data *cfqd, struct io_context *ioc)
+{
+ struct rb_node *n;
+ struct cfq_io_context *cic;
+ void *k, *key = cfqd;
+
+restart:
+ n = ioc->cic_root.rb_node;
+ while (n) {
+ cic = rb_entry(n, struct cfq_io_context, rb_node);
+ /* ->key must be copied to avoid race with cfq_exit_queue() */
+ k = cic->key;
+ if (unlikely(!k)) {
+ cfq_drop_dead_cic(ioc, cic);
+ goto restart;
+ }
+
+ if (key < k)
+ n = n->rb_left;
+ else if (key > k)
+ n = n->rb_right;
+ else
+ return cic;
+ }
+
+ return NULL;
+}
+
+static inline void
+cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
+ struct cfq_io_context *cic)
+{
+ struct rb_node **p;
+ struct rb_node *parent;
+ struct cfq_io_context *__cic;
+ void *k;
+
+ cic->ioc = ioc;
+ cic->key = cfqd;
+
+ ioc->set_ioprio = cfq_ioc_set_ioprio;
+restart:
+ parent = NULL;
+ p = &ioc->cic_root.rb_node;
+ while (*p) {
+ parent = *p;
+ __cic = rb_entry(parent, struct cfq_io_context, rb_node);
+ /* ->key must be copied to avoid race with cfq_exit_queue() */
+ k = __cic->key;
+ if (unlikely(!k)) {
+ cfq_drop_dead_cic(ioc, cic);
+ goto restart;
+ }
+
+ if (cic->key < k)
+ p = &(*p)->rb_left;
+ else if (cic->key > k)
+ p = &(*p)->rb_right;
+ else
+ BUG();
+ }
+
+ spin_lock(&cfq_exit_lock);
+ rb_link_node(&cic->rb_node, parent, p);
+ rb_insert_color(&cic->rb_node, &ioc->cic_root);
+ list_add(&cic->queue_list, &cfqd->cic_list);
+ spin_unlock(&cfq_exit_lock);
+}
+
/*
* Setup general io context and cfq io context. There can be several cfq
* io contexts per general io context, if this process is doing io to more
- * than one device managed by cfq. Note that caller is holding a reference to
- * cfqq, so we don't need to worry about it disappearing
+ * than one device managed by cfq.
*/
static struct cfq_io_context *
-cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
+cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
{
struct io_context *ioc = NULL;
struct cfq_io_context *cic;
@@ -1463,88 +1586,15 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
if (!ioc)
return NULL;
-restart:
- if ((cic = ioc->cic) == NULL) {
- cic = cfq_alloc_io_context(cfqd, gfp_mask);
-
- if (cic == NULL)
- goto err;
-
- /*
- * manually increment generic io_context usage count, it
- * cannot go away since we are already holding one ref to it
- */
- cic->ioc = ioc;
- cic->key = cfqd;
- read_lock(&cfq_exit_lock);
- ioc->set_ioprio = cfq_ioc_set_ioprio;
- ioc->cic = cic;
- list_add(&cic->queue_list, &cfqd->cic_list);
- read_unlock(&cfq_exit_lock);
- } else {
- struct cfq_io_context *__cic;
-
- /*
- * the first cic on the list is actually the head itself
- */
- if (cic->key == cfqd)
- goto out;
-
- if (unlikely(!cic->key)) {
- read_lock(&cfq_exit_lock);
- if (list_empty(&cic->list))
- ioc->cic = NULL;
- else
- ioc->cic = list_entry(cic->list.next,
- struct cfq_io_context,
- list);
- read_unlock(&cfq_exit_lock);
- kmem_cache_free(cfq_ioc_pool, cic);
- atomic_dec(&ioc_count);
- goto restart;
- }
-
- /*
- * cic exists, check if we already are there. linear search
- * should be ok here, the list will usually not be more than
- * 1 or a few entries long
- */
- list_for_each_entry(__cic, &cic->list, list) {
- /*
- * this process is already holding a reference to
- * this queue, so no need to get one more
- */
- if (__cic->key == cfqd) {
- cic = __cic;
- goto out;
- }
- if (unlikely(!__cic->key)) {
- read_lock(&cfq_exit_lock);
- list_del(&__cic->list);
- read_unlock(&cfq_exit_lock);
- kmem_cache_free(cfq_ioc_pool, __cic);
- atomic_dec(&ioc_count);
- goto restart;
- }
- }
+ cic = cfq_cic_rb_lookup(cfqd, ioc);
+ if (cic)
+ goto out;
- /*
- * nope, process doesn't have a cic assoicated with this
- * cfqq yet. get a new one and add to list
- */
- __cic = cfq_alloc_io_context(cfqd, gfp_mask);
- if (__cic == NULL)
- goto err;
-
- __cic->ioc = ioc;
- __cic->key = cfqd;
- read_lock(&cfq_exit_lock);
- list_add(&__cic->list, &cic->list);
- list_add(&__cic->queue_list, &cfqd->cic_list);
- read_unlock(&cfq_exit_lock);
- cic = __cic;
- }
+ cic = cfq_alloc_io_context(cfqd, gfp_mask);
+ if (cic == NULL)
+ goto err;
+ cfq_cic_link(cfqd, ioc, cic);
out:
return cic;
err:
@@ -1577,7 +1627,33 @@ cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples;
}
-#define sample_valid(samples) ((samples) > 80)
+static void
+cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic,
+ struct cfq_rq *crq)
+{
+ sector_t sdist;
+ u64 total;
+
+ if (cic->last_request_pos < crq->request->sector)
+ sdist = crq->request->sector - cic->last_request_pos;
+ else
+ sdist = cic->last_request_pos - crq->request->sector;
+
+ /*
+ * Don't allow the seek distance to get too large from the
+ * odd fragment, pagein, etc
+ */
+ if (cic->seek_samples <= 60) /* second&third seek */
+ sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*1024);
+ else
+ sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*64);
+
+ cic->seek_samples = (7*cic->seek_samples + 256) / 8;
+ cic->seek_total = (7*cic->seek_total + (u64)256*sdist) / 8;
+ total = cic->seek_total + (cic->seek_samples/2);
+ do_div(total, cic->seek_samples);
+ cic->seek_mean = (sector_t)total;
+}
/*
* Disable idle window if the process thinks too long or seeks so much that
@@ -1589,7 +1665,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
{
int enable_idle = cfq_cfqq_idle_window(cfqq);
- if (!cic->ioc->task || !cfqd->cfq_slice_idle)
+ if (!cic->ioc->task || !cfqd->cfq_slice_idle || cfqd->hw_tag)
enable_idle = 0;
else if (sample_valid(cic->ttime_samples)) {
if (cic->ttime_mean > cfqd->cfq_slice_idle)
@@ -1680,19 +1756,31 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
+ cic = crq->io_context;
+
/*
* we never wait for an async request and we don't allow preemption
* of an async request. so just return early
*/
- if (!cfq_crq_is_sync(crq))
+ if (!cfq_crq_is_sync(crq)) {
+ /*
+ * sync process issued an async request, if it's waiting
+ * then expire it and kick rq handling.
+ */
+ if (cic == cfqd->active_cic &&
+ del_timer(&cfqd->idle_slice_timer)) {
+ cfq_slice_expired(cfqd, 0);
+ cfq_start_queueing(cfqd, cfqq);
+ }
return;
-
- cic = crq->io_context;
+ }
cfq_update_io_thinktime(cfqd, cic);
+ cfq_update_io_seektime(cfqd, cic, crq);
cfq_update_idle_window(cfqd, cfqq, cic);
cic->last_queue = jiffies;
+ cic->last_request_pos = crq->request->sector + crq->request->nr_sectors;
if (cfqq == cfqd->active_queue) {
/*
@@ -1825,14 +1913,6 @@ static void cfq_prio_boost(struct cfq_queue *cfqq)
cfq_resort_rr_list(cfqq, 0);
}
-static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
-{
- if (rw == READ || process_sync(task))
- return task->pid;
-
- return CFQ_KEY_ASYNC;
-}
-
static inline int
__cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq,
struct task_struct *task, int rw)
@@ -1965,7 +2045,7 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
might_sleep_if(gfp_mask & __GFP_WAIT);
- cic = cfq_get_io_context(cfqd, key, gfp_mask);
+ cic = cfq_get_io_context(cfqd, gfp_mask);
spin_lock_irqsave(q->queue_lock, flags);
@@ -2111,10 +2191,9 @@ static void cfq_idle_class_timer(unsigned long data)
* race with a non-idle queue, reset timer
*/
end = cfqd->last_end_request + CFQ_IDLE_GRACE;
- if (!time_after_eq(jiffies, end)) {
- cfqd->idle_class_timer.expires = end;
- add_timer(&cfqd->idle_class_timer);
- } else
+ if (!time_after_eq(jiffies, end))
+ mod_timer(&cfqd->idle_class_timer, end);
+ else
cfq_schedule_dispatch(cfqd);
spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
@@ -2133,11 +2212,14 @@ static void cfq_exit_queue(elevator_t *e)
request_queue_t *q = cfqd->queue;
cfq_shutdown_timer_wq(cfqd);
- write_lock(&cfq_exit_lock);
+
+ spin_lock(&cfq_exit_lock);
spin_lock_irq(q->queue_lock);
+
if (cfqd->active_queue)
__cfq_slice_expired(cfqd, cfqd->active_queue, 0);
- while(!list_empty(&cfqd->cic_list)) {
+
+ while (!list_empty(&cfqd->cic_list)) {
struct cfq_io_context *cic = list_entry(cfqd->cic_list.next,
struct cfq_io_context,
queue_list);
@@ -2152,8 +2234,9 @@ static void cfq_exit_queue(elevator_t *e)
cic->key = NULL;
list_del_init(&cic->queue_list);
}
+
spin_unlock_irq(q->queue_lock);
- write_unlock(&cfq_exit_lock);
+ spin_unlock(&cfq_exit_lock);
cfq_shutdown_timer_wq(cfqd);
@@ -2163,14 +2246,14 @@ static void cfq_exit_queue(elevator_t *e)
kfree(cfqd);
}
-static int cfq_init_queue(request_queue_t *q, elevator_t *e)
+static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
{
struct cfq_data *cfqd;
int i;
cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL);
if (!cfqd)
- return -ENOMEM;
+ return NULL;
memset(cfqd, 0, sizeof(*cfqd));
@@ -2200,8 +2283,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
for (i = 0; i < CFQ_QHASH_ENTRIES; i++)
INIT_HLIST_HEAD(&cfqd->cfq_hash[i]);
- e->elevator_data = cfqd;
-
cfqd->queue = q;
cfqd->max_queued = q->nr_requests / 4;
@@ -2227,16 +2308,15 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
cfqd->cfq_slice[1] = cfq_slice_sync;
cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
cfqd->cfq_slice_idle = cfq_slice_idle;
- cfqd->cfq_max_depth = cfq_max_depth;
- return 0;
+ return cfqd;
out_crqpool:
kfree(cfqd->cfq_hash);
out_cfqhash:
kfree(cfqd->crq_hash);
out_crqhash:
kfree(cfqd);
- return -ENOMEM;
+ return NULL;
}
static void cfq_slab_kill(void)
@@ -2310,7 +2390,6 @@ SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1);
SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1);
SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1);
SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0);
-SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0);
#undef SHOW_FUNCTION
#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
@@ -2339,7 +2418,6 @@ STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1);
STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1);
STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1);
STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0);
-STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0);
#undef STORE_FUNCTION
#define CFQ_ATTR(name) \
@@ -2356,7 +2434,6 @@ static struct elv_fs_entry cfq_attrs[] = {
CFQ_ATTR(slice_async),
CFQ_ATTR(slice_async_rq),
CFQ_ATTR(slice_idle),
- CFQ_ATTR(max_depth),
__ATTR_NULL
};
@@ -2412,9 +2489,10 @@ static void __exit cfq_exit(void)
DECLARE_COMPLETION(all_gone);
elv_unregister(&iosched_cfq);
ioc_gone = &all_gone;
- barrier();
+ /* ioc_gone's update must be visible before reading ioc_count */
+ smp_wmb();
if (atomic_read(&ioc_count))
- complete(ioc_gone);
+ wait_for_completion(ioc_gone);
synchronize_rcu();
cfq_slab_kill();
}
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index 399fa1e60e1..3bd0415a982 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -613,24 +613,24 @@ static void deadline_exit_queue(elevator_t *e)
* initialize elevator private data (deadline_data), and alloc a drq for
* each request on the free lists
*/
-static int deadline_init_queue(request_queue_t *q, elevator_t *e)
+static void *deadline_init_queue(request_queue_t *q, elevator_t *e)
{
struct deadline_data *dd;
int i;
if (!drq_pool)
- return -ENOMEM;
+ return NULL;
dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
if (!dd)
- return -ENOMEM;
+ return NULL;
memset(dd, 0, sizeof(*dd));
dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES,
GFP_KERNEL, q->node);
if (!dd->hash) {
kfree(dd);
- return -ENOMEM;
+ return NULL;
}
dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
@@ -638,7 +638,7 @@ static int deadline_init_queue(request_queue_t *q, elevator_t *e)
if (!dd->drq_pool) {
kfree(dd->hash);
kfree(dd);
- return -ENOMEM;
+ return NULL;
}
for (i = 0; i < DL_HASH_ENTRIES; i++)
@@ -653,8 +653,7 @@ static int deadline_init_queue(request_queue_t *q, elevator_t *e)
dd->writes_starved = writes_starved;
dd->front_merges = 1;
dd->fifo_batch = fifo_batch;
- e->elevator_data = dd;
- return 0;
+ return dd;
}
static void deadline_put_request(request_queue_t *q, struct request *rq)
diff --git a/block/elevator.c b/block/elevator.c
index 56c2ed06a9e..a0afdd317ce 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -121,16 +121,16 @@ static struct elevator_type *elevator_get(const char *name)
return e;
}
-static int elevator_attach(request_queue_t *q, struct elevator_queue *eq)
+static void *elevator_init_queue(request_queue_t *q, struct elevator_queue *eq)
{
- int ret = 0;
+ return eq->ops->elevator_init_fn(q, eq);
+}
+static void elevator_attach(request_queue_t *q, struct elevator_queue *eq,
+ void *data)
+{
q->elevator = eq;
-
- if (eq->ops->elevator_init_fn)
- ret = eq->ops->elevator_init_fn(q, eq);
-
- return ret;
+ eq->elevator_data = data;
}
static char chosen_elevator[16];
@@ -145,7 +145,7 @@ static int __init elevator_setup(char *str)
strcpy(chosen_elevator, "anticipatory");
else
strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1);
- return 0;
+ return 1;
}
__setup("elevator=", elevator_setup);
@@ -181,6 +181,7 @@ int elevator_init(request_queue_t *q, char *name)
struct elevator_type *e = NULL;
struct elevator_queue *eq;
int ret = 0;
+ void *data;
INIT_LIST_HEAD(&q->queue_head);
q->last_merge = NULL;
@@ -202,10 +203,13 @@ int elevator_init(request_queue_t *q, char *name)
if (!eq)
return -ENOMEM;
- ret = elevator_attach(q, eq);
- if (ret)
+ data = elevator_init_queue(q, eq);
+ if (!data) {
kobject_put(&eq->kobj);
+ return -ENOMEM;
+ }
+ elevator_attach(q, eq, data);
return ret;
}
@@ -333,6 +337,7 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
{
struct list_head *pos;
unsigned ordseq;
+ int unplug_it = 1;
blk_add_trace_rq(q, rq, BLK_TA_INSERT);
@@ -399,6 +404,11 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
}
list_add_tail(&rq->queuelist, pos);
+ /*
+ * most requeues happen because of a busy condition, don't
+ * force unplug of the queue for that case.
+ */
+ unplug_it = 0;
break;
default:
@@ -407,7 +417,7 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
BUG();
}
- if (blk_queue_plugged(q)) {
+ if (unplug_it && blk_queue_plugged(q)) {
int nrq = q->rq.count[READ] + q->rq.count[WRITE]
- q->in_flight;
@@ -716,13 +726,16 @@ int elv_register_queue(struct request_queue *q)
return error;
}
+static void __elv_unregister_queue(elevator_t *e)
+{
+ kobject_uevent(&e->kobj, KOBJ_REMOVE);
+ kobject_del(&e->kobj);
+}
+
void elv_unregister_queue(struct request_queue *q)
{
- if (q) {
- elevator_t *e = q->elevator;
- kobject_uevent(&e->kobj, KOBJ_REMOVE);
- kobject_del(&e->kobj);
- }
+ if (q)
+ __elv_unregister_queue(q->elevator);
}
int elv_register(struct elevator_type *e)
@@ -774,6 +787,7 @@ EXPORT_SYMBOL_GPL(elv_unregister);
static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
{
elevator_t *old_elevator, *e;
+ void *data;
/*
* Allocate new elevator
@@ -782,6 +796,12 @@ static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
if (!e)
return 0;
+ data = elevator_init_queue(q, e);
+ if (!data) {
+ kobject_put(&e->kobj);
+ return 0;
+ }
+
/*
* Turn on BYPASS and drain all requests w/ elevator private data
*/
@@ -800,19 +820,19 @@ static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
elv_drain_elevator(q);
}
- spin_unlock_irq(q->queue_lock);
-
/*
- * unregister old elevator data
+ * Remember old elevator.
*/
- elv_unregister_queue(q);
old_elevator = q->elevator;
/*
* attach and start new elevator
*/
- if (elevator_attach(q, e))
- goto fail;
+ elevator_attach(q, e, data);
+
+ spin_unlock_irq(q->queue_lock);
+
+ __elv_unregister_queue(old_elevator);
if (elv_register_queue(q))
goto fail_register;
@@ -831,7 +851,6 @@ fail_register:
*/
elevator_exit(e);
e = NULL;
-fail:
q->elevator = old_elevator;
elv_register_queue(q);
clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
@@ -895,10 +914,8 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
EXPORT_SYMBOL(elv_dispatch_sort);
EXPORT_SYMBOL(elv_add_request);
EXPORT_SYMBOL(__elv_add_request);
-EXPORT_SYMBOL(elv_requeue_request);
EXPORT_SYMBOL(elv_next_request);
EXPORT_SYMBOL(elv_dequeue_request);
EXPORT_SYMBOL(elv_queue_empty);
-EXPORT_SYMBOL(elv_completed_request);
EXPORT_SYMBOL(elevator_exit);
EXPORT_SYMBOL(elevator_init);
diff --git a/block/genhd.c b/block/genhd.c
index 64510fd8862..5a8d3bf02f1 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -17,8 +17,6 @@
#include <linux/buffer_head.h>
#include <linux/mutex.h>
-#define MAX_PROBE_HASH 255 /* random */
-
static struct subsystem block_subsys;
static DEFINE_MUTEX(block_subsys_lock);
@@ -31,108 +29,29 @@ static struct blk_major_name {
struct blk_major_name *next;
int major;
char name[16];
-} *major_names[MAX_PROBE_HASH];
+} *major_names[BLKDEV_MAJOR_HASH_SIZE];
/* index in the above - for now: assume no multimajor ranges */
static inline int major_to_index(int major)
{
- return major % MAX_PROBE_HASH;
-}
-
-struct blkdev_info {
- int index;
- struct blk_major_name *bd;
-};
-
-/*
- * iterate over a list of blkdev_info structures. allows
- * the major_names array to be iterated over from outside this file
- * must be called with the block_subsys_lock held
- */
-void *get_next_blkdev(void *dev)
-{
- struct blkdev_info *info;
-
- if (dev == NULL) {
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info)
- goto out;
- info->index=0;
- info->bd = major_names[info->index];
- if (info->bd)
- goto out;
- } else {
- info = dev;
- }
-
- while (info->index < ARRAY_SIZE(major_names)) {
- if (info->bd)
- info->bd = info->bd->next;
- if (info->bd)
- goto out;
- /*
- * No devices on this chain, move to the next
- */
- info->index++;
- info->bd = (info->index < ARRAY_SIZE(major_names)) ?
- major_names[info->index] : NULL;
- if (info->bd)
- goto out;
- }
-
-out:
- return info;
-}
-
-void *acquire_blkdev_list(void)
-{
- mutex_lock(&block_subsys_lock);
- return get_next_blkdev(NULL);
-}
-
-void release_blkdev_list(void *dev)
-{
- mutex_unlock(&block_subsys_lock);
- kfree(dev);
+ return major % BLKDEV_MAJOR_HASH_SIZE;
}
+#ifdef CONFIG_PROC_FS
-/*
- * Count the number of records in the blkdev_list.
- * must be called with the block_subsys_lock held
- */
-int count_blkdev_list(void)
+void blkdev_show(struct seq_file *f, off_t offset)
{
- struct blk_major_name *n;
- int i, count;
+ struct blk_major_name *dp;
- count = 0;
-
- for (i = 0; i < ARRAY_SIZE(major_names); i++) {
- for (n = major_names[i]; n; n = n->next)
- count++;
+ if (offset < BLKDEV_MAJOR_HASH_SIZE) {
+ mutex_lock(&block_subsys_lock);
+ for (dp = major_names[offset]; dp; dp = dp->next)
+ seq_printf(f, "%3d %s\n", dp->major, dp->name);
+ mutex_unlock(&block_subsys_lock);
}
-
- return count;
-}
-
-/*
- * extract the major and name values from a blkdev_info struct
- * passed in as a void to *dev. Must be called with
- * block_subsys_lock held
- */
-int get_blkdev_info(void *dev, int *major, char **name)
-{
- struct blkdev_info *info = dev;
-
- if (info->bd == NULL)
- return 1;
-
- *major = info->bd->major;
- *name = info->bd->name;
- return 0;
}
+#endif /* CONFIG_PROC_FS */
int register_blkdev(unsigned int major, const char *name)
{
@@ -454,8 +373,8 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page)
disk_round_stats(disk);
preempt_enable();
return sprintf(page,
- "%8u %8u %8llu %8u "
- "%8u %8u %8llu %8u "
+ "%8lu %8lu %8llu %8u "
+ "%8lu %8lu %8llu %8u "
"%8u %8u %8u"
"\n",
disk_stat_read(disk, ios[READ]),
@@ -649,7 +568,7 @@ static int diskstats_show(struct seq_file *s, void *v)
preempt_disable();
disk_round_stats(gp);
preempt_enable();
- seq_printf(s, "%4d %4d %s %u %u %llu %u %u %u %llu %u %u %u %u\n",
+ seq_printf(s, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n",
gp->major, n + gp->first_minor, disk_name(gp, n, buf),
disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]),
(unsigned long long)disk_stat_read(gp, sectors[0]),
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 062067fa7ea..7eb36c53f4b 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -785,6 +785,8 @@ void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b)
t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments);
t->max_segment_size = min(t->max_segment_size,b->max_segment_size);
t->hardsect_size = max(t->hardsect_size,b->hardsect_size);
+ if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags))
+ clear_bit(QUEUE_FLAG_CLUSTER, &t->queue_flags);
}
EXPORT_SYMBOL(blk_queue_stack_limits);
@@ -906,17 +908,15 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
__FUNCTION__, depth);
}
- tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC);
+ tag_index = kzalloc(depth * sizeof(struct request *), GFP_ATOMIC);
if (!tag_index)
goto fail;
nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG;
- tag_map = kmalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC);
+ tag_map = kzalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC);
if (!tag_map)
goto fail;
- memset(tag_index, 0, depth * sizeof(struct request *));
- memset(tag_map, 0, nr_ulongs * sizeof(unsigned long));
tags->real_max_depth = depth;
tags->max_depth = depth;
tags->tag_index = tag_index;
@@ -1554,7 +1554,7 @@ void blk_plug_device(request_queue_t *q)
* don't plug a stopped queue, it must be paired with blk_start_queue()
* which will restart the queueing
*/
- if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
+ if (blk_queue_stopped(q))
return;
if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
@@ -1587,7 +1587,7 @@ EXPORT_SYMBOL(blk_remove_plug);
*/
void __generic_unplug_device(request_queue_t *q)
{
- if (unlikely(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)))
+ if (unlikely(blk_queue_stopped(q)))
return;
if (!blk_remove_plug(q))
@@ -1732,15 +1732,28 @@ void blk_run_queue(struct request_queue *q)
spin_lock_irqsave(q->queue_lock, flags);
blk_remove_plug(q);
- if (!elv_queue_empty(q))
- q->request_fn(q);
+
+ /*
+ * Only recurse once to avoid overrunning the stack, let the unplug
+ * handling reinvoke the handler shortly if we already got there.
+ */
+ if (!elv_queue_empty(q)) {
+ if (!test_and_set_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
+ q->request_fn(q);
+ clear_bit(QUEUE_FLAG_REENTER, &q->queue_flags);
+ } else {
+ blk_plug_device(q);
+ kblockd_schedule_work(&q->unplug_work);
+ }
+ }
+
spin_unlock_irqrestore(q->queue_lock, flags);
}
EXPORT_SYMBOL(blk_run_queue);
/**
* blk_cleanup_queue: - release a &request_queue_t when it is no longer needed
- * @q: the request queue to be released
+ * @kobj: the kobj belonging of the request queue to be released
*
* Description:
* blk_cleanup_queue is the pair to blk_init_queue() or
@@ -2479,10 +2492,12 @@ void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk,
rq->rq_disk = bd_disk;
rq->flags |= REQ_NOMERGE;
rq->end_io = done;
- elv_add_request(q, rq, where, 1);
- generic_unplug_device(q);
+ WARN_ON(irqs_disabled());
+ spin_lock_irq(q->queue_lock);
+ __elv_add_request(q, rq, where, 1);
+ __generic_unplug_device(q);
+ spin_unlock_irq(q->queue_lock);
}
-
EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
/**
@@ -3383,7 +3398,7 @@ static int blk_cpu_notify(struct notifier_block *self, unsigned long action,
}
-static struct notifier_block __devinitdata blk_cpu_notifier = {
+static struct notifier_block blk_cpu_notifier = {
.notifier_call = blk_cpu_notify,
};
@@ -3437,7 +3452,12 @@ void end_that_request_last(struct request *req, int uptodate)
if (unlikely(laptop_mode) && blk_fs_request(req))
laptop_io_completion();
- if (disk && blk_fs_request(req)) {
+ /*
+ * Account IO completion. bar_rq isn't accounted as a normal
+ * IO on queueing nor completion. Accounting the containing
+ * request is enough.
+ */
+ if (disk && blk_fs_request(req) && req != &req->q->bar_rq) {
unsigned long duration = jiffies - req->start_time;
const int rw = rq_data_dir(req);
@@ -3512,7 +3532,7 @@ int __init blk_dev_init(void)
iocontext_cachep = kmem_cache_create("blkdev_ioc",
sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL);
- for_each_cpu(i)
+ for_each_possible_cpu(i)
INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i));
open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL);
@@ -3537,11 +3557,17 @@ void put_io_context(struct io_context *ioc)
BUG_ON(atomic_read(&ioc->refcount) == 0);
if (atomic_dec_and_test(&ioc->refcount)) {
+ struct cfq_io_context *cic;
+
rcu_read_lock();
if (ioc->aic && ioc->aic->dtor)
ioc->aic->dtor(ioc->aic);
- if (ioc->cic && ioc->cic->dtor)
- ioc->cic->dtor(ioc->cic);
+ if (ioc->cic_root.rb_node != NULL) {
+ struct rb_node *n = rb_first(&ioc->cic_root);
+
+ cic = rb_entry(n, struct cfq_io_context, rb_node);
+ cic->dtor(ioc);
+ }
rcu_read_unlock();
kmem_cache_free(iocontext_cachep, ioc);
@@ -3554,6 +3580,7 @@ void exit_io_context(void)
{
unsigned long flags;
struct io_context *ioc;
+ struct cfq_io_context *cic;
local_irq_save(flags);
task_lock(current);
@@ -3565,9 +3592,11 @@ void exit_io_context(void)
if (ioc->aic && ioc->aic->exit)
ioc->aic->exit(ioc->aic);
- if (ioc->cic && ioc->cic->exit)
- ioc->cic->exit(ioc->cic);
-
+ if (ioc->cic_root.rb_node != NULL) {
+ cic = rb_entry(rb_first(&ioc->cic_root), struct cfq_io_context, rb_node);
+ cic->exit(ioc);
+ }
+
put_io_context(ioc);
}
@@ -3596,7 +3625,7 @@ struct io_context *current_io_context(gfp_t gfp_flags)
ret->last_waited = jiffies; /* doesn't matter... */
ret->nr_batch_requests = 0; /* because this is 0 */
ret->aic = NULL;
- ret->cic = NULL;
+ ret->cic_root.rb_node = NULL;
tsk->io_context = ret;
}
diff --git a/block/noop-iosched.c b/block/noop-iosched.c
index f370e4a7fe6..56a7c620574 100644
--- a/block/noop-iosched.c
+++ b/block/noop-iosched.c
@@ -65,16 +65,15 @@ noop_latter_request(request_queue_t *q, struct request *rq)
return list_entry(rq->queuelist.next, struct request, queuelist);
}
-static int noop_init_queue(request_queue_t *q, elevator_t *e)
+static void *noop_init_queue(request_queue_t *q, elevator_t *e)
{
struct noop_data *nd;
nd = kmalloc(sizeof(*nd), GFP_KERNEL);
if (!nd)
- return -ENOMEM;
+ return NULL;
INIT_LIST_HEAD(&nd->queue);
- e->elevator_data = nd;
- return 0;
+ return nd;
}
static void noop_exit_queue(elevator_t *e)
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 24f7af9d0ab..b33eda26e20 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -350,16 +350,51 @@ out:
return ret;
}
+/**
+ * sg_scsi_ioctl -- handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl
+ * @file: file this ioctl operates on (optional)
+ * @q: request queue to send scsi commands down
+ * @disk: gendisk to operate on (option)
+ * @sic: userspace structure describing the command to perform
+ *
+ * Send down the scsi command described by @sic to the device below
+ * the request queue @q. If @file is non-NULL it's used to perform
+ * fine-grained permission checks that allow users to send down
+ * non-destructive SCSI commands. If the caller has a struct gendisk
+ * available it should be passed in as @disk to allow the low level
+ * driver to use the information contained in it. A non-NULL @disk
+ * is only allowed if the caller knows that the low level driver doesn't
+ * need it (e.g. in the scsi subsystem).
+ *
+ * Notes:
+ * - This interface is deprecated - users should use the SG_IO
+ * interface instead, as this is a more flexible approach to
+ * performing SCSI commands on a device.
+ * - The SCSI command length is determined by examining the 1st byte
+ * of the given command. There is no way to override this.
+ * - Data transfers are limited to PAGE_SIZE
+ * - The length (x + y) must be at least OMAX_SB_LEN bytes long to
+ * accommodate the sense buffer when an error occurs.
+ * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
+ * old code will not be surprised.
+ * - If a Unix error occurs (e.g. ENOMEM) then the user will receive
+ * a negative return and the Unix error code in 'errno'.
+ * If the SCSI command succeeds then 0 is returned.
+ * Positive numbers returned are the compacted SCSI error codes (4
+ * bytes in one int) where the lowest byte is the SCSI status.
+ */
#define OMAX_SB_LEN 16 /* For backward compatibility */
-
-static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
- struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic)
+int sg_scsi_ioctl(struct file *file, struct request_queue *q,
+ struct gendisk *disk, struct scsi_ioctl_command __user *sic)
{
struct request *rq;
int err;
unsigned int in_len, out_len, bytes, opcode, cmdlen;
char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
+ if (!sic)
+ return -EINVAL;
+
/*
* get in an out lengths, verify they don't exceed a page worth of data
*/
@@ -393,45 +428,53 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
if (copy_from_user(rq->cmd, sic->data, cmdlen))
goto error;
- if (copy_from_user(buffer, sic->data + cmdlen, in_len))
+ if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
goto error;
err = verify_command(file, rq->cmd);
if (err)
goto error;
+ /* default. possible overriden later */
+ rq->retries = 5;
+
switch (opcode) {
- case SEND_DIAGNOSTIC:
- case FORMAT_UNIT:
- rq->timeout = FORMAT_UNIT_TIMEOUT;
- break;
- case START_STOP:
- rq->timeout = START_STOP_TIMEOUT;
- break;
- case MOVE_MEDIUM:
- rq->timeout = MOVE_MEDIUM_TIMEOUT;
- break;
- case READ_ELEMENT_STATUS:
- rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
- break;
- case READ_DEFECT_DATA:
- rq->timeout = READ_DEFECT_DATA_TIMEOUT;
- break;
- default:
- rq->timeout = BLK_DEFAULT_TIMEOUT;
- break;
+ case SEND_DIAGNOSTIC:
+ case FORMAT_UNIT:
+ rq->timeout = FORMAT_UNIT_TIMEOUT;
+ rq->retries = 1;
+ break;
+ case START_STOP:
+ rq->timeout = START_STOP_TIMEOUT;
+ break;
+ case MOVE_MEDIUM:
+ rq->timeout = MOVE_MEDIUM_TIMEOUT;
+ break;
+ case READ_ELEMENT_STATUS:
+ rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
+ break;
+ case READ_DEFECT_DATA:
+ rq->timeout = READ_DEFECT_DATA_TIMEOUT;
+ rq->retries = 1;
+ break;
+ default:
+ rq->timeout = BLK_DEFAULT_TIMEOUT;
+ break;
+ }
+
+ if (bytes && blk_rq_map_kern(q, rq, buffer, bytes, __GFP_WAIT)) {
+ err = DRIVER_ERROR << 24;
+ goto out;
}
memset(sense, 0, sizeof(sense));
rq->sense = sense;
rq->sense_len = 0;
-
- rq->data = buffer;
- rq->data_len = bytes;
rq->flags |= REQ_BLOCK_PC;
- rq->retries = 0;
- blk_execute_rq(q, bd_disk, rq, 0);
+ blk_execute_rq(q, disk, rq, 0);
+
+out:
err = rq->errors & 0xff; /* only 8 bit SCSI status */
if (err) {
if (rq->sense_len && rq->sense) {
@@ -450,7 +493,7 @@ error:
blk_put_request(rq);
return err;
}
-
+EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
/* Send basic block requests */
static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index bddf431bbb7..aeb5ab2391e 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -64,10 +64,12 @@ source "drivers/usb/Kconfig"
source "drivers/mmc/Kconfig"
-source "drivers/infiniband/Kconfig"
+source "drivers/leds/Kconfig"
-source "drivers/sn/Kconfig"
+source "drivers/infiniband/Kconfig"
source "drivers/edac/Kconfig"
+source "drivers/rtc/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 5c69b86db62..447d8e68887 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -25,9 +25,6 @@ obj-$(CONFIG_CONNECTOR) += connector/
obj-$(CONFIG_FB_I810) += video/i810/
obj-$(CONFIG_FB_INTEL) += video/intelfb/
-# we also need input/serio early so serio bus is initialized by the time
-# serial drivers start registering their serio ports
-obj-$(CONFIG_SERIO) += input/serio/
obj-y += serial/
obj-$(CONFIG_PARPORT) += parport/
obj-y += base/ block/ misc/ mfd/ net/ media/
@@ -53,9 +50,11 @@ obj-$(CONFIG_TC) += tc/
obj-$(CONFIG_USB) += usb/
obj-$(CONFIG_PCI) += usb/
obj-$(CONFIG_USB_GADGET) += usb/gadget/
+obj-$(CONFIG_SERIO) += input/serio/
obj-$(CONFIG_GAMEPORT) += input/gameport/
obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_I2O) += message/
+obj-$(CONFIG_RTC_LIB) += rtc/
obj-$(CONFIG_I2C) += i2c/
obj-$(CONFIG_W1) += w1/
obj-$(CONFIG_HWMON) += hwmon/
@@ -68,7 +67,9 @@ obj-$(CONFIG_MCA) += mca/
obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_MMC) += mmc/
+obj-$(CONFIG_NEW_LEDS) += leds/
obj-$(CONFIG_INFINIBAND) += infiniband/
+obj-$(CONFIG_IPATH_CORE) += infiniband/
obj-$(CONFIG_SGI_SN) += sn/
obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 5cb96300eb0..2b2fbec1454 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -10,9 +10,8 @@ menu "ACPI (Advanced Configuration and Power Interface) Support"
config ACPI
bool "ACPI Support"
depends on IA64 || X86
+ depends on PCI
select PM
- select PCI
-
default y
---help---
Advanced Configuration and Power Interface (ACPI) support for
@@ -329,7 +328,7 @@ config ACPI_CONTAINER
config ACPI_HOTPLUG_MEMORY
tristate "Memory Hotplug"
depends on ACPI
- depends on MEMORY_HOTPLUG
+ depends on MEMORY_HOTPLUG || X86_64
default n
help
This driver adds supports for ACPI Memory Hotplug. This driver
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index d882bf87fa9..e0a95ba7237 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -74,7 +74,7 @@ struct acpi_memory_device {
unsigned short caching; /* memory cache attribute */
unsigned short write_protect; /* memory read/write attribute */
u64 start_addr; /* Memory Range start physical addr */
- u64 end_addr; /* Memory Range end physical addr */
+ u64 length; /* Memory Range length */
};
static int
@@ -97,12 +97,11 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
if (ACPI_SUCCESS(status)) {
if (address64.resource_type == ACPI_MEMORY_RANGE) {
/* Populate the structure */
- mem_device->caching =
- address64.info.mem.caching;
+ mem_device->caching = address64.info.mem.caching;
mem_device->write_protect =
address64.info.mem.write_protect;
mem_device->start_addr = address64.minimum;
- mem_device->end_addr = address64.maximum;
+ mem_device->length = address64.address_length;
}
}
@@ -199,8 +198,7 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
* Tell the VM there is more memory here...
* Note: Assume that this function returns zero on success
*/
- result = add_memory(mem_device->start_addr,
- (mem_device->end_addr - mem_device->start_addr) + 1);
+ result = add_memory(mem_device->start_addr, mem_device->length);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "\nadd_memory failed\n"));
mem_device->state = MEMORY_INVALID_STATE;
@@ -249,7 +247,7 @@ static int acpi_memory_disable_device(struct acpi_memory_device *mem_device)
{
int result;
u64 start = mem_device->start_addr;
- u64 len = mem_device->end_addr - start + 1;
+ u64 len = mem_device->length;
ACPI_FUNCTION_TRACE("acpi_memory_disable_device");
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index f4c87750dbf..1a545489e85 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -817,7 +817,7 @@ typedef int (proc_writefunc) (struct file * file, const char __user * buffer,
unsigned long count, void *data);
static int
-__init asus_proc_add(char *name, proc_writefunc * writefunc,
+asus_proc_add(char *name, proc_writefunc * writefunc,
proc_readfunc * readfunc, mode_t mode,
struct acpi_device *device)
{
@@ -836,7 +836,7 @@ __init asus_proc_add(char *name, proc_writefunc * writefunc,
return 0;
}
-static int __init asus_hotk_add_fs(struct acpi_device *device)
+static int asus_hotk_add_fs(struct acpi_device *device)
{
struct proc_dir_entry *proc;
mode_t mode;
@@ -954,7 +954,7 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
* This function is used to initialize the hotk with right values. In this
* method, we can make all the detection we want, and modify the hotk struct
*/
-static int __init asus_hotk_get_info(void)
+static int asus_hotk_get_info(void)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -970,7 +970,7 @@ static int __init asus_hotk_get_info(void)
* HID), this bit will be moved. A global variable asus_info contains
* the DSDT header.
*/
- status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt);
+ status = acpi_get_table(ACPI_TABLE_ID_DSDT, 1, &dsdt);
if (ACPI_FAILURE(status))
printk(KERN_WARNING " Couldn't get the DSDT table header\n");
else
@@ -1101,7 +1101,7 @@ static int __init asus_hotk_get_info(void)
return AE_OK;
}
-static int __init asus_hotk_check(void)
+static int asus_hotk_check(void)
{
int result = 0;
@@ -1119,7 +1119,7 @@ static int __init asus_hotk_check(void)
return result;
}
-static int __init asus_hotk_add(struct acpi_device *device)
+static int asus_hotk_add(struct acpi_device *device)
{
acpi_status status = AE_OK;
int result;
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 606f8733a77..b77f03d51f0 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -43,7 +43,7 @@ ACPI_MODULE_NAME("acpi_bus")
extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger);
#endif
-FADT_DESCRIPTOR acpi_fadt;
+struct fadt_descriptor acpi_fadt;
EXPORT_SYMBOL(acpi_fadt);
struct acpi_device *acpi_root;
@@ -596,6 +596,8 @@ void __init acpi_early_init(void)
if (acpi_disabled)
return_VOID;
+ printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION);
+
/* enable workarounds, unless strict ACPI spec. compliance */
if (!acpi_strict)
acpi_gbl_enable_interpreter_slack = TRUE;
@@ -617,7 +619,7 @@ void __init acpi_early_init(void)
/*
* Get a separate copy of the FADT for use by other drivers.
*/
- status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer);
+ status = acpi_get_table(ACPI_TABLE_ID_FADT, 1, &buffer);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX "Unable to get the FADT\n");
goto error0;
@@ -743,8 +745,6 @@ static int __init acpi_init(void)
ACPI_FUNCTION_TRACE("acpi_init");
- printk(KERN_INFO PREFIX "Subsystem revision %08x\n", ACPI_CA_VERSION);
-
if (acpi_disabled) {
printk(KERN_INFO PREFIX "Interpreter disabled.\n");
return_VALUE(-ENODEV);
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c
index 76bc0463f6d..a6d77efb41a 100644
--- a/drivers/acpi/dispatcher/dsfield.c
+++ b/drivers/acpi/dispatcher/dsfield.c
@@ -87,7 +87,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
union acpi_operand_object *second_desc = NULL;
u32 flags;
- ACPI_FUNCTION_TRACE("ds_create_buffer_field");
+ ACPI_FUNCTION_TRACE(ds_create_buffer_field);
/* Get the name_string argument */
@@ -210,7 +210,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
acpi_status status;
acpi_integer position;
- ACPI_FUNCTION_TRACE_PTR("ds_get_field_names", info);
+ ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info);
/* First field starts at bit zero */
@@ -342,7 +342,7 @@ acpi_ds_create_field(union acpi_parse_object *op,
union acpi_parse_object *arg;
struct acpi_create_field_info info;
- ACPI_FUNCTION_TRACE_PTR("ds_create_field", op);
+ ACPI_FUNCTION_TRACE_PTR(ds_create_field, op);
/* First arg is the name of the parent op_region (must already exist) */
@@ -399,7 +399,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
struct acpi_namespace_node *node;
u8 type = 0;
- ACPI_FUNCTION_TRACE_PTR("ds_init_field_objects", op);
+ ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
switch (walk_state->opcode) {
case AML_FIELD_OP:
@@ -425,6 +425,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
* Walk the list of entries in the field_list
*/
while (arg) {
+
/* Ignore OFFSET and ACCESSAS terms here */
if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
@@ -481,7 +482,7 @@ acpi_ds_create_bank_field(union acpi_parse_object *op,
union acpi_parse_object *arg;
struct acpi_create_field_info info;
- ACPI_FUNCTION_TRACE_PTR("ds_create_bank_field", op);
+ ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op);
/* First arg is the name of the parent op_region (must already exist) */
@@ -554,7 +555,7 @@ acpi_ds_create_index_field(union acpi_parse_object *op,
union acpi_parse_object *arg;
struct acpi_create_field_info info;
- ACPI_FUNCTION_TRACE_PTR("ds_create_index_field", op);
+ ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op);
/* First arg is the name of the Index register (must already exist) */
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c
index e65a07ad242..bbdf990e9f6 100644
--- a/drivers/acpi/dispatcher/dsinit.c
+++ b/drivers/acpi/dispatcher/dsinit.c
@@ -184,7 +184,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
*
* RETURN: Status
*
- * DESCRIPTION: Walk the namespace starting at "start_node" and perform any
+ * DESCRIPTION: Walk the namespace starting at "StartNode" and perform any
* necessary initialization on the objects found therein
*
******************************************************************************/
@@ -196,7 +196,7 @@ acpi_ds_initialize_objects(struct acpi_table_desc * table_desc,
acpi_status status;
struct acpi_init_walk_info info;
- ACPI_FUNCTION_TRACE("ds_initialize_objects");
+ ACPI_FUNCTION_TRACE(ds_initialize_objects);
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"**** Starting initialization of namespace objects ****\n"));
@@ -213,7 +213,7 @@ acpi_ds_initialize_objects(struct acpi_table_desc * table_desc,
status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
acpi_ds_init_one_object, &info, NULL);
if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace"));
+ ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index c475546535b..bc9aca4e740 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -81,6 +81,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)
/* Invoke the global exception handler */
if (acpi_gbl_exception_handler) {
+
/* Exit the interpreter, allow handler to execute methods */
acpi_ex_exit_interpreter();
@@ -100,6 +101,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)
}
#ifdef ACPI_DISASSEMBLER
if (ACPI_FAILURE(status)) {
+
/* Display method locals/args if disassembler is present */
acpi_dm_dump_method_info(status, walk_state, walk_state->op);
@@ -132,7 +134,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE_PTR("ds_begin_method_execution", method_node);
+ ACPI_FUNCTION_TRACE_PTR(ds_begin_method_execution, method_node);
if (!method_node) {
return_ACPI_STATUS(AE_NULL_ENTRY);
@@ -168,11 +170,14 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,
/*
* Get a unit from the method semaphore. This releases the
- * interpreter if we block
+ * interpreter if we block (then reacquires it)
*/
status =
acpi_ex_system_wait_semaphore(obj_desc->method.semaphore,
ACPI_WAIT_FOREVER);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
}
/*
@@ -183,7 +188,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,
if (!obj_desc->method.owner_id) {
status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ goto cleanup;
}
}
@@ -193,6 +198,14 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,
*/
obj_desc->method.thread_count++;
return_ACPI_STATUS(status);
+
+ cleanup:
+ /* On error, must signal the method semaphore if present */
+
+ if (obj_desc->method.semaphore) {
+ (void)acpi_os_signal_semaphore(obj_desc->method.semaphore, 1);
+ }
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -218,10 +231,10 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
struct acpi_namespace_node *method_node;
struct acpi_walk_state *next_walk_state = NULL;
union acpi_operand_object *obj_desc;
- struct acpi_parameter_info info;
+ struct acpi_evaluate_info *info;
u32 i;
- ACPI_FUNCTION_TRACE_PTR("ds_call_control_method", this_walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state);
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Execute method %p, currentstate=%p\n",
@@ -240,25 +253,31 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
return_ACPI_STATUS(AE_NULL_OBJECT);
}
- /* Init for new method, wait on concurrency semaphore */
+ /* Init for new method, possibly wait on concurrency semaphore */
status = acpi_ds_begin_method_execution(method_node, obj_desc,
this_walk_state->method_node);
if (ACPI_FAILURE(status)) {
- goto cleanup;
+ return_ACPI_STATUS(status);
}
+ /*
+ * 1) Parse the method. All "normal" methods are parsed for each execution.
+ * Internal methods (_OSI, etc.) do not require parsing.
+ */
if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) {
- /* 1) Parse: Create a new walk state for the preempting walk */
+
+ /* Create a new walk state for the parse */
next_walk_state =
acpi_ds_create_walk_state(obj_desc->method.owner_id, op,
obj_desc, NULL);
if (!next_walk_state) {
- return_ACPI_STATUS(AE_NO_MEMORY);
+ status = AE_NO_MEMORY;
+ goto cleanup;
}
- /* Create and init a Root Node */
+ /* Create and init a parse tree root */
op = acpi_ps_create_scope_op();
if (!op) {
@@ -271,17 +290,20 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
obj_desc->method.aml_length,
NULL, 1);
if (ACPI_FAILURE(status)) {
- acpi_ds_delete_walk_state(next_walk_state);
+ acpi_ps_delete_parse_tree(op);
goto cleanup;
}
- /* Begin AML parse */
+ /* Begin AML parse (deletes next_walk_state) */
status = acpi_ps_parse_aml(next_walk_state);
acpi_ps_delete_parse_tree(op);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
+ }
}
- /* 2) Execute: Create a new state for the preempting walk */
+ /* 2) Begin method execution. Create a new walk state */
next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id,
NULL, obj_desc, thread);
@@ -289,6 +311,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
status = AE_NO_MEMORY;
goto cleanup;
}
+
/*
* The resolved arguments were put on the previous walk state's operand
* stack. Operands on the previous walk state stack always
@@ -296,12 +319,24 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
*/
this_walk_state->operands[this_walk_state->num_operands] = NULL;
- info.parameters = &this_walk_state->operands[0];
- info.parameter_type = ACPI_PARAM_ARGS;
+ /*
+ * Allocate and initialize the evaluation information block
+ * TBD: this is somewhat inefficient, should change interface to
+ * ds_init_aml_walk. For now, keeps this struct off the CPU stack
+ */
+ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+ if (!info) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ info->parameters = &this_walk_state->operands[0];
+ info->parameter_type = ACPI_PARAM_ARGS;
status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node,
obj_desc->method.aml_start,
- obj_desc->method.aml_length, &info, 3);
+ obj_desc->method.aml_length, info, 3);
+
+ ACPI_FREE(info);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -323,6 +358,8 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
"Starting nested execution, newstate=%p\n",
next_walk_state));
+ /* Invoke an internal method if necessary */
+
if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
status = obj_desc->method.implementation(next_walk_state);
}
@@ -330,16 +367,14 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
return_ACPI_STATUS(status);
cleanup:
- /* Decrement the thread count on the method parse tree */
- if (next_walk_state && (next_walk_state->method_desc)) {
- next_walk_state->method_desc->method.thread_count--;
- }
+ /* On error, we must terminate the method properly */
- /* On error, we must delete the new walk state */
+ acpi_ds_terminate_control_method(obj_desc, next_walk_state);
+ if (next_walk_state) {
+ acpi_ds_delete_walk_state(next_walk_state);
+ }
- acpi_ds_terminate_control_method(next_walk_state);
- acpi_ds_delete_walk_state(next_walk_state);
return_ACPI_STATUS(status);
}
@@ -362,25 +397,33 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
union acpi_operand_object *return_desc)
{
acpi_status status;
+ int same_as_implicit_return;
- ACPI_FUNCTION_TRACE_PTR("ds_restart_control_method", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state);
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
- "****Restart [%4.4s] Op %p return_value_from_callee %p\n",
+ "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
(char *)&walk_state->method_node->name,
walk_state->method_call_op, return_desc));
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
- " return_from_this_method_used?=%X res_stack %p Walk %p\n",
+ " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
walk_state->return_used,
walk_state->results, walk_state));
/* Did the called method return a value? */
if (return_desc) {
+
+ /* Is the implicit return object the same as the return desc? */
+
+ same_as_implicit_return =
+ (walk_state->implicit_return_obj == return_desc);
+
/* Are we actually going to use the return value? */
if (walk_state->return_used) {
+
/* Save the return value from the previous method */
status = acpi_ds_result_push(return_desc, walk_state);
@@ -397,18 +440,23 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
}
/*
- * The following code is the
- * optional support for a so-called "implicit return". Some AML code
- * assumes that the last value of the method is "implicitly" returned
- * to the caller. Just save the last result as the return value.
+ * The following code is the optional support for the so-called
+ * "implicit return". Some AML code assumes that the last value of the
+ * method is "implicitly" returned to the caller, in the absence of an
+ * explicit return value.
+ *
+ * Just save the last result of the method as the return value.
+ *
* NOTE: this is optional because the ASL language does not actually
* support this behavior.
*/
else if (!acpi_ds_do_implicit_return
- (return_desc, walk_state, FALSE)) {
+ (return_desc, walk_state, FALSE)
+ || same_as_implicit_return) {
/*
* Delete the return value if it will not be used by the
- * calling method
+ * calling method or remove one reference if the explicit return
+ * is the same as the implicit return value.
*/
acpi_ut_remove_reference(return_desc);
}
@@ -421,7 +469,8 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
*
* FUNCTION: acpi_ds_terminate_control_method
*
- * PARAMETERS: walk_state - State of the method
+ * PARAMETERS: method_desc - Method object
+ * walk_state - State associated with the method
*
* RETURN: None
*
@@ -431,95 +480,100 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
*
******************************************************************************/
-void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
+void
+acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *obj_desc;
struct acpi_namespace_node *method_node;
acpi_status status;
- ACPI_FUNCTION_TRACE_PTR("ds_terminate_control_method", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state);
- if (!walk_state) {
- return_VOID;
- }
+ /* method_desc is required, walk_state is optional */
- /* The current method object was saved in the walk state */
-
- obj_desc = walk_state->method_desc;
- if (!obj_desc) {
+ if (!method_desc) {
return_VOID;
}
- /* Delete all arguments and locals */
+ if (walk_state) {
- acpi_ds_method_data_delete_all(walk_state);
+ /* Delete all arguments and locals */
+
+ acpi_ds_method_data_delete_all(walk_state);
+ }
/*
* Lock the parser while we terminate this method.
* If this is the last thread executing the method,
* we have additional cleanup to perform
*/
- status = acpi_ut_acquire_mutex(ACPI_MTX_PARSER);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_CONTROL_METHOD);
if (ACPI_FAILURE(status)) {
return_VOID;
}
/* Signal completion of the execution of this method if necessary */
- if (walk_state->method_desc->method.semaphore) {
+ if (method_desc->method.semaphore) {
status =
- acpi_os_signal_semaphore(walk_state->method_desc->method.
- semaphore, 1);
+ acpi_os_signal_semaphore(method_desc->method.semaphore, 1);
if (ACPI_FAILURE(status)) {
- ACPI_ERROR((AE_INFO,
- "Could not signal method semaphore"));
- /* Ignore error and continue cleanup */
+ /* Ignore error and continue */
+
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not signal method semaphore"));
}
}
- /*
- * There are no more threads executing this method. Perform
- * additional cleanup.
- *
- * The method Node is stored in the walk state
- */
- method_node = walk_state->method_node;
+ if (walk_state) {
+ /*
+ * Delete any objects created by this method during execution.
+ * The method Node is stored in the walk state
+ */
+ method_node = walk_state->method_node;
- /* Lock namespace for possible update */
+ /* Lock namespace for possible update */
- status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(status)) {
- goto exit;
- }
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
- /*
- * Delete any namespace entries created immediately underneath
- * the method
- */
- if (method_node->child) {
- acpi_ns_delete_namespace_subtree(method_node);
+ /*
+ * Delete any namespace entries created immediately underneath
+ * the method
+ */
+ if (method_node && method_node->child) {
+ acpi_ns_delete_namespace_subtree(method_node);
+ }
+
+ /*
+ * Delete any namespace entries created anywhere else within
+ * the namespace by the execution of this method
+ */
+ acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id);
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
}
- /*
- * Delete any namespace entries created anywhere else within
- * the namespace by the execution of this method
- */
- acpi_ns_delete_namespace_by_owner(walk_state->method_desc->method.
- owner_id);
- status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ /* Decrement the thread count on the method */
+
+ if (method_desc->method.thread_count) {
+ method_desc->method.thread_count--;
+ } else {
+ ACPI_ERROR((AE_INFO, "Invalid zero thread count in method"));
+ }
/* Are there any other threads currently executing this method? */
- if (walk_state->method_desc->method.thread_count) {
+ if (method_desc->method.thread_count) {
/*
* Additional threads. Do not release the owner_id in this case,
* we immediately reuse it for the next thread executing this method
*/
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"*** Completed execution of one thread, %d threads remaining\n",
- walk_state->method_desc->method.
- thread_count));
+ method_desc->method.thread_count));
} else {
/* This is the only executing thread for this method */
@@ -533,22 +587,20 @@ void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
* This code is here because we must wait until the last thread exits
* before creating the synchronization semaphore.
*/
- if ((walk_state->method_desc->method.concurrency == 1) &&
- (!walk_state->method_desc->method.semaphore)) {
+ if ((method_desc->method.concurrency == 1) &&
+ (!method_desc->method.semaphore)) {
status = acpi_os_create_semaphore(1, 1,
- &walk_state->
- method_desc->method.
+ &method_desc->method.
semaphore);
}
/* No more threads, we can free the owner_id */
- acpi_ut_release_owner_id(&walk_state->method_desc->method.
- owner_id);
+ acpi_ut_release_owner_id(&method_desc->method.owner_id);
}
exit:
- (void)acpi_ut_release_mutex(ACPI_MTX_PARSER);
+ (void)acpi_ut_release_mutex(ACPI_MTX_CONTROL_METHOD);
return_VOID;
}
@@ -581,7 +633,7 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
union acpi_parse_object *op;
struct acpi_walk_state *walk_state;
- ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);
+ ACPI_FUNCTION_TRACE_PTR(ds_parse_method, node);
/* Parameter Validation */
@@ -590,7 +642,7 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
}
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "**** Parsing [%4.4s] **** named_obj=%p\n",
+ "**** Parsing [%4.4s] **** NamedObj=%p\n",
acpi_ut_get_node_name(node), node));
/* Extract the method object from the method Node */
@@ -669,7 +721,7 @@ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node)
}
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
+ "**** [%4.4s] Parsed **** NamedObj=%p Op=%p\n",
acpi_ut_get_node_name(node), node, op));
/*
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
index c025674f938..459160ff905 100644
--- a/drivers/acpi/dispatcher/dsmthdat.c
+++ b/drivers/acpi/dispatcher/dsmthdat.c
@@ -81,7 +81,7 @@ acpi_ds_method_data_get_type(u16 opcode,
* special data types.
*
* NOTES: walk_state fields are initialized to zero by the
- * ACPI_MEM_CALLOCATE().
+ * ACPI_ALLOCATE_ZEROED().
*
* A pseudo-Namespace Node is assigned to each argument and local
* so that ref_of() can return a pointer to the Node.
@@ -92,7 +92,7 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
{
u32 i;
- ACPI_FUNCTION_TRACE("ds_method_data_init");
+ ACPI_FUNCTION_TRACE(ds_method_data_init);
/* Init the method arguments */
@@ -100,10 +100,10 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name,
NAMEOF_ARG_NTE);
walk_state->arguments[i].name.integer |= (i << 24);
- walk_state->arguments[i].descriptor = ACPI_DESC_TYPE_NAMED;
+ walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED;
walk_state->arguments[i].type = ACPI_TYPE_ANY;
- walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST |
- ANOBJ_METHOD_ARG;
+ walk_state->arguments[i].flags =
+ ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG;
}
/* Init the method locals */
@@ -113,11 +113,11 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
NAMEOF_LOCAL_NTE);
walk_state->local_variables[i].name.integer |= (i << 24);
- walk_state->local_variables[i].descriptor =
+ walk_state->local_variables[i].descriptor_type =
ACPI_DESC_TYPE_NAMED;
walk_state->local_variables[i].type = ACPI_TYPE_ANY;
- walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST |
- ANOBJ_METHOD_LOCAL;
+ walk_state->local_variables[i].flags =
+ ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL;
}
return_VOID;
@@ -140,7 +140,7 @@ void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state)
{
u32 index;
- ACPI_FUNCTION_TRACE("ds_method_data_delete_all");
+ ACPI_FUNCTION_TRACE(ds_method_data_delete_all);
/* Detach the locals */
@@ -199,7 +199,7 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params,
acpi_status status;
u32 index = 0;
- ACPI_FUNCTION_TRACE_PTR("ds_method_data_init_args", params);
+ ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params);
if (!params) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -251,7 +251,7 @@ acpi_ds_method_data_get_node(u16 opcode,
struct acpi_walk_state *walk_state,
struct acpi_namespace_node **node)
{
- ACPI_FUNCTION_TRACE("ds_method_data_get_node");
+ ACPI_FUNCTION_TRACE(ds_method_data_get_node);
/*
* Method Locals and Arguments are supported
@@ -318,10 +318,10 @@ acpi_ds_method_data_set_value(u16 opcode,
acpi_status status;
struct acpi_namespace_node *node;
- ACPI_FUNCTION_TRACE("ds_method_data_set_value");
+ ACPI_FUNCTION_TRACE(ds_method_data_set_value);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "new_obj %p Opcode %X, Refs=%d [%s]\n", object,
+ "NewObj %p Opcode %X, Refs=%d [%s]\n", object,
opcode, object->common.reference_count,
acpi_ut_get_type_name(object->common.type)));
@@ -336,7 +336,7 @@ acpi_ds_method_data_set_value(u16 opcode,
* Increment ref count so object can't be deleted while installed.
* NOTE: We do not copy the object in order to preserve the call by
* reference semantics of ACPI Control Method invocation.
- * (See ACPI specification 2.0_c)
+ * (See ACPI Specification 2.0_c)
*/
acpi_ut_add_reference(object);
@@ -351,7 +351,7 @@ acpi_ds_method_data_set_value(u16 opcode,
* FUNCTION: acpi_ds_method_data_get_value
*
* PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
- * Index - which local_var or argument to get
+ * Index - Which local_var or argument to get
* walk_state - Current walk state object
* dest_desc - Where Arg or Local value is returned
*
@@ -372,7 +372,7 @@ acpi_ds_method_data_get_value(u16 opcode,
struct acpi_namespace_node *node;
union acpi_operand_object *object;
- ACPI_FUNCTION_TRACE("ds_method_data_get_value");
+ ACPI_FUNCTION_TRACE(ds_method_data_get_value);
/* Validate the object descriptor */
@@ -459,7 +459,7 @@ acpi_ds_method_data_get_value(u16 opcode,
* FUNCTION: acpi_ds_method_data_delete_value
*
* PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
- * Index - which local_var or argument to delete
+ * Index - Which local_var or argument to delete
* walk_state - Current walk state object
*
* RETURN: None
@@ -477,7 +477,7 @@ acpi_ds_method_data_delete_value(u16 opcode,
struct acpi_namespace_node *node;
union acpi_operand_object *object;
- ACPI_FUNCTION_TRACE("ds_method_data_delete_value");
+ ACPI_FUNCTION_TRACE(ds_method_data_delete_value);
/* Get the namespace node for the arg/local */
@@ -538,7 +538,7 @@ acpi_ds_store_object_to_local(u16 opcode,
union acpi_operand_object *current_obj_desc;
union acpi_operand_object *new_obj_desc;
- ACPI_FUNCTION_TRACE("ds_store_object_to_local");
+ ACPI_FUNCTION_TRACE(ds_store_object_to_local);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n",
opcode, index, obj_desc));
@@ -614,7 +614,7 @@ acpi_ds_store_object_to_local(u16 opcode,
&& (current_obj_desc->reference.opcode ==
AML_REF_OF_OP)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Arg (%p) is an obj_ref(Node), storing in node %p\n",
+ "Arg (%p) is an ObjRef(Node), storing in node %p\n",
new_obj_desc,
current_obj_desc));
@@ -688,7 +688,7 @@ acpi_ds_method_data_get_type(u16 opcode,
struct acpi_namespace_node *node;
union acpi_operand_object *object;
- ACPI_FUNCTION_TRACE("ds_method_data_get_type");
+ ACPI_FUNCTION_TRACE(ds_method_data_get_type);
/* Get the namespace node for the arg/local */
@@ -701,6 +701,7 @@ acpi_ds_method_data_get_type(u16 opcode,
object = acpi_ns_get_attached_object(node);
if (!object) {
+
/* Uninitialized local/arg, return TYPE_ANY */
return_VALUE(ACPI_TYPE_ANY);
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
index 8b21f0f9e51..72190abb1d5 100644
--- a/drivers/acpi/dispatcher/dsobject.c
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -81,7 +81,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
union acpi_operand_object *obj_desc;
acpi_status status;
- ACPI_FUNCTION_TRACE("ds_build_internal_object");
+ ACPI_FUNCTION_TRACE(ds_build_internal_object);
*obj_desc_ptr = NULL;
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
@@ -103,6 +103,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
common.
node)));
if (ACPI_FAILURE(status)) {
+
/* Check if we are resolving a named reference within a package */
if ((status == AE_NOT_FOUND)
@@ -186,7 +187,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
union acpi_parse_object *byte_list;
u32 byte_list_length = 0;
- ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj");
+ ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj);
/*
* If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
@@ -195,6 +196,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
*/
obj_desc = *obj_desc_ptr;
if (!obj_desc) {
+
/* Create a new buffer object */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
@@ -243,7 +245,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
"Buffer defined with zero length in AML, creating\n"));
} else {
obj_desc->buffer.pointer =
- ACPI_MEM_CALLOCATE(obj_desc->buffer.length);
+ ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length);
if (!obj_desc->buffer.pointer) {
acpi_ut_delete_object_desc(obj_desc);
return_ACPI_STATUS(AE_NO_MEMORY);
@@ -291,7 +293,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
acpi_status status = AE_OK;
acpi_native_uint i;
- ACPI_FUNCTION_TRACE("ds_build_internal_package_obj");
+ ACPI_FUNCTION_TRACE(ds_build_internal_package_obj);
/* Find the parent of a possibly nested package */
@@ -339,9 +341,10 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
* individual objects). Add an extra pointer slot so
* that the list is always null terminated.
*/
- obj_desc->package.elements = ACPI_MEM_CALLOCATE(((acpi_size) obj_desc->
- package.count +
- 1) * sizeof(void *));
+ obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
+ obj_desc->package.
+ count +
+ 1) * sizeof(void *));
if (!obj_desc->package.elements) {
acpi_ut_delete_object_desc(obj_desc);
@@ -355,6 +358,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
arg = arg->common.next;
for (i = 0; arg; i++) {
if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
+
/* Object (package or buffer) is already built */
obj_desc->package.elements[i] =
@@ -396,7 +400,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state,
acpi_status status;
union acpi_operand_object *obj_desc;
- ACPI_FUNCTION_TRACE_PTR("ds_create_node", op);
+ ACPI_FUNCTION_TRACE_PTR(ds_create_node, op);
/*
* Because of the execution pass through the non-control-method
@@ -408,6 +412,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state,
}
if (!op->common.value.arg) {
+
/* No arguments, there is nothing to do */
return_ACPI_STATUS(AE_OK);
@@ -464,11 +469,12 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
union acpi_operand_object *obj_desc;
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ds_init_object_from_op");
+ ACPI_FUNCTION_TRACE(ds_init_object_from_op);
obj_desc = *ret_obj_desc;
op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
+
/* Unknown opcode */
return_ACPI_STATUS(AE_TYPE);
@@ -626,6 +632,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
default: /* Other literals, etc.. */
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
+
/* Node was saved in Op */
obj_desc->reference.node = op->common.node;
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index 6229c10674e..5b974a8fe61 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -91,7 +91,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node,
union acpi_parse_object *op;
struct acpi_walk_state *walk_state;
- ACPI_FUNCTION_TRACE("ds_execute_arguments");
+ ACPI_FUNCTION_TRACE(ds_execute_arguments);
/*
* Allocate a new parser op to be the root of the parsed tree
@@ -193,7 +193,7 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
struct acpi_namespace_node *node;
acpi_status status;
- ACPI_FUNCTION_TRACE_PTR("ds_get_buffer_field_arguments", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
return_ACPI_STATUS(AE_OK);
@@ -206,7 +206,7 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
(ACPI_TYPE_BUFFER_FIELD, node, NULL));
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] buffer_field Arg Init\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
acpi_ut_get_node_name(node)));
/* Execute the AML code for the term_arg arguments */
@@ -235,7 +235,7 @@ acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)
struct acpi_namespace_node *node;
acpi_status status;
- ACPI_FUNCTION_TRACE_PTR("ds_get_buffer_arguments", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
return_ACPI_STATUS(AE_OK);
@@ -279,7 +279,7 @@ acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc)
struct acpi_namespace_node *node;
acpi_status status;
- ACPI_FUNCTION_TRACE_PTR("ds_get_package_arguments", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc);
if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
return_ACPI_STATUS(AE_OK);
@@ -324,7 +324,7 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
acpi_status status;
union acpi_operand_object *extra_desc;
- ACPI_FUNCTION_TRACE_PTR("ds_get_region_arguments", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc);
if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
return_ACPI_STATUS(AE_OK);
@@ -342,8 +342,7 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
(ACPI_TYPE_REGION, node, NULL));
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "[%4.4s] op_region Arg Init at AML %p\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n",
acpi_ut_get_node_name(node),
extra_desc->extra.aml_start));
@@ -352,6 +351,28 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
extra_desc->extra.aml_length,
extra_desc->extra.aml_start);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Validate the region address/length via the host OS */
+
+ status = acpi_os_validate_address(obj_desc->region.space_id,
+ obj_desc->region.address,
+ (acpi_size) obj_desc->region.length);
+ if (ACPI_FAILURE(status)) {
+ /*
+ * Invalid address/length. We will emit an error message and mark
+ * the region as invalid, so that it will cause an additional error if
+ * it is ever used. Then return AE_OK.
+ */
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During address validation of OpRegion [%4.4s]",
+ node->name.ascii));
+ obj_desc->common.flags |= AOPOBJ_INVALID;
+ status = AE_OK;
+ }
+
return_ACPI_STATUS(status);
}
@@ -411,7 +432,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode,
u8 field_flags;
acpi_status status;
- ACPI_FUNCTION_TRACE_PTR("ds_init_buffer_field", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);
/* Host object must be a Buffer */
@@ -457,7 +478,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode,
if (bit_count == 0) {
ACPI_ERROR((AE_INFO,
- "Attempt to create_field of length zero"));
+ "Attempt to CreateField of length zero"));
status = AE_AML_OPERAND_VALUE;
goto cleanup;
}
@@ -595,7 +616,7 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
- ACPI_FUNCTION_TRACE_PTR("ds_eval_buffer_field_operands", op);
+ ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);
/*
* This is where we evaluate the address and length fields of the
@@ -627,7 +648,7 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
acpi_ps_get_opcode_name(op->common.aml_opcode),
walk_state->num_operands,
- "after acpi_ex_resolve_operands");
+ "after AcpiExResolveOperands");
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)",
@@ -640,6 +661,7 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
/* Initialize the Buffer Field */
if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
+
/* NOTE: Slightly different operands for this opcode */
status =
@@ -685,7 +707,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
- ACPI_FUNCTION_TRACE_PTR("ds_eval_region_operands", op);
+ ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
/*
* This is where we evaluate the address and length fields of the
@@ -718,7 +740,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
acpi_ps_get_opcode_name(op->common.aml_opcode),
- 1, "after acpi_ex_resolve_operands");
+ 1, "after AcpiExResolveOperands");
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
@@ -744,7 +766,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
operand_desc->integer.value;
acpi_ut_remove_reference(operand_desc);
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "rgn_obj %p Addr %8.8X%8.8X Len %X\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
obj_desc,
ACPI_FORMAT_UINT64(obj_desc->region.address),
obj_desc->region.length));
@@ -780,7 +802,7 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
union acpi_operand_object *arg_desc;
u32 length;
- ACPI_FUNCTION_TRACE("ds_eval_data_object_operands");
+ ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);
/* The first operand (for all of these data objects) is the length */
@@ -874,7 +896,7 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
acpi_status status = AE_OK;
union acpi_generic_state *control_state;
- ACPI_FUNCTION_NAME("ds_exec_begin_control_op");
+ ACPI_FUNCTION_NAME(ds_exec_begin_control_op);
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op,
op->common.aml_opcode, walk_state));
@@ -952,7 +974,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
acpi_status status = AE_OK;
union acpi_generic_state *control_state;
- ACPI_FUNCTION_NAME("ds_exec_end_control_op");
+ ACPI_FUNCTION_NAME(ds_exec_end_control_op);
switch (op->common.aml_opcode) {
case AML_IF_OP:
@@ -984,6 +1006,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
if (walk_state->control_state->common.value) {
+
/* Predicate was true, go back and evaluate it again! */
status = AE_CTRL_PENDING;
@@ -1014,6 +1037,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
* has been bubbled up the tree
*/
if (op->common.value.arg) {
+
/* Since we have a real Return(), delete any implicit return */
acpi_ds_clear_implicit_return(walk_state);
@@ -1047,6 +1071,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
walk_state->return_desc = walk_state->operands[0];
} else if ((walk_state->results) &&
(walk_state->results->results.num_results > 0)) {
+
/* Since we have a real Return(), delete any implicit return */
acpi_ds_clear_implicit_return(walk_state);
@@ -1095,7 +1120,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
}
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
- "Completed RETURN_OP State=%p, ret_val=%p\n",
+ "Completed RETURN_OP State=%p, RetVal=%p\n",
walk_state, walk_state->return_desc));
/* End the control method execution right now */
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
index 53356a591ac..05230baf5de 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -68,7 +68,7 @@ ACPI_MODULE_NAME("dsutils")
******************************************************************************/
void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
{
- ACPI_FUNCTION_NAME("ds_clear_implicit_return");
+ ACPI_FUNCTION_NAME(ds_clear_implicit_return);
/*
* Slack must be enabled for this feature
@@ -115,7 +115,7 @@ u8
acpi_ds_do_implicit_return(union acpi_operand_object *return_desc,
struct acpi_walk_state *walk_state, u8 add_reference)
{
- ACPI_FUNCTION_NAME("ds_do_implicit_return");
+ ACPI_FUNCTION_NAME(ds_do_implicit_return);
/*
* Slack must be enabled for this feature, and we must
@@ -171,7 +171,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
{
const struct acpi_opcode_info *parent_info;
- ACPI_FUNCTION_TRACE_PTR("ds_is_result_used", op);
+ ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op);
/* Must have both an Op and a Result Object */
@@ -202,6 +202,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
*/
if ((!op->common.parent) ||
(op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
+
/* No parent, the return value cannot possibly be used */
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
@@ -340,7 +341,7 @@ acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
union acpi_operand_object *obj_desc;
acpi_status status;
- ACPI_FUNCTION_TRACE_PTR("ds_delete_result_if_not_used", result_obj);
+ ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj);
if (!op) {
ACPI_ERROR((AE_INFO, "Null Op"));
@@ -352,6 +353,7 @@ acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
}
if (!acpi_ds_is_result_used(op, walk_state)) {
+
/* Must pop the result stack (obj_desc should be equal to result_obj) */
status = acpi_ds_result_pop(&obj_desc, walk_state);
@@ -382,7 +384,7 @@ acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state)
u32 i;
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE_PTR("ds_resolve_operands", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state);
/*
* Attempt to resolve each of the valid operands
@@ -417,7 +419,7 @@ void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
{
u32 i;
- ACPI_FUNCTION_TRACE_PTR("ds_clear_operands", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state);
/* Remove a reference on each operand on the stack */
@@ -465,7 +467,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
acpi_interpreter_mode interpreter_mode;
const struct acpi_opcode_info *op_info;
- ACPI_FUNCTION_TRACE_PTR("ds_create_operand", arg);
+ ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg);
/* A valid name must be looked up in the namespace */
@@ -498,7 +500,9 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
*/
if ((walk_state->deferred_node) &&
(walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
- && (arg_index != 0)) {
+ && (arg_index ==
+ (u32) ((walk_state->opcode ==
+ AML_CREATE_FIELD_OP) ? 3 : 2))) {
obj_desc =
ACPI_CAST_PTR(union acpi_operand_object,
walk_state->deferred_node);
@@ -521,6 +525,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
&& (parent_op->common.aml_opcode != AML_REGION_OP)
&& (parent_op->common.aml_opcode !=
AML_INT_NAMEPATH_OP)) {
+
/* Enter name into namespace if not found */
interpreter_mode = ACPI_IMODE_LOAD_PASS2;
@@ -572,7 +577,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
/* Free the namestring created above */
- ACPI_MEM_FREE(name_string);
+ ACPI_FREE(name_string);
/* Check status from the lookup */
@@ -696,7 +701,7 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *arg;
u32 arg_count = 0;
- ACPI_FUNCTION_TRACE_PTR("ds_create_operands", first_arg);
+ ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
/* For all arguments in the list... */
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index f1af655ff11..3acbd9145d7 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -49,7 +49,6 @@
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
#include <acpi/acdebug.h>
-#include <acpi/acdisasm.h>
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dswexec")
@@ -93,7 +92,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
union acpi_operand_object *obj_desc;
union acpi_operand_object *local_obj_desc = NULL;
- ACPI_FUNCTION_TRACE_PTR("ds_get_predicate_value", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ds_get_predicate_value, walk_state);
walk_state->control_state->common.state = 0;
@@ -123,7 +122,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
if (!obj_desc) {
ACPI_ERROR((AE_INFO,
- "No predicate obj_desc=%p State=%p",
+ "No predicate ObjDesc=%p State=%p",
obj_desc, walk_state));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
@@ -140,7 +139,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO,
- "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X",
+ "Bad predicate (not an integer) ObjDesc=%p State=%p Type=%X",
obj_desc, walk_state,
ACPI_GET_OBJECT_TYPE(obj_desc)));
@@ -214,7 +213,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
acpi_status status = AE_OK;
u32 opcode_class;
- ACPI_FUNCTION_TRACE_PTR("ds_exec_begin_op", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ds_exec_begin_op, walk_state);
op = walk_state->op;
if (!op) {
@@ -296,7 +295,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
case AML_CLASS_NAMED_OBJECT:
- if (walk_state->walk_type == ACPI_WALK_METHOD) {
+ if (walk_state->walk_type & ACPI_WALK_METHOD) {
/*
* Found a named object declaration during method execution;
* we must enter this object into the namespace. The created
@@ -354,7 +353,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
union acpi_parse_object *next_op;
union acpi_parse_object *first_arg;
- ACPI_FUNCTION_TRACE_PTR("ds_exec_end_op", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state);
op = walk_state->op;
op_type = walk_state->op_info->type;
@@ -409,6 +408,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
* being the object_type and size_of operators.
*/
if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) {
+
/* Resolve all operands */
status = acpi_ex_resolve_operands(walk_state->opcode,
@@ -423,7 +423,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
acpi_ps_get_opcode_name
(walk_state->opcode),
walk_state->num_operands,
- "after ex_resolve_operands");
+ "after ExResolveOperands");
}
}
@@ -437,7 +437,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
acpi_gbl_op_type_dispatch[op_type] (walk_state);
} else {
/*
- * Treat constructs of the form "Store(local_x,local_x)" as noops when the
+ * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the
* Local is uninitialized.
*/
if ((status == AE_AML_UNINITIALIZED_LOCAL) &&
@@ -548,6 +548,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
*/
status = acpi_ds_resolve_operands(walk_state);
if (ACPI_FAILURE(status)) {
+
/* On error, clear all resolved operands */
acpi_ds_clear_operands(walk_state);
@@ -569,7 +570,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
case AML_TYPE_CREATE_FIELD:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Executing create_field Buffer/Index Op=%p\n",
+ "Executing CreateField Buffer/Index Op=%p\n",
op));
status = acpi_ds_load2_end_op(walk_state);
@@ -584,7 +585,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
case AML_TYPE_CREATE_OBJECT:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Executing create_object (Buffer/Package) Op=%p\n",
+ "Executing CreateObject (Buffer/Package) Op=%p\n",
op));
switch (op->common.parent->common.aml_opcode) {
@@ -657,7 +658,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
if (op->common.aml_opcode == AML_REGION_OP) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Executing op_region Address/Length Op=%p\n",
+ "Executing OpRegion Address/Length Op=%p\n",
op));
status =
@@ -722,6 +723,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
cleanup:
if (walk_state->result_obj) {
+
/* Break to debugger to display result */
ACPI_DEBUGGER_EXEC(acpi_db_display_result_object
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index d3d24da31c8..35074399c61 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -127,7 +127,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
char *path;
u32 flags;
- ACPI_FUNCTION_TRACE("ds_load1_begin_op");
+ ACPI_FUNCTION_TRACE(ds_load1_begin_op);
op = walk_state->op;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
@@ -178,12 +178,12 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
* Target of Scope() not found. Generate an External for it, and
* insert the name into the namespace.
*/
- acpi_dm_add_to_external_list(path);
+ acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0);
status =
acpi_ns_lookup(walk_state->scope_info, path,
object_type, ACPI_IMODE_LOAD_PASS1,
ACPI_NS_SEARCH_PARENT, walk_state,
- &(node));
+ &node);
}
#endif
if (ACPI_FAILURE(status)) {
@@ -261,6 +261,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
*/
if (walk_state->deferred_node) {
+
/* This name is already in the namespace, get the node */
node = walk_state->deferred_node;
@@ -300,10 +301,41 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
status =
acpi_ns_lookup(walk_state->scope_info, path, object_type,
ACPI_IMODE_LOAD_PASS1, flags, walk_state,
- &(node));
+ &node);
if (ACPI_FAILURE(status)) {
- ACPI_ERROR_NAMESPACE(path, status);
- return_ACPI_STATUS(status);
+ if (status == AE_ALREADY_EXISTS) {
+
+ /* The name already exists in this scope */
+
+ if (node->flags & ANOBJ_IS_EXTERNAL) {
+ /*
+ * Allow one create on an object or segment that was
+ * previously declared External
+ */
+ node->flags &= ~ANOBJ_IS_EXTERNAL;
+ node->type = (u8) object_type;
+
+ /* Just retyped a node, probably will need to open a scope */
+
+ if (acpi_ns_opens_scope(object_type)) {
+ status =
+ acpi_ds_scope_stack_push
+ (node, object_type,
+ walk_state);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS
+ (status);
+ }
+ }
+ status = AE_OK;
+ }
+ }
+
+ if (ACPI_FAILURE(status)) {
+
+ ACPI_ERROR_NAMESPACE(path, status);
+ return_ACPI_STATUS(status);
+ }
}
break;
}
@@ -311,6 +343,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
/* Common exit */
if (!op) {
+
/* Create a new op */
op = acpi_ps_alloc_op(walk_state->opcode);
@@ -359,7 +392,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
acpi_object_type object_type;
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ds_load1_end_op");
+ ACPI_FUNCTION_TRACE(ds_load1_end_op);
op = walk_state->op;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
@@ -413,6 +446,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
#endif
if (op->common.aml_opcode == AML_NAME_OP) {
+
/* For Name opcode, get the object type from the argument */
if (op->common.value.arg) {
@@ -445,7 +479,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
* arguments.)
*/
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
- "LOADING-Method: State=%p Op=%p named_obj=%p\n",
+ "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
walk_state, op, op->named.node));
if (!acpi_ns_get_attached_object(op->named.node)) {
@@ -511,7 +545,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
acpi_object_type object_type;
char *buffer_ptr;
- ACPI_FUNCTION_TRACE("ds_load2_begin_op");
+ ACPI_FUNCTION_TRACE(ds_load2_begin_op);
op = walk_state->op;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
@@ -521,6 +555,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
if ((walk_state->control_state) &&
(walk_state->control_state->common.state ==
ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
+
/* We are executing a while loop outside of a method */
status = acpi_ds_exec_begin_op(walk_state, out_op);
@@ -554,10 +589,12 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
/* Get the name we are going to enter or lookup in the namespace */
if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
+
/* For Namepath op, get the path string */
buffer_ptr = op->common.value.string;
if (!buffer_ptr) {
+
/* No name, just exit */
return_ACPI_STATUS(AE_OK);
@@ -680,6 +717,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
/* All other opcodes */
if (op && op->common.node) {
+
/* This op/node was previously entered into the namespace */
node = op->common.node;
@@ -705,6 +743,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
* Note: Name may already exist if we are executing a deferred opcode.
*/
if (walk_state->deferred_node) {
+
/* This name is already in the namespace, get the node */
node = walk_state->deferred_node;
@@ -727,6 +766,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
}
if (!op) {
+
/* Create a new op */
op = acpi_ps_alloc_op(walk_state->opcode);
@@ -776,7 +816,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
u32 i;
#endif
- ACPI_FUNCTION_TRACE("ds_load2_end_op");
+ ACPI_FUNCTION_TRACE(ds_load2_end_op);
op = walk_state->op;
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
@@ -870,7 +910,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
*/
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
- "Create-Load [%s] State=%p Op=%p named_obj=%p\n",
+ "Create-Load [%s] State=%p Op=%p NamedObj=%p\n",
acpi_ps_get_opcode_name(op->common.aml_opcode),
walk_state, op, node));
@@ -1045,7 +1085,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
* arguments.)
*/
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
- "LOADING-Method: State=%p Op=%p named_obj=%p\n",
+ "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
walk_state, op, op->named.node));
if (!acpi_ns_get_attached_object(op->named.node)) {
@@ -1090,7 +1130,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
case AML_CLASS_METHOD_CALL:
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
- "RESOLVING-method_call: State=%p Op=%p named_obj=%p\n",
+ "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n",
walk_state, op, node));
/*
@@ -1104,7 +1144,6 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
ACPI_NS_DONT_OPEN_SCOPE, walk_state,
&(new_node));
if (ACPI_SUCCESS(status)) {
-
/*
* Make sure that what we found is indeed a method
* We didn't search for a method on purpose, to see if the name
diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c
index ada21ef4a17..c9228972f5f 100644
--- a/drivers/acpi/dispatcher/dswscope.c
+++ b/drivers/acpi/dispatcher/dswscope.c
@@ -63,9 +63,10 @@ void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state)
{
union acpi_generic_state *scope_info;
- ACPI_FUNCTION_NAME("ds_scope_stack_clear");
+ ACPI_FUNCTION_NAME(ds_scope_stack_clear);
while (walk_state->scope_info) {
+
/* Pop a scope off the stack */
scope_info = walk_state->scope_info;
@@ -102,9 +103,10 @@ acpi_ds_scope_stack_push(struct acpi_namespace_node *node,
union acpi_generic_state *scope_info;
union acpi_generic_state *old_scope_info;
- ACPI_FUNCTION_TRACE("ds_scope_stack_push");
+ ACPI_FUNCTION_TRACE(ds_scope_stack_push);
if (!node) {
+
/* Invalid scope */
ACPI_ERROR((AE_INFO, "Null scope parameter"));
@@ -126,7 +128,7 @@ acpi_ds_scope_stack_push(struct acpi_namespace_node *node,
/* Init new scope object */
- scope_info->common.data_type = ACPI_DESC_TYPE_STATE_WSCOPE;
+ scope_info->common.descriptor_type = ACPI_DESC_TYPE_STATE_WSCOPE;
scope_info->scope.node = node;
scope_info->common.value = (u16) type;
@@ -176,7 +178,7 @@ acpi_status acpi_ds_scope_stack_pop(struct acpi_walk_state *walk_state)
union acpi_generic_state *scope_info;
union acpi_generic_state *new_scope_info;
- ACPI_FUNCTION_TRACE("ds_scope_stack_pop");
+ ACPI_FUNCTION_TRACE(ds_scope_stack_pop);
/*
* Pop scope info object off the stack.
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
index fa78cb74ee3..7817e552267 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -66,7 +66,6 @@ void *acpi_ds_obj_stack_get_value(u32 index,
#endif
#ifdef ACPI_FUTURE_USAGE
-
/*******************************************************************************
*
* FUNCTION: acpi_ds_result_remove
@@ -88,7 +87,7 @@ acpi_ds_result_remove(union acpi_operand_object **object,
{
union acpi_generic_state *state;
- ACPI_FUNCTION_NAME("ds_result_remove");
+ ACPI_FUNCTION_NAME(ds_result_remove);
state = walk_state->results;
if (!state) {
@@ -128,7 +127,6 @@ acpi_ds_result_remove(union acpi_operand_object **object,
return (AE_OK);
}
-
#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
@@ -152,7 +150,7 @@ acpi_ds_result_pop(union acpi_operand_object ** object,
acpi_native_uint index;
union acpi_generic_state *state;
- ACPI_FUNCTION_NAME("ds_result_pop");
+ ACPI_FUNCTION_NAME(ds_result_pop);
state = walk_state->results;
if (!state) {
@@ -170,6 +168,7 @@ acpi_ds_result_pop(union acpi_operand_object ** object,
state->results.num_results--;
for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) {
+
/* Check for a valid result object */
if (state->results.obj_desc[index - 1]) {
@@ -213,7 +212,7 @@ acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object,
acpi_native_uint index;
union acpi_generic_state *state;
- ACPI_FUNCTION_NAME("ds_result_pop_from_bottom");
+ ACPI_FUNCTION_NAME(ds_result_pop_from_bottom);
state = walk_state->results;
if (!state) {
@@ -278,7 +277,7 @@ acpi_ds_result_push(union acpi_operand_object * object,
{
union acpi_generic_state *state;
- ACPI_FUNCTION_NAME("ds_result_push");
+ ACPI_FUNCTION_NAME(ds_result_push);
state = walk_state->results;
if (!state) {
@@ -331,14 +330,14 @@ acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state)
{
union acpi_generic_state *state;
- ACPI_FUNCTION_NAME("ds_result_stack_push");
+ ACPI_FUNCTION_NAME(ds_result_stack_push);
state = acpi_ut_create_generic_state();
if (!state) {
return (AE_NO_MEMORY);
}
- state->common.data_type = ACPI_DESC_TYPE_STATE_RESULT;
+ state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT;
acpi_ut_push_generic_state(&walk_state->results, state);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n",
@@ -363,7 +362,7 @@ acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state)
{
union acpi_generic_state *state;
- ACPI_FUNCTION_NAME("ds_result_stack_pop");
+ ACPI_FUNCTION_NAME(ds_result_stack_pop);
/* Check for stack underflow */
@@ -376,7 +375,7 @@ acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state)
state = acpi_ut_pop_generic_state(&walk_state->results);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Result=%p remaining_results=%X State=%p\n",
+ "Result=%p RemainingResults=%X State=%p\n",
state, state->results.num_results, walk_state));
acpi_ut_delete_generic_state(state);
@@ -400,7 +399,7 @@ acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state)
acpi_status
acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state)
{
- ACPI_FUNCTION_NAME("ds_obj_stack_push");
+ ACPI_FUNCTION_NAME(ds_obj_stack_push);
/* Check for stack overflow */
@@ -445,9 +444,10 @@ acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state)
{
u32 i;
- ACPI_FUNCTION_NAME("ds_obj_stack_pop");
+ ACPI_FUNCTION_NAME(ds_obj_stack_pop);
for (i = 0; i < pop_count; i++) {
+
/* Check for stack underflow */
if (walk_state->num_operands == 0) {
@@ -491,9 +491,10 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
u32 i;
union acpi_operand_object *obj_desc;
- ACPI_FUNCTION_NAME("ds_obj_stack_pop_and_delete");
+ ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete);
for (i = 0; i < pop_count; i++) {
+
/* Check for stack underflow */
if (walk_state->num_operands == 0) {
@@ -538,13 +539,13 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state
*thread)
{
- ACPI_FUNCTION_NAME("ds_get_current_walk_state");
+ ACPI_FUNCTION_NAME(ds_get_current_walk_state);
if (!thread) {
return (NULL);
}
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current walk_state %p\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current WalkState %p\n",
thread->walk_state_list));
return (thread->walk_state_list);
@@ -567,7 +568,7 @@ void
acpi_ds_push_walk_state(struct acpi_walk_state *walk_state,
struct acpi_thread_state *thread)
{
- ACPI_FUNCTION_TRACE("ds_push_walk_state");
+ ACPI_FUNCTION_TRACE(ds_push_walk_state);
walk_state->next = thread->walk_state_list;
thread->walk_state_list = walk_state;
@@ -593,11 +594,12 @@ struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread)
{
struct acpi_walk_state *walk_state;
- ACPI_FUNCTION_TRACE("ds_pop_walk_state");
+ ACPI_FUNCTION_TRACE(ds_pop_walk_state);
walk_state = thread->walk_state_list;
if (walk_state) {
+
/* Next walk state becomes the current walk state */
thread->walk_state_list = walk_state->next;
@@ -618,7 +620,7 @@ struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread)
*
* PARAMETERS: owner_id - ID for object creation
* Origin - Starting point for this walk
- * mth_desc - Method object
+ * method_desc - Method object
* Thread - Current thread state
*
* RETURN: Pointer to the new walk state.
@@ -632,24 +634,24 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id,
union acpi_parse_object
*origin,
union acpi_operand_object
- *mth_desc,
+ *method_desc,
struct acpi_thread_state
*thread)
{
struct acpi_walk_state *walk_state;
acpi_status status;
- ACPI_FUNCTION_TRACE("ds_create_walk_state");
+ ACPI_FUNCTION_TRACE(ds_create_walk_state);
- walk_state = ACPI_MEM_CALLOCATE(sizeof(struct acpi_walk_state));
+ walk_state = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state));
if (!walk_state) {
return_PTR(NULL);
}
- walk_state->data_type = ACPI_DESC_TYPE_WALK;
+ walk_state->descriptor_type = ACPI_DESC_TYPE_WALK;
+ walk_state->method_desc = method_desc;
walk_state->owner_id = owner_id;
walk_state->origin = origin;
- walk_state->method_desc = mth_desc;
walk_state->thread = thread;
walk_state->parser_state.start_op = origin;
@@ -664,7 +666,7 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id,
status = acpi_ds_result_stack_push(walk_state);
if (ACPI_FAILURE(status)) {
- ACPI_MEM_FREE(walk_state);
+ ACPI_FREE(walk_state);
return_PTR(NULL);
}
@@ -701,13 +703,13 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
struct acpi_namespace_node *method_node,
u8 * aml_start,
u32 aml_length,
- struct acpi_parameter_info *info, u8 pass_number)
+ struct acpi_evaluate_info *info, u8 pass_number)
{
acpi_status status;
struct acpi_parse_state *parser_state = &walk_state->parser_state;
union acpi_parse_object *extra_op;
- ACPI_FUNCTION_TRACE("ds_init_aml_walk");
+ ACPI_FUNCTION_TRACE(ds_init_aml_walk);
walk_state->parser_state.aml =
walk_state->parser_state.aml_start = aml_start;
@@ -778,6 +780,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
}
if (parser_state->start_node) {
+
/* Push start scope on scope stack and make it current */
status =
@@ -810,21 +813,24 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state)
{
union acpi_generic_state *state;
- ACPI_FUNCTION_TRACE_PTR("ds_delete_walk_state", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state);
if (!walk_state) {
return;
}
- if (walk_state->data_type != ACPI_DESC_TYPE_WALK) {
+ if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) {
ACPI_ERROR((AE_INFO, "%p is not a valid walk state",
walk_state));
return;
}
+ /* There should not be any open scopes */
+
if (walk_state->parser_state.scope) {
ACPI_ERROR((AE_INFO, "%p walk still has a scope list",
walk_state));
+ acpi_ps_cleanup_scope(&walk_state->parser_state);
}
/* Always must free any linked control states */
@@ -854,7 +860,7 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state)
acpi_ut_delete_generic_state(state);
}
- ACPI_MEM_FREE(walk_state);
+ ACPI_FREE(walk_state);
return_VOID;
}
@@ -879,7 +885,7 @@ acpi_ds_result_insert(void *object,
{
union acpi_generic_state *state;
- ACPI_FUNCTION_NAME("ds_result_insert");
+ ACPI_FUNCTION_NAME(ds_result_insert);
state = walk_state->results;
if (!state) {
@@ -937,7 +943,7 @@ acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state * walk_state)
{
u32 i;
- ACPI_FUNCTION_TRACE_PTR("ds_obj_stack_delete_all", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_delete_all, walk_state);
/* The stack size is configurable, but fixed */
@@ -969,7 +975,7 @@ acpi_status
acpi_ds_obj_stack_pop_object(union acpi_operand_object **object,
struct acpi_walk_state *walk_state)
{
- ACPI_FUNCTION_NAME("ds_obj_stack_pop_object");
+ ACPI_FUNCTION_NAME(ds_obj_stack_pop_object);
/* Check for stack underflow */
@@ -1025,7 +1031,7 @@ acpi_ds_obj_stack_pop_object(union acpi_operand_object **object,
void *acpi_ds_obj_stack_get_value(u32 index, struct acpi_walk_state *walk_state)
{
- ACPI_FUNCTION_TRACE_PTR("ds_obj_stack_get_value", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_get_value, walk_state);
/* Can't do it if the stack is empty */
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 79b09d76c18..c036e2a69f3 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -763,8 +763,7 @@ static u32 acpi_ec_gpe_poll_handler(void *data)
acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
- status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
- acpi_ec_gpe_query, ec);
+ status = acpi_os_execute(OSL_EC_POLL_HANDLER, acpi_ec_gpe_query, ec);
if (status == AE_OK)
return ACPI_INTERRUPT_HANDLED;
@@ -799,7 +798,7 @@ static u32 acpi_ec_gpe_intr_handler(void *data)
if (value & ACPI_EC_FLAG_SCI) {
atomic_add(1, &ec->intr.pending_gpe);
- status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
+ status = acpi_os_execute(OSL_EC_BURST_HANDLER,
acpi_ec_gpe_query, ec);
return status == AE_OK ?
ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
@@ -991,7 +990,6 @@ static int acpi_ec_poll_add(struct acpi_device *device)
int result = 0;
acpi_status status = AE_OK;
union acpi_ec *ec = NULL;
- unsigned long uid;
ACPI_FUNCTION_TRACE("acpi_ec_add");
@@ -1014,10 +1012,9 @@ static int acpi_ec_poll_add(struct acpi_device *device)
acpi_evaluate_integer(ec->common.handle, "_GLK", NULL,
&ec->common.global_lock);
- /* If our UID matches the UID for the ECDT-enumerated EC,
- we now have the *real* EC info, so kill the makeshift one. */
- acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid);
- if (ec_ecdt && ec_ecdt->common.uid == uid) {
+ /* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
+ http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
+ if (ec_ecdt) {
acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler);
@@ -1062,7 +1059,6 @@ static int acpi_ec_intr_add(struct acpi_device *device)
int result = 0;
acpi_status status = AE_OK;
union acpi_ec *ec = NULL;
- unsigned long uid;
ACPI_FUNCTION_TRACE("acpi_ec_add");
@@ -1088,10 +1084,9 @@ static int acpi_ec_intr_add(struct acpi_device *device)
acpi_evaluate_integer(ec->common.handle, "_GLK", NULL,
&ec->common.global_lock);
- /* If our UID matches the UID for the ECDT-enumerated EC,
- we now have the *real* EC info, so kill the makeshift one. */
- acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid);
- if (ec_ecdt && ec_ecdt->common.uid == uid) {
+ /* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
+ http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
+ if (ec_ecdt) {
acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler);
@@ -1572,7 +1567,7 @@ static void __exit acpi_ec_exit(void)
static int __init acpi_fake_ecdt_setup(char *str)
{
acpi_fake_ecdt_enabled = 1;
- return 0;
+ return 1;
}
__setup("acpi_fake_ecdt", acpi_fake_ecdt_setup);
@@ -1591,7 +1586,7 @@ static int __init acpi_ec_set_intr_mode(char *str)
acpi_ec_driver.ops.add = acpi_ec_poll_add;
}
printk(KERN_INFO PREFIX "EC %s mode.\n", intr ? "interrupt" : "polling");
- return 0;
+ return 1;
}
__setup("ec_intr=", acpi_ec_set_intr_mode);
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
index c9ac05c4685..919037d6acf 100644
--- a/drivers/acpi/events/evevent.c
+++ b/drivers/acpi/events/evevent.c
@@ -68,7 +68,7 @@ acpi_status acpi_ev_initialize_events(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_initialize_events");
+ ACPI_FUNCTION_TRACE(ev_initialize_events);
/* Make sure we have ACPI tables */
@@ -118,7 +118,7 @@ acpi_status acpi_ev_install_fadt_gpes(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_install_fadt_gpes");
+ ACPI_FUNCTION_TRACE(ev_install_fadt_gpes);
/* Namespace must be locked */
@@ -157,7 +157,7 @@ acpi_status acpi_ev_install_xrupt_handlers(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_install_xrupt_handlers");
+ ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers);
/* Install the SCI handler */
@@ -241,7 +241,7 @@ u32 acpi_ev_fixed_event_detect(void)
u32 fixed_enable;
acpi_native_uint i;
- ACPI_FUNCTION_NAME("ev_fixed_event_detect");
+ ACPI_FUNCTION_NAME(ev_fixed_event_detect);
/*
* Read the fixed feature status and enable registers, as all the cases
@@ -260,12 +260,14 @@ u32 acpi_ev_fixed_event_detect(void)
* Check for all possible Fixed Events and dispatch those that are active
*/
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
+
/* Both the status and enable bits must be on for this event */
if ((fixed_status & acpi_gbl_fixed_event_info[i].
status_bit_mask)
&& (fixed_enable & acpi_gbl_fixed_event_info[i].
enable_bit_mask)) {
+
/* Found an active (signalled) event */
int_status |= acpi_ev_fixed_event_dispatch((u32) i);
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index f64f977dd3d..f01d339407f 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -69,7 +69,7 @@ acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_set_gpe_type");
+ ACPI_FUNCTION_TRACE(ev_set_gpe_type);
/* Validate type and update register enable masks */
@@ -115,7 +115,7 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
struct acpi_gpe_register_info *gpe_register_info;
u8 register_bit;
- ACPI_FUNCTION_TRACE("ev_update_gpe_enable_masks");
+ ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks);
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
@@ -178,7 +178,7 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_enable_gpe");
+ ACPI_FUNCTION_TRACE(ev_enable_gpe);
/* Make sure HW enable masks are updated */
@@ -207,6 +207,7 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
if (write_to_hardware) {
+
/* Clear the GPE (of stale events), then enable it */
status = acpi_hw_clear_gpe(gpe_event_info);
@@ -243,7 +244,7 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_disable_gpe");
+ ACPI_FUNCTION_TRACE(ev_disable_gpe);
if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) {
return_ACPI_STATUS(AE_OK);
@@ -313,6 +314,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
/* A NULL gpe_block means use the FADT-defined GPE block(s) */
if (!gpe_device) {
+
/* Examine GPE Block 0 and 1 (These blocks are permanent) */
for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
@@ -380,10 +382,11 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
u32 status_reg;
u32 enable_reg;
acpi_cpu_flags flags;
+ acpi_cpu_flags hw_flags;
acpi_native_uint i;
acpi_native_uint j;
- ACPI_FUNCTION_NAME("ev_gpe_detect");
+ ACPI_FUNCTION_NAME(ev_gpe_detect);
/* Check for the case where there are no GPEs */
@@ -391,9 +394,12 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
return (int_status);
}
- /* Examine all GPE blocks attached to this interrupt level */
+ /* We need to hold the GPE lock now, hardware lock in the loop */
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+ /* Examine all GPE blocks attached to this interrupt level */
+
gpe_block = gpe_xrupt_list->gpe_block_list_head;
while (gpe_block) {
/*
@@ -402,10 +408,13 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
* Find all currently active GP events.
*/
for (i = 0; i < gpe_block->register_count; i++) {
+
/* Get the next status/enable pair */
gpe_register_info = &gpe_block->register_info[i];
+ hw_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
+
/* Read the Status Register */
status =
@@ -414,6 +423,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
&gpe_register_info->
status_address);
if (ACPI_FAILURE(status)) {
+ acpi_os_release_lock(acpi_gbl_hardware_lock,
+ hw_flags);
goto unlock_and_exit;
}
@@ -424,6 +435,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
&enable_reg,
&gpe_register_info->
enable_address);
+ acpi_os_release_lock(acpi_gbl_hardware_lock, hw_flags);
+
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@@ -437,6 +450,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
enabled_status_byte = (u8) (status_reg & enable_reg);
if (!enabled_status_byte) {
+
/* No active GPEs in this register, move on */
continue;
@@ -445,6 +459,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
/* Now look at the individual GPEs in this byte register */
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
+
/* Examine one GPE bit */
if (enabled_status_byte &
@@ -483,9 +498,9 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
*
* RETURN: None
*
- * DESCRIPTION: Perform the actual execution of a GPE control method. This
- * function is called from an invocation of acpi_os_queue_for_execution
- * (and therefore does NOT execute at interrupt level) so that
+ * DESCRIPTION: Perform the actual execution of a GPE control method. This
+ * function is called from an invocation of acpi_os_execute and
+ * therefore does NOT execute at interrupt level - so that
* the control method itself is not executed in the context of
* an interrupt handler.
*
@@ -494,12 +509,11 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
{
struct acpi_gpe_event_info *gpe_event_info = (void *)context;
- u32 gpe_number = 0;
acpi_status status;
struct acpi_gpe_event_info local_gpe_event_info;
- struct acpi_parameter_info info;
+ struct acpi_evaluate_info *info;
- ACPI_FUNCTION_TRACE("ev_asynch_execute_gpe_method");
+ ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
@@ -535,22 +549,35 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
*/
if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) ==
ACPI_GPE_DISPATCH_METHOD) {
- /*
- * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
- * control method that corresponds to this GPE
- */
- info.node = local_gpe_event_info.dispatch.method_node;
- info.parameters =
- ACPI_CAST_PTR(union acpi_operand_object *, gpe_event_info);
- info.parameter_type = ACPI_PARAM_GPE;
- status = acpi_ns_evaluate_by_handle(&info);
+ /* Allocate the evaluation information block */
+
+ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+ if (!info) {
+ status = AE_NO_MEMORY;
+ } else {
+ /*
+ * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
+ * control method that corresponds to this GPE
+ */
+ info->prefix_node =
+ local_gpe_event_info.dispatch.method_node;
+ info->parameters =
+ ACPI_CAST_PTR(union acpi_operand_object *,
+ gpe_event_info);
+ info->parameter_type = ACPI_PARAM_GPE;
+ info->flags = ACPI_IGNORE_RETURN_VALUE;
+
+ status = acpi_ns_evaluate(info);
+ ACPI_FREE(info);
+ }
+
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
- "While evaluating method [%4.4s] for GPE[%2X]",
+ "While evaluating GPE method [%4.4s]",
acpi_ut_get_node_name
(local_gpe_event_info.dispatch.
- method_node), gpe_number));
+ method_node)));
}
}
@@ -593,7 +620,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_gpe_dispatch");
+ ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
/*
* If edge-triggered, clear the GPE status bit now. Note that
@@ -669,9 +696,9 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
* Execute the method associated with the GPE
* NOTE: Level-triggered GPEs are cleared after the method completes.
*/
- status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
- acpi_ev_asynch_execute_gpe_method,
- gpe_event_info);
+ status = acpi_os_execute(OSL_GPE_HANDLER,
+ acpi_ev_asynch_execute_gpe_method,
+ gpe_event_info);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to queue handler for GPE[%2X] - event disabled",
@@ -716,7 +743,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
*
* DESCRIPTION: Determine if a a GPE is "wake-only".
*
- * Called from Notify() code in interpreter when a "device_wake"
+ * Called from Notify() code in interpreter when a "DeviceWake"
* Notify comes in.
*
******************************************************************************/
@@ -726,7 +753,7 @@ acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_check_for_wake_only_gpe");
+ ACPI_FUNCTION_TRACE(ev_check_for_wake_only_gpe);
if ((gpe_event_info) && /* Only >0 for _Lxx/_Exx */
((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) { /* System state at GPE time */
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
index 0fd00b5ad65..95ddeb48bc0 100644
--- a/drivers/acpi/events/evgpeblk.c
+++ b/drivers/acpi/events/evgpeblk.c
@@ -131,14 +131,14 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info)
*
******************************************************************************/
-acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback)
+acpi_status acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback)
{
struct acpi_gpe_block_info *gpe_block;
struct acpi_gpe_xrupt_info *gpe_xrupt_info;
acpi_status status = AE_OK;
acpi_cpu_flags flags;
- ACPI_FUNCTION_TRACE("ev_walk_gpe_list");
+ ACPI_FUNCTION_TRACE(ev_walk_gpe_list);
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
@@ -146,10 +146,12 @@ acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback)
gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
while (gpe_xrupt_info) {
+
/* Walk all Gpe Blocks attached to this interrupt level */
gpe_block = gpe_xrupt_info->gpe_block_list_head;
while (gpe_block) {
+
/* One callback per GPE block */
status = gpe_walk_callback(gpe_xrupt_info, gpe_block);
@@ -190,11 +192,12 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
acpi_native_uint i;
acpi_native_uint j;
- ACPI_FUNCTION_TRACE("ev_delete_gpe_handlers");
+ ACPI_FUNCTION_TRACE(ev_delete_gpe_handlers);
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
+
/* Now look at the individual GPEs in this byte register */
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
@@ -204,7 +207,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
ACPI_GPE_DISPATCH_HANDLER) {
- ACPI_MEM_FREE(gpe_event_info->dispatch.handler);
+ ACPI_FREE(gpe_event_info->dispatch.handler);
gpe_event_info->dispatch.handler = NULL;
gpe_event_info->flags &=
~ACPI_GPE_DISPATCH_MASK;
@@ -248,7 +251,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
u8 type;
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_save_method_info");
+ ACPI_FUNCTION_TRACE(ev_save_method_info);
/*
* _Lxx and _Exx GPE method support
@@ -279,9 +282,9 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
default:
/* Unknown method type, just ignore it! */
- ACPI_ERROR((AE_INFO,
- "Unknown GPE method type: %s (name not of form _Lxx or _Exx)",
- name));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+ "Ignoring unknown GPE method type: %s (name not of form _Lxx or _Exx)",
+ name));
return_ACPI_STATUS(AE_OK);
}
@@ -289,11 +292,12 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
gpe_number = ACPI_STRTOUL(&name[2], NULL, 16);
if (gpe_number == ACPI_UINT32_MAX) {
+
/* Conversion failed; invalid method, just ignore it */
- ACPI_ERROR((AE_INFO,
- "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)",
- name));
+ ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+ "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)",
+ name));
return_ACPI_STATUS(AE_OK);
}
@@ -364,13 +368,14 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
u32 gpe_number;
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_match_prw_and_gpe");
+ ACPI_FUNCTION_TRACE(ev_match_prw_and_gpe);
/* Check for a _PRW method under this device */
status = acpi_ut_evaluate_object(obj_handle, METHOD_NAME__PRW,
ACPI_BTYPE_PACKAGE, &pkg_desc);
if (ACPI_FAILURE(status)) {
+
/* Ignore all errors from _PRW, we don't want to abort the subsystem */
return_ACPI_STATUS(AE_OK);
@@ -394,6 +399,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
obj_desc = pkg_desc->package.elements[0];
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
+
/* Use FADT-defined GPE device (from definition of _PRW) */
target_gpe_device = acpi_gbl_fadt_gpe_device;
@@ -402,6 +408,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
gpe_number = (u32) obj_desc->integer.value;
} else if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
+
/* Package contains a GPE reference and GPE number within a GPE block */
if ((obj_desc->package.count < 2) ||
@@ -482,7 +489,7 @@ static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32
acpi_status status;
acpi_cpu_flags flags;
- ACPI_FUNCTION_TRACE("ev_get_gpe_xrupt_block");
+ ACPI_FUNCTION_TRACE(ev_get_gpe_xrupt_block);
/* No need for lock since we are not changing any list elements here */
@@ -497,7 +504,7 @@ static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32
/* Not found, must allocate a new xrupt descriptor */
- gpe_xrupt = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_xrupt_info));
+ gpe_xrupt = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_xrupt_info));
if (!gpe_xrupt) {
return_PTR(NULL);
}
@@ -556,7 +563,7 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt)
acpi_status status;
acpi_cpu_flags flags;
- ACPI_FUNCTION_TRACE("ev_delete_gpe_xrupt");
+ ACPI_FUNCTION_TRACE(ev_delete_gpe_xrupt);
/* We never want to remove the SCI interrupt handler */
@@ -588,7 +595,7 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt)
/* Free the block */
- ACPI_MEM_FREE(gpe_xrupt);
+ ACPI_FREE(gpe_xrupt);
return_ACPI_STATUS(AE_OK);
}
@@ -614,7 +621,7 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
acpi_status status;
acpi_cpu_flags flags;
- ACPI_FUNCTION_TRACE("ev_install_gpe_block");
+ ACPI_FUNCTION_TRACE(ev_install_gpe_block);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
@@ -667,7 +674,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
acpi_status status;
acpi_cpu_flags flags;
- ACPI_FUNCTION_TRACE("ev_install_gpe_block");
+ ACPI_FUNCTION_TRACE(ev_install_gpe_block);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
@@ -679,6 +686,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
status = acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block);
if (!gpe_block->previous && !gpe_block->next) {
+
/* This is the last gpe_block on this interrupt */
status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block);
@@ -704,9 +712,9 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
/* Free the gpe_block */
- ACPI_MEM_FREE(gpe_block->register_info);
- ACPI_MEM_FREE(gpe_block->event_info);
- ACPI_MEM_FREE(gpe_block);
+ ACPI_FREE(gpe_block->register_info);
+ ACPI_FREE(gpe_block->event_info);
+ ACPI_FREE(gpe_block);
unlock_and_exit:
status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
@@ -736,17 +744,17 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
acpi_native_uint j;
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_create_gpe_info_blocks");
+ ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks);
/* Allocate the GPE register information block */
- gpe_register_info = ACPI_MEM_CALLOCATE((acpi_size) gpe_block->
- register_count *
- sizeof(struct
- acpi_gpe_register_info));
+ gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block->
+ register_count *
+ sizeof(struct
+ acpi_gpe_register_info));
if (!gpe_register_info) {
ACPI_ERROR((AE_INFO,
- "Could not allocate the gpe_register_info table"));
+ "Could not allocate the GpeRegisterInfo table"));
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -754,13 +762,14 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
* Allocate the GPE event_info block. There are eight distinct GPEs
* per register. Initialization to zeros is sufficient.
*/
- gpe_event_info = ACPI_MEM_CALLOCATE(((acpi_size) gpe_block->
- register_count *
- ACPI_GPE_REGISTER_WIDTH) *
- sizeof(struct acpi_gpe_event_info));
+ gpe_event_info = ACPI_ALLOCATE_ZEROED(((acpi_size) gpe_block->
+ register_count *
+ ACPI_GPE_REGISTER_WIDTH) *
+ sizeof(struct
+ acpi_gpe_event_info));
if (!gpe_event_info) {
ACPI_ERROR((AE_INFO,
- "Could not allocate the gpe_event_info table"));
+ "Could not allocate the GpeEventInfo table"));
status = AE_NO_MEMORY;
goto error_exit;
}
@@ -780,6 +789,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
this_event = gpe_event_info;
for (i = 0; i < gpe_block->register_count; i++) {
+
/* Init the register_info for this GPE register (8 GPEs) */
this_register->base_gpe_number =
@@ -839,10 +849,10 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
error_exit:
if (gpe_register_info) {
- ACPI_MEM_FREE(gpe_register_info);
+ ACPI_FREE(gpe_register_info);
}
if (gpe_event_info) {
- ACPI_MEM_FREE(gpe_event_info);
+ ACPI_FREE(gpe_event_info);
}
return_ACPI_STATUS(status);
@@ -878,7 +888,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
acpi_status status;
struct acpi_gpe_block_info *gpe_block;
- ACPI_FUNCTION_TRACE("ev_create_gpe_block");
+ ACPI_FUNCTION_TRACE(ev_create_gpe_block);
if (!register_count) {
return_ACPI_STATUS(AE_OK);
@@ -886,7 +896,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
/* Allocate a new GPE block */
- gpe_block = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_block_info));
+ gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info));
if (!gpe_block) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -906,7 +916,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
*/
status = acpi_ev_create_gpe_info_blocks(gpe_block);
if (ACPI_FAILURE(status)) {
- ACPI_MEM_FREE(gpe_block);
+ ACPI_FREE(gpe_block);
return_ACPI_STATUS(status);
}
@@ -914,7 +924,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
if (ACPI_FAILURE(status)) {
- ACPI_MEM_FREE(gpe_block);
+ ACPI_FREE(gpe_block);
return_ACPI_STATUS(status);
}
@@ -971,7 +981,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
acpi_native_uint i;
acpi_native_uint j;
- ACPI_FUNCTION_TRACE("ev_initialize_gpe_block");
+ ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
/* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
@@ -1013,6 +1023,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
for (i = 0; i < gpe_block->register_count; i++) {
for (j = 0; j < 8; j++) {
+
/* Get the info block for this particular GPE */
gpe_event_info =
@@ -1040,7 +1051,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block);
if (ACPI_FAILURE(status)) {
- ACPI_ERROR((AE_INFO, "Could not enable GPEs in gpe_block %p",
+ ACPI_ERROR((AE_INFO, "Could not enable GPEs in GpeBlock %p",
gpe_block));
}
@@ -1066,7 +1077,7 @@ acpi_status acpi_ev_gpe_initialize(void)
u32 gpe_number_max = 0;
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_gpe_initialize");
+ ACPI_FUNCTION_TRACE(ev_gpe_initialize);
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
@@ -1099,6 +1110,7 @@ acpi_status acpi_ev_gpe_initialize(void)
* particular block is not supported.
*/
if (acpi_gbl_FADT->gpe0_blk_len && acpi_gbl_FADT->xgpe0_blk.address) {
+
/* GPE block 0 exists (has both length and address > 0) */
register_count0 = (u16) (acpi_gbl_FADT->gpe0_blk_len / 2);
@@ -1121,6 +1133,7 @@ acpi_status acpi_ev_gpe_initialize(void)
}
if (acpi_gbl_FADT->gpe1_blk_len && acpi_gbl_FADT->xgpe1_blk.address) {
+
/* GPE block 1 exists (has both length and address > 0) */
register_count1 = (u16) (acpi_gbl_FADT->gpe1_blk_len / 2);
@@ -1168,6 +1181,7 @@ acpi_status acpi_ev_gpe_initialize(void)
/* Exit if there are no GPE registers */
if ((register_count0 + register_count1) == 0) {
+
/* GPEs are not required by ACPI, this is OK */
ACPI_DEBUG_PRINT((ACPI_DB_INIT,
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index 0909ba69577..6eef4efddcf 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -49,12 +49,13 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evmisc")
+/* Names for Notify() values, used for debug output */
#ifdef ACPI_DEBUG_OUTPUT
static const char *acpi_notify_value_names[] = {
"Bus Check",
"Device Check",
"Device Wake",
- "Eject request",
+ "Eject Request",
"Device Check Light",
"Frequency Mismatch",
"Bus Mode Mismatch",
@@ -124,7 +125,7 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
union acpi_generic_state *notify_info;
acpi_status status = AE_OK;
- ACPI_FUNCTION_NAME("ev_queue_notify_request");
+ ACPI_FUNCTION_NAME(ev_queue_notify_request);
/*
* For value 3 (Ejection Request), some device method may need to be run.
@@ -150,6 +151,7 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
+
/* We have the notify object, Get the right handler */
switch (node->type) {
@@ -184,14 +186,15 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
return (AE_NO_MEMORY);
}
- notify_info->common.data_type = ACPI_DESC_TYPE_STATE_NOTIFY;
+ notify_info->common.descriptor_type =
+ ACPI_DESC_TYPE_STATE_NOTIFY;
notify_info->notify.node = node;
notify_info->notify.value = (u16) notify_value;
notify_info->notify.handler_obj = handler_obj;
- status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH,
- acpi_ev_notify_dispatch,
- notify_info);
+ status =
+ acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
+ notify_info);
if (ACPI_FAILURE(status)) {
acpi_ut_delete_generic_state(notify_info);
}
@@ -240,6 +243,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
* to the device.
*/
if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) {
+
/* Global system notification handler */
if (acpi_gbl_system_notify.handler) {
@@ -297,6 +301,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context)
/* Signal threads that are waiting for the lock */
if (acpi_gbl_global_lock_thread_count) {
+
/* Send sufficient units to the semaphore */
status =
@@ -335,15 +340,16 @@ static u32 acpi_ev_global_lock_handler(void *context)
*/
ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
if (acquired) {
+
/* Got the lock, now wake all threads waiting for it */
acpi_gbl_global_lock_acquired = TRUE;
/* Run the Global Lock thread which will signal all waiting threads */
- status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH,
- acpi_ev_global_lock_thread,
- context);
+ status =
+ acpi_os_execute(OSL_GLOBAL_LOCK_HANDLER,
+ acpi_ev_global_lock_thread, context);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not queue Global Lock thread"));
@@ -371,7 +377,7 @@ acpi_status acpi_ev_init_global_lock_handler(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_init_global_lock_handler");
+ ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);
acpi_gbl_global_lock_present = TRUE;
status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
@@ -413,7 +419,7 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
acpi_status status = AE_OK;
u8 acquired = FALSE;
- ACPI_FUNCTION_TRACE("ev_acquire_global_lock");
+ ACPI_FUNCTION_TRACE(ev_acquire_global_lock);
#ifndef ACPI_APPLICATION
/* Make sure that we actually have a global lock */
@@ -439,6 +445,7 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
if (acquired) {
+
/* We got the lock */
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -458,8 +465,9 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
* Acquire the global lock semaphore first.
* Since this wait will block, we must release the interpreter
*/
- status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
- timeout);
+ status =
+ acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
+ timeout);
return_ACPI_STATUS(status);
}
@@ -480,7 +488,7 @@ acpi_status acpi_ev_release_global_lock(void)
u8 pending = FALSE;
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ev_release_global_lock");
+ ACPI_FUNCTION_TRACE(ev_release_global_lock);
if (!acpi_gbl_global_lock_thread_count) {
ACPI_WARNING((AE_INFO,
@@ -492,6 +500,7 @@ acpi_status acpi_ev_release_global_lock(void)
acpi_gbl_global_lock_thread_count--;
if (acpi_gbl_global_lock_thread_count) {
+
/* There are still some threads holding the lock, cannot release */
return_ACPI_STATUS(AE_OK);
@@ -533,7 +542,7 @@ void acpi_ev_terminate(void)
acpi_native_uint i;
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_terminate");
+ ACPI_FUNCTION_TRACE(ev_terminate);
if (acpi_gbl_events_initialized) {
/*
@@ -573,7 +582,7 @@ void acpi_ev_terminate(void)
if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
status = acpi_disable();
if (ACPI_FAILURE(status)) {
- ACPI_WARNING((AE_INFO, "acpi_disable failed"));
+ ACPI_WARNING((AE_INFO, "AcpiDisable failed"));
}
}
return_VOID;
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index 6da58e77641..094a17e4c86 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/events/evregion.c
@@ -83,7 +83,7 @@ acpi_status acpi_ev_install_region_handlers(void)
acpi_status status;
acpi_native_uint i;
- ACPI_FUNCTION_TRACE("ev_install_region_handlers");
+ ACPI_FUNCTION_TRACE(ev_install_region_handlers);
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
@@ -153,7 +153,7 @@ acpi_status acpi_ev_initialize_op_regions(void)
acpi_status status;
acpi_native_uint i;
- ACPI_FUNCTION_TRACE("ev_initialize_op_regions");
+ ACPI_FUNCTION_TRACE(ev_initialize_op_regions);
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
@@ -164,6 +164,7 @@ acpi_status acpi_ev_initialize_op_regions(void)
* Run the _REG methods for op_regions in each default address space
*/
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
+
/* TBD: Make sure handler is the DEFAULT handler, otherwise
* _REG will have already been run.
*/
@@ -192,12 +193,12 @@ acpi_status acpi_ev_initialize_op_regions(void)
acpi_status
acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
{
- struct acpi_parameter_info info;
- union acpi_operand_object *params[3];
+ struct acpi_evaluate_info *info;
+ union acpi_operand_object *args[3];
union acpi_operand_object *region_obj2;
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_execute_reg_method");
+ ACPI_FUNCTION_TRACE(ev_execute_reg_method);
region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
@@ -208,48 +209,60 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
return_ACPI_STATUS(AE_OK);
}
+ /* Allocate and initialize the evaluation information block */
+
+ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+ if (!info) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ info->prefix_node = region_obj2->extra.method_REG;
+ info->pathname = NULL;
+ info->parameters = args;
+ info->parameter_type = ACPI_PARAM_ARGS;
+ info->flags = ACPI_IGNORE_RETURN_VALUE;
+
/*
* The _REG method has two arguments:
*
- * Arg0, Integer: Operation region space ID
- * Same value as region_obj->Region.space_id
- * Arg1, Integer: connection status
- * 1 for connecting the handler,
- * 0 for disconnecting the handler
- * Passed as a parameter
+ * Arg0 - Integer:
+ * Operation region space ID Same value as region_obj->Region.space_id
+ *
+ * Arg1 - Integer:
+ * connection status 1 for connecting the handler, 0 for disconnecting
+ * the handler (Passed as a parameter)
*/
- params[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
- if (!params[0]) {
- return_ACPI_STATUS(AE_NO_MEMORY);
+ args[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ if (!args[0]) {
+ status = AE_NO_MEMORY;
+ goto cleanup1;
}
- params[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
- if (!params[1]) {
+ args[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ if (!args[1]) {
status = AE_NO_MEMORY;
- goto cleanup;
+ goto cleanup2;
}
/* Setup the parameter objects */
- params[0]->integer.value = region_obj->region.space_id;
- params[1]->integer.value = function;
- params[2] = NULL;
-
- info.node = region_obj2->extra.method_REG;
- info.parameters = params;
- info.parameter_type = ACPI_PARAM_ARGS;
+ args[0]->integer.value = region_obj->region.space_id;
+ args[1]->integer.value = function;
+ args[2] = NULL;
/* Execute the method, no return value */
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
- (ACPI_TYPE_METHOD, info.node, NULL));
- status = acpi_ns_evaluate_by_handle(&info);
+ (ACPI_TYPE_METHOD, info->prefix_node, NULL));
- acpi_ut_remove_reference(params[1]);
+ status = acpi_ns_evaluate(info);
+ acpi_ut_remove_reference(args[1]);
- cleanup:
- acpi_ut_remove_reference(params[0]);
+ cleanup2:
+ acpi_ut_remove_reference(args[0]);
+ cleanup1:
+ ACPI_FREE(info);
return_ACPI_STATUS(status);
}
@@ -261,7 +274,8 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
* Function - Read or Write operation
* Address - Where in the space to read or write
* bit_width - Field width in bits (8, 16, 32, or 64)
- * Value - Pointer to in or out value
+ * Value - Pointer to in or out value, must be
+ * full 64-bit acpi_integer
*
* RETURN: Status
*
@@ -274,7 +288,7 @@ acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
u32 function,
acpi_physical_address address,
- u32 bit_width, void *value)
+ u32 bit_width, acpi_integer * value)
{
acpi_status status;
acpi_status status2;
@@ -284,7 +298,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
union acpi_operand_object *region_obj2;
void *region_context = NULL;
- ACPI_FUNCTION_TRACE("ev_address_space_dispatch");
+ ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
@@ -315,6 +329,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
*/
region_setup = handler_desc->address_space.setup;
if (!region_setup) {
+
/* No initialization routine, exit with error */
ACPI_ERROR((AE_INFO,
@@ -361,9 +376,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
if (region_obj2->extra.region_context) {
+
/* The handler for this region was already installed */
- ACPI_MEM_FREE(region_context);
+ ACPI_FREE(region_context);
} else {
/*
* Save the returned context for use in all accesses to
@@ -386,9 +402,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
acpi_ut_get_region_name(region_obj->region.
space_id)));
- if (!
- (handler_desc->address_space.
- hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+ if (!(handler_desc->address_space.handler_flags &
+ ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* For handlers other than the default (supplied) handlers, we must
* exit the interpreter because the handler *might* block -- we don't
@@ -409,9 +424,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
space_id)));
}
- if (!
- (handler_desc->address_space.
- hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+ if (!(handler_desc->address_space.handler_flags &
+ ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* We just returned from a non-default handler, we must re-enter the
* interpreter
@@ -451,7 +465,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
union acpi_operand_object *region_obj2;
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_detach_region");
+ ACPI_FUNCTION_TRACE(ev_detach_region);
region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
@@ -463,6 +477,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
handler_obj = region_obj->region.handler;
if (!handler_obj) {
+
/* This region has no handler, all done */
return_VOID;
@@ -474,6 +489,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
last_obj_ptr = &handler_obj->address_space.region_list;
while (obj_desc) {
+
/* Is this the correct Region? */
if (obj_desc == region_obj) {
@@ -583,7 +599,7 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj,
u8 acpi_ns_is_locked)
{
- ACPI_FUNCTION_TRACE("ev_attach_region");
+ ACPI_FUNCTION_TRACE(ev_attach_region);
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Adding Region [%4.4s] %p to address handler %p [%s]\n",
@@ -636,7 +652,7 @@ acpi_ev_install_handler(acpi_handle obj_handle,
struct acpi_namespace_node *node;
acpi_status status;
- ACPI_FUNCTION_NAME("ev_install_handler");
+ ACPI_FUNCTION_NAME(ev_install_handler);
handler_obj = (union acpi_operand_object *)context;
@@ -666,6 +682,7 @@ acpi_ev_install_handler(acpi_handle obj_handle,
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
+
/* No object, just exit */
return (AE_OK);
@@ -674,10 +691,12 @@ acpi_ev_install_handler(acpi_handle obj_handle,
/* Devices are handled different than regions */
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) {
+
/* Check if this Device already has a handler for this address space */
next_handler_obj = obj_desc->device.handler;
while (next_handler_obj) {
+
/* Found a handler, is it for the same address space? */
if (next_handler_obj->address_space.space_id ==
@@ -764,9 +783,9 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
union acpi_operand_object *handler_obj;
acpi_status status;
acpi_object_type type;
- u16 flags = 0;
+ u8 flags = 0;
- ACPI_FUNCTION_TRACE("ev_install_space_handler");
+ ACPI_FUNCTION_TRACE(ev_install_space_handler);
/*
* This registration is valid for only the types below
@@ -839,6 +858,7 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
/* Walk the handler list for this device */
while (handler_obj) {
+
/* Same space_id indicates a handler already installed */
if (handler_obj->address_space.space_id == space_id) {
@@ -921,7 +941,7 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
/* Init handler obj */
handler_obj->address_space.space_id = (u8) space_id;
- handler_obj->address_space.hflags = flags;
+ handler_obj->address_space.handler_flags = flags;
handler_obj->address_space.region_list = NULL;
handler_obj->address_space.node = node;
handler_obj->address_space.handler = handler;
@@ -979,7 +999,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_execute_reg_methods");
+ ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
/*
* Run all _REG methods for all Operation Regions for this
@@ -1001,7 +1021,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
*
* PARAMETERS: walk_namespace callback
*
- * DESCRIPTION: Run _REg method for region objects of the requested space_iD
+ * DESCRIPTION: Run _REG method for region objects of the requested space_iD
*
******************************************************************************/
@@ -1035,6 +1055,7 @@ acpi_ev_reg_run(acpi_handle obj_handle,
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
+
/* No object, just exit */
return (AE_OK);
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
index baed8c1a1b9..5b3c7a85eb9 100644
--- a/drivers/acpi/events/evrgnini.c
+++ b/drivers/acpi/events/evrgnini.c
@@ -71,11 +71,22 @@ acpi_ev_system_memory_region_setup(acpi_handle handle,
(union acpi_operand_object *)handle;
struct acpi_mem_space_context *local_region_context;
- ACPI_FUNCTION_TRACE("ev_system_memory_region_setup");
+ ACPI_FUNCTION_TRACE(ev_system_memory_region_setup);
if (function == ACPI_REGION_DEACTIVATE) {
if (*region_context) {
- ACPI_MEM_FREE(*region_context);
+ local_region_context =
+ (struct acpi_mem_space_context *)*region_context;
+
+ /* Delete a cached mapping if present */
+
+ if (local_region_context->mapped_length) {
+ acpi_os_unmap_memory(local_region_context->
+ mapped_logical_address,
+ local_region_context->
+ mapped_length);
+ }
+ ACPI_FREE(local_region_context);
*region_context = NULL;
}
return_ACPI_STATUS(AE_OK);
@@ -84,7 +95,7 @@ acpi_ev_system_memory_region_setup(acpi_handle handle,
/* Create a new context */
local_region_context =
- ACPI_MEM_CALLOCATE(sizeof(struct acpi_mem_space_context));
+ ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context));
if (!(local_region_context)) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -118,7 +129,7 @@ acpi_ev_io_space_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context)
{
- ACPI_FUNCTION_TRACE("ev_io_space_region_setup");
+ ACPI_FUNCTION_TRACE(ev_io_space_region_setup);
if (function == ACPI_REGION_DEACTIVATE) {
*region_context = NULL;
@@ -161,7 +172,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
(union acpi_operand_object *)handle;
struct acpi_device_id object_hID;
- ACPI_FUNCTION_TRACE("ev_pci_config_region_setup");
+ ACPI_FUNCTION_TRACE(ev_pci_config_region_setup);
handler_obj = region_obj->region.handler;
if (!handler_obj) {
@@ -178,7 +189,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
*region_context = NULL;
if (function == ACPI_REGION_DEACTIVATE) {
if (pci_id) {
- ACPI_MEM_FREE(pci_id);
+ ACPI_FREE(pci_id);
}
return_ACPI_STATUS(status);
}
@@ -199,6 +210,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
* handlers with that device.
*/
if (handler_obj->address_space.node == acpi_gbl_root_node) {
+
/* Start search from the parent object */
pci_root_node = parent_node;
@@ -220,6 +232,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
PCI_EXPRESS_ROOT_HID_STRING,
sizeof(PCI_EXPRESS_ROOT_HID_STRING)))))
{
+
/* Install a handler for this PCI root bridge */
status =
@@ -235,7 +248,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
} else {
ACPI_EXCEPTION((AE_INFO,
status,
- "Could not install pci_config handler for Root Bridge %4.4s",
+ "Could not install PciConfig handler for Root Bridge %4.4s",
acpi_ut_get_node_name
(pci_root_node)));
}
@@ -262,7 +275,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
/* Region is still not initialized. Create a new context */
- pci_id = ACPI_MEM_CALLOCATE(sizeof(struct acpi_pci_id));
+ pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id));
if (!pci_id) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -337,7 +350,7 @@ acpi_ev_pci_bar_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context)
{
- ACPI_FUNCTION_TRACE("ev_pci_bar_region_setup");
+ ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup);
return_ACPI_STATUS(AE_OK);
}
@@ -364,7 +377,7 @@ acpi_ev_cmos_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context)
{
- ACPI_FUNCTION_TRACE("ev_cmos_region_setup");
+ ACPI_FUNCTION_TRACE(ev_cmos_region_setup);
return_ACPI_STATUS(AE_OK);
}
@@ -389,7 +402,7 @@ acpi_ev_default_region_setup(acpi_handle handle,
u32 function,
void *handler_context, void **region_context)
{
- ACPI_FUNCTION_TRACE("ev_default_region_setup");
+ ACPI_FUNCTION_TRACE(ev_default_region_setup);
if (function == ACPI_REGION_DEACTIVATE) {
*region_context = NULL;
@@ -435,7 +448,7 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
union acpi_operand_object *region_obj2;
- ACPI_FUNCTION_TRACE_U32("ev_initialize_region", acpi_ns_locked);
+ ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked);
if (!region_obj) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -462,8 +475,9 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
/* Find any "_REG" method associated with this region definition */
- status = acpi_ns_search_node(*reg_name_ptr, node,
- ACPI_TYPE_METHOD, &method_node);
+ status =
+ acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,
+ &method_node);
if (ACPI_SUCCESS(status)) {
/*
* The _REG method is optional and there can be only one per region
@@ -478,11 +492,13 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
* ie: acpi_gbl_root_node->parent_entry being set to NULL
*/
while (node) {
+
/* Check to see if a handler exists */
handler_obj = NULL;
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
+
/* Can only be a handler if the object exists */
switch (node->type) {
@@ -507,10 +523,12 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
}
while (handler_obj) {
+
/* Is this handler of the correct type? */
if (handler_obj->address_space.space_id ==
space_id) {
+
/* Found correct handler */
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
@@ -571,7 +589,7 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
/* If we get here, there is no handler for this region */
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
- "No handler for region_type %s(%X) (region_obj %p)\n",
+ "No handler for RegionType %s(%X) (RegionObj %p)\n",
acpi_ut_get_region_name(space_id), space_id,
region_obj));
diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c
index 9a622169008..8106215ad55 100644
--- a/drivers/acpi/events/evsci.c
+++ b/drivers/acpi/events/evsci.c
@@ -69,7 +69,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
- ACPI_FUNCTION_TRACE("ev_sci_xrupt_handler");
+ ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler);
/*
* We are guaranteed by the ACPI CA initialization/shutdown code that
@@ -108,7 +108,7 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
- ACPI_FUNCTION_TRACE("ev_gpe_xrupt_handler");
+ ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler);
/*
* We are guaranteed by the ACPI CA initialization/shutdown code that
@@ -140,7 +140,7 @@ u32 acpi_ev_install_sci_handler(void)
{
u32 status = AE_OK;
- ACPI_FUNCTION_TRACE("ev_install_sci_handler");
+ ACPI_FUNCTION_TRACE(ev_install_sci_handler);
status = acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT->sci_int,
acpi_ev_sci_xrupt_handler,
@@ -171,7 +171,7 @@ acpi_status acpi_ev_remove_sci_handler(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ev_remove_sci_handler");
+ ACPI_FUNCTION_TRACE(ev_remove_sci_handler);
/* Just let the OS remove the handler and disable the level */
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index b38b39dde54..76c34a66e0e 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -41,8 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
@@ -68,7 +66,7 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_install_exception_handler");
+ ACPI_FUNCTION_TRACE(acpi_install_exception_handler);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
@@ -90,6 +88,8 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
+
+ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
@@ -107,14 +107,13 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
* event.
*
******************************************************************************/
-
acpi_status
acpi_install_fixed_event_handler(u32 event,
acpi_event_handler handler, void *context)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_install_fixed_event_handler");
+ ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);
/* Parameter validation */
@@ -161,7 +160,7 @@ acpi_install_fixed_event_handler(u32 event,
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_fixed_event_handler);
+ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)
/*******************************************************************************
*
@@ -175,13 +174,12 @@ EXPORT_SYMBOL(acpi_install_fixed_event_handler);
* DESCRIPTION: Disables the event and unregisters the event handler.
*
******************************************************************************/
-
acpi_status
acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("acpi_remove_fixed_event_handler");
+ ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);
/* Parameter validation */
@@ -216,7 +214,7 @@ acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
+ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)
/*******************************************************************************
*
@@ -235,7 +233,6 @@ EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
* DESCRIPTION: Install a handler for notifies on an ACPI device
*
******************************************************************************/
-
acpi_status
acpi_install_notify_handler(acpi_handle device,
u32 handler_type,
@@ -246,7 +243,7 @@ acpi_install_notify_handler(acpi_handle device,
struct acpi_namespace_node *node;
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_install_notify_handler");
+ ACPI_FUNCTION_TRACE(acpi_install_notify_handler);
/* Parameter validation */
@@ -275,6 +272,7 @@ acpi_install_notify_handler(acpi_handle device,
* only one <external> global handler can be regsitered (per notify type).
*/
if (device == ACPI_ROOT_OBJECT) {
+
/* Make sure the handler is not already installed */
if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
@@ -317,6 +315,7 @@ acpi_install_notify_handler(acpi_handle device,
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
+
/* Object exists - make sure there's no handler */
if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
@@ -370,6 +369,7 @@ acpi_install_notify_handler(acpi_handle device,
}
if (handler_type == ACPI_ALL_NOTIFY) {
+
/* Extra ref if installed in both */
acpi_ut_add_reference(notify_obj);
@@ -381,7 +381,7 @@ acpi_install_notify_handler(acpi_handle device,
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_notify_handler);
+ACPI_EXPORT_SYMBOL(acpi_install_notify_handler)
/*******************************************************************************
*
@@ -399,7 +399,6 @@ EXPORT_SYMBOL(acpi_install_notify_handler);
* DESCRIPTION: Remove a handler for notifies on an ACPI device
*
******************************************************************************/
-
acpi_status
acpi_remove_notify_handler(acpi_handle device,
u32 handler_type, acpi_notify_handler handler)
@@ -409,7 +408,7 @@ acpi_remove_notify_handler(acpi_handle device,
struct acpi_namespace_node *node;
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_remove_notify_handler");
+ ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);
/* Parameter validation */
@@ -535,7 +534,7 @@ acpi_remove_notify_handler(acpi_handle device,
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_notify_handler);
+ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler)
/*******************************************************************************
*
@@ -554,7 +553,6 @@ EXPORT_SYMBOL(acpi_remove_notify_handler);
* DESCRIPTION: Install a handler for a General Purpose Event.
*
******************************************************************************/
-
acpi_status
acpi_install_gpe_handler(acpi_handle gpe_device,
u32 gpe_number,
@@ -565,7 +563,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
acpi_status status;
acpi_cpu_flags flags;
- ACPI_FUNCTION_TRACE("acpi_install_gpe_handler");
+ ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);
/* Parameter validation */
@@ -596,7 +594,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
/* Allocate and init handler object */
- handler = ACPI_MEM_CALLOCATE(sizeof(struct acpi_handler_info));
+ handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info));
if (!handler) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
@@ -630,7 +628,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_gpe_handler);
+ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)
/*******************************************************************************
*
@@ -646,7 +644,6 @@ EXPORT_SYMBOL(acpi_install_gpe_handler);
* DESCRIPTION: Remove a handler for a General Purpose acpi_event.
*
******************************************************************************/
-
acpi_status
acpi_remove_gpe_handler(acpi_handle gpe_device,
u32 gpe_number, acpi_event_handler address)
@@ -656,7 +653,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
acpi_status status;
acpi_cpu_flags flags;
- ACPI_FUNCTION_TRACE("acpi_remove_gpe_handler");
+ ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler);
/* Parameter validation */
@@ -724,14 +721,14 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
/* Now we can free the handler object */
- ACPI_MEM_FREE(handler);
+ ACPI_FREE(handler);
unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_gpe_handler);
+ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
/*******************************************************************************
*
@@ -746,7 +743,6 @@ EXPORT_SYMBOL(acpi_remove_gpe_handler);
* DESCRIPTION: Acquire the ACPI Global Lock
*
******************************************************************************/
-
acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
{
acpi_status status;
@@ -771,7 +767,7 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
return (status);
}
-EXPORT_SYMBOL(acpi_acquire_global_lock);
+ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock)
/*******************************************************************************
*
@@ -784,7 +780,6 @@ EXPORT_SYMBOL(acpi_acquire_global_lock);
* DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
*
******************************************************************************/
-
acpi_status acpi_release_global_lock(u32 handle)
{
acpi_status status;
@@ -797,4 +792,4 @@ acpi_status acpi_release_global_lock(u32 handle)
return (status);
}
-EXPORT_SYMBOL(acpi_release_global_lock);
+ACPI_EXPORT_SYMBOL(acpi_release_global_lock)
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index ec9ce8429f1..7ebc2efac93 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -41,8 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include <acpi/acevents.h>
#include <acpi/acnamesp.h>
@@ -65,7 +63,7 @@ acpi_status acpi_enable(void)
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("acpi_enable");
+ ACPI_FUNCTION_TRACE(acpi_enable);
/* Make sure we have the FADT */
@@ -94,6 +92,8 @@ acpi_status acpi_enable(void)
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_enable)
+
/*******************************************************************************
*
* FUNCTION: acpi_disable
@@ -105,12 +105,11 @@ acpi_status acpi_enable(void)
* DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
*
******************************************************************************/
-
acpi_status acpi_disable(void)
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("acpi_disable");
+ ACPI_FUNCTION_TRACE(acpi_disable);
if (!acpi_gbl_FADT) {
ACPI_WARNING((AE_INFO, "No FADT information present!"));
@@ -137,6 +136,8 @@ acpi_status acpi_disable(void)
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_disable)
+
/*******************************************************************************
*
* FUNCTION: acpi_enable_event
@@ -149,13 +150,12 @@ acpi_status acpi_disable(void)
* DESCRIPTION: Enable an ACPI event (fixed)
*
******************************************************************************/
-
acpi_status acpi_enable_event(u32 event, u32 flags)
{
acpi_status status = AE_OK;
u32 value;
- ACPI_FUNCTION_TRACE("acpi_enable_event");
+ ACPI_FUNCTION_TRACE(acpi_enable_event);
/* Decode the Fixed Event */
@@ -193,7 +193,7 @@ acpi_status acpi_enable_event(u32 event, u32 flags)
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_enable_event);
+ACPI_EXPORT_SYMBOL(acpi_enable_event)
/*******************************************************************************
*
@@ -208,13 +208,12 @@ EXPORT_SYMBOL(acpi_enable_event);
* DESCRIPTION: Set the type of an individual GPE
*
******************************************************************************/
-
acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
- ACPI_FUNCTION_TRACE("acpi_set_gpe_type");
+ ACPI_FUNCTION_TRACE(acpi_set_gpe_type);
/* Ensure that we have a valid GPE number */
@@ -236,7 +235,7 @@ acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type)
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_set_gpe_type);
+ACPI_EXPORT_SYMBOL(acpi_set_gpe_type)
/*******************************************************************************
*
@@ -252,13 +251,12 @@ EXPORT_SYMBOL(acpi_set_gpe_type);
* DESCRIPTION: Enable an ACPI event (general purpose)
*
******************************************************************************/
-
acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
- ACPI_FUNCTION_TRACE("acpi_enable_gpe");
+ ACPI_FUNCTION_TRACE(acpi_enable_gpe);
/* Use semaphore lock if not executing at interrupt level */
@@ -288,7 +286,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_enable_gpe);
+ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
/*******************************************************************************
*
@@ -304,13 +302,12 @@ EXPORT_SYMBOL(acpi_enable_gpe);
* DESCRIPTION: Disable an ACPI event (general purpose)
*
******************************************************************************/
-
acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
- ACPI_FUNCTION_TRACE("acpi_disable_gpe");
+ ACPI_FUNCTION_TRACE(acpi_disable_gpe);
/* Use semaphore lock if not executing at interrupt level */
@@ -338,6 +335,8 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
+
/*******************************************************************************
*
* FUNCTION: acpi_disable_event
@@ -350,13 +349,12 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
* DESCRIPTION: Disable an ACPI event (fixed)
*
******************************************************************************/
-
acpi_status acpi_disable_event(u32 event, u32 flags)
{
acpi_status status = AE_OK;
u32 value;
- ACPI_FUNCTION_TRACE("acpi_disable_event");
+ ACPI_FUNCTION_TRACE(acpi_disable_event);
/* Decode the Fixed Event */
@@ -392,7 +390,7 @@ acpi_status acpi_disable_event(u32 event, u32 flags)
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_disable_event);
+ACPI_EXPORT_SYMBOL(acpi_disable_event)
/*******************************************************************************
*
@@ -405,12 +403,11 @@ EXPORT_SYMBOL(acpi_disable_event);
* DESCRIPTION: Clear an ACPI event (fixed)
*
******************************************************************************/
-
acpi_status acpi_clear_event(u32 event)
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("acpi_clear_event");
+ ACPI_FUNCTION_TRACE(acpi_clear_event);
/* Decode the Fixed Event */
@@ -429,7 +426,7 @@ acpi_status acpi_clear_event(u32 event)
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_clear_event);
+ACPI_EXPORT_SYMBOL(acpi_clear_event)
/*******************************************************************************
*
@@ -444,13 +441,12 @@ EXPORT_SYMBOL(acpi_clear_event);
* DESCRIPTION: Clear an ACPI event (general purpose)
*
******************************************************************************/
-
acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
- ACPI_FUNCTION_TRACE("acpi_clear_gpe");
+ ACPI_FUNCTION_TRACE(acpi_clear_gpe);
/* Use semaphore lock if not executing at interrupt level */
@@ -478,6 +474,8 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
+
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -492,12 +490,11 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
* DESCRIPTION: Obtains and returns the current status of the event
*
******************************************************************************/
-
acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("acpi_get_event_status");
+ ACPI_FUNCTION_TRACE(acpi_get_event_status);
if (!event_status) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -518,6 +515,8 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_get_event_status)
+
/*******************************************************************************
*
* FUNCTION: acpi_get_gpe_status
@@ -533,7 +532,6 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
* DESCRIPTION: Get status of an event (general purpose)
*
******************************************************************************/
-
acpi_status
acpi_get_gpe_status(acpi_handle gpe_device,
u32 gpe_number, u32 flags, acpi_event_status * event_status)
@@ -541,7 +539,7 @@ acpi_get_gpe_status(acpi_handle gpe_device,
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
- ACPI_FUNCTION_TRACE("acpi_get_gpe_status");
+ ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
/* Use semaphore lock if not executing at interrupt level */
@@ -570,6 +568,8 @@ acpi_get_gpe_status(acpi_handle gpe_device,
}
return_ACPI_STATUS(status);
}
+
+ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
@@ -586,7 +586,6 @@ acpi_get_gpe_status(acpi_handle gpe_device,
* DESCRIPTION: Create and Install a block of GPE registers
*
******************************************************************************/
-
acpi_status
acpi_install_gpe_block(acpi_handle gpe_device,
struct acpi_generic_address *gpe_block_address,
@@ -597,7 +596,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
struct acpi_namespace_node *node;
struct acpi_gpe_block_info *gpe_block;
- ACPI_FUNCTION_TRACE("acpi_install_gpe_block");
+ ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -636,6 +635,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
+
/* No object, create a new one */
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
@@ -665,7 +665,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_gpe_block);
+ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
/*******************************************************************************
*
@@ -678,14 +678,13 @@ EXPORT_SYMBOL(acpi_install_gpe_block);
* DESCRIPTION: Remove a previously installed block of GPE registers
*
******************************************************************************/
-
acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
{
union acpi_operand_object *obj_desc;
acpi_status status;
struct acpi_namespace_node *node;
- ACPI_FUNCTION_TRACE("acpi_remove_gpe_block");
+ ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
if (!gpe_device) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -721,4 +720,4 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_gpe_block);
+ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c
index abf5caca9ae..e8b86a0baad 100644
--- a/drivers/acpi/events/evxfregn.c
+++ b/drivers/acpi/events/evxfregn.c
@@ -42,8 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
@@ -75,7 +73,7 @@ acpi_install_address_space_handler(acpi_handle device,
struct acpi_namespace_node *node;
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_install_address_space_handler");
+ ACPI_FUNCTION_TRACE(acpi_install_address_space_handler);
/* Parameter validation */
@@ -114,7 +112,7 @@ acpi_install_address_space_handler(acpi_handle device,
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_install_address_space_handler);
+ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
/*******************************************************************************
*
@@ -129,7 +127,6 @@ EXPORT_SYMBOL(acpi_install_address_space_handler);
* DESCRIPTION: Remove a previously installed handler.
*
******************************************************************************/
-
acpi_status
acpi_remove_address_space_handler(acpi_handle device,
acpi_adr_space_type space_id,
@@ -142,7 +139,7 @@ acpi_remove_address_space_handler(acpi_handle device,
struct acpi_namespace_node *node;
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_remove_address_space_handler");
+ ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler);
/* Parameter validation */
@@ -176,9 +173,11 @@ acpi_remove_address_space_handler(acpi_handle device,
handler_obj = obj_desc->device.handler;
last_obj_ptr = &obj_desc->device.handler;
while (handler_obj) {
+
/* We have a handler, see if user requested this one */
if (handler_obj->address_space.space_id == space_id) {
+
/* Matched space_id, first dereference this in the Regions */
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
@@ -229,7 +228,7 @@ acpi_remove_address_space_handler(acpi_handle device,
/* The handler does not exist */
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
- "Unable to remove address handler %p for %s(%X), dev_node %p, obj %p\n",
+ "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
handler, acpi_ut_get_region_name(space_id), space_id,
node, obj_desc));
@@ -240,4 +239,4 @@ acpi_remove_address_space_handler(acpi_handle device,
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_remove_address_space_handler);
+ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index a29782fe3ec..823352435e0 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -82,7 +82,7 @@ acpi_ex_add_table(struct acpi_table_header *table,
struct acpi_table_desc table_info;
union acpi_operand_object *obj_desc;
- ACPI_FUNCTION_TRACE("ex_add_table");
+ ACPI_FUNCTION_TRACE(ex_add_table);
/* Create an object to be the table handle */
@@ -100,7 +100,7 @@ acpi_ex_add_table(struct acpi_table_header *table,
ACPI_MEMSET(&table_info, 0, sizeof(struct acpi_table_desc));
- table_info.type = ACPI_TABLE_SSDT;
+ table_info.type = ACPI_TABLE_ID_SSDT;
table_info.pointer = table;
table_info.length = (acpi_size) table->length;
table_info.allocation = ACPI_MEM_ALLOCATED;
@@ -110,6 +110,7 @@ acpi_ex_add_table(struct acpi_table_header *table,
if (ACPI_FAILURE(status)) {
if (status == AE_ALREADY_EXISTS) {
+
/* Table already exists, just return the handle */
return_ACPI_STATUS(AE_OK);
@@ -121,6 +122,7 @@ acpi_ex_add_table(struct acpi_table_header *table,
status = acpi_ns_load_table(table_info.installed_desc, parent_node);
if (ACPI_FAILURE(status)) {
+
/* Uninstall table on error */
(void)acpi_tb_uninstall_table(table_info.installed_desc);
@@ -160,7 +162,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
struct acpi_namespace_node *parameter_node = NULL;
union acpi_operand_object *ddb_handle;
- ACPI_FUNCTION_TRACE("ex_load_table_op");
+ ACPI_FUNCTION_TRACE(ex_load_table_op);
#if 0
/*
@@ -169,6 +171,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
*/
status = acpi_tb_match_signature(operand[0]->string.pointer, NULL);
if (status == AE_OK) {
+
/* Signature matched -- don't allow override */
return_ACPI_STATUS(AE_ALREADY_EXISTS);
@@ -211,9 +214,8 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
* location within the namespace where the table will be loaded.
*/
status =
- acpi_ns_get_node_by_path(operand[3]->string.pointer,
- start_node, ACPI_NS_SEARCH_PARENT,
- &parent_node);
+ acpi_ns_get_node(start_node, operand[3]->string.pointer,
+ ACPI_NS_SEARCH_PARENT, &parent_node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -234,9 +236,8 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
/* Find the node referenced by the parameter_path_string */
status =
- acpi_ns_get_node_by_path(operand[4]->string.pointer,
- start_node, ACPI_NS_SEARCH_PARENT,
- &parameter_node);
+ acpi_ns_get_node(start_node, operand[4]->string.pointer,
+ ACPI_NS_SEARCH_PARENT, &parameter_node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -252,6 +253,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
/* Parameter Data (optional) */
if (parameter_node) {
+
/* Store the parameter data into the optional parameter object */
status = acpi_ex_store(operand[5],
@@ -294,9 +296,10 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
struct acpi_table_header *table_ptr = NULL;
acpi_physical_address address;
struct acpi_table_header table_header;
+ acpi_integer temp;
u32 i;
- ACPI_FUNCTION_TRACE("ex_load_op");
+ ACPI_FUNCTION_TRACE(ex_load_op);
/* Object can be either an op_region or a Field */
@@ -322,7 +325,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
address = obj_desc->region.address;
- /* Get the table length from the table header */
+ /* Get part of the table header to get the table length */
table_header.length = 0;
for (i = 0; i < 8; i++) {
@@ -330,11 +333,14 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
(acpi_physical_address)
(i + address), 8,
- ((u8 *) &
- table_header) + i);
+ &temp);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
+
+ /* Get the one valid byte of the returned 64-bit value */
+
+ ACPI_CAST_PTR(u8, &table_header)[i] = (u8) temp;
}
/* Sanity check the table length */
@@ -345,7 +351,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/* Allocate a buffer for the entire table */
- table_ptr = ACPI_MEM_ALLOCATE(table_header.length);
+ table_ptr = ACPI_ALLOCATE(table_header.length);
if (!table_ptr) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -357,11 +363,14 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
(acpi_physical_address)
(i + address), 8,
- ((u8 *) table_ptr +
- i));
+ &temp);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
+
+ /* Get the one valid byte of the returned 64-bit value */
+
+ ACPI_CAST_PTR(u8, table_ptr)[i] = (u8) temp;
}
break;
@@ -407,12 +416,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/* The table must be either an SSDT or a PSDT */
- if ((!ACPI_STRNCMP(table_ptr->signature,
- acpi_gbl_table_data[ACPI_TABLE_PSDT].signature,
- acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) &&
- (!ACPI_STRNCMP(table_ptr->signature,
- acpi_gbl_table_data[ACPI_TABLE_SSDT].signature,
- acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) {
+ if ((!ACPI_COMPARE_NAME(table_ptr->signature, PSDT_SIG)) &&
+ (!ACPI_COMPARE_NAME(table_ptr->signature, SSDT_SIG))) {
ACPI_ERROR((AE_INFO,
"Table has invalid signature [%4.4s], must be SSDT or PSDT",
table_ptr->signature));
@@ -424,6 +429,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
status = acpi_ex_add_table(table_ptr, acpi_gbl_root_node, &ddb_handle);
if (ACPI_FAILURE(status)) {
+
/* On error, table_ptr was deallocated above */
return_ACPI_STATUS(status);
@@ -442,7 +448,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
cleanup:
if (ACPI_FAILURE(status)) {
- ACPI_MEM_FREE(table_ptr);
+ ACPI_FREE(table_ptr);
}
return_ACPI_STATUS(status);
}
@@ -465,7 +471,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
union acpi_operand_object *table_desc = ddb_handle;
struct acpi_table_desc *table_info;
- ACPI_FUNCTION_TRACE("ex_unload_table");
+ ACPI_FUNCTION_TRACE(ex_unload_table);
/*
* Validate the handle
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
index e6d52e12d77..b732e399b1e 100644
--- a/drivers/acpi/executer/exconvrt.c
+++ b/drivers/acpi/executer/exconvrt.c
@@ -79,7 +79,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
u32 count;
acpi_status status;
- ACPI_FUNCTION_TRACE_PTR("ex_convert_to_integer", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc);
switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_INTEGER:
@@ -199,7 +199,7 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc,
union acpi_operand_object *return_desc;
u8 *new_buf;
- ACPI_FUNCTION_TRACE_PTR("ex_convert_to_buffer", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc);
switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_BUFFER:
@@ -319,6 +319,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer,
remainder = 0;
for (i = decimal_length; i > 0; i--) {
+
/* Divide by nth factor of 10 */
digit = integer;
@@ -346,6 +347,7 @@ acpi_ex_convert_to_ascii(acpi_integer integer,
hex_length = (acpi_native_uint) ACPI_MUL_2(data_width);
for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) {
+
/* Get one hex digit, most significant digits first */
string[k] =
@@ -400,7 +402,7 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
u16 base = 16;
u8 separator = ',';
- ACPI_FUNCTION_TRACE_PTR("ex_convert_to_string", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc);
switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
case ACPI_TYPE_STRING:
@@ -567,7 +569,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type,
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ex_convert_to_target_type");
+ ACPI_FUNCTION_TRACE(ex_convert_to_target_type);
/* Default behavior */
@@ -657,7 +659,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type,
default:
ACPI_ERROR((AE_INFO,
- "Unknown Target type ID 0x%X aml_opcode %X dest_type %s",
+ "Unknown Target type ID 0x%X AmlOpcode %X DestType %s",
GET_CURRENT_ARG_TYPE(walk_state->op_info->
runtime_args),
walk_state->opcode,
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
index 68057540283..106dc7219df 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/executer/excreate.c
@@ -69,7 +69,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
struct acpi_namespace_node *alias_node;
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ex_create_alias");
+ ACPI_FUNCTION_TRACE(ex_create_alias);
/* Get the source/alias operands (both namespace nodes) */
@@ -164,7 +164,7 @@ acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state)
acpi_status status;
union acpi_operand_object *obj_desc;
- ACPI_FUNCTION_TRACE("ex_create_event");
+ ACPI_FUNCTION_TRACE(ex_create_event);
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT);
if (!obj_desc) {
@@ -216,7 +216,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
acpi_status status = AE_OK;
union acpi_operand_object *obj_desc;
- ACPI_FUNCTION_TRACE_PTR("ex_create_mutex", ACPI_WALK_OPERANDS);
+ ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS);
/* Create the new mutex object */
@@ -243,8 +243,9 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
obj_desc->mutex.node =
(struct acpi_namespace_node *)walk_state->operands[0];
- status = acpi_ns_attach_object(obj_desc->mutex.node,
- obj_desc, ACPI_TYPE_MUTEX);
+ status =
+ acpi_ns_attach_object(obj_desc->mutex.node, obj_desc,
+ ACPI_TYPE_MUTEX);
cleanup:
/*
@@ -280,7 +281,7 @@ acpi_ex_create_region(u8 * aml_start,
struct acpi_namespace_node *node;
union acpi_operand_object *region_obj2;
- ACPI_FUNCTION_TRACE("ex_create_region");
+ ACPI_FUNCTION_TRACE(ex_create_region);
/* Get the Namespace Node */
@@ -300,7 +301,7 @@ acpi_ex_create_region(u8 * aml_start,
*/
if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
(region_space < ACPI_USER_REGION_BEGIN)) {
- ACPI_ERROR((AE_INFO, "Invalid address_space type %X",
+ ACPI_ERROR((AE_INFO, "Invalid AddressSpace type %X",
region_space));
return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
}
@@ -364,7 +365,7 @@ acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state)
struct acpi_table_header *table;
union acpi_operand_object *region_obj2;
- ACPI_FUNCTION_TRACE("ex_create_table_region");
+ ACPI_FUNCTION_TRACE(ex_create_table_region);
/* Get the Node from the object stack */
@@ -452,7 +453,7 @@ acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state)
union acpi_operand_object *obj_desc;
acpi_status status;
- ACPI_FUNCTION_TRACE_PTR("ex_create_processor", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state);
/* Create the processor object */
@@ -464,9 +465,9 @@ acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state)
/* Initialize the processor object from the operands */
obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
+ obj_desc->processor.length = (u8) operand[3]->integer.value;
obj_desc->processor.address =
(acpi_io_address) operand[2]->integer.value;
- obj_desc->processor.length = (u8) operand[3]->integer.value;
/* Install the processor object in the parent Node */
@@ -499,7 +500,7 @@ acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state)
acpi_status status;
union acpi_operand_object *obj_desc;
- ACPI_FUNCTION_TRACE_PTR("ex_create_power_resource", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state);
/* Create the power resource object */
@@ -549,7 +550,7 @@ acpi_ex_create_method(u8 * aml_start,
acpi_status status;
u8 method_flags;
- ACPI_FUNCTION_TRACE_PTR("ex_create_method", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state);
/* Create a new method object */
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index a7cca8d4f85..7b9718e976b 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -61,6 +61,10 @@ static void acpi_ex_out_pointer(char *title, void *value);
static void acpi_ex_out_address(char *title, acpi_physical_address value);
+static void
+acpi_ex_dump_object(union acpi_operand_object *obj_desc,
+ struct acpi_exdump_info *info);
+
static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc);
static void
@@ -119,7 +123,7 @@ static struct acpi_exdump_info acpi_ex_dump_event[2] = {
static struct acpi_exdump_info acpi_ex_dump_method[8] = {
{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL},
- {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "param_count"},
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "ParamCount"},
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.concurrency), "Concurrency"},
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.semaphore), "Semaphore"},
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.owner_id), "Owner Id"},
@@ -263,12 +267,10 @@ static struct acpi_exdump_info acpi_ex_dump_field_common[7] = {
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(common_field.node), "Parent Node"}
};
-static struct acpi_exdump_info acpi_ex_dump_node[6] = {
+static struct acpi_exdump_info acpi_ex_dump_node[5] = {
{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL},
{ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"},
{ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"},
- {ACPI_EXD_UINT16, ACPI_EXD_NSOFFSET(reference_count),
- "Reference Count"},
{ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(child), "Child List"},
{ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(peer), "Next Peer"}
};
@@ -330,7 +332,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
if (!info) {
acpi_os_printf
- ("ex_dump_object: Display not implemented for object type %s\n",
+ ("ExDumpObject: Display not implemented for object type %s\n",
acpi_ut_get_object_type_name(obj_desc));
return;
}
@@ -454,7 +456,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
u32 length;
u32 index;
- ACPI_FUNCTION_NAME("ex_dump_operand")
+ ACPI_FUNCTION_NAME(ex_dump_operand)
if (!
((ACPI_LV_EXEC & acpi_dbg_level)
@@ -463,6 +465,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
}
if (!obj_desc) {
+
/* This could be a null element of a package */
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Null Object Descriptor\n"));
@@ -522,7 +525,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
case AML_REF_OF_OP:
- acpi_os_printf("Reference: (ref_of) %p\n",
+ acpi_os_printf("Reference: (RefOf) %p\n",
obj_desc->reference.object);
break;
@@ -532,6 +535,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
obj_desc->reference.offset);
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
+
/* Value is an Integer */
acpi_os_printf(" value is [%8.8X%8.8x]",
@@ -610,7 +614,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
case ACPI_TYPE_PACKAGE:
- acpi_os_printf("Package [Len %X] element_array %p\n",
+ acpi_os_printf("Package [Len %X] ElementArray %p\n",
obj_desc->package.count,
obj_desc->package.elements);
@@ -662,13 +666,13 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
case ACPI_TYPE_LOCAL_BANK_FIELD:
- acpi_os_printf("bank_field\n");
+ acpi_os_printf("BankField\n");
break;
case ACPI_TYPE_LOCAL_REGION_FIELD:
acpi_os_printf
- ("region_field: Bits=%X acc_width=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n",
+ ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n",
obj_desc->field.bit_length,
obj_desc->field.access_byte_width,
obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK,
@@ -681,12 +685,12 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
case ACPI_TYPE_LOCAL_INDEX_FIELD:
- acpi_os_printf("index_field\n");
+ acpi_os_printf("IndexField\n");
break;
case ACPI_TYPE_BUFFER_FIELD:
- acpi_os_printf("buffer_field: %X bits at byte %X bit %X of\n",
+ acpi_os_printf("BufferField: %X bits at byte %X bit %X of\n",
obj_desc->buffer_field.bit_length,
obj_desc->buffer_field.base_byte_offset,
obj_desc->buffer_field.start_field_bit_offset);
@@ -777,7 +781,7 @@ acpi_ex_dump_operands(union acpi_operand_object **operands,
{
acpi_native_uint i;
- ACPI_FUNCTION_NAME("ex_dump_operands");
+ ACPI_FUNCTION_NAME(ex_dump_operands);
if (!ident) {
ident = "?";
@@ -901,7 +905,7 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc)
acpi_os_printf("Could not convert name to pathname\n");
} else {
acpi_os_printf("%s\n", (char *)ret_buf.pointer);
- ACPI_MEM_FREE(ret_buf.pointer);
+ ACPI_FREE(ret_buf.pointer);
}
} else if (obj_desc->reference.object) {
acpi_os_printf("\nReferenced Object: %p\n",
@@ -1017,7 +1021,7 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
void
acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
{
- ACPI_FUNCTION_TRACE("ex_dump_object_descriptor");
+ ACPI_FUNCTION_TRACE(ex_dump_object_descriptor);
if (!obj_desc) {
return_VOID;
@@ -1046,7 +1050,7 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) {
acpi_os_printf
- ("ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n",
+ ("ExDumpObjectDescriptor: %p is not an ACPI operand object: [%s]\n",
obj_desc, acpi_ut_get_descriptor_name(obj_desc));
return_VOID;
}
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c
index e259201ce9a..9ea9c3a67ca 100644
--- a/drivers/acpi/executer/exfield.c
+++ b/drivers/acpi/executer/exfield.c
@@ -73,7 +73,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
void *buffer;
u8 locked;
- ACPI_FUNCTION_TRACE_PTR("ex_read_data_from_field", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
/* Parameter validation */
@@ -142,6 +142,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
length =
(acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
if (length > acpi_gbl_integer_byte_width) {
+
/* Field is too large for an Integer, create a Buffer instead */
buffer_desc = acpi_ut_create_buffer_object(length);
@@ -163,11 +164,11 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
}
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "field_read [TO]: Obj %p, Type %X, Buf %p, byte_len %X\n",
+ "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
obj_desc, ACPI_GET_OBJECT_TYPE(obj_desc), buffer,
(u32) length));
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "field_read [FROM]: bit_len %X, bit_off %X, byte_off %X\n",
+ "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
obj_desc->common_field.bit_length,
obj_desc->common_field.start_field_bit_offset,
obj_desc->common_field.base_byte_offset));
@@ -219,7 +220,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
u8 locked;
union acpi_operand_object *buffer_desc;
- ACPI_FUNCTION_TRACE_PTR("ex_write_data_to_field", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
/* Parameter validation */
@@ -329,9 +330,10 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
if (length < required_length) {
+
/* We need to create a new buffer */
- new_buffer = ACPI_MEM_CALLOCATE(required_length);
+ new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
if (!new_buffer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -347,14 +349,14 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
}
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "field_write [FROM]: Obj %p (%s:%X), Buf %p, byte_len %X\n",
+ "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
source_desc,
acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE
(source_desc)),
ACPI_GET_OBJECT_TYPE(source_desc), buffer, length));
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "field_write [TO]: Obj %p (%s:%X), bit_len %X, bit_off %X, byte_off %X\n",
+ "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
obj_desc,
acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)),
ACPI_GET_OBJECT_TYPE(obj_desc),
@@ -375,7 +377,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
/* Free temporary buffer if we used one */
if (new_buffer) {
- ACPI_MEM_FREE(new_buffer);
+ ACPI_FREE(new_buffer);
}
return_ACPI_STATUS(status);
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
index bd1af35f7fc..051053f7ccc 100644
--- a/drivers/acpi/executer/exfldio.c
+++ b/drivers/acpi/executer/exfldio.c
@@ -87,7 +87,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
acpi_status status = AE_OK;
union acpi_operand_object *rgn_desc;
- ACPI_FUNCTION_TRACE_U32("ex_setup_region", field_datum_byte_offset);
+ ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset);
rgn_desc = obj_desc->common_field.region_obj;
@@ -112,7 +112,18 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
}
}
+ /* Exit if Address/Length have been disallowed by the host OS */
+
+ if (rgn_desc->common.flags & AOPOBJ_INVALID) {
+ return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
+ }
+
+ /*
+ * Exit now for SMBus address space, it has a non-linear address space
+ * and the request cannot be directly validated
+ */
if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
+
/* SMBus has a non-linear address space */
return_ACPI_STATUS(AE_OK);
@@ -134,10 +145,10 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
* length of one field datum (access width) must fit within the region.
* (Region length is specified in bytes)
*/
- if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset +
- field_datum_byte_offset +
- obj_desc->common_field.
- access_byte_width)) {
+ if (rgn_desc->region.length <
+ (obj_desc->common_field.base_byte_offset +
+ field_datum_byte_offset +
+ obj_desc->common_field.access_byte_width)) {
if (acpi_gbl_enable_interpreter_slack) {
/*
* Slack mode only: We will go ahead and allow access to this
@@ -217,7 +228,7 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
union acpi_operand_object *rgn_desc;
acpi_physical_address address;
- ACPI_FUNCTION_TRACE("ex_access_region");
+ ACPI_FUNCTION_TRACE(ex_access_region);
/*
* Ensure that the region operands are fully evaluated and verify
@@ -246,7 +257,7 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
- " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n",
+ " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
acpi_ut_get_region_name(rgn_desc->region.
space_id),
rgn_desc->region.space_id,
@@ -352,7 +363,7 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
acpi_status status;
acpi_integer local_value;
- ACPI_FUNCTION_TRACE_U32("ex_field_datum_io", field_datum_byte_offset);
+ ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset);
if (read_write == ACPI_READ) {
if (!value) {
@@ -487,10 +498,11 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
}
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "I/O to Data Register: value_ptr %p\n",
+ "I/O to Data Register: ValuePtr %p\n",
value));
if (read_write == ACPI_READ) {
+
/* Read the datum from the data_register */
status =
@@ -559,7 +571,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
acpi_integer merged_value;
acpi_integer current_value;
- ACPI_FUNCTION_TRACE_U32("ex_write_with_update_rule", mask);
+ ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask);
/* Start with the new bits */
@@ -568,6 +580,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
/* If the mask is all ones, we don't need to worry about the update rule */
if (mask != ACPI_INTEGER_MAX) {
+
/* Decode the update rule */
switch (obj_desc->common_field.
@@ -614,7 +627,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
default:
ACPI_ERROR((AE_INFO,
- "Unknown update_rule value: %X",
+ "Unknown UpdateRule value: %X",
(obj_desc->common_field.
field_flags &
AML_FIELD_UPDATE_RULE_MASK)));
@@ -623,7 +636,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
}
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n",
+ "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
ACPI_FORMAT_UINT64(mask),
field_datum_byte_offset,
obj_desc->common_field.access_byte_width,
@@ -666,7 +679,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
u32 field_datum_count;
u32 i;
- ACPI_FUNCTION_TRACE("ex_extract_from_field");
+ ACPI_FUNCTION_TRACE(ex_extract_from_field);
/* Validate target buffer and clear it */
@@ -704,6 +717,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
/* Read the rest of the field */
for (i = 1; i < field_datum_count; i++) {
+
/* Get next input datum from the field */
field_offset += obj_desc->common_field.access_byte_width;
@@ -771,6 +785,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
{
acpi_status status;
acpi_integer mask;
+ acpi_integer width_mask;
acpi_integer merged_datum;
acpi_integer raw_datum = 0;
u32 field_offset = 0;
@@ -780,7 +795,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
u32 field_datum_count;
u32 i;
- ACPI_FUNCTION_TRACE("ex_insert_into_field");
+ ACPI_FUNCTION_TRACE(ex_insert_into_field);
/* Validate input buffer */
@@ -795,15 +810,20 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
/* Compute the number of datums (access width data items) */
+ width_mask =
+ ACPI_MASK_BITS_ABOVE(obj_desc->common_field.access_bit_width);
mask =
- ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);
- datum_count =
- ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
- obj_desc->common_field.access_bit_width);
- field_datum_count =
- ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
- obj_desc->common_field.start_field_bit_offset,
- obj_desc->common_field.access_bit_width);
+ width_mask & ACPI_MASK_BITS_BELOW(obj_desc->common_field.
+ start_field_bit_offset);
+
+ datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
+ obj_desc->common_field.access_bit_width);
+
+ field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
+ obj_desc->common_field.
+ start_field_bit_offset,
+ obj_desc->common_field.
+ access_bit_width);
/* Get initial Datum from the input buffer */
@@ -817,6 +837,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
/* Write the entire field */
for (i = 1; i < field_datum_count; i++) {
+
/* Write merged datum to the target field */
merged_datum &= mask;
@@ -833,7 +854,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
merged_datum = raw_datum >>
(obj_desc->common_field.access_bit_width -
obj_desc->common_field.start_field_bit_offset);
- mask = ACPI_INTEGER_MAX;
+ mask = width_mask;
if (i == datum_count) {
break;
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
index 48c18d29222..bd98aab017c 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/drivers/acpi/executer/exmisc.c
@@ -72,7 +72,7 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
union acpi_operand_object *reference_obj;
union acpi_operand_object *referenced_obj;
- ACPI_FUNCTION_TRACE_PTR("ex_get_object_reference", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc);
*return_desc = NULL;
@@ -168,7 +168,7 @@ acpi_ex_concat_template(union acpi_operand_object *operand0,
acpi_size length1;
acpi_size new_length;
- ACPI_FUNCTION_TRACE("ex_concat_template");
+ ACPI_FUNCTION_TRACE(ex_concat_template);
/*
* Find the end_tag descriptor in each resource template.
@@ -250,7 +250,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
char *new_buf;
acpi_status status;
- ACPI_FUNCTION_TRACE("ex_do_concatenate");
+ ACPI_FUNCTION_TRACE(ex_do_concatenate);
/*
* Convert the second operand if necessary. The first operand
@@ -445,10 +445,24 @@ acpi_ex_do_math_op(u16 opcode, acpi_integer integer0, acpi_integer integer1)
case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */
+ /*
+ * We need to check if the shiftcount is larger than the integer bit
+ * width since the behavior of this is not well-defined in the C language.
+ */
+ if (integer1 >= acpi_gbl_integer_bit_width) {
+ return (0);
+ }
return (integer0 << integer1);
case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */
+ /*
+ * We need to check if the shiftcount is larger than the integer bit
+ * width since the behavior of this is not well-defined in the C language.
+ */
+ if (integer1 >= acpi_gbl_integer_bit_width) {
+ return (0);
+ }
return (integer0 >> integer1);
case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */
@@ -489,7 +503,7 @@ acpi_ex_do_logical_numeric_op(u16 opcode,
acpi_status status = AE_OK;
u8 local_result = FALSE;
- ACPI_FUNCTION_TRACE("ex_do_logical_numeric_op");
+ ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op);
switch (opcode) {
case AML_LAND_OP: /* LAnd (Integer0, Integer1) */
@@ -557,7 +571,7 @@ acpi_ex_do_logical_op(u16 opcode,
u8 local_result = FALSE;
int compare;
- ACPI_FUNCTION_TRACE("ex_do_logical_op");
+ ACPI_FUNCTION_TRACE(ex_do_logical_op);
/*
* Convert the second operand if necessary. The first operand
@@ -649,6 +663,7 @@ acpi_ex_do_logical_op(u16 opcode,
/* Length and all bytes must be equal */
if ((length0 == length1) && (compare == 0)) {
+
/* Length and all bytes match ==> TRUE */
local_result = TRUE;
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index f843b22e20b..93098d68cad 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -61,7 +61,7 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
*
* RETURN: None
*
- * DESCRIPTION: Remove a mutex from the "acquired_mutex" list
+ * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list
*
******************************************************************************/
@@ -95,7 +95,7 @@ void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
*
* RETURN: None
*
- * DESCRIPTION: Add a mutex to the "acquired_mutex" list for this walk
+ * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk
*
******************************************************************************/
@@ -144,7 +144,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
{
acpi_status status;
- ACPI_FUNCTION_TRACE_PTR("ex_acquire_mutex", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex, obj_desc);
if (!obj_desc) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -165,7 +165,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
*/
if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
ACPI_ERROR((AE_INFO,
- "Cannot acquire Mutex [%4.4s], incorrect sync_level",
+ "Cannot acquire Mutex [%4.4s], incorrect SyncLevel",
acpi_ut_get_node_name(obj_desc->mutex.node)));
return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
}
@@ -173,6 +173,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
/* Support for multiple acquires by the owning thread */
if (obj_desc->mutex.owner_thread) {
+
/* Special case for Global Lock, allow all threads */
if ((obj_desc->mutex.owner_thread->thread_id ==
@@ -192,6 +193,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
status = acpi_ex_system_acquire_mutex(time_desc, obj_desc);
if (ACPI_FAILURE(status)) {
+
/* Includes failure from a timeout on time_desc */
return_ACPI_STATUS(status);
@@ -232,7 +234,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ex_release_mutex");
+ ACPI_FUNCTION_TRACE(ex_release_mutex);
if (!obj_desc) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -277,7 +279,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
*/
if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
ACPI_ERROR((AE_INFO,
- "Cannot release Mutex [%4.4s], incorrect sync_level",
+ "Cannot release Mutex [%4.4s], incorrect SyncLevel",
acpi_ut_get_node_name(obj_desc->mutex.node)));
return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
}
@@ -286,6 +288,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
obj_desc->mutex.acquisition_depth--;
if (obj_desc->mutex.acquisition_depth != 0) {
+
/* Just decrement the depth and return */
return_ACPI_STATUS(AE_OK);
diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c
index 054fe5e1a31..d3d70364626 100644
--- a/drivers/acpi/executer/exnames.c
+++ b/drivers/acpi/executer/exnames.c
@@ -77,7 +77,7 @@ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
char *name_string;
u32 size_needed;
- ACPI_FUNCTION_TRACE("ex_allocate_name_string");
+ ACPI_FUNCTION_TRACE(ex_allocate_name_string);
/*
* Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix.
@@ -85,6 +85,7 @@ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
* This may actually be somewhat longer than needed.
*/
if (prefix_count == ACPI_UINT32_MAX) {
+
/* Special case for root */
size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
@@ -97,7 +98,7 @@ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
* Allocate a buffer for the name.
* This buffer must be deleted by the caller!
*/
- name_string = ACPI_MEM_ALLOCATE(size_needed);
+ name_string = ACPI_ALLOCATE(size_needed);
if (!name_string) {
ACPI_ERROR((AE_INFO,
"Could not allocate size %d", size_needed));
@@ -119,11 +120,13 @@ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
/* Set up Dual or Multi prefixes if needed */
if (num_name_segs > 2) {
+
/* Set up multi prefixes */
*temp_ptr++ = AML_MULTI_NAME_PREFIX_OP;
*temp_ptr++ = (char)num_name_segs;
} else if (2 == num_name_segs) {
+
/* Set up dual prefixes */
*temp_ptr++ = AML_DUAL_NAME_PREFIX;
@@ -159,7 +162,7 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
u32 index;
char char_buf[5];
- ACPI_FUNCTION_TRACE("ex_name_segment");
+ ACPI_FUNCTION_TRACE(ex_name_segment);
/*
* If first character is a digit, then we know that we aren't looking at a
@@ -176,7 +179,7 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
for (index = 0;
(index < ACPI_NAME_SIZE)
- && (acpi_ut_valid_acpi_character(*aml_address)); index++) {
+ && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) {
char_buf[index] = *aml_address++;
ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index]));
}
@@ -184,6 +187,7 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
/* Valid name segment */
if (index == 4) {
+
/* Found 4 valid characters */
char_buf[4] = '\0';
@@ -249,11 +253,12 @@ acpi_ex_get_name_string(acpi_object_type data_type,
u32 prefix_count = 0;
u8 has_prefix = FALSE;
- ACPI_FUNCTION_TRACE_PTR("ex_get_name_string", aml_address);
+ ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address);
if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type ||
ACPI_TYPE_LOCAL_BANK_FIELD == data_type ||
ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
+
/* Disallow prefixes for types associated with field_unit names */
name_string = acpi_ex_allocate_name_string(0, 1);
@@ -272,7 +277,7 @@ acpi_ex_get_name_string(acpi_object_type data_type,
case AML_ROOT_PREFIX:
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
- "root_prefix(\\) at %p\n",
+ "RootPrefix(\\) at %p\n",
aml_address));
/*
@@ -290,7 +295,7 @@ acpi_ex_get_name_string(acpi_object_type data_type,
do {
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
- "parent_prefix (^) at %p\n",
+ "ParentPrefix (^) at %p\n",
aml_address));
aml_address++;
@@ -314,7 +319,7 @@ acpi_ex_get_name_string(acpi_object_type data_type,
case AML_DUAL_NAME_PREFIX:
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
- "dual_name_prefix at %p\n",
+ "DualNamePrefix at %p\n",
aml_address));
aml_address++;
@@ -341,7 +346,7 @@ acpi_ex_get_name_string(acpi_object_type data_type,
case AML_MULTI_NAME_PREFIX_OP:
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
- "multi_name_prefix at %p\n",
+ "MultiNamePrefix at %p\n",
aml_address));
/* Fetch count of segments remaining in name path */
@@ -377,7 +382,7 @@ acpi_ex_get_name_string(acpi_object_type data_type,
if (prefix_count == ACPI_UINT32_MAX) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "name_seg is \"\\\" followed by NULL\n"));
+ "NameSeg is \"\\\" followed by NULL\n"));
}
/* Consume the NULL byte */
@@ -410,6 +415,7 @@ acpi_ex_get_name_string(acpi_object_type data_type,
}
if (AE_CTRL_PENDING == status && has_prefix) {
+
/* Ran out of segments after processing a prefix */
ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string));
@@ -418,7 +424,7 @@ acpi_ex_get_name_string(acpi_object_type data_type,
if (ACPI_FAILURE(status)) {
if (name_string) {
- ACPI_MEM_FREE(name_string);
+ ACPI_FREE(name_string);
}
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
index 23d0823bcd5..6374d8be88e 100644
--- a/drivers/acpi/executer/exoparg1.c
+++ b/drivers/acpi/executer/exoparg1.c
@@ -89,7 +89,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)
acpi_status status = AE_OK;
union acpi_operand_object *return_desc = NULL;
- ACPI_FUNCTION_TRACE_STR("ex_opcode_0A_0T_1R",
+ ACPI_FUNCTION_TRACE_STR(ex_opcode_0A_0T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
@@ -150,7 +150,7 @@ acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state)
union acpi_operand_object **operand = &walk_state->operands[0];
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_0T_0R",
+ ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_0R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
@@ -216,7 +216,7 @@ acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state)
acpi_status status = AE_OK;
union acpi_operand_object **operand = &walk_state->operands[0];
- ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_1T_0R",
+ ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_0R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
@@ -264,7 +264,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
acpi_integer power_of_ten;
acpi_integer digit;
- ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_1T_1R",
+ ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
@@ -322,8 +322,9 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
/* Since the bit position is one-based, subtract from 33 (65) */
- return_desc->integer.value = temp32 == 0 ? 0 :
- (ACPI_INTEGER_BIT_SIZE + 1) - temp32;
+ return_desc->integer.value =
+ temp32 ==
+ 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32;
break;
case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */
@@ -342,6 +343,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
for (i = 0;
(i < acpi_gbl_integer_nybble_width) && (digit > 0);
i++) {
+
/* Get the least significant 4-bit BCD digit */
temp32 = ((u32) digit) & 0xF;
@@ -487,6 +489,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
status = acpi_ex_convert_to_string(operand[0], &return_desc,
ACPI_EXPLICIT_CONVERT_DECIMAL);
if (return_desc == operand[0]) {
+
/* No conversion performed, add ref to handle return value */
acpi_ut_add_reference(return_desc);
}
@@ -497,6 +500,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
status = acpi_ex_convert_to_string(operand[0], &return_desc,
ACPI_EXPLICIT_CONVERT_HEX);
if (return_desc == operand[0]) {
+
/* No conversion performed, add ref to handle return value */
acpi_ut_add_reference(return_desc);
}
@@ -506,6 +510,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
status = acpi_ex_convert_to_buffer(operand[0], &return_desc);
if (return_desc == operand[0]) {
+
/* No conversion performed, add ref to handle return value */
acpi_ut_add_reference(return_desc);
}
@@ -516,6 +521,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
status = acpi_ex_convert_to_integer(operand[0], &return_desc,
ACPI_ANY_BASE);
if (return_desc == operand[0]) {
+
/* No conversion performed, add ref to handle return value */
acpi_ut_add_reference(return_desc);
}
@@ -541,6 +547,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
}
if (ACPI_SUCCESS(status)) {
+
/* Store the return value computed above into the target object */
status = acpi_ex_store(return_desc, operand[1], walk_state);
@@ -548,16 +555,18 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
cleanup:
- if (!walk_state->result_obj) {
- walk_state->result_obj = return_desc;
- }
-
/* Delete return object on error */
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(return_desc);
}
+ /* Save return object on success */
+
+ else if (!walk_state->result_obj) {
+ walk_state->result_obj = return_desc;
+ }
+
return_ACPI_STATUS(status);
}
@@ -582,7 +591,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
u32 type;
acpi_integer value;
- ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_0T_1R",
+ ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the AML opcode */
@@ -625,6 +634,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
temp_desc = operand[0];
if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) ==
ACPI_DESC_TYPE_OPERAND) {
+
/* Internal reference object - prevent deletion */
acpi_ut_add_reference(temp_desc);
@@ -689,6 +699,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
if (ACPI_FAILURE(status)) {
goto cleanup;
}
+
/* Allocate a descriptor to hold the type. */
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
@@ -777,8 +788,25 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
/* Check for a method local or argument, or standalone String */
- if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) !=
+ if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==
ACPI_DESC_TYPE_NAMED) {
+ temp_desc =
+ acpi_ns_get_attached_object((struct
+ acpi_namespace_node *)
+ operand[0]);
+ if (temp_desc
+ &&
+ ((ACPI_GET_OBJECT_TYPE(temp_desc) ==
+ ACPI_TYPE_STRING)
+ || (ACPI_GET_OBJECT_TYPE(temp_desc) ==
+ ACPI_TYPE_LOCAL_REFERENCE))) {
+ operand[0] = temp_desc;
+ acpi_ut_add_reference(temp_desc);
+ } else {
+ status = AE_AML_OPERAND_TYPE;
+ goto cleanup;
+ }
+ } else {
switch (ACPI_GET_OBJECT_TYPE(operand[0])) {
case ACPI_TYPE_LOCAL_REFERENCE:
/*
@@ -827,26 +855,35 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
break;
case ACPI_TYPE_STRING:
+ break;
+ default:
+ status = AE_AML_OPERAND_TYPE;
+ goto cleanup;
+ }
+ }
+
+ if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) !=
+ ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_OBJECT_TYPE(operand[0]) ==
+ ACPI_TYPE_STRING) {
/*
* This is a deref_of (String). The string is a reference
* to a named ACPI object.
*
* 1) Find the owning Node
- * 2) Dereference the node to an actual object. Could be a
+ * 2) Dereference the node to an actual object. Could be a
* Field, so we need to resolve the node to a value.
*/
status =
- acpi_ns_get_node_by_path(operand[0]->string.
- pointer,
- walk_state->
- scope_info->scope.
- node,
- ACPI_NS_SEARCH_PARENT,
- ACPI_CAST_INDIRECT_PTR
- (struct
- acpi_namespace_node,
- &return_desc));
+ acpi_ns_get_node(walk_state->scope_info->
+ scope.node,
+ operand[0]->string.pointer,
+ ACPI_NS_SEARCH_PARENT,
+ ACPI_CAST_INDIRECT_PTR
+ (struct
+ acpi_namespace_node,
+ &return_desc));
if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -857,11 +894,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
(struct acpi_namespace_node, &return_desc),
walk_state);
goto cleanup;
-
- default:
-
- status = AE_AML_OPERAND_TYPE;
- goto cleanup;
}
}
@@ -937,13 +969,12 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
acpi_ut_add_reference
(return_desc);
}
-
break;
default:
ACPI_ERROR((AE_INFO,
- "Unknown Index target_type %X in obj %p",
+ "Unknown Index TargetType %X in obj %p",
operand[0]->reference.
target_type, operand[0]));
status = AE_AML_OPERAND_TYPE;
@@ -957,7 +988,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) ==
ACPI_DESC_TYPE_NAMED) {
-
return_desc =
acpi_ns_get_attached_object((struct
acpi_namespace_node
@@ -972,7 +1002,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
default:
ACPI_ERROR((AE_INFO,
- "Unknown opcode in ref(%p) - %X",
+ "Unknown opcode in reference(%p) - %X",
operand[0],
operand[0]->reference.opcode));
@@ -998,6 +1028,11 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
acpi_ut_remove_reference(return_desc);
}
- walk_state->result_obj = return_desc;
+ /* Save return object on success */
+
+ else {
+ walk_state->result_obj = return_desc;
+ }
+
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
index e263a5ddd40..7d2cbc11316 100644
--- a/drivers/acpi/executer/exoparg2.c
+++ b/drivers/acpi/executer/exoparg2.c
@@ -92,7 +92,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
u32 value;
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_0R",
+ ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Examine the opcode */
@@ -121,7 +121,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
#ifdef ACPI_GPE_NOTIFY_CHECK
/*
* GPE method wake/notify check. Here, we want to ensure that we
- * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx
+ * don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx
* GPE method during system runtime. If we do, the GPE is marked
* as "wake-only" and disabled.
*
@@ -138,6 +138,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
acpi_ev_check_for_wake_only_gpe(walk_state->
gpe_event_info);
if (ACPI_FAILURE(status)) {
+
/* AE_WAKE_ONLY_GPE only error, means ignore this notify */
return_ACPI_STATUS(AE_OK)
@@ -185,7 +186,7 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
union acpi_operand_object *return_desc2 = NULL;
acpi_status status;
- ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_2T_1R",
+ ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Execute the opcode */
@@ -252,6 +253,7 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
acpi_ut_remove_reference(return_desc2);
if (ACPI_FAILURE(status)) {
+
/* Delete the return object */
acpi_ut_remove_reference(return_desc1);
@@ -281,12 +283,13 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
acpi_status status = AE_OK;
acpi_size length;
- ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_1T_1R",
+ ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Execute the opcode */
if (walk_state->op_info->flags & AML_MATH) {
+
/* All simple math opcodes (add, etc.) */
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
@@ -383,54 +386,70 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
goto cleanup;
}
+ /* Initialize the Index reference object */
+
index = operand[1]->integer.value;
+ return_desc->reference.offset = (u32) index;
+ return_desc->reference.opcode = AML_INDEX_OP;
- /* At this point, the Source operand is a Package, Buffer, or String */
+ /*
+ * At this point, the Source operand is a String, Buffer, or Package.
+ * Verify that the index is within range.
+ */
+ switch (ACPI_GET_OBJECT_TYPE(operand[0])) {
+ case ACPI_TYPE_STRING:
- if (ACPI_GET_OBJECT_TYPE(operand[0]) == ACPI_TYPE_PACKAGE) {
- /* Object to be indexed is a Package */
+ if (index >= operand[0]->string.length) {
+ status = AE_AML_STRING_LIMIT;
+ }
+
+ return_desc->reference.target_type =
+ ACPI_TYPE_BUFFER_FIELD;
+ break;
+
+ case ACPI_TYPE_BUFFER:
+
+ if (index >= operand[0]->buffer.length) {
+ status = AE_AML_BUFFER_LIMIT;
+ }
+
+ return_desc->reference.target_type =
+ ACPI_TYPE_BUFFER_FIELD;
+ break;
+
+ case ACPI_TYPE_PACKAGE:
if (index >= operand[0]->package.count) {
- ACPI_ERROR((AE_INFO,
- "Index value (%X%8.8X) beyond package end (%X)",
- ACPI_FORMAT_UINT64(index),
- operand[0]->package.count));
status = AE_AML_PACKAGE_LIMIT;
- goto cleanup;
}
return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
- return_desc->reference.object = operand[0];
return_desc->reference.where =
&operand[0]->package.elements[index];
- } else {
- /* Object to be indexed is a Buffer/String */
+ break;
- if (index >= operand[0]->buffer.length) {
- ACPI_ERROR((AE_INFO,
- "Index value (%X%8.8X) beyond end of buffer (%X)",
- ACPI_FORMAT_UINT64(index),
- operand[0]->buffer.length));
- status = AE_AML_BUFFER_LIMIT;
- goto cleanup;
- }
+ default:
- return_desc->reference.target_type =
- ACPI_TYPE_BUFFER_FIELD;
- return_desc->reference.object = operand[0];
+ status = AE_AML_INTERNAL;
+ goto cleanup;
+ }
+
+ /* Failure means that the Index was beyond the end of the object */
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Index (%X%8.8X) is beyond end of object",
+ ACPI_FORMAT_UINT64(index)));
+ goto cleanup;
}
/*
- * Add a reference to the target package/buffer/string for the life
- * of the index.
+ * Save the target object and add a reference to it for the life
+ * of the index
*/
+ return_desc->reference.object = operand[0];
acpi_ut_add_reference(operand[0]);
- /* Complete the Index reference object */
-
- return_desc->reference.opcode = AML_INDEX_OP;
- return_desc->reference.offset = (u32) index;
-
/* Store the reference to the Target */
status = acpi_ex_store(return_desc, operand[2], walk_state);
@@ -495,7 +514,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
acpi_status status = AE_OK;
u8 logical_result = FALSE;
- ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_1R",
+ ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
/* Create the internal return object */
@@ -509,6 +528,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
/* Execute the Opcode */
if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) {
+
/* logical_op (Operand0, Operand1) */
status = acpi_ex_do_logical_numeric_op(walk_state->opcode,
@@ -518,6 +538,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
value, &logical_result);
goto store_logical_result;
} else if (walk_state->op_info->flags & AML_LOGICAL) {
+
/* logical_op (Operand0, Operand1) */
status = acpi_ex_do_logical_op(walk_state->opcode, operand[0],
diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c
index 6a3a883cb8a..e2d945dfd50 100644
--- a/drivers/acpi/executer/exoparg3.c
+++ b/drivers/acpi/executer/exoparg3.c
@@ -88,20 +88,19 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
struct acpi_signal_fatal_info *fatal;
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_0T_0R",
+ ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R,
acpi_ps_get_opcode_name(walk_state->opcode));
switch (walk_state->opcode) {
case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
+ "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
(u32) operand[0]->integer.value,
(u32) operand[1]->integer.value,
(u32) operand[2]->integer.value));
- fatal =
- ACPI_MEM_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
+ fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
if (fatal) {
fatal->type = (u32) operand[0]->integer.value;
fatal->code = (u32) operand[1]->integer.value;
@@ -114,7 +113,7 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
/* Might return while OS is shutting down, just continue */
- ACPI_MEM_FREE(fatal);
+ ACPI_FREE(fatal);
break;
default:
@@ -151,7 +150,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
acpi_integer index;
acpi_size length;
- ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_1T_1R",
+ ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_1T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
switch (walk_state->opcode) {
@@ -196,7 +195,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
/* Always allocate a new buffer for the String */
- buffer = ACPI_MEM_CALLOCATE((acpi_size) length + 1);
+ buffer = ACPI_ALLOCATE_ZEROED((acpi_size) length + 1);
if (!buffer) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -208,9 +207,10 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
/* If the requested length is zero, don't allocate a buffer */
if (length > 0) {
+
/* Allocate a new buffer for the Buffer */
- buffer = ACPI_MEM_CALLOCATE(length);
+ buffer = ACPI_ALLOCATE_ZEROED(length);
if (!buffer) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -225,6 +225,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
}
if (buffer) {
+
/* We have a buffer, copy the portion requested */
ACPI_MEMCPY(buffer, operand[0]->string.pointer + index,
diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c
index e043d924444..f0c0ba6eb40 100644
--- a/drivers/acpi/executer/exoparg6.c
+++ b/drivers/acpi/executer/exoparg6.c
@@ -220,7 +220,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
acpi_integer index;
union acpi_operand_object *this_element;
- ACPI_FUNCTION_TRACE_STR("ex_opcode_6A_0T_1R",
+ ACPI_FUNCTION_TRACE_STR(ex_opcode_6A_0T_1R,
acpi_ps_get_opcode_name(walk_state->opcode));
switch (walk_state->opcode) {
@@ -276,6 +276,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
* match was found.
*/
for (; index < operand[0]->package.count; index++) {
+
/* Get the current package element */
this_element = operand[0]->package.elements[index];
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
index 7719ae5d4f1..44d064f427b 100644
--- a/drivers/acpi/executer/exprep.c
+++ b/drivers/acpi/executer/exprep.c
@@ -97,7 +97,7 @@ acpi_ex_generate_access(u32 field_bit_offset,
u32 minimum_accesses = 0xFFFFFFFF;
u32 accesses;
- ACPI_FUNCTION_TRACE("ex_generate_access");
+ ACPI_FUNCTION_TRACE(ex_generate_access);
/* Round Field start offset and length to "minimal" byte boundaries */
@@ -146,7 +146,7 @@ acpi_ex_generate_access(u32 field_bit_offset,
accesses = field_end_offset - field_start_offset;
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "access_width %d end is within region\n",
+ "AccessWidth %d end is within region\n",
access_byte_width));
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
@@ -173,7 +173,7 @@ acpi_ex_generate_access(u32 field_bit_offset,
}
} else {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "access_width %d end is NOT within region\n",
+ "AccessWidth %d end is NOT within region\n",
access_byte_width));
if (access_byte_width == 1) {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
@@ -228,7 +228,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
u32 byte_alignment;
u32 bit_length;
- ACPI_FUNCTION_TRACE("ex_decode_field_access");
+ ACPI_FUNCTION_TRACE(ex_decode_field_access);
access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK);
@@ -322,7 +322,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
u32 byte_alignment;
u32 nearest_byte_address;
- ACPI_FUNCTION_TRACE("ex_prep_common_field_object");
+ ACPI_FUNCTION_TRACE(ex_prep_common_field_object);
/*
* Note: the structure being initialized is the
@@ -415,13 +415,13 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
u32 type;
acpi_status status;
- ACPI_FUNCTION_TRACE("ex_prep_field_value");
+ ACPI_FUNCTION_TRACE(ex_prep_field_value);
/* Parameter validation */
if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
if (!info->region_node) {
- ACPI_ERROR((AE_INFO, "Null region_node"));
+ ACPI_ERROR((AE_INFO, "Null RegionNode"));
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
@@ -467,7 +467,7 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
acpi_ut_add_reference(obj_desc->field.region_obj);
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "region_field: bit_off %X, Off %X, Gran %X, Region %p\n",
+ "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
obj_desc->field.start_field_bit_offset,
obj_desc->field.base_byte_offset,
obj_desc->field.access_byte_width,
@@ -488,7 +488,7 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
acpi_ut_add_reference(obj_desc->bank_field.bank_obj);
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "Bank Field: bit_off %X, Off %X, Gran %X, Region %p, bank_reg %p\n",
+ "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n",
obj_desc->bank_field.start_field_bit_offset,
obj_desc->bank_field.base_byte_offset,
obj_desc->field.access_byte_width,
@@ -519,16 +519,29 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
acpi_ut_add_reference(obj_desc->index_field.index_obj);
/*
+ * April 2006: Changed to match MS behavior
+ *
* The value written to the Index register is the byte offset of the
- * target field
- * Note: may change code to: ACPI_DIV_8 (Info->field_bit_position)
+ * target field in units of the granularity of the index_field
+ *
+ * Previously, the value was calculated as an index in terms of the
+ * width of the Data register, as below:
+ *
+ * obj_desc->index_field.Value = (u32)
+ * (Info->field_bit_position / ACPI_MUL_8 (
+ * obj_desc->Field.access_byte_width));
+ *
+ * February 2006: Tried value as a byte offset:
+ * obj_desc->index_field.Value = (u32)
+ * ACPI_DIV_8 (Info->field_bit_position);
*/
- obj_desc->index_field.value = (u32)
- (info->field_bit_position /
- ACPI_MUL_8(obj_desc->field.access_byte_width));
+ obj_desc->index_field.value =
+ (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position),
+ obj_desc->index_field.
+ access_byte_width);
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
+ "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
obj_desc->index_field.start_field_bit_offset,
obj_desc->index_field.base_byte_offset,
obj_desc->index_field.value,
@@ -550,7 +563,7 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
acpi_ns_get_type(info->field_node));
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "Set named_obj %p [%4.4s], obj_desc %p\n",
+ "Set NamedObj %p [%4.4s], ObjDesc %p\n",
info->field_node,
acpi_ut_get_node_name(info->field_node), obj_desc));
diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c
index 6a4cfdff606..3cc97ba48b3 100644
--- a/drivers/acpi/executer/exregion.c
+++ b/drivers/acpi/executer/exregion.c
@@ -81,7 +81,7 @@ acpi_ex_system_memory_space_handler(u32 function,
u32 remainder;
#endif
- ACPI_FUNCTION_TRACE("ex_system_memory_space_handler");
+ ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
/* Validate and translate the bit width */
@@ -103,7 +103,7 @@ acpi_ex_system_memory_space_handler(u32 function,
break;
default:
- ACPI_ERROR((AE_INFO, "Invalid system_memory width %d",
+ ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %d",
bit_width));
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
@@ -135,6 +135,7 @@ acpi_ex_system_memory_space_handler(u32 function,
* Delete the existing mapping and create a new one.
*/
if (mem_info->mapped_length) {
+
/* Valid mapping, delete it */
acpi_os_unmap_memory(mem_info->mapped_logical_address,
@@ -181,8 +182,8 @@ acpi_ex_system_memory_space_handler(u32 function,
(acpi_integer) mem_info->mapped_physical_address);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "system_memory %d (%d width) Address=%8.8X%8.8X\n",
- function, bit_width, ACPI_FORMAT_UINT64(address)));
+ "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n",
+ bit_width, function, ACPI_FORMAT_UINT64(address)));
/*
* Perform the memory read or write
@@ -283,11 +284,11 @@ acpi_ex_system_io_space_handler(u32 function,
acpi_status status = AE_OK;
u32 value32;
- ACPI_FUNCTION_TRACE("ex_system_io_space_handler");
+ ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "system_iO %d (%d width) Address=%8.8X%8.8X\n",
- function, bit_width, ACPI_FORMAT_UINT64(address)));
+ "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n",
+ bit_width, function, ACPI_FORMAT_UINT64(address)));
/* Decode the function parameter */
@@ -342,7 +343,7 @@ acpi_ex_pci_config_space_handler(u32 function,
struct acpi_pci_id *pci_id;
u16 pci_register;
- ACPI_FUNCTION_TRACE("ex_pci_config_space_handler");
+ ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
/*
* The arguments to acpi_os(Read|Write)pci_configuration are:
@@ -360,7 +361,7 @@ acpi_ex_pci_config_space_handler(u32 function,
pci_register = (u16) (u32) address;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
+ "Pci-Config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
function, bit_width, pci_id->segment, pci_id->bus,
pci_id->device, pci_id->function, pci_register));
@@ -414,7 +415,7 @@ acpi_ex_cmos_space_handler(u32 function,
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ex_cmos_space_handler");
+ ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
return_ACPI_STATUS(status);
}
@@ -446,7 +447,7 @@ acpi_ex_pci_bar_space_handler(u32 function,
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ex_pci_bar_space_handler");
+ ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
return_ACPI_STATUS(status);
}
@@ -476,23 +477,16 @@ acpi_ex_data_table_space_handler(u32 function,
acpi_integer * value,
void *handler_context, void *region_context)
{
- acpi_status status = AE_OK;
- u32 byte_width = ACPI_DIV_8(bit_width);
- u32 i;
- char *logical_addr_ptr;
-
- ACPI_FUNCTION_TRACE("ex_data_table_space_handler");
-
- logical_addr_ptr = ACPI_PHYSADDR_TO_PTR(address);
+ ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
/* Perform the memory read or write */
switch (function) {
case ACPI_READ:
- for (i = 0; i < byte_width; i++) {
- ((char *)value)[i] = logical_addr_ptr[i];
- }
+ ACPI_MEMCPY(ACPI_CAST_PTR(char, value),
+ ACPI_PHYSADDR_TO_PTR(address),
+ ACPI_DIV_8(bit_width));
break;
case ACPI_WRITE:
@@ -501,5 +495,5 @@ acpi_ex_data_table_space_handler(u32 function,
return_ACPI_STATUS(AE_SUPPORT);
}
- return_ACPI_STATUS(status);
+ return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c
index 01b26c80d22..3089b05a136 100644
--- a/drivers/acpi/executer/exresnte.c
+++ b/drivers/acpi/executer/exresnte.c
@@ -87,7 +87,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
struct acpi_namespace_node *node;
acpi_object_type entry_type;
- ACPI_FUNCTION_TRACE("ex_resolve_node_to_value");
+ ACPI_FUNCTION_TRACE(ex_resolve_node_to_value);
/*
* The stack pointer points to a struct acpi_namespace_node (Node). Get the
@@ -97,12 +97,13 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
source_desc = acpi_ns_get_attached_object(node);
entry_type = acpi_ns_get_type((acpi_handle) node);
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n",
node, source_desc,
acpi_ut_get_type_name(entry_type)));
if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) ||
(entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
+
/* There is always exactly one level of indirection */
node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object);
@@ -113,10 +114,11 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
/*
* Several object types require no further processing:
- * 1) Devices rarely have an attached object, return the Node
+ * 1) Device/Thermal objects don't have a "real" subobject, return the Node
* 2) Method locals and arguments have a pseudo-Node
*/
- if (entry_type == ACPI_TYPE_DEVICE ||
+ if ((entry_type == ACPI_TYPE_DEVICE) ||
+ (entry_type == ACPI_TYPE_THERMAL) ||
(node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
return_ACPI_STATUS(AE_OK);
}
@@ -141,6 +143,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
status = acpi_ds_get_package_arguments(source_desc);
if (ACPI_SUCCESS(status)) {
+
/* Return an additional reference to the object */
obj_desc = source_desc;
@@ -158,6 +161,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
status = acpi_ds_get_buffer_arguments(source_desc);
if (ACPI_SUCCESS(status)) {
+
/* Return an additional reference to the object */
obj_desc = source_desc;
@@ -199,7 +203,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
case ACPI_TYPE_LOCAL_INDEX_FIELD:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "field_read Node=%p source_desc=%p Type=%X\n",
+ "FieldRead Node=%p SourceDesc=%p Type=%X\n",
node, source_desc, entry_type));
status =
@@ -213,7 +217,6 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
case ACPI_TYPE_METHOD:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
- case ACPI_TYPE_THERMAL:
case ACPI_TYPE_EVENT:
case ACPI_TYPE_REGION:
@@ -240,6 +243,8 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
/* This is a ddb_handle */
/* Return an additional reference to the object */
+ case AML_REF_OF_OP:
+
obj_desc = source_desc;
acpi_ut_add_reference(obj_desc);
break;
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
index 1deed492fe8..6499de87801 100644
--- a/drivers/acpi/executer/exresolv.c
+++ b/drivers/acpi/executer/exresolv.c
@@ -78,7 +78,7 @@ acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
{
acpi_status status;
- ACPI_FUNCTION_TRACE_PTR("ex_resolve_to_value", stack_ptr);
+ ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr);
if (!stack_ptr || !*stack_ptr) {
ACPI_ERROR((AE_INFO, "Internal - null pointer"));
@@ -144,7 +144,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
union acpi_operand_object *obj_desc;
u16 opcode;
- ACPI_FUNCTION_TRACE("ex_resolve_object_to_value");
+ ACPI_FUNCTION_TRACE(ex_resolve_object_to_value);
stack_desc = *stack_ptr;
@@ -190,7 +190,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "[Arg/Local %X] value_obj is %p\n",
+ "[Arg/Local %X] ValueObj is %p\n",
stack_desc->reference.offset,
obj_desc));
@@ -239,7 +239,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
/* Invalid reference object */
ACPI_ERROR((AE_INFO,
- "Unknown target_type %X in Index/Reference obj %p",
+ "Unknown TargetType %X in Index/Reference obj %p",
stack_desc->reference.target_type,
stack_desc));
status = AE_AML_INTERNAL;
@@ -257,10 +257,24 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
case AML_INT_NAMEPATH_OP: /* Reference to a named object */
- /* Get the object pointed to by the namespace node */
+ /* Dereference the name */
+
+ if ((stack_desc->reference.node->type ==
+ ACPI_TYPE_DEVICE)
+ || (stack_desc->reference.node->type ==
+ ACPI_TYPE_THERMAL)) {
+
+ /* These node types do not have 'real' subobjects */
+
+ *stack_ptr = (void *)stack_desc->reference.node;
+ } else {
+ /* Get the object pointed to by the namespace node */
+
+ *stack_ptr =
+ (stack_desc->reference.node)->object;
+ acpi_ut_add_reference(*stack_ptr);
+ }
- *stack_ptr = (stack_desc->reference.node)->object;
- acpi_ut_add_reference(*stack_ptr);
acpi_ut_remove_reference(stack_desc);
break;
@@ -293,7 +307,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
case ACPI_TYPE_LOCAL_INDEX_FIELD:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "field_read source_desc=%p Type=%X\n",
+ "FieldRead SourceDesc=%p Type=%X\n",
stack_desc,
ACPI_GET_OBJECT_TYPE(stack_desc)));
@@ -337,7 +351,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
acpi_object_type type;
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_ex_resolve_multiple");
+ ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple);
/* Operand can be either a namespace node or an operand descriptor */
@@ -382,10 +396,16 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
switch (obj_desc->reference.opcode) {
case AML_REF_OF_OP:
+ case AML_INT_NAMEPATH_OP:
/* Dereference the reference pointer */
- node = obj_desc->reference.object;
+ if (obj_desc->reference.opcode == AML_REF_OF_OP) {
+ node = obj_desc->reference.object;
+ } else { /* AML_INT_NAMEPATH_OP */
+
+ node = obj_desc->reference.node;
+ }
/* All "References" point to a NS node */
@@ -401,6 +421,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
+
/* No object, use the NS node type */
type = acpi_ns_get_type(node);
@@ -432,6 +453,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
*/
obj_desc = *(obj_desc->reference.where);
if (!obj_desc) {
+
/* NULL package elements are allowed */
type = 0; /* Uninitialized */
@@ -439,39 +461,6 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
}
break;
- case AML_INT_NAMEPATH_OP:
-
- /* Dereference the reference pointer */
-
- node = obj_desc->reference.node;
-
- /* All "References" point to a NS node */
-
- if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
- ACPI_DESC_TYPE_NAMED) {
- ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]",
- node,
- acpi_ut_get_descriptor_name(node)));
- return_ACPI_STATUS(AE_AML_INTERNAL);
- }
-
- /* Get the attached object */
-
- obj_desc = acpi_ns_get_attached_object(node);
- if (!obj_desc) {
- /* No object, use the NS node type */
-
- type = acpi_ns_get_type(node);
- goto exit;
- }
-
- /* Check for circular references */
-
- if (obj_desc == operand) {
- return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
- }
- break;
-
case AML_LOCAL_OP:
case AML_ARG_OP:
@@ -513,7 +502,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
case AML_DEBUG_OP:
- /* The Debug Object is of type "debug_object" */
+ /* The Debug Object is of type "DebugObject" */
type = ACPI_TYPE_DEBUG_OBJECT;
goto exit;
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c
index a1c000f5a41..4c93d097233 100644
--- a/drivers/acpi/executer/exresop.c
+++ b/drivers/acpi/executer/exresop.c
@@ -77,6 +77,7 @@ acpi_ex_check_object_type(acpi_object_type type_needed,
ACPI_FUNCTION_ENTRY();
if (type_needed == ACPI_TYPE_ANY) {
+
/* All types OK, so we don't perform any typechecks */
return (AE_OK);
@@ -143,7 +144,7 @@ acpi_ex_resolve_operands(u16 opcode,
acpi_object_type type_needed;
u16 target_op = 0;
- ACPI_FUNCTION_TRACE_U32("ex_resolve_operands", opcode);
+ ACPI_FUNCTION_TRACE_U32(ex_resolve_operands, opcode);
op_info = acpi_ps_get_opcode_info(opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
@@ -158,7 +159,7 @@ acpi_ex_resolve_operands(u16 opcode,
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Opcode %X [%s] required_operand_types=%8.8X\n",
+ "Opcode %X [%s] RequiredOperandTypes=%8.8X\n",
opcode, op_info->name, arg_types));
/*
@@ -224,6 +225,7 @@ acpi_ex_resolve_operands(u16 opcode,
}
if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) {
+
/* Decode the Reference */
op_info = acpi_ps_get_opcode_info(opcode);
@@ -247,7 +249,7 @@ acpi_ex_resolve_operands(u16 opcode,
ACPI_DEBUG_ONLY_MEMBERS(ACPI_DEBUG_PRINT
((ACPI_DB_EXEC,
- "Operand is a Reference, ref_opcode [%s]\n",
+ "Operand is a Reference, RefOpcode [%s]\n",
(acpi_ps_get_opcode_info
(obj_desc->
reference.
@@ -332,6 +334,7 @@ acpi_ex_resolve_operands(u16 opcode,
}
if (obj_desc->reference.opcode == AML_NAME_OP) {
+
/* Convert a named reference to the actual named object */
temp_node = obj_desc->reference.object;
@@ -623,7 +626,7 @@ acpi_ex_resolve_operands(u16 opcode,
default:
ACPI_ERROR((AE_INFO,
- "Needed [Region/region_field], found [%s] %p",
+ "Needed [Region/RegionField], found [%s] %p",
acpi_ut_get_object_type_name
(obj_desc), obj_desc));
@@ -662,6 +665,7 @@ acpi_ex_resolve_operands(u16 opcode,
}
if (target_op == AML_DEBUG_OP) {
+
/* Allow store of any object to the Debug object */
break;
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
index 3f020c0e2b9..0456405ba01 100644
--- a/drivers/acpi/executer/exstore.c
+++ b/drivers/acpi/executer/exstore.c
@@ -82,7 +82,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
{
u32 i;
- ACPI_FUNCTION_TRACE_PTR("ex_do_debug_object", source_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc);
ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s",
level, " "));
@@ -245,7 +245,7 @@ acpi_ex_store(union acpi_operand_object *source_desc,
acpi_status status = AE_OK;
union acpi_operand_object *ref_desc = dest_desc;
- ACPI_FUNCTION_TRACE_PTR("ex_store", dest_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc);
/* Validate parameters */
@@ -297,7 +297,7 @@ acpi_ex_store(union acpi_operand_object *source_desc,
ACPI_DUMP_STACK_ENTRY(source_desc);
ACPI_DUMP_STACK_ENTRY(dest_desc);
- ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ex_store",
+ ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ExStore",
2,
"Target is not a Reference or Constant object");
@@ -396,7 +396,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
u8 value = 0;
u32 i;
- ACPI_FUNCTION_TRACE("ex_store_object_to_index");
+ ACPI_FUNCTION_TRACE(ex_store_object_to_index);
/*
* Destination must be a reference pointer, and
@@ -423,6 +423,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
}
if (obj_desc) {
+
/* Decrement reference count by the ref count of the parent package */
for (i = 0; i < ((union acpi_operand_object *)
@@ -502,8 +503,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
break;
default:
- ACPI_ERROR((AE_INFO,
- "Target is not a Package or buffer_field"));
+ ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField"));
status = AE_AML_OPERAND_TYPE;
break;
}
@@ -548,7 +548,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
union acpi_operand_object *new_desc;
acpi_object_type target_type;
- ACPI_FUNCTION_TRACE_PTR("ex_store_object_to_node", source_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc);
/* Get current type of the node, and object attached to Node */
@@ -572,6 +572,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
/* If no implicit conversion, drop into the default case below */
if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) {
+
/* Force execution of default (no implicit conversion) */
target_type = ACPI_TYPE_ANY;
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
index 42967baf760..591aaf0e18b 100644
--- a/drivers/acpi/executer/exstoren.c
+++ b/drivers/acpi/executer/exstoren.c
@@ -72,7 +72,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
union acpi_operand_object *source_desc = *source_desc_ptr;
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ex_resolve_object");
+ ACPI_FUNCTION_TRACE(ex_resolve_object);
/* Ensure we have a Target that can be stored to */
@@ -97,6 +97,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
*/
if (ACPI_GET_OBJECT_TYPE(source_desc) ==
ACPI_TYPE_LOCAL_REFERENCE) {
+
/* Resolve a reference object first */
status =
@@ -121,6 +122,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
!((ACPI_GET_OBJECT_TYPE(source_desc) ==
ACPI_TYPE_LOCAL_REFERENCE)
&& (source_desc->reference.opcode == AML_LOAD_OP))) {
+
/* Conversion successful but still not a valid type */
ACPI_ERROR((AE_INFO,
@@ -199,7 +201,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc,
union acpi_operand_object *actual_src_desc;
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE_PTR("ex_store_object_to_object", source_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_object, source_desc);
actual_src_desc = source_desc;
if (!dest_desc) {
@@ -289,6 +291,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc,
}
if (actual_src_desc != source_desc) {
+
/* Delete the intermediate (temporary) source object */
acpi_ut_remove_reference(actual_src_desc);
diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c
index 6ab70708775..99ebe5adfcd 100644
--- a/drivers/acpi/executer/exstorob.c
+++ b/drivers/acpi/executer/exstorob.c
@@ -67,7 +67,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
u32 length;
u8 *buffer;
- ACPI_FUNCTION_TRACE_PTR("ex_store_buffer_to_buffer", source_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc);
/* We know that source_desc is a buffer by now */
@@ -80,7 +80,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
*/
if ((target_desc->buffer.length == 0) ||
(target_desc->common.flags & AOPOBJ_STATIC_POINTER)) {
- target_desc->buffer.pointer = ACPI_MEM_ALLOCATE(length);
+ target_desc->buffer.pointer = ACPI_ALLOCATE(length);
if (!target_desc->buffer.pointer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -91,6 +91,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
/* Copy source buffer to target buffer */
if (length <= target_desc->buffer.length) {
+
/* Clear existing buffer and copy in the new one */
ACPI_MEMSET(target_desc->buffer.pointer, 0,
@@ -102,7 +103,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
* NOTE: ACPI versions up to 3.0 specified that the buffer must be
* truncated if the string is smaller than the buffer. However, "other"
* implementations of ACPI never did this and thus became the defacto
- * standard. ACPi 3.0_a changes this behavior such that the buffer
+ * standard. ACPI 3.0_a changes this behavior such that the buffer
* is no longer truncated.
*/
@@ -113,6 +114,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
* copy must not truncate the original buffer.
*/
if (original_src_type == ACPI_TYPE_STRING) {
+
/* Set the new length of the target */
target_desc->buffer.length = length;
@@ -156,7 +158,7 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
u32 length;
u8 *buffer;
- ACPI_FUNCTION_TRACE_PTR("ex_store_string_to_string", source_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc);
/* We know that source_desc is a string by now */
@@ -183,13 +185,14 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
*/
if (target_desc->string.pointer &&
(!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
+
/* Only free if not a pointer into the DSDT */
- ACPI_MEM_FREE(target_desc->string.pointer);
+ ACPI_FREE(target_desc->string.pointer);
}
- target_desc->string.pointer = ACPI_MEM_CALLOCATE((acpi_size)
- length + 1);
+ target_desc->string.pointer = ACPI_ALLOCATE_ZEROED((acpi_size)
+ length + 1);
if (!target_desc->string.pointer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
index ea9144f42e1..52beee3674a 100644
--- a/drivers/acpi/executer/exsystem.c
+++ b/drivers/acpi/executer/exsystem.c
@@ -68,7 +68,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_handle semaphore, u16 timeout)
acpi_status status;
acpi_status status2;
- ACPI_FUNCTION_TRACE("ex_system_wait_semaphore");
+ ACPI_FUNCTION_TRACE(ex_system_wait_semaphore);
status = acpi_os_wait_semaphore(semaphore, 1, 0);
if (ACPI_SUCCESS(status)) {
@@ -76,6 +76,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_handle semaphore, u16 timeout)
}
if (status == AE_TIME) {
+
/* We must wait, so unlock the interpreter */
acpi_ex_exit_interpreter();
@@ -90,6 +91,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_handle semaphore, u16 timeout)
status2 = acpi_ex_enter_interpreter();
if (ACPI_FAILURE(status2)) {
+
/* Report fatal error, could not acquire interpreter */
return_ACPI_STATUS(status2);
@@ -191,7 +193,7 @@ acpi_ex_system_acquire_mutex(union acpi_operand_object * time_desc,
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE_PTR("ex_system_acquire_mutex", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ex_system_acquire_mutex, obj_desc);
if (!obj_desc) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -229,7 +231,7 @@ acpi_status acpi_ex_system_release_mutex(union acpi_operand_object *obj_desc)
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ex_system_release_mutex");
+ ACPI_FUNCTION_TRACE(ex_system_release_mutex);
if (!obj_desc) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -263,7 +265,7 @@ acpi_status acpi_ex_system_signal_event(union acpi_operand_object *obj_desc)
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ex_system_signal_event");
+ ACPI_FUNCTION_TRACE(ex_system_signal_event);
if (obj_desc) {
status = acpi_os_signal_semaphore(obj_desc->event.semaphore, 1);
@@ -293,7 +295,7 @@ acpi_ex_system_wait_event(union acpi_operand_object *time_desc,
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ex_system_wait_event");
+ ACPI_FUNCTION_TRACE(ex_system_wait_event);
if (obj_desc) {
status =
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
index f73a61aeb7e..982c8b65876 100644
--- a/drivers/acpi/executer/exutils.c
+++ b/drivers/acpi/executer/exutils.c
@@ -87,9 +87,9 @@ acpi_status acpi_ex_enter_interpreter(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ex_enter_interpreter");
+ ACPI_FUNCTION_TRACE(ex_enter_interpreter);
- status = acpi_ut_acquire_mutex(ACPI_MTX_EXECUTE);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex"));
}
@@ -123,9 +123,9 @@ void acpi_ex_exit_interpreter(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ex_exit_interpreter");
+ ACPI_FUNCTION_TRACE(ex_exit_interpreter);
- status = acpi_ut_release_mutex(ACPI_MTX_EXECUTE);
+ status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "Could not release interpreter mutex"));
}
@@ -189,11 +189,12 @@ u8 acpi_ex_acquire_global_lock(u32 field_flags)
u8 locked = FALSE;
acpi_status status;
- ACPI_FUNCTION_TRACE("ex_acquire_global_lock");
+ ACPI_FUNCTION_TRACE(ex_acquire_global_lock);
/* Only attempt lock if the always_lock bit is set */
if (field_flags & AML_FIELD_LOCK_RULE_MASK) {
+
/* We should attempt to get the lock, wait forever */
status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER);
@@ -225,15 +226,17 @@ void acpi_ex_release_global_lock(u8 locked_by_me)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ex_release_global_lock");
+ ACPI_FUNCTION_TRACE(ex_release_global_lock);
/* Only attempt unlock if the caller locked it */
if (locked_by_me) {
+
/* OK, now release the lock */
status = acpi_ev_release_global_lock();
if (ACPI_FAILURE(status)) {
+
/* Report the error, but there isn't much else we can do */
ACPI_EXCEPTION((AE_INFO, status,
@@ -263,7 +266,7 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base)
u32 num_digits;
acpi_integer current_value;
- ACPI_FUNCTION_TRACE("ex_digits_needed");
+ ACPI_FUNCTION_TRACE(ex_digits_needed);
/* acpi_integer is unsigned, so we don't worry about a '-' prefix */
diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c
index ea2f13271ff..de50fab2a91 100644
--- a/drivers/acpi/hardware/hwacpi.c
+++ b/drivers/acpi/hardware/hwacpi.c
@@ -63,7 +63,7 @@ acpi_status acpi_hw_initialize(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("hw_initialize");
+ ACPI_FUNCTION_TRACE(hw_initialize);
/* We must have the ACPI tables by the time we get here */
@@ -100,7 +100,7 @@ acpi_status acpi_hw_set_mode(u32 mode)
acpi_status status;
u32 retry;
- ACPI_FUNCTION_TRACE("hw_set_mode");
+ ACPI_FUNCTION_TRACE(hw_set_mode);
/*
* ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
@@ -198,7 +198,7 @@ u32 acpi_hw_get_mode(void)
acpi_status status;
u32 value;
- ACPI_FUNCTION_TRACE("hw_get_mode");
+ ACPI_FUNCTION_TRACE(hw_get_mode);
/*
* ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
index d84942d22dd..608a3a60ee1 100644
--- a/drivers/acpi/hardware/hwgpe.c
+++ b/drivers/acpi/hardware/hwgpe.c
@@ -214,6 +214,7 @@ acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
+
/* Disable all GPEs in this register */
status = acpi_hw_low_level_write(8, 0x00,
@@ -250,6 +251,7 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
+
/* Clear status on all GPEs in this register */
status = acpi_hw_low_level_write(8, 0xFF,
@@ -368,7 +370,7 @@ acpi_status acpi_hw_disable_all_gpes(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("hw_disable_all_gpes");
+ ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block);
status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
@@ -391,7 +393,7 @@ acpi_status acpi_hw_enable_all_runtime_gpes(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("hw_enable_all_runtime_gpes");
+ ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block);
return_ACPI_STATUS(status);
@@ -413,7 +415,7 @@ acpi_status acpi_hw_enable_all_wakeup_gpes(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("hw_enable_all_wakeup_gpes");
+ ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block);
return_ACPI_STATUS(status);
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
index e1fe7549841..ae142de1950 100644
--- a/drivers/acpi/hardware/hwregs.c
+++ b/drivers/acpi/hardware/hwregs.c
@@ -43,8 +43,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
@@ -63,23 +61,21 @@ ACPI_MODULE_NAME("hwregs")
* DESCRIPTION: Clears all fixed and general purpose status bits
* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
*
+ * NOTE: TBD: Flags parameter is obsolete, to be removed
+ *
******************************************************************************/
acpi_status acpi_hw_clear_acpi_status(u32 flags)
{
acpi_status status;
+ acpi_cpu_flags lock_flags = 0;
- ACPI_FUNCTION_TRACE("hw_clear_acpi_status");
+ ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n",
ACPI_BITMASK_ALL_FIXED_STATUS,
(u16) acpi_gbl_FADT->xpm1a_evt_blk.address));
- if (flags & ACPI_MTX_LOCK) {
- status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
+ lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
ACPI_REGISTER_PM1_STATUS,
@@ -104,9 +100,7 @@ acpi_status acpi_hw_clear_acpi_status(u32 flags)
status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
unlock_and_exit:
- if (flags & ACPI_MTX_LOCK) {
- (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
- }
+ acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
return_ACPI_STATUS(status);
}
@@ -129,10 +123,9 @@ acpi_status
acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
{
acpi_status status = AE_OK;
- struct acpi_parameter_info info;
- char *sleep_state_name;
+ struct acpi_evaluate_info *info;
- ACPI_FUNCTION_TRACE("acpi_get_sleep_type_data");
+ ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data);
/* Validate parameters */
@@ -140,34 +133,39 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- /* Evaluate the namespace object containing the values for this state */
+ /* Allocate the evaluation information block */
+
+ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+ if (!info) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
- info.parameters = NULL;
- info.return_object = NULL;
- sleep_state_name =
+ info->pathname =
ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
- status = acpi_ns_evaluate_by_name(sleep_state_name, &info);
+ /* Evaluate the namespace object containing the values for this state */
+
+ status = acpi_ns_evaluate(info);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "%s while evaluating sleep_state [%s]\n",
+ "%s while evaluating SleepState [%s]\n",
acpi_format_exception(status),
- sleep_state_name));
+ info->pathname));
- return_ACPI_STATUS(status);
+ goto cleanup;
}
/* Must have a return object */
- if (!info.return_object) {
+ if (!info->return_object) {
ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
- sleep_state_name));
+ info->pathname));
status = AE_NOT_EXIST;
}
/* It must be of type Package */
- else if (ACPI_GET_OBJECT_TYPE(info.return_object) != ACPI_TYPE_PACKAGE) {
+ else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) {
ACPI_ERROR((AE_INFO,
"Sleep State return object is not a Package"));
status = AE_AML_OPERAND_TYPE;
@@ -180,7 +178,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
* by BIOS vendors seems to be to have 2 or more elements, at least
* one per sleep type (A/B).
*/
- else if (info.return_object->package.count < 2) {
+ else if (info->return_object->package.count < 2) {
ACPI_ERROR((AE_INFO,
"Sleep State return package does not have at least two elements"));
status = AE_AML_NO_OPERAND;
@@ -188,39 +186,42 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
/* The first two elements must both be of type Integer */
- else if ((ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[0])
+ else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0])
!= ACPI_TYPE_INTEGER) ||
- (ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[1])
+ (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1])
!= ACPI_TYPE_INTEGER)) {
ACPI_ERROR((AE_INFO,
"Sleep State return package elements are not both Integers (%s, %s)",
- acpi_ut_get_object_type_name(info.return_object->
+ acpi_ut_get_object_type_name(info->return_object->
package.elements[0]),
- acpi_ut_get_object_type_name(info.return_object->
+ acpi_ut_get_object_type_name(info->return_object->
package.elements[1])));
status = AE_AML_OPERAND_TYPE;
} else {
/* Valid _Sx_ package size, type, and value */
*sleep_type_a = (u8)
- (info.return_object->package.elements[0])->integer.value;
+ (info->return_object->package.elements[0])->integer.value;
*sleep_type_b = (u8)
- (info.return_object->package.elements[1])->integer.value;
+ (info->return_object->package.elements[1])->integer.value;
}
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
- "While evaluating sleep_state [%s], bad Sleep object %p type %s",
- sleep_state_name, info.return_object,
- acpi_ut_get_object_type_name(info.
+ "While evaluating SleepState [%s], bad Sleep object %p type %s",
+ info->pathname, info->return_object,
+ acpi_ut_get_object_type_name(info->
return_object)));
}
- acpi_ut_remove_reference(info.return_object);
+ acpi_ut_remove_reference(info->return_object);
+
+ cleanup:
+ ACPI_FREE(info);
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_sleep_type_data);
+ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data)
/*******************************************************************************
*
@@ -233,13 +234,12 @@ EXPORT_SYMBOL(acpi_get_sleep_type_data);
* DESCRIPTION: Map register_id into a register bitmask.
*
******************************************************************************/
-
struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
{
ACPI_FUNCTION_ENTRY();
if (register_id > ACPI_BITREG_MAX) {
- ACPI_ERROR((AE_INFO, "Invalid bit_register ID: %X",
+ ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X",
register_id));
return (NULL);
}
@@ -260,6 +260,8 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
*
* DESCRIPTION: ACPI bit_register read function.
*
+ * NOTE: TBD: Flags parameter is obsolete, to be removed
+ *
******************************************************************************/
acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags)
@@ -268,7 +270,7 @@ acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags)
struct acpi_bit_register_info *bit_reg_info;
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_get_register");
+ ACPI_FUNCTION_TRACE(acpi_get_register);
/* Get the info structure corresponding to the requested ACPI Register */
@@ -277,24 +279,14 @@ acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags)
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- if (flags & ACPI_MTX_LOCK) {
- status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
-
/* Read from the register */
- status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+ status = acpi_hw_register_read(ACPI_MTX_LOCK,
bit_reg_info->parent_register,
&register_value);
- if (flags & ACPI_MTX_LOCK) {
- (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
- }
-
if (ACPI_SUCCESS(status)) {
+
/* Normalize the value that was read */
register_value =
@@ -311,7 +303,7 @@ acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags)
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_register);
+ACPI_EXPORT_SYMBOL(acpi_get_register)
/*******************************************************************************
*
@@ -326,31 +318,28 @@ EXPORT_SYMBOL(acpi_get_register);
*
* DESCRIPTION: ACPI Bit Register write function.
*
+ * NOTE: TBD: Flags parameter is obsolete, to be removed
+ *
******************************************************************************/
-
acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
{
u32 register_value = 0;
struct acpi_bit_register_info *bit_reg_info;
acpi_status status;
+ acpi_cpu_flags lock_flags;
- ACPI_FUNCTION_TRACE_U32("acpi_set_register", register_id);
+ ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id);
/* Get the info structure corresponding to the requested ACPI Register */
bit_reg_info = acpi_hw_get_bit_register_info(register_id);
if (!bit_reg_info) {
- ACPI_ERROR((AE_INFO, "Bad ACPI HW register_id: %X",
+ ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X",
register_id));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- if (flags & ACPI_MTX_LOCK) {
- status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
+ lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
/* Always do a register read first so we can insert the new bits */
@@ -458,9 +447,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
unlock_and_exit:
- if (flags & ACPI_MTX_LOCK) {
- (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
- }
+ acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
/* Normalize the value that was read */
@@ -474,7 +461,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_set_register);
+ACPI_EXPORT_SYMBOL(acpi_set_register)
/******************************************************************************
*
@@ -490,21 +477,18 @@ EXPORT_SYMBOL(acpi_set_register);
* given offset.
*
******************************************************************************/
-
acpi_status
acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
{
u32 value1 = 0;
u32 value2 = 0;
acpi_status status;
+ acpi_cpu_flags lock_flags = 0;
- ACPI_FUNCTION_TRACE("hw_register_read");
+ ACPI_FUNCTION_TRACE(hw_register_read);
if (ACPI_MTX_LOCK == use_lock) {
- status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
+ lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
}
switch (register_id) {
@@ -582,7 +566,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
unlock_and_exit:
if (ACPI_MTX_LOCK == use_lock) {
- (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
+ acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
}
if (ACPI_SUCCESS(status)) {
@@ -610,14 +594,12 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
{
acpi_status status;
+ acpi_cpu_flags lock_flags = 0;
- ACPI_FUNCTION_TRACE("hw_register_write");
+ ACPI_FUNCTION_TRACE(hw_register_write);
if (ACPI_MTX_LOCK == use_lock) {
- status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
+ lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
}
switch (register_id) {
@@ -707,7 +689,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
unlock_and_exit:
if (ACPI_MTX_LOCK == use_lock) {
- (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
+ acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
}
return_ACPI_STATUS(status);
@@ -733,7 +715,7 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
u64 address;
acpi_status status;
- ACPI_FUNCTION_NAME("hw_low_level_read");
+ ACPI_FUNCTION_NAME(hw_low_level_read);
/*
* Must have a valid pointer to a GAS structure, and
@@ -805,7 +787,7 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
u64 address;
acpi_status status;
- ACPI_FUNCTION_NAME("hw_low_level_write");
+ ACPI_FUNCTION_NAME(hw_low_level_write);
/*
* Must have a valid pointer to a GAS structure, and
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index 89269272fd6..8bb43cae60c 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
#include <acpi/acpi.h>
#define _COMPONENT ACPI_HARDWARE
@@ -64,7 +63,7 @@ acpi_status
acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
{
- ACPI_FUNCTION_TRACE("acpi_set_firmware_waking_vector");
+ ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
/* Set the vector */
@@ -79,6 +78,8 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
return_ACPI_STATUS(AE_OK);
}
+ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
+
/*******************************************************************************
*
* FUNCTION: acpi_get_firmware_waking_vector
@@ -92,13 +93,12 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
* DESCRIPTION: Access function for the firmware_waking_vector field in FACS
*
******************************************************************************/
-
#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
{
- ACPI_FUNCTION_TRACE("acpi_get_firmware_waking_vector");
+ ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector);
if (!physical_address) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -118,6 +118,8 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
return_ACPI_STATUS(AE_OK);
}
+
+ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector)
#endif
/*******************************************************************************
@@ -134,14 +136,13 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
* various OS-specific tasks between the two steps.
*
******************************************************************************/
-
acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
{
acpi_status status;
struct acpi_object_list arg_list;
union acpi_object arg;
- ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_prep");
+ ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep);
/*
* _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
@@ -206,6 +207,8 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
return_ACPI_STATUS(AE_OK);
}
+ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
+
/*******************************************************************************
*
* FUNCTION: acpi_enter_sleep_state
@@ -218,7 +221,6 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
*
******************************************************************************/
-
acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
{
u32 PM1Acontrol;
@@ -228,7 +230,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
u32 in_value;
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_enter_sleep_state");
+ ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);
if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
(acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
@@ -378,7 +380,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_enter_sleep_state);
+ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)
/*******************************************************************************
*
@@ -392,13 +394,12 @@ EXPORT_SYMBOL(acpi_enter_sleep_state);
* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
*
******************************************************************************/
-
acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)
{
u32 in_value;
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_s4bios");
+ ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios);
status =
acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
@@ -443,7 +444,7 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)
return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios);
+ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
/*******************************************************************************
*
@@ -457,7 +458,6 @@ EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios);
* Called with interrupts ENABLED.
*
******************************************************************************/
-
acpi_status acpi_leave_sleep_state(u8 sleep_state)
{
struct acpi_object_list arg_list;
@@ -468,7 +468,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
u32 PM1Acontrol;
u32 PM1Bcontrol;
- ACPI_FUNCTION_TRACE("acpi_leave_sleep_state");
+ ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
/*
* Set SLP_TYPE and SLP_EN to state S0.
@@ -490,6 +490,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
ACPI_REGISTER_PM1_CONTROL,
&PM1Acontrol);
if (ACPI_SUCCESS(status)) {
+
/* Clear SLP_EN and SLP_TYP fields */
PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
@@ -583,3 +584,5 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
return_ACPI_STATUS(status);
}
+
+ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state)
diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c
index fc10b7cb456..c4ec47c939f 100644
--- a/drivers/acpi/hardware/hwtimer.c
+++ b/drivers/acpi/hardware/hwtimer.c
@@ -42,7 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
#include <acpi/acpi.h>
#define _COMPONENT ACPI_HARDWARE
@@ -61,13 +60,13 @@ ACPI_MODULE_NAME("hwtimer")
******************************************************************************/
acpi_status acpi_get_timer_resolution(u32 * resolution)
{
- ACPI_FUNCTION_TRACE("acpi_get_timer_resolution");
+ ACPI_FUNCTION_TRACE(acpi_get_timer_resolution);
if (!resolution) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- if (0 == acpi_gbl_FADT->tmr_val_ext) {
+ if (acpi_gbl_FADT->tmr_val_ext == 0) {
*resolution = 24;
} else {
*resolution = 32;
@@ -76,6 +75,8 @@ acpi_status acpi_get_timer_resolution(u32 * resolution)
return_ACPI_STATUS(AE_OK);
}
+ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution)
+
/******************************************************************************
*
* FUNCTION: acpi_get_timer
@@ -87,12 +88,11 @@ acpi_status acpi_get_timer_resolution(u32 * resolution)
* DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
*
******************************************************************************/
-
acpi_status acpi_get_timer(u32 * ticks)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_get_timer");
+ ACPI_FUNCTION_TRACE(acpi_get_timer);
if (!ticks) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -103,7 +103,7 @@ acpi_status acpi_get_timer(u32 * ticks)
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_timer);
+ACPI_EXPORT_SYMBOL(acpi_get_timer)
/******************************************************************************
*
@@ -133,7 +133,6 @@ EXPORT_SYMBOL(acpi_get_timer);
* 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
*
******************************************************************************/
-
acpi_status
acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
{
@@ -141,7 +140,7 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
u32 delta_ticks;
acpi_integer quotient;
- ACPI_FUNCTION_TRACE("acpi_get_timer_duration");
+ ACPI_FUNCTION_TRACE(acpi_get_timer_duration);
if (!time_elapsed) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -154,7 +153,8 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
if (start_ticks < end_ticks) {
delta_ticks = end_ticks - start_ticks;
} else if (start_ticks > end_ticks) {
- if (0 == acpi_gbl_FADT->tmr_val_ext) {
+ if (acpi_gbl_FADT->tmr_val_ext == 0) {
+
/* 24-bit Timer */
delta_ticks =
@@ -183,4 +183,4 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_timer_duration);
+ACPI_EXPORT_SYMBOL(acpi_get_timer_duration)
diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c
index 468244147ec..d51d68f5dd8 100644
--- a/drivers/acpi/motherboard.c
+++ b/drivers/acpi/motherboard.c
@@ -37,7 +37,7 @@ ACPI_MODULE_NAME("acpi_motherboard")
#define ACPI_MB_HID2 "PNP0C02"
/**
* Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved
- * Doesn't care about the failure of 'request_region', since other may reserve
+ * Doesn't care about the failure of 'request_region', since other may reserve
* the io ports as well
*/
#define IS_RESERVED_ADDR(base, len) \
@@ -46,7 +46,7 @@ ACPI_MODULE_NAME("acpi_motherboard")
/*
* Clearing the flag (IORESOURCE_BUSY) allows drivers to use
* the io ports if they really know they can use it, while
- * still preventing hotplug PCI devices from using it.
+ * still preventing hotplug PCI devices from using it.
*/
static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data)
{
@@ -123,49 +123,54 @@ static struct acpi_driver acpi_motherboard_driver2 = {
},
};
+static void __init acpi_request_region (struct acpi_generic_address *addr,
+ unsigned int length, char *desc)
+{
+ if (!addr->address || !length)
+ return;
+
+ if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_IO)
+ request_region(addr->address, length, desc);
+ else if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ request_mem_region(addr->address, length, desc);
+}
+
static void __init acpi_reserve_resources(void)
{
- if (acpi_gbl_FADT->xpm1a_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
- request_region(acpi_gbl_FADT->xpm1a_evt_blk.address,
- acpi_gbl_FADT->pm1_evt_len, "PM1a_EVT_BLK");
+ acpi_request_region(&acpi_gbl_FADT->xpm1a_evt_blk,
+ acpi_gbl_FADT->pm1_evt_len, "ACPI PM1a_EVT_BLK");
- if (acpi_gbl_FADT->xpm1b_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
- request_region(acpi_gbl_FADT->xpm1b_evt_blk.address,
- acpi_gbl_FADT->pm1_evt_len, "PM1b_EVT_BLK");
+ acpi_request_region(&acpi_gbl_FADT->xpm1b_evt_blk,
+ acpi_gbl_FADT->pm1_evt_len, "ACPI PM1b_EVT_BLK");
- if (acpi_gbl_FADT->xpm1a_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
- request_region(acpi_gbl_FADT->xpm1a_cnt_blk.address,
- acpi_gbl_FADT->pm1_cnt_len, "PM1a_CNT_BLK");
+ acpi_request_region(&acpi_gbl_FADT->xpm1a_cnt_blk,
+ acpi_gbl_FADT->pm1_cnt_len, "ACPI PM1a_CNT_BLK");
- if (acpi_gbl_FADT->xpm1b_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
- request_region(acpi_gbl_FADT->xpm1b_cnt_blk.address,
- acpi_gbl_FADT->pm1_cnt_len, "PM1b_CNT_BLK");
+ acpi_request_region(&acpi_gbl_FADT->xpm1b_cnt_blk,
+ acpi_gbl_FADT->pm1_cnt_len, "ACPI PM1b_CNT_BLK");
- if (acpi_gbl_FADT->xpm_tmr_blk.address && acpi_gbl_FADT->pm_tm_len == 4)
- request_region(acpi_gbl_FADT->xpm_tmr_blk.address, 4, "PM_TMR");
+ if (acpi_gbl_FADT->pm_tm_len == 4)
+ acpi_request_region(&acpi_gbl_FADT->xpm_tmr_blk, 4, "ACPI PM_TMR");
- if (acpi_gbl_FADT->xpm2_cnt_blk.address && acpi_gbl_FADT->pm2_cnt_len)
- request_region(acpi_gbl_FADT->xpm2_cnt_blk.address,
- acpi_gbl_FADT->pm2_cnt_len, "PM2_CNT_BLK");
+ acpi_request_region(&acpi_gbl_FADT->xpm2_cnt_blk,
+ acpi_gbl_FADT->pm2_cnt_len, "ACPI PM2_CNT_BLK");
/* Length of GPE blocks must be a non-negative multiple of 2 */
- if (acpi_gbl_FADT->xgpe0_blk.address && acpi_gbl_FADT->gpe0_blk_len &&
- !(acpi_gbl_FADT->gpe0_blk_len & 0x1))
- request_region(acpi_gbl_FADT->xgpe0_blk.address,
- acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK");
+ if (!(acpi_gbl_FADT->gpe0_blk_len & 0x1))
+ acpi_request_region(&acpi_gbl_FADT->xgpe0_blk,
+ acpi_gbl_FADT->gpe0_blk_len, "ACPI GPE0_BLK");
- if (acpi_gbl_FADT->xgpe1_blk.address && acpi_gbl_FADT->gpe1_blk_len &&
- !(acpi_gbl_FADT->gpe1_blk_len & 0x1))
- request_region(acpi_gbl_FADT->xgpe1_blk.address,
- acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK");
+ if (!(acpi_gbl_FADT->gpe1_blk_len & 0x1))
+ acpi_request_region(&acpi_gbl_FADT->xgpe1_blk,
+ acpi_gbl_FADT->gpe1_blk_len, "ACPI GPE1_BLK");
}
static int __init acpi_motherboard_init(void)
{
acpi_bus_register_driver(&acpi_motherboard_driver1);
acpi_bus_register_driver(&acpi_motherboard_driver2);
- /*
+ /*
* Guarantee motherboard IO reservation first
* This module must run after scan.c
*/
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
index 1149bc18fb3..48fadade52e 100644
--- a/drivers/acpi/namespace/nsaccess.c
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -70,7 +70,7 @@ acpi_status acpi_ns_root_initialize(void)
union acpi_operand_object *obj_desc;
acpi_string val = NULL;
- ACPI_FUNCTION_TRACE("ns_root_initialize");
+ ACPI_FUNCTION_TRACE(ns_root_initialize);
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
@@ -98,6 +98,7 @@ acpi_status acpi_ns_root_initialize(void)
"Entering predefined entries into namespace\n"));
for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) {
+
/* _OSI is optional for now, will be permanent later */
if (!ACPI_STRCMP(init_val->name, "_OSI")
@@ -156,7 +157,7 @@ acpi_status acpi_ns_root_initialize(void)
#if defined (ACPI_ASL_COMPILER)
- /* save the parameter count for the i_aSL compiler */
+ /* Save the parameter count for the i_aSL compiler */
new_node->value = obj_desc->method.param_count;
#else
@@ -258,10 +259,8 @@ acpi_status acpi_ns_root_initialize(void)
/* Save a handle to "_GPE", it is always present */
if (ACPI_SUCCESS(status)) {
- status =
- acpi_ns_get_node_by_path("\\_GPE", NULL,
- ACPI_NS_NO_UPSEARCH,
- &acpi_gbl_fadt_gpe_device);
+ status = acpi_ns_get_node(NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH,
+ &acpi_gbl_fadt_gpe_device);
}
return_ACPI_STATUS(status);
@@ -310,17 +309,17 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
acpi_object_type type_to_check_for;
acpi_object_type this_search_type;
u32 search_parent_flag = ACPI_NS_SEARCH_PARENT;
- u32 local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND |
- ACPI_NS_SEARCH_PARENT);
+ u32 local_flags;
- ACPI_FUNCTION_TRACE("ns_lookup");
+ ACPI_FUNCTION_TRACE(ns_lookup);
if (!return_node) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- acpi_gbl_ns_lookup_count++;
+ local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT);
*return_node = ACPI_ENTRY_NOT_FOUND;
+ acpi_gbl_ns_lookup_count++;
if (!acpi_gbl_root_node) {
return_ACPI_STATUS(AE_NO_NAMESPACE);
@@ -346,14 +345,17 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
return_ACPI_STATUS(AE_AML_INTERNAL);
}
- /*
- * This node might not be a actual "scope" node (such as a
- * Device/Method, etc.) It could be a Package or other object node.
- * Backup up the tree to find the containing scope node.
- */
- while (!acpi_ns_opens_scope(prefix_node->type) &&
- prefix_node->type != ACPI_TYPE_ANY) {
- prefix_node = acpi_ns_get_parent_node(prefix_node);
+ if (!(flags & ACPI_NS_PREFIX_IS_SCOPE)) {
+ /*
+ * This node might not be a actual "scope" node (such as a
+ * Device/Method, etc.) It could be a Package or other object node.
+ * Backup up the tree to find the containing scope node.
+ */
+ while (!acpi_ns_opens_scope(prefix_node->type) &&
+ prefix_node->type != ACPI_TYPE_ANY) {
+ prefix_node =
+ acpi_ns_get_parent_node(prefix_node);
+ }
}
}
@@ -365,6 +367,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
* Begin examination of the actual pathname
*/
if (!pathname) {
+
/* A Null name_path is allowed and refers to the root */
num_segments = 0;
@@ -389,6 +392,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
* to the current scope).
*/
if (*path == (u8) AML_ROOT_PREFIX) {
+
/* Pathname is fully qualified, start from the root */
this_node = acpi_gbl_root_node;
@@ -416,6 +420,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
this_node = prefix_node;
num_carats = 0;
while (*path == (u8) AML_PARENT_PREFIX) {
+
/* Name is fully qualified, no search rules apply */
search_parent_flag = ACPI_NS_NO_UPSEARCH;
@@ -430,6 +435,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
num_carats++;
this_node = acpi_ns_get_parent_node(this_node);
if (!this_node) {
+
/* Current scope has no parent scope */
ACPI_ERROR((AE_INFO,
@@ -569,6 +575,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
&this_node);
if (ACPI_FAILURE(status)) {
if (status == AE_NOT_FOUND) {
+
/* Name not found in ACPI namespace */
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
@@ -602,10 +609,11 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
(type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) &&
(this_node->type != ACPI_TYPE_ANY) &&
(this_node->type != type_to_check_for)) {
+
/* Complain about a type mismatch */
ACPI_WARNING((AE_INFO,
- "ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)",
+ "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
ACPI_CAST_PTR(char, &simple_name),
acpi_ut_get_type_name(this_node->type),
acpi_ut_get_type_name
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
index 9b871f38b61..dc3f0739a46 100644
--- a/drivers/acpi/namespace/nsalloc.c
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -47,9 +47,6 @@
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsalloc")
-/* Local prototypes */
-static void acpi_ns_remove_reference(struct acpi_namespace_node *node);
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_create_node
@@ -61,14 +58,13 @@ static void acpi_ns_remove_reference(struct acpi_namespace_node *node);
* DESCRIPTION: Create a namespace node
*
******************************************************************************/
-
struct acpi_namespace_node *acpi_ns_create_node(u32 name)
{
struct acpi_namespace_node *node;
- ACPI_FUNCTION_TRACE("ns_create_node");
+ ACPI_FUNCTION_TRACE(ns_create_node);
- node = ACPI_MEM_CALLOCATE(sizeof(struct acpi_namespace_node));
+ node = acpi_os_acquire_object(acpi_gbl_namespace_cache);
if (!node) {
return_PTR(NULL);
}
@@ -76,9 +72,7 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name)
ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++);
node->name.integer = name;
- node->reference_count = 1;
ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED);
-
return_PTR(node);
}
@@ -100,7 +94,7 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node)
struct acpi_namespace_node *prev_node;
struct acpi_namespace_node *next_node;
- ACPI_FUNCTION_TRACE_PTR("ns_delete_node", node);
+ ACPI_FUNCTION_TRACE_PTR(ns_delete_node, node);
parent_node = acpi_ns_get_parent_node(node);
@@ -115,6 +109,7 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node)
}
if (prev_node) {
+
/* Node is not first child, unlink it */
prev_node->peer = next_node->peer;
@@ -125,6 +120,7 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node)
/* Node is first child (has no previous peer) */
if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
+
/* No peers at all */
parent_node->child = NULL;
@@ -137,10 +133,10 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node)
ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
/*
- * Detach an object if there is one then delete the node
+ * Detach an object if there is one, then delete the node
*/
acpi_ns_detach_object(node);
- ACPI_MEM_FREE(node);
+ (void)acpi_os_release_object(acpi_gbl_namespace_cache, node);
return_VOID;
}
@@ -171,7 +167,7 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp
acpi_owner_id owner_id = 0;
struct acpi_namespace_node *child_node;
- ACPI_FUNCTION_TRACE("ns_install_node");
+ ACPI_FUNCTION_TRACE(ns_install_node);
/*
* Get the owner ID from the Walk state
@@ -216,14 +212,6 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp
acpi_ut_get_type_name(parent_node->type),
parent_node));
- /*
- * Increment the reference count(s) of all parents up to
- * the root!
- */
- while ((node = acpi_ns_get_parent_node(node)) != NULL) {
- node->reference_count++;
- }
-
return_VOID;
}
@@ -244,10 +232,9 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
{
struct acpi_namespace_node *child_node;
struct acpi_namespace_node *next_node;
- struct acpi_namespace_node *node;
u8 flags;
- ACPI_FUNCTION_TRACE_PTR("ns_delete_children", parent_node);
+ ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node);
if (!parent_node) {
return_VOID;
@@ -264,6 +251,7 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
* Deallocate all children at this level
*/
do {
+
/* Get the things we need */
next_node = child_node->peer;
@@ -289,26 +277,10 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
*/
acpi_ns_detach_object(child_node);
- /*
- * Decrement the reference count(s) of all parents up to
- * the root! (counts were incremented when the node was created)
- */
- node = child_node;
- while ((node = acpi_ns_get_parent_node(node)) != NULL) {
- node->reference_count--;
- }
-
- /* There should be only one reference remaining on this node */
-
- if (child_node->reference_count != 1) {
- ACPI_WARNING((AE_INFO,
- "Existing references (%d) on node being deleted (%p)",
- child_node->reference_count, child_node));
- }
-
/* Now we can delete the node */
- ACPI_MEM_FREE(child_node);
+ (void)acpi_os_release_object(acpi_gbl_namespace_cache,
+ child_node);
/* And move on to the next child in the list */
@@ -341,7 +313,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)
struct acpi_namespace_node *child_node = NULL;
u32 level = 1;
- ACPI_FUNCTION_TRACE("ns_delete_namespace_subtree");
+ ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree);
if (!parent_node) {
return_VOID;
@@ -352,11 +324,14 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)
* to where we started.
*/
while (level > 0) {
+
/* Get the next node in this scope (NULL if none) */
- child_node = acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node,
- child_node);
+ child_node =
+ acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node,
+ child_node);
if (child_node) {
+
/* Found a child node - detach any attached object */
acpi_ns_detach_object(child_node);
@@ -401,55 +376,6 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)
/*******************************************************************************
*
- * FUNCTION: acpi_ns_remove_reference
- *
- * PARAMETERS: Node - Named node whose reference count is to be
- * decremented
- *
- * RETURN: None.
- *
- * DESCRIPTION: Remove a Node reference. Decrements the reference count
- * of all parent Nodes up to the root. Any node along
- * the way that reaches zero references is freed.
- *
- ******************************************************************************/
-
-static void acpi_ns_remove_reference(struct acpi_namespace_node *node)
-{
- struct acpi_namespace_node *parent_node;
- struct acpi_namespace_node *this_node;
-
- ACPI_FUNCTION_ENTRY();
-
- /*
- * Decrement the reference count(s) of this node and all
- * nodes up to the root, Delete anything with zero remaining references.
- */
- this_node = node;
- while (this_node) {
- /* Prepare to move up to parent */
-
- parent_node = acpi_ns_get_parent_node(this_node);
-
- /* Decrement the reference count on this node */
-
- this_node->reference_count--;
-
- /* Delete the node if no more references */
-
- if (!this_node->reference_count) {
- /* Delete all children and delete the node */
-
- acpi_ns_delete_children(this_node);
- acpi_ns_delete_node(this_node);
- }
-
- this_node = parent_node;
- }
-}
-
-/*******************************************************************************
- *
* FUNCTION: acpi_ns_delete_namespace_by_owner
*
* PARAMETERS: owner_id - All nodes with this owner will be deleted
@@ -469,15 +395,15 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)
u32 level;
struct acpi_namespace_node *parent_node;
- ACPI_FUNCTION_TRACE_U32("ns_delete_namespace_by_owner", owner_id);
+ ACPI_FUNCTION_TRACE_U32(ns_delete_namespace_by_owner, owner_id);
if (owner_id == 0) {
return_VOID;
}
+ deletion_node = NULL;
parent_node = acpi_gbl_root_node;
child_node = NULL;
- deletion_node = NULL;
level = 1;
/*
@@ -494,12 +420,14 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)
child_node);
if (deletion_node) {
- acpi_ns_remove_reference(deletion_node);
+ acpi_ns_delete_children(deletion_node);
+ acpi_ns_delete_node(deletion_node);
deletion_node = NULL;
}
if (child_node) {
if (child_node->owner_id == owner_id) {
+
/* Found a matching child node - detach any attached object */
acpi_ns_detach_object(child_node);
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
index a2807317a84..d72df66aa96 100644
--- a/drivers/acpi/namespace/nsdump.c
+++ b/drivers/acpi/namespace/nsdump.c
@@ -75,7 +75,7 @@ void acpi_ns_print_pathname(u32 num_segments, char *pathname)
{
acpi_native_uint i;
- ACPI_FUNCTION_NAME("ns_print_pathname");
+ ACPI_FUNCTION_NAME(ns_print_pathname);
if (!(acpi_dbg_level & ACPI_LV_NAMES)
|| !(acpi_dbg_layer & ACPI_NAMESPACE)) {
@@ -123,7 +123,7 @@ void
acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component)
{
- ACPI_FUNCTION_TRACE("ns_dump_pathname");
+ ACPI_FUNCTION_TRACE(ns_dump_pathname);
/* Do this only if the requested debug level and component are enabled */
@@ -167,7 +167,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
u32 dbg_level;
u32 i;
- ACPI_FUNCTION_NAME("ns_dump_one_object");
+ ACPI_FUNCTION_NAME(ns_dump_one_object);
/* Is output enabled? */
@@ -191,6 +191,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
}
if (!(info->display_type & ACPI_DISPLAY_SHORT)) {
+
/* Indent the object according to the level */
acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " ");
@@ -203,6 +204,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
}
if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
+ this_node->name.integer =
+ acpi_ut_repair_name(this_node->name.integer);
+
ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X",
this_node->name.integer));
}
@@ -226,6 +230,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
case ACPI_DISPLAY_SUMMARY:
if (!obj_desc) {
+
/* No attached object, we are done */
acpi_os_printf("\n");
@@ -419,6 +424,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
acpi_os_printf("O:%p", obj_desc);
if (!obj_desc) {
+
/* No attached object, we are done */
acpi_os_printf("\n");
@@ -669,7 +675,7 @@ void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth)
{
acpi_handle search_handle = search_base;
- ACPI_FUNCTION_TRACE("ns_dump_tables");
+ ACPI_FUNCTION_TRACE(ns_dump_tables);
if (!acpi_gbl_root_node) {
/*
@@ -682,6 +688,7 @@ void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth)
}
if (ACPI_NS_ALL == search_base) {
+
/* Entire namespace */
search_handle = acpi_gbl_root_node;
diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c
index aff899a935e..c6bf5d30fca 100644
--- a/drivers/acpi/namespace/nsdumpdv.c
+++ b/drivers/acpi/namespace/nsdumpdv.c
@@ -74,7 +74,7 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
acpi_status status;
u32 i;
- ACPI_FUNCTION_NAME("ns_dump_one_device");
+ ACPI_FUNCTION_NAME(ns_dump_one_device);
status =
acpi_ns_dump_one_object(obj_handle, level, context, return_value);
@@ -92,7 +92,7 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
info->hardware_id.value,
ACPI_FORMAT_UINT64(info->address),
info->current_status));
- ACPI_MEM_FREE(info);
+ ACPI_FREE(info);
}
return (status);
@@ -115,7 +115,7 @@ void acpi_ns_dump_root_devices(void)
acpi_handle sys_bus_handle;
acpi_status status;
- ACPI_FUNCTION_NAME("ns_dump_root_devices");
+ ACPI_FUNCTION_NAME(ns_dump_root_devices);
/* Only dump the table if tracing is enabled */
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index 19d7b94d40c..4b0a4a8c984 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -1,7 +1,6 @@
/*******************************************************************************
*
- * Module Name: nseval - Object evaluation interfaces -- includes control
- * method lookup and execution.
+ * Module Name: nseval - Object evaluation, includes control method execution
*
******************************************************************************/
@@ -50,196 +49,14 @@
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nseval")
-/* Local prototypes */
-static acpi_status
-acpi_ns_execute_control_method(struct acpi_parameter_info *info);
-
-static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info);
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ns_evaluate_relative
- *
- * PARAMETERS: Pathname - Name of method to execute, If NULL, the
- * handle is the object to execute
- * Info - Method info block, contains:
- * return_object - Where to put method's return value (if
- * any). If NULL, no value is returned.
- * Params - List of parameters to pass to the method,
- * terminated by NULL. Params itself may be
- * NULL if no parameters are being passed.
- *
- * RETURN: Status
- *
- * DESCRIPTION: Evaluate the object or find and execute the requested method
- *
- * MUTEX: Locks Namespace
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info)
-{
- acpi_status status;
- struct acpi_namespace_node *node = NULL;
- union acpi_generic_state *scope_info;
- char *internal_path = NULL;
-
- ACPI_FUNCTION_TRACE("ns_evaluate_relative");
-
- /*
- * Must have a valid object handle
- */
- if (!info || !info->node) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
-
- /* Build an internal name string for the method */
-
- status = acpi_ns_internalize_name(pathname, &internal_path);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- scope_info = acpi_ut_create_generic_state();
- if (!scope_info) {
- goto cleanup1;
- }
-
- /* Get the prefix handle and Node */
-
- status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(status)) {
- goto cleanup;
- }
-
- info->node = acpi_ns_map_handle_to_node(info->node);
- if (!info->node) {
- (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
- status = AE_BAD_PARAMETER;
- goto cleanup;
- }
-
- /* Lookup the name in the namespace */
-
- scope_info->scope.node = info->node;
- status = acpi_ns_lookup(scope_info, internal_path, ACPI_TYPE_ANY,
- ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
- &node);
-
- (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-
- if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Object [%s] not found [%s]\n",
- pathname, acpi_format_exception(status)));
- goto cleanup;
- }
-
- /*
- * Now that we have a handle to the object, we can attempt to evaluate it.
- */
- ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
- pathname, node, acpi_ns_get_attached_object(node)));
-
- info->node = node;
- status = acpi_ns_evaluate_by_handle(info);
-
- ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
- "*** Completed eval of object %s ***\n", pathname));
-
- cleanup:
- acpi_ut_delete_generic_state(scope_info);
-
- cleanup1:
- ACPI_MEM_FREE(internal_path);
- return_ACPI_STATUS(status);
-}
-
/*******************************************************************************
*
- * FUNCTION: acpi_ns_evaluate_by_name
+ * FUNCTION: acpi_ns_evaluate
*
- * PARAMETERS: Pathname - Fully qualified pathname to the object
- * Info - Method info block, contains:
- * return_object - Where to put method's return value (if
- * any). If NULL, no value is returned.
- * Params - List of parameters to pass to the method,
- * terminated by NULL. Params itself may be
- * NULL if no parameters are being passed.
- *
- * RETURN: Status
- *
- * DESCRIPTION: Evaluate the object or rind and execute the requested method
- * passing the given parameters
- *
- * MUTEX: Locks Namespace
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info)
-{
- acpi_status status;
- char *internal_path = NULL;
-
- ACPI_FUNCTION_TRACE("ns_evaluate_by_name");
-
- /* Build an internal name string for the method */
-
- status = acpi_ns_internalize_name(pathname, &internal_path);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(status)) {
- goto cleanup;
- }
-
- /* Lookup the name in the namespace */
-
- status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY,
- ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
- &info->node);
-
- (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-
- if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
- "Object at [%s] was not found, status=%.4X\n",
- pathname, status));
- goto cleanup;
- }
-
- /*
- * Now that we have a handle to the object, we can attempt to evaluate it.
- */
- ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
- pathname, info->node,
- acpi_ns_get_attached_object(info->node)));
-
- status = acpi_ns_evaluate_by_handle(info);
-
- ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
- "*** Completed eval of object %s ***\n", pathname));
-
- cleanup:
-
- /* Cleanup */
-
- if (internal_path) {
- ACPI_MEM_FREE(internal_path);
- }
-
- return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ns_evaluate_by_handle
- *
- * PARAMETERS: Info - Method info block, contains:
- * Node - Method/Object Node to execute
+ * PARAMETERS: Info - Evaluation info block, contains:
+ * prefix_node - Prefix or Method/Object Node to execute
+ * Pathname - Name of method to execute, If NULL, the
+ * Node is the object to execute
* Parameters - List of parameters to pass to the method,
* terminated by NULL. Params itself may be
* NULL if no parameters are being passed.
@@ -248,29 +65,21 @@ acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info)
* parameter_type - Type of Parameter list
* return_object - Where to put method's return value (if
* any). If NULL, no value is returned.
+ * Flags - ACPI_IGNORE_RETURN_VALUE to delete return
*
* RETURN: Status
*
- * DESCRIPTION: Evaluate object or execute the requested method passing the
- * given parameters
+ * DESCRIPTION: Execute a control method or return the current value of an
+ * ACPI namespace object.
*
- * MUTEX: Locks Namespace
+ * MUTEX: Locks interpreter
*
******************************************************************************/
-
-acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info)
+acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ns_evaluate_by_handle");
-
- /* Check if namespace has been initialized */
-
- if (!acpi_gbl_root_node) {
- return_ACPI_STATUS(AE_NO_NAMESPACE);
- }
-
- /* Parameter Validation */
+ ACPI_FUNCTION_TRACE(ns_evaluate);
if (!info) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -280,202 +89,120 @@ acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info)
info->return_object = NULL;
- /* Get the prefix handle and Node */
-
- status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ /*
+ * Get the actual namespace node for the target object. Handles these cases:
+ *
+ * 1) Null node, Pathname (absolute path)
+ * 2) Node, Pathname (path relative to Node)
+ * 3) Node, Null Pathname
+ */
+ status = acpi_ns_get_node(info->prefix_node, info->pathname,
+ ACPI_NS_NO_UPSEARCH, &info->resolved_node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- info->node = acpi_ns_map_handle_to_node(info->node);
- if (!info->node) {
- (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
-
/*
* For a method alias, we must grab the actual method node so that proper
* scoping context will be established before execution.
*/
- if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
- info->node =
+ if (acpi_ns_get_type(info->resolved_node) ==
+ ACPI_TYPE_LOCAL_METHOD_ALIAS) {
+ info->resolved_node =
ACPI_CAST_PTR(struct acpi_namespace_node,
- info->node->object);
+ info->resolved_node->object);
}
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname,
+ info->resolved_node,
+ acpi_ns_get_attached_object(info->resolved_node)));
+
/*
* Two major cases here:
- * 1) The object is an actual control method -- execute it.
- * 2) The object is not a method -- just return it's current value
*
- * In both cases, the namespace is unlocked by the acpi_ns* procedure
+ * 1) The object is a control method -- execute it
+ * 2) The object is not a method -- just return it's current value
*/
- if (acpi_ns_get_type(info->node) == ACPI_TYPE_METHOD) {
- /*
- * Case 1) We have an actual control method to execute
- */
- status = acpi_ns_execute_control_method(info);
- } else {
+ if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) {
/*
- * Case 2) Object is NOT a method, just return its current value
+ * 1) Object is a control method - execute it
*/
- status = acpi_ns_get_object_value(info);
- }
-
- /*
- * Check if there is a return value on the stack that must be dealt with
- */
- if (status == AE_CTRL_RETURN_VALUE) {
- /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
-
- status = AE_OK;
- }
-
- /*
- * Namespace was unlocked by the handling acpi_ns* function, so we
- * just return
- */
- return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ns_execute_control_method
- *
- * PARAMETERS: Info - Method info block, contains:
- * Node - Method Node to execute
- * obj_desc - Method object
- * Parameters - List of parameters to pass to the method,
- * terminated by NULL. Params itself may be
- * NULL if no parameters are being passed.
- * return_object - Where to put method's return value (if
- * any). If NULL, no value is returned.
- * parameter_type - Type of Parameter list
- * return_object - Where to put method's return value (if
- * any). If NULL, no value is returned.
- *
- * RETURN: Status
- *
- * DESCRIPTION: Execute the requested method passing the given parameters
- *
- * MUTEX: Assumes namespace is locked
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ns_execute_control_method(struct acpi_parameter_info *info)
-{
- acpi_status status;
-
- ACPI_FUNCTION_TRACE("ns_execute_control_method");
-
- /* Verify that there is a method associated with this object */
-
- info->obj_desc = acpi_ns_get_attached_object(info->node);
- if (!info->obj_desc) {
- ACPI_ERROR((AE_INFO, "No attached method object"));
- (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS(AE_NULL_OBJECT);
- }
-
- ACPI_DUMP_PATHNAME(info->node, "Execute Method:",
- ACPI_LV_INFO, _COMPONENT);
-
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
- info->obj_desc->method.aml_start + 1,
- info->obj_desc->method.aml_length - 1));
-
- /*
- * Unlock the namespace before execution. This allows namespace access
- * via the external Acpi* interfaces while a method is being executed.
- * However, any namespace deletion must acquire both the namespace and
- * interpreter locks to ensure that no thread is using the portion of the
- * namespace that is being deleted.
- */
- status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
+ /* Verify that there is a method object associated with this node */
- /*
- * Execute the method via the interpreter. The interpreter is locked
- * here before calling into the AML parser
- */
- status = acpi_ex_enter_interpreter();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
+ info->obj_desc =
+ acpi_ns_get_attached_object(info->resolved_node);
+ if (!info->obj_desc) {
+ ACPI_ERROR((AE_INFO,
+ "Control method has no attached sub-object"));
+ return_ACPI_STATUS(AE_NULL_OBJECT);
+ }
- status = acpi_ps_execute_method(info);
- acpi_ex_exit_interpreter();
+ ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:",
+ ACPI_LV_INFO, _COMPONENT);
- return_ACPI_STATUS(status);
-}
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Method at AML address %p Length %X\n",
+ info->obj_desc->method.aml_start + 1,
+ info->obj_desc->method.aml_length - 1));
-/*******************************************************************************
- *
- * FUNCTION: acpi_ns_get_object_value
- *
- * PARAMETERS: Info - Method info block, contains:
- * Node - Object's NS node
- * return_object - Where to put object value (if
- * any). If NULL, no value is returned.
- *
- * RETURN: Status
- *
- * DESCRIPTION: Return the current value of the object
- *
- * MUTEX: Assumes namespace is locked, leaves namespace unlocked
- *
- ******************************************************************************/
+ /*
+ * Any namespace deletion must acquire both the namespace and
+ * interpreter locks to ensure that no thread is using the portion of
+ * the namespace that is being deleted.
+ *
+ * Execute the method via the interpreter. The interpreter is locked
+ * here before calling into the AML parser
+ */
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
-static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info)
-{
- acpi_status status = AE_OK;
- struct acpi_namespace_node *resolved_node = info->node;
+ status = acpi_ps_execute_method(info);
+ acpi_ex_exit_interpreter();
+ } else {
+ /*
+ * 2) Object is not a method, return its current value
+ */
- ACPI_FUNCTION_TRACE("ns_get_object_value");
+ /*
+ * Objects require additional resolution steps (e.g., the Node may be
+ * a field that must be read, etc.) -- we can't just grab the object
+ * out of the node.
+ *
+ * Use resolve_node_to_value() to get the associated value.
+ *
+ * NOTE: we can get away with passing in NULL for a walk state because
+ * resolved_node is guaranteed to not be a reference to either a method
+ * local or a method argument (because this interface is never called
+ * from a running method.)
+ *
+ * Even though we do not directly invoke the interpreter for object
+ * resolution, we must lock it because we could access an opregion.
+ * The opregion access code assumes that the interpreter is locked.
+ */
+ status = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
- /*
- * Objects require additional resolution steps (e.g., the Node may be a
- * field that must be read, etc.) -- we can't just grab the object out of
- * the node.
- */
+ /* Function has a strange interface */
- /*
- * Use resolve_node_to_value() to get the associated value. This call always
- * deletes obj_desc (allocated above).
- *
- * NOTE: we can get away with passing in NULL for a walk state because
- * obj_desc is guaranteed to not be a reference to either a method local or
- * a method argument (because this interface can only be called from the
- * acpi_evaluate external interface, never called from a running method.)
- *
- * Even though we do not directly invoke the interpreter for this, we must
- * enter it because we could access an opregion. The opregion access code
- * assumes that the interpreter is locked.
- *
- * We must release the namespace lock before entering the intepreter.
- */
- status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
+ status =
+ acpi_ex_resolve_node_to_value(&info->resolved_node, NULL);
+ acpi_ex_exit_interpreter();
- status = acpi_ex_enter_interpreter();
- if (ACPI_SUCCESS(status)) {
- status = acpi_ex_resolve_node_to_value(&resolved_node, NULL);
/*
* If acpi_ex_resolve_node_to_value() succeeded, the return value was placed
* in resolved_node.
*/
- acpi_ex_exit_interpreter();
-
if (ACPI_SUCCESS(status)) {
status = AE_CTRL_RETURN_VALUE;
- info->return_object = ACPI_CAST_PTR
- (union acpi_operand_object, resolved_node);
+ info->return_object =
+ ACPI_CAST_PTR(union acpi_operand_object,
+ info->resolved_node);
+
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"Returning object %p [%s]\n",
info->return_object,
@@ -484,7 +211,30 @@ static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info)
}
}
- /* Namespace is unlocked */
+ /*
+ * Check if there is a return value that must be dealt with
+ */
+ if (status == AE_CTRL_RETURN_VALUE) {
+
+ /* If caller does not want the return value, delete it */
+ if (info->flags & ACPI_IGNORE_RETURN_VALUE) {
+ acpi_ut_remove_reference(info->return_object);
+ info->return_object = NULL;
+ }
+
+ /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
+
+ status = AE_OK;
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "*** Completed evaluation of object %s ***\n",
+ info->pathname));
+
+ /*
+ * Namespace was unlocked by the handling acpi_ns* function, so we
+ * just return
+ */
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index 9f929e479fd..aec8488c001 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -58,6 +58,10 @@ static acpi_status
acpi_ns_init_one_device(acpi_handle obj_handle,
u32 nesting_level, void *context, void **return_value);
+static acpi_status
+acpi_ns_find_ini_methods(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value);
+
/*******************************************************************************
*
* FUNCTION: acpi_ns_initialize_objects
@@ -76,7 +80,7 @@ acpi_status acpi_ns_initialize_objects(void)
acpi_status status;
struct acpi_init_walk_info info;
- ACPI_FUNCTION_TRACE("ns_initialize_objects");
+ ACPI_FUNCTION_TRACE(ns_initialize_objects);
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"**** Starting initialization of namespace objects ****\n"));
@@ -93,7 +97,7 @@ acpi_status acpi_ns_initialize_objects(void)
ACPI_UINT32_MAX, acpi_ns_init_one_object,
&info, NULL);
if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace"));
+ ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
@@ -133,7 +137,7 @@ acpi_status acpi_ns_initialize_devices(void)
acpi_status status;
struct acpi_device_walk_info info;
- ACPI_FUNCTION_TRACE("ns_initialize_devices");
+ ACPI_FUNCTION_TRACE(ns_initialize_devices);
/* Init counters */
@@ -142,30 +146,46 @@ acpi_status acpi_ns_initialize_devices(void)
info.num_INI = 0;
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
- "Executing all Device _STA and_INI methods:"));
+ "Initializing Device/Processor/Thermal objects by executing _INI methods:"));
+
+ /* Tree analysis: find all subtrees that contain _INI methods */
- status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, FALSE,
+ acpi_ns_find_ini_methods, &info, NULL);
if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ goto error_exit;
}
- /* Walk namespace for all objects */
+ /* Allocate the evaluation information block */
+
+ info.evaluate_info =
+ ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+ if (!info.evaluate_info) {
+ status = AE_NO_MEMORY;
+ goto error_exit;
+ }
+
+ /* Walk namespace to execute all _INIs on present devices */
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, TRUE,
+ ACPI_UINT32_MAX, FALSE,
acpi_ns_init_one_device, &info, NULL);
- (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-
+ ACPI_FREE(info.evaluate_info);
if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace"));
+ goto error_exit;
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
- "\n%hd Devices found - executed %hd _STA, %hd _INI methods\n",
- info.device_count, info.num_STA, info.num_INI));
+ "\nExecuted %hd _INI methods requiring %hd _STA executions (examined %hd objects)\n",
+ info.num_INI, info.num_STA, info.device_count));
return_ACPI_STATUS(status);
+
+ error_exit:
+ ACPI_EXCEPTION((AE_INFO, status, "During device initialization"));
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -200,7 +220,7 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
(struct acpi_namespace_node *)obj_handle;
union acpi_operand_object *obj_desc;
- ACPI_FUNCTION_NAME("ns_init_one_object");
+ ACPI_FUNCTION_NAME(ns_init_one_object);
info->object_count++;
@@ -311,6 +331,72 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
/*******************************************************************************
*
+ * FUNCTION: acpi_ns_find_ini_methods
+ *
+ * PARAMETERS: acpi_walk_callback
+ *
+ * RETURN: acpi_status
+ *
+ * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
+ * device/processor/thermal objects, and marks the entire subtree
+ * with a SUBTREE_HAS_INI flag. This flag is used during the
+ * subsequent device initialization walk to avoid entire subtrees
+ * that do not contain an _INI.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_find_ini_methods(acpi_handle obj_handle,
+ u32 nesting_level, void *context, void **return_value)
+{
+ struct acpi_device_walk_info *info =
+ ACPI_CAST_PTR(struct acpi_device_walk_info, context);
+ struct acpi_namespace_node *node;
+ struct acpi_namespace_node *parent_node;
+
+ /* Keep count of device/processor/thermal objects */
+
+ node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
+ if ((node->type == ACPI_TYPE_DEVICE) ||
+ (node->type == ACPI_TYPE_PROCESSOR) ||
+ (node->type == ACPI_TYPE_THERMAL)) {
+ info->device_count++;
+ return (AE_OK);
+ }
+
+ /* We are only looking for methods named _INI */
+
+ if (!ACPI_COMPARE_NAME(node->name.ascii, METHOD_NAME__INI)) {
+ return (AE_OK);
+ }
+
+ /*
+ * The only _INI methods that we care about are those that are
+ * present under Device, Processor, and Thermal objects.
+ */
+ parent_node = acpi_ns_get_parent_node(node);
+ switch (parent_node->type) {
+ case ACPI_TYPE_DEVICE:
+ case ACPI_TYPE_PROCESSOR:
+ case ACPI_TYPE_THERMAL:
+
+ /* Mark parent and bubble up the INI present flag to the root */
+
+ while (parent_node) {
+ parent_node->flags |= ANOBJ_SUBTREE_HAS_INI;
+ parent_node = acpi_ns_get_parent_node(parent_node);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ns_init_one_device
*
* PARAMETERS: acpi_walk_callback
@@ -327,119 +413,165 @@ static acpi_status
acpi_ns_init_one_device(acpi_handle obj_handle,
u32 nesting_level, void *context, void **return_value)
{
- struct acpi_device_walk_info *info =
- (struct acpi_device_walk_info *)context;
- struct acpi_parameter_info pinfo;
+ struct acpi_device_walk_info *walk_info =
+ ACPI_CAST_PTR(struct acpi_device_walk_info, context);
+ struct acpi_evaluate_info *info = walk_info->evaluate_info;
u32 flags;
acpi_status status;
- struct acpi_namespace_node *ini_node;
struct acpi_namespace_node *device_node;
- ACPI_FUNCTION_TRACE("ns_init_one_device");
+ ACPI_FUNCTION_TRACE(ns_init_one_device);
- device_node = acpi_ns_map_handle_to_node(obj_handle);
- if (!device_node) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
+ /* We are interested in Devices, Processors and thermal_zones only */
- /*
- * We will run _STA/_INI on Devices, Processors and thermal_zones only
- */
+ device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
if ((device_node->type != ACPI_TYPE_DEVICE) &&
(device_node->type != ACPI_TYPE_PROCESSOR) &&
(device_node->type != ACPI_TYPE_THERMAL)) {
return_ACPI_STATUS(AE_OK);
}
- if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) &&
- (!(acpi_dbg_level & ACPI_LV_INFO))) {
- ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
- }
-
- info->device_count++;
-
/*
- * Check if the _INI method exists for this device -
- * if _INI does not exist, there is no need to run _STA
- * No _INI means device requires no initialization
+ * Because of an earlier namespace analysis, all subtrees that contain an
+ * _INI method are tagged.
+ *
+ * If this device subtree does not contain any _INI methods, we
+ * can exit now and stop traversing this entire subtree.
*/
- status = acpi_ns_search_node(*ACPI_CAST_PTR(u32, METHOD_NAME__INI),
- device_node, ACPI_TYPE_METHOD, &ini_node);
- if (ACPI_FAILURE(status)) {
- /* No _INI method found - move on to next device */
-
- return_ACPI_STATUS(AE_OK);
+ if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) {
+ return_ACPI_STATUS(AE_CTRL_DEPTH);
}
/*
- * Run _STA to determine if we can run _INI on the device -
- * the device must be present before _INI can be run.
- * However, _STA is not required - assume device present if no _STA
+ * Run _STA to determine if this device is present and functioning. We
+ * must know this information for two important reasons (from ACPI spec):
+ *
+ * 1) We can only run _INI if the device is present.
+ * 2) We must abort the device tree walk on this subtree if the device is
+ * not present and is not functional (we will not examine the children)
+ *
+ * The _STA method is not required to be present under the device, we
+ * assume the device is present if _STA does not exist.
*/
- ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
- device_node,
- METHOD_NAME__STA));
-
- pinfo.node = device_node;
- pinfo.parameters = NULL;
- pinfo.parameter_type = ACPI_PARAM_ARGS;
+ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
+ (ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA));
- status = acpi_ut_execute_STA(pinfo.node, &flags);
+ status = acpi_ut_execute_STA(device_node, &flags);
if (ACPI_FAILURE(status)) {
+
/* Ignore error and move on to next device */
return_ACPI_STATUS(AE_OK);
}
+ /*
+ * Flags == -1 means that _STA was not found. In this case, we assume that
+ * the device is both present and functional.
+ *
+ * From the ACPI spec, description of _STA:
+ *
+ * "If a device object (including the processor object) does not have an
+ * _STA object, then OSPM assumes that all of the above bits are set (in
+ * other words, the device is present, ..., and functioning)"
+ */
if (flags != ACPI_UINT32_MAX) {
- info->num_STA++;
+ walk_info->num_STA++;
}
+ /*
+ * Examine the PRESENT and FUNCTIONING status bits
+ *
+ * Note: ACPI spec does not seem to specify behavior for the present but
+ * not functioning case, so we assume functioning if present.
+ */
if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
- /* Don't look at children of a not present device */
- return_ACPI_STATUS(AE_CTRL_DEPTH);
+ /* Device is not present, we must examine the Functioning bit */
+
+ if (flags & ACPI_STA_DEVICE_FUNCTIONING) {
+ /*
+ * Device is not present but is "functioning". In this case,
+ * we will not run _INI, but we continue to examine the children
+ * of this device.
+ *
+ * From the ACPI spec, description of _STA: (Note - no mention
+ * of whether to run _INI or not on the device in question)
+ *
+ * "_STA may return bit 0 clear (not present) with bit 3 set
+ * (device is functional). This case is used to indicate a valid
+ * device for which no device driver should be loaded (for example,
+ * a bridge device.) Children of this device may be present and
+ * valid. OSPM should continue enumeration below a device whose
+ * _STA returns this bit combination"
+ */
+ return_ACPI_STATUS(AE_OK);
+ } else {
+ /*
+ * Device is not present and is not functioning. We must abort the
+ * walk of this subtree immediately -- don't look at the children
+ * of such a device.
+ *
+ * From the ACPI spec, description of _INI:
+ *
+ * "If the _STA method indicates that the device is not present,
+ * OSPM will not run the _INI and will not examine the children
+ * of the device for _INI methods"
+ */
+ return_ACPI_STATUS(AE_CTRL_DEPTH);
+ }
}
/*
- * The device is present and _INI exists. Run the _INI method.
- * (We already have the _INI node from above)
+ * The device is present or is assumed present if no _STA exists.
+ * Run the _INI if it exists (not required to exist)
+ *
+ * Note: We know there is an _INI within this subtree, but it may not be
+ * under this particular device, it may be lower in the branch.
*/
- ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
- pinfo.node,
- METHOD_NAME__INI));
+ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
+ (ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI));
+
+ info->prefix_node = device_node;
+ info->pathname = METHOD_NAME__INI;
+ info->parameters = NULL;
+ info->parameter_type = ACPI_PARAM_ARGS;
+ info->flags = ACPI_IGNORE_RETURN_VALUE;
+
+ status = acpi_ns_evaluate(info);
+ if (ACPI_SUCCESS(status)) {
+ walk_info->num_INI++;
+
+ if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) &&
+ (!(acpi_dbg_level & ACPI_LV_INFO))) {
+ ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
+ }
+ }
+#ifdef ACPI_DEBUG_OUTPUT
+ else if (status != AE_NOT_FOUND) {
- pinfo.node = ini_node;
- status = acpi_ns_evaluate_by_handle(&pinfo);
- if (ACPI_FAILURE(status)) {
/* Ignore error and move on to next device */
-#ifdef ACPI_DEBUG_OUTPUT
- char *scope_name = acpi_ns_get_external_pathname(ini_node);
-
- ACPI_WARNING((AE_INFO, "%s._INI failed: %s",
- scope_name, acpi_format_exception(status)));
+ char *scope_name =
+ acpi_ns_get_external_pathname(info->resolved_node);
- ACPI_MEM_FREE(scope_name);
+ ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution",
+ scope_name));
+ ACPI_FREE(scope_name);
+ }
#endif
- } else {
- /* Delete any return object (especially if implicit_return is enabled) */
- if (pinfo.return_object) {
- acpi_ut_remove_reference(pinfo.return_object);
- }
+ /* Ignore errors from above */
- /* Count of successful INIs */
-
- info->num_INI++;
- }
+ status = AE_OK;
+ /*
+ * The _INI method has been run if present; call the Global Initialization
+ * Handler for this device.
+ */
if (acpi_gbl_init_handler) {
- /* External initialization handler is present, call it */
-
status =
- acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI);
+ acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI);
}
- return_ACPI_STATUS(AE_OK);
+ return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
index 4e0b0524c18..fe75d888e18 100644
--- a/drivers/acpi/namespace/nsload.c
+++ b/drivers/acpi/namespace/nsload.c
@@ -77,13 +77,14 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc,
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ns_load_table");
+ ACPI_FUNCTION_TRACE(ns_load_table);
/* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */
if (!
(acpi_gbl_table_data[table_desc->type].
flags & ACPI_TABLE_EXECUTABLE)) {
+
/* Just ignore this table */
return_ACPI_STATUS(AE_OK);
@@ -168,7 +169,7 @@ static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type)
acpi_status status;
struct acpi_table_desc *table_desc;
- ACPI_FUNCTION_TRACE("ns_load_table_by_type");
+ ACPI_FUNCTION_TRACE(ns_load_table_by_type);
status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
if (ACPI_FAILURE(status)) {
@@ -180,11 +181,11 @@ static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type)
* DSDT (one), SSDT/PSDT (multiple)
*/
switch (table_type) {
- case ACPI_TABLE_DSDT:
+ case ACPI_TABLE_ID_DSDT:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace load: DSDT\n"));
- table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next;
+ table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_DSDT].next;
/* If table already loaded into namespace, just return */
@@ -200,8 +201,8 @@ static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type)
}
break;
- case ACPI_TABLE_SSDT:
- case ACPI_TABLE_PSDT:
+ case ACPI_TABLE_ID_SSDT:
+ case ACPI_TABLE_ID_PSDT:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Namespace load: %d SSDT or PSDTs\n",
@@ -258,7 +259,7 @@ acpi_status acpi_ns_load_namespace(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_load_name_space");
+ ACPI_FUNCTION_TRACE(acpi_load_name_space);
/* There must be at least a DSDT installed */
@@ -271,15 +272,15 @@ acpi_status acpi_ns_load_namespace(void)
* Load the namespace. The DSDT is required,
* but the SSDT and PSDT tables are optional.
*/
- status = acpi_ns_load_table_by_type(ACPI_TABLE_DSDT);
+ status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Ignore exceptions from these */
- (void)acpi_ns_load_table_by_type(ACPI_TABLE_SSDT);
- (void)acpi_ns_load_table_by_type(ACPI_TABLE_PSDT);
+ (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_SSDT);
+ (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_PSDT);
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
"ACPI Namespace successfully loaded at root %p\n",
@@ -314,7 +315,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
acpi_handle dummy;
u32 level;
- ACPI_FUNCTION_TRACE("ns_delete_subtree");
+ ACPI_FUNCTION_TRACE(ns_delete_subtree);
parent_handle = start_handle;
child_handle = NULL;
@@ -325,6 +326,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
* to where we started.
*/
while (level > 0) {
+
/* Attempt to get the next object in this scope */
status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle,
@@ -335,6 +337,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
/* Did we get a new object? */
if (ACPI_SUCCESS(status)) {
+
/* Check if this object has any children */
if (ACPI_SUCCESS
@@ -392,7 +395,7 @@ acpi_status acpi_ns_unload_namespace(acpi_handle handle)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ns_unload_name_space");
+ ACPI_FUNCTION_TRACE(ns_unload_name_space);
/* Parameter validation */
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
index 639f653b4b6..97b8332c974 100644
--- a/drivers/acpi/namespace/nsnames.c
+++ b/drivers/acpi/namespace/nsnames.c
@@ -48,11 +48,6 @@
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsnames")
-/* Local prototypes */
-static void
-acpi_ns_build_external_path(struct acpi_namespace_node *node,
- acpi_size size, char *name_buffer);
-
/*******************************************************************************
*
* FUNCTION: acpi_ns_build_external_path
@@ -67,8 +62,7 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node,
* DESCRIPTION: Generate a full pathaname
*
******************************************************************************/
-
-static void
+void
acpi_ns_build_external_path(struct acpi_namespace_node *node,
acpi_size size, char *name_buffer)
{
@@ -138,7 +132,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
char *name_buffer;
acpi_size size;
- ACPI_FUNCTION_TRACE_PTR("ns_get_external_pathname", node);
+ ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node);
/* Calculate required buffer size based on depth below root */
@@ -146,7 +140,7 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
/* Allocate a buffer to be returned to caller */
- name_buffer = ACPI_MEM_CALLOCATE(size);
+ name_buffer = ACPI_ALLOCATE_ZEROED(size);
if (!name_buffer) {
ACPI_ERROR((AE_INFO, "Allocation failure"));
return_PTR(NULL);
@@ -219,7 +213,7 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle,
struct acpi_namespace_node *node;
acpi_size required_size;
- ACPI_FUNCTION_TRACE_PTR("ns_handle_to_pathname", target_handle);
+ ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle);
node = acpi_ns_map_handle_to_node(target_handle);
if (!node) {
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
index 10ae6292bca..aabe8794b90 100644
--- a/drivers/acpi/namespace/nsobject.c
+++ b/drivers/acpi/namespace/nsobject.c
@@ -76,19 +76,21 @@ acpi_ns_attach_object(struct acpi_namespace_node *node,
union acpi_operand_object *last_obj_desc;
acpi_object_type object_type = ACPI_TYPE_ANY;
- ACPI_FUNCTION_TRACE("ns_attach_object");
+ ACPI_FUNCTION_TRACE(ns_attach_object);
/*
* Parameter validation
*/
if (!node) {
+
/* Invalid handle */
- ACPI_ERROR((AE_INFO, "Null named_obj handle"));
+ ACPI_ERROR((AE_INFO, "Null NamedObj handle"));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (!object && (ACPI_TYPE_ANY != type)) {
+
/* Null object */
ACPI_ERROR((AE_INFO,
@@ -97,6 +99,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node,
}
if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
+
/* Not a name handle */
ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
@@ -108,7 +111,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node,
if (node->object == object) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Obj %p already installed in name_obj %p\n",
+ "Obj %p already installed in NameObj %p\n",
object, node));
return_ACPI_STATUS(AE_OK);
@@ -201,7 +204,7 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node)
{
union acpi_operand_object *obj_desc;
- ACPI_FUNCTION_TRACE("ns_detach_object");
+ ACPI_FUNCTION_TRACE(ns_detach_object);
obj_desc = node->object;
@@ -252,7 +255,7 @@ union acpi_operand_object *acpi_ns_get_attached_object(struct
acpi_namespace_node
*node)
{
- ACPI_FUNCTION_TRACE_PTR("ns_get_attached_object", node);
+ ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node);
if (!node) {
ACPI_WARNING((AE_INFO, "Null Node ptr"));
@@ -287,7 +290,7 @@ union acpi_operand_object *acpi_ns_get_secondary_object(union
acpi_operand_object
*obj_desc)
{
- ACPI_FUNCTION_TRACE_PTR("ns_get_secondary_object", obj_desc);
+ ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc);
if ((!obj_desc) ||
(ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) ||
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
index 232be430365..155505a4ef6 100644
--- a/drivers/acpi/namespace/nsparse.c
+++ b/drivers/acpi/namespace/nsparse.c
@@ -62,13 +62,13 @@ ACPI_MODULE_NAME("nsparse")
*
******************************************************************************/
acpi_status
-acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc * table_desc)
+acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc)
{
union acpi_parse_object *parse_root;
acpi_status status;
struct acpi_walk_state *walk_state;
- ACPI_FUNCTION_TRACE("ns_one_complete_parse");
+ ACPI_FUNCTION_TRACE(ns_one_complete_parse);
/* Create and init a Root Node */
@@ -124,7 +124,7 @@ acpi_ns_parse_table(struct acpi_table_desc *table_desc,
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ns_parse_table");
+ ACPI_FUNCTION_TRACE(ns_parse_table);
/*
* AML Parse, pass 1
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
index d64b78952f2..500e2bbcfaf 100644
--- a/drivers/acpi/namespace/nssearch.c
+++ b/drivers/acpi/namespace/nssearch.c
@@ -56,16 +56,16 @@ acpi_ns_search_parent_tree(u32 target_name,
/*******************************************************************************
*
- * FUNCTION: acpi_ns_search_node
+ * FUNCTION: acpi_ns_search_one_scope
*
* PARAMETERS: target_name - Ascii ACPI name to search for
- * Node - Starting node where search will begin
+ * parent_node - Starting node where search will begin
* Type - Object type to match
* return_node - Where the matched Named obj is returned
*
* RETURN: Status
*
- * DESCRIPTION: Search a single level of the namespace. Performs a
+ * DESCRIPTION: Search a single level of the namespace. Performs a
* simple search of the specified level, and does not add
* entries or search parents.
*
@@ -75,35 +75,40 @@ acpi_ns_search_parent_tree(u32 target_name,
*
* All namespace searching is linear in this implementation, but
* could be easily modified to support any improved search
- * algorithm. However, the linear search was chosen for simplicity
+ * algorithm. However, the linear search was chosen for simplicity
* and because the trees are small and the other interpreter
* execution overhead is relatively high.
*
+ * Note: CPU execution analysis has shown that the AML interpreter spends
+ * a very small percentage of its time searching the namespace. Therefore,
+ * the linear search seems to be sufficient, as there would seem to be
+ * little value in improving the search.
+ *
******************************************************************************/
acpi_status
-acpi_ns_search_node(u32 target_name,
- struct acpi_namespace_node *node,
- acpi_object_type type,
- struct acpi_namespace_node **return_node)
+acpi_ns_search_one_scope(u32 target_name,
+ struct acpi_namespace_node *parent_node,
+ acpi_object_type type,
+ struct acpi_namespace_node **return_node)
{
- struct acpi_namespace_node *next_node;
+ struct acpi_namespace_node *node;
- ACPI_FUNCTION_TRACE("ns_search_node");
+ ACPI_FUNCTION_TRACE(ns_search_one_scope);
#ifdef ACPI_DEBUG_OUTPUT
if (ACPI_LV_NAMES & acpi_dbg_level) {
char *scope_name;
- scope_name = acpi_ns_get_external_pathname(node);
+ scope_name = acpi_ns_get_external_pathname(parent_node);
if (scope_name) {
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"Searching %s (%p) For [%4.4s] (%s)\n",
- scope_name, node, ACPI_CAST_PTR(char,
- &target_name),
+ scope_name, parent_node,
+ ACPI_CAST_PTR(char, &target_name),
acpi_ut_get_type_name(type)));
- ACPI_MEM_FREE(scope_name);
+ ACPI_FREE(scope_name);
}
}
#endif
@@ -112,32 +117,33 @@ acpi_ns_search_node(u32 target_name,
* Search for name at this namespace level, which is to say that we
* must search for the name among the children of this object
*/
- next_node = node->child;
- while (next_node) {
+ node = parent_node->child;
+ while (node) {
+
/* Check for match against the name */
- if (next_node->name.integer == target_name) {
+ if (node->name.integer == target_name) {
+
/* Resolve a control method alias if any */
- if (acpi_ns_get_type(next_node) ==
+ if (acpi_ns_get_type(node) ==
ACPI_TYPE_LOCAL_METHOD_ALIAS) {
- next_node =
+ node =
ACPI_CAST_PTR(struct acpi_namespace_node,
- next_node->object);
+ node->object);
}
- /*
- * Found matching entry.
- */
+ /* Found matching entry */
+
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n",
ACPI_CAST_PTR(char, &target_name),
- acpi_ut_get_type_name(next_node->
- type),
- next_node,
- acpi_ut_get_node_name(node), node));
+ acpi_ut_get_type_name(node->type),
+ node,
+ acpi_ut_get_node_name(parent_node),
+ parent_node));
- *return_node = next_node;
+ *return_node = node;
return_ACPI_STATUS(AE_OK);
}
@@ -145,7 +151,8 @@ acpi_ns_search_node(u32 target_name,
* The last entry in the list points back to the parent,
* so a flag is used to indicate the end-of-list
*/
- if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
+ if (node->flags & ANOBJ_END_OF_PEER_LIST) {
+
/* Searched entire list, we are done */
break;
@@ -153,7 +160,7 @@ acpi_ns_search_node(u32 target_name,
/* Didn't match name, move on to the next peer object */
- next_node = next_node->peer;
+ node = node->peer;
}
/* Searched entire namespace level, not found */
@@ -162,7 +169,8 @@ acpi_ns_search_node(u32 target_name,
"Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n",
ACPI_CAST_PTR(char, &target_name),
acpi_ut_get_type_name(type),
- acpi_ut_get_node_name(node), node, node->child));
+ acpi_ut_get_node_name(parent_node), parent_node,
+ parent_node->child));
return_ACPI_STATUS(AE_NOT_FOUND);
}
@@ -179,14 +187,14 @@ acpi_ns_search_node(u32 target_name,
* RETURN: Status
*
* DESCRIPTION: Called when a name has not been found in the current namespace
- * level. Before adding it or giving up, ACPI scope rules require
+ * level. Before adding it or giving up, ACPI scope rules require
* searching enclosing scopes in cases identified by acpi_ns_local().
*
* "A name is located by finding the matching name in the current
* name space, and then in the parent name space. If the parent
* name space does not contain the name, the search continues
* recursively until either the name is found or the name space
- * does not have a parent (the root of the name space). This
+ * does not have a parent (the root of the name space). This
* indicates that the name is not found" (From ACPI Specification,
* section 5.3)
*
@@ -201,7 +209,7 @@ acpi_ns_search_parent_tree(u32 target_name,
acpi_status status;
struct acpi_namespace_node *parent_node;
- ACPI_FUNCTION_TRACE("ns_search_parent_tree");
+ ACPI_FUNCTION_TRACE(ns_search_parent_tree);
parent_node = acpi_ns_get_parent_node(node);
@@ -235,20 +243,19 @@ acpi_ns_search_parent_tree(u32 target_name,
*/
while (parent_node) {
/*
- * Search parent scope. Use TYPE_ANY because we don't care about the
+ * Search parent scope. Use TYPE_ANY because we don't care about the
* object type at this point, we only care about the existence of
- * the actual name we are searching for. Typechecking comes later.
+ * the actual name we are searching for. Typechecking comes later.
*/
- status = acpi_ns_search_node(target_name, parent_node,
+ status =
+ acpi_ns_search_one_scope(target_name, parent_node,
ACPI_TYPE_ANY, return_node);
if (ACPI_SUCCESS(status)) {
return_ACPI_STATUS(status);
}
- /*
- * Not found here, go up another level
- * (until we reach the root)
- */
+ /* Not found here, go up another level (until we reach the root) */
+
parent_node = acpi_ns_get_parent_node(parent_node);
}
@@ -273,7 +280,7 @@ acpi_ns_search_parent_tree(u32 target_name,
* RETURN: Status
*
* DESCRIPTION: Search for a name segment in a single namespace level,
- * optionally adding it if it is not found. If the passed
+ * optionally adding it if it is not found. If the passed
* Type is not Any and the type previously stored in the
* entry was Any (i.e. unknown), update the stored type.
*
@@ -293,29 +300,46 @@ acpi_ns_search_and_enter(u32 target_name,
acpi_status status;
struct acpi_namespace_node *new_node;
- ACPI_FUNCTION_TRACE("ns_search_and_enter");
+ ACPI_FUNCTION_TRACE(ns_search_and_enter);
/* Parameter validation */
if (!node || !target_name || !return_node) {
ACPI_ERROR((AE_INFO,
- "Null param: Node %p Name %X return_node %p",
+ "Null parameter: Node %p Name %X ReturnNode %p",
node, target_name, return_node));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- /* Name must consist of printable characters */
-
+ /*
+ * Name must consist of valid ACPI characters. We will repair the name if
+ * necessary because we don't want to abort because of this, but we want
+ * all namespace names to be printable. A warning message is appropriate.
+ *
+ * This issue came up because there are in fact machines that exhibit
+ * this problem, and we want to be able to enable ACPI support for them,
+ * even though there are a few bad names.
+ */
if (!acpi_ut_valid_acpi_name(target_name)) {
- ACPI_ERROR((AE_INFO, "Bad character in ACPI Name: %X",
- target_name));
- return_ACPI_STATUS(AE_BAD_CHARACTER);
+ target_name = acpi_ut_repair_name(target_name);
+
+ /* Report warning only if in strict mode or debug mode */
+
+ if (!acpi_gbl_enable_interpreter_slack) {
+ ACPI_WARNING((AE_INFO,
+ "Found bad character(s) in name, repaired: [%4.4s]\n",
+ ACPI_CAST_PTR(char, &target_name)));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+ "Found bad character(s) in name, repaired: [%4.4s]\n",
+ ACPI_CAST_PTR(char, &target_name)));
+ }
}
/* Try to find the name in the namespace level specified by the caller */
*return_node = ACPI_ENTRY_NOT_FOUND;
- status = acpi_ns_search_node(target_name, node, type, return_node);
+ status = acpi_ns_search_one_scope(target_name, node, type, return_node);
if (status != AE_NOT_FOUND) {
/*
* If we found it AND the request specifies that a find is an error,
@@ -325,18 +349,16 @@ acpi_ns_search_and_enter(u32 target_name,
status = AE_ALREADY_EXISTS;
}
- /*
- * Either found it or there was an error
- * -- finished either way
- */
+ /* Either found it or there was an error: finished either way */
+
return_ACPI_STATUS(status);
}
/*
- * The name was not found. If we are NOT performing the first pass
+ * The name was not found. If we are NOT performing the first pass
* (name entry) of loading the namespace, search the parent tree (all the
* way to the root if necessary.) We don't want to perform the parent
- * search when the namespace is actually being loaded. We want to perform
+ * search when the namespace is actually being loaded. We want to perform
* the search when namespace references are being resolved (load pass 2)
* and during the execution phase.
*/
@@ -354,9 +376,8 @@ acpi_ns_search_and_enter(u32 target_name,
}
}
- /*
- * In execute mode, just search, never add names. Exit now.
- */
+ /* In execute mode, just search, never add names. Exit now */
+
if (interpreter_mode == ACPI_IMODE_EXECUTE) {
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"%4.4s Not found in %p [Not adding]\n",
@@ -371,11 +392,18 @@ acpi_ns_search_and_enter(u32 target_name,
if (!new_node) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
+#ifdef ACPI_ASL_COMPILER
+ /*
+ * Node is an object defined by an External() statement
+ */
+ if (flags & ACPI_NS_EXTERNAL) {
+ new_node->flags |= ANOBJ_IS_EXTERNAL;
+ }
+#endif
/* Install the new object into the parent's list of children */
acpi_ns_install_node(walk_state, node, new_node, type);
*return_node = new_node;
-
return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
index 3e7cad549a3..aa4e799d9a8 100644
--- a/drivers/acpi/namespace/nsutils.c
+++ b/drivers/acpi/namespace/nsutils.c
@@ -78,15 +78,17 @@ acpi_ns_report_error(char *module_name,
char *internal_name, acpi_status lookup_status)
{
acpi_status status;
+ u32 bad_name;
char *name = NULL;
- acpi_ut_report_error(module_name, line_number);
+ acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
if (lookup_status == AE_BAD_CHARACTER) {
+
/* There is a non-ascii character in the name */
- acpi_os_printf("[0x%4.4X] (NON-ASCII)",
- *(ACPI_CAST_PTR(u32, internal_name)));
+ ACPI_MOVE_32_TO_32(&bad_name, internal_name);
+ acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
} else {
/* Convert path to external format */
@@ -102,7 +104,7 @@ acpi_ns_report_error(char *module_name,
}
if (name) {
- ACPI_MEM_FREE(name);
+ ACPI_FREE(name);
}
}
@@ -137,11 +139,12 @@ acpi_ns_report_method_error(char *module_name,
acpi_status status;
struct acpi_namespace_node *node = prefix_node;
- acpi_ut_report_error(module_name, line_number);
+ acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
if (path) {
- status = acpi_ns_get_node_by_path(path, prefix_node,
- ACPI_NS_NO_UPSEARCH, &node);
+ status =
+ acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH,
+ &node);
if (ACPI_FAILURE(status)) {
acpi_os_printf("[Could not get node by pathname]");
}
@@ -185,7 +188,7 @@ acpi_ns_print_node_pathname(struct acpi_namespace_node *node, char *message)
}
acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node);
- ACPI_MEM_FREE(buffer.pointer);
+ ACPI_FREE(buffer.pointer);
}
}
@@ -239,7 +242,7 @@ static u8 acpi_ns_valid_path_separator(char sep)
acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
{
- ACPI_FUNCTION_TRACE("ns_get_type");
+ ACPI_FUNCTION_TRACE(ns_get_type);
if (!node) {
ACPI_WARNING((AE_INFO, "Null Node parameter"));
@@ -264,9 +267,10 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
u32 acpi_ns_local(acpi_object_type type)
{
- ACPI_FUNCTION_TRACE("ns_local");
+ ACPI_FUNCTION_TRACE(ns_local);
if (!acpi_ut_valid_object_type(type)) {
+
/* Type code out of range */
ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type));
@@ -363,7 +367,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
char *result = NULL;
acpi_native_uint i;
- ACPI_FUNCTION_TRACE("ns_build_internal_name");
+ ACPI_FUNCTION_TRACE(ns_build_internal_name);
/* Setup the correct prefixes, counts, and pointers */
@@ -411,6 +415,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
for (i = 0; i < ACPI_NAME_SIZE; i++) {
if (acpi_ns_valid_path_separator(*external_name) ||
(*external_name == 0)) {
+
/* Pad the segment with underscore(s) if segment is short */
result[i] = '_';
@@ -473,7 +478,7 @@ acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name)
struct acpi_namestring_info info;
acpi_status status;
- ACPI_FUNCTION_TRACE("ns_internalize_name");
+ ACPI_FUNCTION_TRACE(ns_internalize_name);
if ((!external_name) || (*external_name == 0) || (!converted_name)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -486,7 +491,7 @@ acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name)
/* We need a segment to store the internal name */
- internal_name = ACPI_MEM_CALLOCATE(info.length);
+ internal_name = ACPI_ALLOCATE_ZEROED(info.length);
if (!internal_name) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -496,7 +501,7 @@ acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name)
info.internal_name = internal_name;
status = acpi_ns_build_internal_name(&info);
if (ACPI_FAILURE(status)) {
- ACPI_MEM_FREE(internal_name);
+ ACPI_FREE(internal_name);
return_ACPI_STATUS(status);
}
@@ -533,7 +538,7 @@ acpi_ns_externalize_name(u32 internal_name_length,
acpi_native_uint i = 0;
acpi_native_uint j = 0;
- ACPI_FUNCTION_TRACE("ns_externalize_name");
+ ACPI_FUNCTION_TRACE(ns_externalize_name);
if (!internal_name_length || !internal_name || !converted_name) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -628,7 +633,7 @@ acpi_ns_externalize_name(u32 internal_name_length,
/*
* Build converted_name
*/
- *converted_name = ACPI_MEM_CALLOCATE(required_length);
+ *converted_name = ACPI_ALLOCATE_ZEROED(required_length);
if (!(*converted_name)) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -681,13 +686,9 @@ struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle)
ACPI_FUNCTION_ENTRY();
/*
- * Simple implementation.
+ * Simple implementation
*/
- if (!handle) {
- return (NULL);
- }
-
- if (handle == ACPI_ROOT_OBJECT) {
+ if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
return (acpi_gbl_root_node);
}
@@ -697,7 +698,7 @@ struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle)
return (NULL);
}
- return ((struct acpi_namespace_node *)handle);
+ return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
}
/*******************************************************************************
@@ -752,7 +753,7 @@ void acpi_ns_terminate(void)
{
union acpi_operand_object *obj_desc;
- ACPI_FUNCTION_TRACE("ns_terminate");
+ ACPI_FUNCTION_TRACE(ns_terminate);
/*
* 1) Free the entire namespace -- all nodes and objects
@@ -792,9 +793,10 @@ void acpi_ns_terminate(void)
u32 acpi_ns_opens_scope(acpi_object_type type)
{
- ACPI_FUNCTION_TRACE_STR("ns_opens_scope", acpi_ut_get_type_name(type));
+ ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type));
if (!acpi_ut_valid_object_type(type)) {
+
/* type code out of range */
ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type));
@@ -806,12 +808,12 @@ u32 acpi_ns_opens_scope(acpi_object_type type)
/*******************************************************************************
*
- * FUNCTION: acpi_ns_get_node_by_path
+ * FUNCTION: acpi_ns_get_node
*
* PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The
* \ (backslash) and ^ (carat) prefixes, and the
* . (period) to separate segments are supported.
- * start_node - Root of subtree to be searched, or NS_ALL for the
+ * prefix_node - Root of subtree to be searched, or NS_ALL for the
* root of the name space. If Name is fully
* qualified (first s8 is '\'), the passed value
* of Scope will not be accessed.
@@ -827,23 +829,29 @@ u32 acpi_ns_opens_scope(acpi_object_type type)
******************************************************************************/
acpi_status
-acpi_ns_get_node_by_path(char *pathname,
- struct acpi_namespace_node *start_node,
- u32 flags, struct acpi_namespace_node **return_node)
+acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
+ char *pathname,
+ u32 flags, struct acpi_namespace_node **return_node)
{
union acpi_generic_state scope_info;
acpi_status status;
- char *internal_path = NULL;
-
- ACPI_FUNCTION_TRACE_PTR("ns_get_node_by_path", pathname);
+ char *internal_path;
- if (pathname) {
- /* Convert path to internal representation */
+ ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname);
- status = acpi_ns_internalize_name(pathname, &internal_path);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ if (!pathname) {
+ *return_node = prefix_node;
+ if (!prefix_node) {
+ *return_node = acpi_gbl_root_node;
}
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ /* Convert path to internal representation */
+
+ status = acpi_ns_internalize_name(pathname, &internal_path);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/* Must lock namespace during lookup */
@@ -855,26 +863,23 @@ acpi_ns_get_node_by_path(char *pathname,
/* Setup lookup scope (search starting point) */
- scope_info.scope.node = start_node;
+ scope_info.scope.node = prefix_node;
/* Lookup the name in the namespace */
- status = acpi_ns_lookup(&scope_info, internal_path,
- ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
- (flags | ACPI_NS_DONT_OPEN_SCOPE),
- NULL, return_node);
+ status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY,
+ ACPI_IMODE_EXECUTE,
+ (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL,
+ return_node);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n",
- internal_path,
- acpi_format_exception(status)));
+ pathname, acpi_format_exception(status)));
}
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
cleanup:
- if (internal_path) {
- ACPI_MEM_FREE(internal_path);
- }
+ ACPI_FREE(internal_path);
return_ACPI_STATUS(status);
}
@@ -960,9 +965,10 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node * child_node)
{
struct acpi_namespace_node *parent_node;
- ACPI_FUNCTION_TRACE("ns_find_parent_name");
+ ACPI_FUNCTION_TRACE(ns_find_parent_name);
if (child_node) {
+
/* Valid entry. Get the parent Node */
parent_node = acpi_ns_get_parent_node(child_node);
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c
index fcab1e784b8..c8f6bef16ed 100644
--- a/drivers/acpi/namespace/nswalk.c
+++ b/drivers/acpi/namespace/nswalk.c
@@ -76,6 +76,7 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type,
ACPI_FUNCTION_ENTRY();
if (!child_node) {
+
/* It's really the parent's _scope_ that we want */
if (parent_node->child) {
@@ -92,6 +93,7 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type,
/* If any type is OK, we are done */
if (type == ACPI_TYPE_ANY) {
+
/* next_node is NULL if we are at the end-of-list */
return (next_node);
@@ -100,6 +102,7 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type,
/* Must search for the node -- but within this scope only */
while (next_node) {
+
/* If type matches, we are done */
if (next_node->type == type) {
@@ -161,7 +164,7 @@ acpi_ns_walk_namespace(acpi_object_type type,
acpi_object_type child_type;
u32 level;
- ACPI_FUNCTION_TRACE("ns_walk_namespace");
+ ACPI_FUNCTION_TRACE(ns_walk_namespace);
/* Special case for the namespace Root Node */
@@ -182,6 +185,7 @@ acpi_ns_walk_namespace(acpi_object_type type,
* bubbled up to (and passed) the original parent handle (start_entry)
*/
while (level > 0) {
+
/* Get the next node in this scope. Null if not found */
status = AE_OK;
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index a95f636dc35..6d9bd45af30 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -42,8 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
@@ -51,6 +49,7 @@
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsxfeval")
+#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
* FUNCTION: acpi_evaluate_object_typed
@@ -71,18 +70,17 @@ ACPI_MODULE_NAME("nsxfeval")
* be valid (non-null)
*
******************************************************************************/
-#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_evaluate_object_typed(acpi_handle handle,
acpi_string pathname,
- struct acpi_object_list *external_params,
- struct acpi_buffer *return_buffer,
+ struct acpi_object_list * external_params,
+ struct acpi_buffer * return_buffer,
acpi_object_type return_type)
{
acpi_status status;
u8 must_free = FALSE;
- ACPI_FUNCTION_TRACE("acpi_evaluate_object_typed");
+ ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed);
/* Return buffer must be valid */
@@ -110,6 +108,7 @@ acpi_evaluate_object_typed(acpi_handle handle,
}
if (return_buffer->length == 0) {
+
/* Error because caller specifically asked for a return value */
ACPI_ERROR((AE_INFO, "No return value"));
@@ -131,6 +130,7 @@ acpi_evaluate_object_typed(acpi_handle handle,
acpi_ut_get_type_name(return_type)));
if (must_free) {
+
/* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
acpi_os_free(return_buffer->pointer);
@@ -140,6 +140,8 @@ acpi_evaluate_object_typed(acpi_handle handle,
return_buffer->length = 0;
return_ACPI_STATUS(AE_TYPE);
}
+
+ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
@@ -161,7 +163,6 @@ acpi_evaluate_object_typed(acpi_handle handle,
* be valid (non-null)
*
******************************************************************************/
-
acpi_status
acpi_evaluate_object(acpi_handle handle,
acpi_string pathname,
@@ -170,51 +171,61 @@ acpi_evaluate_object(acpi_handle handle,
{
acpi_status status;
acpi_status status2;
- struct acpi_parameter_info info;
+ struct acpi_evaluate_info *info;
acpi_size buffer_space_needed;
u32 i;
- ACPI_FUNCTION_TRACE("acpi_evaluate_object");
+ ACPI_FUNCTION_TRACE(acpi_evaluate_object);
- info.node = handle;
- info.parameters = NULL;
- info.return_object = NULL;
- info.parameter_type = ACPI_PARAM_ARGS;
+ /* Allocate and initialize the evaluation information block */
+
+ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+ if (!info) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ info->pathname = pathname;
+ info->parameter_type = ACPI_PARAM_ARGS;
+
+ /* Convert and validate the device handle */
+
+ info->prefix_node = acpi_ns_map_handle_to_node(handle);
+ if (!info->prefix_node) {
+ status = AE_BAD_PARAMETER;
+ goto cleanup;
+ }
/*
- * If there are parameters to be passed to the object
- * (which must be a control method), the external objects
- * must be converted to internal objects
+ * If there are parameters to be passed to a control method, the external
+ * objects must all be converted to internal objects
*/
if (external_params && external_params->count) {
/*
* Allocate a new parameter block for the internal objects
* Add 1 to count to allow for null terminated internal list
*/
- info.parameters = ACPI_MEM_CALLOCATE(((acpi_size)
- external_params->count +
- 1) * sizeof(void *));
- if (!info.parameters) {
- return_ACPI_STATUS(AE_NO_MEMORY);
+ info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
+ external_params->
+ count +
+ 1) * sizeof(void *));
+ if (!info->parameters) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
}
- /*
- * Convert each external object in the list to an
- * internal object
- */
+ /* Convert each external object in the list to an internal object */
+
for (i = 0; i < external_params->count; i++) {
status =
acpi_ut_copy_eobject_to_iobject(&external_params->
pointer[i],
- &info.
+ &info->
parameters[i]);
if (ACPI_FAILURE(status)) {
- acpi_ut_delete_internal_object_list(info.
- parameters);
- return_ACPI_STATUS(status);
+ goto cleanup;
}
}
- info.parameters[external_params->count] = NULL;
+ info->parameters[external_params->count] = NULL;
}
/*
@@ -224,43 +235,31 @@ acpi_evaluate_object(acpi_handle handle,
* 3) Valid handle
*/
if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) {
- /*
- * The path is fully qualified, just evaluate by name
- */
- status = acpi_ns_evaluate_by_name(pathname, &info);
+
+ /* The path is fully qualified, just evaluate by name */
+
+ info->prefix_node = NULL;
+ status = acpi_ns_evaluate(info);
} else if (!handle) {
/*
- * A handle is optional iff a fully qualified pathname
- * is specified. Since we've already handled fully
- * qualified names above, this is an error
+ * A handle is optional iff a fully qualified pathname is specified.
+ * Since we've already handled fully qualified names above, this is
+ * an error
*/
if (!pathname) {
- ACPI_ERROR((AE_INFO,
- "Both Handle and Pathname are NULL"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Both Handle and Pathname are NULL"));
} else {
- ACPI_ERROR((AE_INFO,
- "Handle is NULL and Pathname is relative"));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Null Handle with relative pathname [%s]",
+ pathname));
}
status = AE_BAD_PARAMETER;
} else {
- /*
- * We get here if we have a handle -- and if we have a
- * pathname it is relative. The handle will be validated
- * in the lower procedures
- */
- if (!pathname) {
- /*
- * The null pathname case means the handle is for
- * the actual object to be evaluated
- */
- status = acpi_ns_evaluate_by_handle(&info);
- } else {
- /*
- * Both a Handle and a relative Pathname
- */
- status = acpi_ns_evaluate_relative(pathname, &info);
- }
+ /* We have a namespace a node and a possible relative path */
+
+ status = acpi_ns_evaluate(info);
}
/*
@@ -268,10 +267,10 @@ acpi_evaluate_object(acpi_handle handle,
* copy the return value to an external object.
*/
if (return_buffer) {
- if (!info.return_object) {
+ if (!info->return_object) {
return_buffer->length = 0;
} else {
- if (ACPI_GET_DESCRIPTOR_TYPE(info.return_object) ==
+ if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
ACPI_DESC_TYPE_NAMED) {
/*
* If we received a NS Node as a return object, this means that
@@ -282,19 +281,19 @@ acpi_evaluate_object(acpi_handle handle,
* support for various types at a later date if necessary.
*/
status = AE_TYPE;
- info.return_object = NULL; /* No need to delete a NS Node */
+ info->return_object = NULL; /* No need to delete a NS Node */
return_buffer->length = 0;
}
if (ACPI_SUCCESS(status)) {
- /*
- * Find out how large a buffer is needed
- * to contain the returned object
- */
+
+ /* Get the size of the returned object */
+
status =
- acpi_ut_get_object_size(info.return_object,
+ acpi_ut_get_object_size(info->return_object,
&buffer_space_needed);
if (ACPI_SUCCESS(status)) {
+
/* Validate/Allocate/Clear caller buffer */
status =
@@ -303,7 +302,8 @@ acpi_evaluate_object(acpi_handle handle,
buffer_space_needed);
if (ACPI_FAILURE(status)) {
/*
- * Caller's buffer is too small or a new one can't be allocated
+ * Caller's buffer is too small or a new one can't
+ * be allocated
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Needed buffer size %X, %s\n",
@@ -312,12 +312,11 @@ acpi_evaluate_object(acpi_handle handle,
acpi_format_exception
(status)));
} else {
- /*
- * We have enough space for the object, build it
- */
+ /* We have enough space for the object, build it */
+
status =
acpi_ut_copy_iobject_to_eobject
- (info.return_object,
+ (info->return_object,
return_buffer);
}
}
@@ -325,35 +324,37 @@ acpi_evaluate_object(acpi_handle handle,
}
}
- if (info.return_object) {
+ if (info->return_object) {
/*
- * Delete the internal return object. NOTE: Interpreter
- * must be locked to avoid race condition.
+ * Delete the internal return object. NOTE: Interpreter must be
+ * locked to avoid race condition.
*/
status2 = acpi_ex_enter_interpreter();
if (ACPI_SUCCESS(status2)) {
- /*
- * Delete the internal return object. (Or at least
- * decrement the reference count by one)
- */
- acpi_ut_remove_reference(info.return_object);
+
+ /* Remove one reference on the return object (should delete it) */
+
+ acpi_ut_remove_reference(info->return_object);
acpi_ex_exit_interpreter();
}
}
- /*
- * Free the input parameter list (if we created one),
- */
- if (info.parameters) {
+ cleanup:
+
+ /* Free the input parameter list (if we created one) */
+
+ if (info->parameters) {
+
/* Free the allocated parameter block */
- acpi_ut_delete_internal_object_list(info.parameters);
+ acpi_ut_delete_internal_object_list(info->parameters);
}
+ ACPI_FREE(info);
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_evaluate_object);
+ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
/*******************************************************************************
*
@@ -384,7 +385,6 @@ EXPORT_SYMBOL(acpi_evaluate_object);
* function, etc.
*
******************************************************************************/
-
acpi_status
acpi_walk_namespace(acpi_object_type type,
acpi_handle start_object,
@@ -394,7 +394,7 @@ acpi_walk_namespace(acpi_object_type type,
{
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_walk_namespace");
+ ACPI_FUNCTION_TRACE(acpi_walk_namespace);
/* Parameter validation */
@@ -421,7 +421,7 @@ acpi_walk_namespace(acpi_object_type type,
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_walk_namespace);
+ACPI_EXPORT_SYMBOL(acpi_walk_namespace)
/*******************************************************************************
*
@@ -436,7 +436,6 @@ EXPORT_SYMBOL(acpi_walk_namespace);
* on that.
*
******************************************************************************/
-
static acpi_status
acpi_ns_get_device_callback(acpi_handle obj_handle,
u32 nesting_level,
@@ -473,6 +472,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
}
if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
+
/* Don't examine children of the device if not present */
return (AE_CTRL_DEPTH);
@@ -489,6 +489,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
}
if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) {
+
/* Get the list of Compatible IDs */
status = acpi_ut_execute_CID(node, &cid);
@@ -505,11 +506,11 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
sizeof(struct
acpi_compatible_id)) !=
0) {
- ACPI_MEM_FREE(cid);
+ ACPI_FREE(cid);
return (AE_OK);
}
}
- ACPI_MEM_FREE(cid);
+ ACPI_FREE(cid);
}
}
@@ -551,7 +552,7 @@ acpi_get_devices(char *HID,
acpi_status status;
struct acpi_get_devices_info info;
- ACPI_FUNCTION_TRACE("acpi_get_devices");
+ ACPI_FUNCTION_TRACE(acpi_get_devices);
/* Parameter validation */
@@ -563,9 +564,9 @@ acpi_get_devices(char *HID,
* We're going to call their callback from OUR callback, so we need
* to know what it is, and their context parameter.
*/
+ info.hid = HID;
info.context = context;
info.user_function = user_function;
- info.hid = HID;
/*
* Lock the namespace around the walk.
@@ -578,9 +579,8 @@ acpi_get_devices(char *HID,
return_ACPI_STATUS(status);
}
- status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE,
- ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK,
+ status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
acpi_ns_get_device_callback, &info,
return_value);
@@ -588,7 +588,7 @@ acpi_get_devices(char *HID,
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_devices);
+ACPI_EXPORT_SYMBOL(acpi_get_devices)
/*******************************************************************************
*
@@ -603,7 +603,6 @@ EXPORT_SYMBOL(acpi_get_devices);
* DESCRIPTION: Attach arbitrary data and handler to a namespace node.
*
******************************************************************************/
-
acpi_status
acpi_attach_data(acpi_handle obj_handle,
acpi_object_handler handler, void *data)
@@ -637,6 +636,8 @@ acpi_attach_data(acpi_handle obj_handle,
return (status);
}
+ACPI_EXPORT_SYMBOL(acpi_attach_data)
+
/*******************************************************************************
*
* FUNCTION: acpi_detach_data
@@ -649,7 +650,6 @@ acpi_attach_data(acpi_handle obj_handle,
* DESCRIPTION: Remove data that was previously attached to a node.
*
******************************************************************************/
-
acpi_status
acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
{
@@ -682,6 +682,8 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
return (status);
}
+ACPI_EXPORT_SYMBOL(acpi_detach_data)
+
/*******************************************************************************
*
* FUNCTION: acpi_get_data
@@ -695,7 +697,6 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
* DESCRIPTION: Retrieve data that was previously attached to a namespace node.
*
******************************************************************************/
-
acpi_status
acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
{
@@ -727,3 +728,5 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return (status);
}
+
+ACPI_EXPORT_SYMBOL(acpi_get_data)
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
index 8cd8675a47c..978213a6c19 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -42,8 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
@@ -114,9 +112,8 @@ acpi_get_handle(acpi_handle parent,
/*
* Find the Node and convert to a handle
*/
- status =
- acpi_ns_get_node_by_path(pathname, prefix_node, ACPI_NS_NO_UPSEARCH,
- &node);
+ status = acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH,
+ &node);
*ret_handle = NULL;
if (ACPI_SUCCESS(status)) {
@@ -126,7 +123,7 @@ acpi_get_handle(acpi_handle parent,
return (status);
}
-EXPORT_SYMBOL(acpi_get_handle);
+ACPI_EXPORT_SYMBOL(acpi_get_handle)
/******************************************************************************
*
@@ -143,7 +140,6 @@ EXPORT_SYMBOL(acpi_get_handle);
* complementary functions.
*
******************************************************************************/
-
acpi_status
acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
{
@@ -162,6 +158,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
}
if (name_type == ACPI_FULL_PATHNAME) {
+
/* Get the full pathname (From the namespace root) */
status = acpi_ns_handle_to_pathname(handle, buffer);
@@ -203,7 +200,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
return (status);
}
-EXPORT_SYMBOL(acpi_get_name);
+ACPI_EXPORT_SYMBOL(acpi_get_name)
/******************************************************************************
*
@@ -219,7 +216,6 @@ EXPORT_SYMBOL(acpi_get_name);
* control methods (Such as in the case of a device.)
*
******************************************************************************/
-
acpi_status
acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
{
@@ -241,7 +237,7 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
return (status);
}
- info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_device_info));
+ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info));
if (!info) {
return (AE_NO_MEMORY);
}
@@ -345,11 +341,11 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
}
cleanup:
- ACPI_MEM_FREE(info);
+ ACPI_FREE(info);
if (cid_list) {
- ACPI_MEM_FREE(cid_list);
+ ACPI_FREE(cid_list);
}
return (status);
}
-EXPORT_SYMBOL(acpi_get_object_info);
+ACPI_EXPORT_SYMBOL(acpi_get_object_info)
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
index a0332595677..a163e1d3708 100644
--- a/drivers/acpi/namespace/nsxfobj.c
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -42,8 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
@@ -101,7 +99,7 @@ acpi_status acpi_get_type(acpi_handle handle, acpi_object_type * ret_type)
return (status);
}
-EXPORT_SYMBOL(acpi_get_type);
+ACPI_EXPORT_SYMBOL(acpi_get_type)
/*******************************************************************************
*
@@ -116,7 +114,6 @@ EXPORT_SYMBOL(acpi_get_type);
* Handle.
*
******************************************************************************/
-
acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle)
{
struct acpi_namespace_node *node;
@@ -162,7 +159,7 @@ acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle)
return (status);
}
-EXPORT_SYMBOL(acpi_get_parent);
+ACPI_EXPORT_SYMBOL(acpi_get_parent)
/*******************************************************************************
*
@@ -181,7 +178,6 @@ EXPORT_SYMBOL(acpi_get_parent);
* Scope is returned.
*
******************************************************************************/
-
acpi_status
acpi_get_next_object(acpi_object_type type,
acpi_handle parent,
@@ -206,6 +202,7 @@ acpi_get_next_object(acpi_object_type type,
/* If null handle, use the parent */
if (!child) {
+
/* Start search at the beginning of the specified scope */
parent_node = acpi_ns_map_handle_to_node(parent);
@@ -242,4 +239,4 @@ acpi_get_next_object(acpi_object_type type,
return (status);
}
-EXPORT_SYMBOL(acpi_get_next_object);
+ACPI_EXPORT_SYMBOL(acpi_get_next_object)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 13b5fd5854a..1bb558adee6 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -37,6 +37,7 @@
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/nmi.h>
+#include <linux/kthread.h>
#include <acpi/acpi.h>
#include <asm/io.h>
#include <acpi/acpi_bus.h>
@@ -600,23 +601,41 @@ static void acpi_os_execute_deferred(void *context)
return_VOID;
}
-acpi_status
-acpi_os_queue_for_execution(u32 priority,
+static int acpi_os_execute_thread(void *context)
+{
+ struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context;
+ if (dpc) {
+ dpc->function(dpc->context);
+ kfree(dpc);
+ }
+ do_exit(0);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_execute
+ *
+ * PARAMETERS: Type - Type of the callback
+ * Function - Function to be executed
+ * Context - Function parameters
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Depending on type, either queues function for deferred execution or
+ * immediately executes function on a separate thread.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_execute(acpi_execute_type type,
acpi_osd_exec_callback function, void *context)
{
acpi_status status = AE_OK;
struct acpi_os_dpc *dpc;
struct work_struct *task;
-
- ACPI_FUNCTION_TRACE("os_queue_for_execution");
-
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Scheduling function [%p(%p)] for deferred execution.\n",
- function, context));
+ struct task_struct *p;
if (!function)
- return_ACPI_STATUS(AE_BAD_PARAMETER);
-
+ return AE_BAD_PARAMETER;
/*
* Allocate/initialize DPC structure. Note that this memory will be
* freed by the callee. The kernel handles the tq_struct list in a
@@ -627,30 +646,37 @@ acpi_os_queue_for_execution(u32 priority,
* We can save time and code by allocating the DPC and tq_structs
* from the same memory.
*/
-
- dpc =
- kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct),
- GFP_ATOMIC);
+ if (type == OSL_NOTIFY_HANDLER) {
+ dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_KERNEL);
+ } else {
+ dpc = kmalloc(sizeof(struct acpi_os_dpc) +
+ sizeof(struct work_struct), GFP_ATOMIC);
+ }
if (!dpc)
- return_ACPI_STATUS(AE_NO_MEMORY);
-
+ return AE_NO_MEMORY;
dpc->function = function;
dpc->context = context;
- task = (void *)(dpc + 1);
- INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
-
- if (!queue_work(kacpid_wq, task)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Call to queue_work() failed.\n"));
- kfree(dpc);
- status = AE_ERROR;
+ if (type == OSL_NOTIFY_HANDLER) {
+ p = kthread_create(acpi_os_execute_thread, dpc, "kacpid_notify");
+ if (!IS_ERR(p)) {
+ wake_up_process(p);
+ } else {
+ status = AE_NO_MEMORY;
+ kfree(dpc);
+ }
+ } else {
+ task = (void *)(dpc + 1);
+ INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
+ if (!queue_work(kacpid_wq, task)) {
+ status = AE_ERROR;
+ kfree(dpc);
+ }
}
-
- return_ACPI_STATUS(status);
+ return status;
}
-EXPORT_SYMBOL(acpi_os_queue_for_execution);
+EXPORT_SYMBOL(acpi_os_execute);
void acpi_os_wait_events_complete(void *context)
{
@@ -769,9 +795,6 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
handle, units, timeout));
- if (in_atomic())
- timeout = 0;
-
switch (timeout) {
/*
* No Wait:
@@ -896,14 +919,6 @@ u8 acpi_os_writable(void *ptr, acpi_size len)
}
#endif
-u32 acpi_os_get_thread_id(void)
-{
- if (!in_atomic())
- return current->pid;
-
- return 0;
-}
-
acpi_status acpi_os_signal(u32 function, void *info)
{
switch (function) {
@@ -1050,12 +1065,12 @@ void acpi_os_release_lock(acpi_handle handle, acpi_cpu_flags flags)
*
* FUNCTION: acpi_os_create_cache
*
- * PARAMETERS: CacheName - Ascii name for the cache
- * ObjectSize - Size of each cached object
- * MaxDepth - Maximum depth of the cache (in objects)
- * ReturnCache - Where the new cache object is returned
+ * PARAMETERS: name - Ascii name for the cache
+ * size - Size of each cached object
+ * depth - Maximum depth of the cache (in objects) <ignored>
+ * cache - Where the new cache object is returned
*
- * RETURN: Status
+ * RETURN: status
*
* DESCRIPTION: Create a cache object
*
@@ -1065,7 +1080,10 @@ acpi_status
acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
{
*cache = kmem_cache_create(name, size, 0, 0, NULL, NULL);
- return AE_OK;
+ if (cache == NULL)
+ return AE_ERROR;
+ else
+ return AE_OK;
}
/*******************************************************************************
@@ -1134,16 +1152,63 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
*
* RETURN: Status
*
- * DESCRIPTION: Get an object from the specified cache. If cache is empty,
- * the object is allocated.
+ * DESCRIPTION: Return a zero-filled object.
*
******************************************************************************/
void *acpi_os_acquire_object(acpi_cache_t * cache)
{
- void *object = kmem_cache_alloc(cache, GFP_KERNEL);
+ void *object = kmem_cache_zalloc(cache, GFP_KERNEL);
WARN_ON(!object);
return object;
}
+/******************************************************************************
+ *
+ * FUNCTION: acpi_os_validate_interface
+ *
+ * PARAMETERS: interface - Requested interface to be validated
+ *
+ * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise
+ *
+ * DESCRIPTION: Match an interface string to the interfaces supported by the
+ * host. Strings originate from an AML call to the _OSI method.
+ *
+ *****************************************************************************/
+
+acpi_status
+acpi_os_validate_interface (char *interface)
+{
+
+ return AE_SUPPORT;
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_os_validate_address
+ *
+ * PARAMETERS: space_id - ACPI space ID
+ * address - Physical address
+ * length - Address length
+ *
+ * RETURN: AE_OK if address/length is valid for the space_id. Otherwise,
+ * should return AE_AML_ILLEGAL_ADDRESS.
+ *
+ * DESCRIPTION: Validate a system address via the host OS. Used to validate
+ * the addresses accessed by AML operation regions.
+ *
+ *****************************************************************************/
+
+acpi_status
+acpi_os_validate_address (
+ u8 space_id,
+ acpi_physical_address address,
+ acpi_size length)
+{
+
+ return AE_OK;
+}
+
+
#endif
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c
index de573be5271..bf88e076c3e 100644
--- a/drivers/acpi/parser/psargs.c
+++ b/drivers/acpi/parser/psargs.c
@@ -79,7 +79,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
acpi_native_uint byte_count;
u8 byte_zero_mask = 0x3F; /* Default [0:5] */
- ACPI_FUNCTION_TRACE("ps_get_next_package_length");
+ ACPI_FUNCTION_TRACE(ps_get_next_package_length);
/*
* Byte 0 bits [6:7] contain the number of additional bytes
@@ -128,7 +128,7 @@ u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state)
u8 *start = parser_state->aml;
u32 package_length;
- ACPI_FUNCTION_TRACE("ps_get_next_package_end");
+ ACPI_FUNCTION_TRACE(ps_get_next_package_end);
/* Function below updates parser_state->Aml */
@@ -157,7 +157,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
u8 *start = parser_state->aml;
u8 *end = parser_state->aml;
- ACPI_FUNCTION_TRACE("ps_get_next_namestring");
+ ACPI_FUNCTION_TRACE(ps_get_next_namestring);
/* Point past any namestring prefix characters (backslash or carat) */
@@ -237,7 +237,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
struct acpi_namespace_node *node;
union acpi_generic_state scope_info;
- ACPI_FUNCTION_TRACE("ps_get_next_namepath");
+ ACPI_FUNCTION_TRACE(ps_get_next_namepath);
path = acpi_ps_get_next_namestring(parser_state);
acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
@@ -275,6 +275,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
*/
if (ACPI_SUCCESS(status) &&
possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
+
/* This name is actually a control method invocation */
method_desc = acpi_ns_get_attached_object(node);
@@ -319,6 +320,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
* some not_found cases are allowed
*/
if (status == AE_NOT_FOUND) {
+
/* 1) not_found is ok during load pass 1/2 (allow forward references) */
if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) !=
@@ -354,6 +356,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
ACPI_PARSE_EXECUTE) {
+
/* Report a control method execution error */
status = acpi_ds_method_error(status, walk_state);
@@ -388,7 +391,7 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
u16 opcode;
u8 *aml = parser_state->aml;
- ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type);
+ ACPI_FUNCTION_TRACE_U32(ps_get_next_simple_arg, arg_type);
switch (arg_type) {
case ARGP_BYTEDATA:
@@ -453,7 +456,7 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
default:
- ACPI_ERROR((AE_INFO, "Invalid arg_type %X", arg_type));
+ ACPI_ERROR((AE_INFO, "Invalid ArgType %X", arg_type));
return_VOID;
}
@@ -484,7 +487,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
u16 opcode;
u32 name;
- ACPI_FUNCTION_TRACE("ps_get_next_field");
+ ACPI_FUNCTION_TRACE(ps_get_next_field);
/* Determine field type */
@@ -590,7 +593,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
u32 subop;
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE_PTR("ps_get_next_arg", parser_state);
+ ACPI_FUNCTION_TRACE_PTR(ps_get_next_arg, parser_state);
switch (arg_type) {
case ARGP_BYTEDATA:
@@ -620,6 +623,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
case ARGP_FIELDLIST:
if (parser_state->aml < parser_state->pkg_end) {
+
/* Non-empty list */
while (parser_state->aml < parser_state->pkg_end) {
@@ -645,6 +649,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
case ARGP_BYTELIST:
if (parser_state->aml < parser_state->pkg_end) {
+
/* Non-empty list */
arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP);
@@ -673,6 +678,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
if (subop == 0 ||
acpi_ps_is_leading_char(subop) ||
acpi_ps_is_prefix_char(subop)) {
+
/* null_name or name_string */
arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
@@ -703,6 +709,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
case ARGP_OBJLIST:
if (parser_state->aml < parser_state->pkg_end) {
+
/* Non-empty list of variable arguments, nothing returned */
walk_state->arg_count = ACPI_VAR_ARGS;
@@ -711,7 +718,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
default:
- ACPI_ERROR((AE_INFO, "Invalid arg_type: %X", arg_type));
+ ACPI_ERROR((AE_INFO, "Invalid ArgType: %X", arg_type));
status = AE_AML_OPERAND_TYPE;
break;
}
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c
index 00b072e15d1..e1541db3753 100644
--- a/drivers/acpi/parser/psloop.c
+++ b/drivers/acpi/parser/psloop.c
@@ -83,7 +83,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
struct acpi_parse_state *parser_state;
u8 *aml_op_start = NULL;
- ACPI_FUNCTION_TRACE_PTR("ps_parse_loop", walk_state);
+ ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state);
if (walk_state->descending_callback == NULL) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -95,6 +95,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
+
/* We are restarting a preempted control method */
if (acpi_ps_has_completed_scope(parser_state)) {
@@ -128,7 +129,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
}
ACPI_EXCEPTION((AE_INFO, status,
- "get_predicate Failed"));
+ "GetPredicate Failed"));
return_ACPI_STATUS(status);
}
@@ -143,6 +144,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
"Popped scope, Op=%p\n", op));
} else if (walk_state->prev_op) {
+
/* We were in the middle of an op */
op = walk_state->prev_op;
@@ -156,6 +158,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
while ((parser_state->aml < parser_state->aml_end) || (op)) {
aml_op_start = parser_state->aml;
if (!op) {
+
/* Get the next opcode from the AML stream */
walk_state->aml_offset =
@@ -213,6 +216,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
/* Create Op structure and append to parent's argument list */
if (walk_state->op_info->flags & AML_NAMED) {
+
/* Allocate a new pre_op if necessary */
if (!pre_op) {
@@ -371,7 +375,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
if (walk_state->op_info) {
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n",
+ "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
(u32) op->common.aml_opcode,
walk_state->op_info->name, op,
parser_state->aml,
@@ -388,6 +392,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
/* Are there any arguments that must be processed? */
if (walk_state->arg_types) {
+
/* Get arguments */
switch (op->common.aml_opcode) {
@@ -742,7 +747,19 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
if (ACPI_FAILURE(status2)) {
return_ACPI_STATUS(status2);
}
+
+ status2 =
+ acpi_ds_result_stack_pop
+ (walk_state);
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
+ }
+
+ acpi_ut_delete_generic_state
+ (acpi_ut_pop_generic_state
+ (&walk_state->control_state));
}
+
acpi_ps_pop_scope(parser_state, &op,
&walk_state->arg_types,
&walk_state->arg_count);
@@ -762,6 +779,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
return_ACPI_STATUS(status2);
}
}
+
acpi_ps_pop_scope(parser_state, &op,
&walk_state->arg_types,
&walk_state->arg_count);
@@ -853,6 +871,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
}
else if (ACPI_FAILURE(status)) {
+
/* First error is most important */
(void)
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index 11d6351ab8b..4bd25e32769 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -725,12 +725,13 @@ static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = {
const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode)
{
- ACPI_FUNCTION_NAME("ps_get_opcode_info");
+ ACPI_FUNCTION_NAME(ps_get_opcode_info);
/*
* Detect normal 8-bit opcode or extended 16-bit opcode
*/
if (!(opcode & 0xFF00)) {
+
/* Simple (8-bit) opcode: 0-255, can't index beyond table */
return (&acpi_gbl_aml_op_info
@@ -739,6 +740,7 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode)
if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) &&
(((u8) opcode) <= MAX_EXTENDED_OPCODE)) {
+
/* Valid extended (16-bit) opcode */
return (&acpi_gbl_aml_op_info
@@ -779,7 +781,7 @@ char *acpi_ps_get_opcode_name(u16 opcode)
return (op->name);
#else
- return ("AE_NOT_CONFIGURED");
+ return ("OpcodeName unavailable");
#endif
}
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index a9f3229f410..7ee2f2e7752 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -106,6 +106,7 @@ u16 acpi_ps_peek_opcode(struct acpi_parse_state * parser_state)
opcode = (u16) ACPI_GET8(aml);
if (opcode == AML_EXTENDED_OP_PREFIX) {
+
/* Extended opcode, get the second opcode byte */
aml++;
@@ -137,7 +138,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
const struct acpi_opcode_info *parent_info;
union acpi_parse_object *replacement_op = NULL;
- ACPI_FUNCTION_TRACE_PTR("ps_complete_this_op", op);
+ ACPI_FUNCTION_TRACE_PTR(ps_complete_this_op, op);
/* Check for null Op, can happen if AML code is corrupt */
@@ -158,6 +159,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
if (op->common.parent) {
prev = op->common.parent->common.value.arg;
if (!prev) {
+
/* Nothing more to do */
goto cleanup;
@@ -245,6 +247,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
/* We must unlink this op from the parent tree */
if (prev == op) {
+
/* This op is the first in the list */
if (replacement_op) {
@@ -265,6 +268,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
else
while (prev) {
+
/* Traverse all siblings in the parent's argument list */
next = prev->common.next;
@@ -329,7 +333,7 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
struct acpi_parse_state *parser_state = &walk_state->parser_state;
acpi_status status = AE_CTRL_PENDING;
- ACPI_FUNCTION_TRACE_PTR("ps_next_parse_state", op);
+ ACPI_FUNCTION_TRACE_PTR(ps_next_parse_state, op);
switch (callback_status) {
case AE_CTRL_TERMINATE:
@@ -449,10 +453,10 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list;
struct acpi_walk_state *previous_walk_state;
- ACPI_FUNCTION_TRACE("ps_parse_aml");
+ ACPI_FUNCTION_TRACE(ps_parse_aml);
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "Entered with walk_state=%p Aml=%p size=%X\n",
+ "Entered with WalkState=%p Aml=%p size=%X\n",
walk_state, walk_state->parser_state.aml,
walk_state->parser_state.aml_size));
@@ -460,6 +464,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
thread = acpi_ut_create_thread_state();
if (!thread) {
+ acpi_ds_delete_walk_state(walk_state);
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -510,6 +515,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
} else if (status == AE_CTRL_TERMINATE) {
status = AE_OK;
} else if ((status != AE_OK) && (walk_state->method_desc)) {
+
/* Either the method parse or actual execution failed */
ACPI_ERROR_METHOD("Method parse/execution failed",
@@ -550,20 +556,9 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
*/
if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) {
- if (walk_state->method_desc) {
- /* Decrement the thread count on the method parse tree */
-
- if (walk_state->method_desc->method.
- thread_count) {
- walk_state->method_desc->method.
- thread_count--;
- } else {
- ACPI_ERROR((AE_INFO,
- "Invalid zero thread count in method"));
- }
- }
-
- acpi_ds_terminate_control_method(walk_state);
+ acpi_ds_terminate_control_method(walk_state->
+ method_desc,
+ walk_state);
}
/* Delete this walk state and all linked control states */
@@ -572,7 +567,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
previous_walk_state = walk_state;
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "return_value=%p, implicit_value=%p State=%p\n",
+ "ReturnValue=%p, ImplicitValue=%p State=%p\n",
walk_state->return_desc,
walk_state->implicit_return_obj, walk_state));
@@ -633,12 +628,14 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
}
} else {
if (previous_walk_state->return_desc) {
+
/* Caller doesn't want it, must delete it */
acpi_ut_remove_reference(previous_walk_state->
return_desc);
}
if (previous_walk_state->implicit_return_obj) {
+
/* Caller doesn't want it, must delete it */
acpi_ut_remove_reference(previous_walk_state->
diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c
index bc6047caccd..a3e0314de24 100644
--- a/drivers/acpi/parser/psscope.c
+++ b/drivers/acpi/parser/psscope.c
@@ -106,14 +106,14 @@ acpi_ps_init_scope(struct acpi_parse_state * parser_state,
{
union acpi_generic_state *scope;
- ACPI_FUNCTION_TRACE_PTR("ps_init_scope", root_op);
+ ACPI_FUNCTION_TRACE_PTR(ps_init_scope, root_op);
scope = acpi_ut_create_generic_state();
if (!scope) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
- scope->common.data_type = ACPI_DESC_TYPE_STATE_RPSCOPE;
+ scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_RPSCOPE;
scope->parse_scope.op = root_op;
scope->parse_scope.arg_count = ACPI_VAR_ARGS;
scope->parse_scope.arg_end = parser_state->aml_end;
@@ -147,14 +147,14 @@ acpi_ps_push_scope(struct acpi_parse_state *parser_state,
{
union acpi_generic_state *scope;
- ACPI_FUNCTION_TRACE_PTR("ps_push_scope", op);
+ ACPI_FUNCTION_TRACE_PTR(ps_push_scope, op);
scope = acpi_ut_create_generic_state();
if (!scope) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
- scope->common.data_type = ACPI_DESC_TYPE_STATE_PSCOPE;
+ scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_PSCOPE;
scope->parse_scope.op = op;
scope->parse_scope.arg_list = remaining_args;
scope->parse_scope.arg_count = arg_count;
@@ -165,6 +165,7 @@ acpi_ps_push_scope(struct acpi_parse_state *parser_state,
acpi_ut_push_generic_state(&parser_state->scope, scope);
if (arg_count == ACPI_VAR_ARGS) {
+
/* Multiple arguments */
scope->parse_scope.arg_end = parser_state->pkg_end;
@@ -199,14 +200,14 @@ acpi_ps_pop_scope(struct acpi_parse_state *parser_state,
{
union acpi_generic_state *scope = parser_state->scope;
- ACPI_FUNCTION_TRACE("ps_pop_scope");
+ ACPI_FUNCTION_TRACE(ps_pop_scope);
/* Only pop the scope if there is in fact a next scope */
if (scope->common.next) {
scope = acpi_ut_pop_generic_state(&parser_state->scope);
- /* return to parsing previous op */
+ /* Return to parsing previous op */
*op = scope->parse_scope.op;
*arg_list = scope->parse_scope.arg_list;
@@ -217,7 +218,7 @@ acpi_ps_pop_scope(struct acpi_parse_state *parser_state,
acpi_ut_delete_generic_state(scope);
} else {
- /* empty parse stack, prepare to fetch next opcode */
+ /* Empty parse stack, prepare to fetch next opcode */
*op = NULL;
*arg_list = 0;
@@ -246,7 +247,7 @@ void acpi_ps_cleanup_scope(struct acpi_parse_state *parser_state)
{
union acpi_generic_state *scope;
- ACPI_FUNCTION_TRACE_PTR("ps_cleanup_scope", parser_state);
+ ACPI_FUNCTION_TRACE_PTR(ps_cleanup_scope, parser_state);
if (!parser_state) {
return_VOID;
diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c
index dd6f16726fc..0015717ef09 100644
--- a/drivers/acpi/parser/pstree.c
+++ b/drivers/acpi/parser/pstree.c
@@ -77,6 +77,7 @@ union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn)
op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
+
/* Invalid opcode or ASCII character */
return (NULL);
@@ -85,6 +86,7 @@ union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn)
/* Check if this opcode requires argument sub-objects */
if (!(op_info->flags & AML_HAS_ARGS)) {
+
/* Has no linked argument objects */
return (NULL);
@@ -130,6 +132,7 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg)
op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
if (op_info->class == AML_CLASS_UNKNOWN) {
+
/* Invalid opcode */
ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X",
@@ -140,6 +143,7 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg)
/* Check if this opcode requires argument sub-objects */
if (!(op_info->flags & AML_HAS_ARGS)) {
+
/* Has no linked argument objects */
return;
@@ -148,6 +152,7 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg)
/* Append the argument to the linked argument list */
if (op->common.value.arg) {
+
/* Append to existing argument list */
prev_arg = op->common.value.arg;
@@ -222,12 +227,14 @@ union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
}
if (arg == origin) {
+
/* Reached parent of origin, end search */
return (NULL);
}
if (parent->common.next) {
+
/* Found sibling of parent */
return (parent->common.next);
@@ -299,5 +306,4 @@ union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op)
return (child);
}
#endif
-
#endif /* ACPI_FUTURE_USAGE */
diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c
index 3e07cb9cb74..182474ae8ce 100644
--- a/drivers/acpi/parser/psutils.c
+++ b/drivers/acpi/parser/psutils.c
@@ -89,7 +89,7 @@ void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode)
{
ACPI_FUNCTION_ENTRY();
- op->common.data_type = ACPI_DESC_TYPE_PARSER;
+ op->common.descriptor_type = ACPI_DESC_TYPE_PARSER;
op->common.aml_opcode = opcode;
ACPI_DISASM_ONLY_MEMBERS(ACPI_STRNCPY(op->common.aml_op_name,
@@ -135,6 +135,7 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode)
/* Allocate the minimum required size object */
if (flags == ACPI_PARSEOP_GENERIC) {
+
/* The generic op (default) is by far the most common (16 to 1) */
op = acpi_os_acquire_object(acpi_gbl_ps_node_cache);
@@ -171,7 +172,7 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode)
void acpi_ps_free_op(union acpi_parse_object *op)
{
- ACPI_FUNCTION_NAME("ps_free_op");
+ ACPI_FUNCTION_NAME(ps_free_op);
if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n",
diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c
index 06f05bfd761..a84a547a0f1 100644
--- a/drivers/acpi/parser/pswalk.c
+++ b/drivers/acpi/parser/pswalk.c
@@ -64,18 +64,21 @@ void acpi_ps_delete_parse_tree(union acpi_parse_object *subtree_root)
union acpi_parse_object *next = NULL;
union acpi_parse_object *parent = NULL;
- ACPI_FUNCTION_TRACE_PTR("ps_delete_parse_tree", subtree_root);
+ ACPI_FUNCTION_TRACE_PTR(ps_delete_parse_tree, subtree_root);
/* Visit all nodes in the subtree */
while (op) {
+
/* Check if we are not ascending */
if (op != parent) {
+
/* Look for an argument or child of the current op */
next = acpi_ps_get_arg(op, 0);
if (next) {
+
/* Still going downward in tree (Op is not completed yet) */
op = next;
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
index 2dd48cbb7c0..5d996c1140a 100644
--- a/drivers/acpi/parser/psxface.c
+++ b/drivers/acpi/parser/psxface.c
@@ -50,14 +50,14 @@
ACPI_MODULE_NAME("psxface")
/* Local Prototypes */
-static void acpi_ps_start_trace(struct acpi_parameter_info *info);
+static void acpi_ps_start_trace(struct acpi_evaluate_info *info);
-static void acpi_ps_stop_trace(struct acpi_parameter_info *info);
+static void acpi_ps_stop_trace(struct acpi_evaluate_info *info);
-static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info);
+static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info);
static void
-acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action);
+acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action);
/*******************************************************************************
*
@@ -113,7 +113,7 @@ acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags)
*
******************************************************************************/
-static void acpi_ps_start_trace(struct acpi_parameter_info *info)
+static void acpi_ps_start_trace(struct acpi_evaluate_info *info)
{
acpi_status status;
@@ -125,7 +125,7 @@ static void acpi_ps_start_trace(struct acpi_parameter_info *info)
}
if ((!acpi_gbl_trace_method_name) ||
- (acpi_gbl_trace_method_name != info->node->name.integer)) {
+ (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) {
goto exit;
}
@@ -158,7 +158,7 @@ static void acpi_ps_start_trace(struct acpi_parameter_info *info)
*
******************************************************************************/
-static void acpi_ps_stop_trace(struct acpi_parameter_info *info)
+static void acpi_ps_stop_trace(struct acpi_evaluate_info *info)
{
acpi_status status;
@@ -170,7 +170,7 @@ static void acpi_ps_stop_trace(struct acpi_parameter_info *info)
}
if ((!acpi_gbl_trace_method_name) ||
- (acpi_gbl_trace_method_name != info->node->name.integer)) {
+ (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) {
goto exit;
}
@@ -212,22 +212,23 @@ static void acpi_ps_stop_trace(struct acpi_parameter_info *info)
*
******************************************************************************/
-acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info)
+acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ps_execute_method");
+ ACPI_FUNCTION_TRACE(ps_execute_method);
/* Validate the Info and method Node */
- if (!info || !info->node) {
+ if (!info || !info->resolved_node) {
return_ACPI_STATUS(AE_NULL_ENTRY);
}
/* Init for new method, wait on concurrency semaphore */
status =
- acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL);
+ acpi_ds_begin_method_execution(info->resolved_node, info->obj_desc,
+ NULL);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -248,7 +249,7 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info)
*/
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
"**** Begin Method Parse **** Entry=%p obj=%p\n",
- info->node, info->obj_desc));
+ info->resolved_node, info->obj_desc));
info->pass_number = 1;
status = acpi_ps_execute_pass(info);
@@ -261,7 +262,7 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info)
*/
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
"**** Begin Method Execution **** Entry=%p obj=%p\n",
- info->node, info->obj_desc));
+ info->resolved_node, info->obj_desc));
info->pass_number = 3;
status = acpi_ps_execute_pass(info);
@@ -286,8 +287,7 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info)
* a control exception code
*/
if (info->return_object) {
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
- "Method returned obj_desc=%p\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
info->return_object));
ACPI_DUMP_STACK_ENTRY(info->return_object);
@@ -301,7 +301,7 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info)
*
* FUNCTION: acpi_ps_update_parameter_list
*
- * PARAMETERS: Info - See struct acpi_parameter_info
+ * PARAMETERS: Info - See struct acpi_evaluate_info
* (Used: parameter_type and Parameters)
* Action - Add or Remove reference
*
@@ -312,14 +312,16 @@ acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info)
******************************************************************************/
static void
-acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action)
+acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action)
{
acpi_native_uint i;
if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) {
+
/* Update reference count for each parameter */
for (i = 0; info->parameters[i]; i++) {
+
/* Ignore errors, just do them all */
(void)acpi_ut_update_object_reference(info->
@@ -333,7 +335,7 @@ acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action)
*
* FUNCTION: acpi_ps_execute_pass
*
- * PARAMETERS: Info - See struct acpi_parameter_info
+ * PARAMETERS: Info - See struct acpi_evaluate_info
* (Used: pass_number, Node, and obj_desc)
*
* RETURN: Status
@@ -342,13 +344,13 @@ acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action)
*
******************************************************************************/
-static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info)
+static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info)
{
acpi_status status;
union acpi_parse_object *op;
struct acpi_walk_state *walk_state;
- ACPI_FUNCTION_TRACE("ps_execute_pass");
+ ACPI_FUNCTION_TRACE(ps_execute_pass);
/* Create and init a Root Node */
@@ -367,7 +369,7 @@ static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info)
goto cleanup;
}
- status = acpi_ds_init_aml_walk(walk_state, op, info->node,
+ status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node,
info->obj_desc->method.aml_start,
info->obj_desc->method.aml_length,
info->pass_number == 1 ? NULL : info,
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 713b763884a..e5041c4f3c2 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -388,7 +388,7 @@ static int acpi_processor_remove_fs(struct acpi_device *device)
/* Use the acpiid in MADT to map cpus in case of SMP */
#ifndef CONFIG_SMP
-#define convert_acpiid_to_cpu(acpi_id) (0xff)
+#define convert_acpiid_to_cpu(acpi_id) (-1)
#else
#ifdef CONFIG_IA64
@@ -401,7 +401,7 @@ static int acpi_processor_remove_fs(struct acpi_device *device)
#define ARCH_BAD_APICID (0xff)
#endif
-static u8 convert_acpiid_to_cpu(u8 acpi_id)
+static int convert_acpiid_to_cpu(u8 acpi_id)
{
u16 apic_id;
int i;
@@ -427,7 +427,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr)
acpi_status status = 0;
union acpi_object object = { 0 };
struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
- u8 cpu_index;
+ int cpu_index;
static int cpu0_initialized;
ACPI_FUNCTION_TRACE("acpi_processor_get_info");
@@ -473,7 +473,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr)
cpu_index = convert_acpiid_to_cpu(pr->acpi_id);
/* Handle UP system running SMP kernel, with no LAPIC in MADT */
- if (!cpu0_initialized && (cpu_index == 0xff) &&
+ if (!cpu0_initialized && (cpu_index == -1) &&
(num_online_cpus() == 1)) {
cpu_index = 0;
}
@@ -487,7 +487,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr)
* less than the max # of CPUs. They should be ignored _iff
* they are physically not present.
*/
- if (cpu_index >= NR_CPUS) {
+ if (cpu_index == -1) {
if (ACPI_FAILURE
(acpi_processor_hotadd_init(pr->handle, &pr->id))) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index abbdb37a7f5..f36db22ce1a 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -577,6 +577,8 @@ acpi_processor_register_performance(struct acpi_processor_performance
return_VALUE(-EBUSY);
}
+ WARN_ON(!performance);
+
pr->performance = performance;
if (acpi_processor_get_performance_info(pr)) {
@@ -609,7 +611,8 @@ acpi_processor_unregister_performance(struct acpi_processor_performance
return_VOID;
}
- kfree(pr->performance->states);
+ if (pr->performance)
+ kfree(pr->performance->states);
pr->performance = NULL;
acpi_cpufreq_remove_file(pr);
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 4038dbfa63a..cf87b023002 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -78,6 +78,7 @@ static u8 acpi_rs_count_set_bits(u16 bit_field)
ACPI_FUNCTION_ENTRY();
for (bits_set = 0; bit_field; bits_set++) {
+
/* Zero the least significant bit that is set */
bit_field &= (bit_field - 1);
@@ -154,15 +155,18 @@ acpi_rs_stream_option_length(u32 resource_length,
* length, minus one byte for the resource_source_index itself.
*/
if (resource_length > minimum_aml_resource_length) {
+
/* Compute the length of the optional string */
string_length =
resource_length - minimum_aml_resource_length - 1;
}
- /* Round up length to 32 bits for internal structure alignment */
-
- return (ACPI_ROUND_UP_to_32_bITS(string_length));
+ /*
+ * Round the length up to a multiple of the native word in order to
+ * guarantee that the entire resource descriptor is native word aligned
+ */
+ return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length));
}
/*******************************************************************************
@@ -186,11 +190,12 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
acpi_size aml_size_needed = 0;
acpi_rs_length total_size;
- ACPI_FUNCTION_TRACE("rs_get_aml_length");
+ ACPI_FUNCTION_TRACE(rs_get_aml_length);
/* Traverse entire list of internal resource descriptors */
while (resource) {
+
/* Validate the descriptor type */
if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
@@ -214,6 +219,7 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
* is a Large Resource data type.
*/
if (resource->data.vendor.byte_length > 7) {
+
/* Base size of a Large resource descriptor */
total_size =
@@ -332,20 +338,22 @@ acpi_rs_get_list_length(u8 * aml_buffer,
acpi_status status;
u8 *end_aml;
u8 *buffer;
- u32 buffer_size = 0;
+ u32 buffer_size;
u16 temp16;
u16 resource_length;
u32 extra_struct_bytes;
u8 resource_index;
u8 minimum_aml_resource_length;
- ACPI_FUNCTION_TRACE("rs_get_list_length");
+ ACPI_FUNCTION_TRACE(rs_get_list_length);
+ *size_needed = 0;
end_aml = aml_buffer + aml_buffer_length;
/* Walk the list of AML resource descriptors */
while (aml_buffer < end_aml) {
+
/* Validate the Resource Type and Resource Length */
status = acpi_ut_validate_resource(aml_buffer, &resource_index);
@@ -386,35 +394,28 @@ acpi_rs_get_list_length(u8 * aml_buffer,
break;
case ACPI_RESOURCE_NAME_VENDOR_SMALL:
+ case ACPI_RESOURCE_NAME_VENDOR_LARGE:
/*
* Vendor Resource:
- * Ensure a 32-bit boundary for the structure
+ * Get the number of vendor data bytes
*/
- extra_struct_bytes =
- ACPI_ROUND_UP_to_32_bITS(resource_length);
+ extra_struct_bytes = resource_length;
break;
case ACPI_RESOURCE_NAME_END_TAG:
/*
- * End Tag: This is the normal exit, add size of end_tag
+ * End Tag:
+ * This is the normal exit, add size of end_tag
*/
- *size_needed = buffer_size + ACPI_RS_SIZE_MIN;
+ *size_needed += ACPI_RS_SIZE_MIN;
return_ACPI_STATUS(AE_OK);
- case ACPI_RESOURCE_NAME_VENDOR_LARGE:
- /*
- * Vendor Resource:
- * Add vendor data and ensure a 32-bit boundary for the structure
- */
- extra_struct_bytes =
- ACPI_ROUND_UP_to_32_bITS(resource_length);
- break;
-
case ACPI_RESOURCE_NAME_ADDRESS32:
case ACPI_RESOURCE_NAME_ADDRESS16:
+ case ACPI_RESOURCE_NAME_ADDRESS64:
/*
- * 32-Bit or 16-bit Address Resource:
- * Add the size of any optional data (resource_source)
+ * Address Resource:
+ * Add the size of the optional resource_source
*/
extra_struct_bytes =
acpi_rs_stream_option_length(resource_length,
@@ -423,50 +424,46 @@ acpi_rs_get_list_length(u8 * aml_buffer,
case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
/*
- * Extended IRQ:
- * Point past the interrupt_vector_flags to get the
- * interrupt_table_length.
+ * Extended IRQ Resource:
+ * Using the interrupt_table_length, add 4 bytes for each additional
+ * interrupt. Note: at least one interrupt is required and is
+ * included in the minimum descriptor size (reason for the -1)
*/
- buffer++;
+ extra_struct_bytes = (buffer[1] - 1) * sizeof(u32);
- extra_struct_bytes =
- /*
- * Add 4 bytes for each additional interrupt. Note: at
- * least one interrupt is required and is included in
- * the minimum descriptor size
- */
- ((*buffer - 1) * sizeof(u32)) +
- /* Add the size of any optional data (resource_source) */
+ /* Add the size of the optional resource_source */
+
+ extra_struct_bytes +=
acpi_rs_stream_option_length(resource_length -
extra_struct_bytes,
minimum_aml_resource_length);
break;
- case ACPI_RESOURCE_NAME_ADDRESS64:
- /*
- * 64-Bit Address Resource:
- * Add the size of any optional data (resource_source)
- * Ensure a 64-bit boundary for the structure
- */
- extra_struct_bytes =
- ACPI_ROUND_UP_to_64_bITS
- (acpi_rs_stream_option_length
- (resource_length, minimum_aml_resource_length));
- break;
-
default:
break;
}
- /* Update the required buffer size for the internal descriptor structs */
+ /*
+ * Update the required buffer size for the internal descriptor structs
+ *
+ * Important: Round the size up for the appropriate alignment. This
+ * is a requirement on IA64.
+ */
+ buffer_size = acpi_gbl_resource_struct_sizes[resource_index] +
+ extra_struct_bytes;
+ buffer_size = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
- temp16 = (u16) (acpi_gbl_resource_struct_sizes[resource_index] +
- extra_struct_bytes);
- buffer_size += (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(temp16);
+ *size_needed += buffer_size;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
+ "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
+ acpi_ut_get_resource_type(aml_buffer),
+ acpi_ut_get_descriptor_length(aml_buffer),
+ buffer_size));
/*
- * Point to the next resource within the stream
- * using the size of the header plus the length contained in the header
+ * Point to the next resource within the AML stream using the length
+ * contained in the resource descriptor header
*/
aml_buffer += acpi_ut_get_descriptor_length(aml_buffer);
}
@@ -506,7 +503,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
u8 name_found;
u32 table_index;
- ACPI_FUNCTION_TRACE("rs_get_pci_routing_table_length");
+ ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length);
number_of_elements = package_object->package.count;
@@ -523,6 +520,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
top_object_list = package_object->package.elements;
for (index = 0; index < number_of_elements; index++) {
+
/* Dereference the sub-package */
package_element = *top_object_list;
@@ -581,7 +579,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
/* Round up the size since each element must be aligned */
- temp_size_needed = ACPI_ROUND_UP_to_64_bITS(temp_size_needed);
+ temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed);
/* Point to the next union acpi_operand_object */
@@ -589,7 +587,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
}
/*
- * Adding an extra element to the end of the list, essentially a
+ * Add an extra element to the end of the list, essentially a
* NULL terminator
*/
*buffer_size_needed =
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index 8c128dea325..008058acdd3 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/resources/rscreate.c
@@ -75,10 +75,11 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
u8 *aml_start;
acpi_size list_size_needed = 0;
u32 aml_buffer_length;
+ void *resource;
- ACPI_FUNCTION_TRACE("rs_create_resource_list");
+ ACPI_FUNCTION_TRACE(rs_create_resource_list);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_buffer = %p\n", aml_buffer));
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlBuffer = %p\n", aml_buffer));
/* Params already validated, so we don't re-validate here */
@@ -92,7 +93,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
status = acpi_rs_get_list_length(aml_start, aml_buffer_length,
&list_size_needed);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X ListSizeNeeded=%X\n",
status, (u32) list_size_needed));
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
@@ -107,13 +108,15 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
/* Do the conversion */
- status = acpi_rs_convert_aml_to_resources(aml_start, aml_buffer_length,
- output_buffer->pointer);
+ resource = output_buffer->pointer;
+ status = acpi_ut_walk_aml_resources(aml_start, aml_buffer_length,
+ acpi_rs_convert_aml_to_resources,
+ &resource);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
output_buffer->pointer, (u32) output_buffer->length));
return_ACPI_STATUS(AE_OK);
}
@@ -155,7 +158,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
acpi_status status;
struct acpi_buffer path_buffer;
- ACPI_FUNCTION_TRACE("rs_create_pci_routing_table");
+ ACPI_FUNCTION_TRACE(rs_create_pci_routing_table);
/* Params already validated, so we don't re-validate here */
@@ -167,7 +170,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "buffer_size_needed = %X\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "BufferSizeNeeded = %X\n",
(u32) buffer_size_needed));
/* Validate/Allocate/Clear caller buffer */
@@ -332,7 +335,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
/* Now align the current length */
user_prt->length =
- (u32) ACPI_ROUND_UP_to_64_bITS(user_prt->length);
+ (u32) ACPI_ROUND_UP_TO_64BIT(user_prt->length);
/* 4) Fourth subobject: Dereference the PRT.source_index */
@@ -341,7 +344,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
user_prt->source_index = (u32) obj_desc->integer.value;
} else {
ACPI_ERROR((AE_INFO,
- "(PRT[%X].source_index) Need Integer, found %s",
+ "(PRT[%X].SourceIndex) Need Integer, found %s",
index,
acpi_ut_get_object_type_name(obj_desc)));
return_ACPI_STATUS(AE_BAD_DATA);
@@ -352,7 +355,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
top_object_list++;
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
output_buffer->pointer, (u32) output_buffer->length));
return_ACPI_STATUS(AE_OK);
}
@@ -382,9 +385,9 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
acpi_status status;
acpi_size aml_size_needed = 0;
- ACPI_FUNCTION_TRACE("rs_create_aml_resources");
+ ACPI_FUNCTION_TRACE(rs_create_aml_resources);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "linked_list_buffer = %p\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "LinkedListBuffer = %p\n",
linked_list_buffer));
/*
@@ -395,7 +398,7 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
*/
status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_size_needed=%X, %s\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n",
(u32) aml_size_needed,
acpi_format_exception(status)));
if (ACPI_FAILURE(status)) {
@@ -419,7 +422,7 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
output_buffer->pointer, (u32) output_buffer->length));
return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c
index e7de061cf88..9c99a723a86 100644
--- a/drivers/acpi/resources/rsdump.c
+++ b/drivers/acpi/resources/rsdump.c
@@ -91,11 +91,11 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table);
struct acpi_rsdump_info acpi_rs_dump_irq[6] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering",
- acpi_gbl_HEdecode},
+ acpi_gbl_he_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity",
- acpi_gbl_LLdecode},
+ acpi_gbl_ll_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing",
- acpi_gbl_SHRdecode},
+ acpi_gbl_shr_decode},
{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count),
"Interrupt Count", NULL},
{ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]),
@@ -105,11 +105,11 @@ struct acpi_rsdump_info acpi_rs_dump_irq[6] = {
struct acpi_rsdump_info acpi_rs_dump_dma[6] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL},
{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed",
- acpi_gbl_TYPdecode},
+ acpi_gbl_typ_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering",
- acpi_gbl_BMdecode},
+ acpi_gbl_bm_decode},
{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type",
- acpi_gbl_SIZdecode},
+ acpi_gbl_siz_decode},
{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count",
NULL},
{ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List",
@@ -158,7 +158,7 @@ struct acpi_rsdump_info acpi_rs_dump_vendor[3] = {
};
struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = {
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "end_tag",
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "EndTag",
NULL}
};
@@ -166,7 +166,7 @@ struct acpi_rsdump_info acpi_rs_dump_memory24[6] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24),
"24-Bit Memory Range", NULL},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect),
- "Write Protect", acpi_gbl_RWdecode},
+ "Write Protect", acpi_gbl_rw_decode},
{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum",
NULL},
{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum",
@@ -181,7 +181,7 @@ struct acpi_rsdump_info acpi_rs_dump_memory32[6] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32),
"32-Bit Memory Range", NULL},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect),
- "Write Protect", acpi_gbl_RWdecode},
+ "Write Protect", acpi_gbl_rw_decode},
{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum",
NULL},
{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum",
@@ -196,7 +196,7 @@ struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32),
"32-Bit Fixed Memory Range", NULL},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect),
- "Write Protect", acpi_gbl_RWdecode},
+ "Write Protect", acpi_gbl_rw_decode},
{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address",
NULL},
{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length),
@@ -278,11 +278,11 @@ struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = {
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer),
"Type", acpi_gbl_consume_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering),
- "Triggering", acpi_gbl_HEdecode},
+ "Triggering", acpi_gbl_he_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity",
- acpi_gbl_LLdecode},
+ acpi_gbl_ll_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing",
- acpi_gbl_SHRdecode},
+ acpi_gbl_shr_decode},
{ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL,
NULL},
{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count),
@@ -314,7 +314,7 @@ static struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = {
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer),
"Consumer/Producer", acpi_gbl_consume_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode",
- acpi_gbl_DECdecode},
+ acpi_gbl_dec_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed),
"Min Relocatability", acpi_gbl_min_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed),
@@ -325,24 +325,24 @@ static struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = {
{ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags),
"Resource Type", (void *)"Memory Range"},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect),
- "Write Protect", acpi_gbl_RWdecode},
+ "Write Protect", acpi_gbl_rw_decode},
{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching),
- "Caching", acpi_gbl_MEMdecode},
+ "Caching", acpi_gbl_mem_decode},
{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type),
- "Range Type", acpi_gbl_MTPdecode},
+ "Range Type", acpi_gbl_mtp_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation),
- "Translation", acpi_gbl_TTPdecode}
+ "Translation", acpi_gbl_ttp_decode}
};
static struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = {
{ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags),
"Resource Type", (void *)"I/O Range"},
{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type),
- "Range Type", acpi_gbl_RNGdecode},
+ "Range Type", acpi_gbl_rng_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation),
- "Translation", acpi_gbl_TTPdecode},
+ "Translation", acpi_gbl_ttp_decode},
{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type),
- "Translation Type", acpi_gbl_TRSdecode}
+ "Translation Type", acpi_gbl_trs_decode}
};
/*
diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/resources/rsinfo.c
index d9ae64b77bd..9e7ae2f8a1d 100644
--- a/drivers/acpi/resources/rsinfo.c
+++ b/drivers/acpi/resources/rsinfo.c
@@ -141,6 +141,7 @@ struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[] = {
acpi_rs_dump_generic_reg, /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
};
#endif
+
#endif /* ACPI_FUTURE_USAGE */
/*
* Base sizes for external AML resource descriptors, indexed by internal type.
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c
index 1434e786477..29423ce030c 100644
--- a/drivers/acpi/resources/rslist.c
+++ b/drivers/acpi/resources/rslist.c
@@ -51,76 +51,62 @@ ACPI_MODULE_NAME("rslist")
*
* FUNCTION: acpi_rs_convert_aml_to_resources
*
- * PARAMETERS: Aml - Pointer to the resource byte stream
- * aml_length - Length of Aml
- * output_buffer - Pointer to the buffer that will
- * contain the output structures
+ * PARAMETERS: acpi_walk_aml_callback
+ * resource_ptr - Pointer to the buffer that will
+ * contain the output structures
*
* RETURN: Status
*
- * DESCRIPTION: Takes the resource byte stream and parses it, creating a
- * linked list of resources in the caller's output buffer
+ * DESCRIPTION: Convert an AML resource to an internal representation of the
+ * resource that is aligned and easier to access.
*
******************************************************************************/
acpi_status
-acpi_rs_convert_aml_to_resources(u8 * aml, u32 aml_length, u8 * output_buffer)
+acpi_rs_convert_aml_to_resources(u8 * aml,
+ u32 length,
+ u32 offset, u8 resource_index, void **context)
{
- struct acpi_resource *resource = (void *)output_buffer;
+ struct acpi_resource **resource_ptr =
+ ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context);
+ struct acpi_resource *resource;
acpi_status status;
- u8 resource_index;
- u8 *end_aml;
-
- ACPI_FUNCTION_TRACE("rs_convert_aml_to_resources");
-
- end_aml = aml + aml_length;
-
- /* Loop until end-of-buffer or an end_tag is found */
-
- while (aml < end_aml) {
- /* Validate the Resource Type and Resource Length */
-
- status = acpi_ut_validate_resource(aml, &resource_index);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- /* Convert the AML byte stream resource to a local resource struct */
-
- status =
- acpi_rs_convert_aml_to_resource(resource,
- ACPI_CAST_PTR(union
- aml_resource,
- aml),
- acpi_gbl_get_resource_dispatch
- [resource_index]);
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "Could not convert AML resource (Type %X)",
- *aml));
- return_ACPI_STATUS(status);
- }
+ ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources);
- /* Normal exit on completion of an end_tag resource descriptor */
-
- if (acpi_ut_get_resource_type(aml) ==
- ACPI_RESOURCE_NAME_END_TAG) {
- return_ACPI_STATUS(AE_OK);
- }
-
- /* Point to the next input AML resource */
-
- aml += acpi_ut_get_descriptor_length(aml);
-
- /* Point to the next structure in the output buffer */
+ /*
+ * Check that the input buffer and all subsequent pointers into it
+ * are aligned on a native word boundary. Most important on IA64
+ */
+ resource = *resource_ptr;
+ if (ACPI_IS_MISALIGNED(resource)) {
+ ACPI_WARNING((AE_INFO,
+ "Misaligned resource pointer %p", resource));
+ }
- resource =
- ACPI_ADD_PTR(struct acpi_resource, resource,
- resource->length);
+ /* Convert the AML byte stream resource to a local resource struct */
+
+ status =
+ acpi_rs_convert_aml_to_resource(resource,
+ ACPI_CAST_PTR(union aml_resource,
+ aml),
+ acpi_gbl_get_resource_dispatch
+ [resource_index]);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Could not convert AML resource (Type %X)",
+ *aml));
+ return_ACPI_STATUS(status);
}
- /* Did not find an end_tag resource descriptor */
+ ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
+ "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
+ acpi_ut_get_resource_type(aml), length,
+ resource->length));
- return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+ /* Point to the next structure in the output buffer */
+
+ *resource_ptr = ACPI_ADD_PTR(void, resource, resource->length);
+ return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
@@ -150,11 +136,12 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
u8 *end_aml = output_buffer + aml_size_needed;
acpi_status status;
- ACPI_FUNCTION_TRACE("rs_convert_resources_to_aml");
+ ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml);
/* Walk the resource descriptor list, convert each descriptor */
while (aml < end_aml) {
+
/* Validate the (internal) Resource Type */
if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
@@ -191,6 +178,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
/* Check for end-of-list, normal exit */
if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
+
/* An End Tag indicates the end of the input Resource Template */
return_ACPI_STATUS(AE_OK);
diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c
index ed866cf1c6d..faf6e106b78 100644
--- a/drivers/acpi/resources/rsmisc.c
+++ b/drivers/acpi/resources/rsmisc.c
@@ -81,9 +81,10 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
u16 item_count = 0;
u16 temp16 = 0;
- ACPI_FUNCTION_TRACE("rs_get_resource");
+ ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource);
if (((acpi_native_uint) resource) & 0x3) {
+
/* Each internal resource struct is expected to be 32-bit aligned */
ACPI_WARNING((AE_INFO,
@@ -295,9 +296,11 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
exit:
if (!flags_mode) {
- /* Round the resource struct length up to the next 32-bit boundary */
- resource->length = ACPI_ROUND_UP_to_32_bITS(resource->length);
+ /* Round the resource struct length up to the next boundary (32 or 64) */
+
+ resource->length =
+ (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length);
}
return_ACPI_STATUS(AE_OK);
}
@@ -329,7 +332,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
u16 temp16 = 0;
u16 item_count = 0;
- ACPI_FUNCTION_TRACE("rs_convert_resource_to_aml");
+ ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml);
/*
* First table entry must be ACPI_RSC_INITxxx and must contain the
@@ -535,6 +538,7 @@ if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) {
resource->data.extended_irq.interrupt_count = temp8;
if (temp8 < 1) {
+
/* Must have at least one IRQ */
return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
index 25b5aedd661..a9cbee8e8b4 100644
--- a/drivers/acpi/resources/rsutils.c
+++ b/drivers/acpi/resources/rsutils.c
@@ -205,6 +205,7 @@ acpi_rs_set_resource_length(acpi_rsdesc_size total_length,
/* Length is stored differently for large and small descriptors */
if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) {
+
/* Large descriptor -- bytes 1-2 contain the 16-bit length */
ACPI_MOVE_16_TO_16(&aml->large_header.resource_length,
@@ -298,7 +299,8 @@ static u16 acpi_rs_strcpy(char *destination, char *source)
* string_ptr - (optional) where to store the actual
* resource_source string
*
- * RETURN: Length of the string plus NULL terminator, rounded up to 32 bit
+ * RETURN: Length of the string plus NULL terminator, rounded up to native
+ * word boundary
*
* DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor
* to an internal resource descriptor
@@ -328,6 +330,7 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length,
* we add 1 to the minimum length.
*/
if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) {
+
/* Get the resource_source_index */
resource_source->index = aml_resource_source[0];
@@ -344,23 +347,26 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length,
}
/*
- * In order for the struct_size to fall on a 32-bit boundary, calculate
- * the length of the string (+1 for the NULL terminator) and expand the
- * struct_size to the next 32-bit boundary.
+ * In order for the Resource length to be a multiple of the native
+ * word, calculate the length of the string (+1 for NULL terminator)
+ * and expand to the next word multiple.
*
* Zero the entire area of the buffer.
*/
total_length =
- ACPI_ROUND_UP_to_32_bITS(ACPI_STRLEN
- ((char *)&aml_resource_source[1]) +
- 1);
+ (u32)
+ ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) +
+ 1;
+ total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length);
+
ACPI_MEMSET(resource_source->string_ptr, 0, total_length);
/* Copy the resource_source string to the destination */
resource_source->string_length =
acpi_rs_strcpy(resource_source->string_ptr,
- (char *)&aml_resource_source[1]);
+ ACPI_CAST_PTR(char,
+ &aml_resource_source[1]));
return ((acpi_rs_length) total_length);
}
@@ -405,6 +411,7 @@ acpi_rs_set_resource_source(union aml_resource * aml,
/* Non-zero string length indicates presence of a resource_source */
if (resource_source->string_length) {
+
/* Point to the end of the AML descriptor */
aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
@@ -415,7 +422,7 @@ acpi_rs_set_resource_source(union aml_resource * aml,
/* Copy the resource_source string */
- ACPI_STRCPY((char *)&aml_resource_source[1],
+ ACPI_STRCPY(ACPI_CAST_PTR(char, &aml_resource_source[1]),
resource_source->string_ptr);
/*
@@ -435,9 +442,9 @@ acpi_rs_set_resource_source(union aml_resource * aml,
*
* FUNCTION: acpi_rs_get_prt_method_data
*
- * PARAMETERS: Handle - a handle to the containing object
- * ret_buffer - a pointer to a buffer structure for the
- * results
+ * PARAMETERS: Node - Device node
+ * ret_buffer - Pointer to a buffer structure for the
+ * results
*
* RETURN: Status
*
@@ -450,18 +457,19 @@ acpi_rs_set_resource_source(union aml_resource * aml,
******************************************************************************/
acpi_status
-acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer)
+acpi_rs_get_prt_method_data(struct acpi_namespace_node * node,
+ struct acpi_buffer * ret_buffer)
{
union acpi_operand_object *obj_desc;
acpi_status status;
- ACPI_FUNCTION_TRACE("rs_get_prt_method_data");
+ ACPI_FUNCTION_TRACE(rs_get_prt_method_data);
/* Parameters guaranteed valid by caller */
/* Execute the method, no parameters */
- status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRT,
+ status = acpi_ut_evaluate_object(node, METHOD_NAME__PRT,
ACPI_BTYPE_PACKAGE, &obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
@@ -483,9 +491,9 @@ acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer)
*
* FUNCTION: acpi_rs_get_crs_method_data
*
- * PARAMETERS: Handle - a handle to the containing object
- * ret_buffer - a pointer to a buffer structure for the
- * results
+ * PARAMETERS: Node - Device node
+ * ret_buffer - Pointer to a buffer structure for the
+ * results
*
* RETURN: Status
*
@@ -498,18 +506,19 @@ acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer)
******************************************************************************/
acpi_status
-acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
+acpi_rs_get_crs_method_data(struct acpi_namespace_node *node,
+ struct acpi_buffer *ret_buffer)
{
union acpi_operand_object *obj_desc;
acpi_status status;
- ACPI_FUNCTION_TRACE("rs_get_crs_method_data");
+ ACPI_FUNCTION_TRACE(rs_get_crs_method_data);
/* Parameters guaranteed valid by caller */
/* Execute the method, no parameters */
- status = acpi_ut_evaluate_object(handle, METHOD_NAME__CRS,
+ status = acpi_ut_evaluate_object(node, METHOD_NAME__CRS,
ACPI_BTYPE_BUFFER, &obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
@@ -522,7 +531,7 @@ acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
*/
status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
- /* on exit, we must delete the object returned by evaluate_object */
+ /* On exit, we must delete the object returned by evaluate_object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
@@ -532,9 +541,9 @@ acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
*
* FUNCTION: acpi_rs_get_prs_method_data
*
- * PARAMETERS: Handle - a handle to the containing object
- * ret_buffer - a pointer to a buffer structure for the
- * results
+ * PARAMETERS: Node - Device node
+ * ret_buffer - Pointer to a buffer structure for the
+ * results
*
* RETURN: Status
*
@@ -548,18 +557,19 @@ acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
+acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,
+ struct acpi_buffer *ret_buffer)
{
union acpi_operand_object *obj_desc;
acpi_status status;
- ACPI_FUNCTION_TRACE("rs_get_prs_method_data");
+ ACPI_FUNCTION_TRACE(rs_get_prs_method_data);
/* Parameters guaranteed valid by caller */
/* Execute the method, no parameters */
- status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRS,
+ status = acpi_ut_evaluate_object(node, METHOD_NAME__PRS,
ACPI_BTYPE_BUFFER, &obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
@@ -572,7 +582,7 @@ acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
*/
status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
- /* on exit, we must delete the object returned by evaluate_object */
+ /* On exit, we must delete the object returned by evaluate_object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
@@ -583,10 +593,10 @@ acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
*
* FUNCTION: acpi_rs_get_method_data
*
- * PARAMETERS: Handle - a handle to the containing object
+ * PARAMETERS: Handle - Handle to the containing object
* Path - Path to method, relative to Handle
- * ret_buffer - a pointer to a buffer structure for the
- * results
+ * ret_buffer - Pointer to a buffer structure for the
+ * results
*
* RETURN: Status
*
@@ -605,7 +615,7 @@ acpi_rs_get_method_data(acpi_handle handle,
union acpi_operand_object *obj_desc;
acpi_status status;
- ACPI_FUNCTION_TRACE("rs_get_method_data");
+ ACPI_FUNCTION_TRACE(rs_get_method_data);
/* Parameters guaranteed valid by caller */
@@ -634,9 +644,9 @@ acpi_rs_get_method_data(acpi_handle handle,
*
* FUNCTION: acpi_rs_set_srs_method_data
*
- * PARAMETERS: Handle - a handle to the containing object
- * in_buffer - a pointer to a buffer structure of the
- * parameter
+ * PARAMETERS: Node - Device node
+ * in_buffer - Pointer to a buffer structure of the
+ * parameter
*
* RETURN: Status
*
@@ -646,23 +656,37 @@ acpi_rs_get_method_data(acpi_handle handle,
* If the function fails an appropriate status will be returned
* and the contents of the callers buffer is undefined.
*
+ * Note: Parameters guaranteed valid by caller
+ *
******************************************************************************/
acpi_status
-acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer)
+acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
+ struct acpi_buffer *in_buffer)
{
- struct acpi_parameter_info info;
- union acpi_operand_object *params[2];
+ struct acpi_evaluate_info *info;
+ union acpi_operand_object *args[2];
acpi_status status;
struct acpi_buffer buffer;
- ACPI_FUNCTION_TRACE("rs_set_srs_method_data");
+ ACPI_FUNCTION_TRACE(rs_set_srs_method_data);
- /* Parameters guaranteed valid by caller */
+ /* Allocate and initialize the evaluation information block */
+
+ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+ if (!info) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ info->prefix_node = node;
+ info->pathname = METHOD_NAME__SRS;
+ info->parameters = args;
+ info->parameter_type = ACPI_PARAM_ARGS;
+ info->flags = ACPI_IGNORE_RETURN_VALUE;
/*
* The in_buffer parameter will point to a linked list of
- * resource parameters. It needs to be formatted into a
+ * resource parameters. It needs to be formatted into a
* byte stream to be sent in as an input parameter to _SRS
*
* Convert the linked list into a byte stream
@@ -670,41 +694,36 @@ acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer)
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer);
if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ goto cleanup;
}
- /* Init the param object */
+ /* Create and initialize the method parameter object */
- params[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
- if (!params[0]) {
- acpi_os_free(buffer.pointer);
- return_ACPI_STATUS(AE_NO_MEMORY);
+ args[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
+ if (!args[0]) {
+ /*
+ * Must free the buffer allocated above (otherwise it is freed
+ * later)
+ */
+ ACPI_FREE(buffer.pointer);
+ status = AE_NO_MEMORY;
+ goto cleanup;
}
- /* Set up the parameter object */
-
- params[0]->buffer.length = (u32) buffer.length;
- params[0]->buffer.pointer = buffer.pointer;
- params[0]->common.flags = AOPOBJ_DATA_VALID;
- params[1] = NULL;
-
- info.node = handle;
- info.parameters = params;
- info.parameter_type = ACPI_PARAM_ARGS;
+ args[0]->buffer.length = (u32) buffer.length;
+ args[0]->buffer.pointer = buffer.pointer;
+ args[0]->common.flags = AOPOBJ_DATA_VALID;
+ args[1] = NULL;
- /* Execute the method, no return value */
+ /* Execute the method, no return value is expected */
- status = acpi_ns_evaluate_relative(METHOD_NAME__SRS, &info);
- if (ACPI_SUCCESS(status)) {
- /* Delete any return object (especially if implicit_return is enabled) */
+ status = acpi_ns_evaluate(info);
- if (info.return_object) {
- acpi_ut_remove_reference(info.return_object);
- }
- }
+ /* Clean up and return the status from acpi_ns_evaluate */
- /* Clean up and return the status from acpi_ns_evaluate_relative */
+ acpi_ut_remove_reference(args[0]);
- acpi_ut_remove_reference(params[0]);
+ cleanup:
+ ACPI_FREE(info);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
index 88b67077aee..1999e2ab7da 100644
--- a/drivers/acpi/resources/rsxface.c
+++ b/drivers/acpi/resources/rsxface.c
@@ -41,10 +41,9 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include <acpi/acresrc.h>
+#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rsxface")
@@ -68,312 +67,262 @@ ACPI_MODULE_NAME("rsxface")
static acpi_status
acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context);
+static acpi_status
+acpi_rs_validate_parameters(acpi_handle device_handle,
+ struct acpi_buffer *buffer,
+ struct acpi_namespace_node **return_node);
+
/*******************************************************************************
*
- * FUNCTION: acpi_get_irq_routing_table
+ * FUNCTION: acpi_rs_validate_parameters
*
- * PARAMETERS: device_handle - a handle to the Bus device we are querying
- * ret_buffer - a pointer to a buffer to receive the
- * current resources for the device
+ * PARAMETERS: device_handle - Handle to a device
+ * Buffer - Pointer to a data buffer
+ * return_node - Pointer to where the device node is returned
*
* RETURN: Status
*
- * DESCRIPTION: This function is called to get the IRQ routing table for a
- * specific bus. The caller must first acquire a handle for the
- * desired bus. The routine table is placed in the buffer pointed
- * to by the ret_buffer variable parameter.
- *
- * If the function fails an appropriate status will be returned
- * and the value of ret_buffer is undefined.
- *
- * This function attempts to execute the _PRT method contained in
- * the object indicated by the passed device_handle.
+ * DESCRIPTION: Common parameter validation for resource interfaces
*
******************************************************************************/
-acpi_status
-acpi_get_irq_routing_table(acpi_handle device_handle,
- struct acpi_buffer *ret_buffer)
+static acpi_status
+acpi_rs_validate_parameters(acpi_handle device_handle,
+ struct acpi_buffer *buffer,
+ struct acpi_namespace_node **return_node)
{
acpi_status status;
+ struct acpi_namespace_node *node;
- ACPI_FUNCTION_TRACE("acpi_get_irq_routing_table ");
+ ACPI_FUNCTION_TRACE(rs_validate_parameters);
/*
- * Must have a valid handle and buffer, So we have to have a handle
- * and a return buffer structure, and if there is a non-zero buffer length
- * we also need a valid pointer in the buffer. If it's a zero buffer length,
- * we'll be returning the needed buffer size, so keep going.
+ * Must have a valid handle to an ACPI device
*/
if (!device_handle) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_ut_validate_buffer(ret_buffer);
+ node = acpi_ns_map_handle_to_node(device_handle);
+ if (!node) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ if (node->type != ACPI_TYPE_DEVICE) {
+ return_ACPI_STATUS(AE_TYPE);
+ }
+
+ /*
+ * Validate the user buffer object
+ *
+ * if there is a non-zero buffer length we also need a valid pointer in
+ * the buffer. If it's a zero buffer length, we'll be returning the
+ * needed buffer size (later), so keep going.
+ */
+ status = acpi_ut_validate_buffer(buffer);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- status = acpi_rs_get_prt_method_data(device_handle, ret_buffer);
- return_ACPI_STATUS(status);
+ *return_node = node;
+ return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
- * FUNCTION: acpi_get_current_resources
+ * FUNCTION: acpi_get_irq_routing_table
*
- * PARAMETERS: device_handle - a handle to the device object for the
- * device we are querying
- * ret_buffer - a pointer to a buffer to receive the
+ * PARAMETERS: device_handle - Handle to the Bus device we are querying
+ * ret_buffer - Pointer to a buffer to receive the
* current resources for the device
*
* RETURN: Status
*
- * DESCRIPTION: This function is called to get the current resources for a
- * specific device. The caller must first acquire a handle for
- * the desired device. The resource data is placed in the buffer
- * pointed to by the ret_buffer variable parameter.
+ * DESCRIPTION: This function is called to get the IRQ routing table for a
+ * specific bus. The caller must first acquire a handle for the
+ * desired bus. The routine table is placed in the buffer pointed
+ * to by the ret_buffer variable parameter.
*
* If the function fails an appropriate status will be returned
* and the value of ret_buffer is undefined.
*
- * This function attempts to execute the _CRS method contained in
+ * This function attempts to execute the _PRT method contained in
* the object indicated by the passed device_handle.
*
******************************************************************************/
acpi_status
-acpi_get_current_resources(acpi_handle device_handle,
+acpi_get_irq_routing_table(acpi_handle device_handle,
struct acpi_buffer *ret_buffer)
{
acpi_status status;
+ struct acpi_namespace_node *node;
- ACPI_FUNCTION_TRACE("acpi_get_current_resources");
+ ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table);
- /*
- * Must have a valid handle and buffer, So we have to have a handle
- * and a return buffer structure, and if there is a non-zero buffer length
- * we also need a valid pointer in the buffer. If it's a zero buffer length,
- * we'll be returning the needed buffer size, so keep going.
- */
- if (!device_handle) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
+ /* Validate parameters then dispatch to internal routine */
- status = acpi_ut_validate_buffer(ret_buffer);
+ status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- status = acpi_rs_get_crs_method_data(device_handle, ret_buffer);
+ status = acpi_rs_get_prt_method_data(node, ret_buffer);
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_current_resources);
+ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table)
/*******************************************************************************
*
- * FUNCTION: acpi_get_possible_resources
+ * FUNCTION: acpi_get_current_resources
*
- * PARAMETERS: device_handle - a handle to the device object for the
+ * PARAMETERS: device_handle - Handle to the device object for the
* device we are querying
- * ret_buffer - a pointer to a buffer to receive the
- * resources for the device
+ * ret_buffer - Pointer to a buffer to receive the
+ * current resources for the device
*
* RETURN: Status
*
- * DESCRIPTION: This function is called to get a list of the possible resources
- * for a specific device. The caller must first acquire a handle
- * for the desired device. The resource data is placed in the
- * buffer pointed to by the ret_buffer variable.
+ * DESCRIPTION: This function is called to get the current resources for a
+ * specific device. The caller must first acquire a handle for
+ * the desired device. The resource data is placed in the buffer
+ * pointed to by the ret_buffer variable parameter.
*
* If the function fails an appropriate status will be returned
* and the value of ret_buffer is undefined.
*
+ * This function attempts to execute the _CRS method contained in
+ * the object indicated by the passed device_handle.
+ *
******************************************************************************/
-
-#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_get_possible_resources(acpi_handle device_handle,
- struct acpi_buffer *ret_buffer)
+acpi_get_current_resources(acpi_handle device_handle,
+ struct acpi_buffer *ret_buffer)
{
acpi_status status;
+ struct acpi_namespace_node *node;
- ACPI_FUNCTION_TRACE("acpi_get_possible_resources");
+ ACPI_FUNCTION_TRACE(acpi_get_current_resources);
- /*
- * Must have a valid handle and buffer, So we have to have a handle
- * and a return buffer structure, and if there is a non-zero buffer length
- * we also need a valid pointer in the buffer. If it's a zero buffer length,
- * we'll be returning the needed buffer size, so keep going.
- */
- if (!device_handle) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
+ /* Validate parameters then dispatch to internal routine */
- status = acpi_ut_validate_buffer(ret_buffer);
+ status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- status = acpi_rs_get_prs_method_data(device_handle, ret_buffer);
+ status = acpi_rs_get_crs_method_data(node, ret_buffer);
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_possible_resources);
-#endif /* ACPI_FUTURE_USAGE */
+ACPI_EXPORT_SYMBOL(acpi_get_current_resources)
+#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
- * FUNCTION: acpi_walk_resources
+ * FUNCTION: acpi_get_possible_resources
*
* PARAMETERS: device_handle - Handle to the device object for the
* device we are querying
- * Name - Method name of the resources we want
- * (METHOD_NAME__CRS or METHOD_NAME__PRS)
- * user_function - Called for each resource
- * Context - Passed to user_function
+ * ret_buffer - Pointer to a buffer to receive the
+ * resources for the device
*
* RETURN: Status
*
- * DESCRIPTION: Retrieves the current or possible resource list for the
- * specified device. The user_function is called once for
- * each resource in the list.
+ * DESCRIPTION: This function is called to get a list of the possible resources
+ * for a specific device. The caller must first acquire a handle
+ * for the desired device. The resource data is placed in the
+ * buffer pointed to by the ret_buffer variable.
+ *
+ * If the function fails an appropriate status will be returned
+ * and the value of ret_buffer is undefined.
*
******************************************************************************/
-
acpi_status
-acpi_walk_resources(acpi_handle device_handle,
- char *name,
- ACPI_WALK_RESOURCE_CALLBACK user_function, void *context)
+acpi_get_possible_resources(acpi_handle device_handle,
+ struct acpi_buffer *ret_buffer)
{
acpi_status status;
- struct acpi_buffer buffer;
- struct acpi_resource *resource;
- struct acpi_resource *resource_end;
-
- ACPI_FUNCTION_TRACE("acpi_walk_resources");
-
- /* Parameter validation */
+ struct acpi_namespace_node *node;
- if (!device_handle || !user_function || !name ||
- (ACPI_STRNCMP(name, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) &&
- ACPI_STRNCMP(name, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
+ ACPI_FUNCTION_TRACE(acpi_get_possible_resources);
- /* Get the _CRS or _PRS resource list */
+ /* Validate parameters then dispatch to internal routine */
- buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
- status = acpi_rs_get_method_data(device_handle, name, &buffer);
+ status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- /* Buffer now contains the resource list */
-
- resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer);
- resource_end =
- ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length);
-
- /* Walk the resource list until the end_tag is found (or buffer end) */
-
- while (resource < resource_end) {
- /* Sanity check the resource */
-
- if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
- status = AE_AML_INVALID_RESOURCE_TYPE;
- break;
- }
-
- /* Invoke the user function, abort on any error returned */
-
- status = user_function(resource, context);
- if (ACPI_FAILURE(status)) {
- if (status == AE_CTRL_TERMINATE) {
- /* This is an OK termination by the user function */
-
- status = AE_OK;
- }
- break;
- }
-
- /* end_tag indicates end-of-list */
-
- if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
- break;
- }
-
- /* Get the next resource descriptor */
-
- resource =
- ACPI_ADD_PTR(struct acpi_resource, resource,
- resource->length);
- }
-
- ACPI_MEM_FREE(buffer.pointer);
+ status = acpi_rs_get_prs_method_data(node, ret_buffer);
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_walk_resources);
+ACPI_EXPORT_SYMBOL(acpi_get_possible_resources)
+#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
* FUNCTION: acpi_set_current_resources
*
- * PARAMETERS: device_handle - a handle to the device object for the
- * device we are changing the resources of
- * in_buffer - a pointer to a buffer containing the
+ * PARAMETERS: device_handle - Handle to the device object for the
+ * device we are setting resources
+ * in_buffer - Pointer to a buffer containing the
* resources to be set for the device
*
* RETURN: Status
*
* DESCRIPTION: This function is called to set the current resources for a
- * specific device. The caller must first acquire a handle for
- * the desired device. The resource data is passed to the routine
+ * specific device. The caller must first acquire a handle for
+ * the desired device. The resource data is passed to the routine
* the buffer pointed to by the in_buffer variable.
*
******************************************************************************/
-
acpi_status
acpi_set_current_resources(acpi_handle device_handle,
struct acpi_buffer *in_buffer)
{
acpi_status status;
+ struct acpi_namespace_node *node;
- ACPI_FUNCTION_TRACE("acpi_set_current_resources");
+ ACPI_FUNCTION_TRACE(acpi_set_current_resources);
- /* Must have a valid handle and buffer */
+ /* Validate the buffer, don't allow zero length */
- if ((!device_handle) ||
- (!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) {
+ if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status = acpi_rs_set_srs_method_data(device_handle, in_buffer);
+ /* Validate parameters then dispatch to internal routine */
+
+ status = acpi_rs_validate_parameters(device_handle, in_buffer, &node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ status = acpi_rs_set_srs_method_data(node, in_buffer);
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_set_current_resources);
+ACPI_EXPORT_SYMBOL(acpi_set_current_resources)
/******************************************************************************
*
* FUNCTION: acpi_resource_to_address64
*
- * PARAMETERS: Resource - Pointer to a resource
- * Out - Pointer to the users's return
- * buffer (a struct
- * struct acpi_resource_address64)
+ * PARAMETERS: Resource - Pointer to a resource
+ * Out - Pointer to the users's return buffer
+ * (a struct acpi_resource_address64)
*
* RETURN: Status
*
* DESCRIPTION: If the resource is an address16, address32, or address64,
- * copy it to the address64 return buffer. This saves the
+ * copy it to the address64 return buffer. This saves the
* caller from having to duplicate code for different-sized
* addresses.
*
******************************************************************************/
-
acpi_status
acpi_resource_to_address64(struct acpi_resource *resource,
struct acpi_resource_address64 *out)
@@ -415,18 +364,18 @@ acpi_resource_to_address64(struct acpi_resource *resource,
return (AE_OK);
}
-EXPORT_SYMBOL(acpi_resource_to_address64);
+ACPI_EXPORT_SYMBOL(acpi_resource_to_address64)
/*******************************************************************************
*
* FUNCTION: acpi_get_vendor_resource
*
- * PARAMETERS: device_handle - Handle for the parent device object
- * Name - Method name for the parent resource
- * (METHOD_NAME__CRS or METHOD_NAME__PRS)
- * Uuid - Pointer to the UUID to be matched.
- * includes both subtype and 16-byte UUID
- * ret_buffer - Where the vendor resource is returned
+ * PARAMETERS: device_handle - Handle for the parent device object
+ * Name - Method name for the parent resource
+ * (METHOD_NAME__CRS or METHOD_NAME__PRS)
+ * Uuid - Pointer to the UUID to be matched.
+ * includes both subtype and 16-byte UUID
+ * ret_buffer - Where the vendor resource is returned
*
* RETURN: Status
*
@@ -435,7 +384,6 @@ EXPORT_SYMBOL(acpi_resource_to_address64);
* UUID subtype. Returns a struct acpi_resource of type Vendor.
*
******************************************************************************/
-
acpi_status
acpi_get_vendor_resource(acpi_handle device_handle,
char *name,
@@ -467,18 +415,19 @@ acpi_get_vendor_resource(acpi_handle device_handle,
return (info.status);
}
+ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource)
+
/*******************************************************************************
*
* FUNCTION: acpi_rs_match_vendor_resource
*
- * PARAMETERS: ACPI_WALK_RESOURCE_CALLBACK
+ * PARAMETERS: acpi_walk_resource_callback
*
* RETURN: Status
*
* DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID
*
******************************************************************************/
-
static acpi_status
acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
{
@@ -526,3 +475,101 @@ acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
info->status = AE_OK;
return (AE_CTRL_TERMINATE);
}
+
+ACPI_EXPORT_SYMBOL(acpi_rs_match_vendor_resource)
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_walk_resources
+ *
+ * PARAMETERS: device_handle - Handle to the device object for the
+ * device we are querying
+ * Name - Method name of the resources we want
+ * (METHOD_NAME__CRS or METHOD_NAME__PRS)
+ * user_function - Called for each resource
+ * Context - Passed to user_function
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Retrieves the current or possible resource list for the
+ * specified device. The user_function is called once for
+ * each resource in the list.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_walk_resources(acpi_handle device_handle,
+ char *name,
+ acpi_walk_resource_callback user_function, void *context)
+{
+ acpi_status status;
+ struct acpi_buffer buffer;
+ struct acpi_resource *resource;
+ struct acpi_resource *resource_end;
+
+ ACPI_FUNCTION_TRACE(acpi_walk_resources);
+
+ /* Parameter validation */
+
+ if (!device_handle || !user_function || !name ||
+ (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) &&
+ !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ /* Get the _CRS or _PRS resource list */
+
+ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ status = acpi_rs_get_method_data(device_handle, name, &buffer);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Buffer now contains the resource list */
+
+ resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer);
+ resource_end =
+ ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length);
+
+ /* Walk the resource list until the end_tag is found (or buffer end) */
+
+ while (resource < resource_end) {
+
+ /* Sanity check the resource */
+
+ if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
+ status = AE_AML_INVALID_RESOURCE_TYPE;
+ break;
+ }
+
+ /* Invoke the user function, abort on any error returned */
+
+ status = user_function(resource, context);
+ if (ACPI_FAILURE(status)) {
+ if (status == AE_CTRL_TERMINATE) {
+
+ /* This is an OK termination by the user function */
+
+ status = AE_OK;
+ }
+ break;
+ }
+
+ /* end_tag indicates end-of-list */
+
+ if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
+ break;
+ }
+
+ /* Get the next resource descriptor */
+
+ resource =
+ ACPI_ADD_PTR(struct acpi_resource, resource,
+ resource->length);
+ }
+
+ ACPI_FREE(buffer.pointer);
+ return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_walk_resources)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index a0ab828b2cc..a5fa85832fa 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -234,12 +234,9 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
int acpi_match_ids(struct acpi_device *device, char *ids)
{
- int error = 0;
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-
if (device->flags.hardware_id)
if (strstr(ids, device->pnp.hardware_id))
- goto Done;
+ return 0;
if (device->flags.compatible_ids) {
struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
@@ -248,15 +245,10 @@ int acpi_match_ids(struct acpi_device *device, char *ids)
/* compare multiple _CID entries against driver ids */
for (i = 0; i < cid_list->count; i++) {
if (strstr(ids, cid_list->id[i].value))
- goto Done;
+ return 0;
}
}
- error = -ENOENT;
-
- Done:
- if (buffer.pointer)
- acpi_os_free(buffer.pointer);
- return error;
+ return -ENOENT;
}
static acpi_status
@@ -441,10 +433,7 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
islockable = device->flags.lockable;
handle = device->handle;
- if (type == ACPI_TYPE_PROCESSOR)
- result = acpi_bus_trim(device, 0);
- else
- result = acpi_bus_trim(device, 1);
+ result = acpi_bus_trim(device, 1);
if (!result)
result = acpi_eject_operation(handle, islockable);
@@ -645,21 +634,19 @@ EXPORT_SYMBOL(acpi_bus_register_driver);
*/
int acpi_bus_unregister_driver(struct acpi_driver *driver)
{
- int error = 0;
-
ACPI_FUNCTION_TRACE("acpi_bus_unregister_driver");
- if (driver) {
- acpi_driver_detach(driver);
+ if (!driver)
+ return_VALUE(-EINVAL);
- if (!atomic_read(&driver->references)) {
- spin_lock(&acpi_device_lock);
- list_del_init(&driver->node);
- spin_unlock(&acpi_device_lock);
- }
- } else
- error = -EINVAL;
- return_VALUE(error);
+ acpi_driver_detach(driver);
+
+ if (!atomic_read(&driver->references)) {
+ spin_lock(&acpi_device_lock);
+ list_del_init(&driver->node);
+ spin_unlock(&acpi_device_lock);
+ }
+ return_VALUE(0);
}
EXPORT_SYMBOL(acpi_bus_unregister_driver);
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
index 85df0ceda2a..af1dbabaf0b 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/sleep/wakeup.c
@@ -155,7 +155,6 @@ static int __init acpi_wakeup_device_init(void)
if (acpi_disabled)
return 0;
- printk("ACPI wakeup devices: \n");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
@@ -174,10 +173,8 @@ static int __init acpi_wakeup_device_init(void)
dev->wakeup.state.enabled = 1;
spin_lock(&acpi_device_lock);
}
- printk("%4s ", dev->pnp.bus_id);
}
spin_unlock(&acpi_device_lock);
- printk("\n");
return 0;
}
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index e4308c7a674..a934ac42178 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -39,7 +39,7 @@ ACPI_MODULE_NAME("acpi_system")
#define ACPI_SYSTEM_FILE_EVENT "event"
#define ACPI_SYSTEM_FILE_DSDT "dsdt"
#define ACPI_SYSTEM_FILE_FADT "fadt"
-extern FADT_DESCRIPTOR acpi_fadt;
+extern struct fadt_descriptor acpi_fadt;
/* --------------------------------------------------------------------------
FS Interface (/proc)
@@ -82,7 +82,7 @@ acpi_system_read_dsdt(struct file *file,
ACPI_FUNCTION_TRACE("acpi_system_read_dsdt");
- status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt);
+ status = acpi_get_table(ACPI_TABLE_ID_DSDT, 1, &dsdt);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
@@ -110,7 +110,7 @@ acpi_system_read_fadt(struct file *file,
ACPI_FUNCTION_TRACE("acpi_system_read_fadt");
- status = acpi_get_table(ACPI_TABLE_FADT, 1, &fadt);
+ status = acpi_get_table(ACPI_TABLE_ID_FADT, 1, &fadt);
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 7f37c7cc5ef..ed5e8816d83 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -282,8 +282,8 @@ acpi_get_table_header_early(enum acpi_table_id id,
/* Map the DSDT header via the pointer in the FADT */
if (id == ACPI_DSDT) {
- struct fadt_descriptor_rev2 *fadt =
- (struct fadt_descriptor_rev2 *)*header;
+ struct fadt_descriptor *fadt =
+ (struct fadt_descriptor *)*header;
if (fadt->revision == 3 && fadt->Xdsdt) {
*header = (void *)__acpi_map_table(fadt->Xdsdt,
diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c
index 03b37d2223b..d697fcb35d5 100644
--- a/drivers/acpi/tables/tbconvrt.c
+++ b/drivers/acpi/tables/tbconvrt.c
@@ -41,8 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include <acpi/actables.h>
@@ -56,15 +54,15 @@ acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct,
acpi_physical_address address);
static void
-acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt,
+acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt,
struct fadt_descriptor_rev1 *original_fadt);
static void
-acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt,
- struct fadt_descriptor_rev2 *original_fadt);
+acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt,
+ struct fadt_descriptor *original_fadt);
u8 acpi_fadt_is_v1;
-EXPORT_SYMBOL(acpi_fadt_is_v1);
+ACPI_EXPORT_SYMBOL(acpi_fadt_is_v1)
/*******************************************************************************
*
@@ -122,7 +120,7 @@ acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info)
{
acpi_size table_size;
u32 i;
- XSDT_DESCRIPTOR *new_table;
+ struct xsdt_descriptor *new_table;
ACPI_FUNCTION_ENTRY();
@@ -133,7 +131,7 @@ acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info)
/* Allocate an XSDT */
- new_table = ACPI_MEM_CALLOCATE(table_size);
+ new_table = ACPI_ALLOCATE_ZEROED(table_size);
if (!new_table) {
return (AE_NO_MEMORY);
}
@@ -147,17 +145,18 @@ acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info)
/* Copy the table pointers */
for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
+
/* RSDT pointers are 32 bits, XSDT pointers are 64 bits */
if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
ACPI_STORE_ADDRESS(new_table->table_offset_entry[i],
(ACPI_CAST_PTR
- (struct rsdt_descriptor_rev1,
+ (struct rsdt_descriptor,
table_info->pointer))->
table_offset_entry[i]);
} else {
new_table->table_offset_entry[i] =
- (ACPI_CAST_PTR(XSDT_DESCRIPTOR,
+ (ACPI_CAST_PTR(struct xsdt_descriptor,
table_info->pointer))->
table_offset_entry[i];
}
@@ -219,7 +218,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct,
******************************************************************************/
static void
-acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt,
+acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt,
struct fadt_descriptor_rev1 *original_fadt)
{
@@ -365,14 +364,13 @@ acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt,
******************************************************************************/
static void
-acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt,
- struct fadt_descriptor_rev2 *original_fadt)
+acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt,
+ struct fadt_descriptor *original_fadt)
{
/* We have an ACPI 2.0 FADT but we must copy it to our local buffer */
- ACPI_MEMCPY(local_fadt, original_fadt,
- sizeof(struct fadt_descriptor_rev2));
+ ACPI_MEMCPY(local_fadt, original_fadt, sizeof(struct fadt_descriptor));
/*
* "X" fields are optional extensions to the original V1.0 fields, so
@@ -491,10 +489,10 @@ acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt,
acpi_status acpi_tb_convert_table_fadt(void)
{
- struct fadt_descriptor_rev2 *local_fadt;
+ struct fadt_descriptor *local_fadt;
struct acpi_table_desc *table_desc;
- ACPI_FUNCTION_TRACE("tb_convert_table_fadt");
+ ACPI_FUNCTION_TRACE(tb_convert_table_fadt);
/*
* acpi_gbl_FADT is valid. Validate the FADT length. The table must be
@@ -508,13 +506,14 @@ acpi_status acpi_tb_convert_table_fadt(void)
/* Allocate buffer for the ACPI 2.0(+) FADT */
- local_fadt = ACPI_MEM_CALLOCATE(sizeof(struct fadt_descriptor_rev2));
+ local_fadt = ACPI_ALLOCATE_ZEROED(sizeof(struct fadt_descriptor));
if (!local_fadt) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) {
- if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev2)) {
+ if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor)) {
+
/* Length is too short to be a V2.0 table */
ACPI_WARNING((AE_INFO,
@@ -538,11 +537,11 @@ acpi_status acpi_tb_convert_table_fadt(void)
/* Global FADT pointer will point to the new common V2.0 FADT */
acpi_gbl_FADT = local_fadt;
- acpi_gbl_FADT->length = sizeof(FADT_DESCRIPTOR);
+ acpi_gbl_FADT->length = sizeof(struct fadt_descriptor);
/* Free the original table */
- table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next;
+ table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_FADT].next;
acpi_tb_delete_single_table(table_desc);
/* Install the new table */
@@ -550,7 +549,7 @@ acpi_status acpi_tb_convert_table_fadt(void)
table_desc->pointer =
ACPI_CAST_PTR(struct acpi_table_header, acpi_gbl_FADT);
table_desc->allocation = ACPI_MEM_ALLOCATED;
- table_desc->length = sizeof(struct fadt_descriptor_rev2);
+ table_desc->length = sizeof(struct fadt_descriptor);
/* Dump the entire FADT */
@@ -580,7 +579,7 @@ acpi_status acpi_tb_convert_table_fadt(void)
acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info)
{
- ACPI_FUNCTION_TRACE("tb_build_common_facs");
+ ACPI_FUNCTION_TRACE(tb_build_common_facs);
/* Absolute minimum length is 24, but the ACPI spec says 64 */
@@ -603,6 +602,7 @@ acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info)
if ((acpi_gbl_RSDP->revision < 2) ||
(acpi_gbl_FACS->length < 32) ||
(!(acpi_gbl_FACS->xfirmware_waking_vector))) {
+
/* ACPI 1.0 FACS or short table or optional X_ field is zero */
acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR(u64,
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
index 09b4ee6dfd6..99eacceff56 100644
--- a/drivers/acpi/tables/tbget.c
+++ b/drivers/acpi/tables/tbget.c
@@ -78,7 +78,7 @@ acpi_tb_get_table(struct acpi_pointer *address,
acpi_status status;
struct acpi_table_header header;
- ACPI_FUNCTION_TRACE("tb_get_table");
+ ACPI_FUNCTION_TRACE(tb_get_table);
/* Get the header in order to get signature and table size */
@@ -124,7 +124,7 @@ acpi_tb_get_table_header(struct acpi_pointer *address,
acpi_status status = AE_OK;
struct acpi_table_header *header = NULL;
- ACPI_FUNCTION_TRACE("tb_get_table_header");
+ ACPI_FUNCTION_TRACE(tb_get_table_header);
/*
* Flags contains the current processor mode (Virtual or Physical
@@ -148,6 +148,10 @@ acpi_tb_get_table_header(struct acpi_pointer *address,
sizeof(struct acpi_table_header),
(void *)&header);
if (ACPI_FAILURE(status)) {
+ ACPI_ERROR((AE_INFO,
+ "Could not map memory at %8.8X%8.8X for table header",
+ ACPI_FORMAT_UINT64(address->pointer.
+ physical)));
return_ACPI_STATUS(status);
}
@@ -198,7 +202,7 @@ acpi_tb_get_table_body(struct acpi_pointer *address,
{
acpi_status status;
- ACPI_FUNCTION_TRACE("tb_get_table_body");
+ ACPI_FUNCTION_TRACE(tb_get_table_body);
if (!table_info || !address) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -208,6 +212,7 @@ acpi_tb_get_table_body(struct acpi_pointer *address,
status = acpi_tb_table_override(header, table_info);
if (ACPI_SUCCESS(status)) {
+
/* Table was overridden by the host OS */
return_ACPI_STATUS(status);
@@ -241,7 +246,7 @@ acpi_tb_table_override(struct acpi_table_header *header,
acpi_status status;
struct acpi_pointer address;
- ACPI_FUNCTION_TRACE("tb_table_override");
+ ACPI_FUNCTION_TRACE(tb_table_override);
/*
* The OSL will examine the header and decide whether to override this
@@ -250,6 +255,7 @@ acpi_tb_table_override(struct acpi_table_header *header,
*/
status = acpi_os_table_override(header, &new_table);
if (ACPI_FAILURE(status)) {
+
/* Some severe error from the OSL, but we basically ignore it */
ACPI_EXCEPTION((AE_INFO, status,
@@ -258,6 +264,7 @@ acpi_tb_table_override(struct acpi_table_header *header,
}
if (!new_table) {
+
/* No table override */
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
@@ -311,7 +318,7 @@ acpi_tb_get_this_table(struct acpi_pointer *address,
u8 allocation;
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("tb_get_this_table");
+ ACPI_FUNCTION_TRACE(tb_get_this_table);
/*
* Flags contains the current processor mode (Virtual or Physical
@@ -323,7 +330,7 @@ acpi_tb_get_this_table(struct acpi_pointer *address,
/* Pointer matches processor mode, copy the table to a new buffer */
- full_table = ACPI_MEM_ALLOCATE(header->length);
+ full_table = ACPI_ALLOCATE(header->length);
if (!full_table) {
ACPI_ERROR((AE_INFO,
"Could not allocate table memory for [%4.4s] length %X",
@@ -376,11 +383,12 @@ acpi_tb_get_this_table(struct acpi_pointer *address,
* Validate checksum for _most_ tables,
* even the ones whose signature we don't recognize
*/
- if (table_info->type != ACPI_TABLE_FACS) {
+ if (table_info->type != ACPI_TABLE_ID_FACS) {
status = acpi_tb_verify_table_checksum(full_table);
#if (!ACPI_CHECKSUM_ABORT)
if (ACPI_FAILURE(status)) {
+
/* Ignore the error if configuration says so */
status = AE_OK;
@@ -409,7 +417,7 @@ acpi_tb_get_this_table(struct acpi_pointer *address,
*
* PARAMETERS: table_type - one of the defined table types
* Instance - Which table of this type
- * table_ptr_loc - pointer to location to place the pointer for
+ * return_table - pointer to location to place the pointer for
* return
*
* RETURN: Status
@@ -420,57 +428,34 @@ acpi_tb_get_this_table(struct acpi_pointer *address,
acpi_status
acpi_tb_get_table_ptr(acpi_table_type table_type,
- u32 instance, struct acpi_table_header **table_ptr_loc)
+ u32 instance, struct acpi_table_header **return_table)
{
struct acpi_table_desc *table_desc;
u32 i;
- ACPI_FUNCTION_TRACE("tb_get_table_ptr");
-
- if (!acpi_gbl_DSDT) {
- return_ACPI_STATUS(AE_NO_ACPI_TABLES);
- }
+ ACPI_FUNCTION_TRACE(tb_get_table_ptr);
- if (table_type > ACPI_TABLE_MAX) {
+ if (table_type > ACPI_TABLE_ID_MAX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- /*
- * For all table types (Single/Multiple), the first
- * instance is always in the list head.
- */
- if (instance == 1) {
- /* Get the first */
-
- *table_ptr_loc = NULL;
- if (acpi_gbl_table_lists[table_type].next) {
- *table_ptr_loc =
- acpi_gbl_table_lists[table_type].next->pointer;
- }
- return_ACPI_STATUS(AE_OK);
- }
-
- /* Check for instance out of range */
+ /* Check for instance out of range of the current table count */
if (instance > acpi_gbl_table_lists[table_type].count) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
- /* Walk the list to get the desired table
- * Since the if (Instance == 1) check above checked for the
- * first table, setting table_desc equal to the .Next member
- * is actually pointing to the second table. Therefore, we
- * need to walk from the 2nd table until we reach the Instance
- * that the user is looking for and return its table pointer.
+ /*
+ * Walk the list to get the desired table
+ * Note: Instance is one-based
*/
table_desc = acpi_gbl_table_lists[table_type].next;
- for (i = 2; i < instance; i++) {
+ for (i = 1; i < instance; i++) {
table_desc = table_desc->next;
}
/* We are now pointing to the requested table's descriptor */
- *table_ptr_loc = table_desc->pointer;
-
+ *return_table = table_desc->pointer;
return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c
index 134e5dce0bc..ad982112e4c 100644
--- a/drivers/acpi/tables/tbgetall.c
+++ b/drivers/acpi/tables/tbgetall.c
@@ -77,7 +77,7 @@ acpi_tb_get_primary_table(struct acpi_pointer *address,
acpi_status status;
struct acpi_table_header header;
- ACPI_FUNCTION_TRACE("tb_get_primary_table");
+ ACPI_FUNCTION_TRACE(tb_get_primary_table);
/* Ignore a NULL address in the RSDT */
@@ -140,7 +140,7 @@ acpi_tb_get_secondary_table(struct acpi_pointer *address,
acpi_status status;
struct acpi_table_header header;
- ACPI_FUNCTION_TRACE_STR("tb_get_secondary_table", signature);
+ ACPI_FUNCTION_TRACE_STR(tb_get_secondary_table, signature);
/* Get the header in order to match the signature */
@@ -151,7 +151,7 @@ acpi_tb_get_secondary_table(struct acpi_pointer *address,
/* Signature must match request */
- if (ACPI_STRNCMP(header.signature, signature, ACPI_NAME_SIZE)) {
+ if (!ACPI_COMPARE_NAME(header.signature, signature)) {
ACPI_ERROR((AE_INFO,
"Incorrect table signature - wanted [%s] found [%4.4s]",
signature, header.signature));
@@ -207,7 +207,7 @@ acpi_status acpi_tb_get_required_tables(void)
struct acpi_table_desc table_info;
struct acpi_pointer address;
- ACPI_FUNCTION_TRACE("tb_get_required_tables");
+ ACPI_FUNCTION_TRACE(tb_get_required_tables);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%d ACPI tables in RSDT\n",
acpi_gbl_rsdt_table_count));
@@ -223,6 +223,7 @@ acpi_status acpi_tb_get_required_tables(void)
* any SSDTs.
*/
for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
+
/* Get the table address from the common internal XSDT */
address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i];
@@ -305,6 +306,6 @@ acpi_status acpi_tb_get_required_tables(void)
/* Always delete the RSDP mapping, we are done with it */
- acpi_tb_delete_tables_by_type(ACPI_TABLE_RSDP);
+ acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_RSDP);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index 7ffd0fddb4e..7ca2df75bb1 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -73,17 +73,18 @@ acpi_tb_match_signature(char *signature,
{
acpi_native_uint i;
- ACPI_FUNCTION_TRACE("tb_match_signature");
+ ACPI_FUNCTION_TRACE(tb_match_signature);
/* Search for a signature match among the known table types */
- for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) {
+ for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) {
if (!(acpi_gbl_table_data[i].flags & search_type)) {
continue;
}
if (!ACPI_STRNCMP(signature, acpi_gbl_table_data[i].signature,
acpi_gbl_table_data[i].sig_length)) {
+
/* Found a signature match, return index if requested */
if (table_info) {
@@ -122,7 +123,7 @@ acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("tb_install_table");
+ ACPI_FUNCTION_TRACE(tb_install_table);
/* Lock tables while installing */
@@ -187,7 +188,7 @@ acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type)
struct acpi_table_header *table_header;
acpi_status status;
- ACPI_FUNCTION_TRACE("tb_recognize_table");
+ ACPI_FUNCTION_TRACE(tb_recognize_table);
/* Ensure that we have a valid table pointer */
@@ -218,7 +219,6 @@ acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type)
/* Return the table type and length via the info struct */
table_info->length = (acpi_size) table_header->length;
-
return_ACPI_STATUS(status);
}
@@ -243,11 +243,11 @@ acpi_tb_init_table_descriptor(acpi_table_type table_type,
struct acpi_table_desc *table_desc;
acpi_status status;
- ACPI_FUNCTION_TRACE_U32("tb_init_table_descriptor", table_type);
+ ACPI_FUNCTION_TRACE_U32(tb_init_table_descriptor, table_type);
/* Allocate a descriptor for this table */
- table_desc = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc));
+ table_desc = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc));
if (!table_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -274,7 +274,7 @@ acpi_tb_init_table_descriptor(acpi_table_type table_type,
* at this location, so return an error.
*/
if (list_head->next) {
- ACPI_MEM_FREE(table_desc);
+ ACPI_FREE(table_desc);
return_ACPI_STATUS(AE_ALREADY_EXISTS);
}
@@ -312,15 +312,14 @@ acpi_tb_init_table_descriptor(acpi_table_type table_type,
/* Finish initialization of the table descriptor */
+ table_desc->loaded_into_namespace = FALSE;
table_desc->type = (u8) table_type;
table_desc->pointer = table_info->pointer;
table_desc->length = table_info->length;
table_desc->allocation = table_info->allocation;
table_desc->aml_start = (u8 *) (table_desc->pointer + 1),
- table_desc->aml_length = (u32) (table_desc->length -
- (u32) sizeof(struct
- acpi_table_header));
- table_desc->loaded_into_namespace = FALSE;
+ table_desc->aml_length = (u32)
+ (table_desc->length - (u32) sizeof(struct acpi_table_header));
/*
* Set the appropriate global pointer (if there is one) to point to the
@@ -335,7 +334,6 @@ acpi_tb_init_table_descriptor(acpi_table_type table_type,
table_info->owner_id = table_desc->owner_id;
table_info->installed_desc = table_desc;
-
return_ACPI_STATUS(AE_OK);
}
@@ -359,7 +357,7 @@ void acpi_tb_delete_all_tables(void)
* Free memory allocated for ACPI tables
* Memory can either be mapped or allocated
*/
- for (type = 0; type < NUM_ACPI_TABLE_TYPES; type++) {
+ for (type = 0; type < (ACPI_TABLE_ID_MAX + 1); type++) {
acpi_tb_delete_tables_by_type(type);
}
}
@@ -383,9 +381,9 @@ void acpi_tb_delete_tables_by_type(acpi_table_type type)
u32 count;
u32 i;
- ACPI_FUNCTION_TRACE_U32("tb_delete_tables_by_type", type);
+ ACPI_FUNCTION_TRACE_U32(tb_delete_tables_by_type, type);
- if (type > ACPI_TABLE_MAX) {
+ if (type > ACPI_TABLE_ID_MAX) {
return_VOID;
}
@@ -396,28 +394,28 @@ void acpi_tb_delete_tables_by_type(acpi_table_type type)
/* Clear the appropriate "typed" global table pointer */
switch (type) {
- case ACPI_TABLE_RSDP:
+ case ACPI_TABLE_ID_RSDP:
acpi_gbl_RSDP = NULL;
break;
- case ACPI_TABLE_DSDT:
+ case ACPI_TABLE_ID_DSDT:
acpi_gbl_DSDT = NULL;
break;
- case ACPI_TABLE_FADT:
+ case ACPI_TABLE_ID_FADT:
acpi_gbl_FADT = NULL;
break;
- case ACPI_TABLE_FACS:
+ case ACPI_TABLE_ID_FACS:
acpi_gbl_FACS = NULL;
break;
- case ACPI_TABLE_XSDT:
+ case ACPI_TABLE_ID_XSDT:
acpi_gbl_XSDT = NULL;
break;
- case ACPI_TABLE_SSDT:
- case ACPI_TABLE_PSDT:
+ case ACPI_TABLE_ID_SSDT:
+ case ACPI_TABLE_ID_PSDT:
default:
break;
}
@@ -471,7 +469,7 @@ void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc)
case ACPI_MEM_ALLOCATED:
- ACPI_MEM_FREE(table_desc->pointer);
+ ACPI_FREE(table_desc->pointer);
break;
case ACPI_MEM_MAPPED:
@@ -503,7 +501,7 @@ struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc
{
struct acpi_table_desc *next_desc;
- ACPI_FUNCTION_TRACE_PTR("tb_uninstall_table", table_desc);
+ ACPI_FUNCTION_TRACE_PTR(tb_uninstall_table, table_desc);
if (!table_desc) {
return_PTR(NULL);
@@ -530,7 +528,7 @@ struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc
/* Free the table descriptor */
next_desc = table_desc->next;
- ACPI_MEM_FREE(table_desc);
+ ACPI_FREE(table_desc);
/* Return pointer to the next descriptor */
diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c
index 4d308220225..abcb08c2592 100644
--- a/drivers/acpi/tables/tbrsdt.c
+++ b/drivers/acpi/tables/tbrsdt.c
@@ -64,7 +64,7 @@ acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address)
acpi_status status;
struct rsdp_descriptor *rsdp;
- ACPI_FUNCTION_TRACE("tb_verify_rsdp");
+ ACPI_FUNCTION_TRACE(tb_verify_rsdp);
switch (address->pointer_type) {
case ACPI_LOGICAL_POINTER:
@@ -78,7 +78,7 @@ acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address)
*/
status = acpi_os_map_memory(address->pointer.physical,
sizeof(struct rsdp_descriptor),
- (void *)&rsdp);
+ ACPI_CAST_PTR(void, &rsdp));
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -95,15 +95,20 @@ acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address)
goto cleanup;
}
- /* The RSDP supplied is OK */
+ /* RSDP is ok. Init the table info */
table_info.pointer = ACPI_CAST_PTR(struct acpi_table_header, rsdp);
table_info.length = sizeof(struct rsdp_descriptor);
- table_info.allocation = ACPI_MEM_MAPPED;
+
+ if (address->pointer_type == ACPI_PHYSICAL_POINTER) {
+ table_info.allocation = ACPI_MEM_MAPPED;
+ } else {
+ table_info.allocation = ACPI_MEM_NOT_ALLOCATED;
+ }
/* Save the table pointers and allocation info */
- status = acpi_tb_init_table_descriptor(ACPI_TABLE_RSDP, &table_info);
+ status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_RSDP, &table_info);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
@@ -174,22 +179,20 @@ void acpi_tb_get_rsdt_address(struct acpi_pointer *out_address)
acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr)
{
- int no_match;
+ char *signature;
ACPI_FUNCTION_ENTRY();
- /*
- * Search for appropriate signature, RSDT or XSDT
- */
+ /* Search for appropriate signature, RSDT or XSDT */
+
if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
- no_match = ACPI_STRNCMP((char *)table_ptr, RSDT_SIG,
- sizeof(RSDT_SIG) - 1);
+ signature = RSDT_SIG;
} else {
- no_match = ACPI_STRNCMP((char *)table_ptr, XSDT_SIG,
- sizeof(XSDT_SIG) - 1);
+ signature = XSDT_SIG;
}
- if (no_match) {
+ if (!ACPI_COMPARE_NAME(table_ptr->signature, signature)) {
+
/* Invalid RSDT or XSDT signature */
ACPI_ERROR((AE_INFO,
@@ -198,10 +201,8 @@ acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr)
ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20);
ACPI_ERROR((AE_INFO,
- "RSDT/XSDT signature at %X (%p) is invalid",
- acpi_gbl_RSDP->rsdt_physical_address,
- (void *)(acpi_native_uint) acpi_gbl_RSDP->
- rsdt_physical_address));
+ "RSDT/XSDT signature at %X is invalid",
+ acpi_gbl_RSDP->rsdt_physical_address));
if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
ACPI_ERROR((AE_INFO, "Looking for RSDT"));
@@ -234,13 +235,13 @@ acpi_status acpi_tb_get_table_rsdt(void)
acpi_status status;
struct acpi_pointer address;
- ACPI_FUNCTION_TRACE("tb_get_table_rsdt");
+ ACPI_FUNCTION_TRACE(tb_get_table_rsdt);
/* Get the RSDT/XSDT via the RSDP */
acpi_tb_get_rsdt_address(&address);
- table_info.type = ACPI_TABLE_XSDT;
+ table_info.type = ACPI_TABLE_ID_XSDT;
status = acpi_tb_get_table(&address, &table_info);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
@@ -274,12 +275,13 @@ acpi_status acpi_tb_get_table_rsdt(void)
/* Save the table pointers and allocation info */
- status = acpi_tb_init_table_descriptor(ACPI_TABLE_XSDT, &table_info);
+ status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_XSDT, &table_info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- acpi_gbl_XSDT = ACPI_CAST_PTR(XSDT_DESCRIPTOR, table_info.pointer);
+ acpi_gbl_XSDT =
+ ACPI_CAST_PTR(struct xsdt_descriptor, table_info.pointer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT));
return_ACPI_STATUS(status);
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
index bc571592f08..209a401801e 100644
--- a/drivers/acpi/tables/tbutils.c
+++ b/drivers/acpi/tables/tbutils.c
@@ -71,7 +71,7 @@ acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc)
{
struct acpi_table_desc *table_desc;
- ACPI_FUNCTION_TRACE("tb_is_table_installed");
+ ACPI_FUNCTION_TRACE(tb_is_table_installed);
/* Get the list descriptor and first table descriptor */
@@ -96,10 +96,11 @@ acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc)
(!ACPI_MEMCMP
(table_desc->pointer, new_table_desc->pointer,
new_table_desc->pointer->length))) {
+
/* Match: this table is already installed */
ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
- "Table [%4.4s] already installed: Rev %X oem_table_id [%8.8s]\n",
+ "Table [%4.4s] already installed: Rev %X OemTableId [%8.8s]\n",
new_table_desc->pointer->signature,
new_table_desc->pointer->revision,
new_table_desc->pointer->
@@ -159,12 +160,8 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header)
ACPI_MOVE_32_TO_32(&signature, table_header->signature);
if (!acpi_ut_valid_acpi_name(signature)) {
- ACPI_ERROR((AE_INFO,
- "Table signature at %p [%p] has invalid characters",
- table_header, &signature));
-
- ACPI_WARNING((AE_INFO, "Invalid table signature found: [%4.4s]",
- ACPI_CAST_PTR(char, &signature)));
+ ACPI_ERROR((AE_INFO, "Invalid table signature 0x%8.8X",
+ signature));
ACPI_DUMP_BUFFER(table_header,
sizeof(struct acpi_table_header));
@@ -175,12 +172,9 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header)
if (table_header->length < sizeof(struct acpi_table_header)) {
ACPI_ERROR((AE_INFO,
- "Invalid length in table header %p name %4.4s",
- table_header, (char *)&signature));
-
- ACPI_WARNING((AE_INFO,
- "Invalid table header length (0x%X) found",
- (u32) table_header->length));
+ "Invalid length 0x%X in table with signature %4.4s",
+ (u32) table_header->length,
+ ACPI_CAST_PTR(char, &signature)));
ACPI_DUMP_BUFFER(table_header,
sizeof(struct acpi_table_header));
@@ -192,72 +186,119 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header)
/*******************************************************************************
*
- * FUNCTION: acpi_tb_verify_table_checksum
+ * FUNCTION: acpi_tb_sum_table
*
- * PARAMETERS: *table_header - ACPI table to verify
+ * PARAMETERS: Buffer - Buffer to sum
+ * Length - Size of the buffer
*
- * RETURN: 8 bit checksum of table
+ * RETURN: 8 bit sum of buffer
*
- * DESCRIPTION: Does an 8 bit checksum of table and returns status. A correct
- * table should have a checksum of 0.
+ * DESCRIPTION: Computes an 8 bit sum of the buffer(length) and returns it.
*
******************************************************************************/
-acpi_status
-acpi_tb_verify_table_checksum(struct acpi_table_header * table_header)
+u8 acpi_tb_sum_table(void *buffer, u32 length)
+{
+ acpi_native_uint i;
+ u8 sum = 0;
+
+ if (!buffer || !length) {
+ return (0);
+ }
+
+ for (i = 0; i < length; i++) {
+ sum = (u8) (sum + ((u8 *) buffer)[i]);
+ }
+ return (sum);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_generate_checksum
+ *
+ * PARAMETERS: Table - Pointer to a valid ACPI table (with a
+ * standard ACPI header)
+ *
+ * RETURN: 8 bit checksum of buffer
+ *
+ * DESCRIPTION: Computes an 8 bit checksum of the table.
+ *
+ ******************************************************************************/
+
+u8 acpi_tb_generate_checksum(struct acpi_table_header * table)
{
u8 checksum;
- acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("tb_verify_table_checksum");
+ /* Sum the entire table as-is */
- /* Compute the checksum on the table */
+ checksum = acpi_tb_sum_table(table, table->length);
- checksum =
- acpi_tb_generate_checksum(table_header, table_header->length);
+ /* Subtract off the existing checksum value in the table */
- /* Return the appropriate exception */
+ checksum = (u8) (checksum - table->checksum);
- if (checksum) {
- ACPI_WARNING((AE_INFO,
- "Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)",
- table_header->signature,
- (u32) table_header->checksum, (u32) checksum));
+ /* Compute the final checksum */
- status = AE_BAD_CHECKSUM;
- }
- return_ACPI_STATUS(status);
+ checksum = (u8) (0 - checksum);
+ return (checksum);
}
/*******************************************************************************
*
- * FUNCTION: acpi_tb_generate_checksum
+ * FUNCTION: acpi_tb_set_checksum
*
- * PARAMETERS: Buffer - Buffer to checksum
- * Length - Size of the buffer
+ * PARAMETERS: Table - Pointer to a valid ACPI table (with a
+ * standard ACPI header)
*
- * RETURN: 8 bit checksum of buffer
+ * RETURN: None. Sets the table checksum field
*
- * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it.
+ * DESCRIPTION: Computes an 8 bit checksum of the table and inserts the
+ * checksum into the table header.
*
******************************************************************************/
-u8 acpi_tb_generate_checksum(void *buffer, u32 length)
+void acpi_tb_set_checksum(struct acpi_table_header *table)
{
- u8 *end_buffer;
- u8 *rover;
- u8 sum = 0;
- if (buffer && length) {
- /* Buffer and Length are valid */
+ table->checksum = acpi_tb_generate_checksum(table);
+}
- end_buffer = ACPI_ADD_PTR(u8, buffer, length);
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_verify_table_checksum
+ *
+ * PARAMETERS: *table_header - ACPI table to verify
+ *
+ * RETURN: 8 bit checksum of table
+ *
+ * DESCRIPTION: Generates an 8 bit checksum of table and returns and compares
+ * it to the existing checksum value.
+ *
+ ******************************************************************************/
- for (rover = buffer; rover < end_buffer; rover++) {
- sum = (u8) (sum + *rover);
- }
+acpi_status
+acpi_tb_verify_table_checksum(struct acpi_table_header *table_header)
+{
+ u8 checksum;
+
+ ACPI_FUNCTION_TRACE(tb_verify_table_checksum);
+
+ /* Compute the checksum on the table */
+
+ checksum = acpi_tb_generate_checksum(table_header);
+
+ /* Checksum ok? */
+
+ if (checksum == table_header->checksum) {
+ return_ACPI_STATUS(AE_OK);
}
- return (sum);
+
+ ACPI_WARNING((AE_INFO,
+ "Incorrect checksum in table [%4.4s] - is %2.2X, should be %2.2X",
+ table_header->signature, table_header->checksum,
+ checksum));
+
+ return_ACPI_STATUS(AE_BAD_CHECKSUM);
}
#ifdef ACPI_OBSOLETE_FUNCTIONS
@@ -276,12 +317,12 @@ u8 acpi_tb_generate_checksum(void *buffer, u32 length)
acpi_status
acpi_tb_handle_to_object(u16 table_id,
- struct acpi_table_desc ** return_table_desc)
+ struct acpi_table_desc **return_table_desc)
{
u32 i;
struct acpi_table_desc *table_desc;
- ACPI_FUNCTION_NAME("tb_handle_to_object");
+ ACPI_FUNCTION_NAME(tb_handle_to_object);
for (i = 0; i < ACPI_TABLE_MAX; i++) {
table_desc = acpi_gbl_table_lists[i].next;
@@ -295,7 +336,7 @@ acpi_tb_handle_to_object(u16 table_id,
}
}
- ACPI_ERROR((AE_INFO, "table_id=%X does not exist", table_id));
+ ACPI_ERROR((AE_INFO, "TableId=%X does not exist", table_id));
return (AE_BAD_PARAMETER);
}
#endif
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 9fe53c9d5b9..4e91f298481 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -42,8 +42,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/actables.h>
@@ -68,7 +66,7 @@ acpi_status acpi_load_tables(void)
struct acpi_pointer rsdp_address;
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_load_tables");
+ ACPI_FUNCTION_TRACE(acpi_load_tables);
/* Get the RSDP */
@@ -123,6 +121,8 @@ acpi_status acpi_load_tables(void)
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_load_tables)
+
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -139,14 +139,13 @@ acpi_status acpi_load_tables(void)
* is determined that the table is invalid, the call will fail.
*
******************************************************************************/
-
acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
{
acpi_status status;
struct acpi_table_desc table_info;
struct acpi_pointer address;
- ACPI_FUNCTION_TRACE("acpi_load_table");
+ ACPI_FUNCTION_TRACE(acpi_load_table);
if (!table_ptr) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -174,6 +173,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
status = acpi_tb_install_table(&table_info);
if (ACPI_FAILURE(status)) {
if (status == AE_ALREADY_EXISTS) {
+
/* Table already exists, no error */
status = AE_OK;
@@ -188,12 +188,12 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
/* Convert the table to common format if necessary */
switch (table_info.type) {
- case ACPI_TABLE_FADT:
+ case ACPI_TABLE_ID_FADT:
status = acpi_tb_convert_table_fadt();
break;
- case ACPI_TABLE_FACS:
+ case ACPI_TABLE_ID_FACS:
status = acpi_tb_build_common_facs(&table_info);
break;
@@ -208,6 +208,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
}
if (ACPI_FAILURE(status)) {
+
/* Uninstall table and free the buffer */
(void)acpi_tb_uninstall_table(table_info.installed_desc);
@@ -216,6 +217,8 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_load_table)
+
/*******************************************************************************
*
* FUNCTION: acpi_unload_table
@@ -227,16 +230,15 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
* DESCRIPTION: This routine is used to force the unload of a table
*
******************************************************************************/
-
acpi_status acpi_unload_table(acpi_table_type table_type)
{
struct acpi_table_desc *table_desc;
- ACPI_FUNCTION_TRACE("acpi_unload_table");
+ ACPI_FUNCTION_TRACE(acpi_unload_table);
/* Parameter validation */
- if (table_type > ACPI_TABLE_MAX) {
+ if (table_type > ACPI_TABLE_ID_MAX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -261,6 +263,8 @@ acpi_status acpi_unload_table(acpi_table_type table_type)
return_ACPI_STATUS(AE_OK);
}
+ACPI_EXPORT_SYMBOL(acpi_unload_table)
+
/*******************************************************************************
*
* FUNCTION: acpi_get_table_header
@@ -281,7 +285,6 @@ acpi_status acpi_unload_table(acpi_table_type table_type)
* have a standard header and is fixed length.
*
******************************************************************************/
-
acpi_status
acpi_get_table_header(acpi_table_type table_type,
u32 instance, struct acpi_table_header *out_table_header)
@@ -289,16 +292,16 @@ acpi_get_table_header(acpi_table_type table_type,
struct acpi_table_header *tbl_ptr;
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_get_table_header");
+ ACPI_FUNCTION_TRACE(acpi_get_table_header);
if ((instance == 0) ||
- (table_type == ACPI_TABLE_RSDP) || (!out_table_header)) {
+ (table_type == ACPI_TABLE_ID_RSDP) || (!out_table_header)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Check the table type and instance */
- if ((table_type > ACPI_TABLE_MAX) ||
+ if ((table_type > ACPI_TABLE_ID_MAX) ||
(ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) &&
instance > 1)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -325,6 +328,7 @@ acpi_get_table_header(acpi_table_type table_type,
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_get_table_header)
#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
@@ -349,7 +353,6 @@ acpi_get_table_header(acpi_table_type table_type,
* a complete table including the header.
*
******************************************************************************/
-
acpi_status
acpi_get_table(acpi_table_type table_type,
u32 instance, struct acpi_buffer *ret_buffer)
@@ -358,7 +361,7 @@ acpi_get_table(acpi_table_type table_type,
acpi_status status;
acpi_size table_length;
- ACPI_FUNCTION_TRACE("acpi_get_table");
+ ACPI_FUNCTION_TRACE(acpi_get_table);
/* Parameter validation */
@@ -373,7 +376,7 @@ acpi_get_table(acpi_table_type table_type,
/* Check the table type and instance */
- if ((table_type > ACPI_TABLE_MAX) ||
+ if ((table_type > ACPI_TABLE_ID_MAX) ||
(ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) &&
instance > 1)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -396,7 +399,8 @@ acpi_get_table(acpi_table_type table_type,
/* Get the table length */
- if (table_type == ACPI_TABLE_RSDP) {
+ if (table_type == ACPI_TABLE_ID_RSDP) {
+
/* RSD PTR is the only "table" without a header */
table_length = sizeof(struct rsdp_descriptor);
@@ -417,4 +421,4 @@ acpi_get_table(acpi_table_type table_type,
return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_get_table);
+ACPI_EXPORT_SYMBOL(acpi_get_table)
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
index a62db6af83c..da2648bbdbc 100644
--- a/drivers/acpi/tables/tbxfroot.c
+++ b/drivers/acpi/tables/tbxfroot.c
@@ -41,8 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include <acpi/actables.h>
@@ -75,6 +73,7 @@ acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp)
* The signature and checksum must both be correct
*/
if (ACPI_STRNCMP((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) {
+
/* Nope, BAD Signature */
return (AE_BAD_SIGNATURE);
@@ -82,15 +81,14 @@ acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp)
/* Check the standard checksum */
- if (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
+ if (acpi_tb_sum_table(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
return (AE_BAD_CHECKSUM);
}
/* Check extended checksum if table version >= 2 */
if ((rsdp->revision >= 2) &&
- (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) !=
- 0)) {
+ (acpi_tb_sum_table(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
return (AE_BAD_CHECKSUM);
}
@@ -121,7 +119,7 @@ acpi_tb_find_table(char *signature,
acpi_status status;
struct acpi_table_header *table;
- ACPI_FUNCTION_TRACE("tb_find_table");
+ ACPI_FUNCTION_TRACE(tb_find_table);
/* Validate string lengths */
@@ -131,7 +129,7 @@ acpi_tb_find_table(char *signature,
return_ACPI_STATUS(AE_AML_STRING_LIMIT);
}
- if (!ACPI_STRNCMP(signature, DSDT_SIG, ACPI_NAME_SIZE)) {
+ if (ACPI_COMPARE_NAME(signature, DSDT_SIG)) {
/*
* The DSDT pointer is contained in the FADT, not the RSDT.
* This code should suffice, because the only code that would perform
@@ -156,10 +154,12 @@ acpi_tb_find_table(char *signature,
/* Check oem_id and oem_table_id */
- if ((oem_id[0] && ACPI_STRNCMP(oem_id, table->oem_id,
- sizeof(table->oem_id))) ||
- (oem_table_id[0] && ACPI_STRNCMP(oem_table_id, table->oem_table_id,
- sizeof(table->oem_table_id)))) {
+ if ((oem_id[0] &&
+ ACPI_STRNCMP(oem_id, table->oem_id,
+ sizeof(table->oem_id))) ||
+ (oem_table_id[0] &&
+ ACPI_STRNCMP(oem_table_id, table->oem_table_id,
+ sizeof(table->oem_table_id)))) {
return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND);
}
@@ -203,7 +203,7 @@ acpi_get_firmware_table(acpi_string signature,
u32 i;
u32 j;
- ACPI_FUNCTION_TRACE("acpi_get_firmware_table");
+ ACPI_FUNCTION_TRACE(acpi_get_firmware_table);
/*
* Ensure that at least the table manager is initialized. We don't
@@ -217,6 +217,7 @@ acpi_get_firmware_table(acpi_string signature,
/* Ensure that we have a RSDP */
if (!acpi_gbl_RSDP) {
+
/* Get the RSDP */
status = acpi_os_get_root_pointer(flags, &address);
@@ -261,7 +262,7 @@ acpi_get_firmware_table(acpi_string signature,
/* Get and validate the RSDT */
- rsdt_info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc));
+ rsdt_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc));
if (!rsdt_info) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -278,13 +279,13 @@ acpi_get_firmware_table(acpi_string signature,
/* Allocate a scratch table header and table descriptor */
- header = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_header));
+ header = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
if (!header) {
status = AE_NO_MEMORY;
goto cleanup;
}
- table_info = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_desc));
+ table_info = ACPI_ALLOCATE(sizeof(struct acpi_table_desc));
if (!table_info) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -308,12 +309,12 @@ acpi_get_firmware_table(acpi_string signature,
if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
address.pointer.value =
(ACPI_CAST_PTR
- (RSDT_DESCRIPTOR,
+ (struct rsdt_descriptor,
rsdt_info->pointer))->table_offset_entry[i];
} else {
address.pointer.value =
(ACPI_CAST_PTR
- (XSDT_DESCRIPTOR,
+ (struct xsdt_descriptor,
rsdt_info->pointer))->table_offset_entry[i];
}
@@ -326,11 +327,13 @@ acpi_get_firmware_table(acpi_string signature,
/* Compare table signatures and table instance */
- if (!ACPI_STRNCMP(header->signature, signature, ACPI_NAME_SIZE)) {
+ if (ACPI_COMPARE_NAME(header->signature, signature)) {
+
/* An instance of the table was found */
j++;
if (j >= instance) {
+
/* Found the correct instance, get the entire table */
status =
@@ -355,23 +358,21 @@ acpi_get_firmware_table(acpi_string signature,
acpi_os_unmap_memory(rsdt_info->pointer,
(acpi_size) rsdt_info->pointer->length);
}
- ACPI_MEM_FREE(rsdt_info);
+ ACPI_FREE(rsdt_info);
if (header) {
- ACPI_MEM_FREE(header);
+ ACPI_FREE(header);
}
if (table_info) {
- ACPI_MEM_FREE(table_info);
+ ACPI_FREE(table_info);
}
return_ACPI_STATUS(status);
}
-EXPORT_SYMBOL(acpi_get_firmware_table);
+ACPI_EXPORT_SYMBOL(acpi_get_firmware_table)
/* TBD: Move to a new file */
-
#if ACPI_MACHINE_WIDTH != 16
-
/*******************************************************************************
*
* FUNCTION: acpi_find_root_pointer
@@ -384,13 +385,12 @@ EXPORT_SYMBOL(acpi_get_firmware_table);
* DESCRIPTION: Find the RSDP
*
******************************************************************************/
-
acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address)
{
struct acpi_table_desc table_info;
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_find_root_pointer");
+ ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
/* Get the RSDP */
@@ -407,6 +407,8 @@ acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address)
return_ACPI_STATUS(AE_OK);
}
+ACPI_EXPORT_SYMBOL(acpi_find_root_pointer)
+
/*******************************************************************************
*
* FUNCTION: acpi_tb_scan_memory_for_rsdp
@@ -419,14 +421,13 @@ acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address)
* DESCRIPTION: Search a block of memory for the RSDP signature
*
******************************************************************************/
-
static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
{
acpi_status status;
u8 *mem_rover;
u8 *end_address;
- ACPI_FUNCTION_TRACE("tb_scan_memory_for_rsdp");
+ ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp);
end_address = start_address + length;
@@ -434,12 +435,14 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
for (mem_rover = start_address; mem_rover < end_address;
mem_rover += ACPI_RSDP_SCAN_STEP) {
+
/* The RSDP signature and checksum must both be correct */
status =
acpi_tb_validate_rsdp(ACPI_CAST_PTR
(struct rsdp_descriptor, mem_rover));
if (ACPI_SUCCESS(status)) {
+
/* Sig and checksum valid, we have found a real RSDP */
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -469,10 +472,10 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
*
* RETURN: Status, RSDP physical address
*
- * DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor
+ * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor
* pointer structure. If it is found, set *RSDP to point to it.
*
- * NOTE1: The RSDp must be either in the first 1_k of the Extended
+ * NOTE1: The RSDP must be either in the first 1_k of the Extended
* BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
* Only a 32-bit physical address is necessary.
*
@@ -489,12 +492,13 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
u32 physical_address;
acpi_status status;
- ACPI_FUNCTION_TRACE("tb_find_rsdp");
+ ACPI_FUNCTION_TRACE(tb_find_rsdp);
/*
* Scan supports either logical addressing or physical addressing
*/
if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
+
/* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
status = acpi_os_map_memory((acpi_physical_address)
@@ -521,7 +525,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
if (physical_address > 0x400) {
/*
- * 1b) Search EBDA paragraphs (EBDa is required to be a
+ * 1b) Search EBDA paragraphs (EBDA is required to be a
* minimum of 1_k length)
*/
status = acpi_os_map_memory((acpi_physical_address)
@@ -542,10 +546,11 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
if (mem_rover) {
+
/* Return the physical address */
physical_address +=
- ACPI_PTR_DIFF(mem_rover, table_ptr);
+ (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
table_info->physical_address =
(acpi_physical_address) physical_address;
@@ -576,11 +581,12 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
if (mem_rover) {
+
/* Return the physical address */
- physical_address =
- ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF(mem_rover,
- table_ptr);
+ physical_address = (u32)
+ (ACPI_HI_RSDP_WINDOW_BASE +
+ ACPI_PTR_DIFF(mem_rover, table_ptr));
table_info->physical_address =
(acpi_physical_address) physical_address;
@@ -601,7 +607,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
if (physical_address > 0x400) {
/*
- * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of
+ * 1b) Search EBDA paragraphs (EBDA is required to be a minimum of
* 1_k length)
*/
mem_rover =
@@ -609,6 +615,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
(physical_address),
ACPI_EBDA_WINDOW_SIZE);
if (mem_rover) {
+
/* Return the physical address */
table_info->physical_address =
@@ -624,6 +631,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
(ACPI_HI_RSDP_WINDOW_BASE),
ACPI_HI_RSDP_WINDOW_SIZE);
if (mem_rover) {
+
/* Found it, return the physical address */
table_info->physical_address =
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 19f3ea48475..fba9c230a84 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -684,8 +684,7 @@ static void acpi_thermal_run(unsigned long data)
{
struct acpi_thermal *tz = (struct acpi_thermal *)data;
if (!tz->zombie)
- acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
- acpi_thermal_check, (void *)data);
+ acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data);
}
static void acpi_thermal_check(void *data)
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index 03b0044974c..7940fc1bd69 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -46,24 +46,6 @@
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utalloc")
-/* Local prototypes */
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation);
-
-static acpi_status
-acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
- acpi_size size,
- u8 alloc_type, u32 component, char *module, u32 line);
-
-static acpi_status
-acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
- u32 component, char *module, u32 line);
-
-static acpi_status
-acpi_ut_create_list(char *list_name,
- u16 object_size, struct acpi_memory_list **return_cache);
-#endif
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_create_caches
@@ -75,33 +57,23 @@ acpi_ut_create_list(char *list_name,
* DESCRIPTION: Create all local caches
*
******************************************************************************/
-
acpi_status acpi_ut_create_caches(void)
{
acpi_status status;
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-
- /* Memory allocation lists */
-
- status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
+ /* Object Caches, for frequently used objects */
status =
- acpi_ut_create_list("Acpi-Namespace",
- sizeof(struct acpi_namespace_node),
- &acpi_gbl_ns_node_list);
+ acpi_os_create_cache("Acpi-Namespace",
+ sizeof(struct acpi_namespace_node),
+ ACPI_MAX_NAMESPACE_CACHE_DEPTH,
+ &acpi_gbl_namespace_cache);
if (ACPI_FAILURE(status)) {
return (status);
}
-#endif
-
- /* Object Caches, for frequently used objects */
status =
- acpi_os_create_cache("acpi_state", sizeof(union acpi_generic_state),
+ acpi_os_create_cache("Acpi-State", sizeof(union acpi_generic_state),
ACPI_MAX_STATE_CACHE_DEPTH,
&acpi_gbl_state_cache);
if (ACPI_FAILURE(status)) {
@@ -109,7 +81,7 @@ acpi_status acpi_ut_create_caches(void)
}
status =
- acpi_os_create_cache("acpi_parse",
+ acpi_os_create_cache("Acpi-Parse",
sizeof(struct acpi_parse_obj_common),
ACPI_MAX_PARSE_CACHE_DEPTH,
&acpi_gbl_ps_node_cache);
@@ -118,7 +90,7 @@ acpi_status acpi_ut_create_caches(void)
}
status =
- acpi_os_create_cache("acpi_parse_ext",
+ acpi_os_create_cache("Acpi-ParseExt",
sizeof(struct acpi_parse_obj_named),
ACPI_MAX_EXTPARSE_CACHE_DEPTH,
&acpi_gbl_ps_node_ext_cache);
@@ -127,7 +99,7 @@ acpi_status acpi_ut_create_caches(void)
}
status =
- acpi_os_create_cache("acpi_operand",
+ acpi_os_create_cache("Acpi-Operand",
sizeof(union acpi_operand_object),
ACPI_MAX_OBJECT_CACHE_DEPTH,
&acpi_gbl_operand_cache);
@@ -135,6 +107,24 @@ acpi_status acpi_ut_create_caches(void)
return (status);
}
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+
+ /* Memory allocation lists */
+
+ status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ status =
+ acpi_ut_create_list("Acpi-Namespace",
+ sizeof(struct acpi_namespace_node),
+ &acpi_gbl_ns_node_list);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+#endif
+
return (AE_OK);
}
@@ -153,6 +143,9 @@ acpi_status acpi_ut_create_caches(void)
acpi_status acpi_ut_delete_caches(void)
{
+ (void)acpi_os_delete_cache(acpi_gbl_namespace_cache);
+ acpi_gbl_namespace_cache = NULL;
+
(void)acpi_os_delete_cache(acpi_gbl_state_cache);
acpi_gbl_state_cache = NULL;
@@ -165,6 +158,21 @@ acpi_status acpi_ut_delete_caches(void)
(void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache);
acpi_gbl_ps_node_ext_cache = NULL;
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+
+ /* Debug only - display leftover memory allocation, if any */
+
+ acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL);
+
+ /* Free memory lists */
+
+ acpi_os_free(acpi_gbl_global_list);
+ acpi_gbl_global_list = NULL;
+
+ acpi_os_free(acpi_gbl_ns_node_list);
+ acpi_gbl_ns_node_list = NULL;
+#endif
+
return (AE_OK);
}
@@ -252,7 +260,7 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
/* Allocate a new buffer with local interface to allow tracking */
- buffer->pointer = ACPI_MEM_CALLOCATE(required_length);
+ buffer->pointer = ACPI_ALLOCATE_ZEROED(required_length);
if (!buffer->pointer) {
return (AE_NO_MEMORY);
}
@@ -288,7 +296,7 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
*
* RETURN: Address of the allocated memory on success, NULL on failure.
*
- * DESCRIPTION: The subsystem's equivalent of malloc.
+ * DESCRIPTION: Subsystem equivalent of malloc.
*
******************************************************************************/
@@ -296,23 +304,23 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line)
{
void *allocation;
- ACPI_FUNCTION_TRACE_U32("ut_allocate", size);
+ ACPI_FUNCTION_TRACE_U32(ut_allocate, size);
/* Check for an inadvertent size of zero bytes */
if (!size) {
- ACPI_ERROR((module, line,
- "ut_allocate: Attempt to allocate zero bytes, allocating 1 byte"));
+ ACPI_WARNING((module, line,
+ "Attempt to allocate zero bytes, allocating 1 byte"));
size = 1;
}
allocation = acpi_os_allocate(size);
if (!allocation) {
+
/* Report allocation error */
- ACPI_ERROR((module, line,
- "ut_allocate: Could not allocate size %X",
- (u32) size));
+ ACPI_WARNING((module, line,
+ "Could not allocate size %X", (u32) size));
return_PTR(NULL);
}
@@ -322,7 +330,7 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line)
/*******************************************************************************
*
- * FUNCTION: acpi_ut_callocate
+ * FUNCTION: acpi_ut_allocate_zeroed
*
* PARAMETERS: Size - Size of the allocation
* Component - Component type of caller
@@ -331,542 +339,24 @@ void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line)
*
* RETURN: Address of the allocated memory on success, NULL on failure.
*
- * DESCRIPTION: Subsystem equivalent of calloc.
+ * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory.
*
******************************************************************************/
-void *acpi_ut_callocate(acpi_size size, u32 component, char *module, u32 line)
+void *acpi_ut_allocate_zeroed(acpi_size size,
+ u32 component, char *module, u32 line)
{
void *allocation;
- ACPI_FUNCTION_TRACE_U32("ut_callocate", size);
-
- /* Check for an inadvertent size of zero bytes */
-
- if (!size) {
- ACPI_ERROR((module, line,
- "Attempt to allocate zero bytes, allocating 1 byte"));
- size = 1;
- }
-
- allocation = acpi_os_allocate(size);
- if (!allocation) {
- /* Report allocation error */
-
- ACPI_ERROR((module, line,
- "Could not allocate size %X", (u32) size));
- return_PTR(NULL);
- }
-
- /* Clear the memory block */
-
- ACPI_MEMSET(allocation, 0, size);
- return_PTR(allocation);
-}
-
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-/*
- * These procedures are used for tracking memory leaks in the subsystem, and
- * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
- *
- * Each memory allocation is tracked via a doubly linked list. Each
- * element contains the caller's component, module name, function name, and
- * line number. acpi_ut_allocate and acpi_ut_callocate call
- * acpi_ut_track_allocation to add an element to the list; deletion
- * occurs in the body of acpi_ut_free.
- */
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_create_list
- *
- * PARAMETERS: cache_name - Ascii name for the cache
- * object_size - Size of each cached object
- * return_cache - Where the new cache object is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Create a local memory list for tracking purposed
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_create_list(char *list_name,
- u16 object_size, struct acpi_memory_list **return_cache)
-{
- struct acpi_memory_list *cache;
-
- cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
- if (!cache) {
- return (AE_NO_MEMORY);
- }
-
- ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
-
- cache->list_name = list_name;
- cache->object_size = object_size;
-
- *return_cache = cache;
- return (AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_allocate_and_track
- *
- * PARAMETERS: Size - Size of the allocation
- * Component - Component type of caller
- * Module - Source file name of caller
- * Line - Line number of caller
- *
- * RETURN: Address of the allocated memory on success, NULL on failure.
- *
- * DESCRIPTION: The subsystem's equivalent of malloc.
- *
- ******************************************************************************/
-
-void *acpi_ut_allocate_and_track(acpi_size size,
- u32 component, char *module, u32 line)
-{
- struct acpi_debug_mem_block *allocation;
- acpi_status status;
-
- allocation =
- acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header),
- component, module, line);
- if (!allocation) {
- return (NULL);
- }
-
- status = acpi_ut_track_allocation(allocation, size,
- ACPI_MEM_MALLOC, component, module,
- line);
- if (ACPI_FAILURE(status)) {
- acpi_os_free(allocation);
- return (NULL);
- }
-
- acpi_gbl_global_list->total_allocated++;
- acpi_gbl_global_list->current_total_size += (u32) size;
-
- return ((void *)&allocation->user_space);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_callocate_and_track
- *
- * PARAMETERS: Size - Size of the allocation
- * Component - Component type of caller
- * Module - Source file name of caller
- * Line - Line number of caller
- *
- * RETURN: Address of the allocated memory on success, NULL on failure.
- *
- * DESCRIPTION: Subsystem equivalent of calloc.
- *
- ******************************************************************************/
-
-void *acpi_ut_callocate_and_track(acpi_size size,
- u32 component, char *module, u32 line)
-{
- struct acpi_debug_mem_block *allocation;
- acpi_status status;
-
- allocation =
- acpi_ut_callocate(size + sizeof(struct acpi_debug_mem_header),
- component, module, line);
- if (!allocation) {
- /* Report allocation error */
-
- ACPI_ERROR((module, line,
- "Could not allocate size %X", (u32) size));
- return (NULL);
- }
-
- status = acpi_ut_track_allocation(allocation, size,
- ACPI_MEM_CALLOC, component, module,
- line);
- if (ACPI_FAILURE(status)) {
- acpi_os_free(allocation);
- return (NULL);
- }
-
- acpi_gbl_global_list->total_allocated++;
- acpi_gbl_global_list->current_total_size += (u32) size;
-
- return ((void *)&allocation->user_space);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_free_and_track
- *
- * PARAMETERS: Allocation - Address of the memory to deallocate
- * Component - Component type of caller
- * Module - Source file name of caller
- * Line - Line number of caller
- *
- * RETURN: None
- *
- * DESCRIPTION: Frees the memory at Allocation
- *
- ******************************************************************************/
-
-void
-acpi_ut_free_and_track(void *allocation, u32 component, char *module, u32 line)
-{
- struct acpi_debug_mem_block *debug_block;
- acpi_status status;
-
- ACPI_FUNCTION_TRACE_PTR("ut_free", allocation);
-
- if (NULL == allocation) {
- ACPI_ERROR((module, line, "Attempt to delete a NULL address"));
-
- return_VOID;
- }
-
- debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block,
- (((char *)allocation) -
- sizeof(struct acpi_debug_mem_header)));
-
- acpi_gbl_global_list->total_freed++;
- acpi_gbl_global_list->current_total_size -= debug_block->size;
-
- status = acpi_ut_remove_allocation(debug_block,
- component, module, line);
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
- }
-
- acpi_os_free(debug_block);
- ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
- return_VOID;
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_find_allocation
- *
- * PARAMETERS: Allocation - Address of allocated memory
- *
- * RETURN: A list element if found; NULL otherwise.
- *
- * DESCRIPTION: Searches for an element in the global allocation tracking list.
- *
- ******************************************************************************/
-
-static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation)
-{
- struct acpi_debug_mem_block *element;
-
ACPI_FUNCTION_ENTRY();
- element = acpi_gbl_global_list->list_head;
-
- /* Search for the address. */
-
- while (element) {
- if (element == allocation) {
- return (element);
- }
-
- element = element->next;
- }
-
- return (NULL);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_track_allocation
- *
- * PARAMETERS: Allocation - Address of allocated memory
- * Size - Size of the allocation
- * alloc_type - MEM_MALLOC or MEM_CALLOC
- * Component - Component type of caller
- * Module - Source file name of caller
- * Line - Line number of caller
- *
- * RETURN: None.
- *
- * DESCRIPTION: Inserts an element into the global allocation tracking list.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
- acpi_size size,
- u8 alloc_type, u32 component, char *module, u32 line)
-{
- struct acpi_memory_list *mem_list;
- struct acpi_debug_mem_block *element;
- acpi_status status = AE_OK;
-
- ACPI_FUNCTION_TRACE_PTR("ut_track_allocation", allocation);
-
- mem_list = acpi_gbl_global_list;
- status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /*
- * Search list for this address to make sure it is not already on the list.
- * This will catch several kinds of problems.
- */
- element = acpi_ut_find_allocation(allocation);
- if (element) {
- ACPI_ERROR((AE_INFO,
- "ut_track_allocation: Allocation already present in list! (%p)",
- allocation));
-
- ACPI_ERROR((AE_INFO, "Element %p Address %p",
- element, allocation));
-
- goto unlock_and_exit;
- }
-
- /* Fill in the instance data. */
-
- allocation->size = (u32) size;
- allocation->alloc_type = alloc_type;
- allocation->component = component;
- allocation->line = line;
-
- ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME);
- allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0;
-
- /* Insert at list head */
-
- if (mem_list->list_head) {
- ((struct acpi_debug_mem_block *)(mem_list->list_head))->
- previous = allocation;
- }
-
- allocation->next = mem_list->list_head;
- allocation->previous = NULL;
-
- mem_list->list_head = allocation;
-
- unlock_and_exit:
- status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
- return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_remove_allocation
- *
- * PARAMETERS: Allocation - Address of allocated memory
- * Component - Component type of caller
- * Module - Source file name of caller
- * Line - Line number of caller
- *
- * RETURN:
- *
- * DESCRIPTION: Deletes an element from the global allocation tracking list.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
- u32 component, char *module, u32 line)
-{
- struct acpi_memory_list *mem_list;
- acpi_status status;
-
- ACPI_FUNCTION_TRACE("ut_remove_allocation");
-
- mem_list = acpi_gbl_global_list;
- if (NULL == mem_list->list_head) {
- /* No allocations! */
-
- ACPI_ERROR((module, line,
- "Empty allocation list, nothing to free!"));
-
- return_ACPI_STATUS(AE_OK);
- }
-
- status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /* Unlink */
-
- if (allocation->previous) {
- (allocation->previous)->next = allocation->next;
- } else {
- mem_list->list_head = allocation->next;
- }
-
- if (allocation->next) {
- (allocation->next)->previous = allocation->previous;
- }
-
- /* Mark the segment as deleted */
-
- ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size);
-
- ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n",
- allocation->size));
+ allocation = acpi_ut_allocate(size, component, module, line);
+ if (allocation) {
- status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
- return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_dump_allocation_info
- *
- * PARAMETERS:
- *
- * RETURN: None
- *
- * DESCRIPTION: Print some info about the outstanding allocations.
- *
- ******************************************************************************/
+ /* Clear the memory block */
-#ifdef ACPI_FUTURE_USAGE
-void acpi_ut_dump_allocation_info(void)
-{
-/*
- struct acpi_memory_list *mem_list;
-*/
-
- ACPI_FUNCTION_TRACE("ut_dump_allocation_info");
-
-/*
- ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
- ("%30s: %4d (%3d Kb)\n", "Current allocations",
- mem_list->current_count,
- ROUND_UP_TO_1K (mem_list->current_size)));
-
- ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
- ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
- mem_list->max_concurrent_count,
- ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
-
- ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
- ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
- running_object_count,
- ROUND_UP_TO_1K (running_object_size)));
-
- ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
- ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
- running_alloc_count,
- ROUND_UP_TO_1K (running_alloc_size)));
-
- ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
- ("%30s: %4d (%3d Kb)\n", "Current Nodes",
- acpi_gbl_current_node_count,
- ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
-
- ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
- ("%30s: %4d (%3d Kb)\n", "Max Nodes",
- acpi_gbl_max_concurrent_node_count,
- ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
- sizeof (struct acpi_namespace_node)))));
-*/
- return_VOID;
-}
-#endif /* ACPI_FUTURE_USAGE */
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_dump_allocations
- *
- * PARAMETERS: Component - Component(s) to dump info for.
- * Module - Module to dump info for. NULL means all.
- *
- * RETURN: None
- *
- * DESCRIPTION: Print a list of all outstanding allocations.
- *
- ******************************************************************************/
-
-void acpi_ut_dump_allocations(u32 component, char *module)
-{
- struct acpi_debug_mem_block *element;
- union acpi_descriptor *descriptor;
- u32 num_outstanding = 0;
-
- ACPI_FUNCTION_TRACE("ut_dump_allocations");
-
- /*
- * Walk the allocation list.
- */
- if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
- return;
+ ACPI_MEMSET(allocation, 0, size);
}
- element = acpi_gbl_global_list->list_head;
- while (element) {
- if ((element->component & component) &&
- ((module == NULL)
- || (0 == ACPI_STRCMP(module, element->module)))) {
- /* Ignore allocated objects that are in a cache */
-
- descriptor =
- ACPI_CAST_PTR(union acpi_descriptor,
- &element->user_space);
- if (descriptor->descriptor_id != ACPI_DESC_TYPE_CACHED) {
- acpi_os_printf("%p Len %04X %9.9s-%d [%s] ",
- descriptor, element->size,
- element->module, element->line,
- acpi_ut_get_descriptor_name
- (descriptor));
-
- /* Most of the elements will be Operand objects. */
-
- switch (ACPI_GET_DESCRIPTOR_TYPE(descriptor)) {
- case ACPI_DESC_TYPE_OPERAND:
- acpi_os_printf("%12.12s R%hd",
- acpi_ut_get_type_name
- (descriptor->object.
- common.type),
- descriptor->object.
- common.reference_count);
- break;
-
- case ACPI_DESC_TYPE_PARSER:
- acpi_os_printf("aml_opcode %04hX",
- descriptor->op.asl.
- aml_opcode);
- break;
-
- case ACPI_DESC_TYPE_NAMED:
- acpi_os_printf("%4.4s",
- acpi_ut_get_node_name
- (&descriptor->node));
- break;
-
- default:
- break;
- }
-
- acpi_os_printf("\n");
- num_outstanding++;
- }
- }
- element = element->next;
- }
-
- (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
-
- /* Print summary */
-
- if (!num_outstanding) {
- ACPI_INFO((AE_INFO, "No outstanding allocations"));
- } else {
- ACPI_ERROR((AE_INFO,
- "%d(%X) Outstanding allocations",
- num_outstanding, num_outstanding));
- }
-
- return_VOID;
+ return (allocation);
}
-
-#endif /* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */
diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c
index 2177cb1ef2c..56270a30718 100644
--- a/drivers/acpi/utilities/utcache.c
+++ b/drivers/acpi/utilities/utcache.c
@@ -118,13 +118,14 @@ acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
/* Walk the list of objects in this cache */
while (cache->list_head) {
+
/* Delete and unlink one cached state object */
next = *(ACPI_CAST_INDIRECT_PTR(char,
&(((char *)cache->
list_head)[cache->
link_offset])));
- ACPI_MEM_FREE(cache->list_head);
+ ACPI_FREE(cache->list_head);
cache->list_head = next;
cache->current_depth--;
@@ -193,7 +194,7 @@ acpi_os_release_object(struct acpi_memory_list * cache, void *object)
/* If cache is full, just free this object */
if (cache->current_depth >= cache->max_depth) {
- ACPI_MEM_FREE(object);
+ ACPI_FREE(object);
ACPI_MEM_TRACKING(cache->total_freed++);
}
@@ -243,7 +244,7 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache)
acpi_status status;
void *object;
- ACPI_FUNCTION_NAME("os_acquire_object");
+ ACPI_FUNCTION_NAME(os_acquire_object);
if (!cache) {
return (NULL);
@@ -259,6 +260,7 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache)
/* Check the cache first */
if (cache->list_head) {
+
/* There is an object available, use it */
object = cache->list_head;
@@ -270,9 +272,9 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache)
cache->current_depth--;
ACPI_MEM_TRACKING(cache->hits++);
- ACPI_MEM_TRACKING(ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Object %p from %s cache\n",
- object, cache->list_name)));
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Object %p from %s cache\n", object,
+ cache->list_name));
status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
if (ACPI_FAILURE(status)) {
@@ -287,14 +289,14 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache)
ACPI_MEM_TRACKING(cache->total_allocated++);
- /* Avoid deadlock with ACPI_MEM_CALLOCATE */
+ /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
if (ACPI_FAILURE(status)) {
return (NULL);
}
- object = ACPI_MEM_CALLOCATE(cache->object_size);
+ object = ACPI_ALLOCATE_ZEROED(cache->object_size);
if (!object) {
return (NULL);
}
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index df2d32096b7..5e1a80d1bc3 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -109,7 +109,7 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ut_copy_isimple_to_esimple");
+ ACPI_FUNCTION_TRACE(ut_copy_isimple_to_esimple);
*buffer_space_used = 0;
@@ -325,7 +325,7 @@ acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
acpi_status status;
struct acpi_pkg_info info;
- ACPI_FUNCTION_TRACE("ut_copy_ipackage_to_epackage");
+ ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_epackage);
/*
* First package at head of the buffer
@@ -383,7 +383,7 @@ acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object,
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ut_copy_iobject_to_eobject");
+ ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject);
if (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE) {
/*
@@ -442,7 +442,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
{
union acpi_operand_object *internal_object;
- ACPI_FUNCTION_TRACE("ut_copy_esimple_to_isimple");
+ ACPI_FUNCTION_TRACE(ut_copy_esimple_to_isimple);
/*
* Simple types supported are: String, Buffer, Integer
@@ -472,8 +472,8 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
case ACPI_TYPE_STRING:
internal_object->string.pointer =
- ACPI_MEM_CALLOCATE((acpi_size) external_object->string.
- length + 1);
+ ACPI_ALLOCATE_ZEROED((acpi_size) external_object->string.
+ length + 1);
if (!internal_object->string.pointer) {
goto error_exit;
}
@@ -488,7 +488,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
case ACPI_TYPE_BUFFER:
internal_object->buffer.pointer =
- ACPI_MEM_CALLOCATE(external_object->buffer.length);
+ ACPI_ALLOCATE_ZEROED(external_object->buffer.length);
if (!internal_object->buffer.pointer) {
goto error_exit;
}
@@ -552,7 +552,7 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_operand_object *internal_object,
union acpi_operand_object *this_internal_obj;
union acpi_object *this_external_obj;
- ACPI_FUNCTION_TRACE("ut_copy_epackage_to_ipackage");
+ ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
/*
* First package at head of the buffer
@@ -600,7 +600,7 @@ acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
{
acpi_status status;
- ACPI_FUNCTION_TRACE("ut_copy_eobject_to_iobject");
+ ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject);
if (external_object->type == ACPI_TYPE_PACKAGE) {
/*
@@ -676,7 +676,7 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
if ((source_desc->buffer.pointer) &&
(source_desc->buffer.length)) {
dest_desc->buffer.pointer =
- ACPI_MEM_ALLOCATE(source_desc->buffer.length);
+ ACPI_ALLOCATE(source_desc->buffer.length);
if (!dest_desc->buffer.pointer) {
return (AE_NO_MEMORY);
}
@@ -697,8 +697,8 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
*/
if (source_desc->string.pointer) {
dest_desc->string.pointer =
- ACPI_MEM_ALLOCATE((acpi_size) source_desc->string.
- length + 1);
+ ACPI_ALLOCATE((acpi_size) source_desc->string.
+ length + 1);
if (!dest_desc->string.pointer) {
return (AE_NO_MEMORY);
}
@@ -805,9 +805,7 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type,
/*
* Create the object array
*/
- target_object->package.elements =
- ACPI_MEM_CALLOCATE(((acpi_size) source_object->package.
- count + 1) * sizeof(void *));
+ target_object->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package.count + 1) * sizeof(void *));
if (!target_object->package.elements) {
status = AE_NO_MEMORY;
goto error_exit;
@@ -856,7 +854,7 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ut_copy_ipackage_to_ipackage");
+ ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage);
dest_obj->common.type = ACPI_GET_OBJECT_TYPE(source_obj);
dest_obj->common.flags = source_obj->common.flags;
@@ -865,10 +863,10 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
/*
* Create the object array and walk the source package tree
*/
- dest_obj->package.elements = ACPI_MEM_CALLOCATE(((acpi_size)
- source_obj->package.
- count +
- 1) * sizeof(void *));
+ dest_obj->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
+ source_obj->package.
+ count +
+ 1) * sizeof(void *));
if (!dest_obj->package.elements) {
ACPI_ERROR((AE_INFO, "Package allocation failure"));
return_ACPI_STATUS(AE_NO_MEMORY);
@@ -882,6 +880,7 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
acpi_ut_copy_ielement_to_ielement,
walk_state);
if (ACPI_FAILURE(status)) {
+
/* On failure, delete the destination package object */
acpi_ut_remove_reference(dest_obj);
@@ -911,7 +910,7 @@ acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc,
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("ut_copy_iobject_to_iobject");
+ ACPI_FUNCTION_TRACE(ut_copy_iobject_to_iobject);
/* Create the top level object */
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
index 35f3d581e03..5ec1cfcc611 100644
--- a/drivers/acpi/utilities/utdebug.c
+++ b/drivers/acpi/utilities/utdebug.c
@@ -41,8 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#define _COMPONENT ACPI_UTILITIES
@@ -123,12 +121,14 @@ static const char *acpi_ut_trim_function_name(const char *function_name)
/* All Function names are longer than 4 chars, check is safe */
if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_MIXED) {
+
/* This is the case where the original source has not been modified */
return (function_name + 4);
}
if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_LOWER) {
+
/* This is the case where the source has been 'linuxized' */
return (function_name + 5);
@@ -162,7 +162,7 @@ acpi_ut_debug_print(u32 requested_debug_level,
const char *function_name,
char *module_name, u32 component_id, char *format, ...)
{
- u32 thread_id;
+ acpi_thread_id thread_id;
va_list args;
/*
@@ -177,7 +177,6 @@ acpi_ut_debug_print(u32 requested_debug_level,
* Thread tracking and context switch notification
*/
thread_id = acpi_os_get_thread_id();
-
if (thread_id != acpi_gbl_prev_thread_id) {
if (ACPI_LV_THREADS & acpi_dbg_level) {
acpi_os_printf
@@ -206,7 +205,7 @@ acpi_ut_debug_print(u32 requested_debug_level,
acpi_os_vprintf(format, args);
}
-EXPORT_SYMBOL(acpi_ut_debug_print);
+ACPI_EXPORT_SYMBOL(acpi_ut_debug_print)
/*******************************************************************************
*
@@ -226,7 +225,6 @@ EXPORT_SYMBOL(acpi_ut_debug_print);
* debug_print so that the same macros can be used.
*
******************************************************************************/
-
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_debug_print_raw(u32 requested_debug_level,
u32 line_number,
@@ -244,7 +242,7 @@ acpi_ut_debug_print_raw(u32 requested_debug_level,
acpi_os_vprintf(format, args);
}
-EXPORT_SYMBOL(acpi_ut_debug_print_raw);
+ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw)
/*******************************************************************************
*
@@ -261,7 +259,6 @@ EXPORT_SYMBOL(acpi_ut_debug_print_raw);
* set in debug_level
*
******************************************************************************/
-
void
acpi_ut_trace(u32 line_number,
const char *function_name, char *module_name, u32 component_id)
@@ -275,7 +272,7 @@ acpi_ut_trace(u32 line_number,
component_id, "%s\n", acpi_gbl_fn_entry_str);
}
-EXPORT_SYMBOL(acpi_ut_trace);
+ACPI_EXPORT_SYMBOL(acpi_ut_trace)
/*******************************************************************************
*
@@ -293,7 +290,6 @@ EXPORT_SYMBOL(acpi_ut_trace);
* set in debug_level
*
******************************************************************************/
-
void
acpi_ut_trace_ptr(u32 line_number,
const char *function_name,
@@ -400,7 +396,7 @@ acpi_ut_exit(u32 line_number,
acpi_gbl_nesting_level--;
}
-EXPORT_SYMBOL(acpi_ut_exit);
+ACPI_EXPORT_SYMBOL(acpi_ut_exit)
/*******************************************************************************
*
@@ -418,7 +414,6 @@ EXPORT_SYMBOL(acpi_ut_exit);
* set in debug_level. Prints exit status also.
*
******************************************************************************/
-
void
acpi_ut_status_exit(u32 line_number,
const char *function_name,
@@ -442,7 +437,7 @@ acpi_ut_status_exit(u32 line_number,
acpi_gbl_nesting_level--;
}
-EXPORT_SYMBOL(acpi_ut_status_exit);
+ACPI_EXPORT_SYMBOL(acpi_ut_status_exit)
/*******************************************************************************
*
@@ -460,7 +455,6 @@ EXPORT_SYMBOL(acpi_ut_status_exit);
* set in debug_level. Prints exit value also.
*
******************************************************************************/
-
void
acpi_ut_value_exit(u32 line_number,
const char *function_name,
@@ -475,7 +469,7 @@ acpi_ut_value_exit(u32 line_number,
acpi_gbl_nesting_level--;
}
-EXPORT_SYMBOL(acpi_ut_value_exit);
+ACPI_EXPORT_SYMBOL(acpi_ut_value_exit)
/*******************************************************************************
*
@@ -493,7 +487,6 @@ EXPORT_SYMBOL(acpi_ut_value_exit);
* set in debug_level. Prints exit value also.
*
******************************************************************************/
-
void
acpi_ut_ptr_exit(u32 line_number,
const char *function_name,
@@ -524,20 +517,13 @@ acpi_ut_ptr_exit(u32 line_number,
*
******************************************************************************/
-void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
+void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
{
acpi_native_uint i = 0;
acpi_native_uint j;
u32 temp32;
u8 buf_char;
- /* Only dump the buffer if tracing is enabled */
-
- if (!((ACPI_LV_TABLES & acpi_dbg_level) &&
- (component_id & acpi_dbg_layer))) {
- return;
- }
-
if ((count < 4) || (count & 0x01)) {
display = DB_BYTE_DISPLAY;
}
@@ -545,6 +531,7 @@ void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
/* Nasty little dump buffer routine! */
while (i < count) {
+
/* Print current offset */
acpi_os_printf("%6.4X: ", (u32) i);
@@ -553,6 +540,7 @@ void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
for (j = 0; j < 16;) {
if (i + j >= count) {
+
/* Dump fill spaces */
acpi_os_printf("%*s", ((display * 2) + 1), " ");
@@ -561,6 +549,7 @@ void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
}
switch (display) {
+ case DB_BYTE_DISPLAY:
default: /* Default is BYTE display */
acpi_os_printf("%02X ", buffer[i + j]);
@@ -618,3 +607,31 @@ void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
return;
}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_dump_buffer
+ *
+ * PARAMETERS: Buffer - Buffer to dump
+ * Count - Amount to dump, in bytes
+ * Display - BYTE, WORD, DWORD, or QWORD display
+ * component_iD - Caller's component ID
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Generic dump buffer in both hex and ascii.
+ *
+ ******************************************************************************/
+
+void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
+{
+
+ /* Only dump the buffer if tracing is enabled */
+
+ if (!((ACPI_LV_TABLES & acpi_dbg_level) &&
+ (component_id & acpi_dbg_layer))) {
+ return;
+ }
+
+ acpi_ut_dump_buffer2(buffer, count, display);
+}
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index 1db9695b002..67b9f325c6f 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -76,7 +76,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
union acpi_operand_object *second_desc;
union acpi_operand_object *next_desc;
- ACPI_FUNCTION_TRACE_PTR("ut_delete_internal_obj", object);
+ ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object);
if (!object) {
return_VOID;
@@ -96,6 +96,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
/* Free the actual string buffer */
if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) {
+
/* But only if it is NOT a pointer into an ACPI table */
obj_pointer = object->string.pointer;
@@ -111,6 +112,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
/* Free the actual buffer */
if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) {
+
/* But only if it is NOT a pointer into an ACPI table */
obj_pointer = object->buffer.pointer;
@@ -198,11 +200,22 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
*/
handler_desc = object->region.handler;
if (handler_desc) {
- if (handler_desc->address_space.
- hflags &
+ if (handler_desc->address_space.handler_flags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
- obj_pointer =
- second_desc->extra.region_context;
+
+ /* Deactivate region and free region context */
+
+ if (handler_desc->address_space.setup) {
+ (void)handler_desc->
+ address_space.setup(object,
+ ACPI_REGION_DEACTIVATE,
+ handler_desc->
+ address_space.
+ context,
+ &second_desc->
+ extra.
+ region_context);
+ }
}
acpi_ut_remove_reference(handler_desc);
@@ -234,7 +247,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
if (obj_pointer) {
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
"Deleting Object Subptr %p\n", obj_pointer));
- ACPI_MEM_FREE(obj_pointer);
+ ACPI_FREE(obj_pointer);
}
/* Now the object can be safely deleted */
@@ -263,7 +276,7 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list)
{
union acpi_operand_object **internal_obj;
- ACPI_FUNCTION_TRACE("ut_delete_internal_object_list");
+ ACPI_FUNCTION_TRACE(ut_delete_internal_object_list);
/* Walk the null-terminated internal list */
@@ -273,7 +286,7 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list)
/* Free the combined parameter pointer list and object array */
- ACPI_MEM_FREE(obj_list);
+ ACPI_FREE(obj_list);
return_VOID;
}
@@ -296,7 +309,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
u16 count;
u16 new_count;
- ACPI_FUNCTION_NAME("ut_update_ref_count");
+ ACPI_FUNCTION_NAME(ut_update_ref_count);
if (!object) {
return;
@@ -306,11 +319,9 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
new_count = count;
/*
- * Perform the reference count action
- * (increment, decrement, or force delete)
+ * Perform the reference count action (increment, decrement, force delete)
*/
switch (action) {
-
case REF_INCREMENT:
new_count++;
@@ -347,7 +358,6 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
if (new_count == 0) {
acpi_ut_delete_internal_obj(object);
}
-
break;
case REF_FORCE_DELETE:
@@ -372,13 +382,10 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
* (A deleted object will have a huge reference count)
*/
if (count > ACPI_MAX_REFERENCE_COUNT) {
-
ACPI_WARNING((AE_INFO,
- "Large Reference Count (%X) in object %p",
- count, object));
+ "Large Reference Count (%X) in object %p", count,
+ object));
}
-
- return;
}
/*******************************************************************************
@@ -404,7 +411,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
******************************************************************************/
acpi_status
-acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action)
+acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
{
acpi_status status = AE_OK;
union acpi_generic_state *state_list = NULL;
@@ -412,9 +419,10 @@ acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action)
union acpi_generic_state *state;
acpi_native_uint i;
- ACPI_FUNCTION_TRACE_PTR("ut_update_object_reference", object);
+ ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object);
while (object) {
+
/* Make sure that this isn't a namespace handle */
if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) {
@@ -507,11 +515,11 @@ acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action)
case ACPI_TYPE_REGION:
default:
- break; /* No subobjects */
+ break; /* No subobjects for all other types */
}
/*
- * Now we can update the count in the main object. This can only
+ * Now we can update the count in the main object. This can only
* happen after we update the sub-objects in case this causes the
* main object to be deleted.
*/
@@ -556,7 +564,7 @@ acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action)
void acpi_ut_add_reference(union acpi_operand_object *object)
{
- ACPI_FUNCTION_TRACE_PTR("ut_add_reference", object);
+ ACPI_FUNCTION_TRACE_PTR(ut_add_reference, object);
/* Ensure that we have a valid object */
@@ -589,11 +597,11 @@ void acpi_ut_add_reference(union acpi_operand_object *object)
void acpi_ut_remove_reference(union acpi_operand_object *object)
{
- ACPI_FUNCTION_TRACE_PTR("ut_remove_reference", object);
+ ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object);
/*
- * Allow a NULL pointer to be passed in, just ignore it. This saves
- * each caller from having to check. Also, ignore NS nodes.
+ * Allow a NULL pointer to be passed in, just ignore it. This saves
+ * each caller from having to check. Also, ignore NS nodes.
*
*/
if (!object ||
@@ -613,7 +621,7 @@ void acpi_ut_remove_reference(union acpi_operand_object *object)
/*
* Decrement the reference count, and only actually delete the object
- * if the reference count becomes 0. (Must also decrement the ref count
+ * if the reference count becomes 0. (Must also decrement the ref count
* of all subobjects!)
*/
(void)acpi_ut_update_object_reference(object, REF_DECREMENT);
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
index 106cc97cb4a..d6d7121583c 100644
--- a/drivers/acpi/utilities/uteval.c
+++ b/drivers/acpi/utilities/uteval.c
@@ -56,6 +56,34 @@ static acpi_status
acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
struct acpi_compatible_id *one_cid);
+/*
+ * Strings supported by the _OSI predefined (internal) method.
+ */
+static const char *acpi_interfaces_supported[] = {
+ /* Operating System Vendor Strings */
+
+ "Linux",
+ "Windows 2000",
+ "Windows 2001",
+ "Windows 2001 SP0",
+ "Windows 2001 SP1",
+ "Windows 2001 SP2",
+ "Windows 2001 SP3",
+ "Windows 2001 SP4",
+ "Windows 2001.1",
+ "Windows 2001.1 SP1", /* Added 03/2006 */
+ "Windows 2006", /* Added 03/2006 */
+
+ /* Feature Group Strings */
+
+ "Extended Address Space Descriptor"
+ /*
+ * All "optional" feature group strings (features that are implemented
+ * by the host) should be implemented in the host version of
+ * acpi_os_validate_interface and should not be added here.
+ */
+};
+
/*******************************************************************************
*
* FUNCTION: acpi_ut_osi_implementation
@@ -64,18 +92,18 @@ acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
*
* RETURN: Status
*
- * DESCRIPTION: Implementation of _OSI predefined control method
- * Supported = _OSI (String)
+ * DESCRIPTION: Implementation of the _OSI predefined control method
*
******************************************************************************/
acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
{
+ acpi_status status;
union acpi_operand_object *string_desc;
union acpi_operand_object *return_desc;
acpi_native_uint i;
- ACPI_FUNCTION_TRACE("ut_osi_implementation");
+ ACPI_FUNCTION_TRACE(ut_osi_implementation);
/* Validate the string input argument */
@@ -84,28 +112,47 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
return_ACPI_STATUS(AE_TYPE);
}
- /* Create a return object (Default value = 0) */
+ /* Create a return object */
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
- /* Compare input string to table of supported strings */
+ /* Default return value is SUPPORTED */
+
+ return_desc->integer.value = ACPI_UINT32_MAX;
+ walk_state->return_desc = return_desc;
+
+ /* Compare input string to static table of supported interfaces */
- for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) {
- if (!ACPI_STRCMP(string_desc->string.pointer,
- ACPI_CAST_PTR(char,
- acpi_gbl_valid_osi_strings[i])))
- {
- /* This string is supported */
+ for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
+ if (!ACPI_STRCMP
+ (string_desc->string.pointer,
+ acpi_interfaces_supported[i])) {
- return_desc->integer.value = 0xFFFFFFFF;
- break;
+ /* The interface is supported */
+
+ return_ACPI_STATUS(AE_CTRL_TERMINATE);
}
}
- walk_state->return_desc = return_desc;
+ /*
+ * Did not match the string in the static table, call the host OSL to
+ * check for a match with one of the optional strings (such as
+ * "Module Device", "3.0 Thermal Model", etc.)
+ */
+ status = acpi_os_validate_interface(string_desc->string.pointer);
+ if (ACPI_SUCCESS(status)) {
+
+ /* The interface is supported */
+
+ return_ACPI_STATUS(AE_CTRL_TERMINATE);
+ }
+
+ /* The interface is not supported */
+
+ return_desc->integer.value = 0;
return_ACPI_STATUS(AE_CTRL_TERMINATE);
}
@@ -134,19 +181,26 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
u32 expected_return_btypes,
union acpi_operand_object **return_desc)
{
- struct acpi_parameter_info info;
+ struct acpi_evaluate_info *info;
acpi_status status;
u32 return_btype;
- ACPI_FUNCTION_TRACE("ut_evaluate_object");
+ ACPI_FUNCTION_TRACE(ut_evaluate_object);
- info.node = prefix_node;
- info.parameters = NULL;
- info.parameter_type = ACPI_PARAM_ARGS;
+ /* Allocate the evaluation information block */
+
+ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+ if (!info) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ info->prefix_node = prefix_node;
+ info->pathname = path;
+ info->parameter_type = ACPI_PARAM_ARGS;
/* Evaluate the object/method */
- status = acpi_ns_evaluate_relative(path, &info);
+ status = acpi_ns_evaluate(info);
if (ACPI_FAILURE(status)) {
if (status == AE_NOT_FOUND) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -158,25 +212,25 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
prefix_node, path, status);
}
- return_ACPI_STATUS(status);
+ goto cleanup;
}
/* Did we get a return object? */
- if (!info.return_object) {
+ if (!info->return_object) {
if (expected_return_btypes) {
ACPI_ERROR_METHOD("No object was returned from",
prefix_node, path, AE_NOT_EXIST);
- return_ACPI_STATUS(AE_NOT_EXIST);
+ status = AE_NOT_EXIST;
}
- return_ACPI_STATUS(AE_OK);
+ goto cleanup;
}
/* Map the return object type to the bitmapped type */
- switch (ACPI_GET_OBJECT_TYPE(info.return_object)) {
+ switch (ACPI_GET_OBJECT_TYPE(info->return_object)) {
case ACPI_TYPE_INTEGER:
return_btype = ACPI_BTYPE_INTEGER;
break;
@@ -204,8 +258,8 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
* happen frequently if the "implicit return" feature is enabled.
* Just delete the return object and return AE_OK.
*/
- acpi_ut_remove_reference(info.return_object);
- return_ACPI_STATUS(AE_OK);
+ acpi_ut_remove_reference(info->return_object);
+ goto cleanup;
}
/* Is the return object one of the expected types? */
@@ -217,19 +271,23 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
ACPI_ERROR((AE_INFO,
"Type returned from %s was incorrect: %s, expected Btypes: %X",
path,
- acpi_ut_get_object_type_name(info.return_object),
+ acpi_ut_get_object_type_name(info->return_object),
expected_return_btypes));
/* On error exit, we must delete the return object */
- acpi_ut_remove_reference(info.return_object);
- return_ACPI_STATUS(AE_TYPE);
+ acpi_ut_remove_reference(info->return_object);
+ status = AE_TYPE;
+ goto cleanup;
}
/* Object type is OK, return it */
- *return_desc = info.return_object;
- return_ACPI_STATUS(AE_OK);
+ *return_desc = info->return_object;
+
+ cleanup:
+ ACPI_FREE(info);
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -257,7 +315,7 @@ acpi_ut_evaluate_numeric_object(char *object_name,
union acpi_operand_object *obj_desc;
acpi_status status;
- ACPI_FUNCTION_TRACE("ut_evaluate_numeric_object");
+ ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object);
status = acpi_ut_evaluate_object(device_node, object_name,
ACPI_BTYPE_INTEGER, &obj_desc);
@@ -333,7 +391,7 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
union acpi_operand_object *obj_desc;
acpi_status status;
- ACPI_FUNCTION_TRACE("ut_execute_HID");
+ ACPI_FUNCTION_TRACE(ut_execute_HID);
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
@@ -343,6 +401,7 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
}
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
+
/* Convert the Numeric HID to string */
acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value,
@@ -436,7 +495,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node,
struct acpi_compatible_id_list *cid_list;
acpi_native_uint i;
- ACPI_FUNCTION_TRACE("ut_execute_CID");
+ ACPI_FUNCTION_TRACE(ut_execute_CID);
/* Evaluate the _CID method for this device */
@@ -459,7 +518,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node,
size = (((count - 1) * sizeof(struct acpi_compatible_id)) +
sizeof(struct acpi_compatible_id_list));
- cid_list = ACPI_MEM_CALLOCATE((acpi_size) size);
+ cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size);
if (!cid_list) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
@@ -479,6 +538,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node,
/* The _CID object can be either a single CID or a package (list) of CIDs */
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
+
/* Translate each package element */
for (i = 0; i < count; i++) {
@@ -499,7 +559,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node,
/* Cleanup on error */
if (ACPI_FAILURE(status)) {
- ACPI_MEM_FREE(cid_list);
+ ACPI_FREE(cid_list);
} else {
*return_cid_list = cid_list;
}
@@ -533,7 +593,7 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
union acpi_operand_object *obj_desc;
acpi_status status;
- ACPI_FUNCTION_TRACE("ut_execute_UID");
+ ACPI_FUNCTION_TRACE(ut_execute_UID);
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
@@ -543,6 +603,7 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
}
if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
+
/* Convert the Numeric UID to string */
acpi_ex_unsigned_integer_to_string(obj_desc->integer.value,
@@ -582,7 +643,7 @@ acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags)
union acpi_operand_object *obj_desc;
acpi_status status;
- ACPI_FUNCTION_TRACE("ut_execute_STA");
+ ACPI_FUNCTION_TRACE(ut_execute_STA);
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA,
ACPI_BTYPE_INTEGER, &obj_desc);
@@ -632,7 +693,7 @@ acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest)
acpi_status status;
u32 i;
- ACPI_FUNCTION_TRACE("ut_execute_Sxds");
+ ACPI_FUNCTION_TRACE(ut_execute_sxds);
for (i = 0; i < 4; i++) {
highest[i] = 0xFF;
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index ffd13383a32..e5999c65c0b 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -43,7 +43,6 @@
#define DEFINE_ACPI_GLOBALS
-#include <linux/module.h>
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
@@ -119,6 +118,7 @@ const char *acpi_format_exception(acpi_status status)
}
if (!exception) {
+
/* Exception code was not recognized */
ACPI_ERROR((AE_INFO,
@@ -143,12 +143,10 @@ const char *acpi_format_exception(acpi_status status)
/* Debug switch - level and trace mask */
u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT;
-EXPORT_SYMBOL(acpi_dbg_level);
/* Debug switch - layer (component) mask */
u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
-EXPORT_SYMBOL(acpi_dbg_layer);
u32 acpi_gbl_nesting_level = 0;
/* Debugger globals */
@@ -183,28 +181,6 @@ const char *acpi_gbl_highest_dstate_names[4] = {
"_S4D"
};
-/*
- * Strings supported by the _OSI predefined (internal) method.
- * When adding strings, be sure to update ACPI_NUM_OSI_STRINGS.
- */
-const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = {
- /* Operating System Vendor Strings */
-
- "Linux",
- "Windows 2000",
- "Windows 2001",
- "Windows 2001.1",
- "Windows 2001 SP0",
- "Windows 2001 SP1",
- "Windows 2001 SP2",
- "Windows 2001 SP3",
- "Windows 2001 SP4",
-
- /* Feature Group Strings */
-
- "Extended Address Space Descriptor"
-};
-
/*******************************************************************************
*
* Namespace globals
@@ -317,9 +293,9 @@ char acpi_ut_hex_to_ascii_char(acpi_integer integer, u32 position)
*
******************************************************************************/
-struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES];
+struct acpi_table_list acpi_gbl_table_lists[ACPI_TABLE_ID_MAX + 1];
-struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] = {
+struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1] = {
/*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */
/* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL, sizeof(RSDP_SIG) - 1,
@@ -467,7 +443,6 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] =
/* Region type decoding */
const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
-/*! [Begin] no source code translation (keep these ASL Keywords as-is) */
"SystemMemory",
"SystemIO",
"PCI_Config",
@@ -476,16 +451,15 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
"CMOS",
"PCIBARTarget",
"DataTable"
-/*! [End] no source code translation !*/
};
char *acpi_ut_get_region_name(u8 space_id)
{
if (space_id >= ACPI_USER_REGION_BEGIN) {
- return ("user_defined_region");
+ return ("UserDefinedRegion");
} else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) {
- return ("invalid_space_id");
+ return ("InvalidSpaceId");
}
return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id]));
@@ -506,20 +480,18 @@ char *acpi_ut_get_region_name(u8 space_id)
/* Event type decoding */
static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = {
-/*! [Begin] no source code translation (keep these strings as-is) */
"PM_Timer",
"GlobalLock",
"PowerButton",
"SleepButton",
"RealTimeClock",
-/*! [End] no source code translation !*/
};
char *acpi_ut_get_event_name(u32 event_id)
{
if (event_id > ACPI_EVENT_MAX) {
- return ("invalid_event_iD");
+ return ("InvalidEventID");
}
return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id]));
@@ -550,7 +522,6 @@ static const char acpi_gbl_bad_type[] = "UNDEFINED";
/* Printable names of the ACPI object types */
static const char *acpi_gbl_ns_type_names[] = {
-/*! [Begin] no source code translation (keep these strings as-is) */
/* 00 */ "Untyped",
/* 01 */ "Integer",
/* 02 */ "String",
@@ -582,7 +553,6 @@ static const char *acpi_gbl_ns_type_names[] = {
/* 28 */ "Extra",
/* 29 */ "Data",
/* 30 */ "Invalid"
-/*! [End] no source code translation !*/
};
char *acpi_ut_get_type_name(acpi_object_type type)
@@ -635,14 +605,14 @@ char *acpi_ut_get_node_name(void *object)
/* Descriptor must be a namespace node */
- if (node->descriptor != ACPI_DESC_TYPE_NAMED) {
+ if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
return ("####");
}
/* Name must be a valid ACPI name */
if (!acpi_ut_valid_acpi_name(node->name.integer)) {
- return ("????");
+ node->name.integer = acpi_ut_repair_name(node->name.integer);
}
/* Return the name */
@@ -665,7 +635,6 @@ char *acpi_ut_get_node_name(void *object)
/* Printable names of object descriptor types */
static const char *acpi_gbl_desc_type_names[] = {
-/*! [Begin] no source code translation (keep these ASL Keywords as-is) */
/* 00 */ "Invalid",
/* 01 */ "Cached",
/* 02 */ "State-Generic",
@@ -682,7 +651,6 @@ static const char *acpi_gbl_desc_type_names[] = {
/* 13 */ "Parser",
/* 14 */ "Operand",
/* 15 */ "Node"
-/*! [End] no source code translation !*/
};
char *acpi_ut_get_descriptor_name(void *object)
@@ -723,7 +691,7 @@ char *acpi_ut_get_descriptor_name(void *object)
char *acpi_ut_get_mutex_name(u32 mutex_id)
{
- if (mutex_id > MAX_MUTEX) {
+ if (mutex_id > ACPI_MAX_MUTEX) {
return ("Invalid Mutex ID");
}
@@ -747,6 +715,7 @@ u8 acpi_ut_valid_object_type(acpi_object_type type)
{
if (type > ACPI_TYPE_LOCAL_MAX) {
+
/* Note: Assumes all TYPEs are contiguous (external/local) */
return (FALSE);
@@ -773,7 +742,7 @@ void acpi_ut_init_globals(void)
acpi_status status;
u32 i;
- ACPI_FUNCTION_TRACE("ut_init_globals");
+ ACPI_FUNCTION_TRACE(ut_init_globals);
/* Create all memory caches */
@@ -784,14 +753,14 @@ void acpi_ut_init_globals(void)
/* ACPI table structure */
- for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) {
+ for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) {
acpi_gbl_table_lists[i].next = NULL;
acpi_gbl_table_lists[i].count = 0;
}
/* Mutex locked flags */
- for (i = 0; i < NUM_MUTEX; i++) {
+ for (i = 0; i < ACPI_NUM_MUTEX; i++) {
acpi_gbl_mutex_info[i].mutex = NULL;
acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
acpi_gbl_mutex_info[i].use_count = 0;
@@ -856,7 +825,7 @@ void acpi_ut_init_globals(void)
acpi_gbl_root_node = NULL;
acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
- acpi_gbl_root_node_struct.descriptor = ACPI_DESC_TYPE_NAMED;
+ acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED;
acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE;
acpi_gbl_root_node_struct.child = NULL;
acpi_gbl_root_node_struct.peer = NULL;
@@ -869,3 +838,6 @@ void acpi_ut_init_globals(void)
return_VOID;
}
+
+ACPI_EXPORT_SYMBOL(acpi_dbg_level)
+ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c
index ba771b4f39b..ff76055eb7d 100644
--- a/drivers/acpi/utilities/utinit.c
+++ b/drivers/acpi/utilities/utinit.c
@@ -50,7 +50,7 @@ ACPI_MODULE_NAME("utinit")
/* Local prototypes */
static void
-acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset);
+acpi_ut_fadt_register_error(char *register_name, u32 value, u8 offset);
static void acpi_ut_terminate(void);
@@ -69,12 +69,12 @@ static void acpi_ut_terminate(void);
******************************************************************************/
static void
-acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset)
+acpi_ut_fadt_register_error(char *register_name, u32 value, u8 offset)
{
ACPI_WARNING((AE_INFO,
"Invalid FADT value %s=%X at offset %X FADT=%p",
- register_name, value, (u32) offset, acpi_gbl_FADT));
+ register_name, value, offset, acpi_gbl_FADT));
}
/******************************************************************************
@@ -176,7 +176,7 @@ static void acpi_ut_terminate(void)
struct acpi_gpe_xrupt_info *gpe_xrupt_info;
struct acpi_gpe_xrupt_info *next_gpe_xrupt_info;
- ACPI_FUNCTION_TRACE("ut_terminate");
+ ACPI_FUNCTION_TRACE(ut_terminate);
/* Free global tables, etc. */
/* Free global GPE blocks and related info structures */
@@ -186,14 +186,14 @@ static void acpi_ut_terminate(void)
gpe_block = gpe_xrupt_info->gpe_block_list_head;
while (gpe_block) {
next_gpe_block = gpe_block->next;
- ACPI_MEM_FREE(gpe_block->event_info);
- ACPI_MEM_FREE(gpe_block->register_info);
- ACPI_MEM_FREE(gpe_block);
+ ACPI_FREE(gpe_block->event_info);
+ ACPI_FREE(gpe_block->register_info);
+ ACPI_FREE(gpe_block);
gpe_block = next_gpe_block;
}
next_gpe_xrupt_info = gpe_xrupt_info->next;
- ACPI_MEM_FREE(gpe_xrupt_info);
+ ACPI_FREE(gpe_xrupt_info);
gpe_xrupt_info = next_gpe_xrupt_info;
}
@@ -216,7 +216,7 @@ static void acpi_ut_terminate(void)
void acpi_ut_subsystem_shutdown(void)
{
- ACPI_FUNCTION_TRACE("ut_subsystem_shutdown");
+ ACPI_FUNCTION_TRACE(ut_subsystem_shutdown);
/* Just exit if subsystem is already shutdown */
@@ -228,6 +228,7 @@ void acpi_ut_subsystem_shutdown(void)
/* Subsystem appears active, go ahead and shut it down */
acpi_gbl_shutdown = TRUE;
+ acpi_gbl_startup_flags = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n"));
/* Close the acpi_event Handling */
@@ -245,12 +246,5 @@ void acpi_ut_subsystem_shutdown(void)
/* Purge the local caches */
(void)acpi_ut_delete_caches();
-
- /* Debug only - display leftover memory allocation, if any */
-
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
- acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL);
-#endif
-
return_VOID;
}
diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c
index 4a3360484e7..19d74bedce2 100644
--- a/drivers/acpi/utilities/utmath.c
+++ b/drivers/acpi/utilities/utmath.c
@@ -77,7 +77,7 @@ acpi_ut_short_divide(acpi_integer dividend,
union uint64_overlay quotient;
u32 remainder32;
- ACPI_FUNCTION_TRACE("ut_short_divide");
+ ACPI_FUNCTION_TRACE(ut_short_divide);
/* Always check for a zero divisor */
@@ -139,7 +139,7 @@ acpi_ut_divide(acpi_integer in_dividend,
union uint64_overlay partial2;
union uint64_overlay partial3;
- ACPI_FUNCTION_TRACE("ut_divide");
+ ACPI_FUNCTION_TRACE(ut_divide);
/* Always check for a zero divisor */
@@ -261,7 +261,7 @@ acpi_ut_short_divide(acpi_integer in_dividend,
acpi_integer * out_quotient, u32 * out_remainder)
{
- ACPI_FUNCTION_TRACE("ut_short_divide");
+ ACPI_FUNCTION_TRACE(ut_short_divide);
/* Always check for a zero divisor */
@@ -287,7 +287,7 @@ acpi_ut_divide(acpi_integer in_dividend,
acpi_integer in_divisor,
acpi_integer * out_quotient, acpi_integer * out_remainder)
{
- ACPI_FUNCTION_TRACE("ut_divide");
+ ACPI_FUNCTION_TRACE(ut_divide);
/* Always check for a zero divisor */
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index 7364f5f8c9c..5c75d35ad1c 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -49,6 +49,33 @@ ACPI_MODULE_NAME("utmisc")
/*******************************************************************************
*
+ * FUNCTION: acpi_ut_is_aml_table
+ *
+ * PARAMETERS: Table - An ACPI table
+ *
+ * RETURN: TRUE if table contains executable AML; FALSE otherwise
+ *
+ * DESCRIPTION: Check ACPI Signature for a table that contains AML code.
+ * Currently, these are DSDT,SSDT,PSDT. All other table types are
+ * data tables that do not contain AML code.
+ *
+ ******************************************************************************/
+u8 acpi_ut_is_aml_table(struct acpi_table_header *table)
+{
+
+ /* Ignore tables that contain AML */
+
+ if (ACPI_COMPARE_NAME(table->signature, DSDT_SIG) ||
+ ACPI_COMPARE_NAME(table->signature, PSDT_SIG) ||
+ ACPI_COMPARE_NAME(table->signature, SSDT_SIG)) {
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ut_allocate_owner_id
*
* PARAMETERS: owner_id - Where the new owner ID is returned
@@ -60,6 +87,7 @@ ACPI_MODULE_NAME("utmisc")
* when the method exits or the table is unloaded.
*
******************************************************************************/
+
acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
{
acpi_native_uint i;
@@ -67,7 +95,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
acpi_native_uint k;
acpi_status status;
- ACPI_FUNCTION_TRACE("ut_allocate_owner_id");
+ ACPI_FUNCTION_TRACE(ut_allocate_owner_id);
/* Guard against multiple allocations of ID to the same location */
@@ -97,6 +125,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) {
if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) {
+
/* There are no free IDs in this mask */
break;
@@ -123,7 +152,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
(acpi_owner_id) ((k + 1) + ACPI_MUL_32(j));
ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
- "Allocated owner_id: %2.2X\n",
+ "Allocated OwnerId: %2.2X\n",
(unsigned int)*owner_id));
goto exit;
}
@@ -144,7 +173,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
*/
status = AE_OWNER_ID_LIMIT;
ACPI_ERROR((AE_INFO,
- "Could not allocate new owner_id (255 max), AE_OWNER_ID_LIMIT"));
+ "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT"));
exit:
(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
@@ -172,7 +201,7 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
acpi_native_uint index;
u32 bit;
- ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id);
+ ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id);
/* Always clear the input owner_id (zero is an invalid ID) */
@@ -181,7 +210,7 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
/* Zero is not a valid owner_iD */
if (owner_id == 0) {
- ACPI_ERROR((AE_INFO, "Invalid owner_id: %2.2X", owner_id));
+ ACPI_ERROR((AE_INFO, "Invalid OwnerId: %2.2X", owner_id));
return_VOID;
}
@@ -207,7 +236,7 @@ void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
acpi_gbl_owner_id_mask[index] ^= bit;
} else {
ACPI_ERROR((AE_INFO,
- "Release of non-allocated owner_id: %2.2X",
+ "Release of non-allocated OwnerId: %2.2X",
owner_id + 1));
}
@@ -273,6 +302,7 @@ void acpi_ut_print_string(char *string, u8 max_length)
acpi_os_printf("\"");
for (i = 0; string[i] && (i < max_length); i++) {
+
/* Escape sequences */
switch (string[i]) {
@@ -461,12 +491,47 @@ acpi_ut_display_init_pathname(u8 type,
}
acpi_os_printf("\n");
- ACPI_MEM_FREE(buffer.pointer);
+ ACPI_FREE(buffer.pointer);
}
#endif
/*******************************************************************************
*
+ * FUNCTION: acpi_ut_valid_acpi_char
+ *
+ * PARAMETERS: Char - The character to be examined
+ *
+ * RETURN: TRUE if the character is valid, FALSE otherwise
+ *
+ * DESCRIPTION: Check for a valid ACPI character. Must be one of:
+ * 1) Upper case alpha
+ * 2) numeric
+ * 3) underscore
+ *
+ * We allow a '!' as the last character because of the ASF! table
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position)
+{
+
+ if (!((character >= 'A' && character <= 'Z') ||
+ (character >= '0' && character <= '9') || (character == '_'))) {
+
+ /* Allow a '!' in the last position */
+
+ if (character == '!' && position == 3) {
+ return (TRUE);
+ }
+
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ut_valid_acpi_name
*
* PARAMETERS: Name - The name to be examined
@@ -482,19 +547,13 @@ acpi_ut_display_init_pathname(u8 type,
u8 acpi_ut_valid_acpi_name(u32 name)
{
- char *name_ptr = (char *)&name;
- char character;
acpi_native_uint i;
ACPI_FUNCTION_ENTRY();
for (i = 0; i < ACPI_NAME_SIZE; i++) {
- character = *name_ptr;
- name_ptr++;
-
- if (!((character == '_') ||
- (character >= 'A' && character <= 'Z') ||
- (character >= '0' && character <= '9'))) {
+ if (!acpi_ut_valid_acpi_char
+ ((ACPI_CAST_PTR(char, &name))[i], i)) {
return (FALSE);
}
}
@@ -504,24 +563,37 @@ u8 acpi_ut_valid_acpi_name(u32 name)
/*******************************************************************************
*
- * FUNCTION: acpi_ut_valid_acpi_character
+ * FUNCTION: acpi_ut_repair_name
*
- * PARAMETERS: Character - The character to be examined
+ * PARAMETERS: Name - The ACPI name to be repaired
*
- * RETURN: 1 if Character may appear in a name, else 0
+ * RETURN: Repaired version of the name
*
- * DESCRIPTION: Check for a printable character
+ * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and
+ * return the new name.
*
******************************************************************************/
-u8 acpi_ut_valid_acpi_character(char character)
+acpi_name acpi_ut_repair_name(acpi_name name)
{
+ char *name_ptr = ACPI_CAST_PTR(char, &name);
+ char new_name[ACPI_NAME_SIZE];
+ acpi_native_uint i;
- ACPI_FUNCTION_ENTRY();
+ for (i = 0; i < ACPI_NAME_SIZE; i++) {
+ new_name[i] = name_ptr[i];
- return ((u8) ((character == '_') ||
- (character >= 'A' && character <= 'Z') ||
- (character >= '0' && character <= '9')));
+ /*
+ * Replace a bad character with something printable, yet technically
+ * still invalid. This prevents any collisions with existing "good"
+ * names in the namespace.
+ */
+ if (!acpi_ut_valid_acpi_char(name_ptr[i], i)) {
+ new_name[i] = '*';
+ }
+ }
+
+ return (*ACPI_CAST_PTR(u32, new_name));
}
/*******************************************************************************
@@ -529,7 +601,8 @@ u8 acpi_ut_valid_acpi_character(char character)
* FUNCTION: acpi_ut_strtoul64
*
* PARAMETERS: String - Null terminated string
- * Base - Radix of the string: 10, 16, or ACPI_ANY_BASE
+ * Base - Radix of the string: 16 or ACPI_ANY_BASE;
+ * ACPI_ANY_BASE means 'in behalf of to_integer'
* ret_integer - Where the converted integer is returned
*
* RETURN: Status and Converted value
@@ -545,16 +618,17 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
u32 this_digit = 0;
acpi_integer return_value = 0;
acpi_integer quotient;
+ acpi_integer dividend;
+ u32 to_integer_op = (base == ACPI_ANY_BASE);
+ u32 mode32 = (acpi_gbl_integer_byte_width == 4);
+ u8 valid_digits = 0;
+ u8 sign_of0x = 0;
+ u8 term = 0;
- ACPI_FUNCTION_TRACE("ut_stroul64");
-
- if ((!string) || !(*string)) {
- goto error_exit;
- }
+ ACPI_FUNCTION_TRACE(ut_stroul64);
switch (base) {
case ACPI_ANY_BASE:
- case 10:
case 16:
break;
@@ -563,76 +637,110 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
+ if (!string) {
+ goto error_exit;
+ }
+
/* Skip over any white space in the buffer */
- while (ACPI_IS_SPACE(*string) || *string == '\t') {
+ while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) {
string++;
}
- /*
- * If the input parameter Base is zero, then we need to
- * determine if it is decimal or hexadecimal:
- */
- if (base == 0) {
+ if (to_integer_op) {
+ /*
+ * Base equal to ACPI_ANY_BASE means 'to_integer operation case'.
+ * We need to determine if it is decimal or hexadecimal.
+ */
if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
+ sign_of0x = 1;
base = 16;
+
+ /* Skip over the leading '0x' */
string += 2;
} else {
base = 10;
}
}
- /*
- * For hexadecimal base, skip over the leading
- * 0 or 0x, if they are present.
- */
- if ((base == 16) &&
- (*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
- string += 2;
+ /* Any string left? Check that '0x' is not followed by white space. */
+
+ if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') {
+ if (to_integer_op) {
+ goto error_exit;
+ } else {
+ goto all_done;
+ }
}
- /* Any string left? */
+ dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
- if (!(*string)) {
- goto error_exit;
- }
+ /* At least one character in the string here */
/* Main loop: convert the string to a 64-bit integer */
while (*string) {
if (ACPI_IS_DIGIT(*string)) {
+
/* Convert ASCII 0-9 to Decimal value */
this_digit = ((u8) * string) - '0';
- } else {
- if (base == 10) {
- /* Digit is out of range */
+ } else if (base == 10) {
- goto error_exit;
- }
+ /* Digit is out of range; possible in to_integer case only */
+ term = 1;
+ } else {
this_digit = (u8) ACPI_TOUPPER(*string);
if (ACPI_IS_XDIGIT((char)this_digit)) {
+
/* Convert ASCII Hex char to value */
this_digit = this_digit - 'A' + 10;
} else {
- /*
- * We allow non-hex chars, just stop now, same as end-of-string.
- * See ACPI spec, string-to-integer conversion.
- */
+ term = 1;
+ }
+ }
+
+ if (term) {
+ if (to_integer_op) {
+ goto error_exit;
+ } else {
break;
}
+ } else if ((valid_digits == 0) && (this_digit == 0)
+ && !sign_of0x) {
+
+ /* Skip zeros */
+ string++;
+ continue;
+ }
+
+ valid_digits++;
+
+ if (sign_of0x
+ && ((valid_digits > 16)
+ || ((valid_digits > 8) && mode32))) {
+ /*
+ * This is to_integer operation case.
+ * No any restrictions for string-to-integer conversion,
+ * see ACPI spec.
+ */
+ goto error_exit;
}
/* Divide the digit into the correct position */
(void)
- acpi_ut_short_divide((ACPI_INTEGER_MAX -
- (acpi_integer) this_digit), base,
- &quotient, NULL);
+ acpi_ut_short_divide((dividend - (acpi_integer) this_digit),
+ base, &quotient, NULL);
+
if (return_value > quotient) {
- goto error_exit;
+ if (to_integer_op) {
+ goto error_exit;
+ } else {
+ break;
+ }
}
return_value *= base;
@@ -642,6 +750,8 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
/* All done, normal exit */
+ all_done:
+
*ret_integer = return_value;
return_ACPI_STATUS(AE_OK);
@@ -719,7 +829,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
u32 this_index;
union acpi_operand_object *this_source_obj;
- ACPI_FUNCTION_TRACE("ut_walk_package_tree");
+ ACPI_FUNCTION_TRACE(ut_walk_package_tree);
state = acpi_ut_create_pkg_state(source_object, target_object, 0);
if (!state) {
@@ -727,6 +837,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
}
while (state) {
+
/* Get one element of the package */
this_index = state->pkg.index;
@@ -814,31 +925,6 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
/*******************************************************************************
*
- * FUNCTION: acpi_ut_generate_checksum
- *
- * PARAMETERS: Buffer - Buffer to be scanned
- * Length - number of bytes to examine
- *
- * RETURN: The generated checksum
- *
- * DESCRIPTION: Generate a checksum on a raw buffer
- *
- ******************************************************************************/
-
-u8 acpi_ut_generate_checksum(u8 * buffer, u32 length)
-{
- u32 i;
- signed char sum = 0;
-
- for (i = 0; i < length; i++) {
- sum = (signed char)(sum + buffer[i]);
- }
-
- return ((u8) (0 - sum));
-}
-
-/*******************************************************************************
- *
* FUNCTION: acpi_ut_error, acpi_ut_warning, acpi_ut_info
*
* PARAMETERS: module_name - Caller's module name (for error output)
@@ -900,36 +986,3 @@ acpi_ut_info(char *module_name, u32 line_number, char *format, ...)
acpi_os_vprintf(format, args);
acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_report_error, Warning, Info
- *
- * PARAMETERS: module_name - Caller's module name (for error output)
- * line_number - Caller's line number (for error output)
- *
- * RETURN: None
- *
- * DESCRIPTION: Print error message
- *
- * Note: Legacy only, should be removed when no longer used by drivers.
- *
- ******************************************************************************/
-
-void acpi_ut_report_error(char *module_name, u32 line_number)
-{
-
- acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
-}
-
-void acpi_ut_report_warning(char *module_name, u32 line_number)
-{
-
- acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number);
-}
-
-void acpi_ut_report_info(char *module_name, u32 line_number)
-{
-
- acpi_os_printf("ACPI (%s-%04d): ", module_name, line_number);
-}
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c
index 45a7244df92..25eb34369af 100644
--- a/drivers/acpi/utilities/utmutex.c
+++ b/drivers/acpi/utilities/utmutex.c
@@ -68,19 +68,26 @@ acpi_status acpi_ut_mutex_initialize(void)
u32 i;
acpi_status status;
- ACPI_FUNCTION_TRACE("ut_mutex_initialize");
+ ACPI_FUNCTION_TRACE(ut_mutex_initialize);
/*
* Create each of the predefined mutex objects
*/
- for (i = 0; i < NUM_MUTEX; i++) {
+ for (i = 0; i < ACPI_NUM_MUTEX; i++) {
status = acpi_ut_create_mutex(i);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
+ /* Create the spinlocks for use at interrupt level */
+
status = acpi_os_create_lock(&acpi_gbl_gpe_lock);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ status = acpi_os_create_lock(&acpi_gbl_hardware_lock);
return_ACPI_STATUS(status);
}
@@ -100,16 +107,19 @@ void acpi_ut_mutex_terminate(void)
{
u32 i;
- ACPI_FUNCTION_TRACE("ut_mutex_terminate");
+ ACPI_FUNCTION_TRACE(ut_mutex_terminate);
/*
* Delete each predefined mutex object
*/
- for (i = 0; i < NUM_MUTEX; i++) {
+ for (i = 0; i < ACPI_NUM_MUTEX; i++) {
(void)acpi_ut_delete_mutex(i);
}
+ /* Delete the spinlocks */
+
acpi_os_delete_lock(acpi_gbl_gpe_lock);
+ acpi_os_delete_lock(acpi_gbl_hardware_lock);
return_VOID;
}
@@ -129,9 +139,9 @@ static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id)
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE_U32("ut_create_mutex", mutex_id);
+ ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id);
- if (mutex_id > MAX_MUTEX) {
+ if (mutex_id > ACPI_MAX_MUTEX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -163,9 +173,9 @@ static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)
{
acpi_status status;
- ACPI_FUNCTION_TRACE_U32("ut_delete_mutex", mutex_id);
+ ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id);
- if (mutex_id > MAX_MUTEX) {
+ if (mutex_id > ACPI_MAX_MUTEX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -192,11 +202,11 @@ static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)
acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
{
acpi_status status;
- u32 this_thread_id;
+ acpi_thread_id this_thread_id;
- ACPI_FUNCTION_NAME("ut_acquire_mutex");
+ ACPI_FUNCTION_NAME(ut_acquire_mutex);
- if (mutex_id > MAX_MUTEX) {
+ if (mutex_id > ACPI_MAX_MUTEX) {
return (AE_BAD_PARAMETER);
}
@@ -213,7 +223,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
* the mutex ordering rule. This indicates a coding error somewhere in
* the ACPI subsystem code.
*/
- for (i = mutex_id; i < MAX_MUTEX; i++) {
+ for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) {
if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
if (i == mutex_id) {
ACPI_ERROR((AE_INFO,
@@ -275,16 +285,16 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
{
acpi_status status;
- u32 this_thread_id;
+ acpi_thread_id this_thread_id;
- ACPI_FUNCTION_NAME("ut_release_mutex");
+ ACPI_FUNCTION_NAME(ut_release_mutex);
this_thread_id = acpi_os_get_thread_id();
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
"Thread %X releasing Mutex [%s]\n", this_thread_id,
acpi_ut_get_mutex_name(mutex_id)));
- if (mutex_id > MAX_MUTEX) {
+ if (mutex_id > ACPI_MAX_MUTEX) {
return (AE_BAD_PARAMETER);
}
@@ -309,7 +319,7 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
* ordering rule. This indicates a coding error somewhere in
* the ACPI subsystem code.
*/
- for (i = mutex_id; i < MAX_MUTEX; i++) {
+ for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) {
if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
if (i == mutex_id) {
continue;
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index 7ee2d1d9807..ba7d8ac702d 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -92,7 +92,7 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name,
union acpi_operand_object *object;
union acpi_operand_object *second_object;
- ACPI_FUNCTION_TRACE_STR("ut_create_internal_object_dbg",
+ ACPI_FUNCTION_TRACE_STR(ut_create_internal_object_dbg,
acpi_ut_get_type_name(type));
/* Allocate the raw object descriptor */
@@ -161,7 +161,7 @@ union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size)
union acpi_operand_object *buffer_desc;
u8 *buffer = NULL;
- ACPI_FUNCTION_TRACE_U32("ut_create_buffer_object", buffer_size);
+ ACPI_FUNCTION_TRACE_U32(ut_create_buffer_object, buffer_size);
/* Create a new Buffer object */
@@ -173,9 +173,10 @@ union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size)
/* Create an actual buffer only if size > 0 */
if (buffer_size > 0) {
+
/* Allocate the actual buffer */
- buffer = ACPI_MEM_CALLOCATE(buffer_size);
+ buffer = ACPI_ALLOCATE_ZEROED(buffer_size);
if (!buffer) {
ACPI_ERROR((AE_INFO, "Could not allocate size %X",
(u32) buffer_size));
@@ -214,7 +215,7 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size)
union acpi_operand_object *string_desc;
char *string;
- ACPI_FUNCTION_TRACE_U32("ut_create_string_object", string_size);
+ ACPI_FUNCTION_TRACE_U32(ut_create_string_object, string_size);
/* Create a new String object */
@@ -227,7 +228,7 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size)
* Allocate the actual string buffer -- (Size + 1) for NULL terminator.
* NOTE: Zero-length strings are NULL terminated
*/
- string = ACPI_MEM_CALLOCATE(string_size + 1);
+ string = ACPI_ALLOCATE_ZEROED(string_size + 1);
if (!string) {
ACPI_ERROR((AE_INFO, "Could not allocate size %X",
(u32) string_size));
@@ -260,7 +261,7 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size)
u8 acpi_ut_valid_internal_object(void *object)
{
- ACPI_FUNCTION_NAME("ut_valid_internal_object");
+ ACPI_FUNCTION_NAME(ut_valid_internal_object);
/* Check for a null pointer */
@@ -308,7 +309,7 @@ void *acpi_ut_allocate_object_desc_dbg(char *module_name,
{
union acpi_operand_object *object;
- ACPI_FUNCTION_TRACE("ut_allocate_object_desc_dbg");
+ ACPI_FUNCTION_TRACE(ut_allocate_object_desc_dbg);
object = acpi_os_acquire_object(acpi_gbl_operand_cache);
if (!object) {
@@ -319,6 +320,7 @@ void *acpi_ut_allocate_object_desc_dbg(char *module_name,
}
/* Mark the descriptor type */
+
memset(object, 0, sizeof(union acpi_operand_object));
ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND);
@@ -342,7 +344,7 @@ void *acpi_ut_allocate_object_desc_dbg(char *module_name,
void acpi_ut_delete_object_desc(union acpi_operand_object *object)
{
- ACPI_FUNCTION_TRACE_PTR("ut_delete_object_desc", object);
+ ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object);
/* Object must be an union acpi_operand_object */
@@ -381,7 +383,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
acpi_size length;
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE_PTR("ut_get_simple_object_size", internal_object);
+ ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object);
/*
* Handle a null object (Could be a uninitialized package
@@ -397,6 +399,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
length = sizeof(union acpi_object);
if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) {
+
/* Object is a named object (reference), just return the length */
*obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length);
@@ -559,7 +562,7 @@ acpi_ut_get_package_object_size(union acpi_operand_object *internal_object,
acpi_status status;
struct acpi_pkg_info info;
- ACPI_FUNCTION_TRACE_PTR("ut_get_package_object_size", internal_object);
+ ACPI_FUNCTION_TRACE_PTR(ut_get_package_object_size, internal_object);
info.length = 0;
info.object_space = 0;
diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c
index 16461317113..5a2de92831d 100644
--- a/drivers/acpi/utilities/utresrc.c
+++ b/drivers/acpi/utilities/utresrc.c
@@ -45,113 +45,113 @@
#include <acpi/amlresrc.h>
#define _COMPONENT ACPI_UTILITIES
-ACPI_MODULE_NAME("utmisc")
+ACPI_MODULE_NAME("utresrc")
#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
/*
* Strings used to decode resource descriptors.
* Used by both the disasssembler and the debugger resource dump routines
*/
-const char *acpi_gbl_BMdecode[2] = {
- "not_bus_master",
- "bus_master"
+const char *acpi_gbl_bm_decode[] = {
+ "NotBusMaster",
+ "BusMaster"
};
-const char *acpi_gbl_config_decode[4] = {
+const char *acpi_gbl_config_decode[] = {
"0 - Good Configuration",
"1 - Acceptable Configuration",
"2 - Suboptimal Configuration",
"3 - ***Invalid Configuration***",
};
-const char *acpi_gbl_consume_decode[2] = {
- "resource_producer",
- "resource_consumer"
+const char *acpi_gbl_consume_decode[] = {
+ "ResourceProducer",
+ "ResourceConsumer"
};
-const char *acpi_gbl_DECdecode[2] = {
- "pos_decode",
- "sub_decode"
+const char *acpi_gbl_dec_decode[] = {
+ "PosDecode",
+ "SubDecode"
};
-const char *acpi_gbl_HEdecode[2] = {
+const char *acpi_gbl_he_decode[] = {
"Level",
"Edge"
};
-const char *acpi_gbl_io_decode[2] = {
+const char *acpi_gbl_io_decode[] = {
"Decode10",
"Decode16"
};
-const char *acpi_gbl_LLdecode[2] = {
- "active_high",
- "active_low"
+const char *acpi_gbl_ll_decode[] = {
+ "ActiveHigh",
+ "ActiveLow"
};
-const char *acpi_gbl_max_decode[2] = {
- "max_not_fixed",
- "max_fixed"
+const char *acpi_gbl_max_decode[] = {
+ "MaxNotFixed",
+ "MaxFixed"
};
-const char *acpi_gbl_MEMdecode[4] = {
- "non_cacheable",
+const char *acpi_gbl_mem_decode[] = {
+ "NonCacheable",
"Cacheable",
- "write_combining",
+ "WriteCombining",
"Prefetchable"
};
-const char *acpi_gbl_min_decode[2] = {
- "min_not_fixed",
- "min_fixed"
+const char *acpi_gbl_min_decode[] = {
+ "MinNotFixed",
+ "MinFixed"
};
-const char *acpi_gbl_MTPdecode[4] = {
- "address_range_memory",
- "address_range_reserved",
- "address_range_aCPI",
- "address_range_nVS"
+const char *acpi_gbl_mtp_decode[] = {
+ "AddressRangeMemory",
+ "AddressRangeReserved",
+ "AddressRangeACPI",
+ "AddressRangeNVS"
};
-const char *acpi_gbl_RNGdecode[4] = {
- "invalid_ranges",
- "non_iSAonly_ranges",
- "ISAonly_ranges",
- "entire_range"
+const char *acpi_gbl_rng_decode[] = {
+ "InvalidRanges",
+ "NonISAOnlyRanges",
+ "ISAOnlyRanges",
+ "EntireRange"
};
-const char *acpi_gbl_RWdecode[2] = {
- "read_only",
- "read_write"
+const char *acpi_gbl_rw_decode[] = {
+ "ReadOnly",
+ "ReadWrite"
};
-const char *acpi_gbl_SHRdecode[2] = {
+const char *acpi_gbl_shr_decode[] = {
"Exclusive",
"Shared"
};
-const char *acpi_gbl_SIZdecode[4] = {
+const char *acpi_gbl_siz_decode[] = {
"Transfer8",
"Transfer8_16",
"Transfer16",
- "invalid_size"
+ "InvalidSize"
};
-const char *acpi_gbl_TRSdecode[2] = {
- "dense_translation",
- "sparse_translation"
+const char *acpi_gbl_trs_decode[] = {
+ "DenseTranslation",
+ "SparseTranslation"
};
-const char *acpi_gbl_TTPdecode[2] = {
- "type_static",
- "type_translation"
+const char *acpi_gbl_ttp_decode[] = {
+ "TypeStatic",
+ "TypeTranslation"
};
-const char *acpi_gbl_TYPdecode[4] = {
+const char *acpi_gbl_typ_decode[] = {
"Compatibility",
- "type_a",
- "type_b",
- "type_f"
+ "TypeA",
+ "TypeB",
+ "TypeF"
};
#endif
@@ -240,6 +240,104 @@ static const u8 acpi_gbl_resource_types[] = {
/*******************************************************************************
*
+ * FUNCTION: acpi_ut_walk_aml_resources
+ *
+ * PARAMETERS: Aml - Pointer to the raw AML resource template
+ * aml_length - Length of the entire template
+ * user_function - Called once for each descriptor found. If
+ * NULL, a pointer to the end_tag is returned
+ * Context - Passed to user_function
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Walk a raw AML resource list(buffer). User function called
+ * once for each resource found.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_walk_aml_resources(u8 * aml,
+ acpi_size aml_length,
+ acpi_walk_aml_callback user_function, void **context)
+{
+ acpi_status status;
+ u8 *end_aml;
+ u8 resource_index;
+ u32 length;
+ u32 offset = 0;
+
+ ACPI_FUNCTION_TRACE(ut_walk_aml_resources);
+
+ /* The absolute minimum resource template is one end_tag descriptor */
+
+ if (aml_length < sizeof(struct aml_resource_end_tag)) {
+ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+ }
+
+ /* Point to the end of the resource template buffer */
+
+ end_aml = aml + aml_length;
+
+ /* Walk the byte list, abort on any invalid descriptor type or length */
+
+ while (aml < end_aml) {
+
+ /* Validate the Resource Type and Resource Length */
+
+ status = acpi_ut_validate_resource(aml, &resource_index);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Get the length of this descriptor */
+
+ length = acpi_ut_get_descriptor_length(aml);
+
+ /* Invoke the user function */
+
+ if (user_function) {
+ status =
+ user_function(aml, length, offset, resource_index,
+ context);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ }
+
+ /* An end_tag descriptor terminates this resource template */
+
+ if (acpi_ut_get_resource_type(aml) ==
+ ACPI_RESOURCE_NAME_END_TAG) {
+ /*
+ * There must be at least one more byte in the buffer for
+ * the 2nd byte of the end_tag
+ */
+ if ((aml + 1) >= end_aml) {
+ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+ }
+
+ /* Return the pointer to the end_tag if requested */
+
+ if (!user_function) {
+ *context = aml;
+ }
+
+ /* Normal exit */
+
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ aml += length;
+ offset += length;
+ }
+
+ /* Did not find an end_tag descriptor */
+
+ return (AE_AML_NO_RESOURCE_END_TAG);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ut_validate_resource
*
* PARAMETERS: Aml - Pointer to the raw AML resource descriptor
@@ -273,6 +371,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
* Examine the large/small bit in the resource header
*/
if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
+
/* Verify the large resource type (name) against the max */
if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
@@ -376,6 +475,7 @@ u8 acpi_ut_get_resource_type(void *aml)
* Examine the large/small bit in the resource header
*/
if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
+
/* Large Resource Type -- bits 6:0 contain the name */
return (ACPI_GET8(aml));
@@ -411,6 +511,7 @@ u16 acpi_ut_get_resource_length(void *aml)
* Examine the large/small bit in the resource header
*/
if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
+
/* Large Resource type -- bytes 1-2 contain the 16-bit length */
ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1));
@@ -495,60 +596,21 @@ acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc,
u8 ** end_tag)
{
acpi_status status;
- u8 *aml;
- u8 *end_aml;
-
- ACPI_FUNCTION_TRACE("ut_get_resource_end_tag");
- /* Get start and end pointers */
-
- aml = obj_desc->buffer.pointer;
- end_aml = aml + obj_desc->buffer.length;
+ ACPI_FUNCTION_TRACE(ut_get_resource_end_tag);
/* Allow a buffer length of zero */
if (!obj_desc->buffer.length) {
- *end_tag = aml;
+ *end_tag = obj_desc->buffer.pointer;
return_ACPI_STATUS(AE_OK);
}
- /* Walk the resource template, one descriptor per iteration */
-
- while (aml < end_aml) {
- /* Validate the Resource Type and Resource Length */
-
- status = acpi_ut_validate_resource(aml, NULL);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /* end_tag resource indicates the end of the resource template */
-
- if (acpi_ut_get_resource_type(aml) ==
- ACPI_RESOURCE_NAME_END_TAG) {
- /*
- * There must be at least one more byte in the buffer for
- * the 2nd byte of the end_tag
- */
- if ((aml + 1) >= end_aml) {
- return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
- }
-
- /* Return the pointer to the end_tag */
-
- *end_tag = aml;
- return_ACPI_STATUS(AE_OK);
- }
-
- /*
- * Point to the next resource descriptor in the AML buffer. The
- * descriptor length is guaranteed to be non-zero by resource
- * validation above.
- */
- aml += acpi_ut_get_descriptor_length(aml);
- }
+ /* Validate the template and get a pointer to the end_tag */
- /* Did not find an end_tag resource descriptor */
+ status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer,
+ obj_desc->buffer.length, NULL,
+ (void **)end_tag);
- return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+ return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c
index 4b134a72290..0f5c5bb5def 100644
--- a/drivers/acpi/utilities/utstate.c
+++ b/drivers/acpi/utilities/utstate.c
@@ -96,7 +96,7 @@ void
acpi_ut_push_generic_state(union acpi_generic_state **list_head,
union acpi_generic_state *state)
{
- ACPI_FUNCTION_TRACE("ut_push_generic_state");
+ ACPI_FUNCTION_TRACE(ut_push_generic_state);
/* Push the state object onto the front of the list (stack) */
@@ -123,12 +123,13 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state
{
union acpi_generic_state *state;
- ACPI_FUNCTION_TRACE("ut_pop_generic_state");
+ ACPI_FUNCTION_TRACE(ut_pop_generic_state);
/* Remove the state object at the head of the list (stack) */
state = *list_head;
if (state) {
+
/* Update the list head */
*list_head = state->common.next;
@@ -158,9 +159,10 @@ union acpi_generic_state *acpi_ut_create_generic_state(void)
state = acpi_os_acquire_object(acpi_gbl_state_cache);
if (state) {
+
/* Initialize */
memset(state, 0, sizeof(union acpi_generic_state));
- state->common.data_type = ACPI_DESC_TYPE_STATE;
+ state->common.descriptor_type = ACPI_DESC_TYPE_STATE;
}
return (state);
@@ -183,7 +185,7 @@ struct acpi_thread_state *acpi_ut_create_thread_state(void)
{
union acpi_generic_state *state;
- ACPI_FUNCTION_TRACE("ut_create_thread_state");
+ ACPI_FUNCTION_TRACE(ut_create_thread_state);
/* Create the generic state object */
@@ -194,7 +196,7 @@ struct acpi_thread_state *acpi_ut_create_thread_state(void)
/* Init fields specific to the update struct */
- state->common.data_type = ACPI_DESC_TYPE_STATE_THREAD;
+ state->common.descriptor_type = ACPI_DESC_TYPE_STATE_THREAD;
state->thread.thread_id = acpi_os_get_thread_id();
return_PTR((struct acpi_thread_state *)state);
@@ -220,7 +222,7 @@ union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object
{
union acpi_generic_state *state;
- ACPI_FUNCTION_TRACE_PTR("ut_create_update_state", object);
+ ACPI_FUNCTION_TRACE_PTR(ut_create_update_state, object);
/* Create the generic state object */
@@ -231,7 +233,7 @@ union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object
/* Init fields specific to the update struct */
- state->common.data_type = ACPI_DESC_TYPE_STATE_UPDATE;
+ state->common.descriptor_type = ACPI_DESC_TYPE_STATE_UPDATE;
state->update.object = object;
state->update.value = action;
@@ -257,7 +259,7 @@ union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object,
{
union acpi_generic_state *state;
- ACPI_FUNCTION_TRACE_PTR("ut_create_pkg_state", internal_object);
+ ACPI_FUNCTION_TRACE_PTR(ut_create_pkg_state, internal_object);
/* Create the generic state object */
@@ -268,7 +270,7 @@ union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object,
/* Init fields specific to the update struct */
- state->common.data_type = ACPI_DESC_TYPE_STATE_PACKAGE;
+ state->common.descriptor_type = ACPI_DESC_TYPE_STATE_PACKAGE;
state->pkg.source_object = (union acpi_operand_object *)internal_object;
state->pkg.dest_object = external_object;
state->pkg.index = index;
@@ -294,7 +296,7 @@ union acpi_generic_state *acpi_ut_create_control_state(void)
{
union acpi_generic_state *state;
- ACPI_FUNCTION_TRACE("ut_create_control_state");
+ ACPI_FUNCTION_TRACE(ut_create_control_state);
/* Create the generic state object */
@@ -305,7 +307,7 @@ union acpi_generic_state *acpi_ut_create_control_state(void)
/* Init fields specific to the control struct */
- state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL;
+ state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL;
state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING;
return_PTR(state);
@@ -319,15 +321,19 @@ union acpi_generic_state *acpi_ut_create_control_state(void)
*
* RETURN: None
*
- * DESCRIPTION: Put a state object back into the global state cache. The object
- * is not actually freed at this time.
+ * DESCRIPTION: Release a state object to the state cache. NULL state objects
+ * are ignored.
*
******************************************************************************/
void acpi_ut_delete_generic_state(union acpi_generic_state *state)
{
- ACPI_FUNCTION_TRACE("ut_delete_generic_state");
+ ACPI_FUNCTION_TRACE(ut_delete_generic_state);
+
+ /* Ignore null state */
- (void)acpi_os_release_object(acpi_gbl_state_cache, state);
+ if (state) {
+ (void)acpi_os_release_object(acpi_gbl_state_cache, state);
+ }
return_VOID;
}
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
index 308a960871b..3538f69c82a 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/utilities/utxface.c
@@ -41,8 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include <acpi/acevents.h>
#include <acpi/acnamesp.h>
@@ -67,7 +65,7 @@ acpi_status acpi_initialize_subsystem(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_initialize_subsystem");
+ ACPI_FUNCTION_TRACE(acpi_initialize_subsystem);
ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace());
@@ -109,6 +107,8 @@ acpi_status acpi_initialize_subsystem(void)
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem)
+
/*******************************************************************************
*
* FUNCTION: acpi_enable_subsystem
@@ -121,12 +121,11 @@ acpi_status acpi_initialize_subsystem(void)
* Puts system into ACPI mode if it isn't already.
*
******************************************************************************/
-
acpi_status acpi_enable_subsystem(u32 flags)
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("acpi_enable_subsystem");
+ ACPI_FUNCTION_TRACE(acpi_enable_subsystem);
/*
* We must initialize the hardware before we can enable ACPI.
@@ -152,7 +151,7 @@ acpi_status acpi_enable_subsystem(u32 flags)
status = acpi_enable();
if (ACPI_FAILURE(status)) {
- ACPI_WARNING((AE_INFO, "acpi_enable failed"));
+ ACPI_WARNING((AE_INFO, "AcpiEnable failed"));
return_ACPI_STATUS(status);
}
}
@@ -229,6 +228,8 @@ acpi_status acpi_enable_subsystem(u32 flags)
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_enable_subsystem)
+
/*******************************************************************************
*
* FUNCTION: acpi_initialize_objects
@@ -241,12 +242,11 @@ acpi_status acpi_enable_subsystem(u32 flags)
* objects and executing AML code for Regions, buffers, etc.
*
******************************************************************************/
-
acpi_status acpi_initialize_objects(u32 flags)
{
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("acpi_initialize_objects");
+ ACPI_FUNCTION_TRACE(acpi_initialize_objects);
/*
* Run all _REG methods
@@ -257,7 +257,7 @@ acpi_status acpi_initialize_objects(u32 flags)
*/
if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "[Init] Executing _REG op_region methods\n"));
+ "[Init] Executing _REG OpRegion methods\n"));
status = acpi_ev_initialize_op_regions();
if (ACPI_FAILURE(status)) {
@@ -305,6 +305,8 @@ acpi_status acpi_initialize_objects(u32 flags)
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_initialize_objects)
+
/*******************************************************************************
*
* FUNCTION: acpi_terminate
@@ -316,12 +318,11 @@ acpi_status acpi_initialize_objects(u32 flags)
* DESCRIPTION: Shutdown the ACPI subsystem. Release all resources.
*
******************************************************************************/
-
acpi_status acpi_terminate(void)
{
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_terminate");
+ ACPI_FUNCTION_TRACE(acpi_terminate);
/* Terminate the AML Debugger if present */
@@ -348,6 +349,8 @@ acpi_status acpi_terminate(void)
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_terminate)
+
#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
@@ -362,7 +365,6 @@ acpi_status acpi_terminate(void)
* initialized successfully.
*
******************************************************************************/
-
acpi_status acpi_subsystem_status(void)
{
@@ -373,6 +375,8 @@ acpi_status acpi_subsystem_status(void)
}
}
+ACPI_EXPORT_SYMBOL(acpi_subsystem_status)
+
/*******************************************************************************
*
* FUNCTION: acpi_get_system_info
@@ -390,14 +394,13 @@ acpi_status acpi_subsystem_status(void)
* and the value of out_buffer is undefined.
*
******************************************************************************/
-
acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer)
{
struct acpi_system_info *info_ptr;
acpi_status status;
u32 i;
- ACPI_FUNCTION_TRACE("acpi_get_system_info");
+ ACPI_FUNCTION_TRACE(acpi_get_system_info);
/* Parameter validation */
@@ -448,15 +451,15 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer)
/* Current status of the ACPI tables, per table type */
- info_ptr->num_table_types = NUM_ACPI_TABLE_TYPES;
- for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) {
+ info_ptr->num_table_types = ACPI_TABLE_ID_MAX + 1;
+ for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) {
info_ptr->table_info[i].count = acpi_gbl_table_lists[i].count;
}
return_ACPI_STATUS(AE_OK);
}
-EXPORT_SYMBOL(acpi_get_system_info);
+ACPI_EXPORT_SYMBOL(acpi_get_system_info)
/*****************************************************************************
*
@@ -472,7 +475,6 @@ EXPORT_SYMBOL(acpi_get_system_info);
* TBD: When a second function is added, must save the Function also.
*
****************************************************************************/
-
acpi_status
acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
{
@@ -489,6 +491,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
return AE_OK;
}
+ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler)
#endif /* ACPI_FUTURE_USAGE */
/*****************************************************************************
@@ -502,10 +505,9 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
* DESCRIPTION: Empty all caches (delete the cached objects)
*
****************************************************************************/
-
acpi_status acpi_purge_cached_objects(void)
{
- ACPI_FUNCTION_TRACE("acpi_purge_cached_objects");
+ ACPI_FUNCTION_TRACE(acpi_purge_cached_objects);
(void)acpi_os_purge_cache(acpi_gbl_state_cache);
(void)acpi_os_purge_cache(acpi_gbl_operand_cache);
@@ -513,3 +515,5 @@ acpi_status acpi_purge_cached_objects(void)
(void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache);
return_ACPI_STATUS(AE_OK);
}
+
+ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects)
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index 69f4c7ce9a6..cac09e353be 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -1972,7 +1972,7 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai)
"(itf %d): No suitable DMA available.\n", lanai->number);
return -EBUSY;
}
- if (pci_set_consistent_dma_mask(pci, 0xFFFFFFFF) != 0) {
+ if (pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) != 0) {
printk(KERN_WARNING DEV_LABEL
"(itf %d): No suitable DMA available.\n", lanai->number);
return -EBUSY;
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 48718b7f4fa..76656acd00d 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device_driver *drv,
up(&dev->sem);
if (dev->parent)
up(&dev->parent->sem);
+
+ if (err > 0) /* success */
+ err = count;
+ else if (err == 0) /* driver didn't accept device */
+ err = -ENODEV;
}
put_device(dev);
put_bus(bus);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index df7fdabd073..b1ea4df85c7 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -456,6 +456,35 @@ static void class_device_remove_attrs(struct class_device * cd)
}
}
+static int class_device_add_groups(struct class_device * cd)
+{
+ int i;
+ int error = 0;
+
+ if (cd->groups) {
+ for (i = 0; cd->groups[i]; i++) {
+ error = sysfs_create_group(&cd->kobj, cd->groups[i]);
+ if (error) {
+ while (--i >= 0)
+ sysfs_remove_group(&cd->kobj, cd->groups[i]);
+ goto out;
+ }
+ }
+ }
+out:
+ return error;
+}
+
+static void class_device_remove_groups(struct class_device * cd)
+{
+ int i;
+ if (cd->groups) {
+ for (i = 0; cd->groups[i]; i++) {
+ sysfs_remove_group(&cd->kobj, cd->groups[i]);
+ }
+ }
+}
+
static ssize_t show_dev(struct class_device *class_dev, char *buf)
{
return print_dev_t(buf, class_dev->devt);
@@ -559,17 +588,18 @@ int class_device_add(struct class_device *class_dev)
class_name);
}
+ class_device_add_groups(class_dev);
+
kobject_uevent(&class_dev->kobj, KOBJ_ADD);
/* notify any interfaces this device is now here */
- if (parent_class) {
- down(&parent_class->sem);
- list_add_tail(&class_dev->node, &parent_class->children);
- list_for_each_entry(class_intf, &parent_class->interfaces, node)
- if (class_intf->add)
- class_intf->add(class_dev, class_intf);
- up(&parent_class->sem);
+ down(&parent_class->sem);
+ list_add_tail(&class_dev->node, &parent_class->children);
+ list_for_each_entry(class_intf, &parent_class->interfaces, node) {
+ if (class_intf->add)
+ class_intf->add(class_dev, class_intf);
}
+ up(&parent_class->sem);
register_done:
if (error) {
@@ -673,6 +703,7 @@ void class_device_del(struct class_device *class_dev)
if (class_dev->devt_attr)
class_device_remove_file(class_dev, class_dev->devt_attr);
class_device_remove_attrs(class_dev);
+ class_device_remove_groups(class_dev);
kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);
kobject_del(&class_dev->kobj);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 730a9ce0a14..889c7111123 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -209,7 +209,7 @@ static void __device_release_driver(struct device * dev)
sysfs_remove_link(&dev->kobj, "driver");
klist_remove(&dev->knode_driver);
- if (dev->bus->remove)
+ if (dev->bus && dev->bus->remove)
dev->bus->remove(dev);
else if (drv->remove)
drv->remove(dev);
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 47231820523..0c99ae6a340 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -86,18 +86,9 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count)
static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
static void fw_class_dev_release(struct class_device *class_dev);
-int firmware_class_uevent(struct class_device *dev, char **envp,
- int num_envp, char *buffer, int buffer_size);
-static struct class firmware_class = {
- .name = "firmware",
- .uevent = firmware_class_uevent,
- .release = fw_class_dev_release,
-};
-
-int
-firmware_class_uevent(struct class_device *class_dev, char **envp,
- int num_envp, char *buffer, int buffer_size)
+static int firmware_class_uevent(struct class_device *class_dev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
{
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
int i = 0, len = 0;
@@ -116,6 +107,12 @@ firmware_class_uevent(struct class_device *class_dev, char **envp,
return 0;
}
+static struct class firmware_class = {
+ .name = "firmware",
+ .uevent = firmware_class_uevent,
+ .release = fw_class_dev_release,
+};
+
static ssize_t
firmware_loading_show(struct class_device *class_dev, char *buf)
{
@@ -493,25 +490,6 @@ release_firmware(const struct firmware *fw)
}
}
-/**
- * register_firmware: - provide a firmware image for later usage
- * @name: name of firmware image file
- * @data: buffer pointer for the firmware image
- * @size: size of the data buffer area
- *
- * Make sure that @data will be available by requesting firmware @name.
- *
- * Note: This will not be possible until some kind of persistence
- * is available.
- **/
-void
-register_firmware(const char *name, const u8 *data, size_t size)
-{
- /* This is meaningless without firmware caching, so until we
- * decide if firmware caching is reasonable just leave it as a
- * noop */
-}
-
/* Async support */
struct firmware_work {
struct work_struct work;
@@ -630,4 +608,3 @@ module_exit(firmware_class_exit);
EXPORT_SYMBOL(release_firmware);
EXPORT_SYMBOL(request_firmware);
EXPORT_SYMBOL(request_firmware_nowait);
-EXPORT_SYMBOL(register_firmware);
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 105a0d61eb1..dd547af4681 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -47,16 +47,16 @@ static struct kset_uevent_ops memory_uevent_ops = {
.uevent = memory_uevent,
};
-static struct notifier_block *memory_chain;
+static BLOCKING_NOTIFIER_HEAD(memory_chain);
int register_memory_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&memory_chain, nb);
+ return blocking_notifier_chain_register(&memory_chain, nb);
}
void unregister_memory_notifier(struct notifier_block *nb)
{
- notifier_chain_unregister(&memory_chain, nb);
+ blocking_notifier_chain_unregister(&memory_chain, nb);
}
/*
@@ -140,7 +140,7 @@ static ssize_t show_mem_state(struct sys_device *dev, char *buf)
static inline int memory_notify(unsigned long val, void *v)
{
- return notifier_call_chain(&memory_chain, val, v);
+ return blocking_notifier_call_chain(&memory_chain, val, v);
}
/*
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 16c513aa4d4..c80c3aeed00 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -106,7 +106,7 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
other_node = 0;
for (i = 0; i < MAX_NR_ZONES; i++) {
struct zone *z = &pg->node_zones[i];
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ for_each_online_cpu(cpu) {
struct per_cpu_pageset *ps = zone_pcp(z,cpu);
numa_hit += ps->numa_hit;
numa_miss += ps->numa_miss;
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index bdb60663f2e..2a769cc6f5f 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -8,8 +8,9 @@
*
*/
-#include <linux/vt_kern.h>
#include <linux/device.h>
+#include <linux/kallsyms.h>
+#include <linux/pm.h>
#include "../base.h"
#include "power.h"
@@ -58,11 +59,13 @@ int suspend_device(struct device * dev, pm_message_t state)
if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
dev_dbg(dev, "suspending\n");
error = dev->bus->suspend(dev, state);
+ suspend_report_result(dev->bus->suspend, error);
}
up(&dev->sem);
return error;
}
+
/**
* device_suspend - Save state and stop all devices in system.
* @state: Power state to put each device in.
@@ -82,9 +85,6 @@ int device_suspend(pm_message_t state)
{
int error = 0;
- if (!is_console_suspend_safe())
- return -EINVAL;
-
down(&dpm_sem);
down(&dpm_list_sem);
while (!list_empty(&dpm_active) && error == 0) {
@@ -169,3 +169,12 @@ int device_power_down(pm_message_t state)
EXPORT_SYMBOL_GPL(device_power_down);
+void __suspend_report_result(const char *function, void *fn, int ret)
+{
+ if (ret) {
+ printk(KERN_ERR "%s(): ", function);
+ print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn);
+ printk("%d\n", ret);
+ }
+}
+EXPORT_SYMBOL_GPL(__suspend_report_result);
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 915810f6237..8c52421cbc5 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -107,7 +107,7 @@ static int __cpuinit topology_remove_dev(struct sys_device * sys_dev)
return 0;
}
-static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
+static int topology_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 9bdea2a5cf0..45bcda54488 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -41,6 +41,7 @@
#include <linux/timer.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
#include <linux/random.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -311,11 +312,10 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
CommandsRemaining = CommandAllocationGroupSize;
CommandGroupByteCount =
CommandsRemaining * CommandAllocationLength;
- AllocationPointer = kmalloc(CommandGroupByteCount, GFP_ATOMIC);
+ AllocationPointer = kzalloc(CommandGroupByteCount, GFP_ATOMIC);
if (AllocationPointer == NULL)
return DAC960_Failure(Controller,
"AUXILIARY STRUCTURE CREATION");
- memset(AllocationPointer, 0, CommandGroupByteCount);
}
Command = (DAC960_Command_T *) AllocationPointer;
AllocationPointer += CommandAllocationLength;
@@ -2709,14 +2709,12 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
void __iomem *BaseAddress;
int i;
- Controller = (DAC960_Controller_T *)
- kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
+ Controller = kzalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
if (Controller == NULL) {
DAC960_Error("Unable to allocate Controller structure for "
"Controller at\n", NULL);
return NULL;
}
- memset(Controller, 0, sizeof(DAC960_Controller_T));
Controller->ControllerNumber = DAC960_ControllerCount;
DAC960_Controllers[DAC960_ControllerCount++] = Controller;
Controller->Bus = PCI_Device->bus->number;
@@ -3657,8 +3655,8 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
(NewEnquiry->EventLogSequenceNumber !=
OldEnquiry->EventLogSequenceNumber) ||
Controller->MonitoringTimerCount == 0 ||
- (jiffies - Controller->SecondaryMonitoringTime
- >= DAC960_SecondaryMonitoringInterval))
+ time_after_eq(jiffies, Controller->SecondaryMonitoringTime
+ + DAC960_SecondaryMonitoringInterval))
{
Controller->V1.NeedLogicalDriveInformation = true;
Controller->V1.NewEventLogSequenceNumber =
@@ -5643,8 +5641,8 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
unsigned int StatusChangeCounter =
Controller->V2.HealthStatusBuffer->StatusChangeCounter;
boolean ForceMonitoringCommand = false;
- if (jiffies - Controller->SecondaryMonitoringTime
- > DAC960_SecondaryMonitoringInterval)
+ if (time_after(jiffies, Controller->SecondaryMonitoringTime
+ + DAC960_SecondaryMonitoringInterval))
{
int LogicalDriveNumber;
for (LogicalDriveNumber = 0;
@@ -5672,8 +5670,8 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
ControllerInfo->ConsistencyChecksActive +
ControllerInfo->RebuildsActive +
ControllerInfo->OnlineExpansionsActive == 0 ||
- jiffies - Controller->PrimaryMonitoringTime
- < DAC960_MonitoringTimerInterval) &&
+ time_before(jiffies, Controller->PrimaryMonitoringTime
+ + DAC960_MonitoringTimerInterval)) &&
!ForceMonitoringCommand)
{
Controller->MonitoringTimer.expires =
@@ -5810,8 +5808,8 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel,
Controller->ProgressBufferLength = Length;
if (Controller->EphemeralProgressMessage)
{
- if (jiffies - Controller->LastProgressReportTime
- >= DAC960_ProgressReportingInterval)
+ if (time_after_eq(jiffies, Controller->LastProgressReportTime
+ + DAC960_ProgressReportingInterval))
{
printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
Controller->ControllerNumber, Buffer);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 875ae769902..ae0949b3394 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -383,8 +383,9 @@ config BLK_DEV_RAM
thus say N here.
config BLK_DEV_RAM_COUNT
- int "Default number of RAM disks" if BLK_DEV_RAM
+ int "Default number of RAM disks"
default "16"
+ depends on BLK_DEV_RAM
help
The default value is 16 RAM disks. Change this if you know what
are doing. If you boot from a filesystem that needs to be extracted
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index a5c1c8e871e..4cb9c133628 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -369,8 +369,6 @@ static ssize_t slm_read( struct file *file, char *buf, size_t count,
int length;
int end;
- if (count < 0)
- return( -EINVAL );
if (!(page = __get_free_page( GFP_KERNEL )))
return( -ENOMEM );
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index b6e29095621..2a8af685926 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1850,6 +1850,7 @@ static int __init amiga_floppy_setup (char *str)
return 0;
printk (KERN_INFO "amiflop: Setting default df0 to %x\n", n);
fd_def_df0 = n;
+ return 1;
}
__setup("floppy=", amiga_floppy_setup);
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 71ec9e66438..1319d8f2064 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -996,13 +996,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
status = -EINVAL;
goto cleanup1;
}
- buff = (unsigned char **) kmalloc(MAXSGENTRIES *
- sizeof(char *), GFP_KERNEL);
+ buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
if (!buff) {
status = -ENOMEM;
goto cleanup1;
}
- memset(buff, 0, MAXSGENTRIES);
buff_size = (int *) kmalloc(MAXSGENTRIES * sizeof(int),
GFP_KERNEL);
if (!buff_size) {
@@ -1182,6 +1180,53 @@ static int revalidate_allvol(ctlr_info_t *host)
return 0;
}
+static inline void complete_buffers(struct bio *bio, int status)
+{
+ while (bio) {
+ struct bio *xbh = bio->bi_next;
+ int nr_sectors = bio_sectors(bio);
+
+ bio->bi_next = NULL;
+ blk_finished_io(len);
+ bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
+ bio = xbh;
+ }
+
+}
+
+static void cciss_softirq_done(struct request *rq)
+{
+ CommandList_struct *cmd = rq->completion_data;
+ ctlr_info_t *h = hba[cmd->ctlr];
+ unsigned long flags;
+ u64bit temp64;
+ int i, ddir;
+
+ if (cmd->Request.Type.Direction == XFER_READ)
+ ddir = PCI_DMA_FROMDEVICE;
+ else
+ ddir = PCI_DMA_TODEVICE;
+
+ /* command did not need to be retried */
+ /* unmap the DMA mapping for all the scatter gather elements */
+ for(i=0; i<cmd->Header.SGList; i++) {
+ temp64.val32.lower = cmd->SG[i].Addr.lower;
+ temp64.val32.upper = cmd->SG[i].Addr.upper;
+ pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
+ }
+
+ complete_buffers(rq->bio, rq->errors);
+
+#ifdef CCISS_DEBUG
+ printk("Done with %p\n", rq);
+#endif /* CCISS_DEBUG */
+
+ spin_lock_irqsave(&h->lock, flags);
+ end_that_request_last(rq, rq->errors);
+ cmd_free(h, cmd,1);
+ spin_unlock_irqrestore(&h->lock, flags);
+}
+
/* This function will check the usage_count of the drive to be updated/added.
* If the usage_count is zero then the drive information will be updated and
* the disk will be re-registered with the kernel. If not then it will be
@@ -1250,6 +1295,8 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
blk_queue_max_sectors(disk->queue, 512);
+ blk_queue_softirq_done(disk->queue, cciss_softirq_done);
+
disk->queue->queuedata = hba[ctlr];
blk_queue_hardsect_size(disk->queue,
@@ -2149,20 +2196,6 @@ static void start_io( ctlr_info_t *h)
addQ (&(h->cmpQ), c);
}
}
-
-static inline void complete_buffers(struct bio *bio, int status)
-{
- while (bio) {
- struct bio *xbh = bio->bi_next;
- int nr_sectors = bio_sectors(bio);
-
- bio->bi_next = NULL;
- blk_finished_io(len);
- bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
- bio = xbh;
- }
-
-}
/* Assumes that CCISS_LOCK(h->ctlr) is held. */
/* Zeros out the error record and then resends the command back */
/* to the controller */
@@ -2180,39 +2213,6 @@ static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c)
start_io(h);
}
-static void cciss_softirq_done(struct request *rq)
-{
- CommandList_struct *cmd = rq->completion_data;
- ctlr_info_t *h = hba[cmd->ctlr];
- unsigned long flags;
- u64bit temp64;
- int i, ddir;
-
- if (cmd->Request.Type.Direction == XFER_READ)
- ddir = PCI_DMA_FROMDEVICE;
- else
- ddir = PCI_DMA_TODEVICE;
-
- /* command did not need to be retried */
- /* unmap the DMA mapping for all the scatter gather elements */
- for(i=0; i<cmd->Header.SGList; i++) {
- temp64.val32.lower = cmd->SG[i].Addr.lower;
- temp64.val32.upper = cmd->SG[i].Addr.upper;
- pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
- }
-
- complete_buffers(rq->bio, rq->errors);
-
-#ifdef CCISS_DEBUG
- printk("Done with %p\n", rq);
-#endif /* CCISS_DEBUG */
-
- spin_lock_irqsave(&h->lock, flags);
- end_that_request_last(rq, rq->errors);
- cmd_free(h, cmd,1);
- spin_unlock_irqrestore(&h->lock, flags);
-}
-
/* checks the status of the job and calls complete buffers to mark all
* buffers for the completed job. Note that this function does not need
* to hold the hba/queue lock.
@@ -2729,9 +2729,9 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *c, struct pci_dev *pdev,
return;
}
}
+default_int_mode:
#endif /* CONFIG_PCI_MSI */
/* if we get here we're going to use the default interrupt mode */
-default_int_mode:
c->intr[SIMPLE_MODE_INT] = pdev->irq;
return;
}
@@ -2940,13 +2940,12 @@ static void cciss_getgeometry(int cntl_num)
int block_size;
int total_size;
- ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
+ ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
if (ld_buff == NULL)
{
printk(KERN_ERR "cciss: out of memory\n");
return;
}
- memset(ld_buff, 0, sizeof(ReportLunData_struct));
size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
if (size_buff == NULL)
{
@@ -3060,10 +3059,9 @@ static int alloc_cciss_hba(void)
for(i=0; i< MAX_CTLR; i++) {
if (!hba[i]) {
ctlr_info_t *p;
- p = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
+ p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL);
if (!p)
goto Enomem;
- memset(p, 0, sizeof(ctlr_info_t));
for (n = 0; n < NWD; n++)
p->gendisk[n] = disk[n];
hba[i] = p;
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 0e66e904bd8..597c007fe81 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -1027,12 +1027,11 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
int i;
c = (ctlr_info_t *) hba[cntl_num];
- ld_buff = kmalloc(reportlunsize, GFP_KERNEL);
+ ld_buff = kzalloc(reportlunsize, GFP_KERNEL);
if (ld_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
return;
}
- memset(ld_buff, 0, reportlunsize);
inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
if (inq_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index d3ad9081697..dff1e67b1dd 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -170,6 +170,7 @@ static int print_unex = 1;
#include <linux/mm.h>
#include <linux/bio.h>
#include <linux/string.h>
+#include <linux/jiffies.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/mc146818rtc.h> /* CMOS defines */
@@ -747,7 +748,7 @@ static int disk_change(int drive)
{
int fdc = FDC(drive);
#ifdef FLOPPY_SANITY_CHECK
- if (jiffies - UDRS->select_date < UDP->select_delay)
+ if (time_before(jiffies, UDRS->select_date + UDP->select_delay))
DPRINT("WARNING disk change called early\n");
if (!(FDCS->dor & (0x10 << UNIT(drive))) ||
(FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) {
@@ -1075,7 +1076,7 @@ static int fd_wait_for_completion(unsigned long delay, timeout_fn function)
return 1;
}
- if ((signed)(jiffies - delay) < 0) {
+ if (time_before(jiffies, delay)) {
del_timer(&fd_timer);
fd_timer.function = function;
fd_timer.expires = delay;
@@ -1535,7 +1536,7 @@ static void setup_rw_floppy(void)
* again just before spinup completion. Beware that
* after scandrives, we must again wait for selection.
*/
- if ((signed)(ready_date - jiffies) > DP->select_delay) {
+ if (time_after(ready_date, jiffies + DP->select_delay)) {
ready_date -= DP->select_delay;
function = (timeout_fn) floppy_start;
} else
@@ -3823,7 +3824,7 @@ static int check_floppy_change(struct gendisk *disk)
if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
return 1;
- if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) {
+ if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
if (floppy_grab_irq_and_dma()) {
return 1;
}
@@ -4300,7 +4301,7 @@ static int __init floppy_init(void)
}
use_virtual_dma = can_use_virtual_dma & 1;
-#if defined(CONFIG_PPC64)
+#if defined(CONFIG_PPC_MERGE)
if (check_legacy_ioport(FDC1)) {
del_timer(&fd_timeout);
err = -ENODEV;
diff --git a/drivers/block/paride/bpck6.c b/drivers/block/paride/bpck6.c
index 08d858ad64d..41a237c5957 100644
--- a/drivers/block/paride/bpck6.c
+++ b/drivers/block/paride/bpck6.c
@@ -224,10 +224,9 @@ static void bpck6_log_adapter( PIA *pi, char * scratch, int verbose )
static int bpck6_init_proto(PIA *pi)
{
- Interface *p = kmalloc(sizeof(Interface), GFP_KERNEL);
+ Interface *p = kzalloc(sizeof(Interface), GFP_KERNEL);
if (p) {
- memset(p, 0, sizeof(Interface));
pi->private = (unsigned long)p;
return 0;
}
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 62d2464c12f..2403721f9db 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -151,6 +151,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV};
#include <linux/cdrom.h> /* for the eject ioctl */
#include <linux/blkdev.h>
#include <linux/blkpg.h>
+#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/sched.h>
#include <linux/workqueue.h>
@@ -275,7 +276,7 @@ static void pd_print_error(struct pd_unit *disk, char *msg, int status)
int i;
printk("%s: %s: status = 0x%x =", disk->name, msg, status);
- for (i = 0; i < 18; i++)
+ for (i = 0; i < ARRAY_SIZE(pd_errs); i++)
if (status & (1 << i))
printk(" %s", pd_errs[i]);
printk("\n");
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 6f5df0fad70..79b86825403 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -643,7 +643,8 @@ static ssize_t pg_read(struct file *filp, char __user *buf, size_t count, loff_t
static int __init pg_init(void)
{
- int unit, err = 0;
+ int unit;
+ int err;
if (disable){
err = -1;
@@ -657,16 +658,17 @@ static int __init pg_init(void)
goto out;
}
- if (register_chrdev(major, name, &pg_fops)) {
+ err = register_chrdev(major, name, &pg_fops);
+ if (err < 0) {
printk("pg_init: unable to get major number %d\n", major);
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present)
pi_release(dev->pi);
}
- err = -1;
goto out;
}
+ major = err; /* In case the user specified `major=0' (dynamic) */
pg_class = class_create(THIS_MODULE, "pg");
if (IS_ERR(pg_class)) {
err = PTR_ERR(pg_class);
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 715ae5dc88f..d2013d36240 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -943,7 +943,8 @@ static ssize_t pt_write(struct file *filp, const char __user *buf, size_t count,
static int __init pt_init(void)
{
- int unit, err = 0;
+ int unit;
+ int err;
if (disable) {
err = -1;
@@ -955,14 +956,15 @@ static int __init pt_init(void)
goto out;
}
- if (register_chrdev(major, name, &pt_fops)) {
+ err = register_chrdev(major, name, &pt_fops);
+ if (err < 0) {
printk("pt_init: unable to get major number %d\n", major);
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present)
pi_release(pt[unit].pi);
- err = -1;
goto out;
}
+ major = err;
pt_class = class_create(THIS_MODULE, "pt");
if (IS_ERR(pt_class)) {
err = PTR_ERR(pt_class);
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index f73446f580d..c688c25992e 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -536,6 +536,9 @@ static void ub_cleanup(struct ub_dev *sc)
kfree(lun);
}
+ usb_set_intfdata(sc->intf, NULL);
+ usb_put_intf(sc->intf);
+ usb_put_dev(sc->dev);
kfree(sc);
}
@@ -2221,7 +2224,12 @@ static int ub_probe(struct usb_interface *intf,
// sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
usb_set_intfdata(intf, sc);
usb_get_dev(sc->dev);
- // usb_get_intf(sc->intf); /* Do we need this? */
+ /*
+ * Since we give the interface struct to the block level through
+ * disk->driverfs_dev, we have to pin it. Otherwise, block_uevent
+ * oopses on close after a disconnect (kernels 2.6.16 and up).
+ */
+ usb_get_intf(sc->intf);
snprintf(sc->name, 12, DRV_NAME "(%d.%d)",
sc->dev->bus->busnum, sc->dev->devnum);
@@ -2286,7 +2294,7 @@ static int ub_probe(struct usb_interface *intf,
err_dev_desc:
usb_set_intfdata(intf, NULL);
- // usb_put_intf(sc->intf);
+ usb_put_intf(sc->intf);
usb_put_dev(sc->dev);
kfree(sc);
err_core:
@@ -2461,12 +2469,6 @@ static void ub_disconnect(struct usb_interface *intf)
* and no URBs left in transit.
*/
- usb_set_intfdata(intf, NULL);
- // usb_put_intf(sc->intf);
- sc->intf = NULL;
- usb_put_dev(sc->dev);
- sc->dev = NULL;
-
ub_put(sc);
}
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index c16e66b9c7a..f7d4c65a7b8 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -50,6 +50,7 @@
#include <linux/timer.h>
#include <linux/pci.h>
#include <linux/slab.h>
+#include <linux/dma-mapping.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/hdreg.h> /* HDIO_GETGEO */
@@ -881,8 +882,8 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
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);
- if (pci_set_dma_mask(dev, 0xffffffffffffffffLL) &&
- pci_set_dma_mask(dev, 0xffffffffLL)) {
+ if (pci_set_dma_mask(dev, DMA_64BIT_MASK) &&
+ pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards);
return -ENOMEM;
}
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 9888bc15175..473a13b22b2 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -65,7 +65,7 @@ MODULE_LICENSE("GPL");
typedef struct bluecard_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct hci_dev *hdev;
@@ -85,8 +85,8 @@ typedef struct bluecard_info_t {
} bluecard_info_t;
-static void bluecard_config(dev_link_t *link);
-static void bluecard_release(dev_link_t *link);
+static int bluecard_config(struct pcmcia_device *link);
+static void bluecard_release(struct pcmcia_device *link);
static void bluecard_detach(struct pcmcia_device *p_dev);
@@ -162,7 +162,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev);
static void bluecard_activity_led_timeout(u_long arg)
{
bluecard_info_t *info = (bluecard_info_t *)arg;
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
return;
@@ -179,7 +179,7 @@ static void bluecard_activity_led_timeout(u_long arg)
static void bluecard_enable_activity_led(bluecard_info_t *info)
{
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
return;
@@ -235,7 +235,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
}
do {
- register unsigned int iobase = info->link.io.BasePort1;
+ register unsigned int iobase = info->p_dev->io.BasePort1;
register unsigned int offset;
register unsigned char command;
register unsigned long ready_bit;
@@ -244,7 +244,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
clear_bit(XMIT_WAKEUP, &(info->tx_state));
- if (!(info->link.state & DEV_PRESENT))
+ if (!pcmcia_dev_present(info->p_dev))
return;
if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) {
@@ -382,7 +382,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
return;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
if (test_bit(XMIT_SENDING_READY, &(info->tx_state)))
bluecard_enable_activity_led(info);
@@ -512,7 +512,7 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst, struct pt_regs *r
if (!test_bit(CARD_READY, &(info->hw_state)))
return IRQ_HANDLED;
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
spin_lock(&(info->lock));
@@ -626,7 +626,7 @@ static int bluecard_hci_flush(struct hci_dev *hdev)
static int bluecard_hci_open(struct hci_dev *hdev)
{
bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
@@ -646,7 +646,7 @@ static int bluecard_hci_open(struct hci_dev *hdev)
static int bluecard_hci_close(struct hci_dev *hdev)
{
bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
@@ -713,7 +713,7 @@ static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned l
static int bluecard_open(bluecard_info_t *info)
{
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
struct hci_dev *hdev;
unsigned char id;
@@ -831,7 +831,7 @@ static int bluecard_open(bluecard_info_t *info)
static int bluecard_close(bluecard_info_t *info)
{
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
struct hci_dev *hdev = info->hdev;
if (!hdev)
@@ -856,17 +856,16 @@ static int bluecard_close(bluecard_info_t *info)
return 0;
}
-static int bluecard_attach(struct pcmcia_device *p_dev)
+static int bluecard_probe(struct pcmcia_device *link)
{
bluecard_info_t *info;
- dev_link_t *link;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -878,32 +877,22 @@ static int bluecard_attach(struct pcmcia_device *p_dev)
link->irq.Instance = info;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- bluecard_config(link);
-
- return 0;
+ return bluecard_config(link);
}
-static void bluecard_detach(struct pcmcia_device *p_dev)
+static void bluecard_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
bluecard_info_t *info = link->priv;
- if (link->state & DEV_CONFIG)
- bluecard_release(link);
-
+ bluecard_release(link);
kfree(info);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int i;
@@ -918,14 +907,12 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static void bluecard_config(dev_link_t *link)
+static int bluecard_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
bluecard_info_t *info = link->priv;
tuple_t tuple;
u_short buf[256];
cisparse_t parse;
- config_info_t config;
int i, n, last_ret, last_fn;
tuple.TupleData = (cisdata_t *)buf;
@@ -935,7 +922,7 @@ static void bluecard_config(dev_link_t *link)
/* Get configuration register information */
tuple.DesiredTuple = CISTPL_CONFIG;
- last_ret = first_tuple(handle, &tuple, &parse);
+ last_ret = first_tuple(link, &tuple, &parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -943,36 +930,31 @@ static void bluecard_config(dev_link_t *link)
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
- i = pcmcia_get_configuration_info(handle, &config);
- link->conf.Vcc = config.Vcc;
-
link->conf.ConfigIndex = 0x20;
link->io.NumPorts1 = 64;
link->io.IOAddrLines = 6;
for (n = 0; n < 0x400; n += 0x40) {
link->io.BasePort1 = n ^ 0x300;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
goto failed;
}
@@ -980,57 +962,28 @@ static void bluecard_config(dev_link_t *link)
goto failed;
strcpy(info->node.dev_name, info->hdev->name);
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &info->node;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
bluecard_release(link);
+ return -ENODEV;
}
-static void bluecard_release(dev_link_t *link)
+static void bluecard_release(struct pcmcia_device *link)
{
bluecard_info_t *info = link->priv;
- if (link->state & DEV_PRESENT)
- bluecard_close(info);
+ bluecard_close(info);
del_timer(&(info->timer));
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-}
-
-static int bluecard_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int bluecard_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
+ pcmcia_disable_device(link);
}
static struct pcmcia_device_id bluecard_ids[] = {
@@ -1046,11 +999,9 @@ static struct pcmcia_driver bluecard_driver = {
.drv = {
.name = "bluecard_cs",
},
- .probe = bluecard_attach,
+ .probe = bluecard_probe,
.remove = bluecard_detach,
.id_table = bluecard_ids,
- .suspend = bluecard_suspend,
- .resume = bluecard_resume,
};
static int __init init_bluecard_cs(void)
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 7e21b1ff27c..b94ac2f9f7b 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -72,7 +72,7 @@ MODULE_LICENSE("GPL");
typedef struct bt3c_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct hci_dev *hdev;
@@ -88,8 +88,8 @@ typedef struct bt3c_info_t {
} bt3c_info_t;
-static void bt3c_config(dev_link_t *link);
-static void bt3c_release(dev_link_t *link);
+static int bt3c_config(struct pcmcia_device *link);
+static void bt3c_release(struct pcmcia_device *link);
static void bt3c_detach(struct pcmcia_device *p_dev);
@@ -191,11 +191,11 @@ static void bt3c_write_wakeup(bt3c_info_t *info)
return;
do {
- register unsigned int iobase = info->link.io.BasePort1;
+ register unsigned int iobase = info->p_dev->io.BasePort1;
register struct sk_buff *skb;
register int len;
- if (!(info->link.state & DEV_PRESENT))
+ if (!pcmcia_dev_present(info->p_dev))
break;
@@ -229,7 +229,7 @@ static void bt3c_receive(bt3c_info_t *info)
return;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
avail = bt3c_read(iobase, 0x7006);
//printk("bt3c_cs: receiving %d bytes\n", avail);
@@ -350,7 +350,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
return IRQ_NONE;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
spin_lock(&(info->lock));
@@ -481,7 +481,7 @@ static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int co
unsigned int iobase, size, addr, fcs, tmp;
int i, err = 0;
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
/* Reset */
bt3c_io_write(iobase, 0x8040, 0x0404);
@@ -562,7 +562,6 @@ static int bt3c_open(bt3c_info_t *info)
{
const struct firmware *firmware;
struct hci_dev *hdev;
- client_handle_t handle;
int err;
spin_lock_init(&(info->lock));
@@ -594,10 +593,8 @@ static int bt3c_open(bt3c_info_t *info)
hdev->owner = THIS_MODULE;
- handle = info->link.handle;
-
/* Load firmware */
- err = request_firmware(&firmware, "BT3CPCC.bin", &handle_to_dev(handle));
+ err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev);
if (err < 0) {
BT_ERR("Firmware request failed");
goto error;
@@ -648,17 +645,16 @@ static int bt3c_close(bt3c_info_t *info)
return 0;
}
-static int bt3c_attach(struct pcmcia_device *p_dev)
+static int bt3c_probe(struct pcmcia_device *link)
{
bt3c_info_t *info;
- dev_link_t *link;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -670,31 +666,21 @@ static int bt3c_attach(struct pcmcia_device *p_dev)
link->irq.Instance = info;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- bt3c_config(link);
-
- return 0;
+ return bt3c_config(link);
}
-static void bt3c_detach(struct pcmcia_device *p_dev)
+static void bt3c_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
bt3c_info_t *info = link->priv;
- if (link->state & DEV_CONFIG)
- bt3c_release(link);
-
+ bt3c_release(link);
kfree(info);
}
-static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int i;
@@ -705,30 +691,28 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
return get_tuple(handle, tuple, parse);
}
-static void bt3c_config(dev_link_t *link)
+static int bt3c_config(struct pcmcia_device *link)
{
static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
- client_handle_t handle = link->handle;
bt3c_info_t *info = link->priv;
tuple_t tuple;
u_short buf[256];
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
- config_info_t config;
int i, j, try, last_ret, last_fn;
tuple.TupleData = (cisdata_t *)buf;
@@ -738,7 +722,7 @@ static void bt3c_config(dev_link_t *link)
/* Get configuration register information */
tuple.DesiredTuple = CISTPL_CONFIG;
- last_ret = first_tuple(handle, &tuple, &parse);
+ last_ret = first_tuple(link, &tuple, &parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -746,11 +730,6 @@ static void bt3c_config(dev_link_t *link)
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
- i = pcmcia_get_configuration_info(handle, &config);
- link->conf.Vcc = config.Vcc;
-
/* First pass: look for a config entry that looks normal. */
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0;
@@ -759,59 +738,59 @@ static void bt3c_config(dev_link_t *link)
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
/* Two tries: without IO aliases, then with aliases */
for (try = 0; try < 2; try++) {
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i != CS_NO_MORE_ITEMS) {
if (i != CS_SUCCESS)
goto next_entry;
if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
next_entry:
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
}
/* Second pass: try to find an entry that isn't picky about
its base address, then try to grab any standard serial port
address, and finally try to get any free port. */
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i != CS_NO_MORE_ITEMS) {
if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
link->conf.ConfigIndex = cf->index;
for (j = 0; j < 5; j++) {
link->io.BasePort1 = base[j];
link->io.IOAddrLines = base[j] ? 16 : 3;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
found_port:
if (i != CS_SUCCESS) {
BT_ERR("No usable port range found");
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
goto failed;
}
@@ -819,55 +798,26 @@ found_port:
goto failed;
strcpy(info->node.dev_name, info->hdev->name);
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &info->node;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
bt3c_release(link);
+ return -ENODEV;
}
-static void bt3c_release(dev_link_t *link)
+static void bt3c_release(struct pcmcia_device *link)
{
bt3c_info_t *info = link->priv;
- if (link->state & DEV_PRESENT)
- bt3c_close(info);
-
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-}
-
-static int bt3c_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
+ bt3c_close(info);
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int bt3c_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
+ pcmcia_disable_device(link);
}
@@ -882,11 +832,9 @@ static struct pcmcia_driver bt3c_driver = {
.drv = {
.name = "bt3c_cs",
},
- .probe = bt3c_attach,
+ .probe = bt3c_probe,
.remove = bt3c_detach,
.id_table = bt3c_ids,
- .suspend = bt3c_suspend,
- .resume = bt3c_resume,
};
static int __init init_bt3c_cs(void)
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 7b4bff4cfa2..9ce4c93467e 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -68,7 +68,7 @@ MODULE_LICENSE("GPL");
typedef struct btuart_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct hci_dev *hdev;
@@ -84,8 +84,8 @@ typedef struct btuart_info_t {
} btuart_info_t;
-static void btuart_config(dev_link_t *link);
-static void btuart_release(dev_link_t *link);
+static int btuart_config(struct pcmcia_device *link);
+static void btuart_release(struct pcmcia_device *link);
static void btuart_detach(struct pcmcia_device *p_dev);
@@ -146,13 +146,13 @@ static void btuart_write_wakeup(btuart_info_t *info)
}
do {
- register unsigned int iobase = info->link.io.BasePort1;
+ register unsigned int iobase = info->p_dev->io.BasePort1;
register struct sk_buff *skb;
register int len;
clear_bit(XMIT_WAKEUP, &(info->tx_state));
- if (!(info->link.state & DEV_PRESENT))
+ if (!pcmcia_dev_present(info->p_dev))
return;
if (!(skb = skb_dequeue(&(info->txq))))
@@ -187,7 +187,7 @@ static void btuart_receive(btuart_info_t *info)
return;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
do {
info->hdev->stat.byte_rx++;
@@ -301,7 +301,7 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst, struct pt_regs *reg
return IRQ_NONE;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
spin_lock(&(info->lock));
@@ -357,7 +357,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
return;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
spin_lock_irqsave(&(info->lock), flags);
@@ -481,7 +481,7 @@ static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned lon
static int btuart_open(btuart_info_t *info)
{
unsigned long flags;
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
struct hci_dev *hdev;
spin_lock_init(&(info->lock));
@@ -550,7 +550,7 @@ static int btuart_open(btuart_info_t *info)
static int btuart_close(btuart_info_t *info)
{
unsigned long flags;
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
struct hci_dev *hdev = info->hdev;
if (!hdev)
@@ -576,17 +576,16 @@ static int btuart_close(btuart_info_t *info)
return 0;
}
-static int btuart_attach(struct pcmcia_device *p_dev)
+static int btuart_probe(struct pcmcia_device *link)
{
btuart_info_t *info;
- dev_link_t *link;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -598,31 +597,21 @@ static int btuart_attach(struct pcmcia_device *p_dev)
link->irq.Instance = info;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- btuart_config(link);
-
- return 0;
+ return btuart_config(link);
}
-static void btuart_detach(struct pcmcia_device *p_dev)
+static void btuart_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
btuart_info_t *info = link->priv;
- if (link->state & DEV_CONFIG)
- btuart_release(link);
-
+ btuart_release(link);
kfree(info);
}
-static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int i;
@@ -633,30 +622,28 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
return get_tuple(handle, tuple, parse);
}
-static void btuart_config(dev_link_t *link)
+static int btuart_config(struct pcmcia_device *link)
{
static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
- client_handle_t handle = link->handle;
btuart_info_t *info = link->priv;
tuple_t tuple;
u_short buf[256];
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
- config_info_t config;
int i, j, try, last_ret, last_fn;
tuple.TupleData = (cisdata_t *)buf;
@@ -666,7 +653,7 @@ static void btuart_config(dev_link_t *link)
/* Get configuration register information */
tuple.DesiredTuple = CISTPL_CONFIG;
- last_ret = first_tuple(handle, &tuple, &parse);
+ last_ret = first_tuple(link, &tuple, &parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -674,11 +661,6 @@ static void btuart_config(dev_link_t *link)
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
- i = pcmcia_get_configuration_info(handle, &config);
- link->conf.Vcc = config.Vcc;
-
/* First pass: look for a config entry that looks normal. */
tuple.TupleData = (cisdata_t *) buf;
tuple.TupleOffset = 0;
@@ -687,29 +669,29 @@ static void btuart_config(dev_link_t *link)
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
/* Two tries: without IO aliases, then with aliases */
for (try = 0; try < 2; try++) {
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i != CS_NO_MORE_ITEMS) {
if (i != CS_SUCCESS)
goto next_entry;
if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
next_entry:
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
}
/* Second pass: try to find an entry that isn't picky about
its base address, then try to grab any standard serial port
address, and finally try to get any free port. */
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i != CS_NO_MORE_ITEMS) {
if ((i == CS_SUCCESS) && (cf->io.nwin > 0)
&& ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
@@ -717,30 +699,30 @@ next_entry:
for (j = 0; j < 5; j++) {
link->io.BasePort1 = base[j];
link->io.IOAddrLines = base[j] ? 16 : 3;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
found_port:
if (i != CS_SUCCESS) {
BT_ERR("No usable port range found");
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
goto failed;
}
@@ -748,58 +730,28 @@ found_port:
goto failed;
strcpy(info->node.dev_name, info->hdev->name);
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &info->node;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
btuart_release(link);
+ return -ENODEV;
}
-static void btuart_release(dev_link_t *link)
+static void btuart_release(struct pcmcia_device *link)
{
btuart_info_t *info = link->priv;
- if (link->state & DEV_PRESENT)
- btuart_close(info);
-
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-}
-
-static int btuart_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
+ btuart_close(info);
- return 0;
+ pcmcia_disable_device(link);
}
-static int btuart_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
-}
-
-
static struct pcmcia_device_id btuart_ids[] = {
/* don't use this driver. Use serial_cs + hci_uart instead */
PCMCIA_DEVICE_NULL
@@ -811,11 +763,9 @@ static struct pcmcia_driver btuart_driver = {
.drv = {
.name = "btuart_cs",
},
- .probe = btuart_attach,
+ .probe = btuart_probe,
.remove = btuart_detach,
.id_table = btuart_ids,
- .suspend = btuart_suspend,
- .resume = btuart_resume,
};
static int __init init_btuart_cs(void)
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 0449bc45ae5..a71a240611e 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -68,7 +68,7 @@ MODULE_LICENSE("GPL");
typedef struct dtl1_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct hci_dev *hdev;
@@ -87,8 +87,8 @@ typedef struct dtl1_info_t {
} dtl1_info_t;
-static void dtl1_config(dev_link_t *link);
-static void dtl1_release(dev_link_t *link);
+static int dtl1_config(struct pcmcia_device *link);
+static void dtl1_release(struct pcmcia_device *link);
static void dtl1_detach(struct pcmcia_device *p_dev);
@@ -153,13 +153,13 @@ static void dtl1_write_wakeup(dtl1_info_t *info)
}
do {
- register unsigned int iobase = info->link.io.BasePort1;
+ register unsigned int iobase = info->p_dev->io.BasePort1;
register struct sk_buff *skb;
register int len;
clear_bit(XMIT_WAKEUP, &(info->tx_state));
- if (!(info->link.state & DEV_PRESENT))
+ if (!pcmcia_dev_present(info->p_dev))
return;
if (!(skb = skb_dequeue(&(info->txq))))
@@ -218,7 +218,7 @@ static void dtl1_receive(dtl1_info_t *info)
return;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
do {
info->hdev->stat.byte_rx++;
@@ -305,7 +305,7 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
return IRQ_NONE;
}
- iobase = info->link.io.BasePort1;
+ iobase = info->p_dev->io.BasePort1;
spin_lock(&(info->lock));
@@ -458,7 +458,7 @@ static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long
static int dtl1_open(dtl1_info_t *info)
{
unsigned long flags;
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
struct hci_dev *hdev;
spin_lock_init(&(info->lock));
@@ -504,7 +504,7 @@ static int dtl1_open(dtl1_info_t *info)
outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */
outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
- info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI;
+ info->ri_latch = inb(info->p_dev->io.BasePort1 + UART_MSR) & UART_MSR_RI;
/* Turn on interrupts */
outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
@@ -529,7 +529,7 @@ static int dtl1_open(dtl1_info_t *info)
static int dtl1_close(dtl1_info_t *info)
{
unsigned long flags;
- unsigned int iobase = info->link.io.BasePort1;
+ unsigned int iobase = info->p_dev->io.BasePort1;
struct hci_dev *hdev = info->hdev;
if (!hdev)
@@ -555,17 +555,16 @@ static int dtl1_close(dtl1_info_t *info)
return 0;
}
-static int dtl1_attach(struct pcmcia_device *p_dev)
+static int dtl1_probe(struct pcmcia_device *link)
{
dtl1_info_t *info;
- dev_link_t *link;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -577,31 +576,22 @@ static int dtl1_attach(struct pcmcia_device *p_dev)
link->irq.Instance = info;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- dtl1_config(link);
-
- return 0;
+ return dtl1_config(link);
}
-static void dtl1_detach(struct pcmcia_device *p_dev)
+static void dtl1_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
dtl1_info_t *info = link->priv;
- if (link->state & DEV_CONFIG)
- dtl1_release(link);
+ dtl1_release(link);
kfree(info);
}
-static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int i;
@@ -612,29 +602,27 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
return get_tuple(handle, tuple, parse);
}
-static void dtl1_config(dev_link_t *link)
+static int dtl1_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
dtl1_info_t *info = link->priv;
tuple_t tuple;
u_short buf[256];
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
- config_info_t config;
int i, last_ret, last_fn;
tuple.TupleData = (cisdata_t *)buf;
@@ -644,7 +632,7 @@ static void dtl1_config(dev_link_t *link)
/* Get configuration register information */
tuple.DesiredTuple = CISTPL_CONFIG;
- last_ret = first_tuple(handle, &tuple, &parse);
+ last_ret = first_tuple(link, &tuple, &parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -652,11 +640,6 @@ static void dtl1_config(dev_link_t *link)
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
- i = pcmcia_get_configuration_info(handle, &config);
- link->conf.Vcc = config.Vcc;
-
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0;
tuple.TupleDataMax = 255;
@@ -665,34 +648,34 @@ static void dtl1_config(dev_link_t *link)
/* Look for a generic full-sized window */
link->io.NumPorts1 = 8;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i != CS_NO_MORE_ITEMS) {
if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.NumPorts1 = cf->io.win[0].len; /*yo */
link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
goto failed;
}
@@ -700,55 +683,26 @@ static void dtl1_config(dev_link_t *link)
goto failed;
strcpy(info->node.dev_name, info->hdev->name);
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &info->node;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
dtl1_release(link);
+ return -ENODEV;
}
-static void dtl1_release(dev_link_t *link)
+static void dtl1_release(struct pcmcia_device *link)
{
dtl1_info_t *info = link->priv;
- if (link->state & DEV_PRESENT)
- dtl1_close(info);
-
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-}
-
-static int dtl1_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int dtl1_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
+ dtl1_close(info);
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
+ pcmcia_disable_device(link);
}
@@ -765,11 +719,9 @@ static struct pcmcia_driver dtl1_driver = {
.drv = {
.name = "dtl1_cs",
},
- .probe = dtl1_attach,
+ .probe = dtl1_probe,
.remove = dtl1_detach,
.id_table = dtl1_ids,
- .suspend = dtl1_suspend,
- .resume = dtl1_resume,
};
static int __init init_dtl1_cs(void)
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
index ce4a1ce59d6..ec004897b63 100644
--- a/drivers/cdrom/aztcd.c
+++ b/drivers/cdrom/aztcd.c
@@ -1763,7 +1763,7 @@ static int __init aztcd_init(void)
release_region(azt_port, 4);
}
}
- if ((azt_port_auto[i] == 0) || (i == 16)) {
+ if ((i == 16) || (azt_port_auto[i] == 0)) {
printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n");
return -EIO;
}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index facc3f1d9e3..78d928f9d9f 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -291,7 +291,7 @@ config SX
config RIO
tristate "Specialix RIO system support"
- depends on SERIAL_NONSTANDARD && !64BIT
+ depends on SERIAL_NONSTANDARD
help
This is a driver for the Specialix RIO, a smart serial card which
drives an outboard box that can support up to 128 ports. Product
@@ -561,14 +561,31 @@ config TIPAR
If unsure, say N.
+config HVC_DRIVER
+ bool
+ help
+ Users of pSeries machines that want to utilize the hvc console front-end
+ module for their backend console driver should select this option.
+ It will automatically be selected if one of the back-end console drivers
+ is selected.
+
+
config HVC_CONSOLE
bool "pSeries Hypervisor Virtual Console support"
depends on PPC_PSERIES
+ select HVC_DRIVER
help
pSeries machines when partitioned support a hypervisor virtual
console. This driver allows each pSeries partition to have a console
which is accessed via the HMC.
+config HVC_RTAS
+ bool "IBM RTAS Console support"
+ depends on PPC_RTAS
+ select HVC_DRIVER
+ help
+ IBM Console device driver which makes use of RTAS
+
config HVCS
tristate "IBM Hypervisor Virtual Console Server support"
depends on PPC_PSERIES
@@ -696,7 +713,7 @@ config NVRAM
config RTC
tristate "Enhanced Real Time Clock Support"
- depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV
+ depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -788,10 +805,6 @@ config S3C2410_RTC
Samsung S3C2410. This can provide periodic interrupt rates
from 1Hz to 64Hz for user programs, and wakeup from Alarm.
-config RTC_VR41XX
- tristate "NEC VR4100 series Real Time Clock Support"
- depends on CPU_VR41XX
-
config COBALT_LCD
bool "Support for Cobalt LCD"
depends on MIPS_COBALT
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index b2a11245fa9..fb919bfb282 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -41,7 +41,9 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
obj-$(CONFIG_SX) += sx.o generic_serial.o
obj-$(CONFIG_RIO) += rio/ generic_serial.o
-obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvc_vio.o hvsi.o
+obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o
+obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o
+obj-$(CONFIG_HVC_DRIVER) += hvc_console.o
obj-$(CONFIG_RAW_DRIVER) += raw.o
obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
obj-$(CONFIG_MMTIMER) += mmtimer.o
@@ -65,7 +67,6 @@ obj-$(CONFIG_SGI_DS1286) += ds1286.o
obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
obj-$(CONFIG_DS1302) += ds1302.o
obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o
-obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o
ifeq ($(CONFIG_GENERIC_NVRAM),y)
obj-$(CONFIG_NVRAM) += generic_nvram.o
else
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 0b9cf9c59a2..7c88c060a9e 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -86,7 +86,7 @@ config AGP_NVIDIA
config AGP_SIS
tristate "SiS chipset support"
- depends on AGP && X86_32
+ depends on AGP
help
This option gives you AGP support for the GLX component of
X on Silicon Integrated Systems [SiS] chipsets.
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 36517d4d1ad..ac3c33a2e37 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -617,6 +617,9 @@ static int agp_amd64_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
+ if (pdev->vendor == PCI_VENDOR_ID_NVIDIA)
+ nforce3_agp_init(pdev);
+
return amd_8151_configure();
}
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index fed0a87448d..86a966b6523 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -64,6 +64,12 @@ static struct gatt_mask efficeon_generic_masks[] =
{.mask = 0x00000001, .type = 0}
};
+/* This function does the same thing as mask_memory() for this chipset... */
+static inline unsigned long efficeon_mask_memory(unsigned long addr)
+{
+ return addr | 0x00000001;
+}
+
static struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
{
{256, 65536, 0},
@@ -251,7 +257,7 @@ static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int t
last_page = NULL;
for (i = 0; i < count; i++) {
int index = pg_start + i;
- unsigned long insert = mem->memory[i];
+ unsigned long insert = efficeon_mask_memory(mem->memory[i]);
page = (unsigned int *) efficeon_private.l1_table[index >> 10];
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 8c4c6ef748e..907fb66ec4a 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -497,7 +497,7 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret)
info = buffer.pointer;
info->hardware_id.value[sizeof(info->hardware_id)-1] = '\0';
match = (strcmp(info->hardware_id.value, "HWP0001") == 0);
- ACPI_MEM_FREE(info);
+ kfree(info);
if (match) {
status = hp_acpi_csr_space(handle, &sba_hpa, &length);
if (ACPI_SUCCESS(status))
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index 70b8ed9cd17..4c67135c12d 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -11,6 +11,7 @@
#include <linux/gfp.h>
#include <linux/page-flags.h>
#include <linux/mm.h>
+#include <linux/jiffies.h>
#include "agp.h"
/* NVIDIA registers */
@@ -256,7 +257,7 @@ static void nvidia_tlbflush(struct agp_memory *mem)
do {
pci_read_config_dword(nvidia_private.dev_1,
NVIDIA_1_WBC, &wbc_reg);
- if ((signed)(end - jiffies) <= 0) {
+ if (time_before_eq(end, jiffies)) {
printk(KERN_ERR PFX
"TLB flush took more than 3 seconds.\n");
}
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index 97b0a890ba7..b8ec25d1747 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -345,6 +345,12 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata =
.chipset_name = "PT880",
},
+ /* PT880 Ultra */
+ {
+ .device_id = PCI_DEVICE_ID_VIA_PT880ULTRA,
+ .chipset_name = "PT880 Ultra",
+ },
+
/* PT890 */
{
.device_id = PCI_DEVICE_ID_VIA_8783_0,
@@ -511,6 +517,7 @@ static struct pci_device_id agp_via_pci_table[] = {
ID(PCI_DEVICE_ID_VIA_8763_0),
ID(PCI_DEVICE_ID_VIA_8378_0),
ID(PCI_DEVICE_ID_VIA_PT880),
+ ID(PCI_DEVICE_ID_VIA_PT880ULTRA),
ID(PCI_DEVICE_ID_VIA_8783_0),
ID(PCI_DEVICE_ID_VIA_PX8X0_0),
ID(PCI_DEVICE_ID_VIA_3269_0),
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 927a5bbe112..a370e7a0bad 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -142,7 +142,7 @@ static int ac_register_board(unsigned long physloc, void __iomem *loc,
if (!boardno)
boardno = readb(loc + NUMCARD_OWNER_TO_PC);
- if (!boardno && boardno > MAX_BOARD) {
+ if (!boardno || boardno > MAX_BOARD) {
printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n",
boardno, physloc, MAX_BOARD);
return 0;
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
index 5d72f50de1a..46d66037b91 100644
--- a/drivers/char/cs5535_gpio.c
+++ b/drivers/char/cs5535_gpio.c
@@ -241,9 +241,10 @@ static int __init cs5535_gpio_init(void)
static void __exit cs5535_gpio_cleanup(void)
{
dev_t dev_id = MKDEV(major, 0);
+
+ cdev_del(&cs5535_gpio_cdev);
unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
- if (gpio_base != 0)
- release_region(gpio_base, CS5535_GPIO_SIZE);
+ release_region(gpio_base, CS5535_GPIO_SIZE);
}
module_init(cs5535_gpio_init);
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 107df9fdba4..cb76e5ca9a2 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -357,6 +357,12 @@ typedef struct drm_freelist {
spinlock_t lock;
} drm_freelist_t;
+typedef struct drm_dma_handle {
+ dma_addr_t busaddr;
+ void *vaddr;
+ size_t size;
+} drm_dma_handle_t;
+
/**
* Buffer entry. There is one of this for each buffer size order.
*/
@@ -366,7 +372,7 @@ typedef struct drm_buf_entry {
drm_buf_t *buflist; /**< buffer list */
int seg_count;
int page_order;
- unsigned long *seglist;
+ drm_dma_handle_t **seglist;
drm_freelist_t freelist;
} drm_buf_entry_t;
@@ -483,12 +489,6 @@ typedef struct drm_sigdata {
drm_hw_lock_t *lock;
} drm_sigdata_t;
-typedef struct drm_dma_handle {
- dma_addr_t busaddr;
- void *vaddr;
- size_t size;
-} drm_dma_handle_t;
-
/**
* Mappings list
*/
@@ -813,12 +813,8 @@ extern void drm_mem_init(void);
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 unsigned long drm_alloc_pages(int order, int area);
-extern void drm_free_pages(unsigned long address, int order, int area);
extern void *drm_ioremap(unsigned long offset, unsigned long size,
drm_device_t * dev);
-extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
- drm_device_t * dev);
extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t * dev);
extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type);
@@ -893,7 +889,6 @@ extern int drm_lock_free(drm_device_t * dev,
/* 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_addbufs_fb(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);
@@ -1024,11 +1019,13 @@ static __inline__ void drm_core_ioremap(struct drm_map *map,
map->handle = drm_ioremap(map->offset, map->size, dev);
}
+#if 0
static __inline__ void drm_core_ioremap_nocache(struct drm_map *map,
struct drm_device *dev)
{
map->handle = drm_ioremap_nocache(map->offset, map->size, dev);
}
+#endif /* 0 */
static __inline__ void drm_core_ioremapfree(struct drm_map *map,
struct drm_device *dev)
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
index fabc930c67a..40bfd9b01e3 100644
--- a/drivers/char/drm/drm_agpsupport.c
+++ b/drivers/char/drm/drm_agpsupport.c
@@ -503,8 +503,6 @@ int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start)
return agp_bind_memory(handle, start);
}
-EXPORT_SYMBOL(drm_agp_bind_memory);
-
/** Calls agp_unbind_memory() */
int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
{
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index e2637b4d51d..006b06d2972 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -386,7 +386,6 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
return 0;
}
-EXPORT_SYMBOL(drm_rmmap_locked);
int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
{
@@ -398,7 +397,6 @@ int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
return ret;
}
-EXPORT_SYMBOL(drm_rmmap);
/* The rmmap ioctl appears to be unnecessary. All mappings are torn down on
* the last close of the device, and this is necessary for cleanup when things
@@ -474,8 +472,7 @@ static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
if (entry->seg_count) {
for (i = 0; i < entry->seg_count; i++) {
if (entry->seglist[i]) {
- drm_free_pages(entry->seglist[i],
- entry->page_order, DRM_MEM_DMA);
+ drm_pci_free(dev, entry->seglist[i]);
}
}
drm_free(entry->seglist,
@@ -678,7 +675,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
int total;
int page_order;
drm_buf_entry_t *entry;
- unsigned long page;
+ drm_dma_handle_t *dmah;
drm_buf_t *buf;
int alignment;
unsigned long offset;
@@ -781,8 +778,10 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
page_count = 0;
while (entry->buf_count < count) {
- page = drm_alloc_pages(page_order, DRM_MEM_DMA);
- if (!page) {
+
+ dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful);
+
+ if (!dmah) {
/* Set count correctly so we free the proper amount. */
entry->buf_count = count;
entry->seg_count = count;
@@ -794,13 +793,13 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
atomic_dec(&dev->buf_alloc);
return -ENOMEM;
}
- entry->seglist[entry->seg_count++] = page;
+ entry->seglist[entry->seg_count++] = dmah;
for (i = 0; i < (1 << page_order); i++) {
DRM_DEBUG("page %d @ 0x%08lx\n",
dma->page_count + page_count,
- page + PAGE_SIZE * i);
+ (unsigned long)dmah->vaddr + PAGE_SIZE * i);
temp_pagelist[dma->page_count + page_count++]
- = page + PAGE_SIZE * i;
+ = (unsigned long)dmah->vaddr + PAGE_SIZE * i;
}
for (offset = 0;
offset + size <= total && entry->buf_count < count;
@@ -811,7 +810,8 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
buf->order = order;
buf->used = 0;
buf->offset = (dma->byte_count + byte_count + offset);
- buf->address = (void *)(page + offset);
+ buf->address = (void *)(dmah->vaddr + offset);
+ buf->bus_address = dmah->busaddr + offset;
buf->next = NULL;
buf->waiting = 0;
buf->pending = 0;
@@ -1051,7 +1051,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
return 0;
}
-int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
+static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
{
drm_device_dma_t *dma = dev->dma;
drm_buf_entry_t *entry;
@@ -1210,7 +1210,6 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
atomic_dec(&dev->buf_alloc);
return 0;
}
-EXPORT_SYMBOL(drm_addbufs_fb);
/**
diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c
index 2afab95ca03..892db709698 100644
--- a/drivers/char/drm/drm_dma.c
+++ b/drivers/char/drm/drm_dma.c
@@ -85,9 +85,7 @@ void drm_dma_takedown(drm_device_t * dev)
dma->bufs[i].seg_count);
for (j = 0; j < dma->bufs[i].seg_count; j++) {
if (dma->bufs[i].seglist[j]) {
- drm_free_pages(dma->bufs[i].seglist[j],
- dma->bufs[i].page_order,
- DRM_MEM_DMA);
+ drm_pci_free(dev, dma->bufs[i].seglist[j]);
}
}
drm_free(dma->bufs[i].seglist,
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index dc6bbe8a18d..3c0b882a8e7 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -75,8 +75,8 @@ static drm_ioctl_desc_t drm_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH},
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
- [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH},
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 641f7633878..b7f7951c458 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -175,7 +175,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
drm_device_t *dev = NULL;
int minor = iminor(inode);
int err = -ENODEV;
- struct file_operations *old_fops;
+ const struct file_operations *old_fops;
DRM_DEBUG("\n");
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index 8074771e348..7e3318e1d1c 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -79,66 +79,72 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
return pt;
}
-/**
- * Allocate pages.
- *
- * \param order size order.
- * \param area memory area. (Not used.)
- * \return page address on success, or zero on failure.
- *
- * Allocate and reserve free pages.
+#if __OS_HAS_AGP
+/*
+ * Find the drm_map that covers the range [offset, offset+size).
*/
-unsigned long drm_alloc_pages(int order, int area)
+static drm_map_t *drm_lookup_map(unsigned long offset,
+ unsigned long size, drm_device_t * dev)
{
- unsigned long address;
- unsigned long bytes = PAGE_SIZE << order;
- unsigned long addr;
- unsigned int sz;
-
- address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order);
- if (!address)
- return 0;
-
- /* Zero */
- memset((void *)address, 0, bytes);
-
- /* Reserve */
- for (addr = address, sz = bytes;
- sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
- SetPageReserved(virt_to_page(addr));
+ struct list_head *list;
+ drm_map_list_t *r_list;
+ drm_map_t *map;
+
+ list_for_each(list, &dev->maplist->head) {
+ r_list = (drm_map_list_t *) list;
+ map = r_list->map;
+ if (!map)
+ continue;
+ if (map->offset <= offset
+ && (offset + size) <= (map->offset + map->size))
+ return map;
}
-
- return address;
+ return NULL;
}
-/**
- * Free pages.
- *
- * \param address address of the pages to free.
- * \param order size order.
- * \param area memory area. (Not used.)
- *
- * Unreserve and free pages allocated by alloc_pages().
- */
-void drm_free_pages(unsigned long address, int order, int area)
+static void *agp_remap(unsigned long offset, unsigned long size,
+ drm_device_t * dev)
{
- unsigned long bytes = PAGE_SIZE << order;
- unsigned long addr;
- unsigned int sz;
+ unsigned long *phys_addr_map, i, num_pages =
+ PAGE_ALIGN(size) / PAGE_SIZE;
+ struct drm_agp_mem *agpmem;
+ struct page **page_map;
+ void *addr;
+
+ size = PAGE_ALIGN(size);
+
+#ifdef __alpha__
+ offset -= dev->hose->mem_space->start;
+#endif
+
+ for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
+ if (agpmem->bound <= offset
+ && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
+ (offset + size))
+ break;
+ if (!agpmem)
+ return NULL;
- if (!address)
- return;
+ /*
+ * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
+ * the CPU do not get remapped by the GART. We fix this by using the kernel's
+ * page-table instead (that's probably faster anyhow...).
+ */
+ /* note: use vmalloc() because num_pages could be large... */
+ page_map = vmalloc(num_pages * sizeof(struct page *));
+ if (!page_map)
+ return NULL;
- /* Unreserve */
- for (addr = address, sz = bytes;
- sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
- ClearPageReserved(virt_to_page(addr));
- }
+ phys_addr_map =
+ agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
+ for (i = 0; i < num_pages; ++i)
+ page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
+ addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
+ vfree(page_map);
- free_pages(address, order);
+ return addr;
}
-#if __OS_HAS_AGP
/** Wrapper around agp_allocate_memory() */
DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type)
{
@@ -162,5 +168,74 @@ int drm_unbind_agp(DRM_AGP_MEM * handle)
{
return drm_agp_unbind_memory(handle);
}
+
+#else /* __OS_HAS_AGP */
+
+static inline drm_map_t *drm_lookup_map(unsigned long offset,
+ unsigned long size, drm_device_t * dev)
+{
+ return NULL;
+}
+
+static inline void *agp_remap(unsigned long offset, unsigned long size,
+ drm_device_t * dev)
+{
+ return NULL;
+}
+
#endif /* agp */
+
+void *drm_ioremap(unsigned long offset, unsigned long size,
+ drm_device_t * dev)
+{
+ if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
+ drm_map_t *map = drm_lookup_map(offset, size, dev);
+
+ if (map && map->type == _DRM_AGP)
+ return agp_remap(offset, size, dev);
+ }
+ return ioremap(offset, size);
+}
+EXPORT_SYMBOL(drm_ioremap);
+
+#if 0
+void *drm_ioremap_nocache(unsigned long offset,
+ unsigned long size, drm_device_t * dev)
+{
+ if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
+ drm_map_t *map = drm_lookup_map(offset, size, dev);
+
+ if (map && map->type == _DRM_AGP)
+ return agp_remap(offset, size, dev);
+ }
+ return ioremap_nocache(offset, size);
+}
+#endif /* 0 */
+
+void drm_ioremapfree(void *pt, unsigned long size,
+ drm_device_t * dev)
+{
+ /*
+ * This is a bit ugly. It would be much cleaner if the DRM API would use separate
+ * routines for handling mappings in the AGP space. Hopefully this can be done in
+ * a future revision of the interface...
+ */
+ if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
+ && ((unsigned long)pt >= VMALLOC_START
+ && (unsigned long)pt < VMALLOC_END)) {
+ unsigned long offset;
+ drm_map_t *map;
+
+ offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK);
+ map = drm_lookup_map(offset, size, dev);
+ if (map && map->type == _DRM_AGP) {
+ vunmap(pt);
+ return;
+ }
+ }
+
+ iounmap(pt);
+}
+EXPORT_SYMBOL(drm_ioremapfree);
+
#endif /* debug_memory */
diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h
index 3732a61c376..714d9aedcff 100644
--- a/drivers/char/drm/drm_memory.h
+++ b/drivers/char/drm/drm_memory.h
@@ -57,71 +57,6 @@
# endif
#endif
-/*
- * Find the drm_map that covers the range [offset, offset+size).
- */
-static inline drm_map_t *drm_lookup_map(unsigned long offset,
- unsigned long size, drm_device_t * dev)
-{
- struct list_head *list;
- drm_map_list_t *r_list;
- drm_map_t *map;
-
- list_for_each(list, &dev->maplist->head) {
- r_list = (drm_map_list_t *) list;
- map = r_list->map;
- if (!map)
- continue;
- if (map->offset <= offset
- && (offset + size) <= (map->offset + map->size))
- return map;
- }
- return NULL;
-}
-
-static inline void *agp_remap(unsigned long offset, unsigned long size,
- drm_device_t * dev)
-{
- unsigned long *phys_addr_map, i, num_pages =
- PAGE_ALIGN(size) / PAGE_SIZE;
- struct drm_agp_mem *agpmem;
- struct page **page_map;
- void *addr;
-
- size = PAGE_ALIGN(size);
-
-#ifdef __alpha__
- offset -= dev->hose->mem_space->start;
-#endif
-
- for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
- if (agpmem->bound <= offset
- && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
- (offset + size))
- break;
- if (!agpmem)
- return NULL;
-
- /*
- * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
- * the CPU do not get remapped by the GART. We fix this by using the kernel's
- * page-table instead (that's probably faster anyhow...).
- */
- /* note: use vmalloc() because num_pages could be large... */
- page_map = vmalloc(num_pages * sizeof(struct page *));
- if (!page_map)
- return NULL;
-
- phys_addr_map =
- agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
- for (i = 0; i < num_pages; ++i)
- page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
- addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
- vfree(page_map);
-
- return addr;
-}
-
static inline unsigned long drm_follow_page(void *vaddr)
{
pgd_t *pgd = pgd_offset_k((unsigned long)vaddr);
@@ -133,18 +68,6 @@ static inline unsigned long drm_follow_page(void *vaddr)
#else /* __OS_HAS_AGP */
-static inline drm_map_t *drm_lookup_map(unsigned long offset,
- unsigned long size, drm_device_t * dev)
-{
- return NULL;
-}
-
-static inline void *agp_remap(unsigned long offset, unsigned long size,
- drm_device_t * dev)
-{
- return NULL;
-}
-
static inline unsigned long drm_follow_page(void *vaddr)
{
return 0;
@@ -152,51 +75,8 @@ static inline unsigned long drm_follow_page(void *vaddr)
#endif
-static inline void *drm_ioremap(unsigned long offset, unsigned long size,
- drm_device_t * dev)
-{
- if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
- drm_map_t *map = drm_lookup_map(offset, size, dev);
-
- if (map && map->type == _DRM_AGP)
- return agp_remap(offset, size, dev);
- }
- return ioremap(offset, size);
-}
-
-static inline void *drm_ioremap_nocache(unsigned long offset,
- unsigned long size, drm_device_t * dev)
-{
- if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
- drm_map_t *map = drm_lookup_map(offset, size, dev);
-
- if (map && map->type == _DRM_AGP)
- return agp_remap(offset, size, dev);
- }
- return ioremap_nocache(offset, size);
-}
-
-static inline void drm_ioremapfree(void *pt, unsigned long size,
- drm_device_t * dev)
-{
- /*
- * This is a bit ugly. It would be much cleaner if the DRM API would use separate
- * routines for handling mappings in the AGP space. Hopefully this can be done in
- * a future revision of the interface...
- */
- if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
- && ((unsigned long)pt >= VMALLOC_START
- && (unsigned long)pt < VMALLOC_END)) {
- unsigned long offset;
- drm_map_t *map;
-
- offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK);
- map = drm_lookup_map(offset, size, dev);
- if (map && map->type == _DRM_AGP) {
- vunmap(pt);
- return;
- }
- }
+void *drm_ioremap(unsigned long offset, unsigned long size,
+ drm_device_t * dev);
- iounmap(pt);
-}
+void drm_ioremapfree(void *pt, unsigned long size,
+ drm_device_t * dev);
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
index e84605fc54a..6543b9a14c4 100644
--- a/drivers/char/drm/drm_memory_debug.h
+++ b/drivers/char/drm/drm_memory_debug.h
@@ -206,76 +206,6 @@ void drm_free (void *pt, size_t size, int area) {
}
}
-unsigned long drm_alloc_pages (int order, int area) {
- unsigned long address;
- unsigned long bytes = PAGE_SIZE << order;
- unsigned long addr;
- unsigned int sz;
-
- spin_lock(&drm_mem_lock);
- if ((drm_ram_used >> PAGE_SHIFT)
- > (DRM_RAM_PERCENT * drm_ram_available) / 100) {
- spin_unlock(&drm_mem_lock);
- return 0;
- }
- spin_unlock(&drm_mem_lock);
-
- address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order);
- if (!address) {
- spin_lock(&drm_mem_lock);
- ++drm_mem_stats[area].fail_count;
- spin_unlock(&drm_mem_lock);
- return 0;
- }
- spin_lock(&drm_mem_lock);
- ++drm_mem_stats[area].succeed_count;
- drm_mem_stats[area].bytes_allocated += bytes;
- drm_ram_used += bytes;
- spin_unlock(&drm_mem_lock);
-
- /* Zero outside the lock */
- memset((void *)address, 0, bytes);
-
- /* Reserve */
- for (addr = address, sz = bytes;
- sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
- SetPageReserved(virt_to_page(addr));
- }
-
- return address;
-}
-
-void drm_free_pages (unsigned long address, int order, int area) {
- unsigned long bytes = PAGE_SIZE << order;
- int alloc_count;
- int free_count;
- unsigned long addr;
- unsigned int sz;
-
- if (!address) {
- DRM_MEM_ERROR(area, "Attempt to free address 0\n");
- } else {
- /* Unreserve */
- for (addr = address, sz = bytes;
- sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
- ClearPageReserved(virt_to_page(addr));
- }
- free_pages(address, order);
- }
-
- spin_lock(&drm_mem_lock);
- free_count = ++drm_mem_stats[area].free_count;
- alloc_count = drm_mem_stats[area].succeed_count;
- drm_mem_stats[area].bytes_freed += bytes;
- drm_ram_used -= bytes;
- spin_unlock(&drm_mem_lock);
- if (free_count > alloc_count) {
- DRM_MEM_ERROR(area,
- "Excess frees: %d frees, %d allocs\n",
- free_count, alloc_count);
- }
-}
-
void *drm_ioremap (unsigned long offset, unsigned long size,
drm_device_t * dev) {
void *pt;
@@ -299,6 +229,7 @@ void *drm_ioremap (unsigned long offset, unsigned long size,
return pt;
}
+#if 0
void *drm_ioremap_nocache (unsigned long offset, unsigned long size,
drm_device_t * dev) {
void *pt;
@@ -321,6 +252,7 @@ void *drm_ioremap_nocache (unsigned long offset, unsigned long size,
spin_unlock(&drm_mem_lock);
return pt;
}
+#endif /* 0 */
void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) {
int alloc_count;
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
index 1fd7ff16481..86a0f1c2209 100644
--- a/drivers/char/drm/drm_pci.c
+++ b/drivers/char/drm/drm_pci.c
@@ -37,6 +37,7 @@
*/
#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include "drmP.h"
/**********************************************************************/
@@ -50,6 +51,10 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
dma_addr_t maxaddr)
{
drm_dma_handle_t *dmah;
+#if 1
+ unsigned long addr;
+ size_t sz;
+#endif
#ifdef DRM_DEBUG_MEMORY
int area = DRM_MEM_DMA;
@@ -79,7 +84,7 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
return NULL;
dmah->size = size;
- dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr);
+ dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP);
#ifdef DRM_DEBUG_MEMORY
if (dmah->vaddr == NULL) {
@@ -104,18 +109,29 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
memset(dmah->vaddr, 0, size);
+ /* XXX - Is virt_to_page() legal for consistent mem? */
+ /* Reserve */
+ for (addr = (unsigned long)dmah->vaddr, sz = size;
+ sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ SetPageReserved(virt_to_page(addr));
+ }
+
return dmah;
}
EXPORT_SYMBOL(drm_pci_alloc);
/**
- * \brief Free a PCI consistent memory block with freeing its descriptor.
+ * \brief Free a PCI consistent memory block without freeing its descriptor.
*
* 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)
{
+#if 1
+ unsigned long addr;
+ size_t sz;
+#endif
#ifdef DRM_DEBUG_MEMORY
int area = DRM_MEM_DMA;
int alloc_count;
@@ -127,8 +143,14 @@ void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
DRM_MEM_ERROR(area, "Attempt to free address 0\n");
#endif
} else {
- pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr,
- dmah->busaddr);
+ /* XXX - Is virt_to_page() legal for consistent mem? */
+ /* Unreserve */
+ for (addr = (unsigned long)dmah->vaddr, sz = dmah->size;
+ sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ }
+ dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
+ dmah->busaddr);
}
#ifdef DRM_DEBUG_MEMORY
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 2c17e88a884..b1bb3c7b568 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -3,49 +3,69 @@
Please contact dri-devel@lists.sf.net to add new cards to this list
*/
#define radeon_PCI_IDS \
- {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350},\
+ {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
{0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \
{0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \
{0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
{0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
{0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
{0x1002, 0x4147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+ {0x1002, 0x4148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+ {0x1002, 0x4149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+ {0x1002, 0x414A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+ {0x1002, 0x414B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
{0x1002, 0x4150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
{0x1002, 0x4151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
{0x1002, 0x4152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
{0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
{0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+ {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
{0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
- {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP}, \
+ {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \
{0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
{0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
{0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
{0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
- {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
- {0x1002, 0x4964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
- {0x1002, 0x4965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
- {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
- {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
- {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \
- {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \
+ {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
+ {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
+ {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
{0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \
{0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \
{0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \
{0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \
- {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
- {0x1002, 0x4C65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
- {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
- {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \
{0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
{0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
- {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+ {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
{0x1002, 0x4E47, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
{0x1002, 0x4E48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
{0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
- {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+ {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
{0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
{0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
{0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
{0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
{0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
{0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
@@ -53,44 +73,66 @@
{0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
{0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
{0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
- {0x1002, 0x5149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
- {0x1002, 0x514A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
- {0x1002, 0x514B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
{0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
{0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
- {0x1002, 0x514E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
- {0x1002, 0x514F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
{0x1002, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
{0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
{0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
{0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
{0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
- {0x1002, 0x5168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
- {0x1002, 0x5169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
- {0x1002, 0x516A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
- {0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
- {0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
- {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
- {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+ {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \
+ {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
{0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
{0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
- {0x1002, 0x5836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
- {0x1002, 0x5837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
{0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
- {0x1002, 0x5963, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
- {0x1002, 0x5968, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+ {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
- {0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
- {0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+ {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
{0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
- {0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
- {0x1002, 0x5c64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
- {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
- {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \
+ {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_NEW_MEMMAP}, \
+ {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
{0, 0, 0}
#define r128_PCI_IDS \
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 68073e14fde..9a842a36bb2 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -229,8 +229,6 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
return ret;
}
-EXPORT_SYMBOL(drm_get_dev);
-
/**
* Put a device minor number.
*
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index ae0aa6d7e0b..c658dde3633 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -126,7 +126,7 @@ static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
drm_device_t *dev = priv->head->dev;
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
drm_i810_private_t *dev_priv = dev->dev_private;
- struct file_operations *old_fops;
+ const struct file_operations *old_fops;
int retcode = 0;
if (buf_priv->currently_mapped == I810_BUF_MAPPED)
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 163f2cbfe60..b0f815d8cea 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -128,7 +128,7 @@ static int i830_map_buffer(drm_buf_t * buf, struct file *filp)
drm_device_t *dev = priv->head->dev;
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
drm_i830_private_t *dev_priv = dev->dev_private;
- struct file_operations *old_fops;
+ const struct file_operations *old_fops;
unsigned long virtual;
int retcode = 0;
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index 1ff4c7ca0bf..9f4b8ce4c05 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -495,8 +495,6 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev,
}
}
- dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
-
i915_emit_breadcrumb(dev);
return 0;
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index d3879ac9970..a752afd86ab 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -53,6 +53,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+ dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+
if (temp & USER_INT_FLAG)
DRM_WAKEUP(&dev_priv->irq_queue);
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index c08fa5076f0..26bdf2ca59d 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -214,13 +214,13 @@ void r300_init_reg_flags(void)
ADD_RANGE(0x4F54, 1);
ADD_RANGE(R300_TX_FILTER_0, 16);
- ADD_RANGE(R300_TX_UNK1_0, 16);
+ ADD_RANGE(R300_TX_FILTER1_0, 16);
ADD_RANGE(R300_TX_SIZE_0, 16);
ADD_RANGE(R300_TX_FORMAT_0, 16);
ADD_RANGE(R300_TX_PITCH_0, 16);
/* Texture offset is dangerous and needs more checking */
ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
- ADD_RANGE(R300_TX_UNK4_0, 16);
+ ADD_RANGE(R300_TX_CHROMA_KEY_0, 16);
ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
/* Sporadic registers used as primitives are emitted */
@@ -242,8 +242,10 @@ static __inline__ int r300_check_range(unsigned reg, int count)
return 0;
}
- /* we expect offsets passed to the framebuffer to be either within video memory or
- within AGP space */
+/*
+ * we expect offsets passed to the framebuffer to be either within video
+ * memory or within AGP space
+ */
static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
u32 offset)
{
@@ -251,11 +253,11 @@ static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
but this value is not being kept.
This code is correct for now (does the same thing as the
code that sets MC_FB_LOCATION) in radeon_cp.c */
- if ((offset >= dev_priv->fb_location) &&
- (offset < dev_priv->gart_vm_start))
+ if (offset >= dev_priv->fb_location &&
+ offset < (dev_priv->fb_location + dev_priv->fb_size))
return 0;
- if ((offset >= dev_priv->gart_vm_start) &&
- (offset < dev_priv->gart_vm_start + dev_priv->gart_size))
+ if (offset >= dev_priv->gart_vm_start &&
+ offset < (dev_priv->gart_vm_start + dev_priv->gart_size))
return 0;
return 1;
}
@@ -490,6 +492,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
return 0;
}
+
static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
drm_radeon_kcmd_buffer_t *cmdbuf)
{
@@ -701,6 +704,64 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
buf->used = 0;
}
+static int r300_scratch(drm_radeon_private_t *dev_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf,
+ drm_r300_cmd_header_t header)
+{
+ u32 *ref_age_base;
+ u32 i, buf_idx, h_pending;
+ RING_LOCALS;
+
+ if (cmdbuf->bufsz <
+ (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) {
+ return DRM_ERR(EINVAL);
+ }
+
+ if (header.scratch.reg >= 5) {
+ return DRM_ERR(EINVAL);
+ }
+
+ dev_priv->scratch_ages[header.scratch.reg]++;
+
+ ref_age_base = (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf);
+
+ cmdbuf->buf += sizeof(u64);
+ cmdbuf->bufsz -= sizeof(u64);
+
+ for (i=0; i < header.scratch.n_bufs; i++) {
+ buf_idx = *(u32 *)cmdbuf->buf;
+ buf_idx *= 2; /* 8 bytes per buf */
+
+ if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
+ return DRM_ERR(EINVAL);
+ }
+
+ if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
+ return DRM_ERR(EINVAL);
+ }
+
+ if (h_pending == 0) {
+ return DRM_ERR(EINVAL);
+ }
+
+ h_pending--;
+
+ if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
+ return DRM_ERR(EINVAL);
+ }
+
+ cmdbuf->buf += sizeof(buf_idx);
+ cmdbuf->bufsz -= sizeof(buf_idx);
+ }
+
+ BEGIN_RING(2);
+ 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;
+}
+
/**
* Parses and validates a user-supplied command buffer and emits appropriate
* commands on the DMA ring buffer.
@@ -838,6 +899,15 @@ int r300_do_cp_cmdbuf(drm_device_t *dev,
}
break;
+ case R300_CMD_SCRATCH:
+ DRM_DEBUG("R300_CMD_SCRATCH\n");
+ ret = r300_scratch(dev_priv, cmdbuf, header);
+ if (ret) {
+ DRM_ERROR("r300_scratch failed\n");
+ goto cleanup;
+ }
+ break;
+
default:
DRM_ERROR("bad cmd_type %i at %p\n",
header.header.cmd_type,
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
index d1e19954406..a881f96c983 100644
--- a/drivers/char/drm/r300_reg.h
+++ b/drivers/char/drm/r300_reg.h
@@ -711,8 +711,22 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_TX_MAX_ANISO_16_TO_1 (8 << 21)
# define R300_TX_MAX_ANISO_MASK (14 << 21)
-#define R300_TX_UNK1_0 0x4440
+#define R300_TX_FILTER1_0 0x4440
+# define R300_CHROMA_KEY_MODE_DISABLE 0
+# define R300_CHROMA_KEY_FORCE 1
+# define R300_CHROMA_KEY_BLEND 2
+# define R300_MC_ROUND_NORMAL (0<<2)
+# define R300_MC_ROUND_MPEG4 (1<<2)
# define R300_LOD_BIAS_MASK 0x1fff
+# define R300_EDGE_ANISO_EDGE_DIAG (0<<13)
+# define R300_EDGE_ANISO_EDGE_ONLY (1<<13)
+# define R300_MC_COORD_TRUNCATE_DISABLE (0<<14)
+# define R300_MC_COORD_TRUNCATE_MPEG (1<<14)
+# define R300_TX_TRI_PERF_0_8 (0<<15)
+# define R300_TX_TRI_PERF_1_8 (1<<15)
+# define R300_TX_TRI_PERF_1_4 (2<<15)
+# define R300_TX_TRI_PERF_3_8 (3<<15)
+# define R300_ANISO_THRESHOLD_MASK (7<<17)
#define R300_TX_SIZE_0 0x4480
# define R300_TX_WIDTHMASK_SHIFT 0
@@ -722,6 +736,8 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# 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_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.
@@ -750,7 +766,8 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# 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_UNK25 (1 << 25) /* no swizzle */
+# define R300_TX_FORMAT_CUBIC_MAP (1 << 26)
/* gap */
/* Floating point formats */
@@ -800,18 +817,20 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_TX_FORMAT_YUV_MODE 0x00800000
-#define R300_TX_PITCH_0 0x4500
+#define R300_TX_PITCH_0 0x4500 /* obvious missing in gap */
#define R300_TX_OFFSET_0 0x4540
/* 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)
# define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0)
+# define R300_TXO_MACRO_TILE (1 << 2)
+# define R300_TXO_MICRO_TILE (1 << 3)
# define R300_TXO_OFFSET_MASK 0xffffffe0
# define R300_TXO_OFFSET_SHIFT 5
/* END */
-#define R300_TX_UNK4_0 0x4580
-#define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 }
+#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 */
@@ -868,7 +887,9 @@ 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_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
@@ -887,6 +908,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
*/
# 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
@@ -962,9 +984,11 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_FPI1_SRC2C_CONST (1 << 17)
# define R300_FPI1_DSTC_SHIFT 18
# define R300_FPI1_DSTC_MASK (31 << 18)
+# define R300_FPI1_DSTC_REG_MASK_SHIFT 23
# define R300_FPI1_DSTC_REG_X (1 << 23)
# define R300_FPI1_DSTC_REG_Y (1 << 24)
# define R300_FPI1_DSTC_REG_Z (1 << 25)
+# define R300_FPI1_DSTC_OUTPUT_MASK_SHIFT 26
# define R300_FPI1_DSTC_OUTPUT_X (1 << 26)
# define R300_FPI1_DSTC_OUTPUT_Y (1 << 27)
# define R300_FPI1_DSTC_OUTPUT_Z (1 << 28)
@@ -983,6 +1007,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_FPI3_DSTA_MASK (31 << 18)
# define R300_FPI3_DSTA_REG (1 << 23)
# define R300_FPI3_DSTA_OUTPUT (1 << 24)
+# define R300_FPI3_DSTA_DEPTH (1 << 27)
#define R300_PFS_INSTR0_0 0x48C0
# define R300_FPI0_ARGC_SRC0C_XYZ 0
@@ -1036,7 +1061,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_FPI0_OUTC_FRC (9 << 23)
# define R300_FPI0_OUTC_REPL_ALPHA (10 << 23)
# define R300_FPI0_OUTC_SAT (1 << 30)
-# define R300_FPI0_UNKNOWN_31 (1 << 31)
+# define R300_FPI0_INSERT_NOP (1 << 31)
#define R300_PFS_INSTR2_0 0x49C0
# define R300_FPI2_ARGA_SRC0C_X 0
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 9bb8ae0c1c2..7f949c9c969 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -1118,14 +1118,20 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
{
u32 ring_start, cur_read_ptr;
u32 tmp;
-
- /* Initialize the memory controller */
- RADEON_WRITE(RADEON_MC_FB_LOCATION,
- ((dev_priv->gart_vm_start - 1) & 0xffff0000)
- | (dev_priv->fb_location >> 16));
+
+ /* Initialize the memory controller. With new memory map, the fb location
+ * is not changed, it should have been properly initialized already. Part
+ * of the problem is that the code below is bogus, assuming the GART is
+ * always appended to the fb which is not necessarily the case
+ */
+ if (!dev_priv->new_memmap)
+ RADEON_WRITE(RADEON_MC_FB_LOCATION,
+ ((dev_priv->gart_vm_start - 1) & 0xffff0000)
+ | (dev_priv->fb_location >> 16));
#if __OS_HAS_AGP
if (dev_priv->flags & CHIP_IS_AGP) {
+ RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
RADEON_WRITE(RADEON_MC_AGP_LOCATION,
(((dev_priv->gart_vm_start - 1 +
dev_priv->gart_size) & 0xffff0000) |
@@ -1153,8 +1159,6 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
#if __OS_HAS_AGP
if (dev_priv->flags & CHIP_IS_AGP) {
- /* set RADEON_AGP_BASE here instead of relying on X from user space */
- RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
dev_priv->ring_rptr->offset
- dev->agp->base + dev_priv->gart_vm_start);
@@ -1174,6 +1178,17 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
entry->handle + tmp_ofs);
}
+ /* Set ring buffer size */
+#ifdef __BIG_ENDIAN
+ RADEON_WRITE(RADEON_CP_RB_CNTL,
+ dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
+#else
+ RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
+#endif
+
+ /* Start with assuming that writeback doesn't work */
+ dev_priv->writeback_works = 0;
+
/* Initialize the scratch register pointer. This will cause
* the scratch register values to be written out to memory
* whenever they are updated.
@@ -1190,28 +1205,9 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
- /* Writeback doesn't seem to work everywhere, test it first */
- DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);
- RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
-
- for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
- if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==
- 0xdeadbeef)
- break;
- DRM_UDELAY(1);
- }
-
- if (tmp < dev_priv->usec_timeout) {
- dev_priv->writeback_works = 1;
- DRM_DEBUG("writeback test succeeded, tmp=%d\n", tmp);
- } else {
- dev_priv->writeback_works = 0;
- DRM_DEBUG("writeback test failed\n");
- }
- if (radeon_no_wb == 1) {
- dev_priv->writeback_works = 0;
- DRM_DEBUG("writeback forced off\n");
- }
+ /* Turn on bus mastering */
+ tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+ RADEON_WRITE(RADEON_BUS_CNTL, tmp);
dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
@@ -1223,26 +1219,45 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
- /* Set ring buffer size */
-#ifdef __BIG_ENDIAN
- RADEON_WRITE(RADEON_CP_RB_CNTL,
- dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
-#else
- RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
-#endif
-
radeon_do_wait_for_idle(dev_priv);
- /* Turn on bus mastering */
- tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
- RADEON_WRITE(RADEON_BUS_CNTL, tmp);
-
/* Sync everything up */
RADEON_WRITE(RADEON_ISYNC_CNTL,
(RADEON_ISYNC_ANY2D_IDLE3D |
RADEON_ISYNC_ANY3D_IDLE2D |
RADEON_ISYNC_WAIT_IDLEGUI |
RADEON_ISYNC_CPSCRATCH_IDLEGUI));
+
+}
+
+static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
+{
+ u32 tmp;
+
+ /* Writeback doesn't seem to work everywhere, test it here and possibly
+ * enable it if it appears to work
+ */
+ DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);
+ RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
+
+ for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
+ if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==
+ 0xdeadbeef)
+ break;
+ DRM_UDELAY(1);
+ }
+
+ if (tmp < dev_priv->usec_timeout) {
+ dev_priv->writeback_works = 1;
+ DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
+ } else {
+ dev_priv->writeback_works = 0;
+ DRM_INFO("writeback test failed\n");
+ }
+ if (radeon_no_wb == 1) {
+ dev_priv->writeback_works = 0;
+ DRM_INFO("writeback forced off\n");
+ }
}
/* Enable or disable PCI-E GART on the chip */
@@ -1317,6 +1332,14 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
DRM_DEBUG("\n");
+ /* if we require new memory map but we don't have it fail */
+ if ((dev_priv->flags & CHIP_NEW_MEMMAP) && !dev_priv->new_memmap)
+ {
+ DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX\n");
+ radeon_do_cleanup_cp(dev);
+ return DRM_ERR(EINVAL);
+ }
+
if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP))
{
DRM_DEBUG("Forcing AGP card to PCI mode\n");
@@ -1496,6 +1519,9 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION)
& 0xffff) << 16;
+ dev_priv->fb_size =
+ ((RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff0000u) + 0x10000)
+ - dev_priv->fb_location;
dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
((dev_priv->front_offset
@@ -1510,8 +1536,46 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
+ dev_priv->fb_location) >> 10));
dev_priv->gart_size = init->gart_size;
- dev_priv->gart_vm_start = dev_priv->fb_location
- + RADEON_READ(RADEON_CONFIG_APER_SIZE);
+
+ /* New let's set the memory map ... */
+ if (dev_priv->new_memmap) {
+ u32 base = 0;
+
+ DRM_INFO("Setting GART location based on new memory map\n");
+
+ /* If using AGP, try to locate the AGP aperture at the same
+ * location in the card and on the bus, though we have to
+ * align it down.
+ */
+#if __OS_HAS_AGP
+ if (dev_priv->flags & CHIP_IS_AGP) {
+ base = dev->agp->base;
+ /* Check if valid */
+ if ((base + dev_priv->gart_size) > dev_priv->fb_location &&
+ base < (dev_priv->fb_location + dev_priv->fb_size)) {
+ DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
+ dev->agp->base);
+ base = 0;
+ }
+ }
+#endif
+ /* If not or if AGP is at 0 (Macs), try to put it elsewhere */
+ if (base == 0) {
+ base = dev_priv->fb_location + dev_priv->fb_size;
+ if (((base + dev_priv->gart_size) & 0xfffffffful)
+ < base)
+ base = dev_priv->fb_location
+ - dev_priv->gart_size;
+ }
+ dev_priv->gart_vm_start = base & 0xffc00000u;
+ if (dev_priv->gart_vm_start != base)
+ DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
+ base, dev_priv->gart_vm_start);
+ } else {
+ DRM_INFO("Setting GART location based on old memory map\n");
+ dev_priv->gart_vm_start = dev_priv->fb_location +
+ RADEON_READ(RADEON_CONFIG_APER_SIZE);
+ }
#if __OS_HAS_AGP
if (dev_priv->flags & CHIP_IS_AGP)
@@ -1596,6 +1660,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
dev_priv->last_buf = 0;
radeon_do_engine_reset(dev);
+ radeon_test_writeback(dev_priv);
return 0;
}
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index 9c177a6b2a4..c8e279e89c2 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -222,6 +222,7 @@ typedef union {
# define R300_WAIT_3D 0x2
# define R300_WAIT_2D_CLEAN 0x3
# define R300_WAIT_3D_CLEAN 0x4
+#define R300_CMD_SCRATCH 8
typedef union {
unsigned int u;
@@ -247,6 +248,9 @@ typedef union {
struct {
unsigned char cmd_type, flags, pad0, pad1;
} wait;
+ struct {
+ unsigned char cmd_type, reg, n_bufs, flags;
+ } scratch;
} drm_r300_cmd_header_t;
#define RADEON_FRONT 0x1
@@ -697,6 +701,7 @@ typedef struct drm_radeon_setparam {
#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */
#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */
#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
+#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */
/* 1.14: Clients can allocate/free a surface
*/
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 1f7d2ab8c4f..78345cee8f8 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -38,7 +38,7 @@
#define DRIVER_NAME "radeon"
#define DRIVER_DESC "ATI Radeon"
-#define DRIVER_DATE "20051229"
+#define DRIVER_DATE "20060225"
/* Interface history:
*
@@ -91,9 +91,11 @@
* 1.20- Add support for r300 texrect
* 1.21- Add support for card type getparam
* 1.22- Add support for texture cache flushes (R300_TX_CNTL)
+ * 1.23- Add new radeon memory map work from benh
+ * 1.24- Add general-purpose packet for manipulating scratch registers (r300)
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 22
+#define DRIVER_MINOR 24
#define DRIVER_PATCHLEVEL 0
/*
@@ -101,20 +103,21 @@
*/
enum radeon_family {
CHIP_R100,
- CHIP_RS100,
CHIP_RV100,
+ CHIP_RS100,
CHIP_RV200,
- CHIP_R200,
CHIP_RS200,
- CHIP_R250,
- CHIP_RS250,
+ CHIP_R200,
CHIP_RV250,
+ CHIP_RS300,
CHIP_RV280,
CHIP_R300,
- CHIP_RS300,
CHIP_R350,
CHIP_RV350,
+ CHIP_RV380,
CHIP_R420,
+ CHIP_RV410,
+ CHIP_RS400,
CHIP_LAST,
};
@@ -136,9 +139,11 @@ enum radeon_chip_flags {
CHIP_IS_AGP = 0x00080000UL,
CHIP_HAS_HIERZ = 0x00100000UL,
CHIP_IS_PCIE = 0x00200000UL,
+ CHIP_NEW_MEMMAP = 0x00400000UL,
};
-#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 )
+#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \
+ DRM_READ32( (dev_priv)->ring_rptr, 0 ) : RADEON_READ(RADEON_CP_RB_RPTR))
#define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
typedef struct drm_radeon_freelist {
@@ -199,6 +204,8 @@ typedef struct drm_radeon_private {
drm_radeon_sarea_t *sarea_priv;
u32 fb_location;
+ u32 fb_size;
+ int new_memmap;
int gart_size;
u32 gart_vm_start;
@@ -272,6 +279,8 @@ typedef struct drm_radeon_private {
unsigned long pcigart_offset;
drm_ati_pcigart_info gart_info;
+ u32 scratch_ages[5];
+
/* starting from here on, data is preserved accross an open */
uint32_t flags; /* see radeon_chip_flags */
} drm_radeon_private_t;
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 7bc27516d42..c5b8f774a59 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -45,22 +45,53 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
u32 off = *offset;
struct drm_radeon_driver_file_fields *radeon_priv;
- if (off >= dev_priv->fb_location &&
- off < (dev_priv->gart_vm_start + dev_priv->gart_size))
- return 0;
-
- radeon_priv = filp_priv->driver_priv;
- off += radeon_priv->radeon_fb_delta;
+ /* Hrm ... the story of the offset ... So this function converts
+ * the various ideas of what userland clients might have for an
+ * offset in the card address space into an offset into the card
+ * address space :) So with a sane client, it should just keep
+ * the value intact and just do some boundary checking. However,
+ * not all clients are sane. Some older clients pass us 0 based
+ * offsets relative to the start of the framebuffer and some may
+ * assume the AGP aperture it appended to the framebuffer, so we
+ * try to detect those cases and fix them up.
+ *
+ * Note: It might be a good idea here to make sure the offset lands
+ * in some "allowed" area to protect things like the PCIE GART...
+ */
- DRM_DEBUG("offset fixed up to 0x%x\n", off);
+ /* First, the best case, the offset already lands in either the
+ * framebuffer or the GART mapped space
+ */
+ if ((off >= dev_priv->fb_location &&
+ off < (dev_priv->fb_location + dev_priv->fb_size)) ||
+ (off >= dev_priv->gart_vm_start &&
+ off < (dev_priv->gart_vm_start + dev_priv->gart_size)))
+ return 0;
- if (off < dev_priv->fb_location ||
- off >= (dev_priv->gart_vm_start + dev_priv->gart_size))
- return DRM_ERR(EINVAL);
+ /* Ok, that didn't happen... now check if we have a zero based
+ * offset that fits in the framebuffer + gart space, apply the
+ * magic offset we get from SETPARAM or calculated from fb_location
+ */
+ if (off < (dev_priv->fb_size + dev_priv->gart_size)) {
+ radeon_priv = filp_priv->driver_priv;
+ off += radeon_priv->radeon_fb_delta;
+ }
- *offset = off;
+ /* Finally, assume we aimed at a GART offset if beyond the fb */
+ if (off > (dev_priv->fb_location + dev_priv->fb_size))
+ off = off - (dev_priv->fb_location + dev_priv->fb_size) +
+ dev_priv->gart_vm_start;
- return 0;
+ /* Now recheck and fail if out of bounds */
+ if ((off >= dev_priv->fb_location &&
+ off < (dev_priv->fb_location + dev_priv->fb_size)) ||
+ (off >= dev_priv->gart_vm_start &&
+ off < (dev_priv->gart_vm_start + dev_priv->gart_size))) {
+ DRM_DEBUG("offset fixed up to 0x%x\n", off);
+ *offset = off;
+ return 0;
+ }
+ return DRM_ERR(EINVAL);
}
static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
@@ -1939,11 +1970,6 @@ static int radeon_surface_alloc(DRM_IOCTL_ARGS)
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_surface_alloc_t alloc;
- if (!dev_priv) {
- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
- return DRM_ERR(EINVAL);
- }
-
DRM_COPY_FROM_USER_IOCTL(alloc,
(drm_radeon_surface_alloc_t __user *) data,
sizeof(alloc));
@@ -1960,12 +1986,7 @@ static int radeon_surface_free(DRM_IOCTL_ARGS)
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_surface_free_t memfree;
- if (!dev_priv) {
- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
- return DRM_ERR(EINVAL);
- }
-
- DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data,
+ DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data,
sizeof(memfree));
if (free_surface(filp, dev_priv, memfree.address))
@@ -2100,11 +2121,6 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS)
LOCK_TEST_WITH_RETURN(dev, filp);
- if (!dev_priv) {
- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
- return DRM_ERR(EINVAL);
- }
-
DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data,
@@ -2189,11 +2205,6 @@ static int radeon_cp_indices(DRM_IOCTL_ARGS)
LOCK_TEST_WITH_RETURN(dev, filp);
- if (!dev_priv) {
- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
- return DRM_ERR(EINVAL);
- }
-
DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data,
@@ -2340,11 +2351,6 @@ static int radeon_cp_indirect(DRM_IOCTL_ARGS)
LOCK_TEST_WITH_RETURN(dev, filp);
- if (!dev_priv) {
- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
- return DRM_ERR(EINVAL);
- }
-
DRM_COPY_FROM_USER_IOCTL(indirect,
(drm_radeon_indirect_t __user *) data,
sizeof(indirect));
@@ -2417,11 +2423,6 @@ static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
LOCK_TEST_WITH_RETURN(dev, filp);
- if (!dev_priv) {
- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
- return DRM_ERR(EINVAL);
- }
-
DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data,
@@ -2738,11 +2739,6 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
LOCK_TEST_WITH_RETURN(dev, filp);
- if (!dev_priv) {
- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
- return DRM_ERR(EINVAL);
- }
-
DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
DRM_COPY_FROM_USER_IOCTL(cmdbuf,
@@ -2897,11 +2893,6 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
drm_radeon_getparam_t param;
int value;
- if (!dev_priv) {
- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
- return DRM_ERR(EINVAL);
- }
-
DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data,
sizeof(param));
@@ -2981,11 +2972,6 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
drm_radeon_setparam_t sp;
struct drm_radeon_driver_file_fields *radeon_priv;
- if (!dev_priv) {
- DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
- return DRM_ERR(EINVAL);
- }
-
DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data,
@@ -3012,6 +2998,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
case RADEON_SETPARAM_PCIGART_LOCATION:
dev_priv->pcigart_offset = sp.value;
break;
+ case RADEON_SETPARAM_NEW_MEMMAP:
+ dev_priv->new_memmap = sp.value;
+ break;
default:
DRM_DEBUG("Invalid parameter %d\n", sp.param);
return DRM_ERR(EINVAL);
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index 6774d2fe345..5e9936bc307 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -110,7 +110,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS)
DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
- DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
+ DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset);
return retval;
}
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index 6152415644e..c33d068cde1 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -196,9 +196,9 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
unsigned int cur_irq_sequence;
- drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+ drm_via_irq_t *cur_irq;
int ret = 0;
- maskarray_t *masks = dev_priv->irq_masks;
+ maskarray_t *masks;
int real_irq;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -221,8 +221,9 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
__FUNCTION__, irq);
return DRM_ERR(EINVAL);
}
-
- cur_irq += real_irq;
+
+ masks = dev_priv->irq_masks;
+ cur_irq = dev_priv->via_irqs + real_irq;
if (masks[real_irq][2] && !force_sequence) {
DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
@@ -247,11 +248,12 @@ void via_driver_irq_preinstall(drm_device_t * dev)
{
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
u32 status;
- drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+ drm_via_irq_t *cur_irq;
int i;
DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv);
if (dev_priv) {
+ cur_irq = dev_priv->via_irqs;
dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index a229915ce1b..87dcaa237f0 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -490,7 +490,7 @@ for (i = 0; i < 10; i++) \
release_region(dtlk_portlist[i], DTLK_IO_EXTENT);
}
- printk(KERN_INFO "\nDoubleTalk PC - not found\n");
+ printk(KERN_INFO "DoubleTalk PC - not found\n");
return -ENODEV;
}
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index 1b5e01e6e12..43ff5981651 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -22,6 +22,9 @@
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/nvram.h>
+#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
+#endif
#define NVRAM_SIZE 8192
@@ -92,7 +95,7 @@ static int nvram_ioctl(struct inode *inode, struct file *file,
case IOC_NVRAM_GET_OFFSET: {
int part, offset;
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return -EINVAL;
if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0)
return -EFAULT;
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index d3a2bc36129..588fca542a9 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -200,13 +200,13 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf,
/* first test allows optimizer to nuke this case for 32-bit machines */
if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) {
unsigned int uidata = data;
- retval = put_user(uidata, (unsigned long __user *)buf);
+ retval = put_user(uidata, (unsigned int __user *)buf) ?:
+ sizeof(unsigned int);
}
else {
- retval = put_user(data, (unsigned long __user *)buf);
+ retval = put_user(data, (unsigned long __user *)buf) ?:
+ sizeof(unsigned long);
}
- if (!retval)
- retval = sizeof(unsigned long);
out:
current->state = TASK_RUNNING;
remove_wait_queue(&gen_rtc_wait, &wait);
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index ef140ebde11..07473cd8412 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -925,11 +925,8 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
status = acpi_resource_to_address64(res, &addr);
if (ACPI_SUCCESS(status)) {
- unsigned long size;
-
- size = addr.maximum - addr.minimum + 1;
hdp->hd_phys_address = addr.minimum;
- hdp->hd_address = ioremap(addr.minimum, size);
+ hdp->hd_address = ioremap(addr.minimum, addr.address_length);
if (hpet_is_known(hdp)) {
printk(KERN_DEBUG "%s: 0x%lx is busy\n",
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index f65b2e14a48..2b6a56b2bf3 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -39,8 +39,10 @@
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
+
#include <asm/uaccess.h>
-#include <asm/hvconsole.h>
+
+#include "hvc_console.h"
#define HVC_MAJOR 229
#define HVC_MINOR 0
@@ -54,17 +56,14 @@
#define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
/*
- * The Linux TTY code does not support dynamic addition of tty derived devices
- * so we need to know how many tty devices we might need when space is allocated
- * for the tty device. Since this driver supports hotplug of vty adapters we
- * need to make sure we have enough allocated.
+ * These sizes are most efficient for vio, because they are the
+ * native transfer size. We could make them selectable in the
+ * future to better deal with backends that want other buffer sizes.
*/
-#define HVC_ALLOC_TTY_ADAPTERS 8
-
#define N_OUTBUF 16
#define N_INBUF 16
-#define __ALIGNED__ __attribute__((__aligned__(8)))
+#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
static struct tty_driver *hvc_driver;
static struct task_struct *hvc_task;
@@ -154,7 +153,7 @@ static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
void hvc_console_print(struct console *co, const char *b, unsigned count)
{
- char c[16] __ALIGNED__;
+ char c[N_OUTBUF] __ALIGNED__;
unsigned i = 0, n = 0;
int r, donecr = 0, index = co->index;
@@ -473,8 +472,10 @@ static void hvc_push(struct hvc_struct *hp)
n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
if (n <= 0) {
- if (n == 0)
+ if (n == 0) {
+ hp->do_wakeup = 1;
return;
+ }
/* throw away output on error; this happens when
there is no session connected to the vterm. */
hp->n_outbuf = 0;
@@ -486,12 +487,19 @@ static void hvc_push(struct hvc_struct *hp)
hp->do_wakeup = 1;
}
-static inline int __hvc_write_kernel(struct hvc_struct *hp,
- const unsigned char *buf, int count)
+static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
+ struct hvc_struct *hp = tty->driver_data;
unsigned long flags;
int rsize, written = 0;
+ /* This write was probably executed during a tty close. */
+ if (!hp)
+ return -EPIPE;
+
+ if (hp->count <= 0)
+ return -EIO;
+
spin_lock_irqsave(&hp->lock, flags);
/* Push pending writes */
@@ -510,26 +518,8 @@ static inline int __hvc_write_kernel(struct hvc_struct *hp,
}
spin_unlock_irqrestore(&hp->lock, flags);
- return written;
-}
-static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
- struct hvc_struct *hp = tty->driver_data;
- int written;
-
- /* This write was probably executed during a tty close. */
- if (!hp)
- return -EPIPE;
-
- if (hp->count <= 0)
- return -EIO;
-
- written = __hvc_write_kernel(hp, buf, count);
-
/*
* Racy, but harmless, kick thread if there is still pending data.
- * There really is nothing wrong with kicking the thread, even if there
- * is no buffered data.
*/
if (hp->n_outbuf)
hvc_kick();
@@ -614,6 +604,13 @@ static int hvc_poll(struct hvc_struct *hp)
spin_unlock_irqrestore(&hp->lock, flags);
tty_hangup(tty);
spin_lock_irqsave(&hp->lock, flags);
+ } else if ( n == -EAGAIN ) {
+ /*
+ * Some back-ends can only ensure a certain min
+ * num of bytes read, which may be > 'count'.
+ * Let the tty clear the flip buff to make room.
+ */
+ poll_mask |= HVC_POLL_READ;
}
break;
}
@@ -635,16 +632,7 @@ static int hvc_poll(struct hvc_struct *hp)
tty_insert_flip_char(tty, buf[i], 0);
}
- /*
- * Account for the total amount read in one loop, and if above
- * 64 bytes, we do a quick schedule loop to let the tty grok
- * the data and eventually throttle us.
- */
read_total += n;
- if (read_total >= 64) {
- poll_mask |= HVC_POLL_QUICK;
- break;
- }
}
throttled:
/* Wakeup write queue if necessary */
@@ -767,7 +755,8 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
* see if this vterm id matches one registered for console.
*/
for (i=0; i < MAX_NR_HVC_CONSOLES; i++)
- if (vtermnos[i] == hp->vtermno)
+ if (vtermnos[i] == hp->vtermno &&
+ cons_ops[i] == hp->ops)
break;
/* no matching slot, just use a counter */
@@ -823,34 +812,38 @@ EXPORT_SYMBOL(hvc_remove);
* interfaces start to become available. */
int __init hvc_init(void)
{
+ struct tty_driver *drv;
+
/* We need more than hvc_count adapters due to hotplug additions. */
- hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
- if (!hvc_driver)
+ drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
+ if (!drv)
return -ENOMEM;
- hvc_driver->owner = THIS_MODULE;
- hvc_driver->devfs_name = "hvc/";
- hvc_driver->driver_name = "hvc";
- hvc_driver->name = "hvc";
- hvc_driver->major = HVC_MAJOR;
- hvc_driver->minor_start = HVC_MINOR;
- hvc_driver->type = TTY_DRIVER_TYPE_SYSTEM;
- hvc_driver->init_termios = tty_std_termios;
- hvc_driver->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(hvc_driver, &hvc_ops);
+ drv->owner = THIS_MODULE;
+ drv->devfs_name = "hvc/";
+ drv->driver_name = "hvc";
+ drv->name = "hvc";
+ drv->major = HVC_MAJOR;
+ drv->minor_start = HVC_MINOR;
+ drv->type = TTY_DRIVER_TYPE_SYSTEM;
+ drv->init_termios = tty_std_termios;
+ drv->flags = TTY_DRIVER_REAL_RAW;
+ tty_set_operations(drv, &hvc_ops);
/* Always start the kthread because there can be hotplug vty adapters
* added later. */
hvc_task = kthread_run(khvcd, NULL, "khvcd");
if (IS_ERR(hvc_task)) {
panic("Couldn't create kthread for console.\n");
- put_tty_driver(hvc_driver);
+ put_tty_driver(drv);
return -EIO;
}
- if (tty_register_driver(hvc_driver))
+ if (tty_register_driver(drv))
panic("Couldn't register hvc console driver\n");
+ mb();
+ hvc_driver = drv;
return 0;
}
module_init(hvc_init);
diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h
new file mode 100644
index 00000000000..96b7401319c
--- /dev/null
+++ b/drivers/char/hvc_console.h
@@ -0,0 +1,63 @@
+/*
+ * hvc_console.h
+ * Copyright (C) 2005 IBM Corporation
+ *
+ * Author(s):
+ * Ryan S. Arnold <rsa@us.ibm.com>
+ *
+ * hvc_console header information:
+ * moved here from include/asm-powerpc/hvconsole.h
+ * and drivers/char/hvc_console.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
+ */
+
+#ifndef HVC_CONSOLE_H
+#define HVC_CONSOLE_H
+
+/*
+ * This is the max number of console adapters that can/will be found as
+ * console devices on first stage console init. Any number beyond this range
+ * can't be used as a console device but is still a valid tty device.
+ */
+#define MAX_NR_HVC_CONSOLES 16
+
+/*
+ * The Linux TTY code does not support dynamic addition of tty derived devices
+ * so we need to know how many tty devices we might need when space is allocated
+ * for the tty device. Since this driver supports hotplug of vty adapters we
+ * need to make sure we have enough allocated.
+ */
+#define HVC_ALLOC_TTY_ADAPTERS 8
+
+
+/* implemented by a low level driver */
+struct hv_ops {
+ int (*get_chars)(uint32_t vtermno, char *buf, int count);
+ int (*put_chars)(uint32_t vtermno, const char *buf, int count);
+};
+
+struct hvc_struct;
+
+/* Register a vterm and a slot index for use as a console (console_init) */
+extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops);
+
+/* register a vterm for hvc tty operation (module_init or hotplug add) */
+extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq,
+ struct hv_ops *ops);
+/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */
+extern int __devexit hvc_remove(struct hvc_struct *hp);
+
+#endif // HVC_CONSOLE_H
diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c
new file mode 100644
index 00000000000..83364ea63cb
--- /dev/null
+++ b/drivers/char/hvc_rtas.c
@@ -0,0 +1,138 @@
+/*
+ * IBM RTAS driver interface to hvc_console.c
+ *
+ * (C) Copyright IBM Corporation 2001-2005
+ * (C) Copyright Red Hat, Inc. 2005
+ *
+ * Author(s): Maximino Augilar <IBM STI Design Center>
+ * : Ryan S. Arnold <rsa@us.ibm.com>
+ * : Utz Bacher <utz.bacher@de.ibm.com>
+ * : David Woodhouse <dwmw2@infradead.org>
+ *
+ * inspired by drivers/char/hvc_console.c
+ * written by Anton Blanchard and Paul Mackerras
+ *
+ * This program is free software; 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/console.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+
+#include <asm/irq.h>
+#include <asm/rtas.h>
+#include "hvc_console.h"
+
+#define hvc_rtas_cookie 0x67781e15
+struct hvc_struct *hvc_rtas_dev;
+
+#define RTASCONS_PUT_ATTEMPTS 16
+
+static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE;
+static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE;
+static int rtascons_put_delay = 100;
+module_param_named(put_delay, rtascons_put_delay, int, 0644);
+
+static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, int count)
+{
+ int done;
+
+ /* if there is more than one character to be displayed, wait a bit */
+ for (done = 0; done < count; done++) {
+ int result;
+ result = rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[done]);
+ if (result)
+ break;
+ }
+ /* the calling routine expects to receive the number of bytes sent */
+ return done;
+}
+
+static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ int c, err;
+
+ err = rtas_call(rtascons_get_char_token, 0, 2, &c);
+ if (err)
+ break;
+
+ buf[i] = c;
+ }
+
+ return i;
+}
+
+static struct hv_ops hvc_rtas_get_put_ops = {
+ .get_chars = hvc_rtas_read_console,
+ .put_chars = hvc_rtas_write_console,
+};
+
+static int hvc_rtas_init(void)
+{
+ struct hvc_struct *hp;
+
+ if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
+ rtascons_put_char_token = rtas_token("put-term-char");
+ if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
+ return -EIO;
+
+ if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
+ rtascons_get_char_token = rtas_token("get-term-char");
+ if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
+ return -EIO;
+
+ BUG_ON(hvc_rtas_dev);
+
+ /* Allocate an hvc_struct for the console device we instantiated
+ * earlier. Save off hp so that we can return it on exit */
+ hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops);
+ if (IS_ERR(hp))
+ return PTR_ERR(hp);
+ hvc_rtas_dev = hp;
+ return 0;
+}
+module_init(hvc_rtas_init);
+
+/* This will tear down the tty portion of the driver */
+static void __exit hvc_rtas_exit(void)
+{
+ /* Really the fun isn't over until the worker thread breaks down and the
+ * tty cleans up */
+ if (hvc_rtas_dev)
+ hvc_remove(hvc_rtas_dev);
+}
+module_exit(hvc_rtas_exit);
+
+/* This will happen prior to module init. There is no tty at this time? */
+static int hvc_rtas_console_init(void)
+{
+ rtascons_put_char_token = rtas_token("put-term-char");
+ if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
+ return -EIO;
+ rtascons_get_char_token = rtas_token("get-term-char");
+ if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
+ return -EIO;
+
+ hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops );
+ add_preferred_console("hvc", 0, NULL);
+ return 0;
+}
+console_initcall(hvc_rtas_console_init);
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c
index f5212eb2b41..9add81ceb44 100644
--- a/drivers/char/hvc_vio.c
+++ b/drivers/char/hvc_vio.c
@@ -31,10 +31,13 @@
#include <linux/types.h>
#include <linux/init.h>
+
#include <asm/hvconsole.h>
#include <asm/vio.h>
#include <asm/prom.h>
+#include "hvc_console.h"
+
char hvc_driver_name[] = "hvc_console";
static struct vio_device_id hvc_driver_table[] __devinitdata = {
@@ -48,6 +51,14 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
unsigned long got;
int i;
+ /*
+ * Vio firmware will read up to SIZE_VIO_GET_CHARS at its own discretion
+ * so we play safe and avoid the situation where got > count which could
+ * overload the flip buffer.
+ */
+ if (count < SIZE_VIO_GET_CHARS)
+ return -EAGAIN;
+
got = hvc_get_chars(vtermno, buf, count);
/*
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index f7ac3185657..8d97b391129 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -439,7 +439,6 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
char buf[HVCS_BUFF_LEN] __ALIGNED__;
unsigned long flags;
int got = 0;
- int i;
spin_lock_irqsave(&hvcsd->lock, flags);
@@ -905,7 +904,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
* It is possible the vty-server was removed after the irq was
* requested but before we have time to enable interrupts.
*/
- if (vio_enable_interrupts(vdev) == H_Success)
+ if (vio_enable_interrupts(vdev) == H_SUCCESS)
return 0;
else {
printk(KERN_ERR "HVCS: int enable failed for"
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index 58dcdee1cd7..0030cd8e2e9 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -165,7 +165,7 @@ static int bt_start_transaction(struct si_sm_data *bt,
{
unsigned int i;
- if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH))
+ if ((size < 2) || (size > (IPMI_MAX_MSG_LENGTH - 2)))
return -1;
if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED))
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 932feedda26..e1c95374984 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -42,7 +42,7 @@
#include <linux/slab.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/ipmi.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/compat.h>
@@ -55,7 +55,7 @@ struct ipmi_file_private
struct file *file;
struct fasync_struct *fasync_queue;
wait_queue_head_t wait;
- struct semaphore recv_sem;
+ struct mutex recv_mutex;
int default_retries;
unsigned int default_retry_time_ms;
};
@@ -141,7 +141,7 @@ static int ipmi_open(struct inode *inode, struct file *file)
INIT_LIST_HEAD(&(priv->recv_msgs));
init_waitqueue_head(&priv->wait);
priv->fasync_queue = NULL;
- sema_init(&(priv->recv_sem), 1);
+ mutex_init(&priv->recv_mutex);
/* Use the low-level defaults. */
priv->default_retries = -1;
@@ -285,15 +285,15 @@ static int ipmi_ioctl(struct inode *inode,
break;
}
- /* We claim a semaphore because we don't want two
+ /* We claim a mutex because we don't want two
users getting something from the queue at a time.
Since we have to release the spinlock before we can
copy the data to the user, it's possible another
user will grab something from the queue, too. Then
the messages might get out of order if something
fails and the message gets put back onto the
- queue. This semaphore prevents that problem. */
- down(&(priv->recv_sem));
+ queue. This mutex prevents that problem. */
+ mutex_lock(&priv->recv_mutex);
/* Grab the message off the list. */
spin_lock_irqsave(&(priv->recv_msg_lock), flags);
@@ -352,7 +352,7 @@ static int ipmi_ioctl(struct inode *inode,
goto recv_putback_on_err;
}
- up(&(priv->recv_sem));
+ mutex_unlock(&priv->recv_mutex);
ipmi_free_recv_msg(msg);
break;
@@ -362,11 +362,11 @@ static int ipmi_ioctl(struct inode *inode,
spin_lock_irqsave(&(priv->recv_msg_lock), flags);
list_add(entry, &(priv->recv_msgs));
spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
- up(&(priv->recv_sem));
+ mutex_unlock(&priv->recv_mutex);
break;
recv_err:
- up(&(priv->recv_sem));
+ mutex_unlock(&priv->recv_mutex);
break;
}
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
index da1554194d3..2062675f9e9 100644
--- a/drivers/char/ipmi/ipmi_kcs_sm.c
+++ b/drivers/char/ipmi/ipmi_kcs_sm.c
@@ -227,7 +227,7 @@ static inline int check_ibf(struct si_sm_data *kcs, unsigned char status,
static inline int check_obf(struct si_sm_data *kcs, unsigned char status,
long time)
{
- if (! GET_STATUS_OBF(status)) {
+ if (!GET_STATUS_OBF(status)) {
kcs->obf_timeout -= time;
if (kcs->obf_timeout < 0) {
start_error_recovery(kcs, "OBF not ready in time");
@@ -407,7 +407,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
}
if (state == KCS_READ_STATE) {
- if (! check_obf(kcs, status, time))
+ if (!check_obf(kcs, status, time))
return SI_SM_CALL_WITH_DELAY;
read_next_byte(kcs);
} else {
@@ -447,7 +447,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
"Not in read state for error2");
break;
}
- if (! check_obf(kcs, status, time))
+ if (!check_obf(kcs, status, time))
return SI_SM_CALL_WITH_DELAY;
clear_obf(kcs, status);
@@ -462,7 +462,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
break;
}
- if (! check_obf(kcs, status, time))
+ if (!check_obf(kcs, status, time))
return SI_SM_CALL_WITH_DELAY;
clear_obf(kcs, status);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index b8fb87c6c29..9f2f8fdec69 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -38,6 +38,7 @@
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
@@ -234,7 +235,7 @@ struct ipmi_smi
/* The list of command receivers that are registered for commands
on this interface. */
- struct semaphore cmd_rcvrs_lock;
+ struct mutex cmd_rcvrs_mutex;
struct list_head cmd_rcvrs;
/* Events that were queues because no one was there to receive
@@ -387,10 +388,10 @@ static void clean_up_interface_data(ipmi_smi_t intf)
/* Wholesale remove all the entries from the list in the
* interface and wait for RCU to know that none are in use. */
- down(&intf->cmd_rcvrs_lock);
+ mutex_lock(&intf->cmd_rcvrs_mutex);
list_add_rcu(&list, &intf->cmd_rcvrs);
list_del_rcu(&intf->cmd_rcvrs);
- up(&intf->cmd_rcvrs_lock);
+ mutex_unlock(&intf->cmd_rcvrs_mutex);
synchronize_rcu();
list_for_each_entry_safe(rcvr, rcvr2, &list, link)
@@ -557,7 +558,7 @@ unsigned int ipmi_addr_length(int addr_type)
static void deliver_response(struct ipmi_recv_msg *msg)
{
- if (! msg->user) {
+ if (!msg->user) {
ipmi_smi_t intf = msg->user_msg_data;
unsigned long flags;
@@ -598,11 +599,11 @@ static int intf_next_seq(ipmi_smi_t intf,
(i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq;
i = (i+1)%IPMI_IPMB_NUM_SEQ)
{
- if (! intf->seq_table[i].inuse)
+ if (!intf->seq_table[i].inuse)
break;
}
- if (! intf->seq_table[i].inuse) {
+ if (!intf->seq_table[i].inuse) {
intf->seq_table[i].recv_msg = recv_msg;
/* Start with the maximum timeout, when the send response
@@ -763,7 +764,7 @@ int ipmi_create_user(unsigned int if_num,
}
new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
- if (! new_user)
+ if (!new_user)
return -ENOMEM;
spin_lock_irqsave(&interfaces_lock, flags);
@@ -819,14 +820,13 @@ static void free_user(struct kref *ref)
int ipmi_destroy_user(ipmi_user_t user)
{
- int rv = -ENODEV;
ipmi_smi_t intf = user->intf;
int i;
unsigned long flags;
struct cmd_rcvr *rcvr;
struct cmd_rcvr *rcvrs = NULL;
- user->valid = 1;
+ user->valid = 0;
/* Remove the user from the interface's sequence table. */
spin_lock_irqsave(&intf->seq_lock, flags);
@@ -847,7 +847,7 @@ int ipmi_destroy_user(ipmi_user_t user)
* since other things may be using it till we do
* synchronize_rcu()) then free everything in that list.
*/
- down(&intf->cmd_rcvrs_lock);
+ mutex_lock(&intf->cmd_rcvrs_mutex);
list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
if (rcvr->user == user) {
list_del_rcu(&rcvr->link);
@@ -855,7 +855,7 @@ int ipmi_destroy_user(ipmi_user_t user)
rcvrs = rcvr;
}
}
- up(&intf->cmd_rcvrs_lock);
+ mutex_unlock(&intf->cmd_rcvrs_mutex);
synchronize_rcu();
while (rcvrs) {
rcvr = rcvrs;
@@ -871,7 +871,7 @@ int ipmi_destroy_user(ipmi_user_t user)
kref_put(&user->refcount, free_user);
- return rv;
+ return 0;
}
void ipmi_get_version(ipmi_user_t user,
@@ -936,10 +936,12 @@ int ipmi_set_gets_events(ipmi_user_t user, int val)
if (val) {
/* Deliver any queued events. */
- list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) {
+ list_for_each_entry_safe(msg, msg2, &intf->waiting_events,
+ link) {
list_del(&msg->link);
list_add_tail(&msg->link, &msgs);
}
+ intf->waiting_events_count = 0;
}
/* Hold the events lock while doing this to preserve order. */
@@ -978,13 +980,13 @@ int ipmi_register_for_cmd(ipmi_user_t user,
rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL);
- if (! rcvr)
+ if (!rcvr)
return -ENOMEM;
rcvr->cmd = cmd;
rcvr->netfn = netfn;
rcvr->user = user;
- down(&intf->cmd_rcvrs_lock);
+ mutex_lock(&intf->cmd_rcvrs_mutex);
/* Make sure the command/netfn is not already registered. */
entry = find_cmd_rcvr(intf, netfn, cmd);
if (entry) {
@@ -995,7 +997,7 @@ int ipmi_register_for_cmd(ipmi_user_t user,
list_add_rcu(&rcvr->link, &intf->cmd_rcvrs);
out_unlock:
- up(&intf->cmd_rcvrs_lock);
+ mutex_unlock(&intf->cmd_rcvrs_mutex);
if (rv)
kfree(rcvr);
@@ -1009,17 +1011,17 @@ int ipmi_unregister_for_cmd(ipmi_user_t user,
ipmi_smi_t intf = user->intf;
struct cmd_rcvr *rcvr;
- down(&intf->cmd_rcvrs_lock);
+ mutex_lock(&intf->cmd_rcvrs_mutex);
/* Make sure the command/netfn is not already registered. */
rcvr = find_cmd_rcvr(intf, netfn, cmd);
if ((rcvr) && (rcvr->user == user)) {
list_del_rcu(&rcvr->link);
- up(&intf->cmd_rcvrs_lock);
+ mutex_unlock(&intf->cmd_rcvrs_mutex);
synchronize_rcu();
kfree(rcvr);
return 0;
} else {
- up(&intf->cmd_rcvrs_lock);
+ mutex_unlock(&intf->cmd_rcvrs_mutex);
return -ENOENT;
}
}
@@ -1514,7 +1516,7 @@ int ipmi_request_settime(ipmi_user_t user,
unsigned char saddr, lun;
int rv;
- if (! user)
+ if (!user)
return -EINVAL;
rv = check_addr(user->intf, addr, &saddr, &lun);
if (rv)
@@ -1545,7 +1547,7 @@ int ipmi_request_supply_msgs(ipmi_user_t user,
unsigned char saddr, lun;
int rv;
- if (! user)
+ if (!user)
return -EINVAL;
rv = check_addr(user->intf, addr, &saddr, &lun);
if (rv)
@@ -1570,7 +1572,7 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off,
char *out = (char *) page;
ipmi_smi_t intf = data;
int i;
- int rv= 0;
+ int rv = 0;
for (i = 0; i < IPMI_MAX_CHANNELS; i++)
rv += sprintf(out+rv, "%x ", intf->channels[i].address);
@@ -1989,7 +1991,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf)
} else {
bmc->dev = platform_device_alloc("ipmi_bmc",
bmc->id.device_id);
- if (! bmc->dev) {
+ if (!bmc->dev) {
printk(KERN_ERR
"ipmi_msghandler:"
" Unable to allocate platform device\n");
@@ -2305,8 +2307,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
void *send_info,
struct ipmi_device_id *device_id,
struct device *si_dev,
- unsigned char slave_addr,
- ipmi_smi_t *new_intf)
+ unsigned char slave_addr)
{
int i, j;
int rv;
@@ -2366,7 +2367,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
spin_lock_init(&intf->events_lock);
INIT_LIST_HEAD(&intf->waiting_events);
intf->waiting_events_count = 0;
- init_MUTEX(&intf->cmd_rcvrs_lock);
+ mutex_init(&intf->cmd_rcvrs_mutex);
INIT_LIST_HEAD(&intf->cmd_rcvrs);
init_waitqueue_head(&intf->waitq);
@@ -2388,9 +2389,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
if (rv)
goto out;
- /* FIXME - this is an ugly kludge, this sets the intf for the
- caller before sending any messages with it. */
- *new_intf = intf;
+ rv = handlers->start_processing(send_info, intf);
+ if (rv)
+ goto out;
get_guid(intf);
@@ -2622,7 +2623,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
spin_unlock_irqrestore(&intf->counter_lock, flags);
recv_msg = ipmi_alloc_recv_msg();
- if (! recv_msg) {
+ if (!recv_msg) {
/* We couldn't allocate memory for the
message, so requeue it for handling
later. */
@@ -2777,7 +2778,7 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
spin_unlock_irqrestore(&intf->counter_lock, flags);
recv_msg = ipmi_alloc_recv_msg();
- if (! recv_msg) {
+ if (!recv_msg) {
/* We couldn't allocate memory for the
message, so requeue it for handling
later. */
@@ -2869,13 +2870,14 @@ static int handle_read_event_rsp(ipmi_smi_t intf,
events. */
rcu_read_lock();
list_for_each_entry_rcu(user, &intf->users, link) {
- if (! user->gets_events)
+ if (!user->gets_events)
continue;
recv_msg = ipmi_alloc_recv_msg();
- if (! recv_msg) {
+ if (!recv_msg) {
rcu_read_unlock();
- list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) {
+ list_for_each_entry_safe(recv_msg, recv_msg2, &msgs,
+ link) {
list_del(&recv_msg->link);
ipmi_free_recv_msg(recv_msg);
}
@@ -2905,7 +2907,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf,
/* No one to receive the message, put it in queue if there's
not already too many things in the queue. */
recv_msg = ipmi_alloc_recv_msg();
- if (! recv_msg) {
+ if (!recv_msg) {
/* We couldn't allocate memory for the
message, so requeue it for handling
later. */
@@ -2915,6 +2917,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf,
copy_event_into_recv_msg(recv_msg, msg);
list_add_tail(&(recv_msg->link), &(intf->waiting_events));
+ intf->waiting_events_count++;
} else {
/* There's too many things in the queue, discard this
message. */
@@ -3190,7 +3193,7 @@ void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf)
rcu_read_lock();
list_for_each_entry_rcu(user, &intf->users, link) {
- if (! user->handler->ipmi_watchdog_pretimeout)
+ if (!user->handler->ipmi_watchdog_pretimeout)
continue;
user->handler->ipmi_watchdog_pretimeout(user->handler_data);
@@ -3278,7 +3281,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot,
ent->seqid);
- if (! smi_msg)
+ if (!smi_msg)
return;
spin_unlock_irqrestore(&intf->seq_lock, *flags);
@@ -3314,8 +3317,9 @@ static void ipmi_timeout_handler(long timeout_period)
/* See if any waiting messages need to be processed. */
spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
- list_for_each_entry_safe(smi_msg, smi_msg2, &intf->waiting_msgs, link) {
- if (! handle_new_recv_msg(intf, smi_msg)) {
+ list_for_each_entry_safe(smi_msg, smi_msg2,
+ &intf->waiting_msgs, link) {
+ if (!handle_new_recv_msg(intf, smi_msg)) {
list_del(&smi_msg->link);
ipmi_free_smi_msg(smi_msg);
} else {
@@ -3744,7 +3748,7 @@ static int ipmi_init_msghandler(void)
ipmi_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES;
add_timer(&ipmi_timer);
- notifier_chain_register(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
initialized = 1;
@@ -3764,7 +3768,7 @@ static __exit void cleanup_ipmi(void)
if (!initialized)
return;
- notifier_chain_unregister(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block);
/* This can't be called if any interfaces exist, so no worry about
shutting down the interfaces. */
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index 786a2802ca3..d0b5c08e7b4 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -346,7 +346,7 @@ static int ipmi_dell_chassis_detect (ipmi_user_t user)
{
const char ipmi_version_major = ipmi_version & 0xF;
const char ipmi_version_minor = (ipmi_version >> 4) & 0xF;
- const char mfr[3]=DELL_IANA_MFR_ID;
+ const char mfr[3] = DELL_IANA_MFR_ID;
if (!memcmp(mfr, &mfg_id, sizeof(mfr)) &&
ipmi_version_major <= 1 &&
ipmi_version_minor < 5)
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 12f858dc999..02a7dd7a8a5 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -237,10 +237,10 @@ struct smi_info
static int try_smi_init(struct smi_info *smi);
-static struct notifier_block *xaction_notifier_list;
+static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list);
static int register_xaction_notifier(struct notifier_block * nb)
{
- return notifier_chain_register(&xaction_notifier_list, nb);
+ return atomic_notifier_chain_register(&xaction_notifier_list, nb);
}
static void si_restart_short_timer(struct smi_info *smi_info);
@@ -302,7 +302,8 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
do_gettimeofday(&t);
printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
#endif
- err = notifier_call_chain(&xaction_notifier_list, 0, smi_info);
+ err = atomic_notifier_call_chain(&xaction_notifier_list,
+ 0, smi_info);
if (err & NOTIFY_STOP_MASK) {
rv = SI_SM_CALL_WITHOUT_DELAY;
goto out;
@@ -802,7 +803,7 @@ static int ipmi_thread(void *data)
set_user_nice(current, 19);
while (!kthread_should_stop()) {
spin_lock_irqsave(&(smi_info->si_lock), flags);
- smi_result=smi_event_handler(smi_info, 0);
+ smi_result = smi_event_handler(smi_info, 0);
spin_unlock_irqrestore(&(smi_info->si_lock), flags);
if (smi_result == SI_SM_CALL_WITHOUT_DELAY) {
/* do nothing */
@@ -971,10 +972,37 @@ static irqreturn_t si_bt_irq_handler(int irq, void *data, struct pt_regs *regs)
return si_irq_handler(irq, data, regs);
}
+static int smi_start_processing(void *send_info,
+ ipmi_smi_t intf)
+{
+ struct smi_info *new_smi = send_info;
+
+ new_smi->intf = intf;
+
+ /* Set up the timer that drives the interface. */
+ setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi);
+ new_smi->last_timeout_jiffies = jiffies;
+ mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
+
+ if (new_smi->si_type != SI_BT) {
+ new_smi->thread = kthread_run(ipmi_thread, new_smi,
+ "kipmi%d", new_smi->intf_num);
+ if (IS_ERR(new_smi->thread)) {
+ printk(KERN_NOTICE "ipmi_si_intf: Could not start"
+ " kernel thread due to error %ld, only using"
+ " timers to drive the interface\n",
+ PTR_ERR(new_smi->thread));
+ new_smi->thread = NULL;
+ }
+ }
+
+ return 0;
+}
static struct ipmi_smi_handlers handlers =
{
.owner = THIS_MODULE,
+ .start_processing = smi_start_processing,
.sender = sender,
.request_events = request_events,
.set_run_to_completion = set_run_to_completion,
@@ -986,7 +1014,7 @@ static struct ipmi_smi_handlers handlers =
#define SI_MAX_PARMS 4
static LIST_HEAD(smi_infos);
-static DECLARE_MUTEX(smi_infos_lock);
+static DEFINE_MUTEX(smi_infos_lock);
static int smi_num; /* Used to sequence the SMIs */
#define DEFAULT_REGSPACING 1
@@ -1156,20 +1184,20 @@ static void port_outl(struct si_sm_io *io, unsigned int offset,
static void port_cleanup(struct smi_info *info)
{
unsigned int addr = info->io.addr_data;
- int mapsize;
+ int idx;
if (addr) {
- mapsize = ((info->io_size * info->io.regspacing)
- - (info->io.regspacing - info->io.regsize));
-
- release_region (addr, mapsize);
+ for (idx = 0; idx < info->io_size; idx++) {
+ release_region(addr + idx * info->io.regspacing,
+ info->io.regsize);
+ }
}
}
static int port_setup(struct smi_info *info)
{
unsigned int addr = info->io.addr_data;
- int mapsize;
+ int idx;
if (!addr)
return -ENODEV;
@@ -1197,16 +1225,22 @@ static int port_setup(struct smi_info *info)
return -EINVAL;
}
- /* Calculate the total amount of memory to claim. This is an
- * unusual looking calculation, but it avoids claiming any
- * more memory than it has to. It will claim everything
- * between the first address to the end of the last full
- * register. */
- mapsize = ((info->io_size * info->io.regspacing)
- - (info->io.regspacing - info->io.regsize));
-
- if (request_region(addr, mapsize, DEVICE_NAME) == NULL)
- return -EIO;
+ /* Some BIOSes reserve disjoint I/O regions in their ACPI
+ * tables. This causes problems when trying to register the
+ * entire I/O region. Therefore we must register each I/O
+ * port separately.
+ */
+ for (idx = 0; idx < info->io_size; idx++) {
+ if (request_region(addr + idx * info->io.regspacing,
+ info->io.regsize, DEVICE_NAME) == NULL) {
+ /* Undo allocations */
+ while (idx--) {
+ release_region(addr + idx * info->io.regspacing,
+ info->io.regsize);
+ }
+ return -EIO;
+ }
+ }
return 0;
}
@@ -2161,16 +2195,20 @@ static void setup_xaction_handlers(struct smi_info *smi_info)
static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
{
- if (smi_info->thread != NULL && smi_info->thread != ERR_PTR(-ENOMEM))
- kthread_stop(smi_info->thread);
- del_timer_sync(&smi_info->si_timer);
+ if (smi_info->intf) {
+ /* The timer and thread are only running if the
+ interface has been started up and registered. */
+ if (smi_info->thread != NULL)
+ kthread_stop(smi_info->thread);
+ del_timer_sync(&smi_info->si_timer);
+ }
}
-static struct ipmi_default_vals
+static __devinitdata struct ipmi_default_vals
{
int type;
int port;
-} __devinit ipmi_defaults[] =
+} ipmi_defaults[] =
{
{ .type = SI_KCS, .port = 0xca2 },
{ .type = SI_SMIC, .port = 0xca9 },
@@ -2244,7 +2282,7 @@ static int try_smi_init(struct smi_info *new_smi)
new_smi->slave_addr, new_smi->irq);
}
- down(&smi_infos_lock);
+ mutex_lock(&smi_infos_lock);
if (!is_new_interface(new_smi)) {
printk(KERN_WARNING "ipmi_si: duplicate interface\n");
rv = -EBUSY;
@@ -2340,21 +2378,6 @@ static int try_smi_init(struct smi_info *new_smi)
if (new_smi->irq)
new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ;
- /* The ipmi_register_smi() code does some operations to
- determine the channel information, so we must be ready to
- handle operations before it is called. This means we have
- to stop the timer if we get an error after this point. */
- init_timer(&(new_smi->si_timer));
- new_smi->si_timer.data = (long) new_smi;
- new_smi->si_timer.function = smi_timeout;
- new_smi->last_timeout_jiffies = jiffies;
- new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
-
- add_timer(&(new_smi->si_timer));
- if (new_smi->si_type != SI_BT)
- new_smi->thread = kthread_run(ipmi_thread, new_smi,
- "kipmi%d", new_smi->intf_num);
-
if (!new_smi->dev) {
/* If we don't already have a device from something
* else (like PCI), then register a new one. */
@@ -2364,7 +2387,7 @@ static int try_smi_init(struct smi_info *new_smi)
printk(KERN_ERR
"ipmi_si_intf:"
" Unable to allocate platform device\n");
- goto out_err_stop_timer;
+ goto out_err;
}
new_smi->dev = &new_smi->pdev->dev;
new_smi->dev->driver = &ipmi_driver;
@@ -2376,7 +2399,7 @@ static int try_smi_init(struct smi_info *new_smi)
" Unable to register system interface device:"
" %d\n",
rv);
- goto out_err_stop_timer;
+ goto out_err;
}
new_smi->dev_registered = 1;
}
@@ -2385,8 +2408,7 @@ static int try_smi_init(struct smi_info *new_smi)
new_smi,
&new_smi->device_id,
new_smi->dev,
- new_smi->slave_addr,
- &(new_smi->intf));
+ new_smi->slave_addr);
if (rv) {
printk(KERN_ERR
"ipmi_si: Unable to register device: error %d\n",
@@ -2416,7 +2438,7 @@ static int try_smi_init(struct smi_info *new_smi)
list_add_tail(&new_smi->link, &smi_infos);
- up(&smi_infos_lock);
+ mutex_unlock(&smi_infos_lock);
printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
@@ -2453,7 +2475,7 @@ static int try_smi_init(struct smi_info *new_smi)
kfree(new_smi);
- up(&smi_infos_lock);
+ mutex_unlock(&smi_infos_lock);
return rv;
}
@@ -2511,26 +2533,26 @@ static __devinit int init_ipmi_si(void)
#endif
if (si_trydefaults) {
- down(&smi_infos_lock);
+ mutex_lock(&smi_infos_lock);
if (list_empty(&smi_infos)) {
/* No BMC was found, try defaults. */
- up(&smi_infos_lock);
+ mutex_unlock(&smi_infos_lock);
default_find_bmc();
} else {
- up(&smi_infos_lock);
+ mutex_unlock(&smi_infos_lock);
}
}
- down(&smi_infos_lock);
+ mutex_lock(&smi_infos_lock);
if (list_empty(&smi_infos)) {
- up(&smi_infos_lock);
+ mutex_unlock(&smi_infos_lock);
#ifdef CONFIG_PCI
pci_unregister_driver(&ipmi_pci_driver);
#endif
printk("ipmi_si: Unable to find any System Interface(s)\n");
return -ENODEV;
} else {
- up(&smi_infos_lock);
+ mutex_unlock(&smi_infos_lock);
return 0;
}
}
@@ -2606,10 +2628,10 @@ static __exit void cleanup_ipmi_si(void)
pci_unregister_driver(&ipmi_pci_driver);
#endif
- down(&smi_infos_lock);
+ mutex_lock(&smi_infos_lock);
list_for_each_entry_safe(e, tmp_e, &smi_infos, link)
cleanup_one_si(e);
- up(&smi_infos_lock);
+ mutex_unlock(&smi_infos_lock);
driver_unregister(&ipmi_driver);
}
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 616539310d9..2d11ddd99e5 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -39,6 +39,7 @@
#include <linux/watchdog.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
+#include <linux/completion.h>
#include <linux/rwsem.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
@@ -303,21 +304,22 @@ static int ipmi_heartbeat(void);
static void panic_halt_ipmi_heartbeat(void);
-/* We use a semaphore to make sure that only one thing can send a set
+/* We use a mutex to make sure that only one thing can send a set
timeout at one time, because we only have one copy of the data.
- The semaphore is claimed when the set_timeout is sent and freed
+ The mutex is claimed when the set_timeout is sent and freed
when both messages are free. */
static atomic_t set_timeout_tofree = ATOMIC_INIT(0);
-static DECLARE_MUTEX(set_timeout_lock);
+static DEFINE_MUTEX(set_timeout_lock);
+static DECLARE_COMPLETION(set_timeout_wait);
static void set_timeout_free_smi(struct ipmi_smi_msg *msg)
{
if (atomic_dec_and_test(&set_timeout_tofree))
- up(&set_timeout_lock);
+ complete(&set_timeout_wait);
}
static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
{
if (atomic_dec_and_test(&set_timeout_tofree))
- up(&set_timeout_lock);
+ complete(&set_timeout_wait);
}
static struct ipmi_smi_msg set_timeout_smi_msg =
{
@@ -399,7 +401,7 @@ static int ipmi_set_timeout(int do_heartbeat)
/* We can only send one of these at a time. */
- down(&set_timeout_lock);
+ mutex_lock(&set_timeout_lock);
atomic_set(&set_timeout_tofree, 2);
@@ -407,16 +409,21 @@ static int ipmi_set_timeout(int do_heartbeat)
&set_timeout_recv_msg,
&send_heartbeat_now);
if (rv) {
- up(&set_timeout_lock);
- } else {
- if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
- || ((send_heartbeat_now)
- && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
- {
- rv = ipmi_heartbeat();
- }
+ mutex_unlock(&set_timeout_lock);
+ goto out;
}
+ wait_for_completion(&set_timeout_wait);
+
+ if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
+ || ((send_heartbeat_now)
+ && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
+ {
+ rv = ipmi_heartbeat();
+ }
+ mutex_unlock(&set_timeout_lock);
+
+out:
return rv;
}
@@ -458,17 +465,17 @@ static void panic_halt_ipmi_set_timeout(void)
The semaphore is claimed when the set_timeout is sent and freed
when both messages are free. */
static atomic_t heartbeat_tofree = ATOMIC_INIT(0);
-static DECLARE_MUTEX(heartbeat_lock);
-static DECLARE_MUTEX_LOCKED(heartbeat_wait_lock);
+static DEFINE_MUTEX(heartbeat_lock);
+static DECLARE_COMPLETION(heartbeat_wait);
static void heartbeat_free_smi(struct ipmi_smi_msg *msg)
{
if (atomic_dec_and_test(&heartbeat_tofree))
- up(&heartbeat_wait_lock);
+ complete(&heartbeat_wait);
}
static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
{
if (atomic_dec_and_test(&heartbeat_tofree))
- up(&heartbeat_wait_lock);
+ complete(&heartbeat_wait);
}
static struct ipmi_smi_msg heartbeat_smi_msg =
{
@@ -511,14 +518,14 @@ static int ipmi_heartbeat(void)
return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
}
- down(&heartbeat_lock);
+ mutex_lock(&heartbeat_lock);
atomic_set(&heartbeat_tofree, 2);
/* Don't reset the timer if we have the timer turned off, that
re-enables the watchdog. */
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {
- up(&heartbeat_lock);
+ mutex_unlock(&heartbeat_lock);
return 0;
}
@@ -539,14 +546,14 @@ static int ipmi_heartbeat(void)
&heartbeat_recv_msg,
1);
if (rv) {
- up(&heartbeat_lock);
+ mutex_unlock(&heartbeat_lock);
printk(KERN_WARNING PFX "heartbeat failure: %d\n",
rv);
return rv;
}
/* Wait for the heartbeat to be sent. */
- down(&heartbeat_wait_lock);
+ wait_for_completion(&heartbeat_wait);
if (heartbeat_recv_msg.msg.data[0] != 0) {
/* Got an error in the heartbeat response. It was already
@@ -555,7 +562,7 @@ static int ipmi_heartbeat(void)
rv = -EINVAL;
}
- up(&heartbeat_lock);
+ mutex_unlock(&heartbeat_lock);
return rv;
}
@@ -589,7 +596,7 @@ static void panic_halt_ipmi_heartbeat(void)
1);
}
-static struct watchdog_info ident=
+static struct watchdog_info ident =
{
.options = 0, /* WDIOF_SETTIMEOUT, */
.firmware_version = 1,
@@ -790,13 +797,13 @@ static int ipmi_fasync(int fd, struct file *file, int on)
static int ipmi_close(struct inode *ino, struct file *filep)
{
- if (iminor(ino)==WATCHDOG_MINOR)
- {
+ if (iminor(ino) == WATCHDOG_MINOR) {
if (expect_close == 42) {
ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
} else {
- printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+ printk(KERN_CRIT PFX
+ "Unexpected close, not stopping watchdog!\n");
ipmi_heartbeat();
}
clear_bit(0, &ipmi_wdog_open);
@@ -1158,7 +1165,8 @@ static int __init ipmi_wdog_init(void)
}
register_reboot_notifier(&wdog_reboot_notifier);
- notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &wdog_panic_notifier);
printk(KERN_INFO PFX "driver initialized\n");
@@ -1176,7 +1184,8 @@ static __exit void ipmi_unregister_watchdog(void)
release_nmi(&ipmi_nmi_handler);
#endif
- notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier);
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &wdog_panic_notifier);
unregister_reboot_notifier(&wdog_reboot_notifier);
if (! watchdog_user)
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index e5247f85a44..ef20c1fc9c4 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -706,7 +706,6 @@ static int stli_portcmdstats(stliport_t *portp);
static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp);
static int stli_getportstruct(stliport_t __user *arg);
static int stli_getbrdstruct(stlibrd_t __user *arg);
-static void *stli_memalloc(int len);
static stlibrd_t *stli_allocbrd(void);
static void stli_ecpinit(stlibrd_t *brdp);
@@ -997,17 +996,6 @@ static int stli_parsebrd(stlconf_t *confp, char **argp)
/*****************************************************************************/
-/*
- * Local driver kernel malloc routine.
- */
-
-static void *stli_memalloc(int len)
-{
- return((void *) kmalloc(len, GFP_KERNEL));
-}
-
-/*****************************************************************************/
-
static int stli_open(struct tty_struct *tty, struct file *filp)
{
stlibrd_t *brdp;
@@ -3227,13 +3215,12 @@ static int stli_initports(stlibrd_t *brdp)
#endif
for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
- portp = (stliport_t *) stli_memalloc(sizeof(stliport_t));
- if (portp == (stliport_t *) NULL) {
+ portp = kzalloc(sizeof(stliport_t), GFP_KERNEL);
+ if (!portp) {
printk("STALLION: failed to allocate port structure\n");
continue;
}
- memset(portp, 0, sizeof(stliport_t));
portp->magic = STLI_PORTMAGIC;
portp->portnr = i;
portp->brdnr = brdp->brdnr;
@@ -4610,14 +4597,13 @@ static stlibrd_t *stli_allocbrd(void)
{
stlibrd_t *brdp;
- brdp = (stlibrd_t *) stli_memalloc(sizeof(stlibrd_t));
- if (brdp == (stlibrd_t *) NULL) {
+ brdp = kzalloc(sizeof(stlibrd_t), GFP_KERNEL);
+ if (!brdp) {
printk(KERN_ERR "STALLION: failed to allocate memory "
"(size=%d)\n", sizeof(stlibrd_t));
- return((stlibrd_t *) NULL);
+ return NULL;
}
- memset(brdp, 0, sizeof(stlibrd_t));
brdp->magic = STLI_BOARDMAGIC;
return(brdp);
}
@@ -5210,12 +5196,12 @@ int __init stli_init(void)
/*
* Allocate a temporary write buffer.
*/
- stli_tmpwritebuf = (char *) stli_memalloc(STLI_TXBUFSIZE);
- if (stli_tmpwritebuf == (char *) NULL)
+ stli_tmpwritebuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
+ if (!stli_tmpwritebuf)
printk(KERN_ERR "STALLION: failed to allocate memory "
"(size=%d)\n", STLI_TXBUFSIZE);
- stli_txcookbuf = stli_memalloc(STLI_TXBUFSIZE);
- if (stli_txcookbuf == (char *) NULL)
+ stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
+ if (!stli_txcookbuf)
printk(KERN_ERR "STALLION: failed to allocate memory "
"(size=%d)\n", STLI_TXBUFSIZE);
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 8b603b2d1c4..5755b7e5f18 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -74,7 +74,7 @@ void compute_shiftstate(void);
k_self, k_fn, k_spec, k_pad,\
k_dead, k_cons, k_cur, k_shift,\
k_meta, k_ascii, k_lock, k_lowercase,\
- k_slock, k_dead2, k_ignore, k_ignore
+ k_slock, k_dead2, k_brl, k_ignore
typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
char up_flag, struct pt_regs *regs);
@@ -100,7 +100,7 @@ static fn_handler_fn *fn_handler[] = { FN_HANDLERS };
const int max_vals[] = {
255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1,
NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1,
- 255, NR_LOCK - 1, 255
+ 255, NR_LOCK - 1, 255, NR_BRL - 1
};
const int NR_TYPES = ARRAY_SIZE(max_vals);
@@ -126,7 +126,7 @@ static unsigned long key_down[NBITS(KEY_MAX)]; /* keyboard key bitmap */
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
static int dead_key_next;
static int npadch = -1; /* -1 or number assembled on pad */
-static unsigned char diacr;
+static unsigned int diacr;
static char rep; /* flag telling character repeat */
static unsigned char ledstate = 0xff; /* undefined */
@@ -394,22 +394,30 @@ void compute_shiftstate(void)
* Otherwise, conclude that DIACR was not combining after all,
* queue it and return CH.
*/
-static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch)
+static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
{
- int d = diacr;
+ unsigned int d = diacr;
unsigned int i;
diacr = 0;
- for (i = 0; i < accent_table_size; i++) {
- if (accent_table[i].diacr == d && accent_table[i].base == ch)
- return accent_table[i].result;
+ if ((d & ~0xff) == BRL_UC_ROW) {
+ if ((ch & ~0xff) == BRL_UC_ROW)
+ return d | ch;
+ } else {
+ for (i = 0; i < accent_table_size; i++)
+ if (accent_table[i].diacr == d && accent_table[i].base == ch)
+ return accent_table[i].result;
}
- if (ch == ' ' || ch == d)
+ if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d)
return d;
- put_queue(vc, d);
+ if (kbd->kbdmode == VC_UNICODE)
+ to_utf8(vc, d);
+ else if (d < 0x100)
+ put_queue(vc, d);
+
return ch;
}
@@ -419,7 +427,10 @@ static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch)
static void fn_enter(struct vc_data *vc, struct pt_regs *regs)
{
if (diacr) {
- put_queue(vc, diacr);
+ if (kbd->kbdmode == VC_UNICODE)
+ to_utf8(vc, diacr);
+ else if (diacr < 0x100)
+ put_queue(vc, diacr);
diacr = 0;
}
put_queue(vc, 13);
@@ -615,7 +626,7 @@ static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag, s
printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n");
}
-static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs)
{
if (up_flag)
return; /* no action, if this is a key release */
@@ -628,7 +639,10 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct
diacr = value;
return;
}
- put_queue(vc, value);
+ if (kbd->kbdmode == VC_UNICODE)
+ to_utf8(vc, value);
+ else if (value < 0x100)
+ put_queue(vc, value);
}
/*
@@ -636,13 +650,23 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct
* dead keys modifying the same character. Very useful
* for Vietnamese.
*/
-static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs)
{
if (up_flag)
return;
diacr = (diacr ? handle_diacr(vc, value) : value);
}
+static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+{
+ k_unicode(vc, value, up_flag, regs);
+}
+
+static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+{
+ k_deadunicode(vc, value, up_flag, regs);
+}
+
/*
* Obsolete - for backwards compatibility only
*/
@@ -650,7 +674,7 @@ static void k_dead(struct vc_data *vc, unsigned char value, char up_flag, struct
{
static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
value = ret_diacr[value];
- k_dead2(vc, value, up_flag, regs);
+ k_deadunicode(vc, value, up_flag, regs);
}
static void k_cons(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
@@ -835,6 +859,80 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag, struc
}
}
+/* by default, 300ms interval for combination release */
+static unsigned brl_timeout = 300;
+MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
+module_param(brl_timeout, uint, 0644);
+
+static unsigned brl_nbchords = 1;
+MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
+module_param(brl_nbchords, uint, 0644);
+
+static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag, struct pt_regs *regs)
+{
+ static unsigned long chords;
+ static unsigned committed;
+
+ if (!brl_nbchords)
+ k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag, regs);
+ else {
+ committed |= pattern;
+ chords++;
+ if (chords == brl_nbchords) {
+ k_unicode(vc, BRL_UC_ROW | committed, up_flag, regs);
+ chords = 0;
+ committed = 0;
+ }
+ }
+}
+
+static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
+{
+ static unsigned pressed,committing;
+ static unsigned long releasestart;
+
+ if (kbd->kbdmode != VC_UNICODE) {
+ if (!up_flag)
+ printk("keyboard mode must be unicode for braille patterns\n");
+ return;
+ }
+
+ if (!value) {
+ k_unicode(vc, BRL_UC_ROW, up_flag, regs);
+ return;
+ }
+
+ if (value > 8)
+ return;
+
+ if (up_flag) {
+ if (brl_timeout) {
+ if (!committing ||
+ jiffies - releasestart > (brl_timeout * HZ) / 1000) {
+ committing = pressed;
+ releasestart = jiffies;
+ }
+ pressed &= ~(1 << (value - 1));
+ if (!pressed) {
+ if (committing) {
+ k_brlcommit(vc, committing, 0, regs);
+ committing = 0;
+ }
+ }
+ } else {
+ if (committing) {
+ k_brlcommit(vc, committing, 0, regs);
+ committing = 0;
+ }
+ pressed &= ~(1 << (value - 1));
+ }
+ } else {
+ pressed |= 1 << (value - 1);
+ if (!brl_timeout)
+ committing = pressed;
+ }
+}
+
/*
* The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
* or (ii) whatever pattern of lights people want to show using KDSETLED,
@@ -1125,9 +1223,13 @@ static void kbd_keycode(unsigned int keycode, int down,
}
if (keycode > NR_KEYS)
- return;
+ if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
+ keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1);
+ else
+ return;
+ else
+ keysym = key_map[keycode];
- keysym = key_map[keycode];
type = KTYP(keysym);
if (type < 0xf0) {
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 5245ba1649e..1fa9fa157c1 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -27,6 +27,7 @@
#include <linux/crash_dump.h>
#include <linux/backing-dev.h>
#include <linux/bootmem.h>
+#include <linux/pipe_fs_i.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -578,6 +579,18 @@ static ssize_t write_null(struct file * file, const char __user * buf,
return count;
}
+static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf,
+ struct splice_desc *sd)
+{
+ return sd->len;
+}
+
+static ssize_t splice_write_null(struct pipe_inode_info *pipe,struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags)
+{
+ return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null);
+}
+
#ifdef CONFIG_MMU
/*
* For fun, we are using the MMU for this.
@@ -785,6 +798,7 @@ static struct file_operations null_fops = {
.llseek = null_lseek,
.read = read_null,
.write = write_null,
+ .splice_write = splice_write_null,
};
#if defined(CONFIG_ISA) || !defined(__mc68000__)
@@ -899,7 +913,7 @@ static const struct {
unsigned int minor;
char *name;
umode_t mode;
- struct file_operations *fops;
+ const struct file_operations *fops;
} devlist[] = { /* list of minor devices */
{1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
{2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 3e4c0414a01..96eb2a709e2 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -129,7 +129,7 @@ static int misc_open(struct inode * inode, struct file * file)
int minor = iminor(inode);
struct miscdevice *c;
int err = -ENODEV;
- struct file_operations *old_fops, *new_fops = NULL;
+ const struct file_operations *old_fops, *new_fops = NULL;
down(&misc_sem);
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index 8666171e187..d3ba2f860ef 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -271,7 +271,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
ipcnum,
pDrvData->IPCs[ipcnum].usIntCount);
- if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) {
+ if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
PRINTK_ERROR(KERN_ERR_MWAVE
"mwavedd::mwave_ioctl:"
" IOCTL_MW_REGISTER_IPC:"
diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h
index e7fd0b08e0b..7e188a4d602 100644
--- a/drivers/char/mxser.h
+++ b/drivers/char/mxser.h
@@ -118,7 +118,7 @@
// enable CTS interrupt
#define MOXA_MUST_IER_ECTSI 0x80
-// eanble RTS interrupt
+// enable RTS interrupt
#define MOXA_MUST_IER_ERTSI 0x40
// enable Xon/Xoff interrupt
#define MOXA_MUST_IER_XINT 0x20
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index ede365d0538..b9371d5bf79 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -1384,8 +1384,10 @@ do_it_again:
* longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
* we won't get any more characters.
*/
- if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE)
+ if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) {
+ n_tty_set_room(tty);
check_unthrottle(tty);
+ }
if (b - buf >= minimum)
break;
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 5fdf1851543..eab5394da66 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -46,7 +46,7 @@
/* #define ATR_CSUM */
#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x) (&handle_to_dev(x->link.handle))
+#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle))
static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0600);
#define DEBUGP(n, rdr, x, args...) do { \
@@ -67,7 +67,7 @@ static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte";
#define T_100MSEC msecs_to_jiffies(100)
#define T_500MSEC msecs_to_jiffies(500)
-static void cm4000_release(dev_link_t *link);
+static void cm4000_release(struct pcmcia_device *link);
static int major; /* major number we get from the kernel */
@@ -106,7 +106,7 @@ static int major; /* major number we get from the kernel */
#define REG_STOPBITS(x) (x + 7)
struct cm4000_dev {
- dev_link_t link; /* pcmcia link */
+ struct pcmcia_device *p_dev;
dev_node_t node; /* OS node (major,minor) */
unsigned char atr[MAX_ATR];
@@ -149,14 +149,14 @@ struct cm4000_dev {
#define ZERO_DEV(dev) \
memset(&dev->atr_csum,0, \
sizeof(struct cm4000_dev) - \
- /*link*/ sizeof(dev_link_t) - \
+ /*link*/ sizeof(struct pcmcia_device *) - \
/*node*/ sizeof(dev_node_t) - \
/*atr*/ MAX_ATR*sizeof(char) - \
/*rbuf*/ 512*sizeof(char) - \
/*sbuf*/ 512*sizeof(char) - \
/*queue*/ 4*sizeof(wait_queue_head_t))
-static dev_link_t *dev_table[CM4000_MAX_DEV];
+static struct pcmcia_device *dev_table[CM4000_MAX_DEV];
static struct class *cmm_class;
/* This table doesn't use spaces after the comma between fields and thus
@@ -454,7 +454,7 @@ static struct card_fixup card_fixups[] = {
static void set_cardparameter(struct cm4000_dev *dev)
{
int i;
- ioaddr_t iobase = dev->link.io.BasePort1;
+ ioaddr_t iobase = dev->p_dev->io.BasePort1;
u_int8_t stopbits = 0x02; /* ISO default */
DEBUGP(3, dev, "-> set_cardparameter\n");
@@ -487,7 +487,7 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)
unsigned short num_bytes_read;
unsigned char pts_reply[4];
ssize_t rc;
- ioaddr_t iobase = dev->link.io.BasePort1;
+ ioaddr_t iobase = dev->p_dev->io.BasePort1;
rc = 0;
@@ -699,7 +699,7 @@ static void terminate_monitor(struct cm4000_dev *dev)
static void monitor_card(unsigned long p)
{
struct cm4000_dev *dev = (struct cm4000_dev *) p;
- ioaddr_t iobase = dev->link.io.BasePort1;
+ ioaddr_t iobase = dev->p_dev->io.BasePort1;
unsigned short s;
struct ptsreq ptsreq;
int i, atrc;
@@ -962,7 +962,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count,
loff_t *ppos)
{
struct cm4000_dev *dev = filp->private_data;
- ioaddr_t iobase = dev->link.io.BasePort1;
+ ioaddr_t iobase = dev->p_dev->io.BasePort1;
ssize_t rc;
int i, j, k;
@@ -971,7 +971,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count,
if (count == 0) /* according to manpage */
return 0;
- if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */
+ if (!pcmcia_dev_present(dev->p_dev) || /* device removed */
test_bit(IS_CMM_ABSENT, &dev->flags))
return -ENODEV;
@@ -1083,7 +1083,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf,
size_t count, loff_t *ppos)
{
struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data;
- ioaddr_t iobase = dev->link.io.BasePort1;
+ ioaddr_t iobase = dev->p_dev->io.BasePort1;
unsigned short s;
unsigned char tmp;
unsigned char infolen;
@@ -1108,7 +1108,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf,
sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0;
- if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */
+ if (!pcmcia_dev_present(dev->p_dev) || /* device removed */
test_bit(IS_CMM_ABSENT, &dev->flags))
return -ENODEV;
@@ -1440,8 +1440,8 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
struct cm4000_dev *dev = filp->private_data;
- ioaddr_t iobase = dev->link.io.BasePort1;
- dev_link_t *link;
+ ioaddr_t iobase = dev->p_dev->io.BasePort1;
+ struct pcmcia_device *link;
int size;
int rc;
void __user *argp = (void __user *)arg;
@@ -1458,7 +1458,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
iminor(inode), ioctl_names[_IOC_NR(cmd)]);
link = dev_table[iminor(inode)];
- if (!(DEV_OK(link))) {
+ if (!pcmcia_dev_present(link)) {
DEBUGP(4, dev, "DEV_OK false\n");
return -ENODEV;
}
@@ -1660,14 +1660,14 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
static int cmm_open(struct inode *inode, struct file *filp)
{
struct cm4000_dev *dev;
- dev_link_t *link;
+ struct pcmcia_device *link;
int rc, minor = iminor(inode);
if (minor >= CM4000_MAX_DEV)
return -ENODEV;
link = dev_table[minor];
- if (link == NULL || !(DEV_OK(link)))
+ if (link == NULL || !pcmcia_dev_present(link))
return -ENODEV;
if (link->open)
@@ -1709,7 +1709,7 @@ static int cmm_open(struct inode *inode, struct file *filp)
static int cmm_close(struct inode *inode, struct file *filp)
{
struct cm4000_dev *dev;
- dev_link_t *link;
+ struct pcmcia_device *link;
int minor = iminor(inode);
if (minor >= CM4000_MAX_DEV)
@@ -1735,7 +1735,7 @@ static int cmm_close(struct inode *inode, struct file *filp)
return 0;
}
-static void cmm_cm4000_release(dev_link_t * link)
+static void cmm_cm4000_release(struct pcmcia_device * link)
{
struct cm4000_dev *dev = link->priv;
@@ -1759,13 +1759,11 @@ static void cmm_cm4000_release(dev_link_t * link)
/*==== Interface to PCMCIA Layer =======================================*/
-static void cm4000_config(dev_link_t * link, int devno)
+static int cm4000_config(struct pcmcia_device * link, int devno)
{
- client_handle_t handle = link->handle;
struct cm4000_dev *dev;
tuple_t tuple;
cisparse_t parse;
- config_info_t conf;
u_char buf[64];
int fail_fn, fail_rc;
int rc;
@@ -1777,41 +1775,34 @@ static void cm4000_config(dev_link_t * link, int devno)
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) {
+ if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) {
fail_fn = GetFirstTuple;
goto cs_failed;
}
- if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) {
+ if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) {
fail_fn = GetTupleData;
goto cs_failed;
}
if ((fail_rc =
- pcmcia_parse_tuple(handle, &tuple, &parse)) != CS_SUCCESS) {
+ pcmcia_parse_tuple(link, &tuple, &parse)) != CS_SUCCESS) {
fail_fn = ParseTuple;
goto cs_failed;
}
- if ((fail_rc =
- pcmcia_get_configuration_info(handle, &conf)) != CS_SUCCESS) {
- fail_fn = GetConfigurationInfo;
- goto cs_failed;
- }
- link->state |= DEV_CONFIG;
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- link->conf.Vcc = conf.Vcc;
link->io.BasePort2 = 0;
link->io.NumPorts2 = 0;
link->io.Attributes2 = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (rc = pcmcia_get_first_tuple(handle, &tuple);
- rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(handle, &tuple)) {
+ for (rc = pcmcia_get_first_tuple(link, &tuple);
+ rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) {
- rc = pcmcia_get_tuple_data(handle, &tuple);
+ rc = pcmcia_get_tuple_data(link, &tuple);
if (rc != CS_SUCCESS)
continue;
- rc = pcmcia_parse_tuple(handle, &tuple, &parse);
+ rc = pcmcia_parse_tuple(link, &tuple, &parse);
if (rc != CS_SUCCESS)
continue;
@@ -1831,7 +1822,7 @@ static void cm4000_config(dev_link_t * link, int devno)
link->io.IOAddrLines = parse.cftable_entry.io.flags
& CISTPL_IO_LINES_MASK;
- rc = pcmcia_request_io(handle, &link->io);
+ rc = pcmcia_request_io(link, &link->io);
if (rc == CS_SUCCESS)
break; /* we are done */
}
@@ -1841,7 +1832,7 @@ static void cm4000_config(dev_link_t * link, int devno)
link->conf.IntType = 00000002;
if ((fail_rc =
- pcmcia_request_configuration(handle, &link->conf)) != CS_SUCCESS) {
+ pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) {
fail_fn = RequestConfiguration;
goto cs_release;
}
@@ -1851,63 +1842,48 @@ static void cm4000_config(dev_link_t * link, int devno)
dev->node.major = major;
dev->node.minor = devno;
dev->node.next = NULL;
- link->dev = &dev->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &dev->node;
- return;
+ return 0;
cs_failed:
- cs_error(handle, fail_fn, fail_rc);
+ cs_error(link, fail_fn, fail_rc);
cs_release:
cm4000_release(link);
-
- link->state &= ~DEV_CONFIG_PENDING;
+ return -ENODEV;
}
-static int cm4000_suspend(struct pcmcia_device *p_dev)
+static int cm4000_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev;
dev = link->priv;
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
stop_monitor(dev);
return 0;
}
-static int cm4000_resume(struct pcmcia_device *p_dev)
+static int cm4000_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev;
dev = link->priv;
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
-
if (link->open)
start_monitor(dev);
return 0;
}
-static void cm4000_release(dev_link_t *link)
+static void cm4000_release(struct pcmcia_device *link)
{
cmm_cm4000_release(link->priv); /* delay release until device closed */
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
+ pcmcia_disable_device(link);
}
-static int cm4000_attach(struct pcmcia_device *p_dev)
+static int cm4000_probe(struct pcmcia_device *link)
{
struct cm4000_dev *dev;
- dev_link_t *link;
- int i;
+ int i, ret;
for (i = 0; i < CM4000_MAX_DEV; i++)
if (dev_table[i] == NULL)
@@ -1923,7 +1899,7 @@ static int cm4000_attach(struct pcmcia_device *p_dev)
if (dev == NULL)
return -ENOMEM;
- link = &dev->link;
+ dev->p_dev = link;
link->priv = dev;
link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link;
@@ -1933,11 +1909,9 @@ static int cm4000_attach(struct pcmcia_device *p_dev)
init_waitqueue_head(&dev->atrq);
init_waitqueue_head(&dev->readq);
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- cm4000_config(link, i);
+ ret = cm4000_config(link, i);
+ if (ret)
+ return ret;
class_device_create(cmm_class, NULL, MKDEV(major, i), NULL,
"cmm%d", i);
@@ -1945,9 +1919,8 @@ static int cm4000_attach(struct pcmcia_device *p_dev)
return 0;
}
-static void cm4000_detach(struct pcmcia_device *p_dev)
+static void cm4000_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev = link->priv;
int devno;
@@ -1958,11 +1931,9 @@ static void cm4000_detach(struct pcmcia_device *p_dev)
if (devno == CM4000_MAX_DEV)
return;
- link->state &= ~DEV_PRESENT;
stop_monitor(dev);
- if (link->state & DEV_CONFIG)
- cm4000_release(link);
+ cm4000_release(link);
dev_table[devno] = NULL;
kfree(dev);
@@ -1993,7 +1964,7 @@ static struct pcmcia_driver cm4000_driver = {
.drv = {
.name = "cm4000_cs",
},
- .probe = cm4000_attach,
+ .probe = cm4000_probe,
.remove = cm4000_detach,
.suspend = cm4000_suspend,
.resume = cm4000_resume,
@@ -2010,10 +1981,6 @@ static int __init cmm_init(void)
if (!cmm_class)
return -1;
- rc = pcmcia_register_driver(&cm4000_driver);
- if (rc < 0)
- return rc;
-
major = register_chrdev(0, DEVICE_NAME, &cm4000_fops);
if (major < 0) {
printk(KERN_WARNING MODULE_NAME
@@ -2021,6 +1988,12 @@ static int __init cmm_init(void)
return -1;
}
+ rc = pcmcia_register_driver(&cm4000_driver);
+ if (rc < 0) {
+ unregister_chrdev(major, DEVICE_NAME);
+ return rc;
+ }
+
return 0;
}
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 466e33bab02..47a8465bf95 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -41,7 +41,7 @@
#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x) (&handle_to_dev(x->link.handle))
+#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle))
static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0600);
#define DEBUGP(n, rdr, x, args...) do { \
@@ -65,7 +65,7 @@ static char *version =
/* how often to poll for fifo status change */
#define POLL_PERIOD msecs_to_jiffies(10)
-static void reader_release(dev_link_t *link);
+static void reader_release(struct pcmcia_device *link);
static int major;
static struct class *cmx_class;
@@ -74,7 +74,7 @@ static struct class *cmx_class;
#define BS_WRITABLE 0x02
struct reader_dev {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
wait_queue_head_t devq;
wait_queue_head_t poll_wait;
@@ -87,7 +87,7 @@ struct reader_dev {
struct timer_list poll_timer;
};
-static dev_link_t *dev_table[CM_MAX_DEV];
+static struct pcmcia_device *dev_table[CM_MAX_DEV];
#ifndef PCMCIA_DEBUG
#define xoutb outb
@@ -116,7 +116,7 @@ static inline unsigned char xinb(unsigned short port)
static void cm4040_do_poll(unsigned long dummy)
{
struct reader_dev *dev = (struct reader_dev *) dummy;
- unsigned int obs = xinb(dev->link.io.BasePort1
+ unsigned int obs = xinb(dev->p_dev->io.BasePort1
+ REG_OFFSET_BUFFER_STATUS);
if ((obs & BSR_BULK_IN_FULL)) {
@@ -147,7 +147,7 @@ static void cm4040_stop_poll(struct reader_dev *dev)
static int wait_for_bulk_out_ready(struct reader_dev *dev)
{
int i, rc;
- int iobase = dev->link.io.BasePort1;
+ int iobase = dev->p_dev->io.BasePort1;
for (i = 0; i < POLL_LOOP_COUNT; i++) {
if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS)
@@ -177,7 +177,7 @@ static int wait_for_bulk_out_ready(struct reader_dev *dev)
/* Write to Sync Control Register */
static int write_sync_reg(unsigned char val, struct reader_dev *dev)
{
- int iobase = dev->link.io.BasePort1;
+ int iobase = dev->p_dev->io.BasePort1;
int rc;
rc = wait_for_bulk_out_ready(dev);
@@ -195,7 +195,7 @@ static int write_sync_reg(unsigned char val, struct reader_dev *dev)
static int wait_for_bulk_in_ready(struct reader_dev *dev)
{
int i, rc;
- int iobase = dev->link.io.BasePort1;
+ int iobase = dev->p_dev->io.BasePort1;
for (i = 0; i < POLL_LOOP_COUNT; i++) {
if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS)
@@ -225,7 +225,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf,
size_t count, loff_t *ppos)
{
struct reader_dev *dev = filp->private_data;
- int iobase = dev->link.io.BasePort1;
+ int iobase = dev->p_dev->io.BasePort1;
size_t bytes_to_read;
unsigned long i;
size_t min_bytes_to_read;
@@ -246,7 +246,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf,
return -EAGAIN;
}
- if ((dev->link.state & DEV_PRESENT)==0)
+ if (!pcmcia_dev_present(dev->p_dev))
return -ENODEV;
for (i = 0; i < 5; i++) {
@@ -328,7 +328,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
size_t count, loff_t *ppos)
{
struct reader_dev *dev = filp->private_data;
- int iobase = dev->link.io.BasePort1;
+ int iobase = dev->p_dev->io.BasePort1;
ssize_t rc;
int i;
unsigned int bytes_to_write;
@@ -351,7 +351,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
return -EAGAIN;
}
- if ((dev->link.state & DEV_PRESENT) == 0)
+ if (!pcmcia_dev_present(dev->p_dev))
return -ENODEV;
bytes_to_write = count;
@@ -445,14 +445,14 @@ static unsigned int cm4040_poll(struct file *filp, poll_table *wait)
static int cm4040_open(struct inode *inode, struct file *filp)
{
struct reader_dev *dev;
- dev_link_t *link;
+ struct pcmcia_device *link;
int minor = iminor(inode);
if (minor >= CM_MAX_DEV)
return -ENODEV;
link = dev_table[minor];
- if (link == NULL || !(DEV_OK(link)))
+ if (link == NULL || !pcmcia_dev_present(link))
return -ENODEV;
if (link->open)
@@ -478,7 +478,7 @@ static int cm4040_open(struct inode *inode, struct file *filp)
static int cm4040_close(struct inode *inode, struct file *filp)
{
struct reader_dev *dev = filp->private_data;
- dev_link_t *link;
+ struct pcmcia_device *link;
int minor = iminor(inode);
DEBUGP(2, dev, "-> cm4040_close(maj/min=%d.%d)\n", imajor(inode),
@@ -500,7 +500,7 @@ static int cm4040_close(struct inode *inode, struct file *filp)
return 0;
}
-static void cm4040_reader_release(dev_link_t *link)
+static void cm4040_reader_release(struct pcmcia_device *link)
{
struct reader_dev *dev = link->priv;
@@ -514,60 +514,49 @@ static void cm4040_reader_release(dev_link_t *link)
return;
}
-static void reader_config(dev_link_t *link, int devno)
+static int reader_config(struct pcmcia_device *link, int devno)
{
- client_handle_t handle;
struct reader_dev *dev;
tuple_t tuple;
cisparse_t parse;
- config_info_t conf;
u_char buf[64];
int fail_fn, fail_rc;
int rc;
- handle = link->handle;
-
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) {
+ if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) {
fail_fn = GetFirstTuple;
goto cs_failed;
}
- if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) {
+ if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) {
fail_fn = GetTupleData;
goto cs_failed;
}
- if ((fail_rc = pcmcia_parse_tuple(handle, &tuple, &parse))
+ if ((fail_rc = pcmcia_parse_tuple(link, &tuple, &parse))
!= CS_SUCCESS) {
fail_fn = ParseTuple;
goto cs_failed;
}
- if ((fail_rc = pcmcia_get_configuration_info(handle, &conf))
- != CS_SUCCESS) {
- fail_fn = GetConfigurationInfo;
- goto cs_failed;
- }
- link->state |= DEV_CONFIG;
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- link->conf.Vcc = conf.Vcc;
link->io.BasePort2 = 0;
link->io.NumPorts2 = 0;
link->io.Attributes2 = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (rc = pcmcia_get_first_tuple(handle, &tuple);
+ for (rc = pcmcia_get_first_tuple(link, &tuple);
rc == CS_SUCCESS;
- rc = pcmcia_get_next_tuple(handle, &tuple)) {
- rc = pcmcia_get_tuple_data(handle, &tuple);
+ rc = pcmcia_get_next_tuple(link, &tuple)) {
+ rc = pcmcia_get_tuple_data(link, &tuple);
if (rc != CS_SUCCESS)
continue;
- rc = pcmcia_parse_tuple(handle, &tuple, &parse);
+ rc = pcmcia_parse_tuple(link, &tuple, &parse);
if (rc != CS_SUCCESS)
continue;
@@ -585,13 +574,13 @@ static void reader_config(dev_link_t *link, int devno)
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.IOAddrLines = parse.cftable_entry.io.flags
& CISTPL_IO_LINES_MASK;
- rc = pcmcia_request_io(handle, &link->io);
+ rc = pcmcia_request_io(link, &link->io);
- dev_printk(KERN_INFO, &handle_to_dev(handle), "foo");
+ dev_printk(KERN_INFO, &handle_to_dev(link), "foo");
if (rc == CS_SUCCESS)
break;
else
- dev_printk(KERN_INFO, &handle_to_dev(handle),
+ dev_printk(KERN_INFO, &handle_to_dev(link),
"pcmcia_request_io failed 0x%x\n", rc);
}
if (rc != CS_SUCCESS)
@@ -599,10 +588,10 @@ static void reader_config(dev_link_t *link, int devno)
link->conf.IntType = 00000002;
- if ((fail_rc = pcmcia_request_configuration(handle,&link->conf))
+ if ((fail_rc = pcmcia_request_configuration(link,&link->conf))
!=CS_SUCCESS) {
fail_fn = RequestConfiguration;
- dev_printk(KERN_INFO, &handle_to_dev(handle),
+ dev_printk(KERN_INFO, &handle_to_dev(link),
"pcmcia_request_configuration failed 0x%x\n",
fail_rc);
goto cs_release;
@@ -612,57 +601,31 @@ static void reader_config(dev_link_t *link, int devno)
sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno);
dev->node.major = major;
dev->node.minor = devno;
- dev->node.next = NULL;
- link->dev = &dev->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ dev->node.next = &dev->node;
DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno,
link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1);
DEBUGP(2, dev, "<- reader_config (succ)\n");
- return;
+ return 0;
cs_failed:
- cs_error(handle, fail_fn, fail_rc);
+ cs_error(link, fail_fn, fail_rc);
cs_release:
reader_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
-}
-
-static int reader_suspend(struct pcmcia_device *p_dev)
-{
- dev_link_t *link = dev_to_instance(p_dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int reader_resume(struct pcmcia_device *p_dev)
-{
- dev_link_t *link = dev_to_instance(p_dev);
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
+ return -ENODEV;
}
-static void reader_release(dev_link_t *link)
+static void reader_release(struct pcmcia_device *link)
{
cm4040_reader_release(link->priv);
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
+ pcmcia_disable_device(link);
}
-static int reader_attach(struct pcmcia_device *p_dev)
+static int reader_probe(struct pcmcia_device *link)
{
struct reader_dev *dev;
- dev_link_t *link;
- int i;
+ int i, ret;
for (i = 0; i < CM_MAX_DEV; i++) {
if (dev_table[i] == NULL)
@@ -679,8 +642,8 @@ static int reader_attach(struct pcmcia_device *p_dev)
dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
dev->buffer_status = 0;
- link = &dev->link;
link->priv = dev;
+ dev->p_dev = link;
link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link;
@@ -692,11 +655,9 @@ static int reader_attach(struct pcmcia_device *p_dev)
init_timer(&dev->poll_timer);
dev->poll_timer.function = &cm4040_do_poll;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- reader_config(link, i);
+ ret = reader_config(link, i);
+ if (ret)
+ return ret;
class_device_create(cmx_class, NULL, MKDEV(major, i), NULL,
"cmx%d", i);
@@ -704,9 +665,8 @@ static int reader_attach(struct pcmcia_device *p_dev)
return 0;
}
-static void reader_detach(struct pcmcia_device *p_dev)
+static void reader_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct reader_dev *dev = link->priv;
int devno;
@@ -718,10 +678,7 @@ static void reader_detach(struct pcmcia_device *p_dev)
if (devno == CM_MAX_DEV)
return;
- link->state &= ~DEV_PRESENT;
-
- if (link->state & DEV_CONFIG)
- reader_release(link);
+ reader_release(link);
dev_table[devno] = NULL;
kfree(dev);
@@ -753,10 +710,8 @@ static struct pcmcia_driver reader_driver = {
.drv = {
.name = "cm4040_cs",
},
- .probe = reader_attach,
+ .probe = reader_probe,
.remove = reader_detach,
- .suspend = reader_suspend,
- .resume = reader_resume,
.id_table = cm4040_ids,
};
@@ -769,16 +724,19 @@ static int __init cm4040_init(void)
if (!cmx_class)
return -1;
- rc = pcmcia_register_driver(&reader_driver);
- if (rc < 0)
- return rc;
-
major = register_chrdev(0, DEVICE_NAME, &reader_fops);
if (major < 0) {
printk(KERN_WARNING MODULE_NAME
": could not get major number\n");
return -1;
}
+
+ rc = pcmcia_register_driver(&reader_driver);
+ if (rc < 0) {
+ unregister_chrdev(major, DEVICE_NAME);
+ return rc;
+ }
+
return 0;
}
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index e6b714b6390..07213454c45 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -228,7 +228,7 @@ typedef struct _mgslpc_info {
struct _input_signal_events input_signal_events;
/* PCMCIA support */
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
int stop;
@@ -484,7 +484,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);
/* PCMCIA prototypes */
-static void mgslpc_config(dev_link_t *link);
+static int mgslpc_config(struct pcmcia_device *link);
static void mgslpc_release(u_long arg);
static void mgslpc_detach(struct pcmcia_device *p_dev);
@@ -533,14 +533,14 @@ static void ldisc_receive_buf(struct tty_struct *tty,
}
}
-static int mgslpc_attach(struct pcmcia_device *p_dev)
+static int mgslpc_probe(struct pcmcia_device *link)
{
MGSLPC_INFO *info;
- dev_link_t *link;
-
+ int ret;
+
if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_attach\n");
-
+
info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
if (!info) {
printk("Error can't allocate device instance data\n");
@@ -565,25 +565,22 @@ static int mgslpc_attach(struct pcmcia_device *p_dev)
info->imrb_value = 0xffff;
info->pim_value = 0xff;
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
-
- /* Initialize the dev_link_t structure */
+
+ /* Initialize the struct pcmcia_device structure */
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = NULL;
-
+
link->conf.Attributes = 0;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- mgslpc_config(link);
+ ret = mgslpc_config(link);
+ if (ret)
+ return ret;
mgslpc_add_device(info);
@@ -596,15 +593,13 @@ static int mgslpc_attach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void mgslpc_config(dev_link_t *link)
+static int mgslpc_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
MGSLPC_INFO *info = link->priv;
tuple_t tuple;
cisparse_t parse;
int last_fn, last_ret;
u_char buf[64];
- config_info_t conf;
cistpl_cftable_entry_t dflt = { 0 };
cistpl_cftable_entry_t *cfg;
@@ -617,27 +612,20 @@ static void mgslpc_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
-
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
/* get CIS configuration entry */
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
cfg = &(parse.cftable_entry);
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
if (cfg->index == 0)
@@ -658,11 +646,10 @@ static void mgslpc_config(dev_link_t *link)
link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
link->io.BasePort1 = io->win[0].base;
link->io.NumPorts1 = io->win[0].len;
- CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+ CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
}
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 8;
link->conf.Present = PRESENT_OPTION;
@@ -670,9 +657,9 @@ static void mgslpc_config(dev_link_t *link)
link->irq.Attributes |= IRQ_HANDLE_PRESENT;
link->irq.Handler = mgslpc_isr;
link->irq.Instance = info;
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
info->io_base = link->io.BasePort1;
info->irq_level = link->irq.AssignedIRQ;
@@ -680,7 +667,7 @@ static void mgslpc_config(dev_link_t *link)
/* add to linked list of devices */
sprintf(info->node.dev_name, "mgslpc0");
info->node.major = info->node.minor = 0;
- link->dev = &info->node;
+ link->dev_node = &info->node;
printk(KERN_INFO "%s: index 0x%02x:",
info->node.dev_name, link->conf.ConfigIndex);
@@ -690,13 +677,12 @@ static void mgslpc_config(dev_link_t *link)
printk(", io 0x%04x-0x%04x", link->io.BasePort1,
link->io.BasePort1+link->io.NumPorts1-1);
printk("\n");
-
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
mgslpc_release((u_long)link);
+ return -ENODEV;
}
/* Card has been removed.
@@ -705,58 +691,38 @@ cs_failed:
*/
static void mgslpc_release(u_long arg)
{
- dev_link_t *link = (dev_link_t *)arg;
+ struct pcmcia_device *link = (struct pcmcia_device *)arg;
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_release(0x%p)\n", link);
-
- /* Unlink the device chain */
- link->dev = NULL;
- link->state &= ~DEV_CONFIG;
+ if (debug_level >= DEBUG_LEVEL_INFO)
+ printk("mgslpc_release(0x%p)\n", link);
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
+ pcmcia_disable_device(link);
}
-static void mgslpc_detach(struct pcmcia_device *p_dev)
+static void mgslpc_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_detach(0x%p)\n", link);
+ if (debug_level >= DEBUG_LEVEL_INFO)
+ printk("mgslpc_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG) {
- ((MGSLPC_INFO *)link->priv)->stop = 1;
- mgslpc_release((u_long)link);
- }
+ ((MGSLPC_INFO *)link->priv)->stop = 1;
+ mgslpc_release((u_long)link);
- mgslpc_remove_device((MGSLPC_INFO *)link->priv);
+ mgslpc_remove_device((MGSLPC_INFO *)link->priv);
}
-static int mgslpc_suspend(struct pcmcia_device *dev)
+static int mgslpc_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
MGSLPC_INFO *info = link->priv;
- link->state |= DEV_SUSPEND;
info->stop = 1;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
return 0;
}
-static int mgslpc_resume(struct pcmcia_device *dev)
+static int mgslpc_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
MGSLPC_INFO *info = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
info->stop = 0;
return 0;
@@ -1280,7 +1246,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs)
if (!info)
return IRQ_NONE;
- if (!(info->link.state & DEV_CONFIG))
+ if (!(info->p_dev->_locked))
return IRQ_HANDLED;
spin_lock(&info->lock);
@@ -3033,7 +2999,7 @@ static struct pcmcia_driver mgslpc_driver = {
.drv = {
.name = "synclink_cs",
},
- .probe = mgslpc_attach,
+ .probe = mgslpc_probe,
.remove = mgslpc_detach,
.id_table = mgslpc_ids,
.suspend = mgslpc_suspend,
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 86be04b241e..58f3512c52e 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1584,7 +1584,6 @@ u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dpo
return twothirdsMD4Transform(daddr, hash);
}
-EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
#endif
#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h
index 3ec73d1a279..179cdbea712 100644
--- a/drivers/char/rio/host.h
+++ b/drivers/char/rio/host.h
@@ -33,12 +33,6 @@
#ifndef __rio_host_h__
#define __rio_host_h__
-#ifdef SCCS_LABELS
-#ifndef lint
-static char *_host_h_sccs_ = "@(#)host.h 1.2";
-#endif
-#endif
-
/*
** the host structure - one per host card in the system.
*/
@@ -77,9 +71,6 @@ struct Host {
#define RC_STARTUP 1
#define RC_RUNNING 2
#define RC_STUFFED 3
-#define RC_SOMETHING 4
-#define RC_SOMETHING_NEW 5
-#define RC_SOMETHING_ELSE 6
#define RC_READY 7
#define RUN_STATE 7
/*
diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
index acda9326c2e..290143addd3 100644
--- a/drivers/char/rio/rioboot.c
+++ b/drivers/char/rio/rioboot.c
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/termios.h>
#include <linux/serial.h>
+#include <linux/vmalloc.h>
#include <asm/semaphore.h>
#include <linux/generic_serial.h>
#include <linux/errno.h>
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
index d31aba62bb7..75b2557c37e 100644
--- a/drivers/char/rio/rioctrl.c
+++ b/drivers/char/rio/rioctrl.c
@@ -1394,14 +1394,17 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
return RIO_FAIL;
}
- if (((int) ((char) PortP->InUse) == -1) || !(CmdBlkP = RIOGetCmdBlk())) {
- rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block for command %d on port %d\n", Cmd, PortP->PortNum);
+ if ((PortP->InUse == (typeof(PortP->InUse))-1) ||
+ !(CmdBlkP = RIOGetCmdBlk())) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block "
+ "for command %d on port %d\n", Cmd, PortP->PortNum);
return RIO_FAIL;
}
- rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n", CmdBlkP, PortP->InUse);
+ rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n",
+ CmdBlkP, PortP->InUse);
- PktCmdP = (struct PktCmd_M *) &CmdBlkP->Packet.data[0];
+ PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0];
CmdBlkP->Packet.src_unit = 0;
if (PortP->SecondBlock)
@@ -1425,38 +1428,46 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
switch (Cmd) {
case MEMDUMP:
- rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p (addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr);
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p "
+ "(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr);
PktCmdP->SubCommand = MEMDUMP;
PktCmdP->SubAddr = SubCmd.Addr;
break;
case FCLOSE:
- rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n", CmdBlkP);
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n",
+ CmdBlkP);
break;
case READ_REGISTER:
- rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk %p\n", (int) SubCmd.Addr, CmdBlkP);
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) "
+ "command blk %p\n", (int) SubCmd.Addr, CmdBlkP);
PktCmdP->SubCommand = READ_REGISTER;
PktCmdP->SubAddr = SubCmd.Addr;
break;
case RESUME:
- rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n", CmdBlkP);
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n",
+ CmdBlkP);
break;
case RFLUSH:
- rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n", CmdBlkP);
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n",
+ CmdBlkP);
CmdBlkP->PostFuncP = RIORFlushEnable;
break;
case SUSPEND:
- rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n", CmdBlkP);
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n",
+ CmdBlkP);
break;
case MGET:
- rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n", CmdBlkP);
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n",
+ CmdBlkP);
break;
case MSET:
case MBIC:
case MBIS:
CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
- rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk %p\n", CmdBlkP);
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command "
+ "blk %p\n", CmdBlkP);
break;
case WFLUSH:
@@ -1465,12 +1476,14 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
** allowed then we should not bother sending any more to the
** RTA.
*/
- if ((int) ((char) PortP->WflushFlag) == (int) -1) {
- rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, WflushFlag about to wrap!");
+ if (PortP->WflushFlag == (typeof(PortP->WflushFlag))-1) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, "
+ "WflushFlag about to wrap!");
RIOFreeCmdBlk(CmdBlkP);
return (RIO_FAIL);
} else {
- rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command blk %p\n", CmdBlkP);
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command "
+ "blk %p\n", CmdBlkP);
CmdBlkP->PostFuncP = RIOWFlushMark;
}
break;
diff --git a/drivers/char/rio/rioioctl.h b/drivers/char/rio/rioioctl.h
index 14b83fae75c..e8af5b30519 100644
--- a/drivers/char/rio/rioioctl.h
+++ b/drivers/char/rio/rioioctl.h
@@ -33,10 +33,6 @@
#ifndef __rioioctl_h__
#define __rioioctl_h__
-#ifdef SCCS_LABELS
-static char *_rioioctl_h_sccs_ = "@(#)rioioctl.h 1.2";
-#endif
-
/*
** RIO device driver - user ioctls and associated structures.
*/
@@ -44,55 +40,13 @@ static char *_rioioctl_h_sccs_ = "@(#)rioioctl.h 1.2";
struct portStats {
int port;
int gather;
- ulong txchars;
- ulong rxchars;
- ulong opens;
- ulong closes;
- ulong ioctls;
+ unsigned long txchars;
+ unsigned long rxchars;
+ unsigned long opens;
+ unsigned long closes;
+ unsigned long ioctls;
};
-
-#define rIOC ('r'<<8)
-#define TCRIOSTATE (rIOC | 1)
-#define TCRIOXPON (rIOC | 2)
-#define TCRIOXPOFF (rIOC | 3)
-#define TCRIOXPCPS (rIOC | 4)
-#define TCRIOXPRINT (rIOC | 5)
-#define TCRIOIXANYON (rIOC | 6)
-#define TCRIOIXANYOFF (rIOC | 7)
-#define TCRIOIXONON (rIOC | 8)
-#define TCRIOIXONOFF (rIOC | 9)
-#define TCRIOMBIS (rIOC | 10)
-#define TCRIOMBIC (rIOC | 11)
-#define TCRIOTRIAD (rIOC | 12)
-#define TCRIOTSTATE (rIOC | 13)
-
-/*
-** 15.10.1998 ARG - ESIL 0761 part fix
-** Add RIO ioctls for manipulating RTS and CTS flow control, (as LynxOS
-** appears to not support hardware flow control).
-*/
-#define TCRIOCTSFLOWEN (rIOC | 14) /* enable CTS flow control */
-#define TCRIOCTSFLOWDIS (rIOC | 15) /* disable CTS flow control */
-#define TCRIORTSFLOWEN (rIOC | 16) /* enable RTS flow control */
-#define TCRIORTSFLOWDIS (rIOC | 17) /* disable RTS flow control */
-
-/*
-** 09.12.1998 ARG - ESIL 0776 part fix
-** Definition for 'RIOC' also appears in daemon.h, so we'd better do a
-** #ifndef here first.
-** 'RIO_QUICK_CHECK' also #define'd here as this ioctl is now
-** allowed to be used by customers.
-**
-** 05.02.1999 ARG -
-** This is what I've decied to do with ioctls etc., which are intended to be
-** invoked from users applications :
-** Anything that needs to be defined here will be removed from daemon.h, that
-** way it won't end up having to be defined/maintained in two places. The only
-** consequence of this is that this file should now be #include'd by daemon.h
-**
-** 'stats' ioctls now #define'd here as they are to be used by customers.
-*/
#define RIOC ('R'<<8)|('i'<<16)|('o'<<24)
#define RIO_QUICK_CHECK (RIOC | 105)
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index b543821d8cb..56c8243cdb7 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -390,7 +390,8 @@ scdrv_init(void)
format_module_id(devnamep, geo_module(geoid),
MODULE_FORMAT_BRIEF);
devnamep = devname + strlen(devname);
- sprintf(devnamep, "#%d", geo_slab(geoid));
+ sprintf(devnamep, "^%d#%d", geo_slot(geoid),
+ geo_slab(geoid));
/* allocate sysctl device data */
scd = kzalloc(sizeof (struct sysctl_data_s),
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index f8dd8527c6a..a90f5d97df3 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1341,6 +1341,9 @@ static int __devinit sonypi_probe(struct platform_device *dev)
else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
+ else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
+ sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
else
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 3f5d6077f39..a9c5a7230f8 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -504,7 +504,6 @@ static int stl_echmcaintr(stlbrd_t *brdp);
static int stl_echpciintr(stlbrd_t *brdp);
static int stl_echpci64intr(stlbrd_t *brdp);
static void stl_offintr(void *private);
-static void *stl_memalloc(int len);
static stlbrd_t *stl_allocbrd(void);
static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);
@@ -940,17 +939,6 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
/*****************************************************************************/
/*
- * Local driver kernel memory allocation routine.
- */
-
-static void *stl_memalloc(int len)
-{
- return (void *) kmalloc(len, GFP_KERNEL);
-}
-
-/*****************************************************************************/
-
-/*
* Allocate a new board structure. Fill out the basic info in it.
*/
@@ -958,14 +946,13 @@ static stlbrd_t *stl_allocbrd(void)
{
stlbrd_t *brdp;
- brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t));
- if (brdp == (stlbrd_t *) NULL) {
+ brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL);
+ if (!brdp) {
printk("STALLION: failed to allocate memory (size=%d)\n",
sizeof(stlbrd_t));
- return (stlbrd_t *) NULL;
+ return NULL;
}
- memset(brdp, 0, sizeof(stlbrd_t));
brdp->magic = STL_BOARDMAGIC;
return brdp;
}
@@ -1017,9 +1004,9 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
portp->refcount++;
if ((portp->flags & ASYNC_INITIALIZED) == 0) {
- if (portp->tx.buf == (char *) NULL) {
- portp->tx.buf = (char *) stl_memalloc(STL_TXBUFSIZE);
- if (portp->tx.buf == (char *) NULL)
+ if (!portp->tx.buf) {
+ portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
+ if (!portp->tx.buf)
return -ENOMEM;
portp->tx.head = portp->tx.buf;
portp->tx.tail = portp->tx.buf;
@@ -2178,13 +2165,12 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
* each ports data structures.
*/
for (i = 0; (i < panelp->nrports); i++) {
- portp = (stlport_t *) stl_memalloc(sizeof(stlport_t));
- if (portp == (stlport_t *) NULL) {
+ portp = kzalloc(sizeof(stlport_t), GFP_KERNEL);
+ if (!portp) {
printk("STALLION: failed to allocate memory "
"(size=%d)\n", sizeof(stlport_t));
break;
}
- memset(portp, 0, sizeof(stlport_t));
portp->magic = STL_PORTMAGIC;
portp->portnr = i;
@@ -2315,13 +2301,12 @@ static inline int stl_initeio(stlbrd_t *brdp)
* can complete the setup.
*/
- panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t));
- if (panelp == (stlpanel_t *) NULL) {
+ panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
+ if (!panelp) {
printk(KERN_WARNING "STALLION: failed to allocate memory "
"(size=%d)\n", sizeof(stlpanel_t));
- return(-ENOMEM);
+ return -ENOMEM;
}
- memset(panelp, 0, sizeof(stlpanel_t));
panelp->magic = STL_PANELMAGIC;
panelp->brdnr = brdp->brdnr;
@@ -2490,13 +2475,12 @@ static inline int stl_initech(stlbrd_t *brdp)
status = inb(ioaddr + ECH_PNLSTATUS);
if ((status & ECH_PNLIDMASK) != nxtid)
break;
- panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t));
- if (panelp == (stlpanel_t *) NULL) {
+ panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
+ if (!panelp) {
printk("STALLION: failed to allocate memory "
"(size=%d)\n", sizeof(stlpanel_t));
break;
}
- memset(panelp, 0, sizeof(stlpanel_t));
panelp->magic = STL_PANELMAGIC;
panelp->brdnr = brdp->brdnr;
panelp->panelnr = panelnr;
@@ -3074,8 +3058,8 @@ static int __init stl_init(void)
/*
* Allocate a temporary write buffer.
*/
- stl_tmpwritebuf = (char *) stl_memalloc(STL_TXBUFSIZE);
- if (stl_tmpwritebuf == (char *) NULL)
+ stl_tmpwritebuf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
+ if (!stl_tmpwritebuf)
printk("STALLION: failed to allocate memory (size=%d)\n",
STL_TXBUFSIZE);
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index d68be61f0a4..fee2aca3f6a 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -941,17 +941,6 @@ static void* mgsl_get_text_ptr(void)
return mgsl_get_text_ptr;
}
-/*
- * tmp_buf is used as a temporary buffer by mgsl_write. We need to
- * lock it in case the COPY_FROM_USER blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ioports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char *tmp_buf;
-
static inline int mgsl_paranoia_check(struct mgsl_struct *info,
char *name, const char *routine)
{
@@ -2150,7 +2139,7 @@ static int mgsl_write(struct tty_struct * tty,
if (mgsl_paranoia_check(info, tty->name, "mgsl_write"))
goto cleanup;
- if (!tty || !info->xmit_buf || !tmp_buf)
+ if (!tty || !info->xmit_buf)
goto cleanup;
if ( info->params.mode == MGSL_MODE_HDLC ||
@@ -3438,7 +3427,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
{
struct mgsl_struct *info;
int retval, line;
- unsigned long page;
unsigned long flags;
/* verify range of specified line number */
@@ -3472,18 +3460,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
goto cleanup;
}
- if (!tmp_buf) {
- page = get_zeroed_page(GFP_KERNEL);
- if (!page) {
- retval = -ENOMEM;
- goto cleanup;
- }
- if (tmp_buf)
- free_page(page);
- else
- tmp_buf = (unsigned char *) page;
- }
-
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags);
@@ -4502,11 +4478,6 @@ static void synclink_cleanup(void)
kfree(tmp);
}
- if (tmp_buf) {
- free_page((unsigned long) tmp_buf);
- tmp_buf = NULL;
- }
-
if (pci_registered)
pci_unregister_driver(&synclink_pci_driver);
}
@@ -6025,7 +5996,7 @@ static void usc_set_async_mode( struct mgsl_struct *info )
* <15..8> ? RxFIFO IRQ Request Level
*
* Note: For async mode the receive FIFO level must be set
- * to 0 to aviod the situation where the FIFO contains fewer bytes
+ * to 0 to avoid the situation where the FIFO contains fewer bytes
* than the trigger level and no more data is expected.
*
* <7> 0 Exited Hunt IA (Interrupt Arm)
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 738ec2f4e56..b4d1f4eea43 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1,5 +1,5 @@
/*
- * $Id: synclink_gt.c,v 4.22 2006/01/09 20:16:06 paulkf Exp $
+ * $Id: synclink_gt.c,v 4.25 2006/02/06 21:20:33 paulkf Exp $
*
* Device driver for Microgate SyncLink GT serial adapters.
*
@@ -92,7 +92,7 @@
* module identification
*/
static char *driver_name = "SyncLink GT";
-static char *driver_version = "$Revision: 4.22 $";
+static char *driver_version = "$Revision: 4.25 $";
static char *tty_driver_name = "synclink_gt";
static char *tty_dev_prefix = "ttySLG";
MODULE_LICENSE("GPL");
@@ -188,6 +188,20 @@ static void hdlcdev_exit(struct slgt_info *info);
#define SLGT_REG_SIZE 256
/*
+ * conditional wait facility
+ */
+struct cond_wait {
+ struct cond_wait *next;
+ wait_queue_head_t q;
+ wait_queue_t wait;
+ unsigned int data;
+};
+static void init_cond_wait(struct cond_wait *w, unsigned int data);
+static void add_cond_wait(struct cond_wait **head, struct cond_wait *w);
+static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w);
+static void flush_cond_wait(struct cond_wait **head);
+
+/*
* DMA buffer descriptor and access macros
*/
struct slgt_desc
@@ -269,6 +283,9 @@ struct slgt_info {
struct timer_list tx_timer;
struct timer_list rx_timer;
+ unsigned int gpio_present;
+ struct cond_wait *gpio_wait_q;
+
spinlock_t lock; /* spinlock for synchronizing with ISR */
struct work_struct task;
@@ -379,6 +396,11 @@ static MGSL_PARAMS default_params = {
#define MASK_OVERRUN BIT4
#define GSR 0x00 /* global status */
+#define JCR 0x04 /* JTAG control */
+#define IODR 0x08 /* GPIO direction */
+#define IOER 0x0c /* GPIO interrupt enable */
+#define IOVR 0x10 /* GPIO value */
+#define IOSR 0x14 /* GPIO interrupt status */
#define TDR 0x80 /* tx data */
#define RDR 0x80 /* rx data */
#define TCR 0x82 /* tx control */
@@ -503,6 +525,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
static void set_break(struct tty_struct *tty, int break_state);
static int get_interface(struct slgt_info *info, int __user *if_mode);
static int set_interface(struct slgt_info *info, int if_mode);
+static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
+static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
+static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
/*
* driver functions
@@ -1112,6 +1137,12 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return get_interface(info, argp);
case MGSL_IOCSIF:
return set_interface(info,(int)arg);
+ case MGSL_IOCSGPIO:
+ return set_gpio(info, argp);
+ case MGSL_IOCGGPIO:
+ return get_gpio(info, argp);
+ case MGSL_IOCWAITGPIO:
+ return wait_gpio(info, argp);
case TIOCGICOUNT:
spin_lock_irqsave(&info->lock,flags);
cnow = info->icount;
@@ -1762,10 +1793,6 @@ static void rx_async(struct slgt_info *info)
DBGDATA(info, p, count, "rx");
for(i=0 ; i < count; i+=2, p+=2) {
- if (tty && chars) {
- tty_flip_buffer_push(tty);
- chars = 0;
- }
ch = *p;
icount->rx++;
@@ -2158,6 +2185,24 @@ static void isr_txeom(struct slgt_info *info, unsigned short status)
}
}
+static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int state)
+{
+ struct cond_wait *w, *prev;
+
+ /* wake processes waiting for specific transitions */
+ for (w = info->gpio_wait_q, prev = NULL ; w != NULL ; w = w->next) {
+ if (w->data & changed) {
+ w->data = state;
+ wake_up_interruptible(&w->q);
+ if (prev != NULL)
+ prev->next = w->next;
+ else
+ info->gpio_wait_q = w->next;
+ } else
+ prev = w;
+ }
+}
+
/* interrupt service routine
*
* irq interrupt number
@@ -2193,6 +2238,22 @@ static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs)
}
}
+ if (info->gpio_present) {
+ unsigned int state;
+ unsigned int changed;
+ while ((changed = rd_reg32(info, IOSR)) != 0) {
+ DBGISR(("%s iosr=%08x\n", info->device_name, changed));
+ /* read latched state of GPIO signals */
+ state = rd_reg32(info, IOVR);
+ /* clear pending GPIO interrupt bits */
+ wr_reg32(info, IOSR, changed);
+ for (i=0 ; i < info->port_count ; i++) {
+ if (info->port_array[i] != NULL)
+ isr_gpio(info->port_array[i], changed, state);
+ }
+ }
+ }
+
for(i=0; i < info->port_count ; i++) {
struct slgt_info *port = info->port_array[i];
@@ -2276,6 +2337,8 @@ static void shutdown(struct slgt_info *info)
set_signals(info);
}
+ flush_cond_wait(&info->gpio_wait_q);
+
spin_unlock_irqrestore(&info->lock,flags);
if (info->tty)
@@ -2650,6 +2713,175 @@ static int set_interface(struct slgt_info *info, int if_mode)
return 0;
}
+/*
+ * set general purpose IO pin state and direction
+ *
+ * user_gpio fields:
+ * state each bit indicates a pin state
+ * smask set bit indicates pin state to set
+ * dir each bit indicates a pin direction (0=input, 1=output)
+ * dmask set bit indicates pin direction to set
+ */
+static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
+{
+ unsigned long flags;
+ struct gpio_desc gpio;
+ __u32 data;
+
+ if (!info->gpio_present)
+ return -EINVAL;
+ if (copy_from_user(&gpio, user_gpio, sizeof(gpio)))
+ return -EFAULT;
+ DBGINFO(("%s set_gpio state=%08x smask=%08x dir=%08x dmask=%08x\n",
+ info->device_name, gpio.state, gpio.smask,
+ gpio.dir, gpio.dmask));
+
+ spin_lock_irqsave(&info->lock,flags);
+ if (gpio.dmask) {
+ data = rd_reg32(info, IODR);
+ data |= gpio.dmask & gpio.dir;
+ data &= ~(gpio.dmask & ~gpio.dir);
+ wr_reg32(info, IODR, data);
+ }
+ if (gpio.smask) {
+ data = rd_reg32(info, IOVR);
+ data |= gpio.smask & gpio.state;
+ data &= ~(gpio.smask & ~gpio.state);
+ wr_reg32(info, IOVR, data);
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ return 0;
+}
+
+/*
+ * get general purpose IO pin state and direction
+ */
+static int get_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
+{
+ struct gpio_desc gpio;
+ if (!info->gpio_present)
+ return -EINVAL;
+ gpio.state = rd_reg32(info, IOVR);
+ gpio.smask = 0xffffffff;
+ gpio.dir = rd_reg32(info, IODR);
+ gpio.dmask = 0xffffffff;
+ if (copy_to_user(user_gpio, &gpio, sizeof(gpio)))
+ return -EFAULT;
+ DBGINFO(("%s get_gpio state=%08x dir=%08x\n",
+ info->device_name, gpio.state, gpio.dir));
+ return 0;
+}
+
+/*
+ * conditional wait facility
+ */
+static void init_cond_wait(struct cond_wait *w, unsigned int data)
+{
+ init_waitqueue_head(&w->q);
+ init_waitqueue_entry(&w->wait, current);
+ w->data = data;
+}
+
+static void add_cond_wait(struct cond_wait **head, struct cond_wait *w)
+{
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&w->q, &w->wait);
+ w->next = *head;
+ *head = w;
+}
+
+static void remove_cond_wait(struct cond_wait **head, struct cond_wait *cw)
+{
+ struct cond_wait *w, *prev;
+ remove_wait_queue(&cw->q, &cw->wait);
+ set_current_state(TASK_RUNNING);
+ for (w = *head, prev = NULL ; w != NULL ; prev = w, w = w->next) {
+ if (w == cw) {
+ if (prev != NULL)
+ prev->next = w->next;
+ else
+ *head = w->next;
+ break;
+ }
+ }
+}
+
+static void flush_cond_wait(struct cond_wait **head)
+{
+ while (*head != NULL) {
+ wake_up_interruptible(&(*head)->q);
+ *head = (*head)->next;
+ }
+}
+
+/*
+ * wait for general purpose I/O pin(s) to enter specified state
+ *
+ * user_gpio fields:
+ * state - bit indicates target pin state
+ * smask - set bit indicates watched pin
+ *
+ * The wait ends when at least one watched pin enters the specified
+ * state. When 0 (no error) is returned, user_gpio->state is set to the
+ * state of all GPIO pins when the wait ends.
+ *
+ * Note: Each pin may be a dedicated input, dedicated output, or
+ * configurable input/output. The number and configuration of pins
+ * varies with the specific adapter model. Only input pins (dedicated
+ * or configured) can be monitored with this function.
+ */
+static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
+{
+ unsigned long flags;
+ int rc = 0;
+ struct gpio_desc gpio;
+ struct cond_wait wait;
+ u32 state;
+
+ if (!info->gpio_present)
+ return -EINVAL;
+ if (copy_from_user(&gpio, user_gpio, sizeof(gpio)))
+ return -EFAULT;
+ DBGINFO(("%s wait_gpio() state=%08x smask=%08x\n",
+ info->device_name, gpio.state, gpio.smask));
+ /* ignore output pins identified by set IODR bit */
+ if ((gpio.smask &= ~rd_reg32(info, IODR)) == 0)
+ return -EINVAL;
+ init_cond_wait(&wait, gpio.smask);
+
+ spin_lock_irqsave(&info->lock, flags);
+ /* enable interrupts for watched pins */
+ wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask);
+ /* get current pin states */
+ state = rd_reg32(info, IOVR);
+
+ if (gpio.smask & ~(state ^ gpio.state)) {
+ /* already in target state */
+ gpio.state = state;
+ } else {
+ /* wait for target state */
+ add_cond_wait(&info->gpio_wait_q, &wait);
+ spin_unlock_irqrestore(&info->lock, flags);
+ schedule();
+ if (signal_pending(current))
+ rc = -ERESTARTSYS;
+ else
+ gpio.state = wait.data;
+ spin_lock_irqsave(&info->lock, flags);
+ remove_cond_wait(&info->gpio_wait_q, &wait);
+ }
+
+ /* disable all GPIO interrupts if no waiting processes */
+ if (info->gpio_wait_q == NULL)
+ wr_reg32(info, IOER, 0);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio)))
+ rc = -EFAULT;
+ return rc;
+}
+
static int modem_input_wait(struct slgt_info *info,int arg)
{
unsigned long flags;
@@ -3166,8 +3398,10 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
} else {
port_array[0]->irq_requested = 1;
adapter_test(port_array[0]);
- for (i=1 ; i < port_count ; i++)
+ for (i=1 ; i < port_count ; i++) {
port_array[i]->init_error = port_array[0]->init_error;
+ port_array[i]->gpio_present = port_array[0]->gpio_present;
+ }
}
}
}
@@ -4301,7 +4535,7 @@ static int register_test(struct slgt_info *info)
break;
}
}
-
+ info->gpio_present = (rd_reg32(info, JCR) & BIT5) ? 1 : 0;
info->init_error = rc ? 0 : DiagStatus_AddressFailure;
return rc;
}
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index eb2eb3e12d6..079db5a935a 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -515,7 +515,7 @@ tipar_init_module(void)
err = PTR_ERR(tipar_class);
goto out_chrdev;
}
- if (parport_register_driver(&tipar_driver) || tp_count == 0) {
+ if (parport_register_driver(&tipar_driver)) {
printk(KERN_ERR "tipar: unable to register with parport\n");
err = -EIO;
goto out_class;
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 2546637a55c..f58ad7f6826 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -327,7 +327,7 @@ static ssize_t store_received_ref_clk3a(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(received_ref_clk3a, S_IWUGO, NULL,
+static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL,
store_received_ref_clk3a);
@@ -349,7 +349,7 @@ static ssize_t store_received_ref_clk3b(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(received_ref_clk3b, S_IWUGO, NULL,
+static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL,
store_received_ref_clk3b);
@@ -371,7 +371,7 @@ static ssize_t store_enable_clk3b_output(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(enable_clk3b_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL,
store_enable_clk3b_output);
static ssize_t store_enable_clk3a_output(struct device *d,
@@ -392,7 +392,7 @@ static ssize_t store_enable_clk3a_output(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(enable_clk3a_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL,
store_enable_clk3a_output);
static ssize_t store_enable_clkb1_output(struct device *d,
@@ -413,7 +413,7 @@ static ssize_t store_enable_clkb1_output(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(enable_clkb1_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL,
store_enable_clkb1_output);
@@ -435,7 +435,7 @@ static ssize_t store_enable_clka1_output(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(enable_clka1_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL,
store_enable_clka1_output);
static ssize_t store_enable_clkb0_output(struct device *d,
@@ -456,7 +456,7 @@ static ssize_t store_enable_clkb0_output(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(enable_clkb0_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL,
store_enable_clkb0_output);
static ssize_t store_enable_clka0_output(struct device *d,
@@ -477,7 +477,7 @@ static ssize_t store_enable_clka0_output(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL,
store_enable_clka0_output);
static ssize_t store_select_amcb2_transmit_clock(struct device *d,
@@ -519,7 +519,7 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(select_amcb2_transmit_clock, S_IWUGO, NULL,
+static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
store_select_amcb2_transmit_clock);
static ssize_t store_select_amcb1_transmit_clock(struct device *d,
@@ -560,7 +560,7 @@ static ssize_t store_select_amcb1_transmit_clock(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(select_amcb1_transmit_clock, S_IWUGO, NULL,
+static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
store_select_amcb1_transmit_clock);
static ssize_t store_select_redundant_clock(struct device *d,
@@ -581,7 +581,7 @@ static ssize_t store_select_redundant_clock(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(select_redundant_clock, S_IWUGO, NULL,
+static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL,
store_select_redundant_clock);
static ssize_t store_select_ref_frequency(struct device *d,
@@ -602,7 +602,7 @@ static ssize_t store_select_ref_frequency(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(select_ref_frequency, S_IWUGO, NULL,
+static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL,
store_select_ref_frequency);
static ssize_t store_filter_select(struct device *d,
@@ -623,7 +623,7 @@ static ssize_t store_filter_select(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(filter_select, S_IWUGO, NULL, store_filter_select);
+static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select);
static ssize_t store_hardware_switching_mode(struct device *d,
struct device_attribute *attr, const char *buf, size_t count)
@@ -643,7 +643,7 @@ static ssize_t store_hardware_switching_mode(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(hardware_switching_mode, S_IWUGO, NULL,
+static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL,
store_hardware_switching_mode);
static ssize_t store_hardware_switching(struct device *d,
@@ -664,7 +664,7 @@ static ssize_t store_hardware_switching(struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(hardware_switching, S_IWUGO, NULL,
+static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL,
store_hardware_switching);
static ssize_t store_refalign (struct device *d,
@@ -684,7 +684,7 @@ static ssize_t store_refalign (struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(refalign, S_IWUGO, NULL, store_refalign);
+static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign);
static ssize_t store_mode_select (struct device *d,
struct device_attribute *attr, const char *buf, size_t count)
@@ -704,7 +704,7 @@ static ssize_t store_mode_select (struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(mode_select, S_IWUGO, NULL, store_mode_select);
+static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select);
static ssize_t store_reset (struct device *d,
struct device_attribute *attr, const char *buf, size_t count)
@@ -724,7 +724,7 @@ static ssize_t store_reset (struct device *d,
return strnlen(buf, count);
}
-static DEVICE_ATTR(reset, S_IWUGO, NULL, store_reset);
+static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset);
static struct attribute *tlclk_sysfs_entries[] = {
&dev_attr_current_ref.attr,
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index a6873bf89ff..fe00c7dfb64 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -20,9 +20,18 @@ config TCG_TPM
Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
and CONFIG_PNPACPI.
+config TCG_TIS
+ tristate "TPM Interface Specification 1.2 Interface"
+ depends on TCG_TPM && 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
+ from within Linux. To compile this driver as a module, choose
+ M here; the module will be called tpm_tis.
+
config TCG_NSC
tristate "National Semiconductor TPM Interface"
- depends on TCG_TPM
+ depends on TCG_TPM && PNPACPI
---help---
If you have a TPM security chip from National Semicondutor
say Yes and it will be accessible from within Linux. To
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index ba4582d160f..ea3a1e02a82 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_TCG_TPM) += tpm.o
ifdef CONFIG_ACPI
obj-$(CONFIG_TCG_TPM) += tpm_bios.o
endif
+obj-$(CONFIG_TCG_TIS) += tpm_tis.o
obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 5a3870477ef..6889e7db3af 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -32,12 +32,291 @@ enum tpm_const {
TPM_MINOR = 224, /* officially assigned */
TPM_BUFSIZE = 2048,
TPM_NUM_DEVICES = 256,
- TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
};
+enum tpm_duration {
+ TPM_SHORT = 0,
+ TPM_MEDIUM = 1,
+ TPM_LONG = 2,
+ TPM_UNDEFINED,
+};
+
+#define TPM_MAX_ORDINAL 243
+#define TPM_MAX_PROTECTED_ORDINAL 12
+#define TPM_PROTECTED_ORDINAL_MASK 0xFF
+
static LIST_HEAD(tpm_chip_list);
static DEFINE_SPINLOCK(driver_lock);
-static int dev_mask[TPM_NUM_MASK_ENTRIES];
+static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
+
+/*
+ * Array with one entry per ordinal defining the maximum amount
+ * of time the chip could take to return the result. The ordinal
+ * designation of short, medium or long is defined in a table in
+ * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
+ * values of the SHORT, MEDIUM, and LONG durations are retrieved
+ * from the chip during initialization with a call to tpm_get_timeouts.
+ */
+static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
+ TPM_UNDEFINED, /* 0 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 5 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 10 */
+ TPM_SHORT,
+};
+
+static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
+ TPM_UNDEFINED, /* 0 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 5 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 10 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_LONG,
+ TPM_MEDIUM, /* 15 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_SHORT, /* 20 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT, /* 25 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 30 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 35 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 40 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 45 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_LONG,
+ TPM_MEDIUM, /* 50 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 55 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 60 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 65 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 70 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 75 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 80 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 85 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 90 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 95 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 100 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 105 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 110 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 115 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 120 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 125 */
+ TPM_SHORT,
+ TPM_LONG,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 130 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_UNDEFINED, /* 135 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 140 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 145 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 150 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 155 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 160 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 165 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 170 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 175 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 180 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM, /* 185 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 190 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 195 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 200 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 205 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 210 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_UNDEFINED, /* 215 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 220 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 225 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 230 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 235 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 240 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+};
static void user_reader_timeout(unsigned long ptr)
{
@@ -46,7 +325,7 @@ static void user_reader_timeout(unsigned long ptr)
schedule_work(&chip->work);
}
-static void timeout_work(void * ptr)
+static void timeout_work(void *ptr)
{
struct tpm_chip *chip = ptr;
@@ -57,17 +336,43 @@ static void timeout_work(void * ptr)
}
/*
+ * Returns max number of jiffies to wait
+ */
+unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
+ u32 ordinal)
+{
+ int duration_idx = TPM_UNDEFINED;
+ int duration = 0;
+
+ if (ordinal < TPM_MAX_ORDINAL)
+ duration_idx = tpm_ordinal_duration[ordinal];
+ else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
+ TPM_MAX_PROTECTED_ORDINAL)
+ duration_idx =
+ tpm_protected_ordinal_duration[ordinal &
+ TPM_PROTECTED_ORDINAL_MASK];
+
+ if (duration_idx != TPM_UNDEFINED)
+ duration = chip->vendor.duration[duration_idx];
+ if (duration <= 0)
+ return 2 * 60 * HZ;
+ else
+ return duration;
+}
+EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
+
+/*
* Internal kernel interface to transmit TPM commands
*/
static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
size_t bufsiz)
{
ssize_t rc;
- u32 count;
+ u32 count, ordinal;
unsigned long stop;
count = be32_to_cpu(*((__be32 *) (buf + 2)));
-
+ ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
if (count == 0)
return -ENODATA;
if (count > bufsiz) {
@@ -78,21 +383,23 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
down(&chip->tpm_mutex);
- if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+ if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) {
dev_err(chip->dev,
"tpm_transmit: tpm_send: error %zd\n", rc);
goto out;
}
- stop = jiffies + 2 * 60 * HZ;
+ if (chip->vendor.irq)
+ goto out_recv;
+
+ stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
do {
- u8 status = chip->vendor->status(chip);
- if ((status & chip->vendor->req_complete_mask) ==
- chip->vendor->req_complete_val) {
+ u8 status = chip->vendor.status(chip);
+ if ((status & chip->vendor.req_complete_mask) ==
+ chip->vendor.req_complete_val)
goto out_recv;
- }
- if ((status == chip->vendor->req_canceled)) {
+ if ((status == chip->vendor.req_canceled)) {
dev_err(chip->dev, "Operation Canceled\n");
rc = -ECANCELED;
goto out;
@@ -102,14 +409,13 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
rmb();
} while (time_before(jiffies, stop));
-
- chip->vendor->cancel(chip);
+ chip->vendor.cancel(chip);
dev_err(chip->dev, "Operation Timed out\n");
rc = -ETIME;
goto out;
out_recv:
- rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+ rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz);
if (rc < 0)
dev_err(chip->dev,
"tpm_transmit: tpm_recv: error %zd\n", rc);
@@ -119,17 +425,247 @@ out:
}
#define TPM_DIGEST_SIZE 20
-#define CAP_PCR_RESULT_SIZE 18
-static const u8 cap_pcr[] = {
+#define TPM_ERROR_SIZE 10
+#define TPM_RET_CODE_IDX 6
+#define TPM_GET_CAP_RET_SIZE_IDX 10
+#define TPM_GET_CAP_RET_UINT32_1_IDX 14
+#define TPM_GET_CAP_RET_UINT32_2_IDX 18
+#define TPM_GET_CAP_RET_UINT32_3_IDX 22
+#define TPM_GET_CAP_RET_UINT32_4_IDX 26
+#define TPM_GET_CAP_PERM_DISABLE_IDX 16
+#define TPM_GET_CAP_PERM_INACTIVE_IDX 18
+#define TPM_GET_CAP_RET_BOOL_1_IDX 14
+#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16
+
+#define TPM_CAP_IDX 13
+#define TPM_CAP_SUBCAP_IDX 21
+
+enum tpm_capabilities {
+ TPM_CAP_FLAG = 4,
+ TPM_CAP_PROP = 5,
+};
+
+enum tpm_sub_capabilities {
+ TPM_CAP_PROP_PCR = 0x1,
+ TPM_CAP_PROP_MANUFACTURER = 0x3,
+ TPM_CAP_FLAG_PERM = 0x8,
+ TPM_CAP_FLAG_VOL = 0x9,
+ TPM_CAP_PROP_OWNER = 0x11,
+ TPM_CAP_PROP_TIS_TIMEOUT = 0x15,
+ TPM_CAP_PROP_TIS_DURATION = 0x20,
+};
+
+/*
+ * This is a semi generic GetCapability command for use
+ * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG
+ * and their associated sub_capabilities.
+ */
+
+static const u8 tpm_cap[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 22, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
- 0, 0, 0, 5,
- 0, 0, 0, 4,
- 0, 0, 1, 1
+ 0, 0, 0, 0, /* TPM_CAP_<TYPE> */
+ 0, 0, 0, 4, /* TPM_CAP_SUB_<TYPE> size */
+ 0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */
};
-#define READ_PCR_RESULT_SIZE 30
+static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len,
+ char *desc)
+{
+ int err;
+
+ len = tpm_transmit(chip, data, len);
+ if (len < 0)
+ return len;
+ if (len == TPM_ERROR_SIZE) {
+ err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)));
+ dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
+ return err;
+ }
+ return 0;
+}
+
+void tpm_gen_interrupt(struct tpm_chip *chip)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
+ ssize_t rc;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the timeouts");
+}
+EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
+
+void tpm_get_timeouts(struct tpm_chip *chip)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
+ ssize_t rc;
+ u32 timeout;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the timeouts");
+ if (rc)
+ goto duration;
+
+ if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+ != 4 * sizeof(u32))
+ goto duration;
+
+ /* Don't overwrite default if value is 0 */
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
+ if (timeout)
+ chip->vendor.timeout_a = msecs_to_jiffies(timeout);
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
+ if (timeout)
+ chip->vendor.timeout_b = msecs_to_jiffies(timeout);
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
+ if (timeout)
+ chip->vendor.timeout_c = msecs_to_jiffies(timeout);
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX)));
+ if (timeout)
+ chip->vendor.timeout_d = msecs_to_jiffies(timeout);
+
+duration:
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the durations");
+ if (rc)
+ return;
+
+ if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+ != 3 * sizeof(u32))
+ return;
+
+ chip->vendor.duration[TPM_SHORT] =
+ msecs_to_jiffies(be32_to_cpu
+ (*((__be32 *) (data +
+ TPM_GET_CAP_RET_UINT32_1_IDX))));
+ chip->vendor.duration[TPM_MEDIUM] =
+ msecs_to_jiffies(be32_to_cpu
+ (*((__be32 *) (data +
+ TPM_GET_CAP_RET_UINT32_2_IDX))));
+ chip->vendor.duration[TPM_LONG] =
+ msecs_to_jiffies(be32_to_cpu
+ (*((__be32 *) (data +
+ TPM_GET_CAP_RET_UINT32_3_IDX))));
+}
+EXPORT_SYMBOL_GPL(tpm_get_timeouts);
+
+void tpm_continue_selftest(struct tpm_chip *chip)
+{
+ u8 data[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 10, /* length */
+ 0, 0, 0, 83, /* TPM_ORD_GetCapability */
+ };
+
+ tpm_transmit(chip, data, sizeof(data));
+}
+EXPORT_SYMBOL_GPL(tpm_continue_selftest);
+
+ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attemtping to determine the permanent state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_enabled);
+
+ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attemtping to determine the permanent state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_active);
+
+ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[sizeof(tpm_cap)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the owner state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_owned);
+
+ssize_t tpm_show_temp_deactivated(struct device * dev,
+ struct device_attribute * attr, char *buf)
+{
+ u8 data[sizeof(tpm_cap)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the temporary state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
+
static const u8 pcrread[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 14, /* length */
@@ -140,8 +676,8 @@ static const u8 pcrread[] = {
ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
char *buf)
{
- u8 data[READ_PCR_RESULT_SIZE];
- ssize_t len;
+ u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)];
+ ssize_t rc;
int i, j, num_pcrs;
__be32 index;
char *str = buf;
@@ -150,29 +686,24 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
if (chip == NULL)
return -ENODEV;
- memcpy(data, cap_pcr, sizeof(cap_pcr));
- if ((len = tpm_transmit(chip, data, sizeof(data)))
- < CAP_PCR_RESULT_SIZE) {
- dev_dbg(chip->dev, "A TPM error (%d) occurred "
- "attempting to determine the number of PCRS\n",
- be32_to_cpu(*((__be32 *) (data + 6))));
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the number of PCRS");
+ if (rc)
return 0;
- }
num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
-
for (i = 0; i < num_pcrs; i++) {
memcpy(data, pcrread, sizeof(pcrread));
index = cpu_to_be32(i);
memcpy(data + 10, &index, 4);
- if ((len = tpm_transmit(chip, data, sizeof(data)))
- < READ_PCR_RESULT_SIZE){
- dev_dbg(chip->dev, "A TPM error (%d) occurred"
- " attempting to read PCR %d of %d\n",
- be32_to_cpu(*((__be32 *) (data + 6))),
- i, num_pcrs);
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to read a PCR");
+ if (rc)
goto out;
- }
str += sprintf(str, "PCR-%02d: ", i);
for (j = 0; j < TPM_DIGEST_SIZE; j++)
str += sprintf(str, "%02X ", *(data + 10 + j));
@@ -194,7 +725,7 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
char *buf)
{
u8 *data;
- ssize_t len;
+ ssize_t err;
int i, rc;
char *str = buf;
@@ -208,14 +739,10 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
memcpy(data, readpubek, sizeof(readpubek));
- if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
- READ_PUBEK_RESULT_SIZE) {
- dev_dbg(chip->dev, "A TPM error (%d) occurred "
- "attempting to read the PUBEK\n",
- be32_to_cpu(*((__be32 *) (data + 6))));
- rc = 0;
+ err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE,
+ "attempting to read the PUBEK");
+ if (err)
goto out;
- }
/*
ignore header 10 bytes
@@ -245,67 +772,110 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
if ((i + 1) % 16 == 0)
str += sprintf(str, "\n");
}
- rc = str - buf;
out:
+ rc = str - buf;
kfree(data);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_show_pubek);
-#define CAP_VER_RESULT_SIZE 18
+#define CAP_VERSION_1_1 6
+#define CAP_VERSION_1_2 0x1A
+#define CAP_VERSION_IDX 13
static const u8 cap_version[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 18, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
- 0, 0, 0, 6,
+ 0, 0, 0, 0,
0, 0, 0, 0
};
-#define CAP_MANUFACTURER_RESULT_SIZE 18
-static const u8 cap_manufacturer[] = {
- 0, 193, /* TPM_TAG_RQU_COMMAND */
- 0, 0, 0, 22, /* length */
- 0, 0, 0, 101, /* TPM_ORD_GetCapability */
- 0, 0, 0, 5,
- 0, 0, 0, 4,
- 0, 0, 1, 3
-};
-
ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
char *buf)
{
- u8 data[sizeof(cap_manufacturer)];
- ssize_t len;
+ u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
+ ssize_t rc;
char *str = buf;
struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip == NULL)
return -ENODEV;
- memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
- if ((len = tpm_transmit(chip, data, sizeof(data))) <
- CAP_MANUFACTURER_RESULT_SIZE)
- return len;
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the manufacturer");
+ if (rc)
+ return 0;
str += sprintf(str, "Manufacturer: 0x%x\n",
- be32_to_cpu(*((__be32 *) (data + 14))));
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
memcpy(data, cap_version, sizeof(cap_version));
+ data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the 1.1 version");
+ if (rc)
+ goto out;
- if ((len = tpm_transmit(chip, data, sizeof(data))) <
- CAP_VER_RESULT_SIZE)
- return len;
-
- str +=
- sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
- (int) data[14], (int) data[15], (int) data[16],
- (int) data[17]);
+ str += sprintf(str,
+ "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[14], (int) data[15], (int) data[16],
+ (int) data[17]);
+out:
return str - buf;
}
EXPORT_SYMBOL_GPL(tpm_show_caps);
+ssize_t tpm_show_caps_1_2(struct device * dev,
+ struct device_attribute * attr, char *buf)
+{
+ u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
+ ssize_t len;
+ char *str = buf;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+ TPM_ERROR_SIZE) {
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the manufacturer\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ return 0;
+ }
+
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
+
+ memcpy(data, cap_version, sizeof(cap_version));
+ data[CAP_VERSION_IDX] = CAP_VERSION_1_2;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+ TPM_ERROR_SIZE) {
+ dev_err(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the 1.2 version\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ goto out;
+ }
+ str += sprintf(str,
+ "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[16], (int) data[17], (int) data[18],
+ (int) data[19]);
+
+out:
+ return str - buf;
+}
+EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
+
ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -313,7 +883,7 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
if (chip == NULL)
return 0;
- chip->vendor->cancel(chip);
+ chip->vendor.cancel(chip);
return count;
}
EXPORT_SYMBOL_GPL(tpm_store_cancel);
@@ -329,7 +899,7 @@ int tpm_open(struct inode *inode, struct file *file)
spin_lock(&driver_lock);
list_for_each_entry(pos, &tpm_chip_list, list) {
- if (pos->vendor->miscdev.minor == minor) {
+ if (pos->vendor.miscdev.minor == minor) {
chip = pos;
break;
}
@@ -387,7 +957,7 @@ int tpm_release(struct inode *inode, struct file *file)
EXPORT_SYMBOL_GPL(tpm_release);
ssize_t tpm_write(struct file *file, const char __user *buf,
- size_t size, loff_t * off)
+ size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
int in_size = size, out_size;
@@ -419,11 +989,10 @@ ssize_t tpm_write(struct file *file, const char __user *buf,
return in_size;
}
-
EXPORT_SYMBOL_GPL(tpm_write);
-ssize_t tpm_read(struct file * file, char __user *buf,
- size_t size, loff_t * off)
+ssize_t tpm_read(struct file *file, char __user *buf,
+ size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
int ret_size;
@@ -462,14 +1031,13 @@ void tpm_remove_hardware(struct device *dev)
spin_unlock(&driver_lock);
dev_set_drvdata(dev, NULL);
- misc_deregister(&chip->vendor->miscdev);
- kfree(chip->vendor->miscdev.name);
+ misc_deregister(&chip->vendor.miscdev);
+ kfree(chip->vendor.miscdev.name);
- sysfs_remove_group(&dev->kobj, chip->vendor->attr_group);
+ sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
tpm_bios_log_teardown(chip->bios_dir);
- dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &=
- ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
+ clear_bit(chip->dev_num, dev_mask);
kfree(chip);
@@ -520,18 +1088,18 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
* upon errant exit from this function specific probe function should call
* pci_disable_device
*/
-int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry)
+struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific
+ *entry)
{
#define DEVNAME_SIZE 7
char *devname;
struct tpm_chip *chip;
- int i, j;
/* Driver specific per-device data */
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
- return -ENOMEM;
+ return NULL;
init_MUTEX(&chip->buffer_mutex);
init_MUTEX(&chip->tpm_mutex);
@@ -543,45 +1111,37 @@ int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry)
chip->user_read_timer.function = user_reader_timeout;
chip->user_read_timer.data = (unsigned long) chip;
- chip->vendor = entry;
-
- chip->dev_num = -1;
+ memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
- for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
- for (j = 0; j < 8 * sizeof(int); j++)
- if ((dev_mask[i] & (1 << j)) == 0) {
- chip->dev_num =
- i * TPM_NUM_MASK_ENTRIES + j;
- dev_mask[i] |= 1 << j;
- goto dev_num_search_complete;
- }
+ chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
-dev_num_search_complete:
- if (chip->dev_num < 0) {
+ if (chip->dev_num >= TPM_NUM_DEVICES) {
dev_err(dev, "No available tpm device numbers\n");
kfree(chip);
- return -ENODEV;
+ return NULL;
} else if (chip->dev_num == 0)
- chip->vendor->miscdev.minor = TPM_MINOR;
+ chip->vendor.miscdev.minor = TPM_MINOR;
else
- chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+ chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
+
+ set_bit(chip->dev_num, dev_mask);
devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
- chip->vendor->miscdev.name = devname;
+ chip->vendor.miscdev.name = devname;
- chip->vendor->miscdev.dev = dev;
+ chip->vendor.miscdev.dev = dev;
chip->dev = get_device(dev);
- if (misc_register(&chip->vendor->miscdev)) {
+ if (misc_register(&chip->vendor.miscdev)) {
dev_err(chip->dev,
"unable to misc_register %s, minor %d\n",
- chip->vendor->miscdev.name,
- chip->vendor->miscdev.minor);
+ chip->vendor.miscdev.name,
+ chip->vendor.miscdev.minor);
put_device(dev);
+ clear_bit(chip->dev_num, dev_mask);
kfree(chip);
- dev_mask[i] &= !(1 << j);
- return -ENODEV;
+ return NULL;
}
spin_lock(&driver_lock);
@@ -592,11 +1152,11 @@ dev_num_search_complete:
spin_unlock(&driver_lock);
- sysfs_create_group(&dev->kobj, chip->vendor->attr_group);
+ sysfs_create_group(&dev->kobj, chip->vendor.attr_group);
chip->bios_dir = tpm_bios_log_setup(devname);
- return 0;
+ return chip;
}
EXPORT_SYMBOL_GPL(tpm_register_hardware);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index dec0224b447..050ced247f6 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -42,18 +42,30 @@ extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
char *);
extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
char *);
+extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr,
+ char *);
extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
const char *, size_t);
+extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_temp_deactivated(struct device *,
+ struct device_attribute *attr, char *);
struct tpm_chip;
struct tpm_vendor_specific {
- u8 req_complete_mask;
- u8 req_complete_val;
- u8 req_canceled;
+ const u8 req_complete_mask;
+ const u8 req_complete_val;
+ const u8 req_canceled;
void __iomem *iobase; /* ioremapped address */
unsigned long base; /* TPM base address */
+ int irq;
+
int region_size;
int have_region;
@@ -63,6 +75,13 @@ struct tpm_vendor_specific {
u8 (*status) (struct tpm_chip *);
struct miscdevice miscdev;
struct attribute_group *attr_group;
+ struct list_head list;
+ int locality;
+ unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
+ unsigned long duration[3]; /* jiffies */
+
+ wait_queue_head_t read_queue;
+ wait_queue_head_t int_queue;
};
struct tpm_chip {
@@ -81,13 +100,15 @@ struct tpm_chip {
struct work_struct work;
struct semaphore tpm_mutex; /* tpm is processing */
- struct tpm_vendor_specific *vendor;
+ struct tpm_vendor_specific vendor;
struct dentry **bios_dir;
struct list_head list;
};
+#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
+
static inline int tpm_read_index(int base, int index)
{
outb(index, base);
@@ -100,8 +121,12 @@ static inline void tpm_write_index(int base, int index, int value)
outb(value & 0xFF, base+1);
}
-extern int tpm_register_hardware(struct device *,
- struct tpm_vendor_specific *);
+extern void tpm_get_timeouts(struct tpm_chip *);
+extern void tpm_gen_interrupt(struct tpm_chip *);
+extern void tpm_continue_selftest(struct tpm_chip *);
+extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
+extern struct tpm_chip* tpm_register_hardware(struct device *,
+ const struct tpm_vendor_specific *);
extern int tpm_open(struct inode *, struct file *);
extern int tpm_release(struct inode *, struct file *);
extern ssize_t tpm_write(struct file *, const char __user *, size_t,
@@ -115,7 +140,7 @@ extern int tpm_pm_resume(struct device *);
extern struct dentry ** tpm_bios_log_setup(char *);
extern void tpm_bios_log_teardown(struct dentry **);
#else
-static inline struct dentry* tpm_bios_log_setup(char *name)
+static inline struct dentry ** tpm_bios_log_setup(char *name)
{
return NULL;
}
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index ff3654964fe..58a258cec15 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -47,12 +47,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
return -EIO;
for (i = 0; i < 6; i++) {
- status = ioread8(chip->vendor->iobase + 1);
+ status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->dev, "error reading header\n");
return -EIO;
}
- *buf++ = ioread8(chip->vendor->iobase);
+ *buf++ = ioread8(chip->vendor.iobase);
}
/* size of the data received */
@@ -63,7 +63,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
dev_err(chip->dev,
"Recv size(%d) less than available space\n", size);
for (; i < size; i++) { /* clear the waiting data anyway */
- status = ioread8(chip->vendor->iobase + 1);
+ status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->dev, "error reading data\n");
return -EIO;
@@ -74,16 +74,16 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
/* read all the data available */
for (; i < size; i++) {
- status = ioread8(chip->vendor->iobase + 1);
+ status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->dev, "error reading data\n");
return -EIO;
}
- *buf++ = ioread8(chip->vendor->iobase);
+ *buf++ = ioread8(chip->vendor.iobase);
}
/* make sure data available is gone */
- status = ioread8(chip->vendor->iobase + 1);
+ status = ioread8(chip->vendor.iobase + 1);
if (status & ATML_STATUS_DATA_AVAIL) {
dev_err(chip->dev, "data available is stuck\n");
@@ -100,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
dev_dbg(chip->dev, "tpm_atml_send:\n");
for (i = 0; i < count; i++) {
dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]);
- iowrite8(buf[i], chip->vendor->iobase);
+ iowrite8(buf[i], chip->vendor.iobase);
}
return count;
@@ -108,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
static void tpm_atml_cancel(struct tpm_chip *chip)
{
- iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1);
+ iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1);
}
static u8 tpm_atml_status(struct tpm_chip *chip)
{
- return ioread8(chip->vendor->iobase + 1);
+ return ioread8(chip->vendor.iobase + 1);
}
static struct file_operations atmel_ops = {
@@ -140,7 +140,7 @@ static struct attribute* atmel_attrs[] = {
static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
-static struct tpm_vendor_specific tpm_atmel = {
+static const struct tpm_vendor_specific tpm_atmel = {
.recv = tpm_atml_recv,
.send = tpm_atml_send,
.cancel = tpm_atml_cancel,
@@ -159,10 +159,10 @@ static void atml_plat_remove(void)
struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
if (chip) {
- if (chip->vendor->have_region)
- atmel_release_region(chip->vendor->base,
- chip->vendor->region_size);
- atmel_put_base_addr(chip->vendor);
+ if (chip->vendor.have_region)
+ atmel_release_region(chip->vendor.base,
+ chip->vendor.region_size);
+ atmel_put_base_addr(chip->vendor.iobase);
tpm_remove_hardware(chip->dev);
platform_device_unregister(pdev);
}
@@ -179,18 +179,22 @@ static struct device_driver atml_drv = {
static int __init init_atmel(void)
{
int rc = 0;
+ void __iomem *iobase = NULL;
+ int have_region, region_size;
+ unsigned long base;
+ struct tpm_chip *chip;
driver_register(&atml_drv);
- if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) {
+ if ((iobase = atmel_get_base_addr(&base, &region_size)) == NULL) {
rc = -ENODEV;
goto err_unreg_drv;
}
- tpm_atmel.have_region =
+ have_region =
(atmel_request_region
- (tpm_atmel.base, tpm_atmel.region_size,
- "tpm_atmel0") == NULL) ? 0 : 1;
+ (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
+
if (IS_ERR
(pdev =
@@ -199,17 +203,25 @@ static int __init init_atmel(void)
goto err_rel_reg;
}
- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0)
+ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) {
+ rc = -ENODEV;
goto err_unreg_dev;
+ }
+
+ chip->vendor.iobase = iobase;
+ chip->vendor.base = base;
+ chip->vendor.have_region = have_region;
+ chip->vendor.region_size = region_size;
+
return 0;
err_unreg_dev:
platform_device_unregister(pdev);
err_rel_reg:
- atmel_put_base_addr(&tpm_atmel);
- if (tpm_atmel.have_region)
- atmel_release_region(tpm_atmel.base,
- tpm_atmel.region_size);
+ atmel_put_base_addr(iobase);
+ if (have_region)
+ atmel_release_region(base,
+ region_size);
err_unreg_drv:
driver_unregister(&atml_drv);
return rc;
diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h
index d3478aaadd7..2e68eeb8a2c 100644
--- a/drivers/char/tpm/tpm_atmel.h
+++ b/drivers/char/tpm/tpm_atmel.h
@@ -28,13 +28,12 @@
#define atmel_request_region request_mem_region
#define atmel_release_region release_mem_region
-static inline void atmel_put_base_addr(struct tpm_vendor_specific
- *vendor)
+static inline void atmel_put_base_addr(void __iomem *iobase)
{
- iounmap(vendor->iobase);
+ iounmap(iobase);
}
-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor)
+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
{
struct device_node *dn;
unsigned long address, size;
@@ -71,9 +70,9 @@ static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor)
else
size = reg[naddrc];
- vendor->base = address;
- vendor->region_size = size;
- return ioremap(vendor->base, vendor->region_size);
+ *base = address;
+ *region_size = size;
+ return ioremap(*base, *region_size);
}
#else
#define atmel_getb(chip, offset) inb(chip->vendor->base + offset)
@@ -106,14 +105,12 @@ static int atmel_verify_tpm11(void)
return 0;
}
-static inline void atmel_put_base_addr(struct tpm_vendor_specific
- *vendor)
+static inline void atmel_put_base_addr(void __iomem *iobase)
{
}
/* Determine where to talk to device */
-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific
- *vendor)
+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
{
int lo, hi;
@@ -123,9 +120,9 @@ static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific
lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
- vendor->base = (hi << 8) | lo;
- vendor->region_size = 2;
+ *base = (hi << 8) | lo;
+ *region_size = 2;
- return ioport_map(vendor->base, vendor->region_size);
+ return ioport_map(*base, *region_size);
}
#endif
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
index 537aa45d8c6..a611972024e 100644
--- a/drivers/char/tpm/tpm_bios.c
+++ b/drivers/char/tpm/tpm_bios.c
@@ -29,6 +29,11 @@
#define MAX_TEXT_EVENT 1000 /* Max event string length */
#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
+enum bios_platform_class {
+ BIOS_CLIENT = 0x00,
+ BIOS_SERVER = 0x01,
+};
+
struct tpm_bios_log {
void *bios_event_log;
void *bios_event_log_end;
@@ -36,9 +41,18 @@ struct tpm_bios_log {
struct acpi_tcpa {
struct acpi_table_header hdr;
- u16 reserved;
- u32 log_max_len __attribute__ ((packed));
- u32 log_start_addr __attribute__ ((packed));
+ u16 platform_class;
+ union {
+ struct client_hdr {
+ u32 log_max_len __attribute__ ((packed));
+ u64 log_start_addr __attribute__ ((packed));
+ } client;
+ struct server_hdr {
+ u16 reserved;
+ u64 log_max_len __attribute__ ((packed));
+ u64 log_start_addr __attribute__ ((packed));
+ } server;
+ };
};
struct tcpa_event {
@@ -91,6 +105,12 @@ static const char* tcpa_event_type_strings[] = {
"Non-Host Info"
};
+struct tcpa_pc_event {
+ u32 event_id;
+ u32 event_size;
+ u8 event_data[0];
+};
+
enum tcpa_pc_event_ids {
SMBIOS = 1,
BIS_CERT,
@@ -100,14 +120,15 @@ enum tcpa_pc_event_ids {
NVRAM,
OPTION_ROM_EXEC,
OPTION_ROM_CONFIG,
- OPTION_ROM_MICROCODE,
+ OPTION_ROM_MICROCODE = 10,
S_CRTM_VERSION,
S_CRTM_CONTENTS,
POST_CONTENTS,
+ HOST_TABLE_OF_DEVICES,
};
static const char* tcpa_pc_event_id_strings[] = {
- ""
+ "",
"SMBIOS",
"BIS Certificate",
"POST BIOS ",
@@ -116,10 +137,12 @@ static const char* tcpa_pc_event_id_strings[] = {
"NVRAM",
"Option ROM",
"Option ROM config",
- "Option ROM microcode",
+ "",
+ "Option ROM microcode ",
"S-CRTM Version",
- "S-CRTM Contents",
- "S-CRTM POST Contents",
+ "S-CRTM Contents ",
+ "POST Contents ",
+ "Table of Devices",
};
/* returns pointer to start of pos. entry of tcg log */
@@ -191,7 +214,7 @@ static int get_event_name(char *dest, struct tcpa_event *event,
const char *name = "";
char data[40] = "";
int i, n_len = 0, d_len = 0;
- u32 event_id;
+ struct tcpa_pc_event *pc_event;
switch(event->event_type) {
case PREBOOT:
@@ -220,31 +243,32 @@ static int get_event_name(char *dest, struct tcpa_event *event,
}
break;
case EVENT_TAG:
- event_id = be32_to_cpu(*((u32 *)event_entry));
+ pc_event = (struct tcpa_pc_event *)event_entry;
/* ToDo Row data -> Base64 */
- switch (event_id) {
+ switch (pc_event->event_id) {
case SMBIOS:
case BIS_CERT:
case CMOS:
case NVRAM:
case OPTION_ROM_EXEC:
case OPTION_ROM_CONFIG:
- case OPTION_ROM_MICROCODE:
case S_CRTM_VERSION:
- case S_CRTM_CONTENTS:
- case POST_CONTENTS:
- name = tcpa_pc_event_id_strings[event_id];
+ name = tcpa_pc_event_id_strings[pc_event->event_id];
n_len = strlen(name);
break;
+ /* hash data */
case POST_BIOS_ROM:
case ESCD:
- name = tcpa_pc_event_id_strings[event_id];
+ case OPTION_ROM_MICROCODE:
+ case S_CRTM_CONTENTS:
+ case POST_CONTENTS:
+ name = tcpa_pc_event_id_strings[pc_event->event_id];
n_len = strlen(name);
for (i = 0; i < 20; i++)
- d_len += sprintf(data, "%02x",
- event_entry[8 + i]);
+ d_len += sprintf(&data[2*i], "%02x",
+ pc_event->event_data[i]);
break;
default:
break;
@@ -260,52 +284,13 @@ static int get_event_name(char *dest, struct tcpa_event *event,
static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
{
+ struct tcpa_event *event = v;
+ char *data = v;
+ int i;
- char *eventname;
- char data[4];
- u32 help;
- int i, len;
- struct tcpa_event *event = (struct tcpa_event *) v;
- unsigned char *event_entry =
- (unsigned char *) (v + sizeof(struct tcpa_event));
-
- eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
- if (!eventname) {
- printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
- __func__);
- return -ENOMEM;
- }
-
- /* 1st: PCR used is in little-endian format (4 bytes) */
- help = le32_to_cpu(event->pcr_index);
- memcpy(data, &help, 4);
- for (i = 0; i < 4; i++)
- seq_putc(m, data[i]);
-
- /* 2nd: SHA1 (20 bytes) */
- for (i = 0; i < 20; i++)
- seq_putc(m, event->pcr_value[i]);
-
- /* 3rd: event type identifier (4 bytes) */
- help = le32_to_cpu(event->event_type);
- memcpy(data, &help, 4);
- for (i = 0; i < 4; i++)
+ for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
seq_putc(m, data[i]);
- len = 0;
-
- len += get_event_name(eventname, event, event_entry);
-
- /* 4th: filename <= 255 + \'0' delimiter */
- if (len > TCG_EVENT_NAME_LEN_MAX)
- len = TCG_EVENT_NAME_LEN_MAX;
-
- for (i = 0; i < len; i++)
- seq_putc(m, eventname[i]);
-
- /* 5th: delimiter */
- seq_putc(m, '\0');
-
return 0;
}
@@ -353,6 +338,7 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
/* 4th: eventname <= max + \'0' delimiter */
seq_printf(m, " %s\n", eventname);
+ kfree(eventname);
return 0;
}
@@ -376,6 +362,7 @@ static int read_log(struct tpm_bios_log *log)
struct acpi_tcpa *buff;
acpi_status status;
struct acpi_table_header *virt;
+ u64 len, start;
if (log->bios_event_log != NULL) {
printk(KERN_ERR
@@ -396,27 +383,37 @@ static int read_log(struct tpm_bios_log *log)
return -EIO;
}
- if (buff->log_max_len == 0) {
+ switch(buff->platform_class) {
+ case BIOS_SERVER:
+ len = buff->server.log_max_len;
+ start = buff->server.log_start_addr;
+ break;
+ case BIOS_CLIENT:
+ default:
+ len = buff->client.log_max_len;
+ start = buff->client.log_start_addr;
+ break;
+ }
+ if (!len) {
printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
return -EIO;
}
/* malloc EventLog space */
- log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL);
+ log->bios_event_log = kmalloc(len, GFP_KERNEL);
if (!log->bios_event_log) {
- printk
- ("%s: ERROR - Not enough Memory for BIOS measurements\n",
- __func__);
+ printk("%s: ERROR - Not enough Memory for BIOS measurements\n",
+ __func__);
return -ENOMEM;
}
- log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
+ log->bios_event_log_end = log->bios_event_log + len;
- acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt);
+ acpi_os_map_memory(start, len, (void *) &virt);
- memcpy(log->bios_event_log, virt, buff->log_max_len);
+ memcpy(log->bios_event_log, virt, len);
- acpi_os_unmap_memory(virt, buff->log_max_len);
+ acpi_os_unmap_memory(virt, len);
return 0;
}
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 24095f6ee6d..adfff21beb2 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -15,6 +15,7 @@
* License.
*/
+#include <linux/init.h>
#include <linux/pnp.h>
#include "tpm.h"
@@ -104,7 +105,7 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
if (clear_wrfifo) {
for (i = 0; i < 4096; i++) {
- status = inb(chip->vendor->base + WRFIFO);
+ status = inb(chip->vendor.base + WRFIFO);
if (status == 0xff) {
if (check == 5)
break;
@@ -124,8 +125,8 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
*/
i = 0;
do {
- status = inb(chip->vendor->base + RDFIFO);
- status = inb(chip->vendor->base + STAT);
+ status = inb(chip->vendor.base + RDFIFO);
+ status = inb(chip->vendor.base + STAT);
i++;
if (i == TPM_MAX_TRIES)
return -EIO;
@@ -138,7 +139,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
int status;
int i;
for (i = 0; i < TPM_MAX_TRIES; i++) {
- status = inb(chip->vendor->base + STAT);
+ status = inb(chip->vendor.base + STAT);
/* check the status-register if wait_for_bit is set */
if (status & 1 << wait_for_bit)
break;
@@ -157,7 +158,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
{
wait(chip, STAT_XFE);
- outb(sendbyte, chip->vendor->base + WRFIFO);
+ outb(sendbyte, chip->vendor.base + WRFIFO);
}
/* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
@@ -204,7 +205,7 @@ recv_begin:
ret = wait(chip, STAT_RDA);
if (ret)
return -EIO;
- buf[i] = inb(chip->vendor->base + RDFIFO);
+ buf[i] = inb(chip->vendor.base + RDFIFO);
}
if (buf[0] != TPM_VL_VER) {
@@ -219,7 +220,7 @@ recv_begin:
for (i = 0; i < size; i++) {
wait(chip, STAT_RDA);
- buf[i] = inb(chip->vendor->base + RDFIFO);
+ buf[i] = inb(chip->vendor.base + RDFIFO);
}
if ((size == 0x6D00) && (buf[1] == 0x80)) {
@@ -268,7 +269,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
u8 count_high, count_low, count_4, count_3, count_2, count_1;
/* Disabling Reset, LP and IRQC */
- outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD);
+ outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD);
ret = empty_fifo(chip, 1);
if (ret) {
@@ -319,7 +320,7 @@ static void tpm_inf_cancel(struct tpm_chip *chip)
static u8 tpm_inf_status(struct tpm_chip *chip)
{
- return inb(chip->vendor->base + STAT);
+ return inb(chip->vendor.base + STAT);
}
static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
@@ -346,7 +347,7 @@ static struct file_operations inf_ops = {
.release = tpm_release,
};
-static struct tpm_vendor_specific tpm_inf = {
+static const struct tpm_vendor_specific tpm_inf = {
.recv = tpm_inf_recv,
.send = tpm_inf_send,
.cancel = tpm_inf_cancel,
@@ -375,6 +376,7 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
int version[2];
int productid[2];
char chipname[20];
+ struct tpm_chip *chip;
/* read IO-ports through PnP */
if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
@@ -395,14 +397,13 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
goto err_last;
}
/* publish my base address and request region */
- tpm_inf.base = TPM_INF_BASE;
if (request_region
- (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
+ (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
rc = -EINVAL;
goto err_last;
}
- if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN,
- "tpm_infineon0") == NULL) {
+ if (request_region
+ (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) {
rc = -EINVAL;
goto err_last;
}
@@ -442,9 +443,9 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
/* configure TPM with IO-ports */
outb(IOLIMH, TPM_INF_ADDR);
- outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
+ outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA);
outb(IOLIML, TPM_INF_ADDR);
- outb((tpm_inf.base & 0xff), TPM_INF_DATA);
+ outb((TPM_INF_BASE & 0xff), TPM_INF_DATA);
/* control if IO-ports are set correctly */
outb(IOLIMH, TPM_INF_ADDR);
@@ -452,10 +453,10 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
outb(IOLIML, TPM_INF_ADDR);
iol = inb(TPM_INF_DATA);
- if ((ioh << 8 | iol) != tpm_inf.base) {
+ if ((ioh << 8 | iol) != TPM_INF_BASE) {
dev_err(&dev->dev,
- "Could not set IO-ports to 0x%lx\n",
- tpm_inf.base);
+ "Could not set IO-ports to 0x%x\n",
+ TPM_INF_BASE);
rc = -EIO;
goto err_release_region;
}
@@ -466,15 +467,15 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
/* disable RESET, LP and IRQC */
- outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
+ outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD);
/* Finally, we're done, print some infos */
dev_info(&dev->dev, "TPM found: "
"config base 0x%x, "
"io base 0x%x, "
- "chip version %02x%02x, "
- "vendor id %x%x (Infineon), "
- "product id %02x%02x"
+ "chip version 0x%02x%02x, "
+ "vendor id 0x%x%x (Infineon), "
+ "product id 0x%02x%02x"
"%s\n",
TPM_INF_ADDR,
TPM_INF_BASE,
@@ -482,11 +483,10 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
vendorid[0], vendorid[1],
productid[0], productid[1], chipname);
- rc = tpm_register_hardware(&dev->dev, &tpm_inf);
- if (rc < 0) {
- rc = -ENODEV;
+ if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) {
goto err_release_region;
}
+ chip->vendor.base = TPM_INF_BASE;
return 0;
} else {
rc = -ENODEV;
@@ -494,7 +494,7 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
}
err_release_region:
- release_region(tpm_inf.base, TPM_INF_PORT_LEN);
+ release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
err_last:
@@ -506,7 +506,8 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
struct tpm_chip *chip = pnp_get_drvdata(dev);
if (chip) {
- release_region(chip->vendor->base, TPM_INF_PORT_LEN);
+ release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
+ release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
tpm_remove_hardware(chip->dev);
}
}
@@ -520,7 +521,7 @@ static struct pnp_driver tpm_inf_pnp = {
},
.id_table = tpm_pnp_tbl,
.probe = tpm_inf_pnp_probe,
- .remove = tpm_inf_pnp_remove,
+ .remove = __devexit_p(tpm_inf_pnp_remove),
};
static int __init init_inf(void)
@@ -538,5 +539,5 @@ module_exit(cleanup_inf);
MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
-MODULE_VERSION("1.7");
+MODULE_VERSION("1.8");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 680a8e33188..4c8bc06c7d9 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -71,7 +71,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
unsigned long stop;
/* status immediately available check */
- *data = inb(chip->vendor->base + NSC_STATUS);
+ *data = inb(chip->vendor.base + NSC_STATUS);
if ((*data & mask) == val)
return 0;
@@ -79,7 +79,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
stop = jiffies + 10 * HZ;
do {
msleep(TPM_TIMEOUT);
- *data = inb(chip->vendor->base + 1);
+ *data = inb(chip->vendor.base + 1);
if ((*data & mask) == val)
return 0;
}
@@ -94,9 +94,9 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
unsigned long stop;
/* status immediately available check */
- status = inb(chip->vendor->base + NSC_STATUS);
+ status = inb(chip->vendor.base + NSC_STATUS);
if (status & NSC_STATUS_OBF)
- status = inb(chip->vendor->base + NSC_DATA);
+ status = inb(chip->vendor.base + NSC_DATA);
if (status & NSC_STATUS_RDY)
return 0;
@@ -104,9 +104,9 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
stop = jiffies + 100;
do {
msleep(TPM_TIMEOUT);
- status = inb(chip->vendor->base + NSC_STATUS);
+ status = inb(chip->vendor.base + NSC_STATUS);
if (status & NSC_STATUS_OBF)
- status = inb(chip->vendor->base + NSC_DATA);
+ status = inb(chip->vendor.base + NSC_DATA);
if (status & NSC_STATUS_RDY)
return 0;
}
@@ -132,7 +132,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
return -EIO;
}
if ((data =
- inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+ inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
dev_err(chip->dev, "not in normal mode (0x%x)\n",
data);
return -EIO;
@@ -148,7 +148,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
}
if (data & NSC_STATUS_F0)
break;
- *p = inb(chip->vendor->base + NSC_DATA);
+ *p = inb(chip->vendor.base + NSC_DATA);
}
if ((data & NSC_STATUS_F0) == 0 &&
@@ -156,7 +156,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
dev_err(chip->dev, "F0 not set\n");
return -EIO;
}
- if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
+ if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) {
dev_err(chip->dev,
"expected end of command(0x%x)\n", data);
return -EIO;
@@ -182,7 +182,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
* fix it. Not sure why this is needed, we followed the flow
* chart in the manual to the letter.
*/
- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
if (nsc_wait_for_ready(chip) != 0)
return -EIO;
@@ -192,7 +192,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
return -EIO;
}
- outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
+ outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND);
if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
dev_err(chip->dev, "IBR timeout\n");
return -EIO;
@@ -204,26 +204,26 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
"IBF timeout (while writing data)\n");
return -EIO;
}
- outb(buf[i], chip->vendor->base + NSC_DATA);
+ outb(buf[i], chip->vendor.base + NSC_DATA);
}
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
dev_err(chip->dev, "IBF timeout\n");
return -EIO;
}
- outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
+ outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND);
return count;
}
static void tpm_nsc_cancel(struct tpm_chip *chip)
{
- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
}
static u8 tpm_nsc_status(struct tpm_chip *chip)
{
- return inb(chip->vendor->base + NSC_STATUS);
+ return inb(chip->vendor.base + NSC_STATUS);
}
static struct file_operations nsc_ops = {
@@ -250,7 +250,7 @@ static struct attribute * nsc_attrs[] = {
static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
-static struct tpm_vendor_specific tpm_nsc = {
+static const struct tpm_vendor_specific tpm_nsc = {
.recv = tpm_nsc_recv,
.send = tpm_nsc_send,
.cancel = tpm_nsc_cancel,
@@ -268,7 +268,7 @@ static void __devexit tpm_nsc_remove(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
if ( chip ) {
- release_region(chip->vendor->base, 2);
+ release_region(chip->vendor.base, 2);
tpm_remove_hardware(chip->dev);
}
}
@@ -286,7 +286,8 @@ static int __init init_nsc(void)
int rc = 0;
int lo, hi;
int nscAddrBase = TPM_ADDR;
-
+ struct tpm_chip *chip;
+ unsigned long base;
/* verify that it is a National part (SID) */
if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
@@ -300,7 +301,7 @@ static int __init init_nsc(void)
hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
- tpm_nsc.base = (hi<<8) | lo;
+ base = (hi<<8) | lo;
/* enable the DPM module */
tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
@@ -320,13 +321,15 @@ static int __init init_nsc(void)
if ((rc = platform_device_register(pdev)) < 0)
goto err_free_dev;
- if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) {
+ if (request_region(base, 2, "tpm_nsc0") == NULL ) {
rc = -EBUSY;
goto err_unreg_dev;
}
- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0)
+ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
+ rc = -ENODEV;
goto err_rel_reg;
+ }
dev_dbg(&pdev->dev, "NSC TPM detected\n");
dev_dbg(&pdev->dev,
@@ -361,10 +364,12 @@ static int __init init_nsc(void)
"NSC TPM revision %d\n",
tpm_read_index(nscAddrBase, 0x27) & 0x1F);
+ chip->vendor.base = base;
+
return 0;
err_rel_reg:
- release_region(tpm_nsc.base, 2);
+ release_region(base, 2);
err_unreg_dev:
platform_device_unregister(pdev);
err_free_dev:
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
new file mode 100644
index 00000000000..8ea70625f7e
--- /dev/null
+++ b/drivers/char/tpm/tpm_tis.c
@@ -0,0 +1,665 @@
+/*
+ * Copyright (C) 2005, 2006 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.0.
+ *
+ * This program is free software; 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/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pnp.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include "tpm.h"
+
+#define TPM_HEADER_SIZE 10
+
+enum tis_access {
+ TPM_ACCESS_VALID = 0x80,
+ TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+ TPM_ACCESS_REQUEST_PENDING = 0x04,
+ TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum tis_status {
+ TPM_STS_VALID = 0x80,
+ TPM_STS_COMMAND_READY = 0x40,
+ TPM_STS_GO = 0x20,
+ TPM_STS_DATA_AVAIL = 0x10,
+ TPM_STS_DATA_EXPECT = 0x08,
+};
+
+enum tis_int_flags {
+ TPM_GLOBAL_INT_ENABLE = 0x80000000,
+ TPM_INTF_BURST_COUNT_STATIC = 0x100,
+ TPM_INTF_CMD_READY_INT = 0x080,
+ TPM_INTF_INT_EDGE_FALLING = 0x040,
+ TPM_INTF_INT_EDGE_RISING = 0x020,
+ TPM_INTF_INT_LEVEL_LOW = 0x010,
+ TPM_INTF_INT_LEVEL_HIGH = 0x008,
+ TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
+ TPM_INTF_STS_VALID_INT = 0x002,
+ TPM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+enum tis_defaults {
+ TIS_MEM_BASE = 0xFED40000,
+ TIS_MEM_LEN = 0x5000,
+ TIS_SHORT_TIMEOUT = 750, /* ms */
+ TIS_LONG_TIMEOUT = 2000, /* 2 sec */
+};
+
+#define TPM_ACCESS(l) (0x0000 | ((l) << 12))
+#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12))
+#define TPM_INT_VECTOR(l) (0x000C | ((l) << 12))
+#define TPM_INT_STATUS(l) (0x0010 | ((l) << 12))
+#define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12))
+#define TPM_STS(l) (0x0018 | ((l) << 12))
+#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12))
+
+#define TPM_DID_VID(l) (0x0F00 | ((l) << 12))
+#define TPM_RID(l) (0x0F04 | ((l) << 12))
+
+static LIST_HEAD(tis_chips);
+static DEFINE_SPINLOCK(tis_lock);
+
+static int check_locality(struct tpm_chip *chip, int l)
+{
+ if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
+ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
+ return chip->vendor.locality = l;
+
+ return -1;
+}
+
+static void release_locality(struct tpm_chip *chip, int l, int force)
+{
+ if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
+ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
+ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
+ iowrite8(TPM_ACCESS_ACTIVE_LOCALITY,
+ chip->vendor.iobase + TPM_ACCESS(l));
+}
+
+static int request_locality(struct tpm_chip *chip, int l)
+{
+ unsigned long stop;
+ long rc;
+
+ if (check_locality(chip, l) >= 0)
+ return l;
+
+ iowrite8(TPM_ACCESS_REQUEST_USE,
+ chip->vendor.iobase + TPM_ACCESS(l));
+
+ if (chip->vendor.irq) {
+ rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
+ (check_locality
+ (chip, l) >= 0),
+ chip->vendor.timeout_a);
+ if (rc > 0)
+ return l;
+
+ } else {
+ /* wait for burstcount */
+ stop = jiffies + chip->vendor.timeout_a;
+ do {
+ if (check_locality(chip, l) >= 0)
+ return l;
+ msleep(TPM_TIMEOUT);
+ }
+ while (time_before(jiffies, stop));
+ }
+ return -1;
+}
+
+static u8 tpm_tis_status(struct tpm_chip *chip)
+{
+ return ioread8(chip->vendor.iobase +
+ TPM_STS(chip->vendor.locality));
+}
+
+static void tpm_tis_ready(struct tpm_chip *chip)
+{
+ /* this causes the current command to be aborted */
+ iowrite8(TPM_STS_COMMAND_READY,
+ chip->vendor.iobase + TPM_STS(chip->vendor.locality));
+}
+
+static int get_burstcount(struct tpm_chip *chip)
+{
+ unsigned long stop;
+ int burstcnt;
+
+ /* wait for burstcount */
+ /* which timeout value, spec has 2 answers (c & d) */
+ stop = jiffies + chip->vendor.timeout_d;
+ do {
+ burstcnt = ioread8(chip->vendor.iobase +
+ TPM_STS(chip->vendor.locality) + 1);
+ burstcnt += ioread8(chip->vendor.iobase +
+ TPM_STS(chip->vendor.locality) +
+ 2) << 8;
+ if (burstcnt)
+ return burstcnt;
+ msleep(TPM_TIMEOUT);
+ } while (time_before(jiffies, stop));
+ return -EBUSY;
+}
+
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+ wait_queue_head_t *queue)
+{
+ unsigned long stop;
+ long rc;
+ u8 status;
+
+ /* check current status */
+ status = tpm_tis_status(chip);
+ if ((status & mask) == mask)
+ return 0;
+
+ if (chip->vendor.irq) {
+ rc = wait_event_interruptible_timeout(*queue,
+ ((tpm_tis_status
+ (chip) & mask) ==
+ mask), timeout);
+ if (rc > 0)
+ return 0;
+ } else {
+ stop = jiffies + timeout;
+ do {
+ msleep(TPM_TIMEOUT);
+ status = tpm_tis_status(chip);
+ if ((status & mask) == mask)
+ return 0;
+ } while (time_before(jiffies, stop));
+ }
+ return -ETIME;
+}
+
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+ int size = 0, burstcnt;
+ while (size < count &&
+ wait_for_stat(chip,
+ TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ chip->vendor.timeout_c,
+ &chip->vendor.read_queue)
+ == 0) {
+ burstcnt = get_burstcount(chip);
+ for (; burstcnt > 0 && size < count; burstcnt--)
+ buf[size++] = ioread8(chip->vendor.iobase +
+ TPM_DATA_FIFO(chip->vendor.
+ locality));
+ }
+ return size;
+}
+
+static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+ int size = 0;
+ int expected, status;
+
+ if (count < TPM_HEADER_SIZE) {
+ size = -EIO;
+ goto out;
+ }
+
+ /* read first 10 bytes, including tag, paramsize, and result */
+ if ((size =
+ recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
+ dev_err(chip->dev, "Unable to read header\n");
+ goto out;
+ }
+
+ expected = be32_to_cpu(*(__be32 *) (buf + 2));
+ if (expected > count) {
+ size = -EIO;
+ goto out;
+ }
+
+ if ((size +=
+ recv_data(chip, &buf[TPM_HEADER_SIZE],
+ expected - TPM_HEADER_SIZE)) < expected) {
+ dev_err(chip->dev, "Unable to read remainder of result\n");
+ size = -ETIME;
+ goto out;
+ }
+
+ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+ status = tpm_tis_status(chip);
+ if (status & TPM_STS_DATA_AVAIL) { /* retry? */
+ dev_err(chip->dev, "Error left over data\n");
+ size = -EIO;
+ goto out;
+ }
+
+out:
+ tpm_tis_ready(chip);
+ release_locality(chip, chip->vendor.locality, 0);
+ return size;
+}
+
+/*
+ * If interrupts are used (signaled by an irq set in the vendor structure)
+ * tpm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+ int rc, status, burstcnt;
+ size_t count = 0;
+ u32 ordinal;
+
+ if (request_locality(chip, 0) < 0)
+ return -EBUSY;
+
+ status = tpm_tis_status(chip);
+ if ((status & TPM_STS_COMMAND_READY) == 0) {
+ tpm_tis_ready(chip);
+ if (wait_for_stat
+ (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
+ &chip->vendor.int_queue) < 0) {
+ rc = -ETIME;
+ goto out_err;
+ }
+ }
+
+ while (count < len - 1) {
+ burstcnt = get_burstcount(chip);
+ for (; burstcnt > 0 && count < len - 1; burstcnt--) {
+ iowrite8(buf[count], chip->vendor.iobase +
+ TPM_DATA_FIFO(chip->vendor.locality));
+ count++;
+ }
+
+ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+ status = tpm_tis_status(chip);
+ if ((status & TPM_STS_DATA_EXPECT) == 0) {
+ rc = -EIO;
+ goto out_err;
+ }
+ }
+
+ /* write last byte */
+ iowrite8(buf[count],
+ chip->vendor.iobase +
+ TPM_DATA_FIFO(chip->vendor.locality));
+ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+ status = tpm_tis_status(chip);
+ if ((status & TPM_STS_DATA_EXPECT) != 0) {
+ rc = -EIO;
+ goto out_err;
+ }
+
+ /* go and do it */
+ iowrite8(TPM_STS_GO,
+ chip->vendor.iobase + TPM_STS(chip->vendor.locality));
+
+ if (chip->vendor.irq) {
+ ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+ if (wait_for_stat
+ (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ tpm_calc_ordinal_duration(chip, ordinal),
+ &chip->vendor.read_queue) < 0) {
+ rc = -ETIME;
+ goto out_err;
+ }
+ }
+ return len;
+out_err:
+ tpm_tis_ready(chip);
+ release_locality(chip, chip->vendor.locality, 0);
+ return rc;
+}
+
+static struct file_operations tis_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tpm_open,
+ .read = tpm_read,
+ .write = tpm_write,
+ .release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
+ NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute *tis_attrs[] = {
+ &dev_attr_pubek.attr,
+ &dev_attr_pcrs.attr,
+ &dev_attr_enabled.attr,
+ &dev_attr_active.attr,
+ &dev_attr_owned.attr,
+ &dev_attr_temp_deactivated.attr,
+ &dev_attr_caps.attr,
+ &dev_attr_cancel.attr, NULL,
+};
+
+static struct attribute_group tis_attr_grp = {
+ .attrs = tis_attrs
+};
+
+static struct tpm_vendor_specific tpm_tis = {
+ .status = tpm_tis_status,
+ .recv = tpm_tis_recv,
+ .send = tpm_tis_send,
+ .cancel = tpm_tis_ready,
+ .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ .req_canceled = TPM_STS_COMMAND_READY,
+ .attr_group = &tis_attr_grp,
+ .miscdev = {
+ .fops = &tis_ops,},
+};
+
+static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct tpm_chip *chip = (struct tpm_chip *) dev_id;
+ u32 interrupt;
+
+ interrupt = ioread32(chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+
+ if (interrupt == 0)
+ return IRQ_NONE;
+
+ chip->vendor.irq = irq;
+
+ /* Clear interrupts handled with TPM_EOI */
+ iowrite32(interrupt,
+ chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct tpm_chip *chip = (struct tpm_chip *) dev_id;
+ u32 interrupt;
+ int i;
+
+ interrupt = ioread32(chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+
+ if (interrupt == 0)
+ return IRQ_NONE;
+
+ if (interrupt & TPM_INTF_DATA_AVAIL_INT)
+ wake_up_interruptible(&chip->vendor.read_queue);
+ if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
+ for (i = 0; i < 5; i++)
+ if (check_locality(chip, i) >= 0)
+ break;
+ if (interrupt &
+ (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
+ TPM_INTF_CMD_READY_INT))
+ wake_up_interruptible(&chip->vendor.int_queue);
+
+ /* Clear interrupts handled with TPM_EOI */
+ iowrite32(interrupt,
+ chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+ return IRQ_HANDLED;
+}
+
+static int interrupts = 1;
+module_param(interrupts, bool, 0444);
+MODULE_PARM_DESC(interrupts, "Enable interrupts");
+
+static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
+ const struct pnp_device_id *pnp_id)
+{
+ u32 vendor, intfcaps, intmask;
+ int rc, i;
+ unsigned long start, len;
+ struct tpm_chip *chip;
+
+ start = pnp_mem_start(pnp_dev, 0);
+ len = pnp_mem_len(pnp_dev, 0);
+
+ if (!start)
+ start = TIS_MEM_BASE;
+ if (!len)
+ len = TIS_MEM_LEN;
+
+ if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis)))
+ return -ENODEV;
+
+ chip->vendor.iobase = ioremap(start, len);
+ if (!chip->vendor.iobase) {
+ rc = -EIO;
+ goto out_err;
+ }
+
+ vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
+
+ /* Default timeouts */
+ chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+ chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+ dev_info(&pnp_dev->dev,
+ "1.2 TPM (device-id 0x%X, rev-id %d)\n",
+ vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
+
+ /* Figure out the capabilities */
+ intfcaps =
+ ioread32(chip->vendor.iobase +
+ TPM_INTF_CAPS(chip->vendor.locality));
+ dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n",
+ intfcaps);
+ if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
+ dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n");
+ if (intfcaps & TPM_INTF_CMD_READY_INT)
+ dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n");
+ if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
+ dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n");
+ if (intfcaps & TPM_INTF_INT_EDGE_RISING)
+ dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n");
+ if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
+ dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n");
+ if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
+ dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n");
+ if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
+ dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n");
+ if (intfcaps & TPM_INTF_STS_VALID_INT)
+ dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n");
+ if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
+ dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n");
+
+ if (request_locality(chip, 0) != 0) {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ /* INTERRUPT Setup */
+ init_waitqueue_head(&chip->vendor.read_queue);
+ init_waitqueue_head(&chip->vendor.int_queue);
+
+ intmask =
+ ioread32(chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+
+ intmask |= TPM_INTF_CMD_READY_INT
+ | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
+ | TPM_INTF_STS_VALID_INT;
+
+ iowrite32(intmask,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ if (interrupts) {
+ chip->vendor.irq =
+ ioread8(chip->vendor.iobase +
+ TPM_INT_VECTOR(chip->vendor.locality));
+
+ for (i = 3; i < 16 && chip->vendor.irq == 0; i++) {
+ iowrite8(i, chip->vendor.iobase +
+ TPM_INT_VECTOR(chip->vendor.locality));
+ if (request_irq
+ (i, tis_int_probe, SA_SHIRQ,
+ chip->vendor.miscdev.name, chip) != 0) {
+ dev_info(chip->dev,
+ "Unable to request irq: %d for probe\n",
+ i);
+ continue;
+ }
+
+ /* Clear all existing */
+ iowrite32(ioread32
+ (chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality)),
+ chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+
+ /* Turn on */
+ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+
+ /* Generate Interrupts */
+ tpm_gen_interrupt(chip);
+
+ /* Turn off */
+ iowrite32(intmask,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ free_irq(i, chip);
+ }
+ }
+ if (chip->vendor.irq) {
+ iowrite8(chip->vendor.irq,
+ chip->vendor.iobase +
+ TPM_INT_VECTOR(chip->vendor.locality));
+ if (request_irq
+ (chip->vendor.irq, tis_int_handler, SA_SHIRQ,
+ chip->vendor.miscdev.name, chip) != 0) {
+ dev_info(chip->dev,
+ "Unable to request irq: %d for use\n",
+ chip->vendor.irq);
+ chip->vendor.irq = 0;
+ } else {
+ /* Clear all existing */
+ iowrite32(ioread32
+ (chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality)),
+ chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+
+ /* Turn on */
+ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ }
+ }
+
+ INIT_LIST_HEAD(&chip->vendor.list);
+ spin_lock(&tis_lock);
+ list_add(&chip->vendor.list, &tis_chips);
+ spin_unlock(&tis_lock);
+
+ tpm_get_timeouts(chip);
+ tpm_continue_selftest(chip);
+
+ return 0;
+out_err:
+ if (chip->vendor.iobase)
+ iounmap(chip->vendor.iobase);
+ tpm_remove_hardware(chip->dev);
+ return rc;
+}
+
+static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
+{
+ return tpm_pm_suspend(&dev->dev, msg);
+}
+
+static int tpm_tis_pnp_resume(struct pnp_dev *dev)
+{
+ return tpm_pm_resume(&dev->dev);
+}
+
+static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
+ {"PNP0C31", 0}, /* TPM */
+ {"ATM1200", 0}, /* Atmel */
+ {"IFX0102", 0}, /* Infineon */
+ {"BCM0101", 0}, /* Broadcom */
+ {"NSC1200", 0}, /* National */
+ /* Add new here */
+ {"", 0}, /* User Specified */
+ {"", 0} /* Terminator */
+};
+
+static struct pnp_driver tis_pnp_driver = {
+ .name = "tpm_tis",
+ .id_table = tpm_pnp_tbl,
+ .probe = tpm_tis_pnp_init,
+ .suspend = tpm_tis_pnp_suspend,
+ .resume = tpm_tis_pnp_resume,
+};
+
+#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
+module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
+ sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
+MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
+
+static int __init init_tis(void)
+{
+ return pnp_register_driver(&tis_pnp_driver);
+}
+
+static void __exit cleanup_tis(void)
+{
+ struct tpm_vendor_specific *i, *j;
+ struct tpm_chip *chip;
+ spin_lock(&tis_lock);
+ list_for_each_entry_safe(i, j, &tis_chips, list) {
+ chip = to_tpm_chip(i);
+ iowrite32(~TPM_GLOBAL_INT_ENABLE &
+ ioread32(chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.
+ locality)),
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ release_locality(chip, chip->vendor.locality, 1);
+ if (chip->vendor.irq)
+ free_irq(chip->vendor.irq, chip);
+ iounmap(i->iobase);
+ list_del(&i->list);
+ tpm_remove_hardware(chip->dev);
+ }
+ spin_unlock(&tis_lock);
+ pnp_unregister_driver(&tis_pnp_driver);
+}
+
+module_init(init_tis);
+module_exit(cleanup_tis);
+MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 811dadb9ce3..a88b94a82b1 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -351,10 +351,10 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size)
spin_unlock_irqrestore(&tty->buf.lock, flags);
return size;
}
-
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
-int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size)
+int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
+ size_t size)
{
int copied = 0;
do {
@@ -368,17 +368,16 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, s
tb->used += space;
copied += space;
chars += space;
-/* printk("Flip insert %d.\n", space); */
}
/* There is a small chance that we need to split the data over
several buffers. If this is the case we must loop */
while (unlikely(size > copied));
return copied;
}
+EXPORT_SYMBOL(tty_insert_flip_string);
-EXPORT_SYMBOL_GPL(tty_insert_flip_string);
-
-int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size)
+int tty_insert_flip_string_flags(struct tty_struct *tty,
+ const unsigned char *chars, const char *flags, size_t size)
{
int copied = 0;
do {
@@ -399,9 +398,20 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *ch
while (unlikely(size > copied));
return copied;
}
+EXPORT_SYMBOL(tty_insert_flip_string_flags);
-EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags);
-
+void tty_schedule_flip(struct tty_struct *tty)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&tty->buf.lock, flags);
+ if (tty->buf.tail != NULL) {
+ tty->buf.tail->active = 0;
+ tty->buf.tail->commit = tty->buf.tail->used;
+ }
+ spin_unlock_irqrestore(&tty->buf.lock, flags);
+ schedule_delayed_work(&tty->buf.work, 1);
+}
+EXPORT_SYMBOL(tty_schedule_flip);
/*
* Prepare a block of space in the buffer for data. Returns the length
@@ -1094,8 +1104,8 @@ static void do_tty_hangup(void *data)
p->signal->tty = NULL;
if (!p->signal->leader)
continue;
- send_group_sig_info(SIGHUP, SEND_SIG_PRIV, p);
- send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p);
+ group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
+ group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
if (tty->pgrp > 0)
p->signal->tty_old_pgrp = tty->pgrp;
} while_each_task_pid(tty->session, PIDTYPE_SID, p);
@@ -1730,7 +1740,7 @@ static void release_dev(struct file * filp)
{
struct tty_struct *tty, *o_tty;
int pty_master, tty_closing, o_tty_closing, do_sleep;
- int devpts_master, devpts;
+ int devpts;
int idx;
char buf[64];
unsigned long flags;
@@ -1747,7 +1757,6 @@ static void release_dev(struct file * filp)
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER);
devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
- devpts_master = pty_master && devpts;
o_tty = tty->link;
#ifdef TTY_PARANOIA_CHECK
@@ -2185,6 +2194,7 @@ static int ptmx_open(struct inode * inode, struct file * filp)
return 0;
out1:
release_dev(filp);
+ return retval;
out:
down(&allocated_ptys_lock);
idr_remove(&allocated_ptys, index);
@@ -2672,7 +2682,7 @@ static void __do_SAK(void *arg)
tty_hangup(tty);
#else
struct tty_struct *tty = arg;
- struct task_struct *p;
+ struct task_struct *g, *p;
int session;
int i;
struct file *filp;
@@ -2693,8 +2703,18 @@ static void __do_SAK(void *arg)
tty->driver->flush_buffer(tty);
read_lock(&tasklist_lock);
+ /* Kill the entire session */
do_each_task_pid(session, PIDTYPE_SID, p) {
- if (p->signal->tty == tty || session > 0) {
+ printk(KERN_NOTICE "SAK: killed process %d"
+ " (%s): p->signal->session==tty->session\n",
+ p->pid, p->comm);
+ send_sig(SIGKILL, p, 1);
+ } while_each_task_pid(session, PIDTYPE_SID, p);
+ /* Now kill any processes that happen to have the
+ * tty open.
+ */
+ do_each_thread(g, p) {
+ if (p->signal->tty == tty) {
printk(KERN_NOTICE "SAK: killed process %d"
" (%s): p->signal->session==tty->session\n",
p->pid, p->comm);
@@ -2703,7 +2723,11 @@ static void __do_SAK(void *arg)
}
task_lock(p);
if (p->files) {
- rcu_read_lock();
+ /*
+ * We don't take a ref to the file, so we must
+ * hold ->file_lock instead.
+ */
+ spin_lock(&p->files->file_lock);
fdt = files_fdtable(p->files);
for (i=0; i < fdt->max_fds; i++) {
filp = fcheck_files(p->files, i);
@@ -2714,14 +2738,14 @@ static void __do_SAK(void *arg)
printk(KERN_NOTICE "SAK: killed process %d"
" (%s): fd#%d opened to the tty\n",
p->pid, p->comm, i);
- send_sig(SIGKILL, p, 1);
+ force_sig(SIGKILL, p);
break;
}
}
- rcu_read_unlock();
+ spin_unlock(&p->files->file_lock);
}
task_unlock(p);
- } while_each_task_pid(session, PIDTYPE_SID, p);
+ } while_each_thread(g, p);
read_unlock(&tasklist_lock);
#endif
}
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index ca4844c527d..6c94879e0b9 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2328,6 +2328,10 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
case TIOCL_SETVESABLANK:
set_vesa_blanking(p);
break;
+ case TIOCL_GETKMSGREDIRECT:
+ data = kmsg_redirect;
+ ret = __put_user(data, p);
+ break;
case TIOCL_SETKMSGREDIRECT:
if (!capable(CAP_SYS_ADMIN)) {
ret = -EPERM;
@@ -3234,14 +3238,6 @@ void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org)
}
}
-int is_console_suspend_safe(void)
-{
- /* It is unsafe to suspend devices while X has control of the
- * hardware. Make sure we are running on a kernel-controlled console.
- */
- return vc_cons[fg_console].d->vc_mode == KD_TEXT;
-}
-
/*
* Visible symbols for modules
*/
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 16e99db2e12..d53f664a4dd 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -60,6 +60,13 @@ config SOFT_WATCHDOG
# ARM Architecture
+config AT91_WATCHDOG
+ tristate "AT91RM9200 watchdog"
+ depends on WATCHDOG && ARCH_AT91RM9200
+ help
+ Watchdog timer embedded into AT91RM9200 chips. This will reboot your
+ system when the timeout is reached.
+
config 21285_WATCHDOG
tristate "DC21285 watchdog"
depends on WATCHDOG && FOOTBRIDGE
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index d6f27fde990..6ab77b61a64 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o
obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
# ARM Architecture
+obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o
obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
obj-$(CONFIG_977_WATCHDOG) += wdt977.o
obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
diff --git a/drivers/char/watchdog/at91_wdt.c b/drivers/char/watchdog/at91_wdt.c
new file mode 100644
index 00000000000..ac83bc4b019
--- /dev/null
+++ b/drivers/char/watchdog/at91_wdt.c
@@ -0,0 +1,228 @@
+/*
+ * Watchdog driver for Atmel AT91RM9200 (Thunder)
+ *
+ * Copyright (C) 2003 SAN People (Pty) Ltd
+ *
+ * This program is free software; 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/config.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+
+#define WDT_DEFAULT_TIME 5 /* 5 seconds */
+#define WDT_MAX_TIME 256 /* 256 seconds */
+
+static int wdt_time = WDT_DEFAULT_TIME;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(wdt_time, int, 0);
+MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+
+static unsigned long at91wdt_busy;
+
+/* ......................................................................... */
+
+/*
+ * Disable the watchdog.
+ */
+static void inline at91_wdt_stop(void)
+{
+ at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN);
+}
+
+/*
+ * Enable and reset the watchdog.
+ */
+static void inline at91_wdt_start(void)
+{
+ at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV));
+ at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+/*
+ * Reload the watchdog timer. (ie, pat the watchdog)
+ */
+static void inline at91_wdt_reload(void)
+{
+ at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+/* ......................................................................... */
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int at91_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(0, &at91wdt_busy))
+ return -EBUSY;
+
+ at91_wdt_start();
+ return nonseekable_open(inode, file);
+}
+
+/*
+ * Close the watchdog device.
+ * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also
+ * disabled.
+ */
+static int at91_wdt_close(struct inode *inode, struct file *file)
+{
+ if (!nowayout)
+ at91_wdt_stop(); /* Disable the watchdog when file is closed */
+
+ clear_bit(0, &at91wdt_busy);
+ return 0;
+}
+
+/*
+ * Change the watchdog time interval.
+ */
+static int at91_wdt_settimeout(int new_time)
+{
+ /*
+ * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
+ *
+ * Since WDV is a 16-bit counter, the maximum period is
+ * 65536 / 0.256 = 256 seconds.
+ */
+ if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
+ return -EINVAL;
+
+ /* Set new watchdog time. It will be used when at91_wdt_start() is called. */
+ wdt_time = new_time;
+ return 0;
+}
+
+static struct watchdog_info at91_wdt_info = {
+ .identity = "at91 watchdog",
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+};
+
+/*
+ * Handle commands from user-space.
+ */
+static int at91_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int new_value;
+
+ switch(cmd) {
+ case WDIOC_KEEPALIVE:
+ at91_wdt_reload(); /* pat the watchdog */
+ return 0;
+
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_value, p))
+ return -EFAULT;
+
+ if (at91_wdt_settimeout(new_value))
+ return -EINVAL;
+
+ /* Enable new time value */
+ at91_wdt_start();
+
+ /* Return current value */
+ return put_user(wdt_time, p);
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(wdt_time, p);
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+
+ case WDIOC_SETOPTIONS:
+ if (get_user(new_value, p))
+ return -EFAULT;
+
+ if (new_value & WDIOS_DISABLECARD)
+ at91_wdt_stop();
+ if (new_value & WDIOS_ENABLECARD)
+ at91_wdt_start();
+ return 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+/*
+ * Pat the watchdog whenever device is written to.
+ */
+static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+ at91_wdt_reload(); /* pat the watchdog */
+ return len;
+}
+
+/* ......................................................................... */
+
+static struct file_operations at91wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .ioctl = at91_wdt_ioctl,
+ .open = at91_wdt_open,
+ .release = at91_wdt_close,
+ .write = at91_wdt_write,
+};
+
+static struct miscdevice at91wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &at91wdt_fops,
+};
+
+static int __init at91_wdt_init(void)
+{
+ int res;
+
+ /* Check that the heartbeat value is within range; if not reset to the default */
+ if (at91_wdt_settimeout(wdt_time)) {
+ at91_wdt_settimeout(WDT_DEFAULT_TIME);
+ printk(KERN_INFO "at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time);
+ }
+
+ res = misc_register(&at91wdt_miscdev);
+ if (res)
+ return res;
+
+ printk("AT91 Watchdog Timer enabled (%d seconds, nowayout=%d)\n", wdt_time, nowayout);
+ return 0;
+}
+
+static void __exit at91_wdt_exit(void)
+{
+ misc_deregister(&at91wdt_miscdev);
+}
+
+module_init(at91_wdt_init);
+module_exit(at91_wdt_exit);
+
+MODULE_AUTHOR("Andrew Victor");
+MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c
index a13395e2c37..fa2ba9ebe42 100644
--- a/drivers/char/watchdog/i8xx_tco.c
+++ b/drivers/char/watchdog/i8xx_tco.c
@@ -33,11 +33,6 @@
* 82801E (C-ICH) : document number 273599-001, 273645-002,
* 82801EB (ICH5) : document number 252516-001, 252517-003,
* 82801ER (ICH5R) : document number 252516-001, 252517-003,
- * 82801FB (ICH6) : document number 301473-002, 301474-007,
- * 82801FR (ICH6R) : document number 301473-002, 301474-007,
- * 82801FBM (ICH6-M) : document number 301473-002, 301474-007,
- * 82801FW (ICH6W) : document number 301473-001, 301474-007,
- * 82801FRW (ICH6RW) : document number 301473-001, 301474-007
*
* 20000710 Nils Faerber
* Initial Version 0.01
@@ -66,6 +61,10 @@
* 20050807 Wim Van Sebroeck <wim@iguana.be>
* 0.08 Make sure that the watchdog is only "armed" when started.
* (Kernel Bug 4251)
+ * 20060416 Wim Van Sebroeck <wim@iguana.be>
+ * 0.09 Remove support for the ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW and
+ * ICH7 chipsets. (See Kernel Bug 6031 - other code will support these
+ * chipsets)
*/
/*
@@ -90,7 +89,7 @@
#include "i8xx_tco.h"
/* Module and version information */
-#define TCO_VERSION "0.08"
+#define TCO_VERSION "0.09"
#define TCO_MODULE_NAME "i8xx TCO timer"
#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION
#define PFX TCO_MODULE_NAME ": "
@@ -391,11 +390,6 @@ static struct pci_device_id i8xx_tco_pci_tbl[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, },
{ 0, }, /* End of list */
};
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 8d6b249ad66..6d44ca68312 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -66,15 +66,13 @@
#include <linux/fs.h> /* For file operations */
#include <linux/ioport.h> /* For io-port access */
#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
-#include <linux/sched.h> /* TASK_INTERRUPTIBLE, set_current_state() and friends */
-#include <linux/slab.h> /* For kmalloc */
#include <asm/uaccess.h> /* For copy_to_user/put_user/... */
#include <asm/io.h> /* For inb/outb/... */
/* Module and version information */
-#define WATCHDOG_VERSION "1.16"
-#define WATCHDOG_DATE "03 Jan 2006"
+#define WATCHDOG_VERSION "1.17"
+#define WATCHDOG_DATE "12 Feb 2006"
#define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
#define WATCHDOG_NAME "pcwd"
#define PFX WATCHDOG_NAME ": "
@@ -96,15 +94,19 @@
* PCI-PC Watchdog card.
*/
/* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */
-#define WD_WDRST 0x01 /* Previously reset state */
-#define WD_T110 0x02 /* Temperature overheat sense */
-#define WD_HRTBT 0x04 /* Heartbeat sense */
-#define WD_RLY2 0x08 /* External relay triggered */
-#define WD_SRLY2 0x80 /* Software external relay triggered */
+#define WD_WDRST 0x01 /* Previously reset state */
+#define WD_T110 0x02 /* Temperature overheat sense */
+#define WD_HRTBT 0x04 /* Heartbeat sense */
+#define WD_RLY2 0x08 /* External relay triggered */
+#define WD_SRLY2 0x80 /* Software external relay triggered */
/* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */
-#define WD_REVC_WTRP 0x01 /* Watchdog Trip status */
-#define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */
-#define WD_REVC_TTRP 0x04 /* Temperature Trip status */
+#define WD_REVC_WTRP 0x01 /* Watchdog Trip status */
+#define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */
+#define WD_REVC_TTRP 0x04 /* Temperature Trip status */
+#define WD_REVC_RL2A 0x08 /* Relay 2 activated by on-board processor */
+#define WD_REVC_RL1A 0x10 /* Relay 1 active */
+#define WD_REVC_R2DS 0x40 /* Relay 2 disable */
+#define WD_REVC_RLY2 0x80 /* Relay 2 activated? */
/* Port 2 : Control Status #2 */
#define WD_WDIS 0x10 /* Watchdog Disabled */
#define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */
@@ -122,9 +124,14 @@
#define CMD_ISA_VERSION_HUNDRETH 0x03
#define CMD_ISA_VERSION_MINOR 0x04
#define CMD_ISA_SWITCH_SETTINGS 0x05
+#define CMD_ISA_RESET_PC 0x06
+#define CMD_ISA_ARM_0 0x07
+#define CMD_ISA_ARM_30 0x08
+#define CMD_ISA_ARM_60 0x09
#define CMD_ISA_DELAY_TIME_2SECS 0x0A
#define CMD_ISA_DELAY_TIME_4SECS 0x0B
#define CMD_ISA_DELAY_TIME_8SECS 0x0C
+#define CMD_ISA_RESET_RELAYS 0x0D
/*
* We are using an kernel timer to do the pinging of the watchdog
@@ -142,6 +149,7 @@ static atomic_t open_allowed = ATOMIC_INIT(1);
static char expect_close;
static int temp_panic;
static struct { /* this is private data for each ISA-PC watchdog card */
+ char fw_ver_str[6]; /* The cards firmware version */
int revision; /* The card's revision */
int supports_temp; /* Wether or not the card has a temperature device */
int command_mode; /* Wether or not the card is in command mode */
@@ -153,6 +161,13 @@ static struct { /* this is private data for each ISA-PC watchdog card */
} pcwd_private;
/* module parameters */
+#define QUIET 0 /* Default */
+#define VERBOSE 1 /* Verbose */
+#define DEBUG 2 /* print fancy stuff too */
+static int debug = QUIET;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
+
#define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */
static int heartbeat = WATCHDOG_HEARTBEAT;
module_param(heartbeat, int, 0);
@@ -172,6 +187,10 @@ static int send_isa_command(int cmd)
int control_status;
int port0, last_port0; /* Double read for stabilising */
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "sending following data cmd=0x%02x\n",
+ cmd);
+
/* The WCMD bit must be 1 and the command is only 4 bits in size */
control_status = (cmd & 0x0F) | WD_WCMD;
outb_p(control_status, pcwd_private.io_addr + 2);
@@ -188,6 +207,10 @@ static int send_isa_command(int cmd)
udelay (250);
}
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n",
+ cmd, port0, last_port0);
+
return port0;
}
@@ -214,6 +237,10 @@ static int set_command_mode(void)
spin_unlock(&pcwd_private.io_lock);
pcwd_private.command_mode = found;
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "command_mode=%d\n",
+ pcwd_private.command_mode);
+
return(found);
}
@@ -226,6 +253,10 @@ static void unset_command_mode(void)
spin_unlock(&pcwd_private.io_lock);
pcwd_private.command_mode = 0;
+
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "command_mode=%d\n",
+ pcwd_private.command_mode);
}
static inline void pcwd_check_temperature_support(void)
@@ -234,27 +265,22 @@ static inline void pcwd_check_temperature_support(void)
pcwd_private.supports_temp = 1;
}
-static inline char *get_firmware(void)
+static inline void pcwd_get_firmware(void)
{
int one, ten, hund, minor;
- char *ret;
- ret = kmalloc(6, GFP_KERNEL);
- if(ret == NULL)
- return NULL;
+ strcpy(pcwd_private.fw_ver_str, "ERROR");
if (set_command_mode()) {
one = send_isa_command(CMD_ISA_VERSION_INTEGER);
ten = send_isa_command(CMD_ISA_VERSION_TENTH);
hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
minor = send_isa_command(CMD_ISA_VERSION_MINOR);
- sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
+ sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c", one, ten, hund, minor);
}
- else
- sprintf(ret, "ERROR");
-
unset_command_mode();
- return(ret);
+
+ return;
}
static inline int pcwd_get_option_switches(void)
@@ -272,17 +298,15 @@ static inline int pcwd_get_option_switches(void)
static void pcwd_show_card_info(void)
{
- char *firmware;
int option_switches;
/* Get some extra info from the hardware (in command/debug/diag mode) */
if (pcwd_private.revision == PCWD_REVISION_A)
printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr);
else if (pcwd_private.revision == PCWD_REVISION_C) {
- firmware = get_firmware();
+ pcwd_get_firmware();
printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
- pcwd_private.io_addr, firmware);
- kfree(firmware);
+ pcwd_private.io_addr, pcwd_private.fw_ver_str);
option_switches = pcwd_get_option_switches();
printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
option_switches,
@@ -362,6 +386,10 @@ static int pcwd_start(void)
return -EIO;
}
}
+
+ if (debug >= VERBOSE)
+ printk(KERN_DEBUG PFX "Watchdog started\n");
+
return 0;
}
@@ -386,6 +414,10 @@ static int pcwd_stop(void)
return -EIO;
}
}
+
+ if (debug >= VERBOSE)
+ printk(KERN_DEBUG PFX "Watchdog stopped\n");
+
return 0;
}
@@ -393,6 +425,10 @@ static int pcwd_keepalive(void)
{
/* user land ping */
pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
+
+ if (debug >= DEBUG)
+ printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
+
return 0;
}
@@ -402,12 +438,17 @@ static int pcwd_set_heartbeat(int t)
return -EINVAL;
heartbeat = t;
+
+ if (debug >= VERBOSE)
+ printk(KERN_DEBUG PFX "New heartbeat: %d\n",
+ heartbeat);
+
return 0;
}
static int pcwd_get_status(int *status)
{
- int card_status;
+ int control_status;
*status=0;
spin_lock(&pcwd_private.io_lock);
@@ -415,37 +456,39 @@ static int pcwd_get_status(int *status)
/* Rev A cards return status information from
* the base register, which is used for the
* temperature in other cards. */
- card_status = inb(pcwd_private.io_addr);
+ control_status = inb(pcwd_private.io_addr);
else {
/* Rev C cards return card status in the base
* address + 1 register. And use different bits
* to indicate a card initiated reset, and an
* over-temperature condition. And the reboot
* status can be reset. */
- card_status = inb(pcwd_private.io_addr + 1);
+ control_status = inb(pcwd_private.io_addr + 1);
}
spin_unlock(&pcwd_private.io_lock);
if (pcwd_private.revision == PCWD_REVISION_A) {
- if (card_status & WD_WDRST)
+ if (control_status & WD_WDRST)
*status |= WDIOF_CARDRESET;
- if (card_status & WD_T110) {
+ if (control_status & WD_T110) {
*status |= WDIOF_OVERHEAT;
if (temp_panic) {
printk (KERN_INFO PFX "Temperature overheat trip!\n");
kernel_power_off();
+ /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
}
}
} else {
- if (card_status & WD_REVC_WTRP)
+ if (control_status & WD_REVC_WTRP)
*status |= WDIOF_CARDRESET;
- if (card_status & WD_REVC_TTRP) {
+ if (control_status & WD_REVC_TTRP) {
*status |= WDIOF_OVERHEAT;
if (temp_panic) {
printk (KERN_INFO PFX "Temperature overheat trip!\n");
kernel_power_off();
+ /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
}
}
}
@@ -455,9 +498,25 @@ static int pcwd_get_status(int *status)
static int pcwd_clear_status(void)
{
+ int control_status;
+
if (pcwd_private.revision == PCWD_REVISION_C) {
spin_lock(&pcwd_private.io_lock);
- outb_p(0x00, pcwd_private.io_addr + 1); /* clear reset status */
+
+ if (debug >= VERBOSE)
+ printk(KERN_INFO PFX "clearing watchdog trip status\n");
+
+ control_status = inb_p(pcwd_private.io_addr + 1);
+
+ if (debug >= DEBUG) {
+ printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status);
+ printk(KERN_DEBUG PFX "sending: 0x%02x\n",
+ (control_status & WD_REVC_R2DS));
+ }
+
+ /* clear reset status & Keep Relay 2 disable state as it is */
+ outb_p((control_status & WD_REVC_R2DS), pcwd_private.io_addr + 1);
+
spin_unlock(&pcwd_private.io_lock);
}
return 0;
@@ -481,6 +540,11 @@ static int pcwd_get_temperature(int *temperature)
*temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32;
spin_unlock(&pcwd_private.io_lock);
+ if (debug >= DEBUG) {
+ printk(KERN_DEBUG PFX "temperature is: %d F\n",
+ *temperature);
+ }
+
return 0;
}
@@ -599,6 +663,8 @@ static ssize_t pcwd_write(struct file *file, const char __user *buf, size_t len,
static int pcwd_open(struct inode *inode, struct file *file)
{
if (!atomic_dec_and_test(&open_allowed) ) {
+ if (debug >= VERBOSE)
+ printk(KERN_ERR PFX "Attempt to open already opened device.\n");
atomic_inc( &open_allowed );
return -EBUSY;
}
@@ -922,7 +988,8 @@ static void __exit pcwd_cleanup_module(void)
{
if (pcwd_private.io_addr)
pcwatchdog_exit();
- return;
+
+ printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
}
module_init(pcwd_init_module);
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 2700c5c45b8..3fdfda9324f 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -705,7 +705,8 @@ err_out_misc_deregister:
err_out_unregister_reboot:
unregister_reboot_notifier(&usb_pcwd_notifier);
error:
- usb_pcwd_delete (usb_pcwd);
+ if (usb_pcwd)
+ usb_pcwd_delete(usb_pcwd);
usb_pcwd_device = NULL;
return retval;
}
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 9dc54736e4e..1ea04e9b2b0 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -423,6 +423,12 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
if (tmr_atboot && started == 0) {
printk(KERN_INFO PFX "Starting Watchdog Timer\n");
s3c2410wdt_start();
+ } else if (!tmr_atboot) {
+ /* if we're not enabling the watchdog, then ensure it is
+ * disabled if it has been left running from the bootloader
+ * or other source */
+
+ s3c2410wdt_stop();
}
return 0;
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c
index 515ce757204..20b88f9b7be 100644
--- a/drivers/char/watchdog/sc1200wdt.c
+++ b/drivers/char/watchdog/sc1200wdt.c
@@ -377,7 +377,7 @@ static int __init sc1200wdt_init(void)
{
int ret;
- printk(banner);
+ printk("%s\n", banner);
spin_lock_init(&sc1200wdt_lock);
sema_init(&open_sem, 1);
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 60c9be99c6d..2cc71b66231 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -99,7 +99,7 @@ config CPU_FREQ_GOV_USERSPACE
Enable this cpufreq governor when you either want to set the
CPU frequency manually or when an userspace program shall
be able to set the CPU dynamically, like on LART
- <http://www.lart.tudelft.nl/>
+ <http://www.lartmaker.nl/>.
For details, take a look at <file:Documentation/cpu-freq/>.
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index aed80e6aec6..29b2fa5534a 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -52,9 +52,8 @@ static void handle_update(void *data);
* changes to devices when the CPU clock speed changes.
* The mutex locks both lists.
*/
-static struct notifier_block *cpufreq_policy_notifier_list;
-static struct notifier_block *cpufreq_transition_notifier_list;
-static DECLARE_RWSEM (cpufreq_notifier_rwsem);
+static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
+static BLOCKING_NOTIFIER_HEAD(cpufreq_transition_notifier_list);
static LIST_HEAD(cpufreq_governor_list);
@@ -247,8 +246,6 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
dprintk("notification %u of frequency transition to %u kHz\n",
state, freqs->new);
- down_read(&cpufreq_notifier_rwsem);
-
policy = cpufreq_cpu_data[freqs->cpu];
switch (state) {
@@ -266,20 +263,19 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
freqs->old = policy->cur;
}
}
- notifier_call_chain(&cpufreq_transition_notifier_list,
- CPUFREQ_PRECHANGE, freqs);
+ blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
+ CPUFREQ_PRECHANGE, freqs);
adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
break;
case CPUFREQ_POSTCHANGE:
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
- notifier_call_chain(&cpufreq_transition_notifier_list,
- CPUFREQ_POSTCHANGE, freqs);
+ blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
+ CPUFREQ_POSTCHANGE, freqs);
if (likely(policy) && likely(policy->cpu == freqs->cpu))
policy->cur = freqs->new;
break;
}
- up_read(&cpufreq_notifier_rwsem);
}
EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
@@ -323,7 +319,6 @@ out:
}
return -EINVAL;
}
-EXPORT_SYMBOL_GPL(cpufreq_parse_governor);
/* drivers/base/cpu.c */
@@ -350,6 +345,8 @@ show_one(scaling_min_freq, min);
show_one(scaling_max_freq, max);
show_one(scaling_cur_freq, cur);
+static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy);
+
/**
* cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
*/
@@ -368,7 +365,10 @@ static ssize_t store_##file_name \
if (ret != 1) \
return -EINVAL; \
\
- ret = cpufreq_set_policy(&new_policy); \
+ mutex_lock(&policy->lock); \
+ ret = __cpufreq_set_policy(policy, &new_policy); \
+ policy->user_policy.object = policy->object; \
+ mutex_unlock(&policy->lock); \
\
return ret ? ret : count; \
}
@@ -424,7 +424,15 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor))
return -EINVAL;
- ret = cpufreq_set_policy(&new_policy);
+ /* Do not use cpufreq_set_policy here or the user_policy.max
+ will be wrongly overridden */
+ mutex_lock(&policy->lock);
+ ret = __cpufreq_set_policy(policy, &new_policy);
+
+ policy->user_policy.policy = policy->policy;
+ policy->user_policy.governor = policy->governor;
+ mutex_unlock(&policy->lock);
+
return ret ? ret : count;
}
@@ -689,7 +697,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
if (!cpu_online(j))
continue;
- dprintk("CPU already managed, adding link\n");
+ dprintk("CPU %u already managed, adding link\n", j);
cpufreq_cpu_get(cpu);
cpu_sys_dev = get_cpu_sysdev(j);
sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
@@ -699,9 +707,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
policy->governor = NULL; /* to assure that the starting sequence is
* run in cpufreq_set_policy */
mutex_unlock(&policy->lock);
-
+
/* set default policy */
-
ret = cpufreq_set_policy(&new_policy);
if (ret) {
dprintk("setting policy failed\n");
@@ -711,7 +718,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
module_put(cpufreq_driver->owner);
dprintk("initialization complete\n");
cpufreq_debug_enable_ratelimit();
-
+
return 0;
@@ -1007,7 +1014,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
freqs.old = cpu_policy->cur;
freqs.new = cur_freq;
- notifier_call_chain(&cpufreq_transition_notifier_list,
+ blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
CPUFREQ_SUSPENDCHANGE, &freqs);
adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs);
@@ -1088,7 +1095,8 @@ static int cpufreq_resume(struct sys_device * sysdev)
freqs.old = cpu_policy->cur;
freqs.new = cur_freq;
- notifier_call_chain(&cpufreq_transition_notifier_list,
+ blocking_notifier_call_chain(
+ &cpufreq_transition_notifier_list,
CPUFREQ_RESUMECHANGE, &freqs);
adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs);
@@ -1125,24 +1133,24 @@ static struct sysdev_driver cpufreq_sysdev_driver = {
* changes in cpufreq policy.
*
* This function may sleep, and has the same return conditions as
- * notifier_chain_register.
+ * blocking_notifier_chain_register.
*/
int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
{
int ret;
- down_write(&cpufreq_notifier_rwsem);
switch (list) {
case CPUFREQ_TRANSITION_NOTIFIER:
- ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb);
+ ret = blocking_notifier_chain_register(
+ &cpufreq_transition_notifier_list, nb);
break;
case CPUFREQ_POLICY_NOTIFIER:
- ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb);
+ ret = blocking_notifier_chain_register(
+ &cpufreq_policy_notifier_list, nb);
break;
default:
ret = -EINVAL;
}
- up_write(&cpufreq_notifier_rwsem);
return ret;
}
@@ -1157,24 +1165,24 @@ EXPORT_SYMBOL(cpufreq_register_notifier);
* Remove a driver from the CPU frequency notifier list.
*
* This function may sleep, and has the same return conditions as
- * notifier_chain_unregister.
+ * blocking_notifier_chain_unregister.
*/
int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
{
int ret;
- down_write(&cpufreq_notifier_rwsem);
switch (list) {
case CPUFREQ_TRANSITION_NOTIFIER:
- ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb);
+ ret = blocking_notifier_chain_unregister(
+ &cpufreq_transition_notifier_list, nb);
break;
case CPUFREQ_POLICY_NOTIFIER:
- ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb);
+ ret = blocking_notifier_chain_unregister(
+ &cpufreq_policy_notifier_list, nb);
break;
default:
ret = -EINVAL;
}
- up_write(&cpufreq_notifier_rwsem);
return ret;
}
@@ -1346,29 +1354,23 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
if (ret)
goto error_out;
- down_read(&cpufreq_notifier_rwsem);
-
/* adjust if necessary - all reasons */
- notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST,
- policy);
+ blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+ CPUFREQ_ADJUST, policy);
/* adjust if necessary - hardware incompatibility*/
- notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE,
- policy);
+ blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+ CPUFREQ_INCOMPATIBLE, policy);
/* verify the cpu speed can be set within this limit,
which might be different to the first one */
ret = cpufreq_driver->verify(policy);
- if (ret) {
- up_read(&cpufreq_notifier_rwsem);
+ if (ret)
goto error_out;
- }
/* notification of the new policy */
- notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY,
- policy);
-
- up_read(&cpufreq_notifier_rwsem);
+ blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+ CPUFREQ_NOTIFY, policy);
data->min = policy->min;
data->max = policy->max;
@@ -1495,7 +1497,7 @@ int cpufreq_update_policy(unsigned int cpu)
}
EXPORT_SYMBOL(cpufreq_update_policy);
-static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb,
+static int cpufreq_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index ac38766b258..e07a35487bd 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -35,12 +35,7 @@
*/
#define DEF_FREQUENCY_UP_THRESHOLD (80)
-#define MIN_FREQUENCY_UP_THRESHOLD (0)
-#define MAX_FREQUENCY_UP_THRESHOLD (100)
-
#define DEF_FREQUENCY_DOWN_THRESHOLD (20)
-#define MIN_FREQUENCY_DOWN_THRESHOLD (0)
-#define MAX_FREQUENCY_DOWN_THRESHOLD (100)
/*
* The polling frequency of this governor depends on the capability of
@@ -53,10 +48,14 @@
* All times here are in uS.
*/
static unsigned int def_sampling_rate;
-#define MIN_SAMPLING_RATE (def_sampling_rate / 2)
+#define MIN_SAMPLING_RATE_RATIO (2)
+/* for correct statistics, we need at least 10 ticks between each measure */
+#define MIN_STAT_SAMPLING_RATE (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
+#define MIN_SAMPLING_RATE (def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
#define MAX_SAMPLING_RATE (500 * def_sampling_rate)
-#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (100000)
-#define DEF_SAMPLING_DOWN_FACTOR (5)
+#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000)
+#define DEF_SAMPLING_DOWN_FACTOR (1)
+#define MAX_SAMPLING_DOWN_FACTOR (10)
#define TRANSITION_LATENCY_LIMIT (10 * 1000)
static void do_dbs_timer(void *data);
@@ -66,6 +65,8 @@ struct cpu_dbs_info_s {
unsigned int prev_cpu_idle_up;
unsigned int prev_cpu_idle_down;
unsigned int enable;
+ unsigned int down_skip;
+ unsigned int requested_freq;
};
static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
@@ -87,6 +88,8 @@ static struct dbs_tuners dbs_tuners_ins = {
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
.down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
+ .ignore_nice = 0,
+ .freq_step = 5,
};
static inline unsigned int get_cpu_idle_time(unsigned int cpu)
@@ -136,7 +139,7 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
unsigned int input;
int ret;
ret = sscanf (buf, "%u", &input);
- if (ret != 1 )
+ if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
return -EINVAL;
mutex_lock(&dbs_mutex);
@@ -173,9 +176,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
ret = sscanf (buf, "%u", &input);
mutex_lock(&dbs_mutex);
- if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
- input < MIN_FREQUENCY_UP_THRESHOLD ||
- input <= dbs_tuners_ins.down_threshold) {
+ if (ret != 1 || input > 100 || input <= dbs_tuners_ins.down_threshold) {
mutex_unlock(&dbs_mutex);
return -EINVAL;
}
@@ -194,9 +195,7 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused,
ret = sscanf (buf, "%u", &input);
mutex_lock(&dbs_mutex);
- if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD ||
- input < MIN_FREQUENCY_DOWN_THRESHOLD ||
- input >= dbs_tuners_ins.up_threshold) {
+ if (ret != 1 || input > 100 || input >= dbs_tuners_ins.up_threshold) {
mutex_unlock(&dbs_mutex);
return -EINVAL;
}
@@ -297,31 +296,17 @@ static struct attribute_group dbs_attr_group = {
static void dbs_check_cpu(int cpu)
{
unsigned int idle_ticks, up_idle_ticks, down_idle_ticks;
+ unsigned int tmp_idle_ticks, total_idle_ticks;
unsigned int freq_step;
unsigned int freq_down_sampling_rate;
- static int down_skip[NR_CPUS];
- static int requested_freq[NR_CPUS];
- static unsigned short init_flag = 0;
- struct cpu_dbs_info_s *this_dbs_info;
- struct cpu_dbs_info_s *dbs_info;
-
+ struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
struct cpufreq_policy *policy;
- unsigned int j;
- this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
if (!this_dbs_info->enable)
return;
policy = this_dbs_info->cur_policy;
- if ( init_flag == 0 ) {
- for_each_online_cpu(j) {
- dbs_info = &per_cpu(cpu_dbs_info, j);
- requested_freq[j] = dbs_info->cur_policy->cur;
- }
- init_flag = 1;
- }
-
/*
* The default safe range is 20% to 80%
* Every sampling_rate, we check
@@ -337,39 +322,29 @@ static void dbs_check_cpu(int cpu)
*/
/* Check for frequency increase */
-
idle_ticks = UINT_MAX;
- for_each_cpu_mask(j, policy->cpus) {
- unsigned int tmp_idle_ticks, total_idle_ticks;
- struct cpu_dbs_info_s *j_dbs_info;
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- /* Check for frequency increase */
- total_idle_ticks = get_cpu_idle_time(j);
- tmp_idle_ticks = total_idle_ticks -
- j_dbs_info->prev_cpu_idle_up;
- j_dbs_info->prev_cpu_idle_up = total_idle_ticks;
-
- if (tmp_idle_ticks < idle_ticks)
- idle_ticks = tmp_idle_ticks;
- }
+ /* Check for frequency increase */
+ total_idle_ticks = get_cpu_idle_time(cpu);
+ tmp_idle_ticks = total_idle_ticks -
+ this_dbs_info->prev_cpu_idle_up;
+ this_dbs_info->prev_cpu_idle_up = total_idle_ticks;
+
+ if (tmp_idle_ticks < idle_ticks)
+ idle_ticks = tmp_idle_ticks;
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks *= 100;
up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) *
- usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+ usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
if (idle_ticks < up_idle_ticks) {
- down_skip[cpu] = 0;
- for_each_cpu_mask(j, policy->cpus) {
- struct cpu_dbs_info_s *j_dbs_info;
+ this_dbs_info->down_skip = 0;
+ this_dbs_info->prev_cpu_idle_down =
+ this_dbs_info->prev_cpu_idle_up;
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- j_dbs_info->prev_cpu_idle_down =
- j_dbs_info->prev_cpu_idle_up;
- }
/* if we are already at full speed then break out early */
- if (requested_freq[cpu] == policy->max)
+ if (this_dbs_info->requested_freq == policy->max)
return;
freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100;
@@ -378,49 +353,45 @@ static void dbs_check_cpu(int cpu)
if (unlikely(freq_step == 0))
freq_step = 5;
- requested_freq[cpu] += freq_step;
- if (requested_freq[cpu] > policy->max)
- requested_freq[cpu] = policy->max;
+ this_dbs_info->requested_freq += freq_step;
+ if (this_dbs_info->requested_freq > policy->max)
+ this_dbs_info->requested_freq = policy->max;
- __cpufreq_driver_target(policy, requested_freq[cpu],
+ __cpufreq_driver_target(policy, this_dbs_info->requested_freq,
CPUFREQ_RELATION_H);
return;
}
/* Check for frequency decrease */
- down_skip[cpu]++;
- if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor)
+ this_dbs_info->down_skip++;
+ if (this_dbs_info->down_skip < dbs_tuners_ins.sampling_down_factor)
return;
- idle_ticks = UINT_MAX;
- for_each_cpu_mask(j, policy->cpus) {
- unsigned int tmp_idle_ticks, total_idle_ticks;
- struct cpu_dbs_info_s *j_dbs_info;
+ /* Check for frequency decrease */
+ total_idle_ticks = this_dbs_info->prev_cpu_idle_up;
+ tmp_idle_ticks = total_idle_ticks -
+ this_dbs_info->prev_cpu_idle_down;
+ this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- total_idle_ticks = j_dbs_info->prev_cpu_idle_up;
- tmp_idle_ticks = total_idle_ticks -
- j_dbs_info->prev_cpu_idle_down;
- j_dbs_info->prev_cpu_idle_down = total_idle_ticks;
-
- if (tmp_idle_ticks < idle_ticks)
- idle_ticks = tmp_idle_ticks;
- }
+ if (tmp_idle_ticks < idle_ticks)
+ idle_ticks = tmp_idle_ticks;
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks *= 100;
- down_skip[cpu] = 0;
+ this_dbs_info->down_skip = 0;
freq_down_sampling_rate = dbs_tuners_ins.sampling_rate *
dbs_tuners_ins.sampling_down_factor;
down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) *
- usecs_to_jiffies(freq_down_sampling_rate);
+ usecs_to_jiffies(freq_down_sampling_rate);
if (idle_ticks > down_idle_ticks) {
- /* if we are already at the lowest speed then break out early
+ /*
+ * if we are already at the lowest speed then break out early
* or if we 'cannot' reduce the speed as the user might want
- * freq_step to be zero */
- if (requested_freq[cpu] == policy->min
+ * freq_step to be zero
+ */
+ if (this_dbs_info->requested_freq == policy->min
|| dbs_tuners_ins.freq_step == 0)
return;
@@ -430,13 +401,12 @@ static void dbs_check_cpu(int cpu)
if (unlikely(freq_step == 0))
freq_step = 5;
- requested_freq[cpu] -= freq_step;
- if (requested_freq[cpu] < policy->min)
- requested_freq[cpu] = policy->min;
+ this_dbs_info->requested_freq -= freq_step;
+ if (this_dbs_info->requested_freq < policy->min)
+ this_dbs_info->requested_freq = policy->min;
- __cpufreq_driver_target(policy,
- requested_freq[cpu],
- CPUFREQ_RELATION_H);
+ __cpufreq_driver_target(policy, this_dbs_info->requested_freq,
+ CPUFREQ_RELATION_H);
return;
}
}
@@ -493,11 +463,13 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
- j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
+ j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(cpu);
j_dbs_info->prev_cpu_idle_down
= j_dbs_info->prev_cpu_idle_up;
}
this_dbs_info->enable = 1;
+ this_dbs_info->down_skip = 0;
+ this_dbs_info->requested_freq = policy->cur;
sysfs_create_group(&policy->kobj, &dbs_attr_group);
dbs_enable++;
/*
@@ -507,16 +479,17 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
if (dbs_enable == 1) {
unsigned int latency;
/* policy latency is in nS. Convert it to uS first */
+ latency = policy->cpuinfo.transition_latency / 1000;
+ if (latency == 0)
+ latency = 1;
- latency = policy->cpuinfo.transition_latency;
- if (latency < 1000)
- latency = 1000;
-
- def_sampling_rate = (latency / 1000) *
+ def_sampling_rate = 10 * latency *
DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
+
+ if (def_sampling_rate < MIN_STAT_SAMPLING_RATE)
+ def_sampling_rate = MIN_STAT_SAMPLING_RATE;
+
dbs_tuners_ins.sampling_rate = def_sampling_rate;
- dbs_tuners_ins.ignore_nice = 0;
- dbs_tuners_ins.freq_step = 5;
dbs_timer_init();
}
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 69aa1db8336..3e6ffcaa5af 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -74,6 +74,8 @@ static unsigned int dbs_enable; /* number of CPUs using this policy */
static DEFINE_MUTEX (dbs_mutex);
static DECLARE_WORK (dbs_work, do_dbs_timer, NULL);
+static struct workqueue_struct *dbs_workq;
+
struct dbs_tuners {
unsigned int sampling_rate;
unsigned int sampling_down_factor;
@@ -84,6 +86,7 @@ struct dbs_tuners {
static struct dbs_tuners dbs_tuners_ins = {
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
+ .ignore_nice = 0,
};
static inline unsigned int get_cpu_idle_time(unsigned int cpu)
@@ -350,6 +353,9 @@ static void dbs_check_cpu(int cpu)
freq_next = (freq_next * policy->cur) /
(dbs_tuners_ins.up_threshold - 10);
+ if (freq_next < policy->min)
+ freq_next = policy->min;
+
if (freq_next <= ((policy->cur * 95) / 100))
__cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L);
}
@@ -360,23 +366,29 @@ static void do_dbs_timer(void *data)
mutex_lock(&dbs_mutex);
for_each_online_cpu(i)
dbs_check_cpu(i);
- schedule_delayed_work(&dbs_work,
- usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
+ queue_delayed_work(dbs_workq, &dbs_work,
+ usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
mutex_unlock(&dbs_mutex);
}
static inline void dbs_timer_init(void)
{
INIT_WORK(&dbs_work, do_dbs_timer, NULL);
- schedule_delayed_work(&dbs_work,
- usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
+ if (!dbs_workq)
+ dbs_workq = create_singlethread_workqueue("ondemand");
+ if (!dbs_workq) {
+ printk(KERN_ERR "ondemand: Cannot initialize kernel thread\n");
+ return;
+ }
+ queue_delayed_work(dbs_workq, &dbs_work,
+ usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
return;
}
static inline void dbs_timer_exit(void)
{
- cancel_delayed_work(&dbs_work);
- return;
+ if (dbs_workq)
+ cancel_rearming_delayed_workqueue(dbs_workq, &dbs_work);
}
static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
@@ -395,8 +407,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return -EINVAL;
if (policy->cpuinfo.transition_latency >
- (TRANSITION_LATENCY_LIMIT * 1000))
+ (TRANSITION_LATENCY_LIMIT * 1000)) {
+ printk(KERN_WARNING "ondemand governor failed to load "
+ "due to too long transition latency\n");
return -EINVAL;
+ }
if (this_dbs_info->enable) /* Already enabled */
break;
@@ -431,8 +446,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
def_sampling_rate = MIN_STAT_SAMPLING_RATE;
dbs_tuners_ins.sampling_rate = def_sampling_rate;
- dbs_tuners_ins.ignore_nice = 0;
-
dbs_timer_init();
}
@@ -484,8 +497,12 @@ static int __init cpufreq_gov_dbs_init(void)
static void __exit cpufreq_gov_dbs_exit(void)
{
- /* Make sure that the scheduled work is indeed not running */
- flush_scheduled_work();
+ /* Make sure that the scheduled work is indeed not running.
+ Assumes the timer has been cancelled first. */
+ if (dbs_workq) {
+ flush_workqueue(dbs_workq);
+ destroy_workqueue(dbs_workq);
+ }
cpufreq_unregister_governor(&cpufreq_gov_dbs);
}
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index b582d0cdc24..4f0898400c6 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -71,7 +71,7 @@ config EDAC_E7XXX
config EDAC_E752X
tristate "Intel e752x (e7520, e7525, e7320)"
- depends on EDAC_MM_EDAC && PCI && X86
+ depends on EDAC_MM_EDAC && PCI && X86 && HOTPLUG
help
Support for error detection and correction on the Intel
E7520, E7525, E7320 server chipsets.
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index 66572c5323a..fce31936e6d 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -25,6 +25,8 @@
#include <linux/slab.h>
#include "edac_mc.h"
+static int force_function_unhide;
+
#define e752x_printk(level, fmt, arg...) \
edac_printk(level, "e752x", fmt, ##arg)
@@ -782,8 +784,16 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
debugf0("%s(): mci\n", __func__);
debugf0("Starting Probe1\n");
- /* enable device 0 function 1 */
+ /* check to see if device 0 function 1 is enabled; if it isn't, we
+ * assume the BIOS has reserved it for a reason and is expecting
+ * exclusive access, we take care not to violate that assumption and
+ * fail the probe. */
pci_read_config_byte(pdev, E752X_DEVPRES1, &stat8);
+ if (!force_function_unhide && !(stat8 & (1 << 5))) {
+ printk(KERN_INFO "Contact your BIOS vendor to see if the "
+ "E752x error registers can be safely un-hidden\n");
+ goto fail;
+ }
stat8 |= (1 << 5);
pci_write_config_byte(pdev, E752X_DEVPRES1, stat8);
@@ -1063,3 +1073,8 @@ module_exit(e752x_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n");
MODULE_DESCRIPTION("MC support for Intel e752x memory controllers");
+
+module_param(force_function_unhide, int, 0444);
+MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:"
+" 1=force unhide and hope BIOS doesn't fight driver for Dev0:Fun1 access");
+
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 905f58ba8e1..ea06e3a4dc3 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -2044,7 +2044,7 @@ static int __init edac_mc_init(void)
*/
clear_pci_parity_errors();
- /* Create the MC sysfs entires */
+ /* Create the MC sysfs entries */
if (edac_sysfs_memctrl_setup()) {
edac_printk(KERN_ERR, EDAC_MC,
"Error initializing sysfs code\n");
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 85429979d0d..98e395f4bb2 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -1,7 +1,8 @@
#
# Makefile for the linux kernel.
#
-obj-$(CONFIG_EDD) += edd.o
+obj-$(CONFIG_DMI) += dmi_scan.o
+obj-$(CONFIG_EDD) += edd.o
obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_PCDP) += pcdp.o
obj-$(CONFIG_DELL_RBU) += dell_rbu.o
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index d6543fc4a92..339f405ff70 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -484,26 +484,15 @@ static void dcdbas_host_control(void)
static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
void *unused)
{
- static unsigned int notify_cnt = 0;
-
switch (code) {
case SYS_DOWN:
case SYS_HALT:
case SYS_POWER_OFF:
if (host_control_on_shutdown) {
/* firmware is going to perform host control action */
- if (++notify_cnt == 2) {
- printk(KERN_WARNING
- "Please wait for shutdown "
- "action to complete...\n");
- dcdbas_host_control();
- }
- /*
- * register again and initiate the host control
- * action on the second notification to allow
- * everyone that registered to be notified
- */
- register_reboot_notifier(nb);
+ printk(KERN_WARNING "Please wait for shutdown "
+ "action to complete...\n");
+ dcdbas_host_control();
}
break;
}
@@ -514,7 +503,7 @@ static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
static struct notifier_block dcdbas_reboot_nb = {
.notifier_call = dcdbas_reboot_notify,
.next = NULL,
- .priority = 0
+ .priority = INT_MIN
};
static DCDBAS_BIN_ATTR_RW(smi_data);
diff --git a/arch/i386/kernel/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 5efceebc48d..948bd7e1445 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -27,7 +27,7 @@ static char * __init dmi_string(struct dmi_header *dm, u8 s)
else
printk(KERN_ERR "dmi_string: out of memory.\n");
}
- }
+ }
return str;
}
@@ -41,7 +41,7 @@ static int __init dmi_table(u32 base, int len, int num,
{
u8 *buf, *data;
int i = 0;
-
+
buf = dmi_ioremap(base, len);
if (buf == NULL)
return -1;
@@ -49,9 +49,9 @@ static int __init dmi_table(u32 base, int len, int num,
data = buf;
/*
- * Stop when we see all the items the table claimed to have
- * OR we run off the end of the table (also happens)
- */
+ * Stop when we see all the items the table claimed to have
+ * OR we run off the end of the table (also happens)
+ */
while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
struct dmi_header *dm = (struct dmi_header *)data;
/*
@@ -75,7 +75,7 @@ static int __init dmi_checksum(u8 *buf)
{
u8 sum = 0;
int a;
-
+
for (a = 0; a < 15; a++)
sum += buf[a];
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index 7636c1a58f9..1659f6c4145 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -33,7 +33,6 @@
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/dmi.h>
-#include <linux/mutex.h>
#include <asm/io.h>
#define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */
@@ -71,10 +70,10 @@ static u8 km_activity;
static int rest_x;
static int rest_y;
-static DEFINE_MUTEX(hdaps_mutex);
+static DECLARE_MUTEX(hdaps_sem);
/*
- * __get_latch - Get the value from a given port. Callers must hold hdaps_mutex.
+ * __get_latch - Get the value from a given port. Callers must hold hdaps_sem.
*/
static inline u8 __get_latch(u16 port)
{
@@ -83,7 +82,7 @@ static inline u8 __get_latch(u16 port)
/*
* __check_latch - Check a port latch for a given value. Returns zero if the
- * port contains the given value. Callers must hold hdaps_mutex.
+ * port contains the given value. Callers must hold hdaps_sem.
*/
static inline int __check_latch(u16 port, u8 val)
{
@@ -94,7 +93,7 @@ static inline int __check_latch(u16 port, u8 val)
/*
* __wait_latch - Wait up to 100us for a port latch to get a certain value,
- * returning zero if the value is obtained. Callers must hold hdaps_mutex.
+ * returning zero if the value is obtained. Callers must hold hdaps_sem.
*/
static int __wait_latch(u16 port, u8 val)
{
@@ -111,7 +110,7 @@ static int __wait_latch(u16 port, u8 val)
/*
* __device_refresh - request a refresh from the accelerometer. Does not wait
- * for refresh to complete. Callers must hold hdaps_mutex.
+ * for refresh to complete. Callers must hold hdaps_sem.
*/
static void __device_refresh(void)
{
@@ -125,7 +124,7 @@ static void __device_refresh(void)
/*
* __device_refresh_sync - request a synchronous refresh from the
* accelerometer. We wait for the refresh to complete. Returns zero if
- * successful and nonzero on error. Callers must hold hdaps_mutex.
+ * successful and nonzero on error. Callers must hold hdaps_sem.
*/
static int __device_refresh_sync(void)
{
@@ -135,7 +134,7 @@ static int __device_refresh_sync(void)
/*
* __device_complete - indicate to the accelerometer that we are done reading
- * data, and then initiate an async refresh. Callers must hold hdaps_mutex.
+ * data, and then initiate an async refresh. Callers must hold hdaps_sem.
*/
static inline void __device_complete(void)
{
@@ -153,7 +152,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val)
{
int ret;
- mutex_lock(&hdaps_mutex);
+ down(&hdaps_sem);
/* do a sync refresh -- we need to be sure that we read fresh data */
ret = __device_refresh_sync();
@@ -164,7 +163,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val)
__device_complete();
out:
- mutex_unlock(&hdaps_mutex);
+ up(&hdaps_sem);
return ret;
}
@@ -199,9 +198,9 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2,
{
int ret;
- mutex_lock(&hdaps_mutex);
+ down(&hdaps_sem);
ret = __hdaps_read_pair(port1, port2, val1, val2);
- mutex_unlock(&hdaps_mutex);
+ up(&hdaps_sem);
return ret;
}
@@ -214,7 +213,7 @@ static int hdaps_device_init(void)
{
int total, ret = -ENXIO;
- mutex_lock(&hdaps_mutex);
+ down(&hdaps_sem);
outb(0x13, 0x1610);
outb(0x01, 0x161f);
@@ -280,7 +279,7 @@ static int hdaps_device_init(void)
}
out:
- mutex_unlock(&hdaps_mutex);
+ up(&hdaps_sem);
return ret;
}
@@ -314,7 +313,7 @@ static struct platform_driver hdaps_driver = {
};
/*
- * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_mutex.
+ * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem.
*/
static void hdaps_calibrate(void)
{
@@ -326,7 +325,7 @@ static void hdaps_mousedev_poll(unsigned long unused)
int x, y;
/* Cannot sleep. Try nonblockingly. If we fail, try again later. */
- if (!mutex_trylock(&hdaps_mutex)) {
+ if (down_trylock(&hdaps_sem)) {
mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD);
return;
}
@@ -341,7 +340,7 @@ static void hdaps_mousedev_poll(unsigned long unused)
mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
out:
- mutex_unlock(&hdaps_mutex);
+ up(&hdaps_sem);
}
@@ -421,9 +420,9 @@ static ssize_t hdaps_calibrate_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- mutex_lock(&hdaps_mutex);
+ down(&hdaps_sem);
hdaps_calibrate();
- mutex_unlock(&hdaps_mutex);
+ up(&hdaps_sem);
return count;
}
@@ -510,12 +509,22 @@ static int hdaps_dmi_match_invert(struct dmi_system_id *id)
} \
}
+#define HDAPS_DMI_MATCH_LENOVO(model) { \
+ .ident = "Lenovo " model, \
+ .callback = hdaps_dmi_match_invert, \
+ .matches = { \
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), \
+ DMI_MATCH(DMI_PRODUCT_VERSION, model) \
+ } \
+}
+
static int __init hdaps_init(void)
{
int ret;
/* Note that DMI_MATCH(...,"ThinkPad T42") will match "ThinkPad T42p" */
struct dmi_system_id hdaps_whitelist[] = {
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad H"),
HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
@@ -525,15 +534,17 @@ static int __init hdaps_init(void)
HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
+ HDAPS_DMI_MATCH_LENOVO("ThinkPad T60p"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"),
+ HDAPS_DMI_MATCH_LENOVO("ThinkPad X60"),
{ .ident = NULL }
};
if (!dmi_check_system(hdaps_whitelist)) {
printk(KERN_WARNING "hdaps: supported laptop not found!\n");
- ret = -ENXIO;
+ ret = -ENODEV;
goto out;
}
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 6865c64d8a5..958602e2841 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -1161,7 +1161,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
bank. */
if (kind < 0) {
if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) {
- dev_warn(dev, "Detection failed at step 3\n");
+ dev_dbg(dev, "Detection failed at step 1\n");
goto ERROR1;
}
val1 = w83792d_read_value(client, W83792D_REG_BANK);
@@ -1170,6 +1170,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
if (!(val1 & 0x07)) { /* is Bank0 */
if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
((val1 & 0x80) && (val2 != 0x5c))) {
+ dev_dbg(dev, "Detection failed at step 2\n");
goto ERROR1;
}
}
@@ -1177,7 +1178,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
should match */
if (w83792d_read_value(client,
W83792D_REG_I2C_ADDR) != address) {
- dev_warn(dev, "Detection failed at step 5\n");
+ dev_dbg(dev, "Detection failed at step 3\n");
goto ERROR1;
}
}
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 089c6f5b24d..d6d44946a28 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -286,7 +286,10 @@ config I2C_PARPORT
This driver is a replacement for (and was inspired by) an older
driver named i2c-philips-par. The new driver supports more devices,
and makes it easier to add support for new devices.
-
+
+ An adapter type parameter is now mandatory. Please read the file
+ Documentation/i2c/busses/i2c-parport for details.
+
Another driver exists, named i2c-parport-light, which doesn't depend
on the parport driver. This is meant for embedded systems. Don't say
Y here if you intend to say Y or M there.
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 8e0f3158215..dfca7493362 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -478,6 +478,11 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
ret = i801_transaction();
}
+ /* Some BIOSes don't like it when PEC is enabled at reboot or resume
+ time, so we forcibly disable it after every transaction. */
+ if (hwpec)
+ outb_p(0, SMBAUXCTL);
+
if(block)
return ret;
if(ret)
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index c63025a4c86..e09ebbb2f9f 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -121,9 +121,14 @@ static struct i2c_adapter parport_adapter = {
static int __init i2c_parport_init(void)
{
- if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
+ if (type < 0) {
+ printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
+ return -ENODEV;
+ }
+
+ if (type >= ARRAY_SIZE(adapter_parm)) {
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
- type = 0;
+ return -ENODEV;
}
if (base == 0) {
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 7e2e8cd1c14..934bd55bae1 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -241,9 +241,14 @@ static struct parport_driver i2c_parport_driver = {
static int __init i2c_parport_init(void)
{
- if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
+ if (type < 0) {
+ printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
+ return -ENODEV;
+ }
+
+ if (type >= ARRAY_SIZE(adapter_parm)) {
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
- type = 0;
+ return -ENODEV;
}
return parport_register_driver(&i2c_parport_driver);
diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h
index d702e5e0388..9ddd816d5d0 100644
--- a/drivers/i2c/busses/i2c-parport.h
+++ b/drivers/i2c/busses/i2c-parport.h
@@ -90,7 +90,7 @@ static struct adapter_parm adapter_parm[] = {
},
};
-static int type;
+static int type = -1;
module_param(type, int, 0);
MODULE_PARM_DESC(type,
"Type of adapter:\n"
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 3024907cdaf..1a73c0532fc 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -43,13 +43,6 @@
#include <linux/init.h>
#include <asm/io.h>
-/*
- HISTORY:
- 2003-05-11 1.0.0 Updated from lm_sensors project for kernel 2.5
- (was i2c-sis645.c from lm_sensors 2.7.0)
-*/
-#define SIS96x_VERSION "1.0.0"
-
/* base address register in PCI config space */
#define SIS96x_BAR 0x04
@@ -337,7 +330,6 @@ static struct pci_driver sis96x_driver = {
static int __init i2c_sis96x_init(void)
{
- printk(KERN_INFO "i2c-sis96x version %s\n", SIS96x_VERSION);
return pci_register_driver(&sis96x_driver);
}
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 8bd305e47f0..766cc969c4d 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -133,6 +133,9 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
outb(ACBST_STASTR | ACBST_NEGACK, ACBST);
+
+ /* Reset the status register */
+ outb(0, ACBST);
return;
}
@@ -228,6 +231,10 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
timeout = jiffies + POLL_TIMEOUT;
while (time_before(jiffies, timeout)) {
status = inb(ACBST);
+
+ /* Reset the status register to avoid the hang */
+ outb(0, ACBST);
+
if ((status & (ACBST_SDAST|ACBST_BER|ACBST_NEGACK)) != 0) {
scx200_acb_machine(iface, status);
return;
@@ -415,7 +422,6 @@ static int __init scx200_acb_create(const char *text, int base, int index)
struct scx200_acb_iface *iface;
struct i2c_adapter *adapter;
int rc;
- char description[64];
iface = kzalloc(sizeof(*iface), GFP_KERNEL);
if (!iface) {
@@ -434,10 +440,7 @@ static int __init scx200_acb_create(const char *text, int base, int index)
mutex_init(&iface->mutex);
- snprintf(description, sizeof(description), "%s ACCESS.bus [%s]",
- text, adapter->name);
-
- if (request_region(base, 8, description) == 0) {
+ if (!request_region(base, 8, adapter->name)) {
printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n",
base, base + 8-1);
rc = -EBUSY;
@@ -488,7 +491,7 @@ static struct pci_device_id divil_pci[] = {
#define MSR_LBAR_SMB 0x5140000B
-static int scx200_add_cs553x(void)
+static __init int scx200_add_cs553x(void)
{
u32 low, hi;
u32 smb_base;
@@ -524,6 +527,9 @@ static int __init scx200_acb_init(void)
} else if (pci_dev_present(divil_pci))
rc = scx200_add_cs553x();
+ /* If at least one bus was created, init must succeed */
+ if (scx200_acb_list)
+ return 0;
return rc;
}
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index f9fae28f561..7aa5c38f085 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -65,15 +65,6 @@ config SENSORS_PCF8591
This driver can also be built as a module. If so, the module
will be called pcf8591.
-config SENSORS_RTC8564
- tristate "Epson 8564 RTC chip"
- depends on I2C && EXPERIMENTAL
- help
- If you say yes here you get support for the Epson 8564 RTC chip.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-rtc8564.
-
config ISP1301_OMAP
tristate "Philips ISP1301 with OMAP OTG"
depends on I2C && ARCH_OMAP_OTG
@@ -126,13 +117,4 @@ config SENSORS_MAX6875
This driver can also be built as a module. If so, the module
will be called max6875.
-config RTC_X1205_I2C
- tristate "Xicor X1205 RTC chip"
- depends on I2C && EXPERIMENTAL
- help
- If you say yes here you get support for the Xicor X1205 RTC chip.
-
- This driver can also be built as a module. If so, the module
- will be called x1205.
-
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 46178b57b1f..779868ef2e2 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -10,10 +10,8 @@ obj-$(CONFIG_SENSORS_M41T00) += m41t00.o
obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
-obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TPS65010) += tps65010.o
-obj-$(CONFIG_RTC_X1205_I2C) += x1205.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index 03d09ed5ec2..4630f1969a0 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -27,6 +27,7 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#define DS1374_REG_TOD0 0x00
#define DS1374_REG_TOD1 0x01
@@ -139,7 +140,7 @@ ulong ds1374_get_rtc_time(void)
return t1;
}
-static void ds1374_set_tlet(ulong arg)
+static void ds1374_set_work(void *arg)
{
ulong t1, t2;
int limit = 10; /* arbitrary retry limit */
@@ -168,17 +169,18 @@ static void ds1374_set_tlet(ulong arg)
static ulong new_time;
-static DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet,
- (ulong) & new_time);
+static struct workqueue_struct *ds1374_workqueue;
+
+static DECLARE_WORK(ds1374_work, ds1374_set_work, &new_time);
int ds1374_set_rtc_time(ulong nowtime)
{
new_time = nowtime;
if (in_interrupt())
- tasklet_schedule(&ds1374_tasklet);
+ queue_work(ds1374_workqueue, &ds1374_work);
else
- ds1374_set_tlet((ulong) & new_time);
+ ds1374_set_work(&new_time);
return 0;
}
@@ -204,6 +206,8 @@ static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
client->adapter = adap;
client->driver = &ds1374_driver;
+ ds1374_workqueue = create_singlethread_workqueue("ds1374");
+
if ((rc = i2c_attach_client(client)) != 0) {
kfree(client);
return rc;
@@ -227,7 +231,7 @@ static int ds1374_detach(struct i2c_client *client)
if ((rc = i2c_detach_client(client)) == 0) {
kfree(i2c_get_clientdata(client));
- tasklet_kill(&ds1374_tasklet);
+ destroy_workqueue(ds1374_workqueue);
}
return rc;
}
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index b5aabe7cf79..99ab4ec3439 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -25,6 +25,7 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#include <asm/time.h>
#include <asm/rtc.h>
@@ -111,7 +112,7 @@ m41t00_get_rtc_time(void)
}
static void
-m41t00_set_tlet(ulong arg)
+m41t00_set(void *arg)
{
struct rtc_time tm;
ulong nowtime = *(ulong *)arg;
@@ -130,13 +131,13 @@ m41t00_set_tlet(ulong arg)
if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0)
|| (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f)
< 0)
- || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x7f)
+ || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x3f)
< 0)
- || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x7f)
+ || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x3f)
< 0)
- || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x7f)
+ || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x1f)
< 0)
- || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0x7f)
+ || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0xff)
< 0))
dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n");
@@ -145,9 +146,9 @@ m41t00_set_tlet(ulong arg)
return;
}
-static ulong new_time;
-
-DECLARE_TASKLET_DISABLED(m41t00_tasklet, m41t00_set_tlet, (ulong)&new_time);
+static ulong new_time;
+static struct workqueue_struct *m41t00_wq;
+static DECLARE_WORK(m41t00_work, m41t00_set, &new_time);
int
m41t00_set_rtc_time(ulong nowtime)
@@ -155,9 +156,9 @@ m41t00_set_rtc_time(ulong nowtime)
new_time = nowtime;
if (in_interrupt())
- tasklet_schedule(&m41t00_tasklet);
+ queue_work(m41t00_wq, &m41t00_work);
else
- m41t00_set_tlet((ulong)&new_time);
+ m41t00_set(&new_time);
return 0;
}
@@ -189,6 +190,7 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
return rc;
}
+ m41t00_wq = create_singlethread_workqueue("m41t00");
save_client = client;
return 0;
}
@@ -206,7 +208,7 @@ m41t00_detach(struct i2c_client *client)
if ((rc = i2c_detach_client(client)) == 0) {
kfree(client);
- tasklet_kill(&m41t00_tasklet);
+ destroy_workqueue(m41t00_wq);
}
return rc;
}
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
deleted file mode 100644
index 0d8699b3f48..00000000000
--- a/drivers/i2c/chips/rtc8564.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * linux/drivers/i2c/chips/rtc8564.c
- *
- * Copyright (C) 2002-2004 Stefan Eletzhofer
- *
- * based on linux/drivers/acron/char/pcf8583.c
- * Copyright (C) 2000 Russell King
- *
- * 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.
- *
- * Driver for system3's EPSON RTC 8564 chip
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/bcd.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/rtc.h> /* get the user-level API */
-#include <linux/init.h>
-
-#include "rtc8564.h"
-
-#ifdef DEBUG
-# define _DBG(x, fmt, args...) do{ if (debug>=x) printk(KERN_DEBUG"%s: " fmt "\n", __FUNCTION__, ##args); } while(0);
-#else
-# define _DBG(x, fmt, args...) do { } while(0);
-#endif
-
-#define _DBGRTCTM(x, rtctm) if (debug>=x) printk("%s: secs=%d, mins=%d, hours=%d, mday=%d, " \
- "mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, \
- (rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, \
- (rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl);
-
-struct rtc8564_data {
- struct i2c_client client;
- u16 ctrl;
-};
-
-static inline u8 _rtc8564_ctrl1(struct i2c_client *client)
-{
- struct rtc8564_data *data = i2c_get_clientdata(client);
- return data->ctrl & 0xff;
-}
-static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
-{
- struct rtc8564_data *data = i2c_get_clientdata(client);
- return (data->ctrl & 0xff00) >> 8;
-}
-
-#define CTRL1(c) _rtc8564_ctrl1(c)
-#define CTRL2(c) _rtc8564_ctrl2(c)
-
-static int debug;
-module_param(debug, int, S_IRUGO | S_IWUSR);
-
-static struct i2c_driver rtc8564_driver;
-
-static unsigned short ignore[] = { I2C_CLIENT_END };
-static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END };
-
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_addr,
- .probe = ignore,
- .ignore = ignore,
-};
-
-static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem);
-static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem);
-
-static int rtc8564_read(struct i2c_client *client, unsigned char adr,
- unsigned char *buf, unsigned char len)
-{
- int ret = -EIO;
- unsigned char addr[1] = { adr };
- struct i2c_msg msgs[2] = {
- {client->addr, 0, 1, addr},
- {client->addr, I2C_M_RD, len, buf}
- };
-
- _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len);
-
- if (!buf) {
- ret = -EINVAL;
- goto done;
- }
-
- ret = i2c_transfer(client->adapter, msgs, 2);
- if (ret == 2) {
- ret = 0;
- }
-
-done:
- return ret;
-}
-
-static int rtc8564_write(struct i2c_client *client, unsigned char adr,
- unsigned char *data, unsigned char len)
-{
- int ret = 0;
- unsigned char _data[16];
- struct i2c_msg wr;
- int i;
-
- if (!data || len > 15) {
- ret = -EINVAL;
- goto done;
- }
-
- _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len);
-
- _data[0] = adr;
- for (i = 0; i < len; i++) {
- _data[i + 1] = data[i];
- _DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]);
- }
-
- wr.addr = client->addr;
- wr.flags = 0;
- wr.len = len + 1;
- wr.buf = _data;
-
- ret = i2c_transfer(client->adapter, &wr, 1);
- if (ret == 1) {
- ret = 0;
- }
-
-done:
- return ret;
-}
-
-static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
-{
- int ret;
- struct i2c_client *new_client;
- struct rtc8564_data *d;
- unsigned char data[10];
- unsigned char ad[1] = { 0 };
- struct i2c_msg ctrl_wr[1] = {
- {addr, 0, 2, data}
- };
- struct i2c_msg ctrl_rd[2] = {
- {addr, 0, 1, ad},
- {addr, I2C_M_RD, 2, data}
- };
-
- d = kzalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
- if (!d) {
- ret = -ENOMEM;
- goto done;
- }
- new_client = &d->client;
-
- strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
- i2c_set_clientdata(new_client, d);
- new_client->addr = addr;
- new_client->adapter = adap;
- new_client->driver = &rtc8564_driver;
-
- _DBG(1, "client=%p", new_client);
-
- /* init ctrl1 reg */
- data[0] = 0;
- data[1] = 0;
- ret = i2c_transfer(new_client->adapter, ctrl_wr, 1);
- if (ret != 1) {
- printk(KERN_INFO "rtc8564: cant init ctrl1\n");
- ret = -ENODEV;
- goto done;
- }
-
- /* read back ctrl1 and ctrl2 */
- ret = i2c_transfer(new_client->adapter, ctrl_rd, 2);
- if (ret != 2) {
- printk(KERN_INFO "rtc8564: cant read ctrl\n");
- ret = -ENODEV;
- goto done;
- }
-
- d->ctrl = data[0] | (data[1] << 8);
-
- _DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x",
- data[0], data[1]);
-
- ret = i2c_attach_client(new_client);
-done:
- if (ret) {
- kfree(d);
- }
- return ret;
-}
-
-static int rtc8564_probe(struct i2c_adapter *adap)
-{
- return i2c_probe(adap, &addr_data, rtc8564_attach);
-}
-
-static int rtc8564_detach(struct i2c_client *client)
-{
- i2c_detach_client(client);
- kfree(i2c_get_clientdata(client));
- return 0;
-}
-
-static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
-{
- int ret = -EIO;
- unsigned char buf[15];
-
- _DBG(1, "client=%p, dt=%p", client, dt);
-
- if (!dt)
- return -EINVAL;
-
- memset(buf, 0, sizeof(buf));
-
- ret = rtc8564_read(client, 0, buf, 15);
- if (ret)
- return ret;
-
- /* century stored in minute alarm reg */
- dt->year = BCD2BIN(buf[RTC8564_REG_YEAR]);
- dt->year += 100 * BCD2BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
- dt->mday = BCD2BIN(buf[RTC8564_REG_DAY] & 0x3f);
- dt->wday = BCD2BIN(buf[RTC8564_REG_WDAY] & 7);
- dt->mon = BCD2BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
-
- dt->secs = BCD2BIN(buf[RTC8564_REG_SEC] & 0x7f);
- dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80;
- dt->mins = BCD2BIN(buf[RTC8564_REG_MIN] & 0x7f);
- dt->hours = BCD2BIN(buf[RTC8564_REG_HR] & 0x3f);
-
- _DBGRTCTM(2, *dt);
-
- return 0;
-}
-
-static int
-rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
-{
- int ret, len = 5;
- unsigned char buf[15];
-
- _DBG(1, "client=%p, dt=%p", client, dt);
-
- if (!dt)
- return -EINVAL;
-
- _DBGRTCTM(2, *dt);
-
- buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP;
- buf[RTC8564_REG_CTRL2] = CTRL2(client);
- buf[RTC8564_REG_SEC] = BIN2BCD(dt->secs);
- buf[RTC8564_REG_MIN] = BIN2BCD(dt->mins);
- buf[RTC8564_REG_HR] = BIN2BCD(dt->hours);
-
- if (datetoo) {
- len += 5;
- buf[RTC8564_REG_DAY] = BIN2BCD(dt->mday);
- buf[RTC8564_REG_WDAY] = BIN2BCD(dt->wday);
- buf[RTC8564_REG_MON_CENT] = BIN2BCD(dt->mon) & 0x1f;
- /* century stored in minute alarm reg */
- buf[RTC8564_REG_YEAR] = BIN2BCD(dt->year % 100);
- buf[RTC8564_REG_AL_MIN] = BIN2BCD(dt->year / 100);
- }
-
- ret = rtc8564_write(client, 0, buf, len);
- if (ret) {
- _DBG(1, "error writing data! %d", ret);
- }
-
- buf[RTC8564_REG_CTRL1] = CTRL1(client);
- ret = rtc8564_write(client, 0, buf, 1);
- if (ret) {
- _DBG(1, "error writing data! %d", ret);
- }
-
- return ret;
-}
-
-static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl)
-{
- struct rtc8564_data *data = i2c_get_clientdata(client);
-
- if (!ctrl)
- return -1;
-
- *ctrl = data->ctrl;
- return 0;
-}
-
-static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl)
-{
- struct rtc8564_data *data = i2c_get_clientdata(client);
- unsigned char buf[2];
-
- if (!ctrl)
- return -1;
-
- buf[0] = *ctrl & 0xff;
- buf[1] = (*ctrl & 0xff00) >> 8;
- data->ctrl = *ctrl;
-
- return rtc8564_write(client, 0, buf, 2);
-}
-
-static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem)
-{
-
- if (!mem)
- return -EINVAL;
-
- return rtc8564_read(client, mem->loc, mem->data, mem->nr);
-}
-
-static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem)
-{
-
- if (!mem)
- return -EINVAL;
-
- return rtc8564_write(client, mem->loc, mem->data, mem->nr);
-}
-
-static int
-rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
-
- _DBG(1, "cmd=%d", cmd);
-
- switch (cmd) {
- case RTC_GETDATETIME:
- return rtc8564_get_datetime(client, arg);
-
- case RTC_SETTIME:
- return rtc8564_set_datetime(client, arg, 0);
-
- case RTC_SETDATETIME:
- return rtc8564_set_datetime(client, arg, 1);
-
- case RTC_GETCTRL:
- return rtc8564_get_ctrl(client, arg);
-
- case RTC_SETCTRL:
- return rtc8564_set_ctrl(client, arg);
-
- case MEM_READ:
- return rtc8564_read_mem(client, arg);
-
- case MEM_WRITE:
- return rtc8564_write_mem(client, arg);
-
- default:
- return -EINVAL;
- }
-}
-
-static struct i2c_driver rtc8564_driver = {
- .driver = {
- .name = "RTC8564",
- },
- .id = I2C_DRIVERID_RTC8564,
- .attach_adapter = rtc8564_probe,
- .detach_client = rtc8564_detach,
- .command = rtc8564_command
-};
-
-static __init int rtc8564_init(void)
-{
- return i2c_add_driver(&rtc8564_driver);
-}
-
-static __exit void rtc8564_exit(void)
-{
- i2c_del_driver(&rtc8564_driver);
-}
-
-MODULE_AUTHOR("Stefan Eletzhofer <Stefan.Eletzhofer@eletztrick.de>");
-MODULE_DESCRIPTION("EPSON RTC8564 Driver");
-MODULE_LICENSE("GPL");
-
-module_init(rtc8564_init);
-module_exit(rtc8564_exit);
diff --git a/drivers/i2c/chips/rtc8564.h b/drivers/i2c/chips/rtc8564.h
deleted file mode 100644
index e5342d10b8f..00000000000
--- a/drivers/i2c/chips/rtc8564.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * linux/drivers/i2c/chips/rtc8564.h
- *
- * Copyright (C) 2002-2004 Stefan Eletzhofer
- *
- * based on linux/drivers/acron/char/pcf8583.h
- * Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-struct rtc_tm {
- unsigned char secs;
- unsigned char mins;
- unsigned char hours;
- unsigned char mday;
- unsigned char mon;
- unsigned short year; /* xxxx 4 digits :) */
- unsigned char wday;
- unsigned char vl;
-};
-
-struct mem {
- unsigned int loc;
- unsigned int nr;
- unsigned char *data;
-};
-
-#define RTC_GETDATETIME 0
-#define RTC_SETTIME 1
-#define RTC_SETDATETIME 2
-#define RTC_GETCTRL 3
-#define RTC_SETCTRL 4
-#define MEM_READ 5
-#define MEM_WRITE 6
-
-#define RTC8564_REG_CTRL1 0x0 /* T 0 S 0 | T 0 0 0 */
-#define RTC8564_REG_CTRL2 0x1 /* 0 0 0 TI/TP | AF TF AIE TIE */
-#define RTC8564_REG_SEC 0x2 /* VL 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_MIN 0x3 /* x 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_HR 0x4 /* x x 2 1 | 8 4 2 1 */
-#define RTC8564_REG_DAY 0x5 /* x x 2 1 | 8 4 2 1 */
-#define RTC8564_REG_WDAY 0x6 /* x x x x | x 4 2 1 */
-#define RTC8564_REG_MON_CENT 0x7 /* C x x 1 | 8 4 2 1 */
-#define RTC8564_REG_YEAR 0x8 /* 8 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_AL_MIN 0x9 /* AE 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_AL_HR 0xa /* AE 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_AL_DAY 0xb /* AE x 2 1 | 8 4 2 1 */
-#define RTC8564_REG_AL_WDAY 0xc /* AE x x x | x 4 2 1 */
-#define RTC8564_REG_CLKOUT 0xd /* FE x x x | x x FD1 FD0 */
-#define RTC8564_REG_TCTL 0xe /* TE x x x | x x FD1 FD0 */
-#define RTC8564_REG_TIMER 0xf /* 8 bit binary */
-
-/* Control reg */
-#define RTC8564_CTRL1_TEST1 (1<<3)
-#define RTC8564_CTRL1_STOP (1<<5)
-#define RTC8564_CTRL1_TEST2 (1<<7)
-
-#define RTC8564_CTRL2_TIE (1<<0)
-#define RTC8564_CTRL2_AIE (1<<1)
-#define RTC8564_CTRL2_TF (1<<2)
-#define RTC8564_CTRL2_AF (1<<3)
-#define RTC8564_CTRL2_TI_TP (1<<4)
-
-/* CLKOUT frequencies */
-#define RTC8564_FD_32768HZ (0x0)
-#define RTC8564_FD_1024HZ (0x1)
-#define RTC8564_FD_32 (0x2)
-#define RTC8564_FD_1HZ (0x3)
-
-/* Timer CTRL */
-#define RTC8564_TD_4096HZ (0x0)
-#define RTC8564_TD_64HZ (0x1)
-#define RTC8564_TD_1HZ (0x2)
-#define RTC8564_TD_1_60HZ (0x3)
-
-#define I2C_DRIVERID_RTC8564 0xf000
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index c7671e18801..b4a41d6d071 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -2143,6 +2143,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
req.data = (char *)&capbuf;
req.data_len = sizeof(capbuf);
+ req.flags |= REQ_QUIET;
stat = cdrom_queue_packet_command(drive, &req);
if (stat == 0) {
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index ccf528d733b..a5017de72da 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -61,6 +61,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/mutex.h>
+#include <linux/leds.h>
#define _IDE_DISK
@@ -317,6 +318,8 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s
return ide_stopped;
}
+ ledtrig_ide_activity();
+
pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
(unsigned long long)block, rq->nr_sectors,
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index ebc59064b47..f04791a58df 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -433,6 +433,7 @@
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
+#include <linux/jiffies.h>
#include <linux/major.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/errno.h>
@@ -2336,7 +2337,7 @@ static ide_startstop_t idetape_rw_callback (ide_drive_t *drive)
}
if (time_after(jiffies, tape->insert_time))
tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
- if (jiffies - tape->avg_time >= HZ) {
+ if (time_after_eq(jiffies, tape->avg_time + HZ)) {
tape->avg_speed = tape->avg_size * HZ / (jiffies - tape->avg_time) / 1024;
tape->avg_size = 0;
tape->avg_time = jiffies;
@@ -2497,7 +2498,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
} else {
return ide_do_reset(drive);
}
- } else if (jiffies - tape->dsc_polling_start > IDETAPE_DSC_MA_THRESHOLD)
+ } else if (time_after(jiffies, tape->dsc_polling_start + IDETAPE_DSC_MA_THRESHOLD))
tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW;
idetape_postpone_request(drive);
return ide_stopped;
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 0606bd2f602..9233b8109a0 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -375,7 +375,13 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
}
}
- ide_end_request(drive, 1, rq->hard_nr_sectors);
+ if (rq->rq_disk) {
+ ide_driver_t *drv;
+
+ drv = *(ide_driver_t **)rq->rq_disk->private_data;;
+ drv->end_request(drive, 1, rq->hard_nr_sectors);
+ } else
+ ide_end_request(drive, 1, rq->hard_nr_sectors);
}
/*
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 6213bd3caee..602797a4420 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -81,14 +81,14 @@ static const char ide_major[] = {
};
typedef struct ide_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
int ndev;
dev_node_t node;
int hd;
} ide_info_t;
-static void ide_release(dev_link_t *);
-static void ide_config(dev_link_t *);
+static void ide_release(struct pcmcia_device *);
+static int ide_config(struct pcmcia_device *);
static void ide_detach(struct pcmcia_device *p_dev);
@@ -103,10 +103,9 @@ static void ide_detach(struct pcmcia_device *p_dev);
======================================================================*/
-static int ide_attach(struct pcmcia_device *p_dev)
+static int ide_probe(struct pcmcia_device *link)
{
ide_info_t *info;
- dev_link_t *link;
DEBUG(0, "ide_attach()\n");
@@ -114,7 +113,9 @@ static int ide_attach(struct pcmcia_device *p_dev)
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- link = &info->link; link->priv = info;
+
+ info->p_dev = link;
+ link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
@@ -122,16 +123,9 @@ static int ide_attach(struct pcmcia_device *p_dev)
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- ide_config(link);
-
- return 0;
+ return ide_config(link);
} /* ide_attach */
/*======================================================================
@@ -143,14 +137,11 @@ static int ide_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void ide_detach(struct pcmcia_device *p_dev)
+static void ide_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "ide_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- ide_release(link);
+ ide_release(link);
kfree(link->priv);
} /* ide_detach */
@@ -177,9 +168,8 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void ide_config(dev_link_t *link)
+static int ide_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
ide_info_t *info = link->priv;
tuple_t tuple;
struct {
@@ -203,34 +193,30 @@ static void ide_config(dev_link_t *link)
tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &stk->parse));
link->conf.ConfigBase = stk->parse.config.base;
link->conf.Present = stk->parse.config.rmask[0];
tuple.DesiredTuple = CISTPL_MANFID;
- if (!pcmcia_get_first_tuple(handle, &tuple) &&
- !pcmcia_get_tuple_data(handle, &tuple) &&
- !pcmcia_parse_tuple(handle, &tuple, &stk->parse))
+ if (!pcmcia_get_first_tuple(link, &tuple) &&
+ !pcmcia_get_tuple_data(link, &tuple) &&
+ !pcmcia_parse_tuple(link, &tuple, &stk->parse))
is_kme = ((stk->parse.manfid.manf == MANFID_KME) &&
((stk->parse.manfid.card == PRODID_KME_KXLC005_A) ||
(stk->parse.manfid.card == PRODID_KME_KXLC005_B)));
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Not sure if this is right... look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf));
- link->conf.Vcc = stk->conf.Vcc;
+ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
pass = io_base = ctl_base = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry;
- if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry;
+ if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
+ if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;
/* Check for matching Vcc, unless we're desperate */
if (!pass) {
@@ -244,10 +230,10 @@ static void ide_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
@@ -261,14 +247,14 @@ static void ide_config(dev_link_t *link)
link->io.NumPorts1 = 8;
link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = (is_kme) ? 2 : 1;
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
io_base = link->io.BasePort1;
ctl_base = link->io.BasePort2;
} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
link->io.NumPorts1 = io->win[0].len;
link->io.NumPorts2 = 0;
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
io_base = link->io.BasePort1;
ctl_base = link->io.BasePort1 + 0x0e;
@@ -281,16 +267,16 @@ static void ide_config(dev_link_t *link)
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
if (pass) {
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
- } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) {
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+ } else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
memset(&stk->dflt, 0, sizeof(stk->dflt));
pass++;
}
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/* disable drive interrupts during IDE probe */
outb(0x02, ctl_base);
@@ -301,12 +287,12 @@ static void ide_config(dev_link_t *link)
/* retry registration in case device is still spinning up */
for (hd = -1, i = 0; i < 10; i++) {
- hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, handle);
+ hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
if (hd >= 0) break;
if (link->io.NumPorts1 == 0x20) {
outb(0x02, ctl_base + 0x10);
hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
- link->irq.AssignedIRQ, handle);
+ link->irq.AssignedIRQ, link);
if (hd >= 0) {
io_base += 0x10;
ctl_base += 0x10;
@@ -328,25 +314,23 @@ static void ide_config(dev_link_t *link)
info->node.major = ide_major[hd];
info->node.minor = 0;
info->hd = hd;
- link->dev = &info->node;
- printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n",
- info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10,
- link->conf.Vpp1 / 10, link->conf.Vpp1 % 10);
+ link->dev_node = &info->node;
+ printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
+ info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
- link->state &= ~DEV_CONFIG_PENDING;
kfree(stk);
- return;
+ return 0;
err_mem:
printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
goto failed;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
kfree(stk);
ide_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
+ return -ENODEV;
} /* ide_config */
/*======================================================================
@@ -357,7 +341,7 @@ failed:
======================================================================*/
-void ide_release(dev_link_t *link)
+void ide_release(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
@@ -369,37 +353,10 @@ void ide_release(dev_link_t *link)
ide_unregister(info->hd);
}
info->ndev = 0;
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
} /* ide_release */
-static int ide_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int ide_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
-}
/*======================================================================
@@ -435,6 +392,7 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
+ PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b),
PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
@@ -459,11 +417,9 @@ static struct pcmcia_driver ide_cs_driver = {
.drv = {
.name = "ide-cs",
},
- .probe = ide_attach,
+ .probe = ide_probe,
.remove = ide_detach,
.id_table = ide_ids,
- .suspend = ide_suspend,
- .resume = ide_resume,
};
static int __init init_ide_cs(void)
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index cf84350efc5..8b24b4f2a83 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -731,6 +731,8 @@ static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
if(m5229_revision <= 0x20)
tmpbyte = (tmpbyte & (~0x02)) | 0x01;
+ else if (m5229_revision == 0xc7)
+ tmpbyte |= 0x03;
else
tmpbyte |= 0x01;
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 21965e5ef25..b22ee546231 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -347,10 +347,8 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
break;
case AMD_UDMA_66:
- pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
- for (i = 24; i >= 0; i -= 8)
- if ((u >> i) & 4)
- amd_80w |= (1 << (1 - (i >> 4)));
+ /* no host side cable detection */
+ amd_80w = 0x03;
break;
}
@@ -386,8 +384,6 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
if (amd_clock < 20000 || amd_clock > 50000) {
printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n",
amd_chipset->name, amd_clock);
- printk(KERN_WARNING "%s: Use ide0=ata66 if you want to assume 80-wire cable\n",
- amd_chipset->name);
amd_clock = 33333;
}
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index df9ee9a7843..900efd1da58 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -348,6 +348,7 @@ static struct pci_device_id atiixp_pci_tbl[] = {
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 6e3ab0c38c4..f82e8210972 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -41,14 +41,15 @@
static int ide_generic_all; /* Set to claim all devices */
+#ifndef MODULE
static int __init ide_generic_all_on(char *unused)
{
ide_generic_all = 1;
printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.\n");
return 1;
}
-
__setup("all-generic-ide", ide_generic_all_on);
+#endif
static void __devinit init_hwif_generic (ide_hwif_t *hwif)
{
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 6f8f8645b02..7ce5bf78368 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -798,7 +798,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
.autodma = AUTODMA,
.bootable = OFF_BOARD,
.extra = 48,
- .flags = IDEPCI_FLAG_FORCE_PDC,
},{ /* 2 */
.name = "PDC20263",
.init_setup = init_setup_pdc202ata4,
@@ -819,7 +818,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
.autodma = AUTODMA,
.bootable = OFF_BOARD,
.extra = 48,
- .flags = IDEPCI_FLAG_FORCE_PDC,
},{ /* 4 */
.name = "PDC20267",
.init_setup = init_setup_pdc202xx,
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 43b96e29836..27c9eb989a9 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -345,17 +345,17 @@ sgiioc4_resetproc(ide_drive_t * drive)
static u8
sgiioc4_INB(unsigned long port)
{
- u8 reg = (u8) inb(port);
+ u8 reg = (u8) readb((void __iomem *) port);
if ((port & 0xFFF) == 0x11C) { /* Status register of IOC4 */
if (reg & 0x51) { /* Not busy...check for interrupt */
unsigned long other_ir = port - 0x110;
- unsigned int intr_reg = (u32) inl(other_ir);
+ unsigned int intr_reg = (u32) readl((void __iomem *) other_ir);
/* Clear the Interrupt, Error bits on the IOC4 */
if (intr_reg & 0x03) {
- outl(0x03, other_ir);
- intr_reg = (u32) inl(other_ir);
+ writel(0x03, (void __iomem *) other_ir);
+ intr_reg = (u32) readl((void __iomem *) other_ir);
}
}
}
@@ -606,6 +606,12 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off;
hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
hwif->ide_dma_timeout = &__ide_dma_timeout;
+
+ /*
+ * The IOC4 uses MMIO rather than Port IO.
+ * It also needs special workarounds for INB.
+ */
+ default_hwif_mmiops(hwif);
hwif->INB = &sgiioc4_INB;
}
@@ -743,6 +749,6 @@ ioc4_ide_exit(void)
module_init(ioc4_ide_init);
module_exit(ioc4_ide_exit);
-MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)");
+MODULE_AUTHOR("Aniket Malatpure/Jeremy Higdon");
MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 75a2253a3e6..8e9d87701ce 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -112,6 +112,7 @@ static const struct {
{ "SiS5596", PCI_DEVICE_ID_SI_5596, ATA_16 },
{ "SiS5571", PCI_DEVICE_ID_SI_5571, ATA_16 },
+ { "SiS5517", PCI_DEVICE_ID_SI_5517, ATA_16 },
{ "SiS551x", PCI_DEVICE_ID_SI_5511, ATA_16 },
};
@@ -524,6 +525,7 @@ static void config_art_rwp_pio (ide_drive_t *drive, u8 pio)
case 3: test1 = 0x30|0x03; break;
case 2: test1 = 0x40|0x04; break;
case 1: test1 = 0x60|0x07; break;
+ case 0: test1 = 0x00; break;
default: break;
}
pci_write_config_byte(dev, drive_pci, test1);
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index c85b87cb59d..3e677c4f8c2 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -440,7 +440,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
#if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32)
- if(_machine == _MACH_chrp && _chrp_type == _CHRP_Pegasos) {
+ if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) {
hwif->irq = hwif->channel ? 15 : 14;
}
#endif
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 5013b1285e2..ffca8b63ee7 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -553,6 +553,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
if (irq != NULL)
*irq = pmac_ide[ix].irq;
+
+ hw->dev = &pmac_ide[ix].mdev->ofdev.dev;
}
#define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x)))
@@ -1677,7 +1679,7 @@ MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match);
void __init
pmac_ide_probe(void)
{
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return;
#ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 7ebf992e8c2..462ed3006c3 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -580,7 +580,6 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a
int port;
int at_least_one_hwif_enabled = 0;
ide_hwif_t *hwif, *mate = NULL;
- static int secondpdc = 0;
u8 tmp;
index->all = 0xf0f0;
@@ -592,21 +591,9 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a
for (port = 0; port <= 1; ++port) {
ide_pci_enablebit_t *e = &(d->enablebits[port]);
- /*
- * If this is a Promise FakeRaid controller,
- * the 2nd controller will be marked as
- * disabled while it is actually there and enabled
- * by the bios for raid purposes.
- * Skip the normal "is it enabled" test for those.
- */
- if ((d->flags & IDEPCI_FLAG_FORCE_PDC) &&
- (secondpdc++==1) && (port==1))
- goto controller_ok;
-
if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
(tmp & e->mask) != e->val))
continue; /* port not enabled */
-controller_ok:
if (d->channels <= port)
break;
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index efeaa944bd0..85c2d4ca0de 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -73,7 +73,7 @@
- fix all XXX showstoppers
- disable IR/IT DMA interrupts on shutdown
- flush pci writes to the card by issuing a read
- - devfs and character device dispatching (* needs testing with Linux 2.2.x)
+ - character device dispatching
- switch over to the new kernel DMA API (pci_map_*()) (* needs testing on platforms with IOMMU!)
- keep all video_cards in a list (for open() via chardev), set file->private_data = video
- dv1394_poll should indicate POLLIN when receiving buffers are available
@@ -1096,7 +1096,6 @@ static int do_dv1394_init_default(struct video_card *video)
init.api_version = DV1394_API_VERSION;
init.n_frames = DV1394_MAX_FRAMES / 4;
- /* the following are now set via devfs */
init.channel = video->channel;
init.format = video->pal_or_ntsc;
init.cip_n = video->cip_n;
@@ -1791,8 +1790,6 @@ static int dv1394_open(struct inode *inode, struct file *file)
{
struct video_card *video = NULL;
- /* if the device was opened through devfs, then file->private_data
- has already been set to video by devfs */
if (file->private_data) {
video = (struct video_card*) file->private_data;
@@ -2211,7 +2208,7 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
video = kzalloc(sizeof(*video), GFP_KERNEL);
if (!video) {
printk(KERN_ERR "dv1394: cannot allocate video_card\n");
- goto err;
+ return -1;
}
video->ohci = ohci;
@@ -2266,37 +2263,14 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
list_add_tail(&video->list, &dv1394_cards);
spin_unlock_irqrestore(&dv1394_cards_lock, flags);
- if (devfs_mk_cdev(MKDEV(IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_DV1394*16 + video->id),
- S_IFCHR|S_IRUGO|S_IWUGO,
- "ieee1394/dv/host%d/%s/%s",
- (video->id>>2),
- (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
- (video->mode == MODE_RECEIVE ? "in" : "out")) < 0)
- goto err_free;
-
debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id);
-
return 0;
-
- err_free:
- kfree(video);
- err:
- return -1;
}
static void dv1394_un_init(struct video_card *video)
{
- char buf[32];
-
/* obviously nobody has the driver open at this point */
do_dv1394_shutdown(video, 1);
- snprintf(buf, sizeof(buf), "dv/host%d/%s/%s", (video->id >> 2),
- (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
- (video->mode == MODE_RECEIVE ? "in" : "out")
- );
-
- devfs_remove("ieee1394/%s", buf);
kfree(video);
}
@@ -2333,9 +2307,6 @@ static void dv1394_remove_host (struct hpsb_host *host)
class_device_destroy(hpsb_protocol_class,
MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)));
- devfs_remove("ieee1394/dv/host%d/NTSC", id);
- devfs_remove("ieee1394/dv/host%d/PAL", id);
- devfs_remove("ieee1394/dv/host%d", id);
}
static void dv1394_add_host (struct hpsb_host *host)
@@ -2352,9 +2323,6 @@ static void dv1394_add_host (struct hpsb_host *host)
class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
NULL, "dv1394-%d", id);
- devfs_mk_dir("ieee1394/dv/host%d", id);
- devfs_mk_dir("ieee1394/dv/host%d/NTSC", id);
- devfs_mk_dir("ieee1394/dv/host%d/PAL", id);
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
@@ -2611,10 +2579,8 @@ MODULE_LICENSE("GPL");
static void __exit dv1394_exit_module(void)
{
hpsb_unregister_protocol(&dv1394_driver);
-
hpsb_unregister_highlevel(&dv1394_highlevel);
cdev_del(&dv1394_cdev);
- devfs_remove("ieee1394/dv");
}
static int __init dv1394_init_module(void)
@@ -2630,15 +2596,12 @@ static int __init dv1394_init_module(void)
return ret;
}
- devfs_mk_dir("ieee1394/dv");
-
hpsb_register_highlevel(&dv1394_highlevel);
ret = hpsb_register_protocol(&dv1394_driver);
if (ret) {
printk(KERN_ERR "dv1394: failed to register protocol\n");
hpsb_unregister_highlevel(&dv1394_highlevel);
- devfs_remove("ieee1394/dv");
cdev_del(&dv1394_cdev);
return ret;
}
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 25ef5a86f5f..be6854e25ad 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -58,7 +58,7 @@ MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
/* Disable Isochronous Resource Manager functionality */
int hpsb_disable_irm = 0;
-module_param_named(disable_irm, hpsb_disable_irm, bool, 0);
+module_param_named(disable_irm, hpsb_disable_irm, bool, 0444);
MODULE_PARM_DESC(disable_irm,
"Disable Isochronous Resource Manager functionality.");
@@ -1078,17 +1078,10 @@ static int __init ieee1394_init(void)
goto exit_release_kernel_thread;
}
- /* actually this is a non-fatal error */
- ret = devfs_mk_dir("ieee1394");
- if (ret < 0) {
- HPSB_ERR("unable to make devfs dir for device major %d!\n", IEEE1394_MAJOR);
- goto release_chrdev;
- }
-
ret = bus_register(&ieee1394_bus_type);
if (ret < 0) {
HPSB_INFO("bus register failed");
- goto release_devfs;
+ goto release_chrdev;
}
for (i = 0; fw_bus_attrs[i]; i++) {
@@ -1099,7 +1092,7 @@ static int __init ieee1394_init(void)
fw_bus_attrs[i--]);
}
bus_unregister(&ieee1394_bus_type);
- goto release_devfs;
+ goto release_chrdev;
}
}
@@ -1152,8 +1145,6 @@ release_all_bus:
for (i = 0; fw_bus_attrs[i]; i++)
bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
bus_unregister(&ieee1394_bus_type);
-release_devfs:
- devfs_remove("ieee1394");
release_chrdev:
unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
exit_release_kernel_thread:
@@ -1191,7 +1182,6 @@ static void __exit ieee1394_cleanup(void)
hpsb_cleanup_config_roms();
unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
- devfs_remove("ieee1394");
}
module_init(ieee1394_init);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index b35466023f0..e7b55e895f5 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -3,7 +3,6 @@
#define _IEEE1394_CORE_H
#include <linux/slab.h>
-#include <linux/devfs_fs_kernel.h>
#include <asm/atomic.h>
#include <asm/semaphore.h>
#include "hosts.h"
@@ -202,14 +201,12 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
#define IEEE1394_MINOR_BLOCK_RAW1394 0
#define IEEE1394_MINOR_BLOCK_VIDEO1394 1
#define IEEE1394_MINOR_BLOCK_DV1394 2
-#define IEEE1394_MINOR_BLOCK_AMDTP 3
#define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15
#define IEEE1394_CORE_DEV MKDEV(IEEE1394_MAJOR, 0)
#define IEEE1394_RAW1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)
#define IEEE1394_VIDEO1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
#define IEEE1394_DV1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16)
-#define IEEE1394_AMDTP_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_AMDTP * 16)
#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
/* return the index (within a minor number block) of a file */
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index b6b96fa04d6..11f13778f13 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -544,12 +544,19 @@ static void ohci_initialize(struct ti_ohci *ohci)
/* Initialize IR Legacy DMA channel mask */
ohci->ir_legacy_channels = 0;
- /*
- * Accept AT requests from all nodes. This probably
- * will have to be controlled from the subsystem
- * on a per node basis.
- */
- reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000);
+ /* Accept AR requests from all nodes */
+ reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
+
+ /* Set the address range of the physical response unit.
+ * Most controllers do not implement it as a writable register though.
+ * They will keep a hardwired offset of 0x00010000 and show 0x0 as
+ * register content.
+ * To actually enable physical responses is the job of our interrupt
+ * handler which programs the physical request filter. */
+ reg_write(ohci, OHCI1394_PhyUpperBound, 0x01000000);
+
+ DBGMSG("physUpperBoundOffset=%08x",
+ reg_read(ohci, OHCI1394_PhyUpperBound));
/* Specify AT retries */
reg_write(ohci, OHCI1394_ATRetries,
@@ -572,6 +579,7 @@ static void ohci_initialize(struct ti_ohci *ohci)
OHCI1394_reqTxComplete |
OHCI1394_isochRx |
OHCI1394_isochTx |
+ OHCI1394_postedWriteErr |
OHCI1394_cycleInconsistent);
/* Enable link */
@@ -2374,7 +2382,10 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
event &= ~OHCI1394_unrecoverableError;
}
-
+ if (event & OHCI1394_postedWriteErr) {
+ PRINT(KERN_ERR, "physical posted write error");
+ /* no recovery strategy yet, had to involve protocol drivers */
+ }
if (event & OHCI1394_cycleInconsistent) {
/* We subscribe to the cycleInconsistent event only to
* clear the corresponding event bit... otherwise,
@@ -2382,7 +2393,6 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
DBGMSG("OHCI1394_cycleInconsistent");
event &= ~OHCI1394_cycleInconsistent;
}
-
if (event & OHCI1394_busReset) {
/* The busReset event bit can't be cleared during the
* selfID phase, so we disable busReset interrupts, to
@@ -2426,7 +2436,6 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
}
event &= ~OHCI1394_busReset;
}
-
if (event & OHCI1394_reqTxComplete) {
struct dma_trm_ctx *d = &ohci->at_req_context;
DBGMSG("Got reqTxComplete interrupt "
@@ -2514,26 +2523,20 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
spin_unlock_irqrestore(&ohci->event_lock, flags);
- /* Accept Physical requests from all nodes. */
- reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0xffffffff);
- reg_write(ohci,OHCI1394_AsReqFilterLoSet, 0xffffffff);
-
/* Turn on phys dma reception.
*
* TODO: Enable some sort of filtering management.
*/
if (phys_dma) {
- reg_write(ohci,OHCI1394_PhyReqFilterHiSet, 0xffffffff);
- reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0xffffffff);
- reg_write(ohci,OHCI1394_PhyUpperBound, 0xffff0000);
- } else {
- reg_write(ohci,OHCI1394_PhyReqFilterHiSet, 0x00000000);
- reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0x00000000);
+ reg_write(ohci, OHCI1394_PhyReqFilterHiSet,
+ 0xffffffff);
+ reg_write(ohci, OHCI1394_PhyReqFilterLoSet,
+ 0xffffffff);
}
DBGMSG("PhyReqFilter=%08x%08x",
- reg_read(ohci,OHCI1394_PhyReqFilterHiSet),
- reg_read(ohci,OHCI1394_PhyReqFilterLoSet));
+ reg_read(ohci, OHCI1394_PhyReqFilterHiSet),
+ reg_read(ohci, OHCI1394_PhyReqFilterLoSet));
hpsb_selfid_complete(host, phyid, isroot);
} else
@@ -3259,8 +3262,8 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
* fail to report the right length. Anyway, the ohci spec
* clearly says it's 2kb, so this shouldn't be a problem. */
ohci_base = pci_resource_start(dev, 0);
- if (pci_resource_len(dev, 0) != OHCI1394_REGISTER_SIZE)
- PRINT(KERN_WARNING, "Unexpected PCI resource length of %lx!",
+ if (pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE)
+ PRINT(KERN_WARNING, "PCI resource length of %lx too small!",
pci_resource_len(dev, 0));
/* Seems PCMCIA handles this internally. Not sure why. Seems
@@ -3526,7 +3529,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
static int ohci1394_pci_resume (struct pci_dev *pdev)
{
#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
struct device_node *of_node;
/* Re-enable 1394 */
@@ -3545,7 +3548,7 @@ static int ohci1394_pci_resume (struct pci_dev *pdev)
static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
{
#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
struct device_node *of_node;
/* Disable 1394 */
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 19f26c5c947..f7de546f2ed 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -41,7 +41,6 @@
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/compat.h>
#include "csr1212.h"
@@ -2999,9 +2998,6 @@ static int __init init_raw1394(void)
goto out_unreg;
}
- devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
- S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
-
cdev_init(&raw1394_cdev, &raw1394_fops);
raw1394_cdev.owner = THIS_MODULE;
kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME);
@@ -3023,7 +3019,6 @@ static int __init init_raw1394(void)
goto out;
out_dev:
- devfs_remove(RAW1394_DEVICE_NAME);
class_device_destroy(hpsb_protocol_class,
MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_RAW1394 * 16));
@@ -3039,7 +3034,6 @@ static void __exit cleanup_raw1394(void)
MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_RAW1394 * 16));
cdev_del(&raw1394_cdev);
- devfs_remove(RAW1394_DEVICE_NAME);
hpsb_unregister_highlevel(&raw1394_highlevel);
hpsb_unregister_protocol(&raw1394_driver);
}
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index eca92eb475a..5413dc43b9f 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -42,6 +42,7 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/string.h>
+#include <linux/stringify.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
@@ -117,7 +118,8 @@ MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default
*/
static int max_sectors = SBP2_MAX_SECTORS;
module_param(max_sectors, int, 0444);
-MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = 255)");
+MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = "
+ __stringify(SBP2_MAX_SECTORS) ")");
/*
* Exclusive login to sbp2 device? In most cases, the sbp2 driver should
@@ -135,18 +137,45 @@ module_param(exclusive_login, int, 0644);
MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)");
/*
- * SCSI inquiry hack for really badly behaved sbp2 devices. Turn this on
- * if your sbp2 device is not properly handling the SCSI inquiry command.
- * This hack makes the inquiry look more like a typical MS Windows inquiry
- * by enforcing 36 byte inquiry and avoiding access to mode_sense page 8.
+ * If any of the following workarounds is required for your device to work,
+ * please submit the kernel messages logged by sbp2 to the linux1394-devel
+ * mailing list.
*
- * If force_inquiry_hack=1 is required for your device to work,
- * please submit the logged sbp2_firmware_revision value of this device to
- * the linux1394-devel mailing list.
+ * - 128kB max transfer
+ * Limit transfer size. Necessary for some old bridges.
+ *
+ * - 36 byte inquiry
+ * When scsi_mod probes the device, let the inquiry command look like that
+ * from MS Windows.
+ *
+ * - skip mode page 8
+ * Suppress sending of mode_sense for mode page 8 if the device pretends to
+ * support the SCSI Primary Block commands instead of Reduced Block Commands.
+ *
+ * - fix capacity
+ * Tell sd_mod to correct the last sector number reported by read_capacity.
+ * Avoids access beyond actual disk limits on devices with an off-by-one bug.
+ * Don't use this with devices which don't have this bug.
+ *
+ * - override internal blacklist
+ * Instead of adding to the built-in blacklist, use only the workarounds
+ * specified in the module load parameter.
+ * Useful if a blacklist entry interfered with a non-broken device.
*/
+static int sbp2_default_workarounds;
+module_param_named(workarounds, sbp2_default_workarounds, int, 0644);
+MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
+ ", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS)
+ ", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36)
+ ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
+ ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
+ ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
+ ", or a combination)");
+
+/* legacy parameter */
static int force_inquiry_hack;
module_param(force_inquiry_hack, int, 0644);
-MODULE_PARM_DESC(force_inquiry_hack, "Force SCSI inquiry hack (default = 0)");
+MODULE_PARM_DESC(force_inquiry_hack, "Deprecated, use 'workarounds'");
/*
* Export information about protocols/devices supported by this driver.
@@ -214,6 +243,7 @@ static u32 global_outstanding_dmas = 0;
#endif
#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
+#define SBP2_DEBUG_ENTER() SBP2_DEBUG("%s", __FUNCTION__)
/*
* Globals
@@ -265,14 +295,55 @@ static struct hpsb_protocol_driver sbp2_driver = {
};
/*
- * List of device firmwares that require the inquiry hack.
- * Yields a few false positives but did not break other devices so far.
+ * List of devices with known bugs.
+ *
+ * The firmware_revision field, masked with 0xffff00, is the best indicator
+ * for the type of bridge chip of a device. It yields a few false positives
+ * but this did not break correctly behaving devices so far.
*/
-static u32 sbp2_broken_inquiry_list[] = {
- 0x00002800, /* Stefan Richter <stefanr@s5r6.in-berlin.de> */
- /* DViCO Momobay CX-1 */
- 0x00000200 /* Andreas Plesch <plesch@fas.harvard.edu> */
- /* QPS Fire DVDBurner */
+static const struct {
+ u32 firmware_revision;
+ u32 model_id;
+ unsigned workarounds;
+} sbp2_workarounds_table[] = {
+ /* TSB42AA9 */ {
+ .firmware_revision = 0x002800,
+ .workarounds = SBP2_WORKAROUND_INQUIRY_36 |
+ SBP2_WORKAROUND_MODE_SENSE_8,
+ },
+ /* Initio bridges, actually only needed for some older ones */ {
+ .firmware_revision = 0x000200,
+ .workarounds = SBP2_WORKAROUND_INQUIRY_36,
+ },
+ /* Symbios bridge */ {
+ .firmware_revision = 0xa0b800,
+ .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS,
+ },
+ /*
+ * Note about the following Apple iPod blacklist entries:
+ *
+ * There are iPods (2nd gen, 3rd gen) with model_id==0. Since our
+ * matching logic treats 0 as a wildcard, we cannot match this ID
+ * without rewriting the matching routine. Fortunately these iPods
+ * do not feature the read_capacity bug according to one report.
+ * Read_capacity behaviour as well as model_id could change due to
+ * Apple-supplied firmware updates though.
+ */
+ /* iPod 4th generation */ {
+ .firmware_revision = 0x0a2700,
+ .model_id = 0x000021,
+ .workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
+ },
+ /* iPod mini */ {
+ .firmware_revision = 0x0a2700,
+ .model_id = 0x000023,
+ .workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
+ },
+ /* iPod Photo */ {
+ .firmware_revision = 0x0a2700,
+ .model_id = 0x00007e,
+ .workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
+ }
};
/**************************************
@@ -495,22 +566,17 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb(
/*
* This function finds the sbp2_command for a given outstanding SCpnt.
* Only looks at the inuse list.
+ * Must be called with scsi_id->sbp2_command_orb_lock held.
*/
-static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt)
+static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(
+ struct scsi_id_instance_data *scsi_id, void *SCpnt)
{
struct sbp2_command_info *command;
- unsigned long flags;
- spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
- if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
- list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
- if (command->Current_SCpnt == SCpnt) {
- spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+ if (!list_empty(&scsi_id->sbp2_command_orb_inuse))
+ list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list)
+ if (command->Current_SCpnt == SCpnt)
return command;
- }
- }
- }
- spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
return NULL;
}
@@ -535,7 +601,7 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
command->Current_SCpnt = Current_SCpnt;
list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse);
} else {
- SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");
+ SBP2_ERR("%s: no orbs available", __FUNCTION__);
}
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
return command;
@@ -549,7 +615,7 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command)
struct hpsb_host *host;
if (!scsi_id) {
- printk(KERN_ERR "%s: scsi_id == NULL\n", __FUNCTION__);
+ SBP2_ERR("%s: scsi_id == NULL", __FUNCTION__);
return;
}
@@ -579,17 +645,15 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command)
/*
* This function moves a command to the completed orb list.
+ * Must be called with scsi_id->sbp2_command_orb_lock held.
*/
-static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
- struct sbp2_command_info *command)
+static void sbp2util_mark_command_completed(
+ struct scsi_id_instance_data *scsi_id,
+ struct sbp2_command_info *command)
{
- unsigned long flags;
-
- spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
list_del(&command->list);
sbp2util_free_command_dma(command);
list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
- spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
}
/*
@@ -610,7 +674,7 @@ static int sbp2_probe(struct device *dev)
struct unit_directory *ud;
struct scsi_id_instance_data *scsi_id;
- SBP2_DEBUG("sbp2_probe");
+ SBP2_DEBUG_ENTER();
ud = container_of(dev, struct unit_directory, device);
@@ -635,7 +699,7 @@ static int sbp2_remove(struct device *dev)
struct scsi_id_instance_data *scsi_id;
struct scsi_device *sdev;
- SBP2_DEBUG("sbp2_remove");
+ SBP2_DEBUG_ENTER();
ud = container_of(dev, struct unit_directory, device);
scsi_id = ud->device.driver_data;
@@ -667,7 +731,7 @@ static int sbp2_update(struct unit_directory *ud)
{
struct scsi_id_instance_data *scsi_id = ud->device.driver_data;
- SBP2_DEBUG("sbp2_update");
+ SBP2_DEBUG_ENTER();
if (sbp2_reconnect_device(scsi_id)) {
@@ -715,7 +779,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
struct Scsi_Host *scsi_host = NULL;
struct scsi_id_instance_data *scsi_id = NULL;
- SBP2_DEBUG("sbp2_alloc_device");
+ SBP2_DEBUG_ENTER();
scsi_id = kzalloc(sizeof(*scsi_id), GFP_KERNEL);
if (!scsi_id) {
@@ -749,24 +813,39 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
/* Handle data movement if physical dma is not
- * enabled/supportedon host controller */
- hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_physdma_ops,
- 0x0ULL, 0xfffffffcULL);
+ * enabled or not supported on host controller */
+ if (!hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host,
+ &sbp2_physdma_ops,
+ 0x0ULL, 0xfffffffcULL)) {
+ SBP2_ERR("failed to register lower 4GB address range");
+ goto failed_alloc;
+ }
#endif
}
+ /* Prevent unloading of the 1394 host */
+ if (!try_module_get(hi->host->driver->owner)) {
+ SBP2_ERR("failed to get a reference on 1394 host driver");
+ goto failed_alloc;
+ }
+
scsi_id->hi = hi;
list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);
/* Register the status FIFO address range. We could use the same FIFO
* for targets at different nodes. However we need different FIFOs per
- * target in order to support multi-unit devices. */
+ * target in order to support multi-unit devices.
+ * The FIFO is located out of the local host controller's physical range
+ * but, if possible, within the posted write area. Status writes will
+ * then be performed as unified transactions. This slightly reduces
+ * bandwidth usage, and some Prolific based devices seem to require it.
+ */
scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace(
&sbp2_highlevel, ud->ne->host, &sbp2_ops,
sizeof(struct sbp2_status_block), sizeof(quadlet_t),
- ~0ULL, ~0ULL);
- if (!scsi_id->status_fifo_addr) {
+ 0x010000000000ULL, CSR1212_ALL_SPACE_END);
+ if (scsi_id->status_fifo_addr == ~0ULL) {
SBP2_ERR("failed to allocate status FIFO address range");
goto failed_alloc;
}
@@ -816,7 +895,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
struct sbp2scsi_host_info *hi = scsi_id->hi;
int error;
- SBP2_DEBUG("sbp2_start_device");
+ SBP2_DEBUG_ENTER();
/* Login FIFO DMA */
scsi_id->login_response =
@@ -891,7 +970,6 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
* allows someone else to login instead. One second makes sense. */
msleep_interruptible(1000);
if (signal_pending(current)) {
- SBP2_WARN("aborting sbp2_start_device due to event");
sbp2_remove_device(scsi_id);
return -EINTR;
}
@@ -944,7 +1022,7 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
{
struct sbp2scsi_host_info *hi;
- SBP2_DEBUG("sbp2_remove_device");
+ SBP2_DEBUG_ENTER();
if (!scsi_id)
return;
@@ -1015,6 +1093,9 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
scsi_id->ud->device.driver_data = NULL;
+ if (hi)
+ module_put(hi->host->driver->owner);
+
SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id);
kfree(scsi_id);
@@ -1073,23 +1154,20 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
int max_logins;
int active_logins;
- SBP2_DEBUG("sbp2_query_logins");
+ SBP2_DEBUG_ENTER();
scsi_id->query_logins_orb->reserved1 = 0x0;
scsi_id->query_logins_orb->reserved2 = 0x0;
scsi_id->query_logins_orb->query_response_lo = scsi_id->query_logins_response_dma;
scsi_id->query_logins_orb->query_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
- SBP2_DEBUG("sbp2_query_logins: query_response_hi/lo initialized");
scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST);
scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);
scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
- SBP2_DEBUG("sbp2_query_logins: lun_misc initialized");
scsi_id->query_logins_orb->reserved_resp_length =
ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response));
- SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized");
scsi_id->query_logins_orb->status_fifo_hi =
ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
@@ -1098,25 +1176,19 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb));
- SBP2_DEBUG("sbp2_query_logins: orb byte-swapped");
-
sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb),
"sbp2 query logins orb", scsi_id->query_logins_orb_dma);
memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response));
memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
- SBP2_DEBUG("sbp2_query_logins: query_logins_response/status FIFO memset");
-
data[0] = ORB_SET_NODE_ID(hi->host->node_id);
data[1] = scsi_id->query_logins_orb_dma;
sbp2util_cpu_to_be32_buffer(data, 8);
atomic_set(&scsi_id->sbp2_login_complete, 0);
- SBP2_DEBUG("sbp2_query_logins: prepared to write");
hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
- SBP2_DEBUG("sbp2_query_logins: written");
if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) {
SBP2_INFO("Error querying logins to SBP-2 device - timed out");
@@ -1165,10 +1237,10 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
struct sbp2scsi_host_info *hi = scsi_id->hi;
quadlet_t data[2];
- SBP2_DEBUG("sbp2_login_device");
+ SBP2_DEBUG_ENTER();
if (!scsi_id->login_orb) {
- SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!");
+ SBP2_DEBUG("%s: login_orb not alloc'd!", __FUNCTION__);
return -EIO;
}
@@ -1182,59 +1254,39 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
/* Set-up login ORB, assume no password */
scsi_id->login_orb->password_hi = 0;
scsi_id->login_orb->password_lo = 0;
- SBP2_DEBUG("sbp2_login_device: password_hi/lo initialized");
scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma;
scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
- SBP2_DEBUG("sbp2_login_device: login_response_hi/lo initialized");
scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST);
scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0); /* One second reconnect time */
scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login); /* Exclusive access to device */
scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1); /* Notify us of login complete */
scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
- SBP2_DEBUG("sbp2_login_device: lun_misc initialized");
scsi_id->login_orb->passwd_resp_lengths =
ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
- SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized");
scsi_id->login_orb->status_fifo_hi =
ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
scsi_id->login_orb->status_fifo_lo =
ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
- /*
- * Byte swap ORB if necessary
- */
sbp2util_cpu_to_be32_buffer(scsi_id->login_orb, sizeof(struct sbp2_login_orb));
- SBP2_DEBUG("sbp2_login_device: orb byte-swapped");
-
sbp2util_packet_dump(scsi_id->login_orb, sizeof(struct sbp2_login_orb),
"sbp2 login orb", scsi_id->login_orb_dma);
- /*
- * Initialize login response and status fifo
- */
memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response));
memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
- SBP2_DEBUG("sbp2_login_device: login_response/status FIFO memset");
-
- /*
- * Ok, let's write to the target's management agent register
- */
data[0] = ORB_SET_NODE_ID(hi->host->node_id);
data[1] = scsi_id->login_orb_dma;
sbp2util_cpu_to_be32_buffer(data, 8);
atomic_set(&scsi_id->sbp2_login_complete, 0);
- SBP2_DEBUG("sbp2_login_device: prepared to write to %08x",
- (unsigned int)scsi_id->sbp2_management_agent_addr);
hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
- SBP2_DEBUG("sbp2_login_device: written");
/*
* Wait for login status (up to 20 seconds)...
@@ -1298,7 +1350,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
quadlet_t data[2];
int error;
- SBP2_DEBUG("sbp2_logout_device");
+ SBP2_DEBUG_ENTER();
/*
* Set-up logout ORB
@@ -1362,7 +1414,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
quadlet_t data[2];
int error;
- SBP2_DEBUG("sbp2_reconnect_device");
+ SBP2_DEBUG_ENTER();
/*
* Set-up reconnect ORB
@@ -1453,17 +1505,11 @@ static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id)
{
quadlet_t data;
- SBP2_DEBUG("sbp2_set_busy_timeout");
+ SBP2_DEBUG_ENTER();
- /*
- * Ok, let's write to the target's busy timeout register
- */
data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
-
- if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {
- SBP2_ERR("sbp2_set_busy_timeout error");
- }
-
+ if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4))
+ SBP2_ERR("%s error", __FUNCTION__);
return 0;
}
@@ -1479,10 +1525,11 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
struct csr1212_dentry *dentry;
u64 management_agent_addr;
u32 command_set_spec_id, command_set, unit_characteristics,
- firmware_revision, workarounds;
+ firmware_revision;
+ unsigned workarounds;
int i;
- SBP2_DEBUG("sbp2_parse_unit_directory");
+ SBP2_DEBUG_ENTER();
management_agent_addr = 0x0;
command_set_spec_id = 0x0;
@@ -1535,12 +1582,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
case SBP2_FIRMWARE_REVISION_KEY:
/* Firmware revision */
firmware_revision = kv->value.immediate;
- if (force_inquiry_hack)
- SBP2_INFO("sbp2_firmware_revision = %x",
- (unsigned int)firmware_revision);
- else
- SBP2_DEBUG("sbp2_firmware_revision = %x",
- (unsigned int)firmware_revision);
+ SBP2_DEBUG("sbp2_firmware_revision = %x",
+ (unsigned int)firmware_revision);
break;
default:
@@ -1548,41 +1591,44 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
}
}
- /* This is the start of our broken device checking. We try to hack
- * around oddities and known defects. */
- workarounds = 0x0;
+ workarounds = sbp2_default_workarounds;
+ if (force_inquiry_hack) {
+ SBP2_WARN("force_inquiry_hack is deprecated. "
+ "Use parameter 'workarounds' instead.");
+ workarounds |= SBP2_WORKAROUND_INQUIRY_36;
+ }
- /* If the vendor id is 0xa0b8 (Symbios vendor id), then we have a
- * bridge with 128KB max transfer size limitation. For sanity, we
- * only voice this when the current max_sectors setting
- * exceeds the 128k limit. By default, that is not the case.
- *
- * It would be really nice if we could detect this before the scsi
- * host gets initialized. That way we can down-force the
- * max_sectors to account for it. That is not currently
- * possible. */
- if ((firmware_revision & 0xffff00) ==
- SBP2_128KB_BROKEN_FIRMWARE &&
- (max_sectors * 512) > (128*1024)) {
- SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB max transfer size.",
- NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));
- SBP2_WARN("WARNING: Current max_sectors setting is larger than 128KB (%d sectors)!",
- max_sectors);
- workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER;
- }
-
- /* Check for a blacklisted set of devices that require us to force
- * a 36 byte host inquiry. This can be overriden as a module param
- * (to force all hosts). */
- for (i = 0; i < ARRAY_SIZE(sbp2_broken_inquiry_list); i++) {
- if ((firmware_revision & 0xffff00) ==
- sbp2_broken_inquiry_list[i]) {
- SBP2_WARN("Node " NODE_BUS_FMT ": Using 36byte inquiry workaround",
- NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));
- workarounds |= SBP2_BREAKAGE_INQUIRY_HACK;
- break; /* No need to continue. */
+ if (!(workarounds & SBP2_WORKAROUND_OVERRIDE))
+ for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
+ if (sbp2_workarounds_table[i].firmware_revision &&
+ sbp2_workarounds_table[i].firmware_revision !=
+ (firmware_revision & 0xffff00))
+ continue;
+ if (sbp2_workarounds_table[i].model_id &&
+ sbp2_workarounds_table[i].model_id != ud->model_id)
+ continue;
+ workarounds |= sbp2_workarounds_table[i].workarounds;
+ break;
}
- }
+
+ if (workarounds)
+ SBP2_INFO("Workarounds for node " NODE_BUS_FMT ": 0x%x "
+ "(firmware_revision 0x%06x, vendor_id 0x%06x,"
+ " model_id 0x%06x)",
+ NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
+ workarounds, firmware_revision,
+ ud->vendor_id ? ud->vendor_id : ud->ne->vendor_id,
+ ud->model_id);
+
+ /* We would need one SCSI host template for each target to adjust
+ * max_sectors on the fly, therefore warn only. */
+ if (workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
+ (max_sectors * 512) > (128 * 1024))
+ SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB "
+ "max transfer size. WARNING: Current max_sectors "
+ "setting is larger than 128KB (%d sectors)",
+ NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
+ max_sectors);
/* If this is a logical unit directory entry, process the parent
* to get the values. */
@@ -1615,7 +1661,7 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
{
struct sbp2scsi_host_info *hi = scsi_id->hi;
- SBP2_DEBUG("sbp2_max_speed_and_size");
+ SBP2_DEBUG_ENTER();
/* Initial setting comes from the hosts speed map */
scsi_id->speed_code =
@@ -1652,11 +1698,8 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
u64 addr;
int retval;
- SBP2_DEBUG("sbp2_agent_reset");
+ SBP2_DEBUG_ENTER();
- /*
- * Ok, let's write to the target's management agent register
- */
data = ntohl(SBP2_AGENT_RESET_DATA);
addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET;
@@ -2004,11 +2047,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
unsigned int request_bufflen = SCpnt->request_bufflen;
struct sbp2_command_info *command;
- SBP2_DEBUG("sbp2_send_command");
-#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP)
- printk("[scsi command]\n ");
- scsi_print_command(SCpnt);
-#endif
+ SBP2_DEBUG_ENTER();
SBP2_DEBUG("SCSI transfer size = %x", request_bufflen);
SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
@@ -2048,7 +2087,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
*/
static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data)
{
- SBP2_DEBUG("sbp2_status_to_sense_data");
+ SBP2_DEBUG_ENTER();
/*
* Ok, it's pretty ugly... ;-)
@@ -2082,7 +2121,7 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
{
u8 *scsi_buf = SCpnt->request_buffer;
- SBP2_DEBUG("sbp2_check_sbp2_response");
+ SBP2_DEBUG_ENTER();
if (SCpnt->cmnd[0] == INQUIRY && (SCpnt->cmnd[1] & 3) == 0) {
/*
@@ -2113,7 +2152,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
struct sbp2_command_info *command;
unsigned long flags;
- SBP2_DEBUG("sbp2_handle_status_write");
+ SBP2_DEBUG_ENTER();
sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr);
@@ -2177,7 +2216,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
* Matched status with command, now grab scsi command pointers and check status
*/
SCpnt = command->Current_SCpnt;
+ spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
sbp2util_mark_command_completed(scsi_id, command);
+ spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
if (SCpnt) {
@@ -2260,7 +2301,10 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
struct sbp2scsi_host_info *hi;
int result = DID_NO_CONNECT << 16;
- SBP2_DEBUG("sbp2scsi_queuecommand");
+ SBP2_DEBUG_ENTER();
+#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP)
+ scsi_print_command(SCpnt);
+#endif
if (!sbp2util_node_is_available(scsi_id))
goto done;
@@ -2338,7 +2382,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
struct sbp2_command_info *command;
unsigned long flags;
- SBP2_DEBUG("sbp2scsi_complete_all_commands");
+ SBP2_DEBUG_ENTER();
spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
@@ -2371,7 +2415,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
u32 scsi_status, struct scsi_cmnd *SCpnt,
void (*done)(struct scsi_cmnd *))
{
- SBP2_DEBUG("sbp2scsi_complete_command");
+ SBP2_DEBUG_ENTER();
/*
* Sanity
@@ -2397,7 +2441,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
*/
switch (scsi_status) {
case SBP2_SCSI_STATUS_GOOD:
- SCpnt->result = DID_OK;
+ SCpnt->result = DID_OK << 16;
break;
case SBP2_SCSI_STATUS_BUSY:
@@ -2407,16 +2451,11 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
case SBP2_SCSI_STATUS_CHECK_CONDITION:
SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
- SCpnt->result = CHECK_CONDITION << 1;
-
- /*
- * Debug stuff
- */
+ SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16;
#if CONFIG_IEEE1394_SBP2_DEBUG >= 1
scsi_print_command(SCpnt);
- scsi_print_sense("bh", SCpnt);
+ scsi_print_sense(SBP2_DEVICE_NAME, SCpnt);
#endif
-
break;
case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
@@ -2441,7 +2480,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
/*
* Take care of any sbp2 response data mucking here (RBC stuff, etc.)
*/
- if (SCpnt->result == DID_OK) {
+ if (SCpnt->result == DID_OK << 16) {
sbp2_check_sbp2_response(scsi_id, SCpnt);
}
@@ -2459,6 +2498,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
* If a unit attention occurs, return busy status so it gets
* retried... it could have happened because of a 1394 bus reset
* or hot-plug...
+ * XXX DID_BUS_BUSY is actually a bad idea because it will defy
+ * the scsi layer's retry logic.
*/
#if 0
if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) &&
@@ -2481,19 +2522,25 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
scsi_id->sdev = sdev;
- if (force_inquiry_hack ||
- scsi_id->workarounds & SBP2_BREAKAGE_INQUIRY_HACK) {
+ if (scsi_id->workarounds & SBP2_WORKAROUND_INQUIRY_36)
sdev->inquiry_len = 36;
- sdev->skip_ms_page_8 = 1;
- }
return 0;
}
static int sbp2scsi_slave_configure(struct scsi_device *sdev)
{
+ struct scsi_id_instance_data *scsi_id =
+ (struct scsi_id_instance_data *)sdev->host->hostdata[0];
+
blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
sdev->use_10_for_rw = 1;
sdev->use_10_for_ms = 1;
+
+ if (sdev->type == TYPE_DISK &&
+ scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
+ sdev->skip_ms_page_8 = 1;
+ if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
+ sdev->fix_capacity = 1;
return 0;
}
@@ -2513,6 +2560,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
struct sbp2scsi_host_info *hi = scsi_id->hi;
struct sbp2_command_info *command;
+ unsigned long flags;
SBP2_ERR("aborting sbp2 command");
scsi_print_command(SCpnt);
@@ -2523,6 +2571,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
* Right now, just return any matching command structures
* to the free pool.
*/
+ spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
if (command) {
SBP2_DEBUG("Found command to abort");
@@ -2540,6 +2589,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
command->Current_done(command->Current_SCpnt);
}
}
+ spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
/*
* Initiate a fetch agent reset.
@@ -2624,7 +2674,7 @@ static int sbp2_module_init(void)
{
int ret;
- SBP2_DEBUG("sbp2_module_init");
+ SBP2_DEBUG_ENTER();
/* Module load debug option to force one command at a time (serializing I/O) */
if (serialize_io) {
@@ -2634,7 +2684,9 @@ static int sbp2_module_init(void)
scsi_driver_template.cmd_per_lun = 1;
}
- /* Set max sectors (module load option). Default is 255 sectors. */
+ if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
+ (max_sectors * 512) > (128 * 1024))
+ max_sectors = 128 * 1024 / 512;
scsi_driver_template.max_sectors = max_sectors;
/* Register our high level driver with 1394 stack */
@@ -2652,7 +2704,7 @@ static int sbp2_module_init(void)
static void __exit sbp2_module_exit(void)
{
- SBP2_DEBUG("sbp2_module_exit");
+ SBP2_DEBUG_ENTER();
hpsb_unregister_protocol(&sbp2_driver);
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index e2d357a9ea3..f4ccc9d0fba 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -227,11 +227,6 @@ struct sbp2_status_block {
#define SBP2_SW_VERSION_ENTRY 0x00010483
/*
- * Other misc defines
- */
-#define SBP2_128KB_BROKEN_FIRMWARE 0xa0b800
-
-/*
* SCSI specific stuff
*/
@@ -239,6 +234,13 @@ struct sbp2_status_block {
#define SBP2_MAX_SECTORS 255 /* Max sectors supported */
#define SBP2_MAX_CMDS 8 /* This should be safe */
+/* Flags for detected oddities and brokeness */
+#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
+#define SBP2_WORKAROUND_INQUIRY_36 0x2
+#define SBP2_WORKAROUND_MODE_SENSE_8 0x4
+#define SBP2_WORKAROUND_FIX_CAPACITY 0x8
+#define SBP2_WORKAROUND_OVERRIDE 0x100
+
/* This is the two dma types we use for cmd_dma below */
enum cmd_dma_types {
CMD_DMA_NONE,
@@ -268,10 +270,6 @@ struct sbp2_command_info {
};
-/* A list of flags for detected oddities and brokeness. */
-#define SBP2_BREAKAGE_128K_MAX_TRANSFER 0x1
-#define SBP2_BREAKAGE_INQUIRY_HACK 0x2
-
struct sbp2scsi_host_info;
/*
@@ -345,7 +343,7 @@ struct scsi_id_instance_data {
struct Scsi_Host *scsi_host;
/* Device specific workarounds/brokeness */
- u32 workarounds;
+ unsigned workarounds;
};
/* Sbp2 host data structure (one per IEEE1394 host) */
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 216dbbf1dc8..4e3bd62c458 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -42,7 +42,6 @@
#include <linux/poll.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/vmalloc.h>
@@ -1322,9 +1321,6 @@ static void video1394_add_host (struct hpsb_host *host)
class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, minor),
NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
- devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
- S_IFCHR | S_IRUSR | S_IWUSR,
- "%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
}
@@ -1332,12 +1328,9 @@ static void video1394_remove_host (struct hpsb_host *host)
{
struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
- if (ohci) {
+ if (ohci)
class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
- devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
- }
-
return;
}
@@ -1478,12 +1471,8 @@ static long video1394_compat_ioctl(struct file *f, unsigned cmd, unsigned long a
static void __exit video1394_exit_module (void)
{
hpsb_unregister_protocol(&video1394_driver);
-
hpsb_unregister_highlevel(&video1394_highlevel);
-
- devfs_remove(VIDEO1394_DRIVER_NAME);
cdev_del(&video1394_cdev);
-
PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module");
}
@@ -1500,15 +1489,12 @@ static int __init video1394_init_module (void)
return ret;
}
- devfs_mk_dir(VIDEO1394_DRIVER_NAME);
-
hpsb_register_highlevel(&video1394_highlevel);
ret = hpsb_register_protocol(&video1394_driver);
if (ret) {
PRINT_G(KERN_ERR, "video1394: failed to register protocol");
hpsb_unregister_highlevel(&video1394_highlevel);
- devfs_remove(VIDEO1394_DRIVER_NAME);
cdev_del(&video1394_cdev);
return ret;
}
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index bdf0891a92d..afc612b8577 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -30,6 +30,7 @@ config INFINIBAND_USER_ACCESS
<http://www.openib.org>.
source "drivers/infiniband/hw/mthca/Kconfig"
+source "drivers/infiniband/hw/ipath/Kconfig"
source "drivers/infiniband/ulp/ipoib/Kconfig"
diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile
index a43fb34cca9..eea27322a22 100644
--- a/drivers/infiniband/Makefile
+++ b/drivers/infiniband/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_INFINIBAND) += core/
obj-$(CONFIG_INFINIBAND_MTHCA) += hw/mthca/
+obj-$(CONFIG_IPATH_CORE) += hw/ipath/
obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/
obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index c57a3871184..50364c0b090 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -302,7 +302,7 @@ static void ib_cache_setup_one(struct ib_device *device)
kmalloc(sizeof *device->cache.pkey_cache *
(end_port(device) - start_port(device) + 1), GFP_KERNEL);
device->cache.gid_cache =
- kmalloc(sizeof *device->cache.pkey_cache *
+ kmalloc(sizeof *device->cache.gid_cache *
(end_port(device) - start_port(device) + 1), GFP_KERNEL);
if (!device->cache.pkey_cache || !device->cache.gid_cache) {
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 7cfedb8d9bc..86fee43502c 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -34,6 +34,8 @@
*
* $Id: cm.c 2821 2005-07-08 17:07:28Z sean.hefty $
*/
+
+#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/idr.h>
@@ -122,7 +124,7 @@ struct cm_id_private {
struct rb_node service_node;
struct rb_node sidr_id_node;
spinlock_t lock; /* Do not acquire inside cm.lock */
- wait_queue_head_t wait;
+ struct completion comp;
atomic_t refcount;
struct ib_mad_send_buf *msg;
@@ -159,7 +161,7 @@ static void cm_work_handler(void *data);
static inline void cm_deref_id(struct cm_id_private *cm_id_priv)
{
if (atomic_dec_and_test(&cm_id_priv->refcount))
- wake_up(&cm_id_priv->wait);
+ complete(&cm_id_priv->comp);
}
static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
@@ -559,7 +561,7 @@ struct ib_cm_id *ib_create_cm_id(struct ib_device *device,
goto error;
spin_lock_init(&cm_id_priv->lock);
- init_waitqueue_head(&cm_id_priv->wait);
+ init_completion(&cm_id_priv->comp);
INIT_LIST_HEAD(&cm_id_priv->work_list);
atomic_set(&cm_id_priv->work_count, -1);
atomic_set(&cm_id_priv->refcount, 1);
@@ -724,8 +726,8 @@ retest:
}
cm_free_id(cm_id->local_id);
- atomic_dec(&cm_id_priv->refcount);
- wait_event(cm_id_priv->wait, !atomic_read(&cm_id_priv->refcount));
+ cm_deref_id(cm_id_priv);
+ wait_for_completion(&cm_id_priv->comp);
while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
cm_free_work(work);
if (cm_id_priv->private_data && cm_id_priv->private_data_len)
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index f7854b65fd5..5ad41a64314 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -227,6 +227,11 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
if (!is_vendor_oui(mad_reg_req->oui))
goto error1;
}
+ /* Make sure class supplied is consistent with RMPP */
+ if (!ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) {
+ if (rmpp_version)
+ goto error1;
+ }
/* Make sure class supplied is consistent with QP type */
if (qp_type == IB_QPT_SMI) {
if ((mad_reg_req->mgmt_class !=
@@ -347,7 +352,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
INIT_WORK(&mad_agent_priv->local_work, local_completions,
mad_agent_priv);
atomic_set(&mad_agent_priv->refcount, 1);
- init_waitqueue_head(&mad_agent_priv->wait);
+ init_completion(&mad_agent_priv->comp);
return &mad_agent_priv->agent;
@@ -462,7 +467,7 @@ struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,
mad_snoop_priv->agent.qp = port_priv->qp_info[qpn].qp;
mad_snoop_priv->agent.port_num = port_num;
mad_snoop_priv->mad_snoop_flags = mad_snoop_flags;
- init_waitqueue_head(&mad_snoop_priv->wait);
+ init_completion(&mad_snoop_priv->comp);
mad_snoop_priv->snoop_index = register_snoop_agent(
&port_priv->qp_info[qpn],
mad_snoop_priv);
@@ -481,6 +486,18 @@ error1:
}
EXPORT_SYMBOL(ib_register_mad_snoop);
+static inline void deref_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
+{
+ if (atomic_dec_and_test(&mad_agent_priv->refcount))
+ complete(&mad_agent_priv->comp);
+}
+
+static inline void deref_snoop_agent(struct ib_mad_snoop_private *mad_snoop_priv)
+{
+ if (atomic_dec_and_test(&mad_snoop_priv->refcount))
+ complete(&mad_snoop_priv->comp);
+}
+
static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
{
struct ib_mad_port_private *port_priv;
@@ -504,9 +521,8 @@ static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
flush_workqueue(port_priv->wq);
ib_cancel_rmpp_recvs(mad_agent_priv);
- atomic_dec(&mad_agent_priv->refcount);
- wait_event(mad_agent_priv->wait,
- !atomic_read(&mad_agent_priv->refcount));
+ deref_mad_agent(mad_agent_priv);
+ wait_for_completion(&mad_agent_priv->comp);
kfree(mad_agent_priv->reg_req);
ib_dereg_mr(mad_agent_priv->agent.mr);
@@ -524,9 +540,8 @@ static void unregister_mad_snoop(struct ib_mad_snoop_private *mad_snoop_priv)
atomic_dec(&qp_info->snoop_count);
spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
- atomic_dec(&mad_snoop_priv->refcount);
- wait_event(mad_snoop_priv->wait,
- !atomic_read(&mad_snoop_priv->refcount));
+ deref_snoop_agent(mad_snoop_priv);
+ wait_for_completion(&mad_snoop_priv->comp);
kfree(mad_snoop_priv);
}
@@ -595,8 +610,7 @@ static void snoop_send(struct ib_mad_qp_info *qp_info,
spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
mad_snoop_priv->agent.snoop_handler(&mad_snoop_priv->agent,
send_buf, mad_send_wc);
- if (atomic_dec_and_test(&mad_snoop_priv->refcount))
- wake_up(&mad_snoop_priv->wait);
+ deref_snoop_agent(mad_snoop_priv);
spin_lock_irqsave(&qp_info->snoop_lock, flags);
}
spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
@@ -621,8 +635,7 @@ static void snoop_recv(struct ib_mad_qp_info *qp_info,
spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
mad_snoop_priv->agent.recv_handler(&mad_snoop_priv->agent,
mad_recv_wc);
- if (atomic_dec_and_test(&mad_snoop_priv->refcount))
- wake_up(&mad_snoop_priv->wait);
+ deref_snoop_agent(mad_snoop_priv);
spin_lock_irqsave(&qp_info->snoop_lock, flags);
}
spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
@@ -890,6 +903,35 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
}
EXPORT_SYMBOL(ib_create_send_mad);
+int ib_get_mad_data_offset(u8 mgmt_class)
+{
+ if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
+ return IB_MGMT_SA_HDR;
+ else if ((mgmt_class == IB_MGMT_CLASS_DEVICE_MGMT) ||
+ (mgmt_class == IB_MGMT_CLASS_DEVICE_ADM) ||
+ (mgmt_class == IB_MGMT_CLASS_BIS))
+ return IB_MGMT_DEVICE_HDR;
+ else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
+ (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
+ return IB_MGMT_VENDOR_HDR;
+ else
+ return IB_MGMT_MAD_HDR;
+}
+EXPORT_SYMBOL(ib_get_mad_data_offset);
+
+int ib_is_mad_class_rmpp(u8 mgmt_class)
+{
+ if ((mgmt_class == IB_MGMT_CLASS_SUBN_ADM) ||
+ (mgmt_class == IB_MGMT_CLASS_DEVICE_MGMT) ||
+ (mgmt_class == IB_MGMT_CLASS_DEVICE_ADM) ||
+ (mgmt_class == IB_MGMT_CLASS_BIS) ||
+ ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
+ (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)))
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL(ib_is_mad_class_rmpp);
+
void *ib_get_rmpp_segment(struct ib_mad_send_buf *send_buf, int seg_num)
{
struct ib_mad_send_wr_private *mad_send_wr;
@@ -934,8 +976,7 @@ void ib_free_send_mad(struct ib_mad_send_buf *send_buf)
free_send_rmpp_list(mad_send_wr);
kfree(send_buf->mad);
- if (atomic_dec_and_test(&mad_agent_priv->refcount))
- wake_up(&mad_agent_priv->wait);
+ deref_mad_agent(mad_agent_priv);
}
EXPORT_SYMBOL(ib_free_send_mad);
@@ -1022,6 +1063,13 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
goto error;
}
+ if (!ib_is_mad_class_rmpp(((struct ib_mad_hdr *) send_buf->mad)->mgmt_class)) {
+ if (mad_agent_priv->agent.rmpp_version) {
+ ret = -EINVAL;
+ goto error;
+ }
+ }
+
/*
* Save pointer to next work request to post in case the
* current one completes, and the user modifies the work
@@ -1618,14 +1666,59 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv,
(rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA);
}
+static inline int rcv_has_same_class(struct ib_mad_send_wr_private *wr,
+ struct ib_mad_recv_wc *rwc)
+{
+ return ((struct ib_mad *)(wr->send_buf.mad))->mad_hdr.mgmt_class ==
+ rwc->recv_buf.mad->mad_hdr.mgmt_class;
+}
+
+static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr,
+ struct ib_mad_recv_wc *rwc )
+{
+ struct ib_ah_attr attr;
+ u8 send_resp, rcv_resp;
+
+ send_resp = ((struct ib_mad *)(wr->send_buf.mad))->
+ mad_hdr.method & IB_MGMT_METHOD_RESP;
+ rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP;
+
+ if (!send_resp && rcv_resp)
+ /* is request/response. GID/LIDs are both local (same). */
+ return 1;
+
+ if (send_resp == rcv_resp)
+ /* both requests, or both responses. GIDs different */
+ return 0;
+
+ if (ib_query_ah(wr->send_buf.ah, &attr))
+ /* Assume not equal, to avoid false positives. */
+ return 0;
+
+ if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH))
+ return attr.dlid == rwc->wc->slid;
+ else if ((attr.ah_flags & IB_AH_GRH) &&
+ (rwc->wc->wc_flags & IB_WC_GRH))
+ return memcmp(attr.grh.dgid.raw,
+ rwc->recv_buf.grh->sgid.raw, 16) == 0;
+ else
+ /* one has GID, other does not. Assume different */
+ return 0;
+}
struct ib_mad_send_wr_private*
-ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid)
+ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv,
+ struct ib_mad_recv_wc *mad_recv_wc)
{
struct ib_mad_send_wr_private *mad_send_wr;
+ struct ib_mad *mad;
+
+ mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad;
list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list,
agent_list) {
- if (mad_send_wr->tid == tid)
+ if ((mad_send_wr->tid == mad->mad_hdr.tid) &&
+ rcv_has_same_class(mad_send_wr, mad_recv_wc) &&
+ rcv_has_same_gid(mad_send_wr, mad_recv_wc))
return mad_send_wr;
}
@@ -1636,7 +1729,10 @@ ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid)
list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
agent_list) {
if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
- mad_send_wr->tid == tid && mad_send_wr->timeout) {
+ mad_send_wr->tid == mad->mad_hdr.tid &&
+ mad_send_wr->timeout &&
+ rcv_has_same_class(mad_send_wr, mad_recv_wc) &&
+ rcv_has_same_gid(mad_send_wr, mad_recv_wc)) {
/* Verify request has not been canceled */
return (mad_send_wr->status == IB_WC_SUCCESS) ?
mad_send_wr : NULL;
@@ -1661,7 +1757,6 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
struct ib_mad_send_wr_private *mad_send_wr;
struct ib_mad_send_wc mad_send_wc;
unsigned long flags;
- __be64 tid;
INIT_LIST_HEAD(&mad_recv_wc->rmpp_list);
list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
@@ -1669,22 +1764,19 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv,
mad_recv_wc);
if (!mad_recv_wc) {
- if (atomic_dec_and_test(&mad_agent_priv->refcount))
- wake_up(&mad_agent_priv->wait);
+ deref_mad_agent(mad_agent_priv);
return;
}
}
/* Complete corresponding request */
if (response_mad(mad_recv_wc->recv_buf.mad)) {
- tid = mad_recv_wc->recv_buf.mad->mad_hdr.tid;
spin_lock_irqsave(&mad_agent_priv->lock, flags);
- mad_send_wr = ib_find_send_mad(mad_agent_priv, tid);
+ mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc);
if (!mad_send_wr) {
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
ib_free_recv_mad(mad_recv_wc);
- if (atomic_dec_and_test(&mad_agent_priv->refcount))
- wake_up(&mad_agent_priv->wait);
+ deref_mad_agent(mad_agent_priv);
return;
}
ib_mark_mad_done(mad_send_wr);
@@ -1703,8 +1795,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
} else {
mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
mad_recv_wc);
- if (atomic_dec_and_test(&mad_agent_priv->refcount))
- wake_up(&mad_agent_priv->wait);
+ deref_mad_agent(mad_agent_priv);
}
}
@@ -1934,8 +2025,7 @@ void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
mad_send_wc);
/* Release reference on agent taken when sending */
- if (atomic_dec_and_test(&mad_agent_priv->refcount))
- wake_up(&mad_agent_priv->wait);
+ deref_mad_agent(mad_agent_priv);
return;
done:
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
@@ -2221,6 +2311,7 @@ static void local_completions(void *data)
local = list_entry(mad_agent_priv->local_list.next,
struct ib_mad_local_private,
completion_list);
+ list_del(&local->completion_list);
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
if (local->mad_priv) {
recv_mad_agent = local->recv_mad_agent;
@@ -2272,7 +2363,6 @@ local_send_completion:
&mad_send_wc);
spin_lock_irqsave(&mad_agent_priv->lock, flags);
- list_del(&local->completion_list);
atomic_dec(&mad_agent_priv->refcount);
if (!recv)
kmem_cache_free(ib_mad_cache, local->mad_priv);
@@ -2408,11 +2498,11 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
}
}
sg_list.addr = dma_map_single(qp_info->port_priv->
- device->dma_device,
- &mad_priv->grh,
- sizeof *mad_priv -
- sizeof mad_priv->header,
- DMA_FROM_DEVICE);
+ device->dma_device,
+ &mad_priv->grh,
+ sizeof *mad_priv -
+ sizeof mad_priv->header,
+ DMA_FROM_DEVICE);
pci_unmap_addr_set(&mad_priv->header, mapping, sg_list.addr);
recv_wr.wr_id = (unsigned long)&mad_priv->header.mad_list;
mad_priv->header.mad_list.mad_queue = recv_queue;
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index a7125d4b5cc..b4fa28d3160 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -37,6 +37,7 @@
#ifndef __IB_MAD_PRIV_H__
#define __IB_MAD_PRIV_H__
+#include <linux/completion.h>
#include <linux/pci.h>
#include <linux/kthread.h>
#include <linux/workqueue.h>
@@ -108,7 +109,7 @@ struct ib_mad_agent_private {
struct list_head rmpp_list;
atomic_t refcount;
- wait_queue_head_t wait;
+ struct completion comp;
};
struct ib_mad_snoop_private {
@@ -117,7 +118,7 @@ struct ib_mad_snoop_private {
int snoop_index;
int mad_snoop_flags;
atomic_t refcount;
- wait_queue_head_t wait;
+ struct completion comp;
};
struct ib_mad_send_wr_private {
@@ -216,7 +217,8 @@ extern kmem_cache_t *ib_mad_cache;
int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr);
struct ib_mad_send_wr_private *
-ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid);
+ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv,
+ struct ib_mad_recv_wc *mad_recv_wc);
void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
struct ib_mad_send_wc *mad_send_wc);
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c
index bacfdd5bdda..d4704e054e3 100644
--- a/drivers/infiniband/core/mad_rmpp.c
+++ b/drivers/infiniband/core/mad_rmpp.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2005 Intel Inc. All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Voltaire, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -49,7 +49,7 @@ struct mad_rmpp_recv {
struct list_head list;
struct work_struct timeout_work;
struct work_struct cleanup_work;
- wait_queue_head_t wait;
+ struct completion comp;
enum rmpp_state state;
spinlock_t lock;
atomic_t refcount;
@@ -69,10 +69,16 @@ struct mad_rmpp_recv {
u8 method;
};
+static inline void deref_rmpp_recv(struct mad_rmpp_recv *rmpp_recv)
+{
+ if (atomic_dec_and_test(&rmpp_recv->refcount))
+ complete(&rmpp_recv->comp);
+}
+
static void destroy_rmpp_recv(struct mad_rmpp_recv *rmpp_recv)
{
- atomic_dec(&rmpp_recv->refcount);
- wait_event(rmpp_recv->wait, !atomic_read(&rmpp_recv->refcount));
+ deref_rmpp_recv(rmpp_recv);
+ wait_for_completion(&rmpp_recv->comp);
ib_destroy_ah(rmpp_recv->ah);
kfree(rmpp_recv);
}
@@ -100,17 +106,6 @@ void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent)
}
}
-static int data_offset(u8 mgmt_class)
-{
- if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
- return IB_MGMT_SA_HDR;
- else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
- (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
- return IB_MGMT_VENDOR_HDR;
- else
- return IB_MGMT_RMPP_HDR;
-}
-
static void format_ack(struct ib_mad_send_buf *msg,
struct ib_rmpp_mad *data,
struct mad_rmpp_recv *rmpp_recv)
@@ -137,7 +132,7 @@ static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
struct ib_mad_send_buf *msg;
int ret, hdr_len;
- hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class);
+ hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class);
msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
recv_wc->wc->pkey_index, 1, hdr_len,
0, GFP_KERNEL);
@@ -163,7 +158,7 @@ static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent,
if (IS_ERR(ah))
return (void *) ah;
- hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class);
+ hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class);
msg = ib_create_send_mad(agent, recv_wc->wc->src_qp,
recv_wc->wc->pkey_index, 1,
hdr_len, 0, GFP_KERNEL);
@@ -264,7 +259,7 @@ create_rmpp_recv(struct ib_mad_agent_private *agent,
goto error;
rmpp_recv->agent = agent;
- init_waitqueue_head(&rmpp_recv->wait);
+ init_completion(&rmpp_recv->comp);
INIT_WORK(&rmpp_recv->timeout_work, recv_timeout_handler, rmpp_recv);
INIT_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler, rmpp_recv);
spin_lock_init(&rmpp_recv->lock);
@@ -290,12 +285,6 @@ error: kfree(rmpp_recv);
return NULL;
}
-static inline void deref_rmpp_recv(struct mad_rmpp_recv *rmpp_recv)
-{
- if (atomic_dec_and_test(&rmpp_recv->refcount))
- wake_up(&rmpp_recv->wait);
-}
-
static struct mad_rmpp_recv *
find_rmpp_recv(struct ib_mad_agent_private *agent,
struct ib_mad_recv_wc *mad_recv_wc)
@@ -408,7 +397,7 @@ static inline int get_mad_len(struct mad_rmpp_recv *rmpp_recv)
rmpp_mad = (struct ib_rmpp_mad *)rmpp_recv->cur_seg_buf->mad;
- hdr_size = data_offset(rmpp_mad->mad_hdr.mgmt_class);
+ hdr_size = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class);
data_size = sizeof(struct ib_rmpp_mad) - hdr_size;
pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
if (pad > IB_MGMT_RMPP_DATA || pad < 0)
@@ -562,15 +551,15 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
return ib_send_mad(mad_send_wr);
}
-static void abort_send(struct ib_mad_agent_private *agent, __be64 tid,
- u8 rmpp_status)
+static void abort_send(struct ib_mad_agent_private *agent,
+ struct ib_mad_recv_wc *mad_recv_wc, u8 rmpp_status)
{
struct ib_mad_send_wr_private *mad_send_wr;
struct ib_mad_send_wc wc;
unsigned long flags;
spin_lock_irqsave(&agent->lock, flags);
- mad_send_wr = ib_find_send_mad(agent, tid);
+ mad_send_wr = ib_find_send_mad(agent, mad_recv_wc);
if (!mad_send_wr)
goto out; /* Unmatched send */
@@ -612,8 +601,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
if (rmpp_mad->rmpp_hdr.rmpp_status) {
- abort_send(agent, rmpp_mad->mad_hdr.tid,
- IB_MGMT_RMPP_STATUS_BAD_STATUS);
+ abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
return;
}
@@ -621,14 +609,13 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num);
newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
if (newwin < seg_num) {
- abort_send(agent, rmpp_mad->mad_hdr.tid,
- IB_MGMT_RMPP_STATUS_W2S);
+ abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S);
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S);
return;
}
spin_lock_irqsave(&agent->lock, flags);
- mad_send_wr = ib_find_send_mad(agent, rmpp_mad->mad_hdr.tid);
+ mad_send_wr = ib_find_send_mad(agent, mad_recv_wc);
if (!mad_send_wr)
goto out; /* Unmatched ACK */
@@ -639,8 +626,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
if (seg_num > mad_send_wr->send_buf.seg_count ||
seg_num > mad_send_wr->newwin) {
spin_unlock_irqrestore(&agent->lock, flags);
- abort_send(agent, rmpp_mad->mad_hdr.tid,
- IB_MGMT_RMPP_STATUS_S2B);
+ abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B);
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B);
return;
}
@@ -728,12 +714,10 @@ static void process_rmpp_stop(struct ib_mad_agent_private *agent,
rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
if (rmpp_mad->rmpp_hdr.rmpp_status != IB_MGMT_RMPP_STATUS_RESX) {
- abort_send(agent, rmpp_mad->mad_hdr.tid,
- IB_MGMT_RMPP_STATUS_BAD_STATUS);
+ abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
} else
- abort_send(agent, rmpp_mad->mad_hdr.tid,
- rmpp_mad->rmpp_hdr.rmpp_status);
+ abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status);
}
static void process_rmpp_abort(struct ib_mad_agent_private *agent,
@@ -745,12 +729,10 @@ static void process_rmpp_abort(struct ib_mad_agent_private *agent,
if (rmpp_mad->rmpp_hdr.rmpp_status < IB_MGMT_RMPP_STATUS_ABORT_MIN ||
rmpp_mad->rmpp_hdr.rmpp_status > IB_MGMT_RMPP_STATUS_ABORT_MAX) {
- abort_send(agent, rmpp_mad->mad_hdr.tid,
- IB_MGMT_RMPP_STATUS_BAD_STATUS);
+ abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS);
} else
- abort_send(agent, rmpp_mad->mad_hdr.tid,
- rmpp_mad->rmpp_hdr.rmpp_status);
+ abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status);
}
struct ib_mad_recv_wc *
@@ -764,8 +746,7 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
return mad_recv_wc;
if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) {
- abort_send(agent, rmpp_mad->mad_hdr.tid,
- IB_MGMT_RMPP_STATUS_UNV);
+ abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV);
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV);
goto out;
}
@@ -783,8 +764,7 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
process_rmpp_abort(agent, mad_recv_wc);
break;
default:
- abort_send(agent, rmpp_mad->mad_hdr.tid,
- IB_MGMT_RMPP_STATUS_BADT);
+ abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT);
nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT);
break;
}
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 15121cb5a1f..21f9282c1b2 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -336,7 +336,7 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
switch (width) {
case 4:
ret = sprintf(buf, "%u\n", (out_mad->data[40 + offset / 8] >>
- (offset % 4)) & 0xf);
+ (4 - (offset % 8))) & 0xf);
break;
case 8:
ret = sprintf(buf, "%u\n", out_mad->data[40 + offset / 8]);
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index f6a05965a4e..9164a09b6cc 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -32,6 +32,8 @@
*
* $Id: ucm.c 2594 2005-06-13 19:46:02Z libor $
*/
+
+#include <linux/completion.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/module.h>
@@ -72,7 +74,7 @@ struct ib_ucm_file {
struct ib_ucm_context {
int id;
- wait_queue_head_t wait;
+ struct completion comp;
atomic_t ref;
int events_reported;
@@ -138,7 +140,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
{
if (atomic_dec_and_test(&ctx->ref))
- wake_up(&ctx->wait);
+ complete(&ctx->comp);
}
static inline int ib_ucm_new_cm_id(int event)
@@ -178,7 +180,7 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
return NULL;
atomic_set(&ctx->ref, 1);
- init_waitqueue_head(&ctx->wait);
+ init_completion(&ctx->comp);
ctx->file = file;
INIT_LIST_HEAD(&ctx->events);
@@ -586,8 +588,8 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
if (IS_ERR(ctx))
return PTR_ERR(ctx);
- atomic_dec(&ctx->ref);
- wait_event(ctx->wait, !atomic_read(&ctx->ref));
+ ib_ucm_ctx_put(ctx);
+ wait_for_completion(&ctx->comp);
/* No new events will be generated after destroying the cm_id. */
ib_destroy_cm_id(ctx->cm_id);
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index fb6cd42601f..afe70a549c2 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -177,17 +177,6 @@ static int queue_packet(struct ib_umad_file *file,
return ret;
}
-static int data_offset(u8 mgmt_class)
-{
- if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
- return IB_MGMT_SA_HDR;
- else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
- (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
- return IB_MGMT_VENDOR_HDR;
- else
- return IB_MGMT_RMPP_HDR;
-}
-
static void send_handler(struct ib_mad_agent *agent,
struct ib_mad_send_wc *send_wc)
{
@@ -283,7 +272,7 @@ static ssize_t copy_recv_mad(char __user *buf, struct ib_umad_packet *packet,
*/
return -ENOSPC;
}
- offset = data_offset(recv_buf->mad->mad_hdr.mgmt_class);
+ offset = ib_get_mad_data_offset(recv_buf->mad->mad_hdr.mgmt_class);
max_seg_payload = sizeof (struct ib_mad) - offset;
for (left = packet->length - seg_payload, buf += seg_payload;
@@ -441,21 +430,14 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
}
rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data;
- if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
- hdr_len = IB_MGMT_SA_HDR;
- copy_offset = IB_MGMT_RMPP_HDR;
- rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
- IB_MGMT_RMPP_FLAG_ACTIVE;
- } else if (rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START &&
- rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END) {
- hdr_len = IB_MGMT_VENDOR_HDR;
+ hdr_len = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class);
+ if (!ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)) {
+ copy_offset = IB_MGMT_MAD_HDR;
+ rmpp_active = 0;
+ } else {
copy_offset = IB_MGMT_RMPP_HDR;
rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
IB_MGMT_RMPP_FLAG_ACTIVE;
- } else {
- hdr_len = IB_MGMT_MAD_HDR;
- copy_offset = IB_MGMT_MAD_HDR;
- rmpp_active = 0;
}
data_len = count - sizeof (struct ib_user_mad) - hdr_len;
diff --git a/drivers/infiniband/core/uverbs_mem.c b/drivers/infiniband/core/uverbs_mem.c
index 36a32c31566..efe147dbeb4 100644
--- a/drivers/infiniband/core/uverbs_mem.c
+++ b/drivers/infiniband/core/uverbs_mem.c
@@ -211,8 +211,10 @@ void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem)
*/
work = kmalloc(sizeof *work, GFP_KERNEL);
- if (!work)
+ if (!work) {
+ mmput(mm);
return;
+ }
INIT_WORK(&work->work, ib_umem_account, work);
work->mm = mm;
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index cae0845f472..b78e7dc6933 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -45,6 +45,40 @@
#include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h>
+int ib_rate_to_mult(enum ib_rate rate)
+{
+ switch (rate) {
+ case IB_RATE_2_5_GBPS: return 1;
+ case IB_RATE_5_GBPS: return 2;
+ case IB_RATE_10_GBPS: return 4;
+ case IB_RATE_20_GBPS: return 8;
+ case IB_RATE_30_GBPS: return 12;
+ case IB_RATE_40_GBPS: return 16;
+ case IB_RATE_60_GBPS: return 24;
+ case IB_RATE_80_GBPS: return 32;
+ case IB_RATE_120_GBPS: return 48;
+ default: return -1;
+ }
+}
+EXPORT_SYMBOL(ib_rate_to_mult);
+
+enum ib_rate mult_to_ib_rate(int mult)
+{
+ switch (mult) {
+ case 1: return IB_RATE_2_5_GBPS;
+ case 2: return IB_RATE_5_GBPS;
+ case 4: return IB_RATE_10_GBPS;
+ case 8: return IB_RATE_20_GBPS;
+ case 12: return IB_RATE_30_GBPS;
+ case 16: return IB_RATE_40_GBPS;
+ case 24: return IB_RATE_60_GBPS;
+ case 32: return IB_RATE_80_GBPS;
+ case 48: return IB_RATE_120_GBPS;
+ default: return IB_RATE_PORT_CURRENT;
+ }
+}
+EXPORT_SYMBOL(mult_to_ib_rate);
+
/* Protection domains */
struct ib_pd *ib_alloc_pd(struct ib_device *device)
diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig
new file mode 100644
index 00000000000..9ea67c409b6
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/Kconfig
@@ -0,0 +1,16 @@
+config IPATH_CORE
+ tristate "PathScale InfiniPath Driver"
+ depends on 64BIT && PCI_MSI && NET
+ ---help---
+ This is a low-level driver for PathScale InfiniPath host channel
+ adapters (HCAs) based on the HT-400 and PE-800 chips.
+
+config INFINIBAND_IPATH
+ tristate "PathScale InfiniPath Verbs Driver"
+ depends on IPATH_CORE && INFINIBAND
+ ---help---
+ This is a driver that provides InfiniBand verbs support for
+ PathScale InfiniPath host channel adapters (HCAs). This
+ allows these devices to be used with both kernel upper level
+ protocols such as IP-over-InfiniBand as well as with userspace
+ applications (in conjunction with InfiniBand userspace access).
diff --git a/drivers/infiniband/hw/ipath/Makefile b/drivers/infiniband/hw/ipath/Makefile
new file mode 100644
index 00000000000..b4d084abfd2
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/Makefile
@@ -0,0 +1,36 @@
+EXTRA_CFLAGS += -DIPATH_IDSTR='"PathScale kernel.org driver"' \
+ -DIPATH_KERN_TYPE=0
+
+obj-$(CONFIG_IPATH_CORE) += ipath_core.o
+obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o
+
+ipath_core-y := \
+ ipath_diag.o \
+ ipath_driver.o \
+ ipath_eeprom.o \
+ ipath_file_ops.o \
+ ipath_fs.o \
+ ipath_ht400.o \
+ ipath_init_chip.o \
+ ipath_intr.o \
+ ipath_layer.o \
+ ipath_pe800.o \
+ ipath_stats.o \
+ ipath_sysfs.o \
+ ipath_user_pages.o
+
+ipath_core-$(CONFIG_X86_64) += ipath_wc_x86_64.o
+
+ib_ipath-y := \
+ ipath_cq.o \
+ ipath_keys.o \
+ ipath_mad.o \
+ ipath_mr.o \
+ ipath_qp.o \
+ ipath_rc.o \
+ ipath_ruc.o \
+ ipath_srq.o \
+ ipath_uc.o \
+ ipath_ud.o \
+ ipath_verbs.o \
+ ipath_verbs_mcast.o
diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h
new file mode 100644
index 00000000000..48a55247b83
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_common.h
@@ -0,0 +1,616 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _IPATH_COMMON_H
+#define _IPATH_COMMON_H
+
+/*
+ * This file contains defines, structures, etc. that are used
+ * to communicate between kernel and user code.
+ */
+
+/* This is the IEEE-assigned OUI for PathScale, Inc. */
+#define IPATH_SRC_OUI_1 0x00
+#define IPATH_SRC_OUI_2 0x11
+#define IPATH_SRC_OUI_3 0x75
+
+/* version of protocol header (known to chip also). In the long run,
+ * we should be able to generate and accept a range of version numbers;
+ * for now we only accept one, and it's compiled in.
+ */
+#define IPS_PROTO_VERSION 2
+
+/*
+ * These are compile time constants that you may want to enable or disable
+ * if you are trying to debug problems with code or performance.
+ * IPATH_VERBOSE_TRACING define as 1 if you want additional tracing in
+ * fastpath code
+ * IPATH_TRACE_REGWRITES define as 1 if you want register writes to be
+ * traced in faspath code
+ * _IPATH_TRACING define as 0 if you want to remove all tracing in a
+ * compilation unit
+ * _IPATH_DEBUGGING define as 0 if you want to remove debug prints
+ */
+
+/*
+ * The value in the BTH QP field that InfiniPath uses to differentiate
+ * an infinipath protocol IB packet vs standard IB transport
+ */
+#define IPATH_KD_QP 0x656b79
+
+/*
+ * valid states passed to ipath_set_linkstate() user call
+ */
+#define IPATH_IB_LINKDOWN 0
+#define IPATH_IB_LINKARM 1
+#define IPATH_IB_LINKACTIVE 2
+#define IPATH_IB_LINKINIT 3
+#define IPATH_IB_LINKDOWN_SLEEP 4
+#define IPATH_IB_LINKDOWN_DISABLE 5
+
+/*
+ * stats maintained by the driver. For now, at least, this is global
+ * to all minor devices.
+ */
+struct infinipath_stats {
+ /* number of interrupts taken */
+ __u64 sps_ints;
+ /* number of interrupts for errors */
+ __u64 sps_errints;
+ /* number of errors from chip (not incl. packet errors or CRC) */
+ __u64 sps_errs;
+ /* number of packet errors from chip other than CRC */
+ __u64 sps_pkterrs;
+ /* number of packets with CRC errors (ICRC and VCRC) */
+ __u64 sps_crcerrs;
+ /* number of hardware errors reported (parity, etc.) */
+ __u64 sps_hwerrs;
+ /* number of times IB link changed state unexpectedly */
+ __u64 sps_iblink;
+ /* no longer used; left for compatibility */
+ __u64 sps_unused3;
+ /* number of kernel (port0) packets received */
+ __u64 sps_port0pkts;
+ /* number of "ethernet" packets sent by driver */
+ __u64 sps_ether_spkts;
+ /* number of "ethernet" packets received by driver */
+ __u64 sps_ether_rpkts;
+ /* number of SMA packets sent by driver */
+ __u64 sps_sma_spkts;
+ /* number of SMA packets received by driver */
+ __u64 sps_sma_rpkts;
+ /* number of times all ports rcvhdrq was full and packet dropped */
+ __u64 sps_hdrqfull;
+ /* number of times all ports egrtid was full and packet dropped */
+ __u64 sps_etidfull;
+ /*
+ * number of times we tried to send from driver, but no pio buffers
+ * avail
+ */
+ __u64 sps_nopiobufs;
+ /* number of ports currently open */
+ __u64 sps_ports;
+ /* list of pkeys (other than default) accepted (0 means not set) */
+ __u16 sps_pkeys[4];
+ /* lids for up to 4 infinipaths, indexed by infinipath # */
+ __u16 sps_lid[4];
+ /* number of user ports per chip (not IB ports) */
+ __u32 sps_nports;
+ /* not our interrupt, or already handled */
+ __u32 sps_nullintr;
+ /* max number of packets handled per receive call */
+ __u32 sps_maxpkts_call;
+ /* avg number of packets handled per receive call */
+ __u32 sps_avgpkts_call;
+ /* total number of pages locked */
+ __u64 sps_pagelocks;
+ /* total number of pages unlocked */
+ __u64 sps_pageunlocks;
+ /*
+ * Number of packets dropped in kernel other than errors (ether
+ * packets if ipath not configured, sma/mad, etc.)
+ */
+ __u64 sps_krdrops;
+ /* mlids for up to 4 infinipaths, indexed by infinipath # */
+ __u16 sps_mlid[4];
+ /* pad for future growth */
+ __u64 __sps_pad[45];
+};
+
+/*
+ * These are the status bits readable (in ascii form, 64bit value)
+ * from the "status" sysfs file.
+ */
+#define IPATH_STATUS_INITTED 0x1 /* basic initialization done */
+#define IPATH_STATUS_DISABLED 0x2 /* hardware disabled */
+/* Device has been disabled via admin request */
+#define IPATH_STATUS_ADMIN_DISABLED 0x4
+#define IPATH_STATUS_OIB_SMA 0x8 /* ipath_mad kernel SMA running */
+#define IPATH_STATUS_SMA 0x10 /* user SMA running */
+/* Chip has been found and initted */
+#define IPATH_STATUS_CHIP_PRESENT 0x20
+/* IB link is at ACTIVE, usable for data traffic */
+#define IPATH_STATUS_IB_READY 0x40
+/* link is configured, LID, MTU, etc. have been set */
+#define IPATH_STATUS_IB_CONF 0x80
+/* no link established, probably no cable */
+#define IPATH_STATUS_IB_NOCABLE 0x100
+/* A Fatal hardware error has occurred. */
+#define IPATH_STATUS_HWERROR 0x200
+
+/*
+ * The list of usermode accessible registers. Also see Reg_* later in file.
+ */
+typedef enum _ipath_ureg {
+ /* (RO) DMA RcvHdr to be used next. */
+ ur_rcvhdrtail = 0,
+ /* (RW) RcvHdr entry to be processed next by host. */
+ ur_rcvhdrhead = 1,
+ /* (RO) Index of next Eager index to use. */
+ ur_rcvegrindextail = 2,
+ /* (RW) Eager TID to be processed next */
+ ur_rcvegrindexhead = 3,
+ /* For internal use only; max register number. */
+ _IPATH_UregMax
+} ipath_ureg;
+
+/* bit values for spi_runtime_flags */
+#define IPATH_RUNTIME_HT 0x1
+#define IPATH_RUNTIME_PCIE 0x2
+#define IPATH_RUNTIME_FORCE_WC_ORDER 0x4
+#define IPATH_RUNTIME_RCVHDR_COPY 0x8
+
+/*
+ * This structure is returned by ipath_userinit() immediately after
+ * open to get implementation-specific info, and info specific to this
+ * instance.
+ *
+ * This struct must have explict pad fields where type sizes
+ * may result in different alignments between 32 and 64 bit
+ * programs, since the 64 bit * bit kernel requires the user code
+ * to have matching offsets
+ */
+struct ipath_base_info {
+ /* version of hardware, for feature checking. */
+ __u32 spi_hw_version;
+ /* version of software, for feature checking. */
+ __u32 spi_sw_version;
+ /* InfiniPath port assigned, goes into sent packets */
+ __u32 spi_port;
+ /*
+ * IB MTU, packets IB data must be less than this.
+ * The MTU is in bytes, and will be a multiple of 4 bytes.
+ */
+ __u32 spi_mtu;
+ /*
+ * Size of a PIO buffer. Any given packet's total size must be less
+ * than this (in words). Included is the starting control word, so
+ * if 513 is returned, then total pkt size is 512 words or less.
+ */
+ __u32 spi_piosize;
+ /* size of the TID cache in infinipath, in entries */
+ __u32 spi_tidcnt;
+ /* size of the TID Eager list in infinipath, in entries */
+ __u32 spi_tidegrcnt;
+ /* size of a single receive header queue entry. */
+ __u32 spi_rcvhdrent_size;
+ /*
+ * Count of receive header queue entries allocated.
+ * This may be less than the spu_rcvhdrcnt passed in!.
+ */
+ __u32 spi_rcvhdr_cnt;
+
+ /* per-chip and other runtime features bitmap (IPATH_RUNTIME_*) */
+ __u32 spi_runtime_flags;
+
+ /* address where receive buffer queue is mapped into */
+ __u64 spi_rcvhdr_base;
+
+ /* user program. */
+
+ /* base address of eager TID receive buffers. */
+ __u64 spi_rcv_egrbufs;
+
+ /* Allocated by initialization code, not by protocol. */
+
+ /*
+ * Size of each TID buffer in host memory, starting at
+ * spi_rcv_egrbufs. The buffers are virtually contiguous.
+ */
+ __u32 spi_rcv_egrbufsize;
+ /*
+ * The special QP (queue pair) value that identifies an infinipath
+ * protocol packet from standard IB packets. More, probably much
+ * more, to be added.
+ */
+ __u32 spi_qpair;
+
+ /*
+ * User register base for init code, not to be used directly by
+ * protocol or applications.
+ */
+ __u64 __spi_uregbase;
+ /*
+ * Maximum buffer size in bytes that can be used in a single TID
+ * entry (assuming the buffer is aligned to this boundary). This is
+ * the minimum of what the hardware and software support Guaranteed
+ * to be a power of 2.
+ */
+ __u32 spi_tid_maxsize;
+ /*
+ * alignment of each pio send buffer (byte count
+ * to add to spi_piobufbase to get to second buffer)
+ */
+ __u32 spi_pioalign;
+ /*
+ * The index of the first pio buffer available to this process;
+ * needed to do lookup in spi_pioavailaddr; not added to
+ * spi_piobufbase.
+ */
+ __u32 spi_pioindex;
+ /* number of buffers mapped for this process */
+ __u32 spi_piocnt;
+
+ /*
+ * Base address of writeonly pio buffers for this process.
+ * Each buffer has spi_piosize words, and is aligned on spi_pioalign
+ * boundaries. spi_piocnt buffers are mapped from this address
+ */
+ __u64 spi_piobufbase;
+
+ /*
+ * Base address of readonly memory copy of the pioavail registers.
+ * There are 2 bits for each buffer.
+ */
+ __u64 spi_pioavailaddr;
+
+ /*
+ * Address where driver updates a copy of the interface and driver
+ * status (IPATH_STATUS_*) as a 64 bit value. It's followed by a
+ * string indicating hardware error, if there was one.
+ */
+ __u64 spi_status;
+
+ /* number of chip ports available to user processes */
+ __u32 spi_nports;
+ /* unit number of chip we are using */
+ __u32 spi_unit;
+ /* num bufs in each contiguous set */
+ __u32 spi_rcv_egrperchunk;
+ /* size in bytes of each contiguous set */
+ __u32 spi_rcv_egrchunksize;
+ /* total size of mmap to cover full rcvegrbuffers */
+ __u32 spi_rcv_egrbuftotlen;
+} __attribute__ ((aligned(8)));
+
+
+/*
+ * This version number is given to the driver by the user code during
+ * initialization in the spu_userversion field of ipath_user_info, so
+ * the driver can check for compatibility with user code.
+ *
+ * The major version changes when data structures
+ * change in an incompatible way. The driver must be the same or higher
+ * for initialization to succeed. In some cases, a higher version
+ * driver will not interoperate with older software, and initialization
+ * will return an error.
+ */
+#define IPATH_USER_SWMAJOR 1
+
+/*
+ * Minor version differences are always compatible
+ * a within a major version, however if if user software is larger
+ * than driver software, some new features and/or structure fields
+ * may not be implemented; the user code must deal with this if it
+ * cares, or it must abort after initialization reports the difference
+ */
+#define IPATH_USER_SWMINOR 2
+
+#define IPATH_USER_SWVERSION ((IPATH_USER_SWMAJOR<<16) | IPATH_USER_SWMINOR)
+
+#define IPATH_KERN_TYPE 0
+
+/*
+ * Similarly, this is the kernel version going back to the user. It's
+ * slightly different, in that we want to tell if the driver was built as
+ * part of a PathScale release, or from the driver from OpenIB, kernel.org,
+ * or a standard distribution, for support reasons. The high bit is 0 for
+ * non-PathScale, and 1 for PathScale-built/supplied.
+ *
+ * It's returned by the driver to the user code during initialization in the
+ * spi_sw_version field of ipath_base_info, so the user code can in turn
+ * check for compatibility with the kernel.
+*/
+#define IPATH_KERN_SWVERSION ((IPATH_KERN_TYPE<<31) | IPATH_USER_SWVERSION)
+
+/*
+ * This structure is passed to ipath_userinit() to tell the driver where
+ * user code buffers are, sizes, etc. The offsets and sizes of the
+ * fields must remain unchanged, for binary compatibility. It can
+ * be extended, if userversion is changed so user code can tell, if needed
+ */
+struct ipath_user_info {
+ /*
+ * version of user software, to detect compatibility issues.
+ * Should be set to IPATH_USER_SWVERSION.
+ */
+ __u32 spu_userversion;
+
+ /* desired number of receive header queue entries */
+ __u32 spu_rcvhdrcnt;
+
+ /* size of struct base_info to write to */
+ __u32 spu_base_info_size;
+
+ /*
+ * number of words in KD protocol header
+ * This tells InfiniPath how many words to copy to rcvhdrq. If 0,
+ * kernel uses a default. Once set, attempts to set any other value
+ * are an error (EAGAIN) until driver is reloaded.
+ */
+ __u32 spu_rcvhdrsize;
+
+ /*
+ * cache line aligned (64 byte) user address to
+ * which the rcvhdrtail register will be written by infinipath
+ * whenever it changes, so that no chip registers are read in
+ * the performance path.
+ */
+ __u64 spu_rcvhdraddr;
+
+ /*
+ * address of struct base_info to write to
+ */
+ __u64 spu_base_info;
+
+} __attribute__ ((aligned(8)));
+
+/* User commands. */
+
+#define IPATH_CMD_MIN 16
+
+#define IPATH_CMD_USER_INIT 16 /* set up userspace */
+#define IPATH_CMD_PORT_INFO 17 /* find out what resources we got */
+#define IPATH_CMD_RECV_CTRL 18 /* control receipt of packets */
+#define IPATH_CMD_TID_UPDATE 19 /* update expected TID entries */
+#define IPATH_CMD_TID_FREE 20 /* free expected TID entries */
+#define IPATH_CMD_SET_PART_KEY 21 /* add partition key */
+
+#define IPATH_CMD_MAX 21
+
+struct ipath_port_info {
+ __u32 num_active; /* number of active units */
+ __u32 unit; /* unit (chip) assigned to caller */
+ __u32 port; /* port on unit assigned to caller */
+};
+
+struct ipath_tid_info {
+ __u32 tidcnt;
+ /* make structure same size in 32 and 64 bit */
+ __u32 tid__unused;
+ /* virtual address of first page in transfer */
+ __u64 tidvaddr;
+ /* pointer (same size 32/64 bit) to __u16 tid array */
+ __u64 tidlist;
+
+ /*
+ * pointer (same size 32/64 bit) to bitmap of TIDs used
+ * for this call; checked for being large enough at open
+ */
+ __u64 tidmap;
+};
+
+struct ipath_cmd {
+ __u32 type; /* command type */
+ union {
+ struct ipath_tid_info tid_info;
+ struct ipath_user_info user_info;
+ /* address in userspace of struct ipath_port_info to
+ write result to */
+ __u64 port_info;
+ /* enable/disable receipt of packets */
+ __u32 recv_ctrl;
+ /* partition key to set */
+ __u16 part_key;
+ } cmd;
+};
+
+struct ipath_iovec {
+ /* Pointer to data, but same size 32 and 64 bit */
+ __u64 iov_base;
+
+ /*
+ * Length of data; don't need 64 bits, but want
+ * ipath_sendpkt to remain same size as before 32 bit changes, so...
+ */
+ __u64 iov_len;
+};
+
+/*
+ * Describes a single packet for send. Each packet can have one or more
+ * buffers, but the total length (exclusive of IB headers) must be less
+ * than the MTU, and if using the PIO method, entire packet length,
+ * including IB headers, must be less than the ipath_piosize value (words).
+ * Use of this necessitates including sys/uio.h
+ */
+struct __ipath_sendpkt {
+ __u32 sps_flags; /* flags for packet (TBD) */
+ __u32 sps_cnt; /* number of entries to use in sps_iov */
+ /* array of iov's describing packet. TEMPORARY */
+ struct ipath_iovec sps_iov[4];
+};
+
+/* Passed into SMA special file's ->read and ->write methods. */
+struct ipath_sma_pkt
+{
+ __u32 unit; /* unit on which to send packet */
+ __u64 data; /* address of payload in userspace */
+ __u32 len; /* length of payload */
+};
+
+/*
+ * Data layout in I2C flash (for GUID, etc.)
+ * All fields are little-endian binary unless otherwise stated
+ */
+#define IPATH_FLASH_VERSION 1
+struct ipath_flash {
+ /* flash layout version (IPATH_FLASH_VERSION) */
+ __u8 if_fversion;
+ /* checksum protecting if_length bytes */
+ __u8 if_csum;
+ /*
+ * valid length (in use, protected by if_csum), including
+ * if_fversion and if_sum themselves)
+ */
+ __u8 if_length;
+ /* the GUID, in network order */
+ __u8 if_guid[8];
+ /* number of GUIDs to use, starting from if_guid */
+ __u8 if_numguid;
+ /* the board serial number, in ASCII */
+ char if_serial[12];
+ /* board mfg date (YYYYMMDD ASCII) */
+ char if_mfgdate[8];
+ /* last board rework/test date (YYYYMMDD ASCII) */
+ char if_testdate[8];
+ /* logging of error counts, TBD */
+ __u8 if_errcntp[4];
+ /* powered on hours, updated at driver unload */
+ __u8 if_powerhour[2];
+ /* ASCII free-form comment field */
+ char if_comment[32];
+ /* 78 bytes used, min flash size is 128 bytes */
+ __u8 if_future[50];
+};
+
+/*
+ * These are the counters implemented in the chip, and are listed in order.
+ * The InterCaps naming is taken straight from the chip spec.
+ */
+struct infinipath_counters {
+ __u64 LBIntCnt;
+ __u64 LBFlowStallCnt;
+ __u64 Reserved1;
+ __u64 TxUnsupVLErrCnt;
+ __u64 TxDataPktCnt;
+ __u64 TxFlowPktCnt;
+ __u64 TxDwordCnt;
+ __u64 TxLenErrCnt;
+ __u64 TxMaxMinLenErrCnt;
+ __u64 TxUnderrunCnt;
+ __u64 TxFlowStallCnt;
+ __u64 TxDroppedPktCnt;
+ __u64 RxDroppedPktCnt;
+ __u64 RxDataPktCnt;
+ __u64 RxFlowPktCnt;
+ __u64 RxDwordCnt;
+ __u64 RxLenErrCnt;
+ __u64 RxMaxMinLenErrCnt;
+ __u64 RxICRCErrCnt;
+ __u64 RxVCRCErrCnt;
+ __u64 RxFlowCtrlErrCnt;
+ __u64 RxBadFormatCnt;
+ __u64 RxLinkProblemCnt;
+ __u64 RxEBPCnt;
+ __u64 RxLPCRCErrCnt;
+ __u64 RxBufOvflCnt;
+ __u64 RxTIDFullErrCnt;
+ __u64 RxTIDValidErrCnt;
+ __u64 RxPKeyMismatchCnt;
+ __u64 RxP0HdrEgrOvflCnt;
+ __u64 RxP1HdrEgrOvflCnt;
+ __u64 RxP2HdrEgrOvflCnt;
+ __u64 RxP3HdrEgrOvflCnt;
+ __u64 RxP4HdrEgrOvflCnt;
+ __u64 RxP5HdrEgrOvflCnt;
+ __u64 RxP6HdrEgrOvflCnt;
+ __u64 RxP7HdrEgrOvflCnt;
+ __u64 RxP8HdrEgrOvflCnt;
+ __u64 Reserved6;
+ __u64 Reserved7;
+ __u64 IBStatusChangeCnt;
+ __u64 IBLinkErrRecoveryCnt;
+ __u64 IBLinkDownedCnt;
+ __u64 IBSymbolErrCnt;
+};
+
+/*
+ * The next set of defines are for packet headers, and chip register
+ * and memory bits that are visible to and/or used by user-mode software
+ * The other bits that are used only by the driver or diags are in
+ * ipath_registers.h
+ */
+
+/* RcvHdrFlags bits */
+#define INFINIPATH_RHF_LENGTH_MASK 0x7FF
+#define INFINIPATH_RHF_LENGTH_SHIFT 0
+#define INFINIPATH_RHF_RCVTYPE_MASK 0x7
+#define INFINIPATH_RHF_RCVTYPE_SHIFT 11
+#define INFINIPATH_RHF_EGRINDEX_MASK 0x7FF
+#define INFINIPATH_RHF_EGRINDEX_SHIFT 16
+#define INFINIPATH_RHF_H_ICRCERR 0x80000000
+#define INFINIPATH_RHF_H_VCRCERR 0x40000000
+#define INFINIPATH_RHF_H_PARITYERR 0x20000000
+#define INFINIPATH_RHF_H_LENERR 0x10000000
+#define INFINIPATH_RHF_H_MTUERR 0x08000000
+#define INFINIPATH_RHF_H_IHDRERR 0x04000000
+#define INFINIPATH_RHF_H_TIDERR 0x02000000
+#define INFINIPATH_RHF_H_MKERR 0x01000000
+#define INFINIPATH_RHF_H_IBERR 0x00800000
+#define INFINIPATH_RHF_L_SWA 0x00008000
+#define INFINIPATH_RHF_L_SWB 0x00004000
+
+/* infinipath header fields */
+#define INFINIPATH_I_VERS_MASK 0xF
+#define INFINIPATH_I_VERS_SHIFT 28
+#define INFINIPATH_I_PORT_MASK 0xF
+#define INFINIPATH_I_PORT_SHIFT 24
+#define INFINIPATH_I_TID_MASK 0x7FF
+#define INFINIPATH_I_TID_SHIFT 13
+#define INFINIPATH_I_OFFSET_MASK 0x1FFF
+#define INFINIPATH_I_OFFSET_SHIFT 0
+
+/* K_PktFlags bits */
+#define INFINIPATH_KPF_INTR 0x1
+
+/* SendPIO per-buffer control */
+#define INFINIPATH_SP_LENGTHP1_MASK 0x3FF
+#define INFINIPATH_SP_LENGTHP1_SHIFT 0
+#define INFINIPATH_SP_INTR 0x80000000
+#define INFINIPATH_SP_TEST 0x40000000
+#define INFINIPATH_SP_TESTEBP 0x20000000
+
+/* SendPIOAvail bits */
+#define INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT 1
+#define INFINIPATH_SENDPIOAVAIL_CHECK_SHIFT 0
+
+#endif /* _IPATH_COMMON_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c
new file mode 100644
index 00000000000..7ece1135ddf
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_cq.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/err.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_verbs.h"
+
+/**
+ * ipath_cq_enter - add a new entry to the completion queue
+ * @cq: completion queue
+ * @entry: work completion entry to add
+ * @sig: true if @entry is a solicitated entry
+ *
+ * This may be called with one of the qp->s_lock or qp->r_rq.lock held.
+ */
+void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited)
+{
+ unsigned long flags;
+ u32 next;
+
+ spin_lock_irqsave(&cq->lock, flags);
+
+ if (cq->head == cq->ibcq.cqe)
+ next = 0;
+ else
+ next = cq->head + 1;
+ if (unlikely(next == cq->tail)) {
+ spin_unlock_irqrestore(&cq->lock, flags);
+ if (cq->ibcq.event_handler) {
+ struct ib_event ev;
+
+ ev.device = cq->ibcq.device;
+ ev.element.cq = &cq->ibcq;
+ ev.event = IB_EVENT_CQ_ERR;
+ cq->ibcq.event_handler(&ev, cq->ibcq.cq_context);
+ }
+ return;
+ }
+ cq->queue[cq->head] = *entry;
+ cq->head = next;
+
+ if (cq->notify == IB_CQ_NEXT_COMP ||
+ (cq->notify == IB_CQ_SOLICITED && solicited)) {
+ cq->notify = IB_CQ_NONE;
+ cq->triggered++;
+ /*
+ * This will cause send_complete() to be called in
+ * another thread.
+ */
+ tasklet_hi_schedule(&cq->comptask);
+ }
+
+ spin_unlock_irqrestore(&cq->lock, flags);
+
+ if (entry->status != IB_WC_SUCCESS)
+ to_idev(cq->ibcq.device)->n_wqe_errs++;
+}
+
+/**
+ * ipath_poll_cq - poll for work completion entries
+ * @ibcq: the completion queue to poll
+ * @num_entries: the maximum number of entries to return
+ * @entry: pointer to array where work completions are placed
+ *
+ * Returns the number of completion entries polled.
+ *
+ * This may be called from interrupt context. Also called by ib_poll_cq()
+ * in the generic verbs code.
+ */
+int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
+{
+ struct ipath_cq *cq = to_icq(ibcq);
+ unsigned long flags;
+ int npolled;
+
+ spin_lock_irqsave(&cq->lock, flags);
+
+ for (npolled = 0; npolled < num_entries; ++npolled, ++entry) {
+ if (cq->tail == cq->head)
+ break;
+ *entry = cq->queue[cq->tail];
+ if (cq->tail == cq->ibcq.cqe)
+ cq->tail = 0;
+ else
+ cq->tail++;
+ }
+
+ spin_unlock_irqrestore(&cq->lock, flags);
+
+ return npolled;
+}
+
+static void send_complete(unsigned long data)
+{
+ struct ipath_cq *cq = (struct ipath_cq *)data;
+
+ /*
+ * The completion handler will most likely rearm the notification
+ * and poll for all pending entries. If a new completion entry
+ * is added while we are in this routine, tasklet_hi_schedule()
+ * won't call us again until we return so we check triggered to
+ * see if we need to call the handler again.
+ */
+ for (;;) {
+ u8 triggered = cq->triggered;
+
+ cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
+
+ if (cq->triggered == triggered)
+ return;
+ }
+}
+
+/**
+ * ipath_create_cq - create a completion queue
+ * @ibdev: the device this completion queue is attached to
+ * @entries: the minimum size of the completion queue
+ * @context: unused by the InfiniPath driver
+ * @udata: unused by the InfiniPath driver
+ *
+ * Returns a pointer to the completion queue or negative errno values
+ * for failure.
+ *
+ * Called by ib_create_cq() in the generic verbs code.
+ */
+struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
+ struct ib_ucontext *context,
+ struct ib_udata *udata)
+{
+ struct ipath_cq *cq;
+ struct ib_wc *wc;
+ struct ib_cq *ret;
+
+ /*
+ * Need to use vmalloc() if we want to support large #s of
+ * entries.
+ */
+ cq = kmalloc(sizeof(*cq), GFP_KERNEL);
+ if (!cq) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /*
+ * Need to use vmalloc() if we want to support large #s of entries.
+ */
+ wc = vmalloc(sizeof(*wc) * (entries + 1));
+ if (!wc) {
+ kfree(cq);
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+ /*
+ * ib_create_cq() will initialize cq->ibcq except for cq->ibcq.cqe.
+ * The number of entries should be >= the number requested or return
+ * an error.
+ */
+ cq->ibcq.cqe = entries;
+ cq->notify = IB_CQ_NONE;
+ cq->triggered = 0;
+ spin_lock_init(&cq->lock);
+ tasklet_init(&cq->comptask, send_complete, (unsigned long)cq);
+ cq->head = 0;
+ cq->tail = 0;
+ cq->queue = wc;
+
+ ret = &cq->ibcq;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_destroy_cq - destroy a completion queue
+ * @ibcq: the completion queue to destroy.
+ *
+ * Returns 0 for success.
+ *
+ * Called by ib_destroy_cq() in the generic verbs code.
+ */
+int ipath_destroy_cq(struct ib_cq *ibcq)
+{
+ struct ipath_cq *cq = to_icq(ibcq);
+
+ tasklet_kill(&cq->comptask);
+ vfree(cq->queue);
+ kfree(cq);
+
+ return 0;
+}
+
+/**
+ * ipath_req_notify_cq - change the notification type for a completion queue
+ * @ibcq: the completion queue
+ * @notify: the type of notification to request
+ *
+ * Returns 0 for success.
+ *
+ * This may be called from interrupt context. Also called by
+ * ib_req_notify_cq() in the generic verbs code.
+ */
+int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
+{
+ struct ipath_cq *cq = to_icq(ibcq);
+ unsigned long flags;
+
+ spin_lock_irqsave(&cq->lock, flags);
+ /*
+ * Don't change IB_CQ_NEXT_COMP to IB_CQ_SOLICITED but allow
+ * any other transitions.
+ */
+ if (cq->notify != IB_CQ_NEXT_COMP)
+ cq->notify = notify;
+ spin_unlock_irqrestore(&cq->lock, flags);
+ return 0;
+}
+
+int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
+{
+ struct ipath_cq *cq = to_icq(ibcq);
+ struct ib_wc *wc, *old_wc;
+ u32 n;
+ int ret;
+
+ /*
+ * Need to use vmalloc() if we want to support large #s of entries.
+ */
+ wc = vmalloc(sizeof(*wc) * (cqe + 1));
+ if (!wc) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ spin_lock_irq(&cq->lock);
+ if (cq->head < cq->tail)
+ n = cq->ibcq.cqe + 1 + cq->head - cq->tail;
+ else
+ n = cq->head - cq->tail;
+ if (unlikely((u32)cqe < n)) {
+ spin_unlock_irq(&cq->lock);
+ vfree(wc);
+ ret = -EOVERFLOW;
+ goto bail;
+ }
+ for (n = 0; cq->tail != cq->head; n++) {
+ wc[n] = cq->queue[cq->tail];
+ if (cq->tail == cq->ibcq.cqe)
+ cq->tail = 0;
+ else
+ cq->tail++;
+ }
+ cq->ibcq.cqe = cqe;
+ cq->head = n;
+ cq->tail = 0;
+ old_wc = cq->queue;
+ cq->queue = wc;
+ spin_unlock_irq(&cq->lock);
+
+ vfree(old_wc);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h
new file mode 100644
index 00000000000..46762387f5f
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_debug.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _IPATH_DEBUG_H
+#define _IPATH_DEBUG_H
+
+#ifndef _IPATH_DEBUGGING /* debugging enabled or not */
+#define _IPATH_DEBUGGING 1
+#endif
+
+#if _IPATH_DEBUGGING
+
+/*
+ * Mask values for debugging. The scheme allows us to compile out any
+ * of the debug tracing stuff, and if compiled in, to enable or disable
+ * dynamically. This can be set at modprobe time also:
+ * modprobe infinipath.ko infinipath_debug=7
+ */
+
+#define __IPATH_INFO 0x1 /* generic low verbosity stuff */
+#define __IPATH_DBG 0x2 /* generic debug */
+#define __IPATH_TRSAMPLE 0x8 /* generate trace buffer sample entries */
+/* leave some low verbosity spots open */
+#define __IPATH_VERBDBG 0x40 /* very verbose debug */
+#define __IPATH_PKTDBG 0x80 /* print packet data */
+/* print process startup (init)/exit messages */
+#define __IPATH_PROCDBG 0x100
+/* print mmap/nopage stuff, not using VDBG any more */
+#define __IPATH_MMDBG 0x200
+#define __IPATH_USER_SEND 0x1000 /* use user mode send */
+#define __IPATH_KERNEL_SEND 0x2000 /* use kernel mode send */
+#define __IPATH_EPKTDBG 0x4000 /* print ethernet packet data */
+#define __IPATH_SMADBG 0x8000 /* sma packet debug */
+#define __IPATH_IPATHDBG 0x10000 /* Ethernet (IPATH) gen debug */
+#define __IPATH_IPATHWARN 0x20000 /* Ethernet (IPATH) warnings */
+#define __IPATH_IPATHERR 0x40000 /* Ethernet (IPATH) errors */
+#define __IPATH_IPATHPD 0x80000 /* Ethernet (IPATH) packet dump */
+#define __IPATH_IPATHTABLE 0x100000 /* Ethernet (IPATH) table dump */
+
+#else /* _IPATH_DEBUGGING */
+
+/*
+ * define all of these even with debugging off, for the few places that do
+ * if(infinipath_debug & _IPATH_xyzzy), but in a way that will make the
+ * compiler eliminate the code
+ */
+
+#define __IPATH_INFO 0x0 /* generic low verbosity stuff */
+#define __IPATH_DBG 0x0 /* generic debug */
+#define __IPATH_TRSAMPLE 0x0 /* generate trace buffer sample entries */
+#define __IPATH_VERBDBG 0x0 /* very verbose debug */
+#define __IPATH_PKTDBG 0x0 /* print packet data */
+#define __IPATH_PROCDBG 0x0 /* process startup (init)/exit messages */
+/* print mmap/nopage stuff, not using VDBG any more */
+#define __IPATH_MMDBG 0x0
+#define __IPATH_EPKTDBG 0x0 /* print ethernet packet data */
+#define __IPATH_SMADBG 0x0 /* process startup (init)/exit messages */
+#define __IPATH_IPATHDBG 0x0 /* Ethernet (IPATH) table dump on */
+#define __IPATH_IPATHWARN 0x0 /* Ethernet (IPATH) warnings on */
+#define __IPATH_IPATHERR 0x0 /* Ethernet (IPATH) errors on */
+#define __IPATH_IPATHPD 0x0 /* Ethernet (IPATH) packet dump on */
+#define __IPATH_IPATHTABLE 0x0 /* Ethernet (IPATH) packet dump on */
+
+#endif /* _IPATH_DEBUGGING */
+
+#define __IPATH_VERBOSEDBG __IPATH_VERBDBG
+
+#endif /* _IPATH_DEBUG_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
new file mode 100644
index 00000000000..28ddceb260e
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This file contains support for diagnostic functions. It is accessed by
+ * opening the ipath_diag device, normally minor number 129. Diagnostic use
+ * of the InfiniPath chip may render the chip or board unusable until the
+ * driver is unloaded, or in some cases, until the system is rebooted.
+ *
+ * Accesses to the chip through this interface are not similar to going
+ * through the /sys/bus/pci resource mmap interface.
+ */
+
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+
+#include "ipath_common.h"
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+int ipath_diag_inuse;
+static int diag_set_link;
+
+static int ipath_diag_open(struct inode *in, struct file *fp);
+static int ipath_diag_release(struct inode *in, struct file *fp);
+static ssize_t ipath_diag_read(struct file *fp, char __user *data,
+ size_t count, loff_t *off);
+static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
+ size_t count, loff_t *off);
+
+static struct file_operations diag_file_ops = {
+ .owner = THIS_MODULE,
+ .write = ipath_diag_write,
+ .read = ipath_diag_read,
+ .open = ipath_diag_open,
+ .release = ipath_diag_release
+};
+
+static struct cdev *diag_cdev;
+static struct class_device *diag_class_dev;
+
+int ipath_diag_init(void)
+{
+ return ipath_cdev_init(IPATH_DIAG_MINOR, "ipath_diag",
+ &diag_file_ops, &diag_cdev, &diag_class_dev);
+}
+
+void ipath_diag_cleanup(void)
+{
+ ipath_cdev_cleanup(&diag_cdev, &diag_class_dev);
+}
+
+/**
+ * ipath_read_umem64 - read a 64-bit quantity from the chip into user space
+ * @dd: the infinipath device
+ * @uaddr: the location to store the data in user memory
+ * @caddr: the source chip address (full pointer, not offset)
+ * @count: number of bytes to copy (multiple of 32 bits)
+ *
+ * This function also localizes all chip memory accesses.
+ * The copy should be written such that we read full cacheline packets
+ * from the chip. This is usually used for a single qword
+ *
+ * NOTE: This assumes the chip address is 64-bit aligned.
+ */
+static int ipath_read_umem64(struct ipath_devdata *dd, void __user *uaddr,
+ const void __iomem *caddr, size_t count)
+{
+ const u64 __iomem *reg_addr = caddr;
+ const u64 __iomem *reg_end = reg_addr + (count / sizeof(u64));
+ int ret;
+
+ /* not very efficient, but it works for now */
+ if (reg_addr < dd->ipath_kregbase ||
+ reg_end > dd->ipath_kregend) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ while (reg_addr < reg_end) {
+ u64 data = readq(reg_addr);
+ if (copy_to_user(uaddr, &data, sizeof(u64))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+ reg_addr++;
+ uaddr++;
+ }
+ ret = 0;
+bail:
+ return ret;
+}
+
+/**
+ * ipath_write_umem64 - write a 64-bit quantity to the chip from user space
+ * @dd: the infinipath device
+ * @caddr: the destination chip address (full pointer, not offset)
+ * @uaddr: the source of the data in user memory
+ * @count: the number of bytes to copy (multiple of 32 bits)
+ *
+ * This is usually used for a single qword
+ * NOTE: This assumes the chip address is 64-bit aligned.
+ */
+
+static int ipath_write_umem64(struct ipath_devdata *dd, void __iomem *caddr,
+ const void __user *uaddr, size_t count)
+{
+ u64 __iomem *reg_addr = caddr;
+ const u64 __iomem *reg_end = reg_addr + (count / sizeof(u64));
+ int ret;
+
+ /* not very efficient, but it works for now */
+ if (reg_addr < dd->ipath_kregbase ||
+ reg_end > dd->ipath_kregend) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ while (reg_addr < reg_end) {
+ u64 data;
+ if (copy_from_user(&data, uaddr, sizeof(data))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+ writeq(data, reg_addr);
+
+ reg_addr++;
+ uaddr++;
+ }
+ ret = 0;
+bail:
+ return ret;
+}
+
+/**
+ * ipath_read_umem32 - read a 32-bit quantity from the chip into user space
+ * @dd: the infinipath device
+ * @uaddr: the location to store the data in user memory
+ * @caddr: the source chip address (full pointer, not offset)
+ * @count: number of bytes to copy
+ *
+ * read 32 bit values, not 64 bit; for memories that only
+ * support 32 bit reads; usually a single dword.
+ */
+static int ipath_read_umem32(struct ipath_devdata *dd, void __user *uaddr,
+ const void __iomem *caddr, size_t count)
+{
+ const u32 __iomem *reg_addr = caddr;
+ const u32 __iomem *reg_end = reg_addr + (count / sizeof(u32));
+ int ret;
+
+ if (reg_addr < (u32 __iomem *) dd->ipath_kregbase ||
+ reg_end > (u32 __iomem *) dd->ipath_kregend) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ /* not very efficient, but it works for now */
+ while (reg_addr < reg_end) {
+ u32 data = readl(reg_addr);
+ if (copy_to_user(uaddr, &data, sizeof(data))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ reg_addr++;
+ uaddr++;
+ }
+ ret = 0;
+bail:
+ return ret;
+}
+
+/**
+ * ipath_write_umem32 - write a 32-bit quantity to the chip from user space
+ * @dd: the infinipath device
+ * @caddr: the destination chip address (full pointer, not offset)
+ * @uaddr: the source of the data in user memory
+ * @count: number of bytes to copy
+ *
+ * write 32 bit values, not 64 bit; for memories that only
+ * support 32 bit write; usually a single dword.
+ */
+
+static int ipath_write_umem32(struct ipath_devdata *dd, void __iomem *caddr,
+ const void __user *uaddr, size_t count)
+{
+ u32 __iomem *reg_addr = caddr;
+ const u32 __iomem *reg_end = reg_addr + (count / sizeof(u32));
+ int ret;
+
+ if (reg_addr < (u32 __iomem *) dd->ipath_kregbase ||
+ reg_end > (u32 __iomem *) dd->ipath_kregend) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ while (reg_addr < reg_end) {
+ u32 data;
+ if (copy_from_user(&data, uaddr, sizeof(data))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+ writel(data, reg_addr);
+
+ reg_addr++;
+ uaddr++;
+ }
+ ret = 0;
+bail:
+ return ret;
+}
+
+static int ipath_diag_open(struct inode *in, struct file *fp)
+{
+ struct ipath_devdata *dd;
+ int unit = 0; /* XXX this is bogus */
+ unsigned long flags;
+ int ret;
+
+ dd = ipath_lookup(unit);
+
+ mutex_lock(&ipath_mutex);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ if (ipath_diag_inuse) {
+ ret = -EBUSY;
+ goto bail;
+ }
+
+ list_for_each_entry(dd, &ipath_dev_list, ipath_list) {
+ /*
+ * we need at least one infinipath device to be present
+ * (don't use INITTED, because we want to be able to open
+ * even if device is in freeze mode, which cleared INITTED).
+ * There is a small amount of risk to this, which is why we
+ * also verify kregbase is set.
+ */
+
+ if (!(dd->ipath_flags & IPATH_PRESENT) ||
+ !dd->ipath_kregbase)
+ continue;
+
+ ipath_diag_inuse = 1;
+ diag_set_link = 0;
+ ret = 0;
+ goto bail;
+ }
+
+ ret = -ENODEV;
+
+bail:
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ /* Only expose a way to reset the device if we
+ make it into diag mode. */
+ if (ret == 0)
+ ipath_expose_reset(&dd->pcidev->dev);
+
+ mutex_unlock(&ipath_mutex);
+
+ return ret;
+}
+
+static int ipath_diag_release(struct inode *i, struct file *f)
+{
+ mutex_lock(&ipath_mutex);
+ ipath_diag_inuse = 0;
+ mutex_unlock(&ipath_mutex);
+ return 0;
+}
+
+static ssize_t ipath_diag_read(struct file *fp, char __user *data,
+ size_t count, loff_t *off)
+{
+ int unit = 0; /* XXX provide for reads on other units some day */
+ struct ipath_devdata *dd;
+ void __iomem *kreg_base;
+ ssize_t ret;
+
+ dd = ipath_lookup(unit);
+ if (!dd) {
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ kreg_base = dd->ipath_kregbase;
+
+ if (count == 0)
+ ret = 0;
+ else if ((count % 4) || (*off % 4))
+ /* address or length is not 32-bit aligned, hence invalid */
+ ret = -EINVAL;
+ else if ((count % 8) || (*off % 8))
+ /* address or length not 64-bit aligned; do 32-bit reads */
+ ret = ipath_read_umem32(dd, data, kreg_base + *off, count);
+ else
+ ret = ipath_read_umem64(dd, data, kreg_base + *off, count);
+
+ if (ret >= 0) {
+ *off += count;
+ ret = count;
+ }
+
+bail:
+ return ret;
+}
+
+static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
+ size_t count, loff_t *off)
+{
+ int unit = 0; /* XXX this is bogus */
+ struct ipath_devdata *dd;
+ void __iomem *kreg_base;
+ ssize_t ret;
+
+ dd = ipath_lookup(unit);
+ if (!dd) {
+ ret = -ENODEV;
+ goto bail;
+ }
+ kreg_base = dd->ipath_kregbase;
+
+ if (count == 0)
+ ret = 0;
+ else if ((count % 4) || (*off % 4))
+ /* address or length is not 32-bit aligned, hence invalid */
+ ret = -EINVAL;
+ else if ((count % 8) || (*off % 8))
+ /* address or length not 64-bit aligned; do 32-bit writes */
+ ret = ipath_write_umem32(dd, kreg_base + *off, data, count);
+ else
+ ret = ipath_write_umem64(dd, kreg_base + *off, data, count);
+
+ if (ret >= 0) {
+ *off += count;
+ ret = count;
+ }
+
+bail:
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
new file mode 100644
index 00000000000..dddcdae736a
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -0,0 +1,1992 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/idr.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+static void ipath_update_pio_bufs(struct ipath_devdata *);
+
+const char *ipath_get_unit_name(int unit)
+{
+ static char iname[16];
+ snprintf(iname, sizeof iname, "infinipath%u", unit);
+ return iname;
+}
+
+EXPORT_SYMBOL_GPL(ipath_get_unit_name);
+
+#define DRIVER_LOAD_MSG "PathScale " IPATH_DRV_NAME " loaded: "
+#define PFX IPATH_DRV_NAME ": "
+
+/*
+ * The size has to be longer than this string, so we can append
+ * board/chip information to it in the init code.
+ */
+const char ipath_core_version[] = IPATH_IDSTR "\n";
+
+static struct idr unit_table;
+DEFINE_SPINLOCK(ipath_devs_lock);
+LIST_HEAD(ipath_dev_list);
+
+wait_queue_head_t ipath_sma_state_wait;
+
+unsigned ipath_debug = __IPATH_INFO;
+
+module_param_named(debug, ipath_debug, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(debug, "mask for debug prints");
+EXPORT_SYMBOL_GPL(ipath_debug);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("PathScale <support@pathscale.com>");
+MODULE_DESCRIPTION("Pathscale InfiniPath driver");
+
+const char *ipath_ibcstatus_str[] = {
+ "Disabled",
+ "LinkUp",
+ "PollActive",
+ "PollQuiet",
+ "SleepDelay",
+ "SleepQuiet",
+ "LState6", /* unused */
+ "LState7", /* unused */
+ "CfgDebounce",
+ "CfgRcvfCfg",
+ "CfgWaitRmt",
+ "CfgIdle",
+ "RecovRetrain",
+ "LState0xD", /* unused */
+ "RecovWaitRmt",
+ "RecovIdle",
+};
+
+/*
+ * These variables are initialized in the chip-specific files
+ * but are defined here.
+ */
+u16 ipath_gpio_sda_num, ipath_gpio_scl_num;
+u64 ipath_gpio_sda, ipath_gpio_scl;
+u64 infinipath_i_bitsextant;
+ipath_err_t infinipath_e_bitsextant, infinipath_hwe_bitsextant;
+u32 infinipath_i_rcvavail_mask, infinipath_i_rcvurg_mask;
+
+static void __devexit ipath_remove_one(struct pci_dev *);
+static int __devinit ipath_init_one(struct pci_dev *,
+ const struct pci_device_id *);
+
+/* Only needed for registration, nothing else needs this info */
+#define PCI_VENDOR_ID_PATHSCALE 0x1fc1
+#define PCI_DEVICE_ID_INFINIPATH_HT 0xd
+#define PCI_DEVICE_ID_INFINIPATH_PE800 0x10
+
+static const struct pci_device_id ipath_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_HT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_PE800) },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, ipath_pci_tbl);
+
+static struct pci_driver ipath_driver = {
+ .name = IPATH_DRV_NAME,
+ .probe = ipath_init_one,
+ .remove = __devexit_p(ipath_remove_one),
+ .id_table = ipath_pci_tbl,
+};
+
+/*
+ * This is where port 0's rcvhdrtail register is written back; we also
+ * want nothing else sharing the cache line, so make it a cache line
+ * in size. Used for all units.
+ */
+volatile __le64 *ipath_port0_rcvhdrtail;
+dma_addr_t ipath_port0_rcvhdrtail_dma;
+static int port0_rcvhdrtail_refs;
+
+static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev,
+ u32 *bar0, u32 *bar1)
+{
+ int ret;
+
+ ret = pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
+ if (ret)
+ ipath_dev_err(dd, "failed to read bar0 before enable: "
+ "error %d\n", -ret);
+
+ ret = pci_read_config_dword(dev, PCI_BASE_ADDRESS_1, bar1);
+ if (ret)
+ ipath_dev_err(dd, "failed to read bar1 before enable: "
+ "error %d\n", -ret);
+
+ ipath_dbg("Read bar0 %x bar1 %x\n", *bar0, *bar1);
+}
+
+static void ipath_free_devdata(struct pci_dev *pdev,
+ struct ipath_devdata *dd)
+{
+ unsigned long flags;
+
+ pci_set_drvdata(pdev, NULL);
+
+ if (dd->ipath_unit != -1) {
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ idr_remove(&unit_table, dd->ipath_unit);
+ list_del(&dd->ipath_list);
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ }
+ dma_free_coherent(&pdev->dev, sizeof(*dd), dd, dd->ipath_dma_addr);
+}
+
+static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
+{
+ unsigned long flags;
+ struct ipath_devdata *dd;
+ dma_addr_t dma_addr;
+ int ret;
+
+ if (!idr_pre_get(&unit_table, GFP_KERNEL)) {
+ dd = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ dd = dma_alloc_coherent(&pdev->dev, sizeof(*dd), &dma_addr,
+ GFP_KERNEL);
+
+ if (!dd) {
+ dd = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ dd->ipath_dma_addr = dma_addr;
+ dd->ipath_unit = -1;
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ ret = idr_get_new(&unit_table, dd, &dd->ipath_unit);
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME
+ ": Could not allocate unit ID: error %d\n", -ret);
+ ipath_free_devdata(pdev, dd);
+ dd = ERR_PTR(ret);
+ goto bail_unlock;
+ }
+
+ dd->pcidev = pdev;
+ pci_set_drvdata(pdev, dd);
+
+ list_add(&dd->ipath_list, &ipath_dev_list);
+
+bail_unlock:
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+bail:
+ return dd;
+}
+
+static inline struct ipath_devdata *__ipath_lookup(int unit)
+{
+ return idr_find(&unit_table, unit);
+}
+
+struct ipath_devdata *ipath_lookup(int unit)
+{
+ struct ipath_devdata *dd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ dd = __ipath_lookup(unit);
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ return dd;
+}
+
+int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp)
+{
+ int nunits, npresent, nup;
+ struct ipath_devdata *dd;
+ unsigned long flags;
+ u32 maxports;
+
+ nunits = npresent = nup = maxports = 0;
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ list_for_each_entry(dd, &ipath_dev_list, ipath_list) {
+ nunits++;
+ if ((dd->ipath_flags & IPATH_PRESENT) && dd->ipath_kregbase)
+ npresent++;
+ if (dd->ipath_lid &&
+ !(dd->ipath_flags & (IPATH_DISABLED | IPATH_LINKDOWN
+ | IPATH_LINKUNK)))
+ nup++;
+ if (dd->ipath_cfgports > maxports)
+ maxports = dd->ipath_cfgports;
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ if (npresentp)
+ *npresentp = npresent;
+ if (nupp)
+ *nupp = nup;
+ if (maxportsp)
+ *maxportsp = maxports;
+
+ return nunits;
+}
+
+static int init_port0_rcvhdrtail(struct pci_dev *pdev)
+{
+ int ret;
+
+ mutex_lock(&ipath_mutex);
+
+ if (!ipath_port0_rcvhdrtail) {
+ ipath_port0_rcvhdrtail =
+ dma_alloc_coherent(&pdev->dev,
+ IPATH_PORT0_RCVHDRTAIL_SIZE,
+ &ipath_port0_rcvhdrtail_dma,
+ GFP_KERNEL);
+
+ if (!ipath_port0_rcvhdrtail) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ }
+ port0_rcvhdrtail_refs++;
+ ret = 0;
+
+bail:
+ mutex_unlock(&ipath_mutex);
+
+ return ret;
+}
+
+static void cleanup_port0_rcvhdrtail(struct pci_dev *pdev)
+{
+ mutex_lock(&ipath_mutex);
+
+ if (!--port0_rcvhdrtail_refs) {
+ dma_free_coherent(&pdev->dev, IPATH_PORT0_RCVHDRTAIL_SIZE,
+ (void *) ipath_port0_rcvhdrtail,
+ ipath_port0_rcvhdrtail_dma);
+ ipath_port0_rcvhdrtail = NULL;
+ }
+
+ mutex_unlock(&ipath_mutex);
+}
+
+/*
+ * These next two routines are placeholders in case we don't have per-arch
+ * code for controlling write combining. If explicit control of write
+ * combining is not available, performance will probably be awful.
+ */
+
+int __attribute__((weak)) ipath_enable_wc(struct ipath_devdata *dd)
+{
+ return -EOPNOTSUPP;
+}
+
+void __attribute__((weak)) ipath_disable_wc(struct ipath_devdata *dd)
+{
+}
+
+static int __devinit ipath_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int ret, len, j;
+ struct ipath_devdata *dd;
+ unsigned long long addr;
+ u32 bar0 = 0, bar1 = 0;
+ u8 rev;
+
+ ret = init_port0_rcvhdrtail(pdev);
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME
+ ": Could not allocate port0_rcvhdrtail: error %d\n",
+ -ret);
+ goto bail;
+ }
+
+ dd = ipath_alloc_devdata(pdev);
+ if (IS_ERR(dd)) {
+ ret = PTR_ERR(dd);
+ printk(KERN_ERR IPATH_DRV_NAME
+ ": Could not allocate devdata: error %d\n", -ret);
+ goto bail_rcvhdrtail;
+ }
+
+ ipath_cdbg(VERBOSE, "initializing unit #%u\n", dd->ipath_unit);
+
+ read_bars(dd, pdev, &bar0, &bar1);
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ /* This can happen iff:
+ *
+ * We did a chip reset, and then failed to reprogram the
+ * BAR, or the chip reset due to an internal error. We then
+ * unloaded the driver and reloaded it.
+ *
+ * Both reset cases set the BAR back to initial state. For
+ * the latter case, the AER sticky error bit at offset 0x718
+ * should be set, but the Linux kernel doesn't yet know
+ * about that, it appears. If the original BAR was retained
+ * in the kernel data structures, this may be OK.
+ */
+ ipath_dev_err(dd, "enable unit %d failed: error %d\n",
+ dd->ipath_unit, -ret);
+ goto bail_devdata;
+ }
+ addr = pci_resource_start(pdev, 0);
+ len = pci_resource_len(pdev, 0);
+ ipath_cdbg(VERBOSE, "regbase (0) %llx len %d irq %x, vend %x/%x "
+ "driver_data %lx\n", addr, len, pdev->irq, ent->vendor,
+ ent->device, ent->driver_data);
+
+ read_bars(dd, pdev, &bar0, &bar1);
+
+ if (!bar1 && !(bar0 & ~0xf)) {
+ if (addr) {
+ dev_info(&pdev->dev, "BAR is 0 (probable RESET), "
+ "rewriting as %llx\n", addr);
+ ret = pci_write_config_dword(
+ pdev, PCI_BASE_ADDRESS_0, addr);
+ if (ret) {
+ ipath_dev_err(dd, "rewrite of BAR0 "
+ "failed: err %d\n", -ret);
+ goto bail_disable;
+ }
+ ret = pci_write_config_dword(
+ pdev, PCI_BASE_ADDRESS_1, addr >> 32);
+ if (ret) {
+ ipath_dev_err(dd, "rewrite of BAR1 "
+ "failed: err %d\n", -ret);
+ goto bail_disable;
+ }
+ } else {
+ ipath_dev_err(dd, "BAR is 0 (probable RESET), "
+ "not usable until reboot\n");
+ ret = -ENODEV;
+ goto bail_disable;
+ }
+ }
+
+ ret = pci_request_regions(pdev, IPATH_DRV_NAME);
+ if (ret) {
+ dev_info(&pdev->dev, "pci_request_regions unit %u fails: "
+ "err %d\n", dd->ipath_unit, -ret);
+ goto bail_disable;
+ }
+
+ ret = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+ if (ret) {
+ /*
+ * if the 64 bit setup fails, try 32 bit. Some systems
+ * do not setup 64 bit maps on systems with 2GB or less
+ * memory installed.
+ */
+ ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (ret) {
+ dev_info(&pdev->dev, "pci_set_dma_mask unit %u "
+ "fails: %d\n", dd->ipath_unit, ret);
+ goto bail_regions;
+ }
+ else
+ ipath_dbg("No 64bit DMA mask, used 32 bit mask\n");
+ }
+
+ pci_set_master(pdev);
+
+ /*
+ * Save BARs to rewrite after device reset. Save all 64 bits of
+ * BAR, just in case.
+ */
+ dd->ipath_pcibar0 = addr;
+ dd->ipath_pcibar1 = addr >> 32;
+ dd->ipath_deviceid = ent->device; /* save for later use */
+ dd->ipath_vendorid = ent->vendor;
+
+ /* setup the chip-specific functions, as early as possible. */
+ switch (ent->device) {
+ case PCI_DEVICE_ID_INFINIPATH_HT:
+ ipath_init_ht400_funcs(dd);
+ break;
+ case PCI_DEVICE_ID_INFINIPATH_PE800:
+ ipath_init_pe800_funcs(dd);
+ break;
+ default:
+ ipath_dev_err(dd, "Found unknown PathScale deviceid 0x%x, "
+ "failing\n", ent->device);
+ return -ENODEV;
+ }
+
+ for (j = 0; j < 6; j++) {
+ if (!pdev->resource[j].start)
+ continue;
+ ipath_cdbg(VERBOSE, "BAR %d start %lx, end %lx, len %lx\n",
+ j, pdev->resource[j].start,
+ pdev->resource[j].end,
+ pci_resource_len(pdev, j));
+ }
+
+ if (!addr) {
+ ipath_dev_err(dd, "No valid address in BAR 0!\n");
+ ret = -ENODEV;
+ goto bail_regions;
+ }
+
+ dd->ipath_deviceid = ent->device; /* save for later use */
+ dd->ipath_vendorid = ent->vendor;
+
+ ret = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+ if (ret) {
+ ipath_dev_err(dd, "Failed to read PCI revision ID unit "
+ "%u: err %d\n", dd->ipath_unit, -ret);
+ goto bail_regions; /* shouldn't ever happen */
+ }
+ dd->ipath_pcirev = rev;
+
+ dd->ipath_kregbase = ioremap_nocache(addr, len);
+
+ if (!dd->ipath_kregbase) {
+ ipath_dbg("Unable to map io addr %llx to kvirt, failing\n",
+ addr);
+ ret = -ENOMEM;
+ goto bail_iounmap;
+ }
+ dd->ipath_kregend = (u64 __iomem *)
+ ((void __iomem *)dd->ipath_kregbase + len);
+ dd->ipath_physaddr = addr; /* used for io_remap, etc. */
+ /* for user mmap */
+ dd->ipath_kregvirt = (u64 __iomem *) phys_to_virt(addr);
+ ipath_cdbg(VERBOSE, "mapped io addr %llx to kregbase %p "
+ "kregvirt %p\n", addr, dd->ipath_kregbase,
+ dd->ipath_kregvirt);
+
+ /*
+ * clear ipath_flags here instead of in ipath_init_chip as it is set
+ * by ipath_setup_htconfig.
+ */
+ dd->ipath_flags = 0;
+
+ if (dd->ipath_f_bus(dd, pdev))
+ ipath_dev_err(dd, "Failed to setup config space; "
+ "continuing anyway\n");
+
+ /*
+ * set up our interrupt handler; SA_SHIRQ probably not needed,
+ * since MSI interrupts shouldn't be shared but won't hurt for now.
+ * check 0 irq after we return from chip-specific bus setup, since
+ * that can affect this due to setup
+ */
+ if (!pdev->irq)
+ ipath_dev_err(dd, "irq is 0, BIOS error? Interrupts won't "
+ "work\n");
+ else {
+ ret = request_irq(pdev->irq, ipath_intr, SA_SHIRQ,
+ IPATH_DRV_NAME, dd);
+ if (ret) {
+ ipath_dev_err(dd, "Couldn't setup irq handler, "
+ "irq=%u: %d\n", pdev->irq, ret);
+ goto bail_iounmap;
+ }
+ }
+
+ ret = ipath_init_chip(dd, 0); /* do the chip-specific init */
+ if (ret)
+ goto bail_iounmap;
+
+ ret = ipath_enable_wc(dd);
+
+ if (ret) {
+ ipath_dev_err(dd, "Write combining not enabled "
+ "(err %d): performance may be poor\n",
+ -ret);
+ ret = 0;
+ }
+
+ ipath_device_create_group(&pdev->dev, dd);
+ ipathfs_add_device(dd);
+ ipath_user_add(dd);
+ ipath_layer_add(dd);
+
+ goto bail;
+
+bail_iounmap:
+ iounmap((volatile void __iomem *) dd->ipath_kregbase);
+
+bail_regions:
+ pci_release_regions(pdev);
+
+bail_disable:
+ pci_disable_device(pdev);
+
+bail_devdata:
+ ipath_free_devdata(pdev, dd);
+
+bail_rcvhdrtail:
+ cleanup_port0_rcvhdrtail(pdev);
+
+bail:
+ return ret;
+}
+
+static void __devexit ipath_remove_one(struct pci_dev *pdev)
+{
+ struct ipath_devdata *dd;
+
+ ipath_cdbg(VERBOSE, "removing, pdev=%p\n", pdev);
+ if (!pdev)
+ return;
+
+ dd = pci_get_drvdata(pdev);
+ ipath_layer_del(dd);
+ ipath_user_del(dd);
+ ipathfs_remove_device(dd);
+ ipath_device_remove_group(&pdev->dev, dd);
+ ipath_cdbg(VERBOSE, "Releasing pci memory regions, dd %p, "
+ "unit %u\n", dd, (u32) dd->ipath_unit);
+ if (dd->ipath_kregbase) {
+ ipath_cdbg(VERBOSE, "Unmapping kregbase %p\n",
+ dd->ipath_kregbase);
+ iounmap((volatile void __iomem *) dd->ipath_kregbase);
+ dd->ipath_kregbase = NULL;
+ }
+ pci_release_regions(pdev);
+ ipath_cdbg(VERBOSE, "calling pci_disable_device\n");
+ pci_disable_device(pdev);
+
+ ipath_free_devdata(pdev, dd);
+ cleanup_port0_rcvhdrtail(pdev);
+}
+
+/* general driver use */
+DEFINE_MUTEX(ipath_mutex);
+
+static DEFINE_SPINLOCK(ipath_pioavail_lock);
+
+/**
+ * ipath_disarm_piobufs - cancel a range of PIO buffers
+ * @dd: the infinipath device
+ * @first: the first PIO buffer to cancel
+ * @cnt: the number of PIO buffers to cancel
+ *
+ * cancel a range of PIO buffers, used when they might be armed, but
+ * not triggered. Used at init to ensure buffer state, and also user
+ * process close, in case it died while writing to a PIO buffer
+ * Also after errors.
+ */
+void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
+ unsigned cnt)
+{
+ unsigned i, last = first + cnt;
+ u64 sendctrl, sendorig;
+
+ ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first);
+ sendorig = dd->ipath_sendctrl | INFINIPATH_S_DISARM;
+ for (i = first; i < last; i++) {
+ sendctrl = sendorig |
+ (i << INFINIPATH_S_DISARMPIOBUF_SHIFT);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ sendctrl);
+ }
+
+ /*
+ * Write it again with current value, in case ipath_sendctrl changed
+ * while we were looping; no critical bits that would require
+ * locking.
+ *
+ * Write a 0, and then the original value, reading scratch in
+ * between. This seems to avoid a chip timing race that causes
+ * pioavail updates to memory to stop.
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ 0);
+ sendorig = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+}
+
+/**
+ * ipath_wait_linkstate - wait for an IB link state change to occur
+ * @dd: the infinipath device
+ * @state: the state to wait for
+ * @msecs: the number of milliseconds to wait
+ *
+ * wait up to msecs milliseconds for IB link state change to occur for
+ * now, take the easy polling route. Currently used only by
+ * ipath_layer_set_linkstate. Returns 0 if state reached, otherwise
+ * -ETIMEDOUT state can have multiple states set, for any of several
+ * transitions.
+ */
+int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, int msecs)
+{
+ dd->ipath_sma_state_wanted = state;
+ wait_event_interruptible_timeout(ipath_sma_state_wait,
+ (dd->ipath_flags & state),
+ msecs_to_jiffies(msecs));
+ dd->ipath_sma_state_wanted = 0;
+
+ if (!(dd->ipath_flags & state)) {
+ u64 val;
+ ipath_cdbg(SMA, "Didn't reach linkstate %s within %u ms\n",
+ /* test INIT ahead of DOWN, both can be set */
+ (state & IPATH_LINKINIT) ? "INIT" :
+ ((state & IPATH_LINKDOWN) ? "DOWN" :
+ ((state & IPATH_LINKARMED) ? "ARM" : "ACTIVE")),
+ msecs);
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+ ipath_cdbg(VERBOSE, "ibcc=%llx ibcstatus=%llx (%s)\n",
+ (unsigned long long) ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_ibcctrl),
+ (unsigned long long) val,
+ ipath_ibcstatus_str[val & 0xf]);
+ }
+ return (dd->ipath_flags & state) ? 0 : -ETIMEDOUT;
+}
+
+void ipath_decode_err(char *buf, size_t blen, ipath_err_t err)
+{
+ *buf = '\0';
+ if (err & INFINIPATH_E_RHDRLEN)
+ strlcat(buf, "rhdrlen ", blen);
+ if (err & INFINIPATH_E_RBADTID)
+ strlcat(buf, "rbadtid ", blen);
+ if (err & INFINIPATH_E_RBADVERSION)
+ strlcat(buf, "rbadversion ", blen);
+ if (err & INFINIPATH_E_RHDR)
+ strlcat(buf, "rhdr ", blen);
+ if (err & INFINIPATH_E_RLONGPKTLEN)
+ strlcat(buf, "rlongpktlen ", blen);
+ if (err & INFINIPATH_E_RSHORTPKTLEN)
+ strlcat(buf, "rshortpktlen ", blen);
+ if (err & INFINIPATH_E_RMAXPKTLEN)
+ strlcat(buf, "rmaxpktlen ", blen);
+ if (err & INFINIPATH_E_RMINPKTLEN)
+ strlcat(buf, "rminpktlen ", blen);
+ if (err & INFINIPATH_E_RFORMATERR)
+ strlcat(buf, "rformaterr ", blen);
+ if (err & INFINIPATH_E_RUNSUPVL)
+ strlcat(buf, "runsupvl ", blen);
+ if (err & INFINIPATH_E_RUNEXPCHAR)
+ strlcat(buf, "runexpchar ", blen);
+ if (err & INFINIPATH_E_RIBFLOW)
+ strlcat(buf, "ribflow ", blen);
+ if (err & INFINIPATH_E_REBP)
+ strlcat(buf, "EBP ", blen);
+ if (err & INFINIPATH_E_SUNDERRUN)
+ strlcat(buf, "sunderrun ", blen);
+ if (err & INFINIPATH_E_SPIOARMLAUNCH)
+ strlcat(buf, "spioarmlaunch ", blen);
+ if (err & INFINIPATH_E_SUNEXPERRPKTNUM)
+ strlcat(buf, "sunexperrpktnum ", blen);
+ if (err & INFINIPATH_E_SDROPPEDDATAPKT)
+ strlcat(buf, "sdroppeddatapkt ", blen);
+ if (err & INFINIPATH_E_SDROPPEDSMPPKT)
+ strlcat(buf, "sdroppedsmppkt ", blen);
+ if (err & INFINIPATH_E_SMAXPKTLEN)
+ strlcat(buf, "smaxpktlen ", blen);
+ if (err & INFINIPATH_E_SMINPKTLEN)
+ strlcat(buf, "sminpktlen ", blen);
+ if (err & INFINIPATH_E_SUNSUPVL)
+ strlcat(buf, "sunsupVL ", blen);
+ if (err & INFINIPATH_E_SPKTLEN)
+ strlcat(buf, "spktlen ", blen);
+ if (err & INFINIPATH_E_INVALIDADDR)
+ strlcat(buf, "invalidaddr ", blen);
+ if (err & INFINIPATH_E_RICRC)
+ strlcat(buf, "CRC ", blen);
+ if (err & INFINIPATH_E_RVCRC)
+ strlcat(buf, "VCRC ", blen);
+ if (err & INFINIPATH_E_RRCVEGRFULL)
+ strlcat(buf, "rcvegrfull ", blen);
+ if (err & INFINIPATH_E_RRCVHDRFULL)
+ strlcat(buf, "rcvhdrfull ", blen);
+ if (err & INFINIPATH_E_IBSTATUSCHANGED)
+ strlcat(buf, "ibcstatuschg ", blen);
+ if (err & INFINIPATH_E_RIBLOSTLINK)
+ strlcat(buf, "riblostlink ", blen);
+ if (err & INFINIPATH_E_HARDWARE)
+ strlcat(buf, "hardware ", blen);
+ if (err & INFINIPATH_E_RESET)
+ strlcat(buf, "reset ", blen);
+}
+
+/**
+ * get_rhf_errstring - decode RHF errors
+ * @err: the err number
+ * @msg: the output buffer
+ * @len: the length of the output buffer
+ *
+ * only used one place now, may want more later
+ */
+static void get_rhf_errstring(u32 err, char *msg, size_t len)
+{
+ /* if no errors, and so don't need to check what's first */
+ *msg = '\0';
+
+ if (err & INFINIPATH_RHF_H_ICRCERR)
+ strlcat(msg, "icrcerr ", len);
+ if (err & INFINIPATH_RHF_H_VCRCERR)
+ strlcat(msg, "vcrcerr ", len);
+ if (err & INFINIPATH_RHF_H_PARITYERR)
+ strlcat(msg, "parityerr ", len);
+ if (err & INFINIPATH_RHF_H_LENERR)
+ strlcat(msg, "lenerr ", len);
+ if (err & INFINIPATH_RHF_H_MTUERR)
+ strlcat(msg, "mtuerr ", len);
+ if (err & INFINIPATH_RHF_H_IHDRERR)
+ /* infinipath hdr checksum error */
+ strlcat(msg, "ipathhdrerr ", len);
+ if (err & INFINIPATH_RHF_H_TIDERR)
+ strlcat(msg, "tiderr ", len);
+ if (err & INFINIPATH_RHF_H_MKERR)
+ /* bad port, offset, etc. */
+ strlcat(msg, "invalid ipathhdr ", len);
+ if (err & INFINIPATH_RHF_H_IBERR)
+ strlcat(msg, "iberr ", len);
+ if (err & INFINIPATH_RHF_L_SWA)
+ strlcat(msg, "swA ", len);
+ if (err & INFINIPATH_RHF_L_SWB)
+ strlcat(msg, "swB ", len);
+}
+
+/**
+ * ipath_get_egrbuf - get an eager buffer
+ * @dd: the infinipath device
+ * @bufnum: the eager buffer to get
+ * @err: unused
+ *
+ * must only be called if ipath_pd[port] is known to be allocated
+ */
+static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum,
+ int err)
+{
+ return dd->ipath_port0_skbs ?
+ (void *)dd->ipath_port0_skbs[bufnum]->data : NULL;
+}
+
+/**
+ * ipath_alloc_skb - allocate an skb and buffer with possible constraints
+ * @dd: the infinipath device
+ * @gfp_mask: the sk_buff SFP mask
+ */
+struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd,
+ gfp_t gfp_mask)
+{
+ struct sk_buff *skb;
+ u32 len;
+
+ /*
+ * Only fully supported way to handle this is to allocate lots
+ * extra, align as needed, and then do skb_reserve(). That wastes
+ * a lot of memory... I'll have to hack this into infinipath_copy
+ * also.
+ */
+
+ /*
+ * We need 4 extra bytes for unaligned transfer copying
+ */
+ if (dd->ipath_flags & IPATH_4BYTE_TID) {
+ /* we need a 4KB multiple alignment, and there is no way
+ * to do it except to allocate extra and then skb_reserve
+ * enough to bring it up to the right alignment.
+ */
+ len = dd->ipath_ibmaxlen + 4 + (1 << 11) - 1;
+ }
+ else
+ len = dd->ipath_ibmaxlen + 4;
+ skb = __dev_alloc_skb(len, gfp_mask);
+ if (!skb) {
+ ipath_dev_err(dd, "Failed to allocate skbuff, length %u\n",
+ len);
+ goto bail;
+ }
+ if (dd->ipath_flags & IPATH_4BYTE_TID) {
+ u32 una = ((1 << 11) - 1) & (unsigned long)(skb->data + 4);
+ if (una)
+ skb_reserve(skb, 4 + (1 << 11) - una);
+ else
+ skb_reserve(skb, 4);
+ } else
+ skb_reserve(skb, 4);
+
+bail:
+ return skb;
+}
+
+/**
+ * ipath_rcv_layer - receive a packet for the layered (ethernet) driver
+ * @dd: the infinipath device
+ * @etail: the sk_buff number
+ * @tlen: the total packet length
+ * @hdr: the ethernet header
+ *
+ * Separate routine for better overall optimization
+ */
+static void ipath_rcv_layer(struct ipath_devdata *dd, u32 etail,
+ u32 tlen, struct ether_header *hdr)
+{
+ u32 elen;
+ u8 pad, *bthbytes;
+ struct sk_buff *skb, *nskb;
+
+ if (dd->ipath_port0_skbs && hdr->sub_opcode == OPCODE_ENCAP) {
+ /*
+ * Allocate a new sk_buff to replace the one we give
+ * to the network stack.
+ */
+ nskb = ipath_alloc_skb(dd, GFP_ATOMIC);
+ if (!nskb) {
+ /* count OK packets that we drop */
+ ipath_stats.sps_krdrops++;
+ return;
+ }
+
+ bthbytes = (u8 *) hdr->bth;
+ pad = (bthbytes[1] >> 4) & 3;
+ /* +CRC32 */
+ elen = tlen - (sizeof(*hdr) + pad + sizeof(u32));
+
+ skb = dd->ipath_port0_skbs[etail];
+ dd->ipath_port0_skbs[etail] = nskb;
+ skb_put(skb, elen);
+
+ dd->ipath_f_put_tid(dd, etail + (u64 __iomem *)
+ ((char __iomem *) dd->ipath_kregbase
+ + dd->ipath_rcvegrbase), 0,
+ virt_to_phys(nskb->data));
+
+ __ipath_layer_rcv(dd, hdr, skb);
+
+ /* another ether packet received */
+ ipath_stats.sps_ether_rpkts++;
+ }
+ else if (hdr->sub_opcode == OPCODE_LID_ARP)
+ __ipath_layer_rcv_lid(dd, hdr);
+}
+
+/*
+ * ipath_kreceive - receive a packet
+ * @dd: the infinipath device
+ *
+ * called from interrupt handler for errors or receive interrupt
+ */
+void ipath_kreceive(struct ipath_devdata *dd)
+{
+ u64 *rc;
+ void *ebuf;
+ const u32 rsize = dd->ipath_rcvhdrentsize; /* words */
+ const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize; /* words */
+ u32 etail = -1, l, hdrqtail;
+ struct ips_message_header *hdr;
+ u32 eflags, i, etype, tlen, pkttot = 0;
+ static u64 totcalls; /* stats, may eventually remove */
+ char emsg[128];
+
+ if (!dd->ipath_hdrqtailptr) {
+ ipath_dev_err(dd,
+ "hdrqtailptr not set, can't do receives\n");
+ goto bail;
+ }
+
+ /* There is already a thread processing this queue. */
+ if (test_and_set_bit(0, &dd->ipath_rcv_pending))
+ goto bail;
+
+ if (dd->ipath_port0head ==
+ (u32)le64_to_cpu(*dd->ipath_hdrqtailptr))
+ goto done;
+
+gotmore:
+ /*
+ * read only once at start. If in flood situation, this helps
+ * performance slightly. If more arrive while we are processing,
+ * we'll come back here and do them
+ */
+ hdrqtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr);
+
+ for (i = 0, l = dd->ipath_port0head; l != hdrqtail; i++) {
+ u32 qp;
+ u8 *bthbytes;
+
+ rc = (u64 *) (dd->ipath_pd[0]->port_rcvhdrq + (l << 2));
+ hdr = (struct ips_message_header *)&rc[1];
+ /*
+ * could make a network order version of IPATH_KD_QP, and
+ * do the obvious shift before masking to speed this up.
+ */
+ qp = ntohl(hdr->bth[1]) & 0xffffff;
+ bthbytes = (u8 *) hdr->bth;
+
+ eflags = ips_get_hdr_err_flags((__le32 *) rc);
+ etype = ips_get_rcv_type((__le32 *) rc);
+ /* total length */
+ tlen = ips_get_length_in_bytes((__le32 *) rc);
+ ebuf = NULL;
+ if (etype != RCVHQ_RCV_TYPE_EXPECTED) {
+ /*
+ * it turns out that the chips uses an eager buffer
+ * for all non-expected packets, whether it "needs"
+ * one or not. So always get the index, but don't
+ * set ebuf (so we try to copy data) unless the
+ * length requires it.
+ */
+ etail = ips_get_index((__le32 *) rc);
+ if (tlen > sizeof(*hdr) ||
+ etype == RCVHQ_RCV_TYPE_NON_KD)
+ ebuf = ipath_get_egrbuf(dd, etail, 0);
+ }
+
+ /*
+ * both tiderr and ipathhdrerr are set for all plain IB
+ * packets; only ipathhdrerr should be set.
+ */
+
+ if (etype != RCVHQ_RCV_TYPE_NON_KD && etype !=
+ RCVHQ_RCV_TYPE_ERROR && ips_get_ipath_ver(
+ hdr->iph.ver_port_tid_offset) !=
+ IPS_PROTO_VERSION) {
+ ipath_cdbg(PKT, "Bad InfiniPath protocol version "
+ "%x\n", etype);
+ }
+
+ if (eflags & ~(INFINIPATH_RHF_H_TIDERR |
+ INFINIPATH_RHF_H_IHDRERR)) {
+ get_rhf_errstring(eflags, emsg, sizeof emsg);
+ ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u "
+ "tlen=%x opcode=%x egridx=%x: %s\n",
+ eflags, l, etype, tlen, bthbytes[0],
+ ips_get_index((__le32 *) rc), emsg);
+ } else if (etype == RCVHQ_RCV_TYPE_NON_KD) {
+ int ret = __ipath_verbs_rcv(dd, rc + 1,
+ ebuf, tlen);
+ if (ret == -ENODEV)
+ ipath_cdbg(VERBOSE,
+ "received IB packet, "
+ "not SMA (QP=%x)\n", qp);
+ } else if (etype == RCVHQ_RCV_TYPE_EAGER) {
+ if (qp == IPATH_KD_QP &&
+ bthbytes[0] == ipath_layer_rcv_opcode &&
+ ebuf)
+ ipath_rcv_layer(dd, etail, tlen,
+ (struct ether_header *)hdr);
+ else
+ ipath_cdbg(PKT, "typ %x, opcode %x (eager, "
+ "qp=%x), len %x; ignored\n",
+ etype, bthbytes[0], qp, tlen);
+ }
+ else if (etype == RCVHQ_RCV_TYPE_EXPECTED)
+ ipath_dbg("Bug: Expected TID, opcode %x; ignored\n",
+ be32_to_cpu(hdr->bth[0]) & 0xff);
+ else if (eflags & (INFINIPATH_RHF_H_TIDERR |
+ INFINIPATH_RHF_H_IHDRERR)) {
+ /*
+ * This is a type 3 packet, only the LRH is in the
+ * rcvhdrq, the rest of the header is in the eager
+ * buffer.
+ */
+ u8 opcode;
+ if (ebuf) {
+ bthbytes = (u8 *) ebuf;
+ opcode = *bthbytes;
+ }
+ else
+ opcode = 0;
+ get_rhf_errstring(eflags, emsg, sizeof emsg);
+ ipath_dbg("Err %x (%s), opcode %x, egrbuf %x, "
+ "len %x\n", eflags, emsg, opcode, etail,
+ tlen);
+ } else {
+ /*
+ * error packet, type of error unknown.
+ * Probably type 3, but we don't know, so don't
+ * even try to print the opcode, etc.
+ */
+ ipath_dbg("Error Pkt, but no eflags! egrbuf %x, "
+ "len %x\nhdrq@%lx;hdrq+%x rhf: %llx; "
+ "hdr %llx %llx %llx %llx %llx\n",
+ etail, tlen, (unsigned long) rc, l,
+ (unsigned long long) rc[0],
+ (unsigned long long) rc[1],
+ (unsigned long long) rc[2],
+ (unsigned long long) rc[3],
+ (unsigned long long) rc[4],
+ (unsigned long long) rc[5]);
+ }
+ l += rsize;
+ if (l >= maxcnt)
+ l = 0;
+ /*
+ * update for each packet, to help prevent overflows if we
+ * have lots of packets.
+ */
+ (void)ipath_write_ureg(dd, ur_rcvhdrhead,
+ dd->ipath_rhdrhead_intr_off | l, 0);
+ if (etype != RCVHQ_RCV_TYPE_EXPECTED)
+ (void)ipath_write_ureg(dd, ur_rcvegrindexhead,
+ etail, 0);
+ }
+
+ pkttot += i;
+
+ dd->ipath_port0head = l;
+
+ if (hdrqtail != (u32)le64_to_cpu(*dd->ipath_hdrqtailptr))
+ /* more arrived while we handled first batch */
+ goto gotmore;
+
+ if (pkttot > ipath_stats.sps_maxpkts_call)
+ ipath_stats.sps_maxpkts_call = pkttot;
+ ipath_stats.sps_port0pkts += pkttot;
+ ipath_stats.sps_avgpkts_call =
+ ipath_stats.sps_port0pkts / ++totcalls;
+
+done:
+ clear_bit(0, &dd->ipath_rcv_pending);
+ smp_mb__after_clear_bit();
+
+bail:;
+}
+
+/**
+ * ipath_update_pio_bufs - update shadow copy of the PIO availability map
+ * @dd: the infinipath device
+ *
+ * called whenever our local copy indicates we have run out of send buffers
+ * NOTE: This can be called from interrupt context by some code
+ * and from non-interrupt context by ipath_getpiobuf().
+ */
+
+static void ipath_update_pio_bufs(struct ipath_devdata *dd)
+{
+ unsigned long flags;
+ int i;
+ const unsigned piobregs = (unsigned)dd->ipath_pioavregs;
+
+ /* If the generation (check) bits have changed, then we update the
+ * busy bit for the corresponding PIO buffer. This algorithm will
+ * modify positions to the value they already have in some cases
+ * (i.e., no change), but it's faster than changing only the bits
+ * that have changed.
+ *
+ * We would like to do this atomicly, to avoid spinlocks in the
+ * critical send path, but that's not really possible, given the
+ * type of changes, and that this routine could be called on
+ * multiple cpu's simultaneously, so we lock in this routine only,
+ * to avoid conflicting updates; all we change is the shadow, and
+ * it's a single 64 bit memory location, so by definition the update
+ * is atomic in terms of what other cpu's can see in testing the
+ * bits. The spin_lock overhead isn't too bad, since it only
+ * happens when all buffers are in use, so only cpu overhead, not
+ * latency or bandwidth is affected.
+ */
+#define _IPATH_ALL_CHECKBITS 0x5555555555555555ULL
+ if (!dd->ipath_pioavailregs_dma) {
+ ipath_dbg("Update shadow pioavail, but regs_dma NULL!\n");
+ return;
+ }
+ if (ipath_debug & __IPATH_VERBDBG) {
+ /* only if packet debug and verbose */
+ volatile __le64 *dma = dd->ipath_pioavailregs_dma;
+ unsigned long *shadow = dd->ipath_pioavailshadow;
+
+ ipath_cdbg(PKT, "Refill avail, dma0=%llx shad0=%lx, "
+ "d1=%llx s1=%lx, d2=%llx s2=%lx, d3=%llx "
+ "s3=%lx\n",
+ (unsigned long long) le64_to_cpu(dma[0]),
+ shadow[0],
+ (unsigned long long) le64_to_cpu(dma[1]),
+ shadow[1],
+ (unsigned long long) le64_to_cpu(dma[2]),
+ shadow[2],
+ (unsigned long long) le64_to_cpu(dma[3]),
+ shadow[3]);
+ if (piobregs > 4)
+ ipath_cdbg(
+ PKT, "2nd group, dma4=%llx shad4=%lx, "
+ "d5=%llx s5=%lx, d6=%llx s6=%lx, "
+ "d7=%llx s7=%lx\n",
+ (unsigned long long) le64_to_cpu(dma[4]),
+ shadow[4],
+ (unsigned long long) le64_to_cpu(dma[5]),
+ shadow[5],
+ (unsigned long long) le64_to_cpu(dma[6]),
+ shadow[6],
+ (unsigned long long) le64_to_cpu(dma[7]),
+ shadow[7]);
+ }
+ spin_lock_irqsave(&ipath_pioavail_lock, flags);
+ for (i = 0; i < piobregs; i++) {
+ u64 pchbusy, pchg, piov, pnew;
+ /*
+ * Chip Errata: bug 6641; even and odd qwords>3 are swapped
+ */
+ if (i > 3) {
+ if (i & 1)
+ piov = le64_to_cpu(
+ dd->ipath_pioavailregs_dma[i - 1]);
+ else
+ piov = le64_to_cpu(
+ dd->ipath_pioavailregs_dma[i + 1]);
+ } else
+ piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i]);
+ pchg = _IPATH_ALL_CHECKBITS &
+ ~(dd->ipath_pioavailshadow[i] ^ piov);
+ pchbusy = pchg << INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT;
+ if (pchg && (pchbusy & dd->ipath_pioavailshadow[i])) {
+ pnew = dd->ipath_pioavailshadow[i] & ~pchbusy;
+ pnew |= piov & pchbusy;
+ dd->ipath_pioavailshadow[i] = pnew;
+ }
+ }
+ spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
+}
+
+/**
+ * ipath_setrcvhdrsize - set the receive header size
+ * @dd: the infinipath device
+ * @rhdrsize: the receive header size
+ *
+ * called from user init code, and also layered driver init
+ */
+int ipath_setrcvhdrsize(struct ipath_devdata *dd, unsigned rhdrsize)
+{
+ int ret = 0;
+
+ if (dd->ipath_flags & IPATH_RCVHDRSZ_SET) {
+ if (dd->ipath_rcvhdrsize != rhdrsize) {
+ dev_info(&dd->pcidev->dev,
+ "Error: can't set protocol header "
+ "size %u, already %u\n",
+ rhdrsize, dd->ipath_rcvhdrsize);
+ ret = -EAGAIN;
+ } else
+ ipath_cdbg(VERBOSE, "Reuse same protocol header "
+ "size %u\n", dd->ipath_rcvhdrsize);
+ } else if (rhdrsize > (dd->ipath_rcvhdrentsize -
+ (sizeof(u64) / sizeof(u32)))) {
+ ipath_dbg("Error: can't set protocol header size %u "
+ "(> max %u)\n", rhdrsize,
+ dd->ipath_rcvhdrentsize -
+ (u32) (sizeof(u64) / sizeof(u32)));
+ ret = -EOVERFLOW;
+ } else {
+ dd->ipath_flags |= IPATH_RCVHDRSZ_SET;
+ dd->ipath_rcvhdrsize = rhdrsize;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrsize,
+ dd->ipath_rcvhdrsize);
+ ipath_cdbg(VERBOSE, "Set protocol header size to %u\n",
+ dd->ipath_rcvhdrsize);
+ }
+ return ret;
+}
+
+/**
+ * ipath_getpiobuf - find an available pio buffer
+ * @dd: the infinipath device
+ * @pbufnum: the buffer number is placed here
+ *
+ * do appropriate marking as busy, etc.
+ * returns buffer number if one found (>=0), negative number is error.
+ * Used by ipath_sma_send_pkt and ipath_layer_send
+ */
+u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 * pbufnum)
+{
+ int i, j, starti, updated = 0;
+ unsigned piobcnt, iter;
+ unsigned long flags;
+ unsigned long *shadow = dd->ipath_pioavailshadow;
+ u32 __iomem *buf;
+
+ piobcnt = (unsigned)(dd->ipath_piobcnt2k
+ + dd->ipath_piobcnt4k);
+ starti = dd->ipath_lastport_piobuf;
+ iter = piobcnt - starti;
+ if (dd->ipath_upd_pio_shadow) {
+ /*
+ * Minor optimization. If we had no buffers on last call,
+ * start out by doing the update; continue and do scan even
+ * if no buffers were updated, to be paranoid
+ */
+ ipath_update_pio_bufs(dd);
+ /* we scanned here, don't do it at end of scan */
+ updated = 1;
+ i = starti;
+ } else
+ i = dd->ipath_lastpioindex;
+
+rescan:
+ /*
+ * while test_and_set_bit() is atomic, we do that and then the
+ * change_bit(), and the pair is not. See if this is the cause
+ * of the remaining armlaunch errors.
+ */
+ spin_lock_irqsave(&ipath_pioavail_lock, flags);
+ for (j = 0; j < iter; j++, i++) {
+ if (i >= piobcnt)
+ i = starti;
+ /*
+ * To avoid bus lock overhead, we first find a candidate
+ * buffer, then do the test and set, and continue if that
+ * fails.
+ */
+ if (test_bit((2 * i) + 1, shadow) ||
+ test_and_set_bit((2 * i) + 1, shadow))
+ continue;
+ /* flip generation bit */
+ change_bit(2 * i, shadow);
+ break;
+ }
+ spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
+
+ if (j == iter) {
+ volatile __le64 *dma = dd->ipath_pioavailregs_dma;
+
+ /*
+ * first time through; shadow exhausted, but may be real
+ * buffers available, so go see; if any updated, rescan
+ * (once)
+ */
+ if (!updated) {
+ ipath_update_pio_bufs(dd);
+ updated = 1;
+ i = starti;
+ goto rescan;
+ }
+ dd->ipath_upd_pio_shadow = 1;
+ /*
+ * not atomic, but if we lose one once in a while, that's OK
+ */
+ ipath_stats.sps_nopiobufs++;
+ if (!(++dd->ipath_consec_nopiobuf % 100000)) {
+ ipath_dbg(
+ "%u pio sends with no bufavail; dmacopy: "
+ "%llx %llx %llx %llx; shadow: "
+ "%lx %lx %lx %lx\n",
+ dd->ipath_consec_nopiobuf,
+ (unsigned long long) le64_to_cpu(dma[0]),
+ (unsigned long long) le64_to_cpu(dma[1]),
+ (unsigned long long) le64_to_cpu(dma[2]),
+ (unsigned long long) le64_to_cpu(dma[3]),
+ shadow[0], shadow[1], shadow[2],
+ shadow[3]);
+ /*
+ * 4 buffers per byte, 4 registers above, cover rest
+ * below
+ */
+ if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) >
+ (sizeof(shadow[0]) * 4 * 4))
+ ipath_dbg("2nd group: dmacopy: %llx %llx "
+ "%llx %llx; shadow: %lx %lx "
+ "%lx %lx\n",
+ (unsigned long long)
+ le64_to_cpu(dma[4]),
+ (unsigned long long)
+ le64_to_cpu(dma[5]),
+ (unsigned long long)
+ le64_to_cpu(dma[6]),
+ (unsigned long long)
+ le64_to_cpu(dma[7]),
+ shadow[4], shadow[5],
+ shadow[6], shadow[7]);
+ }
+ buf = NULL;
+ goto bail;
+ }
+
+ if (updated)
+ /*
+ * ran out of bufs, now some (at least this one we just
+ * got) are now available, so tell the layered driver.
+ */
+ __ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE);
+
+ /*
+ * set next starting place. Since it's just an optimization,
+ * it doesn't matter who wins on this, so no locking
+ */
+ dd->ipath_lastpioindex = i + 1;
+ if (dd->ipath_upd_pio_shadow)
+ dd->ipath_upd_pio_shadow = 0;
+ if (dd->ipath_consec_nopiobuf)
+ dd->ipath_consec_nopiobuf = 0;
+ if (i < dd->ipath_piobcnt2k)
+ buf = (u32 __iomem *) (dd->ipath_pio2kbase +
+ i * dd->ipath_palign);
+ else
+ buf = (u32 __iomem *)
+ (dd->ipath_pio4kbase +
+ (i - dd->ipath_piobcnt2k) * dd->ipath_4kalign);
+ ipath_cdbg(VERBOSE, "Return piobuf%u %uk @ %p\n",
+ i, (i < dd->ipath_piobcnt2k) ? 2 : 4, buf);
+ if (pbufnum)
+ *pbufnum = i;
+
+bail:
+ return buf;
+}
+
+/**
+ * ipath_create_rcvhdrq - create a receive header queue
+ * @dd: the infinipath device
+ * @pd: the port data
+ *
+ * this *must* be physically contiguous memory, and for now,
+ * that limits it to what kmalloc can do.
+ */
+int ipath_create_rcvhdrq(struct ipath_devdata *dd,
+ struct ipath_portdata *pd)
+{
+ int ret = 0, amt;
+
+ amt = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize *
+ sizeof(u32), PAGE_SIZE);
+ if (!pd->port_rcvhdrq) {
+ /*
+ * not using REPEAT isn't viable; at 128KB, we can easily
+ * fail this. The problem with REPEAT is we can block here
+ * "forever". There isn't an inbetween, unfortunately. We
+ * could reduce the risk by never freeing the rcvhdrq except
+ * at unload, but even then, the first time a port is used,
+ * we could delay for some time...
+ */
+ gfp_t gfp_flags = GFP_USER | __GFP_COMP;
+
+ pd->port_rcvhdrq = dma_alloc_coherent(
+ &dd->pcidev->dev, amt, &pd->port_rcvhdrq_phys,
+ gfp_flags);
+
+ if (!pd->port_rcvhdrq) {
+ ipath_dev_err(dd, "attempt to allocate %d bytes "
+ "for port %u rcvhdrq failed\n",
+ amt, pd->port_port);
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ pd->port_rcvhdrq_size = amt;
+
+ ipath_cdbg(VERBOSE, "%d pages at %p (phys %lx) size=%lu "
+ "for port %u rcvhdr Q\n",
+ amt >> PAGE_SHIFT, pd->port_rcvhdrq,
+ (unsigned long) pd->port_rcvhdrq_phys,
+ (unsigned long) pd->port_rcvhdrq_size,
+ pd->port_port);
+ } else {
+ /*
+ * clear for security, sanity, and/or debugging, each
+ * time we reuse
+ */
+ memset(pd->port_rcvhdrq, 0, amt);
+ }
+
+ /*
+ * tell chip each time we init it, even if we are re-using previous
+ * memory (we zero it at process close)
+ */
+ ipath_cdbg(VERBOSE, "writing port %d rcvhdraddr as %lx\n",
+ pd->port_port, (unsigned long) pd->port_rcvhdrq_phys);
+ ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr,
+ pd->port_port, pd->port_rcvhdrq_phys);
+
+ ret = 0;
+bail:
+ return ret;
+}
+
+int ipath_waitfor_complete(struct ipath_devdata *dd, ipath_kreg reg_id,
+ u64 bits_to_wait_for, u64 * valp)
+{
+ unsigned long timeout;
+ u64 lastval, val;
+ int ret;
+
+ lastval = ipath_read_kreg64(dd, reg_id);
+ /* wait a ridiculously long time */
+ timeout = jiffies + msecs_to_jiffies(5);
+ do {
+ val = ipath_read_kreg64(dd, reg_id);
+ /* set so they have something, even on failures. */
+ *valp = val;
+ if ((val & bits_to_wait_for) == bits_to_wait_for) {
+ ret = 0;
+ break;
+ }
+ if (val != lastval)
+ ipath_cdbg(VERBOSE, "Changed from %llx to %llx, "
+ "waiting for %llx bits\n",
+ (unsigned long long) lastval,
+ (unsigned long long) val,
+ (unsigned long long) bits_to_wait_for);
+ cond_resched();
+ if (time_after(jiffies, timeout)) {
+ ipath_dbg("Didn't get bits %llx in register 0x%x, "
+ "got %llx\n",
+ (unsigned long long) bits_to_wait_for,
+ reg_id, (unsigned long long) *valp);
+ ret = -ENODEV;
+ break;
+ }
+ } while (1);
+
+ return ret;
+}
+
+/**
+ * ipath_waitfor_mdio_cmdready - wait for last command to complete
+ * @dd: the infinipath device
+ *
+ * Like ipath_waitfor_complete(), but we wait for the CMDVALID bit to go
+ * away indicating the last command has completed. It doesn't return data
+ */
+int ipath_waitfor_mdio_cmdready(struct ipath_devdata *dd)
+{
+ unsigned long timeout;
+ u64 val;
+ int ret;
+
+ /* wait a ridiculously long time */
+ timeout = jiffies + msecs_to_jiffies(5);
+ do {
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_mdio);
+ if (!(val & IPATH_MDIO_CMDVALID)) {
+ ret = 0;
+ break;
+ }
+ cond_resched();
+ if (time_after(jiffies, timeout)) {
+ ipath_dbg("CMDVALID stuck in mdio reg? (%llx)\n",
+ (unsigned long long) val);
+ ret = -ENODEV;
+ break;
+ }
+ } while (1);
+
+ return ret;
+}
+
+void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
+{
+ static const char *what[4] = {
+ [0] = "DOWN",
+ [INFINIPATH_IBCC_LINKCMD_INIT] = "INIT",
+ [INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED",
+ [INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE"
+ };
+ ipath_cdbg(SMA, "Trying to move unit %u to %s, current ltstate "
+ "is %s\n", dd->ipath_unit,
+ what[(which >> INFINIPATH_IBCC_LINKCMD_SHIFT) &
+ INFINIPATH_IBCC_LINKCMD_MASK],
+ ipath_ibcstatus_str[
+ (ipath_read_kreg64
+ (dd, dd->ipath_kregs->kr_ibcstatus) >>
+ INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+ INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]);
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl | which);
+}
+
+/**
+ * ipath_read_kreg64_port - read a device's per-port 64-bit kernel register
+ * @dd: the infinipath device
+ * @regno: the register number to read
+ * @port: the port containing the register
+ *
+ * Registers that vary with the chip implementation constants (port)
+ * use this routine.
+ */
+u64 ipath_read_kreg64_port(const struct ipath_devdata *dd, ipath_kreg regno,
+ unsigned port)
+{
+ u16 where;
+
+ if (port < dd->ipath_portcnt &&
+ (regno == dd->ipath_kregs->kr_rcvhdraddr ||
+ regno == dd->ipath_kregs->kr_rcvhdrtailaddr))
+ where = regno + port;
+ else
+ where = -1;
+
+ return ipath_read_kreg64(dd, where);
+}
+
+/**
+ * ipath_write_kreg_port - write a device's per-port 64-bit kernel register
+ * @dd: the infinipath device
+ * @regno: the register number to write
+ * @port: the port containing the register
+ * @value: the value to write
+ *
+ * Registers that vary with the chip implementation constants (port)
+ * use this routine.
+ */
+void ipath_write_kreg_port(const struct ipath_devdata *dd, ipath_kreg regno,
+ unsigned port, u64 value)
+{
+ u16 where;
+
+ if (port < dd->ipath_portcnt &&
+ (regno == dd->ipath_kregs->kr_rcvhdraddr ||
+ regno == dd->ipath_kregs->kr_rcvhdrtailaddr))
+ where = regno + port;
+ else
+ where = -1;
+
+ ipath_write_kreg(dd, where, value);
+}
+
+/**
+ * ipath_shutdown_device - shut down a device
+ * @dd: the infinipath device
+ *
+ * This is called to make the device quiet when we are about to
+ * unload the driver, and also when the device is administratively
+ * disabled. It does not free any data structures.
+ * Everything it does has to be setup again by ipath_init_chip(dd,1)
+ */
+void ipath_shutdown_device(struct ipath_devdata *dd)
+{
+ u64 val;
+
+ ipath_dbg("Shutting down the device\n");
+
+ dd->ipath_flags |= IPATH_LINKUNK;
+ dd->ipath_flags &= ~(IPATH_INITTED | IPATH_LINKDOWN |
+ IPATH_LINKINIT | IPATH_LINKARMED |
+ IPATH_LINKACTIVE);
+ *dd->ipath_statusp &= ~(IPATH_STATUS_IB_CONF |
+ IPATH_STATUS_IB_READY);
+
+ /* mask interrupts, but not errors */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL);
+
+ dd->ipath_rcvctrl = 0;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+ /*
+ * gracefully stop all sends allowing any in progress to trickle out
+ * first.
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0ULL);
+ /* flush it */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ /*
+ * enough for anything that's going to trickle out to have actually
+ * done so.
+ */
+ udelay(5);
+
+ /*
+ * abort any armed or launched PIO buffers that didn't go. (self
+ * clearing). Will cause any packet currently being transmitted to
+ * go out with an EBP, and may also cause a short packet error on
+ * the receiver.
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ INFINIPATH_S_ABORT);
+
+ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+ INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+
+ /*
+ * we are shutting down, so tell the layered driver. We don't do
+ * this on just a link state change, much like ethernet, a cable
+ * unplug, etc. doesn't change driver state
+ */
+ ipath_layer_intr(dd, IPATH_LAYER_INT_IF_DOWN);
+
+ /* disable IBC */
+ dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+ dd->ipath_control);
+
+ /*
+ * clear SerdesEnable and turn the leds off; do this here because
+ * we are unloading, so don't count on interrupts to move along
+ * Turn the LEDs off explictly for the same reason.
+ */
+ dd->ipath_f_quiet_serdes(dd);
+ dd->ipath_f_setextled(dd, 0, 0);
+
+ if (dd->ipath_stats_timer_active) {
+ del_timer_sync(&dd->ipath_stats_timer);
+ dd->ipath_stats_timer_active = 0;
+ }
+
+ /*
+ * clear all interrupts and errors, so that the next time the driver
+ * is loaded or device is enabled, we know that whatever is set
+ * happened while we were unloaded
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ ~0ULL & ~INFINIPATH_HWE_MEMBISTFAILED);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, -1LL);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL);
+}
+
+/**
+ * ipath_free_pddata - free a port's allocated data
+ * @dd: the infinipath device
+ * @port: the port
+ * @freehdrq: free the port data structure if true
+ *
+ * when closing, free up any allocated data for a port, if the
+ * reference count goes to zero
+ * Note: this also optionally frees the portdata itself!
+ * Any changes here have to be matched up with the reinit case
+ * of ipath_init_chip(), which calls this routine on reinit after reset.
+ */
+void ipath_free_pddata(struct ipath_devdata *dd, u32 port, int freehdrq)
+{
+ struct ipath_portdata *pd = dd->ipath_pd[port];
+
+ if (!pd)
+ return;
+ if (freehdrq)
+ /*
+ * only clear and free portdata if we are going to also
+ * release the hdrq, otherwise we leak the hdrq on each
+ * open/close cycle
+ */
+ dd->ipath_pd[port] = NULL;
+ if (freehdrq && pd->port_rcvhdrq) {
+ ipath_cdbg(VERBOSE, "free closed port %d rcvhdrq @ %p "
+ "(size=%lu)\n", pd->port_port, pd->port_rcvhdrq,
+ (unsigned long) pd->port_rcvhdrq_size);
+ dma_free_coherent(&dd->pcidev->dev, pd->port_rcvhdrq_size,
+ pd->port_rcvhdrq, pd->port_rcvhdrq_phys);
+ pd->port_rcvhdrq = NULL;
+ }
+ if (port && pd->port_rcvegrbuf) {
+ /* always free this */
+ if (pd->port_rcvegrbuf) {
+ unsigned e;
+
+ for (e = 0; e < pd->port_rcvegrbuf_chunks; e++) {
+ void *base = pd->port_rcvegrbuf[e];
+ size_t size = pd->port_rcvegrbuf_size;
+
+ ipath_cdbg(VERBOSE, "egrbuf free(%p, %lu), "
+ "chunk %u/%u\n", base,
+ (unsigned long) size,
+ e, pd->port_rcvegrbuf_chunks);
+ dma_free_coherent(
+ &dd->pcidev->dev, size, base,
+ pd->port_rcvegrbuf_phys[e]);
+ }
+ vfree(pd->port_rcvegrbuf);
+ pd->port_rcvegrbuf = NULL;
+ vfree(pd->port_rcvegrbuf_phys);
+ pd->port_rcvegrbuf_phys = NULL;
+ }
+ pd->port_rcvegrbuf_chunks = 0;
+ } else if (port == 0 && dd->ipath_port0_skbs) {
+ unsigned e;
+ struct sk_buff **skbs = dd->ipath_port0_skbs;
+
+ dd->ipath_port0_skbs = NULL;
+ ipath_cdbg(VERBOSE, "free closed port %d ipath_port0_skbs "
+ "@ %p\n", pd->port_port, skbs);
+ for (e = 0; e < dd->ipath_rcvegrcnt; e++)
+ if (skbs[e])
+ dev_kfree_skb(skbs[e]);
+ vfree(skbs);
+ }
+ if (freehdrq) {
+ kfree(pd->port_tid_pg_list);
+ kfree(pd);
+ }
+}
+
+static int __init infinipath_init(void)
+{
+ int ret;
+
+ ipath_dbg(KERN_INFO DRIVER_LOAD_MSG "%s", ipath_core_version);
+
+ /*
+ * These must be called before the driver is registered with
+ * the PCI subsystem.
+ */
+ idr_init(&unit_table);
+ if (!idr_pre_get(&unit_table, GFP_KERNEL)) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ ret = pci_register_driver(&ipath_driver);
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME
+ ": Unable to register driver: error %d\n", -ret);
+ goto bail_unit;
+ }
+
+ ret = ipath_driver_create_group(&ipath_driver.driver);
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME ": Unable to create driver "
+ "sysfs entries: error %d\n", -ret);
+ goto bail_pci;
+ }
+
+ ret = ipath_init_ipathfs();
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME ": Unable to create "
+ "ipathfs: error %d\n", -ret);
+ goto bail_group;
+ }
+
+ goto bail;
+
+bail_group:
+ ipath_driver_remove_group(&ipath_driver.driver);
+
+bail_pci:
+ pci_unregister_driver(&ipath_driver);
+
+bail_unit:
+ idr_destroy(&unit_table);
+
+bail:
+ return ret;
+}
+
+static void cleanup_device(struct ipath_devdata *dd)
+{
+ int port;
+
+ ipath_shutdown_device(dd);
+
+ if (*dd->ipath_statusp & IPATH_STATUS_CHIP_PRESENT) {
+ /* can't do anything more with chip; needs re-init */
+ *dd->ipath_statusp &= ~IPATH_STATUS_CHIP_PRESENT;
+ if (dd->ipath_kregbase) {
+ /*
+ * if we haven't already cleaned up before these are
+ * to ensure any register reads/writes "fail" until
+ * re-init
+ */
+ dd->ipath_kregbase = NULL;
+ dd->ipath_kregvirt = NULL;
+ dd->ipath_uregbase = 0;
+ dd->ipath_sregbase = 0;
+ dd->ipath_cregbase = 0;
+ dd->ipath_kregsize = 0;
+ }
+ ipath_disable_wc(dd);
+ }
+
+ if (dd->ipath_pioavailregs_dma) {
+ dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
+ (void *) dd->ipath_pioavailregs_dma,
+ dd->ipath_pioavailregs_phys);
+ dd->ipath_pioavailregs_dma = NULL;
+ }
+
+ if (dd->ipath_pageshadow) {
+ struct page **tmpp = dd->ipath_pageshadow;
+ int i, cnt = 0;
+
+ ipath_cdbg(VERBOSE, "Unlocking any expTID pages still "
+ "locked\n");
+ for (port = 0; port < dd->ipath_cfgports; port++) {
+ int port_tidbase = port * dd->ipath_rcvtidcnt;
+ int maxtid = port_tidbase + dd->ipath_rcvtidcnt;
+ for (i = port_tidbase; i < maxtid; i++) {
+ if (!tmpp[i])
+ continue;
+ ipath_release_user_pages(&tmpp[i], 1);
+ tmpp[i] = NULL;
+ cnt++;
+ }
+ }
+ if (cnt) {
+ ipath_stats.sps_pageunlocks += cnt;
+ ipath_cdbg(VERBOSE, "There were still %u expTID "
+ "entries locked\n", cnt);
+ }
+ if (ipath_stats.sps_pagelocks ||
+ ipath_stats.sps_pageunlocks)
+ ipath_cdbg(VERBOSE, "%llu pages locked, %llu "
+ "unlocked via ipath_m{un}lock\n",
+ (unsigned long long)
+ ipath_stats.sps_pagelocks,
+ (unsigned long long)
+ ipath_stats.sps_pageunlocks);
+
+ ipath_cdbg(VERBOSE, "Free shadow page tid array at %p\n",
+ dd->ipath_pageshadow);
+ vfree(dd->ipath_pageshadow);
+ dd->ipath_pageshadow = NULL;
+ }
+
+ /*
+ * free any resources still in use (usually just kernel ports)
+ * at unload
+ */
+ for (port = 0; port < dd->ipath_cfgports; port++)
+ ipath_free_pddata(dd, port, 1);
+ kfree(dd->ipath_pd);
+ /*
+ * debuggability, in case some cleanup path tries to use it
+ * after this
+ */
+ dd->ipath_pd = NULL;
+}
+
+static void __exit infinipath_cleanup(void)
+{
+ struct ipath_devdata *dd, *tmp;
+ unsigned long flags;
+
+ ipath_exit_ipathfs();
+
+ ipath_driver_remove_group(&ipath_driver.driver);
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ /*
+ * turn off rcv, send, and interrupts for all ports, all drivers
+ * should also hard reset the chip here?
+ * free up port 0 (kernel) rcvhdr, egr bufs, and eventually tid bufs
+ * for all versions of the driver, if they were allocated
+ */
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ if (dd->ipath_kregbase)
+ cleanup_device(dd);
+
+ if (dd->pcidev) {
+ if (dd->pcidev->irq) {
+ ipath_cdbg(VERBOSE,
+ "unit %u free_irq of irq %x\n",
+ dd->ipath_unit, dd->pcidev->irq);
+ free_irq(dd->pcidev->irq, dd);
+ } else
+ ipath_dbg("irq is 0, not doing free_irq "
+ "for unit %u\n", dd->ipath_unit);
+
+ /*
+ * we check for NULL here, because it's outside
+ * the kregbase check, and we need to call it
+ * after the free_irq. Thus it's possible that
+ * the function pointers were never initialized.
+ */
+ if (dd->ipath_f_cleanup)
+ /* clean up chip-specific stuff */
+ dd->ipath_f_cleanup(dd);
+
+ dd->pcidev = NULL;
+ }
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ ipath_cdbg(VERBOSE, "Unregistering pci driver\n");
+ pci_unregister_driver(&ipath_driver);
+
+ idr_destroy(&unit_table);
+}
+
+/**
+ * ipath_reset_device - reset the chip if possible
+ * @unit: the device to reset
+ *
+ * Whether or not reset is successful, we attempt to re-initialize the chip
+ * (that is, much like a driver unload/reload). We clear the INITTED flag
+ * so that the various entry points will fail until we reinitialize. For
+ * now, we only allow this if no user ports are open that use chip resources
+ */
+int ipath_reset_device(int unit)
+{
+ int ret, i;
+ struct ipath_devdata *dd = ipath_lookup(unit);
+
+ if (!dd) {
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ dev_info(&dd->pcidev->dev, "Reset on unit %u requested\n", unit);
+
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) {
+ dev_info(&dd->pcidev->dev, "Invalid unit number %u or "
+ "not initialized or not present\n", unit);
+ ret = -ENXIO;
+ goto bail;
+ }
+
+ if (dd->ipath_pd)
+ for (i = 1; i < dd->ipath_cfgports; i++) {
+ if (dd->ipath_pd[i] && dd->ipath_pd[i]->port_cnt) {
+ ipath_dbg("unit %u port %d is in use "
+ "(PID %u cmd %s), can't reset\n",
+ unit, i,
+ dd->ipath_pd[i]->port_pid,
+ dd->ipath_pd[i]->port_comm);
+ ret = -EBUSY;
+ goto bail;
+ }
+ }
+
+ dd->ipath_flags &= ~IPATH_INITTED;
+ ret = dd->ipath_f_reset(dd);
+ if (ret != 1)
+ ipath_dbg("reset was not successful\n");
+ ipath_dbg("Trying to reinitialize unit %u after reset attempt\n",
+ unit);
+ ret = ipath_init_chip(dd, 1);
+ if (ret)
+ ipath_dev_err(dd, "Reinitialize unit %u after "
+ "reset failed with %d\n", unit, ret);
+ else
+ dev_info(&dd->pcidev->dev, "Reinitialized unit %u after "
+ "resetting\n", unit);
+
+bail:
+ return ret;
+}
+
+module_init(infinipath_init);
+module_exit(infinipath_cleanup);
diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c
new file mode 100644
index 00000000000..a2f1ceafcca
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c
@@ -0,0 +1,612 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_kernel.h"
+
+/*
+ * InfiniPath I2C driver for a serial eeprom. This is not a generic
+ * I2C interface. For a start, the device we're using (Atmel AT24C11)
+ * doesn't work like a regular I2C device. It looks like one
+ * electrically, but not logically. Normal I2C devices have a single
+ * 7-bit or 10-bit I2C address that they respond to. Valid 7-bit
+ * addresses range from 0x03 to 0x77. Addresses 0x00 to 0x02 and 0x78
+ * to 0x7F are special reserved addresses (e.g. 0x00 is the "general
+ * call" address.) The Atmel device, on the other hand, responds to ALL
+ * 7-bit addresses. It's designed to be the only device on a given I2C
+ * bus. A 7-bit address corresponds to the memory address within the
+ * Atmel device itself.
+ *
+ * Also, the timing requirements mean more than simple software
+ * bitbanging, with readbacks from chip to ensure timing (simple udelay
+ * is not enough).
+ *
+ * This all means that accessing the device is specialized enough
+ * that using the standard kernel I2C bitbanging interface would be
+ * impossible. For example, the core I2C eeprom driver expects to find
+ * a device at one or more of a limited set of addresses only. It doesn't
+ * allow writing to an eeprom. It also doesn't provide any means of
+ * accessing eeprom contents from within the kernel, only via sysfs.
+ */
+
+enum i2c_type {
+ i2c_line_scl = 0,
+ i2c_line_sda
+};
+
+enum i2c_state {
+ i2c_line_low = 0,
+ i2c_line_high
+};
+
+#define READ_CMD 1
+#define WRITE_CMD 0
+
+static int eeprom_init;
+
+/*
+ * The gpioval manipulation really should be protected by spinlocks
+ * or be converted to use atomic operations.
+ */
+
+/**
+ * i2c_gpio_set - set a GPIO line
+ * @dd: the infinipath device
+ * @line: the line to set
+ * @new_line_state: the state to set
+ *
+ * Returns 0 if the line was set to the new state successfully, non-zero
+ * on error.
+ */
+static int i2c_gpio_set(struct ipath_devdata *dd,
+ enum i2c_type line,
+ enum i2c_state new_line_state)
+{
+ u64 read_val, write_val, mask, *gpioval;
+
+ gpioval = &dd->ipath_gpio_out;
+ read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
+ if (line == i2c_line_scl)
+ mask = ipath_gpio_scl;
+ else
+ mask = ipath_gpio_sda;
+
+ if (new_line_state == i2c_line_high)
+ /* tri-state the output rather than force high */
+ write_val = read_val & ~mask;
+ else
+ /* config line to be an output */
+ write_val = read_val | mask;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
+
+ /* set high and verify */
+ if (new_line_state == i2c_line_high)
+ write_val = 0x1UL;
+ else
+ write_val = 0x0UL;
+
+ if (line == i2c_line_scl) {
+ write_val <<= ipath_gpio_scl_num;
+ *gpioval = *gpioval & ~(1UL << ipath_gpio_scl_num);
+ *gpioval |= write_val;
+ } else {
+ write_val <<= ipath_gpio_sda_num;
+ *gpioval = *gpioval & ~(1UL << ipath_gpio_sda_num);
+ *gpioval |= write_val;
+ }
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_out, *gpioval);
+
+ return 0;
+}
+
+/**
+ * i2c_gpio_get - get a GPIO line state
+ * @dd: the infinipath device
+ * @line: the line to get
+ * @curr_statep: where to put the line state
+ *
+ * Returns 0 if the line was set to the new state successfully, non-zero
+ * on error. curr_state is not set on error.
+ */
+static int i2c_gpio_get(struct ipath_devdata *dd,
+ enum i2c_type line,
+ enum i2c_state *curr_statep)
+{
+ u64 read_val, write_val, mask;
+ int ret;
+
+ /* check args */
+ if (curr_statep == NULL) {
+ ret = 1;
+ goto bail;
+ }
+
+ read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
+ /* config line to be an input */
+ if (line == i2c_line_scl)
+ mask = ipath_gpio_scl;
+ else
+ mask = ipath_gpio_sda;
+ write_val = read_val & ~mask;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
+ read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+
+ if (read_val & mask)
+ *curr_statep = i2c_line_high;
+ else
+ *curr_statep = i2c_line_low;
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * i2c_wait_for_writes - wait for a write
+ * @dd: the infinipath device
+ *
+ * We use this instead of udelay directly, so we can make sure
+ * that previous register writes have been flushed all the way
+ * to the chip. Since we are delaying anyway, the cost doesn't
+ * hurt, and makes the bit twiddling more regular
+ */
+static void i2c_wait_for_writes(struct ipath_devdata *dd)
+{
+ (void)ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
+}
+
+static void scl_out(struct ipath_devdata *dd, u8 bit)
+{
+ i2c_gpio_set(dd, i2c_line_scl, bit ? i2c_line_high : i2c_line_low);
+
+ i2c_wait_for_writes(dd);
+}
+
+static void sda_out(struct ipath_devdata *dd, u8 bit)
+{
+ i2c_gpio_set(dd, i2c_line_sda, bit ? i2c_line_high : i2c_line_low);
+
+ i2c_wait_for_writes(dd);
+}
+
+static u8 sda_in(struct ipath_devdata *dd, int wait)
+{
+ enum i2c_state bit;
+
+ if (i2c_gpio_get(dd, i2c_line_sda, &bit))
+ ipath_dbg("get bit failed!\n");
+
+ if (wait)
+ i2c_wait_for_writes(dd);
+
+ return bit == i2c_line_high ? 1U : 0;
+}
+
+/**
+ * i2c_ackrcv - see if ack following write is true
+ * @dd: the infinipath device
+ */
+static int i2c_ackrcv(struct ipath_devdata *dd)
+{
+ u8 ack_received;
+
+ /* AT ENTRY SCL = LOW */
+ /* change direction, ignore data */
+ ack_received = sda_in(dd, 1);
+ scl_out(dd, i2c_line_high);
+ ack_received = sda_in(dd, 1) == 0;
+ scl_out(dd, i2c_line_low);
+ return ack_received;
+}
+
+/**
+ * wr_byte - write a byte, one bit at a time
+ * @dd: the infinipath device
+ * @data: the byte to write
+ *
+ * Returns 0 if we got the following ack, otherwise 1
+ */
+static int wr_byte(struct ipath_devdata *dd, u8 data)
+{
+ int bit_cntr;
+ u8 bit;
+
+ for (bit_cntr = 7; bit_cntr >= 0; bit_cntr--) {
+ bit = (data >> bit_cntr) & 1;
+ sda_out(dd, bit);
+ scl_out(dd, i2c_line_high);
+ scl_out(dd, i2c_line_low);
+ }
+ return (!i2c_ackrcv(dd)) ? 1 : 0;
+}
+
+static void send_ack(struct ipath_devdata *dd)
+{
+ sda_out(dd, i2c_line_low);
+ scl_out(dd, i2c_line_high);
+ scl_out(dd, i2c_line_low);
+ sda_out(dd, i2c_line_high);
+}
+
+/**
+ * i2c_startcmd - transmit the start condition, followed by address/cmd
+ * @dd: the infinipath device
+ * @offset_dir: direction byte
+ *
+ * (both clock/data high, clock high, data low while clock is high)
+ */
+static int i2c_startcmd(struct ipath_devdata *dd, u8 offset_dir)
+{
+ int res;
+
+ /* issue start sequence */
+ sda_out(dd, i2c_line_high);
+ scl_out(dd, i2c_line_high);
+ sda_out(dd, i2c_line_low);
+ scl_out(dd, i2c_line_low);
+
+ /* issue length and direction byte */
+ res = wr_byte(dd, offset_dir);
+
+ if (res)
+ ipath_cdbg(VERBOSE, "No ack to complete start\n");
+
+ return res;
+}
+
+/**
+ * stop_cmd - transmit the stop condition
+ * @dd: the infinipath device
+ *
+ * (both clock/data low, clock high, data high while clock is high)
+ */
+static void stop_cmd(struct ipath_devdata *dd)
+{
+ scl_out(dd, i2c_line_low);
+ sda_out(dd, i2c_line_low);
+ scl_out(dd, i2c_line_high);
+ sda_out(dd, i2c_line_high);
+ udelay(2);
+}
+
+/**
+ * eeprom_reset - reset I2C communication
+ * @dd: the infinipath device
+ */
+
+static int eeprom_reset(struct ipath_devdata *dd)
+{
+ int clock_cycles_left = 9;
+ u64 *gpioval = &dd->ipath_gpio_out;
+ int ret;
+
+ eeprom_init = 1;
+ *gpioval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_out);
+ ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg "
+ "is %llx\n", (unsigned long long) *gpioval);
+
+ /*
+ * This is to get the i2c into a known state, by first going low,
+ * then tristate sda (and then tristate scl as first thing
+ * in loop)
+ */
+ scl_out(dd, i2c_line_low);
+ sda_out(dd, i2c_line_high);
+
+ while (clock_cycles_left--) {
+ scl_out(dd, i2c_line_high);
+
+ if (sda_in(dd, 0)) {
+ sda_out(dd, i2c_line_low);
+ scl_out(dd, i2c_line_low);
+ ret = 0;
+ goto bail;
+ }
+
+ scl_out(dd, i2c_line_low);
+ }
+
+ ret = 1;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_eeprom_read - receives bytes from the eeprom via I2C
+ * @dd: the infinipath device
+ * @eeprom_offset: address to read from
+ * @buffer: where to store result
+ * @len: number of bytes to receive
+ */
+
+int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
+ void *buffer, int len)
+{
+ /* compiler complains unless initialized */
+ u8 single_byte = 0;
+ int bit_cntr;
+ int ret;
+
+ if (!eeprom_init)
+ eeprom_reset(dd);
+
+ eeprom_offset = (eeprom_offset << 1) | READ_CMD;
+
+ if (i2c_startcmd(dd, eeprom_offset)) {
+ ipath_dbg("Failed startcmd\n");
+ stop_cmd(dd);
+ ret = 1;
+ goto bail;
+ }
+
+ /*
+ * eeprom keeps clocking data out as long as we ack, automatically
+ * incrementing the address.
+ */
+ while (len-- > 0) {
+ /* get data */
+ single_byte = 0;
+ for (bit_cntr = 8; bit_cntr; bit_cntr--) {
+ u8 bit;
+ scl_out(dd, i2c_line_high);
+ bit = sda_in(dd, 0);
+ single_byte |= bit << (bit_cntr - 1);
+ scl_out(dd, i2c_line_low);
+ }
+
+ /* send ack if not the last byte */
+ if (len)
+ send_ack(dd);
+
+ *((u8 *) buffer) = single_byte;
+ buffer++;
+ }
+
+ stop_cmd(dd);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_eeprom_write - writes data to the eeprom via I2C
+ * @dd: the infinipath device
+ * @eeprom_offset: where to place data
+ * @buffer: data to write
+ * @len: number of bytes to write
+ */
+int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
+ const void *buffer, int len)
+{
+ u8 single_byte;
+ int sub_len;
+ const u8 *bp = buffer;
+ int max_wait_time, i;
+ int ret;
+
+ if (!eeprom_init)
+ eeprom_reset(dd);
+
+ while (len > 0) {
+ if (i2c_startcmd(dd, (eeprom_offset << 1) | WRITE_CMD)) {
+ ipath_dbg("Failed to start cmd offset %u\n",
+ eeprom_offset);
+ goto failed_write;
+ }
+
+ sub_len = min(len, 4);
+ eeprom_offset += sub_len;
+ len -= sub_len;
+
+ for (i = 0; i < sub_len; i++) {
+ if (wr_byte(dd, *bp++)) {
+ ipath_dbg("no ack after byte %u/%u (%u "
+ "total remain)\n", i, sub_len,
+ len + sub_len - i);
+ goto failed_write;
+ }
+ }
+
+ stop_cmd(dd);
+
+ /*
+ * wait for write complete by waiting for a successful
+ * read (the chip replies with a zero after the write
+ * cmd completes, and before it writes to the eeprom.
+ * The startcmd for the read will fail the ack until
+ * the writes have completed. We do this inline to avoid
+ * the debug prints that are in the real read routine
+ * if the startcmd fails.
+ */
+ max_wait_time = 100;
+ while (i2c_startcmd(dd, READ_CMD)) {
+ stop_cmd(dd);
+ if (!--max_wait_time) {
+ ipath_dbg("Did not get successful read to "
+ "complete write\n");
+ goto failed_write;
+ }
+ }
+ /* now read the zero byte */
+ for (i = single_byte = 0; i < 8; i++) {
+ u8 bit;
+ scl_out(dd, i2c_line_high);
+ bit = sda_in(dd, 0);
+ scl_out(dd, i2c_line_low);
+ single_byte <<= 1;
+ single_byte |= bit;
+ }
+ stop_cmd(dd);
+ }
+
+ ret = 0;
+ goto bail;
+
+failed_write:
+ stop_cmd(dd);
+ ret = 1;
+
+bail:
+ return ret;
+}
+
+static u8 flash_csum(struct ipath_flash *ifp, int adjust)
+{
+ u8 *ip = (u8 *) ifp;
+ u8 csum = 0, len;
+
+ for (len = 0; len < ifp->if_length; len++)
+ csum += *ip++;
+ csum -= ifp->if_csum;
+ csum = ~csum;
+ if (adjust)
+ ifp->if_csum = csum;
+
+ return csum;
+}
+
+/**
+ * ipath_get_guid - get the GUID from the i2c device
+ * @dd: the infinipath device
+ *
+ * We have the capability to use the ipath_nguid field, and get
+ * the guid from the first chip's flash, to use for all of them.
+ */
+void ipath_get_eeprom_info(struct ipath_devdata *dd)
+{
+ void *buf;
+ struct ipath_flash *ifp;
+ __be64 guid;
+ int len;
+ u8 csum, *bguid;
+ int t = dd->ipath_unit;
+ struct ipath_devdata *dd0 = ipath_lookup(0);
+
+ if (t && dd0->ipath_nguid > 1 && t <= dd0->ipath_nguid) {
+ u8 *bguid, oguid;
+ dd->ipath_guid = dd0->ipath_guid;
+ bguid = (u8 *) & dd->ipath_guid;
+
+ oguid = bguid[7];
+ bguid[7] += t;
+ if (oguid > bguid[7]) {
+ if (bguid[6] == 0xff) {
+ if (bguid[5] == 0xff) {
+ ipath_dev_err(
+ dd,
+ "Can't set %s GUID from "
+ "base, wraps to OUI!\n",
+ ipath_get_unit_name(t));
+ dd->ipath_guid = 0;
+ goto bail;
+ }
+ bguid[5]++;
+ }
+ bguid[6]++;
+ }
+ dd->ipath_nguid = 1;
+
+ ipath_dbg("nguid %u, so adding %u to device 0 guid, "
+ "for %llx\n",
+ dd0->ipath_nguid, t,
+ (unsigned long long) be64_to_cpu(dd->ipath_guid));
+ goto bail;
+ }
+
+ len = offsetof(struct ipath_flash, if_future);
+ buf = vmalloc(len);
+ if (!buf) {
+ ipath_dev_err(dd, "Couldn't allocate memory to read %u "
+ "bytes from eeprom for GUID\n", len);
+ goto bail;
+ }
+
+ if (ipath_eeprom_read(dd, 0, buf, len)) {
+ ipath_dev_err(dd, "Failed reading GUID from eeprom\n");
+ goto done;
+ }
+ ifp = (struct ipath_flash *)buf;
+
+ csum = flash_csum(ifp, 0);
+ if (csum != ifp->if_csum) {
+ dev_info(&dd->pcidev->dev, "Bad I2C flash checksum: "
+ "0x%x, not 0x%x\n", csum, ifp->if_csum);
+ goto done;
+ }
+ if (*(__be64 *) ifp->if_guid == 0ULL ||
+ *(__be64 *) ifp->if_guid == __constant_cpu_to_be64(-1LL)) {
+ ipath_dev_err(dd, "Invalid GUID %llx from flash; "
+ "ignoring\n",
+ *(unsigned long long *) ifp->if_guid);
+ /* don't allow GUID if all 0 or all 1's */
+ goto done;
+ }
+
+ /* complain, but allow it */
+ if (*(u64 *) ifp->if_guid == 0x100007511000000ULL)
+ dev_info(&dd->pcidev->dev, "Warning, GUID %llx is "
+ "default, probably not correct!\n",
+ *(unsigned long long *) ifp->if_guid);
+
+ bguid = ifp->if_guid;
+ if (!bguid[0] && !bguid[1] && !bguid[2]) {
+ /* original incorrect GUID format in flash; fix in
+ * core copy, by shifting up 2 octets; don't need to
+ * change top octet, since both it and shifted are
+ * 0.. */
+ bguid[1] = bguid[3];
+ bguid[2] = bguid[4];
+ bguid[3] = bguid[4] = 0;
+ guid = *(__be64 *) ifp->if_guid;
+ ipath_cdbg(VERBOSE, "Old GUID format in flash, top 3 zero, "
+ "shifting 2 octets\n");
+ } else
+ guid = *(__be64 *) ifp->if_guid;
+ dd->ipath_guid = guid;
+ dd->ipath_nguid = ifp->if_numguid;
+ memcpy(dd->ipath_serial, ifp->if_serial,
+ sizeof(ifp->if_serial));
+ ipath_cdbg(VERBOSE, "Initted GUID to %llx from eeprom\n",
+ (unsigned long long) be64_to_cpu(dd->ipath_guid));
+
+done:
+ vfree(buf);
+
+bail:;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
new file mode 100644
index 00000000000..ada267e41f6
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -0,0 +1,1914 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+#include <linux/poll.h>
+#include <linux/cdev.h>
+#include <linux/swap.h>
+#include <linux/vmalloc.h>
+#include <asm/pgtable.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+static int ipath_open(struct inode *, struct file *);
+static int ipath_close(struct inode *, struct file *);
+static ssize_t ipath_write(struct file *, const char __user *, size_t,
+ loff_t *);
+static unsigned int ipath_poll(struct file *, struct poll_table_struct *);
+static int ipath_mmap(struct file *, struct vm_area_struct *);
+
+static struct file_operations ipath_file_ops = {
+ .owner = THIS_MODULE,
+ .write = ipath_write,
+ .open = ipath_open,
+ .release = ipath_close,
+ .poll = ipath_poll,
+ .mmap = ipath_mmap
+};
+
+static int ipath_get_base_info(struct ipath_portdata *pd,
+ void __user *ubase, size_t ubase_size)
+{
+ int ret = 0;
+ struct ipath_base_info *kinfo = NULL;
+ struct ipath_devdata *dd = pd->port_dd;
+
+ if (ubase_size < sizeof(*kinfo)) {
+ ipath_cdbg(PROC,
+ "Base size %lu, need %lu (version mismatch?)\n",
+ (unsigned long) ubase_size,
+ (unsigned long) sizeof(*kinfo));
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ kinfo = kzalloc(sizeof(*kinfo), GFP_KERNEL);
+ if (kinfo == NULL) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ ret = dd->ipath_f_get_base_info(pd, kinfo);
+ if (ret < 0)
+ goto bail;
+
+ kinfo->spi_rcvhdr_cnt = dd->ipath_rcvhdrcnt;
+ kinfo->spi_rcvhdrent_size = dd->ipath_rcvhdrentsize;
+ kinfo->spi_tidegrcnt = dd->ipath_rcvegrcnt;
+ kinfo->spi_rcv_egrbufsize = dd->ipath_rcvegrbufsize;
+ /*
+ * have to mmap whole thing
+ */
+ kinfo->spi_rcv_egrbuftotlen =
+ pd->port_rcvegrbuf_chunks * pd->port_rcvegrbuf_size;
+ kinfo->spi_rcv_egrperchunk = pd->port_rcvegrbufs_perchunk;
+ kinfo->spi_rcv_egrchunksize = kinfo->spi_rcv_egrbuftotlen /
+ pd->port_rcvegrbuf_chunks;
+ kinfo->spi_tidcnt = dd->ipath_rcvtidcnt;
+ /*
+ * for this use, may be ipath_cfgports summed over all chips that
+ * are are configured and present
+ */
+ kinfo->spi_nports = dd->ipath_cfgports;
+ /* unit (chip/board) our port is on */
+ kinfo->spi_unit = dd->ipath_unit;
+ /* for now, only a single page */
+ kinfo->spi_tid_maxsize = PAGE_SIZE;
+
+ /*
+ * Doing this per port, and based on the skip value, etc. This has
+ * to be the actual buffer size, since the protocol code treats it
+ * as an array.
+ *
+ * These have to be set to user addresses in the user code via mmap.
+ * These values are used on return to user code for the mmap target
+ * addresses only. For 32 bit, same 44 bit address problem, so use
+ * the physical address, not virtual. Before 2.6.11, using the
+ * page_address() macro worked, but in 2.6.11, even that returns the
+ * full 64 bit address (upper bits all 1's). So far, using the
+ * physical addresses (or chip offsets, for chip mapping) works, but
+ * no doubt some future kernel release will chang that, and we'll be
+ * on to yet another method of dealing with this
+ */
+ kinfo->spi_rcvhdr_base = (u64) pd->port_rcvhdrq_phys;
+ kinfo->spi_rcv_egrbufs = (u64) pd->port_rcvegr_phys;
+ kinfo->spi_pioavailaddr = (u64) dd->ipath_pioavailregs_phys;
+ kinfo->spi_status = (u64) kinfo->spi_pioavailaddr +
+ (void *) dd->ipath_statusp -
+ (void *) dd->ipath_pioavailregs_dma;
+ kinfo->spi_piobufbase = (u64) pd->port_piobufs;
+ kinfo->__spi_uregbase =
+ dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
+
+ kinfo->spi_pioindex = dd->ipath_pbufsport * (pd->port_port - 1);
+ kinfo->spi_piocnt = dd->ipath_pbufsport;
+ kinfo->spi_pioalign = dd->ipath_palign;
+
+ kinfo->spi_qpair = IPATH_KD_QP;
+ kinfo->spi_piosize = dd->ipath_ibmaxlen;
+ kinfo->spi_mtu = dd->ipath_ibmaxlen; /* maxlen, not ibmtu */
+ kinfo->spi_port = pd->port_port;
+ kinfo->spi_sw_version = IPATH_KERN_SWVERSION;
+ kinfo->spi_hw_version = dd->ipath_revision;
+
+ if (copy_to_user(ubase, kinfo, sizeof(*kinfo)))
+ ret = -EFAULT;
+
+bail:
+ kfree(kinfo);
+ return ret;
+}
+
+/**
+ * ipath_tid_update - update a port TID
+ * @pd: the port
+ * @ti: the TID information
+ *
+ * The new implementation as of Oct 2004 is that the driver assigns
+ * the tid and returns it to the caller. To make it easier to
+ * catch bugs, and to reduce search time, we keep a cursor for
+ * each port, walking the shadow tid array to find one that's not
+ * in use.
+ *
+ * For now, if we can't allocate the full list, we fail, although
+ * in the long run, we'll allocate as many as we can, and the
+ * caller will deal with that by trying the remaining pages later.
+ * That means that when we fail, we have to mark the tids as not in
+ * use again, in our shadow copy.
+ *
+ * It's up to the caller to free the tids when they are done.
+ * We'll unlock the pages as they free them.
+ *
+ * Also, right now we are locking one page at a time, but since
+ * the intended use of this routine is for a single group of
+ * virtually contiguous pages, that should change to improve
+ * performance.
+ */
+static int ipath_tid_update(struct ipath_portdata *pd,
+ const struct ipath_tid_info *ti)
+{
+ int ret = 0, ntids;
+ u32 tid, porttid, cnt, i, tidcnt;
+ u16 *tidlist;
+ struct ipath_devdata *dd = pd->port_dd;
+ u64 physaddr;
+ unsigned long vaddr;
+ u64 __iomem *tidbase;
+ unsigned long tidmap[8];
+ struct page **pagep = NULL;
+
+ if (!dd->ipath_pageshadow) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ cnt = ti->tidcnt;
+ if (!cnt) {
+ ipath_dbg("After copyin, tidcnt 0, tidlist %llx\n",
+ (unsigned long long) ti->tidlist);
+ /*
+ * Should we treat as success? likely a bug
+ */
+ ret = -EFAULT;
+ goto done;
+ }
+ tidcnt = dd->ipath_rcvtidcnt;
+ if (cnt >= tidcnt) {
+ /* make sure it all fits in port_tid_pg_list */
+ dev_info(&dd->pcidev->dev, "Process tried to allocate %u "
+ "TIDs, only trying max (%u)\n", cnt, tidcnt);
+ cnt = tidcnt;
+ }
+ pagep = (struct page **)pd->port_tid_pg_list;
+ tidlist = (u16 *) (&pagep[cnt]);
+
+ memset(tidmap, 0, sizeof(tidmap));
+ tid = pd->port_tidcursor;
+ /* before decrement; chip actual # */
+ porttid = pd->port_port * tidcnt;
+ ntids = tidcnt;
+ tidbase = (u64 __iomem *) (((char __iomem *) dd->ipath_kregbase) +
+ dd->ipath_rcvtidbase +
+ porttid * sizeof(*tidbase));
+
+ ipath_cdbg(VERBOSE, "Port%u %u tids, cursor %u, tidbase %p\n",
+ pd->port_port, cnt, tid, tidbase);
+
+ /* virtual address of first page in transfer */
+ vaddr = ti->tidvaddr;
+ if (!access_ok(VERIFY_WRITE, (void __user *) vaddr,
+ cnt * PAGE_SIZE)) {
+ ipath_dbg("Fail vaddr %p, %u pages, !access_ok\n",
+ (void *)vaddr, cnt);
+ ret = -EFAULT;
+ goto done;
+ }
+ ret = ipath_get_user_pages(vaddr, cnt, pagep);
+ if (ret) {
+ if (ret == -EBUSY) {
+ ipath_dbg("Failed to lock addr %p, %u pages "
+ "(already locked)\n",
+ (void *) vaddr, cnt);
+ /*
+ * for now, continue, and see what happens but with
+ * the new implementation, this should never happen,
+ * unless perhaps the user has mpin'ed the pages
+ * themselves (something we need to test)
+ */
+ ret = 0;
+ } else {
+ dev_info(&dd->pcidev->dev,
+ "Failed to lock addr %p, %u pages: "
+ "errno %d\n", (void *) vaddr, cnt, -ret);
+ goto done;
+ }
+ }
+ for (i = 0; i < cnt; i++, vaddr += PAGE_SIZE) {
+ for (; ntids--; tid++) {
+ if (tid == tidcnt)
+ tid = 0;
+ if (!dd->ipath_pageshadow[porttid + tid])
+ break;
+ }
+ if (ntids < 0) {
+ /*
+ * oops, wrapped all the way through their TIDs,
+ * and didn't have enough free; see comments at
+ * start of routine
+ */
+ ipath_dbg("Not enough free TIDs for %u pages "
+ "(index %d), failing\n", cnt, i);
+ i--; /* last tidlist[i] not filled in */
+ ret = -ENOMEM;
+ break;
+ }
+ tidlist[i] = tid;
+ ipath_cdbg(VERBOSE, "Updating idx %u to TID %u, "
+ "vaddr %lx\n", i, tid, vaddr);
+ /* we "know" system pages and TID pages are same size */
+ dd->ipath_pageshadow[porttid + tid] = pagep[i];
+ /*
+ * don't need atomic or it's overhead
+ */
+ __set_bit(tid, tidmap);
+ physaddr = page_to_phys(pagep[i]);
+ ipath_stats.sps_pagelocks++;
+ ipath_cdbg(VERBOSE,
+ "TID %u, vaddr %lx, physaddr %llx pgp %p\n",
+ tid, vaddr, (unsigned long long) physaddr,
+ pagep[i]);
+ dd->ipath_f_put_tid(dd, &tidbase[tid], 1, physaddr);
+ /*
+ * don't check this tid in ipath_portshadow, since we
+ * just filled it in; start with the next one.
+ */
+ tid++;
+ }
+
+ if (ret) {
+ u32 limit;
+ cleanup:
+ /* jump here if copy out of updated info failed... */
+ ipath_dbg("After failure (ret=%d), undo %d of %d entries\n",
+ -ret, i, cnt);
+ /* same code that's in ipath_free_tid() */
+ limit = sizeof(tidmap) * BITS_PER_BYTE;
+ if (limit > tidcnt)
+ /* just in case size changes in future */
+ limit = tidcnt;
+ tid = find_first_bit((const unsigned long *)tidmap, limit);
+ for (; tid < limit; tid++) {
+ if (!test_bit(tid, tidmap))
+ continue;
+ if (dd->ipath_pageshadow[porttid + tid]) {
+ ipath_cdbg(VERBOSE, "Freeing TID %u\n",
+ tid);
+ dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
+ dd->ipath_tidinvalid);
+ dd->ipath_pageshadow[porttid + tid] = NULL;
+ ipath_stats.sps_pageunlocks++;
+ }
+ }
+ ipath_release_user_pages(pagep, cnt);
+ } else {
+ /*
+ * Copy the updated array, with ipath_tid's filled in, back
+ * to user. Since we did the copy in already, this "should
+ * never fail" If it does, we have to clean up...
+ */
+ if (copy_to_user((void __user *)
+ (unsigned long) ti->tidlist,
+ tidlist, cnt * sizeof(*tidlist))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ if (copy_to_user((void __user *) (unsigned long) ti->tidmap,
+ tidmap, sizeof tidmap)) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ if (tid == tidcnt)
+ tid = 0;
+ pd->port_tidcursor = tid;
+ }
+
+done:
+ if (ret)
+ ipath_dbg("Failed to map %u TID pages, failing with %d\n",
+ ti->tidcnt, -ret);
+ return ret;
+}
+
+/**
+ * ipath_tid_free - free a port TID
+ * @pd: the port
+ * @ti: the TID info
+ *
+ * right now we are unlocking one page at a time, but since
+ * the intended use of this routine is for a single group of
+ * virtually contiguous pages, that should change to improve
+ * performance. We check that the TID is in range for this port
+ * but otherwise don't check validity; if user has an error and
+ * frees the wrong tid, it's only their own data that can thereby
+ * be corrupted. We do check that the TID was in use, for sanity
+ * We always use our idea of the saved address, not the address that
+ * they pass in to us.
+ */
+
+static int ipath_tid_free(struct ipath_portdata *pd,
+ const struct ipath_tid_info *ti)
+{
+ int ret = 0;
+ u32 tid, porttid, cnt, limit, tidcnt;
+ struct ipath_devdata *dd = pd->port_dd;
+ u64 __iomem *tidbase;
+ unsigned long tidmap[8];
+
+ if (!dd->ipath_pageshadow) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ if (copy_from_user(tidmap, (void __user *)(unsigned long)ti->tidmap,
+ sizeof tidmap)) {
+ ret = -EFAULT;
+ goto done;
+ }
+
+ porttid = pd->port_port * dd->ipath_rcvtidcnt;
+ tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
+ dd->ipath_rcvtidbase +
+ porttid * sizeof(*tidbase));
+
+ tidcnt = dd->ipath_rcvtidcnt;
+ limit = sizeof(tidmap) * BITS_PER_BYTE;
+ if (limit > tidcnt)
+ /* just in case size changes in future */
+ limit = tidcnt;
+ tid = find_first_bit(tidmap, limit);
+ ipath_cdbg(VERBOSE, "Port%u free %u tids; first bit (max=%d) "
+ "set is %d, porttid %u\n", pd->port_port, ti->tidcnt,
+ limit, tid, porttid);
+ for (cnt = 0; tid < limit; tid++) {
+ /*
+ * small optimization; if we detect a run of 3 or so without
+ * any set, use find_first_bit again. That's mainly to
+ * accelerate the case where we wrapped, so we have some at
+ * the beginning, and some at the end, and a big gap
+ * in the middle.
+ */
+ if (!test_bit(tid, tidmap))
+ continue;
+ cnt++;
+ if (dd->ipath_pageshadow[porttid + tid]) {
+ ipath_cdbg(VERBOSE, "PID %u freeing TID %u\n",
+ pd->port_pid, tid);
+ dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
+ dd->ipath_tidinvalid);
+ ipath_release_user_pages(
+ &dd->ipath_pageshadow[porttid + tid], 1);
+ dd->ipath_pageshadow[porttid + tid] = NULL;
+ ipath_stats.sps_pageunlocks++;
+ } else
+ ipath_dbg("Unused tid %u, ignoring\n", tid);
+ }
+ if (cnt != ti->tidcnt)
+ ipath_dbg("passed in tidcnt %d, only %d bits set in map\n",
+ ti->tidcnt, cnt);
+done:
+ if (ret)
+ ipath_dbg("Failed to unmap %u TID pages, failing with %d\n",
+ ti->tidcnt, -ret);
+ return ret;
+}
+
+/**
+ * ipath_set_part_key - set a partition key
+ * @pd: the port
+ * @key: the key
+ *
+ * We can have up to 4 active at a time (other than the default, which is
+ * always allowed). This is somewhat tricky, since multiple ports may set
+ * the same key, so we reference count them, and clean up at exit. All 4
+ * partition keys are packed into a single infinipath register. It's an
+ * error for a process to set the same pkey multiple times. We provide no
+ * mechanism to de-allocate a pkey at this time, we may eventually need to
+ * do that. I've used the atomic operations, and no locking, and only make
+ * a single pass through what's available. This should be more than
+ * adequate for some time. I'll think about spinlocks or the like if and as
+ * it's necessary.
+ */
+static int ipath_set_part_key(struct ipath_portdata *pd, u16 key)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ int i, any = 0, pidx = -1;
+ u16 lkey = key & 0x7FFF;
+ int ret;
+
+ if (lkey == (IPS_DEFAULT_P_KEY & 0x7FFF)) {
+ /* nothing to do; this key always valid */
+ ret = 0;
+ goto bail;
+ }
+
+ ipath_cdbg(VERBOSE, "p%u try to set pkey %hx, current keys "
+ "%hx:%x %hx:%x %hx:%x %hx:%x\n",
+ pd->port_port, key, dd->ipath_pkeys[0],
+ atomic_read(&dd->ipath_pkeyrefs[0]), dd->ipath_pkeys[1],
+ atomic_read(&dd->ipath_pkeyrefs[1]), dd->ipath_pkeys[2],
+ atomic_read(&dd->ipath_pkeyrefs[2]), dd->ipath_pkeys[3],
+ atomic_read(&dd->ipath_pkeyrefs[3]));
+
+ if (!lkey) {
+ ipath_cdbg(PROC, "p%u tries to set key 0, not allowed\n",
+ pd->port_port);
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ /*
+ * Set the full membership bit, because it has to be
+ * set in the register or the packet, and it seems
+ * cleaner to set in the register than to force all
+ * callers to set it. (see bug 4331)
+ */
+ key |= 0x8000;
+
+ for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) {
+ if (!pd->port_pkeys[i] && pidx == -1)
+ pidx = i;
+ if (pd->port_pkeys[i] == key) {
+ ipath_cdbg(VERBOSE, "p%u tries to set same pkey "
+ "(%x) more than once\n",
+ pd->port_port, key);
+ ret = -EEXIST;
+ goto bail;
+ }
+ }
+ if (pidx == -1) {
+ ipath_dbg("All pkeys for port %u already in use, "
+ "can't set %x\n", pd->port_port, key);
+ ret = -EBUSY;
+ goto bail;
+ }
+ for (any = i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+ if (!dd->ipath_pkeys[i]) {
+ any++;
+ continue;
+ }
+ if (dd->ipath_pkeys[i] == key) {
+ atomic_t *pkrefs = &dd->ipath_pkeyrefs[i];
+
+ if (atomic_inc_return(pkrefs) > 1) {
+ pd->port_pkeys[pidx] = key;
+ ipath_cdbg(VERBOSE, "p%u set key %x "
+ "matches #%d, count now %d\n",
+ pd->port_port, key, i,
+ atomic_read(pkrefs));
+ ret = 0;
+ goto bail;
+ } else {
+ /*
+ * lost race, decrement count, catch below
+ */
+ atomic_dec(pkrefs);
+ ipath_cdbg(VERBOSE, "Lost race, count was "
+ "0, after dec, it's %d\n",
+ atomic_read(pkrefs));
+ any++;
+ }
+ }
+ if ((dd->ipath_pkeys[i] & 0x7FFF) == lkey) {
+ /*
+ * It makes no sense to have both the limited and
+ * full membership PKEY set at the same time since
+ * the unlimited one will disable the limited one.
+ */
+ ret = -EEXIST;
+ goto bail;
+ }
+ }
+ if (!any) {
+ ipath_dbg("port %u, all pkeys already in use, "
+ "can't set %x\n", pd->port_port, key);
+ ret = -EBUSY;
+ goto bail;
+ }
+ for (any = i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+ if (!dd->ipath_pkeys[i] &&
+ atomic_inc_return(&dd->ipath_pkeyrefs[i]) == 1) {
+ u64 pkey;
+
+ /* for ipathstats, etc. */
+ ipath_stats.sps_pkeys[i] = lkey;
+ pd->port_pkeys[pidx] = dd->ipath_pkeys[i] = key;
+ pkey =
+ (u64) dd->ipath_pkeys[0] |
+ ((u64) dd->ipath_pkeys[1] << 16) |
+ ((u64) dd->ipath_pkeys[2] << 32) |
+ ((u64) dd->ipath_pkeys[3] << 48);
+ ipath_cdbg(PROC, "p%u set key %x in #%d, "
+ "portidx %d, new pkey reg %llx\n",
+ pd->port_port, key, i, pidx,
+ (unsigned long long) pkey);
+ ipath_write_kreg(
+ dd, dd->ipath_kregs->kr_partitionkey, pkey);
+
+ ret = 0;
+ goto bail;
+ }
+ }
+ ipath_dbg("port %u, all pkeys already in use 2nd pass, "
+ "can't set %x\n", pd->port_port, key);
+ ret = -EBUSY;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_manage_rcvq - manage a port's receive queue
+ * @pd: the port
+ * @start_stop: action to carry out
+ *
+ * start_stop == 0 disables receive on the port, for use in queue
+ * overflow conditions. start_stop==1 re-enables, to be used to
+ * re-init the software copy of the head register
+ */
+static int ipath_manage_rcvq(struct ipath_portdata *pd, int start_stop)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ u64 tval;
+
+ ipath_cdbg(PROC, "%sabling rcv for unit %u port %u\n",
+ start_stop ? "en" : "dis", dd->ipath_unit,
+ pd->port_port);
+ /* atomically clear receive enable port. */
+ if (start_stop) {
+ /*
+ * On enable, force in-memory copy of the tail register to
+ * 0, so that protocol code doesn't have to worry about
+ * whether or not the chip has yet updated the in-memory
+ * copy or not on return from the system call. The chip
+ * always resets it's tail register back to 0 on a
+ * transition from disabled to enabled. This could cause a
+ * problem if software was broken, and did the enable w/o
+ * the disable, but eventually the in-memory copy will be
+ * updated and correct itself, even in the face of software
+ * bugs.
+ */
+ *pd->port_rcvhdrtail_kvaddr = 0;
+ set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+ &dd->ipath_rcvctrl);
+ } else
+ clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+ &dd->ipath_rcvctrl);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+ /* now be sure chip saw it before we return */
+ tval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ if (start_stop) {
+ /*
+ * And try to be sure that tail reg update has happened too.
+ * This should in theory interlock with the RXE changes to
+ * the tail register. Don't assign it to the tail register
+ * in memory copy, since we could overwrite an update by the
+ * chip if we did.
+ */
+ tval = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+ }
+ /* always; new head should be equal to new tail; see above */
+ return 0;
+}
+
+static void ipath_clean_part_key(struct ipath_portdata *pd,
+ struct ipath_devdata *dd)
+{
+ int i, j, pchanged = 0;
+ u64 oldpkey;
+
+ /* for debugging only */
+ oldpkey = (u64) dd->ipath_pkeys[0] |
+ ((u64) dd->ipath_pkeys[1] << 16) |
+ ((u64) dd->ipath_pkeys[2] << 32) |
+ ((u64) dd->ipath_pkeys[3] << 48);
+
+ for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) {
+ if (!pd->port_pkeys[i])
+ continue;
+ ipath_cdbg(VERBOSE, "look for key[%d] %hx in pkeys\n", i,
+ pd->port_pkeys[i]);
+ for (j = 0; j < ARRAY_SIZE(dd->ipath_pkeys); j++) {
+ /* check for match independent of the global bit */
+ if ((dd->ipath_pkeys[j] & 0x7fff) !=
+ (pd->port_pkeys[i] & 0x7fff))
+ continue;
+ if (atomic_dec_and_test(&dd->ipath_pkeyrefs[j])) {
+ ipath_cdbg(VERBOSE, "p%u clear key "
+ "%x matches #%d\n",
+ pd->port_port,
+ pd->port_pkeys[i], j);
+ ipath_stats.sps_pkeys[j] =
+ dd->ipath_pkeys[j] = 0;
+ pchanged++;
+ }
+ else ipath_cdbg(
+ VERBOSE, "p%u key %x matches #%d, "
+ "but ref still %d\n", pd->port_port,
+ pd->port_pkeys[i], j,
+ atomic_read(&dd->ipath_pkeyrefs[j]));
+ break;
+ }
+ pd->port_pkeys[i] = 0;
+ }
+ if (pchanged) {
+ u64 pkey = (u64) dd->ipath_pkeys[0] |
+ ((u64) dd->ipath_pkeys[1] << 16) |
+ ((u64) dd->ipath_pkeys[2] << 32) |
+ ((u64) dd->ipath_pkeys[3] << 48);
+ ipath_cdbg(VERBOSE, "p%u old pkey reg %llx, "
+ "new pkey reg %llx\n", pd->port_port,
+ (unsigned long long) oldpkey,
+ (unsigned long long) pkey);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey,
+ pkey);
+ }
+}
+
+/**
+ * ipath_create_user_egr - allocate eager TID buffers
+ * @pd: the port to allocate TID buffers for
+ *
+ * This routine is now quite different for user and kernel, because
+ * the kernel uses skb's, for the accelerated network performance
+ * This is the user port version
+ *
+ * Allocate the eager TID buffers and program them into infinipath
+ * They are no longer completely contiguous, we do multiple allocation
+ * calls.
+ */
+static int ipath_create_user_egr(struct ipath_portdata *pd)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ unsigned e, egrcnt, alloced, egrperchunk, chunk, egrsize, egroff;
+ size_t size;
+ int ret;
+
+ egrcnt = dd->ipath_rcvegrcnt;
+ /* TID number offset for this port */
+ egroff = pd->port_port * egrcnt;
+ egrsize = dd->ipath_rcvegrbufsize;
+ ipath_cdbg(VERBOSE, "Allocating %d egr buffers, at egrtid "
+ "offset %x, egrsize %u\n", egrcnt, egroff, egrsize);
+
+ /*
+ * to avoid wasting a lot of memory, we allocate 32KB chunks of
+ * physically contiguous memory, advance through it until used up
+ * and then allocate more. Of course, we need memory to store those
+ * extra pointers, now. Started out with 256KB, but under heavy
+ * memory pressure (creating large files and then copying them over
+ * NFS while doing lots of MPI jobs), we hit some allocation
+ * failures, even though we can sleep... (2.6.10) Still get
+ * failures at 64K. 32K is the lowest we can go without waiting
+ * more memory again. It seems likely that the coalescing in
+ * free_pages, etc. still has issues (as it has had previously
+ * during 2.6.x development).
+ */
+ size = 0x8000;
+ alloced = ALIGN(egrsize * egrcnt, size);
+ egrperchunk = size / egrsize;
+ chunk = (egrcnt + egrperchunk - 1) / egrperchunk;
+ pd->port_rcvegrbuf_chunks = chunk;
+ pd->port_rcvegrbufs_perchunk = egrperchunk;
+ pd->port_rcvegrbuf_size = size;
+ pd->port_rcvegrbuf = vmalloc(chunk * sizeof(pd->port_rcvegrbuf[0]));
+ if (!pd->port_rcvegrbuf) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ pd->port_rcvegrbuf_phys =
+ vmalloc(chunk * sizeof(pd->port_rcvegrbuf_phys[0]));
+ if (!pd->port_rcvegrbuf_phys) {
+ ret = -ENOMEM;
+ goto bail_rcvegrbuf;
+ }
+ for (e = 0; e < pd->port_rcvegrbuf_chunks; e++) {
+ /*
+ * GFP_USER, but without GFP_FS, so buffer cache can be
+ * coalesced (we hope); otherwise, even at order 4,
+ * heavy filesystem activity makes these fail
+ */
+ gfp_t gfp_flags = __GFP_WAIT | __GFP_IO | __GFP_COMP;
+
+ pd->port_rcvegrbuf[e] = dma_alloc_coherent(
+ &dd->pcidev->dev, size, &pd->port_rcvegrbuf_phys[e],
+ gfp_flags);
+
+ if (!pd->port_rcvegrbuf[e]) {
+ ret = -ENOMEM;
+ goto bail_rcvegrbuf_phys;
+ }
+ }
+
+ pd->port_rcvegr_phys = pd->port_rcvegrbuf_phys[0];
+
+ for (e = chunk = 0; chunk < pd->port_rcvegrbuf_chunks; chunk++) {
+ dma_addr_t pa = pd->port_rcvegrbuf_phys[chunk];
+ unsigned i;
+
+ for (i = 0; e < egrcnt && i < egrperchunk; e++, i++) {
+ dd->ipath_f_put_tid(dd, e + egroff +
+ (u64 __iomem *)
+ ((char __iomem *)
+ dd->ipath_kregbase +
+ dd->ipath_rcvegrbase), 0, pa);
+ pa += egrsize;
+ }
+ cond_resched(); /* don't hog the cpu */
+ }
+
+ ret = 0;
+ goto bail;
+
+bail_rcvegrbuf_phys:
+ for (e = 0; e < pd->port_rcvegrbuf_chunks &&
+ pd->port_rcvegrbuf[e]; e++)
+ dma_free_coherent(&dd->pcidev->dev, size,
+ pd->port_rcvegrbuf[e],
+ pd->port_rcvegrbuf_phys[e]);
+
+ vfree(pd->port_rcvegrbuf_phys);
+ pd->port_rcvegrbuf_phys = NULL;
+bail_rcvegrbuf:
+ vfree(pd->port_rcvegrbuf);
+ pd->port_rcvegrbuf = NULL;
+bail:
+ return ret;
+}
+
+static int ipath_do_user_init(struct ipath_portdata *pd,
+ const struct ipath_user_info *uinfo)
+{
+ int ret = 0;
+ struct ipath_devdata *dd = pd->port_dd;
+ u64 physaddr, uaddr, off, atmp;
+ struct page *pagep;
+ u32 head32;
+ u64 head;
+
+ /* for now, if major version is different, bail */
+ if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) {
+ dev_info(&dd->pcidev->dev,
+ "User major version %d not same as driver "
+ "major %d\n", uinfo->spu_userversion >> 16,
+ IPATH_USER_SWMAJOR);
+ ret = -ENODEV;
+ goto done;
+ }
+
+ if ((uinfo->spu_userversion & 0xffff) != IPATH_USER_SWMINOR)
+ ipath_dbg("User minor version %d not same as driver "
+ "minor %d\n", uinfo->spu_userversion & 0xffff,
+ IPATH_USER_SWMINOR);
+
+ if (uinfo->spu_rcvhdrsize) {
+ ret = ipath_setrcvhdrsize(dd, uinfo->spu_rcvhdrsize);
+ if (ret)
+ goto done;
+ }
+
+ /* for now we do nothing with rcvhdrcnt: uinfo->spu_rcvhdrcnt */
+
+ /* set up for the rcvhdr Q tail register writeback to user memory */
+ if (!uinfo->spu_rcvhdraddr ||
+ !access_ok(VERIFY_WRITE, (u64 __user *) (unsigned long)
+ uinfo->spu_rcvhdraddr, sizeof(u64))) {
+ ipath_dbg("Port %d rcvhdrtail addr %llx not valid\n",
+ pd->port_port,
+ (unsigned long long) uinfo->spu_rcvhdraddr);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ off = offset_in_page(uinfo->spu_rcvhdraddr);
+ uaddr = PAGE_MASK & (unsigned long) uinfo->spu_rcvhdraddr;
+ ret = ipath_get_user_pages_nocopy(uaddr, &pagep);
+ if (ret) {
+ dev_info(&dd->pcidev->dev, "Failed to lookup and lock "
+ "address %llx for rcvhdrtail: errno %d\n",
+ (unsigned long long) uinfo->spu_rcvhdraddr, -ret);
+ goto done;
+ }
+ ipath_stats.sps_pagelocks++;
+ pd->port_rcvhdrtail_uaddr = uaddr;
+ pd->port_rcvhdrtail_pagep = pagep;
+ pd->port_rcvhdrtail_kvaddr =
+ page_address(pagep);
+ pd->port_rcvhdrtail_kvaddr += off;
+ physaddr = page_to_phys(pagep) + off;
+ ipath_cdbg(VERBOSE, "port %d user addr %llx hdrtailaddr, %llx "
+ "physical (off=%llx)\n",
+ pd->port_port,
+ (unsigned long long) uinfo->spu_rcvhdraddr,
+ (unsigned long long) physaddr, (unsigned long long) off);
+ ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdrtailaddr,
+ pd->port_port, physaddr);
+ atmp = ipath_read_kreg64_port(dd,
+ dd->ipath_kregs->kr_rcvhdrtailaddr,
+ pd->port_port);
+ if (physaddr != atmp) {
+ ipath_dev_err(dd,
+ "Catastrophic software error, "
+ "RcvHdrTailAddr%u written as %llx, "
+ "read back as %llx\n", pd->port_port,
+ (unsigned long long) physaddr,
+ (unsigned long long) atmp);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* for right now, kernel piobufs are at end, so port 1 is at 0 */
+ pd->port_piobufs = dd->ipath_piobufbase +
+ dd->ipath_pbufsport * (pd->port_port -
+ 1) * dd->ipath_palign;
+ ipath_cdbg(VERBOSE, "Set base of piobufs for port %u to 0x%x\n",
+ pd->port_port, pd->port_piobufs);
+
+ /*
+ * Now allocate the rcvhdr Q and eager TIDs; skip the TID
+ * array for time being. If pd->port_port > chip-supported,
+ * we need to do extra stuff here to handle by handling overflow
+ * through port 0, someday
+ */
+ ret = ipath_create_rcvhdrq(dd, pd);
+ if (!ret)
+ ret = ipath_create_user_egr(pd);
+ if (ret)
+ goto done;
+ /* enable receives now */
+ /* atomically set enable bit for this port */
+ set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+ &dd->ipath_rcvctrl);
+
+ /*
+ * set the head registers for this port to the current values
+ * of the tail pointers, since we don't know if they were
+ * updated on last use of the port.
+ */
+ head32 = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+ head = (u64) head32;
+ ipath_write_ureg(dd, ur_rcvhdrhead, head, pd->port_port);
+ head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port);
+ ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port);
+ dd->ipath_lastegrheads[pd->port_port] = -1;
+ dd->ipath_lastrcvhdrqtails[pd->port_port] = -1;
+ ipath_cdbg(VERBOSE, "Wrote port%d head %llx, egrhead %x from "
+ "tail regs\n", pd->port_port,
+ (unsigned long long) head, head32);
+ pd->port_tidcursor = 0; /* start at beginning after open */
+ /*
+ * now enable the port; the tail registers will be written to memory
+ * by the chip as soon as it sees the write to
+ * dd->ipath_kregs->kr_rcvctrl. The update only happens on
+ * transition from 0 to 1, so clear it first, then set it as part of
+ * enabling the port. This will (very briefly) affect any other
+ * open ports, but it shouldn't be long enough to be an issue.
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+done:
+ return ret;
+}
+
+static int mmap_ureg(struct vm_area_struct *vma, struct ipath_devdata *dd,
+ u64 ureg)
+{
+ unsigned long phys;
+ int ret;
+
+ /* it's the real hardware, so io_remap works */
+
+ if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) {
+ dev_info(&dd->pcidev->dev, "FAIL mmap userreg: reqlen "
+ "%lx > PAGE\n", vma->vm_end - vma->vm_start);
+ ret = -EFAULT;
+ } else {
+ phys = dd->ipath_physaddr + ureg;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
+ ret = io_remap_pfn_range(vma, vma->vm_start,
+ phys >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+ }
+ return ret;
+}
+
+static int mmap_piobufs(struct vm_area_struct *vma,
+ struct ipath_devdata *dd,
+ struct ipath_portdata *pd)
+{
+ unsigned long phys;
+ int ret;
+
+ /*
+ * When we map the PIO buffers, we want to map them as writeonly, no
+ * read possible.
+ */
+
+ if ((vma->vm_end - vma->vm_start) >
+ (dd->ipath_pbufsport * dd->ipath_palign)) {
+ dev_info(&dd->pcidev->dev, "FAIL mmap piobufs: "
+ "reqlen %lx > PAGE\n",
+ vma->vm_end - vma->vm_start);
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ phys = dd->ipath_physaddr + pd->port_piobufs;
+ /*
+ * Do *NOT* mark this as non-cached (PWT bit), or we don't get the
+ * write combining behavior we want on the PIO buffers!
+ * vma->vm_page_prot =
+ * pgprot_noncached(vma->vm_page_prot);
+ */
+
+ if (vma->vm_flags & VM_READ) {
+ dev_info(&dd->pcidev->dev,
+ "Can't map piobufs as readable (flags=%lx)\n",
+ vma->vm_flags);
+ ret = -EPERM;
+ goto bail;
+ }
+
+ /* don't allow them to later change to readable with mprotect */
+
+ vma->vm_flags &= ~VM_MAYWRITE;
+ vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
+
+ ret = io_remap_pfn_range(vma, vma->vm_start, phys >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+bail:
+ return ret;
+}
+
+static int mmap_rcvegrbufs(struct vm_area_struct *vma,
+ struct ipath_portdata *pd)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ unsigned long start, size;
+ size_t total_size, i;
+ dma_addr_t *phys;
+ int ret;
+
+ if (!pd->port_rcvegrbuf) {
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ size = pd->port_rcvegrbuf_size;
+ total_size = pd->port_rcvegrbuf_chunks * size;
+ if ((vma->vm_end - vma->vm_start) > total_size) {
+ dev_info(&dd->pcidev->dev, "FAIL on egr bufs: "
+ "reqlen %lx > actual %lx\n",
+ vma->vm_end - vma->vm_start,
+ (unsigned long) total_size);
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ if (vma->vm_flags & VM_WRITE) {
+ dev_info(&dd->pcidev->dev, "Can't map eager buffers as "
+ "writable (flags=%lx)\n", vma->vm_flags);
+ ret = -EPERM;
+ goto bail;
+ }
+
+ start = vma->vm_start;
+ phys = pd->port_rcvegrbuf_phys;
+
+ /* don't allow them to later change to writeable with mprotect */
+ vma->vm_flags &= ~VM_MAYWRITE;
+
+ for (i = 0; i < pd->port_rcvegrbuf_chunks; i++, start += size) {
+ ret = remap_pfn_range(vma, start, phys[i] >> PAGE_SHIFT,
+ size, vma->vm_page_prot);
+ if (ret < 0)
+ goto bail;
+ }
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static int mmap_rcvhdrq(struct vm_area_struct *vma,
+ struct ipath_portdata *pd)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ size_t total_size;
+ int ret;
+
+ /*
+ * kmalloc'ed memory, physically contiguous; this is from
+ * spi_rcvhdr_base; we allow user to map read-write so they can
+ * write hdrq entries to allow protocol code to directly poll
+ * whether a hdrq entry has been written.
+ */
+ total_size = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize *
+ sizeof(u32), PAGE_SIZE);
+ if ((vma->vm_end - vma->vm_start) > total_size) {
+ dev_info(&dd->pcidev->dev,
+ "FAIL on rcvhdrq: reqlen %lx > actual %lx\n",
+ vma->vm_end - vma->vm_start,
+ (unsigned long) total_size);
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ ret = remap_pfn_range(vma, vma->vm_start,
+ pd->port_rcvhdrq_phys >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+bail:
+ return ret;
+}
+
+static int mmap_pioavailregs(struct vm_area_struct *vma,
+ struct ipath_portdata *pd)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ int ret;
+
+ /*
+ * when we map the PIO bufferavail registers, we want to map them as
+ * readonly, no write possible.
+ *
+ * kmalloc'ed memory, physically contiguous, one page only, readonly
+ */
+
+ if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) {
+ dev_info(&dd->pcidev->dev, "FAIL on pioavailregs_dma: "
+ "reqlen %lx > actual %lx\n",
+ vma->vm_end - vma->vm_start,
+ (unsigned long) PAGE_SIZE);
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ if (vma->vm_flags & VM_WRITE) {
+ dev_info(&dd->pcidev->dev,
+ "Can't map pioavailregs as writable (flags=%lx)\n",
+ vma->vm_flags);
+ ret = -EPERM;
+ goto bail;
+ }
+
+ /* don't allow them to later change with mprotect */
+ vma->vm_flags &= ~VM_MAYWRITE;
+
+ ret = remap_pfn_range(vma, vma->vm_start,
+ dd->ipath_pioavailregs_phys >> PAGE_SHIFT,
+ PAGE_SIZE, vma->vm_page_prot);
+bail:
+ return ret;
+}
+
+/**
+ * ipath_mmap - mmap various structures into user space
+ * @fp: the file pointer
+ * @vma: the VM area
+ *
+ * We use this to have a shared buffer between the kernel and the user code
+ * for the rcvhdr queue, egr buffers, and the per-port user regs and pio
+ * buffers in the chip. We have the open and close entries so we can bump
+ * the ref count and keep the driver from being unloaded while still mapped.
+ */
+static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
+{
+ struct ipath_portdata *pd;
+ struct ipath_devdata *dd;
+ u64 pgaddr, ureg;
+ int ret;
+
+ pd = port_fp(fp);
+ dd = pd->port_dd;
+ /*
+ * This is the ipath_do_user_init() code, mapping the shared buffers
+ * into the user process. The address referred to by vm_pgoff is the
+ * virtual, not physical, address; we only do one mmap for each
+ * space mapped.
+ */
+ pgaddr = vma->vm_pgoff << PAGE_SHIFT;
+
+ /*
+ * note that ureg does *NOT* have the kregvirt as part of it, to be
+ * sure that for 32 bit programs, we don't end up trying to map a >
+ * 44 address. Has to match ipath_get_base_info() code that sets
+ * __spi_uregbase
+ */
+
+ ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
+
+ ipath_cdbg(MM, "ushare: pgaddr %llx vm_start=%lx, vmlen %lx\n",
+ (unsigned long long) pgaddr, vma->vm_start,
+ vma->vm_end - vma->vm_start);
+
+ if (pgaddr == ureg)
+ ret = mmap_ureg(vma, dd, ureg);
+ else if (pgaddr == pd->port_piobufs)
+ ret = mmap_piobufs(vma, dd, pd);
+ else if (pgaddr == (u64) pd->port_rcvegr_phys)
+ ret = mmap_rcvegrbufs(vma, pd);
+ else if (pgaddr == (u64) pd->port_rcvhdrq_phys)
+ ret = mmap_rcvhdrq(vma, pd);
+ else if (pgaddr == dd->ipath_pioavailregs_phys)
+ ret = mmap_pioavailregs(vma, pd);
+ else
+ ret = -EINVAL;
+
+ vma->vm_private_data = NULL;
+
+ if (ret < 0)
+ dev_info(&dd->pcidev->dev,
+ "Failure %d on addr %lx, off %lx\n",
+ -ret, vma->vm_start, vma->vm_pgoff);
+
+ return ret;
+}
+
+static unsigned int ipath_poll(struct file *fp,
+ struct poll_table_struct *pt)
+{
+ struct ipath_portdata *pd;
+ u32 head, tail;
+ int bit;
+ struct ipath_devdata *dd;
+
+ pd = port_fp(fp);
+ dd = pd->port_dd;
+
+ bit = pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT;
+ set_bit(bit, &dd->ipath_rcvctrl);
+
+ /*
+ * Before blocking, make sure that head is still == tail,
+ * reading from the chip, so we can be sure the interrupt
+ * enable has made it to the chip. If not equal, disable
+ * interrupt again and return immediately. This avoids races,
+ * and the overhead of the chip read doesn't matter much at
+ * this point, since we are waiting for something anyway.
+ */
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+ head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port);
+ tail = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+
+ if (tail == head) {
+ set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
+ if(dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */
+ (void)ipath_write_ureg(dd, ur_rcvhdrhead,
+ dd->ipath_rhdrhead_intr_off
+ | head, pd->port_port);
+ poll_wait(fp, &pd->port_wait, pt);
+
+ if (test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) {
+ /* timed out, no packets received */
+ clear_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
+ pd->port_rcvwait_to++;
+ }
+ }
+ else {
+ /* it's already happened; don't do wait_event overhead */
+ pd->port_rcvnowait++;
+ }
+
+ clear_bit(bit, &dd->ipath_rcvctrl);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+ return 0;
+}
+
+static int try_alloc_port(struct ipath_devdata *dd, int port,
+ struct file *fp)
+{
+ int ret;
+
+ if (!dd->ipath_pd[port]) {
+ void *p, *ptmp;
+
+ p = kzalloc(sizeof(struct ipath_portdata), GFP_KERNEL);
+
+ /*
+ * Allocate memory for use in ipath_tid_update() just once
+ * at open, not per call. Reduces cost of expected send
+ * setup.
+ */
+ ptmp = kmalloc(dd->ipath_rcvtidcnt * sizeof(u16) +
+ dd->ipath_rcvtidcnt * sizeof(struct page **),
+ GFP_KERNEL);
+ if (!p || !ptmp) {
+ ipath_dev_err(dd, "Unable to allocate portdata "
+ "memory, failing open\n");
+ ret = -ENOMEM;
+ kfree(p);
+ kfree(ptmp);
+ goto bail;
+ }
+ dd->ipath_pd[port] = p;
+ dd->ipath_pd[port]->port_port = port;
+ dd->ipath_pd[port]->port_dd = dd;
+ dd->ipath_pd[port]->port_tid_pg_list = ptmp;
+ init_waitqueue_head(&dd->ipath_pd[port]->port_wait);
+ }
+ if (!dd->ipath_pd[port]->port_cnt) {
+ dd->ipath_pd[port]->port_cnt = 1;
+ fp->private_data = (void *) dd->ipath_pd[port];
+ ipath_cdbg(PROC, "%s[%u] opened unit:port %u:%u\n",
+ current->comm, current->pid, dd->ipath_unit,
+ port);
+ dd->ipath_pd[port]->port_pid = current->pid;
+ strncpy(dd->ipath_pd[port]->port_comm, current->comm,
+ sizeof(dd->ipath_pd[port]->port_comm));
+ ipath_stats.sps_ports++;
+ ret = 0;
+ goto bail;
+ }
+ ret = -EBUSY;
+
+bail:
+ return ret;
+}
+
+static inline int usable(struct ipath_devdata *dd)
+{
+ return dd &&
+ (dd->ipath_flags & IPATH_PRESENT) &&
+ dd->ipath_kregbase &&
+ dd->ipath_lid &&
+ !(dd->ipath_flags & (IPATH_LINKDOWN | IPATH_DISABLED
+ | IPATH_LINKUNK));
+}
+
+static int find_free_port(int unit, struct file *fp)
+{
+ struct ipath_devdata *dd = ipath_lookup(unit);
+ int ret, i;
+
+ if (!dd) {
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ if (!usable(dd)) {
+ ret = -ENETDOWN;
+ goto bail;
+ }
+
+ for (i = 0; i < dd->ipath_cfgports; i++) {
+ ret = try_alloc_port(dd, i, fp);
+ if (ret != -EBUSY)
+ goto bail;
+ }
+ ret = -EBUSY;
+
+bail:
+ return ret;
+}
+
+static int find_best_unit(struct file *fp)
+{
+ int ret = 0, i, prefunit = -1, devmax;
+ int maxofallports, npresent, nup;
+ int ndev;
+
+ (void) ipath_count_units(&npresent, &nup, &maxofallports);
+
+ /*
+ * This code is present to allow a knowledgeable person to
+ * specify the layout of processes to processors before opening
+ * this driver, and then we'll assign the process to the "closest"
+ * HT-400 to that processor (we assume reasonable connectivity,
+ * for now). This code assumes that if affinity has been set
+ * before this point, that at most one cpu is set; for now this
+ * is reasonable. I check for both cpus_empty() and cpus_full(),
+ * in case some kernel variant sets none of the bits when no
+ * affinity is set. 2.6.11 and 12 kernels have all present
+ * cpus set. Some day we'll have to fix it up further to handle
+ * a cpu subset. This algorithm fails for two HT-400's connected
+ * in tunnel fashion. Eventually this needs real topology
+ * information. There may be some issues with dual core numbering
+ * as well. This needs more work prior to release.
+ */
+ if (!cpus_empty(current->cpus_allowed) &&
+ !cpus_full(current->cpus_allowed)) {
+ int ncpus = num_online_cpus(), curcpu = -1;
+ for (i = 0; i < ncpus; i++)
+ if (cpu_isset(i, current->cpus_allowed)) {
+ ipath_cdbg(PROC, "%s[%u] affinity set for "
+ "cpu %d\n", current->comm,
+ current->pid, i);
+ curcpu = i;
+ }
+ if (curcpu != -1) {
+ if (npresent) {
+ prefunit = curcpu / (ncpus / npresent);
+ ipath_dbg("%s[%u] %d chips, %d cpus, "
+ "%d cpus/chip, select unit %d\n",
+ current->comm, current->pid,
+ npresent, ncpus, ncpus / npresent,
+ prefunit);
+ }
+ }
+ }
+
+ /*
+ * user ports start at 1, kernel port is 0
+ * For now, we do round-robin access across all chips
+ */
+
+ if (prefunit != -1)
+ devmax = prefunit + 1;
+ else
+ devmax = ipath_count_units(NULL, NULL, NULL);
+recheck:
+ for (i = 1; i < maxofallports; i++) {
+ for (ndev = prefunit != -1 ? prefunit : 0; ndev < devmax;
+ ndev++) {
+ struct ipath_devdata *dd = ipath_lookup(ndev);
+
+ if (!usable(dd))
+ continue; /* can't use this unit */
+ if (i >= dd->ipath_cfgports)
+ /*
+ * Maxed out on users of this unit. Try
+ * next.
+ */
+ continue;
+ ret = try_alloc_port(dd, i, fp);
+ if (!ret)
+ goto done;
+ }
+ }
+
+ if (npresent) {
+ if (nup == 0) {
+ ret = -ENETDOWN;
+ ipath_dbg("No ports available (none initialized "
+ "and ready)\n");
+ } else {
+ if (prefunit > 0) {
+ /* if started above 0, retry from 0 */
+ ipath_cdbg(PROC,
+ "%s[%u] no ports on prefunit "
+ "%d, clear and re-check\n",
+ current->comm, current->pid,
+ prefunit);
+ devmax = ipath_count_units(NULL, NULL,
+ NULL);
+ prefunit = -1;
+ goto recheck;
+ }
+ ret = -EBUSY;
+ ipath_dbg("No ports available\n");
+ }
+ } else {
+ ret = -ENXIO;
+ ipath_dbg("No boards found\n");
+ }
+
+done:
+ return ret;
+}
+
+static int ipath_open(struct inode *in, struct file *fp)
+{
+ int ret, minor;
+
+ mutex_lock(&ipath_mutex);
+
+ minor = iminor(in);
+ ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n",
+ (long)in->i_rdev, minor);
+
+ if (minor)
+ ret = find_free_port(minor - 1, fp);
+ else
+ ret = find_best_unit(fp);
+
+ mutex_unlock(&ipath_mutex);
+ return ret;
+}
+
+/**
+ * unlock_exptid - unlock any expected TID entries port still had in use
+ * @pd: port
+ *
+ * We don't actually update the chip here, because we do a bulk update
+ * below, using ipath_f_clear_tids.
+ */
+static void unlock_expected_tids(struct ipath_portdata *pd)
+{
+ struct ipath_devdata *dd = pd->port_dd;
+ int port_tidbase = pd->port_port * dd->ipath_rcvtidcnt;
+ int i, cnt = 0, maxtid = port_tidbase + dd->ipath_rcvtidcnt;
+
+ ipath_cdbg(VERBOSE, "Port %u unlocking any locked expTID pages\n",
+ pd->port_port);
+ for (i = port_tidbase; i < maxtid; i++) {
+ if (!dd->ipath_pageshadow[i])
+ continue;
+
+ ipath_release_user_pages_on_close(&dd->ipath_pageshadow[i],
+ 1);
+ dd->ipath_pageshadow[i] = NULL;
+ cnt++;
+ ipath_stats.sps_pageunlocks++;
+ }
+ if (cnt)
+ ipath_cdbg(VERBOSE, "Port %u locked %u expTID entries\n",
+ pd->port_port, cnt);
+
+ if (ipath_stats.sps_pagelocks || ipath_stats.sps_pageunlocks)
+ ipath_cdbg(VERBOSE, "%llu pages locked, %llu unlocked\n",
+ (unsigned long long) ipath_stats.sps_pagelocks,
+ (unsigned long long)
+ ipath_stats.sps_pageunlocks);
+}
+
+static int ipath_close(struct inode *in, struct file *fp)
+{
+ int ret = 0;
+ struct ipath_portdata *pd;
+ struct ipath_devdata *dd;
+ unsigned port;
+
+ ipath_cdbg(VERBOSE, "close on dev %lx, private data %p\n",
+ (long)in->i_rdev, fp->private_data);
+
+ mutex_lock(&ipath_mutex);
+
+ pd = port_fp(fp);
+ port = pd->port_port;
+ fp->private_data = NULL;
+ dd = pd->port_dd;
+
+ if (pd->port_hdrqfull) {
+ ipath_cdbg(PROC, "%s[%u] had %u rcvhdrqfull errors "
+ "during run\n", pd->port_comm, pd->port_pid,
+ pd->port_hdrqfull);
+ pd->port_hdrqfull = 0;
+ }
+
+ if (pd->port_rcvwait_to || pd->port_piowait_to
+ || pd->port_rcvnowait || pd->port_pionowait) {
+ ipath_cdbg(VERBOSE, "port%u, %u rcv, %u pio wait timeo; "
+ "%u rcv %u, pio already\n",
+ pd->port_port, pd->port_rcvwait_to,
+ pd->port_piowait_to, pd->port_rcvnowait,
+ pd->port_pionowait);
+ pd->port_rcvwait_to = pd->port_piowait_to =
+ pd->port_rcvnowait = pd->port_pionowait = 0;
+ }
+ if (pd->port_flag) {
+ ipath_dbg("port %u port_flag still set to 0x%lx\n",
+ pd->port_port, pd->port_flag);
+ pd->port_flag = 0;
+ }
+
+ if (dd->ipath_kregbase) {
+ if (pd->port_rcvhdrtail_uaddr) {
+ pd->port_rcvhdrtail_uaddr = 0;
+ pd->port_rcvhdrtail_kvaddr = NULL;
+ ipath_release_user_pages_on_close(
+ &pd->port_rcvhdrtail_pagep, 1);
+ pd->port_rcvhdrtail_pagep = NULL;
+ ipath_stats.sps_pageunlocks++;
+ }
+ ipath_write_kreg_port(
+ dd, dd->ipath_kregs->kr_rcvhdrtailaddr,
+ port, 0ULL);
+ ipath_write_kreg_port(
+ dd, dd->ipath_kregs->kr_rcvhdraddr,
+ pd->port_port, 0);
+
+ /* clean up the pkeys for this port user */
+ ipath_clean_part_key(pd, dd);
+
+ if (port < dd->ipath_cfgports) {
+ int i = dd->ipath_pbufsport * (port - 1);
+ ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);
+
+ /* atomically clear receive enable port. */
+ clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + port,
+ &dd->ipath_rcvctrl);
+ ipath_write_kreg(
+ dd,
+ dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+ if (dd->ipath_pageshadow)
+ unlock_expected_tids(pd);
+ ipath_stats.sps_ports--;
+ ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n",
+ pd->port_comm, pd->port_pid,
+ dd->ipath_unit, port);
+ }
+ }
+
+ pd->port_cnt = 0;
+ pd->port_pid = 0;
+
+ dd->ipath_f_clear_tids(dd, pd->port_port);
+
+ ipath_free_pddata(dd, pd->port_port, 0);
+
+ mutex_unlock(&ipath_mutex);
+
+ return ret;
+}
+
+static int ipath_port_info(struct ipath_portdata *pd,
+ struct ipath_port_info __user *uinfo)
+{
+ struct ipath_port_info info;
+ int nup;
+ int ret;
+
+ (void) ipath_count_units(NULL, &nup, NULL);
+ info.num_active = nup;
+ info.unit = pd->port_dd->ipath_unit;
+ info.port = pd->port_port;
+
+ if (copy_to_user(uinfo, &info, sizeof(info))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static ssize_t ipath_write(struct file *fp, const char __user *data,
+ size_t count, loff_t *off)
+{
+ const struct ipath_cmd __user *ucmd;
+ struct ipath_portdata *pd;
+ const void __user *src;
+ size_t consumed, copy;
+ struct ipath_cmd cmd;
+ ssize_t ret = 0;
+ void *dest;
+
+ if (count < sizeof(cmd.type)) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ ucmd = (const struct ipath_cmd __user *) data;
+
+ if (copy_from_user(&cmd.type, &ucmd->type, sizeof(cmd.type))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ consumed = sizeof(cmd.type);
+
+ switch (cmd.type) {
+ case IPATH_CMD_USER_INIT:
+ copy = sizeof(cmd.cmd.user_info);
+ dest = &cmd.cmd.user_info;
+ src = &ucmd->cmd.user_info;
+ break;
+ case IPATH_CMD_RECV_CTRL:
+ copy = sizeof(cmd.cmd.recv_ctrl);
+ dest = &cmd.cmd.recv_ctrl;
+ src = &ucmd->cmd.recv_ctrl;
+ break;
+ case IPATH_CMD_PORT_INFO:
+ copy = sizeof(cmd.cmd.port_info);
+ dest = &cmd.cmd.port_info;
+ src = &ucmd->cmd.port_info;
+ break;
+ case IPATH_CMD_TID_UPDATE:
+ case IPATH_CMD_TID_FREE:
+ copy = sizeof(cmd.cmd.tid_info);
+ dest = &cmd.cmd.tid_info;
+ src = &ucmd->cmd.tid_info;
+ break;
+ case IPATH_CMD_SET_PART_KEY:
+ copy = sizeof(cmd.cmd.part_key);
+ dest = &cmd.cmd.part_key;
+ src = &ucmd->cmd.part_key;
+ break;
+ default:
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if ((count - consumed) < copy) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (copy_from_user(dest, src, copy)) {
+ ret = -EFAULT;
+ goto bail;
+ }
+
+ consumed += copy;
+ pd = port_fp(fp);
+
+ switch (cmd.type) {
+ case IPATH_CMD_USER_INIT:
+ ret = ipath_do_user_init(pd, &cmd.cmd.user_info);
+ if (ret < 0)
+ goto bail;
+ ret = ipath_get_base_info(
+ pd, (void __user *) (unsigned long)
+ cmd.cmd.user_info.spu_base_info,
+ cmd.cmd.user_info.spu_base_info_size);
+ break;
+ case IPATH_CMD_RECV_CTRL:
+ ret = ipath_manage_rcvq(pd, cmd.cmd.recv_ctrl);
+ break;
+ case IPATH_CMD_PORT_INFO:
+ ret = ipath_port_info(pd,
+ (struct ipath_port_info __user *)
+ (unsigned long) cmd.cmd.port_info);
+ break;
+ case IPATH_CMD_TID_UPDATE:
+ ret = ipath_tid_update(pd, &cmd.cmd.tid_info);
+ break;
+ case IPATH_CMD_TID_FREE:
+ ret = ipath_tid_free(pd, &cmd.cmd.tid_info);
+ break;
+ case IPATH_CMD_SET_PART_KEY:
+ ret = ipath_set_part_key(pd, cmd.cmd.part_key);
+ break;
+ }
+
+ if (ret >= 0)
+ ret = consumed;
+
+bail:
+ return ret;
+}
+
+static struct class *ipath_class;
+
+static int init_cdev(int minor, char *name, struct file_operations *fops,
+ struct cdev **cdevp, struct class_device **class_devp)
+{
+ const dev_t dev = MKDEV(IPATH_MAJOR, minor);
+ struct cdev *cdev = NULL;
+ struct class_device *class_dev = NULL;
+ int ret;
+
+ cdev = cdev_alloc();
+ if (!cdev) {
+ printk(KERN_ERR IPATH_DRV_NAME
+ ": Could not allocate cdev for minor %d, %s\n",
+ minor, name);
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ cdev->owner = THIS_MODULE;
+ cdev->ops = fops;
+ kobject_set_name(&cdev->kobj, name);
+
+ ret = cdev_add(cdev, dev, 1);
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME
+ ": Could not add cdev for minor %d, %s (err %d)\n",
+ minor, name, -ret);
+ goto err_cdev;
+ }
+
+ class_dev = class_device_create(ipath_class, NULL, dev, NULL, name);
+
+ if (IS_ERR(class_dev)) {
+ ret = PTR_ERR(class_dev);
+ printk(KERN_ERR IPATH_DRV_NAME ": Could not create "
+ "class_dev for minor %d, %s (err %d)\n",
+ minor, name, -ret);
+ goto err_cdev;
+ }
+
+ goto done;
+
+err_cdev:
+ cdev_del(cdev);
+ cdev = NULL;
+
+done:
+ if (ret >= 0) {
+ *cdevp = cdev;
+ *class_devp = class_dev;
+ } else {
+ *cdevp = NULL;
+ *class_devp = NULL;
+ }
+
+ return ret;
+}
+
+int ipath_cdev_init(int minor, char *name, struct file_operations *fops,
+ struct cdev **cdevp, struct class_device **class_devp)
+{
+ return init_cdev(minor, name, fops, cdevp, class_devp);
+}
+
+static void cleanup_cdev(struct cdev **cdevp,
+ struct class_device **class_devp)
+{
+ struct class_device *class_dev = *class_devp;
+
+ if (class_dev) {
+ class_device_unregister(class_dev);
+ *class_devp = NULL;
+ }
+
+ if (*cdevp) {
+ cdev_del(*cdevp);
+ *cdevp = NULL;
+ }
+}
+
+void ipath_cdev_cleanup(struct cdev **cdevp,
+ struct class_device **class_devp)
+{
+ cleanup_cdev(cdevp, class_devp);
+}
+
+static struct cdev *wildcard_cdev;
+static struct class_device *wildcard_class_dev;
+
+static const dev_t dev = MKDEV(IPATH_MAJOR, 0);
+
+static int user_init(void)
+{
+ int ret;
+
+ ret = register_chrdev_region(dev, IPATH_NMINORS, IPATH_DRV_NAME);
+ if (ret < 0) {
+ printk(KERN_ERR IPATH_DRV_NAME ": Could not register "
+ "chrdev region (err %d)\n", -ret);
+ goto done;
+ }
+
+ ipath_class = class_create(THIS_MODULE, IPATH_DRV_NAME);
+
+ if (IS_ERR(ipath_class)) {
+ ret = PTR_ERR(ipath_class);
+ printk(KERN_ERR IPATH_DRV_NAME ": Could not create "
+ "device class (err %d)\n", -ret);
+ goto bail;
+ }
+
+ goto done;
+bail:
+ unregister_chrdev_region(dev, IPATH_NMINORS);
+done:
+ return ret;
+}
+
+static void user_cleanup(void)
+{
+ if (ipath_class) {
+ class_destroy(ipath_class);
+ ipath_class = NULL;
+ }
+
+ unregister_chrdev_region(dev, IPATH_NMINORS);
+}
+
+static atomic_t user_count = ATOMIC_INIT(0);
+static atomic_t user_setup = ATOMIC_INIT(0);
+
+int ipath_user_add(struct ipath_devdata *dd)
+{
+ char name[10];
+ int ret;
+
+ if (atomic_inc_return(&user_count) == 1) {
+ ret = user_init();
+ if (ret < 0) {
+ ipath_dev_err(dd, "Unable to set up user support: "
+ "error %d\n", -ret);
+ goto bail;
+ }
+ ret = ipath_diag_init();
+ if (ret < 0) {
+ ipath_dev_err(dd, "Unable to set up diag support: "
+ "error %d\n", -ret);
+ goto bail_sma;
+ }
+
+ ret = init_cdev(0, "ipath", &ipath_file_ops, &wildcard_cdev,
+ &wildcard_class_dev);
+ if (ret < 0) {
+ ipath_dev_err(dd, "Could not create wildcard "
+ "minor: error %d\n", -ret);
+ goto bail_diag;
+ }
+
+ atomic_set(&user_setup, 1);
+ }
+
+ snprintf(name, sizeof(name), "ipath%d", dd->ipath_unit);
+
+ ret = init_cdev(dd->ipath_unit + 1, name, &ipath_file_ops,
+ &dd->cdev, &dd->class_dev);
+ if (ret < 0)
+ ipath_dev_err(dd, "Could not create user minor %d, %s\n",
+ dd->ipath_unit + 1, name);
+
+ goto bail;
+
+bail_diag:
+ ipath_diag_cleanup();
+bail_sma:
+ user_cleanup();
+bail:
+ return ret;
+}
+
+void ipath_user_del(struct ipath_devdata *dd)
+{
+ cleanup_cdev(&dd->cdev, &dd->class_dev);
+
+ if (atomic_dec_return(&user_count) == 0) {
+ if (atomic_read(&user_setup) == 0)
+ goto bail;
+
+ cleanup_cdev(&wildcard_cdev, &wildcard_class_dev);
+ ipath_diag_cleanup();
+ user_cleanup();
+
+ atomic_set(&user_setup, 0);
+ }
+bail:
+ return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
new file mode 100644
index 00000000000..e274120567e
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -0,0 +1,605 @@
+/*
+ * Copyright (c) 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/version.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/namei.h>
+#include <linux/pci.h>
+
+#include "ipath_kernel.h"
+
+#define IPATHFS_MAGIC 0x726a77
+
+static struct super_block *ipath_super;
+
+static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
+ int mode, struct file_operations *fops,
+ void *data)
+{
+ int error;
+ struct inode *inode = new_inode(dir->i_sb);
+
+ if (!inode) {
+ error = -EPERM;
+ goto bail;
+ }
+
+ inode->i_mode = mode;
+ inode->i_uid = 0;
+ inode->i_gid = 0;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->u.generic_ip = data;
+ if ((mode & S_IFMT) == S_IFDIR) {
+ inode->i_op = &simple_dir_inode_operations;
+ inode->i_nlink++;
+ dir->i_nlink++;
+ }
+
+ inode->i_fop = fops;
+
+ d_instantiate(dentry, inode);
+ error = 0;
+
+bail:
+ return error;
+}
+
+static int create_file(const char *name, mode_t mode,
+ struct dentry *parent, struct dentry **dentry,
+ struct file_operations *fops, void *data)
+{
+ int error;
+
+ *dentry = NULL;
+ mutex_lock(&parent->d_inode->i_mutex);
+ *dentry = lookup_one_len(name, parent, strlen(name));
+ if (!IS_ERR(dentry))
+ error = ipathfs_mknod(parent->d_inode, *dentry,
+ mode, fops, data);
+ else
+ error = PTR_ERR(dentry);
+ mutex_unlock(&parent->d_inode->i_mutex);
+
+ return error;
+}
+
+static ssize_t atomic_stats_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return simple_read_from_buffer(buf, count, ppos, &ipath_stats,
+ sizeof ipath_stats);
+}
+
+static struct file_operations atomic_stats_ops = {
+ .read = atomic_stats_read,
+};
+
+#define NUM_COUNTERS sizeof(struct infinipath_counters) / sizeof(u64)
+
+static ssize_t atomic_counters_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ u64 counters[NUM_COUNTERS];
+ u16 i;
+ struct ipath_devdata *dd;
+
+ dd = file->f_dentry->d_inode->u.generic_ip;
+
+ for (i = 0; i < NUM_COUNTERS; i++)
+ counters[i] = ipath_snap_cntr(dd, i);
+
+ return simple_read_from_buffer(buf, count, ppos, counters,
+ sizeof counters);
+}
+
+static struct file_operations atomic_counters_ops = {
+ .read = atomic_counters_read,
+};
+
+static ssize_t atomic_node_info_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ u32 nodeinfo[10];
+ struct ipath_devdata *dd;
+ u64 guid;
+
+ dd = file->f_dentry->d_inode->u.generic_ip;
+
+ guid = be64_to_cpu(dd->ipath_guid);
+
+ nodeinfo[0] = /* BaseVersion is SMA */
+ /* ClassVersion is SMA */
+ (1 << 8) /* NodeType */
+ | (1 << 0); /* NumPorts */
+ nodeinfo[1] = (u32) (guid >> 32);
+ nodeinfo[2] = (u32) (guid & 0xffffffff);
+ /* PortGUID == SystemImageGUID for us */
+ nodeinfo[3] = nodeinfo[1];
+ /* PortGUID == SystemImageGUID for us */
+ nodeinfo[4] = nodeinfo[2];
+ /* PortGUID == NodeGUID for us */
+ nodeinfo[5] = nodeinfo[3];
+ /* PortGUID == NodeGUID for us */
+ nodeinfo[6] = nodeinfo[4];
+ nodeinfo[7] = (4 << 16) /* we support 4 pkeys */
+ | (dd->ipath_deviceid << 0);
+ /* our chip version as 16 bits major, 16 bits minor */
+ nodeinfo[8] = dd->ipath_minrev | (dd->ipath_majrev << 16);
+ nodeinfo[9] = (dd->ipath_unit << 24) | (dd->ipath_vendorid << 0);
+
+ return simple_read_from_buffer(buf, count, ppos, nodeinfo,
+ sizeof nodeinfo);
+}
+
+static struct file_operations atomic_node_info_ops = {
+ .read = atomic_node_info_read,
+};
+
+static ssize_t atomic_port_info_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ u32 portinfo[13];
+ u32 tmp, tmp2;
+ struct ipath_devdata *dd;
+
+ dd = file->f_dentry->d_inode->u.generic_ip;
+
+ /* so we only initialize non-zero fields. */
+ memset(portinfo, 0, sizeof portinfo);
+
+ /*
+ * Notimpl yet M_Key (64)
+ * Notimpl yet GID (64)
+ */
+
+ portinfo[4] = (dd->ipath_lid << 16);
+
+ /*
+ * Notimpl yet SMLID (should we store this in the driver, in case
+ * SMA dies?) CapabilityMask is 0, we don't support any of these
+ * DiagCode is 0; we don't store any diag info for now Notimpl yet
+ * M_KeyLeasePeriod (we don't support M_Key)
+ */
+
+ /* LocalPortNum is whichever port number they ask for */
+ portinfo[7] = (dd->ipath_unit << 24)
+ /* LinkWidthEnabled */
+ | (2 << 16)
+ /* LinkWidthSupported (really 2, but not IB valid) */
+ | (3 << 8)
+ /* LinkWidthActive */
+ | (2 << 0);
+ tmp = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
+ tmp2 = 5;
+ if (tmp == IPATH_IBSTATE_INIT)
+ tmp = 2;
+ else if (tmp == IPATH_IBSTATE_ARM)
+ tmp = 3;
+ else if (tmp == IPATH_IBSTATE_ACTIVE)
+ tmp = 4;
+ else {
+ tmp = 0; /* down */
+ tmp2 = tmp & 0xf;
+ }
+
+ portinfo[8] = (1 << 28) /* LinkSpeedSupported */
+ | (tmp << 24) /* PortState */
+ | (tmp2 << 20) /* PortPhysicalState */
+ | (2 << 16)
+
+ /* LinkDownDefaultState */
+ /* M_KeyProtectBits == 0 */
+ /* NotImpl yet LMC == 0 (we can support all values) */
+ | (1 << 4) /* LinkSpeedActive */
+ | (1 << 0); /* LinkSpeedEnabled */
+ switch (dd->ipath_ibmtu) {
+ case 4096:
+ tmp = 5;
+ break;
+ case 2048:
+ tmp = 4;
+ break;
+ case 1024:
+ tmp = 3;
+ break;
+ case 512:
+ tmp = 2;
+ break;
+ case 256:
+ tmp = 1;
+ break;
+ default: /* oops, something is wrong */
+ ipath_dbg("Problem, ipath_ibmtu 0x%x not a valid IB MTU, "
+ "treat as 2048\n", dd->ipath_ibmtu);
+ tmp = 4;
+ break;
+ }
+ portinfo[9] = (tmp << 28)
+ /* NeighborMTU */
+ /* Notimpl MasterSMSL */
+ | (1 << 20)
+
+ /* VLCap */
+ /* Notimpl InitType (actually, an SMA decision) */
+ /* VLHighLimit is 0 (only one VL) */
+ ; /* VLArbitrationHighCap is 0 (only one VL) */
+ portinfo[10] = /* VLArbitrationLowCap is 0 (only one VL) */
+ /* InitTypeReply is SMA decision */
+ (5 << 16) /* MTUCap 4096 */
+ | (7 << 13) /* VLStallCount */
+ | (0x1f << 8) /* HOQLife */
+ | (1 << 4)
+
+ /* OperationalVLs 0 */
+ /* PartitionEnforcementInbound */
+ /* PartitionEnforcementOutbound not enforced */
+ /* FilterRawinbound not enforced */
+ ; /* FilterRawOutbound not enforced */
+ /* M_KeyViolations are not counted by hardware, SMA can count */
+ tmp = ipath_read_creg32(dd, dd->ipath_cregs->cr_errpkey);
+ /* P_KeyViolations are counted by hardware. */
+ portinfo[11] = ((tmp & 0xffff) << 0);
+ portinfo[12] =
+ /* Q_KeyViolations are not counted by hardware */
+ (1 << 8)
+
+ /* GUIDCap */
+ /* SubnetTimeOut handled by SMA */
+ /* RespTimeValue handled by SMA */
+ ;
+ /* LocalPhyErrors are programmed to max */
+ portinfo[12] |= (0xf << 20)
+ | (0xf << 16) /* OverRunErrors are programmed to max */
+ ;
+
+ return simple_read_from_buffer(buf, count, ppos, portinfo,
+ sizeof portinfo);
+}
+
+static struct file_operations atomic_port_info_ops = {
+ .read = atomic_port_info_read,
+};
+
+static ssize_t flash_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct ipath_devdata *dd;
+ ssize_t ret;
+ loff_t pos;
+ char *tmp;
+
+ pos = *ppos;
+
+ if ( pos < 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (pos >= sizeof(struct ipath_flash)) {
+ ret = 0;
+ goto bail;
+ }
+
+ if (count > sizeof(struct ipath_flash) - pos)
+ count = sizeof(struct ipath_flash) - pos;
+
+ tmp = kmalloc(count, GFP_KERNEL);
+ if (!tmp) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ dd = file->f_dentry->d_inode->u.generic_ip;
+ if (ipath_eeprom_read(dd, pos, tmp, count)) {
+ ipath_dev_err(dd, "failed to read from flash\n");
+ ret = -ENXIO;
+ goto bail_tmp;
+ }
+
+ if (copy_to_user(buf, tmp, count)) {
+ ret = -EFAULT;
+ goto bail_tmp;
+ }
+
+ *ppos = pos + count;
+ ret = count;
+
+bail_tmp:
+ kfree(tmp);
+
+bail:
+ return ret;
+}
+
+static ssize_t flash_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct ipath_devdata *dd;
+ ssize_t ret;
+ loff_t pos;
+ char *tmp;
+
+ pos = *ppos;
+
+ if ( pos < 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (pos >= sizeof(struct ipath_flash)) {
+ ret = 0;
+ goto bail;
+ }
+
+ if (count > sizeof(struct ipath_flash) - pos)
+ count = sizeof(struct ipath_flash) - pos;
+
+ tmp = kmalloc(count, GFP_KERNEL);
+ if (!tmp) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ if (copy_from_user(tmp, buf, count)) {
+ ret = -EFAULT;
+ goto bail_tmp;
+ }
+
+ dd = file->f_dentry->d_inode->u.generic_ip;
+ if (ipath_eeprom_write(dd, pos, tmp, count)) {
+ ret = -ENXIO;
+ ipath_dev_err(dd, "failed to write to flash\n");
+ goto bail_tmp;
+ }
+
+ *ppos = pos + count;
+ ret = count;
+
+bail_tmp:
+ kfree(tmp);
+
+bail:
+ return ret;
+}
+
+static struct file_operations flash_ops = {
+ .read = flash_read,
+ .write = flash_write,
+};
+
+static int create_device_files(struct super_block *sb,
+ struct ipath_devdata *dd)
+{
+ struct dentry *dir, *tmp;
+ char unit[10];
+ int ret;
+
+ snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
+ ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, sb->s_root, &dir,
+ (struct file_operations *) &simple_dir_operations,
+ dd);
+ if (ret) {
+ printk(KERN_ERR "create_file(%s) failed: %d\n", unit, ret);
+ goto bail;
+ }
+
+ ret = create_file("atomic_counters", S_IFREG|S_IRUGO, dir, &tmp,
+ &atomic_counters_ops, dd);
+ if (ret) {
+ printk(KERN_ERR "create_file(%s/atomic_counters) "
+ "failed: %d\n", unit, ret);
+ goto bail;
+ }
+
+ ret = create_file("node_info", S_IFREG|S_IRUGO, dir, &tmp,
+ &atomic_node_info_ops, dd);
+ if (ret) {
+ printk(KERN_ERR "create_file(%s/node_info) "
+ "failed: %d\n", unit, ret);
+ goto bail;
+ }
+
+ ret = create_file("port_info", S_IFREG|S_IRUGO, dir, &tmp,
+ &atomic_port_info_ops, dd);
+ if (ret) {
+ printk(KERN_ERR "create_file(%s/port_info) "
+ "failed: %d\n", unit, ret);
+ goto bail;
+ }
+
+ ret = create_file("flash", S_IFREG|S_IWUSR|S_IRUGO, dir, &tmp,
+ &flash_ops, dd);
+ if (ret) {
+ printk(KERN_ERR "create_file(%s/flash) "
+ "failed: %d\n", unit, ret);
+ goto bail;
+ }
+
+bail:
+ return ret;
+}
+
+static void remove_file(struct dentry *parent, char *name)
+{
+ struct dentry *tmp;
+
+ tmp = lookup_one_len(name, parent, strlen(name));
+
+ spin_lock(&dcache_lock);
+ spin_lock(&tmp->d_lock);
+ if (!(d_unhashed(tmp) && tmp->d_inode)) {
+ dget_locked(tmp);
+ __d_drop(tmp);
+ spin_unlock(&tmp->d_lock);
+ spin_unlock(&dcache_lock);
+ simple_unlink(parent->d_inode, tmp);
+ } else {
+ spin_unlock(&tmp->d_lock);
+ spin_unlock(&dcache_lock);
+ }
+}
+
+static int remove_device_files(struct super_block *sb,
+ struct ipath_devdata *dd)
+{
+ struct dentry *dir, *root;
+ char unit[10];
+ int ret;
+
+ root = dget(sb->s_root);
+ mutex_lock(&root->d_inode->i_mutex);
+ snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
+ dir = lookup_one_len(unit, root, strlen(unit));
+
+ if (IS_ERR(dir)) {
+ ret = PTR_ERR(dir);
+ printk(KERN_ERR "Lookup of %s failed\n", unit);
+ goto bail;
+ }
+
+ remove_file(dir, "flash");
+ remove_file(dir, "port_info");
+ remove_file(dir, "node_info");
+ remove_file(dir, "atomic_counters");
+ d_delete(dir);
+ ret = simple_rmdir(root->d_inode, dir);
+
+bail:
+ mutex_unlock(&root->d_inode->i_mutex);
+ dput(root);
+ return ret;
+}
+
+static int ipathfs_fill_super(struct super_block *sb, void *data,
+ int silent)
+{
+ struct ipath_devdata *dd, *tmp;
+ unsigned long flags;
+ int ret;
+
+ static struct tree_descr files[] = {
+ [1] = {"atomic_stats", &atomic_stats_ops, S_IRUGO},
+ {""},
+ };
+
+ ret = simple_fill_super(sb, IPATHFS_MAGIC, files);
+ if (ret) {
+ printk(KERN_ERR "simple_fill_super failed: %d\n", ret);
+ goto bail;
+ }
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ ret = create_device_files(sb, dd);
+ if (ret) {
+ deactivate_super(sb);
+ goto bail;
+ }
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+bail:
+ return ret;
+}
+
+static struct super_block *ipathfs_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name,
+ void *data)
+{
+ ipath_super = get_sb_single(fs_type, flags, data,
+ ipathfs_fill_super);
+ return ipath_super;
+}
+
+static void ipathfs_kill_super(struct super_block *s)
+{
+ kill_litter_super(s);
+ ipath_super = NULL;
+}
+
+int ipathfs_add_device(struct ipath_devdata *dd)
+{
+ int ret;
+
+ if (ipath_super == NULL) {
+ ret = 0;
+ goto bail;
+ }
+
+ ret = create_device_files(ipath_super, dd);
+
+bail:
+ return ret;
+}
+
+int ipathfs_remove_device(struct ipath_devdata *dd)
+{
+ int ret;
+
+ if (ipath_super == NULL) {
+ ret = 0;
+ goto bail;
+ }
+
+ ret = remove_device_files(ipath_super, dd);
+
+bail:
+ return ret;
+}
+
+static struct file_system_type ipathfs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "ipathfs",
+ .get_sb = ipathfs_get_sb,
+ .kill_sb = ipathfs_kill_super,
+};
+
+int __init ipath_init_ipathfs(void)
+{
+ return register_filesystem(&ipathfs_fs_type);
+}
+
+void __exit ipath_exit_ipathfs(void)
+{
+ unregister_filesystem(&ipathfs_fs_type);
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_ht400.c b/drivers/infiniband/hw/ipath/ipath_ht400.c
new file mode 100644
index 00000000000..fac0a2b74de
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_ht400.c
@@ -0,0 +1,1603 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This file contains all of the code that is specific to the InfiniPath
+ * HT-400 chip.
+ */
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "ipath_kernel.h"
+#include "ipath_registers.h"
+
+/*
+ * This lists the InfiniPath HT400 registers, in the actual chip layout.
+ * This structure should never be directly accessed.
+ *
+ * The names are in InterCap form because they're taken straight from
+ * the chip specification. Since they're only used in this file, they
+ * don't pollute the rest of the source.
+*/
+
+struct _infinipath_do_not_use_kernel_regs {
+ unsigned long long Revision;
+ unsigned long long Control;
+ unsigned long long PageAlign;
+ unsigned long long PortCnt;
+ unsigned long long DebugPortSelect;
+ unsigned long long DebugPort;
+ unsigned long long SendRegBase;
+ unsigned long long UserRegBase;
+ unsigned long long CounterRegBase;
+ unsigned long long Scratch;
+ unsigned long long ReservedMisc1;
+ unsigned long long InterruptConfig;
+ unsigned long long IntBlocked;
+ unsigned long long IntMask;
+ unsigned long long IntStatus;
+ unsigned long long IntClear;
+ unsigned long long ErrorMask;
+ unsigned long long ErrorStatus;
+ unsigned long long ErrorClear;
+ unsigned long long HwErrMask;
+ unsigned long long HwErrStatus;
+ unsigned long long HwErrClear;
+ unsigned long long HwDiagCtrl;
+ unsigned long long MDIO;
+ unsigned long long IBCStatus;
+ unsigned long long IBCCtrl;
+ unsigned long long ExtStatus;
+ unsigned long long ExtCtrl;
+ unsigned long long GPIOOut;
+ unsigned long long GPIOMask;
+ unsigned long long GPIOStatus;
+ unsigned long long GPIOClear;
+ unsigned long long RcvCtrl;
+ unsigned long long RcvBTHQP;
+ unsigned long long RcvHdrSize;
+ unsigned long long RcvHdrCnt;
+ unsigned long long RcvHdrEntSize;
+ unsigned long long RcvTIDBase;
+ unsigned long long RcvTIDCnt;
+ unsigned long long RcvEgrBase;
+ unsigned long long RcvEgrCnt;
+ unsigned long long RcvBufBase;
+ unsigned long long RcvBufSize;
+ unsigned long long RxIntMemBase;
+ unsigned long long RxIntMemSize;
+ unsigned long long RcvPartitionKey;
+ unsigned long long ReservedRcv[10];
+ unsigned long long SendCtrl;
+ unsigned long long SendPIOBufBase;
+ unsigned long long SendPIOSize;
+ unsigned long long SendPIOBufCnt;
+ unsigned long long SendPIOAvailAddr;
+ unsigned long long TxIntMemBase;
+ unsigned long long TxIntMemSize;
+ unsigned long long ReservedSend[9];
+ unsigned long long SendBufferError;
+ unsigned long long SendBufferErrorCONT1;
+ unsigned long long SendBufferErrorCONT2;
+ unsigned long long SendBufferErrorCONT3;
+ unsigned long long ReservedSBE[4];
+ unsigned long long RcvHdrAddr0;
+ unsigned long long RcvHdrAddr1;
+ unsigned long long RcvHdrAddr2;
+ unsigned long long RcvHdrAddr3;
+ unsigned long long RcvHdrAddr4;
+ unsigned long long RcvHdrAddr5;
+ unsigned long long RcvHdrAddr6;
+ unsigned long long RcvHdrAddr7;
+ unsigned long long RcvHdrAddr8;
+ unsigned long long ReservedRHA[7];
+ unsigned long long RcvHdrTailAddr0;
+ unsigned long long RcvHdrTailAddr1;
+ unsigned long long RcvHdrTailAddr2;
+ unsigned long long RcvHdrTailAddr3;
+ unsigned long long RcvHdrTailAddr4;
+ unsigned long long RcvHdrTailAddr5;
+ unsigned long long RcvHdrTailAddr6;
+ unsigned long long RcvHdrTailAddr7;
+ unsigned long long RcvHdrTailAddr8;
+ unsigned long long ReservedRHTA[7];
+ unsigned long long Sync; /* Software only */
+ unsigned long long Dump; /* Software only */
+ unsigned long long SimVer; /* Software only */
+ unsigned long long ReservedSW[5];
+ unsigned long long SerdesConfig0;
+ unsigned long long SerdesConfig1;
+ unsigned long long SerdesStatus;
+ unsigned long long XGXSConfig;
+ unsigned long long ReservedSW2[4];
+};
+
+#define IPATH_KREG_OFFSET(field) (offsetof(struct \
+ _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
+#define IPATH_CREG_OFFSET(field) (offsetof( \
+ struct infinipath_counters, field) / sizeof(u64))
+
+static const struct ipath_kregs ipath_ht_kregs = {
+ .kr_control = IPATH_KREG_OFFSET(Control),
+ .kr_counterregbase = IPATH_KREG_OFFSET(CounterRegBase),
+ .kr_debugport = IPATH_KREG_OFFSET(DebugPort),
+ .kr_debugportselect = IPATH_KREG_OFFSET(DebugPortSelect),
+ .kr_errorclear = IPATH_KREG_OFFSET(ErrorClear),
+ .kr_errormask = IPATH_KREG_OFFSET(ErrorMask),
+ .kr_errorstatus = IPATH_KREG_OFFSET(ErrorStatus),
+ .kr_extctrl = IPATH_KREG_OFFSET(ExtCtrl),
+ .kr_extstatus = IPATH_KREG_OFFSET(ExtStatus),
+ .kr_gpio_clear = IPATH_KREG_OFFSET(GPIOClear),
+ .kr_gpio_mask = IPATH_KREG_OFFSET(GPIOMask),
+ .kr_gpio_out = IPATH_KREG_OFFSET(GPIOOut),
+ .kr_gpio_status = IPATH_KREG_OFFSET(GPIOStatus),
+ .kr_hwdiagctrl = IPATH_KREG_OFFSET(HwDiagCtrl),
+ .kr_hwerrclear = IPATH_KREG_OFFSET(HwErrClear),
+ .kr_hwerrmask = IPATH_KREG_OFFSET(HwErrMask),
+ .kr_hwerrstatus = IPATH_KREG_OFFSET(HwErrStatus),
+ .kr_ibcctrl = IPATH_KREG_OFFSET(IBCCtrl),
+ .kr_ibcstatus = IPATH_KREG_OFFSET(IBCStatus),
+ .kr_intblocked = IPATH_KREG_OFFSET(IntBlocked),
+ .kr_intclear = IPATH_KREG_OFFSET(IntClear),
+ .kr_interruptconfig = IPATH_KREG_OFFSET(InterruptConfig),
+ .kr_intmask = IPATH_KREG_OFFSET(IntMask),
+ .kr_intstatus = IPATH_KREG_OFFSET(IntStatus),
+ .kr_mdio = IPATH_KREG_OFFSET(MDIO),
+ .kr_pagealign = IPATH_KREG_OFFSET(PageAlign),
+ .kr_partitionkey = IPATH_KREG_OFFSET(RcvPartitionKey),
+ .kr_portcnt = IPATH_KREG_OFFSET(PortCnt),
+ .kr_rcvbthqp = IPATH_KREG_OFFSET(RcvBTHQP),
+ .kr_rcvbufbase = IPATH_KREG_OFFSET(RcvBufBase),
+ .kr_rcvbufsize = IPATH_KREG_OFFSET(RcvBufSize),
+ .kr_rcvctrl = IPATH_KREG_OFFSET(RcvCtrl),
+ .kr_rcvegrbase = IPATH_KREG_OFFSET(RcvEgrBase),
+ .kr_rcvegrcnt = IPATH_KREG_OFFSET(RcvEgrCnt),
+ .kr_rcvhdrcnt = IPATH_KREG_OFFSET(RcvHdrCnt),
+ .kr_rcvhdrentsize = IPATH_KREG_OFFSET(RcvHdrEntSize),
+ .kr_rcvhdrsize = IPATH_KREG_OFFSET(RcvHdrSize),
+ .kr_rcvintmembase = IPATH_KREG_OFFSET(RxIntMemBase),
+ .kr_rcvintmemsize = IPATH_KREG_OFFSET(RxIntMemSize),
+ .kr_rcvtidbase = IPATH_KREG_OFFSET(RcvTIDBase),
+ .kr_rcvtidcnt = IPATH_KREG_OFFSET(RcvTIDCnt),
+ .kr_revision = IPATH_KREG_OFFSET(Revision),
+ .kr_scratch = IPATH_KREG_OFFSET(Scratch),
+ .kr_sendbuffererror = IPATH_KREG_OFFSET(SendBufferError),
+ .kr_sendctrl = IPATH_KREG_OFFSET(SendCtrl),
+ .kr_sendpioavailaddr = IPATH_KREG_OFFSET(SendPIOAvailAddr),
+ .kr_sendpiobufbase = IPATH_KREG_OFFSET(SendPIOBufBase),
+ .kr_sendpiobufcnt = IPATH_KREG_OFFSET(SendPIOBufCnt),
+ .kr_sendpiosize = IPATH_KREG_OFFSET(SendPIOSize),
+ .kr_sendregbase = IPATH_KREG_OFFSET(SendRegBase),
+ .kr_txintmembase = IPATH_KREG_OFFSET(TxIntMemBase),
+ .kr_txintmemsize = IPATH_KREG_OFFSET(TxIntMemSize),
+ .kr_userregbase = IPATH_KREG_OFFSET(UserRegBase),
+ .kr_serdesconfig0 = IPATH_KREG_OFFSET(SerdesConfig0),
+ .kr_serdesconfig1 = IPATH_KREG_OFFSET(SerdesConfig1),
+ .kr_serdesstatus = IPATH_KREG_OFFSET(SerdesStatus),
+ .kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig),
+ /*
+ * These should not be used directly via ipath_read_kreg64(),
+ * use them with ipath_read_kreg64_port(),
+ */
+ .kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0),
+ .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0)
+};
+
+static const struct ipath_cregs ipath_ht_cregs = {
+ .cr_badformatcnt = IPATH_CREG_OFFSET(RxBadFormatCnt),
+ .cr_erricrccnt = IPATH_CREG_OFFSET(RxICRCErrCnt),
+ .cr_errlinkcnt = IPATH_CREG_OFFSET(RxLinkProblemCnt),
+ .cr_errlpcrccnt = IPATH_CREG_OFFSET(RxLPCRCErrCnt),
+ .cr_errpkey = IPATH_CREG_OFFSET(RxPKeyMismatchCnt),
+ .cr_errrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowCtrlErrCnt),
+ .cr_err_rlencnt = IPATH_CREG_OFFSET(RxLenErrCnt),
+ .cr_errslencnt = IPATH_CREG_OFFSET(TxLenErrCnt),
+ .cr_errtidfull = IPATH_CREG_OFFSET(RxTIDFullErrCnt),
+ .cr_errtidvalid = IPATH_CREG_OFFSET(RxTIDValidErrCnt),
+ .cr_errvcrccnt = IPATH_CREG_OFFSET(RxVCRCErrCnt),
+ .cr_ibstatuschange = IPATH_CREG_OFFSET(IBStatusChangeCnt),
+ /* calc from Reg_CounterRegBase + offset */
+ .cr_intcnt = IPATH_CREG_OFFSET(LBIntCnt),
+ .cr_invalidrlencnt = IPATH_CREG_OFFSET(RxMaxMinLenErrCnt),
+ .cr_invalidslencnt = IPATH_CREG_OFFSET(TxMaxMinLenErrCnt),
+ .cr_lbflowstallcnt = IPATH_CREG_OFFSET(LBFlowStallCnt),
+ .cr_pktrcvcnt = IPATH_CREG_OFFSET(RxDataPktCnt),
+ .cr_pktrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowPktCnt),
+ .cr_pktsendcnt = IPATH_CREG_OFFSET(TxDataPktCnt),
+ .cr_pktsendflowcnt = IPATH_CREG_OFFSET(TxFlowPktCnt),
+ .cr_portovflcnt = IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt),
+ .cr_rcvebpcnt = IPATH_CREG_OFFSET(RxEBPCnt),
+ .cr_rcvovflcnt = IPATH_CREG_OFFSET(RxBufOvflCnt),
+ .cr_senddropped = IPATH_CREG_OFFSET(TxDroppedPktCnt),
+ .cr_sendstallcnt = IPATH_CREG_OFFSET(TxFlowStallCnt),
+ .cr_sendunderruncnt = IPATH_CREG_OFFSET(TxUnderrunCnt),
+ .cr_wordrcvcnt = IPATH_CREG_OFFSET(RxDwordCnt),
+ .cr_wordsendcnt = IPATH_CREG_OFFSET(TxDwordCnt),
+ .cr_unsupvlcnt = IPATH_CREG_OFFSET(TxUnsupVLErrCnt),
+ .cr_rxdroppktcnt = IPATH_CREG_OFFSET(RxDroppedPktCnt),
+ .cr_iblinkerrrecovcnt = IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt),
+ .cr_iblinkdowncnt = IPATH_CREG_OFFSET(IBLinkDownedCnt),
+ .cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt)
+};
+
+/* kr_intstatus, kr_intclear, kr_intmask bits */
+#define INFINIPATH_I_RCVURG_MASK 0x1FF
+#define INFINIPATH_I_RCVAVAIL_MASK 0x1FF
+
+/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+#define INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT 0
+#define INFINIPATH_HWE_HTCMEMPARITYERR_MASK 0x3FFFFFULL
+#define INFINIPATH_HWE_HTCLNKABYTE0CRCERR 0x0000000000800000ULL
+#define INFINIPATH_HWE_HTCLNKABYTE1CRCERR 0x0000000001000000ULL
+#define INFINIPATH_HWE_HTCLNKBBYTE0CRCERR 0x0000000002000000ULL
+#define INFINIPATH_HWE_HTCLNKBBYTE1CRCERR 0x0000000004000000ULL
+#define INFINIPATH_HWE_HTCMISCERR4 0x0000000008000000ULL
+#define INFINIPATH_HWE_HTCMISCERR5 0x0000000010000000ULL
+#define INFINIPATH_HWE_HTCMISCERR6 0x0000000020000000ULL
+#define INFINIPATH_HWE_HTCMISCERR7 0x0000000040000000ULL
+#define INFINIPATH_HWE_HTCBUSTREQPARITYERR 0x0000000080000000ULL
+#define INFINIPATH_HWE_HTCBUSTRESPPARITYERR 0x0000000100000000ULL
+#define INFINIPATH_HWE_HTCBUSIREQPARITYERR 0x0000000200000000ULL
+#define INFINIPATH_HWE_COREPLL_FBSLIP 0x0080000000000000ULL
+#define INFINIPATH_HWE_COREPLL_RFSLIP 0x0100000000000000ULL
+#define INFINIPATH_HWE_HTBPLL_FBSLIP 0x0200000000000000ULL
+#define INFINIPATH_HWE_HTBPLL_RFSLIP 0x0400000000000000ULL
+#define INFINIPATH_HWE_HTAPLL_FBSLIP 0x0800000000000000ULL
+#define INFINIPATH_HWE_HTAPLL_RFSLIP 0x1000000000000000ULL
+#define INFINIPATH_HWE_SERDESPLLFAILED 0x2000000000000000ULL
+
+/* kr_extstatus bits */
+#define INFINIPATH_EXTS_FREQSEL 0x2
+#define INFINIPATH_EXTS_SERDESSEL 0x4
+#define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000
+#define INFINIPATH_EXTS_MEMBIST_CORRECT 0x0000000000008000
+
+/*
+ * masks and bits that are different in different chips, or present only
+ * in one
+ */
+static const ipath_err_t infinipath_hwe_htcmemparityerr_mask =
+ INFINIPATH_HWE_HTCMEMPARITYERR_MASK;
+static const ipath_err_t infinipath_hwe_htcmemparityerr_shift =
+ INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT;
+
+static const ipath_err_t infinipath_hwe_htclnkabyte0crcerr =
+ INFINIPATH_HWE_HTCLNKABYTE0CRCERR;
+static const ipath_err_t infinipath_hwe_htclnkabyte1crcerr =
+ INFINIPATH_HWE_HTCLNKABYTE1CRCERR;
+static const ipath_err_t infinipath_hwe_htclnkbbyte0crcerr =
+ INFINIPATH_HWE_HTCLNKBBYTE0CRCERR;
+static const ipath_err_t infinipath_hwe_htclnkbbyte1crcerr =
+ INFINIPATH_HWE_HTCLNKBBYTE1CRCERR;
+
+#define _IPATH_GPIO_SDA_NUM 1
+#define _IPATH_GPIO_SCL_NUM 0
+
+#define IPATH_GPIO_SDA \
+ (1ULL << (_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+#define IPATH_GPIO_SCL \
+ (1ULL << (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+
+/* keep the code below somewhat more readonable; not used elsewhere */
+#define _IPATH_HTLINK0_CRCBITS (infinipath_hwe_htclnkabyte0crcerr | \
+ infinipath_hwe_htclnkabyte1crcerr)
+#define _IPATH_HTLINK1_CRCBITS (infinipath_hwe_htclnkbbyte0crcerr | \
+ infinipath_hwe_htclnkbbyte1crcerr)
+#define _IPATH_HTLANE0_CRCBITS (infinipath_hwe_htclnkabyte0crcerr | \
+ infinipath_hwe_htclnkbbyte0crcerr)
+#define _IPATH_HTLANE1_CRCBITS (infinipath_hwe_htclnkabyte1crcerr | \
+ infinipath_hwe_htclnkbbyte1crcerr)
+
+static void hwerr_crcbits(struct ipath_devdata *dd, ipath_err_t hwerrs,
+ char *msg, size_t msgl)
+{
+ char bitsmsg[64];
+ ipath_err_t crcbits = hwerrs &
+ (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS);
+ /* don't check if 8bit HT */
+ if (dd->ipath_flags & IPATH_8BIT_IN_HT0)
+ crcbits &= ~infinipath_hwe_htclnkabyte1crcerr;
+ /* don't check if 8bit HT */
+ if (dd->ipath_flags & IPATH_8BIT_IN_HT1)
+ crcbits &= ~infinipath_hwe_htclnkbbyte1crcerr;
+ /*
+ * we'll want to ignore link errors on link that is
+ * not in use, if any. For now, complain about both
+ */
+ if (crcbits) {
+ u16 ctrl0, ctrl1;
+ snprintf(bitsmsg, sizeof bitsmsg,
+ "[HT%s lane %s CRC (%llx); ignore till reload]",
+ !(crcbits & _IPATH_HTLINK1_CRCBITS) ?
+ "0 (A)" : (!(crcbits & _IPATH_HTLINK0_CRCBITS)
+ ? "1 (B)" : "0+1 (A+B)"),
+ !(crcbits & _IPATH_HTLANE1_CRCBITS) ? "0"
+ : (!(crcbits & _IPATH_HTLANE0_CRCBITS) ? "1" :
+ "0+1"), (unsigned long long) crcbits);
+ strlcat(msg, bitsmsg, msgl);
+
+ /*
+ * print extra info for debugging. slave/primary
+ * config word 4, 8 (link control 0, 1)
+ */
+
+ if (pci_read_config_word(dd->pcidev,
+ dd->ipath_ht_slave_off + 0x4,
+ &ctrl0))
+ dev_info(&dd->pcidev->dev, "Couldn't read "
+ "linkctrl0 of slave/primary "
+ "config block\n");
+ else if (!(ctrl0 & 1 << 6))
+ /* not if EOC bit set */
+ ipath_dbg("HT linkctrl0 0x%x%s%s\n", ctrl0,
+ ((ctrl0 >> 8) & 7) ? " CRC" : "",
+ ((ctrl0 >> 4) & 1) ? "linkfail" :
+ "");
+ if (pci_read_config_word(dd->pcidev,
+ dd->ipath_ht_slave_off + 0x8,
+ &ctrl1))
+ dev_info(&dd->pcidev->dev, "Couldn't read "
+ "linkctrl1 of slave/primary "
+ "config block\n");
+ else if (!(ctrl1 & 1 << 6))
+ /* not if EOC bit set */
+ ipath_dbg("HT linkctrl1 0x%x%s%s\n", ctrl1,
+ ((ctrl1 >> 8) & 7) ? " CRC" : "",
+ ((ctrl1 >> 4) & 1) ? "linkfail" :
+ "");
+
+ /* disable until driver reloaded */
+ dd->ipath_hwerrmask &= ~crcbits;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ ipath_dbg("HT crc errs: %s\n", msg);
+ } else
+ ipath_dbg("ignoring HT crc errors 0x%llx, "
+ "not in use\n", (unsigned long long)
+ (hwerrs & (_IPATH_HTLINK0_CRCBITS |
+ _IPATH_HTLINK1_CRCBITS)));
+}
+
+/**
+ * ipath_ht_handle_hwerrors - display hardware errors
+ * @dd: the infinipath device
+ * @msg: the output buffer
+ * @msgl: the size of the output buffer
+ *
+ * Use same msg buffer as regular errors to avoid
+ * excessive stack use. Most hardware errors are catastrophic, but for
+ * right now, we'll print them and continue.
+ * We reuse the same message buffer as ipath_handle_errors() to avoid
+ * excessive stack usage.
+ */
+static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ size_t msgl)
+{
+ ipath_err_t hwerrs;
+ u32 bits, ctrl;
+ int isfatal = 0;
+ char bitsmsg[64];
+
+ hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
+
+ if (!hwerrs) {
+ ipath_cdbg(VERBOSE, "Called but no hardware errors set\n");
+ /*
+ * better than printing cofusing messages
+ * This seems to be related to clearing the crc error, or
+ * the pll error during init.
+ */
+ goto bail;
+ } else if (hwerrs == -1LL) {
+ ipath_dev_err(dd, "Read of hardware error status failed "
+ "(all bits set); ignoring\n");
+ goto bail;
+ }
+ ipath_stats.sps_hwerrs++;
+
+ /* Always clear the error status register, except MEMBISTFAIL,
+ * regardless of whether we continue or stop using the chip.
+ * We want that set so we know it failed, even across driver reload.
+ * We'll still ignore it in the hwerrmask. We do this partly for
+ * diagnostics, but also for support */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ hwerrs&~INFINIPATH_HWE_MEMBISTFAILED);
+
+ hwerrs &= dd->ipath_hwerrmask;
+
+ /*
+ * make sure we get this much out, unless told to be quiet,
+ * or it's occurred within the last 5 seconds
+ */
+ if ((hwerrs & ~dd->ipath_lasthwerror) ||
+ (ipath_debug & __IPATH_VERBDBG))
+ dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "
+ "(cleared)\n", (unsigned long long) hwerrs);
+ dd->ipath_lasthwerror |= hwerrs;
+
+ if (hwerrs & ~infinipath_hwe_bitsextant)
+ ipath_dev_err(dd, "hwerror interrupt with unknown errors "
+ "%llx set\n", (unsigned long long)
+ (hwerrs & ~infinipath_hwe_bitsextant));
+
+ ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
+ if (ctrl & INFINIPATH_C_FREEZEMODE) {
+ if (hwerrs) {
+ /*
+ * if any set that we aren't ignoring; only
+ * make the complaint once, in case it's stuck
+ * or recurring, and we get here multiple
+ * times.
+ */
+ if (dd->ipath_flags & IPATH_INITTED) {
+ ipath_dev_err(dd, "Fatal Error (freeze "
+ "mode), no longer usable\n");
+ isfatal = 1;
+ }
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+ /* mark as having had error */
+ *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+ /*
+ * mark as not usable, at a minimum until driver
+ * is reloaded, probably until reboot, since no
+ * other reset is possible.
+ */
+ dd->ipath_flags &= ~IPATH_INITTED;
+ } else {
+ ipath_dbg("Clearing freezemode on ignored hardware "
+ "error\n");
+ ctrl &= ~INFINIPATH_C_FREEZEMODE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+ ctrl);
+ }
+ }
+
+ *msg = '\0';
+
+ /*
+ * may someday want to decode into which bits are which
+ * functional area for parity errors, etc.
+ */
+ if (hwerrs & (infinipath_hwe_htcmemparityerr_mask
+ << INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT)) {
+ bits = (u32) ((hwerrs >>
+ INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) &
+ INFINIPATH_HWE_HTCMEMPARITYERR_MASK);
+ snprintf(bitsmsg, sizeof bitsmsg, "[HTC Parity Errs %x] ",
+ bits);
+ strlcat(msg, bitsmsg, msgl);
+ }
+ if (hwerrs & (INFINIPATH_HWE_RXEMEMPARITYERR_MASK
+ << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)) {
+ bits = (u32) ((hwerrs >>
+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) &
+ INFINIPATH_HWE_RXEMEMPARITYERR_MASK);
+ snprintf(bitsmsg, sizeof bitsmsg, "[RXE Parity Errs %x] ",
+ bits);
+ strlcat(msg, bitsmsg, msgl);
+ }
+ if (hwerrs & (INFINIPATH_HWE_TXEMEMPARITYERR_MASK
+ << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {
+ bits = (u32) ((hwerrs >>
+ INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) &
+ INFINIPATH_HWE_TXEMEMPARITYERR_MASK);
+ snprintf(bitsmsg, sizeof bitsmsg, "[TXE Parity Errs %x] ",
+ bits);
+ strlcat(msg, bitsmsg, msgl);
+ }
+ if (hwerrs & INFINIPATH_HWE_IBCBUSTOSPCPARITYERR)
+ strlcat(msg, "[IB2IPATH Parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_IBCBUSFRSPCPARITYERR)
+ strlcat(msg, "[IPATH2IB Parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_HTCBUSIREQPARITYERR)
+ strlcat(msg, "[HTC Ireq Parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_HTCBUSTREQPARITYERR)
+ strlcat(msg, "[HTC Treq Parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_HTCBUSTRESPPARITYERR)
+ strlcat(msg, "[HTC Tresp Parity]", msgl);
+
+ if (hwerrs & (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS))
+ hwerr_crcbits(dd, hwerrs, msg, msgl);
+
+ if (hwerrs & INFINIPATH_HWE_HTCMISCERR5)
+ strlcat(msg, "[HT core Misc5]", msgl);
+ if (hwerrs & INFINIPATH_HWE_HTCMISCERR6)
+ strlcat(msg, "[HT core Misc6]", msgl);
+ if (hwerrs & INFINIPATH_HWE_HTCMISCERR7)
+ strlcat(msg, "[HT core Misc7]", msgl);
+ if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) {
+ strlcat(msg, "[Memory BIST test failed, HT-400 unusable]",
+ msgl);
+ /* ignore from now on, so disable until driver reloaded */
+ dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ }
+#define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP | \
+ INFINIPATH_HWE_COREPLL_RFSLIP | \
+ INFINIPATH_HWE_HTBPLL_FBSLIP | \
+ INFINIPATH_HWE_HTBPLL_RFSLIP | \
+ INFINIPATH_HWE_HTAPLL_FBSLIP | \
+ INFINIPATH_HWE_HTAPLL_RFSLIP)
+
+ if (hwerrs & _IPATH_PLL_FAIL) {
+ snprintf(bitsmsg, sizeof bitsmsg,
+ "[PLL failed (%llx), HT-400 unusable]",
+ (unsigned long long) (hwerrs & _IPATH_PLL_FAIL));
+ strlcat(msg, bitsmsg, msgl);
+ /* ignore from now on, so disable until driver reloaded */
+ dd->ipath_hwerrmask &= ~(hwerrs & _IPATH_PLL_FAIL);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ }
+
+ if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) {
+ /*
+ * If it occurs, it is left masked since the eternal
+ * interface is unused
+ */
+ dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ }
+
+ if (hwerrs & INFINIPATH_HWE_RXDSYNCMEMPARITYERR)
+ strlcat(msg, "[Rx Dsync]", msgl);
+ if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED)
+ strlcat(msg, "[SerDes PLL]", msgl);
+
+ ipath_dev_err(dd, "%s hardware error\n", msg);
+ if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg)
+ /*
+ * for status file; if no trailing brace is copied,
+ * we'll know it was truncated.
+ */
+ snprintf(dd->ipath_freezemsg,
+ dd->ipath_freezelen, "{%s}", msg);
+
+bail:;
+}
+
+/**
+ * ipath_ht_boardname - fill in the board name
+ * @dd: the infinipath device
+ * @name: the output buffer
+ * @namelen: the size of the output buffer
+ *
+ * fill in the board name, based on the board revision register
+ */
+static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
+ size_t namelen)
+{
+ char *n = NULL;
+ u8 boardrev = dd->ipath_boardrev;
+ int ret;
+
+ switch (boardrev) {
+ case 4: /* Ponderosa is one of the bringup boards */
+ n = "Ponderosa";
+ break;
+ case 5:
+ /*
+ * HT-460 original production board; two production levels, with
+ * different serial number ranges. See ipath_ht_early_init() for
+ * case where we enable IPATH_GPIO_INTR for later serial # range.
+ */
+ n = "InfiniPath_HT-460";
+ break;
+ case 6:
+ n = "OEM_Board_3";
+ break;
+ case 7:
+ /* HT-460 small form factor production board */
+ n = "InfiniPath_HT-465";
+ break;
+ case 8:
+ n = "LS/X-1";
+ break;
+ case 9: /* Comstock bringup test board */
+ n = "Comstock";
+ break;
+ case 10:
+ n = "OEM_Board_2";
+ break;
+ case 11:
+ n = "InfiniPath_HT-470";
+ break;
+ case 12:
+ n = "OEM_Board_4";
+ break;
+ default: /* don't know, just print the number */
+ ipath_dev_err(dd, "Don't yet know about board "
+ "with ID %u\n", boardrev);
+ snprintf(name, namelen, "Unknown_InfiniPath_HT-4xx_%u",
+ boardrev);
+ break;
+ }
+ if (n)
+ snprintf(name, namelen, "%s", n);
+
+ if (dd->ipath_majrev != 3 || (dd->ipath_minrev < 2 || dd->ipath_minrev > 3)) {
+ /*
+ * This version of the driver only supports the HT-400
+ * Rev 3.2
+ */
+ ipath_dev_err(dd,
+ "Unsupported HT-400 revision %u.%u!\n",
+ dd->ipath_majrev, dd->ipath_minrev);
+ ret = 1;
+ goto bail;
+ }
+ /*
+ * pkt/word counters are 32 bit, and therefore wrap fast enough
+ * that we snapshot them from a timer, and maintain 64 bit shadow
+ * copies
+ */
+ dd->ipath_flags |= IPATH_32BITCOUNTERS;
+ if (dd->ipath_htspeed != 800)
+ ipath_dev_err(dd,
+ "Incorrectly configured for HT @ %uMHz\n",
+ dd->ipath_htspeed);
+ if (dd->ipath_boardrev == 7 || dd->ipath_boardrev == 11 ||
+ dd->ipath_boardrev == 6)
+ dd->ipath_flags |= IPATH_GPIO_INTR;
+ else
+ dd->ipath_flags |= IPATH_POLL_RX_INTR;
+ if (dd->ipath_boardrev == 8) { /* LS/X-1 */
+ u64 val;
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+ if (val & INFINIPATH_EXTS_SERDESSEL) {
+ /*
+ * hardware disabled
+ *
+ * This means that the chip is hardware disabled,
+ * and will not be able to bring up the link,
+ * in any case. We special case this and abort
+ * early, to avoid later messages. We also set
+ * the DISABLED status bit
+ */
+ ipath_dbg("Unit %u is hardware-disabled\n",
+ dd->ipath_unit);
+ *dd->ipath_statusp |= IPATH_STATUS_DISABLED;
+ /* this value is handled differently */
+ ret = 2;
+ goto bail;
+ }
+ }
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static void ipath_check_htlink(struct ipath_devdata *dd)
+{
+ u8 linkerr, link_off, i;
+
+ for (i = 0; i < 2; i++) {
+ link_off = dd->ipath_ht_slave_off + i * 4 + 0xd;
+ if (pci_read_config_byte(dd->pcidev, link_off, &linkerr))
+ dev_info(&dd->pcidev->dev, "Couldn't read "
+ "linkerror%d of HT slave/primary block\n",
+ i);
+ else if (linkerr & 0xf0) {
+ ipath_cdbg(VERBOSE, "HT linkerr%d bits 0x%x set, "
+ "clearing\n", linkerr >> 4, i);
+ /*
+ * writing the linkerr bits that are set should
+ * clear them
+ */
+ if (pci_write_config_byte(dd->pcidev, link_off,
+ linkerr))
+ ipath_dbg("Failed write to clear HT "
+ "linkerror%d\n", i);
+ if (pci_read_config_byte(dd->pcidev, link_off,
+ &linkerr))
+ dev_info(&dd->pcidev->dev,
+ "Couldn't reread linkerror%d of "
+ "HT slave/primary block\n", i);
+ else if (linkerr & 0xf0)
+ dev_info(&dd->pcidev->dev,
+ "HT linkerror%d bits 0x%x "
+ "couldn't be cleared\n",
+ i, linkerr >> 4);
+ }
+ }
+}
+
+static int ipath_setup_ht_reset(struct ipath_devdata *dd)
+{
+ ipath_dbg("No reset possible for HT-400\n");
+ return 0;
+}
+
+#define HT_CAPABILITY_ID 0x08 /* HT capabilities not defined in kernel */
+#define HT_INTR_DISC_CONFIG 0x80 /* HT interrupt and discovery cap */
+#define HT_INTR_REG_INDEX 2 /* intconfig requires indirect accesses */
+
+/*
+ * Bits 13-15 of command==0 is slave/primary block. Clear any HT CRC
+ * errors. We only bother to do this at load time, because it's OK if
+ * it happened before we were loaded (first time after boot/reset),
+ * but any time after that, it's fatal anyway. Also need to not check
+ * for for upper byte errors if we are in 8 bit mode, so figure out
+ * our width. For now, at least, also complain if it's 8 bit.
+ */
+static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev,
+ int pos, u8 cap_type)
+{
+ u8 linkwidth = 0, linkerr, link_a_b_off, link_off;
+ u16 linkctrl = 0;
+ int i;
+
+ dd->ipath_ht_slave_off = pos;
+ /* command word, master_host bit */
+ /* master host || slave */
+ if ((cap_type >> 2) & 1)
+ link_a_b_off = 4;
+ else
+ link_a_b_off = 0;
+ ipath_cdbg(VERBOSE, "HT%u (Link %c) connected to processor\n",
+ link_a_b_off ? 1 : 0,
+ link_a_b_off ? 'B' : 'A');
+
+ link_a_b_off += pos;
+
+ /*
+ * check both link control registers; clear both HT CRC sets if
+ * necessary.
+ */
+ for (i = 0; i < 2; i++) {
+ link_off = pos + i * 4 + 0x4;
+ if (pci_read_config_word(pdev, link_off, &linkctrl))
+ ipath_dev_err(dd, "Couldn't read HT link control%d "
+ "register\n", i);
+ else if (linkctrl & (0xf << 8)) {
+ ipath_cdbg(VERBOSE, "Clear linkctrl%d CRC Error "
+ "bits %x\n", i, linkctrl & (0xf << 8));
+ /*
+ * now write them back to clear the error.
+ */
+ pci_write_config_byte(pdev, link_off,
+ linkctrl & (0xf << 8));
+ }
+ }
+
+ /*
+ * As with HT CRC bits, same for protocol errors that might occur
+ * during boot.
+ */
+ for (i = 0; i < 2; i++) {
+ link_off = pos + i * 4 + 0xd;
+ if (pci_read_config_byte(pdev, link_off, &linkerr))
+ dev_info(&pdev->dev, "Couldn't read linkerror%d "
+ "of HT slave/primary block\n", i);
+ else if (linkerr & 0xf0) {
+ ipath_cdbg(VERBOSE, "HT linkerr%d bits 0x%x set, "
+ "clearing\n", linkerr >> 4, i);
+ /*
+ * writing the linkerr bits that are set will clear
+ * them
+ */
+ if (pci_write_config_byte
+ (pdev, link_off, linkerr))
+ ipath_dbg("Failed write to clear HT "
+ "linkerror%d\n", i);
+ if (pci_read_config_byte(pdev, link_off, &linkerr))
+ dev_info(&pdev->dev, "Couldn't reread "
+ "linkerror%d of HT slave/primary "
+ "block\n", i);
+ else if (linkerr & 0xf0)
+ dev_info(&pdev->dev, "HT linkerror%d bits "
+ "0x%x couldn't be cleared\n",
+ i, linkerr >> 4);
+ }
+ }
+
+ /*
+ * this is just for our link to the host, not devices connected
+ * through tunnel.
+ */
+
+ if (pci_read_config_byte(pdev, link_a_b_off + 7, &linkwidth))
+ ipath_dev_err(dd, "Couldn't read HT link width "
+ "config register\n");
+ else {
+ u32 width;
+ switch (linkwidth & 7) {
+ case 5:
+ width = 4;
+ break;
+ case 4:
+ width = 2;
+ break;
+ case 3:
+ width = 32;
+ break;
+ case 1:
+ width = 16;
+ break;
+ case 0:
+ default: /* if wrong, assume 8 bit */
+ width = 8;
+ break;
+ }
+
+ dd->ipath_htwidth = width;
+
+ if (linkwidth != 0x11) {
+ ipath_dev_err(dd, "Not configured for 16 bit HT "
+ "(%x)\n", linkwidth);
+ if (!(linkwidth & 0xf)) {
+ ipath_dbg("Will ignore HT lane1 errors\n");
+ dd->ipath_flags |= IPATH_8BIT_IN_HT0;
+ }
+ }
+ }
+
+ /*
+ * this is just for our link to the host, not devices connected
+ * through tunnel.
+ */
+ if (pci_read_config_byte(pdev, link_a_b_off + 0xd, &linkwidth))
+ ipath_dev_err(dd, "Couldn't read HT link frequency "
+ "config register\n");
+ else {
+ u32 speed;
+ switch (linkwidth & 0xf) {
+ case 6:
+ speed = 1000;
+ break;
+ case 5:
+ speed = 800;
+ break;
+ case 4:
+ speed = 600;
+ break;
+ case 3:
+ speed = 500;
+ break;
+ case 2:
+ speed = 400;
+ break;
+ case 1:
+ speed = 300;
+ break;
+ default:
+ /*
+ * assume reserved and vendor-specific are 200...
+ */
+ case 0:
+ speed = 200;
+ break;
+ }
+ dd->ipath_htspeed = speed;
+ }
+}
+
+static int set_int_handler(struct ipath_devdata *dd, struct pci_dev *pdev,
+ int pos)
+{
+ u32 int_handler_addr_lower;
+ u32 int_handler_addr_upper;
+ u64 ihandler;
+ u32 intvec;
+
+ /* use indirection register to get the intr handler */
+ pci_write_config_byte(pdev, pos + HT_INTR_REG_INDEX, 0x10);
+ pci_read_config_dword(pdev, pos + 4, &int_handler_addr_lower);
+ pci_write_config_byte(pdev, pos + HT_INTR_REG_INDEX, 0x11);
+ pci_read_config_dword(pdev, pos + 4, &int_handler_addr_upper);
+
+ ihandler = (u64) int_handler_addr_lower |
+ ((u64) int_handler_addr_upper << 32);
+
+ /*
+ * kernels with CONFIG_PCI_MSI set the vector in the irq field of
+ * struct pci_device, so we use that to program the HT-400 internal
+ * interrupt register (not config space) with that value. The BIOS
+ * must still have done the basic MSI setup.
+ */
+ intvec = pdev->irq;
+ /*
+ * clear any vector bits there; normally not set but we'll overload
+ * this for some debug purposes (setting the HTC debug register
+ * value from software, rather than GPIOs), so it might be set on a
+ * driver reload.
+ */
+ ihandler &= ~0xff0000;
+ /* x86 vector goes in intrinfo[23:16] */
+ ihandler |= intvec << 16;
+ ipath_cdbg(VERBOSE, "ihandler lower %x, upper %x, intvec %x, "
+ "interruptconfig %llx\n", int_handler_addr_lower,
+ int_handler_addr_upper, intvec,
+ (unsigned long long) ihandler);
+
+ /* can't program yet, so save for interrupt setup */
+ dd->ipath_intconfig = ihandler;
+ /* keep going, so we find link control stuff also */
+
+ return ihandler != 0;
+}
+
+/**
+ * ipath_setup_ht_config - setup the interruptconfig register
+ * @dd: the infinipath device
+ * @pdev: the PCI device
+ *
+ * setup the interruptconfig register from the HT config info.
+ * Also clear CRC errors in HT linkcontrol, if necessary.
+ * This is done only for the real hardware. It is done before
+ * chip address space is initted, so can't touch infinipath registers
+ */
+static int ipath_setup_ht_config(struct ipath_devdata *dd,
+ struct pci_dev *pdev)
+{
+ int pos, ret = 0;
+ int ihandler = 0;
+
+ /*
+ * Read the capability info to find the interrupt info, and also
+ * handle clearing CRC errors in linkctrl register if necessary. We
+ * do this early, before we ever enable errors or hardware errors,
+ * mostly to avoid causing the chip to enter freeze mode.
+ */
+ pos = pci_find_capability(pdev, HT_CAPABILITY_ID);
+ if (!pos) {
+ ipath_dev_err(dd, "Couldn't find HyperTransport "
+ "capability; no interrupts\n");
+ ret = -ENODEV;
+ goto bail;
+ }
+ do {
+ u8 cap_type;
+
+ /* the HT capability type byte is 3 bytes after the
+ * capability byte.
+ */
+ if (pci_read_config_byte(pdev, pos + 3, &cap_type)) {
+ dev_info(&pdev->dev, "Couldn't read config "
+ "command @ %d\n", pos);
+ continue;
+ }
+ if (!(cap_type & 0xE0))
+ slave_or_pri_blk(dd, pdev, pos, cap_type);
+ else if (cap_type == HT_INTR_DISC_CONFIG)
+ ihandler = set_int_handler(dd, pdev, pos);
+ } while ((pos = pci_find_next_capability(pdev, pos,
+ HT_CAPABILITY_ID)));
+
+ if (!ihandler) {
+ ipath_dev_err(dd, "Couldn't find interrupt handler in "
+ "config space\n");
+ ret = -ENODEV;
+ }
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_setup_ht_cleanup - clean up any per-chip chip-specific stuff
+ * @dd: the infinipath device
+ *
+ * Called during driver unload.
+ * This is currently a nop for the HT-400, not for all chips
+ */
+static void ipath_setup_ht_cleanup(struct ipath_devdata *dd)
+{
+}
+
+/**
+ * ipath_setup_ht_setextled - set the state of the two external LEDs
+ * @dd: the infinipath device
+ * @lst: the L state
+ * @ltst: the LT state
+ *
+ * Set the state of the two external LEDs, to indicate physical and
+ * logical state of IB link. For this chip (at least with recommended
+ * board pinouts), LED1 is Green (physical state), and LED2 is Yellow
+ * (logical state)
+ *
+ * Note: We try to match the Mellanox HCA LED behavior as best
+ * we can. Green indicates physical link state is OK (something is
+ * plugged in, and we can train).
+ * Amber indicates the link is logically up (ACTIVE).
+ * Mellanox further blinks the amber LED to indicate data packet
+ * activity, but we have no hardware support for that, so it would
+ * require waking up every 10-20 msecs and checking the counters
+ * on the chip, and then turning the LED off if appropriate. That's
+ * visible overhead, so not something we will do.
+ *
+ */
+static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
+ u64 lst, u64 ltst)
+{
+ u64 extctl;
+
+ /* the diags use the LED to indicate diag info, so we leave
+ * the external LED alone when the diags are running */
+ if (ipath_diag_inuse)
+ return;
+
+ /*
+ * start by setting both LED control bits to off, then turn
+ * on the appropriate bit(s).
+ */
+ if (dd->ipath_boardrev == 8) { /* LS/X-1 uses different pins */
+ /*
+ * major difference is that INFINIPATH_EXTC_LEDGBLERR_OFF
+ * is inverted, because it is normally used to indicate
+ * a hardware fault at reset, if there were errors
+ */
+ extctl = (dd->ipath_extctrl & ~INFINIPATH_EXTC_LEDGBLOK_ON)
+ | INFINIPATH_EXTC_LEDGBLERR_OFF;
+ if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP)
+ extctl &= ~INFINIPATH_EXTC_LEDGBLERR_OFF;
+ if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
+ extctl |= INFINIPATH_EXTC_LEDGBLOK_ON;
+ }
+ else {
+ extctl = dd->ipath_extctrl &
+ ~(INFINIPATH_EXTC_LED1PRIPORT_ON |
+ INFINIPATH_EXTC_LED2PRIPORT_ON);
+ if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP)
+ extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
+ if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
+ extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON;
+ }
+ dd->ipath_extctrl = extctl;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
+}
+
+static void ipath_init_ht_variables(void)
+{
+ ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
+ ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
+ ipath_gpio_sda = IPATH_GPIO_SDA;
+ ipath_gpio_scl = IPATH_GPIO_SCL;
+
+ infinipath_i_bitsextant =
+ (INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
+ (INFINIPATH_I_RCVAVAIL_MASK <<
+ INFINIPATH_I_RCVAVAIL_SHIFT) |
+ INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT |
+ INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO;
+
+ infinipath_e_bitsextant =
+ INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC |
+ INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN |
+ INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN |
+ INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RUNEXPCHAR |
+ INFINIPATH_E_RUNSUPVL | INFINIPATH_E_REBP |
+ INFINIPATH_E_RIBFLOW | INFINIPATH_E_RBADVERSION |
+ INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
+ INFINIPATH_E_RBADTID | INFINIPATH_E_RHDRLEN |
+ INFINIPATH_E_RHDR | INFINIPATH_E_RIBLOSTLINK |
+ INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SMAXPKTLEN |
+ INFINIPATH_E_SUNDERRUN | INFINIPATH_E_SPKTLEN |
+ INFINIPATH_E_SDROPPEDSMPPKT | INFINIPATH_E_SDROPPEDDATAPKT |
+ INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM |
+ INFINIPATH_E_SUNSUPVL | INFINIPATH_E_IBSTATUSCHANGED |
+ INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET |
+ INFINIPATH_E_HARDWARE;
+
+ infinipath_hwe_bitsextant =
+ (INFINIPATH_HWE_HTCMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) |
+ (INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) |
+ (INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) |
+ INFINIPATH_HWE_HTCLNKABYTE0CRCERR |
+ INFINIPATH_HWE_HTCLNKABYTE1CRCERR |
+ INFINIPATH_HWE_HTCLNKBBYTE0CRCERR |
+ INFINIPATH_HWE_HTCLNKBBYTE1CRCERR |
+ INFINIPATH_HWE_HTCMISCERR4 |
+ INFINIPATH_HWE_HTCMISCERR5 | INFINIPATH_HWE_HTCMISCERR6 |
+ INFINIPATH_HWE_HTCMISCERR7 |
+ INFINIPATH_HWE_HTCBUSTREQPARITYERR |
+ INFINIPATH_HWE_HTCBUSTRESPPARITYERR |
+ INFINIPATH_HWE_HTCBUSIREQPARITYERR |
+ INFINIPATH_HWE_RXDSYNCMEMPARITYERR |
+ INFINIPATH_HWE_MEMBISTFAILED |
+ INFINIPATH_HWE_COREPLL_FBSLIP |
+ INFINIPATH_HWE_COREPLL_RFSLIP |
+ INFINIPATH_HWE_HTBPLL_FBSLIP |
+ INFINIPATH_HWE_HTBPLL_RFSLIP |
+ INFINIPATH_HWE_HTAPLL_FBSLIP |
+ INFINIPATH_HWE_HTAPLL_RFSLIP |
+ INFINIPATH_HWE_SERDESPLLFAILED |
+ INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |
+ INFINIPATH_HWE_IBCBUSFRSPCPARITYERR;
+
+ infinipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
+ infinipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+}
+
+/**
+ * ipath_ht_init_hwerrors - enable hardware errors
+ * @dd: the infinipath device
+ *
+ * now that we have finished initializing everything that might reasonably
+ * cause a hardware error, and cleared those errors bits as they occur,
+ * we can enable hardware errors in the mask (potentially enabling
+ * freeze mode), and enable hardware errors as errors (along with
+ * everything else) in errormask
+ */
+static void ipath_ht_init_hwerrors(struct ipath_devdata *dd)
+{
+ ipath_err_t val;
+ u64 extsval;
+
+ extsval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+
+ if (!(extsval & INFINIPATH_EXTS_MEMBIST_ENDTEST))
+ ipath_dev_err(dd, "MemBIST did not complete!\n");
+
+ ipath_check_htlink(dd);
+
+ /* barring bugs, all hwerrors become interrupts, which can */
+ val = -1LL;
+ /* don't look at crc lane1 if 8 bit */
+ if (dd->ipath_flags & IPATH_8BIT_IN_HT0)
+ val &= ~infinipath_hwe_htclnkabyte1crcerr;
+ /* don't look at crc lane1 if 8 bit */
+ if (dd->ipath_flags & IPATH_8BIT_IN_HT1)
+ val &= ~infinipath_hwe_htclnkbbyte1crcerr;
+
+ /*
+ * disable RXDSYNCMEMPARITY because external serdes is unused,
+ * and therefore the logic will never be used or initialized,
+ * and uninitialized state will normally result in this error
+ * being asserted. Similarly for the external serdess pll
+ * lock signal.
+ */
+ val &= ~(INFINIPATH_HWE_SERDESPLLFAILED |
+ INFINIPATH_HWE_RXDSYNCMEMPARITYERR);
+
+ /*
+ * Disable MISCERR4 because of an inversion in the HT core
+ * logic checking for errors that cause this bit to be set.
+ * The errata can also cause the protocol error bit to be set
+ * in the HT config space linkerror register(s).
+ */
+ val &= ~INFINIPATH_HWE_HTCMISCERR4;
+
+ /*
+ * PLL ignored because MDIO interface has a logic problem
+ * for reads, on Comstock and Ponderosa. BRINGUP
+ */
+ if (dd->ipath_boardrev == 4 || dd->ipath_boardrev == 9)
+ val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+ dd->ipath_hwerrmask = val;
+}
+
+/**
+ * ipath_ht_bringup_serdes - bring up the serdes
+ * @dd: the infinipath device
+ */
+static int ipath_ht_bringup_serdes(struct ipath_devdata *dd)
+{
+ u64 val, config1;
+ int ret = 0, change = 0;
+
+ ipath_dbg("Trying to bringup serdes\n");
+
+ if (ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus) &
+ INFINIPATH_HWE_SERDESPLLFAILED)
+ {
+ ipath_dbg("At start, serdes PLL failed bit set in "
+ "hwerrstatus, clearing and continuing\n");
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ INFINIPATH_HWE_SERDESPLLFAILED);
+ }
+
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+ config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1);
+
+ ipath_cdbg(VERBOSE, "Initial serdes status is config0=%llx "
+ "config1=%llx, sstatus=%llx xgxs %llx\n",
+ (unsigned long long) val, (unsigned long long) config1,
+ (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus),
+ (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+
+ /* force reset on */
+ val |= INFINIPATH_SERDC0_RESET_PLL
+ /* | INFINIPATH_SERDC0_RESET_MASK */
+ ;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+ udelay(15); /* need pll reset set at least for a bit */
+
+ if (val & INFINIPATH_SERDC0_RESET_PLL) {
+ u64 val2 = val &= ~INFINIPATH_SERDC0_RESET_PLL;
+ /* set lane resets, and tx idle, during pll reset */
+ val2 |= INFINIPATH_SERDC0_RESET_MASK |
+ INFINIPATH_SERDC0_TXIDLE;
+ ipath_cdbg(VERBOSE, "Clearing serdes PLL reset (writing "
+ "%llx)\n", (unsigned long long) val2);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0,
+ val2);
+ /*
+ * be sure chip saw it
+ */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ /*
+ * need pll reset clear at least 11 usec before lane
+ * resets cleared; give it a few more
+ */
+ udelay(15);
+ val = val2; /* for check below */
+ }
+
+ if (val & (INFINIPATH_SERDC0_RESET_PLL |
+ INFINIPATH_SERDC0_RESET_MASK |
+ INFINIPATH_SERDC0_TXIDLE)) {
+ val &= ~(INFINIPATH_SERDC0_RESET_PLL |
+ INFINIPATH_SERDC0_RESET_MASK |
+ INFINIPATH_SERDC0_TXIDLE);
+ /* clear them */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0,
+ val);
+ }
+
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+ if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
+ INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
+ val &= ~(INFINIPATH_XGXS_MDIOADDR_MASK <<
+ INFINIPATH_XGXS_MDIOADDR_SHIFT);
+ /*
+ * we use address 3
+ */
+ val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
+ change = 1;
+ }
+ if (val & INFINIPATH_XGXS_RESET) {
+ /* normally true after boot */
+ val &= ~INFINIPATH_XGXS_RESET;
+ change = 1;
+ }
+ if (change)
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
+
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+
+ /* clear current and de-emphasis bits */
+ config1 &= ~0x0ffffffff00ULL;
+ /* set current to 20ma */
+ config1 |= 0x00000000000ULL;
+ /* set de-emphasis to -5.68dB */
+ config1 |= 0x0cccc000000ULL;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig1, config1);
+
+ ipath_cdbg(VERBOSE, "After setup: serdes status is config0=%llx "
+ "config1=%llx, sstatus=%llx xgxs %llx\n",
+ (unsigned long long) val, (unsigned long long) config1,
+ (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus),
+ (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+
+ if (!ipath_waitfor_mdio_cmdready(dd)) {
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_mdio,
+ ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,
+ IPATH_MDIO_CTRL_XGXS_REG_8,
+ 0));
+ if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,
+ IPATH_MDIO_DATAVALID, &val))
+ ipath_dbg("Never got MDIO data for XGXS status "
+ "read\n");
+ else
+ ipath_cdbg(VERBOSE, "MDIO Read reg8, "
+ "'bank' 31 %x\n", (u32) val);
+ } else
+ ipath_dbg("Never got MDIO cmdready for XGXS status read\n");
+
+ return ret; /* for now, say we always succeeded */
+}
+
+/**
+ * ipath_ht_quiet_serdes - set serdes to txidle
+ * @dd: the infinipath device
+ * driver is being unloaded
+ */
+static void ipath_ht_quiet_serdes(struct ipath_devdata *dd)
+{
+ u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+
+ val |= INFINIPATH_SERDC0_TXIDLE;
+ ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n",
+ (unsigned long long) val);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+}
+
+static int ipath_ht_intconfig(struct ipath_devdata *dd)
+{
+ int ret;
+
+ if (!dd->ipath_intconfig) {
+ ipath_dev_err(dd, "No interrupts enabled, couldn't setup "
+ "interrupt address\n");
+ ret = 1;
+ goto bail;
+ }
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_interruptconfig,
+ dd->ipath_intconfig); /* interrupt address */
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_pe_put_tid - write a TID in chip
+ * @dd: the infinipath device
+ * @tidptr: pointer to the expected TID (in chip) to udpate
+ * @tidtype: 0 for eager, 1 for expected
+ * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
+ *
+ * This exists as a separate routine to allow for special locking etc.
+ * It's used for both the full cleanup on exit, as well as the normal
+ * setup and teardown.
+ */
+static void ipath_ht_put_tid(struct ipath_devdata *dd,
+ u64 __iomem *tidptr, u32 type,
+ unsigned long pa)
+{
+ if (pa != dd->ipath_tidinvalid) {
+ if (unlikely((pa & ~INFINIPATH_RT_ADDR_MASK))) {
+ dev_info(&dd->pcidev->dev,
+ "physaddr %lx has more than "
+ "40 bits, using only 40!!!\n", pa);
+ pa &= INFINIPATH_RT_ADDR_MASK;
+ }
+ if (type == 0)
+ pa |= dd->ipath_tidtemplate;
+ else {
+ /* in words (fixed, full page). */
+ u64 lenvalid = PAGE_SIZE >> 2;
+ lenvalid <<= INFINIPATH_RT_BUFSIZE_SHIFT;
+ pa |= lenvalid | INFINIPATH_RT_VALID;
+ }
+ }
+ if (dd->ipath_kregbase)
+ writeq(pa, tidptr);
+}
+
+/**
+ * ipath_ht_clear_tid - clear all TID entries for a port, expected and eager
+ * @dd: the infinipath device
+ * @port: the port
+ *
+ * Used from ipath_close(), and at chip initialization.
+ */
+static void ipath_ht_clear_tids(struct ipath_devdata *dd, unsigned port)
+{
+ u64 __iomem *tidbase;
+ int i;
+
+ if (!dd->ipath_kregbase)
+ return;
+
+ ipath_cdbg(VERBOSE, "Invalidate TIDs for port %u\n", port);
+
+ /*
+ * need to invalidate all of the expected TID entries for this
+ * port, so we don't have valid entries that might somehow get
+ * used (early in next use of this port, or through some bug)
+ */
+ tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
+ dd->ipath_rcvtidbase +
+ port * dd->ipath_rcvtidcnt *
+ sizeof(*tidbase));
+ for (i = 0; i < dd->ipath_rcvtidcnt; i++)
+ ipath_ht_put_tid(dd, &tidbase[i], 1, dd->ipath_tidinvalid);
+
+ tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
+ dd->ipath_rcvegrbase +
+ port * dd->ipath_rcvegrcnt *
+ sizeof(*tidbase));
+
+ for (i = 0; i < dd->ipath_rcvegrcnt; i++)
+ ipath_ht_put_tid(dd, &tidbase[i], 0, dd->ipath_tidinvalid);
+}
+
+/**
+ * ipath_ht_tidtemplate - setup constants for TID updates
+ * @dd: the infinipath device
+ *
+ * We setup stuff that we use a lot, to avoid calculating each time
+ */
+static void ipath_ht_tidtemplate(struct ipath_devdata *dd)
+{
+ dd->ipath_tidtemplate = dd->ipath_ibmaxlen >> 2;
+ dd->ipath_tidtemplate <<= INFINIPATH_RT_BUFSIZE_SHIFT;
+ dd->ipath_tidtemplate |= INFINIPATH_RT_VALID;
+
+ /*
+ * work around chip errata bug 7358, by marking invalid tids
+ * as having max length
+ */
+ dd->ipath_tidinvalid = (-1LL & INFINIPATH_RT_BUFSIZE_MASK) <<
+ INFINIPATH_RT_BUFSIZE_SHIFT;
+}
+
+static int ipath_ht_early_init(struct ipath_devdata *dd)
+{
+ u32 __iomem *piobuf;
+ u32 pioincr, val32, egrsize;
+ int i;
+
+ /*
+ * one cache line; long IB headers will spill over into received
+ * buffer
+ */
+ dd->ipath_rcvhdrentsize = 16;
+ dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
+
+ /*
+ * For HT-400, we allocate a somewhat overly large eager buffer,
+ * such that we can guarantee that we can receive the largest
+ * packet that we can send out. To truly support a 4KB MTU,
+ * we need to bump this to a large value. To date, other than
+ * testing, we have never encountered an HCA that can really
+ * send 4KB MTU packets, so we do not handle that (we'll get
+ * errors interrupts if we ever see one).
+ */
+ dd->ipath_rcvegrbufsize = dd->ipath_piosize2k;
+ egrsize = dd->ipath_rcvegrbufsize;
+
+ /*
+ * the min() check here is currently a nop, but it may not
+ * always be, depending on just how we do ipath_rcvegrbufsize
+ */
+ dd->ipath_ibmaxlen = min(dd->ipath_piosize2k,
+ dd->ipath_rcvegrbufsize);
+ dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen;
+ ipath_ht_tidtemplate(dd);
+
+ /*
+ * zero all the TID entries at startup. We do this for sanity,
+ * in case of a previous driver crash of some kind, and also
+ * because the chip powers up with these memories in an unknown
+ * state. Use portcnt, not cfgports, since this is for the
+ * full chip, not for current (possibly different) configuration
+ * value.
+ * Chip Errata bug 6447
+ */
+ for (val32 = 0; val32 < dd->ipath_portcnt; val32++)
+ ipath_ht_clear_tids(dd, val32);
+
+ /*
+ * write the pbc of each buffer, to be sure it's initialized, then
+ * cancel all the buffers, and also abort any packets that might
+ * have been in flight for some reason (the latter is for driver
+ * unload/reload, but isn't a bad idea at first init). PIO send
+ * isn't enabled at this point, so there is no danger of sending
+ * these out on the wire.
+ * Chip Errata bug 6610
+ */
+ piobuf = (u32 __iomem *) (((char __iomem *)(dd->ipath_kregbase)) +
+ dd->ipath_piobufbase);
+ pioincr = dd->ipath_palign / sizeof(*piobuf);
+ for (i = 0; i < dd->ipath_piobcnt2k; i++) {
+ /*
+ * reasonable word count, just to init pbc
+ */
+ writel(16, piobuf);
+ piobuf += pioincr;
+ }
+ /*
+ * self-clearing
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ INFINIPATH_S_ABORT);
+
+ ipath_get_eeprom_info(dd);
+ if(dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' &&
+ dd->ipath_serial[1] == '2' && dd->ipath_serial[2] == '8') {
+ /*
+ * Later production HT-460 has same changes as HT-465, so
+ * can use GPIO interrupts. They have serial #'s starting
+ * with 128, rather than 112.
+ */
+ dd->ipath_flags |= IPATH_GPIO_INTR;
+ dd->ipath_flags &= ~IPATH_POLL_RX_INTR;
+ }
+ return 0;
+}
+
+/**
+ * ipath_init_ht_get_base_info - set chip-specific flags for user code
+ * @dd: the infinipath device
+ * @kbase: ipath_base_info pointer
+ *
+ * We set the PCIE flag because the lower bandwidth on PCIe vs
+ * HyperTransport can affect some user packet algorithims.
+ */
+static int ipath_ht_get_base_info(struct ipath_portdata *pd, void *kbase)
+{
+ struct ipath_base_info *kinfo = kbase;
+
+ kinfo->spi_runtime_flags |= IPATH_RUNTIME_HT |
+ IPATH_RUNTIME_RCVHDR_COPY;
+
+ return 0;
+}
+
+/**
+ * ipath_init_ht400_funcs - set up the chip-specific function pointers
+ * @dd: the infinipath device
+ *
+ * This is global, and is called directly at init to set up the
+ * chip-specific function pointers for later use.
+ */
+void ipath_init_ht400_funcs(struct ipath_devdata *dd)
+{
+ dd->ipath_f_intrsetup = ipath_ht_intconfig;
+ dd->ipath_f_bus = ipath_setup_ht_config;
+ dd->ipath_f_reset = ipath_setup_ht_reset;
+ dd->ipath_f_get_boardname = ipath_ht_boardname;
+ dd->ipath_f_init_hwerrors = ipath_ht_init_hwerrors;
+ dd->ipath_f_init_hwerrors = ipath_ht_init_hwerrors;
+ dd->ipath_f_early_init = ipath_ht_early_init;
+ dd->ipath_f_handle_hwerrors = ipath_ht_handle_hwerrors;
+ dd->ipath_f_quiet_serdes = ipath_ht_quiet_serdes;
+ dd->ipath_f_bringup_serdes = ipath_ht_bringup_serdes;
+ dd->ipath_f_clear_tids = ipath_ht_clear_tids;
+ dd->ipath_f_put_tid = ipath_ht_put_tid;
+ dd->ipath_f_cleanup = ipath_setup_ht_cleanup;
+ dd->ipath_f_setextled = ipath_setup_ht_setextled;
+ dd->ipath_f_get_base_info = ipath_ht_get_base_info;
+
+ /*
+ * initialize chip-specific variables
+ */
+ dd->ipath_f_tidtemplate = ipath_ht_tidtemplate;
+
+ /*
+ * setup the register offsets, since they are different for each
+ * chip
+ */
+ dd->ipath_kregs = &ipath_ht_kregs;
+ dd->ipath_cregs = &ipath_ht_cregs;
+
+ /*
+ * do very early init that is needed before ipath_f_bus is
+ * called
+ */
+ ipath_init_ht_variables();
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
new file mode 100644
index 00000000000..dc83250d26a
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -0,0 +1,958 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+
+/*
+ * min buffers we want to have per port, after driver
+ */
+#define IPATH_MIN_USER_PORT_BUFCNT 8
+
+/*
+ * Number of ports we are configured to use (to allow for more pio
+ * buffers per port, etc.) Zero means use chip value.
+ */
+static ushort ipath_cfgports;
+
+module_param_named(cfgports, ipath_cfgports, ushort, S_IRUGO);
+MODULE_PARM_DESC(cfgports, "Set max number of ports to use");
+
+/*
+ * Number of buffers reserved for driver (layered drivers and SMA
+ * send). Reserved at end of buffer list. Initialized based on
+ * number of PIO buffers if not set via module interface.
+ * The problem with this is that it's global, but we'll use different
+ * numbers for different chip types. So the default value is not
+ * very useful. I've redefined it for the 1.3 release so that it's
+ * zero unless set by the user to something else, in which case we
+ * try to respect it.
+ */
+static ushort ipath_kpiobufs;
+
+static int ipath_set_kpiobufs(const char *val, struct kernel_param *kp);
+
+module_param_call(kpiobufs, ipath_set_kpiobufs, param_get_ushort,
+ &ipath_kpiobufs, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(kpiobufs, "Set number of PIO buffers for driver");
+
+/**
+ * create_port0_egr - allocate the eager TID buffers
+ * @dd: the infinipath device
+ *
+ * This code is now quite different for user and kernel, because
+ * the kernel uses skb's, for the accelerated network performance.
+ * This is the kernel (port0) version.
+ *
+ * Allocate the eager TID buffers and program them into infinipath.
+ * We use the network layer alloc_skb() allocator to allocate the
+ * memory, and either use the buffers as is for things like SMA
+ * packets, or pass the buffers up to the ipath layered driver and
+ * thence the network layer, replacing them as we do so (see
+ * ipath_rcv_layer()).
+ */
+static int create_port0_egr(struct ipath_devdata *dd)
+{
+ unsigned e, egrcnt;
+ struct sk_buff **skbs;
+ int ret;
+
+ egrcnt = dd->ipath_rcvegrcnt;
+
+ skbs = vmalloc(sizeof(*dd->ipath_port0_skbs) * egrcnt);
+ if (skbs == NULL) {
+ ipath_dev_err(dd, "allocation error for eager TID "
+ "skb array\n");
+ ret = -ENOMEM;
+ goto bail;
+ }
+ for (e = 0; e < egrcnt; e++) {
+ /*
+ * This is a bit tricky in that we allocate extra
+ * space for 2 bytes of the 14 byte ethernet header.
+ * These two bytes are passed in the ipath header so
+ * the rest of the data is word aligned. We allocate
+ * 4 bytes so that the data buffer stays word aligned.
+ * See ipath_kreceive() for more details.
+ */
+ skbs[e] = ipath_alloc_skb(dd, GFP_KERNEL);
+ if (!skbs[e]) {
+ ipath_dev_err(dd, "SKB allocation error for "
+ "eager TID %u\n", e);
+ while (e != 0)
+ dev_kfree_skb(skbs[--e]);
+ ret = -ENOMEM;
+ goto bail;
+ }
+ }
+ /*
+ * After loop above, so we can test non-NULL to see if ready
+ * to use at receive, etc.
+ */
+ dd->ipath_port0_skbs = skbs;
+
+ for (e = 0; e < egrcnt; e++) {
+ unsigned long phys =
+ virt_to_phys(dd->ipath_port0_skbs[e]->data);
+ dd->ipath_f_put_tid(dd, e + (u64 __iomem *)
+ ((char __iomem *) dd->ipath_kregbase +
+ dd->ipath_rcvegrbase), 0, phys);
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static int bringup_link(struct ipath_devdata *dd)
+{
+ u64 val, ibc;
+ int ret = 0;
+
+ /* hold IBC in reset */
+ dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+ dd->ipath_control);
+
+ /*
+ * Note that prior to try 14 or 15 of IB, the credit scaling
+ * wasn't working, because it was swapped for writes with the
+ * 1 bit default linkstate field
+ */
+
+ /* ignore pbc and align word */
+ val = dd->ipath_piosize2k - 2 * sizeof(u32);
+ /*
+ * for ICRC, which we only send in diag test pkt mode, and we
+ * don't need to worry about that for mtu
+ */
+ val += 1;
+ /*
+ * Set the IBC maxpktlength to the size of our pio buffers the
+ * maxpktlength is in words. This is *not* the IB data MTU.
+ */
+ ibc = (val / sizeof(u32)) << INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
+ /* in KB */
+ ibc |= 0x5ULL << INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT;
+ /*
+ * How often flowctrl sent. More or less in usecs; balance against
+ * watermark value, so that in theory senders always get a flow
+ * control update in time to not let the IB link go idle.
+ */
+ ibc |= 0x3ULL << INFINIPATH_IBCC_FLOWCTRLPERIOD_SHIFT;
+ /* max error tolerance */
+ ibc |= 0xfULL << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT;
+ /* use "real" buffer space for */
+ ibc |= 4ULL << INFINIPATH_IBCC_CREDITSCALE_SHIFT;
+ /* IB credit flow control. */
+ ibc |= 0xfULL << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT;
+ /* initially come up waiting for TS1, without sending anything. */
+ dd->ipath_ibcctrl = ibc;
+ /*
+ * Want to start out with both LINKCMD and LINKINITCMD in NOP
+ * (0 and 0). Don't put linkinitcmd in ipath_ibcctrl, want that
+ * to stay a NOP
+ */
+ ibc |= INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+ INFINIPATH_IBCC_LINKINITCMD_SHIFT;
+ ipath_cdbg(VERBOSE, "Writing 0x%llx to ibcctrl\n",
+ (unsigned long long) ibc);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, ibc);
+
+ // be sure chip saw it
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+
+ ret = dd->ipath_f_bringup_serdes(dd);
+
+ if (ret)
+ dev_info(&dd->pcidev->dev, "Could not initialize SerDes, "
+ "not usable\n");
+ else {
+ /* enable IBC */
+ dd->ipath_control |= INFINIPATH_C_LINKENABLE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+ dd->ipath_control);
+ }
+
+ return ret;
+}
+
+static int init_chip_first(struct ipath_devdata *dd,
+ struct ipath_portdata **pdp)
+{
+ struct ipath_portdata *pd = NULL;
+ int ret = 0;
+ u64 val;
+
+ /*
+ * skip cfgports stuff because we are not allocating memory,
+ * and we don't want problems if the portcnt changed due to
+ * cfgports. We do still check and report a difference, if
+ * not same (should be impossible).
+ */
+ dd->ipath_portcnt =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
+ if (!ipath_cfgports)
+ dd->ipath_cfgports = dd->ipath_portcnt;
+ else if (ipath_cfgports <= dd->ipath_portcnt) {
+ dd->ipath_cfgports = ipath_cfgports;
+ ipath_dbg("Configured to use %u ports out of %u in chip\n",
+ dd->ipath_cfgports, dd->ipath_portcnt);
+ } else {
+ dd->ipath_cfgports = dd->ipath_portcnt;
+ ipath_dbg("Tried to configured to use %u ports; chip "
+ "only supports %u\n", ipath_cfgports,
+ dd->ipath_portcnt);
+ }
+ dd->ipath_pd = kzalloc(sizeof(*dd->ipath_pd) * dd->ipath_cfgports,
+ GFP_KERNEL);
+
+ if (!dd->ipath_pd) {
+ ipath_dev_err(dd, "Unable to allocate portdata array, "
+ "failing\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ dd->ipath_lastegrheads = kzalloc(sizeof(*dd->ipath_lastegrheads)
+ * dd->ipath_cfgports,
+ GFP_KERNEL);
+ dd->ipath_lastrcvhdrqtails =
+ kzalloc(sizeof(*dd->ipath_lastrcvhdrqtails)
+ * dd->ipath_cfgports, GFP_KERNEL);
+
+ if (!dd->ipath_lastegrheads || !dd->ipath_lastrcvhdrqtails) {
+ ipath_dev_err(dd, "Unable to allocate head arrays, "
+ "failing\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ dd->ipath_pd[0] = kzalloc(sizeof(*pd), GFP_KERNEL);
+
+ if (!dd->ipath_pd[0]) {
+ ipath_dev_err(dd, "Unable to allocate portdata for port "
+ "0, failing\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+ pd = dd->ipath_pd[0];
+ pd->port_dd = dd;
+ pd->port_port = 0;
+ pd->port_cnt = 1;
+ /* The port 0 pkey table is used by the layer interface. */
+ pd->port_pkeys[0] = IPS_DEFAULT_P_KEY;
+ dd->ipath_rcvtidcnt =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt);
+ dd->ipath_rcvtidbase =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidbase);
+ dd->ipath_rcvegrcnt =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt);
+ dd->ipath_rcvegrbase =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrbase);
+ dd->ipath_palign =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_pagealign);
+ dd->ipath_piobufbase =
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufbase);
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiosize);
+ dd->ipath_piosize2k = val & ~0U;
+ dd->ipath_piosize4k = val >> 32;
+ dd->ipath_ibmtu = 4096; /* default to largest legal MTU */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufcnt);
+ dd->ipath_piobcnt2k = val & ~0U;
+ dd->ipath_piobcnt4k = val >> 32;
+ dd->ipath_pio2kbase =
+ (u32 __iomem *) (((char __iomem *) dd->ipath_kregbase) +
+ (dd->ipath_piobufbase & 0xffffffff));
+ if (dd->ipath_piobcnt4k) {
+ dd->ipath_pio4kbase = (u32 __iomem *)
+ (((char __iomem *) dd->ipath_kregbase) +
+ (dd->ipath_piobufbase >> 32));
+ /*
+ * 4K buffers take 2 pages; we use roundup just to be
+ * paranoid; we calculate it once here, rather than on
+ * ever buf allocate
+ */
+ dd->ipath_4kalign = ALIGN(dd->ipath_piosize4k,
+ dd->ipath_palign);
+ ipath_dbg("%u 2k(%x) piobufs @ %p, %u 4k(%x) @ %p "
+ "(%x aligned)\n",
+ dd->ipath_piobcnt2k, dd->ipath_piosize2k,
+ dd->ipath_pio2kbase, dd->ipath_piobcnt4k,
+ dd->ipath_piosize4k, dd->ipath_pio4kbase,
+ dd->ipath_4kalign);
+ }
+ else ipath_dbg("%u 2k piobufs @ %p\n",
+ dd->ipath_piobcnt2k, dd->ipath_pio2kbase);
+
+ spin_lock_init(&dd->ipath_tid_lock);
+
+done:
+ *pdp = pd;
+ return ret;
+}
+
+/**
+ * init_chip_reset - re-initialize after a reset, or enable
+ * @dd: the infinipath device
+ * @pdp: output for port data
+ *
+ * sanity check at least some of the values after reset, and
+ * ensure no receive or transmit (explictly, in case reset
+ * failed
+ */
+static int init_chip_reset(struct ipath_devdata *dd,
+ struct ipath_portdata **pdp)
+{
+ struct ipath_portdata *pd;
+ u32 rtmp;
+
+ *pdp = pd = dd->ipath_pd[0];
+ /* ensure chip does no sends or receives while we re-initialize */
+ dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, 0);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0);
+
+ rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
+ if (dd->ipath_portcnt != rtmp)
+ dev_info(&dd->pcidev->dev, "portcnt was %u before "
+ "reset, now %u, using original\n",
+ dd->ipath_portcnt, rtmp);
+ rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt);
+ if (rtmp != dd->ipath_rcvtidcnt)
+ dev_info(&dd->pcidev->dev, "tidcnt was %u before "
+ "reset, now %u, using original\n",
+ dd->ipath_rcvtidcnt, rtmp);
+ rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidbase);
+ if (rtmp != dd->ipath_rcvtidbase)
+ dev_info(&dd->pcidev->dev, "tidbase was %u before "
+ "reset, now %u, using original\n",
+ dd->ipath_rcvtidbase, rtmp);
+ rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt);
+ if (rtmp != dd->ipath_rcvegrcnt)
+ dev_info(&dd->pcidev->dev, "egrcnt was %u before "
+ "reset, now %u, using original\n",
+ dd->ipath_rcvegrcnt, rtmp);
+ rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrbase);
+ if (rtmp != dd->ipath_rcvegrbase)
+ dev_info(&dd->pcidev->dev, "egrbase was %u before "
+ "reset, now %u, using original\n",
+ dd->ipath_rcvegrbase, rtmp);
+
+ return 0;
+}
+
+static int init_pioavailregs(struct ipath_devdata *dd)
+{
+ int ret;
+
+ dd->ipath_pioavailregs_dma = dma_alloc_coherent(
+ &dd->pcidev->dev, PAGE_SIZE, &dd->ipath_pioavailregs_phys,
+ GFP_KERNEL);
+ if (!dd->ipath_pioavailregs_dma) {
+ ipath_dev_err(dd, "failed to allocate PIOavail reg area "
+ "in memory\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ /*
+ * we really want L2 cache aligned, but for current CPUs of
+ * interest, they are the same.
+ */
+ dd->ipath_statusp = (u64 *)
+ ((char *)dd->ipath_pioavailregs_dma +
+ ((2 * L1_CACHE_BYTES +
+ dd->ipath_pioavregs * sizeof(u64)) & ~L1_CACHE_BYTES));
+ /* copy the current value now that it's really allocated */
+ *dd->ipath_statusp = dd->_ipath_status;
+ /*
+ * setup buffer to hold freeze msg, accessible to apps,
+ * following statusp
+ */
+ dd->ipath_freezemsg = (char *)&dd->ipath_statusp[1];
+ /* and its length */
+ dd->ipath_freezelen = L1_CACHE_BYTES - sizeof(dd->ipath_statusp[0]);
+
+ if (dd->ipath_unit * 64 > (IPATH_PORT0_RCVHDRTAIL_SIZE - 64)) {
+ ipath_dev_err(dd, "unit %u too large for port 0 "
+ "rcvhdrtail buffer size\n", dd->ipath_unit);
+ ret = -ENODEV;
+ }
+ else
+ ret = 0;
+
+ /* so we can get current tail in ipath_kreceive(), per chip */
+ dd->ipath_hdrqtailptr = &ipath_port0_rcvhdrtail[
+ dd->ipath_unit * (64 / sizeof(*ipath_port0_rcvhdrtail))];
+done:
+ return ret;
+}
+
+/**
+ * init_shadow_tids - allocate the shadow TID array
+ * @dd: the infinipath device
+ *
+ * allocate the shadow TID array, so we can ipath_munlock previous
+ * entries. It may make more sense to move the pageshadow to the
+ * port data structure, so we only allocate memory for ports actually
+ * in use, since we at 8k per port, now.
+ */
+static void init_shadow_tids(struct ipath_devdata *dd)
+{
+ dd->ipath_pageshadow = (struct page **)
+ vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt *
+ sizeof(struct page *));
+ if (!dd->ipath_pageshadow)
+ ipath_dev_err(dd, "failed to allocate shadow page * "
+ "array, no expected sends!\n");
+ else
+ memset(dd->ipath_pageshadow, 0,
+ dd->ipath_cfgports * dd->ipath_rcvtidcnt *
+ sizeof(struct page *));
+}
+
+static void enable_chip(struct ipath_devdata *dd,
+ struct ipath_portdata *pd, int reinit)
+{
+ u32 val;
+ int i;
+
+ if (!reinit) {
+ init_waitqueue_head(&ipath_sma_state_wait);
+ }
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+ /* Enable PIO send, and update of PIOavail regs to memory. */
+ dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE |
+ INFINIPATH_S_PIOBUFAVAILUPD;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+
+ /*
+ * enable port 0 receive, and receive interrupt. other ports
+ * done as user opens and inits them.
+ */
+ dd->ipath_rcvctrl = INFINIPATH_R_TAILUPD |
+ (1ULL << INFINIPATH_R_PORTENABLE_SHIFT) |
+ (1ULL << INFINIPATH_R_INTRAVAIL_SHIFT);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+ /*
+ * now ready for use. this should be cleared whenever we
+ * detect a reset, or initiate one.
+ */
+ dd->ipath_flags |= IPATH_INITTED;
+
+ /*
+ * init our shadow copies of head from tail values, and write
+ * head values to match.
+ */
+ val = ipath_read_ureg32(dd, ur_rcvegrindextail, 0);
+ (void)ipath_write_ureg(dd, ur_rcvegrindexhead, val, 0);
+ dd->ipath_port0head = ipath_read_ureg32(dd, ur_rcvhdrtail, 0);
+
+ /* Initialize so we interrupt on next packet received */
+ (void)ipath_write_ureg(dd, ur_rcvhdrhead,
+ dd->ipath_rhdrhead_intr_off |
+ dd->ipath_port0head, 0);
+
+ /*
+ * by now pioavail updates to memory should have occurred, so
+ * copy them into our working/shadow registers; this is in
+ * case something went wrong with abort, but mostly to get the
+ * initial values of the generation bit correct.
+ */
+ for (i = 0; i < dd->ipath_pioavregs; i++) {
+ __le64 val;
+
+ /*
+ * Chip Errata bug 6641; even and odd qwords>3 are swapped.
+ */
+ if (i > 3) {
+ if (i & 1)
+ val = dd->ipath_pioavailregs_dma[i - 1];
+ else
+ val = dd->ipath_pioavailregs_dma[i + 1];
+ }
+ else
+ val = dd->ipath_pioavailregs_dma[i];
+ dd->ipath_pioavailshadow[i] = le64_to_cpu(val);
+ }
+ /* can get counters, stats, etc. */
+ dd->ipath_flags |= IPATH_PRESENT;
+}
+
+static int init_housekeeping(struct ipath_devdata *dd,
+ struct ipath_portdata **pdp, int reinit)
+{
+ char boardn[32];
+ int ret = 0;
+
+ /*
+ * have to clear shadow copies of registers at init that are
+ * not otherwise set here, or all kinds of bizarre things
+ * happen with driver on chip reset
+ */
+ dd->ipath_rcvhdrsize = 0;
+
+ /*
+ * Don't clear ipath_flags as 8bit mode was set before
+ * entering this func. However, we do set the linkstate to
+ * unknown, so we can watch for a transition.
+ * PRESENT is set because we want register reads to work,
+ * and the kernel infrastructure saw it in config space;
+ * We clear it if we have failures.
+ */
+ dd->ipath_flags |= IPATH_LINKUNK | IPATH_PRESENT;
+ dd->ipath_flags &= ~(IPATH_LINKACTIVE | IPATH_LINKARMED |
+ IPATH_LINKDOWN | IPATH_LINKINIT);
+
+ ipath_cdbg(VERBOSE, "Try to read spc chip revision\n");
+ dd->ipath_revision =
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision);
+
+ /*
+ * set up fundamental info we need to use the chip; we assume
+ * if the revision reg and these regs are OK, we don't need to
+ * special case the rest
+ */
+ dd->ipath_sregbase =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_sendregbase);
+ dd->ipath_cregbase =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_counterregbase);
+ dd->ipath_uregbase =
+ ipath_read_kreg32(dd, dd->ipath_kregs->kr_userregbase);
+ ipath_cdbg(VERBOSE, "ipath_kregbase %p, sendbase %x usrbase %x, "
+ "cntrbase %x\n", dd->ipath_kregbase, dd->ipath_sregbase,
+ dd->ipath_uregbase, dd->ipath_cregbase);
+ if ((dd->ipath_revision & 0xffffffff) == 0xffffffff
+ || (dd->ipath_sregbase & 0xffffffff) == 0xffffffff
+ || (dd->ipath_cregbase & 0xffffffff) == 0xffffffff
+ || (dd->ipath_uregbase & 0xffffffff) == 0xffffffff) {
+ ipath_dev_err(dd, "Register read failures from chip, "
+ "giving up initialization\n");
+ dd->ipath_flags &= ~IPATH_PRESENT;
+ ret = -ENODEV;
+ goto done;
+ }
+
+ /* clear the initial reset flag, in case first driver load */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
+ INFINIPATH_E_RESET);
+
+ if (reinit)
+ ret = init_chip_reset(dd, pdp);
+ else
+ ret = init_chip_first(dd, pdp);
+
+ if (ret)
+ goto done;
+
+ ipath_cdbg(VERBOSE, "Revision %llx (PCI %x), %u ports, %u tids, "
+ "%u egrtids\n", (unsigned long long) dd->ipath_revision,
+ dd->ipath_pcirev, dd->ipath_portcnt, dd->ipath_rcvtidcnt,
+ dd->ipath_rcvegrcnt);
+
+ if (((dd->ipath_revision >> INFINIPATH_R_SOFTWARE_SHIFT) &
+ INFINIPATH_R_SOFTWARE_MASK) != IPATH_CHIP_SWVERSION) {
+ ipath_dev_err(dd, "Driver only handles version %d, "
+ "chip swversion is %d (%llx), failng\n",
+ IPATH_CHIP_SWVERSION,
+ (int)(dd->ipath_revision >>
+ INFINIPATH_R_SOFTWARE_SHIFT) &
+ INFINIPATH_R_SOFTWARE_MASK,
+ (unsigned long long) dd->ipath_revision);
+ ret = -ENOSYS;
+ goto done;
+ }
+ dd->ipath_majrev = (u8) ((dd->ipath_revision >>
+ INFINIPATH_R_CHIPREVMAJOR_SHIFT) &
+ INFINIPATH_R_CHIPREVMAJOR_MASK);
+ dd->ipath_minrev = (u8) ((dd->ipath_revision >>
+ INFINIPATH_R_CHIPREVMINOR_SHIFT) &
+ INFINIPATH_R_CHIPREVMINOR_MASK);
+ dd->ipath_boardrev = (u8) ((dd->ipath_revision >>
+ INFINIPATH_R_BOARDID_SHIFT) &
+ INFINIPATH_R_BOARDID_MASK);
+
+ ret = dd->ipath_f_get_boardname(dd, boardn, sizeof boardn);
+
+ snprintf(dd->ipath_boardversion, sizeof(dd->ipath_boardversion),
+ "Driver %u.%u, %s, InfiniPath%u %u.%u, PCI %u, "
+ "SW Compat %u\n",
+ IPATH_CHIP_VERS_MAJ, IPATH_CHIP_VERS_MIN, boardn,
+ (unsigned)(dd->ipath_revision >> INFINIPATH_R_ARCH_SHIFT) &
+ INFINIPATH_R_ARCH_MASK,
+ dd->ipath_majrev, dd->ipath_minrev, dd->ipath_pcirev,
+ (unsigned)(dd->ipath_revision >>
+ INFINIPATH_R_SOFTWARE_SHIFT) &
+ INFINIPATH_R_SOFTWARE_MASK);
+
+ ipath_dbg("%s", dd->ipath_boardversion);
+
+done:
+ return ret;
+}
+
+
+/**
+ * ipath_init_chip - do the actual initialization sequence on the chip
+ * @dd: the infinipath device
+ * @reinit: reinitializing, so don't allocate new memory
+ *
+ * Do the actual initialization sequence on the chip. This is done
+ * both from the init routine called from the PCI infrastructure, and
+ * when we reset the chip, or detect that it was reset internally,
+ * or it's administratively re-enabled.
+ *
+ * Memory allocation here and in called routines is only done in
+ * the first case (reinit == 0). We have to be careful, because even
+ * without memory allocation, we need to re-write all the chip registers
+ * TIDs, etc. after the reset or enable has completed.
+ */
+int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+{
+ int ret = 0, i;
+ u32 val32, kpiobufs;
+ u64 val, atmp;
+ struct ipath_portdata *pd = NULL; /* keep gcc4 happy */
+
+ ret = init_housekeeping(dd, &pd, reinit);
+ if (ret)
+ goto done;
+
+ /*
+ * we ignore most issues after reporting them, but have to specially
+ * handle hardware-disabled chips.
+ */
+ if (ret == 2) {
+ /* unique error, known to ipath_init_one */
+ ret = -EPERM;
+ goto done;
+ }
+
+ /*
+ * We could bump this to allow for full rcvegrcnt + rcvtidcnt,
+ * but then it no longer nicely fits power of two, and since
+ * we now use routines that backend onto __get_free_pages, the
+ * rest would be wasted.
+ */
+ dd->ipath_rcvhdrcnt = dd->ipath_rcvegrcnt;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrcnt,
+ dd->ipath_rcvhdrcnt);
+
+ /*
+ * Set up the shadow copies of the piobufavail registers,
+ * which we compare against the chip registers for now, and
+ * the in memory DMA'ed copies of the registers. This has to
+ * be done early, before we calculate lastport, etc.
+ */
+ val = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
+ /*
+ * calc number of pioavail registers, and save it; we have 2
+ * bits per buffer.
+ */
+ dd->ipath_pioavregs = ALIGN(val, sizeof(u64) * BITS_PER_BYTE / 2)
+ / (sizeof(u64) * BITS_PER_BYTE / 2);
+ if (ipath_kpiobufs == 0) {
+ /* not set by user, or set explictly to default */
+ if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) > 128)
+ kpiobufs = 32;
+ else
+ kpiobufs = 16;
+ }
+ else
+ kpiobufs = ipath_kpiobufs;
+
+ if (kpiobufs >
+ (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k -
+ (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT))) {
+ i = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k -
+ (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT);
+ if (i < 0)
+ i = 0;
+ dev_info(&dd->pcidev->dev, "Allocating %d PIO bufs for "
+ "kernel leaves too few for %d user ports "
+ "(%d each); using %u\n", kpiobufs,
+ dd->ipath_cfgports - 1,
+ IPATH_MIN_USER_PORT_BUFCNT, i);
+ /*
+ * shouldn't change ipath_kpiobufs, because could be
+ * different for different devices...
+ */
+ kpiobufs = i;
+ }
+ dd->ipath_lastport_piobuf =
+ dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - kpiobufs;
+ dd->ipath_pbufsport = dd->ipath_cfgports > 1
+ ? dd->ipath_lastport_piobuf / (dd->ipath_cfgports - 1)
+ : 0;
+ val32 = dd->ipath_lastport_piobuf -
+ (dd->ipath_pbufsport * (dd->ipath_cfgports - 1));
+ if (val32 > 0) {
+ ipath_dbg("allocating %u pbufs/port leaves %u unused, "
+ "add to kernel\n", dd->ipath_pbufsport, val32);
+ dd->ipath_lastport_piobuf -= val32;
+ ipath_dbg("%u pbufs/port leaves %u unused, add to kernel\n",
+ dd->ipath_pbufsport, val32);
+ }
+ dd->ipath_lastpioindex = dd->ipath_lastport_piobuf;
+ ipath_cdbg(VERBOSE, "%d PIO bufs for kernel out of %d total %u "
+ "each for %u user ports\n", kpiobufs,
+ dd->ipath_piobcnt2k + dd->ipath_piobcnt4k,
+ dd->ipath_pbufsport, dd->ipath_cfgports - 1);
+
+ dd->ipath_f_early_init(dd);
+
+ /* early_init sets rcvhdrentsize and rcvhdrsize, so this must be
+ * done after early_init */
+ dd->ipath_hdrqlast =
+ dd->ipath_rcvhdrentsize * (dd->ipath_rcvhdrcnt - 1);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrentsize,
+ dd->ipath_rcvhdrentsize);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrsize,
+ dd->ipath_rcvhdrsize);
+
+ if (!reinit) {
+ ret = init_pioavailregs(dd);
+ init_shadow_tids(dd);
+ if (ret)
+ goto done;
+ }
+
+ (void)ipath_write_kreg(dd, dd->ipath_kregs->kr_sendpioavailaddr,
+ dd->ipath_pioavailregs_phys);
+ /*
+ * this is to detect s/w errors, which the h/w works around by
+ * ignoring the low 6 bits of address, if it wasn't aligned.
+ */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpioavailaddr);
+ if (val != dd->ipath_pioavailregs_phys) {
+ ipath_dev_err(dd, "Catastrophic software error, "
+ "SendPIOAvailAddr written as %lx, "
+ "read back as %llx\n",
+ (unsigned long) dd->ipath_pioavailregs_phys,
+ (unsigned long long) val);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ val = ipath_port0_rcvhdrtail_dma + dd->ipath_unit * 64;
+
+ /* verify that the alignment requirement was met */
+ ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdrtailaddr,
+ 0, val);
+ atmp = ipath_read_kreg64_port(
+ dd, dd->ipath_kregs->kr_rcvhdrtailaddr, 0);
+ if (val != atmp) {
+ ipath_dev_err(dd, "Catastrophic software error, "
+ "RcvHdrTailAddr0 written as %llx, "
+ "read back as %llx from %x\n",
+ (unsigned long long) val,
+ (unsigned long long) atmp,
+ dd->ipath_kregs->kr_rcvhdrtailaddr);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvbthqp, IPATH_KD_QP);
+
+ /*
+ * make sure we are not in freeze, and PIO send enabled, so
+ * writes to pbc happen
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, 0ULL);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ INFINIPATH_S_PIOENABLE);
+
+ /*
+ * before error clears, since we expect serdes pll errors during
+ * this, the first time after reset
+ */
+ if (bringup_link(dd)) {
+ dev_info(&dd->pcidev->dev, "Failed to bringup IB link\n");
+ ret = -ENETDOWN;
+ goto done;
+ }
+
+ /*
+ * clear any "expected" hwerrs from reset and/or initialization
+ * clear any that aren't enabled (at least this once), and then
+ * set the enable mask
+ */
+ dd->ipath_f_init_hwerrors(dd);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+
+ dd->ipath_maskederrs = dd->ipath_ignorederrs;
+ /* clear all */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, -1LL);
+ /* enable errors that are masked, at least this first time. */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+ ~dd->ipath_maskederrs);
+ /* clear any interrups up to this point (ints still not enabled) */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL);
+
+ ipath_stats.sps_lid[dd->ipath_unit] = dd->ipath_lid;
+
+ /*
+ * Set up the port 0 (kernel) rcvhdr q and egr TIDs. If doing
+ * re-init, the simplest way to handle this is to free
+ * existing, and re-allocate.
+ */
+ if (reinit)
+ ipath_free_pddata(dd, 0, 0);
+ dd->ipath_f_tidtemplate(dd);
+ ret = ipath_create_rcvhdrq(dd, pd);
+ if (!ret)
+ ret = create_port0_egr(dd);
+ if (ret)
+ ipath_dev_err(dd, "failed to allocate port 0 (kernel) "
+ "rcvhdrq and/or egr bufs\n");
+ else
+ enable_chip(dd, pd, reinit);
+
+ /*
+ * cause retrigger of pending interrupts ignored during init,
+ * even if we had errors
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL);
+
+ if(!dd->ipath_stats_timer_active) {
+ /*
+ * first init, or after an admin disable/enable
+ * set up stats retrieval timer, even if we had errors
+ * in last portion of setup
+ */
+ init_timer(&dd->ipath_stats_timer);
+ dd->ipath_stats_timer.function = ipath_get_faststats;
+ dd->ipath_stats_timer.data = (unsigned long) dd;
+ /* every 5 seconds; */
+ dd->ipath_stats_timer.expires = jiffies + 5 * HZ;
+ /* takes ~16 seconds to overflow at full IB 4x bandwdith */
+ add_timer(&dd->ipath_stats_timer);
+ dd->ipath_stats_timer_active = 1;
+ }
+
+done:
+ if (!ret) {
+ *dd->ipath_statusp |= IPATH_STATUS_CHIP_PRESENT;
+ if (!dd->ipath_f_intrsetup(dd)) {
+ /* now we can enable all interrupts from the chip */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask,
+ -1LL);
+ /* force re-interrupt of any pending interrupts. */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear,
+ 0ULL);
+ /* chip is usable; mark it as initialized */
+ *dd->ipath_statusp |= IPATH_STATUS_INITTED;
+ } else
+ ipath_dev_err(dd, "No interrupts enabled, couldn't "
+ "setup interrupt address\n");
+
+ if (dd->ipath_cfgports > ipath_stats.sps_nports)
+ /*
+ * sps_nports is a global, so, we set it to
+ * the highest number of ports of any of the
+ * chips we find; we never decrement it, at
+ * least for now. Since this might have changed
+ * over disable/enable or prior to reset, always
+ * do the check and potentially adjust.
+ */
+ ipath_stats.sps_nports = dd->ipath_cfgports;
+ } else
+ ipath_dbg("Failed (%d) to initialize chip\n", ret);
+
+ /* if ret is non-zero, we probably should do some cleanup
+ here... */
+ return ret;
+}
+
+static int ipath_set_kpiobufs(const char *str, struct kernel_param *kp)
+{
+ struct ipath_devdata *dd;
+ unsigned long flags;
+ unsigned short val;
+ int ret;
+
+ ret = ipath_parse_ushort(str, &val);
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ if (ret < 0)
+ goto bail;
+
+ if (val == 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ list_for_each_entry(dd, &ipath_dev_list, ipath_list) {
+ if (dd->ipath_kregbase)
+ continue;
+ if (val > (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k -
+ (dd->ipath_cfgports *
+ IPATH_MIN_USER_PORT_BUFCNT)))
+ {
+ ipath_dev_err(
+ dd,
+ "Allocating %d PIO bufs for kernel leaves "
+ "too few for %d user ports (%d each)\n",
+ val, dd->ipath_cfgports - 1,
+ IPATH_MIN_USER_PORT_BUFCNT);
+ ret = -EINVAL;
+ goto bail;
+ }
+ dd->ipath_lastport_piobuf =
+ dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - val;
+ }
+
+ ret = 0;
+bail:
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
new file mode 100644
index 00000000000..3e72a1fe3d7
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -0,0 +1,854 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+#define E_SUM_PKTERRS \
+ (INFINIPATH_E_RHDRLEN | INFINIPATH_E_RBADTID | \
+ INFINIPATH_E_RBADVERSION | INFINIPATH_E_RHDR | \
+ INFINIPATH_E_RLONGPKTLEN | INFINIPATH_E_RSHORTPKTLEN | \
+ INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RMINPKTLEN | \
+ INFINIPATH_E_RFORMATERR | INFINIPATH_E_RUNSUPVL | \
+ INFINIPATH_E_RUNEXPCHAR | INFINIPATH_E_REBP)
+
+#define E_SUM_ERRS \
+ (INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM | \
+ INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \
+ INFINIPATH_E_SMAXPKTLEN | INFINIPATH_E_SUNSUPVL | \
+ INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SPKTLEN | \
+ INFINIPATH_E_INVALIDADDR)
+
+static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs)
+{
+ unsigned long sbuf[4];
+ u64 ignore_this_time = 0;
+ u32 piobcnt;
+
+ /* if possible that sendbuffererror could be valid */
+ piobcnt = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
+ /* read these before writing errorclear */
+ sbuf[0] = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_sendbuffererror);
+ sbuf[1] = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_sendbuffererror + 1);
+ if (piobcnt > 128) {
+ sbuf[2] = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_sendbuffererror + 2);
+ sbuf[3] = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_sendbuffererror + 3);
+ }
+
+ if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) {
+ int i;
+
+ ipath_cdbg(PKT, "SendbufErrs %lx %lx ", sbuf[0], sbuf[1]);
+ if (ipath_debug & __IPATH_PKTDBG && piobcnt > 128)
+ printk("%lx %lx ", sbuf[2], sbuf[3]);
+ for (i = 0; i < piobcnt; i++) {
+ if (test_bit(i, sbuf)) {
+ u32 __iomem *piobuf;
+ if (i < dd->ipath_piobcnt2k)
+ piobuf = (u32 __iomem *)
+ (dd->ipath_pio2kbase +
+ i * dd->ipath_palign);
+ else
+ piobuf = (u32 __iomem *)
+ (dd->ipath_pio4kbase +
+ (i - dd->ipath_piobcnt2k) *
+ dd->ipath_4kalign);
+
+ ipath_cdbg(PKT,
+ "PIObuf[%u] @%p pbc is %x; ",
+ i, piobuf, readl(piobuf));
+
+ ipath_disarm_piobufs(dd, i, 1);
+ }
+ }
+ if (ipath_debug & __IPATH_PKTDBG)
+ printk("\n");
+ }
+ if ((errs & (INFINIPATH_E_SDROPPEDDATAPKT |
+ INFINIPATH_E_SDROPPEDSMPPKT |
+ INFINIPATH_E_SMINPKTLEN)) &&
+ !(dd->ipath_flags & IPATH_LINKACTIVE)) {
+ /*
+ * This can happen when SMA is trying to bring the link
+ * up, but the IB link changes state at the "wrong" time.
+ * The IB logic then complains that the packet isn't
+ * valid. We don't want to confuse people, so we just
+ * don't print them, except at debug
+ */
+ ipath_dbg("Ignoring pktsend errors %llx, because not "
+ "yet active\n", (unsigned long long) errs);
+ ignore_this_time = INFINIPATH_E_SDROPPEDDATAPKT |
+ INFINIPATH_E_SDROPPEDSMPPKT |
+ INFINIPATH_E_SMINPKTLEN;
+ }
+
+ return ignore_this_time;
+}
+
+/* return the strings for the most common link states */
+static char *ib_linkstate(u32 linkstate)
+{
+ char *ret;
+
+ switch (linkstate) {
+ case IPATH_IBSTATE_INIT:
+ ret = "Init";
+ break;
+ case IPATH_IBSTATE_ARM:
+ ret = "Arm";
+ break;
+ case IPATH_IBSTATE_ACTIVE:
+ ret = "Active";
+ break;
+ default:
+ ret = "Down";
+ }
+
+ return ret;
+}
+
+static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
+ ipath_err_t errs, int noprint)
+{
+ u64 val;
+ u32 ltstate, lstate;
+
+ /*
+ * even if diags are enabled, we want to notice LINKINIT, etc.
+ * We just don't want to change the LED state, or
+ * dd->ipath_kregs->kr_ibcctrl
+ */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+ lstate = val & IPATH_IBSTATE_MASK;
+ if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM ||
+ lstate == IPATH_IBSTATE_ACTIVE) {
+ /*
+ * only print at SMA if there is a change, debug if not
+ * (sometimes we want to know that, usually not).
+ */
+ if (lstate == ((unsigned) dd->ipath_lastibcstat
+ & IPATH_IBSTATE_MASK)) {
+ ipath_dbg("Status change intr but no change (%s)\n",
+ ib_linkstate(lstate));
+ }
+ else
+ ipath_cdbg(SMA, "Unit %u link state %s, last "
+ "was %s\n", dd->ipath_unit,
+ ib_linkstate(lstate),
+ ib_linkstate((unsigned)
+ dd->ipath_lastibcstat
+ & IPATH_IBSTATE_MASK));
+ }
+ else {
+ lstate = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
+ if (lstate == IPATH_IBSTATE_INIT ||
+ lstate == IPATH_IBSTATE_ARM ||
+ lstate == IPATH_IBSTATE_ACTIVE)
+ ipath_cdbg(SMA, "Unit %u link state down"
+ " (state 0x%x), from %s\n",
+ dd->ipath_unit,
+ (u32)val & IPATH_IBSTATE_MASK,
+ ib_linkstate(lstate));
+ else
+ ipath_cdbg(VERBOSE, "Unit %u link state changed "
+ "to 0x%x from down (%x)\n",
+ dd->ipath_unit, (u32) val, lstate);
+ }
+ ltstate = (val >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+ INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+ lstate = (val >> INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+ INFINIPATH_IBCS_LINKSTATE_MASK;
+
+ if (ltstate == INFINIPATH_IBCS_LT_STATE_POLLACTIVE ||
+ ltstate == INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
+ u32 last_ltstate;
+
+ /*
+ * Ignore cycling back and forth from Polling.Active
+ * to Polling.Quiet while waiting for the other end of
+ * the link to come up. We will cycle back and forth
+ * between them if no cable is plugged in,
+ * the other device is powered off or disabled, etc.
+ */
+ last_ltstate = (dd->ipath_lastibcstat >>
+ INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT)
+ & INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+ if (last_ltstate == INFINIPATH_IBCS_LT_STATE_POLLACTIVE
+ || last_ltstate ==
+ INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
+ if (dd->ipath_ibpollcnt > 40) {
+ dd->ipath_flags |= IPATH_NOCABLE;
+ *dd->ipath_statusp |=
+ IPATH_STATUS_IB_NOCABLE;
+ } else
+ dd->ipath_ibpollcnt++;
+ goto skip_ibchange;
+ }
+ }
+ dd->ipath_ibpollcnt = 0; /* some state other than 2 or 3 */
+ ipath_stats.sps_iblink++;
+ if (ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
+ dd->ipath_flags |= IPATH_LINKDOWN;
+ dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
+ | IPATH_LINKACTIVE |
+ IPATH_LINKARMED);
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+ if (!noprint) {
+ if (((dd->ipath_lastibcstat >>
+ INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+ INFINIPATH_IBCS_LINKSTATE_MASK)
+ == INFINIPATH_IBCS_L_STATE_ACTIVE)
+ /* if from up to down be more vocal */
+ ipath_cdbg(SMA,
+ "Unit %u link now down (%s)\n",
+ dd->ipath_unit,
+ ipath_ibcstatus_str[ltstate]);
+ else
+ ipath_cdbg(VERBOSE, "Unit %u link is "
+ "down (%s)\n", dd->ipath_unit,
+ ipath_ibcstatus_str[ltstate]);
+ }
+
+ dd->ipath_f_setextled(dd, lstate, ltstate);
+ } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ACTIVE) {
+ dd->ipath_flags |= IPATH_LINKACTIVE;
+ dd->ipath_flags &=
+ ~(IPATH_LINKUNK | IPATH_LINKINIT | IPATH_LINKDOWN |
+ IPATH_LINKARMED | IPATH_NOCABLE);
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_NOCABLE;
+ *dd->ipath_statusp |=
+ IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF;
+ dd->ipath_f_setextled(dd, lstate, ltstate);
+
+ __ipath_layer_intr(dd, IPATH_LAYER_INT_IF_UP);
+ } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_INIT) {
+ /*
+ * set INIT and DOWN. Down is checked by most of the other
+ * code, but INIT is useful to know in a few places.
+ */
+ dd->ipath_flags |= IPATH_LINKINIT | IPATH_LINKDOWN;
+ dd->ipath_flags &=
+ ~(IPATH_LINKUNK | IPATH_LINKACTIVE | IPATH_LINKARMED
+ | IPATH_NOCABLE);
+ *dd->ipath_statusp &= ~(IPATH_STATUS_IB_NOCABLE
+ | IPATH_STATUS_IB_READY);
+ dd->ipath_f_setextled(dd, lstate, ltstate);
+ } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ARM) {
+ dd->ipath_flags |= IPATH_LINKARMED;
+ dd->ipath_flags &=
+ ~(IPATH_LINKUNK | IPATH_LINKDOWN | IPATH_LINKINIT |
+ IPATH_LINKACTIVE | IPATH_NOCABLE);
+ *dd->ipath_statusp &= ~(IPATH_STATUS_IB_NOCABLE
+ | IPATH_STATUS_IB_READY);
+ dd->ipath_f_setextled(dd, lstate, ltstate);
+ } else {
+ if (!noprint)
+ ipath_dbg("IBstatuschange unit %u: %s (%x)\n",
+ dd->ipath_unit,
+ ipath_ibcstatus_str[ltstate], ltstate);
+ }
+skip_ibchange:
+ dd->ipath_lastibcstat = val;
+}
+
+static void handle_supp_msgs(struct ipath_devdata *dd,
+ unsigned supp_msgs, char msg[512])
+{
+ /*
+ * Print the message unless it's ibc status change only, which
+ * happens so often we never want to count it.
+ */
+ if (dd->ipath_lasterror & ~INFINIPATH_E_IBSTATUSCHANGED) {
+ ipath_decode_err(msg, sizeof msg, dd->ipath_lasterror &
+ ~INFINIPATH_E_IBSTATUSCHANGED);
+ if (dd->ipath_lasterror &
+ ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL))
+ ipath_dev_err(dd, "Suppressed %u messages for "
+ "fast-repeating errors (%s) (%llx)\n",
+ supp_msgs, msg,
+ (unsigned long long)
+ dd->ipath_lasterror);
+ else {
+ /*
+ * rcvegrfull and rcvhdrqfull are "normal", for some
+ * types of processes (mostly benchmarks) that send
+ * huge numbers of messages, while not processing
+ * them. So only complain about these at debug
+ * level.
+ */
+ ipath_dbg("Suppressed %u messages for %s\n",
+ supp_msgs, msg);
+ }
+ }
+}
+
+static unsigned handle_frequent_errors(struct ipath_devdata *dd,
+ ipath_err_t errs, char msg[512],
+ int *noprint)
+{
+ unsigned long nc;
+ static unsigned long nextmsg_time;
+ static unsigned nmsgs, supp_msgs;
+
+ /*
+ * Throttle back "fast" messages to no more than 10 per 5 seconds.
+ * This isn't perfect, but it's a reasonable heuristic. If we get
+ * more than 10, give a 6x longer delay.
+ */
+ nc = jiffies;
+ if (nmsgs > 10) {
+ if (time_before(nc, nextmsg_time)) {
+ *noprint = 1;
+ if (!supp_msgs++)
+ nextmsg_time = nc + HZ * 3;
+ }
+ else if (supp_msgs) {
+ handle_supp_msgs(dd, supp_msgs, msg);
+ supp_msgs = 0;
+ nmsgs = 0;
+ }
+ }
+ else if (!nmsgs++ || time_after(nc, nextmsg_time))
+ nextmsg_time = nc + HZ / 2;
+
+ return supp_msgs;
+}
+
+static void handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+{
+ char msg[512];
+ u64 ignore_this_time = 0;
+ int i;
+ int chkerrpkts = 0, noprint = 0;
+ unsigned supp_msgs;
+
+ supp_msgs = handle_frequent_errors(dd, errs, msg, &noprint);
+
+ /*
+ * don't report errors that are masked (includes those always
+ * ignored)
+ */
+ errs &= ~dd->ipath_maskederrs;
+
+ /* do these first, they are most important */
+ if (errs & INFINIPATH_E_HARDWARE) {
+ /* reuse same msg buf */
+ dd->ipath_f_handle_hwerrors(dd, msg, sizeof msg);
+ }
+
+ if (!noprint && (errs & ~infinipath_e_bitsextant))
+ ipath_dev_err(dd, "error interrupt with unknown errors "
+ "%llx set\n", (unsigned long long)
+ (errs & ~infinipath_e_bitsextant));
+
+ if (errs & E_SUM_ERRS)
+ ignore_this_time = handle_e_sum_errs(dd, errs);
+
+ if (supp_msgs == 250000) {
+ /*
+ * It's not entirely reasonable assuming that the errors set
+ * in the last clear period are all responsible for the
+ * problem, but the alternative is to assume it's the only
+ * ones on this particular interrupt, which also isn't great
+ */
+ dd->ipath_maskederrs |= dd->ipath_lasterror | errs;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+ ~dd->ipath_maskederrs);
+ ipath_decode_err(msg, sizeof msg,
+ (dd->ipath_maskederrs & ~dd->
+ ipath_ignorederrs));
+
+ if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) &
+ ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL))
+ ipath_dev_err(dd, "Disabling error(s) %llx because "
+ "occuring too frequently (%s)\n",
+ (unsigned long long)
+ (dd->ipath_maskederrs &
+ ~dd->ipath_ignorederrs), msg);
+ else {
+ /*
+ * rcvegrfull and rcvhdrqfull are "normal",
+ * for some types of processes (mostly benchmarks)
+ * that send huge numbers of messages, while not
+ * processing them. So only complain about
+ * these at debug level.
+ */
+ ipath_dbg("Disabling frequent queue full errors "
+ "(%s)\n", msg);
+ }
+
+ /*
+ * Re-enable the masked errors after around 3 minutes. in
+ * ipath_get_faststats(). If we have a series of fast
+ * repeating but different errors, the interval will keep
+ * stretching out, but that's OK, as that's pretty
+ * catastrophic.
+ */
+ dd->ipath_unmasktime = jiffies + HZ * 180;
+ }
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, errs);
+ if (ignore_this_time)
+ errs &= ~ignore_this_time;
+ if (errs & ~dd->ipath_lasterror) {
+ errs &= ~dd->ipath_lasterror;
+ /* never suppress duplicate hwerrors or ibstatuschange */
+ dd->ipath_lasterror |= errs &
+ ~(INFINIPATH_E_HARDWARE |
+ INFINIPATH_E_IBSTATUSCHANGED);
+ }
+ if (!errs)
+ return;
+
+ if (!noprint)
+ /*
+ * the ones we mask off are handled specially below or above
+ */
+ ipath_decode_err(msg, sizeof msg,
+ errs & ~(INFINIPATH_E_IBSTATUSCHANGED |
+ INFINIPATH_E_RRCVEGRFULL |
+ INFINIPATH_E_RRCVHDRFULL |
+ INFINIPATH_E_HARDWARE));
+ else
+ /* so we don't need if (!noprint) at strlcat's below */
+ *msg = 0;
+
+ if (errs & E_SUM_PKTERRS) {
+ ipath_stats.sps_pkterrs++;
+ chkerrpkts = 1;
+ }
+ if (errs & E_SUM_ERRS)
+ ipath_stats.sps_errs++;
+
+ if (errs & (INFINIPATH_E_RICRC | INFINIPATH_E_RVCRC)) {
+ ipath_stats.sps_crcerrs++;
+ chkerrpkts = 1;
+ }
+
+ /*
+ * We don't want to print these two as they happen, or we can make
+ * the situation even worse, because it takes so long to print
+ * messages to serial consoles. Kernel ports get printed from
+ * fast_stats, no more than every 5 seconds, user ports get printed
+ * on close
+ */
+ if (errs & INFINIPATH_E_RRCVHDRFULL) {
+ int any;
+ u32 hd, tl;
+ ipath_stats.sps_hdrqfull++;
+ for (any = i = 0; i < dd->ipath_cfgports; i++) {
+ struct ipath_portdata *pd = dd->ipath_pd[i];
+ if (i == 0) {
+ hd = dd->ipath_port0head;
+ tl = (u32) le64_to_cpu(
+ *dd->ipath_hdrqtailptr);
+ } else if (pd && pd->port_cnt &&
+ pd->port_rcvhdrtail_kvaddr) {
+ /*
+ * don't report same point multiple times,
+ * except kernel
+ */
+ tl = (u32) * pd->port_rcvhdrtail_kvaddr;
+ if (tl == dd->ipath_lastrcvhdrqtails[i])
+ continue;
+ hd = ipath_read_ureg32(dd, ur_rcvhdrhead,
+ i);
+ } else
+ continue;
+ if (hd == (tl + 1) ||
+ (!hd && tl == dd->ipath_hdrqlast)) {
+ dd->ipath_lastrcvhdrqtails[i] = tl;
+ pd->port_hdrqfull++;
+ if (i == 0)
+ chkerrpkts = 1;
+ }
+ }
+ }
+ if (errs & INFINIPATH_E_RRCVEGRFULL) {
+ /*
+ * since this is of less importance and not likely to
+ * happen without also getting hdrfull, only count
+ * occurrences; don't check each port (or even the kernel
+ * vs user)
+ */
+ ipath_stats.sps_etidfull++;
+ if (dd->ipath_port0head !=
+ (u32) le64_to_cpu(*dd->ipath_hdrqtailptr))
+ chkerrpkts = 1;
+ }
+
+ /*
+ * do this before IBSTATUSCHANGED, in case both bits set in a single
+ * interrupt; we want the STATUSCHANGE to "win", so we do our
+ * internal copy of state machine correctly
+ */
+ if (errs & INFINIPATH_E_RIBLOSTLINK) {
+ /*
+ * force through block below
+ */
+ errs |= INFINIPATH_E_IBSTATUSCHANGED;
+ ipath_stats.sps_iblink++;
+ dd->ipath_flags |= IPATH_LINKDOWN;
+ dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
+ | IPATH_LINKARMED | IPATH_LINKACTIVE);
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+ if (!noprint) {
+ u64 st = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_ibcstatus);
+
+ ipath_dbg("Lost link, link now down (%s)\n",
+ ipath_ibcstatus_str[st & 0xf]);
+ }
+ }
+ if (errs & INFINIPATH_E_IBSTATUSCHANGED)
+ handle_e_ibstatuschanged(dd, errs, noprint);
+
+ if (errs & INFINIPATH_E_RESET) {
+ if (!noprint)
+ ipath_dev_err(dd, "Got reset, requires re-init "
+ "(unload and reload driver)\n");
+ dd->ipath_flags &= ~IPATH_INITTED; /* needs re-init */
+ /* mark as having had error */
+ *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_CONF;
+ }
+
+ if (!noprint && *msg)
+ ipath_dev_err(dd, "%s error\n", msg);
+ if (dd->ipath_sma_state_wanted & dd->ipath_flags) {
+ ipath_cdbg(VERBOSE, "sma wanted state %x, iflags now %x, "
+ "waking\n", dd->ipath_sma_state_wanted,
+ dd->ipath_flags);
+ wake_up_interruptible(&ipath_sma_state_wait);
+ }
+
+ if (chkerrpkts)
+ /* process possible error packets in hdrq */
+ ipath_kreceive(dd);
+}
+
+/* this is separate to allow for better optimization of ipath_intr() */
+
+static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
+{
+ /*
+ * sometimes happen during driver init and unload, don't want
+ * to process any interrupts at that point
+ */
+
+ /* this is just a bandaid, not a fix, if something goes badly
+ * wrong */
+ if (++*unexpectp > 100) {
+ if (++*unexpectp > 105) {
+ /*
+ * ok, we must be taking somebody else's interrupts,
+ * due to a messed up mptable and/or PIRQ table, so
+ * unregister the interrupt. We've seen this during
+ * linuxbios development work, and it may happen in
+ * the future again.
+ */
+ if (dd->pcidev && dd->pcidev->irq) {
+ ipath_dev_err(dd, "Now %u unexpected "
+ "interrupts, unregistering "
+ "interrupt handler\n",
+ *unexpectp);
+ ipath_dbg("free_irq of irq %x\n",
+ dd->pcidev->irq);
+ free_irq(dd->pcidev->irq, dd);
+ }
+ }
+ if (ipath_read_kreg32(dd, dd->ipath_kregs->kr_intmask)) {
+ ipath_dev_err(dd, "%u unexpected interrupts, "
+ "disabling interrupts completely\n",
+ *unexpectp);
+ /*
+ * disable all interrupts, something is very wrong
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask,
+ 0ULL);
+ }
+ } else if (*unexpectp > 1)
+ ipath_dbg("Interrupt when not ready, should not happen, "
+ "ignoring\n");
+}
+
+static void ipath_bad_regread(struct ipath_devdata *dd)
+{
+ static int allbits;
+
+ /* separate routine, for better optimization of ipath_intr() */
+
+ /*
+ * We print the message and disable interrupts, in hope of
+ * having a better chance of debugging the problem.
+ */
+ ipath_dev_err(dd,
+ "Read of interrupt status failed (all bits set)\n");
+ if (allbits++) {
+ /* disable all interrupts, something is very wrong */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL);
+ if (allbits == 2) {
+ ipath_dev_err(dd, "Still bad interrupt status, "
+ "unregistering interrupt\n");
+ free_irq(dd->pcidev->irq, dd);
+ } else if (allbits > 2) {
+ if ((allbits % 10000) == 0)
+ printk(".");
+ } else
+ ipath_dev_err(dd, "Disabling interrupts, "
+ "multiple errors\n");
+ }
+}
+
+static void handle_port_pioavail(struct ipath_devdata *dd)
+{
+ u32 i;
+ /*
+ * start from port 1, since for now port 0 is never using
+ * wait_event for PIO
+ */
+ for (i = 1; dd->ipath_portpiowait && i < dd->ipath_cfgports; i++) {
+ struct ipath_portdata *pd = dd->ipath_pd[i];
+
+ if (pd && pd->port_cnt &&
+ dd->ipath_portpiowait & (1U << i)) {
+ clear_bit(i, &dd->ipath_portpiowait);
+ if (test_bit(IPATH_PORT_WAITING_PIO,
+ &pd->port_flag)) {
+ clear_bit(IPATH_PORT_WAITING_PIO,
+ &pd->port_flag);
+ wake_up_interruptible(&pd->port_wait);
+ }
+ }
+ }
+}
+
+static void handle_layer_pioavail(struct ipath_devdata *dd)
+{
+ int ret;
+
+ ret = __ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE);
+ if (ret > 0)
+ goto set;
+
+ ret = __ipath_verbs_piobufavail(dd);
+ if (ret > 0)
+ goto set;
+
+ return;
+set:
+ set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+}
+
+static void handle_rcv(struct ipath_devdata *dd, u32 istat)
+{
+ u64 portr;
+ int i;
+ int rcvdint = 0;
+
+ portr = ((istat >> INFINIPATH_I_RCVAVAIL_SHIFT) &
+ infinipath_i_rcvavail_mask)
+ | ((istat >> INFINIPATH_I_RCVURG_SHIFT) &
+ infinipath_i_rcvurg_mask);
+ for (i = 0; i < dd->ipath_cfgports; i++) {
+ struct ipath_portdata *pd = dd->ipath_pd[i];
+ if (portr & (1 << i) && pd &&
+ pd->port_cnt) {
+ if (i == 0)
+ ipath_kreceive(dd);
+ else if (test_bit(IPATH_PORT_WAITING_RCV,
+ &pd->port_flag)) {
+ int rcbit;
+ clear_bit(IPATH_PORT_WAITING_RCV,
+ &pd->port_flag);
+ rcbit = i + INFINIPATH_R_INTRAVAIL_SHIFT;
+ clear_bit(1UL << rcbit, &dd->ipath_rcvctrl);
+ wake_up_interruptible(&pd->port_wait);
+ rcvdint = 1;
+ }
+ }
+ }
+ if (rcvdint) {
+ /* only want to take one interrupt, so turn off the rcv
+ * interrupt for all the ports that we did the wakeup on
+ * (but never for kernel port)
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+ }
+}
+
+irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs)
+{
+ struct ipath_devdata *dd = data;
+ u32 istat;
+ ipath_err_t estat = 0;
+ static unsigned unexpected = 0;
+ irqreturn_t ret;
+
+ if(!(dd->ipath_flags & IPATH_PRESENT)) {
+ /* this is mostly so we don't try to touch the chip while
+ * it is being reset */
+ /*
+ * This return value is perhaps odd, but we do not want the
+ * interrupt core code to remove our interrupt handler
+ * because we don't appear to be handling an interrupt
+ * during a chip reset.
+ */
+ return IRQ_HANDLED;
+ }
+
+ istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus);
+ if (unlikely(!istat)) {
+ ipath_stats.sps_nullintr++;
+ ret = IRQ_NONE; /* not our interrupt, or already handled */
+ goto bail;
+ }
+ if (unlikely(istat == -1)) {
+ ipath_bad_regread(dd);
+ /* don't know if it was our interrupt or not */
+ ret = IRQ_NONE;
+ goto bail;
+ }
+
+ ipath_stats.sps_ints++;
+
+ /*
+ * this needs to be flags&initted, not statusp, so we keep
+ * taking interrupts even after link goes down, etc.
+ * Also, we *must* clear the interrupt at some point, or we won't
+ * take it again, which can be real bad for errors, etc...
+ */
+
+ if (!(dd->ipath_flags & IPATH_INITTED)) {
+ ipath_bad_intr(dd, &unexpected);
+ ret = IRQ_NONE;
+ goto bail;
+ }
+ if (unexpected)
+ unexpected = 0;
+
+ ipath_cdbg(VERBOSE, "intr stat=0x%x\n", istat);
+
+ if (istat & ~infinipath_i_bitsextant)
+ ipath_dev_err(dd,
+ "interrupt with unknown interrupts %x set\n",
+ istat & (u32) ~ infinipath_i_bitsextant);
+
+ if (istat & INFINIPATH_I_ERROR) {
+ ipath_stats.sps_errints++;
+ estat = ipath_read_kreg64(dd,
+ dd->ipath_kregs->kr_errorstatus);
+ if (!estat)
+ dev_info(&dd->pcidev->dev, "error interrupt (%x), "
+ "but no error bits set!\n", istat);
+ else if (estat == -1LL)
+ /*
+ * should we try clearing all, or hope next read
+ * works?
+ */
+ ipath_dev_err(dd, "Read of error status failed "
+ "(all bits set); ignoring\n");
+ else
+ handle_errors(dd, estat);
+ }
+
+ if (istat & INFINIPATH_I_GPIO) {
+ if (unlikely(!(dd->ipath_flags & IPATH_GPIO_INTR))) {
+ u32 gpiostatus;
+ gpiostatus = ipath_read_kreg32(
+ dd, dd->ipath_kregs->kr_gpio_status);
+ ipath_dbg("Unexpected GPIO interrupt bits %x\n",
+ gpiostatus);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear,
+ gpiostatus);
+ }
+ else {
+ /* Clear GPIO status bit 2 */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear,
+ (u64) (1 << 2));
+
+ /*
+ * Packets are available in the port 0 rcv queue.
+ * Eventually this needs to be generalized to check
+ * IPATH_GPIO_INTR, and the specific GPIO bit, if
+ * GPIO interrupts are used for anything else.
+ */
+ ipath_kreceive(dd);
+ }
+ }
+
+ /*
+ * clear the ones we will deal with on this round
+ * We clear it early, mostly for receive interrupts, so we
+ * know the chip will have seen this by the time we process
+ * the queue, and will re-interrupt if necessary. The processor
+ * itself won't take the interrupt again until we return.
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat);
+
+ if (istat & INFINIPATH_I_SPIOBUFAVAIL) {
+ clear_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+
+ if (dd->ipath_portpiowait)
+ handle_port_pioavail(dd);
+
+ handle_layer_pioavail(dd);
+ }
+
+ /*
+ * we check for both transition from empty to non-empty, and urgent
+ * packets (those with the interrupt bit set in the header)
+ */
+
+ if (istat & ((infinipath_i_rcvavail_mask <<
+ INFINIPATH_I_RCVAVAIL_SHIFT)
+ | (infinipath_i_rcvurg_mask <<
+ INFINIPATH_I_RCVURG_SHIFT)))
+ handle_rcv(dd, istat);
+
+ ret = IRQ_HANDLED;
+
+bail:
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
new file mode 100644
index 00000000000..5d92d57b6f5
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -0,0 +1,883 @@
+#ifndef _IPATH_KERNEL_H
+#define _IPATH_KERNEL_H
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This header file is the base header file for infinipath kernel code
+ * ipath_user.h serves a similar purpose for user code.
+ */
+
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include "ipath_common.h"
+#include "ipath_debug.h"
+#include "ipath_registers.h"
+
+/* only s/w major version of InfiniPath we can handle */
+#define IPATH_CHIP_VERS_MAJ 2U
+
+/* don't care about this except printing */
+#define IPATH_CHIP_VERS_MIN 0U
+
+/* temporary, maybe always */
+extern struct infinipath_stats ipath_stats;
+
+#define IPATH_CHIP_SWVERSION IPATH_CHIP_VERS_MAJ
+
+struct ipath_portdata {
+ void **port_rcvegrbuf;
+ dma_addr_t *port_rcvegrbuf_phys;
+ /* rcvhdrq base, needs mmap before useful */
+ void *port_rcvhdrq;
+ /* kernel virtual address where hdrqtail is updated */
+ u64 *port_rcvhdrtail_kvaddr;
+ /* page * used for uaddr */
+ struct page *port_rcvhdrtail_pagep;
+ /*
+ * temp buffer for expected send setup, allocated at open, instead
+ * of each setup call
+ */
+ void *port_tid_pg_list;
+ /* when waiting for rcv or pioavail */
+ wait_queue_head_t port_wait;
+ /*
+ * rcvegr bufs base, physical, must fit
+ * in 44 bits so 32 bit programs mmap64 44 bit works)
+ */
+ dma_addr_t port_rcvegr_phys;
+ /* mmap of hdrq, must fit in 44 bits */
+ dma_addr_t port_rcvhdrq_phys;
+ /*
+ * the actual user address that we ipath_mlock'ed, so we can
+ * ipath_munlock it at close
+ */
+ unsigned long port_rcvhdrtail_uaddr;
+ /*
+ * number of opens on this instance (0 or 1; ignoring forks, dup,
+ * etc. for now)
+ */
+ int port_cnt;
+ /*
+ * how much space to leave at start of eager TID entries for
+ * protocol use, on each TID
+ */
+ /* instead of calculating it */
+ unsigned port_port;
+ /* chip offset of PIO buffers for this port */
+ u32 port_piobufs;
+ /* how many alloc_pages() chunks in port_rcvegrbuf_pages */
+ u32 port_rcvegrbuf_chunks;
+ /* how many egrbufs per chunk */
+ u32 port_rcvegrbufs_perchunk;
+ /* order for port_rcvegrbuf_pages */
+ size_t port_rcvegrbuf_size;
+ /* rcvhdrq size (for freeing) */
+ size_t port_rcvhdrq_size;
+ /* next expected TID to check when looking for free */
+ u32 port_tidcursor;
+ /* next expected TID to check */
+ unsigned long port_flag;
+ /* WAIT_RCV that timed out, no interrupt */
+ u32 port_rcvwait_to;
+ /* WAIT_PIO that timed out, no interrupt */
+ u32 port_piowait_to;
+ /* WAIT_RCV already happened, no wait */
+ u32 port_rcvnowait;
+ /* WAIT_PIO already happened, no wait */
+ u32 port_pionowait;
+ /* total number of rcvhdrqfull errors */
+ u32 port_hdrqfull;
+ /* pid of process using this port */
+ pid_t port_pid;
+ /* same size as task_struct .comm[] */
+ char port_comm[16];
+ /* pkeys set by this use of this port */
+ u16 port_pkeys[4];
+ /* so file ops can get at unit */
+ struct ipath_devdata *port_dd;
+};
+
+struct sk_buff;
+
+/*
+ * control information for layered drivers
+ */
+struct _ipath_layer {
+ void *l_arg;
+};
+
+/* Verbs layer interface */
+struct _verbs_layer {
+ void *l_arg;
+ struct timer_list l_timer;
+};
+
+struct ipath_devdata {
+ struct list_head ipath_list;
+
+ struct ipath_kregs const *ipath_kregs;
+ struct ipath_cregs const *ipath_cregs;
+
+ /* mem-mapped pointer to base of chip regs */
+ u64 __iomem *ipath_kregbase;
+ /* end of mem-mapped chip space; range checking */
+ u64 __iomem *ipath_kregend;
+ /* physical address of chip for io_remap, etc. */
+ unsigned long ipath_physaddr;
+ /* base of memory alloced for ipath_kregbase, for free */
+ u64 *ipath_kregalloc;
+ /*
+ * version of kregbase that doesn't have high bits set (for 32 bit
+ * programs, so mmap64 44 bit works)
+ */
+ u64 __iomem *ipath_kregvirt;
+ /*
+ * virtual address where port0 rcvhdrqtail updated for this unit.
+ * only written to by the chip, not the driver.
+ */
+ volatile __le64 *ipath_hdrqtailptr;
+ dma_addr_t ipath_dma_addr;
+ /* ipath_cfgports pointers */
+ struct ipath_portdata **ipath_pd;
+ /* sk_buffs used by port 0 eager receive queue */
+ struct sk_buff **ipath_port0_skbs;
+ /* kvirt address of 1st 2k pio buffer */
+ void __iomem *ipath_pio2kbase;
+ /* kvirt address of 1st 4k pio buffer */
+ void __iomem *ipath_pio4kbase;
+ /*
+ * points to area where PIOavail registers will be DMA'ed.
+ * Has to be on a page of it's own, because the page will be
+ * mapped into user program space. This copy is *ONLY* ever
+ * written by DMA, not by the driver! Need a copy per device
+ * when we get to multiple devices
+ */
+ volatile __le64 *ipath_pioavailregs_dma;
+ /* physical address where updates occur */
+ dma_addr_t ipath_pioavailregs_phys;
+ struct _ipath_layer ipath_layer;
+ /* setup intr */
+ int (*ipath_f_intrsetup)(struct ipath_devdata *);
+ /* setup on-chip bus config */
+ int (*ipath_f_bus)(struct ipath_devdata *, struct pci_dev *);
+ /* hard reset chip */
+ int (*ipath_f_reset)(struct ipath_devdata *);
+ int (*ipath_f_get_boardname)(struct ipath_devdata *, char *,
+ size_t);
+ void (*ipath_f_init_hwerrors)(struct ipath_devdata *);
+ void (*ipath_f_handle_hwerrors)(struct ipath_devdata *, char *,
+ size_t);
+ void (*ipath_f_quiet_serdes)(struct ipath_devdata *);
+ int (*ipath_f_bringup_serdes)(struct ipath_devdata *);
+ int (*ipath_f_early_init)(struct ipath_devdata *);
+ void (*ipath_f_clear_tids)(struct ipath_devdata *, unsigned);
+ void (*ipath_f_put_tid)(struct ipath_devdata *, u64 __iomem*,
+ u32, unsigned long);
+ void (*ipath_f_tidtemplate)(struct ipath_devdata *);
+ void (*ipath_f_cleanup)(struct ipath_devdata *);
+ void (*ipath_f_setextled)(struct ipath_devdata *, u64, u64);
+ /* fill out chip-specific fields */
+ int (*ipath_f_get_base_info)(struct ipath_portdata *, void *);
+ struct _verbs_layer verbs_layer;
+ /* total dwords sent (summed from counter) */
+ u64 ipath_sword;
+ /* total dwords rcvd (summed from counter) */
+ u64 ipath_rword;
+ /* total packets sent (summed from counter) */
+ u64 ipath_spkts;
+ /* total packets rcvd (summed from counter) */
+ u64 ipath_rpkts;
+ /* ipath_statusp initially points to this. */
+ u64 _ipath_status;
+ /* GUID for this interface, in network order */
+ __be64 ipath_guid;
+ /*
+ * aggregrate of error bits reported since last cleared, for
+ * limiting of error reporting
+ */
+ ipath_err_t ipath_lasterror;
+ /*
+ * aggregrate of error bits reported since last cleared, for
+ * limiting of hwerror reporting
+ */
+ ipath_err_t ipath_lasthwerror;
+ /*
+ * errors masked because they occur too fast, also includes errors
+ * that are always ignored (ipath_ignorederrs)
+ */
+ ipath_err_t ipath_maskederrs;
+ /* time in jiffies at which to re-enable maskederrs */
+ unsigned long ipath_unmasktime;
+ /*
+ * errors always ignored (masked), at least for a given
+ * chip/device, because they are wrong or not useful
+ */
+ ipath_err_t ipath_ignorederrs;
+ /* count of egrfull errors, combined for all ports */
+ u64 ipath_last_tidfull;
+ /* for ipath_qcheck() */
+ u64 ipath_lastport0rcv_cnt;
+ /* template for writing TIDs */
+ u64 ipath_tidtemplate;
+ /* value to write to free TIDs */
+ u64 ipath_tidinvalid;
+ /* PE-800 rcv interrupt setup */
+ u64 ipath_rhdrhead_intr_off;
+
+ /* size of memory at ipath_kregbase */
+ u32 ipath_kregsize;
+ /* number of registers used for pioavail */
+ u32 ipath_pioavregs;
+ /* IPATH_POLL, etc. */
+ u32 ipath_flags;
+ /* ipath_flags sma is waiting for */
+ u32 ipath_sma_state_wanted;
+ /* last buffer for user use, first buf for kernel use is this
+ * index. */
+ u32 ipath_lastport_piobuf;
+ /* is a stats timer active */
+ u32 ipath_stats_timer_active;
+ /* dwords sent read from counter */
+ u32 ipath_lastsword;
+ /* dwords received read from counter */
+ u32 ipath_lastrword;
+ /* sent packets read from counter */
+ u32 ipath_lastspkts;
+ /* received packets read from counter */
+ u32 ipath_lastrpkts;
+ /* pio bufs allocated per port */
+ u32 ipath_pbufsport;
+ /*
+ * number of ports configured as max; zero is set to number chip
+ * supports, less gives more pio bufs/port, etc.
+ */
+ u32 ipath_cfgports;
+ /* port0 rcvhdrq head offset */
+ u32 ipath_port0head;
+ /* count of port 0 hdrqfull errors */
+ u32 ipath_p0_hdrqfull;
+
+ /*
+ * (*cfgports) used to suppress multiple instances of same
+ * port staying stuck at same point
+ */
+ u32 *ipath_lastrcvhdrqtails;
+ /*
+ * (*cfgports) used to suppress multiple instances of same
+ * port staying stuck at same point
+ */
+ u32 *ipath_lastegrheads;
+ /*
+ * index of last piobuffer we used. Speeds up searching, by
+ * starting at this point. Doesn't matter if multiple cpu's use and
+ * update, last updater is only write that matters. Whenever it
+ * wraps, we update shadow copies. Need a copy per device when we
+ * get to multiple devices
+ */
+ u32 ipath_lastpioindex;
+ /* max length of freezemsg */
+ u32 ipath_freezelen;
+ /*
+ * consecutive times we wanted a PIO buffer but were unable to
+ * get one
+ */
+ u32 ipath_consec_nopiobuf;
+ /*
+ * hint that we should update ipath_pioavailshadow before
+ * looking for a PIO buffer
+ */
+ u32 ipath_upd_pio_shadow;
+ /* so we can rewrite it after a chip reset */
+ u32 ipath_pcibar0;
+ /* so we can rewrite it after a chip reset */
+ u32 ipath_pcibar1;
+ /* sequential tries for SMA send and no bufs */
+ u32 ipath_nosma_bufs;
+ /* duration (seconds) ipath_nosma_bufs set */
+ u32 ipath_nosma_secs;
+
+ /* HT/PCI Vendor ID (here for NodeInfo) */
+ u16 ipath_vendorid;
+ /* HT/PCI Device ID (here for NodeInfo) */
+ u16 ipath_deviceid;
+ /* offset in HT config space of slave/primary interface block */
+ u8 ipath_ht_slave_off;
+ /* for write combining settings */
+ unsigned long ipath_wc_cookie;
+ /* ref count for each pkey */
+ atomic_t ipath_pkeyrefs[4];
+ /* shadow copy of all exptids physaddr; used only by funcsim */
+ u64 *ipath_tidsimshadow;
+ /* shadow copy of struct page *'s for exp tid pages */
+ struct page **ipath_pageshadow;
+ /* lock to workaround chip bug 9437 */
+ spinlock_t ipath_tid_lock;
+
+ /*
+ * IPATH_STATUS_*,
+ * this address is mapped readonly into user processes so they can
+ * get status cheaply, whenever they want.
+ */
+ u64 *ipath_statusp;
+ /* freeze msg if hw error put chip in freeze */
+ char *ipath_freezemsg;
+ /* pci access data structure */
+ struct pci_dev *pcidev;
+ struct cdev *cdev;
+ struct class_device *class_dev;
+ /* timer used to prevent stats overflow, error throttling, etc. */
+ struct timer_list ipath_stats_timer;
+ /* check for stale messages in rcv queue */
+ /* only allow one intr at a time. */
+ unsigned long ipath_rcv_pending;
+
+ /*
+ * Shadow copies of registers; size indicates read access size.
+ * Most of them are readonly, but some are write-only register,
+ * where we manipulate the bits in the shadow copy, and then write
+ * the shadow copy to infinipath.
+ *
+ * We deliberately make most of these 32 bits, since they have
+ * restricted range. For any that we read, we won't to generate 32
+ * bit accesses, since Opteron will generate 2 separate 32 bit HT
+ * transactions for a 64 bit read, and we want to avoid unnecessary
+ * HT transactions.
+ */
+
+ /* This is the 64 bit group */
+
+ /*
+ * shadow of pioavail, check to be sure it's large enough at
+ * init time.
+ */
+ unsigned long ipath_pioavailshadow[8];
+ /* shadow of kr_gpio_out, for rmw ops */
+ u64 ipath_gpio_out;
+ /* kr_revision shadow */
+ u64 ipath_revision;
+ /*
+ * shadow of ibcctrl, for interrupt handling of link changes,
+ * etc.
+ */
+ u64 ipath_ibcctrl;
+ /*
+ * last ibcstatus, to suppress "duplicate" status change messages,
+ * mostly from 2 to 3
+ */
+ u64 ipath_lastibcstat;
+ /* hwerrmask shadow */
+ ipath_err_t ipath_hwerrmask;
+ /* interrupt config reg shadow */
+ u64 ipath_intconfig;
+ /* kr_sendpiobufbase value */
+ u64 ipath_piobufbase;
+
+ /* these are the "32 bit" regs */
+
+ /*
+ * number of GUIDs in the flash for this interface; may need some
+ * rethinking for setting on other ifaces
+ */
+ u32 ipath_nguid;
+ /*
+ * the following two are 32-bit bitmasks, but {test,clear,set}_bit
+ * all expect bit fields to be "unsigned long"
+ */
+ /* shadow kr_rcvctrl */
+ unsigned long ipath_rcvctrl;
+ /* shadow kr_sendctrl */
+ unsigned long ipath_sendctrl;
+
+ /* value we put in kr_rcvhdrcnt */
+ u32 ipath_rcvhdrcnt;
+ /* value we put in kr_rcvhdrsize */
+ u32 ipath_rcvhdrsize;
+ /* value we put in kr_rcvhdrentsize */
+ u32 ipath_rcvhdrentsize;
+ /* offset of last entry in rcvhdrq */
+ u32 ipath_hdrqlast;
+ /* kr_portcnt value */
+ u32 ipath_portcnt;
+ /* kr_pagealign value */
+ u32 ipath_palign;
+ /* number of "2KB" PIO buffers */
+ u32 ipath_piobcnt2k;
+ /* size in bytes of "2KB" PIO buffers */
+ u32 ipath_piosize2k;
+ /* number of "4KB" PIO buffers */
+ u32 ipath_piobcnt4k;
+ /* size in bytes of "4KB" PIO buffers */
+ u32 ipath_piosize4k;
+ /* kr_rcvegrbase value */
+ u32 ipath_rcvegrbase;
+ /* kr_rcvegrcnt value */
+ u32 ipath_rcvegrcnt;
+ /* kr_rcvtidbase value */
+ u32 ipath_rcvtidbase;
+ /* kr_rcvtidcnt value */
+ u32 ipath_rcvtidcnt;
+ /* kr_sendregbase */
+ u32 ipath_sregbase;
+ /* kr_userregbase */
+ u32 ipath_uregbase;
+ /* kr_counterregbase */
+ u32 ipath_cregbase;
+ /* shadow the control register contents */
+ u32 ipath_control;
+ /* shadow the gpio output contents */
+ u32 ipath_extctrl;
+ /* PCI revision register (HTC rev on FPGA) */
+ u32 ipath_pcirev;
+
+ /* chip address space used by 4k pio buffers */
+ u32 ipath_4kalign;
+ /* The MTU programmed for this unit */
+ u32 ipath_ibmtu;
+ /*
+ * The max size IB packet, included IB headers that we can send.
+ * Starts same as ipath_piosize, but is affected when ibmtu is
+ * changed, or by size of eager buffers
+ */
+ u32 ipath_ibmaxlen;
+ /*
+ * ibmaxlen at init time, limited by chip and by receive buffer
+ * size. Not changed after init.
+ */
+ u32 ipath_init_ibmaxlen;
+ /* size of each rcvegrbuffer */
+ u32 ipath_rcvegrbufsize;
+ /* width (2,4,8,16,32) from HT config reg */
+ u32 ipath_htwidth;
+ /* HT speed (200,400,800,1000) from HT config */
+ u32 ipath_htspeed;
+ /* ports waiting for PIOavail intr */
+ unsigned long ipath_portpiowait;
+ /*
+ * number of sequential ibcstatus change for polling active/quiet
+ * (i.e., link not coming up).
+ */
+ u32 ipath_ibpollcnt;
+ /* low and high portions of MSI capability/vector */
+ u32 ipath_msi_lo;
+ /* saved after PCIe init for restore after reset */
+ u32 ipath_msi_hi;
+ /* MSI data (vector) saved for restore */
+ u16 ipath_msi_data;
+ /* MLID programmed for this instance */
+ u16 ipath_mlid;
+ /* LID programmed for this instance */
+ u16 ipath_lid;
+ /* list of pkeys programmed; 0 if not set */
+ u16 ipath_pkeys[4];
+ /* ASCII serial number, from flash */
+ u8 ipath_serial[12];
+ /* human readable board version */
+ u8 ipath_boardversion[80];
+ /* chip major rev, from ipath_revision */
+ u8 ipath_majrev;
+ /* chip minor rev, from ipath_revision */
+ u8 ipath_minrev;
+ /* board rev, from ipath_revision */
+ u8 ipath_boardrev;
+ /* unit # of this chip, if present */
+ int ipath_unit;
+ /* saved for restore after reset */
+ u8 ipath_pci_cacheline;
+ /* LID mask control */
+ u8 ipath_lmc;
+};
+
+extern volatile __le64 *ipath_port0_rcvhdrtail;
+extern dma_addr_t ipath_port0_rcvhdrtail_dma;
+
+#define IPATH_PORT0_RCVHDRTAIL_SIZE PAGE_SIZE
+
+extern struct list_head ipath_dev_list;
+extern spinlock_t ipath_devs_lock;
+extern struct ipath_devdata *ipath_lookup(int unit);
+
+extern u16 ipath_layer_rcv_opcode;
+extern int __ipath_layer_intr(struct ipath_devdata *, u32);
+extern int ipath_layer_intr(struct ipath_devdata *, u32);
+extern int __ipath_layer_rcv(struct ipath_devdata *, void *,
+ struct sk_buff *);
+extern int __ipath_layer_rcv_lid(struct ipath_devdata *, void *);
+extern int __ipath_verbs_piobufavail(struct ipath_devdata *);
+extern int __ipath_verbs_rcv(struct ipath_devdata *, void *, void *, u32);
+
+void ipath_layer_add(struct ipath_devdata *);
+void ipath_layer_del(struct ipath_devdata *);
+
+int ipath_init_chip(struct ipath_devdata *, int);
+int ipath_enable_wc(struct ipath_devdata *dd);
+void ipath_disable_wc(struct ipath_devdata *dd);
+int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp);
+void ipath_shutdown_device(struct ipath_devdata *);
+
+struct file_operations;
+int ipath_cdev_init(int minor, char *name, struct file_operations *fops,
+ struct cdev **cdevp, struct class_device **class_devp);
+void ipath_cdev_cleanup(struct cdev **cdevp,
+ struct class_device **class_devp);
+
+int ipath_diag_init(void);
+void ipath_diag_cleanup(void);
+void ipath_diag_bringup_link(struct ipath_devdata *);
+
+extern wait_queue_head_t ipath_sma_state_wait;
+
+int ipath_user_add(struct ipath_devdata *dd);
+void ipath_user_del(struct ipath_devdata *dd);
+
+struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, gfp_t);
+
+extern int ipath_diag_inuse;
+
+irqreturn_t ipath_intr(int irq, void *devid, struct pt_regs *regs);
+void ipath_decode_err(char *buf, size_t blen, ipath_err_t err);
+#if __IPATH_INFO || __IPATH_DBG
+extern const char *ipath_ibcstatus_str[];
+#endif
+
+/* clean up any per-chip chip-specific stuff */
+void ipath_chip_cleanup(struct ipath_devdata *);
+/* clean up any chip type-specific stuff */
+void ipath_chip_done(void);
+
+/* check to see if we have to force ordering for write combining */
+int ipath_unordered_wc(void);
+
+void ipath_disarm_piobufs(struct ipath_devdata *, unsigned first,
+ unsigned cnt);
+
+int ipath_create_rcvhdrq(struct ipath_devdata *, struct ipath_portdata *);
+void ipath_free_pddata(struct ipath_devdata *, u32, int);
+
+int ipath_parse_ushort(const char *str, unsigned short *valp);
+
+int ipath_wait_linkstate(struct ipath_devdata *, u32, int);
+void ipath_set_ib_lstate(struct ipath_devdata *, int);
+void ipath_kreceive(struct ipath_devdata *);
+int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned);
+int ipath_reset_device(int);
+void ipath_get_faststats(unsigned long);
+
+/* for use in system calls, where we want to know device type, etc. */
+#define port_fp(fp) ((struct ipath_portdata *) (fp)->private_data)
+
+/*
+ * values for ipath_flags
+ */
+/* The chip is up and initted */
+#define IPATH_INITTED 0x2
+ /* set if any user code has set kr_rcvhdrsize */
+#define IPATH_RCVHDRSZ_SET 0x4
+ /* The chip is present and valid for accesses */
+#define IPATH_PRESENT 0x8
+ /* HT link0 is only 8 bits wide, ignore upper byte crc
+ * errors, etc. */
+#define IPATH_8BIT_IN_HT0 0x10
+ /* HT link1 is only 8 bits wide, ignore upper byte crc
+ * errors, etc. */
+#define IPATH_8BIT_IN_HT1 0x20
+ /* The link is down */
+#define IPATH_LINKDOWN 0x40
+ /* The link level is up (0x11) */
+#define IPATH_LINKINIT 0x80
+ /* The link is in the armed (0x21) state */
+#define IPATH_LINKARMED 0x100
+ /* The link is in the active (0x31) state */
+#define IPATH_LINKACTIVE 0x200
+ /* link current state is unknown */
+#define IPATH_LINKUNK 0x400
+ /* no IB cable, or no device on IB cable */
+#define IPATH_NOCABLE 0x4000
+ /* Supports port zero per packet receive interrupts via
+ * GPIO */
+#define IPATH_GPIO_INTR 0x8000
+ /* uses the coded 4byte TID, not 8 byte */
+#define IPATH_4BYTE_TID 0x10000
+ /* packet/word counters are 32 bit, else those 4 counters
+ * are 64bit */
+#define IPATH_32BITCOUNTERS 0x20000
+ /* can miss port0 rx interrupts */
+#define IPATH_POLL_RX_INTR 0x40000
+#define IPATH_DISABLED 0x80000 /* administratively disabled */
+
+/* portdata flag bit offsets */
+ /* waiting for a packet to arrive */
+#define IPATH_PORT_WAITING_RCV 2
+ /* waiting for a PIO buffer to be available */
+#define IPATH_PORT_WAITING_PIO 3
+
+/* free up any allocated data at closes */
+void ipath_free_data(struct ipath_portdata *dd);
+int ipath_waitfor_mdio_cmdready(struct ipath_devdata *);
+int ipath_waitfor_complete(struct ipath_devdata *, ipath_kreg, u64, u64 *);
+u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *);
+/* init PE-800-specific func */
+void ipath_init_pe800_funcs(struct ipath_devdata *);
+/* init HT-400-specific func */
+void ipath_init_ht400_funcs(struct ipath_devdata *);
+void ipath_get_eeprom_info(struct ipath_devdata *);
+u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg);
+
+/*
+ * number of words used for protocol header if not set by ipath_userinit();
+ */
+#define IPATH_DFLT_RCVHDRSIZE 9
+
+#define IPATH_MDIO_CMD_WRITE 1
+#define IPATH_MDIO_CMD_READ 2
+#define IPATH_MDIO_CLD_DIV 25 /* to get 2.5 Mhz mdio clock */
+#define IPATH_MDIO_CMDVALID 0x40000000 /* bit 30 */
+#define IPATH_MDIO_DATAVALID 0x80000000 /* bit 31 */
+#define IPATH_MDIO_CTRL_STD 0x0
+
+static inline u64 ipath_mdio_req(int cmd, int dev, int reg, int data)
+{
+ return (((u64) IPATH_MDIO_CLD_DIV) << 32) |
+ (cmd << 26) |
+ (dev << 21) |
+ (reg << 16) |
+ (data & 0xFFFF);
+}
+
+ /* signal and fifo status, in bank 31 */
+#define IPATH_MDIO_CTRL_XGXS_REG_8 0x8
+ /* controls loopback, redundancy */
+#define IPATH_MDIO_CTRL_8355_REG_1 0x10
+ /* premph, encdec, etc. */
+#define IPATH_MDIO_CTRL_8355_REG_2 0x11
+ /* Kchars, etc. */
+#define IPATH_MDIO_CTRL_8355_REG_6 0x15
+#define IPATH_MDIO_CTRL_8355_REG_9 0x18
+#define IPATH_MDIO_CTRL_8355_REG_10 0x1D
+
+int ipath_get_user_pages(unsigned long, size_t, struct page **);
+int ipath_get_user_pages_nocopy(unsigned long, struct page **);
+void ipath_release_user_pages(struct page **, size_t);
+void ipath_release_user_pages_on_close(struct page **, size_t);
+int ipath_eeprom_read(struct ipath_devdata *, u8, void *, int);
+int ipath_eeprom_write(struct ipath_devdata *, u8, const void *, int);
+
+/* these are used for the registers that vary with port */
+void ipath_write_kreg_port(const struct ipath_devdata *, ipath_kreg,
+ unsigned, u64);
+u64 ipath_read_kreg64_port(const struct ipath_devdata *, ipath_kreg,
+ unsigned);
+
+/*
+ * We could have a single register get/put routine, that takes a group type,
+ * but this is somewhat clearer and cleaner. It also gives us some error
+ * checking. 64 bit register reads should always work, but are inefficient
+ * on opteron (the northbridge always generates 2 separate HT 32 bit reads),
+ * so we use kreg32 wherever possible. User register and counter register
+ * reads are always 32 bit reads, so only one form of those routines.
+ */
+
+/*
+ * At the moment, none of the s-registers are writable, so no
+ * ipath_write_sreg(), and none of the c-registers are writable, so no
+ * ipath_write_creg().
+ */
+
+/**
+ * ipath_read_ureg32 - read 32-bit virtualized per-port register
+ * @dd: device
+ * @regno: register number
+ * @port: port number
+ *
+ * Return the contents of a register that is virtualized to be per port.
+ * Prints a debug message and returns -1 on errors (not distinguishable from
+ * valid contents at runtime; we may add a separate error variable at some
+ * point).
+ *
+ * This is normally not used by the kernel, but may be for debugging, and
+ * has a different implementation than user mode, which is why it's not in
+ * _common.h.
+ */
+static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd,
+ ipath_ureg regno, int port)
+{
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT))
+ return 0;
+
+ return readl(regno + (u64 __iomem *)
+ (dd->ipath_uregbase +
+ (char __iomem *)dd->ipath_kregbase +
+ dd->ipath_palign * port));
+}
+
+/**
+ * ipath_write_ureg - write 32-bit virtualized per-port register
+ * @dd: device
+ * @regno: register number
+ * @value: value
+ * @port: port
+ *
+ * Write the contents of a register that is virtualized to be per port.
+ */
+static inline void ipath_write_ureg(const struct ipath_devdata *dd,
+ ipath_ureg regno, u64 value, int port)
+{
+ u64 __iomem *ubase = (u64 __iomem *)
+ (dd->ipath_uregbase + (char __iomem *) dd->ipath_kregbase +
+ dd->ipath_palign * port);
+ if (dd->ipath_kregbase)
+ writeq(value, &ubase[regno]);
+}
+
+static inline u32 ipath_read_kreg32(const struct ipath_devdata *dd,
+ ipath_kreg regno)
+{
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT))
+ return -1;
+ return readl((u32 __iomem *) & dd->ipath_kregbase[regno]);
+}
+
+static inline u64 ipath_read_kreg64(const struct ipath_devdata *dd,
+ ipath_kreg regno)
+{
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT))
+ return -1;
+
+ return readq(&dd->ipath_kregbase[regno]);
+}
+
+static inline void ipath_write_kreg(const struct ipath_devdata *dd,
+ ipath_kreg regno, u64 value)
+{
+ if (dd->ipath_kregbase)
+ writeq(value, &dd->ipath_kregbase[regno]);
+}
+
+static inline u64 ipath_read_creg(const struct ipath_devdata *dd,
+ ipath_sreg regno)
+{
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT))
+ return 0;
+
+ return readq(regno + (u64 __iomem *)
+ (dd->ipath_cregbase +
+ (char __iomem *)dd->ipath_kregbase));
+}
+
+static inline u32 ipath_read_creg32(const struct ipath_devdata *dd,
+ ipath_sreg regno)
+{
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT))
+ return 0;
+ return readl(regno + (u64 __iomem *)
+ (dd->ipath_cregbase +
+ (char __iomem *)dd->ipath_kregbase));
+}
+
+/*
+ * sysfs interface.
+ */
+
+struct device_driver;
+
+extern const char ipath_core_version[];
+
+int ipath_driver_create_group(struct device_driver *);
+void ipath_driver_remove_group(struct device_driver *);
+
+int ipath_device_create_group(struct device *, struct ipath_devdata *);
+void ipath_device_remove_group(struct device *, struct ipath_devdata *);
+int ipath_expose_reset(struct device *);
+
+int ipath_init_ipathfs(void);
+void ipath_exit_ipathfs(void);
+int ipathfs_add_device(struct ipath_devdata *);
+int ipathfs_remove_device(struct ipath_devdata *);
+
+/*
+ * Flush write combining store buffers (if present) and perform a write
+ * barrier.
+ */
+#if defined(CONFIG_X86_64)
+#define ipath_flush_wc() asm volatile("sfence" ::: "memory")
+#else
+#define ipath_flush_wc() wmb()
+#endif
+
+extern unsigned ipath_debug; /* debugging bit mask */
+
+const char *ipath_get_unit_name(int unit);
+
+extern struct mutex ipath_mutex;
+
+#define IPATH_DRV_NAME "ipath_core"
+#define IPATH_MAJOR 233
+#define IPATH_SMA_MINOR 128
+#define IPATH_DIAG_MINOR 129
+#define IPATH_NMINORS 130
+
+#define ipath_dev_err(dd,fmt,...) \
+ do { \
+ const struct ipath_devdata *__dd = (dd); \
+ if (__dd->pcidev) \
+ dev_err(&__dd->pcidev->dev, "%s: " fmt, \
+ ipath_get_unit_name(__dd->ipath_unit), \
+ ##__VA_ARGS__); \
+ else \
+ printk(KERN_ERR IPATH_DRV_NAME ": %s: " fmt, \
+ ipath_get_unit_name(__dd->ipath_unit), \
+ ##__VA_ARGS__); \
+ } while (0)
+
+#if _IPATH_DEBUGGING
+
+# define __IPATH_DBG_WHICH(which,fmt,...) \
+ do { \
+ if(unlikely(ipath_debug&(which))) \
+ printk(KERN_DEBUG IPATH_DRV_NAME ": %s: " fmt, \
+ __func__,##__VA_ARGS__); \
+ } while(0)
+
+# define ipath_dbg(fmt,...) \
+ __IPATH_DBG_WHICH(__IPATH_DBG,fmt,##__VA_ARGS__)
+# define ipath_cdbg(which,fmt,...) \
+ __IPATH_DBG_WHICH(__IPATH_##which##DBG,fmt,##__VA_ARGS__)
+
+#else /* ! _IPATH_DEBUGGING */
+
+# define ipath_dbg(fmt,...)
+# define ipath_cdbg(which,fmt,...)
+
+#endif /* _IPATH_DEBUGGING */
+
+#endif /* _IPATH_KERNEL_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c
new file mode 100644
index 00000000000..5ae8761f9dd
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_keys.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <asm/io.h>
+
+#include "ipath_verbs.h"
+
+/**
+ * ipath_alloc_lkey - allocate an lkey
+ * @rkt: lkey table in which to allocate the lkey
+ * @mr: memory region that this lkey protects
+ *
+ * Returns 1 if successful, otherwise returns 0.
+ */
+
+int ipath_alloc_lkey(struct ipath_lkey_table *rkt, struct ipath_mregion *mr)
+{
+ unsigned long flags;
+ u32 r;
+ u32 n;
+ int ret;
+
+ spin_lock_irqsave(&rkt->lock, flags);
+
+ /* Find the next available LKEY */
+ r = n = rkt->next;
+ for (;;) {
+ if (rkt->table[r] == NULL)
+ break;
+ r = (r + 1) & (rkt->max - 1);
+ if (r == n) {
+ spin_unlock_irqrestore(&rkt->lock, flags);
+ _VERBS_INFO("LKEY table full\n");
+ ret = 0;
+ goto bail;
+ }
+ }
+ rkt->next = (r + 1) & (rkt->max - 1);
+ /*
+ * Make sure lkey is never zero which is reserved to indicate an
+ * unrestricted LKEY.
+ */
+ rkt->gen++;
+ mr->lkey = (r << (32 - ib_ipath_lkey_table_size)) |
+ ((((1 << (24 - ib_ipath_lkey_table_size)) - 1) & rkt->gen)
+ << 8);
+ if (mr->lkey == 0) {
+ mr->lkey |= 1 << 8;
+ rkt->gen++;
+ }
+ rkt->table[r] = mr;
+ spin_unlock_irqrestore(&rkt->lock, flags);
+
+ ret = 1;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_free_lkey - free an lkey
+ * @rkt: table from which to free the lkey
+ * @lkey: lkey id to free
+ */
+void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey)
+{
+ unsigned long flags;
+ u32 r;
+
+ if (lkey == 0)
+ return;
+ r = lkey >> (32 - ib_ipath_lkey_table_size);
+ spin_lock_irqsave(&rkt->lock, flags);
+ rkt->table[r] = NULL;
+ spin_unlock_irqrestore(&rkt->lock, flags);
+}
+
+/**
+ * ipath_lkey_ok - check IB SGE for validity and initialize
+ * @rkt: table containing lkey to check SGE against
+ * @isge: outgoing internal SGE
+ * @sge: SGE to check
+ * @acc: access flags
+ *
+ * Return 1 if valid and successful, otherwise returns 0.
+ *
+ * Check the IB SGE for validity and initialize our internal version
+ * of it.
+ */
+int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
+ struct ib_sge *sge, int acc)
+{
+ struct ipath_mregion *mr;
+ size_t off;
+ int ret;
+
+ /*
+ * We use LKEY == zero to mean a physical kmalloc() address.
+ * This is a bit of a hack since we rely on dma_map_single()
+ * being reversible by calling bus_to_virt().
+ */
+ if (sge->lkey == 0) {
+ isge->mr = NULL;
+ isge->vaddr = bus_to_virt(sge->addr);
+ isge->length = sge->length;
+ isge->sge_length = sge->length;
+ ret = 1;
+ goto bail;
+ }
+ mr = rkt->table[(sge->lkey >> (32 - ib_ipath_lkey_table_size))];
+ if (unlikely(mr == NULL || mr->lkey != sge->lkey)) {
+ ret = 0;
+ goto bail;
+ }
+
+ off = sge->addr - mr->user_base;
+ if (unlikely(sge->addr < mr->user_base ||
+ off + sge->length > mr->length ||
+ (mr->access_flags & acc) != acc)) {
+ ret = 0;
+ goto bail;
+ }
+
+ off += mr->offset;
+ isge->mr = mr;
+ isge->m = 0;
+ isge->n = 0;
+ while (off >= mr->map[isge->m]->segs[isge->n].length) {
+ off -= mr->map[isge->m]->segs[isge->n].length;
+ isge->n++;
+ if (isge->n >= IPATH_SEGSZ) {
+ isge->m++;
+ isge->n = 0;
+ }
+ }
+ isge->vaddr = mr->map[isge->m]->segs[isge->n].vaddr + off;
+ isge->length = mr->map[isge->m]->segs[isge->n].length - off;
+ isge->sge_length = sge->length;
+
+ ret = 1;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_rkey_ok - check the IB virtual address, length, and RKEY
+ * @dev: infiniband device
+ * @ss: SGE state
+ * @len: length of data
+ * @vaddr: virtual address to place data
+ * @rkey: rkey to check
+ * @acc: access flags
+ *
+ * Return 1 if successful, otherwise 0.
+ */
+int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
+ u32 len, u64 vaddr, u32 rkey, int acc)
+{
+ struct ipath_lkey_table *rkt = &dev->lk_table;
+ struct ipath_sge *sge = &ss->sge;
+ struct ipath_mregion *mr;
+ size_t off;
+ int ret;
+
+ mr = rkt->table[(rkey >> (32 - ib_ipath_lkey_table_size))];
+ if (unlikely(mr == NULL || mr->lkey != rkey)) {
+ ret = 0;
+ goto bail;
+ }
+
+ off = vaddr - mr->iova;
+ if (unlikely(vaddr < mr->iova || off + len > mr->length ||
+ (mr->access_flags & acc) == 0)) {
+ ret = 0;
+ goto bail;
+ }
+
+ off += mr->offset;
+ sge->mr = mr;
+ sge->m = 0;
+ sge->n = 0;
+ while (off >= mr->map[sge->m]->segs[sge->n].length) {
+ off -= mr->map[sge->m]->segs[sge->n].length;
+ sge->n++;
+ if (sge->n >= IPATH_SEGSZ) {
+ sge->m++;
+ sge->n = 0;
+ }
+ }
+ sge->vaddr = mr->map[sge->m]->segs[sge->n].vaddr + off;
+ sge->length = mr->map[sge->m]->segs[sge->n].length - off;
+ sge->sge_length = len;
+ ss->sg_list = NULL;
+ ss->num_sge = 1;
+
+ ret = 1;
+
+bail:
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c
new file mode 100644
index 00000000000..9ec4ac77b87
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_layer.c
@@ -0,0 +1,1521 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * These are the routines used by layered drivers, currently just the
+ * layered ethernet driver and verbs layer.
+ */
+
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <asm/byteorder.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+/* Acquire before ipath_devs_lock. */
+static DEFINE_MUTEX(ipath_layer_mutex);
+
+static int ipath_verbs_registered;
+
+u16 ipath_layer_rcv_opcode;
+
+static int (*layer_intr)(void *, u32);
+static int (*layer_rcv)(void *, void *, struct sk_buff *);
+static int (*layer_rcv_lid)(void *, void *);
+static int (*verbs_piobufavail)(void *);
+static void (*verbs_rcv)(void *, void *, void *, u32);
+
+static void *(*layer_add_one)(int, struct ipath_devdata *);
+static void (*layer_remove_one)(void *);
+static void *(*verbs_add_one)(int, struct ipath_devdata *);
+static void (*verbs_remove_one)(void *);
+static void (*verbs_timer_cb)(void *);
+
+int __ipath_layer_intr(struct ipath_devdata *dd, u32 arg)
+{
+ int ret = -ENODEV;
+
+ if (dd->ipath_layer.l_arg && layer_intr)
+ ret = layer_intr(dd->ipath_layer.l_arg, arg);
+
+ return ret;
+}
+
+int ipath_layer_intr(struct ipath_devdata *dd, u32 arg)
+{
+ int ret;
+
+ mutex_lock(&ipath_layer_mutex);
+
+ ret = __ipath_layer_intr(dd, arg);
+
+ mutex_unlock(&ipath_layer_mutex);
+
+ return ret;
+}
+
+int __ipath_layer_rcv(struct ipath_devdata *dd, void *hdr,
+ struct sk_buff *skb)
+{
+ int ret = -ENODEV;
+
+ if (dd->ipath_layer.l_arg && layer_rcv)
+ ret = layer_rcv(dd->ipath_layer.l_arg, hdr, skb);
+
+ return ret;
+}
+
+int __ipath_layer_rcv_lid(struct ipath_devdata *dd, void *hdr)
+{
+ int ret = -ENODEV;
+
+ if (dd->ipath_layer.l_arg && layer_rcv_lid)
+ ret = layer_rcv_lid(dd->ipath_layer.l_arg, hdr);
+
+ return ret;
+}
+
+int __ipath_verbs_piobufavail(struct ipath_devdata *dd)
+{
+ int ret = -ENODEV;
+
+ if (dd->verbs_layer.l_arg && verbs_piobufavail)
+ ret = verbs_piobufavail(dd->verbs_layer.l_arg);
+
+ return ret;
+}
+
+int __ipath_verbs_rcv(struct ipath_devdata *dd, void *rc, void *ebuf,
+ u32 tlen)
+{
+ int ret = -ENODEV;
+
+ if (dd->verbs_layer.l_arg && verbs_rcv) {
+ verbs_rcv(dd->verbs_layer.l_arg, rc, ebuf, tlen);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+int ipath_layer_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+{
+ u32 lstate;
+ int ret;
+
+ switch (newstate) {
+ case IPATH_IB_LINKDOWN:
+ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL <<
+ INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+ /* don't wait */
+ ret = 0;
+ goto bail;
+
+ case IPATH_IB_LINKDOWN_SLEEP:
+ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_SLEEP <<
+ INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+ /* don't wait */
+ ret = 0;
+ goto bail;
+
+ case IPATH_IB_LINKDOWN_DISABLE:
+ ipath_set_ib_lstate(dd,
+ INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+ INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+ /* don't wait */
+ ret = 0;
+ goto bail;
+
+ case IPATH_IB_LINKINIT:
+ if (dd->ipath_flags & IPATH_LINKINIT) {
+ ret = 0;
+ goto bail;
+ }
+ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_INIT <<
+ INFINIPATH_IBCC_LINKCMD_SHIFT);
+ lstate = IPATH_LINKINIT;
+ break;
+
+ case IPATH_IB_LINKARM:
+ if (dd->ipath_flags & IPATH_LINKARMED) {
+ ret = 0;
+ goto bail;
+ }
+ if (!(dd->ipath_flags &
+ (IPATH_LINKINIT | IPATH_LINKACTIVE))) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED <<
+ INFINIPATH_IBCC_LINKCMD_SHIFT);
+ /*
+ * Since the port can transition to ACTIVE by receiving
+ * a non VL 15 packet, wait for either state.
+ */
+ lstate = IPATH_LINKARMED | IPATH_LINKACTIVE;
+ break;
+
+ case IPATH_IB_LINKACTIVE:
+ if (dd->ipath_flags & IPATH_LINKACTIVE) {
+ ret = 0;
+ goto bail;
+ }
+ if (!(dd->ipath_flags & IPATH_LINKARMED)) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE <<
+ INFINIPATH_IBCC_LINKCMD_SHIFT);
+ lstate = IPATH_LINKACTIVE;
+ break;
+
+ default:
+ ipath_dbg("Invalid linkstate 0x%x requested\n", newstate);
+ ret = -EINVAL;
+ goto bail;
+ }
+ ret = ipath_wait_linkstate(dd, lstate, 2000);
+
+bail:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_linkstate);
+
+/**
+ * ipath_layer_set_mtu - set the MTU
+ * @dd: the infinipath device
+ * @arg: the new MTU
+ *
+ * we can handle "any" incoming size, the issue here is whether we
+ * need to restrict our outgoing size. For now, we don't do any
+ * sanity checking on this, and we don't deal with what happens to
+ * programs that are already running when the size changes.
+ * NOTE: changing the MTU will usually cause the IBC to go back to
+ * link initialize (IPATH_IBSTATE_INIT) state...
+ */
+int ipath_layer_set_mtu(struct ipath_devdata *dd, u16 arg)
+{
+ u32 piosize;
+ int changed = 0;
+ int ret;
+
+ /*
+ * mtu is IB data payload max. It's the largest power of 2 less
+ * than piosize (or even larger, since it only really controls the
+ * largest we can receive; we can send the max of the mtu and
+ * piosize). We check that it's one of the valid IB sizes.
+ */
+ if (arg != 256 && arg != 512 && arg != 1024 && arg != 2048 &&
+ arg != 4096) {
+ ipath_dbg("Trying to set invalid mtu %u, failing\n", arg);
+ ret = -EINVAL;
+ goto bail;
+ }
+ if (dd->ipath_ibmtu == arg) {
+ ret = 0; /* same as current */
+ goto bail;
+ }
+
+ piosize = dd->ipath_ibmaxlen;
+ dd->ipath_ibmtu = arg;
+
+ if (arg >= (piosize - IPATH_PIO_MAXIBHDR)) {
+ /* Only if it's not the initial value (or reset to it) */
+ if (piosize != dd->ipath_init_ibmaxlen) {
+ dd->ipath_ibmaxlen = piosize;
+ changed = 1;
+ }
+ } else if ((arg + IPATH_PIO_MAXIBHDR) != dd->ipath_ibmaxlen) {
+ piosize = arg + IPATH_PIO_MAXIBHDR;
+ ipath_cdbg(VERBOSE, "ibmaxlen was 0x%x, setting to 0x%x "
+ "(mtu 0x%x)\n", dd->ipath_ibmaxlen, piosize,
+ arg);
+ dd->ipath_ibmaxlen = piosize;
+ changed = 1;
+ }
+
+ if (changed) {
+ /*
+ * set the IBC maxpktlength to the size of our pio
+ * buffers in words
+ */
+ u64 ibc = dd->ipath_ibcctrl;
+ ibc &= ~(INFINIPATH_IBCC_MAXPKTLEN_MASK <<
+ INFINIPATH_IBCC_MAXPKTLEN_SHIFT);
+
+ piosize = piosize - 2 * sizeof(u32); /* ignore pbc */
+ dd->ipath_ibmaxlen = piosize;
+ piosize /= sizeof(u32); /* in words */
+ /*
+ * for ICRC, which we only send in diag test pkt mode, and
+ * we don't need to worry about that for mtu
+ */
+ piosize += 1;
+
+ ibc |= piosize << INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
+ dd->ipath_ibcctrl = ibc;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl);
+ dd->ipath_f_tidtemplate(dd);
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_mtu);
+
+int ipath_set_sps_lid(struct ipath_devdata *dd, u32 arg, u8 lmc)
+{
+ ipath_stats.sps_lid[dd->ipath_unit] = arg;
+ dd->ipath_lid = arg;
+ dd->ipath_lmc = lmc;
+
+ mutex_lock(&ipath_layer_mutex);
+
+ if (dd->ipath_layer.l_arg && layer_intr)
+ layer_intr(dd->ipath_layer.l_arg, IPATH_LAYER_INT_LID);
+
+ mutex_unlock(&ipath_layer_mutex);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_set_sps_lid);
+
+int ipath_layer_set_guid(struct ipath_devdata *dd, __be64 guid)
+{
+ /* XXX - need to inform anyone who cares this just happened. */
+ dd->ipath_guid = guid;
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_guid);
+
+__be64 ipath_layer_get_guid(struct ipath_devdata *dd)
+{
+ return dd->ipath_guid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_guid);
+
+u32 ipath_layer_get_nguid(struct ipath_devdata *dd)
+{
+ return dd->ipath_nguid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_nguid);
+
+int ipath_layer_query_device(struct ipath_devdata *dd, u32 * vendor,
+ u32 * boardrev, u32 * majrev, u32 * minrev)
+{
+ *vendor = dd->ipath_vendorid;
+ *boardrev = dd->ipath_boardrev;
+ *majrev = dd->ipath_majrev;
+ *minrev = dd->ipath_minrev;
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_query_device);
+
+u32 ipath_layer_get_flags(struct ipath_devdata *dd)
+{
+ return dd->ipath_flags;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_flags);
+
+struct device *ipath_layer_get_device(struct ipath_devdata *dd)
+{
+ return &dd->pcidev->dev;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_device);
+
+u16 ipath_layer_get_deviceid(struct ipath_devdata *dd)
+{
+ return dd->ipath_deviceid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_deviceid);
+
+u64 ipath_layer_get_lastibcstat(struct ipath_devdata *dd)
+{
+ return dd->ipath_lastibcstat;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_lastibcstat);
+
+u32 ipath_layer_get_ibmtu(struct ipath_devdata *dd)
+{
+ return dd->ipath_ibmtu;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_ibmtu);
+
+void ipath_layer_add(struct ipath_devdata *dd)
+{
+ mutex_lock(&ipath_layer_mutex);
+
+ if (layer_add_one)
+ dd->ipath_layer.l_arg =
+ layer_add_one(dd->ipath_unit, dd);
+
+ if (verbs_add_one)
+ dd->verbs_layer.l_arg =
+ verbs_add_one(dd->ipath_unit, dd);
+
+ mutex_unlock(&ipath_layer_mutex);
+}
+
+void ipath_layer_del(struct ipath_devdata *dd)
+{
+ mutex_lock(&ipath_layer_mutex);
+
+ if (dd->ipath_layer.l_arg && layer_remove_one) {
+ layer_remove_one(dd->ipath_layer.l_arg);
+ dd->ipath_layer.l_arg = NULL;
+ }
+
+ if (dd->verbs_layer.l_arg && verbs_remove_one) {
+ verbs_remove_one(dd->verbs_layer.l_arg);
+ dd->verbs_layer.l_arg = NULL;
+ }
+
+ mutex_unlock(&ipath_layer_mutex);
+}
+
+int ipath_layer_register(void *(*l_add)(int, struct ipath_devdata *),
+ void (*l_remove)(void *),
+ int (*l_intr)(void *, u32),
+ int (*l_rcv)(void *, void *, struct sk_buff *),
+ u16 l_rcv_opcode,
+ int (*l_rcv_lid)(void *, void *))
+{
+ struct ipath_devdata *dd, *tmp;
+ unsigned long flags;
+
+ mutex_lock(&ipath_layer_mutex);
+
+ layer_add_one = l_add;
+ layer_remove_one = l_remove;
+ layer_intr = l_intr;
+ layer_rcv = l_rcv;
+ layer_rcv_lid = l_rcv_lid;
+ ipath_layer_rcv_opcode = l_rcv_opcode;
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ if (!(dd->ipath_flags & IPATH_INITTED))
+ continue;
+
+ if (dd->ipath_layer.l_arg)
+ continue;
+
+ if (!(*dd->ipath_statusp & IPATH_STATUS_SMA))
+ *dd->ipath_statusp |= IPATH_STATUS_OIB_SMA;
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ dd->ipath_layer.l_arg = l_add(dd->ipath_unit, dd);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ mutex_unlock(&ipath_layer_mutex);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_register);
+
+void ipath_layer_unregister(void)
+{
+ struct ipath_devdata *dd, *tmp;
+ unsigned long flags;
+
+ mutex_lock(&ipath_layer_mutex);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ if (dd->ipath_layer.l_arg && layer_remove_one) {
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ layer_remove_one(dd->ipath_layer.l_arg);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ dd->ipath_layer.l_arg = NULL;
+ }
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ layer_add_one = NULL;
+ layer_remove_one = NULL;
+ layer_intr = NULL;
+ layer_rcv = NULL;
+ layer_rcv_lid = NULL;
+
+ mutex_unlock(&ipath_layer_mutex);
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_unregister);
+
+static void __ipath_verbs_timer(unsigned long arg)
+{
+ struct ipath_devdata *dd = (struct ipath_devdata *) arg;
+
+ /*
+ * If port 0 receive packet interrupts are not available, or
+ * can be missed, poll the receive queue
+ */
+ if (dd->ipath_flags & IPATH_POLL_RX_INTR)
+ ipath_kreceive(dd);
+
+ /* Handle verbs layer timeouts. */
+ if (dd->verbs_layer.l_arg && verbs_timer_cb)
+ verbs_timer_cb(dd->verbs_layer.l_arg);
+
+ mod_timer(&dd->verbs_layer.l_timer, jiffies + 1);
+}
+
+/**
+ * ipath_verbs_register - verbs layer registration
+ * @l_piobufavail: callback for when PIO buffers become available
+ * @l_rcv: callback for receiving a packet
+ * @l_timer_cb: timer callback
+ * @ipath_devdata: device data structure is put here
+ */
+int ipath_verbs_register(void *(*l_add)(int, struct ipath_devdata *),
+ void (*l_remove)(void *arg),
+ int (*l_piobufavail) (void *arg),
+ void (*l_rcv) (void *arg, void *rhdr,
+ void *data, u32 tlen),
+ void (*l_timer_cb) (void *arg))
+{
+ struct ipath_devdata *dd, *tmp;
+ unsigned long flags;
+
+ mutex_lock(&ipath_layer_mutex);
+
+ verbs_add_one = l_add;
+ verbs_remove_one = l_remove;
+ verbs_piobufavail = l_piobufavail;
+ verbs_rcv = l_rcv;
+ verbs_timer_cb = l_timer_cb;
+
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ if (!(dd->ipath_flags & IPATH_INITTED))
+ continue;
+
+ if (dd->verbs_layer.l_arg)
+ continue;
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ dd->verbs_layer.l_arg = l_add(dd->ipath_unit, dd);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ mutex_unlock(&ipath_layer_mutex);
+
+ ipath_verbs_registered = 1;
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_verbs_register);
+
+void ipath_verbs_unregister(void)
+{
+ struct ipath_devdata *dd, *tmp;
+ unsigned long flags;
+
+ mutex_lock(&ipath_layer_mutex);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+
+ list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+ *dd->ipath_statusp &= ~IPATH_STATUS_OIB_SMA;
+
+ if (dd->verbs_layer.l_arg && verbs_remove_one) {
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+ verbs_remove_one(dd->verbs_layer.l_arg);
+ spin_lock_irqsave(&ipath_devs_lock, flags);
+ dd->verbs_layer.l_arg = NULL;
+ }
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+ verbs_add_one = NULL;
+ verbs_remove_one = NULL;
+ verbs_piobufavail = NULL;
+ verbs_rcv = NULL;
+ verbs_timer_cb = NULL;
+
+ ipath_verbs_registered = 0;
+
+ mutex_unlock(&ipath_layer_mutex);
+}
+
+EXPORT_SYMBOL_GPL(ipath_verbs_unregister);
+
+int ipath_layer_open(struct ipath_devdata *dd, u32 * pktmax)
+{
+ int ret;
+ u32 intval = 0;
+
+ mutex_lock(&ipath_layer_mutex);
+
+ if (!dd->ipath_layer.l_arg) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ ret = ipath_setrcvhdrsize(dd, NUM_OF_EXTRA_WORDS_IN_HEADER_QUEUE);
+
+ if (ret < 0)
+ goto bail;
+
+ *pktmax = dd->ipath_ibmaxlen;
+
+ if (*dd->ipath_statusp & IPATH_STATUS_IB_READY)
+ intval |= IPATH_LAYER_INT_IF_UP;
+ if (ipath_stats.sps_lid[dd->ipath_unit])
+ intval |= IPATH_LAYER_INT_LID;
+ if (ipath_stats.sps_mlid[dd->ipath_unit])
+ intval |= IPATH_LAYER_INT_BCAST;
+ /*
+ * do this on open, in case low level is already up and
+ * just layered driver was reloaded, etc.
+ */
+ if (intval)
+ layer_intr(dd->ipath_layer.l_arg, intval);
+
+ ret = 0;
+bail:
+ mutex_unlock(&ipath_layer_mutex);
+
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_open);
+
+u16 ipath_layer_get_lid(struct ipath_devdata *dd)
+{
+ return dd->ipath_lid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_lid);
+
+/**
+ * ipath_layer_get_mac - get the MAC address
+ * @dd: the infinipath device
+ * @mac: the MAC is put here
+ *
+ * This is the EUID-64 OUI octets (top 3), then
+ * skip the next 2 (which should both be zero or 0xff).
+ * The returned MAC is in network order
+ * mac points to at least 6 bytes of buffer
+ * We assume that by the time the LID is set, that the GUID is as valid
+ * as it's ever going to be, rather than adding yet another status bit.
+ */
+
+int ipath_layer_get_mac(struct ipath_devdata *dd, u8 * mac)
+{
+ u8 *guid;
+
+ guid = (u8 *) &dd->ipath_guid;
+
+ mac[0] = guid[0];
+ mac[1] = guid[1];
+ mac[2] = guid[2];
+ mac[3] = guid[5];
+ mac[4] = guid[6];
+ mac[5] = guid[7];
+ if ((guid[3] || guid[4]) && !(guid[3] == 0xff && guid[4] == 0xff))
+ ipath_dbg("Warning, guid bytes 3 and 4 not 0 or 0xffff: "
+ "%x %x\n", guid[3], guid[4]);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_mac);
+
+u16 ipath_layer_get_bcast(struct ipath_devdata *dd)
+{
+ return dd->ipath_mlid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_bcast);
+
+u32 ipath_layer_get_cr_errpkey(struct ipath_devdata *dd)
+{
+ return ipath_read_creg32(dd, dd->ipath_cregs->cr_errpkey);
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_cr_errpkey);
+
+static void update_sge(struct ipath_sge_state *ss, u32 length)
+{
+ struct ipath_sge *sge = &ss->sge;
+
+ sge->vaddr += length;
+ sge->length -= length;
+ sge->sge_length -= length;
+ if (sge->sge_length == 0) {
+ if (--ss->num_sge)
+ *sge = *ss->sg_list++;
+ } else if (sge->length == 0 && sge->mr != NULL) {
+ if (++sge->n >= IPATH_SEGSZ) {
+ if (++sge->m >= sge->mr->mapsz)
+ return;
+ sge->n = 0;
+ }
+ sge->vaddr = sge->mr->map[sge->m]->segs[sge->n].vaddr;
+ sge->length = sge->mr->map[sge->m]->segs[sge->n].length;
+ }
+}
+
+#ifdef __LITTLE_ENDIAN
+static inline u32 get_upper_bits(u32 data, u32 shift)
+{
+ return data >> shift;
+}
+
+static inline u32 set_upper_bits(u32 data, u32 shift)
+{
+ return data << shift;
+}
+
+static inline u32 clear_upper_bytes(u32 data, u32 n, u32 off)
+{
+ data <<= ((sizeof(u32) - n) * BITS_PER_BYTE);
+ data >>= ((sizeof(u32) - n - off) * BITS_PER_BYTE);
+ return data;
+}
+#else
+static inline u32 get_upper_bits(u32 data, u32 shift)
+{
+ return data << shift;
+}
+
+static inline u32 set_upper_bits(u32 data, u32 shift)
+{
+ return data >> shift;
+}
+
+static inline u32 clear_upper_bytes(u32 data, u32 n, u32 off)
+{
+ data >>= ((sizeof(u32) - n) * BITS_PER_BYTE);
+ data <<= ((sizeof(u32) - n - off) * BITS_PER_BYTE);
+ return data;
+}
+#endif
+
+static void copy_io(u32 __iomem *piobuf, struct ipath_sge_state *ss,
+ u32 length)
+{
+ u32 extra = 0;
+ u32 data = 0;
+ u32 last;
+
+ while (1) {
+ u32 len = ss->sge.length;
+ u32 off;
+
+ BUG_ON(len == 0);
+ if (len > length)
+ len = length;
+ if (len > ss->sge.sge_length)
+ len = ss->sge.sge_length;
+ /* If the source address is not aligned, try to align it. */
+ off = (unsigned long)ss->sge.vaddr & (sizeof(u32) - 1);
+ if (off) {
+ u32 *addr = (u32 *)((unsigned long)ss->sge.vaddr &
+ ~(sizeof(u32) - 1));
+ u32 v = get_upper_bits(*addr, off * BITS_PER_BYTE);
+ u32 y;
+
+ y = sizeof(u32) - off;
+ if (len > y)
+ len = y;
+ if (len + extra >= sizeof(u32)) {
+ data |= set_upper_bits(v, extra *
+ BITS_PER_BYTE);
+ len = sizeof(u32) - extra;
+ if (len == length) {
+ last = data;
+ break;
+ }
+ __raw_writel(data, piobuf);
+ piobuf++;
+ extra = 0;
+ data = 0;
+ } else {
+ /* Clear unused upper bytes */
+ data |= clear_upper_bytes(v, len, extra);
+ if (len == length) {
+ last = data;
+ break;
+ }
+ extra += len;
+ }
+ } else if (extra) {
+ /* Source address is aligned. */
+ u32 *addr = (u32 *) ss->sge.vaddr;
+ int shift = extra * BITS_PER_BYTE;
+ int ushift = 32 - shift;
+ u32 l = len;
+
+ while (l >= sizeof(u32)) {
+ u32 v = *addr;
+
+ data |= set_upper_bits(v, shift);
+ __raw_writel(data, piobuf);
+ data = get_upper_bits(v, ushift);
+ piobuf++;
+ addr++;
+ l -= sizeof(u32);
+ }
+ /*
+ * We still have 'extra' number of bytes leftover.
+ */
+ if (l) {
+ u32 v = *addr;
+
+ if (l + extra >= sizeof(u32)) {
+ data |= set_upper_bits(v, shift);
+ len -= l + extra - sizeof(u32);
+ if (len == length) {
+ last = data;
+ break;
+ }
+ __raw_writel(data, piobuf);
+ piobuf++;
+ extra = 0;
+ data = 0;
+ } else {
+ /* Clear unused upper bytes */
+ data |= clear_upper_bytes(v, l,
+ extra);
+ if (len == length) {
+ last = data;
+ break;
+ }
+ extra += l;
+ }
+ } else if (len == length) {
+ last = data;
+ break;
+ }
+ } else if (len == length) {
+ u32 w;
+
+ /*
+ * Need to round up for the last dword in the
+ * packet.
+ */
+ w = (len + 3) >> 2;
+ __iowrite32_copy(piobuf, ss->sge.vaddr, w - 1);
+ piobuf += w - 1;
+ last = ((u32 *) ss->sge.vaddr)[w - 1];
+ break;
+ } else {
+ u32 w = len >> 2;
+
+ __iowrite32_copy(piobuf, ss->sge.vaddr, w);
+ piobuf += w;
+
+ extra = len & (sizeof(u32) - 1);
+ if (extra) {
+ u32 v = ((u32 *) ss->sge.vaddr)[w];
+
+ /* Clear unused upper bytes */
+ data = clear_upper_bytes(v, extra, 0);
+ }
+ }
+ update_sge(ss, len);
+ length -= len;
+ }
+ /* Update address before sending packet. */
+ update_sge(ss, length);
+ /* must flush early everything before trigger word */
+ ipath_flush_wc();
+ __raw_writel(last, piobuf);
+ /* be sure trigger word is written */
+ ipath_flush_wc();
+}
+
+/**
+ * ipath_verbs_send - send a packet from the verbs layer
+ * @dd: the infinipath device
+ * @hdrwords: the number of works in the header
+ * @hdr: the packet header
+ * @len: the length of the packet in bytes
+ * @ss: the SGE to send
+ *
+ * This is like ipath_sma_send_pkt() in that we need to be able to send
+ * packets after the chip is initialized (MADs) but also like
+ * ipath_layer_send_hdr() since its used by the verbs layer.
+ */
+int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords,
+ u32 *hdr, u32 len, struct ipath_sge_state *ss)
+{
+ u32 __iomem *piobuf;
+ u32 plen;
+ int ret;
+
+ /* +1 is for the qword padding of pbc */
+ plen = hdrwords + ((len + 3) >> 2) + 1;
+ if (unlikely((plen << 2) > dd->ipath_ibmaxlen)) {
+ ipath_dbg("packet len 0x%x too long, failing\n", plen);
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ /* Get a PIO buffer to use. */
+ piobuf = ipath_getpiobuf(dd, NULL);
+ if (unlikely(piobuf == NULL)) {
+ ret = -EBUSY;
+ goto bail;
+ }
+
+ /*
+ * Write len to control qword, no flags.
+ * We have to flush after the PBC for correctness on some cpus
+ * or WC buffer can be written out of order.
+ */
+ writeq(plen, piobuf);
+ ipath_flush_wc();
+ piobuf += 2;
+ if (len == 0) {
+ /*
+ * If there is just the header portion, must flush before
+ * writing last word of header for correctness, and after
+ * the last header word (trigger word).
+ */
+ __iowrite32_copy(piobuf, hdr, hdrwords - 1);
+ ipath_flush_wc();
+ __raw_writel(hdr[hdrwords - 1], piobuf + hdrwords - 1);
+ ipath_flush_wc();
+ ret = 0;
+ goto bail;
+ }
+
+ __iowrite32_copy(piobuf, hdr, hdrwords);
+ piobuf += hdrwords;
+
+ /* The common case is aligned and contained in one segment. */
+ if (likely(ss->num_sge == 1 && len <= ss->sge.length &&
+ !((unsigned long)ss->sge.vaddr & (sizeof(u32) - 1)))) {
+ u32 w;
+ u32 *addr = (u32 *) ss->sge.vaddr;
+
+ /* Update address before sending packet. */
+ update_sge(ss, len);
+ /* Need to round up for the last dword in the packet. */
+ w = (len + 3) >> 2;
+ __iowrite32_copy(piobuf, addr, w - 1);
+ /* must flush early everything before trigger word */
+ ipath_flush_wc();
+ __raw_writel(addr[w - 1], piobuf + w - 1);
+ /* be sure trigger word is written */
+ ipath_flush_wc();
+ ret = 0;
+ goto bail;
+ }
+ copy_io(piobuf, ss, len);
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_verbs_send);
+
+int ipath_layer_snapshot_counters(struct ipath_devdata *dd, u64 *swords,
+ u64 *rwords, u64 *spkts, u64 *rpkts,
+ u64 *xmit_wait)
+{
+ int ret;
+
+ if (!(dd->ipath_flags & IPATH_INITTED)) {
+ /* no hardware, freeze, etc. */
+ ipath_dbg("unit %u not usable\n", dd->ipath_unit);
+ ret = -EINVAL;
+ goto bail;
+ }
+ *swords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
+ *rwords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
+ *spkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
+ *rpkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
+ *xmit_wait = ipath_snap_cntr(dd, dd->ipath_cregs->cr_sendstallcnt);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_snapshot_counters);
+
+/**
+ * ipath_layer_get_counters - get various chip counters
+ * @dd: the infinipath device
+ * @cntrs: counters are placed here
+ *
+ * Return the counters needed by recv_pma_get_portcounters().
+ */
+int ipath_layer_get_counters(struct ipath_devdata *dd,
+ struct ipath_layer_counters *cntrs)
+{
+ int ret;
+
+ if (!(dd->ipath_flags & IPATH_INITTED)) {
+ /* no hardware, freeze, etc. */
+ ipath_dbg("unit %u not usable\n", dd->ipath_unit);
+ ret = -EINVAL;
+ goto bail;
+ }
+ cntrs->symbol_error_counter =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_ibsymbolerrcnt);
+ cntrs->link_error_recovery_counter =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt);
+ cntrs->link_downed_counter =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkdowncnt);
+ cntrs->port_rcv_errors =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_rxdroppktcnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvovflcnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_portovflcnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_errrcvflowctrlcnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_err_rlencnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_invalidrlencnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_erricrccnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_errvcrccnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_errlpcrccnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_errlinkcnt) +
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_badformatcnt);
+ cntrs->port_rcv_remphys_errors =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvebpcnt);
+ cntrs->port_xmit_discards =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_unsupvlcnt);
+ cntrs->port_xmit_data =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
+ cntrs->port_rcv_data =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
+ cntrs->port_xmit_packets =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
+ cntrs->port_rcv_packets =
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_counters);
+
+int ipath_layer_want_buffer(struct ipath_devdata *dd)
+{
+ set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_want_buffer);
+
+int ipath_layer_send_hdr(struct ipath_devdata *dd, struct ether_header *hdr)
+{
+ int ret = 0;
+ u32 __iomem *piobuf;
+ u32 plen, *uhdr;
+ size_t count;
+ __be16 vlsllnh;
+
+ if (!(dd->ipath_flags & IPATH_RCVHDRSZ_SET)) {
+ ipath_dbg("send while not open\n");
+ ret = -EINVAL;
+ } else
+ if ((dd->ipath_flags & (IPATH_LINKUNK | IPATH_LINKDOWN)) ||
+ dd->ipath_lid == 0) {
+ /*
+ * lid check is for when sma hasn't yet configured
+ */
+ ret = -ENETDOWN;
+ ipath_cdbg(VERBOSE, "send while not ready, "
+ "mylid=%u, flags=0x%x\n",
+ dd->ipath_lid, dd->ipath_flags);
+ }
+
+ vlsllnh = *((__be16 *) hdr);
+ if (vlsllnh != htons(IPS_LRH_BTH)) {
+ ipath_dbg("Warning: lrh[0] wrong (%x, not %x); "
+ "not sending\n", be16_to_cpu(vlsllnh),
+ IPS_LRH_BTH);
+ ret = -EINVAL;
+ }
+ if (ret)
+ goto done;
+
+ /* Get a PIO buffer to use. */
+ piobuf = ipath_getpiobuf(dd, NULL);
+ if (piobuf == NULL) {
+ ret = -EBUSY;
+ goto done;
+ }
+
+ plen = (sizeof(*hdr) >> 2); /* actual length */
+ ipath_cdbg(EPKT, "0x%x+1w pio %p\n", plen, piobuf);
+
+ writeq(plen+1, piobuf); /* len (+1 for pad) to pbc, no flags */
+ ipath_flush_wc();
+ piobuf += 2;
+ uhdr = (u32 *)hdr;
+ count = plen-1; /* amount we can copy before trigger word */
+ __iowrite32_copy(piobuf, uhdr, count);
+ ipath_flush_wc();
+ __raw_writel(uhdr[count], piobuf + count);
+ ipath_flush_wc(); /* ensure it's sent, now */
+
+ ipath_stats.sps_ether_spkts++; /* ether packet sent */
+
+done:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_send_hdr);
+
+int ipath_layer_set_piointbufavail_int(struct ipath_devdata *dd)
+{
+ set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_piointbufavail_int);
+
+int ipath_layer_enable_timer(struct ipath_devdata *dd)
+{
+ /*
+ * HT-400 has a design flaw where the chip and kernel idea
+ * of the tail register don't always agree, and therefore we won't
+ * get an interrupt on the next packet received.
+ * If the board supports per packet receive interrupts, use it.
+ * Otherwise, the timer function periodically checks for packets
+ * to cover this case.
+ * Either way, the timer is needed for verbs layer related
+ * processing.
+ */
+ if (dd->ipath_flags & IPATH_GPIO_INTR) {
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect,
+ 0x2074076542310ULL);
+ /* Enable GPIO bit 2 interrupt */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
+ (u64) (1 << 2));
+ }
+
+ init_timer(&dd->verbs_layer.l_timer);
+ dd->verbs_layer.l_timer.function = __ipath_verbs_timer;
+ dd->verbs_layer.l_timer.data = (unsigned long)dd;
+ dd->verbs_layer.l_timer.expires = jiffies + 1;
+ add_timer(&dd->verbs_layer.l_timer);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_enable_timer);
+
+int ipath_layer_disable_timer(struct ipath_devdata *dd)
+{
+ /* Disable GPIO bit 2 interrupt */
+ if (dd->ipath_flags & IPATH_GPIO_INTR)
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, 0);
+
+ del_timer_sync(&dd->verbs_layer.l_timer);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_disable_timer);
+
+/**
+ * ipath_layer_set_verbs_flags - set the verbs layer flags
+ * @dd: the infinipath device
+ * @flags: the flags to set
+ */
+int ipath_layer_set_verbs_flags(struct ipath_devdata *dd, unsigned flags)
+{
+ struct ipath_devdata *ss;
+ unsigned long lflags;
+
+ spin_lock_irqsave(&ipath_devs_lock, lflags);
+
+ list_for_each_entry(ss, &ipath_dev_list, ipath_list) {
+ if (!(ss->ipath_flags & IPATH_INITTED))
+ continue;
+ if ((flags & IPATH_VERBS_KERNEL_SMA) &&
+ !(*ss->ipath_statusp & IPATH_STATUS_SMA))
+ *ss->ipath_statusp |= IPATH_STATUS_OIB_SMA;
+ else
+ *ss->ipath_statusp &= ~IPATH_STATUS_OIB_SMA;
+ }
+
+ spin_unlock_irqrestore(&ipath_devs_lock, lflags);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_verbs_flags);
+
+/**
+ * ipath_layer_get_npkeys - return the size of the PKEY table for port 0
+ * @dd: the infinipath device
+ */
+unsigned ipath_layer_get_npkeys(struct ipath_devdata *dd)
+{
+ return ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys);
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_npkeys);
+
+/**
+ * ipath_layer_get_pkey - return the indexed PKEY from the port 0 PKEY table
+ * @dd: the infinipath device
+ * @index: the PKEY index
+ */
+unsigned ipath_layer_get_pkey(struct ipath_devdata *dd, unsigned index)
+{
+ unsigned ret;
+
+ if (index >= ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys))
+ ret = 0;
+ else
+ ret = dd->ipath_pd[0]->port_pkeys[index];
+
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_pkey);
+
+/**
+ * ipath_layer_get_pkeys - return the PKEY table for port 0
+ * @dd: the infinipath device
+ * @pkeys: the pkey table is placed here
+ */
+int ipath_layer_get_pkeys(struct ipath_devdata *dd, u16 * pkeys)
+{
+ struct ipath_portdata *pd = dd->ipath_pd[0];
+
+ memcpy(pkeys, pd->port_pkeys, sizeof(pd->port_pkeys));
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_pkeys);
+
+/**
+ * rm_pkey - decrecment the reference count for the given PKEY
+ * @dd: the infinipath device
+ * @key: the PKEY index
+ *
+ * Return true if this was the last reference and the hardware table entry
+ * needs to be changed.
+ */
+static int rm_pkey(struct ipath_devdata *dd, u16 key)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+ if (dd->ipath_pkeys[i] != key)
+ continue;
+ if (atomic_dec_and_test(&dd->ipath_pkeyrefs[i])) {
+ dd->ipath_pkeys[i] = 0;
+ ret = 1;
+ goto bail;
+ }
+ break;
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * add_pkey - add the given PKEY to the hardware table
+ * @dd: the infinipath device
+ * @key: the PKEY
+ *
+ * Return an error code if unable to add the entry, zero if no change,
+ * or 1 if the hardware PKEY register needs to be updated.
+ */
+static int add_pkey(struct ipath_devdata *dd, u16 key)
+{
+ int i;
+ u16 lkey = key & 0x7FFF;
+ int any = 0;
+ int ret;
+
+ if (lkey == 0x7FFF) {
+ ret = 0;
+ goto bail;
+ }
+
+ /* Look for an empty slot or a matching PKEY. */
+ for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+ if (!dd->ipath_pkeys[i]) {
+ any++;
+ continue;
+ }
+ /* If it matches exactly, try to increment the ref count */
+ if (dd->ipath_pkeys[i] == key) {
+ if (atomic_inc_return(&dd->ipath_pkeyrefs[i]) > 1) {
+ ret = 0;
+ goto bail;
+ }
+ /* Lost the race. Look for an empty slot below. */
+ atomic_dec(&dd->ipath_pkeyrefs[i]);
+ any++;
+ }
+ /*
+ * It makes no sense to have both the limited and unlimited
+ * PKEY set at the same time since the unlimited one will
+ * disable the limited one.
+ */
+ if ((dd->ipath_pkeys[i] & 0x7FFF) == lkey) {
+ ret = -EEXIST;
+ goto bail;
+ }
+ }
+ if (!any) {
+ ret = -EBUSY;
+ goto bail;
+ }
+ for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+ if (!dd->ipath_pkeys[i] &&
+ atomic_inc_return(&dd->ipath_pkeyrefs[i]) == 1) {
+ /* for ipathstats, etc. */
+ ipath_stats.sps_pkeys[i] = lkey;
+ dd->ipath_pkeys[i] = key;
+ ret = 1;
+ goto bail;
+ }
+ }
+ ret = -EBUSY;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_layer_set_pkeys - set the PKEY table for port 0
+ * @dd: the infinipath device
+ * @pkeys: the PKEY table
+ */
+int ipath_layer_set_pkeys(struct ipath_devdata *dd, u16 * pkeys)
+{
+ struct ipath_portdata *pd;
+ int i;
+ int changed = 0;
+
+ pd = dd->ipath_pd[0];
+
+ for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) {
+ u16 key = pkeys[i];
+ u16 okey = pd->port_pkeys[i];
+
+ if (key == okey)
+ continue;
+ /*
+ * The value of this PKEY table entry is changing.
+ * Remove the old entry in the hardware's array of PKEYs.
+ */
+ if (okey & 0x7FFF)
+ changed |= rm_pkey(dd, okey);
+ if (key & 0x7FFF) {
+ int ret = add_pkey(dd, key);
+
+ if (ret < 0)
+ key = 0;
+ else
+ changed |= ret;
+ }
+ pd->port_pkeys[i] = key;
+ }
+ if (changed) {
+ u64 pkey;
+
+ pkey = (u64) dd->ipath_pkeys[0] |
+ ((u64) dd->ipath_pkeys[1] << 16) |
+ ((u64) dd->ipath_pkeys[2] << 32) |
+ ((u64) dd->ipath_pkeys[3] << 48);
+ ipath_cdbg(VERBOSE, "p0 new pkey reg %llx\n",
+ (unsigned long long) pkey);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey,
+ pkey);
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_pkeys);
+
+/**
+ * ipath_layer_get_linkdowndefaultstate - get the default linkdown state
+ * @dd: the infinipath device
+ *
+ * Returns zero if the default is POLL, 1 if the default is SLEEP.
+ */
+int ipath_layer_get_linkdowndefaultstate(struct ipath_devdata *dd)
+{
+ return !!(dd->ipath_ibcctrl & INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE);
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_linkdowndefaultstate);
+
+/**
+ * ipath_layer_set_linkdowndefaultstate - set the default linkdown state
+ * @dd: the infinipath device
+ * @sleep: the new state
+ *
+ * Note that this will only take effect when the link state changes.
+ */
+int ipath_layer_set_linkdowndefaultstate(struct ipath_devdata *dd,
+ int sleep)
+{
+ if (sleep)
+ dd->ipath_ibcctrl |= INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE;
+ else
+ dd->ipath_ibcctrl &= ~INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_linkdowndefaultstate);
+
+int ipath_layer_get_phyerrthreshold(struct ipath_devdata *dd)
+{
+ return (dd->ipath_ibcctrl >>
+ INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) &
+ INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_phyerrthreshold);
+
+/**
+ * ipath_layer_set_phyerrthreshold - set the physical error threshold
+ * @dd: the infinipath device
+ * @n: the new threshold
+ *
+ * Note that this will only take effect when the link state changes.
+ */
+int ipath_layer_set_phyerrthreshold(struct ipath_devdata *dd, unsigned n)
+{
+ unsigned v;
+
+ v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) &
+ INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK;
+ if (v != n) {
+ dd->ipath_ibcctrl &=
+ ~(INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK <<
+ INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT);
+ dd->ipath_ibcctrl |=
+ (u64) n << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl);
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_phyerrthreshold);
+
+int ipath_layer_get_overrunthreshold(struct ipath_devdata *dd)
+{
+ return (dd->ipath_ibcctrl >>
+ INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) &
+ INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_overrunthreshold);
+
+/**
+ * ipath_layer_set_overrunthreshold - set the overrun threshold
+ * @dd: the infinipath device
+ * @n: the new threshold
+ *
+ * Note that this will only take effect when the link state changes.
+ */
+int ipath_layer_set_overrunthreshold(struct ipath_devdata *dd, unsigned n)
+{
+ unsigned v;
+
+ v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) &
+ INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK;
+ if (v != n) {
+ dd->ipath_ibcctrl &=
+ ~(INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK <<
+ INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT);
+ dd->ipath_ibcctrl |=
+ (u64) n << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl);
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_overrunthreshold);
+
+int ipath_layer_get_boardname(struct ipath_devdata *dd, char *name,
+ size_t namelen)
+{
+ return dd->ipath_f_get_boardname(dd, name, namelen);
+}
+EXPORT_SYMBOL_GPL(ipath_layer_get_boardname);
+
+u32 ipath_layer_get_rcvhdrentsize(struct ipath_devdata *dd)
+{
+ return dd->ipath_rcvhdrentsize;
+}
+EXPORT_SYMBOL_GPL(ipath_layer_get_rcvhdrentsize);
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.h b/drivers/infiniband/hw/ipath/ipath_layer.h
new file mode 100644
index 00000000000..6fefd15bd2d
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_layer.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _IPATH_LAYER_H
+#define _IPATH_LAYER_H
+
+/*
+ * This header file is for symbols shared between the infinipath driver
+ * and drivers layered upon it (such as ipath).
+ */
+
+struct sk_buff;
+struct ipath_sge_state;
+struct ipath_devdata;
+struct ether_header;
+
+struct ipath_layer_counters {
+ u64 symbol_error_counter;
+ u64 link_error_recovery_counter;
+ u64 link_downed_counter;
+ u64 port_rcv_errors;
+ u64 port_rcv_remphys_errors;
+ u64 port_xmit_discards;
+ u64 port_xmit_data;
+ u64 port_rcv_data;
+ u64 port_xmit_packets;
+ u64 port_rcv_packets;
+};
+
+/*
+ * A segment is a linear region of low physical memory.
+ * XXX Maybe we should use phys addr here and kmap()/kunmap().
+ * Used by the verbs layer.
+ */
+struct ipath_seg {
+ void *vaddr;
+ size_t length;
+};
+
+/* The number of ipath_segs that fit in a page. */
+#define IPATH_SEGSZ (PAGE_SIZE / sizeof (struct ipath_seg))
+
+struct ipath_segarray {
+ struct ipath_seg segs[IPATH_SEGSZ];
+};
+
+struct ipath_mregion {
+ u64 user_base; /* User's address for this region */
+ u64 iova; /* IB start address of this region */
+ size_t length;
+ u32 lkey;
+ u32 offset; /* offset (bytes) to start of region */
+ int access_flags;
+ u32 max_segs; /* number of ipath_segs in all the arrays */
+ u32 mapsz; /* size of the map array */
+ struct ipath_segarray *map[0]; /* the segments */
+};
+
+/*
+ * These keep track of the copy progress within a memory region.
+ * Used by the verbs layer.
+ */
+struct ipath_sge {
+ struct ipath_mregion *mr;
+ void *vaddr; /* current pointer into the segment */
+ u32 sge_length; /* length of the SGE */
+ u32 length; /* remaining length of the segment */
+ u16 m; /* current index: mr->map[m] */
+ u16 n; /* current index: mr->map[m]->segs[n] */
+};
+
+struct ipath_sge_state {
+ struct ipath_sge *sg_list; /* next SGE to be used if any */
+ struct ipath_sge sge; /* progress state for the current SGE */
+ u8 num_sge;
+};
+
+int ipath_layer_register(void *(*l_add)(int, struct ipath_devdata *),
+ void (*l_remove)(void *),
+ int (*l_intr)(void *, u32),
+ int (*l_rcv)(void *, void *,
+ struct sk_buff *),
+ u16 rcv_opcode,
+ int (*l_rcv_lid)(void *, void *));
+int ipath_verbs_register(void *(*l_add)(int, struct ipath_devdata *),
+ void (*l_remove)(void *arg),
+ int (*l_piobufavail)(void *arg),
+ void (*l_rcv)(void *arg, void *rhdr,
+ void *data, u32 tlen),
+ void (*l_timer_cb)(void *arg));
+void ipath_layer_unregister(void);
+void ipath_verbs_unregister(void);
+int ipath_layer_open(struct ipath_devdata *, u32 * pktmax);
+u16 ipath_layer_get_lid(struct ipath_devdata *dd);
+int ipath_layer_get_mac(struct ipath_devdata *dd, u8 *);
+u16 ipath_layer_get_bcast(struct ipath_devdata *dd);
+u32 ipath_layer_get_cr_errpkey(struct ipath_devdata *dd);
+int ipath_layer_set_linkstate(struct ipath_devdata *dd, u8 state);
+int ipath_layer_set_mtu(struct ipath_devdata *, u16);
+int ipath_set_sps_lid(struct ipath_devdata *, u32, u8);
+int ipath_layer_send_hdr(struct ipath_devdata *dd,
+ struct ether_header *hdr);
+int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords,
+ u32 * hdr, u32 len, struct ipath_sge_state *ss);
+int ipath_layer_set_piointbufavail_int(struct ipath_devdata *dd);
+int ipath_layer_get_boardname(struct ipath_devdata *dd, char *name,
+ size_t namelen);
+int ipath_layer_snapshot_counters(struct ipath_devdata *dd, u64 *swords,
+ u64 *rwords, u64 *spkts, u64 *rpkts,
+ u64 *xmit_wait);
+int ipath_layer_get_counters(struct ipath_devdata *dd,
+ struct ipath_layer_counters *cntrs);
+int ipath_layer_want_buffer(struct ipath_devdata *dd);
+int ipath_layer_set_guid(struct ipath_devdata *, __be64 guid);
+__be64 ipath_layer_get_guid(struct ipath_devdata *);
+u32 ipath_layer_get_nguid(struct ipath_devdata *);
+int ipath_layer_query_device(struct ipath_devdata *, u32 * vendor,
+ u32 * boardrev, u32 * majrev, u32 * minrev);
+u32 ipath_layer_get_flags(struct ipath_devdata *dd);
+struct device *ipath_layer_get_device(struct ipath_devdata *dd);
+u16 ipath_layer_get_deviceid(struct ipath_devdata *dd);
+u64 ipath_layer_get_lastibcstat(struct ipath_devdata *dd);
+u32 ipath_layer_get_ibmtu(struct ipath_devdata *dd);
+int ipath_layer_enable_timer(struct ipath_devdata *dd);
+int ipath_layer_disable_timer(struct ipath_devdata *dd);
+int ipath_layer_set_verbs_flags(struct ipath_devdata *dd, unsigned flags);
+unsigned ipath_layer_get_npkeys(struct ipath_devdata *dd);
+unsigned ipath_layer_get_pkey(struct ipath_devdata *dd, unsigned index);
+int ipath_layer_get_pkeys(struct ipath_devdata *dd, u16 *pkeys);
+int ipath_layer_set_pkeys(struct ipath_devdata *dd, u16 *pkeys);
+int ipath_layer_get_linkdowndefaultstate(struct ipath_devdata *dd);
+int ipath_layer_set_linkdowndefaultstate(struct ipath_devdata *dd,
+ int sleep);
+int ipath_layer_get_phyerrthreshold(struct ipath_devdata *dd);
+int ipath_layer_set_phyerrthreshold(struct ipath_devdata *dd, unsigned n);
+int ipath_layer_get_overrunthreshold(struct ipath_devdata *dd);
+int ipath_layer_set_overrunthreshold(struct ipath_devdata *dd, unsigned n);
+u32 ipath_layer_get_rcvhdrentsize(struct ipath_devdata *dd);
+
+/* ipath_ether interrupt values */
+#define IPATH_LAYER_INT_IF_UP 0x2
+#define IPATH_LAYER_INT_IF_DOWN 0x4
+#define IPATH_LAYER_INT_LID 0x8
+#define IPATH_LAYER_INT_SEND_CONTINUE 0x10
+#define IPATH_LAYER_INT_BCAST 0x40
+
+/* _verbs_layer.l_flags */
+#define IPATH_VERBS_KERNEL_SMA 0x1
+
+extern unsigned ipath_debug; /* debugging bit mask */
+
+#endif /* _IPATH_LAYER_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
new file mode 100644
index 00000000000..f7f8391fe43
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -0,0 +1,1352 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_smi.h>
+
+#include "ipath_kernel.h"
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+#define IB_SMP_UNSUP_VERSION __constant_htons(0x0004)
+#define IB_SMP_UNSUP_METHOD __constant_htons(0x0008)
+#define IB_SMP_UNSUP_METH_ATTR __constant_htons(0x000C)
+#define IB_SMP_INVALID_FIELD __constant_htons(0x001C)
+
+static int reply(struct ib_smp *smp)
+{
+ /*
+ * The verbs framework will handle the directed/LID route
+ * packet changes.
+ */
+ smp->method = IB_MGMT_METHOD_GET_RESP;
+ if (smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
+ smp->status |= IB_SMP_DIRECTION;
+ return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
+}
+
+static int recv_subn_get_nodedescription(struct ib_smp *smp,
+ struct ib_device *ibdev)
+{
+ if (smp->attr_mod)
+ smp->status |= IB_SMP_INVALID_FIELD;
+
+ strncpy(smp->data, ibdev->node_desc, sizeof(smp->data));
+
+ return reply(smp);
+}
+
+struct nodeinfo {
+ u8 base_version;
+ u8 class_version;
+ u8 node_type;
+ u8 num_ports;
+ __be64 sys_guid;
+ __be64 node_guid;
+ __be64 port_guid;
+ __be16 partition_cap;
+ __be16 device_id;
+ __be32 revision;
+ u8 local_port_num;
+ u8 vendor_id[3];
+} __attribute__ ((packed));
+
+static int recv_subn_get_nodeinfo(struct ib_smp *smp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct nodeinfo *nip = (struct nodeinfo *)&smp->data;
+ struct ipath_devdata *dd = to_idev(ibdev)->dd;
+ u32 vendor, boardid, majrev, minrev;
+
+ if (smp->attr_mod)
+ smp->status |= IB_SMP_INVALID_FIELD;
+
+ nip->base_version = 1;
+ nip->class_version = 1;
+ nip->node_type = 1; /* channel adapter */
+ /*
+ * XXX The num_ports value will need a layer function to get
+ * the value if we ever have more than one IB port on a chip.
+ * We will also need to get the GUID for the port.
+ */
+ nip->num_ports = ibdev->phys_port_cnt;
+ /* This is already in network order */
+ nip->sys_guid = to_idev(ibdev)->sys_image_guid;
+ nip->node_guid = ipath_layer_get_guid(dd);
+ nip->port_guid = nip->sys_guid;
+ nip->partition_cap = cpu_to_be16(ipath_layer_get_npkeys(dd));
+ nip->device_id = cpu_to_be16(ipath_layer_get_deviceid(dd));
+ ipath_layer_query_device(dd, &vendor, &boardid, &majrev, &minrev);
+ nip->revision = cpu_to_be32((majrev << 16) | minrev);
+ nip->local_port_num = port;
+ nip->vendor_id[0] = 0;
+ nip->vendor_id[1] = vendor >> 8;
+ nip->vendor_id[2] = vendor;
+
+ return reply(smp);
+}
+
+static int recv_subn_get_guidinfo(struct ib_smp *smp,
+ struct ib_device *ibdev)
+{
+ u32 startgx = 8 * be32_to_cpu(smp->attr_mod);
+ __be64 *p = (__be64 *) smp->data;
+
+ /* 32 blocks of 8 64-bit GUIDs per block */
+
+ memset(smp->data, 0, sizeof(smp->data));
+
+ /*
+ * We only support one GUID for now. If this changes, the
+ * portinfo.guid_cap field needs to be updated too.
+ */
+ if (startgx == 0)
+ /* The first is a copy of the read-only HW GUID. */
+ *p = ipath_layer_get_guid(to_idev(ibdev)->dd);
+ else
+ smp->status |= IB_SMP_INVALID_FIELD;
+
+ return reply(smp);
+}
+
+struct port_info {
+ __be64 mkey;
+ __be64 gid_prefix;
+ __be16 lid;
+ __be16 sm_lid;
+ __be32 cap_mask;
+ __be16 diag_code;
+ __be16 mkey_lease_period;
+ u8 local_port_num;
+ u8 link_width_enabled;
+ u8 link_width_supported;
+ u8 link_width_active;
+ u8 linkspeed_portstate; /* 4 bits, 4 bits */
+ u8 portphysstate_linkdown; /* 4 bits, 4 bits */
+ u8 mkeyprot_resv_lmc; /* 2 bits, 3, 3 */
+ u8 linkspeedactive_enabled; /* 4 bits, 4 bits */
+ u8 neighbormtu_mastersmsl; /* 4 bits, 4 bits */
+ u8 vlcap_inittype; /* 4 bits, 4 bits */
+ u8 vl_high_limit;
+ u8 vl_arb_high_cap;
+ u8 vl_arb_low_cap;
+ u8 inittypereply_mtucap; /* 4 bits, 4 bits */
+ u8 vlstallcnt_hoqlife; /* 3 bits, 5 bits */
+ u8 operationalvl_pei_peo_fpi_fpo; /* 4 bits, 1, 1, 1, 1 */
+ __be16 mkey_violations;
+ __be16 pkey_violations;
+ __be16 qkey_violations;
+ u8 guid_cap;
+ u8 clientrereg_resv_subnetto; /* 1 bit, 2 bits, 5 */
+ u8 resv_resptimevalue; /* 3 bits, 5 bits */
+ u8 localphyerrors_overrunerrors; /* 4 bits, 4 bits */
+ __be16 max_credit_hint;
+ u8 resv;
+ u8 link_roundtrip_latency[3];
+} __attribute__ ((packed));
+
+static int recv_subn_get_portinfo(struct ib_smp *smp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ipath_ibdev *dev;
+ struct port_info *pip = (struct port_info *)smp->data;
+ u16 lid;
+ u8 ibcstat;
+ u8 mtu;
+ int ret;
+
+ if (be32_to_cpu(smp->attr_mod) > ibdev->phys_port_cnt) {
+ smp->status |= IB_SMP_INVALID_FIELD;
+ ret = reply(smp);
+ goto bail;
+ }
+
+ dev = to_idev(ibdev);
+
+ /* Clear all fields. Only set the non-zero fields. */
+ memset(smp->data, 0, sizeof(smp->data));
+
+ /* Only return the mkey if the protection field allows it. */
+ if (smp->method == IB_MGMT_METHOD_SET || dev->mkey == smp->mkey ||
+ (dev->mkeyprot_resv_lmc >> 6) == 0)
+ pip->mkey = dev->mkey;
+ pip->gid_prefix = dev->gid_prefix;
+ lid = ipath_layer_get_lid(dev->dd);
+ pip->lid = lid ? cpu_to_be16(lid) : IB_LID_PERMISSIVE;
+ pip->sm_lid = cpu_to_be16(dev->sm_lid);
+ pip->cap_mask = cpu_to_be32(dev->port_cap_flags);
+ /* pip->diag_code; */
+ pip->mkey_lease_period = cpu_to_be16(dev->mkey_lease_period);
+ pip->local_port_num = port;
+ pip->link_width_enabled = dev->link_width_enabled;
+ pip->link_width_supported = 3; /* 1x or 4x */
+ pip->link_width_active = 2; /* 4x */
+ pip->linkspeed_portstate = 0x10; /* 2.5Gbps */
+ ibcstat = ipath_layer_get_lastibcstat(dev->dd);
+ pip->linkspeed_portstate |= ((ibcstat >> 4) & 0x3) + 1;
+ pip->portphysstate_linkdown =
+ (ipath_cvt_physportstate[ibcstat & 0xf] << 4) |
+ (ipath_layer_get_linkdowndefaultstate(dev->dd) ? 1 : 2);
+ pip->mkeyprot_resv_lmc = dev->mkeyprot_resv_lmc;
+ pip->linkspeedactive_enabled = 0x11; /* 2.5Gbps, 2.5Gbps */
+ switch (ipath_layer_get_ibmtu(dev->dd)) {
+ case 4096:
+ mtu = IB_MTU_4096;
+ break;
+ case 2048:
+ mtu = IB_MTU_2048;
+ break;
+ case 1024:
+ mtu = IB_MTU_1024;
+ break;
+ case 512:
+ mtu = IB_MTU_512;
+ break;
+ case 256:
+ mtu = IB_MTU_256;
+ break;
+ default: /* oops, something is wrong */
+ mtu = IB_MTU_2048;
+ break;
+ }
+ pip->neighbormtu_mastersmsl = (mtu << 4) | dev->sm_sl;
+ pip->vlcap_inittype = 0x10; /* VLCap = VL0, InitType = 0 */
+ pip->vl_high_limit = dev->vl_high_limit;
+ /* pip->vl_arb_high_cap; // only one VL */
+ /* pip->vl_arb_low_cap; // only one VL */
+ /* InitTypeReply = 0 */
+ pip->inittypereply_mtucap = IB_MTU_4096;
+ // HCAs ignore VLStallCount and HOQLife
+ /* pip->vlstallcnt_hoqlife; */
+ pip->operationalvl_pei_peo_fpi_fpo = 0x10; /* OVLs = 1 */
+ pip->mkey_violations = cpu_to_be16(dev->mkey_violations);
+ /* P_KeyViolations are counted by hardware. */
+ pip->pkey_violations =
+ cpu_to_be16((ipath_layer_get_cr_errpkey(dev->dd) -
+ dev->n_pkey_violations) & 0xFFFF);
+ pip->qkey_violations = cpu_to_be16(dev->qkey_violations);
+ /* Only the hardware GUID is supported for now */
+ pip->guid_cap = 1;
+ pip->clientrereg_resv_subnetto = dev->subnet_timeout;
+ /* 32.768 usec. response time (guessing) */
+ pip->resv_resptimevalue = 3;
+ pip->localphyerrors_overrunerrors =
+ (ipath_layer_get_phyerrthreshold(dev->dd) << 4) |
+ ipath_layer_get_overrunthreshold(dev->dd);
+ /* pip->max_credit_hint; */
+ /* pip->link_roundtrip_latency[3]; */
+
+ ret = reply(smp);
+
+bail:
+ return ret;
+}
+
+static int recv_subn_get_pkeytable(struct ib_smp *smp,
+ struct ib_device *ibdev)
+{
+ u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff);
+ u16 *p = (u16 *) smp->data;
+ __be16 *q = (__be16 *) smp->data;
+
+ /* 64 blocks of 32 16-bit P_Key entries */
+
+ memset(smp->data, 0, sizeof(smp->data));
+ if (startpx == 0) {
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ unsigned i, n = ipath_layer_get_npkeys(dev->dd);
+
+ ipath_layer_get_pkeys(dev->dd, p);
+
+ for (i = 0; i < n; i++)
+ q[i] = cpu_to_be16(p[i]);
+ } else
+ smp->status |= IB_SMP_INVALID_FIELD;
+
+ return reply(smp);
+}
+
+static int recv_subn_set_guidinfo(struct ib_smp *smp,
+ struct ib_device *ibdev)
+{
+ /* The only GUID we support is the first read-only entry. */
+ return recv_subn_get_guidinfo(smp, ibdev);
+}
+
+/**
+ * recv_subn_set_portinfo - set port information
+ * @smp: the incoming SM packet
+ * @ibdev: the infiniband device
+ * @port: the port on the device
+ *
+ * Set Portinfo (see ch. 14.2.5.6).
+ */
+static int recv_subn_set_portinfo(struct ib_smp *smp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct port_info *pip = (struct port_info *)smp->data;
+ struct ib_event event;
+ struct ipath_ibdev *dev;
+ u32 flags;
+ char clientrereg = 0;
+ u16 lid, smlid;
+ u8 lwe;
+ u8 lse;
+ u8 state;
+ u16 lstate;
+ u32 mtu;
+ int ret;
+
+ if (be32_to_cpu(smp->attr_mod) > ibdev->phys_port_cnt)
+ goto err;
+
+ dev = to_idev(ibdev);
+ event.device = ibdev;
+ event.element.port_num = port;
+
+ dev->mkey = pip->mkey;
+ dev->gid_prefix = pip->gid_prefix;
+ dev->mkey_lease_period = be16_to_cpu(pip->mkey_lease_period);
+
+ lid = be16_to_cpu(pip->lid);
+ if (lid != ipath_layer_get_lid(dev->dd)) {
+ /* Must be a valid unicast LID address. */
+ if (lid == 0 || lid >= IPS_MULTICAST_LID_BASE)
+ goto err;
+ ipath_set_sps_lid(dev->dd, lid, pip->mkeyprot_resv_lmc & 7);
+ event.event = IB_EVENT_LID_CHANGE;
+ ib_dispatch_event(&event);
+ }
+
+ smlid = be16_to_cpu(pip->sm_lid);
+ if (smlid != dev->sm_lid) {
+ /* Must be a valid unicast LID address. */
+ if (smlid == 0 || smlid >= IPS_MULTICAST_LID_BASE)
+ goto err;
+ dev->sm_lid = smlid;
+ event.event = IB_EVENT_SM_CHANGE;
+ ib_dispatch_event(&event);
+ }
+
+ /* Only 4x supported but allow 1x or 4x to be set (see 14.2.6.6). */
+ lwe = pip->link_width_enabled;
+ if ((lwe >= 4 && lwe <= 8) || (lwe >= 0xC && lwe <= 0xFE))
+ goto err;
+ if (lwe == 0xFF)
+ dev->link_width_enabled = 3; /* 1x or 4x */
+ else if (lwe)
+ dev->link_width_enabled = lwe;
+
+ /* Only 2.5 Gbs supported. */
+ lse = pip->linkspeedactive_enabled & 0xF;
+ if (lse >= 2 && lse <= 0xE)
+ goto err;
+
+ /* Set link down default state. */
+ switch (pip->portphysstate_linkdown & 0xF) {
+ case 0: /* NOP */
+ break;
+ case 1: /* SLEEP */
+ if (ipath_layer_set_linkdowndefaultstate(dev->dd, 1))
+ goto err;
+ break;
+ case 2: /* POLL */
+ if (ipath_layer_set_linkdowndefaultstate(dev->dd, 0))
+ goto err;
+ break;
+ default:
+ goto err;
+ }
+
+ dev->mkeyprot_resv_lmc = pip->mkeyprot_resv_lmc;
+ dev->vl_high_limit = pip->vl_high_limit;
+
+ switch ((pip->neighbormtu_mastersmsl >> 4) & 0xF) {
+ case IB_MTU_256:
+ mtu = 256;
+ break;
+ case IB_MTU_512:
+ mtu = 512;
+ break;
+ case IB_MTU_1024:
+ mtu = 1024;
+ break;
+ case IB_MTU_2048:
+ mtu = 2048;
+ break;
+ case IB_MTU_4096:
+ mtu = 4096;
+ break;
+ default:
+ /* XXX We have already partially updated our state! */
+ goto err;
+ }
+ ipath_layer_set_mtu(dev->dd, mtu);
+
+ dev->sm_sl = pip->neighbormtu_mastersmsl & 0xF;
+
+ /* We only support VL0 */
+ if (((pip->operationalvl_pei_peo_fpi_fpo >> 4) & 0xF) > 1)
+ goto err;
+
+ if (pip->mkey_violations == 0)
+ dev->mkey_violations = 0;
+
+ /*
+ * Hardware counter can't be reset so snapshot and subtract
+ * later.
+ */
+ if (pip->pkey_violations == 0)
+ dev->n_pkey_violations =
+ ipath_layer_get_cr_errpkey(dev->dd);
+
+ if (pip->qkey_violations == 0)
+ dev->qkey_violations = 0;
+
+ if (ipath_layer_set_phyerrthreshold(
+ dev->dd,
+ (pip->localphyerrors_overrunerrors >> 4) & 0xF))
+ goto err;
+
+ if (ipath_layer_set_overrunthreshold(
+ dev->dd,
+ (pip->localphyerrors_overrunerrors & 0xF)))
+ goto err;
+
+ dev->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F;
+
+ if (pip->clientrereg_resv_subnetto & 0x80) {
+ clientrereg = 1;
+ event.event = IB_EVENT_LID_CHANGE;
+ ib_dispatch_event(&event);
+ }
+
+ /*
+ * Do the port state change now that the other link parameters
+ * have been set.
+ * Changing the port physical state only makes sense if the link
+ * is down or is being set to down.
+ */
+ state = pip->linkspeed_portstate & 0xF;
+ flags = ipath_layer_get_flags(dev->dd);
+ lstate = (pip->portphysstate_linkdown >> 4) & 0xF;
+ if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP))
+ goto err;
+
+ /*
+ * Only state changes of DOWN, ARM, and ACTIVE are valid
+ * and must be in the correct state to take effect (see 7.2.6).
+ */
+ switch (state) {
+ case IB_PORT_NOP:
+ if (lstate == 0)
+ break;
+ /* FALLTHROUGH */
+ case IB_PORT_DOWN:
+ if (lstate == 0)
+ if (ipath_layer_get_linkdowndefaultstate(dev->dd))
+ lstate = IPATH_IB_LINKDOWN_SLEEP;
+ else
+ lstate = IPATH_IB_LINKDOWN;
+ else if (lstate == 1)
+ lstate = IPATH_IB_LINKDOWN_SLEEP;
+ else if (lstate == 2)
+ lstate = IPATH_IB_LINKDOWN;
+ else if (lstate == 3)
+ lstate = IPATH_IB_LINKDOWN_DISABLE;
+ else
+ goto err;
+ ipath_layer_set_linkstate(dev->dd, lstate);
+ if (flags & IPATH_LINKACTIVE) {
+ event.event = IB_EVENT_PORT_ERR;
+ ib_dispatch_event(&event);
+ }
+ break;
+ case IB_PORT_ARMED:
+ if (!(flags & (IPATH_LINKINIT | IPATH_LINKACTIVE)))
+ break;
+ ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKARM);
+ if (flags & IPATH_LINKACTIVE) {
+ event.event = IB_EVENT_PORT_ERR;
+ ib_dispatch_event(&event);
+ }
+ break;
+ case IB_PORT_ACTIVE:
+ if (!(flags & IPATH_LINKARMED))
+ break;
+ ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKACTIVE);
+ event.event = IB_EVENT_PORT_ACTIVE;
+ ib_dispatch_event(&event);
+ break;
+ default:
+ /* XXX We have already partially updated our state! */
+ goto err;
+ }
+
+ ret = recv_subn_get_portinfo(smp, ibdev, port);
+
+ if (clientrereg)
+ pip->clientrereg_resv_subnetto |= 0x80;
+
+ goto done;
+
+err:
+ smp->status |= IB_SMP_INVALID_FIELD;
+ ret = recv_subn_get_portinfo(smp, ibdev, port);
+
+done:
+ return ret;
+}
+
+static int recv_subn_set_pkeytable(struct ib_smp *smp,
+ struct ib_device *ibdev)
+{
+ u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff);
+ __be16 *p = (__be16 *) smp->data;
+ u16 *q = (u16 *) smp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ unsigned i, n = ipath_layer_get_npkeys(dev->dd);
+
+ for (i = 0; i < n; i++)
+ q[i] = be16_to_cpu(p[i]);
+
+ if (startpx != 0 ||
+ ipath_layer_set_pkeys(dev->dd, q) != 0)
+ smp->status |= IB_SMP_INVALID_FIELD;
+
+ return recv_subn_get_pkeytable(smp, ibdev);
+}
+
+#define IB_PMA_CLASS_PORT_INFO __constant_htons(0x0001)
+#define IB_PMA_PORT_SAMPLES_CONTROL __constant_htons(0x0010)
+#define IB_PMA_PORT_SAMPLES_RESULT __constant_htons(0x0011)
+#define IB_PMA_PORT_COUNTERS __constant_htons(0x0012)
+#define IB_PMA_PORT_COUNTERS_EXT __constant_htons(0x001D)
+#define IB_PMA_PORT_SAMPLES_RESULT_EXT __constant_htons(0x001E)
+
+struct ib_perf {
+ u8 base_version;
+ u8 mgmt_class;
+ u8 class_version;
+ u8 method;
+ __be16 status;
+ __be16 unused;
+ __be64 tid;
+ __be16 attr_id;
+ __be16 resv;
+ __be32 attr_mod;
+ u8 reserved[40];
+ u8 data[192];
+} __attribute__ ((packed));
+
+struct ib_pma_classportinfo {
+ u8 base_version;
+ u8 class_version;
+ __be16 cap_mask;
+ u8 reserved[3];
+ u8 resp_time_value; /* only lower 5 bits */
+ union ib_gid redirect_gid;
+ __be32 redirect_tc_sl_fl; /* 8, 4, 20 bits respectively */
+ __be16 redirect_lid;
+ __be16 redirect_pkey;
+ __be32 redirect_qp; /* only lower 24 bits */
+ __be32 redirect_qkey;
+ union ib_gid trap_gid;
+ __be32 trap_tc_sl_fl; /* 8, 4, 20 bits respectively */
+ __be16 trap_lid;
+ __be16 trap_pkey;
+ __be32 trap_hl_qp; /* 8, 24 bits respectively */
+ __be32 trap_qkey;
+} __attribute__ ((packed));
+
+struct ib_pma_portsamplescontrol {
+ u8 opcode;
+ u8 port_select;
+ u8 tick;
+ u8 counter_width; /* only lower 3 bits */
+ __be32 counter_mask0_9; /* 2, 10 * 3, bits */
+ __be16 counter_mask10_14; /* 1, 5 * 3, bits */
+ u8 sample_mechanisms;
+ u8 sample_status; /* only lower 2 bits */
+ __be64 option_mask;
+ __be64 vendor_mask;
+ __be32 sample_start;
+ __be32 sample_interval;
+ __be16 tag;
+ __be16 counter_select[15];
+} __attribute__ ((packed));
+
+struct ib_pma_portsamplesresult {
+ __be16 tag;
+ __be16 sample_status; /* only lower 2 bits */
+ __be32 counter[15];
+} __attribute__ ((packed));
+
+struct ib_pma_portsamplesresult_ext {
+ __be16 tag;
+ __be16 sample_status; /* only lower 2 bits */
+ __be32 extended_width; /* only upper 2 bits */
+ __be64 counter[15];
+} __attribute__ ((packed));
+
+struct ib_pma_portcounters {
+ u8 reserved;
+ u8 port_select;
+ __be16 counter_select;
+ __be16 symbol_error_counter;
+ u8 link_error_recovery_counter;
+ u8 link_downed_counter;
+ __be16 port_rcv_errors;
+ __be16 port_rcv_remphys_errors;
+ __be16 port_rcv_switch_relay_errors;
+ __be16 port_xmit_discards;
+ u8 port_xmit_constraint_errors;
+ u8 port_rcv_constraint_errors;
+ u8 reserved1;
+ u8 lli_ebor_errors; /* 4, 4, bits */
+ __be16 reserved2;
+ __be16 vl15_dropped;
+ __be32 port_xmit_data;
+ __be32 port_rcv_data;
+ __be32 port_xmit_packets;
+ __be32 port_rcv_packets;
+} __attribute__ ((packed));
+
+#define IB_PMA_SEL_SYMBOL_ERROR __constant_htons(0x0001)
+#define IB_PMA_SEL_LINK_ERROR_RECOVERY __constant_htons(0x0002)
+#define IB_PMA_SEL_LINK_DOWNED __constant_htons(0x0004)
+#define IB_PMA_SEL_PORT_RCV_ERRORS __constant_htons(0x0008)
+#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS __constant_htons(0x0010)
+#define IB_PMA_SEL_PORT_XMIT_DISCARDS __constant_htons(0x0040)
+#define IB_PMA_SEL_PORT_XMIT_DATA __constant_htons(0x1000)
+#define IB_PMA_SEL_PORT_RCV_DATA __constant_htons(0x2000)
+#define IB_PMA_SEL_PORT_XMIT_PACKETS __constant_htons(0x4000)
+#define IB_PMA_SEL_PORT_RCV_PACKETS __constant_htons(0x8000)
+
+struct ib_pma_portcounters_ext {
+ u8 reserved;
+ u8 port_select;
+ __be16 counter_select;
+ __be32 reserved1;
+ __be64 port_xmit_data;
+ __be64 port_rcv_data;
+ __be64 port_xmit_packets;
+ __be64 port_rcv_packets;
+ __be64 port_unicast_xmit_packets;
+ __be64 port_unicast_rcv_packets;
+ __be64 port_multicast_xmit_packets;
+ __be64 port_multicast_rcv_packets;
+} __attribute__ ((packed));
+
+#define IB_PMA_SELX_PORT_XMIT_DATA __constant_htons(0x0001)
+#define IB_PMA_SELX_PORT_RCV_DATA __constant_htons(0x0002)
+#define IB_PMA_SELX_PORT_XMIT_PACKETS __constant_htons(0x0004)
+#define IB_PMA_SELX_PORT_RCV_PACKETS __constant_htons(0x0008)
+#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS __constant_htons(0x0010)
+#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS __constant_htons(0x0020)
+#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS __constant_htons(0x0040)
+#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS __constant_htons(0x0080)
+
+static int recv_pma_get_classportinfo(struct ib_perf *pmp)
+{
+ struct ib_pma_classportinfo *p =
+ (struct ib_pma_classportinfo *)pmp->data;
+
+ memset(pmp->data, 0, sizeof(pmp->data));
+
+ if (pmp->attr_mod != 0)
+ pmp->status |= IB_SMP_INVALID_FIELD;
+
+ /* Indicate AllPortSelect is valid (only one port anyway) */
+ p->cap_mask = __constant_cpu_to_be16(1 << 8);
+ p->base_version = 1;
+ p->class_version = 1;
+ /*
+ * Expected response time is 4.096 usec. * 2^18 == 1.073741824
+ * sec.
+ */
+ p->resp_time_value = 18;
+
+ return reply((struct ib_smp *) pmp);
+}
+
+/*
+ * The PortSamplesControl.CounterMasks field is an array of 3 bit fields
+ * which specify the N'th counter's capabilities. See ch. 16.1.3.2.
+ * We support 5 counters which only count the mandatory quantities.
+ */
+#define COUNTER_MASK(q, n) (q << ((9 - n) * 3))
+#define COUNTER_MASK0_9 \
+ __constant_cpu_to_be32(COUNTER_MASK(1, 0) | \
+ COUNTER_MASK(1, 1) | \
+ COUNTER_MASK(1, 2) | \
+ COUNTER_MASK(1, 3) | \
+ COUNTER_MASK(1, 4))
+
+static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ib_pma_portsamplescontrol *p =
+ (struct ib_pma_portsamplescontrol *)pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ unsigned long flags;
+ u8 port_select = p->port_select;
+
+ memset(pmp->data, 0, sizeof(pmp->data));
+
+ p->port_select = port_select;
+ if (pmp->attr_mod != 0 ||
+ (port_select != port && port_select != 0xFF))
+ pmp->status |= IB_SMP_INVALID_FIELD;
+ /*
+ * Ticks are 10x the link transfer period which for 2.5Gbs is 4
+ * nsec. 0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec. Sample
+ * intervals are counted in ticks. Since we use Linux timers, that
+ * count in jiffies, we can't sample for less than 1000 ticks if HZ
+ * == 1000 (4000 ticks if HZ is 250).
+ */
+ /* XXX This is WRONG. */
+ p->tick = 250; /* 1 usec. */
+ p->counter_width = 4; /* 32 bit counters */
+ p->counter_mask0_9 = COUNTER_MASK0_9;
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ p->sample_status = dev->pma_sample_status;
+ p->sample_start = cpu_to_be32(dev->pma_sample_start);
+ p->sample_interval = cpu_to_be32(dev->pma_sample_interval);
+ p->tag = cpu_to_be16(dev->pma_tag);
+ p->counter_select[0] = dev->pma_counter_select[0];
+ p->counter_select[1] = dev->pma_counter_select[1];
+ p->counter_select[2] = dev->pma_counter_select[2];
+ p->counter_select[3] = dev->pma_counter_select[3];
+ p->counter_select[4] = dev->pma_counter_select[4];
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+ return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ib_pma_portsamplescontrol *p =
+ (struct ib_pma_portsamplescontrol *)pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ unsigned long flags;
+ u32 start;
+ int ret;
+
+ if (pmp->attr_mod != 0 ||
+ (p->port_select != port && p->port_select != 0xFF)) {
+ pmp->status |= IB_SMP_INVALID_FIELD;
+ ret = reply((struct ib_smp *) pmp);
+ goto bail;
+ }
+
+ start = be32_to_cpu(p->sample_start);
+ if (start != 0) {
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_DONE) {
+ dev->pma_sample_status =
+ IB_PMA_SAMPLE_STATUS_STARTED;
+ dev->pma_sample_start = start;
+ dev->pma_sample_interval =
+ be32_to_cpu(p->sample_interval);
+ dev->pma_tag = be16_to_cpu(p->tag);
+ if (p->counter_select[0])
+ dev->pma_counter_select[0] =
+ p->counter_select[0];
+ if (p->counter_select[1])
+ dev->pma_counter_select[1] =
+ p->counter_select[1];
+ if (p->counter_select[2])
+ dev->pma_counter_select[2] =
+ p->counter_select[2];
+ if (p->counter_select[3])
+ dev->pma_counter_select[3] =
+ p->counter_select[3];
+ if (p->counter_select[4])
+ dev->pma_counter_select[4] =
+ p->counter_select[4];
+ }
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+ }
+ ret = recv_pma_get_portsamplescontrol(pmp, ibdev, port);
+
+bail:
+ return ret;
+}
+
+static u64 get_counter(struct ipath_ibdev *dev, __be16 sel)
+{
+ u64 ret;
+
+ switch (sel) {
+ case IB_PMA_PORT_XMIT_DATA:
+ ret = dev->ipath_sword;
+ break;
+ case IB_PMA_PORT_RCV_DATA:
+ ret = dev->ipath_rword;
+ break;
+ case IB_PMA_PORT_XMIT_PKTS:
+ ret = dev->ipath_spkts;
+ break;
+ case IB_PMA_PORT_RCV_PKTS:
+ ret = dev->ipath_rpkts;
+ break;
+ case IB_PMA_PORT_XMIT_WAIT:
+ ret = dev->ipath_xmit_wait;
+ break;
+ default:
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
+ struct ib_device *ibdev)
+{
+ struct ib_pma_portsamplesresult *p =
+ (struct ib_pma_portsamplesresult *)pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ int i;
+
+ memset(pmp->data, 0, sizeof(pmp->data));
+ p->tag = cpu_to_be16(dev->pma_tag);
+ p->sample_status = cpu_to_be16(dev->pma_sample_status);
+ for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
+ p->counter[i] = cpu_to_be32(
+ get_counter(dev, dev->pma_counter_select[i]));
+
+ return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
+ struct ib_device *ibdev)
+{
+ struct ib_pma_portsamplesresult_ext *p =
+ (struct ib_pma_portsamplesresult_ext *)pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ int i;
+
+ memset(pmp->data, 0, sizeof(pmp->data));
+ p->tag = cpu_to_be16(dev->pma_tag);
+ p->sample_status = cpu_to_be16(dev->pma_sample_status);
+ /* 64 bits */
+ p->extended_width = __constant_cpu_to_be32(0x80000000);
+ for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
+ p->counter[i] = cpu_to_be64(
+ get_counter(dev, dev->pma_counter_select[i]));
+
+ return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_get_portcounters(struct ib_perf *pmp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
+ pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ struct ipath_layer_counters cntrs;
+ u8 port_select = p->port_select;
+
+ ipath_layer_get_counters(dev->dd, &cntrs);
+
+ /* Adjust counters for any resets done. */
+ cntrs.symbol_error_counter -= dev->n_symbol_error_counter;
+ cntrs.link_error_recovery_counter -=
+ dev->n_link_error_recovery_counter;
+ cntrs.link_downed_counter -= dev->n_link_downed_counter;
+ cntrs.port_rcv_errors += dev->rcv_errors;
+ cntrs.port_rcv_errors -= dev->n_port_rcv_errors;
+ cntrs.port_rcv_remphys_errors -= dev->n_port_rcv_remphys_errors;
+ cntrs.port_xmit_discards -= dev->n_port_xmit_discards;
+ cntrs.port_xmit_data -= dev->n_port_xmit_data;
+ cntrs.port_rcv_data -= dev->n_port_rcv_data;
+ cntrs.port_xmit_packets -= dev->n_port_xmit_packets;
+ cntrs.port_rcv_packets -= dev->n_port_rcv_packets;
+
+ memset(pmp->data, 0, sizeof(pmp->data));
+
+ p->port_select = port_select;
+ if (pmp->attr_mod != 0 ||
+ (port_select != port && port_select != 0xFF))
+ pmp->status |= IB_SMP_INVALID_FIELD;
+
+ if (cntrs.symbol_error_counter > 0xFFFFUL)
+ p->symbol_error_counter = __constant_cpu_to_be16(0xFFFF);
+ else
+ p->symbol_error_counter =
+ cpu_to_be16((u16)cntrs.symbol_error_counter);
+ if (cntrs.link_error_recovery_counter > 0xFFUL)
+ p->link_error_recovery_counter = 0xFF;
+ else
+ p->link_error_recovery_counter =
+ (u8)cntrs.link_error_recovery_counter;
+ if (cntrs.link_downed_counter > 0xFFUL)
+ p->link_downed_counter = 0xFF;
+ else
+ p->link_downed_counter = (u8)cntrs.link_downed_counter;
+ if (cntrs.port_rcv_errors > 0xFFFFUL)
+ p->port_rcv_errors = __constant_cpu_to_be16(0xFFFF);
+ else
+ p->port_rcv_errors =
+ cpu_to_be16((u16) cntrs.port_rcv_errors);
+ if (cntrs.port_rcv_remphys_errors > 0xFFFFUL)
+ p->port_rcv_remphys_errors = __constant_cpu_to_be16(0xFFFF);
+ else
+ p->port_rcv_remphys_errors =
+ cpu_to_be16((u16)cntrs.port_rcv_remphys_errors);
+ if (cntrs.port_xmit_discards > 0xFFFFUL)
+ p->port_xmit_discards = __constant_cpu_to_be16(0xFFFF);
+ else
+ p->port_xmit_discards =
+ cpu_to_be16((u16)cntrs.port_xmit_discards);
+ if (cntrs.port_xmit_data > 0xFFFFFFFFUL)
+ p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF);
+ else
+ p->port_xmit_data = cpu_to_be32((u32)cntrs.port_xmit_data);
+ if (cntrs.port_rcv_data > 0xFFFFFFFFUL)
+ p->port_rcv_data = __constant_cpu_to_be32(0xFFFFFFFF);
+ else
+ p->port_rcv_data = cpu_to_be32((u32)cntrs.port_rcv_data);
+ if (cntrs.port_xmit_packets > 0xFFFFFFFFUL)
+ p->port_xmit_packets = __constant_cpu_to_be32(0xFFFFFFFF);
+ else
+ p->port_xmit_packets =
+ cpu_to_be32((u32)cntrs.port_xmit_packets);
+ if (cntrs.port_rcv_packets > 0xFFFFFFFFUL)
+ p->port_rcv_packets = __constant_cpu_to_be32(0xFFFFFFFF);
+ else
+ p->port_rcv_packets =
+ cpu_to_be32((u32) cntrs.port_rcv_packets);
+
+ return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ib_pma_portcounters_ext *p =
+ (struct ib_pma_portcounters_ext *)pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ u64 swords, rwords, spkts, rpkts, xwait;
+ u8 port_select = p->port_select;
+
+ ipath_layer_snapshot_counters(dev->dd, &swords, &rwords, &spkts,
+ &rpkts, &xwait);
+
+ /* Adjust counters for any resets done. */
+ swords -= dev->n_port_xmit_data;
+ rwords -= dev->n_port_rcv_data;
+ spkts -= dev->n_port_xmit_packets;
+ rpkts -= dev->n_port_rcv_packets;
+
+ memset(pmp->data, 0, sizeof(pmp->data));
+
+ p->port_select = port_select;
+ if (pmp->attr_mod != 0 ||
+ (port_select != port && port_select != 0xFF))
+ pmp->status |= IB_SMP_INVALID_FIELD;
+
+ p->port_xmit_data = cpu_to_be64(swords);
+ p->port_rcv_data = cpu_to_be64(rwords);
+ p->port_xmit_packets = cpu_to_be64(spkts);
+ p->port_rcv_packets = cpu_to_be64(rpkts);
+ p->port_unicast_xmit_packets = cpu_to_be64(dev->n_unicast_xmit);
+ p->port_unicast_rcv_packets = cpu_to_be64(dev->n_unicast_rcv);
+ p->port_multicast_xmit_packets = cpu_to_be64(dev->n_multicast_xmit);
+ p->port_multicast_rcv_packets = cpu_to_be64(dev->n_multicast_rcv);
+
+ return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_set_portcounters(struct ib_perf *pmp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
+ pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ struct ipath_layer_counters cntrs;
+
+ /*
+ * Since the HW doesn't support clearing counters, we save the
+ * current count and subtract it from future responses.
+ */
+ ipath_layer_get_counters(dev->dd, &cntrs);
+
+ if (p->counter_select & IB_PMA_SEL_SYMBOL_ERROR)
+ dev->n_symbol_error_counter = cntrs.symbol_error_counter;
+
+ if (p->counter_select & IB_PMA_SEL_LINK_ERROR_RECOVERY)
+ dev->n_link_error_recovery_counter =
+ cntrs.link_error_recovery_counter;
+
+ if (p->counter_select & IB_PMA_SEL_LINK_DOWNED)
+ dev->n_link_downed_counter = cntrs.link_downed_counter;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_RCV_ERRORS)
+ dev->n_port_rcv_errors =
+ cntrs.port_rcv_errors + dev->rcv_errors;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS)
+ dev->n_port_rcv_remphys_errors =
+ cntrs.port_rcv_remphys_errors;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DISCARDS)
+ dev->n_port_xmit_discards = cntrs.port_xmit_discards;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA)
+ dev->n_port_xmit_data = cntrs.port_xmit_data;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_RCV_DATA)
+ dev->n_port_rcv_data = cntrs.port_rcv_data;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_XMIT_PACKETS)
+ dev->n_port_xmit_packets = cntrs.port_xmit_packets;
+
+ if (p->counter_select & IB_PMA_SEL_PORT_RCV_PACKETS)
+ dev->n_port_rcv_packets = cntrs.port_rcv_packets;
+
+ return recv_pma_get_portcounters(pmp, ibdev, port);
+}
+
+static int recv_pma_set_portcounters_ext(struct ib_perf *pmp,
+ struct ib_device *ibdev, u8 port)
+{
+ struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
+ pmp->data;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ u64 swords, rwords, spkts, rpkts, xwait;
+
+ ipath_layer_snapshot_counters(dev->dd, &swords, &rwords, &spkts,
+ &rpkts, &xwait);
+
+ if (p->counter_select & IB_PMA_SELX_PORT_XMIT_DATA)
+ dev->n_port_xmit_data = swords;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_RCV_DATA)
+ dev->n_port_rcv_data = rwords;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_XMIT_PACKETS)
+ dev->n_port_xmit_packets = spkts;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_RCV_PACKETS)
+ dev->n_port_rcv_packets = rpkts;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_UNI_XMIT_PACKETS)
+ dev->n_unicast_xmit = 0;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_UNI_RCV_PACKETS)
+ dev->n_unicast_rcv = 0;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS)
+ dev->n_multicast_xmit = 0;
+
+ if (p->counter_select & IB_PMA_SELX_PORT_MULTI_RCV_PACKETS)
+ dev->n_multicast_rcv = 0;
+
+ return recv_pma_get_portcounters_ext(pmp, ibdev, port);
+}
+
+static int process_subn(struct ib_device *ibdev, int mad_flags,
+ u8 port_num, struct ib_mad *in_mad,
+ struct ib_mad *out_mad)
+{
+ struct ib_smp *smp = (struct ib_smp *)out_mad;
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ int ret;
+
+ *out_mad = *in_mad;
+ if (smp->class_version != 1) {
+ smp->status |= IB_SMP_UNSUP_VERSION;
+ ret = reply(smp);
+ goto bail;
+ }
+
+ /* Is the mkey in the process of expiring? */
+ if (dev->mkey_lease_timeout && jiffies >= dev->mkey_lease_timeout) {
+ /* Clear timeout and mkey protection field. */
+ dev->mkey_lease_timeout = 0;
+ dev->mkeyprot_resv_lmc &= 0x3F;
+ }
+
+ /*
+ * M_Key checking depends on
+ * Portinfo:M_Key_protect_bits
+ */
+ if ((mad_flags & IB_MAD_IGNORE_MKEY) == 0 && dev->mkey != 0 &&
+ dev->mkey != smp->mkey &&
+ (smp->method == IB_MGMT_METHOD_SET ||
+ (smp->method == IB_MGMT_METHOD_GET &&
+ (dev->mkeyprot_resv_lmc >> 7) != 0))) {
+ if (dev->mkey_violations != 0xFFFF)
+ ++dev->mkey_violations;
+ if (dev->mkey_lease_timeout ||
+ dev->mkey_lease_period == 0) {
+ ret = IB_MAD_RESULT_SUCCESS |
+ IB_MAD_RESULT_CONSUMED;
+ goto bail;
+ }
+ dev->mkey_lease_timeout = jiffies +
+ dev->mkey_lease_period * HZ;
+ /* Future: Generate a trap notice. */
+ ret = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
+ goto bail;
+ } else if (dev->mkey_lease_timeout)
+ dev->mkey_lease_timeout = 0;
+
+ switch (smp->method) {
+ case IB_MGMT_METHOD_GET:
+ switch (smp->attr_id) {
+ case IB_SMP_ATTR_NODE_DESC:
+ ret = recv_subn_get_nodedescription(smp, ibdev);
+ goto bail;
+ case IB_SMP_ATTR_NODE_INFO:
+ ret = recv_subn_get_nodeinfo(smp, ibdev, port_num);
+ goto bail;
+ case IB_SMP_ATTR_GUID_INFO:
+ ret = recv_subn_get_guidinfo(smp, ibdev);
+ goto bail;
+ case IB_SMP_ATTR_PORT_INFO:
+ ret = recv_subn_get_portinfo(smp, ibdev, port_num);
+ goto bail;
+ case IB_SMP_ATTR_PKEY_TABLE:
+ ret = recv_subn_get_pkeytable(smp, ibdev);
+ goto bail;
+ case IB_SMP_ATTR_SM_INFO:
+ if (dev->port_cap_flags & IB_PORT_SM_DISABLED) {
+ ret = IB_MAD_RESULT_SUCCESS |
+ IB_MAD_RESULT_CONSUMED;
+ goto bail;
+ }
+ if (dev->port_cap_flags & IB_PORT_SM) {
+ ret = IB_MAD_RESULT_SUCCESS;
+ goto bail;
+ }
+ /* FALLTHROUGH */
+ default:
+ smp->status |= IB_SMP_UNSUP_METH_ATTR;
+ ret = reply(smp);
+ goto bail;
+ }
+
+ case IB_MGMT_METHOD_SET:
+ switch (smp->attr_id) {
+ case IB_SMP_ATTR_GUID_INFO:
+ ret = recv_subn_set_guidinfo(smp, ibdev);
+ goto bail;
+ case IB_SMP_ATTR_PORT_INFO:
+ ret = recv_subn_set_portinfo(smp, ibdev, port_num);
+ goto bail;
+ case IB_SMP_ATTR_PKEY_TABLE:
+ ret = recv_subn_set_pkeytable(smp, ibdev);
+ goto bail;
+ case IB_SMP_ATTR_SM_INFO:
+ if (dev->port_cap_flags & IB_PORT_SM_DISABLED) {
+ ret = IB_MAD_RESULT_SUCCESS |
+ IB_MAD_RESULT_CONSUMED;
+ goto bail;
+ }
+ if (dev->port_cap_flags & IB_PORT_SM) {
+ ret = IB_MAD_RESULT_SUCCESS;
+ goto bail;
+ }
+ /* FALLTHROUGH */
+ default:
+ smp->status |= IB_SMP_UNSUP_METH_ATTR;
+ ret = reply(smp);
+ goto bail;
+ }
+
+ case IB_MGMT_METHOD_GET_RESP:
+ /*
+ * The ib_mad module will call us to process responses
+ * before checking for other consumers.
+ * Just tell the caller to process it normally.
+ */
+ ret = IB_MAD_RESULT_FAILURE;
+ goto bail;
+ default:
+ smp->status |= IB_SMP_UNSUP_METHOD;
+ ret = reply(smp);
+ }
+
+bail:
+ return ret;
+}
+
+static int process_perf(struct ib_device *ibdev, u8 port_num,
+ struct ib_mad *in_mad,
+ struct ib_mad *out_mad)
+{
+ struct ib_perf *pmp = (struct ib_perf *)out_mad;
+ int ret;
+
+ *out_mad = *in_mad;
+ if (pmp->class_version != 1) {
+ pmp->status |= IB_SMP_UNSUP_VERSION;
+ ret = reply((struct ib_smp *) pmp);
+ goto bail;
+ }
+
+ switch (pmp->method) {
+ case IB_MGMT_METHOD_GET:
+ switch (pmp->attr_id) {
+ case IB_PMA_CLASS_PORT_INFO:
+ ret = recv_pma_get_classportinfo(pmp);
+ goto bail;
+ case IB_PMA_PORT_SAMPLES_CONTROL:
+ ret = recv_pma_get_portsamplescontrol(pmp, ibdev,
+ port_num);
+ goto bail;
+ case IB_PMA_PORT_SAMPLES_RESULT:
+ ret = recv_pma_get_portsamplesresult(pmp, ibdev);
+ goto bail;
+ case IB_PMA_PORT_SAMPLES_RESULT_EXT:
+ ret = recv_pma_get_portsamplesresult_ext(pmp,
+ ibdev);
+ goto bail;
+ case IB_PMA_PORT_COUNTERS:
+ ret = recv_pma_get_portcounters(pmp, ibdev,
+ port_num);
+ goto bail;
+ case IB_PMA_PORT_COUNTERS_EXT:
+ ret = recv_pma_get_portcounters_ext(pmp, ibdev,
+ port_num);
+ goto bail;
+ default:
+ pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ ret = reply((struct ib_smp *) pmp);
+ goto bail;
+ }
+
+ case IB_MGMT_METHOD_SET:
+ switch (pmp->attr_id) {
+ case IB_PMA_PORT_SAMPLES_CONTROL:
+ ret = recv_pma_set_portsamplescontrol(pmp, ibdev,
+ port_num);
+ goto bail;
+ case IB_PMA_PORT_COUNTERS:
+ ret = recv_pma_set_portcounters(pmp, ibdev,
+ port_num);
+ goto bail;
+ case IB_PMA_PORT_COUNTERS_EXT:
+ ret = recv_pma_set_portcounters_ext(pmp, ibdev,
+ port_num);
+ goto bail;
+ default:
+ pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+ ret = reply((struct ib_smp *) pmp);
+ goto bail;
+ }
+
+ case IB_MGMT_METHOD_GET_RESP:
+ /*
+ * The ib_mad module will call us to process responses
+ * before checking for other consumers.
+ * Just tell the caller to process it normally.
+ */
+ ret = IB_MAD_RESULT_FAILURE;
+ goto bail;
+ default:
+ pmp->status |= IB_SMP_UNSUP_METHOD;
+ ret = reply((struct ib_smp *) pmp);
+ }
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_process_mad - process an incoming MAD packet
+ * @ibdev: the infiniband device this packet came in on
+ * @mad_flags: MAD flags
+ * @port_num: the port number this packet came in on
+ * @in_wc: the work completion entry for this packet
+ * @in_grh: the global route header for this packet
+ * @in_mad: the incoming MAD
+ * @out_mad: any outgoing MAD reply
+ *
+ * Returns IB_MAD_RESULT_SUCCESS if this is a MAD that we are not
+ * interested in processing.
+ *
+ * Note that the verbs framework has already done the MAD sanity checks,
+ * and hop count/pointer updating for IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE
+ * MADs.
+ *
+ * This is called by the ib_mad module.
+ */
+int ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+ struct ib_wc *in_wc, struct ib_grh *in_grh,
+ struct ib_mad *in_mad, struct ib_mad *out_mad)
+{
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ int ret;
+
+ /*
+ * Snapshot current HW counters to "clear" them.
+ * This should be done when the driver is loaded except that for
+ * some reason we get a zillion errors when brining up the link.
+ */
+ if (dev->rcv_errors == 0) {
+ struct ipath_layer_counters cntrs;
+
+ ipath_layer_get_counters(to_idev(ibdev)->dd, &cntrs);
+ dev->rcv_errors++;
+ dev->n_symbol_error_counter = cntrs.symbol_error_counter;
+ dev->n_link_error_recovery_counter =
+ cntrs.link_error_recovery_counter;
+ dev->n_link_downed_counter = cntrs.link_downed_counter;
+ dev->n_port_rcv_errors = cntrs.port_rcv_errors + 1;
+ dev->n_port_rcv_remphys_errors =
+ cntrs.port_rcv_remphys_errors;
+ dev->n_port_xmit_discards = cntrs.port_xmit_discards;
+ dev->n_port_xmit_data = cntrs.port_xmit_data;
+ dev->n_port_rcv_data = cntrs.port_rcv_data;
+ dev->n_port_xmit_packets = cntrs.port_xmit_packets;
+ dev->n_port_rcv_packets = cntrs.port_rcv_packets;
+ }
+ switch (in_mad->mad_hdr.mgmt_class) {
+ case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
+ case IB_MGMT_CLASS_SUBN_LID_ROUTED:
+ ret = process_subn(ibdev, mad_flags, port_num,
+ in_mad, out_mad);
+ goto bail;
+ case IB_MGMT_CLASS_PERF_MGMT:
+ ret = process_perf(ibdev, port_num, in_mad, out_mad);
+ goto bail;
+ default:
+ ret = IB_MAD_RESULT_SUCCESS;
+ }
+
+bail:
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c b/drivers/infiniband/hw/ipath/ipath_mr.c
new file mode 100644
index 00000000000..69ffec66d45
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_pack.h>
+#include <rdma/ib_smi.h>
+
+#include "ipath_verbs.h"
+
+/**
+ * ipath_get_dma_mr - get a DMA memory region
+ * @pd: protection domain for this memory region
+ * @acc: access flags
+ *
+ * Returns the memory region on success, otherwise returns an errno.
+ */
+struct ib_mr *ipath_get_dma_mr(struct ib_pd *pd, int acc)
+{
+ struct ipath_mr *mr;
+ struct ib_mr *ret;
+
+ mr = kzalloc(sizeof *mr, GFP_KERNEL);
+ if (!mr) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ mr->mr.access_flags = acc;
+ ret = &mr->ibmr;
+
+bail:
+ return ret;
+}
+
+static struct ipath_mr *alloc_mr(int count,
+ struct ipath_lkey_table *lk_table)
+{
+ struct ipath_mr *mr;
+ int m, i = 0;
+
+ /* Allocate struct plus pointers to first level page tables. */
+ m = (count + IPATH_SEGSZ - 1) / IPATH_SEGSZ;
+ mr = kmalloc(sizeof *mr + m * sizeof mr->mr.map[0], GFP_KERNEL);
+ if (!mr)
+ goto done;
+
+ /* Allocate first level page tables. */
+ for (; i < m; i++) {
+ mr->mr.map[i] = kmalloc(sizeof *mr->mr.map[0], GFP_KERNEL);
+ if (!mr->mr.map[i])
+ goto bail;
+ }
+ mr->mr.mapsz = m;
+
+ /*
+ * ib_reg_phys_mr() will initialize mr->ibmr except for
+ * lkey and rkey.
+ */
+ if (!ipath_alloc_lkey(lk_table, &mr->mr))
+ goto bail;
+ mr->ibmr.rkey = mr->ibmr.lkey = mr->mr.lkey;
+
+ goto done;
+
+bail:
+ while (i) {
+ i--;
+ kfree(mr->mr.map[i]);
+ }
+ kfree(mr);
+ mr = NULL;
+
+done:
+ return mr;
+}
+
+/**
+ * ipath_reg_phys_mr - register a physical memory region
+ * @pd: protection domain for this memory region
+ * @buffer_list: pointer to the list of physical buffers to register
+ * @num_phys_buf: the number of physical buffers to register
+ * @iova_start: the starting address passed over IB which maps to this MR
+ *
+ * Returns the memory region on success, otherwise returns an errno.
+ */
+struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd,
+ struct ib_phys_buf *buffer_list,
+ int num_phys_buf, int acc, u64 *iova_start)
+{
+ struct ipath_mr *mr;
+ int n, m, i;
+ struct ib_mr *ret;
+
+ mr = alloc_mr(num_phys_buf, &to_idev(pd->device)->lk_table);
+ if (mr == NULL) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ mr->mr.user_base = *iova_start;
+ mr->mr.iova = *iova_start;
+ mr->mr.length = 0;
+ mr->mr.offset = 0;
+ mr->mr.access_flags = acc;
+ mr->mr.max_segs = num_phys_buf;
+
+ m = 0;
+ n = 0;
+ for (i = 0; i < num_phys_buf; i++) {
+ mr->mr.map[m]->segs[n].vaddr =
+ phys_to_virt(buffer_list[i].addr);
+ mr->mr.map[m]->segs[n].length = buffer_list[i].size;
+ mr->mr.length += buffer_list[i].size;
+ n++;
+ if (n == IPATH_SEGSZ) {
+ m++;
+ n = 0;
+ }
+ }
+
+ ret = &mr->ibmr;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_reg_user_mr - register a userspace memory region
+ * @pd: protection domain for this memory region
+ * @region: the user memory region
+ * @mr_access_flags: access flags for this memory region
+ * @udata: unused by the InfiniPath driver
+ *
+ * Returns the memory region on success, otherwise returns an errno.
+ */
+struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
+ int mr_access_flags, struct ib_udata *udata)
+{
+ struct ipath_mr *mr;
+ struct ib_umem_chunk *chunk;
+ int n, m, i;
+ struct ib_mr *ret;
+
+ n = 0;
+ list_for_each_entry(chunk, &region->chunk_list, list)
+ n += chunk->nents;
+
+ mr = alloc_mr(n, &to_idev(pd->device)->lk_table);
+ if (!mr) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ mr->mr.user_base = region->user_base;
+ mr->mr.iova = region->virt_base;
+ mr->mr.length = region->length;
+ mr->mr.offset = region->offset;
+ mr->mr.access_flags = mr_access_flags;
+ mr->mr.max_segs = n;
+
+ m = 0;
+ n = 0;
+ list_for_each_entry(chunk, &region->chunk_list, list) {
+ for (i = 0; i < chunk->nmap; i++) {
+ mr->mr.map[m]->segs[n].vaddr =
+ page_address(chunk->page_list[i].page);
+ mr->mr.map[m]->segs[n].length = region->page_size;
+ n++;
+ if (n == IPATH_SEGSZ) {
+ m++;
+ n = 0;
+ }
+ }
+ }
+ ret = &mr->ibmr;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_dereg_mr - unregister and free a memory region
+ * @ibmr: the memory region to free
+ *
+ * Returns 0 on success.
+ *
+ * Note that this is called to free MRs created by ipath_get_dma_mr()
+ * or ipath_reg_user_mr().
+ */
+int ipath_dereg_mr(struct ib_mr *ibmr)
+{
+ struct ipath_mr *mr = to_imr(ibmr);
+ int i;
+
+ ipath_free_lkey(&to_idev(ibmr->device)->lk_table, ibmr->lkey);
+ i = mr->mr.mapsz;
+ while (i) {
+ i--;
+ kfree(mr->mr.map[i]);
+ }
+ kfree(mr);
+ return 0;
+}
+
+/**
+ * ipath_alloc_fmr - allocate a fast memory region
+ * @pd: the protection domain for this memory region
+ * @mr_access_flags: access flags for this memory region
+ * @fmr_attr: fast memory region attributes
+ *
+ * Returns the memory region on success, otherwise returns an errno.
+ */
+struct ib_fmr *ipath_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
+ struct ib_fmr_attr *fmr_attr)
+{
+ struct ipath_fmr *fmr;
+ int m, i = 0;
+ struct ib_fmr *ret;
+
+ /* Allocate struct plus pointers to first level page tables. */
+ m = (fmr_attr->max_pages + IPATH_SEGSZ - 1) / IPATH_SEGSZ;
+ fmr = kmalloc(sizeof *fmr + m * sizeof fmr->mr.map[0], GFP_KERNEL);
+ if (!fmr)
+ goto bail;
+
+ /* Allocate first level page tables. */
+ for (; i < m; i++) {
+ fmr->mr.map[i] = kmalloc(sizeof *fmr->mr.map[0],
+ GFP_KERNEL);
+ if (!fmr->mr.map[i])
+ goto bail;
+ }
+ fmr->mr.mapsz = m;
+
+ /*
+ * ib_alloc_fmr() will initialize fmr->ibfmr except for lkey &
+ * rkey.
+ */
+ if (!ipath_alloc_lkey(&to_idev(pd->device)->lk_table, &fmr->mr))
+ goto bail;
+ fmr->ibfmr.rkey = fmr->ibfmr.lkey = fmr->mr.lkey;
+ /*
+ * Resources are allocated but no valid mapping (RKEY can't be
+ * used).
+ */
+ fmr->mr.user_base = 0;
+ fmr->mr.iova = 0;
+ fmr->mr.length = 0;
+ fmr->mr.offset = 0;
+ fmr->mr.access_flags = mr_access_flags;
+ fmr->mr.max_segs = fmr_attr->max_pages;
+ fmr->page_shift = fmr_attr->page_shift;
+
+ ret = &fmr->ibfmr;
+ goto done;
+
+bail:
+ while (i)
+ kfree(fmr->mr.map[--i]);
+ kfree(fmr);
+ ret = ERR_PTR(-ENOMEM);
+
+done:
+ return ret;
+}
+
+/**
+ * ipath_map_phys_fmr - set up a fast memory region
+ * @ibmfr: the fast memory region to set up
+ * @page_list: the list of pages to associate with the fast memory region
+ * @list_len: the number of pages to associate with the fast memory region
+ * @iova: the virtual address of the start of the fast memory region
+ *
+ * This may be called from interrupt context.
+ */
+
+int ipath_map_phys_fmr(struct ib_fmr *ibfmr, u64 * page_list,
+ int list_len, u64 iova)
+{
+ struct ipath_fmr *fmr = to_ifmr(ibfmr);
+ struct ipath_lkey_table *rkt;
+ unsigned long flags;
+ int m, n, i;
+ u32 ps;
+ int ret;
+
+ if (list_len > fmr->mr.max_segs) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ rkt = &to_idev(ibfmr->device)->lk_table;
+ spin_lock_irqsave(&rkt->lock, flags);
+ fmr->mr.user_base = iova;
+ fmr->mr.iova = iova;
+ ps = 1 << fmr->page_shift;
+ fmr->mr.length = list_len * ps;
+ m = 0;
+ n = 0;
+ ps = 1 << fmr->page_shift;
+ for (i = 0; i < list_len; i++) {
+ fmr->mr.map[m]->segs[n].vaddr = phys_to_virt(page_list[i]);
+ fmr->mr.map[m]->segs[n].length = ps;
+ if (++n == IPATH_SEGSZ) {
+ m++;
+ n = 0;
+ }
+ }
+ spin_unlock_irqrestore(&rkt->lock, flags);
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_unmap_fmr - unmap fast memory regions
+ * @fmr_list: the list of fast memory regions to unmap
+ *
+ * Returns 0 on success.
+ */
+int ipath_unmap_fmr(struct list_head *fmr_list)
+{
+ struct ipath_fmr *fmr;
+ struct ipath_lkey_table *rkt;
+ unsigned long flags;
+
+ list_for_each_entry(fmr, fmr_list, ibfmr.list) {
+ rkt = &to_idev(fmr->ibfmr.device)->lk_table;
+ spin_lock_irqsave(&rkt->lock, flags);
+ fmr->mr.user_base = 0;
+ fmr->mr.iova = 0;
+ fmr->mr.length = 0;
+ spin_unlock_irqrestore(&rkt->lock, flags);
+ }
+ return 0;
+}
+
+/**
+ * ipath_dealloc_fmr - deallocate a fast memory region
+ * @ibfmr: the fast memory region to deallocate
+ *
+ * Returns 0 on success.
+ */
+int ipath_dealloc_fmr(struct ib_fmr *ibfmr)
+{
+ struct ipath_fmr *fmr = to_ifmr(ibfmr);
+ int i;
+
+ ipath_free_lkey(&to_idev(ibfmr->device)->lk_table, ibfmr->lkey);
+ i = fmr->mr.mapsz;
+ while (i)
+ kfree(fmr->mr.map[--i]);
+ kfree(fmr);
+ return 0;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_pe800.c b/drivers/infiniband/hw/ipath/ipath_pe800.c
new file mode 100644
index 00000000000..02e8c75b24f
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_pe800.c
@@ -0,0 +1,1253 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+/*
+ * This file contains all of the code that is specific to the
+ * InfiniPath PE-800 chip.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+
+#include "ipath_kernel.h"
+#include "ipath_registers.h"
+
+/*
+ * This file contains all the chip-specific register information and
+ * access functions for the PathScale PE800, the PCI-Express chip.
+ *
+ * This lists the InfiniPath PE800 registers, in the actual chip layout.
+ * This structure should never be directly accessed.
+ */
+struct _infinipath_do_not_use_kernel_regs {
+ unsigned long long Revision;
+ unsigned long long Control;
+ unsigned long long PageAlign;
+ unsigned long long PortCnt;
+ unsigned long long DebugPortSelect;
+ unsigned long long Reserved0;
+ unsigned long long SendRegBase;
+ unsigned long long UserRegBase;
+ unsigned long long CounterRegBase;
+ unsigned long long Scratch;
+ unsigned long long Reserved1;
+ unsigned long long Reserved2;
+ unsigned long long IntBlocked;
+ unsigned long long IntMask;
+ unsigned long long IntStatus;
+ unsigned long long IntClear;
+ unsigned long long ErrorMask;
+ unsigned long long ErrorStatus;
+ unsigned long long ErrorClear;
+ unsigned long long HwErrMask;
+ unsigned long long HwErrStatus;
+ unsigned long long HwErrClear;
+ unsigned long long HwDiagCtrl;
+ unsigned long long MDIO;
+ unsigned long long IBCStatus;
+ unsigned long long IBCCtrl;
+ unsigned long long ExtStatus;
+ unsigned long long ExtCtrl;
+ unsigned long long GPIOOut;
+ unsigned long long GPIOMask;
+ unsigned long long GPIOStatus;
+ unsigned long long GPIOClear;
+ unsigned long long RcvCtrl;
+ unsigned long long RcvBTHQP;
+ unsigned long long RcvHdrSize;
+ unsigned long long RcvHdrCnt;
+ unsigned long long RcvHdrEntSize;
+ unsigned long long RcvTIDBase;
+ unsigned long long RcvTIDCnt;
+ unsigned long long RcvEgrBase;
+ unsigned long long RcvEgrCnt;
+ unsigned long long RcvBufBase;
+ unsigned long long RcvBufSize;
+ unsigned long long RxIntMemBase;
+ unsigned long long RxIntMemSize;
+ unsigned long long RcvPartitionKey;
+ unsigned long long Reserved3;
+ unsigned long long RcvPktLEDCnt;
+ unsigned long long Reserved4[8];
+ unsigned long long SendCtrl;
+ unsigned long long SendPIOBufBase;
+ unsigned long long SendPIOSize;
+ unsigned long long SendPIOBufCnt;
+ unsigned long long SendPIOAvailAddr;
+ unsigned long long TxIntMemBase;
+ unsigned long long TxIntMemSize;
+ unsigned long long Reserved5;
+ unsigned long long PCIeRBufTestReg0;
+ unsigned long long PCIeRBufTestReg1;
+ unsigned long long Reserved51[6];
+ unsigned long long SendBufferError;
+ unsigned long long SendBufferErrorCONT1;
+ unsigned long long Reserved6SBE[6];
+ unsigned long long RcvHdrAddr0;
+ unsigned long long RcvHdrAddr1;
+ unsigned long long RcvHdrAddr2;
+ unsigned long long RcvHdrAddr3;
+ unsigned long long RcvHdrAddr4;
+ unsigned long long Reserved7RHA[11];
+ unsigned long long RcvHdrTailAddr0;
+ unsigned long long RcvHdrTailAddr1;
+ unsigned long long RcvHdrTailAddr2;
+ unsigned long long RcvHdrTailAddr3;
+ unsigned long long RcvHdrTailAddr4;
+ unsigned long long Reserved8RHTA[11];
+ unsigned long long Reserved9SW[8];
+ unsigned long long SerdesConfig0;
+ unsigned long long SerdesConfig1;
+ unsigned long long SerdesStatus;
+ unsigned long long XGXSConfig;
+ unsigned long long IBPLLCfg;
+ unsigned long long Reserved10SW2[3];
+ unsigned long long PCIEQ0SerdesConfig0;
+ unsigned long long PCIEQ0SerdesConfig1;
+ unsigned long long PCIEQ0SerdesStatus;
+ unsigned long long Reserved11;
+ unsigned long long PCIEQ1SerdesConfig0;
+ unsigned long long PCIEQ1SerdesConfig1;
+ unsigned long long PCIEQ1SerdesStatus;
+ unsigned long long Reserved12;
+};
+
+#define IPATH_KREG_OFFSET(field) (offsetof(struct \
+ _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
+#define IPATH_CREG_OFFSET(field) (offsetof( \
+ struct infinipath_counters, field) / sizeof(u64))
+
+static const struct ipath_kregs ipath_pe_kregs = {
+ .kr_control = IPATH_KREG_OFFSET(Control),
+ .kr_counterregbase = IPATH_KREG_OFFSET(CounterRegBase),
+ .kr_debugportselect = IPATH_KREG_OFFSET(DebugPortSelect),
+ .kr_errorclear = IPATH_KREG_OFFSET(ErrorClear),
+ .kr_errormask = IPATH_KREG_OFFSET(ErrorMask),
+ .kr_errorstatus = IPATH_KREG_OFFSET(ErrorStatus),
+ .kr_extctrl = IPATH_KREG_OFFSET(ExtCtrl),
+ .kr_extstatus = IPATH_KREG_OFFSET(ExtStatus),
+ .kr_gpio_clear = IPATH_KREG_OFFSET(GPIOClear),
+ .kr_gpio_mask = IPATH_KREG_OFFSET(GPIOMask),
+ .kr_gpio_out = IPATH_KREG_OFFSET(GPIOOut),
+ .kr_gpio_status = IPATH_KREG_OFFSET(GPIOStatus),
+ .kr_hwdiagctrl = IPATH_KREG_OFFSET(HwDiagCtrl),
+ .kr_hwerrclear = IPATH_KREG_OFFSET(HwErrClear),
+ .kr_hwerrmask = IPATH_KREG_OFFSET(HwErrMask),
+ .kr_hwerrstatus = IPATH_KREG_OFFSET(HwErrStatus),
+ .kr_ibcctrl = IPATH_KREG_OFFSET(IBCCtrl),
+ .kr_ibcstatus = IPATH_KREG_OFFSET(IBCStatus),
+ .kr_intblocked = IPATH_KREG_OFFSET(IntBlocked),
+ .kr_intclear = IPATH_KREG_OFFSET(IntClear),
+ .kr_intmask = IPATH_KREG_OFFSET(IntMask),
+ .kr_intstatus = IPATH_KREG_OFFSET(IntStatus),
+ .kr_mdio = IPATH_KREG_OFFSET(MDIO),
+ .kr_pagealign = IPATH_KREG_OFFSET(PageAlign),
+ .kr_partitionkey = IPATH_KREG_OFFSET(RcvPartitionKey),
+ .kr_portcnt = IPATH_KREG_OFFSET(PortCnt),
+ .kr_rcvbthqp = IPATH_KREG_OFFSET(RcvBTHQP),
+ .kr_rcvbufbase = IPATH_KREG_OFFSET(RcvBufBase),
+ .kr_rcvbufsize = IPATH_KREG_OFFSET(RcvBufSize),
+ .kr_rcvctrl = IPATH_KREG_OFFSET(RcvCtrl),
+ .kr_rcvegrbase = IPATH_KREG_OFFSET(RcvEgrBase),
+ .kr_rcvegrcnt = IPATH_KREG_OFFSET(RcvEgrCnt),
+ .kr_rcvhdrcnt = IPATH_KREG_OFFSET(RcvHdrCnt),
+ .kr_rcvhdrentsize = IPATH_KREG_OFFSET(RcvHdrEntSize),
+ .kr_rcvhdrsize = IPATH_KREG_OFFSET(RcvHdrSize),
+ .kr_rcvintmembase = IPATH_KREG_OFFSET(RxIntMemBase),
+ .kr_rcvintmemsize = IPATH_KREG_OFFSET(RxIntMemSize),
+ .kr_rcvtidbase = IPATH_KREG_OFFSET(RcvTIDBase),
+ .kr_rcvtidcnt = IPATH_KREG_OFFSET(RcvTIDCnt),
+ .kr_revision = IPATH_KREG_OFFSET(Revision),
+ .kr_scratch = IPATH_KREG_OFFSET(Scratch),
+ .kr_sendbuffererror = IPATH_KREG_OFFSET(SendBufferError),
+ .kr_sendctrl = IPATH_KREG_OFFSET(SendCtrl),
+ .kr_sendpioavailaddr = IPATH_KREG_OFFSET(SendPIOAvailAddr),
+ .kr_sendpiobufbase = IPATH_KREG_OFFSET(SendPIOBufBase),
+ .kr_sendpiobufcnt = IPATH_KREG_OFFSET(SendPIOBufCnt),
+ .kr_sendpiosize = IPATH_KREG_OFFSET(SendPIOSize),
+ .kr_sendregbase = IPATH_KREG_OFFSET(SendRegBase),
+ .kr_txintmembase = IPATH_KREG_OFFSET(TxIntMemBase),
+ .kr_txintmemsize = IPATH_KREG_OFFSET(TxIntMemSize),
+ .kr_userregbase = IPATH_KREG_OFFSET(UserRegBase),
+ .kr_serdesconfig0 = IPATH_KREG_OFFSET(SerdesConfig0),
+ .kr_serdesconfig1 = IPATH_KREG_OFFSET(SerdesConfig1),
+ .kr_serdesstatus = IPATH_KREG_OFFSET(SerdesStatus),
+ .kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig),
+ .kr_ibpllcfg = IPATH_KREG_OFFSET(IBPLLCfg),
+
+ /*
+ * These should not be used directly via ipath_read_kreg64(),
+ * use them with ipath_read_kreg64_port()
+ */
+ .kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0),
+ .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0),
+
+ /* This group is pe-800-specific; and used only in this file */
+ /* The rcvpktled register controls one of the debug port signals, so
+ * a packet activity LED can be connected to it. */
+ .kr_rcvpktledcnt = IPATH_KREG_OFFSET(RcvPktLEDCnt),
+ .kr_pcierbuftestreg0 = IPATH_KREG_OFFSET(PCIeRBufTestReg0),
+ .kr_pcierbuftestreg1 = IPATH_KREG_OFFSET(PCIeRBufTestReg1),
+ .kr_pcieq0serdesconfig0 = IPATH_KREG_OFFSET(PCIEQ0SerdesConfig0),
+ .kr_pcieq0serdesconfig1 = IPATH_KREG_OFFSET(PCIEQ0SerdesConfig1),
+ .kr_pcieq0serdesstatus = IPATH_KREG_OFFSET(PCIEQ0SerdesStatus),
+ .kr_pcieq1serdesconfig0 = IPATH_KREG_OFFSET(PCIEQ1SerdesConfig0),
+ .kr_pcieq1serdesconfig1 = IPATH_KREG_OFFSET(PCIEQ1SerdesConfig1),
+ .kr_pcieq1serdesstatus = IPATH_KREG_OFFSET(PCIEQ1SerdesStatus)
+};
+
+static const struct ipath_cregs ipath_pe_cregs = {
+ .cr_badformatcnt = IPATH_CREG_OFFSET(RxBadFormatCnt),
+ .cr_erricrccnt = IPATH_CREG_OFFSET(RxICRCErrCnt),
+ .cr_errlinkcnt = IPATH_CREG_OFFSET(RxLinkProblemCnt),
+ .cr_errlpcrccnt = IPATH_CREG_OFFSET(RxLPCRCErrCnt),
+ .cr_errpkey = IPATH_CREG_OFFSET(RxPKeyMismatchCnt),
+ .cr_errrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowCtrlErrCnt),
+ .cr_err_rlencnt = IPATH_CREG_OFFSET(RxLenErrCnt),
+ .cr_errslencnt = IPATH_CREG_OFFSET(TxLenErrCnt),
+ .cr_errtidfull = IPATH_CREG_OFFSET(RxTIDFullErrCnt),
+ .cr_errtidvalid = IPATH_CREG_OFFSET(RxTIDValidErrCnt),
+ .cr_errvcrccnt = IPATH_CREG_OFFSET(RxVCRCErrCnt),
+ .cr_ibstatuschange = IPATH_CREG_OFFSET(IBStatusChangeCnt),
+ .cr_intcnt = IPATH_CREG_OFFSET(LBIntCnt),
+ .cr_invalidrlencnt = IPATH_CREG_OFFSET(RxMaxMinLenErrCnt),
+ .cr_invalidslencnt = IPATH_CREG_OFFSET(TxMaxMinLenErrCnt),
+ .cr_lbflowstallcnt = IPATH_CREG_OFFSET(LBFlowStallCnt),
+ .cr_pktrcvcnt = IPATH_CREG_OFFSET(RxDataPktCnt),
+ .cr_pktrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowPktCnt),
+ .cr_pktsendcnt = IPATH_CREG_OFFSET(TxDataPktCnt),
+ .cr_pktsendflowcnt = IPATH_CREG_OFFSET(TxFlowPktCnt),
+ .cr_portovflcnt = IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt),
+ .cr_rcvebpcnt = IPATH_CREG_OFFSET(RxEBPCnt),
+ .cr_rcvovflcnt = IPATH_CREG_OFFSET(RxBufOvflCnt),
+ .cr_senddropped = IPATH_CREG_OFFSET(TxDroppedPktCnt),
+ .cr_sendstallcnt = IPATH_CREG_OFFSET(TxFlowStallCnt),
+ .cr_sendunderruncnt = IPATH_CREG_OFFSET(TxUnderrunCnt),
+ .cr_wordrcvcnt = IPATH_CREG_OFFSET(RxDwordCnt),
+ .cr_wordsendcnt = IPATH_CREG_OFFSET(TxDwordCnt),
+ .cr_unsupvlcnt = IPATH_CREG_OFFSET(TxUnsupVLErrCnt),
+ .cr_rxdroppktcnt = IPATH_CREG_OFFSET(RxDroppedPktCnt),
+ .cr_iblinkerrrecovcnt = IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt),
+ .cr_iblinkdowncnt = IPATH_CREG_OFFSET(IBLinkDownedCnt),
+ .cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt)
+};
+
+/* kr_intstatus, kr_intclear, kr_intmask bits */
+#define INFINIPATH_I_RCVURG_MASK 0x1F
+#define INFINIPATH_I_RCVAVAIL_MASK 0x1F
+
+/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+#define INFINIPATH_HWE_PCIEMEMPARITYERR_MASK 0x000000000000003fULL
+#define INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT 0
+#define INFINIPATH_HWE_PCIEPOISONEDTLP 0x0000000010000000ULL
+#define INFINIPATH_HWE_PCIECPLTIMEOUT 0x0000000020000000ULL
+#define INFINIPATH_HWE_PCIEBUSPARITYXTLH 0x0000000040000000ULL
+#define INFINIPATH_HWE_PCIEBUSPARITYXADM 0x0000000080000000ULL
+#define INFINIPATH_HWE_PCIEBUSPARITYRADM 0x0000000100000000ULL
+#define INFINIPATH_HWE_COREPLL_FBSLIP 0x0080000000000000ULL
+#define INFINIPATH_HWE_COREPLL_RFSLIP 0x0100000000000000ULL
+#define INFINIPATH_HWE_PCIE1PLLFAILED 0x0400000000000000ULL
+#define INFINIPATH_HWE_PCIE0PLLFAILED 0x0800000000000000ULL
+#define INFINIPATH_HWE_SERDESPLLFAILED 0x1000000000000000ULL
+
+/* kr_extstatus bits */
+#define INFINIPATH_EXTS_FREQSEL 0x2
+#define INFINIPATH_EXTS_SERDESSEL 0x4
+#define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000
+#define INFINIPATH_EXTS_MEMBIST_FOUND 0x0000000000008000
+
+#define _IPATH_GPIO_SDA_NUM 1
+#define _IPATH_GPIO_SCL_NUM 0
+
+#define IPATH_GPIO_SDA (1ULL << \
+ (_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+#define IPATH_GPIO_SCL (1ULL << \
+ (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+
+/**
+ * ipath_pe_handle_hwerrors - display hardware errors.
+ * @dd: the infinipath device
+ * @msg: the output buffer
+ * @msgl: the size of the output buffer
+ *
+ * Use same msg buffer as regular errors to avoid excessive stack
+ * use. Most hardware errors are catastrophic, but for right now,
+ * we'll print them and continue. We reuse the same message buffer as
+ * ipath_handle_errors() to avoid excessive stack usage.
+ */
+static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ size_t msgl)
+{
+ ipath_err_t hwerrs;
+ u32 bits, ctrl;
+ int isfatal = 0;
+ char bitsmsg[64];
+
+ hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
+ if (!hwerrs) {
+ /*
+ * better than printing cofusing messages
+ * This seems to be related to clearing the crc error, or
+ * the pll error during init.
+ */
+ ipath_cdbg(VERBOSE, "Called but no hardware errors set\n");
+ return;
+ } else if (hwerrs == ~0ULL) {
+ ipath_dev_err(dd, "Read of hardware error status failed "
+ "(all bits set); ignoring\n");
+ return;
+ }
+ ipath_stats.sps_hwerrs++;
+
+ /* Always clear the error status register, except MEMBISTFAIL,
+ * regardless of whether we continue or stop using the chip.
+ * We want that set so we know it failed, even across driver reload.
+ * We'll still ignore it in the hwerrmask. We do this partly for
+ * diagnostics, but also for support */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ hwerrs&~INFINIPATH_HWE_MEMBISTFAILED);
+
+ hwerrs &= dd->ipath_hwerrmask;
+
+ /*
+ * make sure we get this much out, unless told to be quiet,
+ * or it's occurred within the last 5 seconds
+ */
+ if ((hwerrs & ~dd->ipath_lasthwerror) ||
+ (ipath_debug & __IPATH_VERBDBG))
+ dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "
+ "(cleared)\n", (unsigned long long) hwerrs);
+ dd->ipath_lasthwerror |= hwerrs;
+
+ if (hwerrs & ~infinipath_hwe_bitsextant)
+ ipath_dev_err(dd, "hwerror interrupt with unknown errors "
+ "%llx set\n", (unsigned long long)
+ (hwerrs & ~infinipath_hwe_bitsextant));
+
+ ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
+ if (ctrl & INFINIPATH_C_FREEZEMODE) {
+ if (hwerrs) {
+ /*
+ * if any set that we aren't ignoring only make the
+ * complaint once, in case it's stuck or recurring,
+ * and we get here multiple times
+ */
+ if (dd->ipath_flags & IPATH_INITTED) {
+ ipath_dev_err(dd, "Fatal Error (freeze "
+ "mode), no longer usable\n");
+ isfatal = 1;
+ }
+ /*
+ * Mark as having had an error for driver, and also
+ * for /sys and status word mapped to user programs.
+ * This marks unit as not usable, until reset
+ */
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+ *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+ dd->ipath_flags &= ~IPATH_INITTED;
+ } else {
+ ipath_dbg("Clearing freezemode on ignored hardware "
+ "error\n");
+ ctrl &= ~INFINIPATH_C_FREEZEMODE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+ ctrl);
+ }
+ }
+
+ *msg = '\0';
+
+ if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) {
+ strlcat(msg, "[Memory BIST test failed, PE-800 unusable]",
+ msgl);
+ /* ignore from now on, so disable until driver reloaded */
+ *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+ dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ }
+ if (hwerrs & (INFINIPATH_HWE_RXEMEMPARITYERR_MASK
+ << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)) {
+ bits = (u32) ((hwerrs >>
+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) &
+ INFINIPATH_HWE_RXEMEMPARITYERR_MASK);
+ snprintf(bitsmsg, sizeof bitsmsg, "[RXE Parity Errs %x] ",
+ bits);
+ strlcat(msg, bitsmsg, msgl);
+ }
+ if (hwerrs & (INFINIPATH_HWE_TXEMEMPARITYERR_MASK
+ << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {
+ bits = (u32) ((hwerrs >>
+ INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) &
+ INFINIPATH_HWE_TXEMEMPARITYERR_MASK);
+ snprintf(bitsmsg, sizeof bitsmsg, "[TXE Parity Errs %x] ",
+ bits);
+ strlcat(msg, bitsmsg, msgl);
+ }
+ if (hwerrs & (INFINIPATH_HWE_PCIEMEMPARITYERR_MASK
+ << INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT)) {
+ bits = (u32) ((hwerrs >>
+ INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) &
+ INFINIPATH_HWE_PCIEMEMPARITYERR_MASK);
+ snprintf(bitsmsg, sizeof bitsmsg,
+ "[PCIe Mem Parity Errs %x] ", bits);
+ strlcat(msg, bitsmsg, msgl);
+ }
+ if (hwerrs & INFINIPATH_HWE_IBCBUSTOSPCPARITYERR)
+ strlcat(msg, "[IB2IPATH Parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_IBCBUSFRSPCPARITYERR)
+ strlcat(msg, "[IPATH2IB Parity]", msgl);
+
+#define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP | \
+ INFINIPATH_HWE_COREPLL_RFSLIP )
+
+ if (hwerrs & _IPATH_PLL_FAIL) {
+ snprintf(bitsmsg, sizeof bitsmsg,
+ "[PLL failed (%llx), PE-800 unusable]",
+ (unsigned long long) hwerrs & _IPATH_PLL_FAIL);
+ strlcat(msg, bitsmsg, msgl);
+ /* ignore from now on, so disable until driver reloaded */
+ dd->ipath_hwerrmask &= ~(hwerrs & _IPATH_PLL_FAIL);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ }
+
+ if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) {
+ /*
+ * If it occurs, it is left masked since the eternal
+ * interface is unused
+ */
+ dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+ dd->ipath_hwerrmask);
+ }
+
+ if (hwerrs & INFINIPATH_HWE_PCIEPOISONEDTLP)
+ strlcat(msg, "[PCIe Poisoned TLP]", msgl);
+ if (hwerrs & INFINIPATH_HWE_PCIECPLTIMEOUT)
+ strlcat(msg, "[PCIe completion timeout]", msgl);
+
+ /*
+ * In practice, it's unlikely wthat we'll see PCIe PLL, or bus
+ * parity or memory parity error failures, because most likely we
+ * won't be able to talk to the core of the chip. Nonetheless, we
+ * might see them, if they are in parts of the PCIe core that aren't
+ * essential.
+ */
+ if (hwerrs & INFINIPATH_HWE_PCIE1PLLFAILED)
+ strlcat(msg, "[PCIePLL1]", msgl);
+ if (hwerrs & INFINIPATH_HWE_PCIE0PLLFAILED)
+ strlcat(msg, "[PCIePLL0]", msgl);
+ if (hwerrs & INFINIPATH_HWE_PCIEBUSPARITYXTLH)
+ strlcat(msg, "[PCIe XTLH core parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_PCIEBUSPARITYXADM)
+ strlcat(msg, "[PCIe ADM TX core parity]", msgl);
+ if (hwerrs & INFINIPATH_HWE_PCIEBUSPARITYRADM)
+ strlcat(msg, "[PCIe ADM RX core parity]", msgl);
+
+ if (hwerrs & INFINIPATH_HWE_RXDSYNCMEMPARITYERR)
+ strlcat(msg, "[Rx Dsync]", msgl);
+ if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED)
+ strlcat(msg, "[SerDes PLL]", msgl);
+
+ ipath_dev_err(dd, "%s hardware error\n", msg);
+ if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) {
+ /*
+ * for /sys status file ; if no trailing } is copied, we'll
+ * know it was truncated.
+ */
+ snprintf(dd->ipath_freezemsg, dd->ipath_freezelen,
+ "{%s}", msg);
+ }
+}
+
+/**
+ * ipath_pe_boardname - fill in the board name
+ * @dd: the infinipath device
+ * @name: the output buffer
+ * @namelen: the size of the output buffer
+ *
+ * info is based on the board revision register
+ */
+static int ipath_pe_boardname(struct ipath_devdata *dd, char *name,
+ size_t namelen)
+{
+ char *n = NULL;
+ u8 boardrev = dd->ipath_boardrev;
+ int ret;
+
+ switch (boardrev) {
+ case 0:
+ n = "InfiniPath_Emulation";
+ break;
+ case 1:
+ n = "InfiniPath_PE-800-Bringup";
+ break;
+ case 2:
+ n = "InfiniPath_PE-880";
+ break;
+ case 3:
+ n = "InfiniPath_PE-850";
+ break;
+ case 4:
+ n = "InfiniPath_PE-860";
+ break;
+ default:
+ ipath_dev_err(dd,
+ "Don't yet know about board with ID %u\n",
+ boardrev);
+ snprintf(name, namelen, "Unknown_InfiniPath_PE-8xx_%u",
+ boardrev);
+ break;
+ }
+ if (n)
+ snprintf(name, namelen, "%s", n);
+
+ if (dd->ipath_majrev != 4 || dd->ipath_minrev != 1) {
+ ipath_dev_err(dd, "Unsupported PE-800 revision %u.%u!\n",
+ dd->ipath_majrev, dd->ipath_minrev);
+ ret = 1;
+ } else
+ ret = 0;
+
+ return ret;
+}
+
+/**
+ * ipath_pe_init_hwerrors - enable hardware errors
+ * @dd: the infinipath device
+ *
+ * now that we have finished initializing everything that might reasonably
+ * cause a hardware error, and cleared those errors bits as they occur,
+ * we can enable hardware errors in the mask (potentially enabling
+ * freeze mode), and enable hardware errors as errors (along with
+ * everything else) in errormask
+ */
+static void ipath_pe_init_hwerrors(struct ipath_devdata *dd)
+{
+ ipath_err_t val;
+ u64 extsval;
+
+ extsval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+
+ if (!(extsval & INFINIPATH_EXTS_MEMBIST_ENDTEST))
+ ipath_dev_err(dd, "MemBIST did not complete!\n");
+
+ val = ~0ULL; /* barring bugs, all hwerrors become interrupts, */
+
+ if (!dd->ipath_boardrev) // no PLL for Emulator
+ val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+
+ /* workaround bug 9460 in internal interface bus parity checking */
+ val &= ~INFINIPATH_HWE_PCIEBUSPARITYRADM;
+
+ dd->ipath_hwerrmask = val;
+}
+
+/**
+ * ipath_pe_bringup_serdes - bring up the serdes
+ * @dd: the infinipath device
+ */
+static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
+{
+ u64 val, tmp, config1;
+ int ret = 0, change = 0;
+
+ ipath_dbg("Trying to bringup serdes\n");
+
+ if (ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus) &
+ INFINIPATH_HWE_SERDESPLLFAILED) {
+ ipath_dbg("At start, serdes PLL failed bit set "
+ "in hwerrstatus, clearing and continuing\n");
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ INFINIPATH_HWE_SERDESPLLFAILED);
+ }
+
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+ config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1);
+
+ ipath_cdbg(VERBOSE, "SerDes status config0=%llx config1=%llx, "
+ "xgxsconfig %llx\n", (unsigned long long) val,
+ (unsigned long long) config1, (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+
+ /*
+ * Force reset on, also set rxdetect enable. Must do before reading
+ * serdesstatus at least for simulation, or some of the bits in
+ * serdes status will come back as undefined and cause simulation
+ * failures
+ */
+ val |= INFINIPATH_SERDC0_RESET_PLL | INFINIPATH_SERDC0_RXDETECT_EN
+ | INFINIPATH_SERDC0_L1PWR_DN;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+ /* be sure chip saw it */
+ tmp = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ udelay(5); /* need pll reset set at least for a bit */
+ /*
+ * after PLL is reset, set the per-lane Resets and TxIdle and
+ * clear the PLL reset and rxdetect (to get falling edge).
+ * Leave L1PWR bits set (permanently)
+ */
+ val &= ~(INFINIPATH_SERDC0_RXDETECT_EN | INFINIPATH_SERDC0_RESET_PLL
+ | INFINIPATH_SERDC0_L1PWR_DN);
+ val |= INFINIPATH_SERDC0_RESET_MASK | INFINIPATH_SERDC0_TXIDLE;
+ ipath_cdbg(VERBOSE, "Clearing pll reset and setting lane resets "
+ "and txidle (%llx)\n", (unsigned long long) val);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+ /* be sure chip saw it */
+ tmp = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ /* need PLL reset clear for at least 11 usec before lane
+ * resets cleared; give it a few more to be sure */
+ udelay(15);
+ val &= ~(INFINIPATH_SERDC0_RESET_MASK | INFINIPATH_SERDC0_TXIDLE);
+
+ ipath_cdbg(VERBOSE, "Clearing lane resets and txidle "
+ "(writing %llx)\n", (unsigned long long) val);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+ /* be sure chip saw it */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+ if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
+ INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
+ val &=
+ ~(INFINIPATH_XGXS_MDIOADDR_MASK <<
+ INFINIPATH_XGXS_MDIOADDR_SHIFT);
+ /* MDIO address 3 */
+ val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
+ change = 1;
+ }
+ if (val & INFINIPATH_XGXS_RESET) {
+ val &= ~INFINIPATH_XGXS_RESET;
+ change = 1;
+ }
+ if (change)
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
+
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+
+ /* clear current and de-emphasis bits */
+ config1 &= ~0x0ffffffff00ULL;
+ /* set current to 20ma */
+ config1 |= 0x00000000000ULL;
+ /* set de-emphasis to -5.68dB */
+ config1 |= 0x0cccc000000ULL;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig1, config1);
+
+ ipath_cdbg(VERBOSE, "done: SerDes status config0=%llx "
+ "config1=%llx, sstatus=%llx xgxs=%llx\n",
+ (unsigned long long) val, (unsigned long long) config1,
+ (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus),
+ (unsigned long long)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+
+ if (!ipath_waitfor_mdio_cmdready(dd)) {
+ ipath_write_kreg(
+ dd, dd->ipath_kregs->kr_mdio,
+ ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,
+ IPATH_MDIO_CTRL_XGXS_REG_8, 0));
+ if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,
+ IPATH_MDIO_DATAVALID, &val))
+ ipath_dbg("Never got MDIO data for XGXS "
+ "status read\n");
+ else
+ ipath_cdbg(VERBOSE, "MDIO Read reg8, "
+ "'bank' 31 %x\n", (u32) val);
+ } else
+ ipath_dbg("Never got MDIO cmdready for XGXS status read\n");
+
+ return ret;
+}
+
+/**
+ * ipath_pe_quiet_serdes - set serdes to txidle
+ * @dd: the infinipath device
+ * Called when driver is being unloaded
+ */
+static void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
+{
+ u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+
+ val |= INFINIPATH_SERDC0_TXIDLE;
+ ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n",
+ (unsigned long long) val);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+}
+
+/* this is not yet needed on the PE800, so just return 0. */
+static int ipath_pe_intconfig(struct ipath_devdata *dd)
+{
+ return 0;
+}
+
+/**
+ * ipath_setup_pe_setextled - set the state of the two external LEDs
+ * @dd: the infinipath device
+ * @lst: the L state
+ * @ltst: the LT state
+
+ * These LEDs indicate the physical and logical state of IB link.
+ * For this chip (at least with recommended board pinouts), LED1
+ * is Yellow (logical state) and LED2 is Green (physical state),
+ *
+ * Note: We try to match the Mellanox HCA LED behavior as best
+ * we can. Green indicates physical link state is OK (something is
+ * plugged in, and we can train).
+ * Amber indicates the link is logically up (ACTIVE).
+ * Mellanox further blinks the amber LED to indicate data packet
+ * activity, but we have no hardware support for that, so it would
+ * require waking up every 10-20 msecs and checking the counters
+ * on the chip, and then turning the LED off if appropriate. That's
+ * visible overhead, so not something we will do.
+ *
+ */
+static void ipath_setup_pe_setextled(struct ipath_devdata *dd, u64 lst,
+ u64 ltst)
+{
+ u64 extctl;
+
+ /* the diags use the LED to indicate diag info, so we leave
+ * the external LED alone when the diags are running */
+ if (ipath_diag_inuse)
+ return;
+
+ extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON |
+ INFINIPATH_EXTC_LED2PRIPORT_ON);
+
+ if (ltst & INFINIPATH_IBCS_LT_STATE_LINKUP)
+ extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON;
+ if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
+ extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
+ dd->ipath_extctrl = extctl;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
+}
+
+/**
+ * ipath_setup_pe_cleanup - clean up any per-chip chip-specific stuff
+ * @dd: the infinipath device
+ *
+ * This is called during driver unload.
+ * We do the pci_disable_msi here, not in generic code, because it
+ * isn't used for the HT-400. If we do end up needing pci_enable_msi
+ * at some point in the future for HT-400, we'll move the call back
+ * into the main init_one code.
+ */
+static void ipath_setup_pe_cleanup(struct ipath_devdata *dd)
+{
+ dd->ipath_msi_lo = 0; /* just in case unload fails */
+ pci_disable_msi(dd->pcidev);
+}
+
+/**
+ * ipath_setup_pe_config - setup PCIe config related stuff
+ * @dd: the infinipath device
+ * @pdev: the PCI device
+ *
+ * The pci_enable_msi() call will fail on systems with MSI quirks
+ * such as those with AMD8131, even if the device of interest is not
+ * attached to that device, (in the 2.6.13 - 2.6.15 kernels, at least, fixed
+ * late in 2.6.16).
+ * All that can be done is to edit the kernel source to remove the quirk
+ * check until that is fixed.
+ * We do not need to call enable_msi() for our HyperTransport chip (HT-400),
+ * even those it uses MSI, and we want to avoid the quirk warning, so
+ * So we call enable_msi only for the PE-800. If we do end up needing
+ * pci_enable_msi at some point in the future for HT-400, we'll move the
+ * call back into the main init_one code.
+ * We save the msi lo and hi values, so we can restore them after
+ * chip reset (the kernel PCI infrastructure doesn't yet handle that
+ * correctly).
+ */
+static int ipath_setup_pe_config(struct ipath_devdata *dd,
+ struct pci_dev *pdev)
+{
+ int pos, ret;
+
+ dd->ipath_msi_lo = 0; /* used as a flag during reset processing */
+ ret = pci_enable_msi(dd->pcidev);
+ if (ret)
+ ipath_dev_err(dd, "pci_enable_msi failed: %d, "
+ "interrupts may not work\n", ret);
+ /* continue even if it fails, we may still be OK... */
+
+ if ((pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_MSI))) {
+ u16 control;
+ pci_read_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_LO,
+ &dd->ipath_msi_lo);
+ pci_read_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_HI,
+ &dd->ipath_msi_hi);
+ pci_read_config_word(dd->pcidev, pos + PCI_MSI_FLAGS,
+ &control);
+ /* now save the data (vector) info */
+ pci_read_config_word(dd->pcidev,
+ pos + ((control & PCI_MSI_FLAGS_64BIT)
+ ? 12 : 8),
+ &dd->ipath_msi_data);
+ ipath_cdbg(VERBOSE, "Read msi data 0x%x from config offset "
+ "0x%x, control=0x%x\n", dd->ipath_msi_data,
+ pos + ((control & PCI_MSI_FLAGS_64BIT) ? 12 : 8),
+ control);
+ /* we save the cachelinesize also, although it doesn't
+ * really matter */
+ pci_read_config_byte(dd->pcidev, PCI_CACHE_LINE_SIZE,
+ &dd->ipath_pci_cacheline);
+ } else
+ ipath_dev_err(dd, "Can't find MSI capability, "
+ "can't save MSI settings for reset\n");
+ if ((pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP))) {
+ u16 linkstat;
+ pci_read_config_word(dd->pcidev, pos + PCI_EXP_LNKSTA,
+ &linkstat);
+ linkstat >>= 4;
+ linkstat &= 0x1f;
+ if (linkstat != 8)
+ ipath_dev_err(dd, "PCIe width %u, "
+ "performance reduced\n", linkstat);
+ }
+ else
+ ipath_dev_err(dd, "Can't find PCI Express "
+ "capability!\n");
+ return 0;
+}
+
+static void ipath_init_pe_variables(void)
+{
+ /*
+ * bits for selecting i2c direction and values,
+ * used for I2C serial flash
+ */
+ ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
+ ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
+ ipath_gpio_sda = IPATH_GPIO_SDA;
+ ipath_gpio_scl = IPATH_GPIO_SCL;
+
+ /* variables for sanity checking interrupt and errors */
+ infinipath_hwe_bitsextant =
+ (INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) |
+ (INFINIPATH_HWE_PCIEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) |
+ INFINIPATH_HWE_PCIE1PLLFAILED |
+ INFINIPATH_HWE_PCIE0PLLFAILED |
+ INFINIPATH_HWE_PCIEPOISONEDTLP |
+ INFINIPATH_HWE_PCIECPLTIMEOUT |
+ INFINIPATH_HWE_PCIEBUSPARITYXTLH |
+ INFINIPATH_HWE_PCIEBUSPARITYXADM |
+ INFINIPATH_HWE_PCIEBUSPARITYRADM |
+ INFINIPATH_HWE_MEMBISTFAILED |
+ INFINIPATH_HWE_COREPLL_FBSLIP |
+ INFINIPATH_HWE_COREPLL_RFSLIP |
+ INFINIPATH_HWE_SERDESPLLFAILED |
+ INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |
+ INFINIPATH_HWE_IBCBUSFRSPCPARITYERR;
+ infinipath_i_bitsextant =
+ (INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
+ (INFINIPATH_I_RCVAVAIL_MASK <<
+ INFINIPATH_I_RCVAVAIL_SHIFT) |
+ INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT |
+ INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO;
+ infinipath_e_bitsextant =
+ INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC |
+ INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN |
+ INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN |
+ INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RUNEXPCHAR |
+ INFINIPATH_E_RUNSUPVL | INFINIPATH_E_REBP |
+ INFINIPATH_E_RIBFLOW | INFINIPATH_E_RBADVERSION |
+ INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
+ INFINIPATH_E_RBADTID | INFINIPATH_E_RHDRLEN |
+ INFINIPATH_E_RHDR | INFINIPATH_E_RIBLOSTLINK |
+ INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SMAXPKTLEN |
+ INFINIPATH_E_SUNDERRUN | INFINIPATH_E_SPKTLEN |
+ INFINIPATH_E_SDROPPEDSMPPKT | INFINIPATH_E_SDROPPEDDATAPKT |
+ INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM |
+ INFINIPATH_E_SUNSUPVL | INFINIPATH_E_IBSTATUSCHANGED |
+ INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET |
+ INFINIPATH_E_HARDWARE;
+
+ infinipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
+ infinipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+}
+
+/* setup the MSI stuff again after a reset. I'd like to just call
+ * pci_enable_msi() and request_irq() again, but when I do that,
+ * the MSI enable bit doesn't get set in the command word, and
+ * we switch to to a different interrupt vector, which is confusing,
+ * so I instead just do it all inline. Perhaps somehow can tie this
+ * into the PCIe hotplug support at some point
+ * Note, because I'm doing it all here, I don't call pci_disable_msi()
+ * or free_irq() at the start of ipath_setup_pe_reset().
+ */
+static int ipath_reinit_msi(struct ipath_devdata *dd)
+{
+ int pos;
+ u16 control;
+ int ret;
+
+ if (!dd->ipath_msi_lo) {
+ dev_info(&dd->pcidev->dev, "Can't restore MSI config, "
+ "initial setup failed?\n");
+ ret = 0;
+ goto bail;
+ }
+
+ if (!(pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_MSI))) {
+ ipath_dev_err(dd, "Can't find MSI capability, "
+ "can't restore MSI settings\n");
+ ret = 0;
+ goto bail;
+ }
+ ipath_cdbg(VERBOSE, "Writing msi_lo 0x%x to config offset 0x%x\n",
+ dd->ipath_msi_lo, pos + PCI_MSI_ADDRESS_LO);
+ pci_write_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_LO,
+ dd->ipath_msi_lo);
+ ipath_cdbg(VERBOSE, "Writing msi_lo 0x%x to config offset 0x%x\n",
+ dd->ipath_msi_hi, pos + PCI_MSI_ADDRESS_HI);
+ pci_write_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_HI,
+ dd->ipath_msi_hi);
+ pci_read_config_word(dd->pcidev, pos + PCI_MSI_FLAGS, &control);
+ if (!(control & PCI_MSI_FLAGS_ENABLE)) {
+ ipath_cdbg(VERBOSE, "MSI control at off %x was %x, "
+ "setting MSI enable (%x)\n", pos + PCI_MSI_FLAGS,
+ control, control | PCI_MSI_FLAGS_ENABLE);
+ control |= PCI_MSI_FLAGS_ENABLE;
+ pci_write_config_word(dd->pcidev, pos + PCI_MSI_FLAGS,
+ control);
+ }
+ /* now rewrite the data (vector) info */
+ pci_write_config_word(dd->pcidev, pos +
+ ((control & PCI_MSI_FLAGS_64BIT) ? 12 : 8),
+ dd->ipath_msi_data);
+ /* we restore the cachelinesize also, although it doesn't really
+ * matter */
+ pci_write_config_byte(dd->pcidev, PCI_CACHE_LINE_SIZE,
+ dd->ipath_pci_cacheline);
+ /* and now set the pci master bit again */
+ pci_set_master(dd->pcidev);
+ ret = 1;
+
+bail:
+ return ret;
+}
+
+/* This routine sleeps, so it can only be called from user context, not
+ * from interrupt context. If we need interrupt context, we can split
+ * it into two routines.
+*/
+static int ipath_setup_pe_reset(struct ipath_devdata *dd)
+{
+ u64 val;
+ int i;
+ int ret;
+
+ /* Use ERROR so it shows up in logs, etc. */
+ ipath_dev_err(dd, "Resetting PE-800 unit %u\n",
+ dd->ipath_unit);
+ /* keep chip from being accessed in a few places */
+ dd->ipath_flags &= ~(IPATH_INITTED|IPATH_PRESENT);
+ val = dd->ipath_control | INFINIPATH_C_RESET;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control, val);
+ mb();
+
+ for (i = 1; i <= 5; i++) {
+ int r;
+ /* allow MBIST, etc. to complete; longer on each retry.
+ * We sometimes get machine checks from bus timeout if no
+ * response, so for now, make it *really* long.
+ */
+ msleep(1000 + (1 + i) * 2000);
+ if ((r =
+ pci_write_config_dword(dd->pcidev, PCI_BASE_ADDRESS_0,
+ dd->ipath_pcibar0)))
+ ipath_dev_err(dd, "rewrite of BAR0 failed: %d\n",
+ r);
+ if ((r =
+ pci_write_config_dword(dd->pcidev, PCI_BASE_ADDRESS_1,
+ dd->ipath_pcibar1)))
+ ipath_dev_err(dd, "rewrite of BAR1 failed: %d\n",
+ r);
+ /* now re-enable memory access */
+ if ((r = pci_enable_device(dd->pcidev)))
+ ipath_dev_err(dd, "pci_enable_device failed after "
+ "reset: %d\n", r);
+ /* whether it worked or not, mark as present, again */
+ dd->ipath_flags |= IPATH_PRESENT;
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision);
+ if (val == dd->ipath_revision) {
+ ipath_cdbg(VERBOSE, "Got matching revision "
+ "register %llx on try %d\n",
+ (unsigned long long) val, i);
+ ret = ipath_reinit_msi(dd);
+ goto bail;
+ }
+ /* Probably getting -1 back */
+ ipath_dbg("Didn't get expected revision register, "
+ "got %llx, try %d\n", (unsigned long long) val,
+ i + 1);
+ }
+ ret = 0; /* failed */
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_pe_put_tid - write a TID in chip
+ * @dd: the infinipath device
+ * @tidptr: pointer to the expected TID (in chip) to udpate
+ * @tidtype: 0 for eager, 1 for expected
+ * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
+ *
+ * This exists as a separate routine to allow for special locking etc.
+ * It's used for both the full cleanup on exit, as well as the normal
+ * setup and teardown.
+ */
+static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
+ u32 type, unsigned long pa)
+{
+ u32 __iomem *tidp32 = (u32 __iomem *)tidptr;
+ unsigned long flags = 0; /* keep gcc quiet */
+
+ if (pa != dd->ipath_tidinvalid) {
+ if (pa & ((1U << 11) - 1)) {
+ dev_info(&dd->pcidev->dev, "BUG: physaddr %lx "
+ "not 4KB aligned!\n", pa);
+ return;
+ }
+ pa >>= 11;
+ /* paranoia check */
+ if (pa & (7<<29))
+ ipath_dev_err(dd,
+ "BUG: Physical page address 0x%lx "
+ "has bits set in 31-29\n", pa);
+
+ if (type == 0)
+ pa |= dd->ipath_tidtemplate;
+ else /* for now, always full 4KB page */
+ pa |= 2 << 29;
+ }
+
+ /* workaround chip bug 9437 by writing each TID twice
+ * and holding a spinlock around the writes, so they don't
+ * intermix with other TID (eager or expected) writes
+ * Unfortunately, this call can be done from interrupt level
+ * for the port 0 eager TIDs, so we have to use irqsave
+ */
+ spin_lock_irqsave(&dd->ipath_tid_lock, flags);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xfeeddeaf);
+ if (dd->ipath_kregbase)
+ writel(pa, tidp32);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xdeadbeef);
+ mmiowb();
+ spin_unlock_irqrestore(&dd->ipath_tid_lock, flags);
+}
+
+/**
+ * ipath_pe_clear_tid - clear all TID entries for a port, expected and eager
+ * @dd: the infinipath device
+ * @port: the port
+ *
+ * clear all TID entries for a port, expected and eager.
+ * Used from ipath_close(). On PE800, TIDs are only 32 bits,
+ * not 64, but they are still on 64 bit boundaries, so tidbase
+ * is declared as u64 * for the pointer math, even though we write 32 bits
+ */
+static void ipath_pe_clear_tids(struct ipath_devdata *dd, unsigned port)
+{
+ u64 __iomem *tidbase;
+ unsigned long tidinv;
+ int i;
+
+ if (!dd->ipath_kregbase)
+ return;
+
+ ipath_cdbg(VERBOSE, "Invalidate TIDs for port %u\n", port);
+
+ tidinv = dd->ipath_tidinvalid;
+ tidbase = (u64 __iomem *)
+ ((char __iomem *)(dd->ipath_kregbase) +
+ dd->ipath_rcvtidbase +
+ port * dd->ipath_rcvtidcnt * sizeof(*tidbase));
+
+ for (i = 0; i < dd->ipath_rcvtidcnt; i++)
+ ipath_pe_put_tid(dd, &tidbase[i], 0, tidinv);
+
+ tidbase = (u64 __iomem *)
+ ((char __iomem *)(dd->ipath_kregbase) +
+ dd->ipath_rcvegrbase +
+ port * dd->ipath_rcvegrcnt * sizeof(*tidbase));
+
+ for (i = 0; i < dd->ipath_rcvegrcnt; i++)
+ ipath_pe_put_tid(dd, &tidbase[i], 1, tidinv);
+}
+
+/**
+ * ipath_pe_tidtemplate - setup constants for TID updates
+ * @dd: the infinipath device
+ *
+ * We setup stuff that we use a lot, to avoid calculating each time
+ */
+static void ipath_pe_tidtemplate(struct ipath_devdata *dd)
+{
+ u32 egrsize = dd->ipath_rcvegrbufsize;
+
+ /* For now, we always allocate 4KB buffers (at init) so we can
+ * receive max size packets. We may want a module parameter to
+ * specify 2KB or 4KB and/or make be per port instead of per device
+ * for those who want to reduce memory footprint. Note that the
+ * ipath_rcvhdrentsize size must be large enough to hold the largest
+ * IB header (currently 96 bytes) that we expect to handle (plus of
+ * course the 2 dwords of RHF).
+ */
+ if (egrsize == 2048)
+ dd->ipath_tidtemplate = 1U << 29;
+ else if (egrsize == 4096)
+ dd->ipath_tidtemplate = 2U << 29;
+ else {
+ egrsize = 4096;
+ dev_info(&dd->pcidev->dev, "BUG: unsupported egrbufsize "
+ "%u, using %u\n", dd->ipath_rcvegrbufsize,
+ egrsize);
+ dd->ipath_tidtemplate = 2U << 29;
+ }
+ dd->ipath_tidinvalid = 0;
+}
+
+static int ipath_pe_early_init(struct ipath_devdata *dd)
+{
+ dd->ipath_flags |= IPATH_4BYTE_TID;
+
+ /*
+ * For openib, we need to be able to handle an IB header of 96 bytes
+ * or 24 dwords. HT-400 has arbitrary sized receive buffers, so we
+ * made them the same size as the PIO buffers. The PE-800 does not
+ * handle arbitrary size buffers, so we need the header large enough
+ * to handle largest IB header, but still have room for a 2KB MTU
+ * standard IB packet.
+ */
+ dd->ipath_rcvhdrentsize = 24;
+ dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
+
+ /* For HT-400, we allocate a somewhat overly large eager buffer,
+ * such that we can guarantee that we can receive the largest packet
+ * that we can send out. To truly support a 4KB MTU, we need to
+ * bump this to a larger value. We'll do this when I get around to
+ * testing 4KB sends on the PE-800, which I have not yet done.
+ */
+ dd->ipath_rcvegrbufsize = 2048;
+ /*
+ * the min() check here is currently a nop, but it may not always
+ * be, depending on just how we do ipath_rcvegrbufsize
+ */
+ dd->ipath_ibmaxlen = min(dd->ipath_piosize2k,
+ dd->ipath_rcvegrbufsize +
+ (dd->ipath_rcvhdrentsize << 2));
+ dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen;
+
+ /*
+ * For PE-800, we can request a receive interrupt for 1 or
+ * more packets from current offset. For now, we set this
+ * up for a single packet, to match the HT-400 behavior.
+ */
+ dd->ipath_rhdrhead_intr_off = 1ULL<<32;
+
+ ipath_get_eeprom_info(dd);
+
+ return 0;
+}
+
+int __attribute__((weak)) ipath_unordered_wc(void)
+{
+ return 0;
+}
+
+/**
+ * ipath_init_pe_get_base_info - set chip-specific flags for user code
+ * @dd: the infinipath device
+ * @kbase: ipath_base_info pointer
+ *
+ * We set the PCIE flag because the lower bandwidth on PCIe vs
+ * HyperTransport can affect some user packet algorithims.
+ */
+static int ipath_pe_get_base_info(struct ipath_portdata *pd, void *kbase)
+{
+ struct ipath_base_info *kinfo = kbase;
+
+ if (ipath_unordered_wc()) {
+ kinfo->spi_runtime_flags |= IPATH_RUNTIME_FORCE_WC_ORDER;
+ ipath_cdbg(PROC, "Intel processor, forcing WC order\n");
+ }
+ else
+ ipath_cdbg(PROC, "Not Intel processor, WC ordered\n");
+
+ kinfo->spi_runtime_flags |= IPATH_RUNTIME_PCIE;
+
+ return 0;
+}
+
+/**
+ * ipath_init_pe800_funcs - set up the chip-specific function pointers
+ * @dd: the infinipath device
+ *
+ * This is global, and is called directly at init to set up the
+ * chip-specific function pointers for later use.
+ */
+void ipath_init_pe800_funcs(struct ipath_devdata *dd)
+{
+ dd->ipath_f_intrsetup = ipath_pe_intconfig;
+ dd->ipath_f_bus = ipath_setup_pe_config;
+ dd->ipath_f_reset = ipath_setup_pe_reset;
+ dd->ipath_f_get_boardname = ipath_pe_boardname;
+ dd->ipath_f_init_hwerrors = ipath_pe_init_hwerrors;
+ dd->ipath_f_early_init = ipath_pe_early_init;
+ dd->ipath_f_handle_hwerrors = ipath_pe_handle_hwerrors;
+ dd->ipath_f_quiet_serdes = ipath_pe_quiet_serdes;
+ dd->ipath_f_bringup_serdes = ipath_pe_bringup_serdes;
+ dd->ipath_f_clear_tids = ipath_pe_clear_tids;
+ dd->ipath_f_put_tid = ipath_pe_put_tid;
+ dd->ipath_f_cleanup = ipath_setup_pe_cleanup;
+ dd->ipath_f_setextled = ipath_setup_pe_setextled;
+ dd->ipath_f_get_base_info = ipath_pe_get_base_info;
+
+ /* initialize chip-specific variables */
+ dd->ipath_f_tidtemplate = ipath_pe_tidtemplate;
+
+ /*
+ * setup the register offsets, since they are different for each
+ * chip
+ */
+ dd->ipath_kregs = &ipath_pe_kregs;
+ dd->ipath_cregs = &ipath_pe_cregs;
+
+ ipath_init_pe_variables();
+}
+
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
new file mode 100644
index 00000000000..9f8855d970c
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_qp.c
@@ -0,0 +1,913 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/err.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+#define BITS_PER_PAGE (PAGE_SIZE*BITS_PER_BYTE)
+#define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1)
+#define mk_qpn(qpt, map, off) (((map) - (qpt)->map) * BITS_PER_PAGE + \
+ (off))
+#define find_next_offset(map, off) find_next_zero_bit((map)->page, \
+ BITS_PER_PAGE, off)
+
+#define TRANS_INVALID 0
+#define TRANS_ANY2RST 1
+#define TRANS_RST2INIT 2
+#define TRANS_INIT2INIT 3
+#define TRANS_INIT2RTR 4
+#define TRANS_RTR2RTS 5
+#define TRANS_RTS2RTS 6
+#define TRANS_SQERR2RTS 7
+#define TRANS_ANY2ERR 8
+#define TRANS_RTS2SQD 9 /* XXX Wait for expected ACKs & signal event */
+#define TRANS_SQD2SQD 10 /* error if not drained & parameter change */
+#define TRANS_SQD2RTS 11 /* error if not drained */
+
+/*
+ * Convert the AETH credit code into the number of credits.
+ */
+static u32 credit_table[31] = {
+ 0, /* 0 */
+ 1, /* 1 */
+ 2, /* 2 */
+ 3, /* 3 */
+ 4, /* 4 */
+ 6, /* 5 */
+ 8, /* 6 */
+ 12, /* 7 */
+ 16, /* 8 */
+ 24, /* 9 */
+ 32, /* A */
+ 48, /* B */
+ 64, /* C */
+ 96, /* D */
+ 128, /* E */
+ 192, /* F */
+ 256, /* 10 */
+ 384, /* 11 */
+ 512, /* 12 */
+ 768, /* 13 */
+ 1024, /* 14 */
+ 1536, /* 15 */
+ 2048, /* 16 */
+ 3072, /* 17 */
+ 4096, /* 18 */
+ 6144, /* 19 */
+ 8192, /* 1A */
+ 12288, /* 1B */
+ 16384, /* 1C */
+ 24576, /* 1D */
+ 32768 /* 1E */
+};
+
+static u32 alloc_qpn(struct ipath_qp_table *qpt)
+{
+ u32 i, offset, max_scan, qpn;
+ struct qpn_map *map;
+ u32 ret;
+
+ qpn = qpt->last + 1;
+ if (qpn >= QPN_MAX)
+ qpn = 2;
+ offset = qpn & BITS_PER_PAGE_MASK;
+ map = &qpt->map[qpn / BITS_PER_PAGE];
+ max_scan = qpt->nmaps - !offset;
+ for (i = 0;;) {
+ if (unlikely(!map->page)) {
+ unsigned long page = get_zeroed_page(GFP_KERNEL);
+ unsigned long flags;
+
+ /*
+ * Free the page if someone raced with us
+ * installing it:
+ */
+ spin_lock_irqsave(&qpt->lock, flags);
+ if (map->page)
+ free_page(page);
+ else
+ map->page = (void *)page;
+ spin_unlock_irqrestore(&qpt->lock, flags);
+ if (unlikely(!map->page))
+ break;
+ }
+ if (likely(atomic_read(&map->n_free))) {
+ do {
+ if (!test_and_set_bit(offset, map->page)) {
+ atomic_dec(&map->n_free);
+ qpt->last = qpn;
+ ret = qpn;
+ goto bail;
+ }
+ offset = find_next_offset(map, offset);
+ qpn = mk_qpn(qpt, map, offset);
+ /*
+ * This test differs from alloc_pidmap().
+ * If find_next_offset() does find a zero
+ * bit, we don't need to check for QPN
+ * wrapping around past our starting QPN.
+ * We just need to be sure we don't loop
+ * forever.
+ */
+ } while (offset < BITS_PER_PAGE && qpn < QPN_MAX);
+ }
+ /*
+ * In order to keep the number of pages allocated to a
+ * minimum, we scan the all existing pages before increasing
+ * the size of the bitmap table.
+ */
+ if (++i > max_scan) {
+ if (qpt->nmaps == QPNMAP_ENTRIES)
+ break;
+ map = &qpt->map[qpt->nmaps++];
+ offset = 0;
+ } else if (map < &qpt->map[qpt->nmaps]) {
+ ++map;
+ offset = 0;
+ } else {
+ map = &qpt->map[0];
+ offset = 2;
+ }
+ qpn = mk_qpn(qpt, map, offset);
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static void free_qpn(struct ipath_qp_table *qpt, u32 qpn)
+{
+ struct qpn_map *map;
+
+ map = qpt->map + qpn / BITS_PER_PAGE;
+ if (map->page)
+ clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
+ atomic_inc(&map->n_free);
+}
+
+/**
+ * ipath_alloc_qpn - allocate a QP number
+ * @qpt: the QP table
+ * @qp: the QP
+ * @type: the QP type (IB_QPT_SMI and IB_QPT_GSI are special)
+ *
+ * Allocate the next available QPN and put the QP into the hash table.
+ * The hash table holds a reference to the QP.
+ */
+static int ipath_alloc_qpn(struct ipath_qp_table *qpt, struct ipath_qp *qp,
+ enum ib_qp_type type)
+{
+ unsigned long flags;
+ u32 qpn;
+ int ret;
+
+ if (type == IB_QPT_SMI)
+ qpn = 0;
+ else if (type == IB_QPT_GSI)
+ qpn = 1;
+ else {
+ /* Allocate the next available QPN */
+ qpn = alloc_qpn(qpt);
+ if (qpn == 0) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ }
+ qp->ibqp.qp_num = qpn;
+
+ /* Add the QP to the hash table. */
+ spin_lock_irqsave(&qpt->lock, flags);
+
+ qpn %= qpt->max;
+ qp->next = qpt->table[qpn];
+ qpt->table[qpn] = qp;
+ atomic_inc(&qp->refcount);
+
+ spin_unlock_irqrestore(&qpt->lock, flags);
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_free_qp - remove a QP from the QP table
+ * @qpt: the QP table
+ * @qp: the QP to remove
+ *
+ * Remove the QP from the table so it can't be found asynchronously by
+ * the receive interrupt routine.
+ */
+static void ipath_free_qp(struct ipath_qp_table *qpt, struct ipath_qp *qp)
+{
+ struct ipath_qp *q, **qpp;
+ unsigned long flags;
+ int fnd = 0;
+
+ spin_lock_irqsave(&qpt->lock, flags);
+
+ /* Remove QP from the hash table. */
+ qpp = &qpt->table[qp->ibqp.qp_num % qpt->max];
+ for (; (q = *qpp) != NULL; qpp = &q->next) {
+ if (q == qp) {
+ *qpp = qp->next;
+ qp->next = NULL;
+ atomic_dec(&qp->refcount);
+ fnd = 1;
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&qpt->lock, flags);
+
+ if (!fnd)
+ return;
+
+ /* If QPN is not reserved, mark QPN free in the bitmap. */
+ if (qp->ibqp.qp_num > 1)
+ free_qpn(qpt, qp->ibqp.qp_num);
+
+ wait_event(qp->wait, !atomic_read(&qp->refcount));
+}
+
+/**
+ * ipath_free_all_qps - remove all QPs from the table
+ * @qpt: the QP table to empty
+ */
+void ipath_free_all_qps(struct ipath_qp_table *qpt)
+{
+ unsigned long flags;
+ struct ipath_qp *qp, *nqp;
+ u32 n;
+
+ for (n = 0; n < qpt->max; n++) {
+ spin_lock_irqsave(&qpt->lock, flags);
+ qp = qpt->table[n];
+ qpt->table[n] = NULL;
+ spin_unlock_irqrestore(&qpt->lock, flags);
+
+ while (qp) {
+ nqp = qp->next;
+ if (qp->ibqp.qp_num > 1)
+ free_qpn(qpt, qp->ibqp.qp_num);
+ if (!atomic_dec_and_test(&qp->refcount) ||
+ !ipath_destroy_qp(&qp->ibqp))
+ _VERBS_INFO("QP memory leak!\n");
+ qp = nqp;
+ }
+ }
+
+ for (n = 0; n < ARRAY_SIZE(qpt->map); n++) {
+ if (qpt->map[n].page)
+ free_page((unsigned long)qpt->map[n].page);
+ }
+}
+
+/**
+ * ipath_lookup_qpn - return the QP with the given QPN
+ * @qpt: the QP table
+ * @qpn: the QP number to look up
+ *
+ * The caller is responsible for decrementing the QP reference count
+ * when done.
+ */
+struct ipath_qp *ipath_lookup_qpn(struct ipath_qp_table *qpt, u32 qpn)
+{
+ unsigned long flags;
+ struct ipath_qp *qp;
+
+ spin_lock_irqsave(&qpt->lock, flags);
+
+ for (qp = qpt->table[qpn % qpt->max]; qp; qp = qp->next) {
+ if (qp->ibqp.qp_num == qpn) {
+ atomic_inc(&qp->refcount);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&qpt->lock, flags);
+ return qp;
+}
+
+/**
+ * ipath_reset_qp - initialize the QP state to the reset state
+ * @qp: the QP to reset
+ */
+static void ipath_reset_qp(struct ipath_qp *qp)
+{
+ qp->remote_qpn = 0;
+ qp->qkey = 0;
+ qp->qp_access_flags = 0;
+ qp->s_hdrwords = 0;
+ qp->s_psn = 0;
+ qp->r_psn = 0;
+ atomic_set(&qp->msn, 0);
+ if (qp->ibqp.qp_type == IB_QPT_RC) {
+ qp->s_state = IB_OPCODE_RC_SEND_LAST;
+ qp->r_state = IB_OPCODE_RC_SEND_LAST;
+ } else {
+ qp->s_state = IB_OPCODE_UC_SEND_LAST;
+ qp->r_state = IB_OPCODE_UC_SEND_LAST;
+ }
+ qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
+ qp->s_nak_state = 0;
+ qp->s_rnr_timeout = 0;
+ qp->s_head = 0;
+ qp->s_tail = 0;
+ qp->s_cur = 0;
+ qp->s_last = 0;
+ qp->s_ssn = 1;
+ qp->s_lsn = 0;
+ qp->r_rq.head = 0;
+ qp->r_rq.tail = 0;
+ qp->r_reuse_sge = 0;
+}
+
+/**
+ * ipath_error_qp - put a QP into an error state
+ * @qp: the QP to put into an error state
+ *
+ * Flushes both send and receive work queues.
+ * QP r_rq.lock and s_lock should be held.
+ */
+
+static void ipath_error_qp(struct ipath_qp *qp)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ struct ib_wc wc;
+
+ _VERBS_INFO("QP%d/%d in error state\n",
+ qp->ibqp.qp_num, qp->remote_qpn);
+
+ spin_lock(&dev->pending_lock);
+ /* XXX What if its already removed by the timeout code? */
+ if (!list_empty(&qp->timerwait))
+ list_del_init(&qp->timerwait);
+ if (!list_empty(&qp->piowait))
+ list_del_init(&qp->piowait);
+ spin_unlock(&dev->pending_lock);
+
+ wc.status = IB_WC_WR_FLUSH_ERR;
+ wc.vendor_err = 0;
+ wc.byte_len = 0;
+ wc.imm_data = 0;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = 0;
+ wc.wc_flags = 0;
+ wc.pkey_index = 0;
+ wc.slid = 0;
+ wc.sl = 0;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+
+ while (qp->s_last != qp->s_head) {
+ struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
+
+ wc.wr_id = wqe->wr.wr_id;
+ wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ if (++qp->s_last >= qp->s_size)
+ qp->s_last = 0;
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1);
+ }
+ qp->s_cur = qp->s_tail = qp->s_head;
+ qp->s_hdrwords = 0;
+ qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
+
+ wc.opcode = IB_WC_RECV;
+ while (qp->r_rq.tail != qp->r_rq.head) {
+ wc.wr_id = get_rwqe_ptr(&qp->r_rq, qp->r_rq.tail)->wr_id;
+ if (++qp->r_rq.tail >= qp->r_rq.size)
+ qp->r_rq.tail = 0;
+ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
+ }
+}
+
+/**
+ * ipath_modify_qp - modify the attributes of a queue pair
+ * @ibqp: the queue pair who's attributes we're modifying
+ * @attr: the new attributes
+ * @attr_mask: the mask of attributes to modify
+ *
+ * Returns 0 on success, otherwise returns an errno.
+ */
+int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask)
+{
+ struct ipath_ibdev *dev = to_idev(ibqp->device);
+ struct ipath_qp *qp = to_iqp(ibqp);
+ enum ib_qp_state cur_state, new_state;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+ spin_lock(&qp->s_lock);
+
+ cur_state = attr_mask & IB_QP_CUR_STATE ?
+ attr->cur_qp_state : qp->state;
+ new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
+
+ if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type,
+ attr_mask))
+ goto inval;
+
+ if (attr_mask & IB_QP_AV)
+ if (attr->ah_attr.dlid == 0 ||
+ attr->ah_attr.dlid >= IPS_MULTICAST_LID_BASE)
+ goto inval;
+
+ if (attr_mask & IB_QP_PKEY_INDEX)
+ if (attr->pkey_index >= ipath_layer_get_npkeys(dev->dd))
+ goto inval;
+
+ if (attr_mask & IB_QP_MIN_RNR_TIMER)
+ if (attr->min_rnr_timer > 31)
+ goto inval;
+
+ switch (new_state) {
+ case IB_QPS_RESET:
+ ipath_reset_qp(qp);
+ break;
+
+ case IB_QPS_ERR:
+ ipath_error_qp(qp);
+ break;
+
+ default:
+ break;
+
+ }
+
+ if (attr_mask & IB_QP_PKEY_INDEX)
+ qp->s_pkey_index = attr->pkey_index;
+
+ if (attr_mask & IB_QP_DEST_QPN)
+ qp->remote_qpn = attr->dest_qp_num;
+
+ if (attr_mask & IB_QP_SQ_PSN) {
+ qp->s_next_psn = attr->sq_psn;
+ qp->s_last_psn = qp->s_next_psn - 1;
+ }
+
+ if (attr_mask & IB_QP_RQ_PSN)
+ qp->r_psn = attr->rq_psn;
+
+ if (attr_mask & IB_QP_ACCESS_FLAGS)
+ qp->qp_access_flags = attr->qp_access_flags;
+
+ if (attr_mask & IB_QP_AV)
+ qp->remote_ah_attr = attr->ah_attr;
+
+ if (attr_mask & IB_QP_PATH_MTU)
+ qp->path_mtu = attr->path_mtu;
+
+ if (attr_mask & IB_QP_RETRY_CNT)
+ qp->s_retry = qp->s_retry_cnt = attr->retry_cnt;
+
+ if (attr_mask & IB_QP_RNR_RETRY) {
+ qp->s_rnr_retry = attr->rnr_retry;
+ if (qp->s_rnr_retry > 7)
+ qp->s_rnr_retry = 7;
+ qp->s_rnr_retry_cnt = qp->s_rnr_retry;
+ }
+
+ if (attr_mask & IB_QP_MIN_RNR_TIMER)
+ qp->s_min_rnr_timer = attr->min_rnr_timer;
+
+ if (attr_mask & IB_QP_QKEY)
+ qp->qkey = attr->qkey;
+
+ if (attr_mask & IB_QP_PKEY_INDEX)
+ qp->s_pkey_index = attr->pkey_index;
+
+ qp->state = new_state;
+ spin_unlock(&qp->s_lock);
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+
+ /*
+ * If QP1 changed to the RTS state, try to move to the link to INIT
+ * even if it was ACTIVE so the SM will reinitialize the SMA's
+ * state.
+ */
+ if (qp->ibqp.qp_num == 1 && new_state == IB_QPS_RTS) {
+ struct ipath_ibdev *dev = to_idev(ibqp->device);
+
+ ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKDOWN);
+ }
+ ret = 0;
+ goto bail;
+
+inval:
+ spin_unlock(&qp->s_lock);
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ ret = -EINVAL;
+
+bail:
+ return ret;
+}
+
+int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask, struct ib_qp_init_attr *init_attr)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+
+ attr->qp_state = qp->state;
+ attr->cur_qp_state = attr->qp_state;
+ attr->path_mtu = qp->path_mtu;
+ attr->path_mig_state = 0;
+ attr->qkey = qp->qkey;
+ attr->rq_psn = qp->r_psn;
+ attr->sq_psn = qp->s_next_psn;
+ attr->dest_qp_num = qp->remote_qpn;
+ attr->qp_access_flags = qp->qp_access_flags;
+ attr->cap.max_send_wr = qp->s_size - 1;
+ attr->cap.max_recv_wr = qp->r_rq.size - 1;
+ attr->cap.max_send_sge = qp->s_max_sge;
+ attr->cap.max_recv_sge = qp->r_rq.max_sge;
+ attr->cap.max_inline_data = 0;
+ attr->ah_attr = qp->remote_ah_attr;
+ memset(&attr->alt_ah_attr, 0, sizeof(attr->alt_ah_attr));
+ attr->pkey_index = qp->s_pkey_index;
+ attr->alt_pkey_index = 0;
+ attr->en_sqd_async_notify = 0;
+ attr->sq_draining = 0;
+ attr->max_rd_atomic = 1;
+ attr->max_dest_rd_atomic = 1;
+ attr->min_rnr_timer = qp->s_min_rnr_timer;
+ attr->port_num = 1;
+ attr->timeout = 0;
+ attr->retry_cnt = qp->s_retry_cnt;
+ attr->rnr_retry = qp->s_rnr_retry;
+ attr->alt_port_num = 0;
+ attr->alt_timeout = 0;
+
+ init_attr->event_handler = qp->ibqp.event_handler;
+ init_attr->qp_context = qp->ibqp.qp_context;
+ init_attr->send_cq = qp->ibqp.send_cq;
+ init_attr->recv_cq = qp->ibqp.recv_cq;
+ init_attr->srq = qp->ibqp.srq;
+ init_attr->cap = attr->cap;
+ init_attr->sq_sig_type =
+ (qp->s_flags & (1 << IPATH_S_SIGNAL_REQ_WR))
+ ? IB_SIGNAL_REQ_WR : 0;
+ init_attr->qp_type = qp->ibqp.qp_type;
+ init_attr->port_num = 1;
+ return 0;
+}
+
+/**
+ * ipath_compute_aeth - compute the AETH (syndrome + MSN)
+ * @qp: the queue pair to compute the AETH for
+ *
+ * Returns the AETH.
+ *
+ * The QP s_lock should be held.
+ */
+__be32 ipath_compute_aeth(struct ipath_qp *qp)
+{
+ u32 aeth = atomic_read(&qp->msn) & IPS_MSN_MASK;
+
+ if (qp->s_nak_state) {
+ aeth |= qp->s_nak_state << IPS_AETH_CREDIT_SHIFT;
+ } else if (qp->ibqp.srq) {
+ /*
+ * Shared receive queues don't generate credits.
+ * Set the credit field to the invalid value.
+ */
+ aeth |= IPS_AETH_CREDIT_INVAL << IPS_AETH_CREDIT_SHIFT;
+ } else {
+ u32 min, max, x;
+ u32 credits;
+
+ /*
+ * Compute the number of credits available (RWQEs).
+ * XXX Not holding the r_rq.lock here so there is a small
+ * chance that the pair of reads are not atomic.
+ */
+ credits = qp->r_rq.head - qp->r_rq.tail;
+ if ((int)credits < 0)
+ credits += qp->r_rq.size;
+ /*
+ * Binary search the credit table to find the code to
+ * use.
+ */
+ min = 0;
+ max = 31;
+ for (;;) {
+ x = (min + max) / 2;
+ if (credit_table[x] == credits)
+ break;
+ if (credit_table[x] > credits)
+ max = x;
+ else if (min == x)
+ break;
+ else
+ min = x;
+ }
+ aeth |= x << IPS_AETH_CREDIT_SHIFT;
+ }
+ return cpu_to_be32(aeth);
+}
+
+/**
+ * ipath_create_qp - create a queue pair for a device
+ * @ibpd: the protection domain who's device we create the queue pair for
+ * @init_attr: the attributes of the queue pair
+ * @udata: unused by InfiniPath
+ *
+ * Returns the queue pair on success, otherwise returns an errno.
+ *
+ * Called by the ib_create_qp() core verbs function.
+ */
+struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
+ struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata)
+{
+ struct ipath_qp *qp;
+ int err;
+ struct ipath_swqe *swq = NULL;
+ struct ipath_ibdev *dev;
+ size_t sz;
+ struct ib_qp *ret;
+
+ if (init_attr->cap.max_send_sge > 255 ||
+ init_attr->cap.max_recv_sge > 255) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ switch (init_attr->qp_type) {
+ case IB_QPT_UC:
+ case IB_QPT_RC:
+ sz = sizeof(struct ipath_sge) *
+ init_attr->cap.max_send_sge +
+ sizeof(struct ipath_swqe);
+ swq = vmalloc((init_attr->cap.max_send_wr + 1) * sz);
+ if (swq == NULL) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+ /* FALLTHROUGH */
+ case IB_QPT_UD:
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
+ qp = kmalloc(sizeof(*qp), GFP_KERNEL);
+ if (!qp) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+ qp->r_rq.size = init_attr->cap.max_recv_wr + 1;
+ sz = sizeof(struct ipath_sge) *
+ init_attr->cap.max_recv_sge +
+ sizeof(struct ipath_rwqe);
+ qp->r_rq.wq = vmalloc(qp->r_rq.size * sz);
+ if (!qp->r_rq.wq) {
+ kfree(qp);
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /*
+ * ib_create_qp() will initialize qp->ibqp
+ * except for qp->ibqp.qp_num.
+ */
+ spin_lock_init(&qp->s_lock);
+ spin_lock_init(&qp->r_rq.lock);
+ atomic_set(&qp->refcount, 0);
+ init_waitqueue_head(&qp->wait);
+ tasklet_init(&qp->s_task,
+ init_attr->qp_type == IB_QPT_RC ?
+ ipath_do_rc_send : ipath_do_uc_send,
+ (unsigned long)qp);
+ INIT_LIST_HEAD(&qp->piowait);
+ INIT_LIST_HEAD(&qp->timerwait);
+ qp->state = IB_QPS_RESET;
+ qp->s_wq = swq;
+ qp->s_size = init_attr->cap.max_send_wr + 1;
+ qp->s_max_sge = init_attr->cap.max_send_sge;
+ qp->r_rq.max_sge = init_attr->cap.max_recv_sge;
+ qp->s_flags = init_attr->sq_sig_type == IB_SIGNAL_REQ_WR ?
+ 1 << IPATH_S_SIGNAL_REQ_WR : 0;
+ dev = to_idev(ibpd->device);
+ err = ipath_alloc_qpn(&dev->qp_table, qp,
+ init_attr->qp_type);
+ if (err) {
+ vfree(swq);
+ vfree(qp->r_rq.wq);
+ kfree(qp);
+ ret = ERR_PTR(err);
+ goto bail;
+ }
+ ipath_reset_qp(qp);
+
+ /* Tell the core driver that the kernel SMA is present. */
+ if (init_attr->qp_type == IB_QPT_SMI)
+ ipath_layer_set_verbs_flags(dev->dd,
+ IPATH_VERBS_KERNEL_SMA);
+ break;
+
+ default:
+ /* Don't support raw QPs */
+ ret = ERR_PTR(-ENOSYS);
+ goto bail;
+ }
+
+ init_attr->cap.max_inline_data = 0;
+
+ ret = &qp->ibqp;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_destroy_qp - destroy a queue pair
+ * @ibqp: the queue pair to destroy
+ *
+ * Returns 0 on success.
+ *
+ * Note that this can be called while the QP is actively sending or
+ * receiving!
+ */
+int ipath_destroy_qp(struct ib_qp *ibqp)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+ struct ipath_ibdev *dev = to_idev(ibqp->device);
+ unsigned long flags;
+
+ /* Tell the core driver that the kernel SMA is gone. */
+ if (qp->ibqp.qp_type == IB_QPT_SMI)
+ ipath_layer_set_verbs_flags(dev->dd, 0);
+
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+ spin_lock(&qp->s_lock);
+ qp->state = IB_QPS_ERR;
+ spin_unlock(&qp->s_lock);
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+
+ /* Stop the sending tasklet. */
+ tasklet_kill(&qp->s_task);
+
+ /* Make sure the QP isn't on the timeout list. */
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ if (!list_empty(&qp->timerwait))
+ list_del_init(&qp->timerwait);
+ if (!list_empty(&qp->piowait))
+ list_del_init(&qp->piowait);
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+ /*
+ * Make sure that the QP is not in the QPN table so receive
+ * interrupts will discard packets for this QP. XXX Also remove QP
+ * from multicast table.
+ */
+ if (atomic_read(&qp->refcount) != 0)
+ ipath_free_qp(&dev->qp_table, qp);
+
+ vfree(qp->s_wq);
+ vfree(qp->r_rq.wq);
+ kfree(qp);
+ return 0;
+}
+
+/**
+ * ipath_init_qp_table - initialize the QP table for a device
+ * @idev: the device who's QP table we're initializing
+ * @size: the size of the QP table
+ *
+ * Returns 0 on success, otherwise returns an errno.
+ */
+int ipath_init_qp_table(struct ipath_ibdev *idev, int size)
+{
+ int i;
+ int ret;
+
+ idev->qp_table.last = 1; /* QPN 0 and 1 are special. */
+ idev->qp_table.max = size;
+ idev->qp_table.nmaps = 1;
+ idev->qp_table.table = kzalloc(size * sizeof(*idev->qp_table.table),
+ GFP_KERNEL);
+ if (idev->qp_table.table == NULL) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(idev->qp_table.map); i++) {
+ atomic_set(&idev->qp_table.map[i].n_free, BITS_PER_PAGE);
+ idev->qp_table.map[i].page = NULL;
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_sqerror_qp - put a QP's send queue into an error state
+ * @qp: QP who's send queue will be put into an error state
+ * @wc: the WC responsible for putting the QP in this state
+ *
+ * Flushes the send work queue.
+ * The QP s_lock should be held.
+ */
+
+void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
+
+ _VERBS_INFO("Send queue error on QP%d/%d: err: %d\n",
+ qp->ibqp.qp_num, qp->remote_qpn, wc->status);
+
+ spin_lock(&dev->pending_lock);
+ /* XXX What if its already removed by the timeout code? */
+ if (!list_empty(&qp->timerwait))
+ list_del_init(&qp->timerwait);
+ if (!list_empty(&qp->piowait))
+ list_del_init(&qp->piowait);
+ spin_unlock(&dev->pending_lock);
+
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 1);
+ if (++qp->s_last >= qp->s_size)
+ qp->s_last = 0;
+
+ wc->status = IB_WC_WR_FLUSH_ERR;
+
+ while (qp->s_last != qp->s_head) {
+ wc->wr_id = wqe->wr.wr_id;
+ wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 1);
+ if (++qp->s_last >= qp->s_size)
+ qp->s_last = 0;
+ wqe = get_swqe_ptr(qp, qp->s_last);
+ }
+ qp->s_cur = qp->s_tail = qp->s_head;
+ qp->state = IB_QPS_SQE;
+}
+
+/**
+ * ipath_get_credit - flush the send work queue of a QP
+ * @qp: the qp who's send work queue to flush
+ * @aeth: the Acknowledge Extended Transport Header
+ *
+ * The QP s_lock should be held.
+ */
+void ipath_get_credit(struct ipath_qp *qp, u32 aeth)
+{
+ u32 credit = (aeth >> IPS_AETH_CREDIT_SHIFT) & IPS_AETH_CREDIT_MASK;
+
+ /*
+ * If the credit is invalid, we can send
+ * as many packets as we like. Otherwise, we have to
+ * honor the credit field.
+ */
+ if (credit == IPS_AETH_CREDIT_INVAL) {
+ qp->s_lsn = (u32) -1;
+ } else if (qp->s_lsn != (u32) -1) {
+ /* Compute new LSN (i.e., MSN + credit) */
+ credit = (aeth + credit_table[credit]) & IPS_MSN_MASK;
+ if (ipath_cmp24(credit, qp->s_lsn) > 0)
+ qp->s_lsn = credit;
+ }
+
+ /* Restart sending if it was blocked due to lack of credits. */
+ if (qp->s_cur != qp->s_head &&
+ (qp->s_lsn == (u32) -1 ||
+ ipath_cmp24(get_swqe_ptr(qp, qp->s_cur)->ssn,
+ qp->s_lsn + 1) <= 0))
+ tasklet_hi_schedule(&qp->s_task);
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
new file mode 100644
index 00000000000..493b1821a93
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -0,0 +1,1856 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+/* cut down ridiculously long IB macro names */
+#define OP(x) IB_OPCODE_RC_##x
+
+/**
+ * ipath_init_restart- initialize the qp->s_sge after a restart
+ * @qp: the QP who's SGE we're restarting
+ * @wqe: the work queue to initialize the QP's SGE from
+ *
+ * The QP s_lock should be held.
+ */
+static void ipath_init_restart(struct ipath_qp *qp, struct ipath_swqe *wqe)
+{
+ struct ipath_ibdev *dev;
+ u32 len;
+
+ len = ((qp->s_psn - wqe->psn) & IPS_PSN_MASK) *
+ ib_mtu_enum_to_int(qp->path_mtu);
+ qp->s_sge.sge = wqe->sg_list[0];
+ qp->s_sge.sg_list = wqe->sg_list + 1;
+ qp->s_sge.num_sge = wqe->wr.num_sge;
+ ipath_skip_sge(&qp->s_sge, len);
+ qp->s_len = wqe->length - len;
+ dev = to_idev(qp->ibqp.device);
+ spin_lock(&dev->pending_lock);
+ if (list_empty(&qp->timerwait))
+ list_add_tail(&qp->timerwait,
+ &dev->pending[dev->pending_index]);
+ spin_unlock(&dev->pending_lock);
+}
+
+/**
+ * ipath_make_rc_ack - construct a response packet (ACK, NAK, or RDMA read)
+ * @qp: a pointer to the QP
+ * @ohdr: a pointer to the IB header being constructed
+ * @pmtu: the path MTU
+ *
+ * Return bth0 if constructed; otherwise, return 0.
+ * Note the QP s_lock must be held.
+ */
+static inline u32 ipath_make_rc_ack(struct ipath_qp *qp,
+ struct ipath_other_headers *ohdr,
+ u32 pmtu)
+{
+ struct ipath_sge_state *ss;
+ u32 hwords;
+ u32 len;
+ u32 bth0;
+
+ /* header size in 32-bit words LRH+BTH = (8+12)/4. */
+ hwords = 5;
+
+ /*
+ * Send a response. Note that we are in the responder's
+ * side of the QP context.
+ */
+ switch (qp->s_ack_state) {
+ case OP(RDMA_READ_REQUEST):
+ ss = &qp->s_rdma_sge;
+ len = qp->s_rdma_len;
+ if (len > pmtu) {
+ len = pmtu;
+ qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST);
+ }
+ else
+ qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY);
+ qp->s_rdma_len -= len;
+ bth0 = qp->s_ack_state << 24;
+ ohdr->u.aeth = ipath_compute_aeth(qp);
+ hwords++;
+ break;
+
+ case OP(RDMA_READ_RESPONSE_FIRST):
+ qp->s_ack_state = OP(RDMA_READ_RESPONSE_MIDDLE);
+ /* FALLTHROUGH */
+ case OP(RDMA_READ_RESPONSE_MIDDLE):
+ ss = &qp->s_rdma_sge;
+ len = qp->s_rdma_len;
+ if (len > pmtu)
+ len = pmtu;
+ else {
+ ohdr->u.aeth = ipath_compute_aeth(qp);
+ hwords++;
+ qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST);
+ }
+ qp->s_rdma_len -= len;
+ bth0 = qp->s_ack_state << 24;
+ break;
+
+ case OP(RDMA_READ_RESPONSE_LAST):
+ case OP(RDMA_READ_RESPONSE_ONLY):
+ /*
+ * We have to prevent new requests from changing
+ * the r_sge state while a ipath_verbs_send()
+ * is in progress.
+ * Changing r_state allows the receiver
+ * to continue processing new packets.
+ * We do it here now instead of above so
+ * that we are sure the packet was sent before
+ * changing the state.
+ */
+ qp->r_state = OP(RDMA_READ_RESPONSE_LAST);
+ qp->s_ack_state = OP(ACKNOWLEDGE);
+ return 0;
+
+ case OP(COMPARE_SWAP):
+ case OP(FETCH_ADD):
+ ss = NULL;
+ len = 0;
+ qp->r_state = OP(SEND_LAST);
+ qp->s_ack_state = OP(ACKNOWLEDGE);
+ bth0 = IB_OPCODE_ATOMIC_ACKNOWLEDGE << 24;
+ ohdr->u.at.aeth = ipath_compute_aeth(qp);
+ ohdr->u.at.atomic_ack_eth = cpu_to_be64(qp->s_ack_atomic);
+ hwords += sizeof(ohdr->u.at) / 4;
+ break;
+
+ default:
+ /* Send a regular ACK. */
+ ss = NULL;
+ len = 0;
+ qp->s_ack_state = OP(ACKNOWLEDGE);
+ bth0 = qp->s_ack_state << 24;
+ ohdr->u.aeth = ipath_compute_aeth(qp);
+ hwords++;
+ }
+ qp->s_hdrwords = hwords;
+ qp->s_cur_sge = ss;
+ qp->s_cur_size = len;
+
+ return bth0;
+}
+
+/**
+ * ipath_make_rc_req - construct a request packet (SEND, RDMA r/w, ATOMIC)
+ * @qp: a pointer to the QP
+ * @ohdr: a pointer to the IB header being constructed
+ * @pmtu: the path MTU
+ * @bth0p: pointer to the BTH opcode word
+ * @bth2p: pointer to the BTH PSN word
+ *
+ * Return 1 if constructed; otherwise, return 0.
+ * Note the QP s_lock must be held.
+ */
+static inline int ipath_make_rc_req(struct ipath_qp *qp,
+ struct ipath_other_headers *ohdr,
+ u32 pmtu, u32 *bth0p, u32 *bth2p)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ struct ipath_sge_state *ss;
+ struct ipath_swqe *wqe;
+ u32 hwords;
+ u32 len;
+ u32 bth0;
+ u32 bth2;
+ char newreq;
+
+ if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) ||
+ qp->s_rnr_timeout)
+ goto done;
+
+ /* header size in 32-bit words LRH+BTH = (8+12)/4. */
+ hwords = 5;
+ bth0 = 0;
+
+ /* Send a request. */
+ wqe = get_swqe_ptr(qp, qp->s_cur);
+ switch (qp->s_state) {
+ default:
+ /*
+ * Resend an old request or start a new one.
+ *
+ * We keep track of the current SWQE so that
+ * we don't reset the "furthest progress" state
+ * if we need to back up.
+ */
+ newreq = 0;
+ if (qp->s_cur == qp->s_tail) {
+ /* Check if send work queue is empty. */
+ if (qp->s_tail == qp->s_head)
+ goto done;
+ qp->s_psn = wqe->psn = qp->s_next_psn;
+ newreq = 1;
+ }
+ /*
+ * Note that we have to be careful not to modify the
+ * original work request since we may need to resend
+ * it.
+ */
+ qp->s_sge.sge = wqe->sg_list[0];
+ qp->s_sge.sg_list = wqe->sg_list + 1;
+ qp->s_sge.num_sge = wqe->wr.num_sge;
+ qp->s_len = len = wqe->length;
+ ss = &qp->s_sge;
+ bth2 = 0;
+ switch (wqe->wr.opcode) {
+ case IB_WR_SEND:
+ case IB_WR_SEND_WITH_IMM:
+ /* If no credit, return. */
+ if (qp->s_lsn != (u32) -1 &&
+ ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0)
+ goto done;
+ wqe->lpsn = wqe->psn;
+ if (len > pmtu) {
+ wqe->lpsn += (len - 1) / pmtu;
+ qp->s_state = OP(SEND_FIRST);
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_SEND)
+ qp->s_state = OP(SEND_ONLY);
+ else {
+ qp->s_state = OP(SEND_ONLY_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+ ohdr->u.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ }
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ bth2 = 1 << 31; /* Request ACK. */
+ if (++qp->s_cur == qp->s_size)
+ qp->s_cur = 0;
+ break;
+
+ case IB_WR_RDMA_WRITE:
+ if (newreq)
+ qp->s_lsn++;
+ /* FALLTHROUGH */
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ /* If no credit, return. */
+ if (qp->s_lsn != (u32) -1 &&
+ ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0)
+ goto done;
+ ohdr->u.rc.reth.vaddr =
+ cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ ohdr->u.rc.reth.rkey =
+ cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ ohdr->u.rc.reth.length = cpu_to_be32(len);
+ hwords += sizeof(struct ib_reth) / 4;
+ wqe->lpsn = wqe->psn;
+ if (len > pmtu) {
+ wqe->lpsn += (len - 1) / pmtu;
+ qp->s_state = OP(RDMA_WRITE_FIRST);
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+ qp->s_state = OP(RDMA_WRITE_ONLY);
+ else {
+ qp->s_state =
+ OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
+ /* Immediate data comes
+ * after RETH */
+ ohdr->u.rc.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ }
+ bth2 = 1 << 31; /* Request ACK. */
+ if (++qp->s_cur == qp->s_size)
+ qp->s_cur = 0;
+ break;
+
+ case IB_WR_RDMA_READ:
+ ohdr->u.rc.reth.vaddr =
+ cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ ohdr->u.rc.reth.rkey =
+ cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ ohdr->u.rc.reth.length = cpu_to_be32(len);
+ qp->s_state = OP(RDMA_READ_REQUEST);
+ hwords += sizeof(ohdr->u.rc.reth) / 4;
+ if (newreq) {
+ qp->s_lsn++;
+ /*
+ * Adjust s_next_psn to count the
+ * expected number of responses.
+ */
+ if (len > pmtu)
+ qp->s_next_psn += (len - 1) / pmtu;
+ wqe->lpsn = qp->s_next_psn++;
+ }
+ ss = NULL;
+ len = 0;
+ if (++qp->s_cur == qp->s_size)
+ qp->s_cur = 0;
+ break;
+
+ case IB_WR_ATOMIC_CMP_AND_SWP:
+ case IB_WR_ATOMIC_FETCH_AND_ADD:
+ if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP)
+ qp->s_state = OP(COMPARE_SWAP);
+ else
+ qp->s_state = OP(FETCH_ADD);
+ ohdr->u.atomic_eth.vaddr = cpu_to_be64(
+ wqe->wr.wr.atomic.remote_addr);
+ ohdr->u.atomic_eth.rkey = cpu_to_be32(
+ wqe->wr.wr.atomic.rkey);
+ ohdr->u.atomic_eth.swap_data = cpu_to_be64(
+ wqe->wr.wr.atomic.swap);
+ ohdr->u.atomic_eth.compare_data = cpu_to_be64(
+ wqe->wr.wr.atomic.compare_add);
+ hwords += sizeof(struct ib_atomic_eth) / 4;
+ if (newreq) {
+ qp->s_lsn++;
+ wqe->lpsn = wqe->psn;
+ }
+ if (++qp->s_cur == qp->s_size)
+ qp->s_cur = 0;
+ ss = NULL;
+ len = 0;
+ break;
+
+ default:
+ goto done;
+ }
+ if (newreq) {
+ qp->s_tail++;
+ if (qp->s_tail >= qp->s_size)
+ qp->s_tail = 0;
+ }
+ bth2 |= qp->s_psn++ & IPS_PSN_MASK;
+ if ((int)(qp->s_psn - qp->s_next_psn) > 0)
+ qp->s_next_psn = qp->s_psn;
+ spin_lock(&dev->pending_lock);
+ if (list_empty(&qp->timerwait))
+ list_add_tail(&qp->timerwait,
+ &dev->pending[dev->pending_index]);
+ spin_unlock(&dev->pending_lock);
+ break;
+
+ case OP(RDMA_READ_RESPONSE_FIRST):
+ /*
+ * This case can only happen if a send is restarted. See
+ * ipath_restart_rc().
+ */
+ ipath_init_restart(qp, wqe);
+ /* FALLTHROUGH */
+ case OP(SEND_FIRST):
+ qp->s_state = OP(SEND_MIDDLE);
+ /* FALLTHROUGH */
+ case OP(SEND_MIDDLE):
+ bth2 = qp->s_psn++ & IPS_PSN_MASK;
+ if ((int)(qp->s_psn - qp->s_next_psn) > 0)
+ qp->s_next_psn = qp->s_psn;
+ ss = &qp->s_sge;
+ len = qp->s_len;
+ if (len > pmtu) {
+ /*
+ * Request an ACK every 1/2 MB to avoid retransmit
+ * timeouts.
+ */
+ if (((wqe->length - len) % (512 * 1024)) == 0)
+ bth2 |= 1 << 31;
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_SEND)
+ qp->s_state = OP(SEND_LAST);
+ else {
+ qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+ ohdr->u.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ }
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ bth2 |= 1 << 31; /* Request ACK. */
+ qp->s_cur++;
+ if (qp->s_cur >= qp->s_size)
+ qp->s_cur = 0;
+ break;
+
+ case OP(RDMA_READ_RESPONSE_LAST):
+ /*
+ * This case can only happen if a RDMA write is restarted.
+ * See ipath_restart_rc().
+ */
+ ipath_init_restart(qp, wqe);
+ /* FALLTHROUGH */
+ case OP(RDMA_WRITE_FIRST):
+ qp->s_state = OP(RDMA_WRITE_MIDDLE);
+ /* FALLTHROUGH */
+ case OP(RDMA_WRITE_MIDDLE):
+ bth2 = qp->s_psn++ & IPS_PSN_MASK;
+ if ((int)(qp->s_psn - qp->s_next_psn) > 0)
+ qp->s_next_psn = qp->s_psn;
+ ss = &qp->s_sge;
+ len = qp->s_len;
+ if (len > pmtu) {
+ /*
+ * Request an ACK every 1/2 MB to avoid retransmit
+ * timeouts.
+ */
+ if (((wqe->length - len) % (512 * 1024)) == 0)
+ bth2 |= 1 << 31;
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+ qp->s_state = OP(RDMA_WRITE_LAST);
+ else {
+ qp->s_state = OP(RDMA_WRITE_LAST_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+ ohdr->u.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ }
+ bth2 |= 1 << 31; /* Request ACK. */
+ qp->s_cur++;
+ if (qp->s_cur >= qp->s_size)
+ qp->s_cur = 0;
+ break;
+
+ case OP(RDMA_READ_RESPONSE_MIDDLE):
+ /*
+ * This case can only happen if a RDMA read is restarted.
+ * See ipath_restart_rc().
+ */
+ ipath_init_restart(qp, wqe);
+ len = ((qp->s_psn - wqe->psn) & IPS_PSN_MASK) * pmtu;
+ ohdr->u.rc.reth.vaddr =
+ cpu_to_be64(wqe->wr.wr.rdma.remote_addr + len);
+ ohdr->u.rc.reth.rkey =
+ cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ ohdr->u.rc.reth.length = cpu_to_be32(qp->s_len);
+ qp->s_state = OP(RDMA_READ_REQUEST);
+ hwords += sizeof(ohdr->u.rc.reth) / 4;
+ bth2 = qp->s_psn++ & IPS_PSN_MASK;
+ if ((int)(qp->s_psn - qp->s_next_psn) > 0)
+ qp->s_next_psn = qp->s_psn;
+ ss = NULL;
+ len = 0;
+ qp->s_cur++;
+ if (qp->s_cur == qp->s_size)
+ qp->s_cur = 0;
+ break;
+
+ case OP(RDMA_READ_REQUEST):
+ case OP(COMPARE_SWAP):
+ case OP(FETCH_ADD):
+ /*
+ * We shouldn't start anything new until this request is
+ * finished. The ACK will handle rescheduling us. XXX The
+ * number of outstanding ones is negotiated at connection
+ * setup time (see pg. 258,289)? XXX Also, if we support
+ * multiple outstanding requests, we need to check the WQE
+ * IB_SEND_FENCE flag and not send a new request if a RDMA
+ * read or atomic is pending.
+ */
+ goto done;
+ }
+ qp->s_len -= len;
+ qp->s_hdrwords = hwords;
+ qp->s_cur_sge = ss;
+ qp->s_cur_size = len;
+ *bth0p = bth0 | (qp->s_state << 24);
+ *bth2p = bth2;
+ return 1;
+
+done:
+ return 0;
+}
+
+static inline void ipath_make_rc_grh(struct ipath_qp *qp,
+ struct ib_global_route *grh,
+ u32 nwords)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+
+ /* GRH header size in 32-bit words. */
+ qp->s_hdrwords += 10;
+ qp->s_hdr.u.l.grh.version_tclass_flow =
+ cpu_to_be32((6 << 28) |
+ (grh->traffic_class << 20) |
+ grh->flow_label);
+ qp->s_hdr.u.l.grh.paylen =
+ cpu_to_be16(((qp->s_hdrwords - 12) + nwords +
+ SIZE_OF_CRC) << 2);
+ /* next_hdr is defined by C8-7 in ch. 8.4.1 */
+ qp->s_hdr.u.l.grh.next_hdr = 0x1B;
+ qp->s_hdr.u.l.grh.hop_limit = grh->hop_limit;
+ /* The SGID is 32-bit aligned. */
+ qp->s_hdr.u.l.grh.sgid.global.subnet_prefix = dev->gid_prefix;
+ qp->s_hdr.u.l.grh.sgid.global.interface_id =
+ ipath_layer_get_guid(dev->dd);
+ qp->s_hdr.u.l.grh.dgid = grh->dgid;
+}
+
+/**
+ * ipath_do_rc_send - perform a send on an RC QP
+ * @data: contains a pointer to the QP
+ *
+ * Process entries in the send work queue until credit or queue is
+ * exhausted. Only allow one CPU to send a packet per QP (tasklet).
+ * Otherwise, after we drop the QP s_lock, two threads could send
+ * packets out of order.
+ */
+void ipath_do_rc_send(unsigned long data)
+{
+ struct ipath_qp *qp = (struct ipath_qp *)data;
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ unsigned long flags;
+ u16 lrh0;
+ u32 nwords;
+ u32 extra_bytes;
+ u32 bth0;
+ u32 bth2;
+ u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ struct ipath_other_headers *ohdr;
+
+ if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags))
+ goto bail;
+
+ if (unlikely(qp->remote_ah_attr.dlid ==
+ ipath_layer_get_lid(dev->dd))) {
+ struct ib_wc wc;
+
+ /*
+ * Pass in an uninitialized ib_wc to be consistent with
+ * other places where ipath_ruc_loopback() is called.
+ */
+ ipath_ruc_loopback(qp, &wc);
+ goto clear;
+ }
+
+ ohdr = &qp->s_hdr.u.oth;
+ if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
+ ohdr = &qp->s_hdr.u.l.oth;
+
+again:
+ /* Check for a constructed packet to be sent. */
+ if (qp->s_hdrwords != 0) {
+ /*
+ * If no PIO bufs are available, return. An interrupt will
+ * call ipath_ib_piobufavail() when one is available.
+ */
+ _VERBS_INFO("h %u %p\n", qp->s_hdrwords, &qp->s_hdr);
+ _VERBS_INFO("d %u %p %u %p %u %u %u %u\n", qp->s_cur_size,
+ qp->s_cur_sge->sg_list,
+ qp->s_cur_sge->num_sge,
+ qp->s_cur_sge->sge.vaddr,
+ qp->s_cur_sge->sge.sge_length,
+ qp->s_cur_sge->sge.length,
+ qp->s_cur_sge->sge.m,
+ qp->s_cur_sge->sge.n);
+ if (ipath_verbs_send(dev->dd, qp->s_hdrwords,
+ (u32 *) &qp->s_hdr, qp->s_cur_size,
+ qp->s_cur_sge)) {
+ ipath_no_bufs_available(qp, dev);
+ goto bail;
+ }
+ dev->n_unicast_xmit++;
+ /* Record that we sent the packet and s_hdr is empty. */
+ qp->s_hdrwords = 0;
+ }
+
+ /*
+ * The lock is needed to synchronize between setting
+ * qp->s_ack_state, resend timer, and post_send().
+ */
+ spin_lock_irqsave(&qp->s_lock, flags);
+
+ /* Sending responses has higher priority over sending requests. */
+ if (qp->s_ack_state != OP(ACKNOWLEDGE) &&
+ (bth0 = ipath_make_rc_ack(qp, ohdr, pmtu)) != 0)
+ bth2 = qp->s_ack_psn++ & IPS_PSN_MASK;
+ else if (!ipath_make_rc_req(qp, ohdr, pmtu, &bth0, &bth2))
+ goto done;
+
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+
+ /* Construct the header. */
+ extra_bytes = (4 - qp->s_cur_size) & 3;
+ nwords = (qp->s_cur_size + extra_bytes) >> 2;
+ lrh0 = IPS_LRH_BTH;
+ if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) {
+ ipath_make_rc_grh(qp, &qp->remote_ah_attr.grh, nwords);
+ lrh0 = IPS_LRH_GRH;
+ }
+ lrh0 |= qp->remote_ah_attr.sl << 4;
+ qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
+ qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
+ qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords +
+ SIZE_OF_CRC);
+ qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd));
+ bth0 |= ipath_layer_get_pkey(dev->dd, qp->s_pkey_index);
+ bth0 |= extra_bytes << 20;
+ ohdr->bth[0] = cpu_to_be32(bth0);
+ ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);
+ ohdr->bth[2] = cpu_to_be32(bth2);
+
+ /* Check for more work to do. */
+ goto again;
+
+done:
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+clear:
+ clear_bit(IPATH_S_BUSY, &qp->s_flags);
+bail:
+ return;
+}
+
+static void send_rc_ack(struct ipath_qp *qp)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ u16 lrh0;
+ u32 bth0;
+ struct ipath_other_headers *ohdr;
+
+ /* Construct the header. */
+ ohdr = &qp->s_hdr.u.oth;
+ lrh0 = IPS_LRH_BTH;
+ /* header size in 32-bit words LRH+BTH+AETH = (8+12+4)/4. */
+ qp->s_hdrwords = 6;
+ if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) {
+ ipath_make_rc_grh(qp, &qp->remote_ah_attr.grh, 0);
+ ohdr = &qp->s_hdr.u.l.oth;
+ lrh0 = IPS_LRH_GRH;
+ }
+ bth0 = ipath_layer_get_pkey(dev->dd, qp->s_pkey_index);
+ ohdr->u.aeth = ipath_compute_aeth(qp);
+ if (qp->s_ack_state >= OP(COMPARE_SWAP)) {
+ bth0 |= IB_OPCODE_ATOMIC_ACKNOWLEDGE << 24;
+ ohdr->u.at.atomic_ack_eth = cpu_to_be64(qp->s_ack_atomic);
+ qp->s_hdrwords += sizeof(ohdr->u.at.atomic_ack_eth) / 4;
+ }
+ else
+ bth0 |= OP(ACKNOWLEDGE) << 24;
+ lrh0 |= qp->remote_ah_attr.sl << 4;
+ qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
+ qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
+ qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + SIZE_OF_CRC);
+ qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd));
+ ohdr->bth[0] = cpu_to_be32(bth0);
+ ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);
+ ohdr->bth[2] = cpu_to_be32(qp->s_ack_psn & IPS_PSN_MASK);
+
+ /*
+ * If we can send the ACK, clear the ACK state.
+ */
+ if (ipath_verbs_send(dev->dd, qp->s_hdrwords, (u32 *) &qp->s_hdr,
+ 0, NULL) == 0) {
+ qp->s_ack_state = OP(ACKNOWLEDGE);
+ dev->n_rc_qacks++;
+ dev->n_unicast_xmit++;
+ }
+}
+
+/**
+ * ipath_restart_rc - back up requester to resend the last un-ACKed request
+ * @qp: the QP to restart
+ * @psn: packet sequence number for the request
+ * @wc: the work completion request
+ *
+ * The QP s_lock should be held.
+ */
+void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc)
+{
+ struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
+ struct ipath_ibdev *dev;
+ u32 n;
+
+ /*
+ * If there are no requests pending, we are done.
+ */
+ if (ipath_cmp24(psn, qp->s_next_psn) >= 0 ||
+ qp->s_last == qp->s_tail)
+ goto done;
+
+ if (qp->s_retry == 0) {
+ wc->wr_id = wqe->wr.wr_id;
+ wc->status = IB_WC_RETRY_EXC_ERR;
+ wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ wc->vendor_err = 0;
+ wc->byte_len = 0;
+ wc->qp_num = qp->ibqp.qp_num;
+ wc->src_qp = qp->remote_qpn;
+ wc->pkey_index = 0;
+ wc->slid = qp->remote_ah_attr.dlid;
+ wc->sl = qp->remote_ah_attr.sl;
+ wc->dlid_path_bits = 0;
+ wc->port_num = 0;
+ ipath_sqerror_qp(qp, wc);
+ goto bail;
+ }
+ qp->s_retry--;
+
+ /*
+ * Remove the QP from the timeout queue.
+ * Note: it may already have been removed by ipath_ib_timer().
+ */
+ dev = to_idev(qp->ibqp.device);
+ spin_lock(&dev->pending_lock);
+ if (!list_empty(&qp->timerwait))
+ list_del_init(&qp->timerwait);
+ spin_unlock(&dev->pending_lock);
+
+ if (wqe->wr.opcode == IB_WR_RDMA_READ)
+ dev->n_rc_resends++;
+ else
+ dev->n_rc_resends += (int)qp->s_psn - (int)psn;
+
+ /*
+ * If we are starting the request from the beginning, let the normal
+ * send code handle initialization.
+ */
+ qp->s_cur = qp->s_last;
+ if (ipath_cmp24(psn, wqe->psn) <= 0) {
+ qp->s_state = OP(SEND_LAST);
+ qp->s_psn = wqe->psn;
+ } else {
+ n = qp->s_cur;
+ for (;;) {
+ if (++n == qp->s_size)
+ n = 0;
+ if (n == qp->s_tail) {
+ if (ipath_cmp24(psn, qp->s_next_psn) >= 0) {
+ qp->s_cur = n;
+ wqe = get_swqe_ptr(qp, n);
+ }
+ break;
+ }
+ wqe = get_swqe_ptr(qp, n);
+ if (ipath_cmp24(psn, wqe->psn) < 0)
+ break;
+ qp->s_cur = n;
+ }
+ qp->s_psn = psn;
+
+ /*
+ * Reset the state to restart in the middle of a request.
+ * Don't change the s_sge, s_cur_sge, or s_cur_size.
+ * See ipath_do_rc_send().
+ */
+ switch (wqe->wr.opcode) {
+ case IB_WR_SEND:
+ case IB_WR_SEND_WITH_IMM:
+ qp->s_state = OP(RDMA_READ_RESPONSE_FIRST);
+ break;
+
+ case IB_WR_RDMA_WRITE:
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ qp->s_state = OP(RDMA_READ_RESPONSE_LAST);
+ break;
+
+ case IB_WR_RDMA_READ:
+ qp->s_state =
+ OP(RDMA_READ_RESPONSE_MIDDLE);
+ break;
+
+ default:
+ /*
+ * This case shouldn't happen since its only
+ * one PSN per req.
+ */
+ qp->s_state = OP(SEND_LAST);
+ }
+ }
+
+done:
+ tasklet_hi_schedule(&qp->s_task);
+
+bail:
+ return;
+}
+
+/**
+ * reset_psn - reset the QP state to send starting from PSN
+ * @qp: the QP
+ * @psn: the packet sequence number to restart at
+ *
+ * This is called from ipath_rc_rcv() to process an incoming RC ACK
+ * for the given QP.
+ * Called at interrupt level with the QP s_lock held.
+ */
+static void reset_psn(struct ipath_qp *qp, u32 psn)
+{
+ struct ipath_swqe *wqe;
+ u32 n;
+
+ n = qp->s_cur;
+ wqe = get_swqe_ptr(qp, n);
+ for (;;) {
+ if (++n == qp->s_size)
+ n = 0;
+ if (n == qp->s_tail) {
+ if (ipath_cmp24(psn, qp->s_next_psn) >= 0) {
+ qp->s_cur = n;
+ wqe = get_swqe_ptr(qp, n);
+ }
+ break;
+ }
+ wqe = get_swqe_ptr(qp, n);
+ if (ipath_cmp24(psn, wqe->psn) < 0)
+ break;
+ qp->s_cur = n;
+ }
+ qp->s_psn = psn;
+
+ /*
+ * Set the state to restart in the middle of a
+ * request. Don't change the s_sge, s_cur_sge, or
+ * s_cur_size. See ipath_do_rc_send().
+ */
+ switch (wqe->wr.opcode) {
+ case IB_WR_SEND:
+ case IB_WR_SEND_WITH_IMM:
+ qp->s_state = OP(RDMA_READ_RESPONSE_FIRST);
+ break;
+
+ case IB_WR_RDMA_WRITE:
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ qp->s_state = OP(RDMA_READ_RESPONSE_LAST);
+ break;
+
+ case IB_WR_RDMA_READ:
+ qp->s_state = OP(RDMA_READ_RESPONSE_MIDDLE);
+ break;
+
+ default:
+ /*
+ * This case shouldn't happen since its only
+ * one PSN per req.
+ */
+ qp->s_state = OP(SEND_LAST);
+ }
+}
+
+/**
+ * do_rc_ack - process an incoming RC ACK
+ * @qp: the QP the ACK came in on
+ * @psn: the packet sequence number of the ACK
+ * @opcode: the opcode of the request that resulted in the ACK
+ *
+ * This is called from ipath_rc_rcv() to process an incoming RC ACK
+ * for the given QP.
+ * Called at interrupt level with the QP s_lock held.
+ * Returns 1 if OK, 0 if current operation should be aborted (NAK).
+ */
+static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ struct ib_wc wc;
+ struct ipath_swqe *wqe;
+ int ret = 0;
+
+ /*
+ * Remove the QP from the timeout queue (or RNR timeout queue).
+ * If ipath_ib_timer() has already removed it,
+ * it's OK since we hold the QP s_lock and ipath_restart_rc()
+ * just won't find anything to restart if we ACK everything.
+ */
+ spin_lock(&dev->pending_lock);
+ if (!list_empty(&qp->timerwait))
+ list_del_init(&qp->timerwait);
+ spin_unlock(&dev->pending_lock);
+
+ /*
+ * Note that NAKs implicitly ACK outstanding SEND and RDMA write
+ * requests and implicitly NAK RDMA read and atomic requests issued
+ * before the NAK'ed request. The MSN won't include the NAK'ed
+ * request but will include an ACK'ed request(s).
+ */
+ wqe = get_swqe_ptr(qp, qp->s_last);
+
+ /* Nothing is pending to ACK/NAK. */
+ if (qp->s_last == qp->s_tail)
+ goto bail;
+
+ /*
+ * The MSN might be for a later WQE than the PSN indicates so
+ * only complete WQEs that the PSN finishes.
+ */
+ while (ipath_cmp24(psn, wqe->lpsn) >= 0) {
+ /* If we are ACKing a WQE, the MSN should be >= the SSN. */
+ if (ipath_cmp24(aeth, wqe->ssn) < 0)
+ break;
+ /*
+ * If this request is a RDMA read or atomic, and the ACK is
+ * for a later operation, this ACK NAKs the RDMA read or
+ * atomic. In other words, only a RDMA_READ_LAST or ONLY
+ * can ACK a RDMA read and likewise for atomic ops. Note
+ * that the NAK case can only happen if relaxed ordering is
+ * used and requests are sent after an RDMA read or atomic
+ * is sent but before the response is received.
+ */
+ if ((wqe->wr.opcode == IB_WR_RDMA_READ &&
+ opcode != OP(RDMA_READ_RESPONSE_LAST)) ||
+ ((wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
+ wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) &&
+ (opcode != OP(ATOMIC_ACKNOWLEDGE) ||
+ ipath_cmp24(wqe->psn, psn) != 0))) {
+ /*
+ * The last valid PSN seen is the previous
+ * request's.
+ */
+ qp->s_last_psn = wqe->psn - 1;
+ /* Retry this request. */
+ ipath_restart_rc(qp, wqe->psn, &wc);
+ /*
+ * No need to process the ACK/NAK since we are
+ * restarting an earlier request.
+ */
+ goto bail;
+ }
+ /* Post a send completion queue entry if requested. */
+ if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &qp->s_flags) ||
+ (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
+ wc.wr_id = wqe->wr.wr_id;
+ wc.status = IB_WC_SUCCESS;
+ wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ wc.vendor_err = 0;
+ wc.byte_len = wqe->length;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = qp->remote_qpn;
+ wc.pkey_index = 0;
+ wc.slid = qp->remote_ah_attr.dlid;
+ wc.sl = qp->remote_ah_attr.sl;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0);
+ }
+ qp->s_retry = qp->s_retry_cnt;
+ /*
+ * If we are completing a request which is in the process of
+ * being resent, we can stop resending it since we know the
+ * responder has already seen it.
+ */
+ if (qp->s_last == qp->s_cur) {
+ if (++qp->s_cur >= qp->s_size)
+ qp->s_cur = 0;
+ wqe = get_swqe_ptr(qp, qp->s_cur);
+ qp->s_state = OP(SEND_LAST);
+ qp->s_psn = wqe->psn;
+ }
+ if (++qp->s_last >= qp->s_size)
+ qp->s_last = 0;
+ wqe = get_swqe_ptr(qp, qp->s_last);
+ if (qp->s_last == qp->s_tail)
+ break;
+ }
+
+ switch (aeth >> 29) {
+ case 0: /* ACK */
+ dev->n_rc_acks++;
+ /* If this is a partial ACK, reset the retransmit timer. */
+ if (qp->s_last != qp->s_tail) {
+ spin_lock(&dev->pending_lock);
+ list_add_tail(&qp->timerwait,
+ &dev->pending[dev->pending_index]);
+ spin_unlock(&dev->pending_lock);
+ }
+ ipath_get_credit(qp, aeth);
+ qp->s_rnr_retry = qp->s_rnr_retry_cnt;
+ qp->s_retry = qp->s_retry_cnt;
+ qp->s_last_psn = psn;
+ ret = 1;
+ goto bail;
+
+ case 1: /* RNR NAK */
+ dev->n_rnr_naks++;
+ if (qp->s_rnr_retry == 0) {
+ if (qp->s_last == qp->s_tail)
+ goto bail;
+
+ wc.status = IB_WC_RNR_RETRY_EXC_ERR;
+ goto class_b;
+ }
+ if (qp->s_rnr_retry_cnt < 7)
+ qp->s_rnr_retry--;
+ if (qp->s_last == qp->s_tail)
+ goto bail;
+
+ /* The last valid PSN seen is the previous request's. */
+ qp->s_last_psn = wqe->psn - 1;
+
+ dev->n_rc_resends += (int)qp->s_psn - (int)psn;
+
+ /*
+ * If we are starting the request from the beginning, let
+ * the normal send code handle initialization.
+ */
+ qp->s_cur = qp->s_last;
+ wqe = get_swqe_ptr(qp, qp->s_cur);
+ if (ipath_cmp24(psn, wqe->psn) <= 0) {
+ qp->s_state = OP(SEND_LAST);
+ qp->s_psn = wqe->psn;
+ } else
+ reset_psn(qp, psn);
+
+ qp->s_rnr_timeout =
+ ib_ipath_rnr_table[(aeth >> IPS_AETH_CREDIT_SHIFT) &
+ IPS_AETH_CREDIT_MASK];
+ ipath_insert_rnr_queue(qp);
+ goto bail;
+
+ case 3: /* NAK */
+ /* The last valid PSN seen is the previous request's. */
+ if (qp->s_last != qp->s_tail)
+ qp->s_last_psn = wqe->psn - 1;
+ switch ((aeth >> IPS_AETH_CREDIT_SHIFT) &
+ IPS_AETH_CREDIT_MASK) {
+ case 0: /* PSN sequence error */
+ dev->n_seq_naks++;
+ /*
+ * Back up to the responder's expected PSN. XXX
+ * Note that we might get a NAK in the middle of an
+ * RDMA READ response which terminates the RDMA
+ * READ.
+ */
+ if (qp->s_last == qp->s_tail)
+ break;
+
+ if (ipath_cmp24(psn, wqe->psn) < 0)
+ break;
+
+ /* Retry the request. */
+ ipath_restart_rc(qp, psn, &wc);
+ break;
+
+ case 1: /* Invalid Request */
+ wc.status = IB_WC_REM_INV_REQ_ERR;
+ dev->n_other_naks++;
+ goto class_b;
+
+ case 2: /* Remote Access Error */
+ wc.status = IB_WC_REM_ACCESS_ERR;
+ dev->n_other_naks++;
+ goto class_b;
+
+ case 3: /* Remote Operation Error */
+ wc.status = IB_WC_REM_OP_ERR;
+ dev->n_other_naks++;
+ class_b:
+ wc.wr_id = wqe->wr.wr_id;
+ wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ wc.vendor_err = 0;
+ wc.byte_len = 0;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = qp->remote_qpn;
+ wc.pkey_index = 0;
+ wc.slid = qp->remote_ah_attr.dlid;
+ wc.sl = qp->remote_ah_attr.sl;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+ ipath_sqerror_qp(qp, &wc);
+ break;
+
+ default:
+ /* Ignore other reserved NAK error codes */
+ goto reserved;
+ }
+ qp->s_rnr_retry = qp->s_rnr_retry_cnt;
+ goto bail;
+
+ default: /* 2: reserved */
+ reserved:
+ /* Ignore reserved NAK codes. */
+ goto bail;
+ }
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_rc_rcv_resp - process an incoming RC response packet
+ * @dev: the device this packet came in on
+ * @ohdr: the other headers for this packet
+ * @data: the packet data
+ * @tlen: the packet length
+ * @qp: the QP for this packet
+ * @opcode: the opcode for this packet
+ * @psn: the packet sequence number for this packet
+ * @hdrsize: the header length
+ * @pmtu: the path MTU
+ * @header_in_data: true if part of the header data is in the data buffer
+ *
+ * This is called from ipath_rc_rcv() to process an incoming RC response
+ * packet for the given QP.
+ * Called at interrupt level.
+ */
+static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
+ struct ipath_other_headers *ohdr,
+ void *data, u32 tlen,
+ struct ipath_qp *qp,
+ u32 opcode,
+ u32 psn, u32 hdrsize, u32 pmtu,
+ int header_in_data)
+{
+ unsigned long flags;
+ struct ib_wc wc;
+ int diff;
+ u32 pad;
+ u32 aeth;
+
+ spin_lock_irqsave(&qp->s_lock, flags);
+
+ /* Ignore invalid responses. */
+ if (ipath_cmp24(psn, qp->s_next_psn) >= 0)
+ goto ack_done;
+
+ /* Ignore duplicate responses. */
+ diff = ipath_cmp24(psn, qp->s_last_psn);
+ if (unlikely(diff <= 0)) {
+ /* Update credits for "ghost" ACKs */
+ if (diff == 0 && opcode == OP(ACKNOWLEDGE)) {
+ if (!header_in_data)
+ aeth = be32_to_cpu(ohdr->u.aeth);
+ else {
+ aeth = be32_to_cpu(((__be32 *) data)[0]);
+ data += sizeof(__be32);
+ }
+ if ((aeth >> 29) == 0)
+ ipath_get_credit(qp, aeth);
+ }
+ goto ack_done;
+ }
+
+ switch (opcode) {
+ case OP(ACKNOWLEDGE):
+ case OP(ATOMIC_ACKNOWLEDGE):
+ case OP(RDMA_READ_RESPONSE_FIRST):
+ if (!header_in_data)
+ aeth = be32_to_cpu(ohdr->u.aeth);
+ else {
+ aeth = be32_to_cpu(((__be32 *) data)[0]);
+ data += sizeof(__be32);
+ }
+ if (opcode == OP(ATOMIC_ACKNOWLEDGE))
+ *(u64 *) qp->s_sge.sge.vaddr = *(u64 *) data;
+ if (!do_rc_ack(qp, aeth, psn, opcode) ||
+ opcode != OP(RDMA_READ_RESPONSE_FIRST))
+ goto ack_done;
+ hdrsize += 4;
+ /*
+ * do_rc_ack() has already checked the PSN so skip
+ * the sequence check.
+ */
+ goto rdma_read;
+
+ case OP(RDMA_READ_RESPONSE_MIDDLE):
+ /* no AETH, no ACK */
+ if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) {
+ dev->n_rdma_seq++;
+ ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
+ goto ack_done;
+ }
+ rdma_read:
+ if (unlikely(qp->s_state != OP(RDMA_READ_REQUEST)))
+ goto ack_done;
+ if (unlikely(tlen != (hdrsize + pmtu + 4)))
+ goto ack_done;
+ if (unlikely(pmtu >= qp->s_len))
+ goto ack_done;
+ /* We got a response so update the timeout. */
+ if (unlikely(qp->s_last == qp->s_tail ||
+ get_swqe_ptr(qp, qp->s_last)->wr.opcode !=
+ IB_WR_RDMA_READ))
+ goto ack_done;
+ spin_lock(&dev->pending_lock);
+ if (qp->s_rnr_timeout == 0 && !list_empty(&qp->timerwait))
+ list_move_tail(&qp->timerwait,
+ &dev->pending[dev->pending_index]);
+ spin_unlock(&dev->pending_lock);
+ /*
+ * Update the RDMA receive state but do the copy w/o holding the
+ * locks and blocking interrupts. XXX Yet another place that
+ * affects relaxed RDMA order since we don't want s_sge modified.
+ */
+ qp->s_len -= pmtu;
+ qp->s_last_psn = psn;
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+ ipath_copy_sge(&qp->s_sge, data, pmtu);
+ goto bail;
+
+ case OP(RDMA_READ_RESPONSE_LAST):
+ /* ACKs READ req. */
+ if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) {
+ dev->n_rdma_seq++;
+ ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
+ goto ack_done;
+ }
+ /* FALLTHROUGH */
+ case OP(RDMA_READ_RESPONSE_ONLY):
+ if (unlikely(qp->s_state != OP(RDMA_READ_REQUEST)))
+ goto ack_done;
+ /*
+ * Get the number of bytes the message was padded by.
+ */
+ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ /*
+ * Check that the data size is >= 1 && <= pmtu.
+ * Remember to account for the AETH header (4) and
+ * ICRC (4).
+ */
+ if (unlikely(tlen <= (hdrsize + pad + 8))) {
+ /*
+ * XXX Need to generate an error CQ
+ * entry.
+ */
+ goto ack_done;
+ }
+ tlen -= hdrsize + pad + 8;
+ if (unlikely(tlen != qp->s_len)) {
+ /*
+ * XXX Need to generate an error CQ
+ * entry.
+ */
+ goto ack_done;
+ }
+ if (!header_in_data)
+ aeth = be32_to_cpu(ohdr->u.aeth);
+ else {
+ aeth = be32_to_cpu(((__be32 *) data)[0]);
+ data += sizeof(__be32);
+ }
+ ipath_copy_sge(&qp->s_sge, data, tlen);
+ if (do_rc_ack(qp, aeth, psn, OP(RDMA_READ_RESPONSE_LAST))) {
+ /*
+ * Change the state so we contimue
+ * processing new requests.
+ */
+ qp->s_state = OP(SEND_LAST);
+ }
+ goto ack_done;
+ }
+
+ack_done:
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+bail:
+ return;
+}
+
+/**
+ * ipath_rc_rcv_error - process an incoming duplicate or error RC packet
+ * @dev: the device this packet came in on
+ * @ohdr: the other headers for this packet
+ * @data: the packet data
+ * @qp: the QP for this packet
+ * @opcode: the opcode for this packet
+ * @psn: the packet sequence number for this packet
+ * @diff: the difference between the PSN and the expected PSN
+ * @header_in_data: true if part of the header data is in the data buffer
+ *
+ * This is called from ipath_rc_rcv() to process an unexpected
+ * incoming RC packet for the given QP.
+ * Called at interrupt level.
+ * Return 1 if no more processing is needed; otherwise return 0 to
+ * schedule a response to be sent and the s_lock unlocked.
+ */
+static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev,
+ struct ipath_other_headers *ohdr,
+ void *data,
+ struct ipath_qp *qp,
+ u32 opcode,
+ u32 psn,
+ int diff,
+ int header_in_data)
+{
+ struct ib_reth *reth;
+
+ if (diff > 0) {
+ /*
+ * Packet sequence error.
+ * A NAK will ACK earlier sends and RDMA writes.
+ * Don't queue the NAK if a RDMA read, atomic, or
+ * NAK is pending though.
+ */
+ spin_lock(&qp->s_lock);
+ if ((qp->s_ack_state >= OP(RDMA_READ_REQUEST) &&
+ qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE) ||
+ qp->s_nak_state != 0) {
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ qp->s_ack_state = OP(SEND_ONLY);
+ qp->s_nak_state = IB_NAK_PSN_ERROR;
+ /* Use the expected PSN. */
+ qp->s_ack_psn = qp->r_psn;
+ goto resched;
+ }
+
+ /*
+ * Handle a duplicate request. Don't re-execute SEND, RDMA
+ * write or atomic op. Don't NAK errors, just silently drop
+ * the duplicate request. Note that r_sge, r_len, and
+ * r_rcv_len may be in use so don't modify them.
+ *
+ * We are supposed to ACK the earliest duplicate PSN but we
+ * can coalesce an outstanding duplicate ACK. We have to
+ * send the earliest so that RDMA reads can be restarted at
+ * the requester's expected PSN.
+ */
+ spin_lock(&qp->s_lock);
+ if (qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE &&
+ ipath_cmp24(psn, qp->s_ack_psn) >= 0) {
+ if (qp->s_ack_state < IB_OPCODE_RDMA_READ_REQUEST)
+ qp->s_ack_psn = psn;
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ switch (opcode) {
+ case OP(RDMA_READ_REQUEST):
+ /*
+ * We have to be careful to not change s_rdma_sge
+ * while ipath_do_rc_send() is using it and not
+ * holding the s_lock.
+ */
+ if (qp->s_ack_state != OP(ACKNOWLEDGE) &&
+ qp->s_ack_state >= IB_OPCODE_RDMA_READ_REQUEST) {
+ spin_unlock(&qp->s_lock);
+ dev->n_rdma_dup_busy++;
+ goto done;
+ }
+ /* RETH comes after BTH */
+ if (!header_in_data)
+ reth = &ohdr->u.rc.reth;
+ else {
+ reth = (struct ib_reth *)data;
+ data += sizeof(*reth);
+ }
+ qp->s_rdma_len = be32_to_cpu(reth->length);
+ if (qp->s_rdma_len != 0) {
+ u32 rkey = be32_to_cpu(reth->rkey);
+ u64 vaddr = be64_to_cpu(reth->vaddr);
+ int ok;
+
+ /*
+ * Address range must be a subset of the original
+ * request and start on pmtu boundaries.
+ */
+ ok = ipath_rkey_ok(dev, &qp->s_rdma_sge,
+ qp->s_rdma_len, vaddr, rkey,
+ IB_ACCESS_REMOTE_READ);
+ if (unlikely(!ok))
+ goto done;
+ } else {
+ qp->s_rdma_sge.sg_list = NULL;
+ qp->s_rdma_sge.num_sge = 0;
+ qp->s_rdma_sge.sge.mr = NULL;
+ qp->s_rdma_sge.sge.vaddr = NULL;
+ qp->s_rdma_sge.sge.length = 0;
+ qp->s_rdma_sge.sge.sge_length = 0;
+ }
+ break;
+
+ case OP(COMPARE_SWAP):
+ case OP(FETCH_ADD):
+ /*
+ * Check for the PSN of the last atomic operations
+ * performed and resend the result if found.
+ */
+ if ((psn & IPS_PSN_MASK) != qp->r_atomic_psn) {
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ qp->s_ack_atomic = qp->r_atomic_data;
+ break;
+ }
+ qp->s_ack_state = opcode;
+ qp->s_nak_state = 0;
+ qp->s_ack_psn = psn;
+resched:
+ return 0;
+
+done:
+ return 1;
+}
+
+/**
+ * ipath_rc_rcv - process an incoming RC packet
+ * @dev: the device this packet came in on
+ * @hdr: the header of this packet
+ * @has_grh: true if the header has a GRH
+ * @data: the packet data
+ * @tlen: the packet length
+ * @qp: the QP for this packet
+ *
+ * This is called from ipath_qp_rcv() to process an incoming RC packet
+ * for the given QP.
+ * Called at interrupt level.
+ */
+void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ int has_grh, void *data, u32 tlen, struct ipath_qp *qp)
+{
+ struct ipath_other_headers *ohdr;
+ u32 opcode;
+ u32 hdrsize;
+ u32 psn;
+ u32 pad;
+ unsigned long flags;
+ struct ib_wc wc;
+ u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ int diff;
+ struct ib_reth *reth;
+ int header_in_data;
+
+ /* Check for GRH */
+ if (!has_grh) {
+ ohdr = &hdr->u.oth;
+ hdrsize = 8 + 12; /* LRH + BTH */
+ psn = be32_to_cpu(ohdr->bth[2]);
+ header_in_data = 0;
+ } else {
+ ohdr = &hdr->u.l.oth;
+ hdrsize = 8 + 40 + 12; /* LRH + GRH + BTH */
+ /*
+ * The header with GRH is 60 bytes and the core driver sets
+ * the eager header buffer size to 56 bytes so the last 4
+ * bytes of the BTH header (PSN) is in the data buffer.
+ */
+ header_in_data =
+ ipath_layer_get_rcvhdrentsize(dev->dd) == 16;
+ if (header_in_data) {
+ psn = be32_to_cpu(((__be32 *) data)[0]);
+ data += sizeof(__be32);
+ } else
+ psn = be32_to_cpu(ohdr->bth[2]);
+ }
+ /*
+ * The opcode is in the low byte when its in network order
+ * (top byte when in host order).
+ */
+ opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+
+ /*
+ * Process responses (ACKs) before anything else. Note that the
+ * packet sequence number will be for something in the send work
+ * queue rather than the expected receive packet sequence number.
+ * In other words, this QP is the requester.
+ */
+ if (opcode >= OP(RDMA_READ_RESPONSE_FIRST) &&
+ opcode <= OP(ATOMIC_ACKNOWLEDGE)) {
+ ipath_rc_rcv_resp(dev, ohdr, data, tlen, qp, opcode, psn,
+ hdrsize, pmtu, header_in_data);
+ goto bail;
+ }
+
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+
+ /* Compute 24 bits worth of difference. */
+ diff = ipath_cmp24(psn, qp->r_psn);
+ if (unlikely(diff)) {
+ if (ipath_rc_rcv_error(dev, ohdr, data, qp, opcode,
+ psn, diff, header_in_data))
+ goto done;
+ goto resched;
+ }
+
+ /* Check for opcode sequence errors. */
+ switch (qp->r_state) {
+ case OP(SEND_FIRST):
+ case OP(SEND_MIDDLE):
+ if (opcode == OP(SEND_MIDDLE) ||
+ opcode == OP(SEND_LAST) ||
+ opcode == OP(SEND_LAST_WITH_IMMEDIATE))
+ break;
+ nack_inv:
+ /*
+ * A NAK will ACK earlier sends and RDMA writes. Don't queue the
+ * NAK if a RDMA read, atomic, or NAK is pending though.
+ */
+ spin_lock(&qp->s_lock);
+ if (qp->s_ack_state >= OP(RDMA_READ_REQUEST) &&
+ qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE) {
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ /* XXX Flush WQEs */
+ qp->state = IB_QPS_ERR;
+ qp->s_ack_state = OP(SEND_ONLY);
+ qp->s_nak_state = IB_NAK_INVALID_REQUEST;
+ qp->s_ack_psn = qp->r_psn;
+ goto resched;
+
+ case OP(RDMA_WRITE_FIRST):
+ case OP(RDMA_WRITE_MIDDLE):
+ if (opcode == OP(RDMA_WRITE_MIDDLE) ||
+ opcode == OP(RDMA_WRITE_LAST) ||
+ opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE))
+ break;
+ goto nack_inv;
+
+ case OP(RDMA_READ_REQUEST):
+ case OP(COMPARE_SWAP):
+ case OP(FETCH_ADD):
+ /*
+ * Drop all new requests until a response has been sent. A
+ * new request then ACKs the RDMA response we sent. Relaxed
+ * ordering would allow new requests to be processed but we
+ * would need to keep a queue of rwqe's for all that are in
+ * progress. Note that we can't RNR NAK this request since
+ * the RDMA READ or atomic response is already queued to be
+ * sent (unless we implement a response send queue).
+ */
+ goto done;
+
+ default:
+ if (opcode == OP(SEND_MIDDLE) ||
+ opcode == OP(SEND_LAST) ||
+ opcode == OP(SEND_LAST_WITH_IMMEDIATE) ||
+ opcode == OP(RDMA_WRITE_MIDDLE) ||
+ opcode == OP(RDMA_WRITE_LAST) ||
+ opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE))
+ goto nack_inv;
+ break;
+ }
+
+ wc.imm_data = 0;
+ wc.wc_flags = 0;
+
+ /* OK, process the packet. */
+ switch (opcode) {
+ case OP(SEND_FIRST):
+ if (!ipath_get_rwqe(qp, 0)) {
+ rnr_nak:
+ /*
+ * A RNR NAK will ACK earlier sends and RDMA writes.
+ * Don't queue the NAK if a RDMA read or atomic
+ * is pending though.
+ */
+ spin_lock(&qp->s_lock);
+ if (qp->s_ack_state >=
+ OP(RDMA_READ_REQUEST) &&
+ qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE) {
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ qp->s_ack_state = OP(SEND_ONLY);
+ qp->s_nak_state = IB_RNR_NAK | qp->s_min_rnr_timer;
+ qp->s_ack_psn = qp->r_psn;
+ goto resched;
+ }
+ qp->r_rcv_len = 0;
+ /* FALLTHROUGH */
+ case OP(SEND_MIDDLE):
+ case OP(RDMA_WRITE_MIDDLE):
+ send_middle:
+ /* Check for invalid length PMTU or posted rwqe len. */
+ if (unlikely(tlen != (hdrsize + pmtu + 4)))
+ goto nack_inv;
+ qp->r_rcv_len += pmtu;
+ if (unlikely(qp->r_rcv_len > qp->r_len))
+ goto nack_inv;
+ ipath_copy_sge(&qp->r_sge, data, pmtu);
+ break;
+
+ case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE):
+ /* consume RWQE */
+ if (!ipath_get_rwqe(qp, 1))
+ goto rnr_nak;
+ goto send_last_imm;
+
+ case OP(SEND_ONLY):
+ case OP(SEND_ONLY_WITH_IMMEDIATE):
+ if (!ipath_get_rwqe(qp, 0))
+ goto rnr_nak;
+ qp->r_rcv_len = 0;
+ if (opcode == OP(SEND_ONLY))
+ goto send_last;
+ /* FALLTHROUGH */
+ case OP(SEND_LAST_WITH_IMMEDIATE):
+ send_last_imm:
+ if (header_in_data) {
+ wc.imm_data = *(__be32 *) data;
+ data += sizeof(__be32);
+ } else {
+ /* Immediate data comes after BTH */
+ wc.imm_data = ohdr->u.imm_data;
+ }
+ hdrsize += 4;
+ wc.wc_flags = IB_WC_WITH_IMM;
+ /* FALLTHROUGH */
+ case OP(SEND_LAST):
+ case OP(RDMA_WRITE_LAST):
+ send_last:
+ /* Get the number of bytes the message was padded by. */
+ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ /* Check for invalid length. */
+ /* XXX LAST len should be >= 1 */
+ if (unlikely(tlen < (hdrsize + pad + 4)))
+ goto nack_inv;
+ /* Don't count the CRC. */
+ tlen -= (hdrsize + pad + 4);
+ wc.byte_len = tlen + qp->r_rcv_len;
+ if (unlikely(wc.byte_len > qp->r_len))
+ goto nack_inv;
+ ipath_copy_sge(&qp->r_sge, data, tlen);
+ atomic_inc(&qp->msn);
+ if (opcode == OP(RDMA_WRITE_LAST) ||
+ opcode == OP(RDMA_WRITE_ONLY))
+ break;
+ wc.wr_id = qp->r_wr_id;
+ wc.status = IB_WC_SUCCESS;
+ wc.opcode = IB_WC_RECV;
+ wc.vendor_err = 0;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = qp->remote_qpn;
+ wc.pkey_index = 0;
+ wc.slid = qp->remote_ah_attr.dlid;
+ wc.sl = qp->remote_ah_attr.sl;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+ /* Signal completion event if the solicited bit is set. */
+ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
+ (ohdr->bth[0] &
+ __constant_cpu_to_be32(1 << 23)) != 0);
+ break;
+
+ case OP(RDMA_WRITE_FIRST):
+ case OP(RDMA_WRITE_ONLY):
+ case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE):
+ /* consume RWQE */
+ /* RETH comes after BTH */
+ if (!header_in_data)
+ reth = &ohdr->u.rc.reth;
+ else {
+ reth = (struct ib_reth *)data;
+ data += sizeof(*reth);
+ }
+ hdrsize += sizeof(*reth);
+ qp->r_len = be32_to_cpu(reth->length);
+ qp->r_rcv_len = 0;
+ if (qp->r_len != 0) {
+ u32 rkey = be32_to_cpu(reth->rkey);
+ u64 vaddr = be64_to_cpu(reth->vaddr);
+ int ok;
+
+ /* Check rkey & NAK */
+ ok = ipath_rkey_ok(dev, &qp->r_sge,
+ qp->r_len, vaddr, rkey,
+ IB_ACCESS_REMOTE_WRITE);
+ if (unlikely(!ok)) {
+ nack_acc:
+ /*
+ * A NAK will ACK earlier sends and RDMA
+ * writes. Don't queue the NAK if a RDMA
+ * read, atomic, or NAK is pending though.
+ */
+ spin_lock(&qp->s_lock);
+ if (qp->s_ack_state >=
+ OP(RDMA_READ_REQUEST) &&
+ qp->s_ack_state !=
+ IB_OPCODE_ACKNOWLEDGE) {
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ /* XXX Flush WQEs */
+ qp->state = IB_QPS_ERR;
+ qp->s_ack_state = OP(RDMA_WRITE_ONLY);
+ qp->s_nak_state =
+ IB_NAK_REMOTE_ACCESS_ERROR;
+ qp->s_ack_psn = qp->r_psn;
+ goto resched;
+ }
+ } else {
+ qp->r_sge.sg_list = NULL;
+ qp->r_sge.sge.mr = NULL;
+ qp->r_sge.sge.vaddr = NULL;
+ qp->r_sge.sge.length = 0;
+ qp->r_sge.sge.sge_length = 0;
+ }
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_WRITE)))
+ goto nack_acc;
+ if (opcode == OP(RDMA_WRITE_FIRST))
+ goto send_middle;
+ else if (opcode == OP(RDMA_WRITE_ONLY))
+ goto send_last;
+ if (!ipath_get_rwqe(qp, 1))
+ goto rnr_nak;
+ goto send_last_imm;
+
+ case OP(RDMA_READ_REQUEST):
+ /* RETH comes after BTH */
+ if (!header_in_data)
+ reth = &ohdr->u.rc.reth;
+ else {
+ reth = (struct ib_reth *)data;
+ data += sizeof(*reth);
+ }
+ spin_lock(&qp->s_lock);
+ if (qp->s_ack_state != OP(ACKNOWLEDGE) &&
+ qp->s_ack_state >= IB_OPCODE_RDMA_READ_REQUEST) {
+ spin_unlock(&qp->s_lock);
+ goto done;
+ }
+ qp->s_rdma_len = be32_to_cpu(reth->length);
+ if (qp->s_rdma_len != 0) {
+ u32 rkey = be32_to_cpu(reth->rkey);
+ u64 vaddr = be64_to_cpu(reth->vaddr);
+ int ok;
+
+ /* Check rkey & NAK */
+ ok = ipath_rkey_ok(dev, &qp->s_rdma_sge,
+ qp->s_rdma_len, vaddr, rkey,
+ IB_ACCESS_REMOTE_READ);
+ if (unlikely(!ok)) {
+ spin_unlock(&qp->s_lock);
+ goto nack_acc;
+ }
+ /*
+ * Update the next expected PSN. We add 1 later
+ * below, so only add the remainder here.
+ */
+ if (qp->s_rdma_len > pmtu)
+ qp->r_psn += (qp->s_rdma_len - 1) / pmtu;
+ } else {
+ qp->s_rdma_sge.sg_list = NULL;
+ qp->s_rdma_sge.num_sge = 0;
+ qp->s_rdma_sge.sge.mr = NULL;
+ qp->s_rdma_sge.sge.vaddr = NULL;
+ qp->s_rdma_sge.sge.length = 0;
+ qp->s_rdma_sge.sge.sge_length = 0;
+ }
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_READ)))
+ goto nack_acc;
+ /*
+ * We need to increment the MSN here instead of when we
+ * finish sending the result since a duplicate request would
+ * increment it more than once.
+ */
+ atomic_inc(&qp->msn);
+ qp->s_ack_state = opcode;
+ qp->s_nak_state = 0;
+ qp->s_ack_psn = psn;
+ qp->r_psn++;
+ qp->r_state = opcode;
+ goto rdmadone;
+
+ case OP(COMPARE_SWAP):
+ case OP(FETCH_ADD): {
+ struct ib_atomic_eth *ateth;
+ u64 vaddr;
+ u64 sdata;
+ u32 rkey;
+
+ if (!header_in_data)
+ ateth = &ohdr->u.atomic_eth;
+ else {
+ ateth = (struct ib_atomic_eth *)data;
+ data += sizeof(*ateth);
+ }
+ vaddr = be64_to_cpu(ateth->vaddr);
+ if (unlikely(vaddr & (sizeof(u64) - 1)))
+ goto nack_inv;
+ rkey = be32_to_cpu(ateth->rkey);
+ /* Check rkey & NAK */
+ if (unlikely(!ipath_rkey_ok(dev, &qp->r_sge,
+ sizeof(u64), vaddr, rkey,
+ IB_ACCESS_REMOTE_ATOMIC)))
+ goto nack_acc;
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_ATOMIC)))
+ goto nack_acc;
+ /* Perform atomic OP and save result. */
+ sdata = be64_to_cpu(ateth->swap_data);
+ spin_lock(&dev->pending_lock);
+ qp->r_atomic_data = *(u64 *) qp->r_sge.sge.vaddr;
+ if (opcode == OP(FETCH_ADD))
+ *(u64 *) qp->r_sge.sge.vaddr =
+ qp->r_atomic_data + sdata;
+ else if (qp->r_atomic_data ==
+ be64_to_cpu(ateth->compare_data))
+ *(u64 *) qp->r_sge.sge.vaddr = sdata;
+ spin_unlock(&dev->pending_lock);
+ atomic_inc(&qp->msn);
+ qp->r_atomic_psn = psn & IPS_PSN_MASK;
+ psn |= 1 << 31;
+ break;
+ }
+
+ default:
+ /* Drop packet for unknown opcodes. */
+ goto done;
+ }
+ qp->r_psn++;
+ qp->r_state = opcode;
+ /* Send an ACK if requested or required. */
+ if (psn & (1 << 31)) {
+ /*
+ * Coalesce ACKs unless there is a RDMA READ or
+ * ATOMIC pending.
+ */
+ spin_lock(&qp->s_lock);
+ if (qp->s_ack_state == OP(ACKNOWLEDGE) ||
+ qp->s_ack_state < IB_OPCODE_RDMA_READ_REQUEST) {
+ qp->s_ack_state = opcode;
+ qp->s_nak_state = 0;
+ qp->s_ack_psn = psn;
+ qp->s_ack_atomic = qp->r_atomic_data;
+ goto resched;
+ }
+ spin_unlock(&qp->s_lock);
+ }
+done:
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ goto bail;
+
+resched:
+ /*
+ * Try to send ACK right away but not if ipath_do_rc_send() is
+ * active.
+ */
+ if (qp->s_hdrwords == 0 &&
+ (qp->s_ack_state < IB_OPCODE_RDMA_READ_REQUEST ||
+ qp->s_ack_state >= IB_OPCODE_COMPARE_SWAP))
+ send_rc_ack(qp);
+
+rdmadone:
+ spin_unlock(&qp->s_lock);
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+
+ /* Call ipath_do_rc_send() in another thread. */
+ tasklet_hi_schedule(&qp->s_task);
+
+bail:
+ return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
new file mode 100644
index 00000000000..402126eb79c
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_registers.h
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _IPATH_REGISTERS_H
+#define _IPATH_REGISTERS_H
+
+/*
+ * This file should only be included by kernel source, and by the diags. It
+ * defines the registers, and their contents, for the InfiniPath HT-400
+ * chip.
+ */
+
+/*
+ * These are the InfiniPath register and buffer bit definitions,
+ * that are visible to software, and needed only by the kernel
+ * and diag code. A few, that are visible to protocol and user
+ * code are in ipath_common.h. Some bits are specific
+ * to a given chip implementation, and have been moved to the
+ * chip-specific source file
+ */
+
+/* kr_revision bits */
+#define INFINIPATH_R_CHIPREVMINOR_MASK 0xFF
+#define INFINIPATH_R_CHIPREVMINOR_SHIFT 0
+#define INFINIPATH_R_CHIPREVMAJOR_MASK 0xFF
+#define INFINIPATH_R_CHIPREVMAJOR_SHIFT 8
+#define INFINIPATH_R_ARCH_MASK 0xFF
+#define INFINIPATH_R_ARCH_SHIFT 16
+#define INFINIPATH_R_SOFTWARE_MASK 0xFF
+#define INFINIPATH_R_SOFTWARE_SHIFT 24
+#define INFINIPATH_R_BOARDID_MASK 0xFF
+#define INFINIPATH_R_BOARDID_SHIFT 32
+
+/* kr_control bits */
+#define INFINIPATH_C_FREEZEMODE 0x00000002
+#define INFINIPATH_C_LINKENABLE 0x00000004
+#define INFINIPATH_C_RESET 0x00000001
+
+/* kr_sendctrl bits */
+#define INFINIPATH_S_DISARMPIOBUF_SHIFT 16
+
+#define IPATH_S_ABORT 0
+#define IPATH_S_PIOINTBUFAVAIL 1
+#define IPATH_S_PIOBUFAVAILUPD 2
+#define IPATH_S_PIOENABLE 3
+#define IPATH_S_DISARM 31
+
+#define INFINIPATH_S_ABORT (1U << IPATH_S_ABORT)
+#define INFINIPATH_S_PIOINTBUFAVAIL (1U << IPATH_S_PIOINTBUFAVAIL)
+#define INFINIPATH_S_PIOBUFAVAILUPD (1U << IPATH_S_PIOBUFAVAILUPD)
+#define INFINIPATH_S_PIOENABLE (1U << IPATH_S_PIOENABLE)
+#define INFINIPATH_S_DISARM (1U << IPATH_S_DISARM)
+
+/* kr_rcvctrl bits */
+#define INFINIPATH_R_PORTENABLE_SHIFT 0
+#define INFINIPATH_R_INTRAVAIL_SHIFT 16
+#define INFINIPATH_R_TAILUPD 0x80000000
+
+/* kr_intstatus, kr_intclear, kr_intmask bits */
+#define INFINIPATH_I_RCVURG_SHIFT 0
+#define INFINIPATH_I_RCVAVAIL_SHIFT 12
+#define INFINIPATH_I_ERROR 0x80000000
+#define INFINIPATH_I_SPIOSENT 0x40000000
+#define INFINIPATH_I_SPIOBUFAVAIL 0x20000000
+#define INFINIPATH_I_GPIO 0x10000000
+
+/* kr_errorstatus, kr_errorclear, kr_errormask bits */
+#define INFINIPATH_E_RFORMATERR 0x0000000000000001ULL
+#define INFINIPATH_E_RVCRC 0x0000000000000002ULL
+#define INFINIPATH_E_RICRC 0x0000000000000004ULL
+#define INFINIPATH_E_RMINPKTLEN 0x0000000000000008ULL
+#define INFINIPATH_E_RMAXPKTLEN 0x0000000000000010ULL
+#define INFINIPATH_E_RLONGPKTLEN 0x0000000000000020ULL
+#define INFINIPATH_E_RSHORTPKTLEN 0x0000000000000040ULL
+#define INFINIPATH_E_RUNEXPCHAR 0x0000000000000080ULL
+#define INFINIPATH_E_RUNSUPVL 0x0000000000000100ULL
+#define INFINIPATH_E_REBP 0x0000000000000200ULL
+#define INFINIPATH_E_RIBFLOW 0x0000000000000400ULL
+#define INFINIPATH_E_RBADVERSION 0x0000000000000800ULL
+#define INFINIPATH_E_RRCVEGRFULL 0x0000000000001000ULL
+#define INFINIPATH_E_RRCVHDRFULL 0x0000000000002000ULL
+#define INFINIPATH_E_RBADTID 0x0000000000004000ULL
+#define INFINIPATH_E_RHDRLEN 0x0000000000008000ULL
+#define INFINIPATH_E_RHDR 0x0000000000010000ULL
+#define INFINIPATH_E_RIBLOSTLINK 0x0000000000020000ULL
+#define INFINIPATH_E_SMINPKTLEN 0x0000000020000000ULL
+#define INFINIPATH_E_SMAXPKTLEN 0x0000000040000000ULL
+#define INFINIPATH_E_SUNDERRUN 0x0000000080000000ULL
+#define INFINIPATH_E_SPKTLEN 0x0000000100000000ULL
+#define INFINIPATH_E_SDROPPEDSMPPKT 0x0000000200000000ULL
+#define INFINIPATH_E_SDROPPEDDATAPKT 0x0000000400000000ULL
+#define INFINIPATH_E_SPIOARMLAUNCH 0x0000000800000000ULL
+#define INFINIPATH_E_SUNEXPERRPKTNUM 0x0000001000000000ULL
+#define INFINIPATH_E_SUNSUPVL 0x0000002000000000ULL
+#define INFINIPATH_E_IBSTATUSCHANGED 0x0001000000000000ULL
+#define INFINIPATH_E_INVALIDADDR 0x0002000000000000ULL
+#define INFINIPATH_E_RESET 0x0004000000000000ULL
+#define INFINIPATH_E_HARDWARE 0x0008000000000000ULL
+
+/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+/* TXEMEMPARITYERR bit 0: PIObuf, 1: PIOpbc, 2: launchfifo
+ * RXEMEMPARITYERR bit 0: rcvbuf, 1: lookupq, 2: eagerTID, 3: expTID
+ * bit 4: flag buffer, 5: datainfo, 6: header info */
+#define INFINIPATH_HWE_TXEMEMPARITYERR_MASK 0xFULL
+#define INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT 40
+#define INFINIPATH_HWE_RXEMEMPARITYERR_MASK 0x7FULL
+#define INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT 44
+#define INFINIPATH_HWE_RXDSYNCMEMPARITYERR 0x0000000400000000ULL
+#define INFINIPATH_HWE_MEMBISTFAILED 0x0040000000000000ULL
+#define INFINIPATH_HWE_IBCBUSTOSPCPARITYERR 0x4000000000000000ULL
+#define INFINIPATH_HWE_IBCBUSFRSPCPARITYERR 0x8000000000000000ULL
+
+/* kr_hwdiagctrl bits */
+#define INFINIPATH_DC_FORCETXEMEMPARITYERR_MASK 0xFULL
+#define INFINIPATH_DC_FORCETXEMEMPARITYERR_SHIFT 40
+#define INFINIPATH_DC_FORCERXEMEMPARITYERR_MASK 0x7FULL
+#define INFINIPATH_DC_FORCERXEMEMPARITYERR_SHIFT 44
+#define INFINIPATH_DC_FORCERXDSYNCMEMPARITYERR 0x0000000400000000ULL
+#define INFINIPATH_DC_COUNTERDISABLE 0x1000000000000000ULL
+#define INFINIPATH_DC_COUNTERWREN 0x2000000000000000ULL
+#define INFINIPATH_DC_FORCEIBCBUSTOSPCPARITYERR 0x4000000000000000ULL
+#define INFINIPATH_DC_FORCEIBCBUSFRSPCPARITYERR 0x8000000000000000ULL
+
+/* kr_ibcctrl bits */
+#define INFINIPATH_IBCC_FLOWCTRLPERIOD_MASK 0xFFULL
+#define INFINIPATH_IBCC_FLOWCTRLPERIOD_SHIFT 0
+#define INFINIPATH_IBCC_FLOWCTRLWATERMARK_MASK 0xFFULL
+#define INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT 8
+#define INFINIPATH_IBCC_LINKINITCMD_MASK 0x3ULL
+#define INFINIPATH_IBCC_LINKINITCMD_DISABLE 1
+/* cycle through TS1/TS2 till OK */
+#define INFINIPATH_IBCC_LINKINITCMD_POLL 2
+/* wait for TS1, then go on */
+#define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3
+#define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16
+#define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL
+#define INFINIPATH_IBCC_LINKCMD_INIT 1 /* move to 0x11 */
+#define INFINIPATH_IBCC_LINKCMD_ARMED 2 /* move to 0x21 */
+#define INFINIPATH_IBCC_LINKCMD_ACTIVE 3 /* move to 0x31 */
+#define INFINIPATH_IBCC_LINKCMD_SHIFT 18
+#define INFINIPATH_IBCC_MAXPKTLEN_MASK 0x7FFULL
+#define INFINIPATH_IBCC_MAXPKTLEN_SHIFT 20
+#define INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK 0xFULL
+#define INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT 32
+#define INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK 0xFULL
+#define INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT 36
+#define INFINIPATH_IBCC_CREDITSCALE_MASK 0x7ULL
+#define INFINIPATH_IBCC_CREDITSCALE_SHIFT 40
+#define INFINIPATH_IBCC_LOOPBACK 0x8000000000000000ULL
+#define INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE 0x4000000000000000ULL
+
+/* kr_ibcstatus bits */
+#define INFINIPATH_IBCS_LINKTRAININGSTATE_MASK 0xF
+#define INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT 0
+#define INFINIPATH_IBCS_LINKSTATE_MASK 0x7
+#define INFINIPATH_IBCS_LINKSTATE_SHIFT 4
+#define INFINIPATH_IBCS_TXREADY 0x40000000
+#define INFINIPATH_IBCS_TXCREDITOK 0x80000000
+/* link training states (shift by
+ INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) */
+#define INFINIPATH_IBCS_LT_STATE_DISABLED 0x00
+#define INFINIPATH_IBCS_LT_STATE_LINKUP 0x01
+#define INFINIPATH_IBCS_LT_STATE_POLLACTIVE 0x02
+#define INFINIPATH_IBCS_LT_STATE_POLLQUIET 0x03
+#define INFINIPATH_IBCS_LT_STATE_SLEEPDELAY 0x04
+#define INFINIPATH_IBCS_LT_STATE_SLEEPQUIET 0x05
+#define INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE 0x08
+#define INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG 0x09
+#define INFINIPATH_IBCS_LT_STATE_CFGWAITRMT 0x0a
+#define INFINIPATH_IBCS_LT_STATE_CFGIDLE 0x0b
+#define INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN 0x0c
+#define INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT 0x0e
+#define INFINIPATH_IBCS_LT_STATE_RECOVERIDLE 0x0f
+/* link state machine states (shift by INFINIPATH_IBCS_LINKSTATE_SHIFT) */
+#define INFINIPATH_IBCS_L_STATE_DOWN 0x0
+#define INFINIPATH_IBCS_L_STATE_INIT 0x1
+#define INFINIPATH_IBCS_L_STATE_ARM 0x2
+#define INFINIPATH_IBCS_L_STATE_ACTIVE 0x3
+#define INFINIPATH_IBCS_L_STATE_ACT_DEFER 0x4
+
+/* combination link status states that we use with some frequency */
+#define IPATH_IBSTATE_MASK ((INFINIPATH_IBCS_LINKTRAININGSTATE_MASK \
+ << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+ (INFINIPATH_IBCS_LINKSTATE_MASK \
+ <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+#define IPATH_IBSTATE_INIT ((INFINIPATH_IBCS_L_STATE_INIT \
+ << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+ (INFINIPATH_IBCS_LT_STATE_LINKUP \
+ <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+#define IPATH_IBSTATE_ARM ((INFINIPATH_IBCS_L_STATE_ARM \
+ << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+ (INFINIPATH_IBCS_LT_STATE_LINKUP \
+ <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+#define IPATH_IBSTATE_ACTIVE ((INFINIPATH_IBCS_L_STATE_ACTIVE \
+ << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+ (INFINIPATH_IBCS_LT_STATE_LINKUP \
+ <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+
+/* kr_extstatus bits */
+#define INFINIPATH_EXTS_SERDESPLLLOCK 0x1
+#define INFINIPATH_EXTS_GPIOIN_MASK 0xFFFFULL
+#define INFINIPATH_EXTS_GPIOIN_SHIFT 48
+
+/* kr_extctrl bits */
+#define INFINIPATH_EXTC_GPIOINVERT_MASK 0xFFFFULL
+#define INFINIPATH_EXTC_GPIOINVERT_SHIFT 32
+#define INFINIPATH_EXTC_GPIOOE_MASK 0xFFFFULL
+#define INFINIPATH_EXTC_GPIOOE_SHIFT 48
+#define INFINIPATH_EXTC_SERDESENABLE 0x80000000ULL
+#define INFINIPATH_EXTC_SERDESCONNECT 0x40000000ULL
+#define INFINIPATH_EXTC_SERDESENTRUNKING 0x20000000ULL
+#define INFINIPATH_EXTC_SERDESDISRXFIFO 0x10000000ULL
+#define INFINIPATH_EXTC_SERDESENPLPBK1 0x08000000ULL
+#define INFINIPATH_EXTC_SERDESENPLPBK2 0x04000000ULL
+#define INFINIPATH_EXTC_SERDESENENCDEC 0x02000000ULL
+#define INFINIPATH_EXTC_LED1SECPORT_ON 0x00000020ULL
+#define INFINIPATH_EXTC_LED2SECPORT_ON 0x00000010ULL
+#define INFINIPATH_EXTC_LED1PRIPORT_ON 0x00000008ULL
+#define INFINIPATH_EXTC_LED2PRIPORT_ON 0x00000004ULL
+#define INFINIPATH_EXTC_LEDGBLOK_ON 0x00000002ULL
+#define INFINIPATH_EXTC_LEDGBLERR_OFF 0x00000001ULL
+
+/* kr_mdio bits */
+#define INFINIPATH_MDIO_CLKDIV_MASK 0x7FULL
+#define INFINIPATH_MDIO_CLKDIV_SHIFT 32
+#define INFINIPATH_MDIO_COMMAND_MASK 0x7ULL
+#define INFINIPATH_MDIO_COMMAND_SHIFT 26
+#define INFINIPATH_MDIO_DEVADDR_MASK 0x1FULL
+#define INFINIPATH_MDIO_DEVADDR_SHIFT 21
+#define INFINIPATH_MDIO_REGADDR_MASK 0x1FULL
+#define INFINIPATH_MDIO_REGADDR_SHIFT 16
+#define INFINIPATH_MDIO_DATA_MASK 0xFFFFULL
+#define INFINIPATH_MDIO_DATA_SHIFT 0
+#define INFINIPATH_MDIO_CMDVALID 0x0000000040000000ULL
+#define INFINIPATH_MDIO_RDDATAVALID 0x0000000080000000ULL
+
+/* kr_partitionkey bits */
+#define INFINIPATH_PKEY_SIZE 16
+#define INFINIPATH_PKEY_MASK 0xFFFF
+#define INFINIPATH_PKEY_DEFAULT_PKEY 0xFFFF
+
+/* kr_serdesconfig0 bits */
+#define INFINIPATH_SERDC0_RESET_MASK 0xfULL /* overal reset bits */
+#define INFINIPATH_SERDC0_RESET_PLL 0x10000000ULL /* pll reset */
+/* tx idle enables (per lane) */
+#define INFINIPATH_SERDC0_TXIDLE 0xF000ULL
+/* rx detect enables (per lane) */
+#define INFINIPATH_SERDC0_RXDETECT_EN 0xF0000ULL
+/* L1 Power down; use with RXDETECT, Otherwise not used on IB side */
+#define INFINIPATH_SERDC0_L1PWR_DN 0xF0ULL
+
+/* kr_xgxsconfig bits */
+#define INFINIPATH_XGXS_RESET 0x7ULL
+#define INFINIPATH_XGXS_MDIOADDR_MASK 0xfULL
+#define INFINIPATH_XGXS_MDIOADDR_SHIFT 4
+
+#define INFINIPATH_RT_ADDR_MASK 0xFFFFFFFFFFULL /* 40 bits valid */
+
+/* TID entries (memory), HT400-only */
+#define INFINIPATH_RT_VALID 0x8000000000000000ULL
+#define INFINIPATH_RT_ADDR_SHIFT 0
+#define INFINIPATH_RT_BUFSIZE_MASK 0x3FFF
+#define INFINIPATH_RT_BUFSIZE_SHIFT 48
+
+/*
+ * IPATH_PIO_MAXIBHDR is the max IB header size allowed for in our
+ * PIO send buffers. This is well beyond anything currently
+ * defined in the InfiniBand spec.
+ */
+#define IPATH_PIO_MAXIBHDR 128
+
+typedef u64 ipath_err_t;
+
+/* mask of defined bits for various registers */
+extern u64 infinipath_i_bitsextant;
+extern ipath_err_t infinipath_e_bitsextant, infinipath_hwe_bitsextant;
+
+/* masks that are different in various chips, or only exist in some chips */
+extern u32 infinipath_i_rcvavail_mask, infinipath_i_rcvurg_mask;
+
+/*
+ * register bits for selecting i2c direction and values, used for I2C serial
+ * flash
+ */
+extern u16 ipath_gpio_sda_num, ipath_gpio_scl_num;
+extern u64 ipath_gpio_sda, ipath_gpio_scl;
+
+/*
+ * These are the infinipath general register numbers (not offsets).
+ * The kernel registers are used directly, those beyond the kernel
+ * registers are calculated from one of the base registers. The use of
+ * an integer type doesn't allow type-checking as thorough as, say,
+ * an enum but allows for better hiding of chip differences.
+ */
+typedef const u16 ipath_kreg, /* infinipath general registers */
+ ipath_creg, /* infinipath counter registers */
+ ipath_sreg; /* kernel-only, infinipath send registers */
+
+/*
+ * These are the chip registers common to all infinipath chips, and
+ * used both by the kernel and the diagnostics or other user code.
+ * They are all implemented such that 64 bit accesses work.
+ * Some implement no more than 32 bits. Because 64 bit reads
+ * require 2 HT cmds on opteron, we access those with 32 bit
+ * reads for efficiency (they are written as 64 bits, since
+ * the extra 32 bits are nearly free on writes, and it slightly reduces
+ * complexity). The rest are all accessed as 64 bits.
+ */
+struct ipath_kregs {
+ /* These are the 32 bit group */
+ ipath_kreg kr_control;
+ ipath_kreg kr_counterregbase;
+ ipath_kreg kr_intmask;
+ ipath_kreg kr_intstatus;
+ ipath_kreg kr_pagealign;
+ ipath_kreg kr_portcnt;
+ ipath_kreg kr_rcvtidbase;
+ ipath_kreg kr_rcvtidcnt;
+ ipath_kreg kr_rcvegrbase;
+ ipath_kreg kr_rcvegrcnt;
+ ipath_kreg kr_scratch;
+ ipath_kreg kr_sendctrl;
+ ipath_kreg kr_sendpiobufbase;
+ ipath_kreg kr_sendpiobufcnt;
+ ipath_kreg kr_sendpiosize;
+ ipath_kreg kr_sendregbase;
+ ipath_kreg kr_userregbase;
+ /* These are the 64 bit group */
+ ipath_kreg kr_debugport;
+ ipath_kreg kr_debugportselect;
+ ipath_kreg kr_errorclear;
+ ipath_kreg kr_errormask;
+ ipath_kreg kr_errorstatus;
+ ipath_kreg kr_extctrl;
+ ipath_kreg kr_extstatus;
+ ipath_kreg kr_gpio_clear;
+ ipath_kreg kr_gpio_mask;
+ ipath_kreg kr_gpio_out;
+ ipath_kreg kr_gpio_status;
+ ipath_kreg kr_hwdiagctrl;
+ ipath_kreg kr_hwerrclear;
+ ipath_kreg kr_hwerrmask;
+ ipath_kreg kr_hwerrstatus;
+ ipath_kreg kr_ibcctrl;
+ ipath_kreg kr_ibcstatus;
+ ipath_kreg kr_intblocked;
+ ipath_kreg kr_intclear;
+ ipath_kreg kr_interruptconfig;
+ ipath_kreg kr_mdio;
+ ipath_kreg kr_partitionkey;
+ ipath_kreg kr_rcvbthqp;
+ ipath_kreg kr_rcvbufbase;
+ ipath_kreg kr_rcvbufsize;
+ ipath_kreg kr_rcvctrl;
+ ipath_kreg kr_rcvhdrcnt;
+ ipath_kreg kr_rcvhdrentsize;
+ ipath_kreg kr_rcvhdrsize;
+ ipath_kreg kr_rcvintmembase;
+ ipath_kreg kr_rcvintmemsize;
+ ipath_kreg kr_revision;
+ ipath_kreg kr_sendbuffererror;
+ ipath_kreg kr_sendpioavailaddr;
+ ipath_kreg kr_serdesconfig0;
+ ipath_kreg kr_serdesconfig1;
+ ipath_kreg kr_serdesstatus;
+ ipath_kreg kr_txintmembase;
+ ipath_kreg kr_txintmemsize;
+ ipath_kreg kr_xgxsconfig;
+ ipath_kreg kr_ibpllcfg;
+ /* use these two (and the following N ports) only with
+ * ipath_k*_kreg64_port(); not *kreg64() */
+ ipath_kreg kr_rcvhdraddr;
+ ipath_kreg kr_rcvhdrtailaddr;
+
+ /* remaining registers are not present on all types of infinipath
+ chips */
+ ipath_kreg kr_rcvpktledcnt;
+ ipath_kreg kr_pcierbuftestreg0;
+ ipath_kreg kr_pcierbuftestreg1;
+ ipath_kreg kr_pcieq0serdesconfig0;
+ ipath_kreg kr_pcieq0serdesconfig1;
+ ipath_kreg kr_pcieq0serdesstatus;
+ ipath_kreg kr_pcieq1serdesconfig0;
+ ipath_kreg kr_pcieq1serdesconfig1;
+ ipath_kreg kr_pcieq1serdesstatus;
+};
+
+struct ipath_cregs {
+ ipath_creg cr_badformatcnt;
+ ipath_creg cr_erricrccnt;
+ ipath_creg cr_errlinkcnt;
+ ipath_creg cr_errlpcrccnt;
+ ipath_creg cr_errpkey;
+ ipath_creg cr_errrcvflowctrlcnt;
+ ipath_creg cr_err_rlencnt;
+ ipath_creg cr_errslencnt;
+ ipath_creg cr_errtidfull;
+ ipath_creg cr_errtidvalid;
+ ipath_creg cr_errvcrccnt;
+ ipath_creg cr_ibstatuschange;
+ ipath_creg cr_intcnt;
+ ipath_creg cr_invalidrlencnt;
+ ipath_creg cr_invalidslencnt;
+ ipath_creg cr_lbflowstallcnt;
+ ipath_creg cr_iblinkdowncnt;
+ ipath_creg cr_iblinkerrrecovcnt;
+ ipath_creg cr_ibsymbolerrcnt;
+ ipath_creg cr_pktrcvcnt;
+ ipath_creg cr_pktrcvflowctrlcnt;
+ ipath_creg cr_pktsendcnt;
+ ipath_creg cr_pktsendflowcnt;
+ ipath_creg cr_portovflcnt;
+ ipath_creg cr_rcvebpcnt;
+ ipath_creg cr_rcvovflcnt;
+ ipath_creg cr_rxdroppktcnt;
+ ipath_creg cr_senddropped;
+ ipath_creg cr_sendstallcnt;
+ ipath_creg cr_sendunderruncnt;
+ ipath_creg cr_unsupvlcnt;
+ ipath_creg cr_wordrcvcnt;
+ ipath_creg cr_wordsendcnt;
+};
+
+#endif /* _IPATH_REGISTERS_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
new file mode 100644
index 00000000000..d38f4f3cfd1
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -0,0 +1,545 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ipath_verbs.h"
+
+/*
+ * Convert the AETH RNR timeout code into the number of milliseconds.
+ */
+const u32 ib_ipath_rnr_table[32] = {
+ 656, /* 0 */
+ 1, /* 1 */
+ 1, /* 2 */
+ 1, /* 3 */
+ 1, /* 4 */
+ 1, /* 5 */
+ 1, /* 6 */
+ 1, /* 7 */
+ 1, /* 8 */
+ 1, /* 9 */
+ 1, /* A */
+ 1, /* B */
+ 1, /* C */
+ 1, /* D */
+ 2, /* E */
+ 2, /* F */
+ 3, /* 10 */
+ 4, /* 11 */
+ 6, /* 12 */
+ 8, /* 13 */
+ 11, /* 14 */
+ 16, /* 15 */
+ 21, /* 16 */
+ 31, /* 17 */
+ 41, /* 18 */
+ 62, /* 19 */
+ 82, /* 1A */
+ 123, /* 1B */
+ 164, /* 1C */
+ 246, /* 1D */
+ 328, /* 1E */
+ 492 /* 1F */
+};
+
+/**
+ * ipath_insert_rnr_queue - put QP on the RNR timeout list for the device
+ * @qp: the QP
+ *
+ * XXX Use a simple list for now. We might need a priority
+ * queue if we have lots of QPs waiting for RNR timeouts
+ * but that should be rare.
+ */
+void ipath_insert_rnr_queue(struct ipath_qp *qp)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ if (list_empty(&dev->rnrwait))
+ list_add(&qp->timerwait, &dev->rnrwait);
+ else {
+ struct list_head *l = &dev->rnrwait;
+ struct ipath_qp *nqp = list_entry(l->next, struct ipath_qp,
+ timerwait);
+
+ while (qp->s_rnr_timeout >= nqp->s_rnr_timeout) {
+ qp->s_rnr_timeout -= nqp->s_rnr_timeout;
+ l = l->next;
+ if (l->next == &dev->rnrwait)
+ break;
+ nqp = list_entry(l->next, struct ipath_qp,
+ timerwait);
+ }
+ list_add(&qp->timerwait, l);
+ }
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+}
+
+/**
+ * ipath_get_rwqe - copy the next RWQE into the QP's RWQE
+ * @qp: the QP
+ * @wr_id_only: update wr_id only, not SGEs
+ *
+ * Return 0 if no RWQE is available, otherwise return 1.
+ *
+ * Called at interrupt level with the QP r_rq.lock held.
+ */
+int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only)
+{
+ struct ipath_rq *rq;
+ struct ipath_srq *srq;
+ struct ipath_rwqe *wqe;
+ int ret;
+
+ if (!qp->ibqp.srq) {
+ rq = &qp->r_rq;
+ if (unlikely(rq->tail == rq->head)) {
+ ret = 0;
+ goto bail;
+ }
+ wqe = get_rwqe_ptr(rq, rq->tail);
+ qp->r_wr_id = wqe->wr_id;
+ if (!wr_id_only) {
+ qp->r_sge.sge = wqe->sg_list[0];
+ qp->r_sge.sg_list = wqe->sg_list + 1;
+ qp->r_sge.num_sge = wqe->num_sge;
+ qp->r_len = wqe->length;
+ }
+ if (++rq->tail >= rq->size)
+ rq->tail = 0;
+ ret = 1;
+ goto bail;
+ }
+
+ srq = to_isrq(qp->ibqp.srq);
+ rq = &srq->rq;
+ spin_lock(&rq->lock);
+ if (unlikely(rq->tail == rq->head)) {
+ spin_unlock(&rq->lock);
+ ret = 0;
+ goto bail;
+ }
+ wqe = get_rwqe_ptr(rq, rq->tail);
+ qp->r_wr_id = wqe->wr_id;
+ if (!wr_id_only) {
+ qp->r_sge.sge = wqe->sg_list[0];
+ qp->r_sge.sg_list = wqe->sg_list + 1;
+ qp->r_sge.num_sge = wqe->num_sge;
+ qp->r_len = wqe->length;
+ }
+ if (++rq->tail >= rq->size)
+ rq->tail = 0;
+ if (srq->ibsrq.event_handler) {
+ struct ib_event ev;
+ u32 n;
+
+ if (rq->head < rq->tail)
+ n = rq->size + rq->head - rq->tail;
+ else
+ n = rq->head - rq->tail;
+ if (n < srq->limit) {
+ srq->limit = 0;
+ spin_unlock(&rq->lock);
+ ev.device = qp->ibqp.device;
+ ev.element.srq = qp->ibqp.srq;
+ ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
+ srq->ibsrq.event_handler(&ev,
+ srq->ibsrq.srq_context);
+ } else
+ spin_unlock(&rq->lock);
+ } else
+ spin_unlock(&rq->lock);
+ ret = 1;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_ruc_loopback - handle UC and RC lookback requests
+ * @sqp: the loopback QP
+ * @wc: the work completion entry
+ *
+ * This is called from ipath_do_uc_send() or ipath_do_rc_send() to
+ * forward a WQE addressed to the same HCA.
+ * Note that although we are single threaded due to the tasklet, we still
+ * have to protect against post_send(). We don't have to worry about
+ * receive interrupts since this is a connected protocol and all packets
+ * will pass through here.
+ */
+void ipath_ruc_loopback(struct ipath_qp *sqp, struct ib_wc *wc)
+{
+ struct ipath_ibdev *dev = to_idev(sqp->ibqp.device);
+ struct ipath_qp *qp;
+ struct ipath_swqe *wqe;
+ struct ipath_sge *sge;
+ unsigned long flags;
+ u64 sdata;
+
+ qp = ipath_lookup_qpn(&dev->qp_table, sqp->remote_qpn);
+ if (!qp) {
+ dev->n_pkt_drops++;
+ return;
+ }
+
+again:
+ spin_lock_irqsave(&sqp->s_lock, flags);
+
+ if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_SEND_OK)) {
+ spin_unlock_irqrestore(&sqp->s_lock, flags);
+ goto done;
+ }
+
+ /* Get the next send request. */
+ if (sqp->s_last == sqp->s_head) {
+ /* Send work queue is empty. */
+ spin_unlock_irqrestore(&sqp->s_lock, flags);
+ goto done;
+ }
+
+ /*
+ * We can rely on the entry not changing without the s_lock
+ * being held until we update s_last.
+ */
+ wqe = get_swqe_ptr(sqp, sqp->s_last);
+ spin_unlock_irqrestore(&sqp->s_lock, flags);
+
+ wc->wc_flags = 0;
+ wc->imm_data = 0;
+
+ sqp->s_sge.sge = wqe->sg_list[0];
+ sqp->s_sge.sg_list = wqe->sg_list + 1;
+ sqp->s_sge.num_sge = wqe->wr.num_sge;
+ sqp->s_len = wqe->length;
+ switch (wqe->wr.opcode) {
+ case IB_WR_SEND_WITH_IMM:
+ wc->wc_flags = IB_WC_WITH_IMM;
+ wc->imm_data = wqe->wr.imm_data;
+ /* FALLTHROUGH */
+ case IB_WR_SEND:
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+ if (!ipath_get_rwqe(qp, 0)) {
+ rnr_nak:
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ /* Handle RNR NAK */
+ if (qp->ibqp.qp_type == IB_QPT_UC)
+ goto send_comp;
+ if (sqp->s_rnr_retry == 0) {
+ wc->status = IB_WC_RNR_RETRY_EXC_ERR;
+ goto err;
+ }
+ if (sqp->s_rnr_retry_cnt < 7)
+ sqp->s_rnr_retry--;
+ dev->n_rnr_naks++;
+ sqp->s_rnr_timeout =
+ ib_ipath_rnr_table[sqp->s_min_rnr_timer];
+ ipath_insert_rnr_queue(sqp);
+ goto done;
+ }
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ break;
+
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ wc->wc_flags = IB_WC_WITH_IMM;
+ wc->imm_data = wqe->wr.imm_data;
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+ if (!ipath_get_rwqe(qp, 1))
+ goto rnr_nak;
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ /* FALLTHROUGH */
+ case IB_WR_RDMA_WRITE:
+ if (wqe->length == 0)
+ break;
+ if (unlikely(!ipath_rkey_ok(dev, &qp->r_sge, wqe->length,
+ wqe->wr.wr.rdma.remote_addr,
+ wqe->wr.wr.rdma.rkey,
+ IB_ACCESS_REMOTE_WRITE))) {
+ acc_err:
+ wc->status = IB_WC_REM_ACCESS_ERR;
+ err:
+ wc->wr_id = wqe->wr.wr_id;
+ wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ wc->vendor_err = 0;
+ wc->byte_len = 0;
+ wc->qp_num = sqp->ibqp.qp_num;
+ wc->src_qp = sqp->remote_qpn;
+ wc->pkey_index = 0;
+ wc->slid = sqp->remote_ah_attr.dlid;
+ wc->sl = sqp->remote_ah_attr.sl;
+ wc->dlid_path_bits = 0;
+ wc->port_num = 0;
+ ipath_sqerror_qp(sqp, wc);
+ goto done;
+ }
+ break;
+
+ case IB_WR_RDMA_READ:
+ if (unlikely(!ipath_rkey_ok(dev, &sqp->s_sge, wqe->length,
+ wqe->wr.wr.rdma.remote_addr,
+ wqe->wr.wr.rdma.rkey,
+ IB_ACCESS_REMOTE_READ)))
+ goto acc_err;
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_READ)))
+ goto acc_err;
+ qp->r_sge.sge = wqe->sg_list[0];
+ qp->r_sge.sg_list = wqe->sg_list + 1;
+ qp->r_sge.num_sge = wqe->wr.num_sge;
+ break;
+
+ case IB_WR_ATOMIC_CMP_AND_SWP:
+ case IB_WR_ATOMIC_FETCH_AND_ADD:
+ if (unlikely(!ipath_rkey_ok(dev, &qp->r_sge, sizeof(u64),
+ wqe->wr.wr.rdma.remote_addr,
+ wqe->wr.wr.rdma.rkey,
+ IB_ACCESS_REMOTE_ATOMIC)))
+ goto acc_err;
+ /* Perform atomic OP and save result. */
+ sdata = wqe->wr.wr.atomic.swap;
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ qp->r_atomic_data = *(u64 *) qp->r_sge.sge.vaddr;
+ if (wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)
+ *(u64 *) qp->r_sge.sge.vaddr =
+ qp->r_atomic_data + sdata;
+ else if (qp->r_atomic_data == wqe->wr.wr.atomic.compare_add)
+ *(u64 *) qp->r_sge.sge.vaddr = sdata;
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+ *(u64 *) sqp->s_sge.sge.vaddr = qp->r_atomic_data;
+ goto send_comp;
+
+ default:
+ goto done;
+ }
+
+ sge = &sqp->s_sge.sge;
+ while (sqp->s_len) {
+ u32 len = sqp->s_len;
+
+ if (len > sge->length)
+ len = sge->length;
+ BUG_ON(len == 0);
+ ipath_copy_sge(&qp->r_sge, sge->vaddr, len);
+ sge->vaddr += len;
+ sge->length -= len;
+ sge->sge_length -= len;
+ if (sge->sge_length == 0) {
+ if (--sqp->s_sge.num_sge)
+ *sge = *sqp->s_sge.sg_list++;
+ } else if (sge->length == 0 && sge->mr != NULL) {
+ if (++sge->n >= IPATH_SEGSZ) {
+ if (++sge->m >= sge->mr->mapsz)
+ break;
+ sge->n = 0;
+ }
+ sge->vaddr =
+ sge->mr->map[sge->m]->segs[sge->n].vaddr;
+ sge->length =
+ sge->mr->map[sge->m]->segs[sge->n].length;
+ }
+ sqp->s_len -= len;
+ }
+
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE ||
+ wqe->wr.opcode == IB_WR_RDMA_READ)
+ goto send_comp;
+
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE_WITH_IMM)
+ wc->opcode = IB_WC_RECV_RDMA_WITH_IMM;
+ else
+ wc->opcode = IB_WC_RECV;
+ wc->wr_id = qp->r_wr_id;
+ wc->status = IB_WC_SUCCESS;
+ wc->vendor_err = 0;
+ wc->byte_len = wqe->length;
+ wc->qp_num = qp->ibqp.qp_num;
+ wc->src_qp = qp->remote_qpn;
+ /* XXX do we know which pkey matched? Only needed for GSI. */
+ wc->pkey_index = 0;
+ wc->slid = qp->remote_ah_attr.dlid;
+ wc->sl = qp->remote_ah_attr.sl;
+ wc->dlid_path_bits = 0;
+ /* Signal completion event if the solicited bit is set. */
+ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), wc,
+ wqe->wr.send_flags & IB_SEND_SOLICITED);
+
+send_comp:
+ sqp->s_rnr_retry = sqp->s_rnr_retry_cnt;
+
+ if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &sqp->s_flags) ||
+ (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
+ wc->wr_id = wqe->wr.wr_id;
+ wc->status = IB_WC_SUCCESS;
+ wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ wc->vendor_err = 0;
+ wc->byte_len = wqe->length;
+ wc->qp_num = sqp->ibqp.qp_num;
+ wc->src_qp = 0;
+ wc->pkey_index = 0;
+ wc->slid = 0;
+ wc->sl = 0;
+ wc->dlid_path_bits = 0;
+ wc->port_num = 0;
+ ipath_cq_enter(to_icq(sqp->ibqp.send_cq), wc, 0);
+ }
+
+ /* Update s_last now that we are finished with the SWQE */
+ spin_lock_irqsave(&sqp->s_lock, flags);
+ if (++sqp->s_last >= sqp->s_size)
+ sqp->s_last = 0;
+ spin_unlock_irqrestore(&sqp->s_lock, flags);
+ goto again;
+
+done:
+ if (atomic_dec_and_test(&qp->refcount))
+ wake_up(&qp->wait);
+}
+
+/**
+ * ipath_no_bufs_available - tell the layer driver we need buffers
+ * @qp: the QP that caused the problem
+ * @dev: the device we ran out of buffers on
+ *
+ * Called when we run out of PIO buffers.
+ */
+void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ if (list_empty(&qp->piowait))
+ list_add_tail(&qp->piowait, &dev->piowait);
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+ /*
+ * Note that as soon as ipath_layer_want_buffer() is called and
+ * possibly before it returns, ipath_ib_piobufavail()
+ * could be called. If we are still in the tasklet function,
+ * tasklet_hi_schedule() will not call us until the next time
+ * tasklet_hi_schedule() is called.
+ * We clear the tasklet flag now since we are committing to return
+ * from the tasklet function.
+ */
+ clear_bit(IPATH_S_BUSY, &qp->s_flags);
+ tasklet_unlock(&qp->s_task);
+ ipath_layer_want_buffer(dev->dd);
+ dev->n_piowait++;
+}
+
+/**
+ * ipath_post_rc_send - post RC and UC sends
+ * @qp: the QP to post on
+ * @wr: the work request to send
+ */
+int ipath_post_rc_send(struct ipath_qp *qp, struct ib_send_wr *wr)
+{
+ struct ipath_swqe *wqe;
+ unsigned long flags;
+ u32 next;
+ int i, j;
+ int acc;
+ int ret;
+
+ /*
+ * Don't allow RDMA reads or atomic operations on UC or
+ * undefined operations.
+ * Make sure buffer is large enough to hold the result for atomics.
+ */
+ if (qp->ibqp.qp_type == IB_QPT_UC) {
+ if ((unsigned) wr->opcode >= IB_WR_RDMA_READ) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ } else if ((unsigned) wr->opcode > IB_WR_ATOMIC_FETCH_AND_ADD) {
+ ret = -EINVAL;
+ goto bail;
+ } else if (wr->opcode >= IB_WR_ATOMIC_CMP_AND_SWP &&
+ (wr->num_sge == 0 ||
+ wr->sg_list[0].length < sizeof(u64) ||
+ wr->sg_list[0].addr & (sizeof(u64) - 1))) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ /* IB spec says that num_sge == 0 is OK. */
+ if (wr->num_sge > qp->s_max_sge) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ spin_lock_irqsave(&qp->s_lock, flags);
+ next = qp->s_head + 1;
+ if (next >= qp->s_size)
+ next = 0;
+ if (next == qp->s_last) {
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ wqe = get_swqe_ptr(qp, qp->s_head);
+ wqe->wr = *wr;
+ wqe->ssn = qp->s_ssn++;
+ wqe->sg_list[0].mr = NULL;
+ wqe->sg_list[0].vaddr = NULL;
+ wqe->sg_list[0].length = 0;
+ wqe->sg_list[0].sge_length = 0;
+ wqe->length = 0;
+ acc = wr->opcode >= IB_WR_RDMA_READ ? IB_ACCESS_LOCAL_WRITE : 0;
+ for (i = 0, j = 0; i < wr->num_sge; i++) {
+ if (to_ipd(qp->ibqp.pd)->user && wr->sg_list[i].lkey == 0) {
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+ ret = -EINVAL;
+ goto bail;
+ }
+ if (wr->sg_list[i].length == 0)
+ continue;
+ if (!ipath_lkey_ok(&to_idev(qp->ibqp.device)->lk_table,
+ &wqe->sg_list[j], &wr->sg_list[i],
+ acc)) {
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+ ret = -EINVAL;
+ goto bail;
+ }
+ wqe->length += wr->sg_list[i].length;
+ j++;
+ }
+ wqe->wr.num_sge = j;
+ qp->s_head = next;
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+
+ if (qp->ibqp.qp_type == IB_QPT_UC)
+ ipath_do_uc_send((unsigned long) qp);
+ else
+ ipath_do_rc_send((unsigned long) qp);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
new file mode 100644
index 00000000000..01c4c6c5611
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_srq.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/err.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_verbs.h"
+
+/**
+ * ipath_post_srq_receive - post a receive on a shared receive queue
+ * @ibsrq: the SRQ to post the receive on
+ * @wr: the list of work requests to post
+ * @bad_wr: the first WR to cause a problem is put here
+ *
+ * This may be called from interrupt context.
+ */
+int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ struct ipath_srq *srq = to_isrq(ibsrq);
+ struct ipath_ibdev *dev = to_idev(ibsrq->device);
+ unsigned long flags;
+ int ret;
+
+ for (; wr; wr = wr->next) {
+ struct ipath_rwqe *wqe;
+ u32 next;
+ int i, j;
+
+ if (wr->num_sge > srq->rq.max_sge) {
+ *bad_wr = wr;
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ spin_lock_irqsave(&srq->rq.lock, flags);
+ next = srq->rq.head + 1;
+ if (next >= srq->rq.size)
+ next = 0;
+ if (next == srq->rq.tail) {
+ spin_unlock_irqrestore(&srq->rq.lock, flags);
+ *bad_wr = wr;
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ wqe = get_rwqe_ptr(&srq->rq, srq->rq.head);
+ wqe->wr_id = wr->wr_id;
+ wqe->sg_list[0].mr = NULL;
+ wqe->sg_list[0].vaddr = NULL;
+ wqe->sg_list[0].length = 0;
+ wqe->sg_list[0].sge_length = 0;
+ wqe->length = 0;
+ for (i = 0, j = 0; i < wr->num_sge; i++) {
+ /* Check LKEY */
+ if (to_ipd(srq->ibsrq.pd)->user &&
+ wr->sg_list[i].lkey == 0) {
+ spin_unlock_irqrestore(&srq->rq.lock,
+ flags);
+ *bad_wr = wr;
+ ret = -EINVAL;
+ goto bail;
+ }
+ if (wr->sg_list[i].length == 0)
+ continue;
+ if (!ipath_lkey_ok(&dev->lk_table,
+ &wqe->sg_list[j],
+ &wr->sg_list[i],
+ IB_ACCESS_LOCAL_WRITE)) {
+ spin_unlock_irqrestore(&srq->rq.lock,
+ flags);
+ *bad_wr = wr;
+ ret = -EINVAL;
+ goto bail;
+ }
+ wqe->length += wr->sg_list[i].length;
+ j++;
+ }
+ wqe->num_sge = j;
+ srq->rq.head = next;
+ spin_unlock_irqrestore(&srq->rq.lock, flags);
+ }
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_create_srq - create a shared receive queue
+ * @ibpd: the protection domain of the SRQ to create
+ * @attr: the attributes of the SRQ
+ * @udata: not used by the InfiniPath verbs driver
+ */
+struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
+ struct ib_srq_init_attr *srq_init_attr,
+ struct ib_udata *udata)
+{
+ struct ipath_srq *srq;
+ u32 sz;
+ struct ib_srq *ret;
+
+ if (srq_init_attr->attr.max_sge < 1) {
+ ret = ERR_PTR(-EINVAL);
+ goto bail;
+ }
+
+ srq = kmalloc(sizeof(*srq), GFP_KERNEL);
+ if (!srq) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /*
+ * Need to use vmalloc() if we want to support large #s of entries.
+ */
+ srq->rq.size = srq_init_attr->attr.max_wr + 1;
+ sz = sizeof(struct ipath_sge) * srq_init_attr->attr.max_sge +
+ sizeof(struct ipath_rwqe);
+ srq->rq.wq = vmalloc(srq->rq.size * sz);
+ if (!srq->rq.wq) {
+ kfree(srq);
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /*
+ * ib_create_srq() will initialize srq->ibsrq.
+ */
+ spin_lock_init(&srq->rq.lock);
+ srq->rq.head = 0;
+ srq->rq.tail = 0;
+ srq->rq.max_sge = srq_init_attr->attr.max_sge;
+ srq->limit = srq_init_attr->attr.srq_limit;
+
+ ret = &srq->ibsrq;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_modify_srq - modify a shared receive queue
+ * @ibsrq: the SRQ to modify
+ * @attr: the new attributes of the SRQ
+ * @attr_mask: indicates which attributes to modify
+ */
+int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ enum ib_srq_attr_mask attr_mask)
+{
+ struct ipath_srq *srq = to_isrq(ibsrq);
+ unsigned long flags;
+ int ret;
+
+ if (attr_mask & IB_SRQ_LIMIT) {
+ spin_lock_irqsave(&srq->rq.lock, flags);
+ srq->limit = attr->srq_limit;
+ spin_unlock_irqrestore(&srq->rq.lock, flags);
+ }
+ if (attr_mask & IB_SRQ_MAX_WR) {
+ u32 size = attr->max_wr + 1;
+ struct ipath_rwqe *wq, *p;
+ u32 n;
+ u32 sz;
+
+ if (attr->max_sge < srq->rq.max_sge) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ sz = sizeof(struct ipath_rwqe) +
+ attr->max_sge * sizeof(struct ipath_sge);
+ wq = vmalloc(size * sz);
+ if (!wq) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ spin_lock_irqsave(&srq->rq.lock, flags);
+ if (srq->rq.head < srq->rq.tail)
+ n = srq->rq.size + srq->rq.head - srq->rq.tail;
+ else
+ n = srq->rq.head - srq->rq.tail;
+ if (size <= n || size <= srq->limit) {
+ spin_unlock_irqrestore(&srq->rq.lock, flags);
+ vfree(wq);
+ ret = -EINVAL;
+ goto bail;
+ }
+ n = 0;
+ p = wq;
+ while (srq->rq.tail != srq->rq.head) {
+ struct ipath_rwqe *wqe;
+ int i;
+
+ wqe = get_rwqe_ptr(&srq->rq, srq->rq.tail);
+ p->wr_id = wqe->wr_id;
+ p->length = wqe->length;
+ p->num_sge = wqe->num_sge;
+ for (i = 0; i < wqe->num_sge; i++)
+ p->sg_list[i] = wqe->sg_list[i];
+ n++;
+ p = (struct ipath_rwqe *)((char *) p + sz);
+ if (++srq->rq.tail >= srq->rq.size)
+ srq->rq.tail = 0;
+ }
+ vfree(srq->rq.wq);
+ srq->rq.wq = wq;
+ srq->rq.size = size;
+ srq->rq.head = n;
+ srq->rq.tail = 0;
+ srq->rq.max_sge = attr->max_sge;
+ spin_unlock_irqrestore(&srq->rq.lock, flags);
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+int ipath_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr)
+{
+ struct ipath_srq *srq = to_isrq(ibsrq);
+
+ attr->max_wr = srq->rq.size - 1;
+ attr->max_sge = srq->rq.max_sge;
+ attr->srq_limit = srq->limit;
+ return 0;
+}
+
+/**
+ * ipath_destroy_srq - destroy a shared receive queue
+ * @ibsrq: the SRQ to destroy
+ */
+int ipath_destroy_srq(struct ib_srq *ibsrq)
+{
+ struct ipath_srq *srq = to_isrq(ibsrq);
+
+ vfree(srq->rq.wq);
+ kfree(srq);
+
+ return 0;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
new file mode 100644
index 00000000000..fe209137ee7
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_stats.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+
+#include "ipath_kernel.h"
+
+struct infinipath_stats ipath_stats;
+
+/**
+ * ipath_snap_cntr - snapshot a chip counter
+ * @dd: the infinipath device
+ * @creg: the counter to snapshot
+ *
+ * called from add_timer and user counter read calls, to deal with
+ * counters that wrap in "human time". The words sent and received, and
+ * the packets sent and received are all that we worry about. For now,
+ * at least, we don't worry about error counters, because if they wrap
+ * that quickly, we probably don't care. We may eventually just make this
+ * handle all the counters. word counters can wrap in about 20 seconds
+ * of full bandwidth traffic, packet counters in a few hours.
+ */
+
+u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
+{
+ u32 val, reg64 = 0;
+ u64 val64;
+ unsigned long t0, t1;
+ u64 ret;
+
+ t0 = jiffies;
+ /* If fast increment counters are only 32 bits, snapshot them,
+ * and maintain them as 64bit values in the driver */
+ if (!(dd->ipath_flags & IPATH_32BITCOUNTERS) &&
+ (creg == dd->ipath_cregs->cr_wordsendcnt ||
+ creg == dd->ipath_cregs->cr_wordrcvcnt ||
+ creg == dd->ipath_cregs->cr_pktsendcnt ||
+ creg == dd->ipath_cregs->cr_pktrcvcnt)) {
+ val64 = ipath_read_creg(dd, creg);
+ val = val64 == ~0ULL ? ~0U : 0;
+ reg64 = 1;
+ } else /* val64 just to keep gcc quiet... */
+ val64 = val = ipath_read_creg32(dd, creg);
+ /*
+ * See if a second has passed. This is just a way to detect things
+ * that are quite broken. Normally this should take just a few
+ * cycles (the check is for long enough that we don't care if we get
+ * pre-empted.) An Opteron HT O read timeout is 4 seconds with
+ * normal NB values
+ */
+ t1 = jiffies;
+ if (time_before(t0 + HZ, t1) && val == -1) {
+ ipath_dev_err(dd, "Error! Read counter 0x%x timed out\n",
+ creg);
+ ret = 0ULL;
+ goto bail;
+ }
+ if (reg64) {
+ ret = val64;
+ goto bail;
+ }
+
+ if (creg == dd->ipath_cregs->cr_wordsendcnt) {
+ if (val != dd->ipath_lastsword) {
+ dd->ipath_sword += val - dd->ipath_lastsword;
+ dd->ipath_lastsword = val;
+ }
+ val64 = dd->ipath_sword;
+ } else if (creg == dd->ipath_cregs->cr_wordrcvcnt) {
+ if (val != dd->ipath_lastrword) {
+ dd->ipath_rword += val - dd->ipath_lastrword;
+ dd->ipath_lastrword = val;
+ }
+ val64 = dd->ipath_rword;
+ } else if (creg == dd->ipath_cregs->cr_pktsendcnt) {
+ if (val != dd->ipath_lastspkts) {
+ dd->ipath_spkts += val - dd->ipath_lastspkts;
+ dd->ipath_lastspkts = val;
+ }
+ val64 = dd->ipath_spkts;
+ } else if (creg == dd->ipath_cregs->cr_pktrcvcnt) {
+ if (val != dd->ipath_lastrpkts) {
+ dd->ipath_rpkts += val - dd->ipath_lastrpkts;
+ dd->ipath_lastrpkts = val;
+ }
+ val64 = dd->ipath_rpkts;
+ } else
+ val64 = (u64) val;
+
+ ret = val64;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_qcheck - print delta of egrfull/hdrqfull errors for kernel ports
+ * @dd: the infinipath device
+ *
+ * print the delta of egrfull/hdrqfull errors for kernel ports no more than
+ * every 5 seconds. User processes are printed at close, but kernel doesn't
+ * close, so... Separate routine so may call from other places someday, and
+ * so function name when printed by _IPATH_INFO is meaningfull
+ */
+static void ipath_qcheck(struct ipath_devdata *dd)
+{
+ static u64 last_tot_hdrqfull;
+ size_t blen = 0;
+ char buf[128];
+
+ *buf = 0;
+ if (dd->ipath_pd[0]->port_hdrqfull != dd->ipath_p0_hdrqfull) {
+ blen = snprintf(buf, sizeof buf, "port 0 hdrqfull %u",
+ dd->ipath_pd[0]->port_hdrqfull -
+ dd->ipath_p0_hdrqfull);
+ dd->ipath_p0_hdrqfull = dd->ipath_pd[0]->port_hdrqfull;
+ }
+ if (ipath_stats.sps_etidfull != dd->ipath_last_tidfull) {
+ blen += snprintf(buf + blen, sizeof buf - blen,
+ "%srcvegrfull %llu",
+ blen ? ", " : "",
+ (unsigned long long)
+ (ipath_stats.sps_etidfull -
+ dd->ipath_last_tidfull));
+ dd->ipath_last_tidfull = ipath_stats.sps_etidfull;
+ }
+
+ /*
+ * this is actually the number of hdrq full interrupts, not actual
+ * events, but at the moment that's mostly what I'm interested in.
+ * Actual count, etc. is in the counters, if needed. For production
+ * users this won't ordinarily be printed.
+ */
+
+ if ((ipath_debug & (__IPATH_PKTDBG | __IPATH_DBG)) &&
+ ipath_stats.sps_hdrqfull != last_tot_hdrqfull) {
+ blen += snprintf(buf + blen, sizeof buf - blen,
+ "%shdrqfull %llu (all ports)",
+ blen ? ", " : "",
+ (unsigned long long)
+ (ipath_stats.sps_hdrqfull -
+ last_tot_hdrqfull));
+ last_tot_hdrqfull = ipath_stats.sps_hdrqfull;
+ }
+ if (blen)
+ ipath_dbg("%s\n", buf);
+
+ if (dd->ipath_port0head != (u32)
+ le64_to_cpu(*dd->ipath_hdrqtailptr)) {
+ if (dd->ipath_lastport0rcv_cnt ==
+ ipath_stats.sps_port0pkts) {
+ ipath_cdbg(PKT, "missing rcv interrupts? "
+ "port0 hd=%llx tl=%x; port0pkts %llx\n",
+ (unsigned long long)
+ le64_to_cpu(*dd->ipath_hdrqtailptr),
+ dd->ipath_port0head,
+ (unsigned long long)
+ ipath_stats.sps_port0pkts);
+ ipath_kreceive(dd);
+ }
+ dd->ipath_lastport0rcv_cnt = ipath_stats.sps_port0pkts;
+ }
+}
+
+/**
+ * ipath_get_faststats - get word counters from chip before they overflow
+ * @opaque - contains a pointer to the infinipath device ipath_devdata
+ *
+ * called from add_timer
+ */
+void ipath_get_faststats(unsigned long opaque)
+{
+ struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
+ u32 val;
+ static unsigned cnt;
+
+ /*
+ * don't access the chip while running diags, or memory diags can
+ * fail
+ */
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT) ||
+ ipath_diag_inuse)
+ /* but re-arm the timer, for diags case; won't hurt other */
+ goto done;
+
+ if (dd->ipath_flags & IPATH_32BITCOUNTERS) {
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
+ }
+
+ ipath_qcheck(dd);
+
+ /*
+ * deal with repeat error suppression. Doesn't really matter if
+ * last error was almost a full interval ago, or just a few usecs
+ * ago; still won't get more than 2 per interval. We may want
+ * longer intervals for this eventually, could do with mod, counter
+ * or separate timer. Also see code in ipath_handle_errors() and
+ * ipath_handle_hwerrors().
+ */
+
+ if (dd->ipath_lasterror)
+ dd->ipath_lasterror = 0;
+ if (dd->ipath_lasthwerror)
+ dd->ipath_lasthwerror = 0;
+ if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs)
+ && time_after(jiffies, dd->ipath_unmasktime)) {
+ char ebuf[256];
+ ipath_decode_err(ebuf, sizeof ebuf,
+ (dd->ipath_maskederrs & ~dd->
+ ipath_ignorederrs));
+ if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) &
+ ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL))
+ ipath_dev_err(dd, "Re-enabling masked errors "
+ "(%s)\n", ebuf);
+ else {
+ /*
+ * rcvegrfull and rcvhdrqfull are "normal", for some
+ * types of processes (mostly benchmarks) that send
+ * huge numbers of messages, while not processing
+ * them. So only complain about these at debug
+ * level.
+ */
+ ipath_dbg("Disabling frequent queue full errors "
+ "(%s)\n", ebuf);
+ }
+ dd->ipath_maskederrs = dd->ipath_ignorederrs;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+ ~dd->ipath_maskederrs);
+ }
+
+ /* limit qfull messages to ~one per minute per port */
+ if ((++cnt & 0x10)) {
+ for (val = dd->ipath_cfgports - 1; ((int)val) >= 0;
+ val--) {
+ if (dd->ipath_lastegrheads[val] != -1)
+ dd->ipath_lastegrheads[val] = -1;
+ if (dd->ipath_lastrcvhdrqtails[val] != -1)
+ dd->ipath_lastrcvhdrqtails[val] = -1;
+ }
+ }
+
+ if (dd->ipath_nosma_bufs) {
+ dd->ipath_nosma_secs += 5;
+ if (dd->ipath_nosma_secs >= 30) {
+ ipath_cdbg(SMA, "No SMA bufs avail %u seconds; "
+ "cancelling pending sends\n",
+ dd->ipath_nosma_secs);
+ /*
+ * issue an abort as well, in case we have a packet
+ * stuck in launch fifo. This could corrupt an
+ * outgoing user packet in the worst case,
+ * but this is a pretty catastrophic, anyway.
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ INFINIPATH_S_ABORT);
+ ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf,
+ dd->ipath_piobcnt2k +
+ dd->ipath_piobcnt4k -
+ dd->ipath_lastport_piobuf);
+ /* start again, if necessary */
+ dd->ipath_nosma_secs = 0;
+ } else
+ ipath_cdbg(SMA, "No SMA bufs avail %u tries, "
+ "after %u seconds\n",
+ dd->ipath_nosma_bufs,
+ dd->ipath_nosma_secs);
+ }
+
+done:
+ mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5);
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
new file mode 100644
index 00000000000..f323791cc49
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
@@ -0,0 +1,790 @@
+/*
+ * Copyright (c) 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/ctype.h>
+#include <linux/pci.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+/**
+ * ipath_parse_ushort - parse an unsigned short value in an arbitrary base
+ * @str: the string containing the number
+ * @valp: where to put the result
+ *
+ * returns the number of bytes consumed, or negative value on error
+ */
+int ipath_parse_ushort(const char *str, unsigned short *valp)
+{
+ unsigned long val;
+ char *end;
+ int ret;
+
+ if (!isdigit(str[0])) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ val = simple_strtoul(str, &end, 0);
+
+ if (val > 0xffff) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ *valp = val;
+
+ ret = end + 1 - str;
+ if (ret == 0)
+ ret = -EINVAL;
+
+bail:
+ return ret;
+}
+
+static ssize_t show_version(struct device_driver *dev, char *buf)
+{
+ /* The string printed here is already newline-terminated. */
+ return scnprintf(buf, PAGE_SIZE, "%s", ipath_core_version);
+}
+
+static ssize_t show_num_units(struct device_driver *dev, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ ipath_count_units(NULL, NULL, NULL));
+}
+
+#define DRIVER_STAT(name, attr) \
+ static ssize_t show_stat_##name(struct device_driver *dev, \
+ char *buf) \
+ { \
+ return scnprintf( \
+ buf, PAGE_SIZE, "%llu\n", \
+ (unsigned long long) ipath_stats.sps_ ##attr); \
+ } \
+ static DRIVER_ATTR(name, S_IRUGO, show_stat_##name, NULL)
+
+DRIVER_STAT(intrs, ints);
+DRIVER_STAT(err_intrs, errints);
+DRIVER_STAT(errs, errs);
+DRIVER_STAT(pkt_errs, pkterrs);
+DRIVER_STAT(crc_errs, crcerrs);
+DRIVER_STAT(hw_errs, hwerrs);
+DRIVER_STAT(ib_link, iblink);
+DRIVER_STAT(port0_pkts, port0pkts);
+DRIVER_STAT(ether_spkts, ether_spkts);
+DRIVER_STAT(ether_rpkts, ether_rpkts);
+DRIVER_STAT(sma_spkts, sma_spkts);
+DRIVER_STAT(sma_rpkts, sma_rpkts);
+DRIVER_STAT(hdrq_full, hdrqfull);
+DRIVER_STAT(etid_full, etidfull);
+DRIVER_STAT(no_piobufs, nopiobufs);
+DRIVER_STAT(ports, ports);
+DRIVER_STAT(pkey0, pkeys[0]);
+DRIVER_STAT(pkey1, pkeys[1]);
+DRIVER_STAT(pkey2, pkeys[2]);
+DRIVER_STAT(pkey3, pkeys[3]);
+/* XXX fix the following when dynamic table of devices used */
+DRIVER_STAT(lid0, lid[0]);
+DRIVER_STAT(lid1, lid[1]);
+DRIVER_STAT(lid2, lid[2]);
+DRIVER_STAT(lid3, lid[3]);
+
+DRIVER_STAT(nports, nports);
+DRIVER_STAT(null_intr, nullintr);
+DRIVER_STAT(max_pkts_call, maxpkts_call);
+DRIVER_STAT(avg_pkts_call, avgpkts_call);
+DRIVER_STAT(page_locks, pagelocks);
+DRIVER_STAT(page_unlocks, pageunlocks);
+DRIVER_STAT(krdrops, krdrops);
+/* XXX fix the following when dynamic table of devices used */
+DRIVER_STAT(mlid0, mlid[0]);
+DRIVER_STAT(mlid1, mlid[1]);
+DRIVER_STAT(mlid2, mlid[2]);
+DRIVER_STAT(mlid3, mlid[3]);
+
+static struct attribute *driver_stat_attributes[] = {
+ &driver_attr_intrs.attr,
+ &driver_attr_err_intrs.attr,
+ &driver_attr_errs.attr,
+ &driver_attr_pkt_errs.attr,
+ &driver_attr_crc_errs.attr,
+ &driver_attr_hw_errs.attr,
+ &driver_attr_ib_link.attr,
+ &driver_attr_port0_pkts.attr,
+ &driver_attr_ether_spkts.attr,
+ &driver_attr_ether_rpkts.attr,
+ &driver_attr_sma_spkts.attr,
+ &driver_attr_sma_rpkts.attr,
+ &driver_attr_hdrq_full.attr,
+ &driver_attr_etid_full.attr,
+ &driver_attr_no_piobufs.attr,
+ &driver_attr_ports.attr,
+ &driver_attr_pkey0.attr,
+ &driver_attr_pkey1.attr,
+ &driver_attr_pkey2.attr,
+ &driver_attr_pkey3.attr,
+ &driver_attr_lid0.attr,
+ &driver_attr_lid1.attr,
+ &driver_attr_lid2.attr,
+ &driver_attr_lid3.attr,
+ &driver_attr_nports.attr,
+ &driver_attr_null_intr.attr,
+ &driver_attr_max_pkts_call.attr,
+ &driver_attr_avg_pkts_call.attr,
+ &driver_attr_page_locks.attr,
+ &driver_attr_page_unlocks.attr,
+ &driver_attr_krdrops.attr,
+ &driver_attr_mlid0.attr,
+ &driver_attr_mlid1.attr,
+ &driver_attr_mlid2.attr,
+ &driver_attr_mlid3.attr,
+ NULL
+};
+
+static struct attribute_group driver_stat_attr_group = {
+ .name = "stats",
+ .attrs = driver_stat_attributes
+};
+
+static ssize_t show_status(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ ssize_t ret;
+
+ if (!dd->ipath_statusp) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n",
+ (unsigned long long) *(dd->ipath_statusp));
+
+bail:
+ return ret;
+}
+
+static const char *ipath_status_str[] = {
+ "Initted",
+ "Disabled",
+ "Admin_Disabled",
+ "OIB_SMA",
+ "SMA",
+ "Present",
+ "IB_link_up",
+ "IB_configured",
+ "NoIBcable",
+ "Fatal_Hardware_Error",
+ NULL,
+};
+
+static ssize_t show_status_str(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ int i, any;
+ u64 s;
+ ssize_t ret;
+
+ if (!dd->ipath_statusp) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ s = *(dd->ipath_statusp);
+ *buf = '\0';
+ for (any = i = 0; s && ipath_status_str[i]; i++) {
+ if (s & 1) {
+ if (any && strlcat(buf, " ", PAGE_SIZE) >=
+ PAGE_SIZE)
+ /* overflow */
+ break;
+ if (strlcat(buf, ipath_status_str[i],
+ PAGE_SIZE) >= PAGE_SIZE)
+ break;
+ any = 1;
+ }
+ s >>= 1;
+ }
+ if (any)
+ strlcat(buf, "\n", PAGE_SIZE);
+
+ ret = strlen(buf);
+
+bail:
+ return ret;
+}
+
+static ssize_t show_boardversion(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ /* The string printed here is already newline-terminated. */
+ return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion);
+}
+
+static ssize_t show_lid(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_lid);
+}
+
+static ssize_t store_lid(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ u16 lid;
+ int ret;
+
+ ret = ipath_parse_ushort(buf, &lid);
+ if (ret < 0)
+ goto invalid;
+
+ if (lid == 0 || lid >= 0xc000) {
+ ret = -EINVAL;
+ goto invalid;
+ }
+
+ ipath_set_sps_lid(dd, lid, 0);
+
+ goto bail;
+invalid:
+ ipath_dev_err(dd, "attempt to set invalid LID\n");
+bail:
+ return ret;
+}
+
+static ssize_t show_mlid(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_mlid);
+}
+
+static ssize_t store_mlid(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ int unit;
+ u16 mlid;
+ int ret;
+
+ ret = ipath_parse_ushort(buf, &mlid);
+ if (ret < 0)
+ goto invalid;
+
+ unit = dd->ipath_unit;
+
+ dd->ipath_mlid = mlid;
+ ipath_stats.sps_mlid[unit] = mlid;
+ ipath_layer_intr(dd, IPATH_LAYER_INT_BCAST);
+
+ goto bail;
+invalid:
+ ipath_dev_err(dd, "attempt to set invalid MLID\n");
+bail:
+ return ret;
+}
+
+static ssize_t show_guid(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ u8 *guid;
+
+ guid = (u8 *) & (dd->ipath_guid);
+
+ return scnprintf(buf, PAGE_SIZE,
+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ guid[0], guid[1], guid[2], guid[3],
+ guid[4], guid[5], guid[6], guid[7]);
+}
+
+static ssize_t store_guid(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ ssize_t ret;
+ unsigned short guid[8];
+ __be64 nguid;
+ u8 *ng;
+ int i;
+
+ if (sscanf(buf, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
+ &guid[0], &guid[1], &guid[2], &guid[3],
+ &guid[4], &guid[5], &guid[6], &guid[7]) != 8)
+ goto invalid;
+
+ ng = (u8 *) &nguid;
+
+ for (i = 0; i < 8; i++) {
+ if (guid[i] > 0xff)
+ goto invalid;
+ ng[i] = guid[i];
+ }
+
+ dd->ipath_guid = nguid;
+ dd->ipath_nguid = 1;
+
+ ret = strlen(buf);
+ goto bail;
+
+invalid:
+ ipath_dev_err(dd, "attempt to set invalid GUID\n");
+ ret = -EINVAL;
+
+bail:
+ return ret;
+}
+
+static ssize_t show_nguid(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid);
+}
+
+static ssize_t show_serial(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+ buf[sizeof dd->ipath_serial] = '\0';
+ memcpy(buf, dd->ipath_serial, sizeof dd->ipath_serial);
+ strcat(buf, "\n");
+ return strlen(buf);
+}
+
+static ssize_t show_unit(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_unit);
+}
+
+#define DEVICE_COUNTER(name, attr) \
+ static ssize_t show_counter_##name(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+ { \
+ struct ipath_devdata *dd = dev_get_drvdata(dev); \
+ return scnprintf(\
+ buf, PAGE_SIZE, "%llu\n", (unsigned long long) \
+ ipath_snap_cntr( \
+ dd, offsetof(struct infinipath_counters, \
+ attr) / sizeof(u64))); \
+ } \
+ static DEVICE_ATTR(name, S_IRUGO, show_counter_##name, NULL);
+
+DEVICE_COUNTER(ib_link_downeds, IBLinkDownedCnt);
+DEVICE_COUNTER(ib_link_err_recoveries, IBLinkErrRecoveryCnt);
+DEVICE_COUNTER(ib_status_changes, IBStatusChangeCnt);
+DEVICE_COUNTER(ib_symbol_errs, IBSymbolErrCnt);
+DEVICE_COUNTER(lb_flow_stalls, LBFlowStallCnt);
+DEVICE_COUNTER(lb_ints, LBIntCnt);
+DEVICE_COUNTER(rx_bad_formats, RxBadFormatCnt);
+DEVICE_COUNTER(rx_buf_ovfls, RxBufOvflCnt);
+DEVICE_COUNTER(rx_data_pkts, RxDataPktCnt);
+DEVICE_COUNTER(rx_dropped_pkts, RxDroppedPktCnt);
+DEVICE_COUNTER(rx_dwords, RxDwordCnt);
+DEVICE_COUNTER(rx_ebps, RxEBPCnt);
+DEVICE_COUNTER(rx_flow_ctrl_errs, RxFlowCtrlErrCnt);
+DEVICE_COUNTER(rx_flow_pkts, RxFlowPktCnt);
+DEVICE_COUNTER(rx_icrc_errs, RxICRCErrCnt);
+DEVICE_COUNTER(rx_len_errs, RxLenErrCnt);
+DEVICE_COUNTER(rx_link_problems, RxLinkProblemCnt);
+DEVICE_COUNTER(rx_lpcrc_errs, RxLPCRCErrCnt);
+DEVICE_COUNTER(rx_max_min_len_errs, RxMaxMinLenErrCnt);
+DEVICE_COUNTER(rx_p0_hdr_egr_ovfls, RxP0HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p1_hdr_egr_ovfls, RxP1HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p2_hdr_egr_ovfls, RxP2HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p3_hdr_egr_ovfls, RxP3HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p4_hdr_egr_ovfls, RxP4HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p5_hdr_egr_ovfls, RxP5HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p6_hdr_egr_ovfls, RxP6HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p7_hdr_egr_ovfls, RxP7HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p8_hdr_egr_ovfls, RxP8HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_pkey_mismatches, RxPKeyMismatchCnt);
+DEVICE_COUNTER(rx_tid_full_errs, RxTIDFullErrCnt);
+DEVICE_COUNTER(rx_tid_valid_errs, RxTIDValidErrCnt);
+DEVICE_COUNTER(rx_vcrc_errs, RxVCRCErrCnt);
+DEVICE_COUNTER(tx_data_pkts, TxDataPktCnt);
+DEVICE_COUNTER(tx_dropped_pkts, TxDroppedPktCnt);
+DEVICE_COUNTER(tx_dwords, TxDwordCnt);
+DEVICE_COUNTER(tx_flow_pkts, TxFlowPktCnt);
+DEVICE_COUNTER(tx_flow_stalls, TxFlowStallCnt);
+DEVICE_COUNTER(tx_len_errs, TxLenErrCnt);
+DEVICE_COUNTER(tx_max_min_len_errs, TxMaxMinLenErrCnt);
+DEVICE_COUNTER(tx_underruns, TxUnderrunCnt);
+DEVICE_COUNTER(tx_unsup_vl_errs, TxUnsupVLErrCnt);
+
+static struct attribute *dev_counter_attributes[] = {
+ &dev_attr_ib_link_downeds.attr,
+ &dev_attr_ib_link_err_recoveries.attr,
+ &dev_attr_ib_status_changes.attr,
+ &dev_attr_ib_symbol_errs.attr,
+ &dev_attr_lb_flow_stalls.attr,
+ &dev_attr_lb_ints.attr,
+ &dev_attr_rx_bad_formats.attr,
+ &dev_attr_rx_buf_ovfls.attr,
+ &dev_attr_rx_data_pkts.attr,
+ &dev_attr_rx_dropped_pkts.attr,
+ &dev_attr_rx_dwords.attr,
+ &dev_attr_rx_ebps.attr,
+ &dev_attr_rx_flow_ctrl_errs.attr,
+ &dev_attr_rx_flow_pkts.attr,
+ &dev_attr_rx_icrc_errs.attr,
+ &dev_attr_rx_len_errs.attr,
+ &dev_attr_rx_link_problems.attr,
+ &dev_attr_rx_lpcrc_errs.attr,
+ &dev_attr_rx_max_min_len_errs.attr,
+ &dev_attr_rx_p0_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p1_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p2_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p3_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p4_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p5_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p6_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p7_hdr_egr_ovfls.attr,
+ &dev_attr_rx_p8_hdr_egr_ovfls.attr,
+ &dev_attr_rx_pkey_mismatches.attr,
+ &dev_attr_rx_tid_full_errs.attr,
+ &dev_attr_rx_tid_valid_errs.attr,
+ &dev_attr_rx_vcrc_errs.attr,
+ &dev_attr_tx_data_pkts.attr,
+ &dev_attr_tx_dropped_pkts.attr,
+ &dev_attr_tx_dwords.attr,
+ &dev_attr_tx_flow_pkts.attr,
+ &dev_attr_tx_flow_stalls.attr,
+ &dev_attr_tx_len_errs.attr,
+ &dev_attr_tx_max_min_len_errs.attr,
+ &dev_attr_tx_underruns.attr,
+ &dev_attr_tx_unsup_vl_errs.attr,
+ NULL
+};
+
+static struct attribute_group dev_counter_attr_group = {
+ .name = "counters",
+ .attrs = dev_counter_attributes
+};
+
+static ssize_t store_reset(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ int ret;
+
+ if (count < 5 || memcmp(buf, "reset", 5)) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (dd->ipath_flags & IPATH_DISABLED) {
+ /*
+ * post-reset init would re-enable interrupts, etc.
+ * so don't allow reset on disabled devices. Not
+ * perfect error, but about the best choice.
+ */
+ dev_info(dev,"Unit %d is disabled, can't reset\n",
+ dd->ipath_unit);
+ ret = -EINVAL;
+ }
+ ret = ipath_reset_device(dd->ipath_unit);
+bail:
+ return ret<0 ? ret : count;
+}
+
+static ssize_t store_link_state(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ int ret, r;
+ u16 state;
+
+ ret = ipath_parse_ushort(buf, &state);
+ if (ret < 0)
+ goto invalid;
+
+ r = ipath_layer_set_linkstate(dd, state);
+ if (r < 0) {
+ ret = r;
+ goto bail;
+ }
+
+ goto bail;
+invalid:
+ ipath_dev_err(dd, "attempt to set invalid link state\n");
+bail:
+ return ret;
+}
+
+static ssize_t show_mtu(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_ibmtu);
+}
+
+static ssize_t store_mtu(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ ssize_t ret;
+ u16 mtu = 0;
+ int r;
+
+ ret = ipath_parse_ushort(buf, &mtu);
+ if (ret < 0)
+ goto invalid;
+
+ r = ipath_layer_set_mtu(dd, mtu);
+ if (r < 0)
+ ret = r;
+
+ goto bail;
+invalid:
+ ipath_dev_err(dd, "attempt to set invalid MTU\n");
+bail:
+ return ret;
+}
+
+static ssize_t show_enabled(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ (dd->ipath_flags & IPATH_DISABLED) ? 0 : 1);
+}
+
+static ssize_t store_enabled(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ ssize_t ret;
+ u16 enable = 0;
+
+ ret = ipath_parse_ushort(buf, &enable);
+ if (ret < 0) {
+ ipath_dev_err(dd, "attempt to use non-numeric on enable\n");
+ goto bail;
+ }
+
+ if (enable) {
+ if (!(dd->ipath_flags & IPATH_DISABLED))
+ goto bail;
+
+ dev_info(dev, "Enabling unit %d\n", dd->ipath_unit);
+ /* same as post-reset */
+ ret = ipath_init_chip(dd, 1);
+ if (ret)
+ ipath_dev_err(dd, "Failed to enable unit %d\n",
+ dd->ipath_unit);
+ else {
+ dd->ipath_flags &= ~IPATH_DISABLED;
+ *dd->ipath_statusp &= ~IPATH_STATUS_ADMIN_DISABLED;
+ }
+ }
+ else if (!(dd->ipath_flags & IPATH_DISABLED)) {
+ dev_info(dev, "Disabling unit %d\n", dd->ipath_unit);
+ ipath_shutdown_device(dd);
+ dd->ipath_flags |= IPATH_DISABLED;
+ *dd->ipath_statusp |= IPATH_STATUS_ADMIN_DISABLED;
+ }
+
+bail:
+ return ret;
+}
+
+static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
+static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
+
+static struct attribute *driver_attributes[] = {
+ &driver_attr_num_units.attr,
+ &driver_attr_version.attr,
+ NULL
+};
+
+static struct attribute_group driver_attr_group = {
+ .attrs = driver_attributes
+};
+
+static DEVICE_ATTR(guid, S_IWUSR | S_IRUGO, show_guid, store_guid);
+static DEVICE_ATTR(lid, S_IWUSR | S_IRUGO, show_lid, store_lid);
+static DEVICE_ATTR(link_state, S_IWUSR, NULL, store_link_state);
+static DEVICE_ATTR(mlid, S_IWUSR | S_IRUGO, show_mlid, store_mlid);
+static DEVICE_ATTR(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu);
+static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled);
+static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL);
+static DEVICE_ATTR(reset, S_IWUSR, NULL, store_reset);
+static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL);
+static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
+static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
+
+static struct attribute *dev_attributes[] = {
+ &dev_attr_guid.attr,
+ &dev_attr_lid.attr,
+ &dev_attr_link_state.attr,
+ &dev_attr_mlid.attr,
+ &dev_attr_mtu.attr,
+ &dev_attr_nguid.attr,
+ &dev_attr_serial.attr,
+ &dev_attr_status.attr,
+ &dev_attr_status_str.attr,
+ &dev_attr_boardversion.attr,
+ &dev_attr_unit.attr,
+ &dev_attr_enabled.attr,
+ NULL
+};
+
+static struct attribute_group dev_attr_group = {
+ .attrs = dev_attributes
+};
+
+/**
+ * ipath_expose_reset - create a device reset file
+ * @dev: the device structure
+ *
+ * Only expose a file that lets us reset the device after someone
+ * enters diag mode. A device reset is quite likely to crash the
+ * machine entirely, so we don't want to normally make it
+ * available.
+ *
+ * Called with ipath_mutex held.
+ */
+int ipath_expose_reset(struct device *dev)
+{
+ static int exposed;
+ int ret;
+
+ if (!exposed) {
+ ret = device_create_file(dev, &dev_attr_reset);
+ exposed = 1;
+ }
+ else
+ ret = 0;
+
+ return ret;
+}
+
+int ipath_driver_create_group(struct device_driver *drv)
+{
+ int ret;
+
+ ret = sysfs_create_group(&drv->kobj, &driver_attr_group);
+ if (ret)
+ goto bail;
+
+ ret = sysfs_create_group(&drv->kobj, &driver_stat_attr_group);
+ if (ret)
+ sysfs_remove_group(&drv->kobj, &driver_attr_group);
+
+bail:
+ return ret;
+}
+
+void ipath_driver_remove_group(struct device_driver *drv)
+{
+ sysfs_remove_group(&drv->kobj, &driver_stat_attr_group);
+ sysfs_remove_group(&drv->kobj, &driver_attr_group);
+}
+
+int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd)
+{
+ int ret;
+ char unit[5];
+
+ ret = sysfs_create_group(&dev->kobj, &dev_attr_group);
+ if (ret)
+ goto bail;
+
+ ret = sysfs_create_group(&dev->kobj, &dev_counter_attr_group);
+ if (ret)
+ goto bail_attrs;
+
+ snprintf(unit, sizeof(unit), "%02d", dd->ipath_unit);
+ ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, unit);
+ if (ret == 0)
+ goto bail;
+
+ sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
+bail_attrs:
+ sysfs_remove_group(&dev->kobj, &dev_attr_group);
+bail:
+ return ret;
+}
+
+void ipath_device_remove_group(struct device *dev, struct ipath_devdata *dd)
+{
+ char unit[5];
+
+ snprintf(unit, sizeof(unit), "%02d", dd->ipath_unit);
+ sysfs_remove_link(&dev->driver->kobj, unit);
+
+ sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
+ sysfs_remove_group(&dev->kobj, &dev_attr_group);
+
+ device_remove_file(dev, &dev_attr_reset);
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c
new file mode 100644
index 00000000000..0d6dbc0a541
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_uc.c
@@ -0,0 +1,645 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+/* cut down ridiculously long IB macro names */
+#define OP(x) IB_OPCODE_UC_##x
+
+static void complete_last_send(struct ipath_qp *qp, struct ipath_swqe *wqe,
+ struct ib_wc *wc)
+{
+ if (++qp->s_last == qp->s_size)
+ qp->s_last = 0;
+ if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &qp->s_flags) ||
+ (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
+ wc->wr_id = wqe->wr.wr_id;
+ wc->status = IB_WC_SUCCESS;
+ wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+ wc->vendor_err = 0;
+ wc->byte_len = wqe->length;
+ wc->qp_num = qp->ibqp.qp_num;
+ wc->src_qp = qp->remote_qpn;
+ wc->pkey_index = 0;
+ wc->slid = qp->remote_ah_attr.dlid;
+ wc->sl = qp->remote_ah_attr.sl;
+ wc->dlid_path_bits = 0;
+ wc->port_num = 0;
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 0);
+ }
+ wqe = get_swqe_ptr(qp, qp->s_last);
+}
+
+/**
+ * ipath_do_uc_send - do a send on a UC queue
+ * @data: contains a pointer to the QP to send on
+ *
+ * Process entries in the send work queue until the queue is exhausted.
+ * Only allow one CPU to send a packet per QP (tasklet).
+ * Otherwise, after we drop the QP lock, two threads could send
+ * packets out of order.
+ * This is similar to ipath_do_rc_send() below except we don't have
+ * timeouts or resends.
+ */
+void ipath_do_uc_send(unsigned long data)
+{
+ struct ipath_qp *qp = (struct ipath_qp *)data;
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ struct ipath_swqe *wqe;
+ unsigned long flags;
+ u16 lrh0;
+ u32 hwords;
+ u32 nwords;
+ u32 extra_bytes;
+ u32 bth0;
+ u32 bth2;
+ u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ u32 len;
+ struct ipath_other_headers *ohdr;
+ struct ib_wc wc;
+
+ if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags))
+ goto bail;
+
+ if (unlikely(qp->remote_ah_attr.dlid ==
+ ipath_layer_get_lid(dev->dd))) {
+ /* Pass in an uninitialized ib_wc to save stack space. */
+ ipath_ruc_loopback(qp, &wc);
+ clear_bit(IPATH_S_BUSY, &qp->s_flags);
+ goto bail;
+ }
+
+ ohdr = &qp->s_hdr.u.oth;
+ if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
+ ohdr = &qp->s_hdr.u.l.oth;
+
+again:
+ /* Check for a constructed packet to be sent. */
+ if (qp->s_hdrwords != 0) {
+ /*
+ * If no PIO bufs are available, return.
+ * An interrupt will call ipath_ib_piobufavail()
+ * when one is available.
+ */
+ if (ipath_verbs_send(dev->dd, qp->s_hdrwords,
+ (u32 *) &qp->s_hdr,
+ qp->s_cur_size,
+ qp->s_cur_sge)) {
+ ipath_no_bufs_available(qp, dev);
+ goto bail;
+ }
+ dev->n_unicast_xmit++;
+ /* Record that we sent the packet and s_hdr is empty. */
+ qp->s_hdrwords = 0;
+ }
+
+ lrh0 = IPS_LRH_BTH;
+ /* header size in 32-bit words LRH+BTH = (8+12)/4. */
+ hwords = 5;
+
+ /*
+ * The lock is needed to synchronize between
+ * setting qp->s_ack_state and post_send().
+ */
+ spin_lock_irqsave(&qp->s_lock, flags);
+
+ if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK))
+ goto done;
+
+ bth0 = ipath_layer_get_pkey(dev->dd, qp->s_pkey_index);
+
+ /* Send a request. */
+ wqe = get_swqe_ptr(qp, qp->s_last);
+ switch (qp->s_state) {
+ default:
+ /*
+ * Signal the completion of the last send (if there is
+ * one).
+ */
+ if (qp->s_last != qp->s_tail)
+ complete_last_send(qp, wqe, &wc);
+
+ /* Check if send work queue is empty. */
+ if (qp->s_tail == qp->s_head)
+ goto done;
+ /*
+ * Start a new request.
+ */
+ qp->s_psn = wqe->psn = qp->s_next_psn;
+ qp->s_sge.sge = wqe->sg_list[0];
+ qp->s_sge.sg_list = wqe->sg_list + 1;
+ qp->s_sge.num_sge = wqe->wr.num_sge;
+ qp->s_len = len = wqe->length;
+ switch (wqe->wr.opcode) {
+ case IB_WR_SEND:
+ case IB_WR_SEND_WITH_IMM:
+ if (len > pmtu) {
+ qp->s_state = OP(SEND_FIRST);
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_SEND)
+ qp->s_state = OP(SEND_ONLY);
+ else {
+ qp->s_state =
+ OP(SEND_ONLY_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+ ohdr->u.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ }
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ break;
+
+ case IB_WR_RDMA_WRITE:
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ ohdr->u.rc.reth.vaddr =
+ cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+ ohdr->u.rc.reth.rkey =
+ cpu_to_be32(wqe->wr.wr.rdma.rkey);
+ ohdr->u.rc.reth.length = cpu_to_be32(len);
+ hwords += sizeof(struct ib_reth) / 4;
+ if (len > pmtu) {
+ qp->s_state = OP(RDMA_WRITE_FIRST);
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+ qp->s_state = OP(RDMA_WRITE_ONLY);
+ else {
+ qp->s_state =
+ OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
+ /* Immediate data comes after the RETH */
+ ohdr->u.rc.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ }
+ break;
+
+ default:
+ goto done;
+ }
+ if (++qp->s_tail >= qp->s_size)
+ qp->s_tail = 0;
+ break;
+
+ case OP(SEND_FIRST):
+ qp->s_state = OP(SEND_MIDDLE);
+ /* FALLTHROUGH */
+ case OP(SEND_MIDDLE):
+ len = qp->s_len;
+ if (len > pmtu) {
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_SEND)
+ qp->s_state = OP(SEND_LAST);
+ else {
+ qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+ ohdr->u.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ }
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ break;
+
+ case OP(RDMA_WRITE_FIRST):
+ qp->s_state = OP(RDMA_WRITE_MIDDLE);
+ /* FALLTHROUGH */
+ case OP(RDMA_WRITE_MIDDLE):
+ len = qp->s_len;
+ if (len > pmtu) {
+ len = pmtu;
+ break;
+ }
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+ qp->s_state = OP(RDMA_WRITE_LAST);
+ else {
+ qp->s_state =
+ OP(RDMA_WRITE_LAST_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+ ohdr->u.imm_data = wqe->wr.imm_data;
+ hwords += 1;
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ }
+ break;
+ }
+ bth2 = qp->s_next_psn++ & IPS_PSN_MASK;
+ qp->s_len -= len;
+ bth0 |= qp->s_state << 24;
+
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+
+ /* Construct the header. */
+ extra_bytes = (4 - len) & 3;
+ nwords = (len + extra_bytes) >> 2;
+ if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) {
+ /* Header size in 32-bit words. */
+ hwords += 10;
+ lrh0 = IPS_LRH_GRH;
+ qp->s_hdr.u.l.grh.version_tclass_flow =
+ cpu_to_be32((6 << 28) |
+ (qp->remote_ah_attr.grh.traffic_class
+ << 20) |
+ qp->remote_ah_attr.grh.flow_label);
+ qp->s_hdr.u.l.grh.paylen =
+ cpu_to_be16(((hwords - 12) + nwords +
+ SIZE_OF_CRC) << 2);
+ /* next_hdr is defined by C8-7 in ch. 8.4.1 */
+ qp->s_hdr.u.l.grh.next_hdr = 0x1B;
+ qp->s_hdr.u.l.grh.hop_limit =
+ qp->remote_ah_attr.grh.hop_limit;
+ /* The SGID is 32-bit aligned. */
+ qp->s_hdr.u.l.grh.sgid.global.subnet_prefix =
+ dev->gid_prefix;
+ qp->s_hdr.u.l.grh.sgid.global.interface_id =
+ ipath_layer_get_guid(dev->dd);
+ qp->s_hdr.u.l.grh.dgid = qp->remote_ah_attr.grh.dgid;
+ }
+ qp->s_hdrwords = hwords;
+ qp->s_cur_sge = &qp->s_sge;
+ qp->s_cur_size = len;
+ lrh0 |= qp->remote_ah_attr.sl << 4;
+ qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
+ /* DEST LID */
+ qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
+ qp->s_hdr.lrh[2] = cpu_to_be16(hwords + nwords + SIZE_OF_CRC);
+ qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd));
+ bth0 |= extra_bytes << 20;
+ ohdr->bth[0] = cpu_to_be32(bth0);
+ ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);
+ ohdr->bth[2] = cpu_to_be32(bth2);
+
+ /* Check for more work to do. */
+ goto again;
+
+done:
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+ clear_bit(IPATH_S_BUSY, &qp->s_flags);
+
+bail:
+ return;
+}
+
+/**
+ * ipath_uc_rcv - handle an incoming UC packet
+ * @dev: the device the packet came in on
+ * @hdr: the header of the packet
+ * @has_grh: true if the packet has a GRH
+ * @data: the packet data
+ * @tlen: the length of the packet
+ * @qp: the QP for this packet.
+ *
+ * This is called from ipath_qp_rcv() to process an incoming UC packet
+ * for the given QP.
+ * Called at interrupt level.
+ */
+void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ int has_grh, void *data, u32 tlen, struct ipath_qp *qp)
+{
+ struct ipath_other_headers *ohdr;
+ int opcode;
+ u32 hdrsize;
+ u32 psn;
+ u32 pad;
+ unsigned long flags;
+ struct ib_wc wc;
+ u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+ struct ib_reth *reth;
+ int header_in_data;
+
+ /* Check for GRH */
+ if (!has_grh) {
+ ohdr = &hdr->u.oth;
+ hdrsize = 8 + 12; /* LRH + BTH */
+ psn = be32_to_cpu(ohdr->bth[2]);
+ header_in_data = 0;
+ } else {
+ ohdr = &hdr->u.l.oth;
+ hdrsize = 8 + 40 + 12; /* LRH + GRH + BTH */
+ /*
+ * The header with GRH is 60 bytes and the
+ * core driver sets the eager header buffer
+ * size to 56 bytes so the last 4 bytes of
+ * the BTH header (PSN) is in the data buffer.
+ */
+ header_in_data =
+ ipath_layer_get_rcvhdrentsize(dev->dd) == 16;
+ if (header_in_data) {
+ psn = be32_to_cpu(((__be32 *) data)[0]);
+ data += sizeof(__be32);
+ } else
+ psn = be32_to_cpu(ohdr->bth[2]);
+ }
+ /*
+ * The opcode is in the low byte when its in network order
+ * (top byte when in host order).
+ */
+ opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+
+ wc.imm_data = 0;
+ wc.wc_flags = 0;
+
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+
+ /* Compare the PSN verses the expected PSN. */
+ if (unlikely(ipath_cmp24(psn, qp->r_psn) != 0)) {
+ /*
+ * Handle a sequence error.
+ * Silently drop any current message.
+ */
+ qp->r_psn = psn;
+ inv:
+ qp->r_state = OP(SEND_LAST);
+ switch (opcode) {
+ case OP(SEND_FIRST):
+ case OP(SEND_ONLY):
+ case OP(SEND_ONLY_WITH_IMMEDIATE):
+ goto send_first;
+
+ case OP(RDMA_WRITE_FIRST):
+ case OP(RDMA_WRITE_ONLY):
+ case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE):
+ goto rdma_first;
+
+ default:
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ }
+
+ /* Check for opcode sequence errors. */
+ switch (qp->r_state) {
+ case OP(SEND_FIRST):
+ case OP(SEND_MIDDLE):
+ if (opcode == OP(SEND_MIDDLE) ||
+ opcode == OP(SEND_LAST) ||
+ opcode == OP(SEND_LAST_WITH_IMMEDIATE))
+ break;
+ goto inv;
+
+ case OP(RDMA_WRITE_FIRST):
+ case OP(RDMA_WRITE_MIDDLE):
+ if (opcode == OP(RDMA_WRITE_MIDDLE) ||
+ opcode == OP(RDMA_WRITE_LAST) ||
+ opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE))
+ break;
+ goto inv;
+
+ default:
+ if (opcode == OP(SEND_FIRST) ||
+ opcode == OP(SEND_ONLY) ||
+ opcode == OP(SEND_ONLY_WITH_IMMEDIATE) ||
+ opcode == OP(RDMA_WRITE_FIRST) ||
+ opcode == OP(RDMA_WRITE_ONLY) ||
+ opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE))
+ break;
+ goto inv;
+ }
+
+ /* OK, process the packet. */
+ switch (opcode) {
+ case OP(SEND_FIRST):
+ case OP(SEND_ONLY):
+ case OP(SEND_ONLY_WITH_IMMEDIATE):
+ send_first:
+ if (qp->r_reuse_sge) {
+ qp->r_reuse_sge = 0;
+ qp->r_sge = qp->s_rdma_sge;
+ } else if (!ipath_get_rwqe(qp, 0)) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ /* Save the WQE so we can reuse it in case of an error. */
+ qp->s_rdma_sge = qp->r_sge;
+ qp->r_rcv_len = 0;
+ if (opcode == OP(SEND_ONLY))
+ goto send_last;
+ else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE))
+ goto send_last_imm;
+ /* FALLTHROUGH */
+ case OP(SEND_MIDDLE):
+ /* Check for invalid length PMTU or posted rwqe len. */
+ if (unlikely(tlen != (hdrsize + pmtu + 4))) {
+ qp->r_reuse_sge = 1;
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ qp->r_rcv_len += pmtu;
+ if (unlikely(qp->r_rcv_len > qp->r_len)) {
+ qp->r_reuse_sge = 1;
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ ipath_copy_sge(&qp->r_sge, data, pmtu);
+ break;
+
+ case OP(SEND_LAST_WITH_IMMEDIATE):
+ send_last_imm:
+ if (header_in_data) {
+ wc.imm_data = *(__be32 *) data;
+ data += sizeof(__be32);
+ } else {
+ /* Immediate data comes after BTH */
+ wc.imm_data = ohdr->u.imm_data;
+ }
+ hdrsize += 4;
+ wc.wc_flags = IB_WC_WITH_IMM;
+ /* FALLTHROUGH */
+ case OP(SEND_LAST):
+ send_last:
+ /* Get the number of bytes the message was padded by. */
+ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ /* Check for invalid length. */
+ /* XXX LAST len should be >= 1 */
+ if (unlikely(tlen < (hdrsize + pad + 4))) {
+ qp->r_reuse_sge = 1;
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ /* Don't count the CRC. */
+ tlen -= (hdrsize + pad + 4);
+ wc.byte_len = tlen + qp->r_rcv_len;
+ if (unlikely(wc.byte_len > qp->r_len)) {
+ qp->r_reuse_sge = 1;
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ /* XXX Need to free SGEs */
+ last_imm:
+ ipath_copy_sge(&qp->r_sge, data, tlen);
+ wc.wr_id = qp->r_wr_id;
+ wc.status = IB_WC_SUCCESS;
+ wc.opcode = IB_WC_RECV;
+ wc.vendor_err = 0;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = qp->remote_qpn;
+ wc.pkey_index = 0;
+ wc.slid = qp->remote_ah_attr.dlid;
+ wc.sl = qp->remote_ah_attr.sl;
+ wc.dlid_path_bits = 0;
+ wc.port_num = 0;
+ /* Signal completion event if the solicited bit is set. */
+ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
+ (ohdr->bth[0] &
+ __constant_cpu_to_be32(1 << 23)) != 0);
+ break;
+
+ case OP(RDMA_WRITE_FIRST):
+ case OP(RDMA_WRITE_ONLY):
+ case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): /* consume RWQE */
+ rdma_first:
+ /* RETH comes after BTH */
+ if (!header_in_data)
+ reth = &ohdr->u.rc.reth;
+ else {
+ reth = (struct ib_reth *)data;
+ data += sizeof(*reth);
+ }
+ hdrsize += sizeof(*reth);
+ qp->r_len = be32_to_cpu(reth->length);
+ qp->r_rcv_len = 0;
+ if (qp->r_len != 0) {
+ u32 rkey = be32_to_cpu(reth->rkey);
+ u64 vaddr = be64_to_cpu(reth->vaddr);
+
+ /* Check rkey */
+ if (unlikely(!ipath_rkey_ok(
+ dev, &qp->r_sge, qp->r_len,
+ vaddr, rkey,
+ IB_ACCESS_REMOTE_WRITE))) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ } else {
+ qp->r_sge.sg_list = NULL;
+ qp->r_sge.sge.mr = NULL;
+ qp->r_sge.sge.vaddr = NULL;
+ qp->r_sge.sge.length = 0;
+ qp->r_sge.sge.sge_length = 0;
+ }
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_WRITE))) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ if (opcode == OP(RDMA_WRITE_ONLY))
+ goto rdma_last;
+ else if (opcode ==
+ OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE))
+ goto rdma_last_imm;
+ /* FALLTHROUGH */
+ case OP(RDMA_WRITE_MIDDLE):
+ /* Check for invalid length PMTU or posted rwqe len. */
+ if (unlikely(tlen != (hdrsize + pmtu + 4))) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ qp->r_rcv_len += pmtu;
+ if (unlikely(qp->r_rcv_len > qp->r_len)) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ ipath_copy_sge(&qp->r_sge, data, pmtu);
+ break;
+
+ case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE):
+ rdma_last_imm:
+ /* Get the number of bytes the message was padded by. */
+ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ /* Check for invalid length. */
+ /* XXX LAST len should be >= 1 */
+ if (unlikely(tlen < (hdrsize + pad + 4))) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ /* Don't count the CRC. */
+ tlen -= (hdrsize + pad + 4);
+ if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ if (qp->r_reuse_sge) {
+ qp->r_reuse_sge = 0;
+ } else if (!ipath_get_rwqe(qp, 1)) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ if (header_in_data) {
+ wc.imm_data = *(__be32 *) data;
+ data += sizeof(__be32);
+ } else {
+ /* Immediate data comes after BTH */
+ wc.imm_data = ohdr->u.imm_data;
+ }
+ hdrsize += 4;
+ wc.wc_flags = IB_WC_WITH_IMM;
+ wc.byte_len = 0;
+ goto last_imm;
+
+ case OP(RDMA_WRITE_LAST):
+ rdma_last:
+ /* Get the number of bytes the message was padded by. */
+ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ /* Check for invalid length. */
+ /* XXX LAST len should be >= 1 */
+ if (unlikely(tlen < (hdrsize + pad + 4))) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ /* Don't count the CRC. */
+ tlen -= (hdrsize + pad + 4);
+ if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) {
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ ipath_copy_sge(&qp->r_sge, data, tlen);
+ break;
+
+ default:
+ /* Drop packet for unknown opcodes. */
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ qp->r_psn++;
+ qp->r_state = opcode;
+done:
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+
+bail:
+ return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
new file mode 100644
index 00000000000..e606daf8321
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_ud.c
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_smi.h>
+
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+/**
+ * ipath_ud_loopback - handle send on loopback QPs
+ * @sqp: the QP
+ * @ss: the SGE state
+ * @length: the length of the data to send
+ * @wr: the work request
+ * @wc: the work completion entry
+ *
+ * This is called from ipath_post_ud_send() to forward a WQE addressed
+ * to the same HCA.
+ */
+static void ipath_ud_loopback(struct ipath_qp *sqp,
+ struct ipath_sge_state *ss,
+ u32 length, struct ib_send_wr *wr,
+ struct ib_wc *wc)
+{
+ struct ipath_ibdev *dev = to_idev(sqp->ibqp.device);
+ struct ipath_qp *qp;
+ struct ib_ah_attr *ah_attr;
+ unsigned long flags;
+ struct ipath_rq *rq;
+ struct ipath_srq *srq;
+ struct ipath_sge_state rsge;
+ struct ipath_sge *sge;
+ struct ipath_rwqe *wqe;
+
+ qp = ipath_lookup_qpn(&dev->qp_table, wr->wr.ud.remote_qpn);
+ if (!qp)
+ return;
+
+ /*
+ * Check that the qkey matches (except for QP0, see 9.6.1.4.1).
+ * Qkeys with the high order bit set mean use the
+ * qkey from the QP context instead of the WR (see 10.2.5).
+ */
+ if (unlikely(qp->ibqp.qp_num &&
+ ((int) wr->wr.ud.remote_qkey < 0
+ ? qp->qkey : wr->wr.ud.remote_qkey) != qp->qkey)) {
+ /* XXX OK to lose a count once in a while. */
+ dev->qkey_violations++;
+ dev->n_pkt_drops++;
+ goto done;
+ }
+
+ /*
+ * A GRH is expected to preceed the data even if not
+ * present on the wire.
+ */
+ wc->byte_len = length + sizeof(struct ib_grh);
+
+ if (wr->opcode == IB_WR_SEND_WITH_IMM) {
+ wc->wc_flags = IB_WC_WITH_IMM;
+ wc->imm_data = wr->imm_data;
+ } else {
+ wc->wc_flags = 0;
+ wc->imm_data = 0;
+ }
+
+ /*
+ * Get the next work request entry to find where to put the data.
+ * Note that it is safe to drop the lock after changing rq->tail
+ * since ipath_post_receive() won't fill the empty slot.
+ */
+ if (qp->ibqp.srq) {
+ srq = to_isrq(qp->ibqp.srq);
+ rq = &srq->rq;
+ } else {
+ srq = NULL;
+ rq = &qp->r_rq;
+ }
+ spin_lock_irqsave(&rq->lock, flags);
+ if (rq->tail == rq->head) {
+ spin_unlock_irqrestore(&rq->lock, flags);
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ /* Silently drop packets which are too big. */
+ wqe = get_rwqe_ptr(rq, rq->tail);
+ if (wc->byte_len > wqe->length) {
+ spin_unlock_irqrestore(&rq->lock, flags);
+ dev->n_pkt_drops++;
+ goto done;
+ }
+ wc->wr_id = wqe->wr_id;
+ rsge.sge = wqe->sg_list[0];
+ rsge.sg_list = wqe->sg_list + 1;
+ rsge.num_sge = wqe->num_sge;
+ if (++rq->tail >= rq->size)
+ rq->tail = 0;
+ if (srq && srq->ibsrq.event_handler) {
+ u32 n;
+
+ if (rq->head < rq->tail)
+ n = rq->size + rq->head - rq->tail;
+ else
+ n = rq->head - rq->tail;
+ if (n < srq->limit) {
+ struct ib_event ev;
+
+ srq->limit = 0;
+ spin_unlock_irqrestore(&rq->lock, flags);
+ ev.device = qp->ibqp.device;
+ ev.element.srq = qp->ibqp.srq;
+ ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
+ srq->ibsrq.event_handler(&ev,
+ srq->ibsrq.srq_context);
+ } else
+ spin_unlock_irqrestore(&rq->lock, flags);
+ } else
+ spin_unlock_irqrestore(&rq->lock, flags);
+ ah_attr = &to_iah(wr->wr.ud.ah)->attr;
+ if (ah_attr->ah_flags & IB_AH_GRH) {
+ ipath_copy_sge(&rsge, &ah_attr->grh, sizeof(struct ib_grh));
+ wc->wc_flags |= IB_WC_GRH;
+ } else
+ ipath_skip_sge(&rsge, sizeof(struct ib_grh));
+ sge = &ss->sge;
+ while (length) {
+ u32 len = sge->length;
+
+ if (len > length)
+ len = length;
+ BUG_ON(len == 0);
+ ipath_copy_sge(&rsge, sge->vaddr, len);
+ sge->vaddr += len;
+ sge->length -= len;
+ sge->sge_length -= len;
+ if (sge->sge_length == 0) {
+ if (--ss->num_sge)
+ *sge = *ss->sg_list++;
+ } else if (sge->length == 0 && sge->mr != NULL) {
+ if (++sge->n >= IPATH_SEGSZ) {
+ if (++sge->m >= sge->mr->mapsz)
+ break;
+ sge->n = 0;
+ }
+ sge->vaddr =
+ sge->mr->map[sge->m]->segs[sge->n].vaddr;
+ sge->length =
+ sge->mr->map[sge->m]->segs[sge->n].length;
+ }
+ length -= len;
+ }
+ wc->status = IB_WC_SUCCESS;
+ wc->opcode = IB_WC_RECV;
+ wc->vendor_err = 0;
+ wc->qp_num = qp->ibqp.qp_num;
+ wc->src_qp = sqp->ibqp.qp_num;
+ /* XXX do we know which pkey matched? Only needed for GSI. */
+ wc->pkey_index = 0;
+ wc->slid = ipath_layer_get_lid(dev->dd) |
+ (ah_attr->src_path_bits &
+ ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1));
+ wc->sl = ah_attr->sl;
+ wc->dlid_path_bits =
+ ah_attr->dlid & ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+ /* Signal completion event if the solicited bit is set. */
+ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), wc,
+ wr->send_flags & IB_SEND_SOLICITED);
+
+done:
+ if (atomic_dec_and_test(&qp->refcount))
+ wake_up(&qp->wait);
+}
+
+/**
+ * ipath_post_ud_send - post a UD send on QP
+ * @qp: the QP
+ * @wr: the work request
+ *
+ * Note that we actually send the data as it is posted instead of putting
+ * the request into a ring buffer. If we wanted to use a ring buffer,
+ * we would need to save a reference to the destination address in the SWQE.
+ */
+int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr)
+{
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+ struct ipath_other_headers *ohdr;
+ struct ib_ah_attr *ah_attr;
+ struct ipath_sge_state ss;
+ struct ipath_sge *sg_list;
+ struct ib_wc wc;
+ u32 hwords;
+ u32 nwords;
+ u32 len;
+ u32 extra_bytes;
+ u32 bth0;
+ u16 lrh0;
+ u16 lid;
+ int i;
+ int ret;
+
+ if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK)) {
+ ret = 0;
+ goto bail;
+ }
+
+ /* IB spec says that num_sge == 0 is OK. */
+ if (wr->num_sge > qp->s_max_sge) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (wr->num_sge > 1) {
+ sg_list = kmalloc((qp->s_max_sge - 1) * sizeof(*sg_list),
+ GFP_ATOMIC);
+ if (!sg_list) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ } else
+ sg_list = NULL;
+
+ /* Check the buffer to send. */
+ ss.sg_list = sg_list;
+ ss.sge.mr = NULL;
+ ss.sge.vaddr = NULL;
+ ss.sge.length = 0;
+ ss.sge.sge_length = 0;
+ ss.num_sge = 0;
+ len = 0;
+ for (i = 0; i < wr->num_sge; i++) {
+ /* Check LKEY */
+ if (to_ipd(qp->ibqp.pd)->user && wr->sg_list[i].lkey == 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (wr->sg_list[i].length == 0)
+ continue;
+ if (!ipath_lkey_ok(&dev->lk_table, ss.num_sge ?
+ sg_list + ss.num_sge - 1 : &ss.sge,
+ &wr->sg_list[i], 0)) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ len += wr->sg_list[i].length;
+ ss.num_sge++;
+ }
+ extra_bytes = (4 - len) & 3;
+ nwords = (len + extra_bytes) >> 2;
+
+ /* Construct the header. */
+ ah_attr = &to_iah(wr->wr.ud.ah)->attr;
+ if (ah_attr->dlid == 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ if (ah_attr->dlid >= IPS_MULTICAST_LID_BASE) {
+ if (ah_attr->dlid != IPS_PERMISSIVE_LID)
+ dev->n_multicast_xmit++;
+ else
+ dev->n_unicast_xmit++;
+ } else {
+ dev->n_unicast_xmit++;
+ lid = ah_attr->dlid &
+ ~((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+ if (unlikely(lid == ipath_layer_get_lid(dev->dd))) {
+ /*
+ * Pass in an uninitialized ib_wc to save stack
+ * space.
+ */
+ ipath_ud_loopback(qp, &ss, len, wr, &wc);
+ goto done;
+ }
+ }
+ if (ah_attr->ah_flags & IB_AH_GRH) {
+ /* Header size in 32-bit words. */
+ hwords = 17;
+ lrh0 = IPS_LRH_GRH;
+ ohdr = &qp->s_hdr.u.l.oth;
+ qp->s_hdr.u.l.grh.version_tclass_flow =
+ cpu_to_be32((6 << 28) |
+ (ah_attr->grh.traffic_class << 20) |
+ ah_attr->grh.flow_label);
+ qp->s_hdr.u.l.grh.paylen =
+ cpu_to_be16(((wr->opcode ==
+ IB_WR_SEND_WITH_IMM ? 6 : 5) +
+ nwords + SIZE_OF_CRC) << 2);
+ /* next_hdr is defined by C8-7 in ch. 8.4.1 */
+ qp->s_hdr.u.l.grh.next_hdr = 0x1B;
+ qp->s_hdr.u.l.grh.hop_limit = ah_attr->grh.hop_limit;
+ /* The SGID is 32-bit aligned. */
+ qp->s_hdr.u.l.grh.sgid.global.subnet_prefix =
+ dev->gid_prefix;
+ qp->s_hdr.u.l.grh.sgid.global.interface_id =
+ ipath_layer_get_guid(dev->dd);
+ qp->s_hdr.u.l.grh.dgid = ah_attr->grh.dgid;
+ /*
+ * Don't worry about sending to locally attached multicast
+ * QPs. It is unspecified by the spec. what happens.
+ */
+ } else {
+ /* Header size in 32-bit words. */
+ hwords = 7;
+ lrh0 = IPS_LRH_BTH;
+ ohdr = &qp->s_hdr.u.oth;
+ }
+ if (wr->opcode == IB_WR_SEND_WITH_IMM) {
+ ohdr->u.ud.imm_data = wr->imm_data;
+ wc.imm_data = wr->imm_data;
+ hwords += 1;
+ bth0 = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE << 24;
+ } else if (wr->opcode == IB_WR_SEND) {
+ wc.imm_data = 0;
+ bth0 = IB_OPCODE_UD_SEND_ONLY << 24;
+ } else {
+ ret = -EINVAL;
+ goto bail;
+ }
+ lrh0 |= ah_attr->sl << 4;
+ if (qp->ibqp.qp_type == IB_QPT_SMI)
+ lrh0 |= 0xF000; /* Set VL (see ch. 13.5.3.1) */
+ qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
+ qp->s_hdr.lrh[1] = cpu_to_be16(ah_attr->dlid); /* DEST LID */
+ qp->s_hdr.lrh[2] = cpu_to_be16(hwords + nwords + SIZE_OF_CRC);
+ lid = ipath_layer_get_lid(dev->dd);
+ if (lid) {
+ lid |= ah_attr->src_path_bits &
+ ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+ qp->s_hdr.lrh[3] = cpu_to_be16(lid);
+ } else
+ qp->s_hdr.lrh[3] = IB_LID_PERMISSIVE;
+ if (wr->send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+ bth0 |= extra_bytes << 20;
+ bth0 |= qp->ibqp.qp_type == IB_QPT_SMI ? IPS_DEFAULT_P_KEY :
+ ipath_layer_get_pkey(dev->dd, qp->s_pkey_index);
+ ohdr->bth[0] = cpu_to_be32(bth0);
+ /*
+ * Use the multicast QP if the destination LID is a multicast LID.
+ */
+ ohdr->bth[1] = ah_attr->dlid >= IPS_MULTICAST_LID_BASE &&
+ ah_attr->dlid != IPS_PERMISSIVE_LID ?
+ __constant_cpu_to_be32(IPS_MULTICAST_QPN) :
+ cpu_to_be32(wr->wr.ud.remote_qpn);
+ /* XXX Could lose a PSN count but not worth locking */
+ ohdr->bth[2] = cpu_to_be32(qp->s_next_psn++ & IPS_PSN_MASK);
+ /*
+ * Qkeys with the high order bit set mean use the
+ * qkey from the QP context instead of the WR (see 10.2.5).
+ */
+ ohdr->u.ud.deth[0] = cpu_to_be32((int)wr->wr.ud.remote_qkey < 0 ?
+ qp->qkey : wr->wr.ud.remote_qkey);
+ ohdr->u.ud.deth[1] = cpu_to_be32(qp->ibqp.qp_num);
+ if (ipath_verbs_send(dev->dd, hwords, (u32 *) &qp->s_hdr,
+ len, &ss))
+ dev->n_no_piobuf++;
+
+done:
+ /* Queue the completion status entry. */
+ if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &qp->s_flags) ||
+ (wr->send_flags & IB_SEND_SIGNALED)) {
+ wc.wr_id = wr->wr_id;
+ wc.status = IB_WC_SUCCESS;
+ wc.vendor_err = 0;
+ wc.opcode = IB_WC_SEND;
+ wc.byte_len = len;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = 0;
+ wc.wc_flags = 0;
+ /* XXX initialize other fields? */
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0);
+ }
+ kfree(sg_list);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_ud_rcv - receive an incoming UD packet
+ * @dev: the device the packet came in on
+ * @hdr: the packet header
+ * @has_grh: true if the packet has a GRH
+ * @data: the packet data
+ * @tlen: the packet length
+ * @qp: the QP the packet came on
+ *
+ * This is called from ipath_qp_rcv() to process an incoming UD packet
+ * for the given QP.
+ * Called at interrupt level.
+ */
+void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ int has_grh, void *data, u32 tlen, struct ipath_qp *qp)
+{
+ struct ipath_other_headers *ohdr;
+ int opcode;
+ u32 hdrsize;
+ u32 pad;
+ unsigned long flags;
+ struct ib_wc wc;
+ u32 qkey;
+ u32 src_qp;
+ struct ipath_rq *rq;
+ struct ipath_srq *srq;
+ struct ipath_rwqe *wqe;
+ u16 dlid;
+ int header_in_data;
+
+ /* Check for GRH */
+ if (!has_grh) {
+ ohdr = &hdr->u.oth;
+ hdrsize = 8 + 12 + 8; /* LRH + BTH + DETH */
+ qkey = be32_to_cpu(ohdr->u.ud.deth[0]);
+ src_qp = be32_to_cpu(ohdr->u.ud.deth[1]);
+ header_in_data = 0;
+ } else {
+ ohdr = &hdr->u.l.oth;
+ hdrsize = 8 + 40 + 12 + 8; /* LRH + GRH + BTH + DETH */
+ /*
+ * The header with GRH is 68 bytes and the core driver sets
+ * the eager header buffer size to 56 bytes so the last 12
+ * bytes of the IB header is in the data buffer.
+ */
+ header_in_data =
+ ipath_layer_get_rcvhdrentsize(dev->dd) == 16;
+ if (header_in_data) {
+ qkey = be32_to_cpu(((__be32 *) data)[1]);
+ src_qp = be32_to_cpu(((__be32 *) data)[2]);
+ data += 12;
+ } else {
+ qkey = be32_to_cpu(ohdr->u.ud.deth[0]);
+ src_qp = be32_to_cpu(ohdr->u.ud.deth[1]);
+ }
+ }
+ src_qp &= IPS_QPN_MASK;
+
+ /*
+ * Check that the permissive LID is only used on QP0
+ * and the QKEY matches (see 9.6.1.4.1 and 9.6.1.5.1).
+ */
+ if (qp->ibqp.qp_num) {
+ if (unlikely(hdr->lrh[1] == IB_LID_PERMISSIVE ||
+ hdr->lrh[3] == IB_LID_PERMISSIVE)) {
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ if (unlikely(qkey != qp->qkey)) {
+ /* XXX OK to lose a count once in a while. */
+ dev->qkey_violations++;
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ } else if (hdr->lrh[1] == IB_LID_PERMISSIVE ||
+ hdr->lrh[3] == IB_LID_PERMISSIVE) {
+ struct ib_smp *smp = (struct ib_smp *) data;
+
+ if (smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ }
+
+ /* Get the number of bytes the message was padded by. */
+ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ if (unlikely(tlen < (hdrsize + pad + 4))) {
+ /* Drop incomplete packets. */
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ tlen -= hdrsize + pad + 4;
+
+ /* Drop invalid MAD packets (see 13.5.3.1). */
+ if (unlikely((qp->ibqp.qp_num == 0 &&
+ (tlen != 256 ||
+ (be16_to_cpu(hdr->lrh[0]) >> 12) != 15)) ||
+ (qp->ibqp.qp_num == 1 &&
+ (tlen != 256 ||
+ (be16_to_cpu(hdr->lrh[0]) >> 12) == 15)))) {
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+
+ /*
+ * A GRH is expected to preceed the data even if not
+ * present on the wire.
+ */
+ wc.byte_len = tlen + sizeof(struct ib_grh);
+
+ /*
+ * The opcode is in the low byte when its in network order
+ * (top byte when in host order).
+ */
+ opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+ if (qp->ibqp.qp_num > 1 &&
+ opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
+ if (header_in_data) {
+ wc.imm_data = *(__be32 *) data;
+ data += sizeof(__be32);
+ } else
+ wc.imm_data = ohdr->u.ud.imm_data;
+ wc.wc_flags = IB_WC_WITH_IMM;
+ hdrsize += sizeof(u32);
+ } else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
+ wc.imm_data = 0;
+ wc.wc_flags = 0;
+ } else {
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+
+ /*
+ * Get the next work request entry to find where to put the data.
+ * Note that it is safe to drop the lock after changing rq->tail
+ * since ipath_post_receive() won't fill the empty slot.
+ */
+ if (qp->ibqp.srq) {
+ srq = to_isrq(qp->ibqp.srq);
+ rq = &srq->rq;
+ } else {
+ srq = NULL;
+ rq = &qp->r_rq;
+ }
+ spin_lock_irqsave(&rq->lock, flags);
+ if (rq->tail == rq->head) {
+ spin_unlock_irqrestore(&rq->lock, flags);
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ /* Silently drop packets which are too big. */
+ wqe = get_rwqe_ptr(rq, rq->tail);
+ if (wc.byte_len > wqe->length) {
+ spin_unlock_irqrestore(&rq->lock, flags);
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ wc.wr_id = wqe->wr_id;
+ qp->r_sge.sge = wqe->sg_list[0];
+ qp->r_sge.sg_list = wqe->sg_list + 1;
+ qp->r_sge.num_sge = wqe->num_sge;
+ if (++rq->tail >= rq->size)
+ rq->tail = 0;
+ if (srq && srq->ibsrq.event_handler) {
+ u32 n;
+
+ if (rq->head < rq->tail)
+ n = rq->size + rq->head - rq->tail;
+ else
+ n = rq->head - rq->tail;
+ if (n < srq->limit) {
+ struct ib_event ev;
+
+ srq->limit = 0;
+ spin_unlock_irqrestore(&rq->lock, flags);
+ ev.device = qp->ibqp.device;
+ ev.element.srq = qp->ibqp.srq;
+ ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
+ srq->ibsrq.event_handler(&ev,
+ srq->ibsrq.srq_context);
+ } else
+ spin_unlock_irqrestore(&rq->lock, flags);
+ } else
+ spin_unlock_irqrestore(&rq->lock, flags);
+ if (has_grh) {
+ ipath_copy_sge(&qp->r_sge, &hdr->u.l.grh,
+ sizeof(struct ib_grh));
+ wc.wc_flags |= IB_WC_GRH;
+ } else
+ ipath_skip_sge(&qp->r_sge, sizeof(struct ib_grh));
+ ipath_copy_sge(&qp->r_sge, data,
+ wc.byte_len - sizeof(struct ib_grh));
+ wc.status = IB_WC_SUCCESS;
+ wc.opcode = IB_WC_RECV;
+ wc.vendor_err = 0;
+ wc.qp_num = qp->ibqp.qp_num;
+ wc.src_qp = src_qp;
+ /* XXX do we know which pkey matched? Only needed for GSI. */
+ wc.pkey_index = 0;
+ wc.slid = be16_to_cpu(hdr->lrh[3]);
+ wc.sl = (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF;
+ dlid = be16_to_cpu(hdr->lrh[1]);
+ /*
+ * Save the LMC lower bits if the destination LID is a unicast LID.
+ */
+ wc.dlid_path_bits = dlid >= IPS_MULTICAST_LID_BASE ? 0 :
+ dlid & ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+ /* Signal completion event if the solicited bit is set. */
+ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
+ (ohdr->bth[0] &
+ __constant_cpu_to_be32(1 << 23)) != 0);
+
+bail:;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c
new file mode 100644
index 00000000000..2bb08afc86d
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/mm.h>
+#include <linux/device.h>
+
+#include "ipath_kernel.h"
+
+static void __ipath_release_user_pages(struct page **p, size_t num_pages,
+ int dirty)
+{
+ size_t i;
+
+ for (i = 0; i < num_pages; i++) {
+ ipath_cdbg(MM, "%lu/%lu put_page %p\n", (unsigned long) i,
+ (unsigned long) num_pages, p[i]);
+ if (dirty)
+ set_page_dirty_lock(p[i]);
+ put_page(p[i]);
+ }
+}
+
+/* call with current->mm->mmap_sem held */
+static int __get_user_pages(unsigned long start_page, size_t num_pages,
+ struct page **p, struct vm_area_struct **vma)
+{
+ unsigned long lock_limit;
+ size_t got;
+ int ret;
+
+#if 0
+ /*
+ * XXX - causes MPI programs to fail, haven't had time to check
+ * yet
+ */
+ if (!capable(CAP_IPC_LOCK)) {
+ ret = -EPERM;
+ goto bail;
+ }
+#endif
+
+ lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >>
+ PAGE_SHIFT;
+
+ if (num_pages > lock_limit) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ ipath_cdbg(VERBOSE, "pin %lx pages from vaddr %lx\n",
+ (unsigned long) num_pages, start_page);
+
+ for (got = 0; got < num_pages; got += ret) {
+ ret = get_user_pages(current, current->mm,
+ start_page + got * PAGE_SIZE,
+ num_pages - got, 1, 1,
+ p + got, vma);
+ if (ret < 0)
+ goto bail_release;
+ }
+
+ current->mm->locked_vm += num_pages;
+
+ ret = 0;
+ goto bail;
+
+bail_release:
+ __ipath_release_user_pages(p, got, 0);
+bail:
+ return ret;
+}
+
+/**
+ * ipath_get_user_pages - lock user pages into memory
+ * @start_page: the start page
+ * @num_pages: the number of pages
+ * @p: the output page structures
+ *
+ * This function takes a given start page (page aligned user virtual
+ * address) and pins it and the following specified number of pages. For
+ * now, num_pages is always 1, but that will probably change at some point
+ * (because caller is doing expected sends on a single virtually contiguous
+ * buffer, so we can do all pages at once).
+ */
+int ipath_get_user_pages(unsigned long start_page, size_t num_pages,
+ struct page **p)
+{
+ int ret;
+
+ down_write(&current->mm->mmap_sem);
+
+ ret = __get_user_pages(start_page, num_pages, p, NULL);
+
+ up_write(&current->mm->mmap_sem);
+
+ return ret;
+}
+
+/**
+ * ipath_get_user_pages_nocopy - lock a single page for I/O and mark shared
+ * @start_page: the page to lock
+ * @p: the output page structure
+ *
+ * This is similar to ipath_get_user_pages, but it's always one page, and we
+ * mark the page as locked for I/O, and shared. This is used for the user
+ * process page that contains the destination address for the rcvhdrq tail
+ * update, so we need to have the vma. If we don't do this, the page can be
+ * taken away from us on fork, even if the child never touches it, and then
+ * the user process never sees the tail register updates.
+ */
+int ipath_get_user_pages_nocopy(unsigned long page, struct page **p)
+{
+ struct vm_area_struct *vma;
+ int ret;
+
+ down_write(&current->mm->mmap_sem);
+
+ ret = __get_user_pages(page, 1, p, &vma);
+
+ up_write(&current->mm->mmap_sem);
+
+ return ret;
+}
+
+void ipath_release_user_pages(struct page **p, size_t num_pages)
+{
+ down_write(&current->mm->mmap_sem);
+
+ __ipath_release_user_pages(p, num_pages, 1);
+
+ current->mm->locked_vm -= num_pages;
+
+ up_write(&current->mm->mmap_sem);
+}
+
+struct ipath_user_pages_work {
+ struct work_struct work;
+ struct mm_struct *mm;
+ unsigned long num_pages;
+};
+
+static void user_pages_account(void *ptr)
+{
+ struct ipath_user_pages_work *work = ptr;
+
+ down_write(&work->mm->mmap_sem);
+ work->mm->locked_vm -= work->num_pages;
+ up_write(&work->mm->mmap_sem);
+ mmput(work->mm);
+ kfree(work);
+}
+
+void ipath_release_user_pages_on_close(struct page **p, size_t num_pages)
+{
+ struct ipath_user_pages_work *work;
+ struct mm_struct *mm;
+
+ __ipath_release_user_pages(p, num_pages, 1);
+
+ mm = get_task_mm(current);
+ if (!mm)
+ goto bail;
+
+ work = kmalloc(sizeof(*work), GFP_KERNEL);
+ if (!work)
+ goto bail_mm;
+
+ goto bail;
+
+ INIT_WORK(&work->work, user_pages_account, work);
+ work->mm = mm;
+ work->num_pages = num_pages;
+
+bail_mm:
+ mmput(mm);
+bail:
+ return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
new file mode 100644
index 00000000000..28fdbdaa789
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -0,0 +1,1204 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_mad.h>
+#include <rdma/ib_user_verbs.h>
+#include <linux/utsname.h>
+
+#include "ipath_kernel.h"
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+/* Not static, because we don't want the compiler removing it */
+const char ipath_verbs_version[] = "ipath_verbs " IPATH_IDSTR;
+
+static unsigned int ib_ipath_qp_table_size = 251;
+module_param_named(qp_table_size, ib_ipath_qp_table_size, uint, S_IRUGO);
+MODULE_PARM_DESC(qp_table_size, "QP table size");
+
+unsigned int ib_ipath_lkey_table_size = 12;
+module_param_named(lkey_table_size, ib_ipath_lkey_table_size, uint,
+ S_IRUGO);
+MODULE_PARM_DESC(lkey_table_size,
+ "LKEY table size in bits (2^n, 1 <= n <= 23)");
+
+unsigned int ib_ipath_debug; /* debug mask */
+module_param_named(debug, ib_ipath_debug, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(debug, "Verbs debug mask");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("PathScale <support@pathscale.com>");
+MODULE_DESCRIPTION("Pathscale InfiniPath driver");
+
+const int ib_ipath_state_ops[IB_QPS_ERR + 1] = {
+ [IB_QPS_RESET] = 0,
+ [IB_QPS_INIT] = IPATH_POST_RECV_OK,
+ [IB_QPS_RTR] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK,
+ [IB_QPS_RTS] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK |
+ IPATH_POST_SEND_OK | IPATH_PROCESS_SEND_OK,
+ [IB_QPS_SQD] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK |
+ IPATH_POST_SEND_OK,
+ [IB_QPS_SQE] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK,
+ [IB_QPS_ERR] = 0,
+};
+
+/*
+ * Translate ib_wr_opcode into ib_wc_opcode.
+ */
+const enum ib_wc_opcode ib_ipath_wc_opcode[] = {
+ [IB_WR_RDMA_WRITE] = IB_WC_RDMA_WRITE,
+ [IB_WR_RDMA_WRITE_WITH_IMM] = IB_WC_RDMA_WRITE,
+ [IB_WR_SEND] = IB_WC_SEND,
+ [IB_WR_SEND_WITH_IMM] = IB_WC_SEND,
+ [IB_WR_RDMA_READ] = IB_WC_RDMA_READ,
+ [IB_WR_ATOMIC_CMP_AND_SWP] = IB_WC_COMP_SWAP,
+ [IB_WR_ATOMIC_FETCH_AND_ADD] = IB_WC_FETCH_ADD
+};
+
+/*
+ * System image GUID.
+ */
+static __be64 sys_image_guid;
+
+/**
+ * ipath_copy_sge - copy data to SGE memory
+ * @ss: the SGE state
+ * @data: the data to copy
+ * @length: the length of the data
+ */
+void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length)
+{
+ struct ipath_sge *sge = &ss->sge;
+
+ while (length) {
+ u32 len = sge->length;
+
+ BUG_ON(len == 0);
+ if (len > length)
+ len = length;
+ memcpy(sge->vaddr, data, len);
+ sge->vaddr += len;
+ sge->length -= len;
+ sge->sge_length -= len;
+ if (sge->sge_length == 0) {
+ if (--ss->num_sge)
+ *sge = *ss->sg_list++;
+ } else if (sge->length == 0 && sge->mr != NULL) {
+ if (++sge->n >= IPATH_SEGSZ) {
+ if (++sge->m >= sge->mr->mapsz)
+ break;
+ sge->n = 0;
+ }
+ sge->vaddr =
+ sge->mr->map[sge->m]->segs[sge->n].vaddr;
+ sge->length =
+ sge->mr->map[sge->m]->segs[sge->n].length;
+ }
+ data += len;
+ length -= len;
+ }
+}
+
+/**
+ * ipath_skip_sge - skip over SGE memory - XXX almost dup of prev func
+ * @ss: the SGE state
+ * @length: the number of bytes to skip
+ */
+void ipath_skip_sge(struct ipath_sge_state *ss, u32 length)
+{
+ struct ipath_sge *sge = &ss->sge;
+
+ while (length > sge->sge_length) {
+ length -= sge->sge_length;
+ ss->sge = *ss->sg_list++;
+ }
+ while (length) {
+ u32 len = sge->length;
+
+ BUG_ON(len == 0);
+ if (len > length)
+ len = length;
+ sge->vaddr += len;
+ sge->length -= len;
+ sge->sge_length -= len;
+ if (sge->sge_length == 0) {
+ if (--ss->num_sge)
+ *sge = *ss->sg_list++;
+ } else if (sge->length == 0 && sge->mr != NULL) {
+ if (++sge->n >= IPATH_SEGSZ) {
+ if (++sge->m >= sge->mr->mapsz)
+ break;
+ sge->n = 0;
+ }
+ sge->vaddr =
+ sge->mr->map[sge->m]->segs[sge->n].vaddr;
+ sge->length =
+ sge->mr->map[sge->m]->segs[sge->n].length;
+ }
+ length -= len;
+ }
+}
+
+/**
+ * ipath_post_send - post a send on a QP
+ * @ibqp: the QP to post the send on
+ * @wr: the list of work requests to post
+ * @bad_wr: the first bad WR is put here
+ *
+ * This may be called from interrupt context.
+ */
+static int ipath_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ struct ib_send_wr **bad_wr)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+ int err = 0;
+
+ /* Check that state is OK to post send. */
+ if (!(ib_ipath_state_ops[qp->state] & IPATH_POST_SEND_OK)) {
+ *bad_wr = wr;
+ err = -EINVAL;
+ goto bail;
+ }
+
+ for (; wr; wr = wr->next) {
+ switch (qp->ibqp.qp_type) {
+ case IB_QPT_UC:
+ case IB_QPT_RC:
+ err = ipath_post_rc_send(qp, wr);
+ break;
+
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
+ case IB_QPT_UD:
+ err = ipath_post_ud_send(qp, wr);
+ break;
+
+ default:
+ err = -EINVAL;
+ }
+ if (err) {
+ *bad_wr = wr;
+ break;
+ }
+ }
+
+bail:
+ return err;
+}
+
+/**
+ * ipath_post_receive - post a receive on a QP
+ * @ibqp: the QP to post the receive on
+ * @wr: the WR to post
+ * @bad_wr: the first bad WR is put here
+ *
+ * This may be called from interrupt context.
+ */
+static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+ unsigned long flags;
+ int ret;
+
+ /* Check that state is OK to post receive. */
+ if (!(ib_ipath_state_ops[qp->state] & IPATH_POST_RECV_OK)) {
+ *bad_wr = wr;
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ for (; wr; wr = wr->next) {
+ struct ipath_rwqe *wqe;
+ u32 next;
+ int i, j;
+
+ if (wr->num_sge > qp->r_rq.max_sge) {
+ *bad_wr = wr;
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ spin_lock_irqsave(&qp->r_rq.lock, flags);
+ next = qp->r_rq.head + 1;
+ if (next >= qp->r_rq.size)
+ next = 0;
+ if (next == qp->r_rq.tail) {
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ *bad_wr = wr;
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ wqe = get_rwqe_ptr(&qp->r_rq, qp->r_rq.head);
+ wqe->wr_id = wr->wr_id;
+ wqe->sg_list[0].mr = NULL;
+ wqe->sg_list[0].vaddr = NULL;
+ wqe->sg_list[0].length = 0;
+ wqe->sg_list[0].sge_length = 0;
+ wqe->length = 0;
+ for (i = 0, j = 0; i < wr->num_sge; i++) {
+ /* Check LKEY */
+ if (to_ipd(qp->ibqp.pd)->user &&
+ wr->sg_list[i].lkey == 0) {
+ spin_unlock_irqrestore(&qp->r_rq.lock,
+ flags);
+ *bad_wr = wr;
+ ret = -EINVAL;
+ goto bail;
+ }
+ if (wr->sg_list[i].length == 0)
+ continue;
+ if (!ipath_lkey_ok(
+ &to_idev(qp->ibqp.device)->lk_table,
+ &wqe->sg_list[j], &wr->sg_list[i],
+ IB_ACCESS_LOCAL_WRITE)) {
+ spin_unlock_irqrestore(&qp->r_rq.lock,
+ flags);
+ *bad_wr = wr;
+ ret = -EINVAL;
+ goto bail;
+ }
+ wqe->length += wr->sg_list[i].length;
+ j++;
+ }
+ wqe->num_sge = j;
+ qp->r_rq.head = next;
+ spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+ }
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_qp_rcv - processing an incoming packet on a QP
+ * @dev: the device the packet came on
+ * @hdr: the packet header
+ * @has_grh: true if the packet has a GRH
+ * @data: the packet data
+ * @tlen: the packet length
+ * @qp: the QP the packet came on
+ *
+ * This is called from ipath_ib_rcv() to process an incoming packet
+ * for the given QP.
+ * Called at interrupt level.
+ */
+static void ipath_qp_rcv(struct ipath_ibdev *dev,
+ struct ipath_ib_header *hdr, int has_grh,
+ void *data, u32 tlen, struct ipath_qp *qp)
+{
+ /* Check for valid receive state. */
+ if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) {
+ dev->n_pkt_drops++;
+ return;
+ }
+
+ switch (qp->ibqp.qp_type) {
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
+ case IB_QPT_UD:
+ ipath_ud_rcv(dev, hdr, has_grh, data, tlen, qp);
+ break;
+
+ case IB_QPT_RC:
+ ipath_rc_rcv(dev, hdr, has_grh, data, tlen, qp);
+ break;
+
+ case IB_QPT_UC:
+ ipath_uc_rcv(dev, hdr, has_grh, data, tlen, qp);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * ipath_ib_rcv - process and incoming packet
+ * @arg: the device pointer
+ * @rhdr: the header of the packet
+ * @data: the packet data
+ * @tlen: the packet length
+ *
+ * This is called from ipath_kreceive() to process an incoming packet at
+ * interrupt level. Tlen is the length of the header + data + CRC in bytes.
+ */
+static void ipath_ib_rcv(void *arg, void *rhdr, void *data, u32 tlen)
+{
+ struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
+ struct ipath_ib_header *hdr = rhdr;
+ struct ipath_other_headers *ohdr;
+ struct ipath_qp *qp;
+ u32 qp_num;
+ int lnh;
+ u8 opcode;
+ u16 lid;
+
+ if (unlikely(dev == NULL))
+ goto bail;
+
+ if (unlikely(tlen < 24)) { /* LRH+BTH+CRC */
+ dev->rcv_errors++;
+ goto bail;
+ }
+
+ /* Check for a valid destination LID (see ch. 7.11.1). */
+ lid = be16_to_cpu(hdr->lrh[1]);
+ if (lid < IPS_MULTICAST_LID_BASE) {
+ lid &= ~((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+ if (unlikely(lid != ipath_layer_get_lid(dev->dd))) {
+ dev->rcv_errors++;
+ goto bail;
+ }
+ }
+
+ /* Check for GRH */
+ lnh = be16_to_cpu(hdr->lrh[0]) & 3;
+ if (lnh == IPS_LRH_BTH)
+ ohdr = &hdr->u.oth;
+ else if (lnh == IPS_LRH_GRH)
+ ohdr = &hdr->u.l.oth;
+ else {
+ dev->rcv_errors++;
+ goto bail;
+ }
+
+ opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+ dev->opstats[opcode].n_bytes += tlen;
+ dev->opstats[opcode].n_packets++;
+
+ /* Get the destination QP number. */
+ qp_num = be32_to_cpu(ohdr->bth[1]) & IPS_QPN_MASK;
+ if (qp_num == IPS_MULTICAST_QPN) {
+ struct ipath_mcast *mcast;
+ struct ipath_mcast_qp *p;
+
+ mcast = ipath_mcast_find(&hdr->u.l.grh.dgid);
+ if (mcast == NULL) {
+ dev->n_pkt_drops++;
+ goto bail;
+ }
+ dev->n_multicast_rcv++;
+ list_for_each_entry_rcu(p, &mcast->qp_list, list)
+ ipath_qp_rcv(dev, hdr, lnh == IPS_LRH_GRH, data,
+ tlen, p->qp);
+ /*
+ * Notify ipath_multicast_detach() if it is waiting for us
+ * to finish.
+ */
+ if (atomic_dec_return(&mcast->refcount) <= 1)
+ wake_up(&mcast->wait);
+ } else {
+ qp = ipath_lookup_qpn(&dev->qp_table, qp_num);
+ if (qp) {
+ dev->n_unicast_rcv++;
+ ipath_qp_rcv(dev, hdr, lnh == IPS_LRH_GRH, data,
+ tlen, qp);
+ /*
+ * Notify ipath_destroy_qp() if it is waiting
+ * for us to finish.
+ */
+ if (atomic_dec_and_test(&qp->refcount))
+ wake_up(&qp->wait);
+ } else
+ dev->n_pkt_drops++;
+ }
+
+bail:;
+}
+
+/**
+ * ipath_ib_timer - verbs timer
+ * @arg: the device pointer
+ *
+ * This is called from ipath_do_rcv_timer() at interrupt level to check for
+ * QPs which need retransmits and to collect performance numbers.
+ */
+static void ipath_ib_timer(void *arg)
+{
+ struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
+ struct ipath_qp *resend = NULL;
+ struct list_head *last;
+ struct ipath_qp *qp;
+ unsigned long flags;
+
+ if (dev == NULL)
+ return;
+
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ /* Start filling the next pending queue. */
+ if (++dev->pending_index >= ARRAY_SIZE(dev->pending))
+ dev->pending_index = 0;
+ /* Save any requests still in the new queue, they have timed out. */
+ last = &dev->pending[dev->pending_index];
+ while (!list_empty(last)) {
+ qp = list_entry(last->next, struct ipath_qp, timerwait);
+ list_del_init(&qp->timerwait);
+ qp->timer_next = resend;
+ resend = qp;
+ atomic_inc(&qp->refcount);
+ }
+ last = &dev->rnrwait;
+ if (!list_empty(last)) {
+ qp = list_entry(last->next, struct ipath_qp, timerwait);
+ if (--qp->s_rnr_timeout == 0) {
+ do {
+ list_del_init(&qp->timerwait);
+ tasklet_hi_schedule(&qp->s_task);
+ if (list_empty(last))
+ break;
+ qp = list_entry(last->next, struct ipath_qp,
+ timerwait);
+ } while (qp->s_rnr_timeout == 0);
+ }
+ }
+ /*
+ * We should only be in the started state if pma_sample_start != 0
+ */
+ if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_STARTED &&
+ --dev->pma_sample_start == 0) {
+ dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_RUNNING;
+ ipath_layer_snapshot_counters(dev->dd, &dev->ipath_sword,
+ &dev->ipath_rword,
+ &dev->ipath_spkts,
+ &dev->ipath_rpkts,
+ &dev->ipath_xmit_wait);
+ }
+ if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_RUNNING) {
+ if (dev->pma_sample_interval == 0) {
+ u64 ta, tb, tc, td, te;
+
+ dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_DONE;
+ ipath_layer_snapshot_counters(dev->dd, &ta, &tb,
+ &tc, &td, &te);
+
+ dev->ipath_sword = ta - dev->ipath_sword;
+ dev->ipath_rword = tb - dev->ipath_rword;
+ dev->ipath_spkts = tc - dev->ipath_spkts;
+ dev->ipath_rpkts = td - dev->ipath_rpkts;
+ dev->ipath_xmit_wait = te - dev->ipath_xmit_wait;
+ }
+ else
+ dev->pma_sample_interval--;
+ }
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+ /* XXX What if timer fires again while this is running? */
+ for (qp = resend; qp != NULL; qp = qp->timer_next) {
+ struct ib_wc wc;
+
+ spin_lock_irqsave(&qp->s_lock, flags);
+ if (qp->s_last != qp->s_tail && qp->state == IB_QPS_RTS) {
+ dev->n_timeouts++;
+ ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
+ }
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+
+ /* Notify ipath_destroy_qp() if it is waiting. */
+ if (atomic_dec_and_test(&qp->refcount))
+ wake_up(&qp->wait);
+ }
+}
+
+/**
+ * ipath_ib_piobufavail - callback when a PIO buffer is available
+ * @arg: the device pointer
+ *
+ * This is called from ipath_intr() at interrupt level when a PIO buffer is
+ * available after ipath_verbs_send() returned an error that no buffers were
+ * available. Return 1 if we consumed all the PIO buffers and we still have
+ * QPs waiting for buffers (for now, just do a tasklet_hi_schedule and
+ * return zero).
+ */
+static int ipath_ib_piobufavail(void *arg)
+{
+ struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
+ struct ipath_qp *qp;
+ unsigned long flags;
+
+ if (dev == NULL)
+ goto bail;
+
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ while (!list_empty(&dev->piowait)) {
+ qp = list_entry(dev->piowait.next, struct ipath_qp,
+ piowait);
+ list_del_init(&qp->piowait);
+ tasklet_hi_schedule(&qp->s_task);
+ }
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+bail:
+ return 0;
+}
+
+static int ipath_query_device(struct ib_device *ibdev,
+ struct ib_device_attr *props)
+{
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ u32 vendor, boardrev, majrev, minrev;
+
+ memset(props, 0, sizeof(*props));
+
+ props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR |
+ IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT |
+ IB_DEVICE_SYS_IMAGE_GUID;
+ ipath_layer_query_device(dev->dd, &vendor, &boardrev,
+ &majrev, &minrev);
+ props->vendor_id = vendor;
+ props->vendor_part_id = boardrev;
+ props->hw_ver = boardrev << 16 | majrev << 8 | minrev;
+
+ props->sys_image_guid = dev->sys_image_guid;
+
+ props->max_mr_size = ~0ull;
+ props->max_qp = 0xffff;
+ props->max_qp_wr = 0xffff;
+ props->max_sge = 255;
+ props->max_cq = 0xffff;
+ props->max_cqe = 0xffff;
+ props->max_mr = 0xffff;
+ props->max_pd = 0xffff;
+ props->max_qp_rd_atom = 1;
+ props->max_qp_init_rd_atom = 1;
+ /* props->max_res_rd_atom */
+ props->max_srq = 0xffff;
+ props->max_srq_wr = 0xffff;
+ props->max_srq_sge = 255;
+ /* props->local_ca_ack_delay */
+ props->atomic_cap = IB_ATOMIC_HCA;
+ props->max_pkeys = ipath_layer_get_npkeys(dev->dd);
+ props->max_mcast_grp = 0xffff;
+ props->max_mcast_qp_attach = 0xffff;
+ props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
+ props->max_mcast_grp;
+
+ return 0;
+}
+
+const u8 ipath_cvt_physportstate[16] = {
+ [INFINIPATH_IBCS_LT_STATE_DISABLED] = 3,
+ [INFINIPATH_IBCS_LT_STATE_LINKUP] = 5,
+ [INFINIPATH_IBCS_LT_STATE_POLLACTIVE] = 2,
+ [INFINIPATH_IBCS_LT_STATE_POLLQUIET] = 2,
+ [INFINIPATH_IBCS_LT_STATE_SLEEPDELAY] = 1,
+ [INFINIPATH_IBCS_LT_STATE_SLEEPQUIET] = 1,
+ [INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE] = 4,
+ [INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG] = 4,
+ [INFINIPATH_IBCS_LT_STATE_CFGWAITRMT] = 4,
+ [INFINIPATH_IBCS_LT_STATE_CFGIDLE] = 4,
+ [INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN] = 6,
+ [INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT] = 6,
+ [INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] = 6,
+};
+
+static int ipath_query_port(struct ib_device *ibdev,
+ u8 port, struct ib_port_attr *props)
+{
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ enum ib_mtu mtu;
+ u16 lid = ipath_layer_get_lid(dev->dd);
+ u64 ibcstat;
+
+ memset(props, 0, sizeof(*props));
+ props->lid = lid ? lid : __constant_be16_to_cpu(IB_LID_PERMISSIVE);
+ props->lmc = dev->mkeyprot_resv_lmc & 7;
+ props->sm_lid = dev->sm_lid;
+ props->sm_sl = dev->sm_sl;
+ ibcstat = ipath_layer_get_lastibcstat(dev->dd);
+ props->state = ((ibcstat >> 4) & 0x3) + 1;
+ /* See phys_state_show() */
+ props->phys_state = ipath_cvt_physportstate[
+ ipath_layer_get_lastibcstat(dev->dd) & 0xf];
+ props->port_cap_flags = dev->port_cap_flags;
+ props->gid_tbl_len = 1;
+ props->max_msg_sz = 4096;
+ props->pkey_tbl_len = ipath_layer_get_npkeys(dev->dd);
+ props->bad_pkey_cntr = ipath_layer_get_cr_errpkey(dev->dd) -
+ dev->n_pkey_violations;
+ props->qkey_viol_cntr = dev->qkey_violations;
+ props->active_width = IB_WIDTH_4X;
+ /* See rate_show() */
+ props->active_speed = 1; /* Regular 10Mbs speed. */
+ props->max_vl_num = 1; /* VLCap = VL0 */
+ props->init_type_reply = 0;
+
+ props->max_mtu = IB_MTU_4096;
+ switch (ipath_layer_get_ibmtu(dev->dd)) {
+ case 4096:
+ mtu = IB_MTU_4096;
+ break;
+ case 2048:
+ mtu = IB_MTU_2048;
+ break;
+ case 1024:
+ mtu = IB_MTU_1024;
+ break;
+ case 512:
+ mtu = IB_MTU_512;
+ break;
+ case 256:
+ mtu = IB_MTU_256;
+ break;
+ default:
+ mtu = IB_MTU_2048;
+ }
+ props->active_mtu = mtu;
+ props->subnet_timeout = dev->subnet_timeout;
+
+ return 0;
+}
+
+static int ipath_modify_device(struct ib_device *device,
+ int device_modify_mask,
+ struct ib_device_modify *device_modify)
+{
+ int ret;
+
+ if (device_modify_mask & ~(IB_DEVICE_MODIFY_SYS_IMAGE_GUID |
+ IB_DEVICE_MODIFY_NODE_DESC)) {
+ ret = -EOPNOTSUPP;
+ goto bail;
+ }
+
+ if (device_modify_mask & IB_DEVICE_MODIFY_NODE_DESC)
+ memcpy(device->node_desc, device_modify->node_desc, 64);
+
+ if (device_modify_mask & IB_DEVICE_MODIFY_SYS_IMAGE_GUID)
+ to_idev(device)->sys_image_guid =
+ cpu_to_be64(device_modify->sys_image_guid);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static int ipath_modify_port(struct ib_device *ibdev,
+ u8 port, int port_modify_mask,
+ struct ib_port_modify *props)
+{
+ struct ipath_ibdev *dev = to_idev(ibdev);
+
+ dev->port_cap_flags |= props->set_port_cap_mask;
+ dev->port_cap_flags &= ~props->clr_port_cap_mask;
+ if (port_modify_mask & IB_PORT_SHUTDOWN)
+ ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKDOWN);
+ if (port_modify_mask & IB_PORT_RESET_QKEY_CNTR)
+ dev->qkey_violations = 0;
+ return 0;
+}
+
+static int ipath_query_gid(struct ib_device *ibdev, u8 port,
+ int index, union ib_gid *gid)
+{
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ int ret;
+
+ if (index >= 1) {
+ ret = -EINVAL;
+ goto bail;
+ }
+ gid->global.subnet_prefix = dev->gid_prefix;
+ gid->global.interface_id = ipath_layer_get_guid(dev->dd);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static struct ib_pd *ipath_alloc_pd(struct ib_device *ibdev,
+ struct ib_ucontext *context,
+ struct ib_udata *udata)
+{
+ struct ipath_pd *pd;
+ struct ib_pd *ret;
+
+ pd = kmalloc(sizeof *pd, GFP_KERNEL);
+ if (!pd) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /* ib_alloc_pd() will initialize pd->ibpd. */
+ pd->user = udata != NULL;
+
+ ret = &pd->ibpd;
+
+bail:
+ return ret;
+}
+
+static int ipath_dealloc_pd(struct ib_pd *ibpd)
+{
+ struct ipath_pd *pd = to_ipd(ibpd);
+
+ kfree(pd);
+
+ return 0;
+}
+
+/**
+ * ipath_create_ah - create an address handle
+ * @pd: the protection domain
+ * @ah_attr: the attributes of the AH
+ *
+ * This may be called from interrupt context.
+ */
+static struct ib_ah *ipath_create_ah(struct ib_pd *pd,
+ struct ib_ah_attr *ah_attr)
+{
+ struct ipath_ah *ah;
+ struct ib_ah *ret;
+
+ /* A multicast address requires a GRH (see ch. 8.4.1). */
+ if (ah_attr->dlid >= IPS_MULTICAST_LID_BASE &&
+ ah_attr->dlid != IPS_PERMISSIVE_LID &&
+ !(ah_attr->ah_flags & IB_AH_GRH)) {
+ ret = ERR_PTR(-EINVAL);
+ goto bail;
+ }
+
+ ah = kmalloc(sizeof *ah, GFP_ATOMIC);
+ if (!ah) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /* ib_create_ah() will initialize ah->ibah. */
+ ah->attr = *ah_attr;
+
+ ret = &ah->ibah;
+
+bail:
+ return ret;
+}
+
+/**
+ * ipath_destroy_ah - destroy an address handle
+ * @ibah: the AH to destroy
+ *
+ * This may be called from interrupt context.
+ */
+static int ipath_destroy_ah(struct ib_ah *ibah)
+{
+ struct ipath_ah *ah = to_iah(ibah);
+
+ kfree(ah);
+
+ return 0;
+}
+
+static int ipath_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
+{
+ struct ipath_ah *ah = to_iah(ibah);
+
+ *ah_attr = ah->attr;
+
+ return 0;
+}
+
+static int ipath_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
+ u16 *pkey)
+{
+ struct ipath_ibdev *dev = to_idev(ibdev);
+ int ret;
+
+ if (index >= ipath_layer_get_npkeys(dev->dd)) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ *pkey = ipath_layer_get_pkey(dev->dd, index);
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+
+/**
+ * ipath_alloc_ucontext - allocate a ucontest
+ * @ibdev: the infiniband device
+ * @udata: not used by the InfiniPath driver
+ */
+
+static struct ib_ucontext *ipath_alloc_ucontext(struct ib_device *ibdev,
+ struct ib_udata *udata)
+{
+ struct ipath_ucontext *context;
+ struct ib_ucontext *ret;
+
+ context = kmalloc(sizeof *context, GFP_KERNEL);
+ if (!context) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ ret = &context->ibucontext;
+
+bail:
+ return ret;
+}
+
+static int ipath_dealloc_ucontext(struct ib_ucontext *context)
+{
+ kfree(to_iucontext(context));
+ return 0;
+}
+
+static int ipath_verbs_register_sysfs(struct ib_device *dev);
+
+/**
+ * ipath_register_ib_device - register our device with the infiniband core
+ * @unit: the device number to register
+ * @dd: the device data structure
+ * Return the allocated ipath_ibdev pointer or NULL on error.
+ */
+static void *ipath_register_ib_device(int unit, struct ipath_devdata *dd)
+{
+ struct ipath_ibdev *idev;
+ struct ib_device *dev;
+ int ret;
+
+ idev = (struct ipath_ibdev *)ib_alloc_device(sizeof *idev);
+ if (idev == NULL)
+ goto bail;
+
+ dev = &idev->ibdev;
+
+ /* Only need to initialize non-zero fields. */
+ spin_lock_init(&idev->qp_table.lock);
+ spin_lock_init(&idev->lk_table.lock);
+ idev->sm_lid = __constant_be16_to_cpu(IB_LID_PERMISSIVE);
+ /* Set the prefix to the default value (see ch. 4.1.1) */
+ idev->gid_prefix = __constant_cpu_to_be64(0xfe80000000000000ULL);
+
+ ret = ipath_init_qp_table(idev, ib_ipath_qp_table_size);
+ if (ret)
+ goto err_qp;
+
+ /*
+ * The top ib_ipath_lkey_table_size bits are used to index the
+ * table. The lower 8 bits can be owned by the user (copied from
+ * the LKEY). The remaining bits act as a generation number or tag.
+ */
+ idev->lk_table.max = 1 << ib_ipath_lkey_table_size;
+ idev->lk_table.table = kzalloc(idev->lk_table.max *
+ sizeof(*idev->lk_table.table),
+ GFP_KERNEL);
+ if (idev->lk_table.table == NULL) {
+ ret = -ENOMEM;
+ goto err_lk;
+ }
+ spin_lock_init(&idev->pending_lock);
+ INIT_LIST_HEAD(&idev->pending[0]);
+ INIT_LIST_HEAD(&idev->pending[1]);
+ INIT_LIST_HEAD(&idev->pending[2]);
+ INIT_LIST_HEAD(&idev->piowait);
+ INIT_LIST_HEAD(&idev->rnrwait);
+ idev->pending_index = 0;
+ idev->port_cap_flags =
+ IB_PORT_SYS_IMAGE_GUID_SUP | IB_PORT_CLIENT_REG_SUP;
+ idev->pma_counter_select[0] = IB_PMA_PORT_XMIT_DATA;
+ idev->pma_counter_select[1] = IB_PMA_PORT_RCV_DATA;
+ idev->pma_counter_select[2] = IB_PMA_PORT_XMIT_PKTS;
+ idev->pma_counter_select[3] = IB_PMA_PORT_RCV_PKTS;
+ idev->pma_counter_select[5] = IB_PMA_PORT_XMIT_WAIT;
+ idev->link_width_enabled = 3; /* 1x or 4x */
+
+ /*
+ * The system image GUID is supposed to be the same for all
+ * IB HCAs in a single system but since there can be other
+ * device types in the system, we can't be sure this is unique.
+ */
+ if (!sys_image_guid)
+ sys_image_guid = ipath_layer_get_guid(dd);
+ idev->sys_image_guid = sys_image_guid;
+ idev->ib_unit = unit;
+ idev->dd = dd;
+
+ strlcpy(dev->name, "ipath%d", IB_DEVICE_NAME_MAX);
+ dev->owner = THIS_MODULE;
+ dev->node_guid = ipath_layer_get_guid(dd);
+ dev->uverbs_abi_ver = IPATH_UVERBS_ABI_VERSION;
+ dev->uverbs_cmd_mask =
+ (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_PORT) |
+ (1ull << IB_USER_VERBS_CMD_ALLOC_PD) |
+ (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_AH) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_AH) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_AH) |
+ (1ull << IB_USER_VERBS_CMD_REG_MR) |
+ (1ull << IB_USER_VERBS_CMD_DEREG_MR) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
+ (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
+ (1ull << IB_USER_VERBS_CMD_POLL_CQ) |
+ (1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_QP) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_QP) |
+ (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
+ (1ull << IB_USER_VERBS_CMD_POST_SEND) |
+ (1ull << IB_USER_VERBS_CMD_POST_RECV) |
+ (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) |
+ (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_POST_SRQ_RECV);
+ dev->node_type = IB_NODE_CA;
+ dev->phys_port_cnt = 1;
+ dev->dma_device = ipath_layer_get_device(dd);
+ dev->class_dev.dev = dev->dma_device;
+ dev->query_device = ipath_query_device;
+ dev->modify_device = ipath_modify_device;
+ dev->query_port = ipath_query_port;
+ dev->modify_port = ipath_modify_port;
+ dev->query_pkey = ipath_query_pkey;
+ dev->query_gid = ipath_query_gid;
+ dev->alloc_ucontext = ipath_alloc_ucontext;
+ dev->dealloc_ucontext = ipath_dealloc_ucontext;
+ dev->alloc_pd = ipath_alloc_pd;
+ dev->dealloc_pd = ipath_dealloc_pd;
+ dev->create_ah = ipath_create_ah;
+ dev->destroy_ah = ipath_destroy_ah;
+ dev->query_ah = ipath_query_ah;
+ dev->create_srq = ipath_create_srq;
+ dev->modify_srq = ipath_modify_srq;
+ dev->query_srq = ipath_query_srq;
+ dev->destroy_srq = ipath_destroy_srq;
+ dev->create_qp = ipath_create_qp;
+ dev->modify_qp = ipath_modify_qp;
+ dev->query_qp = ipath_query_qp;
+ dev->destroy_qp = ipath_destroy_qp;
+ dev->post_send = ipath_post_send;
+ dev->post_recv = ipath_post_receive;
+ dev->post_srq_recv = ipath_post_srq_receive;
+ dev->create_cq = ipath_create_cq;
+ dev->destroy_cq = ipath_destroy_cq;
+ dev->resize_cq = ipath_resize_cq;
+ dev->poll_cq = ipath_poll_cq;
+ dev->req_notify_cq = ipath_req_notify_cq;
+ dev->get_dma_mr = ipath_get_dma_mr;
+ dev->reg_phys_mr = ipath_reg_phys_mr;
+ dev->reg_user_mr = ipath_reg_user_mr;
+ dev->dereg_mr = ipath_dereg_mr;
+ dev->alloc_fmr = ipath_alloc_fmr;
+ dev->map_phys_fmr = ipath_map_phys_fmr;
+ dev->unmap_fmr = ipath_unmap_fmr;
+ dev->dealloc_fmr = ipath_dealloc_fmr;
+ dev->attach_mcast = ipath_multicast_attach;
+ dev->detach_mcast = ipath_multicast_detach;
+ dev->process_mad = ipath_process_mad;
+
+ snprintf(dev->node_desc, sizeof(dev->node_desc),
+ IPATH_IDSTR " %s kernel_SMA", system_utsname.nodename);
+
+ ret = ib_register_device(dev);
+ if (ret)
+ goto err_reg;
+
+ if (ipath_verbs_register_sysfs(dev))
+ goto err_class;
+
+ ipath_layer_enable_timer(dd);
+
+ goto bail;
+
+err_class:
+ ib_unregister_device(dev);
+err_reg:
+ kfree(idev->lk_table.table);
+err_lk:
+ kfree(idev->qp_table.table);
+err_qp:
+ ib_dealloc_device(dev);
+ _VERBS_ERROR("ib_ipath%d cannot register verbs (%d)!\n",
+ unit, -ret);
+ idev = NULL;
+
+bail:
+ return idev;
+}
+
+static void ipath_unregister_ib_device(void *arg)
+{
+ struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
+ struct ib_device *ibdev = &dev->ibdev;
+
+ ipath_layer_disable_timer(dev->dd);
+
+ ib_unregister_device(ibdev);
+
+ if (!list_empty(&dev->pending[0]) ||
+ !list_empty(&dev->pending[1]) ||
+ !list_empty(&dev->pending[2]))
+ _VERBS_ERROR("ipath%d pending list not empty!\n",
+ dev->ib_unit);
+ if (!list_empty(&dev->piowait))
+ _VERBS_ERROR("ipath%d piowait list not empty!\n",
+ dev->ib_unit);
+ if (!list_empty(&dev->rnrwait))
+ _VERBS_ERROR("ipath%d rnrwait list not empty!\n",
+ dev->ib_unit);
+ if (!ipath_mcast_tree_empty())
+ _VERBS_ERROR("ipath%d multicast table memory leak!\n",
+ dev->ib_unit);
+ /*
+ * Note that ipath_unregister_ib_device() can be called before all
+ * the QPs are destroyed!
+ */
+ ipath_free_all_qps(&dev->qp_table);
+ kfree(dev->qp_table.table);
+ kfree(dev->lk_table.table);
+ ib_dealloc_device(ibdev);
+}
+
+static int __init ipath_verbs_init(void)
+{
+ return ipath_verbs_register(ipath_register_ib_device,
+ ipath_unregister_ib_device,
+ ipath_ib_piobufavail, ipath_ib_rcv,
+ ipath_ib_timer);
+}
+
+static void __exit ipath_verbs_cleanup(void)
+{
+ ipath_verbs_unregister();
+}
+
+static ssize_t show_rev(struct class_device *cdev, char *buf)
+{
+ struct ipath_ibdev *dev =
+ container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+ int vendor, boardrev, majrev, minrev;
+
+ ipath_layer_query_device(dev->dd, &vendor, &boardrev,
+ &majrev, &minrev);
+ return sprintf(buf, "%d.%d\n", majrev, minrev);
+}
+
+static ssize_t show_hca(struct class_device *cdev, char *buf)
+{
+ struct ipath_ibdev *dev =
+ container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+ int ret;
+
+ ret = ipath_layer_get_boardname(dev->dd, buf, 128);
+ if (ret < 0)
+ goto bail;
+ strcat(buf, "\n");
+ ret = strlen(buf);
+
+bail:
+ return ret;
+}
+
+static ssize_t show_stats(struct class_device *cdev, char *buf)
+{
+ struct ipath_ibdev *dev =
+ container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+ int i;
+ int len;
+
+ len = sprintf(buf,
+ "RC resends %d\n"
+ "RC no QACK %d\n"
+ "RC ACKs %d\n"
+ "RC SEQ NAKs %d\n"
+ "RC RDMA seq %d\n"
+ "RC RNR NAKs %d\n"
+ "RC OTH NAKs %d\n"
+ "RC timeouts %d\n"
+ "RC RDMA dup %d\n"
+ "piobuf wait %d\n"
+ "no piobuf %d\n"
+ "PKT drops %d\n"
+ "WQE errs %d\n",
+ dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks,
+ dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks,
+ dev->n_other_naks, dev->n_timeouts,
+ dev->n_rdma_dup_busy, dev->n_piowait,
+ dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs);
+ for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) {
+ const struct ipath_opcode_stats *si = &dev->opstats[i];
+
+ if (!si->n_packets && !si->n_bytes)
+ continue;
+ len += sprintf(buf + len, "%02x %llu/%llu\n", i,
+ (unsigned long long) si->n_packets,
+ (unsigned long long) si->n_bytes);
+ }
+ return len;
+}
+
+static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);
+static CLASS_DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);
+
+static struct class_device_attribute *ipath_class_attributes[] = {
+ &class_device_attr_hw_rev,
+ &class_device_attr_hca_type,
+ &class_device_attr_board_id,
+ &class_device_attr_stats
+};
+
+static int ipath_verbs_register_sysfs(struct ib_device *dev)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(ipath_class_attributes); ++i)
+ if (class_device_create_file(&dev->class_dev,
+ ipath_class_attributes[i])) {
+ ret = 1;
+ goto bail;
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+module_init(ipath_verbs_init);
+module_exit(ipath_verbs_cleanup);
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
new file mode 100644
index 00000000000..4f8d59300e9
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
@@ -0,0 +1,693 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IPATH_VERBS_H
+#define IPATH_VERBS_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <rdma/ib_pack.h>
+
+#include "ipath_layer.h"
+#include "verbs_debug.h"
+
+#define QPN_MAX (1 << 24)
+#define QPNMAP_ENTRIES (QPN_MAX / PAGE_SIZE / BITS_PER_BYTE)
+
+/*
+ * Increment this value if any changes that break userspace ABI
+ * compatibility are made.
+ */
+#define IPATH_UVERBS_ABI_VERSION 1
+
+/*
+ * Define an ib_cq_notify value that is not valid so we know when CQ
+ * notifications are armed.
+ */
+#define IB_CQ_NONE (IB_CQ_NEXT_COMP + 1)
+
+#define IB_RNR_NAK 0x20
+#define IB_NAK_PSN_ERROR 0x60
+#define IB_NAK_INVALID_REQUEST 0x61
+#define IB_NAK_REMOTE_ACCESS_ERROR 0x62
+#define IB_NAK_REMOTE_OPERATIONAL_ERROR 0x63
+#define IB_NAK_INVALID_RD_REQUEST 0x64
+
+#define IPATH_POST_SEND_OK 0x01
+#define IPATH_POST_RECV_OK 0x02
+#define IPATH_PROCESS_RECV_OK 0x04
+#define IPATH_PROCESS_SEND_OK 0x08
+
+/* IB Performance Manager status values */
+#define IB_PMA_SAMPLE_STATUS_DONE 0x00
+#define IB_PMA_SAMPLE_STATUS_STARTED 0x01
+#define IB_PMA_SAMPLE_STATUS_RUNNING 0x02
+
+/* Mandatory IB performance counter select values. */
+#define IB_PMA_PORT_XMIT_DATA __constant_htons(0x0001)
+#define IB_PMA_PORT_RCV_DATA __constant_htons(0x0002)
+#define IB_PMA_PORT_XMIT_PKTS __constant_htons(0x0003)
+#define IB_PMA_PORT_RCV_PKTS __constant_htons(0x0004)
+#define IB_PMA_PORT_XMIT_WAIT __constant_htons(0x0005)
+
+struct ib_reth {
+ __be64 vaddr;
+ __be32 rkey;
+ __be32 length;
+} __attribute__ ((packed));
+
+struct ib_atomic_eth {
+ __be64 vaddr;
+ __be32 rkey;
+ __be64 swap_data;
+ __be64 compare_data;
+} __attribute__ ((packed));
+
+struct ipath_other_headers {
+ __be32 bth[3];
+ union {
+ struct {
+ __be32 deth[2];
+ __be32 imm_data;
+ } ud;
+ struct {
+ struct ib_reth reth;
+ __be32 imm_data;
+ } rc;
+ struct {
+ __be32 aeth;
+ __be64 atomic_ack_eth;
+ } at;
+ __be32 imm_data;
+ __be32 aeth;
+ struct ib_atomic_eth atomic_eth;
+ } u;
+} __attribute__ ((packed));
+
+/*
+ * Note that UD packets with a GRH header are 8+40+12+8 = 68 bytes
+ * long (72 w/ imm_data). Only the first 56 bytes of the IB header
+ * will be in the eager header buffer. The remaining 12 or 16 bytes
+ * are in the data buffer.
+ */
+struct ipath_ib_header {
+ __be16 lrh[4];
+ union {
+ struct {
+ struct ib_grh grh;
+ struct ipath_other_headers oth;
+ } l;
+ struct ipath_other_headers oth;
+ } u;
+} __attribute__ ((packed));
+
+/*
+ * There is one struct ipath_mcast for each multicast GID.
+ * All attached QPs are then stored as a list of
+ * struct ipath_mcast_qp.
+ */
+struct ipath_mcast_qp {
+ struct list_head list;
+ struct ipath_qp *qp;
+};
+
+struct ipath_mcast {
+ struct rb_node rb_node;
+ union ib_gid mgid;
+ struct list_head qp_list;
+ wait_queue_head_t wait;
+ atomic_t refcount;
+};
+
+/* Memory region */
+struct ipath_mr {
+ struct ib_mr ibmr;
+ struct ipath_mregion mr; /* must be last */
+};
+
+/* Fast memory region */
+struct ipath_fmr {
+ struct ib_fmr ibfmr;
+ u8 page_shift;
+ struct ipath_mregion mr; /* must be last */
+};
+
+/* Protection domain */
+struct ipath_pd {
+ struct ib_pd ibpd;
+ int user; /* non-zero if created from user space */
+};
+
+/* Address Handle */
+struct ipath_ah {
+ struct ib_ah ibah;
+ struct ib_ah_attr attr;
+};
+
+/*
+ * Quick description of our CQ/QP locking scheme:
+ *
+ * We have one global lock that protects dev->cq/qp_table. Each
+ * struct ipath_cq/qp also has its own lock. An individual qp lock
+ * may be taken inside of an individual cq lock. Both cqs attached to
+ * a qp may be locked, with the send cq locked first. No other
+ * nesting should be done.
+ *
+ * Each struct ipath_cq/qp also has an atomic_t ref count. The
+ * pointer from the cq/qp_table to the struct counts as one reference.
+ * This reference also is good for access through the consumer API, so
+ * modifying the CQ/QP etc doesn't need to take another reference.
+ * Access because of a completion being polled does need a reference.
+ *
+ * Finally, each struct ipath_cq/qp has a wait_queue_head_t for the
+ * destroy function to sleep on.
+ *
+ * This means that access from the consumer API requires nothing but
+ * taking the struct's lock.
+ *
+ * Access because of a completion event should go as follows:
+ * - lock cq/qp_table and look up struct
+ * - increment ref count in struct
+ * - drop cq/qp_table lock
+ * - lock struct, do your thing, and unlock struct
+ * - decrement ref count; if zero, wake up waiters
+ *
+ * To destroy a CQ/QP, we can do the following:
+ * - lock cq/qp_table, remove pointer, unlock cq/qp_table lock
+ * - decrement ref count
+ * - wait_event until ref count is zero
+ *
+ * It is the consumer's responsibilty to make sure that no QP
+ * operations (WQE posting or state modification) are pending when the
+ * QP is destroyed. Also, the consumer must make sure that calls to
+ * qp_modify are serialized.
+ *
+ * Possible optimizations (wait for profile data to see if/where we
+ * have locks bouncing between CPUs):
+ * - split cq/qp table lock into n separate (cache-aligned) locks,
+ * indexed (say) by the page in the table
+ */
+
+struct ipath_cq {
+ struct ib_cq ibcq;
+ struct tasklet_struct comptask;
+ spinlock_t lock;
+ u8 notify;
+ u8 triggered;
+ u32 head; /* new records added to the head */
+ u32 tail; /* poll_cq() reads from here. */
+ struct ib_wc *queue; /* this is actually ibcq.cqe + 1 */
+};
+
+/*
+ * Send work request queue entry.
+ * The size of the sg_list is determined when the QP is created and stored
+ * in qp->s_max_sge.
+ */
+struct ipath_swqe {
+ struct ib_send_wr wr; /* don't use wr.sg_list */
+ u32 psn; /* first packet sequence number */
+ u32 lpsn; /* last packet sequence number */
+ u32 ssn; /* send sequence number */
+ u32 length; /* total length of data in sg_list */
+ struct ipath_sge sg_list[0];
+};
+
+/*
+ * Receive work request queue entry.
+ * The size of the sg_list is determined when the QP is created and stored
+ * in qp->r_max_sge.
+ */
+struct ipath_rwqe {
+ u64 wr_id;
+ u32 length; /* total length of data in sg_list */
+ u8 num_sge;
+ struct ipath_sge sg_list[0];
+};
+
+struct ipath_rq {
+ spinlock_t lock;
+ u32 head; /* new work requests posted to the head */
+ u32 tail; /* receives pull requests from here. */
+ u32 size; /* size of RWQE array */
+ u8 max_sge;
+ struct ipath_rwqe *wq; /* RWQE array */
+};
+
+struct ipath_srq {
+ struct ib_srq ibsrq;
+ struct ipath_rq rq;
+ /* send signal when number of RWQEs < limit */
+ u32 limit;
+};
+
+/*
+ * Variables prefixed with s_ are for the requester (sender).
+ * Variables prefixed with r_ are for the responder (receiver).
+ * Variables prefixed with ack_ are for responder replies.
+ *
+ * Common variables are protected by both r_rq.lock and s_lock in that order
+ * which only happens in modify_qp() or changing the QP 'state'.
+ */
+struct ipath_qp {
+ struct ib_qp ibqp;
+ struct ipath_qp *next; /* link list for QPN hash table */
+ struct ipath_qp *timer_next; /* link list for ipath_ib_timer() */
+ struct list_head piowait; /* link for wait PIO buf */
+ struct list_head timerwait; /* link for waiting for timeouts */
+ struct ib_ah_attr remote_ah_attr;
+ struct ipath_ib_header s_hdr; /* next packet header to send */
+ atomic_t refcount;
+ wait_queue_head_t wait;
+ struct tasklet_struct s_task;
+ struct ipath_sge_state *s_cur_sge;
+ struct ipath_sge_state s_sge; /* current send request data */
+ /* current RDMA read send data */
+ struct ipath_sge_state s_rdma_sge;
+ struct ipath_sge_state r_sge; /* current receive data */
+ spinlock_t s_lock;
+ unsigned long s_flags;
+ u32 s_hdrwords; /* size of s_hdr in 32 bit words */
+ u32 s_cur_size; /* size of send packet in bytes */
+ u32 s_len; /* total length of s_sge */
+ u32 s_rdma_len; /* total length of s_rdma_sge */
+ u32 s_next_psn; /* PSN for next request */
+ u32 s_last_psn; /* last response PSN processed */
+ u32 s_psn; /* current packet sequence number */
+ u32 s_rnr_timeout; /* number of milliseconds for RNR timeout */
+ u32 s_ack_psn; /* PSN for next ACK or RDMA_READ */
+ u64 s_ack_atomic; /* data for atomic ACK */
+ u64 r_wr_id; /* ID for current receive WQE */
+ u64 r_atomic_data; /* data for last atomic op */
+ u32 r_atomic_psn; /* PSN of last atomic op */
+ u32 r_len; /* total length of r_sge */
+ u32 r_rcv_len; /* receive data len processed */
+ u32 r_psn; /* expected rcv packet sequence number */
+ u8 state; /* QP state */
+ u8 s_state; /* opcode of last packet sent */
+ u8 s_ack_state; /* opcode of packet to ACK */
+ u8 s_nak_state; /* non-zero if NAK is pending */
+ u8 r_state; /* opcode of last packet received */
+ u8 r_reuse_sge; /* for UC receive errors */
+ u8 r_sge_inx; /* current index into sg_list */
+ u8 s_max_sge; /* size of s_wq->sg_list */
+ u8 qp_access_flags;
+ u8 s_retry_cnt; /* number of times to retry */
+ u8 s_rnr_retry_cnt;
+ u8 s_min_rnr_timer;
+ u8 s_retry; /* requester retry counter */
+ u8 s_rnr_retry; /* requester RNR retry counter */
+ u8 s_pkey_index; /* PKEY index to use */
+ enum ib_mtu path_mtu;
+ atomic_t msn; /* message sequence number */
+ u32 remote_qpn;
+ u32 qkey; /* QKEY for this QP (for UD or RD) */
+ u32 s_size; /* send work queue size */
+ u32 s_head; /* new entries added here */
+ u32 s_tail; /* next entry to process */
+ u32 s_cur; /* current work queue entry */
+ u32 s_last; /* last un-ACK'ed entry */
+ u32 s_ssn; /* SSN of tail entry */
+ u32 s_lsn; /* limit sequence number (credit) */
+ struct ipath_swqe *s_wq; /* send work queue */
+ struct ipath_rq r_rq; /* receive work queue */
+};
+
+/*
+ * Bit definitions for s_flags.
+ */
+#define IPATH_S_BUSY 0
+#define IPATH_S_SIGNAL_REQ_WR 1
+
+/*
+ * Since struct ipath_swqe is not a fixed size, we can't simply index into
+ * struct ipath_qp.s_wq. This function does the array index computation.
+ */
+static inline struct ipath_swqe *get_swqe_ptr(struct ipath_qp *qp,
+ unsigned n)
+{
+ return (struct ipath_swqe *)((char *)qp->s_wq +
+ (sizeof(struct ipath_swqe) +
+ qp->s_max_sge *
+ sizeof(struct ipath_sge)) * n);
+}
+
+/*
+ * Since struct ipath_rwqe is not a fixed size, we can't simply index into
+ * struct ipath_rq.wq. This function does the array index computation.
+ */
+static inline struct ipath_rwqe *get_rwqe_ptr(struct ipath_rq *rq,
+ unsigned n)
+{
+ return (struct ipath_rwqe *)
+ ((char *) rq->wq +
+ (sizeof(struct ipath_rwqe) +
+ rq->max_sge * sizeof(struct ipath_sge)) * n);
+}
+
+/*
+ * QPN-map pages start out as NULL, they get allocated upon
+ * first use and are never deallocated. This way,
+ * large bitmaps are not allocated unless large numbers of QPs are used.
+ */
+struct qpn_map {
+ atomic_t n_free;
+ void *page;
+};
+
+struct ipath_qp_table {
+ spinlock_t lock;
+ u32 last; /* last QP number allocated */
+ u32 max; /* size of the hash table */
+ u32 nmaps; /* size of the map table */
+ struct ipath_qp **table;
+ /* bit map of free numbers */
+ struct qpn_map map[QPNMAP_ENTRIES];
+};
+
+struct ipath_lkey_table {
+ spinlock_t lock;
+ u32 next; /* next unused index (speeds search) */
+ u32 gen; /* generation count */
+ u32 max; /* size of the table */
+ struct ipath_mregion **table;
+};
+
+struct ipath_opcode_stats {
+ u64 n_packets; /* number of packets */
+ u64 n_bytes; /* total number of bytes */
+};
+
+struct ipath_ibdev {
+ struct ib_device ibdev;
+ struct list_head dev_list;
+ struct ipath_devdata *dd;
+ int ib_unit; /* This is the device number */
+ u16 sm_lid; /* in host order */
+ u8 sm_sl;
+ u8 mkeyprot_resv_lmc;
+ /* non-zero when timer is set */
+ unsigned long mkey_lease_timeout;
+
+ /* The following fields are really per port. */
+ struct ipath_qp_table qp_table;
+ struct ipath_lkey_table lk_table;
+ struct list_head pending[3]; /* FIFO of QPs waiting for ACKs */
+ struct list_head piowait; /* list for wait PIO buf */
+ /* list of QPs waiting for RNR timer */
+ struct list_head rnrwait;
+ spinlock_t pending_lock;
+ __be64 sys_image_guid; /* in network order */
+ __be64 gid_prefix; /* in network order */
+ __be64 mkey;
+ u64 ipath_sword; /* total dwords sent (sample result) */
+ u64 ipath_rword; /* total dwords received (sample result) */
+ u64 ipath_spkts; /* total packets sent (sample result) */
+ u64 ipath_rpkts; /* total packets received (sample result) */
+ /* # of ticks no data sent (sample result) */
+ u64 ipath_xmit_wait;
+ u64 rcv_errors; /* # of packets with SW detected rcv errs */
+ u64 n_unicast_xmit; /* total unicast packets sent */
+ u64 n_unicast_rcv; /* total unicast packets received */
+ u64 n_multicast_xmit; /* total multicast packets sent */
+ u64 n_multicast_rcv; /* total multicast packets received */
+ u64 n_symbol_error_counter; /* starting count for PMA */
+ u64 n_link_error_recovery_counter; /* starting count for PMA */
+ u64 n_link_downed_counter; /* starting count for PMA */
+ u64 n_port_rcv_errors; /* starting count for PMA */
+ u64 n_port_rcv_remphys_errors; /* starting count for PMA */
+ u64 n_port_xmit_discards; /* starting count for PMA */
+ u64 n_port_xmit_data; /* starting count for PMA */
+ u64 n_port_rcv_data; /* starting count for PMA */
+ u64 n_port_xmit_packets; /* starting count for PMA */
+ u64 n_port_rcv_packets; /* starting count for PMA */
+ u32 n_pkey_violations; /* starting count for PMA */
+ u32 n_rc_resends;
+ u32 n_rc_acks;
+ u32 n_rc_qacks;
+ u32 n_seq_naks;
+ u32 n_rdma_seq;
+ u32 n_rnr_naks;
+ u32 n_other_naks;
+ u32 n_timeouts;
+ u32 n_pkt_drops;
+ u32 n_wqe_errs;
+ u32 n_rdma_dup_busy;
+ u32 n_piowait;
+ u32 n_no_piobuf;
+ u32 port_cap_flags;
+ u32 pma_sample_start;
+ u32 pma_sample_interval;
+ __be16 pma_counter_select[5];
+ u16 pma_tag;
+ u16 qkey_violations;
+ u16 mkey_violations;
+ u16 mkey_lease_period;
+ u16 pending_index; /* which pending queue is active */
+ u8 pma_sample_status;
+ u8 subnet_timeout;
+ u8 link_width_enabled;
+ u8 vl_high_limit;
+ struct ipath_opcode_stats opstats[128];
+};
+
+struct ipath_ucontext {
+ struct ib_ucontext ibucontext;
+};
+
+static inline struct ipath_mr *to_imr(struct ib_mr *ibmr)
+{
+ return container_of(ibmr, struct ipath_mr, ibmr);
+}
+
+static inline struct ipath_fmr *to_ifmr(struct ib_fmr *ibfmr)
+{
+ return container_of(ibfmr, struct ipath_fmr, ibfmr);
+}
+
+static inline struct ipath_pd *to_ipd(struct ib_pd *ibpd)
+{
+ return container_of(ibpd, struct ipath_pd, ibpd);
+}
+
+static inline struct ipath_ah *to_iah(struct ib_ah *ibah)
+{
+ return container_of(ibah, struct ipath_ah, ibah);
+}
+
+static inline struct ipath_cq *to_icq(struct ib_cq *ibcq)
+{
+ return container_of(ibcq, struct ipath_cq, ibcq);
+}
+
+static inline struct ipath_srq *to_isrq(struct ib_srq *ibsrq)
+{
+ return container_of(ibsrq, struct ipath_srq, ibsrq);
+}
+
+static inline struct ipath_qp *to_iqp(struct ib_qp *ibqp)
+{
+ return container_of(ibqp, struct ipath_qp, ibqp);
+}
+
+static inline struct ipath_ibdev *to_idev(struct ib_device *ibdev)
+{
+ return container_of(ibdev, struct ipath_ibdev, ibdev);
+}
+
+int ipath_process_mad(struct ib_device *ibdev,
+ int mad_flags,
+ u8 port_num,
+ struct ib_wc *in_wc,
+ struct ib_grh *in_grh,
+ struct ib_mad *in_mad, struct ib_mad *out_mad);
+
+static inline struct ipath_ucontext *to_iucontext(struct ib_ucontext
+ *ibucontext)
+{
+ return container_of(ibucontext, struct ipath_ucontext, ibucontext);
+}
+
+/*
+ * Compare the lower 24 bits of the two values.
+ * Returns an integer <, ==, or > than zero.
+ */
+static inline int ipath_cmp24(u32 a, u32 b)
+{
+ return (((int) a) - ((int) b)) << 8;
+}
+
+struct ipath_mcast *ipath_mcast_find(union ib_gid *mgid);
+
+int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
+
+int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
+
+int ipath_mcast_tree_empty(void);
+
+__be32 ipath_compute_aeth(struct ipath_qp *qp);
+
+struct ipath_qp *ipath_lookup_qpn(struct ipath_qp_table *qpt, u32 qpn);
+
+struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
+ struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata);
+
+int ipath_destroy_qp(struct ib_qp *ibqp);
+
+int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask);
+
+int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask, struct ib_qp_init_attr *init_attr);
+
+void ipath_free_all_qps(struct ipath_qp_table *qpt);
+
+int ipath_init_qp_table(struct ipath_ibdev *idev, int size);
+
+void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc);
+
+void ipath_get_credit(struct ipath_qp *qp, u32 aeth);
+
+void ipath_do_rc_send(unsigned long data);
+
+void ipath_do_uc_send(unsigned long data);
+
+void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig);
+
+int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
+ u32 len, u64 vaddr, u32 rkey, int acc);
+
+int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
+ struct ib_sge *sge, int acc);
+
+void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length);
+
+void ipath_skip_sge(struct ipath_sge_state *ss, u32 length);
+
+int ipath_post_rc_send(struct ipath_qp *qp, struct ib_send_wr *wr);
+
+void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ int has_grh, void *data, u32 tlen, struct ipath_qp *qp);
+
+void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ int has_grh, void *data, u32 tlen, struct ipath_qp *qp);
+
+void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc);
+
+int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr);
+
+void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ int has_grh, void *data, u32 tlen, struct ipath_qp *qp);
+
+int ipath_alloc_lkey(struct ipath_lkey_table *rkt,
+ struct ipath_mregion *mr);
+
+void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey);
+
+int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
+ struct ib_sge *sge, int acc);
+
+int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
+ u32 len, u64 vaddr, u32 rkey, int acc);
+
+int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr);
+
+struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
+ struct ib_srq_init_attr *srq_init_attr,
+ struct ib_udata *udata);
+
+int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ enum ib_srq_attr_mask attr_mask);
+
+int ipath_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr);
+
+int ipath_destroy_srq(struct ib_srq *ibsrq);
+
+void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig);
+
+int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry);
+
+struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
+ struct ib_ucontext *context,
+ struct ib_udata *udata);
+
+int ipath_destroy_cq(struct ib_cq *ibcq);
+
+int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify);
+
+int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata);
+
+struct ib_mr *ipath_get_dma_mr(struct ib_pd *pd, int acc);
+
+struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd,
+ struct ib_phys_buf *buffer_list,
+ int num_phys_buf, int acc, u64 *iova_start);
+
+struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
+ int mr_access_flags,
+ struct ib_udata *udata);
+
+int ipath_dereg_mr(struct ib_mr *ibmr);
+
+struct ib_fmr *ipath_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
+ struct ib_fmr_attr *fmr_attr);
+
+int ipath_map_phys_fmr(struct ib_fmr *ibfmr, u64 * page_list,
+ int list_len, u64 iova);
+
+int ipath_unmap_fmr(struct list_head *fmr_list);
+
+int ipath_dealloc_fmr(struct ib_fmr *ibfmr);
+
+void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev);
+
+void ipath_insert_rnr_queue(struct ipath_qp *qp);
+
+int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only);
+
+void ipath_ruc_loopback(struct ipath_qp *sqp, struct ib_wc *wc);
+
+extern const enum ib_wc_opcode ib_ipath_wc_opcode[];
+
+extern const u8 ipath_cvt_physportstate[];
+
+extern const int ib_ipath_state_ops[];
+
+extern unsigned int ib_ipath_lkey_table_size;
+
+extern const u32 ib_ipath_rnr_table[];
+
+#endif /* IPATH_VERBS_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
new file mode 100644
index 00000000000..10b31d2c4f2
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/list.h>
+#include <linux/rcupdate.h>
+
+#include "ipath_verbs.h"
+
+/*
+ * Global table of GID to attached QPs.
+ * The table is global to all ipath devices since a send from one QP/device
+ * needs to be locally routed to any locally attached QPs on the same
+ * or different device.
+ */
+static struct rb_root mcast_tree;
+static DEFINE_SPINLOCK(mcast_lock);
+
+/**
+ * ipath_mcast_qp_alloc - alloc a struct to link a QP to mcast GID struct
+ * @qp: the QP to link
+ */
+static struct ipath_mcast_qp *ipath_mcast_qp_alloc(struct ipath_qp *qp)
+{
+ struct ipath_mcast_qp *mqp;
+
+ mqp = kmalloc(sizeof *mqp, GFP_KERNEL);
+ if (!mqp)
+ goto bail;
+
+ mqp->qp = qp;
+ atomic_inc(&qp->refcount);
+
+bail:
+ return mqp;
+}
+
+static void ipath_mcast_qp_free(struct ipath_mcast_qp *mqp)
+{
+ struct ipath_qp *qp = mqp->qp;
+
+ /* Notify ipath_destroy_qp() if it is waiting. */
+ if (atomic_dec_and_test(&qp->refcount))
+ wake_up(&qp->wait);
+
+ kfree(mqp);
+}
+
+/**
+ * ipath_mcast_alloc - allocate the multicast GID structure
+ * @mgid: the multicast GID
+ *
+ * A list of QPs will be attached to this structure.
+ */
+static struct ipath_mcast *ipath_mcast_alloc(union ib_gid *mgid)
+{
+ struct ipath_mcast *mcast;
+
+ mcast = kmalloc(sizeof *mcast, GFP_KERNEL);
+ if (!mcast)
+ goto bail;
+
+ mcast->mgid = *mgid;
+ INIT_LIST_HEAD(&mcast->qp_list);
+ init_waitqueue_head(&mcast->wait);
+ atomic_set(&mcast->refcount, 0);
+
+bail:
+ return mcast;
+}
+
+static void ipath_mcast_free(struct ipath_mcast *mcast)
+{
+ struct ipath_mcast_qp *p, *tmp;
+
+ list_for_each_entry_safe(p, tmp, &mcast->qp_list, list)
+ ipath_mcast_qp_free(p);
+
+ kfree(mcast);
+}
+
+/**
+ * ipath_mcast_find - search the global table for the given multicast GID
+ * @mgid: the multicast GID to search for
+ *
+ * Returns NULL if not found.
+ *
+ * The caller is responsible for decrementing the reference count if found.
+ */
+struct ipath_mcast *ipath_mcast_find(union ib_gid *mgid)
+{
+ struct rb_node *n;
+ unsigned long flags;
+ struct ipath_mcast *mcast;
+
+ spin_lock_irqsave(&mcast_lock, flags);
+ n = mcast_tree.rb_node;
+ while (n) {
+ int ret;
+
+ mcast = rb_entry(n, struct ipath_mcast, rb_node);
+
+ ret = memcmp(mgid->raw, mcast->mgid.raw,
+ sizeof(union ib_gid));
+ if (ret < 0)
+ n = n->rb_left;
+ else if (ret > 0)
+ n = n->rb_right;
+ else {
+ atomic_inc(&mcast->refcount);
+ spin_unlock_irqrestore(&mcast_lock, flags);
+ goto bail;
+ }
+ }
+ spin_unlock_irqrestore(&mcast_lock, flags);
+
+ mcast = NULL;
+
+bail:
+ return mcast;
+}
+
+/**
+ * ipath_mcast_add - insert mcast GID into table and attach QP struct
+ * @mcast: the mcast GID table
+ * @mqp: the QP to attach
+ *
+ * Return zero if both were added. Return EEXIST if the GID was already in
+ * the table but the QP was added. Return ESRCH if the QP was already
+ * attached and neither structure was added.
+ */
+static int ipath_mcast_add(struct ipath_mcast *mcast,
+ struct ipath_mcast_qp *mqp)
+{
+ struct rb_node **n = &mcast_tree.rb_node;
+ struct rb_node *pn = NULL;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&mcast_lock, flags);
+
+ while (*n) {
+ struct ipath_mcast *tmcast;
+ struct ipath_mcast_qp *p;
+
+ pn = *n;
+ tmcast = rb_entry(pn, struct ipath_mcast, rb_node);
+
+ ret = memcmp(mcast->mgid.raw, tmcast->mgid.raw,
+ sizeof(union ib_gid));
+ if (ret < 0) {
+ n = &pn->rb_left;
+ continue;
+ }
+ if (ret > 0) {
+ n = &pn->rb_right;
+ continue;
+ }
+
+ /* Search the QP list to see if this is already there. */
+ list_for_each_entry_rcu(p, &tmcast->qp_list, list) {
+ if (p->qp == mqp->qp) {
+ spin_unlock_irqrestore(&mcast_lock, flags);
+ ret = ESRCH;
+ goto bail;
+ }
+ }
+ list_add_tail_rcu(&mqp->list, &tmcast->qp_list);
+ spin_unlock_irqrestore(&mcast_lock, flags);
+ ret = EEXIST;
+ goto bail;
+ }
+
+ list_add_tail_rcu(&mqp->list, &mcast->qp_list);
+
+ atomic_inc(&mcast->refcount);
+ rb_link_node(&mcast->rb_node, pn, n);
+ rb_insert_color(&mcast->rb_node, &mcast_tree);
+
+ spin_unlock_irqrestore(&mcast_lock, flags);
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+ struct ipath_mcast *mcast;
+ struct ipath_mcast_qp *mqp;
+ int ret;
+
+ /*
+ * Allocate data structures since its better to do this outside of
+ * spin locks and it will most likely be needed.
+ */
+ mcast = ipath_mcast_alloc(gid);
+ if (mcast == NULL) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ mqp = ipath_mcast_qp_alloc(qp);
+ if (mqp == NULL) {
+ ipath_mcast_free(mcast);
+ ret = -ENOMEM;
+ goto bail;
+ }
+ switch (ipath_mcast_add(mcast, mqp)) {
+ case ESRCH:
+ /* Neither was used: can't attach the same QP twice. */
+ ipath_mcast_qp_free(mqp);
+ ipath_mcast_free(mcast);
+ ret = -EINVAL;
+ goto bail;
+ case EEXIST: /* The mcast wasn't used */
+ ipath_mcast_free(mcast);
+ break;
+ default:
+ break;
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+{
+ struct ipath_qp *qp = to_iqp(ibqp);
+ struct ipath_mcast *mcast = NULL;
+ struct ipath_mcast_qp *p, *tmp;
+ struct rb_node *n;
+ unsigned long flags;
+ int last = 0;
+ int ret;
+
+ spin_lock_irqsave(&mcast_lock, flags);
+
+ /* Find the GID in the mcast table. */
+ n = mcast_tree.rb_node;
+ while (1) {
+ if (n == NULL) {
+ spin_unlock_irqrestore(&mcast_lock, flags);
+ ret = 0;
+ goto bail;
+ }
+
+ mcast = rb_entry(n, struct ipath_mcast, rb_node);
+ ret = memcmp(gid->raw, mcast->mgid.raw,
+ sizeof(union ib_gid));
+ if (ret < 0)
+ n = n->rb_left;
+ else if (ret > 0)
+ n = n->rb_right;
+ else
+ break;
+ }
+
+ /* Search the QP list. */
+ list_for_each_entry_safe(p, tmp, &mcast->qp_list, list) {
+ if (p->qp != qp)
+ continue;
+ /*
+ * We found it, so remove it, but don't poison the forward
+ * link until we are sure there are no list walkers.
+ */
+ list_del_rcu(&p->list);
+
+ /* If this was the last attached QP, remove the GID too. */
+ if (list_empty(&mcast->qp_list)) {
+ rb_erase(&mcast->rb_node, &mcast_tree);
+ last = 1;
+ }
+ break;
+ }
+
+ spin_unlock_irqrestore(&mcast_lock, flags);
+
+ if (p) {
+ /*
+ * Wait for any list walkers to finish before freeing the
+ * list element.
+ */
+ wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
+ ipath_mcast_qp_free(p);
+ }
+ if (last) {
+ atomic_dec(&mcast->refcount);
+ wait_event(mcast->wait, !atomic_read(&mcast->refcount));
+ ipath_mcast_free(mcast);
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+int ipath_mcast_tree_empty(void)
+{
+ return mcast_tree.rb_node == NULL;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c b/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
new file mode 100644
index 00000000000..adc5322f15c
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This file is conditionally built on x86_64 only. Otherwise weak symbol
+ * versions of the functions exported from here are used.
+ */
+
+#include <linux/pci.h>
+#include <asm/mtrr.h>
+#include <asm/processor.h>
+
+#include "ipath_kernel.h"
+
+/**
+ * ipath_enable_wc - enable write combining for MMIO writes to the device
+ * @dd: infinipath device
+ *
+ * This routine is x86_64-specific; it twiddles the CPU's MTRRs to enable
+ * write combining.
+ */
+int ipath_enable_wc(struct ipath_devdata *dd)
+{
+ int ret = 0;
+ u64 pioaddr, piolen;
+ unsigned bits;
+ const unsigned long addr = pci_resource_start(dd->pcidev, 0);
+ const size_t len = pci_resource_len(dd->pcidev, 0);
+
+ /*
+ * Set the PIO buffers to be WCCOMB, so we get HT bursts to the
+ * chip. Linux (possibly the hardware) requires it to be on a power
+ * of 2 address matching the length (which has to be a power of 2).
+ * For rev1, that means the base address, for rev2, it will be just
+ * the PIO buffers themselves.
+ */
+ pioaddr = addr + dd->ipath_piobufbase;
+ piolen = (dd->ipath_piobcnt2k +
+ dd->ipath_piobcnt4k) *
+ ALIGN(dd->ipath_piobcnt2k +
+ dd->ipath_piobcnt4k, dd->ipath_palign);
+
+ for (bits = 0; !(piolen & (1ULL << bits)); bits++)
+ /* do nothing */ ;
+
+ if (piolen != (1ULL << bits)) {
+ piolen >>= bits;
+ while (piolen >>= 1)
+ bits++;
+ piolen = 1ULL << (bits + 1);
+ }
+ if (pioaddr & (piolen - 1)) {
+ u64 atmp;
+ ipath_dbg("pioaddr %llx not on right boundary for size "
+ "%llx, fixing\n",
+ (unsigned long long) pioaddr,
+ (unsigned long long) piolen);
+ atmp = pioaddr & ~(piolen - 1);
+ if (atmp < addr || (atmp + piolen) > (addr + len)) {
+ ipath_dev_err(dd, "No way to align address/size "
+ "(%llx/%llx), no WC mtrr\n",
+ (unsigned long long) atmp,
+ (unsigned long long) piolen << 1);
+ ret = -ENODEV;
+ } else {
+ ipath_dbg("changing WC base from %llx to %llx, "
+ "len from %llx to %llx\n",
+ (unsigned long long) pioaddr,
+ (unsigned long long) atmp,
+ (unsigned long long) piolen,
+ (unsigned long long) piolen << 1);
+ pioaddr = atmp;
+ piolen <<= 1;
+ }
+ }
+
+ if (!ret) {
+ int cookie;
+ ipath_cdbg(VERBOSE, "Setting mtrr for chip to WC "
+ "(addr %llx, len=0x%llx)\n",
+ (unsigned long long) pioaddr,
+ (unsigned long long) piolen);
+ cookie = mtrr_add(pioaddr, piolen, MTRR_TYPE_WRCOMB, 0);
+ if (cookie < 0) {
+ {
+ dev_info(&dd->pcidev->dev,
+ "mtrr_add() WC for PIO bufs "
+ "failed (%d)\n",
+ cookie);
+ ret = -EINVAL;
+ }
+ } else {
+ ipath_cdbg(VERBOSE, "Set mtrr for chip to WC, "
+ "cookie is %d\n", cookie);
+ dd->ipath_wc_cookie = cookie;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * ipath_disable_wc - disable write combining for MMIO writes to the device
+ * @dd: infinipath device
+ */
+void ipath_disable_wc(struct ipath_devdata *dd)
+{
+ if (dd->ipath_wc_cookie) {
+ ipath_cdbg(VERBOSE, "undoing WCCOMB on pio buffers\n");
+ mtrr_del(dd->ipath_wc_cookie, 0, 0);
+ dd->ipath_wc_cookie = 0;
+ }
+}
+
+/**
+ * ipath_unordered_wc - indicate whether write combining is ordered
+ *
+ * Because our performance depends on our ability to do write combining mmio
+ * writes in the most efficient way, we need to know if we are on an Intel
+ * or AMD x86_64 processor. AMD x86_64 processors flush WC buffers out in
+ * the order completed, and so no special flushing is required to get
+ * correct ordering. Intel processors, however, will flush write buffers
+ * out in "random" orders, and so explicit ordering is needed at times.
+ */
+int ipath_unordered_wc(void)
+{
+ return boot_cpu_data.x86_vendor != X86_VENDOR_AMD;
+}
diff --git a/drivers/infiniband/hw/ipath/ips_common.h b/drivers/infiniband/hw/ipath/ips_common.h
new file mode 100644
index 00000000000..ab7cbbbfd03
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ips_common.h
@@ -0,0 +1,263 @@
+#ifndef IPS_COMMON_H
+#define IPS_COMMON_H
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ipath_common.h"
+
+struct ipath_header {
+ /*
+ * Version - 4 bits, Port - 4 bits, TID - 10 bits and Offset -
+ * 14 bits before ECO change ~28 Dec 03. After that, Vers 4,
+ * Port 3, TID 11, offset 14.
+ */
+ __le32 ver_port_tid_offset;
+ __le16 chksum;
+ __le16 pkt_flags;
+};
+
+struct ips_message_header {
+ __be16 lrh[4];
+ __be32 bth[3];
+ /* fields below this point are in host byte order */
+ struct ipath_header iph;
+ __u8 sub_opcode;
+ __u8 flags;
+ __u16 src_rank;
+ /* 24 bits. The upper 8 bit is available for other use */
+ union {
+ struct {
+ unsigned ack_seq_num:24;
+ unsigned port:4;
+ unsigned unused:4;
+ };
+ __u32 ack_seq_num_org;
+ };
+ __u8 expected_tid_session_id;
+ __u8 tinylen; /* to aid MPI */
+ union {
+ __u16 tag; /* to aid MPI */
+ __u16 mqhdr; /* for PSM MQ */
+ };
+ union {
+ __u32 mpi[4]; /* to aid MPI */
+ __u32 data[4];
+ __u64 mq[2]; /* for PSM MQ */
+ struct {
+ __u16 mtu;
+ __u8 major_ver;
+ __u8 minor_ver;
+ __u32 not_used; //free
+ __u32 run_id;
+ __u32 client_ver;
+ };
+ };
+};
+
+struct ether_header {
+ __be16 lrh[4];
+ __be32 bth[3];
+ struct ipath_header iph;
+ __u8 sub_opcode;
+ __u8 cmd;
+ __be16 lid;
+ __u16 mac[3];
+ __u8 frag_num;
+ __u8 seq_num;
+ __le32 len;
+ /* MUST be of word size due to PIO write requirements */
+ __le32 csum;
+ __le16 csum_offset;
+ __le16 flags;
+ __u16 first_2_bytes;
+ __u8 unused[2]; /* currently unused */
+};
+
+/*
+ * The PIO buffer used for sending infinipath messages must only be written
+ * in 32-bit words, all the data must be written, and no writes can occur
+ * after the last word is written (which transfers "ownership" of the buffer
+ * to the chip and triggers the message to be sent).
+ * Since the Linux sk_buff structure can be recursive, non-aligned, and
+ * any number of bytes in each segment, we use the following structure
+ * to keep information about the overall state of the copy operation.
+ * This is used to save the information needed to store the checksum
+ * in the right place before sending the last word to the hardware and
+ * to buffer the last 0-3 bytes of non-word sized segments.
+ */
+struct copy_data_s {
+ struct ether_header *hdr;
+ /* addr of PIO buf to write csum to */
+ __u32 __iomem *csum_pio;
+ __u32 __iomem *to; /* addr of PIO buf to write data to */
+ __u32 device; /* which device to allocate PIO bufs from */
+ __s32 error; /* set if there is an error. */
+ __s32 extra; /* amount of data saved in u.buf below */
+ __u32 len; /* total length to send in bytes */
+ __u32 flen; /* frament length in words */
+ __u32 csum; /* partial IP checksum */
+ __u32 pos; /* position for partial checksum */
+ __u32 offset; /* offset to where data currently starts */
+ __s32 checksum_calc; /* set to 1 when csum has been calculated */
+ struct sk_buff *skb;
+ union {
+ __u32 w;
+ __u8 buf[4];
+ } u;
+};
+
+/* IB - LRH header consts */
+#define IPS_LRH_GRH 0x0003 /* 1. word of IB LRH - next header: GRH */
+#define IPS_LRH_BTH 0x0002 /* 1. word of IB LRH - next header: BTH */
+
+#define IPS_OFFSET 0
+
+/*
+ * defines the cut-off point between the header queue and eager/expected
+ * TID queue
+ */
+#define NUM_OF_EXTRA_WORDS_IN_HEADER_QUEUE \
+ ((sizeof(struct ips_message_header) - \
+ offsetof(struct ips_message_header, iph)) >> 2)
+
+/* OpCodes */
+#define OPCODE_IPS 0xC0
+#define OPCODE_ITH4X 0xC1
+
+/* OpCode 30 is use by stand-alone test programs */
+#define OPCODE_RAW_DATA 0xDE
+/* last OpCode (31) is reserved for test */
+#define OPCODE_TEST 0xDF
+
+/* sub OpCodes - ips */
+#define OPCODE_SEQ_DATA 0x01
+#define OPCODE_SEQ_CTRL 0x02
+
+#define OPCODE_SEQ_MQ_DATA 0x03
+#define OPCODE_SEQ_MQ_CTRL 0x04
+
+#define OPCODE_ACK 0x10
+#define OPCODE_NAK 0x11
+
+#define OPCODE_ERR_CHK 0x20
+#define OPCODE_ERR_CHK_PLS 0x21
+
+#define OPCODE_STARTUP 0x30
+#define OPCODE_STARTUP_ACK 0x31
+#define OPCODE_STARTUP_NAK 0x32
+
+#define OPCODE_STARTUP_EXT 0x34
+#define OPCODE_STARTUP_ACK_EXT 0x35
+#define OPCODE_STARTUP_NAK_EXT 0x36
+
+#define OPCODE_TIDS_RELEASE 0x40
+#define OPCODE_TIDS_RELEASE_CONFIRM 0x41
+
+#define OPCODE_CLOSE 0x50
+#define OPCODE_CLOSE_ACK 0x51
+/*
+ * like OPCODE_CLOSE, but no complaint if other side has already closed.
+ * Used when doing abort(), MPI_Abort(), etc.
+ */
+#define OPCODE_ABORT 0x52
+
+/* sub OpCodes - ith4x */
+#define OPCODE_ENCAP 0x81
+#define OPCODE_LID_ARP 0x82
+
+/* Receive Header Queue: receive type (from infinipath) */
+#define RCVHQ_RCV_TYPE_EXPECTED 0
+#define RCVHQ_RCV_TYPE_EAGER 1
+#define RCVHQ_RCV_TYPE_NON_KD 2
+#define RCVHQ_RCV_TYPE_ERROR 3
+
+/* misc. */
+#define SIZE_OF_CRC 1
+
+#define EAGER_TID_ID INFINIPATH_I_TID_MASK
+
+#define IPS_DEFAULT_P_KEY 0xFFFF
+
+#define IPS_PERMISSIVE_LID 0xFFFF
+#define IPS_MULTICAST_LID_BASE 0xC000
+
+#define IPS_AETH_CREDIT_SHIFT 24
+#define IPS_AETH_CREDIT_MASK 0x1F
+#define IPS_AETH_CREDIT_INVAL 0x1F
+
+#define IPS_PSN_MASK 0xFFFFFF
+#define IPS_MSN_MASK 0xFFFFFF
+#define IPS_QPN_MASK 0xFFFFFF
+#define IPS_MULTICAST_QPN 0xFFFFFF
+
+/* functions for extracting fields from rcvhdrq entries */
+static inline __u32 ips_get_hdr_err_flags(const __le32 * rbuf)
+{
+ return __le32_to_cpu(rbuf[1]);
+}
+
+static inline __u32 ips_get_index(const __le32 * rbuf)
+{
+ return (__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_EGRINDEX_SHIFT)
+ & INFINIPATH_RHF_EGRINDEX_MASK;
+}
+
+static inline __u32 ips_get_rcv_type(const __le32 * rbuf)
+{
+ return (__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_RCVTYPE_SHIFT)
+ & INFINIPATH_RHF_RCVTYPE_MASK;
+}
+
+static inline __u32 ips_get_length_in_bytes(const __le32 * rbuf)
+{
+ return ((__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_LENGTH_SHIFT)
+ & INFINIPATH_RHF_LENGTH_MASK) << 2;
+}
+
+static inline void *ips_get_first_protocol_header(const __u32 * rbuf)
+{
+ return (void *)&rbuf[2];
+}
+
+static inline struct ips_message_header *ips_get_ips_header(const __u32 *
+ rbuf)
+{
+ return (struct ips_message_header *)&rbuf[2];
+}
+
+static inline __u32 ips_get_ipath_ver(__le32 hdrword)
+{
+ return (__le32_to_cpu(hdrword) >> INFINIPATH_I_VERS_SHIFT)
+ & INFINIPATH_I_VERS_MASK;
+}
+
+#endif /* IPS_COMMON_H */
diff --git a/drivers/infiniband/hw/ipath/verbs_debug.h b/drivers/infiniband/hw/ipath/verbs_debug.h
new file mode 100644
index 00000000000..40d693cf3f9
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/verbs_debug.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _VERBS_DEBUG_H
+#define _VERBS_DEBUG_H
+
+/*
+ * This file contains tracing code for the ib_ipath kernel module.
+ */
+#ifndef _VERBS_DEBUGGING /* tracing enabled or not */
+#define _VERBS_DEBUGGING 1
+#endif
+
+extern unsigned ib_ipath_debug;
+
+#define _VERBS_ERROR(fmt,...) \
+ do { \
+ printk(KERN_ERR "%s: " fmt, "ib_ipath", ##__VA_ARGS__); \
+ } while(0)
+
+#define _VERBS_UNIT_ERROR(unit,fmt,...) \
+ do { \
+ printk(KERN_ERR "%s: " fmt, "ib_ipath", ##__VA_ARGS__); \
+ } while(0)
+
+#if _VERBS_DEBUGGING
+
+/*
+ * Mask values for debugging. The scheme allows us to compile out any
+ * of the debug tracing stuff, and if compiled in, to enable or
+ * disable dynamically.
+ * This can be set at modprobe time also:
+ * modprobe ib_path ib_ipath_debug=3
+ */
+
+#define __VERBS_INFO 0x1 /* generic low verbosity stuff */
+#define __VERBS_DBG 0x2 /* generic debug */
+#define __VERBS_VDBG 0x4 /* verbose debug */
+#define __VERBS_SMADBG 0x8000 /* sma packet debug */
+
+#define _VERBS_INFO(fmt,...) \
+ do { \
+ if (unlikely(ib_ipath_debug&__VERBS_INFO)) \
+ printk(KERN_INFO "%s: " fmt,"ib_ipath", \
+ ##__VA_ARGS__); \
+ } while(0)
+
+#define _VERBS_DBG(fmt,...) \
+ do { \
+ if (unlikely(ib_ipath_debug&__VERBS_DBG)) \
+ printk(KERN_DEBUG "%s: " fmt, __func__, \
+ ##__VA_ARGS__); \
+ } while(0)
+
+#define _VERBS_VDBG(fmt,...) \
+ do { \
+ if (unlikely(ib_ipath_debug&__VERBS_VDBG)) \
+ printk(KERN_DEBUG "%s: " fmt, __func__, \
+ ##__VA_ARGS__); \
+ } while(0)
+
+#define _VERBS_SMADBG(fmt,...) \
+ do { \
+ if (unlikely(ib_ipath_debug&__VERBS_SMADBG)) \
+ printk(KERN_DEBUG "%s: " fmt, __func__, \
+ ##__VA_ARGS__); \
+ } while(0)
+
+#else /* ! _VERBS_DEBUGGING */
+
+#define _VERBS_INFO(fmt,...)
+#define _VERBS_DBG(fmt,...)
+#define _VERBS_VDBG(fmt,...)
+#define _VERBS_SMADBG(fmt,...)
+
+#endif /* _VERBS_DEBUGGING */
+
+#endif /* _VERBS_DEBUG_H */
diff --git a/drivers/infiniband/hw/mthca/Kconfig b/drivers/infiniband/hw/mthca/Kconfig
index e88be85b3d5..9aa5a4468a7 100644
--- a/drivers/infiniband/hw/mthca/Kconfig
+++ b/drivers/infiniband/hw/mthca/Kconfig
@@ -7,10 +7,11 @@ config INFINIBAND_MTHCA
("Tavor") and the MT25208 PCI Express HCA ("Arbel").
config INFINIBAND_MTHCA_DEBUG
- bool "Verbose debugging output"
+ bool "Verbose debugging output" if EMBEDDED
depends on INFINIBAND_MTHCA
- default n
+ default y
---help---
- This option causes the mthca driver produce a bunch of debug
- messages. Select this is you are developing the driver or
- trying to diagnose a problem.
+ This option causes debugging code to be compiled into the
+ mthca driver. The output can be turned on via the
+ debug_level module parameter (which can also be set after
+ the driver is loaded through sysfs).
diff --git a/drivers/infiniband/hw/mthca/Makefile b/drivers/infiniband/hw/mthca/Makefile
index 47ec5a7cba0..e388d95d0cf 100644
--- a/drivers/infiniband/hw/mthca/Makefile
+++ b/drivers/infiniband/hw/mthca/Makefile
@@ -1,7 +1,3 @@
-ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
-EXTRA_CFLAGS += -DDEBUG
-endif
-
obj-$(CONFIG_INFINIBAND_MTHCA) += ib_mthca.o
ib_mthca-y := mthca_main.o mthca_cmd.o mthca_profile.o mthca_reset.o \
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index f023d393651..b12aa03be25 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -42,6 +42,20 @@
#include "mthca_dev.h"
+enum {
+ MTHCA_RATE_TAVOR_FULL = 0,
+ MTHCA_RATE_TAVOR_1X = 1,
+ MTHCA_RATE_TAVOR_4X = 2,
+ MTHCA_RATE_TAVOR_1X_DDR = 3
+};
+
+enum {
+ MTHCA_RATE_MEMFREE_FULL = 0,
+ MTHCA_RATE_MEMFREE_QUARTER = 1,
+ MTHCA_RATE_MEMFREE_EIGHTH = 2,
+ MTHCA_RATE_MEMFREE_HALF = 3
+};
+
struct mthca_av {
__be32 port_pd;
u8 reserved1;
@@ -55,6 +69,90 @@ struct mthca_av {
__be32 dgid[4];
};
+static enum ib_rate memfree_rate_to_ib(u8 mthca_rate, u8 port_rate)
+{
+ switch (mthca_rate) {
+ case MTHCA_RATE_MEMFREE_EIGHTH:
+ return mult_to_ib_rate(port_rate >> 3);
+ case MTHCA_RATE_MEMFREE_QUARTER:
+ return mult_to_ib_rate(port_rate >> 2);
+ case MTHCA_RATE_MEMFREE_HALF:
+ return mult_to_ib_rate(port_rate >> 1);
+ case MTHCA_RATE_MEMFREE_FULL:
+ default:
+ return mult_to_ib_rate(port_rate);
+ }
+}
+
+static enum ib_rate tavor_rate_to_ib(u8 mthca_rate, u8 port_rate)
+{
+ switch (mthca_rate) {
+ case MTHCA_RATE_TAVOR_1X: return IB_RATE_2_5_GBPS;
+ case MTHCA_RATE_TAVOR_1X_DDR: return IB_RATE_5_GBPS;
+ case MTHCA_RATE_TAVOR_4X: return IB_RATE_10_GBPS;
+ default: return port_rate;
+ }
+}
+
+enum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port)
+{
+ if (mthca_is_memfree(dev)) {
+ /* Handle old Arbel FW */
+ if (dev->limits.stat_rate_support == 0x3 && mthca_rate)
+ return IB_RATE_2_5_GBPS;
+
+ return memfree_rate_to_ib(mthca_rate, dev->rate[port - 1]);
+ } else
+ return tavor_rate_to_ib(mthca_rate, dev->rate[port - 1]);
+}
+
+static u8 ib_rate_to_memfree(u8 req_rate, u8 cur_rate)
+{
+ if (cur_rate <= req_rate)
+ return 0;
+
+ /*
+ * Inter-packet delay (IPD) to get from rate X down to a rate
+ * no more than Y is (X - 1) / Y.
+ */
+ switch ((cur_rate - 1) / req_rate) {
+ case 0: return MTHCA_RATE_MEMFREE_FULL;
+ case 1: return MTHCA_RATE_MEMFREE_HALF;
+ case 2: /* fall through */
+ case 3: return MTHCA_RATE_MEMFREE_QUARTER;
+ default: return MTHCA_RATE_MEMFREE_EIGHTH;
+ }
+}
+
+static u8 ib_rate_to_tavor(u8 static_rate)
+{
+ switch (static_rate) {
+ case IB_RATE_2_5_GBPS: return MTHCA_RATE_TAVOR_1X;
+ case IB_RATE_5_GBPS: return MTHCA_RATE_TAVOR_1X_DDR;
+ case IB_RATE_10_GBPS: return MTHCA_RATE_TAVOR_4X;
+ default: return MTHCA_RATE_TAVOR_FULL;
+ }
+}
+
+u8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port)
+{
+ u8 rate;
+
+ if (!static_rate || ib_rate_to_mult(static_rate) >= dev->rate[port - 1])
+ return 0;
+
+ if (mthca_is_memfree(dev))
+ rate = ib_rate_to_memfree(ib_rate_to_mult(static_rate),
+ dev->rate[port - 1]);
+ else
+ rate = ib_rate_to_tavor(static_rate);
+
+ if (!(dev->limits.stat_rate_support & (1 << rate)))
+ rate = 1;
+
+ return rate;
+}
+
int mthca_create_ah(struct mthca_dev *dev,
struct mthca_pd *pd,
struct ib_ah_attr *ah_attr,
@@ -107,7 +205,7 @@ on_hca_fail:
av->g_slid = ah_attr->src_path_bits;
av->dlid = cpu_to_be16(ah_attr->dlid);
av->msg_sr = (3 << 4) | /* 2K message */
- ah_attr->static_rate;
+ mthca_get_rate(dev, ah_attr->static_rate, ah_attr->port_num);
av->sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
if (ah_attr->ah_flags & IB_AH_GRH) {
av->g_slid |= 0x80;
@@ -265,7 +363,7 @@ int __devinit mthca_init_av_table(struct mthca_dev *dev)
return -ENOMEM;
}
-void __devexit mthca_cleanup_av_table(struct mthca_dev *dev)
+void mthca_cleanup_av_table(struct mthca_dev *dev)
{
if (mthca_is_memfree(dev))
return;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 343eca50787..798e13e14fa 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -182,7 +182,7 @@ struct mthca_cmd_context {
u8 status;
};
-static int fw_cmd_doorbell = 1;
+static int fw_cmd_doorbell = 0;
module_param(fw_cmd_doorbell, int, 0644);
MODULE_PARM_DESC(fw_cmd_doorbell, "post FW commands through doorbell page if nonzero "
"(and supported by FW)");
@@ -965,6 +965,7 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
u32 *outbox;
u8 field;
u16 size;
+ u16 stat_rate;
int err;
#define QUERY_DEV_LIM_OUT_SIZE 0x100
@@ -995,6 +996,7 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
#define QUERY_DEV_LIM_MTU_WIDTH_OFFSET 0x36
#define QUERY_DEV_LIM_VL_PORT_OFFSET 0x37
#define QUERY_DEV_LIM_MAX_GID_OFFSET 0x3b
+#define QUERY_DEV_LIM_RATE_SUPPORT_OFFSET 0x3c
#define QUERY_DEV_LIM_MAX_PKEY_OFFSET 0x3f
#define QUERY_DEV_LIM_FLAGS_OFFSET 0x44
#define QUERY_DEV_LIM_RSVD_UAR_OFFSET 0x48
@@ -1086,6 +1088,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
dev_lim->num_ports = field & 0xf;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_GID_OFFSET);
dev_lim->max_gids = 1 << (field & 0xf);
+ MTHCA_GET(stat_rate, outbox, QUERY_DEV_LIM_RATE_SUPPORT_OFFSET);
+ dev_lim->stat_rate_support = stat_rate;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_PKEY_OFFSET);
dev_lim->max_pkeys = 1 << (field & 0xf);
MTHCA_GET(dev_lim->flags, outbox, QUERY_DEV_LIM_FLAGS_OFFSET);
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
index e4ec35c40dd..2f976f2051d 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -146,6 +146,7 @@ struct mthca_dev_lim {
int max_vl;
int num_ports;
int max_gids;
+ u16 stat_rate_support;
int max_pkeys;
u32 flags;
int reserved_uars;
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 76aabc5bf37..205854e9c66 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -238,9 +238,9 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
spin_lock(&dev->cq_table.lock);
cq = mthca_array_get(&dev->cq_table.cq, cqn & (dev->limits.num_cqs - 1));
-
if (cq)
- atomic_inc(&cq->refcount);
+ ++cq->refcount;
+
spin_unlock(&dev->cq_table.lock);
if (!cq) {
@@ -254,8 +254,10 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
if (cq->ibcq.event_handler)
cq->ibcq.event_handler(&event, cq->ibcq.cq_context);
- if (atomic_dec_and_test(&cq->refcount))
+ spin_lock(&dev->cq_table.lock);
+ if (!--cq->refcount)
wake_up(&cq->wait);
+ spin_unlock(&dev->cq_table.lock);
}
static inline int is_recv_cqe(struct mthca_cqe *cqe)
@@ -267,23 +269,13 @@ static inline int is_recv_cqe(struct mthca_cqe *cqe)
return !(cqe->is_send & 0x80);
}
-void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
+void mthca_cq_clean(struct mthca_dev *dev, struct mthca_cq *cq, u32 qpn,
struct mthca_srq *srq)
{
- struct mthca_cq *cq;
struct mthca_cqe *cqe;
u32 prod_index;
int nfreed = 0;
- spin_lock_irq(&dev->cq_table.lock);
- cq = mthca_array_get(&dev->cq_table.cq, cqn & (dev->limits.num_cqs - 1));
- if (cq)
- atomic_inc(&cq->refcount);
- spin_unlock_irq(&dev->cq_table.lock);
-
- if (!cq)
- return;
-
spin_lock_irq(&cq->lock);
/*
@@ -301,7 +293,7 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
if (0)
mthca_dbg(dev, "Cleaning QPN %06x from CQN %06x; ci %d, pi %d\n",
- qpn, cqn, cq->cons_index, prod_index);
+ qpn, cq->cqn, cq->cons_index, prod_index);
/*
* Now sweep backwards through the CQ, removing CQ entries
@@ -325,8 +317,6 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
}
spin_unlock_irq(&cq->lock);
- if (atomic_dec_and_test(&cq->refcount))
- wake_up(&cq->wait);
}
void mthca_cq_resize_copy_cqes(struct mthca_cq *cq)
@@ -821,7 +811,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
}
spin_lock_init(&cq->lock);
- atomic_set(&cq->refcount, 1);
+ cq->refcount = 1;
init_waitqueue_head(&cq->wait);
memset(cq_context, 0, sizeof *cq_context);
@@ -896,6 +886,17 @@ err_out:
return err;
}
+static inline int get_cq_refcount(struct mthca_dev *dev, struct mthca_cq *cq)
+{
+ int c;
+
+ spin_lock_irq(&dev->cq_table.lock);
+ c = cq->refcount;
+ spin_unlock_irq(&dev->cq_table.lock);
+
+ return c;
+}
+
void mthca_free_cq(struct mthca_dev *dev,
struct mthca_cq *cq)
{
@@ -929,6 +930,7 @@ void mthca_free_cq(struct mthca_dev *dev,
spin_lock_irq(&dev->cq_table.lock);
mthca_array_clear(&dev->cq_table.cq,
cq->cqn & (dev->limits.num_cqs - 1));
+ --cq->refcount;
spin_unlock_irq(&dev->cq_table.lock);
if (dev->mthca_flags & MTHCA_FLAG_MSI_X)
@@ -936,8 +938,7 @@ void mthca_free_cq(struct mthca_dev *dev,
else
synchronize_irq(dev->pdev->irq);
- atomic_dec(&cq->refcount);
- wait_event(cq->wait, !atomic_read(&cq->refcount));
+ wait_event(cq->wait, !get_cq_refcount(dev, cq));
if (cq->is_kernel) {
mthca_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);
@@ -973,7 +974,7 @@ int __devinit mthca_init_cq_table(struct mthca_dev *dev)
return err;
}
-void __devexit mthca_cleanup_cq_table(struct mthca_dev *dev)
+void mthca_cleanup_cq_table(struct mthca_dev *dev)
{
mthca_array_cleanup(&dev->cq_table.cq, dev->limits.num_cqs);
mthca_alloc_cleanup(&dev->cq_table.alloc);
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index ad52edbefe9..f8160b8de09 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -151,6 +151,7 @@ struct mthca_limits {
int reserved_qps;
int num_srqs;
int max_srq_wqes;
+ int max_srq_sge;
int reserved_srqs;
int num_eecs;
int reserved_eecs;
@@ -172,6 +173,7 @@ struct mthca_limits {
int reserved_pds;
u32 page_size_cap;
u32 flags;
+ u16 stat_rate_support;
u8 port_width_cap;
};
@@ -353,10 +355,24 @@ struct mthca_dev {
struct ib_mad_agent *send_agent[MTHCA_MAX_PORTS][2];
struct ib_ah *sm_ah[MTHCA_MAX_PORTS];
spinlock_t sm_lock;
+ u8 rate[MTHCA_MAX_PORTS];
};
-#define mthca_dbg(mdev, format, arg...) \
- dev_dbg(&mdev->pdev->dev, format, ## arg)
+#ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
+extern int mthca_debug_level;
+
+#define mthca_dbg(mdev, format, arg...) \
+ do { \
+ if (mthca_debug_level) \
+ dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ## arg); \
+ } while (0)
+
+#else /* CONFIG_INFINIBAND_MTHCA_DEBUG */
+
+#define mthca_dbg(mdev, format, arg...) do { (void) mdev; } while (0)
+
+#endif /* CONFIG_INFINIBAND_MTHCA_DEBUG */
+
#define mthca_err(mdev, format, arg...) \
dev_err(&mdev->pdev->dev, format, ## arg)
#define mthca_info(mdev, format, arg...) \
@@ -480,7 +496,7 @@ void mthca_free_cq(struct mthca_dev *dev,
void mthca_cq_completion(struct mthca_dev *dev, u32 cqn);
void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
enum ib_event_type event_type);
-void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
+void mthca_cq_clean(struct mthca_dev *dev, struct mthca_cq *cq, u32 qpn,
struct mthca_srq *srq);
void mthca_cq_resize_copy_cqes(struct mthca_cq *cq);
int mthca_alloc_cq_buf(struct mthca_dev *dev, struct mthca_cq_buf *buf, int nent);
@@ -492,6 +508,7 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq);
int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
enum ib_srq_attr_mask attr_mask);
int mthca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
+int mthca_max_srq_sge(struct mthca_dev *dev);
void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
enum ib_event_type event_type);
void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr);
@@ -542,6 +559,8 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
struct ib_ud_header *header);
int mthca_ah_query(struct ib_ah *ibah, struct ib_ah_attr *attr);
int mthca_ah_grh_present(struct mthca_ah *ah);
+u8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port);
+enum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port);
int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index cbdc348fb68..99f109c3815 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -765,7 +765,7 @@ static int __devinit mthca_map_eq_regs(struct mthca_dev *dev)
}
-static void __devexit mthca_unmap_eq_regs(struct mthca_dev *dev)
+static void mthca_unmap_eq_regs(struct mthca_dev *dev)
{
if (mthca_is_memfree(dev)) {
mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
@@ -821,7 +821,7 @@ int __devinit mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
return ret;
}
-void __devexit mthca_unmap_eq_icm(struct mthca_dev *dev)
+void mthca_unmap_eq_icm(struct mthca_dev *dev)
{
u8 status;
@@ -954,7 +954,7 @@ err_out_free:
return err;
}
-void __devexit mthca_cleanup_eq_table(struct mthca_dev *dev)
+void mthca_cleanup_eq_table(struct mthca_dev *dev)
{
u8 status;
int i;
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index 4ace6a392f4..4730863ece9 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -49,6 +49,30 @@ enum {
MTHCA_VENDOR_CLASS2 = 0xa
};
+static int mthca_update_rate(struct mthca_dev *dev, u8 port_num)
+{
+ struct ib_port_attr *tprops = NULL;
+ int ret;
+
+ tprops = kmalloc(sizeof *tprops, GFP_KERNEL);
+ if (!tprops)
+ return -ENOMEM;
+
+ ret = ib_query_port(&dev->ib_dev, port_num, tprops);
+ if (ret) {
+ printk(KERN_WARNING "ib_query_port failed (%d) for %s port %d\n",
+ ret, dev->ib_dev.name, port_num);
+ goto out;
+ }
+
+ dev->rate[port_num - 1] = tprops->active_speed *
+ ib_width_enum_to_int(tprops->active_width);
+
+out:
+ kfree(tprops);
+ return ret;
+}
+
static void update_sm_ah(struct mthca_dev *dev,
u8 port_num, u16 lid, u8 sl)
{
@@ -90,6 +114,7 @@ static void smp_snoop(struct ib_device *ibdev,
mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) &&
mad->mad_hdr.method == IB_MGMT_METHOD_SET) {
if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) {
+ mthca_update_rate(to_mdev(ibdev), port_num);
update_sm_ah(to_mdev(ibdev), port_num,
be16_to_cpup((__be16 *) (mad->data + 58)),
(*(u8 *) (mad->data + 76)) & 0xf);
@@ -246,6 +271,7 @@ int mthca_create_agents(struct mthca_dev *dev)
{
struct ib_mad_agent *agent;
int p, q;
+ int ret;
spin_lock_init(&dev->sm_lock);
@@ -255,11 +281,23 @@ int mthca_create_agents(struct mthca_dev *dev)
q ? IB_QPT_GSI : IB_QPT_SMI,
NULL, 0, send_handler,
NULL, NULL);
- if (IS_ERR(agent))
+ if (IS_ERR(agent)) {
+ ret = PTR_ERR(agent);
goto err;
+ }
dev->send_agent[p][q] = agent;
}
+
+ for (p = 1; p <= dev->limits.num_ports; ++p) {
+ ret = mthca_update_rate(dev, p);
+ if (ret) {
+ mthca_err(dev, "Failed to obtain port %d rate."
+ " aborting.\n", p);
+ goto err;
+ }
+ }
+
return 0;
err:
@@ -268,10 +306,10 @@ err:
if (dev->send_agent[p][q])
ib_unregister_mad_agent(dev->send_agent[p][q]);
- return PTR_ERR(agent);
+ return ret;
}
-void mthca_free_agents(struct mthca_dev *dev)
+void __devexit mthca_free_agents(struct mthca_dev *dev)
{
struct ib_mad_agent *agent;
int p, q;
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 266f347c670..9b9ff7bff35 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -52,6 +52,14 @@ MODULE_DESCRIPTION("Mellanox InfiniBand HCA low-level driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRV_VERSION);
+#ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
+
+int mthca_debug_level = 0;
+module_param_named(debug_level, mthca_debug_level, int, 0644);
+MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
+
+#endif /* CONFIG_INFINIBAND_MTHCA_DEBUG */
+
#ifdef CONFIG_PCI_MSI
static int msi_x = 0;
@@ -69,6 +77,10 @@ MODULE_PARM_DESC(msi, "attempt to use MSI if nonzero");
#endif /* CONFIG_PCI_MSI */
+static int tune_pci = 0;
+module_param(tune_pci, int, 0444);
+MODULE_PARM_DESC(tune_pci, "increase PCI burst from the default set by BIOS if nonzero");
+
static const char mthca_version[] __devinitdata =
DRV_NAME ": Mellanox InfiniBand HCA driver v"
DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -90,6 +102,9 @@ static int __devinit mthca_tune_pci(struct mthca_dev *mdev)
int cap;
u16 val;
+ if (!tune_pci)
+ return 0;
+
/* First try to max out Read Byte Count */
cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX);
if (cap) {
@@ -176,6 +191,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
mdev->limits.reserved_srqs = dev_lim->reserved_srqs;
mdev->limits.reserved_eecs = dev_lim->reserved_eecs;
mdev->limits.max_desc_sz = dev_lim->max_desc_sz;
+ mdev->limits.max_srq_sge = mthca_max_srq_sge(mdev);
/*
* Subtract 1 from the limit because we need to allocate a
* spare CQE so the HCA HW can tell the difference between an
@@ -191,6 +207,18 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
mdev->limits.port_width_cap = dev_lim->max_port_width;
mdev->limits.page_size_cap = ~(u32) (dev_lim->min_page_sz - 1);
mdev->limits.flags = dev_lim->flags;
+ /*
+ * For old FW that doesn't return static rate support, use a
+ * value of 0x3 (only static rate values of 0 or 1 are handled),
+ * except on Sinai, where even old FW can handle static rate
+ * values of 2 and 3.
+ */
+ if (dev_lim->stat_rate_support)
+ mdev->limits.stat_rate_support = dev_lim->stat_rate_support;
+ else if (mdev->mthca_flags & MTHCA_FLAG_SINAI_OPT)
+ mdev->limits.stat_rate_support = 0xf;
+ else
+ mdev->limits.stat_rate_support = 0x3;
/* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
May be doable since hardware supports it for SRQ.
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index 9965bda9afe..47ca8a9b724 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -388,7 +388,7 @@ int __devinit mthca_init_mcg_table(struct mthca_dev *dev)
return 0;
}
-void __devexit mthca_cleanup_mcg_table(struct mthca_dev *dev)
+void mthca_cleanup_mcg_table(struct mthca_dev *dev)
{
mthca_alloc_cleanup(&dev->mcg_table.alloc);
}
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index 698b6212576..a486dec1707 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -170,7 +170,7 @@ err_out:
return -ENOMEM;
}
-static void __devexit mthca_buddy_cleanup(struct mthca_buddy *buddy)
+static void mthca_buddy_cleanup(struct mthca_buddy *buddy)
{
int i;
@@ -761,6 +761,7 @@ void mthca_arbel_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
int __devinit mthca_init_mr_table(struct mthca_dev *dev)
{
+ unsigned long addr;
int err, i;
err = mthca_alloc_init(&dev->mr_table.mpt_alloc,
@@ -796,9 +797,12 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev)
goto err_fmr_mpt;
}
+ addr = pci_resource_start(dev->pdev, 4) +
+ ((pci_resource_len(dev->pdev, 4) - 1) &
+ dev->mr_table.mpt_base);
+
dev->mr_table.tavor_fmr.mpt_base =
- ioremap(dev->mr_table.mpt_base,
- (1 << i) * sizeof (struct mthca_mpt_entry));
+ ioremap(addr, (1 << i) * sizeof(struct mthca_mpt_entry));
if (!dev->mr_table.tavor_fmr.mpt_base) {
mthca_warn(dev, "MPT ioremap for FMR failed.\n");
@@ -806,9 +810,12 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev)
goto err_fmr_mpt;
}
+ addr = pci_resource_start(dev->pdev, 4) +
+ ((pci_resource_len(dev->pdev, 4) - 1) &
+ dev->mr_table.mtt_base);
+
dev->mr_table.tavor_fmr.mtt_base =
- ioremap(dev->mr_table.mtt_base,
- (1 << i) * MTHCA_MTT_SEG_SIZE);
+ ioremap(addr, (1 << i) * MTHCA_MTT_SEG_SIZE);
if (!dev->mr_table.tavor_fmr.mtt_base) {
mthca_warn(dev, "MTT ioremap for FMR failed.\n");
err = -ENOMEM;
@@ -866,7 +873,7 @@ err_mtt_buddy:
return err;
}
-void __devexit mthca_cleanup_mr_table(struct mthca_dev *dev)
+void mthca_cleanup_mr_table(struct mthca_dev *dev)
{
/* XXX check if any MRs are still allocated? */
if (dev->limits.fmr_reserved_mtts)
diff --git a/drivers/infiniband/hw/mthca/mthca_pd.c b/drivers/infiniband/hw/mthca/mthca_pd.c
index 105fc5faadd..59df51614c8 100644
--- a/drivers/infiniband/hw/mthca/mthca_pd.c
+++ b/drivers/infiniband/hw/mthca/mthca_pd.c
@@ -77,7 +77,7 @@ int __devinit mthca_init_pd_table(struct mthca_dev *dev)
dev->limits.reserved_pds);
}
-void __devexit mthca_cleanup_pd_table(struct mthca_dev *dev)
+void mthca_cleanup_pd_table(struct mthca_dev *dev)
{
/* XXX check if any PDs are still allocated? */
mthca_alloc_cleanup(&dev->pd_table.alloc);
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 2c250bc11c3..a2eae8a3016 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -106,7 +106,7 @@ static int mthca_query_device(struct ib_device *ibdev,
props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp;
props->max_srq = mdev->limits.num_srqs - mdev->limits.reserved_srqs;
props->max_srq_wr = mdev->limits.max_srq_wqes;
- props->max_srq_sge = mdev->limits.max_sg;
+ props->max_srq_sge = mdev->limits.max_srq_sge;
props->local_ca_ack_delay = mdev->limits.local_ca_ack_delay;
props->atomic_cap = mdev->limits.flags & DEV_LIM_FLAG_ATOMIC ?
IB_ATOMIC_HCA : IB_ATOMIC_NONE;
@@ -306,7 +306,7 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
goto out;
}
- memcpy(gid->raw + 8, out_mad->data + (index % 8) * 16, 8);
+ memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8);
out:
kfree(in_mad);
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 2e7f5213696..179a8f610d0 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -139,11 +139,12 @@ struct mthca_ah {
* a qp may be locked, with the send cq locked first. No other
* nesting should be done.
*
- * Each struct mthca_cq/qp also has an atomic_t ref count. The
- * pointer from the cq/qp_table to the struct counts as one reference.
- * This reference also is good for access through the consumer API, so
- * modifying the CQ/QP etc doesn't need to take another reference.
- * Access because of a completion being polled does need a reference.
+ * Each struct mthca_cq/qp also has an ref count, protected by the
+ * corresponding table lock. The pointer from the cq/qp_table to the
+ * struct counts as one reference. This reference also is good for
+ * access through the consumer API, so modifying the CQ/QP etc doesn't
+ * need to take another reference. Access to a QP because of a
+ * completion being polled does not need a reference either.
*
* Finally, each struct mthca_cq/qp has a wait_queue_head_t for the
* destroy function to sleep on.
@@ -159,8 +160,9 @@ struct mthca_ah {
* - decrement ref count; if zero, wake up waiters
*
* To destroy a CQ/QP, we can do the following:
- * - lock cq/qp_table, remove pointer, unlock cq/qp_table lock
- * - decrement ref count
+ * - lock cq/qp_table
+ * - remove pointer and decrement ref count
+ * - unlock cq/qp_table lock
* - wait_event until ref count is zero
*
* It is the consumer's responsibilty to make sure that no QP
@@ -197,7 +199,7 @@ struct mthca_cq_resize {
struct mthca_cq {
struct ib_cq ibcq;
spinlock_t lock;
- atomic_t refcount;
+ int refcount;
int cqn;
u32 cons_index;
struct mthca_cq_buf buf;
@@ -217,7 +219,7 @@ struct mthca_cq {
struct mthca_srq {
struct ib_srq ibsrq;
spinlock_t lock;
- atomic_t refcount;
+ int refcount;
int srqn;
int max;
int max_gs;
@@ -254,9 +256,11 @@ struct mthca_wq {
struct mthca_qp {
struct ib_qp ibqp;
- atomic_t refcount;
+ int refcount;
u32 qpn;
int is_direct;
+ u8 port; /* for SQP and memfree use only */
+ u8 alt_port; /* for memfree use only */
u8 transport;
u8 state;
u8 atomic_rd_en;
@@ -278,7 +282,6 @@ struct mthca_qp {
struct mthca_sqp {
struct mthca_qp qp;
- int port;
int pkey_index;
u32 qkey;
u32 send_psn;
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 1bc2678c2fa..07c13be07a4 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -240,7 +240,7 @@ void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
spin_lock(&dev->qp_table.lock);
qp = mthca_array_get(&dev->qp_table.qp, qpn & (dev->limits.num_qps - 1));
if (qp)
- atomic_inc(&qp->refcount);
+ ++qp->refcount;
spin_unlock(&dev->qp_table.lock);
if (!qp) {
@@ -248,14 +248,19 @@ void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
return;
}
+ if (event_type == IB_EVENT_PATH_MIG)
+ qp->port = qp->alt_port;
+
event.device = &dev->ib_dev;
event.event = event_type;
event.element.qp = &qp->ibqp;
if (qp->ibqp.event_handler)
qp->ibqp.event_handler(&event, qp->ibqp.qp_context);
- if (atomic_dec_and_test(&qp->refcount))
+ spin_lock(&dev->qp_table.lock);
+ if (!--qp->refcount)
wake_up(&qp->wait);
+ spin_unlock(&dev->qp_table.lock);
}
static int to_mthca_state(enum ib_qp_state ib_state)
@@ -392,10 +397,16 @@ static void to_ib_ah_attr(struct mthca_dev *dev, struct ib_ah_attr *ib_ah_attr,
{
memset(ib_ah_attr, 0, sizeof *path);
ib_ah_attr->port_num = (be32_to_cpu(path->port_pkey) >> 24) & 0x3;
+
+ if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->limits.num_ports)
+ return;
+
ib_ah_attr->dlid = be16_to_cpu(path->rlid);
ib_ah_attr->sl = be32_to_cpu(path->sl_tclass_flowlabel) >> 28;
ib_ah_attr->src_path_bits = path->g_mylmc & 0x7f;
- ib_ah_attr->static_rate = path->static_rate & 0x7;
+ ib_ah_attr->static_rate = mthca_rate_to_ib(dev,
+ path->static_rate & 0x7,
+ ib_ah_attr->port_num);
ib_ah_attr->ah_flags = (path->g_mylmc & (1 << 7)) ? IB_AH_GRH : 0;
if (ib_ah_attr->ah_flags) {
ib_ah_attr->grh.sgid_index = path->mgid_index & (dev->limits.gid_table_len - 1);
@@ -455,8 +466,10 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
qp_attr->cap.max_recv_sge = qp->rq.max_gs;
qp_attr->cap.max_inline_data = qp->max_inline_data;
- to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
- to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
+ if (qp->transport == RC || qp->transport == UC) {
+ to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
+ to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
+ }
qp_attr->pkey_index = be32_to_cpu(context->pri_path.port_pkey) & 0x7f;
qp_attr->alt_pkey_index = be32_to_cpu(context->alt_path.port_pkey) & 0x7f;
@@ -484,11 +497,11 @@ out:
}
static int mthca_path_set(struct mthca_dev *dev, struct ib_ah_attr *ah,
- struct mthca_qp_path *path)
+ struct mthca_qp_path *path, u8 port)
{
path->g_mylmc = ah->src_path_bits & 0x7f;
path->rlid = cpu_to_be16(ah->dlid);
- path->static_rate = !!ah->static_rate;
+ path->static_rate = mthca_get_rate(dev, ah->static_rate, port);
if (ah->ah_flags & IB_AH_GRH) {
if (ah->grh.sgid_index >= dev->limits.gid_table_len) {
@@ -634,7 +647,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
if (qp->transport == MLX)
qp_context->pri_path.port_pkey |=
- cpu_to_be32(to_msqp(qp)->port << 24);
+ cpu_to_be32(qp->port << 24);
else {
if (attr_mask & IB_QP_PORT) {
qp_context->pri_path.port_pkey |=
@@ -657,7 +670,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
}
if (attr_mask & IB_QP_AV) {
- if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path))
+ if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path,
+ attr_mask & IB_QP_PORT ? attr->port_num : qp->port))
return -EINVAL;
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);
@@ -681,7 +695,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
return -EINVAL;
}
- if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path))
+ if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path,
+ attr->alt_ah_attr.port_num))
return -EINVAL;
qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index |
@@ -791,6 +806,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp->atomic_rd_en = attr->qp_access_flags;
if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
qp->resp_depth = attr->max_dest_rd_atomic;
+ if (attr_mask & IB_QP_PORT)
+ qp->port = attr->port_num;
+ if (attr_mask & IB_QP_ALT_PATH)
+ qp->alt_port = attr->alt_port_num;
if (is_sqp(dev, qp))
store_attrs(to_msqp(qp), attr, attr_mask);
@@ -802,13 +821,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
if (is_qp0(dev, qp)) {
if (cur_state != IB_QPS_RTR &&
new_state == IB_QPS_RTR)
- init_port(dev, to_msqp(qp)->port);
+ init_port(dev, qp->port);
if (cur_state != IB_QPS_RESET &&
cur_state != IB_QPS_ERR &&
(new_state == IB_QPS_RESET ||
new_state == IB_QPS_ERR))
- mthca_CLOSE_IB(dev, to_msqp(qp)->port, &status);
+ mthca_CLOSE_IB(dev, qp->port, &status);
}
/*
@@ -816,10 +835,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
* entries and reinitialize the QP.
*/
if (new_state == IB_QPS_RESET && !qp->ibqp.uobject) {
- mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
+ mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq), qp->qpn,
qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
- mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn,
+ mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn,
qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
mthca_wq_init(&qp->sq);
@@ -1079,7 +1098,7 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
int ret;
int i;
- atomic_set(&qp->refcount, 1);
+ qp->refcount = 1;
init_waitqueue_head(&qp->wait);
qp->state = IB_QPS_RESET;
qp->atomic_rd_en = 0;
@@ -1212,6 +1231,9 @@ int mthca_alloc_qp(struct mthca_dev *dev,
if (qp->qpn == -1)
return -ENOMEM;
+ /* initialize port to zero for error-catching. */
+ qp->port = 0;
+
err = mthca_alloc_qp_common(dev, pd, send_cq, recv_cq,
send_policy, qp);
if (err) {
@@ -1261,7 +1283,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
if (err)
goto err_out;
- sqp->port = port;
+ sqp->qp.port = port;
sqp->qp.qpn = mqpn;
sqp->qp.transport = MLX;
@@ -1298,6 +1320,17 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
return err;
}
+static inline int get_qp_refcount(struct mthca_dev *dev, struct mthca_qp *qp)
+{
+ int c;
+
+ spin_lock_irq(&dev->qp_table.lock);
+ c = qp->refcount;
+ spin_unlock_irq(&dev->qp_table.lock);
+
+ return c;
+}
+
void mthca_free_qp(struct mthca_dev *dev,
struct mthca_qp *qp)
{
@@ -1319,14 +1352,14 @@ void mthca_free_qp(struct mthca_dev *dev,
spin_lock(&dev->qp_table.lock);
mthca_array_clear(&dev->qp_table.qp,
qp->qpn & (dev->limits.num_qps - 1));
+ --qp->refcount;
spin_unlock(&dev->qp_table.lock);
if (send_cq != recv_cq)
spin_unlock(&recv_cq->lock);
spin_unlock_irq(&send_cq->lock);
- atomic_dec(&qp->refcount);
- wait_event(qp->wait, !atomic_read(&qp->refcount));
+ wait_event(qp->wait, !get_qp_refcount(dev, qp));
if (qp->state != IB_QPS_RESET)
mthca_MODIFY_QP(dev, qp->state, IB_QPS_RESET, qp->qpn, 0,
@@ -1338,10 +1371,10 @@ void mthca_free_qp(struct mthca_dev *dev,
* unref the mem-free tables and free the QPN in our table.
*/
if (!qp->ibqp.uobject) {
- mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
+ mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq), qp->qpn,
qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
- mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn,
+ mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn,
qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
mthca_free_memfree(dev, qp);
@@ -1404,10 +1437,10 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
if (!sqp->qp.ibqp.qp_num)
- ib_get_cached_pkey(&dev->ib_dev, sqp->port,
+ ib_get_cached_pkey(&dev->ib_dev, sqp->qp.port,
sqp->pkey_index, &pkey);
else
- ib_get_cached_pkey(&dev->ib_dev, sqp->port,
+ ib_get_cached_pkey(&dev->ib_dev, sqp->qp.port,
wr->wr.ud.pkey_index, &pkey);
sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
@@ -1694,23 +1727,7 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
ind = qp->rq.next_ind;
- for (nreq = 0; wr; ++nreq, wr = wr->next) {
- if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
- nreq = 0;
-
- doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
- doorbell[1] = cpu_to_be32(qp->qpn << 8);
-
- wmb();
-
- mthca_write64(doorbell,
- dev->kar + MTHCA_RECEIVE_DOORBELL,
- MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
-
- qp->rq.head += MTHCA_TAVOR_MAX_WQES_PER_RECV_DB;
- size0 = 0;
- }
-
+ for (nreq = 0; wr; wr = wr->next) {
if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {
mthca_err(dev, "RQ %06x full (%u head, %u tail,"
" %d max, %d nreq)\n", qp->qpn,
@@ -1764,6 +1781,23 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
++ind;
if (unlikely(ind >= qp->rq.max))
ind -= qp->rq.max;
+
+ ++nreq;
+ if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
+ nreq = 0;
+
+ doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
+ doorbell[1] = cpu_to_be32(qp->qpn << 8);
+
+ wmb();
+
+ mthca_write64(doorbell,
+ dev->kar + MTHCA_RECEIVE_DOORBELL,
+ MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+
+ qp->rq.head += MTHCA_TAVOR_MAX_WQES_PER_RECV_DB;
+ size0 = 0;
+ }
}
out:
@@ -2204,7 +2238,7 @@ int __devinit mthca_init_qp_table(struct mthca_dev *dev)
return err;
}
-void __devexit mthca_cleanup_qp_table(struct mthca_dev *dev)
+void mthca_cleanup_qp_table(struct mthca_dev *dev)
{
int i;
u8 status;
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 0cfd1580221..b292fefa3b4 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -192,7 +192,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
/* Sanity check SRQ size before proceeding */
if (attr->max_wr > dev->limits.max_srq_wqes ||
- attr->max_sge > dev->limits.max_sg)
+ attr->max_sge > dev->limits.max_srq_sge)
return -EINVAL;
srq->max = attr->max_wr;
@@ -206,7 +206,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
roundup_pow_of_two(sizeof (struct mthca_next_seg) +
srq->max_gs * sizeof (struct mthca_data_seg)));
- if (ds > dev->limits.max_desc_sz)
+ if (!mthca_is_memfree(dev) && (ds > dev->limits.max_desc_sz))
return -EINVAL;
srq->wqe_shift = long_log2(ds);
@@ -241,7 +241,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
goto err_out_mailbox;
spin_lock_init(&srq->lock);
- atomic_set(&srq->refcount, 1);
+ srq->refcount = 1;
init_waitqueue_head(&srq->wait);
if (mthca_is_memfree(dev))
@@ -308,6 +308,17 @@ err_out:
return err;
}
+static inline int get_srq_refcount(struct mthca_dev *dev, struct mthca_srq *srq)
+{
+ int c;
+
+ spin_lock_irq(&dev->srq_table.lock);
+ c = srq->refcount;
+ spin_unlock_irq(&dev->srq_table.lock);
+
+ return c;
+}
+
void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
{
struct mthca_mailbox *mailbox;
@@ -329,10 +340,10 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
spin_lock_irq(&dev->srq_table.lock);
mthca_array_clear(&dev->srq_table.srq,
srq->srqn & (dev->limits.num_srqs - 1));
+ --srq->refcount;
spin_unlock_irq(&dev->srq_table.lock);
- atomic_dec(&srq->refcount);
- wait_event(srq->wait, !atomic_read(&srq->refcount));
+ wait_event(srq->wait, !get_srq_refcount(dev, srq));
if (!srq->ibsrq.uobject) {
mthca_free_srq_buf(dev, srq);
@@ -414,7 +425,7 @@ void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
spin_lock(&dev->srq_table.lock);
srq = mthca_array_get(&dev->srq_table.srq, srqn & (dev->limits.num_srqs - 1));
if (srq)
- atomic_inc(&srq->refcount);
+ ++srq->refcount;
spin_unlock(&dev->srq_table.lock);
if (!srq) {
@@ -431,8 +442,10 @@ void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
srq->ibsrq.event_handler(&event, srq->ibsrq.srq_context);
out:
- if (atomic_dec_and_test(&srq->refcount))
+ spin_lock(&dev->srq_table.lock);
+ if (!--srq->refcount)
wake_up(&srq->wait);
+ spin_unlock(&dev->srq_table.lock);
}
/*
@@ -477,26 +490,7 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
first_ind = srq->first_free;
- for (nreq = 0; wr; ++nreq, wr = wr->next) {
- if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
- nreq = 0;
-
- doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
- doorbell[1] = cpu_to_be32(srq->srqn << 8);
-
- /*
- * Make sure that descriptors are written
- * before doorbell is rung.
- */
- wmb();
-
- mthca_write64(doorbell,
- dev->kar + MTHCA_RECEIVE_DOORBELL,
- MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
-
- first_ind = srq->first_free;
- }
-
+ for (nreq = 0; wr; wr = wr->next) {
ind = srq->first_free;
if (ind < 0) {
@@ -556,6 +550,26 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
srq->wrid[ind] = wr->wr_id;
srq->first_free = next_ind;
+
+ ++nreq;
+ if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
+ nreq = 0;
+
+ doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
+ doorbell[1] = cpu_to_be32(srq->srqn << 8);
+
+ /*
+ * Make sure that descriptors are written
+ * before doorbell is rung.
+ */
+ wmb();
+
+ mthca_write64(doorbell,
+ dev->kar + MTHCA_RECEIVE_DOORBELL,
+ MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+
+ first_ind = srq->first_free;
+ }
}
if (likely(nreq)) {
@@ -660,6 +674,31 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
return err;
}
+int mthca_max_srq_sge(struct mthca_dev *dev)
+{
+ if (mthca_is_memfree(dev))
+ return dev->limits.max_sg;
+
+ /*
+ * SRQ allocations are based on powers of 2 for Tavor,
+ * (although they only need to be multiples of 16 bytes).
+ *
+ * Therefore, we need to base the max number of sg entries on
+ * the largest power of 2 descriptor size that is <= to the
+ * actual max WQE descriptor size, rather than return the
+ * max_sg value given by the firmware (which is based on WQE
+ * sizes as multiples of 16, not powers of 2).
+ *
+ * If SRQ implementation is changed for Tavor to be based on
+ * multiples of 16, the calculation below can be deleted and
+ * the FW max_sg value returned.
+ */
+ return min_t(int, dev->limits.max_sg,
+ ((1 << (fls(dev->limits.max_desc_sz) - 1)) -
+ sizeof (struct mthca_next_seg)) /
+ sizeof (struct mthca_data_seg));
+}
+
int __devinit mthca_init_srq_table(struct mthca_dev *dev)
{
int err;
@@ -684,7 +723,7 @@ int __devinit mthca_init_srq_table(struct mthca_dev *dev)
return err;
}
-void __devexit mthca_cleanup_srq_table(struct mthca_dev *dev)
+void mthca_cleanup_srq_table(struct mthca_dev *dev)
{
if (!(dev->mthca_flags & MTHCA_FLAG_SRQ))
return;
diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig
index 8d2e04cac68..13d6d01c72c 100644
--- a/drivers/infiniband/ulp/ipoib/Kconfig
+++ b/drivers/infiniband/ulp/ipoib/Kconfig
@@ -10,8 +10,9 @@ config INFINIBAND_IPOIB
group: <http://www.ietf.org/html.charters/ipoib-charter.html>.
config INFINIBAND_IPOIB_DEBUG
- bool "IP-over-InfiniBand debugging"
+ bool "IP-over-InfiniBand debugging" if EMBEDDED
depends on INFINIBAND_IPOIB
+ default y
---help---
This option causes debugging code to be compiled into the
IPoIB driver. The output can be turned on via the
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index b640107fb73..12a1e0572ef 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -65,6 +65,8 @@ enum {
IPOIB_RX_RING_SIZE = 128,
IPOIB_TX_RING_SIZE = 64,
+ IPOIB_MAX_QUEUE_SIZE = 8192,
+ IPOIB_MIN_QUEUE_SIZE = 2,
IPOIB_NUM_WC = 4,
@@ -230,6 +232,9 @@ static inline struct ipoib_neigh **to_ipoib_neigh(struct neighbour *neigh)
INFINIBAND_ALEN, sizeof(void *));
}
+struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh);
+void ipoib_neigh_free(struct ipoib_neigh *neigh);
+
extern struct workqueue_struct *ipoib_workqueue;
/* functions */
@@ -329,6 +334,8 @@ static inline void ipoib_unregister_debugfs(void) { }
#define ipoib_warn(priv, format, arg...) \
ipoib_printk(KERN_WARNING, priv, format , ## arg)
+extern int ipoib_sendq_size;
+extern int ipoib_recvq_size;
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
extern int ipoib_debug_level;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index 685258e3403..5dde380e8db 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -213,7 +213,7 @@ static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr)
gid_buf, path.pathrec.dlid ? "yes" : "no");
if (path.pathrec.dlid) {
- rate = ib_sa_rate_enum_to_int(path.pathrec.rate) * 25;
+ rate = ib_rate_to_mult(path.pathrec.rate) * 25;
seq_printf(file,
" DLID: 0x%04x\n"
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index ed65202878d..8406839b91c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -161,7 +161,7 @@ static int ipoib_ib_post_receives(struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev);
int i;
- for (i = 0; i < IPOIB_RX_RING_SIZE; ++i) {
+ for (i = 0; i < ipoib_recvq_size; ++i) {
if (ipoib_alloc_rx_skb(dev, i)) {
ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
return -ENOMEM;
@@ -187,7 +187,7 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
if (wr_id & IPOIB_OP_RECV) {
wr_id &= ~IPOIB_OP_RECV;
- if (wr_id < IPOIB_RX_RING_SIZE) {
+ if (wr_id < ipoib_recvq_size) {
struct sk_buff *skb = priv->rx_ring[wr_id].skb;
dma_addr_t addr = priv->rx_ring[wr_id].mapping;
@@ -252,9 +252,9 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
struct ipoib_tx_buf *tx_req;
unsigned long flags;
- if (wr_id >= IPOIB_TX_RING_SIZE) {
+ if (wr_id >= ipoib_sendq_size) {
ipoib_warn(priv, "completion event with wrid %d (> %d)\n",
- wr_id, IPOIB_TX_RING_SIZE);
+ wr_id, ipoib_sendq_size);
return;
}
@@ -275,7 +275,8 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
spin_lock_irqsave(&priv->tx_lock, flags);
++priv->tx_tail;
if (netif_queue_stopped(dev) &&
- priv->tx_head - priv->tx_tail <= IPOIB_TX_RING_SIZE / 2)
+ test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags) &&
+ priv->tx_head - priv->tx_tail <= ipoib_sendq_size >> 1)
netif_wake_queue(dev);
spin_unlock_irqrestore(&priv->tx_lock, flags);
@@ -344,13 +345,13 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
* means we have to make sure everything is properly recorded and
* our state is consistent before we call post_send().
*/
- tx_req = &priv->tx_ring[priv->tx_head & (IPOIB_TX_RING_SIZE - 1)];
+ tx_req = &priv->tx_ring[priv->tx_head & (ipoib_sendq_size - 1)];
tx_req->skb = skb;
addr = dma_map_single(priv->ca->dma_device, skb->data, skb->len,
DMA_TO_DEVICE);
pci_unmap_addr_set(tx_req, mapping, addr);
- if (unlikely(post_send(priv, priv->tx_head & (IPOIB_TX_RING_SIZE - 1),
+ if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
address->ah, qpn, addr, skb->len))) {
ipoib_warn(priv, "post_send failed\n");
++priv->stats.tx_errors;
@@ -363,7 +364,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
address->last_send = priv->tx_head;
++priv->tx_head;
- if (priv->tx_head - priv->tx_tail == IPOIB_TX_RING_SIZE) {
+ if (priv->tx_head - priv->tx_tail == ipoib_sendq_size) {
ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
netif_stop_queue(dev);
}
@@ -488,7 +489,7 @@ static int recvs_pending(struct net_device *dev)
int pending = 0;
int i;
- for (i = 0; i < IPOIB_RX_RING_SIZE; ++i)
+ for (i = 0; i < ipoib_recvq_size; ++i)
if (priv->rx_ring[i].skb)
++pending;
@@ -527,7 +528,7 @@ int ipoib_ib_dev_stop(struct net_device *dev)
*/
while ((int) priv->tx_tail - (int) priv->tx_head < 0) {
tx_req = &priv->tx_ring[priv->tx_tail &
- (IPOIB_TX_RING_SIZE - 1)];
+ (ipoib_sendq_size - 1)];
dma_unmap_single(priv->ca->dma_device,
pci_unmap_addr(tx_req, mapping),
tx_req->skb->len,
@@ -536,7 +537,7 @@ int ipoib_ib_dev_stop(struct net_device *dev)
++priv->tx_tail;
}
- for (i = 0; i < IPOIB_RX_RING_SIZE; ++i)
+ for (i = 0; i < ipoib_recvq_size; ++i)
if (priv->rx_ring[i].skb) {
dma_unmap_single(priv->ca->dma_device,
pci_unmap_addr(&priv->rx_ring[i],
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 53a32f65788..cb078a7d0bf 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -41,6 +41,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/kernel.h>
#include <linux/if_arp.h> /* For ARPHRD_xxx */
@@ -53,6 +54,14 @@ MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("IP-over-InfiniBand net driver");
MODULE_LICENSE("Dual BSD/GPL");
+int ipoib_sendq_size __read_mostly = IPOIB_TX_RING_SIZE;
+int ipoib_recvq_size __read_mostly = IPOIB_RX_RING_SIZE;
+
+module_param_named(send_queue_size, ipoib_sendq_size, int, 0444);
+MODULE_PARM_DESC(send_queue_size, "Number of descriptors in send queue");
+module_param_named(recv_queue_size, ipoib_recvq_size, int, 0444);
+MODULE_PARM_DESC(recv_queue_size, "Number of descriptors in receive queue");
+
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
int ipoib_debug_level;
@@ -252,8 +261,8 @@ static void path_free(struct net_device *dev, struct ipoib_path *path)
*/
if (neigh->ah)
ipoib_put_ah(neigh->ah);
- *to_ipoib_neigh(neigh->neighbour) = NULL;
- kfree(neigh);
+
+ ipoib_neigh_free(neigh);
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -327,9 +336,8 @@ void ipoib_flush_paths(struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_path *path, *tp;
LIST_HEAD(remove_list);
- unsigned long flags;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irq(&priv->lock);
list_splice(&priv->path_list, &remove_list);
INIT_LIST_HEAD(&priv->path_list);
@@ -337,14 +345,15 @@ void ipoib_flush_paths(struct net_device *dev)
list_for_each_entry(path, &remove_list, list)
rb_erase(&path->rb_node, &priv->path_tree);
- spin_unlock_irqrestore(&priv->lock, flags);
-
list_for_each_entry_safe(path, tp, &remove_list, list) {
if (path->query)
ib_sa_cancel_query(path->query_id, path->query);
+ spin_unlock_irq(&priv->lock);
wait_for_completion(&path->done);
path_free(dev, path);
+ spin_lock_irq(&priv->lock);
}
+ spin_unlock_irq(&priv->lock);
}
static void path_rec_completion(int status,
@@ -373,16 +382,9 @@ static void path_rec_completion(int status,
struct ib_ah_attr av = {
.dlid = be16_to_cpu(pathrec->dlid),
.sl = pathrec->sl,
- .port_num = priv->port
+ .port_num = priv->port,
+ .static_rate = pathrec->rate
};
- int path_rate = ib_sa_rate_enum_to_int(pathrec->rate);
-
- if (path_rate > 0 && priv->local_rate > path_rate)
- av.static_rate = (priv->local_rate - 1) / path_rate;
-
- ipoib_dbg(priv, "static_rate %d for local port %dX, path %dX\n",
- av.static_rate, priv->local_rate,
- ib_sa_rate_enum_to_int(pathrec->rate));
ah = ipoib_create_ah(dev, priv->pd, &av);
}
@@ -481,7 +483,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
struct ipoib_path *path;
struct ipoib_neigh *neigh;
- neigh = kmalloc(sizeof *neigh, GFP_ATOMIC);
+ neigh = ipoib_neigh_alloc(skb->dst->neighbour);
if (!neigh) {
++priv->stats.tx_dropped;
dev_kfree_skb_any(skb);
@@ -489,8 +491,6 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
}
skb_queue_head_init(&neigh->queue);
- neigh->neighbour = skb->dst->neighbour;
- *to_ipoib_neigh(skb->dst->neighbour) = neigh;
/*
* We can only be called from ipoib_start_xmit, so we're
@@ -503,7 +503,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
path = path_rec_create(dev,
(union ib_gid *) (skb->dst->neighbour->ha + 4));
if (!path)
- goto err;
+ goto err_path;
__path_add(dev, path);
}
@@ -521,17 +521,17 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
__skb_queue_tail(&neigh->queue, skb);
if (!path->query && path_rec_start(dev, path))
- goto err;
+ goto err_list;
}
spin_unlock(&priv->lock);
return;
-err:
- *to_ipoib_neigh(skb->dst->neighbour) = NULL;
+err_list:
list_del(&neigh->list);
- kfree(neigh);
+err_path:
+ ipoib_neigh_free(neigh);
++priv->stats.tx_dropped;
dev_kfree_skb_any(skb);
@@ -723,7 +723,7 @@ static int ipoib_hard_header(struct sk_buff *skb,
* destination address onto the front of the skb so we can
* figure out where to send the packet later.
*/
- if (!skb->dst || !skb->dst->neighbour) {
+ if ((!skb->dst || !skb->dst->neighbour) && daddr) {
struct ipoib_pseudoheader *phdr =
(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
@@ -763,8 +763,7 @@ static void ipoib_neigh_destructor(struct neighbour *n)
if (neigh->ah)
ah = neigh->ah;
list_del(&neigh->list);
- *to_ipoib_neigh(n) = NULL;
- kfree(neigh);
+ ipoib_neigh_free(neigh);
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -773,6 +772,26 @@ static void ipoib_neigh_destructor(struct neighbour *n)
ipoib_put_ah(ah);
}
+struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
+{
+ struct ipoib_neigh *neigh;
+
+ neigh = kmalloc(sizeof *neigh, GFP_ATOMIC);
+ if (!neigh)
+ return NULL;
+
+ neigh->neighbour = neighbour;
+ *to_ipoib_neigh(neighbour) = neigh;
+
+ return neigh;
+}
+
+void ipoib_neigh_free(struct ipoib_neigh *neigh)
+{
+ *to_ipoib_neigh(neigh->neighbour) = NULL;
+ kfree(neigh);
+}
+
static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms)
{
parms->neigh_destructor = ipoib_neigh_destructor;
@@ -785,20 +804,19 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
struct ipoib_dev_priv *priv = netdev_priv(dev);
/* Allocate RX/TX "rings" to hold queued skbs */
-
- priv->rx_ring = kzalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_rx_buf),
+ priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring,
GFP_KERNEL);
if (!priv->rx_ring) {
printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n",
- ca->name, IPOIB_RX_RING_SIZE);
+ ca->name, ipoib_recvq_size);
goto out;
}
- priv->tx_ring = kzalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_tx_buf),
+ priv->tx_ring = kzalloc(ipoib_sendq_size * sizeof *priv->tx_ring,
GFP_KERNEL);
if (!priv->tx_ring) {
printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n",
- ca->name, IPOIB_TX_RING_SIZE);
+ ca->name, ipoib_sendq_size);
goto out_rx_ring_cleanup;
}
@@ -866,7 +884,7 @@ static void ipoib_setup(struct net_device *dev)
dev->hard_header_len = IPOIB_ENCAP_LEN + INFINIBAND_ALEN;
dev->addr_len = INFINIBAND_ALEN;
dev->type = ARPHRD_INFINIBAND;
- dev->tx_queue_len = IPOIB_TX_RING_SIZE * 2;
+ dev->tx_queue_len = ipoib_sendq_size * 2;
dev->features = NETIF_F_VLAN_CHALLENGED | NETIF_F_LLTX;
/* MTU will be reset when mcast join happens */
@@ -1118,6 +1136,14 @@ static int __init ipoib_init_module(void)
{
int ret;
+ ipoib_recvq_size = roundup_pow_of_two(ipoib_recvq_size);
+ ipoib_recvq_size = min(ipoib_recvq_size, IPOIB_MAX_QUEUE_SIZE);
+ ipoib_recvq_size = max(ipoib_recvq_size, IPOIB_MIN_QUEUE_SIZE);
+
+ ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size);
+ ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE);
+ ipoib_sendq_size = max(ipoib_sendq_size, IPOIB_MIN_QUEUE_SIZE);
+
ret = ipoib_register_debugfs();
if (ret)
return ret;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 93c462eaf4f..1dae4b23825 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -114,8 +114,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
*/
if (neigh->ah)
ipoib_put_ah(neigh->ah);
- *to_ipoib_neigh(neigh->neighbour) = NULL;
- kfree(neigh);
+ ipoib_neigh_free(neigh);
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -251,6 +250,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
.port_num = priv->port,
.sl = mcast->mcmember.sl,
.ah_flags = IB_AH_GRH,
+ .static_rate = mcast->mcmember.rate,
.grh = {
.flow_label = be32_to_cpu(mcast->mcmember.flow_label),
.hop_limit = mcast->mcmember.hop_limit,
@@ -258,17 +258,8 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
.traffic_class = mcast->mcmember.traffic_class
}
};
- int path_rate = ib_sa_rate_enum_to_int(mcast->mcmember.rate);
-
av.grh.dgid = mcast->mcmember.mgid;
- if (path_rate > 0 && priv->local_rate > path_rate)
- av.static_rate = (priv->local_rate - 1) / path_rate;
-
- ipoib_dbg_mcast(priv, "static_rate %d for local port %dX, mcmember %dX\n",
- av.static_rate, priv->local_rate,
- ib_sa_rate_enum_to_int(mcast->mcmember.rate));
-
ah = ipoib_create_ah(dev, priv->pd, &av);
if (!ah) {
ipoib_warn(priv, "ib_address_create failed\n");
@@ -618,6 +609,22 @@ int ipoib_mcast_start_thread(struct net_device *dev)
return 0;
}
+static void wait_for_mcast_join(struct ipoib_dev_priv *priv,
+ struct ipoib_mcast *mcast)
+{
+ spin_lock_irq(&priv->lock);
+ if (mcast && mcast->query) {
+ ib_sa_cancel_query(mcast->query_id, mcast->query);
+ mcast->query = NULL;
+ spin_unlock_irq(&priv->lock);
+ ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n",
+ IPOIB_GID_ARG(mcast->mcmember.mgid));
+ wait_for_completion(&mcast->done);
+ }
+ else
+ spin_unlock_irq(&priv->lock);
+}
+
int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -637,28 +644,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
if (flush)
flush_workqueue(ipoib_workqueue);
- spin_lock_irq(&priv->lock);
- if (priv->broadcast && priv->broadcast->query) {
- ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query);
- priv->broadcast->query = NULL;
- spin_unlock_irq(&priv->lock);
- ipoib_dbg_mcast(priv, "waiting for bcast\n");
- wait_for_completion(&priv->broadcast->done);
- } else
- spin_unlock_irq(&priv->lock);
+ wait_for_mcast_join(priv, priv->broadcast);
- list_for_each_entry(mcast, &priv->multicast_list, list) {
- spin_lock_irq(&priv->lock);
- if (mcast->query) {
- ib_sa_cancel_query(mcast->query_id, mcast->query);
- mcast->query = NULL;
- spin_unlock_irq(&priv->lock);
- ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n",
- IPOIB_GID_ARG(mcast->mcmember.mgid));
- wait_for_completion(&mcast->done);
- } else
- spin_unlock_irq(&priv->lock);
- }
+ list_for_each_entry(mcast, &priv->multicast_list, list)
+ wait_for_mcast_join(priv, mcast);
return 0;
}
@@ -772,13 +761,11 @@ out:
if (skb->dst &&
skb->dst->neighbour &&
!*to_ipoib_neigh(skb->dst->neighbour)) {
- struct ipoib_neigh *neigh = kmalloc(sizeof *neigh, GFP_ATOMIC);
+ struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour);
if (neigh) {
kref_get(&mcast->ah->ref);
neigh->ah = mcast->ah;
- neigh->neighbour = skb->dst->neighbour;
- *to_ipoib_neigh(skb->dst->neighbour) = neigh;
list_add_tail(&neigh->list, &mcast->neigh_list);
}
}
@@ -913,6 +900,7 @@ void ipoib_mcast_restart_task(void *dev_ptr)
/* We have to cancel outside of the spinlock */
list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
+ wait_for_mcast_join(priv, mcast);
ipoib_mcast_leave(mcast->dev, mcast);
ipoib_mcast_free(mcast);
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 5f0388027b2..1d49d1643c5 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -159,8 +159,8 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ib_qp_init_attr init_attr = {
.cap = {
- .max_send_wr = IPOIB_TX_RING_SIZE,
- .max_recv_wr = IPOIB_RX_RING_SIZE,
+ .max_send_wr = ipoib_sendq_size,
+ .max_recv_wr = ipoib_recvq_size,
.max_send_sge = 1,
.max_recv_sge = 1
},
@@ -175,7 +175,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
}
priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev,
- IPOIB_TX_RING_SIZE + IPOIB_RX_RING_SIZE + 1);
+ ipoib_sendq_size + ipoib_recvq_size + 1);
if (IS_ERR(priv->cq)) {
printk(KERN_WARNING "%s: failed to create CQ\n", ca->name);
goto out_free_pd;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index 4ca175553f9..f887780e809 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -158,10 +158,8 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
if (priv->pkey == pkey) {
unregister_netdev(priv->dev);
ipoib_dev_cleanup(priv->dev);
-
list_del(&priv->list);
-
- kfree(priv);
+ free_netdev(priv->dev);
ret = 0;
break;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 61924cc30e5..9cbdffa08dc 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -340,7 +340,10 @@ static void srp_disconnect_target(struct srp_target_port *target)
/* XXX should send SRP_I_LOGOUT request */
init_completion(&target->done);
- ib_send_cm_dreq(target->cm_id, NULL, 0);
+ if (ib_send_cm_dreq(target->cm_id, NULL, 0)) {
+ printk(KERN_DEBUG PFX "Sending CM DREQ failed\n");
+ return;
+ }
wait_for_completion(&target->done);
}
@@ -351,7 +354,6 @@ static void srp_remove_work(void *target_ptr)
spin_lock_irq(target->scsi_host->host_lock);
if (target->state != SRP_TARGET_DEAD) {
spin_unlock_irq(target->scsi_host->host_lock);
- scsi_host_put(target->scsi_host);
return;
}
target->state = SRP_TARGET_REMOVED;
@@ -365,8 +367,6 @@ static void srp_remove_work(void *target_ptr)
ib_destroy_cm_id(target->cm_id);
srp_free_target_ib(target);
scsi_host_put(target->scsi_host);
- /* And another put to really free the target port... */
- scsi_host_put(target->scsi_host);
}
static int srp_connect_target(struct srp_target_port *target)
@@ -409,6 +409,34 @@ static int srp_connect_target(struct srp_target_port *target)
}
}
+static void srp_unmap_data(struct scsi_cmnd *scmnd,
+ struct srp_target_port *target,
+ struct srp_request *req)
+{
+ struct scatterlist *scat;
+ int nents;
+
+ if (!scmnd->request_buffer ||
+ (scmnd->sc_data_direction != DMA_TO_DEVICE &&
+ scmnd->sc_data_direction != DMA_FROM_DEVICE))
+ return;
+
+ /*
+ * This handling of non-SG commands can be killed when the
+ * SCSI midlayer no longer generates non-SG commands.
+ */
+ if (likely(scmnd->use_sg)) {
+ nents = scmnd->use_sg;
+ scat = scmnd->request_buffer;
+ } else {
+ nents = 1;
+ scat = &req->fake_sg;
+ }
+
+ dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents,
+ scmnd->sc_data_direction);
+}
+
static int srp_reconnect_target(struct srp_target_port *target)
{
struct ib_cm_id *new_cm_id;
@@ -455,16 +483,16 @@ static int srp_reconnect_target(struct srp_target_port *target)
list_for_each_entry(req, &target->req_queue, list) {
req->scmnd->result = DID_RESET << 16;
req->scmnd->scsi_done(req->scmnd);
+ srp_unmap_data(req->scmnd, target, req);
}
target->rx_head = 0;
target->tx_head = 0;
target->tx_tail = 0;
- target->req_head = 0;
- for (i = 0; i < SRP_SQ_SIZE - 1; ++i)
- target->req_ring[i].next = i + 1;
- target->req_ring[SRP_SQ_SIZE - 1].next = -1;
+ INIT_LIST_HEAD(&target->free_reqs);
INIT_LIST_HEAD(&target->req_queue);
+ for (i = 0; i < SRP_SQ_SIZE; ++i)
+ list_add_tail(&target->req_ring[i].list, &target->free_reqs);
ret = srp_connect_target(target);
if (ret)
@@ -589,32 +617,10 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
return len;
}
-static void srp_unmap_data(struct scsi_cmnd *scmnd,
- struct srp_target_port *target,
- struct srp_request *req)
+static void srp_remove_req(struct srp_target_port *target, struct srp_request *req)
{
- struct scatterlist *scat;
- int nents;
-
- if (!scmnd->request_buffer ||
- (scmnd->sc_data_direction != DMA_TO_DEVICE &&
- scmnd->sc_data_direction != DMA_FROM_DEVICE))
- return;
-
- /*
- * This handling of non-SG commands can be killed when the
- * SCSI midlayer no longer generates non-SG commands.
- */
- if (likely(scmnd->use_sg)) {
- nents = scmnd->use_sg;
- scat = (struct scatterlist *) scmnd->request_buffer;
- } else {
- nents = 1;
- scat = (struct scatterlist *) scmnd->request_buffer;
- }
-
- dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents,
- scmnd->sc_data_direction);
+ srp_unmap_data(req->scmnd, target, req);
+ list_move_tail(&req->list, &target->free_reqs);
}
static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
@@ -639,7 +645,7 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
req->tsk_status = rsp->data[3];
complete(&req->done);
} else {
- scmnd = req->scmnd;
+ scmnd = req->scmnd;
if (!scmnd)
printk(KERN_ERR "Null scmnd for RSP w/tag %016llx\n",
(unsigned long long) rsp->tag);
@@ -657,16 +663,11 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))
scmnd->resid = be32_to_cpu(rsp->data_in_res_cnt);
- srp_unmap_data(scmnd, target, req);
-
if (!req->tsk_mgmt) {
- req->scmnd = NULL;
scmnd->host_scribble = (void *) -1L;
scmnd->scsi_done(scmnd);
- list_del(&req->list);
- req->next = target->req_head;
- target->req_head = rsp->tag & ~SRP_TAG_TSK_MGMT;
+ srp_remove_req(target, req);
} else
req->cmd_done = 1;
}
@@ -853,7 +854,6 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
struct srp_request *req;
struct srp_iu *iu;
struct srp_cmd *cmd;
- long req_index;
int len;
if (target->state == SRP_TARGET_CONNECTING)
@@ -873,22 +873,20 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma,
SRP_MAX_IU_LEN, DMA_TO_DEVICE);
- req_index = target->req_head;
+ req = list_entry(target->free_reqs.next, struct srp_request, list);
scmnd->scsi_done = done;
scmnd->result = 0;
- scmnd->host_scribble = (void *) req_index;
+ scmnd->host_scribble = (void *) (long) req->index;
cmd = iu->buf;
memset(cmd, 0, sizeof *cmd);
cmd->opcode = SRP_CMD;
cmd->lun = cpu_to_be64((u64) scmnd->device->lun << 48);
- cmd->tag = req_index;
+ cmd->tag = req->index;
memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
- req = &target->req_ring[req_index];
-
req->scmnd = scmnd;
req->cmd = iu;
req->cmd_done = 0;
@@ -913,8 +911,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
goto err_unmap;
}
- target->req_head = req->next;
- list_add_tail(&req->list, &target->req_queue);
+ list_move_tail(&req->list, &target->req_queue);
return 0;
@@ -1137,30 +1134,20 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
return 0;
}
-static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func)
+static int srp_send_tsk_mgmt(struct srp_target_port *target,
+ struct srp_request *req, u8 func)
{
- struct srp_target_port *target = host_to_target(scmnd->device->host);
- struct srp_request *req;
struct srp_iu *iu;
struct srp_tsk_mgmt *tsk_mgmt;
- int req_index;
- int ret = FAILED;
spin_lock_irq(target->scsi_host->host_lock);
if (target->state == SRP_TARGET_DEAD ||
target->state == SRP_TARGET_REMOVED) {
- scmnd->result = DID_BAD_TARGET << 16;
+ req->scmnd->result = DID_BAD_TARGET << 16;
goto out;
}
- if (scmnd->host_scribble == (void *) -1L)
- goto out;
-
- req_index = (long) scmnd->host_scribble;
- printk(KERN_ERR "Abort for req_index %d\n", req_index);
-
- req = &target->req_ring[req_index];
init_completion(&req->done);
iu = __srp_get_tx_iu(target);
@@ -1171,10 +1158,10 @@ static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func)
memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
tsk_mgmt->opcode = SRP_TSK_MGMT;
- tsk_mgmt->lun = cpu_to_be64((u64) scmnd->device->lun << 48);
- tsk_mgmt->tag = req_index | SRP_TAG_TSK_MGMT;
+ tsk_mgmt->lun = cpu_to_be64((u64) req->scmnd->device->lun << 48);
+ tsk_mgmt->tag = req->index | SRP_TAG_TSK_MGMT;
tsk_mgmt->tsk_mgmt_func = func;
- tsk_mgmt->task_tag = req_index;
+ tsk_mgmt->task_tag = req->index;
if (__srp_post_send(target, iu, sizeof *tsk_mgmt))
goto out;
@@ -1182,39 +1169,85 @@ static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func)
req->tsk_mgmt = iu;
spin_unlock_irq(target->scsi_host->host_lock);
+
if (!wait_for_completion_timeout(&req->done,
msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)))
- return FAILED;
- spin_lock_irq(target->scsi_host->host_lock);
+ return -1;
- if (req->cmd_done) {
- list_del(&req->list);
- req->next = target->req_head;
- target->req_head = req_index;
-
- scmnd->scsi_done(scmnd);
- } else if (!req->tsk_status) {
- scmnd->result = DID_ABORT << 16;
- ret = SUCCESS;
- }
+ return 0;
out:
spin_unlock_irq(target->scsi_host->host_lock);
- return ret;
+ return -1;
+}
+
+static int srp_find_req(struct srp_target_port *target,
+ struct scsi_cmnd *scmnd,
+ struct srp_request **req)
+{
+ if (scmnd->host_scribble == (void *) -1L)
+ return -1;
+
+ *req = &target->req_ring[(long) scmnd->host_scribble];
+
+ return 0;
}
static int srp_abort(struct scsi_cmnd *scmnd)
{
+ struct srp_target_port *target = host_to_target(scmnd->device->host);
+ struct srp_request *req;
+ int ret = SUCCESS;
+
printk(KERN_ERR "SRP abort called\n");
- return srp_send_tsk_mgmt(scmnd, SRP_TSK_ABORT_TASK);
+ if (srp_find_req(target, scmnd, &req))
+ return FAILED;
+ if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK))
+ return FAILED;
+
+ spin_lock_irq(target->scsi_host->host_lock);
+
+ if (req->cmd_done) {
+ srp_remove_req(target, req);
+ scmnd->scsi_done(scmnd);
+ } else if (!req->tsk_status) {
+ srp_remove_req(target, req);
+ scmnd->result = DID_ABORT << 16;
+ } else
+ ret = FAILED;
+
+ spin_unlock_irq(target->scsi_host->host_lock);
+
+ return ret;
}
static int srp_reset_device(struct scsi_cmnd *scmnd)
{
+ struct srp_target_port *target = host_to_target(scmnd->device->host);
+ struct srp_request *req, *tmp;
+
printk(KERN_ERR "SRP reset_device called\n");
- return srp_send_tsk_mgmt(scmnd, SRP_TSK_LUN_RESET);
+ if (srp_find_req(target, scmnd, &req))
+ return FAILED;
+ if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET))
+ return FAILED;
+ if (req->tsk_status)
+ return FAILED;
+
+ spin_lock_irq(target->scsi_host->host_lock);
+
+ list_for_each_entry_safe(req, tmp, &target->req_queue, list)
+ if (req->scmnd->device == scmnd->device) {
+ req->scmnd->result = DID_RESET << 16;
+ req->scmnd->scsi_done(req->scmnd);
+ srp_remove_req(target, req);
+ }
+
+ spin_unlock_irq(target->scsi_host->host_lock);
+
+ return SUCCESS;
}
static int srp_reset_host(struct scsi_cmnd *scmnd)
@@ -1434,6 +1467,7 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
p = match_strdup(args);
if (strlen(p) != 32) {
printk(KERN_WARNING PFX "bad dest GID parameter '%s'\n", p);
+ kfree(p);
goto out;
}
@@ -1513,10 +1547,12 @@ static ssize_t srp_create_target(struct class_device *class_dev,
INIT_WORK(&target->work, srp_reconnect_work, target);
- for (i = 0; i < SRP_SQ_SIZE - 1; ++i)
- target->req_ring[i].next = i + 1;
- target->req_ring[SRP_SQ_SIZE - 1].next = -1;
+ INIT_LIST_HEAD(&target->free_reqs);
INIT_LIST_HEAD(&target->req_queue);
+ for (i = 0; i < SRP_SQ_SIZE; ++i) {
+ target->req_ring[i].index = i;
+ list_add_tail(&target->req_ring[i].list, &target->free_reqs);
+ }
ret = srp_parse_options(buf, target);
if (ret)
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index bd7f7c3115d..c5cd43aae86 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -101,7 +101,7 @@ struct srp_request {
*/
struct scatterlist fake_sg;
struct completion done;
- short next;
+ short index;
u8 cmd_done;
u8 tsk_status;
};
@@ -133,7 +133,7 @@ struct srp_target_port {
unsigned tx_tail;
struct srp_iu *tx_ring[SRP_SQ_SIZE + 1];
- int req_head;
+ struct list_head free_reqs;
struct list_head req_queue;
struct srp_request req_ring[SRP_SQ_SIZE];
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c
index d7828936fd8..07358fb51b8 100644
--- a/drivers/input/evbug.c
+++ b/drivers/input/evbug.c
@@ -49,9 +49,8 @@ static struct input_handle *evbug_connect(struct input_handler *handler, struct
{
struct input_handle *handle;
- if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+ if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
return NULL;
- memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->handler = handler;
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 745979f33dc..ba325f16d07 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -130,9 +130,8 @@ static int evdev_open(struct inode * inode, struct file * file)
if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
return accept_err;
- if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
+ if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
return -ENOMEM;
- memset(list, 0, sizeof(struct evdev_list));
list->evdev = evdev_table[i];
list_add_tail(&list->node, &evdev_table[i]->list);
@@ -404,6 +403,27 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
case EVIOCGID:
if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
return -EFAULT;
+ return 0;
+
+ case EVIOCGREP:
+ if (!test_bit(EV_REP, dev->evbit))
+ return -ENOSYS;
+ if (put_user(dev->rep[REP_DELAY], ip))
+ return -EFAULT;
+ if (put_user(dev->rep[REP_PERIOD], ip + 1))
+ return -EFAULT;
+ return 0;
+
+ case EVIOCSREP:
+ if (!test_bit(EV_REP, dev->evbit))
+ return -ENOSYS;
+ if (get_user(u, ip))
+ return -EFAULT;
+ if (get_user(v, ip + 1))
+ return -EFAULT;
+
+ input_event(dev, EV_REP, REP_DELAY, u);
+ input_event(dev, EV_REP, REP_PERIOD, v);
return 0;
@@ -609,9 +629,8 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
return NULL;
}
- if (!(evdev = kmalloc(sizeof(struct evdev), GFP_KERNEL)))
+ if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL)))
return NULL;
- memset(evdev, 0, sizeof(struct evdev));
INIT_LIST_HEAD(&evdev->list);
init_waitqueue_head(&evdev->wait);
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index b765a155c00..36644bff379 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/sched.h> /* HZ */
+#include <linux/mutex.h>
/*#include <asm/io.h>*/
@@ -43,10 +44,10 @@ EXPORT_SYMBOL(gameport_start_polling);
EXPORT_SYMBOL(gameport_stop_polling);
/*
- * gameport_sem protects entire gameport subsystem and is taken
+ * gameport_mutex protects entire gameport subsystem and is taken
* every time gameport port or driver registrered or unregistered.
*/
-static DECLARE_MUTEX(gameport_sem);
+static DEFINE_MUTEX(gameport_mutex);
static LIST_HEAD(gameport_list);
@@ -265,6 +266,7 @@ static void gameport_queue_event(void *object, struct module *owner,
if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) {
if (!try_module_get(owner)) {
printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type);
+ kfree(event);
goto out;
}
@@ -342,7 +344,7 @@ static void gameport_handle_event(void)
struct gameport_event *event;
struct gameport_driver *gameport_drv;
- down(&gameport_sem);
+ mutex_lock(&gameport_mutex);
/*
* Note that we handle only one event here to give swsusp
@@ -379,7 +381,7 @@ static void gameport_handle_event(void)
gameport_free_event(event);
}
- up(&gameport_sem);
+ mutex_unlock(&gameport_mutex);
}
/*
@@ -464,7 +466,7 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut
struct device_driver *drv;
int retval;
- retval = down_interruptible(&gameport_sem);
+ retval = mutex_lock_interruptible(&gameport_mutex);
if (retval)
return retval;
@@ -484,7 +486,7 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut
retval = -EINVAL;
}
- up(&gameport_sem);
+ mutex_unlock(&gameport_mutex);
return retval;
}
@@ -521,7 +523,7 @@ static void gameport_init_port(struct gameport *gameport)
__module_get(THIS_MODULE);
- init_MUTEX(&gameport->drv_sem);
+ mutex_init(&gameport->drv_mutex);
device_initialize(&gameport->dev);
snprintf(gameport->dev.bus_id, sizeof(gameport->dev.bus_id),
"gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
@@ -661,10 +663,10 @@ void __gameport_register_port(struct gameport *gameport, struct module *owner)
*/
void gameport_unregister_port(struct gameport *gameport)
{
- down(&gameport_sem);
+ mutex_lock(&gameport_mutex);
gameport_disconnect_port(gameport);
gameport_destroy_port(gameport);
- up(&gameport_sem);
+ mutex_unlock(&gameport_mutex);
}
@@ -717,7 +719,7 @@ void gameport_unregister_driver(struct gameport_driver *drv)
{
struct gameport *gameport;
- down(&gameport_sem);
+ mutex_lock(&gameport_mutex);
drv->ignore = 1; /* so gameport_find_driver ignores it */
start_over:
@@ -731,7 +733,7 @@ start_over:
}
driver_unregister(&drv->driver);
- up(&gameport_sem);
+ mutex_unlock(&gameport_mutex);
}
static int gameport_bus_match(struct device *dev, struct device_driver *drv)
@@ -743,9 +745,9 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv)
static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv)
{
- down(&gameport->drv_sem);
+ mutex_lock(&gameport->drv_mutex);
gameport->drv = drv;
- up(&gameport->drv_sem);
+ mutex_unlock(&gameport->drv_mutex);
}
int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
@@ -796,5 +798,5 @@ static void __exit gameport_exit(void)
kthread_stop(gameport_task);
}
-module_init(gameport_init);
+subsys_initcall(gameport_init);
module_exit(gameport_exit);
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
index d2e55dc956b..3e2d28f263e 100644
--- a/drivers/input/gameport/ns558.c
+++ b/drivers/input/gameport/ns558.c
@@ -252,14 +252,14 @@ static struct pnp_driver ns558_pnp_driver;
#endif
-static int pnp_registered = 0;
-
static int __init ns558_init(void)
{
int i = 0;
+ int error;
- if (pnp_register_driver(&ns558_pnp_driver) >= 0)
- pnp_registered = 1;
+ error = pnp_register_driver(&ns558_pnp_driver);
+ if (error && error != -ENODEV) /* should be ENOSYS really */
+ return error;
/*
* Probe ISA ports after PnP, so that PnP ports that are already
@@ -270,7 +270,7 @@ static int __init ns558_init(void)
while (ns558_isa_portlist[i])
ns558_isa_probe(ns558_isa_portlist[i++]);
- return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0;
+ return list_empty(&ns558_list) && error ? -ENODEV : 0;
}
static void __exit ns558_exit(void)
@@ -283,8 +283,7 @@ static void __exit ns558_exit(void)
kfree(ns558);
}
- if (pnp_registered)
- pnp_unregister_driver(&ns558_pnp_driver);
+ pnp_unregister_driver(&ns558_pnp_driver);
}
module_init(ns558_init);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 4fe3da3c667..3038c268917 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -18,9 +18,11 @@
#include <linux/random.h>
#include <linux/major.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/device.h>
+#include <linux/mutex.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input core");
@@ -153,6 +155,9 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
if (code > SND_MAX || !test_bit(code, dev->sndbit))
return;
+ if (!!test_bit(code, dev->snd) != !!value)
+ change_bit(code, dev->snd);
+
if (dev->event) dev->event(dev, type, code, value);
break;
@@ -224,7 +229,7 @@ int input_open_device(struct input_handle *handle)
struct input_dev *dev = handle->dev;
int err;
- err = down_interruptible(&dev->sem);
+ err = mutex_lock_interruptible(&dev->mutex);
if (err)
return err;
@@ -236,7 +241,7 @@ int input_open_device(struct input_handle *handle)
if (err)
handle->open--;
- up(&dev->sem);
+ mutex_unlock(&dev->mutex);
return err;
}
@@ -255,13 +260,13 @@ void input_close_device(struct input_handle *handle)
input_release_device(handle);
- down(&dev->sem);
+ mutex_lock(&dev->mutex);
if (!--dev->users && dev->close)
dev->close(dev);
handle->open--;
- up(&dev->sem);
+ mutex_unlock(&dev->mutex);
}
static void input_link_handle(struct input_handle *handle)
@@ -284,19 +289,19 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st
for (; id->flags || id->driver_info; id++) {
if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
- if (id->id.bustype != dev->id.bustype)
+ if (id->bustype != dev->id.bustype)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
- if (id->id.vendor != dev->id.vendor)
+ if (id->vendor != dev->id.vendor)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
- if (id->id.product != dev->id.product)
+ if (id->product != dev->id.product)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
- if (id->id.version != dev->id.version)
+ if (id->version != dev->id.version)
continue;
MATCH_BIT(evbit, EV_MAX);
@@ -315,21 +320,6 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st
return NULL;
}
-static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, int max)
-{
- int i;
- int len = 0;
-
- for (i = NBITS(max) - 1; i > 0; i--)
- if (bitmap[i])
- break;
-
- for (; i >= 0; i--)
- len += snprintf(buf + len, max(buf_size - len, 0),
- "%lx%s", bitmap[i], i > 0 ? " " : "");
- return len;
-}
-
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_bus_input_dir;
@@ -342,7 +332,7 @@ static inline void input_wakeup_procfs_readers(void)
wake_up(&input_devices_poll_wait);
}
-static unsigned int input_devices_poll(struct file *file, poll_table *wait)
+static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait)
{
int state = input_devices_state;
poll_wait(file, &input_devices_poll_wait, wait);
@@ -351,115 +341,171 @@ static unsigned int input_devices_poll(struct file *file, poll_table *wait)
return 0;
}
-#define SPRINTF_BIT(ev, bm) \
- do { \
- len += sprintf(buf + len, "B: %s=", #ev); \
- len += input_print_bitmap(buf + len, INT_MAX, \
- dev->bm##bit, ev##_MAX); \
- len += sprintf(buf + len, "\n"); \
- } while (0)
+static struct list_head *list_get_nth_element(struct list_head *list, loff_t *pos)
+{
+ struct list_head *node;
+ loff_t i = 0;
-#define TEST_AND_SPRINTF_BIT(ev, bm) \
- do { \
- if (test_bit(EV_##ev, dev->evbit)) \
- SPRINTF_BIT(ev, bm); \
- } while (0)
+ list_for_each(node, list)
+ if (i++ == *pos)
+ return node;
-static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+ return NULL;
+}
+
+static struct list_head *list_get_next_element(struct list_head *list, struct list_head *element, loff_t *pos)
{
- struct input_dev *dev;
- struct input_handle *handle;
- const char *path;
+ if (element->next == list)
+ return NULL;
+
+ ++(*pos);
+ return element->next;
+}
+
+static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ /* acquire lock here ... Yes, we do need locking, I knowi, I know... */
+
+ return list_get_nth_element(&input_dev_list, pos);
+}
- off_t at = 0;
- int len, cnt = 0;
+static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ return list_get_next_element(&input_dev_list, v, pos);
+}
- list_for_each_entry(dev, &input_dev_list, node) {
+static void input_devices_seq_stop(struct seq_file *seq, void *v)
+{
+ /* release lock here */
+}
- path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
+ unsigned long *bitmap, int max)
+{
+ int i;
- len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
- dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
+ for (i = NBITS(max) - 1; i > 0; i--)
+ if (bitmap[i])
+ break;
- len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
- len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
- len += sprintf(buf + len, "S: Sysfs=%s\n", path ? path : "");
- len += sprintf(buf + len, "H: Handlers=");
+ seq_printf(seq, "B: %s=", name);
+ for (; i >= 0; i--)
+ seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : "");
+ seq_putc(seq, '\n');
+}
- list_for_each_entry(handle, &dev->h_list, d_node)
- len += sprintf(buf + len, "%s ", handle->name);
-
- len += sprintf(buf + len, "\n");
-
- SPRINTF_BIT(EV, ev);
- TEST_AND_SPRINTF_BIT(KEY, key);
- TEST_AND_SPRINTF_BIT(REL, rel);
- TEST_AND_SPRINTF_BIT(ABS, abs);
- TEST_AND_SPRINTF_BIT(MSC, msc);
- TEST_AND_SPRINTF_BIT(LED, led);
- TEST_AND_SPRINTF_BIT(SND, snd);
- TEST_AND_SPRINTF_BIT(FF, ff);
- TEST_AND_SPRINTF_BIT(SW, sw);
-
- len += sprintf(buf + len, "\n");
-
- at += len;
-
- if (at >= pos) {
- if (!*start) {
- *start = buf + (pos - (at - len));
- cnt = at - pos;
- } else cnt += len;
- buf += len;
- if (cnt >= count)
- break;
- }
+static int input_devices_seq_show(struct seq_file *seq, void *v)
+{
+ struct input_dev *dev = container_of(v, struct input_dev, node);
+ const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+ struct input_handle *handle;
- kfree(path);
- }
+ seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
+ dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
+
+ seq_printf(seq, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
+ seq_printf(seq, "P: Phys=%s\n", dev->phys ? dev->phys : "");
+ seq_printf(seq, "S: Sysfs=%s\n", path ? path : "");
+ seq_printf(seq, "H: Handlers=");
+
+ list_for_each_entry(handle, &dev->h_list, d_node)
+ seq_printf(seq, "%s ", handle->name);
+ seq_putc(seq, '\n');
+
+ input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX);
+ if (test_bit(EV_KEY, dev->evbit))
+ input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX);
+ if (test_bit(EV_REL, dev->evbit))
+ input_seq_print_bitmap(seq, "REL", dev->relbit, REL_MAX);
+ if (test_bit(EV_ABS, dev->evbit))
+ input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX);
+ if (test_bit(EV_MSC, dev->evbit))
+ input_seq_print_bitmap(seq, "MSC", dev->mscbit, MSC_MAX);
+ if (test_bit(EV_LED, dev->evbit))
+ input_seq_print_bitmap(seq, "LED", dev->ledbit, LED_MAX);
+ if (test_bit(EV_SND, dev->evbit))
+ input_seq_print_bitmap(seq, "SND", dev->sndbit, SND_MAX);
+ if (test_bit(EV_FF, dev->evbit))
+ input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX);
+ if (test_bit(EV_SW, dev->evbit))
+ input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX);
+
+ seq_putc(seq, '\n');
+
+ kfree(path);
+ return 0;
+}
- if (&dev->node == &input_dev_list)
- *eof = 1;
+static struct seq_operations input_devices_seq_ops = {
+ .start = input_devices_seq_start,
+ .next = input_devices_seq_next,
+ .stop = input_devices_seq_stop,
+ .show = input_devices_seq_show,
+};
- return (count > cnt) ? cnt : count;
+static int input_proc_devices_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &input_devices_seq_ops);
}
-static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+static struct file_operations input_devices_fileops = {
+ .owner = THIS_MODULE,
+ .open = input_proc_devices_open,
+ .poll = input_proc_devices_poll,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
{
- struct input_handler *handler;
+ /* acquire lock here ... Yes, we do need locking, I knowi, I know... */
+ seq->private = (void *)(unsigned long)*pos;
+ return list_get_nth_element(&input_handler_list, pos);
+}
- off_t at = 0;
- int len = 0, cnt = 0;
- int i = 0;
+static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ seq->private = (void *)(unsigned long)(*pos + 1);
+ return list_get_next_element(&input_handler_list, v, pos);
+}
- list_for_each_entry(handler, &input_handler_list, node) {
+static void input_handlers_seq_stop(struct seq_file *seq, void *v)
+{
+ /* release lock here */
+}
- if (handler->fops)
- len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n",
- i++, handler->name, handler->minor);
- else
- len = sprintf(buf, "N: Number=%d Name=%s\n",
- i++, handler->name);
+static int input_handlers_seq_show(struct seq_file *seq, void *v)
+{
+ struct input_handler *handler = container_of(v, struct input_handler, node);
- at += len;
+ seq_printf(seq, "N: Number=%ld Name=%s",
+ (unsigned long)seq->private, handler->name);
+ if (handler->fops)
+ seq_printf(seq, " Minor=%d", handler->minor);
+ seq_putc(seq, '\n');
- if (at >= pos) {
- if (!*start) {
- *start = buf + (pos - (at - len));
- cnt = at - pos;
- } else cnt += len;
- buf += len;
- if (cnt >= count)
- break;
- }
- }
- if (&handler->node == &input_handler_list)
- *eof = 1;
+ return 0;
+}
+static struct seq_operations input_handlers_seq_ops = {
+ .start = input_handlers_seq_start,
+ .next = input_handlers_seq_next,
+ .stop = input_handlers_seq_stop,
+ .show = input_handlers_seq_show,
+};
- return (count > cnt) ? cnt : count;
+static int input_proc_handlers_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &input_handlers_seq_ops);
}
-static struct file_operations input_fileops;
+static struct file_operations input_handlers_fileops = {
+ .owner = THIS_MODULE,
+ .open = input_proc_handlers_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
static int __init input_proc_init(void)
{
@@ -471,20 +517,19 @@ static int __init input_proc_init(void)
proc_bus_input_dir->owner = THIS_MODULE;
- entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL);
+ entry = create_proc_entry("devices", 0, proc_bus_input_dir);
if (!entry)
goto fail1;
entry->owner = THIS_MODULE;
- input_fileops = *entry->proc_fops;
- input_fileops.poll = input_devices_poll;
- entry->proc_fops = &input_fileops;
+ entry->proc_fops = &input_devices_fileops;
- entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
+ entry = create_proc_entry("handlers", 0, proc_bus_input_dir);
if (!entry)
goto fail2;
entry->owner = THIS_MODULE;
+ entry->proc_fops = &input_handlers_fileops;
return 0;
@@ -512,13 +557,14 @@ static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \
struct input_dev *input_dev = to_input_dev(dev); \
int retval; \
\
- retval = down_interruptible(&input_dev->sem); \
+ retval = mutex_lock_interruptible(&input_dev->mutex); \
if (retval) \
return retval; \
\
- retval = sprintf(buf, "%s\n", input_dev->name ? input_dev->name : ""); \
+ retval = scnprintf(buf, PAGE_SIZE, \
+ "%s\n", input_dev->name ? input_dev->name : ""); \
\
- up(&input_dev->sem); \
+ mutex_unlock(&input_dev->mutex); \
\
return retval; \
} \
@@ -528,46 +574,51 @@ INPUT_DEV_STRING_ATTR_SHOW(name);
INPUT_DEV_STRING_ATTR_SHOW(phys);
INPUT_DEV_STRING_ATTR_SHOW(uniq);
-static int print_modalias_bits(char *buf, int size, char prefix, unsigned long *arr,
- unsigned int min, unsigned int max)
+static int input_print_modalias_bits(char *buf, int size,
+ char name, unsigned long *bm,
+ unsigned int min_bit, unsigned int max_bit)
{
- int len, i;
+ int len = 0, i;
- len = snprintf(buf, size, "%c", prefix);
- for (i = min; i < max; i++)
- if (arr[LONG(i)] & BIT(i))
- len += snprintf(buf + len, size - len, "%X,", i);
+ len += snprintf(buf, max(size, 0), "%c", name);
+ for (i = min_bit; i < max_bit; i++)
+ if (bm[LONG(i)] & BIT(i))
+ len += snprintf(buf + len, max(size - len, 0), "%X,", i);
return len;
}
-static int print_modalias(char *buf, int size, struct input_dev *id)
+static int input_print_modalias(char *buf, int size, struct input_dev *id,
+ int add_cr)
{
int len;
- len = snprintf(buf, size, "input:b%04Xv%04Xp%04Xe%04X-",
- id->id.bustype,
- id->id.vendor,
- id->id.product,
- id->id.version);
-
- len += print_modalias_bits(buf + len, size - len, 'e', id->evbit,
- 0, EV_MAX);
- len += print_modalias_bits(buf + len, size - len, 'k', id->keybit,
- KEY_MIN_INTERESTING, KEY_MAX);
- len += print_modalias_bits(buf + len, size - len, 'r', id->relbit,
- 0, REL_MAX);
- len += print_modalias_bits(buf + len, size - len, 'a', id->absbit,
- 0, ABS_MAX);
- len += print_modalias_bits(buf + len, size - len, 'm', id->mscbit,
- 0, MSC_MAX);
- len += print_modalias_bits(buf + len, size - len, 'l', id->ledbit,
- 0, LED_MAX);
- len += print_modalias_bits(buf + len, size - len, 's', id->sndbit,
- 0, SND_MAX);
- len += print_modalias_bits(buf + len, size - len, 'f', id->ffbit,
- 0, FF_MAX);
- len += print_modalias_bits(buf + len, size - len, 'w', id->swbit,
- 0, SW_MAX);
+ len = snprintf(buf, max(size, 0),
+ "input:b%04Xv%04Xp%04Xe%04X-",
+ id->id.bustype, id->id.vendor,
+ id->id.product, id->id.version);
+
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'e', id->evbit, 0, EV_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'r', id->relbit, 0, REL_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'a', id->absbit, 0, ABS_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'm', id->mscbit, 0, MSC_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'l', id->ledbit, 0, LED_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 's', id->sndbit, 0, SND_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'f', id->ffbit, 0, FF_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'w', id->swbit, 0, SW_MAX);
+
+ if (add_cr)
+ len += snprintf(buf + len, max(size - len, 0), "\n");
+
return len;
}
@@ -576,9 +627,9 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
struct input_dev *id = to_input_dev(dev);
ssize_t len;
- len = print_modalias(buf, PAGE_SIZE, id);
- len += snprintf(buf + len, PAGE_SIZE-len, "\n");
- return len;
+ len = input_print_modalias(buf, PAGE_SIZE, id, 1);
+
+ return max_t(int, len, PAGE_SIZE);
}
static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
@@ -598,7 +649,7 @@ static struct attribute_group input_dev_attr_group = {
static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \
{ \
struct input_dev *input_dev = to_input_dev(dev); \
- return sprintf(buf, "%04x\n", input_dev->id.name); \
+ return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \
} \
static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
@@ -620,11 +671,33 @@ static struct attribute_group input_dev_id_attr_group = {
.attrs = input_dev_id_attrs,
};
+static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
+ int max, int add_cr)
+{
+ int i;
+ int len = 0;
+
+ for (i = NBITS(max) - 1; i > 0; i--)
+ if (bitmap[i])
+ break;
+
+ for (; i >= 0; i--)
+ len += snprintf(buf + len, max(buf_size - len, 0),
+ "%lx%s", bitmap[i], i > 0 ? " " : "");
+
+ if (add_cr)
+ len += snprintf(buf + len, max(buf_size - len, 0), "\n");
+
+ return len;
+}
+
#define INPUT_DEV_CAP_ATTR(ev, bm) \
static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \
{ \
struct input_dev *input_dev = to_input_dev(dev); \
- return input_print_bitmap(buf, PAGE_SIZE, input_dev->bm##bit, ev##_MAX);\
+ int len = input_print_bitmap(buf, PAGE_SIZE, \
+ input_dev->bm##bit, ev##_MAX, 1); \
+ return min_t(int, len, PAGE_SIZE); \
} \
static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
@@ -669,8 +742,8 @@ static void input_dev_release(struct class_device *class_dev)
* device bitfields.
*/
static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
- char *buffer, int buffer_size, int *cur_len,
- const char *name, unsigned long *bitmap, int max)
+ char *buffer, int buffer_size, int *cur_len,
+ const char *name, unsigned long *bitmap, int max)
{
if (*cur_index >= num_envp - 1)
return -ENOMEM;
@@ -678,12 +751,36 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
envp[*cur_index] = buffer + *cur_len;
*cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name);
- if (*cur_len > buffer_size)
+ if (*cur_len >= buffer_size)
return -ENOMEM;
*cur_len += input_print_bitmap(buffer + *cur_len,
max(buffer_size - *cur_len, 0),
- bitmap, max) + 1;
+ bitmap, max, 0) + 1;
+ if (*cur_len > buffer_size)
+ return -ENOMEM;
+
+ (*cur_index)++;
+ return 0;
+}
+
+static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index,
+ char *buffer, int buffer_size, int *cur_len,
+ struct input_dev *dev)
+{
+ if (*cur_index >= num_envp - 1)
+ return -ENOMEM;
+
+ envp[*cur_index] = buffer + *cur_len;
+
+ *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0),
+ "MODALIAS=");
+ if (*cur_len >= buffer_size)
+ return -ENOMEM;
+
+ *cur_len += input_print_modalias(buffer + *cur_len,
+ max(buffer_size - *cur_len, 0),
+ dev, 0) + 1;
if (*cur_len > buffer_size)
return -ENOMEM;
@@ -693,7 +790,7 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
do { \
- int err = add_uevent_var(envp, num_envp, &i, \
+ int err = add_uevent_var(envp, num_envp, &i, \
buffer, buffer_size, &len, \
fmt, val); \
if (err) \
@@ -709,6 +806,16 @@ static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
return err; \
} while (0)
+#define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \
+ do { \
+ int err = input_add_uevent_modalias_var(envp, \
+ num_envp, &i, \
+ buffer, buffer_size, &len, \
+ dev); \
+ if (err) \
+ return err; \
+ } while (0)
+
static int input_dev_uevent(struct class_device *cdev, char **envp,
int num_envp, char *buffer, int buffer_size)
{
@@ -744,9 +851,7 @@ static int input_dev_uevent(struct class_device *cdev, char **envp,
if (test_bit(EV_SW, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
- envp[i++] = buffer + len;
- len += snprintf(buffer + len, buffer_size - len, "MODALIAS=");
- len += print_modalias(buffer + len, buffer_size - len, dev) + 1;
+ INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
envp[i] = NULL;
return 0;
@@ -790,7 +895,7 @@ int input_register_device(struct input_dev *dev)
return -EINVAL;
}
- init_MUTEX(&dev->sem);
+ mutex_init(&dev->mutex);
set_bit(EV_SYN, dev->evbit);
/*
@@ -923,7 +1028,7 @@ void input_unregister_handler(struct input_handler *handler)
static int input_open_file(struct inode *inode, struct file *file)
{
struct input_handler *handler = input_table[iminor(inode) >> 5];
- struct file_operations *old_fops, *new_fops = NULL;
+ const struct file_operations *old_fops, *new_fops = NULL;
int err;
/* No load-on-demand here? */
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 20e2972b920..949bdcef8c2 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -171,9 +171,8 @@ static int joydev_open(struct inode *inode, struct file *file)
if (i >= JOYDEV_MINORS || !joydev_table[i])
return -ENODEV;
- if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL)))
+ if (!(list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL)))
return -ENOMEM;
- memset(list, 0, sizeof(struct joydev_list));
list->joydev = joydev_table[i];
list_add_tail(&list->node, &joydev_table[i]->list);
@@ -457,9 +456,8 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
return NULL;
}
- if (!(joydev = kmalloc(sizeof(struct joydev), GFP_KERNEL)))
+ if (!(joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL)))
return NULL;
- memset(joydev, 0, sizeof(struct joydev));
INIT_LIST_HEAD(&joydev->list);
init_waitqueue_head(&joydev->wait);
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index ec55a29fc86..7249d324297 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -36,6 +36,7 @@
#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
+#include <linux/mutex.h>
#include <asm/system.h>
#include <asm/amigahw.h>
@@ -52,7 +53,7 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is
__obsolete_setup("amijoy=");
static int amijoy_used;
-static DECLARE_MUTEX(amijoy_sem);
+static DEFINE_MUTEX(amijoy_mutex);
static struct input_dev *amijoy_dev[2];
static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
@@ -85,7 +86,7 @@ static int amijoy_open(struct input_dev *dev)
{
int err;
- err = down_interruptible(&amijoy_sem);
+ err = mutex_lock_interruptible(&amijoy_mutex);
if (err)
return err;
@@ -97,16 +98,16 @@ static int amijoy_open(struct input_dev *dev)
amijoy_used++;
out:
- up(&amijoy_sem);
+ mutex_unlock(&amijoy_mutex);
return err;
}
static void amijoy_close(struct input_dev *dev)
{
- down(&amijoy_sem);
+ mutex_lock(&amijoy_mutex);
if (!--amijoy_used)
free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
- up(&amijoy_sem);
+ mutex_unlock(&amijoy_mutex);
}
static int __init amijoy_init(void)
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index dcffc34f30c..e61894685cb 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -38,6 +38,7 @@
#include <linux/init.h>
#include <linux/parport.h>
#include <linux/input.h>
+#include <linux/mutex.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
@@ -111,7 +112,7 @@ struct db9 {
struct pardevice *pd;
int mode;
int used;
- struct semaphore sem;
+ struct mutex mutex;
char phys[DB9_MAX_DEVICES][32];
};
@@ -525,7 +526,7 @@ static int db9_open(struct input_dev *dev)
struct parport *port = db9->pd->port;
int err;
- err = down_interruptible(&db9->sem);
+ err = mutex_lock_interruptible(&db9->mutex);
if (err)
return err;
@@ -539,7 +540,7 @@ static int db9_open(struct input_dev *dev)
mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
}
- up(&db9->sem);
+ mutex_unlock(&db9->mutex);
return 0;
}
@@ -548,14 +549,14 @@ static void db9_close(struct input_dev *dev)
struct db9 *db9 = dev->private;
struct parport *port = db9->pd->port;
- down(&db9->sem);
+ mutex_lock(&db9->mutex);
if (!--db9->used) {
del_timer_sync(&db9->timer);
parport_write_control(port, 0x00);
parport_data_forward(port);
parport_release(db9->pd);
}
- up(&db9->sem);
+ mutex_unlock(&db9->mutex);
}
static struct db9 __init *db9_probe(int parport, int mode)
@@ -603,7 +604,7 @@ static struct db9 __init *db9_probe(int parport, int mode)
goto err_unreg_pardev;
}
- init_MUTEX(&db9->sem);
+ mutex_init(&db9->mutex);
db9->pd = pd;
db9->mode = mode;
init_timer(&db9->timer);
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 900587acdb4..ecbdb6b9bbd 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -7,6 +7,7 @@
* Based on the work of:
* Andree Borrmann John Dahlstrom
* David Kuder Nathan Hand
+ * Raphael Assenat
*/
/*
@@ -36,6 +37,7 @@
#include <linux/init.h>
#include <linux/parport.h>
#include <linux/input.h>
+#include <linux/mutex.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
@@ -72,8 +74,9 @@ __obsolete_setup("gc_3=");
#define GC_N64 6
#define GC_PSX 7
#define GC_DDR 8
+#define GC_SNESMOUSE 9
-#define GC_MAX 8
+#define GC_MAX 9
#define GC_REFRESH_TIME HZ/100
@@ -83,7 +86,7 @@ struct gc {
struct timer_list timer;
unsigned char pads[GC_MAX + 1];
int used;
- struct semaphore sem;
+ struct mutex mutex;
char phys[GC_MAX_DEVICES][32];
};
@@ -93,7 +96,7 @@ static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
"Multisystem 2-button joystick", "N64 controller", "PSX controller",
- "PSX DDR controller" };
+ "PSX DDR controller", "SNES mouse" };
/*
* N64 support.
*/
@@ -205,9 +208,12 @@ static void gc_n64_process_packet(struct gc *gc)
* NES/SNES support.
*/
-#define GC_NES_DELAY 6 /* Delay between bits - 6us */
-#define GC_NES_LENGTH 8 /* The NES pads use 8 bits of data */
-#define GC_SNES_LENGTH 12 /* The SNES true length is 16, but the last 4 bits are unused */
+#define GC_NES_DELAY 6 /* Delay between bits - 6us */
+#define GC_NES_LENGTH 8 /* The NES pads use 8 bits of data */
+#define GC_SNES_LENGTH 12 /* The SNES true length is 16, but the
+ last 4 bits are unused */
+#define GC_SNESMOUSE_LENGTH 32 /* The SNES mouse uses 32 bits, the first
+ 16 bits are equivalent to a gamepad */
#define GC_NES_POWER 0xfc
#define GC_NES_CLOCK 0x01
@@ -242,11 +248,15 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data)
static void gc_nes_process_packet(struct gc *gc)
{
- unsigned char data[GC_SNES_LENGTH];
+ unsigned char data[GC_SNESMOUSE_LENGTH];
struct input_dev *dev;
- int i, j, s;
+ int i, j, s, len;
+ char x_rel, y_rel;
+
+ len = gc->pads[GC_SNESMOUSE] ? GC_SNESMOUSE_LENGTH :
+ (gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH);
- gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
+ gc_nes_read_packet(gc, len, data);
for (i = 0; i < GC_MAX_DEVICES; i++) {
@@ -269,6 +279,44 @@ static void gc_nes_process_packet(struct gc *gc)
for (j = 0; j < 8; j++)
input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
+ if (s & gc->pads[GC_SNESMOUSE]) {
+ /*
+ * The 4 unused bits from SNES controllers appear to be ID bits
+ * so use them to make sure iwe are dealing with a mouse.
+ * gamepad is connected. This is important since
+ * my SNES gamepad sends 1's for bits 16-31, which
+ * cause the mouse pointer to quickly move to the
+ * upper left corner of the screen.
+ */
+ if (!(s & data[12]) && !(s & data[13]) &&
+ !(s & data[14]) && (s & data[15])) {
+ input_report_key(dev, BTN_LEFT, s & data[9]);
+ input_report_key(dev, BTN_RIGHT, s & data[8]);
+
+ x_rel = y_rel = 0;
+ for (j = 0; j < 7; j++) {
+ x_rel <<= 1;
+ if (data[25 + j] & s)
+ x_rel |= 1;
+
+ y_rel <<= 1;
+ if (data[17 + j] & s)
+ y_rel |= 1;
+ }
+
+ if (x_rel) {
+ if (data[24] & s)
+ x_rel = -x_rel;
+ input_report_rel(dev, REL_X, x_rel);
+ }
+
+ if (y_rel) {
+ if (data[16] & s)
+ y_rel = -y_rel;
+ input_report_rel(dev, REL_Y, y_rel);
+ }
+ }
+ }
input_sync(dev);
}
}
@@ -524,10 +572,10 @@ static void gc_timer(unsigned long private)
gc_n64_process_packet(gc);
/*
- * NES and SNES pads
+ * NES and SNES pads or mouse
*/
- if (gc->pads[GC_NES] || gc->pads[GC_SNES])
+ if (gc->pads[GC_NES] || gc->pads[GC_SNES] || gc->pads[GC_SNESMOUSE])
gc_nes_process_packet(gc);
/*
@@ -552,7 +600,7 @@ static int gc_open(struct input_dev *dev)
struct gc *gc = dev->private;
int err;
- err = down_interruptible(&gc->sem);
+ err = mutex_lock_interruptible(&gc->mutex);
if (err)
return err;
@@ -562,7 +610,7 @@ static int gc_open(struct input_dev *dev)
mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
}
- up(&gc->sem);
+ mutex_unlock(&gc->mutex);
return 0;
}
@@ -570,13 +618,13 @@ static void gc_close(struct input_dev *dev)
{
struct gc *gc = dev->private;
- down(&gc->sem);
+ mutex_lock(&gc->mutex);
if (!--gc->used) {
del_timer_sync(&gc->timer);
parport_write_control(gc->pd->port, 0x00);
parport_release(gc->pd);
}
- up(&gc->sem);
+ mutex_unlock(&gc->mutex);
}
static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
@@ -609,10 +657,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
input_dev->open = gc_open;
input_dev->close = gc_close;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ if (pad_type != GC_SNESMOUSE) {
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- for (i = 0; i < 2; i++)
- input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
+ for (i = 0; i < 2; i++)
+ input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
+ } else
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
gc->pads[0] |= gc_status_bit[idx];
gc->pads[pad_type] |= gc_status_bit[idx];
@@ -630,6 +681,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
break;
+ case GC_SNESMOUSE:
+ set_bit(BTN_LEFT, input_dev->keybit);
+ set_bit(BTN_RIGHT, input_dev->keybit);
+ set_bit(REL_X, input_dev->relbit);
+ set_bit(REL_Y, input_dev->relbit);
+ break;
+
case GC_SNES:
for (i = 4; i < 8; i++)
set_bit(gc_snes_btn[i], input_dev->keybit);
@@ -693,7 +751,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
goto err_unreg_pardev;
}
- init_MUTEX(&gc->sem);
+ mutex_init(&gc->mutex);
gc->pd = pd;
init_timer(&gc->timer);
gc->timer.data = (long) gc;
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
index 4678b6dab43..2b8e8456c9f 100644
--- a/drivers/input/joystick/iforce/iforce-ff.c
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -42,14 +42,14 @@ static int make_magnitude_modifier(struct iforce* iforce,
unsigned char data[3];
if (!no_alloc) {
- down(&iforce->mem_mutex);
+ mutex_lock(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
iforce->device_memory.start, iforce->device_memory.end, 2L,
NULL, NULL)) {
- up(&iforce->mem_mutex);
+ mutex_unlock(&iforce->mem_mutex);
return -ENOMEM;
}
- up(&iforce->mem_mutex);
+ mutex_unlock(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
@@ -75,14 +75,14 @@ static int make_period_modifier(struct iforce* iforce,
period = TIME_SCALE(period);
if (!no_alloc) {
- down(&iforce->mem_mutex);
+ mutex_lock(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
iforce->device_memory.start, iforce->device_memory.end, 2L,
NULL, NULL)) {
- up(&iforce->mem_mutex);
+ mutex_unlock(&iforce->mem_mutex);
return -ENOMEM;
}
- up(&iforce->mem_mutex);
+ mutex_unlock(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
@@ -115,14 +115,14 @@ static int make_envelope_modifier(struct iforce* iforce,
fade_duration = TIME_SCALE(fade_duration);
if (!no_alloc) {
- down(&iforce->mem_mutex);
+ mutex_lock(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
iforce->device_memory.start, iforce->device_memory.end, 2L,
NULL, NULL)) {
- up(&iforce->mem_mutex);
+ mutex_unlock(&iforce->mem_mutex);
return -ENOMEM;
}
- up(&iforce->mem_mutex);
+ mutex_unlock(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
@@ -152,14 +152,14 @@ static int make_condition_modifier(struct iforce* iforce,
unsigned char data[10];
if (!no_alloc) {
- down(&iforce->mem_mutex);
+ mutex_lock(&iforce->mem_mutex);
if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
iforce->device_memory.start, iforce->device_memory.end, 2L,
NULL, NULL)) {
- up(&iforce->mem_mutex);
+ mutex_unlock(&iforce->mem_mutex);
return -ENOMEM;
}
- up(&iforce->mem_mutex);
+ mutex_unlock(&iforce->mem_mutex);
}
data[0] = LO(mod_chunk->start);
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index b6bc0499804..ab0a26b924c 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -350,7 +350,7 @@ int iforce_init_device(struct iforce *iforce)
init_waitqueue_head(&iforce->wait);
spin_lock_init(&iforce->xmit_lock);
- init_MUTEX(&iforce->mem_mutex);
+ mutex_init(&iforce->mem_mutex);
iforce->xmit.buf = iforce->xmit_data;
iforce->dev = input_dev;
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index 146f406b8f8..668f24535ba 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -37,7 +37,7 @@
#include <linux/serio.h>
#include <linux/config.h>
#include <linux/circ_buf.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
/* This module provides arbitrary resource management routines.
* I use it to manage the device's memory.
@@ -45,6 +45,7 @@
*/
#include <linux/ioport.h>
+
#define IFORCE_MAX_LENGTH 16
/* iforce::bus */
@@ -146,7 +147,7 @@ struct iforce {
wait_queue_head_t wait;
struct resource device_memory;
struct iforce_core_effect core_effects[FF_EFFECTS_MAX];
- struct semaphore mem_mutex;
+ struct mutex mem_mutex;
};
/* Get hi and low bytes of a 16-bits int */
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index 2b2ec1057de..95c0de7964a 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -589,7 +589,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
struct sw *sw;
struct input_dev *input_dev;
int i, j, k, l;
- int err;
+ int err = 0;
unsigned char *buf = NULL; /* [SW_LENGTH] */
unsigned char *idbuf = NULL; /* [SW_LENGTH] */
unsigned char m = 1;
@@ -776,7 +776,10 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
goto fail4;
}
- return 0;
+ out: kfree(buf);
+ kfree(idbuf);
+
+ return err;
fail4: input_free_device(sw->dev[i]);
fail3: while (--i >= 0)
@@ -784,9 +787,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
kfree(sw);
- kfree(buf);
- kfree(idbuf);
- return err;
+ goto out;
}
static void sw_disconnect(struct gameport *gameport)
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index b154938e88a..5570fd5487c 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -37,6 +37,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/mutex.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
@@ -86,7 +87,7 @@ static struct tgfx {
char phys[TGFX_MAX_DEVICES][32];
int sticks;
int used;
- struct semaphore sem;
+ struct mutex sem;
} *tgfx_base[TGFX_MAX_PORTS];
/*
@@ -128,7 +129,7 @@ static int tgfx_open(struct input_dev *dev)
struct tgfx *tgfx = dev->private;
int err;
- err = down_interruptible(&tgfx->sem);
+ err = mutex_lock_interruptible(&tgfx->sem);
if (err)
return err;
@@ -138,7 +139,7 @@ static int tgfx_open(struct input_dev *dev)
mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
}
- up(&tgfx->sem);
+ mutex_unlock(&tgfx->sem);
return 0;
}
@@ -146,13 +147,13 @@ static void tgfx_close(struct input_dev *dev)
{
struct tgfx *tgfx = dev->private;
- down(&tgfx->sem);
+ mutex_lock(&tgfx->sem);
if (!--tgfx->used) {
del_timer_sync(&tgfx->timer);
parport_write_control(tgfx->pd->port, 0x00);
parport_release(tgfx->pd);
}
- up(&tgfx->sem);
+ mutex_unlock(&tgfx->sem);
}
@@ -191,7 +192,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
goto err_unreg_pardev;
}
- init_MUTEX(&tgfx->sem);
+ mutex_init(&tgfx->sem);
tgfx->pd = pd;
init_timer(&tgfx->timer);
tgfx->timer.data = (long) tgfx;
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 3b0ac3b43c5..a9dda56f62c 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -13,7 +13,7 @@ menuconfig INPUT_KEYBOARD
if INPUT_KEYBOARD
config KEYBOARD_ATKBD
- tristate "AT keyboard" if !X86_PC
+ tristate "AT keyboard" if EMBEDDED || !X86_PC
default y
select SERIO
select SERIO_LIBPS2
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index ffacf6eca5f..fad04b66d26 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -27,6 +27,7 @@
#include <linux/serio.h>
#include <linux/workqueue.h>
#include <linux/libps2.h>
+#include <linux/mutex.h>
#define DRIVER_DESC "AT and PS/2 keyboard driver"
@@ -216,7 +217,7 @@ struct atkbd {
unsigned long time;
struct work_struct event_work;
- struct semaphore event_sem;
+ struct mutex event_mutex;
unsigned long event_mask;
};
@@ -302,19 +303,19 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
if (atkbd->translated) {
if (atkbd->emul ||
- !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
- code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
- (code == ATKBD_RET_ERR && !atkbd->err_xl) ||
- (code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
+ (code != ATKBD_RET_EMUL0 && code != ATKBD_RET_EMUL1 &&
+ code != ATKBD_RET_HANGUEL && code != ATKBD_RET_HANJA &&
+ (code != ATKBD_RET_ERR || atkbd->err_xl) &&
+ (code != ATKBD_RET_BAT || atkbd->bat_xl))) {
atkbd->release = code >> 7;
code &= 0x7f;
}
if (!atkbd->emul) {
if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
- atkbd->bat_xl = !atkbd->release;
+ atkbd->bat_xl = !(data >> 7);
if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f))
- atkbd->err_xl = !atkbd->release;
+ atkbd->err_xl = !(data >> 7);
}
}
@@ -449,7 +450,7 @@ static void atkbd_event_work(void *data)
unsigned char param[2];
int i, j;
- down(&atkbd->event_sem);
+ mutex_lock(&atkbd->event_mutex);
if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) {
param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
@@ -480,7 +481,7 @@ static void atkbd_event_work(void *data)
ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);
}
- up(&atkbd->event_sem);
+ mutex_unlock(&atkbd->event_mutex);
}
/*
@@ -846,7 +847,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio);
INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd);
- init_MUTEX(&atkbd->event_sem);
+ mutex_init(&atkbd->event_mutex);
switch (serio->id.type) {
@@ -862,9 +863,6 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->softrepeat = atkbd_softrepeat;
atkbd->scroll = atkbd_scroll;
- if (!atkbd->write)
- atkbd->softrepeat = 1;
-
if (atkbd->softrepeat)
atkbd->softraw = 1;
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index e301ee4ca26..1f0e720267d 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -29,11 +29,11 @@
#define KB_COLS 12
#define KB_ROWMASK(r) (1 << (r))
#define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 )
-/* zero code, 124 scancodes + 3 hinge combinations */
-#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 )
-#define SCAN_INTERVAL (HZ/10)
+/* zero code, 124 scancodes */
+#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 )
-#define HINGE_SCAN_INTERVAL (HZ/4)
+#define SCAN_INTERVAL (50) /* ms */
+#define HINGE_SCAN_INTERVAL (250) /* ms */
#define CORGI_KEY_CALENDER KEY_F1
#define CORGI_KEY_ADDRESS KEY_F2
@@ -49,9 +49,6 @@
#define CORGI_KEY_MAIL KEY_F10
#define CORGI_KEY_OK KEY_F11
#define CORGI_KEY_MENU KEY_F12
-#define CORGI_HINGE_0 KEY_KP0
-#define CORGI_HINGE_1 KEY_KP1
-#define CORGI_HINGE_2 KEY_KP2
static unsigned char corgikbd_keycode[NR_SCANCODES] = {
0, /* 0 */
@@ -63,7 +60,6 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = {
CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */
KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */
CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */
- CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */
};
@@ -187,7 +183,7 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs
/* if any keys are pressed, enable the timer */
if (num_pressed)
- mod_timer(&corgikbd_data->timer, jiffies + SCAN_INTERVAL);
+ mod_timer(&corgikbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL));
spin_unlock_irqrestore(&corgikbd_data->lock, flags);
}
@@ -228,6 +224,7 @@ static void corgikbd_timer_callback(unsigned long data)
* 0x0c - Keyboard and Screen Closed
*/
+#define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x))
#define HINGE_STABLE_COUNT 2
static int sharpsl_hinge_state;
static int hinge_count;
@@ -239,6 +236,7 @@ static void corgikbd_hinge_timer(unsigned long data)
unsigned long flags;
gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
+ gprr |= (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0);
if (gprr != sharpsl_hinge_state) {
hinge_count = 0;
sharpsl_hinge_state = gprr;
@@ -247,29 +245,40 @@ static void corgikbd_hinge_timer(unsigned long data)
if (hinge_count >= HINGE_STABLE_COUNT) {
spin_lock_irqsave(&corgikbd_data->lock, flags);
- input_report_switch(corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
- input_report_switch(corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
+ input_report_switch(corgikbd_data->input, SW_LID, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
+ input_report_switch(corgikbd_data->input, SW_TABLET_MODE, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
+ input_report_switch(corgikbd_data->input, SW_HEADPHONE_INSERT, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0));
input_sync(corgikbd_data->input);
spin_unlock_irqrestore(&corgikbd_data->lock, flags);
}
}
- mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL);
+ mod_timer(&corgikbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
}
#ifdef CONFIG_PM
static int corgikbd_suspend(struct platform_device *dev, pm_message_t state)
{
+ int i;
struct corgikbd *corgikbd = platform_get_drvdata(dev);
+
corgikbd->suspended = 1;
+ /* strobe 0 is the power key so this can't be made an input for
+ powersaving therefore i = 1 */
+ for (i = 1; i < CORGI_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_IN);
return 0;
}
static int corgikbd_resume(struct platform_device *dev)
{
+ int i;
struct corgikbd *corgikbd = platform_get_drvdata(dev);
+ for (i = 1; i < CORGI_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
+
/* Upon resume, ignore the suspend key for a short while */
corgikbd->suspend_jiffies=jiffies;
corgikbd->suspended = 0;
@@ -331,12 +340,13 @@ static int __init corgikbd_probe(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
set_bit(corgikbd->keycode[i], input_dev->keybit);
clear_bit(0, input_dev->keybit);
- set_bit(SW_0, input_dev->swbit);
- set_bit(SW_1, input_dev->swbit);
+ set_bit(SW_LID, input_dev->swbit);
+ set_bit(SW_TABLET_MODE, input_dev->swbit);
+ set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
input_register_device(corgikbd->input);
- mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
+ mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
@@ -351,6 +361,9 @@ static int __init corgikbd_probe(struct platform_device *pdev)
for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
+ /* Setup the headphone jack as an input */
+ pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
+
return 0;
}
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index 0a90962c38e..2e4abdc2636 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -66,7 +66,7 @@ static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] =
static char hil_language[][16] = { HIL_LOCALE_MAP };
struct hil_kbd {
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
/* Input buffer and index for packets from HIL bus. */
@@ -86,7 +86,7 @@ struct hil_kbd {
/* Process a complete packet after transfer from the HIL */
static void hil_kbd_process_record(struct hil_kbd *kbd)
{
- struct input_dev *dev = &kbd->dev;
+ struct input_dev *dev = kbd->dev;
hil_packet *data = kbd->data;
hil_packet p;
int idx, i, cnt;
@@ -240,8 +240,8 @@ static void hil_kbd_disconnect(struct serio *serio)
return;
}
- input_unregister_device(&kbd->dev);
serio_close(serio);
+ input_unregister_device(kbd->dev);
kfree(kbd);
}
@@ -250,17 +250,22 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
struct hil_kbd *kbd;
uint8_t did, *idd;
int i;
-
- kbd = kmalloc(sizeof(*kbd), GFP_KERNEL);
+
+ kbd = kzalloc(sizeof(*kbd), GFP_KERNEL);
if (!kbd)
return -ENOMEM;
- memset(kbd, 0, sizeof(struct hil_kbd));
- if (serio_open(serio, drv)) goto bail0;
+ kbd->dev = input_allocate_device();
+ if (!kbd->dev)
+ goto bail0;
+
+ kbd->dev->private = kbd;
+
+ if (serio_open(serio, drv))
+ goto bail1;
serio_set_drvdata(serio, kbd);
kbd->serio = serio;
- kbd->dev.private = kbd;
init_MUTEX_LOCKED(&(kbd->sem));
@@ -302,38 +307,38 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]);
break;
default:
- goto bail1;
+ goto bail2;
}
if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
- goto bail1;
+ goto bail2;
}
- kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
- kbd->dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
- kbd->dev.keycodesize = sizeof(hil_kbd_set1[0]);
- kbd->dev.keycode = hil_kbd_set1;
- kbd->dev.name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME;
- kbd->dev.phys = "hpkbd/input0"; /* XXX */
+ kbd->dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ kbd->dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+ kbd->dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
+ kbd->dev->keycodesize = sizeof(hil_kbd_set1[0]);
+ kbd->dev->keycode = hil_kbd_set1;
+ kbd->dev->name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME;
+ kbd->dev->phys = "hpkbd/input0"; /* XXX */
- kbd->dev.id.bustype = BUS_HIL;
- kbd->dev.id.vendor = PCI_VENDOR_ID_HP;
- kbd->dev.id.product = 0x0001; /* TODO: get from kbd->rsc */
- kbd->dev.id.version = 0x0100; /* TODO: get from kbd->rsc */
- kbd->dev.dev = &serio->dev;
+ kbd->dev->id.bustype = BUS_HIL;
+ kbd->dev->id.vendor = PCI_VENDOR_ID_HP;
+ kbd->dev->id.product = 0x0001; /* TODO: get from kbd->rsc */
+ kbd->dev->id.version = 0x0100; /* TODO: get from kbd->rsc */
+ kbd->dev->dev = &serio->dev;
for (i = 0; i < 128; i++) {
- set_bit(hil_kbd_set1[i], kbd->dev.keybit);
- set_bit(hil_kbd_set3[i], kbd->dev.keybit);
+ set_bit(hil_kbd_set1[i], kbd->dev->keybit);
+ set_bit(hil_kbd_set3[i], kbd->dev->keybit);
}
- clear_bit(0, kbd->dev.keybit);
+ clear_bit(0, kbd->dev->keybit);
- input_register_device(&kbd->dev);
+ input_register_device(kbd->dev);
printk(KERN_INFO "input: %s, ID: %d\n",
- kbd->dev.name, did);
+ kbd->dev->name, did);
serio->write(serio, 0);
serio->write(serio, 0);
@@ -343,11 +348,13 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
up(&(kbd->sem));
return 0;
- bail1:
+ bail2:
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
+ bail1:
+ input_free_device(kbd->dev);
bail0:
kfree(kbd);
- serio_set_drvdata(serio, NULL);
return -EIO;
}
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index e95bc052e32..33edd030aa7 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1998 Philip Blundell <philb@gnu.org>
* Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
- * Copyright (C) 1999-2003 Helge Deller <deller@gmx.de>
+ * Copyright (C) 1999-2006 Helge Deller <deller@gmx.de>
*
* Very basic HP Human Interface Loop (HIL) driver.
* This driver handles the keyboard on HP300 (m68k) and on some
@@ -90,7 +90,7 @@ static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] =
/* HIL structure */
static struct {
- struct input_dev dev;
+ struct input_dev *dev;
unsigned int curdev;
@@ -117,7 +117,7 @@ static void poll_finished(void)
down = (hil_dev.data[1] & 1) == 0;
scode = hil_dev.data[1] >> 1;
key = hphilkeyb_keycode[scode];
- input_report_key(&hil_dev.dev, key, down);
+ input_report_key(hil_dev.dev, key, down);
break;
}
hil_dev.curdev = 0;
@@ -207,9 +207,14 @@ hil_keyb_init(void)
unsigned int i, kbid;
wait_queue_head_t hil_wait;
- if (hil_dev.dev.id.bustype) {
+ if (hil_dev.dev) {
return -ENODEV; /* already initialized */
}
+
+ hil_dev.dev = input_allocate_device();
+ if (!hil_dev.dev)
+ return -ENOMEM;
+ hil_dev.dev->private = &hil_dev;
#if defined(CONFIG_HP300)
if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
@@ -247,28 +252,26 @@ hil_keyb_init(void)
c = 0;
hil_do(HIL_WRITEKBDSADR, &c, 1);
- init_input_dev(&hil_dev.dev);
-
for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
if (hphilkeyb_keycode[i] != KEY_RESERVED)
- set_bit(hphilkeyb_keycode[i], hil_dev.dev.keybit);
-
- hil_dev.dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- hil_dev.dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
- hil_dev.dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
- hil_dev.dev.keycodesize = sizeof(hphilkeyb_keycode[0]);
- hil_dev.dev.keycode = hphilkeyb_keycode;
- hil_dev.dev.name = "HIL keyboard";
- hil_dev.dev.phys = "hpkbd/input0";
-
- hil_dev.dev.id.bustype = BUS_HIL;
- hil_dev.dev.id.vendor = PCI_VENDOR_ID_HP;
- hil_dev.dev.id.product = 0x0001;
- hil_dev.dev.id.version = 0x0010;
-
- input_register_device(&hil_dev.dev);
+ set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit);
+
+ hil_dev.dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ hil_dev.dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+ hil_dev.dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
+ hil_dev.dev->keycodesize = sizeof(hphilkeyb_keycode[0]);
+ hil_dev.dev->keycode = hphilkeyb_keycode;
+ hil_dev.dev->name = "HIL keyboard";
+ hil_dev.dev->phys = "hpkbd/input0";
+
+ hil_dev.dev->id.bustype = BUS_HIL;
+ hil_dev.dev->id.vendor = PCI_VENDOR_ID_HP;
+ hil_dev.dev->id.product = 0x0001;
+ hil_dev.dev->id.version = 0x0010;
+
+ input_register_device(hil_dev.dev);
printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
- hil_dev.dev.name, kbid, HILBASE, HIL_IRQ);
+ hil_dev.dev->name, kbid, HILBASE, HIL_IRQ);
return 0;
}
@@ -329,7 +332,9 @@ static void __exit hil_exit(void)
/* Turn off interrupts */
hil_do(HIL_INTOFF, NULL, 0);
- input_unregister_device(&hil_dev.dev);
+ input_unregister_device(hil_dev.dev);
+
+ hil_dev.dev = NULL;
#if defined(CONFIG_PARISC)
unregister_parisc_driver(&hil_driver);
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 83999d58312..c5d03fb77bc 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -30,6 +30,7 @@
#define SCANCODE(r,c) (((r)<<4) + (c) + 1)
#define NR_SCANCODES ((KB_ROWS<<4) + 1)
+#define SCAN_INTERVAL (50) /* ms */
#define HINGE_SCAN_INTERVAL (150) /* ms */
#define SPITZ_KEY_CALENDER KEY_F1
@@ -52,8 +53,8 @@ static unsigned char spitzkbd_keycode[NR_SCANCODES] = {
KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */
0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */
KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */
- SPITZ_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */
- SPITZ_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */
+ SPITZ_KEY_ADDRESS, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */
+ SPITZ_KEY_CALENDER, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */
SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */
KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */
};
@@ -230,7 +231,7 @@ static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs
/* if any keys are pressed, enable the timer */
if (num_pressed)
- mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(100));
+ mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL));
spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
}
@@ -287,6 +288,7 @@ static void spitzkbd_hinge_timer(unsigned long data)
unsigned long flags;
state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB));
+ state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT));
if (state != sharpsl_hinge_state) {
hinge_count = 0;
sharpsl_hinge_state = state;
@@ -297,8 +299,9 @@ static void spitzkbd_hinge_timer(unsigned long data)
if (hinge_count >= HINGE_STABLE_COUNT) {
spin_lock_irqsave(&spitzkbd_data->lock, flags);
- input_report_switch(spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
- input_report_switch(spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
+ input_report_switch(spitzkbd_data->input, SW_LID, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
+ input_report_switch(spitzkbd_data->input, SW_TABLET_MODE, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
+ input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0));
input_sync(spitzkbd_data->input);
spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
@@ -395,8 +398,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++)
set_bit(spitzkbd->keycode[i], input_dev->keybit);
clear_bit(0, input_dev->keybit);
- set_bit(SW_0, input_dev->swbit);
- set_bit(SW_1, input_dev->swbit);
+ set_bit(SW_LID, input_dev->swbit);
+ set_bit(SW_TABLET_MODE, input_dev->swbit);
+ set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
input_register_device(input_dev);
@@ -432,6 +436,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
"Spitzkbd SWB", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
+ SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+ "Spitzkbd HP", spitzkbd);
printk(KERN_INFO "input: Spitz Keyboard Registered\n");
@@ -450,6 +457,7 @@ static int spitzkbd_remove(struct platform_device *dev)
free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd);
free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd);
free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd);
del_timer_sync(&spitzkbd->htimer);
del_timer_sync(&spitzkbd->timer);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 1ef477f4469..afd322185bb 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -24,7 +24,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("PC Speaker beeper driver");
MODULE_LICENSE("GPL");
-static struct platform_device *pcspkr_platform_device;
static DEFINE_SPINLOCK(i8253_beep_lock);
static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -135,35 +134,11 @@ static struct platform_driver pcspkr_platform_driver = {
static int __init pcspkr_init(void)
{
- int err;
-
- err = platform_driver_register(&pcspkr_platform_driver);
- if (err)
- return err;
-
- pcspkr_platform_device = platform_device_alloc("pcspkr", -1);
- if (!pcspkr_platform_device) {
- err = -ENOMEM;
- goto err_unregister_driver;
- }
-
- err = platform_device_add(pcspkr_platform_device);
- if (err)
- goto err_free_device;
-
- return 0;
-
- err_free_device:
- platform_device_put(pcspkr_platform_device);
- err_unregister_driver:
- platform_driver_unregister(&pcspkr_platform_driver);
-
- return err;
+ return platform_driver_register(&pcspkr_platform_driver);
}
static void __exit pcspkr_exit(void)
{
- platform_device_unregister(pcspkr_platform_device);
platform_driver_unregister(&pcspkr_platform_driver);
}
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 546ed9b4901..d723e9ad7c4 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -194,7 +194,7 @@ static int uinput_open(struct inode *inode, struct file *file)
if (!newdev)
return -ENOMEM;
- init_MUTEX(&newdev->sem);
+ mutex_init(&newdev->mutex);
spin_lock_init(&newdev->requests_lock);
init_waitqueue_head(&newdev->requests_waitq);
init_waitqueue_head(&newdev->waitq);
@@ -340,7 +340,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t
struct uinput_device *udev = file->private_data;
int retval;
- retval = down_interruptible(&udev->sem);
+ retval = mutex_lock_interruptible(&udev->mutex);
if (retval)
return retval;
@@ -348,7 +348,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t
uinput_inject_event(udev, buffer, count) :
uinput_setup_device(udev, buffer, count);
- up(&udev->sem);
+ mutex_unlock(&udev->mutex);
return retval;
}
@@ -369,7 +369,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count,
if (retval)
return retval;
- retval = down_interruptible(&udev->sem);
+ retval = mutex_lock_interruptible(&udev->mutex);
if (retval)
return retval;
@@ -388,7 +388,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count,
}
out:
- up(&udev->sem);
+ mutex_unlock(&udev->mutex);
return retval;
}
@@ -439,7 +439,7 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
udev = file->private_data;
- retval = down_interruptible(&udev->sem);
+ retval = mutex_lock_interruptible(&udev->mutex);
if (retval)
return retval;
@@ -589,7 +589,7 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
out:
- up(&udev->sem);
+ mutex_unlock(&udev->mutex);
return retval;
}
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 4b415d9b012..e4e5be111c9 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -273,6 +273,18 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] = {
{ KE_END, 0 }
};
+static struct key_entry keymap_fujitsu_n3510[] = {
+ { KE_KEY, 0x11, KEY_PROG1 },
+ { KE_KEY, 0x12, KEY_PROG2 },
+ { KE_KEY, 0x36, KEY_WWW },
+ { KE_KEY, 0x31, KEY_MAIL },
+ { KE_KEY, 0x71, KEY_STOPCD },
+ { KE_KEY, 0x72, KEY_PLAYPAUSE },
+ { KE_KEY, 0x74, KEY_REWIND },
+ { KE_KEY, 0x78, KEY_FORWARD },
+ { KE_END, 0 }
+};
+
static struct key_entry keymap_wistron_ms2141[] = {
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
@@ -306,6 +318,16 @@ static struct key_entry keymap_acer_travelmate_240[] = {
{ KE_END, 0 }
};
+static struct key_entry keymap_aopen_1559as[] = {
+ { KE_KEY, 0x01, KEY_HELP },
+ { KE_KEY, 0x06, KEY_PROG3 },
+ { KE_KEY, 0x11, KEY_PROG1 },
+ { KE_KEY, 0x12, KEY_PROG2 },
+ { KE_WIFI, 0x30, 0 },
+ { KE_KEY, 0x31, KEY_MAIL },
+ { KE_KEY, 0x36, KEY_WWW },
+};
+
/*
* If your machine is not here (which is currently rather likely), please send
* a list of buttons and their key codes (reported when loading this module
@@ -323,6 +345,24 @@ static struct dmi_system_id dmi_ids[] = {
},
{
.callback = dmi_matched,
+ .ident = "Fujitsu-Siemens Amilo M7400",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M "),
+ },
+ .driver_data = keymap_fs_amilo_pro_v2000
+ },
+ {
+ .callback = dmi_matched,
+ .ident = "Fujitsu N3510",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "N3510"),
+ },
+ .driver_data = keymap_fujitsu_n3510
+ },
+ {
+ .callback = dmi_matched,
.ident = "Acer Aspire 1500",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -339,6 +379,15 @@ static struct dmi_system_id dmi_ids[] = {
},
.driver_data = keymap_acer_travelmate_240
},
+ {
+ .callback = dmi_matched,
+ .ident = "AOpen 1559AS",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "E2U"),
+ DMI_MATCH(DMI_BOARD_NAME, "E2U"),
+ },
+ .driver_data = keymap_aopen_1559as
+ },
{ NULL, }
};
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 2141501e9f2..a0e2e797c6d 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -100,8 +100,8 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
}
if (priv->i->flags & ALPS_OLDPROTO) {
- left = packet[2] & 0x08;
- right = packet[2] & 0x10;
+ left = packet[2] & 0x10;
+ right = packet[2] & 0x08;
middle = 0;
x = packet[1] | ((packet[0] & 0x07) << 7);
y = packet[4] | ((packet[3] & 0x07) << 7);
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index c2bf2ed07dc..69f02178c52 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -55,7 +55,7 @@ MODULE_LICENSE("Dual BSD/GPL");
#define HIL_PTR_MAX_LENGTH 16
struct hil_ptr {
- struct input_dev dev;
+ struct input_dev *dev;
struct serio *serio;
/* Input buffer and index for packets from HIL bus. */
@@ -79,7 +79,7 @@ struct hil_ptr {
/* Process a complete packet after transfer from the HIL */
static void hil_ptr_process_record(struct hil_ptr *ptr)
{
- struct input_dev *dev = &ptr->dev;
+ struct input_dev *dev = ptr->dev;
hil_packet *data = ptr->data;
hil_packet p;
int idx, i, cnt, laxis;
@@ -148,12 +148,12 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
if (absdev) {
val = lo + (hi<<8);
#ifdef TABLET_AUTOADJUST
- if (val < ptr->dev.absmin[ABS_X + i])
- ptr->dev.absmin[ABS_X + i] = val;
- if (val > ptr->dev.absmax[ABS_X + i])
- ptr->dev.absmax[ABS_X + i] = val;
+ if (val < dev->absmin[ABS_X + i])
+ dev->absmin[ABS_X + i] = val;
+ if (val > dev->absmax[ABS_X + i])
+ dev->absmax[ABS_X + i] = val;
#endif
- if (i%3) val = ptr->dev.absmax[ABS_X + i] - val;
+ if (i%3) val = dev->absmax[ABS_X + i] - val;
input_report_abs(dev, ABS_X + i, val);
} else {
val = (int) (((int8_t)lo) | ((int8_t)hi<<8));
@@ -233,26 +233,32 @@ static void hil_ptr_disconnect(struct serio *serio)
return;
}
- input_unregister_device(&ptr->dev);
serio_close(serio);
+ input_unregister_device(ptr->dev);
kfree(ptr);
}
static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
{
- struct hil_ptr *ptr;
- char *txt;
- unsigned int i, naxsets, btntype;
- uint8_t did, *idd;
+ struct hil_ptr *ptr;
+ char *txt;
+ unsigned int i, naxsets, btntype;
+ uint8_t did, *idd;
- if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return -ENOMEM;
- memset(ptr, 0, sizeof(struct hil_ptr));
+ if (!(ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL)))
+ return -ENOMEM;
- if (serio_open(serio, driver)) goto bail0;
+ ptr->dev = input_allocate_device();
+ if (!ptr->dev)
+ goto bail0;
+
+ ptr->dev->private = ptr;
+
+ if (serio_open(serio, driver))
+ goto bail1;
serio_set_drvdata(serio, ptr);
ptr->serio = serio;
- ptr->dev.private = ptr;
init_MUTEX_LOCKED(&(ptr->sem));
@@ -283,25 +289,24 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
up(&(ptr->sem));
- init_input_dev(&ptr->dev);
did = ptr->idd[0];
idd = ptr->idd + 1;
txt = "unknown";
if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
- ptr->dev.evbit[0] = BIT(EV_REL);
+ ptr->dev->evbit[0] = BIT(EV_REL);
txt = "relative";
}
if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) {
- ptr->dev.evbit[0] = BIT(EV_ABS);
+ ptr->dev->evbit[0] = BIT(EV_ABS);
txt = "absolute";
}
- if (!ptr->dev.evbit[0]) {
- goto bail1;
+ if (!ptr->dev->evbit[0]) {
+ goto bail2;
}
ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
- if (ptr->nbtn) ptr->dev.evbit[0] |= BIT(EV_KEY);
+ if (ptr->nbtn) ptr->dev->evbit[0] |= BIT(EV_KEY);
naxsets = HIL_IDD_NUM_AXSETS(*idd);
ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);
@@ -325,7 +330,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
btntype = BTN_MOUSE;
for (i = 0; i < ptr->nbtn; i++) {
- set_bit(btntype | i, ptr->dev.keybit);
+ set_bit(btntype | i, ptr->dev->keybit);
ptr->btnmap[i] = btntype | i;
}
@@ -337,50 +342,52 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
for (i = 0; i < ptr->naxes; i++) {
- set_bit(REL_X + i, ptr->dev.relbit);
+ set_bit(REL_X + i, ptr->dev->relbit);
}
for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
- set_bit(REL_X + i, ptr->dev.relbit);
+ set_bit(REL_X + i, ptr->dev->relbit);
}
} else {
for (i = 0; i < ptr->naxes; i++) {
- set_bit(ABS_X + i, ptr->dev.absbit);
- ptr->dev.absmin[ABS_X + i] = 0;
- ptr->dev.absmax[ABS_X + i] =
+ set_bit(ABS_X + i, ptr->dev->absbit);
+ ptr->dev->absmin[ABS_X + i] = 0;
+ ptr->dev->absmax[ABS_X + i] =
HIL_IDD_AXIS_MAX((ptr->idd + 1), i);
}
for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
- set_bit(ABS_X + i, ptr->dev.absbit);
- ptr->dev.absmin[ABS_X + i] = 0;
- ptr->dev.absmax[ABS_X + i] =
+ set_bit(ABS_X + i, ptr->dev->absbit);
+ ptr->dev->absmin[ABS_X + i] = 0;
+ ptr->dev->absmax[ABS_X + i] =
HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3));
}
#ifdef TABLET_AUTOADJUST
for (i = 0; i < ABS_MAX; i++) {
- int diff = ptr->dev.absmax[ABS_X + i] / 10;
- ptr->dev.absmin[ABS_X + i] += diff;
- ptr->dev.absmax[ABS_X + i] -= diff;
+ int diff = ptr->dev->absmax[ABS_X + i] / 10;
+ ptr->dev->absmin[ABS_X + i] += diff;
+ ptr->dev->absmax[ABS_X + i] -= diff;
}
#endif
}
- ptr->dev.name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME;
+ ptr->dev->name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME;
- ptr->dev.id.bustype = BUS_HIL;
- ptr->dev.id.vendor = PCI_VENDOR_ID_HP;
- ptr->dev.id.product = 0x0001; /* TODO: get from ptr->rsc */
- ptr->dev.id.version = 0x0100; /* TODO: get from ptr->rsc */
- ptr->dev.dev = &serio->dev;
+ ptr->dev->id.bustype = BUS_HIL;
+ ptr->dev->id.vendor = PCI_VENDOR_ID_HP;
+ ptr->dev->id.product = 0x0001; /* TODO: get from ptr->rsc */
+ ptr->dev->id.version = 0x0100; /* TODO: get from ptr->rsc */
+ ptr->dev->dev = &serio->dev;
- input_register_device(&ptr->dev);
+ input_register_device(ptr->dev);
printk(KERN_INFO "input: %s (%s), ID: %d\n",
- ptr->dev.name,
+ ptr->dev->name,
(btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
did);
return 0;
- bail1:
+ bail2:
serio_close(serio);
+ bail1:
+ input_free_device(ptr->dev);
bail0:
kfree(ptr);
serio_set_drvdata(serio, NULL);
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index 5ccc3ef3b89..c14395ba798 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -22,12 +22,36 @@
static struct dmi_system_id lifebook_dmi_table[] = {
{
+ .ident = "LifeBook B",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"),
+ },
+ },
+ {
.ident = "Lifebook B",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
},
},
{
+ .ident = "Lifebook B213x/B2150",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"),
+ },
+ },
+ {
+ .ident = "Zephyr",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"),
+ },
+ },
+ {
+ .ident = "CF-18",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
+ },
+ },
+ {
.ident = "Lifebook B142",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 40333d61093..2f0d2884081 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -19,6 +19,7 @@
#define PS2PP_KIND_WHEEL 1
#define PS2PP_KIND_MX 2
#define PS2PP_KIND_TP3 3
+#define PS2PP_KIND_TRACKMAN 4
/* Logitech mouse features */
#define PS2PP_WHEEL 0x01
@@ -223,6 +224,7 @@ static struct ps2pp_info *get_model_info(unsigned char model)
{ 73, 0, PS2PP_SIDE_BTN },
{ 75, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 76, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
+ { 79, PS2PP_KIND_TRACKMAN, PS2PP_WHEEL }, /* TrackMan with wheel */
{ 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL },
{ 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
@@ -298,6 +300,10 @@ static void ps2pp_set_model_properties(struct psmouse *psmouse, struct ps2pp_inf
psmouse->name = "TouchPad 3";
break;
+ case PS2PP_KIND_TRACKMAN:
+ psmouse->name = "TrackMan";
+ break;
+
default:
/*
* Set name to "Mouse" only when using PS2++,
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index ad621746767..136321a2cfd 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -20,6 +20,8 @@
#include <linux/serio.h>
#include <linux/init.h>
#include <linux/libps2.h>
+#include <linux/mutex.h>
+
#include "psmouse.h"
#include "synaptics.h"
#include "logips2pp.h"
@@ -98,13 +100,13 @@ __obsolete_setup("psmouse_resetafter=");
__obsolete_setup("psmouse_rate=");
/*
- * psmouse_sem protects all operations changing state of mouse
+ * psmouse_mutex protects all operations changing state of mouse
* (connecting, disconnecting, changing rate or resolution via
* sysfs). We could use a per-device semaphore but since there
* rarely more than one PS/2 mouse connected and since semaphore
* is taken in "slow" paths it is not worth it.
*/
-static DECLARE_MUTEX(psmouse_sem);
+static DEFINE_MUTEX(psmouse_mutex);
static struct workqueue_struct *kpsmoused_wq;
@@ -300,8 +302,10 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
* Check if this is a new device announcement (0xAA 0x00)
*/
if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) {
- if (psmouse->pktcnt == 1)
+ if (psmouse->pktcnt == 1) {
+ psmouse->last = jiffies;
goto out;
+ }
if (psmouse->packet[1] == PSMOUSE_RET_ID) {
__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
@@ -868,7 +872,7 @@ static void psmouse_resync(void *p)
int failed = 0, enabled = 0;
int i;
- down(&psmouse_sem);
+ mutex_lock(&psmouse_mutex);
if (psmouse->state != PSMOUSE_RESYNCING)
goto out;
@@ -948,7 +952,7 @@ static void psmouse_resync(void *p)
if (parent)
psmouse_activate(parent);
out:
- up(&psmouse_sem);
+ mutex_unlock(&psmouse_mutex);
}
/*
@@ -974,14 +978,14 @@ static void psmouse_disconnect(struct serio *serio)
sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
- down(&psmouse_sem);
+ mutex_lock(&psmouse_mutex);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
/* make sure we don't have a resync in progress */
- up(&psmouse_sem);
+ mutex_unlock(&psmouse_mutex);
flush_workqueue(kpsmoused_wq);
- down(&psmouse_sem);
+ mutex_lock(&psmouse_mutex);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent);
@@ -1004,7 +1008,7 @@ static void psmouse_disconnect(struct serio *serio)
if (parent)
psmouse_activate(parent);
- up(&psmouse_sem);
+ mutex_unlock(&psmouse_mutex);
}
static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto)
@@ -1076,7 +1080,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
struct input_dev *input_dev;
int retval = -ENOMEM;
- down(&psmouse_sem);
+ mutex_lock(&psmouse_mutex);
/*
* If this is a pass-through port deactivate parent so the device
@@ -1144,7 +1148,7 @@ out:
if (parent)
psmouse_activate(parent);
- up(&psmouse_sem);
+ mutex_unlock(&psmouse_mutex);
return retval;
}
@@ -1161,7 +1165,7 @@ static int psmouse_reconnect(struct serio *serio)
return -1;
}
- down(&psmouse_sem);
+ mutex_lock(&psmouse_mutex);
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent);
@@ -1195,7 +1199,7 @@ out:
if (parent)
psmouse_activate(parent);
- up(&psmouse_sem);
+ mutex_unlock(&psmouse_mutex);
return rc;
}
@@ -1273,7 +1277,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
goto out_unpin;
}
- retval = down_interruptible(&psmouse_sem);
+ retval = mutex_lock_interruptible(&psmouse_mutex);
if (retval)
goto out_unpin;
@@ -1281,7 +1285,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
if (psmouse->state == PSMOUSE_IGNORE) {
retval = -ENODEV;
- goto out_up;
+ goto out_unlock;
}
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
@@ -1299,8 +1303,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
if (parent)
psmouse_activate(parent);
- out_up:
- up(&psmouse_sem);
+ out_unlock:
+ mutex_unlock(&psmouse_mutex);
out_unpin:
serio_unpin_driver(serio);
return retval;
@@ -1357,11 +1361,11 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
return -EIO;
}
- up(&psmouse_sem);
+ mutex_unlock(&psmouse_mutex);
serio_unpin_driver(serio);
serio_unregister_child_port(serio);
serio_pin_driver_uninterruptible(serio);
- down(&psmouse_sem);
+ mutex_lock(&psmouse_mutex);
if (serio->drv != &psmouse_drv) {
input_free_device(new_dev);
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 2051bec2c39..ad5d0a85e96 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -247,14 +247,12 @@ static void synaptics_pt_create(struct psmouse *psmouse)
{
struct serio *serio;
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+ serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio) {
printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
return;
}
- memset(serio, 0, sizeof(struct serio));
-
serio->id.type = SERIO_PS_PSTHRU;
strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
@@ -605,14 +603,21 @@ static struct dmi_system_id toshiba_dmi_table[] = {
.ident = "Toshiba Satellite",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- DMI_MATCH(DMI_PRODUCT_NAME , "Satellite"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
},
},
{
.ident = "Toshiba Dynabook",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- DMI_MATCH(DMI_PRODUCT_NAME , "dynabook"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"),
+ },
+ },
+ {
+ .ident = "Toshiba Portege M300",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
},
},
{ }
@@ -623,10 +628,9 @@ int synaptics_init(struct psmouse *psmouse)
{
struct synaptics_data *priv;
- psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL);
+ psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
if (!priv)
return -1;
- memset(priv, 0, sizeof(struct synaptics_data));
if (synaptics_query_hardware(psmouse)) {
printk(KERN_ERR "Unable to query Synaptics hardware.\n");
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 9abed18d2ec..b685a507955 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -412,9 +412,8 @@ static int mousedev_open(struct inode * inode, struct file * file)
if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
return -ENODEV;
- if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
+ if (!(list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
return -ENOMEM;
- memset(list, 0, sizeof(struct mousedev_list));
spin_lock_init(&list->packet_lock);
list->pos_x = xres / 2;
@@ -626,9 +625,8 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
return NULL;
}
- if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL)))
+ if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL)))
return NULL;
- memset(mousedev, 0, sizeof(struct mousedev));
INIT_LIST_HEAD(&mousedev->list);
init_waitqueue_head(&mousedev->wait);
diff --git a/drivers/input/power.c b/drivers/input/power.c
index bfc5c63ebff..526e6070600 100644
--- a/drivers/input/power.c
+++ b/drivers/input/power.c
@@ -103,9 +103,8 @@ static struct input_handle *power_connect(struct input_handler *handler,
{
struct input_handle *handle;
- if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+ if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
return NULL;
- memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->handler = handler;
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index a7b0de0f92b..c0b1e4becad 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -1,7 +1,7 @@
/*
* drivers/input/serio/gscps2.c
*
- * Copyright (c) 2004 Helge Deller <deller@gmx.de>
+ * Copyright (c) 2004-2006 Helge Deller <deller@gmx.de>
* Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
* Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org>
*
@@ -354,7 +354,7 @@ static int __init gscps2_probe(struct parisc_device *dev)
memset(serio, 0, sizeof(struct serio));
ps2port->port = serio;
ps2port->padev = dev;
- ps2port->addr = ioremap(hpa, GSC_STATUS + 4);
+ ps2port->addr = ioremap_nocache(hpa, GSC_STATUS + 4);
spin_lock_init(&ps2port->lock);
gscps2_reset(ps2port);
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index ea499783fb1..bbbe15e2190 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -872,9 +872,8 @@ int hil_mlc_register(hil_mlc *mlc) {
for (i = 0; i < HIL_MLC_DEVMEM; i++) {
struct serio *mlc_serio;
hil_mlc_copy_di_scratch(mlc, i);
- mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL);
+ mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL);
mlc->serio[i] = mlc_serio;
- memset(mlc_serio, 0, sizeof(*mlc_serio));
mlc_serio->id = hil_mlc_serio_id;
mlc_serio->write = hil_mlc_serio_write;
mlc_serio->open = hil_mlc_serio_open;
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index 9a922164425..cc21914fbc7 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -67,14 +67,14 @@ static inline int i8042_platform_init(void)
* On some platforms touching the i8042 data register region can do really
* bad things. Because of this the region is always reserved on such boxes.
*/
-#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64)
+#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC_MERGE)
if (!request_region(I8042_DATA_REG, 16, "i8042"))
return -EBUSY;
#endif
i8042_reset = 1;
-#if defined(CONFIG_PPC64)
+#if defined(CONFIG_PPC_MERGE)
if (check_legacy_ioport(I8042_DATA_REG))
return -EBUSY;
if (!request_region(I8042_DATA_REG, 16, "i8042"))
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index a4c6f352272..f606e96bc2f 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -192,7 +192,9 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
#include <linux/pnp.h>
static int i8042_pnp_kbd_registered;
+static unsigned int i8042_pnp_kbd_devices;
static int i8042_pnp_aux_registered;
+static unsigned int i8042_pnp_aux_devices;
static int i8042_pnp_command_reg;
static int i8042_pnp_data_reg;
@@ -219,6 +221,7 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
}
+ i8042_pnp_kbd_devices++;
return 0;
}
@@ -239,6 +242,7 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
}
+ i8042_pnp_aux_devices++;
return 0;
}
@@ -287,21 +291,23 @@ static void i8042_pnp_exit(void)
static int __init i8042_pnp_init(void)
{
- int result_kbd = 0, result_aux = 0;
char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 };
+ int err;
if (i8042_nopnp) {
printk(KERN_INFO "i8042: PNP detection disabled\n");
return 0;
}
- if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0)
+ err = pnp_register_driver(&i8042_pnp_kbd_driver);
+ if (!err)
i8042_pnp_kbd_registered = 1;
- if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0)
+ err = pnp_register_driver(&i8042_pnp_aux_driver);
+ if (!err)
i8042_pnp_aux_registered = 1;
- if (result_kbd <= 0 && result_aux <= 0) {
+ if (!i8042_pnp_kbd_devices && !i8042_pnp_aux_devices) {
i8042_pnp_exit();
#if defined(__ia64__)
return -ENODEV;
@@ -311,24 +317,24 @@ static int __init i8042_pnp_init(void)
#endif
}
- if (result_kbd > 0)
+ if (i8042_pnp_kbd_devices)
snprintf(kbd_irq_str, sizeof(kbd_irq_str),
"%d", i8042_pnp_kbd_irq);
- if (result_aux > 0)
+ if (i8042_pnp_aux_devices)
snprintf(aux_irq_str, sizeof(aux_irq_str),
"%d", i8042_pnp_aux_irq);
printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n",
- i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "",
+ i8042_pnp_kbd_name, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "",
i8042_pnp_aux_name,
i8042_pnp_data_reg, i8042_pnp_command_reg,
- kbd_irq_str, (result_kbd > 0 && result_aux > 0) ? "," : "",
+ kbd_irq_str, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "",
aux_irq_str);
#if defined(__ia64__)
- if (result_kbd <= 0)
+ if (!i8042_pnp_kbd_devices)
i8042_nokbd = 1;
- if (result_aux <= 0)
+ if (!i8042_pnp_aux_devices)
i8042_noaux = 1;
#endif
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index d4c990f7c85..79c97f94bcb 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -84,7 +84,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
maxbytes = sizeof(ps2dev->cmdbuf);
}
- down(&ps2dev->cmd_sem);
+ mutex_lock(&ps2dev->cmd_mutex);
serio_pause_rx(ps2dev->serio);
ps2dev->flags = PS2_FLAG_CMD;
@@ -94,7 +94,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
wait_event_timeout(ps2dev->wait,
!(ps2dev->flags & PS2_FLAG_CMD),
msecs_to_jiffies(timeout));
- up(&ps2dev->cmd_sem);
+ mutex_unlock(&ps2dev->cmd_mutex);
}
/*
@@ -177,7 +177,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
return -1;
}
- down(&ps2dev->cmd_sem);
+ mutex_lock(&ps2dev->cmd_mutex);
serio_pause_rx(ps2dev->serio);
ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0;
@@ -229,7 +229,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
ps2dev->flags = 0;
serio_continue_rx(ps2dev->serio);
- up(&ps2dev->cmd_sem);
+ mutex_unlock(&ps2dev->cmd_mutex);
return rc;
}
@@ -281,7 +281,7 @@ int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int comman
void ps2_init(struct ps2dev *ps2dev, struct serio *serio)
{
- init_MUTEX(&ps2dev->cmd_sem);
+ mutex_init(&ps2dev->cmd_mutex);
init_waitqueue_head(&ps2dev->wait);
ps2dev->serio = serio;
}
diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c
index 1d15c281981..a5c1fb3a4a5 100644
--- a/drivers/input/serio/parkbd.c
+++ b/drivers/input/serio/parkbd.c
@@ -171,9 +171,8 @@ static struct serio * __init parkbd_allocate_serio(void)
{
struct serio *serio;
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+ serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
- memset(serio, 0, sizeof(struct serio));
serio->id.type = parkbd_mode;
serio->write = parkbd_write,
strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index a3bd11589bc..513d37fc1ac 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -111,11 +111,10 @@ static int __devinit rpckbd_probe(struct platform_device *dev)
{
struct serio *serio;
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+ serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio)
return -ENOMEM;
- memset(serio, 0, sizeof(struct serio));
serio->id.type = SERIO_8042;
serio->write = rpckbd_write;
serio->open = rpckbd_open;
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 2f76813c3a6..6521034bc93 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -34,6 +34,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/kthread.h>
+#include <linux/mutex.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Serio abstraction core");
@@ -52,10 +53,10 @@ EXPORT_SYMBOL(serio_rescan);
EXPORT_SYMBOL(serio_reconnect);
/*
- * serio_sem protects entire serio subsystem and is taken every time
+ * serio_mutex protects entire serio subsystem and is taken every time
* serio port or driver registrered or unregistered.
*/
-static DECLARE_MUTEX(serio_sem);
+static DEFINE_MUTEX(serio_mutex);
static LIST_HEAD(serio_list);
@@ -70,9 +71,9 @@ static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
{
int retval;
- down(&serio->drv_sem);
+ mutex_lock(&serio->drv_mutex);
retval = drv->connect(serio, drv);
- up(&serio->drv_sem);
+ mutex_unlock(&serio->drv_mutex);
return retval;
}
@@ -81,20 +82,20 @@ static int serio_reconnect_driver(struct serio *serio)
{
int retval = -1;
- down(&serio->drv_sem);
+ mutex_lock(&serio->drv_mutex);
if (serio->drv && serio->drv->reconnect)
retval = serio->drv->reconnect(serio);
- up(&serio->drv_sem);
+ mutex_unlock(&serio->drv_mutex);
return retval;
}
static void serio_disconnect_driver(struct serio *serio)
{
- down(&serio->drv_sem);
+ mutex_lock(&serio->drv_mutex);
if (serio->drv)
serio->drv->disconnect(serio);
- up(&serio->drv_sem);
+ mutex_unlock(&serio->drv_mutex);
}
static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
@@ -195,6 +196,7 @@ static void serio_queue_event(void *object, struct module *owner,
if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
if (!try_module_get(owner)) {
printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type);
+ kfree(event);
goto out;
}
@@ -272,7 +274,7 @@ static void serio_handle_event(void)
struct serio_event *event;
struct serio_driver *serio_drv;
- down(&serio_sem);
+ mutex_lock(&serio_mutex);
/*
* Note that we handle only one event here to give swsusp
@@ -314,7 +316,7 @@ static void serio_handle_event(void)
serio_free_event(event);
}
- up(&serio_sem);
+ mutex_unlock(&serio_mutex);
}
/*
@@ -449,7 +451,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
struct device_driver *drv;
int retval;
- retval = down_interruptible(&serio_sem);
+ retval = mutex_lock_interruptible(&serio_mutex);
if (retval)
return retval;
@@ -469,7 +471,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
retval = -EINVAL;
}
- up(&serio_sem);
+ mutex_unlock(&serio_mutex);
return retval;
}
@@ -524,7 +526,7 @@ static void serio_init_port(struct serio *serio)
__module_get(THIS_MODULE);
spin_lock_init(&serio->lock);
- init_MUTEX(&serio->drv_sem);
+ mutex_init(&serio->drv_mutex);
device_initialize(&serio->dev);
snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id),
"serio%ld", (long)atomic_inc_return(&serio_no) - 1);
@@ -661,10 +663,10 @@ void __serio_register_port(struct serio *serio, struct module *owner)
*/
void serio_unregister_port(struct serio *serio)
{
- down(&serio_sem);
+ mutex_lock(&serio_mutex);
serio_disconnect_port(serio);
serio_destroy_port(serio);
- up(&serio_sem);
+ mutex_unlock(&serio_mutex);
}
/*
@@ -672,17 +674,17 @@ void serio_unregister_port(struct serio *serio)
*/
void serio_unregister_child_port(struct serio *serio)
{
- down(&serio_sem);
+ mutex_lock(&serio_mutex);
if (serio->child) {
serio_disconnect_port(serio->child);
serio_destroy_port(serio->child);
}
- up(&serio_sem);
+ mutex_unlock(&serio_mutex);
}
/*
* Submits register request to kseriod for subsequent execution.
- * Can be used when it is not obvious whether the serio_sem is
+ * Can be used when it is not obvious whether the serio_mutex is
* taken or not and when delayed execution is feasible.
*/
void __serio_unregister_port_delayed(struct serio *serio, struct module *owner)
@@ -765,7 +767,7 @@ void serio_unregister_driver(struct serio_driver *drv)
{
struct serio *serio;
- down(&serio_sem);
+ mutex_lock(&serio_mutex);
drv->manual_bind = 1; /* so serio_find_driver ignores it */
start_over:
@@ -779,7 +781,7 @@ start_over:
}
driver_unregister(&drv->driver);
- up(&serio_sem);
+ mutex_unlock(&serio_mutex);
}
static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
@@ -858,7 +860,7 @@ static int serio_resume(struct device *dev)
return 0;
}
-/* called from serio_driver->connect/disconnect methods under serio_sem */
+/* called from serio_driver->connect/disconnect methods under serio_mutex */
int serio_open(struct serio *serio, struct serio_driver *drv)
{
serio_set_drv(serio, drv);
@@ -870,7 +872,7 @@ int serio_open(struct serio *serio, struct serio_driver *drv)
return 0;
}
-/* called from serio_driver->connect/disconnect methods under serio_sem */
+/* called from serio_driver->connect/disconnect methods under serio_mutex */
void serio_close(struct serio *serio)
{
if (serio->close)
@@ -923,5 +925,5 @@ static void __exit serio_exit(void)
kthread_stop(serio_task);
}
-module_init(serio_init);
+subsys_initcall(serio_init);
module_exit(serio_exit);
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 47e08de18d0..5a2703b536d 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -19,6 +19,7 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/miscdevice.h>
#include <linux/wait.h>
+#include <linux/mutex.h>
#define DRIVER_DESC "Raw serio driver"
@@ -46,7 +47,7 @@ struct serio_raw_list {
struct list_head node;
};
-static DECLARE_MUTEX(serio_raw_sem);
+static DEFINE_MUTEX(serio_raw_mutex);
static LIST_HEAD(serio_raw_list);
static unsigned int serio_raw_no;
@@ -81,7 +82,7 @@ static int serio_raw_open(struct inode *inode, struct file *file)
struct serio_raw_list *list;
int retval = 0;
- retval = down_interruptible(&serio_raw_sem);
+ retval = mutex_lock_interruptible(&serio_raw_mutex);
if (retval)
return retval;
@@ -95,12 +96,11 @@ static int serio_raw_open(struct inode *inode, struct file *file)
goto out;
}
- if (!(list = kmalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) {
+ if (!(list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) {
retval = -ENOMEM;
goto out;
}
- memset(list, 0, sizeof(struct serio_raw_list));
list->serio_raw = serio_raw;
file->private_data = list;
@@ -108,7 +108,7 @@ static int serio_raw_open(struct inode *inode, struct file *file)
list_add_tail(&list->node, &serio_raw->list);
out:
- up(&serio_raw_sem);
+ mutex_unlock(&serio_raw_mutex);
return retval;
}
@@ -130,12 +130,12 @@ static int serio_raw_release(struct inode *inode, struct file *file)
struct serio_raw_list *list = file->private_data;
struct serio_raw *serio_raw = list->serio_raw;
- down(&serio_raw_sem);
+ mutex_lock(&serio_raw_mutex);
serio_raw_fasync(-1, file, 0);
serio_raw_cleanup(serio_raw);
- up(&serio_raw_sem);
+ mutex_unlock(&serio_raw_mutex);
return 0;
}
@@ -194,7 +194,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
int retval;
unsigned char c;
- retval = down_interruptible(&serio_raw_sem);
+ retval = mutex_lock_interruptible(&serio_raw_mutex);
if (retval)
return retval;
@@ -219,7 +219,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
};
out:
- up(&serio_raw_sem);
+ mutex_unlock(&serio_raw_mutex);
return written;
}
@@ -275,14 +275,13 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
struct serio_raw *serio_raw;
int err;
- if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
+ if (!(serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
return -ENOMEM;
}
- down(&serio_raw_sem);
+ mutex_lock(&serio_raw_mutex);
- memset(serio_raw, 0, sizeof(struct serio_raw));
snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
serio_raw->refcnt = 1;
serio_raw->serio = serio;
@@ -325,7 +324,7 @@ out_free:
serio_set_drvdata(serio, NULL);
kfree(serio_raw);
out:
- up(&serio_raw_sem);
+ mutex_unlock(&serio_raw_mutex);
return err;
}
@@ -350,7 +349,7 @@ static void serio_raw_disconnect(struct serio *serio)
{
struct serio_raw *serio_raw;
- down(&serio_raw_sem);
+ mutex_lock(&serio_raw_mutex);
serio_raw = serio_get_drvdata(serio);
@@ -361,7 +360,7 @@ static void serio_raw_disconnect(struct serio *serio)
if (!serio_raw_cleanup(serio_raw))
wake_up_interruptible(&serio_raw->wait);
- up(&serio_raw_sem);
+ mutex_unlock(&serio_raw_mutex);
}
static struct serio_device_id serio_raw_serio_ids[] = {
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 46d1fec2cfd..161afddd0f4 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -2,6 +2,8 @@
* ADS7846 based touchscreen and sensor driver
*
* Copyright (c) 2005 David Brownell
+ * Copyright (c) 2006 Nokia Corporation
+ * Various changes: Imre Deak <imre.deak@nokia.com>
*
* Using code from:
* - corgi_ts.c
@@ -34,17 +36,22 @@
/*
- * This code has been lightly tested on an ads7846.
+ * This code has been heavily tested on a Nokia 770, and lightly
+ * tested on other ads7846 devices (OSK/Mistral, Lubbock).
* Support for ads7843 and ads7845 has only been stubbed in.
*
- * Not yet done: investigate the values reported. Are x/y/pressure
- * event values sane enough for X11? How accurate are the temperature
- * and voltage readings? (System-specific calibration should support
- * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.)
+ * IRQ handling needs a workaround because of a shortcoming in handling
+ * edge triggered IRQs on some platforms like the OMAP1/2. These
+ * platforms don't handle the ARM lazy IRQ disabling properly, thus we
+ * have to maintain our own SW IRQ disabled status. This should be
+ * removed as soon as the affected platform's IRQ handling is fixed.
*
* app note sbaa036 talks in more detail about accurate sampling...
* that ought to help in situations like LCDs inducing noise (which
* can also be helped by using synch signals) and more generally.
+ * This driver tries to utilize the measures described in the app
+ * note. The strength of filtering can be set in the board-* specific
+ * files.
*/
#define TS_POLL_PERIOD msecs_to_jiffies(10)
@@ -61,6 +68,7 @@ struct ts_event {
__be16 x;
__be16 y;
__be16 z1, z2;
+ int ignore;
};
struct ads7846 {
@@ -71,12 +79,23 @@ struct ads7846 {
u16 model;
u16 vref_delay_usecs;
u16 x_plate_ohms;
+ u16 pressure_max;
- u8 read_x, read_y, read_z1, read_z2;
+ u8 read_x, read_y, read_z1, read_z2, pwrdown;
+ u16 dummy; /* for the pwrdown read */
struct ts_event tc;
- struct spi_transfer xfer[8];
- struct spi_message msg;
+ struct spi_transfer xfer[10];
+ struct spi_message msg[5];
+ struct spi_message *last_msg;
+ int msg_idx;
+ int read_cnt;
+ int read_rep;
+ int last_read;
+
+ u16 debounce_max;
+ u16 debounce_tol;
+ u16 debounce_rep;
spinlock_t lock;
struct timer_list timer; /* P: lock */
@@ -84,6 +103,9 @@ struct ads7846 {
unsigned pending:1; /* P: lock */
// FIXME remove "irq_disabled"
unsigned irq_disabled:1; /* P: lock */
+ unsigned disabled:1;
+
+ int (*get_pendown_state)(void);
};
/* leave chip selected when we're done, for quicker re-select? */
@@ -125,7 +147,9 @@ struct ads7846 {
#define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON)
#define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON)
#define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON)
-#define READ_X (READ_12BIT_DFR(x) | ADS_PD10_PDOWN) /* LAST */
+
+#define READ_X (READ_12BIT_DFR(x) | ADS_PD10_ADC_ON)
+#define PWRDOWN (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) /* LAST */
/* single-ended samples need to first power up reference voltage;
* we leave both ADC and VREF powered
@@ -152,6 +176,15 @@ struct ser_req {
struct spi_transfer xfer[6];
};
+static void ads7846_enable(struct ads7846 *ts);
+static void ads7846_disable(struct ads7846 *ts);
+
+static int device_suspended(struct device *dev)
+{
+ struct ads7846 *ts = dev_get_drvdata(dev);
+ return dev->power.power_state.event != PM_EVENT_ON || ts->disabled;
+}
+
static int ads7846_read12_ser(struct device *dev, unsigned command)
{
struct spi_device *spi = to_spi_device(dev);
@@ -164,7 +197,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
if (!req)
return -ENOMEM;
- INIT_LIST_HEAD(&req->msg.transfers);
+ spi_message_init(&req->msg);
/* activate reference, so it has time to settle; */
req->ref_on = REF_ON;
@@ -204,16 +237,21 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
for (i = 0; i < 6; i++)
spi_message_add_tail(&req->xfer[i], &req->msg);
+ ts->irq_disabled = 1;
disable_irq(spi->irq);
status = spi_sync(spi, &req->msg);
+ ts->irq_disabled = 0;
enable_irq(spi->irq);
if (req->msg.status)
status = req->msg.status;
+
+ /* on-wire is a must-ignore bit, a BE12 value, then padding */
sample = be16_to_cpu(req->sample);
- sample = sample >> 4;
- kfree(req);
+ sample = sample >> 3;
+ sample &= 0x0fff;
+ kfree(req);
return status ? status : sample;
}
@@ -233,6 +271,52 @@ SHOW(temp1)
SHOW(vaux)
SHOW(vbatt)
+static int is_pen_down(struct device *dev)
+{
+ struct ads7846 *ts = dev_get_drvdata(dev);
+
+ return ts->pendown;
+}
+
+static ssize_t ads7846_pen_down_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", is_pen_down(dev));
+}
+
+static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
+
+static ssize_t ads7846_disable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ads7846 *ts = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", ts->disabled);
+}
+
+static ssize_t ads7846_disable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ads7846 *ts = dev_get_drvdata(dev);
+ char *endp;
+ int i;
+
+ i = simple_strtoul(buf, &endp, 10);
+ spin_lock_irq(&ts->lock);
+
+ if (i)
+ ads7846_disable(ts);
+ else
+ ads7846_enable(ts);
+
+ spin_unlock_irq(&ts->lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
+
/*--------------------------------------------------------------------------*/
/*
@@ -252,19 +336,19 @@ static void ads7846_rx(void *ads)
u16 x, y, z1, z2;
unsigned long flags;
- /* adjust: 12 bit samples (left aligned), built from
- * two 8 bit values writen msb-first.
+ /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding;
+ * built from two 8 bit values written msb-first.
*/
- x = be16_to_cpu(ts->tc.x) >> 4;
- y = be16_to_cpu(ts->tc.y) >> 4;
- z1 = be16_to_cpu(ts->tc.z1) >> 4;
- z2 = be16_to_cpu(ts->tc.z2) >> 4;
+ x = (be16_to_cpu(ts->tc.x) >> 3) & 0x0fff;
+ y = (be16_to_cpu(ts->tc.y) >> 3) & 0x0fff;
+ z1 = (be16_to_cpu(ts->tc.z1) >> 3) & 0x0fff;
+ z2 = (be16_to_cpu(ts->tc.z2) >> 3) & 0x0fff;
/* range filtering */
if (x == MAX_12BIT)
x = 0;
- if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) {
+ if (likely(x && z1 && !device_suspended(&ts->spi->dev))) {
/* compute touch pressure resistance using equation #2 */
Rt = z2;
Rt -= z1;
@@ -275,6 +359,14 @@ static void ads7846_rx(void *ads)
} else
Rt = 0;
+ /* Sample found inconsistent by debouncing or pressure is beyond
+ * the maximum. Don't report it to user space, repeat at least
+ * once more the measurement */
+ if (ts->tc.ignore || Rt > ts->pressure_max) {
+ mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
+ return;
+ }
+
/* NOTE: "pendown" is inferred from pressure; we don't rely on
* being able to check nPENIRQ status, or "friendly" trigger modes
* (both-edges is much better than just-falling or low-level).
@@ -296,11 +388,13 @@ static void ads7846_rx(void *ads)
if (Rt) {
input_report_abs(input_dev, ABS_X, x);
input_report_abs(input_dev, ABS_Y, y);
- input_report_abs(input_dev, ABS_PRESSURE, Rt);
sync = 1;
}
- if (sync)
+
+ if (sync) {
+ input_report_abs(input_dev, ABS_PRESSURE, Rt);
input_sync(input_dev);
+ }
#ifdef VERBOSE
if (Rt || ts->pendown)
@@ -308,80 +402,137 @@ static void ads7846_rx(void *ads)
x, y, Rt, Rt ? "" : " UP");
#endif
- /* don't retrigger while we're suspended */
spin_lock_irqsave(&ts->lock, flags);
ts->pendown = (Rt != 0);
- ts->pending = 0;
+ mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
- if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) {
- if (ts->pendown)
- mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
- else if (ts->irq_disabled) {
- ts->irq_disabled = 0;
- enable_irq(ts->spi->irq);
+ spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static void ads7846_debounce(void *ads)
+{
+ struct ads7846 *ts = ads;
+ struct spi_message *m;
+ struct spi_transfer *t;
+ int val;
+ int status;
+
+ m = &ts->msg[ts->msg_idx];
+ t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
+ val = (be16_to_cpu(*(__be16 *)t->rx_buf) >> 3) & 0x0fff;
+ if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) {
+ /* Repeat it, if this was the first read or the read
+ * wasn't consistent enough. */
+ if (ts->read_cnt < ts->debounce_max) {
+ ts->last_read = val;
+ ts->read_cnt++;
+ } else {
+ /* Maximum number of debouncing reached and still
+ * not enough number of consistent readings. Abort
+ * the whole sample, repeat it in the next sampling
+ * period.
+ */
+ ts->tc.ignore = 1;
+ ts->read_cnt = 0;
+ /* Last message will contain ads7846_rx() as the
+ * completion function.
+ */
+ m = ts->last_msg;
}
+ /* Start over collecting consistent readings. */
+ ts->read_rep = 0;
+ } else {
+ if (++ts->read_rep > ts->debounce_rep) {
+ /* Got a good reading for this coordinate,
+ * go for the next one. */
+ ts->tc.ignore = 0;
+ ts->msg_idx++;
+ ts->read_cnt = 0;
+ ts->read_rep = 0;
+ m++;
+ } else
+ /* Read more values that are consistent. */
+ ts->read_cnt++;
}
-
- spin_unlock_irqrestore(&ts->lock, flags);
+ status = spi_async(ts->spi, m);
+ if (status)
+ dev_err(&ts->spi->dev, "spi_async --> %d\n",
+ status);
}
static void ads7846_timer(unsigned long handle)
{
struct ads7846 *ts = (void *)handle;
int status = 0;
- unsigned long flags;
+
+ spin_lock_irq(&ts->lock);
+
+ if (unlikely(ts->msg_idx && !ts->pendown)) {
+ /* measurement cycle ended */
+ if (!device_suspended(&ts->spi->dev)) {
+ ts->irq_disabled = 0;
+ enable_irq(ts->spi->irq);
+ }
+ ts->pending = 0;
+ ts->msg_idx = 0;
+ } else {
+ /* pen is still down, continue with the measurement */
+ ts->msg_idx = 0;
+ status = spi_async(ts->spi, &ts->msg[0]);
+ if (status)
+ dev_err(&ts->spi->dev, "spi_async --> %d\n", status);
+ }
+
+ spin_unlock_irq(&ts->lock);
+}
+
+static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
+{
+ struct ads7846 *ts = handle;
+ unsigned long flags;
spin_lock_irqsave(&ts->lock, flags);
- if (!ts->pending) {
- ts->pending = 1;
+ if (likely(ts->get_pendown_state())) {
if (!ts->irq_disabled) {
+ /* The ARM do_simple_IRQ() dispatcher doesn't act
+ * like the other dispatchers: it will report IRQs
+ * even after they've been disabled. We work around
+ * that here. (The "generic irq" framework may help...)
+ */
ts->irq_disabled = 1;
disable_irq(ts->spi->irq);
+ ts->pending = 1;
+ mod_timer(&ts->timer, jiffies);
}
- status = spi_async(ts->spi, &ts->msg);
- if (status)
- dev_err(&ts->spi->dev, "spi_async --> %d\n",
- status);
}
spin_unlock_irqrestore(&ts->lock, flags);
-}
-static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
-{
- ads7846_timer((unsigned long) handle);
return IRQ_HANDLED;
}
/*--------------------------------------------------------------------------*/
-static int
-ads7846_suspend(struct spi_device *spi, pm_message_t message)
+/* Must be called with ts->lock held */
+static void ads7846_disable(struct ads7846 *ts)
{
- struct ads7846 *ts = dev_get_drvdata(&spi->dev);
- unsigned long flags;
+ if (ts->disabled)
+ return;
- spin_lock_irqsave(&ts->lock, flags);
-
- spi->dev.power.power_state = message;
+ ts->disabled = 1;
/* are we waiting for IRQ, or polling? */
- if (!ts->pendown) {
- if (!ts->irq_disabled) {
- ts->irq_disabled = 1;
- disable_irq(ts->spi->irq);
- }
+ if (!ts->pending) {
+ ts->irq_disabled = 1;
+ disable_irq(ts->spi->irq);
} else {
- /* polling; force a final SPI completion;
- * that will clean things up neatly
+ /* the timer will run at least once more, and
+ * leave everything in a clean state, IRQ disabled
*/
- if (!ts->pending)
- mod_timer(&ts->timer, jiffies);
-
- while (ts->pendown || ts->pending) {
- spin_unlock_irqrestore(&ts->lock, flags);
- udelay(10);
- spin_lock_irqsave(&ts->lock, flags);
+ while (ts->pending) {
+ spin_unlock_irq(&ts->lock);
+ msleep(1);
+ spin_lock_irq(&ts->lock);
}
}
@@ -389,17 +540,45 @@ ads7846_suspend(struct spi_device *spi, pm_message_t message)
* leave it that way after every request
*/
- spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+/* Must be called with ts->lock held */
+static void ads7846_enable(struct ads7846 *ts)
+{
+ if (!ts->disabled)
+ return;
+
+ ts->disabled = 0;
+ ts->irq_disabled = 0;
+ enable_irq(ts->spi->irq);
+}
+
+static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
+{
+ struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+
+ spin_lock_irq(&ts->lock);
+
+ spi->dev.power.power_state = message;
+ ads7846_disable(ts);
+
+ spin_unlock_irq(&ts->lock);
+
return 0;
+
}
static int ads7846_resume(struct spi_device *spi)
{
struct ads7846 *ts = dev_get_drvdata(&spi->dev);
- ts->irq_disabled = 0;
- enable_irq(ts->spi->irq);
+ spin_lock_irq(&ts->lock);
+
spi->dev.power.power_state = PMSG_ON;
+ ads7846_enable(ts);
+
+ spin_unlock_irq(&ts->lock);
+
return 0;
}
@@ -408,6 +587,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
struct ads7846 *ts;
struct input_dev *input_dev;
struct ads7846_platform_data *pdata = spi->dev.platform_data;
+ struct spi_message *m;
struct spi_transfer *x;
int err;
@@ -428,11 +608,20 @@ static int __devinit ads7846_probe(struct spi_device *spi)
return -EINVAL;
}
- /* We'd set the wordsize to 12 bits ... except that some controllers
- * will then treat the 8 bit command words as 12 bits (and drop the
- * four MSBs of the 12 bit result). Result: inputs must be shifted
- * to discard the four garbage LSBs.
+ /* REVISIT when the irq can be triggered active-low, or if for some
+ * reason the touchscreen isn't hooked up, we don't need to access
+ * the pendown state.
*/
+ if (pdata->get_pendown_state == NULL) {
+ dev_dbg(&spi->dev, "no get_pendown_state function?\n");
+ return -EINVAL;
+ }
+
+ /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except
+ * that even if the hardware can do that, the SPI controller driver
+ * may not. So we stick to very-portable 8 bit words, both RX and TX.
+ */
+ spi->bits_per_word = 8;
ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
input_dev = input_allocate_device();
@@ -451,9 +640,21 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts->timer.data = (unsigned long) ts;
ts->timer.function = ads7846_timer;
+ spin_lock_init(&ts->lock);
+
ts->model = pdata->model ? : 7846;
ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
+ ts->pressure_max = pdata->pressure_max ? : ~0;
+ if (pdata->debounce_max) {
+ ts->debounce_max = pdata->debounce_max;
+ ts->debounce_tol = pdata->debounce_tol;
+ ts->debounce_rep = pdata->debounce_rep;
+ if (ts->debounce_rep > ts->debounce_max + 1)
+ ts->debounce_rep = ts->debounce_max - 1;
+ } else
+ ts->debounce_tol = ~0;
+ ts->get_pendown_state = pdata->get_pendown_state;
snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id);
@@ -477,64 +678,104 @@ static int __devinit ads7846_probe(struct spi_device *spi)
/* set up the transfers to read touchscreen state; this assumes we
* use formula #2 for pressure, not #3.
*/
- INIT_LIST_HEAD(&ts->msg.transfers);
+ m = &ts->msg[0];
x = ts->xfer;
+ spi_message_init(m);
+
/* y- still on; turn on only y+ (and ADC) */
ts->read_y = READ_Y;
x->tx_buf = &ts->read_y;
x->len = 1;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
x++;
x->rx_buf = &ts->tc.y;
x->len = 2;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
+
+ m->complete = ads7846_debounce;
+ m->context = ts;
+
+ m++;
+ spi_message_init(m);
+
+ /* turn y- off, x+ on, then leave in lowpower */
+ x++;
+ ts->read_x = READ_X;
+ x->tx_buf = &ts->read_x;
+ x->len = 1;
+ spi_message_add_tail(x, m);
+
+ x++;
+ x->rx_buf = &ts->tc.x;
+ x->len = 2;
+ spi_message_add_tail(x, m);
+
+ m->complete = ads7846_debounce;
+ m->context = ts;
/* turn y+ off, x- on; we'll use formula #2 */
if (ts->model == 7846) {
+ m++;
+ spi_message_init(m);
+
x++;
ts->read_z1 = READ_Z1;
x->tx_buf = &ts->read_z1;
x->len = 1;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
x++;
x->rx_buf = &ts->tc.z1;
x->len = 2;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
+
+ m->complete = ads7846_debounce;
+ m->context = ts;
+
+ m++;
+ spi_message_init(m);
x++;
ts->read_z2 = READ_Z2;
x->tx_buf = &ts->read_z2;
x->len = 1;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
x++;
x->rx_buf = &ts->tc.z2;
x->len = 2;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
+
+ m->complete = ads7846_debounce;
+ m->context = ts;
}
- /* turn y- off, x+ on, then leave in lowpower */
+ /* power down */
+ m++;
+ spi_message_init(m);
+
x++;
- ts->read_x = READ_X;
- x->tx_buf = &ts->read_x;
+ ts->pwrdown = PWRDOWN;
+ x->tx_buf = &ts->pwrdown;
x->len = 1;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
x++;
- x->rx_buf = &ts->tc.x;
+ x->rx_buf = &ts->dummy;
x->len = 2;
CS_CHANGE(*x);
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
+
+ m->complete = ads7846_rx;
+ m->context = ts;
- ts->msg.complete = ads7846_rx;
- ts->msg.context = ts;
+ ts->last_msg = m;
if (request_irq(spi->irq, ads7846_irq,
SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,
- spi->dev.bus_id, ts)) {
+ spi->dev.driver->name, ts)) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
err = -EBUSY;
goto err_free_mem;
@@ -559,13 +800,27 @@ static int __devinit ads7846_probe(struct spi_device *spi)
device_create_file(&spi->dev, &dev_attr_vbatt);
device_create_file(&spi->dev, &dev_attr_vaux);
+ device_create_file(&spi->dev, &dev_attr_pen_down);
+
+ device_create_file(&spi->dev, &dev_attr_disable);
+
err = input_register_device(input_dev);
if (err)
- goto err_free_irq;
+ goto err_remove_attr;
return 0;
- err_free_irq:
+ err_remove_attr:
+ device_remove_file(&spi->dev, &dev_attr_disable);
+ device_remove_file(&spi->dev, &dev_attr_pen_down);
+ if (ts->model == 7846) {
+ device_remove_file(&spi->dev, &dev_attr_temp1);
+ device_remove_file(&spi->dev, &dev_attr_temp0);
+ }
+ if (ts->model != 7845)
+ device_remove_file(&spi->dev, &dev_attr_vbatt);
+ device_remove_file(&spi->dev, &dev_attr_vaux);
+
free_irq(spi->irq, ts);
err_free_mem:
input_free_device(input_dev);
@@ -577,20 +832,24 @@ static int __devexit ads7846_remove(struct spi_device *spi)
{
struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+ input_unregister_device(ts->input);
+
ads7846_suspend(spi, PMSG_SUSPEND);
- free_irq(ts->spi->irq, ts);
- if (ts->irq_disabled)
- enable_irq(ts->spi->irq);
+ device_remove_file(&spi->dev, &dev_attr_disable);
+ device_remove_file(&spi->dev, &dev_attr_pen_down);
if (ts->model == 7846) {
- device_remove_file(&spi->dev, &dev_attr_temp0);
device_remove_file(&spi->dev, &dev_attr_temp1);
+ device_remove_file(&spi->dev, &dev_attr_temp0);
}
if (ts->model != 7845)
device_remove_file(&spi->dev, &dev_attr_vbatt);
device_remove_file(&spi->dev, &dev_attr_vaux);
- input_unregister_device(ts->input);
+ free_irq(ts->spi->irq, ts);
+ /* suspend left the IRQ disabled */
+ enable_irq(ts->spi->irq);
+
kfree(ts);
dev_dbg(&spi->dev, "unregistered touchscreen\n");
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 1042987856f..5013703db0e 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -17,7 +17,7 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <asm/irq.h>
+//#include <asm/irq.h>
#include <asm/arch/sharpsl.h>
#include <asm/arch/hardware.h>
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index ca1547929d6..d678d144bbf 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -157,9 +157,8 @@ static int tsdev_open(struct inode *inode, struct file *file)
if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK])
return -ENODEV;
- if (!(list = kmalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
+ if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
return -ENOMEM;
- memset(list, 0, sizeof(struct tsdev_list));
list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0;
@@ -379,9 +378,8 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
return NULL;
}
- if (!(tsdev = kmalloc(sizeof(struct tsdev), GFP_KERNEL)))
+ if (!(tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL)))
return NULL;
- memset(tsdev, 0, sizeof(struct tsdev));
INIT_LIST_HEAD(&tsdev->list);
init_waitqueue_head(&tsdev->wait);
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 623adbb0d13..173c899a1fb 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1485,6 +1485,7 @@ static int __init capi_init(void)
{
char *p;
char *compileinfo;
+ int major_ret;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strlcpy(rev, p + 2, sizeof(rev));
@@ -1493,11 +1494,11 @@ static int __init capi_init(void)
} else
strcpy(rev, "1.0");
- if (register_chrdev(capi_major, "capi20", &capi_fops)) {
+ major_ret = register_chrdev(capi_major, "capi20", &capi_fops);
+ if (major_ret < 0) {
printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
- return -EIO;
+ return major_ret;
}
-
capi_class = class_create(THIS_MODULE, "capi");
if (IS_ERR(capi_class)) {
unregister_chrdev(capi_major, "capi20");
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index 2cc8b27e4c3..ca9dc00a45c 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -233,7 +233,7 @@ static struct file_operations proc_applstats_ops = {
};
static void
-create_seq_entry(char *name, mode_t mode, struct file_operations *f)
+create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
{
struct proc_dir_entry *entry;
entry = create_proc_entry(name, mode, NULL);
diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig
index 53c4fb62ed8..5b203fe21dc 100644
--- a/drivers/isdn/gigaset/Kconfig
+++ b/drivers/isdn/gigaset/Kconfig
@@ -3,8 +3,8 @@ menu "Siemens Gigaset"
config ISDN_DRV_GIGASET
tristate "Siemens Gigaset support (isdn)"
- depends on ISDN_I4L && m
-# depends on ISDN_I4L && MODULES
+ depends on ISDN_I4L
+ select CRC_CCITT
help
Say m here if you have a Gigaset or Sinus isdn device.
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index 171f8b703d6..ce3cd77094b 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>,
* Hansjoerg Lipp <hjlipp@web.de>,
- * Stefan Eilers <Eilers.Stefan@epost.de>.
+ * Stefan Eilers.
*
* =====================================================================
* This program is free software; you can redistribute it and/or
@@ -11,10 +11,6 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: asyncdata.c,v 1.2.2.7 2005/11/13 23:05:18 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
@@ -45,7 +41,7 @@ static inline int muststuff(unsigned char c)
* number of processed bytes
*/
static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
- struct inbuf_t *inbuf)
+ struct inbuf_t *inbuf)
{
struct cardstate *cs = inbuf->cs;
unsigned cbytes = cs->cbytes;
@@ -55,10 +51,11 @@ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
for (;;) {
cs->respdata[cbytes] = c;
if (c == 10 || c == 13) {
- dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
- __func__, cbytes);
+ gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
+ __func__, cbytes);
cs->cbytes = cbytes;
- gigaset_handle_modem_response(cs); /* can change cs->dle */
+ gigaset_handle_modem_response(cs); /* can change
+ cs->dle */
cbytes = 0;
if (cs->dle &&
@@ -71,7 +68,7 @@ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
if (cbytes < MAX_RESP_SIZE - 1)
cbytes++;
else
- warn("response too large");
+ dev_warn(cs->dev, "response too large\n");
}
if (!numbytes)
@@ -96,11 +93,12 @@ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
* number of processed bytes
*/
static inline int lock_loop(unsigned char *src, int numbytes,
- struct inbuf_t *inbuf)
+ struct inbuf_t *inbuf)
{
struct cardstate *cs = inbuf->cs;
- gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src, 0);
+ gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
+ numbytes, src);
gigaset_if_receive(cs, src, numbytes);
return numbytes;
@@ -115,24 +113,18 @@ static inline int lock_loop(unsigned char *src, int numbytes,
* numbytes (all bytes processed) on error --FIXME
*/
static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
- struct inbuf_t *inbuf)
+ struct inbuf_t *inbuf)
{
struct cardstate *cs = inbuf->cs;
struct bc_state *bcs = inbuf->bcs;
- int inputstate;
- __u16 fcs;
- struct sk_buff *skb;
+ int inputstate = bcs->inputstate;
+ __u16 fcs = bcs->fcs;
+ struct sk_buff *skb = bcs->skb;
unsigned char error;
struct sk_buff *compskb;
int startbytes = numbytes;
int l;
- IFNULLRETVAL(bcs, numbytes);
- inputstate = bcs->inputstate;
- fcs = bcs->fcs;
- skb = bcs->skb;
- IFNULLRETVAL(skb, numbytes);
-
if (unlikely(inputstate & INS_byte_stuff)) {
inputstate &= ~INS_byte_stuff;
goto byte_stuff;
@@ -156,39 +148,37 @@ byte_stuff:
c ^= PPP_TRANS;
#ifdef CONFIG_GIGASET_DEBUG
if (unlikely(!muststuff(c)))
- dbg(DEBUG_HDLC,
- "byte stuffed: 0x%02x", c);
+ gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
#endif
} else if (unlikely(c == PPP_FLAG)) {
if (unlikely(inputstate & INS_skip_frame)) {
if (!(inputstate & INS_have_data)) { /* 7E 7E */
- //dbg(DEBUG_HDLC, "(7e)7e------------------------");
#ifdef CONFIG_GIGASET_DEBUG
++bcs->emptycount;
#endif
} else
- dbg(DEBUG_HDLC,
+ gig_dbg(DEBUG_HDLC,
"7e----------------------------");
/* end of frame */
error = 1;
gigaset_rcv_error(NULL, cs, bcs);
} else if (!(inputstate & INS_have_data)) { /* 7E 7E */
- //dbg(DEBUG_HDLC, "(7e)7e------------------------");
#ifdef CONFIG_GIGASET_DEBUG
++bcs->emptycount;
#endif
break;
} else {
- dbg(DEBUG_HDLC,
- "7e----------------------------");
+ gig_dbg(DEBUG_HDLC,
+ "7e----------------------------");
/* end of frame */
error = 0;
if (unlikely(fcs != PPP_GOODFCS)) {
- err("Packet checksum at %lu failed, "
- "packet is corrupted (%u bytes)!",
+ dev_err(cs->dev,
+ "Packet checksum at %lu failed, "
+ "packet is corrupted (%u bytes)!\n",
bcs->rcvbytes, skb->len);
compskb = NULL;
gigaset_rcv_error(compskb, cs, bcs);
@@ -202,9 +192,11 @@ byte_stuff:
skb = NULL;
inputstate |= INS_skip_frame;
if (l == 1) {
- err("invalid packet size (1)!");
+ dev_err(cs->dev,
+ "invalid packet size (1)!\n");
error = 1;
- gigaset_rcv_error(NULL, cs, bcs);
+ gigaset_rcv_error(NULL,
+ cs, bcs);
}
}
if (likely(!(error ||
@@ -227,7 +219,8 @@ byte_stuff:
} else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) {
skb_reserve(skb, HW_HDR_LEN);
} else {
- warn("could not allocate new skb");
+ dev_warn(cs->dev,
+ "could not allocate new skb\n");
inputstate |= INS_skip_frame;
}
@@ -235,7 +228,7 @@ byte_stuff:
#ifdef CONFIG_GIGASET_DEBUG
} else if (unlikely(muststuff(c))) {
/* Should not happen. Possible after ZDLE=1<CR><LF>. */
- dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
+ gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
#endif
}
@@ -243,8 +236,8 @@ byte_stuff:
#ifdef CONFIG_GIGASET_DEBUG
if (unlikely(!(inputstate & INS_have_data))) {
- dbg(DEBUG_HDLC,
- "7e (%d x) ================", bcs->emptycount);
+ gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
+ bcs->emptycount);
bcs->emptycount = 0;
}
#endif
@@ -253,14 +246,13 @@ byte_stuff:
if (likely(!(inputstate & INS_skip_frame))) {
if (unlikely(skb->len == SBUFSIZE)) {
- warn("received packet too long");
+ dev_warn(cs->dev, "received packet too long\n");
dev_kfree_skb_any(skb);
skb = NULL;
inputstate |= INS_skip_frame;
break;
}
- *gigaset_skb_put_quick(skb, 1) = c;
- /* *__skb_put (skb, 1) = c; */
+ *__skb_put(skb, 1) = c;
fcs = crc_ccitt_byte(fcs, c);
}
@@ -289,19 +281,14 @@ byte_stuff:
* numbytes (all bytes processed) on error --FIXME
*/
static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
- struct inbuf_t *inbuf)
+ struct inbuf_t *inbuf)
{
struct cardstate *cs = inbuf->cs;
struct bc_state *bcs = inbuf->bcs;
- int inputstate;
- struct sk_buff *skb;
+ int inputstate = bcs->inputstate;
+ struct sk_buff *skb = bcs->skb;
int startbytes = numbytes;
- IFNULLRETVAL(bcs, numbytes);
- inputstate = bcs->inputstate;
- skb = bcs->skb;
- IFNULLRETVAL(skb, numbytes);
-
for (;;) {
/* add character */
inputstate |= INS_have_data;
@@ -309,13 +296,13 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
if (likely(!(inputstate & INS_skip_frame))) {
if (unlikely(skb->len == SBUFSIZE)) {
//FIXME just pass skb up and allocate a new one
- warn("received packet too long");
+ dev_warn(cs->dev, "received packet too long\n");
dev_kfree_skb_any(skb);
skb = NULL;
inputstate |= INS_skip_frame;
break;
}
- *gigaset_skb_put_quick(skb, 1) = gigaset_invtab[c];
+ *__skb_put(skb, 1) = gigaset_invtab[c];
}
if (unlikely(!numbytes))
@@ -343,7 +330,7 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
!= NULL)) {
skb_reserve(skb, HW_HDR_LEN);
} else {
- warn("could not allocate new skb");
+ dev_warn(cs->dev, "could not allocate new skb\n");
inputstate |= INS_skip_frame;
}
}
@@ -364,13 +351,13 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
head = atomic_read(&inbuf->head);
tail = atomic_read(&inbuf->tail);
- dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
+ gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
if (head != tail) {
cs = inbuf->cs;
src = inbuf->data + head;
numbytes = (head > tail ? RBUFSIZE : tail) - head;
- dbg(DEBUG_INTR, "processing %u bytes", numbytes);
+ gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
while (numbytes) {
if (atomic_read(&cs->mstate) == MS_LOCKED) {
@@ -392,8 +379,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
if (!(inbuf->inputstate & INS_DLE_char)) {
- /* FIXME Einfach je nach Modus Funktionszeiger in cs setzen [hier+hdlc_loop]? */
- /* FIXME Spart folgendes "if" und ermoeglicht andere Protokolle */
+ /* FIXME use function pointers? */
if (inbuf->inputstate & INS_command)
procbytes = cmd_loop(c, src, numbytes, inbuf);
else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC)
@@ -403,13 +389,14 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
src += procbytes;
numbytes -= procbytes;
- } else { /* DLE-char */
+ } else { /* DLE char */
inbuf->inputstate &= ~INS_DLE_char;
switch (c) {
case 'X': /*begin of command*/
#ifdef CONFIG_GIGASET_DEBUG
if (inbuf->inputstate & INS_command)
- err("received <DLE> 'X' in command mode");
+ dev_err(cs->dev,
+ "received <DLE> 'X' in command mode\n");
#endif
inbuf->inputstate |=
INS_command | INS_DLE_command;
@@ -417,7 +404,8 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
case '.': /*end of command*/
#ifdef CONFIG_GIGASET_DEBUG
if (!(inbuf->inputstate & INS_command))
- err("received <DLE> '.' in hdlc mode");
+ dev_err(cs->dev,
+ "received <DLE> '.' in hdlc mode\n");
#endif
inbuf->inputstate &= cs->dle ?
~(INS_DLE_command|INS_command)
@@ -425,7 +413,9 @@ void gigaset_m10x_input(struct inbuf_t *inbuf)
break;
//case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
default:
- err("received 0x10 0x%02x!", (int) c);
+ dev_err(cs->dev,
+ "received 0x10 0x%02x!\n",
+ (int) c);
/* FIXME: reset driver?? */
}
}
@@ -444,7 +434,7 @@ nextbyte:
}
}
- dbg(DEBUG_INTR, "setting head to %u", head);
+ gig_dbg(DEBUG_INTR, "setting head to %u", head);
atomic_set(&inbuf->head, head);
}
}
@@ -479,14 +469,13 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
stuf_cnt++;
fcs = crc_ccitt_byte(fcs, *cp++);
}
- fcs ^= 0xffff; /* complement */
+ fcs ^= 0xffff; /* complement */
/* size of new buffer: original size + number of stuffing bytes
* + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
*/
hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head);
if (!hdlc_skb) {
- err("unable to allocate memory for HDLC encoding!");
dev_kfree_skb(skb);
return NULL;
}
@@ -508,7 +497,7 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
}
/* Finally add FCS (byte stuffed) and flag sequence */
- c = (fcs & 0x00ff); /* least significant byte first */
+ c = (fcs & 0x00ff); /* least significant byte first */
if (muststuff(c)) {
*(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
c ^= PPP_TRANS;
@@ -546,7 +535,6 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
/* worst case: every byte must be stuffed */
iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
if (!iraw_skb) {
- err("unable to allocate memory for HDLC encoding!");
dev_kfree_skb(skb);
return NULL;
}
@@ -577,21 +565,23 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
*/
int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
{
- unsigned len;
-
- IFNULLRETVAL(bcs, -EFAULT);
- IFNULLRETVAL(skb, -EFAULT);
- len = skb->len;
+ unsigned len = skb->len;
+ unsigned long flags;
if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
else
skb = iraw_encode(skb, HW_HDR_LEN, 0);
- if (!skb)
+ if (!skb) {
+ err("unable to allocate memory for encoding!\n");
return -ENOMEM;
+ }
skb_queue_tail(&bcs->squeue, skb);
- tasklet_schedule(&bcs->cs->write_tasklet);
+ spin_lock_irqsave(&bcs->cs->lock, flags);
+ if (bcs->cs->connected)
+ tasklet_schedule(&bcs->cs->write_tasklet);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return len; /* ok so far */
}
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 31f0f07832b..eb41aba3dde 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -3,9 +3,7 @@
*
* Copyright (c) 2001 by Hansjoerg Lipp <hjlipp@web.de>,
* Tilman Schmidt <tilman@imap.cc>,
- * Stefan Eilers <Eilers.Stefan@epost.de>.
- *
- * Based on usb-gigaset.c.
+ * Stefan Eilers.
*
* =====================================================================
* This program is free software; you can redistribute it and/or
@@ -13,10 +11,6 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: bas-gigaset.c,v 1.52.4.19 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
@@ -30,7 +24,7 @@
#include <linux/moduleparam.h>
/* Version Information */
-#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers"
#define DRIVER_DESC "USB Driver for Gigaset 307x"
@@ -50,19 +44,20 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
#define GIGASET_DEVFSNAME "gig/bas/"
#define GIGASET_DEVNAME "ttyGB"
-#define IF_WRITEBUF 256 //FIXME
+/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */
+#define IF_WRITEBUF 264
/* Values for the Gigaset 307x */
#define USB_GIGA_VENDOR_ID 0x0681
-#define USB_GIGA_PRODUCT_ID 0x0001
-#define USB_4175_PRODUCT_ID 0x0002
+#define USB_3070_PRODUCT_ID 0x0001
+#define USB_3075_PRODUCT_ID 0x0002
#define USB_SX303_PRODUCT_ID 0x0021
#define USB_SX353_PRODUCT_ID 0x0022
/* table of devices that work with this driver */
static struct usb_device_id gigaset_table [] = {
- { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_GIGA_PRODUCT_ID) },
- { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_4175_PRODUCT_ID) },
+ { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) },
+ { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) },
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) },
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) },
{ } /* Terminating entry */
@@ -70,9 +65,6 @@ static struct usb_device_id gigaset_table [] = {
MODULE_DEVICE_TABLE(usb, gigaset_table);
-/* Get a minor range for your devices from the usb maintainer */
-#define USB_SKEL_MINOR_BASE 200
-
/*======================= local function prototypes =============================*/
/* This function is called if a new device is connected to the USB port. It
@@ -84,29 +76,33 @@ static int gigaset_probe(struct usb_interface *interface,
/* Function will be called if the device is unplugged */
static void gigaset_disconnect(struct usb_interface *interface);
+static void read_ctrl_callback(struct urb *, struct pt_regs *);
+static void stopurbs(struct bas_bc_state *);
+static int atwrite_submit(struct cardstate *, unsigned char *, int);
+static int start_cbsend(struct cardstate *);
/*==============================================================================*/
struct bas_cardstate {
- struct usb_device *udev; /* USB device pointer */
- struct usb_interface *interface; /* interface for this device */
+ struct usb_device *udev; /* USB device pointer */
+ struct usb_interface *interface; /* interface for this device */
unsigned char minor; /* starting minor number */
- struct urb *urb_ctrl; /* control pipe default URB */
+ struct urb *urb_ctrl; /* control pipe default URB */
struct usb_ctrlrequest dr_ctrl;
struct timer_list timer_ctrl; /* control request timeout */
struct timer_list timer_atrdy; /* AT command ready timeout */
- struct urb *urb_cmd_out; /* for sending AT commands */
+ struct urb *urb_cmd_out; /* for sending AT commands */
struct usb_ctrlrequest dr_cmd_out;
int retry_cmd_out;
- struct urb *urb_cmd_in; /* for receiving AT replies */
+ struct urb *urb_cmd_in; /* for receiving AT replies */
struct usb_ctrlrequest dr_cmd_in;
struct timer_list timer_cmd_in; /* receive request timeout */
- unsigned char *rcvbuf; /* AT reply receive buffer */
+ unsigned char *rcvbuf; /* AT reply receive buffer */
- struct urb *urb_int_in; /* URB for interrupt pipe */
+ struct urb *urb_int_in; /* URB for interrupt pipe */
unsigned char int_in_buf[3];
spinlock_t lock; /* locks all following */
@@ -118,12 +114,14 @@ struct bas_cardstate {
};
/* status of direct USB connection to 307x base (bits in basstate) */
-#define BS_ATOPEN 0x001
-#define BS_B1OPEN 0x002
-#define BS_B2OPEN 0x004
-#define BS_ATREADY 0x008
-#define BS_INIT 0x010
-#define BS_ATTIMER 0x020
+#define BS_ATOPEN 0x001 /* AT channel open */
+#define BS_B1OPEN 0x002 /* B channel 1 open */
+#define BS_B2OPEN 0x004 /* B channel 2 open */
+#define BS_ATREADY 0x008 /* base ready for AT command */
+#define BS_INIT 0x010 /* base has signalled INIT_OK */
+#define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */
+#define BS_ATRDPEND 0x040 /* urb_cmd_in in use */
+#define BS_ATWRPEND 0x080 /* urb_cmd_out in use */
static struct gigaset_driver *driver = NULL;
@@ -137,6 +135,47 @@ static struct usb_driver gigaset_usb_driver = {
.id_table = gigaset_table,
};
+/* get message text for usb_submit_urb return code
+ */
+static char *get_usb_rcmsg(int rc)
+{
+ static char unkmsg[28];
+
+ switch (rc) {
+ case 0:
+ return "success";
+ case -ENOMEM:
+ return "out of memory";
+ case -ENODEV:
+ return "device not present";
+ case -ENOENT:
+ return "endpoint not present";
+ case -ENXIO:
+ return "URB type not supported";
+ case -EINVAL:
+ return "invalid argument";
+ case -EAGAIN:
+ return "start frame too early or too much scheduled";
+ case -EFBIG:
+ return "too many isochronous frames requested";
+ case -EPIPE:
+ return "endpoint stalled";
+ case -EMSGSIZE:
+ return "invalid packet size";
+ case -ENOSPC:
+ return "would overcommit USB bandwidth";
+ case -ESHUTDOWN:
+ return "device shut down";
+ case -EPERM:
+ return "reject flag set";
+ case -EHOSTUNREACH:
+ return "device suspended";
+ default:
+ snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", rc);
+ return unkmsg;
+ }
+}
+
/* get message text for USB status code
*/
static char *get_usb_statmsg(int status)
@@ -147,43 +186,37 @@ static char *get_usb_statmsg(int status)
case 0:
return "success";
case -ENOENT:
- return "canceled";
- case -ECONNRESET:
- return "canceled (async)";
+ return "unlinked (sync)";
case -EINPROGRESS:
return "pending";
case -EPROTO:
- return "bit stuffing or unknown USB error";
+ return "bit stuffing error, timeout, or unknown USB error";
case -EILSEQ:
- return "Illegal byte sequence (CRC mismatch)";
- case -EPIPE:
- return "babble detect or endpoint stalled";
- case -ENOSR:
- return "buffer error";
+ return "CRC mismatch, timeout, or unknown USB error";
case -ETIMEDOUT:
return "timed out";
- case -ENODEV:
- return "device not present";
+ case -EPIPE:
+ return "endpoint stalled";
+ case -ECOMM:
+ return "IN buffer overrun";
+ case -ENOSR:
+ return "OUT buffer underrun";
+ case -EOVERFLOW:
+ return "too much data";
case -EREMOTEIO:
return "short packet detected";
+ case -ENODEV:
+ return "device removed";
case -EXDEV:
return "partial isochronous transfer";
case -EINVAL:
return "invalid argument";
- case -ENXIO:
- return "URB already queued";
- case -EAGAIN:
- return "isochronous start frame too early or too much scheduled";
- case -EFBIG:
- return "too many isochronous frames requested";
- case -EMSGSIZE:
- return "endpoint message size zero";
+ case -ECONNRESET:
+ return "unlinked (async)";
case -ESHUTDOWN:
- return "endpoint shutdown";
- case -EBUSY:
- return "another request pending";
+ return "device shut down";
default:
- snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", status);
+ snprintf(unkmsg, sizeof(unkmsg), "unknown status %d", status);
return unkmsg;
}
}
@@ -208,53 +241,54 @@ static inline char *usb_pipetype_str(int pipe)
* write content of URB to syslog for debugging
*/
static inline void dump_urb(enum debuglevel level, const char *tag,
- struct urb *urb)
+ struct urb *urb)
{
#ifdef CONFIG_GIGASET_DEBUG
int i;
- IFNULLRET(tag);
- dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb);
+ gig_dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb);
if (urb) {
- dbg(level,
- " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, "
- "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,",
- (unsigned long) urb->dev,
- usb_pipetype_str(urb->pipe),
- usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe),
- usb_pipein(urb->pipe) ? "in" : "out",
- urb->status, (unsigned long) urb->hcpriv,
- urb->transfer_flags);
- dbg(level,
- " transfer_buffer=0x%08lx[%d], actual_length=%d, "
- "bandwidth=%d, setup_packet=0x%08lx,",
- (unsigned long) urb->transfer_buffer,
- urb->transfer_buffer_length, urb->actual_length,
- urb->bandwidth, (unsigned long) urb->setup_packet);
- dbg(level,
- " start_frame=%d, number_of_packets=%d, interval=%d, "
- "error_count=%d,",
- urb->start_frame, urb->number_of_packets, urb->interval,
- urb->error_count);
- dbg(level,
- " context=0x%08lx, complete=0x%08lx, iso_frame_desc[]={",
- (unsigned long) urb->context,
- (unsigned long) urb->complete);
+ gig_dbg(level,
+ " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, "
+ "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,",
+ (unsigned long) urb->dev,
+ usb_pipetype_str(urb->pipe),
+ usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe),
+ usb_pipein(urb->pipe) ? "in" : "out",
+ urb->status, (unsigned long) urb->hcpriv,
+ urb->transfer_flags);
+ gig_dbg(level,
+ " transfer_buffer=0x%08lx[%d], actual_length=%d, "
+ "bandwidth=%d, setup_packet=0x%08lx,",
+ (unsigned long) urb->transfer_buffer,
+ urb->transfer_buffer_length, urb->actual_length,
+ urb->bandwidth, (unsigned long) urb->setup_packet);
+ gig_dbg(level,
+ " start_frame=%d, number_of_packets=%d, interval=%d, "
+ "error_count=%d,",
+ urb->start_frame, urb->number_of_packets, urb->interval,
+ urb->error_count);
+ gig_dbg(level,
+ " context=0x%08lx, complete=0x%08lx, "
+ "iso_frame_desc[]={",
+ (unsigned long) urb->context,
+ (unsigned long) urb->complete);
for (i = 0; i < urb->number_of_packets; i++) {
- struct usb_iso_packet_descriptor *pifd = &urb->iso_frame_desc[i];
- dbg(level,
- " {offset=%u, length=%u, actual_length=%u, "
- "status=%u}",
- pifd->offset, pifd->length, pifd->actual_length,
- pifd->status);
+ struct usb_iso_packet_descriptor *pifd
+ = &urb->iso_frame_desc[i];
+ gig_dbg(level,
+ " {offset=%u, length=%u, actual_length=%u, "
+ "status=%u}",
+ pifd->offset, pifd->length, pifd->actual_length,
+ pifd->status);
}
}
- dbg(level, "}}");
+ gig_dbg(level, "}}");
#endif
}
/* read/set modem control bits etc. (m10x only) */
static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
- unsigned new_state)
+ unsigned new_state)
{
return -EINVAL;
}
@@ -280,43 +314,39 @@ static inline void error_hangup(struct bc_state *bcs)
{
struct cardstate *cs = bcs->cs;
- dbg(DEBUG_ANY,
- "%s: scheduling HUP for channel %d", __func__, bcs->channel);
+ gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d",
+ __func__, bcs->channel);
- if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) {
- //FIXME what should we do?
- return;
- }
+ if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL))
+ dev_err(cs->dev, "event queue full\n");
gigaset_schedule_event(cs);
}
/* error_reset
* reset Gigaset device because of an unrecoverable error
- * This function may be called from any context and takes care of scheduling
- * the necessary actions for execution outside of interrupt context.
+ * This function may be called from any context, and should take care of
+ * scheduling the necessary actions for execution outside of interrupt context.
+ * Right now, it just generates a kernel message calling for help.
* argument:
* controller state structure
*/
static inline void error_reset(struct cardstate *cs)
{
//FIXME try to recover without bothering the user
- err("unrecoverable error - please disconnect the Gigaset base to reset");
+ dev_err(cs->dev,
+ "unrecoverable error - please disconnect Gigaset base to reset\n");
}
/* check_pending
* check for completion of pending control request
* parameter:
- * urb USB request block of completed request
- * urb->context = hardware specific controller state structure
+ * ucs hardware specific controller state structure
*/
static void check_pending(struct bas_cardstate *ucs)
{
unsigned long flags;
- IFNULLRET(ucs);
- IFNULLRET(cardstate);
-
spin_lock_irqsave(&ucs->lock, flags);
switch (ucs->pending) {
case 0:
@@ -336,8 +366,6 @@ static void check_pending(struct bas_cardstate *ucs)
case HD_CLOSE_ATCHANNEL:
if (!(atomic_read(&ucs->basstate) & BS_ATOPEN))
ucs->pending = 0;
- //wake_up_interruptible(cs->initwait);
- //FIXME need own wait queue?
break;
case HD_CLOSE_B1CHANNEL:
if (!(atomic_read(&ucs->basstate) & BS_B1OPEN))
@@ -354,7 +382,9 @@ static void check_pending(struct bas_cardstate *ucs)
* are handled separately and should never end up here
*/
default:
- warn("unknown pending request 0x%02x cleared", ucs->pending);
+ dev_warn(&ucs->interface->dev,
+ "unknown pending request 0x%02x cleared\n",
+ ucs->pending);
ucs->pending = 0;
}
@@ -372,58 +402,53 @@ static void check_pending(struct bas_cardstate *ucs)
static void cmd_in_timeout(unsigned long data)
{
struct cardstate *cs = (struct cardstate *) data;
- struct bas_cardstate *ucs;
- unsigned long flags;
-
- IFNULLRET(cs);
- ucs = cs->hw.bas;
- IFNULLRET(ucs);
+ struct bas_cardstate *ucs = cs->hw.bas;
- spin_lock_irqsave(&cs->lock, flags);
- if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_USBREQ, "%s: disconnected", __func__);
- spin_unlock_irqrestore(&cs->lock, flags);
- return;
- }
if (!ucs->rcvbuf_size) {
- dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__);
- spin_unlock_irqrestore(&cs->lock, flags);
+ gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__);
return;
}
- spin_unlock_irqrestore(&cs->lock, flags);
- err("timeout reading AT response");
+ dev_err(cs->dev, "timeout reading AT response\n");
error_reset(cs); //FIXME retry?
}
+/* set/clear bits in base connection state, return previous state
+ */
+inline static int update_basstate(struct bas_cardstate *ucs,
+ int set, int clear)
+{
+ unsigned long flags;
+ int state;
-static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs);
+ spin_lock_irqsave(&ucs->lock, flags);
+ state = atomic_read(&ucs->basstate);
+ atomic_set(&ucs->basstate, (state & ~clear) | set);
+ spin_unlock_irqrestore(&ucs->lock, flags);
+ return state;
+}
/* atread_submit
- * submit an HD_READ_ATMESSAGE command URB
+ * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout
* parameters:
* cs controller state structure
* timeout timeout in 1/10 sec., 0: none
* return value:
* 0 on success
- * -EINVAL if a NULL pointer is encountered somewhere
* -EBUSY if another request is pending
* any URB submission error code
*/
static int atread_submit(struct cardstate *cs, int timeout)
{
- struct bas_cardstate *ucs;
+ struct bas_cardstate *ucs = cs->hw.bas;
int ret;
- IFNULLRETVAL(cs, -EINVAL);
- ucs = cs->hw.bas;
- IFNULLRETVAL(ucs, -EINVAL);
- IFNULLRETVAL(ucs->urb_cmd_in, -EINVAL);
+ gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)",
+ ucs->rcvbuf_size);
- dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", ucs->rcvbuf_size);
-
- if (ucs->urb_cmd_in->status == -EINPROGRESS) {
- err("could not submit HD_READ_ATMESSAGE: URB busy");
+ if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) {
+ dev_err(cs->dev,
+ "could not submit HD_READ_ATMESSAGE: URB busy\n");
return -EBUSY;
}
@@ -433,19 +458,20 @@ static int atread_submit(struct cardstate *cs, int timeout)
ucs->dr_cmd_in.wIndex = 0;
ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size);
usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev,
- usb_rcvctrlpipe(ucs->udev, 0),
- (unsigned char*) & ucs->dr_cmd_in,
- ucs->rcvbuf, ucs->rcvbuf_size,
- read_ctrl_callback, cs->inbuf);
+ usb_rcvctrlpipe(ucs->udev, 0),
+ (unsigned char*) & ucs->dr_cmd_in,
+ ucs->rcvbuf, ucs->rcvbuf_size,
+ read_ctrl_callback, cs->inbuf);
if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) {
- err("could not submit HD_READ_ATMESSAGE: %s",
- get_usb_statmsg(ret));
+ update_basstate(ucs, 0, BS_ATRDPEND);
+ dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n",
+ get_usb_statmsg(ret));
return ret;
}
if (timeout > 0) {
- dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
+ gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
ucs->timer_cmd_in.expires = jiffies + timeout * HZ / 10;
ucs->timer_cmd_in.data = (unsigned long) cs;
ucs->timer_cmd_in.function = cmd_in_timeout;
@@ -454,26 +480,6 @@ static int atread_submit(struct cardstate *cs, int timeout)
return 0;
}
-static void stopurbs(struct bas_bc_state *);
-static int start_cbsend(struct cardstate *);
-
-/* set/clear bits in base connection state
- */
-inline static void update_basstate(struct bas_cardstate *ucs,
- int set, int clear)
-{
- unsigned long flags;
- int state;
-
- spin_lock_irqsave(&ucs->lock, flags);
- state = atomic_read(&ucs->basstate);
- state &= ~clear;
- state |= set;
- atomic_set(&ucs->basstate, state);
- spin_unlock_irqrestore(&ucs->lock, flags);
-}
-
-
/* read_int_callback
* USB completion handler for interrupt pipe input
* called by the USB subsystem in interrupt context
@@ -483,48 +489,49 @@ inline static void update_basstate(struct bas_cardstate *ucs,
*/
static void read_int_callback(struct urb *urb, struct pt_regs *regs)
{
- struct cardstate *cs;
- struct bas_cardstate *ucs;
+ struct cardstate *cs = urb->context;
+ struct bas_cardstate *ucs = cs->hw.bas;
struct bc_state *bcs;
unsigned long flags;
- int status;
+ int rc;
unsigned l;
int channel;
- IFNULLRET(urb);
- cs = (struct cardstate *) urb->context;
- IFNULLRET(cs);
- ucs = cs->hw.bas;
- IFNULLRET(ucs);
-
- if (unlikely(!atomic_read(&cs->connected))) {
- warn("%s: disconnected", __func__);
- return;
- }
-
switch (urb->status) {
case 0: /* success */
break;
- case -ENOENT: /* canceled */
- case -ECONNRESET: /* canceled (async) */
+ case -ENOENT: /* cancelled */
+ case -ECONNRESET: /* cancelled (async) */
case -EINPROGRESS: /* pending */
/* ignore silently */
- dbg(DEBUG_USBREQ,
- "%s: %s", __func__, get_usb_statmsg(urb->status));
+ gig_dbg(DEBUG_USBREQ, "%s: %s",
+ __func__, get_usb_statmsg(urb->status));
+ return;
+ case -ENODEV: /* device removed */
+ case -ESHUTDOWN: /* device shut down */
+ //FIXME use this as disconnect indicator?
+ gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__);
return;
default: /* severe trouble */
- warn("interrupt read: %s", get_usb_statmsg(urb->status));
+ dev_warn(cs->dev, "interrupt read: %s\n",
+ get_usb_statmsg(urb->status));
//FIXME corrective action? resubmission always ok?
goto resubmit;
}
+ /* drop incomplete packets even if the missing bytes wouldn't matter */
+ if (unlikely(urb->actual_length < 3)) {
+ dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n",
+ urb->actual_length);
+ goto resubmit;
+ }
+
l = (unsigned) ucs->int_in_buf[1] +
(((unsigned) ucs->int_in_buf[2]) << 8);
- dbg(DEBUG_USBREQ,
- "<-------%d: 0x%02x (%u [0x%02x 0x%02x])", urb->actual_length,
- (int)ucs->int_in_buf[0], l,
- (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]);
+ gig_dbg(DEBUG_USBREQ, "<-------%d: 0x%02x (%u [0x%02x 0x%02x])",
+ urb->actual_length, (int)ucs->int_in_buf[0], l,
+ (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]);
channel = 0;
@@ -570,62 +577,68 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs)
case HD_B1_FLOW_CONTROL:
bcs = cs->bcs + channel;
atomic_add((l - BAS_NORMFRAME) * BAS_CORRFRAMES,
- &bcs->hw.bas->corrbytes);
- dbg(DEBUG_ISO,
- "Flow control (channel %d, sub %d): 0x%02x => %d",
- channel, bcs->hw.bas->numsub, l,
- atomic_read(&bcs->hw.bas->corrbytes));
+ &bcs->hw.bas->corrbytes);
+ gig_dbg(DEBUG_ISO,
+ "Flow control (channel %d, sub %d): 0x%02x => %d",
+ channel, bcs->hw.bas->numsub, l,
+ atomic_read(&bcs->hw.bas->corrbytes));
break;
case HD_RECEIVEATDATA_ACK: /* AT response ready to be received */
if (!l) {
- warn("HD_RECEIVEATDATA_ACK with length 0 ignored");
+ dev_warn(cs->dev,
+ "HD_RECEIVEATDATA_ACK with length 0 ignored\n");
break;
}
spin_lock_irqsave(&cs->lock, flags);
if (ucs->rcvbuf_size) {
- spin_unlock_irqrestore(&cs->lock, flags);
- err("receive AT data overrun, %d bytes lost", l);
- error_reset(cs); //FIXME reschedule
- break;
+ /* throw away previous buffer - we have no queue */
+ dev_err(cs->dev,
+ "receive AT data overrun, %d bytes lost\n",
+ ucs->rcvbuf_size);
+ kfree(ucs->rcvbuf);
+ ucs->rcvbuf_size = 0;
}
if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) {
spin_unlock_irqrestore(&cs->lock, flags);
- err("%s: out of memory, %d bytes lost", __func__, l);
- error_reset(cs); //FIXME reschedule
+ dev_err(cs->dev, "out of memory receiving AT data\n");
+ error_reset(cs);
break;
}
ucs->rcvbuf_size = l;
ucs->retry_cmd_in = 0;
- if ((status = atread_submit(cs, BAS_TIMEOUT)) < 0) {
+ if ((rc = atread_submit(cs, BAS_TIMEOUT)) < 0) {
kfree(ucs->rcvbuf);
ucs->rcvbuf = NULL;
ucs->rcvbuf_size = 0;
- error_reset(cs); //FIXME reschedule
+ if (rc != -ENODEV)
+ //FIXME corrective action?
+ error_reset(cs);
}
spin_unlock_irqrestore(&cs->lock, flags);
break;
case HD_RESET_INTERRUPT_PIPE_ACK:
- dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK");
+ gig_dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK");
break;
case HD_SUSPEND_END:
- dbg(DEBUG_USBREQ, "HD_SUSPEND_END");
+ gig_dbg(DEBUG_USBREQ, "HD_SUSPEND_END");
break;
default:
- warn("unknown Gigaset signal 0x%02x (%u) ignored",
- (int) ucs->int_in_buf[0], l);
+ dev_warn(cs->dev,
+ "unknown Gigaset signal 0x%02x (%u) ignored\n",
+ (int) ucs->int_in_buf[0], l);
}
check_pending(ucs);
resubmit:
- status = usb_submit_urb(urb, SLAB_ATOMIC);
- if (unlikely(status)) {
- err("could not resubmit interrupt URB: %s",
- get_usb_statmsg(status));
+ rc = usb_submit_urb(urb, SLAB_ATOMIC);
+ if (unlikely(rc != 0 && rc != -ENODEV)) {
+ dev_err(cs->dev, "could not resubmit interrupt URB: %s\n",
+ get_usb_rcmsg(rc));
error_reset(cs);
}
}
@@ -639,31 +652,17 @@ resubmit:
*/
static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
{
- struct cardstate *cs;
- struct bas_cardstate *ucs;
- unsigned numbytes;
- unsigned long flags;
- struct inbuf_t *inbuf;
+ struct inbuf_t *inbuf = urb->context;
+ struct cardstate *cs = inbuf->cs;
+ struct bas_cardstate *ucs = cs->hw.bas;
int have_data = 0;
+ unsigned numbytes;
+ int rc;
- IFNULLRET(urb);
- inbuf = (struct inbuf_t *) urb->context;
- IFNULLRET(inbuf);
- cs = inbuf->cs;
- IFNULLRET(cs);
- ucs = cs->hw.bas;
- IFNULLRET(ucs);
-
- spin_lock_irqsave(&cs->lock, flags);
- if (!atomic_read(&cs->connected)) {
- warn("%s: disconnected", __func__);
- spin_unlock_irqrestore(&cs->lock, flags);
- return;
- }
+ update_basstate(ucs, 0, BS_ATRDPEND);
if (!ucs->rcvbuf_size) {
- warn("%s: no receive in progress", __func__);
- spin_unlock_irqrestore(&cs->lock, flags);
+ dev_warn(cs->dev, "%s: no receive in progress\n", __func__);
return;
}
@@ -673,12 +672,14 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
case 0: /* normal completion */
numbytes = urb->actual_length;
if (unlikely(numbytes == 0)) {
- warn("control read: empty block received");
+ dev_warn(cs->dev,
+ "control read: empty block received\n");
goto retry;
}
if (unlikely(numbytes != ucs->rcvbuf_size)) {
- warn("control read: received %d chars, expected %d",
- numbytes, ucs->rcvbuf_size);
+ dev_warn(cs->dev,
+ "control read: received %d chars, expected %d\n",
+ numbytes, ucs->rcvbuf_size);
if (numbytes > ucs->rcvbuf_size)
numbytes = ucs->rcvbuf_size;
}
@@ -694,27 +695,32 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
}
break;
- case -ENOENT: /* canceled */
- case -ECONNRESET: /* canceled (async) */
+ case -ENOENT: /* cancelled */
+ case -ECONNRESET: /* cancelled (async) */
case -EINPROGRESS: /* pending */
+ case -ENODEV: /* device removed */
+ case -ESHUTDOWN: /* device shut down */
/* no action necessary */
- dbg(DEBUG_USBREQ,
- "%s: %s", __func__, get_usb_statmsg(urb->status));
+ gig_dbg(DEBUG_USBREQ, "%s: %s",
+ __func__, get_usb_statmsg(urb->status));
break;
default: /* severe trouble */
- warn("control read: %s", get_usb_statmsg(urb->status));
+ dev_warn(cs->dev, "control read: %s\n",
+ get_usb_statmsg(urb->status));
retry:
if (ucs->retry_cmd_in++ < BAS_RETRY) {
- notice("control read: retry %d", ucs->retry_cmd_in);
- if (atread_submit(cs, BAS_TIMEOUT) >= 0) {
- /* resubmitted - bypass regular exit block */
- spin_unlock_irqrestore(&cs->lock, flags);
+ dev_notice(cs->dev, "control read: retry %d\n",
+ ucs->retry_cmd_in);
+ rc = atread_submit(cs, BAS_TIMEOUT);
+ if (rc >= 0 || rc == -ENODEV)
+ /* resubmitted or disconnected */
+ /* - bypass regular exit block */
return;
- }
} else {
- err("control read: giving up after %d tries",
- ucs->retry_cmd_in);
+ dev_err(cs->dev,
+ "control read: giving up after %d tries\n",
+ ucs->retry_cmd_in);
}
error_reset(cs);
}
@@ -722,9 +728,8 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
kfree(ucs->rcvbuf);
ucs->rcvbuf = NULL;
ucs->rcvbuf_size = 0;
- spin_unlock_irqrestore(&cs->lock, flags);
if (have_data) {
- dbg(DEBUG_INTR, "%s-->BH", __func__);
+ gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
gigaset_schedule_event(cs);
}
}
@@ -743,21 +748,19 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs)
unsigned long flags;
int i, rc;
- IFNULLRET(urb);
- IFNULLRET(urb->context);
- IFNULLRET(cardstate);
-
/* status codes not worth bothering the tasklet with */
- if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
- urb->status == -EINPROGRESS)) {
- dbg(DEBUG_ISO,
- "%s: %s", __func__, get_usb_statmsg(urb->status));
+ if (unlikely(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -EINPROGRESS ||
+ urb->status == -ENODEV ||
+ urb->status == -ESHUTDOWN)) {
+ gig_dbg(DEBUG_ISO, "%s: %s",
+ __func__, get_usb_statmsg(urb->status));
return;
}
- bcs = (struct bc_state *) urb->context;
+ bcs = urb->context;
ubc = bcs->hw.bas;
- IFNULLRET(ubc);
spin_lock_irqsave(&ubc->isoinlock, flags);
if (likely(ubc->isoindone == NULL)) {
@@ -770,21 +773,24 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs)
for (i = 0; i < BAS_NUMFRAMES; i++) {
ubc->isoinlost += urb->iso_frame_desc[i].actual_length;
if (unlikely(urb->iso_frame_desc[i].status != 0 &&
- urb->iso_frame_desc[i].status != -EINPROGRESS)) {
+ urb->iso_frame_desc[i].status !=
+ -EINPROGRESS))
ubc->loststatus = urb->iso_frame_desc[i].status;
- }
urb->iso_frame_desc[i].status = 0;
urb->iso_frame_desc[i].actual_length = 0;
}
if (likely(atomic_read(&ubc->running))) {
- urb->dev = bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */
+ /* urb->dev is clobbered by USB subsystem */
+ urb->dev = bcs->cs->hw.bas->udev;
urb->transfer_flags = URB_ISO_ASAP;
urb->number_of_packets = BAS_NUMFRAMES;
- dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", __func__);
+ gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit",
+ __func__);
rc = usb_submit_urb(urb, SLAB_ATOMIC);
- if (unlikely(rc != 0)) {
- err("could not resubmit isochronous read URB: %s",
- get_usb_statmsg(rc));
+ if (unlikely(rc != 0 && rc != -ENODEV)) {
+ dev_err(bcs->cs->dev,
+ "could not resubmit isochronous read "
+ "URB: %s\n", get_usb_rcmsg(rc));
dump_urb(DEBUG_ISO, "isoc read", urb);
error_hangup(bcs);
}
@@ -806,23 +812,20 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs)
struct bas_bc_state *ubc;
unsigned long flags;
- IFNULLRET(urb);
- IFNULLRET(urb->context);
- IFNULLRET(cardstate);
-
/* status codes not worth bothering the tasklet with */
- if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
- urb->status == -EINPROGRESS)) {
- dbg(DEBUG_ISO,
- "%s: %s", __func__, get_usb_statmsg(urb->status));
+ if (unlikely(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -EINPROGRESS ||
+ urb->status == -ENODEV ||
+ urb->status == -ESHUTDOWN)) {
+ gig_dbg(DEBUG_ISO, "%s: %s",
+ __func__, get_usb_statmsg(urb->status));
return;
}
/* pass URB context to tasklet */
- ucx = (struct isow_urbctx_t *) urb->context;
- IFNULLRET(ucx->bcs);
+ ucx = urb->context;
ubc = ucx->bcs->hw.bas;
- IFNULLRET(ubc);
spin_lock_irqsave(&ubc->isooutlock, flags);
ubc->isooutovfl = ubc->isooutdone;
@@ -841,15 +844,11 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs)
*/
static int starturbs(struct bc_state *bcs)
{
+ struct bas_bc_state *ubc = bcs->hw.bas;
struct urb *urb;
- struct bas_bc_state *ubc;
int j, k;
int rc;
- IFNULLRETVAL(bcs, -EFAULT);
- ubc = bcs->hw.bas;
- IFNULLRETVAL(ubc, -EFAULT);
-
/* initialize L2 reception */
if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
bcs->inputstate |= INS_flag_hunt;
@@ -859,7 +858,6 @@ static int starturbs(struct bc_state *bcs)
for (k = 0; k < BAS_INURBS; k++) {
urb = ubc->isoinurbs[k];
if (!urb) {
- err("isoinurbs[%d]==NULL", k);
rc = -EFAULT;
goto error;
}
@@ -881,11 +879,8 @@ static int starturbs(struct bc_state *bcs)
}
dump_urb(DEBUG_ISO, "Initial isoc read", urb);
- if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
- err("could not submit isochronous read URB %d: %s",
- k, get_usb_statmsg(rc));
+ if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0)
goto error;
- }
}
/* initialize L2 transmission */
@@ -895,7 +890,6 @@ static int starturbs(struct bc_state *bcs)
for (k = 0; k < BAS_OUTURBS; ++k) {
urb = ubc->isoouturbs[k].urb;
if (!urb) {
- err("isoouturbs[%d].urb==NULL", k);
rc = -EFAULT;
goto error;
}
@@ -921,11 +915,8 @@ static int starturbs(struct bc_state *bcs)
for (k = 0; k < 2; ++k) {
dump_urb(DEBUG_ISO, "Initial isoc write", urb);
rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC);
- if (rc != 0) {
- err("could not submit isochronous write URB %d: %s",
- k, get_usb_statmsg(rc));
+ if (rc != 0)
goto error;
- }
}
dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb);
ubc->isooutfree = &ubc->isoouturbs[2];
@@ -946,20 +937,20 @@ static void stopurbs(struct bas_bc_state *ubc)
{
int k, rc;
- IFNULLRET(ubc);
-
atomic_set(&ubc->running, 0);
for (k = 0; k < BAS_INURBS; ++k) {
rc = usb_unlink_urb(ubc->isoinurbs[k]);
- dbg(DEBUG_ISO, "%s: isoc input URB %d unlinked, result = %d",
- __func__, k, rc);
+ gig_dbg(DEBUG_ISO,
+ "%s: isoc input URB %d unlinked, result = %s",
+ __func__, k, get_usb_rcmsg(rc));
}
for (k = 0; k < BAS_OUTURBS; ++k) {
rc = usb_unlink_urb(ubc->isoouturbs[k].urb);
- dbg(DEBUG_ISO, "%s: isoc output URB %d unlinked, result = %d",
- __func__, k, rc);
+ gig_dbg(DEBUG_ISO,
+ "%s: isoc output URB %d unlinked, result = %s",
+ __func__, k, get_usb_rcmsg(rc));
}
}
@@ -969,7 +960,7 @@ static void stopurbs(struct bas_bc_state *ubc)
/* submit_iso_write_urb
* fill and submit the next isochronous write URB
* parameters:
- * bcs B channel state structure
+ * ucx context structure containing URB
* return value:
* number of frames submitted in URB
* 0 if URB not submitted because no data available (isooutbuf busy)
@@ -977,19 +968,13 @@ static void stopurbs(struct bas_bc_state *ubc)
*/
static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
{
- struct urb *urb;
- struct bas_bc_state *ubc;
+ struct urb *urb = ucx->urb;
+ struct bas_bc_state *ubc = ucx->bcs->hw.bas;
struct usb_iso_packet_descriptor *ifd;
int corrbytes, nframe, rc;
- IFNULLRETVAL(ucx, -EFAULT);
- urb = ucx->urb;
- IFNULLRETVAL(urb, -EFAULT);
- IFNULLRETVAL(ucx->bcs, -EFAULT);
- ubc = ucx->bcs->hw.bas;
- IFNULLRETVAL(ubc, -EFAULT);
-
- urb->dev = ucx->bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */
+ /* urb->dev is clobbered by USB subsystem */
+ urb->dev = ucx->bcs->cs->hw.bas->udev;
urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = ubc->isooutbuf->data;
urb->transfer_buffer_length = sizeof(ubc->isooutbuf->data);
@@ -1000,7 +985,8 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
/* compute frame length according to flow control */
ifd->length = BAS_NORMFRAME;
if ((corrbytes = atomic_read(&ubc->corrbytes)) != 0) {
- dbg(DEBUG_ISO, "%s: corrbytes=%d", __func__, corrbytes);
+ gig_dbg(DEBUG_ISO, "%s: corrbytes=%d",
+ __func__, corrbytes);
if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME)
corrbytes = BAS_HIGHFRAME - BAS_NORMFRAME;
else if (corrbytes < BAS_LOWFRAME - BAS_NORMFRAME)
@@ -1008,18 +994,21 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
ifd->length += corrbytes;
atomic_add(-corrbytes, &ubc->corrbytes);
}
- //dbg(DEBUG_ISO, "%s: frame %d length=%d", __func__, nframe, ifd->length);
/* retrieve block of data to send */
- ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf, ifd->length);
+ ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf,
+ ifd->length);
if (ifd->offset < 0) {
if (ifd->offset == -EBUSY) {
- dbg(DEBUG_ISO, "%s: buffer busy at frame %d",
- __func__, nframe);
- /* tasklet will be restarted from gigaset_send_skb() */
+ gig_dbg(DEBUG_ISO,
+ "%s: buffer busy at frame %d",
+ __func__, nframe);
+ /* tasklet will be restarted from
+ gigaset_send_skb() */
} else {
- err("%s: buffer error %d at frame %d",
- __func__, ifd->offset, nframe);
+ dev_err(ucx->bcs->cs->dev,
+ "%s: buffer error %d at frame %d\n",
+ __func__, ifd->offset, nframe);
return ifd->offset;
}
break;
@@ -1028,15 +1017,22 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
ifd->status = 0;
ifd->actual_length = 0;
}
- if ((urb->number_of_packets = nframe) > 0) {
- if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
- err("could not submit isochronous write URB: %s",
- get_usb_statmsg(rc));
- dump_urb(DEBUG_ISO, "isoc write", urb);
- return rc;
- }
- ++ubc->numsub;
+ if (unlikely(nframe == 0))
+ return 0; /* no data to send */
+ urb->number_of_packets = nframe;
+
+ rc = usb_submit_urb(urb, SLAB_ATOMIC);
+ if (unlikely(rc)) {
+ if (rc == -ENODEV)
+ /* device removed - give up silently */
+ gig_dbg(DEBUG_ISO, "%s: disconnected", __func__);
+ else
+ dev_err(ucx->bcs->cs->dev,
+ "could not submit isochronous write URB: %s\n",
+ get_usb_rcmsg(rc));
+ return rc;
}
+ ++ubc->numsub;
return nframe;
}
@@ -1048,9 +1044,9 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
*/
static void write_iso_tasklet(unsigned long data)
{
- struct bc_state *bcs;
- struct bas_bc_state *ubc;
- struct cardstate *cs;
+ struct bc_state *bcs = (struct bc_state *) data;
+ struct bas_bc_state *ubc = bcs->hw.bas;
+ struct cardstate *cs = bcs->cs;
struct isow_urbctx_t *done, *next, *ovfl;
struct urb *urb;
struct usb_iso_packet_descriptor *ifd;
@@ -1059,23 +1055,12 @@ static void write_iso_tasklet(unsigned long data)
int i;
struct sk_buff *skb;
int len;
-
- bcs = (struct bc_state *) data;
- IFNULLRET(bcs);
- ubc = bcs->hw.bas;
- IFNULLRET(ubc);
- cs = bcs->cs;
- IFNULLRET(cs);
+ int rc;
/* loop while completed URBs arrive in time */
for (;;) {
- if (unlikely(!atomic_read(&cs->connected))) {
- warn("%s: disconnected", __func__);
- return;
- }
-
if (unlikely(!(atomic_read(&ubc->running)))) {
- dbg(DEBUG_ISO, "%s: not running", __func__);
+ gig_dbg(DEBUG_ISO, "%s: not running", __func__);
return;
}
@@ -1087,7 +1072,7 @@ static void write_iso_tasklet(unsigned long data)
ubc->isooutovfl = NULL;
spin_unlock_irqrestore(&ubc->isooutlock, flags);
if (ovfl) {
- err("isochronous write buffer underrun - buy a faster machine :-)");
+ dev_err(cs->dev, "isochronous write buffer underrun\n");
error_hangup(bcs);
break;
}
@@ -1100,7 +1085,8 @@ static void write_iso_tasklet(unsigned long data)
ubc->isooutfree = NULL;
spin_unlock_irqrestore(&ubc->isooutlock, flags);
if (next) {
- if (submit_iso_write_urb(next) <= 0) {
+ rc = submit_iso_write_urb(next);
+ if (unlikely(rc <= 0 && rc != -ENODEV)) {
/* could not submit URB, put it back */
spin_lock_irqsave(&ubc->isooutlock, flags);
if (ubc->isooutfree == NULL) {
@@ -1110,7 +1096,8 @@ static void write_iso_tasklet(unsigned long data)
spin_unlock_irqrestore(&ubc->isooutlock, flags);
if (next) {
/* couldn't put it back */
- err("losing isochronous write URB");
+ dev_err(cs->dev,
+ "losing isochronous write URB\n");
error_hangup(bcs);
}
}
@@ -1119,26 +1106,30 @@ static void write_iso_tasklet(unsigned long data)
/* process completed URB */
urb = done->urb;
switch (urb->status) {
+ case -EXDEV: /* partial completion */
+ gig_dbg(DEBUG_ISO, "%s: URB partially completed",
+ __func__);
+ /* fall through - what's the difference anyway? */
case 0: /* normal completion */
- break;
- case -EXDEV: /* inspect individual frames */
- /* assumptions (for lack of documentation):
- * - actual_length bytes of the frame in error are successfully sent
+ /* inspect individual frames
+ * assumptions (for lack of documentation):
+ * - actual_length bytes of first frame in error are
+ * successfully sent
* - all following frames are not sent at all
*/
- dbg(DEBUG_ISO, "%s: URB partially completed", __func__);
- offset = done->limit; /* just in case */
+ offset = done->limit; /* default (no error) */
for (i = 0; i < BAS_NUMFRAMES; i++) {
ifd = &urb->iso_frame_desc[i];
if (ifd->status ||
ifd->actual_length != ifd->length) {
- warn("isochronous write: frame %d: %s, "
- "only %d of %d bytes sent",
+ dev_warn(cs->dev,
+ "isochronous write: frame %d: %s, "
+ "only %d of %d bytes sent\n",
i, get_usb_statmsg(ifd->status),
ifd->actual_length, ifd->length);
offset = (ifd->offset +
- ifd->actual_length)
- % BAS_OUTBUFSIZE;
+ ifd->actual_length)
+ % BAS_OUTBUFSIZE;
break;
}
}
@@ -1148,25 +1139,26 @@ static void write_iso_tasklet(unsigned long data)
ifd = &urb->iso_frame_desc[i];
if (ifd->status != -EINPROGRESS
|| ifd->actual_length != 0) {
- warn("isochronous write: frame %d: %s, "
- "%d of %d bytes sent",
+ dev_warn(cs->dev,
+ "isochronous write: frame %d: %s, "
+ "%d of %d bytes sent\n",
i, get_usb_statmsg(ifd->status),
ifd->actual_length, ifd->length);
offset = (ifd->offset +
- ifd->actual_length)
- % BAS_OUTBUFSIZE;
+ ifd->actual_length)
+ % BAS_OUTBUFSIZE;
break;
}
}
#endif
break;
- case -EPIPE: //FIXME is this the code for "underrun"?
- err("isochronous write stalled");
+ case -EPIPE: /* stall - probably underrun */
+ dev_err(cs->dev, "isochronous write stalled\n");
error_hangup(bcs);
break;
default: /* severe trouble */
- warn("isochronous write: %s",
- get_usb_statmsg(urb->status));
+ dev_warn(cs->dev, "isochronous write: %s\n",
+ get_usb_statmsg(urb->status));
}
/* mark the write buffer area covered by this URB as free */
@@ -1180,7 +1172,8 @@ static void write_iso_tasklet(unsigned long data)
spin_unlock_irqrestore(&ubc->isooutlock, flags);
if (next) {
/* only one URB still active - resubmit one */
- if (submit_iso_write_urb(next) <= 0) {
+ rc = submit_iso_write_urb(next);
+ if (unlikely(rc <= 0 && rc != -ENODEV)) {
/* couldn't submit */
error_hangup(bcs);
}
@@ -1194,8 +1187,8 @@ static void write_iso_tasklet(unsigned long data)
if (gigaset_isoc_buildframe(bcs, skb->data, len) == -EAGAIN) {
/* insufficient buffer space, push back onto queue */
skb_queue_head(&bcs->squeue, skb);
- dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d",
- __func__, skb_queue_len(&bcs->squeue));
+ gig_dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d",
+ __func__, skb_queue_len(&bcs->squeue));
break;
}
skb_pull(skb, len);
@@ -1215,28 +1208,16 @@ static void write_iso_tasklet(unsigned long data)
*/
static void read_iso_tasklet(unsigned long data)
{
- struct bc_state *bcs;
- struct bas_bc_state *ubc;
- struct cardstate *cs;
+ struct bc_state *bcs = (struct bc_state *) data;
+ struct bas_bc_state *ubc = bcs->hw.bas;
+ struct cardstate *cs = bcs->cs;
struct urb *urb;
char *rcvbuf;
unsigned long flags;
int totleft, numbytes, offset, frame, rc;
- bcs = (struct bc_state *) data;
- IFNULLRET(bcs);
- ubc = bcs->hw.bas;
- IFNULLRET(ubc);
- cs = bcs->cs;
- IFNULLRET(cs);
-
/* loop while more completed URBs arrive in the meantime */
for (;;) {
- if (!atomic_read(&cs->connected)) {
- warn("%s: disconnected", __func__);
- return;
- }
-
/* retrieve URB */
spin_lock_irqsave(&ubc->isoinlock, flags);
if (!(urb = ubc->isoindone)) {
@@ -1245,38 +1226,44 @@ static void read_iso_tasklet(unsigned long data)
}
ubc->isoindone = NULL;
if (unlikely(ubc->loststatus != -EINPROGRESS)) {
- warn("isochronous read overrun, dropped URB with status: %s, %d bytes lost",
- get_usb_statmsg(ubc->loststatus), ubc->isoinlost);
+ dev_warn(cs->dev,
+ "isochronous read overrun, "
+ "dropped URB with status: %s, %d bytes lost\n",
+ get_usb_statmsg(ubc->loststatus),
+ ubc->isoinlost);
ubc->loststatus = -EINPROGRESS;
}
spin_unlock_irqrestore(&ubc->isoinlock, flags);
if (unlikely(!(atomic_read(&ubc->running)))) {
- dbg(DEBUG_ISO, "%s: channel not running, dropped URB with status: %s",
- __func__, get_usb_statmsg(urb->status));
+ gig_dbg(DEBUG_ISO,
+ "%s: channel not running, "
+ "dropped URB with status: %s",
+ __func__, get_usb_statmsg(urb->status));
return;
}
switch (urb->status) {
case 0: /* normal completion */
break;
- case -EXDEV: /* inspect individual frames (we do that anyway) */
- dbg(DEBUG_ISO, "%s: URB partially completed", __func__);
+ case -EXDEV: /* inspect individual frames
+ (we do that anyway) */
+ gig_dbg(DEBUG_ISO, "%s: URB partially completed",
+ __func__);
break;
case -ENOENT:
case -ECONNRESET:
- dbg(DEBUG_ISO, "%s: URB canceled", __func__);
- continue; /* -> skip */
- case -EINPROGRESS: /* huh? */
- dbg(DEBUG_ISO, "%s: URB still pending", __func__);
+ case -EINPROGRESS:
+ gig_dbg(DEBUG_ISO, "%s: %s",
+ __func__, get_usb_statmsg(urb->status));
continue; /* -> skip */
case -EPIPE:
- err("isochronous read stalled");
+ dev_err(cs->dev, "isochronous read stalled\n");
error_hangup(bcs);
continue; /* -> skip */
default: /* severe trouble */
- warn("isochronous read: %s",
- get_usb_statmsg(urb->status));
+ dev_warn(cs->dev, "isochronous read: %s\n",
+ get_usb_statmsg(urb->status));
goto error;
}
@@ -1284,33 +1271,44 @@ static void read_iso_tasklet(unsigned long data)
totleft = urb->actual_length;
for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) {
if (unlikely(urb->iso_frame_desc[frame].status)) {
- warn("isochronous read: frame %d: %s",
- frame, get_usb_statmsg(urb->iso_frame_desc[frame].status));
+ dev_warn(cs->dev,
+ "isochronous read: frame %d: %s\n",
+ frame,
+ get_usb_statmsg(
+ urb->iso_frame_desc[frame].status));
break;
}
numbytes = urb->iso_frame_desc[frame].actual_length;
if (unlikely(numbytes > BAS_MAXFRAME)) {
- warn("isochronous read: frame %d: numbytes (%d) > BAS_MAXFRAME",
- frame, numbytes);
+ dev_warn(cs->dev,
+ "isochronous read: frame %d: "
+ "numbytes (%d) > BAS_MAXFRAME\n",
+ frame, numbytes);
break;
}
if (unlikely(numbytes > totleft)) {
- warn("isochronous read: frame %d: numbytes (%d) > totleft (%d)",
- frame, numbytes, totleft);
+ dev_warn(cs->dev,
+ "isochronous read: frame %d: "
+ "numbytes (%d) > totleft (%d)\n",
+ frame, numbytes, totleft);
break;
}
offset = urb->iso_frame_desc[frame].offset;
if (unlikely(offset + numbytes > BAS_INBUFSIZE)) {
- warn("isochronous read: frame %d: offset (%d) + numbytes (%d) > BAS_INBUFSIZE",
- frame, offset, numbytes);
+ dev_warn(cs->dev,
+ "isochronous read: frame %d: "
+ "offset (%d) + numbytes (%d) "
+ "> BAS_INBUFSIZE\n",
+ frame, offset, numbytes);
break;
}
gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs);
totleft -= numbytes;
}
if (unlikely(totleft > 0))
- warn("isochronous read: %d data bytes missing",
- totleft);
+ dev_warn(cs->dev,
+ "isochronous read: %d data bytes missing\n",
+ totleft);
error:
/* URB processed, resubmit */
@@ -1318,12 +1316,15 @@ static void read_iso_tasklet(unsigned long data)
urb->iso_frame_desc[frame].status = 0;
urb->iso_frame_desc[frame].actual_length = 0;
}
- urb->dev = bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */
+ /* urb->dev is clobbered by USB subsystem */
+ urb->dev = bcs->cs->hw.bas->udev;
urb->transfer_flags = URB_ISO_ASAP;
urb->number_of_packets = BAS_NUMFRAMES;
- if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
- err("could not resubmit isochronous read URB: %s",
- get_usb_statmsg(rc));
+ rc = usb_submit_urb(urb, SLAB_ATOMIC);
+ if (unlikely(rc != 0 && rc != -ENODEV)) {
+ dev_err(cs->dev,
+ "could not resubmit isochronous read URB: %s\n",
+ get_usb_rcmsg(rc));
dump_urb(DEBUG_ISO, "resubmit iso read", urb);
error_hangup(bcs);
}
@@ -1341,15 +1342,10 @@ static void read_iso_tasklet(unsigned long data)
static void req_timeout(unsigned long data)
{
struct bc_state *bcs = (struct bc_state *) data;
- struct bas_cardstate *ucs;
+ struct bas_cardstate *ucs = bcs->cs->hw.bas;
int pending;
unsigned long flags;
- IFNULLRET(bcs);
- IFNULLRET(bcs->cs);
- ucs = bcs->cs->hw.bas;
- IFNULLRET(ucs);
-
check_pending(ucs);
spin_lock_irqsave(&ucs->lock, flags);
@@ -1359,33 +1355,34 @@ static void req_timeout(unsigned long data)
switch (pending) {
case 0: /* no pending request */
- dbg(DEBUG_USBREQ, "%s: no request pending", __func__);
+ gig_dbg(DEBUG_USBREQ, "%s: no request pending", __func__);
break;
case HD_OPEN_ATCHANNEL:
- err("timeout opening AT channel");
+ dev_err(bcs->cs->dev, "timeout opening AT channel\n");
error_reset(bcs->cs);
break;
case HD_OPEN_B2CHANNEL:
case HD_OPEN_B1CHANNEL:
- err("timeout opening channel %d", bcs->channel + 1);
+ dev_err(bcs->cs->dev, "timeout opening channel %d\n",
+ bcs->channel + 1);
error_hangup(bcs);
break;
case HD_CLOSE_ATCHANNEL:
- err("timeout closing AT channel");
- //wake_up_interruptible(cs->initwait);
- //FIXME need own wait queue?
+ dev_err(bcs->cs->dev, "timeout closing AT channel\n");
break;
case HD_CLOSE_B2CHANNEL:
case HD_CLOSE_B1CHANNEL:
- err("timeout closing channel %d", bcs->channel + 1);
+ dev_err(bcs->cs->dev, "timeout closing channel %d\n",
+ bcs->channel + 1);
break;
default:
- warn("request 0x%02x timed out, clearing", pending);
+ dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n",
+ pending);
}
}
@@ -1398,18 +1395,14 @@ static void req_timeout(unsigned long data)
*/
static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs)
{
- struct bas_cardstate *ucs;
+ struct bas_cardstate *ucs = urb->context;
unsigned long flags;
- IFNULLRET(urb);
- IFNULLRET(urb->context);
- IFNULLRET(cardstate);
-
- ucs = (struct bas_cardstate *) urb->context;
spin_lock_irqsave(&ucs->lock, flags);
if (urb->status && ucs->pending) {
- err("control request 0x%02x failed: %s",
- ucs->pending, get_usb_statmsg(urb->status));
+ dev_err(&ucs->interface->dev,
+ "control request 0x%02x failed: %s\n",
+ ucs->pending, get_usb_statmsg(urb->status));
del_timer(&ucs->timer_ctrl);
ucs->pending = 0;
}
@@ -1432,34 +1425,24 @@ static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs)
* timeout timeout in seconds (0: no timeout)
* return value:
* 0 on success
- * -EINVAL if a NULL pointer is encountered somewhere
* -EBUSY if another request is pending
* any URB submission error code
*/
static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
{
- struct bas_cardstate *ucs;
+ struct bas_cardstate *ucs = bcs->cs->hw.bas;
int ret;
unsigned long flags;
- IFNULLRETVAL(bcs, -EINVAL);
- IFNULLRETVAL(bcs->cs, -EINVAL);
- ucs = bcs->cs->hw.bas;
- IFNULLRETVAL(ucs, -EINVAL);
- IFNULLRETVAL(ucs->urb_ctrl, -EINVAL);
-
- dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val);
+ gig_dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val);
spin_lock_irqsave(&ucs->lock, flags);
if (ucs->pending) {
spin_unlock_irqrestore(&ucs->lock, flags);
- err("submission of request 0x%02x failed: request 0x%02x still pending",
- req, ucs->pending);
- return -EBUSY;
- }
- if (ucs->urb_ctrl->status == -EINPROGRESS) {
- spin_unlock_irqrestore(&ucs->lock, flags);
- err("could not submit request 0x%02x: URB busy", req);
+ dev_err(bcs->cs->dev,
+ "submission of request 0x%02x failed: "
+ "request 0x%02x still pending\n",
+ req, ucs->pending);
return -EBUSY;
}
@@ -1469,19 +1452,19 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
ucs->dr_ctrl.wIndex = 0;
ucs->dr_ctrl.wLength = 0;
usb_fill_control_urb(ucs->urb_ctrl, ucs->udev,
- usb_sndctrlpipe(ucs->udev, 0),
- (unsigned char*) &ucs->dr_ctrl, NULL, 0,
- write_ctrl_callback, ucs);
+ usb_sndctrlpipe(ucs->udev, 0),
+ (unsigned char*) &ucs->dr_ctrl, NULL, 0,
+ write_ctrl_callback, ucs);
if ((ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC)) != 0) {
- err("could not submit request 0x%02x: %s",
- req, get_usb_statmsg(ret));
+ dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n",
+ req, get_usb_statmsg(ret));
spin_unlock_irqrestore(&ucs->lock, flags);
return ret;
}
ucs->pending = req;
if (timeout > 0) {
- dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
+ gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
ucs->timer_ctrl.expires = jiffies + timeout * HZ / 10;
ucs->timer_ctrl.data = (unsigned long) bcs;
ucs->timer_ctrl.function = req_timeout;
@@ -1503,23 +1486,36 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
static int gigaset_init_bchannel(struct bc_state *bcs)
{
int req, ret;
+ unsigned long flags;
- IFNULLRETVAL(bcs, -EINVAL);
+ spin_lock_irqsave(&bcs->cs->lock, flags);
+ if (unlikely(!bcs->cs->connected)) {
+ gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
+ return -ENODEV;
+ }
if ((ret = starturbs(bcs)) < 0) {
- err("could not start isochronous I/O for channel %d",
- bcs->channel + 1);
- error_hangup(bcs);
+ dev_err(bcs->cs->dev,
+ "could not start isochronous I/O for channel B%d: %s\n",
+ bcs->channel + 1,
+ ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret));
+ if (ret != -ENODEV)
+ error_hangup(bcs);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return ret;
}
req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL;
if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) {
- err("could not open channel %d: %s",
- bcs->channel + 1, get_usb_statmsg(ret));
+ dev_err(bcs->cs->dev, "could not open channel B%d\n",
+ bcs->channel + 1);
stopurbs(bcs->hw.bas);
- error_hangup(bcs);
+ if (ret != -ENODEV)
+ error_hangup(bcs);
}
+
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return ret;
}
@@ -1536,20 +1532,30 @@ static int gigaset_init_bchannel(struct bc_state *bcs)
static int gigaset_close_bchannel(struct bc_state *bcs)
{
int req, ret;
+ unsigned long flags;
- IFNULLRETVAL(bcs, -EINVAL);
+ spin_lock_irqsave(&bcs->cs->lock, flags);
+ if (unlikely(!bcs->cs->connected)) {
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
+ gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+ return -ENODEV;
+ }
if (!(atomic_read(&bcs->cs->hw.bas->basstate) &
(bcs->channel ? BS_B2OPEN : BS_B1OPEN))) {
/* channel not running: just signal common.c */
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
gigaset_bchannel_down(bcs);
return 0;
}
+ /* channel running: tell device to close it */
req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL;
if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0)
- err("could not submit HD_CLOSE_BxCHANNEL request: %s",
- get_usb_statmsg(ret));
+ dev_err(bcs->cs->dev, "closing channel B%d failed\n",
+ bcs->channel + 1);
+
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return ret;
}
@@ -1564,17 +1570,13 @@ static int gigaset_close_bchannel(struct bc_state *bcs)
*/
static void complete_cb(struct cardstate *cs)
{
- struct cmdbuf_t *cb;
-
- IFNULLRET(cs);
- cb = cs->cmdbuf;
- IFNULLRET(cb);
+ struct cmdbuf_t *cb = cs->cmdbuf;
/* unqueue completed buffer */
cs->cmdbytes -= cs->curlen;
- dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD,
- "write_command: sent %u bytes, %u left",
- cs->curlen, cs->cmdbytes);
+ gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD,
+ "write_command: sent %u bytes, %u left",
+ cs->curlen, cs->cmdbytes);
if ((cs->cmdbuf = cb->next) != NULL) {
cs->cmdbuf->prev = NULL;
cs->curlen = cs->cmdbuf->len;
@@ -1589,8 +1591,6 @@ static void complete_cb(struct cardstate *cs)
kfree(cb);
}
-static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len);
-
/* write_command_callback
* USB completion handler for AT command transmission
* called by the USB subsystem in interrupt context
@@ -1600,40 +1600,43 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len);
*/
static void write_command_callback(struct urb *urb, struct pt_regs *regs)
{
- struct cardstate *cs;
+ struct cardstate *cs = urb->context;
+ struct bas_cardstate *ucs = cs->hw.bas;
unsigned long flags;
- struct bas_cardstate *ucs;
- IFNULLRET(urb);
- cs = (struct cardstate *) urb->context;
- IFNULLRET(cs);
- ucs = cs->hw.bas;
- IFNULLRET(ucs);
+ update_basstate(ucs, 0, BS_ATWRPEND);
/* check status */
switch (urb->status) {
case 0: /* normal completion */
break;
- case -ENOENT: /* canceled */
- case -ECONNRESET: /* canceled (async) */
+ case -ENOENT: /* cancelled */
+ case -ECONNRESET: /* cancelled (async) */
case -EINPROGRESS: /* pending */
+ case -ENODEV: /* device removed */
+ case -ESHUTDOWN: /* device shut down */
/* ignore silently */
- dbg(DEBUG_USBREQ,
- "%s: %s", __func__, get_usb_statmsg(urb->status));
+ gig_dbg(DEBUG_USBREQ, "%s: %s",
+ __func__, get_usb_statmsg(urb->status));
return;
default: /* any failure */
if (++ucs->retry_cmd_out > BAS_RETRY) {
- warn("command write: %s, giving up after %d retries",
- get_usb_statmsg(urb->status), ucs->retry_cmd_out);
+ dev_warn(cs->dev,
+ "command write: %s, "
+ "giving up after %d retries\n",
+ get_usb_statmsg(urb->status),
+ ucs->retry_cmd_out);
break;
}
if (cs->cmdbuf == NULL) {
- warn("command write: %s, cannot retry - cmdbuf gone",
- get_usb_statmsg(urb->status));
+ dev_warn(cs->dev,
+ "command write: %s, "
+ "cannot retry - cmdbuf gone\n",
+ get_usb_statmsg(urb->status));
break;
}
- notice("command write: %s, retry %d",
- get_usb_statmsg(urb->status), ucs->retry_cmd_out);
+ dev_notice(cs->dev, "command write: %s, retry %d\n",
+ get_usb_statmsg(urb->status), ucs->retry_cmd_out);
if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0)
/* resubmitted - bypass regular exit block */
return;
@@ -1655,13 +1658,9 @@ static void write_command_callback(struct urb *urb, struct pt_regs *regs)
static void atrdy_timeout(unsigned long data)
{
struct cardstate *cs = (struct cardstate *) data;
- struct bas_cardstate *ucs;
-
- IFNULLRET(cs);
- ucs = cs->hw.bas;
- IFNULLRET(ucs);
+ struct bas_cardstate *ucs = cs->hw.bas;
- warn("timeout waiting for HD_READY_SEND_ATDATA");
+ dev_warn(cs->dev, "timeout waiting for HD_READY_SEND_ATDATA\n");
/* fake the missing signal - what else can I do? */
update_basstate(ucs, BS_ATREADY, BS_ATTIMER);
@@ -1676,24 +1675,19 @@ static void atrdy_timeout(unsigned long data)
* len length of command to send
* return value:
* 0 on success
- * -EFAULT if a NULL pointer is encountered somewhere
* -EBUSY if another request is pending
* any URB submission error code
*/
static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
{
- struct bas_cardstate *ucs;
- int ret;
-
- IFNULLRETVAL(cs, -EFAULT);
- ucs = cs->hw.bas;
- IFNULLRETVAL(ucs, -EFAULT);
- IFNULLRETVAL(ucs->urb_cmd_out, -EFAULT);
+ struct bas_cardstate *ucs = cs->hw.bas;
+ int rc;
- dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len);
+ gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len);
- if (ucs->urb_cmd_out->status == -EINPROGRESS) {
- err("could not submit HD_WRITE_ATMESSAGE: URB busy");
+ if (update_basstate(ucs, BS_ATWRPEND, 0) & BS_ATWRPEND) {
+ dev_err(cs->dev,
+ "could not submit HD_WRITE_ATMESSAGE: URB busy\n");
return -EBUSY;
}
@@ -1706,25 +1700,22 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
usb_sndctrlpipe(ucs->udev, 0),
(unsigned char*) &ucs->dr_cmd_out, buf, len,
write_command_callback, cs);
-
- if ((ret = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC)) != 0) {
- err("could not submit HD_WRITE_ATMESSAGE: %s",
- get_usb_statmsg(ret));
- return ret;
+ rc = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC);
+ if (unlikely(rc)) {
+ update_basstate(ucs, 0, BS_ATWRPEND);
+ dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n",
+ get_usb_rcmsg(rc));
+ return rc;
}
- /* submitted successfully */
- update_basstate(ucs, 0, BS_ATREADY);
-
- /* start timeout if necessary */
- if (!(atomic_read(&ucs->basstate) & BS_ATTIMER)) {
- dbg(DEBUG_OUTPUT,
- "setting ATREADY timeout of %d/10 secs", ATRDY_TIMEOUT);
+ /* submitted successfully, start timeout if necessary */
+ if (!(update_basstate(ucs, BS_ATTIMER, BS_ATREADY) & BS_ATTIMER)) {
+ gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs",
+ ATRDY_TIMEOUT);
ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10;
ucs->timer_atrdy.data = (unsigned long) cs;
ucs->timer_atrdy.function = atrdy_timeout;
add_timer(&ucs->timer_atrdy);
- update_basstate(ucs, BS_ATTIMER, 0);
}
return 0;
}
@@ -1740,21 +1731,16 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
static int start_cbsend(struct cardstate *cs)
{
struct cmdbuf_t *cb;
- struct bas_cardstate *ucs;
+ struct bas_cardstate *ucs = cs->hw.bas;
unsigned long flags;
int rc;
int retval = 0;
- IFNULLRETVAL(cs, -EFAULT);
- ucs = cs->hw.bas;
- IFNULLRETVAL(ucs, -EFAULT);
-
/* check if AT channel is open */
if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) {
- dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD, "AT channel not open");
+ gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open");
rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT);
if (rc < 0) {
- err("could not open AT channel");
/* flush command queue */
spin_lock_irqsave(&cs->cmdlock, flags);
while (cs->cmdbuf != NULL)
@@ -1792,27 +1778,23 @@ static int start_cbsend(struct cardstate *cs)
* cs controller state structure
* buf command string to send
* len number of bytes to send (max. IF_WRITEBUF)
- * wake_tasklet tasklet to run when transmission is completed (NULL if none)
+ * wake_tasklet tasklet to run when transmission is completed
+ * (NULL if none)
* return value:
* number of bytes queued on success
* error code < 0 on error
*/
static int gigaset_write_cmd(struct cardstate *cs,
- const unsigned char *buf, int len,
- struct tasklet_struct *wake_tasklet)
+ const unsigned char *buf, int len,
+ struct tasklet_struct *wake_tasklet)
{
struct cmdbuf_t *cb;
unsigned long flags;
int status;
gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
- DEBUG_TRANSCMD : DEBUG_LOCKCMD,
- "CMD Transmit", len, buf, 0);
-
- if (!atomic_read(&cs->connected)) {
- err("%s: not connected", __func__);
- return -ENODEV;
- }
+ DEBUG_TRANSCMD : DEBUG_LOCKCMD,
+ "CMD Transmit", len, buf);
if (len <= 0)
return 0; /* nothing to do */
@@ -1820,7 +1802,7 @@ static int gigaset_write_cmd(struct cardstate *cs,
if (len > IF_WRITEBUF)
len = IF_WRITEBUF;
if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
- err("%s: out of memory", __func__);
+ dev_err(cs->dev, "%s: out of memory\n", __func__);
return -ENOMEM;
}
@@ -1842,14 +1824,21 @@ static int gigaset_write_cmd(struct cardstate *cs,
cs->lastcmdbuf = cb;
spin_unlock_irqrestore(&cs->cmdlock, flags);
+ spin_lock_irqsave(&cs->lock, flags);
+ if (unlikely(!cs->connected)) {
+ spin_unlock_irqrestore(&cs->lock, flags);
+ gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+ return -ENODEV;
+ }
status = start_cbsend(cs);
-
+ spin_unlock_irqrestore(&cs->lock, flags);
return status < 0 ? status : len;
}
/* gigaset_write_room
* tty_driver.write_room interface routine
- * return number of characters the driver will accept to be written via gigaset_write_cmd
+ * return number of characters the driver will accept to be written via
+ * gigaset_write_cmd
* parameter:
* controller state structure
* return value:
@@ -1904,12 +1893,32 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
*/
static int gigaset_freebcshw(struct bc_state *bcs)
{
- if (!bcs->hw.bas)
+ struct bas_bc_state *ubc = bcs->hw.bas;
+ int i;
+
+ if (!ubc)
return 0;
- if (bcs->hw.bas->isooutbuf)
- kfree(bcs->hw.bas->isooutbuf);
- kfree(bcs->hw.bas);
+ /* kill URBs and tasklets before freeing - better safe than sorry */
+ atomic_set(&ubc->running, 0);
+ for (i = 0; i < BAS_OUTURBS; ++i)
+ if (ubc->isoouturbs[i].urb) {
+ gig_dbg(DEBUG_INIT, "%s: killing iso out URB %d",
+ __func__, i);
+ usb_kill_urb(ubc->isoouturbs[i].urb);
+ usb_free_urb(ubc->isoouturbs[i].urb);
+ }
+ for (i = 0; i < BAS_INURBS; ++i)
+ if (ubc->isoinurbs[i]) {
+ gig_dbg(DEBUG_INIT, "%s: killing iso in URB %d",
+ __func__, i);
+ usb_kill_urb(ubc->isoinurbs[i]);
+ usb_free_urb(ubc->isoinurbs[i]);
+ }
+ tasklet_kill(&ubc->sent_tasklet);
+ tasklet_kill(&ubc->rcvd_tasklet);
+ kfree(ubc->isooutbuf);
+ kfree(ubc);
bcs->hw.bas = NULL;
return 1;
}
@@ -1947,7 +1956,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
return 0;
}
tasklet_init(&ubc->sent_tasklet,
- &write_iso_tasklet, (unsigned long) bcs);
+ &write_iso_tasklet, (unsigned long) bcs);
spin_lock_init(&ubc->isoinlock);
for (i = 0; i < BAS_INURBS; ++i)
@@ -1968,7 +1977,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
ubc->shared0s = 0;
ubc->stolen0s = 0;
tasklet_init(&ubc->rcvd_tasklet,
- &read_iso_tasklet, (unsigned long) bcs);
+ &read_iso_tasklet, (unsigned long) bcs);
return 1;
}
@@ -1986,13 +1995,9 @@ static void gigaset_reinitbcshw(struct bc_state *bcs)
static void gigaset_freecshw(struct cardstate *cs)
{
- struct bas_cardstate *ucs = cs->hw.bas;
-
- del_timer(&ucs->timer_ctrl);
- del_timer(&ucs->timer_atrdy);
- del_timer(&ucs->timer_cmd_in);
-
+ /* timers, URBs and rcvbuf are disposed of in disconnect */
kfree(cs->hw.bas);
+ cs->hw.bas = NULL;
}
static int gigaset_initcshw(struct cardstate *cs)
@@ -2027,57 +2032,56 @@ static int gigaset_initcshw(struct cardstate *cs)
*/
static void freeurbs(struct cardstate *cs)
{
- struct bas_cardstate *ucs;
+ struct bas_cardstate *ucs = cs->hw.bas;
struct bas_bc_state *ubc;
int i, j;
- IFNULLRET(cs);
- ucs = cs->hw.bas;
- IFNULLRET(ucs);
-
for (j = 0; j < 2; ++j) {
ubc = cs->bcs[j].hw.bas;
- IFNULLCONT(ubc);
for (i = 0; i < BAS_OUTURBS; ++i)
if (ubc->isoouturbs[i].urb) {
usb_kill_urb(ubc->isoouturbs[i].urb);
- dbg(DEBUG_INIT,
- "%s: isoc output URB %d/%d unlinked",
- __func__, j, i);
+ gig_dbg(DEBUG_INIT,
+ "%s: isoc output URB %d/%d unlinked",
+ __func__, j, i);
usb_free_urb(ubc->isoouturbs[i].urb);
ubc->isoouturbs[i].urb = NULL;
}
for (i = 0; i < BAS_INURBS; ++i)
if (ubc->isoinurbs[i]) {
usb_kill_urb(ubc->isoinurbs[i]);
- dbg(DEBUG_INIT,
- "%s: isoc input URB %d/%d unlinked",
- __func__, j, i);
+ gig_dbg(DEBUG_INIT,
+ "%s: isoc input URB %d/%d unlinked",
+ __func__, j, i);
usb_free_urb(ubc->isoinurbs[i]);
ubc->isoinurbs[i] = NULL;
}
}
if (ucs->urb_int_in) {
usb_kill_urb(ucs->urb_int_in);
- dbg(DEBUG_INIT, "%s: interrupt input URB unlinked", __func__);
+ gig_dbg(DEBUG_INIT, "%s: interrupt input URB unlinked",
+ __func__);
usb_free_urb(ucs->urb_int_in);
ucs->urb_int_in = NULL;
}
if (ucs->urb_cmd_out) {
usb_kill_urb(ucs->urb_cmd_out);
- dbg(DEBUG_INIT, "%s: command output URB unlinked", __func__);
+ gig_dbg(DEBUG_INIT, "%s: command output URB unlinked",
+ __func__);
usb_free_urb(ucs->urb_cmd_out);
ucs->urb_cmd_out = NULL;
}
if (ucs->urb_cmd_in) {
usb_kill_urb(ucs->urb_cmd_in);
- dbg(DEBUG_INIT, "%s: command input URB unlinked", __func__);
+ gig_dbg(DEBUG_INIT, "%s: command input URB unlinked",
+ __func__);
usb_free_urb(ucs->urb_cmd_in);
ucs->urb_cmd_in = NULL;
}
if (ucs->urb_ctrl) {
usb_kill_urb(ucs->urb_ctrl);
- dbg(DEBUG_INIT, "%s: control output URB unlinked", __func__);
+ gig_dbg(DEBUG_INIT, "%s: control output URB unlinked",
+ __func__);
usb_free_urb(ucs->urb_ctrl);
ucs->urb_ctrl = NULL;
}
@@ -2097,35 +2101,24 @@ static int gigaset_probe(struct usb_interface *interface,
struct bas_bc_state *ubc;
struct usb_endpoint_descriptor *endpoint;
int i, j;
- int ret;
-
- IFNULLRETVAL(udev, -ENODEV);
-
- dbg(DEBUG_ANY,
- "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
- __func__, le16_to_cpu(udev->descriptor.idVendor),
- le16_to_cpu(udev->descriptor.idProduct));
+ int rc;
- /* See if the device offered us matches what we can accept */
- if ((le16_to_cpu(udev->descriptor.idVendor) != USB_GIGA_VENDOR_ID) ||
- (le16_to_cpu(udev->descriptor.idProduct) != USB_GIGA_PRODUCT_ID &&
- le16_to_cpu(udev->descriptor.idProduct) != USB_4175_PRODUCT_ID &&
- le16_to_cpu(udev->descriptor.idProduct) != USB_SX303_PRODUCT_ID &&
- le16_to_cpu(udev->descriptor.idProduct) != USB_SX353_PRODUCT_ID)) {
- dbg(DEBUG_ANY, "%s: unmatched ID - exiting", __func__);
- return -ENODEV;
- }
+ gig_dbg(DEBUG_ANY,
+ "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
+ __func__, le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
/* set required alternate setting */
hostif = interface->cur_altsetting;
if (hostif->desc.bAlternateSetting != 3) {
- dbg(DEBUG_ANY,
- "%s: wrong alternate setting %d - trying to switch",
- __func__, hostif->desc.bAlternateSetting);
+ gig_dbg(DEBUG_ANY,
+ "%s: wrong alternate setting %d - trying to switch",
+ __func__, hostif->desc.bAlternateSetting);
if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) < 0) {
- warn("usb_set_interface failed, device %d interface %d altsetting %d",
- udev->devnum, hostif->desc.bInterfaceNumber,
- hostif->desc.bAlternateSetting);
+ dev_warn(&udev->dev, "usb_set_interface failed, "
+ "device %d interface %d altsetting %d\n",
+ udev->devnum, hostif->desc.bInterfaceNumber,
+ hostif->desc.bAlternateSetting);
return -ENODEV;
}
hostif = interface->cur_altsetting;
@@ -2134,68 +2127,50 @@ static int gigaset_probe(struct usb_interface *interface,
/* Reject application specific interfaces
*/
if (hostif->desc.bInterfaceClass != 255) {
- warn("%s: bInterfaceClass == %d",
- __func__, hostif->desc.bInterfaceClass);
+ dev_warn(&udev->dev, "%s: bInterfaceClass == %d\n",
+ __func__, hostif->desc.bInterfaceClass);
return -ENODEV;
}
- info("%s: Device matched (Vendor: 0x%x, Product: 0x%x)",
- __func__, le16_to_cpu(udev->descriptor.idVendor),
- le16_to_cpu(udev->descriptor.idProduct));
+ dev_info(&udev->dev,
+ "%s: Device matched (Vendor: 0x%x, Product: 0x%x)\n",
+ __func__, le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
cs = gigaset_getunassignedcs(driver);
if (!cs) {
- err("%s: no free cardstate", __func__);
+ dev_err(&udev->dev, "no free cardstate\n");
return -ENODEV;
}
ucs = cs->hw.bas;
+
+ /* save off device structure ptrs for later use */
+ usb_get_dev(udev);
ucs->udev = udev;
ucs->interface = interface;
+ cs->dev = &interface->dev;
/* allocate URBs:
* - one for the interrupt pipe
* - three for the different uses of the default control pipe
* - three for each isochronous pipe
*/
- ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL);
- if (!ucs->urb_int_in) {
- err("No free urbs available");
- goto error;
- }
- ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL);
- if (!ucs->urb_cmd_in) {
- err("No free urbs available");
- goto error;
- }
- ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL);
- if (!ucs->urb_cmd_out) {
- err("No free urbs available");
- goto error;
- }
- ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL);
- if (!ucs->urb_ctrl) {
- err("No free urbs available");
- goto error;
- }
+ if (!(ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL)) ||
+ !(ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL)) ||
+ !(ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL)) ||
+ !(ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL)))
+ goto allocerr;
for (j = 0; j < 2; ++j) {
ubc = cs->bcs[j].hw.bas;
- for (i = 0; i < BAS_OUTURBS; ++i) {
- ubc->isoouturbs[i].urb =
- usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL);
- if (!ubc->isoouturbs[i].urb) {
- err("No free urbs available");
- goto error;
- }
- }
- for (i = 0; i < BAS_INURBS; ++i) {
- ubc->isoinurbs[i] =
- usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL);
- if (!ubc->isoinurbs[i]) {
- err("No free urbs available");
- goto error;
- }
- }
+ for (i = 0; i < BAS_OUTURBS; ++i)
+ if (!(ubc->isoouturbs[i].urb =
+ usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL)))
+ goto allocerr;
+ for (i = 0; i < BAS_INURBS; ++i)
+ if (!(ubc->isoinurbs[i] =
+ usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL)))
+ goto allocerr;
}
ucs->rcvbuf = NULL;
@@ -2204,35 +2179,37 @@ static int gigaset_probe(struct usb_interface *interface,
/* Fill the interrupt urb and send it to the core */
endpoint = &hostif->endpoint[0].desc;
usb_fill_int_urb(ucs->urb_int_in, udev,
- usb_rcvintpipe(udev,
- (endpoint->bEndpointAddress) & 0x0f),
- ucs->int_in_buf, 3, read_int_callback, cs,
- endpoint->bInterval);
- ret = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL);
- if (ret) {
- err("could not submit interrupt URB: %s", get_usb_statmsg(ret));
+ usb_rcvintpipe(udev,
+ (endpoint->bEndpointAddress) & 0x0f),
+ ucs->int_in_buf, 3, read_int_callback, cs,
+ endpoint->bInterval);
+ if ((rc = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL)) != 0) {
+ dev_err(cs->dev, "could not submit interrupt URB: %s\n",
+ get_usb_rcmsg(rc));
goto error;
}
/* tell the device that the driver is ready */
- if ((ret = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0)
+ if ((rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0)
goto error;
/* tell common part that the device is ready */
if (startmode == SM_LOCKED)
atomic_set(&cs->mstate, MS_LOCKED);
- if (!gigaset_start(cs))
- goto error;
/* save address of controller structure */
usb_set_intfdata(interface, cs);
- /* set up device sysfs */
- gigaset_init_dev_sysfs(interface);
+ if (!gigaset_start(cs))
+ goto error;
+
return 0;
+allocerr:
+ dev_err(cs->dev, "could not allocate URBs\n");
error:
freeurbs(cs);
+ usb_set_intfdata(interface, NULL);
gigaset_unassign(cs);
return -ENODEV;
}
@@ -2244,24 +2221,38 @@ static void gigaset_disconnect(struct usb_interface *interface)
{
struct cardstate *cs;
struct bas_cardstate *ucs;
-
- /* clear device sysfs */
- gigaset_free_dev_sysfs(interface);
+ int j;
cs = usb_get_intfdata(interface);
- usb_set_intfdata(interface, NULL);
- IFNULLRET(cs);
ucs = cs->hw.bas;
- IFNULLRET(ucs);
- info("disconnecting GigaSet base");
+ dev_info(cs->dev, "disconnecting Gigaset base\n");
+
+ /* mark base as not ready, all channels disconnected */
+ atomic_set(&ucs->basstate, 0);
+
+ /* tell LL all channels are down */
+ //FIXME shouldn't gigaset_stop() do this?
+ for (j = 0; j < 2; ++j)
+ gigaset_bchannel_down(cs->bcs + j);
+
+ /* stop driver (common part) */
gigaset_stop(cs);
+
+ /* stop timers and URBs, free ressources */
+ del_timer_sync(&ucs->timer_ctrl);
+ del_timer_sync(&ucs->timer_atrdy);
+ del_timer_sync(&ucs->timer_cmd_in);
freeurbs(cs);
+ usb_set_intfdata(interface, NULL);
kfree(ucs->rcvbuf);
ucs->rcvbuf = NULL;
ucs->rcvbuf_size = 0;
- atomic_set(&ucs->basstate, 0);
+ usb_put_dev(ucs->udev);
+ ucs->interface = NULL;
+ ucs->udev = NULL;
+ cs->dev = NULL;
gigaset_unassign(cs);
}
@@ -2293,13 +2284,14 @@ static int __init bas_gigaset_init(void)
/* allocate memory for our driver state and intialize it */
if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
- GIGASET_MODULENAME, GIGASET_DEVNAME,
- GIGASET_DEVFSNAME, &gigops,
- THIS_MODULE)) == NULL)
+ GIGASET_MODULENAME, GIGASET_DEVNAME,
+ GIGASET_DEVFSNAME, &gigops,
+ THIS_MODULE)) == NULL)
goto error;
/* allocate memory for our device state and intialize it */
- cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode, GIGASET_MODULENAME);
+ cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode,
+ GIGASET_MODULENAME);
if (!cardstate)
goto error;
@@ -2328,22 +2320,35 @@ error: if (cardstate)
*/
static void __exit bas_gigaset_exit(void)
{
+ struct bas_cardstate *ucs = cardstate->hw.bas;
+
gigaset_blockdriver(driver); /* => probe will fail
- * => no gigaset_start any more
- */
+ * => no gigaset_start any more
+ */
gigaset_shutdown(cardstate);
/* from now on, no isdn callback should be possible */
- if (atomic_read(&cardstate->hw.bas->basstate) & BS_ATOPEN) {
- dbg(DEBUG_ANY, "closing AT channel");
- if (req_submit(cardstate->bcs,
- HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT) >= 0) {
- /* successfully submitted - wait for completion */
- //wait_event_interruptible(cs->initwait, !cs->hw.bas->pending);
- //FIXME need own wait queue? wakeup?
- }
+ /* close all still open channels */
+ if (atomic_read(&ucs->basstate) & BS_B1OPEN) {
+ gig_dbg(DEBUG_INIT, "closing B1 channel");
+ usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+ HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0,
+ NULL, 0, BAS_TIMEOUT);
+ }
+ if (atomic_read(&ucs->basstate) & BS_B2OPEN) {
+ gig_dbg(DEBUG_INIT, "closing B2 channel");
+ usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+ HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0,
+ NULL, 0, BAS_TIMEOUT);
+ }
+ if (atomic_read(&ucs->basstate) & BS_ATOPEN) {
+ gig_dbg(DEBUG_INIT, "closing AT channel");
+ usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+ HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0,
+ NULL, 0, BAS_TIMEOUT);
}
+ atomic_set(&ucs->basstate, 0);
/* deregister this driver with the USB subsystem */
usb_deregister(&gigaset_usb_driver);
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 64371995c1a..e55767b2ccd 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -1,7 +1,7 @@
/*
* Stuff used by all variants of the driver
*
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Copyright (c) 2001 by Stefan Eilers,
* Hansjoerg Lipp <hjlipp@web.de>,
* Tilman Schmidt <tilman@imap.cc>.
*
@@ -11,10 +11,6 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: common.c,v 1.104.4.22 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
@@ -23,7 +19,7 @@
#include <linux/moduleparam.h>
/* Version Information */
-#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers"
#define DRIVER_DESC "Driver for Gigaset 307x"
/* Module parameters */
@@ -32,21 +28,10 @@ EXPORT_SYMBOL_GPL(gigaset_debuglevel);
module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(debug, "debug level");
-/*======================================================================
- Prototypes of internal functions
- */
-
-//static void gigaset_process_response(int resp_code, int parameter,
-// struct at_state_t *at_state,
-// unsigned char ** pstring);
-static struct cardstate *alloc_cs(struct gigaset_driver *drv);
-static void free_cs(struct cardstate *cs);
-static void make_valid(struct cardstate *cs, unsigned mask);
-static void make_invalid(struct cardstate *cs, unsigned mask);
-
-#define VALID_MINOR 0x01
-#define VALID_ID 0x02
-#define ASSIGNED 0x04
+/* driver state flags */
+#define VALID_MINOR 0x01
+#define VALID_ID 0x02
+#define ASSIGNED 0x04
/* bitwise byte inversion table */
__u8 gigaset_invtab[256] = {
@@ -86,42 +71,40 @@ __u8 gigaset_invtab[256] = {
EXPORT_SYMBOL_GPL(gigaset_invtab);
void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
- size_t len, const unsigned char *buf, int from_user)
+ size_t len, const unsigned char *buf)
{
unsigned char outbuf[80];
- unsigned char inbuf[80 - 1];
- size_t numin;
- const unsigned char *in;
+ unsigned char c;
size_t space = sizeof outbuf - 1;
unsigned char *out = outbuf;
+ size_t numin = len;
- if (!from_user) {
- in = buf;
- numin = len;
- } else {
- numin = len < sizeof inbuf ? len : sizeof inbuf;
- in = inbuf;
- if (copy_from_user(inbuf, (const unsigned char __user *) buf, numin)) {
- strncpy(inbuf, "<FAULT>", sizeof inbuf);
- numin = sizeof "<FAULT>" - 1;
+ while (numin--) {
+ c = *buf++;
+ if (c == '~' || c == '^' || c == '\\') {
+ if (!space--)
+ break;
+ *out++ = '\\';
}
- }
-
- for (; numin && space; --numin, ++in) {
- --space;
- if (*in >= 32)
- *out++ = *in;
- else {
+ if (c & 0x80) {
+ if (!space--)
+ break;
+ *out++ = '~';
+ c ^= 0x80;
+ }
+ if (c < 0x20 || c == 0x7f) {
+ if (!space--)
+ break;
*out++ = '^';
- if (space) {
- *out++ = '@' + *in;
- --space;
- }
+ c ^= 0x40;
}
+ if (!space--)
+ break;
+ *out++ = c;
}
*out = 0;
- dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf);
+ gig_dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf);
}
EXPORT_SYMBOL_GPL(gigaset_dbg_buffer);
@@ -146,11 +129,6 @@ int gigaset_enterconfigmode(struct cardstate *cs)
{
int i, r;
- if (!atomic_read(&cs->connected)) {
- err("not connected!");
- return -1;
- }
-
cs->control_state = TIOCM_RTS; //FIXME
r = setflags(cs, TIOCM_DTR, 200);
@@ -174,7 +152,7 @@ int gigaset_enterconfigmode(struct cardstate *cs)
return 0;
error:
- err("error %d on setuartbits!\n", -r);
+ dev_err(cs->dev, "error %d on setuartbits\n", -r);
cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value?
cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR);
@@ -187,13 +165,13 @@ static int test_timeout(struct at_state_t *at_state)
return 0;
if (--at_state->timer_expires) {
- dbg(DEBUG_MCMD, "decreased timer of %p to %lu",
- at_state, at_state->timer_expires);
+ gig_dbg(DEBUG_MCMD, "decreased timer of %p to %lu",
+ at_state, at_state->timer_expires);
return 0;
}
if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL,
- atomic_read(&at_state->timer_index), NULL)) {
+ at_state->timer_index, NULL)) {
//FIXME what should we do?
}
@@ -221,10 +199,10 @@ static void timer_tick(unsigned long data)
if (test_timeout(at_state))
timeout = 1;
- if (atomic_read(&cs->running)) {
- mod_timer(&cs->timer, jiffies + GIG_TICK);
+ if (cs->running) {
+ mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK));
if (timeout) {
- dbg(DEBUG_CMD, "scheduling timeout");
+ gig_dbg(DEBUG_CMD, "scheduling timeout");
tasklet_schedule(&cs->event_tasklet);
}
}
@@ -238,13 +216,14 @@ int gigaset_get_channel(struct bc_state *bcs)
spin_lock_irqsave(&bcs->cs->lock, flags);
if (bcs->use_count) {
- dbg(DEBUG_ANY, "could not allocate channel %d", bcs->channel);
+ gig_dbg(DEBUG_ANY, "could not allocate channel %d",
+ bcs->channel);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
return 0;
}
++bcs->use_count;
bcs->busy = 1;
- dbg(DEBUG_ANY, "allocated channel %d", bcs->channel);
+ gig_dbg(DEBUG_ANY, "allocated channel %d", bcs->channel);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
return 1;
}
@@ -255,13 +234,13 @@ void gigaset_free_channel(struct bc_state *bcs)
spin_lock_irqsave(&bcs->cs->lock, flags);
if (!bcs->busy) {
- dbg(DEBUG_ANY, "could not free channel %d", bcs->channel);
+ gig_dbg(DEBUG_ANY, "could not free channel %d", bcs->channel);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
return;
}
--bcs->use_count;
bcs->busy = 0;
- dbg(DEBUG_ANY, "freed channel %d", bcs->channel);
+ gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
}
@@ -274,14 +253,14 @@ int gigaset_get_channels(struct cardstate *cs)
for (i = 0; i < cs->channels; ++i)
if (cs->bcs[i].use_count) {
spin_unlock_irqrestore(&cs->lock, flags);
- dbg(DEBUG_ANY, "could not allocated all channels");
+ gig_dbg(DEBUG_ANY, "could not allocate all channels");
return 0;
}
for (i = 0; i < cs->channels; ++i)
++cs->bcs[i].use_count;
spin_unlock_irqrestore(&cs->lock, flags);
- dbg(DEBUG_ANY, "allocated all channels");
+ gig_dbg(DEBUG_ANY, "allocated all channels");
return 1;
}
@@ -291,7 +270,7 @@ void gigaset_free_channels(struct cardstate *cs)
unsigned long flags;
int i;
- dbg(DEBUG_ANY, "unblocking all channels");
+ gig_dbg(DEBUG_ANY, "unblocking all channels");
spin_lock_irqsave(&cs->lock, flags);
for (i = 0; i < cs->channels; ++i)
--cs->bcs[i].use_count;
@@ -303,7 +282,7 @@ void gigaset_block_channels(struct cardstate *cs)
unsigned long flags;
int i;
- dbg(DEBUG_ANY, "blocking all channels");
+ gig_dbg(DEBUG_ANY, "blocking all channels");
spin_lock_irqsave(&cs->lock, flags);
for (i = 0; i < cs->channels; ++i)
++cs->bcs[i].use_count;
@@ -314,25 +293,27 @@ static void clear_events(struct cardstate *cs)
{
struct event_t *ev;
unsigned head, tail;
+ unsigned long flags;
- /* no locking needed (no reader/writer allowed) */
+ spin_lock_irqsave(&cs->ev_lock, flags);
- head = atomic_read(&cs->ev_head);
- tail = atomic_read(&cs->ev_tail);
+ head = cs->ev_head;
+ tail = cs->ev_tail;
while (tail != head) {
ev = cs->events + head;
kfree(ev->ptr);
-
head = (head + 1) % MAX_EVENTS;
}
- atomic_set(&cs->ev_head, tail);
+ cs->ev_head = tail;
+
+ spin_unlock_irqrestore(&cs->ev_lock, flags);
}
struct event_t *gigaset_add_event(struct cardstate *cs,
- struct at_state_t *at_state, int type,
- void *ptr, int parameter, void *arg)
+ struct at_state_t *at_state, int type,
+ void *ptr, int parameter, void *arg)
{
unsigned long flags;
unsigned next, tail;
@@ -340,9 +321,9 @@ struct event_t *gigaset_add_event(struct cardstate *cs,
spin_lock_irqsave(&cs->ev_lock, flags);
- tail = atomic_read(&cs->ev_tail);
+ tail = cs->ev_tail;
next = (tail + 1) % MAX_EVENTS;
- if (unlikely(next == atomic_read(&cs->ev_head)))
+ if (unlikely(next == cs->ev_head))
err("event queue full");
else {
event = cs->events + tail;
@@ -352,7 +333,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs,
event->ptr = ptr;
event->arg = arg;
event->parameter = parameter;
- atomic_set(&cs->ev_tail, next);
+ cs->ev_tail = next;
}
spin_unlock_irqrestore(&cs->ev_lock, flags);
@@ -391,14 +372,14 @@ static void gigaset_freebcs(struct bc_state *bcs)
{
int i;
- dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
+ gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
if (!bcs->cs->ops->freebcshw(bcs)) {
- dbg(DEBUG_INIT, "failed");
+ gig_dbg(DEBUG_INIT, "failed");
}
- dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
+ gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
clear_at_state(&bcs->at_state);
- dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
+ gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
if (bcs->skb)
dev_kfree_skb(bcs->skb);
@@ -408,6 +389,52 @@ static void gigaset_freebcs(struct bc_state *bcs)
}
}
+static struct cardstate *alloc_cs(struct gigaset_driver *drv)
+{
+ unsigned long flags;
+ unsigned i;
+ static struct cardstate *ret = NULL;
+
+ spin_lock_irqsave(&drv->lock, flags);
+ for (i = 0; i < drv->minors; ++i) {
+ if (!(drv->flags[i] & VALID_MINOR)) {
+ drv->flags[i] = VALID_MINOR;
+ ret = drv->cs + i;
+ }
+ if (ret)
+ break;
+ }
+ spin_unlock_irqrestore(&drv->lock, flags);
+ return ret;
+}
+
+static void free_cs(struct cardstate *cs)
+{
+ unsigned long flags;
+ struct gigaset_driver *drv = cs->driver;
+ spin_lock_irqsave(&drv->lock, flags);
+ drv->flags[cs->minor_index] = 0;
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+static void make_valid(struct cardstate *cs, unsigned mask)
+{
+ unsigned long flags;
+ struct gigaset_driver *drv = cs->driver;
+ spin_lock_irqsave(&drv->lock, flags);
+ drv->flags[cs->minor_index] |= mask;
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+static void make_invalid(struct cardstate *cs, unsigned mask)
+{
+ unsigned long flags;
+ struct gigaset_driver *drv = cs->driver;
+ spin_lock_irqsave(&drv->lock, flags);
+ drv->flags[cs->minor_index] &= ~mask;
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+
void gigaset_freecs(struct cardstate *cs)
{
int i;
@@ -416,7 +443,7 @@ void gigaset_freecs(struct cardstate *cs)
if (!cs)
return;
- down(&cs->sem);
+ mutex_lock(&cs->mutex);
if (!cs->bcs)
goto f_cs;
@@ -424,8 +451,9 @@ void gigaset_freecs(struct cardstate *cs)
goto f_bcs;
spin_lock_irqsave(&cs->lock, flags);
- atomic_set(&cs->running, 0);
- spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are not rescheduled below */
+ cs->running = 0;
+ spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are
+ not rescheduled below */
tasklet_kill(&cs->event_tasklet);
del_timer_sync(&cs->timer);
@@ -434,7 +462,7 @@ void gigaset_freecs(struct cardstate *cs)
default:
gigaset_if_free(cs);
- dbg(DEBUG_INIT, "clearing hw");
+ gig_dbg(DEBUG_INIT, "clearing hw");
cs->ops->freecshw(cs);
//FIXME cmdbuf
@@ -443,36 +471,36 @@ void gigaset_freecs(struct cardstate *cs)
case 2: /* error in initcshw */
/* Deregister from LL */
make_invalid(cs, VALID_ID);
- dbg(DEBUG_INIT, "clearing iif");
+ gig_dbg(DEBUG_INIT, "clearing iif");
gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
/* fall through */
case 1: /* error when regestering to LL */
- dbg(DEBUG_INIT, "clearing at_state");
+ gig_dbg(DEBUG_INIT, "clearing at_state");
clear_at_state(&cs->at_state);
dealloc_at_states(cs);
/* fall through */
case 0: /* error in one call to initbcs */
for (i = 0; i < cs->channels; ++i) {
- dbg(DEBUG_INIT, "clearing bcs[%d]", i);
+ gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i);
gigaset_freebcs(cs->bcs + i);
}
clear_events(cs);
- dbg(DEBUG_INIT, "freeing inbuf");
+ gig_dbg(DEBUG_INIT, "freeing inbuf");
kfree(cs->inbuf);
}
-f_bcs: dbg(DEBUG_INIT, "freeing bcs[]");
+f_bcs: gig_dbg(DEBUG_INIT, "freeing bcs[]");
kfree(cs->bcs);
-f_cs: dbg(DEBUG_INIT, "freeing cs");
- up(&cs->sem);
+f_cs: gig_dbg(DEBUG_INIT, "freeing cs");
+ mutex_unlock(&cs->mutex);
free_cs(cs);
}
EXPORT_SYMBOL_GPL(gigaset_freecs);
void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
- struct cardstate *cs, int cid)
+ struct cardstate *cs, int cid)
{
int i;
@@ -482,8 +510,8 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
at_state->pending_commands = 0;
at_state->timer_expires = 0;
at_state->timer_active = 0;
- atomic_set(&at_state->timer_index, 0);
- atomic_set(&at_state->seq_index, 0);
+ at_state->timer_index = 0;
+ at_state->seq_index = 0;
at_state->ConState = 0;
for (i = 0; i < STR_NUM; ++i)
at_state->str_var[i] = NULL;
@@ -501,7 +529,7 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
- struct cardstate *cs, int inputstate)
+ struct cardstate *cs, int inputstate)
/* inbuf->read must be allocated before! */
{
atomic_set(&inbuf->head, 0);
@@ -512,9 +540,50 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
inbuf->inputstate = inputstate;
}
+/* append received bytes to inbuf */
+int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
+ unsigned numbytes)
+{
+ unsigned n, head, tail, bytesleft;
+
+ gig_dbg(DEBUG_INTR, "received %u bytes", numbytes);
+
+ if (!numbytes)
+ return 0;
+
+ bytesleft = numbytes;
+ tail = atomic_read(&inbuf->tail);
+ head = atomic_read(&inbuf->head);
+ gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
+
+ while (bytesleft) {
+ if (head > tail)
+ n = head - 1 - tail;
+ else if (head == 0)
+ n = (RBUFSIZE-1) - tail;
+ else
+ n = RBUFSIZE - tail;
+ if (!n) {
+ dev_err(inbuf->cs->dev,
+ "buffer overflow (%u bytes lost)", bytesleft);
+ break;
+ }
+ if (n > bytesleft)
+ n = bytesleft;
+ memcpy(inbuf->data + tail, src, n);
+ bytesleft -= n;
+ tail = (tail + n) % RBUFSIZE;
+ src += n;
+ }
+ gig_dbg(DEBUG_INTR, "setting tail to %u", tail);
+ atomic_set(&inbuf->tail, tail);
+ return numbytes != bytesleft;
+}
+EXPORT_SYMBOL_GPL(gigaset_fill_inbuf);
+
/* Initialize the b-channel structure */
static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
- struct cardstate *cs, int channel)
+ struct cardstate *cs, int channel)
{
int i;
@@ -526,7 +595,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
bcs->trans_down = 0;
bcs->trans_up = 0;
- dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel);
+ gig_dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel);
gigaset_at_init(&bcs->at_state, bcs, cs, -1);
bcs->rcvbytes = 0;
@@ -535,7 +604,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
bcs->emptycount = 0;
#endif
- dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
+ gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
bcs->fcs = PPP_INITFCS;
bcs->inputstate = 0;
if (cs->ignoreframes) {
@@ -544,7 +613,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
} else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
skb_reserve(bcs->skb, HW_HDR_LEN);
else {
- warn("could not allocate skb");
+ dev_warn(cs->dev, "could not allocate skb\n");
bcs->inputstate |= INS_skip_frame;
}
@@ -559,14 +628,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
for (i = 0; i < AT_NUM; ++i)
bcs->commands[i] = NULL;
- dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel);
+ gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel);
if (cs->ops->initbcshw(bcs))
return bcs;
-//error:
- dbg(DEBUG_INIT, " failed");
+ gig_dbg(DEBUG_INIT, " failed");
- dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel);
+ gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel);
if (bcs->skb)
dev_kfree_skb(bcs->skb);
@@ -578,9 +646,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
* Calls hardware dependent gigaset_initcshw() function
* Calls B channel initialization function gigaset_initbcs() for each B channel
* parameters:
- * drv hardware driver the device belongs to
+ * drv hardware driver the device belongs to
* channels number of B channels supported by device
- * onechannel !=0: B channel data and AT commands share one communication channel
+ * onechannel !=0: B channel data and AT commands share one
+ * communication channel
* ==0: B channels have separate communication channels
* ignoreframes number of frames to ignore after setting up B channel
* cidmode !=0: start in CallID mode
@@ -593,17 +662,18 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
int cidmode, const char *modulename)
{
struct cardstate *cs = NULL;
+ unsigned long flags;
int i;
- dbg(DEBUG_INIT, "allocating cs");
+ gig_dbg(DEBUG_INIT, "allocating cs");
cs = alloc_cs(drv);
if (!cs)
goto error;
- dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
+ gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
if (!cs->bcs)
goto error;
- dbg(DEBUG_INIT, "allocating inbuf");
+ gig_dbg(DEBUG_INIT, "allocating inbuf");
cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL);
if (!cs->inbuf)
goto error;
@@ -613,19 +683,23 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
cs->onechannel = onechannel;
cs->ignoreframes = ignoreframes;
INIT_LIST_HEAD(&cs->temp_at_states);
- atomic_set(&cs->running, 0);
+ cs->running = 0;
init_timer(&cs->timer); /* clear next & prev */
spin_lock_init(&cs->ev_lock);
- atomic_set(&cs->ev_tail, 0);
- atomic_set(&cs->ev_head, 0);
- init_MUTEX_LOCKED(&cs->sem);
- tasklet_init(&cs->event_tasklet, &gigaset_handle_event, (unsigned long) cs);
+ cs->ev_tail = 0;
+ cs->ev_head = 0;
+ mutex_init(&cs->mutex);
+ mutex_lock(&cs->mutex);
+
+ tasklet_init(&cs->event_tasklet, &gigaset_handle_event,
+ (unsigned long) cs);
atomic_set(&cs->commands_pending, 0);
cs->cur_at_seq = 0;
cs->gotfwver = -1;
cs->open_count = 0;
+ cs->dev = NULL;
cs->tty = NULL;
- atomic_set(&cs->cidmode, cidmode != 0);
+ cs->cidmode = cidmode != 0;
//if(onechannel) { //FIXME
cs->tabnocid = gigaset_tab_nocid_m10x;
@@ -642,50 +716,43 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
atomic_set(&cs->mstate, MS_UNINITIALIZED);
for (i = 0; i < channels; ++i) {
- dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
+ gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
if (!gigaset_initbcs(cs->bcs + i, cs, i))
goto error;
}
++cs->cs_init;
- dbg(DEBUG_INIT, "setting up at_state");
+ gig_dbg(DEBUG_INIT, "setting up at_state");
spin_lock_init(&cs->lock);
gigaset_at_init(&cs->at_state, NULL, cs, 0);
cs->dle = 0;
cs->cbytes = 0;
- dbg(DEBUG_INIT, "setting up inbuf");
+ gig_dbg(DEBUG_INIT, "setting up inbuf");
if (onechannel) { //FIXME distinction necessary?
gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command);
} else
gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command);
- atomic_set(&cs->connected, 0);
+ cs->connected = 0;
+ cs->isdn_up = 0;
- dbg(DEBUG_INIT, "setting up cmdbuf");
+ gig_dbg(DEBUG_INIT, "setting up cmdbuf");
cs->cmdbuf = cs->lastcmdbuf = NULL;
spin_lock_init(&cs->cmdlock);
cs->curlen = 0;
cs->cmdbytes = 0;
- /*
- * Tell the ISDN4Linux subsystem (the LL) that
- * a driver for a USB-Device is available !
- * If this is done, "isdnctrl" is able to bind a device for this driver even
- * if no physical usb-device is currently connected.
- * But this device will just be accessable if a physical USB device is connected
- * (via "gigaset_probe") .
- */
- dbg(DEBUG_INIT, "setting up iif");
+ gig_dbg(DEBUG_INIT, "setting up iif");
if (!gigaset_register_to_LL(cs, modulename)) {
- err("register_isdn=>error");
+ err("register_isdn failed");
goto error;
}
make_valid(cs, VALID_ID);
++cs->cs_init;
- dbg(DEBUG_INIT, "setting up hw");
+ gig_dbg(DEBUG_INIT, "setting up hw");
if (!cs->ops->initcshw(cs))
goto error;
@@ -693,27 +760,28 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
gigaset_if_init(cs);
- atomic_set(&cs->running, 1);
- cs->timer.data = (unsigned long) cs;
- cs->timer.function = timer_tick;
- cs->timer.expires = jiffies + GIG_TICK;
+ spin_lock_irqsave(&cs->lock, flags);
+ cs->running = 1;
+ spin_unlock_irqrestore(&cs->lock, flags);
+ setup_timer(&cs->timer, timer_tick, (unsigned long) cs);
+ cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK);
/* FIXME: can jiffies increase too much until the timer is added?
* Same problem(?) with mod_timer() in timer_tick(). */
add_timer(&cs->timer);
- dbg(DEBUG_INIT, "cs initialized!");
- up(&cs->sem);
+ gig_dbg(DEBUG_INIT, "cs initialized");
+ mutex_unlock(&cs->mutex);
return cs;
error: if (cs)
- up(&cs->sem);
- dbg(DEBUG_INIT, "failed");
+ mutex_unlock(&cs->mutex);
+ gig_dbg(DEBUG_INIT, "failed");
gigaset_freecs(cs);
return NULL;
}
EXPORT_SYMBOL_GPL(gigaset_initcs);
-/* ReInitialize the b-channel structure */ /* e.g. called on hangup, disconnect */
+/* ReInitialize the b-channel structure on hangup */
void gigaset_bcs_reinit(struct bc_state *bcs)
{
struct sk_buff *skb;
@@ -723,12 +791,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs)
while ((skb = skb_dequeue(&bcs->squeue)) != NULL)
dev_kfree_skb(skb);
- spin_lock_irqsave(&cs->lock, flags); //FIXME
+ spin_lock_irqsave(&cs->lock, flags);
clear_at_state(&bcs->at_state);
bcs->at_state.ConState = 0;
bcs->at_state.timer_active = 0;
bcs->at_state.timer_expires = 0;
- bcs->at_state.cid = -1; /* No CID defined */
+ bcs->at_state.cid = -1; /* No CID defined */
spin_unlock_irqrestore(&cs->lock, flags);
bcs->inputstate = 0;
@@ -803,11 +871,14 @@ static void cleanup_cs(struct cardstate *cs)
int gigaset_start(struct cardstate *cs)
{
- if (down_interruptible(&cs->sem))
+ unsigned long flags;
+
+ if (mutex_lock_interruptible(&cs->mutex))
return 0;
- //info("USB device for Gigaset 307x now attached to Dev %d", ucs->minor);
- atomic_set(&cs->connected, 1);
+ spin_lock_irqsave(&cs->lock, flags);
+ cs->connected = 1;
+ spin_unlock_irqrestore(&cs->lock, flags);
if (atomic_read(&cs->mstate) != MS_LOCKED) {
cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
@@ -826,23 +897,26 @@ int gigaset_start(struct cardstate *cs)
goto error;
}
- dbg(DEBUG_CMD, "scheduling START");
+ gig_dbg(DEBUG_CMD, "scheduling START");
gigaset_schedule_event(cs);
wait_event(cs->waitqueue, !cs->waiting);
- up(&cs->sem);
+ /* set up device sysfs */
+ gigaset_init_dev_sysfs(cs);
+
+ mutex_unlock(&cs->mutex);
return 1;
error:
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return 0;
}
EXPORT_SYMBOL_GPL(gigaset_start);
void gigaset_shutdown(struct cardstate *cs)
{
- down(&cs->sem);
+ mutex_lock(&cs->mutex);
cs->waiting = 1;
@@ -851,11 +925,11 @@ void gigaset_shutdown(struct cardstate *cs)
goto exit;
}
- dbg(DEBUG_CMD, "scheduling SHUTDOWN");
+ gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN");
gigaset_schedule_event(cs);
if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
- warn("aborted");
+ warn("%s: aborted", __func__);
//FIXME
}
@@ -872,15 +946,13 @@ void gigaset_shutdown(struct cardstate *cs)
cleanup_cs(cs);
exit:
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
}
EXPORT_SYMBOL_GPL(gigaset_shutdown);
void gigaset_stop(struct cardstate *cs)
{
- down(&cs->sem);
-
- atomic_set(&cs->connected, 0);
+ mutex_lock(&cs->mutex);
cs->waiting = 1;
@@ -889,21 +961,21 @@ void gigaset_stop(struct cardstate *cs)
goto exit;
}
- dbg(DEBUG_CMD, "scheduling STOP");
+ gig_dbg(DEBUG_CMD, "scheduling STOP");
gigaset_schedule_event(cs);
if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
- warn("aborted");
+ warn("%s: aborted", __func__);
//FIXME
}
- /* Tell the LL that the device is not available .. */
- gigaset_i4l_cmd(cs, ISDN_STAT_STOP); // FIXME move to event layer?
+ /* clear device sysfs */
+ gigaset_free_dev_sysfs(cs);
cleanup_cs(cs);
exit:
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
}
EXPORT_SYMBOL_GPL(gigaset_stop);
@@ -947,31 +1019,25 @@ void gigaset_debugdrivers(void)
spin_lock_irqsave(&driver_lock, flags);
list_for_each_entry(drv, &drivers, list) {
- dbg(DEBUG_DRIVER, "driver %p", drv);
+ gig_dbg(DEBUG_DRIVER, "driver %p", drv);
spin_lock(&drv->lock);
for (i = 0; i < drv->minors; ++i) {
- dbg(DEBUG_DRIVER, " index %u", i);
- dbg(DEBUG_DRIVER, " flags 0x%02x", drv->flags[i]);
+ gig_dbg(DEBUG_DRIVER, " index %u", i);
+ gig_dbg(DEBUG_DRIVER, " flags 0x%02x",
+ drv->flags[i]);
cs = drv->cs + i;
- dbg(DEBUG_DRIVER, " cardstate %p", cs);
- dbg(DEBUG_DRIVER, " minor_index %u", cs->minor_index);
- dbg(DEBUG_DRIVER, " driver %p", cs->driver);
- dbg(DEBUG_DRIVER, " i4l id %d", cs->myid);
+ gig_dbg(DEBUG_DRIVER, " cardstate %p", cs);
+ gig_dbg(DEBUG_DRIVER, " minor_index %u",
+ cs->minor_index);
+ gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver);
+ gig_dbg(DEBUG_DRIVER, " i4l id %d", cs->myid);
}
spin_unlock(&drv->lock);
}
spin_unlock_irqrestore(&driver_lock, flags);
}
-EXPORT_SYMBOL_GPL(gigaset_debugdrivers);
-
-struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
-{
- if (tty->index < 0 || tty->index >= tty->driver->num)
- return NULL;
- return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
-}
-struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
+static struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
{
unsigned long flags;
static struct cardstate *ret = NULL;
@@ -994,6 +1060,13 @@ struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
return ret;
}
+struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
+{
+ if (tty->index < 0 || tty->index >= tty->driver->num)
+ return NULL;
+ return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
+}
+
void gigaset_freedriver(struct gigaset_driver *drv)
{
unsigned long flags;
@@ -1014,20 +1087,20 @@ EXPORT_SYMBOL_GPL(gigaset_freedriver);
/* gigaset_initdriver
* Allocate and initialize gigaset_driver structure. Initialize interface.
* parameters:
- * minor First minor number
- * minors Number of minors this driver can handle
- * procname Name of the driver (e.g. for /proc/tty/drivers, path in /proc/driver)
- * devname Name of the device files (prefix without minor number)
- * devfsname Devfs name of the device files without %d
+ * minor First minor number
+ * minors Number of minors this driver can handle
+ * procname Name of the driver
+ * devname Name of the device files (prefix without minor number)
+ * devfsname Devfs name of the device files without %d
* return value:
- * Pointer to the gigaset_driver structure on success, NULL on failure.
+ * Pointer to the gigaset_driver structure on success, NULL on failure.
*/
struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
- const char *procname,
- const char *devname,
- const char *devfsname,
- const struct gigaset_ops *ops,
- struct module *owner)
+ const char *procname,
+ const char *devname,
+ const char *devfsname,
+ const struct gigaset_ops *ops,
+ struct module *owner)
{
struct gigaset_driver *drv;
unsigned long flags;
@@ -1036,8 +1109,9 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
drv = kmalloc(sizeof *drv, GFP_KERNEL);
if (!drv)
return NULL;
+
if (!try_module_get(owner))
- return NULL;
+ goto out1;
drv->cs = NULL;
drv->have_tty = 0;
@@ -1051,10 +1125,11 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL);
if (!drv->cs)
- goto out1;
+ goto out2;
+
drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL);
if (!drv->flags)
- goto out2;
+ goto out3;
for (i = 0; i < minors; ++i) {
drv->flags[i] = 0;
@@ -1071,61 +1146,16 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
return drv;
-out2:
+out3:
kfree(drv->cs);
+out2:
+ module_put(owner);
out1:
kfree(drv);
- module_put(owner);
return NULL;
}
EXPORT_SYMBOL_GPL(gigaset_initdriver);
-static struct cardstate *alloc_cs(struct gigaset_driver *drv)
-{
- unsigned long flags;
- unsigned i;
- static struct cardstate *ret = NULL;
-
- spin_lock_irqsave(&drv->lock, flags);
- for (i = 0; i < drv->minors; ++i) {
- if (!(drv->flags[i] & VALID_MINOR)) {
- drv->flags[i] = VALID_MINOR;
- ret = drv->cs + i;
- }
- if (ret)
- break;
- }
- spin_unlock_irqrestore(&drv->lock, flags);
- return ret;
-}
-
-static void free_cs(struct cardstate *cs)
-{
- unsigned long flags;
- struct gigaset_driver *drv = cs->driver;
- spin_lock_irqsave(&drv->lock, flags);
- drv->flags[cs->minor_index] = 0;
- spin_unlock_irqrestore(&drv->lock, flags);
-}
-
-static void make_valid(struct cardstate *cs, unsigned mask)
-{
- unsigned long flags;
- struct gigaset_driver *drv = cs->driver;
- spin_lock_irqsave(&drv->lock, flags);
- drv->flags[cs->minor_index] |= mask;
- spin_unlock_irqrestore(&drv->lock, flags);
-}
-
-static void make_invalid(struct cardstate *cs, unsigned mask)
-{
- unsigned long flags;
- struct gigaset_driver *drv = cs->driver;
- spin_lock_irqsave(&drv->lock, flags);
- drv->flags[cs->minor_index] &= ~mask;
- spin_unlock_irqrestore(&drv->lock, flags);
-}
-
/* For drivers without fixed assignment device<->cardstate (usb) */
struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv)
{
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index fdcb80bb21c..18e05c09b71 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -1,7 +1,7 @@
/*
* Stuff used by all variants of the driver
*
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Copyright (c) 2001 by Stefan Eilers,
* Hansjoerg Lipp <hjlipp@web.de>,
* Tilman Schmidt <tilman@imap.cc>.
*
@@ -11,82 +11,78 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: ev-layer.c,v 1.4.2.18 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
/* ========================================================== */
/* bit masks for pending commands */
-#define PC_INIT 0x004
-#define PC_DLE0 0x008
-#define PC_DLE1 0x010
-#define PC_CID 0x080
-#define PC_NOCID 0x100
-#define PC_HUP 0x002
-#define PC_DIAL 0x001
-#define PC_ACCEPT 0x040
-#define PC_SHUTDOWN 0x020
-#define PC_CIDMODE 0x200
-#define PC_UMMODE 0x400
+#define PC_DIAL 0x001
+#define PC_HUP 0x002
+#define PC_INIT 0x004
+#define PC_DLE0 0x008
+#define PC_DLE1 0x010
+#define PC_SHUTDOWN 0x020
+#define PC_ACCEPT 0x040
+#define PC_CID 0x080
+#define PC_NOCID 0x100
+#define PC_CIDMODE 0x200
+#define PC_UMMODE 0x400
/* types of modem responses */
-#define RT_NOTHING 0
-#define RT_ZSAU 1
-#define RT_RING 2
-#define RT_NUMBER 3
-#define RT_STRING 4
-#define RT_HEX 5
-#define RT_ZCAU 6
+#define RT_NOTHING 0
+#define RT_ZSAU 1
+#define RT_RING 2
+#define RT_NUMBER 3
+#define RT_STRING 4
+#define RT_HEX 5
+#define RT_ZCAU 6
/* Possible ASCII responses */
-#define RSP_OK 0
-//#define RSP_BUSY 1
-//#define RSP_CONNECT 2
-#define RSP_ZGCI 3
-#define RSP_RING 4
-#define RSP_ZAOC 5
-#define RSP_ZCSTR 6
-#define RSP_ZCFGT 7
-#define RSP_ZCFG 8
-#define RSP_ZCCR 9
-#define RSP_EMPTY 10
-#define RSP_ZLOG 11
-#define RSP_ZCAU 12
-#define RSP_ZMWI 13
-#define RSP_ZABINFO 14
-#define RSP_ZSMLSTCHG 15
-#define RSP_VAR 100
-#define RSP_ZSAU (RSP_VAR + VAR_ZSAU)
-#define RSP_ZDLE (RSP_VAR + VAR_ZDLE)
-#define RSP_ZVLS (RSP_VAR + VAR_ZVLS)
-#define RSP_ZCTP (RSP_VAR + VAR_ZCTP)
-#define RSP_STR (RSP_VAR + VAR_NUM)
-#define RSP_NMBR (RSP_STR + STR_NMBR)
-#define RSP_ZCPN (RSP_STR + STR_ZCPN)
-#define RSP_ZCON (RSP_STR + STR_ZCON)
-#define RSP_ZBC (RSP_STR + STR_ZBC)
-#define RSP_ZHLC (RSP_STR + STR_ZHLC)
-#define RSP_ERROR -1 /* ERROR */
-#define RSP_WRONG_CID -2 /* unknown cid in cmd */
-//#define RSP_EMPTY -3
-#define RSP_UNKNOWN -4 /* unknown response */
-#define RSP_FAIL -5 /* internal error */
-#define RSP_INVAL -6 /* invalid response */
-
-#define RSP_NONE -19
-#define RSP_STRING -20
-#define RSP_NULL -21
-//#define RSP_RETRYFAIL -22
-//#define RSP_RETRY -23
-//#define RSP_SKIP -24
-#define RSP_INIT -27
-#define RSP_ANY -26
-#define RSP_LAST -28
-#define RSP_NODEV -9
+#define RSP_OK 0
+//#define RSP_BUSY 1
+//#define RSP_CONNECT 2
+#define RSP_ZGCI 3
+#define RSP_RING 4
+#define RSP_ZAOC 5
+#define RSP_ZCSTR 6
+#define RSP_ZCFGT 7
+#define RSP_ZCFG 8
+#define RSP_ZCCR 9
+#define RSP_EMPTY 10
+#define RSP_ZLOG 11
+#define RSP_ZCAU 12
+#define RSP_ZMWI 13
+#define RSP_ZABINFO 14
+#define RSP_ZSMLSTCHG 15
+#define RSP_VAR 100
+#define RSP_ZSAU (RSP_VAR + VAR_ZSAU)
+#define RSP_ZDLE (RSP_VAR + VAR_ZDLE)
+#define RSP_ZVLS (RSP_VAR + VAR_ZVLS)
+#define RSP_ZCTP (RSP_VAR + VAR_ZCTP)
+#define RSP_STR (RSP_VAR + VAR_NUM)
+#define RSP_NMBR (RSP_STR + STR_NMBR)
+#define RSP_ZCPN (RSP_STR + STR_ZCPN)
+#define RSP_ZCON (RSP_STR + STR_ZCON)
+#define RSP_ZBC (RSP_STR + STR_ZBC)
+#define RSP_ZHLC (RSP_STR + STR_ZHLC)
+#define RSP_ERROR -1 /* ERROR */
+#define RSP_WRONG_CID -2 /* unknown cid in cmd */
+//#define RSP_EMPTY -3
+#define RSP_UNKNOWN -4 /* unknown response */
+#define RSP_FAIL -5 /* internal error */
+#define RSP_INVAL -6 /* invalid response */
+
+#define RSP_NONE -19
+#define RSP_STRING -20
+#define RSP_NULL -21
+//#define RSP_RETRYFAIL -22
+//#define RSP_RETRY -23
+//#define RSP_SKIP -24
+#define RSP_INIT -27
+#define RSP_ANY -26
+#define RSP_LAST -28
+#define RSP_NODEV -9
/* actions for process_response */
#define ACT_NOTHING 0
@@ -112,7 +108,7 @@
#define ACT_DISCONNECT 20
#define ACT_CONNECT 21
#define ACT_REMOTEREJECT 22
-#define ACT_CONNTIMEOUT 23
+#define ACT_CONNTIMEOUT 23
#define ACT_REMOTEHUP 24
#define ACT_ABORTHUP 25
#define ACT_ICALL 26
@@ -127,40 +123,40 @@
#define ACT_ERROR 35
#define ACT_ABORTCID 36
#define ACT_ZCAU 37
-#define ACT_NOTIFY_BC_DOWN 38
-#define ACT_NOTIFY_BC_UP 39
-#define ACT_DIAL 40
-#define ACT_ACCEPT 41
-#define ACT_PROTO_L2 42
-#define ACT_HUP 43
-#define ACT_IF_LOCK 44
-#define ACT_START 45
-#define ACT_STOP 46
-#define ACT_FAKEDLE0 47
-#define ACT_FAKEHUP 48
-#define ACT_FAKESDOWN 49
-#define ACT_SHUTDOWN 50
-#define ACT_PROC_CIDMODE 51
-#define ACT_UMODESET 52
-#define ACT_FAILUMODE 53
-#define ACT_CMODESET 54
-#define ACT_FAILCMODE 55
-#define ACT_IF_VER 56
+#define ACT_NOTIFY_BC_DOWN 38
+#define ACT_NOTIFY_BC_UP 39
+#define ACT_DIAL 40
+#define ACT_ACCEPT 41
+#define ACT_PROTO_L2 42
+#define ACT_HUP 43
+#define ACT_IF_LOCK 44
+#define ACT_START 45
+#define ACT_STOP 46
+#define ACT_FAKEDLE0 47
+#define ACT_FAKEHUP 48
+#define ACT_FAKESDOWN 49
+#define ACT_SHUTDOWN 50
+#define ACT_PROC_CIDMODE 51
+#define ACT_UMODESET 52
+#define ACT_FAILUMODE 53
+#define ACT_CMODESET 54
+#define ACT_FAILCMODE 55
+#define ACT_IF_VER 56
#define ACT_CMD 100
/* at command sequences */
-#define SEQ_NONE 0
-#define SEQ_INIT 100
-#define SEQ_DLE0 200
-#define SEQ_DLE1 250
-#define SEQ_CID 300
-#define SEQ_NOCID 350
-#define SEQ_HUP 400
-#define SEQ_DIAL 600
-#define SEQ_ACCEPT 720
-#define SEQ_SHUTDOWN 500
-#define SEQ_CIDMODE 10
-#define SEQ_UMMODE 11
+#define SEQ_NONE 0
+#define SEQ_INIT 100
+#define SEQ_DLE0 200
+#define SEQ_DLE1 250
+#define SEQ_CID 300
+#define SEQ_NOCID 350
+#define SEQ_HUP 400
+#define SEQ_DIAL 600
+#define SEQ_ACCEPT 720
+#define SEQ_SHUTDOWN 500
+#define SEQ_CIDMODE 10
+#define SEQ_UMMODE 11
// 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring
@@ -175,7 +171,7 @@ struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */
// {ACT_TIMEOUT}},
{RSP_INIT, -1, -1,SEQ_INIT, 100, INIT_TIMEOUT,
- {ACT_TIMEOUT}}, /* wait until device is ready */
+ {ACT_TIMEOUT}}, /* wait until device is ready */
{EV_TIMEOUT, 100,100, -1, 101, 3, {0}, "Z\r"}, /* device in transparent mode? try to initialize it. */
{RSP_OK, 101,103, -1, 120, 5, {ACT_GETSTRING}, "+GMR\r"}, /* get version */
@@ -190,8 +186,8 @@ struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */
{RSP_ERROR, 108,108, -1, 0, 0, {ACT_FAILINIT}},
{EV_TIMEOUT, 108,108, -1, 105, 2, {ACT_SETDLE0,
- ACT_HUPMODEM,
- ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */
+ ACT_HUPMODEM,
+ ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */
{EV_TIMEOUT, 105,105, -1, 103, 5, {0}, "Z\r"},
{RSP_ERROR, 102,102, -1, 107, 5, {0}, "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */
@@ -377,6 +373,9 @@ struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */
{EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}},
+ /* B channel closed (general case) */
+ {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME
+
/* misc. */
{EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME
@@ -393,7 +392,7 @@ struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */
#if 0
-static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME aenderungen uebernehmen
+static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME
{
/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
@@ -401,7 +400,7 @@ static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME aenderungen ueberne
{RSP_LAST,0,0,0,0,0,0}
};
-static struct reply_t tab_cid[] = /* no dle mode */ //FIXME aenderungen uebernehmen
+static struct reply_t tab_cid[] = /* no dle mode */ //FIXME
{
/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
@@ -412,30 +411,30 @@ static struct reply_t tab_cid[] = /* no dle mode */ //FIXME aenderungen ueberneh
static struct resp_type_t resp_type[]=
{
- /*{"", RSP_EMPTY, RT_NOTHING},*/
- {"OK", RSP_OK, RT_NOTHING},
- {"ERROR", RSP_ERROR, RT_NOTHING},
- {"ZSAU", RSP_ZSAU, RT_ZSAU},
- {"ZCAU", RSP_ZCAU, RT_ZCAU},
- {"RING", RSP_RING, RT_RING},
- {"ZGCI", RSP_ZGCI, RT_NUMBER},
- {"ZVLS", RSP_ZVLS, RT_NUMBER},
- {"ZCTP", RSP_ZCTP, RT_NUMBER},
- {"ZDLE", RSP_ZDLE, RT_NUMBER},
- {"ZCFGT", RSP_ZCFGT, RT_NUMBER},
- {"ZCCR", RSP_ZCCR, RT_NUMBER},
- {"ZMWI", RSP_ZMWI, RT_NUMBER},
- {"ZHLC", RSP_ZHLC, RT_STRING},
- {"ZBC", RSP_ZBC, RT_STRING},
- {"NMBR", RSP_NMBR, RT_STRING},
- {"ZCPN", RSP_ZCPN, RT_STRING},
- {"ZCON", RSP_ZCON, RT_STRING},
- {"ZAOC", RSP_ZAOC, RT_STRING},
- {"ZCSTR", RSP_ZCSTR, RT_STRING},
- {"ZCFG", RSP_ZCFG, RT_HEX},
- {"ZLOG", RSP_ZLOG, RT_NOTHING},
- {"ZABINFO", RSP_ZABINFO, RT_NOTHING},
- {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING},
+ /*{"", RSP_EMPTY, RT_NOTHING},*/
+ {"OK", RSP_OK, RT_NOTHING},
+ {"ERROR", RSP_ERROR, RT_NOTHING},
+ {"ZSAU", RSP_ZSAU, RT_ZSAU},
+ {"ZCAU", RSP_ZCAU, RT_ZCAU},
+ {"RING", RSP_RING, RT_RING},
+ {"ZGCI", RSP_ZGCI, RT_NUMBER},
+ {"ZVLS", RSP_ZVLS, RT_NUMBER},
+ {"ZCTP", RSP_ZCTP, RT_NUMBER},
+ {"ZDLE", RSP_ZDLE, RT_NUMBER},
+ {"ZCFGT", RSP_ZCFGT, RT_NUMBER},
+ {"ZCCR", RSP_ZCCR, RT_NUMBER},
+ {"ZMWI", RSP_ZMWI, RT_NUMBER},
+ {"ZHLC", RSP_ZHLC, RT_STRING},
+ {"ZBC", RSP_ZBC, RT_STRING},
+ {"NMBR", RSP_NMBR, RT_STRING},
+ {"ZCPN", RSP_ZCPN, RT_STRING},
+ {"ZCON", RSP_ZCON, RT_STRING},
+ {"ZAOC", RSP_ZAOC, RT_STRING},
+ {"ZCSTR", RSP_ZCSTR, RT_STRING},
+ {"ZCFG", RSP_ZCFG, RT_HEX},
+ {"ZLOG", RSP_ZLOG, RT_NOTHING},
+ {"ZABINFO", RSP_ZABINFO, RT_NOTHING},
+ {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING},
{NULL,0,0}
};
@@ -446,9 +445,7 @@ static int isdn_getnum(char *p)
{
int v = -1;
- IFNULLRETVAL(p, -1);
-
- dbg(DEBUG_TRANSCMD, "string: %s", p);
+ gig_dbg(DEBUG_TRANSCMD, "string: %s", p);
while (*p >= '0' && *p <= '9')
v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0');
@@ -465,9 +462,7 @@ static int isdn_gethex(char *p)
int v = 0;
int c;
- IFNULLRETVAL(p, -1);
-
- dbg(DEBUG_TRANSCMD, "string: %s", p);
+ gig_dbg(DEBUG_TRANSCMD, "string: %s", p);
if (!*p)
return -1;
@@ -490,14 +485,6 @@ static int isdn_gethex(char *p)
return v;
}
-static inline void new_index(atomic_t *index, int max)
-{
- if (atomic_read(index) == max) //FIXME race?
- atomic_set(index, 0);
- else
- atomic_inc(index);
-}
-
/* retrieve CID from parsed response
* returns 0 if no CID, -1 if invalid CID, or CID value 1..65535
*/
@@ -536,16 +523,14 @@ void gigaset_handle_modem_response(struct cardstate *cs)
int cid;
int rawstring;
- IFNULLRET(cs);
-
len = cs->cbytes;
if (!len) {
/* ignore additional LFs/CRs (M10x config mode or cx100) */
- dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]);
+ gig_dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]);
return;
}
cs->respdata[len] = 0;
- dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata);
+ gig_dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata);
argv[0] = cs->respdata;
params = 1;
if (cs->at_state.getstring) {
@@ -561,7 +546,8 @@ void gigaset_handle_modem_response(struct cardstate *cs)
case ',':
case '=':
if (params > MAX_REC_PARAMS) {
- warn("too many parameters in response");
+ dev_warn(cs->dev,
+ "too many parameters in response\n");
/* need last parameter (might be CID) */
params--;
}
@@ -572,33 +558,33 @@ void gigaset_handle_modem_response(struct cardstate *cs)
cid = params > 1 ? cid_of_response(argv[params-1]) : 0;
if (cid < 0) {
gigaset_add_event(cs, &cs->at_state, RSP_INVAL,
- NULL, 0, NULL);
+ NULL, 0, NULL);
return;
}
for (j = 1; j < params; ++j)
argv[j][-1] = 0;
- dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]);
+ gig_dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]);
if (cid) {
--params;
- dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]);
+ gig_dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]);
}
- dbg(DEBUG_TRANSCMD, "available params: %d", params - 1);
+ gig_dbg(DEBUG_TRANSCMD, "available params: %d", params - 1);
for (j = 1; j < params; j++)
- dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]);
+ gig_dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]);
}
spin_lock_irqsave(&cs->ev_lock, flags);
- head = atomic_read(&cs->ev_head);
- tail = atomic_read(&cs->ev_tail);
+ head = cs->ev_head;
+ tail = cs->ev_tail;
abort = 1;
curarg = 0;
while (curarg < params) {
next = (tail + 1) % MAX_EVENTS;
if (unlikely(next == head)) {
- err("event queue full");
+ dev_err(cs->dev, "event queue full\n");
break;
}
@@ -619,8 +605,9 @@ void gigaset_handle_modem_response(struct cardstate *cs)
if (!rt->response) {
event->type = RSP_UNKNOWN;
- warn("unknown modem response: %s",
- argv[curarg]);
+ dev_warn(cs->dev,
+ "unknown modem response: %s\n",
+ argv[curarg]);
break;
}
@@ -636,7 +623,8 @@ void gigaset_handle_modem_response(struct cardstate *cs)
break;
case RT_RING:
if (!cid) {
- err("received RING without CID!");
+ dev_err(cs->dev,
+ "received RING without CID!\n");
event->type = RSP_INVAL;
abort = 1;
} else {
@@ -664,27 +652,25 @@ void gigaset_handle_modem_response(struct cardstate *cs)
event->parameter = ZSAU_DISCONNECT_REQ;
else {
event->parameter = ZSAU_UNKNOWN;
- warn("%s: unknown parameter %s after ZSAU",
- __func__, argv[curarg]);
+ dev_warn(cs->dev,
+ "%s: unknown parameter %s after ZSAU\n",
+ __func__, argv[curarg]);
}
++curarg;
break;
case RT_STRING:
if (curarg < params) {
- len = strlen(argv[curarg]) + 1;
- event->ptr = kmalloc(len, GFP_ATOMIC);
- if (event->ptr)
- memcpy(event->ptr, argv[curarg], len);
- else
- err("no memory for string!");
+ event->ptr = kstrdup(argv[curarg], GFP_ATOMIC);
+ if (!event->ptr)
+ dev_err(cs->dev, "out of memory\n");
++curarg;
}
#ifdef CONFIG_GIGASET_DEBUG
if (!event->ptr)
- dbg(DEBUG_CMD, "string==NULL");
+ gig_dbg(DEBUG_CMD, "string==NULL");
else
- dbg(DEBUG_CMD,
- "string==%s", (char *) event->ptr);
+ gig_dbg(DEBUG_CMD, "string==%s",
+ (char *) event->ptr);
#endif
break;
case RT_ZCAU:
@@ -694,7 +680,7 @@ void gigaset_handle_modem_response(struct cardstate *cs)
j = isdn_gethex(argv[curarg + 1]);
if (i >= 0 && i < 256 && j >= 0 && j < 256)
event->parameter = (unsigned) i << 8
- | j;
+ | j;
curarg += 2;
} else
curarg = params - 1;
@@ -712,7 +698,7 @@ void gigaset_handle_modem_response(struct cardstate *cs)
} else
event->parameter = -1;
#ifdef CONFIG_GIGASET_DEBUG
- dbg(DEBUG_CMD, "parameter==%d", event->parameter);
+ gig_dbg(DEBUG_CMD, "parameter==%d", event->parameter);
#endif
break;
}
@@ -724,12 +710,13 @@ void gigaset_handle_modem_response(struct cardstate *cs)
break;
}
- atomic_set(&cs->ev_tail, tail);
+ cs->ev_tail = tail;
spin_unlock_irqrestore(&cs->ev_lock, flags);
if (curarg != params)
- dbg(DEBUG_ANY, "invalid number of processed parameters: %d/%d",
- curarg, params);
+ gig_dbg(DEBUG_ANY,
+ "invalid number of processed parameters: %d/%d",
+ curarg, params);
}
EXPORT_SYMBOL_GPL(gigaset_handle_modem_response);
@@ -739,23 +726,19 @@ EXPORT_SYMBOL_GPL(gigaset_handle_modem_response);
static void disconnect(struct at_state_t **at_state_p)
{
unsigned long flags;
- struct bc_state *bcs;
- struct cardstate *cs;
-
- IFNULLRET(at_state_p);
- IFNULLRET(*at_state_p);
- bcs = (*at_state_p)->bcs;
- cs = (*at_state_p)->cs;
- IFNULLRET(cs);
+ struct bc_state *bcs = (*at_state_p)->bcs;
+ struct cardstate *cs = (*at_state_p)->cs;
- new_index(&(*at_state_p)->seq_index, MAX_SEQ_INDEX);
+ spin_lock_irqsave(&cs->lock, flags);
+ ++(*at_state_p)->seq_index;
/* revert to selected idle mode */
- if (!atomic_read(&cs->cidmode)) {
+ if (!cs->cidmode) {
cs->at_state.pending_commands |= PC_UMMODE;
atomic_set(&cs->commands_pending, 1); //FIXME
- dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
+ gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
}
+ spin_unlock_irqrestore(&cs->lock, flags);
if (bcs) {
/* B channel assigned: invoke hardware specific handler */
@@ -777,7 +760,7 @@ static void disconnect(struct at_state_t **at_state_p)
* The structure should be freed by calling disconnect() after use.
*/
static inline struct at_state_t *get_free_channel(struct cardstate *cs,
- int cid)
+ int cid)
/* cids: >0: siemens-cid
0: without cid
-1: no cid assigned yet
@@ -826,7 +809,7 @@ static void init_failed(struct cardstate *cs, int mode)
static void schedule_init(struct cardstate *cs, int state)
{
if (cs->at_state.pending_commands & PC_INIT) {
- dbg(DEBUG_CMD, "not scheduling PC_INIT again");
+ gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again");
return;
}
atomic_set(&cs->mstate, state);
@@ -834,52 +817,56 @@ static void schedule_init(struct cardstate *cs, int state)
gigaset_block_channels(cs);
cs->at_state.pending_commands |= PC_INIT;
atomic_set(&cs->commands_pending, 1);
- dbg(DEBUG_CMD, "Scheduling PC_INIT");
+ gig_dbg(DEBUG_CMD, "Scheduling PC_INIT");
}
-/* Add "AT" to a command, add the cid, dle encode it, send the result to the hardware. */
+/* Add "AT" to a command, add the cid, dle encode it, send the result to the
+ hardware. */
static void send_command(struct cardstate *cs, const char *cmd, int cid,
- int dle, gfp_t kmallocflags)
+ int dle, gfp_t kmallocflags)
{
size_t cmdlen, buflen;
char *cmdpos, *cmdbuf, *cmdtail;
cmdlen = strlen(cmd);
buflen = 11 + cmdlen;
+ if (unlikely(buflen <= cmdlen)) {
+ dev_err(cs->dev, "integer overflow in buflen\n");
+ return;
+ }
- if (likely(buflen > cmdlen)) {
- cmdbuf = kmalloc(buflen, kmallocflags);
- if (likely(cmdbuf != NULL)) {
- cmdpos = cmdbuf + 9;
- cmdtail = cmdpos + cmdlen;
- memcpy(cmdpos, cmd, cmdlen);
-
- if (cid > 0 && cid <= 65535) {
- do {
- *--cmdpos = '0' + cid % 10;
- cid /= 10;
- ++cmdlen;
- } while (cid);
- }
+ cmdbuf = kmalloc(buflen, kmallocflags);
+ if (unlikely(!cmdbuf)) {
+ dev_err(cs->dev, "out of memory\n");
+ return;
+ }
- cmdlen += 2;
- *--cmdpos = 'T';
- *--cmdpos = 'A';
+ cmdpos = cmdbuf + 9;
+ cmdtail = cmdpos + cmdlen;
+ memcpy(cmdpos, cmd, cmdlen);
- if (dle) {
- cmdlen += 4;
- *--cmdpos = '(';
- *--cmdpos = 0x10;
- *cmdtail++ = 0x10;
- *cmdtail++ = ')';
- }
+ if (cid > 0 && cid <= 65535) {
+ do {
+ *--cmdpos = '0' + cid % 10;
+ cid /= 10;
+ ++cmdlen;
+ } while (cid);
+ }
- cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL);
- kfree(cmdbuf);
- } else
- err("no memory for command buffer");
- } else
- err("overflow in buflen");
+ cmdlen += 2;
+ *--cmdpos = 'T';
+ *--cmdpos = 'A';
+
+ if (dle) {
+ cmdlen += 4;
+ *--cmdpos = '(';
+ *--cmdpos = 0x10;
+ *cmdtail++ = 0x10;
+ *cmdtail++ = ')';
+ }
+
+ cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL);
+ kfree(cmdbuf);
}
static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid)
@@ -910,9 +897,6 @@ static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid)
static void bchannel_down(struct bc_state *bcs)
{
- IFNULLRET(bcs);
- IFNULLRET(bcs->cs);
-
if (bcs->chstate & CHS_B_UP) {
bcs->chstate &= ~CHS_B_UP;
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP);
@@ -930,16 +914,15 @@ static void bchannel_down(struct bc_state *bcs)
static void bchannel_up(struct bc_state *bcs)
{
- IFNULLRET(bcs);
-
if (!(bcs->chstate & CHS_D_UP)) {
- notice("%s: D channel not up", __func__);
+ dev_notice(bcs->cs->dev, "%s: D channel not up\n", __func__);
bcs->chstate |= CHS_D_UP;
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
}
if (bcs->chstate & CHS_B_UP) {
- notice("%s: B channel already up", __func__);
+ dev_notice(bcs->cs->dev, "%s: B channel already up\n",
+ __func__);
return;
}
@@ -947,17 +930,21 @@ static void bchannel_up(struct bc_state *bcs)
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN);
}
-static void start_dial(struct at_state_t *at_state, void *data, int seq_index)
+static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index)
{
struct bc_state *bcs = at_state->bcs;
struct cardstate *cs = at_state->cs;
int retval;
+ unsigned long flags;
bcs->chstate |= CHS_NOTIFY_LL;
- //atomic_set(&bcs->status, BCS_INIT);
- if (atomic_read(&at_state->seq_index) != seq_index)
+ spin_lock_irqsave(&cs->lock, flags);
+ if (at_state->seq_index != seq_index) {
+ spin_unlock_irqrestore(&cs->lock, flags);
goto error;
+ }
+ spin_unlock_irqrestore(&cs->lock, flags);
retval = gigaset_isdn_setup_dial(at_state, data);
if (retval != 0)
@@ -965,20 +952,14 @@ static void start_dial(struct at_state_t *at_state, void *data, int seq_index)
at_state->pending_commands |= PC_CID;
- dbg(DEBUG_CMD, "Scheduling PC_CID");
-//#ifdef GIG_MAYINITONDIAL
-// if (atomic_read(&cs->MState) == MS_UNKNOWN) {
-// cs->at_state.pending_commands |= PC_INIT;
-// dbg(DEBUG_CMD, "Scheduling PC_INIT");
-// }
-//#endif
- atomic_set(&cs->commands_pending, 1); //FIXME
+ gig_dbg(DEBUG_CMD, "Scheduling PC_CID");
+ atomic_set(&cs->commands_pending, 1);
return;
error:
at_state->pending_commands |= PC_NOCID;
- dbg(DEBUG_CMD, "Scheduling PC_NOCID");
- atomic_set(&cs->commands_pending, 1); //FIXME
+ gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID");
+ atomic_set(&cs->commands_pending, 1);
return;
}
@@ -991,13 +972,13 @@ static void start_accept(struct at_state_t *at_state)
if (retval == 0) {
at_state->pending_commands |= PC_ACCEPT;
- dbg(DEBUG_CMD, "Scheduling PC_ACCEPT");
- atomic_set(&cs->commands_pending, 1); //FIXME
+ gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT");
+ atomic_set(&cs->commands_pending, 1);
} else {
//FIXME
at_state->pending_commands |= PC_HUP;
- dbg(DEBUG_CMD, "Scheduling PC_HUP");
- atomic_set(&cs->commands_pending, 1); //FIXME
+ gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
+ atomic_set(&cs->commands_pending, 1);
}
}
@@ -1008,9 +989,10 @@ static void do_start(struct cardstate *cs)
if (atomic_read(&cs->mstate) != MS_LOCKED)
schedule_init(cs, MS_INIT);
+ cs->isdn_up = 1;
gigaset_i4l_cmd(cs, ISDN_STAT_RUN);
- // FIXME: not in locked mode
- // FIXME 2: only after init sequence
+ // FIXME: not in locked mode
+ // FIXME 2: only after init sequence
cs->waiting = 0;
wake_up(&cs->waitqueue);
@@ -1023,6 +1005,12 @@ static void finish_shutdown(struct cardstate *cs)
atomic_set(&cs->mode, M_UNKNOWN);
}
+ /* Tell the LL that the device is not available .. */
+ if (cs->isdn_up) {
+ cs->isdn_up = 0;
+ gigaset_i4l_cmd(cs, ISDN_STAT_STOP);
+ }
+
/* The rest is done by cleanup_cs () in user mode. */
cs->cmd_result = -ENODEV;
@@ -1037,15 +1025,20 @@ static void do_shutdown(struct cardstate *cs)
if (atomic_read(&cs->mstate) == MS_READY) {
atomic_set(&cs->mstate, MS_SHUTDOWN);
cs->at_state.pending_commands |= PC_SHUTDOWN;
- atomic_set(&cs->commands_pending, 1); //FIXME
- dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); //FIXME
- //gigaset_schedule_event(cs); //FIXME
+ atomic_set(&cs->commands_pending, 1);
+ gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN");
} else
finish_shutdown(cs);
}
static void do_stop(struct cardstate *cs)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cs->lock, flags);
+ cs->connected = 0;
+ spin_unlock_irqrestore(&cs->lock, flags);
+
do_shutdown(cs);
}
@@ -1069,9 +1062,11 @@ static int reinit_and_retry(struct cardstate *cs, int channel)
return 0;
if (channel < 0)
- warn("Could not enter cid mode. Reinit device and try again.");
+ dev_warn(cs->dev,
+ "Could not enter cid mode. Reinit device and try again.\n");
else {
- warn("Could not get a call id. Reinit device and try again.");
+ dev_warn(cs->dev,
+ "Could not get a call id. Reinit device and try again.\n");
cs->bcs[channel].at_state.pending_commands |= PC_CID;
}
schedule_init(cs, MS_INIT);
@@ -1079,7 +1074,7 @@ static int reinit_and_retry(struct cardstate *cs, int channel)
}
static int at_state_invalid(struct cardstate *cs,
- struct at_state_t *test_ptr)
+ struct at_state_t *test_ptr)
{
unsigned long flags;
unsigned channel;
@@ -1116,7 +1111,7 @@ static void handle_icall(struct cardstate *cs, struct bc_state *bcs,
case ICALL_ACCEPT:
break;
default:
- err("internal error: disposition=%d", retval);
+ dev_err(cs->dev, "internal error: disposition=%d\n", retval);
/* --v-- fall through --v-- */
case ICALL_IGNORE:
case ICALL_REJECT:
@@ -1160,7 +1155,6 @@ static int do_lock(struct cardstate *cs)
mode = atomic_read(&cs->mode);
atomic_set(&cs->mstate, MS_LOCKED);
atomic_set(&cs->mode, M_UNKNOWN);
- //FIXME reset card state / at states / bcs states
return mode;
}
@@ -1173,8 +1167,7 @@ static int do_unlock(struct cardstate *cs)
atomic_set(&cs->mstate, MS_UNINITIALIZED);
atomic_set(&cs->mode, M_UNKNOWN);
gigaset_free_channels(cs);
- //FIXME reset card state / at states / bcs states
- if (atomic_read(&cs->connected))
+ if (cs->connected)
schedule_init(cs, MS_INIT);
return 0;
@@ -1203,21 +1196,23 @@ static void do_action(int action, struct cardstate *cs,
at_state->waiting = 1;
break;
case ACT_INIT:
- //FIXME setup everything
cs->at_state.pending_commands &= ~PC_INIT;
cs->cur_at_seq = SEQ_NONE;
atomic_set(&cs->mode, M_UNIMODEM);
- if (!atomic_read(&cs->cidmode)) {
+ spin_lock_irqsave(&cs->lock, flags);
+ if (!cs->cidmode) {
+ spin_unlock_irqrestore(&cs->lock, flags);
gigaset_free_channels(cs);
atomic_set(&cs->mstate, MS_READY);
break;
}
+ spin_unlock_irqrestore(&cs->lock, flags);
cs->at_state.pending_commands |= PC_CIDMODE;
- atomic_set(&cs->commands_pending, 1); //FIXME
- dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
+ atomic_set(&cs->commands_pending, 1);
+ gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
break;
case ACT_FAILINIT:
- warn("Could not initialize the device.");
+ dev_warn(cs->dev, "Could not initialize the device.\n");
cs->dle = 0;
init_failed(cs, M_UNKNOWN);
cs->cur_at_seq = SEQ_NONE;
@@ -1273,8 +1268,8 @@ static void do_action(int action, struct cardstate *cs,
/* get fresh AT state structure for new CID */
at_state2 = get_free_channel(cs, ev->parameter);
if (!at_state2) {
- warn("RING ignored: "
- "could not allocate channel structure");
+ dev_warn(cs->dev,
+ "RING ignored: could not allocate channel structure\n");
break;
}
@@ -1302,7 +1297,7 @@ static void do_action(int action, struct cardstate *cs,
at_state = *p_at_state;
break;
case ACT_FAILSDOWN:
- warn("Could not shut down the device.");
+ dev_warn(cs->dev, "Could not shut down the device.\n");
/* fall through */
case ACT_FAKESDOWN:
case ACT_SDOWN:
@@ -1355,7 +1350,7 @@ static void do_action(int action, struct cardstate *cs,
break;
case ACT_ABORTHUP:
cs->cur_at_seq = SEQ_NONE;
- warn("Could not hang up.");
+ dev_warn(cs->dev, "Could not hang up.\n");
at_state->cid = -1;
if (bcs && cs->onechannel)
at_state->pending_commands |= PC_DLE0;
@@ -1367,14 +1362,15 @@ static void do_action(int action, struct cardstate *cs,
break;
case ACT_FAILDLE0:
cs->cur_at_seq = SEQ_NONE;
- warn("Could not leave DLE mode.");
+ dev_warn(cs->dev, "Could not leave DLE mode.\n");
at_state2 = &cs->bcs[cs->curchannel].at_state;
disconnect(&at_state2);
schedule_init(cs, MS_RECOVER);
break;
case ACT_FAILDLE1:
cs->cur_at_seq = SEQ_NONE;
- warn("Could not enter DLE mode. Try to hang up.");
+ dev_warn(cs->dev,
+ "Could not enter DLE mode. Trying to hang up.\n");
channel = cs->curchannel;
cs->bcs[channel].at_state.pending_commands |= PC_HUP;
atomic_set(&cs->commands_pending, 1);
@@ -1395,7 +1391,8 @@ static void do_action(int action, struct cardstate *cs,
cs->cur_at_seq = SEQ_NONE;
channel = cs->curchannel;
if (!reinit_and_retry(cs, channel)) {
- warn("Could not get a call id. Dialing not possible");
+ dev_warn(cs->dev,
+ "Could not get a call ID. Cannot dial.\n");
at_state2 = &cs->bcs[channel].at_state;
disconnect(&at_state2);
}
@@ -1428,7 +1425,8 @@ static void do_action(int action, struct cardstate *cs,
at_state->pending_commands |= PC_HUP;
atomic_set(&cs->commands_pending, 1);
break;
- case ACT_GETSTRING: /* warning: RING, ZDLE, ... are not handled properly any more */
+ case ACT_GETSTRING: /* warning: RING, ZDLE, ...
+ are not handled properly anymore */
at_state->getstring = 1;
break;
case ACT_SETVER:
@@ -1469,16 +1467,16 @@ static void do_action(int action, struct cardstate *cs,
case ACT_GOTVER:
if (cs->gotfwver == 0) {
cs->gotfwver = 1;
- dbg(DEBUG_ANY,
- "firmware version %02d.%03d.%02d.%02d",
- cs->fwver[0], cs->fwver[1],
- cs->fwver[2], cs->fwver[3]);
+ gig_dbg(DEBUG_ANY,
+ "firmware version %02d.%03d.%02d.%02d",
+ cs->fwver[0], cs->fwver[1],
+ cs->fwver[2], cs->fwver[3]);
break;
}
/* fall through */
case ACT_FAILVER:
cs->gotfwver = -1;
- err("could not read firmware version.");
+ dev_err(cs->dev, "could not read firmware version.\n");
break;
#ifdef CONFIG_GIGASET_DEBUG
case ACT_ERROR:
@@ -1496,16 +1494,16 @@ static void do_action(int action, struct cardstate *cs,
break;
#endif
case ACT_DEBUG:
- dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d",
+ gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d",
__func__, ev->type, at_state->ConState);
break;
case ACT_WARN:
- warn("%s: resp_code %d in ConState %d!",
- __func__, ev->type, at_state->ConState);
+ dev_warn(cs->dev, "%s: resp_code %d in ConState %d!\n",
+ __func__, ev->type, at_state->ConState);
break;
case ACT_ZCAU:
- warn("cause code %04x in connection state %d.",
- ev->parameter, at_state->ConState);
+ dev_warn(cs->dev, "cause code %04x in connection state %d.\n",
+ ev->parameter, at_state->ConState);
break;
/* events from the LL */
@@ -1516,14 +1514,14 @@ static void do_action(int action, struct cardstate *cs,
start_accept(at_state);
break;
case ACT_PROTO_L2:
- dbg(DEBUG_CMD,
- "set protocol to %u", (unsigned) ev->parameter);
+ gig_dbg(DEBUG_CMD, "set protocol to %u",
+ (unsigned) ev->parameter);
at_state->bcs->proto2 = ev->parameter;
break;
case ACT_HUP:
at_state->pending_commands |= PC_HUP;
- atomic_set(&cs->commands_pending, 1); //FIXME
- dbg(DEBUG_CMD, "Scheduling PC_HUP");
+ atomic_set(&cs->commands_pending, 1);
+ gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
break;
/* hotplug events */
@@ -1555,17 +1553,19 @@ static void do_action(int action, struct cardstate *cs,
/* events from the proc file system */ // FIXME without ACT_xxxx?
case ACT_PROC_CIDMODE:
- if (ev->parameter != atomic_read(&cs->cidmode)) {
- atomic_set(&cs->cidmode, ev->parameter);
+ spin_lock_irqsave(&cs->lock, flags);
+ if (ev->parameter != cs->cidmode) {
+ cs->cidmode = ev->parameter;
if (ev->parameter) {
cs->at_state.pending_commands |= PC_CIDMODE;
- dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
+ gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
} else {
cs->at_state.pending_commands |= PC_UMMODE;
- dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
+ gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
}
atomic_set(&cs->commands_pending, 1);
}
+ spin_unlock_irqrestore(&cs->lock, flags);
cs->waiting = 0;
wake_up(&cs->waitqueue);
break;
@@ -1590,7 +1590,7 @@ static void do_action(int action, struct cardstate *cs,
*p_resp_code = RSP_NULL;
}
} else
- err("%s: action==%d!", __func__, action);
+ dev_err(cs->dev, "%s: action==%d!\n", __func__, action);
}
}
@@ -1609,47 +1609,46 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
int curact;
unsigned long flags;
- IFNULLRET(cs);
- IFNULLRET(ev);
-
if (ev->cid >= 0) {
at_state = at_state_from_cid(cs, ev->cid);
if (!at_state) {
gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID,
- NULL, 0, NULL);
+ NULL, 0, NULL);
return;
}
} else {
at_state = ev->at_state;
if (at_state_invalid(cs, at_state)) {
- dbg(DEBUG_ANY,
- "event for invalid at_state %p", at_state);
+ gig_dbg(DEBUG_ANY, "event for invalid at_state %p",
+ at_state);
return;
}
}
- dbg(DEBUG_CMD,
- "connection state %d, event %d", at_state->ConState, ev->type);
+ gig_dbg(DEBUG_CMD, "connection state %d, event %d",
+ at_state->ConState, ev->type);
bcs = at_state->bcs;
sendcid = at_state->cid;
/* Setting the pointer to the dial array */
rep = at_state->replystruct;
- IFNULLRET(rep);
+ spin_lock_irqsave(&cs->lock, flags);
if (ev->type == EV_TIMEOUT) {
- if (ev->parameter != atomic_read(&at_state->timer_index)
+ if (ev->parameter != at_state->timer_index
|| !at_state->timer_active) {
ev->type = RSP_NONE; /* old timeout */
- dbg(DEBUG_ANY, "old timeout");
+ gig_dbg(DEBUG_ANY, "old timeout");
} else if (!at_state->waiting)
- dbg(DEBUG_ANY, "timeout occured");
+ gig_dbg(DEBUG_ANY, "timeout occurred");
else
- dbg(DEBUG_ANY, "stopped waiting");
+ gig_dbg(DEBUG_ANY, "stopped waiting");
}
+ spin_unlock_irqrestore(&cs->lock, flags);
- /* if the response belongs to a variable in at_state->int_var[VAR_XXXX] or at_state->str_var[STR_XXXX], set it */
+ /* if the response belongs to a variable in at_state->int_var[VAR_XXXX]
+ or at_state->str_var[STR_XXXX], set it */
if (ev->type >= RSP_VAR && ev->type < RSP_VAR + VAR_NUM) {
index = ev->type - RSP_VAR;
at_state->int_var[index] = ev->parameter;
@@ -1657,20 +1656,22 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
index = ev->type - RSP_STR;
kfree(at_state->str_var[index]);
at_state->str_var[index] = ev->ptr;
- ev->ptr = NULL; /* prevent process_events() from deallocating ptr */
+ ev->ptr = NULL; /* prevent process_events() from
+ deallocating ptr */
}
if (ev->type == EV_TIMEOUT || ev->type == RSP_STRING)
at_state->getstring = 0;
- /* Search row in dial array which matches modem response and current constate */
+ /* Search row in dial array which matches modem response and current
+ constate */
for (;; rep++) {
rcode = rep->resp_code;
- /* dbg (DEBUG_ANY, "rcode %d", rcode); */
if (rcode == RSP_LAST) {
/* found nothing...*/
- warn("%s: rcode=RSP_LAST: resp_code %d in ConState %d!",
- __func__, ev->type, at_state->ConState);
+ dev_warn(cs->dev, "%s: rcode=RSP_LAST: "
+ "resp_code %d in ConState %d!\n",
+ __func__, ev->type, at_state->ConState);
return;
}
if ((rcode == RSP_ANY || rcode == ev->type)
@@ -1706,14 +1707,14 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
} else {
/* Send command to modem if not NULL... */
if (p_command/*rep->command*/) {
- if (atomic_read(&cs->connected))
+ if (cs->connected)
send_command(cs, p_command,
- sendcid, cs->dle,
- GFP_ATOMIC);
+ sendcid, cs->dle,
+ GFP_ATOMIC);
else
gigaset_add_event(cs, at_state,
- RSP_NODEV,
- NULL, 0, NULL);
+ RSP_NODEV,
+ NULL, 0, NULL);
}
spin_lock_irqsave(&cs->lock, flags);
@@ -1723,8 +1724,7 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
} else if (rep->timeout > 0) { /* new timeout */
at_state->timer_expires = rep->timeout * 10;
at_state->timer_active = 1;
- new_index(&at_state->timer_index,
- MAX_TIMER_INDEX);
+ ++at_state->timer_index;
}
spin_unlock_irqrestore(&cs->lock, flags);
}
@@ -1744,17 +1744,16 @@ static void process_command_flags(struct cardstate *cs)
struct bc_state *bcs;
int i;
int sequence;
-
- IFNULLRET(cs);
+ unsigned long flags;
atomic_set(&cs->commands_pending, 0);
if (cs->cur_at_seq) {
- dbg(DEBUG_CMD, "not searching scheduled commands: busy");
+ gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy");
return;
}
- dbg(DEBUG_CMD, "searching scheduled commands");
+ gig_dbg(DEBUG_CMD, "searching scheduled commands");
sequence = SEQ_NONE;
@@ -1795,8 +1794,9 @@ static void process_command_flags(struct cardstate *cs)
}
/* only switch back to unimodem mode, if no commands are pending and no channels are up */
+ spin_lock_irqsave(&cs->lock, flags);
if (cs->at_state.pending_commands == PC_UMMODE
- && !atomic_read(&cs->cidmode)
+ && !cs->cidmode
&& list_empty(&cs->temp_at_states)
&& atomic_read(&cs->mode) == M_CID) {
sequence = SEQ_UMMODE;
@@ -1810,6 +1810,7 @@ static void process_command_flags(struct cardstate *cs)
}
}
}
+ spin_unlock_irqrestore(&cs->lock, flags);
cs->at_state.pending_commands &= ~PC_UMMODE;
if (sequence != SEQ_NONE) {
schedule_sequence(cs, at_state, sequence);
@@ -1865,11 +1866,7 @@ static void process_command_flags(struct cardstate *cs)
if (cs->at_state.pending_commands & PC_CIDMODE) {
cs->at_state.pending_commands &= ~PC_CIDMODE;
if (atomic_read(&cs->mode) == M_UNIMODEM) {
-#if 0
- cs->retry_count = 2;
-#else
cs->retry_count = 1;
-#endif
schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE);
return;
}
@@ -1897,7 +1894,7 @@ static void process_command_flags(struct cardstate *cs)
switch (atomic_read(&cs->mode)) {
case M_UNIMODEM:
cs->at_state.pending_commands |= PC_CIDMODE;
- dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
+ gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
atomic_set(&cs->commands_pending, 1);
return;
#ifdef GIG_MAYINITONDIAL
@@ -1926,18 +1923,21 @@ static void process_events(struct cardstate *cs)
int i;
int check_flags = 0;
int was_busy;
+ unsigned long flags;
- /* no locking needed (only one reader) */
- head = atomic_read(&cs->ev_head);
+ spin_lock_irqsave(&cs->ev_lock, flags);
+ head = cs->ev_head;
for (i = 0; i < 2 * MAX_EVENTS; ++i) {
- tail = atomic_read(&cs->ev_tail);
+ tail = cs->ev_tail;
if (tail == head) {
if (!check_flags && !atomic_read(&cs->commands_pending))
break;
check_flags = 0;
+ spin_unlock_irqrestore(&cs->ev_lock, flags);
process_command_flags(cs);
- tail = atomic_read(&cs->ev_tail);
+ spin_lock_irqsave(&cs->ev_lock, flags);
+ tail = cs->ev_tail;
if (tail == head) {
if (!atomic_read(&cs->commands_pending))
break;
@@ -1947,18 +1947,23 @@ static void process_events(struct cardstate *cs)
ev = cs->events + head;
was_busy = cs->cur_at_seq != SEQ_NONE;
+ spin_unlock_irqrestore(&cs->ev_lock, flags);
process_event(cs, ev);
+ spin_lock_irqsave(&cs->ev_lock, flags);
kfree(ev->ptr);
ev->ptr = NULL;
if (was_busy && cs->cur_at_seq == SEQ_NONE)
check_flags = 1;
head = (head + 1) % MAX_EVENTS;
- atomic_set(&cs->ev_head, head);
+ cs->ev_head = head;
}
+ spin_unlock_irqrestore(&cs->ev_lock, flags);
+
if (i == 2 * MAX_EVENTS) {
- err("infinite loop in process_events; aborting.");
+ dev_err(cs->dev,
+ "infinite loop in process_events; aborting.\n");
}
}
@@ -1970,12 +1975,9 @@ void gigaset_handle_event(unsigned long data)
{
struct cardstate *cs = (struct cardstate *) data;
- IFNULLRET(cs);
- IFNULLRET(cs->inbuf);
-
/* handle incoming data on control/common channel */
if (atomic_read(&cs->inbuf->head) != atomic_read(&cs->inbuf->tail)) {
- dbg(DEBUG_INTR, "processing new data");
+ gig_dbg(DEBUG_INTR, "processing new data");
cs->ops->handle_input(cs->inbuf);
}
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 729edcdb6da..22b9693f7c0 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -1,11 +1,16 @@
-/* Siemens Gigaset 307x driver
+/*
+ * Siemens Gigaset 307x driver
* Common header file for all connection variants
*
- * Written by Stefan Eilers <Eilers.Stefan@epost.de>
+ * Written by Stefan Eilers
* and Hansjoerg Lipp <hjlipp@web.de>
*
- * Version: $Id: gigaset.h,v 1.97.4.26 2006/02/04 18:28:16 hjlipp Exp $
- * ===========================================================================
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ * =====================================================================
*/
#ifndef GIGASET_H
@@ -15,7 +20,6 @@
#include <linux/kernel.h>
#include <linux/compiler.h>
#include <linux/types.h>
-#include <asm/atomic.h>
#include <linux/spinlock.h>
#include <linux/isdnif.h>
#include <linux/usb.h>
@@ -27,21 +31,22 @@
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/list.h>
+#include <asm/atomic.h>
#define GIG_VERSION {0,5,0,0}
#define GIG_COMPAT {0,4,0,0}
-#define MAX_REC_PARAMS 10 /* Max. number of params in response string */
-#define MAX_RESP_SIZE 512 /* Max. size of a response string */
-#define HW_HDR_LEN 2 /* Header size used to store ack info */
+#define MAX_REC_PARAMS 10 /* Max. number of params in response string */
+#define MAX_RESP_SIZE 512 /* Max. size of a response string */
+#define HW_HDR_LEN 2 /* Header size used to store ack info */
-#define MAX_EVENTS 64 /* size of event queue */
+#define MAX_EVENTS 64 /* size of event queue */
#define RBUFSIZE 8192
-#define SBUFSIZE 4096 /* sk_buff payload size */
+#define SBUFSIZE 4096 /* sk_buff payload size */
-#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */
-#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
+#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
+#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */
/* compile time options */
#define GIG_MAJOR 0
@@ -50,10 +55,7 @@
#define GIG_RETRYCID
#define GIG_X75
-#define MAX_TIMER_INDEX 1000
-#define MAX_SEQ_INDEX 1000
-
-#define GIG_TICK (HZ / 10)
+#define GIG_TICK 100 /* in milliseconds */
/* timeout values (unit: 1 sec) */
#define INIT_TIMEOUT 1
@@ -67,74 +69,89 @@
#define MAXACT 3
-#define IFNULL(a) if (unlikely(!(a)))
-#define IFNULLRET(a) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return; }
-#define IFNULLRETVAL(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return (b); }
-#define IFNULLCONT(a) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); continue; }
-#define IFNULLGOTO(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); goto b; }
-
extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */
-/* any combination of these can be given with the 'debug=' parameter to insmod, e.g.
- * 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and DEBUG_INTR. */
-enum debuglevel { /* up to 24 bits (atomic_t) */
+/* any combination of these can be given with the 'debug=' parameter to insmod,
+ * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and
+ * DEBUG_INTR.
+ */
+enum debuglevel {
DEBUG_REG = 0x0002, /* serial port I/O register operations */
DEBUG_OPEN = 0x0004, /* open/close serial port */
DEBUG_INTR = 0x0008, /* interrupt processing */
- DEBUG_INTR_DUMP = 0x0010, /* Activating hexdump debug output on interrupt
- requests, not available as run-time option */
+ DEBUG_INTR_DUMP = 0x0010, /* Activating hexdump debug output on
+ interrupt requests, not available as
+ run-time option */
DEBUG_CMD = 0x00020, /* sent/received LL commands */
DEBUG_STREAM = 0x00040, /* application data stream I/O events */
DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */
DEBUG_LLDATA = 0x00100, /* sent/received LL data */
- DEBUG_INTR_0 = 0x00200, /* serial port output interrupt processing */
+ DEBUG_INTR_0 = 0x00200, /* serial port interrupt processing */
DEBUG_DRIVER = 0x00400, /* driver structure */
DEBUG_HDLC = 0x00800, /* M10x HDLC processing */
DEBUG_WRITE = 0x01000, /* M105 data write */
- DEBUG_TRANSCMD = 0x02000, /*AT-COMMANDS+RESPONSES*/
- DEBUG_MCMD = 0x04000, /*COMMANDS THAT ARE SENT VERY OFTEN*/
- DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data structures */
+ DEBUG_TRANSCMD = 0x02000, /* AT-COMMANDS+RESPONSES */
+ DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */
+ DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data
+ structures */
DEBUG_LOCK = 0x10000, /* semaphore operations */
DEBUG_OUTPUT = 0x20000, /* output to device */
- DEBUG_ISO = 0x40000, /* isochronous transfers */
+ DEBUG_ISO = 0x40000, /* isochronous transfers */
DEBUG_IF = 0x80000, /* character device operations */
- DEBUG_USBREQ = 0x100000, /* USB communication (except payload data) */
- DEBUG_LOCKCMD = 0x200000, /* AT commands and responses when MS_LOCKED */
+ DEBUG_USBREQ = 0x100000, /* USB communication (except payload
+ data) */
+ DEBUG_LOCKCMD = 0x200000, /* AT commands and responses when
+ MS_LOCKED */
- DEBUG_ANY = 0x3fffff, /* print message if any of the others is activated */
+ DEBUG_ANY = 0x3fffff, /* print message if any of the others is
+ activated */
};
-#ifdef CONFIG_GIGASET_DEBUG
-#define DEBUG_DEFAULT (DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ)
-//#define DEBUG_DEFAULT (DEBUG_LOCK | DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUF_IF | DEBUG_DRIVER | DEBUG_OUTPUT | DEBUG_INTR)
-#else
-#define DEBUG_DEFAULT 0
+/* missing from linux/device.h ... */
+#ifndef dev_notice
+#define dev_notice(dev, format, arg...) \
+ dev_printk(KERN_NOTICE , dev , format , ## arg)
#endif
-/* redefine syslog macros to prepend module name instead of entire source path */
-/* The space before the comma in ", ##" is needed by gcc 2.95 */
+/* Kernel message macros for situations where dev_printk and friends cannot be
+ * used for lack of reliable access to a device structure.
+ * linux/usb.h already contains these but in an obsolete form which clutters
+ * the log needlessly, and according to the USB maintainer those should be
+ * removed rather than fixed anyway.
+ */
+#undef err
#undef info
-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
-
-#undef notice
-#define notice(format, arg...) printk(KERN_NOTICE "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
-
#undef warn
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
+#undef notice
-#undef err
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
+#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
+ format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \
+ format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING KBUILD_MODNAME ": " \
+ format "\n" , ## arg)
+#define notice(format, arg...) printk(KERN_NOTICE KBUILD_MODNAME ": " \
+ format "\n" , ## arg)
-#undef dbg
#ifdef CONFIG_GIGASET_DEBUG
-#define dbg(level, format, arg...) do { if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \
- printk(KERN_DEBUG "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg); } while (0)
+
+#define gig_dbg(level, format, arg...) \
+ do { \
+ if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \
+ printk(KERN_DEBUG KBUILD_MODNAME ": " format "\n", \
+ ## arg); \
+ } while (0)
+#define DEBUG_DEFAULT (DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ)
+
#else
-#define dbg(level, format, arg...) do {} while (0)
+
+#define gig_dbg(level, format, arg...) do {} while (0)
+#define DEBUG_DEFAULT 0
+
#endif
void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
- size_t len, const unsigned char *buf, int from_user);
+ size_t len, const unsigned char *buf);
/* connection state */
#define ZSAU_NONE 0
@@ -148,13 +165,14 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define ZSAU_UNKNOWN -1
/* USB control transfer requests */
-#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
-#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
+#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
+#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
/* int-in-events 3070 */
#define HD_B1_FLOW_CONTROL 0x80
#define HD_B2_FLOW_CONTROL 0x81
-#define HD_RECEIVEATDATA_ACK (0x35) // 3070 // att: HD_RECEIVE>>AT<<DATA_ACK
+#define HD_RECEIVEATDATA_ACK (0x35) // 3070
+ // att: HD_RECEIVE>>AT<<DATA_ACK
#define HD_READY_SEND_ATDATA (0x36) // 3070
#define HD_OPEN_ATCHANNEL_ACK (0x37) // 3070
#define HD_CLOSE_ATCHANNEL_ACK (0x38) // 3070
@@ -181,17 +199,18 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define HD_CLOSE_ATCHANNEL (0x29) // 3070
/* USB frames for isochronous transfer */
-#define BAS_FRAMETIME 1 /* number of milliseconds between frames */
-#define BAS_NUMFRAMES 8 /* number of frames per URB */
-#define BAS_MAXFRAME 16 /* allocated bytes per frame */
-#define BAS_NORMFRAME 8 /* send size without flow control */
-#define BAS_HIGHFRAME 10 /* " " with positive flow control */
-#define BAS_LOWFRAME 5 /* " " with negative flow control */
-#define BAS_CORRFRAMES 4 /* flow control multiplicator */
-
-#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES) /* size of isochronous input buffer per URB */
-#define BAS_OUTBUFSIZE 4096 /* size of common isochronous output buffer */
-#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isochronous output buffer */
+#define BAS_FRAMETIME 1 /* number of milliseconds between frames */
+#define BAS_NUMFRAMES 8 /* number of frames per URB */
+#define BAS_MAXFRAME 16 /* allocated bytes per frame */
+#define BAS_NORMFRAME 8 /* send size without flow control */
+#define BAS_HIGHFRAME 10 /* " " with positive flow control */
+#define BAS_LOWFRAME 5 /* " " with negative flow control */
+#define BAS_CORRFRAMES 4 /* flow control multiplicator */
+
+#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES)
+ /* size of isoc in buf per URB */
+#define BAS_OUTBUFSIZE 4096 /* size of common isoc out buffer */
+#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isoc out buf */
#define BAS_INURBS 3
#define BAS_OUTURBS 3
@@ -207,40 +226,40 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define AT_NUM 7
/* variables in struct at_state_t */
-#define VAR_ZSAU 0
-#define VAR_ZDLE 1
-#define VAR_ZVLS 2
-#define VAR_ZCTP 3
-#define VAR_NUM 4
-
-#define STR_NMBR 0
-#define STR_ZCPN 1
-#define STR_ZCON 2
-#define STR_ZBC 3
-#define STR_ZHLC 4
-#define STR_NUM 5
-
-#define EV_TIMEOUT -105
-#define EV_IF_VER -106
-#define EV_PROC_CIDMODE -107
-#define EV_SHUTDOWN -108
-#define EV_START -110
-#define EV_STOP -111
-#define EV_IF_LOCK -112
-#define EV_PROTO_L2 -113
-#define EV_ACCEPT -114
-#define EV_DIAL -115
-#define EV_HUP -116
-#define EV_BC_OPEN -117
-#define EV_BC_CLOSED -118
+#define VAR_ZSAU 0
+#define VAR_ZDLE 1
+#define VAR_ZVLS 2
+#define VAR_ZCTP 3
+#define VAR_NUM 4
+
+#define STR_NMBR 0
+#define STR_ZCPN 1
+#define STR_ZCON 2
+#define STR_ZBC 3
+#define STR_ZHLC 4
+#define STR_NUM 5
+
+#define EV_TIMEOUT -105
+#define EV_IF_VER -106
+#define EV_PROC_CIDMODE -107
+#define EV_SHUTDOWN -108
+#define EV_START -110
+#define EV_STOP -111
+#define EV_IF_LOCK -112
+#define EV_PROTO_L2 -113
+#define EV_ACCEPT -114
+#define EV_DIAL -115
+#define EV_HUP -116
+#define EV_BC_OPEN -117
+#define EV_BC_CLOSED -118
/* input state */
-#define INS_command 0x0001
-#define INS_DLE_char 0x0002
-#define INS_byte_stuff 0x0004
-#define INS_have_data 0x0008
-#define INS_skip_frame 0x0010
-#define INS_DLE_command 0x0020
+#define INS_command 0x0001
+#define INS_DLE_char 0x0002
+#define INS_byte_stuff 0x0004
+#define INS_have_data 0x0008
+#define INS_skip_frame 0x0010
+#define INS_DLE_command 0x0020
#define INS_flag_hunt 0x0040
/* channel state */
@@ -248,27 +267,27 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define CHS_B_UP 0x02
#define CHS_NOTIFY_LL 0x04
-#define ICALL_REJECT 0
-#define ICALL_ACCEPT 1
-#define ICALL_IGNORE 2
+#define ICALL_REJECT 0
+#define ICALL_ACCEPT 1
+#define ICALL_IGNORE 2
/* device state */
-#define MS_UNINITIALIZED 0
-#define MS_INIT 1
-#define MS_LOCKED 2
-#define MS_SHUTDOWN 3
-#define MS_RECOVER 4
-#define MS_READY 5
+#define MS_UNINITIALIZED 0
+#define MS_INIT 1
+#define MS_LOCKED 2
+#define MS_SHUTDOWN 3
+#define MS_RECOVER 4
+#define MS_READY 5
/* mode */
-#define M_UNKNOWN 0
-#define M_CONFIG 1
-#define M_UNIMODEM 2
-#define M_CID 3
+#define M_UNKNOWN 0
+#define M_CONFIG 1
+#define M_UNIMODEM 2
+#define M_CID 3
/* start mode */
-#define SM_LOCKED 0
-#define SM_ISDN 1 /* default */
+#define SM_LOCKED 0
+#define SM_ISDN 1 /* default */
struct gigaset_ops;
struct gigaset_driver;
@@ -283,27 +302,26 @@ struct ser_bc_state;
struct bas_bc_state;
struct reply_t {
- int resp_code; /* RSP_XXXX */
- int min_ConState; /* <0 => ignore */
- int max_ConState; /* <0 => ignore */
- int parameter; /* e.g. ZSAU_XXXX <0: ignore*/
- int new_ConState; /* <0 => ignore */
- int timeout; /* >0 => *HZ; <=0 => TOUT_XXXX*/
- int action[MAXACT]; /* ACT_XXXX */
- char *command; /* NULL==none */
+ int resp_code; /* RSP_XXXX */
+ int min_ConState; /* <0 => ignore */
+ int max_ConState; /* <0 => ignore */
+ int parameter; /* e.g. ZSAU_XXXX <0: ignore*/
+ int new_ConState; /* <0 => ignore */
+ int timeout; /* >0 => *HZ; <=0 => TOUT_XXXX*/
+ int action[MAXACT]; /* ACT_XXXX */
+ char *command; /* NULL==none */
};
extern struct reply_t gigaset_tab_cid_m10x[];
extern struct reply_t gigaset_tab_nocid_m10x[];
struct inbuf_t {
- unsigned char *rcvbuf; /* usb-gigaset receive buffer */
+ unsigned char *rcvbuf; /* usb-gigaset receive buffer */
struct bc_state *bcs;
- struct cardstate *cs;
- int inputstate;
-
- atomic_t head, tail;
- unsigned char data[RBUFSIZE];
+ struct cardstate *cs;
+ int inputstate;
+ atomic_t head, tail;
+ unsigned char data[RBUFSIZE];
};
/* isochronous write buffer structure
@@ -319,16 +337,9 @@ struct inbuf_t {
* if writesem <= 0, data[write..read-1] is currently being written to
* - idle contains the byte value to repeat when the end of valid data is
* reached; if nextread==write (buffer contains no data to send), either the
- * BAS_OUTBUFPAD bytes immediately before data[write] (if write>=BAS_OUTBUFPAD)
- * or those of the pad area (if write<BAS_OUTBUFPAD) are also filled with that
- * value
- * - optionally, the following statistics on the buffer's usage can be collected:
- * maxfill: maximum number of bytes occupied
- * idlefills: number of times a frame of idle bytes is prepared
- * emptygets: number of times the buffer was empty when a data frame was requested
- * backtoback: number of times two data packets were entered into the buffer
- * without intervening idle flags
- * nakedback: set if no idle flags have been inserted since the last data packet
+ * BAS_OUTBUFPAD bytes immediately before data[write] (if
+ * write>=BAS_OUTBUFPAD) or those of the pad area (if write<BAS_OUTBUFPAD)
+ * are also filled with that value
*/
struct isowbuf_t {
atomic_t read;
@@ -358,34 +369,28 @@ struct isow_urbctx_t {
* it is currently assigned a B channel
*/
struct at_state_t {
- struct list_head list;
- int waiting;
- int getstring;
- atomic_t timer_index;
+ struct list_head list;
+ int waiting;
+ int getstring;
+ unsigned timer_index;
unsigned long timer_expires;
int timer_active;
- unsigned int ConState; /* State of connection */
- struct reply_t *replystruct;
- int cid;
- int int_var[VAR_NUM]; /* see VAR_XXXX */
- char *str_var[STR_NUM]; /* see STR_XXXX */
- unsigned pending_commands; /* see PC_XXXX */
- atomic_t seq_index;
-
- struct cardstate *cs;
- struct bc_state *bcs;
+ unsigned int ConState; /* State of connection */
+ struct reply_t *replystruct;
+ int cid;
+ int int_var[VAR_NUM]; /* see VAR_XXXX */
+ char *str_var[STR_NUM]; /* see STR_XXXX */
+ unsigned pending_commands; /* see PC_XXXX */
+ unsigned seq_index;
+
+ struct cardstate *cs;
+ struct bc_state *bcs;
};
struct resp_type_t {
unsigned char *response;
- int resp_code; /* RSP_XXXX */
- int type; /* RT_XXXX */
-};
-
-struct prot_skb {
- atomic_t empty;
- struct semaphore *sem;
- struct sk_buff *skb;
+ int resp_code; /* RSP_XXXX */
+ int type; /* RT_XXXX */
};
struct event_t {
@@ -398,29 +403,29 @@ struct event_t {
/* This buffer holds all information about the used B-Channel */
struct bc_state {
- struct sk_buff *tx_skb; /* Current transfer buffer to modem */
- struct sk_buff_head squeue; /* B-Channel send Queue */
+ struct sk_buff *tx_skb; /* Current transfer buffer to modem */
+ struct sk_buff_head squeue; /* B-Channel send Queue */
/* Variables for debugging .. */
- int corrupted; /* Counter for corrupted packages */
- int trans_down; /* Counter of packages (downstream) */
- int trans_up; /* Counter of packages (upstream) */
+ int corrupted; /* Counter for corrupted packages */
+ int trans_down; /* Counter of packages (downstream) */
+ int trans_up; /* Counter of packages (upstream) */
struct at_state_t at_state;
unsigned long rcvbytes;
__u16 fcs;
struct sk_buff *skb;
- int inputstate; /* see INS_XXXX */
+ int inputstate; /* see INS_XXXX */
int channel;
struct cardstate *cs;
- unsigned chstate; /* bitmap (CHS_*) */
+ unsigned chstate; /* bitmap (CHS_*) */
int ignore;
- unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */
- char *commands[AT_NUM]; /* see AT_XXXX */
+ unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */
+ char *commands[AT_NUM]; /* see AT_XXXX */
#ifdef CONFIG_GIGASET_DEBUG
int emptycount;
@@ -428,37 +433,39 @@ struct bc_state {
int busy;
int use_count;
- /* hardware drivers */
+ /* private data of hardware drivers */
union {
- struct ser_bc_state *ser; /* private data of serial hardware driver */
- struct usb_bc_state *usb; /* private data of usb hardware driver */
- struct bas_bc_state *bas;
+ struct ser_bc_state *ser; /* serial hardware driver */
+ struct usb_bc_state *usb; /* usb hardware driver (m105) */
+ struct bas_bc_state *bas; /* usb hardware driver (base) */
} hw;
};
struct cardstate {
struct gigaset_driver *driver;
unsigned minor_index;
+ struct device *dev;
const struct gigaset_ops *ops;
/* Stuff to handle communication */
- //wait_queue_head_t initwait;
wait_queue_head_t waitqueue;
int waiting;
- atomic_t mode; /* see M_XXXX */
- atomic_t mstate; /* Modem state: see MS_XXXX */
- /* only changed by the event layer */
+ atomic_t mode; /* see M_XXXX */
+ atomic_t mstate; /* Modem state: see MS_XXXX */
+ /* only changed by the event layer */
int cmd_result;
int channels;
- struct bc_state *bcs; /* Array of struct bc_state */
+ struct bc_state *bcs; /* Array of struct bc_state */
- int onechannel; /* data and commands transmitted in one stream (M10x) */
+ int onechannel; /* data and commands transmitted in one
+ stream (M10x) */
spinlock_t lock;
- struct at_state_t at_state; /* at_state_t for cid == 0 */
- struct list_head temp_at_states; /* list of temporary "struct at_state_t"s without B channel */
+ struct at_state_t at_state; /* at_state_t for cid == 0 */
+ struct list_head temp_at_states;/* list of temporary "struct
+ at_state_t"s without B channel */
struct inbuf_t *inbuf;
@@ -474,58 +481,69 @@ struct cardstate {
unsigned fwver[4];
int gotfwver;
- atomic_t running; /* !=0 if events are handled */
- atomic_t connected; /* !=0 if hardware is connected */
+ unsigned running; /* !=0 if events are handled */
+ unsigned connected; /* !=0 if hardware is connected */
+ unsigned isdn_up; /* !=0 after ISDN_STAT_RUN */
- atomic_t cidmode;
+ unsigned cidmode;
- int myid; /* id for communication with LL */
+ int myid; /* id for communication with LL */
isdn_if iif;
struct reply_t *tabnocid;
struct reply_t *tabcid;
int cs_init;
- int ignoreframes; /* frames to ignore after setting up the B channel */
- struct semaphore sem; /* locks this structure: */
- /* connected is not changed, */
- /* hardware_up is not changed, */
- /* MState is not changed to or from MS_LOCKED */
+ int ignoreframes; /* frames to ignore after setting up the
+ B channel */
+ struct mutex mutex; /* locks this structure:
+ * connected is not changed,
+ * hardware_up is not changed,
+ * MState is not changed to or from
+ * MS_LOCKED */
struct timer_list timer;
int retry_count;
- int dle; /* !=0 if modem commands/responses are dle encoded */
- int cur_at_seq; /* sequence of AT commands being processed */
- int curchannel; /* channel, those commands are meant for */
- atomic_t commands_pending; /* flag(s) in xxx.commands_pending have been set */
- struct tasklet_struct event_tasklet; /* tasklet for serializing AT commands. Scheduled
- * -> for modem reponses (and incomming data for M10x)
- * -> on timeout
- * -> after setting bits in xxx.at_state.pending_command
- * (e.g. command from LL) */
- struct tasklet_struct write_tasklet; /* tasklet for serial output
- * (not used in base driver) */
+ int dle; /* !=0 if modem commands/responses are
+ dle encoded */
+ int cur_at_seq; /* sequence of AT commands being
+ processed */
+ int curchannel; /* channel those commands are meant
+ for */
+ atomic_t commands_pending; /* flag(s) in xxx.commands_pending have
+ been set */
+ struct tasklet_struct event_tasklet;
+ /* tasklet for serializing AT commands.
+ * Scheduled
+ * -> for modem reponses (and
+ * incoming data for M10x)
+ * -> on timeout
+ * -> after setting bits in
+ * xxx.at_state.pending_command
+ * (e.g. command from LL) */
+ struct tasklet_struct write_tasklet;
+ /* tasklet for serial output
+ * (not used in base driver) */
/* event queue */
struct event_t events[MAX_EVENTS];
- atomic_t ev_tail, ev_head;
+ unsigned ev_tail, ev_head;
spinlock_t ev_lock;
/* current modem response */
unsigned char respdata[MAX_RESP_SIZE];
unsigned cbytes;
- /* hardware drivers */
+ /* private data of hardware drivers */
union {
- struct usb_cardstate *usb; /* private data of USB hardware driver */
- struct ser_cardstate *ser; /* private data of serial hardware driver */
- struct bas_cardstate *bas; /* private data of base hardware driver */
+ struct usb_cardstate *usb; /* USB hardware driver (m105) */
+ struct ser_cardstate *ser; /* serial hardware driver */
+ struct bas_cardstate *bas; /* USB hardware driver (base) */
} hw;
};
struct gigaset_driver {
struct list_head list;
- spinlock_t lock; /* locks minor tables and blocked */
- //struct semaphore sem; /* locks this structure */
+ spinlock_t lock; /* locks minor tables and blocked */
struct tty_driver *tty;
unsigned have_tty;
unsigned minor;
@@ -553,37 +571,42 @@ struct bas_bc_state {
struct isow_urbctx_t isoouturbs[BAS_OUTURBS];
struct isow_urbctx_t *isooutdone, *isooutfree, *isooutovfl;
struct isowbuf_t *isooutbuf;
- unsigned numsub; /* submitted URB counter (for diagnostic messages only) */
+ unsigned numsub; /* submitted URB counter
+ (for diagnostic messages only) */
struct tasklet_struct sent_tasklet;
/* isochronous input state */
spinlock_t isoinlock;
struct urb *isoinurbs[BAS_INURBS];
unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS];
- struct urb *isoindone; /* completed isoc read URB */
- int loststatus; /* status of dropped URB */
- unsigned isoinlost; /* number of bytes lost */
- /* state of bit unstuffing algorithm (in addition to BC_state.inputstate) */
- unsigned seqlen; /* number of '1' bits not yet unstuffed */
- unsigned inbyte, inbits; /* collected bits for next byte */
+ struct urb *isoindone; /* completed isoc read URB */
+ int loststatus; /* status of dropped URB */
+ unsigned isoinlost; /* number of bytes lost */
+ /* state of bit unstuffing algorithm
+ (in addition to BC_state.inputstate) */
+ unsigned seqlen; /* number of '1' bits not yet
+ unstuffed */
+ unsigned inbyte, inbits; /* collected bits for next byte */
/* statistics */
- unsigned goodbytes; /* bytes correctly received */
- unsigned alignerrs; /* frames with incomplete byte at end */
- unsigned fcserrs; /* FCS errors */
- unsigned frameerrs; /* framing errors */
- unsigned giants; /* long frames */
- unsigned runts; /* short frames */
- unsigned aborts; /* HDLC aborts */
- unsigned shared0s; /* '0' bits shared between flags */
- unsigned stolen0s; /* '0' stuff bits also serving as leading flag bits */
+ unsigned goodbytes; /* bytes correctly received */
+ unsigned alignerrs; /* frames with incomplete byte at end */
+ unsigned fcserrs; /* FCS errors */
+ unsigned frameerrs; /* framing errors */
+ unsigned giants; /* long frames */
+ unsigned runts; /* short frames */
+ unsigned aborts; /* HDLC aborts */
+ unsigned shared0s; /* '0' bits shared between flags */
+ unsigned stolen0s; /* '0' stuff bits also serving as
+ leading flag bits */
struct tasklet_struct rcvd_tasklet;
};
struct gigaset_ops {
- /* Called from ev-layer.c/interface.c for sending AT commands to the device */
+ /* Called from ev-layer.c/interface.c for sending AT commands to the
+ device */
int (*write_cmd)(struct cardstate *cs,
- const unsigned char *buf, int len,
- struct tasklet_struct *wake_tasklet);
+ const unsigned char *buf, int len,
+ struct tasklet_struct *wake_tasklet);
/* Called from interface.c for additional device control */
int (*write_room)(struct cardstate *cs);
@@ -604,7 +627,7 @@ struct gigaset_ops {
/* Called by gigaset_freecs() for freeing bcs->hw.xxx */
int (*freebcshw)(struct bc_state *bcs);
- /* Called by gigaset_stop() or gigaset_bchannel_down() for resetting bcs->hw.xxx */
+ /* Called by gigaset_bchannel_down() for resetting bcs->hw.xxx */
void (*reinitbcshw)(struct bc_state *bcs);
/* Called by gigaset_initcs() for setting up cs->hw.xxx */
@@ -613,13 +636,10 @@ struct gigaset_ops {
/* Called by gigaset_freecs() for freeing cs->hw.xxx */
void (*freecshw)(struct cardstate *cs);
- ///* Called by gigaset_stop() for killing URBs, shutting down the device, ...
- // hardwareup: ==0: don't try to shut down the device, hardware is really not accessible
- // !=0: hardware still up */
- //void (*stophw)(struct cardstate *cs, int hardwareup);
-
- /* Called from common.c/interface.c for additional serial port control */
- int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state, unsigned new_state);
+ /* Called from common.c/interface.c for additional serial port
+ control */
+ int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state,
+ unsigned new_state);
int (*baud_rate)(struct cardstate *cs, unsigned cflag);
int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag);
@@ -639,7 +659,7 @@ struct gigaset_ops {
* <DLE_FLAG>: 0x10
* <EVENT>: ((a-z)* | (A-Z)* | (0-10)*)+
*/
-#define DLE_FLAG 0x10
+#define DLE_FLAG 0x10
/* ===========================================================================
* Functions implemented in asyncdata.c
@@ -667,7 +687,8 @@ void gigaset_isoc_input(struct inbuf_t *inbuf);
/* Called from bas-gigaset.c to process a block of data
* received through the isochronous channel */
-void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs);
+void gigaset_isoc_receive(unsigned char *src, unsigned count,
+ struct bc_state *bcs);
/* Called from bas-gigaset.c to put a block of data
* into the isochronous output buffer */
@@ -703,7 +724,7 @@ static inline void gigaset_isdn_rcv_err(struct bc_state *bcs)
isdn_ctrl response;
/* error -> LL */
- dbg(DEBUG_CMD, "sending L1ERR");
+ gig_dbg(DEBUG_CMD, "sending L1ERR");
response.driver = bcs->cs->myid;
response.command = ISDN_STAT_L1ERR;
response.arg = bcs->channel;
@@ -727,8 +748,8 @@ void gigaset_handle_modem_response(struct cardstate *cs);
*/
/* initialize sysfs for device */
-void gigaset_init_dev_sysfs(struct usb_interface *interface);
-void gigaset_free_dev_sysfs(struct usb_interface *interface);
+void gigaset_init_dev_sysfs(struct cardstate *cs);
+void gigaset_free_dev_sysfs(struct cardstate *cs);
/* ===========================================================================
* Functions implemented in common.c/gigaset.h
@@ -736,7 +757,7 @@ void gigaset_free_dev_sysfs(struct usb_interface *interface);
void gigaset_bcs_reinit(struct bc_state *bcs);
void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
- struct cardstate *cs, int cid);
+ struct cardstate *cs, int cid);
int gigaset_get_channel(struct bc_state *bcs);
void gigaset_free_channel(struct bc_state *bcs);
int gigaset_get_channels(struct cardstate *cs);
@@ -745,16 +766,15 @@ void gigaset_block_channels(struct cardstate *cs);
/* Allocate and initialize driver structure. */
struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
- const char *procname,
- const char *devname,
- const char *devfsname,
- const struct gigaset_ops *ops,
- struct module *owner);
+ const char *procname,
+ const char *devname,
+ const char *devfsname,
+ const struct gigaset_ops *ops,
+ struct module *owner);
/* Deallocate driver structure. */
void gigaset_freedriver(struct gigaset_driver *drv);
void gigaset_debugdrivers(void);
-struct cardstate *gigaset_get_cs_by_minor(unsigned minor);
struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty);
struct cardstate *gigaset_get_cs_by_id(int id);
@@ -763,7 +783,8 @@ struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv);
void gigaset_unassign(struct cardstate *cs);
void gigaset_blockdriver(struct gigaset_driver *drv);
-/* Allocate and initialize card state. Calls hardware dependent gigaset_init[b]cs(). */
+/* Allocate and initialize card state. Calls hardware dependent
+ gigaset_init[b]cs(). */
struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
int onechannel, int ignoreframes,
int cidmode, const char *modulename);
@@ -788,8 +809,8 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb);
* ptr must be kmalloc()ed (and not be freed by the caller).
*/
struct event_t *gigaset_add_event(struct cardstate *cs,
- struct at_state_t *at_state, int type,
- void *ptr, int parameter, void *arg);
+ struct at_state_t *at_state, int type,
+ void *ptr, int parameter, void *arg);
/* Called on CONFIG1 command from frontend. */
int gigaset_enterconfigmode(struct cardstate *cs); //0: success <0: errorcode
@@ -799,7 +820,7 @@ static inline void gigaset_schedule_event(struct cardstate *cs)
{
unsigned long flags;
spin_lock_irqsave(&cs->lock, flags);
- if (atomic_read(&cs->running))
+ if (cs->running)
tasklet_schedule(&cs->event_tasklet);
spin_unlock_irqrestore(&cs->lock, flags);
}
@@ -810,7 +831,7 @@ static inline void gigaset_bchannel_down(struct bc_state *bcs)
{
gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL);
- dbg(DEBUG_CMD, "scheduling BC_CLOSED");
+ gig_dbg(DEBUG_CMD, "scheduling BC_CLOSED");
gigaset_schedule_event(bcs->cs);
}
@@ -820,36 +841,19 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs)
{
gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL);
- dbg(DEBUG_CMD, "scheduling BC_OPEN");
+ gig_dbg(DEBUG_CMD, "scheduling BC_OPEN");
gigaset_schedule_event(bcs->cs);
}
/* handling routines for sk_buff */
/* ============================= */
-/* private version of __skb_put()
- * append 'len' bytes to the content of 'skb', already knowing that the
- * existing buffer can accomodate them
- * returns a pointer to the location where the new bytes should be copied to
- * This function does not take any locks so it must be called with the
- * appropriate locks held only.
- */
-static inline unsigned char *gigaset_skb_put_quick(struct sk_buff *skb,
- unsigned int len)
-{
- unsigned char *tmp = skb->tail;
- /*SKB_LINEAR_ASSERT(skb);*/ /* not needed here */
- skb->tail += len;
- skb->len += len;
- return tmp;
-}
-
/* pass received skb to LL
* Warning: skb must not be accessed anymore!
*/
static inline void gigaset_rcv_skb(struct sk_buff *skb,
- struct cardstate *cs,
- struct bc_state *bcs)
+ struct cardstate *cs,
+ struct bc_state *bcs)
{
cs->iif.rcvcallb_skb(cs->myid, bcs->channel, skb);
bcs->trans_down++;
@@ -859,8 +863,8 @@ static inline void gigaset_rcv_skb(struct sk_buff *skb,
* Warning: skb must not be accessed anymore!
*/
static inline void gigaset_rcv_error(struct sk_buff *procskb,
- struct cardstate *cs,
- struct bc_state *bcs)
+ struct cardstate *cs,
+ struct bc_state *bcs)
{
if (procskb)
dev_kfree_skb(procskb);
@@ -877,46 +881,9 @@ static inline void gigaset_rcv_error(struct sk_buff *procskb,
/* bitwise byte inversion table */
extern __u8 gigaset_invtab[]; /* in common.c */
-
/* append received bytes to inbuf */
-static inline int gigaset_fill_inbuf(struct inbuf_t *inbuf,
- const unsigned char *src,
- unsigned numbytes)
-{
- unsigned n, head, tail, bytesleft;
-
- dbg(DEBUG_INTR, "received %u bytes", numbytes);
-
- if (!numbytes)
- return 0;
-
- bytesleft = numbytes;
- tail = atomic_read(&inbuf->tail);
- head = atomic_read(&inbuf->head);
- dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
-
- while (bytesleft) {
- if (head > tail)
- n = head - 1 - tail;
- else if (head == 0)
- n = (RBUFSIZE-1) - tail;
- else
- n = RBUFSIZE - tail;
- if (!n) {
- err("buffer overflow (%u bytes lost)", bytesleft);
- break;
- }
- if (n > bytesleft)
- n = bytesleft;
- memcpy(inbuf->data + tail, src, n);
- bytesleft -= n;
- tail = (tail + n) % RBUFSIZE;
- src += n;
- }
- dbg(DEBUG_INTR, "setting tail to %u", tail);
- atomic_set(&inbuf->tail, tail);
- return numbytes != bytesleft;
-}
+int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
+ unsigned numbytes);
/* ===========================================================================
* Functions implemented in interface.c
@@ -924,7 +891,7 @@ static inline int gigaset_fill_inbuf(struct inbuf_t *inbuf,
/* initialize interface */
void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
- const char *devname, const char *devfsname);
+ const char *devname, const char *devfsname);
/* release interface */
void gigaset_if_freedriver(struct gigaset_driver *drv);
/* add minor */
@@ -933,6 +900,6 @@ void gigaset_if_init(struct cardstate *cs);
void gigaset_if_free(struct cardstate *cs);
/* device received data */
void gigaset_if_receive(struct cardstate *cs,
- unsigned char *buffer, size_t len);
+ unsigned char *buffer, size_t len);
#endif
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 731a675f21b..1654fa41357 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -1,9 +1,9 @@
/*
* Stuff used by all variants of the driver
*
- * Copyright (c) 2001 by Stefan Eilers (Eilers.Stefan@epost.de),
- * Hansjoerg Lipp (hjlipp@web.de),
- * Tilman Schmidt (tilman@imap.cc).
+ * Copyright (c) 2001 by Stefan Eilers,
+ * Hansjoerg Lipp <hjlipp@web.de>,
+ * Tilman Schmidt <tilman@imap.cc>.
*
* =====================================================================
* This program is free software; you can redistribute it and/or
@@ -11,15 +11,11 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: i4l.c,v 1.3.2.9 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
-/* == Handling of I4L IO ============================================================================*/
+/* == Handling of I4L IO =====================================================*/
/* writebuf_from_LL
* called by LL to transmit data on an open channel
@@ -29,14 +25,16 @@
* parameters:
* driverID driver ID as assigned by LL
* channel channel number
- * ack if != 0 LL wants to be notified on completion via statcallb(ISDN_STAT_BSENT)
+ * ack if != 0 LL wants to be notified on completion via
+ * statcallb(ISDN_STAT_BSENT)
* skb skb containing data to send
* return value:
* number of accepted bytes
* 0 if temporarily unable to accept data (out of buffer space)
* <0 on error (eg. -EINVAL)
*/
-static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff *skb)
+static int writebuf_from_LL(int driverID, int channel, int ack,
+ struct sk_buff *skb)
{
struct cardstate *cs;
struct bc_state *bcs;
@@ -54,28 +52,25 @@ static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff *
bcs = &cs->bcs[channel];
len = skb->len;
- dbg(DEBUG_LLDATA,
- "Receiving data from LL (id: %d, channel: %d, ack: %d, size: %d)",
- driverID, channel, ack, len);
+ gig_dbg(DEBUG_LLDATA,
+ "Receiving data from LL (id: %d, ch: %d, ack: %d, sz: %d)",
+ driverID, channel, ack, len);
if (!len) {
if (ack)
- warn("not ACKing empty packet from LL");
+ notice("%s: not ACKing empty packet", __func__);
return 0;
}
if (len > MAX_BUF_SIZE) {
- err("%s: packet too large (%d bytes)", __func__, channel);
+ err("%s: packet too large (%d bytes)", __func__, len);
return -EINVAL;
}
- if (!atomic_read(&cs->connected))
- return -ENODEV;
-
skblen = ack ? len : 0;
skb->head[0] = skblen & 0xff;
skb->head[1] = skblen >> 8;
- dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", len, skblen,
- (unsigned) skb->head[0], (unsigned) skb->head[1]);
+ gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x",
+ len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]);
/* pass to device-specific module */
return cs->ops->send_skb(bcs, skb);
@@ -89,14 +84,14 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
++bcs->trans_up;
if (skb->len)
- warn("%s: skb->len==%d", __func__, skb->len);
+ dev_warn(bcs->cs->dev, "%s: skb->len==%d\n",
+ __func__, skb->len);
len = (unsigned char) skb->head[0] |
(unsigned) (unsigned char) skb->head[1] << 8;
if (len) {
- dbg(DEBUG_MCMD,
- "Acknowledge sending to LL (id: %d, channel: %d size: %u)",
- bcs->cs->myid, bcs->channel, len);
+ gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)",
+ bcs->cs->myid, bcs->channel, len);
response.driver = bcs->cs->myid;
response.command = ISDN_STAT_BSENT;
@@ -119,15 +114,12 @@ static int command_from_LL(isdn_ctrl *cntrl)
struct bc_state *bcs;
int retval = 0;
struct setup_parm *sp;
+ unsigned param;
+ unsigned long flags;
- //dbg(DEBUG_ANY, "Gigaset_HW: Receiving command");
gigaset_debugdrivers();
- /* Terminate this call if no device is present. Bt if the command is "ISDN_CMD_LOCK" or
- * "ISDN_CMD_UNLOCK" then execute it due to the fact that they are device independent !
- */
- //FIXME "remove test for &connected"
- if ((!cs || !atomic_read(&cs->connected))) {
+ if (!cs) {
warn("LL tried to access unknown device with nr. %d",
cntrl->driver);
return -ENODEV;
@@ -135,29 +127,30 @@ static int command_from_LL(isdn_ctrl *cntrl)
switch (cntrl->command) {
case ISDN_CMD_IOCTL:
-
- dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver:%d,arg: %ld)",
- cntrl->driver, cntrl->arg);
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)",
+ cntrl->driver, cntrl->arg);
warn("ISDN_CMD_IOCTL is not supported.");
return -EINVAL;
case ISDN_CMD_DIAL:
- dbg(DEBUG_ANY, "ISDN_CMD_DIAL (driver: %d, channel: %ld, "
- "phone: %s,ownmsn: %s, si1: %d, si2: %d)",
- cntrl->driver, cntrl->arg,
- cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
- cntrl->parm.setup.si1, cntrl->parm.setup.si2);
+ gig_dbg(DEBUG_ANY,
+ "ISDN_CMD_DIAL (driver: %d, ch: %ld, "
+ "phone: %s, ownmsn: %s, si1: %d, si2: %d)",
+ cntrl->driver, cntrl->arg,
+ cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
+ cntrl->parm.setup.si1, cntrl->parm.setup.si2);
if (cntrl->arg >= cs->channels) {
- err("invalid channel (%d)", (int) cntrl->arg);
+ err("ISDN_CMD_DIAL: invalid channel (%d)",
+ (int) cntrl->arg);
return -EINVAL;
}
bcs = cs->bcs + cntrl->arg;
if (!gigaset_get_channel(bcs)) {
- err("channel not free");
+ err("ISDN_CMD_DIAL: channel not free");
return -EBUSY;
}
@@ -169,42 +162,46 @@ static int command_from_LL(isdn_ctrl *cntrl)
}
*sp = cntrl->parm.setup;
- if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp,
- atomic_read(&bcs->at_state.seq_index),
- NULL)) {
+ spin_lock_irqsave(&cs->lock, flags);
+ param = bcs->at_state.seq_index;
+ spin_unlock_irqrestore(&cs->lock, flags);
+
+ if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, param,
+ NULL)) {
//FIXME what should we do?
kfree(sp);
gigaset_free_channel(bcs);
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling DIAL");
+ gig_dbg(DEBUG_CMD, "scheduling DIAL");
gigaset_schedule_event(cs);
break;
case ISDN_CMD_ACCEPTD: //FIXME
- dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
if (cntrl->arg >= cs->channels) {
- err("invalid channel (%d)", (int) cntrl->arg);
+ err("ISDN_CMD_ACCEPTD: invalid channel (%d)",
+ (int) cntrl->arg);
return -EINVAL;
}
if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
- EV_ACCEPT, NULL, 0, NULL)) {
+ EV_ACCEPT, NULL, 0, NULL)) {
//FIXME what should we do?
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling ACCEPT");
+ gig_dbg(DEBUG_CMD, "scheduling ACCEPT");
gigaset_schedule_event(cs);
break;
case ISDN_CMD_ACCEPTB:
- dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB");
break;
case ISDN_CMD_HANGUP:
- dbg(DEBUG_ANY,
- "ISDN_CMD_HANGUP (channel: %d)", (int) cntrl->arg);
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)",
+ (int) cntrl->arg);
if (cntrl->arg >= cs->channels) {
err("ISDN_CMD_HANGUP: invalid channel (%u)",
@@ -213,66 +210,68 @@ static int command_from_LL(isdn_ctrl *cntrl)
}
if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
- EV_HUP, NULL, 0, NULL)) {
+ EV_HUP, NULL, 0, NULL)) {
//FIXME what should we do?
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling HUP");
+ gig_dbg(DEBUG_CMD, "scheduling HUP");
gigaset_schedule_event(cs);
break;
- case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME
- dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ");
+ case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ");
break;
- case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME
- dbg(DEBUG_ANY,
- "ISDN_CMD_SETEAZ (id:%d, channel: %ld, number: %s)",
- cntrl->driver, cntrl->arg, cntrl->parm.num);
+ case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME
+ gig_dbg(DEBUG_ANY,
+ "ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)",
+ cntrl->driver, cntrl->arg, cntrl->parm.num);
break;
- case ISDN_CMD_SETL2: /* Set L2 to given protocol */
- dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (Channel: %ld, Proto: %lx)",
- cntrl->arg & 0xff, (cntrl->arg >> 8));
+ case ISDN_CMD_SETL2: /* Set L2 to given protocol */
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)",
+ cntrl->arg & 0xff, (cntrl->arg >> 8));
if ((cntrl->arg & 0xff) >= cs->channels) {
- err("invalid channel (%u)",
+ err("ISDN_CMD_SETL2: invalid channel (%u)",
(unsigned) cntrl->arg & 0xff);
return -EINVAL;
}
if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state,
- EV_PROTO_L2, NULL, cntrl->arg >> 8,
- NULL)) {
+ EV_PROTO_L2, NULL, cntrl->arg >> 8,
+ NULL)) {
//FIXME what should we do?
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling PROTO_L2");
+ gig_dbg(DEBUG_CMD, "scheduling PROTO_L2");
gigaset_schedule_event(cs);
break;
- case ISDN_CMD_SETL3: /* Set L3 to given protocol */
- dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (Channel: %ld, Proto: %lx)",
- cntrl->arg & 0xff, (cntrl->arg >> 8));
+ case ISDN_CMD_SETL3: /* Set L3 to given protocol */
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)",
+ cntrl->arg & 0xff, (cntrl->arg >> 8));
if ((cntrl->arg & 0xff) >= cs->channels) {
- err("invalid channel (%u)",
+ err("ISDN_CMD_SETL3: invalid channel (%u)",
(unsigned) cntrl->arg & 0xff);
return -EINVAL;
}
if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
- err("invalid protocol %lu", cntrl->arg >> 8);
+ err("ISDN_CMD_SETL3: invalid protocol %lu",
+ cntrl->arg >> 8);
return -EINVAL;
}
break;
case ISDN_CMD_PROCEED:
- dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME
break;
case ISDN_CMD_ALERT:
- dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
if (cntrl->arg >= cs->channels) {
- err("invalid channel (%d)", (int) cntrl->arg);
+ err("ISDN_CMD_ALERT: invalid channel (%d)",
+ (int) cntrl->arg);
return -EINVAL;
}
//bcs = cs->bcs + cntrl->arg;
@@ -280,32 +279,31 @@ static int command_from_LL(isdn_ctrl *cntrl)
// FIXME
break;
case ISDN_CMD_REDIR:
- dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME
break;
case ISDN_CMD_PROT_IO:
- dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO");
break;
case ISDN_CMD_FAXCMD:
- dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD");
break;
case ISDN_CMD_GETL2:
- dbg(DEBUG_ANY, "ISDN_CMD_GETL2");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL2");
break;
case ISDN_CMD_GETL3:
- dbg(DEBUG_ANY, "ISDN_CMD_GETL3");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL3");
break;
case ISDN_CMD_GETEAZ:
- dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ");
break;
case ISDN_CMD_SETSIL:
- dbg(DEBUG_ANY, "ISDN_CMD_SETSIL");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_SETSIL");
break;
case ISDN_CMD_GETSIL:
- dbg(DEBUG_ANY, "ISDN_CMD_GETSIL");
+ gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL");
break;
default:
- err("unknown command %d from LL",
- cntrl->command);
+ err("unknown command %d from LL", cntrl->command);
return -EINVAL;
}
@@ -350,7 +348,8 @@ int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data)
proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
break;
default:
- err("invalid protocol: %u", bcs->proto2);
+ dev_err(bcs->cs->dev, "%s: invalid L2 protocol: %u\n",
+ __func__, bcs->proto2);
return -EINVAL;
}
@@ -378,7 +377,7 @@ int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data)
bcs->commands[i] = NULL;
if (length[i] &&
!(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {
- err("out of memory");
+ dev_err(bcs->cs->dev, "out of memory\n");
return -ENOMEM;
}
}
@@ -396,10 +395,14 @@ int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data)
}
if (bcs->commands[AT_MSN])
- snprintf(bcs->commands[AT_MSN], length[AT_MSN], "^SMSN=%s\r", sp->eazmsn);
- snprintf(bcs->commands[AT_BC ], length[AT_BC ], "^SBC=%s\r", bc);
- snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto);
- snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], "^SISO=%u\r", (unsigned)bcs->channel + 1);
+ snprintf(bcs->commands[AT_MSN], length[AT_MSN],
+ "^SMSN=%s\r", sp->eazmsn);
+ snprintf(bcs->commands[AT_BC ], length[AT_BC ],
+ "^SBC=%s\r", bc);
+ snprintf(bcs->commands[AT_PROTO], length[AT_PROTO],
+ "^SBPR=%u\r", proto);
+ snprintf(bcs->commands[AT_ISO ], length[AT_ISO ],
+ "^SISO=%u\r", (unsigned)bcs->channel + 1);
return 0;
}
@@ -419,7 +422,8 @@ int gigaset_isdn_setup_accept(struct at_state_t *at_state)
proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
break;
default:
- err("invalid protocol: %u", bcs->proto2);
+ dev_err(at_state->cs->dev, "%s: invalid protocol: %u\n",
+ __func__, bcs->proto2);
return -EINVAL;
}
@@ -436,13 +440,15 @@ int gigaset_isdn_setup_accept(struct at_state_t *at_state)
bcs->commands[i] = NULL;
if (length[i] &&
!(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {
- err("out of memory");
+ dev_err(at_state->cs->dev, "out of memory\n");
return -ENOMEM;
}
}
- snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto);
- snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], "^SISO=%u\r", (unsigned) bcs->channel + 1);
+ snprintf(bcs->commands[AT_PROTO], length[AT_PROTO],
+ "^SBPR=%u\r", proto);
+ snprintf(bcs->commands[AT_ISO ], length[AT_ISO ],
+ "^SISO=%u\r", (unsigned) bcs->channel + 1);
return 0;
}
@@ -473,7 +479,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
response.parm.setup.si1 = 1;
response.parm.setup.si2 = 2;
} else {
- warn("RING ignored - unsupported BC %s",
+ dev_warn(cs->dev, "RING ignored - unsupported BC %s\n",
at_state->str_var[STR_ZBC]);
return ICALL_IGNORE;
}
@@ -491,18 +497,17 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
response.parm.setup.eazmsn[0] = 0;
if (!bcs) {
- notice("no channel for incoming call");
- dbg(DEBUG_CMD, "Sending ICALLW");
+ dev_notice(cs->dev, "no channel for incoming call\n");
response.command = ISDN_STAT_ICALLW;
response.arg = 0; //FIXME
} else {
- dbg(DEBUG_CMD, "Sending ICALL");
+ gig_dbg(DEBUG_CMD, "Sending ICALL");
response.command = ISDN_STAT_ICALL;
response.arg = bcs->channel; //FIXME
}
response.driver = cs->myid;
retval = cs->iif.statcallb(&response);
- dbg(DEBUG_CMD, "Response: %d", retval);
+ gig_dbg(DEBUG_CMD, "Response: %d", retval);
switch (retval) {
case 0: /* no takers */
return ICALL_IGNORE;
@@ -512,7 +517,8 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
case 2: /* reject */
return ICALL_REJECT;
case 3: /* incomplete */
- warn("LL requested unsupported feature: Incomplete Number");
+ dev_warn(cs->dev,
+ "LL requested unsupported feature: Incomplete Number\n");
return ICALL_IGNORE;
case 4: /* proceeding */
/* Gigaset will send ALERTING anyway.
@@ -520,10 +526,11 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
*/
return ICALL_ACCEPT;
case 5: /* deflect */
- warn("LL requested unsupported feature: Call Deflection");
+ dev_warn(cs->dev,
+ "LL requested unsupported feature: Call Deflection\n");
return ICALL_IGNORE;
default:
- err("LL error %d on ICALL", retval);
+ dev_err(cs->dev, "LL error %d on ICALL\n", retval);
return ICALL_IGNORE;
}
}
@@ -533,7 +540,7 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid)
{
isdn_if *iif = &cs->iif;
- dbg(DEBUG_ANY, "Register driver capabilities to LL");
+ gig_dbg(DEBUG_ANY, "Register driver capabilities to LL");
//iif->id[sizeof(iif->id) - 1]=0;
//strncpy(iif->id, isdnid, sizeof(iif->id) - 1);
@@ -542,26 +549,26 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid)
return -ENOMEM; //FIXME EINVAL/...??
iif->owner = THIS_MODULE;
- iif->channels = cs->channels; /* I am supporting just one channel *//* I was supporting...*/
+ iif->channels = cs->channels;
iif->maxbufsize = MAX_BUF_SIZE;
- iif->features = ISDN_FEATURE_L2_TRANS | /* Our device is very advanced, therefore */
+ iif->features = ISDN_FEATURE_L2_TRANS |
ISDN_FEATURE_L2_HDLC |
#ifdef GIG_X75
ISDN_FEATURE_L2_X75I |
#endif
ISDN_FEATURE_L3_TRANS |
ISDN_FEATURE_P_EURO;
- iif->hl_hdrlen = HW_HDR_LEN; /* Area for storing ack */
+ iif->hl_hdrlen = HW_HDR_LEN; /* Area for storing ack */
iif->command = command_from_LL;
iif->writebuf_skb = writebuf_from_LL;
- iif->writecmd = NULL; /* Don't support isdnctrl */
- iif->readstat = NULL; /* Don't support isdnctrl */
- iif->rcvcallb_skb = NULL; /* Will be set by LL */
- iif->statcallb = NULL; /* Will be set by LL */
+ iif->writecmd = NULL; /* Don't support isdnctrl */
+ iif->readstat = NULL; /* Don't support isdnctrl */
+ iif->rcvcallb_skb = NULL; /* Will be set by LL */
+ iif->statcallb = NULL; /* Will be set by LL */
if (!register_isdn(iif))
return 0;
- cs->myid = iif->channels; /* Set my device id */
+ cs->myid = iif->channels; /* Set my device id */
return 1;
}
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index 3a81d9c6514..08e4c4eea14 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -9,8 +9,6 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * Version: $Id: interface.c,v 1.14.4.15 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
@@ -24,7 +22,7 @@ static int if_lock(struct cardstate *cs, int *arg)
{
int cmd = *arg;
- dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd);
+ gig_dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd);
if (cmd > 1)
return -EINVAL;
@@ -35,7 +33,7 @@ static int if_lock(struct cardstate *cs, int *arg)
}
if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED
- && atomic_read(&cs->connected)) {
+ && cs->connected) {
cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
cs->ops->baud_rate(cs, B115200);
cs->ops->set_line_ctrl(cs, CS8);
@@ -44,12 +42,12 @@ static int if_lock(struct cardstate *cs, int *arg)
cs->waiting = 1;
if (!gigaset_add_event(cs, &cs->at_state, EV_IF_LOCK,
- NULL, cmd, NULL)) {
+ NULL, cmd, NULL)) {
cs->waiting = 0;
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling IF_LOCK");
+ gig_dbg(DEBUG_CMD, "scheduling IF_LOCK");
gigaset_schedule_event(cs);
wait_event(cs->waitqueue, !cs->waiting);
@@ -68,7 +66,7 @@ static int if_version(struct cardstate *cs, unsigned arg[4])
static const unsigned compat[4] = GIG_COMPAT;
unsigned cmd = arg[0];
- dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd);
+ gig_dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd);
switch (cmd) {
case GIGVER_DRIVER:
@@ -80,12 +78,12 @@ static int if_version(struct cardstate *cs, unsigned arg[4])
case GIGVER_FWBASE:
cs->waiting = 1;
if (!gigaset_add_event(cs, &cs->at_state, EV_IF_VER,
- NULL, 0, arg)) {
+ NULL, 0, arg)) {
cs->waiting = 0;
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling IF_VER");
+ gig_dbg(DEBUG_CMD, "scheduling IF_VER");
gigaset_schedule_event(cs);
wait_event(cs->waitqueue, !cs->waiting);
@@ -101,7 +99,7 @@ static int if_version(struct cardstate *cs, unsigned arg[4])
static int if_config(struct cardstate *cs, int *arg)
{
- dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg);
+ gig_dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg);
if (*arg != 1)
return -EINVAL;
@@ -109,6 +107,11 @@ static int if_config(struct cardstate *cs, int *arg)
if (atomic_read(&cs->mstate) != MS_LOCKED)
return -EBUSY;
+ if (!cs->connected) {
+ err("not connected!");
+ return -ENODEV;
+ }
+
*arg = 0;
return gigaset_enterconfigmode(cs);
}
@@ -119,7 +122,7 @@ static int if_config(struct cardstate *cs, int *arg)
static int if_open(struct tty_struct *tty, struct file *filp);
static void if_close(struct tty_struct *tty, struct file *filp);
static int if_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg);
+ unsigned int cmd, unsigned long arg);
static int if_write_room(struct tty_struct *tty);
static int if_chars_in_buffer(struct tty_struct *tty);
static void if_throttle(struct tty_struct *tty);
@@ -127,9 +130,9 @@ static void if_unthrottle(struct tty_struct *tty);
static void if_set_termios(struct tty_struct *tty, struct termios *old);
static int if_tiocmget(struct tty_struct *tty, struct file *file);
static int if_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear);
+ unsigned int set, unsigned int clear);
static int if_write(struct tty_struct *tty,
- const unsigned char *buf, int count);
+ const unsigned char *buf, int count);
static struct tty_operations if_ops = {
.open = if_open,
@@ -153,8 +156,8 @@ static int if_open(struct tty_struct *tty, struct file *filp)
struct cardstate *cs;
unsigned long flags;
- dbg(DEBUG_IF, "%d+%d: %s()", tty->driver->minor_start, tty->index,
- __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%d+%d: %s()",
+ tty->driver->minor_start, tty->index, __func__);
tty->driver_data = NULL;
@@ -162,7 +165,7 @@ static int if_open(struct tty_struct *tty, struct file *filp)
if (!cs)
return -ENODEV;
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
tty->driver_data = cs;
@@ -173,10 +176,9 @@ static int if_open(struct tty_struct *tty, struct file *filp)
cs->tty = tty;
spin_unlock_irqrestore(&cs->lock, flags);
tty->low_latency = 1; //FIXME test
- //FIXME
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return 0;
}
@@ -187,30 +189,29 @@ static void if_close(struct tty_struct *tty, struct file *filp)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- down(&cs->sem);
+ mutex_lock(&cs->mutex);
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else {
if (!--cs->open_count) {
spin_lock_irqsave(&cs->lock, flags);
cs->tty = NULL;
spin_unlock_irqrestore(&cs->lock, flags);
- //FIXME
}
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
}
static int if_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct cardstate *cs;
int retval = -ENODEV;
@@ -220,17 +221,17 @@ static int if_ioctl(struct tty_struct *tty, struct file *file,
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return -ENODEV;
}
- dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __FUNCTION__, cmd);
+ gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd);
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else {
retval = 0;
switch (cmd) {
@@ -250,37 +251,40 @@ static int if_ioctl(struct tty_struct *tty, struct file *file,
break;
case GIGASET_BRKCHARS:
//FIXME test if MS_LOCKED
- gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS",
- 6, (const unsigned char *) arg, 1);
- if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_ANY, "can't communicate with unplugged device");
+ if (!cs->connected) {
+ gig_dbg(DEBUG_ANY,
+ "can't communicate with unplugged device");
retval = -ENODEV;
break;
}
retval = copy_from_user(&buf,
- (const unsigned char __user *) arg, 6)
- ? -EFAULT : 0;
- if (retval >= 0)
+ (const unsigned char __user *) arg, 6)
+ ? -EFAULT : 0;
+ if (retval >= 0) {
+ gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS",
+ 6, (const unsigned char *) arg);
retval = cs->ops->brkchars(cs, buf);
+ }
break;
case GIGASET_VERSION:
- retval = copy_from_user(version, (unsigned __user *) arg,
- sizeof version) ? -EFAULT : 0;
+ retval = copy_from_user(version,
+ (unsigned __user *) arg, sizeof version)
+ ? -EFAULT : 0;
if (retval >= 0)
retval = if_version(cs, version);
if (retval >= 0)
- retval = copy_to_user((unsigned __user *) arg, version,
- sizeof version)
- ? -EFAULT : 0;
+ retval = copy_to_user((unsigned __user *) arg,
+ version, sizeof version)
+ ? -EFAULT : 0;
break;
- default:
- dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x",
- __FUNCTION__, cmd);
+ default:
+ gig_dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x",
+ __func__, cmd);
retval = -ENOIOCTLCMD;
}
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return retval;
}
@@ -292,25 +296,25 @@ static int if_tiocmget(struct tty_struct *tty, struct file *file)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return -ENODEV;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
// FIXME read from device?
retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR);
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return retval;
}
static int if_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
+ unsigned int set, unsigned int clear)
{
struct cardstate *cs;
int retval;
@@ -318,18 +322,18 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file,
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return -ENODEV;
}
- dbg(DEBUG_IF,
- "%u: %s(0x%x, 0x%x)", cs->minor_index, __FUNCTION__, set, clear);
+ gig_dbg(DEBUG_IF, "%u: %s(0x%x, 0x%x)",
+ cs->minor_index, __func__, set, clear);
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
- if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_ANY, "can't communicate with unplugged device");
+ if (!cs->connected) {
+ gig_dbg(DEBUG_ANY, "can't communicate with unplugged device");
retval = -ENODEV;
} else {
mc = (cs->control_state | set) & ~clear & (TIOCM_RTS|TIOCM_DTR);
@@ -337,7 +341,7 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file,
cs->control_state = mc;
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return retval;
}
@@ -349,29 +353,29 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return -ENODEV;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else if (atomic_read(&cs->mstate) != MS_LOCKED) {
warn("can't write to unlocked device");
retval = -EBUSY;
- } else if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_ANY, "can't write to unplugged device");
+ } else if (!cs->connected) {
+ gig_dbg(DEBUG_ANY, "can't write to unplugged device");
retval = -EBUSY; //FIXME
} else {
retval = cs->ops->write_cmd(cs, buf, count,
- &cs->if_wake_tasklet);
+ &cs->if_wake_tasklet);
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return retval;
}
@@ -383,27 +387,27 @@ static int if_write_room(struct tty_struct *tty)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return -ENODEV;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else if (atomic_read(&cs->mstate) != MS_LOCKED) {
warn("can't write to unlocked device");
retval = -EBUSY; //FIXME
- } else if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_ANY, "can't write to unplugged device");
+ } else if (!cs->connected) {
+ gig_dbg(DEBUG_ANY, "can't write to unplugged device");
retval = -EBUSY; //FIXME
} else
retval = cs->ops->write_room(cs);
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return retval;
}
@@ -415,27 +419,27 @@ static int if_chars_in_buffer(struct tty_struct *tty)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return -ENODEV;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else if (atomic_read(&cs->mstate) != MS_LOCKED) {
warn("can't write to unlocked device");
retval = -EBUSY;
- } else if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_ANY, "can't write to unplugged device");
+ } else if (!cs->connected) {
+ gig_dbg(DEBUG_ANY, "can't write to unplugged device");
retval = -EBUSY; //FIXME
} else
retval = cs->ops->chars_in_buffer(cs);
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return retval;
}
@@ -446,21 +450,21 @@ static void if_throttle(struct tty_struct *tty)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- down(&cs->sem);
+ mutex_lock(&cs->mutex);
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else {
//FIXME
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
}
static void if_unthrottle(struct tty_struct *tty)
@@ -469,21 +473,21 @@ static void if_unthrottle(struct tty_struct *tty)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- down(&cs->sem);
+ mutex_lock(&cs->mutex);
if (!cs->open_count)
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
else {
//FIXME
}
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
}
static void if_set_termios(struct tty_struct *tty, struct termios *old)
@@ -496,21 +500,21 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old)
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
- err("cs==NULL in %s", __FUNCTION__);
+ err("cs==NULL in %s", __func__);
return;
}
- dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+ gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- down(&cs->sem);
+ mutex_lock(&cs->mutex);
if (!cs->open_count) {
- warn("%s: device not opened", __FUNCTION__);
+ warn("%s: device not opened", __func__);
goto out;
}
- if (!atomic_read(&cs->connected)) {
- dbg(DEBUG_ANY, "can't communicate with unplugged device");
+ if (!cs->connected) {
+ gig_dbg(DEBUG_ANY, "can't communicate with unplugged device");
goto out;
}
@@ -518,8 +522,8 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old)
iflag = tty->termios->c_iflag;
cflag = tty->termios->c_cflag;
old_cflag = old ? old->c_cflag : cflag; //FIXME?
- dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", cs->minor_index,
- iflag, cflag, old_cflag);
+ gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x",
+ cs->minor_index, iflag, cflag, old_cflag);
/* get a local copy of the current port settings */
control_state = cs->control_state;
@@ -531,14 +535,15 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old)
* Premature optimization is the root of all evil.
*/
- /* reassert DTR and (maybe) RTS on transition from B0 */
+ /* reassert DTR and (maybe) RTS on transition from B0 */
if ((old_cflag & CBAUD) == B0) {
new_state = control_state | TIOCM_DTR;
/* don't set RTS if using hardware flow control */
if (!(old_cflag & CRTSCTS))
new_state |= TIOCM_RTS;
- dbg(DEBUG_IF, "%u: from B0 - set DTR%s", cs->minor_index,
- (new_state & TIOCM_RTS) ? " only" : "/RTS");
+ gig_dbg(DEBUG_IF, "%u: from B0 - set DTR%s",
+ cs->minor_index,
+ (new_state & TIOCM_RTS) ? " only" : "/RTS");
cs->ops->set_modem_ctrl(cs, control_state, new_state);
control_state = new_state;
}
@@ -547,7 +552,7 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old)
if ((cflag & CBAUD) == B0) {
/* Drop RTS and DTR */
- dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index);
+ gig_dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index);
new_state = control_state & ~(TIOCM_DTR | TIOCM_RTS);
cs->ops->set_modem_ctrl(cs, control_state, new_state);
control_state = new_state;
@@ -567,15 +572,17 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old)
* Just do what we have seen with SniffUSB on Win98.
*/
/* Drop DTR/RTS if no flow control otherwise assert */
- dbg(DEBUG_IF, "%u: control_state %x", cs->minor_index, control_state);
+ gig_dbg(DEBUG_IF, "%u: control_state %x",
+ cs->minor_index, control_state);
new_state = control_state;
if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
new_state |= TIOCM_DTR | TIOCM_RTS;
else
new_state &= ~(TIOCM_DTR | TIOCM_RTS);
if (new_state != control_state) {
- dbg(DEBUG_IF, "%u: new_state %x", cs->minor_index, new_state);
- gigaset_set_modem_ctrl(cs, control_state, new_state); // FIXME: mct_u232.c sets the old state here. is this a bug?
+ gig_dbg(DEBUG_IF, "%u: new_state %x",
+ cs->minor_index, new_state);
+ gigaset_set_modem_ctrl(cs, control_state, new_state);
control_state = new_state;
}
#endif
@@ -584,7 +591,7 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old)
cs->control_state = control_state;
out:
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
}
@@ -600,7 +607,7 @@ static void if_wake(unsigned long data)
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup) {
- dbg(DEBUG_IF, "write wakeup call");
+ gig_dbg(DEBUG_IF, "write wakeup call");
tty->ldisc.write_wakeup(tty);
}
@@ -635,14 +642,14 @@ void gigaset_if_free(struct cardstate *cs)
}
void gigaset_if_receive(struct cardstate *cs,
- unsigned char *buffer, size_t len)
+ unsigned char *buffer, size_t len)
{
unsigned long flags;
struct tty_struct *tty;
spin_lock_irqsave(&cs->lock, flags);
if ((tty = cs->tty) == NULL)
- dbg(DEBUG_ANY, "receive on closed device");
+ gig_dbg(DEBUG_ANY, "receive on closed device");
else {
tty_buffer_request_room(tty, len);
tty_insert_flip_string(tty, buffer, len);
@@ -655,13 +662,13 @@ EXPORT_SYMBOL_GPL(gigaset_if_receive);
/* gigaset_if_initdriver
* Initialize tty interface.
* parameters:
- * drv Driver
- * procname Name of the driver (e.g. for /proc/tty/drivers)
- * devname Name of the device files (prefix without minor number)
- * devfsname Devfs name of the device files without %d
+ * drv Driver
+ * procname Name of the driver (e.g. for /proc/tty/drivers)
+ * devname Name of the device files (prefix without minor number)
+ * devfsname Devfs name of the device files without %d
*/
void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
- const char *devname, const char *devfsname)
+ const char *devname, const char *devfsname)
{
unsigned minors = drv->minors;
int ret;
@@ -696,7 +703,7 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
warn("failed to register tty driver (error %d)", ret);
goto error;
}
- dbg(DEBUG_IF, "tty driver initialized");
+ gig_dbg(DEBUG_IF, "tty driver initialized");
drv->have_tty = 1;
return;
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 5744eb91b31..8667daaa1a8 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -10,10 +10,6 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: isocdata.c,v 1.2.2.5 2005/11/13 23:05:19 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
@@ -87,14 +83,14 @@ static inline int isowbuf_startwrite(struct isowbuf_t *iwb)
{
if (!atomic_dec_and_test(&iwb->writesem)) {
atomic_inc(&iwb->writesem);
- dbg(DEBUG_ISO,
- "%s: couldn't acquire iso write semaphore", __func__);
+ gig_dbg(DEBUG_ISO, "%s: couldn't acquire iso write semaphore",
+ __func__);
return 0;
}
#ifdef CONFIG_GIGASET_DEBUG
- dbg(DEBUG_ISO,
- "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
- __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits);
+ gig_dbg(DEBUG_ISO,
+ "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
+ __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits);
#endif
return 1;
}
@@ -147,7 +143,7 @@ static inline void isowbuf_putflag(struct isowbuf_t *iwb)
/* recover the idle flag byte */
write = atomic_read(&iwb->write);
iwb->idle = iwb->data[write];
- dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle);
+ gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle);
/* mask extraneous bits in buffer */
iwb->data[write] &= (1 << iwb->wbits) - 1;
}
@@ -166,15 +162,14 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
read = atomic_read(&iwb->nextread);
write = atomic_read(&iwb->write);
if (likely(read == write)) {
- //dbg(DEBUG_STREAM, "%s: send buffer empty", __func__);
/* return idle frame */
return read < BAS_OUTBUFPAD ?
- BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD;
+ BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD;
}
limit = read + size;
- dbg(DEBUG_STREAM,
- "%s: read=%d write=%d limit=%d", __func__, read, write, limit);
+ gig_dbg(DEBUG_STREAM, "%s: read=%d write=%d limit=%d",
+ __func__, read, write, limit);
#ifdef CONFIG_GIGASET_DEBUG
if (unlikely(size < 0 || size > BAS_OUTBUFPAD)) {
err("invalid size %d", size);
@@ -196,11 +191,12 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
return -EBUSY;
/* write position could have changed */
if (limit >= (write = atomic_read(&iwb->write))) {
- pbyte = iwb->data[write]; /* save partial byte */
+ pbyte = iwb->data[write]; /* save
+ partial byte */
limit = write + BAS_OUTBUFPAD;
- dbg(DEBUG_STREAM,
- "%s: filling %d->%d with %02x",
- __func__, write, limit, iwb->idle);
+ gig_dbg(DEBUG_STREAM,
+ "%s: filling %d->%d with %02x",
+ __func__, write, limit, iwb->idle);
if (write + BAS_OUTBUFPAD < BAS_OUTBUFSIZE)
memset(iwb->data + write, iwb->idle,
BAS_OUTBUFPAD);
@@ -211,9 +207,11 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
- write);
limit = 0;
}
- dbg(DEBUG_STREAM, "%s: restoring %02x at %d",
- __func__, pbyte, limit);
- iwb->data[limit] = pbyte; /* restore partial byte */
+ gig_dbg(DEBUG_STREAM,
+ "%s: restoring %02x at %d",
+ __func__, pbyte, limit);
+ iwb->data[limit] = pbyte; /* restore
+ partial byte */
atomic_set(&iwb->write, limit);
}
isowbuf_donewrite(iwb);
@@ -242,19 +240,17 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
* write hex bytes to syslog for debugging
*/
static inline void dump_bytes(enum debuglevel level, const char *tag,
- unsigned char *bytes, int count)
+ unsigned char *bytes, int count)
{
#ifdef CONFIG_GIGASET_DEBUG
unsigned char c;
static char dbgline[3 * 32 + 1];
static const char hexdigit[] = "0123456789abcdef";
int i = 0;
- IFNULLRET(tag);
- IFNULLRET(bytes);
while (count-- > 0) {
if (i > sizeof(dbgline) - 4) {
dbgline[i] = '\0';
- dbg(level, "%s:%s", tag, dbgline);
+ gig_dbg(level, "%s:%s", tag, dbgline);
i = 0;
}
c = *bytes++;
@@ -264,7 +260,7 @@ static inline void dump_bytes(enum debuglevel level, const char *tag,
dbgline[i++] = hexdigit[c & 0x0f];
}
dbgline[i] = '\0';
- dbg(level, "%s:%s", tag, dbgline);
+ gig_dbg(level, "%s:%s", tag, dbgline);
#endif
}
@@ -380,7 +376,7 @@ static u16 stufftab[5 * 256] = {
*/
static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin,
- int ones)
+ int ones)
{
u16 stuff;
int shiftinc, newones;
@@ -422,7 +418,7 @@ static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin,
*/
static inline int hdlc_buildframe(struct isowbuf_t *iwb,
- unsigned char *in, int count)
+ unsigned char *in, int count)
{
int ones;
u16 fcs;
@@ -431,8 +427,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb,
if (isowbuf_freebytes(iwb) < count + count / 5 + 6 ||
!isowbuf_startwrite(iwb)) {
- dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN",
- __func__, isowbuf_freebytes(iwb));
+ gig_dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN",
+ __func__, isowbuf_freebytes(iwb));
return -EAGAIN;
}
@@ -484,11 +480,11 @@ static inline int trans_buildframe(struct isowbuf_t *iwb,
if (isowbuf_freebytes(iwb) < count ||
!isowbuf_startwrite(iwb)) {
- dbg(DEBUG_ISO, "can't put %d bytes", count);
+ gig_dbg(DEBUG_ISO, "can't put %d bytes", count);
return -EAGAIN;
}
- dbg(DEBUG_STREAM, "put %d bytes", count);
+ gig_dbg(DEBUG_STREAM, "put %d bytes", count);
write = atomic_read(&iwb->write);
do {
c = gigaset_invtab[*in++];
@@ -508,11 +504,13 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len)
switch (bcs->proto2) {
case ISDN_PROTO_L2_HDLC:
result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len);
- dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", __func__, len, result);
+ gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d",
+ __func__, len, result);
break;
default: /* assume transparent */
result = trans_buildframe(bcs->hw.bas->isooutbuf, in, len);
- dbg(DEBUG_ISO, "%s: %d bytes trans -> %d", __func__, len, result);
+ gig_dbg(DEBUG_ISO, "%s: %d bytes trans -> %d",
+ __func__, len, result);
}
return result;
}
@@ -528,13 +526,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
return;
}
if (unlikely(bcs->skb->len == SBUFSIZE)) {
- warn("received oversized packet discarded");
+ dev_warn(bcs->cs->dev, "received oversized packet discarded\n");
bcs->hw.bas->giants++;
dev_kfree_skb_any(bcs->skb);
bcs->skb = NULL;
return;
}
- *gigaset_skb_put_quick(bcs->skb, 1) = c;
+ *__skb_put(bcs->skb, 1) = c;
}
/* hdlc_flush
@@ -549,7 +547,7 @@ static inline void hdlc_flush(struct bc_state *bcs)
if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
skb_reserve(bcs->skb, HW_HDR_LEN);
else
- err("could not allocate skb");
+ dev_err(bcs->cs->dev, "could not allocate skb\n");
}
/* reset packet state */
@@ -571,23 +569,25 @@ static inline void hdlc_done(struct bc_state *bcs)
if ((procskb = bcs->skb) == NULL) {
/* previous error */
- dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
+ gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
gigaset_rcv_error(NULL, bcs->cs, bcs);
} else if (procskb->len < 2) {
- notice("received short frame (%d octets)", procskb->len);
+ dev_notice(bcs->cs->dev, "received short frame (%d octets)\n",
+ procskb->len);
bcs->hw.bas->runts++;
gigaset_rcv_error(procskb, bcs->cs, bcs);
} else if (bcs->fcs != PPP_GOODFCS) {
- notice("frame check error (0x%04x)", bcs->fcs);
+ dev_notice(bcs->cs->dev, "frame check error (0x%04x)\n",
+ bcs->fcs);
bcs->hw.bas->fcserrs++;
gigaset_rcv_error(procskb, bcs->cs, bcs);
} else {
procskb->len -= 2; /* subtract FCS */
procskb->tail -= 2;
- dbg(DEBUG_ISO,
- "%s: good frame (%d octets)", __func__, procskb->len);
+ gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)",
+ __func__, procskb->len);
dump_bytes(DEBUG_STREAM,
- "rcv data", procskb->data, procskb->len);
+ "rcv data", procskb->data, procskb->len);
bcs->hw.bas->goodbytes += procskb->len;
gigaset_rcv_skb(procskb, bcs->cs, bcs);
}
@@ -595,7 +595,7 @@ static inline void hdlc_done(struct bc_state *bcs)
if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
skb_reserve(bcs->skb, HW_HDR_LEN);
else
- err("could not allocate skb");
+ dev_err(bcs->cs->dev, "could not allocate skb\n");
bcs->fcs = PPP_INITFCS;
}
@@ -610,14 +610,14 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)
return;
}
- notice("received partial byte (%d bits)", inbits);
+ dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
bcs->hw.bas->alignerrs++;
gigaset_rcv_error(bcs->skb, bcs->cs, bcs);
if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
skb_reserve(bcs->skb, HW_HDR_LEN);
else
- err("could not allocate skb");
+ dev_err(bcs->cs->dev, "could not allocate skb\n");
bcs->fcs = PPP_INITFCS;
}
@@ -659,16 +659,12 @@ static unsigned char bitcounts[256] = {
* bcs receiving B channel structure
*/
static inline void hdlc_unpack(unsigned char *src, unsigned count,
- struct bc_state *bcs)
+ struct bc_state *bcs)
{
- struct bas_bc_state *ubc;
+ struct bas_bc_state *ubc = bcs->hw.bas;
int inputstate;
unsigned seqlen, inbyte, inbits;
- IFNULLRET(bcs);
- ubc = bcs->hw.bas;
- IFNULLRET(ubc);
-
/* load previous state:
* inputstate = set of flag bits:
* - INS_flag_hunt: no complete opening flag received since connection setup or last abort
@@ -856,7 +852,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
* bcs receiving B channel structure
*/
static inline void trans_receive(unsigned char *src, unsigned count,
- struct bc_state *bcs)
+ struct bc_state *bcs)
{
struct sk_buff *skb;
int dobytes;
@@ -870,7 +866,7 @@ static inline void trans_receive(unsigned char *src, unsigned count,
if (unlikely((skb = bcs->skb) == NULL)) {
bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
if (!skb) {
- err("could not allocate skb");
+ dev_err(bcs->cs->dev, "could not allocate skb\n");
return;
}
skb_reserve(skb, HW_HDR_LEN);
@@ -888,7 +884,8 @@ static inline void trans_receive(unsigned char *src, unsigned count,
gigaset_rcv_skb(skb, bcs->cs, bcs);
bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
if (!skb) {
- err("could not allocate skb");
+ dev_err(bcs->cs->dev,
+ "could not allocate skb\n");
return;
}
skb_reserve(bcs->skb, HW_HDR_LEN);
@@ -921,8 +918,8 @@ static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf)
case '\r':
case '\n':
/* end of line */
- dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
- __func__, cbytes);
+ gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
+ __func__, cbytes);
cs->cbytes = cbytes;
gigaset_handle_modem_response(cs);
cbytes = 0;
@@ -932,7 +929,7 @@ static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf)
if (cbytes < MAX_RESP_SIZE - 1)
cbytes++;
else
- warn("response too large");
+ dev_warn(cs->dev, "response too large\n");
}
}
@@ -951,27 +948,27 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
head = atomic_read(&inbuf->head);
while (head != (tail = atomic_read(&inbuf->tail))) {
- dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
+ gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
if (head > tail)
tail = RBUFSIZE;
src = inbuf->data + head;
numbytes = tail - head;
- dbg(DEBUG_INTR, "processing %u bytes", numbytes);
+ gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
if (atomic_read(&cs->mstate) == MS_LOCKED) {
gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
- numbytes, src, 0);
+ numbytes, src);
gigaset_if_receive(inbuf->cs, src, numbytes);
} else {
gigaset_dbg_buffer(DEBUG_CMD, "received response",
- numbytes, src, 0);
+ numbytes, src);
cmd_loop(src, numbytes, inbuf);
}
head += numbytes;
if (head == RBUFSIZE)
head = 0;
- dbg(DEBUG_INTR, "setting head to %u", head);
+ gig_dbg(DEBUG_INTR, "setting head to %u", head);
atomic_set(&inbuf->head, head);
}
}
@@ -992,18 +989,22 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
*/
int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb)
{
- int len;
+ int len = skb->len;
+ unsigned long flags;
- IFNULLRETVAL(bcs, -EFAULT);
- IFNULLRETVAL(skb, -EFAULT);
- len = skb->len;
+ spin_lock_irqsave(&bcs->cs->lock, flags);
+ if (!bcs->cs->connected) {
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
+ return -ENODEV;
+ }
skb_queue_tail(&bcs->squeue, skb);
- dbg(DEBUG_ISO,
- "%s: skb queued, qlen=%d", __func__, skb_queue_len(&bcs->squeue));
+ gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d",
+ __func__, skb_queue_len(&bcs->squeue));
/* tasklet submits URB if necessary */
tasklet_schedule(&bcs->hw.bas->sent_tasklet);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
return len; /* ok so far */
}
diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c
index c6915fa2be6..d267a636b53 100644
--- a/drivers/isdn/gigaset/proc.c
+++ b/drivers/isdn/gigaset/proc.c
@@ -1,7 +1,7 @@
/*
* Stuff used by all variants of the driver
*
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Copyright (c) 2001 by Stefan Eilers,
* Hansjoerg Lipp <hjlipp@web.de>,
* Tilman Schmidt <tilman@imap.cc>.
*
@@ -11,26 +11,29 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: proc.c,v 1.5.2.13 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
#include <linux/ctype.h>
-static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- struct usb_interface *intf = to_usb_interface(dev);
- struct cardstate *cs = usb_get_intfdata(intf);
- return sprintf(buf, "%d\n", atomic_read(&cs->cidmode)); // FIXME use scnprintf for 13607 bit architectures (if PAGE_SIZE==4096)
+ int ret;
+ unsigned long flags;
+ struct cardstate *cs = dev_get_drvdata(dev);
+
+ spin_lock_irqsave(&cs->lock, flags);
+ ret = sprintf(buf, "%u\n", cs->cidmode);
+ spin_unlock_irqrestore(&cs->lock, flags);
+
+ return ret;
}
-static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct usb_interface *intf = to_usb_interface(dev);
- struct cardstate *cs = usb_get_intfdata(intf);
+ struct cardstate *cs = dev_get_drvdata(dev);
long int value;
char *end;
@@ -41,23 +44,23 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, co
if (value < 0 || value > 1)
return -EINVAL;
- if (down_interruptible(&cs->sem))
+ if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
cs->waiting = 1;
if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE,
- NULL, value, NULL)) {
+ NULL, value, NULL)) {
cs->waiting = 0;
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return -ENOMEM;
}
- dbg(DEBUG_CMD, "scheduling PROC_CIDMODE");
+ gig_dbg(DEBUG_CMD, "scheduling PROC_CIDMODE");
gigaset_schedule_event(cs);
wait_event(cs->waitqueue, !cs->waiting);
- up(&cs->sem);
+ mutex_unlock(&cs->mutex);
return count;
}
@@ -65,17 +68,15 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, co
static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode);
/* free sysfs for device */
-void gigaset_free_dev_sysfs(struct usb_interface *interface)
+void gigaset_free_dev_sysfs(struct cardstate *cs)
{
- dbg(DEBUG_INIT, "removing sysfs entries");
- device_remove_file(&interface->dev, &dev_attr_cidmode);
+ gig_dbg(DEBUG_INIT, "removing sysfs entries");
+ device_remove_file(cs->dev, &dev_attr_cidmode);
}
-EXPORT_SYMBOL_GPL(gigaset_free_dev_sysfs);
/* initialize sysfs for device */
-void gigaset_init_dev_sysfs(struct usb_interface *interface)
+void gigaset_init_dev_sysfs(struct cardstate *cs)
{
- dbg(DEBUG_INIT, "setting up sysfs");
- device_create_file(&interface->dev, &dev_attr_cidmode);
+ gig_dbg(DEBUG_INIT, "setting up sysfs");
+ device_create_file(cs->dev, &dev_attr_cidmode);
}
-EXPORT_SYMBOL_GPL(gigaset_init_dev_sysfs);
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index 323fc7349de..d86ab68114b 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -1,7 +1,7 @@
/*
* USB driver for Gigaset 307x directly or using M105 Data.
*
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>
+ * Copyright (c) 2001 by Stefan Eilers
* and Hansjoerg Lipp <hjlipp@web.de>.
*
* This driver was derived from the USB skeleton driver by
@@ -13,10 +13,6 @@
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: usb-gigaset.c,v 1.85.4.18 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
*/
#include "gigaset.h"
@@ -29,7 +25,7 @@
#include <linux/moduleparam.h>
/* Version Information */
-#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers"
#define DRIVER_DESC "USB Driver for Gigaset 307x using M105"
/* Module parameters */
@@ -62,10 +58,6 @@ static struct usb_device_id gigaset_table [] = {
MODULE_DEVICE_TABLE(usb, gigaset_table);
-/* Get a minor range for your devices from the usb maintainer */
-#define USB_SKEL_MINOR_BASE 200
-
-
/*
* Control requests (empty fields: 00)
*
@@ -114,7 +106,7 @@ MODULE_DEVICE_TABLE(usb, gigaset_table);
*/
static int gigaset_probe(struct usb_interface *interface,
- const struct usb_device_id *id);
+ const struct usb_device_id *id);
static void gigaset_disconnect(struct usb_interface *interface);
static struct gigaset_driver *driver = NULL;
@@ -122,29 +114,29 @@ static struct cardstate *cardstate = NULL;
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver gigaset_usb_driver = {
- .name = GIGASET_MODULENAME,
- .probe = gigaset_probe,
- .disconnect = gigaset_disconnect,
- .id_table = gigaset_table,
+ .name = GIGASET_MODULENAME,
+ .probe = gigaset_probe,
+ .disconnect = gigaset_disconnect,
+ .id_table = gigaset_table,
};
struct usb_cardstate {
- struct usb_device *udev; /* save off the usb device pointer */
- struct usb_interface *interface; /* the interface for this device */
- atomic_t busy; /* bulk output in progress */
-
- /* Output buffer for commands (M105: and data)*/
- unsigned char *bulk_out_buffer; /* the buffer to send data */
- int bulk_out_size; /* the size of the send buffer */
- __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
- struct urb *bulk_out_urb; /* the urb used to transmit data */
-
- /* Input buffer for command responses (M105: and data)*/
- int rcvbuf_size; /* the size of the receive buffer */
- struct urb *read_urb; /* the urb used to receive data */
- __u8 int_in_endpointAddr; /* the address of the bulk in endpoint */
-
- char bchars[6]; /* req. 0x19 */
+ struct usb_device *udev; /* usb device pointer */
+ struct usb_interface *interface; /* interface for this device */
+ atomic_t busy; /* bulk output in progress */
+
+ /* Output buffer */
+ unsigned char *bulk_out_buffer;
+ int bulk_out_size;
+ __u8 bulk_out_endpointAddr;
+ struct urb *bulk_out_urb;
+
+ /* Input buffer */
+ int rcvbuf_size;
+ struct urb *read_urb;
+ __u8 int_in_endpointAddr;
+
+ char bchars[6]; /* for request 0x19 */
};
struct usb_bc_state {};
@@ -157,19 +149,20 @@ static inline unsigned tiocm_to_gigaset(unsigned state)
#ifdef CONFIG_GIGASET_UNDOCREQ
/* WARNING: EXPERIMENTAL! */
static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
- unsigned new_state)
+ unsigned new_state)
{
+ struct usb_device *udev = cs->hw.usb->udev;
unsigned mask, val;
int r;
mask = tiocm_to_gigaset(old_state ^ new_state);
val = tiocm_to_gigaset(new_state);
- dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask);
- r = usb_control_msg(cs->hw.usb->udev,
- usb_sndctrlpipe(cs->hw.usb->udev, 0), 7, 0x41,
- (val & 0xff) | ((mask & 0xff) << 8), 0,
- NULL, 0, 2000 /*timeout??*/); // don't use this in an interrupt/BH
+ gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask);
+ // don't use this in an interrupt/BH
+ r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41,
+ (val & 0xff) | ((mask & 0xff) << 8), 0,
+ NULL, 0, 2000 /* timeout? */);
if (r < 0)
return r;
//..
@@ -178,30 +171,29 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
static int set_value(struct cardstate *cs, u8 req, u16 val)
{
+ struct usb_device *udev = cs->hw.usb->udev;
int r, r2;
- dbg(DEBUG_USBREQ, "request %02x (%04x)", (unsigned)req, (unsigned)val);
- r = usb_control_msg(cs->hw.usb->udev,
- usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x12, 0x41,
- 0xf /*?*/, 0,
- NULL, 0, 2000 /*?*/); /* no idea, what this does */
+ gig_dbg(DEBUG_USBREQ, "request %02x (%04x)",
+ (unsigned)req, (unsigned)val);
+ r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x12, 0x41,
+ 0xf /*?*/, 0, NULL, 0, 2000 /*?*/);
+ /* no idea what this does */
if (r < 0) {
- err("error %d on request 0x12", -r);
+ dev_err(&udev->dev, "error %d on request 0x12\n", -r);
return r;
}
- r = usb_control_msg(cs->hw.usb->udev,
- usb_sndctrlpipe(cs->hw.usb->udev, 0), req, 0x41,
- val, 0,
- NULL, 0, 2000 /*?*/);
+ r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), req, 0x41,
+ val, 0, NULL, 0, 2000 /*?*/);
if (r < 0)
- err("error %d on request 0x%02x", -r, (unsigned)req);
+ dev_err(&udev->dev, "error %d on request 0x%02x\n",
+ -r, (unsigned)req);
- r2 = usb_control_msg(cs->hw.usb->udev,
- usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41,
- 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/);
+ r2 = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41,
+ 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/);
if (r2 < 0)
- err("error %d on request 0x19", -r2);
+ dev_err(&udev->dev, "error %d on request 0x19\n", -r2);
return r < 0 ? r : (r2 < 0 ? r2 : 0);
}
@@ -229,8 +221,8 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
case B115200: rate = 115200; break;
default:
rate = 9600;
- err("unsupported baudrate request 0x%x,"
- " using default of B9600", cflag);
+ dev_err(cs->dev, "unsupported baudrate request 0x%x,"
+ " using default of B9600\n", cflag);
}
val = 0x383fff / rate + 1;
@@ -259,7 +251,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
case CS8:
val |= 8 << 8; break;
default:
- err("CSIZE was not CS5-CS8, using default of 8");
+ dev_err(cs->dev, "CSIZE was not CS5-CS8, using default of 8\n");
val |= 8 << 8;
break;
}
@@ -277,7 +269,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
#else
static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
- unsigned new_state)
+ unsigned new_state)
{
return -EINVAL;
}
@@ -309,15 +301,12 @@ static int gigaset_close_bchannel(struct bc_state *bcs)
return 0;
}
-//void send_ack_to_LL(void *data);
static int write_modem(struct cardstate *cs);
static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb);
-/* Handling of send queue. If there is already a skb opened, put data to
- * the transfer buffer by calling "write_modem". Otherwise take a new skb out of the queue.
- * This function will be called by the ISR via "transmit_chars" (USB: B-Channel Bulk callback handler
- * via immediate task queue) or by writebuf_from_LL if the LL wants to transmit data.
+/* Write tasklet handler: Continue sending current skb, or send command, or
+ * start sending an skb from the send queue.
*/
static void gigaset_modem_fill(unsigned long data)
{
@@ -327,10 +316,10 @@ static void gigaset_modem_fill(unsigned long data)
unsigned long flags;
int again;
- dbg(DEBUG_OUTPUT, "modem_fill");
+ gig_dbg(DEBUG_OUTPUT, "modem_fill");
if (atomic_read(&cs->hw.usb->busy)) {
- dbg(DEBUG_OUTPUT, "modem_fill: busy");
+ gig_dbg(DEBUG_OUTPUT, "modem_fill: busy");
return;
}
@@ -341,26 +330,27 @@ static void gigaset_modem_fill(unsigned long data)
cb = cs->cmdbuf;
spin_unlock_irqrestore(&cs->cmdlock, flags);
if (cb) { /* commands to send? */
- dbg(DEBUG_OUTPUT, "modem_fill: cb");
+ gig_dbg(DEBUG_OUTPUT, "modem_fill: cb");
if (send_cb(cs, cb) < 0) {
- dbg(DEBUG_OUTPUT,
- "modem_fill: send_cb failed");
- again = 1; /* no callback will be called! */
+ gig_dbg(DEBUG_OUTPUT,
+ "modem_fill: send_cb failed");
+ again = 1; /* no callback will be
+ called! */
}
} else { /* skbs to send? */
bcs->tx_skb = skb_dequeue(&bcs->squeue);
if (bcs->tx_skb)
- dbg(DEBUG_INTR,
- "Dequeued skb (Adr: %lx)!",
- (unsigned long) bcs->tx_skb);
+ gig_dbg(DEBUG_INTR,
+ "Dequeued skb (Adr: %lx)!",
+ (unsigned long) bcs->tx_skb);
}
}
if (bcs->tx_skb) {
- dbg(DEBUG_OUTPUT, "modem_fill: tx_skb");
+ gig_dbg(DEBUG_OUTPUT, "modem_fill: tx_skb");
if (write_modem(cs) < 0) {
- dbg(DEBUG_OUTPUT,
- "modem_fill: write_modem failed");
+ gig_dbg(DEBUG_OUTPUT,
+ "modem_fill: write_modem failed");
// FIXME should we tell the LL?
again = 1; /* no callback will be called! */
}
@@ -371,88 +361,85 @@ static void gigaset_modem_fill(unsigned long data)
/**
* gigaset_read_int_callback
*
- * It is called if the data was received from the device. This is almost similiar to
- * the interrupt service routine in the serial device.
+ * It is called if the data was received from the device.
*/
static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs)
{
+ struct inbuf_t *inbuf = urb->context;
+ struct cardstate *cs = inbuf->cs;
int resubmit = 0;
int r;
- struct cardstate *cs;
unsigned numbytes;
unsigned char *src;
- //unsigned long flags;
- struct inbuf_t *inbuf;
-
- IFNULLRET(urb);
- inbuf = (struct inbuf_t *) urb->context;
- IFNULLRET(inbuf);
- //spin_lock_irqsave(&inbuf->lock, flags);
- cs = inbuf->cs;
- IFNULLGOTO(cs, exit);
- IFNULLGOTO(cardstate, exit);
-
- if (!atomic_read(&cs->connected)) {
- err("%s: disconnected", __func__);
- goto exit;
- }
+ unsigned long flags;
if (!urb->status) {
+ if (!cs->connected) {
+ err("%s: disconnected", __func__); /* should never happen */
+ return;
+ }
+
numbytes = urb->actual_length;
if (numbytes) {
src = inbuf->rcvbuf;
if (unlikely(*src))
- warn("%s: There was no leading 0, but 0x%02x!",
- __func__, (unsigned) *src);
+ dev_warn(cs->dev,
+ "%s: There was no leading 0, but 0x%02x!\n",
+ __func__, (unsigned) *src);
++src; /* skip leading 0x00 */
--numbytes;
if (gigaset_fill_inbuf(inbuf, src, numbytes)) {
- dbg(DEBUG_INTR, "%s-->BH", __func__);
+ gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
gigaset_schedule_event(inbuf->cs);
}
} else
- dbg(DEBUG_INTR, "Received zero block length");
+ gig_dbg(DEBUG_INTR, "Received zero block length");
resubmit = 1;
} else {
/* The urb might have been killed. */
- dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
- __func__, urb->status);
- if (urb->status != -ENOENT) /* not killed */
+ gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
+ __func__, urb->status);
+ if (urb->status != -ENOENT) { /* not killed */
+ if (!cs->connected) {
+ err("%s: disconnected", __func__); /* should never happen */
+ return;
+ }
resubmit = 1;
+ }
}
-exit:
- //spin_unlock_irqrestore(&inbuf->lock, flags);
+
if (resubmit) {
- r = usb_submit_urb(urb, SLAB_ATOMIC);
+ spin_lock_irqsave(&cs->lock, flags);
+ r = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
+ spin_unlock_irqrestore(&cs->lock, flags);
if (r)
- err("error %d when resubmitting urb.", -r);
+ dev_err(cs->dev, "error %d when resubmitting urb.\n",
+ -r);
}
}
-/* This callback routine is called when data was transmitted to a B-Channel.
- * Therefore it has to check if there is still data to transmit. This
- * happens by calling modem_fill via task queue.
- *
- */
+/* This callback routine is called when data was transmitted to the device. */
static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
{
- struct cardstate *cs = (struct cardstate *) urb->context;
+ struct cardstate *cs = urb->context;
+ unsigned long flags;
- IFNULLRET(cs);
-#ifdef CONFIG_GIGASET_DEBUG
- if (!atomic_read(&cs->connected)) {
- err("%s:not connected", __func__);
- return;
- }
-#endif
if (urb->status)
- err("bulk transfer failed (status %d)", -urb->status); /* That's all we can do. Communication problems
- are handeled by timeouts or network protocols */
+ dev_err(cs->dev, "bulk transfer failed (status %d)\n",
+ -urb->status);
+ /* That's all we can do. Communication problems
+ are handled by timeouts or network protocols. */
- atomic_set(&cs->hw.usb->busy, 0);
- tasklet_schedule(&cs->write_tasklet);
+ spin_lock_irqsave(&cs->lock, flags);
+ if (!cs->connected) {
+ err("%s: not connected", __func__);
+ } else {
+ atomic_set(&cs->hw.usb->busy, 0);
+ tasklet_schedule(&cs->write_tasklet);
+ }
+ spin_unlock_irqrestore(&cs->lock, flags);
}
static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
@@ -469,8 +456,8 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
spin_lock_irqsave(&cs->cmdlock, flags);
cs->cmdbytes -= cs->curlen;
- dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left",
- cs->curlen, cs->cmdbytes);
+ gig_dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left",
+ cs->curlen, cs->cmdbytes);
cs->cmdbuf = cb = cb->next;
if (cb) {
cb->prev = NULL;
@@ -487,52 +474,51 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
}
if (cb) {
count = min(cb->len, ucs->bulk_out_size);
+ gig_dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count);
+
usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
- usb_sndbulkpipe(ucs->udev,
- ucs->bulk_out_endpointAddr & 0x0f),
- cb->buf + cb->offset, count,
- gigaset_write_bulk_callback, cs);
+ usb_sndbulkpipe(ucs->udev,
+ ucs->bulk_out_endpointAddr & 0x0f),
+ cb->buf + cb->offset, count,
+ gigaset_write_bulk_callback, cs);
cb->offset += count;
cb->len -= count;
atomic_set(&ucs->busy, 1);
- dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count);
- status = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
+ spin_lock_irqsave(&cs->lock, flags);
+ status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC) : -ENODEV;
+ spin_unlock_irqrestore(&cs->lock, flags);
+
if (status) {
atomic_set(&ucs->busy, 0);
- err("could not submit urb (error %d).",
+ err("could not submit urb (error %d)\n",
-status);
- cb->len = 0; /* skip urb => remove cb+wakeup in next loop cycle */
+ cb->len = 0; /* skip urb => remove cb+wakeup
+ in next loop cycle */
}
}
- } while (cb && status); /* bei Fehler naechster Befehl //FIXME: ist das OK? */
+ } while (cb && status); /* next command on error */
return status;
}
-/* Write string into transbuf and send it to modem.
- */
+/* Send command to device. */
static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
- int len, struct tasklet_struct *wake_tasklet)
+ int len, struct tasklet_struct *wake_tasklet)
{
struct cmdbuf_t *cb;
unsigned long flags;
gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
- DEBUG_TRANSCMD : DEBUG_LOCKCMD,
- "CMD Transmit", len, buf, 0);
-
- if (!atomic_read(&cs->connected)) {
- err("%s: not connected", __func__);
- return -ENODEV;
- }
+ DEBUG_TRANSCMD : DEBUG_LOCKCMD,
+ "CMD Transmit", len, buf);
if (len <= 0)
return 0;
if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
- err("%s: out of memory", __func__);
+ dev_err(cs->dev, "%s: out of memory\n", __func__);
return -ENOMEM;
}
@@ -554,7 +540,10 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
cs->lastcmdbuf = cb;
spin_unlock_irqrestore(&cs->cmdlock, flags);
- tasklet_schedule(&cs->write_tasklet);
+ spin_lock_irqsave(&cs->lock, flags);
+ if (cs->connected)
+ tasklet_schedule(&cs->write_tasklet);
+ spin_unlock_irqrestore(&cs->lock, flags);
return len;
}
@@ -578,11 +567,12 @@ static int gigaset_chars_in_buffer(struct cardstate *cs)
static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
{
#ifdef CONFIG_GIGASET_UNDOCREQ
- gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf, 0);
+ struct usb_device *udev = cs->hw.usb->udev;
+
+ gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf);
memcpy(cs->hw.usb->bchars, buf, 6);
- return usb_control_msg(cs->hw.usb->udev,
- usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41,
- 0, 0, &buf, 6, 2000);
+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41,
+ 0, 0, &buf, 6, 2000);
#else
return -EINVAL;
#endif
@@ -604,7 +594,6 @@ static int gigaset_initbcshw(struct bc_state *bcs)
if (!bcs->hw.usb)
return 0;
- //bcs->hw.usb->trans_flg = READY_TO_TRNSMIT; /* B-Channel ready to transmit */
return 1;
}
@@ -614,7 +603,6 @@ static void gigaset_reinitbcshw(struct bc_state *bcs)
static void gigaset_freecshw(struct cardstate *cs)
{
- //FIXME
tasklet_kill(&cs->write_tasklet);
kfree(cs->hw.usb);
}
@@ -639,33 +627,21 @@ static int gigaset_initcshw(struct cardstate *cs)
//ucs->urb_cmd_out = NULL;
ucs->read_urb = NULL;
tasklet_init(&cs->write_tasklet,
- &gigaset_modem_fill, (unsigned long) cs);
+ &gigaset_modem_fill, (unsigned long) cs);
return 1;
}
-/* Writes the data of the current open skb into the modem.
- * We have to protect against multiple calls until the
- * callback handler () is called , due to the fact that we
- * are just allowed to send data once to an endpoint. Therefore
- * we using "trans_flg" to synchonize ...
- */
+/* Send data from current skb to the device. */
static int write_modem(struct cardstate *cs)
{
- int ret;
+ int ret = 0;
int count;
struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
struct usb_cardstate *ucs = cs->hw.usb;
- //unsigned long flags;
-
- IFNULLRETVAL(bcs->tx_skb, -EINVAL);
-
- dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len);
+ unsigned long flags;
- ret = -ENODEV;
- IFNULLGOTO(ucs->bulk_out_buffer, error);
- IFNULLGOTO(ucs->bulk_out_urb, error);
- ret = 0;
+ gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len);
if (!bcs->tx_skb->len) {
dev_kfree_skb_any(bcs->tx_skb);
@@ -679,40 +655,42 @@ static int write_modem(struct cardstate *cs)
count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size);
memcpy(ucs->bulk_out_buffer, bcs->tx_skb->data, count);
skb_pull(bcs->tx_skb, count);
-
- usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
- usb_sndbulkpipe(ucs->udev,
- ucs->bulk_out_endpointAddr & 0x0f),
- ucs->bulk_out_buffer, count,
- gigaset_write_bulk_callback, cs);
atomic_set(&ucs->busy, 1);
- dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count);
+ gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count);
+
+ spin_lock_irqsave(&cs->lock, flags);
+ if (cs->connected) {
+ usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
+ usb_sndbulkpipe(ucs->udev,
+ ucs->bulk_out_endpointAddr & 0x0f),
+ ucs->bulk_out_buffer, count,
+ gigaset_write_bulk_callback, cs);
+ ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
+ } else {
+ ret = -ENODEV;
+ }
+ spin_unlock_irqrestore(&cs->lock, flags);
- ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
if (ret) {
- err("could not submit urb (error %d).", -ret);
+ err("could not submit urb (error %d)\n", -ret);
atomic_set(&ucs->busy, 0);
}
+
if (!bcs->tx_skb->len) {
/* skb sent completely */
gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0?
- dbg(DEBUG_INTR,
- "kfree skb (Adr: %lx)!", (unsigned long) bcs->tx_skb);
+ gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!",
+ (unsigned long) bcs->tx_skb);
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
}
return ret;
-error:
- dev_kfree_skb_any(bcs->tx_skb);
- bcs->tx_skb = NULL;
- return ret;
-
}
static int gigaset_probe(struct usb_interface *interface,
- const struct usb_device_id *id)
+ const struct usb_device_id *id)
{
int retval;
struct usb_device *udev = interface_to_usbdev(interface);
@@ -720,22 +698,20 @@ static int gigaset_probe(struct usb_interface *interface,
struct usb_host_interface *hostif;
struct cardstate *cs = NULL;
struct usb_cardstate *ucs = NULL;
- //struct usb_interface_descriptor *iface_desc;
struct usb_endpoint_descriptor *endpoint;
- //isdn_ctrl command;
int buffer_size;
int alt;
- //unsigned long flags;
- info("%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
- __func__, le16_to_cpu(udev->descriptor.idVendor),
- le16_to_cpu(udev->descriptor.idProduct));
+ gig_dbg(DEBUG_ANY,
+ "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
+ __func__, le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
retval = -ENODEV; //FIXME
/* See if the device offered us matches what we can accept */
- if ((le16_to_cpu(udev->descriptor.idVendor != USB_M105_VENDOR_ID)) ||
- (le16_to_cpu(udev->descriptor.idProduct != USB_M105_PRODUCT_ID)))
+ if ((le16_to_cpu(udev->descriptor.idVendor) != USB_M105_VENDOR_ID) ||
+ (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID))
return -ENODEV;
/* this starts to become ascii art... */
@@ -744,7 +720,7 @@ static int gigaset_probe(struct usb_interface *interface,
ifnum = hostif->desc.bInterfaceNumber; // FIXME ?
if (alt != 0 || ifnum != 0) {
- warn("ifnum %d, alt %d", ifnum, alt);
+ dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt);
return -ENODEV;
}
@@ -752,42 +728,29 @@ static int gigaset_probe(struct usb_interface *interface,
*
*/
if (hostif->desc.bInterfaceClass != 255) {
- info("%s: Device matched, but iface_desc[%d]->bInterfaceClass==%d !",
- __func__, ifnum, hostif->desc.bInterfaceClass);
+ dev_info(&udev->dev,
+ "%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n",
+ __func__, ifnum, hostif->desc.bInterfaceClass);
return -ENODEV;
}
- info("%s: Device matched ... !", __func__);
+ dev_info(&udev->dev, "%s: Device matched ... !\n", __func__);
cs = gigaset_getunassignedcs(driver);
if (!cs) {
- warn("No free cardstate!");
+ dev_warn(&udev->dev, "no free cardstate\n");
return -ENODEV;
}
ucs = cs->hw.usb;
-#if 0
- if (usb_set_configuration(udev, udev->config[0].desc.bConfigurationValue) < 0) {
- warn("set_configuration failed");
- goto error;
- }
-
-
- if (usb_set_interface(udev, ifnum/*==0*/, alt/*==0*/) < 0) {
- warn("usb_set_interface failed, device %d interface %d altsetting %d",
- udev->devnum, ifnum, alt);
- goto error;
- }
-#endif
+ /* save off device structure ptrs for later use */
+ usb_get_dev(udev);
+ ucs->udev = udev;
+ ucs->interface = interface;
+ cs->dev = &interface->dev;
- /* set up the endpoint information */
- /* check out the endpoints */
- /* We will get 2 endpoints: One for sending commands to the device (bulk out) and one to
- * poll messages from the device(int in).
- * Therefore we will have an almost similiar situation as with our serial port handler.
- * If an connection will be established, we will have to create data in/out pipes
- * dynamically...
- */
+ /* save address of controller structure */
+ usb_set_intfdata(interface, cs); // dev_set_drvdata(&interface->dev, cs);
endpoint = &hostif->endpoint[0].desc;
@@ -796,14 +759,14 @@ static int gigaset_probe(struct usb_interface *interface,
ucs->bulk_out_endpointAddr = endpoint->bEndpointAddress;
ucs->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!ucs->bulk_out_buffer) {
- err("Couldn't allocate bulk_out_buffer");
+ dev_err(cs->dev, "Couldn't allocate bulk_out_buffer\n");
retval = -ENOMEM;
goto error;
}
ucs->bulk_out_urb = usb_alloc_urb(0, SLAB_KERNEL);
if (!ucs->bulk_out_urb) {
- err("Couldn't allocate bulk_out_buffer");
+ dev_err(cs->dev, "Couldn't allocate bulk_out_urb\n");
retval = -ENOMEM;
goto error;
}
@@ -811,12 +774,10 @@ static int gigaset_probe(struct usb_interface *interface,
endpoint = &hostif->endpoint[1].desc;
atomic_set(&ucs->busy, 0);
- ucs->udev = udev;
- ucs->interface = interface;
ucs->read_urb = usb_alloc_urb(0, SLAB_KERNEL);
if (!ucs->read_urb) {
- err("No free urbs available");
+ dev_err(cs->dev, "No free urbs available\n");
retval = -ENOMEM;
goto error;
}
@@ -825,38 +786,33 @@ static int gigaset_probe(struct usb_interface *interface,
ucs->int_in_endpointAddr = endpoint->bEndpointAddress;
cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL);
if (!cs->inbuf[0].rcvbuf) {
- err("Couldn't allocate rcvbuf");
+ dev_err(cs->dev, "Couldn't allocate rcvbuf\n");
retval = -ENOMEM;
goto error;
}
/* Fill the interrupt urb and send it to the core */
usb_fill_int_urb(ucs->read_urb, udev,
- usb_rcvintpipe(udev,
- endpoint->bEndpointAddress & 0x0f),
- cs->inbuf[0].rcvbuf, buffer_size,
- gigaset_read_int_callback,
- cs->inbuf + 0, endpoint->bInterval);
+ usb_rcvintpipe(udev,
+ endpoint->bEndpointAddress & 0x0f),
+ cs->inbuf[0].rcvbuf, buffer_size,
+ gigaset_read_int_callback,
+ cs->inbuf + 0, endpoint->bInterval);
retval = usb_submit_urb(ucs->read_urb, SLAB_KERNEL);
if (retval) {
- err("Could not submit URB!");
+ dev_err(cs->dev, "Could not submit URB (error %d)\n", -retval);
goto error;
}
/* tell common part that the device is ready */
if (startmode == SM_LOCKED)
atomic_set(&cs->mstate, MS_LOCKED);
+
if (!gigaset_start(cs)) {
tasklet_kill(&cs->write_tasklet);
retval = -ENODEV; //FIXME
goto error;
}
-
- /* save address of controller structure */
- usb_set_intfdata(interface, cs);
-
- /* set up device sysfs */
- gigaset_init_dev_sysfs(interface);
return 0;
error:
@@ -868,48 +824,45 @@ error:
kfree(cs->inbuf[0].rcvbuf);
if (ucs->read_urb != NULL)
usb_free_urb(ucs->read_urb);
+ usb_set_intfdata(interface, NULL);
ucs->read_urb = ucs->bulk_out_urb = NULL;
cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
+ usb_put_dev(ucs->udev);
+ ucs->udev = NULL;
+ ucs->interface = NULL;
gigaset_unassign(cs);
return retval;
}
-/**
- * skel_disconnect
- */
static void gigaset_disconnect(struct usb_interface *interface)
{
struct cardstate *cs;
struct usb_cardstate *ucs;
cs = usb_get_intfdata(interface);
-
- /* clear device sysfs */
- gigaset_free_dev_sysfs(interface);
-
- usb_set_intfdata(interface, NULL);
ucs = cs->hw.usb;
usb_kill_urb(ucs->read_urb);
- //info("GigaSet USB device #%d will be disconnected", minor);
gigaset_stop(cs);
+ usb_set_intfdata(interface, NULL);
tasklet_kill(&cs->write_tasklet);
- usb_kill_urb(ucs->bulk_out_urb); /* FIXME: nur, wenn noetig */
- //usb_kill_urb(ucs->urb_cmd_out); /* FIXME: nur, wenn noetig */
+ usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */
kfree(ucs->bulk_out_buffer);
if (ucs->bulk_out_urb != NULL)
usb_free_urb(ucs->bulk_out_urb);
- //if(ucs->urb_cmd_out != NULL)
- // usb_free_urb(ucs->urb_cmd_out);
kfree(cs->inbuf[0].rcvbuf);
if (ucs->read_urb != NULL)
usb_free_urb(ucs->read_urb);
- ucs->read_urb = ucs->bulk_out_urb/*=ucs->urb_cmd_out*/=NULL;
+ ucs->read_urb = ucs->bulk_out_urb = NULL;
cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
+ usb_put_dev(ucs->udev);
+ ucs->interface = NULL;
+ ucs->udev = NULL;
+ cs->dev = NULL;
gigaset_unassign(cs);
}
@@ -942,9 +895,9 @@ static int __init usb_gigaset_init(void)
/* allocate memory for our driver state and intialize it */
if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
- GIGASET_MODULENAME, GIGASET_DEVNAME,
- GIGASET_DEVFSNAME, &ops,
- THIS_MODULE)) == NULL)
+ GIGASET_MODULENAME, GIGASET_DEVNAME,
+ GIGASET_DEVFSNAME, &ops,
+ THIS_MODULE)) == NULL)
goto error;
/* allocate memory for our device state and intialize it */
@@ -981,8 +934,8 @@ error: if (cardstate)
static void __exit usb_gigaset_exit(void)
{
gigaset_blockdriver(driver); /* => probe will fail
- * => no gigaset_start any more
- */
+ * => no gigaset_start any more
+ */
gigaset_shutdown(cardstate);
/* from now on, no isdn callback should be possible */
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 2a2b03ff096..7bbfd85ab79 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -51,8 +51,8 @@ MODULE_LICENSE("GPL");
handler.
*/
-static void avmcs_config(dev_link_t *link);
-static void avmcs_release(dev_link_t *link);
+static int avmcs_config(struct pcmcia_device *link);
+static void avmcs_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -65,10 +65,10 @@ static void avmcs_detach(struct pcmcia_device *p_dev);
/*
A linked list of "instances" of the skeleton device. Each actual
PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
+ by one struct pcmcia_device structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
+ memory card driver uses an array of struct pcmcia_device pointers, where minor
device numbers are used to derive the corresponding array index.
*/
@@ -78,7 +78,7 @@ static void avmcs_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally can't be allocated dynamically.
*/
@@ -99,54 +99,38 @@ typedef struct local_info_t {
======================================================================*/
-static int avmcs_attach(struct pcmcia_device *p_dev)
+static int avmcs_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
local_info_t *local;
- /* Initialize the dev_link_t structure */
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link)
- goto err;
- memset(link, 0, sizeof(struct dev_link_t));
-
/* The io structure describes IO port mapping */
- link->io.NumPorts1 = 16;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.NumPorts2 = 0;
+ p_dev->io.NumPorts1 = 16;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.NumPorts2 = 0;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-
/* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
+ p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.ConfigIndex = 1;
+ p_dev->conf.Present = PRESENT_OPTION;
/* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local)
- goto err_kfree;
+ goto err;
memset(local, 0, sizeof(local_info_t));
- link->priv = local;
+ p_dev->priv = local;
- link->handle = p_dev;
- p_dev->instance = link;
+ return avmcs_config(p_dev);
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- avmcs_config(link);
-
- return 0;
-
- err_kfree:
- kfree(link);
err:
- return -EINVAL;
+ return -ENOMEM;
} /* avmcs_attach */
/*======================================================================
@@ -158,15 +142,10 @@ static int avmcs_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void avmcs_detach(struct pcmcia_device *p_dev)
+static void avmcs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
- if (link->state & DEV_CONFIG)
avmcs_release(link);
-
- kfree(link->priv);
- kfree(link);
+ kfree(link->priv);
} /* avmcs_detach */
/*======================================================================
@@ -177,7 +156,7 @@ static void avmcs_detach(struct pcmcia_device *p_dev)
======================================================================*/
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_tuple_data(handle, tuple);
@@ -185,7 +164,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_first_tuple(handle, tuple);
@@ -193,7 +172,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_next_tuple(handle, tuple);
@@ -201,9 +180,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static void avmcs_config(dev_link_t *link)
+static int avmcs_config(struct pcmcia_device *link)
{
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
@@ -213,8 +191,7 @@ static void avmcs_config(dev_link_t *link)
char devname[128];
int cardtype;
int (*addcard)(unsigned int port, unsigned irq);
-
- handle = link->handle;
+
dev = link->priv;
/*
@@ -223,25 +200,21 @@ static void avmcs_config(dev_link_t *link)
*/
do {
tuple.DesiredTuple = CISTPL_CONFIG;
- i = pcmcia_get_first_tuple(handle, &tuple);
+ i = pcmcia_get_first_tuple(link, &tuple);
if (i != CS_SUCCESS) break;
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- i = pcmcia_get_tuple_data(handle, &tuple);
+ i = pcmcia_get_tuple_data(link, &tuple);
if (i != CS_SUCCESS) break;
- i = pcmcia_parse_tuple(handle, &tuple, &parse);
+ i = pcmcia_parse_tuple(link, &tuple, &parse);
if (i != CS_SUCCESS) break;
link->conf.ConfigBase = parse.config.base;
} while (0);
if (i != CS_SUCCESS) {
- cs_error(link->handle, ParseTuple, i);
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ cs_error(link, ParseTuple, i);
+ return -ENODEV;
}
-
- /* Configure card */
- link->state |= DEV_CONFIG;
do {
@@ -252,7 +225,7 @@ static void avmcs_config(dev_link_t *link)
tuple.DesiredTuple = CISTPL_VERS_1;
devname[0] = 0;
- if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
+ if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) {
strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1],
sizeof(devname));
}
@@ -263,7 +236,7 @@ static void avmcs_config(dev_link_t *link)
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i == CS_SUCCESS) {
if (cf->io.nwin > 0) {
link->conf.ConfigIndex = cf->index;
@@ -273,36 +246,36 @@ static void avmcs_config(dev_link_t *link)
printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
link->io.BasePort1,
link->io.BasePort1+link->io.NumPorts1-1);
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) goto found_port;
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
found_port:
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
break;
}
-
+
/*
* allocate an interrupt line
*/
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
- pcmcia_release_io(link->handle, &link->io);
+ cs_error(link, RequestIRQ, i);
+ /* undo */
+ pcmcia_disable_device(link);
break;
}
-
+
/*
* configure the PCMCIA socket
*/
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
+ cs_error(link, RequestConfiguration, i);
+ pcmcia_disable_device(link);
break;
}
@@ -331,13 +304,12 @@ found_port:
dev->node.major = 64;
dev->node.minor = 0;
- link->dev = &dev->node;
-
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &dev->node;
+
/* If any step failed, release any partially configured state */
if (i != 0) {
avmcs_release(link);
- return;
+ return -ENODEV;
}
@@ -351,9 +323,10 @@ found_port:
printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n",
dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
avmcs_release(link);
- return;
+ return -ENODEV;
}
dev->node.minor = i;
+ return 0;
} /* avmcs_config */
@@ -365,56 +338,12 @@ found_port:
======================================================================*/
-static void avmcs_release(dev_link_t *link)
+static void avmcs_release(struct pcmcia_device *link)
{
- b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
-
- /* Unlink the device chain */
- link->dev = NULL;
-
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
+ pcmcia_disable_device(link);
} /* avmcs_release */
-static int avmcs_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int avmcs_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
-}
-
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
-
- When a CARD_REMOVAL event is received, we immediately set a flag
- to block future accesses to this device. All the functions that
- actually access the device should check this flag to make sure
- the card is still present.
-
-======================================================================*/
-
static struct pcmcia_device_id avmcs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335),
@@ -429,11 +358,9 @@ static struct pcmcia_driver avmcs_driver = {
.drv = {
.name = "avm_cs",
},
- .probe = avmcs_attach,
+ .probe = avmcs_probe,
.remove = avmcs_detach,
.id_table = avmcs_ids,
- .suspend= avmcs_suspend,
- .resume = avmcs_resume,
};
static int __init avmcs_init(void)
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 969da40c424..ac28e3278ad 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -67,8 +67,8 @@ module_param(isdnprot, int, 0);
handler.
*/
-static void avma1cs_config(dev_link_t *link);
-static void avma1cs_release(dev_link_t *link);
+static int avma1cs_config(struct pcmcia_device *link);
+static void avma1cs_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -82,10 +82,10 @@ static void avma1cs_detach(struct pcmcia_device *p_dev);
/*
A linked list of "instances" of the skeleton device. Each actual
PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
+ by one struct pcmcia_device structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
+ memory card driver uses an array of struct pcmcia_device pointers, where minor
device numbers are used to derive the corresponding array index.
*/
@@ -95,7 +95,7 @@ static void avma1cs_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally can't be allocated dynamically.
*/
@@ -116,55 +116,40 @@ typedef struct local_info_t {
======================================================================*/
-static int avma1cs_attach(struct pcmcia_device *p_dev)
+static int avma1cs_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
local_info_t *local;
DEBUG(0, "avma1cs_attach()\n");
- /* Initialize the dev_link_t structure */
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link)
- return -ENOMEM;
- memset(link, 0, sizeof(struct dev_link_t));
-
/* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
- if (!local) {
- kfree(link);
+ if (!local)
return -ENOMEM;
- }
+
memset(local, 0, sizeof(local_info_t));
- link->priv = local;
+ p_dev->priv = local;
/* The io structure describes IO port mapping */
- link->io.NumPorts1 = 16;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.NumPorts2 = 16;
- link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
- link->io.IOAddrLines = 5;
+ p_dev->io.NumPorts1 = 16;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.NumPorts2 = 16;
+ p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
+ p_dev->io.IOAddrLines = 5;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
/* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
+ p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.ConfigIndex = 1;
+ p_dev->conf.Present = PRESENT_OPTION;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- avma1cs_config(link);
-
- return 0;
+ return avma1cs_config(p_dev);
} /* avma1cs_attach */
/*======================================================================
@@ -176,17 +161,11 @@ static int avma1cs_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void avma1cs_detach(struct pcmcia_device *p_dev)
+static void avma1cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
- DEBUG(0, "avma1cs_detach(0x%p)\n", link);
-
- if (link->state & DEV_CONFIG)
- avma1cs_release(link);
-
- kfree(link->priv);
- kfree(link);
+ DEBUG(0, "avma1cs_detach(0x%p)\n", link);
+ avma1cs_release(link);
+ kfree(link->priv);
} /* avma1cs_detach */
/*======================================================================
@@ -197,7 +176,7 @@ static void avma1cs_detach(struct pcmcia_device *p_dev)
======================================================================*/
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_tuple_data(handle, tuple);
@@ -205,7 +184,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_first_tuple(handle, tuple);
@@ -213,7 +192,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_next_tuple(handle, tuple);
@@ -221,9 +200,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static void avma1cs_config(dev_link_t *link)
+static int avma1cs_config(struct pcmcia_device *link)
{
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
@@ -233,8 +211,7 @@ static void avma1cs_config(dev_link_t *link)
char devname[128];
IsdnCard_t icard;
int busy = 0;
-
- handle = link->handle;
+
dev = link->priv;
DEBUG(0, "avma1cs_config(0x%p)\n", link);
@@ -245,25 +222,21 @@ static void avma1cs_config(dev_link_t *link)
*/
do {
tuple.DesiredTuple = CISTPL_CONFIG;
- i = pcmcia_get_first_tuple(handle, &tuple);
+ i = pcmcia_get_first_tuple(link, &tuple);
if (i != CS_SUCCESS) break;
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- i = pcmcia_get_tuple_data(handle, &tuple);
+ i = pcmcia_get_tuple_data(link, &tuple);
if (i != CS_SUCCESS) break;
- i = pcmcia_parse_tuple(handle, &tuple, &parse);
+ i = pcmcia_parse_tuple(link, &tuple, &parse);
if (i != CS_SUCCESS) break;
link->conf.ConfigBase = parse.config.base;
} while (0);
if (i != CS_SUCCESS) {
- cs_error(link->handle, ParseTuple, i);
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ cs_error(link, ParseTuple, i);
+ return -ENODEV;
}
-
- /* Configure card */
- link->state |= DEV_CONFIG;
do {
@@ -274,7 +247,7 @@ static void avma1cs_config(dev_link_t *link)
tuple.DesiredTuple = CISTPL_VERS_1;
devname[0] = 0;
- if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
+ if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) {
strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1],
sizeof(devname));
}
@@ -285,7 +258,7 @@ static void avma1cs_config(dev_link_t *link)
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i == CS_SUCCESS) {
if (cf->io.nwin > 0) {
link->conf.ConfigIndex = cf->index;
@@ -295,36 +268,36 @@ static void avma1cs_config(dev_link_t *link)
printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
link->io.BasePort1,
link->io.BasePort1+link->io.NumPorts1 - 1);
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) goto found_port;
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
found_port:
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
break;
}
/*
* allocate an interrupt line
*/
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
- pcmcia_release_io(link->handle, &link->io);
+ cs_error(link, RequestIRQ, i);
+ /* undo */
+ pcmcia_disable_device(link);
break;
}
-
+
/*
* configure the PCMCIA socket
*/
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
+ cs_error(link, RequestConfiguration, i);
+ pcmcia_disable_device(link);
break;
}
@@ -336,13 +309,12 @@ found_port:
strcpy(dev->node.dev_name, "A1");
dev->node.major = 45;
dev->node.minor = 0;
- link->dev = &dev->node;
-
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &dev->node;
+
/* If any step failed, release any partially configured state */
if (i != 0) {
avma1cs_release(link);
- return;
+ return -ENODEV;
}
printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
@@ -357,10 +329,11 @@ found_port:
if (i < 0) {
printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
avma1cs_release(link);
- return;
+ return -ENODEV;
}
dev->node.minor = i;
+ return 0;
} /* avma1cs_config */
/*======================================================================
@@ -371,47 +344,18 @@ found_port:
======================================================================*/
-static void avma1cs_release(dev_link_t *link)
+static void avma1cs_release(struct pcmcia_device *link)
{
- local_info_t *local = link->priv;
+ local_info_t *local = link->priv;
- DEBUG(0, "avma1cs_release(0x%p)\n", link);
+ DEBUG(0, "avma1cs_release(0x%p)\n", link);
- /* no unregister function with hisax */
- HiSax_closecard(local->node.minor);
+ /* now unregister function with hisax */
+ HiSax_closecard(local->node.minor);
- /* Unlink the device chain */
- link->dev = NULL;
-
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
} /* avma1cs_release */
-static int avma1cs_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int avma1cs_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
-}
-
static struct pcmcia_device_id avma1cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
@@ -425,13 +369,11 @@ static struct pcmcia_driver avma1cs_driver = {
.drv = {
.name = "avma1_cs",
},
- .probe = avma1cs_attach,
+ .probe = avma1cs_probe,
.remove = avma1cs_detach,
.id_table = avma1cs_ids,
- .suspend = avma1cs_suspend,
- .resume = avma1cs_resume,
};
-
+
/*====================================================================*/
static int __init init_avma1_cs(void)
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 062fb8f0739..e18e75be8ed 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -94,8 +94,8 @@ module_param(protocol, int, 0);
handler.
*/
-static void elsa_cs_config(dev_link_t *link);
-static void elsa_cs_release(dev_link_t *link);
+static int elsa_cs_config(struct pcmcia_device *link);
+static void elsa_cs_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -111,7 +111,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally shouldn't be allocated dynamically.
In this case, we also provide a flag to indicate if a device is
@@ -121,7 +121,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev);
*/
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
int busy;
int cardnr;
@@ -139,9 +139,8 @@ typedef struct local_info_t {
======================================================================*/
-static int elsa_cs_attach(struct pcmcia_device *p_dev)
+static int elsa_cs_probe(struct pcmcia_device *link)
{
- dev_link_t *link;
local_info_t *local;
DEBUG(0, "elsa_cs_attach()\n");
@@ -150,8 +149,11 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev)
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) return -ENOMEM;
memset(local, 0, sizeof(local_info_t));
+
+ local->p_dev = link;
+ link->priv = local;
+
local->cardnr = -1;
- link = &local->link; link->priv = local;
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
@@ -170,16 +172,9 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev)
link->io.IOAddrLines = 3;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- elsa_cs_config(link);
-
- return 0;
+ return elsa_cs_config(link);
} /* elsa_cs_attach */
/*======================================================================
@@ -191,20 +186,16 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void elsa_cs_detach(struct pcmcia_device *p_dev)
+static void elsa_cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
- local_info_t *info = link->priv;
+ local_info_t *info = link->priv;
- DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
+ DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG) {
- info->busy = 1;
- elsa_cs_release(link);
- }
-
- kfree(info);
+ info->busy = 1;
+ elsa_cs_release(link);
+ kfree(info);
} /* elsa_cs_detach */
/*======================================================================
@@ -214,7 +205,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev)
device available to the system.
======================================================================*/
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_tuple_data(handle, tuple);
@@ -222,7 +213,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_first_tuple(handle, tuple);
@@ -230,7 +221,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_next_tuple(handle, tuple);
@@ -238,9 +229,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static void elsa_cs_config(dev_link_t *link)
+static int elsa_cs_config(struct pcmcia_device *link)
{
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
local_info_t *dev;
@@ -250,7 +240,6 @@ static void elsa_cs_config(dev_link_t *link)
IsdnCard_t icard;
DEBUG(0, "elsa_config(0x%p)\n", link);
- handle = link->handle;
dev = link->priv;
/*
@@ -262,7 +251,7 @@ static void elsa_cs_config(dev_link_t *link)
tuple.TupleDataMax = 255;
tuple.TupleOffset = 0;
tuple.Attributes = 0;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
if (i != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -270,32 +259,29 @@ static void elsa_cs_config(dev_link_t *link)
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i == CS_SUCCESS) {
if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
} else {
printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
link->conf.ConfigIndex = cf->index;
for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
link->io.BasePort1 = j;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
break;
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
if (i != CS_SUCCESS) {
@@ -303,14 +289,14 @@ static void elsa_cs_config(dev_link_t *link)
goto cs_failed;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
link->irq.AssignedIRQ = 0;
last_fn = RequestIRQ;
goto cs_failed;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
last_fn = RequestConfiguration;
goto cs_failed;
@@ -321,14 +307,11 @@ static void elsa_cs_config(dev_link_t *link)
sprintf(dev->node.dev_name, "elsa");
dev->node.major = dev->node.minor = 0x0;
- link->dev = &dev->node;
+ link->dev_node = &dev->node;
/* Finally, report what we've done */
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev->node.dev_name, link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "%s: index 0x%02x: ",
+ dev->node.dev_name, link->conf.ConfigIndex);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
@@ -339,8 +322,6 @@ static void elsa_cs_config(dev_link_t *link)
link->io.BasePort2+link->io.NumPorts2-1);
printk("\n");
- link->state &= ~DEV_CONFIG_PENDING;
-
icard.para[0] = link->irq.AssignedIRQ;
icard.para[1] = link->io.BasePort1;
icard.protocol = protocol;
@@ -354,10 +335,11 @@ static void elsa_cs_config(dev_link_t *link)
} else
((local_info_t*)link->priv)->cardnr = i;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, i);
+ cs_error(link, last_fn, i);
elsa_cs_release(link);
+ return -ENODEV;
} /* elsa_cs_config */
/*======================================================================
@@ -368,7 +350,7 @@ cs_failed:
======================================================================*/
-static void elsa_cs_release(dev_link_t *link)
+static void elsa_cs_release(struct pcmcia_device *link)
{
local_info_t *local = link->priv;
@@ -380,39 +362,23 @@ static void elsa_cs_release(dev_link_t *link)
HiSax_closecard(local->cardnr);
}
}
- /* Unlink the device chain */
- link->dev = NULL;
-
- /* Don't bother checking to see if these succeed or not */
- if (link->win)
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+
+ pcmcia_disable_device(link);
} /* elsa_cs_release */
-static int elsa_suspend(struct pcmcia_device *p_dev)
+static int elsa_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state |= DEV_SUSPEND;
dev->busy = 1;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
return 0;
}
-static int elsa_resume(struct pcmcia_device *p_dev)
+static int elsa_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
dev->busy = 0;
return 0;
@@ -430,7 +396,7 @@ static struct pcmcia_driver elsa_cs_driver = {
.drv = {
.name = "elsa_cs",
},
- .probe = elsa_cs_attach,
+ .probe = elsa_cs_probe,
.remove = elsa_cs_detach,
.id_table = elsa_ids,
.suspend = elsa_suspend,
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 6f5213a18a8..9bb18f3f782 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -95,8 +95,8 @@ module_param(protocol, int, 0);
event handler.
*/
-static void sedlbauer_config(dev_link_t *link);
-static void sedlbauer_release(dev_link_t *link);
+static int sedlbauer_config(struct pcmcia_device *link);
+static void sedlbauer_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -119,7 +119,7 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally shouldn't be allocated dynamically.
@@ -130,7 +130,7 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev);
*/
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
int stop;
int cardnr;
@@ -148,11 +148,10 @@ typedef struct local_info_t {
======================================================================*/
-static int sedlbauer_attach(struct pcmcia_device *p_dev)
+static int sedlbauer_probe(struct pcmcia_device *link)
{
local_info_t *local;
- dev_link_t *link;
-
+
DEBUG(0, "sedlbauer_attach()\n");
/* Allocate space for private device-specific data */
@@ -160,8 +159,10 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev)
if (!local) return -ENOMEM;
memset(local, 0, sizeof(local_info_t));
local->cardnr = -1;
- link = &local->link; link->priv = local;
-
+
+ local->p_dev = link;
+ link->priv = local;
+
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
@@ -182,18 +183,10 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev)
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.IOAddrLines = 3;
-
link->conf.Attributes = 0;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- sedlbauer_config(link);
-
- return 0;
+ return sedlbauer_config(link);
} /* sedlbauer_attach */
/*======================================================================
@@ -205,19 +198,15 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void sedlbauer_detach(struct pcmcia_device *p_dev)
+static void sedlbauer_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
- DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
+ DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG) {
- ((local_info_t *)link->priv)->stop = 1;
- sedlbauer_release(link);
- }
+ ((local_info_t *)link->priv)->stop = 1;
+ sedlbauer_release(link);
- /* This points to the parent local_info_t struct */
- kfree(link->priv);
+ /* This points to the parent local_info_t struct */
+ kfree(link->priv);
} /* sedlbauer_detach */
/*======================================================================
@@ -230,9 +219,8 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void sedlbauer_config(dev_link_t *link)
+static int sedlbauer_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
local_info_t *dev = link->priv;
tuple_t tuple;
cisparse_t parse;
@@ -254,18 +242,13 @@ static void sedlbauer_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
-
- /* Configure card */
- link->state |= DEV_CONFIG;
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
+ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
/*
In this loop, we scan the CIS for configuration table entries,
@@ -280,12 +263,12 @@ static void sedlbauer_config(dev_link_t *link)
will only use the CIS to fill in implementation-defined details.
*/
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t dflt = { 0 };
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -309,10 +292,10 @@ static void sedlbauer_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
/* Do we need to allocate an interrupt? */
@@ -339,13 +322,13 @@ static void sedlbauer_config(dev_link_t *link)
link->io.NumPorts2 = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
/*
Now set up a common memory window, if needed. There is room
- in the dev_link_t structure for one memory window handle,
+ in the struct pcmcia_device structure for one memory window handle,
but if the base addresses need to be saved, or if multiple
windows are needed, the info should go in the private data
structure for this device.
@@ -366,7 +349,7 @@ static void sedlbauer_config(dev_link_t *link)
req.Size = 0x1000;
*/
req.AccessSpeed = 0;
- if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+ if (pcmcia_request_window(&link, &req, &link->win) != 0)
goto next_entry;
map.Page = 0; map.CardOffset = mem->win[0].card_addr;
if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -374,29 +357,25 @@ static void sedlbauer_config(dev_link_t *link)
}
/* If we got this far, we're cool! */
break;
-
+
next_entry:
-/* new in dummy.cs 2001/01/28 MN
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
-*/
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
-
+
/*
Allocate an interrupt line. Note that this does not assign a
handler to the interrupt, unless the 'Handler' member of the
irq structure is initialized.
*/
if (link->conf.Attributes & CONF_ENABLE_IRQ)
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/*
This actually configures the PCMCIA socket -- setting up
the I/O windows and the interrupt mapping, and putting the
card and host interface into "Memory and IO" mode.
*/
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/*
At this point, the dev_node_t structure(s) need to be
@@ -404,14 +383,13 @@ static void sedlbauer_config(dev_link_t *link)
*/
sprintf(dev->node.dev_name, "sedlbauer");
dev->node.major = dev->node.minor = 0;
- link->dev = &dev->node;
+ link->dev_node = &dev->node;
/* Finally, report what we've done */
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev->node.dev_name, link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "%s: index 0x%02x:",
+ dev->node.dev_name, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
@@ -424,8 +402,6 @@ static void sedlbauer_config(dev_link_t *link)
printk(", mem 0x%06lx-0x%06lx", req.Base,
req.Base+req.Size-1);
printk("\n");
-
- link->state &= ~DEV_CONFIG_PENDING;
icard.para[0] = link->irq.AssignedIRQ;
icard.para[1] = link->io.BasePort1;
@@ -437,14 +413,16 @@ static void sedlbauer_config(dev_link_t *link)
printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n",
last_ret, link->io.BasePort1);
sedlbauer_release(link);
+ return -ENODEV;
} else
((local_info_t*)link->priv)->cardnr = last_ret;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
sedlbauer_release(link);
+ return -ENODEV;
} /* sedlbauer_config */
@@ -456,7 +434,7 @@ cs_failed:
======================================================================*/
-static void sedlbauer_release(dev_link_t *link)
+static void sedlbauer_release(struct pcmcia_device *link)
{
local_info_t *local = link->priv;
DEBUG(0, "sedlbauer_release(0x%p)\n", link);
@@ -467,46 +445,23 @@ static void sedlbauer_release(dev_link_t *link)
HiSax_closecard(local->cardnr);
}
}
- /* Unlink the device chain */
- link->dev = NULL;
- /*
- In a normal driver, additional code may be needed to release
- other kernel data structures associated with this device.
- */
-
- /* Don't bother checking to see if these succeed or not */
- if (link->win)
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
} /* sedlbauer_release */
-static int sedlbauer_suspend(struct pcmcia_device *p_dev)
+static int sedlbauer_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state |= DEV_SUSPEND;
dev->stop = 1;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
return 0;
}
-static int sedlbauer_resume(struct pcmcia_device *p_dev)
+static int sedlbauer_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
dev->stop = 0;
return 0;
@@ -530,7 +485,7 @@ static struct pcmcia_driver sedlbauer_driver = {
.drv = {
.name = "sedlbauer_cs",
},
- .probe = sedlbauer_attach,
+ .probe = sedlbauer_probe,
.remove = sedlbauer_detach,
.id_table = sedlbauer_ids,
.suspend = sedlbauer_suspend,
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 4e5c14c7240..afcc2aeadb3 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -75,8 +75,8 @@ module_param(protocol, int, 0);
handler.
*/
-static void teles_cs_config(dev_link_t *link);
-static void teles_cs_release(dev_link_t *link);
+static int teles_cs_config(struct pcmcia_device *link);
+static void teles_cs_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -89,10 +89,10 @@ static void teles_detach(struct pcmcia_device *p_dev);
/*
A linked list of "instances" of the teles_cs device. Each actual
PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
+ by one struct pcmcia_device structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
+ memory card driver uses an array of struct pcmcia_device pointers, where minor
device numbers are used to derive the corresponding array index.
*/
@@ -102,7 +102,7 @@ static void teles_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally shouldn't be allocated dynamically.
In this case, we also provide a flag to indicate if a device is
@@ -112,7 +112,7 @@ static void teles_detach(struct pcmcia_device *p_dev);
*/
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
int busy;
int cardnr;
@@ -130,9 +130,8 @@ typedef struct local_info_t {
======================================================================*/
-static int teles_attach(struct pcmcia_device *p_dev)
+static int teles_probe(struct pcmcia_device *link)
{
- dev_link_t *link;
local_info_t *local;
DEBUG(0, "teles_attach()\n");
@@ -142,7 +141,9 @@ static int teles_attach(struct pcmcia_device *p_dev)
if (!local) return -ENOMEM;
memset(local, 0, sizeof(local_info_t));
local->cardnr = -1;
- link = &local->link; link->priv = local;
+
+ local->p_dev = link;
+ link->priv = local;
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
@@ -161,16 +162,9 @@ static int teles_attach(struct pcmcia_device *p_dev)
link->io.IOAddrLines = 5;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- teles_cs_config(link);
-
- return 0;
+ return teles_cs_config(link);
} /* teles_attach */
/*======================================================================
@@ -182,20 +176,16 @@ static int teles_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void teles_detach(struct pcmcia_device *p_dev)
+static void teles_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
- local_info_t *info = link->priv;
-
- DEBUG(0, "teles_detach(0x%p)\n", link);
+ local_info_t *info = link->priv;
- if (link->state & DEV_CONFIG) {
- info->busy = 1;
- teles_cs_release(link);
- }
+ DEBUG(0, "teles_detach(0x%p)\n", link);
- kfree(info);
+ info->busy = 1;
+ teles_cs_release(link);
+ kfree(info);
} /* teles_detach */
/*======================================================================
@@ -205,7 +195,7 @@ static void teles_detach(struct pcmcia_device *p_dev)
device available to the system.
======================================================================*/
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_tuple_data(handle, tuple);
@@ -213,7 +203,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple,
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_first_tuple(handle, tuple);
@@ -221,7 +211,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i = pcmcia_get_next_tuple(handle, tuple);
@@ -229,9 +219,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
return get_tuple(handle, tuple, parse);
}
-static void teles_cs_config(dev_link_t *link)
+static int teles_cs_config(struct pcmcia_device *link)
{
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
local_info_t *dev;
@@ -241,7 +230,6 @@ static void teles_cs_config(dev_link_t *link)
IsdnCard_t icard;
DEBUG(0, "teles_config(0x%p)\n", link);
- handle = link->handle;
dev = link->priv;
/*
@@ -253,7 +241,7 @@ static void teles_cs_config(dev_link_t *link)
tuple.TupleDataMax = 255;
tuple.TupleOffset = 0;
tuple.Attributes = 0;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
if (i != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -261,32 +249,29 @@ static void teles_cs_config(dev_link_t *link)
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(handle, &tuple, &parse);
+ i = first_tuple(link, &tuple, &parse);
while (i == CS_SUCCESS) {
if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
} else {
printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
link->conf.ConfigIndex = cf->index;
for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
link->io.BasePort1 = j;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
break;
}
- i = next_tuple(handle, &tuple, &parse);
+ i = next_tuple(link, &tuple, &parse);
}
if (i != CS_SUCCESS) {
@@ -294,14 +279,14 @@ static void teles_cs_config(dev_link_t *link)
goto cs_failed;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
link->irq.AssignedIRQ = 0;
last_fn = RequestIRQ;
goto cs_failed;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
last_fn = RequestConfiguration;
goto cs_failed;
@@ -312,14 +297,11 @@ static void teles_cs_config(dev_link_t *link)
sprintf(dev->node.dev_name, "teles");
dev->node.major = dev->node.minor = 0x0;
- link->dev = &dev->node;
+ link->dev_node = &dev->node;
/* Finally, report what we've done */
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev->node.dev_name, link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "%s: index 0x%02x:",
+ dev->node.dev_name, link->conf.ConfigIndex);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
@@ -330,8 +312,6 @@ static void teles_cs_config(dev_link_t *link)
link->io.BasePort2+link->io.NumPorts2-1);
printk("\n");
- link->state &= ~DEV_CONFIG_PENDING;
-
icard.para[0] = link->irq.AssignedIRQ;
icard.para[1] = link->io.BasePort1;
icard.protocol = protocol;
@@ -342,13 +322,16 @@ static void teles_cs_config(dev_link_t *link)
printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n",
i, link->io.BasePort1);
teles_cs_release(link);
- } else
- ((local_info_t*)link->priv)->cardnr = i;
+ return -ENODEV;
+ }
+
+ ((local_info_t*)link->priv)->cardnr = i;
+ return 0;
- return;
cs_failed:
- cs_error(link->handle, last_fn, i);
+ cs_error(link, last_fn, i);
teles_cs_release(link);
+ return -ENODEV;
} /* teles_cs_config */
/*======================================================================
@@ -359,7 +342,7 @@ cs_failed:
======================================================================*/
-static void teles_cs_release(dev_link_t *link)
+static void teles_cs_release(struct pcmcia_device *link)
{
local_info_t *local = link->priv;
@@ -371,39 +354,23 @@ static void teles_cs_release(dev_link_t *link)
HiSax_closecard(local->cardnr);
}
}
- /* Unlink the device chain */
- link->dev = NULL;
-
- /* Don't bother checking to see if these succeed or not */
- if (link->win)
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+
+ pcmcia_disable_device(link);
} /* teles_cs_release */
-static int teles_suspend(struct pcmcia_device *p_dev)
+static int teles_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state |= DEV_SUSPEND;
dev->busy = 1;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
return 0;
}
-static int teles_resume(struct pcmcia_device *p_dev)
+static int teles_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
dev->busy = 0;
return 0;
@@ -421,7 +388,7 @@ static struct pcmcia_driver teles_cs_driver = {
.drv = {
.name = "teles_cs",
},
- .probe = teles_attach,
+ .probe = teles_probe,
.remove = teles_detach,
.id_table = teles_ids,
.suspend = teles_suspend,
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index a0927d1b7a0..918742271c7 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -109,7 +109,7 @@ isdn_ppp_free(isdn_net_local * lp)
{
struct ippp_struct *is;
- if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
__FUNCTION__, lp->ppp_slot);
return 0;
@@ -126,7 +126,7 @@ isdn_ppp_free(isdn_net_local * lp)
lp->netdev->pb->ref_ct--;
spin_unlock(&lp->netdev->pb->lock);
#endif /* CONFIG_ISDN_MPP */
- if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
__FUNCTION__, lp->ppp_slot);
return 0;
@@ -279,7 +279,7 @@ isdn_ppp_open(int min, struct file *file)
int slot;
struct ippp_struct *is;
- if (min < 0 || min > ISDN_MAX_CHANNELS)
+ if (min < 0 || min >= ISDN_MAX_CHANNELS)
return -ENODEV;
slot = isdn_ppp_get_slot();
@@ -1042,7 +1042,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
if (lp->master) { // FIXME?
mlp = (isdn_net_local *) lp->master->priv;
slot = mlp->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
lp->ppp_slot);
goto drop_packet;
@@ -1264,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
/* we have our lp locked from now on */
slot = lp->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
lp->ppp_slot);
kfree_skb(skb);
@@ -1603,7 +1603,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
mp = net_dev->pb;
stats = &mp->stats;
slot = lp->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
__FUNCTION__, lp->ppp_slot);
stats->frame_drops++;
@@ -1640,7 +1640,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
is->last_link_seqno = minseq = newseq;
for (lpq = net_dev->queue;;) {
slot = lpq->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
__FUNCTION__, lpq->ppp_slot);
} else {
@@ -2648,7 +2648,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
lp->ppp_slot);
- if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
__FUNCTION__, lp->ppp_slot);
return;
@@ -2658,7 +2658,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
if(lp->master) {
int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: slot(%d) out of range\n",
__FUNCTION__, slot);
return;
@@ -2845,7 +2845,7 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct
if (lp->master) {
slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: slot(%d) out of range\n",
__FUNCTION__, slot);
return;
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 3585fb1f334..2ac90242d26 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -2880,7 +2880,7 @@ isdn_tty_cmd_ATand(char **p, modem_info * info)
p[0]++;
i = 0;
while (*p[0] && (strchr("0123456789,-*[]?;", *p[0])) &&
- (i < ISDN_LMSNLEN))
+ (i < ISDN_LMSNLEN - 1))
m->lmsn[i++] = *p[0]++;
m->lmsn[i] = '\0';
break;
diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c
index 94c9afb7017..f4f71226a07 100644
--- a/drivers/isdn/sc/ioctl.c
+++ b/drivers/isdn/sc/ioctl.c
@@ -46,7 +46,8 @@ int sc_ioctl(int card, scs_ioctl *data)
pr_debug("%s: SCIOCRESET: ioctl received\n",
sc_adapter[card]->devicename);
sc_adapter[card]->StartOnReset = 0;
- return (reset(card));
+ kfree(rcvmsg);
+ return reset(card);
}
case SCIOCLOAD:
@@ -183,7 +184,7 @@ int sc_ioctl(int card, scs_ioctl *data)
sc_adapter[card]->devicename);
spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
- if(!spid) {
+ if (!spid) {
kfree(rcvmsg);
return -ENOMEM;
}
@@ -195,10 +196,10 @@ int sc_ioctl(int card, scs_ioctl *data)
if (!status) {
pr_debug("%s: SCIOCGETSPID: command successful\n",
sc_adapter[card]->devicename);
- }
- else {
+ } else {
pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n",
sc_adapter[card]->devicename, status);
+ kfree(spid);
kfree(rcvmsg);
return status;
}
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
new file mode 100644
index 00000000000..626506234b7
--- /dev/null
+++ b/drivers/leds/Kconfig
@@ -0,0 +1,91 @@
+
+menu "LED devices"
+
+config NEW_LEDS
+ bool "LED Support"
+ help
+ Say Y to enable Linux LED support. This allows control of supported
+ LEDs from both userspace and optionally, by kernel events (triggers).
+
+ This is not related to standard keyboard LEDs which are controlled
+ via the input system.
+
+config LEDS_CLASS
+ tristate "LED Class Support"
+ depends NEW_LEDS
+ help
+ This option enables the led sysfs class in /sys/class/leds. You'll
+ need this to do anything useful with LEDs. If unsure, say N.
+
+comment "LED drivers"
+
+config LEDS_CORGI
+ tristate "LED Support for the Sharp SL-C7x0 series"
+ depends LEDS_CLASS && PXA_SHARP_C7xx
+ help
+ This option enables support for the LEDs on Sharp Zaurus
+ SL-C7x0 series (C700, C750, C760, C860).
+
+config LEDS_LOCOMO
+ tristate "LED Support for Locomo device"
+ depends LEDS_CLASS && SHARP_LOCOMO
+ help
+ This option enables support for the LEDs on Sharp Locomo.
+ Zaurus models SL-5500 and SL-5600.
+
+config LEDS_SPITZ
+ tristate "LED Support for the Sharp SL-Cxx00 series"
+ depends LEDS_CLASS && PXA_SHARP_Cxx00
+ help
+ This option enables support for the LEDs on Sharp Zaurus
+ SL-Cxx00 series (C1000, C3000, C3100).
+
+config LEDS_IXP4XX
+ tristate "LED Support for GPIO connected LEDs on IXP4XX processors"
+ depends LEDS_CLASS && ARCH_IXP4XX
+ help
+ This option enables support for the LEDs connected to GPIO
+ outputs of the Intel IXP4XX processors. To be useful the
+ particular board must have LEDs and they must be connected
+ to the GPIO lines. If unsure, say Y.
+
+config LEDS_TOSA
+ tristate "LED Support for the Sharp SL-6000 series"
+ depends LEDS_CLASS && PXA_SHARPSL
+ help
+ This option enables support for the LEDs on Sharp Zaurus
+ SL-6000 series.
+
+config LEDS_S3C24XX
+ tristate "LED Support for Samsung S3C24XX GPIO LEDs"
+ depends on LEDS_CLASS && ARCH_S3C2410
+ help
+ This option enables support for LEDs connected to GPIO lines
+ on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
+
+comment "LED Triggers"
+
+config LEDS_TRIGGERS
+ bool "LED Trigger support"
+ depends NEW_LEDS
+ help
+ This option enables trigger support for the leds class.
+ These triggers allow kernel events to drive the LEDs and can
+ be configured via sysfs. If unsure, say Y.
+
+config LEDS_TRIGGER_TIMER
+ tristate "LED Timer Trigger"
+ depends LEDS_TRIGGERS
+ help
+ This allows LEDs to be controlled by a programmable timer
+ via sysfs. If unsure, say Y.
+
+config LEDS_TRIGGER_IDE_DISK
+ bool "LED IDE Disk Trigger"
+ depends LEDS_TRIGGERS && BLK_DEV_IDEDISK
+ help
+ This allows LEDs to be controlled by IDE disk activity.
+ If unsure, say Y.
+
+endmenu
+
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
new file mode 100644
index 00000000000..40f042633bf
--- /dev/null
+++ b/drivers/leds/Makefile
@@ -0,0 +1,17 @@
+
+# LED Core
+obj-$(CONFIG_NEW_LEDS) += led-core.o
+obj-$(CONFIG_LEDS_CLASS) += led-class.o
+obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
+
+# LED Platform Drivers
+obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o
+obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
+obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o
+obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o
+obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o
+obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
+
+# LED Triggers
+obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
+obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
new file mode 100644
index 00000000000..c75d0ef1609
--- /dev/null
+++ b/drivers/leds/led-class.c
@@ -0,0 +1,172 @@
+/*
+ * LED Class Core
+ *
+ * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu>
+ * Copyright (C) 2005-2006 Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/timer.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+static struct class *leds_class;
+
+static ssize_t led_brightness_show(struct class_device *dev, char *buf)
+{
+ struct led_classdev *led_cdev = class_get_devdata(dev);
+ ssize_t ret = 0;
+
+ /* no lock needed for this */
+ sprintf(buf, "%u\n", led_cdev->brightness);
+ ret = strlen(buf) + 1;
+
+ return ret;
+}
+
+static ssize_t led_brightness_store(struct class_device *dev,
+ const char *buf, size_t size)
+{
+ struct led_classdev *led_cdev = class_get_devdata(dev);
+ ssize_t ret = -EINVAL;
+ char *after;
+ unsigned long state = simple_strtoul(buf, &after, 10);
+ size_t count = after - buf;
+
+ if (*after && isspace(*after))
+ count++;
+
+ if (count == size) {
+ ret = count;
+ led_set_brightness(led_cdev, state);
+ }
+
+ return ret;
+}
+
+static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show,
+ led_brightness_store);
+#ifdef CONFIG_LEDS_TRIGGERS
+static CLASS_DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
+#endif
+
+/**
+ * led_classdev_suspend - suspend an led_classdev.
+ * @led_cdev: the led_classdev to suspend.
+ */
+void led_classdev_suspend(struct led_classdev *led_cdev)
+{
+ led_cdev->flags |= LED_SUSPENDED;
+ led_cdev->brightness_set(led_cdev, 0);
+}
+EXPORT_SYMBOL_GPL(led_classdev_suspend);
+
+/**
+ * led_classdev_resume - resume an led_classdev.
+ * @led_cdev: the led_classdev to resume.
+ */
+void led_classdev_resume(struct led_classdev *led_cdev)
+{
+ led_cdev->brightness_set(led_cdev, led_cdev->brightness);
+ led_cdev->flags &= ~LED_SUSPENDED;
+}
+EXPORT_SYMBOL_GPL(led_classdev_resume);
+
+/**
+ * led_classdev_register - register a new object of led_classdev class.
+ * @dev: The device to register.
+ * @led_cdev: the led_classdev structure for this device.
+ */
+int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
+{
+ led_cdev->class_dev = class_device_create(leds_class, NULL, 0,
+ parent, "%s", led_cdev->name);
+ if (unlikely(IS_ERR(led_cdev->class_dev)))
+ return PTR_ERR(led_cdev->class_dev);
+
+ class_set_devdata(led_cdev->class_dev, led_cdev);
+
+ /* register the attributes */
+ class_device_create_file(led_cdev->class_dev,
+ &class_device_attr_brightness);
+
+ /* add to the list of leds */
+ write_lock(&leds_list_lock);
+ list_add_tail(&led_cdev->node, &leds_list);
+ write_unlock(&leds_list_lock);
+
+#ifdef CONFIG_LEDS_TRIGGERS
+ rwlock_init(&led_cdev->trigger_lock);
+
+ led_trigger_set_default(led_cdev);
+
+ class_device_create_file(led_cdev->class_dev,
+ &class_device_attr_trigger);
+#endif
+
+ printk(KERN_INFO "Registered led device: %s\n",
+ led_cdev->class_dev->class_id);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(led_classdev_register);
+
+/**
+ * led_classdev_unregister - unregisters a object of led_properties class.
+ * @led_cdev: the led device to unreigister
+ *
+ * Unregisters a previously registered via led_classdev_register object.
+ */
+void led_classdev_unregister(struct led_classdev *led_cdev)
+{
+ class_device_remove_file(led_cdev->class_dev,
+ &class_device_attr_brightness);
+#ifdef CONFIG_LEDS_TRIGGERS
+ class_device_remove_file(led_cdev->class_dev,
+ &class_device_attr_trigger);
+ write_lock(&led_cdev->trigger_lock);
+ if (led_cdev->trigger)
+ led_trigger_set(led_cdev, NULL);
+ write_unlock(&led_cdev->trigger_lock);
+#endif
+
+ class_device_unregister(led_cdev->class_dev);
+
+ write_lock(&leds_list_lock);
+ list_del(&led_cdev->node);
+ write_unlock(&leds_list_lock);
+}
+EXPORT_SYMBOL_GPL(led_classdev_unregister);
+
+static int __init leds_init(void)
+{
+ leds_class = class_create(THIS_MODULE, "leds");
+ if (IS_ERR(leds_class))
+ return PTR_ERR(leds_class);
+ return 0;
+}
+
+static void __exit leds_exit(void)
+{
+ class_destroy(leds_class);
+}
+
+subsys_initcall(leds_init);
+module_exit(leds_exit);
+
+MODULE_AUTHOR("John Lenz, Richard Purdie");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LED Class Interface");
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
new file mode 100644
index 00000000000..fe6541326c7
--- /dev/null
+++ b/drivers/leds/led-core.c
@@ -0,0 +1,25 @@
+/*
+ * LED Class Core
+ *
+ * Copyright 2005-2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+rwlock_t leds_list_lock = RW_LOCK_UNLOCKED;
+LIST_HEAD(leds_list);
+
+EXPORT_SYMBOL_GPL(leds_list);
+EXPORT_SYMBOL_GPL(leds_list_lock);
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
new file mode 100644
index 00000000000..5e2cd8be119
--- /dev/null
+++ b/drivers/leds/led-triggers.c
@@ -0,0 +1,239 @@
+/*
+ * LED Triggers Core
+ *
+ * Copyright 2005-2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/timer.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+/*
+ * Nests outside led_cdev->trigger_lock
+ */
+static rwlock_t triggers_list_lock = RW_LOCK_UNLOCKED;
+static LIST_HEAD(trigger_list);
+
+ssize_t led_trigger_store(struct class_device *dev, const char *buf,
+ size_t count)
+{
+ struct led_classdev *led_cdev = class_get_devdata(dev);
+ char trigger_name[TRIG_NAME_MAX];
+ struct led_trigger *trig;
+ size_t len;
+
+ trigger_name[sizeof(trigger_name) - 1] = '\0';
+ strncpy(trigger_name, buf, sizeof(trigger_name) - 1);
+ len = strlen(trigger_name);
+
+ if (len && trigger_name[len - 1] == '\n')
+ trigger_name[len - 1] = '\0';
+
+ if (!strcmp(trigger_name, "none")) {
+ write_lock(&led_cdev->trigger_lock);
+ led_trigger_set(led_cdev, NULL);
+ write_unlock(&led_cdev->trigger_lock);
+ return count;
+ }
+
+ read_lock(&triggers_list_lock);
+ list_for_each_entry(trig, &trigger_list, next_trig) {
+ if (!strcmp(trigger_name, trig->name)) {
+ write_lock(&led_cdev->trigger_lock);
+ led_trigger_set(led_cdev, trig);
+ write_unlock(&led_cdev->trigger_lock);
+
+ read_unlock(&triggers_list_lock);
+ return count;
+ }
+ }
+ read_unlock(&triggers_list_lock);
+
+ return -EINVAL;
+}
+
+
+ssize_t led_trigger_show(struct class_device *dev, char *buf)
+{
+ struct led_classdev *led_cdev = class_get_devdata(dev);
+ struct led_trigger *trig;
+ int len = 0;
+
+ read_lock(&triggers_list_lock);
+ read_lock(&led_cdev->trigger_lock);
+
+ if (!led_cdev->trigger)
+ len += sprintf(buf+len, "[none] ");
+ else
+ len += sprintf(buf+len, "none ");
+
+ list_for_each_entry(trig, &trigger_list, next_trig) {
+ if (led_cdev->trigger && !strcmp(led_cdev->trigger->name,
+ trig->name))
+ len += sprintf(buf+len, "[%s] ", trig->name);
+ else
+ len += sprintf(buf+len, "%s ", trig->name);
+ }
+ read_unlock(&led_cdev->trigger_lock);
+ read_unlock(&triggers_list_lock);
+
+ len += sprintf(len+buf, "\n");
+ return len;
+}
+
+void led_trigger_event(struct led_trigger *trigger,
+ enum led_brightness brightness)
+{
+ struct list_head *entry;
+
+ if (!trigger)
+ return;
+
+ read_lock(&trigger->leddev_list_lock);
+ list_for_each(entry, &trigger->led_cdevs) {
+ struct led_classdev *led_cdev;
+
+ led_cdev = list_entry(entry, struct led_classdev, trig_list);
+ led_set_brightness(led_cdev, brightness);
+ }
+ read_unlock(&trigger->leddev_list_lock);
+}
+
+/* Caller must ensure led_cdev->trigger_lock held */
+void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
+{
+ unsigned long flags;
+
+ /* Remove any existing trigger */
+ if (led_cdev->trigger) {
+ write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags);
+ list_del(&led_cdev->trig_list);
+ write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags);
+ if (led_cdev->trigger->deactivate)
+ led_cdev->trigger->deactivate(led_cdev);
+ }
+ if (trigger) {
+ write_lock_irqsave(&trigger->leddev_list_lock, flags);
+ list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs);
+ write_unlock_irqrestore(&trigger->leddev_list_lock, flags);
+ if (trigger->activate)
+ trigger->activate(led_cdev);
+ }
+ led_cdev->trigger = trigger;
+}
+
+void led_trigger_set_default(struct led_classdev *led_cdev)
+{
+ struct led_trigger *trig;
+
+ if (!led_cdev->default_trigger)
+ return;
+
+ read_lock(&triggers_list_lock);
+ write_lock(&led_cdev->trigger_lock);
+ list_for_each_entry(trig, &trigger_list, next_trig) {
+ if (!strcmp(led_cdev->default_trigger, trig->name))
+ led_trigger_set(led_cdev, trig);
+ }
+ write_unlock(&led_cdev->trigger_lock);
+ read_unlock(&triggers_list_lock);
+}
+
+int led_trigger_register(struct led_trigger *trigger)
+{
+ struct led_classdev *led_cdev;
+
+ rwlock_init(&trigger->leddev_list_lock);
+ INIT_LIST_HEAD(&trigger->led_cdevs);
+
+ /* Add to the list of led triggers */
+ write_lock(&triggers_list_lock);
+ list_add_tail(&trigger->next_trig, &trigger_list);
+ write_unlock(&triggers_list_lock);
+
+ /* Register with any LEDs that have this as a default trigger */
+ read_lock(&leds_list_lock);
+ list_for_each_entry(led_cdev, &leds_list, node) {
+ write_lock(&led_cdev->trigger_lock);
+ if (!led_cdev->trigger && led_cdev->default_trigger &&
+ !strcmp(led_cdev->default_trigger, trigger->name))
+ led_trigger_set(led_cdev, trigger);
+ write_unlock(&led_cdev->trigger_lock);
+ }
+ read_unlock(&leds_list_lock);
+
+ return 0;
+}
+
+void led_trigger_register_simple(const char *name, struct led_trigger **tp)
+{
+ struct led_trigger *trigger;
+
+ trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+
+ if (trigger) {
+ trigger->name = name;
+ led_trigger_register(trigger);
+ }
+ *tp = trigger;
+}
+
+void led_trigger_unregister(struct led_trigger *trigger)
+{
+ struct led_classdev *led_cdev;
+
+ /* Remove from the list of led triggers */
+ write_lock(&triggers_list_lock);
+ list_del(&trigger->next_trig);
+ write_unlock(&triggers_list_lock);
+
+ /* Remove anyone actively using this trigger */
+ read_lock(&leds_list_lock);
+ list_for_each_entry(led_cdev, &leds_list, node) {
+ write_lock(&led_cdev->trigger_lock);
+ if (led_cdev->trigger == trigger)
+ led_trigger_set(led_cdev, NULL);
+ write_unlock(&led_cdev->trigger_lock);
+ }
+ read_unlock(&leds_list_lock);
+}
+
+void led_trigger_unregister_simple(struct led_trigger *trigger)
+{
+ led_trigger_unregister(trigger);
+ kfree(trigger);
+}
+
+/* Used by LED Class */
+EXPORT_SYMBOL_GPL(led_trigger_set);
+EXPORT_SYMBOL_GPL(led_trigger_set_default);
+EXPORT_SYMBOL_GPL(led_trigger_show);
+EXPORT_SYMBOL_GPL(led_trigger_store);
+
+/* LED Trigger Interface */
+EXPORT_SYMBOL_GPL(led_trigger_register);
+EXPORT_SYMBOL_GPL(led_trigger_unregister);
+
+/* Simple LED Tigger Interface */
+EXPORT_SYMBOL_GPL(led_trigger_register_simple);
+EXPORT_SYMBOL_GPL(led_trigger_unregister_simple);
+EXPORT_SYMBOL_GPL(led_trigger_event);
+
+MODULE_AUTHOR("Richard Purdie");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LED Triggers Core");
diff --git a/drivers/leds/leds-corgi.c b/drivers/leds/leds-corgi.c
new file mode 100644
index 00000000000..bb7d84df012
--- /dev/null
+++ b/drivers/leds/leds-corgi.c
@@ -0,0 +1,121 @@
+/*
+ * LED Triggers Core
+ *
+ * Copyright 2005-2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/arch/corgi.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/hardware/scoop.h>
+
+static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+ if (value)
+ GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
+ else
+ GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
+}
+
+static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+ if (value)
+ set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
+ else
+ reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
+}
+
+static struct led_classdev corgi_amber_led = {
+ .name = "corgi:amber",
+ .default_trigger = "sharpsl-charge",
+ .brightness_set = corgiled_amber_set,
+};
+
+static struct led_classdev corgi_green_led = {
+ .name = "corgi:green",
+ .default_trigger = "nand-disk",
+ .brightness_set = corgiled_green_set,
+};
+
+#ifdef CONFIG_PM
+static int corgiled_suspend(struct platform_device *dev, pm_message_t state)
+{
+#ifdef CONFIG_LEDS_TRIGGERS
+ if (corgi_amber_led.trigger && strcmp(corgi_amber_led.trigger->name, "sharpsl-charge"))
+#endif
+ led_classdev_suspend(&corgi_amber_led);
+ led_classdev_suspend(&corgi_green_led);
+ return 0;
+}
+
+static int corgiled_resume(struct platform_device *dev)
+{
+ led_classdev_resume(&corgi_amber_led);
+ led_classdev_resume(&corgi_green_led);
+ return 0;
+}
+#endif
+
+static int corgiled_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = led_classdev_register(&pdev->dev, &corgi_amber_led);
+ if (ret < 0)
+ return ret;
+
+ ret = led_classdev_register(&pdev->dev, &corgi_green_led);
+ if (ret < 0)
+ led_classdev_unregister(&corgi_amber_led);
+
+ return ret;
+}
+
+static int corgiled_remove(struct platform_device *pdev)
+{
+ led_classdev_unregister(&corgi_amber_led);
+ led_classdev_unregister(&corgi_green_led);
+ return 0;
+}
+
+static struct platform_driver corgiled_driver = {
+ .probe = corgiled_probe,
+ .remove = corgiled_remove,
+#ifdef CONFIG_PM
+ .suspend = corgiled_suspend,
+ .resume = corgiled_resume,
+#endif
+ .driver = {
+ .name = "corgi-led",
+ },
+};
+
+static int __init corgiled_init(void)
+{
+ return platform_driver_register(&corgiled_driver);
+}
+
+static void __exit corgiled_exit(void)
+{
+ platform_driver_unregister(&corgiled_driver);
+}
+
+module_init(corgiled_init);
+module_exit(corgiled_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
+MODULE_DESCRIPTION("Corgi LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-ixp4xx-gpio.c b/drivers/leds/leds-ixp4xx-gpio.c
new file mode 100644
index 00000000000..30ced150e4c
--- /dev/null
+++ b/drivers/leds/leds-ixp4xx-gpio.c
@@ -0,0 +1,215 @@
+/*
+ * IXP4XX GPIO driver LED driver
+ *
+ * Author: John Bowler <jbowler@acm.org>
+ *
+ * Copyright (c) 2006 John Bowler
+ *
+ * Permission is hereby granted, free of charge, to any
+ * person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the
+ * Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice
+ * shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+ * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/leds.h>
+#include <asm/arch/hardware.h>
+
+extern spinlock_t gpio_lock;
+
+/* Up to 16 gpio lines are possible. */
+#define GPIO_MAX 16
+static struct ixp4xxgpioled_device {
+ struct led_classdev ancestor;
+ int flags;
+} ixp4xxgpioled_devices[GPIO_MAX];
+
+void ixp4xxgpioled_brightness_set(struct led_classdev *pled,
+ enum led_brightness value)
+{
+ const struct ixp4xxgpioled_device *const ixp4xx_dev =
+ container_of(pled, struct ixp4xxgpioled_device, ancestor);
+ const u32 gpio_pin = ixp4xx_dev - ixp4xxgpioled_devices;
+
+ if (gpio_pin < GPIO_MAX && ixp4xx_dev->ancestor.name != 0) {
+ /* Set or clear the 'gpio_pin' bit according to the style
+ * and the required setting (value > 0 == on)
+ */
+ const int gpio_value =
+ (value > 0) == (ixp4xx_dev->flags != IXP4XX_GPIO_LOW) ?
+ IXP4XX_GPIO_HIGH : IXP4XX_GPIO_LOW;
+
+ {
+ unsigned long flags;
+ spin_lock_irqsave(&gpio_lock, flags);
+ gpio_line_set(gpio_pin, gpio_value);
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ }
+ }
+}
+
+/* LEDs are described in resources, the following iterates over the valid
+ * LED resources.
+ */
+#define for_all_leds(i, pdev) \
+ for (i=0; i<pdev->num_resources; ++i) \
+ if (pdev->resource[i].start < GPIO_MAX && \
+ pdev->resource[i].name != 0)
+
+/* The following applies 'operation' to each LED from the given platform,
+ * the function always returns 0 to allow tail call elimination.
+ */
+static int apply_to_all_leds(struct platform_device *pdev,
+ void (*operation)(struct led_classdev *pled))
+{
+ int i;
+
+ for_all_leds(i, pdev)
+ operation(&ixp4xxgpioled_devices[pdev->resource[i].start].ancestor);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int ixp4xxgpioled_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ return apply_to_all_leds(pdev, led_classdev_suspend);
+}
+
+static int ixp4xxgpioled_resume(struct platform_device *pdev)
+{
+ return apply_to_all_leds(pdev, led_classdev_resume);
+}
+#endif
+
+static void ixp4xxgpioled_remove_one_led(struct led_classdev *pled)
+{
+ led_classdev_unregister(pled);
+ pled->name = 0;
+}
+
+static int ixp4xxgpioled_remove(struct platform_device *pdev)
+{
+ return apply_to_all_leds(pdev, ixp4xxgpioled_remove_one_led);
+}
+
+static int ixp4xxgpioled_probe(struct platform_device *pdev)
+{
+ /* The board level has to tell the driver where the
+ * LEDs are connected - there is no way to find out
+ * electrically. It must also say whether the GPIO
+ * lines are active high or active low.
+ *
+ * To do this read the num_resources (the number of
+ * LEDs) and the struct resource (the data for each
+ * LED). The name comes from the resource, and it
+ * isn't copied.
+ */
+ int i;
+
+ for_all_leds(i, pdev) {
+ const u8 gpio_pin = pdev->resource[i].start;
+ int rc;
+
+ if (ixp4xxgpioled_devices[gpio_pin].ancestor.name == 0) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+ gpio_line_config(gpio_pin, IXP4XX_GPIO_OUT);
+ /* The config can, apparently, reset the state,
+ * I suspect the gpio line may be an input and
+ * the config may cause the line to be latched,
+ * so the setting depends on how the LED is
+ * connected to the line (which affects how it
+ * floats if not driven).
+ */
+ gpio_line_set(gpio_pin, IXP4XX_GPIO_HIGH);
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ ixp4xxgpioled_devices[gpio_pin].flags =
+ pdev->resource[i].flags & IORESOURCE_BITS;
+
+ ixp4xxgpioled_devices[gpio_pin].ancestor.name =
+ pdev->resource[i].name;
+
+ /* This is how a board manufacturer makes the LED
+ * come on on reset - the GPIO line will be high, so
+ * make the LED light when the line is low...
+ */
+ if (ixp4xxgpioled_devices[gpio_pin].flags != IXP4XX_GPIO_LOW)
+ ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 100;
+ else
+ ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 0;
+
+ ixp4xxgpioled_devices[gpio_pin].ancestor.flags = 0;
+
+ ixp4xxgpioled_devices[gpio_pin].ancestor.brightness_set =
+ ixp4xxgpioled_brightness_set;
+
+ ixp4xxgpioled_devices[gpio_pin].ancestor.default_trigger = 0;
+ }
+
+ rc = led_classdev_register(&pdev->dev,
+ &ixp4xxgpioled_devices[gpio_pin].ancestor);
+ if (rc < 0) {
+ ixp4xxgpioled_devices[gpio_pin].ancestor.name = 0;
+ ixp4xxgpioled_remove(pdev);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static struct platform_driver ixp4xxgpioled_driver = {
+ .probe = ixp4xxgpioled_probe,
+ .remove = ixp4xxgpioled_remove,
+#ifdef CONFIG_PM
+ .suspend = ixp4xxgpioled_suspend,
+ .resume = ixp4xxgpioled_resume,
+#endif
+ .driver = {
+ .name = "IXP4XX-GPIO-LED",
+ },
+};
+
+static int __init ixp4xxgpioled_init(void)
+{
+ return platform_driver_register(&ixp4xxgpioled_driver);
+}
+
+static void __exit ixp4xxgpioled_exit(void)
+{
+ platform_driver_unregister(&ixp4xxgpioled_driver);
+}
+
+module_init(ixp4xxgpioled_init);
+module_exit(ixp4xxgpioled_exit);
+
+MODULE_AUTHOR("John Bowler <jbowler@acm.org>");
+MODULE_DESCRIPTION("IXP4XX GPIO LED driver");
+MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c
new file mode 100644
index 00000000000..749a86c2adb
--- /dev/null
+++ b/drivers/leds/leds-locomo.c
@@ -0,0 +1,95 @@
+/*
+ * linux/drivers/leds/locomo.c
+ *
+ * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu>
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/leds.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/locomo.h>
+
+static void locomoled_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value, int offset)
+{
+ struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->class_dev->dev);
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (value)
+ locomo_writel(LOCOMO_LPT_TOFH, locomo_dev->mapbase + offset);
+ else
+ locomo_writel(LOCOMO_LPT_TOFL, locomo_dev->mapbase + offset);
+ local_irq_restore(flags);
+}
+
+static void locomoled_brightness_set0(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ locomoled_brightness_set(led_cdev, value, LOCOMO_LPT0);
+}
+
+static void locomoled_brightness_set1(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ locomoled_brightness_set(led_cdev, value, LOCOMO_LPT1);
+}
+
+static struct led_classdev locomo_led0 = {
+ .name = "locomo:amber",
+ .brightness_set = locomoled_brightness_set0,
+};
+
+static struct led_classdev locomo_led1 = {
+ .name = "locomo:green",
+ .brightness_set = locomoled_brightness_set1,
+};
+
+static int locomoled_probe(struct locomo_dev *ldev)
+{
+ int ret;
+
+ ret = led_classdev_register(&ldev->dev, &locomo_led0);
+ if (ret < 0)
+ return ret;
+
+ ret = led_classdev_register(&ldev->dev, &locomo_led1);
+ if (ret < 0)
+ led_classdev_unregister(&locomo_led0);
+
+ return ret;
+}
+
+static int locomoled_remove(struct locomo_dev *dev)
+{
+ led_classdev_unregister(&locomo_led0);
+ led_classdev_unregister(&locomo_led1);
+ return 0;
+}
+
+static struct locomo_driver locomoled_driver = {
+ .drv = {
+ .name = "locomoled"
+ },
+ .devid = LOCOMO_DEVID_LED,
+ .probe = locomoled_probe,
+ .remove = locomoled_remove,
+};
+
+static int __init locomoled_init(void)
+{
+ return locomo_driver_register(&locomoled_driver);
+}
+module_init(locomoled_init);
+
+MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>");
+MODULE_DESCRIPTION("Locomo LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
new file mode 100644
index 00000000000..650cf72dc67
--- /dev/null
+++ b/drivers/leds/leds-s3c24xx.c
@@ -0,0 +1,163 @@
+/* drivers/leds/leds-s3c24xx.c
+ *
+ * (c) 2006 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX - LEDs GPIO driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/leds-gpio.h>
+
+/* our context */
+
+struct s3c24xx_gpio_led {
+ struct led_classdev cdev;
+ struct s3c24xx_led_platdata *pdata;
+};
+
+static inline struct s3c24xx_gpio_led *pdev_to_gpio(struct platform_device *dev)
+{
+ return platform_get_drvdata(dev);
+}
+
+static inline struct s3c24xx_gpio_led *to_gpio(struct led_classdev *led_cdev)
+{
+ return container_of(led_cdev, struct s3c24xx_gpio_led, cdev);
+}
+
+static void s3c24xx_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct s3c24xx_gpio_led *led = to_gpio(led_cdev);
+ struct s3c24xx_led_platdata *pd = led->pdata;
+
+ /* there will be a sort delay between setting the output and
+ * going from output to input when using tristate. */
+
+ s3c2410_gpio_setpin(pd->gpio, (value ? 1 : 0) ^
+ (pd->flags & S3C24XX_LEDF_ACTLOW));
+
+ if (pd->flags & S3C24XX_LEDF_TRISTATE)
+ s3c2410_gpio_cfgpin(pd->gpio,
+ value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT);
+
+}
+
+static int s3c24xx_led_remove(struct platform_device *dev)
+{
+ struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
+
+ led_classdev_unregister(&led->cdev);
+ kfree(led);
+
+ return 0;
+}
+
+static int s3c24xx_led_probe(struct platform_device *dev)
+{
+ struct s3c24xx_led_platdata *pdata = dev->dev.platform_data;
+ struct s3c24xx_gpio_led *led;
+ int ret;
+
+ led = kzalloc(sizeof(struct s3c24xx_gpio_led), GFP_KERNEL);
+ if (led == NULL) {
+ dev_err(&dev->dev, "No memory for device\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(dev, led);
+
+ led->cdev.brightness_set = s3c24xx_led_set;
+ led->cdev.default_trigger = pdata->def_trigger;
+ led->cdev.name = pdata->name;
+
+ led->pdata = pdata;
+
+ /* no point in having a pull-up if we are always driving */
+
+ if (pdata->flags & S3C24XX_LEDF_TRISTATE) {
+ s3c2410_gpio_setpin(pdata->gpio, 0);
+ s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_INPUT);
+ } else {
+ s3c2410_gpio_pullup(pdata->gpio, 0);
+ s3c2410_gpio_setpin(pdata->gpio, 0);
+ s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_OUTPUT);
+ }
+
+ /* register our new led device */
+
+ ret = led_classdev_register(&dev->dev, &led->cdev);
+ if (ret < 0) {
+ dev_err(&dev->dev, "led_classdev_register failed\n");
+ goto exit_err1;
+ }
+
+ return 0;
+
+ exit_err1:
+ kfree(led);
+ return ret;
+}
+
+
+#ifdef CONFIG_PM
+static int s3c24xx_led_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
+
+ led_classdev_suspend(&led->cdev);
+ return 0;
+}
+
+static int s3c24xx_led_resume(struct platform_device *dev)
+{
+ struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
+
+ led_classdev_resume(&led->cdev);
+ return 0;
+}
+#else
+#define s3c24xx_led_suspend NULL
+#define s3c24xx_led_resume NULL
+#endif
+
+static struct platform_driver s3c24xx_led_driver = {
+ .probe = s3c24xx_led_probe,
+ .remove = s3c24xx_led_remove,
+ .suspend = s3c24xx_led_suspend,
+ .resume = s3c24xx_led_resume,
+ .driver = {
+ .name = "s3c24xx_led",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init s3c24xx_led_init(void)
+{
+ return platform_driver_register(&s3c24xx_led_driver);
+}
+
+static void __exit s3c24xx_led_exit(void)
+{
+ platform_driver_unregister(&s3c24xx_led_driver);
+}
+
+module_init(s3c24xx_led_init);
+module_exit(s3c24xx_led_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("S3C24XX LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-spitz.c b/drivers/leds/leds-spitz.c
new file mode 100644
index 00000000000..65bbef4a5e0
--- /dev/null
+++ b/drivers/leds/leds-spitz.c
@@ -0,0 +1,125 @@
+/*
+ * LED Triggers Core
+ *
+ * Copyright 2005-2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/hardware/scoop.h>
+#include <asm/mach-types.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/spitz.h>
+
+static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+ if (value)
+ set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
+ else
+ reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
+}
+
+static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+ if (value)
+ set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN);
+ else
+ reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN);
+}
+
+static struct led_classdev spitz_amber_led = {
+ .name = "spitz:amber",
+ .default_trigger = "sharpsl-charge",
+ .brightness_set = spitzled_amber_set,
+};
+
+static struct led_classdev spitz_green_led = {
+ .name = "spitz:green",
+ .default_trigger = "ide-disk",
+ .brightness_set = spitzled_green_set,
+};
+
+#ifdef CONFIG_PM
+static int spitzled_suspend(struct platform_device *dev, pm_message_t state)
+{
+#ifdef CONFIG_LEDS_TRIGGERS
+ if (spitz_amber_led.trigger && strcmp(spitz_amber_led.trigger->name, "sharpsl-charge"))
+#endif
+ led_classdev_suspend(&spitz_amber_led);
+ led_classdev_suspend(&spitz_green_led);
+ return 0;
+}
+
+static int spitzled_resume(struct platform_device *dev)
+{
+ led_classdev_resume(&spitz_amber_led);
+ led_classdev_resume(&spitz_green_led);
+ return 0;
+}
+#endif
+
+static int spitzled_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ if (machine_is_akita())
+ spitz_green_led.default_trigger = "nand-disk";
+
+ ret = led_classdev_register(&pdev->dev, &spitz_amber_led);
+ if (ret < 0)
+ return ret;
+
+ ret = led_classdev_register(&pdev->dev, &spitz_green_led);
+ if (ret < 0)
+ led_classdev_unregister(&spitz_amber_led);
+
+ return ret;
+}
+
+static int spitzled_remove(struct platform_device *pdev)
+{
+ led_classdev_unregister(&spitz_amber_led);
+ led_classdev_unregister(&spitz_green_led);
+
+ return 0;
+}
+
+static struct platform_driver spitzled_driver = {
+ .probe = spitzled_probe,
+ .remove = spitzled_remove,
+#ifdef CONFIG_PM
+ .suspend = spitzled_suspend,
+ .resume = spitzled_resume,
+#endif
+ .driver = {
+ .name = "spitz-led",
+ },
+};
+
+static int __init spitzled_init(void)
+{
+ return platform_driver_register(&spitzled_driver);
+}
+
+static void __exit spitzled_exit(void)
+{
+ platform_driver_unregister(&spitzled_driver);
+}
+
+module_init(spitzled_init);
+module_exit(spitzled_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
+MODULE_DESCRIPTION("Spitz LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-tosa.c b/drivers/leds/leds-tosa.c
new file mode 100644
index 00000000000..c9e8cc1ec48
--- /dev/null
+++ b/drivers/leds/leds-tosa.c
@@ -0,0 +1,131 @@
+/*
+ * LED Triggers Core
+ *
+ * Copyright 2005 Dirk Opfer
+ *
+ * Author: Dirk Opfer <Dirk@Opfer-Online.de>
+ * based on spitz.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/hardware/scoop.h>
+#include <asm/mach-types.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/tosa.h>
+
+static void tosaled_amber_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (value)
+ set_scoop_gpio(&tosascoop_jc_device.dev,
+ TOSA_SCOOP_JC_CHRG_ERR_LED);
+ else
+ reset_scoop_gpio(&tosascoop_jc_device.dev,
+ TOSA_SCOOP_JC_CHRG_ERR_LED);
+}
+
+static void tosaled_green_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (value)
+ set_scoop_gpio(&tosascoop_jc_device.dev,
+ TOSA_SCOOP_JC_NOTE_LED);
+ else
+ reset_scoop_gpio(&tosascoop_jc_device.dev,
+ TOSA_SCOOP_JC_NOTE_LED);
+}
+
+static struct led_classdev tosa_amber_led = {
+ .name = "tosa:amber",
+ .default_trigger = "sharpsl-charge",
+ .brightness_set = tosaled_amber_set,
+};
+
+static struct led_classdev tosa_green_led = {
+ .name = "tosa:green",
+ .default_trigger = "nand-disk",
+ .brightness_set = tosaled_green_set,
+};
+
+#ifdef CONFIG_PM
+static int tosaled_suspend(struct platform_device *dev, pm_message_t state)
+{
+#ifdef CONFIG_LEDS_TRIGGERS
+ if (tosa_amber_led.trigger && strcmp(tosa_amber_led.trigger->name,
+ "sharpsl-charge"))
+#endif
+ led_classdev_suspend(&tosa_amber_led);
+ led_classdev_suspend(&tosa_green_led);
+ return 0;
+}
+
+static int tosaled_resume(struct platform_device *dev)
+{
+ led_classdev_resume(&tosa_amber_led);
+ led_classdev_resume(&tosa_green_led);
+ return 0;
+}
+#else
+#define tosaled_suspend NULL
+#define tosaled_resume NULL
+#endif
+
+static int tosaled_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = led_classdev_register(&pdev->dev, &tosa_amber_led);
+ if (ret < 0)
+ return ret;
+
+ ret = led_classdev_register(&pdev->dev, &tosa_green_led);
+ if (ret < 0)
+ led_classdev_unregister(&tosa_amber_led);
+
+ return ret;
+}
+
+static int tosaled_remove(struct platform_device *pdev)
+{
+ led_classdev_unregister(&tosa_amber_led);
+ led_classdev_unregister(&tosa_green_led);
+
+ return 0;
+}
+
+static struct platform_driver tosaled_driver = {
+ .probe = tosaled_probe,
+ .remove = tosaled_remove,
+ .suspend = tosaled_suspend,
+ .resume = tosaled_resume,
+ .driver = {
+ .name = "tosa-led",
+ },
+};
+
+static int __init tosaled_init(void)
+{
+ return platform_driver_register(&tosaled_driver);
+}
+
+static void __exit tosaled_exit(void)
+{
+ platform_driver_unregister(&tosaled_driver);
+}
+
+module_init(tosaled_init);
+module_exit(tosaled_exit);
+
+MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>");
+MODULE_DESCRIPTION("Tosa LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
new file mode 100644
index 00000000000..a715c4ed93f
--- /dev/null
+++ b/drivers/leds/leds.h
@@ -0,0 +1,44 @@
+/*
+ * LED Core
+ *
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __LEDS_H_INCLUDED
+#define __LEDS_H_INCLUDED
+
+#include <linux/leds.h>
+
+static inline void led_set_brightness(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (value > LED_FULL)
+ value = LED_FULL;
+ led_cdev->brightness = value;
+ if (!(led_cdev->flags & LED_SUSPENDED))
+ led_cdev->brightness_set(led_cdev, value);
+}
+
+extern rwlock_t leds_list_lock;
+extern struct list_head leds_list;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+void led_trigger_set_default(struct led_classdev *led_cdev);
+void led_trigger_set(struct led_classdev *led_cdev,
+ struct led_trigger *trigger);
+#else
+#define led_trigger_set_default(x) do {} while(0)
+#define led_trigger_set(x, y) do {} while(0)
+#endif
+
+ssize_t led_trigger_store(struct class_device *dev, const char *buf,
+ size_t count);
+ssize_t led_trigger_show(struct class_device *dev, char *buf);
+
+#endif /* __LEDS_H_INCLUDED */
diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c
new file mode 100644
index 00000000000..fa651886ab4
--- /dev/null
+++ b/drivers/leds/ledtrig-ide-disk.c
@@ -0,0 +1,62 @@
+/*
+ * LED IDE-Disk Activity Trigger
+ *
+ * Copyright 2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/leds.h>
+
+static void ledtrig_ide_timerfunc(unsigned long data);
+
+DEFINE_LED_TRIGGER(ledtrig_ide);
+static DEFINE_TIMER(ledtrig_ide_timer, ledtrig_ide_timerfunc, 0, 0);
+static int ide_activity;
+static int ide_lastactivity;
+
+void ledtrig_ide_activity(void)
+{
+ ide_activity++;
+ if (!timer_pending(&ledtrig_ide_timer))
+ mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
+}
+EXPORT_SYMBOL(ledtrig_ide_activity);
+
+static void ledtrig_ide_timerfunc(unsigned long data)
+{
+ if (ide_lastactivity != ide_activity) {
+ ide_lastactivity = ide_activity;
+ led_trigger_event(ledtrig_ide, LED_FULL);
+ mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
+ } else {
+ led_trigger_event(ledtrig_ide, LED_OFF);
+ }
+}
+
+static int __init ledtrig_ide_init(void)
+{
+ led_trigger_register_simple("ide-disk", &ledtrig_ide);
+ return 0;
+}
+
+static void __exit ledtrig_ide_exit(void)
+{
+ led_trigger_unregister_simple(ledtrig_ide);
+}
+
+module_init(ledtrig_ide_init);
+module_exit(ledtrig_ide_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
+MODULE_DESCRIPTION("LED IDE Disk Activity Trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
new file mode 100644
index 00000000000..fbf141ef46e
--- /dev/null
+++ b/drivers/leds/ledtrig-timer.c
@@ -0,0 +1,179 @@
+/*
+ * LED Kernel Timer Trigger
+ *
+ * Copyright 2005-2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/timer.h>
+#include <linux/ctype.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+struct timer_trig_data {
+ unsigned long delay_on; /* milliseconds on */
+ unsigned long delay_off; /* milliseconds off */
+ struct timer_list timer;
+};
+
+static void led_timer_function(unsigned long data)
+{
+ struct led_classdev *led_cdev = (struct led_classdev *) data;
+ struct timer_trig_data *timer_data = led_cdev->trigger_data;
+ unsigned long brightness = LED_OFF;
+ unsigned long delay = timer_data->delay_off;
+
+ if (!timer_data->delay_on || !timer_data->delay_off) {
+ led_set_brightness(led_cdev, LED_OFF);
+ return;
+ }
+
+ if (!led_cdev->brightness) {
+ brightness = LED_FULL;
+ delay = timer_data->delay_on;
+ }
+
+ led_set_brightness(led_cdev, brightness);
+
+ mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay));
+}
+
+static ssize_t led_delay_on_show(struct class_device *dev, char *buf)
+{
+ struct led_classdev *led_cdev = class_get_devdata(dev);
+ struct timer_trig_data *timer_data = led_cdev->trigger_data;
+
+ sprintf(buf, "%lu\n", timer_data->delay_on);
+
+ return strlen(buf) + 1;
+}
+
+static ssize_t led_delay_on_store(struct class_device *dev, const char *buf,
+ size_t size)
+{
+ struct led_classdev *led_cdev = class_get_devdata(dev);
+ struct timer_trig_data *timer_data = led_cdev->trigger_data;
+ int ret = -EINVAL;
+ char *after;
+ unsigned long state = simple_strtoul(buf, &after, 10);
+ size_t count = after - buf;
+
+ if (*after && isspace(*after))
+ count++;
+
+ if (count == size) {
+ timer_data->delay_on = state;
+ mod_timer(&timer_data->timer, jiffies + 1);
+ ret = count;
+ }
+
+ return ret;
+}
+
+static ssize_t led_delay_off_show(struct class_device *dev, char *buf)
+{
+ struct led_classdev *led_cdev = class_get_devdata(dev);
+ struct timer_trig_data *timer_data = led_cdev->trigger_data;
+
+ sprintf(buf, "%lu\n", timer_data->delay_off);
+
+ return strlen(buf) + 1;
+}
+
+static ssize_t led_delay_off_store(struct class_device *dev, const char *buf,
+ size_t size)
+{
+ struct led_classdev *led_cdev = class_get_devdata(dev);
+ struct timer_trig_data *timer_data = led_cdev->trigger_data;
+ int ret = -EINVAL;
+ char *after;
+ unsigned long state = simple_strtoul(buf, &after, 10);
+ size_t count = after - buf;
+
+ if (*after && isspace(*after))
+ count++;
+
+ if (count == size) {
+ timer_data->delay_off = state;
+ mod_timer(&timer_data->timer, jiffies + 1);
+ ret = count;
+ }
+
+ return ret;
+}
+
+static CLASS_DEVICE_ATTR(delay_on, 0644, led_delay_on_show,
+ led_delay_on_store);
+static CLASS_DEVICE_ATTR(delay_off, 0644, led_delay_off_show,
+ led_delay_off_store);
+
+static void timer_trig_activate(struct led_classdev *led_cdev)
+{
+ struct timer_trig_data *timer_data;
+
+ timer_data = kzalloc(sizeof(struct timer_trig_data), GFP_KERNEL);
+ if (!timer_data)
+ return;
+
+ led_cdev->trigger_data = timer_data;
+
+ init_timer(&timer_data->timer);
+ timer_data->timer.function = led_timer_function;
+ timer_data->timer.data = (unsigned long) led_cdev;
+
+ class_device_create_file(led_cdev->class_dev,
+ &class_device_attr_delay_on);
+ class_device_create_file(led_cdev->class_dev,
+ &class_device_attr_delay_off);
+}
+
+static void timer_trig_deactivate(struct led_classdev *led_cdev)
+{
+ struct timer_trig_data *timer_data = led_cdev->trigger_data;
+
+ if (timer_data) {
+ class_device_remove_file(led_cdev->class_dev,
+ &class_device_attr_delay_on);
+ class_device_remove_file(led_cdev->class_dev,
+ &class_device_attr_delay_off);
+ del_timer_sync(&timer_data->timer);
+ kfree(timer_data);
+ }
+}
+
+static struct led_trigger timer_led_trigger = {
+ .name = "timer",
+ .activate = timer_trig_activate,
+ .deactivate = timer_trig_deactivate,
+};
+
+static int __init timer_trig_init(void)
+{
+ return led_trigger_register(&timer_led_trigger);
+}
+
+static void __exit timer_trig_exit(void)
+{
+ led_trigger_unregister(&timer_led_trigger);
+}
+
+module_init(timer_trig_init);
+module_exit(timer_trig_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
+MODULE_DESCRIPTION("Timer LED trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index d2ead1776c1..259fd8973ce 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -42,6 +42,7 @@
#include <asm/semaphore.h>
#ifdef CONFIG_PPC
#include <asm/prom.h>
+#include <asm/machdep.h>
#endif
@@ -80,7 +81,7 @@ static struct adb_driver *adb_driver_list[] = {
static struct class *adb_dev_class;
struct adb_driver *adb_controller;
-struct notifier_block *adb_client_list = NULL;
+BLOCKING_NOTIFIER_HEAD(adb_client_list);
static int adb_got_sleep;
static int adb_inited;
static pid_t adb_probe_task_pid;
@@ -294,7 +295,7 @@ int __init adb_init(void)
int i;
#ifdef CONFIG_PPC32
- if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
+ if (!machine_is(chrp) && !machine_is(powermac))
return 0;
#endif
#ifdef CONFIG_MAC
@@ -354,7 +355,8 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
/* Stop autopoll */
if (adb_controller->autopoll)
adb_controller->autopoll(0);
- ret = notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL);
+ ret = blocking_notifier_call_chain(&adb_client_list,
+ ADB_MSG_POWERDOWN, NULL);
if (ret & NOTIFY_STOP_MASK) {
up(&adb_probe_mutex);
return PBOOK_SLEEP_REFUSE;
@@ -391,7 +393,8 @@ do_adb_reset_bus(void)
if (adb_controller->autopoll)
adb_controller->autopoll(0);
- nret = notifier_call_chain(&adb_client_list, ADB_MSG_PRE_RESET, NULL);
+ nret = blocking_notifier_call_chain(&adb_client_list,
+ ADB_MSG_PRE_RESET, NULL);
if (nret & NOTIFY_STOP_MASK) {
if (adb_controller->autopoll)
adb_controller->autopoll(autopoll_devs);
@@ -426,7 +429,8 @@ do_adb_reset_bus(void)
}
up(&adb_handler_sem);
- nret = notifier_call_chain(&adb_client_list, ADB_MSG_POST_RESET, NULL);
+ nret = blocking_notifier_call_chain(&adb_client_list,
+ ADB_MSG_POST_RESET, NULL);
if (nret & NOTIFY_STOP_MASK)
return -EBUSY;
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index c0b46bceb5d..394334ec576 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -1206,15 +1206,16 @@ init_ms_a3(int id)
static int __init adbhid_init(void)
{
#ifndef CONFIG_MAC
- if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
- return 0;
+ if (!machine_is(chrp) && !machine_is(powermac))
+ return 0;
#endif
led_request.complete = 1;
adbhid_probe();
- notifier_chain_register(&adb_client_list, &adbhid_adb_notifier);
+ blocking_notifier_chain_register(&adb_client_list,
+ &adbhid_adb_notifier);
return 0;
}
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 8dbf2852bae..53c1c790941 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -839,8 +839,8 @@ static int __init media_bay_init(void)
media_bays[i].cd_index = -1;
#endif
}
- if (_machine != _MACH_Pmac)
- return -ENODEV;
+ if (!machine_is(powermac))
+ return 0;
macio_register_driver(&media_bay_driver);
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 5ebfd1d138d..5282fec1707 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -627,8 +627,8 @@ thermostat_init(void)
if(therm_type == ADT7460)
device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed);
-#ifndef CONFIG_I2C_KEYWEST
- request_module("i2c-keywest");
+#ifndef CONFIG_I2C_POWERMAC
+ request_module("i2c-powermac");
#endif
return i2c_add_driver(&thermostat_driver);
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 4f5f3abc9cb..0b5ff553e39 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -187,7 +187,7 @@ extern int disable_kernel_backlight;
int __fake_sleep;
int asleep;
-struct notifier_block *sleep_notifier_list;
+BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
#ifdef CONFIG_ADB
static int adb_dev_map = 0;
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index f08e52f2107..35b70323e7e 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -102,7 +102,7 @@ static int pmu_kind = PMU_UNKNOWN;
static int pmu_fully_inited = 0;
int asleep;
-struct notifier_block *sleep_notifier_list;
+BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
static int pmu_probe(void);
static int pmu_init(void);
@@ -913,7 +913,8 @@ int powerbook_sleep(void)
struct adb_request sleep_req;
/* Notify device drivers */
- ret = notifier_call_chain(&sleep_notifier_list, PBOOK_SLEEP, NULL);
+ ret = blocking_notifier_call_chain(&sleep_notifier_list,
+ PBOOK_SLEEP, NULL);
if (ret & NOTIFY_STOP_MASK)
return -EBUSY;
@@ -984,7 +985,7 @@ int powerbook_sleep(void)
enable_irq(i);
/* Notify drivers */
- notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL);
+ blocking_notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL);
/* reenable ADB autopoll */
pmu_adb_autopoll(adb_dev_map);
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 6c0ba04bc57..ab3faa702d5 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -52,7 +52,7 @@
static LIST_HEAD(wf_controls);
static LIST_HEAD(wf_sensors);
static DEFINE_MUTEX(wf_lock);
-static struct notifier_block *wf_client_list;
+static BLOCKING_NOTIFIER_HEAD(wf_client_list);
static int wf_client_count;
static unsigned int wf_overtemp;
static unsigned int wf_overtemp_counter;
@@ -68,7 +68,7 @@ static struct platform_device wf_platform_device = {
static inline void wf_notify(int event, void *param)
{
- notifier_call_chain(&wf_client_list, event, param);
+ blocking_notifier_call_chain(&wf_client_list, event, param);
}
int wf_critical_overtemp(void)
@@ -398,7 +398,7 @@ int wf_register_client(struct notifier_block *nb)
struct wf_sensor *sr;
mutex_lock(&wf_lock);
- rc = notifier_chain_register(&wf_client_list, nb);
+ rc = blocking_notifier_chain_register(&wf_client_list, nb);
if (rc != 0)
goto bail;
wf_client_count++;
@@ -417,7 +417,7 @@ EXPORT_SYMBOL_GPL(wf_register_client);
int wf_unregister_client(struct notifier_block *nb)
{
mutex_lock(&wf_lock);
- notifier_chain_unregister(&wf_client_list, nb);
+ blocking_notifier_chain_unregister(&wf_client_list, nb);
wf_client_count++;
if (wf_client_count == 0)
wf_stop_thread();
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index ac43f98062f..ac25a48362a 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -127,6 +127,33 @@ config MD_RAID5
If unsure, say Y.
+config MD_RAID5_RESHAPE
+ bool "Support adding drives to a raid-5 array (experimental)"
+ depends on MD_RAID5 && EXPERIMENTAL
+ ---help---
+ A RAID-5 set can be expanded by adding extra drives. This
+ requires "restriping" the array which means (almost) every
+ block must be written to a different place.
+
+ This option allows such restriping to be done while the array
+ is online. However it is still EXPERIMENTAL code. It should
+ work, but please be sure that you have backups.
+
+ You will need mdadm verion 2.4.1 or later to use this
+ feature safely. During the early stage of reshape there is
+ a critical section where live data is being over-written. A
+ crash during this time needs extra care for recovery. The
+ newer mdadm takes a copy of the data in the critical section
+ and will restore it, if necessary, after a crash.
+
+ The mdadm usage is e.g.
+ mdadm --grow /dev/md1 --raid-disks=6
+ to grow '/dev/md1' to having 6 disks.
+
+ Note: The array can only be expanded, not contracted.
+ There should be enough spares already present to make the new
+ array workable.
+
config MD_RAID6
tristate "RAID-6 mode"
depends on BLK_DEV_MD
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 259e86f2654..61a590bb624 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -518,6 +518,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
char *ivopts;
unsigned int crypto_flags;
unsigned int key_size;
+ unsigned long long tmpll;
if (argc != 5) {
ti->error = PFX "Not enough arguments";
@@ -633,15 +634,17 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad5;
}
- if (sscanf(argv[2], SECTOR_FORMAT, &cc->iv_offset) != 1) {
+ if (sscanf(argv[2], "%llu", &tmpll) != 1) {
ti->error = PFX "Invalid iv_offset sector";
goto bad5;
}
+ cc->iv_offset = tmpll;
- if (sscanf(argv[4], SECTOR_FORMAT, &cc->start) != 1) {
+ if (sscanf(argv[4], "%llu", &tmpll) != 1) {
ti->error = PFX "Invalid device sector";
goto bad5;
}
+ cc->start = tmpll;
if (dm_get_device(ti, argv[3], cc->start, ti->len,
dm_table_get_mode(ti->table), &cc->dev)) {
@@ -885,8 +888,8 @@ static int crypt_status(struct dm_target *ti, status_type_t type,
result[sz++] = '-';
}
- DMEMIT(" " SECTOR_FORMAT " %s " SECTOR_FORMAT,
- cc->iv_offset, cc->dev->name, cc->start);
+ DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
+ cc->dev->name, (unsigned long long)cc->start);
break;
}
return 0;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 442e2be6052..8edd6435414 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/dm-ioctl.h>
+#include <linux/hdreg.h>
#include <asm/uaccess.h>
@@ -244,9 +245,9 @@ static void __hash_remove(struct hash_cell *hc)
dm_table_put(table);
}
- dm_put(hc->md);
if (hc->new_map)
dm_table_put(hc->new_map);
+ dm_put(hc->md);
free_cell(hc);
}
@@ -600,12 +601,22 @@ static int dev_create(struct dm_ioctl *param, size_t param_size)
*/
static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
{
+ struct mapped_device *md;
+ void *mdptr = NULL;
+
if (*param->uuid)
return __get_uuid_cell(param->uuid);
- else if (*param->name)
+
+ if (*param->name)
return __get_name_cell(param->name);
- else
- return dm_get_mdptr(huge_decode_dev(param->dev));
+
+ md = dm_get_md(huge_decode_dev(param->dev));
+ if (md) {
+ mdptr = dm_get_mdptr(md);
+ dm_put(md);
+ }
+
+ return mdptr;
}
static struct mapped_device *find_device(struct dm_ioctl *param)
@@ -690,6 +701,54 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size)
return dm_hash_rename(param->name, new_name);
}
+static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
+{
+ int r = -EINVAL, x;
+ struct mapped_device *md;
+ struct hd_geometry geometry;
+ unsigned long indata[4];
+ char *geostr = (char *) param + param->data_start;
+
+ md = find_device(param);
+ if (!md)
+ return -ENXIO;
+
+ if (geostr < (char *) (param + 1) ||
+ invalid_str(geostr, (void *) param + param_size)) {
+ DMWARN("Invalid geometry supplied.");
+ goto out;
+ }
+
+ x = sscanf(geostr, "%lu %lu %lu %lu", indata,
+ indata + 1, indata + 2, indata + 3);
+
+ if (x != 4) {
+ DMWARN("Unable to interpret geometry settings.");
+ goto out;
+ }
+
+ if (indata[0] > 65535 || indata[1] > 255 ||
+ indata[2] > 255 || indata[3] > ULONG_MAX) {
+ DMWARN("Geometry exceeds range limits.");
+ goto out;
+ }
+
+ geometry.cylinders = indata[0];
+ geometry.heads = indata[1];
+ geometry.sectors = indata[2];
+ geometry.start = indata[3];
+
+ r = dm_set_geometry(md, &geometry);
+ if (!r)
+ r = __dev_status(md, param);
+
+ param->data_size = 0;
+
+out:
+ dm_put(md);
+ return r;
+}
+
static int do_suspend(struct dm_ioctl *param)
{
int r = 0;
@@ -975,33 +1034,43 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
int r;
struct hash_cell *hc;
struct dm_table *t;
+ struct mapped_device *md;
- r = dm_table_create(&t, get_mode(param), param->target_count);
+ md = find_device(param);
+ if (!md)
+ return -ENXIO;
+
+ r = dm_table_create(&t, get_mode(param), param->target_count, md);
if (r)
- return r;
+ goto out;
r = populate_table(t, param, param_size);
if (r) {
dm_table_put(t);
- return r;
+ goto out;
}
down_write(&_hash_lock);
- hc = __find_device_hash_cell(param);
- if (!hc) {
- DMWARN("device doesn't appear to be in the dev hash table.");
- up_write(&_hash_lock);
+ hc = dm_get_mdptr(md);
+ if (!hc || hc->md != md) {
+ DMWARN("device has been removed from the dev hash table.");
dm_table_put(t);
- return -ENXIO;
+ up_write(&_hash_lock);
+ r = -ENXIO;
+ goto out;
}
if (hc->new_map)
dm_table_put(hc->new_map);
hc->new_map = t;
+ up_write(&_hash_lock);
+
param->flags |= DM_INACTIVE_PRESENT_FLAG;
+ r = __dev_status(md, param);
+
+out:
+ dm_put(md);
- r = __dev_status(hc->md, param);
- up_write(&_hash_lock);
return r;
}
@@ -1214,7 +1283,8 @@ static ioctl_fn lookup_ioctl(unsigned int cmd)
{DM_LIST_VERSIONS_CMD, list_versions},
- {DM_TARGET_MSG_CMD, target_message}
+ {DM_TARGET_MSG_CMD, target_message},
+ {DM_DEV_SET_GEOMETRY_CMD, dev_set_geometry}
};
return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn;
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 6a2cd5dc8a6..daf586c0898 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -26,6 +26,7 @@ struct linear_c {
static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
struct linear_c *lc;
+ unsigned long long tmp;
if (argc != 2) {
ti->error = "dm-linear: Invalid argument count";
@@ -38,10 +39,11 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return -ENOMEM;
}
- if (sscanf(argv[1], SECTOR_FORMAT, &lc->start) != 1) {
+ if (sscanf(argv[1], "%llu", &tmp) != 1) {
ti->error = "dm-linear: Invalid device sector";
goto bad;
}
+ lc->start = tmp;
if (dm_get_device(ti, argv[0], lc->start, ti->len,
dm_table_get_mode(ti->table), &lc->dev)) {
@@ -87,8 +89,8 @@ static int linear_status(struct dm_target *ti, status_type_t type,
break;
case STATUSTYPE_TABLE:
- snprintf(result, maxlen, "%s " SECTOR_FORMAT, lc->dev->name,
- lc->start);
+ snprintf(result, maxlen, "%s %llu", lc->dev->name,
+ (unsigned long long)lc->start);
break;
}
return 0;
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 4e90f231fbf..d12cf3e5e07 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -402,9 +402,21 @@ static void rh_dec(struct region_hash *rh, region_t region)
spin_lock_irqsave(&rh->region_lock, flags);
if (atomic_dec_and_test(&reg->pending)) {
+ /*
+ * There is no pending I/O for this region.
+ * We can move the region to corresponding list for next action.
+ * At this point, the region is not yet connected to any list.
+ *
+ * If the state is RH_NOSYNC, the region should be kept off
+ * from clean list.
+ * The hash entry for RH_NOSYNC will remain in memory
+ * until the region is recovered or the map is reloaded.
+ */
+
+ /* do nothing for RH_NOSYNC */
if (reg->state == RH_RECOVERING) {
list_add_tail(&reg->list, &rh->quiesced_regions);
- } else {
+ } else if (reg->state == RH_DIRTY) {
reg->state = RH_CLEAN;
list_add(&reg->list, &rh->clean_regions);
}
@@ -922,9 +934,9 @@ static inline int _check_region_size(struct dm_target *ti, uint32_t size)
static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
unsigned int mirror, char **argv)
{
- sector_t offset;
+ unsigned long long offset;
- if (sscanf(argv[1], SECTOR_FORMAT, &offset) != 1) {
+ if (sscanf(argv[1], "%llu", &offset) != 1) {
ti->error = "dm-mirror: Invalid offset";
return -EINVAL;
}
@@ -1191,16 +1203,17 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
for (m = 0; m < ms->nr_mirrors; m++)
DMEMIT("%s ", ms->mirror[m].dev->name);
- DMEMIT(SECTOR_FORMAT "/" SECTOR_FORMAT,
- ms->rh.log->type->get_sync_count(ms->rh.log),
- ms->nr_regions);
+ DMEMIT("%llu/%llu",
+ (unsigned long long)ms->rh.log->type->
+ get_sync_count(ms->rh.log),
+ (unsigned long long)ms->nr_regions);
break;
case STATUSTYPE_TABLE:
DMEMIT("%d ", ms->nr_mirrors);
for (m = 0; m < ms->nr_mirrors; m++)
- DMEMIT("%s " SECTOR_FORMAT " ",
- ms->mirror[m].dev->name, ms->mirror[m].offset);
+ DMEMIT("%s %llu ", ms->mirror[m].dev->name,
+ (unsigned long long)ms->mirror[m].offset);
}
return 0;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 7401540086d..08312b46463 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -49,11 +49,26 @@ struct pending_exception {
struct bio_list snapshot_bios;
/*
- * Other pending_exceptions that are processing this
- * chunk. When this list is empty, we know we can
- * complete the origins.
+ * Short-term queue of pending exceptions prior to submission.
*/
- struct list_head siblings;
+ struct list_head list;
+
+ /*
+ * The primary pending_exception is the one that holds
+ * the sibling_count and the list of origin_bios for a
+ * group of pending_exceptions. It is always last to get freed.
+ * These fields get set up when writing to the origin.
+ */
+ struct pending_exception *primary_pe;
+
+ /*
+ * Number of pending_exceptions processing this chunk.
+ * When this drops to zero we must complete the origin bios.
+ * If incrementing or decrementing this, hold pe->snap->lock for
+ * the sibling concerned and not pe->primary_pe->snap->lock unless
+ * they are the same.
+ */
+ atomic_t sibling_count;
/* Pointer back to snapshot context */
struct dm_snapshot *snap;
@@ -377,6 +392,8 @@ static void read_snapshot_metadata(struct dm_snapshot *s)
down_write(&s->lock);
s->valid = 0;
up_write(&s->lock);
+
+ dm_table_event(s->table);
}
}
@@ -542,8 +559,12 @@ static void snapshot_dtr(struct dm_target *ti)
{
struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+ /* Prevent further origin writes from using this snapshot. */
+ /* After this returns there can be no new kcopyd jobs. */
unregister_snapshot(s);
+ kcopyd_client_destroy(s->kcopyd_client);
+
exit_exception_table(&s->pending, pending_cache);
exit_exception_table(&s->complete, exception_cache);
@@ -552,7 +573,7 @@ static void snapshot_dtr(struct dm_target *ti)
dm_put_device(ti, s->origin);
dm_put_device(ti, s->cow);
- kcopyd_client_destroy(s->kcopyd_client);
+
kfree(s);
}
@@ -586,78 +607,117 @@ static void error_bios(struct bio *bio)
}
}
+static inline void error_snapshot_bios(struct pending_exception *pe)
+{
+ error_bios(bio_list_get(&pe->snapshot_bios));
+}
+
static struct bio *__flush_bios(struct pending_exception *pe)
{
- struct pending_exception *sibling;
+ /*
+ * If this pe is involved in a write to the origin and
+ * it is the last sibling to complete then release
+ * the bios for the original write to the origin.
+ */
+
+ if (pe->primary_pe &&
+ atomic_dec_and_test(&pe->primary_pe->sibling_count))
+ return bio_list_get(&pe->primary_pe->origin_bios);
+
+ return NULL;
+}
+
+static void __invalidate_snapshot(struct dm_snapshot *s,
+ struct pending_exception *pe, int err)
+{
+ if (!s->valid)
+ return;
- if (list_empty(&pe->siblings))
- return bio_list_get(&pe->origin_bios);
+ if (err == -EIO)
+ DMERR("Invalidating snapshot: Error reading/writing.");
+ else if (err == -ENOMEM)
+ DMERR("Invalidating snapshot: Unable to allocate exception.");
- sibling = list_entry(pe->siblings.next,
- struct pending_exception, siblings);
+ if (pe)
+ remove_exception(&pe->e);
- list_del(&pe->siblings);
+ if (s->store.drop_snapshot)
+ s->store.drop_snapshot(&s->store);
- /* This is fine as long as kcopyd is single-threaded. If kcopyd
- * becomes multi-threaded, we'll need some locking here.
- */
- bio_list_merge(&sibling->origin_bios, &pe->origin_bios);
+ s->valid = 0;
- return NULL;
+ dm_table_event(s->table);
}
static void pending_complete(struct pending_exception *pe, int success)
{
struct exception *e;
+ struct pending_exception *primary_pe;
struct dm_snapshot *s = pe->snap;
struct bio *flush = NULL;
- if (success) {
- e = alloc_exception();
- if (!e) {
- DMWARN("Unable to allocate exception.");
- down_write(&s->lock);
- s->store.drop_snapshot(&s->store);
- s->valid = 0;
- flush = __flush_bios(pe);
- up_write(&s->lock);
-
- error_bios(bio_list_get(&pe->snapshot_bios));
- goto out;
- }
- *e = pe->e;
-
- /*
- * Add a proper exception, and remove the
- * in-flight exception from the list.
- */
+ if (!success) {
+ /* Read/write error - snapshot is unusable */
down_write(&s->lock);
- insert_exception(&s->complete, e);
- remove_exception(&pe->e);
+ __invalidate_snapshot(s, pe, -EIO);
flush = __flush_bios(pe);
-
- /* Submit any pending write bios */
up_write(&s->lock);
- flush_bios(bio_list_get(&pe->snapshot_bios));
- } else {
- /* Read/write error - snapshot is unusable */
+ error_snapshot_bios(pe);
+ goto out;
+ }
+
+ e = alloc_exception();
+ if (!e) {
down_write(&s->lock);
- if (s->valid)
- DMERR("Error reading/writing snapshot");
- s->store.drop_snapshot(&s->store);
- s->valid = 0;
- remove_exception(&pe->e);
+ __invalidate_snapshot(s, pe, -ENOMEM);
flush = __flush_bios(pe);
up_write(&s->lock);
- error_bios(bio_list_get(&pe->snapshot_bios));
+ error_snapshot_bios(pe);
+ goto out;
+ }
+ *e = pe->e;
- dm_table_event(s->table);
+ /*
+ * Add a proper exception, and remove the
+ * in-flight exception from the list.
+ */
+ down_write(&s->lock);
+ if (!s->valid) {
+ flush = __flush_bios(pe);
+ up_write(&s->lock);
+
+ free_exception(e);
+
+ error_snapshot_bios(pe);
+ goto out;
}
+ insert_exception(&s->complete, e);
+ remove_exception(&pe->e);
+ flush = __flush_bios(pe);
+
+ up_write(&s->lock);
+
+ /* Submit any pending write bios */
+ flush_bios(bio_list_get(&pe->snapshot_bios));
+
out:
- free_pending_exception(pe);
+ primary_pe = pe->primary_pe;
+
+ /*
+ * Free the pe if it's not linked to an origin write or if
+ * it's not itself a primary pe.
+ */
+ if (!primary_pe || primary_pe != pe)
+ free_pending_exception(pe);
+
+ /*
+ * Free the primary pe if nothing references it.
+ */
+ if (primary_pe && !atomic_read(&primary_pe->sibling_count))
+ free_pending_exception(primary_pe);
if (flush)
flush_bios(flush);
@@ -734,38 +794,45 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
if (e) {
/* cast the exception to a pending exception */
pe = container_of(e, struct pending_exception, e);
+ goto out;
+ }
- } else {
- /*
- * Create a new pending exception, we don't want
- * to hold the lock while we do this.
- */
- up_write(&s->lock);
- pe = alloc_pending_exception();
- down_write(&s->lock);
+ /*
+ * Create a new pending exception, we don't want
+ * to hold the lock while we do this.
+ */
+ up_write(&s->lock);
+ pe = alloc_pending_exception();
+ down_write(&s->lock);
- e = lookup_exception(&s->pending, chunk);
- if (e) {
- free_pending_exception(pe);
- pe = container_of(e, struct pending_exception, e);
- } else {
- pe->e.old_chunk = chunk;
- bio_list_init(&pe->origin_bios);
- bio_list_init(&pe->snapshot_bios);
- INIT_LIST_HEAD(&pe->siblings);
- pe->snap = s;
- pe->started = 0;
-
- if (s->store.prepare_exception(&s->store, &pe->e)) {
- free_pending_exception(pe);
- s->valid = 0;
- return NULL;
- }
+ if (!s->valid) {
+ free_pending_exception(pe);
+ return NULL;
+ }
- insert_exception(&s->pending, &pe->e);
- }
+ e = lookup_exception(&s->pending, chunk);
+ if (e) {
+ free_pending_exception(pe);
+ pe = container_of(e, struct pending_exception, e);
+ goto out;
+ }
+
+ pe->e.old_chunk = chunk;
+ bio_list_init(&pe->origin_bios);
+ bio_list_init(&pe->snapshot_bios);
+ pe->primary_pe = NULL;
+ atomic_set(&pe->sibling_count, 1);
+ pe->snap = s;
+ pe->started = 0;
+
+ if (s->store.prepare_exception(&s->store, &pe->e)) {
+ free_pending_exception(pe);
+ return NULL;
}
+ insert_exception(&s->pending, &pe->e);
+
+ out:
return pe;
}
@@ -782,13 +849,15 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
{
struct exception *e;
struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+ int copy_needed = 0;
int r = 1;
chunk_t chunk;
- struct pending_exception *pe;
+ struct pending_exception *pe = NULL;
chunk = sector_to_chunk(s, bio->bi_sector);
/* Full snapshots are not usable */
+ /* To get here the table must be live so s->active is always set. */
if (!s->valid)
return -EIO;
@@ -806,36 +875,41 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
* to copy an exception */
down_write(&s->lock);
+ if (!s->valid) {
+ r = -EIO;
+ goto out_unlock;
+ }
+
/* If the block is already remapped - use that, else remap it */
e = lookup_exception(&s->complete, chunk);
if (e) {
remap_exception(s, e, bio);
- up_write(&s->lock);
-
- } else {
- pe = __find_pending_exception(s, bio);
-
- if (!pe) {
- if (s->store.drop_snapshot)
- s->store.drop_snapshot(&s->store);
- s->valid = 0;
- r = -EIO;
- up_write(&s->lock);
- } else {
- remap_exception(s, &pe->e, bio);
- bio_list_add(&pe->snapshot_bios, bio);
-
- if (!pe->started) {
- /* this is protected by snap->lock */
- pe->started = 1;
- up_write(&s->lock);
- start_copy(pe);
- } else
- up_write(&s->lock);
- r = 0;
- }
+ goto out_unlock;
+ }
+
+ pe = __find_pending_exception(s, bio);
+ if (!pe) {
+ __invalidate_snapshot(s, pe, -ENOMEM);
+ r = -EIO;
+ goto out_unlock;
+ }
+
+ remap_exception(s, &pe->e, bio);
+ bio_list_add(&pe->snapshot_bios, bio);
+
+ if (!pe->started) {
+ /* this is protected by snap->lock */
+ pe->started = 1;
+ copy_needed = 1;
}
+ r = 0;
+
+ out_unlock:
+ up_write(&s->lock);
+
+ if (copy_needed)
+ start_copy(pe);
} else {
/*
* FIXME: this read path scares me because we
@@ -847,6 +921,11 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
/* Do reads */
down_read(&s->lock);
+ if (!s->valid) {
+ up_read(&s->lock);
+ return -EIO;
+ }
+
/* See if it it has been remapped */
e = lookup_exception(&s->complete, chunk);
if (e)
@@ -884,9 +963,9 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
snap->store.fraction_full(&snap->store,
&numerator,
&denominator);
- snprintf(result, maxlen,
- SECTOR_FORMAT "/" SECTOR_FORMAT,
- numerator, denominator);
+ snprintf(result, maxlen, "%llu/%llu",
+ (unsigned long long)numerator,
+ (unsigned long long)denominator);
}
else
snprintf(result, maxlen, "Unknown");
@@ -899,9 +978,10 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
* to make private copies if the output is to
* make sense.
*/
- snprintf(result, maxlen, "%s %s %c " SECTOR_FORMAT,
+ snprintf(result, maxlen, "%s %s %c %llu",
snap->origin->name, snap->cow->name,
- snap->type, snap->chunk_size);
+ snap->type,
+ (unsigned long long)snap->chunk_size);
break;
}
@@ -911,40 +991,27 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
/*-----------------------------------------------------------------
* Origin methods
*---------------------------------------------------------------*/
-static void list_merge(struct list_head *l1, struct list_head *l2)
-{
- struct list_head *l1_n, *l2_p;
-
- l1_n = l1->next;
- l2_p = l2->prev;
-
- l1->next = l2;
- l2->prev = l1;
-
- l2_p->next = l1_n;
- l1_n->prev = l2_p;
-}
-
static int __origin_write(struct list_head *snapshots, struct bio *bio)
{
- int r = 1, first = 1;
+ int r = 1, first = 0;
struct dm_snapshot *snap;
struct exception *e;
- struct pending_exception *pe, *last = NULL;
+ struct pending_exception *pe, *next_pe, *primary_pe = NULL;
chunk_t chunk;
+ LIST_HEAD(pe_queue);
/* Do all the snapshots on this origin */
list_for_each_entry (snap, snapshots, list) {
+ down_write(&snap->lock);
+
/* Only deal with valid and active snapshots */
if (!snap->valid || !snap->active)
- continue;
+ goto next_snapshot;
/* Nothing to do if writing beyond end of snapshot */
if (bio->bi_sector >= dm_table_get_size(snap->table))
- continue;
-
- down_write(&snap->lock);
+ goto next_snapshot;
/*
* Remember, different snapshots can have
@@ -956,49 +1023,75 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
* Check exception table to see if block
* is already remapped in this snapshot
* and trigger an exception if not.
+ *
+ * sibling_count is initialised to 1 so pending_complete()
+ * won't destroy the primary_pe while we're inside this loop.
*/
e = lookup_exception(&snap->complete, chunk);
- if (!e) {
- pe = __find_pending_exception(snap, bio);
- if (!pe) {
- snap->store.drop_snapshot(&snap->store);
- snap->valid = 0;
-
- } else {
- if (last)
- list_merge(&pe->siblings,
- &last->siblings);
-
- last = pe;
- r = 0;
+ if (e)
+ goto next_snapshot;
+
+ pe = __find_pending_exception(snap, bio);
+ if (!pe) {
+ __invalidate_snapshot(snap, pe, ENOMEM);
+ goto next_snapshot;
+ }
+
+ if (!primary_pe) {
+ /*
+ * Either every pe here has same
+ * primary_pe or none has one yet.
+ */
+ if (pe->primary_pe)
+ primary_pe = pe->primary_pe;
+ else {
+ primary_pe = pe;
+ first = 1;
}
+
+ bio_list_add(&primary_pe->origin_bios, bio);
+
+ r = 0;
+ }
+
+ if (!pe->primary_pe) {
+ atomic_inc(&primary_pe->sibling_count);
+ pe->primary_pe = primary_pe;
+ }
+
+ if (!pe->started) {
+ pe->started = 1;
+ list_add_tail(&pe->list, &pe_queue);
}
+ next_snapshot:
up_write(&snap->lock);
}
+ if (!primary_pe)
+ goto out;
+
/*
- * Now that we have a complete pe list we can start the copying.
+ * If this is the first time we're processing this chunk and
+ * sibling_count is now 1 it means all the pending exceptions
+ * got completed while we were in the loop above, so it falls to
+ * us here to remove the primary_pe and submit any origin_bios.
*/
- if (last) {
- pe = last;
- do {
- down_write(&pe->snap->lock);
- if (first)
- bio_list_add(&pe->origin_bios, bio);
- if (!pe->started) {
- pe->started = 1;
- up_write(&pe->snap->lock);
- start_copy(pe);
- } else
- up_write(&pe->snap->lock);
- first = 0;
- pe = list_entry(pe->siblings.next,
- struct pending_exception, siblings);
-
- } while (pe != last);
+
+ if (first && atomic_dec_and_test(&primary_pe->sibling_count)) {
+ flush_bios(bio_list_get(&primary_pe->origin_bios));
+ free_pending_exception(primary_pe);
+ /* If we got here, pe_queue is necessarily empty. */
+ goto out;
}
+ /*
+ * Now that we have a complete pe list we can start the copying.
+ */
+ list_for_each_entry_safe(pe, next_pe, &pe_queue, list)
+ start_copy(pe);
+
+ out:
return r;
}
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 697aacafb02..08328a8f5a3 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -49,9 +49,9 @@ static inline struct stripe_c *alloc_context(unsigned int stripes)
static int get_stripe(struct dm_target *ti, struct stripe_c *sc,
unsigned int stripe, char **argv)
{
- sector_t start;
+ unsigned long long start;
- if (sscanf(argv[1], SECTOR_FORMAT, &start) != 1)
+ if (sscanf(argv[1], "%llu", &start) != 1)
return -EINVAL;
if (dm_get_device(ti, argv[0], start, sc->stripe_width,
@@ -103,7 +103,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return -EINVAL;
}
- if (((uint32_t)ti->len) & (chunk_size - 1)) {
+ if (ti->len & (chunk_size - 1)) {
ti->error = "dm-stripe: Target length not divisible by "
"chunk size";
return -EINVAL;
@@ -201,10 +201,11 @@ static int stripe_status(struct dm_target *ti,
break;
case STATUSTYPE_TABLE:
- DMEMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1);
+ DMEMIT("%d %llu", sc->stripes,
+ (unsigned long long)sc->chunk_mask + 1);
for (i = 0; i < sc->stripes; i++)
- DMEMIT(" %s " SECTOR_FORMAT, sc->stripe[i].dev->name,
- sc->stripe[i].physical_start);
+ DMEMIT(" %s %llu", sc->stripe[i].dev->name,
+ (unsigned long long)sc->stripe[i].physical_start);
break;
}
return 0;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 907b08ddb78..8f56a54cf0c 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -14,6 +14,7 @@
#include <linux/ctype.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
+#include <linux/mutex.h>
#include <asm/atomic.h>
#define MAX_DEPTH 16
@@ -22,6 +23,7 @@
#define CHILDREN_PER_NODE (KEYS_PER_NODE + 1)
struct dm_table {
+ struct mapped_device *md;
atomic_t holders;
/* btree table */
@@ -97,6 +99,8 @@ static void combine_restrictions_low(struct io_restrictions *lhs,
lhs->seg_boundary_mask =
min_not_zero(lhs->seg_boundary_mask, rhs->seg_boundary_mask);
+
+ lhs->no_cluster |= rhs->no_cluster;
}
/*
@@ -204,7 +208,8 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
return 0;
}
-int dm_table_create(struct dm_table **result, int mode, unsigned num_targets)
+int dm_table_create(struct dm_table **result, int mode,
+ unsigned num_targets, struct mapped_device *md)
{
struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL);
@@ -227,6 +232,7 @@ int dm_table_create(struct dm_table **result, int mode, unsigned num_targets)
}
t->mode = mode;
+ t->md = md;
*result = t;
return 0;
}
@@ -345,7 +351,7 @@ static struct dm_dev *find_device(struct list_head *l, dev_t dev)
/*
* Open a device so we can use it as a map destination.
*/
-static int open_dev(struct dm_dev *d, dev_t dev)
+static int open_dev(struct dm_dev *d, dev_t dev, struct mapped_device *md)
{
static char *_claim_ptr = "I belong to device-mapper";
struct block_device *bdev;
@@ -357,7 +363,7 @@ static int open_dev(struct dm_dev *d, dev_t dev)
bdev = open_by_devnum(dev, d->mode);
if (IS_ERR(bdev))
return PTR_ERR(bdev);
- r = bd_claim(bdev, _claim_ptr);
+ r = bd_claim_by_disk(bdev, _claim_ptr, dm_disk(md));
if (r)
blkdev_put(bdev);
else
@@ -368,12 +374,12 @@ static int open_dev(struct dm_dev *d, dev_t dev)
/*
* Close a device that we've been using.
*/
-static void close_dev(struct dm_dev *d)
+static void close_dev(struct dm_dev *d, struct mapped_device *md)
{
if (!d->bdev)
return;
- bd_release(d->bdev);
+ bd_release_from_disk(d->bdev, dm_disk(md));
blkdev_put(d->bdev);
d->bdev = NULL;
}
@@ -394,7 +400,7 @@ static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len)
* careful to leave things as they were if we fail to reopen the
* device.
*/
-static int upgrade_mode(struct dm_dev *dd, int new_mode)
+static int upgrade_mode(struct dm_dev *dd, int new_mode, struct mapped_device *md)
{
int r;
struct dm_dev dd_copy;
@@ -404,9 +410,9 @@ static int upgrade_mode(struct dm_dev *dd, int new_mode)
dd->mode |= new_mode;
dd->bdev = NULL;
- r = open_dev(dd, dev);
+ r = open_dev(dd, dev, md);
if (!r)
- close_dev(&dd_copy);
+ close_dev(&dd_copy, md);
else
*dd = dd_copy;
@@ -448,7 +454,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
dd->mode = mode;
dd->bdev = NULL;
- if ((r = open_dev(dd, dev))) {
+ if ((r = open_dev(dd, dev, t->md))) {
kfree(dd);
return r;
}
@@ -459,7 +465,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
list_add(&dd->list, &t->devices);
} else if (dd->mode != (mode | dd->mode)) {
- r = upgrade_mode(dd, mode);
+ r = upgrade_mode(dd, mode, t->md);
if (r)
return r;
}
@@ -523,6 +529,8 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
rs->seg_boundary_mask =
min_not_zero(rs->seg_boundary_mask,
q->seg_boundary_mask);
+
+ rs->no_cluster |= !test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
}
return r;
@@ -534,7 +542,7 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
void dm_put_device(struct dm_target *ti, struct dm_dev *dd)
{
if (atomic_dec_and_test(&dd->count)) {
- close_dev(dd);
+ close_dev(dd, ti->table->md);
list_del(&dd->list);
kfree(dd);
}
@@ -763,14 +771,14 @@ int dm_table_complete(struct dm_table *t)
return r;
}
-static DECLARE_MUTEX(_event_lock);
+static DEFINE_MUTEX(_event_lock);
void dm_table_event_callback(struct dm_table *t,
void (*fn)(void *), void *context)
{
- down(&_event_lock);
+ mutex_lock(&_event_lock);
t->event_fn = fn;
t->event_context = context;
- up(&_event_lock);
+ mutex_unlock(&_event_lock);
}
void dm_table_event(struct dm_table *t)
@@ -781,10 +789,10 @@ void dm_table_event(struct dm_table *t)
*/
BUG_ON(in_interrupt());
- down(&_event_lock);
+ mutex_lock(&_event_lock);
if (t->event_fn)
t->event_fn(t->event_context);
- up(&_event_lock);
+ mutex_unlock(&_event_lock);
}
sector_t dm_table_get_size(struct dm_table *t)
@@ -832,6 +840,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
q->hardsect_size = t->limits.hardsect_size;
q->max_segment_size = t->limits.max_segment_size;
q->seg_boundary_mask = t->limits.seg_boundary_mask;
+ if (t->limits.no_cluster)
+ q->queue_flags &= ~(1 << QUEUE_FLAG_CLUSTER);
+ else
+ q->queue_flags |= (1 << QUEUE_FLAG_CLUSTER);
+
}
unsigned int dm_table_get_num_targets(struct dm_table *t)
@@ -943,12 +956,20 @@ int dm_table_flush_all(struct dm_table *t)
return ret;
}
+struct mapped_device *dm_table_get_md(struct dm_table *t)
+{
+ dm_get(t->md);
+
+ return t->md;
+}
+
EXPORT_SYMBOL(dm_vcalloc);
EXPORT_SYMBOL(dm_get_device);
EXPORT_SYMBOL(dm_put_device);
EXPORT_SYMBOL(dm_table_event);
EXPORT_SYMBOL(dm_table_get_size);
EXPORT_SYMBOL(dm_table_get_mode);
+EXPORT_SYMBOL(dm_table_get_md);
EXPORT_SYMBOL(dm_table_put);
EXPORT_SYMBOL(dm_table_get);
EXPORT_SYMBOL(dm_table_unplug_all);
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c
index aecd9e0c261..64fd8e79ea4 100644
--- a/drivers/md/dm-target.c
+++ b/drivers/md/dm-target.c
@@ -78,8 +78,7 @@ void dm_put_target_type(struct target_type *t)
if (--ti->use == 0)
module_put(ti->tt.module);
- if (ti->use < 0)
- BUG();
+ BUG_ON(ti->use < 0);
up_read(&_lock);
return;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index a64798ef481..4d710b7a133 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/moduleparam.h>
#include <linux/blkpg.h>
#include <linux/bio.h>
@@ -17,6 +18,7 @@
#include <linux/mempool.h>
#include <linux/slab.h>
#include <linux/idr.h>
+#include <linux/hdreg.h>
#include <linux/blktrace_api.h>
static const char *_name = DM_NAME;
@@ -69,6 +71,7 @@ struct mapped_device {
request_queue_t *queue;
struct gendisk *disk;
+ char name[16];
void *interface_ptr;
@@ -101,6 +104,9 @@ struct mapped_device {
*/
struct super_block *frozen_sb;
struct block_device *suspended_bdev;
+
+ /* forced geometry settings */
+ struct hd_geometry geometry;
};
#define MIN_IOS 256
@@ -226,6 +232,13 @@ static int dm_blk_close(struct inode *inode, struct file *file)
return 0;
}
+static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct mapped_device *md = bdev->bd_disk->private_data;
+
+ return dm_get_geometry(md, geo);
+}
+
static inline struct dm_io *alloc_io(struct mapped_device *md)
{
return mempool_alloc(md->io_pool, GFP_NOIO);
@@ -312,6 +325,33 @@ struct dm_table *dm_get_table(struct mapped_device *md)
return t;
}
+/*
+ * Get the geometry associated with a dm device
+ */
+int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo)
+{
+ *geo = md->geometry;
+
+ return 0;
+}
+
+/*
+ * Set the geometry of a device.
+ */
+int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo)
+{
+ sector_t sz = (sector_t)geo->cylinders * geo->heads * geo->sectors;
+
+ if (geo->start > sz) {
+ DMWARN("Start sector is beyond the geometry limits.");
+ return -EINVAL;
+ }
+
+ md->geometry = *geo;
+
+ return 0;
+}
+
/*-----------------------------------------------------------------
* CRUD START:
* A more elegant soln is in the works that uses the queue
@@ -704,14 +744,14 @@ static int dm_any_congested(void *congested_data, int bdi_bits)
/*-----------------------------------------------------------------
* An IDR is used to keep track of allocated minor numbers.
*---------------------------------------------------------------*/
-static DECLARE_MUTEX(_minor_lock);
+static DEFINE_MUTEX(_minor_lock);
static DEFINE_IDR(_minor_idr);
static void free_minor(unsigned int minor)
{
- down(&_minor_lock);
+ mutex_lock(&_minor_lock);
idr_remove(&_minor_idr, minor);
- up(&_minor_lock);
+ mutex_unlock(&_minor_lock);
}
/*
@@ -724,7 +764,7 @@ static int specific_minor(struct mapped_device *md, unsigned int minor)
if (minor >= (1 << MINORBITS))
return -EINVAL;
- down(&_minor_lock);
+ mutex_lock(&_minor_lock);
if (idr_find(&_minor_idr, minor)) {
r = -EBUSY;
@@ -749,7 +789,7 @@ static int specific_minor(struct mapped_device *md, unsigned int minor)
}
out:
- up(&_minor_lock);
+ mutex_unlock(&_minor_lock);
return r;
}
@@ -758,7 +798,7 @@ static int next_free_minor(struct mapped_device *md, unsigned int *minor)
int r;
unsigned int m;
- down(&_minor_lock);
+ mutex_lock(&_minor_lock);
r = idr_pre_get(&_minor_idr, GFP_KERNEL);
if (!r) {
@@ -780,7 +820,7 @@ static int next_free_minor(struct mapped_device *md, unsigned int *minor)
*minor = m;
out:
- up(&_minor_lock);
+ mutex_unlock(&_minor_lock);
return r;
}
@@ -842,6 +882,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent)
md->disk->private_data = md;
sprintf(md->disk->disk_name, "dm-%d", minor);
add_disk(md->disk);
+ format_dev_t(md->name, MKDEV(_major, minor));
atomic_set(&md->pending, 0);
init_waitqueue_head(&md->wait);
@@ -904,6 +945,13 @@ static int __bind(struct mapped_device *md, struct dm_table *t)
sector_t size;
size = dm_table_get_size(t);
+
+ /*
+ * Wipe any geometry if the size of the table changed.
+ */
+ if (size != get_capacity(md->disk))
+ memset(&md->geometry, 0, sizeof(md->geometry));
+
__set_size(md, size);
if (size == 0)
return 0;
@@ -967,13 +1015,13 @@ static struct mapped_device *dm_find_md(dev_t dev)
if (MAJOR(dev) != _major || minor >= (1 << MINORBITS))
return NULL;
- down(&_minor_lock);
+ mutex_lock(&_minor_lock);
md = idr_find(&_minor_idr, minor);
if (!md || (dm_disk(md)->first_minor != minor))
md = NULL;
- up(&_minor_lock);
+ mutex_unlock(&_minor_lock);
return md;
}
@@ -988,15 +1036,9 @@ struct mapped_device *dm_get_md(dev_t dev)
return md;
}
-void *dm_get_mdptr(dev_t dev)
+void *dm_get_mdptr(struct mapped_device *md)
{
- struct mapped_device *md;
- void *mdptr = NULL;
-
- md = dm_find_md(dev);
- if (md)
- mdptr = md->interface_ptr;
- return mdptr;
+ return md->interface_ptr;
}
void dm_set_mdptr(struct mapped_device *md, void *ptr)
@@ -1011,18 +1053,18 @@ void dm_get(struct mapped_device *md)
void dm_put(struct mapped_device *md)
{
- struct dm_table *map = dm_get_table(md);
+ struct dm_table *map;
if (atomic_dec_and_test(&md->holders)) {
+ map = dm_get_table(md);
if (!dm_suspended(md)) {
dm_table_presuspend_targets(map);
dm_table_postsuspend_targets(map);
}
__unbind(md);
+ dm_table_put(map);
free_dev(md);
}
-
- dm_table_put(map);
}
/*
@@ -1107,6 +1149,7 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
{
struct dm_table *map = NULL;
DECLARE_WAITQUEUE(wait, current);
+ struct bio *def;
int r = -EINVAL;
down(&md->suspend_lock);
@@ -1166,9 +1209,11 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
/* were we interrupted ? */
r = -EINTR;
if (atomic_read(&md->pending)) {
+ clear_bit(DMF_BLOCK_IO, &md->flags);
+ def = bio_list_get(&md->deferred);
+ __flush_deferred_io(md, def);
up_write(&md->io_lock);
unlock_fs(md);
- clear_bit(DMF_BLOCK_IO, &md->flags);
goto out;
}
up_write(&md->io_lock);
@@ -1262,6 +1307,7 @@ int dm_suspended(struct mapped_device *md)
static struct block_device_operations dm_blk_dops = {
.open = dm_blk_open,
.release = dm_blk_close,
+ .getgeo = dm_blk_getgeo,
.owner = THIS_MODULE
};
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 4eaf075da21..fd90bc8f9e4 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -14,6 +14,7 @@
#include <linux/device-mapper.h>
#include <linux/list.h>
#include <linux/blkdev.h>
+#include <linux/hdreg.h>
#define DM_NAME "device-mapper"
#define DMWARN(f, x...) printk(KERN_WARNING DM_NAME ": " f "\n" , ## x)
@@ -23,16 +24,6 @@
#define DMEMIT(x...) sz += ((sz >= maxlen) ? \
0 : scnprintf(result + sz, maxlen - sz, x))
-/*
- * FIXME: I think this should be with the definition of sector_t
- * in types.h.
- */
-#ifdef CONFIG_LBD
-#define SECTOR_FORMAT "%llu"
-#else
-#define SECTOR_FORMAT "%lu"
-#endif
-
#define SECTOR_SHIFT 9
/*
@@ -57,7 +48,7 @@ struct mapped_device;
int dm_create(struct mapped_device **md);
int dm_create_with_minor(unsigned int minor, struct mapped_device **md);
void dm_set_mdptr(struct mapped_device *md, void *ptr);
-void *dm_get_mdptr(dev_t dev);
+void *dm_get_mdptr(struct mapped_device *md);
struct mapped_device *dm_get_md(dev_t dev);
/*
@@ -95,11 +86,18 @@ int dm_wait_event(struct mapped_device *md, int event_nr);
struct gendisk *dm_disk(struct mapped_device *md);
int dm_suspended(struct mapped_device *md);
+/*
+ * Geometry functions.
+ */
+int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo);
+int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo);
+
/*-----------------------------------------------------------------
* Functions for manipulating a table. Tables are also reference
* counted.
*---------------------------------------------------------------*/
-int dm_table_create(struct dm_table **result, int mode, unsigned num_targets);
+int dm_table_create(struct dm_table **result, int mode,
+ unsigned num_targets, struct mapped_device *md);
void dm_table_get(struct dm_table *t);
void dm_table_put(struct dm_table *t);
@@ -117,6 +115,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q);
unsigned int dm_table_get_num_targets(struct dm_table *t);
struct list_head *dm_table_get_devices(struct dm_table *t);
int dm_table_get_mode(struct dm_table *t);
+struct mapped_device *dm_table_get_md(struct dm_table *t);
void dm_table_presuspend_targets(struct dm_table *t);
void dm_table_postsuspend_targets(struct dm_table *t);
void dm_table_resume_targets(struct dm_table *t);
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index 9dcb2c8a385..72480a48d88 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
+#include <linux/mutex.h>
#include "kcopyd.h"
@@ -44,6 +45,9 @@ struct kcopyd_client {
struct page_list *pages;
unsigned int nr_pages;
unsigned int nr_free_pages;
+
+ wait_queue_head_t destroyq;
+ atomic_t nr_jobs;
};
static struct page_list *alloc_pl(void)
@@ -292,10 +296,15 @@ static int run_complete_job(struct kcopyd_job *job)
int read_err = job->read_err;
unsigned int write_err = job->write_err;
kcopyd_notify_fn fn = job->fn;
+ struct kcopyd_client *kc = job->kc;
- kcopyd_put_pages(job->kc, job->pages);
+ kcopyd_put_pages(kc, job->pages);
mempool_free(job, _job_pool);
fn(read_err, write_err, context);
+
+ if (atomic_dec_and_test(&kc->nr_jobs))
+ wake_up(&kc->destroyq);
+
return 0;
}
@@ -430,6 +439,7 @@ static void do_work(void *ignored)
*/
static void dispatch_job(struct kcopyd_job *job)
{
+ atomic_inc(&job->kc->nr_jobs);
push(&_pages_jobs, job);
wake();
}
@@ -572,21 +582,21 @@ int kcopyd_cancel(struct kcopyd_job *job, int block)
/*-----------------------------------------------------------------
* Unit setup
*---------------------------------------------------------------*/
-static DECLARE_MUTEX(_client_lock);
+static DEFINE_MUTEX(_client_lock);
static LIST_HEAD(_clients);
static void client_add(struct kcopyd_client *kc)
{
- down(&_client_lock);
+ mutex_lock(&_client_lock);
list_add(&kc->list, &_clients);
- up(&_client_lock);
+ mutex_unlock(&_client_lock);
}
static void client_del(struct kcopyd_client *kc)
{
- down(&_client_lock);
+ mutex_lock(&_client_lock);
list_del(&kc->list);
- up(&_client_lock);
+ mutex_unlock(&_client_lock);
}
static DEFINE_MUTEX(kcopyd_init_lock);
@@ -669,6 +679,9 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
return r;
}
+ init_waitqueue_head(&kc->destroyq);
+ atomic_set(&kc->nr_jobs, 0);
+
client_add(kc);
*result = kc;
return 0;
@@ -676,6 +689,9 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
void kcopyd_client_destroy(struct kcopyd_client *kc)
{
+ /* Wait for completion of all jobs submitted by this client. */
+ wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
+
dm_io_put(kc->nr_pages);
client_free_pages(kc);
client_del(kc);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 5ed2228745c..f19b874753a 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -43,6 +43,7 @@
#include <linux/buffer_head.h> /* for invalidate_bdev */
#include <linux/suspend.h>
#include <linux/poll.h>
+#include <linux/mutex.h>
#include <linux/init.h>
@@ -158,7 +159,18 @@ static int start_readonly;
*/
static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
static atomic_t md_event_count;
-static void md_new_event(mddev_t *mddev)
+void md_new_event(mddev_t *mddev)
+{
+ atomic_inc(&md_event_count);
+ wake_up(&md_event_waiters);
+ sysfs_notify(&mddev->kobj, NULL, "sync_action");
+}
+EXPORT_SYMBOL_GPL(md_new_event);
+
+/* Alternate version that can be called from interrupts
+ * when calling sysfs_notify isn't needed.
+ */
+void md_new_event_inintr(mddev_t *mddev)
{
atomic_inc(&md_event_count);
wake_up(&md_event_waiters);
@@ -213,13 +225,11 @@ static void mddev_put(mddev_t *mddev)
return;
if (!mddev->raid_disks && list_empty(&mddev->disks)) {
list_del(&mddev->all_mddevs);
- /* that blocks */
+ spin_unlock(&all_mddevs_lock);
blk_cleanup_queue(mddev->queue);
- /* that also blocks */
kobject_unregister(&mddev->kobj);
- /* result blows... */
- }
- spin_unlock(&all_mddevs_lock);
+ } else
+ spin_unlock(&all_mddevs_lock);
}
static mddev_t * mddev_find(dev_t unit)
@@ -253,7 +263,7 @@ static mddev_t * mddev_find(dev_t unit)
else
new->md_minor = MINOR(unit) >> MdpMinorShift;
- init_MUTEX(&new->reconfig_sem);
+ mutex_init(&new->reconfig_mutex);
INIT_LIST_HEAD(&new->disks);
INIT_LIST_HEAD(&new->all_mddevs);
init_timer(&new->safemode_timer);
@@ -266,6 +276,7 @@ static mddev_t * mddev_find(dev_t unit)
kfree(new);
return NULL;
}
+ set_bit(QUEUE_FLAG_CLUSTER, &new->queue->queue_flags);
blk_queue_make_request(new->queue, md_fail_request);
@@ -274,22 +285,17 @@ static mddev_t * mddev_find(dev_t unit)
static inline int mddev_lock(mddev_t * mddev)
{
- return down_interruptible(&mddev->reconfig_sem);
-}
-
-static inline void mddev_lock_uninterruptible(mddev_t * mddev)
-{
- down(&mddev->reconfig_sem);
+ return mutex_lock_interruptible(&mddev->reconfig_mutex);
}
static inline int mddev_trylock(mddev_t * mddev)
{
- return down_trylock(&mddev->reconfig_sem);
+ return mutex_trylock(&mddev->reconfig_mutex);
}
static inline void mddev_unlock(mddev_t * mddev)
{
- up(&mddev->reconfig_sem);
+ mutex_unlock(&mddev->reconfig_mutex);
md_wakeup_thread(mddev->thread);
}
@@ -660,7 +666,8 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
}
if (sb->major_version != 0 ||
- sb->minor_version != 90) {
+ sb->minor_version < 90 ||
+ sb->minor_version > 91) {
printk(KERN_WARNING "Bad version number %d.%d on %s\n",
sb->major_version, sb->minor_version,
b);
@@ -745,6 +752,20 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->bitmap_offset = 0;
mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
+ if (mddev->minor_version >= 91) {
+ mddev->reshape_position = sb->reshape_position;
+ mddev->delta_disks = sb->delta_disks;
+ mddev->new_level = sb->new_level;
+ mddev->new_layout = sb->new_layout;
+ mddev->new_chunk = sb->new_chunk;
+ } else {
+ mddev->reshape_position = MaxSector;
+ mddev->delta_disks = 0;
+ mddev->new_level = mddev->level;
+ mddev->new_layout = mddev->layout;
+ mddev->new_chunk = mddev->chunk_size;
+ }
+
if (sb->state & (1<<MD_SB_CLEAN))
mddev->recovery_cp = MaxSector;
else {
@@ -764,7 +785,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
mddev->bitmap_file == NULL) {
- if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6
+ if (mddev->level != 1 && mddev->level != 4
+ && mddev->level != 5 && mddev->level != 6
&& mddev->level != 10) {
/* FIXME use a better test */
printk(KERN_WARNING "md: bitmaps not supported for this level.\n");
@@ -838,7 +860,6 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->md_magic = MD_SB_MAGIC;
sb->major_version = mddev->major_version;
- sb->minor_version = mddev->minor_version;
sb->patch_version = mddev->patch_version;
sb->gvalid_words = 0; /* ignored */
memcpy(&sb->set_uuid0, mddev->uuid+0, 4);
@@ -857,6 +878,17 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->events_hi = (mddev->events>>32);
sb->events_lo = (u32)mddev->events;
+ if (mddev->reshape_position == MaxSector)
+ sb->minor_version = 90;
+ else {
+ sb->minor_version = 91;
+ sb->reshape_position = mddev->reshape_position;
+ sb->new_level = mddev->new_level;
+ sb->delta_disks = mddev->delta_disks;
+ sb->new_layout = mddev->new_layout;
+ sb->new_chunk = mddev->new_chunk;
+ }
+ mddev->minor_version = sb->minor_version;
if (mddev->in_sync)
{
sb->recovery_cp = mddev->recovery_cp;
@@ -893,10 +925,9 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
d->raid_disk = rdev2->raid_disk;
else
d->raid_disk = rdev2->desc_nr; /* compatibility */
- if (test_bit(Faulty, &rdev2->flags)) {
+ if (test_bit(Faulty, &rdev2->flags))
d->state = (1<<MD_DISK_FAULTY);
- failed++;
- } else if (test_bit(In_sync, &rdev2->flags)) {
+ else if (test_bit(In_sync, &rdev2->flags)) {
d->state = (1<<MD_DISK_ACTIVE);
d->state |= (1<<MD_DISK_SYNC);
active++;
@@ -1102,6 +1133,20 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
}
mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset);
}
+ if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) {
+ mddev->reshape_position = le64_to_cpu(sb->reshape_position);
+ mddev->delta_disks = le32_to_cpu(sb->delta_disks);
+ mddev->new_level = le32_to_cpu(sb->new_level);
+ mddev->new_layout = le32_to_cpu(sb->new_layout);
+ mddev->new_chunk = le32_to_cpu(sb->new_chunk)<<9;
+ } else {
+ mddev->reshape_position = MaxSector;
+ mddev->delta_disks = 0;
+ mddev->new_level = mddev->level;
+ mddev->new_layout = mddev->layout;
+ mddev->new_chunk = mddev->chunk_size;
+ }
+
} else if (mddev->pers == NULL) {
/* Insist of good event counter while assembling */
__u64 ev1 = le64_to_cpu(sb->events);
@@ -1173,6 +1218,14 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
}
+ if (mddev->reshape_position != MaxSector) {
+ sb->feature_map |= cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE);
+ sb->reshape_position = cpu_to_le64(mddev->reshape_position);
+ sb->new_layout = cpu_to_le32(mddev->new_layout);
+ sb->delta_disks = cpu_to_le32(mddev->delta_disks);
+ sb->new_level = cpu_to_le32(mddev->new_level);
+ sb->new_chunk = cpu_to_le32(mddev->new_chunk>>9);
+ }
max_dev = 0;
ITERATE_RDEV(mddev,rdev2,tmp)
@@ -1301,6 +1354,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
else
ko = &rdev->bdev->bd_disk->kobj;
sysfs_create_link(&rdev->kobj, ko, "block");
+ bd_claim_by_disk(rdev->bdev, rdev, mddev->gendisk);
return 0;
}
@@ -1311,6 +1365,7 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
MD_BUG();
return;
}
+ bd_release_from_disk(rdev->bdev, rdev->mddev->gendisk);
list_del_init(&rdev->same_set);
printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));
rdev->mddev = NULL;
@@ -1493,7 +1548,7 @@ static void sync_sbs(mddev_t * mddev)
}
}
-static void md_update_sb(mddev_t * mddev)
+void md_update_sb(mddev_t * mddev)
{
int err;
struct list_head *tmp;
@@ -1570,6 +1625,7 @@ repeat:
wake_up(&mddev->sb_wait);
}
+EXPORT_SYMBOL_GPL(md_update_sb);
/* words written to sysfs files may, or my not, be \n terminated.
* We want to accept with case. For this we use cmd_match.
@@ -2162,7 +2218,9 @@ action_show(mddev_t *mddev, char *page)
char *type = "idle";
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) {
- if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+ if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+ type = "reshape";
+ else if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
type = "resync";
else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
@@ -2193,10 +2251,17 @@ action_store(mddev_t *mddev, const char *page, size_t len)
return -EBUSY;
else if (cmd_match(page, "resync") || cmd_match(page, "recover"))
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- else {
+ else if (cmd_match(page, "reshape")) {
+ int err;
+ if (mddev->pers->start_reshape == NULL)
+ return -EINVAL;
+ err = mddev->pers->start_reshape(mddev);
+ if (err)
+ return err;
+ } else {
if (cmd_match(page, "check"))
set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
- else if (cmd_match(page, "repair"))
+ else if (!cmd_match(page, "repair"))
return -EINVAL;
set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
@@ -2304,6 +2369,63 @@ sync_completed_show(mddev_t *mddev, char *page)
static struct md_sysfs_entry
md_sync_completed = __ATTR_RO(sync_completed);
+static ssize_t
+suspend_lo_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo);
+}
+
+static ssize_t
+suspend_lo_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ char *e;
+ unsigned long long new = simple_strtoull(buf, &e, 10);
+
+ if (mddev->pers->quiesce == NULL)
+ return -EINVAL;
+ if (buf == e || (*e && *e != '\n'))
+ return -EINVAL;
+ if (new >= mddev->suspend_hi ||
+ (new > mddev->suspend_lo && new < mddev->suspend_hi)) {
+ mddev->suspend_lo = new;
+ mddev->pers->quiesce(mddev, 2);
+ return len;
+ } else
+ return -EINVAL;
+}
+static struct md_sysfs_entry md_suspend_lo =
+__ATTR(suspend_lo, S_IRUGO|S_IWUSR, suspend_lo_show, suspend_lo_store);
+
+
+static ssize_t
+suspend_hi_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_hi);
+}
+
+static ssize_t
+suspend_hi_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ char *e;
+ unsigned long long new = simple_strtoull(buf, &e, 10);
+
+ if (mddev->pers->quiesce == NULL)
+ return -EINVAL;
+ if (buf == e || (*e && *e != '\n'))
+ return -EINVAL;
+ if ((new <= mddev->suspend_lo && mddev->suspend_lo >= mddev->suspend_hi) ||
+ (new > mddev->suspend_lo && new > mddev->suspend_hi)) {
+ mddev->suspend_hi = new;
+ mddev->pers->quiesce(mddev, 1);
+ mddev->pers->quiesce(mddev, 0);
+ return len;
+ } else
+ return -EINVAL;
+}
+static struct md_sysfs_entry md_suspend_hi =
+__ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store);
+
+
static struct attribute *md_default_attrs[] = {
&md_level.attr,
&md_raid_disks.attr,
@@ -2321,6 +2443,8 @@ static struct attribute *md_redundancy_attrs[] = {
&md_sync_max.attr,
&md_sync_speed.attr,
&md_sync_completed.attr,
+ &md_suspend_lo.attr,
+ &md_suspend_hi.attr,
NULL,
};
static struct attribute_group md_redundancy_group = {
@@ -2338,9 +2462,11 @@ md_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
if (!entry->show)
return -EIO;
- mddev_lock(mddev);
- rv = entry->show(mddev, page);
- mddev_unlock(mddev);
+ rv = mddev_lock(mddev);
+ if (!rv) {
+ rv = entry->show(mddev, page);
+ mddev_unlock(mddev);
+ }
return rv;
}
@@ -2354,9 +2480,11 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
if (!entry->store)
return -EIO;
- mddev_lock(mddev);
- rv = entry->store(mddev, page, length);
- mddev_unlock(mddev);
+ rv = mddev_lock(mddev);
+ if (!rv) {
+ rv = entry->store(mddev, page, length);
+ mddev_unlock(mddev);
+ }
return rv;
}
@@ -2380,7 +2508,7 @@ int mdp_major = 0;
static struct kobject *md_probe(dev_t dev, int *part, void *data)
{
- static DECLARE_MUTEX(disks_sem);
+ static DEFINE_MUTEX(disks_mutex);
mddev_t *mddev = mddev_find(dev);
struct gendisk *disk;
int partitioned = (MAJOR(dev) != MD_MAJOR);
@@ -2390,15 +2518,15 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)
if (!mddev)
return NULL;
- down(&disks_sem);
+ mutex_lock(&disks_mutex);
if (mddev->gendisk) {
- up(&disks_sem);
+ mutex_unlock(&disks_mutex);
mddev_put(mddev);
return NULL;
}
disk = alloc_disk(1 << shift);
if (!disk) {
- up(&disks_sem);
+ mutex_unlock(&disks_mutex);
mddev_put(mddev);
return NULL;
}
@@ -2416,7 +2544,7 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)
disk->queue = mddev->queue;
add_disk(disk);
mddev->gendisk = disk;
- up(&disks_sem);
+ mutex_unlock(&disks_mutex);
mddev->kobj.parent = &disk->kobj;
mddev->kobj.k_name = NULL;
snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md");
@@ -2539,6 +2667,14 @@ static int do_md_run(mddev_t * mddev)
mddev->level = pers->level;
strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
+ if (mddev->reshape_position != MaxSector &&
+ pers->start_reshape == NULL) {
+ /* This personality cannot handle reshaping... */
+ mddev->pers = NULL;
+ module_put(pers->owner);
+ return -EINVAL;
+ }
+
mddev->recovery = 0;
mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
mddev->barriers_work = 1;
@@ -2772,7 +2908,6 @@ static void autorun_array(mddev_t *mddev)
*/
static void autorun_devices(int part)
{
- struct list_head candidates;
struct list_head *tmp;
mdk_rdev_t *rdev0, *rdev;
mddev_t *mddev;
@@ -2781,6 +2916,7 @@ static void autorun_devices(int part)
printk(KERN_INFO "md: autorun ...\n");
while (!list_empty(&pending_raid_disks)) {
dev_t dev;
+ LIST_HEAD(candidates);
rdev0 = list_entry(pending_raid_disks.next,
mdk_rdev_t, same_set);
@@ -3427,11 +3563,18 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
mddev->bitmap_offset = 0;
+ mddev->reshape_position = MaxSector;
+
/*
* Generate a 128 bit UUID
*/
get_random_bytes(mddev->uuid, 16);
+ mddev->new_level = mddev->level;
+ mddev->new_chunk = mddev->chunk_size;
+ mddev->new_layout = mddev->layout;
+ mddev->delta_disks = 0;
+
return 0;
}
@@ -3440,6 +3583,7 @@ static int update_size(mddev_t *mddev, unsigned long size)
mdk_rdev_t * rdev;
int rv;
struct list_head *tmp;
+ int fit = (size == 0);
if (mddev->pers->resize == NULL)
return -EINVAL;
@@ -3457,7 +3601,6 @@ static int update_size(mddev_t *mddev, unsigned long size)
return -EBUSY;
ITERATE_RDEV(mddev,rdev,tmp) {
sector_t avail;
- int fit = (size == 0);
if (rdev->sb_offset > rdev->data_offset)
avail = (rdev->sb_offset*2) - rdev->data_offset;
else
@@ -3487,14 +3630,16 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks)
{
int rv;
/* change the number of raid disks */
- if (mddev->pers->reshape == NULL)
+ if (mddev->pers->check_reshape == NULL)
return -EINVAL;
if (raid_disks <= 0 ||
raid_disks >= mddev->max_disks)
return -EINVAL;
- if (mddev->sync_thread)
+ if (mddev->sync_thread || mddev->reshape_position != MaxSector)
return -EBUSY;
- rv = mddev->pers->reshape(mddev, raid_disks);
+ mddev->delta_disks = raid_disks - mddev->raid_disks;
+
+ rv = mddev->pers->check_reshape(mddev);
return rv;
}
@@ -4013,7 +4158,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
- md_new_event(mddev);
+ md_new_event_inintr(mddev);
}
/* seq_file implementation /proc/mdstat */
@@ -4041,7 +4186,10 @@ static void status_unused(struct seq_file *seq)
static void status_resync(struct seq_file *seq, mddev_t * mddev)
{
- unsigned long max_blocks, resync, res, dt, db, rt;
+ sector_t max_blocks, resync, res;
+ unsigned long dt, db, rt;
+ int scale;
+ unsigned int per_milli;
resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2;
@@ -4057,9 +4205,22 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev)
MD_BUG();
return;
}
- res = (resync/1024)*1000/(max_blocks/1024 + 1);
+ /* Pick 'scale' such that (resync>>scale)*1000 will fit
+ * in a sector_t, and (max_blocks>>scale) will fit in a
+ * u32, as those are the requirements for sector_div.
+ * Thus 'scale' must be at least 10
+ */
+ scale = 10;
+ if (sizeof(sector_t) > sizeof(unsigned long)) {
+ while ( max_blocks/2 > (1ULL<<(scale+32)))
+ scale++;
+ }
+ res = (resync>>scale)*1000;
+ sector_div(res, (u32)((max_blocks>>scale)+1));
+
+ per_milli = res;
{
- int i, x = res/50, y = 20-x;
+ int i, x = per_milli/50, y = 20-x;
seq_printf(seq, "[");
for (i = 0; i < x; i++)
seq_printf(seq, "=");
@@ -4068,10 +4229,14 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev)
seq_printf(seq, ".");
seq_printf(seq, "] ");
}
- seq_printf(seq, " %s =%3lu.%lu%% (%lu/%lu)",
+ seq_printf(seq, " %s =%3u.%u%% (%llu/%llu)",
+ (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)?
+ "reshape" :
(test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ?
- "resync" : "recovery"),
- res/10, res % 10, resync, max_blocks);
+ "resync" : "recovery")),
+ per_milli/10, per_milli % 10,
+ (unsigned long long) resync,
+ (unsigned long long) max_blocks);
/*
* We do not want to overflow, so the order of operands and
@@ -4085,7 +4250,7 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev)
dt = ((jiffies - mddev->resync_mark) / HZ);
if (!dt) dt++;
db = resync - (mddev->resync_mark_cnt/2);
- rt = (dt * ((max_blocks-resync) / (db/100+1)))/100;
+ rt = (dt * ((unsigned long)(max_blocks-resync) / (db/100+1)))/100;
seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6);
@@ -4184,8 +4349,9 @@ static int md_seq_show(struct seq_file *seq, void *v)
return 0;
}
- if (mddev_lock(mddev)!=0)
+ if (mddev_lock(mddev) < 0)
return -EINTR;
+
if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) {
seq_printf(seq, "%s : %sactive", mdname(mddev),
mddev->pers ? "" : "in");
@@ -4442,7 +4608,7 @@ static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
#define SYNC_MARKS 10
#define SYNC_MARK_STEP (3*HZ)
-static void md_do_sync(mddev_t *mddev)
+void md_do_sync(mddev_t *mddev)
{
mddev_t *mddev2;
unsigned int currspeed = 0,
@@ -4522,7 +4688,9 @@ static void md_do_sync(mddev_t *mddev)
*/
max_sectors = mddev->resync_max_sectors;
mddev->resync_mismatches = 0;
- } else
+ } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+ max_sectors = mddev->size << 1;
+ else
/* recovery follows the physical size of devices */
max_sectors = mddev->size << 1;
@@ -4658,6 +4826,8 @@ static void md_do_sync(mddev_t *mddev)
mddev->pers->sync_request(mddev, max_sectors, &skipped, 1);
if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
+ test_bit(MD_RECOVERY_SYNC, &mddev->recovery) &&
+ !test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
mddev->curr_resync > 2 &&
mddev->curr_resync >= mddev->recovery_cp) {
if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
@@ -4675,6 +4845,7 @@ static void md_do_sync(mddev_t *mddev)
set_bit(MD_RECOVERY_DONE, &mddev->recovery);
md_wakeup_thread(mddev->thread);
}
+EXPORT_SYMBOL_GPL(md_do_sync);
/*
@@ -4730,7 +4901,7 @@ void md_check_recovery(mddev_t *mddev)
))
return;
- if (mddev_trylock(mddev)==0) {
+ if (mddev_trylock(mddev)) {
int spares =0;
spin_lock_irq(&mddev->write_lock);
@@ -4866,8 +5037,10 @@ static int md_notify_reboot(struct notifier_block *this,
printk(KERN_INFO "md: stopping all md devices.\n");
ITERATE_MDDEV(mddev,tmp)
- if (mddev_trylock(mddev)==0)
+ if (mddev_trylock(mddev)) {
do_md_stop (mddev, 1);
+ mddev_unlock(mddev);
+ }
/*
* certain more exotic SCSI devices are known to be
* volatile wrt too early system reboots. While the
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 678f4dbbea1..cb8c6317e4e 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -331,13 +331,14 @@ static int raid0_run (mddev_t *mddev)
goto out_free_conf;
size = conf->strip_zone[cur].size;
- for (i=0; i< nb_zone; i++) {
- conf->hash_table[i] = conf->strip_zone + cur;
+ conf->hash_table[0] = conf->strip_zone + cur;
+ for (i=1; i< nb_zone; i++) {
while (size <= conf->hash_spacing) {
cur++;
size += conf->strip_zone[cur].size;
}
size -= conf->hash_spacing;
+ conf->hash_table[i] = conf->strip_zone + cur;
}
if (conf->preshift) {
conf->hash_spacing >>= conf->preshift;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 5d88329e3c7..4070eff6f0f 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -315,10 +315,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
if (r1_bio->bios[mirror] == bio)
break;
- if (error == -ENOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) {
+ if (error == -EOPNOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) {
set_bit(BarriersNotsupp, &conf->mirrors[mirror].rdev->flags);
set_bit(R1BIO_BarrierRetry, &r1_bio->state);
r1_bio->mddev->barriers_work = 0;
+ /* Don't rdev_dec_pending in this branch - keep it for the retry */
} else {
/*
* this branch is our 'one mirror IO has finished' event handler:
@@ -365,6 +366,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
}
}
}
+ rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
}
/*
*
@@ -374,11 +376,9 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
if (atomic_dec_and_test(&r1_bio->remaining)) {
if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) {
reschedule_retry(r1_bio);
- /* Don't dec_pending yet, we want to hold
- * the reference over the retry
- */
goto out;
}
+ /* it really is the end of this request */
if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
/* free extra copy of the data pages */
int i = bio->bi_vcnt;
@@ -393,8 +393,6 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
md_write_end(r1_bio->mddev);
raid_end_bio_io(r1_bio);
}
-
- rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
out:
if (to_put)
bio_put(to_put);
@@ -753,18 +751,24 @@ static int make_request(request_queue_t *q, struct bio * bio)
const int rw = bio_data_dir(bio);
int do_barriers;
- if (unlikely(!mddev->barriers_work && bio_barrier(bio))) {
- bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
- return 0;
- }
-
/*
* Register the new request and wait if the reconstruction
* thread has put up a bar for new requests.
* Continue immediately if no resync is active currently.
+ * We test barriers_work *after* md_write_start as md_write_start
+ * may cause the first superblock write, and that will check out
+ * if barriers work.
*/
+
md_write_start(mddev, bio); /* wait on superblock update early */
+ if (unlikely(!mddev->barriers_work && bio_barrier(bio))) {
+ if (rw == WRITE)
+ md_write_end(mddev);
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
+
wait_barrier(conf);
disk_stat_inc(mddev->gendisk, ios[rw]);
@@ -1135,8 +1139,19 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
mirror = i;
break;
}
- if (!uptodate)
+ if (!uptodate) {
+ int sync_blocks = 0;
+ sector_t s = r1_bio->sector;
+ long sectors_to_go = r1_bio->sectors;
+ /* make sure these bits doesn't get cleared. */
+ do {
+ bitmap_end_sync(mddev->bitmap, r1_bio->sector,
+ &sync_blocks, 1);
+ s += sync_blocks;
+ sectors_to_go -= sync_blocks;
+ } while (sectors_to_go > 0);
md_error(mddev, conf->mirrors[mirror].rdev);
+ }
update_head_pos(mirror, r1_bio);
@@ -1393,15 +1408,19 @@ static void raid1d(mddev_t *mddev)
unplug = 1;
} else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) {
/* some requests in the r1bio were BIO_RW_BARRIER
- * requests which failed with -ENOTSUPP. Hohumm..
+ * requests which failed with -EOPNOTSUPP. Hohumm..
* Better resubmit without the barrier.
* We know which devices to resubmit for, because
* all others have had their bios[] entry cleared.
+ * We already have a nr_pending reference on these rdevs.
*/
int i;
clear_bit(R1BIO_BarrierRetry, &r1_bio->state);
clear_bit(R1BIO_Barrier, &r1_bio->state);
for (i=0; i < conf->raid_disks; i++)
+ if (r1_bio->bios[i])
+ atomic_inc(&r1_bio->remaining);
+ for (i=0; i < conf->raid_disks; i++)
if (r1_bio->bios[i]) {
struct bio_vec *bvec;
int j;
@@ -1544,8 +1563,7 @@ static int init_resync(conf_t *conf)
int buffs;
buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
- if (conf->r1buf_pool)
- BUG();
+ BUG_ON(conf->r1buf_pool);
conf->r1buf_pool = mempool_create(buffs, r1buf_pool_alloc, r1buf_pool_free,
conf->poolinfo);
if (!conf->r1buf_pool)
@@ -1718,8 +1736,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
!conf->fullsync &&
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
break;
- if (sync_blocks < (PAGE_SIZE>>9))
- BUG();
+ BUG_ON(sync_blocks < (PAGE_SIZE>>9));
if (len > (sync_blocks<<9))
len = sync_blocks<<9;
}
@@ -1789,6 +1806,11 @@ static int run(mddev_t *mddev)
mdname(mddev), mddev->level);
goto out;
}
+ if (mddev->reshape_position != MaxSector) {
+ printk("raid1: %s: reshape_position set but not supported\n",
+ mdname(mddev));
+ goto out;
+ }
/*
* copy the already verified devices into our private RAID1
* bookkeeping area. [whatever we allocate in run(),
@@ -1971,7 +1993,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
return 0;
}
-static int raid1_reshape(mddev_t *mddev, int raid_disks)
+static int raid1_reshape(mddev_t *mddev)
{
/* We need to:
* 1/ resize the r1bio_pool
@@ -1988,10 +2010,22 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
struct pool_info *newpoolinfo;
mirror_info_t *newmirrors;
conf_t *conf = mddev_to_conf(mddev);
- int cnt;
+ int cnt, raid_disks;
int d, d2;
+ /* Cannot change chunk_size, layout, or level */
+ if (mddev->chunk_size != mddev->new_chunk ||
+ mddev->layout != mddev->new_layout ||
+ mddev->level != mddev->new_level) {
+ mddev->new_chunk = mddev->chunk_size;
+ mddev->new_layout = mddev->layout;
+ mddev->new_level = mddev->level;
+ return -EINVAL;
+ }
+
+ raid_disks = mddev->raid_disks + mddev->delta_disks;
+
if (raid_disks < conf->raid_disks) {
cnt=0;
for (d= 0; d < conf->raid_disks; d++)
@@ -2038,6 +2072,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
mddev->degraded += (raid_disks - conf->raid_disks);
conf->raid_disks = mddev->raid_disks = raid_disks;
+ mddev->delta_disks = 0;
conf->last_used = 0; /* just make sure it is in-range */
lower_barrier(conf);
@@ -2079,7 +2114,7 @@ static struct mdk_personality raid1_personality =
.spare_active = raid1_spare_active,
.sync_request = sync_request,
.resize = raid1_resize,
- .reshape = raid1_reshape,
+ .check_reshape = raid1_reshape,
.quiesce = raid1_quiesce,
};
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index ab90a6d1202..1440935414e 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1117,8 +1117,7 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
for (i=0; i<conf->copies; i++)
if (r10_bio->devs[i].bio == bio)
break;
- if (i == conf->copies)
- BUG();
+ BUG_ON(i == conf->copies);
update_head_pos(i, r10_bio);
d = r10_bio->devs[i].devnum;
@@ -1408,43 +1407,54 @@ static void raid10d(mddev_t *mddev)
if (s > (PAGE_SIZE>>9))
s = PAGE_SIZE >> 9;
+ rcu_read_lock();
do {
int d = r10_bio->devs[sl].devnum;
- rdev = conf->mirrors[d].rdev;
+ rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev &&
- test_bit(In_sync, &rdev->flags) &&
- sync_page_io(rdev->bdev,
- r10_bio->devs[sl].addr +
- sect + rdev->data_offset,
- s<<9,
- conf->tmppage, READ))
- success = 1;
- else {
- sl++;
- if (sl == conf->copies)
- sl = 0;
+ test_bit(In_sync, &rdev->flags)) {
+ atomic_inc(&rdev->nr_pending);
+ rcu_read_unlock();
+ success = sync_page_io(rdev->bdev,
+ r10_bio->devs[sl].addr +
+ sect + rdev->data_offset,
+ s<<9,
+ conf->tmppage, READ);
+ rdev_dec_pending(rdev, mddev);
+ rcu_read_lock();
+ if (success)
+ break;
}
+ sl++;
+ if (sl == conf->copies)
+ sl = 0;
} while (!success && sl != r10_bio->read_slot);
+ rcu_read_unlock();
if (success) {
int start = sl;
/* write it back and re-read */
+ rcu_read_lock();
while (sl != r10_bio->read_slot) {
int d;
if (sl==0)
sl = conf->copies;
sl--;
d = r10_bio->devs[sl].devnum;
- rdev = conf->mirrors[d].rdev;
- atomic_add(s, &rdev->corrected_errors);
+ rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev &&
test_bit(In_sync, &rdev->flags)) {
+ atomic_inc(&rdev->nr_pending);
+ rcu_read_unlock();
+ atomic_add(s, &rdev->corrected_errors);
if (sync_page_io(rdev->bdev,
r10_bio->devs[sl].addr +
sect + rdev->data_offset,
s<<9, conf->tmppage, WRITE) == 0)
/* Well, this device is dead */
md_error(mddev, rdev);
+ rdev_dec_pending(rdev, mddev);
+ rcu_read_lock();
}
}
sl = start;
@@ -1454,17 +1464,22 @@ static void raid10d(mddev_t *mddev)
sl = conf->copies;
sl--;
d = r10_bio->devs[sl].devnum;
- rdev = conf->mirrors[d].rdev;
+ rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev &&
test_bit(In_sync, &rdev->flags)) {
+ atomic_inc(&rdev->nr_pending);
+ rcu_read_unlock();
if (sync_page_io(rdev->bdev,
r10_bio->devs[sl].addr +
sect + rdev->data_offset,
s<<9, conf->tmppage, READ) == 0)
/* Well, this device is dead */
md_error(mddev, rdev);
+ rdev_dec_pending(rdev, mddev);
+ rcu_read_lock();
}
}
+ rcu_read_unlock();
} else {
/* Cannot read from anywhere -- bye bye array */
md_error(mddev, conf->mirrors[r10_bio->devs[r10_bio->read_slot].devnum].rdev);
@@ -1518,8 +1533,7 @@ static int init_resync(conf_t *conf)
int buffs;
buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
- if (conf->r10buf_pool)
- BUG();
+ BUG_ON(conf->r10buf_pool);
conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf);
if (!conf->r10buf_pool)
return -ENOMEM;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 2dba305daf3..31843604049 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -22,6 +22,7 @@
#include <linux/raid/raid5.h>
#include <linux/highmem.h>
#include <linux/bitops.h>
+#include <linux/kthread.h>
#include <asm/atomic.h>
#include <linux/raid/bitmap.h>
@@ -72,10 +73,8 @@ static void print_raid5_conf (raid5_conf_t *conf);
static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
{
if (atomic_dec_and_test(&sh->count)) {
- if (!list_empty(&sh->lru))
- BUG();
- if (atomic_read(&conf->active_stripes)==0)
- BUG();
+ BUG_ON(!list_empty(&sh->lru));
+ BUG_ON(atomic_read(&conf->active_stripes)==0);
if (test_bit(STRIPE_HANDLE, &sh->state)) {
if (test_bit(STRIPE_DELAYED, &sh->state))
list_add_tail(&sh->lru, &conf->delayed_list);
@@ -93,11 +92,11 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
md_wakeup_thread(conf->mddev->thread);
}
- list_add_tail(&sh->lru, &conf->inactive_list);
atomic_dec(&conf->active_stripes);
- if (!conf->inactive_blocked ||
- atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4))
+ if (!test_bit(STRIPE_EXPANDING, &sh->state)) {
+ list_add_tail(&sh->lru, &conf->inactive_list);
wake_up(&conf->wait_for_stripe);
+ }
}
}
}
@@ -178,15 +177,13 @@ static int grow_buffers(struct stripe_head *sh, int num)
static void raid5_build_block (struct stripe_head *sh, int i);
-static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
+static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int disks)
{
raid5_conf_t *conf = sh->raid_conf;
- int disks = conf->raid_disks, i;
+ int i;
- if (atomic_read(&sh->count) != 0)
- BUG();
- if (test_bit(STRIPE_HANDLE, &sh->state))
- BUG();
+ BUG_ON(atomic_read(&sh->count) != 0);
+ BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
CHECK_DEVLOCK();
PRINTK("init_stripe called, stripe %llu\n",
@@ -198,7 +195,9 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
sh->pd_idx = pd_idx;
sh->state = 0;
- for (i=disks; i--; ) {
+ sh->disks = disks;
+
+ for (i = sh->disks; i--; ) {
struct r5dev *dev = &sh->dev[i];
if (dev->toread || dev->towrite || dev->written ||
@@ -215,7 +214,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
insert_hash(conf, sh);
}
-static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector)
+static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector, int disks)
{
struct stripe_head *sh;
struct hlist_node *hn;
@@ -223,7 +222,7 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector)
CHECK_DEVLOCK();
PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
- if (sh->sector == sector)
+ if (sh->sector == sector && sh->disks == disks)
return sh;
PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
return NULL;
@@ -232,8 +231,8 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector)
static void unplug_slaves(mddev_t *mddev);
static void raid5_unplug_device(request_queue_t *q);
-static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector,
- int pd_idx, int noblock)
+static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector, int disks,
+ int pd_idx, int noblock)
{
struct stripe_head *sh;
@@ -245,7 +244,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
wait_event_lock_irq(conf->wait_for_stripe,
conf->quiesce == 0,
conf->device_lock, /* nothing */);
- sh = __find_stripe(conf, sector);
+ sh = __find_stripe(conf, sector, disks);
if (!sh) {
if (!conf->inactive_blocked)
sh = get_free_stripe(conf);
@@ -259,21 +258,19 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
< (conf->max_nr_stripes *3/4)
|| !conf->inactive_blocked),
conf->device_lock,
- unplug_slaves(conf->mddev);
+ unplug_slaves(conf->mddev)
);
conf->inactive_blocked = 0;
} else
- init_stripe(sh, sector, pd_idx);
+ init_stripe(sh, sector, pd_idx, disks);
} else {
if (atomic_read(&sh->count)) {
- if (!list_empty(&sh->lru))
- BUG();
+ BUG_ON(!list_empty(&sh->lru));
} else {
if (!test_bit(STRIPE_HANDLE, &sh->state))
atomic_inc(&conf->active_stripes);
- if (list_empty(&sh->lru))
- BUG();
- list_del_init(&sh->lru);
+ if (!list_empty(&sh->lru))
+ list_del_init(&sh->lru);
}
}
} while (sh == NULL);
@@ -300,6 +297,7 @@ static int grow_one_stripe(raid5_conf_t *conf)
kmem_cache_free(conf->slab_cache, sh);
return 0;
}
+ sh->disks = conf->raid_disks;
/* we just created an active stripe so... */
atomic_set(&sh->count, 1);
atomic_inc(&conf->active_stripes);
@@ -313,14 +311,16 @@ static int grow_stripes(raid5_conf_t *conf, int num)
kmem_cache_t *sc;
int devs = conf->raid_disks;
- sprintf(conf->cache_name, "raid5/%s", mdname(conf->mddev));
-
- sc = kmem_cache_create(conf->cache_name,
+ sprintf(conf->cache_name[0], "raid5/%s", mdname(conf->mddev));
+ sprintf(conf->cache_name[1], "raid5/%s-alt", mdname(conf->mddev));
+ conf->active_name = 0;
+ sc = kmem_cache_create(conf->cache_name[conf->active_name],
sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
0, 0, NULL, NULL);
if (!sc)
return 1;
conf->slab_cache = sc;
+ conf->pool_size = devs;
while (num--) {
if (!grow_one_stripe(conf))
return 1;
@@ -328,6 +328,129 @@ static int grow_stripes(raid5_conf_t *conf, int num)
return 0;
}
+#ifdef CONFIG_MD_RAID5_RESHAPE
+static int resize_stripes(raid5_conf_t *conf, int newsize)
+{
+ /* Make all the stripes able to hold 'newsize' devices.
+ * New slots in each stripe get 'page' set to a new page.
+ *
+ * This happens in stages:
+ * 1/ create a new kmem_cache and allocate the required number of
+ * stripe_heads.
+ * 2/ gather all the old stripe_heads and tranfer the pages across
+ * to the new stripe_heads. This will have the side effect of
+ * freezing the array as once all stripe_heads have been collected,
+ * no IO will be possible. Old stripe heads are freed once their
+ * pages have been transferred over, and the old kmem_cache is
+ * freed when all stripes are done.
+ * 3/ reallocate conf->disks to be suitable bigger. If this fails,
+ * we simple return a failre status - no need to clean anything up.
+ * 4/ allocate new pages for the new slots in the new stripe_heads.
+ * If this fails, we don't bother trying the shrink the
+ * stripe_heads down again, we just leave them as they are.
+ * As each stripe_head is processed the new one is released into
+ * active service.
+ *
+ * Once step2 is started, we cannot afford to wait for a write,
+ * so we use GFP_NOIO allocations.
+ */
+ struct stripe_head *osh, *nsh;
+ LIST_HEAD(newstripes);
+ struct disk_info *ndisks;
+ int err = 0;
+ kmem_cache_t *sc;
+ int i;
+
+ if (newsize <= conf->pool_size)
+ return 0; /* never bother to shrink */
+
+ /* Step 1 */
+ sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
+ sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev),
+ 0, 0, NULL, NULL);
+ if (!sc)
+ return -ENOMEM;
+
+ for (i = conf->max_nr_stripes; i; i--) {
+ nsh = kmem_cache_alloc(sc, GFP_KERNEL);
+ if (!nsh)
+ break;
+
+ memset(nsh, 0, sizeof(*nsh) + (newsize-1)*sizeof(struct r5dev));
+
+ nsh->raid_conf = conf;
+ spin_lock_init(&nsh->lock);
+
+ list_add(&nsh->lru, &newstripes);
+ }
+ if (i) {
+ /* didn't get enough, give up */
+ while (!list_empty(&newstripes)) {
+ nsh = list_entry(newstripes.next, struct stripe_head, lru);
+ list_del(&nsh->lru);
+ kmem_cache_free(sc, nsh);
+ }
+ kmem_cache_destroy(sc);
+ return -ENOMEM;
+ }
+ /* Step 2 - Must use GFP_NOIO now.
+ * OK, we have enough stripes, start collecting inactive
+ * stripes and copying them over
+ */
+ list_for_each_entry(nsh, &newstripes, lru) {
+ spin_lock_irq(&conf->device_lock);
+ wait_event_lock_irq(conf->wait_for_stripe,
+ !list_empty(&conf->inactive_list),
+ conf->device_lock,
+ unplug_slaves(conf->mddev)
+ );
+ osh = get_free_stripe(conf);
+ spin_unlock_irq(&conf->device_lock);
+ atomic_set(&nsh->count, 1);
+ for(i=0; i<conf->pool_size; i++)
+ nsh->dev[i].page = osh->dev[i].page;
+ for( ; i<newsize; i++)
+ nsh->dev[i].page = NULL;
+ kmem_cache_free(conf->slab_cache, osh);
+ }
+ kmem_cache_destroy(conf->slab_cache);
+
+ /* Step 3.
+ * At this point, we are holding all the stripes so the array
+ * is completely stalled, so now is a good time to resize
+ * conf->disks.
+ */
+ ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO);
+ if (ndisks) {
+ for (i=0; i<conf->raid_disks; i++)
+ ndisks[i] = conf->disks[i];
+ kfree(conf->disks);
+ conf->disks = ndisks;
+ } else
+ err = -ENOMEM;
+
+ /* Step 4, return new stripes to service */
+ while(!list_empty(&newstripes)) {
+ nsh = list_entry(newstripes.next, struct stripe_head, lru);
+ list_del_init(&nsh->lru);
+ for (i=conf->raid_disks; i < newsize; i++)
+ if (nsh->dev[i].page == NULL) {
+ struct page *p = alloc_page(GFP_NOIO);
+ nsh->dev[i].page = p;
+ if (!p)
+ err = -ENOMEM;
+ }
+ release_stripe(nsh);
+ }
+ /* critical section pass, GFP_NOIO no longer needed */
+
+ conf->slab_cache = sc;
+ conf->active_name = 1-conf->active_name;
+ conf->pool_size = newsize;
+ return err;
+}
+#endif
+
static int drop_one_stripe(raid5_conf_t *conf)
{
struct stripe_head *sh;
@@ -337,9 +460,8 @@ static int drop_one_stripe(raid5_conf_t *conf)
spin_unlock_irq(&conf->device_lock);
if (!sh)
return 0;
- if (atomic_read(&sh->count))
- BUG();
- shrink_buffers(sh, conf->raid_disks);
+ BUG_ON(atomic_read(&sh->count));
+ shrink_buffers(sh, conf->pool_size);
kmem_cache_free(conf->slab_cache, sh);
atomic_dec(&conf->active_stripes);
return 1;
@@ -360,7 +482,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
{
struct stripe_head *sh = bi->bi_private;
raid5_conf_t *conf = sh->raid_conf;
- int disks = conf->raid_disks, i;
+ int disks = sh->disks, i;
int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
if (bi->bi_size)
@@ -458,7 +580,7 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
{
struct stripe_head *sh = bi->bi_private;
raid5_conf_t *conf = sh->raid_conf;
- int disks = conf->raid_disks, i;
+ int disks = sh->disks, i;
unsigned long flags;
int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -612,7 +734,7 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks,
static sector_t compute_blocknr(struct stripe_head *sh, int i)
{
raid5_conf_t *conf = sh->raid_conf;
- int raid_disks = conf->raid_disks, data_disks = raid_disks - 1;
+ int raid_disks = sh->disks, data_disks = raid_disks - 1;
sector_t new_sector = sh->sector, check;
int sectors_per_chunk = conf->chunk_size >> 9;
sector_t stripe;
@@ -713,8 +835,7 @@ static void copy_data(int frombio, struct bio *bio,
static void compute_block(struct stripe_head *sh, int dd_idx)
{
- raid5_conf_t *conf = sh->raid_conf;
- int i, count, disks = conf->raid_disks;
+ int i, count, disks = sh->disks;
void *ptr[MAX_XOR_BLOCKS], *p;
PRINTK("compute_block, stripe %llu, idx %d\n",
@@ -744,7 +865,7 @@ static void compute_block(struct stripe_head *sh, int dd_idx)
static void compute_parity(struct stripe_head *sh, int method)
{
raid5_conf_t *conf = sh->raid_conf;
- int i, pd_idx = sh->pd_idx, disks = conf->raid_disks, count;
+ int i, pd_idx = sh->pd_idx, disks = sh->disks, count;
void *ptr[MAX_XOR_BLOCKS];
struct bio *chosen;
@@ -755,8 +876,7 @@ static void compute_parity(struct stripe_head *sh, int method)
ptr[0] = page_address(sh->dev[pd_idx].page);
switch(method) {
case READ_MODIFY_WRITE:
- if (!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags))
- BUG();
+ BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags));
for (i=disks ; i-- ;) {
if (i==pd_idx)
continue;
@@ -769,7 +889,7 @@ static void compute_parity(struct stripe_head *sh, int method)
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
- if (sh->dev[i].written) BUG();
+ BUG_ON(sh->dev[i].written);
sh->dev[i].written = chosen;
check_xor();
}
@@ -785,7 +905,7 @@ static void compute_parity(struct stripe_head *sh, int method)
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
- if (sh->dev[i].written) BUG();
+ BUG_ON(sh->dev[i].written);
sh->dev[i].written = chosen;
}
break;
@@ -868,8 +988,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
goto overlap;
- if (*bip && bi->bi_next && (*bip) != bi->bi_next)
- BUG();
+ BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
if (*bip)
bi->bi_next = *bip;
*bip = bi;
@@ -910,6 +1029,20 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
return 0;
}
+static void end_reshape(raid5_conf_t *conf);
+
+static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks)
+{
+ int sectors_per_chunk = conf->chunk_size >> 9;
+ sector_t x = stripe;
+ int pd_idx, dd_idx;
+ int chunk_offset = sector_div(x, sectors_per_chunk);
+ stripe = x;
+ raid5_compute_sector(stripe*(disks-1)*sectors_per_chunk
+ + chunk_offset, disks, disks-1, &dd_idx, &pd_idx, conf);
+ return pd_idx;
+}
+
/*
* handle_stripe - do things to a stripe.
@@ -932,11 +1065,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
static void handle_stripe(struct stripe_head *sh)
{
raid5_conf_t *conf = sh->raid_conf;
- int disks = conf->raid_disks;
+ int disks = sh->disks;
struct bio *return_bi= NULL;
struct bio *bi;
int i;
- int syncing;
+ int syncing, expanding, expanded;
int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
int non_overwrite = 0;
int failed_num=0;
@@ -951,6 +1084,8 @@ static void handle_stripe(struct stripe_head *sh)
clear_bit(STRIPE_DELAYED, &sh->state);
syncing = test_bit(STRIPE_SYNCING, &sh->state);
+ expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+ expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
/* Now to look around and see what can be done */
rcu_read_lock();
@@ -1143,13 +1278,14 @@ static void handle_stripe(struct stripe_head *sh)
* parity, or to satisfy requests
* or to load a block that is being partially written.
*/
- if (to_read || non_overwrite || (syncing && (uptodate < disks))) {
+ if (to_read || non_overwrite || (syncing && (uptodate < disks)) || expanding) {
for (i=disks; i--;) {
dev = &sh->dev[i];
if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
(dev->toread ||
(dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
syncing ||
+ expanding ||
(failed && (sh->dev[failed_num].toread ||
(sh->dev[failed_num].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num].flags))))
)
@@ -1286,8 +1422,7 @@ static void handle_stripe(struct stripe_head *sh)
set_bit(STRIPE_HANDLE, &sh->state);
if (failed == 0) {
char *pagea;
- if (uptodate != disks)
- BUG();
+ BUG_ON(uptodate != disks);
compute_parity(sh, CHECK_PARITY);
uptodate--;
pagea = page_address(sh->dev[sh->pd_idx].page);
@@ -1339,13 +1474,77 @@ static void handle_stripe(struct stripe_head *sh)
set_bit(R5_Wantwrite, &dev->flags);
set_bit(R5_ReWrite, &dev->flags);
set_bit(R5_LOCKED, &dev->flags);
+ locked++;
} else {
/* let's read it back */
set_bit(R5_Wantread, &dev->flags);
set_bit(R5_LOCKED, &dev->flags);
+ locked++;
}
}
+ if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
+ /* Need to write out all blocks after computing parity */
+ sh->disks = conf->raid_disks;
+ sh->pd_idx = stripe_to_pdidx(sh->sector, conf, conf->raid_disks);
+ compute_parity(sh, RECONSTRUCT_WRITE);
+ for (i= conf->raid_disks; i--;) {
+ set_bit(R5_LOCKED, &sh->dev[i].flags);
+ locked++;
+ set_bit(R5_Wantwrite, &sh->dev[i].flags);
+ }
+ clear_bit(STRIPE_EXPANDING, &sh->state);
+ } else if (expanded) {
+ clear_bit(STRIPE_EXPAND_READY, &sh->state);
+ atomic_dec(&conf->reshape_stripes);
+ wake_up(&conf->wait_for_overlap);
+ md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
+ }
+
+ if (expanding && locked == 0) {
+ /* We have read all the blocks in this stripe and now we need to
+ * copy some of them into a target stripe for expand.
+ */
+ clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+ for (i=0; i< sh->disks; i++)
+ if (i != sh->pd_idx) {
+ int dd_idx, pd_idx, j;
+ struct stripe_head *sh2;
+
+ sector_t bn = compute_blocknr(sh, i);
+ sector_t s = raid5_compute_sector(bn, conf->raid_disks,
+ conf->raid_disks-1,
+ &dd_idx, &pd_idx, conf);
+ sh2 = get_active_stripe(conf, s, conf->raid_disks, pd_idx, 1);
+ if (sh2 == NULL)
+ /* so far only the early blocks of this stripe
+ * have been requested. When later blocks
+ * get requested, we will try again
+ */
+ continue;
+ if(!test_bit(STRIPE_EXPANDING, &sh2->state) ||
+ test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) {
+ /* must have already done this block */
+ release_stripe(sh2);
+ continue;
+ }
+ memcpy(page_address(sh2->dev[dd_idx].page),
+ page_address(sh->dev[i].page),
+ STRIPE_SIZE);
+ set_bit(R5_Expanded, &sh2->dev[dd_idx].flags);
+ set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags);
+ for (j=0; j<conf->raid_disks; j++)
+ if (j != sh2->pd_idx &&
+ !test_bit(R5_Expanded, &sh2->dev[j].flags))
+ break;
+ if (j == conf->raid_disks) {
+ set_bit(STRIPE_EXPAND_READY, &sh2->state);
+ set_bit(STRIPE_HANDLE, &sh2->state);
+ }
+ release_stripe(sh2);
+ }
+ }
+
spin_unlock(&sh->lock);
while ((bi=return_bi)) {
@@ -1384,7 +1583,7 @@ static void handle_stripe(struct stripe_head *sh)
rcu_read_unlock();
if (rdev) {
- if (syncing)
+ if (syncing || expanding || expanded)
md_sync_acct(rdev->bdev, STRIPE_SECTORS);
bi->bi_bdev = rdev->bdev;
@@ -1526,17 +1725,16 @@ static inline void raid5_plug_device(raid5_conf_t *conf)
spin_unlock_irq(&conf->device_lock);
}
-static int make_request (request_queue_t *q, struct bio * bi)
+static int make_request(request_queue_t *q, struct bio * bi)
{
mddev_t *mddev = q->queuedata;
raid5_conf_t *conf = mddev_to_conf(mddev);
- const unsigned int raid_disks = conf->raid_disks;
- const unsigned int data_disks = raid_disks - 1;
unsigned int dd_idx, pd_idx;
sector_t new_sector;
sector_t logical_sector, last_sector;
struct stripe_head *sh;
const int rw = bio_data_dir(bi);
+ int remaining;
if (unlikely(bio_barrier(bi))) {
bio_endio(bi, bi->bi_size, -EOPNOTSUPP);
@@ -1555,20 +1753,77 @@ static int make_request (request_queue_t *q, struct bio * bi)
for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
DEFINE_WAIT(w);
-
- new_sector = raid5_compute_sector(logical_sector,
- raid_disks, data_disks, &dd_idx, &pd_idx, conf);
+ int disks;
+ retry:
+ prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
+ if (likely(conf->expand_progress == MaxSector))
+ disks = conf->raid_disks;
+ else {
+ /* spinlock is needed as expand_progress may be
+ * 64bit on a 32bit platform, and so it might be
+ * possible to see a half-updated value
+ * Ofcourse expand_progress could change after
+ * the lock is dropped, so once we get a reference
+ * to the stripe that we think it is, we will have
+ * to check again.
+ */
+ spin_lock_irq(&conf->device_lock);
+ disks = conf->raid_disks;
+ if (logical_sector >= conf->expand_progress)
+ disks = conf->previous_raid_disks;
+ else {
+ if (logical_sector >= conf->expand_lo) {
+ spin_unlock_irq(&conf->device_lock);
+ schedule();
+ goto retry;
+ }
+ }
+ spin_unlock_irq(&conf->device_lock);
+ }
+ new_sector = raid5_compute_sector(logical_sector, disks, disks - 1,
+ &dd_idx, &pd_idx, conf);
PRINTK("raid5: make_request, sector %llu logical %llu\n",
(unsigned long long)new_sector,
(unsigned long long)logical_sector);
- retry:
- prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
- sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK));
+ sh = get_active_stripe(conf, new_sector, disks, pd_idx, (bi->bi_rw&RWA_MASK));
if (sh) {
- if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) {
- /* Add failed due to overlap. Flush everything
+ if (unlikely(conf->expand_progress != MaxSector)) {
+ /* expansion might have moved on while waiting for a
+ * stripe, so we must do the range check again.
+ * Expansion could still move past after this
+ * test, but as we are holding a reference to
+ * 'sh', we know that if that happens,
+ * STRIPE_EXPANDING will get set and the expansion
+ * won't proceed until we finish with the stripe.
+ */
+ int must_retry = 0;
+ spin_lock_irq(&conf->device_lock);
+ if (logical_sector < conf->expand_progress &&
+ disks == conf->previous_raid_disks)
+ /* mismatch, need to try again */
+ must_retry = 1;
+ spin_unlock_irq(&conf->device_lock);
+ if (must_retry) {
+ release_stripe(sh);
+ goto retry;
+ }
+ }
+ /* FIXME what if we get a false positive because these
+ * are being updated.
+ */
+ if (logical_sector >= mddev->suspend_lo &&
+ logical_sector < mddev->suspend_hi) {
+ release_stripe(sh);
+ schedule();
+ goto retry;
+ }
+
+ if (test_bit(STRIPE_EXPANDING, &sh->state) ||
+ !add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) {
+ /* Stripe is busy expanding or
+ * add failed due to overlap. Flush everything
* and wait a while
*/
raid5_unplug_device(mddev->queue);
@@ -1580,7 +1835,6 @@ static int make_request (request_queue_t *q, struct bio * bi)
raid5_plug_device(conf);
handle_stripe(sh);
release_stripe(sh);
-
} else {
/* cannot get stripe for read-ahead, just give-up */
clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -1590,7 +1844,9 @@ static int make_request (request_queue_t *q, struct bio * bi)
}
spin_lock_irq(&conf->device_lock);
- if (--bi->bi_phys_segments == 0) {
+ remaining = --bi->bi_phys_segments;
+ spin_unlock_irq(&conf->device_lock);
+ if (remaining == 0) {
int bytes = bi->bi_size;
if ( bio_data_dir(bi) == WRITE )
@@ -1598,7 +1854,6 @@ static int make_request (request_queue_t *q, struct bio * bi)
bi->bi_size = 0;
bi->bi_end_io(bi, bytes, 0);
}
- spin_unlock_irq(&conf->device_lock);
return 0;
}
@@ -1607,12 +1862,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
{
raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
struct stripe_head *sh;
- int sectors_per_chunk = conf->chunk_size >> 9;
- sector_t x;
- unsigned long stripe;
- int chunk_offset;
- int dd_idx, pd_idx;
- sector_t first_sector;
+ int pd_idx;
+ sector_t first_sector, last_sector;
int raid_disks = conf->raid_disks;
int data_disks = raid_disks-1;
sector_t max_sector = mddev->size << 1;
@@ -1621,6 +1872,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
if (sector_nr >= max_sector) {
/* just being told to finish up .. nothing much to do */
unplug_slaves(mddev);
+ if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) {
+ end_reshape(conf);
+ return 0;
+ }
if (mddev->curr_resync < max_sector) /* aborted */
bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
@@ -1631,6 +1886,123 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return 0;
}
+
+ if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) {
+ /* reshaping is quite different to recovery/resync so it is
+ * handled quite separately ... here.
+ *
+ * On each call to sync_request, we gather one chunk worth of
+ * destination stripes and flag them as expanding.
+ * Then we find all the source stripes and request reads.
+ * As the reads complete, handle_stripe will copy the data
+ * into the destination stripe and release that stripe.
+ */
+ int i;
+ int dd_idx;
+ sector_t writepos, safepos, gap;
+
+ if (sector_nr == 0 &&
+ conf->expand_progress != 0) {
+ /* restarting in the middle, skip the initial sectors */
+ sector_nr = conf->expand_progress;
+ sector_div(sector_nr, conf->raid_disks-1);
+ *skipped = 1;
+ return sector_nr;
+ }
+
+ /* we update the metadata when there is more than 3Meg
+ * in the block range (that is rather arbitrary, should
+ * probably be time based) or when the data about to be
+ * copied would over-write the source of the data at
+ * the front of the range.
+ * i.e. one new_stripe forward from expand_progress new_maps
+ * to after where expand_lo old_maps to
+ */
+ writepos = conf->expand_progress +
+ conf->chunk_size/512*(conf->raid_disks-1);
+ sector_div(writepos, conf->raid_disks-1);
+ safepos = conf->expand_lo;
+ sector_div(safepos, conf->previous_raid_disks-1);
+ gap = conf->expand_progress - conf->expand_lo;
+
+ if (writepos >= safepos ||
+ gap > (conf->raid_disks-1)*3000*2 /*3Meg*/) {
+ /* Cannot proceed until we've updated the superblock... */
+ wait_event(conf->wait_for_overlap,
+ atomic_read(&conf->reshape_stripes)==0);
+ mddev->reshape_position = conf->expand_progress;
+ mddev->sb_dirty = 1;
+ md_wakeup_thread(mddev->thread);
+ wait_event(mddev->sb_wait, mddev->sb_dirty == 0 ||
+ kthread_should_stop());
+ spin_lock_irq(&conf->device_lock);
+ conf->expand_lo = mddev->reshape_position;
+ spin_unlock_irq(&conf->device_lock);
+ wake_up(&conf->wait_for_overlap);
+ }
+
+ for (i=0; i < conf->chunk_size/512; i+= STRIPE_SECTORS) {
+ int j;
+ int skipped = 0;
+ pd_idx = stripe_to_pdidx(sector_nr+i, conf, conf->raid_disks);
+ sh = get_active_stripe(conf, sector_nr+i,
+ conf->raid_disks, pd_idx, 0);
+ set_bit(STRIPE_EXPANDING, &sh->state);
+ atomic_inc(&conf->reshape_stripes);
+ /* If any of this stripe is beyond the end of the old
+ * array, then we need to zero those blocks
+ */
+ for (j=sh->disks; j--;) {
+ sector_t s;
+ if (j == sh->pd_idx)
+ continue;
+ s = compute_blocknr(sh, j);
+ if (s < (mddev->array_size<<1)) {
+ skipped = 1;
+ continue;
+ }
+ memset(page_address(sh->dev[j].page), 0, STRIPE_SIZE);
+ set_bit(R5_Expanded, &sh->dev[j].flags);
+ set_bit(R5_UPTODATE, &sh->dev[j].flags);
+ }
+ if (!skipped) {
+ set_bit(STRIPE_EXPAND_READY, &sh->state);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ }
+ release_stripe(sh);
+ }
+ spin_lock_irq(&conf->device_lock);
+ conf->expand_progress = (sector_nr + i)*(conf->raid_disks-1);
+ spin_unlock_irq(&conf->device_lock);
+ /* Ok, those stripe are ready. We can start scheduling
+ * reads on the source stripes.
+ * The source stripes are determined by mapping the first and last
+ * block on the destination stripes.
+ */
+ raid_disks = conf->previous_raid_disks;
+ data_disks = raid_disks - 1;
+ first_sector =
+ raid5_compute_sector(sector_nr*(conf->raid_disks-1),
+ raid_disks, data_disks,
+ &dd_idx, &pd_idx, conf);
+ last_sector =
+ raid5_compute_sector((sector_nr+conf->chunk_size/512)
+ *(conf->raid_disks-1) -1,
+ raid_disks, data_disks,
+ &dd_idx, &pd_idx, conf);
+ if (last_sector >= (mddev->size<<1))
+ last_sector = (mddev->size<<1)-1;
+ while (first_sector <= last_sector) {
+ pd_idx = stripe_to_pdidx(first_sector, conf, conf->previous_raid_disks);
+ sh = get_active_stripe(conf, first_sector,
+ conf->previous_raid_disks, pd_idx, 0);
+ set_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ release_stripe(sh);
+ first_sector += STRIPE_SECTORS;
+ }
+ return conf->chunk_size>>9;
+ }
/* if there is 1 or more failed drives and we are trying
* to resync, then assert that we are finished, because there is
* nothing we can do.
@@ -1649,16 +2021,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
}
- x = sector_nr;
- chunk_offset = sector_div(x, sectors_per_chunk);
- stripe = x;
- BUG_ON(x != stripe);
-
- first_sector = raid5_compute_sector((sector_t)stripe*data_disks*sectors_per_chunk
- + chunk_offset, raid_disks, data_disks, &dd_idx, &pd_idx, conf);
- sh = get_active_stripe(conf, sector_nr, pd_idx, 1);
+ pd_idx = stripe_to_pdidx(sector_nr, conf, raid_disks);
+ sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1);
if (sh == NULL) {
- sh = get_active_stripe(conf, sector_nr, pd_idx, 0);
+ sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 0);
/* make sure we don't swamp the stripe cache if someone else
* is trying to get access
*/
@@ -1721,8 +2087,7 @@ static void raid5d (mddev_t *mddev)
list_del_init(first);
atomic_inc(&sh->count);
- if (atomic_read(&sh->count)!= 1)
- BUG();
+ BUG_ON(atomic_read(&sh->count)!= 1);
spin_unlock_irq(&conf->device_lock);
handled++;
@@ -1822,11 +2187,64 @@ static int run(mddev_t *mddev)
return -EIO;
}
- mddev->private = kzalloc(sizeof (raid5_conf_t)
- + mddev->raid_disks * sizeof(struct disk_info),
- GFP_KERNEL);
+ if (mddev->reshape_position != MaxSector) {
+ /* Check that we can continue the reshape.
+ * Currently only disks can change, it must
+ * increase, and we must be past the point where
+ * a stripe over-writes itself
+ */
+ sector_t here_new, here_old;
+ int old_disks;
+
+ if (mddev->new_level != mddev->level ||
+ mddev->new_layout != mddev->layout ||
+ mddev->new_chunk != mddev->chunk_size) {
+ printk(KERN_ERR "raid5: %s: unsupported reshape required - aborting.\n",
+ mdname(mddev));
+ return -EINVAL;
+ }
+ if (mddev->delta_disks <= 0) {
+ printk(KERN_ERR "raid5: %s: unsupported reshape (reduce disks) required - aborting.\n",
+ mdname(mddev));
+ return -EINVAL;
+ }
+ old_disks = mddev->raid_disks - mddev->delta_disks;
+ /* reshape_position must be on a new-stripe boundary, and one
+ * further up in new geometry must map after here in old geometry.
+ */
+ here_new = mddev->reshape_position;
+ if (sector_div(here_new, (mddev->chunk_size>>9)*(mddev->raid_disks-1))) {
+ printk(KERN_ERR "raid5: reshape_position not on a stripe boundary\n");
+ return -EINVAL;
+ }
+ /* here_new is the stripe we will write to */
+ here_old = mddev->reshape_position;
+ sector_div(here_old, (mddev->chunk_size>>9)*(old_disks-1));
+ /* here_old is the first stripe that we might need to read from */
+ if (here_new >= here_old) {
+ /* Reading from the same stripe as writing to - bad */
+ printk(KERN_ERR "raid5: reshape_position too early for auto-recovery - aborting.\n");
+ return -EINVAL;
+ }
+ printk(KERN_INFO "raid5: reshape will continue\n");
+ /* OK, we should be able to continue; */
+ }
+
+
+ mddev->private = kzalloc(sizeof (raid5_conf_t), GFP_KERNEL);
if ((conf = mddev->private) == NULL)
goto abort;
+ if (mddev->reshape_position == MaxSector) {
+ conf->previous_raid_disks = conf->raid_disks = mddev->raid_disks;
+ } else {
+ conf->raid_disks = mddev->raid_disks;
+ conf->previous_raid_disks = mddev->raid_disks - mddev->delta_disks;
+ }
+
+ conf->disks = kzalloc(conf->raid_disks * sizeof(struct disk_info),
+ GFP_KERNEL);
+ if (!conf->disks)
+ goto abort;
conf->mddev = mddev;
@@ -1847,7 +2265,7 @@ static int run(mddev_t *mddev)
ITERATE_RDEV(mddev,rdev,tmp) {
raid_disk = rdev->raid_disk;
- if (raid_disk >= mddev->raid_disks
+ if (raid_disk >= conf->raid_disks
|| raid_disk < 0)
continue;
disk = conf->disks + raid_disk;
@@ -1863,7 +2281,6 @@ static int run(mddev_t *mddev)
}
}
- conf->raid_disks = mddev->raid_disks;
/*
* 0 for a fully functional array, 1 for a degraded array.
*/
@@ -1873,6 +2290,7 @@ static int run(mddev_t *mddev)
conf->level = mddev->level;
conf->algorithm = mddev->layout;
conf->max_nr_stripes = NR_STRIPES;
+ conf->expand_progress = mddev->reshape_position;
/* device size must be a multiple of chunk size */
mddev->size &= ~(mddev->chunk_size/1024 -1);
@@ -1945,6 +2363,21 @@ static int run(mddev_t *mddev)
print_raid5_conf(conf);
+ if (conf->expand_progress != MaxSector) {
+ printk("...ok start reshape thread\n");
+ conf->expand_lo = conf->expand_progress;
+ atomic_set(&conf->reshape_stripes, 0);
+ clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+ clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+ set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+ set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+ mddev->sync_thread = md_register_thread(md_do_sync, mddev,
+ "%s_reshape");
+ /* FIXME if md_register_thread fails?? */
+ md_wakeup_thread(mddev->sync_thread);
+
+ }
+
/* read-ahead size must cover two whole stripes, which is
* 2 * (n-1) * chunksize where 'n' is the number of raid devices
*/
@@ -1960,12 +2393,13 @@ static int run(mddev_t *mddev)
mddev->queue->unplug_fn = raid5_unplug_device;
mddev->queue->issue_flush_fn = raid5_issue_flush;
+ mddev->array_size = mddev->size * (conf->previous_raid_disks - 1);
- mddev->array_size = mddev->size * (mddev->raid_disks - 1);
return 0;
abort:
if (conf) {
print_raid5_conf(conf);
+ kfree(conf->disks);
kfree(conf->stripe_hashtbl);
kfree(conf);
}
@@ -1986,6 +2420,7 @@ static int stop(mddev_t *mddev)
kfree(conf->stripe_hashtbl);
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
sysfs_remove_group(&mddev->kobj, &raid5_attrs_group);
+ kfree(conf->disks);
kfree(conf);
mddev->private = NULL;
return 0;
@@ -2001,7 +2436,7 @@ static void print_sh (struct stripe_head *sh)
printk("sh %llu, count %d.\n",
(unsigned long long)sh->sector, atomic_read(&sh->count));
printk("sh %llu, ", (unsigned long long)sh->sector);
- for (i = 0; i < sh->raid_conf->raid_disks; i++) {
+ for (i = 0; i < sh->disks; i++) {
printk("(cache%d: %p %ld) ",
i, sh->dev[i].page, sh->dev[i].flags);
}
@@ -2132,7 +2567,7 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
/*
* find the disk ...
*/
- for (disk=0; disk < mddev->raid_disks; disk++)
+ for (disk=0; disk < conf->raid_disks; disk++)
if ((p=conf->disks + disk)->rdev == NULL) {
clear_bit(In_sync, &rdev->flags);
rdev->raid_disk = disk;
@@ -2168,11 +2603,146 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
return 0;
}
+#ifdef CONFIG_MD_RAID5_RESHAPE
+static int raid5_check_reshape(mddev_t *mddev)
+{
+ raid5_conf_t *conf = mddev_to_conf(mddev);
+ int err;
+
+ if (mddev->delta_disks < 0 ||
+ mddev->new_level != mddev->level)
+ return -EINVAL; /* Cannot shrink array or change level yet */
+ if (mddev->delta_disks == 0)
+ return 0; /* nothing to do */
+
+ /* Can only proceed if there are plenty of stripe_heads.
+ * We need a minimum of one full stripe,, and for sensible progress
+ * it is best to have about 4 times that.
+ * If we require 4 times, then the default 256 4K stripe_heads will
+ * allow for chunk sizes up to 256K, which is probably OK.
+ * If the chunk size is greater, user-space should request more
+ * stripe_heads first.
+ */
+ if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes ||
+ (mddev->new_chunk / STRIPE_SIZE) * 4 > conf->max_nr_stripes) {
+ printk(KERN_WARNING "raid5: reshape: not enough stripes. Needed %lu\n",
+ (mddev->chunk_size / STRIPE_SIZE)*4);
+ return -ENOSPC;
+ }
+
+ err = resize_stripes(conf, conf->raid_disks + mddev->delta_disks);
+ if (err)
+ return err;
+
+ /* looks like we might be able to manage this */
+ return 0;
+}
+
+static int raid5_start_reshape(mddev_t *mddev)
+{
+ raid5_conf_t *conf = mddev_to_conf(mddev);
+ mdk_rdev_t *rdev;
+ struct list_head *rtmp;
+ int spares = 0;
+ int added_devices = 0;
+
+ if (mddev->degraded ||
+ test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+ return -EBUSY;
+
+ ITERATE_RDEV(mddev, rdev, rtmp)
+ if (rdev->raid_disk < 0 &&
+ !test_bit(Faulty, &rdev->flags))
+ spares++;
+
+ if (spares < mddev->delta_disks-1)
+ /* Not enough devices even to make a degraded array
+ * of that size
+ */
+ return -EINVAL;
+
+ atomic_set(&conf->reshape_stripes, 0);
+ spin_lock_irq(&conf->device_lock);
+ conf->previous_raid_disks = conf->raid_disks;
+ conf->raid_disks += mddev->delta_disks;
+ conf->expand_progress = 0;
+ conf->expand_lo = 0;
+ spin_unlock_irq(&conf->device_lock);
+
+ /* Add some new drives, as many as will fit.
+ * We know there are enough to make the newly sized array work.
+ */
+ ITERATE_RDEV(mddev, rdev, rtmp)
+ if (rdev->raid_disk < 0 &&
+ !test_bit(Faulty, &rdev->flags)) {
+ if (raid5_add_disk(mddev, rdev)) {
+ char nm[20];
+ set_bit(In_sync, &rdev->flags);
+ conf->working_disks++;
+ added_devices++;
+ sprintf(nm, "rd%d", rdev->raid_disk);
+ sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
+ } else
+ break;
+ }
+
+ mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices;
+ mddev->raid_disks = conf->raid_disks;
+ mddev->reshape_position = 0;
+ mddev->sb_dirty = 1;
+
+ clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+ clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+ set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+ set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+ mddev->sync_thread = md_register_thread(md_do_sync, mddev,
+ "%s_reshape");
+ if (!mddev->sync_thread) {
+ mddev->recovery = 0;
+ spin_lock_irq(&conf->device_lock);
+ mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks;
+ conf->expand_progress = MaxSector;
+ spin_unlock_irq(&conf->device_lock);
+ return -EAGAIN;
+ }
+ md_wakeup_thread(mddev->sync_thread);
+ md_new_event(mddev);
+ return 0;
+}
+#endif
+
+static void end_reshape(raid5_conf_t *conf)
+{
+ struct block_device *bdev;
+
+ if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
+ conf->mddev->array_size = conf->mddev->size * (conf->raid_disks-1);
+ set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1);
+ conf->mddev->changed = 1;
+
+ bdev = bdget_disk(conf->mddev->gendisk, 0);
+ if (bdev) {
+ mutex_lock(&bdev->bd_inode->i_mutex);
+ i_size_write(bdev->bd_inode, conf->mddev->array_size << 10);
+ mutex_unlock(&bdev->bd_inode->i_mutex);
+ bdput(bdev);
+ }
+ spin_lock_irq(&conf->device_lock);
+ conf->expand_progress = MaxSector;
+ spin_unlock_irq(&conf->device_lock);
+ conf->mddev->reshape_position = MaxSector;
+ }
+}
+
static void raid5_quiesce(mddev_t *mddev, int state)
{
raid5_conf_t *conf = mddev_to_conf(mddev);
switch(state) {
+ case 2: /* resume for a suspend */
+ wake_up(&conf->wait_for_overlap);
+ break;
+
case 1: /* stop all writes */
spin_lock_irq(&conf->device_lock);
conf->quiesce = 1;
@@ -2186,6 +2756,7 @@ static void raid5_quiesce(mddev_t *mddev, int state)
spin_lock_irq(&conf->device_lock);
conf->quiesce = 0;
wake_up(&conf->wait_for_stripe);
+ wake_up(&conf->wait_for_overlap);
spin_unlock_irq(&conf->device_lock);
break;
}
@@ -2206,6 +2777,10 @@ static struct mdk_personality raid5_personality =
.spare_active = raid5_spare_active,
.sync_request = sync_request,
.resize = raid5_resize,
+#ifdef CONFIG_MD_RAID5_RESHAPE
+ .check_reshape = raid5_check_reshape,
+ .start_reshape = raid5_start_reshape,
+#endif
.quiesce = raid5_quiesce,
};
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index cd477ebf2ee..bc69355e010 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -91,10 +91,8 @@ static void print_raid6_conf (raid6_conf_t *conf);
static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
{
if (atomic_dec_and_test(&sh->count)) {
- if (!list_empty(&sh->lru))
- BUG();
- if (atomic_read(&conf->active_stripes)==0)
- BUG();
+ BUG_ON(!list_empty(&sh->lru));
+ BUG_ON(atomic_read(&conf->active_stripes)==0);
if (test_bit(STRIPE_HANDLE, &sh->state)) {
if (test_bit(STRIPE_DELAYED, &sh->state))
list_add_tail(&sh->lru, &conf->delayed_list);
@@ -202,10 +200,8 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
raid6_conf_t *conf = sh->raid_conf;
int disks = conf->raid_disks, i;
- if (atomic_read(&sh->count) != 0)
- BUG();
- if (test_bit(STRIPE_HANDLE, &sh->state))
- BUG();
+ BUG_ON(atomic_read(&sh->count) != 0);
+ BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
CHECK_DEVLOCK();
PRINTK("init_stripe called, stripe %llu\n",
@@ -284,13 +280,11 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector
init_stripe(sh, sector, pd_idx);
} else {
if (atomic_read(&sh->count)) {
- if (!list_empty(&sh->lru))
- BUG();
+ BUG_ON(!list_empty(&sh->lru));
} else {
if (!test_bit(STRIPE_HANDLE, &sh->state))
atomic_inc(&conf->active_stripes);
- if (list_empty(&sh->lru))
- BUG();
+ BUG_ON(list_empty(&sh->lru));
list_del_init(&sh->lru);
}
}
@@ -331,9 +325,9 @@ static int grow_stripes(raid6_conf_t *conf, int num)
kmem_cache_t *sc;
int devs = conf->raid_disks;
- sprintf(conf->cache_name, "raid6/%s", mdname(conf->mddev));
+ sprintf(conf->cache_name[0], "raid6/%s", mdname(conf->mddev));
- sc = kmem_cache_create(conf->cache_name,
+ sc = kmem_cache_create(conf->cache_name[0],
sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
0, 0, NULL, NULL);
if (!sc)
@@ -353,8 +347,7 @@ static int drop_one_stripe(raid6_conf_t *conf)
spin_unlock_irq(&conf->device_lock);
if (!sh)
return 0;
- if (atomic_read(&sh->count))
- BUG();
+ BUG_ON(atomic_read(&sh->count));
shrink_buffers(sh, conf->raid_disks);
kmem_cache_free(conf->slab_cache, sh);
atomic_dec(&conf->active_stripes);
@@ -780,7 +773,7 @@ static void compute_parity(struct stripe_head *sh, int method)
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
- if (sh->dev[i].written) BUG();
+ BUG_ON(sh->dev[i].written);
sh->dev[i].written = chosen;
}
break;
@@ -970,8 +963,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
goto overlap;
- if (*bip && bi->bi_next && (*bip) != bi->bi_next)
- BUG();
+ BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
if (*bip)
bi->bi_next = *bip;
*bip = bi;
@@ -1906,8 +1898,7 @@ static void raid6d (mddev_t *mddev)
list_del_init(first);
atomic_inc(&sh->count);
- if (atomic_read(&sh->count)!= 1)
- BUG();
+ BUG_ON(atomic_read(&sh->count)!= 1);
spin_unlock_irq(&conf->device_lock);
handled++;
@@ -2006,11 +1997,14 @@ static int run(mddev_t *mddev)
return -EIO;
}
- mddev->private = kzalloc(sizeof (raid6_conf_t)
- + mddev->raid_disks * sizeof(struct disk_info),
- GFP_KERNEL);
+ mddev->private = kzalloc(sizeof (raid6_conf_t), GFP_KERNEL);
if ((conf = mddev->private) == NULL)
goto abort;
+ conf->disks = kzalloc(mddev->raid_disks * sizeof(struct disk_info),
+ GFP_KERNEL);
+ if (!conf->disks)
+ goto abort;
+
conf->mddev = mddev;
if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)
@@ -2148,6 +2142,8 @@ static int run(mddev_t *mddev)
}
/* Ok, everything is just fine now */
+ sysfs_create_group(&mddev->kobj, &raid6_attrs_group);
+
mddev->array_size = mddev->size * (mddev->raid_disks - 2);
mddev->queue->unplug_fn = raid6_unplug_device;
@@ -2158,6 +2154,7 @@ abort:
print_raid6_conf(conf);
safe_put_page(conf->spare_page);
kfree(conf->stripe_hashtbl);
+ kfree(conf->disks);
kfree(conf);
}
mddev->private = NULL;
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index baa9f58beff..344d83aae3e 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -8,22 +8,54 @@ config VIDEO_DEV
tristate "Video For Linux"
---help---
Support for audio/video capture and overlay devices and FM radio
- cards. The exact capabilities of each device vary. User tools for
- this are available from
- <ftp://ftp.uk.linux.org/pub/linux/video4linux/>.
+ cards. The exact capabilities of each device vary.
This kernel includes support for the new Video for Linux Two API,
(V4L2) as well as the original system. Drivers and applications
need to be rewritten to use V4L2, but drivers for popular cards
and applications for most video capture functions already exist.
- Documentation for the original API is included in the file
- <file:Documentation/video4linux/API.html>. Documentation for V4L2 is
- available on the web at <http://bytesex.org/v4l/>.
+ Additional info and docs are available on the web at
+ <http://linuxtv.org>
+
+ Documentation for V4L2 is also available on the web at
+ <http://bytesex.org/v4l/>.
To compile this driver as a module, choose M here: the
module will be called videodev.
+config VIDEO_V4L1
+ boolean "Enable Video For Linux API 1 (DEPRECATED)"
+ depends on VIDEO_DEV
+ select VIDEO_V4L1_COMPAT
+ default y
+ ---help---
+ Enables a compatibility API used by most V4L2 devices to allow
+ its usage with legacy applications that supports only V4L1 api.
+
+ If you are unsure as to whether this is required, answer Y.
+
+config VIDEO_V4L1_COMPAT
+ boolean "Enable Video For Linux API 1 compatible Layer"
+ depends on VIDEO_DEV
+ default y
+ ---help---
+ This api were developed to be used at Kernel 2.2 and 2.4, but
+ lacks support for several video standards. There are several
+ drivers at kernel that still depends on it.
+
+ Documentation for the original API is included in the file
+ <Documentation/video4linux/API.html>.
+
+ User tools for this are available from
+ <ftp://ftp.uk.linux.org/pub/linux/video4linux/>.
+
+ If you are unsure as to whether this is required, answer Y.
+
+config VIDEO_V4L2
+ tristate
+ default y
+
source "drivers/media/video/Kconfig"
source "drivers/media/radio/Kconfig"
@@ -51,18 +83,17 @@ config VIDEO_TVEEPROM
tristate
config USB_DABUSB
- tristate "DABUSB driver"
- depends on USB
- ---help---
- A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
- brought to you by the DAB-Team
- <http://wwwbode.cs.tum.edu/Par/arch/dab/>. This driver can be taken
- as an example for URB-based bulk, control, and isochronous
- transactions. URB's are explained in
- <Documentation/usb/URB.txt>.
-
- To compile this driver as a module, choose M here: the
- module will be called dabusb.
+ tristate "DABUSB driver"
+ depends on USB
+ ---help---
+ A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
+ brought to you by the DAB-Team
+ <http://wwwbode.cs.tum.edu/Par/arch/dab/>. This driver can be taken
+ as an example for URB-based bulk, control, and isochronous
+ transactions. URB's are explained in
+ <Documentation/usb/URB.txt>.
-endmenu
+ To compile this driver as a module, choose M here: the
+ module will be called dabusb.
+endmenu
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
index 6a901a0268e..1a04db4552d 100644
--- a/drivers/media/common/Kconfig
+++ b/drivers/media/common/Kconfig
@@ -1,9 +1,10 @@
config VIDEO_SAA7146
tristate
- select I2C
+ depends on I2C
config VIDEO_SAA7146_VV
tristate
+ select VIDEO_V4L2
select VIDEO_BUF
select VIDEO_VIDEOBUF
select VIDEO_SAA7146
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 3f0ec6be03a..a97c8f5e9a5 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -22,26 +22,26 @@ config DVB
source "drivers/media/dvb/dvb-core/Kconfig"
comment "Supported SAA7146 based PCI Adapters"
- depends on DVB_CORE && PCI
+ depends on DVB_CORE && PCI && I2C
source "drivers/media/dvb/ttpci/Kconfig"
comment "Supported USB Adapters"
- depends on DVB_CORE && USB
+ depends on DVB_CORE && USB && I2C
source "drivers/media/dvb/dvb-usb/Kconfig"
source "drivers/media/dvb/ttusb-budget/Kconfig"
source "drivers/media/dvb/ttusb-dec/Kconfig"
source "drivers/media/dvb/cinergyT2/Kconfig"
comment "Supported FlexCopII (B2C2) Adapters"
- depends on DVB_CORE && (PCI || USB)
+ depends on DVB_CORE && (PCI || USB) && I2C
source "drivers/media/dvb/b2c2/Kconfig"
comment "Supported BT878 Adapters"
- depends on DVB_CORE && PCI
+ depends on DVB_CORE && PCI && I2C
source "drivers/media/dvb/bt8xx/Kconfig"
comment "Supported Pluto2 Adapters"
- depends on DVB_CORE && PCI
+ depends on DVB_CORE && PCI && I2C
source "drivers/media/dvb/pluto2/Kconfig"
comment "Supported DVB Frontends"
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index 2963605c0ec..d7f1fd5b7b0 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -1,6 +1,6 @@
config DVB_B2C2_FLEXCOP
tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters"
- depends on DVB_CORE
+ depends on DVB_CORE && I2C
select DVB_STV0299
select DVB_MT352
select DVB_MT312
@@ -16,7 +16,7 @@ config DVB_B2C2_FLEXCOP
config DVB_B2C2_FLEXCOP_PCI
tristate "Technisat/B2C2 Air/Sky/Cable2PC PCI"
- depends on DVB_B2C2_FLEXCOP && PCI
+ depends on DVB_B2C2_FLEXCOP && PCI && I2C
help
Support for the Air/Sky/CableStar2 PCI card (DVB/ATSC) by Technisat/B2C2.
@@ -24,7 +24,7 @@ config DVB_B2C2_FLEXCOP_PCI
config DVB_B2C2_FLEXCOP_USB
tristate "Technisat/B2C2 Air/Sky/Cable2PC USB"
- depends on DVB_B2C2_FLEXCOP && USB
+ depends on DVB_B2C2_FLEXCOP && USB && I2C
help
Support for the Air/Sky/Cable2PC USB1.1 box (DVB/ATSC) by Technisat/B2C2,
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index 2337b41714e..f394002118f 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -1,12 +1,14 @@
config DVB_BT8XX
tristate "BT8xx based PCI cards"
- depends on DVB_CORE && PCI && VIDEO_BT848
+ depends on DVB_CORE && PCI && I2C && VIDEO_BT848
select DVB_MT352
select DVB_SP887X
select DVB_NXT6000
select DVB_CX24110
select DVB_OR51211
select DVB_LGDT330X
+ select DVB_ZL10353
+ select FW_LOADER
help
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index baa8227ef87..ccc7b2eb4a2 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -115,7 +115,7 @@ static int is_pci_slot_eq(struct pci_dev* adev, struct pci_dev* bdev)
return 0;
}
-static struct bt878 __init *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci_dev* bttv_pci_dev)
+static struct bt878 __devinit *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci_dev* bttv_pci_dev)
{
unsigned int card_nr;
@@ -709,7 +709,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
}
}
-static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
+static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
{
int result;
@@ -794,7 +794,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
return 0;
}
-static int dvb_bt8xx_probe(struct bttv_sub_device *sub)
+static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
{
struct dvb_bt8xx_card *card;
struct pci_dev* bttv_pci_dev;
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 71b575dc22b..9325d039ea6 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -902,7 +902,10 @@ static int cinergyt2_probe (struct usb_interface *intf,
return -ENOMEM;
}
- dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE);
+ if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE)) < 0) {
+ kfree(cinergyt2);
+ return err;
+ }
cinergyt2->demux.priv = cinergyt2;
cinergyt2->demux.filternum = 256;
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 09e96e9ddbd..04578df3f24 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -141,12 +141,18 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
}
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
- void *mem = vmalloc(DVR_BUFFER_SIZE);
+ void *mem;
+ if (!dvbdev->readers) {
+ mutex_unlock(&dmxdev->mutex);
+ return -EBUSY;
+ }
+ mem = vmalloc(DVR_BUFFER_SIZE);
if (!mem) {
mutex_unlock(&dmxdev->mutex);
return -ENOMEM;
}
dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
+ dvbdev->readers--;
}
if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
@@ -184,6 +190,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
dmxdev->dvr_orig_fe);
}
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+ dvbdev->readers++;
if (dmxdev->dvr_buffer.data) {
void *mem = dmxdev->dvr_buffer.data;
mb();
@@ -1029,8 +1036,7 @@ static struct file_operations dvb_dvr_fops = {
static struct dvb_device dvbdev_dvr = {
.priv = NULL,
- .users = 1,
- .writers = 1,
+ .readers = 1,
.fops = &dvb_dvr_fops
};
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 2c3ea8f95dc..a051790161b 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -105,6 +105,9 @@ struct dvb_frontend_private {
fe_status_t status;
unsigned long tune_mode_flags;
unsigned int delay;
+ unsigned int reinitialise;
+ int tone;
+ int voltage;
/* swzigzag values */
unsigned int state;
@@ -121,6 +124,7 @@ struct dvb_frontend_private {
unsigned int check_wrapped;
};
+static void dvb_frontend_wakeup(struct dvb_frontend *fe);
static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
{
@@ -213,6 +217,15 @@ static void dvb_frontend_init(struct dvb_frontend *fe)
fe->ops->init(fe);
}
+void dvb_frontend_reinitialise(struct dvb_frontend *fe)
+{
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+ fepriv->reinitialise = 1;
+ dvb_frontend_wakeup(fe);
+}
+EXPORT_SYMBOL(dvb_frontend_reinitialise);
+
static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
{
int q2;
@@ -505,8 +518,8 @@ static int dvb_frontend_thread(void *data)
fepriv->quality = 0;
fepriv->delay = 3*HZ;
fepriv->status = 0;
- dvb_frontend_init(fe);
fepriv->wakeup = 0;
+ fepriv->reinitialise = 1;
while (1) {
up(&fepriv->sem); /* is locked when we enter the thread... */
@@ -524,6 +537,17 @@ static int dvb_frontend_thread(void *data)
if (down_interruptible(&fepriv->sem))
break;
+ if (fepriv->reinitialise) {
+ dvb_frontend_init(fe);
+ if (fepriv->tone != -1) {
+ fe->ops->set_tone(fe, fepriv->tone);
+ }
+ if (fepriv->voltage != -1) {
+ fe->ops->set_voltage(fe, fepriv->voltage);
+ }
+ fepriv->reinitialise = 0;
+ }
+
/* do an iteration of the tuning loop */
if (fe->ops->tune) {
/* have we been asked to retune? */
@@ -772,6 +796,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_SET_TONE:
if (fe->ops->set_tone) {
err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
+ fepriv->tone = (fe_sec_tone_mode_t) parg;
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
}
@@ -780,6 +805,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_SET_VOLTAGE:
if (fe->ops->set_voltage) {
err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg);
+ fepriv->voltage = (fe_sec_voltage_t) parg;
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
}
@@ -979,6 +1005,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
/* normal tune mode when opened R/W */
fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
+ fepriv->tone = -1;
+ fepriv->voltage = -1;
}
return ret;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index d5aee5ad67a..5926a3b745c 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -112,6 +112,8 @@ extern int dvb_register_frontend(struct dvb_adapter* dvb,
extern int dvb_unregister_frontend(struct dvb_frontend* fe);
+extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
+
extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 54f8b95717b..3852430d026 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -86,7 +86,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
if (dvbdev && dvbdev->fops) {
int err = 0;
- struct file_operations *old_fops;
+ const struct file_operations *old_fops;
file->private_data = dvbdev;
old_fops = file->f_op;
@@ -219,8 +219,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
return -ENOMEM;
}
- mutex_unlock(&dvbdev_register_lock);
-
memcpy(dvbdev, template, sizeof(struct dvb_device));
dvbdev->type = type;
dvbdev->id = id;
@@ -231,6 +229,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
list_add_tail (&dvbdev->list_head, &adap->device_list);
+ mutex_unlock(&dvbdev_register_lock);
+
devfs_mk_cdev(MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
S_IFCHR | S_IRUSR | S_IWUSR,
"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index d3df12039b0..e388fb1567d 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -1,6 +1,6 @@
config DVB_USB
tristate "Support for various USB DVB devices"
- depends on DVB_CORE && USB
+ depends on DVB_CORE && USB && I2C
select FW_LOADER
help
By enabling this you will be able to choose the various supported
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index a14e737ec84..1f0d3e995c8 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -150,6 +150,15 @@ static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff)
return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0);
}
+static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ u8 b = 0;
+ if (onoff)
+ return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0);
+ else
+ return 0;
+}
+
static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
{
u8 buf[2] = { 0x03, 0x00 };
@@ -233,6 +242,45 @@ static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
{ 0xfe, 0x4e, KEY_POWER },
};
+static struct dvb_usb_rc_key dvico_portable_rc_keys[] = {
+ { 0xfc, 0x02, KEY_SETUP }, /* Profile */
+ { 0xfc, 0x43, KEY_POWER2 },
+ { 0xfc, 0x06, KEY_EPG },
+ { 0xfc, 0x5a, KEY_BACK },
+ { 0xfc, 0x05, KEY_MENU },
+ { 0xfc, 0x47, KEY_INFO },
+ { 0xfc, 0x01, KEY_TAB },
+ { 0xfc, 0x42, KEY_PREVIOUSSONG },/* Replay */
+ { 0xfc, 0x49, KEY_VOLUMEUP },
+ { 0xfc, 0x09, KEY_VOLUMEDOWN },
+ { 0xfc, 0x54, KEY_CHANNELUP },
+ { 0xfc, 0x0b, KEY_CHANNELDOWN },
+ { 0xfc, 0x16, KEY_CAMERA },
+ { 0xfc, 0x40, KEY_TUNER }, /* ATV/DTV */
+ { 0xfc, 0x45, KEY_OPEN },
+ { 0xfc, 0x19, KEY_1 },
+ { 0xfc, 0x18, KEY_2 },
+ { 0xfc, 0x1b, KEY_3 },
+ { 0xfc, 0x1a, KEY_4 },
+ { 0xfc, 0x58, KEY_5 },
+ { 0xfc, 0x59, KEY_6 },
+ { 0xfc, 0x15, KEY_7 },
+ { 0xfc, 0x14, KEY_8 },
+ { 0xfc, 0x17, KEY_9 },
+ { 0xfc, 0x44, KEY_ANGLE }, /* Aspect */
+ { 0xfc, 0x55, KEY_0 },
+ { 0xfc, 0x07, KEY_ZOOM },
+ { 0xfc, 0x0a, KEY_REWIND },
+ { 0xfc, 0x08, KEY_PLAYPAUSE },
+ { 0xfc, 0x4b, KEY_FASTFORWARD },
+ { 0xfc, 0x5b, KEY_MUTE },
+ { 0xfc, 0x04, KEY_STOP },
+ { 0xfc, 0x56, KEY_RECORD },
+ { 0xfc, 0x57, KEY_POWER },
+ { 0xfc, 0x41, KEY_UNKNOWN }, /* INPUT */
+ { 0xfc, 0x00, KEY_UNKNOWN }, /* HD */
+};
+
static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
{
static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 };
@@ -505,12 +553,17 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
.size_of_priv = sizeof(struct cxusb_state),
.streaming_ctrl = cxusb_streaming_ctrl,
- .power_ctrl = cxusb_power_ctrl,
+ .power_ctrl = cxusb_bluebird_power_ctrl,
.frontend_attach = cxusb_lgdt3303_frontend_attach,
.tuner_attach = cxusb_lgh064f_tuner_attach,
.i2c_algo = &cxusb_i2c_algo,
+ .rc_interval = 100,
+ .rc_key_map = dvico_portable_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys),
+ .rc_query = cxusb_rc_query,
+
.generic_bulk_ctrl_endpoint = 0x01,
/* parameter for the MPEG2-data transfer */
.urb = {
@@ -545,7 +598,7 @@ static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = {
.size_of_priv = sizeof(struct cxusb_state),
.streaming_ctrl = cxusb_streaming_ctrl,
- .power_ctrl = cxusb_power_ctrl,
+ .power_ctrl = cxusb_bluebird_power_ctrl,
.frontend_attach = cxusb_dee1601_frontend_attach,
.tuner_attach = cxusb_dee1601_tuner_attach,
@@ -594,12 +647,17 @@ static struct dvb_usb_properties cxusb_bluebird_lgz201_properties = {
.size_of_priv = sizeof(struct cxusb_state),
.streaming_ctrl = cxusb_streaming_ctrl,
- .power_ctrl = cxusb_power_ctrl,
+ .power_ctrl = cxusb_bluebird_power_ctrl,
.frontend_attach = cxusb_mt352_frontend_attach,
.tuner_attach = cxusb_lgz201_tuner_attach,
.i2c_algo = &cxusb_i2c_algo,
+ .rc_interval = 100,
+ .rc_key_map = dvico_portable_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys),
+ .rc_query = cxusb_rc_query,
+
.generic_bulk_ctrl_endpoint = 0x01,
/* parameter for the MPEG2-data transfer */
.urb = {
@@ -634,12 +692,17 @@ static struct dvb_usb_properties cxusb_bluebird_dtt7579_properties = {
.size_of_priv = sizeof(struct cxusb_state),
.streaming_ctrl = cxusb_streaming_ctrl,
- .power_ctrl = cxusb_power_ctrl,
+ .power_ctrl = cxusb_bluebird_power_ctrl,
.frontend_attach = cxusb_mt352_frontend_attach,
.tuner_attach = cxusb_dtt7579_tuner_attach,
.i2c_algo = &cxusb_i2c_algo,
+ .rc_interval = 100,
+ .rc_key_map = dvico_portable_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys),
+ .rc_query = cxusb_rc_query,
+
.generic_bulk_ctrl_endpoint = 0x01,
/* parameter for the MPEG2-data transfer */
.urb = {
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 12ebaf8bddc..70afcfd141c 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -94,12 +94,14 @@ static int dtt200u_frontend_attach(struct dvb_usb_device *d)
static struct dvb_usb_properties dtt200u_properties;
static struct dvb_usb_properties wt220u_properties;
+static struct dvb_usb_properties wt220u_zl0353_properties;
static int dtt200u_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
- dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0)
+ dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0)
return 0;
return -ENODEV;
@@ -110,6 +112,8 @@ static struct usb_device_id dtt200u_usb_table [] = {
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) },
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD) },
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM) },
+ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_COLD) },
+ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_WARM) },
{ 0 },
};
MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
@@ -196,6 +200,47 @@ static struct dvb_usb_properties wt220u_properties = {
}
};
+static struct dvb_usb_properties wt220u_zl0353_properties = {
+ .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
+ .pid_filter_count = 15,
+
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-wt220u-zl0353-01.fw",
+
+ .power_ctrl = dtt200u_power_ctrl,
+ .streaming_ctrl = dtt200u_streaming_ctrl,
+ .pid_filter = dtt200u_pid_filter,
+ .frontend_attach = dtt200u_frontend_attach,
+
+ .rc_interval = 300,
+ .rc_key_map = dtt200u_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
+ .rc_query = dtt200u_rc_query,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { .name = "WideView WT-220U PenType Receiver (based on ZL353)",
+ .cold_ids = { &dtt200u_usb_table[4], NULL },
+ .warm_ids = { &dtt200u_usb_table[5], NULL },
+ },
+ { NULL },
+ }
+};
+
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver dtt200u_usb_driver = {
.name = "dvb_usb_dtt200u",
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 4a1b9e77e33..cb239049b09 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -83,6 +83,8 @@
#define USB_PID_DTT200U_WARM 0x0301
#define USB_PID_WT220U_COLD 0x0222
#define USB_PID_WT220U_WARM 0x0221
+#define USB_PID_WT220U_ZL0353_COLD 0x022a
+#define USB_PID_WT220U_ZL0353_WARM 0x022b
#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
#define USB_PID_NEBULA_DIGITV 0x0201
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
index b6d95e1c9c5..2a89f8c5da9 100644
--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -147,8 +147,9 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
cmd[4] = (sr >> 4) & 0xff;
cmd[5] = (sr << 4) & 0xf0;
- deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %Lu (%Lx)\n",
- fep->frequency,freq,freq, fep->u.qpsk.symbol_rate, sr, sr);
+ deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %lu (%lx)\n",
+ fep->frequency,freq,freq, fep->u.qpsk.symbol_rate,
+ (unsigned long) sr, (unsigned long) sr);
/* if (fep->inversion == INVERSION_ON)
cmd[6] |= 0x80; */
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 94233168d24..37d5e0af168 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -181,6 +181,11 @@ config DVB_OR51211
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
+ This driver needs external firmware. Please use the command
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
+ download it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
+
config DVB_OR51132
tristate "Oren OR51132 based"
depends on DVB_CORE
@@ -189,6 +194,13 @@ config DVB_OR51132
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
+ This driver needs external firmware. Please use the commands
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_vsb" and/or
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_qam" to
+ download firmwares for 8VSB and QAM64/256, respectively. Copy them to
+ /usr/lib/hotplug/firmware or /lib/firmware (depending on
+ configuration of firmware hotplug).
+
config DVB_BCM3510
tristate "Broadcom BCM3510"
depends on DVB_CORE
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
index d661c6f9cbe..691dc840dcc 100644
--- a/drivers/media/dvb/frontends/cx24123.c
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -29,6 +29,9 @@
#include "dvb_frontend.h"
#include "cx24123.h"
+#define XTAL 10111000
+
+static int force_band;
static int debug;
#define dprintk(args...) \
do { \
@@ -52,6 +55,7 @@ struct cx24123_state
u32 VGAarg;
u32 bandselectarg;
u32 pllarg;
+ u32 FILTune;
/* The Demod/Tuner can't easily provide these, we cache them */
u32 currentfreq;
@@ -63,43 +67,33 @@ static struct
{
u32 symbolrate_low;
u32 symbolrate_high;
- u32 VCAslope;
- u32 VCAoffset;
- u32 VGA1offset;
- u32 VGA2offset;
u32 VCAprogdata;
u32 VGAprogdata;
+ u32 FILTune;
} cx24123_AGC_vals[] =
{
{
.symbolrate_low = 1000000,
.symbolrate_high = 4999999,
- .VCAslope = 0x07,
- .VCAoffset = 0x0f,
- .VGA1offset = 0x1f8,
- .VGA2offset = 0x1f8,
- .VGAprogdata = (2 << 18) | (0x1f8 << 9) | 0x1f8,
- .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07,
+ /* the specs recommend other values for VGA offsets,
+ but tests show they are wrong */
+ .VGAprogdata = (1 << 19) | (0x180 << 9) | 0x1e0,
+ .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x07,
+ .FILTune = 0x27f /* 0.41 V */
},
{
.symbolrate_low = 5000000,
.symbolrate_high = 14999999,
- .VCAslope = 0x1f,
- .VCAoffset = 0x1f,
- .VGA1offset = 0x1e0,
- .VGA2offset = 0x180,
- .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0,
- .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f,
+ .VGAprogdata = (1 << 19) | (0x180 << 9) | 0x1e0,
+ .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x1f,
+ .FILTune = 0x317 /* 0.90 V */
},
{
.symbolrate_low = 15000000,
.symbolrate_high = 45000000,
- .VCAslope = 0x3f,
- .VCAoffset = 0x3f,
- .VGA1offset = 0x180,
- .VGA2offset = 0x100,
- .VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180,
- .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f,
+ .VGAprogdata = (1 << 19) | (0x100 << 9) | 0x180,
+ .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x3f,
+ .FILTune = 0x145 /* 2.70 V */
},
};
@@ -112,91 +106,80 @@ static struct
{
u32 freq_low;
u32 freq_high;
- u32 bandselect;
u32 VCOdivider;
- u32 VCOnumber;
u32 progdata;
} cx24123_bandselect_vals[] =
{
+ /* band 1 */
{
.freq_low = 950000,
- .freq_high = 1018999,
- .bandselect = 0x40,
- .VCOdivider = 4,
- .VCOnumber = 7,
- .progdata = (0 << 18) | (0 << 9) | 0x40,
- },
- {
- .freq_low = 1019000,
.freq_high = 1074999,
- .bandselect = 0x80,
.VCOdivider = 4,
- .VCOnumber = 8,
- .progdata = (0 << 18) | (0 << 9) | 0x80,
+ .progdata = (0 << 19) | (0 << 9) | 0x40,
},
+
+ /* band 2 */
{
.freq_low = 1075000,
- .freq_high = 1227999,
- .bandselect = 0x01,
- .VCOdivider = 2,
- .VCOnumber = 1,
- .progdata = (0 << 18) | (1 << 9) | 0x01,
+ .freq_high = 1177999,
+ .VCOdivider = 4,
+ .progdata = (0 << 19) | (0 << 9) | 0x80,
},
+
+ /* band 3 */
{
- .freq_low = 1228000,
- .freq_high = 1349999,
- .bandselect = 0x02,
+ .freq_low = 1178000,
+ .freq_high = 1295999,
.VCOdivider = 2,
- .VCOnumber = 2,
- .progdata = (0 << 18) | (1 << 9) | 0x02,
+ .progdata = (0 << 19) | (1 << 9) | 0x01,
},
+
+ /* band 4 */
{
- .freq_low = 1350000,
- .freq_high = 1481999,
- .bandselect = 0x04,
+ .freq_low = 1296000,
+ .freq_high = 1431999,
.VCOdivider = 2,
- .VCOnumber = 3,
- .progdata = (0 << 18) | (1 << 9) | 0x04,
+ .progdata = (0 << 19) | (1 << 9) | 0x02,
},
+
+ /* band 5 */
{
- .freq_low = 1482000,
- .freq_high = 1595999,
- .bandselect = 0x08,
+ .freq_low = 1432000,
+ .freq_high = 1575999,
.VCOdivider = 2,
- .VCOnumber = 4,
- .progdata = (0 << 18) | (1 << 9) | 0x08,
+ .progdata = (0 << 19) | (1 << 9) | 0x04,
},
+
+ /* band 6 */
{
- .freq_low = 1596000,
+ .freq_low = 1576000,
.freq_high = 1717999,
- .bandselect = 0x10,
.VCOdivider = 2,
- .VCOnumber = 5,
- .progdata = (0 << 18) | (1 << 9) | 0x10,
+ .progdata = (0 << 19) | (1 << 9) | 0x08,
},
+
+ /* band 7 */
{
.freq_low = 1718000,
.freq_high = 1855999,
- .bandselect = 0x20,
.VCOdivider = 2,
- .VCOnumber = 6,
- .progdata = (0 << 18) | (1 << 9) | 0x20,
+ .progdata = (0 << 19) | (1 << 9) | 0x10,
},
+
+ /* band 8 */
{
.freq_low = 1856000,
.freq_high = 2035999,
- .bandselect = 0x40,
.VCOdivider = 2,
- .VCOnumber = 7,
- .progdata = (0 << 18) | (1 << 9) | 0x40,
+ .progdata = (0 << 19) | (1 << 9) | 0x20,
},
+
+ /* band 9 */
{
.freq_low = 2036000,
- .freq_high = 2149999,
- .bandselect = 0x80,
+ .freq_high = 2150000,
.VCOdivider = 2,
- .VCOnumber = 8,
- .progdata = (0 << 18) | (1 << 9) | 0x80,
+ .progdata = (0 << 19) | (1 << 9) | 0x40,
},
};
@@ -207,49 +190,44 @@ static struct {
{
{0x00, 0x03}, /* Reset system */
{0x00, 0x00}, /* Clear reset */
- {0x01, 0x3b}, /* Apply sensible defaults, from an i2c sniffer */
- {0x03, 0x07},
- {0x04, 0x10},
- {0x05, 0x04},
- {0x06, 0x31},
- {0x0d, 0x02},
- {0x0e, 0x03},
- {0x0f, 0xfe},
- {0x10, 0x01},
- {0x14, 0x01},
- {0x15, 0x98},
- {0x16, 0x00},
- {0x17, 0x01},
- {0x1b, 0x05},
- {0x1c, 0x80},
- {0x1d, 0x00},
- {0x1e, 0x00},
- {0x20, 0x41},
- {0x21, 0x15},
- {0x27, 0x14},
- {0x28, 0x46},
- {0x29, 0x00},
- {0x2a, 0xb0},
- {0x2b, 0x73},
- {0x2c, 0x00},
+ {0x03, 0x07}, /* QPSK, DVB, Auto Acquisition (default) */
+ {0x04, 0x10}, /* MPEG */
+ {0x05, 0x04}, /* MPEG */
+ {0x06, 0x31}, /* MPEG (default) */
+ {0x0b, 0x00}, /* Freq search start point (default) */
+ {0x0c, 0x00}, /* Demodulator sample gain (default) */
+ {0x0d, 0x02}, /* Frequency search range = Fsymbol / 4 (default) */
+ {0x0e, 0x03}, /* Default non-inverted, FEC 3/4 (default) */
+ {0x0f, 0xfe}, /* FEC search mask (all supported codes) */
+ {0x10, 0x01}, /* Default search inversion, no repeat (default) */
+ {0x16, 0x00}, /* Enable reading of frequency */
+ {0x17, 0x01}, /* Enable EsNO Ready Counter */
+ {0x1c, 0x80}, /* Enable error counter */
+ {0x20, 0x00}, /* Tuner burst clock rate = 500KHz */
+ {0x21, 0x15}, /* Tuner burst mode, word length = 0x15 */
+ {0x28, 0x00}, /* Enable FILTERV with positive pol., DiSEqC 2.x off */
+ {0x29, 0x00}, /* DiSEqC LNB_DC off */
+ {0x2a, 0xb0}, /* DiSEqC Parameters (default) */
+ {0x2b, 0x73}, /* DiSEqC Tone Frequency (default) */
+ {0x2c, 0x00}, /* DiSEqC Message (0x2c - 0x31) */
{0x2d, 0x00},
{0x2e, 0x00},
{0x2f, 0x00},
{0x30, 0x00},
{0x31, 0x00},
- {0x32, 0x8c},
- {0x33, 0x00},
+ {0x32, 0x8c}, /* DiSEqC Parameters (default) */
+ {0x33, 0x00}, /* Interrupts off (0x33 - 0x34) */
{0x34, 0x00},
- {0x35, 0x03},
- {0x36, 0x02},
- {0x37, 0x3a},
- {0x3a, 0x00}, /* Enable AGC accumulator */
- {0x44, 0x00},
- {0x45, 0x00},
- {0x46, 0x05},
- {0x56, 0x41},
- {0x57, 0xff},
- {0x67, 0x83},
+ {0x35, 0x03}, /* DiSEqC Tone Amplitude (default) */
+ {0x36, 0x02}, /* DiSEqC Parameters (default) */
+ {0x37, 0x3a}, /* DiSEqC Parameters (default) */
+ {0x3a, 0x00}, /* Enable AGC accumulator (for signal strength) */
+ {0x44, 0x00}, /* Constellation (default) */
+ {0x45, 0x00}, /* Symbol count (default) */
+ {0x46, 0x0d}, /* Symbol rate estimator on (default) */
+ {0x56, 0x41}, /* Various (default) */
+ {0x57, 0xff}, /* Error Counter Window (default) */
+ {0x67, 0x83}, /* Non-DCII symbol clock */
};
static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
@@ -258,6 +236,10 @@ static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
int err;
+ if (debug>1)
+ printk("cx24123: %s: write reg 0x%02x, value 0x%02x\n",
+ __FUNCTION__,reg, data);
+
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
printk("%s: writereg error(err == %i, reg == 0x%02x,"
" data == 0x%02x)\n", __FUNCTION__, err, reg, data);
@@ -274,6 +256,10 @@ static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
int err;
+ if (debug>1)
+ printk("cx24123: %s: writeln addr=0x08, reg 0x%02x, value 0x%02x\n",
+ __FUNCTION__,reg, data);
+
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
" data == 0x%02x)\n", __FUNCTION__, err, reg, data);
@@ -303,6 +289,9 @@ static int cx24123_readreg(struct cx24123_state* state, u8 reg)
return ret;
}
+ if (debug>1)
+ printk("cx24123: read reg 0x%02x, value 0x%02x\n",reg, ret);
+
return b1[0];
}
@@ -313,17 +302,23 @@ static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
{
+ u8 nom_reg = cx24123_readreg(state, 0x0e);
+ u8 auto_reg = cx24123_readreg(state, 0x10);
+
switch (inversion) {
case INVERSION_OFF:
- cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) & 0x7f);
- cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
+ dprintk("%s: inversion off\n",__FUNCTION__);
+ cx24123_writereg(state, 0x0e, nom_reg & ~0x80);
+ cx24123_writereg(state, 0x10, auto_reg | 0x80);
break;
case INVERSION_ON:
- cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) | 0x80);
- cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
+ dprintk("%s: inversion on\n",__FUNCTION__);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x80);
+ cx24123_writereg(state, 0x10, auto_reg | 0x80);
break;
case INVERSION_AUTO:
- cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) & 0x7f);
+ dprintk("%s: inversion auto\n",__FUNCTION__);
+ cx24123_writereg(state, 0x10, auto_reg & ~0x80);
break;
default:
return -EINVAL;
@@ -338,92 +333,191 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers
val = cx24123_readreg(state, 0x1b) >> 7;
- if (val == 0)
+ if (val == 0) {
+ dprintk("%s: read inversion off\n",__FUNCTION__);
*inversion = INVERSION_OFF;
- else
+ } else {
+ dprintk("%s: read inversion on\n",__FUNCTION__);
*inversion = INVERSION_ON;
+ }
return 0;
}
static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
{
+ u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
+
if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
fec = FEC_AUTO;
- /* Hardware has 5/11 and 3/5 but are never unused */
switch (fec) {
- case FEC_NONE:
- return cx24123_writereg(state, 0x0f, 0x01);
case FEC_1_2:
- return cx24123_writereg(state, 0x0f, 0x02);
+ dprintk("%s: set FEC to 1/2\n",__FUNCTION__);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x01);
+ cx24123_writereg(state, 0x0f, 0x02);
+ break;
case FEC_2_3:
- return cx24123_writereg(state, 0x0f, 0x04);
+ dprintk("%s: set FEC to 2/3\n",__FUNCTION__);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x02);
+ cx24123_writereg(state, 0x0f, 0x04);
+ break;
case FEC_3_4:
- return cx24123_writereg(state, 0x0f, 0x08);
+ dprintk("%s: set FEC to 3/4\n",__FUNCTION__);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x03);
+ cx24123_writereg(state, 0x0f, 0x08);
+ break;
+ case FEC_4_5:
+ dprintk("%s: set FEC to 4/5\n",__FUNCTION__);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x04);
+ cx24123_writereg(state, 0x0f, 0x10);
+ break;
case FEC_5_6:
- return cx24123_writereg(state, 0x0f, 0x20);
+ dprintk("%s: set FEC to 5/6\n",__FUNCTION__);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x05);
+ cx24123_writereg(state, 0x0f, 0x20);
+ break;
+ case FEC_6_7:
+ dprintk("%s: set FEC to 6/7\n",__FUNCTION__);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x06);
+ cx24123_writereg(state, 0x0f, 0x40);
+ break;
case FEC_7_8:
- return cx24123_writereg(state, 0x0f, 0x80);
+ dprintk("%s: set FEC to 7/8\n",__FUNCTION__);
+ cx24123_writereg(state, 0x0e, nom_reg | 0x07);
+ cx24123_writereg(state, 0x0f, 0x80);
+ break;
case FEC_AUTO:
- return cx24123_writereg(state, 0x0f, 0xae);
+ dprintk("%s: set FEC to auto\n",__FUNCTION__);
+ cx24123_writereg(state, 0x0f, 0xfe);
+ break;
default:
return -EOPNOTSUPP;
}
+
+ return 0;
}
static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
{
int ret;
- u8 val;
ret = cx24123_readreg (state, 0x1b);
if (ret < 0)
return ret;
- val = ret & 0x07;
- switch (val) {
+ ret = ret & 0x07;
+
+ switch (ret) {
case 1:
*fec = FEC_1_2;
break;
- case 3:
+ case 2:
*fec = FEC_2_3;
break;
- case 4:
+ case 3:
*fec = FEC_3_4;
break;
- case 5:
+ case 4:
*fec = FEC_4_5;
break;
- case 6:
+ case 5:
*fec = FEC_5_6;
break;
+ case 6:
+ *fec = FEC_6_7;
+ break;
case 7:
*fec = FEC_7_8;
break;
- case 2: /* *fec = FEC_3_5; break; */
- case 0: /* *fec = FEC_5_11; break; */
- *fec = FEC_AUTO;
- break;
default:
- *fec = FEC_NONE; // can't happen
+ /* this can happen when there's no lock */
+ *fec = FEC_NONE;
}
return 0;
}
-/* fixme: Symbol rates < 3MSps may not work because of precision loss */
+/* Approximation of closest integer of log2(a/b). It actually gives the
+ lowest integer i such that 2^i >= round(a/b) */
+static u32 cx24123_int_log2(u32 a, u32 b)
+{
+ u32 exp, nearest = 0;
+ u32 div = a / b;
+ if(a % b >= b / 2) ++div;
+ if(div < (1 << 31))
+ {
+ for(exp = 1; div > exp; nearest++)
+ exp += exp;
+ }
+ return nearest;
+}
+
static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
{
- u32 val;
+ u32 tmp, sample_rate, ratio, sample_gain;
+ u8 pll_mult;
+
+ /* check if symbol rate is within limits */
+ if ((srate > state->ops.info.symbol_rate_max) ||
+ (srate < state->ops.info.symbol_rate_min))
+ return -EOPNOTSUPP;;
+
+ /* choose the sampling rate high enough for the required operation,
+ while optimizing the power consumed by the demodulator */
+ if (srate < (XTAL*2)/2)
+ pll_mult = 2;
+ else if (srate < (XTAL*3)/2)
+ pll_mult = 3;
+ else if (srate < (XTAL*4)/2)
+ pll_mult = 4;
+ else if (srate < (XTAL*5)/2)
+ pll_mult = 5;
+ else if (srate < (XTAL*6)/2)
+ pll_mult = 6;
+ else if (srate < (XTAL*7)/2)
+ pll_mult = 7;
+ else if (srate < (XTAL*8)/2)
+ pll_mult = 8;
+ else
+ pll_mult = 9;
+
+
+ sample_rate = pll_mult * XTAL;
+
+ /*
+ SYSSymbolRate[21:0] = (srate << 23) / sample_rate
+
+ We have to use 32 bit unsigned arithmetic without precision loss.
+ The maximum srate is 45000000 or 0x02AEA540. This number has
+ only 6 clear bits on top, hence we can shift it left only 6 bits
+ at a time. Borrowed from cx24110.c
+ */
+
+ tmp = srate << 6;
+ ratio = tmp / sample_rate;
+
+ tmp = (tmp % sample_rate) << 6;
+ ratio = (ratio << 6) + (tmp / sample_rate);
+
+ tmp = (tmp % sample_rate) << 6;
+ ratio = (ratio << 6) + (tmp / sample_rate);
+
+ tmp = (tmp % sample_rate) << 5;
+ ratio = (ratio << 5) + (tmp / sample_rate);
+
+
+ cx24123_writereg(state, 0x01, pll_mult * 6);
- val = (srate / 1185) * 100;
+ cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f );
+ cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff );
+ cx24123_writereg(state, 0x0a, (ratio ) & 0xff );
- /* Compensate for scaling up, by removing 17 symbols per 1Msps */
- val = val - (17 * (srate / 1000000));
+ /* also set the demodulator sample gain */
+ sample_gain = cx24123_int_log2(sample_rate, srate);
+ tmp = cx24123_readreg(state, 0x0c) & ~0xe0;
+ cx24123_writereg(state, 0x0c, tmp | sample_gain << 5);
- cx24123_writereg(state, 0x08, (val >> 16) & 0xff );
- cx24123_writereg(state, 0x09, (val >> 8) & 0xff );
- cx24123_writereg(state, 0x0a, (val ) & 0xff );
+ dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n", __FUNCTION__, srate, ratio, sample_rate, sample_gain);
return 0;
}
@@ -437,6 +531,9 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
struct cx24123_state *state = fe->demodulator_priv;
u32 ndiv = 0, adiv = 0, vco_div = 0;
int i = 0;
+ int pump = 2;
+ int band = 0;
+ int num_bands = sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]);
/* Defaults for low freq, low rate */
state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
@@ -444,38 +541,49 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
state->bandselectarg = cx24123_bandselect_vals[0].progdata;
vco_div = cx24123_bandselect_vals[0].VCOdivider;
- /* For the given symbolerate, determine the VCA and VGA programming bits */
+ /* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */
for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++)
{
if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) &&
- (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
+ (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
state->VCAarg = cx24123_AGC_vals[i].VCAprogdata;
state->VGAarg = cx24123_AGC_vals[i].VGAprogdata;
+ state->FILTune = cx24123_AGC_vals[i].FILTune;
}
}
- /* For the given frequency, determine the bandselect programming bits */
- for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++)
+ /* determine the band to use */
+ if(force_band < 1 || force_band > num_bands)
{
- if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
- (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) {
- state->bandselectarg = cx24123_bandselect_vals[i].progdata;
- vco_div = cx24123_bandselect_vals[i].VCOdivider;
+ for (i = 0; i < num_bands; i++)
+ {
+ if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
+ (cx24123_bandselect_vals[i].freq_high >= p->frequency) )
+ band = i;
}
}
+ else
+ band = force_band - 1;
+
+ state->bandselectarg = cx24123_bandselect_vals[band].progdata;
+ vco_div = cx24123_bandselect_vals[band].VCOdivider;
+
+ /* determine the charge pump current */
+ if ( p->frequency < (cx24123_bandselect_vals[band].freq_low + cx24123_bandselect_vals[band].freq_high)/2 )
+ pump = 0x01;
+ else
+ pump = 0x02;
/* Determine the N/A dividers for the requested lband freq (in kHz). */
- /* Note: 10111 (kHz) is the Crystal Freq and divider of 10. */
- ndiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) / 32) & 0x1ff;
- adiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) % 32) & 0x1f;
+ /* Note: the reference divider R=10, frequency is in KHz, XTAL is in Hz */
+ ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff;
+ adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f;
if (adiv == 0)
- adiv++;
+ ndiv++;
- /* determine the correct pll frequency values. */
- /* Command 11, refdiv 11, cpump polarity 1, cpump current 3mA 10. */
- state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (2 << 14);
- state->pllarg |= (ndiv << 5) | adiv;
+ /* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */
+ state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv;
return 0;
}
@@ -489,6 +597,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
struct cx24123_state *state = fe->demodulator_priv;
unsigned long timeout;
+ dprintk("%s: pll writereg called, data=0x%08x\n",__FUNCTION__,data);
+
/* align the 21 bytes into to bit23 boundary */
data = data << 3;
@@ -538,6 +648,9 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct cx24123_state *state = fe->demodulator_priv;
+ u8 val;
+
+ dprintk("frequency=%i\n", p->frequency);
if (cx24123_pll_calculate(fe, p) != 0) {
printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__);
@@ -552,6 +665,14 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet
cx24123_pll_writereg(fe, p, state->bandselectarg);
cx24123_pll_writereg(fe, p, state->pllarg);
+ /* set the FILTUNE voltage */
+ val = cx24123_readreg(state, 0x28) & ~0x3;
+ cx24123_writereg(state, 0x27, state->FILTune >> 2);
+ cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3));
+
+ dprintk("%s: pll tune VCA=%d, band=%d, pll=%d\n",__FUNCTION__,state->VCAarg,
+ state->bandselectarg,state->pllarg);
+
return 0;
}
@@ -560,6 +681,8 @@ static int cx24123_initfe(struct dvb_frontend* fe)
struct cx24123_state *state = fe->demodulator_priv;
int i;
+ dprintk("%s: init frontend\n",__FUNCTION__);
+
/* Configure the demod to a good set of defaults */
for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
@@ -587,10 +710,13 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
switch (voltage) {
case SEC_VOLTAGE_13:
+ dprintk("%s: isl6421 voltage = 13V\n",__FUNCTION__);
return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
case SEC_VOLTAGE_18:
+ dprintk("%s: isl6421 voltage = 18V\n",__FUNCTION__);
return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
case SEC_VOLTAGE_OFF:
+ dprintk("%s: isl5421 voltage off\n",__FUNCTION__);
return cx24123_writelnbreg(state, 0x0, val & 0x30);
default:
return -EINVAL;
@@ -624,13 +750,93 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
return 0;
}
-static int cx24123_send_diseqc_msg(struct dvb_frontend* fe,
- struct dvb_diseqc_master_cmd *cmd)
+/* wait for diseqc queue to become ready (or timeout) */
+static void cx24123_wait_for_diseqc(struct cx24123_state *state)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(200);
+ while (!(cx24123_readreg(state, 0x29) & 0x40)) {
+ if(time_after(jiffies, timeout)) {
+ printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
+ break;
+ }
+ msleep(10);
+ }
+}
+
+static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
{
- /* fixme: Implement diseqc */
- printk("%s: No support yet\n",__FUNCTION__);
+ struct cx24123_state *state = fe->demodulator_priv;
+ int i, val;
+
+ dprintk("%s:\n",__FUNCTION__);
+
+ /* check if continuous tone has been stopped */
+ if (state->config->use_isl6421)
+ val = cx24123_readlnbreg(state, 0x00) & 0x10;
+ else
+ val = cx24123_readreg(state, 0x29) & 0x10;
- return -ENOTSUPP;
+
+ if (val) {
+ printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
+ return -ENOTSUPP;
+ }
+
+ /* wait for diseqc queue ready */
+ cx24123_wait_for_diseqc(state);
+
+ /* select tone mode */
+ cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8);
+
+ for (i = 0; i < cmd->msg_len; i++)
+ cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
+
+ val = cx24123_readreg(state, 0x29);
+ cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
+
+ /* wait for diseqc message to finish sending */
+ cx24123_wait_for_diseqc(state);
+
+ return 0;
+}
+
+static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ int val;
+
+ dprintk("%s:\n", __FUNCTION__);
+
+ /* check if continuous tone has been stoped */
+ if (state->config->use_isl6421)
+ val = cx24123_readlnbreg(state, 0x00) & 0x10;
+ else
+ val = cx24123_readreg(state, 0x29) & 0x10;
+
+
+ if (val) {
+ printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
+ return -ENOTSUPP;
+ }
+
+ cx24123_wait_for_diseqc(state);
+
+ /* select tone mode */
+ val = cx24123_readreg(state, 0x2a) & 0xf8;
+ cx24123_writereg(state, 0x2a, val | 0x04);
+
+ val = cx24123_readreg(state, 0x29);
+
+ if (burst == SEC_MINI_A)
+ cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
+ else if (burst == SEC_MINI_B)
+ cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x08));
+ else
+ return -EINVAL;
+
+ cx24123_wait_for_diseqc(state);
+
+ return 0;
}
static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
@@ -642,13 +848,15 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
*status = 0;
if (lock & 0x01)
- *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ *status |= FE_HAS_SIGNAL;
+ if (sync & 0x02)
+ *status |= FE_HAS_CARRIER;
if (sync & 0x04)
*status |= FE_HAS_VITERBI;
if (sync & 0x08)
- *status |= FE_HAS_CARRIER;
+ *status |= FE_HAS_SYNC;
if (sync & 0x80)
- *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+ *status |= FE_HAS_LOCK;
return 0;
}
@@ -681,6 +889,8 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
else
state->snr = 0;
+ dprintk("%s: BER = %d, S/N index = %d\n",__FUNCTION__,state->lastber, state->snr);
+
*ber = state->lastber;
return 0;
@@ -691,6 +901,8 @@ static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
struct cx24123_state *state = fe->demodulator_priv;
*signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
+ dprintk("%s: Signal strength = %d\n",__FUNCTION__,*signal_strength);
+
return 0;
}
@@ -699,6 +911,8 @@ static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
struct cx24123_state *state = fe->demodulator_priv;
*snr = state->snr;
+ dprintk("%s: read S/N index = %d\n",__FUNCTION__,*snr);
+
return 0;
}
@@ -707,6 +921,8 @@ static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
struct cx24123_state *state = fe->demodulator_priv;
*ucblocks = state->lastber;
+ dprintk("%s: ucblocks (ber) = %d\n",__FUNCTION__,*ucblocks);
+
return 0;
}
@@ -714,6 +930,8 @@ static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
{
struct cx24123_state *state = fe->demodulator_priv;
+ dprintk("%s: set_frontend\n",__FUNCTION__);
+
if (state->config->set_ts_params)
state->config->set_ts_params(fe, 0);
@@ -737,6 +955,8 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
{
struct cx24123_state *state = fe->demodulator_priv;
+ dprintk("%s: get_frontend\n",__FUNCTION__);
+
if (cx24123_get_inversion(state, &p->inversion) != 0) {
printk("%s: Failed to get inversion status\n",__FUNCTION__);
return -EREMOTEIO;
@@ -763,8 +983,10 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
switch (tone) {
case SEC_TONE_ON:
+ dprintk("%s: isl6421 sec tone on\n",__FUNCTION__);
return cx24123_writelnbreg(state, 0x0, val | 0x10);
case SEC_TONE_OFF:
+ dprintk("%s: isl6421 sec tone off\n",__FUNCTION__);
return cx24123_writelnbreg(state, 0x0, val & 0x2f);
default:
printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
@@ -855,12 +1077,13 @@ static struct dvb_frontend_ops cx24123_ops = {
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 1011, /* kHz for QPSK frontends */
- .frequency_tolerance = 29500,
+ .frequency_tolerance = 5000,
.symbol_rate_min = 1000000,
.symbol_rate_max = 45000000,
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+ FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_RECOVER
},
@@ -875,12 +1098,16 @@ static struct dvb_frontend_ops cx24123_ops = {
.read_snr = cx24123_read_snr,
.read_ucblocks = cx24123_read_ucblocks,
.diseqc_send_master_cmd = cx24123_send_diseqc_msg,
+ .diseqc_send_burst = cx24123_diseqc_send_burst,
.set_tone = cx24123_set_tone,
.set_voltage = cx24123_set_voltage,
};
module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
+module_param(force_band, int, 0644);
+MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off).");
MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware");
MODULE_AUTHOR("Steven Toth");
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index b6e2c387a04..791706ec1da 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -235,8 +235,8 @@ struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
.max = 863000000,
.count = 3,
.entries = {
- { 160000000, 44000000, 62500, 0xce, 0x01 },
- { 455000000, 44000000, 62500, 0xce, 0x02 },
+ { 165000000, 44000000, 62500, 0xce, 0x01 },
+ { 450000000, 44000000, 62500, 0xce, 0x02 },
{ 999999999, 44000000, 62500, 0xce, 0x04 },
},
};
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 8e8df7b4ca0..b83dafa4e12 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -52,7 +52,6 @@ struct tda1004x_state {
struct dvb_frontend frontend;
/* private demod data */
- u8 initialised;
enum tda1004x_demod demod_type;
};
@@ -594,9 +593,6 @@ static int tda10045_init(struct dvb_frontend* fe)
dprintk("%s\n", __FUNCTION__);
- if (state->initialised)
- return 0;
-
if (tda10045_fwupload(fe)) {
printk("tda1004x: firmware upload failed\n");
return -EIO;
@@ -626,7 +622,6 @@ static int tda10045_init(struct dvb_frontend* fe)
tda1004x_write_mask(state, 0x1f, 0x01, state->config->invert_oclk);
- state->initialised = 1;
return 0;
}
@@ -635,9 +630,6 @@ static int tda10046_init(struct dvb_frontend* fe)
struct tda1004x_state* state = fe->demodulator_priv;
dprintk("%s\n", __FUNCTION__);
- if (state->initialised)
- return 0;
-
if (tda10046_fwupload(fe)) {
printk("tda1004x: firmware upload failed\n");
return -EIO;
@@ -697,7 +689,6 @@ static int tda10046_init(struct dvb_frontend* fe)
// tda1004x_write_mask(state, 0x50, 0x80, 0x80); // handle out of guard echoes
tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
- state->initialised = 1;
return 0;
}
@@ -1207,7 +1198,6 @@ static int tda1004x_sleep(struct dvb_frontend* fe)
tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
break;
}
- state->initialised = 0;
return 0;
}
@@ -1271,7 +1261,6 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
state->config = config;
state->i2c = i2c;
memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
- state->initialised = 0;
state->demod_type = TDA1004X_DEMOD_TDA10045;
/* check if the demod is there */
@@ -1330,7 +1319,6 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
state->config = config;
state->i2c = i2c;
memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
- state->initialised = 0;
state->demod_type = TDA1004X_DEMOD_TDA10046;
/* check if the demod is there */
diff --git a/drivers/media/dvb/pluto2/Kconfig b/drivers/media/dvb/pluto2/Kconfig
index 84f8f9f5286..7d8e6e87bdb 100644
--- a/drivers/media/dvb/pluto2/Kconfig
+++ b/drivers/media/dvb/pluto2/Kconfig
@@ -1,7 +1,6 @@
config DVB_PLUTO2
tristate "Pluto2 cards"
- depends on DVB_CORE && PCI
- select I2C
+ depends on DVB_CORE && PCI && I2C
select I2C_ALGOBIT
select DVB_TDA1004X
help
diff --git a/drivers/media/dvb/pluto2/Makefile b/drivers/media/dvb/pluto2/Makefile
index 86ca84b2be6..ce6a9aaf937 100644
--- a/drivers/media/dvb/pluto2/Makefile
+++ b/drivers/media/dvb/pluto2/Makefile
@@ -1,3 +1,3 @@
-obj-$(CONFIG_DVB_PLUTO2) = pluto2.o
+obj-$(CONFIG_DVB_PLUTO2) += pluto2.o
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index 5b2aadb8385..b5ac7dfde52 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -1,8 +1,7 @@
config DVB_AV7110
tristate "AV7110 cards"
- depends on DVB_CORE && PCI
+ depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
select FW_LOADER
- select VIDEO_DEV
select VIDEO_SAA7146_VV
select DVB_VES1820
select DVB_VES1X93
@@ -59,7 +58,7 @@ config DVB_AV7110_OSD
config DVB_BUDGET
tristate "Budget cards"
- depends on DVB_CORE && PCI
+ depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
select VIDEO_SAA7146
select DVB_STV0299
select DVB_VES1X93
@@ -80,7 +79,7 @@ config DVB_BUDGET
config DVB_BUDGET_CI
tristate "Budget cards with onboard CI connector"
- depends on DVB_CORE && PCI
+ depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
select VIDEO_SAA7146
select DVB_STV0297
select DVB_STV0299
@@ -100,8 +99,7 @@ config DVB_BUDGET_CI
config DVB_BUDGET_AV
tristate "Budget cards with analog video inputs"
- depends on DVB_CORE && PCI
- select VIDEO_DEV
+ depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
select VIDEO_SAA7146_VV
select DVB_STV0299
select DVB_TDA1004X
@@ -119,7 +117,7 @@ config DVB_BUDGET_AV
config DVB_BUDGET_PATCH
tristate "AV7110 cards with Budget Patch"
- depends on DVB_CORE && DVB_BUDGET
+ depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1
select DVB_AV7110
select DVB_STV0299
select DVB_VES1X93
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 840efec32cb..d028245c8ee 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -87,6 +87,7 @@ static int volume = 255;
static int budgetpatch;
static int wss_cfg_4_3 = 0x4008;
static int wss_cfg_16_9 = 0x0007;
+static int tv_standard;
module_param_named(debug, av7110_debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
@@ -109,6 +110,8 @@ module_param(wss_cfg_4_3, int, 0444);
MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
module_param(wss_cfg_16_9, int, 0444);
MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: burst mode, 13..0: wss data");
+module_param(tv_standard, int, 0444);
+MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
static void restart_feeds(struct av7110 *av7110);
@@ -2123,7 +2126,7 @@ static int frontend_init(struct av7110 *av7110)
read_pwm(av7110));
break;
case 0x0003:
- /* Haupauge DVB-C 2.1 VES1820/ALPS TDBE2 */
+ /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,
read_pwm(av7110));
break;
@@ -2543,6 +2546,9 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
av7110->osdwin = 1;
mutex_init(&av7110->osd_mutex);
+ /* TV standard */
+ av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
+
/* ARM "watchdog" */
init_waitqueue_head(&av7110->arm_wait);
av7110->arm_thread = NULL;
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 400facec740..2eff09f638d 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -1479,8 +1479,6 @@ int av7110_av_init(struct av7110 *av7110)
void (*play[])(u8 *, int, void *) = { play_audio_cb, play_video_cb };
int i, ret;
- av7110->vidmode = VIDEO_MODE_PAL;
-
for (i = 0; i < 2; i++) {
struct ipack *ipack = av7110->ipack + i;
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 9dd4745f531..8a7cd7d505c 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -60,11 +60,11 @@ struct budget_av {
struct dvb_ca_en50221 ca;
};
-/* GPIO CI Connections:
- * 0 - Vcc/Reset (Reset is controlled by capacitor)
- * 1 - Attribute Memory
- * 2 - Card Enable (Active Low)
- * 3 - Card Detect
+/* GPIO Connections:
+ * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
+ * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
+ * 2 - CI Card Enable (Active Low)
+ * 3 - CI Card Detect
*/
/****************************************************************************
@@ -214,6 +214,9 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
msleep(100);
+ /* reinitialise the frontend */
+ dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
+
if (timeout <= 0)
{
printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
@@ -1187,8 +1190,6 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
SAA7146_HPS_SYNC_PORT_A);
saa7113_setinput(budget_av, 0);
- } else {
- ciintf_init(budget_av);
}
/* fixme: find some sane values here... */
@@ -1208,6 +1209,10 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
budget_av->budget.dvb_adapter.priv = budget_av;
frontend_init(budget_av);
+ if (!budget_av->has_saa7113) {
+ ciintf_init(budget_av);
+ }
+
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 5f91036f5b8..e64a609cf4f 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -71,6 +71,7 @@ struct budget_ci {
struct tasklet_struct msp430_irq_tasklet;
struct tasklet_struct ciintf_irq_tasklet;
int slot_status;
+ int ci_irq;
struct dvb_ca_en50221 ca;
char ir_dev_name[50];
u8 tuner_pll_address; /* used for philips_tdm1316l configs */
@@ -276,8 +277,10 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
if (slot != 0)
return -EINVAL;
- // trigger on RISING edge during reset so we know when READY is re-asserted
- saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
+ if (budget_ci->ci_irq) {
+ // trigger on RISING edge during reset so we know when READY is re-asserted
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
+ }
budget_ci->slot_status = SLOTSTATUS_RESET;
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
msleep(1);
@@ -370,11 +373,50 @@ static void ciintf_interrupt(unsigned long data)
}
}
+static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
+{
+ struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
+ unsigned int flags;
+
+ // ensure we don't get spurious IRQs during initialisation
+ if (!budget_ci->budget.ci_present)
+ return -EINVAL;
+
+ // read the CAM status
+ flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
+ if (flags & CICONTROL_CAMDETECT) {
+ // mark it as present if it wasn't before
+ if (budget_ci->slot_status & SLOTSTATUS_NONE) {
+ budget_ci->slot_status = SLOTSTATUS_PRESENT;
+ }
+
+ // during a RESET, we check if we can read from IO memory to see when CAM is ready
+ if (budget_ci->slot_status & SLOTSTATUS_RESET) {
+ if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
+ budget_ci->slot_status = SLOTSTATUS_READY;
+ }
+ }
+ } else {
+ budget_ci->slot_status = SLOTSTATUS_NONE;
+ }
+
+ if (budget_ci->slot_status != SLOTSTATUS_NONE) {
+ if (budget_ci->slot_status & SLOTSTATUS_READY) {
+ return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
+ }
+ return DVB_CA_EN50221_POLL_CAM_PRESENT;
+ }
+
+ return 0;
+}
+
static int ciintf_init(struct budget_ci *budget_ci)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
int flags;
int result;
+ int ci_version;
+ int ca_flags;
memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
@@ -382,16 +424,29 @@ static int ciintf_init(struct budget_ci *budget_ci)
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
// test if it is there
- if ((ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0) & 0xa0) != 0xa0) {
+ ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
+ if ((ci_version & 0xa0) != 0xa0) {
result = -ENODEV;
goto error;
}
+
// determine whether a CAM is present or not
flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
budget_ci->slot_status = SLOTSTATUS_NONE;
if (flags & CICONTROL_CAMDETECT)
budget_ci->slot_status = SLOTSTATUS_PRESENT;
+ // version 0xa2 of the CI firmware doesn't generate interrupts
+ if (ci_version == 0xa2) {
+ ca_flags = 0;
+ budget_ci->ci_irq = 0;
+ } else {
+ ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
+ DVB_CA_EN50221_FLAG_IRQ_FR |
+ DVB_CA_EN50221_FLAG_IRQ_DA;
+ budget_ci->ci_irq = 1;
+ }
+
// register CI interface
budget_ci->ca.owner = THIS_MODULE;
budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
@@ -401,23 +456,27 @@ static int ciintf_init(struct budget_ci *budget_ci)
budget_ci->ca.slot_reset = ciintf_slot_reset;
budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
+ budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
budget_ci->ca.data = budget_ci;
if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
&budget_ci->ca,
- DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
- DVB_CA_EN50221_FLAG_IRQ_FR |
- DVB_CA_EN50221_FLAG_IRQ_DA, 1)) != 0) {
+ ca_flags, 1)) != 0) {
printk("budget_ci: CI interface detected, but initialisation failed.\n");
goto error;
}
+
// Setup CI slot IRQ
- tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
- if (budget_ci->slot_status != SLOTSTATUS_NONE) {
- saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
- } else {
- saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
+ if (budget_ci->ci_irq) {
+ tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
+ if (budget_ci->slot_status != SLOTSTATUS_NONE) {
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
+ } else {
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
+ }
+ saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03);
}
- saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03);
+
+ // enable interface
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
CICONTROL_RESET, 1, 0);
@@ -426,10 +485,12 @@ static int ciintf_init(struct budget_ci *budget_ci)
budget_ci->budget.ci_present = 1;
// forge a fake CI IRQ so the CAM state is setup correctly
- flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
- if (budget_ci->slot_status != SLOTSTATUS_NONE)
- flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
- dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
+ if (budget_ci->ci_irq) {
+ flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
+ if (budget_ci->slot_status != SLOTSTATUS_NONE)
+ flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
+ dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
+ }
return 0;
@@ -443,9 +504,13 @@ static void ciintf_deinit(struct budget_ci *budget_ci)
struct saa7146_dev *saa = budget_ci->budget.dev;
// disable CI interrupts
- saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03);
- saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
- tasklet_kill(&budget_ci->ciintf_irq_tasklet);
+ if (budget_ci->ci_irq) {
+ saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03);
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
+ tasklet_kill(&budget_ci->ciintf_irq_tasklet);
+ }
+
+ // reset interface
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
msleep(1);
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
@@ -473,7 +538,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
if (*isr & MASK_10)
ttpci_budget_irq10_handler(dev, isr);
- if ((*isr & MASK_03) && (budget_ci->budget.ci_present))
+ if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
}
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 633e68c341c..ea2066d461f 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -39,9 +39,21 @@
#include "budget.h"
#include "ttpci-eeprom.h"
+#define TS_WIDTH (2 * TS_SIZE)
+#define TS_WIDTH_ACTIVY TS_SIZE
+#define TS_HEIGHT_MASK 0xf00
+#define TS_HEIGHT_MASK_ACTIVY 0xc00
+#define TS_MIN_BUFSIZE_K 188
+#define TS_MAX_BUFSIZE_K 1410
+#define TS_MAX_BUFSIZE_K_ACTIVY 564
+#define BUFFER_WARNING_WAIT (30*HZ)
+
int budget_debug;
+static int dma_buffer_size = TS_MIN_BUFSIZE_K;
module_param_named(debug, budget_debug, int, 0644);
+module_param_named(bufsize, dma_buffer_size, int, 0444);
MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
+MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
/****************************************************************************
* TT budget / WinTV Nova
@@ -70,11 +82,10 @@ static int start_ts_capture(struct budget *budget)
saa7146_write(dev, MC1, MASK_20); // DMA3 off
- memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
+ memset(budget->grabbing, 0x00, budget->buffer_size);
saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
- budget->tsf = 0xff;
budget->ttbp = 0;
/*
@@ -115,16 +126,12 @@ static int start_ts_capture(struct budget *budget)
saa7146_write(dev, BASE_ODD3, 0);
saa7146_write(dev, BASE_EVEN3, 0);
- saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
+ saa7146_write(dev, PROT_ADDR3, budget->buffer_size);
saa7146_write(dev, BASE_PAGE3, budget->pt.dma | ME1 | 0x90);
- if (budget->card->type == BUDGET_FS_ACTIVY) {
- saa7146_write(dev, PITCH3, TS_WIDTH / 2);
- saa7146_write(dev, NUM_LINE_BYTE3, ((TS_HEIGHT * 2) << 16) | (TS_WIDTH / 2));
- } else {
- saa7146_write(dev, PITCH3, TS_WIDTH);
- saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
- }
+ saa7146_write(dev, PITCH3, budget->buffer_width);
+ saa7146_write(dev, NUM_LINE_BYTE3,
+ (budget->buffer_height << 16) | budget->buffer_width);
saa7146_write(dev, MC2, (MASK_04 | MASK_20));
@@ -141,11 +148,12 @@ static void vpeirq(unsigned long data)
u8 *mem = (u8 *) (budget->grabbing);
u32 olddma = budget->ttbp;
u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
+ u32 count;
/* nearest lower position divisible by 188 */
newdma -= newdma % 188;
- if (newdma >= TS_BUFLEN)
+ if (newdma >= budget->buffer_size)
return;
budget->ttbp = newdma;
@@ -154,11 +162,24 @@ static void vpeirq(unsigned long data)
return;
if (newdma > olddma) { /* no wraparound, dump olddma..newdma */
- dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (newdma - olddma) / 188);
+ count = newdma - olddma;
+ dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
} else { /* wraparound, dump olddma..buflen and 0..newdma */
- dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
+ count = budget->buffer_size - olddma;
+ dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
+ count += newdma;
dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 188);
}
+
+ if (count > budget->buffer_warning_threshold)
+ budget->buffer_warnings++;
+
+ if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) {
+ printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n",
+ budget->dev->name, __FUNCTION__, budget->buffer_warnings, count);
+ budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT;
+ budget->buffer_warnings = 0;
+ }
}
@@ -341,9 +362,10 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
struct saa7146_pci_extension_data *info,
struct module *owner)
{
- int length = TS_WIDTH * TS_HEIGHT;
int ret = 0;
struct budget_info *bi = info->ext_priv;
+ int max_bufsize;
+ int height_mask;
memset(budget, 0, sizeof(struct budget));
@@ -352,6 +374,32 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
budget->card = bi;
budget->dev = (struct saa7146_dev *) dev;
+ if (budget->card->type == BUDGET_FS_ACTIVY) {
+ budget->buffer_width = TS_WIDTH_ACTIVY;
+ max_bufsize = TS_MAX_BUFSIZE_K_ACTIVY;
+ height_mask = TS_HEIGHT_MASK_ACTIVY;
+ } else {
+ budget->buffer_width = TS_WIDTH;
+ max_bufsize = TS_MAX_BUFSIZE_K;
+ height_mask = TS_HEIGHT_MASK;
+ }
+
+ if (dma_buffer_size < TS_MIN_BUFSIZE_K)
+ dma_buffer_size = TS_MIN_BUFSIZE_K;
+ else if (dma_buffer_size > max_bufsize)
+ dma_buffer_size = max_bufsize;
+
+ budget->buffer_height = dma_buffer_size * 1024 / budget->buffer_width;
+ budget->buffer_height &= height_mask;
+ budget->buffer_size = budget->buffer_height * budget->buffer_width;
+ budget->buffer_warning_threshold = budget->buffer_size * 80/100;
+ budget->buffer_warnings = 0;
+ budget->buffer_warning_time = jiffies;
+
+ dprintk(2, "%s: width = %d, height = %d\n",
+ budget->dev->name, budget->buffer_width, budget->buffer_height);
+ printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
+
dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner);
/* set dd1 stream a & b */
@@ -392,7 +440,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac);
if (NULL ==
- (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, length, &budget->pt))) {
+ (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt))) {
ret = -ENOMEM;
goto err;
}
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 9fc9185a842..1b3aaac5e76 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -577,6 +577,17 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
// Set RPS1 Address register to point to RPS code (r108 p42)
saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
+
+ if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
+ return -ENOMEM;
+
+ dprintk(2, "budget: %p\n", budget);
+
+ if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
+ kfree (budget);
+ return err;
+ }
+
// Set Source Line Counter Threshold, using BRS (rCC p43)
// It generates HS event every TS_HEIGHT lines
// this is related to TS_WIDTH set in register
@@ -585,24 +596,13 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
//,then RPS_THRESH1
// should be set to trigger every TS_HEIGHT (512) lines.
//
- saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
+ saa7146_write(dev, RPS_THRESH1, budget->buffer_height | MASK_12 );
// saa7146_write(dev, RPS_THRESH0, ((TS_HEIGHT/2)<<16) |MASK_28| (TS_HEIGHT/2) |MASK_12 );
// Enable RPS1 (rFC p33)
saa7146_write(dev, MC1, (MASK_13 | MASK_29));
- if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
- return -ENOMEM;
-
- dprintk(2, "budget: %p\n", budget);
-
- if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
- kfree (budget);
- return err;
- }
-
-
dev->ext_priv = budget;
budget->dvb_adapter.priv = budget;
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index 4ac0f4d0802..ecea3a13030 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -58,7 +58,13 @@ struct budget {
int ci_present;
int video_port;
- u8 tsf;
+ u32 buffer_width;
+ u32 buffer_height;
+ u32 buffer_size;
+ u32 buffer_warning_threshold;
+ u32 buffer_warnings;
+ unsigned long buffer_warning_time;
+
u32 ttbp;
int feeding;
@@ -79,11 +85,6 @@ static struct saa7146_pci_extension_data x_var = { \
.ext_priv = &x_var ## _info, \
.ext = &budget_extension };
-#define TS_WIDTH (376)
-#define TS_HEIGHT (512)
-#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
-#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
-
#define BUDGET_TT 0
#define BUDGET_TT_HW_DISEQC 1
#define BUDGET_PATCH 3
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 248fdc7accf..6ceae38125c 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -1507,7 +1507,11 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
mutex_unlock(&ttusb->semi2c);
- dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE);
+ if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE)) < 0) {
+ ttusb_free_iso_urbs(ttusb);
+ kfree(ttusb);
+ return result;
+ }
ttusb->adapter.priv = ttusb;
/* i2c */
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index d318be383de..3fff7576369 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -7,7 +7,7 @@ menu "Radio Adapters"
config RADIO_CADET
tristate "ADS Cadet AM/FM Tuner"
- depends on ISA && VIDEO_DEV
+ depends on ISA && VIDEO_V4L1
---help---
Choose Y here if you have one of these AM/FM radio cards, and then
fill in the port address below.
@@ -25,7 +25,7 @@ config RADIO_CADET
config RADIO_RTRACK
tristate "AIMSlab RadioTrack (aka RadioReveal) support"
- depends on ISA && VIDEO_DEV
+ depends on ISA && VIDEO_V4L1
---help---
Choose Y here if you have one of these FM radio cards, and then fill
in the port address below.
@@ -59,7 +59,7 @@ config RADIO_RTRACK_PORT
config RADIO_RTRACK2
tristate "AIMSlab RadioTrack II support"
- depends on ISA && VIDEO_DEV
+ depends on ISA && VIDEO_V4L1
---help---
Choose Y here if you have this FM radio card, and then fill in the
port address below.
@@ -82,7 +82,7 @@ config RADIO_RTRACK2_PORT
config RADIO_AZTECH
tristate "Aztech/Packard Bell Radio"
- depends on ISA && VIDEO_DEV
+ depends on ISA && VIDEO_V4L1
---help---
Choose Y here if you have one of these FM radio cards, and then fill
in the port address below.
@@ -106,7 +106,7 @@ config RADIO_AZTECH_PORT
config RADIO_GEMTEK
tristate "GemTek Radio Card support"
- depends on ISA && VIDEO_DEV
+ depends on ISA && VIDEO_V4L1
---help---
Choose Y here if you have this FM radio card, and then fill in the
port address below.
@@ -131,7 +131,7 @@ config RADIO_GEMTEK_PORT
config RADIO_GEMTEK_PCI
tristate "GemTek PCI Radio Card support"
- depends on VIDEO_DEV && PCI
+ depends on VIDEO_V4L1 && PCI
---help---
Choose Y here if you have this PCI FM radio card.
@@ -145,7 +145,7 @@ config RADIO_GEMTEK_PCI
config RADIO_MAXIRADIO
tristate "Guillemot MAXI Radio FM 2000 radio"
- depends on VIDEO_DEV && PCI
+ depends on VIDEO_V4L1 && PCI
---help---
Choose Y here if you have this radio card. This card may also be
found as Gemtek PCI FM.
@@ -160,7 +160,7 @@ config RADIO_MAXIRADIO
config RADIO_MAESTRO
tristate "Maestro on board radio"
- depends on VIDEO_DEV
+ depends on VIDEO_V4L1
---help---
Say Y here to directly support the on-board radio tuner on the
Maestro 2 or 2E sound card.
@@ -175,7 +175,7 @@ config RADIO_MAESTRO
config RADIO_MIROPCM20
tristate "miroSOUND PCM20 radio"
- depends on ISA && VIDEO_DEV && SOUND_ACI_MIXER
+ depends on ISA && VIDEO_V4L1 && SOUND_ACI_MIXER
---help---
Choose Y here if you have this FM radio card. You also need to say Y
to "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)" (in "Sound")
@@ -208,7 +208,7 @@ config RADIO_MIROPCM20_RDS
config RADIO_SF16FMI
tristate "SF16FMI Radio"
- depends on ISA && VIDEO_DEV
+ depends on ISA && VIDEO_V4L1
---help---
Choose Y here if you have one of these FM radio cards. If you
compile the driver into the kernel and your card is not PnP one, you
@@ -225,7 +225,7 @@ config RADIO_SF16FMI
config RADIO_SF16FMR2
tristate "SF16FMR2 Radio"
- depends on ISA && VIDEO_DEV
+ depends on ISA && VIDEO_V4L1
---help---
Choose Y here if you have one of these FM radio cards.
@@ -239,7 +239,7 @@ config RADIO_SF16FMR2
config RADIO_TERRATEC
tristate "TerraTec ActiveRadio ISA Standalone"
- depends on ISA && VIDEO_DEV
+ depends on ISA && VIDEO_V4L1
---help---
Choose Y here if you have this FM radio card, and then fill in the
port address below. (TODO)
@@ -268,7 +268,7 @@ config RADIO_TERRATEC_PORT
config RADIO_TRUST
tristate "Trust FM radio card"
- depends on ISA && VIDEO_DEV
+ depends on ISA && VIDEO_V4L1
help
This is a driver for the Trust FM radio cards. Say Y if you have
such a card and want to use it under Linux.
@@ -286,7 +286,7 @@ config RADIO_TRUST_PORT
config RADIO_TYPHOON
tristate "Typhoon Radio (a.k.a. EcoRadio)"
- depends on ISA && VIDEO_DEV
+ depends on ISA && VIDEO_V4L1
---help---
Choose Y here if you have one of these FM radio cards, and then fill
in the port address and the frequency used for muting below.
@@ -330,7 +330,7 @@ config RADIO_TYPHOON_MUTEFREQ
config RADIO_ZOLTRIX
tristate "Zoltrix Radio"
- depends on ISA && VIDEO_DEV
+ depends on ISA && VIDEO_V4L1
---help---
Choose Y here if you have one of these FM radio cards, and then fill
in the port address below.
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index f31a19890b1..6b419701856 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -2,10 +2,10 @@
# Multimedia Video device configuration
#
-menu "Video For Linux"
+menu "Video Capture Adapters"
depends on VIDEO_DEV
-comment "Video Adapters"
+comment "Video Capture Adapters"
config VIDEO_ADV_DEBUG
bool "Enable advanced debug functionality"
@@ -16,11 +16,23 @@ config VIDEO_ADV_DEBUG
V4L devices.
In doubt, say N.
+config VIDEO_VIVI
+ tristate "Virtual Video Driver"
+ depends on VIDEO_V4L2 && !SPARC32 && !SPARC64
+ select VIDEO_BUF
+ default n
+ ---help---
+ Enables a virtual video driver. This device shows a color bar
+ and a timestamp, as a real device would generate by using V4L2
+ api.
+ Say Y here if you want to test video apps or debug V4L devices.
+ In doubt, say N.
+
source "drivers/media/video/bt8xx/Kconfig"
config VIDEO_SAA6588
tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards"
- depends on VIDEO_DEV && I2C && VIDEO_BT848
+ depends on I2C && VIDEO_BT848
help
Support for Radio Data System (RDS) decoder. This allows seeing
@@ -32,7 +44,7 @@ config VIDEO_SAA6588
config VIDEO_PMS
tristate "Mediavision Pro Movie Studio Video For Linux"
- depends on VIDEO_DEV && ISA
+ depends on ISA && VIDEO_V4L1
help
Say Y if you have such a thing.
@@ -41,7 +53,7 @@ config VIDEO_PMS
config VIDEO_PLANB
tristate "PlanB Video-In on PowerMac"
- depends on PPC_PMAC && VIDEO_DEV && BROKEN
+ depends on PPC_PMAC && VIDEO_V4L1 && BROKEN
help
PlanB is the V4L driver for the PowerMac 7x00/8x00 series video
input hardware. If you want to experiment with this, say Y.
@@ -52,7 +64,7 @@ config VIDEO_PLANB
config VIDEO_BWQCAM
tristate "Quickcam BW Video For Linux"
- depends on VIDEO_DEV && PARPORT
+ depends on PARPORT && VIDEO_V4L1
help
Say Y have if you the black and white version of the QuickCam
camera. See the next option for the color version.
@@ -62,7 +74,7 @@ config VIDEO_BWQCAM
config VIDEO_CQCAM
tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)"
- depends on EXPERIMENTAL && VIDEO_DEV && PARPORT
+ depends on EXPERIMENTAL && PARPORT && VIDEO_V4L1
help
This is the video4linux driver for the colour version of the
Connectix QuickCam. If you have one of these cameras, say Y here,
@@ -73,7 +85,7 @@ config VIDEO_CQCAM
config VIDEO_W9966
tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux"
- depends on PARPORT_1284 && VIDEO_DEV && PARPORT
+ depends on PARPORT_1284 && PARPORT && VIDEO_V4L1
help
Video4linux driver for Winbond's w9966 based Webcams.
Currently tested with the LifeView FlyCam Supra.
@@ -86,7 +98,7 @@ config VIDEO_W9966
config VIDEO_CPIA
tristate "CPiA Video For Linux"
- depends on VIDEO_DEV
+ depends on VIDEO_V4L1
---help---
This is the video4linux driver for cameras based on Vision's CPiA
(Colour Processor Interface ASIC), such as the Creative Labs Video
@@ -123,7 +135,7 @@ source "drivers/media/video/cpia2/Kconfig"
config VIDEO_SAA5246A
tristate "SAA5246A, SAA5281 Teletext processor"
- depends on VIDEO_DEV && I2C
+ depends on I2C && VIDEO_V4L1
help
Support for I2C bus based teletext using the SAA5246A or SAA5281
chip. Useful only if you live in Europe.
@@ -150,7 +162,7 @@ config TUNER_3036
config VIDEO_VINO
tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
- depends on VIDEO_DEV && I2C && SGI_IP22 && EXPERIMENTAL
+ depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L1
select I2C_ALGO_SGI
help
Say Y here to build in support for the Vino video input system found
@@ -158,7 +170,7 @@ config VIDEO_VINO
config VIDEO_STRADIS
tristate "Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)"
- depends on EXPERIMENTAL && VIDEO_DEV && PCI
+ depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && !PPC64
help
Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video
driver for PCI. There is a product page at
@@ -166,7 +178,7 @@ config VIDEO_STRADIS
config VIDEO_ZORAN
tristate "Zoran ZR36057/36067 Video For Linux"
- depends on VIDEO_DEV && PCI && I2C_ALGOBIT
+ depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && !PPC64
help
Say Y for support for MJPEG capture cards based on the Zoran
36057/36067 PCI controller chipset. This includes the Iomega
@@ -214,7 +226,7 @@ config VIDEO_ZORAN_LML33R10
config VIDEO_ZR36120
tristate "Zoran ZR36120/36125 Video For Linux"
- depends on VIDEO_DEV && PCI && I2C && BROKEN
+ depends on PCI && I2C && VIDEO_V4L1 && BROKEN
help
Support for ZR36120/ZR36125 based frame grabber/overlay boards.
This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV,
@@ -226,7 +238,7 @@ config VIDEO_ZR36120
config VIDEO_MEYE
tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
- depends on VIDEO_DEV && PCI && SONYPI
+ depends on PCI && SONYPI && VIDEO_V4L1
---help---
This is the video4linux driver for the Motion Eye camera found
in the Vaio Picturebook laptops. Please read the material in
@@ -242,7 +254,7 @@ source "drivers/media/video/saa7134/Kconfig"
config VIDEO_MXB
tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
- depends on VIDEO_DEV && PCI
+ depends on PCI && VIDEO_V4L1
select VIDEO_SAA7146_VV
select VIDEO_TUNER
---help---
@@ -254,8 +266,9 @@ config VIDEO_MXB
config VIDEO_DPC
tristate "Philips-Semiconductors 'dpc7146 demonstration board'"
- depends on VIDEO_DEV && PCI
+ depends on PCI && VIDEO_V4L1
select VIDEO_SAA7146_VV
+ select VIDEO_V4L2
---help---
This is a video4linux driver for the 'dpc7146 demonstration
board' by Philips-Semiconductors. It's the reference design
@@ -268,8 +281,9 @@ config VIDEO_DPC
config VIDEO_HEXIUM_ORION
tristate "Hexium HV-PCI6 and Orion frame grabber"
- depends on VIDEO_DEV && PCI
+ depends on PCI && VIDEO_V4L1
select VIDEO_SAA7146_VV
+ select VIDEO_V4L2
---help---
This is a video4linux driver for the Hexium HV-PCI6 and
Orion frame grabber cards by Hexium.
@@ -279,8 +293,9 @@ config VIDEO_HEXIUM_ORION
config VIDEO_HEXIUM_GEMINI
tristate "Hexium Gemini frame grabber"
- depends on VIDEO_DEV && PCI
+ depends on PCI && VIDEO_V4L1
select VIDEO_SAA7146_VV
+ select VIDEO_V4L2
---help---
This is a video4linux driver for the Hexium Gemini frame
grabber card by Hexium. Please note that the Gemini Dual
@@ -293,18 +308,18 @@ source "drivers/media/video/cx88/Kconfig"
config VIDEO_OVCAMCHIP
tristate "OmniVision Camera Chip support"
- depends on VIDEO_DEV && I2C
+ depends on I2C && VIDEO_V4L1
---help---
Support for the OmniVision OV6xxx and OV7xxx series of camera chips.
This driver is intended to be used with the ov511 and w9968cf USB
camera drivers.
To compile this driver as a module, choose M here: the
- module will be called ovcamchip
+ module will be called ovcamchip.
config VIDEO_M32R_AR
tristate "AR devices"
- depends on M32R
+ depends on M32R && VIDEO_V4L1
---help---
This is a video4linux driver for the Renesas AR (Artificial Retina)
camera module.
@@ -316,6 +331,13 @@ config VIDEO_M32R_AR_M64278
Say Y here to use the Renesas M64278E-800 camera module,
which supports VGA(640x480 pixcels) size of images.
+#
+# Encoder / Decoder module configuration
+#
+
+menu "Encoders and Decoders"
+ depends on VIDEO_DEV
+
config VIDEO_MSP3400
tristate "Micronas MSP34xx audio decoders"
depends on VIDEO_DEV && I2C
@@ -323,7 +345,7 @@ config VIDEO_MSP3400
Support for the Micronas MSP34xx series of audio decoders.
To compile this driver as a module, choose M here: the
- module will be called msp3400
+ module will be called msp3400.
config VIDEO_CS53L32A
tristate "Cirrus Logic CS53L32A audio ADC"
@@ -333,37 +355,72 @@ config VIDEO_CS53L32A
stereo A/D converter.
To compile this driver as a module, choose M here: the
- module will be called cs53l32a
+ module will be called cs53l32a.
config VIDEO_WM8775
- tristate "Wolfson Microelectronics WM8775 audio ADC"
+ tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
depends on VIDEO_DEV && I2C && EXPERIMENTAL
---help---
- Support for the Wolfson Microelectronics WM8775
- high performance stereo A/D Converter.
+ Support for the Wolfson Microelectronics WM8775 high
+ performance stereo A/D Converter with a 4 channel input mixer.
To compile this driver as a module, choose M here: the
- module will be called wm8775
+ module will be called wm8775.
+
+config VIDEO_WM8739
+ tristate "Wolfson Microelectronics WM8739 stereo audio ADC"
+ depends on VIDEO_DEV && I2C && EXPERIMENTAL
+ ---help---
+ Support for the Wolfson Microelectronics WM8739
+ stereo A/D Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wm8739.
source "drivers/media/video/cx25840/Kconfig"
config VIDEO_SAA711X
- tristate "Philips SAA7113/4/5 video decoders"
- depends on VIDEO_DEV && I2C && EXPERIMENTAL
+ tristate "Philips SAA7113/4/5 video decoders (OBSOLETED)"
+ depends on VIDEO_V4L1 && I2C && EXPERIMENTAL
---help---
- Support for the Philips SAA7113/4/5 video decoders.
+ Old support for the Philips SAA7113/4 video decoders.
To compile this driver as a module, choose M here: the
- module will be called saa7115
+ module will be called saa7115.
config VIDEO_SAA7127
tristate "Philips SAA7127/9 digital video encoders"
- depends on VIDEO_DEV && I2C && EXPERIMENTAL
+ depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
---help---
Support for the Philips SAA7127/9 digital video encoders.
To compile this driver as a module, choose M here: the
- module will be called saa7127
+ module will be called saa7127.
+
+config VIDEO_UPD64031A
+ tristate "NEC Electronics uPD64031A Ghost Reduction"
+ depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+ ---help---
+ Support for the NEC Electronics uPD64031A Ghost Reduction
+ video chip. It is most often found in NTSC TV cards made for
+ Japan and is used to reduce the 'ghosting' effect that can
+ be present in analog TV broadcasts.
+
+ To compile this driver as a module, choose M here: the
+ module will be called upd64031a.
+
+config VIDEO_UPD64083
+ tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
+ depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+ ---help---
+ Support for the NEC Electronics uPD64083 3-Dimensional Y/C
+ separation video chip. It is used to improve the quality of
+ the colors of a composite signal.
+
+ To compile this driver as a module, choose M here: the
+ module will be called upd64083.
+
+endmenu # encoder / decoder chips
#
# USB Multimedia device configuration
@@ -374,157 +431,62 @@ menu "V4L USB devices"
source "drivers/media/video/em28xx/Kconfig"
-config USB_VICAM
- tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
- depends on USB && VIDEO_DEV && EXPERIMENTAL
- ---help---
- Say Y here if you have 3com homeconnect camera (vicam).
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Multimedia Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called vicam.
-
config USB_DSBR
tristate "D-Link USB FM radio support (EXPERIMENTAL)"
- depends on USB && VIDEO_DEV && EXPERIMENTAL
+ depends on USB && VIDEO_V4L1 && EXPERIMENTAL
---help---
Say Y here if you want to connect this type of radio to your
computer's USB port. Note that the audio is not digital, and
you must connect the line out connector to a sound card or a
set of speakers.
- This driver uses the Video For Linux API. You must enable
- (Y or M in config) Video For Linux (under Character Devices)
- to use this driver. Information on this API and pointers to
- "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
-
To compile this driver as a module, choose M here: the
module will be called dsbr100.
-config USB_ET61X251
- tristate "USB ET61X[12]51 PC Camera Controller support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want support for cameras based on Etoms ET61X151
- or ET61X251 PC Camera Controllers.
+source "drivers/media/video/usbvideo/Kconfig"
- See <file:Documentation/usb/et61x251.txt> for more informations.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" to use this driver.
-
- To compile this driver as a module, choose M here: the
- module will be called et61x251.
-
-config USB_IBMCAM
- tristate "USB IBM (Xirlink) C-it Camera support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want to connect a IBM "C-It" camera, also known as
- "Xirlink PC Camera" to your computer's USB port. For more
- information, read <file:Documentation/usb/ibmcam.txt>.
-
- This driver uses the Video For Linux API. You must enable
- (Y or M in config) Video For Linux (under Character Devices)
- to use this driver. Information on this API and pointers to
- "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called ibmcam.
-
- This camera has several configuration options which
- can be specified when you load the module. Read
- <file:Documentation/usb/ibmcam.txt> to learn more.
-
-config USB_KONICAWC
- tristate "USB Konica Webcam support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want support for webcams based on a Konica
- chipset. This is known to work with the Intel YC76 webcam.
-
- This driver uses the Video For Linux API. You must enable
- (Y or M in config) Video For Linux (under Character Devices)
- to use this driver. Information on this API and pointers to
- "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called konicawc.
+source "drivers/media/video/et61x251/Kconfig"
config USB_OV511
tristate "USB OV511 Camera support"
- depends on USB && VIDEO_DEV
+ depends on USB && VIDEO_V4L1
---help---
Say Y here if you want to connect this type of camera to your
- computer's USB port. See <file:Documentation/usb/ov511.txt> for more
- information and for a list of supported cameras.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Character Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
+ computer's USB port. See <file:Documentation/video4linux/ov511.txt>
+ for more information and for a list of supported cameras.
To compile this driver as a module, choose M here: the
module will be called ov511.
config USB_SE401
tristate "USB SE401 Camera support"
- depends on USB && VIDEO_DEV
+ depends on USB && VIDEO_V4L1
---help---
Say Y here if you want to connect this type of camera to your
- computer's USB port. See <file:Documentation/usb/se401.txt> for more
- information and for a list of supported cameras.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Multimedia Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
+ computer's USB port. See <file:Documentation/video4linux/se401.txt>
+ for more information and for a list of supported cameras.
To compile this driver as a module, choose M here: the
module will be called se401.
-config USB_SN9C102
- tristate "USB SN9C10x PC Camera Controller support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want support for cameras based on SONiX SN9C101,
- SN9C102 or SN9C103 PC Camera Controllers.
-
- See <file:Documentation/usb/sn9c102.txt> for more informations.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" to use this driver.
-
- To compile this driver as a module, choose M here: the
- module will be called sn9c102.
+source "drivers/media/video/sn9c102/Kconfig"
config USB_STV680
tristate "USB STV680 (Pencam) Camera support"
- depends on USB && VIDEO_DEV
+ depends on USB && VIDEO_V4L1
---help---
Say Y here if you want to connect this type of camera to your
computer's USB port. This includes the Pencam line of cameras.
- See <file:Documentation/usb/stv680.txt> for more information and for
- a list of supported cameras.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Multimedia Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
+ See <file:Documentation/video4linux/stv680.txt> for more information
+ and for a list of supported cameras.
To compile this driver as a module, choose M here: the
module will be called stv680.
config USB_W9968CF
tristate "USB W996[87]CF JPEG Dual Mode Camera support"
- depends on USB && VIDEO_DEV && I2C && VIDEO_OVCAMCHIP
+ depends on USB && VIDEO_V4L1 && I2C
+ select VIDEO_OVCAMCHIP
---help---
Say Y here if you want support for cameras based on OV681 or
Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
@@ -534,64 +496,14 @@ config USB_W9968CF
resolutions and framerates, but cannot be included in the official
Linux kernel for performance purposes.
- See <file:Documentation/usb/w9968cf.txt> for more informations.
-
- This driver uses the Video For Linux and the I2C APIs. It needs the
- OmniVision Camera Chip support as well. You must say Y or M to
- "Video For Linux", "I2C Support" and "OmniVision Camera Chip
- support" to use this driver.
+ See <file:Documentation/video4linux/w9968cf.txt> for more info.
To compile this driver as a module, choose M here: the
module will be called w9968cf.
-config USB_ZC0301
- tristate "USB ZC0301 Image Processor and Control Chip support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want support for cameras based on the ZC0301
- Image Processor and Control Chip.
-
- See <file:Documentation/usb/zc0301.txt> for more informations.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" to use this driver.
-
- To compile this driver as a module, choose M here: the
- module will be called zc0301.
+source "drivers/media/video/zc0301/Kconfig"
-config USB_PWC
- tristate "USB Philips Cameras"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y or M here if you want to use one of these Philips & OEM
- webcams:
- * Philips PCA645, PCA646
- * Philips PCVC675, PCVC680, PCVC690
- * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
- * Askey VC010
- * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
- and 'Orbit'/'Sphere'
- * Samsung MPC-C10, MPC-C30
- * Creative Webcam 5, Pro Ex
- * SOTEC Afina Eye
- * Visionite VCS-UC300, VCS-UM100
-
- The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
- and never will be, but the 665 and 720/20 are supported by other
- drivers.
-
- See <file:Documentation/usb/philips.txt> for more information and
- installation instructions.
-
- The built-in microphone is enabled by selecting USB Audio support.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Character Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called pwc.
+source "drivers/media/video/pwc/Kconfig"
endmenu # V4L USB devices
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 1c0e72e5a59..e5bf2687b76 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -10,7 +10,11 @@ tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \
msp3400-objs := msp3400-driver.o msp3400-kthreads.o
-obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o
+obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o
+
+ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y)
+ obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o
+endif
obj-$(CONFIG_VIDEO_BT848) += bt8xx/
obj-$(CONFIG_VIDEO_BT848) += tvaudio.o tda7432.o tda9875.o ir-kbd-i2c.o
@@ -45,6 +49,7 @@ obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o
obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
+obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
obj-$(CONFIG_VIDEO_MXB) += saa7111.o tda9840.o tea6415c.o tea6420.o mxb.o
@@ -64,9 +69,8 @@ obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
obj-$(CONFIG_VIDEO_CX25840) += cx25840/
obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
-
-et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o
-zc0301-objs := zc0301_core.o zc0301_pas202bcb.o
+obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
+obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
obj-$(CONFIG_USB_DABUSB) += dabusb.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
@@ -84,4 +88,8 @@ obj-$(CONFIG_USB_IBMCAM) += usbvideo/
obj-$(CONFIG_USB_KONICAWC) += usbvideo/
obj-$(CONFIG_USB_VICAM) += usbvideo/
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
+obj-$(CONFIG_VIDEO_VIVI) += vivi.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+extra-cflags-$(CONFIG_VIDEO_V4L1_COMPAT) += -DCONFIG_VIDEO_V4L1_COMPAT
+
diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig
index 085477c1261..153f6a4a96c 100644
--- a/drivers/media/video/bt8xx/Kconfig
+++ b/drivers/media/video/bt8xx/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_BT848
tristate "BT848 Video For Linux"
- depends on VIDEO_DEV && PCI && I2C
+ depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile
index 94350f21cdc..a096a03418a 100644
--- a/drivers/media/video/bt8xx/Makefile
+++ b/drivers/media/video/bt8xx/Makefile
@@ -8,5 +8,5 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
obj-$(CONFIG_VIDEO_BT848) += bttv.o
-EXTRA_CFLAGS += -I$(src)/..
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index f209a749205..2b64aa835b4 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -2991,13 +2991,13 @@ void __devinit bttv_idcard(struct bttv *btv)
if (UNSET != audiomux[0]) {
gpiobits = 0;
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < 4; i++) {
bttv_tvcards[btv->c.type].gpiomux[i] = audiomux[i];
gpiobits |= audiomux[i];
}
} else {
gpiobits = audioall;
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < 4; i++) {
bttv_tvcards[btv->c.type].gpiomux[i] = audioall;
}
}
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 74def9c2395..423e954948b 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -973,12 +973,12 @@ audio_mux(struct bttv *btv, int input, int mute)
For now this is sufficient. */
switch (input) {
case TVAUDIO_INPUT_RADIO:
- route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
- MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+ route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
+ MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
break;
case TVAUDIO_INPUT_EXTERN:
- route.input = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
- MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+ route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
+ MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
break;
case TVAUDIO_INPUT_INTERN:
/* Yes, this is the same input as for RADIO. I doubt
@@ -986,8 +986,8 @@ audio_mux(struct bttv *btv, int input, int mute)
input is the BTTV_BOARD_AVERMEDIA98. I wonder how
that was tested. My guess is that the whole INTERN
input does not work. */
- route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
- MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+ route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
+ MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
break;
case TVAUDIO_INPUT_TUNER:
default:
@@ -1023,14 +1023,11 @@ audio_input(struct bttv *btv, int input)
static void
i2c_vidiocschan(struct bttv *btv)
{
- struct video_channel c;
+ v4l2_std_id std = bttv_tvnorms[btv->tvnorm].v4l2_id;
- memset(&c,0,sizeof(c));
- c.norm = btv->tvnorm;
- c.channel = btv->input;
- bttv_call_i2c_clients(btv,VIDIOCSCHAN,&c);
+ bttv_call_i2c_clients(btv, VIDIOC_S_STD, &std);
if (btv->c.type == BTTV_BOARD_VOODOOTV_FM)
- bttv_tda9880_setnorm(btv,c.norm);
+ bttv_tda9880_setnorm(btv,btv->tvnorm);
}
static int
@@ -1184,11 +1181,27 @@ static int get_control(struct bttv *btv, struct v4l2_control *c)
break;
if (i == BTTV_CTLS)
return -EINVAL;
- if (i >= 4 && i <= 8) {
+ if (btv->audio_hook && i >= 4 && i <= 8) {
memset(&va,0,sizeof(va));
- bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
- if (btv->audio_hook)
- btv->audio_hook(btv,&va,0);
+ btv->audio_hook(btv,&va,0);
+ switch (c->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0;
+ break;
+ case V4L2_CID_AUDIO_VOLUME:
+ c->value = va.volume;
+ break;
+ case V4L2_CID_AUDIO_BALANCE:
+ c->value = va.balance;
+ break;
+ case V4L2_CID_AUDIO_BASS:
+ c->value = va.bass;
+ break;
+ case V4L2_CID_AUDIO_TREBLE:
+ c->value = va.treble;
+ break;
+ }
+ return 0;
}
switch (c->id) {
case V4L2_CID_BRIGHTNESS:
@@ -1205,19 +1218,11 @@ static int get_control(struct bttv *btv, struct v4l2_control *c)
break;
case V4L2_CID_AUDIO_MUTE:
- c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0;
- break;
case V4L2_CID_AUDIO_VOLUME:
- c->value = va.volume;
- break;
case V4L2_CID_AUDIO_BALANCE:
- c->value = va.balance;
- break;
case V4L2_CID_AUDIO_BASS:
- c->value = va.bass;
- break;
case V4L2_CID_AUDIO_TREBLE:
- c->value = va.treble;
+ bttv_call_i2c_clients(btv,VIDIOC_G_CTRL,c);
break;
case V4L2_CID_PRIVATE_CHROMA_AGC:
@@ -1269,11 +1274,35 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
break;
if (i == BTTV_CTLS)
return -EINVAL;
- if (i >= 4 && i <= 8) {
+ if (btv->audio_hook && i >= 4 && i <= 8) {
memset(&va,0,sizeof(va));
- bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
- if (btv->audio_hook)
- btv->audio_hook(btv,&va,0);
+ btv->audio_hook(btv,&va,0);
+ switch (c->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ if (c->value) {
+ va.flags |= VIDEO_AUDIO_MUTE;
+ audio_mute(btv, 1);
+ } else {
+ va.flags &= ~VIDEO_AUDIO_MUTE;
+ audio_mute(btv, 0);
+ }
+ break;
+
+ case V4L2_CID_AUDIO_VOLUME:
+ va.volume = c->value;
+ break;
+ case V4L2_CID_AUDIO_BALANCE:
+ va.balance = c->value;
+ break;
+ case V4L2_CID_AUDIO_BASS:
+ va.bass = c->value;
+ break;
+ case V4L2_CID_AUDIO_TREBLE:
+ va.treble = c->value;
+ break;
+ }
+ btv->audio_hook(btv,&va,1);
+ return 0;
}
switch (c->id) {
case V4L2_CID_BRIGHTNESS:
@@ -1289,26 +1318,13 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
bt848_sat(btv,c->value);
break;
case V4L2_CID_AUDIO_MUTE:
- if (c->value) {
- va.flags |= VIDEO_AUDIO_MUTE;
- audio_mute(btv, 1);
- } else {
- va.flags &= ~VIDEO_AUDIO_MUTE;
- audio_mute(btv, 0);
- }
- break;
-
+ audio_mute(btv, c->value);
+ /* fall through */
case V4L2_CID_AUDIO_VOLUME:
- va.volume = c->value;
- break;
case V4L2_CID_AUDIO_BALANCE:
- va.balance = c->value;
- break;
case V4L2_CID_AUDIO_BASS:
- va.bass = c->value;
- break;
case V4L2_CID_AUDIO_TREBLE:
- va.treble = c->value;
+ bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c);
break;
case V4L2_CID_PRIVATE_CHROMA_AGC:
@@ -1364,11 +1380,6 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
default:
return -EINVAL;
}
- if (i >= 4 && i <= 8) {
- bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va);
- if (btv->audio_hook)
- btv->audio_hook(btv,&va,1);
- }
return 0;
}
@@ -1591,12 +1602,16 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
}
case VIDIOCSFREQ:
{
- unsigned long *freq = arg;
+ struct v4l2_frequency freq;
+
+ memset(&freq, 0, sizeof(freq));
+ freq.frequency = *(unsigned long *)arg;
mutex_lock(&btv->lock);
- btv->freq=*freq;
- bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq);
+ freq.type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+ btv->freq = *(unsigned long *)arg;
+ bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,&freq);
if (btv->has_matchbox && btv->radio_user)
- tea5757_set_freq(btv,*freq);
+ tea5757_set_freq(btv,*(unsigned long *)arg);
mutex_unlock(&btv->lock);
return 0;
}
@@ -1827,33 +1842,26 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
mutex_lock(&btv->lock);
memset(t,0,sizeof(*t));
+ t->rxsubchans = V4L2_TUNER_SUB_MONO;
+ bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
strcpy(t->name, "Television");
- t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM;
- t->rxsubchans = V4L2_TUNER_SUB_MONO;
+ t->type = V4L2_TUNER_ANALOG_TV;
if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
t->signal = 0xffff;
- {
- struct video_tuner tuner;
-
- memset(&tuner, 0, sizeof (tuner));
- tuner.rangehigh = 0xffffffffUL;
- bttv_call_i2c_clients(btv, VIDIOCGTUNER, &tuner);
- t->rangelow = tuner.rangelow;
- t->rangehigh = tuner.rangehigh;
- }
- {
+
+ if (btv->audio_hook) {
/* Hmmm ... */
struct video_audio va;
memset(&va, 0, sizeof(struct video_audio));
- bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
- if (btv->audio_hook)
- btv->audio_hook(btv,&va,0);
+ btv->audio_hook(btv,&va,0);
+ t->audmode = V4L2_TUNER_MODE_MONO;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO;
if(va.mode & VIDEO_SOUND_STEREO) {
- t->audmode = V4L2_TUNER_MODE_STEREO;
- t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ t->audmode = V4L2_TUNER_MODE_STEREO;
+ t->rxsubchans = V4L2_TUNER_SUB_STEREO;
}
- if(va.mode & VIDEO_SOUND_LANG1) {
+ if(va.mode & VIDEO_SOUND_LANG2) {
t->audmode = V4L2_TUNER_MODE_LANG1;
t->rxsubchans = V4L2_TUNER_SUB_LANG1
| V4L2_TUNER_SUB_LANG2;
@@ -1872,10 +1880,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (0 != t->index)
return -EINVAL;
mutex_lock(&btv->lock);
- {
+ bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t);
+ if (btv->audio_hook) {
struct video_audio va;
memset(&va, 0, sizeof(struct video_audio));
- bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
if (t->audmode == V4L2_TUNER_MODE_MONO)
va.mode = VIDEO_SOUND_MONO;
else if (t->audmode == V4L2_TUNER_MODE_STEREO ||
@@ -1885,9 +1893,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
va.mode = VIDEO_SOUND_LANG1;
else if (t->audmode == V4L2_TUNER_MODE_LANG2)
va.mode = VIDEO_SOUND_LANG2;
- bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va);
- if (btv->audio_hook)
- btv->audio_hook(btv,&va,1);
+ btv->audio_hook(btv,&va,1);
}
mutex_unlock(&btv->lock);
return 0;
@@ -1912,7 +1918,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
mutex_lock(&btv->lock);
btv->freq = f->frequency;
- bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq);
+ bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,f);
if (btv->has_matchbox && btv->radio_user)
tea5757_set_freq(btv,btv->freq);
mutex_unlock(&btv->lock);
@@ -1920,7 +1926,9 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
}
case VIDIOC_LOG_STATUS:
{
+ printk(KERN_INFO "bttv%d: ================= START STATUS CARD #%d =================\n", btv->c.nr, btv->c.nr);
bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
+ printk(KERN_INFO "bttv%d: ================== END STATUS CARD #%d ==================\n", btv->c.nr, btv->c.nr);
return 0;
}
@@ -2870,12 +2878,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
return 0;
}
*c = bttv_ctls[i];
- if (i >= 4 && i <= 8) {
+ if (btv->audio_hook && i >= 4 && i <= 8) {
struct video_audio va;
memset(&va,0,sizeof(va));
- bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
- if (btv->audio_hook)
- btv->audio_hook(btv,&va,0);
+ btv->audio_hook(btv,&va,0);
switch (bttv_ctls[i].id) {
case V4L2_CID_AUDIO_VOLUME:
if (!(va.flags & VIDEO_AUDIO_VOLUME))
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c
index 16323a5d68a..afcfe71e379 100644
--- a/drivers/media/video/bt8xx/bttv-risc.c
+++ b/drivers/media/video/bt8xx/bttv-risc.c
@@ -233,7 +233,7 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
const struct bttv_format *fmt, struct bttv_overlay *ov,
int skip_even, int skip_odd)
{
- int instructions,rc,line,maxy,start,end,skip,nskips;
+ int dwords,rc,line,maxy,start,end,skip,nskips;
struct btcx_skiplist *skips;
u32 *rp,ri,ra;
u32 addr;
@@ -242,12 +242,12 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
return -ENOMEM;
- /* estimate risc mem: worst case is (clip+1) * lines instructions
+ /* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
+ sync + jump (all 2 dwords) */
- instructions = (ov->nclips + 1) *
- ((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height);
- instructions += 2;
- if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) {
+ dwords = (3 * ov->nclips + 2) *
+ ((skip_even || skip_odd) ? (ov->w.height+1)>>1 : ov->w.height);
+ dwords += 4;
+ if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {
kfree(skips);
return rc;
}
@@ -276,8 +276,6 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
if (line > maxy)
btcx_calc_skips(line, ov->w.width, &maxy,
skips, &nskips, ov->clips, ov->nclips);
- else
- nskips = 0;
/* write out risc code */
for (start = 0, skip = 0; start < ov->w.width; start = end) {
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index e20ff238e40..8c9f0f7cf46 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -184,7 +184,7 @@ void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f)
- tvnorm->vbistart[0];
count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1]
- tvnorm->vbistart[1];
- count = clamp (max (count0, count1), 1LL, (s64) VBI_MAXLINES);
+ count = clamp (max (count0, count1), (s64) 1, (s64) VBI_MAXLINES);
f->fmt.vbi.start[0] = tvnorm->vbistart[0];
f->fmt.vbi.start[1] = tvnorm->vbistart[1];
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 2227c5640c1..85d84e89d8f 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -64,14 +64,13 @@ MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("video");
#endif
-static unsigned short colorspace_conv = 0;
+static unsigned short colorspace_conv;
module_param(colorspace_conv, ushort, 0444);
MODULE_PARM_DESC(colorspace_conv,
- "\n<n> Colorspace conversion:"
- "\n0 = disable"
- "\n1 = enable"
- "\nDefault value is 0"
- "\n");
+ " Colorspace conversion:"
+ "\n 0 = disable, 1 = enable"
+ "\n Default value is 0"
+ );
#define ABOUT "V4L-Driver for Vision CPiA based cameras"
@@ -4042,7 +4041,7 @@ static int __init cpia_init(void)
"allowed, it is disabled by default now. Users should fix the "
"applications in case they don't work without conversion "
"reenabled by setting the 'colorspace_conv' module "
- "parameter to 1");
+ "parameter to 1\n");
#ifdef CONFIG_PROC_FS
proc_cpia_create();
diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h
index 8394283993f..1764991b0ac 100644
--- a/drivers/media/video/cpia2/cpia2.h
+++ b/drivers/media/video/cpia2/cpia2.h
@@ -456,7 +456,7 @@ int cpia2_init_camera(struct camera_data *cam);
int cpia2_allocate_buffers(struct camera_data *cam);
void cpia2_free_buffers(struct camera_data *cam);
long cpia2_read(struct camera_data *cam,
- char *buf, unsigned long count, int noblock);
+ char __user *buf, unsigned long count, int noblock);
unsigned int cpia2_poll(struct camera_data *cam,
struct file *filp, poll_table *wait);
int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma);
diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c
index 3021f21aae3..0b00e6027df 100644
--- a/drivers/media/video/cpia_pp.c
+++ b/drivers/media/video/cpia_pp.c
@@ -873,7 +873,7 @@ static int __init cpia_pp_setup(char *str)
parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE;
}
- return 0;
+ return 1;
}
__setup("cpia_pp=", cpia_pp_setup);
diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/video/cx25840/Makefile
index 32a896c23d1..6e8665be895 100644
--- a/drivers/media/video/cx25840/Makefile
+++ b/drivers/media/video/cx25840/Makefile
@@ -3,4 +3,4 @@ cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \
obj-$(CONFIG_VIDEO_CX25840) += cx25840.o
-EXTRA_CFLAGS += -I$(src)/..
+EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index a4540e858f2..9a4b813152e 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -19,8 +19,9 @@
#include <linux/videodev2.h>
#include <linux/i2c.h>
#include <media/v4l2-common.h>
+#include <media/cx25840.h>
-#include "cx25840.h"
+#include "cx25840-core.h"
static int set_audclk_freq(struct i2c_client *client, u32 freq)
{
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index a65b3cc4bf0..a961bb2ab0f 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -32,8 +32,9 @@
#include <linux/videodev2.h>
#include <linux/i2c.h>
#include <media/v4l2-common.h>
+#include <media/cx25840.h>
-#include "cx25840.h"
+#include "cx25840-core.h"
MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver");
MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford");
@@ -668,6 +669,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
{
struct cx25840_state *state = i2c_get_clientdata(client);
struct v4l2_tuner *vt = arg;
+ struct v4l2_routing *route = arg;
switch (cmd) {
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -749,19 +751,21 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
state->radio = 1;
break;
- case VIDIOC_G_INPUT:
- *(int *)arg = state->vid_input;
+ case VIDIOC_INT_G_VIDEO_ROUTING:
+ route->input = state->vid_input;
+ route->output = 0;
break;
- case VIDIOC_S_INPUT:
- return set_input(client, *(enum cx25840_video_input *)arg, state->aud_input);
+ case VIDIOC_INT_S_VIDEO_ROUTING:
+ return set_input(client, route->input, state->aud_input);
- case VIDIOC_S_AUDIO:
- {
- struct v4l2_audio *input = arg;
+ case VIDIOC_INT_G_AUDIO_ROUTING:
+ route->input = state->aud_input;
+ route->output = 0;
+ break;
- return set_input(client, state->vid_input, input->index);
- }
+ case VIDIOC_INT_S_AUDIO_ROUTING:
+ return set_input(client, state->vid_input, route->input);
case VIDIOC_S_FREQUENCY:
input_change(client);
diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840-core.h
index dd70664d1dd..1736929fc20 100644
--- a/drivers/media/video/cx25840/cx25840.h
+++ b/drivers/media/video/cx25840/cx25840-core.h
@@ -1,4 +1,4 @@
-/* cx25840 API header
+/* cx25840 internal API header
*
* Copyright (C) 2003-2004 Chris Kennedy
*
@@ -17,8 +17,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef _CX25840_H_
-#define _CX25840_H_
+#ifndef _CX25840_CORE_H_
+#define _CX25840_CORE_H_
#include <linux/videodev2.h>
@@ -32,46 +32,6 @@
providing this information. */
#define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0)
-enum cx25840_video_input {
- /* Composite video inputs In1-In8 */
- CX25840_COMPOSITE1 = 1,
- CX25840_COMPOSITE2,
- CX25840_COMPOSITE3,
- CX25840_COMPOSITE4,
- CX25840_COMPOSITE5,
- CX25840_COMPOSITE6,
- CX25840_COMPOSITE7,
- CX25840_COMPOSITE8,
-
- /* S-Video inputs consist of one luma input (In1-In4) ORed with one
- chroma input (In5-In8) */
- CX25840_SVIDEO_LUMA1 = 0x10,
- CX25840_SVIDEO_LUMA2 = 0x20,
- CX25840_SVIDEO_LUMA3 = 0x30,
- CX25840_SVIDEO_LUMA4 = 0x40,
- CX25840_SVIDEO_CHROMA4 = 0x400,
- CX25840_SVIDEO_CHROMA5 = 0x500,
- CX25840_SVIDEO_CHROMA6 = 0x600,
- CX25840_SVIDEO_CHROMA7 = 0x700,
- CX25840_SVIDEO_CHROMA8 = 0x800,
-
- /* S-Video aliases for common luma/chroma combinations */
- CX25840_SVIDEO1 = 0x510,
- CX25840_SVIDEO2 = 0x620,
- CX25840_SVIDEO3 = 0x730,
- CX25840_SVIDEO4 = 0x840,
-};
-
-enum cx25840_audio_input {
- /* Audio inputs: serial or In4-In8 */
- CX25840_AUDIO_SERIAL,
- CX25840_AUDIO4 = 4,
- CX25840_AUDIO5,
- CX25840_AUDIO6,
- CX25840_AUDIO7,
- CX25840_AUDIO8,
-};
-
struct cx25840_state {
int pvr150_workaround;
int radio;
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c
index e1a7823d82c..1958d4016ea 100644
--- a/drivers/media/video/cx25840/cx25840-firmware.c
+++ b/drivers/media/video/cx25840/cx25840-firmware.c
@@ -20,37 +20,31 @@
#include <linux/i2c-algo-bit.h>
#include <linux/firmware.h>
#include <media/v4l2-common.h>
+#include <media/cx25840.h>
-#include "cx25840.h"
+#include "cx25840-core.h"
#define FWFILE "v4l-cx25840.fw"
-#define FWSEND 1024
+
+/*
+ * Mike Isely <isely@pobox.com> - The FWSEND parameter controls the
+ * size of the firmware chunks sent down the I2C bus to the chip.
+ * Previously this had been set to 1024 but unfortunately some I2C
+ * implementations can't transfer data in such big gulps.
+ * Specifically, the pvrusb2 driver has a hard limit of around 60
+ * bytes, due to the encapsulation there of I2C traffic into USB
+ * messages. So we have to significantly reduce this parameter.
+ */
+#define FWSEND 48
#define FWDEV(x) &((x)->adapter->dev)
-static int fastfw = 1;
static char *firmware = FWFILE;
-module_param(fastfw, bool, 0444);
module_param(firmware, charp, 0444);
-MODULE_PARM_DESC(fastfw, "Load firmware fast [0=100MHz 1=333MHz (default)]");
MODULE_PARM_DESC(firmware, "Firmware image [default: " FWFILE "]");
-static void set_i2c_delay(struct i2c_client *client, int delay)
-{
- struct i2c_algo_bit_data *algod = client->adapter->algo_data;
-
- /* We aren't guaranteed to be using algo_bit,
- * so avoid the null pointer dereference
- * and disable the 'fast firmware load' */
- if (algod) {
- algod->udelay = delay;
- } else {
- fastfw = 0;
- }
-}
-
static void start_fw_load(struct i2c_client *client)
{
/* DL_ADDR_LB=0 DL_ADDR_HB=0 */
@@ -60,16 +54,10 @@ static void start_fw_load(struct i2c_client *client)
cx25840_write(client, 0x803, 0x0b);
/* AUTO_INC_DIS=1 */
cx25840_write(client, 0x000, 0x20);
-
- if (fastfw)
- set_i2c_delay(client, 3);
}
static void end_fw_load(struct i2c_client *client)
{
- if (fastfw)
- set_i2c_delay(client, 10);
-
/* AUTO_INC_DIS=0 */
cx25840_write(client, 0x000, 0x00);
/* DL_ENABLE=0 */
@@ -96,30 +84,8 @@ static int fw_write(struct i2c_client *client, u8 * data, int size)
int sent;
if ((sent = i2c_master_send(client, data, size)) < size) {
-
- if (fastfw) {
- v4l_err(client, "333MHz i2c firmware load failed\n");
- fastfw = 0;
- set_i2c_delay(client, 10);
-
- if (sent > 2) {
- u16 dl_addr = cx25840_read(client, 0x801) << 8;
- dl_addr |= cx25840_read(client, 0x800);
- dl_addr -= sent - 2;
- cx25840_write(client, 0x801, dl_addr >> 8);
- cx25840_write(client, 0x800, dl_addr & 0xff);
- }
-
- if (i2c_master_send(client, data, size) < size) {
- v4l_err(client, "100MHz i2c firmware load failed\n");
- return -ENOSYS;
- }
-
- } else {
- v4l_err(client, "firmware load i2c failure\n");
- return -ENOSYS;
- }
-
+ v4l_err(client, "firmware load i2c failure\n");
+ return -ENOSYS;
}
return 0;
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
index e96fd1f1d6d..57feca288d2 100644
--- a/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/drivers/media/video/cx25840/cx25840-vbi.c
@@ -19,8 +19,9 @@
#include <linux/videodev2.h>
#include <linux/i2c.h>
#include <media/v4l2-common.h>
+#include <media/cx25840.h>
-#include "cx25840.h"
+#include "cx25840-core.h"
static int odd_parity(u8 c)
{
@@ -151,7 +152,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
case VIDIOC_G_FMT:
{
static u16 lcr2vbi[] = {
- 0, V4L2_SLICED_TELETEXT_PAL_B, 0, /* 1 */
+ 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
0, V4L2_SLICED_WSS_625, 0, /* 4 */
V4L2_SLICED_CAPTION_525, /* 6 */
0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */
@@ -231,7 +232,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
for (i = 7; i <= 23; i++) {
for (x = 0; x <= 1; x++) {
switch (svbi->service_lines[1-x][i]) {
- case V4L2_SLICED_TELETEXT_PAL_B:
+ case V4L2_SLICED_TELETEXT_B:
lcr[i] |= 1 << (4 * x);
break;
case V4L2_SLICED_WSS_625:
@@ -282,7 +283,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
switch (id2) {
case 1:
- id2 = V4L2_SLICED_TELETEXT_PAL_B;
+ id2 = V4L2_SLICED_TELETEXT_B;
break;
case 4:
id2 = V4L2_SLICED_WSS_625;
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index ff0f72340d6..630273992a4 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -1,3 +1,7 @@
+config VIDEO_CX88_VP3054
+ tristate
+ depends on VIDEO_CX88_DVB && DVB_MT352
+
config VIDEO_CX88
tristate "Conexant 2388x (bt878 successor) support"
depends on VIDEO_DEV && PCI && I2C
@@ -25,7 +29,7 @@ config VIDEO_CX88_ALSA
It only works with boards with function 01 enabled.
To check if your board supports, use lspci -n.
- If supported, you should see 1471:8801 or 1471:8811
+ If supported, you should see 14f1:8801 or 14f1:8811
PCI device.
To compile this driver as a module, choose M here: the
@@ -73,10 +77,11 @@ config VIDEO_CX88_DVB_MT352
This adds DVB-T support for cards based on the
Connexant 2388x chip and the MT352 demodulator.
-config VIDEO_CX88_VP3054
- tristate "VP-3054 Secondary I2C Bus Support"
- default m
- depends on DVB_MT352
+config VIDEO_CX88_DVB_VP3054
+ bool "VP-3054 Secondary I2C Bus Support"
+ default y
+ depends on VIDEO_CX88_DVB_MT352
+ select VIDEO_CX88_VP3054
---help---
This adds DVB-T support for cards based on the
Connexant 2388x chip and the MT352 demodulator,
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 6482b9aa6a1..0dcd09b9b72 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -8,9 +8,9 @@ obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
-EXTRA_CFLAGS += -I$(src)/..
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
extra-cflags-$(CONFIG_DVB_CX22702) += -DHAVE_CX22702=1
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index f9d87b86492..320b3d9384b 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -616,7 +616,7 @@ static struct snd_kcontrol_new snd_cx88_capture_volume = {
* Only boards with eeprom and byte 1 at eeprom=1 have it
*/
-static struct pci_device_id cx88_audio_pci_tbl[] = {
+static struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = {
{0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
{0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
{0, }
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index c7042cf4123..f80154b87d2 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -564,7 +564,7 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_PCHDTV_HD3000] = {
.name = "pcHDTV HD3000 HDTV",
- .tuner_type = TUNER_THOMSON_DTT7610,
+ .tuner_type = TUNER_THOMSON_DTT761X,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 2c3d9f1999b..e1092d5d462 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -146,9 +146,11 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
fields++;
/* estimate risc mem: worst case is one write per page border +
- one write per scan line + syncs + jump (all 2 dwords) */
- instructions = (bpl * lines * fields) / PAGE_SIZE + lines * fields;
- instructions += 3 + 4;
+ one write per scan line + syncs + jump (all 2 dwords). Padding
+ can cause next bpl to start close to a page border. First DMA
+ region may be smaller than PAGE_SIZE */
+ instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+ instructions += 2;
if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
return rc;
@@ -176,9 +178,11 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
int rc;
/* estimate risc mem: worst case is one write per page border +
- one write per scan line + syncs + jump (all 2 dwords) */
- instructions = (bpl * lines) / PAGE_SIZE + lines;
- instructions += 3 + 4;
+ one write per scan line + syncs + jump (all 2 dwords). Here
+ there is no padding and no sync. First DMA region may be smaller
+ than PAGE_SIZE */
+ instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
+ instructions += 1;
if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
return rc;
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index f0ea9b5cdbc..3619a449aef 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -372,7 +372,7 @@ static int or51132_set_ts_param(struct dvb_frontend* fe,
static struct or51132_config pchdtv_hd3000 = {
.demod_address = 0x15,
.pll_address = 0x61,
- .pll_desc = &dvb_pll_thomson_dtt7610,
+ .pll_desc = &dvb_pll_thomson_dtt761x,
.set_ts_params = or51132_set_ts_param,
};
#endif
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 72a417b3174..694d1d80ff3 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -35,8 +35,10 @@
#include "cx88.h"
#include <media/v4l2-common.h>
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
/* Include V4L1 specific functions. Should be removed soon */
#include <linux/videodev.h>
+#endif
MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
index 5a793ae7cc2..dfb15bfb83d 100644
--- a/drivers/media/video/em28xx/Kconfig
+++ b/drivers/media/video/em28xx/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_EM28XX
tristate "Empia EM2800/2820/2840 USB video capture support"
- depends on VIDEO_DEV && USB && I2C
+ depends on VIDEO_V4L1 && USB && I2C
select VIDEO_BUF
select VIDEO_TUNER
select VIDEO_TVEEPROM
diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile
index da457a05b0d..826d0e34075 100644
--- a/drivers/media/video/em28xx/Makefile
+++ b/drivers/media/video/em28xx/Makefile
@@ -3,4 +3,4 @@ em28xx-objs := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \
obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
-EXTRA_CFLAGS += -I$(src)/..
+EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index f62fd706b45..3ba3439db58 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -151,8 +151,8 @@ struct em28xx_board em28xx_boards[] = {
},{
.type = EM28XX_VMUX_SVIDEO,
.vmux = 2,
- .amux = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
- MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART),
+ .amux = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
+ MSP_DSP_IN_SCART, MSP_DSP_IN_SCART),
}},
},
[EM2820_BOARD_MSI_VOX_USB_2] = {
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index dfba33d0fa6..cf7cdf9ef61 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -222,7 +222,7 @@ static void video_mux(struct em28xx *dev, int index)
if (dev->i2s_speed)
em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
route.input = dev->ctl_ainput;
- route.output = MSP_OUTPUT(MSP_OUT_SCART1_DA);
+ route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
/* Note: this is msp3400 specific */
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
ainput = EM28XX_AUDIO_SRC_TUNER;
@@ -1141,26 +1141,16 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *t = arg;
- int status = 0;
if (0 != t->index)
return -EINVAL;
memset(t, 0, sizeof(*t));
strcpy(t->name, "Tuner");
- t->type = V4L2_TUNER_ANALOG_TV;
- t->capability = V4L2_TUNER_CAP_NORM;
- t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */
-/* t->signal = 0xffff;*/
-/* em28xx_i2c_call_clients(dev,VIDIOC_G_TUNER,t);*/
- /* No way to get signal strength? */
mutex_lock(&dev->lock);
- em28xx_i2c_call_clients(dev, DECODER_GET_STATUS,
- &status);
+ /* let clients fill in the remainder of this struct */
+ em28xx_i2c_call_clients(dev, cmd, t);
mutex_unlock(&dev->lock);
- t->signal =
- (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0;
-
em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x\n", t->signal,
t->afc);
return 0;
@@ -1168,26 +1158,13 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_S_TUNER:
{
struct v4l2_tuner *t = arg;
- int status = 0;
if (0 != t->index)
return -EINVAL;
- memset(t, 0, sizeof(*t));
- strcpy(t->name, "Tuner");
- t->type = V4L2_TUNER_ANALOG_TV;
- t->capability = V4L2_TUNER_CAP_NORM;
- t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */
-/* t->signal = 0xffff; */
- /* No way to get signal strength? */
mutex_lock(&dev->lock);
- em28xx_i2c_call_clients(dev, DECODER_GET_STATUS,
- &status);
+ /* let clients handle this */
+ em28xx_i2c_call_clients(dev, cmd, t);
mutex_unlock(&dev->lock);
- t->signal =
- (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0;
-
- em28xx_videodbg("VIDIO_S_TUNER: signal=%x, afc=%x\n",
- t->signal, t->afc);
return 0;
}
case VIDIOC_G_FREQUENCY:
@@ -1599,8 +1576,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
errCode = em28xx_config(dev);
if (errCode) {
em28xx_errdev("error configuring device\n");
- kfree(dev);
em28xx_devused&=~(1<<dev->devno);
+ kfree(dev);
return -ENOMEM;
}
@@ -1626,8 +1603,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->vdev = video_device_alloc();
if (NULL == dev->vdev) {
em28xx_errdev("cannot allocate video_device.\n");
- kfree(dev);
em28xx_devused&=~(1<<dev->devno);
+ kfree(dev);
return -ENOMEM;
}
@@ -1635,8 +1612,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
if (NULL == dev->vbi_dev) {
em28xx_errdev("cannot allocate video_device.\n");
kfree(dev->vdev);
- kfree(dev);
em28xx_devused&=~(1<<dev->devno);
+ kfree(dev);
return -ENOMEM;
}
@@ -1673,8 +1650,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
mutex_unlock(&dev->lock);
list_del(&dev->devlist);
video_device_release(dev->vdev);
- kfree(dev);
em28xx_devused&=~(1<<dev->devno);
+ kfree(dev);
return -ENODEV;
}
@@ -1685,8 +1662,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
list_del(&dev->devlist);
video_device_release(dev->vbi_dev);
video_device_release(dev->vdev);
- kfree(dev);
em28xx_devused&=~(1<<dev->devno);
+ kfree(dev);
return -ENODEV;
} else {
printk("registered VBI\n");
diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig
new file mode 100644
index 00000000000..c6bff705688
--- /dev/null
+++ b/drivers/media/video/et61x251/Kconfig
@@ -0,0 +1,14 @@
+config USB_ET61X251
+ tristate "USB ET61X[12]51 PC Camera Controller support"
+ depends on USB && VIDEO_V4L1
+ ---help---
+ Say Y here if you want support for cameras based on Etoms ET61X151
+ or ET61X251 PC Camera Controllers.
+
+ See <file:Documentation/video4linux/et61x251.txt> for more info.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" to use this driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called et61x251.
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 95bacf43541..7e66d83fe0c 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -411,6 +411,9 @@ static int ir_probe(struct i2c_adapter *adap)
case I2C_HW_B_BT848:
probe = probe_bttv;
break;
+ case I2C_HW_B_CX2341X:
+ probe = probe_bttv;
+ break;
case I2C_HW_SAA7134:
probe = probe_saa7134;
break;
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index c40e8ba9a2e..b806999d6e0 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -279,20 +279,8 @@ void msp_set_scart(struct i2c_client *client, int in, int out)
msp_write_dsp(client, 0x13, state->acb);
/* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */
- msp_write_dem(client, 0x40, state->i2s_mode);
-}
-
-void msp_set_mute(struct i2c_client *client)
-{
- struct msp_state *state = i2c_get_clientdata(client);
-
- v4l_dbg(1, msp_debug, client, "mute audio\n");
- msp_write_dsp(client, 0x0000, 0);
- msp_write_dsp(client, 0x0007, 1);
- if (state->has_scart2_out_volume)
- msp_write_dsp(client, 0x0040, 1);
- if (state->has_headphones)
- msp_write_dsp(client, 0x0006, 0);
+ if (state->has_i2s_conf)
+ msp_write_dem(client, 0x40, state->i2s_mode);
}
void msp_set_audio(struct i2c_client *client)
@@ -300,17 +288,19 @@ void msp_set_audio(struct i2c_client *client)
struct msp_state *state = i2c_get_clientdata(client);
int bal = 0, bass, treble, loudness;
int val = 0;
+ int reallymuted = state->muted | state->scan_in_progress;
- if (!state->muted)
+ if (!reallymuted)
val = (state->volume * 0x7f / 65535) << 8;
- v4l_dbg(1, msp_debug, client, "mute=%s volume=%d\n",
- state->muted ? "on" : "off", state->volume);
+ v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n",
+ state->muted ? "on" : "off", state->scan_in_progress ? "yes" : "no",
+ state->volume);
msp_write_dsp(client, 0x0000, val);
- msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1));
+ msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1));
if (state->has_scart2_out_volume)
- msp_write_dsp(client, 0x0040, state->muted ? 0x1 : (val | 0x1));
+ msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1));
if (state->has_headphones)
msp_write_dsp(client, 0x0006, val);
if (!state->has_sound_processing)
@@ -346,7 +336,6 @@ static void msp_wake_thread(struct i2c_client *client)
if (NULL == state->kthread)
return;
- msp_set_mute(client);
state->watch_stereo = 0;
state->restart = 1;
wake_up_interruptible(&state->wq);
@@ -374,19 +363,15 @@ int msp_sleep(struct msp_state *state, int timeout)
/* ------------------------------------------------------------------------ */
-static int msp_mode_v4l2_to_v4l1(int rxsubchans)
+static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode)
{
- int mode = 0;
-
- if (rxsubchans & V4L2_TUNER_SUB_STEREO)
- mode |= VIDEO_SOUND_STEREO;
- if (rxsubchans & V4L2_TUNER_SUB_LANG2)
- mode |= VIDEO_SOUND_LANG2 | VIDEO_SOUND_STEREO;
- if (rxsubchans & V4L2_TUNER_SUB_LANG1)
- mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_STEREO;
- if (mode == 0)
- mode |= VIDEO_SOUND_MONO;
- return mode;
+ if (rxsubchans == V4L2_TUNER_SUB_MONO)
+ return VIDEO_SOUND_MONO;
+ if (rxsubchans == V4L2_TUNER_SUB_STEREO)
+ return VIDEO_SOUND_STEREO;
+ if (audmode == V4L2_TUNER_MODE_LANG2)
+ return VIDEO_SOUND_LANG2;
+ return VIDEO_SOUND_LANG1;
}
static int msp_mode_v4l1_to_v4l2(int mode)
@@ -605,7 +590,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
break;
if (state->opmode == OPMODE_AUTOSELECT)
msp_detect_stereo(client);
- va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans);
+ va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans, state->audmode);
break;
}
@@ -620,7 +605,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
state->treble = va->treble;
msp_set_audio(client);
- if (va->mode != 0 && state->radio == 0) {
+ if (va->mode != 0 && state->radio == 0 &&
+ state->audmode != msp_mode_v4l1_to_v4l2(va->mode)) {
state->audmode = msp_mode_v4l1_to_v4l2(va->mode);
msp_set_audmode(client);
}
@@ -687,21 +673,23 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
int sc_in = rt->input & 0x7;
int sc1_out = rt->output & 0xf;
int sc2_out = (rt->output >> 4) & 0xf;
- u16 val;
+ u16 val, reg;
+ if (state->routing.input == rt->input &&
+ state->routing.output == rt->output)
+ break;
state->routing = *rt;
- if (state->opmode == OPMODE_AUTOSELECT) {
- val = msp_read_dem(client, 0x30) & ~0x100;
- msp_write_dem(client, 0x30, val | (tuner ? 0x100 : 0));
- } else {
- val = msp_read_dem(client, 0xbb) & ~0x100;
- msp_write_dem(client, 0xbb, val | (tuner ? 0x100 : 0));
- }
msp_set_scart(client, sc_in, 0);
msp_set_scart(client, sc1_out, 1);
msp_set_scart(client, sc2_out, 2);
msp_set_audmode(client);
- msp_wake_thread(client);
+ reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb;
+ val = msp_read_dem(client, reg);
+ if (tuner != ((val >> 8) & 1)) {
+ msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8));
+ /* wake thread when a new tuner input is chosen */
+ msp_wake_thread(client);
+ }
break;
}
@@ -715,7 +703,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
msp_detect_stereo(client);
vt->audmode = state->audmode;
vt->rxsubchans = state->rxsubchans;
- vt->capability = V4L2_TUNER_CAP_STEREO |
+ vt->capability |= V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
break;
}
@@ -726,6 +714,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (state->radio) /* TODO: add mono/stereo support for radio */
break;
+ if (state->audmode == vt->audmode)
+ break;
state->audmode = vt->audmode;
/* only set audmode */
msp_set_audmode(client);
@@ -887,7 +877,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
memset(state, 0, sizeof(*state));
state->v4l2_std = V4L2_STD_NTSC;
- state->audmode = V4L2_TUNER_MODE_LANG1;
+ state->audmode = V4L2_TUNER_MODE_STEREO;
state->volume = 58880; /* 0db gain */
state->balance = 32768; /* 0db gain */
state->bass = 32768;
@@ -931,13 +921,16 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
state->has_radio = msp_revision >= 'G';
/* Has headphones output: not for stripped down products */
state->has_headphones = msp_prod_lo < 5;
+ /* Has scart2 input: not in stripped down products of the '3' family */
+ state->has_scart2 = msp_family >= 4 || msp_prod_lo < 7;
+ /* Has scart3 input: not in stripped down products of the '3' family */
+ state->has_scart3 = msp_family >= 4 || msp_prod_lo < 5;
/* Has scart4 input: not in pre D revisions, not in stripped D revs */
state->has_scart4 = msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5);
- /* Has scart2 and scart3 inputs and scart2 output: not in stripped
- down products of the '3' family */
- state->has_scart23_in_scart2_out = msp_family >= 4 || msp_prod_lo < 5;
+ /* Has scart2 output: not in stripped down products of the '3' family */
+ state->has_scart2_out = msp_family >= 4 || msp_prod_lo < 5;
/* Has scart2 a volume control? Not in pre-D revisions. */
- state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart23_in_scart2_out;
+ state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart2_out;
/* Has a configurable i2s out? */
state->has_i2s_conf = msp_revision >= 'G' && msp_prod_lo < 7;
/* Has subwoofer output: not in pre-D revs and not in stripped down products */
diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h
index 1940748bb63..4e451049013 100644
--- a/drivers/media/video/msp3400-driver.h
+++ b/drivers/media/video/msp3400-driver.h
@@ -54,8 +54,10 @@ struct msp_state {
u8 has_radio;
u8 has_headphones;
u8 has_ntsc_jp_d_k3;
+ u8 has_scart2;
+ u8 has_scart3;
u8 has_scart4;
- u8 has_scart23_in_scart2_out;
+ u8 has_scart2_out;
u8 has_scart2_out_volume;
u8 has_i2s_conf;
u8 has_subwoofer;
@@ -83,6 +85,7 @@ struct msp_state {
int volume, muted;
int balance, loudness;
int bass, treble;
+ int scan_in_progress;
/* thread */
struct task_struct *kthread;
@@ -98,7 +101,6 @@ int msp_read_dem(struct i2c_client *client, int addr);
int msp_read_dsp(struct i2c_client *client, int addr);
int msp_reset(struct i2c_client *client);
void msp_set_scart(struct i2c_client *client, int in, int out);
-void msp_set_mute(struct i2c_client *client);
void msp_set_audio(struct i2c_client *client);
int msp_sleep(struct msp_state *state, int timeout);
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index c3984ea9ca0..633a1021378 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -170,7 +170,7 @@ static void msp_set_source(struct i2c_client *client, u16 src)
msp_write_dsp(client, 0x000a, src);
msp_write_dsp(client, 0x000b, src);
msp_write_dsp(client, 0x000c, src);
- if (state->has_scart23_in_scart2_out)
+ if (state->has_scart2_out)
msp_write_dsp(client, 0x0041, src);
}
@@ -228,6 +228,7 @@ static void msp3400c_set_audmode(struct i2c_client *client)
char *modestr = (state->audmode >= 0 && state->audmode < 5) ?
strmode[state->audmode] : "unknown";
int src = 0; /* channel source: FM/AM, nicam or SCART */
+ int audmode = state->audmode;
if (state->opmode == OPMODE_AUTOSELECT) {
/* this method would break everything, let's make sure
@@ -239,11 +240,29 @@ static void msp3400c_set_audmode(struct i2c_client *client)
return;
}
+ /* Note: for the C and D revs no NTSC stereo + SAP is possible as
+ the hardware does not support SAP. So the rxsubchans combination
+ of STEREO | LANG2 does not occur. */
+
+ /* switch to mono if only mono is available */
+ if (state->rxsubchans == V4L2_TUNER_SUB_MONO)
+ audmode = V4L2_TUNER_MODE_MONO;
+ /* if bilingual */
+ else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) {
+ /* and mono or stereo, then fallback to lang1 */
+ if (audmode == V4L2_TUNER_MODE_MONO ||
+ audmode == V4L2_TUNER_MODE_STEREO)
+ audmode = V4L2_TUNER_MODE_LANG1;
+ }
+ /* if stereo, and audmode is not mono, then switch to stereo */
+ else if (audmode != V4L2_TUNER_MODE_MONO)
+ audmode = V4L2_TUNER_MODE_STEREO;
+
/* switch demodulator */
switch (state->mode) {
case MSP_MODE_FM_TERRA:
v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr);
- switch (state->audmode) {
+ switch (audmode) {
case V4L2_TUNER_MODE_STEREO:
msp_write_dsp(client, 0x000e, 0x3001);
break;
@@ -257,7 +276,7 @@ static void msp3400c_set_audmode(struct i2c_client *client)
break;
case MSP_MODE_FM_SAT:
v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr);
- switch (state->audmode) {
+ switch (audmode) {
case V4L2_TUNER_MODE_MONO:
msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
break;
@@ -296,7 +315,8 @@ static void msp3400c_set_audmode(struct i2c_client *client)
}
/* switch audio */
- switch (state->audmode) {
+ v4l_dbg(1, msp_debug, client, "set audmode %d\n", audmode);
+ switch (audmode) {
case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1_LANG2:
src |= 0x0020;
@@ -314,10 +334,6 @@ static void msp3400c_set_audmode(struct i2c_client *client)
src = 0x0030;
break;
case V4L2_TUNER_MODE_LANG1:
- /* switch to stereo for stereo transmission, otherwise
- keep first language */
- if (state->rxsubchans & V4L2_TUNER_SUB_STEREO)
- src |= 0x0020;
break;
case V4L2_TUNER_MODE_LANG2:
src |= 0x0010;
@@ -367,7 +383,7 @@ static int msp3400c_detect_stereo(struct i2c_client *client)
if (val > 32767)
val -= 65536;
v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val);
- if (val > 4096) {
+ if (val > 8192) {
rxsubchans = V4L2_TUNER_SUB_STEREO;
} else if (val < -4096) {
rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
@@ -464,19 +480,22 @@ int msp3400c_thread(void *data)
if (state->radio || MSP_MODE_EXTERN == state->mode) {
/* no carrier scan, just unmute */
v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
+ state->scan_in_progress = 0;
msp_set_audio(client);
continue;
}
- /* mute */
- msp_set_mute(client);
+ /* mute audio */
+ state->scan_in_progress = 1;
+ msp_set_audio(client);
+
msp3400c_set_mode(client, MSP_MODE_AM_DETECT);
val1 = val2 = 0;
max1 = max2 = -1;
state->watch_stereo = 0;
state->nicam_on = 0;
- /* some time for the tuner to sync */
+ /* wait for tuner to settle down after a channel change */
if (msp_sleep(state, 200))
goto restart;
@@ -552,7 +571,6 @@ int msp3400c_thread(void *data)
/* B/G NICAM */
state->second = msp3400c_carrier_detect_55[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
- msp3400c_set_carrier(client, state->second, state->main);
state->nicam_on = 1;
state->watch_stereo = 1;
} else {
@@ -563,7 +581,6 @@ int msp3400c_thread(void *data)
/* PAL I NICAM */
state->second = MSP_CARRIER(6.552);
msp3400c_set_mode(client, MSP_MODE_FM_NICAM2);
- msp3400c_set_carrier(client, state->second, state->main);
state->nicam_on = 1;
state->watch_stereo = 1;
break;
@@ -577,13 +594,11 @@ int msp3400c_thread(void *data)
/* L NICAM or AM-mono */
state->second = msp3400c_carrier_detect_65[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_AM_NICAM);
- msp3400c_set_carrier(client, state->second, state->main);
state->watch_stereo = 1;
} else if (max2 == 0 && state->has_nicam) {
/* D/K NICAM */
state->second = msp3400c_carrier_detect_65[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
- msp3400c_set_carrier(client, state->second, state->main);
state->nicam_on = 1;
state->watch_stereo = 1;
} else {
@@ -595,25 +610,25 @@ int msp3400c_thread(void *data)
no_second:
state->second = msp3400c_carrier_detect_main[max1].cdo;
msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
- msp3400c_set_carrier(client, state->second, state->main);
- state->rxsubchans = V4L2_TUNER_SUB_MONO;
break;
}
+ msp3400c_set_carrier(client, state->second, state->main);
/* unmute */
- msp_set_audio(client);
+ state->scan_in_progress = 0;
msp3400c_set_audmode(client);
+ msp_set_audio(client);
if (msp_debug)
msp3400c_print_mode(client);
/* monitor tv audio mode, the first time don't wait
so long to get a quick stereo/bilingual result */
- if (msp_sleep(state, 1000))
- goto restart;
+ count = 3;
while (state->watch_stereo) {
- if (msp_sleep(state, 5000))
+ if (msp_sleep(state, count ? 1000 : 5000))
goto restart;
+ if (count) count--;
watch_stereo(client);
}
}
@@ -626,7 +641,7 @@ int msp3410d_thread(void *data)
{
struct i2c_client *client = data;
struct msp_state *state = i2c_get_clientdata(client);
- int val, i, std;
+ int val, i, std, count;
v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
@@ -644,16 +659,14 @@ int msp3410d_thread(void *data)
if (state->mode == MSP_MODE_EXTERN) {
/* no carrier scan needed, just unmute */
v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
+ state->scan_in_progress = 0;
msp_set_audio(client);
continue;
}
- /* put into sane state (and mute) */
- msp_reset(client);
-
- /* some time for the tuner to sync */
- if (msp_sleep(state,200))
- goto restart;
+ /* mute audio */
+ state->scan_in_progress = 1;
+ msp_set_audio(client);
/* start autodetect. Note: autodetect is not supported for
NTSC-M and radio, hence we force the standard in those cases. */
@@ -664,6 +677,10 @@ int msp3410d_thread(void *data)
state->watch_stereo = 0;
state->nicam_on = 0;
+ /* wait for tuner to settle down after a channel change */
+ if (msp_sleep(state, 200))
+ goto restart;
+
if (msp_debug)
v4l_dbg(2, msp_debug, client, "setting standard: %s (0x%04x)\n",
msp_standard_std_name(std), std);
@@ -693,6 +710,7 @@ int msp3410d_thread(void *data)
state->main = msp_stdlist[i].main;
state->second = msp_stdlist[i].second;
state->std = val;
+ state->rxsubchans = V4L2_TUNER_SUB_MONO;
if (msp_amsound && !state->radio && (state->v4l2_std & V4L2_STD_SECAM) &&
(val != 0x0009)) {
@@ -714,20 +732,17 @@ int msp3410d_thread(void *data)
else
state->mode = MSP_MODE_FM_NICAM1;
/* just turn on stereo */
- state->rxsubchans = V4L2_TUNER_SUB_STEREO;
state->nicam_on = 1;
state->watch_stereo = 1;
break;
case 0x0009:
state->mode = MSP_MODE_AM_NICAM;
- state->rxsubchans = V4L2_TUNER_SUB_MONO;
state->nicam_on = 1;
state->watch_stereo = 1;
break;
case 0x0020: /* BTSC */
/* The pre-'G' models only have BTSC-mono */
state->mode = MSP_MODE_BTSC;
- state->rxsubchans = V4L2_TUNER_SUB_MONO;
break;
case 0x0040: /* FM radio */
state->mode = MSP_MODE_FM_RADIO;
@@ -737,15 +752,12 @@ int msp3410d_thread(void *data)
msp3400c_set_mode(client, MSP_MODE_FM_RADIO);
msp3400c_set_carrier(client, MSP_CARRIER(10.7),
MSP_CARRIER(10.7));
- /* scart routing (this doesn't belong here I think) */
- msp_set_scart(client,SCART_IN2,0);
break;
case 0x0002:
case 0x0003:
case 0x0004:
case 0x0005:
state->mode = MSP_MODE_FM_TERRA;
- state->rxsubchans = V4L2_TUNER_SUB_MONO;
state->watch_stereo = 1;
break;
}
@@ -759,20 +771,19 @@ int msp3410d_thread(void *data)
if (state->has_i2s_conf)
msp_write_dem(client, 0x40, state->i2s_mode);
- /* unmute, restore misc registers */
- msp_set_audio(client);
-
- msp_write_dsp(client, 0x13, state->acb);
+ /* unmute */
msp3400c_set_audmode(client);
+ state->scan_in_progress = 0;
+ msp_set_audio(client);
/* monitor tv audio mode, the first time don't wait
so long to get a quick stereo/bilingual result */
- if (msp_sleep(state, 1000))
- goto restart;
+ count = 3;
while (state->watch_stereo) {
- watch_stereo(client);
- if (msp_sleep(state, 5000))
+ if (msp_sleep(state, count ? 1000 : 5000))
goto restart;
+ if (count) count--;
+ watch_stereo(client);
}
}
v4l_dbg(1, msp_debug, client, "thread: exit\n");
@@ -829,27 +840,27 @@ static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
source = 0; /* mono only */
matrix = 0x30;
break;
- case V4L2_TUNER_MODE_LANG1:
- source = 3; /* stereo or A */
- matrix = 0x00;
- break;
case V4L2_TUNER_MODE_LANG2:
source = 4; /* stereo or B */
matrix = 0x10;
break;
- case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1_LANG2:
- default:
source = 1; /* stereo or A|B */
matrix = 0x20;
break;
+ case V4L2_TUNER_MODE_STEREO:
+ case V4L2_TUNER_MODE_LANG1:
+ default:
+ source = 3; /* stereo or A */
+ matrix = 0x00;
+ break;
}
- if (in == MSP_DSP_OUT_TUNER)
+ if (in == MSP_DSP_IN_TUNER)
source = (source << 8) | 0x20;
/* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14
instead of 11, 12, 13. So we add one for that msp version. */
- else if (in >= MSP_DSP_OUT_MAIN_AVC && state->has_dolby_pro_logic)
+ else if (in >= MSP_DSP_IN_MAIN_AVC && state->has_dolby_pro_logic)
source = ((in + 1) << 8) | matrix;
else
source = (in << 8) | matrix;
@@ -869,7 +880,7 @@ static void msp34xxg_set_sources(struct i2c_client *client)
msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf);
msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf);
msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf);
- if (state->has_scart23_in_scart2_out)
+ if (state->has_scart2_out)
msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf);
msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf);
}
@@ -887,10 +898,6 @@ static void msp34xxg_reset(struct i2c_client *client)
msp_reset(client);
- /* make sure that input/output is muted (paranoid mode) */
- /* ACB, mute DSP input, mute SCART 1 */
- msp_write_dsp(client, 0x13, 0x0f20);
-
if (state->has_i2s_conf)
msp_write_dem(client, 0x40, state->i2s_mode);
@@ -1028,7 +1035,7 @@ static void msp34xxg_set_audmode(struct i2c_client *client)
if (state->std == 0x20) {
if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) &&
- (state->audmode == V4L2_TUNER_MODE_STEREO ||
+ (state->audmode == V4L2_TUNER_MODE_LANG1_LANG2 ||
state->audmode == V4L2_TUNER_MODE_LANG2)) {
msp_write_dem(client, 0x20, 0x21);
} else {
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index 522e9ddeb08..d9e3cada52f 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -2156,7 +2156,7 @@ static int find_planb(void)
struct pci_dev *pdev;
int rc;
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return 0;
planb_devices = find_devices("planb");
diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig
new file mode 100644
index 00000000000..53cbc950f95
--- /dev/null
+++ b/drivers/media/video/pwc/Kconfig
@@ -0,0 +1,28 @@
+config USB_PWC
+ tristate "USB Philips Cameras"
+ depends on USB && VIDEO_V4L1
+ ---help---
+ Say Y or M here if you want to use one of these Philips & OEM
+ webcams:
+ * Philips PCA645, PCA646
+ * Philips PCVC675, PCVC680, PCVC690
+ * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
+ * Askey VC010
+ * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
+ and 'Orbit'/'Sphere'
+ * Samsung MPC-C10, MPC-C30
+ * Creative Webcam 5, Pro Ex
+ * SOTEC Afina Eye
+ * Visionite VCS-UC300, VCS-UM100
+
+ The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
+ and never will be, but the 665 and 720/20 are supported by other
+ drivers.
+
+ See <file:Documentation/usb/philips.txt> for more information and
+ installation instructions.
+
+ The built-in microphone is enabled by selecting USB Audio support.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pwc.
diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/video/pwc/Makefile
index 8326684f49f..33d60126c02 100644
--- a/drivers/media/video/pwc/Makefile
+++ b/drivers/media/video/pwc/Makefile
@@ -1,20 +1,3 @@
-ifneq ($(KERNELRELEASE),)
-
pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o
obj-$(CONFIG_USB_PWC) += pwc.o
-
-else
-
-KDIR := /lib/modules/$(shell uname -r)/build
-PWD := $(shell pwd)
-
-default:
- $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
-
-endif
-
-clean:
- rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c
- rm -rf .tmp_versions
-
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index b0501528260..dceebc0b125 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -40,6 +40,7 @@
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
+#include <media/saa7115.h>
#include <asm/div64.h>
MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver");
@@ -53,7 +54,7 @@ module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
static unsigned short normal_i2c[] = {
- 0x4a >>1, 0x48 >>1, /* SAA7113 */
+ 0x4a >> 1, 0x48 >> 1, /* SAA7113 */
0x42 >> 1, 0x40 >> 1, /* SAA7114 and SAA7115 */
I2C_CLIENT_END };
@@ -722,16 +723,16 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
100 reserved NTSC-Japan (3.58MHz)
*/
if (state->ident == V4L2_IDENT_SAA7113) {
- u8 reg = saa7115_read(client, 0x0e) & 0x8f;
+ u8 reg = saa7115_read(client, 0x0e) & 0x8f;
if (std == V4L2_STD_PAL_M) {
- reg|=0x30;
+ reg |= 0x30;
} else if (std == V4L2_STD_PAL_N) {
- reg|=0x20;
+ reg |= 0x20;
} else if (std == V4L2_STD_PAL_60) {
- reg|=0x10;
+ reg |= 0x10;
} else if (std == V4L2_STD_NTSC_M_JP) {
- reg|=0x40;
+ reg |= 0x40;
}
saa7115_write(client, 0x0e, reg);
}
@@ -811,7 +812,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
u8 lcr[24];
int i, x;
- /* saa7113/71144 doesn't yet support VBI */
+ /* saa7113/7114 doesn't yet support VBI */
if (state->ident != V4L2_IDENT_SAA7115)
return;
@@ -851,7 +852,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
case 0:
lcr[i] |= 0xf << (4 * x);
break;
- case V4L2_SLICED_TELETEXT_PAL_B:
+ case V4L2_SLICED_TELETEXT_B:
lcr[i] |= 1 << (4 * x);
break;
case V4L2_SLICED_CAPTION_525:
@@ -880,7 +881,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
{
static u16 lcr2vbi[] = {
- 0, V4L2_SLICED_TELETEXT_PAL_B, 0, /* 1 */
+ 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
0, V4L2_SLICED_CAPTION_525, /* 4 */
V4L2_SLICED_WSS_625, 0, /* 5 */
V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
@@ -1045,7 +1046,7 @@ static void saa7115_decode_vbi_line(struct i2c_client *client,
/* decode payloads */
switch (id2) {
case 1:
- vbi->type = V4L2_SLICED_TELETEXT_PAL_B;
+ vbi->type = V4L2_SLICED_TELETEXT_B;
break;
case 4:
if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1]))
@@ -1180,6 +1181,46 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
state->radio = 1;
break;
+ case VIDIOC_INT_G_VIDEO_ROUTING:
+ {
+ struct v4l2_routing *route = arg;
+
+ route->input = state->input;
+ route->output = 0;
+ break;
+ }
+
+ case VIDIOC_INT_S_VIDEO_ROUTING:
+ {
+ struct v4l2_routing *route = arg;
+
+ v4l_dbg(1, debug, client, "decoder set input %d\n", route->input);
+ /* saa7113 does not have these inputs */
+ if (state->ident == V4L2_IDENT_SAA7113 &&
+ (route->input == SAA7115_COMPOSITE4 ||
+ route->input == SAA7115_COMPOSITE5)) {
+ return -EINVAL;
+ }
+ if (route->input > SAA7115_SVIDEO3)
+ return -EINVAL;
+ if (state->input == route->input)
+ break;
+ v4l_dbg(1, debug, client, "now setting %s input\n",
+ (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite");
+ state->input = route->input;
+
+ /* select mode */
+ saa7115_write(client, 0x02,
+ (saa7115_read(client, 0x02) & 0xf0) |
+ state->input);
+
+ /* bypass chrominance trap for S-Video modes */
+ saa7115_write(client, 0x09,
+ (saa7115_read(client, 0x09) & 0x7f) |
+ (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
+ break;
+ }
+
case VIDIOC_G_INPUT:
*(int *)arg = state->input;
break;
@@ -1321,7 +1362,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
saa7115_write(client, 0, 5);
chip_id = saa7115_read(client, 0) & 0x0f;
- if (chip_id <3 && chip_id > 5) {
+ if (chip_id < 3 && chip_id > 5) {
v4l_dbg(1, debug, client, "saa7115 not found\n");
kfree(client);
return 0;
@@ -1360,7 +1401,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
v4l_dbg(1, debug, client, "writing init values\n");
/* init to 60hz/48khz */
- if (state->ident==V4L2_IDENT_SAA7113)
+ if (state->ident == V4L2_IDENT_SAA7113)
saa7115_writeregs(client, saa7113_init_auto_input);
else
saa7115_writeregs(client, saa7115_init_auto_input);
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index 992c71774f3..c271e2e1410 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -54,6 +54,7 @@
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
+#include <media/saa7127.h>
static int debug = 0;
static int test_image = 0;
@@ -141,6 +142,7 @@ struct i2c_reg_value {
static const struct i2c_reg_value saa7129_init_config_extra[] = {
{ SAA7127_REG_OUTPUT_PORT_CONTROL, 0x38 },
{ SAA7127_REG_VTRIG, 0xfa },
+ { 0, 0 }
};
static const struct i2c_reg_value saa7127_init_config_common[] = {
@@ -222,22 +224,6 @@ static struct i2c_reg_value saa7127_init_config_50hz[] = {
{ 0, 0 }
};
-/* Enumeration for the Supported input types */
-enum saa7127_input_type {
- SAA7127_INPUT_TYPE_NORMAL,
- SAA7127_INPUT_TYPE_TEST_IMAGE
-};
-
-/* Enumeration for the Supported Output signal types */
-enum saa7127_output_type {
- SAA7127_OUTPUT_TYPE_BOTH,
- SAA7127_OUTPUT_TYPE_COMPOSITE,
- SAA7127_OUTPUT_TYPE_SVIDEO,
- SAA7127_OUTPUT_TYPE_RGB,
- SAA7127_OUTPUT_TYPE_YUV_C,
- SAA7127_OUTPUT_TYPE_YUV_V
-};
-
/*
**********************************************************************
*
@@ -561,7 +547,7 @@ static int saa7127_command(struct i2c_client *client,
{
struct saa7127_state *state = i2c_get_clientdata(client);
struct v4l2_format *fmt = arg;
- int *iarg = arg;
+ struct v4l2_routing *route = arg;
switch (cmd) {
case VIDIOC_S_STD:
@@ -573,15 +559,23 @@ static int saa7127_command(struct i2c_client *client,
*(v4l2_std_id *)arg = state->std;
break;
- case VIDIOC_S_INPUT:
- if (state->input_type == *iarg)
- break;
- return saa7127_set_input_type(client, *iarg);
+ case VIDIOC_INT_G_VIDEO_ROUTING:
+ route->input = state->input_type;
+ route->output = state->output_type;
+ break;
- case VIDIOC_S_OUTPUT:
- if (state->output_type == *iarg)
- break;
- return saa7127_set_output_type(client, *iarg);
+ case VIDIOC_INT_S_VIDEO_ROUTING:
+ {
+ int rc = 0;
+
+ if (state->input_type != route->input) {
+ rc = saa7127_set_input_type(client, route->input);
+ }
+ if (rc == 0 && state->output_type != route->output) {
+ rc = saa7127_set_output_type(client, route->output);
+ }
+ return rc;
+ }
case VIDIOC_STREAMON:
case VIDIOC_STREAMOFF:
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index 86671a43e76..e1c1805df1f 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
@@ -39,6 +39,7 @@ config VIDEO_SAA7134_DVB
tristate "DVB/ATSC Support for saa7134 based TV cards"
depends on VIDEO_SAA7134 && DVB_CORE
select VIDEO_BUF_DVB
+ select FW_LOADER
---help---
This adds support for DVB cards based on the
Philips saa7134 chip.
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile
index 1ba998424bb..be7b9ee697d 100644
--- a/drivers/media/video/saa7134/Makefile
+++ b/drivers/media/video/saa7134/Makefile
@@ -11,9 +11,9 @@ obj-$(CONFIG_VIDEO_SAA7134_OSS) += saa7134-oss.o
obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
-EXTRA_CFLAGS += -I$(src)/..
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index fdd7f48f3b7..86eae352833 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -208,7 +208,7 @@ struct saa7134_board saa7134_boards[] = {
[SAA7134_BOARD_FLYTVPLATINUM_FM] = {
/* LifeView FlyTV Platinum FM (LR214WF) */
/* "Peter Missel <peter.missel@onlinehome.de> */
- .name = "LifeView FlyTV Platinum FM",
+ .name = "LifeView FlyTV Platinum FM / Gold",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_TDA8290,
.radio_type = UNSET,
@@ -2660,7 +2660,7 @@ struct saa7134_board saa7134_boards[] = {
.mpeg = SAA7134_MPEG_DVB,
.inputs = {{
.name = name_comp1,
- .vmux = 0,
+ .vmux = 1,
.amux = LINE1,
},{
.name = name_svideo,
@@ -2671,7 +2671,7 @@ struct saa7134_board saa7134_boards[] = {
[SAA7134_BOARD_FLYDVBT_LR301] = {
/* LifeView FlyDVB-T */
/* Giampiero Giancipoli <gianci@libero.it> */
- .name = "LifeView FlyDVB-T",
+ .name = "LifeView FlyDVB-T / Genius VideoWonder DVB-T",
.audio_clock = 0x00200000,
.tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
@@ -2808,6 +2808,40 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
},
+ [SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = {
+ .name = "LifeView FlyDVB-T Hybrid Cardbus",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .mpeg = SAA7134_MPEG_DVB,
+ .gpiomask = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .gpio = 0x200000, /* GPIO21=High for TV input */
+ .tv = 1,
+ },{
+ .name = name_svideo, /* S-Video signal on S-Video input */
+ .vmux = 8,
+ .amux = LINE2,
+ },{
+ .name = name_comp1, /* Composite signal on S-Video input */
+ .vmux = 0,
+ .amux = LINE2,
+ },{
+ .name = name_comp2, /* Composite input */
+ .vmux = 3,
+ .amux = LINE2,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */
+ },
+ },
};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -3333,6 +3367,30 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x0005,
.driver_data = SAA7134_BOARD_MD7134_BRIDGE_2,
},{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+ .subvendor = 0x1489,
+ .subdevice = 0x0301,
+ .driver_data = SAA7134_BOARD_FLYDVBT_LR301,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x5168, /* Animation Technologies (LifeView) */
+ .subdevice = 0x0304,
+ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x5168,
+ .subdevice = 0x3306,
+ .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x5168,
+ .subdevice = 0x3502, /* whats the difference to 0x3306 ?*/
+ .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+ },{
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -3446,6 +3504,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
/* power-up tuner chip */
saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000);
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000);
+ break;
case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
/* this turns the remote control chip off to work around a bug in it */
saa_writeb(SAA7134_GPIO_GPMODE1, 0x80);
@@ -3462,6 +3521,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06);
break;
case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
+ case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
saa_writeb(SAA7134_GPIO_GPMODE3, 0x08);
saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x00);
break;
@@ -3633,6 +3693,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
}
break;
case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
+ case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
/* make the tda10046 find its eeprom */
{
u8 data[] = { 0x3c, 0x33, 0x62};
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index c98571c9d5a..f0c2111f14a 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -32,6 +32,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
#include "saa7134-reg.h"
#include "saa7134.h"
@@ -547,6 +548,8 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
if (report & SAA7134_IRQ_REPORT_GPIO16) {
switch (dev->has_remote) {
case SAA7134_REMOTE_GPIO:
+ if (!dev->remote)
+ break;
if (dev->remote->mask_keydown & 0x10000) {
saa7134_input_irq(dev);
}
@@ -563,6 +566,8 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
if (report & SAA7134_IRQ_REPORT_GPIO18) {
switch (dev->has_remote) {
case SAA7134_REMOTE_GPIO:
+ if (!dev->remote)
+ break;
if ((dev->remote->mask_keydown & 0x40000) ||
(dev->remote->mask_keyup & 0x40000)) {
saa7134_input_irq(dev);
@@ -675,7 +680,7 @@ static int saa7134_hwinit2(struct saa7134_dev *dev)
SAA7134_IRQ2_INTE_PE |
SAA7134_IRQ2_INTE_AR;
- if (dev->has_remote == SAA7134_REMOTE_GPIO) {
+ if (dev->has_remote == SAA7134_REMOTE_GPIO && dev->remote) {
if (dev->remote->mask_keydown & 0x10000)
irq2_mask |= SAA7134_IRQ2_INTE_GPIO16;
else if (dev->remote->mask_keydown & 0x40000)
@@ -870,7 +875,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
dev->pci_lat,pci_resource_start(pci_dev,0));
pci_set_master(pci_dev);
- if (!pci_dma_supported(pci_dev,0xffffffff)) {
+ if (!pci_dma_supported(pci_dev, DMA_32BIT_MASK)) {
printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name);
err = -EIO;
goto fail1;
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 86cfdb8514c..222a36c3891 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1064,6 +1064,10 @@ static int dvb_init(struct saa7134_dev *dev)
dev->dvb.frontend = tda10046_attach(&tevion_dvbt220rf_config,
&dev->i2c_adap);
break;
+ case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
+ dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config,
+ &dev->i2c_adap);
+ break;
#endif
#ifdef HAVE_NXT200X
case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index aeef80f88a6..e4156ec9c6d 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -31,8 +31,10 @@
#include "saa7134.h"
#include <media/v4l2-common.h>
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
/* Include V4L1 specific functions. Should be removed soon */
#include <linux/videodev.h>
+#endif
/* ------------------------------------------------------------------ */
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 31ba293854c..353af3a8b76 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -220,6 +220,7 @@ struct saa7134_format {
#define SAA7134_BOARD_AVERMEDIA_A169_B 91
#define SAA7134_BOARD_AVERMEDIA_A169_B1 92
#define SAA7134_BOARD_MD7134_BRIDGE_2 93
+#define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig
new file mode 100644
index 00000000000..cf552e6b8ec
--- /dev/null
+++ b/drivers/media/video/sn9c102/Kconfig
@@ -0,0 +1,11 @@
+config USB_SN9C102
+ tristate "USB SN9C10x PC Camera Controller support"
+ depends on USB && VIDEO_V4L1
+ ---help---
+ Say Y here if you want support for cameras based on SONiX SN9C101,
+ SN9C102 or SN9C103 PC Camera Controllers.
+
+ See <file:Documentation/video4linux/sn9c102.txt> for more info.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sn9c102.
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index df195c90536..1013b4de89a 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -401,7 +401,7 @@ static void tuner_status(struct i2c_client *client)
}
tuner_info("Tuner mode: %s\n", p);
tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction);
- tuner_info("Standard: 0x%08llx\n", t->std);
+ tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std);
if (t->mode != V4L2_TUNER_RADIO)
return;
if (t->has_signal) {
@@ -558,10 +558,10 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode,
static inline int check_v4l2(struct tuner *t)
{
- if (t->using_v4l2) {
- tuner_dbg ("ignore v4l1 call\n");
- return EINVAL;
- }
+ /* bttv still uses both v4l1 and v4l2 calls to the tuner (v4l2 for
+ TV, v4l1 for radio), until that is fixed this code is disabled.
+ Otherwise the radio (v4l1) wouldn't tune after using the TV (v4l2)
+ first. */
return 0;
}
@@ -744,6 +744,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
switch_v4l2();
tuner->type = t->mode;
+ if (t->mode == V4L2_TUNER_ANALOG_TV)
+ tuner->capability |= V4L2_TUNER_CAP_NORM;
if (t->mode != V4L2_TUNER_RADIO) {
tuner->rangelow = tv_range[0] * 16;
tuner->rangehigh = tv_range[1] * 16;
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
index 72e0f01db56..a1ae036b44e 100644
--- a/drivers/media/video/tuner-types.c
+++ b/drivers/media/video/tuner-types.c
@@ -877,8 +877,8 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
/* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */
static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
- { 16 * 160.00 /*MHz*/, 0x8e, 0x01 },
- { 16 * 455.00 /*MHz*/, 0x8e, 0x02 },
+ { 16 * 165.00 /*MHz*/, 0x8e, 0x01 },
+ { 16 * 450.00 /*MHz*/, 0x8e, 0x02 },
{ 16 * 999.99 , 0x8e, 0x04 },
};
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 356bff455ad..c2b75610754 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -1706,21 +1706,6 @@ static int chip_command(struct i2c_client *client,
break;
}
- case VIDIOC_S_AUDIO:
- {
- struct v4l2_audio *sarg = arg;
-
- if (!(desc->flags & CHIP_HAS_INPUTSEL) || sarg->index >= 4)
- return -EINVAL;
- /* There are four inputs: tuner, radio, extern and intern. */
- chip->input = sarg->index;
- if (chip->muted)
- break;
- chip_write_masked(chip, desc->inputreg,
- desc->inputmap[chip->input], desc->inputmask);
- break;
- }
-
case VIDIOC_S_TUNER:
{
struct v4l2_tuner *vt = arg;
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index e0d2ff83fc9..b463e996961 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -218,7 +218,7 @@ hauppauge_tuner[] =
/* 110-119 */
{ TUNER_ABSENT, "Thompson DTT75105"},
{ TUNER_ABSENT, "Conexant_CX24109"},
- { TUNER_ABSENT, "TCL M2523_5N_E"},
+ { TUNER_TCL_2002N, "TCL M2523_5N_E"},
{ TUNER_ABSENT, "TCL M2523_3DB_E"},
{ TUNER_ABSENT, "Philips 8275A"},
{ TUNER_ABSENT, "Microtune MT2060"},
@@ -757,9 +757,9 @@ tveeprom_detect_client(struct i2c_adapter *adapter,
static int
tveeprom_attach_adapter (struct i2c_adapter *adapter)
{
- if (adapter->id != I2C_HW_B_BT848)
- return 0;
- return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
+ return 0;
}
static int
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index 69d0fe159f4..dab4973bcf8 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -53,7 +53,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = {
.minimum = 0,
.maximum = 255,
.step = 1,
- .default_value = 0,
+ .default_value = 128,
.flags = 0,
}, {
.id = V4L2_CID_CONTRAST,
@@ -62,7 +62,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = {
.minimum = 0,
.maximum = 255,
.step = 0x1,
- .default_value = 0x10,
+ .default_value = 128,
.flags = 0,
}, {
.id = V4L2_CID_SATURATION,
@@ -71,7 +71,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = {
.minimum = 0,
.maximum = 255,
.step = 0x1,
- .default_value = 0x10,
+ .default_value = 128,
.flags = 0,
}, {
.id = V4L2_CID_HUE,
@@ -80,7 +80,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = {
.minimum = -128,
.maximum = 127,
.step = 0x1,
- .default_value = 0x10,
+ .default_value = 0,
.flags = 0,
}
};
@@ -500,16 +500,21 @@ struct i2c_vbi_ram_value {
static struct i2c_vbi_ram_value vbi_ram_default[] =
{
+ /* FIXME: Current api doesn't handle all VBI types, those not
+ yet supported are placed under #if 0 */
+#if 0
{0x010, /* Teletext, SECAM, WST System A */
{V4L2_SLICED_TELETEXT_SECAM,6,23,1},
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26,
0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 }
},
+#endif
{0x030, /* Teletext, PAL, WST System B */
- {V4L2_SLICED_TELETEXT_PAL_B,6,22,1},
+ {V4L2_SLICED_TELETEXT_B,6,22,1},
{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b,
0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 }
},
+#if 0
{0x050, /* Teletext, PAL, WST System C */
{V4L2_SLICED_TELETEXT_PAL_C,6,22,1},
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
@@ -535,6 +540,7 @@ static struct i2c_vbi_ram_value vbi_ram_default[] =
{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
},
+#endif
{0x0f0, /* Closed Caption, NTSC */
{V4L2_SLICED_CAPTION_525,21,21,1},
{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
@@ -545,6 +551,7 @@ static struct i2c_vbi_ram_value vbi_ram_default[] =
{ 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42,
0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 }
},
+#if 0
{0x130, /* Wide Screen Signal, NTSC C */
{V4L2_SLICED_WSS_525,20,20,1},
{ 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43,
@@ -560,6 +567,7 @@ static struct i2c_vbi_ram_value vbi_ram_default[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
},
+#endif
{0x190, /* Video Program System (VPS), PAL */
{V4L2_SLICED_VPS,16,16,0},
{ 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d,
@@ -850,7 +858,6 @@ static int tvp5150_command(struct i2c_client *c,
case 0:
case VIDIOC_INT_RESET:
- case DECODER_INIT:
tvp5150_reset(c);
break;
case VIDIOC_S_STD:
@@ -949,99 +956,15 @@ static int tvp5150_command(struct i2c_client *c,
#endif
case VIDIOC_LOG_STATUS:
- case DECODER_DUMP:
dump_reg(c);
break;
- case DECODER_GET_CAPABILITIES:
+ case VIDIOC_G_TUNER:
{
- struct video_decoder_capability *cap = arg;
-
- cap->flags = VIDEO_DECODER_PAL |
- VIDEO_DECODER_NTSC |
- VIDEO_DECODER_SECAM |
- VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR;
- cap->inputs = 3;
- cap->outputs = 1;
- break;
- }
- case DECODER_GET_STATUS:
- {
- int *iarg = arg;
- int status;
- int res=0;
- status = tvp5150_read(c, 0x88);
- if(status&0x08){
- res |= DECODER_STATUS_COLOR;
- }
- if(status&0x04 && status&0x02){
- res |= DECODER_STATUS_GOOD;
- }
- *iarg=res;
- break;
- }
-
- case DECODER_SET_GPIO:
- break;
-
- case DECODER_SET_VBI_BYPASS:
- break;
-
- case DECODER_SET_NORM:
- {
- int *iarg = arg;
-
- switch (*iarg) {
-
- case VIDEO_MODE_NTSC:
- break;
-
- case VIDEO_MODE_PAL:
- break;
-
- case VIDEO_MODE_SECAM:
- break;
-
- case VIDEO_MODE_AUTO:
- break;
-
- default:
- return -EINVAL;
-
- }
- decoder->norm = *iarg;
- break;
- }
- case DECODER_SET_INPUT:
- {
- int *iarg = arg;
- if (*iarg < 0 || *iarg > 3) {
- return -EINVAL;
- }
-
- decoder->input = *iarg;
- tvp5150_selmux(c, decoder->input);
-
- break;
- }
- case DECODER_SET_OUTPUT:
- {
- int *iarg = arg;
-
- /* not much choice of outputs */
- if (*iarg != 0) {
- return -EINVAL;
- }
- break;
- }
- case DECODER_ENABLE_OUTPUT:
- {
- int *iarg = arg;
-
- decoder->enable = (*iarg != 0);
-
- tvp5150_selmux(c, decoder->input);
+ struct v4l2_tuner *vt = arg;
+ int status = tvp5150_read(c, 0x88);
+ vt->signal = ((status & 0x04) && (status & 0x02)) ? 0xffff : 0x0;
break;
}
case VIDIOC_QUERYCTRL:
@@ -1087,35 +1010,6 @@ static int tvp5150_command(struct i2c_client *c,
return -EINVAL;
}
- case DECODER_SET_PICTURE:
- {
- struct video_picture *pic = arg;
- if (decoder->bright != pic->brightness) {
- /* We want 0 to 255 we get 0-65535 */
- decoder->bright = pic->brightness;
- tvp5150_write(c, TVP5150_BRIGHT_CTL,
- decoder->bright >> 8);
- }
- if (decoder->contrast != pic->contrast) {
- /* We want 0 to 255 we get 0-65535 */
- decoder->contrast = pic->contrast;
- tvp5150_write(c, TVP5150_CONTRAST_CTL,
- decoder->contrast >> 8);
- }
- if (decoder->sat != pic->colour) {
- /* We want 0 to 255 we get 0-65535 */
- decoder->sat = pic->colour;
- tvp5150_write(c, TVP5150_SATURATION_CTL,
- decoder->contrast >> 8);
- }
- if (decoder->hue != pic->hue) {
- /* We want -128 to 127 we get 0-65535 */
- decoder->hue = pic->hue;
- tvp5150_write(c, TVP5150_HUE_CTL,
- (decoder->hue - 32768) >> 8);
- }
- break;
- }
default:
return -EINVAL;
}
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c
new file mode 100644
index 00000000000..fc52201d607
--- /dev/null
+++ b/drivers/media/video/upd64031a.c
@@ -0,0 +1,286 @@
+/*
+ * upd64031A - NEC Electronics Ghost Reduction for NTSC in Japan
+ *
+ * 2003 by T.Adachi <tadachi@tadachi-net.com>
+ * 2003 by Takeru KOMORIYA <komoriya@paken.org>
+ * 2006 by Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; 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/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/upd64031a.h>
+
+// --------------------- read registers functions define -----------------------
+
+/* bit masks */
+#define GR_MODE_MASK 0xc0
+#define DIRECT_3DYCS_CONNECT_MASK 0xc0
+#define SYNC_CIRCUIT_MASK 0xa0
+
+// -----------------------------------------------------------------------------
+
+MODULE_DESCRIPTION("uPD64031A driver");
+MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+static unsigned short normal_i2c[] = { 0x24 >> 1, 0x26 >> 1, I2C_CLIENT_END };
+
+
+I2C_CLIENT_INSMOD;
+
+enum {
+ R00 = 0, R01, R02, R03, R04,
+ R05, R06, R07, R08, R09,
+ R0A, R0B, R0C, R0D, R0E, R0F,
+ /* unused registers
+ R10, R11, R12, R13, R14,
+ R15, R16, R17,
+ */
+ TOT_REGS
+};
+
+struct upd64031a_state {
+ u8 regs[TOT_REGS];
+ u8 gr_mode;
+ u8 direct_3dycs_connect;
+ u8 ext_comp_sync;
+ u8 ext_vert_sync;
+};
+
+static u8 upd64031a_init[] = {
+ 0x00, 0xb8, 0x48, 0xd2, 0xe6,
+ 0x03, 0x10, 0x0b, 0xaf, 0x7f,
+ 0x00, 0x00, 0x1d, 0x5e, 0x00,
+ 0xd0
+};
+
+/* ------------------------------------------------------------------------ */
+
+static u8 upd64031a_read(struct i2c_client *client, u8 reg)
+{
+ u8 buf[2];
+
+ if (reg >= sizeof(buf))
+ return 0xff;
+ i2c_master_recv(client, buf, 2);
+ return buf[reg];
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void upd64031a_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ u8 buf[2];
+
+ buf[0] = reg;
+ buf[1] = val;
+ v4l_dbg(1, debug, client, "writing reg addr: %02X val: %02X\n", reg, val);
+ if (i2c_master_send(client, buf, 2) != 2)
+ v4l_err(client, "I/O error write 0x%02x/0x%02x\n", reg, val);
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* The input changed due to new input or channel changed */
+static void upd64031a_change(struct i2c_client *client)
+{
+ struct upd64031a_state *state = i2c_get_clientdata(client);
+ u8 reg = state->regs[R00];
+
+ v4l_dbg(1, debug, client, "changed input or channel\n");
+ upd64031a_write(client, R00, reg | 0x10);
+ upd64031a_write(client, R00, reg & ~0x10);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+ struct upd64031a_state *state = i2c_get_clientdata(client);
+ struct v4l2_routing *route = arg;
+
+ switch (cmd) {
+ case VIDIOC_S_FREQUENCY:
+ upd64031a_change(client);
+ break;
+
+ case VIDIOC_INT_G_VIDEO_ROUTING:
+ route->input = (state->gr_mode >> 6) |
+ (state->direct_3dycs_connect >> 4) |
+ (state->ext_comp_sync >> 1) |
+ (state->ext_vert_sync >> 2);
+ route->output = 0;
+ break;
+
+ case VIDIOC_INT_S_VIDEO_ROUTING:
+ {
+ u8 r00, r05, r08;
+
+ state->gr_mode = (route->input & 3) << 6;
+ state->direct_3dycs_connect = (route->input & 0xc) << 4;
+ state->ext_comp_sync = (route->input & UPD64031A_COMPOSITE_EXTERNAL) << 1;
+ state->ext_vert_sync = (route->input & UPD64031A_VERTICAL_EXTERNAL) << 2;
+ r00 = (state->regs[R00] & ~GR_MODE_MASK) | state->gr_mode;
+ r05 = (state->regs[R00] & ~SYNC_CIRCUIT_MASK) |
+ state->ext_comp_sync | state->ext_vert_sync;
+ r08 = (state->regs[R08] & ~DIRECT_3DYCS_CONNECT_MASK) |
+ state->direct_3dycs_connect;
+ upd64031a_write(client, R00, r00);
+ upd64031a_write(client, R05, r05);
+ upd64031a_write(client, R08, r08);
+ upd64031a_change(client);
+ break;
+ }
+
+ case VIDIOC_LOG_STATUS:
+ v4l_info(client, "Status: SA00=0x%02x SA01=0x%02x\n",
+ upd64031a_read(client, 0), upd64031a_read(client, 1));
+ break;
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_INT_G_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+
+ if (reg->i2c_id != I2C_DRIVERID_UPD64031A)
+ return -EINVAL;
+ reg->val = upd64031a_read(client, reg->reg & 0xff);
+ break;
+ }
+
+ case VIDIOC_INT_S_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+ u8 addr = reg->reg & 0xff;
+ u8 val = reg->val & 0xff;
+
+ if (reg->i2c_id != I2C_DRIVERID_UPD64031A)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ upd64031a_write(client, addr, val);
+ break;
+ }
+#endif
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* i2c implementation */
+
+static struct i2c_driver i2c_driver;
+
+static int upd64031a_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct upd64031a_state *state;
+ int i;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL) {
+ return -ENOMEM;
+ }
+
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &i2c_driver;
+ snprintf(client->name, sizeof(client->name) - 1, "uPD64031A");
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+ state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
+ if (state == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ i2c_set_clientdata(client, state);
+ memcpy(state->regs, upd64031a_init, sizeof(state->regs));
+ state->gr_mode = UPD64031A_GR_ON << 6;
+ state->direct_3dycs_connect = UPD64031A_3DYCS_COMPOSITE << 4;
+ state->ext_comp_sync = state->ext_vert_sync = 0;
+ for (i = 0; i < TOT_REGS; i++) {
+ upd64031a_write(client, i, state->regs[i]);
+ }
+
+ i2c_attach_client(client);
+
+ return 0;
+}
+
+static int upd64031a_probe(struct i2c_adapter *adapter)
+{
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, upd64031a_attach);
+ return 0;
+}
+
+static int upd64031a_detach(struct i2c_client *client)
+{
+ int err;
+
+ err = i2c_detach_client(client);
+ if (err)
+ return err;
+
+ kfree(client);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+ .driver = {
+ .name = "upd64031a",
+ },
+ .id = I2C_DRIVERID_UPD64031A,
+ .attach_adapter = upd64031a_probe,
+ .detach_client = upd64031a_detach,
+ .command = upd64031a_command,
+};
+
+
+static int __init upd64031a_init_module(void)
+{
+ return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit upd64031a_exit_module(void)
+{
+ i2c_del_driver(&i2c_driver);
+}
+
+module_init(upd64031a_init_module);
+module_exit(upd64031a_exit_module);
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c
new file mode 100644
index 00000000000..c3a7ffe5c26
--- /dev/null
+++ b/drivers/media/video/upd64083.c
@@ -0,0 +1,262 @@
+/*
+ * upd6408x - NEC Electronics 3-Dimensional Y/C separation driver
+ *
+ * 2003 by T.Adachi (tadachi@tadachi-net.com)
+ * 2003 by Takeru KOMORIYA <komoriya@paken.org>
+ * 2006 by Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/upd64083.h>
+
+MODULE_DESCRIPTION("uPD64083 driver");
+MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+module_param(debug, bool, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+static unsigned short normal_i2c[] = { 0xb8 >> 1, 0xba >> 1, I2C_CLIENT_END };
+
+
+I2C_CLIENT_INSMOD;
+
+enum {
+ R00 = 0, R01, R02, R03, R04,
+ R05, R06, R07, R08, R09,
+ R0A, R0B, R0C, R0D, R0E, R0F,
+ R10, R11, R12, R13, R14,
+ R15, R16,
+ TOT_REGS
+};
+
+struct upd64083_state {
+ u8 mode;
+ u8 ext_y_adc;
+ u8 regs[TOT_REGS];
+};
+
+/* Initial values when used in combination with the
+ NEC upd64031a ghost reduction chip. */
+static u8 upd64083_init[] = {
+ 0x1f, 0x01, 0xa0, 0x2d, 0x29, /* we use EXCSS=0 */
+ 0x36, 0xdd, 0x05, 0x56, 0x48,
+ 0x00, 0x3a, 0xa0, 0x05, 0x08,
+ 0x44, 0x60, 0x08, 0x52, 0xf8,
+ 0x53, 0x60, 0x10
+};
+
+/* ------------------------------------------------------------------------ */
+
+static void upd64083_log_status(struct i2c_client *client)
+{
+ u8 buf[7];
+
+ i2c_master_recv(client, buf, 7);
+ v4l_info(client, "Status: SA00=%02x SA01=%02x SA02=%02x SA03=%02x "
+ "SA04=%02x SA05=%02x SA06=%02x\n",
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void upd64083_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ u8 buf[2];
+
+ buf[0] = reg;
+ buf[1] = val;
+ v4l_dbg(1, debug, client, "writing reg addr: %02x val: %02x\n", reg, val);
+ if (i2c_master_send(client, buf, 2) != 2)
+ v4l_err(client, "I/O error write 0x%02x/0x%02x\n", reg, val);
+}
+
+/* ------------------------------------------------------------------------ */
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static u8 upd64083_read(struct i2c_client *client, u8 reg)
+{
+ u8 buf[7];
+
+ if (reg >= sizeof(buf))
+ return 0xff;
+ i2c_master_recv(client, buf, sizeof(buf));
+ return buf[reg];
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+ struct upd64083_state *state = i2c_get_clientdata(client);
+ struct v4l2_routing *route = arg;
+
+ switch (cmd) {
+ case VIDIOC_INT_G_VIDEO_ROUTING:
+ route->input = (state->mode >> 6) | (state->ext_y_adc >> 3);
+ route->output = 0;
+ break;
+
+ case VIDIOC_INT_S_VIDEO_ROUTING:
+ {
+ u8 r00, r02;
+
+ if (route->input > 7 || (route->input & 6) == 6)
+ return -EINVAL;
+ state->mode = (route->input & 3) << 6;
+ state->ext_y_adc = (route->input & UPD64083_EXT_Y_ADC) << 3;
+ r00 = (state->regs[R00] & ~(3 << 6)) | state->mode;
+ r02 = (state->regs[R02] & ~(1 << 5)) | state->ext_y_adc;
+ upd64083_write(client, R00, r00);
+ upd64083_write(client, R02, r02);
+ break;
+ }
+
+ case VIDIOC_LOG_STATUS:
+ upd64083_log_status(client);
+ break;
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_INT_G_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+
+ if (reg->i2c_id != I2C_DRIVERID_UPD64083)
+ return -EINVAL;
+ reg->val = upd64083_read(client, reg->reg & 0xff);
+ break;
+ }
+
+ case VIDIOC_INT_S_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+ u8 addr = reg->reg & 0xff;
+ u8 val = reg->val & 0xff;
+
+ if (reg->i2c_id != I2C_DRIVERID_UPD64083)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ upd64083_write(client, addr, val);
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* i2c implementation */
+
+static struct i2c_driver i2c_driver;
+
+static int upd64083_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct upd64083_state *state;
+ int i;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL) {
+ return -ENOMEM;
+ }
+
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &i2c_driver;
+ snprintf(client->name, sizeof(client->name) - 1, "uPD64083");
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+ state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL);
+ if (state == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ i2c_set_clientdata(client, state);
+ /* Initially assume that a ghost reduction chip is present */
+ state->mode = 0; /* YCS mode */
+ state->ext_y_adc = (1 << 5);
+ memcpy(state->regs, upd64083_init, TOT_REGS);
+ for (i = 0; i < TOT_REGS; i++) {
+ upd64083_write(client, i, state->regs[i]);
+ }
+ i2c_attach_client(client);
+
+ return 0;
+}
+
+static int upd64083_probe(struct i2c_adapter *adapter)
+{
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, upd64083_attach);
+ return 0;
+}
+
+static int upd64083_detach(struct i2c_client *client)
+{
+ int err;
+
+ err = i2c_detach_client(client);
+ if (err)
+ return err;
+
+ kfree(client);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+ .driver = {
+ .name = "upd64083",
+ },
+ .id = I2C_DRIVERID_UPD64083,
+ .attach_adapter = upd64083_probe,
+ .detach_client = upd64083_detach,
+ .command = upd64083_command,
+};
+
+
+static int __init upd64083_init_module(void)
+{
+ return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit upd64083_exit_module(void)
+{
+ i2c_del_driver(&i2c_driver);
+}
+
+module_init(upd64083_init_module);
+module_exit(upd64083_exit_module);
diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig
new file mode 100644
index 00000000000..39269a2c563
--- /dev/null
+++ b/drivers/media/video/usbvideo/Kconfig
@@ -0,0 +1,38 @@
+config VIDEO_USBVIDEO
+ tristate
+
+config USB_VICAM
+ tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
+ depends on USB && VIDEO_V4L1 && EXPERIMENTAL
+ select VIDEO_USBVIDEO
+ ---help---
+ Say Y here if you have 3com homeconnect camera (vicam).
+
+ To compile this driver as a module, choose M here: the
+ module will be called vicam.
+
+config USB_IBMCAM
+ tristate "USB IBM (Xirlink) C-it Camera support"
+ depends on USB && VIDEO_V4L1
+ select VIDEO_USBVIDEO
+ ---help---
+ Say Y here if you want to connect a IBM "C-It" camera, also known as
+ "Xirlink PC Camera" to your computer's USB port.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ibmcam.
+
+ This camera has several configuration options which
+ can be specified when you load the module. Read
+ <file:Documentation/video4linux/ibmcam.txt> to learn more.
+
+config USB_KONICAWC
+ tristate "USB Konica Webcam support"
+ depends on USB && VIDEO_V4L1
+ select VIDEO_USBVIDEO
+ ---help---
+ Say Y here if you want support for webcams based on a Konica
+ chipset. This is known to work with the Intel YC76 webcam.
+
+ To compile this driver as a module, choose M here: the
+ module will be called konicawc.
diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile
index ed410a5ee8c..bb52eb8dc2f 100644
--- a/drivers/media/video/usbvideo/Makefile
+++ b/drivers/media/video/usbvideo/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o
-obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o
-obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o
-
+obj-$(CONFIG_VIDEO_USBVIDEO) += usbvideo.o
+obj-$(CONFIG_USB_IBMCAM) += ibmcam.o ultracam.o
+obj-$(CONFIG_USB_KONICAWC) += konicawc.o
+obj-$(CONFIG_USB_VICAM) += vicam.o
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 11a97f30b87..d330fa985bc 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -317,6 +317,7 @@ static const char *v4l2_int_ioctls[] = {
[_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY",
[_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG",
+ [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE",
[_IOC_NR(VIDIOC_INT_S_REGISTER)] = "VIDIOC_INT_S_REGISTER",
[_IOC_NR(VIDIOC_INT_G_REGISTER)] = "VIDIOC_INT_G_REGISTER",
[_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET",
@@ -325,7 +326,12 @@ static const char *v4l2_int_ioctls[] = {
[_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA",
[_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA",
[_IOC_NR(VIDIOC_INT_G_CHIP_IDENT)] = "VIDIOC_INT_G_CHIP_IDENT",
- [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ"
+ [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ",
+ [_IOC_NR(VIDIOC_INT_S_STANDBY)] = "VIDIOC_INT_S_STANDBY",
+ [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING",
+ [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING",
+ [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING",
+ [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING"
};
#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index d2ca0f08d0d..acc5ea93668 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -399,19 +399,25 @@ void videobuf_queue_pci(struct videobuf_queue* q)
int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
{
struct videobuf_queue q;
+ struct videobuf_queue_ops qops;
q.dev=pci;
- q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg;
+ qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg;
+ qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
+ q.ops = &qops;
- return (videobuf_dma_unmap(&q,dma));
+ return (videobuf_dma_map(&q,dma));
}
int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
{
struct videobuf_queue q;
+ struct videobuf_queue_ops qops;
q.dev=pci;
- q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg;
+ qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg;
+ qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
+ q.ops = &qops;
return (videobuf_dma_unmap(&q,dma));
}
@@ -923,7 +929,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
/* need to capture a new frame */
retval = -ENOMEM;
q->read_buf = videobuf_alloc(q->msize);
- dprintk(1,"video alloc=0x%08x\n",(unsigned int) q->read_buf);
+ dprintk(1,"video alloc=0x%p\n", q->read_buf);
if (NULL == q->read_buf)
goto done;
q->read_buf->memory = V4L2_MEMORY_USERPTR;
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 75e3d41382f..5f87dd5f1d0 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -97,7 +97,7 @@ static int video_open(struct inode *inode, struct file *file)
unsigned int minor = iminor(inode);
int err = 0;
struct video_device *vfl;
- struct file_operations *old_fops;
+ const struct file_operations *old_fops;
if(minor>=VIDEO_NUM_DEVICES)
return -ENODEV;
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 5e813404d06..779db26771c 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -26,6 +26,11 @@
#include <linux/random.h>
#include <linux/version.h>
#include <linux/videodev2.h>
+#include <linux/dma-mapping.h>
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+/* Include V4L1 specific functions. Should be removed soon */
+#include <linux/videodev.h>
+#endif
#include <linux/interrupt.h>
#include <media/video-buf.h>
#include <media/v4l2-common.h>
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
new file mode 100644
index 00000000000..a9b59c35cd6
--- /dev/null
+++ b/drivers/media/video/wm8739.c
@@ -0,0 +1,355 @@
+/*
+ * wm8739
+ *
+ * Copyright (C) 2005 T. Adachi <tadachi@tadachi-net.com>
+ *
+ * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl>
+ * - Cleanup
+ *
+ * This program is free software; 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/types.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+
+MODULE_DESCRIPTION("wm8739 driver");
+MODULE_AUTHOR("T. Adachi, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+static unsigned short normal_i2c[] = { 0x34 >> 1, 0x36 >> 1, I2C_CLIENT_END };
+
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+
+I2C_CLIENT_INSMOD;
+
+/* ------------------------------------------------------------------------ */
+
+enum {
+ R0 = 0, R1,
+ R5 = 5, R6, R7, R8, R9, R15 = 15,
+ TOT_REGS
+};
+
+struct wm8739_state {
+ u32 clock_freq;
+ u8 muted;
+ u16 volume;
+ u16 balance;
+ u8 vol_l; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
+ u8 vol_r; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
+};
+
+/* ------------------------------------------------------------------------ */
+
+static int wm8739_write(struct i2c_client *client, int reg, u16 val)
+{
+ int i;
+
+ if (reg < 0 || reg >= TOT_REGS) {
+ v4l_err(client, "Invalid register R%d\n", reg);
+ return -1;
+ }
+
+ v4l_dbg(1, debug, client, "write: %02x %02x\n", reg, val);
+
+ for (i = 0; i < 3; i++) {
+ if (i2c_smbus_write_byte_data(client, (reg << 1) |
+ (val >> 8), val & 0xff) == 0) {
+ return 0;
+ }
+ }
+ v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg);
+ return -1;
+}
+
+/* write regs to set audio volume etc */
+static void wm8739_set_audio(struct i2c_client *client)
+{
+ struct wm8739_state *state = i2c_get_clientdata(client);
+ u16 mute = state->muted ? 0x80 : 0;
+
+ /* Volume setting: bits 0-4, 0x1f = 12 dB, 0x00 = -34.5 dB
+ * Default setting: 0x17 = 0 dB
+ */
+ wm8739_write(client, R0, (state->vol_l & 0x1f) | mute);
+ wm8739_write(client, R1, (state->vol_r & 0x1f) | mute);
+}
+
+static int wm8739_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+ struct wm8739_state *state = i2c_get_clientdata(client);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ ctrl->value = state->muted;
+ break;
+
+ case V4L2_CID_AUDIO_VOLUME:
+ ctrl->value = state->volume;
+ break;
+
+ case V4L2_CID_AUDIO_BALANCE:
+ ctrl->value = state->balance;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int wm8739_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+ struct wm8739_state *state = i2c_get_clientdata(client);
+ unsigned int work_l, work_r;
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ state->muted = ctrl->value;
+ break;
+
+ case V4L2_CID_AUDIO_VOLUME:
+ state->volume = ctrl->value;
+ break;
+
+ case V4L2_CID_AUDIO_BALANCE:
+ state->balance = ctrl->value;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* normalize ( 65535 to 0 -> 31 to 0 (12dB to -34.5dB) ) */
+ work_l = (min(65536 - state->balance, 32768) * state->volume) / 32768;
+ work_r = (min(state->balance, (u16)32768) * state->volume) / 32768;
+
+ state->vol_l = (long)work_l * 31 / 65535;
+ state->vol_r = (long)work_r * 31 / 65535;
+
+ /* set audio volume etc. */
+ wm8739_set_audio(client);
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static struct v4l2_queryctrl wm8739_qctrl[] = {
+ {
+ .id = V4L2_CID_AUDIO_VOLUME,
+ .name = "Volume",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 58880,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_AUDIO_MUTE,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ },{
+ .id = V4L2_CID_AUDIO_BALANCE,
+ .name = "Balance",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }
+};
+
+/* ------------------------------------------------------------------------ */
+
+static int wm8739_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+ struct wm8739_state *state = i2c_get_clientdata(client);
+
+ switch (cmd) {
+ case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+ {
+ u32 audiofreq = *(u32 *)arg;
+
+ state->clock_freq = audiofreq;
+ wm8739_write(client, R9, 0x000); /* de-activate */
+ switch (audiofreq) {
+ case 44100:
+ wm8739_write(client, R8, 0x020); /* 256fps, fs=44.1k */
+ break;
+ case 48000:
+ wm8739_write(client, R8, 0x000); /* 256fps, fs=48k */
+ break;
+ case 32000:
+ wm8739_write(client, R8, 0x018); /* 256fps, fs=32k */
+ break;
+ default:
+ break;
+ }
+ wm8739_write(client, R9, 0x001); /* activate */
+ break;
+ }
+
+ case VIDIOC_G_CTRL:
+ return wm8739_get_ctrl(client, arg);
+
+ case VIDIOC_S_CTRL:
+ return wm8739_set_ctrl(client, arg);
+
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *qc = arg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8739_qctrl); i++)
+ if (qc->id && qc->id == wm8739_qctrl[i].id) {
+ memcpy(qc, &wm8739_qctrl[i], sizeof(*qc));
+ return 0;
+ }
+ return -EINVAL;
+ }
+
+ case VIDIOC_LOG_STATUS:
+ v4l_info(client, "Frequency: %u Hz\n", state->clock_freq);
+ v4l_info(client, "Volume L: %02x%s\n", state->vol_l & 0x1f,
+ state->muted ? " (muted)" : "");
+ v4l_info(client, "Volume R: %02x%s\n", state->vol_r & 0x1f,
+ state->muted ? " (muted)" : "");
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* i2c implementation */
+
+static struct i2c_driver i2c_driver;
+
+static int wm8739_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct wm8739_state *state;
+
+ /* Check if the adapter supports the needed features */
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return 0;
+
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &i2c_driver;
+ snprintf(client->name, sizeof(client->name) - 1, "wm8739");
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+ state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL);
+ if (state == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ state->vol_l = 0x17; /* 0dB */
+ state->vol_r = 0x17; /* 0dB */
+ state->muted = 0;
+ state->balance = 32768;
+ /* normalize (12dB(31) to -34.5dB(0) [0dB(23)] -> 65535 to 0) */
+ state->volume = ((long)state->vol_l + 1) * 65535 / 31;
+ state->clock_freq = 48000;
+ i2c_set_clientdata(client, state);
+
+ /* initialize wm8739 */
+ wm8739_write(client, R15, 0x00); /* reset */
+ wm8739_write(client, R5, 0x000); /* filter setting, high path, offet clear */
+ wm8739_write(client, R6, 0x000); /* ADC, OSC, Power Off mode Disable */
+ wm8739_write(client, R7, 0x049); /* Digital Audio interface format */
+ /* Enable Master mode */
+ /* 24 bit, MSB first/left justified */
+ wm8739_write(client, R8, 0x000); /* sampling control */
+ /* normal, 256fs, 48KHz sampling rate */
+ wm8739_write(client, R9, 0x001); /* activate */
+ wm8739_set_audio(client); /* set volume/mute */
+
+ i2c_attach_client(client);
+
+ return 0;
+}
+
+static int wm8739_probe(struct i2c_adapter *adapter)
+{
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, wm8739_attach);
+ return 0;
+}
+
+static int wm8739_detach(struct i2c_client *client)
+{
+ int err;
+
+ err = i2c_detach_client(client);
+ if (err)
+ return err;
+
+ kfree(client);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+ .driver = {
+ .name = "wm8739",
+ },
+ .id = I2C_DRIVERID_WM8739,
+ .attach_adapter = wm8739_probe,
+ .detach_client = wm8739_detach,
+ .command = wm8739_command,
+};
+
+
+static int __init wm8739_init_module(void)
+{
+ return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit wm8739_cleanup_module(void)
+{
+ i2c_del_driver(&i2c_driver);
+}
+
+module_init(wm8739_init_module);
+module_exit(wm8739_cleanup_module);
diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig
new file mode 100644
index 00000000000..115833e4f4d
--- /dev/null
+++ b/drivers/media/video/zc0301/Kconfig
@@ -0,0 +1,11 @@
+config USB_ZC0301
+ tristate "USB ZC0301 Image Processor and Control Chip support"
+ depends on USB && VIDEO_V4L1
+ ---help---
+ Say Y here if you want support for cameras based on the ZC0301
+ Image Processor and Control Chip.
+
+ See <file:Documentation/video4linux/zc0301.txt> for more info.
+
+ To compile this driver as a module, choose M here: the
+ module will be called zc0301.
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 266414ca281..a30084076ac 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1189,7 +1189,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->diagPending = 0;
spin_lock_init(&ioc->diagLock);
spin_lock_init(&ioc->fc_rescan_work_lock);
- spin_lock_init(&ioc->fc_rport_lock);
spin_lock_init(&ioc->initializing_hba_lock);
/* Initialize the event logging.
@@ -1606,6 +1605,21 @@ mpt_resume(struct pci_dev *pdev)
}
#endif
+static int
+mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
+{
+ if ((MptDriverClass[index] == MPTSPI_DRIVER &&
+ ioc->bus_type != SPI) ||
+ (MptDriverClass[index] == MPTFC_DRIVER &&
+ ioc->bus_type != FC) ||
+ (MptDriverClass[index] == MPTSAS_DRIVER &&
+ ioc->bus_type != SAS))
+ /* make sure we only call the relevant reset handler
+ * for the bus */
+ return 0;
+ return (MptResetHandlers[index])(ioc, reset_phase);
+}
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mpt_do_ioc_recovery - Initialize or recover MPT adapter.
@@ -1886,14 +1900,14 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
if ((ret == 0) && MptResetHandlers[ii]) {
dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
ioc->name, ii));
- rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
+ rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
handlers++;
}
if (alt_ioc_ready && MptResetHandlers[ii]) {
drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
ioc->name, ioc->alt_ioc->name, ii));
- rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
+ rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
handlers++;
}
}
@@ -3268,11 +3282,11 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
if (MptResetHandlers[ii]) {
dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
ioc->name, ii));
- r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
+ r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
if (ioc->alt_ioc) {
dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
ioc->name, ioc->alt_ioc->name, ii));
- r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
+ r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
}
}
}
@@ -5707,11 +5721,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
if (MptResetHandlers[ii]) {
dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
ioc->name, ii));
- r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
+ r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
if (ioc->alt_ioc) {
dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
ioc->name, ioc->alt_ioc->name, ii));
- r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
+ r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
}
}
}
@@ -5736,11 +5750,13 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
return rc;
}
+# define EVENT_DESCR_STR_SZ 100
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static void
EventDescriptionStr(u8 event, u32 evData0, char *evStr)
{
- char *ds;
+ char *ds = NULL;
switch(event) {
case MPI_EVENT_NONE:
@@ -5777,9 +5793,9 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
ds = "Loop State(LIP) Change";
else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
- ds = "Loop State(LPE) Change"; /* ??? */
+ ds = "Loop State(LPE) Change"; /* ??? */
else
- ds = "Loop State(LPB) Change"; /* ??? */
+ ds = "Loop State(LPB) Change"; /* ??? */
break;
case MPI_EVENT_LOGOUT:
ds = "Logout";
@@ -5841,27 +5857,32 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
break;
case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
{
- char buf[50];
u8 id = (u8)(evData0);
u8 ReasonCode = (u8)(evData0 >> 16);
switch (ReasonCode) {
case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
- sprintf(buf,"SAS Device Status Change: Added: id=%d", id);
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Device Status Change: Added: id=%d", id);
break;
case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
- sprintf(buf,"SAS Device Status Change: Deleted: id=%d", id);
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Device Status Change: Deleted: id=%d", id);
break;
case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
- sprintf(buf,"SAS Device Status Change: SMART Data: id=%d", id);
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Device Status Change: SMART Data: id=%d",
+ id);
break;
case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
- sprintf(buf,"SAS Device Status Change: No Persistancy Added: id=%d", id);
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Device Status Change: No Persistancy "
+ "Added: id=%d", id);
break;
default:
- sprintf(buf,"SAS Device Status Change: Unknown: id=%d", id);
- break;
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Device Status Change: Unknown: id=%d", id);
+ break;
}
- ds = buf;
break;
}
case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
@@ -5878,41 +5899,46 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
break;
case MPI_EVENT_SAS_PHY_LINK_STATUS:
{
- char buf[50];
u8 LinkRates = (u8)(evData0 >> 8);
u8 PhyNumber = (u8)(evData0);
LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
switch (LinkRates) {
case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
- sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS PHY Link Status: Phy=%d:"
" Rate Unknown",PhyNumber);
break;
case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
- sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS PHY Link Status: Phy=%d:"
" Phy Disabled",PhyNumber);
break;
case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
- sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS PHY Link Status: Phy=%d:"
" Failed Speed Nego",PhyNumber);
break;
case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
- sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS PHY Link Status: Phy=%d:"
" Sata OOB Completed",PhyNumber);
break;
case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
- sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS PHY Link Status: Phy=%d:"
" Rate 1.5 Gbps",PhyNumber);
break;
case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
- sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS PHY Link Status: Phy=%d:"
" Rate 3.0 Gpbs",PhyNumber);
break;
default:
- sprintf(buf,"SAS PHY Link Status: Phy=%d", PhyNumber);
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS PHY Link Status: Phy=%d", PhyNumber);
break;
}
- ds = buf;
break;
}
case MPI_EVENT_SAS_DISCOVERY_ERROR:
@@ -5921,9 +5947,8 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
case MPI_EVENT_IR_RESYNC_UPDATE:
{
u8 resync_complete = (u8)(evData0 >> 16);
- char buf[40];
- sprintf(buf,"IR Resync Update: Complete = %d:",resync_complete);
- ds = buf;
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "IR Resync Update: Complete = %d:",resync_complete);
break;
}
case MPI_EVENT_IR2:
@@ -5976,7 +6001,8 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
ds = "Unknown";
break;
}
- strcpy(evStr,ds);
+ if (ds)
+ strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5998,7 +6024,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
int ii;
int r = 0;
int handlers = 0;
- char evStr[100];
+ char evStr[EVENT_DESCR_STR_SZ];
u8 event;
/*
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index be7e8501b53..f673cca507e 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.03.08"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.08"
+#define MPT_LINUX_VERSION_COMMON "3.03.09"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.09"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -489,7 +489,6 @@ typedef struct _RaidCfgData {
#define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */
#define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */
-#define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04 /* target mapped in vdev */
/*
* data allocated for each fc rport device
@@ -501,7 +500,6 @@ struct mptfc_rport_info
struct scsi_target *starget;
FCDevicePage0_t pg0;
u8 flags;
- u8 remap_needed;
};
/*
@@ -628,11 +626,11 @@ typedef struct _MPT_ADAPTER
struct work_struct mptscsih_persistTask;
struct list_head fc_rports;
- spinlock_t fc_rport_lock; /* list and ri flags */
spinlock_t fc_rescan_work_lock;
int fc_rescan_work_count;
struct work_struct fc_rescan_work;
-
+ char fc_rescan_work_q_name[KOBJ_NAME_LEN];
+ struct workqueue_struct *fc_rescan_work_q;
} MPT_ADAPTER;
/*
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index b343f2a68b1..856487741ef 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -341,9 +341,6 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
rid->port_id = pg0->PortIdentifier;
rid->roles = FC_RPORT_ROLE_UNKNOWN;
- rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
- if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
- rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
return 0;
}
@@ -355,15 +352,18 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
struct fc_rport *rport;
struct mptfc_rport_info *ri;
int new_ri = 1;
- u64 pn;
- unsigned long flags;
+ u64 pn, nn;
VirtTarget *vtarget;
+ u32 roles = FC_RPORT_ROLE_UNKNOWN;
if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
return;
+ roles |= FC_RPORT_ROLE_FCP_TARGET;
+ if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
+ roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+
/* scan list looking for a match */
- spin_lock_irqsave(&ioc->fc_rport_lock, flags);
list_for_each_entry(ri, &ioc->fc_rports, list) {
pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
if (pn == rport_ids.port_name) { /* match */
@@ -373,11 +373,9 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
}
}
if (new_ri) { /* allocate one */
- spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
if (!ri)
return;
- spin_lock_irqsave(&ioc->fc_rport_lock, flags);
list_add_tail(&ri->list, &ioc->fc_rports);
}
@@ -387,14 +385,11 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
/* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
- spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
- spin_lock_irqsave(&ioc->fc_rport_lock, flags);
if (rport) {
ri->rport = rport;
if (new_ri) /* may have been reset by user */
rport->dev_loss_tmo = mptfc_dev_loss_tmo;
- *((struct mptfc_rport_info **)rport->dd_data) = ri;
/*
* if already mapped, remap here. If not mapped,
* target_alloc will allocate vtarget and map,
@@ -406,16 +401,21 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
vtarget->target_id = pg0->CurrentTargetID;
vtarget->bus_id = pg0->CurrentBus;
}
- ri->remap_needed = 0;
}
+ *((struct mptfc_rport_info **)rport->dd_data) = ri;
+ /* scan will be scheduled once rport becomes a target */
+ fc_remote_port_rolechg(rport,roles);
+
+ pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+ nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
dfcprintk ((MYIOC_s_INFO_FMT
"mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
"rport tid %d, tmo %d\n",
ioc->name,
ioc->sh->host_no,
pg0->PortIdentifier,
- pg0->WWNN,
- pg0->WWPN,
+ (unsigned long long)nn,
+ (unsigned long long)pn,
pg0->CurrentTargetID,
ri->rport->scsi_target_id,
ri->rport->dev_loss_tmo));
@@ -425,8 +425,6 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
ri = NULL;
}
}
- spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
-
}
/*
@@ -476,7 +474,6 @@ mptfc_target_alloc(struct scsi_target *starget)
vtarget->target_id = ri->pg0.CurrentTargetID;
vtarget->bus_id = ri->pg0.CurrentBus;
ri->starget = starget;
- ri->remap_needed = 0;
rc = 0;
}
}
@@ -502,10 +499,10 @@ mptfc_slave_alloc(struct scsi_device *sdev)
VirtDevice *vdev;
struct scsi_target *starget;
struct fc_rport *rport;
- unsigned long flags;
- rport = starget_to_rport(scsi_target(sdev));
+ starget = scsi_target(sdev);
+ rport = starget_to_rport(starget);
if (!rport || fc_remote_port_chkready(rport))
return -ENXIO;
@@ -519,10 +516,8 @@ mptfc_slave_alloc(struct scsi_device *sdev)
return -ENOMEM;
}
- spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
sdev->hostdata = vdev;
- starget = scsi_target(sdev);
vtarget = starget->hostdata;
if (vtarget->num_luns == 0) {
@@ -535,14 +530,16 @@ mptfc_slave_alloc(struct scsi_device *sdev)
vdev->vtarget = vtarget;
vdev->lun = sdev->lun;
- spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
-
vtarget->num_luns++;
+
#ifdef DMPT_DEBUG_FC
- {
+ {
+ u64 nn, pn;
struct mptfc_rport_info *ri;
ri = *((struct mptfc_rport_info **)rport->dd_data);
+ pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+ nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
dfcprintk ((MYIOC_s_INFO_FMT
"mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
"CurrentTargetID %d, %x %llx %llx\n",
@@ -550,7 +547,9 @@ mptfc_slave_alloc(struct scsi_device *sdev)
sdev->host->host_no,
vtarget->num_luns,
sdev->id, ri->pg0.CurrentTargetID,
- ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN));
+ ri->pg0.PortIdentifier,
+ (unsigned long long)pn,
+ (unsigned long long)nn));
}
#endif
@@ -570,11 +569,31 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
done(SCpnt);
return 0;
}
+
+ /* dd_data is null until finished adding target */
ri = *((struct mptfc_rport_info **)rport->dd_data);
- if (unlikely(ri->remap_needed))
- return SCSI_MLQUEUE_HOST_BUSY;
+ if (unlikely(!ri)) {
+ dfcprintk ((MYIOC_s_INFO_FMT
+ "mptfc_qcmd.%d: %d:%d, dd_data is null.\n",
+ ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
+ ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
+ SCpnt->device->id,SCpnt->device->lun));
+ SCpnt->result = DID_IMM_RETRY << 16;
+ done(SCpnt);
+ return 0;
+ }
- return mptscsih_qcmd(SCpnt,done);
+ err = mptscsih_qcmd(SCpnt,done);
+#ifdef DMPT_DEBUG_FC
+ if (unlikely(err)) {
+ dfcprintk ((MYIOC_s_INFO_FMT
+ "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n",
+ ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
+ ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
+ SCpnt->device->id,SCpnt->device->lun));
+ }
+#endif
+ return err;
}
static void
@@ -615,18 +634,17 @@ mptfc_rescan_devices(void *arg)
MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
int ii;
int work_to_do;
+ u64 pn;
unsigned long flags;
struct mptfc_rport_info *ri;
do {
/* start by tagging all ports as missing */
- spin_lock_irqsave(&ioc->fc_rport_lock,flags);
list_for_each_entry(ri, &ioc->fc_rports, list) {
if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
}
}
- spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
/*
* now rescan devices known to adapter,
@@ -639,33 +657,24 @@ mptfc_rescan_devices(void *arg)
}
/* delete devices still missing */
- spin_lock_irqsave(&ioc->fc_rport_lock, flags);
list_for_each_entry(ri, &ioc->fc_rports, list) {
/* if newly missing, delete it */
- if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |
- MPT_RPORT_INFO_FLAGS_MISSING))
- == (MPT_RPORT_INFO_FLAGS_REGISTERED |
- MPT_RPORT_INFO_FLAGS_MISSING)) {
+ if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
MPT_RPORT_INFO_FLAGS_MISSING);
- ri->remap_needed = 1;
- fc_remote_port_delete(ri->rport);
- /*
- * remote port not really deleted 'cause
- * binding is by WWPN and driver only
- * registers FCP_TARGETs but cannot trust
- * data structures.
- */
+ fc_remote_port_delete(ri->rport); /* won't sleep */
ri->rport = NULL;
+
+ pn = (u64)ri->pg0.WWPN.High << 32 |
+ (u64)ri->pg0.WWPN.Low;
dfcprintk ((MYIOC_s_INFO_FMT
"mptfc_rescan.%d: %llx deleted\n",
ioc->name,
ioc->sh->host_no,
- ri->pg0.WWPN));
+ (unsigned long long)pn));
}
}
- spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
/*
* allow multiple passes as target state
@@ -870,10 +879,23 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_mptfc_probe;
}
- for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
- mptfc_init_host_attr(ioc,ii);
- mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
- }
+ /* initialize workqueue */
+
+ snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
+ sh->host_no);
+ ioc->fc_rescan_work_q =
+ create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
+ if (!ioc->fc_rescan_work_q)
+ goto out_mptfc_probe;
+
+ /*
+ * scan for rports -
+ * by doing it via the workqueue, some locking is eliminated
+ */
+
+ ioc->fc_rescan_work_count = 1;
+ queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
+ flush_workqueue(ioc->fc_rescan_work_q);
return 0;
@@ -949,8 +971,18 @@ mptfc_init(void)
static void __devexit
mptfc_remove(struct pci_dev *pdev)
{
- MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
- struct mptfc_rport_info *p, *n;
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ struct mptfc_rport_info *p, *n;
+ struct workqueue_struct *work_q;
+ unsigned long flags;
+
+ /* destroy workqueue */
+ if ((work_q=ioc->fc_rescan_work_q)) {
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ ioc->fc_rescan_work_q = NULL;
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+ destroy_workqueue(work_q);
+ }
fc_remove_host(ioc->sh);
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 010d4a39269..af6ec553ff7 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -91,6 +91,7 @@ enum mptsas_hotplug_action {
MPTSAS_DEL_DEVICE,
MPTSAS_ADD_RAID,
MPTSAS_DEL_RAID,
+ MPTSAS_IGNORE_EVENT,
};
struct mptsas_hotplug_event {
@@ -298,6 +299,26 @@ mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
return rc;
}
+/*
+ * Returns true if there is a scsi end device
+ */
+static inline int
+mptsas_is_end_device(struct mptsas_devinfo * attached)
+{
+ if ((attached->handle) &&
+ (attached->device_info &
+ MPI_SAS_DEVICE_INFO_END_DEVICE) &&
+ ((attached->device_info &
+ MPI_SAS_DEVICE_INFO_SSP_TARGET) |
+ (attached->device_info &
+ MPI_SAS_DEVICE_INFO_STP_TARGET) |
+ (attached->device_info &
+ MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
+ return 1;
+ else
+ return 0;
+}
+
static int
mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
u32 form, u32 form_specific)
@@ -366,7 +387,15 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
static int
mptsas_slave_configure(struct scsi_device *sdev)
{
- sas_read_port_mode_page(sdev);
+ struct Scsi_Host *host = sdev->host;
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+
+ /*
+ * RAID volumes placed beyond the last expected port.
+ * Ignore sending sas mode pages in that case..
+ */
+ if (sdev->channel < hd->ioc->num_ports)
+ sas_read_port_mode_page(sdev);
return mptscsih_slave_configure(sdev);
}
@@ -864,7 +893,11 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
SasDevicePage0_t *buffer;
dma_addr_t dma_handle;
__le64 sas_address;
- int error;
+ int error=0;
+
+ if (ioc->sas_discovery_runtime &&
+ mptsas_is_end_device(device_info))
+ goto out;
hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
hdr.ExtPageLength = 0;
@@ -1001,7 +1034,11 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
CONFIGPARMS cfg;
SasExpanderPage1_t *buffer;
dma_addr_t dma_handle;
- int error;
+ int error=0;
+
+ if (ioc->sas_discovery_runtime &&
+ mptsas_is_end_device(&phy_info->attached))
+ goto out;
hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
hdr.ExtPageLength = 0;
@@ -1060,26 +1097,6 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
return error;
}
-/*
- * Returns true if there is a scsi end device
- */
-static inline int
-mptsas_is_end_device(struct mptsas_devinfo * attached)
-{
- if ((attached->handle) &&
- (attached->device_info &
- MPI_SAS_DEVICE_INFO_END_DEVICE) &&
- ((attached->device_info &
- MPI_SAS_DEVICE_INFO_SSP_TARGET) |
- (attached->device_info &
- MPI_SAS_DEVICE_INFO_STP_TARGET) |
- (attached->device_info &
- MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
- return 1;
- else
- return 0;
-}
-
static void
mptsas_parse_device_info(struct sas_identify *identify,
struct mptsas_devinfo *device_info)
@@ -1729,6 +1746,9 @@ mptsas_hotplug_work(void *arg)
break;
case MPTSAS_ADD_DEVICE:
+ if (ev->phys_disk_num_valid)
+ mpt_findImVolumes(ioc);
+
/*
* Refresh sas device pg0 data
*/
@@ -1860,6 +1880,9 @@ mptsas_hotplug_work(void *arg)
scsi_device_put(sdev);
mpt_findImVolumes(ioc);
break;
+ case MPTSAS_IGNORE_EVENT:
+ default:
+ break;
}
kfree(ev);
@@ -1932,7 +1955,8 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
EVENT_DATA_RAID *raid_event_data)
{
struct mptsas_hotplug_event *ev;
- RAID_VOL0_STATUS * volumeStatus;
+ int status = le32_to_cpu(raid_event_data->SettingsStatus);
+ int state = (status >> 8) & 0xff;
if (ioc->bus_type != SAS)
return;
@@ -1947,6 +1971,7 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
ev->ioc = ioc;
ev->id = raid_event_data->VolumeID;
+ ev->event_type = MPTSAS_IGNORE_EVENT;
switch (raid_event_data->ReasonCode) {
case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
@@ -1958,6 +1983,25 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
ev->phys_disk_num = raid_event_data->PhysDiskNum;
ev->event_type = MPTSAS_DEL_DEVICE;
break;
+ case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
+ switch (state) {
+ case MPI_PD_STATE_ONLINE:
+ ioc->raid_data.isRaid = 1;
+ ev->phys_disk_num_valid = 1;
+ ev->phys_disk_num = raid_event_data->PhysDiskNum;
+ ev->event_type = MPTSAS_ADD_DEVICE;
+ break;
+ case MPI_PD_STATE_MISSING:
+ case MPI_PD_STATE_NOT_COMPATIBLE:
+ case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
+ case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
+ case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
+ ev->event_type = MPTSAS_DEL_DEVICE;
+ break;
+ default:
+ break;
+ }
+ break;
case MPI_EVENT_RAID_RC_VOLUME_DELETED:
ev->event_type = MPTSAS_DEL_RAID;
break;
@@ -1965,11 +2009,18 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
ev->event_type = MPTSAS_ADD_RAID;
break;
case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
- volumeStatus = (RAID_VOL0_STATUS *) &
- raid_event_data->SettingsStatus;
- ev->event_type = (volumeStatus->State ==
- MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
- MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
+ switch (state) {
+ case MPI_RAIDVOL0_STATUS_STATE_FAILED:
+ case MPI_RAIDVOL0_STATUS_STATE_MISSING:
+ ev->event_type = MPTSAS_DEL_RAID;
+ break;
+ case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
+ case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
+ ev->event_type = MPTSAS_ADD_RAID;
+ break;
+ default:
+ break;
+ }
break;
default:
break;
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 3729062db31..84fa271eb8f 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -632,7 +632,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
/* Spoof to SCSI Selection Timeout! */
- sc->result = DID_NO_CONNECT << 16;
+ if (ioc->bus_type != FC)
+ sc->result = DID_NO_CONNECT << 16;
+ /* else fibre, just stall until rescan event */
+ else
+ sc->result = DID_REQUEUE << 16;
if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
hd->sel_timeout[pScsiReq->TargetID]++;
@@ -877,7 +881,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
struct scsi_cmnd *sc;
dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
- vdevice->target_id, vdevice->lun, max));
+ vdevice->vtarget->target_id, vdevice->lun, max));
for (ii=0; ii < max; ii++) {
if ((sc = hd->ScsiLookup[ii]) != NULL) {
@@ -1645,7 +1649,6 @@ int
mptscsih_abort(struct scsi_cmnd * SCpnt)
{
MPT_SCSI_HOST *hd;
- MPT_ADAPTER *ioc;
MPT_FRAME_HDR *mf;
u32 ctx2abort;
int scpnt_idx;
@@ -1663,14 +1666,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
return FAILED;
}
- ioc = hd->ioc;
- if (hd->resetPending) {
- return FAILED;
- }
-
- if (hd->timeouts < -1)
- hd->timeouts++;
-
/* Find this command
*/
if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
@@ -1684,6 +1679,13 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
return SUCCESS;
}
+ if (hd->resetPending) {
+ return FAILED;
+ }
+
+ if (hd->timeouts < -1)
+ hd->timeouts++;
+
printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
hd->ioc->name, SCpnt);
scsi_print_command(SCpnt);
@@ -1703,7 +1705,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
vdev = SCpnt->device->hostdata;
retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
- ctx2abort, mptscsih_get_tm_timeout(ioc));
+ ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
hd->ioc->name,
@@ -2521,15 +2523,15 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
/* 7. FC: Rescan for blocked rports which might have returned.
*/
- else if (ioc->bus_type == FC) {
- int work_count;
- unsigned long flags;
-
+ if (ioc->bus_type == FC) {
spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
- work_count = ++ioc->fc_rescan_work_count;
+ if (ioc->fc_rescan_work_q) {
+ if (ioc->fc_rescan_work_count++ == 0) {
+ queue_work(ioc->fc_rescan_work_q,
+ &ioc->fc_rescan_work);
+ }
+ }
spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
- if (work_count == 1)
- schedule_work(&ioc->fc_rescan_work);
}
dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
@@ -2544,7 +2546,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
{
MPT_SCSI_HOST *hd;
u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
- int work_count;
unsigned long flags;
devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
@@ -2569,10 +2570,13 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
case MPI_EVENT_RESCAN: /* 06 */
spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
- work_count = ++ioc->fc_rescan_work_count;
+ if (ioc->fc_rescan_work_q) {
+ if (ioc->fc_rescan_work_count++ == 0) {
+ queue_work(ioc->fc_rescan_work_q,
+ &ioc->fc_rescan_work);
+ }
+ }
spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
- if (work_count == 1)
- schedule_work(&ioc->fc_rescan_work);
break;
/*
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 09c745b19cc..3201de05394 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -783,6 +783,72 @@ static struct pci_device_id mptspi_pci_table[] = {
};
MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
+
+/*
+ * renegotiate for a given target
+ */
+static void
+mptspi_dv_renegotiate_work(void *data)
+{
+ struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
+ struct _MPT_SCSI_HOST *hd = wqw->hd;
+ struct scsi_device *sdev;
+
+ kfree(wqw);
+
+ shost_for_each_device(sdev, hd->ioc->sh)
+ mptspi_dv_device(hd, sdev);
+}
+
+static void
+mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd)
+{
+ struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
+
+ if (!wqw)
+ return;
+
+ INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work, wqw);
+ wqw->hd = hd;
+
+ schedule_work(&wqw->work);
+}
+
+/*
+ * spi module reset handler
+ */
+static int
+mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
+{
+ struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
+ int rc;
+
+ rc = mptscsih_ioc_reset(ioc, reset_phase);
+
+ if (reset_phase == MPT_IOC_POST_RESET)
+ mptspi_dv_renegotiate(hd);
+
+ return rc;
+}
+
+#ifdef CONFIG_PM
+/*
+ * spi module resume handler
+ */
+static int
+mptspi_resume(struct pci_dev *pdev)
+{
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
+ int rc;
+
+ rc = mptscsih_resume(pdev);
+ mptspi_dv_renegotiate(hd);
+
+ return rc;
+}
+#endif
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -1032,7 +1098,7 @@ static struct pci_driver mptspi_driver = {
.shutdown = mptscsih_shutdown,
#ifdef CONFIG_PM
.suspend = mptscsih_suspend,
- .resume = mptscsih_resume,
+ .resume = mptspi_resume,
#endif
};
@@ -1061,7 +1127,7 @@ mptspi_init(void)
": Registered for IOC event notifications\n"));
}
- if (mpt_reset_register(mptspiDoneCtx, mptscsih_ioc_reset) == 0) {
+ if (mpt_reset_register(mptspiDoneCtx, mptspi_ioc_reset) == 0) {
dprintk((KERN_INFO MYNAM
": Registered for IOC reset notifications\n"));
}
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 5ea133c59af..7bd4d85d0b4 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -55,6 +55,7 @@ struct i2o_exec_wait {
u32 m; /* message id */
struct i2o_message *msg; /* pointer to the reply message */
struct list_head list; /* node in global wait list */
+ spinlock_t lock; /* lock before modifying */
};
/* Work struct needed to handle LCT NOTIFY replies */
@@ -87,6 +88,7 @@ static struct i2o_exec_wait *i2o_exec_wait_alloc(void)
return NULL;
INIT_LIST_HEAD(&wait->list);
+ spin_lock_init(&wait->lock);
return wait;
};
@@ -125,6 +127,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
DECLARE_WAIT_QUEUE_HEAD(wq);
struct i2o_exec_wait *wait;
static u32 tcntxt = 0x80000000;
+ long flags;
int rc = 0;
wait = i2o_exec_wait_alloc();
@@ -146,33 +149,28 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
wait->tcntxt = tcntxt++;
msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt);
+ wait->wq = &wq;
+ /*
+ * we add elements to the head, because if a entry in the list will
+ * never be removed, we have to iterate over it every time
+ */
+ list_add(&wait->list, &i2o_exec_wait_list);
+
/*
* Post the message to the controller. At some point later it will
* return. If we time out before it returns then complete will be zero.
*/
i2o_msg_post(c, msg);
- if (!wait->complete) {
- wait->wq = &wq;
- /*
- * we add elements add the head, because if a entry in the list
- * will never be removed, we have to iterate over it every time
- */
- list_add(&wait->list, &i2o_exec_wait_list);
-
- wait_event_interruptible_timeout(wq, wait->complete,
- timeout * HZ);
+ wait_event_interruptible_timeout(wq, wait->complete, timeout * HZ);
- wait->wq = NULL;
- }
+ spin_lock_irqsave(&wait->lock, flags);
- barrier();
+ wait->wq = NULL;
- if (wait->complete) {
+ if (wait->complete)
rc = le32_to_cpu(wait->msg->body[0]) >> 24;
- i2o_flush_reply(c, wait->m);
- i2o_exec_wait_free(wait);
- } else {
+ else {
/*
* We cannot remove it now. This is important. When it does
* terminate (which it must do if the controller has not
@@ -186,6 +184,13 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
rc = -ETIMEDOUT;
}
+ spin_unlock_irqrestore(&wait->lock, flags);
+
+ if (rc != -ETIMEDOUT) {
+ i2o_flush_reply(c, wait->m);
+ i2o_exec_wait_free(wait);
+ }
+
return rc;
};
@@ -213,7 +218,6 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
{
struct i2o_exec_wait *wait, *tmp;
unsigned long flags;
- static spinlock_t lock = SPIN_LOCK_UNLOCKED;
int rc = 1;
/*
@@ -223,23 +227,24 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
* already expired. Not much we can do about that except log it for
* debug purposes, increase timeout, and recompile.
*/
- spin_lock_irqsave(&lock, flags);
list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) {
if (wait->tcntxt == context) {
- list_del(&wait->list);
+ spin_lock_irqsave(&wait->lock, flags);
- spin_unlock_irqrestore(&lock, flags);
+ list_del(&wait->list);
wait->m = m;
wait->msg = msg;
wait->complete = 1;
- barrier();
-
- if (wait->wq) {
- wake_up_interruptible(wait->wq);
+ if (wait->wq)
rc = 0;
- } else {
+ else
+ rc = -1;
+
+ spin_unlock_irqrestore(&wait->lock, flags);
+
+ if (rc) {
struct device *dev;
dev = &c->pdev->dev;
@@ -248,15 +253,13 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
c->name);
i2o_dma_free(dev, &wait->dma);
i2o_exec_wait_free(wait);
- rc = -1;
- }
+ } else
+ wake_up_interruptible(wait->wq);
return rc;
}
}
- spin_unlock_irqrestore(&lock, flags);
-
osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
context);
@@ -322,14 +325,9 @@ static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL);
static int i2o_exec_probe(struct device *dev)
{
struct i2o_device *i2o_dev = to_i2o_device(dev);
- struct i2o_controller *c = i2o_dev->iop;
i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
- c->exec = i2o_dev;
-
- i2o_exec_lct_notify(c, c->lct->change_ind + 1);
-
device_create_file(dev, &dev_attr_vendor_id);
device_create_file(dev, &dev_attr_product_id);
@@ -523,6 +521,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
struct device *dev;
struct i2o_message *msg;
+ down(&c->lct_lock);
+
dev = &c->pdev->dev;
if (i2o_dma_realloc
@@ -545,6 +545,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
i2o_msg_post(c, msg);
+ up(&c->lct_lock);
+
return 0;
};
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index 2a0c42b8cda..3d2e76eea93 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -56,7 +56,7 @@
typedef struct _i2o_proc_entry_t {
char *name; /* entry name */
mode_t mode; /* mode */
- struct file_operations *fops; /* open function */
+ const struct file_operations *fops; /* open function */
} i2o_proc_entry;
/* global I2O /proc/i2o entry */
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 49216744693..febbdd4e060 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -804,8 +804,6 @@ void i2o_iop_remove(struct i2o_controller *c)
/* Ask the IOP to switch to RESET state */
i2o_iop_reset(c);
-
- put_device(&c->device);
}
/**
@@ -1059,7 +1057,7 @@ struct i2o_controller *i2o_iop_alloc(void)
snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name);
if (i2o_pool_alloc
- (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4,
+ (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32),
I2O_MSG_INPOOL_MIN)) {
kfree(c);
return ERR_PTR(-ENOMEM);
diff --git a/drivers/misc/ibmasm/heartbeat.c b/drivers/misc/ibmasm/heartbeat.c
index f295401fac2..7fd7a43e38d 100644
--- a/drivers/misc/ibmasm/heartbeat.c
+++ b/drivers/misc/ibmasm/heartbeat.c
@@ -52,12 +52,13 @@ static struct notifier_block panic_notifier = { panic_happened, NULL, 1 };
void ibmasm_register_panic_notifier(void)
{
- notifier_chain_register(&panic_notifier_list, &panic_notifier);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier);
}
void ibmasm_unregister_panic_notifier(void)
{
- notifier_chain_unregister(&panic_notifier_list, &panic_notifier);
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &panic_notifier);
}
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index 5c550fcac2c..26a230b6ff8 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -101,7 +101,7 @@ static struct super_operations ibmasmfs_s_ops = {
.drop_inode = generic_delete_inode,
};
-static struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations;
+static const struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations;
static struct file_system_type ibmasmfs_type = {
.owner = THIS_MODULE,
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 3f5d77f633f..45bcf098e76 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -60,6 +60,17 @@ config MMC_SDHCI
If unsure, say N.
+config MMC_OMAP
+ tristate "TI OMAP Multimedia Card Interface support"
+ depends on ARCH_OMAP && MMC
+ select TPS65010 if MACH_OMAP_H2
+ help
+ This selects the TI OMAP Multimedia card Interface.
+ If you have an OMAP board with a Multimedia Card slot,
+ say Y or M here.
+
+ If unsure, say N.
+
config MMC_WBSD
tristate "Winbond W83L51xD SD/MMC Card Interface support"
depends on MMC && ISA_DMA_API
@@ -73,11 +84,29 @@ config MMC_WBSD
config MMC_AU1X
tristate "Alchemy AU1XX0 MMC Card Interface support"
- depends on SOC_AU1X00 && MMC
+ depends on MMC && SOC_AU1200
help
This selects the AMD Alchemy(R) Multimedia card interface.
If you have a Alchemy platform with a MMC slot, say Y or M here.
If unsure, say N.
+config MMC_AT91RM9200
+ tristate "AT91RM9200 SD/MMC Card Interface support"
+ depends on ARCH_AT91RM9200 && MMC
+ help
+ This selects the AT91RM9200 MCI controller.
+
+ If unsure, say N.
+
+config MMC_IMX
+ tristate "Motorola i.MX Multimedia Card Interface support"
+ depends on ARCH_IMX && MMC
+ help
+ This selects the Motorola i.MX Multimedia card Interface.
+ If you have a i.MX platform with a Multimedia Card slot,
+ say Y or M here.
+
+ If unsure, say N.
+
endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 769d545284a..d2957e35cc6 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -17,8 +17,15 @@ obj-$(CONFIG_MMC_BLOCK) += mmc_block.o
#
obj-$(CONFIG_MMC_ARMMMCI) += mmci.o
obj-$(CONFIG_MMC_PXA) += pxamci.o
+obj-$(CONFIG_MMC_IMX) += imxmmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
+obj-$(CONFIG_MMC_OMAP) += omap.o
+obj-$(CONFIG_MMC_AT91RM9200) += at91_mci.o
mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
+
+ifeq ($(CONFIG_MMC_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
new file mode 100644
index 00000000000..88f0eef9cf3
--- /dev/null
+++ b/drivers/mmc/at91_mci.c
@@ -0,0 +1,985 @@
+/*
+ * linux/drivers/mmc/at91_mci.c - ATMEL AT91RM9200 MCI Driver
+ *
+ * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
+ *
+ * Copyright (C) 2006 Malcolm Noyes
+ *
+ * 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 is the AT91RM9200 MCI driver that has been tested with both MMC cards
+ and SD-cards. Boards that support write protect are now supported.
+ The CCAT91SBC001 board does not support SD cards.
+
+ The three entry points are at91_mci_request, at91_mci_set_ios
+ and at91_mci_get_ro.
+
+ SET IOS
+ This configures the device to put it into the correct mode and clock speed
+ required.
+
+ MCI REQUEST
+ MCI request processes the commands sent in the mmc_request structure. This
+ can consist of a processing command and a stop command in the case of
+ multiple block transfers.
+
+ There are three main types of request, commands, reads and writes.
+
+ Commands are straight forward. The command is submitted to the controller and
+ the request function returns. When the controller generates an interrupt to indicate
+ the command is finished, the response to the command are read and the mmc_request_done
+ function called to end the request.
+
+ Reads and writes work in a similar manner to normal commands but involve the PDC (DMA)
+ controller to manage the transfers.
+
+ A read is done from the controller directly to the scatterlist passed in from the request.
+ Due to a bug in the controller, when a read is completed, all the words are byte
+ swapped in the scatterlist buffers.
+
+ The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
+
+ A write is slightly different in that the bytes to write are read from the scatterlist
+ into a dma memory buffer (this is in case the source buffer should be read only). The
+ entire write buffer is then done from this single dma memory buffer.
+
+ The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY
+
+ GET RO
+ Gets the status of the write protect pin, if available.
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/mmc.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200_mci.h>
+#include <asm/arch/at91rm9200_pdc.h>
+
+#define DRIVER_NAME "at91_mci"
+
+#undef SUPPORT_4WIRE
+
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(fmt...) \
+ printk(fmt)
+#else
+#define DBG(fmt...) do { } while (0)
+#endif
+
+static struct clk *mci_clk;
+
+#define FL_SENT_COMMAND (1 << 0)
+#define FL_SENT_STOP (1 << 1)
+
+
+
+/*
+ * Read from a MCI register.
+ */
+static inline unsigned long at91_mci_read(unsigned int reg)
+{
+ void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
+
+ return __raw_readl(mci_base + reg);
+}
+
+/*
+ * Write to a MCI register.
+ */
+static inline void at91_mci_write(unsigned int reg, unsigned long value)
+{
+ void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
+
+ __raw_writel(value, mci_base + reg);
+}
+
+/*
+ * Low level type for this driver
+ */
+struct at91mci_host
+{
+ struct mmc_host *mmc;
+ struct mmc_command *cmd;
+ struct mmc_request *request;
+
+ struct at91_mmc_data *board;
+ int present;
+
+ /*
+ * Flag indicating when the command has been sent. This is used to
+ * work out whether or not to send the stop
+ */
+ unsigned int flags;
+ /* flag for current bus settings */
+ u32 bus_mode;
+
+ /* DMA buffer used for transmitting */
+ unsigned int* buffer;
+ dma_addr_t physical_address;
+ unsigned int total_length;
+
+ /* Latest in the scatterlist that has been enabled for transfer, but not freed */
+ int in_use_index;
+
+ /* Latest in the scatterlist that has been enabled for transfer */
+ int transfer_index;
+};
+
+/*
+ * Copy from sg to a dma block - used for transfers
+ */
+static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
+{
+ unsigned int len, i, size;
+ unsigned *dmabuf = host->buffer;
+
+ size = host->total_length;
+ len = data->sg_len;
+
+ /*
+ * Just loop through all entries. Size might not
+ * be the entire list though so make sure that
+ * we do not transfer too much.
+ */
+ for (i = 0; i < len; i++) {
+ struct scatterlist *sg;
+ int amount;
+ int index;
+ unsigned int *sgbuffer;
+
+ sg = &data->sg[i];
+
+ sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+ amount = min(size, sg->length);
+ size -= amount;
+ amount /= 4;
+
+ for (index = 0; index < amount; index++)
+ *dmabuf++ = swab32(sgbuffer[index]);
+
+ kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
+
+ if (size == 0)
+ break;
+ }
+
+ /*
+ * Check that we didn't get a request to transfer
+ * more data than can fit into the SG list.
+ */
+ BUG_ON(size != 0);
+}
+
+/*
+ * Prepare a dma read
+ */
+static void at91mci_pre_dma_read(struct at91mci_host *host)
+{
+ int i;
+ struct scatterlist *sg;
+ struct mmc_command *cmd;
+ struct mmc_data *data;
+
+ DBG("pre dma read\n");
+
+ cmd = host->cmd;
+ if (!cmd) {
+ DBG("no command\n");
+ return;
+ }
+
+ data = cmd->data;
+ if (!data) {
+ DBG("no data\n");
+ return;
+ }
+
+ for (i = 0; i < 2; i++) {
+ /* nothing left to transfer */
+ if (host->transfer_index >= data->sg_len) {
+ DBG("Nothing left to transfer (index = %d)\n", host->transfer_index);
+ break;
+ }
+
+ /* Check to see if this needs filling */
+ if (i == 0) {
+ if (at91_mci_read(AT91_PDC_RCR) != 0) {
+ DBG("Transfer active in current\n");
+ continue;
+ }
+ }
+ else {
+ if (at91_mci_read(AT91_PDC_RNCR) != 0) {
+ DBG("Transfer active in next\n");
+ continue;
+ }
+ }
+
+ /* Setup the next transfer */
+ DBG("Using transfer index %d\n", host->transfer_index);
+
+ sg = &data->sg[host->transfer_index++];
+ DBG("sg = %p\n", sg);
+
+ sg->dma_address = dma_map_page(NULL, sg->page, sg->offset, sg->length, DMA_FROM_DEVICE);
+
+ DBG("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
+
+ if (i == 0) {
+ at91_mci_write(AT91_PDC_RPR, sg->dma_address);
+ at91_mci_write(AT91_PDC_RCR, sg->length / 4);
+ }
+ else {
+ at91_mci_write(AT91_PDC_RNPR, sg->dma_address);
+ at91_mci_write(AT91_PDC_RNCR, sg->length / 4);
+ }
+ }
+
+ DBG("pre dma read done\n");
+}
+
+/*
+ * Handle after a dma read
+ */
+static void at91mci_post_dma_read(struct at91mci_host *host)
+{
+ struct mmc_command *cmd;
+ struct mmc_data *data;
+
+ DBG("post dma read\n");
+
+ cmd = host->cmd;
+ if (!cmd) {
+ DBG("no command\n");
+ return;
+ }
+
+ data = cmd->data;
+ if (!data) {
+ DBG("no data\n");
+ return;
+ }
+
+ while (host->in_use_index < host->transfer_index) {
+ unsigned int *buffer;
+ int index;
+ int len;
+
+ struct scatterlist *sg;
+
+ DBG("finishing index %d\n", host->in_use_index);
+
+ sg = &data->sg[host->in_use_index++];
+
+ DBG("Unmapping page %08X\n", sg->dma_address);
+
+ dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
+
+ /* Swap the contents of the buffer */
+ buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+ DBG("buffer = %p, length = %d\n", buffer, sg->length);
+
+ data->bytes_xfered += sg->length;
+
+ len = sg->length / 4;
+
+ for (index = 0; index < len; index++) {
+ buffer[index] = swab32(buffer[index]);
+ }
+ kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
+ flush_dcache_page(sg->page);
+ }
+
+ /* Is there another transfer to trigger? */
+ if (host->transfer_index < data->sg_len)
+ at91mci_pre_dma_read(host);
+ else {
+ at91_mci_write(AT91_MCI_IER, AT91_MCI_RXBUFF);
+ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+ }
+
+ DBG("post dma read done\n");
+}
+
+/*
+ * Handle transmitted data
+ */
+static void at91_mci_handle_transmitted(struct at91mci_host *host)
+{
+ struct mmc_command *cmd;
+ struct mmc_data *data;
+
+ DBG("Handling the transmit\n");
+
+ /* Disable the transfer */
+ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+
+ /* Now wait for cmd ready */
+ at91_mci_write(AT91_MCI_IDR, AT91_MCI_TXBUFE);
+ at91_mci_write(AT91_MCI_IER, AT91_MCI_NOTBUSY);
+
+ cmd = host->cmd;
+ if (!cmd) return;
+
+ data = cmd->data;
+ if (!data) return;
+
+ data->bytes_xfered = host->total_length;
+}
+
+/*
+ * Enable the controller
+ */
+static void at91_mci_enable(void)
+{
+ at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
+ at91_mci_write(AT91_MCI_IDR, 0xFFFFFFFF);
+ at91_mci_write(AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
+ at91_mci_write(AT91_MCI_MR, 0x834A);
+ at91_mci_write(AT91_MCI_SDCR, 0x0);
+}
+
+/*
+ * Disable the controller
+ */
+static void at91_mci_disable(void)
+{
+ at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
+}
+
+/*
+ * Send a command
+ * return the interrupts to enable
+ */
+static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
+{
+ unsigned int cmdr, mr;
+ unsigned int block_length;
+ struct mmc_data *data = cmd->data;
+
+ unsigned int blocks;
+ unsigned int ier = 0;
+
+ host->cmd = cmd;
+
+ /* Not sure if this is needed */
+#if 0
+ if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
+ DBG("Clearing timeout\n");
+ at91_mci_write(AT91_MCI_ARGR, 0);
+ at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD);
+ while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
+ /* spin */
+ DBG("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR));
+ }
+ }
+#endif
+ cmdr = cmd->opcode;
+
+ if (mmc_resp_type(cmd) == MMC_RSP_NONE)
+ cmdr |= AT91_MCI_RSPTYP_NONE;
+ else {
+ /* if a response is expected then allow maximum response latancy */
+ cmdr |= AT91_MCI_MAXLAT;
+ /* set 136 bit response for R2, 48 bit response otherwise */
+ if (mmc_resp_type(cmd) == MMC_RSP_R2)
+ cmdr |= AT91_MCI_RSPTYP_136;
+ else
+ cmdr |= AT91_MCI_RSPTYP_48;
+ }
+
+ if (data) {
+ block_length = 1 << data->blksz_bits;
+ blocks = data->blocks;
+
+ /* always set data start - also set direction flag for read */
+ if (data->flags & MMC_DATA_READ)
+ cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
+ else if (data->flags & MMC_DATA_WRITE)
+ cmdr |= AT91_MCI_TRCMD_START;
+
+ if (data->flags & MMC_DATA_STREAM)
+ cmdr |= AT91_MCI_TRTYP_STREAM;
+ if (data->flags & MMC_DATA_MULTI)
+ cmdr |= AT91_MCI_TRTYP_MULTIPLE;
+ }
+ else {
+ block_length = 0;
+ blocks = 0;
+ }
+
+ if (cmd->opcode == MMC_STOP_TRANSMISSION)
+ cmdr |= AT91_MCI_TRCMD_STOP;
+
+ if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+ cmdr |= AT91_MCI_OPDCMD;
+
+ /*
+ * Set the arguments and send the command
+ */
+ DBG("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n",
+ cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR));
+
+ if (!data) {
+ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS);
+ at91_mci_write(AT91_PDC_RPR, 0);
+ at91_mci_write(AT91_PDC_RCR, 0);
+ at91_mci_write(AT91_PDC_RNPR, 0);
+ at91_mci_write(AT91_PDC_RNCR, 0);
+ at91_mci_write(AT91_PDC_TPR, 0);
+ at91_mci_write(AT91_PDC_TCR, 0);
+ at91_mci_write(AT91_PDC_TNPR, 0);
+ at91_mci_write(AT91_PDC_TNCR, 0);
+
+ at91_mci_write(AT91_MCI_ARGR, cmd->arg);
+ at91_mci_write(AT91_MCI_CMDR, cmdr);
+ return AT91_MCI_CMDRDY;
+ }
+
+ mr = at91_mci_read(AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */
+ at91_mci_write(AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
+
+ /*
+ * Disable the PDC controller
+ */
+ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+
+ if (cmdr & AT91_MCI_TRCMD_START) {
+ data->bytes_xfered = 0;
+ host->transfer_index = 0;
+ host->in_use_index = 0;
+ if (cmdr & AT91_MCI_TRDIR) {
+ /*
+ * Handle a read
+ */
+ host->buffer = NULL;
+ host->total_length = 0;
+
+ at91mci_pre_dma_read(host);
+ ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
+ }
+ else {
+ /*
+ * Handle a write
+ */
+ host->total_length = block_length * blocks;
+ host->buffer = dma_alloc_coherent(NULL,
+ host->total_length,
+ &host->physical_address, GFP_KERNEL);
+
+ at91mci_sg_to_dma(host, data);
+
+ DBG("Transmitting %d bytes\n", host->total_length);
+
+ at91_mci_write(AT91_PDC_TPR, host->physical_address);
+ at91_mci_write(AT91_PDC_TCR, host->total_length / 4);
+ ier = AT91_MCI_TXBUFE;
+ }
+ }
+
+ /*
+ * Send the command and then enable the PDC - not the other way round as
+ * the data sheet says
+ */
+
+ at91_mci_write(AT91_MCI_ARGR, cmd->arg);
+ at91_mci_write(AT91_MCI_CMDR, cmdr);
+
+ if (cmdr & AT91_MCI_TRCMD_START) {
+ if (cmdr & AT91_MCI_TRDIR)
+ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTEN);
+ else
+ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTEN);
+ }
+ return ier;
+}
+
+/*
+ * Wait for a command to complete
+ */
+static void at91mci_process_command(struct at91mci_host *host, struct mmc_command *cmd)
+{
+ unsigned int ier;
+
+ ier = at91_mci_send_command(host, cmd);
+
+ DBG("setting ier to %08X\n", ier);
+
+ /* Stop on errors or the required value */
+ at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier);
+}
+
+/*
+ * Process the next step in the request
+ */
+static void at91mci_process_next(struct at91mci_host *host)
+{
+ if (!(host->flags & FL_SENT_COMMAND)) {
+ host->flags |= FL_SENT_COMMAND;
+ at91mci_process_command(host, host->request->cmd);
+ }
+ else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
+ host->flags |= FL_SENT_STOP;
+ at91mci_process_command(host, host->request->stop);
+ }
+ else
+ mmc_request_done(host->mmc, host->request);
+}
+
+/*
+ * Handle a command that has been completed
+ */
+static void at91mci_completed_command(struct at91mci_host *host)
+{
+ struct mmc_command *cmd = host->cmd;
+ unsigned int status;
+
+ at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+
+ cmd->resp[0] = at91_mci_read(AT91_MCI_RSPR(0));
+ cmd->resp[1] = at91_mci_read(AT91_MCI_RSPR(1));
+ cmd->resp[2] = at91_mci_read(AT91_MCI_RSPR(2));
+ cmd->resp[3] = at91_mci_read(AT91_MCI_RSPR(3));
+
+ if (host->buffer) {
+ dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
+ host->buffer = NULL;
+ }
+
+ status = at91_mci_read(AT91_MCI_SR);
+
+ DBG("Status = %08X [%08X %08X %08X %08X]\n",
+ status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+
+ if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE |
+ AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE |
+ AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) {
+ if ((status & AT91_MCI_RCRCE) &&
+ ((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND))) {
+ cmd->error = MMC_ERR_NONE;
+ }
+ else {
+ if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE))
+ cmd->error = MMC_ERR_TIMEOUT;
+ else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE))
+ cmd->error = MMC_ERR_BADCRC;
+ else if (status & (AT91_MCI_OVRE | AT91_MCI_UNRE))
+ cmd->error = MMC_ERR_FIFO;
+ else
+ cmd->error = MMC_ERR_FAILED;
+
+ DBG("Error detected and set to %d (cmd = %d, retries = %d)\n",
+ cmd->error, cmd->opcode, cmd->retries);
+ }
+ }
+ else
+ cmd->error = MMC_ERR_NONE;
+
+ at91mci_process_next(host);
+}
+
+/*
+ * Handle an MMC request
+ */
+static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ struct at91mci_host *host = mmc_priv(mmc);
+ host->request = mrq;
+ host->flags = 0;
+
+ at91mci_process_next(host);
+}
+
+/*
+ * Set the IOS
+ */
+static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ int clkdiv;
+ struct at91mci_host *host = mmc_priv(mmc);
+ unsigned long at91_master_clock = clk_get_rate(mci_clk);
+
+ if (host)
+ host->bus_mode = ios->bus_mode;
+ else
+ printk("MMC: No host for bus_mode\n");
+
+ if (ios->clock == 0) {
+ /* Disable the MCI controller */
+ at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS);
+ clkdiv = 0;
+ }
+ else {
+ /* Enable the MCI controller */
+ at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
+
+ if ((at91_master_clock % (ios->clock * 2)) == 0)
+ clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
+ else
+ clkdiv = (at91_master_clock / ios->clock) / 2;
+
+ DBG("clkdiv = %d. mcck = %ld\n", clkdiv,
+ at91_master_clock / (2 * (clkdiv + 1)));
+ }
+ if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
+ DBG("MMC: Setting controller bus width to 4\n");
+ at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
+ }
+ else {
+ DBG("MMC: Setting controller bus width to 1\n");
+ at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
+ }
+
+ /* Set the clock divider */
+ at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
+
+ /* maybe switch power to the card */
+ if (host && host->board->vcc_pin) {
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF:
+ at91_set_gpio_output(host->board->vcc_pin, 0);
+ break;
+ case MMC_POWER_UP:
+ case MMC_POWER_ON:
+ at91_set_gpio_output(host->board->vcc_pin, 1);
+ break;
+ }
+ }
+}
+
+/*
+ * Handle an interrupt
+ */
+static irqreturn_t at91_mci_irq(int irq, void *devid, struct pt_regs *regs)
+{
+ struct at91mci_host *host = devid;
+ int completed = 0;
+
+ unsigned int int_status;
+
+ if (host == NULL)
+ return IRQ_HANDLED;
+
+ int_status = at91_mci_read(AT91_MCI_SR);
+ DBG("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR),
+ int_status & at91_mci_read(AT91_MCI_IMR));
+
+ if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000)
+ completed = 1;
+
+ int_status &= at91_mci_read(AT91_MCI_IMR);
+
+ if (int_status & AT91_MCI_UNRE)
+ DBG("MMC: Underrun error\n");
+ if (int_status & AT91_MCI_OVRE)
+ DBG("MMC: Overrun error\n");
+ if (int_status & AT91_MCI_DTOE)
+ DBG("MMC: Data timeout\n");
+ if (int_status & AT91_MCI_DCRCE)
+ DBG("MMC: CRC error in data\n");
+ if (int_status & AT91_MCI_RTOE)
+ DBG("MMC: Response timeout\n");
+ if (int_status & AT91_MCI_RENDE)
+ DBG("MMC: Response end bit error\n");
+ if (int_status & AT91_MCI_RCRCE)
+ DBG("MMC: Response CRC error\n");
+ if (int_status & AT91_MCI_RDIRE)
+ DBG("MMC: Response direction error\n");
+ if (int_status & AT91_MCI_RINDE)
+ DBG("MMC: Response index error\n");
+
+ /* Only continue processing if no errors */
+ if (!completed) {
+ if (int_status & AT91_MCI_TXBUFE) {
+ DBG("TX buffer empty\n");
+ at91_mci_handle_transmitted(host);
+ }
+
+ if (int_status & AT91_MCI_RXBUFF) {
+ DBG("RX buffer full\n");
+ at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+ }
+
+ if (int_status & AT91_MCI_ENDTX) {
+ DBG("Transmit has ended\n");
+ }
+
+ if (int_status & AT91_MCI_ENDRX) {
+ DBG("Receive has ended\n");
+ at91mci_post_dma_read(host);
+ }
+
+ if (int_status & AT91_MCI_NOTBUSY) {
+ DBG("Card is ready\n");
+ at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+ }
+
+ if (int_status & AT91_MCI_DTIP) {
+ DBG("Data transfer in progress\n");
+ }
+
+ if (int_status & AT91_MCI_BLKE) {
+ DBG("Block transfer has ended\n");
+ }
+
+ if (int_status & AT91_MCI_TXRDY) {
+ DBG("Ready to transmit\n");
+ }
+
+ if (int_status & AT91_MCI_RXRDY) {
+ DBG("Ready to receive\n");
+ }
+
+ if (int_status & AT91_MCI_CMDRDY) {
+ DBG("Command ready\n");
+ completed = 1;
+ }
+ }
+ at91_mci_write(AT91_MCI_IDR, int_status);
+
+ if (completed) {
+ DBG("Completed command\n");
+ at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+ at91mci_completed_command(host);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t at91_mmc_det_irq(int irq, void *_host, struct pt_regs *regs)
+{
+ struct at91mci_host *host = _host;
+ int present = !at91_get_gpio_value(irq);
+
+ /*
+ * we expect this irq on both insert and remove,
+ * and use a short delay to debounce.
+ */
+ if (present != host->present) {
+ host->present = present;
+ DBG("%s: card %s\n", mmc_hostname(host->mmc),
+ present ? "insert" : "remove");
+ if (!present) {
+ DBG("****** Resetting SD-card bus width ******\n");
+ at91_mci_write(AT91_MCI_SDCR, 0);
+ }
+ mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+ }
+ return IRQ_HANDLED;
+}
+
+int at91_mci_get_ro(struct mmc_host *mmc)
+{
+ int read_only = 0;
+ struct at91mci_host *host = mmc_priv(mmc);
+
+ if (host->board->wp_pin) {
+ read_only = at91_get_gpio_value(host->board->wp_pin);
+ printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc),
+ (read_only ? "read-only" : "read-write") );
+ }
+ else {
+ printk(KERN_WARNING "%s: host does not support reading read-only "
+ "switch. Assuming write-enable.\n", mmc_hostname(mmc));
+ }
+ return read_only;
+}
+
+static struct mmc_host_ops at91_mci_ops = {
+ .request = at91_mci_request,
+ .set_ios = at91_mci_set_ios,
+ .get_ro = at91_mci_get_ro,
+};
+
+/*
+ * Probe for the device
+ */
+static int at91_mci_probe(struct platform_device *pdev)
+{
+ struct mmc_host *mmc;
+ struct at91mci_host *host;
+ int ret;
+
+ DBG("Probe MCI devices\n");
+ at91_mci_disable();
+ at91_mci_enable();
+
+ mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
+ if (!mmc) {
+ DBG("Failed to allocate mmc host\n");
+ return -ENOMEM;
+ }
+
+ mmc->ops = &at91_mci_ops;
+ mmc->f_min = 375000;
+ mmc->f_max = 25000000;
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
+ host->buffer = NULL;
+ host->bus_mode = 0;
+ host->board = pdev->dev.platform_data;
+ if (host->board->wire4) {
+#ifdef SUPPORT_4WIRE
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+#else
+ printk("MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
+#endif
+ }
+
+ /*
+ * Get Clock
+ */
+ mci_clk = clk_get(&pdev->dev, "mci_clk");
+ if (!mci_clk) {
+ printk(KERN_ERR "AT91 MMC: no clock defined.\n");
+ return -ENODEV;
+ }
+ clk_enable(mci_clk); /* Enable the peripheral clock */
+
+ /*
+ * Allocate the MCI interrupt
+ */
+ ret = request_irq(AT91_ID_MCI, at91_mci_irq, SA_SHIRQ, DRIVER_NAME, host);
+ if (ret) {
+ DBG("Failed to request MCI interrupt\n");
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, mmc);
+
+ /*
+ * Add host to MMC layer
+ */
+ if (host->board->det_pin)
+ host->present = !at91_get_gpio_value(host->board->det_pin);
+ else
+ host->present = -1;
+
+ mmc_add_host(mmc);
+
+ /*
+ * monitor card insertion/removal if we can
+ */
+ if (host->board->det_pin) {
+ ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
+ SA_SAMPLE_RANDOM, DRIVER_NAME, host);
+ if (ret)
+ DBG("couldn't allocate MMC detect irq\n");
+ }
+
+ DBG(KERN_INFO "Added MCI driver\n");
+
+ return 0;
+}
+
+/*
+ * Remove a device
+ */
+static int at91_mci_remove(struct platform_device *pdev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+ struct at91mci_host *host;
+
+ if (!mmc)
+ return -1;
+
+ host = mmc_priv(mmc);
+
+ if (host->present != -1) {
+ free_irq(host->board->det_pin, host);
+ cancel_delayed_work(&host->mmc->detect);
+ }
+
+ mmc_remove_host(mmc);
+ at91_mci_disable();
+ free_irq(AT91_ID_MCI, host);
+ mmc_free_host(mmc);
+
+ clk_disable(mci_clk); /* Disable the peripheral clock */
+ clk_put(mci_clk);
+
+ platform_set_drvdata(pdev, NULL);
+
+ DBG("Removed\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+ int ret = 0;
+
+ if (mmc)
+ ret = mmc_suspend_host(mmc, state);
+
+ return ret;
+}
+
+static int at91_mci_resume(struct platform_device *pdev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+ int ret = 0;
+
+ if (mmc)
+ ret = mmc_resume_host(mmc);
+
+ return ret;
+}
+#else
+#define at91_mci_suspend NULL
+#define at91_mci_resume NULL
+#endif
+
+static struct platform_driver at91_mci_driver = {
+ .probe = at91_mci_probe,
+ .remove = at91_mci_remove,
+ .suspend = at91_mci_suspend,
+ .resume = at91_mci_resume,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init at91_mci_init(void)
+{
+ return platform_driver_register(&at91_mci_driver);
+}
+
+static void __exit at91_mci_exit(void)
+{
+ platform_driver_unregister(&at91_mci_driver);
+}
+
+module_init(at91_mci_init);
+module_exit(at91_mci_exit);
+
+MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
+MODULE_AUTHOR("Nick Randell");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index 85e89c77bde..5dc4bee7abe 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -56,12 +56,11 @@
#define DRIVER_NAME "au1xxx-mmc"
/* Set this to enable special debugging macros */
-/* #define MMC_DEBUG */
-#ifdef MMC_DEBUG
-#define DEBUG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
+#ifdef DEBUG
+#define DBG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
#else
-#define DEBUG(fmt, idx, args...)
+#define DBG(fmt, idx, args...)
#endif
const struct {
@@ -311,7 +310,7 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
}
else
data->bytes_xfered =
- (data->blocks * (1 << data->blksz_bits)) -
+ (data->blocks * data->blksz) -
host->pio.len;
}
@@ -424,18 +423,18 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
break;
if (status & SD_STATUS_RC) {
- DEBUG("RX CRC Error [%d + %d].\n", host->id,
+ DBG("RX CRC Error [%d + %d].\n", host->id,
host->pio.len, count);
break;
}
if (status & SD_STATUS_RO) {
- DEBUG("RX Overrun [%d + %d]\n", host->id,
+ DBG("RX Overrun [%d + %d]\n", host->id,
host->pio.len, count);
break;
}
else if (status & SD_STATUS_RU) {
- DEBUG("RX Underrun [%d + %d]\n", host->id,
+ DBG("RX Underrun [%d + %d]\n", host->id,
host->pio.len, count);
break;
}
@@ -576,7 +575,7 @@ static int
au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
{
- int datalen = data->blocks * (1 << data->blksz_bits);
+ int datalen = data->blocks * data->blksz;
if (dma != 0)
host->flags |= HOST_F_DMA;
@@ -597,7 +596,7 @@ au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
if (host->dma.len == 0)
return MMC_ERR_TIMEOUT;
- au_writel((1 << data->blksz_bits) - 1, HOST_BLKSIZE(host));
+ au_writel(data->blksz - 1, HOST_BLKSIZE(host));
if (host->flags & HOST_F_DMA) {
int i;
@@ -721,10 +720,6 @@ static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
{
struct au1xmmc_host *host = mmc_priv(mmc);
- DEBUG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n",
- host->id, ios->power_mode, ios->clock, ios->vdd,
- ios->bus_mode);
-
if (ios->power_mode == MMC_POWER_OFF)
au1xmmc_set_power(host, 0);
else if (ios->power_mode == MMC_POWER_ON) {
@@ -810,7 +805,7 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id, struct pt_regs *regs)
au1xmmc_receive_pio(host);
}
else if (status & 0x203FBC70) {
- DEBUG("Unhandled status %8.8x\n", host->id, status);
+ DBG("Unhandled status %8.8x\n", host->id, status);
handled = 0;
}
@@ -839,7 +834,7 @@ static void au1xmmc_poll_event(unsigned long arg)
if (host->mrq != NULL) {
u32 status = au_readl(HOST_STATUS(host));
- DEBUG("PENDING - %8.8x\n", host->id, status);
+ DBG("PENDING - %8.8x\n", host->id, status);
}
mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT);
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
new file mode 100644
index 00000000000..a4eb1d0e7a7
--- /dev/null
+++ b/drivers/mmc/imxmmc.c
@@ -0,0 +1,1128 @@
+/*
+ * linux/drivers/mmc/imxmmc.c - Motorola i.MX MMCI driver
+ *
+ * Copyright (C) 2004 Sascha Hauer, Pengutronix <sascha@saschahauer.de>
+ * Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
+ *
+ * derived from pxamci.c by Russell King
+ *
+ * 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.
+ *
+ * 2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ * Changed to conform redesigned i.MX scatter gather DMA interface
+ *
+ * 2005-11-04 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ * Updated for 2.6.14 kernel
+ *
+ * 2005-12-13 Jay Monkman <jtm@smoothsmoothie.com>
+ * Found and corrected problems in the write path
+ *
+ * 2005-12-30 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ * The event handling rewritten right way in softirq.
+ * Added many ugly hacks and delays to overcome SDHC
+ * deficiencies
+ *
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_MMC_DEBUG
+#define DEBUG
+#else
+#undef DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/protocol.h>
+#include <linux/delay.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/imx-dma.h>
+
+#include "imxmmc.h"
+
+#define DRIVER_NAME "imx-mmc"
+
+#define IMXMCI_INT_MASK_DEFAULT (INT_MASK_BUF_READY | INT_MASK_DATA_TRAN | \
+ INT_MASK_WRITE_OP_DONE | INT_MASK_END_CMD_RES | \
+ INT_MASK_AUTO_CARD_DETECT | INT_MASK_DAT0_EN | INT_MASK_SDIO)
+
+struct imxmci_host {
+ struct mmc_host *mmc;
+ spinlock_t lock;
+ struct resource *res;
+ int irq;
+ imx_dmach_t dma;
+ unsigned int clkrt;
+ unsigned int cmdat;
+ volatile unsigned int imask;
+ unsigned int power_mode;
+ unsigned int present;
+ struct imxmmc_platform_data *pdata;
+
+ struct mmc_request *req;
+ struct mmc_command *cmd;
+ struct mmc_data *data;
+
+ struct timer_list timer;
+ struct tasklet_struct tasklet;
+ unsigned int status_reg;
+ unsigned long pending_events;
+ /* Next to fields are there for CPU driven transfers to overcome SDHC deficiencies */
+ u16 *data_ptr;
+ unsigned int data_cnt;
+ atomic_t stuck_timeout;
+
+ unsigned int dma_nents;
+ unsigned int dma_size;
+ unsigned int dma_dir;
+ int dma_allocated;
+
+ unsigned char actual_bus_width;
+};
+
+#define IMXMCI_PEND_IRQ_b 0
+#define IMXMCI_PEND_DMA_END_b 1
+#define IMXMCI_PEND_DMA_ERR_b 2
+#define IMXMCI_PEND_WAIT_RESP_b 3
+#define IMXMCI_PEND_DMA_DATA_b 4
+#define IMXMCI_PEND_CPU_DATA_b 5
+#define IMXMCI_PEND_CARD_XCHG_b 6
+#define IMXMCI_PEND_SET_INIT_b 7
+#define IMXMCI_PEND_STARTED_b 8
+
+#define IMXMCI_PEND_IRQ_m (1 << IMXMCI_PEND_IRQ_b)
+#define IMXMCI_PEND_DMA_END_m (1 << IMXMCI_PEND_DMA_END_b)
+#define IMXMCI_PEND_DMA_ERR_m (1 << IMXMCI_PEND_DMA_ERR_b)
+#define IMXMCI_PEND_WAIT_RESP_m (1 << IMXMCI_PEND_WAIT_RESP_b)
+#define IMXMCI_PEND_DMA_DATA_m (1 << IMXMCI_PEND_DMA_DATA_b)
+#define IMXMCI_PEND_CPU_DATA_m (1 << IMXMCI_PEND_CPU_DATA_b)
+#define IMXMCI_PEND_CARD_XCHG_m (1 << IMXMCI_PEND_CARD_XCHG_b)
+#define IMXMCI_PEND_SET_INIT_m (1 << IMXMCI_PEND_SET_INIT_b)
+#define IMXMCI_PEND_STARTED_m (1 << IMXMCI_PEND_STARTED_b)
+
+static void imxmci_stop_clock(struct imxmci_host *host)
+{
+ int i = 0;
+ MMC_STR_STP_CLK &= ~STR_STP_CLK_START_CLK;
+ while(i < 0x1000) {
+ if(!(i & 0x7f))
+ MMC_STR_STP_CLK |= STR_STP_CLK_STOP_CLK;
+
+ if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)) {
+ /* Check twice before cut */
+ if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN))
+ return;
+ }
+
+ i++;
+ }
+ dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n");
+}
+
+static int imxmci_start_clock(struct imxmci_host *host)
+{
+ unsigned int trials = 0;
+ unsigned int delay_limit = 128;
+ unsigned long flags;
+
+ MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK;
+
+ clear_bit(IMXMCI_PEND_STARTED_b, &host->pending_events);
+
+ /*
+ * Command start of the clock, this usually succeeds in less
+ * then 6 delay loops, but during card detection (low clockrate)
+ * it takes up to 5000 delay loops and sometimes fails for the first time
+ */
+ MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
+
+ do {
+ unsigned int delay = delay_limit;
+
+ while(delay--){
+ if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
+ /* Check twice before cut */
+ if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
+ return 0;
+
+ if(test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events))
+ return 0;
+ }
+
+ local_irq_save(flags);
+ /*
+ * Ensure, that request is not doubled under all possible circumstances.
+ * It is possible, that cock running state is missed, because some other
+ * IRQ or schedule delays this function execution and the clocks has
+ * been already stopped by other means (response processing, SDHC HW)
+ */
+ if(!test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events))
+ MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
+ local_irq_restore(flags);
+
+ } while(++trials<256);
+
+ dev_err(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n");
+
+ return -1;
+}
+
+static void imxmci_softreset(void)
+{
+ /* reset sequence */
+ MMC_STR_STP_CLK = 0x8;
+ MMC_STR_STP_CLK = 0xD;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+ MMC_STR_STP_CLK = 0x5;
+
+ MMC_RES_TO = 0xff;
+ MMC_BLK_LEN = 512;
+ MMC_NOB = 1;
+}
+
+static int imxmci_busy_wait_for_status(struct imxmci_host *host,
+ unsigned int *pstat, unsigned int stat_mask,
+ int timeout, const char *where)
+{
+ int loops=0;
+ while(!(*pstat & stat_mask)) {
+ loops+=2;
+ if(loops >= timeout) {
+ dev_dbg(mmc_dev(host->mmc), "busy wait timeout in %s, STATUS = 0x%x (0x%x)\n",
+ where, *pstat, stat_mask);
+ return -1;
+ }
+ udelay(2);
+ *pstat |= MMC_STATUS;
+ }
+ if(!loops)
+ return 0;
+
+ /* The busy-wait is expected there for clock <8MHz due to SDHC hardware flaws */
+ if(!(stat_mask & STATUS_END_CMD_RESP) || (host->mmc->ios.clock>=8000000))
+ dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n",
+ loops, where, *pstat, stat_mask);
+ return loops;
+}
+
+static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data)
+{
+ unsigned int nob = data->blocks;
+ unsigned int blksz = 1 << data->blksz_bits;
+ unsigned int datasz = nob * blksz;
+ int i;
+
+ if (data->flags & MMC_DATA_STREAM)
+ nob = 0xffff;
+
+ host->data = data;
+ data->bytes_xfered = 0;
+
+ MMC_NOB = nob;
+ MMC_BLK_LEN = blksz;
+
+ /*
+ * DMA cannot be used for small block sizes, we have to use CPU driven transfers otherwise.
+ * We are in big troubles for non-512 byte transfers according to note in the paragraph
+ * 20.6.7 of User Manual anyway, but we need to be able to transfer SCR at least.
+ * The situation is even more complex in reality. The SDHC in not able to handle wll
+ * partial FIFO fills and reads. The length has to be rounded up to burst size multiple.
+ * This is required for SCR read at least.
+ */
+ if (datasz < 64) {
+ host->dma_size = datasz;
+ if (data->flags & MMC_DATA_READ) {
+ host->dma_dir = DMA_FROM_DEVICE;
+
+ /* Hack to enable read SCR */
+ if(datasz < 16) {
+ MMC_NOB = 1;
+ MMC_BLK_LEN = 16;
+ }
+ } else {
+ host->dma_dir = DMA_TO_DEVICE;
+ }
+
+ /* Convert back to virtual address */
+ host->data_ptr = (u16*)(page_address(data->sg->page) + data->sg->offset);
+ host->data_cnt = 0;
+
+ clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
+ set_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
+
+ return;
+ }
+
+ if (data->flags & MMC_DATA_READ) {
+ host->dma_dir = DMA_FROM_DEVICE;
+ host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
+ data->sg_len, host->dma_dir);
+
+ imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz,
+ host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_READ);
+
+ /*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_READ, IMX_DMA_WIDTH_16, CCR_REN);*/
+ CCR(host->dma) = CCR_DMOD_LINEAR | CCR_DSIZ_32 | CCR_SMOD_FIFO | CCR_SSIZ_16 | CCR_REN;
+ } else {
+ host->dma_dir = DMA_TO_DEVICE;
+
+ host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
+ data->sg_len, host->dma_dir);
+
+ imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz,
+ host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_WRITE);
+
+ /*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_WRITE, IMX_DMA_WIDTH_16, CCR_REN);*/
+ CCR(host->dma) = CCR_SMOD_LINEAR | CCR_SSIZ_32 | CCR_DMOD_FIFO | CCR_DSIZ_16 | CCR_REN;
+ }
+
+#if 1 /* This code is there only for consistency checking and can be disabled in future */
+ host->dma_size = 0;
+ for(i=0; i<host->dma_nents; i++)
+ host->dma_size+=data->sg[i].length;
+
+ if (datasz > host->dma_size) {
+ dev_err(mmc_dev(host->mmc), "imxmci_setup_data datasz 0x%x > 0x%x dm_size\n",
+ datasz, host->dma_size);
+ }
+#endif
+
+ host->dma_size = datasz;
+
+ wmb();
+
+ if(host->actual_bus_width == MMC_BUS_WIDTH_4)
+ BLR(host->dma) = 0; /* burst 64 byte read / 64 bytes write */
+ else
+ BLR(host->dma) = 16; /* burst 16 byte read / 16 bytes write */
+
+ RSSR(host->dma) = DMA_REQ_SDHC;
+
+ set_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
+ clear_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
+
+ /* start DMA engine for read, write is delayed after initial response */
+ if (host->dma_dir == DMA_FROM_DEVICE) {
+ imx_dma_enable(host->dma);
+ }
+}
+
+static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, unsigned int cmdat)
+{
+ unsigned long flags;
+ u32 imask;
+
+ WARN_ON(host->cmd != NULL);
+ host->cmd = cmd;
+
+ /* Ensure, that clock are stopped else command programming and start fails */
+ imxmci_stop_clock(host);
+
+ if (cmd->flags & MMC_RSP_BUSY)
+ cmdat |= CMD_DAT_CONT_BUSY;
+
+ switch (mmc_resp_type(cmd)) {
+ case MMC_RSP_R1: /* short CRC, OPCODE */
+ case MMC_RSP_R1B:/* short CRC, OPCODE, BUSY */
+ cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R1;
+ break;
+ case MMC_RSP_R2: /* long 136 bit + CRC */
+ cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R2;
+ break;
+ case MMC_RSP_R3: /* short */
+ cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R3;
+ break;
+ case MMC_RSP_R6: /* short CRC */
+ cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R6;
+ break;
+ default:
+ break;
+ }
+
+ if ( test_and_clear_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events) )
+ cmdat |= CMD_DAT_CONT_INIT; /* This command needs init */
+
+ if ( host->actual_bus_width == MMC_BUS_WIDTH_4 )
+ cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
+
+ MMC_CMD = cmd->opcode;
+ MMC_ARGH = cmd->arg >> 16;
+ MMC_ARGL = cmd->arg & 0xffff;
+ MMC_CMD_DAT_CONT = cmdat;
+
+ atomic_set(&host->stuck_timeout, 0);
+ set_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events);
+
+
+ imask = IMXMCI_INT_MASK_DEFAULT;
+ imask &= ~INT_MASK_END_CMD_RES;
+ if ( cmdat & CMD_DAT_CONT_DATA_ENABLE ) {
+ /*imask &= ~INT_MASK_BUF_READY;*/
+ imask &= ~INT_MASK_DATA_TRAN;
+ if ( cmdat & CMD_DAT_CONT_WRITE )
+ imask &= ~INT_MASK_WRITE_OP_DONE;
+ if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events))
+ imask &= ~INT_MASK_BUF_READY;
+ }
+
+ spin_lock_irqsave(&host->lock, flags);
+ host->imask = imask;
+ MMC_INT_MASK = host->imask;
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ dev_dbg(mmc_dev(host->mmc), "CMD%02d (0x%02x) mask set to 0x%04x\n",
+ cmd->opcode, cmd->opcode, imask);
+
+ imxmci_start_clock(host);
+}
+
+static void imxmci_finish_request(struct imxmci_host *host, struct mmc_request *req)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ host->pending_events &= ~(IMXMCI_PEND_WAIT_RESP_m | IMXMCI_PEND_DMA_END_m |
+ IMXMCI_PEND_DMA_DATA_m | IMXMCI_PEND_CPU_DATA_m);
+
+ host->imask = IMXMCI_INT_MASK_DEFAULT;
+ MMC_INT_MASK = host->imask;
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ host->req = NULL;
+ host->cmd = NULL;
+ host->data = NULL;
+ mmc_request_done(host->mmc, req);
+}
+
+static int imxmci_finish_data(struct imxmci_host *host, unsigned int stat)
+{
+ struct mmc_data *data = host->data;
+ int data_error;
+
+ if(test_and_clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)){
+ imx_dma_disable(host->dma);
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents,
+ host->dma_dir);
+ }
+
+ if ( stat & STATUS_ERR_MASK ) {
+ dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",stat);
+ if(stat & (STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR))
+ data->error = MMC_ERR_BADCRC;
+ else if(stat & STATUS_TIME_OUT_READ)
+ data->error = MMC_ERR_TIMEOUT;
+ else
+ data->error = MMC_ERR_FAILED;
+ } else {
+ data->bytes_xfered = host->dma_size;
+ }
+
+ data_error = data->error;
+
+ host->data = NULL;
+
+ return data_error;
+}
+
+static int imxmci_cmd_done(struct imxmci_host *host, unsigned int stat)
+{
+ struct mmc_command *cmd = host->cmd;
+ int i;
+ u32 a,b,c;
+ struct mmc_data *data = host->data;
+
+ if (!cmd)
+ return 0;
+
+ host->cmd = NULL;
+
+ if (stat & STATUS_TIME_OUT_RESP) {
+ dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n");
+ cmd->error = MMC_ERR_TIMEOUT;
+ } else if (stat & STATUS_RESP_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
+ dev_dbg(mmc_dev(host->mmc), "cmd crc error\n");
+ cmd->error = MMC_ERR_BADCRC;
+ }
+
+ if(cmd->flags & MMC_RSP_PRESENT) {
+ if(cmd->flags & MMC_RSP_136) {
+ for (i = 0; i < 4; i++) {
+ u32 a = MMC_RES_FIFO & 0xffff;
+ u32 b = MMC_RES_FIFO & 0xffff;
+ cmd->resp[i] = a<<16 | b;
+ }
+ } else {
+ a = MMC_RES_FIFO & 0xffff;
+ b = MMC_RES_FIFO & 0xffff;
+ c = MMC_RES_FIFO & 0xffff;
+ cmd->resp[0] = a<<24 | b<<8 | c>>8;
+ }
+ }
+
+ dev_dbg(mmc_dev(host->mmc), "RESP 0x%08x, 0x%08x, 0x%08x, 0x%08x, error %d\n",
+ cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3], cmd->error);
+
+ if (data && (cmd->error == MMC_ERR_NONE) && !(stat & STATUS_ERR_MASK)) {
+ if (host->req->data->flags & MMC_DATA_WRITE) {
+
+ /* Wait for FIFO to be empty before starting DMA write */
+
+ stat = MMC_STATUS;
+ if(imxmci_busy_wait_for_status(host, &stat,
+ STATUS_APPL_BUFF_FE,
+ 40, "imxmci_cmd_done DMA WR") < 0) {
+ cmd->error = MMC_ERR_FIFO;
+ imxmci_finish_data(host, stat);
+ if(host->req)
+ imxmci_finish_request(host, host->req);
+ dev_warn(mmc_dev(host->mmc), "STATUS = 0x%04x\n",
+ stat);
+ return 0;
+ }
+
+ if(test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) {
+ imx_dma_enable(host->dma);
+ }
+ }
+ } else {
+ struct mmc_request *req;
+ imxmci_stop_clock(host);
+ req = host->req;
+
+ if(data)
+ imxmci_finish_data(host, stat);
+
+ if( req ) {
+ imxmci_finish_request(host, req);
+ } else {
+ dev_warn(mmc_dev(host->mmc), "imxmci_cmd_done: no request to finish\n");
+ }
+ }
+
+ return 1;
+}
+
+static int imxmci_data_done(struct imxmci_host *host, unsigned int stat)
+{
+ struct mmc_data *data = host->data;
+ int data_error;
+
+ if (!data)
+ return 0;
+
+ data_error = imxmci_finish_data(host, stat);
+
+ if (host->req->stop) {
+ imxmci_stop_clock(host);
+ imxmci_start_cmd(host, host->req->stop, 0);
+ } else {
+ struct mmc_request *req;
+ req = host->req;
+ if( req ) {
+ imxmci_finish_request(host, req);
+ } else {
+ dev_warn(mmc_dev(host->mmc), "imxmci_data_done: no request to finish\n");
+ }
+ }
+
+ return 1;
+}
+
+static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
+{
+ int i;
+ int burst_len;
+ int flush_len;
+ int trans_done = 0;
+ unsigned int stat = *pstat;
+
+ if(host->actual_bus_width != MMC_BUS_WIDTH_4)
+ burst_len = 16;
+ else
+ burst_len = 64;
+
+ /* This is unfortunately required */
+ dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n",
+ stat);
+
+ if(host->dma_dir == DMA_FROM_DEVICE) {
+ imxmci_busy_wait_for_status(host, &stat,
+ STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE,
+ 20, "imxmci_cpu_driven_data read");
+
+ while((stat & (STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE)) &&
+ (host->data_cnt < host->dma_size)) {
+ if(burst_len >= host->dma_size - host->data_cnt) {
+ flush_len = burst_len;
+ burst_len = host->dma_size - host->data_cnt;
+ flush_len -= burst_len;
+ host->data_cnt = host->dma_size;
+ trans_done = 1;
+ } else {
+ flush_len = 0;
+ host->data_cnt += burst_len;
+ }
+
+ for(i = burst_len; i>=2 ; i-=2) {
+ *(host->data_ptr++) = MMC_BUFFER_ACCESS;
+ udelay(20); /* required for clocks < 8MHz*/
+ }
+
+ if(i == 1)
+ *(u8*)(host->data_ptr) = MMC_BUFFER_ACCESS;
+
+ stat = MMC_STATUS;
+
+ /* Flush extra bytes from FIFO */
+ while(flush_len && !(stat & STATUS_DATA_TRANS_DONE)){
+ i = MMC_BUFFER_ACCESS;
+ stat = MMC_STATUS;
+ stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */
+ }
+
+ dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read burst %d STATUS = 0x%x\n",
+ burst_len, stat);
+ }
+ } else {
+ imxmci_busy_wait_for_status(host, &stat,
+ STATUS_APPL_BUFF_FE,
+ 20, "imxmci_cpu_driven_data write");
+
+ while((stat & STATUS_APPL_BUFF_FE) &&
+ (host->data_cnt < host->dma_size)) {
+ if(burst_len >= host->dma_size - host->data_cnt) {
+ burst_len = host->dma_size - host->data_cnt;
+ host->data_cnt = host->dma_size;
+ trans_done = 1;
+ } else {
+ host->data_cnt += burst_len;
+ }
+
+ for(i = burst_len; i>0 ; i-=2)
+ MMC_BUFFER_ACCESS = *(host->data_ptr++);
+
+ stat = MMC_STATUS;
+
+ dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data write burst %d STATUS = 0x%x\n",
+ burst_len, stat);
+ }
+ }
+
+ *pstat = stat;
+
+ return trans_done;
+}
+
+static void imxmci_dma_irq(int dma, void *devid, struct pt_regs *regs)
+{
+ struct imxmci_host *host = devid;
+ uint32_t stat = MMC_STATUS;
+
+ atomic_set(&host->stuck_timeout, 0);
+ host->status_reg = stat;
+ set_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
+ tasklet_schedule(&host->tasklet);
+}
+
+static irqreturn_t imxmci_irq(int irq, void *devid, struct pt_regs *regs)
+{
+ struct imxmci_host *host = devid;
+ uint32_t stat = MMC_STATUS;
+ int handled = 1;
+
+ MMC_INT_MASK = host->imask | INT_MASK_SDIO | INT_MASK_AUTO_CARD_DETECT;
+
+ atomic_set(&host->stuck_timeout, 0);
+ host->status_reg = stat;
+ set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
+ set_bit(IMXMCI_PEND_STARTED_b, &host->pending_events);
+ tasklet_schedule(&host->tasklet);
+
+ return IRQ_RETVAL(handled);;
+}
+
+static void imxmci_tasklet_fnc(unsigned long data)
+{
+ struct imxmci_host *host = (struct imxmci_host *)data;
+ u32 stat;
+ unsigned int data_dir_mask = 0; /* STATUS_WR_CRC_ERROR_CODE_MASK */
+ int timeout = 0;
+
+ if(atomic_read(&host->stuck_timeout) > 4) {
+ char *what;
+ timeout = 1;
+ stat = MMC_STATUS;
+ host->status_reg = stat;
+ if (test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+ if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
+ what = "RESP+DMA";
+ else
+ what = "RESP";
+ else
+ if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
+ if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events))
+ what = "DATA";
+ else
+ what = "DMA";
+ else
+ what = "???";
+
+ dev_err(mmc_dev(host->mmc), "%s TIMEOUT, hardware stucked STATUS = 0x%04x IMASK = 0x%04x\n",
+ what, stat, MMC_INT_MASK);
+ dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n",
+ MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma));
+ dev_err(mmc_dev(host->mmc), "CMD%d, bus %d-bit, dma_size = 0x%x\n",
+ host->cmd?host->cmd->opcode:0, 1<<host->actual_bus_width, host->dma_size);
+ }
+
+ if(!host->present || timeout)
+ host->status_reg = STATUS_TIME_OUT_RESP | STATUS_TIME_OUT_READ |
+ STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR;
+
+ if(test_bit(IMXMCI_PEND_IRQ_b, &host->pending_events) || timeout) {
+ clear_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
+
+ stat = MMC_STATUS;
+ /*
+ * This is not required in theory, but there is chance to miss some flag
+ * which clears automatically by mask write, FreeScale original code keeps
+ * stat from IRQ time so do I
+ */
+ stat |= host->status_reg;
+
+ if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
+ imxmci_busy_wait_for_status(host, &stat,
+ STATUS_END_CMD_RESP | STATUS_ERR_MASK,
+ 20, "imxmci_tasklet_fnc resp (ERRATUM #4)");
+ }
+
+ if(stat & (STATUS_END_CMD_RESP | STATUS_ERR_MASK)) {
+ if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+ imxmci_cmd_done(host, stat);
+ if(host->data && (stat & STATUS_ERR_MASK))
+ imxmci_data_done(host, stat);
+ }
+
+ if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) {
+ stat |= MMC_STATUS;
+ if(imxmci_cpu_driven_data(host, &stat)){
+ if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+ imxmci_cmd_done(host, stat);
+ atomic_clear_mask(IMXMCI_PEND_IRQ_m|IMXMCI_PEND_CPU_DATA_m,
+ &host->pending_events);
+ imxmci_data_done(host, stat);
+ }
+ }
+ }
+
+ if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events) &&
+ !test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
+
+ stat = MMC_STATUS;
+ /* Same as above */
+ stat |= host->status_reg;
+
+ if(host->dma_dir == DMA_TO_DEVICE) {
+ data_dir_mask = STATUS_WRITE_OP_DONE;
+ } else {
+ data_dir_mask = STATUS_DATA_TRANS_DONE;
+ }
+
+ if(stat & data_dir_mask) {
+ clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
+ imxmci_data_done(host, stat);
+ }
+ }
+
+ if(test_and_clear_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events)) {
+
+ if(host->cmd)
+ imxmci_cmd_done(host, STATUS_TIME_OUT_RESP);
+
+ if(host->data)
+ imxmci_data_done(host, STATUS_TIME_OUT_READ |
+ STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR);
+
+ if(host->req)
+ imxmci_finish_request(host, host->req);
+
+ mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+
+ }
+}
+
+static void imxmci_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+ struct imxmci_host *host = mmc_priv(mmc);
+ unsigned int cmdat;
+
+ WARN_ON(host->req != NULL);
+
+ host->req = req;
+
+ cmdat = 0;
+
+ if (req->data) {
+ imxmci_setup_data(host, req->data);
+
+ cmdat |= CMD_DAT_CONT_DATA_ENABLE;
+
+ if (req->data->flags & MMC_DATA_WRITE)
+ cmdat |= CMD_DAT_CONT_WRITE;
+
+ if (req->data->flags & MMC_DATA_STREAM) {
+ cmdat |= CMD_DAT_CONT_STREAM_BLOCK;
+ }
+ }
+
+ imxmci_start_cmd(host, req->cmd, cmdat);
+}
+
+#define CLK_RATE 19200000
+
+static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct imxmci_host *host = mmc_priv(mmc);
+ int prescaler;
+
+ if( ios->bus_width==MMC_BUS_WIDTH_4 ) {
+ host->actual_bus_width = MMC_BUS_WIDTH_4;
+ imx_gpio_mode(PB11_PF_SD_DAT3);
+ }else{
+ host->actual_bus_width = MMC_BUS_WIDTH_1;
+ imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
+ }
+
+ if ( host->power_mode != ios->power_mode ) {
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF:
+ break;
+ case MMC_POWER_UP:
+ set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events);
+ break;
+ case MMC_POWER_ON:
+ break;
+ }
+ host->power_mode = ios->power_mode;
+ }
+
+ if ( ios->clock ) {
+ unsigned int clk;
+
+ /* The prescaler is 5 for PERCLK2 equal to 96MHz
+ * then 96MHz / 5 = 19.2 MHz
+ */
+ clk=imx_get_perclk2();
+ prescaler=(clk+(CLK_RATE*7)/8)/CLK_RATE;
+ switch(prescaler) {
+ case 0:
+ case 1: prescaler = 0;
+ break;
+ case 2: prescaler = 1;
+ break;
+ case 3: prescaler = 2;
+ break;
+ case 4: prescaler = 4;
+ break;
+ default:
+ case 5: prescaler = 5;
+ break;
+ }
+
+ dev_dbg(mmc_dev(host->mmc), "PERCLK2 %d MHz -> prescaler %d\n",
+ clk, prescaler);
+
+ for(clk=0; clk<8; clk++) {
+ int x;
+ x = CLK_RATE / (1<<clk);
+ if( x <= ios->clock)
+ break;
+ }
+
+ MMC_STR_STP_CLK |= STR_STP_CLK_ENABLE; /* enable controller */
+
+ imxmci_stop_clock(host);
+ MMC_CLK_RATE = (prescaler<<3) | clk;
+ /*
+ * Under my understanding, clock should not be started there, because it would
+ * initiate SDHC sequencer and send last or random command into card
+ */
+ /*imxmci_start_clock(host);*/
+
+ dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE);
+ } else {
+ imxmci_stop_clock(host);
+ }
+}
+
+static struct mmc_host_ops imxmci_ops = {
+ .request = imxmci_request,
+ .set_ios = imxmci_set_ios,
+};
+
+static struct resource *platform_device_resource(struct platform_device *dev, unsigned int mask, int nr)
+{
+ int i;
+
+ for (i = 0; i < dev->num_resources; i++)
+ if (dev->resource[i].flags == mask && nr-- == 0)
+ return &dev->resource[i];
+ return NULL;
+}
+
+static int platform_device_irq(struct platform_device *dev, int nr)
+{
+ int i;
+
+ for (i = 0; i < dev->num_resources; i++)
+ if (dev->resource[i].flags == IORESOURCE_IRQ && nr-- == 0)
+ return dev->resource[i].start;
+ return NO_IRQ;
+}
+
+static void imxmci_check_status(unsigned long data)
+{
+ struct imxmci_host *host = (struct imxmci_host *)data;
+
+ if( host->pdata->card_present() != host->present ) {
+ host->present ^= 1;
+ dev_info(mmc_dev(host->mmc), "card %s\n",
+ host->present ? "inserted" : "removed");
+
+ set_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events);
+ tasklet_schedule(&host->tasklet);
+ }
+
+ if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events) ||
+ test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) {
+ atomic_inc(&host->stuck_timeout);
+ if(atomic_read(&host->stuck_timeout) > 4)
+ tasklet_schedule(&host->tasklet);
+ } else {
+ atomic_set(&host->stuck_timeout, 0);
+
+ }
+
+ mod_timer(&host->timer, jiffies + (HZ>>1));
+}
+
+static int imxmci_probe(struct platform_device *pdev)
+{
+ struct mmc_host *mmc;
+ struct imxmci_host *host = NULL;
+ struct resource *r;
+ int ret = 0, irq;
+
+ printk(KERN_INFO "i.MX mmc driver\n");
+
+ r = platform_device_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_device_irq(pdev, 0);
+ if (!r || irq == NO_IRQ)
+ return -ENXIO;
+
+ r = request_mem_region(r->start, 0x100, "IMXMCI");
+ if (!r)
+ return -EBUSY;
+
+ mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev);
+ if (!mmc) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ mmc->ops = &imxmci_ops;
+ mmc->f_min = 150000;
+ mmc->f_max = CLK_RATE/2;
+ mmc->ocr_avail = MMC_VDD_32_33;
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+ /* MMC core transfer sizes tunable parameters */
+ mmc->max_hw_segs = 64;
+ mmc->max_phys_segs = 64;
+ mmc->max_sectors = 64; /* default 1 << (PAGE_CACHE_SHIFT - 9) */
+ mmc->max_seg_size = 64*512; /* default PAGE_CACHE_SIZE */
+
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
+ host->dma_allocated = 0;
+ host->pdata = pdev->dev.platform_data;
+
+ spin_lock_init(&host->lock);
+ host->res = r;
+ host->irq = irq;
+
+ imx_gpio_mode(PB8_PF_SD_DAT0);
+ imx_gpio_mode(PB9_PF_SD_DAT1);
+ imx_gpio_mode(PB10_PF_SD_DAT2);
+ /* Configured as GPIO with pull-up to ensure right MCC card mode */
+ /* Switched to PB11_PF_SD_DAT3 if 4 bit bus is configured */
+ imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
+ /* imx_gpio_mode(PB11_PF_SD_DAT3); */
+ imx_gpio_mode(PB12_PF_SD_CLK);
+ imx_gpio_mode(PB13_PF_SD_CMD);
+
+ imxmci_softreset();
+
+ if ( MMC_REV_NO != 0x390 ) {
+ dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n",
+ MMC_REV_NO);
+ goto out;
+ }
+
+ MMC_READ_TO = 0x2db4; /* recommended in data sheet */
+
+ host->imask = IMXMCI_INT_MASK_DEFAULT;
+ MMC_INT_MASK = host->imask;
+
+
+ if(imx_dma_request_by_prio(&host->dma, DRIVER_NAME, DMA_PRIO_LOW)<0){
+ dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n");
+ ret = -EBUSY;
+ goto out;
+ }
+ host->dma_allocated=1;
+ imx_dma_setup_handlers(host->dma, imxmci_dma_irq, NULL, host);
+
+ tasklet_init(&host->tasklet, imxmci_tasklet_fnc, (unsigned long)host);
+ host->status_reg=0;
+ host->pending_events=0;
+
+ ret = request_irq(host->irq, imxmci_irq, 0, DRIVER_NAME, host);
+ if (ret)
+ goto out;
+
+ host->present = host->pdata->card_present();
+ init_timer(&host->timer);
+ host->timer.data = (unsigned long)host;
+ host->timer.function = imxmci_check_status;
+ add_timer(&host->timer);
+ mod_timer(&host->timer, jiffies + (HZ>>1));
+
+ platform_set_drvdata(pdev, mmc);
+
+ mmc_add_host(mmc);
+
+ return 0;
+
+out:
+ if (host) {
+ if(host->dma_allocated){
+ imx_dma_free(host->dma);
+ host->dma_allocated=0;
+ }
+ }
+ if (mmc)
+ mmc_free_host(mmc);
+ release_resource(r);
+ return ret;
+}
+
+static int imxmci_remove(struct platform_device *pdev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ if (mmc) {
+ struct imxmci_host *host = mmc_priv(mmc);
+
+ tasklet_disable(&host->tasklet);
+
+ del_timer_sync(&host->timer);
+ mmc_remove_host(mmc);
+
+ free_irq(host->irq, host);
+ if(host->dma_allocated){
+ imx_dma_free(host->dma);
+ host->dma_allocated=0;
+ }
+
+ tasklet_kill(&host->tasklet);
+
+ release_resource(host->res);
+
+ mmc_free_host(mmc);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int imxmci_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct mmc_host *mmc = platform_get_drvdata(dev);
+ int ret = 0;
+
+ if (mmc)
+ ret = mmc_suspend_host(mmc, state);
+
+ return ret;
+}
+
+static int imxmci_resume(struct platform_device *dev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct imxmci_host *host;
+ int ret = 0;
+
+ if (mmc) {
+ host = mmc_priv(mmc);
+ if(host)
+ set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events);
+ ret = mmc_resume_host(mmc);
+ }
+
+ return ret;
+}
+#else
+#define imxmci_suspend NULL
+#define imxmci_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver imxmci_driver = {
+ .probe = imxmci_probe,
+ .remove = imxmci_remove,
+ .suspend = imxmci_suspend,
+ .resume = imxmci_resume,
+ .driver = {
+ .name = DRIVER_NAME,
+ }
+};
+
+static int __init imxmci_init(void)
+{
+ return platform_driver_register(&imxmci_driver);
+}
+
+static void __exit imxmci_exit(void)
+{
+ platform_driver_unregister(&imxmci_driver);
+}
+
+module_init(imxmci_init);
+module_exit(imxmci_exit);
+
+MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/imxmmc.h b/drivers/mmc/imxmmc.h
new file mode 100644
index 00000000000..e5339e334db
--- /dev/null
+++ b/drivers/mmc/imxmmc.h
@@ -0,0 +1,67 @@
+
+# define __REG16(x) (*((volatile u16 *)IO_ADDRESS(x)))
+
+#define MMC_STR_STP_CLK __REG16(IMX_MMC_BASE + 0x00)
+#define MMC_STATUS __REG16(IMX_MMC_BASE + 0x04)
+#define MMC_CLK_RATE __REG16(IMX_MMC_BASE + 0x08)
+#define MMC_CMD_DAT_CONT __REG16(IMX_MMC_BASE + 0x0C)
+#define MMC_RES_TO __REG16(IMX_MMC_BASE + 0x10)
+#define MMC_READ_TO __REG16(IMX_MMC_BASE + 0x14)
+#define MMC_BLK_LEN __REG16(IMX_MMC_BASE + 0x18)
+#define MMC_NOB __REG16(IMX_MMC_BASE + 0x1C)
+#define MMC_REV_NO __REG16(IMX_MMC_BASE + 0x20)
+#define MMC_INT_MASK __REG16(IMX_MMC_BASE + 0x24)
+#define MMC_CMD __REG16(IMX_MMC_BASE + 0x28)
+#define MMC_ARGH __REG16(IMX_MMC_BASE + 0x2C)
+#define MMC_ARGL __REG16(IMX_MMC_BASE + 0x30)
+#define MMC_RES_FIFO __REG16(IMX_MMC_BASE + 0x34)
+#define MMC_BUFFER_ACCESS __REG16(IMX_MMC_BASE + 0x38)
+#define MMC_BUFFER_ACCESS_OFS 0x38
+
+
+#define STR_STP_CLK_ENDIAN (1<<5)
+#define STR_STP_CLK_RESET (1<<3)
+#define STR_STP_CLK_ENABLE (1<<2)
+#define STR_STP_CLK_START_CLK (1<<1)
+#define STR_STP_CLK_STOP_CLK (1<<0)
+#define STATUS_CARD_PRESENCE (1<<15)
+#define STATUS_SDIO_INT_ACTIVE (1<<14)
+#define STATUS_END_CMD_RESP (1<<13)
+#define STATUS_WRITE_OP_DONE (1<<12)
+#define STATUS_DATA_TRANS_DONE (1<<11)
+#define STATUS_WR_CRC_ERROR_CODE_MASK (3<<10)
+#define STATUS_CARD_BUS_CLK_RUN (1<<8)
+#define STATUS_APPL_BUFF_FF (1<<7)
+#define STATUS_APPL_BUFF_FE (1<<6)
+#define STATUS_RESP_CRC_ERR (1<<5)
+#define STATUS_CRC_READ_ERR (1<<3)
+#define STATUS_CRC_WRITE_ERR (1<<2)
+#define STATUS_TIME_OUT_RESP (1<<1)
+#define STATUS_TIME_OUT_READ (1<<0)
+#define STATUS_ERR_MASK 0x2f
+#define CLK_RATE_PRESCALER(x) ((x) & 0x7)
+#define CLK_RATE_CLK_RATE(x) (((x) & 0x7) << 3)
+#define CMD_DAT_CONT_CMD_RESP_LONG_OFF (1<<12)
+#define CMD_DAT_CONT_STOP_READWAIT (1<<11)
+#define CMD_DAT_CONT_START_READWAIT (1<<10)
+#define CMD_DAT_CONT_BUS_WIDTH_1 (0<<8)
+#define CMD_DAT_CONT_BUS_WIDTH_4 (2<<8)
+#define CMD_DAT_CONT_INIT (1<<7)
+#define CMD_DAT_CONT_BUSY (1<<6)
+#define CMD_DAT_CONT_STREAM_BLOCK (1<<5)
+#define CMD_DAT_CONT_WRITE (1<<4)
+#define CMD_DAT_CONT_DATA_ENABLE (1<<3)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R1 (1)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R2 (2)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R3 (3)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R4 (4)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R5 (5)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R6 (6)
+#define INT_MASK_AUTO_CARD_DETECT (1<<6)
+#define INT_MASK_DAT0_EN (1<<5)
+#define INT_MASK_SDIO (1<<4)
+#define INT_MASK_BUF_READY (1<<3)
+#define INT_MASK_END_CMD_RES (1<<2)
+#define INT_MASK_WRITE_OP_DONE (1<<1)
+#define INT_MASK_DATA_TRAN (1<<0)
+#define INT_ALL (0x7f)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 1888060c5e0..6201f3086a0 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -27,12 +27,6 @@
#include "mmc.h"
-#ifdef CONFIG_MMC_DEBUG
-#define DBG(x...) printk(KERN_DEBUG x)
-#else
-#define DBG(x...) do { } while (0)
-#endif
-
#define CMD_RETRIES 3
/*
@@ -65,20 +59,23 @@ static const unsigned int tacc_mant[] = {
/**
- * mmc_request_done - finish processing an MMC command
- * @host: MMC host which completed command
- * @mrq: MMC request which completed
+ * mmc_request_done - finish processing an MMC request
+ * @host: MMC host which completed request
+ * @mrq: MMC request which request
*
* MMC drivers should call this function when they have completed
- * their processing of a command. This should be called before the
- * data part of the command has completed.
+ * their processing of a request.
*/
void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
{
struct mmc_command *cmd = mrq->cmd;
- int err = mrq->cmd->error;
- DBG("MMC: req done (%02x): %d: %08x %08x %08x %08x\n", cmd->opcode,
- err, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+ int err = cmd->error;
+
+ pr_debug("%s: req done (CMD%u): %d/%d/%d: %08x %08x %08x %08x\n",
+ mmc_hostname(host), cmd->opcode, err,
+ mrq->data ? mrq->data->error : 0,
+ mrq->stop ? mrq->stop->error : 0,
+ cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
if (err && cmd->retries) {
cmd->retries--;
@@ -102,8 +99,9 @@ EXPORT_SYMBOL(mmc_request_done);
void
mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
{
- DBG("MMC: starting cmd %02x arg %08x flags %08x\n",
- mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags);
+ pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
+ mmc_hostname(host), mrq->cmd->opcode,
+ mrq->cmd->arg, mrq->cmd->flags);
WARN_ON(host->card_busy == NULL);
@@ -317,6 +315,18 @@ void mmc_release_host(struct mmc_host *host)
EXPORT_SYMBOL(mmc_release_host);
+static inline void mmc_set_ios(struct mmc_host *host)
+{
+ struct mmc_ios *ios = &host->ios;
+
+ pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
+ mmc_hostname(host), ios->clock, ios->bus_mode,
+ ios->power_mode, ios->chip_select, ios->vdd,
+ ios->bus_width);
+
+ host->ops->set_ios(host, ios);
+}
+
static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
{
int err;
@@ -369,7 +379,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
}
}
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
return MMC_ERR_NONE;
}
@@ -420,7 +430,7 @@ static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
ocr = 3 << bit;
host->ios.vdd = bit;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
} else {
ocr = 0;
}
@@ -554,6 +564,7 @@ static void mmc_decode_csd(struct mmc_card *card)
csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
} else {
@@ -588,6 +599,7 @@ static void mmc_decode_csd(struct mmc_card *card)
csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
}
@@ -671,7 +683,7 @@ static void mmc_idle_cards(struct mmc_host *host)
struct mmc_command cmd;
host->ios.chip_select = MMC_CS_HIGH;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
mmc_delay(1);
@@ -684,7 +696,7 @@ static void mmc_idle_cards(struct mmc_host *host)
mmc_delay(1);
host->ios.chip_select = MMC_CS_DONTCARE;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
mmc_delay(1);
}
@@ -709,13 +721,13 @@ static void mmc_power_up(struct mmc_host *host)
host->ios.chip_select = MMC_CS_DONTCARE;
host->ios.power_mode = MMC_POWER_UP;
host->ios.bus_width = MMC_BUS_WIDTH_1;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
mmc_delay(1);
host->ios.clock = host->f_min;
host->ios.power_mode = MMC_POWER_ON;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
mmc_delay(2);
}
@@ -728,7 +740,7 @@ static void mmc_power_off(struct mmc_host *host)
host->ios.chip_select = MMC_CS_DONTCARE;
host->ios.power_mode = MMC_POWER_OFF;
host->ios.bus_width = MMC_BUS_WIDTH_1;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
}
static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
@@ -939,6 +951,7 @@ static void mmc_read_scrs(struct mmc_host *host)
data.timeout_ns = card->csd.tacc_ns * 10;
data.timeout_clks = card->csd.tacc_clks * 10;
data.blksz_bits = 3;
+ data.blksz = 1 << 3;
data.blocks = 1;
data.flags = MMC_DATA_READ;
data.sg = &sg;
@@ -976,8 +989,9 @@ static unsigned int mmc_calculate_clock(struct mmc_host *host)
if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr)
max_dtr = card->csd.max_dtr;
- DBG("MMC: selected %d.%03dMHz transfer rate\n",
- max_dtr / 1000000, (max_dtr / 1000) % 1000);
+ pr_debug("%s: selected %d.%03dMHz transfer rate\n",
+ mmc_hostname(host),
+ max_dtr / 1000000, (max_dtr / 1000) % 1000);
return max_dtr;
}
@@ -1051,7 +1065,7 @@ static void mmc_setup(struct mmc_host *host)
} else {
host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
host->ios.clock = host->f_min;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
/*
* We should remember the OCR mask from the existing
@@ -1087,7 +1101,7 @@ static void mmc_setup(struct mmc_host *host)
* Ok, now switch to push-pull mode.
*/
host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
mmc_read_csds(host);
@@ -1133,7 +1147,7 @@ static void mmc_rescan(void *data)
* attached cards and the host support.
*/
host->ios.clock = mmc_calculate_clock(host);
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
}
mmc_release_host(host);
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 8eb2a2ede64..587458b370b 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -175,6 +175,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
brq.data.timeout_ns = card->csd.tacc_ns * 10;
brq.data.timeout_clks = card->csd.tacc_clks * 10;
brq.data.blksz_bits = md->block_bits;
+ brq.data.blksz = 1 << md->block_bits;
brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
brq.stop.opcode = MMC_STOP_TRANSMISSION;
brq.stop.arg = 0;
@@ -187,6 +188,12 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
brq.cmd.opcode = MMC_WRITE_BLOCK;
brq.data.flags |= MMC_DATA_WRITE;
brq.data.blocks = 1;
+
+ /*
+ * Scale up the timeout by the r2w factor
+ */
+ brq.data.timeout_ns <<= card->csd.r2w_factor;
+ brq.data.timeout_clks <<= card->csd.r2w_factor;
}
if (brq.data.blocks > 1) {
@@ -346,7 +353,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
*/
printk(KERN_ERR "%s: unable to select block size for "
"writing (rb%u wb%u rp%u wp%u)\n",
- md->disk->disk_name,
+ mmc_card_id(card),
1 << card->csd.read_blkbits,
1 << card->csd.write_blkbits,
card->csd.read_partial,
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 9fef29d978b..da8e4d7339c 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -33,12 +33,8 @@
#define DRIVER_NAME "mmci-pl18x"
-#ifdef CONFIG_MMC_DEBUG
#define DBG(host,fmt,args...) \
pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args)
-#else
-#define DBG(host,fmt,args...) do { } while (0)
-#endif
static unsigned int fmax = 515633;
@@ -406,9 +402,6 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct mmci_host *host = mmc_priv(mmc);
u32 clk = 0, pwr = 0;
- DBG(host, "clock %uHz busmode %u powermode %u Vdd %u\n",
- ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
-
if (ios->clock) {
if (ios->clock >= host->mclk) {
clk = MCI_CLK_BYPASS;
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c
new file mode 100644
index 00000000000..becb3c68c34
--- /dev/null
+++ b/drivers/mmc/omap.c
@@ -0,0 +1,1226 @@
+/*
+ * linux/drivers/media/mmc/omap.c
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Written by Tuukka Tikkanen and Juha Yrjölä<juha.yrjola@nokia.com>
+ * Misc hacks here and there by Tony Lindgren <tony@atomide.com>
+ * Other hacks (DMA, SD, etc) by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+#include <linux/mmc/card.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/scatterlist.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/fpga.h>
+#include <asm/arch/tps65010.h>
+
+#include "omap.h"
+
+#define DRIVER_NAME "mmci-omap"
+#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
+
+/* Specifies how often in millisecs to poll for card status changes
+ * when the cover switch is open */
+#define OMAP_MMC_SWITCH_POLL_DELAY 500
+
+static int mmc_omap_enable_poll = 1;
+
+struct mmc_omap_host {
+ int initialized;
+ int suspended;
+ struct mmc_request * mrq;
+ struct mmc_command * cmd;
+ struct mmc_data * data;
+ struct mmc_host * mmc;
+ struct device * dev;
+ unsigned char id; /* 16xx chips have 2 MMC blocks */
+ struct clk * iclk;
+ struct clk * fclk;
+ void __iomem *base;
+ int irq;
+ unsigned char bus_mode;
+ unsigned char hw_bus_mode;
+
+ unsigned int sg_len;
+ int sg_idx;
+ u16 * buffer;
+ u32 buffer_bytes_left;
+ u32 total_bytes_left;
+
+ unsigned use_dma:1;
+ unsigned brs_received:1, dma_done:1;
+ unsigned dma_is_read:1;
+ unsigned dma_in_use:1;
+ int dma_ch;
+ spinlock_t dma_lock;
+ struct timer_list dma_timer;
+ unsigned dma_len;
+
+ short power_pin;
+ short wp_pin;
+
+ int switch_pin;
+ struct work_struct switch_work;
+ struct timer_list switch_timer;
+ int switch_last_state;
+};
+
+static inline int
+mmc_omap_cover_is_open(struct mmc_omap_host *host)
+{
+ if (host->switch_pin < 0)
+ return 0;
+ return omap_get_gpio_datain(host->switch_pin);
+}
+
+static ssize_t
+mmc_omap_show_cover_switch(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", mmc_omap_cover_is_open(host) ? "open" :
+ "closed");
+}
+
+static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
+
+static ssize_t
+mmc_omap_show_enable_poll(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", mmc_omap_enable_poll);
+}
+
+static ssize_t
+mmc_omap_store_enable_poll(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ int enable_poll;
+
+ if (sscanf(buf, "%10d", &enable_poll) != 1)
+ return -EINVAL;
+
+ if (enable_poll != mmc_omap_enable_poll) {
+ struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+ mmc_omap_enable_poll = enable_poll;
+ if (enable_poll && host->switch_pin >= 0)
+ schedule_work(&host->switch_work);
+ }
+ return size;
+}
+
+static DEVICE_ATTR(enable_poll, 0664,
+ mmc_omap_show_enable_poll, mmc_omap_store_enable_poll);
+
+static void
+mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
+{
+ u32 cmdreg;
+ u32 resptype;
+ u32 cmdtype;
+
+ host->cmd = cmd;
+
+ resptype = 0;
+ cmdtype = 0;
+
+ /* Our hardware needs to know exact type */
+ switch (RSP_TYPE(mmc_resp_type(cmd))) {
+ case RSP_TYPE(MMC_RSP_R1):
+ /* resp 1, resp 1b */
+ resptype = 1;
+ break;
+ case RSP_TYPE(MMC_RSP_R2):
+ resptype = 2;
+ break;
+ case RSP_TYPE(MMC_RSP_R3):
+ resptype = 3;
+ break;
+ default:
+ break;
+ }
+
+ if (mmc_cmd_type(cmd) == MMC_CMD_ADTC) {
+ cmdtype = OMAP_MMC_CMDTYPE_ADTC;
+ } else if (mmc_cmd_type(cmd) == MMC_CMD_BC) {
+ cmdtype = OMAP_MMC_CMDTYPE_BC;
+ } else if (mmc_cmd_type(cmd) == MMC_CMD_BCR) {
+ cmdtype = OMAP_MMC_CMDTYPE_BCR;
+ } else {
+ cmdtype = OMAP_MMC_CMDTYPE_AC;
+ }
+
+ cmdreg = cmd->opcode | (resptype << 8) | (cmdtype << 12);
+
+ if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+ cmdreg |= 1 << 6;
+
+ if (cmd->flags & MMC_RSP_BUSY)
+ cmdreg |= 1 << 11;
+
+ if (host->data && !(host->data->flags & MMC_DATA_WRITE))
+ cmdreg |= 1 << 15;
+
+ clk_enable(host->fclk);
+
+ OMAP_MMC_WRITE(host->base, CTO, 200);
+ OMAP_MMC_WRITE(host->base, ARGL, cmd->arg & 0xffff);
+ OMAP_MMC_WRITE(host->base, ARGH, cmd->arg >> 16);
+ OMAP_MMC_WRITE(host->base, IE,
+ OMAP_MMC_STAT_A_EMPTY | OMAP_MMC_STAT_A_FULL |
+ OMAP_MMC_STAT_CMD_CRC | OMAP_MMC_STAT_CMD_TOUT |
+ OMAP_MMC_STAT_DATA_CRC | OMAP_MMC_STAT_DATA_TOUT |
+ OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR |
+ OMAP_MMC_STAT_END_OF_DATA);
+ OMAP_MMC_WRITE(host->base, CMD, cmdreg);
+}
+
+static void
+mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
+{
+ if (host->dma_in_use) {
+ enum dma_data_direction dma_data_dir;
+
+ BUG_ON(host->dma_ch < 0);
+ if (data->error != MMC_ERR_NONE)
+ omap_stop_dma(host->dma_ch);
+ /* Release DMA channel lazily */
+ mod_timer(&host->dma_timer, jiffies + HZ);
+ if (data->flags & MMC_DATA_WRITE)
+ dma_data_dir = DMA_TO_DEVICE;
+ else
+ dma_data_dir = DMA_FROM_DEVICE;
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
+ dma_data_dir);
+ }
+ host->data = NULL;
+ host->sg_len = 0;
+ clk_disable(host->fclk);
+
+ /* NOTE: MMC layer will sometimes poll-wait CMD13 next, issuing
+ * dozens of requests until the card finishes writing data.
+ * It'd be cheaper to just wait till an EOFB interrupt arrives...
+ */
+
+ if (!data->stop) {
+ host->mrq = NULL;
+ mmc_request_done(host->mmc, data->mrq);
+ return;
+ }
+
+ mmc_omap_start_command(host, data->stop);
+}
+
+static void
+mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data)
+{
+ unsigned long flags;
+ int done;
+
+ if (!host->dma_in_use) {
+ mmc_omap_xfer_done(host, data);
+ return;
+ }
+ done = 0;
+ spin_lock_irqsave(&host->dma_lock, flags);
+ if (host->dma_done)
+ done = 1;
+ else
+ host->brs_received = 1;
+ spin_unlock_irqrestore(&host->dma_lock, flags);
+ if (done)
+ mmc_omap_xfer_done(host, data);
+}
+
+static void
+mmc_omap_dma_timer(unsigned long data)
+{
+ struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+
+ BUG_ON(host->dma_ch < 0);
+ omap_free_dma(host->dma_ch);
+ host->dma_ch = -1;
+}
+
+static void
+mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data)
+{
+ unsigned long flags;
+ int done;
+
+ done = 0;
+ spin_lock_irqsave(&host->dma_lock, flags);
+ if (host->brs_received)
+ done = 1;
+ else
+ host->dma_done = 1;
+ spin_unlock_irqrestore(&host->dma_lock, flags);
+ if (done)
+ mmc_omap_xfer_done(host, data);
+}
+
+static void
+mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
+{
+ host->cmd = NULL;
+
+ if (cmd->flags & MMC_RSP_PRESENT) {
+ if (cmd->flags & MMC_RSP_136) {
+ /* response type 2 */
+ cmd->resp[3] =
+ OMAP_MMC_READ(host->base, RSP0) |
+ (OMAP_MMC_READ(host->base, RSP1) << 16);
+ cmd->resp[2] =
+ OMAP_MMC_READ(host->base, RSP2) |
+ (OMAP_MMC_READ(host->base, RSP3) << 16);
+ cmd->resp[1] =
+ OMAP_MMC_READ(host->base, RSP4) |
+ (OMAP_MMC_READ(host->base, RSP5) << 16);
+ cmd->resp[0] =
+ OMAP_MMC_READ(host->base, RSP6) |
+ (OMAP_MMC_READ(host->base, RSP7) << 16);
+ } else {
+ /* response types 1, 1b, 3, 4, 5, 6 */
+ cmd->resp[0] =
+ OMAP_MMC_READ(host->base, RSP6) |
+ (OMAP_MMC_READ(host->base, RSP7) << 16);
+ }
+ }
+
+ if (host->data == NULL || cmd->error != MMC_ERR_NONE) {
+ host->mrq = NULL;
+ clk_disable(host->fclk);
+ mmc_request_done(host->mmc, cmd->mrq);
+ }
+}
+
+/* PIO only */
+static void
+mmc_omap_sg_to_buf(struct mmc_omap_host *host)
+{
+ struct scatterlist *sg;
+
+ sg = host->data->sg + host->sg_idx;
+ host->buffer_bytes_left = sg->length;
+ host->buffer = page_address(sg->page) + sg->offset;
+ if (host->buffer_bytes_left > host->total_bytes_left)
+ host->buffer_bytes_left = host->total_bytes_left;
+}
+
+/* PIO only */
+static void
+mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
+{
+ int n;
+ void __iomem *reg;
+ u16 *p;
+
+ if (host->buffer_bytes_left == 0) {
+ host->sg_idx++;
+ BUG_ON(host->sg_idx == host->sg_len);
+ mmc_omap_sg_to_buf(host);
+ }
+ n = 64;
+ if (n > host->buffer_bytes_left)
+ n = host->buffer_bytes_left;
+ host->buffer_bytes_left -= n;
+ host->total_bytes_left -= n;
+ host->data->bytes_xfered += n;
+
+ if (write) {
+ __raw_writesw(host->base + OMAP_MMC_REG_DATA, host->buffer, n);
+ } else {
+ __raw_readsw(host->base + OMAP_MMC_REG_DATA, host->buffer, n);
+ }
+}
+
+static inline void mmc_omap_report_irq(u16 status)
+{
+ static const char *mmc_omap_status_bits[] = {
+ "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO",
+ "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR"
+ };
+ int i, c = 0;
+
+ for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++)
+ if (status & (1 << i)) {
+ if (c)
+ printk(" ");
+ printk("%s", mmc_omap_status_bits[i]);
+ c++;
+ }
+}
+
+static irqreturn_t mmc_omap_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct mmc_omap_host * host = (struct mmc_omap_host *)dev_id;
+ u16 status;
+ int end_command;
+ int end_transfer;
+ int transfer_error;
+
+ if (host->cmd == NULL && host->data == NULL) {
+ status = OMAP_MMC_READ(host->base, STAT);
+ dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status);
+ if (status != 0) {
+ OMAP_MMC_WRITE(host->base, STAT, status);
+ OMAP_MMC_WRITE(host->base, IE, 0);
+ }
+ return IRQ_HANDLED;
+ }
+
+ end_command = 0;
+ end_transfer = 0;
+ transfer_error = 0;
+
+ while ((status = OMAP_MMC_READ(host->base, STAT)) != 0) {
+ OMAP_MMC_WRITE(host->base, STAT, status);
+#ifdef CONFIG_MMC_DEBUG
+ dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ",
+ status, host->cmd != NULL ? host->cmd->opcode : -1);
+ mmc_omap_report_irq(status);
+ printk("\n");
+#endif
+ if (host->total_bytes_left) {
+ if ((status & OMAP_MMC_STAT_A_FULL) ||
+ (status & OMAP_MMC_STAT_END_OF_DATA))
+ mmc_omap_xfer_data(host, 0);
+ if (status & OMAP_MMC_STAT_A_EMPTY)
+ mmc_omap_xfer_data(host, 1);
+ }
+
+ if (status & OMAP_MMC_STAT_END_OF_DATA) {
+ end_transfer = 1;
+ }
+
+ if (status & OMAP_MMC_STAT_DATA_TOUT) {
+ dev_dbg(mmc_dev(host->mmc), "data timeout\n");
+ if (host->data) {
+ host->data->error |= MMC_ERR_TIMEOUT;
+ transfer_error = 1;
+ }
+ }
+
+ if (status & OMAP_MMC_STAT_DATA_CRC) {
+ if (host->data) {
+ host->data->error |= MMC_ERR_BADCRC;
+ dev_dbg(mmc_dev(host->mmc),
+ "data CRC error, bytes left %d\n",
+ host->total_bytes_left);
+ transfer_error = 1;
+ } else {
+ dev_dbg(mmc_dev(host->mmc), "data CRC error\n");
+ }
+ }
+
+ if (status & OMAP_MMC_STAT_CMD_TOUT) {
+ /* Timeouts are routine with some commands */
+ if (host->cmd) {
+ if (host->cmd->opcode != MMC_ALL_SEND_CID &&
+ host->cmd->opcode !=
+ MMC_SEND_OP_COND &&
+ host->cmd->opcode !=
+ MMC_APP_CMD &&
+ !mmc_omap_cover_is_open(host))
+ dev_err(mmc_dev(host->mmc),
+ "command timeout, CMD %d\n",
+ host->cmd->opcode);
+ host->cmd->error = MMC_ERR_TIMEOUT;
+ end_command = 1;
+ }
+ }
+
+ if (status & OMAP_MMC_STAT_CMD_CRC) {
+ if (host->cmd) {
+ dev_err(mmc_dev(host->mmc),
+ "command CRC error (CMD%d, arg 0x%08x)\n",
+ host->cmd->opcode, host->cmd->arg);
+ host->cmd->error = MMC_ERR_BADCRC;
+ end_command = 1;
+ } else
+ dev_err(mmc_dev(host->mmc),
+ "command CRC error without cmd?\n");
+ }
+
+ if (status & OMAP_MMC_STAT_CARD_ERR) {
+ if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) {
+ u32 response = OMAP_MMC_READ(host->base, RSP6)
+ | (OMAP_MMC_READ(host->base, RSP7) << 16);
+ /* STOP sometimes sets must-ignore bits */
+ if (!(response & (R1_CC_ERROR
+ | R1_ILLEGAL_COMMAND
+ | R1_COM_CRC_ERROR))) {
+ end_command = 1;
+ continue;
+ }
+ }
+
+ dev_dbg(mmc_dev(host->mmc), "card status error (CMD%d)\n",
+ host->cmd->opcode);
+ if (host->cmd) {
+ host->cmd->error = MMC_ERR_FAILED;
+ end_command = 1;
+ }
+ if (host->data) {
+ host->data->error = MMC_ERR_FAILED;
+ transfer_error = 1;
+ }
+ }
+
+ /*
+ * NOTE: On 1610 the END_OF_CMD may come too early when
+ * starting a write
+ */
+ if ((status & OMAP_MMC_STAT_END_OF_CMD) &&
+ (!(status & OMAP_MMC_STAT_A_EMPTY))) {
+ end_command = 1;
+ }
+ }
+
+ if (end_command) {
+ mmc_omap_cmd_done(host, host->cmd);
+ }
+ if (transfer_error)
+ mmc_omap_xfer_done(host, host->data);
+ else if (end_transfer)
+ mmc_omap_end_of_data(host, host->data);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mmc_omap_switch_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct mmc_omap_host *host = (struct mmc_omap_host *) dev_id;
+
+ schedule_work(&host->switch_work);
+
+ return IRQ_HANDLED;
+}
+
+static void mmc_omap_switch_timer(unsigned long arg)
+{
+ struct mmc_omap_host *host = (struct mmc_omap_host *) arg;
+
+ schedule_work(&host->switch_work);
+}
+
+/* FIXME: Handle card insertion and removal properly. Maybe use a mask
+ * for MMC state? */
+static void mmc_omap_switch_callback(unsigned long data, u8 mmc_mask)
+{
+}
+
+static void mmc_omap_switch_handler(void *data)
+{
+ struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+ struct mmc_card *card;
+ static int complained = 0;
+ int cards = 0, cover_open;
+
+ if (host->switch_pin == -1)
+ return;
+ cover_open = mmc_omap_cover_is_open(host);
+ if (cover_open != host->switch_last_state) {
+ kobject_uevent(&host->dev->kobj, KOBJ_CHANGE);
+ host->switch_last_state = cover_open;
+ }
+ mmc_detect_change(host->mmc, 0);
+ list_for_each_entry(card, &host->mmc->cards, node) {
+ if (mmc_card_present(card))
+ cards++;
+ }
+ if (mmc_omap_cover_is_open(host)) {
+ if (!complained) {
+ dev_info(mmc_dev(host->mmc), "cover is open");
+ complained = 1;
+ }
+ if (mmc_omap_enable_poll)
+ mod_timer(&host->switch_timer, jiffies +
+ msecs_to_jiffies(OMAP_MMC_SWITCH_POLL_DELAY));
+ } else {
+ complained = 0;
+ }
+}
+
+/* Prepare to transfer the next segment of a scatterlist */
+static void
+mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
+{
+ int dma_ch = host->dma_ch;
+ unsigned long data_addr;
+ u16 buf, frame;
+ u32 count;
+ struct scatterlist *sg = &data->sg[host->sg_idx];
+ int src_port = 0;
+ int dst_port = 0;
+ int sync_dev = 0;
+
+ data_addr = io_v2p((u32) host->base) + OMAP_MMC_REG_DATA;
+ frame = 1 << data->blksz_bits;
+ count = sg_dma_len(sg);
+
+ if ((data->blocks == 1) && (count > (1 << data->blksz_bits)))
+ count = frame;
+
+ host->dma_len = count;
+
+ /* FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx and 24xx.
+ * Use 16 or 32 word frames when the blocksize is at least that large.
+ * Blocksize is usually 512 bytes; but not for some SD reads.
+ */
+ if (cpu_is_omap15xx() && frame > 32)
+ frame = 32;
+ else if (frame > 64)
+ frame = 64;
+ count /= frame;
+ frame >>= 1;
+
+ if (!(data->flags & MMC_DATA_WRITE)) {
+ buf = 0x800f | ((frame - 1) << 8);
+
+ if (cpu_class_is_omap1()) {
+ src_port = OMAP_DMA_PORT_TIPB;
+ dst_port = OMAP_DMA_PORT_EMIFF;
+ }
+ if (cpu_is_omap24xx())
+ sync_dev = OMAP24XX_DMA_MMC1_RX;
+
+ omap_set_dma_src_params(dma_ch, src_port,
+ OMAP_DMA_AMODE_CONSTANT,
+ data_addr, 0, 0);
+ omap_set_dma_dest_params(dma_ch, dst_port,
+ OMAP_DMA_AMODE_POST_INC,
+ sg_dma_address(sg), 0, 0);
+ omap_set_dma_dest_data_pack(dma_ch, 1);
+ omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
+ } else {
+ buf = 0x0f80 | ((frame - 1) << 0);
+
+ if (cpu_class_is_omap1()) {
+ src_port = OMAP_DMA_PORT_EMIFF;
+ dst_port = OMAP_DMA_PORT_TIPB;
+ }
+ if (cpu_is_omap24xx())
+ sync_dev = OMAP24XX_DMA_MMC1_TX;
+
+ omap_set_dma_dest_params(dma_ch, dst_port,
+ OMAP_DMA_AMODE_CONSTANT,
+ data_addr, 0, 0);
+ omap_set_dma_src_params(dma_ch, src_port,
+ OMAP_DMA_AMODE_POST_INC,
+ sg_dma_address(sg), 0, 0);
+ omap_set_dma_src_data_pack(dma_ch, 1);
+ omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
+ }
+
+ /* Max limit for DMA frame count is 0xffff */
+ if (unlikely(count > 0xffff))
+ BUG();
+
+ OMAP_MMC_WRITE(host->base, BUF, buf);
+ omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16,
+ frame, count, OMAP_DMA_SYNC_FRAME,
+ sync_dev, 0);
+}
+
+/* A scatterlist segment completed */
+static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
+{
+ struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+ struct mmc_data *mmcdat = host->data;
+
+ if (unlikely(host->dma_ch < 0)) {
+ dev_err(mmc_dev(host->mmc), "DMA callback while DMA not
+ enabled\n");
+ return;
+ }
+ /* FIXME: We really should do something to _handle_ the errors */
+ if (ch_status & OMAP_DMA_TOUT_IRQ) {
+ dev_err(mmc_dev(host->mmc),"DMA timeout\n");
+ return;
+ }
+ if (ch_status & OMAP_DMA_DROP_IRQ) {
+ dev_err(mmc_dev(host->mmc), "DMA sync error\n");
+ return;
+ }
+ if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) {
+ return;
+ }
+ mmcdat->bytes_xfered += host->dma_len;
+ host->sg_idx++;
+ if (host->sg_idx < host->sg_len) {
+ mmc_omap_prepare_dma(host, host->data);
+ omap_start_dma(host->dma_ch);
+ } else
+ mmc_omap_dma_done(host, host->data);
+}
+
+static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data *data)
+{
+ const char *dev_name;
+ int sync_dev, dma_ch, is_read, r;
+
+ is_read = !(data->flags & MMC_DATA_WRITE);
+ del_timer_sync(&host->dma_timer);
+ if (host->dma_ch >= 0) {
+ if (is_read == host->dma_is_read)
+ return 0;
+ omap_free_dma(host->dma_ch);
+ host->dma_ch = -1;
+ }
+
+ if (is_read) {
+ if (host->id == 1) {
+ sync_dev = OMAP_DMA_MMC_RX;
+ dev_name = "MMC1 read";
+ } else {
+ sync_dev = OMAP_DMA_MMC2_RX;
+ dev_name = "MMC2 read";
+ }
+ } else {
+ if (host->id == 1) {
+ sync_dev = OMAP_DMA_MMC_TX;
+ dev_name = "MMC1 write";
+ } else {
+ sync_dev = OMAP_DMA_MMC2_TX;
+ dev_name = "MMC2 write";
+ }
+ }
+ r = omap_request_dma(sync_dev, dev_name, mmc_omap_dma_cb,
+ host, &dma_ch);
+ if (r != 0) {
+ dev_dbg(mmc_dev(host->mmc), "omap_request_dma() failed with %d\n", r);
+ return r;
+ }
+ host->dma_ch = dma_ch;
+ host->dma_is_read = is_read;
+
+ return 0;
+}
+
+static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req)
+{
+ u16 reg;
+
+ reg = OMAP_MMC_READ(host->base, SDIO);
+ reg &= ~(1 << 5);
+ OMAP_MMC_WRITE(host->base, SDIO, reg);
+ /* Set maximum timeout */
+ OMAP_MMC_WRITE(host->base, CTO, 0xff);
+}
+
+static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req)
+{
+ int timeout;
+ u16 reg;
+
+ /* Convert ns to clock cycles by assuming 20MHz frequency
+ * 1 cycle at 20MHz = 500 ns
+ */
+ timeout = req->data->timeout_clks + req->data->timeout_ns / 500;
+
+ /* Check if we need to use timeout multiplier register */
+ reg = OMAP_MMC_READ(host->base, SDIO);
+ if (timeout > 0xffff) {
+ reg |= (1 << 5);
+ timeout /= 1024;
+ } else
+ reg &= ~(1 << 5);
+ OMAP_MMC_WRITE(host->base, SDIO, reg);
+ OMAP_MMC_WRITE(host->base, DTO, timeout);
+}
+
+static void
+mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
+{
+ struct mmc_data *data = req->data;
+ int i, use_dma, block_size;
+ unsigned sg_len;
+
+ host->data = data;
+ if (data == NULL) {
+ OMAP_MMC_WRITE(host->base, BLEN, 0);
+ OMAP_MMC_WRITE(host->base, NBLK, 0);
+ OMAP_MMC_WRITE(host->base, BUF, 0);
+ host->dma_in_use = 0;
+ set_cmd_timeout(host, req);
+ return;
+ }
+
+
+ block_size = 1 << data->blksz_bits;
+
+ OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1);
+ OMAP_MMC_WRITE(host->base, BLEN, block_size - 1);
+ set_data_timeout(host, req);
+
+ /* cope with calling layer confusion; it issues "single
+ * block" writes using multi-block scatterlists.
+ */
+ sg_len = (data->blocks == 1) ? 1 : data->sg_len;
+
+ /* Only do DMA for entire blocks */
+ use_dma = host->use_dma;
+ if (use_dma) {
+ for (i = 0; i < sg_len; i++) {
+ if ((data->sg[i].length % block_size) != 0) {
+ use_dma = 0;
+ break;
+ }
+ }
+ }
+
+ host->sg_idx = 0;
+ if (use_dma) {
+ if (mmc_omap_get_dma_channel(host, data) == 0) {
+ enum dma_data_direction dma_data_dir;
+
+ if (data->flags & MMC_DATA_WRITE)
+ dma_data_dir = DMA_TO_DEVICE;
+ else
+ dma_data_dir = DMA_FROM_DEVICE;
+
+ host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
+ sg_len, dma_data_dir);
+ host->total_bytes_left = 0;
+ mmc_omap_prepare_dma(host, req->data);
+ host->brs_received = 0;
+ host->dma_done = 0;
+ host->dma_in_use = 1;
+ } else
+ use_dma = 0;
+ }
+
+ /* Revert to PIO? */
+ if (!use_dma) {
+ OMAP_MMC_WRITE(host->base, BUF, 0x1f1f);
+ host->total_bytes_left = data->blocks * block_size;
+ host->sg_len = sg_len;
+ mmc_omap_sg_to_buf(host);
+ host->dma_in_use = 0;
+ }
+}
+
+static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+ struct mmc_omap_host *host = mmc_priv(mmc);
+
+ WARN_ON(host->mrq != NULL);
+
+ host->mrq = req;
+
+ /* only touch fifo AFTER the controller readies it */
+ mmc_omap_prepare_data(host, req);
+ mmc_omap_start_command(host, req->cmd);
+ if (host->dma_in_use)
+ omap_start_dma(host->dma_ch);
+}
+
+static void innovator_fpga_socket_power(int on)
+{
+#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
+
+ if (on) {
+ fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
+ OMAP1510_FPGA_POWER);
+ } else {
+ fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3),
+ OMAP1510_FPGA_POWER);
+ }
+#endif
+}
+
+/*
+ * Turn the socket power on/off. Innovator uses FPGA, most boards
+ * probably use GPIO.
+ */
+static void mmc_omap_power(struct mmc_omap_host *host, int on)
+{
+ if (on) {
+ if (machine_is_omap_innovator())
+ innovator_fpga_socket_power(1);
+ else if (machine_is_omap_h2())
+ tps65010_set_gpio_out_value(GPIO3, HIGH);
+ else if (machine_is_omap_h3())
+ /* GPIO 4 of TPS65010 sends SD_EN signal */
+ tps65010_set_gpio_out_value(GPIO4, HIGH);
+ else if (cpu_is_omap24xx()) {
+ u16 reg = OMAP_MMC_READ(host->base, CON);
+ OMAP_MMC_WRITE(host->base, CON, reg | (1 << 11));
+ } else
+ if (host->power_pin >= 0)
+ omap_set_gpio_dataout(host->power_pin, 1);
+ } else {
+ if (machine_is_omap_innovator())
+ innovator_fpga_socket_power(0);
+ else if (machine_is_omap_h2())
+ tps65010_set_gpio_out_value(GPIO3, LOW);
+ else if (machine_is_omap_h3())
+ tps65010_set_gpio_out_value(GPIO4, LOW);
+ else if (cpu_is_omap24xx()) {
+ u16 reg = OMAP_MMC_READ(host->base, CON);
+ OMAP_MMC_WRITE(host->base, CON, reg & ~(1 << 11));
+ } else
+ if (host->power_pin >= 0)
+ omap_set_gpio_dataout(host->power_pin, 0);
+ }
+}
+
+static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct mmc_omap_host *host = mmc_priv(mmc);
+ int dsor;
+ int realclock, i;
+
+ realclock = ios->clock;
+
+ if (ios->clock == 0)
+ dsor = 0;
+ else {
+ int func_clk_rate = clk_get_rate(host->fclk);
+
+ dsor = func_clk_rate / realclock;
+ if (dsor < 1)
+ dsor = 1;
+
+ if (func_clk_rate / dsor > realclock)
+ dsor++;
+
+ if (dsor > 250)
+ dsor = 250;
+ dsor++;
+
+ if (ios->bus_width == MMC_BUS_WIDTH_4)
+ dsor |= 1 << 15;
+ }
+
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF:
+ mmc_omap_power(host, 0);
+ break;
+ case MMC_POWER_UP:
+ case MMC_POWER_ON:
+ mmc_omap_power(host, 1);
+ dsor |= 1<<11;
+ break;
+ }
+
+ host->bus_mode = ios->bus_mode;
+ host->hw_bus_mode = host->bus_mode;
+
+ clk_enable(host->fclk);
+
+ /* On insanely high arm_per frequencies something sometimes
+ * goes somehow out of sync, and the POW bit is not being set,
+ * which results in the while loop below getting stuck.
+ * Writing to the CON register twice seems to do the trick. */
+ for (i = 0; i < 2; i++)
+ OMAP_MMC_WRITE(host->base, CON, dsor);
+ if (ios->power_mode == MMC_POWER_UP) {
+ /* Send clock cycles, poll completion */
+ OMAP_MMC_WRITE(host->base, IE, 0);
+ OMAP_MMC_WRITE(host->base, STAT, 0xffff);
+ OMAP_MMC_WRITE(host->base, CMD, 1<<7);
+ while (0 == (OMAP_MMC_READ(host->base, STAT) & 1));
+ OMAP_MMC_WRITE(host->base, STAT, 1);
+ }
+ clk_disable(host->fclk);
+}
+
+static int mmc_omap_get_ro(struct mmc_host *mmc)
+{
+ struct mmc_omap_host *host = mmc_priv(mmc);
+
+ return host->wp_pin && omap_get_gpio_datain(host->wp_pin);
+}
+
+static struct mmc_host_ops mmc_omap_ops = {
+ .request = mmc_omap_request,
+ .set_ios = mmc_omap_set_ios,
+ .get_ro = mmc_omap_get_ro,
+};
+
+static int __init mmc_omap_probe(struct platform_device *pdev)
+{
+ struct omap_mmc_conf *minfo = pdev->dev.platform_data;
+ struct mmc_host *mmc;
+ struct mmc_omap_host *host = NULL;
+ int ret = 0;
+
+ if (platform_get_resource(pdev, IORESOURCE_MEM, 0) ||
+ platform_get_irq(pdev, IORESOURCE_IRQ, 0)) {
+ dev_err(&pdev->dev, "mmc_omap_probe: invalid resource type\n");
+ return -ENODEV;
+ }
+
+ if (!request_mem_region(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start + 1,
+ pdev->name)) {
+ dev_dbg(&pdev->dev, "request_mem_region failed\n");
+ return -EBUSY;
+ }
+
+ mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
+ if (!mmc) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
+
+ spin_lock_init(&host->dma_lock);
+ init_timer(&host->dma_timer);
+ host->dma_timer.function = mmc_omap_dma_timer;
+ host->dma_timer.data = (unsigned long) host;
+
+ host->id = pdev->id;
+
+ if (cpu_is_omap24xx()) {
+ host->iclk = clk_get(&pdev->dev, "mmc_ick");
+ if (IS_ERR(host->iclk))
+ goto out;
+ clk_enable(host->iclk);
+ }
+
+ if (!cpu_is_omap24xx())
+ host->fclk = clk_get(&pdev->dev, "mmc_ck");
+ else
+ host->fclk = clk_get(&pdev->dev, "mmc_fck");
+
+ if (IS_ERR(host->fclk)) {
+ ret = PTR_ERR(host->fclk);
+ goto out;
+ }
+
+ /* REVISIT:
+ * Also, use minfo->cover to decide how to manage
+ * the card detect sensing.
+ */
+ host->power_pin = minfo->power_pin;
+ host->switch_pin = minfo->switch_pin;
+ host->wp_pin = minfo->wp_pin;
+ host->use_dma = 1;
+ host->dma_ch = -1;
+
+ host->irq = pdev->resource[1].start;
+ host->base = ioremap(pdev->res.start, SZ_4K);
+ if (!host->base) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (minfo->wire4)
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+ mmc->ops = &mmc_omap_ops;
+ mmc->f_min = 400000;
+ mmc->f_max = 24000000;
+ mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+
+ /* Use scatterlist DMA to reduce per-transfer costs.
+ * NOTE max_seg_size assumption that small blocks aren't
+ * normally used (except e.g. for reading SD registers).
+ */
+ mmc->max_phys_segs = 32;
+ mmc->max_hw_segs = 32;
+ mmc->max_sectors = 256; /* NBLK max 11-bits, OMAP also limited by DMA */
+ mmc->max_seg_size = mmc->max_sectors * 512;
+
+ if (host->power_pin >= 0) {
+ if ((ret = omap_request_gpio(host->power_pin)) != 0) {
+ dev_err(mmc_dev(host->mmc), "Unable to get GPIO
+ pin for MMC power\n");
+ goto out;
+ }
+ omap_set_gpio_direction(host->power_pin, 0);
+ }
+
+ ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host);
+ if (ret)
+ goto out;
+
+ host->dev = &pdev->dev;
+ platform_set_drvdata(pdev, host);
+
+ mmc_add_host(mmc);
+
+ if (host->switch_pin >= 0) {
+ INIT_WORK(&host->switch_work, mmc_omap_switch_handler, host);
+ init_timer(&host->switch_timer);
+ host->switch_timer.function = mmc_omap_switch_timer;
+ host->switch_timer.data = (unsigned long) host;
+ if (omap_request_gpio(host->switch_pin) != 0) {
+ dev_warn(mmc_dev(host->mmc), "Unable to get GPIO pin for MMC cover switch\n");
+ host->switch_pin = -1;
+ goto no_switch;
+ }
+
+ omap_set_gpio_direction(host->switch_pin, 1);
+ ret = request_irq(OMAP_GPIO_IRQ(host->switch_pin),
+ mmc_omap_switch_irq, SA_TRIGGER_RISING, DRIVER_NAME, host);
+ if (ret) {
+ dev_warn(mmc_dev(host->mmc), "Unable to get IRQ for MMC cover switch\n");
+ omap_free_gpio(host->switch_pin);
+ host->switch_pin = -1;
+ goto no_switch;
+ }
+ ret = device_create_file(&pdev->dev, &dev_attr_cover_switch);
+ if (ret == 0) {
+ ret = device_create_file(&pdev->dev, &dev_attr_enable_poll);
+ if (ret != 0)
+ device_remove_file(&pdev->dev, &dev_attr_cover_switch);
+ }
+ if (ret) {
+ dev_wan(mmc_dev(host->mmc), "Unable to create sysfs attributes\n");
+ free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+ omap_free_gpio(host->switch_pin);
+ host->switch_pin = -1;
+ goto no_switch;
+ }
+ if (mmc_omap_enable_poll && mmc_omap_cover_is_open(host))
+ schedule_work(&host->switch_work);
+ }
+
+no_switch:
+ return 0;
+
+out:
+ /* FIXME: Free other resources too. */
+ if (host) {
+ if (host->iclk && !IS_ERR(host->iclk))
+ clk_put(host->iclk);
+ if (host->fclk && !IS_ERR(host->fclk))
+ clk_put(host->fclk);
+ mmc_free_host(host->mmc);
+ }
+ return ret;
+}
+
+static int mmc_omap_remove(struct platform_device *pdev)
+{
+ struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ if (host) {
+ mmc_remove_host(host->mmc);
+ free_irq(host->irq, host);
+
+ if (host->power_pin >= 0)
+ omap_free_gpio(host->power_pin);
+ if (host->switch_pin >= 0) {
+ device_remove_file(&pdev->dev, &dev_attr_enable_poll);
+ device_remove_file(&pdev->dev, &dev_attr_cover_switch);
+ free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+ omap_free_gpio(host->switch_pin);
+ host->switch_pin = -1;
+ del_timer_sync(&host->switch_timer);
+ flush_scheduled_work();
+ }
+ if (host->iclk && !IS_ERR(host->iclk))
+ clk_put(host->iclk);
+ if (host->fclk && !IS_ERR(host->fclk))
+ clk_put(host->fclk);
+ mmc_free_host(host->mmc);
+ }
+
+ release_mem_region(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start + 1);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int mmc_omap_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ int ret = 0;
+ struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+ if (host && host->suspended)
+ return 0;
+
+ if (host) {
+ ret = mmc_suspend_host(host->mmc, mesg);
+ if (ret == 0)
+ host->suspended = 1;
+ }
+ return ret;
+}
+
+static int mmc_omap_resume(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+ if (host && !host->suspended)
+ return 0;
+
+ if (host) {
+ ret = mmc_resume_host(host->mmc);
+ if (ret == 0)
+ host->suspended = 0;
+ }
+
+ return ret;
+}
+#else
+#define mmc_omap_suspend NULL
+#define mmc_omap_resume NULL
+#endif
+
+static struct platform_driver mmc_omap_driver = {
+ .probe = mmc_omap_probe,
+ .remove = mmc_omap_remove,
+ .suspend = mmc_omap_suspend,
+ .resume = mmc_omap_resume,
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+};
+
+static int __init mmc_omap_init(void)
+{
+ return platform_driver_register(&mmc_omap_driver);
+}
+
+static void __exit mmc_omap_exit(void)
+{
+ platform_driver_unregister(&mmc_omap_driver);
+}
+
+module_init(mmc_omap_init);
+module_exit(mmc_omap_exit);
+
+MODULE_DESCRIPTION("OMAP Multimedia Card driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS(DRIVER_NAME);
+MODULE_AUTHOR("Juha Yrjölä");
diff --git a/drivers/mmc/omap.h b/drivers/mmc/omap.h
new file mode 100644
index 00000000000..c954d355a5e
--- /dev/null
+++ b/drivers/mmc/omap.h
@@ -0,0 +1,55 @@
+#ifndef DRIVERS_MEDIA_MMC_OMAP_H
+#define DRIVERS_MEDIA_MMC_OMAP_H
+
+#define OMAP_MMC_REG_CMD 0x00
+#define OMAP_MMC_REG_ARGL 0x04
+#define OMAP_MMC_REG_ARGH 0x08
+#define OMAP_MMC_REG_CON 0x0c
+#define OMAP_MMC_REG_STAT 0x10
+#define OMAP_MMC_REG_IE 0x14
+#define OMAP_MMC_REG_CTO 0x18
+#define OMAP_MMC_REG_DTO 0x1c
+#define OMAP_MMC_REG_DATA 0x20
+#define OMAP_MMC_REG_BLEN 0x24
+#define OMAP_MMC_REG_NBLK 0x28
+#define OMAP_MMC_REG_BUF 0x2c
+#define OMAP_MMC_REG_SDIO 0x34
+#define OMAP_MMC_REG_REV 0x3c
+#define OMAP_MMC_REG_RSP0 0x40
+#define OMAP_MMC_REG_RSP1 0x44
+#define OMAP_MMC_REG_RSP2 0x48
+#define OMAP_MMC_REG_RSP3 0x4c
+#define OMAP_MMC_REG_RSP4 0x50
+#define OMAP_MMC_REG_RSP5 0x54
+#define OMAP_MMC_REG_RSP6 0x58
+#define OMAP_MMC_REG_RSP7 0x5c
+#define OMAP_MMC_REG_IOSR 0x60
+#define OMAP_MMC_REG_SYSC 0x64
+#define OMAP_MMC_REG_SYSS 0x68
+
+#define OMAP_MMC_STAT_CARD_ERR (1 << 14)
+#define OMAP_MMC_STAT_CARD_IRQ (1 << 13)
+#define OMAP_MMC_STAT_OCR_BUSY (1 << 12)
+#define OMAP_MMC_STAT_A_EMPTY (1 << 11)
+#define OMAP_MMC_STAT_A_FULL (1 << 10)
+#define OMAP_MMC_STAT_CMD_CRC (1 << 8)
+#define OMAP_MMC_STAT_CMD_TOUT (1 << 7)
+#define OMAP_MMC_STAT_DATA_CRC (1 << 6)
+#define OMAP_MMC_STAT_DATA_TOUT (1 << 5)
+#define OMAP_MMC_STAT_END_BUSY (1 << 4)
+#define OMAP_MMC_STAT_END_OF_DATA (1 << 3)
+#define OMAP_MMC_STAT_CARD_BUSY (1 << 2)
+#define OMAP_MMC_STAT_END_OF_CMD (1 << 0)
+
+#define OMAP_MMC_READ(base, reg) __raw_readw((base) + OMAP_MMC_REG_##reg)
+#define OMAP_MMC_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MMC_REG_##reg)
+
+/*
+ * Command types
+ */
+#define OMAP_MMC_CMDTYPE_BC 0
+#define OMAP_MMC_CMDTYPE_BCR 1
+#define OMAP_MMC_CMDTYPE_AC 2
+#define OMAP_MMC_CMDTYPE_ADTC 3
+
+#endif
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index c32fad1ce51..b49368fd96b 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -37,12 +37,6 @@
#include "pxamci.h"
-#ifdef CONFIG_MMC_DEBUG
-#define DBG(x...) printk(KERN_DEBUG x)
-#else
-#define DBG(x...) do { } while (0)
-#endif
-
#define DRIVER_NAME "pxa2xx-mci"
#define NR_SG 1
@@ -71,11 +65,6 @@ struct pxamci_host {
unsigned int dma_dir;
};
-static inline unsigned int ns_to_clocks(unsigned int ns)
-{
- return (ns * (CLOCKRATE / 1000000) + 999) / 1000;
-}
-
static void pxamci_stop_clock(struct pxamci_host *host)
{
if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
@@ -119,6 +108,7 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)
static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
{
unsigned int nob = data->blocks;
+ unsigned long long clks;
unsigned int timeout;
u32 dcmd;
int i;
@@ -129,9 +119,11 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
nob = 0xffff;
writel(nob, host->base + MMC_NOB);
- writel(1 << data->blksz_bits, host->base + MMC_BLKLEN);
+ writel(data->blksz, host->base + MMC_BLKLEN);
- timeout = ns_to_clocks(data->timeout_ns) + data->timeout_clks;
+ clks = (unsigned long long)data->timeout_ns * CLOCKRATE;
+ do_div(clks, 1000000000UL);
+ timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt);
writel((timeout + 255) / 256, host->base + MMC_RDTO);
if (data->flags & MMC_DATA_READ) {
@@ -206,7 +198,6 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd,
static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq)
{
- DBG("PXAMCI: request done\n");
host->mrq = NULL;
host->cmd = NULL;
host->data = NULL;
@@ -252,7 +243,7 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)
if ((cmd->resp[0] & 0x80000000) == 0)
cmd->error = MMC_ERR_BADCRC;
} else {
- DBG("ignoring CRC from command %d - *risky*\n",cmd->opcode);
+ pr_debug("ignoring CRC from command %d - *risky*\n",cmd->opcode);
}
#else
cmd->error = MMC_ERR_BADCRC;
@@ -292,14 +283,14 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
* data blocks as being in error.
*/
if (data->error == MMC_ERR_NONE)
- data->bytes_xfered = data->blocks << data->blksz_bits;
+ data->bytes_xfered = data->blocks * data->blksz;
else
data->bytes_xfered = 0;
pxamci_disable_irq(host, DATA_TRAN_DONE);
host->data = NULL;
- if (host->mrq->stop && data->error == MMC_ERR_NONE) {
+ if (host->mrq->stop) {
pxamci_stop_clock(host);
pxamci_start_cmd(host, host->mrq->stop, 0);
} else {
@@ -317,12 +308,10 @@ static irqreturn_t pxamci_irq(int irq, void *devid, struct pt_regs *regs)
ireg = readl(host->base + MMC_I_REG);
- DBG("PXAMCI: irq %08x\n", ireg);
-
if (ireg) {
unsigned stat = readl(host->base + MMC_STAT);
- DBG("PXAMCI: stat %08x\n", stat);
+ pr_debug("PXAMCI: irq %08x stat %08x\n", ireg, stat);
if (ireg & END_CMD_RES)
handled |= pxamci_cmd_done(host, stat);
@@ -376,10 +365,6 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct pxamci_host *host = mmc_priv(mmc);
- DBG("pxamci_set_ios: clock %u power %u vdd %u.%02u\n",
- ios->clock, ios->power_mode, ios->vdd / 100,
- ios->vdd % 100);
-
if (ios->clock) {
unsigned int clk = CLOCKRATE / ios->clock;
if (CLOCKRATE / clk > ios->clock)
@@ -405,8 +390,8 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->cmdat |= CMDAT_INIT;
}
- DBG("pxamci_set_ios: clkrt = %x cmdat = %x\n",
- host->clkrt, host->cmdat);
+ pr_debug("PXAMCI: clkrt = %x cmdat = %x\n",
+ host->clkrt, host->cmdat);
}
static struct mmc_host_ops pxamci_ops = {
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 8b811d94371..b0053280ff2 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -31,12 +31,8 @@
#define BUGMAIL "<sdhci-devel@list.drzeus.cx>"
-#ifdef CONFIG_MMC_DEBUG
#define DBG(f, x...) \
- printk(KERN_DEBUG DRIVER_NAME " [%s()]: " f, __func__,## x)
-#else
-#define DBG(f, x...) do { } while (0)
-#endif
+ pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
static const struct pci_device_id pci_ids[] __devinitdata = {
/* handle any SD host controller */
@@ -574,10 +570,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
spin_lock_irqsave(&host->lock, flags);
- DBG("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
- ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
- ios->vdd, ios->bus_width);
-
/*
* Reset the chip on each power off.
* Should clear out any weird states.
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 3be397d436f..8167332d401 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -44,15 +44,10 @@
#define DRIVER_NAME "wbsd"
#define DRIVER_VERSION "1.5"
-#ifdef CONFIG_MMC_DEBUG
#define DBG(x...) \
- printk(KERN_DEBUG DRIVER_NAME ": " x)
+ pr_debug(DRIVER_NAME ": " x)
#define DBGF(f, x...) \
- printk(KERN_DEBUG DRIVER_NAME " [%s()]: " f, __func__ , ##x)
-#else
-#define DBG(x...) do { } while (0)
-#define DBGF(x...) do { } while (0)
-#endif
+ pr_debug(DRIVER_NAME " [%s()]: " f, __func__ , ##x)
/*
* Device resources
@@ -667,14 +662,14 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
unsigned long dmaflags;
DBGF("blksz %04x blks %04x flags %08x\n",
- 1 << data->blksz_bits, data->blocks, data->flags);
+ data->blksz, data->blocks, data->flags);
DBGF("tsac %d ms nsac %d clk\n",
data->timeout_ns / 1000000, data->timeout_clks);
/*
* Calculate size.
*/
- host->size = data->blocks << data->blksz_bits;
+ host->size = data->blocks * data->blksz;
/*
* Check timeout values for overflow.
@@ -701,12 +696,12 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
* Two bytes are needed for each data line.
*/
if (host->bus_width == MMC_BUS_WIDTH_1) {
- blksize = (1 << data->blksz_bits) + 2;
+ blksize = data->blksz + 2;
wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
} else if (host->bus_width == MMC_BUS_WIDTH_4) {
- blksize = (1 << data->blksz_bits) + 2 * 4;
+ blksize = data->blksz + 2 * 4;
wbsd_write_index(host, WBSD_IDX_PBSMSB,
((blksize >> 4) & 0xF0) | WBSD_DATA_WIDTH);
@@ -936,10 +931,6 @@ static void wbsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct wbsd_host *host = mmc_priv(mmc);
u8 clk, setup, pwr;
- DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
- ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
- ios->vdd, ios->bus_width);
-
spin_lock_bh(&host->lock);
/*
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index 0f6bb2e625d..a7ec5954caf 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -200,27 +200,6 @@ config MTD_CFI_AMDSTD
provides support for one of those command sets, used on chips
including the AMD Am29LV320.
-config MTD_CFI_AMDSTD_RETRY
- int "Retry failed commands (erase/program)"
- depends on MTD_CFI_AMDSTD
- default "0"
- help
- Some chips, when attached to a shared bus, don't properly filter
- bus traffic that is destined to other devices. This broken
- behavior causes erase and program sequences to be aborted when
- the sequences are mixed with traffic for other devices.
-
- SST49LF040 (and related) chips are know to be broken.
-
-config MTD_CFI_AMDSTD_RETRY_MAX
- int "Max retries of failed commands (erase/program)"
- depends on MTD_CFI_AMDSTD_RETRY
- default "0"
- help
- If you have an SST49LF040 (or related chip) then this value should
- be set to at least 1. This can also be adjusted at driver load
- time with the retry_cmd_max module parameter.
-
config MTD_CFI_STAA
tristate "Support for ST (Advanced Architecture) flash chips"
depends on MTD_GEN_PROBE
diff --git a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c
index fdb91b6f1d9..57115618c49 100644
--- a/drivers/mtd/chips/amd_flash.c
+++ b/drivers/mtd/chips/amd_flash.c
@@ -664,7 +664,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map)
printk("%s: Probing for AMD compatible flash...\n", map->name);
if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table,
- sizeof(table)/sizeof(table[0])))
+ ARRAY_SIZE(table)))
== -1) {
printk(KERN_WARNING
"%s: Found no AMD compatible device at location zero\n",
@@ -696,7 +696,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map)
base += (1 << temp.chipshift)) {
int numchips = temp.numchips;
table_pos[numchips] = probe_new_chip(mtd, base, chips,
- &temp, table, sizeof(table)/sizeof(table[0]));
+ &temp, table, ARRAY_SIZE(table));
}
mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) *
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index edb306c03c0..517ea33e726 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -34,6 +34,7 @@
#define MANUFACTURER_MACRONIX 0x00C2
#define MANUFACTURER_NEC 0x0010
#define MANUFACTURER_PMC 0x009D
+#define MANUFACTURER_SHARP 0x00b0
#define MANUFACTURER_SST 0x00BF
#define MANUFACTURER_ST 0x0020
#define MANUFACTURER_TOSHIBA 0x0098
@@ -124,6 +125,9 @@
#define PM49FL004 0x006E
#define PM49FL008 0x006A
+/* Sharp */
+#define LH28F640BF 0x00b0
+
/* ST - www.st.com */
#define M29W800DT 0x00D7
#define M29W800DB 0x005B
@@ -1267,6 +1271,19 @@ static const struct amd_flash_info jedec_table[] = {
.regions = {
ERASEINFO( 0x01000, 256 )
}
+ }, {
+ .mfr_id = MANUFACTURER_SHARP,
+ .dev_id = LH28F640BF,
+ .name = "LH28F640BF",
+ .uaddr = {
+ [0] = MTD_UADDR_UNNECESSARY, /* x8 */
+ },
+ .DevSize = SIZE_4MiB,
+ .CmdSet = P_ID_INTEL_STD,
+ .NumEraseRegions= 1,
+ .regions = {
+ ERASEINFO(0x40000,16),
+ }
}, {
.mfr_id = MANUFACTURER_SST,
.dev_id = SST39LF512,
@@ -2035,7 +2052,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
DEBUG(MTD_DEBUG_LEVEL3,
"Search for id:(%02x %02x) interleave(%d) type(%d)\n",
cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type);
- for (i=0; i<sizeof(jedec_table)/sizeof(jedec_table[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) {
DEBUG( MTD_DEBUG_LEVEL3,
"MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
index 36f61a6a766..3cc0b23c586 100644
--- a/drivers/mtd/chips/sharp.c
+++ b/drivers/mtd/chips/sharp.c
@@ -64,7 +64,7 @@
#undef AUTOUNLOCK /* automatically unlocks blocks before erasing */
-struct mtd_info *sharp_probe(struct map_info *);
+static struct mtd_info *sharp_probe(struct map_info *);
static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd);
@@ -96,7 +96,6 @@ struct sharp_info{
struct flchip chips[1];
};
-struct mtd_info *sharp_probe(struct map_info *map);
static void sharp_destroy(struct mtd_info *mtd);
static struct mtd_chip_driver sharp_chipdrv = {
@@ -107,7 +106,7 @@ static struct mtd_chip_driver sharp_chipdrv = {
};
-struct mtd_info *sharp_probe(struct map_info *map)
+static struct mtd_info *sharp_probe(struct map_info *map)
{
struct mtd_info *mtd = NULL;
struct sharp_info *sharp = NULL;
@@ -581,7 +580,7 @@ static void sharp_destroy(struct mtd_info *mtd)
}
-int __init sharp_probe_init(void)
+static int __init sharp_probe_init(void)
{
printk("MTD Sharp chip driver <ds@lineo.com>\n");
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index 6b8bb2e4dcf..a7a7bfe3387 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -42,7 +42,8 @@
/* special size referring to all the remaining space in a partition */
-#define SIZE_REMAINING 0xffffffff
+#define SIZE_REMAINING UINT_MAX
+#define OFFSET_CONTINUOUS UINT_MAX
struct cmdline_mtd_partition {
struct cmdline_mtd_partition *next;
@@ -75,7 +76,7 @@ static struct mtd_partition * newpart(char *s,
{
struct mtd_partition *parts;
unsigned long size;
- unsigned long offset = 0;
+ unsigned long offset = OFFSET_CONTINUOUS;
char *name;
int name_len;
unsigned char *extra_mem;
@@ -314,7 +315,7 @@ static int parse_cmdline_partitions(struct mtd_info *master,
{
for(i = 0, offset = 0; i < part->num_parts; i++)
{
- if (!part->parts[i].offset)
+ if (part->parts[i].offset == OFFSET_CONTINUOUS)
part->parts[i].offset = offset;
else
offset = part->parts[i].offset;
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index dd628cb51e3..7fac438b5c3 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -129,8 +129,8 @@ config MTDRAM_ABS_POS
allocating space from Linux's available memory. Otherwise, leave
this set to zero. Most people will want to leave this as zero.
-config MTD_BLKMTD
- tristate "MTD emulation using block device"
+config MTD_BLOCK2MTD
+ tristate "MTD using block device"
depends on MTD
help
This driver allows a block device to appear as an MTD. It would
@@ -141,15 +141,6 @@ config MTD_BLKMTD
Testing MTD users (eg JFFS2) on large media and media that might
be removed during a write (using the floppy drive).
-config MTD_BLOCK2MTD
- tristate "MTD using block device (rewrite)"
- depends on MTD && EXPERIMENTAL
- help
- This driver is basically the same at MTD_BLKMTD above, but
- experienced some interface changes plus serious speedups. In
- the long term, it should replace MTD_BLKMTD. Right now, you
- shouldn't entrust important data to it yet.
-
comment "Disk-On-Chip Device Drivers"
config MTD_DOC2000
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 7c5ed217838..b6573670316 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_MTD_PMC551) += pmc551.o
obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o
obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
obj-$(CONFIG_MTD_LART) += lart.o
-obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
obj-$(CONFIG_MTD_M25P80) += m25p80.o
diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
deleted file mode 100644
index 04f864d238d..00000000000
--- a/drivers/mtd/devices/blkmtd.c
+++ /dev/null
@@ -1,820 +0,0 @@
-/*
- * $Id: blkmtd.c,v 1.27 2005/11/07 11:14:24 gleixner Exp $
- *
- * blkmtd.c - use a block device as a fake MTD
- *
- * Author: Simon Evans <spse@secret.org.uk>
- *
- * Copyright (C) 2001,2002 Simon Evans
- *
- * Licence: GPL
- *
- * How it works:
- * The driver uses raw/io to read/write the device and the page
- * cache to cache access. Writes update the page cache with the
- * new data and mark it dirty and add the page into a BIO which
- * is then written out.
- *
- * It can be loaded Read-Only to prevent erases and writes to the
- * medium.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/blkdev.h>
-#include <linux/bio.h>
-#include <linux/pagemap.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/mtd/mtd.h>
-
-
-#define err(format, arg...) printk(KERN_ERR "blkmtd: " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO "blkmtd: " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "blkmtd: " format "\n" , ## arg)
-#define crit(format, arg...) printk(KERN_CRIT "blkmtd: " format "\n" , ## arg)
-
-
-/* Default erase size in K, always make it a multiple of PAGE_SIZE */
-#define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */
-#define VERSION "$Revision: 1.27 $"
-
-/* Info for the block device */
-struct blkmtd_dev {
- struct list_head list;
- struct block_device *blkdev;
- struct mtd_info mtd_info;
- struct semaphore wrbuf_mutex;
-};
-
-
-/* Static info about the MTD, used in cleanup_module */
-static LIST_HEAD(blkmtd_device_list);
-
-
-static void blkmtd_sync(struct mtd_info *mtd);
-
-#define MAX_DEVICES 4
-
-/* Module parameters passed by insmod/modprobe */
-static char *device[MAX_DEVICES]; /* the block device to use */
-static int erasesz[MAX_DEVICES]; /* optional default erase size */
-static int ro[MAX_DEVICES]; /* optional read only flag */
-static int sync;
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
-MODULE_DESCRIPTION("Emulate an MTD using a block device");
-module_param_array(device, charp, NULL, 0);
-MODULE_PARM_DESC(device, "block device to use");
-module_param_array(erasesz, int, NULL, 0);
-MODULE_PARM_DESC(erasesz, "optional erase size to use in KiB. eg 4=4KiB.");
-module_param_array(ro, bool, NULL, 0);
-MODULE_PARM_DESC(ro, "1=Read only, writes and erases cause errors");
-module_param(sync, bool, 0);
-MODULE_PARM_DESC(sync, "1=Synchronous writes");
-
-
-/* completion handler for BIO reads */
-static int bi_read_complete(struct bio *bio, unsigned int bytes_done, int error)
-{
- if (bio->bi_size)
- return 1;
-
- complete((struct completion*)bio->bi_private);
- return 0;
-}
-
-
-/* completion handler for BIO writes */
-static int bi_write_complete(struct bio *bio, unsigned int bytes_done, int error)
-{
- const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
- struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
-
- if (bio->bi_size)
- return 1;
-
- if(!uptodate)
- err("bi_write_complete: not uptodate\n");
-
- do {
- struct page *page = bvec->bv_page;
- DEBUG(3, "Cleaning up page %ld\n", page->index);
- if (--bvec >= bio->bi_io_vec)
- prefetchw(&bvec->bv_page->flags);
-
- if (uptodate) {
- SetPageUptodate(page);
- } else {
- ClearPageUptodate(page);
- SetPageError(page);
- }
- clear_page_dirty(page);
- unlock_page(page);
- page_cache_release(page);
- } while (bvec >= bio->bi_io_vec);
-
- complete((struct completion*)bio->bi_private);
- return 0;
-}
-
-
-/* read one page from the block device */
-static int blkmtd_readpage(struct blkmtd_dev *dev, struct page *page)
-{
- struct bio *bio;
- struct completion event;
- int err = -ENOMEM;
-
- if(PageUptodate(page)) {
- DEBUG(2, "blkmtd: readpage page %ld is already upto date\n", page->index);
- unlock_page(page);
- return 0;
- }
-
- ClearPageUptodate(page);
- ClearPageError(page);
-
- bio = bio_alloc(GFP_KERNEL, 1);
- if(bio) {
- init_completion(&event);
- bio->bi_bdev = dev->blkdev;
- bio->bi_sector = page->index << (PAGE_SHIFT-9);
- bio->bi_private = &event;
- bio->bi_end_io = bi_read_complete;
- if(bio_add_page(bio, page, PAGE_SIZE, 0) == PAGE_SIZE) {
- submit_bio(READ_SYNC, bio);
- wait_for_completion(&event);
- err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO;
- bio_put(bio);
- }
- }
-
- if(err)
- SetPageError(page);
- else
- SetPageUptodate(page);
- flush_dcache_page(page);
- unlock_page(page);
- return err;
-}
-
-
-/* write out the current BIO and wait for it to finish */
-static int blkmtd_write_out(struct bio *bio)
-{
- struct completion event;
- int err;
-
- if(!bio->bi_vcnt) {
- bio_put(bio);
- return 0;
- }
-
- init_completion(&event);
- bio->bi_private = &event;
- bio->bi_end_io = bi_write_complete;
- submit_bio(WRITE_SYNC, bio);
- wait_for_completion(&event);
- DEBUG(3, "submit_bio completed, bi_vcnt = %d\n", bio->bi_vcnt);
- err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO;
- bio_put(bio);
- return err;
-}
-
-
-/**
- * blkmtd_add_page - add a page to the current BIO
- * @bio: bio to add to (NULL to alloc initial bio)
- * @blkdev: block device
- * @page: page to add
- * @pagecnt: pages left to add
- *
- * Adds a page to the current bio, allocating it if necessary. If it cannot be
- * added, the current bio is written out and a new one is allocated. Returns
- * the new bio to add or NULL on error
- */
-static struct bio *blkmtd_add_page(struct bio *bio, struct block_device *blkdev,
- struct page *page, int pagecnt)
-{
-
- retry:
- if(!bio) {
- bio = bio_alloc(GFP_KERNEL, pagecnt);
- if(!bio)
- return NULL;
- bio->bi_sector = page->index << (PAGE_SHIFT-9);
- bio->bi_bdev = blkdev;
- }
-
- if(bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) {
- blkmtd_write_out(bio);
- bio = NULL;
- goto retry;
- }
- return bio;
-}
-
-
-/**
- * write_pages - write block of data to device via the page cache
- * @dev: device to write to
- * @buf: data source or NULL if erase (output is set to 0xff)
- * @to: offset into output device
- * @len: amount to data to write
- * @retlen: amount of data written
- *
- * Grab pages from the page cache and fill them with the source data.
- * Non page aligned start and end result in a readin of the page and
- * part of the page being modified. Pages are added to the bio and then written
- * out.
- */
-static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to,
- size_t len, size_t *retlen)
-{
- int pagenr, offset;
- size_t start_len = 0, end_len;
- int pagecnt = 0;
- int err = 0;
- struct bio *bio = NULL;
- size_t thislen = 0;
-
- pagenr = to >> PAGE_SHIFT;
- offset = to & ~PAGE_MASK;
-
- DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %zd pagenr = %d offset = %d\n",
- buf, (long)to, len, pagenr, offset);
-
- /* see if we have to do a partial write at the start */
- if(offset) {
- start_len = ((offset + len) > PAGE_SIZE) ? PAGE_SIZE - offset : len;
- len -= start_len;
- }
-
- /* calculate the length of the other two regions */
- end_len = len & ~PAGE_MASK;
- len -= end_len;
-
- if(start_len)
- pagecnt++;
-
- if(len)
- pagecnt += len >> PAGE_SHIFT;
-
- if(end_len)
- pagecnt++;
-
- down(&dev->wrbuf_mutex);
-
- DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n",
- start_len, len, end_len, pagecnt);
-
- if(start_len) {
- /* do partial start region */
- struct page *page;
-
- DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %zd offset = %d\n",
- pagenr, start_len, offset);
-
- BUG_ON(!buf);
- page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
- lock_page(page);
- if(PageDirty(page)) {
- err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n",
- to, start_len, len, end_len, pagenr);
- BUG();
- }
- memcpy(page_address(page)+offset, buf, start_len);
- set_page_dirty(page);
- SetPageUptodate(page);
- buf += start_len;
- thislen = start_len;
- bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
- if(!bio) {
- err = -ENOMEM;
- err("bio_add_page failed\n");
- goto write_err;
- }
- pagecnt--;
- pagenr++;
- }
-
- /* Now do the main loop to a page aligned, n page sized output */
- if(len) {
- int pagesc = len >> PAGE_SHIFT;
- DEBUG(3, "blkmtd: write: whole pages start = %d, count = %d\n",
- pagenr, pagesc);
- while(pagesc) {
- struct page *page;
-
- /* see if page is in the page cache */
- DEBUG(3, "blkmtd: write: grabbing page %d from page cache\n", pagenr);
- page = grab_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr);
- if(PageDirty(page)) {
- BUG();
- }
- if(!page) {
- warn("write: cannot grab cache page %d", pagenr);
- err = -ENOMEM;
- goto write_err;
- }
- if(!buf) {
- memset(page_address(page), 0xff, PAGE_SIZE);
- } else {
- memcpy(page_address(page), buf, PAGE_SIZE);
- buf += PAGE_SIZE;
- }
- bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
- if(!bio) {
- err = -ENOMEM;
- err("bio_add_page failed\n");
- goto write_err;
- }
- pagenr++;
- pagecnt--;
- set_page_dirty(page);
- SetPageUptodate(page);
- pagesc--;
- thislen += PAGE_SIZE;
- }
- }
-
- if(end_len) {
- /* do the third region */
- struct page *page;
- DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %zd\n",
- pagenr, end_len);
- BUG_ON(!buf);
- page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
- lock_page(page);
- if(PageDirty(page)) {
- err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n",
- to, start_len, len, end_len, pagenr);
- BUG();
- }
- memcpy(page_address(page), buf, end_len);
- set_page_dirty(page);
- SetPageUptodate(page);
- DEBUG(3, "blkmtd: write: writing out partial end\n");
- thislen += end_len;
- bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
- if(!bio) {
- err = -ENOMEM;
- err("bio_add_page failed\n");
- goto write_err;
- }
- pagenr++;
- }
-
- DEBUG(3, "blkmtd: write: got %d vectors to write\n", bio->bi_vcnt);
- write_err:
- if(bio)
- blkmtd_write_out(bio);
-
- DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err);
- up(&dev->wrbuf_mutex);
-
- if(retlen)
- *retlen = thislen;
- return err;
-}
-
-
-/* erase a specified part of the device */
-static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
- struct blkmtd_dev *dev = mtd->priv;
- struct mtd_erase_region_info *einfo = mtd->eraseregions;
- int numregions = mtd->numeraseregions;
- size_t from;
- u_long len;
- int err = -EIO;
- size_t retlen;
-
- instr->state = MTD_ERASING;
- from = instr->addr;
- len = instr->len;
-
- /* check erase region has valid start and length */
- DEBUG(2, "blkmtd: erase: dev = `%s' from = 0x%zx len = 0x%lx\n",
- mtd->name+9, from, len);
- while(numregions) {
- DEBUG(3, "blkmtd: checking erase region = 0x%08X size = 0x%X num = 0x%x\n",
- einfo->offset, einfo->erasesize, einfo->numblocks);
- if(from >= einfo->offset
- && from < einfo->offset + (einfo->erasesize * einfo->numblocks)) {
- if(len == einfo->erasesize
- && ( (from - einfo->offset) % einfo->erasesize == 0))
- break;
- }
- numregions--;
- einfo++;
- }
-
- if(!numregions) {
- /* Not a valid erase block */
- err("erase: invalid erase request 0x%lX @ 0x%08zX", len, from);
- instr->state = MTD_ERASE_FAILED;
- err = -EIO;
- }
-
- if(instr->state != MTD_ERASE_FAILED) {
- /* do the erase */
- DEBUG(3, "Doing erase from = %zd len = %ld\n", from, len);
- err = write_pages(dev, NULL, from, len, &retlen);
- if(err || retlen != len) {
- err("erase failed err = %d", err);
- instr->state = MTD_ERASE_FAILED;
- } else {
- instr->state = MTD_ERASE_DONE;
- }
- }
-
- DEBUG(3, "blkmtd: erase: checking callback\n");
- mtd_erase_callback(instr);
- DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err);
- return err;
-}
-
-
-/* read a range of the data via the page cache */
-static int blkmtd_read(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
-{
- struct blkmtd_dev *dev = mtd->priv;
- int err = 0;
- int offset;
- int pagenr, pages;
- size_t thislen = 0;
-
- DEBUG(2, "blkmtd: read: dev = `%s' from = %lld len = %zd buf = %p\n",
- mtd->name+9, from, len, buf);
-
- if(from > mtd->size)
- return -EINVAL;
- if(from + len > mtd->size)
- len = mtd->size - from;
-
- pagenr = from >> PAGE_SHIFT;
- offset = from - (pagenr << PAGE_SHIFT);
-
- pages = (offset+len+PAGE_SIZE-1) >> PAGE_SHIFT;
- DEBUG(3, "blkmtd: read: pagenr = %d offset = %d, pages = %d\n",
- pagenr, offset, pages);
-
- while(pages) {
- struct page *page;
- int cpylen;
-
- DEBUG(3, "blkmtd: read: looking for page: %d\n", pagenr);
- page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
- if(IS_ERR(page)) {
- err = -EIO;
- goto readerr;
- }
-
- cpylen = (PAGE_SIZE > len) ? len : PAGE_SIZE;
- if(offset+cpylen > PAGE_SIZE)
- cpylen = PAGE_SIZE-offset;
-
- memcpy(buf + thislen, page_address(page) + offset, cpylen);
- offset = 0;
- len -= cpylen;
- thislen += cpylen;
- pagenr++;
- pages--;
- if(!PageDirty(page))
- page_cache_release(page);
- }
-
- readerr:
- if(retlen)
- *retlen = thislen;
- DEBUG(2, "blkmtd: end read: retlen = %zd, err = %d\n", thislen, err);
- return err;
-}
-
-
-/* write data to the underlying device */
-static int blkmtd_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
-{
- struct blkmtd_dev *dev = mtd->priv;
- int err;
-
- if(!len)
- return 0;
-
- DEBUG(2, "blkmtd: write: dev = `%s' to = %lld len = %zd buf = %p\n",
- mtd->name+9, to, len, buf);
-
- if(to >= mtd->size) {
- return -ENOSPC;
- }
-
- if(to + len > mtd->size) {
- len = mtd->size - to;
- }
-
- err = write_pages(dev, buf, to, len, retlen);
- if(err > 0)
- err = 0;
- DEBUG(2, "blkmtd: write: end, err = %d\n", err);
- return err;
-}
-
-
-/* sync the device - wait until the write queue is empty */
-static void blkmtd_sync(struct mtd_info *mtd)
-{
- /* Currently all writes are synchronous */
-}
-
-
-static void free_device(struct blkmtd_dev *dev)
-{
- DEBUG(2, "blkmtd: free_device() dev = %p\n", dev);
- if(dev) {
- kfree(dev->mtd_info.eraseregions);
- kfree(dev->mtd_info.name);
- if(dev->blkdev) {
- invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping);
- close_bdev_excl(dev->blkdev);
- }
- kfree(dev);
- }
-}
-
-
-/* For a given size and initial erase size, calculate the number
- * and size of each erase region. Goes round the loop twice,
- * once to find out how many regions, then allocates space,
- * then round the loop again to fill it in.
- */
-static struct mtd_erase_region_info *calc_erase_regions(
- size_t erase_size, size_t total_size, int *regions)
-{
- struct mtd_erase_region_info *info = NULL;
-
- DEBUG(2, "calc_erase_regions, es = %zd size = %zd regions = %d\n",
- erase_size, total_size, *regions);
- /* Make any user specified erasesize be a power of 2
- and at least PAGE_SIZE */
- if(erase_size) {
- int es = erase_size;
- erase_size = 1;
- while(es != 1) {
- es >>= 1;
- erase_size <<= 1;
- }
- if(erase_size < PAGE_SIZE)
- erase_size = PAGE_SIZE;
- } else {
- erase_size = CONFIG_MTD_BLKDEV_ERASESIZE;
- }
-
- *regions = 0;
-
- do {
- int tot_size = total_size;
- int er_size = erase_size;
- int count = 0, offset = 0, regcnt = 0;
-
- while(tot_size) {
- count = tot_size / er_size;
- if(count) {
- tot_size = tot_size % er_size;
- if(info) {
- DEBUG(2, "adding to erase info off=%d er=%d cnt=%d\n",
- offset, er_size, count);
- (info+regcnt)->offset = offset;
- (info+regcnt)->erasesize = er_size;
- (info+regcnt)->numblocks = count;
- (*regions)++;
- }
- regcnt++;
- offset += (count * er_size);
- }
- while(er_size > tot_size)
- er_size >>= 1;
- }
- if(info == NULL) {
- info = kmalloc(regcnt * sizeof(struct mtd_erase_region_info), GFP_KERNEL);
- if(!info)
- break;
- }
- } while(!(*regions));
- DEBUG(2, "calc_erase_regions done, es = %zd size = %zd regions = %d\n",
- erase_size, total_size, *regions);
- return info;
-}
-
-
-extern dev_t __init name_to_dev_t(const char *line);
-
-static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size)
-{
- struct block_device *bdev;
- int mode;
- struct blkmtd_dev *dev;
-
- if(!devname)
- return NULL;
-
- /* Get a handle on the device */
-
-
-#ifdef MODULE
- mode = (readonly) ? O_RDONLY : O_RDWR;
- bdev = open_bdev_excl(devname, mode, NULL);
-#else
- mode = (readonly) ? FMODE_READ : FMODE_WRITE;
- bdev = open_by_devnum(name_to_dev_t(devname), mode);
-#endif
- if(IS_ERR(bdev)) {
- err("error: cannot open device %s", devname);
- DEBUG(2, "blkmtd: opening bdev returned %ld\n", PTR_ERR(bdev));
- return NULL;
- }
-
- DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n",
- MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
-
- if(MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
- err("attempting to use an MTD device as a block device");
- blkdev_put(bdev);
- return NULL;
- }
-
- dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL);
- if(dev == NULL) {
- blkdev_put(bdev);
- return NULL;
- }
-
- memset(dev, 0, sizeof(struct blkmtd_dev));
- dev->blkdev = bdev;
- if(!readonly) {
- init_MUTEX(&dev->wrbuf_mutex);
- }
-
- dev->mtd_info.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
-
- /* Setup the MTD structure */
- /* make the name contain the block device in */
- dev->mtd_info.name = kmalloc(sizeof("blkmtd: ") + strlen(devname), GFP_KERNEL);
- if(dev->mtd_info.name == NULL)
- goto devinit_err;
-
- sprintf(dev->mtd_info.name, "blkmtd: %s", devname);
- dev->mtd_info.eraseregions = calc_erase_regions(erase_size, dev->mtd_info.size,
- &dev->mtd_info.numeraseregions);
- if(dev->mtd_info.eraseregions == NULL)
- goto devinit_err;
-
- dev->mtd_info.erasesize = dev->mtd_info.eraseregions->erasesize;
- DEBUG(1, "blkmtd: init: found %d erase regions\n",
- dev->mtd_info.numeraseregions);
-
- if(readonly) {
- dev->mtd_info.type = MTD_ROM;
- dev->mtd_info.flags = MTD_CAP_ROM;
- } else {
- dev->mtd_info.type = MTD_RAM;
- dev->mtd_info.flags = MTD_CAP_RAM;
- dev->mtd_info.erase = blkmtd_erase;
- dev->mtd_info.write = blkmtd_write;
- dev->mtd_info.writev = default_mtd_writev;
- dev->mtd_info.sync = blkmtd_sync;
- }
- dev->mtd_info.read = blkmtd_read;
- dev->mtd_info.readv = default_mtd_readv;
- dev->mtd_info.priv = dev;
- dev->mtd_info.owner = THIS_MODULE;
-
- list_add(&dev->list, &blkmtd_device_list);
- if (add_mtd_device(&dev->mtd_info)) {
- /* Device didnt get added, so free the entry */
- list_del(&dev->list);
- goto devinit_err;
- } else {
- info("mtd%d: [%s] erase_size = %dKiB %s",
- dev->mtd_info.index, dev->mtd_info.name + strlen("blkmtd: "),
- dev->mtd_info.erasesize >> 10,
- readonly ? "(read-only)" : "");
- }
-
- return dev;
-
- devinit_err:
- free_device(dev);
- return NULL;
-}
-
-
-/* Cleanup and exit - sync the device and kill of the kernel thread */
-static void __devexit cleanup_blkmtd(void)
-{
- struct list_head *temp1, *temp2;
-
- /* Remove the MTD devices */
- list_for_each_safe(temp1, temp2, &blkmtd_device_list) {
- struct blkmtd_dev *dev = list_entry(temp1, struct blkmtd_dev,
- list);
- blkmtd_sync(&dev->mtd_info);
- del_mtd_device(&dev->mtd_info);
- info("mtd%d: [%s] removed", dev->mtd_info.index,
- dev->mtd_info.name + strlen("blkmtd: "));
- list_del(&dev->list);
- free_device(dev);
- }
-}
-
-#ifndef MODULE
-
-/* Handle kernel boot params */
-
-
-static int __init param_blkmtd_device(char *str)
-{
- int i;
-
- for(i = 0; i < MAX_DEVICES; i++) {
- device[i] = str;
- DEBUG(2, "blkmtd: device setup: %d = %s\n", i, device[i]);
- strsep(&str, ",");
- }
- return 1;
-}
-
-
-static int __init param_blkmtd_erasesz(char *str)
-{
- int i;
- for(i = 0; i < MAX_DEVICES; i++) {
- char *val = strsep(&str, ",");
- if(val)
- erasesz[i] = simple_strtoul(val, NULL, 0);
- DEBUG(2, "blkmtd: erasesz setup: %d = %d\n", i, erasesz[i]);
- }
-
- return 1;
-}
-
-
-static int __init param_blkmtd_ro(char *str)
-{
- int i;
- for(i = 0; i < MAX_DEVICES; i++) {
- char *val = strsep(&str, ",");
- if(val)
- ro[i] = simple_strtoul(val, NULL, 0);
- DEBUG(2, "blkmtd: ro setup: %d = %d\n", i, ro[i]);
- }
-
- return 1;
-}
-
-
-static int __init param_blkmtd_sync(char *str)
-{
- if(str[0] == '1')
- sync = 1;
- return 1;
-}
-
-__setup("blkmtd_device=", param_blkmtd_device);
-__setup("blkmtd_erasesz=", param_blkmtd_erasesz);
-__setup("blkmtd_ro=", param_blkmtd_ro);
-__setup("blkmtd_sync=", param_blkmtd_sync);
-
-#endif
-
-
-/* Startup */
-static int __init init_blkmtd(void)
-{
- int i;
-
- info("version " VERSION);
- /* Check args - device[0] is the bare minimum*/
- if(!device[0]) {
- err("error: missing `device' name\n");
- return -EINVAL;
- }
-
- for(i = 0; i < MAX_DEVICES; i++)
- add_device(device[i], ro[i], erasesz[i] << 10);
-
- if(list_empty(&blkmtd_device_list))
- return -EINVAL;
-
- return 0;
-}
-
-module_init(init_blkmtd);
-module_exit(cleanup_blkmtd);
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 7ff403b2a0a..4160b8334c5 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/buffer_head.h>
+#include <linux/mutex.h>
#define VERSION "$Revision: 1.30 $"
@@ -31,7 +32,7 @@ struct block2mtd_dev {
struct list_head list;
struct block_device *blkdev;
struct mtd_info mtd;
- struct semaphore write_mutex;
+ struct mutex write_mutex;
};
@@ -134,9 +135,9 @@ static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
int err;
instr->state = MTD_ERASING;
- down(&dev->write_mutex);
+ mutex_lock(&dev->write_mutex);
err = _block2mtd_erase(dev, from, len);
- up(&dev->write_mutex);
+ mutex_unlock(&dev->write_mutex);
if (err) {
ERROR("erase failed err = %d", err);
instr->state = MTD_ERASE_FAILED;
@@ -249,9 +250,9 @@ static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
if (to + len > mtd->size)
len = mtd->size - to;
- down(&dev->write_mutex);
+ mutex_lock(&dev->write_mutex);
err = _block2mtd_write(dev, buf, to, len, retlen);
- up(&dev->write_mutex);
+ mutex_unlock(&dev->write_mutex);
if (err > 0)
err = 0;
return err;
@@ -310,7 +311,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
goto devinit_err;
}
- init_MUTEX(&dev->write_mutex);
+ mutex_init(&dev->write_mutex);
/* Setup the MTD structure */
/* make the name contain the block device in */
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index e4345cf744a..23e7a5c7d2c 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -20,6 +20,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/bitops.h>
+#include <linux/mutex.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
@@ -605,7 +606,7 @@ static void DoC2k_init(struct mtd_info *mtd)
this->curfloor = -1;
this->curchip = -1;
- init_MUTEX(&this->lock);
+ mutex_init(&this->lock);
/* Ident all the chips present. */
DoC_ScanChips(this, maxchips);
@@ -645,7 +646,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
if (from >= this->totlen)
return -EINVAL;
- down(&this->lock);
+ mutex_lock(&this->lock);
*retlen = 0;
while (left) {
@@ -774,7 +775,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
buf += len;
}
- up(&this->lock);
+ mutex_unlock(&this->lock);
return ret;
}
@@ -803,7 +804,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
if (to >= this->totlen)
return -EINVAL;
- down(&this->lock);
+ mutex_lock(&this->lock);
*retlen = 0;
while (left) {
@@ -873,7 +874,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
printk(KERN_ERR "Error programming flash\n");
/* Error in programming */
*retlen = 0;
- up(&this->lock);
+ mutex_unlock(&this->lock);
return -EIO;
}
@@ -935,7 +936,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
printk(KERN_ERR "Error programming flash\n");
/* Error in programming */
*retlen = 0;
- up(&this->lock);
+ mutex_unlock(&this->lock);
return -EIO;
}
@@ -956,7 +957,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x);
if (ret) {
- up(&this->lock);
+ mutex_unlock(&this->lock);
return ret;
}
}
@@ -966,7 +967,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
buf += len;
}
- up(&this->lock);
+ mutex_unlock(&this->lock);
return 0;
}
@@ -975,13 +976,13 @@ static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
u_char *eccbuf, struct nand_oobinfo *oobsel)
{
static char static_buf[512];
- static DECLARE_MUTEX(writev_buf_sem);
+ static DEFINE_MUTEX(writev_buf_mutex);
size_t totretlen = 0;
size_t thisvecofs = 0;
int ret= 0;
- down(&writev_buf_sem);
+ mutex_lock(&writev_buf_mutex);
while(count) {
size_t thislen, thisretlen;
@@ -1024,7 +1025,7 @@ static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
to += thislen;
}
- up(&writev_buf_sem);
+ mutex_unlock(&writev_buf_mutex);
*retlen = totretlen;
return ret;
}
@@ -1037,7 +1038,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
int len256 = 0, ret;
struct Nand *mychip;
- down(&this->lock);
+ mutex_lock(&this->lock);
mychip = &this->chips[ofs >> this->chipshift];
@@ -1083,7 +1084,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
ret = DoC_WaitReady(this);
- up(&this->lock);
+ mutex_unlock(&this->lock);
return ret;
}
@@ -1197,10 +1198,10 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
struct DiskOnChip *this = mtd->priv;
int ret;
- down(&this->lock);
+ mutex_lock(&this->lock);
ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf);
- up(&this->lock);
+ mutex_unlock(&this->lock);
return ret;
}
@@ -1214,10 +1215,10 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
struct Nand *mychip;
int status;
- down(&this->lock);
+ mutex_lock(&this->lock);
if (ofs & (mtd->erasesize-1) || len & (mtd->erasesize-1)) {
- up(&this->lock);
+ mutex_unlock(&this->lock);
return -EINVAL;
}
@@ -1265,7 +1266,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
callback:
mtd_erase_callback(instr);
- up(&this->lock);
+ mutex_unlock(&this->lock);
return 0;
}
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
index 1e876fcb040..29b0ddaa324 100644
--- a/drivers/mtd/devices/lart.c
+++ b/drivers/mtd/devices/lart.c
@@ -581,8 +581,6 @@ static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen
/***************************************************************************************************/
-#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
-
static struct mtd_info mtd;
static struct mtd_erase_region_info erase_regions[] = {
@@ -640,7 +638,7 @@ int __init lart_flash_init (void)
mtd.flags = MTD_CAP_NORFLASH;
mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN;
mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
- mtd.numeraseregions = NB_OF (erase_regions);
+ mtd.numeraseregions = ARRAY_SIZE(erase_regions);
mtd.eraseregions = erase_regions;
mtd.erase = flash_erase;
mtd.read = flash_read;
@@ -670,9 +668,9 @@ int __init lart_flash_init (void)
result,mtd.eraseregions[result].numblocks);
#ifdef HAVE_PARTITIONS
- printk ("\npartitions = %d\n",NB_OF (lart_partitions));
+ printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions));
- for (result = 0; result < NB_OF (lart_partitions); result++)
+ for (result = 0; result < ARRAY_SIZE(lart_partitions); result++)
printk (KERN_DEBUG
"\n\n"
"lart_partitions[%d].name = %s\n"
@@ -687,7 +685,7 @@ int __init lart_flash_init (void)
#ifndef HAVE_PARTITIONS
result = add_mtd_device (&mtd);
#else
- result = add_mtd_partitions (&mtd,lart_partitions,NB_OF (lart_partitions));
+ result = add_mtd_partitions (&mtd,lart_partitions, ARRAY_SIZE(lart_partitions));
#endif
return (result);
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index d5f24089be7..04e65d5dae0 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -186,7 +186,7 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
struct m25p *flash = mtd_to_m25p(mtd);
u32 addr,len;
- DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
flash->spi->dev.bus_id, __FUNCTION__, "at",
(u32)instr->addr, instr->len);
diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c
index 0ff2e437824..485f663493d 100644
--- a/drivers/mtd/devices/ms02-nv.c
+++ b/drivers/mtd/devices/ms02-nv.c
@@ -308,7 +308,7 @@ static int __init ms02nv_init(void)
break;
}
- for (i = 0; i < (sizeof(ms02nv_addrs) / sizeof(*ms02nv_addrs)); i++)
+ for (i = 0; i < ARRAY_SIZE(ms02nv_addrs); i++)
if (!ms02nv_init_one(ms02nv_addrs[i] << stride))
count++;
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index 8a544890173..a3b92479719 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -47,9 +47,6 @@
*/
#define MAX_LOOPS 10000
-extern void INFTL_dumptables(struct INFTLrecord *inftl);
-extern void INFTL_dumpVUchains(struct INFTLrecord *inftl);
-
static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
{
struct INFTLrecord *inftl;
@@ -132,7 +129,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
return;
}
#ifdef PSYCHO_DEBUG
- printk(KERN_INFO "INFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a');
+ printk(KERN_INFO "INFTL: Found new inftl%c\n", inftl->mbd.devnum + 'a');
#endif
return;
}
@@ -885,8 +882,6 @@ static struct mtd_blktrans_ops inftl_tr = {
.owner = THIS_MODULE,
};
-extern char inftlmountrev[];
-
static int __init init_inftl(void)
{
printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.19 $, "
diff --git a/drivers/mtd/maps/alchemy-flash.c b/drivers/mtd/maps/alchemy-flash.c
index a57791a6ce4..b933a2a27b1 100644
--- a/drivers/mtd/maps/alchemy-flash.c
+++ b/drivers/mtd/maps/alchemy-flash.c
@@ -126,8 +126,6 @@ static struct mtd_partition alchemy_partitions[] = {
}
};
-#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
-
static struct mtd_info *mymtd;
int __init alchemy_mtd_init(void)
@@ -154,7 +152,7 @@ int __init alchemy_mtd_init(void)
* Static partition definition selection
*/
parts = alchemy_partitions;
- nb_parts = NB_OF(alchemy_partitions);
+ nb_parts = ARRAY_SIZE(alchemy_partitions);
alchemy_map.size = window_size;
/*
diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c
index 6a8c0415bde..fd0f0d3187d 100644
--- a/drivers/mtd/maps/cfi_flagadm.c
+++ b/drivers/mtd/maps/cfi_flagadm.c
@@ -86,7 +86,7 @@ struct mtd_partition flagadm_parts[] = {
}
};
-#define PARTITION_COUNT (sizeof(flagadm_parts)/sizeof(struct mtd_partition))
+#define PARTITION_COUNT ARRAY_SIZE(flagadm_parts)
static struct mtd_info *mymtd;
diff --git a/drivers/mtd/maps/dbox2-flash.c b/drivers/mtd/maps/dbox2-flash.c
index 49d90542fc7..652813cd6c2 100644
--- a/drivers/mtd/maps/dbox2-flash.c
+++ b/drivers/mtd/maps/dbox2-flash.c
@@ -57,7 +57,7 @@ static struct mtd_partition partition_info[]= {
}
};
-#define NUM_PARTITIONS (sizeof(partition_info) / sizeof(partition_info[0]))
+#define NUM_PARTITIONS ARRAY_SIZE(partition_info)
#define WINDOW_ADDR 0x10000000
#define WINDOW_SIZE 0x800000
diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c
index efb22169264..c299d10b33e 100644
--- a/drivers/mtd/maps/dilnetpc.c
+++ b/drivers/mtd/maps/dilnetpc.c
@@ -300,7 +300,7 @@ static struct mtd_partition partition_info[]=
},
};
-#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
+#define NUM_PARTITIONS ARRAY_SIZE(partition_info)
static struct mtd_info *mymtd;
static struct mtd_info *lowlvl_parts[NUM_PARTITIONS];
@@ -345,7 +345,7 @@ static struct mtd_partition higlvl_partition_info[]=
},
};
-#define NUM_HIGHLVL_PARTITIONS (sizeof(higlvl_partition_info)/sizeof(partition_info[0]))
+#define NUM_HIGHLVL_PARTITIONS ARRAY_SIZE(higlvl_partition_info)
static int dnp_adnp_probe(void)
diff --git a/drivers/mtd/maps/dmv182.c b/drivers/mtd/maps/dmv182.c
index b993ac01a9a..2bb3c0f0f97 100644
--- a/drivers/mtd/maps/dmv182.c
+++ b/drivers/mtd/maps/dmv182.c
@@ -99,7 +99,7 @@ static struct mtd_info *this_mtd;
static int __init init_svme182(void)
{
struct mtd_partition *partitions;
- int num_parts = sizeof(svme182_partitions) / sizeof(struct mtd_partition);
+ int num_parts = ARRAY_SIZE(svme182_partitions);
partitions = svme182_partitions;
diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c
index 31909482110..0667101ccbe 100644
--- a/drivers/mtd/maps/h720x-flash.c
+++ b/drivers/mtd/maps/h720x-flash.c
@@ -59,7 +59,7 @@ static struct mtd_partition h720x_partitions[] = {
}
};
-#define NUM_PARTITIONS (sizeof(h720x_partitions)/sizeof(h720x_partitions[0]))
+#define NUM_PARTITIONS ARRAY_SIZE(h720x_partitions)
static int nr_mtd_parts;
static struct mtd_partition *mtd_parts;
diff --git a/drivers/mtd/maps/netsc520.c b/drivers/mtd/maps/netsc520.c
index 33060a31572..ed215470158 100644
--- a/drivers/mtd/maps/netsc520.c
+++ b/drivers/mtd/maps/netsc520.c
@@ -76,7 +76,7 @@ static struct mtd_partition partition_info[]={
.size = 0x80000
},
};
-#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
+#define NUM_PARTITIONS ARRAY_SIZE(partition_info)
#define WINDOW_SIZE 0x00100000
#define WINDOW_ADDR 0x00200000
@@ -88,7 +88,7 @@ static struct map_info netsc520_map = {
.phys = WINDOW_ADDR,
};
-#define NUM_FLASH_BANKS (sizeof(netsc520_map)/sizeof(struct map_info))
+#define NUM_FLASH_BANKS ARRAY_SIZE(netsc520_map)
static struct mtd_info *mymtd;
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
index 632eb2aa968..54a3102ab19 100644
--- a/drivers/mtd/maps/nettel.c
+++ b/drivers/mtd/maps/nettel.c
@@ -128,8 +128,7 @@ static struct mtd_partition nettel_amd_partitions[] = {
}
};
-#define NUM_AMD_PARTITIONS \
- (sizeof(nettel_amd_partitions)/sizeof(nettel_amd_partitions[0]))
+#define NUM_AMD_PARTITIONS ARRAY_SIZE(nettel_amd_partitions)
/****************************************************************************/
diff --git a/drivers/mtd/maps/ocotea.c b/drivers/mtd/maps/ocotea.c
index c223514ca2e..a21fcd195ab 100644
--- a/drivers/mtd/maps/ocotea.c
+++ b/drivers/mtd/maps/ocotea.c
@@ -58,8 +58,6 @@ static struct mtd_partition ocotea_large_partitions[] = {
}
};
-#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
-
int __init init_ocotea(void)
{
u8 fpga0_reg;
@@ -97,7 +95,7 @@ int __init init_ocotea(void)
if (flash) {
flash->owner = THIS_MODULE;
add_mtd_partitions(flash, ocotea_small_partitions,
- NB_OF(ocotea_small_partitions));
+ ARRAY_SIZE(ocotea_small_partitions));
} else {
printk("map probe failed for flash\n");
return -ENXIO;
@@ -118,7 +116,7 @@ int __init init_ocotea(void)
if (flash) {
flash->owner = THIS_MODULE;
add_mtd_partitions(flash, ocotea_large_partitions,
- NB_OF(ocotea_large_partitions));
+ ARRAY_SIZE(ocotea_large_partitions));
} else {
printk("map probe failed for flash\n");
return -ENXIO;
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
index 21822c2edbe..d2ab1bae9c3 100644
--- a/drivers/mtd/maps/pci.c
+++ b/drivers/mtd/maps/pci.c
@@ -334,9 +334,6 @@ mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
return 0;
release:
- if (mtd)
- map_destroy(mtd);
-
if (map) {
map->exit(dev, map);
kfree(map);
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index f988c817e19..d27f4129afd 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -54,7 +54,7 @@ static const int debug = 0;
#define MAX_PCMCIA_ADDR 0x4000000
struct pcmciamtd_dev {
- dev_link_t link; /* PCMCIA link */
+ struct pcmcia_device *p_dev;
dev_node_t node; /* device node */
caddr_t win_base; /* ioremapped address of PCMCIA window */
unsigned int win_size; /* size of window */
@@ -111,8 +111,8 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)
memreq_t mrq;
int ret;
- if(!(dev->link.state & DEV_PRESENT)) {
- DEBUG(1, "device removed state = 0x%4.4X", dev->link.state);
+ if (!pcmcia_dev_present(dev->p_dev)) {
+ DEBUG(1, "device removed");
return 0;
}
@@ -122,7 +122,7 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)
dev->offset, mrq.CardOffset);
mrq.Page = 0;
if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) {
- cs_error(dev->link.handle, MapMemPage, ret);
+ cs_error(dev->p_dev, MapMemPage, ret);
return NULL;
}
dev->offset = mrq.CardOffset;
@@ -238,7 +238,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v
/* read/write{8,16} copy_{from,to} routines with direct access */
-#define DEV_REMOVED(x) (!(*(u_int *)x->map_priv_1 & DEV_PRESENT))
+#define DEV_REMOVED(x) (!(pcmcia_dev_present(((struct pcmciamtd_dev *)map->map_priv_1)->p_dev)))
static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
{
@@ -319,7 +319,7 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f
static void pcmciamtd_set_vpp(struct map_info *map, int on)
{
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
- dev_link_t *link = &dev->link;
+ struct pcmcia_device *link = dev->p_dev;
modconf_t mod;
int ret;
@@ -328,9 +328,9 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
- ret = pcmcia_modify_configuration(link->handle, &mod);
+ ret = pcmcia_modify_configuration(link, &mod);
if(ret != CS_SUCCESS) {
- cs_error(link->handle, ModifyConfiguration, ret);
+ cs_error(link, ModifyConfiguration, ret);
}
}
@@ -340,7 +340,7 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
* still open, this will be postponed until it is closed.
*/
-static void pcmciamtd_release(dev_link_t *link)
+static void pcmciamtd_release(struct pcmcia_device *link)
{
struct pcmciamtd_dev *dev = link->priv;
@@ -353,12 +353,11 @@ static void pcmciamtd_release(dev_link_t *link)
}
pcmcia_release_window(link->win);
}
- pcmcia_release_configuration(link->handle);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_name)
+static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name)
{
int rc;
tuple_t tuple;
@@ -371,16 +370,16 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_
tuple.TupleOffset = 0;
tuple.DesiredTuple = RETURN_FIRST_TUPLE;
- rc = pcmcia_get_first_tuple(link->handle, &tuple);
+ rc = pcmcia_get_first_tuple(link, &tuple);
while(rc == CS_SUCCESS) {
- rc = pcmcia_get_tuple_data(link->handle, &tuple);
+ rc = pcmcia_get_tuple_data(link, &tuple);
if(rc != CS_SUCCESS) {
- cs_error(link->handle, GetTupleData, rc);
+ cs_error(link, GetTupleData, rc);
break;
}
- rc = pcmcia_parse_tuple(link->handle, &tuple, &parse);
+ rc = pcmcia_parse_tuple(link, &tuple, &parse);
if(rc != CS_SUCCESS) {
- cs_error(link->handle, ParseTuple, rc);
+ cs_error(link, ParseTuple, rc);
break;
}
@@ -451,7 +450,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_
DEBUG(2, "Unknown tuple code %d", tuple.TupleCode);
}
- rc = pcmcia_get_next_tuple(link->handle, &tuple);
+ rc = pcmcia_get_next_tuple(link, &tuple);
}
if(!dev->pcmcia_map.size)
dev->pcmcia_map.size = MAX_PCMCIA_ADDR;
@@ -488,7 +487,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void pcmciamtd_config(dev_link_t *link)
+static int pcmciamtd_config(struct pcmcia_device *link)
{
struct pcmciamtd_dev *dev = link->priv;
struct mtd_info *mtd = NULL;
@@ -504,13 +503,10 @@ static void pcmciamtd_config(dev_link_t *link)
DEBUG(3, "link=0x%p", link);
- /* Configure card */
- link->state |= DEV_CONFIG;
-
DEBUG(2, "Validating CIS");
- ret = pcmcia_validate_cis(link->handle, &cisinfo);
+ ret = pcmcia_validate_cis(link, &cisinfo);
if(ret != CS_SUCCESS) {
- cs_error(link->handle, GetTupleData, ret);
+ cs_error(link, GetTupleData, ret);
} else {
DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains);
}
@@ -538,7 +534,7 @@ static void pcmciamtd_config(dev_link_t *link)
req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
req.Base = 0;
req.AccessSpeed = mem_speed;
- link->win = (window_handle_t)link->handle;
+ link->win = (window_handle_t)link;
req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR;
dev->win_size = 0;
@@ -546,7 +542,7 @@ static void pcmciamtd_config(dev_link_t *link)
int ret;
DEBUG(2, "requesting window with size = %dKiB memspeed = %d",
req.Size >> 10, req.AccessSpeed);
- ret = pcmcia_request_window(&link->handle, &req, &link->win);
+ ret = pcmcia_request_window(&link, &req, &link->win);
DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
if(ret) {
req.Size >>= 1;
@@ -562,19 +558,19 @@ static void pcmciamtd_config(dev_link_t *link)
if(!dev->win_size) {
err("Cant allocate memory window");
pcmciamtd_release(link);
- return;
+ return -ENODEV;
}
DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
/* Get write protect status */
- CS_CHECK(GetStatus, pcmcia_get_status(link->handle, &status));
+ CS_CHECK(GetStatus, pcmcia_get_status(link, &status));
DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx",
status.CardState, (unsigned long)link->win);
dev->win_base = ioremap(req.Base, req.Size);
if(!dev->win_base) {
err("ioremap(%lu, %u) failed", req.Base, req.Size);
pcmciamtd_release(link);
- return;
+ return -ENODEV;
}
DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
dev, req.Base, dev->win_base, req.Size);
@@ -584,17 +580,14 @@ static void pcmciamtd_config(dev_link_t *link)
dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
DEBUG(2, "Getting configuration");
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link->handle, &t));
+ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &t));
DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2);
dev->vpp = (vpp) ? vpp : t.Vpp1;
link->conf.Attributes = 0;
- link->conf.Vcc = t.Vcc;
if(setvpp == 2) {
- link->conf.Vpp1 = dev->vpp;
- link->conf.Vpp2 = dev->vpp;
+ link->conf.Vpp = dev->vpp;
} else {
- link->conf.Vpp1 = 0;
- link->conf.Vpp2 = 0;
+ link->conf.Vpp = 0;
}
link->conf.IntType = INT_MEMORY;
@@ -606,9 +599,10 @@ static void pcmciamtd_config(dev_link_t *link)
link->conf.ConfigIndex = 0;
link->conf.Present = t.Present;
DEBUG(2, "Setting Configuration");
- ret = pcmcia_request_configuration(link->handle, &link->conf);
+ ret = pcmcia_request_configuration(link, &link->conf);
if(ret != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, ret);
+ cs_error(link, RequestConfiguration, ret);
+ return -ENODEV;
}
if(mem_type == 1) {
@@ -616,7 +610,7 @@ static void pcmciamtd_config(dev_link_t *link)
} else if(mem_type == 2) {
mtd = do_map_probe("map_rom", &dev->pcmcia_map);
} else {
- for(i = 0; i < sizeof(probes) / sizeof(char *); i++) {
+ for(i = 0; i < ARRAY_SIZE(probes); i++) {
DEBUG(1, "Trying %s", probes[i]);
mtd = do_map_probe(probes[i], &dev->pcmcia_map);
if(mtd)
@@ -629,7 +623,7 @@ static void pcmciamtd_config(dev_link_t *link)
if(!mtd) {
DEBUG(1, "Cant find an MTD");
pcmciamtd_release(link);
- return;
+ return -ENODEV;
}
dev->mtd_info = mtd;
@@ -654,7 +648,6 @@ static void pcmciamtd_config(dev_link_t *link)
use the faster non-remapping read/write functions */
if(mtd->size <= dev->win_size) {
DEBUG(1, "Using non remapping memory functions");
- dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state);
dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
if (dev->pcmcia_map.bankwidth == 1) {
dev->pcmcia_map.read = pcmcia_read8;
@@ -672,19 +665,18 @@ static void pcmciamtd_config(dev_link_t *link)
dev->mtd_info = NULL;
err("Couldnt register MTD device");
pcmciamtd_release(link);
- return;
+ return -ENODEV;
}
snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index);
info("mtd%d: %s", mtd->index, mtd->name);
- link->state &= ~DEV_CONFIG_PENDING;
- link->dev = &dev->node;
- return;
+ link->dev_node = &dev->node;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
err("CS Error, exiting");
pcmciamtd_release(link);
- return;
+ return -ENODEV;
}
@@ -713,21 +705,18 @@ static int pcmciamtd_resume(struct pcmcia_device *dev)
* when the device is released.
*/
-static void pcmciamtd_detach(struct pcmcia_device *p_dev)
+static void pcmciamtd_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
+ struct pcmciamtd_dev *dev = link->priv;
DEBUG(3, "link=0x%p", link);
- if(link->state & DEV_CONFIG) {
- struct pcmciamtd_dev *dev = link->priv;
- if(dev->mtd_info) {
- del_mtd_device(dev->mtd_info);
- info("mtd%d: Removed", dev->mtd_info->index);
- }
-
- pcmciamtd_release(link);
+ if(dev->mtd_info) {
+ del_mtd_device(dev->mtd_info);
+ info("mtd%d: Removed", dev->mtd_info->index);
}
+
+ pcmciamtd_release(link);
}
@@ -736,10 +725,9 @@ static void pcmciamtd_detach(struct pcmcia_device *p_dev)
* with Card Services.
*/
-static int pcmciamtd_attach(struct pcmcia_device *p_dev)
+static int pcmciamtd_probe(struct pcmcia_device *link)
{
struct pcmciamtd_dev *dev;
- dev_link_t *link;
/* Create new memory card device */
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
@@ -747,20 +735,13 @@ static int pcmciamtd_attach(struct pcmcia_device *p_dev)
DEBUG(1, "dev=0x%p", dev);
memset(dev, 0, sizeof(*dev));
- link = &dev->link;
+ dev->p_dev = link;
link->priv = dev;
link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY;
- link->next = NULL;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- pcmciamtd_config(link);
-
- return 0;
+ return pcmciamtd_config(link);
}
static struct pcmcia_device_id pcmciamtd_ids[] = {
@@ -794,7 +775,7 @@ static struct pcmcia_driver pcmciamtd_driver = {
.drv = {
.name = "pcmciamtd"
},
- .probe = pcmciamtd_attach,
+ .probe = pcmciamtd_probe,
.remove = pcmciamtd_detach,
.owner = THIS_MODULE,
.id_table = pcmciamtd_ids,
diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c
index 5b76ed88618..50b14033613 100644
--- a/drivers/mtd/maps/redwood.c
+++ b/drivers/mtd/maps/redwood.c
@@ -121,8 +121,7 @@ struct map_info redwood_flash_map = {
};
-#define NUM_REDWOOD_FLASH_PARTITIONS \
- (sizeof(redwood_flash_partitions)/sizeof(redwood_flash_partitions[0]))
+#define NUM_REDWOOD_FLASH_PARTITIONS ARRAY_SIZE(redwood_flash_partitions)
static struct mtd_info *redwood_mtd;
diff --git a/drivers/mtd/maps/sbc8240.c b/drivers/mtd/maps/sbc8240.c
index 225cdd9ba5b..350286dc1d2 100644
--- a/drivers/mtd/maps/sbc8240.c
+++ b/drivers/mtd/maps/sbc8240.c
@@ -66,7 +66,7 @@ static struct map_info sbc8240_map[2] = {
}
};
-#define NUM_FLASH_BANKS (sizeof(sbc8240_map) / sizeof(struct map_info))
+#define NUM_FLASH_BANKS ARRAY_SIZE(sbc8240_map)
/*
* The following defines the partition layout of SBC8240 boards.
@@ -125,8 +125,6 @@ static struct mtd_partition sbc8240_fs_partitions [] = {
}
};
-#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
-
/* trivial struct to describe partition information */
struct mtd_part_def
{
@@ -190,10 +188,10 @@ int __init init_sbc8240_mtd (void)
#ifdef CONFIG_MTD_PARTITIONS
sbc8240_part_banks[0].mtd_part = sbc8240_uboot_partitions;
sbc8240_part_banks[0].type = "static image";
- sbc8240_part_banks[0].nums = NB_OF(sbc8240_uboot_partitions);
+ sbc8240_part_banks[0].nums = ARRAY_SIZE(sbc8240_uboot_partitions);
sbc8240_part_banks[1].mtd_part = sbc8240_fs_partitions;
sbc8240_part_banks[1].type = "static file system";
- sbc8240_part_banks[1].nums = NB_OF(sbc8240_fs_partitions);
+ sbc8240_part_banks[1].nums = ARRAY_SIZE(sbc8240_fs_partitions);
for (i = 0; i < NUM_FLASH_BANKS; i++) {
diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c
index ed92afadd8a..e8c130e1efd 100644
--- a/drivers/mtd/maps/sc520cdp.c
+++ b/drivers/mtd/maps/sc520cdp.c
@@ -107,7 +107,7 @@ static struct map_info sc520cdp_map[] = {
},
};
-#define NUM_FLASH_BANKS (sizeof(sc520cdp_map)/sizeof(struct map_info))
+#define NUM_FLASH_BANKS ARRAY_SIZE(sc520cdp_map)
static struct mtd_info *mymtd[NUM_FLASH_BANKS];
static struct mtd_info *merged_mtd;
diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c
index 2c91dff8bb6..28b8a571a91 100644
--- a/drivers/mtd/maps/scx200_docflash.c
+++ b/drivers/mtd/maps/scx200_docflash.c
@@ -70,7 +70,7 @@ static struct mtd_partition partition_info[] = {
.size = 0x80000
},
};
-#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
+#define NUM_PARTITIONS ARRAY_SIZE(partition_info)
#endif
diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c
index 999f4bb3d84..12fe53c0d2f 100644
--- a/drivers/mtd/maps/sharpsl-flash.c
+++ b/drivers/mtd/maps/sharpsl-flash.c
@@ -49,8 +49,6 @@ static struct mtd_partition sharpsl_partitions[1] = {
}
};
-#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
-
int __init init_sharpsl(void)
{
struct mtd_partition *parts;
@@ -92,7 +90,7 @@ int __init init_sharpsl(void)
}
parts = sharpsl_partitions;
- nb_parts = NB_OF(sharpsl_partitions);
+ nb_parts = ARRAY_SIZE(sharpsl_partitions);
printk(KERN_NOTICE "Using %s partision definition\n", part_type);
add_mtd_partitions(mymtd, parts, nb_parts);
diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c
index 4b372bcb17f..a7422c20056 100644
--- a/drivers/mtd/maps/ts5500_flash.c
+++ b/drivers/mtd/maps/ts5500_flash.c
@@ -64,7 +64,7 @@ static struct mtd_partition ts5500_partitions[] = {
}
};
-#define NUM_PARTITIONS (sizeof(ts5500_partitions)/sizeof(struct mtd_partition))
+#define NUM_PARTITIONS ARRAY_SIZE(ts5500_partitions)
static struct mtd_info *mymtd;
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index 79d92808b76..f7264dc2ac9 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -37,7 +37,7 @@ struct mtd_partition uclinux_romfs[] = {
{ .name = "ROMfs" }
};
-#define NUM_PARTITIONS (sizeof(uclinux_romfs) / sizeof(uclinux_romfs[0]))
+#define NUM_PARTITIONS ARRAY_SIZE(uclinux_romfs)
/****************************************************************************/
diff --git a/drivers/mtd/maps/vmax301.c b/drivers/mtd/maps/vmax301.c
index e0063941c0d..b3e48739543 100644
--- a/drivers/mtd/maps/vmax301.c
+++ b/drivers/mtd/maps/vmax301.c
@@ -182,7 +182,7 @@ int __init init_vmax301(void)
}
}
- if (!vmax_mtd[1] && !vmax_mtd[2]) {
+ if (!vmax_mtd[0] && !vmax_mtd[1]) {
iounmap((void *)iomapadr);
return -ENXIO;
}
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 840dd66ce2d..458d3c8ae1e 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -19,12 +19,12 @@
#include <linux/spinlock.h>
#include <linux/hdreg.h>
#include <linux/init.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
static LIST_HEAD(blktrans_majors);
-extern struct semaphore mtd_table_mutex;
+extern struct mutex mtd_table_mutex;
extern struct mtd_info *mtd_table[];
struct mtd_blkcore_priv {
@@ -122,9 +122,9 @@ static int mtd_blktrans_thread(void *arg)
spin_unlock_irq(rq->queue_lock);
- down(&dev->sem);
+ mutex_lock(&dev->lock);
res = do_blktrans_request(tr, dev, req);
- up(&dev->sem);
+ mutex_unlock(&dev->lock);
spin_lock_irq(rq->queue_lock);
@@ -235,8 +235,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
int last_devnum = -1;
struct gendisk *gd;
- if (!down_trylock(&mtd_table_mutex)) {
- up(&mtd_table_mutex);
+ if (!!mutex_trylock(&mtd_table_mutex)) {
+ mutex_unlock(&mtd_table_mutex);
BUG();
}
@@ -267,7 +267,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
return -EBUSY;
}
- init_MUTEX(&new->sem);
+ mutex_init(&new->lock);
list_add_tail(&new->list, &tr->devs);
added:
if (!tr->writesect)
@@ -313,8 +313,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
{
- if (!down_trylock(&mtd_table_mutex)) {
- up(&mtd_table_mutex);
+ if (!!mutex_trylock(&mtd_table_mutex)) {
+ mutex_unlock(&mtd_table_mutex);
BUG();
}
@@ -378,14 +378,14 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv));
- down(&mtd_table_mutex);
+ mutex_lock(&mtd_table_mutex);
ret = register_blkdev(tr->major, tr->name);
if (ret) {
printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n",
tr->name, tr->major, ret);
kfree(tr->blkcore_priv);
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
return ret;
}
spin_lock_init(&tr->blkcore_priv->queue_lock);
@@ -396,7 +396,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
if (!tr->blkcore_priv->rq) {
unregister_blkdev(tr->major, tr->name);
kfree(tr->blkcore_priv);
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
return -ENOMEM;
}
@@ -407,7 +407,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
blk_cleanup_queue(tr->blkcore_priv->rq);
unregister_blkdev(tr->major, tr->name);
kfree(tr->blkcore_priv);
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
return ret;
}
@@ -419,7 +419,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
tr->add_mtd(tr, mtd_table[i]);
}
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
return 0;
}
@@ -428,7 +428,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
{
struct list_head *this, *next;
- down(&mtd_table_mutex);
+ mutex_lock(&mtd_table_mutex);
/* Clean up the kernel thread */
tr->blkcore_priv->exiting = 1;
@@ -446,7 +446,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
blk_cleanup_queue(tr->blkcore_priv->rq);
unregister_blkdev(tr->major, tr->name);
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
kfree(tr->blkcore_priv);
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index e84756644fd..2cef280e388 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -19,11 +19,13 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/blktrans.h>
+#include <linux/mutex.h>
+
static struct mtdblk_dev {
struct mtd_info *mtd;
int count;
- struct semaphore cache_sem;
+ struct mutex cache_mutex;
unsigned char *cache_data;
unsigned long cache_offset;
unsigned int cache_size;
@@ -284,7 +286,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
mtdblk->count = 1;
mtdblk->mtd = mtd;
- init_MUTEX (&mtdblk->cache_sem);
+ mutex_init(&mtdblk->cache_mutex);
mtdblk->cache_state = STATE_EMPTY;
if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM &&
mtdblk->mtd->erasesize) {
@@ -306,9 +308,9 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
- down(&mtdblk->cache_sem);
+ mutex_lock(&mtdblk->cache_mutex);
write_cached_data(mtdblk);
- up(&mtdblk->cache_sem);
+ mutex_unlock(&mtdblk->cache_mutex);
if (!--mtdblk->count) {
/* It was the last usage. Free the device */
@@ -327,9 +329,9 @@ static int mtdblock_flush(struct mtd_blktrans_dev *dev)
{
struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];
- down(&mtdblk->cache_sem);
+ mutex_lock(&mtdblk->cache_mutex);
write_cached_data(mtdblk);
- up(&mtdblk->cache_sem);
+ mutex_unlock(&mtdblk->cache_mutex);
if (mtdblk->mtd->sync)
mtdblk->mtd->sync(mtdblk->mtd);
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index dade02ab068..9905870f56e 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -19,15 +19,13 @@
#include <linux/ioctl.h>
#include <linux/init.h>
#include <linux/mtd/compatmac.h>
-#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
-#endif
#include <linux/mtd/mtd.h>
/* These are exported solely for the purpose of mtd_blkdevs.c. You
should not use them for _anything_ else */
-DECLARE_MUTEX(mtd_table_mutex);
+DEFINE_MUTEX(mtd_table_mutex);
struct mtd_info *mtd_table[MAX_MTD_DEVICES];
EXPORT_SYMBOL_GPL(mtd_table_mutex);
@@ -49,7 +47,7 @@ int add_mtd_device(struct mtd_info *mtd)
{
int i;
- down(&mtd_table_mutex);
+ mutex_lock(&mtd_table_mutex);
for (i=0; i < MAX_MTD_DEVICES; i++)
if (!mtd_table[i]) {
@@ -67,7 +65,7 @@ int add_mtd_device(struct mtd_info *mtd)
not->add(mtd);
}
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
/* We _know_ we aren't being removed, because
our caller is still holding us here. So none
of this try_ nonsense, and no bitching about it
@@ -76,7 +74,7 @@ int add_mtd_device(struct mtd_info *mtd)
return 0;
}
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
return 1;
}
@@ -94,7 +92,7 @@ int del_mtd_device (struct mtd_info *mtd)
{
int ret;
- down(&mtd_table_mutex);
+ mutex_lock(&mtd_table_mutex);
if (mtd_table[mtd->index] != mtd) {
ret = -ENODEV;
@@ -118,7 +116,7 @@ int del_mtd_device (struct mtd_info *mtd)
ret = 0;
}
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
return ret;
}
@@ -135,7 +133,7 @@ void register_mtd_user (struct mtd_notifier *new)
{
int i;
- down(&mtd_table_mutex);
+ mutex_lock(&mtd_table_mutex);
list_add(&new->list, &mtd_notifiers);
@@ -145,7 +143,7 @@ void register_mtd_user (struct mtd_notifier *new)
if (mtd_table[i])
new->add(mtd_table[i]);
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
}
/**
@@ -162,7 +160,7 @@ int unregister_mtd_user (struct mtd_notifier *old)
{
int i;
- down(&mtd_table_mutex);
+ mutex_lock(&mtd_table_mutex);
module_put(THIS_MODULE);
@@ -171,7 +169,7 @@ int unregister_mtd_user (struct mtd_notifier *old)
old->remove(mtd_table[i]);
list_del(&old->list);
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
return 0;
}
@@ -193,7 +191,7 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
struct mtd_info *ret = NULL;
int i;
- down(&mtd_table_mutex);
+ mutex_lock(&mtd_table_mutex);
if (num == -1) {
for (i=0; i< MAX_MTD_DEVICES; i++)
@@ -211,7 +209,7 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
if (ret)
ret->usecount++;
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
return ret;
}
@@ -219,9 +217,9 @@ void put_mtd_device(struct mtd_info *mtd)
{
int c;
- down(&mtd_table_mutex);
+ mutex_lock(&mtd_table_mutex);
c = --mtd->usecount;
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
BUG_ON(c < 0);
module_put(mtd->owner);
@@ -296,10 +294,11 @@ EXPORT_SYMBOL(unregister_mtd_user);
EXPORT_SYMBOL(default_mtd_writev);
EXPORT_SYMBOL(default_mtd_readv);
+#ifdef CONFIG_PROC_FS
+
/*====================================================================*/
/* Support for /proc/mtd */
-#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_mtd;
static inline int mtd_proc_info (char *buf, int i)
@@ -319,7 +318,7 @@ static int mtd_read_proc (char *page, char **start, off_t off, int count,
int len, l, i;
off_t begin = 0;
- down(&mtd_table_mutex);
+ mutex_lock(&mtd_table_mutex);
len = sprintf(page, "dev: size erasesize name\n");
for (i=0; i< MAX_MTD_DEVICES; i++) {
@@ -337,38 +336,34 @@ static int mtd_read_proc (char *page, char **start, off_t off, int count,
*eof = 1;
done:
- up(&mtd_table_mutex);
+ mutex_unlock(&mtd_table_mutex);
if (off >= len+begin)
return 0;
*start = page + (off-begin);
return ((count < begin+len-off) ? count : begin+len-off);
}
-#endif /* CONFIG_PROC_FS */
-
/*====================================================================*/
/* Init code */
static int __init init_mtd(void)
{
-#ifdef CONFIG_PROC_FS
if ((proc_mtd = create_proc_entry( "mtd", 0, NULL )))
proc_mtd->read_proc = mtd_read_proc;
-#endif
return 0;
}
static void __exit cleanup_mtd(void)
{
-#ifdef CONFIG_PROC_FS
if (proc_mtd)
remove_proc_entry( "mtd", NULL);
-#endif
}
module_init(init_mtd);
module_exit(cleanup_mtd);
+#endif /* CONFIG_PROC_FS */
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 1fc4c134d93..cfe288a6e85 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -178,17 +178,16 @@ config MTD_NAND_DISKONCHIP_BBTWRITE
Even if you leave this disabled, you can enable BBT writes at module
load time (assuming you build diskonchip as a module) with the module
parameter "inftl_bbt_write=1".
-
- config MTD_NAND_SHARPSL
- bool "Support for NAND Flash on Sharp SL Series (C7xx + others)"
- depends on MTD_NAND && ARCH_PXA
-
- config MTD_NAND_NANDSIM
- bool "Support for NAND Flash Simulator"
- depends on MTD_NAND && MTD_PARTITIONS
+config MTD_NAND_SHARPSL
+ tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
+ depends on MTD_NAND && ARCH_PXA
+
+config MTD_NAND_NANDSIM
+ tristate "Support for NAND Flash Simulator"
+ depends on MTD_NAND && MTD_PARTITIONS
help
The simulator may simulate verious NAND flash chips for the
MTD nand layer.
-
+
endmenu
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 201e1362da1..bde3550910a 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -55,8 +55,6 @@ static const struct mtd_partition partition_info[] = {
.size = MTDPART_SIZ_FULL
}
};
-#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
-
/**
* au_read_byte - read one byte from the chip
@@ -462,7 +460,7 @@ int __init au1xxx_nand_init (void)
}
/* Register the partitions */
- add_mtd_partitions(au1550_mtd, partition_info, NB_OF(partition_info));
+ add_mtd_partitions(au1550_mtd, partition_info, ARRAY_SIZE(partition_info));
return 0;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 5d222460b42..95e96fa1fce 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -80,6 +80,7 @@
#include <linux/mtd/compatmac.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
+#include <linux/leds.h>
#include <asm/io.h>
#ifdef CONFIG_MTD_PARTITIONS
@@ -515,6 +516,8 @@ static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, i
return nand_isbad_bbt (mtd, ofs, allowbbt);
}
+DEFINE_LED_TRIGGER(nand_led_trigger);
+
/*
* Wait for the ready pin, after a command
* The timeout is catched later.
@@ -524,12 +527,14 @@ static void nand_wait_ready(struct mtd_info *mtd)
struct nand_chip *this = mtd->priv;
unsigned long timeo = jiffies + 2;
+ led_trigger_event(nand_led_trigger, LED_FULL);
/* wait until command is processed or timeout occures */
do {
if (this->dev_ready(mtd))
- return;
+ break;
touch_softlockup_watchdog();
} while (time_before(jiffies, timeo));
+ led_trigger_event(nand_led_trigger, LED_OFF);
}
/**
@@ -817,6 +822,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
else
timeo += (HZ * 20) / 1000;
+ led_trigger_event(nand_led_trigger, LED_FULL);
+
/* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine. */
ndelay (100);
@@ -840,6 +847,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
}
cond_resched();
}
+ led_trigger_event(nand_led_trigger, LED_OFF);
+
status = (int) this->read_byte(mtd);
return status;
}
@@ -2724,6 +2733,21 @@ void nand_release (struct mtd_info *mtd)
EXPORT_SYMBOL_GPL (nand_scan);
EXPORT_SYMBOL_GPL (nand_release);
+
+static int __init nand_base_init(void)
+{
+ led_trigger_register_simple("nand-disk", &nand_led_trigger);
+ return 0;
+}
+
+static void __exit nand_base_exit(void)
+{
+ led_trigger_unregister_simple(nand_led_trigger);
+}
+
+module_init(nand_base_init);
+module_exit(nand_base_exit);
+
MODULE_LICENSE ("GPL");
MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
MODULE_DESCRIPTION ("Generic NAND flash driver code");
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index 8815c8dbef2..c077d2ec9cd 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -85,10 +85,6 @@ static int parse_redboot_partitions(struct mtd_info *master,
numslots = (master->erasesize / sizeof(struct fis_image_desc));
for (i = 0; i < numslots; i++) {
- if (buf[i].name[0] == 0xff) {
- i = numslots;
- break;
- }
if (!memcmp(buf[i].name, "FIS directory", 14)) {
/* This is apparently the FIS directory entry for the
* FIS directory itself. The FIS directory size is
@@ -128,7 +124,7 @@ static int parse_redboot_partitions(struct mtd_info *master,
struct fis_list *new_fl, **prev;
if (buf[i].name[0] == 0xff)
- break;
+ continue;
if (!redboot_checksum(&buf[i]))
break;
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 70f63891b19..274b0138d44 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -788,7 +788,7 @@ struct vortex_private {
int options; /* User-settable misc. driver options. */
unsigned int media_override:4, /* Passed-in media type. */
default_media:4, /* Read from the EEPROM/Wn3_Config. */
- full_duplex:1, force_fd:1, autoselect:1,
+ full_duplex:1, autoselect:1,
bus_master:1, /* Vortex can only do a fragment bus-m. */
full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang */
flow_ctrl:1, /* Use 802.3x flow control (PAUSE only) */
@@ -1633,12 +1633,6 @@ vortex_set_duplex(struct net_device *dev)
((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ?
0x100 : 0),
ioaddr + Wn3_MAC_Ctrl);
-
- issue_and_wait(dev, TxReset);
- /*
- * Don't reset the PHY - that upsets autonegotiation during DHCP operations.
- */
- issue_and_wait(dev, RxReset|0x04);
}
static void vortex_check_media(struct net_device *dev, unsigned int init)
@@ -1663,7 +1657,7 @@ vortex_up(struct net_device *dev)
struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
unsigned int config;
- int i;
+ int i, mii_reg1, mii_reg5;
if (VORTEX_PCI(vp)) {
pci_set_power_state(VORTEX_PCI(vp), PCI_D0); /* Go active */
@@ -1723,14 +1717,23 @@ vortex_up(struct net_device *dev)
printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", config);
iowrite32(config, ioaddr + Wn3_Config);
- netif_carrier_off(dev);
if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
EL3WINDOW(4);
+ mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR);
+ mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA);
+ vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);
+
vortex_check_media(dev, 1);
}
else
vortex_set_duplex(dev);
+ issue_and_wait(dev, TxReset);
+ /*
+ * Don't reset the PHY - that upsets autonegotiation during DHCP operations.
+ */
+ issue_and_wait(dev, RxReset|0x04);
+
iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
@@ -2083,16 +2086,14 @@ vortex_error(struct net_device *dev, int status)
}
if (tx_status & 0x14) vp->stats.tx_fifo_errors++;
if (tx_status & 0x38) vp->stats.tx_aborted_errors++;
+ if (tx_status & 0x08) vp->xstats.tx_max_collisions++;
iowrite8(0, ioaddr + TxStatus);
if (tx_status & 0x30) { /* txJabber or txUnderrun */
do_tx_reset = 1;
- } else if (tx_status & 0x08) { /* maxCollisions */
- vp->xstats.tx_max_collisions++;
- if (vp->drv_flags & MAX_COLLISION_RESET) {
- do_tx_reset = 1;
- reset_mask = 0x0108; /* Reset interface logic, but not download logic */
- }
- } else { /* Merely re-enable the transmitter. */
+ } else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET)) { /* maxCollisions */
+ do_tx_reset = 1;
+ reset_mask = 0x0108; /* Reset interface logic, but not download logic */
+ } else { /* Merely re-enable the transmitter. */
iowrite16(TxEnable, ioaddr + EL3_CMD);
}
}
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index ce99845d826..066e22b01a9 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -539,8 +539,7 @@ rx_status_loop:
unsigned buflen;
skb = cp->rx_skb[rx_tail].skb;
- if (!skb)
- BUG();
+ BUG_ON(!skb);
desc = &cp->rx_ring[rx_tail];
status = le32_to_cpu(desc->opts1);
@@ -723,8 +722,7 @@ static void cp_tx (struct cp_private *cp)
break;
skb = cp->tx_skb[tx_tail].skb;
- if (!skb)
- BUG();
+ BUG_ON(!skb);
pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
@@ -1550,8 +1548,7 @@ static void cp_get_ethtool_stats (struct net_device *dev,
tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort);
tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun);
tmp_stats[i++] = cp->cp_stats.rx_frags;
- if (i != CP_NUM_STATS)
- BUG();
+ BUG_ON(i != CP_NUM_STATS);
pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma);
}
@@ -1856,8 +1853,7 @@ static void cp_remove_one (struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct cp_private *cp = netdev_priv(dev);
- if (!dev)
- BUG();
+ BUG_ON(!dev);
unregister_netdev(dev);
iounmap(cp->regs);
if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0);
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 599b68d8c45..51e39dcd060 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -134,7 +134,7 @@ struct ei_device {
#define inb_p(_p) inb(_p)
#define outb_p(_v,_p) outb(_v,_p)
-#elif defined(CONFIG_NET_CBUS) || defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE)
+#elif defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE)
#define EI_SHIFT(x) (ei_local->reg_offset[x])
#else
#define EI_SHIFT(x) (x)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e20b849a22e..bdaaad8f212 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2313,13 +2313,11 @@ config S2IO_NAPI
endmenu
-if !UML
source "drivers/net/tokenring/Kconfig"
source "drivers/net/wireless/Kconfig"
source "drivers/net/pcmcia/Kconfig"
-endif
source "drivers/net/wan/Kconfig"
diff --git a/drivers/net/acenic_firmware.h b/drivers/net/acenic_firmware.h
index 6d625d59562..d7882dd783c 100644
--- a/drivers/net/acenic_firmware.h
+++ b/drivers/net/acenic_firmware.h
@@ -4397,7 +4397,7 @@ static u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __devinitdata = {
0x3c010001, 0x220821, 0xac317e30, 0x8fbf0024,
0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
0x8fb00010, 0x3e00008, 0x27bd0028, 0x0 };
-static u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
+static u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __devinitdata = {
0x24486561, 0x6465723a, 0x202f7072,
0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e,
@@ -4571,7 +4571,7 @@ static u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x0, 0x14c38, 0x14c38, 0x14b80,
0x14bc4, 0x14c38, 0x14c38, 0x0,
0x0, 0x0 };
-static u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = {
+static u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __devinitdata = {
0x416c7465,
0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465,
0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242,
@@ -4612,7 +4612,7 @@ static u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = {
#define tigon2FwSbssLen 0xcc
#define tigon2FwBssAddr 0x00016f50
#define tigon2FwBssLen 0x20c0
-static u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
+static u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __devinitdata = {
0x0,
0x10000003, 0x0, 0xd, 0xd,
0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 0x3c100000,
@@ -9154,7 +9154,7 @@ static u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24020001, 0x8f430328, 0x1021, 0x24630001,
0x3e00008, 0xaf430328, 0x3e00008, 0x0,
0x0, 0x0, 0x0, 0x0 };
-static u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
+static u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __devinitdata = {
0x24486561, 0x6465723a, 0x202f7072,
0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
@@ -9425,7 +9425,7 @@ static u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x14ed8, 0x14b8c, 0x14bd8, 0x14c24,
0x14ed8, 0x7365746d, 0x61636163, 0x74000000,
0x0, 0x0 };
-static u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __initdata = {
+static u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __devinitdata = {
0x1,
0x1, 0x1, 0xc001fc, 0x3ffc,
0xc00000, 0x416c7465, 0x6f6e2041, 0x63654e49,
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 64e2caf3083..fabc0607b0f 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -765,8 +765,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
BUGMSG(D_DURING, "in arcnet_interrupt\n");
lp = dev->priv;
- if (!lp)
- BUG();
+ BUG_ON(!lp);
spin_lock(&lp->lock);
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index 43150b2bd13..0d45553ff75 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -125,11 +125,11 @@ static void __init com90xx_probe(void)
if (!io && !irq && !shmem && !*device && com90xx_skip_probe)
return;
- shmems = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(unsigned long),
+ shmems = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(unsigned long),
GFP_KERNEL);
if (!shmems)
return;
- iomem = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(void __iomem *),
+ iomem = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(void __iomem *),
GFP_KERNEL);
if (!iomem) {
kfree(shmems);
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 1363083b4d8..14dbad14afb 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -52,6 +52,7 @@
#include <linux/mii.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
+#include <linux/crc32.h>
#include <asm/mipsregs.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -2070,23 +2071,6 @@ static void au1000_tx_timeout(struct net_device *dev)
netif_wake_queue(dev);
}
-
-static unsigned const ethernet_polynomial = 0x04c11db7U;
-static inline u32 ether_crc(int length, unsigned char *data)
-{
- int crc = -1;
-
- while(--length >= 0) {
- unsigned char current_octet = *data++;
- int bit;
- for (bit = 0; bit < 8; bit++, current_octet >>= 1)
- crc = (crc << 1) ^
- ((crc < 0) ^ (current_octet & 1) ?
- ethernet_polynomial : 0);
- }
- return crc;
-}
-
static void set_rx_mode(struct net_device *dev)
{
struct au1000_private *aup = (struct au1000_private *) dev->priv;
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index c3267e4e1bb..d8233e0b789 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
* Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
+ * Copyright (C) 2006 Broadcom Corporation.
*
* Distribute under GPL.
*/
@@ -28,8 +29,8 @@
#define DRV_MODULE_NAME "b44"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "0.97"
-#define DRV_MODULE_RELDATE "Nov 30, 2005"
+#define DRV_MODULE_VERSION "1.00"
+#define DRV_MODULE_RELDATE "Apr 7, 2006"
#define B44_DEF_MSG_ENABLE \
(NETIF_MSG_DRV | \
@@ -136,7 +137,7 @@ static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
return readl(bp->regs + reg);
}
-static inline void bw32(const struct b44 *bp,
+static inline void bw32(const struct b44 *bp,
unsigned long reg, unsigned long val)
{
writel(val, bp->regs + reg);
@@ -286,13 +287,13 @@ static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
val |= ((u32) data[4]) << 8;
val |= ((u32) data[5]) << 0;
bw32(bp, B44_CAM_DATA_LO, val);
- val = (CAM_DATA_HI_VALID |
+ val = (CAM_DATA_HI_VALID |
(((u32) data[0]) << 8) |
(((u32) data[1]) << 0));
bw32(bp, B44_CAM_DATA_HI, val);
bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE |
(index << CAM_CTRL_INDEX_SHIFT)));
- b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
+ b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
}
static inline void __b44_disable_ints(struct b44 *bp)
@@ -410,25 +411,18 @@ static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags)
static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
{
- u32 pause_enab = bp->flags & (B44_FLAG_TX_PAUSE |
- B44_FLAG_RX_PAUSE);
+ u32 pause_enab = 0;
- if (local & ADVERTISE_PAUSE_CAP) {
- if (local & ADVERTISE_PAUSE_ASYM) {
- if (remote & LPA_PAUSE_CAP)
- pause_enab |= (B44_FLAG_TX_PAUSE |
- B44_FLAG_RX_PAUSE);
- else if (remote & LPA_PAUSE_ASYM)
- pause_enab |= B44_FLAG_RX_PAUSE;
- } else {
- if (remote & LPA_PAUSE_CAP)
- pause_enab |= (B44_FLAG_TX_PAUSE |
- B44_FLAG_RX_PAUSE);
- }
- } else if (local & ADVERTISE_PAUSE_ASYM) {
- if ((remote & LPA_PAUSE_CAP) &&
- (remote & LPA_PAUSE_ASYM))
- pause_enab |= B44_FLAG_TX_PAUSE;
+ /* The driver supports only rx pause by default because
+ the b44 mac tx pause mechanism generates excessive
+ pause frames.
+ Use ethtool to turn on b44 tx pause if necessary.
+ */
+ if ((local & ADVERTISE_PAUSE_CAP) &&
+ (local & ADVERTISE_PAUSE_ASYM)){
+ if ((remote & LPA_PAUSE_ASYM) &&
+ !(remote & LPA_PAUSE_CAP))
+ pause_enab |= B44_FLAG_RX_PAUSE;
}
__b44_set_flow_ctrl(bp, pause_enab);
@@ -608,8 +602,7 @@ static void b44_tx(struct b44 *bp)
struct ring_info *rp = &bp->tx_buffers[cons];
struct sk_buff *skb = rp->skb;
- if (unlikely(skb == NULL))
- BUG();
+ BUG_ON(skb == NULL);
pci_unmap_single(bp->pdev,
pci_unmap_addr(rp, mapping),
@@ -657,9 +650,11 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
/* Hardware bug work-around, the chip is unable to do PCI DMA
to/from anything above 1GB :-( */
- if (mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
+ if (dma_mapping_error(mapping) ||
+ mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
/* Sigh... */
- pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
+ if (!dma_mapping_error(mapping))
+ pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(skb);
skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
if (skb == NULL)
@@ -667,8 +662,10 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
mapping = pci_map_single(bp->pdev, skb->data,
RX_PKT_BUF_SZ,
PCI_DMA_FROMDEVICE);
- if (mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
- pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
+ if (dma_mapping_error(mapping) ||
+ mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
+ if (!dma_mapping_error(mapping))
+ pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(skb);
return -ENOMEM;
}
@@ -974,9 +971,10 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
- if (mapping + len > B44_DMA_MASK) {
+ if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
- pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
+ if (!dma_mapping_error(mapping))
+ pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
GFP_ATOMIC|GFP_DMA);
@@ -985,8 +983,9 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
mapping = pci_map_single(bp->pdev, bounce_skb->data,
len, PCI_DMA_TODEVICE);
- if (mapping + len > B44_DMA_MASK) {
- pci_unmap_single(bp->pdev, mapping,
+ if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
+ if (!dma_mapping_error(mapping))
+ pci_unmap_single(bp->pdev, mapping,
len, PCI_DMA_TODEVICE);
dev_kfree_skb_any(bounce_skb);
goto err_out;
@@ -1064,7 +1063,7 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu)
spin_unlock_irq(&bp->lock);
b44_enable_ints(bp);
-
+
return 0;
}
@@ -1210,7 +1209,8 @@ static int b44_alloc_consistent(struct b44 *bp)
DMA_TABLE_BYTES,
DMA_BIDIRECTIONAL);
- if (rx_ring_dma + size > B44_DMA_MASK) {
+ if (dma_mapping_error(rx_ring_dma) ||
+ rx_ring_dma + size > B44_DMA_MASK) {
kfree(rx_ring);
goto out_err;
}
@@ -1236,7 +1236,8 @@ static int b44_alloc_consistent(struct b44 *bp)
DMA_TABLE_BYTES,
DMA_TO_DEVICE);
- if (tx_ring_dma + size > B44_DMA_MASK) {
+ if (dma_mapping_error(tx_ring_dma) ||
+ tx_ring_dma + size > B44_DMA_MASK) {
kfree(tx_ring);
goto out_err;
}
@@ -1339,6 +1340,9 @@ static int b44_set_mac_addr(struct net_device *dev, void *p)
if (netif_running(dev))
return -EBUSY;
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EINVAL;
+
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
spin_lock_irq(&bp->lock);
@@ -1379,7 +1383,7 @@ static void b44_init_hw(struct b44 *bp)
bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
bw32(bp, B44_DMARX_PTR, bp->rx_pending);
- bp->rx_prod = bp->rx_pending;
+ bp->rx_prod = bp->rx_pending;
bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
@@ -1551,9 +1555,9 @@ static void __b44_set_rx_mode(struct net_device *dev)
val |= RXCONFIG_ALLMULTI;
else
i = __b44_load_mcast(bp, dev);
-
+
for (; i < 64; i++) {
- __b44_cam_write(bp, zero, i);
+ __b44_cam_write(bp, zero, i);
}
bw32(bp, B44_RXCONFIG, val);
val = br32(bp, B44_CAM_CTRL);
@@ -1735,7 +1739,7 @@ static int b44_set_ringparam(struct net_device *dev,
spin_unlock_irq(&bp->lock);
b44_enable_ints(bp);
-
+
return 0;
}
@@ -1780,7 +1784,7 @@ static int b44_set_pauseparam(struct net_device *dev,
spin_unlock_irq(&bp->lock);
b44_enable_ints(bp);
-
+
return 0;
}
@@ -1876,6 +1880,12 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp->dev->dev_addr[3] = eeprom[80];
bp->dev->dev_addr[4] = eeprom[83];
bp->dev->dev_addr[5] = eeprom[82];
+
+ if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){
+ printk(KERN_ERR PFX "Invalid MAC address found in EEPROM\n");
+ return -EINVAL;
+ }
+
memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
bp->phy_addr = eeprom[90] & 0x1f;
@@ -1890,7 +1900,7 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp->core_unit = ssb_core_unit(bp);
bp->dma_offset = SB_PCI_DMA;
- /* XXX - really required?
+ /* XXX - really required?
bp->flags |= B44_FLAG_BUGGY_TXPTR;
*/
out:
@@ -1938,7 +1948,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
"aborting.\n");
goto err_out_free_res;
}
-
+
err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
if (err) {
printk(KERN_ERR PFX "No usable DMA configuration, "
@@ -2033,6 +2043,11 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
pci_save_state(bp->pdev);
+ /* Chip reset provides power to the b44 MAC & PCI cores, which
+ * is necessary for MAC register access.
+ */
+ b44_chip_reset(bp);
+
printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i],
@@ -2078,10 +2093,10 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
del_timer_sync(&bp->timer);
- spin_lock_irq(&bp->lock);
+ spin_lock_irq(&bp->lock);
b44_halt(bp);
- netif_carrier_off(bp->dev);
+ netif_carrier_off(bp->dev);
netif_device_detach(bp->dev);
b44_free_rings(bp);
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 2671da20a49..54161aef3ca 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -55,15 +55,15 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.4.39"
-#define DRV_MODULE_RELDATE "March 22, 2006"
+#define DRV_MODULE_VERSION "1.4.40"
+#define DRV_MODULE_RELDATE "May 22, 2006"
#define RUN_AT(x) (jiffies + (x))
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT (5*HZ)
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
"Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
@@ -2945,7 +2945,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
int buf_size)
{
u32 written, offset32, len32;
- u8 *buf, start[4], end[4];
+ u8 *buf, start[4], end[4], *flash_buffer = NULL;
int rc = 0;
int align_start, align_end;
@@ -2985,12 +2985,19 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
memcpy(buf + align_start, data_buf, buf_size);
}
+ if (bp->flash_info->buffered == 0) {
+ flash_buffer = kmalloc(264, GFP_KERNEL);
+ if (flash_buffer == NULL) {
+ rc = -ENOMEM;
+ goto nvram_write_end;
+ }
+ }
+
written = 0;
while ((written < len32) && (rc == 0)) {
u32 page_start, page_end, data_start, data_end;
u32 addr, cmd_flags;
int i;
- u8 flash_buffer[264];
/* Find the page_start addr */
page_start = offset32 + written;
@@ -3061,7 +3068,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
}
/* Loop to write the new data from data_start to data_end */
- for (addr = data_start; addr < data_end; addr += 4, i++) {
+ for (addr = data_start; addr < data_end; addr += 4, i += 4) {
if ((addr == page_end - 4) ||
((bp->flash_info->buffered) &&
(addr == data_end - 4))) {
@@ -3109,6 +3116,9 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
}
nvram_write_end:
+ if (bp->flash_info->buffered == 0)
+ kfree(flash_buffer);
+
if (align_start || align_end)
kfree(buf);
return rc;
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index f3f5825469d..6a407070c2e 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2294,6 +2294,34 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
port->sm_vars |= AD_PORT_BEGIN;
}
+/*
+ * set link state for bonding master: if we have an active partnered
+ * aggregator, we're up, if not, we're down. Presumes that we cannot
+ * have an active aggregator if there are no slaves with link up.
+ *
+ * Called by bond_set_carrier(). Return zero if carrier state does not
+ * change, nonzero if it does.
+ */
+int bond_3ad_set_carrier(struct bonding *bond)
+{
+ struct aggregator *agg;
+
+ agg = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator));
+ if (agg && MAC_ADDRESS_COMPARE(&agg->partner_system, &null_mac_addr)) {
+ if (!netif_carrier_ok(bond->dev)) {
+ netif_carrier_on(bond->dev);
+ return 1;
+ }
+ return 0;
+ }
+
+ if (netif_carrier_ok(bond->dev)) {
+ netif_carrier_off(bond->dev);
+ return 1;
+ }
+ return 0;
+}
+
/**
* bond_3ad_get_active_agg_info - get information of the active aggregator
* @bond: bonding struct to work on
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 5ee2cef5b03..6ad5ad6e65d 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -283,5 +283,6 @@ void bond_3ad_handle_link_change(struct slave *slave, char link);
int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev);
+int bond_3ad_set_carrier(struct bonding *bond);
#endif //__BOND_3AD_H__
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 2d0ac169a86..55d236726d1 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -559,6 +559,42 @@ out:
/*------------------------------- Link status -------------------------------*/
/*
+ * Set the carrier state for the master according to the state of its
+ * slaves. If any slaves are up, the master is up. In 802.3ad mode,
+ * do special 802.3ad magic.
+ *
+ * Returns zero if carrier state does not change, nonzero if it does.
+ */
+static int bond_set_carrier(struct bonding *bond)
+{
+ struct slave *slave;
+ int i;
+
+ if (bond->slave_cnt == 0)
+ goto down;
+
+ if (bond->params.mode == BOND_MODE_8023AD)
+ return bond_3ad_set_carrier(bond);
+
+ bond_for_each_slave(bond, slave, i) {
+ if (slave->link == BOND_LINK_UP) {
+ if (!netif_carrier_ok(bond->dev)) {
+ netif_carrier_on(bond->dev);
+ return 1;
+ }
+ return 0;
+ }
+ }
+
+down:
+ if (netif_carrier_ok(bond->dev)) {
+ netif_carrier_off(bond->dev);
+ return 1;
+ }
+ return 0;
+}
+
+/*
* Get link speed and duplex from the slave's base driver
* using ethtool. If for some reason the call fails or the
* values are invalid, fake speed and duplex to 100/Full
@@ -1074,10 +1110,24 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
void bond_select_active_slave(struct bonding *bond)
{
struct slave *best_slave;
+ int rv;
best_slave = bond_find_best_slave(bond);
if (best_slave != bond->curr_active_slave) {
bond_change_active_slave(bond, best_slave);
+ rv = bond_set_carrier(bond);
+ if (!rv)
+ return;
+
+ if (netif_carrier_ok(bond->dev)) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: first active interface up!\n",
+ bond->dev->name);
+ } else {
+ printk(KERN_INFO DRV_NAME ": %s: "
+ "now running without any active interface !\n",
+ bond->dev->name);
+ }
}
}
@@ -1458,10 +1508,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
if (((!bond->curr_active_slave) ||
(bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) &&
(new_slave->link != BOND_LINK_DOWN)) {
- dprintk("This is the first active slave\n");
/* first slave or no active slave yet, and this link
is OK, so make this interface the active one */
bond_change_active_slave(bond, new_slave);
+ printk(KERN_INFO DRV_NAME
+ ": %s: first active interface up!\n",
+ bond->dev->name);
+ netif_carrier_on(bond->dev);
+
} else {
dprintk("This is just a backup slave\n");
bond_set_slave_inactive_flags(new_slave);
@@ -1517,6 +1571,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
break;
} /* switch(bond_mode) */
+ bond_set_carrier(bond);
+
write_unlock_bh(&bond->lock);
res = bond_create_slave_symlinks(bond_dev, slave_dev);
@@ -1656,18 +1712,12 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
bond_alb_deinit_slave(bond, slave);
}
- if (oldcurrent == slave) {
+ if (oldcurrent == slave)
bond_select_active_slave(bond);
- if (!bond->curr_active_slave) {
- printk(KERN_INFO DRV_NAME
- ": %s: now running without any active "
- "interface !\n",
- bond_dev->name);
- }
- }
-
if (bond->slave_cnt == 0) {
+ bond_set_carrier(bond);
+
/* if the last slave was removed, zero the mac address
* of the master so it will be set by the application
* to the mac address of the first slave
@@ -1751,6 +1801,8 @@ static int bond_release_all(struct net_device *bond_dev)
write_lock_bh(&bond->lock);
+ netif_carrier_off(bond_dev);
+
if (bond->slave_cnt == 0) {
goto out;
}
@@ -2187,15 +2239,9 @@ void bond_mii_monitor(struct net_device *bond_dev)
bond_select_active_slave(bond);
- if (oldcurrent && !bond->curr_active_slave) {
- printk(KERN_INFO DRV_NAME
- ": %s: now running without any active "
- "interface !\n",
- bond_dev->name);
- }
-
write_unlock(&bond->curr_slave_lock);
- }
+ } else
+ bond_set_carrier(bond);
re_arm:
if (bond->params.miimon) {
@@ -2499,13 +2545,6 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev)
bond_select_active_slave(bond);
- if (oldcurrent && !bond->curr_active_slave) {
- printk(KERN_INFO DRV_NAME
- ": %s: now running without any active "
- "interface !\n",
- bond_dev->name);
- }
-
write_unlock(&bond->curr_slave_lock);
}
@@ -2579,12 +2618,15 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
bond->current_arp_slave = NULL;
}
+ bond_set_carrier(bond);
+
if (slave == bond->curr_active_slave) {
printk(KERN_INFO DRV_NAME
": %s: %s is up and now the "
"active interface\n",
bond_dev->name,
slave->dev->name);
+ netif_carrier_on(bond->dev);
} else {
printk(KERN_INFO DRV_NAME
": %s: backup interface %s is "
@@ -2844,7 +2886,8 @@ static void bond_info_show_master(struct seq_file *seq)
(curr) ? curr->dev->name : "None");
}
- seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down");
+ seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ?
+ "up" : "down");
seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon);
seq_printf(seq, "Up Delay (ms): %d\n",
bond->params.updelay * bond->params.miimon);
@@ -3159,7 +3202,7 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
* bond_netdev_event: handle netdev notifier chain events.
*
* This function receives events for the netdev chain. The caller (an
- * ioctl handler calling notifier_call_chain) holds the necessary
+ * ioctl handler calling blocking_notifier_call_chain) holds the necessary
* locks for us to safely manipulate the slave devices (RTNL lock,
* dev_probe_lock).
*/
@@ -4531,6 +4574,8 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond
if (newbond)
*newbond = bond_dev->priv;
+ netif_carrier_off(bond_dev);
+
rtnl_unlock(); /* allows sysfs registration of net device */
res = bond_create_sysfs_entry(bond_dev->priv);
goto done;
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index ce9dc9b4e2d..0bdfe2c7145 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -22,8 +22,8 @@
#include "bond_3ad.h"
#include "bond_alb.h"
-#define DRV_VERSION "3.0.2"
-#define DRV_RELDATE "February 21, 2006"
+#define DRV_VERSION "3.0.3"
+#define DRV_RELDATE "March 23, 2006"
#define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
diff --git a/drivers/net/chelsio/Makefile b/drivers/net/chelsio/Makefile
index 91e927827c4..54c78d94f48 100644
--- a/drivers/net/chelsio/Makefile
+++ b/drivers/net/chelsio/Makefile
@@ -4,7 +4,7 @@
obj-$(CONFIG_CHELSIO_T1) += cxgb.o
-EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/chelsio $(DEBUG_FLAGS)
+EXTRA_CFLAGS += -Idrivers/net/chelsio $(DEBUG_FLAGS)
cxgb-objs := cxgb2.o espi.o pm3393.o sge.o subr.o mv88x201x.o
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 30ff8ea1a40..4391bf4bf57 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1093,8 +1093,7 @@ static int process_responses(struct adapter *adapter, int budget)
if (likely(e->DataValid)) {
struct freelQ *fl = &sge->freelQ[e->FreelistQid];
- if (unlikely(!e->Sop || !e->Eop))
- BUG();
+ BUG_ON(!e->Sop || !e->Eop);
if (unlikely(e->Offload))
unexpected_offload(adapter, fl);
else
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 1f3627470c9..038447fb5c5 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -53,6 +53,7 @@
#define DRV_VERSION "v1.17b"
#define DRV_RELDATE "2006/03/10"
#include "dl2k.h"
+#include <linux/dma-mapping.h>
static char version[] __devinitdata =
KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n";
@@ -765,7 +766,7 @@ rio_free_tx (struct net_device *dev, int irq)
break;
skb = np->tx_skbuff[entry];
pci_unmap_single (np->pdev,
- np->tx_ring[entry].fraginfo & 0xffffffffffff,
+ np->tx_ring[entry].fraginfo & DMA_48BIT_MASK,
skb->len, PCI_DMA_TODEVICE);
if (irq)
dev_kfree_skb_irq (skb);
@@ -893,7 +894,7 @@ receive_packet (struct net_device *dev)
/* Small skbuffs for short packets */
if (pkt_len > copy_thresh) {
pci_unmap_single (np->pdev,
- desc->fraginfo & 0xffffffffffff,
+ desc->fraginfo & DMA_48BIT_MASK,
np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
skb_put (skb = np->rx_skbuff[entry], pkt_len);
@@ -901,7 +902,7 @@ receive_packet (struct net_device *dev)
} else if ((skb = dev_alloc_skb (pkt_len + 2)) != NULL) {
pci_dma_sync_single_for_cpu(np->pdev,
desc->fraginfo &
- 0xffffffffffff,
+ DMA_48BIT_MASK,
np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
skb->dev = dev;
@@ -913,7 +914,7 @@ receive_packet (struct net_device *dev)
skb_put (skb, pkt_len);
pci_dma_sync_single_for_device(np->pdev,
desc->fraginfo &
- 0xffffffffffff,
+ DMA_48BIT_MASK,
np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
}
@@ -1800,7 +1801,7 @@ rio_close (struct net_device *dev)
skb = np->rx_skbuff[i];
if (skb) {
pci_unmap_single(np->pdev,
- np->rx_ring[i].fraginfo & 0xffffffffffff,
+ np->rx_ring[i].fraginfo & DMA_48BIT_MASK,
skb->len, PCI_DMA_FROMDEVICE);
dev_kfree_skb (skb);
np->rx_skbuff[i] = NULL;
@@ -1810,7 +1811,7 @@ rio_close (struct net_device *dev)
skb = np->tx_skbuff[i];
if (skb) {
pci_unmap_single(np->pdev,
- np->tx_ring[i].fraginfo & 0xffffffffffff,
+ np->tx_ring[i].fraginfo & DMA_48BIT_MASK,
skb->len, PCI_DMA_TODEVICE);
dev_kfree_skb (skb);
np->tx_skbuff[i] = NULL;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index ecccca35c6f..d1c705b412c 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -870,13 +870,16 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
*data = 0;
/* Hook up test interrupt handler just for this test */
- if (!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
+ if (!request_irq(irq, &e1000_test_intr, SA_PROBEIRQ, netdev->name,
+ netdev)) {
shared_int = FALSE;
} else if (request_irq(irq, &e1000_test_intr, SA_SHIRQ,
netdev->name, netdev)){
*data = 1;
return -1;
}
+ DPRINTK(PROBE,INFO, "testing %s interrupt\n",
+ (shared_int ? "shared" : "unshared"));
/* Disable all the interrupts */
E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 49cd096a3c3..97e71a4fe8e 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -220,6 +220,7 @@ static void e1000_restore_vlan(struct e1000_adapter *adapter);
static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
static int e1000_resume(struct pci_dev *pdev);
#endif
+static void e1000_shutdown(struct pci_dev *pdev);
#ifdef CONFIG_NET_POLL_CONTROLLER
/* for netdump / net console */
@@ -235,8 +236,9 @@ static struct pci_driver e1000_driver = {
/* Power Managment Hooks */
#ifdef CONFIG_PM
.suspend = e1000_suspend,
- .resume = e1000_resume
+ .resume = e1000_resume,
#endif
+ .shutdown = e1000_shutdown
};
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
@@ -3308,8 +3310,7 @@ e1000_clean(struct net_device *poll_dev, int *budget)
while (poll_dev != &adapter->polling_netdev[i]) {
i++;
- if (unlikely(i == adapter->num_rx_queues))
- BUG();
+ BUG_ON(i == adapter->num_rx_queues);
}
if (likely(adapter->num_tx_queues == 1)) {
@@ -3518,7 +3519,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
buffer_info = &rx_ring->buffer_info[i];
while (rx_desc->status & E1000_RXD_STAT_DD) {
- struct sk_buff *skb, *next_skb;
+ struct sk_buff *skb;
u8 status;
#ifdef CONFIG_E1000_NAPI
if (*work_done >= work_to_do)
@@ -3536,8 +3537,6 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
prefetch(next_rxd);
next_buffer = &rx_ring->buffer_info[i];
- next_skb = next_buffer->skb;
- prefetch(next_skb->data - NET_IP_ALIGN);
cleaned = TRUE;
cleaned_count++;
@@ -3667,7 +3666,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info, *next_buffer;
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
- struct sk_buff *skb, *next_skb;
+ struct sk_buff *skb;
unsigned int i, j;
uint32_t length, staterr;
int cleaned_count = 0;
@@ -3696,8 +3695,6 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
prefetch(next_rxd);
next_buffer = &rx_ring->buffer_info[i];
- next_skb = next_buffer->skb;
- prefetch(next_skb->data - NET_IP_ALIGN);
cleaned = TRUE;
cleaned_count++;
@@ -3769,6 +3766,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
ps_page->ps_page[j] = NULL;
skb->len += length;
skb->data_len += length;
+ skb->truesize += length;
}
copydone:
@@ -4611,6 +4609,12 @@ e1000_resume(struct pci_dev *pdev)
return 0;
}
#endif
+
+static void e1000_shutdown(struct pci_dev *pdev)
+{
+ e1000_suspend(pdev, PMSG_SUSPEND);
+}
+
#ifdef CONFIG_NET_POLL_CONTROLLER
/*
* Polling 'interrupt' - used by things like netconsole to send skbs
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index aa1569182fd..815436c6170 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -203,8 +203,7 @@ static int eql_open(struct net_device *dev)
printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on "
"your slave devices.\n", dev->name);
- if (!list_empty(&eql->queue.all_slaves))
- BUG();
+ BUG_ON(!list_empty(&eql->queue.all_slaves));
eql->min_slaves = 1;
eql->max_slaves = EQL_DEFAULT_MAX_SLAVES; /* 4 usually... */
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index e7fc28b07e5..feb5b223cd6 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -105,6 +105,8 @@
* 0.50: 20 Jan 2006: Add 8021pq tagging support.
* 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings.
* 0.52: 20 Jan 2006: Add MSI/MSIX support.
+ * 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset.
+ * 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -116,7 +118,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
-#define FORCEDETH_VERSION "0.52"
+#define FORCEDETH_VERSION "0.54"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -134,6 +136,7 @@
#include <linux/random.h>
#include <linux/init.h>
#include <linux/if_vlan.h>
+#include <linux/dma-mapping.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -159,6 +162,7 @@
#define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */
#define DEV_HAS_MSI 0x0040 /* device supports MSI */
#define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */
+#define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */
enum {
NvRegIrqStatus = 0x000,
@@ -202,6 +206,8 @@ enum {
#define NVREG_MISC1_HD 0x02
#define NVREG_MISC1_FORCE 0x3b0f3c
+ NvRegMacReset = 0x3c,
+#define NVREG_MAC_RESET_ASSERT 0x0F3
NvRegTransmitterControl = 0x084,
#define NVREG_XMITCTL_START 0x01
NvRegTransmitterStatus = 0x088,
@@ -325,6 +331,10 @@ enum {
NvRegMSIXMap0 = 0x3e0,
NvRegMSIXMap1 = 0x3e4,
NvRegMSIXIrqStatus = 0x3f0,
+
+ NvRegPowerState2 = 0x600,
+#define NVREG_POWERSTATE2_POWERUP_MASK 0x0F11
+#define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001
};
/* Big endian: should work, but is untested */
@@ -413,7 +423,8 @@ typedef union _ring_type {
#define NV_RX3_VLAN_TAG_MASK (0x0000FFFF)
/* Miscelaneous hardware related defines: */
-#define NV_PCI_REGSZ 0x270
+#define NV_PCI_REGSZ_VER1 0x270
+#define NV_PCI_REGSZ_VER2 0x604
/* various timeout delays: all in usec */
#define NV_TXRX_RESET_DELAY 4
@@ -430,6 +441,7 @@ typedef union _ring_type {
#define NV_MIIBUSY_DELAY 50
#define NV_MIIPHY_DELAY 10
#define NV_MIIPHY_DELAYMAX 10000
+#define NV_MAC_RESET_DELAY 64
#define NV_WAKEUPPATTERNS 5
#define NV_WAKEUPMASKENTRIES 4
@@ -551,6 +563,8 @@ struct fe_priv {
u32 desc_ver;
u32 txrxctl_bits;
u32 vlanctl_bits;
+ u32 driver_data;
+ u32 register_size;
void __iomem *base;
@@ -697,6 +711,72 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
}
}
+static int using_multi_irqs(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+
+ if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
+ ((np->msi_flags & NV_MSI_X_ENABLED) &&
+ ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1)))
+ return 0;
+ else
+ return 1;
+}
+
+static void nv_enable_irq(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ enable_irq(dev->irq);
+ } else {
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+ }
+}
+
+static void nv_disable_irq(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ disable_irq(dev->irq);
+ } else {
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+ }
+}
+
+/* In MSIX mode, a write to irqmask behaves as XOR */
+static void nv_enable_hw_interrupts(struct net_device *dev, u32 mask)
+{
+ u8 __iomem *base = get_hwbase(dev);
+
+ writel(mask, base + NvRegIrqMask);
+}
+
+static void nv_disable_hw_interrupts(struct net_device *dev, u32 mask)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+
+ if (np->msi_flags & NV_MSI_X_ENABLED) {
+ writel(mask, base + NvRegIrqMask);
+ } else {
+ if (np->msi_flags & NV_MSI_ENABLED)
+ writel(0, base + NvRegMSIIrqMask);
+ writel(0, base + NvRegIrqMask);
+ }
+}
+
#define MII_READ (-1)
/* mii_rw: read/write a register on the PHY.
*
@@ -918,6 +998,24 @@ static void nv_txrx_reset(struct net_device *dev)
pci_push(base);
}
+static void nv_mac_reset(struct net_device *dev)
+{
+ struct fe_priv *np = netdev_priv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+
+ dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name);
+ writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
+ pci_push(base);
+ writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset);
+ pci_push(base);
+ udelay(NV_MAC_RESET_DELAY);
+ writel(0, base + NvRegMacReset);
+ pci_push(base);
+ udelay(NV_MAC_RESET_DELAY);
+ writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl);
+ pci_push(base);
+}
+
/*
* nv_get_stats: dev->get_stats function
* Get latest stats value from the nic.
@@ -988,24 +1086,25 @@ static void nv_do_rx_refill(unsigned long data)
struct net_device *dev = (struct net_device *) data;
struct fe_priv *np = netdev_priv(dev);
-
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- disable_irq(dev->irq);
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ disable_irq(dev->irq);
} else {
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
}
if (nv_alloc_rx(dev)) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
}
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- enable_irq(dev->irq);
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ enable_irq(dev->irq);
} else {
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
}
@@ -1330,7 +1429,7 @@ static void nv_tx_timeout(struct net_device *dev)
dev->name, (unsigned long)np->ring_addr,
np->next_tx, np->nic_tx);
printk(KERN_INFO "%s: Dumping tx registers\n", dev->name);
- for (i=0;i<0x400;i+= 32) {
+ for (i=0;i<=np->register_size;i+= 32) {
printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
i,
readl(base + i + 0), readl(base + i + 4),
@@ -1637,15 +1736,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
* guessed, there is probably a simpler approach.
* Changing the MTU is a rare event, it shouldn't matter.
*/
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- disable_irq(dev->irq);
- } else {
- disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
- disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
- disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
- }
+ nv_disable_irq(dev);
spin_lock_bh(&dev->xmit_lock);
spin_lock(&np->lock);
/* stop engines */
@@ -1678,15 +1769,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
nv_start_tx(dev);
spin_unlock(&np->lock);
spin_unlock_bh(&dev->xmit_lock);
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- enable_irq(dev->irq);
- } else {
- enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
- enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
- enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
- }
+ nv_enable_irq(dev);
}
return 0;
}
@@ -2077,16 +2160,16 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
if (!(events & np->irqmask))
break;
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
nv_tx_done(dev);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
if (events & (NVREG_IRQ_TX_ERR)) {
dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
dev->name, events);
}
if (i > max_interrupt_work) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
/* disable interrupts on the nic */
writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask);
pci_push(base);
@@ -2096,7 +2179,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
}
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
break;
}
@@ -2126,14 +2209,14 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
nv_rx_process(dev);
if (nv_alloc_rx(dev)) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
}
if (i > max_interrupt_work) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
/* disable interrupts on the nic */
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
pci_push(base);
@@ -2143,7 +2226,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
}
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
break;
}
@@ -2172,14 +2255,14 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
break;
if (events & NVREG_IRQ_LINK) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
nv_link_irq(dev);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
}
if (np->need_linktimer && time_after(jiffies, np->link_timeout)) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
nv_linkchange(dev);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
np->link_timeout = jiffies + LINK_TIMEOUT;
}
if (events & (NVREG_IRQ_UNKNOWN)) {
@@ -2187,7 +2270,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
dev->name, events);
}
if (i > max_interrupt_work) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
/* disable interrupts on the nic */
writel(NVREG_IRQ_OTHER, base + NvRegIrqMask);
pci_push(base);
@@ -2197,7 +2280,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
}
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
break;
}
@@ -2220,10 +2303,11 @@ static void nv_do_nic_poll(unsigned long data)
* nv_nic_irq because that may decide to do otherwise
*/
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- disable_irq(dev->irq);
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ disable_irq(dev->irq);
mask = np->irqmask;
} else {
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
@@ -2246,11 +2330,12 @@ static void nv_do_nic_poll(unsigned long data)
writel(mask, base + NvRegIrqMask);
pci_push(base);
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
+ if (!using_multi_irqs(dev)) {
nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL);
- enable_irq(dev->irq);
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ enable_irq(dev->irq);
} else {
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
nv_nic_irq_rx((int) 0, (void *) data, (struct pt_regs *) NULL);
@@ -2487,11 +2572,11 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
}
#define FORCEDETH_REGS_VER 1
-#define FORCEDETH_REGS_SIZE 0x400 /* 256 32-bit registers */
static int nv_get_regs_len(struct net_device *dev)
{
- return FORCEDETH_REGS_SIZE;
+ struct fe_priv *np = netdev_priv(dev);
+ return np->register_size;
}
static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
@@ -2503,7 +2588,7 @@ static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void
regs->version = FORCEDETH_REGS_VER;
spin_lock_irq(&np->lock);
- for (i=0;i<FORCEDETH_REGS_SIZE/sizeof(u32);i++)
+ for (i = 0;i <= np->register_size/sizeof(u32); i++)
rbuf[i] = readl(base + i*sizeof(u32));
spin_unlock_irq(&np->lock);
}
@@ -2530,6 +2615,18 @@ static int nv_nway_reset(struct net_device *dev)
return ret;
}
+#ifdef NETIF_F_TSO
+static int nv_set_tso(struct net_device *dev, u32 value)
+{
+ struct fe_priv *np = netdev_priv(dev);
+
+ if ((np->driver_data & DEV_HAS_CHECKSUM))
+ return ethtool_op_set_tso(dev, value);
+ else
+ return value ? -EOPNOTSUPP : 0;
+}
+#endif
+
static struct ethtool_ops ops = {
.get_drvinfo = nv_get_drvinfo,
.get_link = ethtool_op_get_link,
@@ -2541,6 +2638,10 @@ static struct ethtool_ops ops = {
.get_regs = nv_get_regs,
.nway_reset = nv_nway_reset,
.get_perm_addr = ethtool_op_get_perm_addr,
+#ifdef NETIF_F_TSO
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = nv_set_tso
+#endif
};
static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
@@ -2597,6 +2698,113 @@ static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask)
writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1);
}
+static int nv_request_irq(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+ int ret = 1;
+ int i;
+
+ if (np->msi_flags & NV_MSI_X_CAPABLE) {
+ for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+ np->msi_x_entry[i].entry = i;
+ }
+ if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) {
+ np->msi_flags |= NV_MSI_X_ENABLED;
+ if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) {
+ /* Request irq for rx handling */
+ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret);
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ goto out_err;
+ }
+ /* Request irq for tx handling */
+ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret);
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ goto out_free_rx;
+ }
+ /* Request irq for link and timer handling */
+ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret);
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ goto out_free_tx;
+ }
+ /* map interrupts to their respective vector */
+ writel(0, base + NvRegMSIXMap0);
+ writel(0, base + NvRegMSIXMap1);
+ set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL);
+ set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL);
+ set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER);
+ } else {
+ /* Request irq for all interrupts */
+ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ goto out_err;
+ }
+
+ /* map interrupts to vector 0 */
+ writel(0, base + NvRegMSIXMap0);
+ writel(0, base + NvRegMSIXMap1);
+ }
+ }
+ }
+ if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
+ if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
+ np->msi_flags |= NV_MSI_ENABLED;
+ if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+ pci_disable_msi(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_ENABLED;
+ goto out_err;
+ }
+
+ /* map interrupts to vector 0 */
+ writel(0, base + NvRegMSIMap0);
+ writel(0, base + NvRegMSIMap1);
+ /* enable msi vector 0 */
+ writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
+ }
+ }
+ if (ret != 0) {
+ if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0)
+ goto out_err;
+ }
+
+ return 0;
+out_free_tx:
+ free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev);
+out_free_rx:
+ free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev);
+out_err:
+ return 1;
+}
+
+static void nv_free_irq(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ int i;
+
+ if (np->msi_flags & NV_MSI_X_ENABLED) {
+ for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+ free_irq(np->msi_x_entry[i].vector, dev);
+ }
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ } else {
+ free_irq(np->pci_dev->irq, dev);
+ if (np->msi_flags & NV_MSI_ENABLED) {
+ pci_disable_msi(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_ENABLED;
+ }
+ }
+}
+
static int nv_open(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
@@ -2607,6 +2815,8 @@ static int nv_open(struct net_device *dev)
dprintk(KERN_DEBUG "nv_open: begin\n");
/* 1) erase previous misconfiguration */
+ if (np->driver_data & DEV_HAS_POWER_CNTRL)
+ nv_mac_reset(dev);
/* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */
writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
writel(0, base + NvRegMulticastAddrB);
@@ -2687,86 +2897,18 @@ static int nv_open(struct net_device *dev)
udelay(10);
writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState);
- writel(0, base + NvRegIrqMask);
+ nv_disable_hw_interrupts(dev, np->irqmask);
pci_push(base);
writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
pci_push(base);
- if (np->msi_flags & NV_MSI_X_CAPABLE) {
- for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
- np->msi_x_entry[i].entry = i;
- }
- if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) {
- np->msi_flags |= NV_MSI_X_ENABLED;
- if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) {
- /* Request irq for rx handling */
- if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) {
- printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret);
- pci_disable_msix(np->pci_dev);
- np->msi_flags &= ~NV_MSI_X_ENABLED;
- goto out_drain;
- }
- /* Request irq for tx handling */
- if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) {
- printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret);
- pci_disable_msix(np->pci_dev);
- np->msi_flags &= ~NV_MSI_X_ENABLED;
- goto out_drain;
- }
- /* Request irq for link and timer handling */
- if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) {
- printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret);
- pci_disable_msix(np->pci_dev);
- np->msi_flags &= ~NV_MSI_X_ENABLED;
- goto out_drain;
- }
-
- /* map interrupts to their respective vector */
- writel(0, base + NvRegMSIXMap0);
- writel(0, base + NvRegMSIXMap1);
- set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL);
- set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL);
- set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER);
- } else {
- /* Request irq for all interrupts */
- if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
- printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
- pci_disable_msix(np->pci_dev);
- np->msi_flags &= ~NV_MSI_X_ENABLED;
- goto out_drain;
- }
-
- /* map interrupts to vector 0 */
- writel(0, base + NvRegMSIXMap0);
- writel(0, base + NvRegMSIXMap1);
- }
- }
- }
- if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
- if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
- np->msi_flags |= NV_MSI_ENABLED;
- if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
- printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
- pci_disable_msi(np->pci_dev);
- np->msi_flags &= ~NV_MSI_ENABLED;
- goto out_drain;
- }
-
- /* map interrupts to vector 0 */
- writel(0, base + NvRegMSIMap0);
- writel(0, base + NvRegMSIMap1);
- /* enable msi vector 0 */
- writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
- }
- }
- if (ret != 0) {
- if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0)
- goto out_drain;
+ if (nv_request_irq(dev)) {
+ goto out_drain;
}
/* ask for interrupts */
- writel(np->irqmask, base + NvRegIrqMask);
+ nv_enable_hw_interrupts(dev, np->irqmask);
spin_lock_irq(&np->lock);
writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
@@ -2810,7 +2952,6 @@ static int nv_close(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base;
- int i;
spin_lock_irq(&np->lock);
np->in_shutdown = 1;
@@ -2828,31 +2969,13 @@ static int nv_close(struct net_device *dev)
/* disable interrupts on the nic or we will lock up */
base = get_hwbase(dev);
- if (np->msi_flags & NV_MSI_X_ENABLED) {
- writel(np->irqmask, base + NvRegIrqMask);
- } else {
- if (np->msi_flags & NV_MSI_ENABLED)
- writel(0, base + NvRegMSIIrqMask);
- writel(0, base + NvRegIrqMask);
- }
+ nv_disable_hw_interrupts(dev, np->irqmask);
pci_push(base);
dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name);
spin_unlock_irq(&np->lock);
- if (np->msi_flags & NV_MSI_X_ENABLED) {
- for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
- free_irq(np->msi_x_entry[i].vector, dev);
- }
- pci_disable_msix(np->pci_dev);
- np->msi_flags &= ~NV_MSI_X_ENABLED;
- } else {
- free_irq(np->pci_dev->irq, dev);
- if (np->msi_flags & NV_MSI_ENABLED) {
- pci_disable_msi(np->pci_dev);
- np->msi_flags &= ~NV_MSI_ENABLED;
- }
- }
+ nv_free_irq(dev);
drain_ring(dev);
@@ -2877,6 +3000,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
unsigned long addr;
u8 __iomem *base;
int err, i;
+ u32 powerstate;
dev = alloc_etherdev(sizeof(struct fe_priv));
err = -ENOMEM;
@@ -2909,6 +3033,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (err < 0)
goto out_disable;
+ if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL))
+ np->register_size = NV_PCI_REGSZ_VER2;
+ else
+ np->register_size = NV_PCI_REGSZ_VER1;
+
err = -EINVAL;
addr = 0;
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
@@ -2917,7 +3046,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
pci_resource_len(pci_dev, i),
pci_resource_flags(pci_dev, i));
if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM &&
- pci_resource_len(pci_dev, i) >= NV_PCI_REGSZ) {
+ pci_resource_len(pci_dev, i) >= np->register_size) {
addr = pci_resource_start(pci_dev, i);
break;
}
@@ -2928,24 +3057,25 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
goto out_relreg;
}
+ /* copy of driver data */
+ np->driver_data = id->driver_data;
+
/* handle different descriptor versions */
if (id->driver_data & DEV_HAS_HIGH_DMA) {
/* packet format 3: supports 40-bit addressing */
np->desc_ver = DESC_VER_3;
- if (pci_set_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
+ np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
+ if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) {
printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
pci_name(pci_dev));
} else {
- if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
- printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n",
- pci_name(pci_dev));
- goto out_relreg;
- } else {
- dev->features |= NETIF_F_HIGHDMA;
- printk(KERN_INFO "forcedeth: using HIGHDMA\n");
- }
+ dev->features |= NETIF_F_HIGHDMA;
+ printk(KERN_INFO "forcedeth: using HIGHDMA\n");
+ }
+ if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
+ printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n",
+ pci_name(pci_dev));
}
- np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
} else if (id->driver_data & DEV_HAS_LARGEDESC) {
/* packet format 2: supports jumbo frames */
np->desc_ver = DESC_VER_2;
@@ -2985,7 +3115,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
}
err = -ENOMEM;
- np->base = ioremap(addr, NV_PCI_REGSZ);
+ np->base = ioremap(addr, np->register_size);
if (!np->base)
goto out_relreg;
dev->base_addr = (unsigned long)np->base;
@@ -3061,6 +3191,20 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
writel(0, base + NvRegWakeUpFlags);
np->wolenabled = 0;
+ if (id->driver_data & DEV_HAS_POWER_CNTRL) {
+ u8 revision_id;
+ pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id);
+
+ /* take phy and nic out of low power mode */
+ powerstate = readl(base + NvRegPowerState2);
+ powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK;
+ if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 ||
+ id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) &&
+ revision_id >= 0xA3)
+ powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
+ writel(powerstate, base + NvRegPowerState2);
+ }
+
if (np->desc_ver == DESC_VER_1) {
np->tx_flags = NV_TX_VALID;
} else {
@@ -3222,19 +3366,19 @@ static struct pci_device_id pci_tbl[] = {
},
{ /* MCP51 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL,
},
{ /* MCP51 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL,
},
{ /* MCP55 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL,
},
{ /* MCP55 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL,
},
{0,},
};
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 771e25d8c41..218d31764c5 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -210,7 +210,8 @@ static int gfar_probe(struct platform_device *pdev)
goto regs_fail;
}
- spin_lock_init(&priv->lock);
+ spin_lock_init(&priv->txlock);
+ spin_lock_init(&priv->rxlock);
platform_set_drvdata(pdev, dev);
@@ -515,11 +516,13 @@ void stop_gfar(struct net_device *dev)
phy_stop(priv->phydev);
/* Lock it down */
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
gfar_halt(dev);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
/* Free the IRQs */
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
@@ -605,14 +608,15 @@ void gfar_start(struct net_device *dev)
tempval |= DMACTRL_INIT_SETTINGS;
gfar_write(&priv->regs->dmactrl, tempval);
- /* Clear THLT, so that the DMA starts polling now */
- gfar_write(&regs->tstat, TSTAT_CLEAR_THALT);
-
/* Make sure we aren't stopped */
tempval = gfar_read(&priv->regs->dmactrl);
tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
gfar_write(&priv->regs->dmactrl, tempval);
+ /* Clear THLT/RHLT, so that the DMA starts polling now */
+ gfar_write(&regs->tstat, TSTAT_CLEAR_THALT);
+ gfar_write(&regs->rstat, RSTAT_CLEAR_RHALT);
+
/* Unmask the interrupts we look for */
gfar_write(&regs->imask, IMASK_DEFAULT);
}
@@ -928,12 +932,13 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct txfcb *fcb = NULL;
struct txbd8 *txbdp;
u16 status;
+ unsigned long flags;
/* Update transmit stats */
priv->stats.tx_bytes += skb->len;
/* Lock priv now */
- spin_lock_irq(&priv->lock);
+ spin_lock_irqsave(&priv->txlock, flags);
/* Point at the first free tx descriptor */
txbdp = priv->cur_tx;
@@ -1004,7 +1009,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
/* Unlock priv */
- spin_unlock_irq(&priv->lock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
return 0;
}
@@ -1049,7 +1054,7 @@ static void gfar_vlan_rx_register(struct net_device *dev,
unsigned long flags;
u32 tempval;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->rxlock, flags);
priv->vlgrp = grp;
@@ -1076,7 +1081,7 @@ static void gfar_vlan_rx_register(struct net_device *dev,
gfar_write(&priv->regs->rctrl, tempval);
}
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
}
@@ -1085,12 +1090,12 @@ static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
struct gfar_private *priv = netdev_priv(dev);
unsigned long flags;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->rxlock, flags);
if (priv->vlgrp)
priv->vlgrp->vlan_devices[vid] = NULL;
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
}
@@ -1179,7 +1184,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs)
gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
/* Lock priv */
- spin_lock(&priv->lock);
+ spin_lock(&priv->txlock);
bdp = priv->dirty_tx;
while ((bdp->status & TXBD_READY) == 0) {
/* If dirty_tx and cur_tx are the same, then either the */
@@ -1224,7 +1229,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs)
else
gfar_write(&priv->regs->txic, 0);
- spin_unlock(&priv->lock);
+ spin_unlock(&priv->txlock);
return IRQ_HANDLED;
}
@@ -1305,9 +1310,10 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
struct gfar_private *priv = netdev_priv(dev);
-
#ifdef CONFIG_GFAR_NAPI
u32 tempval;
+#else
+ unsigned long flags;
#endif
/* Clear IEVENT, so rx interrupt isn't called again
@@ -1330,7 +1336,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
}
#else
- spin_lock(&priv->lock);
+ spin_lock_irqsave(&priv->rxlock, flags);
gfar_clean_rx_ring(dev, priv->rx_ring_size);
/* If we are coalescing interrupts, update the timer */
@@ -1341,7 +1347,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
else
gfar_write(&priv->regs->rxic, 0);
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
#endif
return IRQ_HANDLED;
@@ -1490,13 +1496,6 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
/* Update the current rxbd pointer to be the next one */
priv->cur_rx = bdp;
- /* If no packets have arrived since the
- * last one we processed, clear the IEVENT RX and
- * BSY bits so that another interrupt won't be
- * generated when we set IMASK */
- if (bdp->status & RXBD_EMPTY)
- gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
-
return howmany;
}
@@ -1516,7 +1515,7 @@ static int gfar_poll(struct net_device *dev, int *budget)
rx_work_limit -= howmany;
*budget -= howmany;
- if (rx_work_limit >= 0) {
+ if (rx_work_limit > 0) {
netif_rx_complete(dev);
/* Clear the halt bit in RSTAT */
@@ -1533,7 +1532,8 @@ static int gfar_poll(struct net_device *dev, int *budget)
gfar_write(&priv->regs->rxic, 0);
}
- return (rx_work_limit < 0) ? 1 : 0;
+ /* Return 1 if there's more work to do */
+ return (rx_work_limit > 0) ? 0 : 1;
}
#endif
@@ -1629,7 +1629,7 @@ static void adjust_link(struct net_device *dev)
struct phy_device *phydev = priv->phydev;
int new_state = 0;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
if (phydev->link) {
u32 tempval = gfar_read(&regs->maccfg2);
u32 ecntrl = gfar_read(&regs->ecntrl);
@@ -1694,7 +1694,7 @@ static void adjust_link(struct net_device *dev)
if (new_state && netif_msg_link(priv))
phy_print_status(phydev);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->txlock, flags);
}
/* Update the hash table based on the current list of multicast
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index d37d5401be6..127c98cf333 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -656,43 +656,62 @@ struct gfar {
* the buffer descriptor determines the actual condition.
*/
struct gfar_private {
- /* pointers to arrays of skbuffs for tx and rx */
+ /* Fields controlled by TX lock */
+ spinlock_t txlock;
+
+ /* Pointer to the array of skbuffs */
struct sk_buff ** tx_skbuff;
- struct sk_buff ** rx_skbuff;
- /* indices pointing to the next free sbk in skb arrays */
+ /* next free skb in the array */
u16 skb_curtx;
- u16 skb_currx;
- /* index of the first skb which hasn't been transmitted
- * yet. */
+ /* First skb in line to be transmitted */
u16 skb_dirtytx;
/* Configuration info for the coalescing features */
unsigned char txcoalescing;
unsigned short txcount;
unsigned short txtime;
+
+ /* Buffer descriptor pointers */
+ struct txbd8 *tx_bd_base; /* First tx buffer descriptor */
+ struct txbd8 *cur_tx; /* Next free ring entry */
+ struct txbd8 *dirty_tx; /* First buffer in line
+ to be transmitted */
+ unsigned int tx_ring_size;
+
+ /* RX Locked fields */
+ spinlock_t rxlock;
+
+ /* skb array and index */
+ struct sk_buff ** rx_skbuff;
+ u16 skb_currx;
+
+ /* RX Coalescing values */
unsigned char rxcoalescing;
unsigned short rxcount;
unsigned short rxtime;
- /* GFAR addresses */
- struct rxbd8 *rx_bd_base; /* Base addresses of Rx and Tx Buffers */
- struct txbd8 *tx_bd_base;
+ struct rxbd8 *rx_bd_base; /* First Rx buffers */
struct rxbd8 *cur_rx; /* Next free rx ring entry */
- struct txbd8 *cur_tx; /* Next free ring entry */
- struct txbd8 *dirty_tx; /* The Ring entry to be freed. */
- struct gfar __iomem *regs; /* Pointer to the GFAR memory mapped Registers */
- u32 __iomem *hash_regs[16];
- int hash_width;
- struct net_device_stats stats; /* linux network statistics */
- struct gfar_extra_stats extra_stats;
- spinlock_t lock;
+
+ /* RX parameters */
+ unsigned int rx_ring_size;
unsigned int rx_buffer_size;
unsigned int rx_stash_size;
unsigned int rx_stash_index;
- unsigned int tx_ring_size;
- unsigned int rx_ring_size;
+
+ struct vlan_group *vlgrp;
+
+ /* Unprotected fields */
+ /* Pointer to the GFAR memory mapped Registers */
+ struct gfar __iomem *regs;
+
+ /* Hash registers and their width */
+ u32 __iomem *hash_regs[16];
+ int hash_width;
+
+ /* global parameters */
unsigned int fifo_threshold;
unsigned int fifo_starve;
unsigned int fifo_starve_off;
@@ -702,13 +721,15 @@ struct gfar_private {
extended_hash:1,
bd_stash_en:1;
unsigned short padding;
- struct vlan_group *vlgrp;
- /* Info structure initialized by board setup code */
+
unsigned int interruptTransmit;
unsigned int interruptReceive;
unsigned int interruptError;
+
+ /* info structure initialized by platform code */
struct gianfar_platform_data *einfo;
+ /* PHY stuff */
struct phy_device *phydev;
struct mii_bus *mii_bus;
int oldspeed;
@@ -716,6 +737,10 @@ struct gfar_private {
int oldlink;
uint32_t msg_enable;
+
+ /* Network Statistics */
+ struct net_device_stats stats;
+ struct gfar_extra_stats extra_stats;
};
static inline u32 gfar_read(volatile unsigned __iomem *addr)
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 5de7b2e259d..d69698c695e 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -455,10 +455,14 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
/* Halt TX and RX, and process the frames which
* have already been received */
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
gfar_halt(dev);
gfar_clean_rx_ring(dev, priv->rx_ring_size);
- spin_unlock_irqrestore(&priv->lock, flags);
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
/* Now we take down the rings to rebuild them */
stop_gfar(dev);
@@ -488,10 +492,14 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
/* Halt TX and RX, and process the frames which
* have already been received */
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
gfar_halt(dev);
gfar_clean_rx_ring(dev, priv->rx_ring_size);
- spin_unlock_irqrestore(&priv->lock, flags);
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
/* Now we take down the rings to rebuild them */
stop_gfar(dev);
@@ -523,7 +531,7 @@ static int gfar_set_tx_csum(struct net_device *dev, uint32_t data)
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return -EOPNOTSUPP;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
gfar_halt(dev);
if (data)
@@ -532,7 +540,7 @@ static int gfar_set_tx_csum(struct net_device *dev, uint32_t data)
dev->features &= ~NETIF_F_IP_CSUM;
gfar_start(dev);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->txlock, flags);
return 0;
}
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c
index 51ef181b136..a6d5c43199c 100644
--- a/drivers/net/gianfar_sysfs.c
+++ b/drivers/net/gianfar_sysfs.c
@@ -82,7 +82,7 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev,
else
return count;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->rxlock, flags);
/* Set the new stashing value */
priv->bd_stash_en = new_setting;
@@ -96,7 +96,7 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev,
gfar_write(&priv->regs->attr, temp);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
return count;
}
@@ -118,7 +118,7 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
u32 temp;
unsigned long flags;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->rxlock, flags);
if (length > priv->rx_buffer_size)
return count;
@@ -142,7 +142,7 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
gfar_write(&priv->regs->attr, temp);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
return count;
}
@@ -166,7 +166,7 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
u32 temp;
unsigned long flags;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->rxlock, flags);
if (index > priv->rx_stash_size)
return count;
@@ -180,7 +180,7 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
temp |= ATTRELI_EI(index);
gfar_write(&priv->regs->attreli, flags);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->rxlock, flags);
return count;
}
@@ -205,7 +205,7 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
if (length > GFAR_MAX_FIFO_THRESHOLD)
return count;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
priv->fifo_threshold = length;
@@ -214,7 +214,7 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
temp |= length;
gfar_write(&priv->regs->fifo_tx_thr, temp);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->txlock, flags);
return count;
}
@@ -240,7 +240,7 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
if (num > GFAR_MAX_FIFO_STARVE)
return count;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
priv->fifo_starve = num;
@@ -249,7 +249,7 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
temp |= num;
gfar_write(&priv->regs->fifo_tx_starve, temp);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->txlock, flags);
return count;
}
@@ -274,7 +274,7 @@ static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev,
if (num > GFAR_MAX_FIFO_STARVE_OFF)
return count;
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->txlock, flags);
priv->fifo_starve_off = num;
@@ -283,7 +283,7 @@ static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev,
temp |= num;
gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->txlock, flags);
return count;
}
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index 79a8fbcf5f9..0d5fccc984b 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -582,7 +582,6 @@ static int __init setup_adapter(int card_base, int type, int n)
INIT_WORK(&priv->rx_work, rx_bh, priv);
dev->priv = priv;
sprintf(dev->name, "dmascc%i", 2 * n + i);
- SET_MODULE_OWNER(dev);
dev->base_addr = card_base;
dev->irq = irq;
dev->open = scc_open;
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 6ace0e914fd..5927784df3f 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1550,7 +1550,6 @@ static unsigned char ax25_nocall[AX25_ADDR_LEN] =
static void scc_net_setup(struct net_device *dev)
{
- SET_MODULE_OWNER(dev);
dev->tx_queue_len = 16; /* should be enough... */
dev->open = scc_net_open;
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index fe22479eb20..b49884048ca 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -1098,7 +1098,6 @@ static void yam_setup(struct net_device *dev)
dev->base_addr = yp->iobase;
dev->irq = yp->irq;
- SET_MODULE_OWNER(dev);
dev->open = yam_open;
dev->stop = yam_close;
diff --git a/drivers/net/hydra.h b/drivers/net/hydra.h
deleted file mode 100644
index 37414146258..00000000000
--- a/drivers/net/hydra.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/* $Linux: hydra.h,v 1.0 1994/10/26 02:03:47 cgd Exp $ */
-
-/*
- * Copyright (c) 1994 Timo Rossi
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Timo Rossi
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * The Hydra Systems card uses the National Semiconductor
- * 8390 NIC (Network Interface Controller) chip, located
- * at card base address + 0xffe1. NIC registers are accessible
- * only at odd byte addresses, so the register offsets must
- * be multiplied by two.
- *
- * Card address PROM is located at card base + 0xffc0 (even byte addresses)
- *
- * RAM starts at the card base address, and is 16K or 64K.
- * The current Amiga NetBSD hydra driver is hardwired for 16K.
- * It seems that the RAM should be accessed as words or longwords only.
- *
- */
-
-/* adapted for Linux by Topi Kanerva 03/29/95
- with original author's permission */
-
-#define HYDRA_NIC_BASE 0xffe1
-
-/* Page0 registers */
-
-#define NIC_CR 0 /* Command register */
-#define NIC_PSTART (1*2) /* Page start (write) */
-#define NIC_PSTOP (2*2) /* Page stop (write) */
-#define NIC_BNDRY (3*2) /* Boundary pointer */
-#define NIC_TSR (4*2) /* Transmit status (read) */
-#define NIC_TPSR (4*2) /* Transmit page start (write) */
-#define NIC_NCR (5*2) /* Number of collisions, read */
-#define NIC_TBCR0 (5*2) /* Transmit byte count low (write) */
-#define NIC_FIFO (6*2) /* FIFO reg. (read) */
-#define NIC_TBCR1 (6*2) /* Transmit byte count high (write) */
-#define NIC_ISR (7*2) /* Interrupt status register */
-#define NIC_RBCR0 (0xa*2) /* Remote byte count low (write) */
-#define NIC_RBCR1 (0xb*2) /* Remote byte count high (write) */
-#define NIC_RSR (0xc*2) /* Receive status (read) */
-#define NIC_RCR (0xc*2) /* Receive config (write) */
-#define NIC_CNTR0 (0xd*2) /* Frame alignment error count (read) */
-#define NIC_TCR (0xd*2) /* Transmit config (write) */
-#define NIC_CNTR1 (0xe*2) /* CRC error counter (read) */
-#define NIC_DCR (0xe*2) /* Data config (write) */
-#define NIC_CNTR2 (0xf*2) /* missed packet counter (read) */
-#define NIC_IMR (0xf*2) /* Interrupt mask reg. (write) */
-
-/* Page1 registers */
-
-#define NIC_PAR0 (1*2) /* Physical address */
-#define NIC_PAR1 (2*2)
-#define NIC_PAR2 (3*2)
-#define NIC_PAR3 (4*2)
-#define NIC_PAR4 (5*2)
-#define NIC_PAR5 (6*2)
-#define NIC_CURR (7*2) /* Current RX ring-buffer page */
-#define NIC_MAR0 (8*2) /* Multicast address */
-#define NIC_MAR1 (9*2)
-#define NIC_MAR2 (0xa*2)
-#define NIC_MAR3 (0xb*2)
-#define NIC_MAR4 (0xc*2)
-#define NIC_MAR5 (0xd*2)
-#define NIC_MAR6 (0xe*2)
-#define NIC_MAR7 (0xf*2)
-
-/* Command register definitions */
-
-#define CR_STOP 0x01 /* Stop -- software reset command */
-#define CR_START 0x02 /* Start */
-#define CR_TXP 0x04 /* Transmit packet */
-
-#define CR_RD0 0x08 /* Remote DMA cmd */
-#define CR_RD1 0x10
-#define CR_RD2 0x20
-
-#define CR_NODMA CR_RD2
-
-#define CR_PS0 0x40 /* Page select */
-#define CR_PS1 0x80
-
-#define CR_PAGE0 0
-#define CR_PAGE1 CR_PS0
-#define CR_PAGE2 CR_PS1
-
-/* Interrupt status reg. definitions */
-
-#define ISR_PRX 0x01 /* Packet received without errors */
-#define ISR_PTX 0x02 /* Packet transmitted without errors */
-#define ISR_RXE 0x04 /* Receive error */
-#define ISR_TXE 0x08 /* Transmit error */
-#define ISR_OVW 0x10 /* Ring buffer overrun */
-#define ISR_CNT 0x20 /* Counter overflow */
-#define ISR_RDC 0x40 /* Remote DMA compile */
-#define ISR_RST 0x80 /* Reset status */
-
-/* Data config reg. definitions */
-
-#define DCR_WTS 0x01 /* Word transfer select */
-#define DCR_BOS 0x02 /* Byte order select */
-#define DCR_LAS 0x04 /* Long address select */
-#define DCR_LS 0x08 /* Loopback select */
-#define DCR_AR 0x10 /* Auto-init remote */
-#define DCR_FT0 0x20 /* FIFO threshold select */
-#define DCR_FT1 0x40
-
-/* Transmit config reg. definitions */
-
-#define TCR_CRC 0x01 /* Inhibit CRC */
-#define TCR_LB0 0x02 /* Loopback control */
-#define TCR_LB1 0x04
-#define TCR_ATD 0x08 /* Auto transmit disable */
-#define TCR_OFST 0x10 /* Collision offset enable */
-
-/* Transmit status reg. definitions */
-
-#define TSR_PTX 0x01 /* Packet transmitted */
-#define TSR_COL 0x04 /* Transmit collided */
-#define TSR_ABT 0x08 /* Transmit aborted */
-#define TSR_CRS 0x10 /* Carrier sense lost */
-#define TSR_FU 0x20 /* FIFO underrun */
-#define TSR_CDH 0x40 /* CD Heartbeat */
-#define TSR_OWC 0x80 /* Out of Window Collision */
-
-/* Receiver config register definitions */
-
-#define RCR_SEP 0x01 /* Save errored packets */
-#define RCR_AR 0x02 /* Accept runt packets */
-#define RCR_AB 0x04 /* Accept broadcast */
-#define RCR_AM 0x08 /* Accept multicast */
-#define RCR_PRO 0x10 /* Promiscuous mode */
-#define RCR_MON 0x20 /* Monitor mode */
-
-/* Receiver status register definitions */
-
-#define RSR_PRX 0x01 /* Packet received without error */
-#define RSR_CRC 0x02 /* CRC error */
-#define RSR_FAE 0x04 /* Frame alignment error */
-#define RSR_FO 0x08 /* FIFO overrun */
-#define RSR_MPA 0x10 /* Missed packet */
-#define RSR_PHY 0x20 /* Physical address */
-#define RSR_DIS 0x40 /* Received disabled */
-#define RSR_DFR 0x80 /* Deferring (jabber) */
-
-/* Hydra System card address PROM offset */
-
-#define HYDRA_ADDRPROM 0xffc0
-
-
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index ceb98fd398a..52d01027d9e 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -235,7 +235,7 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
pool->free_map[free_index] = index;
pool->skbuff[index] = NULL;
pool->consumer_index--;
@@ -373,7 +373,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc);
ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
}
@@ -511,7 +511,7 @@ static int ibmveth_open(struct net_device *netdev)
adapter->filter_list_dma,
mac_address);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
ibmveth_error_printk("buffer TCE:0x%lx filter TCE:0x%lx rxq desc:0x%lx MAC:0x%lx\n",
adapter->buffer_list_dma,
@@ -527,7 +527,7 @@ static int ibmveth_open(struct net_device *netdev)
ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc);
do {
rc = h_free_logical_lan(adapter->vdev->unit_address);
- } while (H_isLongBusy(rc) || (rc == H_Busy));
+ } while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY));
ibmveth_cleanup(adapter);
return rc;
@@ -556,9 +556,9 @@ static int ibmveth_close(struct net_device *netdev)
do {
lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
- } while (H_isLongBusy(lpar_rc) || (lpar_rc == H_Busy));
+ } while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));
- if(lpar_rc != H_Success)
+ if(lpar_rc != H_SUCCESS)
{
ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n",
lpar_rc);
@@ -693,9 +693,9 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
desc[4].desc,
desc[5].desc,
correlator);
- } while ((lpar_rc == H_Busy) && (retry_count--));
+ } while ((lpar_rc == H_BUSY) && (retry_count--));
- if(lpar_rc != H_Success && lpar_rc != H_Dropped) {
+ if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
int i;
ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
for(i = 0; i < 6; i++) {
@@ -786,14 +786,14 @@ static int ibmveth_poll(struct net_device *netdev, int *budget)
/* we think we are done - reenable interrupts, then check once more to make sure we are done */
lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_ENABLE);
- ibmveth_assert(lpar_rc == H_Success);
+ ibmveth_assert(lpar_rc == H_SUCCESS);
netif_rx_complete(netdev);
if(ibmveth_rxq_pending_buffer(adapter) && netif_rx_reschedule(netdev, frames_processed))
{
lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
- ibmveth_assert(lpar_rc == H_Success);
+ ibmveth_assert(lpar_rc == H_SUCCESS);
more_work = 1;
goto restart_poll;
}
@@ -813,7 +813,7 @@ static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs
if(netif_rx_schedule_prep(netdev)) {
lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
- ibmveth_assert(lpar_rc == H_Success);
+ ibmveth_assert(lpar_rc == H_SUCCESS);
__netif_rx_schedule(netdev);
}
return IRQ_HANDLED;
@@ -835,7 +835,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
IbmVethMcastEnableRecv |
IbmVethMcastDisableFiltering,
0);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc);
}
} else {
@@ -847,7 +847,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
IbmVethMcastDisableFiltering |
IbmVethMcastClearFilterTable,
0);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc);
}
/* add the addresses to the filter table */
@@ -858,7 +858,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
IbmVethMcastAddFilter,
mcast_addr);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc);
}
}
@@ -867,7 +867,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
IbmVethMcastEnableFiltering,
0);
- if(lpar_rc != H_Success) {
+ if(lpar_rc != H_SUCCESS) {
ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc);
}
}
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 9b8295ee06e..ae71ed57c12 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -44,6 +44,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
+#include <linux/dma-mapping.h>
#ifdef CONFIG_SERIAL_8250
#include <linux/serial_core.h>
@@ -1195,17 +1196,17 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int err, pci_using_dac;
/* Configure DMA attributes. */
- err = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+ err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
if (!err) {
pci_using_dac = 1;
- err = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
if (err < 0) {
printk(KERN_ERR "%s: Unable to obtain 64 bit DMA "
"for consistent allocations\n", pci_name(pdev));
goto out;
}
} else {
- err = pci_set_dma_mask(pdev, 0xffffffffULL);
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
printk(KERN_ERR "%s: No usable DMA configuration, "
"aborting.\n", pci_name(pdev));
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 5e6d0075299..cff8598aa80 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -33,7 +33,7 @@ config DONGLE
config ESI_DONGLE
tristate "ESI JetEye PC dongle"
- depends on DONGLE && IRDA
+ depends on IRTTY_SIR && DONGLE && IRDA
help
Say Y here if you want to build support for the Extended Systems
JetEye PC dongle. To compile it as a module, choose M here. The ESI
@@ -44,7 +44,7 @@ config ESI_DONGLE
config ACTISYS_DONGLE
tristate "ACTiSYS IR-220L and IR220L+ dongle"
- depends on DONGLE && IRDA
+ depends on IRTTY_SIR && DONGLE && IRDA
help
Say Y here if you want to build support for the ACTiSYS IR-220L and
IR220L+ dongles. To compile it as a module, choose M here. The
@@ -55,7 +55,7 @@ config ACTISYS_DONGLE
config TEKRAM_DONGLE
tristate "Tekram IrMate 210B dongle"
- depends on DONGLE && IRDA
+ depends on IRTTY_SIR && DONGLE && IRDA
help
Say Y here if you want to build support for the Tekram IrMate 210B
dongle. To compile it as a module, choose M here. The Tekram dongle
@@ -66,7 +66,7 @@ config TEKRAM_DONGLE
config TOIM3232_DONGLE
tristate "TOIM3232 IrDa dongle"
- depends on DONGLE && IRDA
+ depends on IRTTY_SIR && DONGLE && IRDA
help
Say Y here if you want to build support for the Vishay/Temic
TOIM3232 and TOIM4232 based dongles.
@@ -74,7 +74,7 @@ config TOIM3232_DONGLE
config LITELINK_DONGLE
tristate "Parallax LiteLink dongle"
- depends on DONGLE && IRDA
+ depends on IRTTY_SIR && DONGLE && IRDA
help
Say Y here if you want to build support for the Parallax Litelink
dongle. To compile it as a module, choose M here. The Parallax
@@ -85,7 +85,7 @@ config LITELINK_DONGLE
config MA600_DONGLE
tristate "Mobile Action MA600 dongle"
- depends on DONGLE && IRDA && EXPERIMENTAL
+ depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Mobile Action MA600
dongle. To compile it as a module, choose M here. The MA600 dongle
@@ -98,7 +98,7 @@ config MA600_DONGLE
config GIRBIL_DONGLE
tristate "Greenwich GIrBIL dongle"
- depends on DONGLE && IRDA && EXPERIMENTAL
+ depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Greenwich GIrBIL
dongle. If you want to compile it as a module, choose M here.
@@ -109,7 +109,7 @@ config GIRBIL_DONGLE
config MCP2120_DONGLE
tristate "Microchip MCP2120"
- depends on DONGLE && IRDA && EXPERIMENTAL
+ depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Microchip MCP2120
dongle. If you want to compile it as a module, choose M here.
@@ -123,7 +123,7 @@ config MCP2120_DONGLE
config OLD_BELKIN_DONGLE
tristate "Old Belkin dongle"
- depends on DONGLE && IRDA && EXPERIMENTAL
+ depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Adaptec Airport 1000
and 2000 dongles. If you want to compile it as a module, choose
@@ -132,7 +132,7 @@ config OLD_BELKIN_DONGLE
config ACT200L_DONGLE
tristate "ACTiSYS IR-200L dongle"
- depends on DONGLE && IRDA && EXPERIMENTAL
+ depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the ACTiSYS IR-200L
dongle. If you want to compile it as a module, choose M here.
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index 27ab75f2079..c1ce2398efe 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -46,4 +46,4 @@ obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o
obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o
# The SIR helper module
-sir-dev-objs := sir_dev.o sir_dongle.o sir_kthread.o
+sir-dev-objs := sir_dev.o sir_dongle.o
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 6e2ec56cde0..cd87593e4e8 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1,7 +1,7 @@
/*****************************************************************************
*
* Filename: irda-usb.c
- * Version: 0.9b
+ * Version: 0.10
* Description: IrDA-USB Driver
* Status: Experimental
* Author: Dag Brattli <dag@brattli.net>
@@ -9,6 +9,9 @@
* Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
* Copyright (C) 2001, Dag Brattli <dag@brattli.net>
* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
+ * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com>
+ * Copyright (C) 2005, Milan Beno <beno@pobox.sk>
+ * Copyright (C) 2006, Nick Fedchik <nick@fedchik.org.ua>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -61,6 +64,7 @@
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/usb.h>
+#include <linux/firmware.h>
#include "irda-usb.h"
@@ -78,8 +82,12 @@ static struct usb_device_id dongles[] = {
{ USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
/* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */
{ USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
+ /* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */
+ { USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
+ { USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
+ { USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
- USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+ USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.bInterfaceClass = USB_CLASS_APP_SPEC,
.bInterfaceSubClass = USB_CLASS_IRDA,
.driver_info = IUC_DEFAULT, },
@@ -99,6 +107,7 @@ MODULE_DEVICE_TABLE(usb, dongles);
/*------------------------------------------------------------------*/
+static void irda_usb_init_qos(struct irda_usb_cb *self) ;
static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf);
static void irda_usb_disconnect(struct usb_interface *intf);
static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self);
@@ -141,7 +150,24 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
__u8 *header,
int force)
{
- /* Set the negotiated link speed */
+ /* Here we check if we have an STIR421x chip,
+ * and if either speed or xbofs (or both) needs
+ * to be changed.
+ */
+ if (self->capability & IUC_STIR_4210 &&
+ ((self->new_speed != -1) || (self->new_xbofs != -1))) {
+
+ /* With STIR421x, speed and xBOFs must be set at the same
+ * time, even if only one of them changes.
+ */
+ if (self->new_speed == -1)
+ self->new_speed = self->speed ;
+
+ if (self->new_xbofs == -1)
+ self->new_xbofs = self->xbofs ;
+ }
+
+ /* Set the link speed */
if (self->new_speed != -1) {
/* Hum... Ugly hack :-(
* Some device are not compliant with the spec and change
@@ -191,7 +217,11 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
*header = SPEED_4000000;
self->new_xbofs = 0;
break;
- }
+ case 16000000:
+ *header = SPEED_16000000;
+ self->new_xbofs = 0;
+ break;
+ }
} else
/* No change */
*header = 0;
@@ -235,6 +265,32 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
}
}
+/*
+* calculate turnaround time for SigmaTel header
+*/
+static __u8 get_turnaround_time(struct sk_buff *skb)
+{
+ int turnaround_time = irda_get_mtt(skb);
+
+ if ( turnaround_time == 0 )
+ return 0;
+ else if ( turnaround_time <= 10 )
+ return 1;
+ else if ( turnaround_time <= 50 )
+ return 2;
+ else if ( turnaround_time <= 100 )
+ return 3;
+ else if ( turnaround_time <= 500 )
+ return 4;
+ else if ( turnaround_time <= 1000 )
+ return 5;
+ else if ( turnaround_time <= 5000 )
+ return 6;
+ else
+ return 7;
+}
+
+
/*------------------------------------------------------------------*/
/*
* Send a command to change the speed of the dongle
@@ -262,12 +318,18 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
/* Set the new speed and xbofs in this fake frame */
irda_usb_build_header(self, frame, 1);
+ if ( self->capability & IUC_STIR_4210 ) {
+ if (frame[0] == 0) return ; // do nothing if no change
+ frame[1] = 0; // other parameters don't change here
+ frame[2] = 0;
+ }
+
/* Submit the 0 length IrDA frame to trigger new speed settings */
usb_fill_bulk_urb(urb, self->usbdev,
usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
frame, IRDA_USB_SPEED_MTU,
speed_bulk_callback, self);
- urb->transfer_buffer_length = USB_IRDA_HEADER;
+ urb->transfer_buffer_length = self->header_length;
urb->transfer_flags = 0;
/* Irq disabled -> GFP_ATOMIC */
@@ -383,16 +445,35 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
* allocation will be done lower in skb_push().
* Also, we don't use directly skb_cow(), because it require
* headroom >= 16, which force unnecessary copies - Jean II */
- if (skb_headroom(skb) < USB_IRDA_HEADER) {
+ if (skb_headroom(skb) < self->header_length) {
IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__);
- if (skb_cow(skb, USB_IRDA_HEADER)) {
+ if (skb_cow(skb, self->header_length)) {
IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__);
goto drop;
}
}
/* Change setting for next frame */
- irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0);
+
+ if ( self->capability & IUC_STIR_4210 ) {
+ __u8 turnaround_time;
+ __u8* frame;
+ turnaround_time = get_turnaround_time( skb );
+ frame= skb_push(skb, self->header_length);
+ irda_usb_build_header(self, frame, 0);
+ frame[2] = turnaround_time;
+ if ((skb->len != 0) &&
+ ((skb->len % 128) == 0) &&
+ ((skb->len % 512) != 0)) {
+ /* add extra byte for special SigmaTel feature */
+ frame[1] = 1;
+ skb_put(skb, 1);
+ } else {
+ frame[1] = 0;
+ }
+ } else {
+ irda_usb_build_header(self, skb_push(skb, self->header_length), 0);
+ }
/* FIXME: Make macro out of this one */
((struct irda_skb_cb *)skb->cb)->context = self;
@@ -795,7 +876,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
}
/* Check for empty frames */
- if (urb->actual_length <= USB_IRDA_HEADER) {
+ if (urb->actual_length <= self->header_length) {
IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__);
goto done;
}
@@ -816,7 +897,11 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD);
/* Allocate a new skb */
- newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
+ if ( self->capability & IUC_STIR_4210 )
+ newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU + USB_IRDA_SIGMATEL_HEADER);
+ else
+ newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
+
if (!newskb) {
self->stats.rx_dropped++;
/* We could deliver the current skb, but this would stall
@@ -845,7 +930,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
/* Set proper length on skb & remove USB-IrDA header */
skb_put(dataskb, urb->actual_length);
- skb_pull(dataskb, USB_IRDA_HEADER);
+ skb_pull(dataskb, self->header_length);
/* Ask the networking layer to queue the packet for the IrDA stack */
dataskb->dev = self->netdev;
@@ -937,6 +1022,191 @@ static int irda_usb_is_receiving(struct irda_usb_cb *self)
return 0; /* For now */
}
+
+#define STIR421X_PATCH_PRODUCT_VERSION_STR "Product Version: "
+#define STIR421X_PATCH_COMPONENT_VERSION_STR "Component Version: "
+#define STIR421X_PATCH_DATA_TAG_STR "STMP"
+#define STIR421X_PATCH_FILE_VERSION_MAX_OFFSET 512 /* version info is before here */
+#define STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET 512 /* patch image starts before here */
+#define STIR421X_PATCH_FILE_END_OF_HEADER_TAG 0x1A /* marks end of patch file header (PC DOS text file EOF character) */
+
+/*
+ * Known firmware patches for STIR421x dongles
+ */
+static char * stir421x_patches[] = {
+ "42101001.sb",
+ "42101002.sb",
+};
+
+static int stir421x_get_patch_version(unsigned char * patch, const unsigned long patch_len)
+{
+ unsigned int version_offset;
+ unsigned long version_major, version_minor, version_build;
+ unsigned char * version_start;
+ int version_found = 0;
+
+ for (version_offset = 0;
+ version_offset < STIR421X_PATCH_FILE_END_OF_HEADER_TAG;
+ version_offset++) {
+ if (!memcmp(patch + version_offset,
+ STIR421X_PATCH_PRODUCT_VERSION_STR,
+ sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1)) {
+ version_found = 1;
+ version_start = patch +
+ version_offset +
+ sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1;
+ break;
+ }
+ }
+
+ /* We couldn't find a product version on this patch */
+ if (!version_found)
+ return -EINVAL;
+
+ /* Let's check if the product version is dotted */
+ if (version_start[3] != '.' ||
+ version_start[7] != '.')
+ return -EINVAL;
+
+ version_major = simple_strtoul(version_start, NULL, 10);
+ version_minor = simple_strtoul(version_start + 4, NULL, 10);
+ version_build = simple_strtoul(version_start + 8, NULL, 10);
+
+ IRDA_DEBUG(2, "%s(), Major: %ld Minor: %ld Build: %ld\n",
+ __FUNCTION__,
+ version_major, version_minor, version_build);
+
+ return (((version_major) << 12) +
+ ((version_minor) << 8) +
+ ((version_build / 10) << 4) +
+ (version_build % 10));
+
+}
+
+
+static int stir421x_upload_patch (struct irda_usb_cb *self,
+ unsigned char * patch,
+ const unsigned int patch_len)
+{
+ int retval = 0;
+ int actual_len;
+ unsigned int i = 0, download_amount = 0;
+ unsigned char * patch_chunk;
+
+ IRDA_DEBUG (2, "%s(), Uploading STIR421x Patch\n", __FUNCTION__);
+
+ patch_chunk = kzalloc(STIR421X_MAX_PATCH_DOWNLOAD_SIZE, GFP_KERNEL);
+ if (patch_chunk == NULL)
+ return -ENOMEM;
+
+ /* break up patch into 1023-byte sections */
+ for (i = 0; retval >= 0 && i < patch_len; i += download_amount) {
+ download_amount = patch_len - i;
+ if (download_amount > STIR421X_MAX_PATCH_DOWNLOAD_SIZE)
+ download_amount = STIR421X_MAX_PATCH_DOWNLOAD_SIZE;
+
+ /* download the patch section */
+ memcpy(patch_chunk, patch + i, download_amount);
+
+ retval = usb_bulk_msg (self->usbdev,
+ usb_sndbulkpipe (self->usbdev,
+ self->bulk_out_ep),
+ patch_chunk, download_amount,
+ &actual_len, msecs_to_jiffies (500));
+ IRDA_DEBUG (2, "%s(), Sent %u bytes\n", __FUNCTION__,
+ actual_len);
+ if (retval == 0)
+ mdelay(10);
+ }
+
+ kfree(patch_chunk);
+
+ if (i != patch_len) {
+ IRDA_ERROR ("%s(), Pushed %d bytes (!= patch_len (%d))\n",
+ __FUNCTION__, i, patch_len);
+ retval = -EIO;
+ }
+
+ if (retval < 0)
+ /* todo - mark device as not ready */
+ IRDA_ERROR ("%s(), STIR421x patch upload failed (%d)\n",
+ __FUNCTION__, retval);
+
+ return retval;
+}
+
+
+static int stir421x_patch_device(struct irda_usb_cb *self)
+{
+ unsigned int i, patch_found = 0, data_found = 0, data_offset;
+ int patch_version, ret = 0;
+ const struct firmware *fw_entry;
+
+ for (i = 0; i < ARRAY_SIZE(stir421x_patches); i++) {
+ if(request_firmware(&fw_entry, stir421x_patches[i], &self->usbdev->dev) != 0) {
+ IRDA_ERROR( "%s(), Patch %s is not available\n", __FUNCTION__, stir421x_patches[i]);
+ continue;
+ }
+
+ /* We found a patch from userspace */
+ patch_version = stir421x_get_patch_version (fw_entry->data, fw_entry->size);
+
+ if (patch_version < 0) {
+ /* Couldn't fetch a version, let's move on to the next file */
+ IRDA_ERROR("%s(), version parsing failed\n", __FUNCTION__);
+ ret = patch_version;
+ release_firmware(fw_entry);
+ continue;
+ }
+
+ if (patch_version != self->usbdev->descriptor.bcdDevice) {
+ /* Patch version and device don't match */
+ IRDA_ERROR ("%s(), wrong patch version (%d <-> %d)\n",
+ __FUNCTION__,
+ patch_version, self->usbdev->descriptor.bcdDevice);
+ ret = -EINVAL;
+ release_firmware(fw_entry);
+ continue;
+ }
+
+ /* If we're here, we've found a correct patch */
+ patch_found = 1;
+ break;
+
+ }
+
+ /* We couldn't find a valid firmware, let's leave */
+ if (!patch_found)
+ return ret;
+
+ /* The actual image starts after the "STMP" keyword */
+ for (data_offset = 0; data_offset < STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET; data_offset++) {
+ if (!memcmp(fw_entry->data + data_offset,
+ STIR421X_PATCH_DATA_TAG_STR,
+ sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))) {
+ IRDA_DEBUG(2, "%s(), found patch data for STIR421x at offset %d\n",
+ __FUNCTION__, data_offset);
+ data_found = 1;
+ break;
+ }
+ }
+
+ /* We couldn't find "STMP" from the header */
+ if (!data_found)
+ return -EINVAL;
+
+ /* Let's upload the patch to the target */
+ ret = stir421x_upload_patch(self,
+ &fw_entry->data[data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)],
+ fw_entry->size - (data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)));
+
+ release_firmware(fw_entry);
+
+ return ret;
+
+}
+
+
/********************** IRDA DEVICE CALLBACKS **********************/
/*
* Main calls from the IrDA/Network subsystem.
@@ -972,6 +1242,11 @@ static int irda_usb_net_open(struct net_device *netdev)
return -1;
}
+ if(self->needspatch) {
+ IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ;
+ return -EIO ;
+ }
+
/* Initialise default speed and xbofs value
* (IrLAP will change that soon) */
self->speed = -1;
@@ -1050,7 +1325,7 @@ static int irda_usb_net_close(struct net_device *netdev)
del_timer(&self->rx_defer_timer);
/* Deallocate all the Rx path buffers (URBs and skb) */
- for (i = 0; i < IU_MAX_RX_URBS; i++) {
+ for (i = 0; i < self->max_rx_urb; i++) {
struct urb *urb = self->rx_urb[i];
struct sk_buff *skb = (struct sk_buff *) urb->context;
/* Cancel the receive command */
@@ -1426,8 +1701,22 @@ static int irda_usb_probe(struct usb_interface *intf,
spin_lock_init(&self->lock);
init_timer(&self->rx_defer_timer);
+ self->capability = id->driver_info;
+ self->needspatch = ((self->capability & IUC_STIR_4210) != 0) ;
+
/* Create all of the needed urbs */
- for (i = 0; i < IU_MAX_RX_URBS; i++) {
+ if (self->capability & IUC_STIR_4210) {
+ self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS;
+ self->header_length = USB_IRDA_SIGMATEL_HEADER;
+ } else {
+ self->max_rx_urb = IU_MAX_RX_URBS;
+ self->header_length = USB_IRDA_HEADER;
+ }
+
+ self->rx_urb = kzalloc(self->max_rx_urb * sizeof(struct urb *),
+ GFP_KERNEL);
+
+ for (i = 0; i < self->max_rx_urb; i++) {
self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
if (!self->rx_urb[i]) {
goto err_out_1;
@@ -1479,17 +1768,28 @@ static int irda_usb_probe(struct usb_interface *intf,
goto err_out_3;
}
+ self->usbdev = dev;
+
/* Find IrDA class descriptor */
irda_desc = irda_usb_find_class_desc(intf);
ret = -ENODEV;
if (irda_desc == NULL)
goto err_out_3;
+ if (self->needspatch) {
+ ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0),
+ 0x02, 0x40, 0, 0, NULL, 0, 500);
+ if (ret < 0) {
+ IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret);
+ goto err_out_3;
+ } else {
+ mdelay(10);
+ }
+ }
+
self->irda_desc = irda_desc;
self->present = 1;
self->netopen = 0;
- self->capability = id->driver_info;
- self->usbdev = dev;
self->usbintf = intf;
/* Allocate the buffer for speed changes */
@@ -1508,8 +1808,32 @@ static int irda_usb_probe(struct usb_interface *intf,
IRDA_MESSAGE("IrDA: Registered device %s\n", net->name);
usb_set_intfdata(intf, self);
+
+ if (self->needspatch) {
+ /* Now we fetch and upload the firmware patch */
+ ret = stir421x_patch_device(self);
+ self->needspatch = (ret < 0);
+ if (ret < 0) {
+ printk("patch_device failed\n");
+ goto err_out_5;
+ }
+
+ /* replace IrDA class descriptor with what patched device is now reporting */
+ irda_desc = irda_usb_find_class_desc (self->usbintf);
+ if (irda_desc == NULL) {
+ ret = -ENODEV;
+ goto err_out_5;
+ }
+ if (self->irda_desc)
+ kfree (self->irda_desc);
+ self->irda_desc = irda_desc;
+ irda_usb_init_qos(self);
+ }
+
return 0;
+err_out_5:
+ unregister_netdev(self->netdev);
err_out_4:
kfree(self->speed_buff);
err_out_3:
@@ -1518,7 +1842,7 @@ err_out_3:
err_out_2:
usb_free_urb(self->tx_urb);
err_out_1:
- for (i = 0; i < IU_MAX_RX_URBS; i++) {
+ for (i = 0; i < self->max_rx_urb; i++) {
if (self->rx_urb[i])
usb_free_urb(self->rx_urb[i]);
}
@@ -1571,7 +1895,7 @@ static void irda_usb_disconnect(struct usb_interface *intf)
/*netif_device_detach(self->netdev);*/
netif_stop_queue(self->netdev);
/* Stop all the receive URBs. Must be synchronous. */
- for (i = 0; i < IU_MAX_RX_URBS; i++)
+ for (i = 0; i < self->max_rx_urb; i++)
usb_kill_urb(self->rx_urb[i]);
/* Cancel Tx and speed URB.
* Make sure it's synchronous to avoid races. */
@@ -1586,8 +1910,9 @@ static void irda_usb_disconnect(struct usb_interface *intf)
self->usbintf = NULL;
/* Clean up our urbs */
- for (i = 0; i < IU_MAX_RX_URBS; i++)
+ for (i = 0; i < self->max_rx_urb; i++)
usb_free_urb(self->rx_urb[i]);
+ kfree(self->rx_urb);
/* Clean up Tx and speed URB */
usb_free_urb(self->tx_urb);
usb_free_urb(self->speed_urb);
@@ -1648,6 +1973,6 @@ module_exit(usb_irda_cleanup);
*/
module_param(qos_mtt_bits, int, 0);
MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
-MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net> and Jean Tourrilhes <jt@hpl.hp.com>");
-MODULE_DESCRIPTION("IrDA-USB Dongle Driver");
+MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net>, Jean Tourrilhes <jt@hpl.hp.com> and Nick Fedchik <nick@fedchik.org.ua>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h
index 4026af42dd4..d833db52ceb 100644
--- a/drivers/net/irda/irda-usb.h
+++ b/drivers/net/irda/irda-usb.h
@@ -1,7 +1,7 @@
/*****************************************************************************
*
* Filename: irda-usb.h
- * Version: 0.9b
+ * Version: 0.10
* Description: IrDA-USB Driver
* Status: Experimental
* Author: Dag Brattli <dag@brattli.net>
@@ -9,6 +9,9 @@
* Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at>
* Copyright (C) 2000, Dag Brattli <dag@brattli.net>
* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
+ * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com>
+ * Copyright (C) 2005, Milan Beno <beno@pobox.sk>
+ * Copyright (C) 2006, Nick FEdchik <nick@fedchik.org.ua>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,6 +34,9 @@
#include <net/irda/irda.h>
#include <net/irda/irda_device.h> /* struct irlap_cb */
+#define PATCH_FILE_SIZE_MAX 65536
+#define PATCH_FILE_SIZE_MIN 80
+
#define RX_COPY_THRESHOLD 200
#define IRDA_USB_MAX_MTU 2051
#define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */
@@ -79,15 +85,16 @@
/* Inbound header */
#define MEDIA_BUSY 0x80
-#define SPEED_2400 0x01
-#define SPEED_9600 0x02
-#define SPEED_19200 0x03
-#define SPEED_38400 0x04
-#define SPEED_57600 0x05
-#define SPEED_115200 0x06
-#define SPEED_576000 0x07
-#define SPEED_1152000 0x08
-#define SPEED_4000000 0x09
+#define SPEED_2400 0x01
+#define SPEED_9600 0x02
+#define SPEED_19200 0x03
+#define SPEED_38400 0x04
+#define SPEED_57600 0x05
+#define SPEED_115200 0x06
+#define SPEED_576000 0x07
+#define SPEED_1152000 0x08
+#define SPEED_4000000 0x09
+#define SPEED_16000000 0x0a
/* Basic capabilities */
#define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */
@@ -100,11 +107,14 @@
#define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */
#define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */
#define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */
+#define IUC_STIR_4210 0x80 /* SigmaTel 4210/4220/4116 VFIR */
/* USB class definitions */
-#define USB_IRDA_HEADER 0x01
-#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */
-#define USB_DT_IRDA 0x21
+#define USB_IRDA_HEADER 0x01
+#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */
+#define USB_DT_IRDA 0x21
+#define USB_IRDA_SIGMATEL_HEADER 0x03
+#define IU_SIGMATEL_MAX_RX_URBS (IU_MAX_ACTIVE_RX_URBS + USB_IRDA_SIGMATEL_HEADER)
struct irda_class_desc {
__u8 bLength;
@@ -123,6 +133,7 @@ struct irda_class_desc {
* (6.2.5, USB-IrDA class spec 1.0) */
#define IU_REQ_GET_CLASS_DESC 0x06
+#define STIR421X_MAX_PATCH_DOWNLOAD_SIZE 1023
struct irda_usb_cb {
struct irda_class_desc *irda_desc;
@@ -136,7 +147,8 @@ struct irda_usb_cb {
__u16 bulk_out_mtu; /* Max Tx packet size in bytes */
__u8 bulk_int_ep; /* Interrupt Endpoint assignments */
- struct urb *rx_urb[IU_MAX_RX_URBS]; /* URBs used to receive data frames */
+ __u8 max_rx_urb;
+ struct urb **rx_urb; /* URBs used to receive data frames */
struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */
struct urb *tx_urb; /* URB used to send data frames */
struct urb *speed_urb; /* URB used to send speed commands */
@@ -157,6 +169,9 @@ struct irda_usb_cb {
__u32 speed; /* Current speed */
__s32 new_speed; /* speed we need to set */
+ __u8 header_length; /* USB-IrDA frame header size */
+ int needspatch; /* device needs firmware patch */
+
struct timer_list rx_defer_timer; /* Wait for Rx error to clear */
};
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 83141a3ff54..cc7ff8f00e4 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -207,7 +207,7 @@ static int __init nsc_ircc_init(void)
/* Register with PnP subsystem to detect disable ports */
ret = pnp_register_driver(&nsc_ircc_pnp_driver);
- if (ret >= 0)
+ if (!ret)
pnp_registered = 1;
ret = -ENODEV;
@@ -812,7 +812,7 @@ static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info)
int cfg_base = info->cfg_base;
int enabled;
- /* User is shure about his config... accept it. */
+ /* User is sure about his config... accept it. */
IRDA_DEBUG(2, "%s(): nsc_ircc_init_39x (user settings): "
"io=0x%04x, irq=%d, dma=%d\n",
__FUNCTION__, info->fir_base, info->irq, info->dma);
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 63d38fbbd04..f530686bd09 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -695,8 +695,7 @@ static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
/*
* We must not be transmitting...
*/
- if (si->txskb)
- BUG();
+ BUG_ON(si->txskb);
netif_stop_queue(dev);
diff --git a/drivers/net/irda/sir-dev.h b/drivers/net/irda/sir-dev.h
index f69fb4cec76..9fa294a546d 100644
--- a/drivers/net/irda/sir-dev.h
+++ b/drivers/net/irda/sir-dev.h
@@ -15,23 +15,14 @@
#define IRDA_SIR_H
#include <linux/netdevice.h>
+#include <linux/workqueue.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h> // iobuff_t
-/* FIXME: unify irda_request with sir_fsm! */
-
-struct irda_request {
- struct list_head lh_request;
- unsigned long pending;
- void (*func)(void *);
- void *data;
- struct timer_list timer;
-};
-
struct sir_fsm {
struct semaphore sem;
- struct irda_request rq;
+ struct work_struct work;
unsigned state, substate;
int param;
int result;
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index ea7c9464d46..3b5854d10c1 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -23,6 +23,298 @@
#include "sir-dev.h"
+
+static struct workqueue_struct *irda_sir_wq;
+
+/* STATE MACHINE */
+
+/* substate handler of the config-fsm to handle the cases where we want
+ * to wait for transmit completion before changing the port configuration
+ */
+
+static int sirdev_tx_complete_fsm(struct sir_dev *dev)
+{
+ struct sir_fsm *fsm = &dev->fsm;
+ unsigned next_state, delay;
+ unsigned bytes_left;
+
+ do {
+ next_state = fsm->substate; /* default: stay in current substate */
+ delay = 0;
+
+ switch(fsm->substate) {
+
+ case SIRDEV_STATE_WAIT_XMIT:
+ if (dev->drv->chars_in_buffer)
+ bytes_left = dev->drv->chars_in_buffer(dev);
+ else
+ bytes_left = 0;
+ if (!bytes_left) {
+ next_state = SIRDEV_STATE_WAIT_UNTIL_SENT;
+ break;
+ }
+
+ if (dev->speed > 115200)
+ delay = (bytes_left*8*10000) / (dev->speed/100);
+ else if (dev->speed > 0)
+ delay = (bytes_left*10*10000) / (dev->speed/100);
+ else
+ delay = 0;
+ /* expected delay (usec) until remaining bytes are sent */
+ if (delay < 100) {
+ udelay(delay);
+ delay = 0;
+ break;
+ }
+ /* sleep some longer delay (msec) */
+ delay = (delay+999) / 1000;
+ break;
+
+ case SIRDEV_STATE_WAIT_UNTIL_SENT:
+ /* block until underlaying hardware buffer are empty */
+ if (dev->drv->wait_until_sent)
+ dev->drv->wait_until_sent(dev);
+ next_state = SIRDEV_STATE_TX_DONE;
+ break;
+
+ case SIRDEV_STATE_TX_DONE:
+ return 0;
+
+ default:
+ IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ fsm->substate = next_state;
+ } while (delay == 0);
+ return delay;
+}
+
+/*
+ * Function sirdev_config_fsm
+ *
+ * State machine to handle the configuration of the device (and attached dongle, if any).
+ * This handler is scheduled for execution in kIrDAd context, so we can sleep.
+ * however, kIrDAd is shared by all sir_dev devices so we better don't sleep there too
+ * long. Instead, for longer delays we start a timer to reschedule us later.
+ * On entry, fsm->sem is always locked and the netdev xmit queue stopped.
+ * Both must be unlocked/restarted on completion - but only on final exit.
+ */
+
+static void sirdev_config_fsm(void *data)
+{
+ struct sir_dev *dev = data;
+ struct sir_fsm *fsm = &dev->fsm;
+ int next_state;
+ int ret = -1;
+ unsigned delay;
+
+ IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies);
+
+ do {
+ IRDA_DEBUG(3, "%s - state=0x%04x / substate=0x%04x\n",
+ __FUNCTION__, fsm->state, fsm->substate);
+
+ next_state = fsm->state;
+ delay = 0;
+
+ switch(fsm->state) {
+
+ case SIRDEV_STATE_DONGLE_OPEN:
+ if (dev->dongle_drv != NULL) {
+ ret = sirdev_put_dongle(dev);
+ if (ret) {
+ fsm->result = -EINVAL;
+ next_state = SIRDEV_STATE_ERROR;
+ break;
+ }
+ }
+
+ /* Initialize dongle */
+ ret = sirdev_get_dongle(dev, fsm->param);
+ if (ret) {
+ fsm->result = ret;
+ next_state = SIRDEV_STATE_ERROR;
+ break;
+ }
+
+ /* Dongles are powered through the modem control lines which
+ * were just set during open. Before resetting, let's wait for
+ * the power to stabilize. This is what some dongle drivers did
+ * in open before, while others didn't - should be safe anyway.
+ */
+
+ delay = 50;
+ fsm->substate = SIRDEV_STATE_DONGLE_RESET;
+ next_state = SIRDEV_STATE_DONGLE_RESET;
+
+ fsm->param = 9600;
+
+ break;
+
+ case SIRDEV_STATE_DONGLE_CLOSE:
+ /* shouldn't we just treat this as success=? */
+ if (dev->dongle_drv == NULL) {
+ fsm->result = -EINVAL;
+ next_state = SIRDEV_STATE_ERROR;
+ break;
+ }
+
+ ret = sirdev_put_dongle(dev);
+ if (ret) {
+ fsm->result = ret;
+ next_state = SIRDEV_STATE_ERROR;
+ break;
+ }
+ next_state = SIRDEV_STATE_DONE;
+ break;
+
+ case SIRDEV_STATE_SET_DTR_RTS:
+ ret = sirdev_set_dtr_rts(dev,
+ (fsm->param&0x02) ? TRUE : FALSE,
+ (fsm->param&0x01) ? TRUE : FALSE);
+ next_state = SIRDEV_STATE_DONE;
+ break;
+
+ case SIRDEV_STATE_SET_SPEED:
+ fsm->substate = SIRDEV_STATE_WAIT_XMIT;
+ next_state = SIRDEV_STATE_DONGLE_CHECK;
+ break;
+
+ case SIRDEV_STATE_DONGLE_CHECK:
+ ret = sirdev_tx_complete_fsm(dev);
+ if (ret < 0) {
+ fsm->result = ret;
+ next_state = SIRDEV_STATE_ERROR;
+ break;
+ }
+ if ((delay=ret) != 0)
+ break;
+
+ if (dev->dongle_drv) {
+ fsm->substate = SIRDEV_STATE_DONGLE_RESET;
+ next_state = SIRDEV_STATE_DONGLE_RESET;
+ }
+ else {
+ dev->speed = fsm->param;
+ next_state = SIRDEV_STATE_PORT_SPEED;
+ }
+ break;
+
+ case SIRDEV_STATE_DONGLE_RESET:
+ if (dev->dongle_drv->reset) {
+ ret = dev->dongle_drv->reset(dev);
+ if (ret < 0) {
+ fsm->result = ret;
+ next_state = SIRDEV_STATE_ERROR;
+ break;
+ }
+ }
+ else
+ ret = 0;
+ if ((delay=ret) == 0) {
+ /* set serial port according to dongle default speed */
+ if (dev->drv->set_speed)
+ dev->drv->set_speed(dev, dev->speed);
+ fsm->substate = SIRDEV_STATE_DONGLE_SPEED;
+ next_state = SIRDEV_STATE_DONGLE_SPEED;
+ }
+ break;
+
+ case SIRDEV_STATE_DONGLE_SPEED:
+ if (dev->dongle_drv->reset) {
+ ret = dev->dongle_drv->set_speed(dev, fsm->param);
+ if (ret < 0) {
+ fsm->result = ret;
+ next_state = SIRDEV_STATE_ERROR;
+ break;
+ }
+ }
+ else
+ ret = 0;
+ if ((delay=ret) == 0)
+ next_state = SIRDEV_STATE_PORT_SPEED;
+ break;
+
+ case SIRDEV_STATE_PORT_SPEED:
+ /* Finally we are ready to change the serial port speed */
+ if (dev->drv->set_speed)
+ dev->drv->set_speed(dev, dev->speed);
+ dev->new_speed = 0;
+ next_state = SIRDEV_STATE_DONE;
+ break;
+
+ case SIRDEV_STATE_DONE:
+ /* Signal network layer so it can send more frames */
+ netif_wake_queue(dev->netdev);
+ next_state = SIRDEV_STATE_COMPLETE;
+ break;
+
+ default:
+ IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
+ fsm->result = -EINVAL;
+ /* fall thru */
+
+ case SIRDEV_STATE_ERROR:
+ IRDA_ERROR("%s - error: %d\n", __FUNCTION__, fsm->result);
+
+#if 0 /* don't enable this before we have netdev->tx_timeout to recover */
+ netif_stop_queue(dev->netdev);
+#else
+ netif_wake_queue(dev->netdev);
+#endif
+ /* fall thru */
+
+ case SIRDEV_STATE_COMPLETE:
+ /* config change finished, so we are not busy any longer */
+ sirdev_enable_rx(dev);
+ up(&fsm->sem);
+ return;
+ }
+ fsm->state = next_state;
+ } while(!delay);
+
+ queue_delayed_work(irda_sir_wq, &fsm->work, msecs_to_jiffies(delay));
+}
+
+/* schedule some device configuration task for execution by kIrDAd
+ * on behalf of the above state machine.
+ * can be called from process or interrupt/tasklet context.
+ */
+
+int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned param)
+{
+ struct sir_fsm *fsm = &dev->fsm;
+
+ IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
+
+ if (down_trylock(&fsm->sem)) {
+ if (in_interrupt() || in_atomic() || irqs_disabled()) {
+ IRDA_DEBUG(1, "%s(), state machine busy!\n", __FUNCTION__);
+ return -EWOULDBLOCK;
+ } else
+ down(&fsm->sem);
+ }
+
+ if (fsm->state == SIRDEV_STATE_DEAD) {
+ /* race with sirdev_close should never happen */
+ IRDA_ERROR("%s(), instance staled!\n", __FUNCTION__);
+ up(&fsm->sem);
+ return -ESTALE; /* or better EPIPE? */
+ }
+
+ netif_stop_queue(dev->netdev);
+ atomic_set(&dev->enable_rx, 0);
+
+ fsm->state = initial_state;
+ fsm->param = param;
+ fsm->result = 0;
+
+ INIT_WORK(&fsm->work, sirdev_config_fsm, dev);
+ queue_work(irda_sir_wq, &fsm->work);
+ return 0;
+}
+
+
/***************************************************************************/
void sirdev_enable_rx(struct sir_dev *dev)
@@ -619,10 +911,6 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n
spin_lock_init(&dev->tx_lock);
init_MUTEX(&dev->fsm.sem);
- INIT_LIST_HEAD(&dev->fsm.rq.lh_request);
- dev->fsm.rq.pending = 0;
- init_timer(&dev->fsm.rq.timer);
-
dev->drv = drv;
dev->netdev = ndev;
@@ -682,3 +970,22 @@ int sirdev_put_instance(struct sir_dev *dev)
}
EXPORT_SYMBOL(sirdev_put_instance);
+static int __init sir_wq_init(void)
+{
+ irda_sir_wq = create_singlethread_workqueue("irda_sir_wq");
+ if (!irda_sir_wq)
+ return -ENOMEM;
+ return 0;
+}
+
+static void __exit sir_wq_exit(void)
+{
+ destroy_workqueue(irda_sir_wq);
+}
+
+module_init(sir_wq_init);
+module_exit(sir_wq_exit);
+
+MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>");
+MODULE_DESCRIPTION("IrDA SIR core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c
deleted file mode 100644
index e3904d6bfec..00000000000
--- a/drivers/net/irda/sir_kthread.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/*********************************************************************
- *
- * sir_kthread.c: dedicated thread to process scheduled
- * sir device setup requests
- *
- * Copyright (c) 2002 Martin Diehl
- *
- * This program is free software; 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/module.h>
-#include <linux/kernel.h>
-#include <linux/version.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-
-#include <net/irda/irda.h>
-
-#include "sir-dev.h"
-
-/**************************************************************************
- *
- * kIrDAd kernel thread and config state machine
- *
- */
-
-struct irda_request_queue {
- struct list_head request_list;
- spinlock_t lock;
- task_t *thread;
- struct completion exit;
- wait_queue_head_t kick, done;
- atomic_t num_pending;
-};
-
-static struct irda_request_queue irda_rq_queue;
-
-static int irda_queue_request(struct irda_request *rq)
-{
- int ret = 0;
- unsigned long flags;
-
- if (!test_and_set_bit(0, &rq->pending)) {
- spin_lock_irqsave(&irda_rq_queue.lock, flags);
- list_add_tail(&rq->lh_request, &irda_rq_queue.request_list);
- wake_up(&irda_rq_queue.kick);
- atomic_inc(&irda_rq_queue.num_pending);
- spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
- ret = 1;
- }
- return ret;
-}
-
-static void irda_request_timer(unsigned long data)
-{
- struct irda_request *rq = (struct irda_request *)data;
- unsigned long flags;
-
- spin_lock_irqsave(&irda_rq_queue.lock, flags);
- list_add_tail(&rq->lh_request, &irda_rq_queue.request_list);
- wake_up(&irda_rq_queue.kick);
- spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
-}
-
-static int irda_queue_delayed_request(struct irda_request *rq, unsigned long delay)
-{
- int ret = 0;
- struct timer_list *timer = &rq->timer;
-
- if (!test_and_set_bit(0, &rq->pending)) {
- timer->expires = jiffies + delay;
- timer->function = irda_request_timer;
- timer->data = (unsigned long)rq;
- atomic_inc(&irda_rq_queue.num_pending);
- add_timer(timer);
- ret = 1;
- }
- return ret;
-}
-
-static void run_irda_queue(void)
-{
- unsigned long flags;
- struct list_head *entry, *tmp;
- struct irda_request *rq;
-
- spin_lock_irqsave(&irda_rq_queue.lock, flags);
- list_for_each_safe(entry, tmp, &irda_rq_queue.request_list) {
- rq = list_entry(entry, struct irda_request, lh_request);
- list_del_init(entry);
- spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
-
- clear_bit(0, &rq->pending);
- rq->func(rq->data);
-
- if (atomic_dec_and_test(&irda_rq_queue.num_pending))
- wake_up(&irda_rq_queue.done);
-
- spin_lock_irqsave(&irda_rq_queue.lock, flags);
- }
- spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
-}
-
-static int irda_thread(void *startup)
-{
- DECLARE_WAITQUEUE(wait, current);
-
- daemonize("kIrDAd");
-
- irda_rq_queue.thread = current;
-
- complete((struct completion *)startup);
-
- while (irda_rq_queue.thread != NULL) {
-
- /* We use TASK_INTERRUPTIBLE, rather than
- * TASK_UNINTERRUPTIBLE. Andrew Morton made this
- * change ; he told me that it is safe, because "signal
- * blocking is now handled in daemonize()", he added
- * that the problem is that "uninterruptible sleep
- * contributes to load average", making user worry.
- * Jean II */
- set_task_state(current, TASK_INTERRUPTIBLE);
- add_wait_queue(&irda_rq_queue.kick, &wait);
- if (list_empty(&irda_rq_queue.request_list))
- schedule();
- else
- __set_task_state(current, TASK_RUNNING);
- remove_wait_queue(&irda_rq_queue.kick, &wait);
-
- /* make swsusp happy with our thread */
- try_to_freeze();
-
- run_irda_queue();
- }
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,35)
- reparent_to_init();
-#endif
- complete_and_exit(&irda_rq_queue.exit, 0);
- /* never reached */
- return 0;
-}
-
-
-static void flush_irda_queue(void)
-{
- if (atomic_read(&irda_rq_queue.num_pending)) {
-
- DECLARE_WAITQUEUE(wait, current);
-
- if (!list_empty(&irda_rq_queue.request_list))
- run_irda_queue();
-
- set_task_state(current, TASK_UNINTERRUPTIBLE);
- add_wait_queue(&irda_rq_queue.done, &wait);
- if (atomic_read(&irda_rq_queue.num_pending))
- schedule();
- else
- __set_task_state(current, TASK_RUNNING);
- remove_wait_queue(&irda_rq_queue.done, &wait);
- }
-}
-
-/* substate handler of the config-fsm to handle the cases where we want
- * to wait for transmit completion before changing the port configuration
- */
-
-static int irda_tx_complete_fsm(struct sir_dev *dev)
-{
- struct sir_fsm *fsm = &dev->fsm;
- unsigned next_state, delay;
- unsigned bytes_left;
-
- do {
- next_state = fsm->substate; /* default: stay in current substate */
- delay = 0;
-
- switch(fsm->substate) {
-
- case SIRDEV_STATE_WAIT_XMIT:
- if (dev->drv->chars_in_buffer)
- bytes_left = dev->drv->chars_in_buffer(dev);
- else
- bytes_left = 0;
- if (!bytes_left) {
- next_state = SIRDEV_STATE_WAIT_UNTIL_SENT;
- break;
- }
-
- if (dev->speed > 115200)
- delay = (bytes_left*8*10000) / (dev->speed/100);
- else if (dev->speed > 0)
- delay = (bytes_left*10*10000) / (dev->speed/100);
- else
- delay = 0;
- /* expected delay (usec) until remaining bytes are sent */
- if (delay < 100) {
- udelay(delay);
- delay = 0;
- break;
- }
- /* sleep some longer delay (msec) */
- delay = (delay+999) / 1000;
- break;
-
- case SIRDEV_STATE_WAIT_UNTIL_SENT:
- /* block until underlaying hardware buffer are empty */
- if (dev->drv->wait_until_sent)
- dev->drv->wait_until_sent(dev);
- next_state = SIRDEV_STATE_TX_DONE;
- break;
-
- case SIRDEV_STATE_TX_DONE:
- return 0;
-
- default:
- IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
- return -EINVAL;
- }
- fsm->substate = next_state;
- } while (delay == 0);
- return delay;
-}
-
-/*
- * Function irda_config_fsm
- *
- * State machine to handle the configuration of the device (and attached dongle, if any).
- * This handler is scheduled for execution in kIrDAd context, so we can sleep.
- * however, kIrDAd is shared by all sir_dev devices so we better don't sleep there too
- * long. Instead, for longer delays we start a timer to reschedule us later.
- * On entry, fsm->sem is always locked and the netdev xmit queue stopped.
- * Both must be unlocked/restarted on completion - but only on final exit.
- */
-
-static void irda_config_fsm(void *data)
-{
- struct sir_dev *dev = data;
- struct sir_fsm *fsm = &dev->fsm;
- int next_state;
- int ret = -1;
- unsigned delay;
-
- IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies);
-
- do {
- IRDA_DEBUG(3, "%s - state=0x%04x / substate=0x%04x\n",
- __FUNCTION__, fsm->state, fsm->substate);
-
- next_state = fsm->state;
- delay = 0;
-
- switch(fsm->state) {
-
- case SIRDEV_STATE_DONGLE_OPEN:
- if (dev->dongle_drv != NULL) {
- ret = sirdev_put_dongle(dev);
- if (ret) {
- fsm->result = -EINVAL;
- next_state = SIRDEV_STATE_ERROR;
- break;
- }
- }
-
- /* Initialize dongle */
- ret = sirdev_get_dongle(dev, fsm->param);
- if (ret) {
- fsm->result = ret;
- next_state = SIRDEV_STATE_ERROR;
- break;
- }
-
- /* Dongles are powered through the modem control lines which
- * were just set during open. Before resetting, let's wait for
- * the power to stabilize. This is what some dongle drivers did
- * in open before, while others didn't - should be safe anyway.
- */
-
- delay = 50;
- fsm->substate = SIRDEV_STATE_DONGLE_RESET;
- next_state = SIRDEV_STATE_DONGLE_RESET;
-
- fsm->param = 9600;
-
- break;
-
- case SIRDEV_STATE_DONGLE_CLOSE:
- /* shouldn't we just treat this as success=? */
- if (dev->dongle_drv == NULL) {
- fsm->result = -EINVAL;
- next_state = SIRDEV_STATE_ERROR;
- break;
- }
-
- ret = sirdev_put_dongle(dev);
- if (ret) {
- fsm->result = ret;
- next_state = SIRDEV_STATE_ERROR;
- break;
- }
- next_state = SIRDEV_STATE_DONE;
- break;
-
- case SIRDEV_STATE_SET_DTR_RTS:
- ret = sirdev_set_dtr_rts(dev,
- (fsm->param&0x02) ? TRUE : FALSE,
- (fsm->param&0x01) ? TRUE : FALSE);
- next_state = SIRDEV_STATE_DONE;
- break;
-
- case SIRDEV_STATE_SET_SPEED:
- fsm->substate = SIRDEV_STATE_WAIT_XMIT;
- next_state = SIRDEV_STATE_DONGLE_CHECK;
- break;
-
- case SIRDEV_STATE_DONGLE_CHECK:
- ret = irda_tx_complete_fsm(dev);
- if (ret < 0) {
- fsm->result = ret;
- next_state = SIRDEV_STATE_ERROR;
- break;
- }
- if ((delay=ret) != 0)
- break;
-
- if (dev->dongle_drv) {
- fsm->substate = SIRDEV_STATE_DONGLE_RESET;
- next_state = SIRDEV_STATE_DONGLE_RESET;
- }
- else {
- dev->speed = fsm->param;
- next_state = SIRDEV_STATE_PORT_SPEED;
- }
- break;
-
- case SIRDEV_STATE_DONGLE_RESET:
- if (dev->dongle_drv->reset) {
- ret = dev->dongle_drv->reset(dev);
- if (ret < 0) {
- fsm->result = ret;
- next_state = SIRDEV_STATE_ERROR;
- break;
- }
- }
- else
- ret = 0;
- if ((delay=ret) == 0) {
- /* set serial port according to dongle default speed */
- if (dev->drv->set_speed)
- dev->drv->set_speed(dev, dev->speed);
- fsm->substate = SIRDEV_STATE_DONGLE_SPEED;
- next_state = SIRDEV_STATE_DONGLE_SPEED;
- }
- break;
-
- case SIRDEV_STATE_DONGLE_SPEED:
- if (dev->dongle_drv->reset) {
- ret = dev->dongle_drv->set_speed(dev, fsm->param);
- if (ret < 0) {
- fsm->result = ret;
- next_state = SIRDEV_STATE_ERROR;
- break;
- }
- }
- else
- ret = 0;
- if ((delay=ret) == 0)
- next_state = SIRDEV_STATE_PORT_SPEED;
- break;
-
- case SIRDEV_STATE_PORT_SPEED:
- /* Finally we are ready to change the serial port speed */
- if (dev->drv->set_speed)
- dev->drv->set_speed(dev, dev->speed);
- dev->new_speed = 0;
- next_state = SIRDEV_STATE_DONE;
- break;
-
- case SIRDEV_STATE_DONE:
- /* Signal network layer so it can send more frames */
- netif_wake_queue(dev->netdev);
- next_state = SIRDEV_STATE_COMPLETE;
- break;
-
- default:
- IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
- fsm->result = -EINVAL;
- /* fall thru */
-
- case SIRDEV_STATE_ERROR:
- IRDA_ERROR("%s - error: %d\n", __FUNCTION__, fsm->result);
-
-#if 0 /* don't enable this before we have netdev->tx_timeout to recover */
- netif_stop_queue(dev->netdev);
-#else
- netif_wake_queue(dev->netdev);
-#endif
- /* fall thru */
-
- case SIRDEV_STATE_COMPLETE:
- /* config change finished, so we are not busy any longer */
- sirdev_enable_rx(dev);
- up(&fsm->sem);
- return;
- }
- fsm->state = next_state;
- } while(!delay);
-
- irda_queue_delayed_request(&fsm->rq, msecs_to_jiffies(delay));
-}
-
-/* schedule some device configuration task for execution by kIrDAd
- * on behalf of the above state machine.
- * can be called from process or interrupt/tasklet context.
- */
-
-int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned param)
-{
- struct sir_fsm *fsm = &dev->fsm;
- int xmit_was_down;
-
- IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
-
- if (down_trylock(&fsm->sem)) {
- if (in_interrupt() || in_atomic() || irqs_disabled()) {
- IRDA_DEBUG(1, "%s(), state machine busy!\n", __FUNCTION__);
- return -EWOULDBLOCK;
- } else
- down(&fsm->sem);
- }
-
- if (fsm->state == SIRDEV_STATE_DEAD) {
- /* race with sirdev_close should never happen */
- IRDA_ERROR("%s(), instance staled!\n", __FUNCTION__);
- up(&fsm->sem);
- return -ESTALE; /* or better EPIPE? */
- }
-
- xmit_was_down = netif_queue_stopped(dev->netdev);
- netif_stop_queue(dev->netdev);
- atomic_set(&dev->enable_rx, 0);
-
- fsm->state = initial_state;
- fsm->param = param;
- fsm->result = 0;
-
- INIT_LIST_HEAD(&fsm->rq.lh_request);
- fsm->rq.pending = 0;
- fsm->rq.func = irda_config_fsm;
- fsm->rq.data = dev;
-
- if (!irda_queue_request(&fsm->rq)) { /* returns 0 on error! */
- atomic_set(&dev->enable_rx, 1);
- if (!xmit_was_down)
- netif_wake_queue(dev->netdev);
- up(&fsm->sem);
- return -EAGAIN;
- }
- return 0;
-}
-
-static int __init irda_thread_create(void)
-{
- struct completion startup;
- int pid;
-
- spin_lock_init(&irda_rq_queue.lock);
- irda_rq_queue.thread = NULL;
- INIT_LIST_HEAD(&irda_rq_queue.request_list);
- init_waitqueue_head(&irda_rq_queue.kick);
- init_waitqueue_head(&irda_rq_queue.done);
- atomic_set(&irda_rq_queue.num_pending, 0);
-
- init_completion(&startup);
- pid = kernel_thread(irda_thread, &startup, CLONE_FS|CLONE_FILES);
- if (pid <= 0)
- return -EAGAIN;
- else
- wait_for_completion(&startup);
-
- return 0;
-}
-
-static void __exit irda_thread_join(void)
-{
- if (irda_rq_queue.thread) {
- flush_irda_queue();
- init_completion(&irda_rq_queue.exit);
- irda_rq_queue.thread = NULL;
- wake_up(&irda_rq_queue.kick);
- wait_for_completion(&irda_rq_queue.exit);
- }
-}
-
-module_init(irda_thread_create);
-module_exit(irda_thread_join);
-
-MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>");
-MODULE_DESCRIPTION("IrDA SIR core");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index ec94ecdb103..a4674044bd6 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -11,6 +11,7 @@
* Copyright (c) 2002 Daniele Peri
* All Rights Reserved.
* Copyright (c) 2002 Jean Tourrilhes
+ * Copyright (c) 2006 Linus Walleij
*
*
* Based on smc-ircc.c:
@@ -53,6 +54,7 @@
#include <linux/rtnetlink.h>
#include <linux/serial_reg.h>
#include <linux/dma-mapping.h>
+#include <linux/pnp.h>
#include <linux/platform_device.h>
#include <asm/io.h>
@@ -61,6 +63,9 @@
#include <linux/spinlock.h>
#include <linux/pm.h>
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
#include <net/irda/wrapper.h>
#include <net/irda/irda.h>
@@ -100,6 +105,22 @@ MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
/* Types */
+#ifdef CONFIG_PCI
+struct smsc_ircc_subsystem_configuration {
+ unsigned short vendor; /* PCI vendor ID */
+ unsigned short device; /* PCI vendor ID */
+ unsigned short subvendor; /* PCI subsystem vendor ID */
+ unsigned short subdevice; /* PCI sybsystem device ID */
+ unsigned short sir_io; /* I/O port for SIR */
+ unsigned short fir_io; /* I/O port for FIR */
+ unsigned char fir_irq; /* FIR IRQ */
+ unsigned char fir_dma; /* FIR DMA */
+ unsigned short cfg_base; /* I/O port for chip configuration */
+ int (*preconfigure)(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); /* Preconfig function */
+ const char *name; /* name shown as info */
+};
+#endif
+
struct smsc_transceiver {
char *name;
void (*set_for_speed)(int fir_base, u32 speed);
@@ -202,6 +223,18 @@ static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned shor
static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type);
static int __init smsc_superio_fdc(unsigned short cfg_base);
static int __init smsc_superio_lpc(unsigned short cfg_base);
+#ifdef CONFIG_PCI
+static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf);
+static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
+static void __init preconfigure_ali_port(struct pci_dev *dev,
+ unsigned short port);
+static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
+static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
+ unsigned short ircc_fir,
+ unsigned short ircc_sir,
+ unsigned char ircc_dma,
+ unsigned char ircc_irq);
+#endif
/* Transceivers specific functions */
@@ -326,6 +359,16 @@ static inline void register_bank(int iobase, int bank)
iobase + IRCC_MASTER);
}
+#ifdef CONFIG_PNP
+/* PNP hotplug support */
+static const struct pnp_device_id smsc_ircc_pnp_table[] = {
+ { .id = "SMCf010", .driver_data = 0 },
+ /* and presumably others */
+ { }
+};
+MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
+#endif
+
/*******************************************************************************
*
@@ -353,6 +396,13 @@ static int __init smsc_ircc_init(void)
return ret;
}
+#ifdef CONFIG_PCI
+ if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) {
+ /* Ignore errors from preconfiguration */
+ IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name);
+ }
+#endif
+
dev_count = 0;
if (ircc_fir > 0 && ircc_sir > 0) {
@@ -2033,7 +2083,8 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self)
/* PROBING
*
- *
+ * REVISIT we can be told about the device by PNP, and should use that info
+ * instead of probing hardware and creating a platform_device ...
*/
static int __init smsc_ircc_look_for_chips(void)
@@ -2285,6 +2336,490 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
return ret;
}
+/*
+ * Look for some specific subsystem setups that need
+ * pre-configuration not properly done by the BIOS (especially laptops)
+ * This code is based in part on smcinit.c, tosh1800-smcinit.c
+ * and tosh2450-smcinit.c. The table lists the device entries
+ * for ISA bridges with an LPC (Low Pin Count) controller which
+ * handles the communication with the SMSC device. After the LPC
+ * controller is initialized through PCI, the SMSC device is initialized
+ * through a dedicated port in the ISA port-mapped I/O area, this latter
+ * area is used to configure the SMSC device with default
+ * SIR and FIR I/O ports, DMA and IRQ. Different vendors have
+ * used different sets of parameters and different control port
+ * addresses making a subsystem device table necessary.
+ */
+#ifdef CONFIG_PCI
+#define PCIID_VENDOR_INTEL 0x8086
+#define PCIID_VENDOR_ALI 0x10b9
+static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __devinitdata = {
+ {
+ .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+ .device = 0x24cc,
+ .subvendor = 0x103c,
+ .subdevice = 0x088c,
+ /* Quite certain these are the same for nc8000 as for nc6000 */
+ .sir_io = 0x02f8,
+ .fir_io = 0x0130,
+ .fir_irq = 0x05,
+ .fir_dma = 0x03,
+ .cfg_base = 0x004e,
+ .preconfigure = preconfigure_through_82801,
+ .name = "HP nc8000",
+ },
+ {
+ .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+ .device = 0x24cc,
+ .subvendor = 0x103c,
+ .subdevice = 0x0890,
+ .sir_io = 0x02f8,
+ .fir_io = 0x0130,
+ .fir_irq = 0x05,
+ .fir_dma = 0x03,
+ .cfg_base = 0x004e,
+ .preconfigure = preconfigure_through_82801,
+ .name = "HP nc6000",
+ },
+ {
+ /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
+ .vendor = PCIID_VENDOR_INTEL,
+ .device = 0x24c0,
+ .subvendor = 0x1179,
+ .subdevice = 0xffff, /* 0xffff is "any" */
+ .sir_io = 0x03f8,
+ .fir_io = 0x0130,
+ .fir_irq = 0x07,
+ .fir_dma = 0x01,
+ .cfg_base = 0x002e,
+ .preconfigure = preconfigure_through_82801,
+ .name = "Toshiba laptop with Intel 82801DB/DBL LPC bridge",
+ },
+ {
+ .vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */
+ .device = 0x248c,
+ .subvendor = 0x1179,
+ .subdevice = 0xffff, /* 0xffff is "any" */
+ .sir_io = 0x03f8,
+ .fir_io = 0x0130,
+ .fir_irq = 0x03,
+ .fir_dma = 0x03,
+ .cfg_base = 0x002e,
+ .preconfigure = preconfigure_through_82801,
+ .name = "Toshiba laptop with Intel 82801CAM ISA bridge",
+ },
+ {
+ /* 82801DBM (ICH4-M) LPC Interface Bridge */
+ .vendor = PCIID_VENDOR_INTEL,
+ .device = 0x24cc,
+ .subvendor = 0x1179,
+ .subdevice = 0xffff, /* 0xffff is "any" */
+ .sir_io = 0x03f8,
+ .fir_io = 0x0130,
+ .fir_irq = 0x03,
+ .fir_dma = 0x03,
+ .cfg_base = 0x002e,
+ .preconfigure = preconfigure_through_82801,
+ .name = "Toshiba laptop with Intel 8281DBM LPC bridge",
+ },
+ {
+ /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */
+ .vendor = PCIID_VENDOR_ALI,
+ .device = 0x1533,
+ .subvendor = 0x1179,
+ .subdevice = 0xffff, /* 0xffff is "any" */
+ .sir_io = 0x02e8,
+ .fir_io = 0x02f8,
+ .fir_irq = 0x07,
+ .fir_dma = 0x03,
+ .cfg_base = 0x002e,
+ .preconfigure = preconfigure_through_ali,
+ .name = "Toshiba laptop with ALi ISA bridge",
+ },
+ { } // Terminator
+};
+
+
+/*
+ * This sets up the basic SMSC parameters
+ * (FIR port, SIR port, FIR DMA, FIR IRQ)
+ * through the chip configuration port.
+ */
+static int __init preconfigure_smsc_chip(struct
+ smsc_ircc_subsystem_configuration
+ *conf)
+{
+ unsigned short iobase = conf->cfg_base;
+ unsigned char tmpbyte;
+
+ outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state
+ outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID
+ tmpbyte = inb(iobase +1); // Read device ID
+ IRDA_DEBUG(0,
+ "Detected Chip id: 0x%02x, setting up registers...\n",
+ tmpbyte);
+
+ /* Disable UART1 and set up SIR I/O port */
+ outb(0x24, iobase); // select CR24 - UART1 base addr
+ outb(0x00, iobase + 1); // disable UART1
+ outb(SMSCSIOFLAT_UART2BASEADDR_REG, iobase); // select CR25 - UART2 base addr
+ outb( (conf->sir_io >> 2), iobase + 1); // bits 2-9 of 0x3f8
+ tmpbyte = inb(iobase + 1);
+ if (tmpbyte != (conf->sir_io >> 2) ) {
+ IRDA_WARNING("ERROR: could not configure SIR ioport.\n");
+ IRDA_WARNING("Try to supply ircc_cfg argument.\n");
+ return -ENXIO;
+ }
+
+ /* Set up FIR IRQ channel for UART2 */
+ outb(SMSCSIOFLAT_UARTIRQSELECT_REG, iobase); // select CR28 - UART1,2 IRQ select
+ tmpbyte = inb(iobase + 1);
+ tmpbyte &= SMSCSIOFLAT_UART1IRQSELECT_MASK; // Do not touch the UART1 portion
+ tmpbyte |= (conf->fir_irq & SMSCSIOFLAT_UART2IRQSELECT_MASK);
+ outb(tmpbyte, iobase + 1);
+ tmpbyte = inb(iobase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
+ if (tmpbyte != conf->fir_irq) {
+ IRDA_WARNING("ERROR: could not configure FIR IRQ channel.\n");
+ return -ENXIO;
+ }
+
+ /* Set up FIR I/O port */
+ outb(SMSCSIOFLAT_FIRBASEADDR_REG, iobase); // CR2B - SCE (FIR) base addr
+ outb((conf->fir_io >> 3), iobase + 1);
+ tmpbyte = inb(iobase + 1);
+ if (tmpbyte != (conf->fir_io >> 3) ) {
+ IRDA_WARNING("ERROR: could not configure FIR I/O port.\n");
+ return -ENXIO;
+ }
+
+ /* Set up FIR DMA channel */
+ outb(SMSCSIOFLAT_FIRDMASELECT_REG, iobase); // CR2C - SCE (FIR) DMA select
+ outb((conf->fir_dma & LPC47N227_FIRDMASELECT_MASK), iobase + 1); // DMA
+ tmpbyte = inb(iobase + 1) & LPC47N227_FIRDMASELECT_MASK;
+ if (tmpbyte != (conf->fir_dma & LPC47N227_FIRDMASELECT_MASK)) {
+ IRDA_WARNING("ERROR: could not configure FIR DMA channel.\n");
+ return -ENXIO;
+ }
+
+ outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase); // CR0C - UART mode
+ tmpbyte = inb(iobase + 1);
+ tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK |
+ SMSCSIOFLAT_UART2MODE_VAL_IRDA;
+ outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed
+
+ outb(LPC47N227_APMBOOTDRIVE_REG, iobase); // CR07 - Auto Pwr Mgt/boot drive sel
+ tmpbyte = inb(iobase + 1);
+ outb(tmpbyte | LPC47N227_UART2AUTOPWRDOWN_MASK, iobase + 1); // enable UART2 autopower down
+
+ /* This one was not part of tosh1800 */
+ outb(0x0a, iobase); // CR0a - ecp fifo / ir mux
+ tmpbyte = inb(iobase + 1);
+ outb(tmpbyte | 0x40, iobase + 1); // send active device to ir port
+
+ outb(LPC47N227_UART12POWER_REG, iobase); // CR02 - UART 1,2 power
+ tmpbyte = inb(iobase + 1);
+ outb(tmpbyte | LPC47N227_UART2POWERDOWN_MASK, iobase + 1); // UART2 power up mode, UART1 power down
+
+ outb(LPC47N227_FDCPOWERVALIDCONF_REG, iobase); // CR00 - FDC Power/valid config cycle
+ tmpbyte = inb(iobase + 1);
+ outb(tmpbyte | LPC47N227_VALID_MASK, iobase + 1); // valid config cycle done
+
+ outb(LPC47N227_CFGEXITKEY, iobase); // Exit configuration
+
+ return 0;
+}
+
+/* 82801CAM generic registers */
+#define VID 0x00
+#define DID 0x02
+#define PIRQ_A_D_ROUT 0x60
+#define SIRQ_CNTL 0x64
+#define PIRQ_E_H_ROUT 0x68
+#define PCI_DMA_C 0x90
+/* LPC-specific registers */
+#define COM_DEC 0xe0
+#define GEN1_DEC 0xe4
+#define LPC_EN 0xe6
+#define GEN2_DEC 0xec
+/*
+ * Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge
+ * or Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge.
+ * They all work the same way!
+ */
+static int __init preconfigure_through_82801(struct pci_dev *dev,
+ struct
+ smsc_ircc_subsystem_configuration
+ *conf)
+{
+ unsigned short tmpword;
+ unsigned char tmpbyte;
+
+ IRDA_MESSAGE("Setting up Intel 82801 controller and SMSC device\n");
+ /*
+ * Select the range for the COMA COM port (SIR)
+ * Register COM_DEC:
+ * Bit 7: reserved
+ * Bit 6-4, COMB decode range
+ * Bit 3: reserved
+ * Bit 2-0, COMA decode range
+ *
+ * Decode ranges:
+ * 000 = 0x3f8-0x3ff (COM1)
+ * 001 = 0x2f8-0x2ff (COM2)
+ * 010 = 0x220-0x227
+ * 011 = 0x228-0x22f
+ * 100 = 0x238-0x23f
+ * 101 = 0x2e8-0x2ef (COM4)
+ * 110 = 0x338-0x33f
+ * 111 = 0x3e8-0x3ef (COM3)
+ */
+ pci_read_config_byte(dev, COM_DEC, &tmpbyte);
+ tmpbyte &= 0xf8; /* mask COMA bits */
+ switch(conf->sir_io) {
+ case 0x3f8:
+ tmpbyte |= 0x00;
+ break;
+ case 0x2f8:
+ tmpbyte |= 0x01;
+ break;
+ case 0x220:
+ tmpbyte |= 0x02;
+ break;
+ case 0x228:
+ tmpbyte |= 0x03;
+ break;
+ case 0x238:
+ tmpbyte |= 0x04;
+ break;
+ case 0x2e8:
+ tmpbyte |= 0x05;
+ break;
+ case 0x338:
+ tmpbyte |= 0x06;
+ break;
+ case 0x3e8:
+ tmpbyte |= 0x07;
+ break;
+ default:
+ tmpbyte |= 0x01; /* COM2 default */
+ }
+ IRDA_DEBUG(1, "COM_DEC (write): 0x%02x\n", tmpbyte);
+ pci_write_config_byte(dev, COM_DEC, tmpbyte);
+
+ /* Enable Low Pin Count interface */
+ pci_read_config_word(dev, LPC_EN, &tmpword);
+ /* These seem to be set up at all times,
+ * just make sure it is properly set.
+ */
+ switch(conf->cfg_base) {
+ case 0x04e:
+ tmpword |= 0x2000;
+ break;
+ case 0x02e:
+ tmpword |= 0x1000;
+ break;
+ case 0x062:
+ tmpword |= 0x0800;
+ break;
+ case 0x060:
+ tmpword |= 0x0400;
+ break;
+ default:
+ IRDA_WARNING("Uncommon I/O base address: 0x%04x\n",
+ conf->cfg_base);
+ break;
+ }
+ tmpword &= 0xfffd; /* disable LPC COMB */
+ tmpword |= 0x0001; /* set bit 0 : enable LPC COMA addr range (GEN2) */
+ IRDA_DEBUG(1, "LPC_EN (write): 0x%04x\n", tmpword);
+ pci_write_config_word(dev, LPC_EN, tmpword);
+
+ /*
+ * Configure LPC DMA channel
+ * PCI_DMA_C bits:
+ * Bit 15-14: DMA channel 7 select
+ * Bit 13-12: DMA channel 6 select
+ * Bit 11-10: DMA channel 5 select
+ * Bit 9-8: Reserved
+ * Bit 7-6: DMA channel 3 select
+ * Bit 5-4: DMA channel 2 select
+ * Bit 3-2: DMA channel 1 select
+ * Bit 1-0: DMA channel 0 select
+ * 00 = Reserved value
+ * 01 = PC/PCI DMA
+ * 10 = Reserved value
+ * 11 = LPC I/F DMA
+ */
+ pci_read_config_word(dev, PCI_DMA_C, &tmpword);
+ switch(conf->fir_dma) {
+ case 0x07:
+ tmpword |= 0xc000;
+ break;
+ case 0x06:
+ tmpword |= 0x3000;
+ break;
+ case 0x05:
+ tmpword |= 0x0c00;
+ break;
+ case 0x03:
+ tmpword |= 0x00c0;
+ break;
+ case 0x02:
+ tmpword |= 0x0030;
+ break;
+ case 0x01:
+ tmpword |= 0x000c;
+ break;
+ case 0x00:
+ tmpword |= 0x0003;
+ break;
+ default:
+ break; /* do not change settings */
+ }
+ IRDA_DEBUG(1, "PCI_DMA_C (write): 0x%04x\n", tmpword);
+ pci_write_config_word(dev, PCI_DMA_C, tmpword);
+
+ /*
+ * GEN2_DEC bits:
+ * Bit 15-4: Generic I/O range
+ * Bit 3-1: reserved (read as 0)
+ * Bit 0: enable GEN2 range on LPC I/F
+ */
+ tmpword = conf->fir_io & 0xfff8;
+ tmpword |= 0x0001;
+ IRDA_DEBUG(1, "GEN2_DEC (write): 0x%04x\n", tmpword);
+ pci_write_config_word(dev, GEN2_DEC, tmpword);
+
+ /* Pre-configure chip */
+ return preconfigure_smsc_chip(conf);
+}
+
+/*
+ * Pre-configure a certain port on the ALi 1533 bridge.
+ * This is based on reverse-engineering since ALi does not
+ * provide any data sheet for the 1533 chip.
+ */
+static void __init preconfigure_ali_port(struct pci_dev *dev,
+ unsigned short port)
+{
+ unsigned char reg;
+ /* These bits obviously control the different ports */
+ unsigned char mask;
+ unsigned char tmpbyte;
+
+ switch(port) {
+ case 0x0130:
+ case 0x0178:
+ reg = 0xb0;
+ mask = 0x80;
+ break;
+ case 0x03f8:
+ reg = 0xb4;
+ mask = 0x80;
+ break;
+ case 0x02f8:
+ reg = 0xb4;
+ mask = 0x30;
+ break;
+ case 0x02e8:
+ reg = 0xb4;
+ mask = 0x08;
+ break;
+ default:
+ IRDA_ERROR("Failed to configure unsupported port on ALi 1533 bridge: 0x%04x\n", port);
+ return;
+ }
+
+ pci_read_config_byte(dev, reg, &tmpbyte);
+ /* Turn on the right bits */
+ tmpbyte |= mask;
+ pci_write_config_byte(dev, reg, tmpbyte);
+ IRDA_MESSAGE("Activated ALi 1533 ISA bridge port 0x%04x.\n", port);
+ return;
+}
+
+static int __init preconfigure_through_ali(struct pci_dev *dev,
+ struct
+ smsc_ircc_subsystem_configuration
+ *conf)
+{
+ /* Configure the two ports on the ALi 1533 */
+ preconfigure_ali_port(dev, conf->sir_io);
+ preconfigure_ali_port(dev, conf->fir_io);
+
+ /* Pre-configure chip */
+ return preconfigure_smsc_chip(conf);
+}
+
+static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
+ unsigned short ircc_fir,
+ unsigned short ircc_sir,
+ unsigned char ircc_dma,
+ unsigned char ircc_irq)
+{
+ struct pci_dev *dev = NULL;
+ unsigned short ss_vendor = 0x0000;
+ unsigned short ss_device = 0x0000;
+ int ret = 0;
+
+ dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+
+ while (dev != NULL) {
+ struct smsc_ircc_subsystem_configuration *conf;
+
+ /*
+ * Cache the subsystem vendor/device:
+ * some manufacturers fail to set this for all components,
+ * so we save it in case there is just 0x0000 0x0000 on the
+ * device we want to check.
+ */
+ if (dev->subsystem_vendor != 0x0000U) {
+ ss_vendor = dev->subsystem_vendor;
+ ss_device = dev->subsystem_device;
+ }
+ conf = subsystem_configurations;
+ for( ; conf->subvendor; conf++) {
+ if(conf->vendor == dev->vendor &&
+ conf->device == dev->device &&
+ conf->subvendor == ss_vendor &&
+ /* Sometimes these are cached values */
+ (conf->subdevice == ss_device ||
+ conf->subdevice == 0xffff)) {
+ struct smsc_ircc_subsystem_configuration
+ tmpconf;
+
+ memcpy(&tmpconf, conf,
+ sizeof(struct smsc_ircc_subsystem_configuration));
+
+ /*
+ * Override the default values with anything
+ * passed in as parameter
+ */
+ if (ircc_cfg != 0)
+ tmpconf.cfg_base = ircc_cfg;
+ if (ircc_fir != 0)
+ tmpconf.fir_io = ircc_fir;
+ if (ircc_sir != 0)
+ tmpconf.sir_io = ircc_sir;
+ if (ircc_dma != 0xff)
+ tmpconf.fir_dma = ircc_dma;
+ if (ircc_irq != 0xff)
+ tmpconf.fir_irq = ircc_irq;
+
+ IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name);
+ if (conf->preconfigure)
+ ret = conf->preconfigure(dev, &tmpconf);
+ else
+ ret = -ENODEV;
+ }
+ }
+ dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+ }
+
+ return ret;
+}
+#endif // CONFIG_PCI
+
/************************************************
*
* Transceivers specific functions
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index f9f77e4f596..cfd67d812f0 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -357,18 +357,20 @@ ixgb_probe(struct pci_dev *pdev,
if((err = pci_enable_device(pdev)))
return err;
- if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
+ !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) {
pci_using_dac = 1;
} else {
- if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+ if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
+ (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
IXGB_ERR("No usable DMA configuration, aborting\n");
- return err;
+ goto err_dma_mask;
}
pci_using_dac = 0;
}
if((err = pci_request_regions(pdev, ixgb_driver_name)))
- return err;
+ goto err_request_regions;
pci_set_master(pdev);
@@ -502,6 +504,9 @@ err_ioremap:
free_netdev(netdev);
err_alloc_etherdev:
pci_release_regions(pdev);
+err_request_regions:
+err_dma_mask:
+ pci_disable_device(pdev);
return err;
}
diff --git a/drivers/net/ixp2000/enp2611.c b/drivers/net/ixp2000/enp2611.c
index 6f7dce8eba5..b67f586d739 100644
--- a/drivers/net/ixp2000/enp2611.c
+++ b/drivers/net/ixp2000/enp2611.c
@@ -149,6 +149,8 @@ static void enp2611_check_link_status(unsigned long __dummy)
int status;
dev = nds[i];
+ if (dev == NULL)
+ continue;
status = pm3386_is_link_up(i);
if (status && !netif_carrier_ok(dev)) {
@@ -191,6 +193,7 @@ static void enp2611_set_port_admin_status(int port, int up)
static int __init enp2611_init_module(void)
{
+ int ports;
int i;
if (!machine_is_enp2611())
@@ -199,7 +202,8 @@ static int __init enp2611_init_module(void)
caleb_reset();
pm3386_reset();
- for (i = 0; i < 3; i++) {
+ ports = pm3386_port_count();
+ for (i = 0; i < ports; i++) {
nds[i] = ixpdev_alloc(i, sizeof(struct enp2611_ixpdev_priv));
if (nds[i] == NULL) {
while (--i >= 0)
@@ -215,9 +219,10 @@ static int __init enp2611_init_module(void)
ixp2400_msf_init(&enp2611_msf_parameters);
- if (ixpdev_init(3, nds, enp2611_set_port_admin_status)) {
- for (i = 0; i < 3; i++)
- free_netdev(nds[i]);
+ if (ixpdev_init(ports, nds, enp2611_set_port_admin_status)) {
+ for (i = 0; i < ports; i++)
+ if (nds[i])
+ free_netdev(nds[i]);
return -EINVAL;
}
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 77f104a005f..fbc2d21020f 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -299,10 +299,7 @@ int ixpdev_init(int __nds_count, struct net_device **__nds,
int i;
int err;
- if (RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192) {
- static void __too_many_rx_or_tx_buffers(void);
- __too_many_rx_or_tx_buffers();
- }
+ BUILD_BUG_ON(RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192);
printk(KERN_INFO "IXP2000 MSF ethernet driver %s\n", DRV_MODULE_VERSION);
diff --git a/drivers/net/ixp2000/pm3386.c b/drivers/net/ixp2000/pm3386.c
index 5c7ab756405..5224651c9aa 100644
--- a/drivers/net/ixp2000/pm3386.c
+++ b/drivers/net/ixp2000/pm3386.c
@@ -86,40 +86,53 @@ static void pm3386_port_reg_write(int port, int _reg, int spacing, u16 value)
pm3386_reg_write(port >> 1, reg, value);
}
+int pm3386_secondary_present(void)
+{
+ return pm3386_reg_read(1, 0) == 0x3386;
+}
void pm3386_reset(void)
{
u8 mac[3][6];
+ int secondary;
+
+ secondary = pm3386_secondary_present();
/* Save programmed MAC addresses. */
pm3386_get_mac(0, mac[0]);
pm3386_get_mac(1, mac[1]);
- pm3386_get_mac(2, mac[2]);
+ if (secondary)
+ pm3386_get_mac(2, mac[2]);
/* Assert analog and digital reset. */
pm3386_reg_write(0, 0x002, 0x0060);
- pm3386_reg_write(1, 0x002, 0x0060);
+ if (secondary)
+ pm3386_reg_write(1, 0x002, 0x0060);
mdelay(1);
/* Deassert analog reset. */
pm3386_reg_write(0, 0x002, 0x0062);
- pm3386_reg_write(1, 0x002, 0x0062);
+ if (secondary)
+ pm3386_reg_write(1, 0x002, 0x0062);
mdelay(10);
/* Deassert digital reset. */
pm3386_reg_write(0, 0x002, 0x0063);
- pm3386_reg_write(1, 0x002, 0x0063);
+ if (secondary)
+ pm3386_reg_write(1, 0x002, 0x0063);
mdelay(10);
/* Restore programmed MAC addresses. */
pm3386_set_mac(0, mac[0]);
pm3386_set_mac(1, mac[1]);
- pm3386_set_mac(2, mac[2]);
+ if (secondary)
+ pm3386_set_mac(2, mac[2]);
/* Disable carrier on all ports. */
pm3386_set_carrier(0, 0);
pm3386_set_carrier(1, 0);
- pm3386_set_carrier(2, 0);
+ if (secondary)
+ pm3386_set_carrier(2, 0);
}
static u16 swaph(u16 x)
@@ -127,6 +140,11 @@ static u16 swaph(u16 x)
return ((x << 8) | (x >> 8)) & 0xffff;
}
+int pm3386_port_count(void)
+{
+ return 2 + pm3386_secondary_present();
+}
+
void pm3386_init_port(int port)
{
int pm = port >> 1;
diff --git a/drivers/net/ixp2000/pm3386.h b/drivers/net/ixp2000/pm3386.h
index fe92bb056ac..cc4183dca91 100644
--- a/drivers/net/ixp2000/pm3386.h
+++ b/drivers/net/ixp2000/pm3386.h
@@ -13,6 +13,7 @@
#define __PM3386_H
void pm3386_reset(void);
+int pm3386_port_count(void);
void pm3386_init_port(int port);
void pm3386_get_mac(int port, u8 *mac);
void pm3386_set_mac(int port, u8 *mac);
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 0c13795dca3..b79d6e8d304 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -172,7 +172,7 @@ static struct net_device_stats *get_stats(struct net_device *dev)
memset(stats, 0, sizeof(struct net_device_stats));
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
struct net_device_stats *lb_stats;
lb_stats = &per_cpu(loopback_stats, i);
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 9f2661355a4..411f4d809c4 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -281,10 +281,16 @@ static void mv643xx_eth_tx_timeout_task(struct net_device *dev)
{
struct mv643xx_private *mp = netdev_priv(dev);
- netif_device_detach(dev);
+ if (!netif_running(dev))
+ return;
+
+ netif_stop_queue(dev);
+
eth_port_reset(mp->port_num);
eth_port_start(dev);
- netif_device_attach(dev);
+
+ if (mp->tx_ring_size - mp->tx_desc_count >= MAX_DESCS_PER_SKB)
+ netif_wake_queue(dev);
}
/**
@@ -552,9 +558,9 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
#else
if (eth_int_cause & ETH_INT_CAUSE_RX)
mv643xx_eth_receive_queue(dev, INT_MAX);
+#endif
if (eth_int_cause_ext & ETH_INT_CAUSE_TX)
mv643xx_eth_free_completed_tx_descs(dev);
-#endif
/*
* If no real interrupt occured, exit.
@@ -1186,7 +1192,12 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
BUG_ON(netif_queue_stopped(dev));
BUG_ON(skb == NULL);
- BUG_ON(mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB);
+
+ if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) {
+ printk(KERN_ERR "%s: transmit with queue full\n", dev->name);
+ netif_stop_queue(dev);
+ return 1;
+ }
if (has_tiny_unaligned_frags(skb)) {
if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
@@ -1408,6 +1419,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
mv643xx_eth_update_pscr(dev, &cmd);
mv643xx_set_settings(dev, &cmd);
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
err = register_netdev(dev);
if (err)
goto out;
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 8d4999837b6..90627756d6f 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -226,7 +226,7 @@ static int full_duplex[MAX_UNITS];
NATSEMI_PG1_NREGS)
#define NATSEMI_REGS_VER 1 /* v1 added RFDR registers */
#define NATSEMI_REGS_SIZE (NATSEMI_NREGS * sizeof(u32))
-#define NATSEMI_EEPROM_SIZE 24 /* 12 16-bit values */
+#define NATSEMI_DEF_EEPROM_SIZE 24 /* 12 16-bit values */
/* Buffer sizes:
* The nic writes 32-bit values, even if the upper bytes of
@@ -238,7 +238,7 @@ static int full_duplex[MAX_UNITS];
#define NATSEMI_RX_LIMIT 2046 /* maximum supported by hardware */
/* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
KERN_INFO DRV_NAME " dp8381x driver, version "
DRV_VERSION ", " DRV_RELDATE "\n"
KERN_INFO " originally by Donald Becker <becker@scyld.com>\n"
@@ -714,6 +714,8 @@ struct netdev_private {
unsigned int iosize;
spinlock_t lock;
u32 msg_enable;
+ /* EEPROM data */
+ int eeprom_size;
};
static void move_int_phy(struct net_device *dev, int addr);
@@ -890,6 +892,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
np->msg_enable = (debug >= 0) ? (1<<debug)-1 : NATSEMI_DEF_MSG;
np->hands_off = 0;
np->intr_status = 0;
+ np->eeprom_size = NATSEMI_DEF_EEPROM_SIZE;
/* Initial port:
* - If the nic was configured to use an external phy and if find_mii
@@ -2582,7 +2585,8 @@ static int get_regs_len(struct net_device *dev)
static int get_eeprom_len(struct net_device *dev)
{
- return NATSEMI_EEPROM_SIZE;
+ struct netdev_private *np = netdev_priv(dev);
+ return np->eeprom_size;
}
static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
@@ -2669,15 +2673,20 @@ static u32 get_link(struct net_device *dev)
static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
{
struct netdev_private *np = netdev_priv(dev);
- u8 eebuf[NATSEMI_EEPROM_SIZE];
+ u8 *eebuf;
int res;
+ eebuf = kmalloc(np->eeprom_size, GFP_KERNEL);
+ if (!eebuf)
+ return -ENOMEM;
+
eeprom->magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16);
spin_lock_irq(&np->lock);
res = netdev_get_eeprom(dev, eebuf);
spin_unlock_irq(&np->lock);
if (!res)
memcpy(data, eebuf+eeprom->offset, eeprom->len);
+ kfree(eebuf);
return res;
}
@@ -3033,9 +3042,10 @@ static int netdev_get_eeprom(struct net_device *dev, u8 *buf)
int i;
u16 *ebuf = (u16 *)buf;
void __iomem * ioaddr = ns_ioaddr(dev);
+ struct netdev_private *np = netdev_priv(dev);
/* eeprom_read reads 16 bits, and indexes by 16 bits */
- for (i = 0; i < NATSEMI_EEPROM_SIZE/2; i++) {
+ for (i = 0; i < np->eeprom_size/2; i++) {
ebuf[i] = eeprom_read(ioaddr, i);
/* The EEPROM itself stores data bit-swapped, but eeprom_read
* reads it back "sanely". So we swap it back here in order to
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 08b218c5bfb..b32765215f7 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -139,8 +139,9 @@ bad_clone_list[] __initdata = {
#if defined(CONFIG_PLAT_MAPPI)
# define DCR_VAL 0x4b
-#elif defined(CONFIG_PLAT_OAKS32R)
-# define DCR_VAL 0x48
+#elif defined(CONFIG_PLAT_OAKS32R) || \
+ defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+# define DCR_VAL 0x48 /* 8-bit mode */
#else
# define DCR_VAL 0x49
#endif
@@ -226,7 +227,7 @@ struct net_device * __init ne_probe(int unit)
netdev_boot_setup_check(dev);
#ifdef CONFIG_TOSHIBA_RBTX4938
- dev->base_addr = 0x07f20280;
+ dev->base_addr = RBTX4938_RTL_8019_BASE;
dev->irq = RBTX4938_RTL_8019_IRQ;
#endif
err = do_ne_probe(dev);
@@ -396,10 +397,22 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
/* We must set the 8390 for word mode. */
outb_p(DCR_VAL, ioaddr + EN0_DCFG);
start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
+
+ /*
+ * Realtek RTL8019AS datasheet says that the PSTOP register
+ * shouldn't exceed 0x60 in 8-bit mode.
+ * This chip can be identified by reading the signature from
+ * the remote byte count registers (otherwise write-only)...
+ */
+ if ((DCR_VAL & 0x01) == 0 && /* 8-bit mode */
+ inb(ioaddr + EN0_RCNTLO) == 0x50 &&
+ inb(ioaddr + EN0_RCNTHI) == 0x70)
+ stop_page = 0x60;
+ else
+ stop_page = NESM_STOP_PG;
} else {
start_page = NE1SM_START_PG;
- stop_page = NE1SM_STOP_PG;
+ stop_page = NE1SM_STOP_PG;
}
#if defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R)
@@ -509,15 +522,9 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
ei_status.name = name;
ei_status.tx_start_page = start_page;
ei_status.stop_page = stop_page;
-#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
- wordlength = 1;
-#endif
-#ifdef CONFIG_PLAT_OAKS32R
- ei_status.word16 = 0;
-#else
- ei_status.word16 = (wordlength == 2);
-#endif
+ /* Use 16-bit mode only if this wasn't overridden by DCR_VAL */
+ ei_status.word16 = (wordlength == 2 && (DCR_VAL & 0x01));
ei_status.rx_start_page = start_page + TX_PAGES;
#ifdef PACKETBUF_MEMSIZE
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index d11821dd86e..ced9fdb8335 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -645,9 +645,7 @@ static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- if (!dev)
- BUG();
-
+ BUG_ON(!dev);
unregister_netdev(dev);
release_region(dev->base_addr, NE_IO_EXTENT);
free_netdev(dev);
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index edd1b5306b1..bf58db29e2e 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -87,6 +87,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
}
static struct console netconsole = {
+ .name = "netcon",
.flags = CON_ENABLED | CON_PRINTBUFFER,
.write = write_msg
};
@@ -94,7 +95,7 @@ static struct console netconsole = {
static int option_setup(char *opt)
{
configured = !netpoll_parse_options(&np, opt);
- return 0;
+ return 1;
}
__setup("netconsole=", option_setup);
@@ -106,7 +107,7 @@ static int init_netconsole(void)
if(!configured) {
printk("netconsole: not configured, aborting\n");
- return -EINVAL;
+ return 0;
}
if(netpoll_setup(&np))
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 0fede50abd3..706aed7d717 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -568,8 +568,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb)
#endif
sg = dev->rx_info.descs + (next_empty * DESC_SIZE);
- if (unlikely(NULL != dev->rx_info.skbs[next_empty]))
- BUG();
+ BUG_ON(NULL != dev->rx_info.skbs[next_empty]);
dev->rx_info.skbs[next_empty] = skb;
dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC;
@@ -1828,10 +1827,10 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
int using_dac = 0;
/* See if we can set the dma mask early on; failure is fatal. */
- if (sizeof(dma_addr_t) == 8 &&
- !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) {
+ if (sizeof(dma_addr_t) == 8 &&
+ !pci_set_dma_mask(pci_dev, DMA_64BIT_MASK)) {
using_dac = 1;
- } else if (!pci_set_dma_mask(pci_dev, 0xffffffff)) {
+ } else if (!pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) {
using_dac = 0;
} else {
printk(KERN_WARNING "ns83820.c: pci_set_dma_mask failed!\n");
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index ce90becb8bd..fab93360f01 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -204,7 +204,7 @@ enum Window4 { /* Window 4: Xcvr/media bits. */
#define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */
struct el3_private {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct net_device_stats stats;
u16 advertising, partner; /* NWay media advertisement */
@@ -225,8 +225,8 @@ static char mii_preamble_required = 0;
/* Index of functions. */
-static void tc574_config(dev_link_t *link);
-static void tc574_release(dev_link_t *link);
+static int tc574_config(struct pcmcia_device *link);
+static void tc574_release(struct pcmcia_device *link);
static void mdio_sync(kio_addr_t ioaddr, int bits);
static int mdio_read(kio_addr_t ioaddr, int phy_id, int location);
@@ -256,10 +256,9 @@ static void tc574_detach(struct pcmcia_device *p_dev);
with Card Services.
*/
-static int tc574_attach(struct pcmcia_device *p_dev)
+static int tc574_probe(struct pcmcia_device *link)
{
struct el3_private *lp;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "3c574_attach()\n");
@@ -269,8 +268,8 @@ static int tc574_attach(struct pcmcia_device *p_dev)
if (!dev)
return -ENOMEM;
lp = netdev_priv(dev);
- link = &lp->link;
link->priv = dev;
+ lp->p_dev = link;
spin_lock_init(&lp->window_lock);
link->io.NumPorts1 = 32;
@@ -280,7 +279,6 @@ static int tc574_attach(struct pcmcia_device *p_dev)
link->irq.Handler = &el3_interrupt;
link->irq.Instance = dev;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
@@ -298,13 +296,7 @@ static int tc574_attach(struct pcmcia_device *p_dev)
dev->watchdog_timeo = TX_TIMEOUT;
#endif
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- tc574_config(link);
-
- return 0;
+ return tc574_config(link);
} /* tc574_attach */
/*
@@ -316,18 +308,16 @@ static int tc574_attach(struct pcmcia_device *p_dev)
*/
-static void tc574_detach(struct pcmcia_device *p_dev)
+static void tc574_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "3c574_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- tc574_release(link);
+ tc574_release(link);
free_netdev(dev);
} /* tc574_detach */
@@ -343,9 +333,8 @@ static void tc574_detach(struct pcmcia_device *p_dev)
static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
-static void tc574_config(dev_link_t *link)
+static int tc574_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
struct el3_private *lp = netdev_priv(dev);
tuple_t tuple;
@@ -363,30 +352,27 @@ static void tc574_config(dev_link_t *link)
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
link->io.IOAddrLines = 16;
for (i = j = 0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
@@ -397,8 +383,8 @@ static void tc574_config(dev_link_t *link)
the hardware address. The future products may include a modem chip
and put the address in the CIS. */
tuple.DesiredTuple = 0x88;
- if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) {
- pcmcia_get_tuple_data(handle, &tuple);
+ if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+ pcmcia_get_tuple_data(link, &tuple);
for (i = 0; i < 3; i++)
phys_addr[i] = htons(buf[i]);
} else {
@@ -412,9 +398,9 @@ static void tc574_config(dev_link_t *link)
}
}
tuple.DesiredTuple = CISTPL_VERS_1;
- if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS &&
- pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS &&
- pcmcia_parse_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
+ if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS &&
+ pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS &&
+ pcmcia_parse_tuple(link, &tuple, &parse) == CS_SUCCESS) {
cardname = parse.version_1.str + parse.version_1.ofs[1];
} else
cardname = "3Com 3c574";
@@ -473,13 +459,12 @@ static void tc574_config(dev_link_t *link)
}
}
- link->state &= ~DEV_CONFIG_PENDING;
- link->dev = &lp->node;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &lp->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -493,13 +478,13 @@ static void tc574_config(dev_link_t *link)
8 << config.u.ram_size, ram_split[config.u.ram_split],
config.u.autoselect ? "autoselect " : "");
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
tc574_release(link);
- return;
+ return -ENODEV;
} /* tc574_config */
@@ -509,44 +494,28 @@ failed:
still open, this will be postponed until it is closed.
*/
-static void tc574_release(dev_link_t *link)
+static void tc574_release(struct pcmcia_device *link)
{
- DEBUG(0, "3c574_release(0x%p)\n", link);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static int tc574_suspend(struct pcmcia_device *p_dev)
+static int tc574_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int tc574_resume(struct pcmcia_device *p_dev)
+static int tc574_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- tc574_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ tc574_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -757,9 +726,9 @@ static void tc574_reset(struct net_device *dev)
static int el3_open(struct net_device *dev)
{
struct el3_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -1203,11 +1172,11 @@ static int el3_close(struct net_device *dev)
{
kio_addr_t ioaddr = dev->base_addr;
struct el3_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
- if (DEV_OK(link)) {
+ if (pcmcia_dev_present(link)) {
unsigned long flags;
/* Turn off statistics ASAP. We update lp->stats below. */
@@ -1246,7 +1215,7 @@ static struct pcmcia_driver tc574_driver = {
.drv = {
.name = "3c574_cs",
},
- .probe = tc574_attach,
+ .probe = tc574_probe,
.remove = tc574_detach,
.id_table = tc574_ids,
.suspend = tc574_suspend,
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 3dba50849da..875a0fe251e 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -105,7 +105,7 @@ enum RxFilter {
#define TX_TIMEOUT ((400*HZ)/1000)
struct el3_private {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct net_device_stats stats;
/* For transceiver monitoring */
@@ -142,8 +142,8 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)";
/*====================================================================*/
-static void tc589_config(dev_link_t *link);
-static void tc589_release(dev_link_t *link);
+static int tc589_config(struct pcmcia_device *link);
+static void tc589_release(struct pcmcia_device *link);
static u16 read_eeprom(kio_addr_t ioaddr, int index);
static void tc589_reset(struct net_device *dev);
@@ -170,10 +170,9 @@ static void tc589_detach(struct pcmcia_device *p_dev);
======================================================================*/
-static int tc589_attach(struct pcmcia_device *p_dev)
+static int tc589_probe(struct pcmcia_device *link)
{
struct el3_private *lp;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "3c589_attach()\n");
@@ -183,8 +182,8 @@ static int tc589_attach(struct pcmcia_device *p_dev)
if (!dev)
return -ENOMEM;
lp = netdev_priv(dev);
- link = &lp->link;
link->priv = dev;
+ lp->p_dev = link;
spin_lock_init(&lp->lock);
link->io.NumPorts1 = 16;
@@ -194,7 +193,6 @@ static int tc589_attach(struct pcmcia_device *p_dev)
link->irq.Handler = &el3_interrupt;
link->irq.Instance = dev;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
@@ -213,13 +211,7 @@ static int tc589_attach(struct pcmcia_device *p_dev)
#endif
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- tc589_config(link);
-
- return 0;
+ return tc589_config(link);
} /* tc589_attach */
/*======================================================================
@@ -231,18 +223,16 @@ static int tc589_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void tc589_detach(struct pcmcia_device *p_dev)
+static void tc589_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "3c589_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- tc589_release(link);
+ tc589_release(link);
free_netdev(dev);
} /* tc589_detach */
@@ -258,9 +248,8 @@ static void tc589_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void tc589_config(dev_link_t *link)
+static int tc589_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
struct el3_private *lp = netdev_priv(dev);
tuple_t tuple;
@@ -275,43 +264,40 @@ static void tc589_config(dev_link_t *link)
phys_addr = (u16 *)dev->dev_addr;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* Is this a 3c562? */
tuple.DesiredTuple = CISTPL_MANFID;
tuple.Attributes = TUPLE_RETURN_COMMON;
- if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
- (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) {
+ if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
+ (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) {
if (le16_to_cpu(buf[0]) != MANFID_3COM)
printk(KERN_INFO "3c589_cs: hmmm, is this really a "
"3Com card??\n");
multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562);
}
-
- /* Configure card */
- link->state |= DEV_CONFIG;
/* For the 3c562, the base address must be xx00-xx7f */
link->io.IOAddrLines = 16;
for (i = j = 0; j < 0x400; j += 0x10) {
if (multi && (j & 0x80)) continue;
link->io.BasePort1 = j ^ 0x300;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
@@ -321,8 +307,8 @@ static void tc589_config(dev_link_t *link)
/* The 3c589 has an extra EEPROM for configuration info, including
the hardware address. The 3c562 puts the address in the CIS. */
tuple.DesiredTuple = 0x88;
- if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) {
- pcmcia_get_tuple_data(handle, &tuple);
+ if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+ pcmcia_get_tuple_data(link, &tuple);
for (i = 0; i < 3; i++)
phys_addr[i] = htons(buf[i]);
} else {
@@ -346,13 +332,12 @@ static void tc589_config(dev_link_t *link)
else
printk(KERN_ERR "3c589_cs: invalid if_port requested\n");
- link->dev = &lp->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &lp->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev) != 0) {
printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -366,14 +351,13 @@ static void tc589_config(dev_link_t *link)
printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n",
(fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
if_names[dev->if_port]);
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
tc589_release(link);
- return;
-
+ return -ENODEV;
} /* tc589_config */
/*======================================================================
@@ -384,44 +368,28 @@ failed:
======================================================================*/
-static void tc589_release(dev_link_t *link)
+static void tc589_release(struct pcmcia_device *link)
{
- DEBUG(0, "3c589_release(0x%p)\n", link);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static int tc589_suspend(struct pcmcia_device *p_dev)
+static int tc589_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int tc589_resume(struct pcmcia_device *p_dev)
+static int tc589_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- tc589_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ tc589_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -587,9 +555,9 @@ static int el3_config(struct net_device *dev, struct ifmap *map)
static int el3_open(struct net_device *dev)
{
struct el3_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -848,9 +816,9 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
{
struct el3_private *lp = netdev_priv(dev);
unsigned long flags;
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
- if (DEV_OK(link)) {
+ if (pcmcia_dev_present(link)) {
spin_lock_irqsave(&lp->lock, flags);
update_stats(dev);
spin_unlock_irqrestore(&lp->lock, flags);
@@ -950,11 +918,11 @@ static int el3_rx(struct net_device *dev)
static void set_multicast_list(struct net_device *dev)
{
struct el3_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
kio_addr_t ioaddr = dev->base_addr;
u16 opts = SetRxFilter | RxStation | RxBroadcast;
- if (!(DEV_OK(link))) return;
+ if (!pcmcia_dev_present(link)) return;
if (dev->flags & IFF_PROMISC)
opts |= RxMulticast | RxProm;
else if (dev->mc_count || (dev->flags & IFF_ALLMULTI))
@@ -965,12 +933,12 @@ static void set_multicast_list(struct net_device *dev)
static int el3_close(struct net_device *dev)
{
struct el3_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
kio_addr_t ioaddr = dev->base_addr;
DEBUG(1, "%s: shutting down ethercard.\n", dev->name);
- if (DEV_OK(link)) {
+ if (pcmcia_dev_present(link)) {
/* Turn off statistics ASAP. We update lp->stats below. */
outw(StatsDisable, ioaddr + EL3_CMD);
@@ -1020,7 +988,7 @@ static struct pcmcia_driver tc589_driver = {
.drv = {
.name = "3c589_cs",
},
- .probe = tc589_attach,
+ .probe = tc589_probe,
.remove = tc589_detach,
.id_table = tc589_ids,
.suspend = tc589_suspend,
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index aa558136939..2ea66aca648 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -35,6 +35,7 @@
#include <linux/spinlock.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
+#include <linux/crc32.h>
#include "../8390.h"
#include <pcmcia/cs_types.h>
@@ -85,8 +86,8 @@ static char *version =
/*====================================================================*/
-static void axnet_config(dev_link_t *link);
-static void axnet_release(dev_link_t *link);
+static int axnet_config(struct pcmcia_device *link);
+static void axnet_release(struct pcmcia_device *link);
static int axnet_open(struct net_device *dev);
static int axnet_close(struct net_device *dev);
static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -116,7 +117,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id, struct pt_regs *regs);
/*====================================================================*/
typedef struct axnet_dev_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
caddr_t base;
struct timer_list watchdog;
@@ -141,10 +142,9 @@ static inline axnet_dev_t *PRIV(struct net_device *dev)
======================================================================*/
-static int axnet_attach(struct pcmcia_device *p_dev)
+static int axnet_probe(struct pcmcia_device *link)
{
axnet_dev_t *info;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "axnet_attach()\n");
@@ -156,7 +156,7 @@ static int axnet_attach(struct pcmcia_device *p_dev)
return -ENOMEM;
info = PRIV(dev);
- link = &info->link;
+ info->p_dev = link;
link->priv = dev;
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
@@ -168,13 +168,7 @@ static int axnet_attach(struct pcmcia_device *p_dev)
dev->do_ioctl = &axnet_ioctl;
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- axnet_config(link);
-
- return 0;
+ return axnet_config(link);
} /* axnet_attach */
/*======================================================================
@@ -186,18 +180,16 @@ static int axnet_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void axnet_detach(struct pcmcia_device *p_dev)
+static void axnet_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "axnet_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- axnet_release(link);
+ axnet_release(link);
free_netdev(dev);
} /* axnet_detach */
@@ -208,7 +200,7 @@ static void axnet_detach(struct pcmcia_device *p_dev)
======================================================================*/
-static int get_prom(dev_link_t *link)
+static int get_prom(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
kio_addr_t ioaddr = dev->base_addr;
@@ -262,7 +254,7 @@ static int get_prom(dev_link_t *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static int try_io_port(dev_link_t *link)
+static int try_io_port(struct pcmcia_device *link)
{
int j, ret;
if (link->io.NumPorts1 == 32) {
@@ -283,25 +275,23 @@ static int try_io_port(dev_link_t *link)
for (j = 0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
link->io.BasePort2 = (j ^ 0x300) + 0x10;
- ret = pcmcia_request_io(link->handle, &link->io);
+ ret = pcmcia_request_io(link, &link->io);
if (ret == CS_SUCCESS) return ret;
}
return ret;
} else {
- return pcmcia_request_io(link->handle, &link->io);
+ return pcmcia_request_io(link, &link->io);
}
}
-static void axnet_config(dev_link_t *link)
+static int axnet_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
axnet_dev_t *info = PRIV(dev);
tuple_t tuple;
cisparse_t parse;
int i, j, last_ret, last_fn;
u_short buf[64];
- config_info_t conf;
DEBUG(0, "axnet_config(0x%p)\n", link);
@@ -310,29 +300,22 @@ static void axnet_config(dev_link_t *link)
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
/* don't trust the CIS on this; Linksys got it wrong */
link->conf.Present = 0x63;
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- /* Look up current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
-
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (last_ret == CS_SUCCESS) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
cistpl_io_t *io = &(parse.cftable_entry.io);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0 ||
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
cfg->index == 0 || cfg->io.nwin == 0)
goto next_entry;
@@ -354,21 +337,21 @@ static void axnet_config(dev_link_t *link)
if (last_ret == CS_SUCCESS) break;
}
next_entry:
- last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ last_ret = pcmcia_get_next_tuple(link, &tuple);
}
if (last_ret != CS_SUCCESS) {
- cs_error(handle, RequestIO, last_ret);
+ cs_error(link, RequestIO, last_ret);
goto failed;
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
if (link->io.NumPorts2 == 8) {
link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA;
}
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
@@ -405,7 +388,7 @@ static void axnet_config(dev_link_t *link)
Bit 2 of CCSR is active low. */
if (i == 32) {
conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 };
- pcmcia_access_configuration_register(link->handle, &reg);
+ pcmcia_access_configuration_register(link, &reg);
for (i = 0; i < 32; i++) {
j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
if ((j != 0) && (j != 0xffff)) break;
@@ -413,13 +396,12 @@ static void axnet_config(dev_link_t *link)
}
info->phy_id = (i < 32) ? i : -1;
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &info->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -435,14 +417,13 @@ static void axnet_config(dev_link_t *link)
} else {
printk(KERN_NOTICE " No MII transceivers found!\n");
}
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
axnet_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return -ENODEV;
} /* axnet_config */
/*======================================================================
@@ -453,45 +434,29 @@ failed:
======================================================================*/
-static void axnet_release(dev_link_t *link)
+static void axnet_release(struct pcmcia_device *link)
{
- DEBUG(0, "axnet_release(0x%p)\n", link);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static int axnet_suspend(struct pcmcia_device *p_dev)
+static int axnet_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int axnet_resume(struct pcmcia_device *p_dev)
+static int axnet_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- axnet_reset_8390(dev);
- AX88190_init(dev, 1);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ axnet_reset_8390(dev);
+ AX88190_init(dev, 1);
+ netif_device_attach(dev);
}
return 0;
@@ -561,11 +526,11 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value)
static int axnet_open(struct net_device *dev)
{
axnet_dev_t *info = PRIV(dev);
- dev_link_t *link = &info->link;
+ struct pcmcia_device *link = info->p_dev;
DEBUG(2, "axnet_open('%s')\n", dev->name);
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -587,7 +552,7 @@ static int axnet_open(struct net_device *dev)
static int axnet_close(struct net_device *dev)
{
axnet_dev_t *info = PRIV(dev);
- dev_link_t *link = &info->link;
+ struct pcmcia_device *link = info->p_dev;
DEBUG(2, "axnet_close('%s')\n", dev->name);
@@ -832,7 +797,7 @@ static struct pcmcia_driver axnet_cs_driver = {
.drv = {
.name = "axnet_cs",
},
- .probe = axnet_attach,
+ .probe = axnet_probe,
.remove = axnet_detach,
.id_table = axnet_ids,
.suspend = axnet_suspend,
@@ -1595,7 +1560,7 @@ static void ei_receive(struct net_device *dev)
static void ei_rx_overrun(struct net_device *dev)
{
- axnet_dev_t *info = (axnet_dev_t *)dev;
+ axnet_dev_t *info = PRIV(dev);
long e8390_base = dev->base_addr;
unsigned char was_txing, must_resend = 0;
struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
@@ -1682,17 +1647,56 @@ static struct net_device_stats *get_stats(struct net_device *dev)
return &ei_local->stat;
}
+/*
+ * Form the 64 bit 8390 multicast table from the linked list of addresses
+ * associated with this dev structure.
+ */
+
+static inline void make_mc_bits(u8 *bits, struct net_device *dev)
+{
+ struct dev_mc_list *dmi;
+ u32 crc;
+
+ for (dmi=dev->mc_list; dmi; dmi=dmi->next) {
+
+ crc = ether_crc(ETH_ALEN, dmi->dmi_addr);
+ /*
+ * The 8390 uses the 6 most significant bits of the
+ * CRC to index the multicast table.
+ */
+ bits[crc>>29] |= (1<<((crc>>26)&7));
+ }
+}
+
/**
* do_set_multicast_list - set/clear multicast filter
* @dev: net device for which multicast filter is adjusted
*
- * Set or clear the multicast filter for this adaptor. May be called
- * from a BH in 2.1.x. Must be called with lock held.
+ * Set or clear the multicast filter for this adaptor.
+ * Must be called with lock held.
*/
static void do_set_multicast_list(struct net_device *dev)
{
long e8390_base = dev->base_addr;
+ int i;
+ struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev);
+
+ if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
+ memset(ei_local->mcfilter, 0, 8);
+ if (dev->mc_list)
+ make_mc_bits(ei_local->mcfilter, dev);
+ } else {
+ /* set to accept-all */
+ memset(ei_local->mcfilter, 0xFF, 8);
+ }
+
+ outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
+ for(i = 0; i < 8; i++)
+ {
+ outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
+ }
+ outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
if(dev->flags&IFF_PROMISC)
outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR);
@@ -1700,6 +1704,8 @@ static void do_set_multicast_list(struct net_device *dev)
outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR);
else
outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR);
+
+ outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
}
/*
@@ -1794,12 +1800,6 @@ static void AX88190_init(struct net_device *dev, int startp)
if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
}
- /*
- * Initialize the multicast list to accept-all. If we enable multicast
- * the higher levels can do the filtering.
- */
- for (i = 0; i < 8; i++)
- outb_p(0xff, e8390_base + EN1_MULT + i);
outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 2827a48ea37..441de824ab6 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -118,8 +118,8 @@ MODULE_LICENSE("GPL");
/*====================================================================*/
-static void com20020_config(dev_link_t *link);
-static void com20020_release(dev_link_t *link);
+static int com20020_config(struct pcmcia_device *link);
+static void com20020_release(struct pcmcia_device *link);
static void com20020_detach(struct pcmcia_device *p_dev);
@@ -138,9 +138,8 @@ typedef struct com20020_dev_t {
======================================================================*/
-static int com20020_attach(struct pcmcia_device *p_dev)
+static int com20020_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
com20020_dev_t *info;
struct net_device *dev;
struct arcnet_local *lp;
@@ -148,10 +147,6 @@ static int com20020_attach(struct pcmcia_device *p_dev)
DEBUG(0, "com20020_attach()\n");
/* Create new network device */
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link)
- return -ENOMEM;
-
info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
if (!info)
goto fail_alloc_info;
@@ -161,7 +156,6 @@ static int com20020_attach(struct pcmcia_device *p_dev)
goto fail_alloc_dev;
memset(info, 0, sizeof(struct com20020_dev_t));
- memset(link, 0, sizeof(struct dev_link_t));
lp = dev->priv;
lp->timeout = timeout;
lp->backplane = backplane;
@@ -172,28 +166,23 @@ static int com20020_attach(struct pcmcia_device *p_dev)
/* fill in our module parameters as defaults */
dev->dev_addr[0] = node;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.NumPorts1 = 16;
- link->io.IOAddrLines = 16;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.Present = PRESENT_OPTION;
-
- link->irq.Instance = info->dev = dev;
- link->priv = info;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.NumPorts1 = 16;
+ p_dev->io.IOAddrLines = 16;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.Present = PRESENT_OPTION;
- link->state |= DEV_PRESENT;
- com20020_config(link);
+ p_dev->irq.Instance = info->dev = dev;
+ p_dev->priv = info;
- return 0;
+ return com20020_config(p_dev);
fail_alloc_dev:
kfree(info);
fail_alloc_info:
- kfree(link);
return -ENOMEM;
} /* com20020_attach */
@@ -206,9 +195,8 @@ fail_alloc_info:
======================================================================*/
-static void com20020_detach(struct pcmcia_device *p_dev)
+static void com20020_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct com20020_dev_t *info = link->priv;
struct net_device *dev = info->dev;
@@ -216,7 +204,7 @@ static void com20020_detach(struct pcmcia_device *p_dev)
DEBUG(0, "com20020_detach(0x%p)\n", link);
- if (link->dev) {
+ if (link->dev_node) {
DEBUG(1,"unregister...\n");
unregister_netdev(dev);
@@ -229,8 +217,7 @@ static void com20020_detach(struct pcmcia_device *p_dev)
free_irq(dev->irq, dev);
}
- if (link->state & DEV_CONFIG)
- com20020_release(link);
+ com20020_release(link);
/* Unlink device structure, free bits */
DEBUG(1,"unlinking...\n");
@@ -245,8 +232,6 @@ static void com20020_detach(struct pcmcia_device *p_dev)
DEBUG(1,"kfree2...\n");
kfree(info);
}
- DEBUG(1,"kfree3...\n");
- kfree(link);
} /* com20020_detach */
@@ -261,10 +246,9 @@ static void com20020_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void com20020_config(dev_link_t *link)
+static int com20020_config(struct pcmcia_device *link)
{
struct arcnet_local *lp;
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
com20020_dev_t *info;
@@ -273,7 +257,6 @@ static void com20020_config(dev_link_t *link)
u_char buf[64];
int ioaddr;
- handle = link->handle;
info = link->priv;
dev = info->dev;
@@ -286,14 +269,11 @@ static void com20020_config(dev_link_t *link)
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
- /* Configure card */
- link->state |= DEV_CONFIG;
-
DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
i = !CS_SUCCESS;
if (!link->io.BasePort1)
@@ -301,13 +281,13 @@ static void com20020_config(dev_link_t *link)
for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
{
link->io.BasePort1 = ioaddr;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
}
else
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i != CS_SUCCESS)
{
@@ -321,7 +301,7 @@ static void com20020_config(dev_link_t *link)
DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
link->irq.AssignedIRQ,
link->irq.IRQInfo1, link->irq.IRQInfo2);
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS)
{
DEBUG(1,"arcnet: requestIRQ failed totally!\n");
@@ -330,7 +310,7 @@ static void com20020_config(dev_link_t *link)
dev->irq = link->irq.AssignedIRQ;
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
if (com20020_check(dev))
{
@@ -342,15 +322,14 @@ static void com20020_config(dev_link_t *link)
lp->card_name = "PCMCIA COM20020";
lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &info->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
i = com20020_found(dev, 0); /* calls register_netdev */
if (i != 0) {
DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -358,13 +337,14 @@ static void com20020_config(dev_link_t *link)
DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
dev->name, dev->base_addr, dev->irq);
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
DEBUG(1,"com20020_config failed...\n");
com20020_release(link);
+ return -ENODEV;
} /* com20020_config */
/*======================================================================
@@ -375,52 +355,33 @@ failed:
======================================================================*/
-static void com20020_release(dev_link_t *link)
+static void com20020_release(struct pcmcia_device *link)
{
-
- DEBUG(1,"release...\n");
-
- DEBUG(0, "com20020_release(0x%p)\n", link);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+ DEBUG(0, "com20020_release(0x%p)\n", link);
+ pcmcia_disable_device(link);
}
-static int com20020_suspend(struct pcmcia_device *p_dev)
+static int com20020_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
com20020_dev_t *info = link->priv;
struct net_device *dev = info->dev;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open) {
- netif_device_detach(dev);
- }
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int com20020_resume(struct pcmcia_device *p_dev)
+static int com20020_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
com20020_dev_t *info = link->priv;
struct net_device *dev = info->dev;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- int ioaddr = dev->base_addr;
- struct arcnet_local *lp = dev->priv;
- ARCRESET;
- }
- }
+ if (link->open) {
+ int ioaddr = dev->base_addr;
+ struct arcnet_local *lp = dev->priv;
+ ARCRESET;
+ }
return 0;
}
@@ -436,7 +397,7 @@ static struct pcmcia_driver com20020_cs_driver = {
.drv = {
.name = "com20020_cs",
},
- .probe = com20020_attach,
+ .probe = com20020_probe,
.remove = com20020_detach,
.id_table = com20020_ids,
.suspend = com20020_suspend,
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index b7ac14ba887..09b11761cdf 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -84,10 +84,10 @@ static char *version = DRV_NAME ".c " DRV_VERSION " 2002/03/23";
/*
PCMCIA event handlers
*/
-static void fmvj18x_config(dev_link_t *link);
-static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id);
-static int fmvj18x_setup_mfc(dev_link_t *link);
-static void fmvj18x_release(dev_link_t *link);
+static int fmvj18x_config(struct pcmcia_device *link);
+static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id);
+static int fmvj18x_setup_mfc(struct pcmcia_device *link);
+static void fmvj18x_release(struct pcmcia_device *link);
static void fmvj18x_detach(struct pcmcia_device *p_dev);
/*
@@ -116,7 +116,7 @@ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
driver specific data structure
*/
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct net_device_stats stats;
long open_time;
@@ -228,10 +228,9 @@ typedef struct local_info_t {
#define BANK_1U 0x24 /* bank 1 (CONFIG_1) */
#define BANK_2U 0x28 /* bank 2 (CONFIG_1) */
-static int fmvj18x_attach(struct pcmcia_device *p_dev)
+static int fmvj18x_probe(struct pcmcia_device *link)
{
local_info_t *lp;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "fmvj18x_attach()\n");
@@ -241,8 +240,8 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev)
if (!dev)
return -ENOMEM;
lp = netdev_priv(dev);
- link = &lp->link;
link->priv = dev;
+ lp->p_dev = link;
/* The io structure describes IO port mapping */
link->io.NumPorts1 = 32;
@@ -257,7 +256,6 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev)
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
/* The FMVJ18x specific entries in the device structure. */
@@ -274,29 +272,21 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev)
#endif
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- fmvj18x_config(link);
-
- return 0;
+ return fmvj18x_config(link);
} /* fmvj18x_attach */
/*====================================================================*/
-static void fmvj18x_detach(struct pcmcia_device *p_dev)
+static void fmvj18x_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- fmvj18x_release(link);
+ fmvj18x_release(link);
free_netdev(dev);
} /* fmvj18x_detach */
@@ -306,7 +296,7 @@ static void fmvj18x_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static int mfc_try_io_port(dev_link_t *link)
+static int mfc_try_io_port(struct pcmcia_device *link)
{
int i, ret;
static const kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
@@ -318,13 +308,13 @@ static int mfc_try_io_port(dev_link_t *link)
link->io.NumPorts2 = 0;
printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
}
- ret = pcmcia_request_io(link->handle, &link->io);
+ ret = pcmcia_request_io(link, &link->io);
if (ret == CS_SUCCESS) return ret;
}
return ret;
}
-static int ungermann_try_io_port(dev_link_t *link)
+static int ungermann_try_io_port(struct pcmcia_device *link)
{
int ret;
kio_addr_t ioaddr;
@@ -334,7 +324,7 @@ static int ungermann_try_io_port(dev_link_t *link)
*/
for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
link->io.BasePort1 = ioaddr;
- ret = pcmcia_request_io(link->handle, &link->io);
+ ret = pcmcia_request_io(link, &link->io);
if (ret == CS_SUCCESS) {
/* calculate ConfigIndex value */
link->conf.ConfigIndex =
@@ -345,9 +335,8 @@ static int ungermann_try_io_port(dev_link_t *link)
return ret; /* RequestIO failed */
}
-static void fmvj18x_config(dev_link_t *link)
+static int fmvj18x_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
local_info_t *lp = netdev_priv(dev);
tuple_t tuple;
@@ -366,42 +355,34 @@ static void fmvj18x_config(dev_link_t *link)
registers.
*/
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = (u_char *)buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
-
- /* Configure card */
- link->state |= DEV_CONFIG;
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
tuple.DesiredTuple = CISTPL_FUNCE;
tuple.TupleOffset = 0;
- if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) {
+ if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
/* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigIndex = parse.cftable_entry.index;
tuple.DesiredTuple = CISTPL_MANFID;
- if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS)
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS)
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
else
buf[0] = 0xffff;
switch (le16_to_cpu(buf[0])) {
case MANFID_TDK:
cardtype = TDK;
- if (le16_to_cpu(buf[1]) == PRODID_TDK_CF010) {
- cs_status_t status;
- pcmcia_get_status(handle, &status);
- if (status.CardState & CS_EVENT_3VCARD)
- link->conf.Vcc = 33; /* inserted in 3.3V slot */
- } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410
+ if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410
|| le16_to_cpu(buf[1]) == PRODID_TDK_NP9610
|| le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) {
/* MultiFunction Card */
@@ -429,8 +410,8 @@ static void fmvj18x_config(dev_link_t *link)
} else {
/* old type card */
tuple.DesiredTuple = CISTPL_MANFID;
- if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS)
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS)
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
else
buf[0] = 0xffff;
switch (le16_to_cpu(buf[0])) {
@@ -461,10 +442,10 @@ static void fmvj18x_config(dev_link_t *link)
ret = ungermann_try_io_port(link);
if (ret != CS_SUCCESS) goto cs_failed;
} else {
- CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+ CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
@@ -493,17 +474,17 @@ static void fmvj18x_config(dev_link_t *link)
case CONTEC:
tuple.DesiredTuple = CISTPL_FUNCE;
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleOffset = 0;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
if (cardtype == MBH10304) {
/* MBH10304's CIS_FUNCE is corrupted */
node_id = &(tuple.TupleData[5]);
card_name = "FMV-J182";
} else {
while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) {
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
}
node_id = &(tuple.TupleData[2]);
if( cardtype == TDK ) {
@@ -545,13 +526,12 @@ static void fmvj18x_config(dev_link_t *link)
}
lp->cardtype = cardtype;
- link->dev = &lp->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &lp->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -564,19 +544,18 @@ static void fmvj18x_config(dev_link_t *link)
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
- return;
+ return 0;
cs_failed:
/* All Card Services errors end up here */
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
fmvj18x_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
-
+ return -ENODEV;
} /* fmvj18x_config */
/*====================================================================*/
-static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
+static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
{
win_req_t req;
memreq_t mem;
@@ -587,9 +566,9 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = 0; req.Size = 0;
req.AccessSpeed = 0;
- i = pcmcia_request_window(&link->handle, &req, &link->win);
+ i = pcmcia_request_window(&link, &req, &link->win);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestWindow, i);
+ cs_error(link, RequestWindow, i);
return -1;
}
@@ -623,13 +602,13 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
iounmap(base);
j = pcmcia_release_window(link->win);
if (j != CS_SUCCESS)
- cs_error(link->handle, ReleaseWindow, j);
+ cs_error(link, ReleaseWindow, j);
return (i != 0x200) ? 0 : -1;
} /* fmvj18x_get_hwinfo */
/*====================================================================*/
-static int fmvj18x_setup_mfc(dev_link_t *link)
+static int fmvj18x_setup_mfc(struct pcmcia_device *link)
{
win_req_t req;
memreq_t mem;
@@ -642,9 +621,9 @@ static int fmvj18x_setup_mfc(dev_link_t *link)
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = 0; req.Size = 0;
req.AccessSpeed = 0;
- i = pcmcia_request_window(&link->handle, &req, &link->win);
+ i = pcmcia_request_window(&link, &req, &link->win);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestWindow, i);
+ cs_error(link, RequestWindow, i);
return -1;
}
@@ -666,54 +645,35 @@ static int fmvj18x_setup_mfc(dev_link_t *link)
iounmap(base);
j = pcmcia_release_window(link->win);
if (j != CS_SUCCESS)
- cs_error(link->handle, ReleaseWindow, j);
+ cs_error(link, ReleaseWindow, j);
return 0;
}
/*====================================================================*/
-static void fmvj18x_release(dev_link_t *link)
+static void fmvj18x_release(struct pcmcia_device *link)
{
-
- DEBUG(0, "fmvj18x_release(0x%p)\n", link);
-
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ DEBUG(0, "fmvj18x_release(0x%p)\n", link);
+ pcmcia_disable_device(link);
}
-static int fmvj18x_suspend(struct pcmcia_device *p_dev)
+static int fmvj18x_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
-
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int fmvj18x_resume(struct pcmcia_device *p_dev)
+static int fmvj18x_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- fjn_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ fjn_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -751,7 +711,7 @@ static struct pcmcia_driver fmvj18x_cs_driver = {
.drv = {
.name = "fmvj18x_cs",
},
- .probe = fmvj18x_attach,
+ .probe = fmvj18x_probe,
.remove = fmvj18x_detach,
.id_table = fmvj18x_ids,
.suspend = fmvj18x_suspend,
@@ -1148,11 +1108,11 @@ static int fjn_config(struct net_device *dev, struct ifmap *map){
static int fjn_open(struct net_device *dev)
{
struct local_info_t *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
DEBUG(4, "fjn_open('%s').\n", dev->name);
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -1173,7 +1133,7 @@ static int fjn_open(struct net_device *dev)
static int fjn_close(struct net_device *dev)
{
struct local_info_t *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
kio_addr_t ioaddr = dev->base_addr;
DEBUG(4, "fjn_close('%s').\n", dev->name);
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index b9c7e39576f..b8fe70b8564 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -105,15 +105,15 @@ MODULE_LICENSE("GPL");
/*====================================================================*/
-static void ibmtr_config(dev_link_t *link);
+static int ibmtr_config(struct pcmcia_device *link);
static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
-static void ibmtr_release(dev_link_t *link);
+static void ibmtr_release(struct pcmcia_device *link);
static void ibmtr_detach(struct pcmcia_device *p_dev);
/*====================================================================*/
typedef struct ibmtr_dev_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
struct net_device *dev;
dev_node_t node;
window_handle_t sram_win_handle;
@@ -138,12 +138,11 @@ static struct ethtool_ops netdev_ethtool_ops = {
======================================================================*/
-static int ibmtr_attach(struct pcmcia_device *p_dev)
+static int ibmtr_attach(struct pcmcia_device *link)
{
ibmtr_dev_t *info;
- dev_link_t *link;
struct net_device *dev;
-
+
DEBUG(0, "ibmtr_attach()\n");
/* Create new token-ring device */
@@ -156,7 +155,7 @@ static int ibmtr_attach(struct pcmcia_device *p_dev)
return -ENOMEM;
}
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
info->ti = netdev_priv(dev);
@@ -167,21 +166,14 @@ static int ibmtr_attach(struct pcmcia_device *p_dev)
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &tok_interrupt;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
link->irq.Instance = info->dev = dev;
-
- SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
-
- link->handle = p_dev;
- p_dev->instance = link;
- link->state |= DEV_PRESENT;
- ibmtr_config(link);
+ SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
- return 0;
+ return ibmtr_config(link);
} /* ibmtr_attach */
/*======================================================================
@@ -193,23 +185,22 @@ static int ibmtr_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void ibmtr_detach(struct pcmcia_device *p_dev)
+static void ibmtr_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
DEBUG(0, "ibmtr_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
{
struct tok_info *ti = netdev_priv(dev);
del_timer_sync(&(ti->tr_timer));
}
- if (link->state & DEV_CONFIG)
- ibmtr_release(link);
+
+ ibmtr_release(link);
free_netdev(dev);
kfree(info);
@@ -226,9 +217,8 @@ static void ibmtr_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void ibmtr_config(dev_link_t *link)
+static int ibmtr_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
struct tok_info *ti = netdev_priv(dev);
@@ -246,29 +236,25 @@ static void ibmtr_config(dev_link_t *link)
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
-
- /* Configure card */
- link->state |= DEV_CONFIG;
-
link->conf.ConfigIndex = 0x61;
/* Determine if this is PRIMARY or ALTERNATE. */
/* Try PRIMARY card at 0xA20-0xA23 */
link->io.BasePort1 = 0xA20;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i != CS_SUCCESS) {
/* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */
link->io.BasePort1 = 0xA24;
- CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+ CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
}
dev->base_addr = link->io.BasePort1;
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
dev->irq = link->irq.AssignedIRQ;
ti->irq = link->irq.AssignedIRQ;
ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
@@ -279,7 +265,7 @@ static void ibmtr_config(dev_link_t *link)
req.Base = 0;
req.Size = 0x2000;
req.AccessSpeed = 250;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
mem.CardOffset = mmiobase;
mem.Page = 0;
@@ -292,7 +278,7 @@ static void ibmtr_config(dev_link_t *link)
req.Base = 0;
req.Size = sramsize * 1024;
req.AccessSpeed = 250;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &info->sram_win_handle));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &info->sram_win_handle));
mem.CardOffset = srambase;
mem.Page = 0;
@@ -302,21 +288,20 @@ static void ibmtr_config(dev_link_t *link)
ti->sram_virt = ioremap(req.Base, req.Size);
ti->sram_phys = req.Base;
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/* Set up the Token-Ring Controller Configuration Register and
turn on the card. Check the "Local Area Network Credit Card
Adapters Technical Reference" SC30-3585 for this info. */
ibmtr_hw_setup(dev, mmiobase);
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &info->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
i = ibmtr_probe_card(dev);
if (i != 0) {
printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -330,12 +315,13 @@ static void ibmtr_config(dev_link_t *link)
for (i = 0; i < TR_ALEN; i++)
printk("%02X", dev->dev_addr[i]);
printk("\n");
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
ibmtr_release(link);
+ return -ENODEV;
} /* ibmtr_config */
/*======================================================================
@@ -346,56 +332,41 @@ failed:
======================================================================*/
-static void ibmtr_release(dev_link_t *link)
+static void ibmtr_release(struct pcmcia_device *link)
{
- ibmtr_dev_t *info = link->priv;
- struct net_device *dev = info->dev;
-
- DEBUG(0, "ibmtr_release(0x%p)\n", link);
+ ibmtr_dev_t *info = link->priv;
+ struct net_device *dev = info->dev;
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- if (link->win) {
- struct tok_info *ti = netdev_priv(dev);
- iounmap(ti->mmio);
- pcmcia_release_window(link->win);
- pcmcia_release_window(info->sram_win_handle);
- }
+ DEBUG(0, "ibmtr_release(0x%p)\n", link);
- link->state &= ~DEV_CONFIG;
+ if (link->win) {
+ struct tok_info *ti = netdev_priv(dev);
+ iounmap(ti->mmio);
+ pcmcia_release_window(info->sram_win_handle);
+ }
+ pcmcia_disable_device(link);
}
-static int ibmtr_suspend(struct pcmcia_device *p_dev)
+static int ibmtr_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int ibmtr_resume(struct pcmcia_device *p_dev)
+static int ibmtr_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- ibmtr_probe(dev); /* really? */
- netif_device_attach(dev);
- }
- }
+ if (link->open) {
+ ibmtr_probe(dev); /* really? */
+ netif_device_attach(dev);
+ }
return 0;
}
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 787176c57fd..a8f6bfc96fd 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -362,7 +362,7 @@ typedef struct _mace_statistics {
} mace_statistics;
typedef struct _mace_private {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct net_device_stats linux_stats; /* Linux statistics counters */
mace_statistics mace_stats; /* MACE chip statistics counters */
@@ -417,8 +417,8 @@ INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
Function Prototypes
---------------------------------------------------------------------------- */
-static void nmclan_config(dev_link_t *link);
-static void nmclan_release(dev_link_t *link);
+static int nmclan_config(struct pcmcia_device *link);
+static void nmclan_release(struct pcmcia_device *link);
static void nmclan_reset(struct net_device *dev);
static int mace_config(struct net_device *dev, struct ifmap *map);
@@ -443,10 +443,9 @@ nmclan_attach
Services.
---------------------------------------------------------------------------- */
-static int nmclan_attach(struct pcmcia_device *p_dev)
+static int nmclan_probe(struct pcmcia_device *link)
{
mace_private *lp;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "nmclan_attach()\n");
@@ -457,7 +456,7 @@ static int nmclan_attach(struct pcmcia_device *p_dev)
if (!dev)
return -ENOMEM;
lp = netdev_priv(dev);
- link = &lp->link;
+ lp->p_dev = link;
link->priv = dev;
spin_lock_init(&lp->bank_lock);
@@ -469,7 +468,6 @@ static int nmclan_attach(struct pcmcia_device *p_dev)
link->irq.Handler = &mace_interrupt;
link->irq.Instance = dev;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
@@ -489,13 +487,7 @@ static int nmclan_attach(struct pcmcia_device *p_dev)
dev->watchdog_timeo = TX_TIMEOUT;
#endif
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- nmclan_config(link);
-
- return 0;
+ return nmclan_config(link);
} /* nmclan_attach */
/* ----------------------------------------------------------------------------
@@ -506,18 +498,16 @@ nmclan_detach
when the device is released.
---------------------------------------------------------------------------- */
-static void nmclan_detach(struct pcmcia_device *p_dev)
+static void nmclan_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "nmclan_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- nmclan_release(link);
+ nmclan_release(link);
free_netdev(dev);
} /* nmclan_detach */
@@ -661,9 +651,8 @@ nmclan_config
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void nmclan_config(dev_link_t *link)
+static int nmclan_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
mace_private *lp = netdev_priv(dev);
tuple_t tuple;
@@ -679,17 +668,14 @@ static void nmclan_config(dev_link_t *link)
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
@@ -700,8 +686,8 @@ static void nmclan_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN);
/* Verify configuration by reading the MACE ID. */
@@ -716,8 +702,7 @@ static void nmclan_config(dev_link_t *link)
} else {
printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should"
" be 0x40 0x?9\n", sig[0], sig[1]);
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return -ENODEV;
}
}
@@ -730,14 +715,13 @@ static void nmclan_config(dev_link_t *link)
else
printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");
- link->dev = &lp->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &lp->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
i = register_netdev(dev);
if (i != 0) {
printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -747,14 +731,13 @@ static void nmclan_config(dev_link_t *link)
dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]);
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
- nmclan_release(link);
- return;
-
+ nmclan_release(link);
+ return -ENODEV;
} /* nmclan_config */
/* ----------------------------------------------------------------------------
@@ -763,46 +746,29 @@ nmclan_release
net device, and release the PCMCIA configuration. If the device
is still open, this will be postponed until it is closed.
---------------------------------------------------------------------------- */
-static void nmclan_release(dev_link_t *link)
+static void nmclan_release(struct pcmcia_device *link)
{
-
- DEBUG(0, "nmclan_release(0x%p)\n", link);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ DEBUG(0, "nmclan_release(0x%p)\n", link);
+ pcmcia_disable_device(link);
}
-static int nmclan_suspend(struct pcmcia_device *p_dev)
+static int nmclan_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
-
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int nmclan_resume(struct pcmcia_device *p_dev)
+static int nmclan_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- nmclan_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ nmclan_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -818,7 +784,7 @@ static void nmclan_reset(struct net_device *dev)
mace_private *lp = netdev_priv(dev);
#if RESET_XILINX
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = &lp->link;
conf_reg_t reg;
u_long OrigCorValue;
@@ -827,7 +793,7 @@ static void nmclan_reset(struct net_device *dev)
reg.Action = CS_READ;
reg.Offset = CISREG_COR;
reg.Value = 0;
- pcmcia_access_configuration_register(link->handle, &reg);
+ pcmcia_access_configuration_register(link, &reg);
OrigCorValue = reg.Value;
/* Reset Xilinx */
@@ -836,12 +802,12 @@ static void nmclan_reset(struct net_device *dev)
DEBUG(1, "nmclan_reset: OrigCorValue=0x%lX, resetting...\n",
OrigCorValue);
reg.Value = COR_SOFT_RESET;
- pcmcia_access_configuration_register(link->handle, &reg);
+ pcmcia_access_configuration_register(link, &reg);
/* Need to wait for 20 ms for PCMCIA to finish reset. */
/* Restore original COR configuration index */
reg.Value = COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK);
- pcmcia_access_configuration_register(link->handle, &reg);
+ pcmcia_access_configuration_register(link, &reg);
/* Xilinx is now completely reset along with the MACE chip. */
lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
@@ -885,9 +851,9 @@ static int mace_open(struct net_device *dev)
{
kio_addr_t ioaddr = dev->base_addr;
mace_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -908,7 +874,7 @@ static int mace_close(struct net_device *dev)
{
kio_addr_t ioaddr = dev->base_addr;
mace_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
@@ -963,12 +929,12 @@ mace_start_xmit
static void mace_tx_timeout(struct net_device *dev)
{
mace_private *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);
#if RESET_ON_TIMEOUT
printk("resetting card\n");
- pcmcia_reset_card(link->handle, NULL);
+ pcmcia_reset_card(link, NULL);
#else /* #if RESET_ON_TIMEOUT */
printk("NOT resetting card\n");
#endif /* #if RESET_ON_TIMEOUT */
@@ -1238,7 +1204,7 @@ static int mace_rx(struct net_device *dev, unsigned char RxCnt)
dev->last_rx = jiffies;
lp->linux_stats.rx_packets++;
- lp->linux_stats.rx_bytes += skb->len;
+ lp->linux_stats.rx_bytes += pkt_len;
outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */
continue;
} else {
@@ -1635,7 +1601,7 @@ static struct pcmcia_driver nmclan_cs_driver = {
.drv = {
.name = "nmclan_cs",
},
- .probe = nmclan_attach,
+ .probe = nmclan_probe,
.remove = nmclan_detach,
.id_table = nmclan_ids,
.suspend = nmclan_suspend,
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index b46e5f703ef..d090df41304 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -103,8 +103,8 @@ module_param_array(hw_addr, int, NULL, 0);
/*====================================================================*/
static void mii_phy_probe(struct net_device *dev);
-static void pcnet_config(dev_link_t *link);
-static void pcnet_release(dev_link_t *link);
+static int pcnet_config(struct pcmcia_device *link);
+static void pcnet_release(struct pcmcia_device *link);
static int pcnet_open(struct net_device *dev);
static int pcnet_close(struct net_device *dev);
static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -113,9 +113,9 @@ static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs);
static void ei_watchdog(u_long arg);
static void pcnet_reset_8390(struct net_device *dev);
static int set_config(struct net_device *dev, struct ifmap *map);
-static int setup_shmem_window(dev_link_t *link, int start_pg,
+static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
int stop_pg, int cm_offset);
-static int setup_dma_config(dev_link_t *link, int start_pg,
+static int setup_dma_config(struct pcmcia_device *link, int start_pg,
int stop_pg);
static void pcnet_detach(struct pcmcia_device *p_dev);
@@ -214,7 +214,7 @@ static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
typedef struct pcnet_dev_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
u_int flags;
void __iomem *base;
@@ -240,10 +240,9 @@ static inline pcnet_dev_t *PRIV(struct net_device *dev)
======================================================================*/
-static int pcnet_probe(struct pcmcia_device *p_dev)
+static int pcnet_probe(struct pcmcia_device *link)
{
pcnet_dev_t *info;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "pcnet_attach()\n");
@@ -252,7 +251,7 @@ static int pcnet_probe(struct pcmcia_device *p_dev)
dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
if (!dev) return -ENOMEM;
info = PRIV(dev);
- link = &info->link;
+ info->p_dev = link;
link->priv = dev;
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
@@ -265,13 +264,7 @@ static int pcnet_probe(struct pcmcia_device *p_dev)
dev->stop = &pcnet_close;
dev->set_config = &set_config;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- pcnet_config(link);
-
- return 0;
+ return pcnet_config(link);
} /* pcnet_attach */
/*======================================================================
@@ -283,18 +276,16 @@ static int pcnet_probe(struct pcmcia_device *p_dev)
======================================================================*/
-static void pcnet_detach(struct pcmcia_device *p_dev)
+static void pcnet_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "pcnet_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- pcnet_release(link);
+ pcnet_release(link);
free_netdev(dev);
} /* pcnet_detach */
@@ -306,7 +297,7 @@ static void pcnet_detach(struct pcmcia_device *p_dev)
======================================================================*/
-static hw_info_t *get_hwinfo(dev_link_t *link)
+static hw_info_t *get_hwinfo(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
win_req_t req;
@@ -318,9 +309,9 @@ static hw_info_t *get_hwinfo(dev_link_t *link)
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = 0; req.Size = 0;
req.AccessSpeed = 0;
- i = pcmcia_request_window(&link->handle, &req, &link->win);
+ i = pcmcia_request_window(&link, &req, &link->win);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestWindow, i);
+ cs_error(link, RequestWindow, i);
return NULL;
}
@@ -343,7 +334,7 @@ static hw_info_t *get_hwinfo(dev_link_t *link)
iounmap(virt);
j = pcmcia_release_window(link->win);
if (j != CS_SUCCESS)
- cs_error(link->handle, ReleaseWindow, j);
+ cs_error(link, ReleaseWindow, j);
return (i < NR_INFO) ? hw_info+i : NULL;
} /* get_hwinfo */
@@ -355,7 +346,7 @@ static hw_info_t *get_hwinfo(dev_link_t *link)
======================================================================*/
-static hw_info_t *get_prom(dev_link_t *link)
+static hw_info_t *get_prom(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
kio_addr_t ioaddr = dev->base_addr;
@@ -409,7 +400,7 @@ static hw_info_t *get_prom(dev_link_t *link)
======================================================================*/
-static hw_info_t *get_dl10019(dev_link_t *link)
+static hw_info_t *get_dl10019(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
int i;
@@ -431,7 +422,7 @@ static hw_info_t *get_dl10019(dev_link_t *link)
======================================================================*/
-static hw_info_t *get_ax88190(dev_link_t *link)
+static hw_info_t *get_ax88190(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
kio_addr_t ioaddr = dev->base_addr;
@@ -464,7 +455,7 @@ static hw_info_t *get_ax88190(dev_link_t *link)
======================================================================*/
-static hw_info_t *get_hwired(dev_link_t *link)
+static hw_info_t *get_hwired(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
int i;
@@ -491,7 +482,7 @@ static hw_info_t *get_hwired(dev_link_t *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static int try_io_port(dev_link_t *link)
+static int try_io_port(struct pcmcia_device *link)
{
int j, ret;
if (link->io.NumPorts1 == 32) {
@@ -512,18 +503,17 @@ static int try_io_port(dev_link_t *link)
for (j = 0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
link->io.BasePort2 = (j ^ 0x300) + 0x10;
- ret = pcmcia_request_io(link->handle, &link->io);
+ ret = pcmcia_request_io(link, &link->io);
if (ret == CS_SUCCESS) return ret;
}
return ret;
} else {
- return pcmcia_request_io(link->handle, &link->io);
+ return pcmcia_request_io(link, &link->io);
}
}
-static void pcnet_config(dev_link_t *link)
+static int pcnet_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
pcnet_dev_t *info = PRIV(dev);
tuple_t tuple;
@@ -531,7 +521,6 @@ static void pcnet_config(dev_link_t *link)
int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
int manfid = 0, prodid = 0, has_shmem = 0;
u_short buf[64];
- config_info_t conf;
hw_info_t *hw_info;
DEBUG(0, "pcnet_config(0x%p)\n", link);
@@ -541,36 +530,29 @@ static void pcnet_config(dev_link_t *link)
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- /* Look up current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
-
tuple.DesiredTuple = CISTPL_MANFID;
tuple.Attributes = TUPLE_RETURN_COMMON;
- if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
- (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) {
+ if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
+ (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) {
manfid = le16_to_cpu(buf[0]);
prodid = le16_to_cpu(buf[1]);
}
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (last_ret == CS_SUCCESS) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
cistpl_io_t *io = &(parse.cftable_entry.io);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0 ||
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
cfg->index == 0 || cfg->io.nwin == 0)
goto next_entry;
@@ -594,14 +576,14 @@ static void pcnet_config(dev_link_t *link)
if (last_ret == CS_SUCCESS) break;
}
next_entry:
- last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ last_ret = pcmcia_get_next_tuple(link, &tuple);
}
if (last_ret != CS_SUCCESS) {
- cs_error(handle, RequestIO, last_ret);
+ cs_error(link, RequestIO, last_ret);
goto failed;
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
if (link->io.NumPorts2 == 8) {
link->conf.Attributes |= CONF_ENABLE_SPKR;
@@ -611,7 +593,7 @@ static void pcnet_config(dev_link_t *link)
(prodid == PRODID_IBM_HOME_AND_AWAY))
link->conf.ConfigIndex |= 0x10;
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
if (info->flags & HAS_MISC_REG) {
@@ -679,9 +661,8 @@ static void pcnet_config(dev_link_t *link)
info->eth_phy = 0;
}
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &info->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = ei_poll;
@@ -689,7 +670,7 @@ static void pcnet_config(dev_link_t *link)
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto failed;
}
@@ -712,14 +693,13 @@ static void pcnet_config(dev_link_t *link)
printk(" hw_addr ");
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
pcnet_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return -ENODEV;
} /* pcnet_config */
/*======================================================================
@@ -730,21 +710,16 @@ failed:
======================================================================*/
-static void pcnet_release(dev_link_t *link)
+static void pcnet_release(struct pcmcia_device *link)
{
- pcnet_dev_t *info = PRIV(link->priv);
+ pcnet_dev_t *info = PRIV(link->priv);
- DEBUG(0, "pcnet_release(0x%p)\n", link);
+ DEBUG(0, "pcnet_release(0x%p)\n", link);
- if (info->flags & USE_SHMEM) {
- iounmap(info->base);
- pcmcia_release_window(link->win);
- }
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
+ if (info->flags & USE_SHMEM)
+ iounmap(info->base);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
/*======================================================================
@@ -756,34 +731,24 @@ static void pcnet_release(dev_link_t *link)
======================================================================*/
-static int pcnet_suspend(struct pcmcia_device *p_dev)
+static int pcnet_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int pcnet_resume(struct pcmcia_device *p_dev)
+static int pcnet_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- pcnet_reset_8390(dev);
- NS8390_init(dev, 1);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ pcnet_reset_8390(dev);
+ NS8390_init(dev, 1);
+ netif_device_attach(dev);
}
return 0;
@@ -1023,11 +988,11 @@ static void mii_phy_probe(struct net_device *dev)
static int pcnet_open(struct net_device *dev)
{
pcnet_dev_t *info = PRIV(dev);
- dev_link_t *link = &info->link;
-
+ struct pcmcia_device *link = info->p_dev;
+
DEBUG(2, "pcnet_open('%s')\n", dev->name);
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -1051,7 +1016,7 @@ static int pcnet_open(struct net_device *dev)
static int pcnet_close(struct net_device *dev)
{
pcnet_dev_t *info = PRIV(dev);
- dev_link_t *link = &info->link;
+ struct pcmcia_device *link = info->p_dev;
DEBUG(2, "pcnet_close('%s')\n", dev->name);
@@ -1429,7 +1394,7 @@ static void dma_block_output(struct net_device *dev, int count,
/*====================================================================*/
-static int setup_dma_config(dev_link_t *link, int start_pg,
+static int setup_dma_config(struct pcmcia_device *link, int start_pg,
int stop_pg)
{
struct net_device *dev = link->priv;
@@ -1532,7 +1497,7 @@ static void shmem_block_output(struct net_device *dev, int count,
/*====================================================================*/
-static int setup_shmem_window(dev_link_t *link, int start_pg,
+static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
int stop_pg, int cm_offset)
{
struct net_device *dev = link->priv;
@@ -1554,7 +1519,7 @@ static int setup_shmem_window(dev_link_t *link, int start_pg,
req.Attributes |= WIN_USE_WAIT;
req.Base = 0; req.Size = window_size;
req.AccessSpeed = mem_speed;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
mem.CardOffset = (start_pg << 8) + cm_offset;
offset = mem.CardOffset % window_size;
@@ -1595,7 +1560,7 @@ static int setup_shmem_window(dev_link_t *link, int start_pg,
return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
return 1;
}
@@ -1674,6 +1639,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722),
PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd),
+ PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 8839c4faafd..e74bf5014ef 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -49,6 +49,7 @@
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
+#include <pcmcia/ss.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -103,7 +104,7 @@ static const char *version =
#define MEMORY_WAIT_TIME 8
struct smc_private {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
spinlock_t lock;
u_short manfid;
u_short cardid;
@@ -278,8 +279,8 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002,
/*====================================================================*/
static void smc91c92_detach(struct pcmcia_device *p_dev);
-static void smc91c92_config(dev_link_t *link);
-static void smc91c92_release(dev_link_t *link);
+static int smc91c92_config(struct pcmcia_device *link);
+static void smc91c92_release(struct pcmcia_device *link);
static int smc_open(struct net_device *dev);
static int smc_close(struct net_device *dev);
@@ -308,10 +309,9 @@ static struct ethtool_ops ethtool_ops;
======================================================================*/
-static int smc91c92_attach(struct pcmcia_device *p_dev)
+static int smc91c92_probe(struct pcmcia_device *link)
{
struct smc_private *smc;
- dev_link_t *link;
struct net_device *dev;
DEBUG(0, "smc91c92_attach()\n");
@@ -321,7 +321,7 @@ static int smc91c92_attach(struct pcmcia_device *p_dev)
if (!dev)
return -ENOMEM;
smc = netdev_priv(dev);
- link = &smc->link;
+ smc->p_dev = link;
link->priv = dev;
spin_lock_init(&smc->lock);
@@ -333,7 +333,6 @@ static int smc91c92_attach(struct pcmcia_device *p_dev)
link->irq.Handler = &smc_interrupt;
link->irq.Instance = dev;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
/* The SMC91c92-specific entries in the device structure. */
@@ -357,13 +356,7 @@ static int smc91c92_attach(struct pcmcia_device *p_dev)
smc->mii_if.phy_id_mask = 0x1f;
smc->mii_if.reg_num_mask = 0x1f;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- smc91c92_config(link);
-
- return 0;
+ return smc91c92_config(link);
} /* smc91c92_attach */
/*======================================================================
@@ -375,18 +368,16 @@ static int smc91c92_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void smc91c92_detach(struct pcmcia_device *p_dev)
+static void smc91c92_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "smc91c92_detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- smc91c92_release(link);
+ smc91c92_release(link);
free_netdev(dev);
} /* smc91c92_detach */
@@ -414,7 +405,7 @@ static int cvt_ascii_address(struct net_device *dev, char *s)
/*====================================================================*/
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i;
@@ -425,7 +416,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple,
return pcmcia_parse_tuple(handle, tuple, parse);
}
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
cisparse_t *parse)
{
int i;
@@ -447,7 +438,7 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple,
======================================================================*/
-static int mhz_3288_power(dev_link_t *link)
+static int mhz_3288_power(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
@@ -469,7 +460,7 @@ static int mhz_3288_power(dev_link_t *link)
return 0;
}
-static int mhz_mfc_config(dev_link_t *link)
+static int mhz_mfc_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
@@ -504,7 +495,7 @@ static int mhz_mfc_config(dev_link_t *link)
tuple->TupleDataMax = 255;
tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
- i = first_tuple(link->handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
/* The Megahertz combo cards have modem-like CIS entries, so
we have to explicitly try a bunch of port combinations. */
while (i == CS_SUCCESS) {
@@ -513,11 +504,11 @@ static int mhz_mfc_config(dev_link_t *link)
for (k = 0; k < 0x400; k += 0x10) {
if (k & 0x80) continue;
link->io.BasePort1 = k ^ 0x300;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
if (i == CS_SUCCESS) break;
- i = next_tuple(link->handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
if (i != CS_SUCCESS)
goto free_cfg_mem;
@@ -527,7 +518,7 @@ static int mhz_mfc_config(dev_link_t *link)
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = req.Size = 0;
req.AccessSpeed = 0;
- i = pcmcia_request_window(&link->handle, &req, &link->win);
+ i = pcmcia_request_window(&link, &req, &link->win);
if (i != CS_SUCCESS)
goto free_cfg_mem;
smc->base = ioremap(req.Base, req.Size);
@@ -546,9 +537,8 @@ free_cfg_mem:
return i;
}
-static int mhz_setup(dev_link_t *link)
+static int mhz_setup(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
struct smc_cfg_mem *cfg_mem;
tuple_t *tuple;
@@ -571,13 +561,13 @@ static int mhz_setup(dev_link_t *link)
/* Read the station address from the CIS. It is stored as the last
(fourth) string in the Version 1 Version/ID tuple. */
tuple->DesiredTuple = CISTPL_VERS_1;
- if (first_tuple(handle, tuple, parse) != CS_SUCCESS) {
+ if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
rc = -1;
goto free_cfg_mem;
}
/* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
- if (next_tuple(handle, tuple, parse) != CS_SUCCESS)
- first_tuple(handle, tuple, parse);
+ if (next_tuple(link, tuple, parse) != CS_SUCCESS)
+ first_tuple(link, tuple, parse);
if (parse->version_1.ns > 3) {
station_addr = parse->version_1.str + parse->version_1.ofs[3];
if (cvt_ascii_address(dev, station_addr) == 0) {
@@ -588,11 +578,11 @@ static int mhz_setup(dev_link_t *link)
/* Another possibility: for the EM3288, in a special tuple */
tuple->DesiredTuple = 0x81;
- if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) {
+ if (pcmcia_get_first_tuple(link, tuple) != CS_SUCCESS) {
rc = -1;
goto free_cfg_mem;
}
- if (pcmcia_get_tuple_data(handle, tuple) != CS_SUCCESS) {
+ if (pcmcia_get_tuple_data(link, tuple) != CS_SUCCESS) {
rc = -1;
goto free_cfg_mem;
}
@@ -616,7 +606,7 @@ free_cfg_mem:
======================================================================*/
-static void mot_config(dev_link_t *link)
+static void mot_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
@@ -637,7 +627,7 @@ static void mot_config(dev_link_t *link)
mdelay(100);
}
-static int mot_setup(dev_link_t *link)
+static int mot_setup(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
kio_addr_t ioaddr = dev->base_addr;
@@ -671,7 +661,7 @@ static int mot_setup(dev_link_t *link)
/*====================================================================*/
-static int smc_config(dev_link_t *link)
+static int smc_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct smc_cfg_mem *cfg_mem;
@@ -696,16 +686,16 @@ static int smc_config(dev_link_t *link)
tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
link->io.NumPorts1 = 16;
- i = first_tuple(link->handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
while (i != CS_NO_MORE_ITEMS) {
if (i == CS_SUCCESS) {
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
- i = next_tuple(link->handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
if (i == CS_SUCCESS)
dev->base_addr = link->io.BasePort1;
@@ -714,9 +704,8 @@ static int smc_config(dev_link_t *link)
return i;
}
-static int smc_setup(dev_link_t *link)
+static int smc_setup(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
struct smc_cfg_mem *cfg_mem;
tuple_t *tuple;
@@ -739,11 +728,11 @@ static int smc_setup(dev_link_t *link)
/* Check for a LAN function extension tuple */
tuple->DesiredTuple = CISTPL_FUNCE;
- i = first_tuple(handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
while (i == CS_SUCCESS) {
if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID)
break;
- i = next_tuple(handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
if (i == CS_SUCCESS) {
node_id = (cistpl_lan_node_id_t *)parse->funce.data;
@@ -756,7 +745,7 @@ static int smc_setup(dev_link_t *link)
}
/* Try the third string in the Version 1 Version/ID tuple. */
tuple->DesiredTuple = CISTPL_VERS_1;
- if (first_tuple(handle, tuple, parse) != CS_SUCCESS) {
+ if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
rc = -1;
goto free_cfg_mem;
}
@@ -774,7 +763,7 @@ free_cfg_mem:
/*====================================================================*/
-static int osi_config(dev_link_t *link)
+static int osi_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
static const kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
@@ -794,22 +783,21 @@ static int osi_config(dev_link_t *link)
for (i = j = 0; j < 4; j++) {
link->io.BasePort2 = com[j];
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
if (i != CS_SUCCESS) {
/* Fallback: turn off hard decode */
link->conf.ConfigIndex = 0x03;
link->io.NumPorts2 = 0;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
}
dev->base_addr = link->io.BasePort1 + 0x10;
return i;
}
-static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
+static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
struct smc_cfg_mem *cfg_mem;
tuple_t *tuple;
@@ -830,12 +818,12 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
/* Read the station address from tuple 0x90, subtuple 0x04 */
tuple->DesiredTuple = 0x90;
- i = pcmcia_get_first_tuple(handle, tuple);
+ i = pcmcia_get_first_tuple(link, tuple);
while (i == CS_SUCCESS) {
- i = pcmcia_get_tuple_data(handle, tuple);
+ i = pcmcia_get_tuple_data(link, tuple);
if ((i != CS_SUCCESS) || (buf[0] == 0x04))
break;
- i = pcmcia_get_next_tuple(handle, tuple);
+ i = pcmcia_get_next_tuple(link, tuple);
}
if (i != CS_SUCCESS) {
rc = -1;
@@ -868,57 +856,47 @@ free_cfg_mem:
return rc;
}
-static int smc91c92_suspend(struct pcmcia_device *p_dev)
+static int smc91c92_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int smc91c92_resume(struct pcmcia_device *p_dev)
+static int smc91c92_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
int i;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if ((smc->manfid == MANFID_MEGAHERTZ) &&
- (smc->cardid == PRODID_MEGAHERTZ_EM3288))
- mhz_3288_power(link);
- pcmcia_request_configuration(link->handle, &link->conf);
- if (smc->manfid == MANFID_MOTOROLA)
- mot_config(link);
- if ((smc->manfid == MANFID_OSITECH) &&
- (smc->cardid != PRODID_OSITECH_SEVEN)) {
- /* Power up the card and enable interrupts */
- set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
- set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
- }
- if (((smc->manfid == MANFID_OSITECH) &&
- (smc->cardid == PRODID_OSITECH_SEVEN)) ||
- ((smc->manfid == MANFID_PSION) &&
- (smc->cardid == PRODID_PSION_NET100))) {
- /* Download the Seven of Diamonds firmware */
- for (i = 0; i < sizeof(__Xilinx7OD); i++) {
- outb(__Xilinx7OD[i], link->io.BasePort1+2);
- udelay(50);
- }
- }
- if (link->open) {
- smc_reset(dev);
- netif_device_attach(dev);
+ if ((smc->manfid == MANFID_MEGAHERTZ) &&
+ (smc->cardid == PRODID_MEGAHERTZ_EM3288))
+ mhz_3288_power(link);
+ if (smc->manfid == MANFID_MOTOROLA)
+ mot_config(link);
+ if ((smc->manfid == MANFID_OSITECH) &&
+ (smc->cardid != PRODID_OSITECH_SEVEN)) {
+ /* Power up the card and enable interrupts */
+ set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
+ set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
+ }
+ if (((smc->manfid == MANFID_OSITECH) &&
+ (smc->cardid == PRODID_OSITECH_SEVEN)) ||
+ ((smc->manfid == MANFID_PSION) &&
+ (smc->cardid == PRODID_PSION_NET100))) {
+ /* Download the Seven of Diamonds firmware */
+ for (i = 0; i < sizeof(__Xilinx7OD); i++) {
+ outb(__Xilinx7OD[i], link->io.BasePort1+2);
+ udelay(50);
}
}
+ if (link->open) {
+ smc_reset(dev);
+ netif_device_attach(dev);
+ }
return 0;
}
@@ -931,7 +909,7 @@ static int smc91c92_resume(struct pcmcia_device *p_dev)
======================================================================*/
-static int check_sig(dev_link_t *link)
+static int check_sig(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
kio_addr_t ioaddr = dev->base_addr;
@@ -964,13 +942,15 @@ static int check_sig(dev_link_t *link)
}
if (width) {
- printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
- smc91c92_suspend(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- pcmcia_request_io(link->handle, &link->io);
- smc91c92_resume(link->handle);
- return check_sig(link);
+ modconf_t mod = {
+ .Attributes = CONF_IO_CHANGE_WIDTH,
+ };
+ printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
+
+ smc91c92_suspend(link);
+ pcmcia_modify_configuration(link, &mod);
+ smc91c92_resume(link);
+ return check_sig(link);
}
return -ENODEV;
}
@@ -984,11 +964,10 @@ static int check_sig(dev_link_t *link)
======================================================================*/
#define CS_EXIT_TEST(ret, svc, label) \
-if (ret != CS_SUCCESS) { cs_error(link->handle, svc, ret); goto label; }
+if (ret != CS_SUCCESS) { cs_error(link, svc, ret); goto label; }
-static void smc91c92_config(dev_link_t *link)
+static int smc91c92_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
struct smc_cfg_mem *cfg_mem;
@@ -1015,21 +994,18 @@ static void smc91c92_config(dev_link_t *link)
tuple->TupleDataMax = 64;
tuple->DesiredTuple = CISTPL_CONFIG;
- i = first_tuple(handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
CS_EXIT_TEST(i, ParseTuple, config_failed);
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
tuple->DesiredTuple = CISTPL_MANFID;
tuple->Attributes = TUPLE_RETURN_COMMON;
- if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+ if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
smc->manfid = parse->manfid.manf;
smc->cardid = parse->manfid.card;
}
- /* Configure card */
- link->state |= DEV_CONFIG;
-
if ((smc->manfid == MANFID_OSITECH) &&
(smc->cardid != PRODID_OSITECH_SEVEN)) {
i = osi_config(link);
@@ -1043,9 +1019,9 @@ static void smc91c92_config(dev_link_t *link)
}
CS_EXIT_TEST(i, RequestIO, config_failed);
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
CS_EXIT_TEST(i, RequestIRQ, config_failed);
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
CS_EXIT_TEST(i, RequestConfiguration, config_failed);
if (smc->manfid == MANFID_MOTOROLA)
@@ -1124,13 +1100,12 @@ static void smc91c92_config(dev_link_t *link)
SMC_SELECT_BANK(0);
}
- link->dev = &smc->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &smc->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev) != 0) {
printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto config_undo;
}
@@ -1160,15 +1135,14 @@ static void smc91c92_config(dev_link_t *link)
}
}
kfree(cfg_mem);
- return;
+ return 0;
config_undo:
unregister_netdev(dev);
config_failed: /* CS_EXIT_TEST() calls jump to here... */
smc91c92_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
kfree(cfg_mem);
-
+ return -ENODEV;
} /* smc91c92_config */
/*======================================================================
@@ -1179,22 +1153,15 @@ config_failed: /* CS_EXIT_TEST() calls jump to here... */
======================================================================*/
-static void smc91c92_release(dev_link_t *link)
+static void smc91c92_release(struct pcmcia_device *link)
{
-
- DEBUG(0, "smc91c92_release(0x%p)\n", link);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- if (link->win) {
- struct net_device *dev = link->priv;
- struct smc_private *smc = netdev_priv(dev);
- iounmap(smc->base);
- pcmcia_release_window(link->win);
- }
-
- link->state &= ~DEV_CONFIG;
+ DEBUG(0, "smc91c92_release(0x%p)\n", link);
+ if (link->win) {
+ struct net_device *dev = link->priv;
+ struct smc_private *smc = netdev_priv(dev);
+ iounmap(smc->base);
+ }
+ pcmcia_disable_device(link);
}
/*======================================================================
@@ -1283,7 +1250,7 @@ static void smc_dump(struct net_device *dev)
static int smc_open(struct net_device *dev)
{
struct smc_private *smc = netdev_priv(dev);
- dev_link_t *link = &smc->link;
+ struct pcmcia_device *link = smc->p_dev;
#ifdef PCMCIA_DEBUG
DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n",
@@ -1292,7 +1259,7 @@ static int smc_open(struct net_device *dev)
#endif
/* Check that the PCMCIA card is still here. */
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
/* Physical device present signature. */
if (check_sig(link) < 0) {
@@ -1320,7 +1287,7 @@ static int smc_open(struct net_device *dev)
static int smc_close(struct net_device *dev)
{
struct smc_private *smc = netdev_priv(dev);
- dev_link_t *link = &smc->link;
+ struct pcmcia_device *link = smc->p_dev;
kio_addr_t ioaddr = dev->base_addr;
DEBUG(0, "%s: smc_close(), status %4.4x.\n",
@@ -2311,7 +2278,7 @@ static struct pcmcia_driver smc91c92_cs_driver = {
.drv = {
.name = "smc91c92_cs",
},
- .probe = smc91c92_attach,
+ .probe = smc91c92_probe,
.remove = smc91c92_detach,
.id_table = smc91c92_ids,
.suspend = smc91c92_suspend,
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index eed496803fe..71f45056a70 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -289,9 +289,9 @@ static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg,
* and ejection events. They are invoked from the event handler.
*/
-static int has_ce2_string(dev_link_t * link);
-static void xirc2ps_config(dev_link_t * link);
-static void xirc2ps_release(dev_link_t * link);
+static int has_ce2_string(struct pcmcia_device * link);
+static int xirc2ps_config(struct pcmcia_device * link);
+static void xirc2ps_release(struct pcmcia_device * link);
/****************
* The attach() and detach() entry points are used to create and destroy
@@ -313,10 +313,10 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs
/****************
* A linked list of "instances" of the device. Each actual
* PCMCIA card corresponds to one device instance, and is described
- * by one dev_link_t structure (defined in ds.h).
+ * by one struct pcmcia_device structure (defined in ds.h).
*
* You may not want to use a linked list for this -- for example, the
- * memory card driver uses an array of dev_link_t pointers, where minor
+ * memory card driver uses an array of struct pcmcia_device pointers, where minor
* device numbers are used to derive the corresponding array index.
*/
@@ -326,13 +326,13 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs
* example, ethernet cards, modems). In other cases, there may be
* many actual or logical devices (SCSI adapters, memory cards with
* multiple partitions). The dev_node_t structures need to be kept
- * in a linked list starting at the 'dev' field of a dev_link_t
+ * in a linked list starting at the 'dev' field of a struct pcmcia_device
* structure. We allocate them in the card's private data structure,
* because they generally can't be allocated dynamically.
*/
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct net_device_stats stats;
int card_type;
@@ -355,7 +355,7 @@ static void do_tx_timeout(struct net_device *dev);
static struct net_device_stats *do_get_stats(struct net_device *dev);
static void set_addresses(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
-static int set_card_type(dev_link_t *link, const void *s);
+static int set_card_type(struct pcmcia_device *link, const void *s);
static int do_config(struct net_device *dev, struct ifmap *map);
static int do_open(struct net_device *dev);
static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -368,7 +368,7 @@ static int do_stop(struct net_device *dev);
/*=============== Helper functions =========================*/
static int
-first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int err;
@@ -379,7 +379,7 @@ first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
}
static int
-next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int err;
@@ -553,9 +553,8 @@ mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len)
*/
static int
-xirc2ps_attach(struct pcmcia_device *p_dev)
+xirc2ps_probe(struct pcmcia_device *link)
{
- dev_link_t *link;
struct net_device *dev;
local_info_t *local;
@@ -566,12 +565,11 @@ xirc2ps_attach(struct pcmcia_device *p_dev)
if (!dev)
return -ENOMEM;
local = netdev_priv(dev);
- link = &local->link;
+ local->p_dev = link;
link->priv = dev;
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
@@ -593,13 +591,7 @@ xirc2ps_attach(struct pcmcia_device *p_dev)
dev->watchdog_timeo = TX_TIMEOUT;
#endif
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- xirc2ps_config(link);
-
- return 0;
+ return xirc2ps_config(link);
} /* xirc2ps_attach */
/****************
@@ -610,18 +602,16 @@ xirc2ps_attach(struct pcmcia_device *p_dev)
*/
static void
-xirc2ps_detach(struct pcmcia_device *p_dev)
+xirc2ps_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "detach(0x%p)\n", link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- xirc2ps_release(link);
+ xirc2ps_release(link);
free_netdev(dev);
} /* xirc2ps_detach */
@@ -645,7 +635,7 @@ xirc2ps_detach(struct pcmcia_device *p_dev)
*
*/
static int
-set_card_type(dev_link_t *link, const void *s)
+set_card_type(struct pcmcia_device *link, const void *s)
{
struct net_device *dev = link->priv;
local_info_t *local = netdev_priv(dev);
@@ -714,9 +704,8 @@ set_card_type(dev_link_t *link, const void *s)
* Returns: true if this is a CE2
*/
static int
-has_ce2_string(dev_link_t * link)
+has_ce2_string(struct pcmcia_device * link)
{
- client_handle_t handle = link->handle;
tuple_t tuple;
cisparse_t parse;
u_char buf[256];
@@ -726,7 +715,7 @@ has_ce2_string(dev_link_t * link)
tuple.TupleDataMax = 254;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_VERS_1;
- if (!first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2) {
+ if (!first_tuple(link, &tuple, &parse) && parse.version_1.ns > 2) {
if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2"))
return 1;
}
@@ -738,10 +727,9 @@ has_ce2_string(dev_link_t * link)
* is received, to configure the PCMCIA socket, and to make the
* ethernet device available to the system.
*/
-static void
-xirc2ps_config(dev_link_t * link)
+static int
+xirc2ps_config(struct pcmcia_device * link)
{
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
local_info_t *local = netdev_priv(dev);
tuple_t tuple;
@@ -767,7 +755,7 @@ xirc2ps_config(dev_link_t * link)
/* Is this a valid card */
tuple.DesiredTuple = CISTPL_MANFID;
- if ((err=first_tuple(handle, &tuple, &parse))) {
+ if ((err=first_tuple(link, &tuple, &parse))) {
printk(KNOT_XIRC "manfid not found in CIS\n");
goto failure;
}
@@ -803,15 +791,15 @@ xirc2ps_config(dev_link_t * link)
/* get configuration stuff */
tuple.DesiredTuple = CISTPL_CONFIG;
- if ((err=first_tuple(handle, &tuple, &parse)))
+ if ((err=first_tuple(link, &tuple, &parse)))
goto cis_error;
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* get the ethernet address from the CIS */
tuple.DesiredTuple = CISTPL_FUNCE;
- for (err = first_tuple(handle, &tuple, &parse); !err;
- err = next_tuple(handle, &tuple, &parse)) {
+ for (err = first_tuple(link, &tuple, &parse); !err;
+ err = next_tuple(link, &tuple, &parse)) {
/* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries:
* the first one with a length of zero the second correct -
* so I skip all entries with length 0 */
@@ -821,8 +809,8 @@ xirc2ps_config(dev_link_t * link)
}
if (err) { /* not found: try to get the node-id from tuple 0x89 */
tuple.DesiredTuple = 0x89; /* data layout looks like tuple 0x22 */
- if ((err = pcmcia_get_first_tuple(handle, &tuple)) == 0 &&
- (err = pcmcia_get_tuple_data(handle, &tuple)) == 0) {
+ if ((err = pcmcia_get_first_tuple(link, &tuple)) == 0 &&
+ (err = pcmcia_get_tuple_data(link, &tuple)) == 0) {
if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID)
memcpy(&parse, buf, 8);
else
@@ -831,8 +819,8 @@ xirc2ps_config(dev_link_t * link)
}
if (err) { /* another try (James Lehmer's CE2 version 4.1)*/
tuple.DesiredTuple = CISTPL_FUNCE;
- for (err = first_tuple(handle, &tuple, &parse); !err;
- err = next_tuple(handle, &tuple, &parse)) {
+ for (err = first_tuple(link, &tuple, &parse); !err;
+ err = next_tuple(link, &tuple, &parse)) {
if (parse.funce.type == 0x02 && parse.funce.data[0] == 1
&& parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) {
buf[1] = 4;
@@ -853,9 +841,6 @@ xirc2ps_config(dev_link_t * link)
for (i=0; i < 6; i++)
dev->dev_addr[i] = node_id->id[i];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
link->io.IOAddrLines =10;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
link->irq.Attributes = IRQ_HANDLE_PRESENT;
@@ -875,14 +860,14 @@ xirc2ps_config(dev_link_t * link)
* Ethernet port */
link->io.NumPorts1 = 16; /* no Mako stuff anymore */
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (err = first_tuple(handle, &tuple, &parse); !err;
- err = next_tuple(handle, &tuple, &parse)) {
+ for (err = first_tuple(link, &tuple, &parse); !err;
+ err = next_tuple(link, &tuple, &parse)) {
if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
link->conf.ConfigIndex = cf->index ;
link->io.BasePort2 = cf->io.win[0].base;
link->io.BasePort1 = ioaddr;
- if (!(err=pcmcia_request_io(link->handle, &link->io)))
+ if (!(err=pcmcia_request_io(link, &link->io)))
goto port_found;
}
}
@@ -896,15 +881,15 @@ xirc2ps_config(dev_link_t * link)
*/
for (pass=0; pass < 2; pass++) {
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (err = first_tuple(handle, &tuple, &parse); !err;
- err = next_tuple(handle, &tuple, &parse)){
+ for (err = first_tuple(link, &tuple, &parse); !err;
+ err = next_tuple(link, &tuple, &parse)){
if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){
link->conf.ConfigIndex = cf->index ;
link->io.BasePort2 = cf->io.win[0].base;
link->io.BasePort1 = link->io.BasePort2
+ (pass ? (cf->index & 0x20 ? -24:8)
: (cf->index & 0x20 ? 8:-24));
- if (!(err=pcmcia_request_io(link->handle, &link->io)))
+ if (!(err=pcmcia_request_io(link, &link->io)))
goto port_found;
}
}
@@ -919,12 +904,12 @@ xirc2ps_config(dev_link_t * link)
link->io.NumPorts1 = 16;
for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
link->io.BasePort1 = ioaddr;
- if (!(err=pcmcia_request_io(link->handle, &link->io)))
+ if (!(err=pcmcia_request_io(link, &link->io)))
goto port_found;
}
link->io.BasePort1 = 0; /* let CS decide */
- if ((err=pcmcia_request_io(link->handle, &link->io))) {
- cs_error(link->handle, RequestIO, err);
+ if ((err=pcmcia_request_io(link, &link->io))) {
+ cs_error(link, RequestIO, err);
goto config_error;
}
}
@@ -936,8 +921,8 @@ xirc2ps_config(dev_link_t * link)
* Now allocate an interrupt line. Note that this does not
* actually assign a handler to the interrupt.
*/
- if ((err=pcmcia_request_irq(link->handle, &link->irq))) {
- cs_error(link->handle, RequestIRQ, err);
+ if ((err=pcmcia_request_irq(link, &link->irq))) {
+ cs_error(link, RequestIRQ, err);
goto config_error;
}
@@ -945,8 +930,8 @@ xirc2ps_config(dev_link_t * link)
* This actually configures the PCMCIA socket -- setting up
* the I/O windows and the interrupt mapping.
*/
- if ((err=pcmcia_request_configuration(link->handle, &link->conf))) {
- cs_error(link->handle, RequestConfiguration, err);
+ if ((err=pcmcia_request_configuration(link, &link->conf))) {
+ cs_error(link, RequestConfiguration, err);
goto config_error;
}
@@ -963,15 +948,15 @@ xirc2ps_config(dev_link_t * link)
reg.Action = CS_WRITE;
reg.Offset = CISREG_IOBASE_0;
reg.Value = link->io.BasePort2 & 0xff;
- if ((err = pcmcia_access_configuration_register(link->handle, &reg))) {
- cs_error(link->handle, AccessConfigurationRegister, err);
+ if ((err = pcmcia_access_configuration_register(link, &reg))) {
+ cs_error(link, AccessConfigurationRegister, err);
goto config_error;
}
reg.Action = CS_WRITE;
reg.Offset = CISREG_IOBASE_1;
reg.Value = (link->io.BasePort2 >> 8) & 0xff;
- if ((err = pcmcia_access_configuration_register(link->handle, &reg))) {
- cs_error(link->handle, AccessConfigurationRegister, err);
+ if ((err = pcmcia_access_configuration_register(link, &reg))) {
+ cs_error(link, AccessConfigurationRegister, err);
goto config_error;
}
@@ -982,15 +967,15 @@ xirc2ps_config(dev_link_t * link)
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = req.Size = 0;
req.AccessSpeed = 0;
- if ((err = pcmcia_request_window(&link->handle, &req, &link->win))) {
- cs_error(link->handle, RequestWindow, err);
+ if ((err = pcmcia_request_window(&link, &req, &link->win))) {
+ cs_error(link, RequestWindow, err);
goto config_error;
}
local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800;
mem.CardOffset = 0x0;
mem.Page = 0;
if ((err = pcmcia_map_mem_page(link->win, &mem))) {
- cs_error(link->handle, MapMemPage, err);
+ cs_error(link, MapMemPage, err);
goto config_error;
}
@@ -1050,13 +1035,12 @@ xirc2ps_config(dev_link_t * link)
if (local->dingo)
do_reset(dev, 1); /* a kludge to make the cem56 work */
- link->dev = &local->node;
- link->state &= ~DEV_CONFIG_PENDING;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ link->dev_node = &local->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if ((err=register_netdev(dev))) {
printk(KNOT_XIRC "register_netdev() failed\n");
- link->dev = NULL;
+ link->dev_node = NULL;
goto config_error;
}
@@ -1069,17 +1053,16 @@ xirc2ps_config(dev_link_t * link)
printk("%c%02X", i?':':' ', dev->dev_addr[i]);
printk("\n");
- return;
+ return 0;
config_error:
- link->state &= ~DEV_CONFIG_PENDING;
xirc2ps_release(link);
- return;
+ return -ENODEV;
cis_error:
printk(KNOT_XIRC "unable to parse CIS\n");
failure:
- link->state &= ~DEV_CONFIG_PENDING;
+ return -ENODEV;
} /* xirc2ps_config */
/****************
@@ -1088,57 +1071,41 @@ xirc2ps_config(dev_link_t * link)
* still open, this will be postponed until it is closed.
*/
static void
-xirc2ps_release(dev_link_t *link)
+xirc2ps_release(struct pcmcia_device *link)
{
+ DEBUG(0, "release(0x%p)\n", link);
- DEBUG(0, "release(0x%p)\n", link);
-
- if (link->win) {
- struct net_device *dev = link->priv;
- local_info_t *local = netdev_priv(dev);
- if (local->dingo)
- iounmap(local->dingo_ccr - 0x0800);
- pcmcia_release_window(link->win);
- }
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
-
+ if (link->win) {
+ struct net_device *dev = link->priv;
+ local_info_t *local = netdev_priv(dev);
+ if (local->dingo)
+ iounmap(local->dingo_ccr - 0x0800);
+ }
+ pcmcia_disable_device(link);
} /* xirc2ps_release */
/*====================================================================*/
-static int xirc2ps_suspend(struct pcmcia_device *p_dev)
+static int xirc2ps_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open) {
- netif_device_detach(dev);
- do_powerdown(dev);
- }
- pcmcia_release_configuration(link->handle);
+ if (link->open) {
+ netif_device_detach(dev);
+ do_powerdown(dev);
}
return 0;
}
-static int xirc2ps_resume(struct pcmcia_device *p_dev)
+static int xirc2ps_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- do_reset(dev,1);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ do_reset(dev,1);
+ netif_device_attach(dev);
}
return 0;
@@ -1552,13 +1519,13 @@ static int
do_open(struct net_device *dev)
{
local_info_t *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
DEBUG(0, "do_open(%p)\n", dev);
/* Check that the PCMCIA card is still here. */
/* Physical device present signature. */
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
/* okay */
@@ -1882,7 +1849,7 @@ do_stop(struct net_device *dev)
{
kio_addr_t ioaddr = dev->base_addr;
local_info_t *lp = netdev_priv(dev);
- dev_link_t *link = &lp->link;
+ struct pcmcia_device *link = lp->p_dev;
DEBUG(0, "do_stop(%p)\n", dev);
@@ -1935,7 +1902,7 @@ static struct pcmcia_driver xirc2ps_cs_driver = {
.drv = {
.name = "xirc2ps_cs",
},
- .probe = xirc2ps_attach,
+ .probe = xirc2ps_probe,
.remove = xirc2ps_detach,
.id_table = xirc2ps_ids,
.suspend = xirc2ps_suspend,
@@ -1973,7 +1940,7 @@ static int __init setup_xirc2ps_cs(char *str)
MAYBE_SET(lockup_hack, 6);
#undef MAYBE_SET
- return 0;
+ return 1;
}
__setup("xirc2ps_cs=", setup_xirc2ps_cs);
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 9595f74da93..fc08c4af506 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1167,8 +1167,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
* station address PROM at the base address and programmed into the
* "Physical Address Registers" CSR12-14.
* As a precautionary measure, we read the PROM values and complain if
- * they disagree with the CSRs. Either way, we use the CSR values, and
- * double check that they are valid.
+ * they disagree with the CSRs. If they miscompare, and the PROM addr
+ * is valid, then the PROM addr is used.
*/
for (i = 0; i < 3; i++) {
unsigned int val;
@@ -1774,8 +1774,6 @@ static int pcnet32_open(struct net_device *dev)
lp->rx_dma_addr[i] = 0;
}
- pcnet32_free_ring(dev);
-
/*
* Switch back to 16bit mode to avoid problems with dumb
* DOS packet driver after a warm reboot
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 459443b572c..1b236bdf6b9 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -60,8 +60,10 @@ int mdiobus_register(struct mii_bus *bus)
for (i = 0; i < PHY_MAX_ADDR; i++) {
struct phy_device *phydev;
- if (bus->phy_mask & (1 << i))
+ if (bus->phy_mask & (1 << i)) {
+ bus->phy_map[i] = NULL;
continue;
+ }
phydev = get_phy_device(bus, i);
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 475dc930380..0d101a18026 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -861,6 +861,9 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
* give dev_queue_xmit something it can free.
*/
skb2 = skb_clone(skb, GFP_ATOMIC);
+
+ if (skb2 == NULL)
+ goto abort;
}
ph = (struct pppoe_hdr *) skb_push(skb2, sizeof(struct pppoe_hdr));
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 8429ceb0138..f5a3bf4d959 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -127,6 +127,7 @@ static const struct mii_chip_info {
} mii_chip_table[] = {
{ "SiS 900 Internal MII PHY", 0x001d, 0x8000, LAN },
{ "SiS 7014 Physical Layer Solution", 0x0016, 0xf830, LAN },
+ { "SiS 900 on Foxconn 661 7MI", 0x0143, 0xBC70, LAN },
{ "Altimata AC101LF PHY", 0x0022, 0x5520, LAN },
{ "ADM 7001 LAN PHY", 0x002e, 0xcc60, LAN },
{ "AMD 79C901 10BASE-T PHY", 0x0000, 0x6B70, LAN },
@@ -2283,7 +2284,7 @@ static void set_rx_mode(struct net_device *net_dev)
int i, table_entries;
u32 rx_mode;
- /* 635 Hash Table entires = 256(2^16) */
+ /* 635 Hash Table entries = 256(2^16) */
if((sis_priv->chipset_rev >= SIS635A_900_REV) ||
(sis_priv->chipset_rev == SIS900B_900_REV))
table_entries = 16;
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 35dbf05c7f0..5ca5a1b546a 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -78,6 +78,7 @@ static const struct pci_device_id skge_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) },
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), },
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, /* DGE-530T */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
{ PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) },
@@ -400,7 +401,7 @@ static int skge_set_ring_param(struct net_device *dev,
int err;
if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE ||
- p->tx_pending == 0 || p->tx_pending > MAX_TX_RING_SIZE)
+ p->tx_pending < MAX_SKB_FRAGS+1 || p->tx_pending > MAX_TX_RING_SIZE)
return -EINVAL;
skge->rx_ring.count = p->rx_pending;
@@ -2715,8 +2716,7 @@ static int skge_poll(struct net_device *dev, int *budget)
if (control & BMU_OWN)
break;
- skb = skge_rx_get(skge, e, control, rd->status,
- le16_to_cpu(rd->csum2));
+ skb = skge_rx_get(skge, e, control, rd->status, rd->csum2);
if (likely(skb)) {
dev->last_rx = jiffies;
netif_receive_skb(skb);
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 68f9c206a62..97fe95666f3 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -51,7 +51,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.1"
+#define DRV_VERSION "1.4"
#define PFX DRV_NAME " "
/*
@@ -79,6 +79,8 @@
#define NAPI_WEIGHT 64
#define PHY_RETRIES 1000
+#define RING_NEXT(x,s) (((x)+1) & ((s)-1))
+
static const u32 default_msg =
NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
| NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR
@@ -96,11 +98,14 @@ static int disable_msi = 0;
module_param(disable_msi, int, 0);
MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
+static int idle_timeout = 100;
+module_param(idle_timeout, int, 0);
+MODULE_PARM_DESC(idle_timeout, "Idle timeout workaround for lost interrupts (ms)");
+
static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
- { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) },
- { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) },
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) },
@@ -124,6 +129,7 @@ MODULE_DEVICE_TABLE(pci, sky2_id_table);
/* Avoid conditionals by using array */
static const unsigned txqaddr[] = { Q_XA1, Q_XA2 };
static const unsigned rxqaddr[] = { Q_R1, Q_R2 };
+static const u32 portirq_msk[] = { Y2_IS_PORT_1, Y2_IS_PORT_2 };
/* This driver supports yukon2 chipset only */
static const char *yukon2_name[] = {
@@ -181,12 +187,11 @@ static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg)
return v;
}
-static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
+static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
{
u16 power_control;
u32 reg1;
int vaux;
- int ret = 0;
pr_debug("sky2_set_power_state %d\n", state);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
@@ -230,6 +235,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
}
if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
+ sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON);
sky2_pci_write32(hw, PCI_DEV_REG3, 0);
reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
reg1 &= P_ASPM_CONTROL_MSK;
@@ -268,12 +274,10 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
break;
default:
printk(KERN_ERR PFX "Unknown power state %d\n", state);
- ret = -1;
}
sky2_pci_write16(hw, hw->pm_cap + PCI_PM_CTRL, power_control);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
- return ret;
}
static void sky2_phy_reset(struct sky2_hw *hw, unsigned port)
@@ -300,7 +304,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
u16 ctrl, ct1000, adv, pg, ledctrl, ledover;
- if (sky2->autoneg == AUTONEG_ENABLE && hw->chip_id != CHIP_ID_YUKON_XL) {
+ if (sky2->autoneg == AUTONEG_ENABLE &&
+ !(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) {
u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
@@ -328,7 +333,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO);
if (sky2->autoneg == AUTONEG_ENABLE &&
- hw->chip_id == CHIP_ID_YUKON_XL) {
+ (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) {
ctrl &= ~PHY_M_PC_DSC_MSK;
ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
}
@@ -444,10 +449,11 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
/* set LED Function Control register */
- gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
- PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */
- PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */
- PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+ (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
+ PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */
+ PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */
+ PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */
/* set Polarity Control register */
gm_phy_write(hw, port, PHY_MARV_PHY_STAT,
@@ -461,6 +467,25 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
/* restore page register */
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
break;
+ case CHIP_ID_YUKON_EC_U:
+ pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+ /* select page 3 to access LED control register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+
+ /* set LED Function Control register */
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+ (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
+ PHY_M_LEDC_INIT_CTRL(8) | /* 10 Mbps */
+ PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */
+ PHY_M_LEDC_STA0_CTRL(7)));/* 1000 Mbps */
+
+ /* set Blink Rate in LED Timer Control Register */
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK,
+ ledctrl | PHY_M_LED_BLINK_RT(BLINK_84MS));
+ /* restore page register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ break;
default:
/* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
@@ -469,19 +494,21 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
}
- if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) {
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_A1) {
/* apply fixes in PHY AFE */
- gm_phy_write(hw, port, 22, 255);
+ pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255);
+
/* increase differential signal amplitude in 10BASE-T */
- gm_phy_write(hw, port, 24, 0xaa99);
- gm_phy_write(hw, port, 23, 0x2011);
+ gm_phy_write(hw, port, 0x18, 0xaa99);
+ gm_phy_write(hw, port, 0x17, 0x2011);
/* fix for IEEE A/B Symmetry failure in 1000BASE-T */
- gm_phy_write(hw, port, 24, 0xa204);
- gm_phy_write(hw, port, 23, 0x2002);
+ gm_phy_write(hw, port, 0x18, 0xa204);
+ gm_phy_write(hw, port, 0x17, 0x2002);
/* set page register to 0 */
- gm_phy_write(hw, port, 22, 0);
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
} else {
gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
@@ -555,6 +582,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
if (sky2->duplex == DUPLEX_FULL)
reg |= GM_GPCR_DUP_FULL;
+
+ /* turn off pause in 10/100mbps half duplex */
+ else if (sky2->speed != SPEED_1000 &&
+ hw->chip_id != CHIP_ID_YUKON_EC_U)
+ sky2->tx_pause = sky2->rx_pause = 0;
} else
reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
@@ -579,8 +611,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
reg = gma_read16(hw, port, GM_PHY_ADDR);
gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
- for (i = 0; i < GM_MIB_CNT_SIZE; i++)
- gma_read16(hw, port, GM_MIB_CNT_BASE + 8 * i);
+ for (i = GM_MIB_CNT_BASE; i <= GM_MIB_CNT_END; i += 4)
+ gma_read16(hw, port, i);
gma_write16(hw, port, GM_PHY_ADDR, reg);
/* transmit control */
@@ -721,7 +753,7 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2)
{
struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod;
- sky2->tx_prod = (sky2->tx_prod + 1) % TX_RING_SIZE;
+ sky2->tx_prod = RING_NEXT(sky2->tx_prod, TX_RING_SIZE);
return le;
}
@@ -737,7 +769,7 @@ static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx)
static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
{
struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put;
- sky2->rx_put = (sky2->rx_put + 1) % RX_LE_SIZE;
+ sky2->rx_put = RING_NEXT(sky2->rx_put, RX_LE_SIZE);
return le;
}
@@ -927,8 +959,7 @@ static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask)
skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask);
if (likely(skb)) {
unsigned long p = (unsigned long) skb->data;
- skb_reserve(skb,
- ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p);
+ skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p);
}
return skb;
@@ -945,6 +976,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
struct sky2_hw *hw = sky2->hw;
unsigned rxq = rxqaddr[sky2->port];
int i;
+ unsigned thresh;
sky2->rx_put = sky2->rx_next = 0;
sky2_qset(hw, rxq);
@@ -969,9 +1001,21 @@ static int sky2_rx_start(struct sky2_port *sky2)
sky2_rx_add(sky2, re->mapaddr);
}
- /* Truncate oversize frames */
- sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), sky2->rx_bufsize - 8);
- sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON);
+
+ /*
+ * The receiver hangs if it receives frames larger than the
+ * packet buffer. As a workaround, truncate oversize frames, but
+ * the register is limited to 9 bits, so if you do frames > 2052
+ * you better get the MTU right!
+ */
+ thresh = (sky2->rx_bufsize - 8) / sizeof(u32);
+ if (thresh > 0x1ff)
+ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF);
+ else {
+ sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), thresh);
+ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON);
+ }
+
/* Tell chip about available buffers */
sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put);
@@ -988,7 +1032,25 @@ static int sky2_up(struct net_device *dev)
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
u32 ramsize, rxspace, imask;
- int err = -ENOMEM;
+ int cap, err = -ENOMEM;
+ struct net_device *otherdev = hw->dev[sky2->port^1];
+
+ /*
+ * On dual port PCI-X card, there is an problem where status
+ * can be received out of order due to split transactions
+ */
+ if (otherdev && netif_running(otherdev) &&
+ (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) {
+ struct sky2_port *osky2 = netdev_priv(otherdev);
+ u16 cmd;
+
+ cmd = sky2_pci_read16(hw, cap + PCI_X_CMD);
+ cmd &= ~PCI_X_CMD_MAX_SPLIT;
+ sky2_pci_write16(hw, cap + PCI_X_CMD, cmd);
+
+ sky2->rx_csum = 0;
+ osky2->rx_csum = 0;
+ }
if (netif_msg_ifup(sky2))
printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
@@ -1053,7 +1115,7 @@ static int sky2_up(struct net_device *dev)
/* Enable interrupts from phy/mac for port */
imask = sky2_read32(hw, B0_IMSK);
- imask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2;
+ imask |= portirq_msk[port];
sky2_write32(hw, B0_IMSK, imask);
return 0;
@@ -1081,7 +1143,7 @@ err_out:
/* Modular subtraction in ring */
static inline int tx_dist(unsigned tail, unsigned head)
{
- return (head - tail) % TX_RING_SIZE;
+ return (head - tail) & (TX_RING_SIZE - 1);
}
/* Number of list elements available for next tx */
@@ -1258,7 +1320,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
le->opcode = OP_BUFFER | HW_OWNER;
fre = sky2->tx_ring
- + ((re - sky2->tx_ring) + i + 1) % TX_RING_SIZE;
+ + RING_NEXT((re - sky2->tx_ring) + i, TX_RING_SIZE);
pci_unmap_addr_set(fre, mapaddr, mapping);
}
@@ -1318,7 +1380,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
struct tx_ring_info *fre;
- fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE;
+ fre = sky2->tx_ring + RING_NEXT(put + i, TX_RING_SIZE);
pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr),
skb_shinfo(skb)->frags[i].size,
PCI_DMA_TODEVICE);
@@ -1404,7 +1466,7 @@ static int sky2_down(struct net_device *dev)
/* Disable port IRQ */
imask = sky2_read32(hw, B0_IMSK);
- imask &= ~(sky2->port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2;
+ imask &= ~portirq_msk[port];
sky2_write32(hw, B0_IMSK, imask);
/* turn off LED's */
@@ -1501,17 +1563,26 @@ static void sky2_link_up(struct sky2_port *sky2)
sky2_write8(hw, SK_REG(port, LNK_LED_REG),
LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
- if (hw->chip_id == CHIP_ID_YUKON_XL) {
+ if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) {
u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+ u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */
+
+ switch(sky2->speed) {
+ case SPEED_10:
+ led |= PHY_M_LEDC_INIT_CTRL(7);
+ break;
+
+ case SPEED_100:
+ led |= PHY_M_LEDC_STA1_CTRL(7);
+ break;
+
+ case SPEED_1000:
+ led |= PHY_M_LEDC_STA0_CTRL(7);
+ break;
+ }
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
- gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
- PHY_M_LEDC_INIT_CTRL(sky2->speed ==
- SPEED_10 ? 7 : 0) |
- PHY_M_LEDC_STA1_CTRL(sky2->speed ==
- SPEED_100 ? 7 : 0) |
- PHY_M_LEDC_STA0_CTRL(sky2->speed ==
- SPEED_1000 ? 7 : 0));
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, led);
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
}
@@ -1586,7 +1657,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
sky2->speed = sky2_phy_speed(hw, aux);
/* Pause bits are offset (9..8) */
- if (hw->chip_id == CHIP_ID_YUKON_XL)
+ if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)
aux >>= 6;
sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0;
@@ -1688,13 +1759,12 @@ static void sky2_tx_timeout(struct net_device *dev)
}
-#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
/* Want receive buffer size to be multiple of 64 bits
* and incl room for vlan and truncation
*/
static inline unsigned sky2_buf_size(int mtu)
{
- return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8;
+ return ALIGN(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8;
}
static int sky2_change_mtu(struct net_device *dev, int new_mtu)
@@ -1859,39 +1929,38 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
}
}
+/* Is status ring empty or is there more to do? */
+static inline int sky2_more_work(const struct sky2_hw *hw)
+{
+ return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX));
+}
+
/* Process status response ring */
static int sky2_status_intr(struct sky2_hw *hw, int to_do)
{
int work_done = 0;
+ u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
rmb();
- for(;;) {
+ while (hw->st_idx != hwidx) {
struct sky2_status_le *le = hw->st_le + hw->st_idx;
struct net_device *dev;
struct sky2_port *sky2;
struct sk_buff *skb;
u32 status;
u16 length;
- u8 link, opcode;
- opcode = le->opcode;
- if (!opcode)
- break;
- opcode &= ~HW_OWNER;
-
- hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE;
- le->opcode = 0;
+ hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE);
- link = le->link;
- BUG_ON(link >= 2);
- dev = hw->dev[link];
+ BUG_ON(le->link >= 2);
+ dev = hw->dev[le->link];
sky2 = netdev_priv(dev);
length = le->length;
status = le->status;
- switch (opcode) {
+ switch (le->opcode & ~HW_OWNER) {
case OP_RXSTAT:
skb = sky2_receive(sky2, length, status);
if (!skb)
@@ -1931,7 +2000,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
case OP_TXINDEXLE:
/* TX index reports status for both ports */
- sky2_tx_done(hw->dev[0], status & 0xffff);
+ BUILD_BUG_ON(TX_RING_SIZE > 0x1000);
+ sky2_tx_done(hw->dev[0], status & 0xfff);
if (hw->dev[1])
sky2_tx_done(hw->dev[1],
((status >> 24) & 0xff)
@@ -1941,8 +2011,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
default:
if (net_ratelimit())
printk(KERN_WARNING PFX
- "unknown status opcode 0x%x\n", opcode);
- break;
+ "unknown status opcode 0x%x\n", le->opcode);
+ goto exit_loop;
}
}
@@ -2088,6 +2158,28 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port,
}
}
+/* If idle then force a fake soft NAPI poll once a second
+ * to work around cases where sharing an edge triggered interrupt.
+ */
+static inline void sky2_idle_start(struct sky2_hw *hw)
+{
+ if (idle_timeout > 0)
+ mod_timer(&hw->idle_timer,
+ jiffies + msecs_to_jiffies(idle_timeout));
+}
+
+static void sky2_idle(unsigned long arg)
+{
+ struct sky2_hw *hw = (struct sky2_hw *) arg;
+ struct net_device *dev = hw->dev[0];
+
+ if (__netif_rx_schedule_prep(dev))
+ __netif_rx_schedule(dev);
+
+ mod_timer(&hw->idle_timer, jiffies + msecs_to_jiffies(idle_timeout));
+}
+
+
static int sky2_poll(struct net_device *dev0, int *budget)
{
struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw;
@@ -2095,49 +2187,49 @@ static int sky2_poll(struct net_device *dev0, int *budget)
int work_done = 0;
u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
- if (unlikely(status & ~Y2_IS_STAT_BMU)) {
- if (status & Y2_IS_HW_ERR)
- sky2_hw_intr(hw);
+ if (!~status)
+ goto out;
- if (status & Y2_IS_IRQ_PHY1)
- sky2_phy_intr(hw, 0);
+ if (status & Y2_IS_HW_ERR)
+ sky2_hw_intr(hw);
- if (status & Y2_IS_IRQ_PHY2)
- sky2_phy_intr(hw, 1);
+ if (status & Y2_IS_IRQ_PHY1)
+ sky2_phy_intr(hw, 0);
- if (status & Y2_IS_IRQ_MAC1)
- sky2_mac_intr(hw, 0);
+ if (status & Y2_IS_IRQ_PHY2)
+ sky2_phy_intr(hw, 1);
- if (status & Y2_IS_IRQ_MAC2)
- sky2_mac_intr(hw, 1);
+ if (status & Y2_IS_IRQ_MAC1)
+ sky2_mac_intr(hw, 0);
- if (status & Y2_IS_CHK_RX1)
- sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1);
+ if (status & Y2_IS_IRQ_MAC2)
+ sky2_mac_intr(hw, 1);
- if (status & Y2_IS_CHK_RX2)
- sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2);
+ if (status & Y2_IS_CHK_RX1)
+ sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1);
- if (status & Y2_IS_CHK_TXA1)
- sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1);
+ if (status & Y2_IS_CHK_RX2)
+ sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2);
- if (status & Y2_IS_CHK_TXA2)
- sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);
- }
+ if (status & Y2_IS_CHK_TXA1)
+ sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1);
- if (status & Y2_IS_STAT_BMU) {
- work_done = sky2_status_intr(hw, work_limit);
- *budget -= work_done;
- dev0->quota -= work_done;
+ if (status & Y2_IS_CHK_TXA2)
+ sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);
- if (work_done >= work_limit)
- return 1;
+ work_done = sky2_status_intr(hw, work_limit);
+ *budget -= work_done;
+ dev0->quota -= work_done;
+ if (status & Y2_IS_STAT_BMU)
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
- }
+ if (sky2_more_work(hw))
+ return 1;
+out:
netif_rx_complete(dev0);
- status = sky2_read32(hw, B0_Y2_SP_LISR);
+ sky2_read32(hw, B0_Y2_SP_LISR);
return 0;
}
@@ -2155,8 +2247,6 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
prefetch(&hw->st_le[hw->st_idx]);
if (likely(__netif_rx_schedule_prep(dev0)))
__netif_rx_schedule(dev0);
- else
- printk(KERN_DEBUG PFX "irq race detected\n");
return IRQ_HANDLED;
}
@@ -2195,7 +2285,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
}
-static int sky2_reset(struct sky2_hw *hw)
+static int __devinit sky2_reset(struct sky2_hw *hw)
{
u16 status;
u8 t8, pmd_type;
@@ -2220,13 +2310,6 @@ static int sky2_reset(struct sky2_hw *hw)
return -EOPNOTSUPP;
}
- /* This chip is new and not tested yet */
- if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
- pr_info(PFX "%s: is a version of Yukon 2 chipset that has not been tested yet.\n",
- pci_name(hw->pdev));
- pr_info("Please report success/failure to maintainer <shemminger@osdl.org>\n");
- }
-
/* disable ASF */
if (hw->chip_id <= CHIP_ID_YUKON_EC) {
sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
@@ -3030,12 +3113,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
sky2->duplex = -1;
sky2->speed = -1;
sky2->advertising = sky2_supported_modes(hw);
-
- /* Receive checksum disabled for Yukon XL
- * because of observed problems with incorrect
- * values when multiple packets are received in one interrupt
- */
- sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL);
+ sky2->rx_csum = 1;
spin_lock_init(&sky2->phy_lock);
sky2->tx_pending = TX_DEF_PENDING;
@@ -3278,6 +3356,9 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+ setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw);
+ sky2_idle_start(hw);
+
pci_set_drvdata(pdev, hw);
return 0;
@@ -3313,13 +3394,17 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
if (!hw)
return;
+ del_timer_sync(&hw->idle_timer);
+
+ sky2_write32(hw, B0_IMSK, 0);
+ synchronize_irq(hw->pdev->irq);
+
dev0 = hw->dev[0];
dev1 = hw->dev[1];
if (dev1)
unregister_netdev(dev1);
unregister_netdev(dev0);
- sky2_write32(hw, B0_IMSK, 0);
sky2_set_power_state(hw, PCI_D3hot);
sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
sky2_write8(hw, B0_CTST, CS_RST_SET);
@@ -3345,8 +3430,14 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct sky2_hw *hw = pci_get_drvdata(pdev);
int i;
+ pci_power_t pstate = pci_choose_state(pdev, state);
+
+ if (!(pstate == PCI_D3hot || pstate == PCI_D3cold))
+ return -EINVAL;
- for (i = 0; i < 2; i++) {
+ del_timer_sync(&hw->idle_timer);
+
+ for (i = 0; i < hw->ports; i++) {
struct net_device *dev = hw->dev[i];
if (dev) {
@@ -3358,7 +3449,10 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
}
}
- return sky2_set_power_state(hw, pci_choose_state(pdev, state));
+ sky2_write32(hw, B0_IMSK, 0);
+ pci_save_state(pdev);
+ sky2_set_power_state(hw, pstate);
+ return 0;
}
static int sky2_resume(struct pci_dev *pdev)
@@ -3368,15 +3462,15 @@ static int sky2_resume(struct pci_dev *pdev)
pci_restore_state(pdev);
pci_enable_wake(pdev, PCI_D0, 0);
- err = sky2_set_power_state(hw, PCI_D0);
- if (err)
- goto out;
+ sky2_set_power_state(hw, PCI_D0);
err = sky2_reset(hw);
if (err)
goto out;
- for (i = 0; i < 2; i++) {
+ sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+
+ for (i = 0; i < hw->ports; i++) {
struct net_device *dev = hw->dev[i];
if (dev && netif_running(dev)) {
netif_device_attach(dev);
@@ -3385,10 +3479,12 @@ static int sky2_resume(struct pci_dev *pdev)
printk(KERN_ERR PFX "%s: could not up: %d\n",
dev->name, err);
dev_close(dev);
- break;
+ goto out;
}
}
}
+
+ sky2_idle_start(hw);
out:
return err;
}
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 62532b4e45c..8a0bc5525f0 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -214,6 +214,8 @@ enum csr_regs {
enum {
Y2_VMAIN_AVAIL = 1<<17,/* VMAIN available (YUKON-2 only) */
Y2_VAUX_AVAIL = 1<<16,/* VAUX available (YUKON-2 only) */
+ Y2_HW_WOL_ON = 1<<15,/* HW WOL On (Yukon-EC Ultra A1 only) */
+ Y2_HW_WOL_OFF = 1<<14,/* HW WOL On (Yukon-EC Ultra A1 only) */
Y2_ASF_ENABLE = 1<<13,/* ASF Unit Enable (YUKON-2 only) */
Y2_ASF_DISABLE = 1<<12,/* ASF Unit Disable (YUKON-2 only) */
Y2_CLK_RUN_ENA = 1<<11,/* CLK_RUN Enable (YUKON-2 only) */
@@ -378,6 +380,9 @@ enum {
CHIP_REV_YU_EC_A1 = 0, /* Chip Rev. for Yukon-EC A1/A0 */
CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */
CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */
+
+ CHIP_REV_YU_EC_U_A0 = 0,
+ CHIP_REV_YU_EC_U_A1 = 1,
};
/* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */
@@ -1375,7 +1380,7 @@ enum {
GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */
/* MIB Counters */
GM_MIB_CNT_BASE = 0x0100, /* Base Address of MIB Counters */
- GM_MIB_CNT_SIZE = 256,
+ GM_MIB_CNT_END = 0x025C, /* Last MIB counter */
};
@@ -1880,6 +1885,8 @@ struct sky2_hw {
struct sky2_status_le *st_le;
u32 st_idx;
dma_addr_t st_dma;
+
+ struct timer_list idle_timer;
int msi_detected;
wait_queue_head_t msi_wait;
};
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 1f5975a61e1..394339d5e87 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1442,7 +1442,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GRFAFLLINT: /* fallthrough */
case SPIDER_NET_GRMFLLINT:
if (netif_msg_intr(card) && net_ratelimit())
- pr_err("Spider RX RAM full, incoming packets "
+ pr_debug("Spider RX RAM full, incoming packets "
"might be discarded!\n");
spider_net_rx_irq_off(card);
tasklet_schedule(&card->rxram_full_tl);
@@ -1652,6 +1652,8 @@ spider_net_enable_card(struct spider_net_card *card)
{ SPIDER_NET_GFTRESTRT, SPIDER_NET_RESTART_VALUE },
{ SPIDER_NET_GMRWOLCTRL, 0 },
+ { SPIDER_NET_GTESTMD, 0x10000000 },
+ { SPIDER_NET_GTTQMSK, 0x00400040 },
{ SPIDER_NET_GTESTMD, 0 },
{ SPIDER_NET_GMACINTEN, 0 },
@@ -1792,15 +1794,7 @@ spider_net_setup_phy(struct spider_net_card *card)
if (phy->def->ops->setup_forced)
phy->def->ops->setup_forced(phy, SPEED_1000, DUPLEX_FULL);
- /* the following two writes could be moved to sungem_phy.c */
- /* enable fiber mode */
- spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x9020);
- /* LEDs active in both modes, autosense prio = fiber */
- spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f);
-
- /* switch off fibre autoneg */
- spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01);
- spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004);
+ phy->def->ops->enable_fiber(phy);
phy->def->ops->read_link(phy);
pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name,
@@ -2086,7 +2080,7 @@ spider_net_setup_netdev(struct spider_net_card *card)
spider_net_setup_netdev_ops(netdev);
- netdev->features = 0;
+ netdev->features = NETIF_F_HW_CSUM;
/* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
* NETIF_F_HW_VLAN_FILTER */
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index 5922b529a04..3b8d951cf73 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -120,6 +120,8 @@ extern char spider_net_driver_name[];
#define SPIDER_NET_GMRUAFILnR 0x00000500
#define SPIDER_NET_GMRUA0FIL15R 0x00000578
+#define SPIDER_NET_GTTQMSK 0x00000934
+
/* RX DMA controller registers, all 0x00000a.. are for DMA controller A,
* 0x00000b.. for DMA controller B, etc. */
#define SPIDER_NET_GDADCHA 0x00000a00
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 35b18057fbd..9b7805be21d 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -335,7 +335,7 @@ do { \
/* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n"
KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
@@ -2122,8 +2122,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct netdev_private *np = netdev_priv(dev);
- if (!dev)
- BUG();
+ BUG_ON(!dev);
unregister_netdev(dev);
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index cb0aba95d4e..b2ddd5e7930 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -275,7 +275,7 @@ static int bcm5411_init(struct mii_phy* phy)
return 0;
}
-static int bcm5411_suspend(struct mii_phy* phy)
+static int generic_suspend(struct mii_phy* phy)
{
phy_write(phy, MII_BMCR, BMCR_PDOWN);
@@ -329,6 +329,30 @@ static int bcm5421_init(struct mii_phy* phy)
return 0;
}
+static int bcm5421_enable_fiber(struct mii_phy* phy)
+{
+ /* enable fiber mode */
+ phy_write(phy, MII_NCONFIG, 0x9020);
+ /* LEDs active in both modes, autosense prio = fiber */
+ phy_write(phy, MII_NCONFIG, 0x945f);
+
+ /* switch off fibre autoneg */
+ phy_write(phy, MII_NCONFIG, 0xfc01);
+ phy_write(phy, 0x0b, 0x0004);
+
+ return 0;
+}
+
+static int bcm5461_enable_fiber(struct mii_phy* phy)
+{
+ phy_write(phy, MII_NCONFIG, 0xfc0c);
+ phy_write(phy, MII_BMCR, 0x4140);
+ phy_write(phy, MII_NCONFIG, 0xfc0b);
+ phy_write(phy, MII_BMCR, 0x0140);
+
+ return 0;
+}
+
static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
{
u16 ctl, adv;
@@ -738,7 +762,7 @@ static struct mii_phy_def bcm5401_phy_def = {
/* Broadcom BCM 5411 */
static struct mii_phy_ops bcm5411_phy_ops = {
.init = bcm5411_init,
- .suspend = bcm5411_suspend,
+ .suspend = generic_suspend,
.setup_aneg = bcm54xx_setup_aneg,
.setup_forced = bcm54xx_setup_forced,
.poll_link = genmii_poll_link,
@@ -757,11 +781,12 @@ static struct mii_phy_def bcm5411_phy_def = {
/* Broadcom BCM 5421 */
static struct mii_phy_ops bcm5421_phy_ops = {
.init = bcm5421_init,
- .suspend = bcm5411_suspend,
+ .suspend = generic_suspend,
.setup_aneg = bcm54xx_setup_aneg,
.setup_forced = bcm54xx_setup_forced,
.poll_link = genmii_poll_link,
.read_link = bcm54xx_read_link,
+ .enable_fiber = bcm5421_enable_fiber,
};
static struct mii_phy_def bcm5421_phy_def = {
@@ -776,7 +801,7 @@ static struct mii_phy_def bcm5421_phy_def = {
/* Broadcom BCM 5421 built-in K2 */
static struct mii_phy_ops bcm5421k2_phy_ops = {
.init = bcm5421_init,
- .suspend = bcm5411_suspend,
+ .suspend = generic_suspend,
.setup_aneg = bcm54xx_setup_aneg,
.setup_forced = bcm54xx_setup_forced,
.poll_link = genmii_poll_link,
@@ -792,10 +817,29 @@ static struct mii_phy_def bcm5421k2_phy_def = {
.ops = &bcm5421k2_phy_ops
};
+static struct mii_phy_ops bcm5461_phy_ops = {
+ .init = bcm5421_init,
+ .suspend = generic_suspend,
+ .setup_aneg = bcm54xx_setup_aneg,
+ .setup_forced = bcm54xx_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = bcm54xx_read_link,
+ .enable_fiber = bcm5461_enable_fiber,
+};
+
+static struct mii_phy_def bcm5461_phy_def = {
+ .phy_id = 0x002060c0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5461",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5461_phy_ops
+};
+
/* Broadcom BCM 5462 built-in Vesta */
static struct mii_phy_ops bcm5462V_phy_ops = {
.init = bcm5421_init,
- .suspend = bcm5411_suspend,
+ .suspend = generic_suspend,
.setup_aneg = bcm54xx_setup_aneg,
.setup_forced = bcm54xx_setup_forced,
.poll_link = genmii_poll_link,
@@ -816,6 +860,7 @@ static struct mii_phy_def bcm5462V_phy_def = {
* would be useful here) --BenH.
*/
static struct mii_phy_ops marvell_phy_ops = {
+ .suspend = generic_suspend,
.setup_aneg = marvell_setup_aneg,
.setup_forced = marvell_setup_forced,
.poll_link = genmii_poll_link,
@@ -856,6 +901,7 @@ static struct mii_phy_def* mii_phy_table[] = {
&bcm5411_phy_def,
&bcm5421_phy_def,
&bcm5421k2_phy_def,
+ &bcm5461_phy_def,
&bcm5462V_phy_def,
&marvell_phy_def,
&genmii_phy_def,
diff --git a/drivers/net/sungem_phy.h b/drivers/net/sungem_phy.h
index 430544496c5..69e125197fc 100644
--- a/drivers/net/sungem_phy.h
+++ b/drivers/net/sungem_phy.h
@@ -12,6 +12,7 @@ struct mii_phy_ops
int (*setup_forced)(struct mii_phy *phy, int speed, int fd);
int (*poll_link)(struct mii_phy *phy);
int (*read_link)(struct mii_phy *phy);
+ int (*enable_fiber)(struct mii_phy *phy);
};
/* Structure used to statically define an mii/gii based PHY */
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index b5473325bff..862c226dbbe 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,8 +69,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.54"
-#define DRV_MODULE_RELDATE "Mar 23, 2006"
+#define DRV_MODULE_VERSION "3.59"
+#define DRV_MODULE_RELDATE "June 8, 2006"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -497,21 +497,20 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
unsigned long flags;
spin_lock_irqsave(&tp->indirect_lock, flags);
- pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
- pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+ if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
- /* Always leave this as zero. */
- pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
- spin_unlock_irqrestore(&tp->indirect_lock, flags);
-}
+ /* Always leave this as zero. */
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+ } else {
+ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+ tw32_f(TG3PCI_MEM_WIN_DATA, val);
-static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val)
-{
- /* If no workaround is needed, write to mem space directly */
- if (tp->write32 != tg3_write_indirect_reg32)
- tw32(NIC_SRAM_WIN_BASE + off, val);
- else
- tg3_write_mem(tp, off, val);
+ /* Always leave this as zero. */
+ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+ }
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
}
static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
@@ -519,11 +518,19 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
unsigned long flags;
spin_lock_irqsave(&tp->indirect_lock, flags);
- pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
- pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+ if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+ pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
- /* Always leave this as zero. */
- pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+ /* Always leave this as zero. */
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+ } else {
+ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+ *val = tr32(TG3PCI_MEM_WIN_DATA);
+
+ /* Always leave this as zero. */
+ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+ }
spin_unlock_irqrestore(&tp->indirect_lock, flags);
}
@@ -967,6 +974,8 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
return err;
}
+static void tg3_link_report(struct tg3 *);
+
/* This will reset the tigon3 PHY if there is no valid
* link unless the FORCE argument is non-zero.
*/
@@ -980,6 +989,11 @@ static int tg3_phy_reset(struct tg3 *tp)
if (err != 0)
return -EBUSY;
+ if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) {
+ netif_carrier_off(tp->dev);
+ tg3_link_report(tp);
+ }
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
@@ -1016,6 +1030,12 @@ out:
tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x14e2);
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
}
+ else if (tp->tg3_flags2 & TG3_FLG2_PHY_JITTER_BUG) {
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
+ }
/* Set Extended packet length bit (bit 14) on all chips that */
/* support jumbo frames */
if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
@@ -1367,12 +1387,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
}
}
+ tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
+
/* Finally, set the new power state. */
pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
udelay(100); /* Delay after power state change */
- tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
-
return 0;
}
@@ -2959,9 +2979,7 @@ static void tg3_tx(struct tg3 *tp)
struct sk_buff *skb = ri->skb;
int i;
- if (unlikely(skb == NULL))
- BUG();
-
+ BUG_ON(skb == NULL);
pci_unmap_single(tp->pdev,
pci_unmap_addr(ri, mapping),
skb_headlen(skb),
@@ -2972,12 +2990,10 @@ static void tg3_tx(struct tg3 *tp)
sw_idx = NEXT_TX(sw_idx);
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- if (unlikely(sw_idx == hw_idx))
- BUG();
+ BUG_ON(sw_idx == hw_idx);
ri = &tp->tx_buffers[sw_idx];
- if (unlikely(ri->skb != NULL))
- BUG();
+ BUG_ON(ri->skb != NULL);
pci_unmap_page(tp->pdev,
pci_unmap_addr(ri, mapping),
@@ -3528,7 +3544,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
return IRQ_RETVAL(0);
}
-static int tg3_init_hw(struct tg3 *);
+static int tg3_init_hw(struct tg3 *, int);
static int tg3_halt(struct tg3 *, int, int);
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3564,7 +3580,7 @@ static void tg3_reset_task(void *_data)
tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER;
tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 1);
tg3_netif_start(tp);
@@ -3600,7 +3616,7 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping,
int len)
{
#if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64)
- if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
+ if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG)
return (((u64) mapping + len) > DMA_40BIT_MASK);
return 0;
#else
@@ -4039,7 +4055,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
tg3_set_mtu(dev, tp, new_mtu);
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 0);
tg3_netif_start(tp);
@@ -4469,9 +4485,8 @@ static void tg3_disable_nvram_access(struct tg3 *tp)
/* tp->lock is held. */
static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
{
- if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
- tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
- NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
+ tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
+ NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) {
switch (kind) {
@@ -4552,13 +4567,12 @@ static int tg3_chip_reset(struct tg3 *tp)
void (*write_op)(struct tg3 *, u32, u32);
int i;
- if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
- tg3_nvram_lock(tp);
- /* No matching tg3_nvram_unlock() after this because
- * chip reset below will undo the nvram lock.
- */
- tp->nvram_lock_cnt = 0;
- }
+ tg3_nvram_lock(tp);
+
+ /* No matching tg3_nvram_unlock() after this because
+ * chip reset below will undo the nvram lock.
+ */
+ tp->nvram_lock_cnt = 0;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
@@ -4711,20 +4725,25 @@ static int tg3_chip_reset(struct tg3 *tp)
tw32_f(MAC_MODE, 0);
udelay(40);
- if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
- /* Wait for firmware initialization to complete. */
- for (i = 0; i < 100000; i++) {
- tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
- if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
- break;
- udelay(10);
- }
- if (i >= 100000) {
- printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
- "firmware will not restart magic=%08x\n",
- tp->dev->name, val);
- return -ENODEV;
- }
+ /* Wait for firmware initialization to complete. */
+ for (i = 0; i < 100000; i++) {
+ tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
+ if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
+ break;
+ udelay(10);
+ }
+
+ /* Chip might not be fitted with firmare. Some Sun onboard
+ * parts are configured like that. So don't signal the timeout
+ * of the above loop as an error, but do report the lack of
+ * running firmware once.
+ */
+ if (i >= 100000 &&
+ !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) {
+ tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED;
+
+ printk(KERN_INFO PFX "%s: No firmware running.\n",
+ tp->dev->name);
}
if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
@@ -4928,9 +4947,8 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
{
int i;
- if (offset == TX_CPU_BASE &&
- (tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
- BUG();
+ BUG_ON(offset == TX_CPU_BASE &&
+ (tp->tg3_flags2 & TG3_FLG2_5705_PLUS));
if (offset == RX_CPU_BASE) {
for (i = 0; i < 10000; i++) {
@@ -5717,9 +5735,23 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
if (!netif_running(dev))
return 0;
- spin_lock_bh(&tp->lock);
- __tg3_set_mac_addr(tp);
- spin_unlock_bh(&tp->lock);
+ if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
+ /* Reset chip so that ASF can re-init any MAC addresses it
+ * needs.
+ */
+ tg3_netif_stop(tp);
+ tg3_full_lock(tp, 1);
+
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
+ tg3_init_hw(tp, 0);
+
+ tg3_netif_start(tp);
+ tg3_full_unlock(tp);
+ } else {
+ spin_lock_bh(&tp->lock);
+ __tg3_set_mac_addr(tp);
+ spin_unlock_bh(&tp->lock);
+ }
return 0;
}
@@ -5769,7 +5801,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
}
/* tp->lock is held. */
-static int tg3_reset_hw(struct tg3 *tp)
+static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
{
u32 val, rdmac_mode;
int i, err, limit;
@@ -5784,7 +5816,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tg3_abort_hw(tp, 1);
}
- if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
+ if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) && reset_phy)
tg3_phy_reset(tp);
err = tg3_chip_reset(tp);
@@ -5833,10 +5865,14 @@ static int tg3_reset_hw(struct tg3 *tp)
GRC_MODE_NO_TX_PHDR_CSUM |
GRC_MODE_NO_RX_PHDR_CSUM);
tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
- if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM)
- tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
- if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM)
- tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
+
+ /* Pseudo-header checksum is done by hardware logic and not
+ * the offload processers, so make the chip do the pseudo-
+ * header checksums on receive. For transmit it is more
+ * convenient to do the pseudo-header checksum in software
+ * as Linux does that on transmit for us in all cases.
+ */
+ tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
tw32(GRC_MODE,
tp->grc_mode |
@@ -6321,7 +6357,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
}
- err = tg3_setup_phy(tp, 1);
+ err = tg3_setup_phy(tp, reset_phy);
if (err)
return err;
@@ -6394,7 +6430,7 @@ static int tg3_reset_hw(struct tg3 *tp)
/* Called at device open time to get the chip ready for
* packet processing. Invoked with tp->lock held.
*/
-static int tg3_init_hw(struct tg3 *tp)
+static int tg3_init_hw(struct tg3 *tp, int reset_phy)
{
int err;
@@ -6407,7 +6443,7 @@ static int tg3_init_hw(struct tg3 *tp)
tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
- err = tg3_reset_hw(tp);
+ err = tg3_reset_hw(tp, reset_phy);
out:
return err;
@@ -6455,12 +6491,19 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
TG3_STAT_ADD32(&sp->rx_frame_too_long_errors, MAC_RX_STATS_FRAME_TOO_LONG);
TG3_STAT_ADD32(&sp->rx_jabbers, MAC_RX_STATS_JABBERS);
TG3_STAT_ADD32(&sp->rx_undersize_packets, MAC_RX_STATS_UNDERSIZE);
+
+ TG3_STAT_ADD32(&sp->rxbds_empty, RCVLPC_NO_RCV_BD_CNT);
+ TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT);
+ TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT);
}
static void tg3_timer(unsigned long __opaque)
{
struct tg3 *tp = (struct tg3 *) __opaque;
+ if (tp->irq_sync)
+ goto restart_timer;
+
spin_lock(&tp->lock);
if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
@@ -6537,11 +6580,11 @@ static void tg3_timer(unsigned long __opaque)
if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
u32 val;
- tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX,
- FWCMD_NICDRV_ALIVE2);
- tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
+ FWCMD_NICDRV_ALIVE2);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
/* 5 seconds timeout */
- tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
val = tr32(GRC_RX_CPU_EVENT);
val |= (1 << 14);
tw32(GRC_RX_CPU_EVENT, val);
@@ -6551,6 +6594,7 @@ static void tg3_timer(unsigned long __opaque)
spin_unlock(&tp->lock);
+restart_timer:
tp->timer.expires = jiffies + tp->timer_offset;
add_timer(&tp->timer);
}
@@ -6673,7 +6717,7 @@ static int tg3_test_msi(struct tg3 *tp)
tg3_full_lock(tp, 1);
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
- err = tg3_init_hw(tp);
+ err = tg3_init_hw(tp, 1);
tg3_full_unlock(tp);
@@ -6738,7 +6782,7 @@ static int tg3_open(struct net_device *dev)
tg3_full_lock(tp, 0);
- err = tg3_init_hw(tp);
+ err = tg3_init_hw(tp, 1);
if (err) {
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp);
@@ -7616,21 +7660,23 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->supported |= (SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full);
- if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
+ if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) {
cmd->supported |= (SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_MII);
- else
+ cmd->port = PORT_TP;
+ } else {
cmd->supported |= SUPPORTED_FIBRE;
+ cmd->port = PORT_FIBRE;
+ }
cmd->advertising = tp->link_config.advertising;
if (netif_running(dev)) {
cmd->speed = tp->link_config.active_speed;
cmd->duplex = tp->link_config.active_duplex;
}
- cmd->port = 0;
cmd->phy_address = PHY_ADDR;
cmd->transceiver = 0;
cmd->autoneg = tp->link_config.autoneg;
@@ -7829,7 +7875,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
if (netif_running(dev)) {
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 1);
tg3_netif_start(tp);
}
@@ -7874,7 +7920,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
if (netif_running(dev)) {
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 1);
tg3_netif_start(tp);
}
@@ -8035,9 +8081,13 @@ static int tg3_test_nvram(struct tg3 *tp)
for (i = 0; i < size; i++)
csum8 += buf8[i];
- if (csum8 == 0)
- return 0;
- return -EIO;
+ if (csum8 == 0) {
+ err = 0;
+ goto out;
+ }
+
+ err = -EIO;
+ goto out;
}
/* Bootstrap checksum at offset 0x10 */
@@ -8399,8 +8449,11 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
}
mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
- if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
+ if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ tg3_writephy(tp, MII_TG3_EXT_CTRL,
+ MII_TG3_EXT_CTRL_LNK3_LED_MODE);
+ }
tw32(MAC_MODE, mac_mode);
}
else
@@ -8410,6 +8463,9 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
tx_len = 1514;
skb = dev_alloc_skb(tx_len);
+ if (!skb)
+ return -ENOMEM;
+
tx_data = skb_put(skb, tx_len);
memcpy(tx_data, tp->dev->dev_addr, 6);
memset(tx_data + 6, 0x0, 8);
@@ -8505,7 +8561,7 @@ static int tg3_test_loopback(struct tg3 *tp)
if (!netif_running(tp->dev))
return TG3_LOOPBACK_FAILED;
- tg3_reset_hw(tp);
+ tg3_reset_hw(tp, 1);
if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
err |= TG3_MAC_LOOPBACK_FAILED;
@@ -8579,7 +8635,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
if (netif_running(dev)) {
tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 1);
tg3_netif_start(tp);
}
@@ -9022,9 +9078,6 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
{
int j;
- if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
- return;
-
tw32_f(GRC_EEPROM_ADDR,
(EEPROM_ADDR_FSM_RESET |
(EEPROM_DEFAULT_CLOCK_PERIOD <<
@@ -9157,11 +9210,6 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
{
int ret;
- if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
- printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n");
- return -EINVAL;
- }
-
if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
return tg3_nvram_read_using_eeprom(tp, offset, val);
@@ -9360,7 +9408,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
if ((page_off == 0) || (i == 0))
nvram_cmd |= NVRAM_CMD_FIRST;
- else if (page_off == (tp->nvram_pagesize - 4))
+ if (page_off == (tp->nvram_pagesize - 4))
nvram_cmd |= NVRAM_CMD_LAST;
if (i == (len - 4))
@@ -9394,11 +9442,6 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
{
int ret;
- if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
- printk(KERN_ERR PFX "Attempt to do nvram_write on Sun 570X\n");
- return -EINVAL;
- }
-
if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
~GRC_LCLCTRL_GPIO_OUTPUT1);
@@ -9525,12 +9568,19 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
tp->misc_host_ctrl);
+ /* The memory arbiter has to be enabled in order for SRAM accesses
+ * to succeed. Normally on powerup the tg3 chip firmware will make
+ * sure it is enabled, but other entities such as system netboot
+ * code might disable it.
+ */
+ val = tr32(MEMARB_MODE);
+ tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
+
tp->phy_id = PHY_ID_INVALID;
tp->led_ctrl = LED_CTRL_MODE_PHY_1;
- /* Do not even try poking around in here on Sun parts. */
- if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
- return;
+ /* Assume an onboard device by default. */
+ tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
if (val == NIC_SRAM_DATA_SIG_MAGIC) {
@@ -9628,10 +9678,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
tp->led_ctrl = LED_CTRL_MODE_PHY_2;
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
- (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP))
+ if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
+ else
+ tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
@@ -9780,16 +9830,8 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
int i;
u32 magic;
- if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
- /* Sun decided not to put the necessary bits in the
- * NVRAM of their onboard tg3 parts :(
- */
- strcpy(tp->board_part_number, "Sun 570X");
- return;
- }
-
if (tg3_nvram_read_swab(tp, 0x0, &magic))
- return;
+ goto out_not_found;
if (magic == TG3_EEPROM_MAGIC) {
for (i = 0; i < 256; i += 4) {
@@ -9820,6 +9862,9 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
break;
msleep(1);
}
+ if (!(tmp16 & 0x8000))
+ goto out_not_found;
+
pci_read_config_dword(tp->pdev, vpd_cap + PCI_VPD_DATA,
&tmp);
tmp = cpu_to_le32(tmp);
@@ -9911,37 +9956,6 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
}
}
-#ifdef CONFIG_SPARC64
-static int __devinit tg3_is_sun_570X(struct tg3 *tp)
-{
- struct pci_dev *pdev = tp->pdev;
- struct pcidev_cookie *pcp = pdev->sysdata;
-
- if (pcp != NULL) {
- int node = pcp->prom_node;
- u32 venid;
- int err;
-
- err = prom_getproperty(node, "subsystem-vendor-id",
- (char *) &venid, sizeof(venid));
- if (err == 0 || err == -1)
- return 0;
- if (venid == PCI_VENDOR_ID_SUN)
- return 1;
-
- /* TG3 chips onboard the SunBlade-2500 don't have the
- * subsystem-vendor-id set to PCI_VENDOR_ID_SUN but they
- * are distinguishable from non-Sun variants by being
- * named "network" by the firmware. Non-Sun cards will
- * show up as being named "ethernet".
- */
- if (!strcmp(pcp->prom_name, "network"))
- return 1;
- }
- return 0;
-}
-#endif
-
static int __devinit tg3_get_invariants(struct tg3 *tp)
{
static struct pci_device_id write_reorder_chipsets[] = {
@@ -9958,11 +9972,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
u16 pci_cmd;
int err;
-#ifdef CONFIG_SPARC64
- if (tg3_is_sun_570X(tp))
- tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
-#endif
-
/* Force memory write invalidate off. If we leave it on,
* then on 5700_BX chips we have to enable a workaround.
* The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
@@ -10255,6 +10264,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
}
+ if (tp->write32 == tg3_write_indirect_reg32 ||
+ ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)))
+ tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
+
/* Get eeprom hw config before calling tg3_set_power_state().
* In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
* determined before calling tg3_set_power_state() so that
@@ -10297,15 +10312,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
- /* Pseudo-header checksum is done by hardware logic and not
- * the offload processers, so make the chip do the pseudo-
- * header checksums on receive. For transmit it is more
- * convenient to do the pseudo-header checksum in software
- * as Linux does that on transmit for us in all cases.
- */
- tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM;
- tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM;
-
/* Derive initial jumbo mode from MTU assigned in
* ether_setup() via the alloc_etherdev() call
*/
@@ -10337,10 +10343,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
- if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787))
- tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
+ else
+ tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
+ }
tp->coalesce_mode = 0;
if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX &&
@@ -10531,6 +10540,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
{
struct net_device *dev = tp->dev;
u32 hi, lo, mac_offset;
+ int addr_ok = 0;
#ifdef CONFIG_SPARC64
if (!tg3_get_macaddr_sparc(tp))
@@ -10538,8 +10548,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
#endif
mac_offset = 0x7c;
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
- !(tp->tg3_flags & TG3_FLG2_SUN_570X)) ||
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
mac_offset = 0xcc;
@@ -10560,29 +10569,33 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
dev->dev_addr[3] = (lo >> 16) & 0xff;
dev->dev_addr[4] = (lo >> 8) & 0xff;
dev->dev_addr[5] = (lo >> 0) & 0xff;
- }
- /* Next, try NVRAM. */
- else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
- !tg3_nvram_read(tp, mac_offset + 0, &hi) &&
- !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
- dev->dev_addr[0] = ((hi >> 16) & 0xff);
- dev->dev_addr[1] = ((hi >> 24) & 0xff);
- dev->dev_addr[2] = ((lo >> 0) & 0xff);
- dev->dev_addr[3] = ((lo >> 8) & 0xff);
- dev->dev_addr[4] = ((lo >> 16) & 0xff);
- dev->dev_addr[5] = ((lo >> 24) & 0xff);
- }
- /* Finally just fetch it out of the MAC control regs. */
- else {
- hi = tr32(MAC_ADDR_0_HIGH);
- lo = tr32(MAC_ADDR_0_LOW);
- dev->dev_addr[5] = lo & 0xff;
- dev->dev_addr[4] = (lo >> 8) & 0xff;
- dev->dev_addr[3] = (lo >> 16) & 0xff;
- dev->dev_addr[2] = (lo >> 24) & 0xff;
- dev->dev_addr[1] = hi & 0xff;
- dev->dev_addr[0] = (hi >> 8) & 0xff;
+ /* Some old bootcode may report a 0 MAC address in SRAM */
+ addr_ok = is_valid_ether_addr(&dev->dev_addr[0]);
+ }
+ if (!addr_ok) {
+ /* Next, try NVRAM. */
+ if (!tg3_nvram_read(tp, mac_offset + 0, &hi) &&
+ !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
+ dev->dev_addr[0] = ((hi >> 16) & 0xff);
+ dev->dev_addr[1] = ((hi >> 24) & 0xff);
+ dev->dev_addr[2] = ((lo >> 0) & 0xff);
+ dev->dev_addr[3] = ((lo >> 8) & 0xff);
+ dev->dev_addr[4] = ((lo >> 16) & 0xff);
+ dev->dev_addr[5] = ((lo >> 24) & 0xff);
+ }
+ /* Finally just fetch it out of the MAC control regs. */
+ else {
+ hi = tr32(MAC_ADDR_0_HIGH);
+ lo = tr32(MAC_ADDR_0_LOW);
+
+ dev->dev_addr[5] = lo & 0xff;
+ dev->dev_addr[4] = (lo >> 8) & 0xff;
+ dev->dev_addr[3] = (lo >> 16) & 0xff;
+ dev->dev_addr[2] = (lo >> 24) & 0xff;
+ dev->dev_addr[1] = hi & 0xff;
+ dev->dev_addr[0] = (hi >> 8) & 0xff;
+ }
}
if (!is_valid_ether_addr(&dev->dev_addr[0])) {
@@ -11547,7 +11560,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
tg3_full_lock(tp, 0);
tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 1);
tp->timer.expires = jiffies + tp->timer_offset;
add_timer(&tp->timer);
@@ -11581,7 +11594,7 @@ static int tg3_resume(struct pci_dev *pdev)
tg3_full_lock(tp, 0);
tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 1);
tp->timer.expires = jiffies + tp->timer_offset;
add_timer(&tp->timer);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index c43cc326420..ff0faab94bd 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2171,8 +2171,7 @@ struct tg3 {
#define TG3_FLAG_PCIX_MODE 0x00020000
#define TG3_FLAG_PCI_HIGH_SPEED 0x00040000
#define TG3_FLAG_PCI_32BIT 0x00080000
-#define TG3_FLAG_NO_TX_PSEUDO_CSUM 0x00100000
-#define TG3_FLAG_NO_RX_PSEUDO_CSUM 0x00200000
+#define TG3_FLAG_SRAM_USE_CONFIG 0x00100000
#define TG3_FLAG_SERDES_WOL_CAP 0x00400000
#define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000
#define TG3_FLAG_10_100_ONLY 0x01000000
@@ -2185,7 +2184,7 @@ struct tg3 {
#define TG3_FLAG_INIT_COMPLETE 0x80000000
u32 tg3_flags2;
#define TG3_FLG2_RESTART_TIMER 0x00000001
-#define TG3_FLG2_SUN_570X 0x00000002
+/* 0x00000002 available */
#define TG3_FLG2_NO_ETH_WIRE_SPEED 0x00000004
#define TG3_FLG2_IS_5788 0x00000008
#define TG3_FLG2_MAX_RXPEND_64 0x00000010
@@ -2216,6 +2215,8 @@ struct tg3 {
#define TG3_FLG2_HW_TSO_2 0x08000000
#define TG3_FLG2_HW_TSO (TG3_FLG2_HW_TSO_1 | TG3_FLG2_HW_TSO_2)
#define TG3_FLG2_1SHOT_MSI 0x10000000
+#define TG3_FLG2_PHY_JITTER_BUG 0x20000000
+#define TG3_FLG2_NO_FWARE_REPORTED 0x40000000
u32 split_mode_max_reqs;
#define SPLIT_MODE_5704_MAX_REQ 3
diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig
index e4cfc80b283..99c4c1922f1 100644
--- a/drivers/net/tokenring/Kconfig
+++ b/drivers/net/tokenring/Kconfig
@@ -3,7 +3,7 @@
#
menu "Token Ring devices"
- depends on NETDEVICES
+ depends on NETDEVICES && !UML
# So far, we only have PCI, ISA, and MCA token ring devices
config TR
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
index 9345e68c451..649d8ea354f 100644
--- a/drivers/net/tokenring/abyss.c
+++ b/drivers/net/tokenring/abyss.c
@@ -438,8 +438,7 @@ static void __devexit abyss_detach (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- if (!dev)
- BUG();
+ BUG_ON(!dev);
unregister_netdev(dev);
release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT);
free_irq(dev->irq, dev);
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index 3a25d191ea4..19e6f4dfd69 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -735,8 +735,7 @@ static int __devexit madgemc_remove(struct device *device)
struct net_local *tp;
struct card_info *card;
- if (!dev)
- BUG();
+ BUG_ON(!dev);
tp = dev->priv;
card = tp->tmspriv;
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index ee48bfd6734..f5609410204 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -513,7 +513,7 @@ struct mii_phy {
u_char *rst; /* Start of reset sequence in SROM */
u_int mc; /* Media Capabilities */
u_int ana; /* NWay Advertisement */
- u_int fdx; /* Full DupleX capabilites for each media */
+ u_int fdx; /* Full DupleX capabilities for each media */
u_int ttm; /* Transmit Threshold Mode for each media */
u_int mci; /* 21142 MII Connector Interrupt info */
};
@@ -4160,7 +4160,7 @@ get_hw_addr(struct net_device *dev)
** If the address starts with 00 a0, we have to bit-reverse
** each byte of the address.
*/
- if ( (_machine & _MACH_Pmac) &&
+ if ( machine_is(powermac) &&
(dev->dev_addr[0] == 0) &&
(dev->dev_addr[1] == 0xa0) )
{
diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c
index 55f4a9a631b..ab985023fcc 100644
--- a/drivers/net/tulip/pnic2.c
+++ b/drivers/net/tulip/pnic2.c
@@ -199,7 +199,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5)
/* negotiation ended successfully */
/* get the link partners reply and mask out all but
- * bits 24-21 which show the partners capabilites
+ * bits 24-21 which show the partners capabilities
* and match those to what we advertised
*
* then begin to interpret the results of the negotiation.
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index ba05dedf29d..136a70c4d5e 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -850,7 +850,7 @@ static void init_rxtx_rings(struct net_device *dev)
break;
skb->dev = dev; /* Mark as being used by this device. */
np->rx_addr[i] = pci_map_single(np->pci_dev,skb->data,
- skb->len,PCI_DMA_FROMDEVICE);
+ np->rx_buf_sz,PCI_DMA_FROMDEVICE);
np->rx_ring[i].buffer1 = np->rx_addr[i];
np->rx_ring[i].status = DescOwn;
@@ -1316,7 +1316,7 @@ static int netdev_rx(struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
np->rx_addr[entry] = pci_map_single(np->pci_dev,
skb->data,
- skb->len, PCI_DMA_FROMDEVICE);
+ np->rx_buf_sz, PCI_DMA_FROMDEVICE);
np->rx_ring[entry].buffer1 = np->rx_addr[entry];
}
wmb();
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index cde35dd8790..d9258d42090 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -134,7 +134,7 @@ static const int multicast_filter_limit = 32;
#include "typhoon.h"
#include "typhoon-firmware.h"
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
"typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
@@ -208,7 +208,7 @@ static const struct typhoon_card_info typhoon_card_info[] __devinitdata = {
};
/* Notes on the new subsystem numbering scheme:
- * bits 0-1 indicate crypto capabilites: (0) variable, (1) DES, or (2) 3DES
+ * bits 0-1 indicate crypto capabilities: (0) variable, (1) DES, or (2) 3DES
* bit 4 indicates if this card has secured firmware (we don't support it)
* bit 8 indicates if this is a (0) copper or (1) fiber card
* bits 12-16 indicate card type: (0) client and (1) server
@@ -788,7 +788,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
/* we have two rings to choose from, but we only use txLo for now
* If we start using the Hi ring as well, we'll need to update
* typhoon_stop_runtime(), typhoon_interrupt(), typhoon_num_free_tx(),
- * and TXHI_ENTIRES to match, as well as update the TSO code below
+ * and TXHI_ENTRIES to match, as well as update the TSO code below
* to get the right DMA address
*/
txRing = &tp->txLoRing;
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 24187158928..fdc21037f6d 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -129,6 +129,7 @@
- Massive clean-up
- Rewrite PHY, media handling (remove options, full_duplex, backoff)
- Fix Tx engine race for good
+ - Craig Brind: Zero padded aligned buffers for short packets.
*/
@@ -469,7 +470,7 @@ struct rhine_private {
struct sk_buff *tx_skbuff[TX_RING_SIZE];
dma_addr_t tx_skbuff_dma[TX_RING_SIZE];
- /* Tx bounce buffers */
+ /* Tx bounce buffers (Rhine-I only) */
unsigned char *tx_buf[TX_RING_SIZE];
unsigned char *tx_bufs;
dma_addr_t tx_bufs_dma;
@@ -490,8 +491,6 @@ struct rhine_private {
u8 tx_thresh, rx_thresh;
struct mii_if_info mii_if;
- struct work_struct tx_timeout_task;
- struct work_struct check_media_task;
void __iomem *base;
};
@@ -499,8 +498,6 @@ static int mdio_read(struct net_device *dev, int phy_id, int location);
static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
static int rhine_open(struct net_device *dev);
static void rhine_tx_timeout(struct net_device *dev);
-static void rhine_tx_timeout_task(struct net_device *dev);
-static void rhine_check_media_task(struct net_device *dev);
static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
static void rhine_tx(struct net_device *dev);
@@ -855,12 +852,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
if (rp->quirks & rqRhineI)
dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
- INIT_WORK(&rp->tx_timeout_task,
- (void (*)(void *))rhine_tx_timeout_task, dev);
-
- INIT_WORK(&rp->check_media_task,
- (void (*)(void *))rhine_check_media_task, dev);
-
/* dev->name not defined before register_netdev()! */
rc = register_netdev(dev);
if (rc)
@@ -1043,7 +1034,8 @@ static void alloc_tbufs(struct net_device* dev)
rp->tx_ring[i].desc_length = cpu_to_le32(TXDESC);
next += sizeof(struct tx_desc);
rp->tx_ring[i].next_desc = cpu_to_le32(next);
- rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ];
+ if (rp->quirks & rqRhineI)
+ rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ];
}
rp->tx_ring[i-1].next_desc = cpu_to_le32(rp->tx_ring_dma);
@@ -1085,11 +1077,25 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media)
else
iowrite8(ioread8(ioaddr + ChipCmd1) & ~Cmd1FDuplex,
ioaddr + ChipCmd1);
+ if (debug > 1)
+ printk(KERN_INFO "%s: force_media %d, carrier %d\n", dev->name,
+ rp->mii_if.force_media, netif_carrier_ok(dev));
}
-static void rhine_check_media_task(struct net_device *dev)
+/* Called after status of force_media possibly changed */
+static void rhine_set_carrier(struct mii_if_info *mii)
{
- rhine_check_media(dev, 0);
+ if (mii->force_media) {
+ /* autoneg is off: Link is always assumed to be up */
+ if (!netif_carrier_ok(mii->dev))
+ netif_carrier_on(mii->dev);
+ }
+ else /* Let MMI library update carrier status */
+ rhine_check_media(mii->dev, 0);
+ if (debug > 1)
+ printk(KERN_INFO "%s: force_media %d, carrier %d\n",
+ mii->dev->name, mii->force_media,
+ netif_carrier_ok(mii->dev));
}
static void init_registers(struct net_device *dev)
@@ -1145,8 +1151,8 @@ static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks)
if (quirks & rqRhineI) {
iowrite8(0x01, ioaddr + MIIRegAddr); // MII_BMSR
- /* Do not call from ISR! */
- msleep(1);
+ /* Can be called from ISR. Evil. */
+ mdelay(1);
/* 0x80 must be set immediately before turning it off */
iowrite8(0x80, ioaddr + MIICmd);
@@ -1236,16 +1242,6 @@ static int rhine_open(struct net_device *dev)
static void rhine_tx_timeout(struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
-
- /*
- * Move bulk of work outside of interrupt context
- */
- schedule_work(&rp->tx_timeout_task);
-}
-
-static void rhine_tx_timeout_task(struct net_device *dev)
-{
- struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
@@ -1306,7 +1302,12 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
rp->stats.tx_dropped++;
return 0;
}
+
+ /* Padding is not copied and so must be redone. */
skb_copy_and_csum_dev(skb, rp->tx_buf[entry]);
+ if (skb->len < ETH_ZLEN)
+ memset(rp->tx_buf[entry] + skb->len, 0,
+ ETH_ZLEN - skb->len);
rp->tx_skbuff_dma[entry] = 0;
rp->tx_ring[entry].addr = cpu_to_le32(rp->tx_bufs_dma +
(rp->tx_buf[entry] -
@@ -1651,7 +1652,7 @@ static void rhine_error(struct net_device *dev, int intr_status)
spin_lock(&rp->lock);
if (intr_status & IntrLinkChange)
- schedule_work(&rp->check_media_task);
+ rhine_check_media(dev, 0);
if (intr_status & IntrStatsMax) {
rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
@@ -1782,6 +1783,7 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
spin_lock_irq(&rp->lock);
rc = mii_ethtool_sset(&rp->mii_if, cmd);
spin_unlock_irq(&rp->lock);
+ rhine_set_carrier(&rp->mii_if);
return rc;
}
@@ -1869,6 +1871,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
spin_lock_irq(&rp->lock);
rc = generic_mii_ioctl(&rp->mii_if, if_mii(rq), cmd, NULL);
spin_unlock_irq(&rp->lock);
+ rhine_set_carrier(&rp->mii_if);
return rc;
}
@@ -1899,9 +1902,6 @@ static int rhine_close(struct net_device *dev)
spin_unlock_irq(&rp->lock);
free_irq(rp->pdev->irq, dev);
-
- flush_scheduled_work();
-
free_rbufs(dev);
free_tbufs(dev);
free_ring(dev);
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 883cf7da10f..b5328b0ff92 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -410,103 +410,6 @@ config WAN_ROUTER_DRIVERS
If unsure, say N.
-config VENDOR_SANGOMA
- tristate "Sangoma WANPIPE(tm) multiprotocol cards"
- depends on WAN_ROUTER_DRIVERS && WAN_ROUTER && (PCI || ISA) && BROKEN
- ---help---
- Driver for S514-PCI/ISA Synchronous Data Link Adapters (SDLA).
-
- WANPIPE from Sangoma Technologies Inc. <http://www.sangoma.com/>
- is a family of intelligent multiprotocol WAN adapters with data
- transfer rates up to 4Mbps. Cards support:
-
- - X.25, Frame Relay, PPP, Cisco HDLC protocols.
-
- - API for protocols like HDLC (LAPB), HDLC Streaming, X.25,
- Frame Relay and BiSync.
-
- - Ethernet Bridging over Frame Relay protocol.
-
- - MULTILINK PPP
-
- - Async PPP (Modem Dialup)
-
- The next questions will ask you about the protocols you want
- the driver to support.
-
- If you have one or more of these cards, say M to this option;
- and read <file:Documentation/networking/wan-router.txt>.
-
- To compile this driver as a module, choose M here: the
- module will be called wanpipe.
-
-config WANPIPE_CHDLC
- bool "WANPIPE Cisco HDLC support"
- depends on VENDOR_SANGOMA
- ---help---
- Connect a WANPIPE card to a leased line using the Cisco HDLC.
-
- - Supports Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards
- which allows user to build applications using the HDLC streaming API.
-
- - CHDLC Streaming MULTILINK PPP that can bind multiple WANPIPE T1
- cards into a single logical channel.
-
- Say Y and the Cisco HDLC support, HDLC streaming API and
- MULTILINK PPP will be included in the driver.
-
-config WANPIPE_FR
- bool "WANPIPE Frame Relay support"
- depends on VENDOR_SANGOMA
- help
- Connect a WANPIPE card to a Frame Relay network, or use Frame Relay
- API to develop custom applications.
-
- Contains the Ethernet Bridging over Frame Relay feature, where
- a WANPIPE frame relay link can be directly connected to the Linux
- kernel bridge. The Frame Relay option is supported on S514-PCI
- and S508-ISA cards.
-
- Say Y and the Frame Relay support will be included in the driver.
-
-config WANPIPE_X25
- bool "WANPIPE X.25 support"
- depends on VENDOR_SANGOMA
- help
- Connect a WANPIPE card to an X.25 network.
-
- Includes the X.25 API support for custom applications over the
- X.25 protocol. The X.25 option is supported on S514-PCI and
- S508-ISA cards.
-
- Say Y and the X.25 support will be included in the driver.
-
-config WANPIPE_PPP
- bool "WANPIPE PPP support"
- depends on VENDOR_SANGOMA
- help
- Connect a WANPIPE card to a leased line using Point-to-Point
- Protocol (PPP).
-
- The PPP option is supported on S514-PCI/S508-ISA cards.
-
- Say Y and the PPP support will be included in the driver.
-
-config WANPIPE_MULTPPP
- bool "WANPIPE Multi-Port PPP support"
- depends on VENDOR_SANGOMA
- help
- Connect a WANPIPE card to a leased line using Point-to-Point
- Protocol (PPP).
-
- Uses in-kernel SyncPPP protocol over the Sangoma HDLC Streaming
- adapter. In this case each Sangoma adapter port can support an
- independent PPP connection. For example, a single Quad-Port PCI
- adapter can support up to four independent PPP links. The PPP
- option is supported on S514-PCI/S508-ISA cards.
-
- Say Y and the Multi-Port PPP support will be included in the driver.
-
config CYCLADES_SYNC
tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)"
depends on WAN_ROUTER_DRIVERS && (PCI || ISA)
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index ce6c56b903e..823c6d5ab90 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -5,14 +5,6 @@
# Rewritten to use lists instead of if-statements.
#
-wanpipe-y := sdlamain.o sdla_ft1.o
-wanpipe-$(CONFIG_WANPIPE_X25) += sdla_x25.o
-wanpipe-$(CONFIG_WANPIPE_FR) += sdla_fr.o
-wanpipe-$(CONFIG_WANPIPE_CHDLC) += sdla_chdlc.o
-wanpipe-$(CONFIG_WANPIPE_PPP) += sdla_ppp.o
-wanpipe-$(CONFIG_WANPIPE_MULTPPP) += wanpipe_multppp.o
-wanpipe-objs := $(wanpipe-y)
-
cyclomx-y := cycx_main.o
cyclomx-$(CONFIG_CYCLOMX_X25) += cycx_x25.o
cyclomx-objs := $(cyclomx-y)
@@ -43,11 +35,6 @@ obj-$(CONFIG_LANMEDIA) += lmc/
obj-$(CONFIG_DLCI) += dlci.o
obj-$(CONFIG_SDLA) += sdla.o
-ifeq ($(CONFIG_WANPIPE_MULTPPP),y)
- obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o syncppp.o
-else
- obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o
-endif
obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o
obj-$(CONFIG_LAPBETHER) += lapbether.o
obj-$(CONFIG_SBNI) += sbni.o
diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
deleted file mode 100644
index 496d29237e9..00000000000
--- a/drivers/net/wan/sdla_chdlc.c
+++ /dev/null
@@ -1,4428 +0,0 @@
-/*****************************************************************************
-* sdla_chdlc.c WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module.
-*
-* Authors: Nenad Corbic <ncorbic@sangoma.com>
-* Gideon Hack
-*
-* Copyright: (c) 1995-2001 Sangoma Technologies 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.
-* ============================================================================
-* Feb 28, 2001 Nenad Corbic Updated if_tx_timeout() routine for
-* 2.4.X kernels.
-* Jan 25, 2001 Nenad Corbic Added a TTY Sync serial driver over the
-* HDLC streaming protocol
-* Added a TTY Async serial driver over the
-* Async protocol.
-* Dec 15, 2000 Nenad Corbic Updated for 2.4.X Kernel support
-* Nov 13, 2000 Nenad Corbic Added true interface type encoding option.
-* Tcpdump doesn't support CHDLC inteface
-* types, to fix this "true type" option will set
-* the interface type to RAW IP mode.
-* Nov 07, 2000 Nenad Corbic Added security features for UDP debugging:
-* Deny all and specify allowed requests.
-* Jun 20, 2000 Nenad Corbic Fixed the API IP ERROR bug. Caused by the
-* latest update.
-* May 09, 2000 Nenad Corbic Option to bring down an interface
-* upon disconnect.
-* Mar 23, 2000 Nenad Corbic Improved task queue, bh handling.
-* Mar 16, 2000 Nenad Corbic Fixed the SLARP Dynamic IP addressing.
-* Mar 06, 2000 Nenad Corbic Bug Fix: corrupted mbox recovery.
-* Feb 10, 2000 Gideon Hack Added ASYNC support.
-* Feb 09, 2000 Nenad Corbic Fixed two shutdown bugs in update() and
-* if_stats() functions.
-* Jan 24, 2000 Nenad Corbic Fixed a startup wanpipe state racing,
-* condition between if_open and isr.
-* Jan 10, 2000 Nenad Corbic Added new socket API support.
-* Dev 15, 1999 Nenad Corbic Fixed up header files for 2.0.X kernels
-* Nov 20, 1999 Nenad Corbic Fixed zero length API bug.
-* Sep 30, 1999 Nenad Corbic Fixed dynamic IP and route setup.
-* Sep 23, 1999 Nenad Corbic Added SMP support, fixed tracing
-* Sep 13, 1999 Nenad Corbic Split up Port 0 and 1 into separate devices.
-* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
-* Oct 30, 1998 Jaspreet Singh Added Support for CHDLC API (HDLC STREAMING).
-* Oct 28, 1998 Jaspreet Singh Added Support for Dual Port CHDLC.
-* Aug 07, 1998 David Fong Initial version.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/if_arp.h> /* ARPHRD_* defines */
-
-
-#include <asm/uaccess.h>
-#include <linux/inetdevice.h>
-#include <linux/netdevice.h>
-
-#include <linux/in.h> /* sockaddr_in */
-#include <linux/inet.h>
-#include <linux/if.h>
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <linux/sdlapci.h>
-#include <asm/io.h>
-
-#include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */
-#include <linux/sdla_asy.h> /* CHDLC (async) API definitions */
-
-#include <linux/if_wanpipe_common.h> /* Socket Driver common area */
-#include <linux/if_wanpipe.h>
-
-/* TTY Includes */
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-
-
-/****** Defines & Macros ****************************************************/
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP 0x01
-#define TMR_INT_ENABLED_UPDATE 0x02
-#define TMR_INT_ENABLED_CONFIG 0x10
-
-#define MAX_IP_ERRORS 10
-
-#define TTY_CHDLC_MAX_MTU 2000
-#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */
-#define CHDLC_HDR_LEN 1
-
-#define CHDLC_API 0x01
-
-#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
-#define MAX_BH_BUFF 10
-
-//#define PRINT_DEBUG
-#ifdef PRINT_DEBUG
-#define dbg_printk(format, a...) printk(format, ## a)
-#else
-#define dbg_printk(format, a...)
-#endif
-
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following
- * structure will incorporate the card structure along with CHDLC specific data
- */
-
-typedef struct chdlc_private_area
-{
- wanpipe_common_t common;
- sdla_t *card;
- int TracingEnabled; /* For enabling Tracing */
- unsigned long curr_trace_addr; /* Used for Tracing */
- unsigned long start_trace_addr;
- unsigned long end_trace_addr;
- unsigned long base_addr_trace_buffer;
- unsigned long end_addr_trace_buffer;
- unsigned short number_trace_elements;
- unsigned available_buffer_space;
- unsigned long router_start_time;
- unsigned char route_status;
- unsigned char route_removed;
- unsigned long tick_counter; /* For 5s timeout counter */
- unsigned long router_up_time;
- u32 IP_address; /* IP addressing */
- u32 IP_netmask;
- u32 ip_local;
- u32 ip_remote;
- u32 ip_local_tmp;
- u32 ip_remote_tmp;
- u8 ip_error;
- u8 config_chdlc;
- u8 config_chdlc_timeout;
- unsigned char mc; /* Mulitcast support on/off */
- unsigned short udp_pkt_lgth; /* udp packet processing */
- char udp_pkt_src;
- char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
- unsigned short timer_int_enabled;
- char update_comms_stats; /* updating comms stats */
-
- bh_data_t *bh_head; /* Circular buffer for chdlc_bh */
- unsigned long tq_working;
- volatile int bh_write;
- volatile int bh_read;
- atomic_t bh_buff_used;
-
- unsigned char interface_down;
-
- /* Polling work queue entry. Each interface
- * has its own work queue entry, which is used
- * to defer events from the interrupt */
- struct work_struct poll_work;
- struct timer_list poll_delay_timer;
-
- u8 gateway;
- u8 true_if_encoding;
- //FIXME: add driver stats as per frame relay!
-
-} chdlc_private_area_t;
-
-/* Route Status options */
-#define NO_ROUTE 0x00
-#define ADD_ROUTE 0x01
-#define ROUTE_ADDED 0x02
-#define REMOVE_ROUTE 0x03
-
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-/* variable for tracking how many interfaces to open for WANPIPE on the
- two ports */
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/****** Function Prototypes *************************************************/
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device* wandev);
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf);
-
-/* Network device interface */
-static int if_init(struct net_device* dev);
-static int if_open(struct net_device* dev);
-static int if_close(struct net_device* dev);
-static int if_header(struct sk_buff* skb, struct net_device* dev,
- unsigned short type, void* daddr, void* saddr,
- unsigned len);
-
-static int if_rebuild_hdr (struct sk_buff *skb);
-static struct net_device_stats* if_stats(struct net_device* dev);
-
-static int if_send(struct sk_buff* skb, struct net_device* dev);
-
-/* CHDLC Firmware interface functions */
-static int chdlc_configure (sdla_t* card, void* data);
-static int chdlc_comm_enable (sdla_t* card);
-static int chdlc_read_version (sdla_t* card, char* str);
-static int chdlc_set_intr_mode (sdla_t* card, unsigned mode);
-static int chdlc_send (sdla_t* card, void* data, unsigned len);
-static int chdlc_read_comm_err_stats (sdla_t* card);
-static int chdlc_read_op_stats (sdla_t* card);
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
-
-
-static int chdlc_disable_comm_shutdown (sdla_t *card);
-static void if_tx_timeout(struct net_device *dev);
-
-/* Miscellaneous CHDLC Functions */
-static int set_chdlc_config (sdla_t* card);
-static void init_chdlc_tx_rx_buff( sdla_t* card);
-static int process_chdlc_exception(sdla_t *card);
-static int process_global_exception(sdla_t *card);
-static int update_comms_stats(sdla_t* card,
- chdlc_private_area_t* chdlc_priv_area);
-static int configure_ip (sdla_t* card);
-static int unconfigure_ip (sdla_t* card);
-static void process_route(sdla_t *card);
-static void port_set_state (sdla_t *card, int);
-static int config_chdlc (sdla_t *card);
-static void disable_comm (sdla_t *card);
-
-static void trigger_chdlc_poll(struct net_device *dev);
-static void chdlc_poll(struct net_device *dev);
-static void chdlc_poll_delay (unsigned long dev_ptr);
-
-
-/* Miscellaneous asynchronous interface Functions */
-static int set_asy_config (sdla_t* card);
-static int asy_comm_enable (sdla_t* card);
-
-/* Interrupt handlers */
-static void wpc_isr (sdla_t* card);
-static void rx_intr (sdla_t* card);
-static void timer_intr(sdla_t *);
-
-/* Bottom half handlers */
-static void chdlc_work(struct net_device *dev);
-static int chdlc_work_cleanup(struct net_device *dev);
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb);
-
-/* Miscellaneous functions */
-static int chk_bcast_mcast_addr(sdla_t* card, struct net_device* dev,
- struct sk_buff *skb);
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-static int intr_test( sdla_t* card);
-static int udp_pkt_type( struct sk_buff *skb , sdla_t* card);
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area);
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area);
-static unsigned short calc_checksum (char *, int);
-static void s508_lock (sdla_t *card, unsigned long *smp_flags);
-static void s508_unlock (sdla_t *card, unsigned long *smp_flags);
-
-
-static int Intr_test_counter;
-
-/* TTY Global Definitions */
-
-#define NR_PORTS 4
-#define WAN_TTY_MAJOR 226
-#define WAN_TTY_MINOR 0
-
-#define WAN_CARD(port) (tty_card_map[port])
-#define MIN_PORT 0
-#define MAX_PORT NR_PORTS-1
-
-#define CRC_LENGTH 2
-
-static int wanpipe_tty_init(sdla_t *card);
-static void wanpipe_tty_receive(sdla_t *, unsigned, unsigned int);
-static void wanpipe_tty_trigger_poll(sdla_t *card);
-
-static struct tty_driver serial_driver;
-static int tty_init_cnt=0;
-
-static struct serial_state rs_table[NR_PORTS];
-
-static char tty_driver_mode=WANOPT_TTY_SYNC;
-
-static char *opt_decode[] = {"NONE","CRTSCTS","XONXOFF-RX",
- "CRTSCTS XONXOFF-RX","XONXOFF-TX",
- "CRTSCTS XONXOFF-TX","CRTSCTS XONXOFF"};
-static char *p_decode[] = {"NONE","ODD","EVEN"};
-
-static void* tty_card_map[NR_PORTS] = {NULL,NULL,NULL,NULL};
-
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Cisco HDLC protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup. At this
- * point adapter is completely initialized and firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the adapter data space.
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-int wpc_init (sdla_t* card, wandev_conf_t* conf)
-{
- unsigned char port_num;
- int err;
- unsigned long max_permitted_baud = 0;
- SHARED_MEMORY_INFO_STRUCT *flags;
-
- union
- {
- char str[80];
- } u;
- volatile CHDLC_MAILBOX_STRUCT* mb;
- CHDLC_MAILBOX_STRUCT* mb1;
- unsigned long timeout;
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_CHDLC) {
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
- return -EINVAL;
- }
-
- /* Find out which Port to use */
- if ((conf->comm_port == WANOPT_PRI) || (conf->comm_port == WANOPT_SEC)){
- if (card->next){
-
- if (conf->comm_port != card->next->u.c.comm_port){
- card->u.c.comm_port = conf->comm_port;
- }else{
- printk(KERN_INFO "%s: ERROR - %s port used!\n",
- card->wandev.name, PORT(conf->comm_port));
- return -EINVAL;
- }
- }else{
- card->u.c.comm_port = conf->comm_port;
- }
- }else{
- printk(KERN_INFO "%s: ERROR - Invalid Port Selected!\n",
- card->wandev.name);
- return -EINVAL;
- }
-
-
- /* Initialize protocol-specific fields */
- if(card->hw.type != SDLA_S514){
-
- if (card->u.c.comm_port == WANOPT_PRI){
- card->mbox = (void *) card->hw.dpmbase;
- }else{
- card->mbox = (void *) card->hw.dpmbase +
- SEC_BASE_ADDR_MB_STRUCT - PRI_BASE_ADDR_MB_STRUCT;
- }
- }else{
- /* for a S514 adapter, set a pointer to the actual mailbox in the */
- /* allocated virtual memory area */
- if (card->u.c.comm_port == WANOPT_PRI){
- card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
- }else{
- card->mbox = (void *) card->hw.dpmbase + SEC_BASE_ADDR_MB_STRUCT;
- }
- }
-
- mb = mb1 = card->mbox;
-
- if (!card->configured){
-
- /* The board will place an 'I' in the return code to indicate that it is
- ready to accept commands. We expect this to be completed in less
- than 1 second. */
-
- timeout = jiffies;
- while (mb->return_code != 'I') /* Wait 1s for board to initialize */
- if ((jiffies - timeout) > 1*HZ) break;
-
- if (mb->return_code != 'I') {
- printk(KERN_INFO
- "%s: Initialization not completed by adapter\n",
- card->devname);
- printk(KERN_INFO "Please contact Sangoma representative.\n");
- return -EIO;
- }
- }
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
-
- if (chdlc_read_version(card, u.str))
- return -EIO;
-
- printk(KERN_INFO "%s: Running Cisco HDLC firmware v%s\n",
- card->devname, u.str);
-
- card->isr = &wpc_isr;
- card->poll = NULL;
- card->exec = NULL;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = NULL;
- card->wandev.udp_port = conf->udp_port;
- card->disable_comm = &disable_comm;
- card->wandev.new_if_cnt = 0;
-
- /* reset the number of times the 'update()' proc has been called */
- card->u.c.update_call_count = 0;
-
- card->wandev.ttl = conf->ttl;
- card->wandev.interface = conf->interface;
-
- if ((card->u.c.comm_port == WANOPT_SEC && conf->interface == WANOPT_V35)&&
- card->hw.type != SDLA_S514){
- printk(KERN_INFO "%s: ERROR - V35 Interface not supported on S508 %s port \n",
- card->devname, PORT(card->u.c.comm_port));
- return -EIO;
- }
-
- card->wandev.clocking = conf->clocking;
-
- port_num = card->u.c.comm_port;
-
- /* in API mode, we can configure for "receive only" buffering */
- if(card->hw.type == SDLA_S514) {
- card->u.c.receive_only = conf->receive_only;
- if(conf->receive_only) {
- printk(KERN_INFO
- "%s: Configured for 'receive only' mode\n",
- card->devname);
- }
- }
-
- /* Setup Port Bps */
-
- if(card->wandev.clocking) {
- if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
- /* For Primary Port 0 */
- max_permitted_baud =
- (card->hw.type == SDLA_S514) ?
- PRI_MAX_BAUD_RATE_S514 :
- PRI_MAX_BAUD_RATE_S508;
-
- }else if(port_num == WANOPT_SEC) {
- /* For Secondary Port 1 */
- max_permitted_baud =
- (card->hw.type == SDLA_S514) ?
- SEC_MAX_BAUD_RATE_S514 :
- SEC_MAX_BAUD_RATE_S508;
- }
-
- if(conf->bps > max_permitted_baud) {
- conf->bps = max_permitted_baud;
- printk(KERN_INFO "%s: Baud too high!\n",
- card->wandev.name);
- printk(KERN_INFO "%s: Baud rate set to %lu bps\n",
- card->wandev.name, max_permitted_baud);
- }
- card->wandev.bps = conf->bps;
- }else{
- card->wandev.bps = 0;
- }
-
- /* Setup the Port MTU */
- if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
-
- /* For Primary Port 0 */
- card->wandev.mtu =
- (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
- min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) :
- CHDLC_DFLT_DATA_LEN;
- } else if(port_num == WANOPT_SEC) {
- /* For Secondary Port 1 */
- card->wandev.mtu =
- (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
- min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) :
- CHDLC_DFLT_DATA_LEN;
- }
-
- /* Set up the interrupt status area */
- /* Read the CHDLC Configuration and obtain:
- * Ptr to shared memory infor struct
- * Use this pointer to calculate the value of card->u.c.flags !
- */
- mb1->buffer_length = 0;
- mb1->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
- if(err != COMMAND_OK) {
- if(card->hw.type != SDLA_S514)
- enable_irq(card->hw.irq);
-
- chdlc_error(card, err, mb1);
- return -EIO;
- }
-
- if(card->hw.type == SDLA_S514){
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct));
- }else{
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
- }
-
- flags = card->u.c.flags;
-
- /* This is for the ports link state */
- card->wandev.state = WAN_DUALPORT;
- card->u.c.state = WAN_DISCONNECTED;
-
-
- if (!card->wandev.piggyback){
- int err;
-
- /* Perform interrupt testing */
- err = intr_test(card);
-
- if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) {
- printk(KERN_INFO "%s: Interrupt test failed (%i)\n",
- card->devname, Intr_test_counter);
- printk(KERN_INFO "%s: Please choose another interrupt\n",
- card->devname);
- return -EIO;
- }
-
- printk(KERN_INFO "%s: Interrupt test passed (%i)\n",
- card->devname, Intr_test_counter);
- card->configured = 1;
- }
-
- if ((card->tty_opt=conf->tty) == WANOPT_YES){
- int err;
- card->tty_minor = conf->tty_minor;
-
- /* On ASYNC connections internal clocking
- * is mandatory */
- if ((card->u.c.async_mode = conf->tty_mode)){
- card->wandev.clocking = 1;
- }
- err=wanpipe_tty_init(card);
- if (err){
- return err;
- }
- }else{
-
-
- if (chdlc_set_intr_mode(card, APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: "
- "Failed to set interrupt triggers!\n",
- card->devname);
- return -EIO;
- }
-
- /* Mask the Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TIMER;
- }
-
- /* If we are using CHDLC in backup mode, this flag will
- * indicate not to look for IP addresses in config_chdlc()*/
- card->u.c.backup = conf->backup;
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics
- * This procedure is called when updating the PROC file system and returns
- * various communications statistics. These statistics are accumulated from 3
- * different locations:
- * 1) The 'if_stats' recorded for the device.
- * 2) Communication error statistics on the adapter.
- * 3) CHDLC operational statistics on the adapter.
- * The board level statistics are read during a timer interrupt. Note that we
- * read the error and operational statistics during consecitive timer ticks so
- * as to minimize the time that we are inside the interrupt handler.
- *
- */
-static int update(struct wan_device* wandev)
-{
- sdla_t* card = wandev->private;
- struct net_device* dev;
- volatile chdlc_private_area_t* chdlc_priv_area;
- SHARED_MEMORY_INFO_STRUCT *flags;
- unsigned long timeout;
-
- /* sanity checks */
- if((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
-
- if(wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- /* more sanity checks */
- if(!card->u.c.flags)
- return -ENODEV;
-
- if(test_bit(PERI_CRIT, (void*)&card->wandev.critical))
- return -EAGAIN;
-
- if((dev=card->wandev.dev) == NULL)
- return -ENODEV;
-
- if((chdlc_priv_area=dev->priv) == NULL)
- return -ENODEV;
-
- flags = card->u.c.flags;
- if(chdlc_priv_area->update_comms_stats){
- return -EAGAIN;
- }
-
- /* we will need 2 timer interrupts to complete the */
- /* reading of the statistics */
- chdlc_priv_area->update_comms_stats = 2;
- flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
- chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE;
-
- /* wait a maximum of 1 second for the statistics to be updated */
- timeout = jiffies;
- for(;;) {
- if(chdlc_priv_area->update_comms_stats == 0)
- break;
- if ((jiffies - timeout) > (1 * HZ)){
- chdlc_priv_area->update_comms_stats = 0;
- chdlc_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- return -EAGAIN;
- }
- }
-
- return 0;
-}
-
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return: 0 o.k.
- * < 0 failure (channel will not be created)
- */
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf)
-{
- sdla_t* card = wandev->private;
- chdlc_private_area_t* chdlc_priv_area;
-
-
- printk(KERN_INFO "%s: Configuring Interface: %s\n",
- card->devname, conf->name);
-
- if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
- printk(KERN_INFO "%s: Invalid interface name!\n",
- card->devname);
- return -EINVAL;
- }
-
- /* allocate and initialize private data */
- chdlc_priv_area = kmalloc(sizeof(chdlc_private_area_t), GFP_KERNEL);
-
- if(chdlc_priv_area == NULL)
- return -ENOMEM;
-
- memset(chdlc_priv_area, 0, sizeof(chdlc_private_area_t));
-
- chdlc_priv_area->card = card;
- chdlc_priv_area->common.sk = NULL;
- chdlc_priv_area->common.func = NULL;
-
- /* initialize data */
- strcpy(card->u.c.if_name, conf->name);
-
- if(card->wandev.new_if_cnt > 0) {
- kfree(chdlc_priv_area);
- return -EEXIST;
- }
-
- card->wandev.new_if_cnt++;
-
- chdlc_priv_area->TracingEnabled = 0;
- chdlc_priv_area->route_status = NO_ROUTE;
- chdlc_priv_area->route_removed = 0;
-
- card->u.c.async_mode = conf->async_mode;
-
- /* setup for asynchronous mode */
- if(conf->async_mode) {
- printk(KERN_INFO "%s: Configuring for asynchronous mode\n",
- wandev->name);
-
- if(card->u.c.comm_port == WANOPT_PRI) {
- printk(KERN_INFO
- "%s:Asynchronous mode on secondary port only\n",
- wandev->name);
- kfree(chdlc_priv_area);
- return -EINVAL;
- }
-
- if(strcmp(conf->usedby, "WANPIPE") == 0) {
- printk(KERN_INFO
- "%s: Running in WANIPE Async Mode\n", wandev->name);
- card->u.c.usedby = WANPIPE;
- }else{
- card->u.c.usedby = API;
- }
-
- if(!card->wandev.clocking) {
- printk(KERN_INFO
- "%s: Asynch. clocking must be 'Internal'\n",
- wandev->name);
- kfree(chdlc_priv_area);
- return -EINVAL;
- }
-
- if((card->wandev.bps < MIN_ASY_BAUD_RATE) ||
- (card->wandev.bps > MAX_ASY_BAUD_RATE)) {
- printk(KERN_INFO "%s: Selected baud rate is invalid.\n",
- wandev->name);
- printk(KERN_INFO "Must be between %u and %u bps.\n",
- MIN_ASY_BAUD_RATE, MAX_ASY_BAUD_RATE);
- kfree(chdlc_priv_area);
- return -EINVAL;
- }
-
- card->u.c.api_options = 0;
- if (conf->asy_data_trans == WANOPT_YES) {
- card->u.c.api_options |= ASY_RX_DATA_TRANSPARENT;
- }
-
- card->u.c.protocol_options = 0;
- if (conf->rts_hs_for_receive == WANOPT_YES) {
- card->u.c.protocol_options |= ASY_RTS_HS_FOR_RX;
- }
- if (conf->xon_xoff_hs_for_receive == WANOPT_YES) {
- card->u.c.protocol_options |= ASY_XON_XOFF_HS_FOR_RX;
- }
- if (conf->xon_xoff_hs_for_transmit == WANOPT_YES) {
- card->u.c.protocol_options |= ASY_XON_XOFF_HS_FOR_TX;
- }
- if (conf->dcd_hs_for_transmit == WANOPT_YES) {
- card->u.c.protocol_options |= ASY_DCD_HS_FOR_TX;
- }
- if (conf->cts_hs_for_transmit == WANOPT_YES) {
- card->u.c.protocol_options |= ASY_CTS_HS_FOR_TX;
- }
-
- card->u.c.tx_bits_per_char = conf->tx_bits_per_char;
- card->u.c.rx_bits_per_char = conf->rx_bits_per_char;
- card->u.c.stop_bits = conf->stop_bits;
- card->u.c.parity = conf->parity;
- card->u.c.break_timer = conf->break_timer;
- card->u.c.inter_char_timer = conf->inter_char_timer;
- card->u.c.rx_complete_length = conf->rx_complete_length;
- card->u.c.xon_char = conf->xon_char;
-
- } else { /* setup for synchronous mode */
-
- card->u.c.protocol_options = 0;
- if (conf->ignore_dcd == WANOPT_YES){
- card->u.c.protocol_options |= IGNORE_DCD_FOR_LINK_STAT;
- }
- if (conf->ignore_cts == WANOPT_YES){
- card->u.c.protocol_options |= IGNORE_CTS_FOR_LINK_STAT;
- }
-
- if (conf->ignore_keepalive == WANOPT_YES) {
- card->u.c.protocol_options |=
- IGNORE_KPALV_FOR_LINK_STAT;
- card->u.c.kpalv_tx = MIN_Tx_KPALV_TIMER;
- card->u.c.kpalv_rx = MIN_Rx_KPALV_TIMER;
- card->u.c.kpalv_err = MIN_KPALV_ERR_TOL;
-
- } else { /* Do not ignore keepalives */
- card->u.c.kpalv_tx =
- ((conf->keepalive_tx_tmr - MIN_Tx_KPALV_TIMER)
- >= 0) ?
- min_t(unsigned int, conf->keepalive_tx_tmr,MAX_Tx_KPALV_TIMER) :
- DEFAULT_Tx_KPALV_TIMER;
-
- card->u.c.kpalv_rx =
- ((conf->keepalive_rx_tmr - MIN_Rx_KPALV_TIMER)
- >= 0) ?
- min_t(unsigned int, conf->keepalive_rx_tmr,MAX_Rx_KPALV_TIMER) :
- DEFAULT_Rx_KPALV_TIMER;
-
- card->u.c.kpalv_err =
- ((conf->keepalive_err_margin-MIN_KPALV_ERR_TOL)
- >= 0) ?
- min_t(unsigned int, conf->keepalive_err_margin,
- MAX_KPALV_ERR_TOL) :
- DEFAULT_KPALV_ERR_TOL;
- }
-
- /* Setup slarp timer to control delay between slarps */
- card->u.c.slarp_timer =
- ((conf->slarp_timer - MIN_SLARP_REQ_TIMER) >= 0) ?
- min_t(unsigned int, conf->slarp_timer, MAX_SLARP_REQ_TIMER) :
- DEFAULT_SLARP_REQ_TIMER;
-
- if (conf->hdlc_streaming == WANOPT_YES) {
- printk(KERN_INFO "%s: Enabling HDLC STREAMING Mode\n",
- wandev->name);
- card->u.c.protocol_options = HDLC_STREAMING_MODE;
- }
-
- if ((chdlc_priv_area->true_if_encoding = conf->true_if_encoding) == WANOPT_YES){
- printk(KERN_INFO
- "%s: Enabling, true interface type encoding.\n",
- card->devname);
- }
-
- /* Setup wanpipe as a router (WANPIPE) or as an API */
- if( strcmp(conf->usedby, "WANPIPE") == 0) {
-
- printk(KERN_INFO "%s: Running in WANPIPE mode!\n",
- wandev->name);
- card->u.c.usedby = WANPIPE;
-
- /* Option to bring down the interface when
- * the link goes down */
- if (conf->if_down){
- set_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down);
- printk(KERN_INFO
- "%s: Dynamic interface configuration enabled\n",
- card->devname);
- }
-
- } else if( strcmp(conf->usedby, "API") == 0) {
- card->u.c.usedby = API;
- printk(KERN_INFO "%s: Running in API mode !\n",
- wandev->name);
- }
- }
-
- /* Tells us that if this interface is a
- * gateway or not */
- if ((chdlc_priv_area->gateway = conf->gateway) == WANOPT_YES){
- printk(KERN_INFO "%s: Interface %s is set as a gateway.\n",
- card->devname,card->u.c.if_name);
- }
-
- /* Get Multicast Information */
- chdlc_priv_area->mc = conf->mc;
-
- /* prepare network device data space for registration */
- strcpy(dev->name,card->u.c.if_name);
-
- dev->init = &if_init;
- dev->priv = chdlc_priv_area;
-
- /* Initialize the polling work routine */
- INIT_WORK(&chdlc_priv_area->poll_work, (void*)(void*)chdlc_poll, dev);
-
- /* Initialize the polling delay timer */
- init_timer(&chdlc_priv_area->poll_delay_timer);
- chdlc_priv_area->poll_delay_timer.data = (unsigned long)dev;
- chdlc_priv_area->poll_delay_timer.function = chdlc_poll_delay;
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration. Returning anything but zero will fail interface
- * registration.
- */
-static int if_init(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
- struct wan_device* wandev = &card->wandev;
-
- /* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_header = &if_header;
- dev->rebuild_header = &if_rebuild_hdr;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
- dev->tx_timeout = &if_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- /* Initialize media-specific parameters */
- dev->flags |= IFF_POINTOPOINT;
- dev->flags |= IFF_NOARP;
-
- /* Enable Mulitcasting if user selected */
- if (chdlc_priv_area->mc == WANOPT_YES){
- dev->flags |= IFF_MULTICAST;
- }
-
- if (chdlc_priv_area->true_if_encoding){
- dev->type = ARPHRD_HDLC; /* This breaks the tcpdump */
- }else{
- dev->type = ARPHRD_PPP;
- }
-
- dev->mtu = card->wandev.mtu;
- /* for API usage, add the API header size to the requested MTU size */
- if(card->u.c.usedby == API) {
- dev->mtu += sizeof(api_tx_hdr_t);
- }
-
- dev->hard_header_len = CHDLC_HDR_LEN;
-
- /* Initialize hardware parameters */
- dev->irq = wandev->irq;
- dev->dma = wandev->dma;
- dev->base_addr = wandev->ioport;
- dev->mem_start = wandev->maddr;
- dev->mem_end = wandev->maddr + wandev->msize - 1;
-
- /* Set transmit buffer queue length
- * If too low packets will not be retransmitted
- * by stack.
- */
- dev->tx_queue_len = 100;
- SET_MODULE_OWNER(dev);
-
- return 0;
-}
-
-/*============================================================================
- * Open network interface.
- * o enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
- struct timeval tv;
- int err = 0;
-
- /* Only one open per interface is allowed */
-
- if (netif_running(dev))
- return -EBUSY;
-
- /* Initialize the work queue entry */
- chdlc_priv_area->tq_working=0;
-
- INIT_WORK(&chdlc_priv_area->common.wanpipe_work,
- (void *)(void *)chdlc_work, dev);
-
- /* Allocate and initialize BH circular buffer */
- /* Add 1 to MAX_BH_BUFF so we don't have test with (MAX_BH_BUFF-1) */
- chdlc_priv_area->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC);
- memset(chdlc_priv_area->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1)));
- atomic_set(&chdlc_priv_area->bh_buff_used, 0);
-
- do_gettimeofday(&tv);
- chdlc_priv_area->router_start_time = tv.tv_sec;
-
- netif_start_queue(dev);
-
- wanpipe_open(card);
-
- /* TTY is configured during wanpipe_set_termios
- * call, not here */
- if (card->tty_opt)
- return err;
-
- set_bit(0,&chdlc_priv_area->config_chdlc);
- chdlc_priv_area->config_chdlc_timeout=jiffies;
-
- /* Start the CHDLC configuration after 1sec delay.
- * This will give the interface initilization time
- * to finish its configuration */
- mod_timer(&chdlc_priv_area->poll_delay_timer, jiffies + HZ);
- return err;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last close, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
-
- if (chdlc_priv_area->bh_head){
- int i;
- struct sk_buff *skb;
-
- for (i=0; i<(MAX_BH_BUFF+1); i++){
- skb = ((bh_data_t *)&chdlc_priv_area->bh_head[i])->skb;
- if (skb != NULL){
- dev_kfree_skb_any(skb);
- }
- }
- kfree(chdlc_priv_area->bh_head);
- chdlc_priv_area->bh_head=NULL;
- }
-
- netif_stop_queue(dev);
- wanpipe_close(card);
- del_timer(&chdlc_priv_area->poll_delay_timer);
- return 0;
-}
-
-static void disable_comm (sdla_t *card)
-{
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
- if (card->u.c.comm_enabled){
- chdlc_disable_comm_shutdown (card);
- }else{
- flags->interrupt_info_struct.interrupt_permission = 0;
- }
-
- if (!tty_init_cnt)
- return;
-
- if (card->tty_opt){
- struct serial_state * state;
- if (!(--tty_init_cnt)){
- int e1;
- serial_driver.refcount=0;
-
- if ((e1 = tty_unregister_driver(&serial_driver)))
- printk("SERIAL: failed to unregister serial driver (%d)\n",
- e1);
- printk(KERN_INFO "%s: Unregistering TTY Driver, Major %i\n",
- card->devname,WAN_TTY_MAJOR);
- }
- card->tty=NULL;
- tty_card_map[card->tty_minor]=NULL;
- state = &rs_table[card->tty_minor];
- memset(state, 0, sizeof(*state));
- }
- return;
-}
-
-
-/*============================================================================
- * Build media header.
- *
- * The trick here is to put packet type (Ethertype) into 'protocol' field of
- * the socket buffer, so that we don't forget it. If packet type is not
- * supported, set skb->protocol to 0 and discard packet later.
- *
- * Return: media header length.
- */
-static int if_header(struct sk_buff* skb, struct net_device* dev,
- unsigned short type, void* daddr, void* saddr,
- unsigned len)
-{
- skb->protocol = htons(type);
-
- return CHDLC_HDR_LEN;
-}
-
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
- chdlc_private_area_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- /* If our device stays busy for at least 5 seconds then we will
- * kick start the device by making dev->tbusy = 0. We expect
- * that our device never stays busy more than 5 seconds. So this
- * is only used as a last resort.
- */
-
- ++card->wandev.stats.collisions;
-
- printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
- netif_wake_queue (dev);
-}
-
-
-
-/*============================================================================
- * Re-build media header.
- *
- * Return: 1 physical address resolved.
- * 0 physical address not resolved
- */
-static int if_rebuild_hdr (struct sk_buff *skb)
-{
- return 1;
-}
-
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- * transmit from overlapping.
- * o check link state. If link is not up, then drop the packet.
- * o execute adapter send command.
- * o free socket buffer
- *
- * Return: 0 complete (socket buffer must be freed)
- * non-0 packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- * bottom half" (with interrupts enabled).
- * 2. Setting tbusy flag will inhibit further transmit requests from the
- * protocol stack and can be used for flow control with protocol layer.
- */
-static int if_send(struct sk_buff* skb, struct net_device* dev)
-{
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- sdla_t *card = chdlc_priv_area->card;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;
- int udp_type = 0;
- unsigned long smp_flags;
- int err=0;
-
- netif_stop_queue(dev);
-
- if (skb == NULL){
- /* If we get here, some higher layer thinks we've missed an
- * tx-done interrupt.
- */
- printk(KERN_INFO "%s: interface %s got kicked!\n",
- card->devname, dev->name);
-
- netif_wake_queue(dev);
- return 0;
- }
-
- if (ntohs(skb->protocol) != htons(PVC_PROT)){
-
- /* check the udp packet type */
-
- udp_type = udp_pkt_type(skb, card);
-
- if (udp_type == UDP_CPIPE_TYPE){
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev,
- chdlc_priv_area)){
- chdlc_int->interrupt_permission |=
- APP_INT_ON_TIMER;
- }
- netif_start_queue(dev);
- return 0;
- }
-
- /* check to see if the source IP address is a broadcast or */
- /* multicast IP address */
- if(chk_bcast_mcast_addr(card, dev, skb)){
- ++card->wandev.stats.tx_dropped;
- dev_kfree_skb_any(skb);
- netif_start_queue(dev);
- return 0;
- }
- }
-
- /* Lock the 508 Card: SMP is supported */
- if(card->hw.type != SDLA_S514){
- s508_lock(card,&smp_flags);
- }
-
- if(test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
-
- printk(KERN_INFO "%s: Critical in if_send: %lx\n",
- card->wandev.name,card->wandev.critical);
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
- goto if_send_exit_crit;
- }
-
- if(card->u.c.state != WAN_CONNECTED){
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
-
- }else if(!skb->protocol){
- ++card->wandev.stats.tx_errors;
- netif_start_queue(dev);
-
- }else {
- void* data = skb->data;
- unsigned len = skb->len;
- unsigned char attr;
-
- /* If it's an API packet pull off the API
- * header. Also check that the packet size
- * is larger than the API header
- */
- if (card->u.c.usedby == API){
- api_tx_hdr_t* api_tx_hdr;
-
- /* discard the frame if we are configured for */
- /* 'receive only' mode or if there is no data */
- if (card->u.c.receive_only ||
- (len <= sizeof(api_tx_hdr_t))) {
-
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
- goto if_send_exit_crit;
- }
-
- api_tx_hdr = (api_tx_hdr_t *)data;
- attr = api_tx_hdr->attr;
- data += sizeof(api_tx_hdr_t);
- len -= sizeof(api_tx_hdr_t);
- }
-
- if(chdlc_send(card, data, len)) {
- netif_stop_queue(dev);
- }else{
- ++card->wandev.stats.tx_packets;
- card->wandev.stats.tx_bytes += len;
-
- netif_start_queue(dev);
-
- dev->trans_start = jiffies;
- }
- }
-
-if_send_exit_crit:
-
- if (!(err=netif_queue_stopped(dev))) {
- dev_kfree_skb_any(skb);
- }else{
- chdlc_priv_area->tick_counter = jiffies;
- chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
- }
-
- clear_bit(SEND_CRIT, (void*)&card->wandev.critical);
- if(card->hw.type != SDLA_S514){
- s508_unlock(card,&smp_flags);
- }
-
- return err;
-}
-
-
-/*============================================================================
- * Check to see if the packet to be transmitted contains a broadcast or
- * multicast source IP address.
- */
-
-static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev,
- struct sk_buff *skb)
-{
- u32 src_ip_addr;
- u32 broadcast_ip_addr = 0;
- struct in_device *in_dev;
-
- /* read the IP source address from the outgoing packet */
- src_ip_addr = *(u32 *)(skb->data + 12);
-
- /* read the IP broadcast address for the device */
- in_dev = dev->ip_ptr;
- if(in_dev != NULL) {
- struct in_ifaddr *ifa= in_dev->ifa_list;
- if(ifa != NULL)
- broadcast_ip_addr = ifa->ifa_broadcast;
- else
- return 0;
- }
-
- /* check if the IP Source Address is a Broadcast address */
- if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
- printk(KERN_INFO "%s: Broadcast Source Address silently discarded\n",
- card->devname);
- return 1;
- }
-
- /* check if the IP Source Address is a Multicast address */
- if((ntohl(src_ip_addr) >= 0xE0000001) &&
- (ntohl(src_ip_addr) <= 0xFFFFFFFE)) {
- printk(KERN_INFO "%s: Multicast Source Address silently discarded\n",
- card->devname);
- return 1;
- }
-
- return 0;
-}
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return length of reply.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
-
- unsigned short len, udp_length, temp, ip_length;
- unsigned long ip_temp;
- int even_bound = 0;
- chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data;
-
- /* Set length of packet */
- len = sizeof(ip_pkt_t)+
- sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- sizeof(trace_info_t)+
- mbox_len;
-
- /* fill in UDP reply */
- c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-
- /* fill in UDP length */
- udp_length = sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- sizeof(trace_info_t)+
- mbox_len;
-
- /* put it on an even boundary */
- if ( udp_length & 0x0001 ) {
- udp_length += 1;
- len += 1;
- even_bound = 1;
- }
-
- temp = (udp_length<<8)|(udp_length>>8);
- c_udp_pkt->udp_pkt.udp_length = temp;
-
- /* swap UDP ports */
- temp = c_udp_pkt->udp_pkt.udp_src_port;
- c_udp_pkt->udp_pkt.udp_src_port =
- c_udp_pkt->udp_pkt.udp_dst_port;
- c_udp_pkt->udp_pkt.udp_dst_port = temp;
-
- /* add UDP pseudo header */
- temp = 0x1100;
- *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp;
- temp = (udp_length<<8)|(udp_length>>8);
- *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
-
- /* calculate UDP checksum */
- c_udp_pkt->udp_pkt.udp_checksum = 0;
- c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET);
-
- /* fill in IP length */
- ip_length = len;
- temp = (ip_length<<8)|(ip_length>>8);
- c_udp_pkt->ip_pkt.total_length = temp;
-
- /* swap IP addresses */
- ip_temp = c_udp_pkt->ip_pkt.ip_src_address;
- c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address;
- c_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
- /* fill in IP checksum */
- c_udp_pkt->ip_pkt.hdr_checksum = 0;
- c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t));
-
- return len;
-
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
- unsigned short temp;
- unsigned long sum=0;
- int i;
-
- for( i = 0; i <len; i+=2 ) {
- memcpy(&temp,&data[i],2);
- sum += (unsigned long)temp;
- }
-
- while (sum >> 16 ) {
- sum = (sum & 0xffffUL) + (sum >> 16);
- }
-
- temp = (unsigned short)sum;
- temp = ~temp;
-
- if( temp == 0 )
- temp = 0xffff;
-
- return temp;
-}
-
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct enet_statistics.
- */
-static struct net_device_stats* if_stats(struct net_device* dev)
-{
- sdla_t *my_card;
- chdlc_private_area_t* chdlc_priv_area;
-
- if ((chdlc_priv_area=dev->priv) == NULL)
- return NULL;
-
- my_card = chdlc_priv_area->card;
- return &my_card->wandev.stats;
-}
-
-
-/****** Cisco HDLC Firmware Interface Functions *******************************/
-
-/*============================================================================
- * Read firmware code version.
- * Put code version as ASCII string in str.
- */
-static int chdlc_read_version (sdla_t* card, char* str)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int len;
- char err;
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CODE_VERSION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- }
- else if (str) { /* is not null */
- len = mb->buffer_length;
- memcpy(str, mb->data, len);
- str[len] = '\0';
- }
- return (err);
-}
-
-/*-----------------------------------------------------------------------------
- * Configure CHDLC firmware.
- */
-static int chdlc_configure (sdla_t* card, void* data)
-{
- int err;
- CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;
- int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT);
-
- mailbox->buffer_length = data_length;
- memcpy(mailbox->data, data, data_length);
- mailbox->command = SET_CHDLC_CONFIGURATION;
- err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;
-
- if (err != COMMAND_OK) chdlc_error (card, err, mailbox);
-
- return err;
-}
-
-
-/*============================================================================
- * Set interrupt mode -- HDLC Version.
- */
-
-static int chdlc_set_intr_mode (sdla_t* card, unsigned mode)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_INT_TRIGGERS_STRUCT* int_data =
- (CHDLC_INT_TRIGGERS_STRUCT *)mb->data;
- int err;
-
- int_data->CHDLC_interrupt_triggers = mode;
- int_data->IRQ = card->hw.irq;
- int_data->interrupt_timer = 1;
-
- mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);
- mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error (card, err, mb);
- return err;
-}
-
-
-/*===========================================================
- * chdlc_disable_comm_shutdown
- *
- * Shutdown() disables the communications. We must
- * have a sparate functions, because we must not
- * call chdlc_error() hander since the private
- * area has already been replaced */
-
-static int chdlc_disable_comm_shutdown (sdla_t *card)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_INT_TRIGGERS_STRUCT* int_data =
- (CHDLC_INT_TRIGGERS_STRUCT *)mb->data;
- int err;
-
- /* Disable Interrutps */
- int_data->CHDLC_interrupt_triggers = 0;
- int_data->IRQ = card->hw.irq;
- int_data->interrupt_timer = 1;
-
- mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);
- mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- /* Disable Communications */
-
- if (card->u.c.async_mode) {
- mb->command = DISABLE_ASY_COMMUNICATIONS;
- }else{
- mb->command = DISABLE_CHDLC_COMMUNICATIONS;
- }
-
- mb->buffer_length = 0;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- card->u.c.comm_enabled = 0;
-
- return 0;
-}
-
-/*============================================================================
- * Enable communications.
- */
-
-static int chdlc_comm_enable (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = ENABLE_CHDLC_COMMUNICATIONS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card, err, mb);
- else
- card->u.c.comm_enabled = 1;
-
- return err;
-}
-
-/*============================================================================
- * Read communication error statistics.
- */
-static int chdlc_read_comm_err_stats (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = READ_COMMS_ERROR_STATS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card,err,mb);
- return err;
-}
-
-
-/*============================================================================
- * Read CHDLC operational statistics.
- */
-static int chdlc_read_op_stats (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_OPERATIONAL_STATS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card,err,mb);
- return err;
-}
-
-
-/*============================================================================
- * Update communications error and general packet statistics.
- */
-static int update_comms_stats(sdla_t* card,
- chdlc_private_area_t* chdlc_priv_area)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- COMMS_ERROR_STATS_STRUCT* err_stats;
- CHDLC_OPERATIONAL_STATS_STRUCT *op_stats;
-
- /* on the first timer interrupt, read the comms error statistics */
- if(chdlc_priv_area->update_comms_stats == 2) {
- if(chdlc_read_comm_err_stats(card))
- return 1;
- err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data;
- card->wandev.stats.rx_over_errors =
- err_stats->Rx_overrun_err_count;
- card->wandev.stats.rx_crc_errors =
- err_stats->CRC_err_count;
- card->wandev.stats.rx_frame_errors =
- err_stats->Rx_abort_count;
- card->wandev.stats.rx_fifo_errors =
- err_stats->Rx_dis_pri_bfrs_full_count;
- card->wandev.stats.rx_missed_errors =
- card->wandev.stats.rx_fifo_errors;
- card->wandev.stats.tx_aborted_errors =
- err_stats->sec_Tx_abort_count;
- }
-
- /* on the second timer interrupt, read the operational statistics */
- else {
- if(chdlc_read_op_stats(card))
- return 1;
- op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data;
- card->wandev.stats.rx_length_errors =
- (op_stats->Rx_Data_discard_short_count +
- op_stats->Rx_Data_discard_long_count);
- }
-
- return 0;
-}
-
-/*============================================================================
- * Send packet.
- * Return: 0 - o.k.
- * 1 - no transmit buffers available
- */
-static int chdlc_send (sdla_t* card, void* data, unsigned len)
-{
- CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf;
-
- if (txbuf->opp_flag)
- return 1;
-
- sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len);
-
- txbuf->frame_length = len;
- txbuf->opp_flag = 1; /* start transmission */
-
- /* Update transmit buffer control fields */
- card->u.c.txbuf = ++txbuf;
-
- if ((void*)txbuf > card->u.c.txbuf_last)
- card->u.c.txbuf = card->u.c.txbuf_base;
-
- return 0;
-}
-
-/****** Firmware Error Handler **********************************************/
-
-/*============================================================================
- * Firmware error handler.
- * This routine is called whenever firmware command returns non-zero
- * return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
-{
- unsigned cmd = mb->command;
-
- switch (err) {
-
- case CMD_TIMEOUT:
- printk(KERN_INFO "%s: command 0x%02X timed out!\n",
- card->devname, cmd);
- break;
-
- case S514_BOTH_PORTS_SAME_CLK_MODE:
- if(cmd == SET_CHDLC_CONFIGURATION) {
- printk(KERN_INFO
- "%s: Configure both ports for the same clock source\n",
- card->devname);
- break;
- }
-
- default:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
- card->devname, cmd, err);
- }
-
- return 0;
-}
-
-
-/********** Bottom Half Handlers ********************************************/
-
-/* NOTE: There is no API, BH support for Kernels lower than 2.2.X.
- * DO NOT INSERT ANY CODE HERE, NOTICE THE
- * PREPROCESSOR STATEMENT ABOVE, UNLESS YOU KNOW WHAT YOU ARE
- * DOING */
-
-static void chdlc_work(struct net_device * dev)
-{
- chdlc_private_area_t* chan = dev->priv;
- sdla_t *card = chan->card;
- struct sk_buff *skb;
-
- if (atomic_read(&chan->bh_buff_used) == 0){
- clear_bit(0, &chan->tq_working);
- return;
- }
-
- while (atomic_read(&chan->bh_buff_used)){
-
- skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb;
-
- if (skb != NULL){
-
- if (chan->common.sk == NULL || chan->common.func == NULL){
- ++card->wandev.stats.rx_dropped;
- dev_kfree_skb_any(skb);
- chdlc_work_cleanup(dev);
- continue;
- }
-
- if (chan->common.func(skb,dev,chan->common.sk) != 0){
- /* Sock full cannot send, queue us for another
- * try */
- atomic_set(&chan->common.receive_block,1);
- return;
- }else{
- chdlc_work_cleanup(dev);
- }
- }else{
- chdlc_work_cleanup(dev);
- }
- }
- clear_bit(0, &chan->tq_working);
-
- return;
-}
-
-static int chdlc_work_cleanup(struct net_device *dev)
-{
- chdlc_private_area_t* chan = dev->priv;
-
- ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL;
-
- if (chan->bh_read == MAX_BH_BUFF){
- chan->bh_read=0;
- }else{
- ++chan->bh_read;
- }
-
- atomic_dec(&chan->bh_buff_used);
- return 0;
-}
-
-
-
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb)
-{
- /* Check for full */
- chdlc_private_area_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){
- ++card->wandev.stats.rx_dropped;
- dev_kfree_skb_any(skb);
- return 1;
- }
-
- ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb;
-
- if (chan->bh_write == MAX_BH_BUFF){
- chan->bh_write=0;
- }else{
- ++chan->bh_write;
- }
-
- atomic_inc(&chan->bh_buff_used);
-
- return 0;
-}
-
-/* END OF API BH Support */
-
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * Cisco HDLC interrupt service routine.
- */
-static void wpc_isr (sdla_t* card)
-{
- struct net_device* dev;
- SHARED_MEMORY_INFO_STRUCT* flags = NULL;
- int i;
- sdla_t *my_card;
-
-
- /* Check for which port the interrupt has been generated
- * Since Secondary Port is piggybacking on the Primary
- * the check must be done here.
- */
-
- flags = card->u.c.flags;
- if (!flags->interrupt_info_struct.interrupt_type){
- /* Check for a second port (piggybacking) */
- if ((my_card = card->next)){
- flags = my_card->u.c.flags;
- if (flags->interrupt_info_struct.interrupt_type){
- card = my_card;
- card->isr(card);
- return;
- }
- }
- }
-
- flags = card->u.c.flags;
- card->in_isr = 1;
- dev = card->wandev.dev;
-
- /* If we get an interrupt with no network device, stop the interrupts
- * and issue an error */
- if (!card->tty_opt && !dev &&
- flags->interrupt_info_struct.interrupt_type !=
- COMMAND_COMPLETE_APP_INT_PEND){
-
- goto isr_done;
- }
-
- /* if critical due to peripheral operations
- * ie. update() or getstats() then reset the interrupt and
- * wait for the board to retrigger.
- */
- if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
- printk(KERN_INFO "ISR CRIT TO PERI\n");
- goto isr_done;
- }
-
- /* On a 508 Card, if critical due to if_send
- * Major Error !!! */
- if(card->hw.type != SDLA_S514) {
- if(test_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
- printk(KERN_INFO "%s: Critical while in ISR: %lx\n",
- card->devname, card->wandev.critical);
- card->in_isr = 0;
- flags->interrupt_info_struct.interrupt_type = 0;
- return;
- }
- }
-
- switch(flags->interrupt_info_struct.interrupt_type) {
-
- case RX_APP_INT_PEND: /* 0x01: receive interrupt */
- rx_intr(card);
- break;
-
- case TX_APP_INT_PEND: /* 0x02: transmit interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TX_FRAME;
-
- if (card->tty_opt){
- wanpipe_tty_trigger_poll(card);
- break;
- }
-
- if (dev && netif_queue_stopped(dev)){
- if (card->u.c.usedby == API){
- netif_start_queue(dev);
- wakeup_sk_bh(dev);
- }else{
- netif_wake_queue(dev);
- }
- }
- break;
-
- case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */
- ++ Intr_test_counter;
- break;
-
- case CHDLC_EXCEP_COND_APP_INT_PEND: /* 0x20 */
- process_chdlc_exception(card);
- break;
-
- case GLOBAL_EXCEP_COND_APP_INT_PEND:
- process_global_exception(card);
- break;
-
- case TIMER_APP_INT_PEND:
- timer_intr(card);
- break;
-
- default:
- printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n",
- card->devname,
- flags->interrupt_info_struct.interrupt_type);
- printk(KERN_INFO "Code name: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codename[i]);
- printk(KERN_INFO "\nCode version: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codeversion[i]);
- printk(KERN_INFO "\n");
- break;
- }
-
-isr_done:
-
- card->in_isr = 0;
- flags->interrupt_info_struct.interrupt_type = 0;
- return;
-}
-
-/*============================================================================
- * Receive interrupt handler.
- */
-static void rx_intr (sdla_t* card)
-{
- struct net_device *dev;
- chdlc_private_area_t *chdlc_priv_area;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb;
- struct sk_buff *skb;
- unsigned len;
- unsigned addr = rxbuf->ptr_data_bfr;
- void *buf;
- int i,udp_type;
-
- if (rxbuf->opp_flag != 0x01) {
- printk(KERN_INFO
- "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n",
- card->devname, (unsigned)rxbuf, rxbuf->opp_flag);
- printk(KERN_INFO "Code name: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codename[i]);
- printk(KERN_INFO "\nCode version: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codeversion[i]);
- printk(KERN_INFO "\n");
-
-
- /* Bug Fix: Mar 6 2000
- * If we get a corrupted mailbox, it measn that driver
- * is out of sync with the firmware. There is no recovery.
- * If we don't turn off all interrupts for this card
- * the machine will crash.
- */
- printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
- printk(KERN_INFO "Please contact Sangoma Technologies !\n");
- chdlc_set_intr_mode(card,0);
- return;
- }
-
- len = rxbuf->frame_length;
-
- if (card->tty_opt){
-
- if (rxbuf->error_flag){
- goto rx_exit;
- }
-
- if (len <= CRC_LENGTH){
- goto rx_exit;
- }
-
- if (!card->u.c.async_mode){
- len -= CRC_LENGTH;
- }
-
- wanpipe_tty_receive(card,addr,len);
- goto rx_exit;
- }
-
- dev = card->wandev.dev;
-
- if (!dev){
- goto rx_exit;
- }
-
- if (!netif_running(dev))
- goto rx_exit;
-
- chdlc_priv_area = dev->priv;
-
-
- /* Allocate socket buffer */
- skb = dev_alloc_skb(len);
-
- if (skb == NULL) {
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- ++card->wandev.stats.rx_dropped;
- goto rx_exit;
- }
-
- /* Copy data to the socket buffer */
- if((addr + len) > card->u.c.rx_top + 1) {
- unsigned tmp = card->u.c.rx_top - addr + 1;
- buf = skb_put(skb, tmp);
- sdla_peek(&card->hw, addr, buf, tmp);
- addr = card->u.c.rx_base;
- len -= tmp;
- }
-
- buf = skb_put(skb, len);
- sdla_peek(&card->hw, addr, buf, len);
-
- skb->protocol = htons(ETH_P_IP);
-
- card->wandev.stats.rx_packets ++;
- card->wandev.stats.rx_bytes += skb->len;
- udp_type = udp_pkt_type( skb, card );
-
- if(udp_type == UDP_CPIPE_TYPE) {
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK,
- card, skb, dev, chdlc_priv_area)) {
- flags->interrupt_info_struct.
- interrupt_permission |=
- APP_INT_ON_TIMER;
- }
- } else if(card->u.c.usedby == API) {
-
- api_rx_hdr_t* api_rx_hdr;
- skb_push(skb, sizeof(api_rx_hdr_t));
- api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00];
- api_rx_hdr->error_flag = rxbuf->error_flag;
- api_rx_hdr->time_stamp = rxbuf->time_stamp;
-
- skb->protocol = htons(PVC_PROT);
- skb->mac.raw = skb->data;
- skb->dev = dev;
- skb->pkt_type = WAN_PACKET_DATA;
-
- bh_enqueue(dev, skb);
-
- if (!test_and_set_bit(0,&chdlc_priv_area->tq_working))
- wanpipe_queue_work(&chdlc_priv_area->common.wanpipe_work);
- }else{
- /* FIXME: we should check to see if the received packet is a
- multicast packet so that we can increment the multicast
- statistic
- ++ chdlc_priv_area->if_stats.multicast;
- */
- /* Pass it up the protocol stack */
-
- skb->dev = dev;
- skb->mac.raw = skb->data;
- netif_rx(skb);
- dev->last_rx = jiffies;
- }
-
-rx_exit:
- /* Release buffer element and calculate a pointer to the next one */
- rxbuf->opp_flag = 0x00;
- card->u.c.rxmb = ++ rxbuf;
- if((void*)rxbuf > card->u.c.rxbuf_last){
- card->u.c.rxmb = card->u.c.rxbuf_base;
- }
-}
-
-/*============================================================================
- * Timer interrupt handler.
- * The timer interrupt is used for two purposes:
- * 1) Processing udp calls from 'cpipemon'.
- * 2) Reading board-level statistics for updating the proc file system.
- */
-void timer_intr(sdla_t *card)
-{
- struct net_device* dev;
- chdlc_private_area_t* chdlc_priv_area = NULL;
- SHARED_MEMORY_INFO_STRUCT* flags = NULL;
-
- if ((dev = card->wandev.dev)==NULL){
- flags = card->u.c.flags;
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TIMER;
- return;
- }
-
- chdlc_priv_area = dev->priv;
-
- if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) {
- if (!config_chdlc(card)){
- chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG;
- }
- }
-
- /* process a udp call if pending */
- if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) {
- process_udp_mgmt_pkt(card, dev,
- chdlc_priv_area);
- chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP;
- }
-
- /* read the communications statistics if required */
- if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) {
- update_comms_stats(card, chdlc_priv_area);
- if(!(-- chdlc_priv_area->update_comms_stats)) {
- chdlc_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- }
- }
-
- /* only disable the timer interrupt if there are no udp or statistic */
- /* updates pending */
- if(!chdlc_priv_area->timer_int_enabled) {
- flags = card->u.c.flags;
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TIMER;
- }
-}
-
-/*------------------------------------------------------------------------------
- Miscellaneous Functions
- - set_chdlc_config() used to set configuration options on the board
-------------------------------------------------------------------------------*/
-
-static int set_chdlc_config(sdla_t* card)
-{
- CHDLC_CONFIGURATION_STRUCT cfg;
-
- memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT));
-
- if(card->wandev.clocking){
- cfg.baud_rate = card->wandev.bps;
- }
-
- cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ?
- INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35;
-
- cfg.modem_config_options = 0;
- cfg.modem_status_timer = 100;
-
- cfg.CHDLC_protocol_options = card->u.c.protocol_options;
-
- if (card->tty_opt){
- cfg.CHDLC_API_options = DISCARD_RX_ERROR_FRAMES;
- }
-
- cfg.percent_data_buffer_for_Tx = (card->u.c.receive_only) ? 0 : 50;
- cfg.CHDLC_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT |
- CHDLC_RX_DATA_BYTE_COUNT_STAT);
-
- if (card->tty_opt){
- card->wandev.mtu = TTY_CHDLC_MAX_MTU;
- }
- cfg.max_CHDLC_data_field_length = card->wandev.mtu;
- cfg.transmit_keepalive_timer = card->u.c.kpalv_tx;
- cfg.receive_keepalive_timer = card->u.c.kpalv_rx;
- cfg.keepalive_error_tolerance = card->u.c.kpalv_err;
- cfg.SLARP_request_timer = card->u.c.slarp_timer;
-
- if (cfg.SLARP_request_timer) {
- cfg.IP_address = 0;
- cfg.IP_netmask = 0;
-
- }else if (card->wandev.dev){
- struct net_device *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
-
- struct in_device *in_dev = dev->ip_ptr;
-
- if(in_dev != NULL) {
- struct in_ifaddr *ifa = in_dev->ifa_list;
-
- if (ifa != NULL ) {
- cfg.IP_address = ntohl(ifa->ifa_local);
- cfg.IP_netmask = ntohl(ifa->ifa_mask);
- chdlc_priv_area->IP_address = ntohl(ifa->ifa_local);
- chdlc_priv_area->IP_netmask = ntohl(ifa->ifa_mask);
- }
- }
-
- /* FIXME: We must re-think this message in next release
- if((cfg.IP_address & 0x000000FF) > 2) {
- printk(KERN_WARNING "\n");
- printk(KERN_WARNING " WARNING:%s configured with an\n",
- card->devname);
- printk(KERN_WARNING " invalid local IP address.\n");
- printk(KERN_WARNING " Slarp pragmatics will fail.\n");
- printk(KERN_WARNING " IP address should be of the\n");
- printk(KERN_WARNING " format A.B.C.1 or A.B.C.2.\n");
- }
- */
- }
-
- return chdlc_configure(card, &cfg);
-}
-
-
-/*-----------------------------------------------------------------------------
- set_asy_config() used to set asynchronous configuration options on the board
-------------------------------------------------------------------------------*/
-
-static int set_asy_config(sdla_t* card)
-{
-
- ASY_CONFIGURATION_STRUCT cfg;
- CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;
- int err;
-
- memset(&cfg, 0, sizeof(ASY_CONFIGURATION_STRUCT));
-
- if(card->wandev.clocking)
- cfg.baud_rate = card->wandev.bps;
-
- cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ?
- INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35;
-
- cfg.modem_config_options = 0;
- cfg.asy_API_options = card->u.c.api_options;
- cfg.asy_protocol_options = card->u.c.protocol_options;
- cfg.Tx_bits_per_char = card->u.c.tx_bits_per_char;
- cfg.Rx_bits_per_char = card->u.c.rx_bits_per_char;
- cfg.stop_bits = card->u.c.stop_bits;
- cfg.parity = card->u.c.parity;
- cfg.break_timer = card->u.c.break_timer;
- cfg.asy_Rx_inter_char_timer = card->u.c.inter_char_timer;
- cfg.asy_Rx_complete_length = card->u.c.rx_complete_length;
- cfg.XON_char = card->u.c.xon_char;
- cfg.XOFF_char = card->u.c.xoff_char;
- cfg.asy_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT |
- CHDLC_RX_DATA_BYTE_COUNT_STAT);
-
- mailbox->buffer_length = sizeof(ASY_CONFIGURATION_STRUCT);
- memcpy(mailbox->data, &cfg, mailbox->buffer_length);
- mailbox->command = SET_ASY_CONFIGURATION;
- err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error (card, err, mailbox);
- return err;
-}
-
-/*============================================================================
- * Enable asynchronous communications.
- */
-
-static int asy_comm_enable (sdla_t* card)
-{
-
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = ENABLE_ASY_COMMUNICATIONS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK && card->wandev.dev)
- chdlc_error(card, err, mb);
-
- if (!err)
- card->u.c.comm_enabled = 1;
-
- return err;
-}
-
-/*============================================================================
- * Process global exception condition
- */
-static int process_global_exception(sdla_t *card)
-{
- CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
- int err;
-
- mbox->buffer_length = 0;
- mbox->command = READ_GLOBAL_EXCEPTION_CONDITION;
- err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT;
-
- if(err != CMD_TIMEOUT ){
-
- switch(mbox->return_code) {
-
- case EXCEP_MODEM_STATUS_CHANGE:
-
- printk(KERN_INFO "%s: Modem status change\n",
- card->devname);
-
- switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) {
- case (DCD_HIGH):
- printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname);
- break;
- case (CTS_HIGH):
- printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname);
- break;
- case ((DCD_HIGH | CTS_HIGH)):
- printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname);
- break;
- default:
- printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname);
- break;
- }
- break;
-
- case EXCEP_TRC_DISABLED:
- printk(KERN_INFO "%s: Line trace disabled\n",
- card->devname);
- break;
-
- case EXCEP_IRQ_TIMEOUT:
- printk(KERN_INFO "%s: IRQ timeout occurred\n",
- card->devname);
- break;
-
- case 0x17:
- if (card->tty_opt){
- if (card->tty && card->tty_open){
- printk(KERN_INFO
- "%s: Modem Hangup Exception: Hanging Up!\n",
- card->devname);
- tty_hangup(card->tty);
- }
- break;
- }
-
- /* If TTY is not used just drop throught */
-
- default:
- printk(KERN_INFO "%s: Global exception %x\n",
- card->devname, mbox->return_code);
- break;
- }
- }
- return 0;
-}
-
-
-/*============================================================================
- * Process chdlc exception condition
- */
-static int process_chdlc_exception(sdla_t *card)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int err;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_EXCEPTION_CONDITION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if(err != CMD_TIMEOUT) {
-
- switch (err) {
-
- case EXCEP_LINK_ACTIVE:
- port_set_state(card, WAN_CONNECTED);
- trigger_chdlc_poll(card->wandev.dev);
- break;
-
- case EXCEP_LINK_INACTIVE_MODEM:
- port_set_state(card, WAN_DISCONNECTED);
- unconfigure_ip(card);
- trigger_chdlc_poll(card->wandev.dev);
- break;
-
- case EXCEP_LINK_INACTIVE_KPALV:
- port_set_state(card, WAN_DISCONNECTED);
- printk(KERN_INFO "%s: Keepalive timer expired.\n",
- card->devname);
- unconfigure_ip(card);
- trigger_chdlc_poll(card->wandev.dev);
- break;
-
- case EXCEP_IP_ADDRESS_DISCOVERED:
- if (configure_ip(card))
- return -1;
- break;
-
- case EXCEP_LOOPBACK_CONDITION:
- printk(KERN_INFO "%s: Loopback Condition Detected.\n",
- card->devname);
- break;
-
- case NO_CHDLC_EXCEP_COND_TO_REPORT:
- printk(KERN_INFO "%s: No exceptions reported.\n",
- card->devname);
- break;
- }
-
- }
- return 0;
-}
-
-
-/*============================================================================
- * Configure IP from SLARP negotiation
- * This adds dynamic routes when SLARP has provided valid addresses
- */
-
-static int configure_ip (sdla_t* card)
-{
- struct net_device *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area;
- char err;
-
- if (!dev)
- return 0;
-
- chdlc_priv_area = dev->priv;
-
-
- /* set to discover */
- if(card->u.c.slarp_timer != 0x00) {
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_CONFIGURATION_STRUCT *cfg;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- return -1;
- }
-
- cfg = (CHDLC_CONFIGURATION_STRUCT *)mb->data;
- chdlc_priv_area->IP_address = cfg->IP_address;
- chdlc_priv_area->IP_netmask = cfg->IP_netmask;
-
- /* Set flag to add route */
- chdlc_priv_area->route_status = ADD_ROUTE;
-
- /* The idea here is to add the route in the poll routine.
- This way, we aren't in interrupt context when adding routes */
- trigger_chdlc_poll(dev);
- }
-
- return 0;
-}
-
-
-/*============================================================================
- * Un-Configure IP negotiated by SLARP
- * This removes dynamic routes when the link becomes inactive.
- */
-
-static int unconfigure_ip (sdla_t* card)
-{
- struct net_device *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area;
-
- if (!dev)
- return 0;
-
- chdlc_priv_area= dev->priv;
-
- if (chdlc_priv_area->route_status == ROUTE_ADDED) {
-
- /* Note: If this function is called, the
- * port state has been DISCONNECTED. This state
- * change will trigger a poll_disconnected
- * function, that will check for this condition.
- */
- chdlc_priv_area->route_status = REMOVE_ROUTE;
-
- }
- return 0;
-}
-
-/*============================================================================
- * Routine to add/remove routes
- * Called like a polling routine when Routes are flagged to be added/removed.
- */
-
-static void process_route (sdla_t *card)
-{
- struct net_device *dev = card->wandev.dev;
- unsigned char port_num;
- chdlc_private_area_t *chdlc_priv_area = NULL;
- u32 local_IP_addr = 0;
- u32 remote_IP_addr = 0;
- u32 IP_netmask, IP_addr;
- int err = 0;
- struct in_device *in_dev;
- mm_segment_t fs;
- struct ifreq if_info;
- struct sockaddr_in *if_data1, *if_data2;
-
- chdlc_priv_area = dev->priv;
- port_num = card->u.c.comm_port;
-
- /* Bug Fix Mar 16 2000
- * AND the IP address to the Mask before checking
- * the last two bits. */
-
- if((chdlc_priv_area->route_status == ADD_ROUTE) &&
- ((chdlc_priv_area->IP_address & ~chdlc_priv_area->IP_netmask) > 2)) {
-
- printk(KERN_INFO "%s: Dynamic route failure.\n",card->devname);
-
- if(card->u.c.slarp_timer) {
- u32 addr_net = htonl(chdlc_priv_area->IP_address);
-
- printk(KERN_INFO "%s: Bad IP address %u.%u.%u.%u received\n",
- card->devname,
- NIPQUAD(addr_net));
- printk(KERN_INFO "%s: from remote station.\n",
- card->devname);
-
- }else{
- u32 addr_net = htonl(chdlc_priv_area->IP_address);
-
- printk(KERN_INFO "%s: Bad IP address %u.%u.%u.%u issued\n",
- card->devname,
- NIPQUAD(addr_net));
- printk(KERN_INFO "%s: to remote station. Local\n",
- card->devname);
- printk(KERN_INFO "%s: IP address must be A.B.C.1\n",
- card->devname);
- printk(KERN_INFO "%s: or A.B.C.2.\n",card->devname);
- }
-
- /* remove the route due to the IP address error condition */
- chdlc_priv_area->route_status = REMOVE_ROUTE;
- err = 1;
- }
-
- /* If we are removing a route with bad IP addressing, then use the */
- /* locally configured IP addresses */
- if((chdlc_priv_area->route_status == REMOVE_ROUTE) && err) {
-
- /* do not remove a bad route that has already been removed */
- if(chdlc_priv_area->route_removed) {
- return;
- }
-
- in_dev = dev->ip_ptr;
-
- if(in_dev != NULL) {
- struct in_ifaddr *ifa = in_dev->ifa_list;
- if (ifa != NULL ) {
- local_IP_addr = ifa->ifa_local;
- IP_netmask = ifa->ifa_mask;
- }
- }
- }else{
- /* According to Cisco HDLC, if the point-to-point address is
- A.B.C.1, then we are the opposite (A.B.C.2), and vice-versa.
- */
- IP_netmask = ntohl(chdlc_priv_area->IP_netmask);
- remote_IP_addr = ntohl(chdlc_priv_area->IP_address);
-
-
- /* If Netmask is 255.255.255.255 the local address
- * calculation will fail. Default it back to 255.255.255.0 */
- if (IP_netmask == 0xffffffff)
- IP_netmask &= 0x00ffffff;
-
- /* Bug Fix Mar 16 2000
- * AND the Remote IP address with IP netmask, instead
- * of static netmask of 255.255.255.0 */
- local_IP_addr = (remote_IP_addr & IP_netmask) +
- (~remote_IP_addr & ntohl(0x0003));
-
- if(!card->u.c.slarp_timer) {
- IP_addr = local_IP_addr;
- local_IP_addr = remote_IP_addr;
- remote_IP_addr = IP_addr;
- }
- }
-
- fs = get_fs(); /* Save file system */
- set_fs(get_ds()); /* Get user space block */
-
- /* Setup a structure for adding/removing routes */
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
-
- switch (chdlc_priv_area->route_status) {
-
- case ADD_ROUTE:
-
- if(!card->u.c.slarp_timer) {
- if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data2->sin_addr.s_addr = remote_IP_addr;
- if_data2->sin_family = AF_INET;
- err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
- } else {
- if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
- if_data1->sin_addr.s_addr = local_IP_addr;
- if_data1->sin_family = AF_INET;
- if(!(err = devinet_ioctl(SIOCSIFADDR, &if_info))){
- if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data2->sin_addr.s_addr = remote_IP_addr;
- if_data2->sin_family = AF_INET;
- err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
- }
- }
-
- if(err) {
- printk(KERN_INFO "%s: Add route %u.%u.%u.%u failed (%d)\n",
- card->devname, NIPQUAD(remote_IP_addr), err);
- } else {
- ((chdlc_private_area_t *)dev->priv)->route_status = ROUTE_ADDED;
- printk(KERN_INFO "%s: Dynamic route added.\n",
- card->devname);
- printk(KERN_INFO "%s: Local IP addr : %u.%u.%u.%u\n",
- card->devname, NIPQUAD(local_IP_addr));
- printk(KERN_INFO "%s: Remote IP addr: %u.%u.%u.%u\n",
- card->devname, NIPQUAD(remote_IP_addr));
- chdlc_priv_area->route_removed = 0;
- }
- break;
-
-
- case REMOVE_ROUTE:
-
- /* Change the local ip address of the interface to 0.
- * This will also delete the destination route.
- */
- if(!card->u.c.slarp_timer) {
- if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data2->sin_addr.s_addr = 0;
- if_data2->sin_family = AF_INET;
- err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
- } else {
- if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
- if_data1->sin_addr.s_addr = 0;
- if_data1->sin_family = AF_INET;
- err = devinet_ioctl(SIOCSIFADDR,&if_info);
-
- }
- if(err) {
- printk(KERN_INFO
- "%s: Remove route %u.%u.%u.%u failed, (err %d)\n",
- card->devname, NIPQUAD(remote_IP_addr),
- err);
- } else {
- ((chdlc_private_area_t *)dev->priv)->route_status =
- NO_ROUTE;
- printk(KERN_INFO "%s: Dynamic route removed: %u.%u.%u.%u\n",
- card->devname, NIPQUAD(local_IP_addr));
- chdlc_priv_area->route_removed = 1;
- }
- break;
- }
-
- set_fs(fs); /* Restore file system */
-
-}
-
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area)
-{
- int udp_pkt_stored = 0;
-
- if(!chdlc_priv_area->udp_pkt_lgth &&
- (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) {
- chdlc_priv_area->udp_pkt_lgth = skb->len;
- chdlc_priv_area->udp_pkt_src = udp_pkt_src;
- memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len);
- chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP;
- udp_pkt_stored = 1;
- }
-
- if(udp_pkt_src == UDP_PKT_FRM_STACK){
- dev_kfree_skb_any(skb);
- }else{
- dev_kfree_skb_any(skb);
- }
-
- return(udp_pkt_stored);
-}
-
-
-/*=============================================================================
- * Process UDP management packet.
- */
-
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area )
-{
- unsigned char *buf;
- unsigned int frames, len;
- struct sk_buff *new_skb;
- unsigned short buffer_length, real_len;
- unsigned long data_ptr;
- unsigned data_length;
- int udp_mgmt_req_valid = 1;
- CHDLC_MAILBOX_STRUCT *mb = card->mbox;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- chdlc_udp_pkt_t *chdlc_udp_pkt;
- struct timeval tv;
- int err;
- char ut_char;
-
- chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data;
-
- if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK){
-
- /* Only these commands are support for remote debugging.
- * All others are not */
- switch(chdlc_udp_pkt->cblock.command) {
-
- case READ_GLOBAL_STATISTICS:
- case READ_MODEM_STATUS:
- case READ_CHDLC_LINK_STATUS:
- case CPIPE_ROUTER_UP_TIME:
- case READ_COMMS_ERROR_STATS:
- case READ_CHDLC_OPERATIONAL_STATS:
-
- /* These two commands are executed for
- * each request */
- case READ_CHDLC_CONFIGURATION:
- case READ_CHDLC_CODE_VERSION:
- udp_mgmt_req_valid = 1;
- break;
- default:
- udp_mgmt_req_valid = 0;
- break;
- }
- }
-
- if(!udp_mgmt_req_valid) {
-
- /* set length to 0 */
- chdlc_udp_pkt->cblock.buffer_length = 0;
-
- /* set return code */
- chdlc_udp_pkt->cblock.return_code = 0xCD;
-
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Warning, Illegal UDP command attempted from network: %x\n",
- card->devname,chdlc_udp_pkt->cblock.command);
- }
-
- } else {
- unsigned long trace_status_cfg_addr = 0;
- TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct;
- TRACE_STATUS_ELEMENT_STRUCT trace_element_struct;
-
- switch(chdlc_udp_pkt->cblock.command) {
-
- case CPIPE_ENABLE_TRACING:
- if (!chdlc_priv_area->TracingEnabled) {
-
- /* OPERATE_DATALINE_MONITOR */
-
- mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
- mb->command = SET_TRACE_CONFIGURATION;
-
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_config = TRACE_ACTIVE;
- /* Trace delay mode is not used because it slows
- down transfer and results in a standoff situation
- when there is a lot of data */
-
- /* Configure the Trace based on user inputs */
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |=
- chdlc_udp_pkt->data[0];
-
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_deactivation_timer = 4000;
-
-
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- card->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = err;
- mb->buffer_length = 0;
- break;
- }
-
- /* Get the base address of the trace element list */
- mb->buffer_length = 0;
- mb->command = READ_TRACE_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if (err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- chdlc_priv_area->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = err;
- mb->buffer_length = 0;
- break;
- }
-
- trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *)
- mb->data) -> ptr_trace_stat_el_cfg_struct;
-
- sdla_peek(&card->hw, trace_status_cfg_addr,
- &trace_cfg_struct, sizeof(trace_cfg_struct));
-
- chdlc_priv_area->start_trace_addr = trace_cfg_struct.
- base_addr_trace_status_elements;
-
- chdlc_priv_area->number_trace_elements =
- trace_cfg_struct.number_trace_status_elements;
-
- chdlc_priv_area->end_trace_addr = (unsigned long)
- ((TRACE_STATUS_ELEMENT_STRUCT *)
- chdlc_priv_area->start_trace_addr +
- (chdlc_priv_area->number_trace_elements - 1));
-
- chdlc_priv_area->base_addr_trace_buffer =
- trace_cfg_struct.base_addr_trace_buffer;
-
- chdlc_priv_area->end_addr_trace_buffer =
- trace_cfg_struct.end_addr_trace_buffer;
-
- chdlc_priv_area->curr_trace_addr =
- trace_cfg_struct.next_trace_element_to_use;
-
- chdlc_priv_area->available_buffer_space = 2000 -
- sizeof(ip_pkt_t) -
- sizeof(udp_pkt_t) -
- sizeof(wp_mgmt_t) -
- sizeof(cblock_t) -
- sizeof(trace_info_t);
- }
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- mb->buffer_length = 0;
- chdlc_priv_area->TracingEnabled = 1;
- break;
-
-
- case CPIPE_DISABLE_TRACING:
- if (chdlc_priv_area->TracingEnabled) {
-
- /* OPERATE_DATALINE_MONITOR */
- mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
- mb->command = SET_TRACE_CONFIGURATION;
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_config = TRACE_INACTIVE;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- }
-
- chdlc_priv_area->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- mb->buffer_length = 0;
- break;
-
-
- case CPIPE_GET_TRACE_INFO:
-
- if (!chdlc_priv_area->TracingEnabled) {
- chdlc_udp_pkt->cblock.return_code = 1;
- mb->buffer_length = 0;
- break;
- }
-
- chdlc_udp_pkt->trace_info.ismoredata = 0x00;
- buffer_length = 0; /* offset of packet already occupied */
-
- for (frames=0; frames < chdlc_priv_area->number_trace_elements; frames++){
-
- trace_pkt_t *trace_pkt = (trace_pkt_t *)
- &chdlc_udp_pkt->data[buffer_length];
-
- sdla_peek(&card->hw, chdlc_priv_area->curr_trace_addr,
- (unsigned char *)&trace_element_struct,
- sizeof(TRACE_STATUS_ELEMENT_STRUCT));
-
- if (trace_element_struct.opp_flag == 0x00) {
- break;
- }
-
- /* get pointer to real data */
- data_ptr = trace_element_struct.ptr_data_bfr;
-
- /* See if there is actual data on the trace buffer */
- if (data_ptr){
- data_length = trace_element_struct.trace_length;
- }else{
- data_length = 0;
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- }
-
- if( (chdlc_priv_area->available_buffer_space - buffer_length)
- < ( sizeof(trace_pkt_t) + data_length) ) {
-
- /* indicate there are more frames on board & exit */
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- break;
- }
-
- trace_pkt->status = trace_element_struct.trace_type;
-
- trace_pkt->time_stamp =
- trace_element_struct.trace_time_stamp;
-
- trace_pkt->real_length =
- trace_element_struct.trace_length;
-
- /* see if we can fit the frame into the user buffer */
- real_len = trace_pkt->real_length;
-
- if (data_ptr == 0) {
- trace_pkt->data_avail = 0x00;
- } else {
- unsigned tmp = 0;
-
- /* get the data from circular buffer
- must check for end of buffer */
- trace_pkt->data_avail = 0x01;
-
- if ((data_ptr + real_len) >
- chdlc_priv_area->end_addr_trace_buffer + 1){
-
- tmp = chdlc_priv_area->end_addr_trace_buffer - data_ptr + 1;
- sdla_peek(&card->hw, data_ptr,
- trace_pkt->data,tmp);
- data_ptr = chdlc_priv_area->base_addr_trace_buffer;
- }
-
- sdla_peek(&card->hw, data_ptr,
- &trace_pkt->data[tmp], real_len - tmp);
- }
-
- /* zero the opp flag to show we got the frame */
- ut_char = 0x00;
- sdla_poke(&card->hw, chdlc_priv_area->curr_trace_addr, &ut_char, 1);
-
- /* now move onto the next frame */
- chdlc_priv_area->curr_trace_addr += sizeof(TRACE_STATUS_ELEMENT_STRUCT);
-
- /* check if we went over the last address */
- if ( chdlc_priv_area->curr_trace_addr > chdlc_priv_area->end_trace_addr ) {
- chdlc_priv_area->curr_trace_addr = chdlc_priv_area->start_trace_addr;
- }
-
- if(trace_pkt->data_avail == 0x01) {
- buffer_length += real_len - 1;
- }
-
- /* for the header */
- buffer_length += sizeof(trace_pkt_t);
-
- } /* For Loop */
-
- if (frames == chdlc_priv_area->number_trace_elements){
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- }
- chdlc_udp_pkt->trace_info.num_frames = frames;
-
- mb->buffer_length = buffer_length;
- chdlc_udp_pkt->cblock.buffer_length = buffer_length;
-
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
-
- break;
-
-
- case CPIPE_FT1_READ_STATUS:
- ((unsigned char *)chdlc_udp_pkt->data )[0] =
- flags->FT1_info_struct.parallel_port_A_input;
-
- ((unsigned char *)chdlc_udp_pkt->data )[1] =
- flags->FT1_info_struct.parallel_port_B_input;
-
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- chdlc_udp_pkt->cblock.buffer_length = 2;
- mb->buffer_length = 2;
- break;
-
- case CPIPE_ROUTER_UP_TIME:
- do_gettimeofday( &tv );
- chdlc_priv_area->router_up_time = tv.tv_sec -
- chdlc_priv_area->router_start_time;
- *(unsigned long *)&chdlc_udp_pkt->data =
- chdlc_priv_area->router_up_time;
- mb->buffer_length = sizeof(unsigned long);
- chdlc_udp_pkt->cblock.buffer_length = sizeof(unsigned long);
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- break;
-
- case FT1_MONITOR_STATUS_CTRL:
- /* Enable FT1 MONITOR STATUS */
- if ((chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_STATUS) ||
- (chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_OP_STATS)) {
-
- if( rCount++ != 0 ) {
- chdlc_udp_pkt->cblock.
- return_code = COMMAND_OK;
- mb->buffer_length = 1;
- break;
- }
- }
-
- /* Disable FT1 MONITOR STATUS */
- if( chdlc_udp_pkt->data[0] == 0) {
-
- if( --rCount != 0) {
- chdlc_udp_pkt->cblock.
- return_code = COMMAND_OK;
- mb->buffer_length = 1;
- break;
- }
- }
- goto dflt_1;
-
- default:
-dflt_1:
- /* it's a board command */
- mb->command = chdlc_udp_pkt->cblock.command;
- mb->buffer_length = chdlc_udp_pkt->cblock.buffer_length;
- if (mb->buffer_length) {
- memcpy(&mb->data, (unsigned char *) chdlc_udp_pkt->
- data, mb->buffer_length);
- }
- /* run the command on the board */
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK) {
- break;
- }
-
- /* copy the result back to our buffer */
- memcpy(&chdlc_udp_pkt->cblock, mb, sizeof(cblock_t));
-
- if (mb->buffer_length) {
- memcpy(&chdlc_udp_pkt->data, &mb->data,
- mb->buffer_length);
- }
-
- } /* end of switch */
- } /* end of else */
-
- /* Fill UDP TTL */
- chdlc_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
-
- len = reply_udp(chdlc_priv_area->udp_pkt_data, mb->buffer_length);
-
-
- if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK){
-
- /* Must check if we interrupted if_send() routine. The
- * tx buffers might be used. If so drop the packet */
- if (!test_bit(SEND_CRIT,&card->wandev.critical)) {
-
- if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) {
- ++ card->wandev.stats.tx_packets;
- card->wandev.stats.tx_bytes += len;
- }
- }
- } else {
-
- /* Pass it up the stack
- Allocate socket buffer */
- if ((new_skb = dev_alloc_skb(len)) != NULL) {
- /* copy data into new_skb */
-
- buf = skb_put(new_skb, len);
- memcpy(buf, chdlc_priv_area->udp_pkt_data, len);
-
- /* Decapsulate pkt and pass it up the protocol stack */
- new_skb->protocol = htons(ETH_P_IP);
- new_skb->dev = dev;
- new_skb->mac.raw = new_skb->data;
-
- netif_rx(new_skb);
- dev->last_rx = jiffies;
- } else {
-
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- }
- }
-
- chdlc_priv_area->udp_pkt_lgth = 0;
-
- return 0;
-}
-
-/*============================================================================
- * Initialize Receive and Transmit Buffers.
- */
-
-static void init_chdlc_tx_rx_buff( sdla_t* card)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_TX_STATUS_EL_CFG_STRUCT *tx_config;
- CHDLC_RX_STATUS_EL_CFG_STRUCT *rx_config;
- char err;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- if (card->wandev.dev){
- chdlc_error(card,err,mb);
- }
- return;
- }
-
- if(card->hw.type == SDLA_S514) {
- tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Tx_stat_el_cfg_struct));
- rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Rx_stat_el_cfg_struct));
-
- /* Setup Head and Tails for buffers */
- card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
- tx_config->base_addr_Tx_status_elements);
- card->u.c.txbuf_last =
- (CHDLC_DATA_TX_STATUS_EL_STRUCT *)
- card->u.c.txbuf_base +
- (tx_config->number_Tx_status_elements - 1);
-
- card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
- rx_config->base_addr_Rx_status_elements);
- card->u.c.rxbuf_last =
- (CHDLC_DATA_RX_STATUS_EL_STRUCT *)
- card->u.c.rxbuf_base +
- (rx_config->number_Rx_status_elements - 1);
-
- /* Set up next pointer to be used */
- card->u.c.txbuf = (void *)(card->hw.dpmbase +
- tx_config->next_Tx_status_element_to_use);
- card->u.c.rxmb = (void *)(card->hw.dpmbase +
- rx_config->next_Rx_status_element_to_use);
- }
- else {
- tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Tx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
-
- rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Rx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
-
- /* Setup Head and Tails for buffers */
- card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
- (tx_config->base_addr_Tx_status_elements % SDLA_WINDOWSIZE));
- card->u.c.txbuf_last =
- (CHDLC_DATA_TX_STATUS_EL_STRUCT *)card->u.c.txbuf_base
- + (tx_config->number_Tx_status_elements - 1);
- card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
- (rx_config->base_addr_Rx_status_elements % SDLA_WINDOWSIZE));
- card->u.c.rxbuf_last =
- (CHDLC_DATA_RX_STATUS_EL_STRUCT *)card->u.c.rxbuf_base
- + (rx_config->number_Rx_status_elements - 1);
-
- /* Set up next pointer to be used */
- card->u.c.txbuf = (void *)(card->hw.dpmbase +
- (tx_config->next_Tx_status_element_to_use % SDLA_WINDOWSIZE));
- card->u.c.rxmb = (void *)(card->hw.dpmbase +
- (rx_config->next_Rx_status_element_to_use % SDLA_WINDOWSIZE));
- }
-
- /* Setup Actual Buffer Start and end addresses */
- card->u.c.rx_base = rx_config->base_addr_Rx_buffer;
- card->u.c.rx_top = rx_config->end_addr_Rx_buffer;
-
-}
-
-/*=============================================================================
- * Perform Interrupt Test by running READ_CHDLC_CODE_VERSION command MAX_INTR
- * _TEST_COUNTER times.
- */
-static int intr_test( sdla_t* card)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int err,i;
-
- Intr_test_counter = 0;
-
- err = chdlc_set_intr_mode(card, APP_INT_ON_COMMAND_COMPLETE);
-
- if (err == CMD_OK) {
- for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) {
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CODE_VERSION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != CMD_OK)
- chdlc_error(card, err, mb);
- }
- }
- else {
- return err;
- }
-
- err = chdlc_set_intr_mode(card, 0);
-
- if (err != CMD_OK)
- return err;
-
- return 0;
-}
-
-/*==============================================================================
- * Determine what type of UDP call it is. CPIPEAB ?
- */
-static int udp_pkt_type(struct sk_buff *skb, sdla_t* card)
-{
- chdlc_udp_pkt_t *chdlc_udp_pkt = (chdlc_udp_pkt_t *)skb->data;
-
-#ifdef _WAN_UDP_DEBUG
- printk(KERN_INFO "SIG %s = %s\n\
- UPP %x = %x\n\
- PRT %x = %x\n\
- REQ %i = %i\n\
- 36 th = %x 37th = %x\n",
- chdlc_udp_pkt->wp_mgmt.signature,
- UDPMGMT_SIGNATURE,
- chdlc_udp_pkt->udp_pkt.udp_dst_port,
- ntohs(card->wandev.udp_port),
- chdlc_udp_pkt->ip_pkt.protocol,
- UDPMGMT_UDP_PROTOCOL,
- chdlc_udp_pkt->wp_mgmt.request_reply,
- UDPMGMT_REQUEST,
- skb->data[36], skb->data[37]);
-#endif
-
- if (!strncmp(chdlc_udp_pkt->wp_mgmt.signature,UDPMGMT_SIGNATURE,8) &&
- (chdlc_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) &&
- (chdlc_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
- (chdlc_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) {
-
- return UDP_CPIPE_TYPE;
-
- }else{
- return UDP_INVALID_TYPE;
- }
-}
-
-/*============================================================================
- * Set PORT state.
- */
-static void port_set_state (sdla_t *card, int state)
-{
- if (card->u.c.state != state)
- {
- switch (state)
- {
- case WAN_CONNECTED:
- printk (KERN_INFO "%s: Link connected!\n",
- card->devname);
- break;
-
- case WAN_CONNECTING:
- printk (KERN_INFO "%s: Link connecting...\n",
- card->devname);
- break;
-
- case WAN_DISCONNECTED:
- printk (KERN_INFO "%s: Link disconnected!\n",
- card->devname);
- break;
- }
-
- card->wandev.state = card->u.c.state = state;
- if (card->wandev.dev){
- struct net_device *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- chdlc_priv_area->common.state = state;
- }
- }
-}
-
-/*===========================================================================
- * config_chdlc
- *
- * Configure the chdlc protocol and enable communications.
- *
- * The if_open() function binds this function to the poll routine.
- * Therefore, this function will run every time the chdlc interface
- * is brought up. We cannot run this function from the if_open
- * because if_open does not have access to the remote IP address.
- *
- * If the communications are not enabled, proceed to configure
- * the card and enable communications.
- *
- * If the communications are enabled, it means that the interface
- * was shutdown by ether the user or driver. In this case, we
- * have to check that the IP addresses have not changed. If
- * the IP addresses have changed, we have to reconfigure the firmware
- * and update the changed IP addresses. Otherwise, just exit.
- *
- */
-
-static int config_chdlc (sdla_t *card)
-{
- struct net_device *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
- if (card->u.c.comm_enabled){
-
- /* Jun 20. 2000: NC
- * IP addresses are not used in the API mode */
-
- if ((chdlc_priv_area->ip_local_tmp != chdlc_priv_area->ip_local ||
- chdlc_priv_area->ip_remote_tmp != chdlc_priv_area->ip_remote) &&
- card->u.c.usedby == WANPIPE) {
-
- /* The IP addersses have changed, we must
- * stop the communications and reconfigure
- * the card. Reason: the firmware must know
- * the local and remote IP addresses. */
- disable_comm(card);
- port_set_state(card, WAN_DISCONNECTED);
- printk(KERN_INFO
- "%s: IP addresses changed!\n",
- card->devname);
- printk(KERN_INFO
- "%s: Restarting communications ...\n",
- card->devname);
- }else{
- /* IP addresses are the same and the link is up,
- * we don't have to do anything here. Therefore, exit */
- return 0;
- }
- }
-
- chdlc_priv_area->ip_local = chdlc_priv_area->ip_local_tmp;
- chdlc_priv_area->ip_remote = chdlc_priv_area->ip_remote_tmp;
-
-
- /* Setup the Board for asynchronous mode */
- if (card->u.c.async_mode){
-
- if (set_asy_config(card)) {
- printk (KERN_INFO "%s: Failed CHDLC Async configuration!\n",
- card->devname);
- return 0;
- }
- }else{
- /* Setup the Board for CHDLC */
- if (set_chdlc_config(card)) {
- printk (KERN_INFO "%s: Failed CHDLC configuration!\n",
- card->devname);
- return 0;
- }
- }
-
- /* Set interrupt mode and mask */
- if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME |
- APP_INT_ON_GLOBAL_EXCEP_COND |
- APP_INT_ON_TX_FRAME |
- APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
- card->devname);
- return 0;
- }
-
-
- /* Mask the Transmit and Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER);
-
- /* In TTY mode, receive interrupt will be enabled during
- * wanpipe_tty_open() operation */
- if (card->tty_opt){
- flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_RX_FRAME;
- }
-
- /* Enable communications */
- if (card->u.c.async_mode){
- if (asy_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable async commnunication!\n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return 0;
- }
- }else{
- if (chdlc_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable chdlc communications!\n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return 0;
- }
- }
-
- /* Initialize Rx/Tx buffer control fields */
- init_chdlc_tx_rx_buff(card);
- port_set_state(card, WAN_CONNECTING);
- return 0;
-}
-
-
-/*============================================================
- * chdlc_poll
- *
- * Rationale:
- * We cannot manipulate the routing tables, or
- * ip addresses withing the interrupt. Therefore
- * we must perform such actons outside an interrupt
- * at a later time.
- *
- * Description:
- * CHDLC polling routine, responsible for
- * shutting down interfaces upon disconnect
- * and adding/removing routes.
- *
- * Usage:
- * This function is executed for each CHDLC
- * interface through a tq_schedule bottom half.
- *
- * trigger_chdlc_poll() function is used to kick
- * the chldc_poll routine.
- */
-
-static void chdlc_poll(struct net_device *dev)
-{
- chdlc_private_area_t *chdlc_priv_area;
- sdla_t *card;
- u8 check_gateway=0;
- SHARED_MEMORY_INFO_STRUCT* flags;
-
-
- if (!dev || (chdlc_priv_area=dev->priv) == NULL)
- return;
-
- card = chdlc_priv_area->card;
- flags = card->u.c.flags;
-
- /* (Re)Configuraiton is in progress, stop what you are
- * doing and get out */
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- clear_bit(POLL_CRIT,&card->wandev.critical);
- return;
- }
-
- /* if_open() function has triggered the polling routine
- * to determine the configured IP addresses. Once the
- * addresses are found, trigger the chdlc configuration */
- if (test_bit(0,&chdlc_priv_area->config_chdlc)){
-
- chdlc_priv_area->ip_local_tmp = get_ip_address(dev,WAN_LOCAL_IP);
- chdlc_priv_area->ip_remote_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP);
-
- /* Jun 20. 2000 Bug Fix
- * Only perform this check in WANPIPE mode, since
- * IP addresses are not used in the API mode. */
-
- if (chdlc_priv_area->ip_local_tmp == chdlc_priv_area->ip_remote_tmp &&
- card->u.c.slarp_timer == 0x00 &&
- !card->u.c.backup &&
- card->u.c.usedby == WANPIPE){
-
- if (++chdlc_priv_area->ip_error > MAX_IP_ERRORS){
- printk(KERN_INFO "\n%s: --- WARNING ---\n",
- card->devname);
- printk(KERN_INFO
- "%s: The local IP address is the same as the\n",
- card->devname);
- printk(KERN_INFO
- "%s: Point-to-Point IP address.\n",
- card->devname);
- printk(KERN_INFO "%s: --- WARNING ---\n\n",
- card->devname);
- }else{
- clear_bit(POLL_CRIT,&card->wandev.critical);
- chdlc_priv_area->poll_delay_timer.expires = jiffies+HZ;
- add_timer(&chdlc_priv_area->poll_delay_timer);
- return;
- }
- }
-
- clear_bit(0,&chdlc_priv_area->config_chdlc);
- clear_bit(POLL_CRIT,&card->wandev.critical);
-
- chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
- flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
- return;
- }
- /* Dynamic interface implementation, as well as dynamic
- * routing. */
-
- switch (card->u.c.state){
-
- case WAN_DISCONNECTED:
-
- /* If the dynamic interface configuration is on, and interface
- * is up, then bring down the netowrk interface */
-
- if (test_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down) &&
- !test_bit(DEV_DOWN, &chdlc_priv_area->interface_down) &&
- card->wandev.dev->flags & IFF_UP){
-
- printk(KERN_INFO "%s: Interface %s down.\n",
- card->devname,card->wandev.dev->name);
- change_dev_flags(card->wandev.dev,(card->wandev.dev->flags&~IFF_UP));
- set_bit(DEV_DOWN,&chdlc_priv_area->interface_down);
- chdlc_priv_area->route_status = NO_ROUTE;
-
- }else{
- /* We need to check if the local IP address is
- * zero. If it is, we shouldn't try to remove it.
- */
-
- if (card->wandev.dev->flags & IFF_UP &&
- get_ip_address(card->wandev.dev,WAN_LOCAL_IP) &&
- chdlc_priv_area->route_status != NO_ROUTE &&
- card->u.c.slarp_timer){
-
- process_route(card);
- }
- }
- break;
-
- case WAN_CONNECTED:
-
- /* In SMP machine this code can execute before the interface
- * comes up. In this case, we must make sure that we do not
- * try to bring up the interface before dev_open() is finished */
-
-
- /* DEV_DOWN will be set only when we bring down the interface
- * for the very first time. This way we know that it was us
- * that brought the interface down */
-
- if (test_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down) &&
- test_bit(DEV_DOWN, &chdlc_priv_area->interface_down) &&
- !(card->wandev.dev->flags & IFF_UP)){
-
- printk(KERN_INFO "%s: Interface %s up.\n",
- card->devname,card->wandev.dev->name);
- change_dev_flags(card->wandev.dev,(card->wandev.dev->flags|IFF_UP));
- clear_bit(DEV_DOWN,&chdlc_priv_area->interface_down);
- check_gateway=1;
- }
-
- if (chdlc_priv_area->route_status == ADD_ROUTE &&
- card->u.c.slarp_timer){
-
- process_route(card);
- check_gateway=1;
- }
-
- if (chdlc_priv_area->gateway && check_gateway)
- add_gateway(card,dev);
-
- break;
- }
-
- clear_bit(POLL_CRIT,&card->wandev.critical);
-}
-
-/*============================================================
- * trigger_chdlc_poll
- *
- * Description:
- * Add a chdlc_poll() work entry into the keventd work queue
- * for a specific dlci/interface. This will kick
- * the fr_poll() routine at a later time.
- *
- * Usage:
- * Interrupts use this to defer a taks to
- * a polling routine.
- *
- */
-static void trigger_chdlc_poll(struct net_device *dev)
-{
- chdlc_private_area_t *chdlc_priv_area;
- sdla_t *card;
-
- if (!dev)
- return;
-
- if ((chdlc_priv_area = dev->priv)==NULL)
- return;
-
- card = chdlc_priv_area->card;
-
- if (test_and_set_bit(POLL_CRIT,&card->wandev.critical)){
- return;
- }
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- return;
- }
- schedule_work(&chdlc_priv_area->poll_work);
-}
-
-
-static void chdlc_poll_delay (unsigned long dev_ptr)
-{
- struct net_device *dev = (struct net_device *)dev_ptr;
- trigger_chdlc_poll(dev);
-}
-
-
-void s508_lock (sdla_t *card, unsigned long *smp_flags)
-{
- spin_lock_irqsave(&card->wandev.lock, *smp_flags);
- if (card->next){
- spin_lock(&card->next->wandev.lock);
- }
-}
-
-void s508_unlock (sdla_t *card, unsigned long *smp_flags)
-{
- if (card->next){
- spin_unlock(&card->next->wandev.lock);
- }
- spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-}
-
-//*********** TTY SECTION ****************
-
-static void wanpipe_tty_trigger_tx_irq(sdla_t *card)
-{
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;
- chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
-}
-
-static void wanpipe_tty_trigger_poll(sdla_t *card)
-{
- schedule_work(&card->tty_work);
-}
-
-static void tty_poll_work (void* data)
-{
- sdla_t *card = (sdla_t*)data;
- struct tty_struct *tty;
-
- if ((tty=card->tty)==NULL)
- return;
-
- tty_wakeup(tty);
-#if defined(SERIAL_HAVE_POLL_WAIT)
- wake_up_interruptible(&tty->poll_wait);
-#endif
- return;
-}
-
-static void wanpipe_tty_close(struct tty_struct *tty, struct file * filp)
-{
- sdla_t *card;
- unsigned long smp_flags;
-
- if (!tty || !tty->driver_data){
- return;
- }
-
- card = (sdla_t*)tty->driver_data;
-
- if (!card)
- return;
-
- printk(KERN_INFO "%s: Closing TTY Driver!\n",
- card->devname);
-
- /* Sanity Check */
- if (!card->tty_open)
- return;
-
- wanpipe_close(card);
- if (--card->tty_open == 0){
-
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- card->tty=NULL;
- chdlc_disable_comm_shutdown(card);
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
-
- kfree(card->tty_buf);
- card->tty_buf = NULL;
- kfree(card->tty_rx);
- card->tty_rx = NULL;
- }
- return;
-}
-static int wanpipe_tty_open(struct tty_struct *tty, struct file * filp)
-{
- unsigned long smp_flags;
- sdla_t *card;
-
- if (!tty){
- return -ENODEV;
- }
-
- if (!tty->driver_data){
- int port;
- port = tty->index;
- if ((port < 0) || (port >= NR_PORTS))
- return -ENODEV;
-
- tty->driver_data = WAN_CARD(port);
- if (!tty->driver_data)
- return -ENODEV;
- }
-
- card = (sdla_t*)tty->driver_data;
-
- if (!card){
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- card->tty=NULL;
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- return -ENODEV;
- }
-
- printk(KERN_INFO "%s: Opening TTY Driver!\n",
- card->devname);
-
- if (card->tty_open == 0){
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- card->tty=tty;
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
-
- if (!card->tty_buf){
- card->tty_buf = kmalloc(TTY_CHDLC_MAX_MTU, GFP_KERNEL);
- if (!card->tty_buf){
- card->tty_buf=NULL;
- card->tty=NULL;
- return -ENOMEM;
- }
- }
-
- if (!card->tty_rx){
- card->tty_rx = kmalloc(TTY_CHDLC_MAX_MTU, GFP_KERNEL);
- if (!card->tty_rx){
- /* Free the buffer above */
- kfree(card->tty_buf);
- card->tty_buf=NULL;
- card->tty=NULL;
- return -ENOMEM;
- }
- }
- }
-
- ++card->tty_open;
- wanpipe_open(card);
- return 0;
-}
-
-static int wanpipe_tty_write(struct tty_struct * tty, const unsigned char *buf, int count)
-{
- unsigned long smp_flags=0;
- sdla_t *card=NULL;
-
- if (!tty){
- dbg_printk(KERN_INFO "NO TTY in Write\n");
- return -ENODEV;
- }
-
- card = (sdla_t *)tty->driver_data;
-
- if (!card){
- dbg_printk(KERN_INFO "No Card in TTY Write\n");
- return -ENODEV;
- }
-
- if (count > card->wandev.mtu){
- dbg_printk(KERN_INFO "Frame too big in Write %i Max: %i\n",
- count,card->wandev.mtu);
- return -EINVAL;
- }
-
- if (card->wandev.state != WAN_CONNECTED){
- dbg_printk(KERN_INFO "Card not connected in TTY Write\n");
- return -EINVAL;
- }
-
- /* Lock the 508 Card: SMP is supported */
- if(card->hw.type != SDLA_S514){
- s508_lock(card,&smp_flags);
- }
-
- if (test_and_set_bit(SEND_CRIT,(void*)&card->wandev.critical)){
- printk(KERN_INFO "%s: Critical in TTY Write\n",
- card->devname);
-
- /* Lock the 508 Card: SMP is supported */
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
-
- return -EINVAL;
- }
-
- if (chdlc_send(card,(void*)buf,count)){
- dbg_printk(KERN_INFO "%s: Failed to send, retry later: kernel!\n",
- card->devname);
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
- wanpipe_tty_trigger_tx_irq(card);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
- return 0;
- }
- dbg_printk(KERN_INFO "%s: Packet sent OK: %i\n",card->devname,count);
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
-
- return count;
-}
-
-static void wanpipe_tty_receive(sdla_t *card, unsigned addr, unsigned int len)
-{
- unsigned offset=0;
- unsigned olen=len;
- char fp=0;
- struct tty_struct *tty;
- int i;
- struct tty_ldisc *ld;
-
- if (!card->tty_open){
- dbg_printk(KERN_INFO "%s: TTY not open during receive\n",
- card->devname);
- return;
- }
-
- if ((tty=card->tty) == NULL){
- dbg_printk(KERN_INFO "%s: No TTY on receive\n",
- card->devname);
- return;
- }
-
- if (!tty->driver_data){
- dbg_printk(KERN_INFO "%s: No Driver Data, or Flip on receive\n",
- card->devname);
- return;
- }
-
-
- if (card->u.c.async_mode){
- if ((tty->flip.count+len) >= TTY_FLIPBUF_SIZE){
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Received packet size too big: %i bytes, Max: %i!\n",
- card->devname,len,TTY_FLIPBUF_SIZE);
- }
- return;
- }
-
-
- if((addr + len) > card->u.c.rx_top + 1) {
- offset = card->u.c.rx_top - addr + 1;
-
- sdla_peek(&card->hw, addr, tty->flip.char_buf_ptr, offset);
-
- addr = card->u.c.rx_base;
- len -= offset;
-
- tty->flip.char_buf_ptr+=offset;
- tty->flip.count+=offset;
- for (i=0;i<offset;i++){
- *tty->flip.flag_buf_ptr = 0;
- tty->flip.flag_buf_ptr++;
- }
- }
-
- sdla_peek(&card->hw, addr, tty->flip.char_buf_ptr, len);
-
- tty->flip.char_buf_ptr+=len;
- card->tty->flip.count+=len;
- for (i=0;i<len;i++){
- *tty->flip.flag_buf_ptr = 0;
- tty->flip.flag_buf_ptr++;
- }
-
- tty->low_latency=1;
- tty_flip_buffer_push(tty);
- }else{
- if (!card->tty_rx){
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Receive sync buffer not available!\n",
- card->devname);
- }
- return;
- }
-
- if (len > TTY_CHDLC_MAX_MTU){
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Received packet size too big: %i bytes, Max: %i!\n",
- card->devname,len,TTY_FLIPBUF_SIZE);
- }
- return;
- }
-
-
- if((addr + len) > card->u.c.rx_top + 1) {
- offset = card->u.c.rx_top - addr + 1;
-
- sdla_peek(&card->hw, addr, card->tty_rx, offset);
-
- addr = card->u.c.rx_base;
- len -= offset;
- }
- sdla_peek(&card->hw, addr, card->tty_rx+offset, len);
- ld = tty_ldisc_ref(tty);
- if (ld) {
- if (ld->receive_buf)
- ld->receive_buf(tty,card->tty_rx,&fp,olen);
- tty_ldisc_deref(ld);
- }else{
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: NO TTY Sync line discipline!\n",
- card->devname);
- }
- }
- }
-
- dbg_printk(KERN_INFO "%s: Received Data %i\n",card->devname,olen);
- return;
-}
-
-#if 0
-static int wanpipe_tty_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- return -ENOIOCTLCMD;
-}
-#endif
-
-static void wanpipe_tty_stop(struct tty_struct *tty)
-{
- return;
-}
-
-static void wanpipe_tty_start(struct tty_struct *tty)
-{
- return;
-}
-
-static int config_tty (sdla_t *card)
-{
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
- /* Setup the Board for asynchronous mode */
- if (card->u.c.async_mode){
-
- if (set_asy_config(card)) {
- printk (KERN_INFO "%s: Failed CHDLC Async configuration!\n",
- card->devname);
- return -EINVAL;
- }
- }else{
- /* Setup the Board for CHDLC */
- if (set_chdlc_config(card)) {
- printk (KERN_INFO "%s: Failed CHDLC configuration!\n",
- card->devname);
- return -EINVAL;
- }
- }
-
- /* Set interrupt mode and mask */
- if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME |
- APP_INT_ON_GLOBAL_EXCEP_COND |
- APP_INT_ON_TX_FRAME |
- APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
- card->devname);
- return -EINVAL;
- }
-
-
- /* Mask the Transmit and Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER);
-
-
- /* Enable communications */
- if (card->u.c.async_mode){
- if (asy_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable async commnunication!\n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return -EINVAL;
- }
- }else{
- if (chdlc_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable chdlc communications!\n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return -EINVAL;
- }
- }
-
- /* Initialize Rx/Tx buffer control fields */
- init_chdlc_tx_rx_buff(card);
- port_set_state(card, WAN_CONNECTING);
- return 0;
-}
-
-
-static int change_speed(sdla_t *card, struct tty_struct *tty,
- struct termios *old_termios)
-{
- int baud, ret=0;
- unsigned cflag;
- int dbits,sbits,parity,handshaking;
-
- cflag = tty->termios->c_cflag;
-
- /* There is always one stop bit */
- sbits=WANOPT_ONE;
-
- /* Parity is defaulted to NONE */
- parity = WANOPT_NONE;
-
- handshaking=0;
-
- /* byte size and parity */
- switch (cflag & CSIZE) {
- case CS5: dbits = 5; break;
- case CS6: dbits = 6; break;
- case CS7: dbits = 7; break;
- case CS8: dbits = 8; break;
- /* Never happens, but GCC is too dumb to figure it out */
- default: dbits = 8; break;
- }
-
- /* One more stop bit should be supported, thus increment
- * the number of stop bits Max=2 */
- if (cflag & CSTOPB) {
- sbits = WANOPT_TWO;
- }
- if (cflag & PARENB) {
- parity = WANOPT_EVEN;
- }
- if (cflag & PARODD){
- parity = WANOPT_ODD;
- }
-
- /* Determine divisor based on baud rate */
- baud = tty_get_baud_rate(tty);
-
- if (!baud)
- baud = 9600; /* B0 transition handled in rs_set_termios */
-
- if (cflag & CRTSCTS) {
- handshaking|=ASY_RTS_HS_FOR_RX;
- }
-
- if (I_IGNPAR(tty))
- parity = WANOPT_NONE;
-
- if (I_IXOFF(tty)){
- handshaking|=ASY_XON_XOFF_HS_FOR_RX;
- handshaking|=ASY_XON_XOFF_HS_FOR_TX;
- }
-
- if (I_IXON(tty)){
- handshaking|=ASY_XON_XOFF_HS_FOR_RX;
- handshaking|=ASY_XON_XOFF_HS_FOR_TX;
- }
-
- if (card->u.c.async_mode){
- if (card->wandev.bps != baud)
- ret=1;
- card->wandev.bps = baud;
- }
-
- if (card->u.c.async_mode){
- if (card->u.c.protocol_options != handshaking)
- ret=1;
- card->u.c.protocol_options = handshaking;
-
- if (card->u.c.tx_bits_per_char != dbits)
- ret=1;
- card->u.c.tx_bits_per_char = dbits;
-
- if (card->u.c.rx_bits_per_char != dbits)
- ret=1;
- card->u.c.rx_bits_per_char = dbits;
-
- if (card->u.c.stop_bits != sbits)
- ret=1;
- card->u.c.stop_bits = sbits;
-
- if (card->u.c.parity != parity)
- ret=1;
- card->u.c.parity = parity;
-
- card->u.c.break_timer = 50;
- card->u.c.inter_char_timer = 10;
- card->u.c.rx_complete_length = 100;
- card->u.c.xon_char = 0xFE;
- }else{
- card->u.c.protocol_options = HDLC_STREAMING_MODE;
- }
-
- return ret;
-}
-
-
-static void wanpipe_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
- sdla_t *card;
- int err=1;
-
- if (!tty){
- return;
- }
-
- card = (sdla_t *)tty->driver_data;
-
- if (!card)
- return;
-
- if (change_speed(card, tty, old_termios) || !card->u.c.comm_enabled){
- unsigned long smp_flags;
-
- if (card->u.c.comm_enabled){
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- chdlc_disable_comm_shutdown(card);
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- }
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- err = config_tty(card);
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- if (card->u.c.async_mode){
- printk(KERN_INFO "%s: TTY Async Configuration:\n"
- " Baud =%i\n"
- " Handshaking =%s\n"
- " Tx Dbits =%i\n"
- " Rx Dbits =%i\n"
- " Parity =%s\n"
- " Stop Bits =%i\n",
- card->devname,
- card->wandev.bps,
- opt_decode[card->u.c.protocol_options],
- card->u.c.tx_bits_per_char,
- card->u.c.rx_bits_per_char,
- p_decode[card->u.c.parity] ,
- card->u.c.stop_bits);
- }else{
- printk(KERN_INFO "%s: TTY Sync Configuration:\n"
- " Baud =%i\n"
- " Protocol =HDLC_STREAMING\n",
- card->devname,card->wandev.bps);
- }
- if (!err){
- port_set_state(card,WAN_CONNECTED);
- }else{
- port_set_state(card,WAN_DISCONNECTED);
- }
- }
- return;
-}
-
-static void wanpipe_tty_put_char(struct tty_struct *tty, unsigned char ch)
-{
- sdla_t *card;
- unsigned long smp_flags=0;
-
- if (!tty){
- return;
- }
-
- card = (sdla_t *)tty->driver_data;
-
- if (!card)
- return;
-
- if (card->wandev.state != WAN_CONNECTED)
- return;
-
- if(card->hw.type != SDLA_S514)
- s508_lock(card,&smp_flags);
-
- if (test_and_set_bit(SEND_CRIT,(void*)&card->wandev.critical)){
-
- wanpipe_tty_trigger_tx_irq(card);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
- return;
- }
-
- if (chdlc_send(card,(void*)&ch,1)){
- wanpipe_tty_trigger_tx_irq(card);
- dbg_printk("%s: Failed to TX char!\n",card->devname);
- }
-
- dbg_printk("%s: Char TX OK\n",card->devname);
-
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
-
- return;
-}
-
-static void wanpipe_tty_flush_chars(struct tty_struct *tty)
-{
- return;
-}
-
-static void wanpipe_tty_flush_buffer(struct tty_struct *tty)
-{
- if (!tty)
- return;
-
-#if defined(SERIAL_HAVE_POLL_WAIT)
- wake_up_interruptible(&tty->poll_wait);
-#endif
- tty_wakeup(tty);
- return;
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void wanpipe_tty_send_xchar(struct tty_struct *tty, char ch)
-{
- return;
-}
-
-
-static int wanpipe_tty_chars_in_buffer(struct tty_struct *tty)
-{
- return 0;
-}
-
-
-static int wanpipe_tty_write_room(struct tty_struct *tty)
-{
- sdla_t *card;
-
- printk(KERN_INFO "TTY Write Room\n");
-
- if (!tty){
- return 0;
- }
-
- card = (sdla_t *)tty->driver_data;
- if (!card)
- return 0;
-
- if (card->wandev.state != WAN_CONNECTED)
- return 0;
-
- return SEC_MAX_NO_DATA_BYTES_IN_FRAME;
-}
-
-
-static int set_modem_status(sdla_t *card, unsigned char data)
-{
- CHDLC_MAILBOX_STRUCT *mb = card->mbox;
- int err;
-
- mb->buffer_length=1;
- mb->command=SET_MODEM_STATUS;
- mb->data[0]=data;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error (card, err, mb);
-
- return err;
-}
-
-static void wanpipe_tty_hangup(struct tty_struct *tty)
-{
- sdla_t *card;
- unsigned long smp_flags;
-
- printk(KERN_INFO "TTY Hangup!\n");
-
- if (!tty){
- return;
- }
-
- card = (sdla_t *)tty->driver_data;
- if (!card)
- return;
-
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- set_modem_status(card,0);
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- return;
-}
-
-static void wanpipe_tty_break(struct tty_struct *tty, int break_state)
-{
- return;
-}
-
-static void wanpipe_tty_wait_until_sent(struct tty_struct *tty, int timeout)
-{
- return;
-}
-
-static void wanpipe_tty_throttle(struct tty_struct * tty)
-{
- return;
-}
-
-static void wanpipe_tty_unthrottle(struct tty_struct * tty)
-{
- return;
-}
-
-int wanpipe_tty_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- return 0;
-}
-
-/*
- * The serial driver boot-time initialization code!
- */
-int wanpipe_tty_init(sdla_t *card)
-{
- struct serial_state * state;
-
- /* Initialize the tty_driver structure */
-
- if (card->tty_minor < 0 || card->tty_minor > NR_PORTS){
- printk(KERN_INFO "%s: Illegal Minor TTY number (0-4): %i\n",
- card->devname,card->tty_minor);
- return -EINVAL;
- }
-
- if (WAN_CARD(card->tty_minor)){
- printk(KERN_INFO "%s: TTY Minor %i, already in use\n",
- card->devname,card->tty_minor);
- return -EBUSY;
- }
-
- if (tty_init_cnt==0){
-
- printk(KERN_INFO "%s: TTY %s Driver Init: Major %i, Minor Range %i-%i\n",
- card->devname,
- card->u.c.async_mode ? "ASYNC" : "SYNC",
- WAN_TTY_MAJOR,MIN_PORT,MAX_PORT);
-
- tty_driver_mode = card->u.c.async_mode;
-
- memset(&serial_driver, 0, sizeof(struct tty_driver));
- serial_driver.magic = TTY_DRIVER_MAGIC;
- serial_driver.owner = THIS_MODULE;
- serial_driver.driver_name = "wanpipe_tty";
- serial_driver.name = "ttyW";
- serial_driver.major = WAN_TTY_MAJOR;
- serial_driver.minor_start = WAN_TTY_MINOR;
- serial_driver.num = NR_PORTS;
- serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
- serial_driver.subtype = SERIAL_TYPE_NORMAL;
-
- serial_driver.init_termios = tty_std_termios;
- serial_driver.init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- serial_driver.flags = TTY_DRIVER_REAL_RAW;
-
- serial_driver.refcount = 1; /* !@!@^#^&!! */
-
- serial_driver.open = wanpipe_tty_open;
- serial_driver.close = wanpipe_tty_close;
- serial_driver.write = wanpipe_tty_write;
-
- serial_driver.put_char = wanpipe_tty_put_char;
- serial_driver.flush_chars = wanpipe_tty_flush_chars;
- serial_driver.write_room = wanpipe_tty_write_room;
- serial_driver.chars_in_buffer = wanpipe_tty_chars_in_buffer;
- serial_driver.flush_buffer = wanpipe_tty_flush_buffer;
- //serial_driver.ioctl = wanpipe_tty_ioctl;
- serial_driver.throttle = wanpipe_tty_throttle;
- serial_driver.unthrottle = wanpipe_tty_unthrottle;
- serial_driver.send_xchar = wanpipe_tty_send_xchar;
- serial_driver.set_termios = wanpipe_tty_set_termios;
- serial_driver.stop = wanpipe_tty_stop;
- serial_driver.start = wanpipe_tty_start;
- serial_driver.hangup = wanpipe_tty_hangup;
- serial_driver.break_ctl = wanpipe_tty_break;
- serial_driver.wait_until_sent = wanpipe_tty_wait_until_sent;
- serial_driver.read_proc = wanpipe_tty_read_proc;
-
- if (tty_register_driver(&serial_driver)){
- printk(KERN_INFO "%s: Failed to register serial driver!\n",
- card->devname);
- }
- }
-
-
- /* The subsequent ports must comply to the initial configuration */
- if (tty_driver_mode != card->u.c.async_mode){
- printk(KERN_INFO "%s: Error: TTY Driver operation mode mismatch!\n",
- card->devname);
- printk(KERN_INFO "%s: The TTY driver is configured for %s!\n",
- card->devname, tty_driver_mode ? "ASYNC" : "SYNC");
- return -EINVAL;
- }
-
- tty_init_cnt++;
-
- printk(KERN_INFO "%s: Initializing TTY %s Driver Minor %i\n",
- card->devname,
- tty_driver_mode ? "ASYNC" : "SYNC",
- card->tty_minor);
-
- tty_card_map[card->tty_minor] = card;
- state = &rs_table[card->tty_minor];
-
- state->magic = SSTATE_MAGIC;
- state->line = 0;
- state->type = PORT_UNKNOWN;
- state->custom_divisor = 0;
- state->close_delay = 5*HZ/10;
- state->closing_wait = 30*HZ;
- state->icount.cts = state->icount.dsr =
- state->icount.rng = state->icount.dcd = 0;
- state->icount.rx = state->icount.tx = 0;
- state->icount.frame = state->icount.parity = 0;
- state->icount.overrun = state->icount.brk = 0;
- state->irq = card->wandev.irq;
-
- INIT_WORK(&card->tty_work, tty_poll_work, (void*)card);
- return 0;
-}
-
-
-MODULE_LICENSE("GPL");
-
-/****** End ****************************************************************/
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
deleted file mode 100644
index 7f1ce9d4333..00000000000
--- a/drivers/net/wan/sdla_fr.c
+++ /dev/null
@@ -1,5061 +0,0 @@
-/*****************************************************************************
-* sdla_fr.c WANPIPE(tm) Multiprotocol WAN Link Driver. Frame relay module.
-*
-* Author(s): Nenad Corbic <ncorbic@sangoma.com>
-* Gideon Hack
-*
-* Copyright: (c) 1995-2001 Sangoma Technologies 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.
-* ============================================================================
-* Nov 23, 2000 Nenad Corbic o Added support for 2.4.X kernels
-* Nov 15, 2000 David Rokavarg
-* Nenad Corbic o Added frame relay bridging support.
-* Original code from Mark Wells and Kristian Hoffmann has
-* been integrated into the frame relay driver.
-* Nov 13, 2000 Nenad Corbic o Added true interface type encoding option.
-* Tcpdump doesn't support Frame Relay inteface
-* types, to fix this true type option will set
-* the interface type to RAW IP mode.
-* Nov 07, 2000 Nenad Corbic o Added security features for UDP debugging:
-* Deny all and specify allowed requests.
-* Nov 06, 2000 Nenad Corbic o Wanpipe interfaces conform to raw packet interfaces.
-* Moved the if_header into the if_send() routine.
-* The if_header() was breaking the libpcap
-* support. i.e. support for tcpdump, ethereal ...
-* Oct 12. 2000 Nenad Corbic o Added error message in fr_configure
-* Jul 31, 2000 Nenad Corbic o Fixed the Router UP Time.
-* Apr 28, 2000 Nenad Corbic o Added the option to shutdown an interface
-* when the channel gets disconnected.
-* Apr 28, 2000 Nenad Corbic o Added M.Grants patch: disallow duplicate
-* interface setups.
-* Apr 25, 2000 Nenad Corbic o Added M.Grants patch: dynamically add/remove
-* new dlcis/interfaces.
-* Mar 23, 2000 Nenad Corbic o Improved task queue, bh handling.
-* Mar 16, 2000 Nenad Corbic o Added Inverse ARP support
-* Mar 13, 2000 Nenad Corbic o Added new socket API support.
-* Mar 06, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery.
-* Feb 24, 2000 Nenad Corbic o Fixed up FT1 UDP debugging problem.
-* Dev 15, 1999 Nenad Corbic o Fixed up header files for 2.0.X kernels
-*
-* Nov 08, 1999 Nenad Corbic o Combined all debug UDP calls into one function
-* o Removed the ARP support. This has to be done
-* in the next version.
-* o Only a Node can implement NO signalling.
-* Initialize DLCI during if_open() if NO
-* signalling.
-* o Took out IPX support, implement in next
-* version
-* Sep 29, 1999 Nenad Corbic o Added SMP support and changed the update
-* function to use timer interrupt.
-* o Fixed the CIR bug: Set the value of BC
-* to CIR when the CIR is enabled.
-* o Updated comments, statistics and tracing.
-* Jun 02, 1999 Gideon Hack o Updated for S514 support.
-* Sep 18, 1998 Jaspreet Singh o Updated for 2.2.X kernels.
-* Jul 31, 1998 Jaspreet Singh o Removed wpf_poll routine. The channel/DLCI
-* status is received through an event interrupt.
-* Jul 08, 1998 David Fong o Added inverse ARP support.
-* Mar 26, 1997 Jaspreet Singh o Returning return codes for failed UDP cmds.
-* Jan 28, 1997 Jaspreet Singh o Improved handling of inactive DLCIs.
-* Dec 30, 1997 Jaspreet Singh o Replaced dev_tint() with mark_bh(NET_BH)
-* Dec 16, 1997 Jaspreet Singh o Implemented Multiple IPX support.
-* Nov 26, 1997 Jaspreet Singh o Improved load sharing with multiple boards
-* o Added Cli() to protect enabling of interrupts
-* while polling is called.
-* Nov 24, 1997 Jaspreet Singh o Added counters to avoid enabling of interrupts
-* when they have been disabled by another
-* interface or routine (eg. wpf_poll).
-* Nov 06, 1997 Jaspreet Singh o Added INTR_TEST_MODE to avoid polling
-* routine disable interrupts during interrupt
-* testing.
-* Oct 20, 1997 Jaspreet Singh o Added hooks in for Router UP time.
-* Oct 16, 1997 Jaspreet Singh o The critical flag is used to maintain flow
-* control by avoiding RACE conditions. The
-* cli() and restore_flags() are taken out.
-* The fr_channel structure is appended for
-* Driver Statistics.
-* Oct 15, 1997 Farhan Thawar o updated if_send() and receive for IPX
-* Aug 29, 1997 Farhan Thawar o Removed most of the cli() and sti()
-* o Abstracted the UDP management stuff
-* o Now use tbusy and critical more intelligently
-* Jul 21, 1997 Jaspreet Singh o Can configure T391, T392, N391, N392 & N393
-* through router.conf.
-* o Protected calls to sdla_peek() by adDing
-* save_flags(), cli() and restore_flags().
-* o Added error message for Inactive DLCIs in
-* fr_event() and update_chan_state().
-* o Fixed freeing up of buffers using kfree()
-* when packets are received.
-* Jul 07, 1997 Jaspreet Singh o Added configurable TTL for UDP packets
-* o Added ability to discard multicast and
-* broadcast source addressed packets
-* Jun 27, 1997 Jaspreet Singh o Added FT1 monitor capabilities
-* New case (0x44) statement in if_send routine
-* Added a global variable rCount to keep track
-* of FT1 status enabled on the board.
-* May 29, 1997 Jaspreet Singh o Fixed major Flow Control Problem
-* With multiple boards a problem was seen where
-* the second board always stopped transmitting
-* packet after running for a while. The code
-* got into a stage where the interrupts were
-* disabled and dev->tbusy was set to 1.
-* This caused the If_send() routine to get into
-* the if clause for it(0,dev->tbusy)
-* forever.
-* The code got into this stage due to an
-* interrupt occurring within the if clause for
-* set_bit(0,dev->tbusy). Since an interrupt
-* disables furhter transmit interrupt and
-* makes dev->tbusy = 0, this effect was undone
-* by making dev->tbusy = 1 in the if clause.
-* The Fix checks to see if Transmit interrupts
-* are disabled then do not make dev->tbusy = 1
-* Introduced a global variable: int_occur and
-* added tx_int_enabled in the wan_device
-* structure.
-* May 21, 1997 Jaspreet Singh o Fixed UDP Management for multiple
-* boards.
-*
-* Apr 25, 1997 Farhan Thawar o added UDP Management stuff
-* o fixed bug in if_send() and tx_intr() to
-* sleep and wakeup all devices
-* Mar 11, 1997 Farhan Thawar Version 3.1.1
-* o fixed (+1) bug in fr508_rx_intr()
-* o changed if_send() to return 0 if
-* wandev.critical() is true
-* o free socket buffer in if_send() if
-* returning 0
-* o added tx_intr() routine
-* Jan 30, 1997 Gene Kozin Version 3.1.0
-* o implemented exec() entry point
-* o fixed a bug causing driver configured as
-* a FR switch to be stuck in WAN_
-* mode
-* Jan 02, 1997 Gene Kozin Initial version.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/workqueue.h>
-#include <linux/if_arp.h> /* ARPHRD_* defines */
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <asm/io.h> /* for inb(), outb(), etc. */
-#include <linux/time.h> /* for do_gettimeofday */
-#include <linux/in.h> /* sockaddr_in */
-#include <linux/jiffies.h> /* time_after() macro */
-#include <asm/errno.h>
-
-#include <linux/ip.h>
-#include <linux/if.h>
-
-#include <linux/if_wanpipe_common.h> /* Wanpipe Socket */
-#include <linux/if_wanpipe.h>
-
-#include <linux/sdla_fr.h> /* frame relay firmware API definitions */
-
-#include <asm/uaccess.h>
-#include <linux/inetdevice.h>
-#include <linux/netdevice.h>
-
-#include <net/route.h> /* Dynamic Route Creation */
-#include <linux/etherdevice.h> /* eth_type_trans() used for bridging */
-#include <linux/random.h>
-
-/****** Defines & Macros ****************************************************/
-
-#define MAX_CMD_RETRY 10 /* max number of firmware retries */
-
-#define FR_HEADER_LEN 8 /* max encapsulation header size */
-#define FR_CHANNEL_MTU 1500 /* unfragmented logical channel MTU */
-
-/* Q.922 frame types */
-#define Q922_UI 0x03 /* Unnumbered Info frame */
-#define Q922_XID 0xAF
-
-/* DLCI configured or not */
-#define DLCI_NOT_CONFIGURED 0x00
-#define DLCI_CONFIG_PENDING 0x01
-#define DLCI_CONFIGURED 0x02
-
-/* CIR enabled or not */
-#define CIR_ENABLED 0x00
-#define CIR_DISABLED 0x01
-
-#define FRAME_RELAY_API 1
-#define MAX_BH_BUFF 10
-
-/* For handle_IPXWAN() */
-#define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b)))
-
-/****** Data Structures *****************************************************/
-
-/* This is an extention of the 'struct device' we create for each network
- * interface to keep the rest of channel-specific data.
- */
-typedef struct fr_channel
-{
- wanpipe_common_t common;
- char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
- unsigned dlci_configured ; /* check whether configured or not */
- unsigned cir_status; /* check whether CIR enabled or not */
- unsigned dlci; /* logical channel number */
- unsigned cir; /* committed information rate */
- unsigned bc; /* committed burst size */
- unsigned be; /* excess burst size */
- unsigned mc; /* multicast support on or off */
- unsigned tx_int_status; /* Transmit Interrupt Status */
- unsigned short pkt_length; /* Packet Length */
- unsigned long router_start_time;/* Router start time in seconds */
- unsigned long tick_counter; /* counter for transmit time out */
- char dev_pending_devtint; /* interface pending dev_tint() */
- void *dlci_int_interface; /* pointer to the DLCI Interface */
- unsigned long IB_addr; /* physical address of Interface Byte */
- unsigned long state_tick; /* time of the last state change */
- unsigned char enable_IPX; /* Enable/Disable the use of IPX */
- unsigned long network_number; /* Internal Network Number for IPX*/
- sdla_t *card; /* -> owner */
- unsigned route_flag; /* Add/Rem dest addr in route tables */
- unsigned inarp; /* Inverse Arp Request status */
- long inarp_ready; /* Ready to send requests */
- int inarp_interval; /* Time between InArp Requests */
- unsigned long inarp_tick; /* InArp jiffies tick counter */
- long interface_down; /* Bring interface down on disconnect */
- struct net_device_stats ifstats; /* interface statistics */
- if_send_stat_t drvstats_if_send;
- rx_intr_stat_t drvstats_rx_intr;
- pipe_mgmt_stat_t drvstats_gen;
- unsigned long router_up_time;
-
- unsigned short transmit_length;
- struct sk_buff *delay_skb;
-
- bh_data_t *bh_head; /* Circular buffer for chdlc_bh */
- unsigned long tq_working;
- volatile int bh_write;
- volatile int bh_read;
- atomic_t bh_buff_used;
-
- /* Polling task queue. Each interface
- * has its own task queue, which is used
- * to defer events from the interrupt */
- struct work_struct fr_poll_work;
- struct timer_list fr_arp_timer;
-
- u32 ip_local;
- u32 ip_remote;
- long config_dlci;
- long unconfig_dlci;
-
- /* Whether this interface should be setup as a gateway.
- * Used by dynamic route setup code */
- u8 gateway;
-
- /* True interface type */
- u8 true_if_encoding;
- u8 fr_header[FR_HEADER_LEN];
- char fr_header_len;
-
-} fr_channel_t;
-
-/* Route Flag options */
-#define NO_ROUTE 0x00
-#define ADD_ROUTE 0x01
-#define ROUTE_ADDED 0x02
-#define REMOVE_ROUTE 0x03
-#define ARP_REQ 0x04
-
-/* inarp options */
-#define INARP_NONE 0x00
-#define INARP_REQUEST 0x01
-#define INARP_CONFIGURED 0x02
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP 0x01
-#define TMR_INT_ENABLED_UPDATE 0x02
-#define TMR_INT_ENABLED_ARP 0x04
-#define TMR_INT_ENABLED_UPDATE_STATE 0x08
-#define TMR_INT_ENABLED_CONFIG 0x10
-#define TMR_INT_ENABLED_UNCONFIG 0x20
-
-
-typedef struct dlci_status
-{
- unsigned short dlci PACKED;
- unsigned char state PACKED;
-} dlci_status_t;
-
-typedef struct dlci_IB_mapping
-{
- unsigned short dlci PACKED;
- unsigned long addr_value PACKED;
-} dlci_IB_mapping_t;
-
-/* This structure is used for DLCI list Tx interrupt mode. It is used to
- enable interrupt bit and set the packet length for transmission
- */
-typedef struct fr_dlci_interface
-{
- unsigned char gen_interrupt PACKED;
- unsigned short packet_length PACKED;
- unsigned char reserved PACKED;
-} fr_dlci_interface_t;
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/* variable for keeping track of number of interrupts generated during
- * interrupt test routine
- */
-static int Intr_test_counter;
-
-/****** Function Prototypes *************************************************/
-
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device *wandev);
-static int new_if(struct wan_device *wandev, struct net_device *dev,
- wanif_conf_t *conf);
-static int del_if(struct wan_device *wandev, struct net_device *dev);
-static void disable_comm (sdla_t *card);
-
-/* WANPIPE-specific entry points */
-static int wpf_exec(struct sdla *card, void *u_cmd, void *u_data);
-
-/* Network device interface */
-static int if_init(struct net_device *dev);
-static int if_open(struct net_device *dev);
-static int if_close(struct net_device *dev);
-
-static void if_tx_timeout(struct net_device *dev);
-
-static int if_rebuild_hdr (struct sk_buff *skb);
-
-static int if_send(struct sk_buff *skb, struct net_device *dev);
-static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev,
- struct sk_buff *skb);
-static struct net_device_stats *if_stats(struct net_device *dev);
-
-/* Interrupt handlers */
-static void fr_isr(sdla_t *card);
-static void rx_intr(sdla_t *card);
-static void tx_intr(sdla_t *card);
-static void timer_intr(sdla_t *card);
-static void spur_intr(sdla_t *card);
-
-/* Frame relay firmware interface functions */
-static int fr_read_version(sdla_t *card, char *str);
-static int fr_configure(sdla_t *card, fr_conf_t *conf);
-static int fr_dlci_configure(sdla_t *card, fr_dlc_conf_t *conf, unsigned dlci);
-static int fr_init_dlci (sdla_t *card, fr_channel_t *chan);
-static int fr_set_intr_mode (sdla_t *card, unsigned mode, unsigned mtu, unsigned short timeout);
-static int fr_comm_enable(sdla_t *card);
-static void fr_comm_disable(sdla_t *card);
-static int fr_get_err_stats(sdla_t *card);
-static int fr_get_stats(sdla_t *card);
-static int fr_add_dlci(sdla_t *card, int dlci);
-static int fr_activate_dlci(sdla_t *card, int dlci);
-static int fr_delete_dlci (sdla_t* card, int dlci);
-static int fr_issue_isf(sdla_t *card, int isf);
-static int fr_send(sdla_t *card, int dlci, unsigned char attr, int len,
- void *buf);
-static int fr_send_data_header(sdla_t *card, int dlci, unsigned char attr, int len,
- void *buf,unsigned char hdr_len);
-static unsigned int fr_send_hdr(sdla_t *card, int dlci, unsigned int offset);
-
-static int check_dlci_config (sdla_t *card, fr_channel_t *chan);
-static void initialize_rx_tx_buffers (sdla_t *card);
-
-
-/* Firmware asynchronous event handlers */
-static int fr_event(sdla_t *card, int event, fr_mbox_t *mbox);
-static int fr_modem_failure(sdla_t *card, fr_mbox_t *mbox);
-static int fr_dlci_change(sdla_t *card, fr_mbox_t *mbox);
-
-/* Miscellaneous functions */
-static int update_chan_state(struct net_device *dev);
-static void set_chan_state(struct net_device *dev, int state);
-static struct net_device *find_channel(sdla_t *card, unsigned dlci);
-static int is_tx_ready(sdla_t *card, fr_channel_t *chan);
-static unsigned int dec_to_uint(unsigned char *str, int len);
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-
-static int intr_test( sdla_t* card );
-static void init_chan_statistics( fr_channel_t* chan );
-static void init_global_statistics( sdla_t* card );
-static void read_DLCI_IB_mapping( sdla_t* card, fr_channel_t* chan );
-static int setup_for_delayed_transmit(struct net_device* dev,
- struct sk_buff *skb);
-
-struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev);
-static int check_tx_status(sdla_t *card, struct net_device *dev);
-
-/* Frame Relay Socket API */
-static void trigger_fr_bh (fr_channel_t *);
-static void fr_bh(struct net_device *dev);
-static int fr_bh_cleanup(struct net_device *dev);
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb);
-
-static void trigger_fr_poll(struct net_device *dev);
-static void fr_poll(struct net_device *dev);
-//static void add_gateway(struct net_device *dev);
-
-static void trigger_unconfig_fr(struct net_device *dev);
-static void unconfig_fr (sdla_t *);
-
-static void trigger_config_fr (sdla_t *);
-static void config_fr (sdla_t *);
-
-
-/* Inverse ARP and Dynamic routing functions */
-int process_ARP(arphdr_1490_t *ArpPacket, sdla_t *card, struct net_device *dev);
-int is_arp(void *buf);
-int send_inarp_request(sdla_t *card, struct net_device *dev);
-
-static void trigger_fr_arp(struct net_device *dev);
-static void fr_arp (unsigned long data);
-
-
-/* Udp management functions */
-static int process_udp_mgmt_pkt(sdla_t *card);
-static int udp_pkt_type( struct sk_buff *skb, sdla_t *card );
-static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, int dlci);
-
-/* IPX functions */
-static void switch_net_numbers(unsigned char *sendpacket,
- unsigned long network_number, unsigned char incoming);
-
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname,
- unsigned char enable_IPX, unsigned long network_number);
-
-/* Lock Functions: SMP supported */
-void s508_s514_unlock(sdla_t *card, unsigned long *smp_flags);
-void s508_s514_lock(sdla_t *card, unsigned long *smp_flags);
-
-unsigned short calc_checksum (char *, int);
-static int setup_fr_header(struct sk_buff *skb,
- struct net_device* dev, char op_mode);
-
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Frame relay protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup. At this
- * point adapter is completely initialized and firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the adapter data space.
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-int wpf_init(sdla_t *card, wandev_conf_t *conf)
-{
-
- int err;
- fr508_flags_t* flags;
-
- union
- {
- char str[80];
- fr_conf_t cfg;
- } u;
-
- fr_buf_info_t* buf_info;
- int i;
-
-
- printk(KERN_INFO "\n");
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_FR) {
-
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
- return -EINVAL;
-
- }
-
- /* Initialize protocol-specific fields of adapter data space */
- switch (card->hw.fwid) {
-
- case SFID_FR508:
- card->mbox = (void*)(card->hw.dpmbase +
- FR508_MBOX_OFFS);
- card->flags = (void*)(card->hw.dpmbase +
- FR508_FLAG_OFFS);
- if(card->hw.type == SDLA_S514) {
- card->mbox += FR_MB_VECTOR;
- card->flags += FR_MB_VECTOR;
- }
- card->isr = &fr_isr;
- break;
-
- default:
- return -EINVAL;
- }
-
- flags = card->flags;
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
-
- if (fr_read_version(card, NULL) || fr_read_version(card, u.str))
- return -EIO;
-
- printk(KERN_INFO "%s: running frame relay firmware v%s\n",
- card->devname, u.str);
-
- /* Adjust configuration */
- conf->mtu += FR_HEADER_LEN;
- conf->mtu = (conf->mtu >= MIN_LGTH_FR_DATA_CFG) ?
- min_t(unsigned int, conf->mtu, FR_MAX_NO_DATA_BYTES_IN_FRAME) :
- FR_CHANNEL_MTU + FR_HEADER_LEN;
-
- conf->bps = min_t(unsigned int, conf->bps, 2048000);
-
- /* Initialze the configuration structure sent to the board to zero */
- memset(&u.cfg, 0, sizeof(u.cfg));
-
- memset(card->u.f.dlci_to_dev_map, 0, sizeof(card->u.f.dlci_to_dev_map));
-
- /* Configure adapter firmware */
-
- u.cfg.mtu = conf->mtu;
- u.cfg.kbps = conf->bps / 1000;
-
- u.cfg.cir_fwd = u.cfg.cir_bwd = 16;
- u.cfg.bc_fwd = u.cfg.bc_bwd = 16;
-
- u.cfg.options = 0x0000;
- printk(KERN_INFO "%s: Global CIR enabled by Default\n", card->devname);
-
- switch (conf->u.fr.signalling) {
-
- case WANOPT_FR_ANSI:
- u.cfg.options = 0x0000;
- break;
-
- case WANOPT_FR_Q933:
- u.cfg.options |= 0x0200;
- break;
-
- case WANOPT_FR_LMI:
- u.cfg.options |= 0x0400;
- break;
-
- case WANOPT_NO:
- u.cfg.options |= 0x0800;
- break;
- default:
- printk(KERN_INFO "%s: Illegal Signalling option\n",
- card->wandev.name);
- return -EINVAL;
- }
-
-
- card->wandev.signalling = conf->u.fr.signalling;
-
- if (conf->station == WANOPT_CPE) {
-
-
- if (conf->u.fr.signalling == WANOPT_NO){
- printk(KERN_INFO
- "%s: ERROR - For NO signalling, station must be set to Node!",
- card->devname);
- return -EINVAL;
- }
-
- u.cfg.station = 0;
- u.cfg.options |= 0x8000; /* auto config DLCI */
- card->u.f.dlci_num = 0;
-
- } else {
-
- u.cfg.station = 1; /* switch emulation mode */
-
- /* For switch emulation we have to create a list of dlci(s)
- * that will be sent to be global SET_DLCI_CONFIGURATION
- * command in fr_configure() routine.
- */
-
- card->u.f.dlci_num = min_t(unsigned int, max_t(unsigned int, conf->u.fr.dlci_num, 1), 100);
-
- for ( i = 0; i < card->u.f.dlci_num; i++) {
-
- card->u.f.node_dlci[i] = (unsigned short)
- conf->u.fr.dlci[i] ? conf->u.fr.dlci[i] : 16;
-
- }
- }
-
- if (conf->clocking == WANOPT_INTERNAL)
- u.cfg.port |= 0x0001;
-
- if (conf->interface == WANOPT_RS232)
- u.cfg.port |= 0x0002;
-
- if (conf->u.fr.t391)
- u.cfg.t391 = min_t(unsigned int, conf->u.fr.t391, 30);
- else
- u.cfg.t391 = 5;
-
- if (conf->u.fr.t392)
- u.cfg.t392 = min_t(unsigned int, conf->u.fr.t392, 30);
- else
- u.cfg.t392 = 15;
-
- if (conf->u.fr.n391)
- u.cfg.n391 = min_t(unsigned int, conf->u.fr.n391, 255);
- else
- u.cfg.n391 = 2;
-
- if (conf->u.fr.n392)
- u.cfg.n392 = min_t(unsigned int, conf->u.fr.n392, 10);
- else
- u.cfg.n392 = 3;
-
- if (conf->u.fr.n393)
- u.cfg.n393 = min_t(unsigned int, conf->u.fr.n393, 10);
- else
- u.cfg.n393 = 4;
-
- if (fr_configure(card, &u.cfg))
- return -EIO;
-
- if (card->hw.type == SDLA_S514) {
-
- buf_info = (void*)(card->hw.dpmbase + FR_MB_VECTOR +
- FR508_RXBC_OFFS);
-
- card->rxmb = (void*)(buf_info->rse_next + card->hw.dpmbase);
-
- card->u.f.rxmb_base =
- (void*)(buf_info->rse_base + card->hw.dpmbase);
-
- card->u.f.rxmb_last =
- (void*)(buf_info->rse_base +
- (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) +
- card->hw.dpmbase);
- }else{
- buf_info = (void*)(card->hw.dpmbase + FR508_RXBC_OFFS);
-
- card->rxmb = (void*)(buf_info->rse_next -
- FR_MB_VECTOR + card->hw.dpmbase);
-
- card->u.f.rxmb_base =
- (void*)(buf_info->rse_base -
- FR_MB_VECTOR + card->hw.dpmbase);
-
- card->u.f.rxmb_last =
- (void*)(buf_info->rse_base +
- (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) -
- FR_MB_VECTOR + card->hw.dpmbase);
- }
-
- card->u.f.rx_base = buf_info->buf_base;
- card->u.f.rx_top = buf_info->buf_top;
-
- card->u.f.tx_interrupts_pending = 0;
-
- card->wandev.mtu = conf->mtu;
- card->wandev.bps = conf->bps;
- card->wandev.interface = conf->interface;
- card->wandev.clocking = conf->clocking;
- card->wandev.station = conf->station;
- card->poll = NULL;
- card->exec = &wpf_exec;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = &del_if;
- card->wandev.state = WAN_DISCONNECTED;
- card->wandev.ttl = conf->ttl;
- card->wandev.udp_port = conf->udp_port;
- card->disable_comm = &disable_comm;
- card->u.f.arp_dev = NULL;
-
- /* Intialize global statistics for a card */
- init_global_statistics( card );
-
- card->TracingEnabled = 0;
-
- /* Interrupt Test */
- Intr_test_counter = 0;
- card->intr_mode = INTR_TEST_MODE;
- err = intr_test( card );
-
- printk(KERN_INFO "%s: End of Interrupt Test rc=0x%x count=%i\n",
- card->devname,err,Intr_test_counter);
-
- if (err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) {
- printk(KERN_ERR "%s: Interrupt Test Failed, Counter: %i\n",
- card->devname, Intr_test_counter);
- printk(KERN_ERR "Please choose another interrupt\n");
- err = -EIO;
- return err;
- }
-
- printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n",
- card->devname, Intr_test_counter);
-
-
- /* Apr 28 2000. Nenad Corbic
- * Enable commnunications here, not in if_open or new_if, since
- * interfaces come down when the link is disconnected.
- */
-
- /* If you enable comms and then set ints, you get a Tx int as you
- * perform the SET_INT_TRIGGERS command. So, we only set int
- * triggers and then adjust the interrupt mask (to disable Tx ints)
- * before enabling comms.
- */
- if (fr_set_intr_mode(card, (FR_INTR_RXRDY | FR_INTR_TXRDY |
- FR_INTR_DLC | FR_INTR_TIMER | FR_INTR_TX_MULT_DLCIs) ,
- card->wandev.mtu, 0)) {
- return -EIO;
- }
-
- flags->imask &= ~(FR_INTR_TXRDY | FR_INTR_TIMER);
-
- if (fr_comm_enable(card)) {
- return -EIO;
- }
- wanpipe_set_state(card, WAN_CONNECTED);
- spin_lock_init(&card->u.f.if_send_lock);
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics.
- */
-static int update(struct wan_device* wandev)
-{
- volatile sdla_t* card;
- unsigned long timeout;
- fr508_flags_t* flags;
-
- /* sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
-
- if (wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- card = wandev->private;
- flags = card->flags;
-
-
- card->u.f.update_comms_stats = 1;
- card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UPDATE;
- flags->imask |= FR_INTR_TIMER;
- timeout = jiffies;
- for(;;) {
- if(card->u.f.update_comms_stats == 0)
- break;
- if (time_after(jiffies, timeout + 1 * HZ)){
- card->u.f.update_comms_stats = 0;
- return -EAGAIN;
- }
- }
-
- return 0;
-}
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return: 0 o.k.
- * < 0 failure (channel will not be created)
- */
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf)
-{
- sdla_t* card = wandev->private;
- fr_channel_t* chan;
- int dlci = 0;
- int err = 0;
-
-
- if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
-
- printk(KERN_INFO "%s: Invalid interface name!\n",
- card->devname);
- return -EINVAL;
- }
-
- /* allocate and initialize private data */
- chan = kmalloc(sizeof(fr_channel_t), GFP_KERNEL);
-
- if (chan == NULL)
- return -ENOMEM;
-
- memset(chan, 0, sizeof(fr_channel_t));
- strcpy(chan->name, conf->name);
- chan->card = card;
-
- /* verify media address */
- if (isdigit(conf->addr[0])) {
-
- dlci = dec_to_uint(conf->addr, 0);
-
- if (dlci && (dlci <= HIGHEST_VALID_DLCI)) {
-
- chan->dlci = dlci;
-
- } else {
-
- printk(KERN_ERR
- "%s: Invalid DLCI %u on interface %s!\n",
- wandev->name, dlci, chan->name);
- err = -EINVAL;
- }
-
- } else {
- printk(KERN_ERR
- "%s: Invalid media address on interface %s!\n",
- wandev->name, chan->name);
- err = -EINVAL;
- }
-
- if ((chan->true_if_encoding = conf->true_if_encoding) == WANOPT_YES){
- printk(KERN_INFO
- "%s: Enabling, true interface type encoding.\n",
- card->devname);
- }
-
-
-
- /* Setup wanpipe as a router (WANPIPE) even if it is
- * a bridged DLCI, or as an API
- */
- if (strcmp(conf->usedby, "WANPIPE") == 0 ||
- strcmp(conf->usedby, "BRIDGE") == 0 ||
- strcmp(conf->usedby, "BRIDGE_N") == 0){
-
- if(strcmp(conf->usedby, "WANPIPE") == 0){
- chan->common.usedby = WANPIPE;
-
- printk(KERN_INFO "%s: Running in WANPIPE mode.\n",
- card->devname);
-
- }else if(strcmp(conf->usedby, "BRIDGE") == 0){
-
- chan->common.usedby = BRIDGE;
-
- printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE) mode.\n",
- card->devname);
- }else if( strcmp(conf->usedby, "BRIDGE_N") == 0 ){
-
- chan->common.usedby = BRIDGE_NODE;
-
- printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE_NODE) mode.\n",
- card->devname);
- }
-
- if (!err){
- /* Dynamic interface configuration option.
- * On disconnect, if the options is selected,
- * the interface will be brought down */
- if (conf->if_down == WANOPT_YES){
- set_bit(DYN_OPT_ON,&chan->interface_down);
- printk(KERN_INFO
- "%s: Dynamic interface configuration enabled.\n",
- card->devname);
- }
- }
-
- } else if(strcmp(conf->usedby, "API") == 0){
-
- chan->common.usedby = API;
- printk(KERN_INFO "%s: Running in API mode.\n",
- wandev->name);
- }
-
- if (err) {
-
- kfree(chan);
- return err;
- }
-
- /* place cir,be,bc and other channel specific information into the
- * chan structure
- */
- if (conf->cir) {
-
- chan->cir = max_t(unsigned int, 1,
- min_t(unsigned int, conf->cir, 512));
- chan->cir_status = CIR_ENABLED;
-
-
- /* If CIR is enabled, force BC to equal CIR
- * this solves number of potential problems if CIR is
- * set and BC is not
- */
- chan->bc = chan->cir;
-
- if (conf->be){
- chan->be = max_t(unsigned int,
- 0, min_t(unsigned int, conf->be, 511));
- }else{
- conf->be = 0;
- }
-
- printk (KERN_INFO "%s: CIR enabled for DLCI %i \n",
- wandev->name,chan->dlci);
- printk (KERN_INFO "%s: CIR = %i ; BC = %i ; BE = %i\n",
- wandev->name,chan->cir,chan->bc,chan->be);
-
-
- }else{
- chan->cir_status = CIR_DISABLED;
- printk (KERN_INFO "%s: CIR disabled for DLCI %i\n",
- wandev->name,chan->dlci);
- }
-
- chan->mc = conf->mc;
-
- if (conf->inarp == WANOPT_YES){
- printk(KERN_INFO "%s: Inverse ARP Support Enabled\n",card->devname);
- chan->inarp = conf->inarp ? INARP_REQUEST : INARP_NONE;
- chan->inarp_interval = conf->inarp_interval ? conf->inarp_interval : 10;
- }else{
- printk(KERN_INFO "%s: Inverse ARP Support Disabled\n",card->devname);
- chan->inarp = INARP_NONE;
- chan->inarp_interval = 10;
- }
-
-
- chan->dlci_configured = DLCI_NOT_CONFIGURED;
-
-
- /*FIXME: IPX disabled in this WANPIPE version */
- if (conf->enable_IPX == WANOPT_YES){
- printk(KERN_INFO "%s: ERROR - This version of WANPIPE doesn't support IPX\n",
- card->devname);
- kfree(chan);
- return -EINVAL;
- }else{
- chan->enable_IPX = WANOPT_NO;
- }
-
- if (conf->network_number){
- chan->network_number = conf->network_number;
- }else{
- chan->network_number = 0xDEADBEEF;
- }
-
- chan->route_flag = NO_ROUTE;
-
- init_chan_statistics(chan);
-
- chan->transmit_length = 0;
-
- /* prepare network device data space for registration */
- strcpy(dev->name,chan->name);
-
- dev->init = &if_init;
- dev->priv = chan;
-
- /* Initialize FR Polling Task Queue
- * We need a poll routine for each network
- * interface.
- */
- INIT_WORK(&chan->fr_poll_work, (void *)fr_poll, dev);
-
- init_timer(&chan->fr_arp_timer);
- chan->fr_arp_timer.data=(unsigned long)dev;
- chan->fr_arp_timer.function = fr_arp;
-
- wandev->new_if_cnt++;
-
- /* Tells us that if this interface is a
- * gateway or not */
- if ((chan->gateway = conf->gateway) == WANOPT_YES){
- printk(KERN_INFO "%s: Interface %s is set as a gateway.\n",
- card->devname,dev->name);
- }
-
- /* M. Grant Patch Apr 28 2000
- * Disallow duplicate dlci configurations. */
- if (card->u.f.dlci_to_dev_map[chan->dlci] != NULL) {
- kfree(chan);
- return -EBUSY;
- }
-
- /* Configure this dlci at a later date, when
- * the interface comes up. i.e. when if_open()
- * executes */
- set_bit(0,&chan->config_dlci);
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/*============================================================================
- * Delete logical channel.
- */
-static int del_if(struct wan_device* wandev, struct net_device* dev)
-{
- fr_channel_t* chan = dev->priv;
- unsigned long smp_flags=0;
-
- /* This interface is dead, make sure the
- * ARP timer is stopped */
- del_timer(&chan->fr_arp_timer);
-
- /* If we are a NODE, we must unconfigure this DLCI
- * Trigger an unconfigure command that will
- * be executed in timer interrupt. We must wait
- * for the command to complete. */
- trigger_unconfig_fr(dev);
-
- lock_adapter_irq(&wandev->lock, &smp_flags);
- wandev->new_if_cnt--;
- unlock_adapter_irq(&wandev->lock, &smp_flags);
-
- return 0;
-}
-
-
-/*=====================================================================
- * disable_comm
- *
- * Description:
- * Disable communications.
- * This code runs in shutdown (sdlamain.c)
- * under critical flag. Therefore it is not
- * necessary to set a critical flag here
- *
- * Usage:
- * Commnunications are disabled only on a card
- * shutdown.
- */
-
-static void disable_comm (sdla_t *card)
-{
- printk(KERN_INFO "%s: Disabling Communications!\n",
- card->devname);
- fr_comm_disable(card);
-}
-
-/****** WANPIPE-specific entry points ***************************************/
-
-/*============================================================================
- * Execute adapter interface command.
- */
-static int wpf_exec (struct sdla* card, void* u_cmd, void* u_data)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err, len;
- fr_cmd_t cmd;
-
- if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd)))
- return -EFAULT;
-
- /* execute command */
- do
- {
- memcpy(&mbox->cmd, &cmd, sizeof(cmd));
-
- if (cmd.length){
- if( copy_from_user((void*)&mbox->data, u_data, cmd.length))
- return -EFAULT;
- }
-
- if (sdla_exec(mbox))
- err = mbox->cmd.result;
-
- else return -EIO;
-
- } while (err && retry-- && fr_event(card, err, mbox));
-
- /* return result */
- if (copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(fr_cmd_t)))
- return -EFAULT;
-
- len = mbox->cmd.length;
-
- if (len && u_data && !copy_to_user(u_data, (void*)&mbox->data, len))
- return -EFAULT;
- return 0;
-}
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration. Returning anything but zero will fail interface
- * registration.
- */
-static int if_init(struct net_device* dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- struct wan_device* wandev = &card->wandev;
-
- /* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_header = NULL;
- dev->rebuild_header = &if_rebuild_hdr;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
- dev->tx_timeout = &if_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- if (chan->common.usedby == WANPIPE || chan->common.usedby == API){
-
- /* Initialize media-specific parameters */
- if (chan->true_if_encoding){
- dev->type = ARPHRD_DLCI; /* This breaks tcpdump */
- }else{
- dev->type = ARPHRD_PPP; /* ARP h/w type */
- }
-
- dev->flags |= IFF_POINTOPOINT;
- dev->flags |= IFF_NOARP;
-
- /* Enable Multicast addressing */
- if (chan->mc == WANOPT_YES){
- dev->flags |= IFF_MULTICAST;
- }
-
- dev->mtu = wandev->mtu - FR_HEADER_LEN;
- /* For an API, the maximum number of bytes that the stack will pass
- to the driver is (dev->mtu + dev->hard_header_len). So, adjust the
- mtu so that a frame of maximum size can be transmitted by the API.
- */
- if(chan->common.usedby == API) {
- dev->mtu += (sizeof(api_tx_hdr_t) - FR_HEADER_LEN);
- }
-
- dev->hard_header_len = FR_HEADER_LEN;/* media header length */
- dev->addr_len = 2; /* hardware address length */
- *(unsigned short*)dev->dev_addr = htons(chan->dlci);
-
- /* Set transmit buffer queue length */
- dev->tx_queue_len = 100;
-
- }else{
-
- /* Setup the interface for Bridging */
- int hw_addr=0;
- ether_setup(dev);
-
- /* Use a random number to generate the MAC address */
- memcpy(dev->dev_addr, "\xFE\xFC\x00\x00\x00\x00", 6);
- get_random_bytes(&hw_addr, sizeof(hw_addr));
- *(int *)(dev->dev_addr + 2) += hw_addr;
- }
-
- /* Initialize hardware parameters (just for reference) */
- dev->irq = wandev->irq;
- dev->dma = wandev->dma;
- dev->base_addr = wandev->ioport;
- dev->mem_start = wandev->maddr;
- dev->mem_end = wandev->maddr + wandev->msize - 1;
- SET_MODULE_OWNER(dev);
-
- return 0;
-}
-
-/*============================================================================
- * Open network interface.
- * o if this is the first open, then enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device* dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- int err = 0;
- struct timeval tv;
-
- if (netif_running(dev))
- return -EBUSY;
-
- /* Initialize the task queue */
- chan->tq_working=0;
-
- INIT_WORK(&chan->common.wanpipe_work, (void *)fr_bh, dev);
-
- /* Allocate and initialize BH circular buffer */
- chan->bh_head = kmalloc((sizeof(bh_data_t)*MAX_BH_BUFF),GFP_ATOMIC);
- memset(chan->bh_head,0,(sizeof(bh_data_t)*MAX_BH_BUFF));
- atomic_set(&chan->bh_buff_used, 0);
-
- netif_start_queue(dev);
-
- wanpipe_open(card);
- do_gettimeofday( &tv );
- chan->router_start_time = tv.tv_sec;
-
- if (test_bit(0,&chan->config_dlci)){
- trigger_config_fr (card);
- }else if (chan->inarp == INARP_REQUEST){
- trigger_fr_arp(dev);
- }
-
- return err;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last open, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device* dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- if (chan->inarp == INARP_CONFIGURED) {
- chan->inarp = INARP_REQUEST;
- }
-
- netif_stop_queue(dev);
- wanpipe_close(card);
-
- return 0;
-}
-
-/*============================================================================
- * Re-build media header.
- *
- * Return: 1 physical address resolved.
- * 0 physical address not resolved
- */
-static int if_rebuild_hdr (struct sk_buff* skb)
-{
- struct net_device *dev = skb->dev;
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",
- card->devname, dev->name);
- return 1;
-}
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- /* If our device stays busy for at least 5 seconds then we will
- * kick start the device by making dev->tbusy = 0. We expect
- * that our device never stays busy more than 5 seconds. So this
- * is only used as a last resort.
- */
-
- chan->drvstats_if_send.if_send_tbusy++;
- ++chan->ifstats.collisions;
-
- printk (KERN_INFO "%s: Transmit timed out on %s\n",
- card->devname, dev->name);
- chan->drvstats_if_send.if_send_tbusy_timeout++;
- netif_wake_queue (dev);
-
-}
-
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- * transmit from overlapping.
- * o set critical flag when accessing board.
- * o check link state. If link is not up, then drop the packet.
- * o check channel status. If it's down then initiate a call.
- * o pass a packet to corresponding WAN device.
- * o free socket buffer
- *
- * Return: 0 complete (socket buffer must be freed)
- * non-0 packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- * bottom half" (with interrupts enabled).
- *
- * 2. Using netif_start_queue() and netif_stop_queue()
- * will inhibit further transmit requests from the protocol stack
- * and can be used for flow control with protocol layer.
- */
-static int if_send(struct sk_buff* skb, struct net_device* dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- int err;
- unsigned char *sendpacket;
- fr508_flags_t* adptr_flags = card->flags;
- int udp_type;
- long delay_tx_queued = 0;
- unsigned long smp_flags=0;
- unsigned char attr = 0;
-
- chan->drvstats_if_send.if_send_entry++;
-
- netif_stop_queue(dev);
-
- if (skb == NULL) {
- /* if we get here, some higher layer thinks we've missed an
- * tx-done interrupt.
- */
- printk(KERN_INFO "%s: interface %s got kicked!\n",
- card->devname, dev->name);
- chan->drvstats_if_send.if_send_skb_null ++;
-
- netif_wake_queue(dev);
- return 0;
- }
-
- /* If a peripheral task is running just drop packets */
- if (test_bit(PERI_CRIT, &card->wandev.critical)){
-
- printk(KERN_INFO "%s: Critical in if_send(): Peripheral running!\n",
- card->devname);
-
- dev_kfree_skb_any(skb);
- netif_start_queue(dev);
- return 0;
- }
-
- /* We must set the 'tbusy' flag if we already have a packet queued for
- transmission in the transmit interrupt handler. However, we must
- ensure that the transmit interrupt does not reset the 'tbusy' flag
- just before we set it, as this will result in a "transmit timeout".
- */
- set_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
- if(chan->transmit_length) {
- netif_stop_queue(dev);
- chan->tick_counter = jiffies;
- clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
- return 1;
- }
- clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
-
- /* Move the if_header() code to here. By inserting frame
- * relay header in if_header() we would break the
- * tcpdump and other packet sniffers */
- chan->fr_header_len = setup_fr_header(skb,dev,chan->common.usedby);
- if (chan->fr_header_len < 0 ){
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
-
- dev_kfree_skb_any(skb);
- netif_start_queue(dev);
- return 0;
- }
-
- sendpacket = skb->data;
-
- udp_type = udp_pkt_type(skb, card);
-
- if(udp_type != UDP_INVALID_TYPE) {
- if(store_udp_mgmt_pkt(udp_type, UDP_PKT_FRM_STACK, card, skb,
- chan->dlci)) {
- adptr_flags->imask |= FR_INTR_TIMER;
- if (udp_type == UDP_FPIPE_TYPE){
- chan->drvstats_if_send.
- if_send_PIPE_request ++;
- }
- }
- netif_start_queue(dev);
- return 0;
- }
-
- //FIXME: can we do better than sendpacket[2]?
- if ((chan->common.usedby == WANPIPE) && (sendpacket[2] == 0x45)) {
-
- /* check to see if the source IP address is a broadcast or */
- /* multicast IP address */
- if(chk_bcast_mcast_addr(card, dev, skb)){
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- dev_kfree_skb_any(skb);
- netif_start_queue(dev);
- return 0;
- }
- }
-
-
- /* Lock the S514/S508 card: SMP Supported */
- s508_s514_lock(card,&smp_flags);
-
- if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
-
- chan->drvstats_if_send.if_send_critical_non_ISR ++;
- chan->ifstats.tx_dropped ++;
- printk(KERN_INFO "%s Critical in IF_SEND: if_send() already running!\n",
- card->devname);
- goto if_send_start_and_exit;
- }
-
- /* API packet check: minimum packet size must be greater than
- * 16 byte API header */
- if((chan->common.usedby == API) && (skb->len <= sizeof(api_tx_hdr_t))) {
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
-
-
- goto if_send_start_and_exit;
-
- }else{
- /* During API transmission, get rid of the API header */
- if (chan->common.usedby == API) {
- api_tx_hdr_t* api_tx_hdr;
- api_tx_hdr = (api_tx_hdr_t*)&skb->data[0x00];
- attr = api_tx_hdr->attr;
- skb_pull(skb,sizeof(api_tx_hdr_t));
- }
- }
-
- if (card->wandev.state != WAN_CONNECTED) {
- chan->drvstats_if_send.if_send_wan_disconnected ++;
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
-
- } else if (chan->common.state != WAN_CONNECTED) {
- chan->drvstats_if_send.if_send_dlci_disconnected ++;
-
- /* Update the DLCI state in timer interrupt */
- card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UPDATE_STATE;
- adptr_flags->imask |= FR_INTR_TIMER;
-
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
-
- } else if (!is_tx_ready(card, chan)) {
- /* No tx buffers available, store for delayed transmit */
- if (!setup_for_delayed_transmit(dev, skb)){
- set_bit(1,&delay_tx_queued);
- }
- chan->drvstats_if_send.if_send_no_bfrs++;
-
- } else if (!skb->protocol) {
- /* No protocols drop packet */
- chan->drvstats_if_send.if_send_protocol_error ++;
- ++card->wandev.stats.tx_errors;
-
- } else if (test_bit(ARP_CRIT,&card->wandev.critical)){
- /* We are trying to send an ARP Packet, block IP data until
- * ARP is sent */
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
-
- } else {
- //FIXME: IPX is not implemented in this version of Frame Relay ?
- if((chan->common.usedby == WANPIPE) &&
- sendpacket[1] == 0x00 &&
- sendpacket[2] == 0x80 &&
- sendpacket[6] == 0x81 &&
- sendpacket[7] == 0x37) {
-
- if( chan->enable_IPX ) {
- switch_net_numbers(sendpacket,
- chan->network_number, 0);
- } else {
- //FIXME: Take this out when IPX is fixed
- printk(KERN_INFO
- "%s: WARNING: Unsupported IPX data in send, packet dropped\n",
- card->devname);
- }
-
- }else{
- err = fr_send_data_header(card, chan->dlci, attr, skb->len, skb->data, chan->fr_header_len);
- if (err) {
- switch(err) {
- case FRRES_CIR_OVERFLOW:
- case FRRES_BUFFER_OVERFLOW:
- if (!setup_for_delayed_transmit(dev, skb)){
- set_bit(1,&delay_tx_queued);
- }
- chan->drvstats_if_send.
- if_send_adptr_bfrs_full ++;
- break;
-
- case FRRES_TOO_LONG:
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Error: Frame too long, transmission failed %i\n",
- card->devname, (unsigned int)skb->len);
- }
- /* Drop down to default */
- default:
- chan->drvstats_if_send.
- if_send_dlci_disconnected ++;
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- break;
- }
- } else {
- chan->drvstats_if_send.
- if_send_bfr_passed_to_adptr++;
- ++chan->ifstats.tx_packets;
- ++card->wandev.stats.tx_packets;
-
- chan->ifstats.tx_bytes += skb->len;
- card->wandev.stats.tx_bytes += skb->len;
- dev->trans_start = jiffies;
- }
- }
- }
-
-if_send_start_and_exit:
-
- netif_start_queue(dev);
-
- /* If we queued the packet for transmission, we must not
- * deallocate it. The packet is unlinked from the IP stack
- * not copied. Therefore, we must keep the original packet */
- if (!test_bit(1,&delay_tx_queued)) {
- dev_kfree_skb_any(skb);
- }else{
- adptr_flags->imask |= FR_INTR_TXRDY;
- card->u.f.tx_interrupts_pending ++;
- }
-
- clear_bit(SEND_CRIT, (void*)&card->wandev.critical);
-
- s508_s514_unlock(card,&smp_flags);
-
- return 0;
-}
-
-
-
-/*============================================================================
- * Setup so that a frame can be transmitted on the occurrence of a transmit
- * interrupt.
- */
-static int setup_for_delayed_transmit(struct net_device* dev,
- struct sk_buff *skb)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- fr_dlci_interface_t* dlci_interface;
- int len = skb->len;
-
- /* Check that the dlci is properly configured,
- * before using tx interrupt */
- if (!chan->dlci_int_interface){
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: ERROR on DLCI %i: Not configured properly !\n",
- card->devname, chan->dlci);
- printk(KERN_INFO "%s: Please contact Sangoma Technologies\n",
- card->devname);
- }
- return 1;
- }
-
- dlci_interface = chan->dlci_int_interface;
-
- if(chan->transmit_length) {
- printk(KERN_INFO "%s: Big mess in setup_for_del...\n",
- card->devname);
- return 1;
- }
-
- if(len > FR_MAX_NO_DATA_BYTES_IN_FRAME) {
- //FIXME: increment some statistic */
- return 1;
- }
-
- chan->transmit_length = len;
- chan->delay_skb = skb;
-
- dlci_interface->gen_interrupt |= FR_INTR_TXRDY;
- dlci_interface->packet_length = len;
-
- /* Turn on TX interrupt at the end of if_send */
- return 0;
-}
-
-
-/*============================================================================
- * Check to see if the packet to be transmitted contains a broadcast or
- * multicast source IP address.
- * Return 0 if not broadcast/multicast address, otherwise return 1.
- */
-
-static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev,
- struct sk_buff *skb)
-{
- u32 src_ip_addr;
- u32 broadcast_ip_addr = 0;
- struct in_device *in_dev;
- fr_channel_t* chan = dev->priv;
-
- /* read the IP source address from the outgoing packet */
- src_ip_addr = *(u32 *)(skb->data + 14);
-
- /* read the IP broadcast address for the device */
- in_dev = dev->ip_ptr;
- if(in_dev != NULL) {
- struct in_ifaddr *ifa= in_dev->ifa_list;
- if(ifa != NULL)
- broadcast_ip_addr = ifa->ifa_broadcast;
- else
- return 0;
- }
-
- /* check if the IP Source Address is a Broadcast address */
- if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
- printk(KERN_INFO
- "%s: Broadcast Source Address silently discarded\n",
- card->devname);
- return 1;
- }
-
- /* check if the IP Source Address is a Multicast address */
- if((chan->mc == WANOPT_NO) && (ntohl(src_ip_addr) >= 0xE0000001) &&
- (ntohl(src_ip_addr) <= 0xFFFFFFFE)) {
- printk(KERN_INFO
- "%s: Multicast Source Address silently discarded\n",
- card->devname);
- return 1;
- }
-
- return 0;
-}
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return nothing.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
- unsigned short len, udp_length, temp, ip_length;
- unsigned long ip_temp;
- int even_bound = 0;
-
-
- fr_udp_pkt_t *fr_udp_pkt = (fr_udp_pkt_t *)data;
-
- /* Set length of packet */
- len = //sizeof(fr_encap_hdr_t)+
- sizeof(ip_pkt_t)+
- sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- mbox_len;
-
-
- /* fill in UDP reply */
- fr_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-
- /* fill in UDP length */
- udp_length = sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- mbox_len;
-
-
- /* put it on an even boundary */
- if ( udp_length & 0x0001 ) {
- udp_length += 1;
- len += 1;
- even_bound = 1;
- }
-
- temp = (udp_length<<8)|(udp_length>>8);
- fr_udp_pkt->udp_pkt.udp_length = temp;
-
- /* swap UDP ports */
- temp = fr_udp_pkt->udp_pkt.udp_src_port;
- fr_udp_pkt->udp_pkt.udp_src_port =
- fr_udp_pkt->udp_pkt.udp_dst_port;
- fr_udp_pkt->udp_pkt.udp_dst_port = temp;
-
-
-
- /* add UDP pseudo header */
- temp = 0x1100;
- *((unsigned short *)
- (fr_udp_pkt->data+mbox_len+even_bound)) = temp;
- temp = (udp_length<<8)|(udp_length>>8);
- *((unsigned short *)
- (fr_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
- /* calculate UDP checksum */
- fr_udp_pkt->udp_pkt.udp_checksum = 0;
-
- fr_udp_pkt->udp_pkt.udp_checksum =
- calc_checksum(&data[UDP_OFFSET/*+sizeof(fr_encap_hdr_t)*/],
- udp_length+UDP_OFFSET);
-
- /* fill in IP length */
- ip_length = udp_length + sizeof(ip_pkt_t);
- temp = (ip_length<<8)|(ip_length>>8);
- fr_udp_pkt->ip_pkt.total_length = temp;
-
- /* swap IP addresses */
- ip_temp = fr_udp_pkt->ip_pkt.ip_src_address;
- fr_udp_pkt->ip_pkt.ip_src_address =
- fr_udp_pkt->ip_pkt.ip_dst_address;
- fr_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
-
- /* fill in IP checksum */
- fr_udp_pkt->ip_pkt.hdr_checksum = 0;
- fr_udp_pkt->ip_pkt.hdr_checksum =
- calc_checksum(&data[/*sizeof(fr_encap_hdr_t)*/0],
- sizeof(ip_pkt_t));
-
- return len;
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
- unsigned short temp;
- unsigned long sum=0;
- int i;
-
- for( i = 0; i <len; i+=2 ) {
- memcpy(&temp,&data[i],2);
- sum += (unsigned long)temp;
- }
-
- while (sum >> 16 ) {
- sum = (sum & 0xffffUL) + (sum >> 16);
- }
-
- temp = (unsigned short)sum;
- temp = ~temp;
-
- if( temp == 0 )
- temp = 0xffff;
-
- return temp;
-}
-
-/*
- If incoming is 0 (outgoing)- if the net numbers is ours make it 0
- if incoming is 1 - if the net number is 0 make it ours
-
-*/
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming)
-{
- unsigned long pnetwork_number;
-
- pnetwork_number = (unsigned long)((sendpacket[14] << 24) +
- (sendpacket[15] << 16) + (sendpacket[16] << 8) +
- sendpacket[17]);
-
- if (!incoming) {
- /* If the destination network number is ours, make it 0 */
- if( pnetwork_number == network_number) {
- sendpacket[14] = sendpacket[15] = sendpacket[16] =
- sendpacket[17] = 0x00;
- }
- } else {
- /* If the incoming network is 0, make it ours */
- if( pnetwork_number == 0) {
- sendpacket[14] = (unsigned char)(network_number >> 24);
- sendpacket[15] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[16] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[17] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-
-
- pnetwork_number = (unsigned long)((sendpacket[26] << 24) +
- (sendpacket[27] << 16) + (sendpacket[28] << 8) +
- sendpacket[29]);
-
- if( !incoming ) {
- /* If the source network is ours, make it 0 */
- if( pnetwork_number == network_number) {
- sendpacket[26] = sendpacket[27] = sendpacket[28] =
- sendpacket[29] = 0x00;
- }
- } else {
- /* If the source network is 0, make it ours */
- if( pnetwork_number == 0 ) {
- sendpacket[26] = (unsigned char)(network_number >> 24);
- sendpacket[27] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[28] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[29] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-} /* switch_net_numbers */
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct enet_statistics.
- */
-static struct net_device_stats *if_stats(struct net_device *dev)
-{
- fr_channel_t* chan = dev->priv;
-
- if(chan == NULL)
- return NULL;
-
- return &chan->ifstats;
-}
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * fr_isr: S508 frame relay interrupt service routine.
- *
- * Description:
- * Frame relay main interrupt service route. This
- * function check the interrupt type and takes
- * the appropriate action.
- */
-static void fr_isr (sdla_t* card)
-{
- fr508_flags_t* flags = card->flags;
- char *ptr = &flags->iflag;
- int i,err;
- fr_mbox_t* mbox = card->mbox;
-
- /* This flag prevents nesting of interrupts. See sdla_isr() routine
- * in sdlamain.c. */
- card->in_isr = 1;
-
- ++card->statistics.isr_entry;
-
-
- /* All peripheral (configuraiton, re-configuration) events
- * take presidence over the ISR. Thus, retrigger */
- if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
- ++card->statistics.isr_already_critical;
- goto fr_isr_exit;
- }
-
- if(card->hw.type != SDLA_S514) {
- if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
- printk(KERN_INFO "%s: Critical while in ISR: If Send Running!\n",
- card->devname);
- ++card->statistics.isr_already_critical;
- goto fr_isr_exit;
- }
- }
-
- switch (flags->iflag) {
-
- case FR_INTR_RXRDY: /* receive interrupt */
- ++card->statistics.isr_rx;
- rx_intr(card);
- break;
-
-
- case FR_INTR_TXRDY: /* transmit interrupt */
- ++ card->statistics.isr_tx;
- tx_intr(card);
- break;
-
- case FR_INTR_READY:
- Intr_test_counter++;
- ++card->statistics.isr_intr_test;
- break;
-
- case FR_INTR_DLC: /* Event interrupt occurred */
- mbox->cmd.command = FR_READ_STATUS;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err)
- fr_event(card, err, mbox);
- break;
-
- case FR_INTR_TIMER: /* Timer interrupt */
- timer_intr(card);
- break;
-
- default:
- ++card->statistics.isr_spurious;
- spur_intr(card);
- printk(KERN_INFO "%s: Interrupt Type 0x%02X!\n",
- card->devname, flags->iflag);
-
- printk(KERN_INFO "%s: ID Bytes = ",card->devname);
- for(i = 0; i < 8; i ++)
- printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));
- printk(KERN_INFO "\n");
-
- break;
- }
-
-fr_isr_exit:
-
- card->in_isr = 0;
- flags->iflag = 0;
- return;
-}
-
-
-
-/*===========================================================
- * rx_intr Receive interrupt handler.
- *
- * Description
- * Upon receiveing an interrupt:
- * 1. Check that the firmware is in sync with
- * the driver.
- * 2. Find an appropriate network interface
- * based on the received dlci number.
- * 3. Check that the netowrk interface exists
- * and that it's setup properly.
- * 4. Copy the data into an skb buffer.
- * 5. Check the packet type and take
- * appropriate acton: UPD, API, ARP or Data.
- */
-
-static void rx_intr (sdla_t* card)
-{
- fr_rx_buf_ctl_t* frbuf = card->rxmb;
- fr508_flags_t* flags = card->flags;
- fr_channel_t* chan;
- char *ptr = &flags->iflag;
- struct sk_buff* skb;
- struct net_device* dev;
- void* buf;
- unsigned dlci, len, offs, len_incl_hdr;
- int i, udp_type;
-
-
- /* Check that firmware buffers are in sync */
- if (frbuf->flag != 0x01) {
-
- printk(KERN_INFO
- "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n",
- card->devname, (unsigned)frbuf, frbuf->flag);
-
- printk(KERN_INFO "%s: ID Bytes = ",card->devname);
- for(i = 0; i < 8; i ++)
- printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));
- printk(KERN_INFO "\n");
-
- ++card->statistics.rx_intr_corrupt_rx_bfr;
-
- /* Bug Fix: Mar 6 2000
- * If we get a corrupted mailbox, it means that driver
- * is out of sync with the firmware. There is no recovery.
- * If we don't turn off all interrupts for this card
- * the machine will crash.
- */
- printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
- printk(KERN_INFO "Please contact Sangoma Technologies !\n");
- fr_set_intr_mode(card, 0, 0, 0);
- return;
- }
-
- len = frbuf->length;
- dlci = frbuf->dlci;
- offs = frbuf->offset;
-
- /* Find the network interface for this packet */
- dev = find_channel(card, dlci);
-
-
- /* Check that the network interface is active and
- * properly setup */
- if (dev == NULL) {
- if( net_ratelimit()) {
- printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n",
- card->devname, dlci);
- }
- ++card->statistics.rx_intr_on_orphaned_DLCI;
- ++card->wandev.stats.rx_dropped;
- goto rx_done;
- }
-
- if ((chan = dev->priv) == NULL){
- if( net_ratelimit()) {
- printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n",
- card->devname, dlci);
- }
- ++card->statistics.rx_intr_on_orphaned_DLCI;
- ++card->wandev.stats.rx_dropped;
- goto rx_done;
- }
-
- skb = dev_alloc_skb(len);
-
- if (!netif_running(dev) || (skb == NULL)){
-
- ++chan->ifstats.rx_dropped;
-
- if(skb == NULL) {
- if (net_ratelimit()) {
- printk(KERN_INFO
- "%s: no socket buffers available!\n",
- card->devname);
- }
- chan->drvstats_rx_intr.rx_intr_no_socket ++;
- }
-
- if (!netif_running(dev)){
- chan->drvstats_rx_intr.
- rx_intr_dev_not_started ++;
- if (skb){
- dev_kfree_skb_any(skb);
- }
- }
- goto rx_done;
- }
-
- /* Copy data from the board into the socket buffer */
- if ((offs + len) > card->u.f.rx_top + 1) {
- unsigned tmp = card->u.f.rx_top - offs + 1;
-
- buf = skb_put(skb, tmp);
- sdla_peek(&card->hw, offs, buf, tmp);
- offs = card->u.f.rx_base;
- len -= tmp;
- }
-
- buf = skb_put(skb, len);
- sdla_peek(&card->hw, offs, buf, len);
-
-
- /* We got the packet from the bard.
- * Check the packet type and take appropriate action */
-
- udp_type = udp_pkt_type( skb, card );
-
- if(udp_type != UDP_INVALID_TYPE) {
-
- /* UDP Debug packet received, store the
- * packet and handle it in timer interrupt */
-
- skb_pull(skb, 1);
- if (wanrouter_type_trans(skb, dev)){
- if(store_udp_mgmt_pkt(udp_type,UDP_PKT_FRM_NETWORK,card,skb,dlci)){
-
- flags->imask |= FR_INTR_TIMER;
-
- if (udp_type == UDP_FPIPE_TYPE){
- ++chan->drvstats_rx_intr.rx_intr_PIPE_request;
- }
- }
- }
-
- }else if (chan->common.usedby == API) {
-
- /* We are in API mode.
- * Add an API header to the RAW packet
- * and queue it into a circular buffer.
- * Then kick the fr_bh() bottom half handler */
-
- api_rx_hdr_t* api_rx_hdr;
- chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack ++;
- chan->ifstats.rx_packets ++;
- card->wandev.stats.rx_packets ++;
-
- chan->ifstats.rx_bytes += skb->len;
- card->wandev.stats.rx_bytes += skb->len;
-
- skb_push(skb, sizeof(api_rx_hdr_t));
- api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00];
- api_rx_hdr->attr = frbuf->attr;
- api_rx_hdr->time_stamp = frbuf->tmstamp;
-
- skb->protocol = htons(ETH_P_IP);
- skb->mac.raw = skb->data;
- skb->dev = dev;
- skb->pkt_type = WAN_PACKET_DATA;
-
- bh_enqueue(dev, skb);
-
- trigger_fr_bh(chan);
-
- }else if (handle_IPXWAN(skb->data,chan->name,chan->enable_IPX, chan->network_number)){
-
- //FIXME: Frame Relay IPX is not supported, Yet !
- //if (chan->enable_IPX) {
- // fr_send(card, dlci, 0, skb->len,skb->data);
- //}
- dev_kfree_skb_any(skb);
-
- } else if (is_arp(skb->data)) {
-
- /* ARP support enabled Mar 16 2000
- * Process incoming ARP reply/request, setup
- * dynamic routes. */
-
- if (process_ARP((arphdr_1490_t *)skb->data, card, dev)) {
- if (net_ratelimit()){
- printk (KERN_INFO
- "%s: Error processing ARP Packet.\n",
- card->devname);
- }
- }
- dev_kfree_skb_any(skb);
-
- } else if (skb->data[0] != 0x03) {
-
- if (net_ratelimit()) {
- printk(KERN_INFO "%s: Non IETF packet discarded.\n",
- card->devname);
- }
- dev_kfree_skb_any(skb);
-
- } else {
-
- len_incl_hdr = skb->len;
- /* Decapsulate packet and pass it up the
- protocol stack */
- skb->dev = dev;
-
- if (chan->common.usedby == BRIDGE || chan->common.usedby == BRIDGE_NODE){
-
- /* Make sure it's an Ethernet frame, otherwise drop it */
- if (!memcmp(skb->data, "\x03\x00\x80\x00\x80\xC2\x00\x07", 8)) {
- skb_pull(skb, 8);
- skb->protocol=eth_type_trans(skb,dev);
- }else{
- ++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack;
- ++chan->ifstats.rx_errors;
- ++card->wandev.stats.rx_errors;
- goto rx_done;
- }
- }else{
-
- /* remove hardware header */
- buf = skb_pull(skb, 1);
-
- if (!wanrouter_type_trans(skb, dev)) {
-
- /* can't decapsulate packet */
- dev_kfree_skb_any(skb);
-
- ++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack;
- ++chan->ifstats.rx_errors;
- ++card->wandev.stats.rx_errors;
- goto rx_done;
- }
- skb->mac.raw = skb->data;
- }
-
-
- /* Send a packet up the IP stack */
- skb->dev->last_rx = jiffies;
- netif_rx(skb);
- ++chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack;
- ++chan->ifstats.rx_packets;
- ++card->wandev.stats.rx_packets;
-
- chan->ifstats.rx_bytes += len_incl_hdr;
- card->wandev.stats.rx_bytes += len_incl_hdr;
- }
-
-rx_done:
-
- /* Release buffer element and calculate a pointer to the next one */
- frbuf->flag = 0;
- card->rxmb = ++frbuf;
- if ((void*)frbuf > card->u.f.rxmb_last)
- card->rxmb = card->u.f.rxmb_base;
-
-}
-
-/*==================================================================
- * tx_intr: Transmit interrupt handler.
- *
- * Rationale:
- * If the board is busy transmitting, if_send() will
- * buffers a single packet and turn on
- * the tx interrupt. Tx interrupt will be called
- * by the board, once the firmware can send more
- * data. Thus, no polling is required.
- *
- * Description:
- * Tx interrupt is called for each
- * configured dlci channel. Thus:
- * 1. Obtain the netowrk interface based on the
- * dlci number.
- * 2. Check that network interface is up and
- * properly setup.
- * 3. Check for a buffered packet.
- * 4. Transmit the packet.
- * 5. If we are in WANPIPE mode, mark the
- * NET_BH handler.
- * 6. If we are in API mode, kick
- * the AF_WANPIPE socket for more data.
- *
- */
-static void tx_intr(sdla_t *card)
-{
- fr508_flags_t* flags = card->flags;
- fr_tx_buf_ctl_t* bctl;
- struct net_device* dev;
- fr_channel_t* chan;
-
- if(card->hw.type == SDLA_S514){
- bctl = (void*)(flags->tse_offs + card->hw.dpmbase);
- }else{
- bctl = (void*)(flags->tse_offs - FR_MB_VECTOR +
- card->hw.dpmbase);
- }
-
- /* Find the structure and make it unbusy */
- dev = find_channel(card, flags->dlci);
- if (dev == NULL){
- printk(KERN_INFO "NO DEV IN TX Interrupt\n");
- goto end_of_tx_intr;
- }
-
- if ((chan = dev->priv) == NULL){
- printk(KERN_INFO "NO CHAN IN TX Interrupt\n");
- goto end_of_tx_intr;
- }
-
- if(!chan->transmit_length || !chan->delay_skb) {
- printk(KERN_INFO "%s: tx int error - transmit length zero\n",
- card->wandev.name);
- goto end_of_tx_intr;
- }
-
- /* If the 'if_send()' procedure is currently checking the 'tbusy'
- status, then we cannot transmit. Instead, we configure the microcode
- so as to re-issue this transmit interrupt at a later stage.
- */
- if (test_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical)) {
-
- fr_dlci_interface_t* dlci_interface = chan->dlci_int_interface;
- bctl->flag = 0xA0;
- dlci_interface->gen_interrupt |= FR_INTR_TXRDY;
- return;
-
- }else{
- bctl->dlci = flags->dlci;
- bctl->length = chan->transmit_length+chan->fr_header_len;
- sdla_poke(&card->hw,
- fr_send_hdr(card,bctl->dlci,bctl->offset),
- chan->delay_skb->data,
- chan->delay_skb->len);
- bctl->flag = 0xC0;
-
- ++chan->ifstats.tx_packets;
- ++card->wandev.stats.tx_packets;
- chan->ifstats.tx_bytes += chan->transmit_length;
- card->wandev.stats.tx_bytes += chan->transmit_length;
-
- /* We must free an sk buffer, which we used
- * for delayed transmission; Otherwise, the sock
- * will run out of memory */
- dev_kfree_skb_any(chan->delay_skb);
-
- chan->delay_skb = NULL;
- chan->transmit_length = 0;
-
- dev->trans_start = jiffies;
-
- if (netif_queue_stopped(dev)){
- /* If using API, than wakeup socket BH handler */
- if (chan->common.usedby == API){
- netif_start_queue(dev);
- wakeup_sk_bh(dev);
- }else{
- netif_wake_queue(dev);
- }
- }
- }
-
-end_of_tx_intr:
-
- /* if any other interfaces have transmit interrupts pending,
- * do not disable the global transmit interrupt */
- if(!(-- card->u.f.tx_interrupts_pending))
- flags->imask &= ~FR_INTR_TXRDY;
-
-
-}
-
-
-/*============================================================================
- * timer_intr: Timer interrupt handler.
- *
- * Rationale:
- * All commans must be executed within the timer
- * interrupt since no two commands should execute
- * at the same time.
- *
- * Description:
- * The timer interrupt is used to:
- * 1. Processing udp calls from 'fpipemon'.
- * 2. Processing update calls from /proc file system
- * 3. Reading board-level statistics for
- * updating the proc file system.
- * 4. Sending inverse ARP request packets.
- * 5. Configure a dlci/channel.
- * 6. Unconfigure a dlci/channel. (Node only)
- */
-
-static void timer_intr(sdla_t *card)
-{
- fr508_flags_t* flags = card->flags;
-
- /* UDP Debuging: fpipemon call */
- if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UDP) {
- if(card->u.f.udp_type == UDP_FPIPE_TYPE) {
- if(process_udp_mgmt_pkt(card)) {
- card->u.f.timer_int_enabled &=
- ~TMR_INT_ENABLED_UDP;
- }
- }
- }
-
- /* /proc update call : triggered from update() */
- if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UPDATE) {
- fr_get_err_stats(card);
- fr_get_stats(card);
- card->u.f.update_comms_stats = 0;
- card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE;
- }
-
- /* Update the channel state call. This is call is
- * triggered by if_send() function */
- if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UPDATE_STATE){
- struct net_device *dev;
- if (card->wandev.state == WAN_CONNECTED){
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)){
- fr_channel_t *chan = dev->priv;
- if (chan->common.state != WAN_CONNECTED){
- update_chan_state(dev);
- }
- }
- }
- card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE_STATE;
- }
-
- /* configure a dlci/channel */
- if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_CONFIG){
- config_fr(card);
- card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG;
- }
-
- /* unconfigure a dlci/channel */
- if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UNCONFIG){
- unconfig_fr(card);
- card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UNCONFIG;
- }
-
-
- /* Transmit ARP packets */
- if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_ARP){
- int i=0;
- struct net_device *dev;
-
- if (card->u.f.arp_dev == NULL)
- card->u.f.arp_dev = card->wandev.dev;
-
- dev = card->u.f.arp_dev;
-
- for (;;){
-
- fr_channel_t *chan = dev->priv;
-
- /* If the interface is brought down cancel sending In-ARPs */
- if (!(dev->flags&IFF_UP)){
- clear_bit(0,&chan->inarp_ready);
- }
-
- if (test_bit(0,&chan->inarp_ready)){
-
- if (check_tx_status(card,dev)){
- set_bit(ARP_CRIT,&card->wandev.critical);
- break;
- }
-
- if (!send_inarp_request(card,dev)){
- trigger_fr_arp(dev);
- chan->inarp_tick = jiffies;
- }
-
- clear_bit(0,&chan->inarp_ready);
- dev = move_dev_to_next(card,dev);
- break;
- }
- dev = move_dev_to_next(card,dev);
-
- if (++i == card->wandev.new_if_cnt){
- card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_ARP;
- break;
- }
- }
- card->u.f.arp_dev = dev;
- }
-
- if(!card->u.f.timer_int_enabled)
- flags->imask &= ~FR_INTR_TIMER;
-}
-
-
-/*============================================================================
- * spur_intr: Spurious interrupt handler.
- *
- * Description:
- * We don't know this interrupt.
- * Print a warning.
- */
-
-static void spur_intr (sdla_t* card)
-{
- if (net_ratelimit()){
- printk(KERN_INFO "%s: spurious interrupt!\n", card->devname);
- }
-}
-
-
-//FIXME: Fix the IPX in next version
-/*===========================================================================
- * Return 0 for non-IPXWAN packet
- * 1 for IPXWAN packet or IPX is not enabled!
- * FIXME: Use a IPX structure here not offsets
- */
-static int handle_IPXWAN(unsigned char *sendpacket,
- char *devname, unsigned char enable_IPX,
- unsigned long network_number)
-{
- int i;
-
- if( sendpacket[1] == 0x00 && sendpacket[2] == 0x80 &&
- sendpacket[6] == 0x81 && sendpacket[7] == 0x37) {
-
- /* It's an IPX packet */
- if (!enable_IPX){
- /* Return 1 so we don't pass it up the stack. */
- //FIXME: Take this out when IPX is fixed
- if (net_ratelimit()){
- printk (KERN_INFO
- "%s: WARNING: Unsupported IPX packet received and dropped\n",
- devname);
- }
- return 1;
- }
- } else {
- /* It's not IPX so return and pass it up the stack. */
- return 0;
- }
-
- if( sendpacket[24] == 0x90 && sendpacket[25] == 0x04){
- /* It's IPXWAN */
-
- if( sendpacket[10] == 0x02 && sendpacket[42] == 0x00){
-
- /* It's a timer request packet */
- printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",
- devname);
-
- /* Go through the routing options and answer no to every
- * option except Unnumbered RIP/SAP
- */
- for(i = 49; sendpacket[i] == 0x00; i += 5){
- /* 0x02 is the option for Unnumbered RIP/SAP */
- if( sendpacket[i + 4] != 0x02){
- sendpacket[i + 1] = 0;
- }
- }
-
- /* Skip over the extended Node ID option */
- if( sendpacket[i] == 0x04 ){
- i += 8;
- }
-
- /* We also want to turn off all header compression opt.
- */
- for(; sendpacket[i] == 0x80 ;){
- sendpacket[i + 1] = 0;
- i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4;
- }
-
- /* Set the packet type to timer response */
- sendpacket[42] = 0x01;
-
- printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",
- devname);
-
- } else if( sendpacket[42] == 0x02 ){
-
- /* This is an information request packet */
- printk(KERN_INFO
- "%s: Received IPXWAN Information Request packet\n",
- devname);
-
- /* Set the packet type to information response */
- sendpacket[42] = 0x03;
-
- /* Set the router name */
- sendpacket[59] = 'F';
- sendpacket[60] = 'P';
- sendpacket[61] = 'I';
- sendpacket[62] = 'P';
- sendpacket[63] = 'E';
- sendpacket[64] = '-';
- sendpacket[65] = CVHexToAscii(network_number >> 28);
- sendpacket[66] = CVHexToAscii((network_number & 0x0F000000)>> 24);
- sendpacket[67] = CVHexToAscii((network_number & 0x00F00000)>> 20);
- sendpacket[68] = CVHexToAscii((network_number & 0x000F0000)>> 16);
- sendpacket[69] = CVHexToAscii((network_number & 0x0000F000)>> 12);
- sendpacket[70] = CVHexToAscii((network_number & 0x00000F00)>> 8);
- sendpacket[71] = CVHexToAscii((network_number & 0x000000F0)>> 4);
- sendpacket[72] = CVHexToAscii(network_number & 0x0000000F);
- for(i = 73; i < 107; i+= 1)
- {
- sendpacket[i] = 0;
- }
-
- printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",
- devname);
- } else {
-
- printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname);
- return 0;
- }
-
- /* Set the WNodeID to our network address */
- sendpacket[43] = (unsigned char)(network_number >> 24);
- sendpacket[44] = (unsigned char)((network_number & 0x00FF0000) >> 16);
- sendpacket[45] = (unsigned char)((network_number & 0x0000FF00) >> 8);
- sendpacket[46] = (unsigned char)(network_number & 0x000000FF);
-
- return 1;
- }
-
- /* If we get here, it's an IPX-data packet so it'll get passed up the
- * stack.
- * switch the network numbers
- */
- switch_net_numbers(sendpacket, network_number ,1);
- return 0;
-}
-/*============================================================================
- * process_route
- *
- * Rationale:
- * If the interface goes down, or we receive an ARP request,
- * we have to change the network interface ip addresses.
- * This cannot be done within the interrupt.
- *
- * Description:
- *
- * This routine is called as a polling routine to dynamically
- * add/delete routes negotiated by inverse ARP. It is in this
- * "task" because we don't want routes to be added while in
- * interrupt context.
- *
- * Usage:
- * This function is called by fr_poll() polling funtion.
- */
-
-static void process_route(struct net_device *dev)
-{
- fr_channel_t *chan = dev->priv;
- sdla_t *card = chan->card;
-
- struct ifreq if_info;
- struct sockaddr_in *if_data;
- mm_segment_t fs = get_fs();
- u32 ip_tmp;
- int err;
-
-
- switch(chan->route_flag){
-
- case ADD_ROUTE:
-
- /* Set remote addresses */
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
-
- set_fs(get_ds()); /* get user space block */
-
- if_data = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data->sin_addr.s_addr = chan->ip_remote;
- if_data->sin_family = AF_INET;
- err = devinet_ioctl( SIOCSIFDSTADDR, &if_info );
-
- set_fs(fs); /* restore old block */
-
- if (err) {
- printk(KERN_INFO
- "%s: Route Add failed. Error: %d\n",
- card->devname,err);
- printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n",
- chan->name, NIPQUAD(chan->ip_remote));
-
- }else {
- printk(KERN_INFO "%s: Route Added Successfully: %u.%u.%u.%u\n",
- card->devname,NIPQUAD(chan->ip_remote));
- chan->route_flag = ROUTE_ADDED;
- }
- break;
-
- case REMOVE_ROUTE:
-
- /* Set remote addresses */
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
-
- ip_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP);
-
- set_fs(get_ds()); /* get user space block */
-
- if_data = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data->sin_addr.s_addr = 0;
- if_data->sin_family = AF_INET;
- err = devinet_ioctl( SIOCSIFDSTADDR, &if_info );
-
- set_fs(fs);
-
- if (err) {
- printk(KERN_INFO
- "%s: Deleting of route failed. Error: %d\n",
- card->devname,err);
- printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n",
- dev->name,NIPQUAD(chan->ip_remote) );
-
- } else {
- printk(KERN_INFO "%s: Route Removed Sucessfuly: %u.%u.%u.%u\n",
- card->devname,NIPQUAD(ip_tmp));
- chan->route_flag = NO_ROUTE;
- }
- break;
-
- } /* Case Statement */
-
-}
-
-
-
-/****** Frame Relay Firmware-Specific Functions *****************************/
-
-/*============================================================================
- * Read firmware code version.
- * o fill string str with firmware version info.
- */
-static int fr_read_version (sdla_t* card, char* str)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- mbox->cmd.command = FR_READ_CODE_VERSION;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if (!err && str) {
- int len = mbox->cmd.length;
- memcpy(str, mbox->data, len);
- str[len] = '\0';
- }
- return err;
-}
-
-/*============================================================================
- * Set global configuration.
- */
-static int fr_configure (sdla_t* card, fr_conf_t *conf)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int dlci_num = card->u.f.dlci_num;
- int err, i;
-
- do
- {
- memcpy(mbox->data, conf, sizeof(fr_conf_t));
-
- if (dlci_num) for (i = 0; i < dlci_num; ++i)
- ((fr_conf_t*)mbox->data)->dlci[i] =
- card->u.f.node_dlci[i];
-
- mbox->cmd.command = FR_SET_CONFIG;
- mbox->cmd.length =
- sizeof(fr_conf_t) + dlci_num * sizeof(short);
-
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- } while (err && retry-- && fr_event(card, err, mbox));
-
- /*NC Oct 12 2000 */
- if (err != CMD_OK){
- printk(KERN_ERR "%s: Frame Relay Configuration Failed: rc=0x%x\n",
- card->devname,err);
- }
-
- return err;
-}
-
-/*============================================================================
- * Set DLCI configuration.
- */
-static int fr_dlci_configure (sdla_t* card, fr_dlc_conf_t *conf, unsigned dlci)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memcpy(mbox->data, conf, sizeof(fr_dlc_conf_t));
- mbox->cmd.dlci = (unsigned short) dlci;
- mbox->cmd.command = FR_SET_CONFIG;
- mbox->cmd.length = sizeof(fr_dlc_conf_t);
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry--);
-
- return err;
-}
-/*============================================================================
- * Set interrupt mode.
- */
-static int fr_set_intr_mode (sdla_t* card, unsigned mode, unsigned mtu,
- unsigned short timeout)
-{
- fr_mbox_t* mbox = card->mbox;
- fr508_intr_ctl_t* ictl = (void*)mbox->data;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(ictl, 0, sizeof(fr508_intr_ctl_t));
- ictl->mode = mode;
- ictl->tx_len = mtu;
- ictl->irq = card->hw.irq;
-
- /* indicate timeout on timer */
- if (mode & 0x20) ictl->timeout = timeout;
-
- mbox->cmd.length = sizeof(fr508_intr_ctl_t);
- mbox->cmd.command = FR_SET_INTR_MODE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- } while (err && retry-- && fr_event(card, err, mbox));
-
- return err;
-}
-
-/*============================================================================
- * Enable communications.
- */
-static int fr_comm_enable (sdla_t* card)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- mbox->cmd.command = FR_COMM_ENABLE;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- return err;
-}
-
-/*============================================================================
- * fr_comm_disable
- *
- * Warning: This functin is called by the shutdown() procedure. It is void
- * since dev->priv are has already been deallocated and no
- * error checking is possible using fr_event() function.
- */
-static void fr_comm_disable (sdla_t* card)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do {
- mbox->cmd.command = FR_SET_MODEM_STATUS;
- mbox->cmd.length = 1;
- mbox->data[0] = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry--);
-
- retry = MAX_CMD_RETRY;
-
- do
- {
- mbox->cmd.command = FR_COMM_DISABLE;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry--);
-
- return;
-}
-
-
-
-/*============================================================================
- * Get communications error statistics.
- */
-static int fr_get_err_stats (sdla_t* card)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
-
- do
- {
- mbox->cmd.command = FR_READ_ERROR_STATS;
- mbox->cmd.length = 0;
- mbox->cmd.dlci = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if (!err) {
- fr_comm_stat_t* stats = (void*)mbox->data;
- card->wandev.stats.rx_over_errors = stats->rx_overruns;
- card->wandev.stats.rx_crc_errors = stats->rx_bad_crc;
- card->wandev.stats.rx_missed_errors = stats->rx_aborts;
- card->wandev.stats.rx_length_errors = stats->rx_too_long;
- card->wandev.stats.tx_aborted_errors = stats->tx_aborts;
-
- }
-
- return err;
-}
-
-/*============================================================================
- * Get statistics.
- */
-static int fr_get_stats (sdla_t* card)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
-
- do
- {
- mbox->cmd.command = FR_READ_STATISTICS;
- mbox->cmd.length = 0;
- mbox->cmd.dlci = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if (!err) {
- fr_link_stat_t* stats = (void*)mbox->data;
- card->wandev.stats.rx_frame_errors = stats->rx_bad_format;
- card->wandev.stats.rx_dropped =
- stats->rx_dropped + stats->rx_dropped2;
- }
-
- return err;
-}
-
-/*============================================================================
- * Add DLCI(s) (Access Node only!).
- * This routine will perform the ADD_DLCIs command for the specified DLCI.
- */
-static int fr_add_dlci (sdla_t* card, int dlci)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- unsigned short* dlci_list = (void*)mbox->data;
-
- mbox->cmd.length = sizeof(short);
- dlci_list[0] = dlci;
- mbox->cmd.command = FR_ADD_DLCI;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- } while (err && retry-- && fr_event(card, err, mbox));
-
- return err;
-}
-
-/*============================================================================
- * Activate DLCI(s) (Access Node only!).
- * This routine will perform the ACTIVATE_DLCIs command with a DLCI number.
- */
-static int fr_activate_dlci (sdla_t* card, int dlci)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- unsigned short* dlci_list = (void*)mbox->data;
-
- mbox->cmd.length = sizeof(short);
- dlci_list[0] = dlci;
- mbox->cmd.command = FR_ACTIVATE_DLCI;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- } while (err && retry-- && fr_event(card, err, mbox));
-
- return err;
-}
-
-/*============================================================================
- * Delete DLCI(s) (Access Node only!).
- * This routine will perform the DELETE_DLCIs command with a DLCI number.
- */
-static int fr_delete_dlci (sdla_t* card, int dlci)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- unsigned short* dlci_list = (void*)mbox->data;
-
- mbox->cmd.length = sizeof(short);
- dlci_list[0] = dlci;
- mbox->cmd.command = FR_DELETE_DLCI;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- } while (err && retry-- && fr_event(card, err, mbox));
-
- return err;
-}
-
-
-
-/*============================================================================
- * Issue in-channel signalling frame.
- */
-static int fr_issue_isf (sdla_t* card, int isf)
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- mbox->data[0] = isf;
- mbox->cmd.length = 1;
- mbox->cmd.command = FR_ISSUE_IS_FRAME;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- return err;
-}
-
-
-static unsigned int fr_send_hdr (sdla_t*card, int dlci, unsigned int offset)
-{
- struct net_device *dev = find_channel(card,dlci);
- fr_channel_t *chan;
-
- if (!dev || !(chan=dev->priv))
- return offset;
-
- if (chan->fr_header_len){
- sdla_poke(&card->hw, offset, chan->fr_header, chan->fr_header_len);
- }
-
- return offset+chan->fr_header_len;
-}
-
-/*============================================================================
- * Send a frame on a selected DLCI.
- */
-static int fr_send_data_header (sdla_t* card, int dlci, unsigned char attr, int len,
- void *buf, unsigned char hdr_len)
-{
- fr_mbox_t* mbox = card->mbox + 0x800;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- mbox->cmd.dlci = dlci;
- mbox->cmd.attr = attr;
- mbox->cmd.length = len+hdr_len;
- mbox->cmd.command = FR_WRITE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if (!err) {
- fr_tx_buf_ctl_t* frbuf;
-
- if(card->hw.type == SDLA_S514)
- frbuf = (void*)(*(unsigned long*)mbox->data +
- card->hw.dpmbase);
- else
- frbuf = (void*)(*(unsigned long*)mbox->data -
- FR_MB_VECTOR + card->hw.dpmbase);
-
- sdla_poke(&card->hw, fr_send_hdr(card,dlci,frbuf->offset), buf, len);
- frbuf->flag = 0x01;
- }
-
- return err;
-}
-
-static int fr_send (sdla_t* card, int dlci, unsigned char attr, int len,
- void *buf)
-{
- fr_mbox_t* mbox = card->mbox + 0x800;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- mbox->cmd.dlci = dlci;
- mbox->cmd.attr = attr;
- mbox->cmd.length = len;
- mbox->cmd.command = FR_WRITE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if (!err) {
- fr_tx_buf_ctl_t* frbuf;
-
- if(card->hw.type == SDLA_S514)
- frbuf = (void*)(*(unsigned long*)mbox->data +
- card->hw.dpmbase);
- else
- frbuf = (void*)(*(unsigned long*)mbox->data -
- FR_MB_VECTOR + card->hw.dpmbase);
-
- sdla_poke(&card->hw, frbuf->offset, buf, len);
- frbuf->flag = 0x01;
- }
-
- return err;
-}
-
-
-/****** Firmware Asynchronous Event Handlers ********************************/
-
-/*============================================================================
- * Main asyncronous event/error handler.
- * This routine is called whenever firmware command returns non-zero
- * return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox)
-{
- fr508_flags_t* flags = card->flags;
- char *ptr = &flags->iflag;
- int i;
-
- switch (event) {
-
- case FRRES_MODEM_FAILURE:
- return fr_modem_failure(card, mbox);
-
- case FRRES_CHANNEL_DOWN: {
- struct net_device *dev;
-
- /* Remove all routes from associated DLCI's */
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)) {
- fr_channel_t *chan = dev->priv;
- if (chan->route_flag == ROUTE_ADDED) {
- chan->route_flag = REMOVE_ROUTE;
- }
-
- if (chan->inarp == INARP_CONFIGURED) {
- chan->inarp = INARP_REQUEST;
- }
-
- /* If the link becomes disconnected then,
- * all channels will be disconnected
- * as well.
- */
- set_chan_state(dev,WAN_DISCONNECTED);
- }
-
- wanpipe_set_state(card, WAN_DISCONNECTED);
- return 1;
- }
-
- case FRRES_CHANNEL_UP: {
- struct net_device *dev;
-
- /* FIXME: Only startup devices that are on the list */
-
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)) {
-
- set_chan_state(dev,WAN_CONNECTED);
- }
-
- wanpipe_set_state(card, WAN_CONNECTED);
- return 1;
- }
-
- case FRRES_DLCI_CHANGE:
- return fr_dlci_change(card, mbox);
-
- case FRRES_DLCI_MISMATCH:
- printk(KERN_INFO "%s: DLCI list mismatch!\n",
- card->devname);
- return 1;
-
- case CMD_TIMEOUT:
- printk(KERN_ERR "%s: command 0x%02X timed out!\n",
- card->devname, mbox->cmd.command);
- printk(KERN_INFO "%s: ID Bytes = ",card->devname);
- for(i = 0; i < 8; i ++)
- printk(KERN_INFO "0x%02X ", *(ptr + 0x18 + i));
- printk(KERN_INFO "\n");
-
- break;
-
- case FRRES_DLCI_INACTIVE:
- break;
-
- case FRRES_CIR_OVERFLOW:
- break;
-
- case FRRES_BUFFER_OVERFLOW:
- break;
-
- default:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n"
- , card->devname, mbox->cmd.command, event);
- }
-
- return 0;
-}
-
-/*============================================================================
- * Handle modem error.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int fr_modem_failure (sdla_t *card, fr_mbox_t* mbox)
-{
- printk(KERN_INFO "%s: physical link down! (modem error 0x%02X)\n",
- card->devname, mbox->data[0]);
-
- switch (mbox->cmd.command){
- case FR_WRITE:
-
- case FR_READ:
- return 0;
- }
-
- return 1;
-}
-
-/*============================================================================
- * Handle DLCI status change.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int fr_dlci_change (sdla_t *card, fr_mbox_t* mbox)
-{
- dlci_status_t* status = (void*)mbox->data;
- int cnt = mbox->cmd.length / sizeof(dlci_status_t);
- fr_channel_t *chan;
- struct net_device* dev2;
-
-
- for (; cnt; --cnt, ++status) {
-
- unsigned short dlci= status->dlci;
- struct net_device* dev = find_channel(card, dlci);
-
- if (dev == NULL){
- printk(KERN_INFO
- "%s: CPE contains unconfigured DLCI= %d\n",
- card->devname, dlci);
-
- printk(KERN_INFO
- "%s: unconfigured DLCI %d reported by network\n"
- , card->devname, dlci);
-
- }else{
- if (status->state == FR_LINK_INOPER) {
- printk(KERN_INFO
- "%s: DLCI %u is inactive!\n",
- card->devname, dlci);
-
- if (dev && netif_running(dev))
- set_chan_state(dev, WAN_DISCONNECTED);
- }
-
- if (status->state & FR_DLCI_DELETED) {
-
- printk(KERN_INFO
- "%s: DLCI %u has been deleted!\n",
- card->devname, dlci);
-
- if (dev && netif_running(dev)){
-
- fr_channel_t *chan = dev->priv;
-
- if (chan->route_flag == ROUTE_ADDED) {
- chan->route_flag = REMOVE_ROUTE;
- /* The state change will trigger
- * the fr polling routine */
- }
-
- if (chan->inarp == INARP_CONFIGURED) {
- chan->inarp = INARP_REQUEST;
- }
-
- set_chan_state(dev, WAN_DISCONNECTED);
- }
-
- } else if (status->state & FR_DLCI_ACTIVE) {
-
- chan = dev->priv;
-
- /* This flag is used for configuring specific
- DLCI(s) when they become active.
- */
- chan->dlci_configured = DLCI_CONFIG_PENDING;
-
- set_chan_state(dev, WAN_CONNECTED);
-
- }
- }
- }
-
- for (dev2 = card->wandev.dev; dev2;
- dev2 = *((struct net_device **)dev2->priv)){
-
- chan = dev2->priv;
-
- if (chan->dlci_configured == DLCI_CONFIG_PENDING) {
- if (fr_init_dlci(card, chan)){
- return 1;
- }
- }
-
- }
- return 1;
-}
-
-
-static int fr_init_dlci (sdla_t *card, fr_channel_t *chan)
-{
- fr_dlc_conf_t cfg;
-
- memset(&cfg, 0, sizeof(cfg));
-
- if ( chan->cir_status == CIR_DISABLED) {
-
- cfg.cir_fwd = cfg.cir_bwd = 16;
- cfg.bc_fwd = cfg.bc_bwd = 16;
- cfg.conf_flags = 0x0001;
-
- }else if (chan->cir_status == CIR_ENABLED) {
-
- cfg.cir_fwd = cfg.cir_bwd = chan->cir;
- cfg.bc_fwd = cfg.bc_bwd = chan->bc;
- cfg.be_fwd = cfg.be_bwd = chan->be;
- cfg.conf_flags = 0x0000;
- }
-
- if (fr_dlci_configure( card, &cfg , chan->dlci)){
- printk(KERN_INFO
- "%s: DLCI Configure failed for %d\n",
- card->devname, chan->dlci);
- return 1;
- }
-
- chan->dlci_configured = DLCI_CONFIGURED;
-
- /* Read the interface byte mapping into the channel
- * structure.
- */
- read_DLCI_IB_mapping( card, chan );
-
- return 0;
-}
-/******* Miscellaneous ******************************************************/
-
-/*============================================================================
- * Update channel state.
- */
-static int update_chan_state(struct net_device* dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- mbox->cmd.command = FR_LIST_ACTIVE_DLCI;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if (!err) {
-
- unsigned short* list = (void*)mbox->data;
- int cnt = mbox->cmd.length / sizeof(short);
-
- err=1;
-
- for (; cnt; --cnt, ++list) {
-
- if (*list == chan->dlci) {
- set_chan_state(dev, WAN_CONNECTED);
-
-
- /* May 23 2000. NC
- * When a dlci is added or restarted,
- * the dlci_int_interface pointer must
- * be reinitialized. */
- if (!chan->dlci_int_interface){
- err=fr_init_dlci (card,chan);
- }
- break;
- }
- }
- }
-
- return err;
-}
-
-/*============================================================================
- * Set channel state.
- */
-static void set_chan_state(struct net_device* dev, int state)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- if (chan->common.state != state) {
-
- switch (state) {
-
- case WAN_CONNECTED:
- printk(KERN_INFO
- "%s: Interface %s: DLCI %d connected\n",
- card->devname, dev->name, chan->dlci);
-
- /* If the interface was previoulsy down,
- * bring it up, since the channel is active */
-
- trigger_fr_poll (dev);
- trigger_fr_arp (dev);
- break;
-
- case WAN_CONNECTING:
- printk(KERN_INFO
- "%s: Interface %s: DLCI %d connecting\n",
- card->devname, dev->name, chan->dlci);
- break;
-
- case WAN_DISCONNECTED:
- printk (KERN_INFO
- "%s: Interface %s: DLCI %d disconnected!\n",
- card->devname, dev->name, chan->dlci);
-
- /* If the interface is up, bring it down,
- * since the channel is now disconnected */
- trigger_fr_poll (dev);
- break;
- }
-
- chan->common.state = state;
- }
-
- chan->state_tick = jiffies;
-}
-
-/*============================================================================
- * Find network device by its channel number.
- *
- * We need this critical flag because we change
- * the dlci_to_dev_map outside the interrupt.
- *
- * NOTE: del_if() functions updates this array, it uses
- * the spin locks to avoid corruption.
- */
-static struct net_device* find_channel(sdla_t* card, unsigned dlci)
-{
- if(dlci > HIGHEST_VALID_DLCI)
- return NULL;
-
- return(card->u.f.dlci_to_dev_map[dlci]);
-}
-
-/*============================================================================
- * Check to see if a frame can be sent. If no transmit buffers available,
- * enable transmit interrupts.
- *
- * Return: 1 - Tx buffer(s) available
- * 0 - no buffers available
- */
-static int is_tx_ready (sdla_t* card, fr_channel_t* chan)
-{
- unsigned char sb;
-
- if(card->hw.type == SDLA_S514)
- return 1;
-
- sb = inb(card->hw.port);
- if (sb & 0x02)
- return 1;
-
- return 0;
-}
-
-/*============================================================================
- * Convert decimal string to unsigned integer.
- * If len != 0 then only 'len' characters of the string are converted.
- */
-static unsigned int dec_to_uint (unsigned char* str, int len)
-{
- unsigned val;
-
- if (!len)
- len = strlen(str);
-
- for (val = 0; len && isdigit(*str); ++str, --len)
- val = (val * 10) + (*str - (unsigned)'0');
-
- return val;
-}
-
-
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, int dlci)
-{
- int udp_pkt_stored = 0;
-
- struct net_device *dev = find_channel(card, dlci);
- fr_channel_t *chan;
-
- if (!dev || !(chan=dev->priv))
- return 1;
-
- if(!card->u.f.udp_pkt_lgth && (skb->len <= MAX_LGTH_UDP_MGNT_PKT)){
- card->u.f.udp_pkt_lgth = skb->len + chan->fr_header_len;
- card->u.f.udp_type = udp_type;
- card->u.f.udp_pkt_src = udp_pkt_src;
- card->u.f.udp_dlci = dlci;
- memcpy(card->u.f.udp_pkt_data, skb->data, skb->len);
- card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UDP;
- udp_pkt_stored = 1;
-
- }else{
- printk(KERN_INFO "ERROR: UDP packet not stored for DLCI %d\n",
- dlci);
- }
-
- if(udp_pkt_src == UDP_PKT_FRM_STACK){
- dev_kfree_skb_any(skb);
- }else{
- dev_kfree_skb_any(skb);
- }
-
- return(udp_pkt_stored);
-}
-
-
-/*==============================================================================
- * Process UDP call of type FPIPE8ND
- */
-static int process_udp_mgmt_pkt(sdla_t* card)
-{
-
- int c_retry = MAX_CMD_RETRY;
- unsigned char *buf;
- unsigned char frames;
- unsigned int len;
- unsigned short buffer_length;
- struct sk_buff *new_skb;
- fr_mbox_t* mbox = card->mbox;
- int err;
- struct timeval tv;
- int udp_mgmt_req_valid = 1;
- struct net_device* dev;
- fr_channel_t* chan;
- fr_udp_pkt_t *fr_udp_pkt;
- unsigned short num_trc_els;
- fr_trc_el_t* ptr_trc_el;
- fr_trc_el_t trc_el;
- fpipemon_trc_t* fpipemon_trc;
-
- char udp_pkt_src = card->u.f.udp_pkt_src;
- int dlci = card->u.f.udp_dlci;
-
- /* Find network interface for this packet */
- dev = find_channel(card, dlci);
- if (!dev){
- card->u.f.udp_pkt_lgth = 0;
- return 1;
- }
- if ((chan = dev->priv) == NULL){
- card->u.f.udp_pkt_lgth = 0;
- return 1;
- }
-
- /* If the UDP packet is from the network, we are going to have to
- transmit a response. Before doing so, we must check to see that
- we are not currently transmitting a frame (in 'if_send()') and
- that we are not already in a 'delayed transmit' state.
- */
- if(udp_pkt_src == UDP_PKT_FRM_NETWORK) {
- if (check_tx_status(card,dev)){
- card->u.f.udp_pkt_lgth = 0;
- return 1;
- }
- }
-
- fr_udp_pkt = (fr_udp_pkt_t *)card->u.f.udp_pkt_data;
-
- if(udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
- switch(fr_udp_pkt->cblock.command) {
-
- case FR_READ_MODEM_STATUS:
- case FR_READ_STATUS:
- case FPIPE_ROUTER_UP_TIME:
- case FR_READ_ERROR_STATS:
- case FPIPE_DRIVER_STAT_GEN:
- case FR_READ_STATISTICS:
- case FR_READ_ADD_DLC_STATS:
- case FR_READ_CONFIG:
- case FR_READ_CODE_VERSION:
- udp_mgmt_req_valid = 1;
- break;
- default:
- udp_mgmt_req_valid = 0;
- break;
- }
- }
-
- if(!udp_mgmt_req_valid) {
- /* set length to 0 */
- fr_udp_pkt->cblock.length = 0;
- /* set return code */
- fr_udp_pkt->cblock.result = 0xCD;
-
- chan->drvstats_gen.UDP_PIPE_mgmt_direction_err ++;
-
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Warning, Illegal UDP command attempted from network: %x\n",
- card->devname,fr_udp_pkt->cblock.command);
- }
-
- } else {
-
- switch(fr_udp_pkt->cblock.command) {
-
- case FPIPE_ENABLE_TRACING:
- if(!card->TracingEnabled) {
- do {
- mbox->cmd.command = FR_SET_TRACE_CONFIG;
- mbox->cmd.length = 1;
- mbox->cmd.dlci = 0x00;
- mbox->data[0] = fr_udp_pkt->data[0] |
- RESET_TRC;
- err = sdla_exec(mbox) ?
- mbox->cmd.result : CMD_TIMEOUT;
- } while (err && c_retry-- && fr_event(card, err,
- mbox));
-
- if(err) {
- card->TracingEnabled = 0;
- /* set the return code */
- fr_udp_pkt->cblock.result =
- mbox->cmd.result;
- mbox->cmd.length = 0;
- break;
- }
-
- sdla_peek(&card->hw, NO_TRC_ELEMENTS_OFF,
- &num_trc_els, 2);
- sdla_peek(&card->hw, BASE_TRC_ELEMENTS_OFF,
- &card->u.f.trc_el_base, 4);
- card->u.f.curr_trc_el = card->u.f.trc_el_base;
- card->u.f.trc_el_last = card->u.f.curr_trc_el +
- ((num_trc_els - 1) *
- sizeof(fr_trc_el_t));
-
- /* Calculate the maximum trace data area in */
- /* the UDP packet */
- card->u.f.trc_bfr_space=(MAX_LGTH_UDP_MGNT_PKT -
- //sizeof(fr_encap_hdr_t) -
- sizeof(ip_pkt_t) -
- sizeof(udp_pkt_t) -
- sizeof(wp_mgmt_t) -
- sizeof(cblock_t));
-
- /* set return code */
- fr_udp_pkt->cblock.result = 0;
-
- } else {
- /* set return code to line trace already
- enabled */
- fr_udp_pkt->cblock.result = 1;
- }
-
- mbox->cmd.length = 0;
- card->TracingEnabled = 1;
- break;
-
-
- case FPIPE_DISABLE_TRACING:
- if(card->TracingEnabled) {
-
- do {
- mbox->cmd.command = FR_SET_TRACE_CONFIG;
- mbox->cmd.length = 1;
- mbox->cmd.dlci = 0x00;
- mbox->data[0] = ~ACTIVATE_TRC;
- err = sdla_exec(mbox) ?
- mbox->cmd.result : CMD_TIMEOUT;
- } while (err && c_retry-- && fr_event(card, err, mbox));
- }
-
- /* set return code */
- fr_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 0;
- card->TracingEnabled = 0;
- break;
-
- case FPIPE_GET_TRACE_INFO:
-
- /* Line trace cannot be performed on the 502 */
- if(!card->TracingEnabled) {
- /* set return code */
- fr_udp_pkt->cblock.result = 1;
- mbox->cmd.length = 0;
- break;
- }
-
- ptr_trc_el = (void *)card->u.f.curr_trc_el;
-
- buffer_length = 0;
- fr_udp_pkt->data[0x00] = 0x00;
-
- for(frames = 0; frames < MAX_FRMS_TRACED; frames ++) {
-
- sdla_peek(&card->hw, (unsigned long)ptr_trc_el,
- (void *)&trc_el.flag,
- sizeof(fr_trc_el_t));
- if(trc_el.flag == 0x00) {
- break;
- }
- if((card->u.f.trc_bfr_space - buffer_length)
- < sizeof(fpipemon_trc_hdr_t)) {
- fr_udp_pkt->data[0x00] |= MORE_TRC_DATA;
- break;
- }
-
- fpipemon_trc =
- (fpipemon_trc_t *)&fr_udp_pkt->data[buffer_length];
- fpipemon_trc->fpipemon_trc_hdr.status =
- trc_el.attr;
- fpipemon_trc->fpipemon_trc_hdr.tmstamp =
- trc_el.tmstamp;
- fpipemon_trc->fpipemon_trc_hdr.length =
- trc_el.length;
-
- if(!trc_el.offset || !trc_el.length) {
-
- fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x00;
-
- }else if((trc_el.length + sizeof(fpipemon_trc_hdr_t) + 1) >
- (card->u.f.trc_bfr_space - buffer_length)){
-
- fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x00;
- fr_udp_pkt->data[0x00] |= MORE_TRC_DATA;
-
- }else {
- fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x01;
- sdla_peek(&card->hw, trc_el.offset,
- fpipemon_trc->data,
- trc_el.length);
- }
-
- trc_el.flag = 0x00;
- sdla_poke(&card->hw, (unsigned long)ptr_trc_el,
- &trc_el.flag, 1);
-
- ptr_trc_el ++;
- if((void *)ptr_trc_el > card->u.f.trc_el_last)
- ptr_trc_el = (void*)card->u.f.trc_el_base;
-
- buffer_length += sizeof(fpipemon_trc_hdr_t);
- if(fpipemon_trc->fpipemon_trc_hdr.data_passed) {
- buffer_length += trc_el.length;
- }
-
- if(fr_udp_pkt->data[0x00] & MORE_TRC_DATA) {
- break;
- }
- }
-
- if(frames == MAX_FRMS_TRACED) {
- fr_udp_pkt->data[0x00] |= MORE_TRC_DATA;
- }
-
- card->u.f.curr_trc_el = (void *)ptr_trc_el;
-
- /* set the total number of frames passed */
- fr_udp_pkt->data[0x00] |=
- ((frames << 1) & (MAX_FRMS_TRACED << 1));
-
- /* set the data length and return code */
- fr_udp_pkt->cblock.length = mbox->cmd.length = buffer_length;
- fr_udp_pkt->cblock.result = 0;
- break;
-
- case FPIPE_FT1_READ_STATUS:
- sdla_peek(&card->hw, 0xF020,
- &fr_udp_pkt->data[0x00] , 2);
- fr_udp_pkt->cblock.length = mbox->cmd.length = 2;
- fr_udp_pkt->cblock.result = 0;
- break;
-
- case FPIPE_FLUSH_DRIVER_STATS:
- init_chan_statistics(chan);
- init_global_statistics(card);
- mbox->cmd.length = 0;
- break;
-
- case FPIPE_ROUTER_UP_TIME:
- do_gettimeofday(&tv);
- chan->router_up_time = tv.tv_sec -
- chan->router_start_time;
- *(unsigned long *)&fr_udp_pkt->data =
- chan->router_up_time;
- mbox->cmd.length = fr_udp_pkt->cblock.length = 4;
- fr_udp_pkt->cblock.result = 0;
- break;
-
- case FPIPE_DRIVER_STAT_IFSEND:
- memcpy(fr_udp_pkt->data,
- &chan->drvstats_if_send.if_send_entry,
- sizeof(if_send_stat_t));
- mbox->cmd.length = fr_udp_pkt->cblock.length =sizeof(if_send_stat_t);
- fr_udp_pkt->cblock.result = 0;
- break;
-
- case FPIPE_DRIVER_STAT_INTR:
-
- memcpy(fr_udp_pkt->data,
- &card->statistics.isr_entry,
- sizeof(global_stats_t));
-
- memcpy(&fr_udp_pkt->data[sizeof(global_stats_t)],
- &chan->drvstats_rx_intr.rx_intr_no_socket,
- sizeof(rx_intr_stat_t));
-
- mbox->cmd.length = fr_udp_pkt->cblock.length =
- sizeof(global_stats_t) +
- sizeof(rx_intr_stat_t);
- fr_udp_pkt->cblock.result = 0;
- break;
-
- case FPIPE_DRIVER_STAT_GEN:
- memcpy(fr_udp_pkt->data,
- &chan->drvstats_gen.UDP_PIPE_mgmt_kmalloc_err,
- sizeof(pipe_mgmt_stat_t));
-
- memcpy(&fr_udp_pkt->data[sizeof(pipe_mgmt_stat_t)],
- &card->statistics, sizeof(global_stats_t));
-
- mbox->cmd.length = fr_udp_pkt->cblock.length = sizeof(global_stats_t)+
- sizeof(rx_intr_stat_t);
- fr_udp_pkt->cblock.result = 0;
- break;
-
-
- case FR_FT1_STATUS_CTRL:
- if(fr_udp_pkt->data[0] == 1) {
- if(rCount++ != 0 ){
- fr_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 1;
- break;
- }
- }
-
- /* Disable FT1 MONITOR STATUS */
- if(fr_udp_pkt->data[0] == 0) {
- if( --rCount != 0) {
- fr_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 1;
- break;
- }
- }
- goto udp_mgmt_dflt;
-
-
- default:
-udp_mgmt_dflt:
- do {
- memcpy(&mbox->cmd,
- &fr_udp_pkt->cblock.command,
- sizeof(fr_cmd_t));
- if(mbox->cmd.length) {
- memcpy(&mbox->data,
- (char *)fr_udp_pkt->data,
- mbox->cmd.length);
- }
-
- err = sdla_exec(mbox) ? mbox->cmd.result :
- CMD_TIMEOUT;
- } while (err && c_retry-- && fr_event(card, err, mbox));
-
- if(!err)
- chan->drvstats_gen.
- UDP_PIPE_mgmt_adptr_cmnd_OK ++;
- else
- chan->drvstats_gen.
- UDP_PIPE_mgmt_adptr_cmnd_timeout ++;
-
- /* copy the result back to our buffer */
- memcpy(&fr_udp_pkt->cblock.command,
- &mbox->cmd, sizeof(fr_cmd_t));
-
- if(mbox->cmd.length) {
- memcpy(&fr_udp_pkt->data,
- &mbox->data, mbox->cmd.length);
- }
- }
- }
-
- /* Fill UDP TTL */
- fr_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
- len = reply_udp(card->u.f.udp_pkt_data, mbox->cmd.length);
-
- if(udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
- chan->fr_header_len=2;
- chan->fr_header[0]=Q922_UI;
- chan->fr_header[1]=NLPID_IP;
-
- err = fr_send_data_header(card, dlci, 0, len,
- card->u.f.udp_pkt_data,chan->fr_header_len);
- if (err){
- chan->drvstats_gen.UDP_PIPE_mgmt_adptr_send_passed ++;
- }else{
- chan->drvstats_gen.UDP_PIPE_mgmt_adptr_send_failed ++;
- }
-
- } else {
- /* Allocate socket buffer */
- if((new_skb = dev_alloc_skb(len)) != NULL) {
-
- /* copy data into new_skb */
- buf = skb_put(new_skb, len);
- memcpy(buf, card->u.f.udp_pkt_data, len);
-
- chan->drvstats_gen.
- UDP_PIPE_mgmt_passed_to_stack ++;
- new_skb->dev = dev;
- new_skb->protocol = htons(ETH_P_IP);
- new_skb->mac.raw = new_skb->data;
- netif_rx(new_skb);
-
- } else {
- chan->drvstats_gen.UDP_PIPE_mgmt_no_socket ++;
- printk(KERN_INFO
- "%s: UDP mgmt cmnd, no socket buffers available!\n",
- card->devname);
- }
- }
-
- card->u.f.udp_pkt_lgth = 0;
-
- return 1;
-}
-
-/*==============================================================================
- * Send Inverse ARP Request
- */
-
-int send_inarp_request(sdla_t *card, struct net_device *dev)
-{
- int err=0;
-
- arphdr_1490_t *ArpPacket;
- arphdr_fr_t *arphdr;
- fr_channel_t *chan = dev->priv;
- struct in_device *in_dev;
-
- in_dev = dev->ip_ptr;
-
- if(in_dev != NULL ) {
-
- ArpPacket = kmalloc(sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), GFP_ATOMIC);
- /* SNAP Header indicating ARP */
- ArpPacket->control = 0x03;
- ArpPacket->pad = 0x00;
- ArpPacket->NLPID = 0x80;
- ArpPacket->OUI[0] = 0;
- ArpPacket->OUI[1] = 0;
- ArpPacket->OUI[2] = 0;
- ArpPacket->PID = 0x0608;
-
- arphdr = (arphdr_fr_t *)(ArpPacket + 1); // Go to ARP Packet
-
- /* InARP request */
- arphdr->ar_hrd = 0x0F00; /* Frame Relay HW type */
- arphdr->ar_pro = 0x0008; /* IP Protocol */
- arphdr->ar_hln = 2; /* HW addr length */
- arphdr->ar_pln = 4; /* IP addr length */
- arphdr->ar_op = htons(0x08); /* InARP Request */
- arphdr->ar_sha = 0; /* src HW DLCI - Doesn't matter */
- if(in_dev->ifa_list != NULL)
- arphdr->ar_sip = in_dev->ifa_list->ifa_local; /* Local Address */else
- arphdr->ar_sip = 0;
- arphdr->ar_tha = 0; /* dst HW DLCI - Doesn't matter */
- arphdr->ar_tip = 0; /* Remote Address -- what we want */
-
- err = fr_send(card, chan->dlci, 0, sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t),
- (void *)ArpPacket);
-
- if (!err){
- printk(KERN_INFO "\n%s: Sending InARP request on DLCI %d.\n",
- card->devname, chan->dlci);
- clear_bit(ARP_CRIT,&card->wandev.critical);
- }
-
- kfree(ArpPacket);
- }else{
- printk(KERN_INFO "%s: INARP ERROR: %s doesn't have a local IP address!\n",
- card->devname,dev->name);
- return 1;
- }
-
- return 0;
-}
-
-
-/*==============================================================================
- * Check packet for ARP Type
- */
-
-int is_arp(void *buf)
-{
- arphdr_1490_t *arphdr = (arphdr_1490_t *)buf;
-
- if (arphdr->pad == 0x00 &&
- arphdr->NLPID == 0x80 &&
- arphdr->PID == 0x0608)
- return 1;
- else return 0;
-}
-
-/*==============================================================================
- * Process ARP Packet Type
- */
-
-int process_ARP(arphdr_1490_t *ArpPacket, sdla_t *card, struct net_device* dev)
-{
-
-
- arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */
- fr_rx_buf_ctl_t* frbuf = card->rxmb;
- struct in_device *in_dev;
- fr_channel_t *chan = dev->priv;
-
- /* Before we transmit ARP packet, we must check
- * to see that we are not currently transmitting a
- * frame (in 'if_send()') and that we are not
- * already in a 'delayed transmit' state. */
- if (check_tx_status(card,dev)){
- if (net_ratelimit()){
- printk(KERN_INFO "%s: Disabling comminication to process ARP\n",
- card->devname);
- }
- set_bit(ARP_CRIT,&card->wandev.critical);
- return 0;
- }
-
- in_dev = dev->ip_ptr;
-
- /* Check that IP addresses exist for our network address */
- if (in_dev == NULL || in_dev->ifa_list == NULL)
- return -1;
-
- switch (ntohs(arphdr->ar_op)) {
-
- case 0x08: // Inverse ARP request -- Send Reply, add route.
-
- /* Check for valid Address */
- printk(KERN_INFO "%s: Recvd PtP addr -InArp Req: %u.%u.%u.%u\n",
- card->devname, NIPQUAD(arphdr->ar_sip));
-
-
- /* Check that the network address is the same as ours, only
- * if the netowrk mask is not 255.255.255.255. Otherwise
- * this check would not make sense */
-
- if (in_dev->ifa_list->ifa_mask != 0xFFFFFFFF &&
- (in_dev->ifa_list->ifa_mask & arphdr->ar_sip) !=
- (in_dev->ifa_list->ifa_mask & in_dev->ifa_list->ifa_local)){
- printk(KERN_INFO
- "%s: Invalid PtP address. %u.%u.%u.%u InARP ignored.\n",
- card->devname,NIPQUAD(arphdr->ar_sip));
-
- printk(KERN_INFO "%s: mask %u.%u.%u.%u\n",
- card->devname, NIPQUAD(in_dev->ifa_list->ifa_mask));
- printk(KERN_INFO "%s: local %u.%u.%u.%u\n",
- card->devname,NIPQUAD(in_dev->ifa_list->ifa_local));
- return -1;
- }
-
- if (in_dev->ifa_list->ifa_local == arphdr->ar_sip){
- printk(KERN_INFO
- "%s: Local addr = PtP addr. InARP ignored.\n",
- card->devname);
- return -1;
- }
-
- arphdr->ar_op = htons(0x09); /* InARP Reply */
-
- /* Set addresses */
- arphdr->ar_tip = arphdr->ar_sip;
- arphdr->ar_sip = in_dev->ifa_list->ifa_local;
-
- chan->ip_local = in_dev->ifa_list->ifa_local;
- chan->ip_remote = arphdr->ar_sip;
-
- fr_send(card, frbuf->dlci, 0, frbuf->length, (void *)ArpPacket);
-
- if (test_bit(ARP_CRIT,&card->wandev.critical)){
- if (net_ratelimit()){
- printk(KERN_INFO "%s: ARP Processed Enabling Communication!\n",
- card->devname);
- }
- }
- clear_bit(ARP_CRIT,&card->wandev.critical);
-
- chan->ip_local = in_dev->ifa_list->ifa_local;
- chan->ip_remote = arphdr->ar_sip;
-
- /* Add Route Flag */
- /* The route will be added in the polling routine so
- that it is not interrupt context. */
-
- chan->route_flag = ADD_ROUTE;
- trigger_fr_poll (dev);
-
- break;
-
- case 0x09: // Inverse ARP reply
-
- /* Check for valid Address */
- printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Reply\n",
- card->devname, NIPQUAD(arphdr->ar_sip));
-
-
- /* Compare network addresses, only if network mask
- * is not 255.255.255.255 It would not make sense
- * to perform this test if the mask was all 1's */
-
- if (in_dev->ifa_list->ifa_mask != 0xffffffff &&
- (in_dev->ifa_list->ifa_mask & arphdr->ar_sip) !=
- (in_dev->ifa_list->ifa_mask & in_dev->ifa_list->ifa_local)) {
-
- printk(KERN_INFO "%s: Invalid PtP address. InARP ignored.\n",
- card->devname);
- return -1;
- }
-
- /* Make sure that the received IP address is not
- * the same as our own local address */
- if (in_dev->ifa_list->ifa_local == arphdr->ar_sip) {
- printk(KERN_INFO "%s: Local addr = PtP addr. InARP ignored.\n",
- card->devname);
- return -1;
- }
-
- chan->ip_local = in_dev->ifa_list->ifa_local;
- chan->ip_remote = arphdr->ar_sip;
-
- /* Add Route Flag */
- /* The route will be added in the polling routine so
- that it is not interrupt context. */
-
- chan->route_flag = ADD_ROUTE;
- chan->inarp = INARP_CONFIGURED;
- trigger_fr_poll(dev);
-
- break;
- default:
- break; // ARP's and RARP's -- Shouldn't happen.
- }
-
- return 0;
-}
-
-
-/*============================================================
- * trigger_fr_arp
- *
- * Description:
- * Add an fr_arp() task into a arp
- * timer handler for a specific dlci/interface.
- * This will kick the fr_arp() routine
- * within the specified time interval.
- *
- * Usage:
- * This timer is used to send ARP requests at
- * certain time intervals.
- * Called by an interrupt to request an action
- * at a later date.
- */
-
-static void trigger_fr_arp(struct net_device *dev)
-{
- fr_channel_t* chan = dev->priv;
-
- mod_timer(&chan->fr_arp_timer, jiffies + chan->inarp_interval * HZ);
- return;
-}
-
-
-
-/*==============================================================================
- * ARP Request Action
- *
- * This funciton is called by timer interrupt to send an arp request
- * to the remote end.
- */
-
-static void fr_arp (unsigned long data)
-{
- struct net_device *dev = (struct net_device *)data;
- fr_channel_t *chan = dev->priv;
- volatile sdla_t *card = chan->card;
- fr508_flags_t* flags = card->flags;
-
- /* Send ARP packets for all devs' until
- * ARP state changes to CONFIGURED */
-
- if (chan->inarp == INARP_REQUEST &&
- chan->common.state == WAN_CONNECTED &&
- card->wandev.state == WAN_CONNECTED){
- set_bit(0,&chan->inarp_ready);
- card->u.f.timer_int_enabled |= TMR_INT_ENABLED_ARP;
- flags->imask |= FR_INTR_TIMER;
- }
-
- return;
-}
-
-
-/*==============================================================================
- * Perform the Interrupt Test by running the READ_CODE_VERSION command MAX_INTR_
- * TEST_COUNTER times.
- */
-static int intr_test( sdla_t* card )
-{
- fr_mbox_t* mb = card->mbox;
- int err,i;
-
- err = fr_set_intr_mode(card, FR_INTR_READY, card->wandev.mtu, 0 );
-
- if (err == CMD_OK) {
-
- for ( i = 0; i < MAX_INTR_TEST_COUNTER; i++ ) {
- /* Run command READ_CODE_VERSION */
- mb->cmd.length = 0;
- mb->cmd.command = FR_READ_CODE_VERSION;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
- if (err != CMD_OK)
- fr_event(card, err, mb);
- }
-
- } else {
- return err;
- }
-
- err = fr_set_intr_mode( card, 0, card->wandev.mtu, 0 );
-
- if( err != CMD_OK )
- return err;
-
- return 0;
-}
-
-/*==============================================================================
- * Determine what type of UDP call it is. FPIPE8ND ?
- */
-static int udp_pkt_type( struct sk_buff *skb, sdla_t* card )
-{
- fr_udp_pkt_t *fr_udp_pkt = (fr_udp_pkt_t *)skb->data;
-
- /* Quick HACK */
-
-
- if((fr_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
- (fr_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45) &&
- (fr_udp_pkt->udp_pkt.udp_dst_port ==
- ntohs(card->wandev.udp_port)) &&
- (fr_udp_pkt->wp_mgmt.request_reply ==
- UDPMGMT_REQUEST)) {
- if(!strncmp(fr_udp_pkt->wp_mgmt.signature,
- UDPMGMT_FPIPE_SIGNATURE, 8)){
- return UDP_FPIPE_TYPE;
- }
- }
- return UDP_INVALID_TYPE;
-}
-
-
-/*==============================================================================
- * Initializes the Statistics values in the fr_channel structure.
- */
-void init_chan_statistics( fr_channel_t* chan)
-{
- memset(&chan->drvstats_if_send.if_send_entry, 0,
- sizeof(if_send_stat_t));
- memset(&chan->drvstats_rx_intr.rx_intr_no_socket, 0,
- sizeof(rx_intr_stat_t));
- memset(&chan->drvstats_gen.UDP_PIPE_mgmt_kmalloc_err, 0,
- sizeof(pipe_mgmt_stat_t));
-}
-
-/*==============================================================================
- * Initializes the Statistics values in the Sdla_t structure.
- */
-void init_global_statistics( sdla_t* card )
-{
- /* Intialize global statistics for a card */
- memset(&card->statistics.isr_entry, 0, sizeof(global_stats_t));
-}
-
-static void read_DLCI_IB_mapping( sdla_t* card, fr_channel_t* chan )
-{
- fr_mbox_t* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- dlci_IB_mapping_t* result;
- int err, counter, found;
-
- do {
- mbox->cmd.command = FR_READ_DLCI_IB_MAPPING;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && fr_event(card, err, mbox));
-
- if( mbox->cmd.result != 0){
- printk(KERN_INFO "%s: Read DLCI IB Mapping failed\n",
- chan->name);
- }
-
- counter = mbox->cmd.length / sizeof(dlci_IB_mapping_t);
- result = (void *)mbox->data;
-
- found = 0;
- for (; counter; --counter, ++result) {
- if ( result->dlci == chan->dlci ) {
- chan->IB_addr = result->addr_value;
- if(card->hw.type == SDLA_S514){
- chan->dlci_int_interface =
- (void*)(card->hw.dpmbase +
- chan->IB_addr);
- }else{
- chan->dlci_int_interface =
- (void*)(card->hw.dpmbase +
- (chan->IB_addr & 0x00001FFF));
-
- }
- found = 1;
- break;
- }
- }
- if (!found)
- printk( KERN_INFO "%s: DLCI %d not found by IB MAPPING cmd\n",
- card->devname, chan->dlci);
-}
-
-
-
-void s508_s514_lock(sdla_t *card, unsigned long *smp_flags)
-{
- if (card->hw.type != SDLA_S514){
-
- spin_lock_irqsave(&card->wandev.lock, *smp_flags);
- }else{
- spin_lock(&card->u.f.if_send_lock);
- }
- return;
-}
-
-
-void s508_s514_unlock(sdla_t *card, unsigned long *smp_flags)
-{
- if (card->hw.type != SDLA_S514){
-
- spin_unlock_irqrestore (&card->wandev.lock, *smp_flags);
- }else{
- spin_unlock(&card->u.f.if_send_lock);
- }
- return;
-}
-
-
-
-/*----------------------------------------------------------------------
- RECEIVE INTERRUPT: BOTTOM HALF HANDLERS
- ----------------------------------------------------------------------*/
-
-
-/*========================================================
- * bh_enqueue
- *
- * Description:
- * Insert a received packet into a circular
- * rx queue. This packet will be picked up
- * by fr_bh() and sent up the stack to the
- * user.
- *
- * Usage:
- * This function is called by rx interrupt,
- * in API mode.
- *
- */
-
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb)
-{
- /* Check for full */
- fr_channel_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
-
- if (atomic_read(&chan->bh_buff_used) == MAX_BH_BUFF){
- ++card->wandev.stats.rx_dropped;
- dev_kfree_skb_any(skb);
- return 1;
- }
-
- ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb;
-
- if (chan->bh_write == (MAX_BH_BUFF-1)){
- chan->bh_write=0;
- }else{
- ++chan->bh_write;
- }
-
- atomic_inc(&chan->bh_buff_used);
-
- return 0;
-}
-
-
-/*========================================================
- * trigger_fr_bh
- *
- * Description:
- * Kick the fr_bh() handler
- *
- * Usage:
- * rx interrupt calls this function during
- * the API mode.
- */
-
-static void trigger_fr_bh (fr_channel_t *chan)
-{
- if (!test_and_set_bit(0,&chan->tq_working)){
- wanpipe_queue_work(&chan->common.wanpipe_work);
- }
-}
-
-
-/*========================================================
- * fr_bh
- *
- * Description:
- * Frame relay receive BH handler.
- * Dequeue data from the BH circular
- * buffer and pass it up the API sock.
- *
- * Rationale:
- * This fuction is used to offload the
- * rx_interrupt during API operation mode.
- * The fr_bh() function executes for each
- * dlci/interface.
- *
- * Once receive interrupt copies data from the
- * card into an skb buffer, the skb buffer
- * is appended to a circular BH buffer.
- * Then the interrupt kicks fr_bh() to finish the
- * job at a later time (not within the interrupt).
- *
- * Usage:
- * Interrupts use this to defer a task to
- * a polling routine.
- *
- */
-
-static void fr_bh(struct net_device * dev)
-{
- fr_channel_t* chan = dev->priv;
- sdla_t *card = chan->card;
- struct sk_buff *skb;
-
- if (atomic_read(&chan->bh_buff_used) == 0){
- clear_bit(0, &chan->tq_working);
- return;
- }
-
- while (atomic_read(&chan->bh_buff_used)){
-
- if (chan->common.sk == NULL || chan->common.func == NULL){
- clear_bit(0, &chan->tq_working);
- return;
- }
-
- skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb;
-
- if (skb != NULL){
-
- if (chan->common.sk == NULL || chan->common.func == NULL){
- ++card->wandev.stats.rx_dropped;
- ++chan->ifstats.rx_dropped;
- dev_kfree_skb_any(skb);
- fr_bh_cleanup(dev);
- continue;
- }
-
- if (chan->common.func(skb,dev,chan->common.sk) != 0){
- /* Sock full cannot send, queue us for
- * another try */
- atomic_set(&chan->common.receive_block,1);
- return;
- }else{
- fr_bh_cleanup(dev);
- }
- }else{
- fr_bh_cleanup(dev);
- }
- }
- clear_bit(0, &chan->tq_working);
-
- return;
-}
-
-static int fr_bh_cleanup(struct net_device *dev)
-{
- fr_channel_t* chan = dev->priv;
-
- ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL;
-
- if (chan->bh_read == (MAX_BH_BUFF-1)){
- chan->bh_read=0;
- }else{
- ++chan->bh_read;
- }
-
- atomic_dec(&chan->bh_buff_used);
- return 0;
-}
-
-
-/*----------------------------------------------------------------------
- POLL BH HANDLERS AND KICK ROUTINES
- ----------------------------------------------------------------------*/
-
-/*============================================================
- * trigger_fr_poll
- *
- * Description:
- * Add a fr_poll() task into a tq_scheduler bh handler
- * for a specific dlci/interface. This will kick
- * the fr_poll() routine at a later time.
- *
- * Usage:
- * Interrupts use this to defer a taks to
- * a polling routine.
- *
- */
-static void trigger_fr_poll(struct net_device *dev)
-{
- fr_channel_t* chan = dev->priv;
- schedule_work(&chan->fr_poll_work);
- return;
-}
-
-
-/*============================================================
- * fr_poll
- *
- * Rationale:
- * We cannot manipulate the routing tables, or
- * ip addresses withing the interrupt. Therefore
- * we must perform such actons outside an interrupt
- * at a later time.
- *
- * Description:
- * Frame relay polling routine, responsible for
- * shutting down interfaces upon disconnect
- * and adding/removing routes.
- *
- * Usage:
- * This function is executed for each frame relay
- * dlci/interface through a tq_schedule bottom half.
- *
- * trigger_fr_poll() function is used to kick
- * the fr_poll routine.
- */
-
-static void fr_poll(struct net_device *dev)
-{
-
- fr_channel_t* chan;
- sdla_t *card;
- u8 check_gateway=0;
-
- if (!dev || (chan = dev->priv) == NULL)
- return;
-
- card = chan->card;
-
- /* (Re)Configuraiton is in progress, stop what you are
- * doing and get out */
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- return;
- }
-
- switch (chan->common.state){
-
- case WAN_DISCONNECTED:
-
- if (test_bit(DYN_OPT_ON,&chan->interface_down) &&
- !test_bit(DEV_DOWN, &chan->interface_down) &&
- dev->flags&IFF_UP){
-
- printk(KERN_INFO "%s: Interface %s is Down.\n",
- card->devname,dev->name);
- change_dev_flags(dev,dev->flags&~IFF_UP);
- set_bit(DEV_DOWN, &chan->interface_down);
- chan->route_flag = NO_ROUTE;
-
- }else{
- if (chan->inarp != INARP_NONE)
- process_route(dev);
- }
- break;
-
- case WAN_CONNECTED:
-
- if (test_bit(DYN_OPT_ON,&chan->interface_down) &&
- test_bit(DEV_DOWN, &chan->interface_down) &&
- !(dev->flags&IFF_UP)){
-
- printk(KERN_INFO "%s: Interface %s is Up.\n",
- card->devname,dev->name);
-
- change_dev_flags(dev,dev->flags|IFF_UP);
- clear_bit(DEV_DOWN, &chan->interface_down);
- check_gateway=1;
- }
-
- if (chan->inarp != INARP_NONE){
- process_route(dev);
- check_gateway=1;
- }
-
- if (chan->gateway && check_gateway)
- add_gateway(card,dev);
-
- break;
-
- }
-
- return;
-}
-
-/*==============================================================
- * check_tx_status
- *
- * Rationale:
- * We cannot transmit from an interrupt while
- * the if_send is transmitting data. Therefore,
- * we must check whether the tx buffers are
- * begin used, before we transmit from an
- * interrupt.
- *
- * Description:
- * Checks whether it's safe to use the transmit
- * buffers.
- *
- * Usage:
- * ARP and UDP handling routines use this function
- * because, they need to transmit data during
- * an interrupt.
- */
-
-static int check_tx_status(sdla_t *card, struct net_device *dev)
-{
-
- if (card->hw.type == SDLA_S514){
- if (test_bit(SEND_CRIT, (void*)&card->wandev.critical) ||
- test_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical)) {
- return 1;
- }
- }
-
- if (netif_queue_stopped(dev) || (card->u.f.tx_interrupts_pending))
- return 1;
-
- return 0;
-}
-
-/*===============================================================
- * move_dev_to_next
- *
- * Description:
- * Move the dev pointer to the next location in the
- * link list. Check if we are at the end of the
- * list, if so start from the begining.
- *
- * Usage:
- * Timer interrupt uses this function to efficiently
- * step through the devices that need to send ARP data.
- *
- */
-
-struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev)
-{
- if (card->wandev.new_if_cnt != 1){
- if (!*((struct net_device **)dev->priv))
- return card->wandev.dev;
- else
- return *((struct net_device **)dev->priv);
- }
- return dev;
-}
-
-/*==============================================================
- * trigger_config_fr
- *
- * Rationale:
- * All commands must be performed inside of a
- * interrupt.
- *
- * Description:
- * Kick the config_fr() routine throught the
- * timer interrupt.
- */
-
-
-static void trigger_config_fr (sdla_t *card)
-{
- fr508_flags_t* flags = card->flags;
-
- card->u.f.timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
- flags->imask |= FR_INTR_TIMER;
-}
-
-
-/*==============================================================
- * config_fr
- *
- * Rationale:
- * All commands must be performed inside of a
- * interrupt.
- &
- * Description:
- * Configure a DLCI. This function is executed
- * by a timer_interrupt. The if_open() function
- * triggers it.
- *
- * Usage:
- * new_if() collects all data necessary to
- * configure the DLCI. It sets the chan->dlci_ready
- * bit. When the if_open() function is executed
- * it checks this bit, and if its set it triggers
- * the timer interrupt to execute the config_fr()
- * function.
- */
-
-static void config_fr (sdla_t *card)
-{
- struct net_device *dev;
- fr_channel_t *chan;
-
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)) {
-
- if ((chan=dev->priv) == NULL)
- continue;
-
- if (!test_bit(0,&chan->config_dlci))
- continue;
-
- clear_bit(0,&chan->config_dlci);
-
- /* If signalling is set to NO, then setup
- * DLCI addresses right away. Don't have to wait for
- * link to connect.
- */
- if (card->wandev.signalling == WANOPT_NO){
- printk(KERN_INFO "%s: Signalling set to NO: Mapping DLCI's\n",
- card->wandev.name);
- if (fr_init_dlci(card,chan)){
- printk(KERN_INFO "%s: ERROR: Failed to configure DLCI %i !\n",
- card->devname, chan->dlci);
- return;
- }
- }
-
- if (card->wandev.station == WANOPT_CPE) {
-
- update_chan_state(dev);
-
- /* CPE: issue full status enquiry */
- fr_issue_isf(card, FR_ISF_FSE);
-
- } else {
- /* FR switch: activate DLCI(s) */
-
- /* For Switch emulation we have to ADD and ACTIVATE
- * the DLCI(s) that were configured with the SET_DLCI_
- * CONFIGURATION command. Add and Activate will fail if
- * DLCI specified is not included in the list.
- *
- * Also If_open is called once for each interface. But
- * it does not get in here for all the interface. So
- * we have to pass the entire list of DLCI(s) to add
- * activate routines.
- */
-
- if (!check_dlci_config (card, chan)){
- fr_add_dlci(card, chan->dlci);
- fr_activate_dlci(card, chan->dlci);
- }
- }
-
- card->u.f.dlci_to_dev_map[chan->dlci] = dev;
- }
- return;
-}
-
-
-/*==============================================================
- * config_fr
- *
- * Rationale:
- * All commands must be executed during an interrupt.
- *
- * Description:
- * Trigger uncofig_fr() function through
- * the timer interrupt.
- *
- */
-
-static void trigger_unconfig_fr(struct net_device *dev)
-{
- fr_channel_t *chan = dev->priv;
- volatile sdla_t *card = chan->card;
- unsigned long timeout;
- fr508_flags_t* flags = card->flags;
- int reset_critical=0;
-
- if (test_bit(PERI_CRIT,(void*)&card->wandev.critical)){
- clear_bit(PERI_CRIT,(void*)&card->wandev.critical);
- reset_critical=1;
- }
-
- /* run unconfig_dlci() function
- * throught the timer interrupt */
- set_bit(0,(void*)&chan->unconfig_dlci);
- card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UNCONFIG;
- flags->imask |= FR_INTR_TIMER;
-
- /* Wait for the command to complete */
- timeout = jiffies;
- for(;;) {
-
- if(!(card->u.f.timer_int_enabled & TMR_INT_ENABLED_UNCONFIG))
- break;
-
- if (time_after(jiffies, timeout + 1 * HZ)){
- card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UNCONFIG;
- printk(KERN_INFO "%s: Failed to delete DLCI %i\n",
- card->devname,chan->dlci);
- break;
- }
- }
-
- if (reset_critical){
- set_bit(PERI_CRIT,(void*)&card->wandev.critical);
- }
-}
-
-/*==============================================================
- * unconfig_fr
- *
- * Rationale:
- * All commands must be executed during an interrupt.
- *
- * Description:
- * Remove the dlci from firmware.
- * This funciton is used in NODE shutdown.
- */
-
-static void unconfig_fr (sdla_t *card)
-{
- struct net_device *dev;
- fr_channel_t *chan;
-
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)){
-
- if ((chan=dev->priv) == NULL)
- continue;
-
- if (!test_bit(0,&chan->unconfig_dlci))
- continue;
-
- clear_bit(0,&chan->unconfig_dlci);
-
- if (card->wandev.station == WANOPT_NODE){
- printk(KERN_INFO "%s: Unconfiguring DLCI %i\n",
- card->devname,chan->dlci);
- fr_delete_dlci(card,chan->dlci);
- }
- card->u.f.dlci_to_dev_map[chan->dlci] = NULL;
- }
-}
-
-static int setup_fr_header(struct sk_buff *skb, struct net_device* dev,
- char op_mode)
-{
- fr_channel_t *chan=dev->priv;
-
- if (op_mode == WANPIPE) {
- chan->fr_header[0]=Q922_UI;
-
- switch (htons(skb->protocol)){
- case ETH_P_IP:
- chan->fr_header[1]=NLPID_IP;
- break;
- default:
- return -EINVAL;
- }
-
- return 2;
- }
-
- /* If we are in bridging mode, we must apply
- * an Ethernet header
- */
- if (op_mode == BRIDGE || op_mode == BRIDGE_NODE) {
- /* Encapsulate the packet as a bridged Ethernet frame. */
-#ifdef DEBUG
- printk(KERN_INFO "%s: encapsulating skb for frame relay\n",
- dev->name);
-#endif
- chan->fr_header[0] = 0x03;
- chan->fr_header[1] = 0x00;
- chan->fr_header[2] = 0x80;
- chan->fr_header[3] = 0x00;
- chan->fr_header[4] = 0x80;
- chan->fr_header[5] = 0xC2;
- chan->fr_header[6] = 0x00;
- chan->fr_header[7] = 0x07;
-
- /* Yuck. */
- skb->protocol = ETH_P_802_3;
- return 8;
- }
-
- return 0;
-}
-
-
-static int check_dlci_config (sdla_t *card, fr_channel_t *chan)
-{
- fr_mbox_t* mbox = card->mbox;
- int err=0;
- fr_conf_t *conf=NULL;
- unsigned short dlci_num = chan->dlci;
- int dlci_offset=0;
- struct net_device *dev = NULL;
-
- mbox->cmd.command = FR_READ_CONFIG;
- mbox->cmd.length = 0;
- mbox->cmd.dlci = dlci_num;
-
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- if (err == CMD_OK){
- return 0;
- }
-
- for (dev = card->wandev.dev; dev;
- dev=*((struct net_device **)dev->priv))
- set_chan_state(dev,WAN_DISCONNECTED);
-
- printk(KERN_INFO "DLCI %i Not configured, configuring\n",dlci_num);
-
- mbox->cmd.command = FR_COMM_DISABLE;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err != CMD_OK){
- fr_event(card, err, mbox);
- return 2;
- }
-
- printk(KERN_INFO "Disabled Communications \n");
-
- mbox->cmd.command = FR_READ_CONFIG;
- mbox->cmd.length = 0;
- mbox->cmd.dlci = 0;
-
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK){
- fr_event(card, err, mbox);
- return 2;
- }
-
- conf = (fr_conf_t *)mbox->data;
-
- dlci_offset=0;
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)) {
- fr_channel_t *chan_tmp = dev->priv;
- conf->dlci[dlci_offset] = chan_tmp->dlci;
- dlci_offset++;
- }
-
- printk(KERN_INFO "Got Fr configuration Buffer Length is %x Dlci %i Dlci Off %i\n",
- mbox->cmd.length,
- mbox->cmd.length > 0x20 ? conf->dlci[0] : -1,
- dlci_offset );
-
- mbox->cmd.length = 0x20 + dlci_offset*2;
-
- mbox->cmd.command = FR_SET_CONFIG;
- mbox->cmd.dlci = 0;
-
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK){
- fr_event(card, err, mbox);
- return 2;
- }
-
- initialize_rx_tx_buffers (card);
-
-
- printk(KERN_INFO "Configuraiton Succeded for new DLCI %i\n",dlci_num);
-
- if (fr_comm_enable (card)){
- return 2;
- }
-
- printk(KERN_INFO "Enabling Communications \n");
-
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)) {
- fr_channel_t *chan_tmp = dev->priv;
- fr_init_dlci(card,chan_tmp);
- fr_add_dlci(card, chan_tmp->dlci);
- fr_activate_dlci(card, chan_tmp->dlci);
- }
-
- printk(KERN_INFO "END OF CONFIGURAITON %i\n",dlci_num);
-
- return 1;
-}
-
-static void initialize_rx_tx_buffers (sdla_t *card)
-{
- fr_buf_info_t* buf_info;
-
- if (card->hw.type == SDLA_S514) {
-
- buf_info = (void*)(card->hw.dpmbase + FR_MB_VECTOR +
- FR508_RXBC_OFFS);
-
- card->rxmb = (void*)(buf_info->rse_next + card->hw.dpmbase);
-
- card->u.f.rxmb_base =
- (void*)(buf_info->rse_base + card->hw.dpmbase);
-
- card->u.f.rxmb_last =
- (void*)(buf_info->rse_base +
- (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) +
- card->hw.dpmbase);
- }else{
- buf_info = (void*)(card->hw.dpmbase + FR508_RXBC_OFFS);
-
- card->rxmb = (void*)(buf_info->rse_next -
- FR_MB_VECTOR + card->hw.dpmbase);
-
- card->u.f.rxmb_base =
- (void*)(buf_info->rse_base -
- FR_MB_VECTOR + card->hw.dpmbase);
-
- card->u.f.rxmb_last =
- (void*)(buf_info->rse_base +
- (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) -
- FR_MB_VECTOR + card->hw.dpmbase);
- }
-
- card->u.f.rx_base = buf_info->buf_base;
- card->u.f.rx_top = buf_info->buf_top;
-
- card->u.f.tx_interrupts_pending = 0;
-
- return;
-}
-
-
-
-MODULE_LICENSE("GPL");
-
-/****** End *****************************************************************/
diff --git a/drivers/net/wan/sdla_ft1.c b/drivers/net/wan/sdla_ft1.c
deleted file mode 100644
index 9d6528a50f7..00000000000
--- a/drivers/net/wan/sdla_ft1.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*****************************************************************************
-* sdla_chdlc.c WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module.
-*
-* Authors: Nenad Corbic <ncorbic@sangoma.com>
-* Gideon Hack
-*
-* Copyright: (c) 1995-1999 Sangoma Technologies 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.
-* ============================================================================
-* Sep 30, 1999 Nenad Corbic Fixed dynamic IP and route setup.
-* Sep 23, 1999 Nenad Corbic Added SMP support, fixed tracing
-* Sep 13, 1999 Nenad Corbic Split up Port 0 and 1 into separate devices.
-* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
-* Oct 30, 1998 Jaspreet Singh Added Support for CHDLC API (HDLC STREAMING).
-* Oct 28, 1998 Jaspreet Singh Added Support for Dual Port CHDLC.
-* Aug 07, 1998 David Fong Initial version.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/if_arp.h> /* ARPHRD_* defines */
-#include <linux/jiffies.h> /* time_after() macro */
-
-#include <linux/inetdevice.h>
-#include <asm/uaccess.h>
-
-#include <linux/in.h> /* sockaddr_in */
-#include <linux/inet.h>
-#include <linux/if.h>
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <linux/sdlapci.h>
-#include <asm/io.h>
-
-#include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */
-
-/****** Defines & Macros ****************************************************/
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP 0x0001
-#define TMR_INT_ENABLED_UPDATE 0x0002
-
-#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */
-#define CHDLC_HDR_LEN 1
-
-#define IFF_POINTTOPOINT 0x10
-
-#define WANPIPE 0x00
-#define API 0x01
-#define CHDLC_API 0x01
-
-#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
-
-
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following
- * structure will incorporate the card structure along with CHDLC specific data
- */
-
-typedef struct chdlc_private_area
-{
- struct net_device *slave;
- sdla_t *card;
- int TracingEnabled; /* For enabling Tracing */
- unsigned long curr_trace_addr; /* Used for Tracing */
- unsigned long start_trace_addr;
- unsigned long end_trace_addr;
- unsigned long base_addr_trace_buffer;
- unsigned long end_addr_trace_buffer;
- unsigned short number_trace_elements;
- unsigned available_buffer_space;
- unsigned long router_start_time;
- unsigned char route_status;
- unsigned char route_removed;
- unsigned long tick_counter; /* For 5s timeout counter */
- unsigned long router_up_time;
- u32 IP_address; /* IP addressing */
- u32 IP_netmask;
- unsigned char mc; /* Mulitcast support on/off */
- unsigned short udp_pkt_lgth; /* udp packet processing */
- char udp_pkt_src;
- char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
- unsigned short timer_int_enabled;
- char update_comms_stats; /* updating comms stats */
- //FIXME: add driver stats as per frame relay!
-
-} chdlc_private_area_t;
-
-/* Route Status options */
-#define NO_ROUTE 0x00
-#define ADD_ROUTE 0x01
-#define ROUTE_ADDED 0x02
-#define REMOVE_ROUTE 0x03
-
-
-/****** Function Prototypes *************************************************/
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int wpft1_exec (struct sdla *card, void *u_cmd, void *u_data);
-static int chdlc_read_version (sdla_t* card, char* str);
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Cisco HDLC protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup. At this
- * point adapter is completely initialized and firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the adapter data space.
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-int wpft1_init (sdla_t* card, wandev_conf_t* conf)
-{
- unsigned char port_num;
- int err;
-
- union
- {
- char str[80];
- } u;
- volatile CHDLC_MAILBOX_STRUCT* mb;
- CHDLC_MAILBOX_STRUCT* mb1;
- unsigned long timeout;
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_CHDLC) {
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
- return -EINVAL;
- }
-
- /* Use primary port */
- card->u.c.comm_port = 0;
-
-
- /* Initialize protocol-specific fields */
- if(card->hw.type != SDLA_S514){
- card->mbox = (void *) card->hw.dpmbase;
- }else{
- card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
- }
-
- mb = mb1 = card->mbox;
-
- if (!card->configured){
-
- /* The board will place an 'I' in the return code to indicate that it is
- ready to accept commands. We expect this to be completed in less
- than 1 second. */
-
- timeout = jiffies;
- while (mb->return_code != 'I') /* Wait 1s for board to initialize */
- if (time_after(jiffies, timeout + 1*HZ)) break;
-
- if (mb->return_code != 'I') {
- printk(KERN_INFO
- "%s: Initialization not completed by adapter\n",
- card->devname);
- printk(KERN_INFO "Please contact Sangoma representative.\n");
- return -EIO;
- }
- }
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
-
- if (chdlc_read_version(card, u.str))
- return -EIO;
-
- printk(KERN_INFO "%s: Running FT1 Configuration firmware v%s\n",
- card->devname, u.str);
-
- card->isr = NULL;
- card->poll = NULL;
- card->exec = &wpft1_exec;
- card->wandev.update = NULL;
- card->wandev.new_if = NULL;
- card->wandev.del_if = NULL;
- card->wandev.state = WAN_DUALPORT;
- card->wandev.udp_port = conf->udp_port;
-
- card->wandev.new_if_cnt = 0;
-
- /* This is for the ports link state */
- card->u.c.state = WAN_DISCONNECTED;
-
- /* reset the number of times the 'update()' proc has been called */
- card->u.c.update_call_count = 0;
-
- card->wandev.ttl = 0x7F;
- card->wandev.interface = 0;
-
- card->wandev.clocking = 0;
-
- port_num = card->u.c.comm_port;
-
- /* Setup Port Bps */
-
- card->wandev.bps = 0;
-
- card->wandev.mtu = MIN_LGTH_CHDLC_DATA_CFG;
-
- /* Set up the interrupt status area */
- /* Read the CHDLC Configuration and obtain:
- * Ptr to shared memory infor struct
- * Use this pointer to calculate the value of card->u.c.flags !
- */
- mb1->buffer_length = 0;
- mb1->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
- if(err != COMMAND_OK) {
- chdlc_error(card, err, mb1);
- return -EIO;
- }
-
- if(card->hw.type == SDLA_S514){
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct));
- }else{
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
- }
-
- card->wandev.state = WAN_FT1_READY;
- printk(KERN_INFO "%s: FT1 Config Ready !\n",card->devname);
-
- return 0;
-}
-
-static int wpft1_exec(sdla_t *card, void *u_cmd, void *u_data)
-{
- CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
- int len;
-
- if (copy_from_user((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t))){
- return -EFAULT;
- }
-
- len = mbox->buffer_length;
-
- if (len) {
- if( copy_from_user((void*)&mbox->data, u_data, len)){
- return -EFAULT;
- }
- }
-
- /* execute command */
- if (!sdla_exec(mbox)){
- return -EIO;
- }
-
- /* return result */
- if( copy_to_user(u_cmd, (void*)&mbox->command, sizeof(ft1_exec_cmd_t))){
- return -EFAULT;
- }
-
- len = mbox->buffer_length;
-
- if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)){
- return -EFAULT;
- }
-
- return 0;
-
-}
-
-/*============================================================================
- * Read firmware code version.
- * Put code version as ASCII string in str.
- */
-static int chdlc_read_version (sdla_t* card, char* str)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int len;
- char err;
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CODE_VERSION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- }
- else if (str) { /* is not null */
- len = mb->buffer_length;
- memcpy(str, mb->data, len);
- str[len] = '\0';
- }
- return (err);
-}
-
-/*============================================================================
- * Firmware error handler.
- * This routine is called whenever firmware command returns non-zero
- * return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
-{
- unsigned cmd = mb->command;
-
- switch (err) {
-
- case CMD_TIMEOUT:
- printk(KERN_ERR "%s: command 0x%02X timed out!\n",
- card->devname, cmd);
- break;
-
- case S514_BOTH_PORTS_SAME_CLK_MODE:
- if(cmd == SET_CHDLC_CONFIGURATION) {
- printk(KERN_INFO
- "%s: Configure both ports for the same clock source\n",
- card->devname);
- break;
- }
-
- default:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
- card->devname, cmd, err);
- }
-
- return 0;
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c
deleted file mode 100644
index a4b489cccbb..00000000000
--- a/drivers/net/wan/sdla_ppp.c
+++ /dev/null
@@ -1,3430 +0,0 @@
-/*****************************************************************************
-* sdla_ppp.c WANPIPE(tm) Multiprotocol WAN Link Driver. PPP module.
-*
-* Author: Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright: (c) 1995-2001 Sangoma Technologies 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.
-* ============================================================================
-* Feb 28, 2001 Nenad Corbic o Updated if_tx_timeout() routine for
-* 2.4.X kernels.
-* Nov 29, 2000 Nenad Corbic o Added the 2.4.x kernel support:
-* get_ip_address() function has moved
-* into the ppp_poll() routine. It cannot
-* be called from an interrupt.
-* Nov 07, 2000 Nenad Corbic o Added security features for UDP debugging:
-* Deny all and specify allowed requests.
-* May 02, 2000 Nenad Corbic o Added the dynamic interface shutdown
-* option. When the link goes down, the
-* network interface IFF_UP flag is reset.
-* Mar 06, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery.
-* Feb 25, 2000 Nenad Corbic o Fixed the FT1 UDP debugger problem.
-* Feb 09, 2000 Nenad Coribc o Shutdown bug fix. update() was called
-* with NULL dev pointer: no check.
-* Jan 24, 2000 Nenad Corbic o Disabled use of CMD complete inter.
-* Dev 15, 1999 Nenad Corbic o Fixed up header files for 2.0.X kernels
-* Oct 25, 1999 Nenad Corbic o Support for 2.0.X kernels
-* Moved dynamic route processing into
-* a polling routine.
-* Oct 07, 1999 Nenad Corbic o Support for S514 PCI card.
-* Gideon Hack o UPD and Updates executed using timer interrupt
-* Sep 10, 1999 Nenad Corbic o Fixed up the /proc statistics
-* Jul 20, 1999 Nenad Corbic o Remove the polling routines and use
-* interrupts instead.
-* Sep 17, 1998 Jaspreet Singh o Updates for 2.2.X Kernels.
-* Aug 13, 1998 Jaspreet Singh o Improved Line Tracing.
-* Jun 22, 1998 David Fong o Added remote IP address assignment
-* Mar 15, 1998 Alan Cox o 2.1.8x basic port.
-* Apr 16, 1998 Jaspreet Singh o using htons() for the IPX protocol.
-* Dec 09, 1997 Jaspreet Singh o Added PAP and CHAP.
-* o Implemented new routines like
-* ppp_set_inbnd_auth(), ppp_set_outbnd_auth(),
-* tokenize() and strstrip().
-* Nov 27, 1997 Jaspreet Singh o Added protection against enabling of irqs
-* while they have been disabled.
-* Nov 24, 1997 Jaspreet Singh o Fixed another RACE condition caused by
-* disabling and enabling of irqs.
-* o Added new counters for stats on disable/enable
-* IRQs.
-* Nov 10, 1997 Jaspreet Singh o Initialized 'skb->mac.raw' to 'skb->data'
-* before every netif_rx().
-* o Free up the device structure in del_if().
-* Nov 07, 1997 Jaspreet Singh o Changed the delay to zero for Line tracing
-* command.
-* Oct 20, 1997 Jaspreet Singh o Added hooks in for Router UP time.
-* Oct 16, 1997 Jaspreet Singh o The critical flag is used to maintain flow
-* control by avoiding RACE conditions. The
-* cli() and restore_flags() are taken out.
-* A new structure, "ppp_private_area", is added
-* to provide Driver Statistics.
-* Jul 21, 1997 Jaspreet Singh o Protected calls to sdla_peek() by adding
-* save_flags(), cli() and restore_flags().
-* Jul 07, 1997 Jaspreet Singh o Added configurable TTL for UDP packets
-* o Added ability to discard mulitcast and
-* broacast source addressed packets.
-* Jun 27, 1997 Jaspreet Singh o Added FT1 monitor capabilities
-* New case (0x25) statement in if_send routine.
-* Added a global variable rCount to keep track
-* of FT1 status enabled on the board.
-* May 22, 1997 Jaspreet Singh o Added change in the PPP_SET_CONFIG command for
-* 508 card to reflect changes in the new
-* ppp508.sfm for supporting:continous transmission
-* of Configure-Request packets without receiving a
-* reply
-* OR-ed 0x300 to conf_flags
-* o Changed connect_tmout from 900 to 0
-* May 21, 1997 Jaspreet Singh o Fixed UDP Management for multiple boards
-* Apr 25, 1997 Farhan Thawar o added UDP Management stuff
-* Mar 11, 1997 Farhan Thawar Version 3.1.1
-* o fixed (+1) bug in rx_intr()
-* o changed if_send() to return 0 if
-* wandev.critical() is true
-* o free socket buffer in if_send() if
-* returning 0
-* Jan 15, 1997 Gene Kozin Version 3.1.0
-* o implemented exec() entry point
-* Jan 06, 1997 Gene Kozin Initial version.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/if_arp.h> /* ARPHRD_* defines */
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <linux/in.h> /* sockaddr_in */
-#include <linux/jiffies.h> /* time_after() macro */
-
-
-#include <asm/uaccess.h>
-#include <linux/inetdevice.h>
-#include <linux/netdevice.h>
-
-#include <linux/if.h>
-#include <linux/sdla_ppp.h> /* PPP firmware API definitions */
-#include <linux/sdlasfm.h> /* S514 Type Definition */
-/****** Defines & Macros ****************************************************/
-
-#define PPP_DFLT_MTU 1500 /* default MTU */
-#define PPP_MAX_MTU 4000 /* maximum MTU */
-#define PPP_HDR_LEN 1
-
-#define MAX_IP_ERRORS 100
-
-#define CONNECT_TIMEOUT (90*HZ) /* link connection timeout */
-#define HOLD_DOWN_TIME (5*HZ) /* link hold down time : Changed from 30 to 5 */
-
-/* For handle_IPXWAN() */
-#define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b)))
-
-/* Macro for enabling/disabling debugging comments */
-//#define NEX_DEBUG
-#ifdef NEX_DEBUG
-#define NEX_PRINTK(format, a...) printk(format, ## a)
-#else
-#define NEX_PRINTK(format, a...)
-#endif /* NEX_DEBUG */
-
-#define DCD(a) ( a & 0x08 ? "HIGH" : "LOW" )
-#define CTS(a) ( a & 0x20 ? "HIGH" : "LOW" )
-#define LCP(a) ( a == 0x09 ? "OPEN" : "CLOSED" )
-#define IP(a) ( a == 0x09 ? "ENABLED" : "DISABLED" )
-
-#define TMR_INT_ENABLED_UPDATE 0x01
-#define TMR_INT_ENABLED_PPP_EVENT 0x02
-#define TMR_INT_ENABLED_UDP 0x04
-#define TMR_INT_ENABLED_CONFIG 0x20
-
-/* Set Configuraton Command Definitions */
-#define PERCENT_TX_BUFF 60
-#define TIME_BETWEEN_CONF_REQ 30
-#define TIME_BETWEEN_PAP_CHAP_REQ 30
-#define WAIT_PAP_CHAP_WITHOUT_REPLY 300
-#define WAIT_AFTER_DCD_CTS_LOW 5
-#define TIME_DCD_CTS_LOW_AFTER_LNK_DOWN 10
-#define WAIT_DCD_HIGH_AFTER_ENABLE_COMM 900
-#define MAX_CONF_REQ_WITHOUT_REPLY 10
-#define MAX_TERM_REQ_WITHOUT_REPLY 2
-#define NUM_CONF_NAK_WITHOUT_REPLY 5
-#define NUM_AUTH_REQ_WITHOUT_REPLY 10
-
-#define END_OFFSET 0x1F0
-
-
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following
- * structure will incorporate the card structure along with PPP specific data
- */
-
-typedef struct ppp_private_area
-{
- struct net_device *slave;
- sdla_t* card;
- unsigned long router_start_time; /*router start time in sec */
- unsigned long tick_counter; /*used for 5 second counter*/
- unsigned mc; /*multicast support on or off*/
- unsigned char enable_IPX;
- unsigned long network_number;
- unsigned char pap;
- unsigned char chap;
- unsigned char sysname[31]; /* system name for in-bnd auth*/
- unsigned char userid[511]; /* list of user ids */
- unsigned char passwd[511]; /* list of passwords */
- unsigned protocol; /* SKB Protocol */
- u32 ip_local; /* Local IP Address */
- u32 ip_remote; /* remote IP Address */
-
- u32 ip_local_tmp;
- u32 ip_remote_tmp;
-
- unsigned char timer_int_enabled; /* Who enabled the timer inter*/
- unsigned char update_comms_stats; /* Used by update function */
- unsigned long curr_trace_addr; /* Trace information */
- unsigned long start_trace_addr;
- unsigned long end_trace_addr;
-
- unsigned char interface_down; /* Brind down interface when channel
- goes down */
- unsigned long config_wait_timeout; /* After if_open() if in dynamic if mode,
- wait a few seconds before configuring */
-
- unsigned short udp_pkt_lgth;
- char udp_pkt_src;
- char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
-
- /* PPP specific statistics */
-
- if_send_stat_t if_send_stat;
- rx_intr_stat_t rx_intr_stat;
- pipe_mgmt_stat_t pipe_mgmt_stat;
-
- unsigned long router_up_time;
-
- /* Polling work queue entry. Each interface
- * has its own work queue entry, which is used
- * to defer events from the interrupt */
- struct work_struct poll_work;
- struct timer_list poll_delay_timer;
-
- u8 gateway;
- u8 config_ppp;
- u8 ip_error;
-
-}ppp_private_area_t;
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/****** Function Prototypes *************************************************/
-
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device *wandev);
-static int new_if(struct wan_device *wandev, struct net_device *dev,
- wanif_conf_t *conf);
-static int del_if(struct wan_device *wandev, struct net_device *dev);
-
-/* WANPIPE-specific entry points */
-static int wpp_exec (struct sdla *card, void *u_cmd, void *u_data);
-
-/* Network device interface */
-static int if_init(struct net_device *dev);
-static int if_open(struct net_device *dev);
-static int if_close(struct net_device *dev);
-static int if_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type,
- void *daddr, void *saddr, unsigned len);
-
-static void if_tx_timeout(struct net_device *dev);
-
-static int if_rebuild_hdr(struct sk_buff *skb);
-static struct net_device_stats *if_stats(struct net_device *dev);
-static int if_send(struct sk_buff *skb, struct net_device *dev);
-
-
-/* PPP firmware interface functions */
-static int ppp_read_version(sdla_t *card, char *str);
-static int ppp_set_outbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area);
-static int ppp_set_inbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area);
-static int ppp_configure(sdla_t *card, void *data);
-static int ppp_set_intr_mode(sdla_t *card, unsigned char mode);
-static int ppp_comm_enable(sdla_t *card);
-static int ppp_comm_disable(sdla_t *card);
-static int ppp_comm_disable_shutdown(sdla_t *card);
-static int ppp_get_err_stats(sdla_t *card);
-static int ppp_send(sdla_t *card, void *data, unsigned len, unsigned proto);
-static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb);
-
-static void wpp_isr(sdla_t *card);
-static void rx_intr(sdla_t *card);
-static void event_intr(sdla_t *card);
-static void timer_intr(sdla_t *card);
-
-/* Background polling routines */
-static void process_route(sdla_t *card);
-static void retrigger_comm(sdla_t *card);
-
-/* Miscellaneous functions */
-static int read_info( sdla_t *card );
-static int read_connection_info (sdla_t *card);
-static void remove_route( sdla_t *card );
-static int config508(struct net_device *dev, sdla_t *card);
-static void show_disc_cause(sdla_t * card, unsigned cause);
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev,
- ppp_private_area_t *ppp_priv_area);
-static void init_ppp_tx_rx_buff( sdla_t *card );
-static int intr_test( sdla_t *card );
-static int udp_pkt_type( struct sk_buff *skb , sdla_t *card);
-static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area);
-static void init_global_statistics( sdla_t *card );
-static int tokenize(char *str, char **tokens);
-static char* strstrip(char *str, char *s);
-static int chk_bcast_mcast_addr(sdla_t* card, struct net_device* dev,
- struct sk_buff *skb);
-
-static int config_ppp (sdla_t *);
-static void ppp_poll(struct net_device *dev);
-static void trigger_ppp_poll(struct net_device *dev);
-static void ppp_poll_delay (unsigned long dev_ptr);
-
-
-static int Read_connection_info;
-static int Intr_test_counter;
-static unsigned short available_buffer_space;
-
-
-/* IPX functions */
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number,
- unsigned char incoming);
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_PX,
- unsigned long network_number, unsigned short proto);
-
-/* Lock Functions */
-static void s508_lock (sdla_t *card, unsigned long *smp_flags);
-static void s508_unlock (sdla_t *card, unsigned long *smp_flags);
-
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- ppp_private_area_t* ppp_priv_area );
-static unsigned short calc_checksum (char *data, int len);
-static void disable_comm (sdla_t *card);
-static int detect_and_fix_tx_bug (sdla_t *card);
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * PPP protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup. At this
- * point adapter is completely initialized and firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the adapter data space.
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-int wpp_init(sdla_t *card, wandev_conf_t *conf)
-{
- ppp_flags_t *flags;
- union
- {
- char str[80];
- } u;
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_PPP) {
-
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
- return -EINVAL;
-
- }
-
- /* Initialize miscellaneous pointers to structures on the adapter */
- switch (card->hw.type) {
-
- case SDLA_S508:
- card->mbox =(void*)(card->hw.dpmbase + PPP508_MB_OFFS);
- card->flags=(void*)(card->hw.dpmbase + PPP508_FLG_OFFS);
- break;
-
- case SDLA_S514:
- card->mbox =(void*)(card->hw.dpmbase + PPP514_MB_OFFS);
- card->flags=(void*)(card->hw.dpmbase + PPP514_FLG_OFFS);
- break;
-
- default:
- return -EINVAL;
-
- }
- flags = card->flags;
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
- if (ppp_read_version(card, NULL) || ppp_read_version(card, u.str))
- return -EIO;
-
- printk(KERN_INFO "%s: running PPP firmware v%s\n",card->devname, u.str);
- /* Adjust configuration and set defaults */
- card->wandev.mtu = (conf->mtu) ?
- min_t(unsigned int, conf->mtu, PPP_MAX_MTU) : PPP_DFLT_MTU;
-
- card->wandev.bps = conf->bps;
- card->wandev.interface = conf->interface;
- card->wandev.clocking = conf->clocking;
- card->wandev.station = conf->station;
- card->isr = &wpp_isr;
- card->poll = NULL;
- card->exec = &wpp_exec;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = &del_if;
- card->wandev.udp_port = conf->udp_port;
- card->wandev.ttl = conf->ttl;
- card->wandev.state = WAN_DISCONNECTED;
- card->disable_comm = &disable_comm;
- card->irq_dis_if_send_count = 0;
- card->irq_dis_poll_count = 0;
- card->u.p.authenticator = conf->u.ppp.authenticator;
- card->u.p.ip_mode = conf->u.ppp.ip_mode ?
- conf->u.ppp.ip_mode : WANOPT_PPP_STATIC;
- card->TracingEnabled = 0;
- Read_connection_info = 1;
-
- /* initialize global statistics */
- init_global_statistics( card );
-
-
-
- if (!card->configured){
- int err;
-
- Intr_test_counter = 0;
- err = intr_test(card);
-
- if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) {
- printk("%s: Interrupt Test Failed, Counter: %i\n",
- card->devname, Intr_test_counter);
- printk( "%s: Please choose another interrupt\n",card->devname);
- return -EIO;
- }
-
- printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n",
- card->devname, Intr_test_counter);
- card->configured = 1;
- }
-
- ppp_set_intr_mode(card, PPP_INTR_TIMER);
-
- /* Turn off the transmit and timer interrupt */
- flags->imask &= ~PPP_INTR_TIMER;
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics.
- */
-static int update(struct wan_device *wandev)
-{
- sdla_t* card = wandev->private;
- struct net_device* dev;
- volatile ppp_private_area_t *ppp_priv_area;
- ppp_flags_t *flags = card->flags;
- unsigned long timeout;
-
- /* sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
-
- if (wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- /* Shutdown bug fix. This function can be
- * called with NULL dev pointer during
- * shutdown
- */
- if ((dev=card->wandev.dev) == NULL){
- return -ENODEV;
- }
-
- if ((ppp_priv_area=dev->priv) == NULL){
- return -ENODEV;
- }
-
- ppp_priv_area->update_comms_stats = 2;
- ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UPDATE;
- flags->imask |= PPP_INTR_TIMER;
-
- /* wait a maximum of 1 second for the statistics to be updated */
- timeout = jiffies;
- for(;;) {
- if(ppp_priv_area->update_comms_stats == 0){
- break;
- }
- if (time_after(jiffies, timeout + 1 * HZ)){
- ppp_priv_area->update_comms_stats = 0;
- ppp_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- return -EAGAIN;
- }
- }
-
- return 0;
-}
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return: 0 o.k.
- * < 0 failure (channel will not be created)
- */
-static int new_if(struct wan_device *wandev, struct net_device *dev,
- wanif_conf_t *conf)
-{
- sdla_t *card = wandev->private;
- ppp_private_area_t *ppp_priv_area;
-
- if (wandev->ndev)
- return -EEXIST;
-
-
- printk(KERN_INFO "%s: Configuring Interface: %s\n",
- card->devname, conf->name);
-
- if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
-
- printk(KERN_INFO "%s: Invalid interface name!\n",
- card->devname);
- return -EINVAL;
-
- }
-
- /* allocate and initialize private data */
- ppp_priv_area = kmalloc(sizeof(ppp_private_area_t), GFP_KERNEL);
-
- if( ppp_priv_area == NULL )
- return -ENOMEM;
-
- memset(ppp_priv_area, 0, sizeof(ppp_private_area_t));
-
- ppp_priv_area->card = card;
-
- /* initialize data */
- strcpy(card->u.p.if_name, conf->name);
-
- /* initialize data in ppp_private_area structure */
-
- init_ppp_priv_struct( ppp_priv_area );
-
- ppp_priv_area->mc = conf->mc;
- ppp_priv_area->pap = conf->pap;
- ppp_priv_area->chap = conf->chap;
-
- /* Option to bring down the interface when
- * the link goes down */
- if (conf->if_down){
- set_bit(DYN_OPT_ON,&ppp_priv_area->interface_down);
- printk("%s: Dynamic interface configuration enabled\n",
- card->devname);
- }
-
- /* If no user ids are specified */
- if(!strlen(conf->userid) && (ppp_priv_area->pap||ppp_priv_area->chap)){
- kfree(ppp_priv_area);
- return -EINVAL;
- }
-
- /* If no passwords are specified */
- if(!strlen(conf->passwd) && (ppp_priv_area->pap||ppp_priv_area->chap)){
- kfree(ppp_priv_area);
- return -EINVAL;
- }
-
- if(strlen(conf->sysname) > 31){
- kfree(ppp_priv_area);
- return -EINVAL;
- }
-
- /* If no system name is specified */
- if(!strlen(conf->sysname) && (card->u.p.authenticator)){
- kfree(ppp_priv_area);
- return -EINVAL;
- }
-
- /* copy the data into the ppp private structure */
- memcpy(ppp_priv_area->userid, conf->userid, strlen(conf->userid));
- memcpy(ppp_priv_area->passwd, conf->passwd, strlen(conf->passwd));
- memcpy(ppp_priv_area->sysname, conf->sysname, strlen(conf->sysname));
-
-
- ppp_priv_area->enable_IPX = conf->enable_IPX;
- if (conf->network_number){
- ppp_priv_area->network_number = conf->network_number;
- }else{
- ppp_priv_area->network_number = 0xDEADBEEF;
- }
-
- /* Tells us that if this interface is a
- * gateway or not */
- if ((ppp_priv_area->gateway = conf->gateway) == WANOPT_YES){
- printk(KERN_INFO "%s: Interface %s is set as a gateway.\n",
- card->devname,card->u.p.if_name);
- }
-
- /* prepare network device data space for registration */
- strcpy(dev->name,card->u.p.if_name);
-
- dev->init = &if_init;
- dev->priv = ppp_priv_area;
- dev->mtu = min_t(unsigned int, dev->mtu, card->wandev.mtu);
-
- /* Initialize the polling work routine */
- INIT_WORK(&ppp_priv_area->poll_work, (void*)(void*)ppp_poll, dev);
-
- /* Initialize the polling delay timer */
- init_timer(&ppp_priv_area->poll_delay_timer);
- ppp_priv_area->poll_delay_timer.data = (unsigned long)dev;
- ppp_priv_area->poll_delay_timer.function = ppp_poll_delay;
-
-
- /* Since we start with dummy IP addresses we can say
- * that route exists */
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/*============================================================================
- * Delete logical channel.
- */
-static int del_if(struct wan_device *wandev, struct net_device *dev)
-{
- return 0;
-}
-
-static void disable_comm (sdla_t *card)
-{
- ppp_comm_disable_shutdown(card);
- return;
-}
-
-/****** WANPIPE-specific entry points ***************************************/
-
-/*============================================================================
- * Execute adapter interface command.
- */
-
-//FIXME: Why do we need this ????
-static int wpp_exec(struct sdla *card, void *u_cmd, void *u_data)
-{
- ppp_mbox_t *mbox = card->mbox;
- int len;
-
- if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t)))
- return -EFAULT;
-
- len = mbox->cmd.length;
-
- if (len) {
-
- if( copy_from_user((void*)&mbox->data, u_data, len))
- return -EFAULT;
-
- }
-
- /* execute command */
- if (!sdla_exec(mbox))
- return -EIO;
-
- /* return result */
- if( copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(ppp_cmd_t)))
- return -EFAULT;
- len = mbox->cmd.length;
-
- if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len))
- return -EFAULT;
-
- return 0;
-}
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration. Returning anything but zero will fail interface
- * registration.
- */
-static int if_init(struct net_device *dev)
-{
- ppp_private_area_t *ppp_priv_area = dev->priv;
- sdla_t *card = ppp_priv_area->card;
- struct wan_device *wandev = &card->wandev;
-
- /* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_header = &if_header;
- dev->rebuild_header = &if_rebuild_hdr;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
- dev->tx_timeout = &if_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- /* Initialize media-specific parameters */
- dev->type = ARPHRD_PPP; /* ARP h/w type */
- dev->flags |= IFF_POINTOPOINT;
- dev->flags |= IFF_NOARP;
-
- /* Enable Mulitcasting if specified by user*/
- if (ppp_priv_area->mc == WANOPT_YES){
- dev->flags |= IFF_MULTICAST;
- }
-
- dev->mtu = wandev->mtu;
- dev->hard_header_len = PPP_HDR_LEN; /* media header length */
-
- /* Initialize hardware parameters (just for reference) */
- dev->irq = wandev->irq;
- dev->dma = wandev->dma;
- dev->base_addr = wandev->ioport;
- dev->mem_start = wandev->maddr;
- dev->mem_end = wandev->maddr + wandev->msize - 1;
-
- /* Set transmit buffer queue length */
- dev->tx_queue_len = 100;
- SET_MODULE_OWNER(dev);
-
- return 0;
-}
-
-/*============================================================================
- * Open network interface.
- * o enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device *dev)
-{
- ppp_private_area_t *ppp_priv_area = dev->priv;
- sdla_t *card = ppp_priv_area->card;
- struct timeval tv;
- //unsigned long smp_flags;
-
- if (netif_running(dev))
- return -EBUSY;
-
- wanpipe_open(card);
-
- netif_start_queue(dev);
-
- do_gettimeofday( &tv );
- ppp_priv_area->router_start_time = tv.tv_sec;
-
- /* We cannot configure the card here because we don't
- * have access to the interface IP addresses.
- * Once the interface initilization is complete, we will be
- * able to access the IP addresses. Therefore,
- * configure the ppp link in the poll routine */
- set_bit(0,&ppp_priv_area->config_ppp);
- ppp_priv_area->config_wait_timeout=jiffies;
-
- /* Start the PPP configuration after 1sec delay.
- * This will give the interface initilization time
- * to finish its configuration */
- mod_timer(&ppp_priv_area->poll_delay_timer, jiffies + HZ);
- return 0;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last open, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device *dev)
-{
- ppp_private_area_t *ppp_priv_area = dev->priv;
- sdla_t *card = ppp_priv_area->card;
-
- netif_stop_queue(dev);
- wanpipe_close(card);
-
- del_timer (&ppp_priv_area->poll_delay_timer);
- return 0;
-}
-
-/*============================================================================
- * Build media header.
- *
- * The trick here is to put packet type (Ethertype) into 'protocol' field of
- * the socket buffer, so that we don't forget it. If packet type is not
- * supported, set skb->protocol to 0 and discard packet later.
- *
- * Return: media header length.
- */
-static int if_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, void *daddr, void *saddr, unsigned len)
-{
- switch (type)
- {
- case ETH_P_IP:
- case ETH_P_IPX:
- skb->protocol = htons(type);
- break;
-
- default:
- skb->protocol = 0;
- }
-
- return PPP_HDR_LEN;
-}
-
-/*============================================================================
- * Re-build media header.
- *
- * Return: 1 physical address resolved.
- * 0 physical address not resolved
- */
-static int if_rebuild_hdr (struct sk_buff *skb)
-{
- struct net_device *dev = skb->dev;
- ppp_private_area_t *ppp_priv_area = dev->priv;
- sdla_t *card = ppp_priv_area->card;
-
- printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",
- card->devname, dev->name);
- return 1;
-}
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
- ppp_private_area_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- /* If our device stays busy for at least 5 seconds then we will
- * kick start the device by making dev->tbusy = 0. We expect
- * that our device never stays busy more than 5 seconds. So this
- * is only used as a last resort.
- */
-
- ++ chan->if_send_stat.if_send_tbusy;
- ++card->wandev.stats.collisions;
-
- printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
- ++chan->if_send_stat.if_send_tbusy_timeout;
- netif_wake_queue (dev);
-}
-
-
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- * transmit from overlapping.
- * o check link state. If link is not up, then drop the packet.
- * o execute adapter send command.
- * o free socket buffer
- *
- * Return: 0 complete (socket buffer must be freed)
- * non-0 packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- * bottom half" (with interrupts enabled).
- * 2. Setting tbusy flag will inhibit further transmit requests from the
- * protocol stack and can be used for flow control with protocol layer.
- */
-static int if_send (struct sk_buff *skb, struct net_device *dev)
-{
- ppp_private_area_t *ppp_priv_area = dev->priv;
- sdla_t *card = ppp_priv_area->card;
- unsigned char *sendpacket;
- unsigned long smp_flags;
- ppp_flags_t *flags = card->flags;
- int udp_type;
- int err=0;
-
- ++ppp_priv_area->if_send_stat.if_send_entry;
-
- netif_stop_queue(dev);
-
- if (skb == NULL) {
-
- /* If we get here, some higher layer thinks we've missed an
- * tx-done interrupt.
- */
- printk(KERN_INFO "%s: interface %s got kicked!\n",
- card->devname, dev->name);
-
- ++ppp_priv_area->if_send_stat.if_send_skb_null;
-
- netif_wake_queue(dev);
- return 0;
- }
-
- sendpacket = skb->data;
-
- udp_type = udp_pkt_type( skb, card );
-
-
- if (udp_type == UDP_PTPIPE_TYPE){
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev,
- ppp_priv_area)){
- flags->imask |= PPP_INTR_TIMER;
- }
- ++ppp_priv_area->if_send_stat.if_send_PIPE_request;
- netif_start_queue(dev);
- return 0;
- }
-
- /* Check for broadcast and multicast addresses
- * If found, drop (deallocate) a packet and return.
- */
- if(chk_bcast_mcast_addr(card, dev, skb)){
- ++card->wandev.stats.tx_dropped;
- dev_kfree_skb_any(skb);
- netif_start_queue(dev);
- return 0;
- }
-
-
- if(card->hw.type != SDLA_S514){
- s508_lock(card,&smp_flags);
- }
-
- if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
-
- printk(KERN_INFO "%s: Critical in if_send: %lx\n",
- card->wandev.name,card->wandev.critical);
-
- ++card->wandev.stats.tx_dropped;
- ++ppp_priv_area->if_send_stat.if_send_critical_non_ISR;
- netif_start_queue(dev);
- goto if_send_exit_crit;
- }
-
- if (card->wandev.state != WAN_CONNECTED) {
-
- ++ppp_priv_area->if_send_stat.if_send_wan_disconnected;
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
-
- } else if (!skb->protocol) {
- ++ppp_priv_area->if_send_stat.if_send_protocol_error;
- ++card->wandev.stats.tx_errors;
- netif_start_queue(dev);
-
- } else {
-
- /*If it's IPX change the network numbers to 0 if they're ours.*/
- if( skb->protocol == htons(ETH_P_IPX) ) {
- if(ppp_priv_area->enable_IPX) {
- switch_net_numbers( skb->data,
- ppp_priv_area->network_number, 0);
- } else {
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
- goto if_send_exit_crit;
- }
- }
-
- if (ppp_send(card, skb->data, skb->len, skb->protocol)) {
- netif_stop_queue(dev);
- ++ppp_priv_area->if_send_stat.if_send_adptr_bfrs_full;
- ++ppp_priv_area->if_send_stat.if_send_tx_int_enabled;
- } else {
- ++ppp_priv_area->if_send_stat.if_send_bfr_passed_to_adptr;
- ++card->wandev.stats.tx_packets;
- card->wandev.stats.tx_bytes += skb->len;
- netif_start_queue(dev);
- dev->trans_start = jiffies;
- }
- }
-
-if_send_exit_crit:
-
- if (!(err=netif_queue_stopped(dev))){
- dev_kfree_skb_any(skb);
- }else{
- ppp_priv_area->tick_counter = jiffies;
- flags->imask |= PPP_INTR_TXRDY; /* unmask Tx interrupts */
- }
-
- clear_bit(SEND_CRIT,&card->wandev.critical);
- if(card->hw.type != SDLA_S514){
- s508_unlock(card,&smp_flags);
- }
-
- return err;
-}
-
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- ppp_private_area_t* ppp_priv_area )
-{
- int udp_pkt_stored = 0;
-
- if(!ppp_priv_area->udp_pkt_lgth && (skb->len<=MAX_LGTH_UDP_MGNT_PKT)){
- ppp_priv_area->udp_pkt_lgth = skb->len;
- ppp_priv_area->udp_pkt_src = udp_pkt_src;
- memcpy(ppp_priv_area->udp_pkt_data, skb->data, skb->len);
- ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UDP;
- ppp_priv_area->protocol = skb->protocol;
- udp_pkt_stored = 1;
- }else{
- if (skb->len > MAX_LGTH_UDP_MGNT_PKT){
- printk(KERN_INFO "%s: PIPEMON UDP request too long : %i\n",
- card->devname, skb->len);
- }else{
- printk(KERN_INFO "%s: PIPEMON UPD request already pending\n",
- card->devname);
- }
- ppp_priv_area->udp_pkt_lgth = 0;
- }
-
- if(udp_pkt_src == UDP_PKT_FRM_STACK){
- dev_kfree_skb_any(skb);
- }else{
- dev_kfree_skb_any(skb);
- }
-
- return(udp_pkt_stored);
-}
-
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return length of reply.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
- unsigned short len, udp_length, temp, ip_length;
- unsigned long ip_temp;
- int even_bound = 0;
- ppp_udp_pkt_t *p_udp_pkt = (ppp_udp_pkt_t *)data;
-
- /* Set length of packet */
- len = sizeof(ip_pkt_t)+
- sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- mbox_len;
-
- /* fill in UDP reply */
- p_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-
- /* fill in UDP length */
- udp_length = sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- mbox_len;
-
-
- /* put it on an even boundary */
- if ( udp_length & 0x0001 ) {
- udp_length += 1;
- len += 1;
- even_bound=1;
- }
-
- temp = (udp_length<<8)|(udp_length>>8);
- p_udp_pkt->udp_pkt.udp_length = temp;
-
-
- /* swap UDP ports */
- temp = p_udp_pkt->udp_pkt.udp_src_port;
- p_udp_pkt->udp_pkt.udp_src_port =
- p_udp_pkt->udp_pkt.udp_dst_port;
- p_udp_pkt->udp_pkt.udp_dst_port = temp;
-
-
- /* add UDP pseudo header */
- temp = 0x1100;
- *((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound)) = temp;
- temp = (udp_length<<8)|(udp_length>>8);
- *((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
- /* calculate UDP checksum */
- p_udp_pkt->udp_pkt.udp_checksum = 0;
- p_udp_pkt->udp_pkt.udp_checksum =
- calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET);
-
- /* fill in IP length */
- ip_length = udp_length + sizeof(ip_pkt_t);
- temp = (ip_length<<8)|(ip_length>>8);
- p_udp_pkt->ip_pkt.total_length = temp;
-
- /* swap IP addresses */
- ip_temp = p_udp_pkt->ip_pkt.ip_src_address;
- p_udp_pkt->ip_pkt.ip_src_address = p_udp_pkt->ip_pkt.ip_dst_address;
- p_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
- /* fill in IP checksum */
- p_udp_pkt->ip_pkt.hdr_checksum = 0;
- p_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t));
-
- return len;
-
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
- unsigned short temp;
- unsigned long sum=0;
- int i;
-
- for( i = 0; i <len; i+=2 ) {
- memcpy(&temp,&data[i],2);
- sum += (unsigned long)temp;
- }
-
- while (sum >> 16 ) {
- sum = (sum & 0xffffUL) + (sum >> 16);
- }
-
- temp = (unsigned short)sum;
- temp = ~temp;
-
- if( temp == 0 )
- temp = 0xffff;
-
- return temp;
-}
-
-/*
- If incoming is 0 (outgoing)- if the net numbers is ours make it 0
- if incoming is 1 - if the net number is 0 make it ours
-
-*/
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming)
-{
- unsigned long pnetwork_number;
-
- pnetwork_number = (unsigned long)((sendpacket[6] << 24) +
- (sendpacket[7] << 16) + (sendpacket[8] << 8) +
- sendpacket[9]);
-
- if (!incoming) {
- //If the destination network number is ours, make it 0
- if( pnetwork_number == network_number) {
- sendpacket[6] = sendpacket[7] = sendpacket[8] =
- sendpacket[9] = 0x00;
- }
- } else {
- //If the incoming network is 0, make it ours
- if( pnetwork_number == 0) {
- sendpacket[6] = (unsigned char)(network_number >> 24);
- sendpacket[7] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[8] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[9] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-
-
- pnetwork_number = (unsigned long)((sendpacket[18] << 24) +
- (sendpacket[19] << 16) + (sendpacket[20] << 8) +
- sendpacket[21]);
-
- if( !incoming ) {
- //If the source network is ours, make it 0
- if( pnetwork_number == network_number) {
- sendpacket[18] = sendpacket[19] = sendpacket[20] =
- sendpacket[21] = 0x00;
- }
- } else {
- //If the source network is 0, make it ours
- if( pnetwork_number == 0 ) {
- sendpacket[18] = (unsigned char)(network_number >> 24);
- sendpacket[19] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[20] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[21] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-} /* switch_net_numbers */
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct net_device_stats.
- */
-static struct net_device_stats *if_stats(struct net_device *dev)
-{
-
- ppp_private_area_t *ppp_priv_area = dev->priv;
- sdla_t* card;
-
- if( ppp_priv_area == NULL )
- return NULL;
-
- card = ppp_priv_area->card;
- return &card->wandev.stats;
-}
-
-/****** PPP Firmware Interface Functions ************************************/
-
-/*============================================================================
- * Read firmware code version.
- * Put code version as ASCII string in str.
- */
-static int ppp_read_version(sdla_t *card, char *str)
-{
- ppp_mbox_t *mb = card->mbox;
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.command = PPP_READ_CODE_VERSION;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK)
-
- ppp_error(card, err, mb);
-
- else if (str) {
-
- int len = mb->cmd.length;
-
- memcpy(str, mb->data, len);
- str[len] = '\0';
-
- }
-
- return err;
-}
-/*===========================================================================
- * Set Out-Bound Authentication.
-*/
-static int ppp_set_outbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area)
-{
- ppp_mbox_t *mb = card->mbox;
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- memset(&mb->data, 0, (strlen(ppp_priv_area->userid) +
- strlen(ppp_priv_area->passwd) + 2 ) );
- memcpy(mb->data, ppp_priv_area->userid, strlen(ppp_priv_area->userid));
- memcpy((mb->data + strlen(ppp_priv_area->userid) + 1),
- ppp_priv_area->passwd, strlen(ppp_priv_area->passwd));
-
- mb->cmd.length = strlen(ppp_priv_area->userid) +
- strlen(ppp_priv_area->passwd) + 2 ;
-
- mb->cmd.command = PPP_SET_OUTBOUND_AUTH;
-
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK)
- ppp_error(card, err, mb);
-
- return err;
-}
-
-/*===========================================================================
- * Set In-Bound Authentication.
-*/
-static int ppp_set_inbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area)
-{
- ppp_mbox_t *mb = card->mbox;
- int err, i;
- char* user_tokens[32];
- char* pass_tokens[32];
- int userids, passwds;
- int add_ptr;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- memset(&mb->data, 0, 1008);
- memcpy(mb->data, ppp_priv_area->sysname,
- strlen(ppp_priv_area->sysname));
-
- /* Parse the userid string and the password string and build a string
- to copy it to the data area of the command structure. The string
- will look like "SYS_NAME<NULL>USER1<NULL>PASS1<NULL>USER2<NULL>PASS2
- ....<NULL> "
- */
- userids = tokenize( ppp_priv_area->userid, user_tokens);
- passwds = tokenize( ppp_priv_area->passwd, pass_tokens);
-
- if (userids != passwds){
- printk(KERN_INFO "%s: Number of passwords does not equal the number of user ids\n", card->devname);
- return 1;
- }
-
- add_ptr = strlen(ppp_priv_area->sysname) + 1;
- for (i=0; i<userids; i++){
- memcpy((mb->data + add_ptr), user_tokens[i],
- strlen(user_tokens[i]));
- memcpy((mb->data + add_ptr + strlen(user_tokens[i]) + 1),
- pass_tokens[i], strlen(pass_tokens[i]));
- add_ptr = add_ptr + strlen(user_tokens[i]) + 1 +
- strlen(pass_tokens[i]) + 1;
- }
-
- mb->cmd.length = add_ptr + 1;
- mb->cmd.command = PPP_SET_INBOUND_AUTH;
-
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK)
- ppp_error(card, err, mb);
-
- return err;
-}
-
-
-/*============================================================================
- * Tokenize string.
- * Parse a string of the following syntax:
- * <arg1>,<arg2>,...
- * and fill array of tokens with pointers to string elements.
- *
- */
-static int tokenize (char *str, char **tokens)
-{
- int cnt = 0;
-
- tokens[0] = strsep(&str, "/");
- while (tokens[cnt] && (cnt < 32 - 1))
- {
- tokens[cnt] = strstrip(tokens[cnt], " \t");
- tokens[++cnt] = strsep(&str, "/");
- }
- return cnt;
-}
-
-/*============================================================================
- * Strip leading and trailing spaces off the string str.
- */
-static char* strstrip (char *str, char* s)
-{
- char *eos = str + strlen(str); /* -> end of string */
-
- while (*str && strchr(s, *str))
- ++str /* strip leading spaces */
- ;
- while ((eos > str) && strchr(s, *(eos - 1)))
- --eos /* strip trailing spaces */
- ;
- *eos = '\0';
- return str;
-}
-/*============================================================================
- * Configure PPP firmware.
- */
-static int ppp_configure(sdla_t *card, void *data)
-{
- ppp_mbox_t *mb = card->mbox;
- int data_len = sizeof(ppp508_conf_t);
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- memcpy(mb->data, data, data_len);
- mb->cmd.length = data_len;
- mb->cmd.command = PPP_SET_CONFIG;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK)
- ppp_error(card, err, mb);
-
- return err;
-}
-
-/*============================================================================
- * Set interrupt mode.
- */
-static int ppp_set_intr_mode(sdla_t *card, unsigned char mode)
-{
- ppp_mbox_t *mb = card->mbox;
- ppp_intr_info_t *ppp_intr_data = (ppp_intr_info_t *) &mb->data[0];
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- ppp_intr_data->i_enable = mode;
-
- ppp_intr_data->irq = card->hw.irq;
- mb->cmd.length = 2;
-
- /* If timer has been enabled, set the timer delay to 1sec */
- if (mode & 0x80){
- ppp_intr_data->timer_len = 250; //5;//100; //250;
- mb->cmd.length = 4;
- }
-
- mb->cmd.command = PPP_SET_INTR_FLAGS;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK)
- ppp_error(card, err, mb);
-
-
- return err;
-}
-
-/*============================================================================
- * Enable communications.
- */
-static int ppp_comm_enable(sdla_t *card)
-{
- ppp_mbox_t *mb = card->mbox;
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.command = PPP_COMM_ENABLE;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK)
- ppp_error(card, err, mb);
- else
- card->u.p.comm_enabled = 1;
-
- return err;
-}
-
-/*============================================================================
- * Disable communications.
- */
-static int ppp_comm_disable(sdla_t *card)
-{
- ppp_mbox_t *mb = card->mbox;
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.command = PPP_COMM_DISABLE;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
- if (err != CMD_OK)
- ppp_error(card, err, mb);
- else
- card->u.p.comm_enabled = 0;
-
- return err;
-}
-
-static int ppp_comm_disable_shutdown(sdla_t *card)
-{
- ppp_mbox_t *mb = card->mbox;
- ppp_intr_info_t *ppp_intr_data;
- int err;
-
- if (!mb){
- return 1;
- }
-
- ppp_intr_data = (ppp_intr_info_t *) &mb->data[0];
-
- /* Disable all interrupts */
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- ppp_intr_data->i_enable = 0;
-
- ppp_intr_data->irq = card->hw.irq;
- mb->cmd.length = 2;
-
- mb->cmd.command = PPP_SET_INTR_FLAGS;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- /* Disable communicatinons */
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.command = PPP_COMM_DISABLE;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- card->u.p.comm_enabled = 0;
-
- return 0;
-}
-
-
-
-/*============================================================================
- * Get communications error statistics.
- */
-static int ppp_get_err_stats(sdla_t *card)
-{
- ppp_mbox_t *mb = card->mbox;
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.command = PPP_READ_ERROR_STATS;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err == CMD_OK) {
-
- ppp_err_stats_t* stats = (void*)mb->data;
- card->wandev.stats.rx_over_errors = stats->rx_overrun;
- card->wandev.stats.rx_crc_errors = stats->rx_bad_crc;
- card->wandev.stats.rx_missed_errors = stats->rx_abort;
- card->wandev.stats.rx_length_errors = stats->rx_lost;
- card->wandev.stats.tx_aborted_errors = stats->tx_abort;
-
- } else
- ppp_error(card, err, mb);
-
- return err;
-}
-
-/*============================================================================
- * Send packet.
- * Return: 0 - o.k.
- * 1 - no transmit buffers available
- */
-static int ppp_send (sdla_t *card, void *data, unsigned len, unsigned proto)
-{
- ppp_buf_ctl_t *txbuf = card->u.p.txbuf;
-
- if (txbuf->flag)
- return 1;
-
- sdla_poke(&card->hw, txbuf->buf.ptr, data, len);
-
- txbuf->length = len; /* frame length */
-
- if (proto == htons(ETH_P_IPX))
- txbuf->proto = 0x01; /* protocol ID */
- else
- txbuf->proto = 0x00; /* protocol ID */
-
- txbuf->flag = 1; /* start transmission */
-
- /* Update transmit buffer control fields */
- card->u.p.txbuf = ++txbuf;
-
- if ((void*)txbuf > card->u.p.txbuf_last)
- card->u.p.txbuf = card->u.p.txbuf_base;
-
- return 0;
-}
-
-/****** Firmware Error Handler **********************************************/
-
-/*============================================================================
- * Firmware error handler.
- * This routine is called whenever firmware command returns non-zero
- * return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb)
-{
- unsigned cmd = mb->cmd.command;
-
- switch (err) {
-
- case CMD_TIMEOUT:
- printk(KERN_ERR "%s: command 0x%02X timed out!\n",
- card->devname, cmd);
- break;
-
- default:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n"
- , card->devname, cmd, err);
- }
-
- return 0;
-}
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * PPP interrupt service routine.
- */
-static void wpp_isr (sdla_t *card)
-{
- ppp_flags_t *flags = card->flags;
- char *ptr = &flags->iflag;
- struct net_device *dev = card->wandev.dev;
- int i;
-
- card->in_isr = 1;
- ++card->statistics.isr_entry;
-
- if (!dev && flags->iflag != PPP_INTR_CMD){
- card->in_isr = 0;
- flags->iflag = 0;
- return;
- }
-
- if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
- card->in_isr = 0;
- flags->iflag = 0;
- return;
- }
-
-
- if(card->hw.type != SDLA_S514){
- if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
- ++card->statistics.isr_already_critical;
- printk (KERN_INFO "%s: Critical while in ISR!\n",
- card->devname);
- card->in_isr = 0;
- flags->iflag = 0;
- return;
- }
- }
-
- switch (flags->iflag) {
-
- case PPP_INTR_RXRDY: /* receive interrupt 0x01 (bit 0)*/
- ++card->statistics.isr_rx;
- rx_intr(card);
- break;
-
- case PPP_INTR_TXRDY: /* transmit interrupt 0x02 (bit 1)*/
- ++card->statistics.isr_tx;
- flags->imask &= ~PPP_INTR_TXRDY;
- netif_wake_queue(dev);
- break;
-
- case PPP_INTR_CMD: /* interface command completed */
- ++Intr_test_counter;
- ++card->statistics.isr_intr_test;
- break;
-
- case PPP_INTR_MODEM: /* modem status change (DCD, CTS) 0x04 (bit 2)*/
- case PPP_INTR_DISC: /* Data link disconnected 0x10 (bit 4)*/
- case PPP_INTR_OPEN: /* Data link open 0x20 (bit 5)*/
- case PPP_INTR_DROP_DTR: /* DTR drop timeout expired 0x40 bit 6 */
- event_intr(card);
- break;
-
- case PPP_INTR_TIMER:
- timer_intr(card);
- break;
-
- default: /* unexpected interrupt */
- ++card->statistics.isr_spurious;
- printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n",
- card->devname, flags->iflag);
- printk(KERN_INFO "%s: ID Bytes = ",card->devname);
- for(i = 0; i < 8; i ++)
- printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));
- printk(KERN_INFO "\n");
- }
-
- card->in_isr = 0;
- flags->iflag = 0;
- return;
-}
-
-/*============================================================================
- * Receive interrupt handler.
- */
-static void rx_intr(sdla_t *card)
-{
- ppp_buf_ctl_t *rxbuf = card->rxmb;
- struct net_device *dev = card->wandev.dev;
- ppp_private_area_t *ppp_priv_area;
- struct sk_buff *skb;
- unsigned len;
- void *buf;
- int i;
- ppp_flags_t *flags = card->flags;
- char *ptr = &flags->iflag;
- int udp_type;
-
-
- if (rxbuf->flag != 0x01) {
-
- printk(KERN_INFO
- "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n",
- card->devname, (unsigned)rxbuf, rxbuf->flag);
-
- printk(KERN_INFO "%s: ID Bytes = ",card->devname);
-
- for(i = 0; i < 8; i ++)
- printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));
- printk(KERN_INFO "\n");
-
- ++card->statistics.rx_intr_corrupt_rx_bfr;
-
-
- /* Bug Fix: Mar 6 2000
- * If we get a corrupted mailbox, it means that driver
- * is out of sync with the firmware. There is no recovery.
- * If we don't turn off all interrupts for this card
- * the machine will crash.
- */
- printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
- printk(KERN_INFO "Please contact Sangoma Technologies !\n");
- ppp_set_intr_mode(card,0);
- return;
- }
-
- if (dev && netif_running(dev) && dev->priv){
-
- len = rxbuf->length;
- ppp_priv_area = dev->priv;
-
- /* Allocate socket buffer */
- skb = dev_alloc_skb(len);
-
- if (skb != NULL) {
-
- /* Copy data to the socket buffer */
- unsigned addr = rxbuf->buf.ptr;
-
- if ((addr + len) > card->u.p.rx_top + 1) {
-
- unsigned tmp = card->u.p.rx_top - addr + 1;
- buf = skb_put(skb, tmp);
- sdla_peek(&card->hw, addr, buf, tmp);
- addr = card->u.p.rx_base;
- len -= tmp;
- }
- buf = skb_put(skb, len);
- sdla_peek(&card->hw, addr, buf, len);
-
- /* Decapsulate packet */
- switch (rxbuf->proto) {
-
- case 0x00:
- skb->protocol = htons(ETH_P_IP);
- break;
-
- case 0x01:
- skb->protocol = htons(ETH_P_IPX);
- break;
- }
-
- udp_type = udp_pkt_type( skb, card );
-
- if (udp_type == UDP_PTPIPE_TYPE){
-
- /* Handle a UDP Request in Timer Interrupt */
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, card, skb, dev,
- ppp_priv_area)){
- flags->imask |= PPP_INTR_TIMER;
- }
- ++ppp_priv_area->rx_intr_stat.rx_intr_PIPE_request;
-
-
- } else if (handle_IPXWAN(skb->data,card->devname,
- ppp_priv_area->enable_IPX,
- ppp_priv_area->network_number,
- skb->protocol)) {
-
- /* Handle an IPXWAN packet */
- if( ppp_priv_area->enable_IPX) {
-
- /* Make sure we are not already sending */
- if (!test_bit(SEND_CRIT, &card->wandev.critical)){
- ppp_send(card, skb->data, skb->len, htons(ETH_P_IPX));
- }
- dev_kfree_skb_any(skb);
-
- } else {
- ++card->wandev.stats.rx_dropped;
- }
- } else {
- /* Pass data up the protocol stack */
- skb->dev = dev;
- skb->mac.raw = skb->data;
-
- ++card->wandev.stats.rx_packets;
- card->wandev.stats.rx_bytes += skb->len;
- ++ppp_priv_area->rx_intr_stat.rx_intr_bfr_passed_to_stack;
- netif_rx(skb);
- dev->last_rx = jiffies;
- }
-
- } else {
-
- if (net_ratelimit()){
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- }
- ++card->wandev.stats.rx_dropped;
- ++ppp_priv_area->rx_intr_stat.rx_intr_no_socket;
- }
-
- } else {
- ++card->statistics.rx_intr_dev_not_started;
- }
-
- /* Release buffer element and calculate a pointer to the next one */
- rxbuf->flag = 0x00;
- card->rxmb = ++rxbuf;
- if ((void*)rxbuf > card->u.p.rxbuf_last)
- card->rxmb = card->u.p.rxbuf_base;
-}
-
-
-void event_intr (sdla_t *card)
-{
-
- struct net_device* dev = card->wandev.dev;
- ppp_private_area_t* ppp_priv_area = dev->priv;
- volatile ppp_flags_t *flags = card->flags;
-
- switch (flags->iflag){
-
- case PPP_INTR_MODEM: /* modem status change (DCD, CTS) 0x04 (bit 2)*/
-
- if (net_ratelimit()){
- printk (KERN_INFO "%s: Modem status: DCD=%s CTS=%s\n",
- card->devname, DCD(flags->mstatus), CTS(flags->mstatus));
- }
- break;
-
- case PPP_INTR_DISC: /* Data link disconnected 0x10 (bit 4)*/
-
- NEX_PRINTK (KERN_INFO "Data link disconnected intr Cause %X\n",
- flags->disc_cause);
-
- if (flags->disc_cause &
- (PPP_LOCAL_TERMINATION | PPP_DCD_CTS_DROP |
- PPP_REMOTE_TERMINATION)) {
-
- if (card->u.p.ip_mode == WANOPT_PPP_PEER) {
- set_bit(0,&Read_connection_info);
- }
- wanpipe_set_state(card, WAN_DISCONNECTED);
-
- show_disc_cause(card, flags->disc_cause);
- ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT;
- flags->imask |= PPP_INTR_TIMER;
- trigger_ppp_poll(dev);
- }
- break;
-
- case PPP_INTR_OPEN: /* Data link open 0x20 (bit 5)*/
-
- NEX_PRINTK (KERN_INFO "%s: PPP Link Open, LCP=%s IP=%s\n",
- card->devname,LCP(flags->lcp_state),
- IP(flags->ip_state));
-
- if (flags->lcp_state == 0x09 &&
- (flags->ip_state == 0x09 || flags->ipx_state == 0x09)){
-
- /* Initialize the polling timer and set the state
- * to WAN_CONNNECTED */
-
-
- /* BUG FIX: When the protocol restarts, during heavy
- * traffic, board tx buffers and driver tx buffers
- * can go out of sync. This checks the condition
- * and if the tx buffers are out of sync, the
- * protocols are restarted.
- * I don't know why the board tx buffer is out
- * of sync. It could be that a packets is tx
- * while the link is down, but that is not
- * possible. The other possiblility is that the
- * firmware doesn't reinitialize properly.
- * FIXME: A better fix should be found.
- */
- if (detect_and_fix_tx_bug(card)){
-
- ppp_comm_disable(card);
-
- wanpipe_set_state(card, WAN_DISCONNECTED);
-
- ppp_priv_area->timer_int_enabled |=
- TMR_INT_ENABLED_PPP_EVENT;
- flags->imask |= PPP_INTR_TIMER;
- break;
- }
-
- card->state_tick = jiffies;
- wanpipe_set_state(card, WAN_CONNECTED);
-
- NEX_PRINTK(KERN_INFO "CON: L Tx: %lx B Tx: %lx || L Rx %lx B Rx %lx\n",
- (unsigned long)card->u.p.txbuf, *card->u.p.txbuf_next,
- (unsigned long)card->rxmb, *card->u.p.rxbuf_next);
-
- /* Tell timer interrupt that PPP event occurred */
- ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT;
- flags->imask |= PPP_INTR_TIMER;
-
- /* If we are in PEER mode, we must first obtain the
- * IP information and then go into the poll routine */
- if (card->u.p.ip_mode != WANOPT_PPP_PEER){
- trigger_ppp_poll(dev);
- }
- }
- break;
-
- case PPP_INTR_DROP_DTR: /* DTR drop timeout expired 0x40 bit 6 */
-
- NEX_PRINTK(KERN_INFO "DTR Drop Timeout Interrrupt \n");
-
- if (card->u.p.ip_mode == WANOPT_PPP_PEER) {
- set_bit(0,&Read_connection_info);
- }
-
- wanpipe_set_state(card, WAN_DISCONNECTED);
-
- show_disc_cause(card, flags->disc_cause);
- ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT;
- flags->imask |= PPP_INTR_TIMER;
- trigger_ppp_poll(dev);
- break;
-
- default:
- printk(KERN_INFO "%s: Error, Invalid PPP Event\n",card->devname);
- }
-}
-
-
-
-/* TIMER INTERRUPT */
-
-void timer_intr (sdla_t *card)
-{
-
- struct net_device* dev = card->wandev.dev;
- ppp_private_area_t* ppp_priv_area = dev->priv;
- ppp_flags_t *flags = card->flags;
-
-
- if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG){
- if (!config_ppp(card)){
- ppp_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_CONFIG;
- }
- }
-
- /* Update statistics */
- if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE){
- ppp_get_err_stats(card);
- if(!(--ppp_priv_area->update_comms_stats)){
- ppp_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- }
- }
-
- /* PPIPEMON UDP request */
-
- if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP){
- process_udp_mgmt_pkt(card,dev, ppp_priv_area);
- ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP;
- }
-
- /* PPP Event */
- if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_PPP_EVENT){
-
- if (card->wandev.state == WAN_DISCONNECTED){
- retrigger_comm(card);
- }
-
- /* If the state is CONNECTING, it means that communicatins were
- * enabled. When the remote side enables its comminication we
- * should get an interrupt PPP_INTR_OPEN, thus turn off polling
- */
-
- else if (card->wandev.state == WAN_CONNECTING){
- /* Turn off the timer interrupt */
- ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT;
- }
-
- /* If state is connected and we are in PEER mode
- * poll for an IP address which will be provided by remote end.
- */
- else if ((card->wandev.state == WAN_CONNECTED &&
- card->u.p.ip_mode == WANOPT_PPP_PEER) &&
- test_bit(0,&Read_connection_info)){
-
- card->state_tick = jiffies;
- if (read_connection_info (card)){
- printk(KERN_INFO "%s: Failed to read PEER IP Addresses\n",
- card->devname);
- }else{
- clear_bit(0,&Read_connection_info);
- set_bit(1,&Read_connection_info);
- trigger_ppp_poll(dev);
- }
- }else{
- //FIXME Put the comment back int
- ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT;
- }
-
- }/* End of PPP_EVENT */
-
-
- /* Only disable the timer interrupt if there are no udp, statistic */
- /* updates or events pending */
- if(!ppp_priv_area->timer_int_enabled) {
- flags->imask &= ~PPP_INTR_TIMER;
- }
-}
-
-
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto)
-{
- int i;
-
- if( proto == htons(ETH_P_IPX) ) {
- //It's an IPX packet
- if(!enable_IPX) {
- //Return 1 so we don't pass it up the stack.
- return 1;
- }
- } else {
- //It's not IPX so pass it up the stack.
- return 0;
- }
-
- if( sendpacket[16] == 0x90 &&
- sendpacket[17] == 0x04)
- {
- //It's IPXWAN
-
- if( sendpacket[2] == 0x02 &&
- sendpacket[34] == 0x00)
- {
- //It's a timer request packet
- printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname);
-
- //Go through the routing options and answer no to every
- //option except Unnumbered RIP/SAP
- for(i = 41; sendpacket[i] == 0x00; i += 5)
- {
- //0x02 is the option for Unnumbered RIP/SAP
- if( sendpacket[i + 4] != 0x02)
- {
- sendpacket[i + 1] = 0;
- }
- }
-
- //Skip over the extended Node ID option
- if( sendpacket[i] == 0x04 )
- {
- i += 8;
- }
-
- //We also want to turn off all header compression opt.
- for(; sendpacket[i] == 0x80 ;)
- {
- sendpacket[i + 1] = 0;
- i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4;
- }
-
- //Set the packet type to timer response
- sendpacket[34] = 0x01;
-
- printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname);
- }
- else if( sendpacket[34] == 0x02 )
- {
- //This is an information request packet
- printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname);
-
- //Set the packet type to information response
- sendpacket[34] = 0x03;
-
- //Set the router name
- sendpacket[51] = 'P';
- sendpacket[52] = 'T';
- sendpacket[53] = 'P';
- sendpacket[54] = 'I';
- sendpacket[55] = 'P';
- sendpacket[56] = 'E';
- sendpacket[57] = '-';
- sendpacket[58] = CVHexToAscii(network_number >> 28);
- sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24);
- sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20);
- sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16);
- sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12);
- sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8);
- sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4);
- sendpacket[65] = CVHexToAscii(network_number & 0x0000000F);
- for(i = 66; i < 99; i+= 1)
- {
- sendpacket[i] = 0;
- }
-
- printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname);
- }
- else
- {
- printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname);
- return 0;
- }
-
- //Set the WNodeID to our network address
- sendpacket[35] = (unsigned char)(network_number >> 24);
- sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16);
- sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8);
- sendpacket[38] = (unsigned char)(network_number & 0x000000FF);
-
- return 1;
- } else {
- //If we get here it's an IPX-data packet, so it'll get passed up the stack.
-
- //switch the network numbers
- switch_net_numbers(sendpacket, network_number, 1);
- return 0;
- }
-}
-
-/****** Background Polling Routines ****************************************/
-
-/* All polling functions are invoked by the TIMER interrupt in the wpp_isr
- * routine.
- */
-
-/*============================================================================
- * Monitor active link phase.
- */
-static void process_route (sdla_t *card)
-{
- ppp_flags_t *flags = card->flags;
- struct net_device *dev = card->wandev.dev;
- ppp_private_area_t *ppp_priv_area = dev->priv;
-
- if ((card->u.p.ip_mode == WANOPT_PPP_PEER) &&
- (flags->ip_state == 0x09)){
-
- /* We get ip_local from the firmware in PEER mode.
- * Therefore, if ip_local is 0, we failed to obtain
- * the remote IP address. */
- if (ppp_priv_area->ip_local == 0)
- return;
-
- printk(KERN_INFO "%s: IPCP State Opened.\n", card->devname);
- if (read_info( card )) {
- printk(KERN_INFO
- "%s: An error occurred in IP assignment.\n",
- card->devname);
- } else {
- struct in_device *in_dev = dev->ip_ptr;
- if (in_dev != NULL ) {
- struct in_ifaddr *ifa = in_dev->ifa_list;
-
- printk(KERN_INFO "%s: Assigned Lcl. Addr: %u.%u.%u.%u\n",
- card->devname, NIPQUAD(ifa->ifa_local));
- printk(KERN_INFO "%s: Assigned Rmt. Addr: %u.%u.%u.%u\n",
- card->devname, NIPQUAD(ifa->ifa_address));
- }else{
- printk(KERN_INFO
- "%s: Error: Failed to add a route for PPP interface %s\n",
- card->devname,dev->name);
- }
- }
- }
-}
-
-/*============================================================================
- * Monitor physical link disconnected phase.
- * o if interface is up and the hold-down timeout has expired, then retry
- * connection.
- */
-static void retrigger_comm(sdla_t *card)
-{
- struct net_device *dev = card->wandev.dev;
-
- if (dev && ((jiffies - card->state_tick) > HOLD_DOWN_TIME)) {
-
- wanpipe_set_state(card, WAN_CONNECTING);
-
- if(ppp_comm_enable(card) == CMD_OK){
- init_ppp_tx_rx_buff( card );
- }
- }
-}
-
-/****** Miscellaneous Functions *********************************************/
-
-/*============================================================================
- * Configure S508 adapter.
- */
-static int config508(struct net_device *dev, sdla_t *card)
-{
- ppp508_conf_t cfg;
- struct in_device *in_dev = dev->ip_ptr;
- ppp_private_area_t *ppp_priv_area = dev->priv;
-
- /* Prepare PPP configuration structure */
- memset(&cfg, 0, sizeof(ppp508_conf_t));
-
- if (card->wandev.clocking)
- cfg.line_speed = card->wandev.bps;
-
- if (card->wandev.interface == WANOPT_RS232)
- cfg.conf_flags |= INTERFACE_LEVEL_RS232;
-
-
- cfg.conf_flags |= DONT_TERMINATE_LNK_MAX_CONFIG; /*send Configure-Request packets forever*/
- cfg.txbuf_percent = PERCENT_TX_BUFF; /* % of Tx bufs */
- cfg.mtu_local = card->wandev.mtu;
- cfg.mtu_remote = card->wandev.mtu; /* Default */
- cfg.restart_tmr = TIME_BETWEEN_CONF_REQ; /* 30 = 3sec */
- cfg.auth_rsrt_tmr = TIME_BETWEEN_PAP_CHAP_REQ; /* 30 = 3sec */
- cfg.auth_wait_tmr = WAIT_PAP_CHAP_WITHOUT_REPLY; /* 300 = 30s */
- cfg.mdm_fail_tmr = WAIT_AFTER_DCD_CTS_LOW; /* 5 = 0.5s */
- cfg.dtr_drop_tmr = TIME_DCD_CTS_LOW_AFTER_LNK_DOWN; /* 10 = 1s */
- cfg.connect_tmout = WAIT_DCD_HIGH_AFTER_ENABLE_COMM; /* 900 = 90s */
- cfg.conf_retry = MAX_CONF_REQ_WITHOUT_REPLY; /* 10 = 1s */
- cfg.term_retry = MAX_TERM_REQ_WITHOUT_REPLY; /* 2 times */
- cfg.fail_retry = NUM_CONF_NAK_WITHOUT_REPLY; /* 5 times */
- cfg.auth_retry = NUM_AUTH_REQ_WITHOUT_REPLY; /* 10 times */
-
-
- if( !card->u.p.authenticator ) {
- printk(KERN_INFO "%s: Device is not configured as an authenticator\n",
- card->devname);
- cfg.auth_options = NO_AUTHENTICATION;
- }else{
- printk(KERN_INFO "%s: Device is configured as an authenticator\n",
- card->devname);
- cfg.auth_options = INBOUND_AUTH;
- }
-
- if( ppp_priv_area->pap == WANOPT_YES){
- cfg.auth_options |=PAP_AUTH;
- printk(KERN_INFO "%s: Pap enabled\n", card->devname);
- }
- if( ppp_priv_area->chap == WANOPT_YES){
- cfg.auth_options |= CHAP_AUTH;
- printk(KERN_INFO "%s: Chap enabled\n", card->devname);
- }
-
-
- if (ppp_priv_area->enable_IPX == WANOPT_YES){
- printk(KERN_INFO "%s: Enabling IPX Protocol\n",card->devname);
- cfg.ipx_options = ENABLE_IPX | ROUTING_PROT_DEFAULT;
- }else{
- cfg.ipx_options = DISABLE_IPX;
- }
-
- switch (card->u.p.ip_mode) {
-
- case WANOPT_PPP_STATIC:
-
- printk(KERN_INFO "%s: PPP IP Mode: STATIC\n",card->devname);
- cfg.ip_options = L_AND_R_IP_NO_ASSIG |
- ENABLE_IP;
- cfg.ip_local = in_dev->ifa_list->ifa_local;
- cfg.ip_remote = in_dev->ifa_list->ifa_address;
- /* Debugging code used to check that IP addresses
- * obtained from the kernel are correct */
-
- NEX_PRINTK(KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n",
- NIPQUAD(ip_local),NIPQUAD(ip_remote), dev->name);
- break;
-
- case WANOPT_PPP_HOST:
-
- printk(KERN_INFO "%s: PPP IP Mode: HOST\n",card->devname);
- cfg.ip_options = L_IP_LOCAL_ASSIG |
- R_IP_LOCAL_ASSIG |
- ENABLE_IP;
- cfg.ip_local = in_dev->ifa_list->ifa_local;
- cfg.ip_remote = in_dev->ifa_list->ifa_address;
- /* Debugging code used to check that IP addresses
- * obtained from the kernel are correct */
- NEX_PRINTK (KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n",
- NIPQUAD(ip_local),NIPQUAD(ip_remote), dev->name);
-
- break;
-
- case WANOPT_PPP_PEER:
-
- printk(KERN_INFO "%s: PPP IP Mode: PEER\n",card->devname);
- cfg.ip_options = L_IP_REMOTE_ASSIG |
- R_IP_REMOTE_ASSIG |
- ENABLE_IP;
- cfg.ip_local = 0x00;
- cfg.ip_remote = 0x00;
- break;
-
- default:
- printk(KERN_INFO "%s: ERROR: Unsupported PPP Mode Selected\n",
- card->devname);
- printk(KERN_INFO "%s: PPP IP Modes: STATIC, PEER or HOST\n",
- card->devname);
- return 1;
- }
-
- return ppp_configure(card, &cfg);
-}
-
-/*============================================================================
- * Show disconnection cause.
- */
-static void show_disc_cause(sdla_t *card, unsigned cause)
-{
- if (cause & 0x0802)
-
- printk(KERN_INFO "%s: link terminated by peer\n",
- card->devname);
-
- else if (cause & 0x0004)
-
- printk(KERN_INFO "%s: link terminated by user\n",
- card->devname);
-
- else if (cause & 0x0008)
-
- printk(KERN_INFO "%s: authentication failed\n", card->devname);
-
- else if (cause & 0x0010)
-
- printk(KERN_INFO
- "%s: authentication protocol negotiation failed\n",
- card->devname);
-
- else if (cause & 0x0020)
-
- printk(KERN_INFO
- "%s: peer's request for authentication rejected\n",
- card->devname);
-
- else if (cause & 0x0040)
-
- printk(KERN_INFO "%s: MRU option rejected by peer\n",
- card->devname);
-
- else if (cause & 0x0080)
-
- printk(KERN_INFO "%s: peer's MRU was too small\n",
- card->devname);
-
- else if (cause & 0x0100)
-
- printk(KERN_INFO "%s: failed to negotiate peer's LCP options\n",
- card->devname);
-
- else if (cause & 0x0200)
-
- printk(KERN_INFO "%s: failed to negotiate peer's IPCP options\n"
- , card->devname);
-
- else if (cause & 0x0400)
-
- printk(KERN_INFO
- "%s: failed to negotiate peer's IPXCP options\n",
- card->devname);
-}
-
-/*=============================================================================
- * Process UDP call of type PTPIPEAB.
- */
-static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev,
- ppp_private_area_t *ppp_priv_area )
-{
- unsigned char buf2[5];
- unsigned char *buf;
- unsigned int frames, len;
- struct sk_buff *new_skb;
- unsigned short data_length, buffer_length, real_len;
- unsigned long data_ptr;
- int udp_mgmt_req_valid = 1;
- ppp_mbox_t *mbox = card->mbox;
- struct timeval tv;
- int err;
- ppp_udp_pkt_t *ppp_udp_pkt = (ppp_udp_pkt_t*)&ppp_priv_area->udp_pkt_data;
-
- memcpy(&buf2, &card->wandev.udp_port, 2 );
-
-
- if(ppp_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
- switch(ppp_udp_pkt->cblock.command) {
-
- case PPIPE_GET_IBA_DATA:
- case PPP_READ_CONFIG:
- case PPP_GET_CONNECTION_INFO:
- case PPIPE_ROUTER_UP_TIME:
- case PPP_READ_STATISTICS:
- case PPP_READ_ERROR_STATS:
- case PPP_READ_PACKET_STATS:
- case PPP_READ_LCP_STATS:
- case PPP_READ_IPCP_STATS:
- case PPP_READ_IPXCP_STATS:
- case PPP_READ_PAP_STATS:
- case PPP_READ_CHAP_STATS:
- case PPP_READ_CODE_VERSION:
- udp_mgmt_req_valid = 1;
- break;
-
- default:
- udp_mgmt_req_valid = 0;
- break;
- }
- }
-
- if(!udp_mgmt_req_valid) {
-
- /* set length to 0 */
- ppp_udp_pkt->cblock.length = 0x00;
-
- /* set return code */
- ppp_udp_pkt->cblock.result = 0xCD;
- ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_direction_err;
-
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Warning, Illegal UDP command attempted from network: %x\n",
- card->devname,ppp_udp_pkt->cblock.command);
- }
- } else {
- /* Initialize the trace element */
- trace_element_t trace_element;
-
- switch (ppp_udp_pkt->cblock.command){
-
- /* PPIPE_ENABLE_TRACING */
- case PPIPE_ENABLE_TRACING:
- if (!card->TracingEnabled) {
-
- /* OPERATE_DATALINE_MONITOR */
- mbox->cmd.command = PPP_DATALINE_MONITOR;
- mbox->cmd.length = 0x01;
- mbox->data[0] = ppp_udp_pkt->data[0];
- err = sdla_exec(mbox) ?
- mbox->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK) {
-
- ppp_error(card, err, mbox);
- card->TracingEnabled = 0;
-
- /* set the return code */
-
- ppp_udp_pkt->cblock.result = mbox->cmd.result;
- mbox->cmd.length = 0;
- break;
- }
-
- sdla_peek(&card->hw, 0xC000, &buf2, 2);
-
- ppp_priv_area->curr_trace_addr = 0;
- memcpy(&ppp_priv_area->curr_trace_addr, &buf2, 2);
- ppp_priv_area->start_trace_addr =
- ppp_priv_area->curr_trace_addr;
- ppp_priv_area->end_trace_addr =
- ppp_priv_area->start_trace_addr + END_OFFSET;
-
- /* MAX_SEND_BUFFER_SIZE - 28 (IP header)
- - 32 (ppipemon CBLOCK) */
- available_buffer_space = MAX_LGTH_UDP_MGNT_PKT -
- sizeof(ip_pkt_t)-
- sizeof(udp_pkt_t)-
- sizeof(wp_mgmt_t)-
- sizeof(cblock_t);
- }
- ppp_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 0;
- card->TracingEnabled = 1;
- break;
-
- /* PPIPE_DISABLE_TRACING */
- case PPIPE_DISABLE_TRACING:
-
- if(card->TracingEnabled) {
-
- /* OPERATE_DATALINE_MONITOR */
- mbox->cmd.command = 0x33;
- mbox->cmd.length = 1;
- mbox->data[0] = 0x00;
- err = sdla_exec(mbox) ?
- mbox->cmd.result : CMD_TIMEOUT;
-
- }
-
- /*set return code*/
- ppp_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 0;
- card->TracingEnabled = 0;
- break;
-
- /* PPIPE_GET_TRACE_INFO */
- case PPIPE_GET_TRACE_INFO:
-
- if(!card->TracingEnabled) {
- /* set return code */
- ppp_udp_pkt->cblock.result = 1;
- mbox->cmd.length = 0;
- }
-
- buffer_length = 0;
-
- /* frames < 62, where 62 is the number of trace
- information elements. There is in total 496
- bytes of space and each trace information
- element is 8 bytes.
- */
- for ( frames=0; frames<62; frames++) {
-
- trace_pkt_t *trace_pkt = (trace_pkt_t *)
- &ppp_udp_pkt->data[buffer_length];
-
- /* Read the whole trace packet */
- sdla_peek(&card->hw, ppp_priv_area->curr_trace_addr,
- &trace_element, sizeof(trace_element_t));
-
- /* no data on board so exit */
- if( trace_element.opp_flag == 0x00 )
- break;
-
- data_ptr = trace_element.trace_data_ptr;
-
- /* See if there is actual data on the trace buffer */
- if (data_ptr){
- data_length = trace_element.trace_length;
- }else{
- data_length = 0;
- ppp_udp_pkt->data[0] |= 0x02;
- }
-
- //FIXME: Do we need this check
- if ((available_buffer_space - buffer_length)
- < (sizeof(trace_element_t)+1)){
-
- /*indicate we have more frames
- * on board and exit
- */
- ppp_udp_pkt->data[0] |= 0x02;
- break;
- }
-
- trace_pkt->status = trace_element.trace_type;
- trace_pkt->time_stamp = trace_element.trace_time_stamp;
- trace_pkt->real_length = trace_element.trace_length;
-
- real_len = trace_element.trace_length;
-
- if(data_ptr == 0){
- trace_pkt->data_avail = 0x00;
- }else{
- /* we can take it next time */
- if ((available_buffer_space - buffer_length)<
- (real_len + sizeof(trace_pkt_t))){
-
- ppp_udp_pkt->data[0] |= 0x02;
- break;
- }
- trace_pkt->data_avail = 0x01;
-
- /* get the data */
- sdla_peek(&card->hw, data_ptr,
- &trace_pkt->data,
- real_len);
- }
- /* zero the opp flag to
- show we got the frame */
- buf2[0] = 0x00;
- sdla_poke(&card->hw, ppp_priv_area->curr_trace_addr,
- &buf2, 1);
-
- /* now move onto the next
- frame */
- ppp_priv_area->curr_trace_addr += 8;
-
- /* check if we passed the last address */
- if ( ppp_priv_area->curr_trace_addr >=
- ppp_priv_area->end_trace_addr){
-
- ppp_priv_area->curr_trace_addr =
- ppp_priv_area->start_trace_addr;
- }
-
- /* update buffer length and make sure its even */
-
- if ( trace_pkt->data_avail == 0x01 ) {
- buffer_length += real_len - 1;
- }
-
- /* for the header */
- buffer_length += 8;
-
- if( buffer_length & 0x0001 )
- buffer_length += 1;
- }
-
- /* ok now set the total number of frames passed
- in the high 5 bits */
- ppp_udp_pkt->data[0] |= (frames << 2);
-
- /* set the data length */
- mbox->cmd.length = buffer_length;
- ppp_udp_pkt->cblock.length = buffer_length;
-
- /* set return code */
- ppp_udp_pkt->cblock.result = 0;
- break;
-
- /* PPIPE_GET_IBA_DATA */
- case PPIPE_GET_IBA_DATA:
-
- mbox->cmd.length = 0x09;
-
- sdla_peek(&card->hw, 0xF003, &ppp_udp_pkt->data,
- mbox->cmd.length);
-
- /* set the length of the data */
- ppp_udp_pkt->cblock.length = 0x09;
-
- /* set return code */
- ppp_udp_pkt->cblock.result = 0x00;
- ppp_udp_pkt->cblock.result = 0;
- break;
-
- /* PPIPE_FT1_READ_STATUS */
- case PPIPE_FT1_READ_STATUS:
- sdla_peek(&card->hw, 0xF020, &ppp_udp_pkt->data[0], 2);
- ppp_udp_pkt->cblock.length = mbox->cmd.length = 2;
- ppp_udp_pkt->cblock.result = 0;
- break;
-
- case PPIPE_FLUSH_DRIVER_STATS:
- init_ppp_priv_struct( ppp_priv_area );
- init_global_statistics( card );
- mbox->cmd.length = 0;
- ppp_udp_pkt->cblock.result = 0;
- break;
-
-
- case PPIPE_ROUTER_UP_TIME:
-
- do_gettimeofday( &tv );
- ppp_priv_area->router_up_time = tv.tv_sec -
- ppp_priv_area->router_start_time;
- *(unsigned long *)&ppp_udp_pkt->data = ppp_priv_area->router_up_time;
- mbox->cmd.length = 4;
- ppp_udp_pkt->cblock.result = 0;
- break;
-
- /* PPIPE_DRIVER_STATISTICS */
- case PPIPE_DRIVER_STAT_IFSEND:
- memcpy(&ppp_udp_pkt->data, &ppp_priv_area->if_send_stat,
- sizeof(if_send_stat_t));
-
-
- ppp_udp_pkt->cblock.result = 0;
- ppp_udp_pkt->cblock.length = sizeof(if_send_stat_t);
- mbox->cmd.length = sizeof(if_send_stat_t);
- break;
-
- case PPIPE_DRIVER_STAT_INTR:
- memcpy(&ppp_udp_pkt->data, &card->statistics,
- sizeof(global_stats_t));
-
- memcpy(&ppp_udp_pkt->data+sizeof(global_stats_t),
- &ppp_priv_area->rx_intr_stat,
- sizeof(rx_intr_stat_t));
-
- ppp_udp_pkt->cblock.result = 0;
- ppp_udp_pkt->cblock.length = sizeof(global_stats_t)+
- sizeof(rx_intr_stat_t);
- mbox->cmd.length = ppp_udp_pkt->cblock.length;
- break;
-
- case PPIPE_DRIVER_STAT_GEN:
- memcpy( &ppp_udp_pkt->data,
- &ppp_priv_area->pipe_mgmt_stat,
- sizeof(pipe_mgmt_stat_t));
-
- memcpy(&ppp_udp_pkt->data+sizeof(pipe_mgmt_stat_t),
- &card->statistics, sizeof(global_stats_t));
-
- ppp_udp_pkt->cblock.result = 0;
- ppp_udp_pkt->cblock.length = sizeof(global_stats_t)+
- sizeof(rx_intr_stat_t);
- mbox->cmd.length = ppp_udp_pkt->cblock.length;
- break;
-
-
- /* FT1 MONITOR STATUS */
- case FT1_MONITOR_STATUS_CTRL:
-
- /* Enable FT1 MONITOR STATUS */
- if( ppp_udp_pkt->data[0] == 1) {
-
- if( rCount++ != 0 ) {
- ppp_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 1;
- break;
- }
- }
-
- /* Disable FT1 MONITOR STATUS */
- if( ppp_udp_pkt->data[0] == 0) {
-
- if( --rCount != 0) {
- ppp_udp_pkt->cblock.result = 0;
- mbox->cmd.length = 1;
- break;
- }
- }
- goto udp_dflt_cmd;
-
- /* WARNING: FIXME: This should be fixed.
- * The FT1 Status Ctrl doesn't have a break
- * statment. Thus, no code must be inserted
- * HERE: between default and above case statement */
-
- default:
-udp_dflt_cmd:
-
- /* it's a board command */
- mbox->cmd.command = ppp_udp_pkt->cblock.command;
- mbox->cmd.length = ppp_udp_pkt->cblock.length;
-
- if(mbox->cmd.length) {
- memcpy(&mbox->data,(unsigned char *)ppp_udp_pkt->data,
- mbox->cmd.length);
- }
-
- /* run the command on the board */
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK) {
-
- ppp_error(card, err, mbox);
- ++ppp_priv_area->pipe_mgmt_stat.
- UDP_PIPE_mgmt_adptr_cmnd_timeout;
- break;
- }
-
- ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_OK;
-
- /* copy the result back to our buffer */
- memcpy(&ppp_udp_pkt->cblock,mbox, sizeof(cblock_t));
-
- if(mbox->cmd.length) {
- memcpy(&ppp_udp_pkt->data,&mbox->data,mbox->cmd.length);
- }
-
- } /* end of switch */
- } /* end of else */
-
- /* Fill UDP TTL */
- ppp_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
- len = reply_udp(ppp_priv_area->udp_pkt_data, mbox->cmd.length);
-
- if (ppp_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
- /* Make sure we are not already sending */
- if (!test_bit(SEND_CRIT,&card->wandev.critical)){
- ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_adptr;
- ppp_send(card,ppp_priv_area->udp_pkt_data,len,ppp_priv_area->protocol);
- }
-
- } else {
-
- /* Pass it up the stack
- Allocate socket buffer */
- if ((new_skb = dev_alloc_skb(len)) != NULL) {
-
- /* copy data into new_skb */
-
- buf = skb_put(new_skb, len);
- memcpy(buf,ppp_priv_area->udp_pkt_data, len);
-
- ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_stack;
-
- /* Decapsulate packet and pass it up the protocol
- stack */
- new_skb->protocol = htons(ETH_P_IP);
- new_skb->dev = dev;
- new_skb->mac.raw = new_skb->data;
- netif_rx(new_skb);
- dev->last_rx = jiffies;
-
- } else {
-
- ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_no_socket;
- printk(KERN_INFO "no socket buffers available!\n");
- }
- }
-
- ppp_priv_area->udp_pkt_lgth = 0;
-
- return;
-}
-
-/*=============================================================================
- * Initial the ppp_private_area structure.
- */
-static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area )
-{
-
- memset(&ppp_priv_area->if_send_stat, 0, sizeof(if_send_stat_t));
- memset(&ppp_priv_area->rx_intr_stat, 0, sizeof(rx_intr_stat_t));
- memset(&ppp_priv_area->pipe_mgmt_stat, 0, sizeof(pipe_mgmt_stat_t));
-}
-
-/*============================================================================
- * Initialize Global Statistics
- */
-static void init_global_statistics( sdla_t *card )
-{
- memset(&card->statistics, 0, sizeof(global_stats_t));
-}
-
-/*============================================================================
- * Initialize Receive and Transmit Buffers.
- */
-static void init_ppp_tx_rx_buff( sdla_t *card )
-{
- ppp508_buf_info_t* info;
-
- if (card->hw.type == SDLA_S514) {
-
- info = (void*)(card->hw.dpmbase + PPP514_BUF_OFFS);
-
- card->u.p.txbuf_base = (void*)(card->hw.dpmbase +
- info->txb_ptr);
-
- card->u.p.txbuf_last = (ppp_buf_ctl_t*)card->u.p.txbuf_base +
- (info->txb_num - 1);
-
- card->u.p.rxbuf_base = (void*)(card->hw.dpmbase +
- info->rxb_ptr);
-
- card->u.p.rxbuf_last = (ppp_buf_ctl_t*)card->u.p.rxbuf_base +
- (info->rxb_num - 1);
-
- } else {
-
- info = (void*)(card->hw.dpmbase + PPP508_BUF_OFFS);
-
- card->u.p.txbuf_base = (void*)(card->hw.dpmbase +
- (info->txb_ptr - PPP508_MB_VECT));
-
- card->u.p.txbuf_last = (ppp_buf_ctl_t*)card->u.p.txbuf_base +
- (info->txb_num - 1);
-
- card->u.p.rxbuf_base = (void*)(card->hw.dpmbase +
- (info->rxb_ptr - PPP508_MB_VECT));
-
- card->u.p.rxbuf_last = (ppp_buf_ctl_t*)card->u.p.rxbuf_base +
- (info->rxb_num - 1);
- }
-
- card->u.p.txbuf_next = (unsigned long*)&info->txb_nxt;
- card->u.p.rxbuf_next = (unsigned long*)&info->rxb1_ptr;
-
- card->u.p.rx_base = info->rxb_base;
- card->u.p.rx_top = info->rxb_end;
-
- card->u.p.txbuf = card->u.p.txbuf_base;
- card->rxmb = card->u.p.rxbuf_base;
-
-}
-
-/*=============================================================================
- * Read Connection Information (ie for Remote IP address assginment).
- * Called when ppp interface connected.
- */
-static int read_info( sdla_t *card )
-{
- struct net_device *dev = card->wandev.dev;
- ppp_private_area_t *ppp_priv_area = dev->priv;
- int err;
-
- struct ifreq if_info;
- struct sockaddr_in *if_data1, *if_data2;
- mm_segment_t fs;
-
- /* Set Local and remote addresses */
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
-
-
- fs = get_fs();
- set_fs(get_ds()); /* get user space block */
-
- /* Change the local and remote ip address of the interface.
- * This will also add in the destination route.
- */
- if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
- if_data1->sin_addr.s_addr = ppp_priv_area->ip_local;
- if_data1->sin_family = AF_INET;
- err = devinet_ioctl( SIOCSIFADDR, &if_info );
- if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data2->sin_addr.s_addr = ppp_priv_area->ip_remote;
- if_data2->sin_family = AF_INET;
- err = devinet_ioctl( SIOCSIFDSTADDR, &if_info );
-
- set_fs(fs); /* restore old block */
-
- if (err) {
- printk (KERN_INFO "%s: Adding of route failed: %i\n",
- card->devname,err);
- printk (KERN_INFO "%s: Local : %u.%u.%u.%u\n",
- card->devname,NIPQUAD(ppp_priv_area->ip_local));
- printk (KERN_INFO "%s: Remote: %u.%u.%u.%u\n",
- card->devname,NIPQUAD(ppp_priv_area->ip_remote));
- }
- return err;
-}
-
-/*=============================================================================
- * Remove Dynamic Route.
- * Called when ppp interface disconnected.
- */
-
-static void remove_route( sdla_t *card )
-{
-
- struct net_device *dev = card->wandev.dev;
- long ip_addr;
- int err;
-
- mm_segment_t fs;
- struct ifreq if_info;
- struct sockaddr_in *if_data1;
- struct in_device *in_dev = dev->ip_ptr;
- struct in_ifaddr *ifa = in_dev->ifa_list;
-
- ip_addr = ifa->ifa_local;
-
- /* Set Local and remote addresses */
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
-
- fs = get_fs();
- set_fs(get_ds()); /* get user space block */
-
- /* Change the local ip address of the interface to 0.
- * This will also delete the destination route.
- */
- if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
- if_data1->sin_addr.s_addr = 0;
- if_data1->sin_family = AF_INET;
- err = devinet_ioctl( SIOCSIFADDR, &if_info );
-
- set_fs(fs); /* restore old block */
-
-
- if (err) {
- printk (KERN_INFO "%s: Deleting dynamic route failed %d!\n",
- card->devname, err);
- return;
- }else{
- printk (KERN_INFO "%s: PPP Deleting dynamic route %u.%u.%u.%u successfuly\n",
- card->devname, NIPQUAD(ip_addr));
- }
- return;
-}
-
-/*=============================================================================
- * Perform the Interrupt Test by running the READ_CODE_VERSION command MAX_INTR
- * _TEST_COUNTER times.
- */
-static int intr_test( sdla_t *card )
-{
- ppp_mbox_t *mb = card->mbox;
- int err,i;
-
- err = ppp_set_intr_mode( card, 0x08 );
-
- if (err == CMD_OK) {
-
- for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) {
- /* Run command READ_CODE_VERSION */
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.length = 0;
- mb->cmd.command = PPP_READ_CODE_VERSION;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
- if (err != CMD_OK)
- ppp_error(card, err, mb);
- }
- }
- else return err;
-
- err = ppp_set_intr_mode( card, 0 );
- if (err != CMD_OK)
- return err;
-
- return 0;
-}
-
-/*==============================================================================
- * Determine what type of UDP call it is. DRVSTATS or PTPIPEAB ?
- */
-static int udp_pkt_type( struct sk_buff *skb, sdla_t *card )
-{
- unsigned char *sendpacket;
- unsigned char buf2[5];
- ppp_udp_pkt_t *ppp_udp_pkt = (ppp_udp_pkt_t *)skb->data;
-
- sendpacket = skb->data;
- memcpy(&buf2, &card->wandev.udp_port, 2);
-
- if( ppp_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45 && /* IP packet */
- sendpacket[9] == 0x11 && /* UDP packet */
- sendpacket[22] == buf2[1] && /* UDP Port */
- sendpacket[23] == buf2[0] &&
- sendpacket[36] == 0x01 ) {
-
- if ( sendpacket[28] == 0x50 && /* PTPIPEAB: Signature */
- sendpacket[29] == 0x54 &&
- sendpacket[30] == 0x50 &&
- sendpacket[31] == 0x49 &&
- sendpacket[32] == 0x50 &&
- sendpacket[33] == 0x45 &&
- sendpacket[34] == 0x41 &&
- sendpacket[35] == 0x42 ){
-
- return UDP_PTPIPE_TYPE;
-
- } else if(sendpacket[28] == 0x44 && /* DRVSTATS: Signature */
- sendpacket[29] == 0x52 &&
- sendpacket[30] == 0x56 &&
- sendpacket[31] == 0x53 &&
- sendpacket[32] == 0x54 &&
- sendpacket[33] == 0x41 &&
- sendpacket[34] == 0x54 &&
- sendpacket[35] == 0x53 ){
-
- return UDP_DRVSTATS_TYPE;
-
- } else
- return UDP_INVALID_TYPE;
-
- } else
- return UDP_INVALID_TYPE;
-
-}
-
-/*============================================================================
- * Check to see if the packet to be transmitted contains a broadcast or
- * multicast source IP address.
- */
-
-static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev,
- struct sk_buff *skb)
-{
- u32 src_ip_addr;
- u32 broadcast_ip_addr = 0;
- struct in_device *in_dev;
-
- /* read the IP source address from the outgoing packet */
- src_ip_addr = *(u32 *)(skb->data + 12);
-
- /* read the IP broadcast address for the device */
- in_dev = dev->ip_ptr;
- if(in_dev != NULL) {
- struct in_ifaddr *ifa= in_dev->ifa_list;
- if(ifa != NULL)
- broadcast_ip_addr = ifa->ifa_broadcast;
- else
- return 0;
- }
-
- /* check if the IP Source Address is a Broadcast address */
- if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
- printk(KERN_INFO "%s: Broadcast Source Address silently discarded\n",
- card->devname);
- return 1;
- }
-
- /* check if the IP Source Address is a Multicast address */
- if((ntohl(src_ip_addr) >= 0xE0000001) &&
- (ntohl(src_ip_addr) <= 0xFFFFFFFE)) {
- printk(KERN_INFO "%s: Multicast Source Address silently discarded\n",
- card->devname);
- return 1;
- }
-
- return 0;
-}
-
-void s508_lock (sdla_t *card, unsigned long *smp_flags)
-{
- spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-}
-
-void s508_unlock (sdla_t *card, unsigned long *smp_flags)
-{
- spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-}
-
-static int read_connection_info (sdla_t *card)
-{
- ppp_mbox_t *mb = card->mbox;
- struct net_device *dev = card->wandev.dev;
- ppp_private_area_t *ppp_priv_area = dev->priv;
- ppp508_connect_info_t *ppp508_connect_info;
- int err;
-
- memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
- mb->cmd.length = 0;
- mb->cmd.command = PPP_GET_CONNECTION_INFO;
- err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK) {
- ppp_error(card, err, mb);
- ppp_priv_area->ip_remote = 0;
- ppp_priv_area->ip_local = 0;
- }
- else {
- ppp508_connect_info = (ppp508_connect_info_t *)mb->data;
- ppp_priv_area->ip_remote = ppp508_connect_info->ip_remote;
- ppp_priv_area->ip_local = ppp508_connect_info->ip_local;
-
- NEX_PRINTK(KERN_INFO "READ CONNECTION GOT IP ADDRESS %x, %x\n",
- ppp_priv_area->ip_remote,
- ppp_priv_area->ip_local);
- }
-
- return err;
-}
-
-/*===============================================================================
- * config_ppp
- *
- * Configure the ppp protocol and enable communications.
- *
- * The if_open function binds this function to the poll routine.
- * Therefore, this function will run every time the ppp interface
- * is brought up.
- *
- * If the communications are not enabled, proceed to configure
- * the card and enable communications.
- *
- * If the communications are enabled, it means that the interface
- * was shutdown by ether the user or driver. In this case, we
- * have to check that the IP addresses have not changed. If
- * the IP addresses changed, we have to reconfigure the firmware
- * and update the changed IP addresses. Otherwise, just exit.
- */
-static int config_ppp (sdla_t *card)
-{
-
- struct net_device *dev = card->wandev.dev;
- ppp_flags_t *flags = card->flags;
- ppp_private_area_t *ppp_priv_area = dev->priv;
-
- if (card->u.p.comm_enabled){
-
- if (ppp_priv_area->ip_local_tmp != ppp_priv_area->ip_local ||
- ppp_priv_area->ip_remote_tmp != ppp_priv_area->ip_remote){
-
- /* The IP addersses have changed, we must
- * stop the communications and reconfigure
- * the card. Reason: the firmware must know
- * the local and remote IP addresses. */
- disable_comm(card);
- wanpipe_set_state(card, WAN_DISCONNECTED);
- printk(KERN_INFO
- "%s: IP addresses changed!\n",
- card->devname);
- printk(KERN_INFO "%s: Restarting communications ...\n",
- card->devname);
- }else{
- /* IP addresses are the same and the link is up,
- * we don't have to do anything here. Therefore, exit */
- return 0;
- }
- }
-
- /* Record the new IP addreses */
- ppp_priv_area->ip_local = ppp_priv_area->ip_local_tmp;
- ppp_priv_area->ip_remote = ppp_priv_area->ip_remote_tmp;
-
- if (config508(dev, card)){
- printk(KERN_INFO "%s: Failed to configure PPP device\n",
- card->devname);
- return 0;
- }
-
- if (ppp_set_intr_mode(card, PPP_INTR_RXRDY|
- PPP_INTR_TXRDY|
- PPP_INTR_MODEM|
- PPP_INTR_DISC |
- PPP_INTR_OPEN |
- PPP_INTR_DROP_DTR |
- PPP_INTR_TIMER)) {
-
- printk(KERN_INFO "%s: Failed to configure board interrupts !\n",
- card->devname);
- return 0;
- }
-
- /* Turn off the transmit and timer interrupt */
- flags->imask &= ~(PPP_INTR_TXRDY | PPP_INTR_TIMER) ;
-
-
- /* If you are not the authenticator and any one of the protocol is
- * enabled then we call the set_out_bound_authentication.
- */
- if ( !card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)) {
- if ( ppp_set_outbnd_auth(card, ppp_priv_area) ){
- printk(KERN_INFO "%s: Outbound authentication failed !\n",
- card->devname);
- return 0;
- }
- }
-
- /* If you are the authenticator and any one of the protocol is enabled
- * then we call the set_in_bound_authentication.
- */
- if (card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)){
- if (ppp_set_inbnd_auth(card, ppp_priv_area)){
- printk(KERN_INFO "%s: Inbound authentication failed !\n",
- card->devname);
- return 0;
- }
- }
-
- /* If we fail to enable communications here it's OK,
- * since the DTR timer will cause a disconnected, which
- * will retrigger communication in timer_intr() */
- if (ppp_comm_enable(card) == CMD_OK) {
- wanpipe_set_state(card, WAN_CONNECTING);
- init_ppp_tx_rx_buff(card);
- }
-
- return 0;
-}
-
-/*============================================================
- * ppp_poll
- *
- * Rationale:
- * We cannot manipulate the routing tables, or
- * ip addresses withing the interrupt. Therefore
- * we must perform such actons outside an interrupt
- * at a later time.
- *
- * Description:
- * PPP polling routine, responsible for
- * shutting down interfaces upon disconnect
- * and adding/removing routes.
- *
- * Usage:
- * This function is executed for each ppp
- * interface through a tq_schedule bottom half.
- *
- * trigger_ppp_poll() function is used to kick
- * the ppp_poll routine.
- */
-static void ppp_poll(struct net_device *dev)
-{
- ppp_private_area_t *ppp_priv_area;
- sdla_t *card;
- u8 check_gateway=0;
- ppp_flags_t *flags;
-
- if (!dev || (ppp_priv_area = dev->priv) == NULL)
- return;
-
- card = ppp_priv_area->card;
- flags = card->flags;
-
- /* Shutdown is in progress, stop what you are
- * doing and get out */
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- clear_bit(POLL_CRIT,&card->wandev.critical);
- return;
- }
-
- /* if_open() function has triggered the polling routine
- * to determine the configured IP addresses. Once the
- * addresses are found, trigger the chdlc configuration */
- if (test_bit(0,&ppp_priv_area->config_ppp)){
-
- ppp_priv_area->ip_local_tmp = get_ip_address(dev,WAN_LOCAL_IP);
- ppp_priv_area->ip_remote_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP);
-
- if (ppp_priv_area->ip_local_tmp == ppp_priv_area->ip_remote_tmp &&
- card->u.p.ip_mode == WANOPT_PPP_HOST){
-
- if (++ppp_priv_area->ip_error > MAX_IP_ERRORS){
- printk(KERN_INFO "\n%s: --- WARNING ---\n",
- card->devname);
- printk(KERN_INFO "%s: The local IP address is the same as the\n",
- card->devname);
- printk(KERN_INFO "%s: Point-to-Point IP address.\n",
- card->devname);
- printk(KERN_INFO "%s: --- WARNING ---\n\n",
- card->devname);
- }else{
- clear_bit(POLL_CRIT,&card->wandev.critical);
- ppp_priv_area->poll_delay_timer.expires = jiffies+HZ;
- add_timer(&ppp_priv_area->poll_delay_timer);
- return;
- }
- }
-
- ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
- flags->imask |= PPP_INTR_TIMER;
- ppp_priv_area->ip_error=0;
-
- clear_bit(0,&ppp_priv_area->config_ppp);
- clear_bit(POLL_CRIT,&card->wandev.critical);
- return;
- }
-
- /* Dynamic interface implementation, as well as dynamic
- * routing. */
-
- switch (card->wandev.state) {
-
- case WAN_DISCONNECTED:
-
- /* If the dynamic interface configuration is on, and interface
- * is up, then bring down the netowrk interface */
-
- if (test_bit(DYN_OPT_ON,&ppp_priv_area->interface_down) &&
- !test_bit(DEV_DOWN,&ppp_priv_area->interface_down) &&
- card->wandev.dev->flags & IFF_UP){
-
- printk(KERN_INFO "%s: Interface %s down.\n",
- card->devname,card->wandev.dev->name);
- change_dev_flags(card->wandev.dev,
- (card->wandev.dev->flags&~IFF_UP));
- set_bit(DEV_DOWN,&ppp_priv_area->interface_down);
- }else{
- /* We need to check if the local IP address is
- * zero. If it is, we shouldn't try to remove it.
- * For some reason the kernel crashes badly if
- * we try to remove the route twice */
-
- if (card->wandev.dev->flags & IFF_UP &&
- get_ip_address(card->wandev.dev,WAN_LOCAL_IP) &&
- card->u.p.ip_mode == WANOPT_PPP_PEER){
-
- remove_route(card);
- }
- }
- break;
-
- case WAN_CONNECTED:
-
- /* In SMP machine this code can execute before the interface
- * comes up. In this case, we must make sure that we do not
- * try to bring up the interface before dev_open() is finished */
-
-
- /* DEV_DOWN will be set only when we bring down the interface
- * for the very first time. This way we know that it was us
- * that brought the interface down */
-
- if (test_bit(DYN_OPT_ON,&ppp_priv_area->interface_down) &&
- test_bit(DEV_DOWN, &ppp_priv_area->interface_down) &&
- !(card->wandev.dev->flags & IFF_UP)){
-
- printk(KERN_INFO "%s: Interface %s up.\n",
- card->devname,card->wandev.dev->name);
-
- change_dev_flags(card->wandev.dev,(card->wandev.dev->flags|IFF_UP));
- clear_bit(DEV_DOWN,&ppp_priv_area->interface_down);
- check_gateway=1;
- }
-
- if ((card->u.p.ip_mode == WANOPT_PPP_PEER) &&
- test_bit(1,&Read_connection_info)) {
-
- process_route(card);
- clear_bit(1,&Read_connection_info);
- check_gateway=1;
- }
-
- if (ppp_priv_area->gateway && check_gateway)
- add_gateway(card,dev);
-
- break;
- }
- clear_bit(POLL_CRIT,&card->wandev.critical);
- return;
-}
-
-/*============================================================
- * trigger_ppp_poll
- *
- * Description:
- * Add a ppp_poll() task into a tq_scheduler bh handler
- * for a specific interface. This will kick
- * the ppp_poll() routine at a later time.
- *
- * Usage:
- * Interrupts use this to defer a taks to
- * a polling routine.
- *
- */
-
-static void trigger_ppp_poll(struct net_device *dev)
-{
- ppp_private_area_t *ppp_priv_area;
- if ((ppp_priv_area=dev->priv) != NULL){
-
- sdla_t *card = ppp_priv_area->card;
-
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- return;
- }
-
- if (test_and_set_bit(POLL_CRIT,&card->wandev.critical)){
- return;
- }
-
- schedule_work(&ppp_priv_area->poll_work);
- }
- return;
-}
-
-static void ppp_poll_delay (unsigned long dev_ptr)
-{
- struct net_device *dev = (struct net_device *)dev_ptr;
- trigger_ppp_poll(dev);
-}
-
-/*============================================================
- * detect_and_fix_tx_bug
- *
- * Description:
- * On connect, if the board tx buffer ptr is not the same
- * as the driver tx buffer ptr, we found a firmware bug.
- * Report the bug to the above layer. To fix the
- * error restart communications again.
- *
- * Usage:
- *
- */
-
-static int detect_and_fix_tx_bug (sdla_t *card)
-{
- if (((unsigned long)card->u.p.txbuf_base&0xFFF) != ((*card->u.p.txbuf_next)&0xFFF)){
- NEX_PRINTK(KERN_INFO "Major Error, Fix the bug\n");
- return 1;
- }
- return 0;
-}
-
-MODULE_LICENSE("GPL");
-
-/****** End *****************************************************************/
diff --git a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c
deleted file mode 100644
index 63f846d6f3a..00000000000
--- a/drivers/net/wan/sdla_x25.c
+++ /dev/null
@@ -1,5497 +0,0 @@
-/*****************************************************************************
-* sdla_x25.c WANPIPE(tm) Multiprotocol WAN Link Driver. X.25 module.
-*
-* Author: Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright: (c) 1995-2001 Sangoma Technologies 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.
-* ============================================================================
-* Apr 03, 2001 Nenad Corbic o Fixed the rx_skb=NULL bug in x25 in rx_intr().
-* Dec 26, 2000 Nenad Corbic o Added a new polling routine, that uses
-* a kernel timer (more efficient).
-* Dec 25, 2000 Nenad Corbic o Updated for 2.4.X kernel
-* Jul 26, 2000 Nenad Corbic o Increased the local packet buffering
-* for API to 4096+header_size.
-* Jul 17, 2000 Nenad Corbic o Fixed the x25 startup bug. Enable
-* communications only after all interfaces
-* come up. HIGH SVC/PVC is used to calculate
-* the number of channels.
-* Enable protocol only after all interfaces
-* are enabled.
-* Jul 10, 2000 Nenad Corbic o Fixed the M_BIT bug.
-* Apr 25, 2000 Nenad Corbic o Pass Modem messages to the API.
-* Disable idle timeout in X25 API.
-* Apr 14, 2000 Nenad Corbic o Fixed: Large LCN number support.
-* Maximum LCN number is 4095.
-* Maximum number of X25 channels is 255.
-* Apr 06, 2000 Nenad Corbic o Added SMP Support.
-* Mar 29, 2000 Nenad Corbic o Added support for S514 PCI Card
-* Mar 23, 2000 Nenad Corbic o Improved task queue, BH handling.
-* Mar 14, 2000 Nenad Corbic o Updated Protocol Violation handling
-* routines. Bug Fix.
-* Mar 10, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery.
-* Mar 09, 2000 Nenad Corbic o Fixed the auto HDLC bug.
-* Mar 08, 2000 Nenad Corbic o Fixed LAPB HDLC startup problems.
-* Application must bring the link up
-* before tx/rx, and bring the
-* link down on close().
-* Mar 06, 2000 Nenad Corbic o Added an option for logging call setup
-* information.
-* Feb 29, 2000 Nenad Corbic o Added support for LAPB HDLC API
-* Feb 25, 2000 Nenad Corbic o Fixed the modem failure handling.
-* No Modem OOB message will be passed
-* to the user.
-* Feb 21, 2000 Nenad Corbic o Added Xpipemon Debug Support
-* Dec 30, 1999 Nenad Corbic o Socket based X25API
-* Sep 17, 1998 Jaspreet Singh o Updates for 2.2.X kernel
-* Mar 15, 1998 Alan Cox o 2.1.x porting
-* Dec 19, 1997 Jaspreet Singh o Added multi-channel IPX support
-* Nov 27, 1997 Jaspreet Singh o Added protection against enabling of irqs
-* when they are disabled.
-* Nov 17, 1997 Farhan Thawar o Added IPX support
-* o Changed if_send() to now buffer packets when
-* the board is busy
-* o Removed queueing of packets via the polling
-* routing
-* o Changed if_send() critical flags to properly
-* handle race conditions
-* Nov 06, 1997 Farhan Thawar o Added support for SVC timeouts
-* o Changed PVC encapsulation to ETH_P_IP
-* Jul 21, 1997 Jaspreet Singh o Fixed freeing up of buffers using kfree()
-* when packets are received.
-* Mar 11, 1997 Farhan Thawar Version 3.1.1
-* o added support for V35
-* o changed if_send() to return 0 if
-* wandev.critical() is true
-* o free socket buffer in if_send() if
-* returning 0
-* o added support for single '@' address to
-* accept all incoming calls
-* o fixed bug in set_chan_state() to disconnect
-* Jan 15, 1997 Gene Kozin Version 3.1.0
-* o implemented exec() entry point
-* Jan 07, 1997 Gene Kozin Initial version.
-*****************************************************************************/
-
-/*======================================================
- * Includes
- *=====================================================*/
-
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/ctype.h>
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/workqueue.h>
-#include <linux/jiffies.h> /* time_after() macro */
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <asm/atomic.h>
-#include <linux/delay.h> /* Experimental delay */
-
-#include <asm/uaccess.h>
-
-#include <linux/if.h>
-#include <linux/if_arp.h>
-#include <linux/sdla_x25.h> /* X.25 firmware API definitions */
-#include <linux/if_wanpipe_common.h>
-#include <linux/if_wanpipe.h>
-
-
-/*======================================================
- * Defines & Macros
- *=====================================================*/
-
-
-#define CMD_OK 0 /* normal firmware return code */
-#define CMD_TIMEOUT 0xFF /* firmware command timed out */
-#define MAX_CMD_RETRY 10 /* max number of firmware retries */
-
-#define X25_CHAN_MTU 4096 /* unfragmented logical channel MTU */
-#define X25_HRDHDR_SZ 7 /* max encapsulation header size */
-#define X25_CONCT_TMOUT (90*HZ) /* link connection timeout */
-#define X25_RECON_TMOUT (10*HZ) /* link connection timeout */
-#define CONNECT_TIMEOUT (90*HZ) /* link connection timeout */
-#define HOLD_DOWN_TIME (30*HZ) /* link hold down time */
-#define MAX_BH_BUFF 10
-#define M_BIT 0x01
-
-//#define PRINT_DEBUG 1
-#ifdef PRINT_DEBUG
-#define DBG_PRINTK(format, a...) printk(format, ## a)
-#else
-#define DBG_PRINTK(format, a...)
-#endif
-
-#define TMR_INT_ENABLED_POLL_ACTIVE 0x01
-#define TMR_INT_ENABLED_POLL_CONNECT_ON 0x02
-#define TMR_INT_ENABLED_POLL_CONNECT_OFF 0x04
-#define TMR_INT_ENABLED_POLL_DISCONNECT 0x08
-#define TMR_INT_ENABLED_CMD_EXEC 0x10
-#define TMR_INT_ENABLED_UPDATE 0x20
-#define TMR_INT_ENABLED_UDP_PKT 0x40
-
-#define MAX_X25_ADDR_SIZE 16
-#define MAX_X25_DATA_SIZE 129
-#define MAX_X25_FACL_SIZE 110
-
-#define TRY_CMD_AGAIN 2
-#define DELAY_RESULT 1
-#define RETURN_RESULT 0
-
-#define DCD(x) (x & 0x03 ? "HIGH" : "LOW")
-#define CTS(x) (x & 0x05 ? "HIGH" : "LOW")
-
-
-/* Driver will not write log messages about
- * modem status if defined.*/
-#define MODEM_NOT_LOG 1
-
-/*====================================================
- * For IPXWAN
- *===================================================*/
-
-#define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b)))
-
-
-/*====================================================
- * MEMORY DEBUGGING FUNCTION
- *====================================================
-
-#define KMEM_SAFETYZONE 8
-
-static void * dbg_kmalloc(unsigned int size, int prio, int line) {
- int i = 0;
- void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio);
- char * c1 = v;
- c1 += sizeof(unsigned int);
- *((unsigned int *)v) = size;
-
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D';
- c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F';
- c1 += 8;
- }
- c1 += size;
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G';
- c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L';
- c1 += 8;
- }
- v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8;
- printk(KERN_INFO "line %d kmalloc(%d,%d) = %p\n",line,size,prio,v);
- return v;
-}
-static void dbg_kfree(void * v, int line) {
- unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8));
- unsigned int size = *sp;
- char * c1 = ((char *)v) - KMEM_SAFETYZONE*8;
- int i = 0;
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- if ( c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D'
- || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') {
- printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v);
- printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
- c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
- }
- c1 += 8;
- }
- c1 += size;
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- if ( c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G'
- || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L'
- ) {
- printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v);
- printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
- c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
- }
- c1 += 8;
- }
- printk(KERN_INFO "line %d kfree(%p)\n",line,v);
- v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8);
- kfree(v);
-}
-
-#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)
-#define kfree(x) dbg_kfree(x,__LINE__)
-
-==============================================================*/
-
-
-
-/*===============================================
- * Data Structures
- *===============================================*/
-
-
-/*========================================================
- * Name: x25_channel
- *
- * Purpose: To hold private informaton for each
- * logical channel.
- *
- * Rationale: Per-channel debugging is possible if each
- * channel has its own private area.
- *
- * Assumptions:
- *
- * Description: This is an extention of the struct net_device
- * we create for each network interface to keep
- * the rest of X.25 channel-specific data.
- *
- * Construct: Typedef
- */
-typedef struct x25_channel
-{
- wanpipe_common_t common; /* common area for x25api and socket */
- char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
- char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */
- unsigned tx_pkt_size;
- unsigned short protocol; /* ethertype, 0 - multiplexed */
- char drop_sequence; /* mark sequence for dropping */
- unsigned long state_tick; /* time of the last state change */
- unsigned idle_timeout; /* sec, before disconnecting */
- unsigned long i_timeout_sofar; /* # of sec's we've been idle */
- unsigned hold_timeout; /* sec, before re-connecting */
- unsigned long tick_counter; /* counter for transmit time out */
- char devtint; /* Weather we should dev_tint() */
- struct sk_buff* rx_skb; /* receive socket buffer */
- struct sk_buff* tx_skb; /* transmit socket buffer */
-
- bh_data_t *bh_head; /* Circular buffer for x25api_bh */
- unsigned long tq_working;
- volatile int bh_write;
- volatile int bh_read;
- atomic_t bh_buff_used;
-
- sdla_t* card; /* -> owner */
- struct net_device *dev; /* -> bound devce */
-
- int ch_idx;
- unsigned char enable_IPX;
- unsigned long network_number;
- struct net_device_stats ifstats; /* interface statistics */
- unsigned short transmit_length;
- unsigned short tx_offset;
- char transmit_buffer[X25_CHAN_MTU+sizeof(x25api_hdr_t)];
-
- if_send_stat_t if_send_stat;
- rx_intr_stat_t rx_intr_stat;
- pipe_mgmt_stat_t pipe_mgmt_stat;
-
- unsigned long router_start_time; /* Router start time in seconds */
- unsigned long router_up_time;
-
-} x25_channel_t;
-
-/* FIXME Take this out */
-
-#ifdef NEX_OLD_CALL_INFO
-typedef struct x25_call_info
-{
- char dest[17]; PACKED;/* ASCIIZ destination address */
- char src[17]; PACKED;/* ASCIIZ source address */
- char nuser; PACKED;/* number of user data bytes */
- unsigned char user[127]; PACKED;/* user data */
- char nfacil; PACKED;/* number of facilities */
- struct
- {
- unsigned char code; PACKED;
- unsigned char parm; PACKED;
- } facil[64]; /* facilities */
-} x25_call_info_t;
-#else
-typedef struct x25_call_info
-{
- char dest[MAX_X25_ADDR_SIZE] PACKED;/* ASCIIZ destination address */
- char src[MAX_X25_ADDR_SIZE] PACKED;/* ASCIIZ source address */
- unsigned char nuser PACKED;
- unsigned char user[MAX_X25_DATA_SIZE] PACKED;/* user data */
- unsigned char nfacil PACKED;
- unsigned char facil[MAX_X25_FACL_SIZE] PACKED;
- unsigned short lcn PACKED;
-} x25_call_info_t;
-#endif
-
-
-
-/*===============================================
- * Private Function Prototypes
- *==============================================*/
-
-
-/*=================================================
- * WAN link driver entry points. These are
- * called by the WAN router module.
- */
-static int update(struct wan_device* wandev);
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf);
-static int del_if(struct wan_device* wandev, struct net_device* dev);
-static void disable_comm (sdla_t* card);
-static void disable_comm_shutdown(sdla_t *card);
-
-
-
-/*=================================================
- * WANPIPE-specific entry points
- */
-static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data);
-static void x25api_bh(struct net_device *dev);
-static int x25api_bh_cleanup(struct net_device *dev);
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb);
-
-
-/*=================================================
- * Network device interface
- */
-static int if_init(struct net_device* dev);
-static int if_open(struct net_device* dev);
-static int if_close(struct net_device* dev);
-static int if_header(struct sk_buff* skb, struct net_device* dev,
- unsigned short type, void* daddr, void* saddr, unsigned len);
-static int if_rebuild_hdr (struct sk_buff* skb);
-static int if_send(struct sk_buff* skb, struct net_device* dev);
-static struct net_device_stats *if_stats(struct net_device* dev);
-
-static void if_tx_timeout(struct net_device *dev);
-
-/*=================================================
- * Interrupt handlers
- */
-static void wpx_isr (sdla_t *);
-static void rx_intr (sdla_t *);
-static void tx_intr (sdla_t *);
-static void status_intr (sdla_t *);
-static void event_intr (sdla_t *);
-static void spur_intr (sdla_t *);
-static void timer_intr (sdla_t *);
-
-static int tx_intr_send(sdla_t *card, struct net_device *dev);
-static struct net_device *move_dev_to_next(sdla_t *card,
- struct net_device *dev);
-
-/*=================================================
- * Background polling routines
- */
-static void wpx_poll (sdla_t* card);
-static void poll_disconnected (sdla_t* card);
-static void poll_connecting (sdla_t* card);
-static void poll_active (sdla_t* card);
-static void trigger_x25_poll(sdla_t *card);
-static void x25_timer_routine(unsigned long data);
-
-
-
-/*=================================================
- * X.25 firmware interface functions
- */
-static int x25_get_version (sdla_t* card, char* str);
-static int x25_configure (sdla_t* card, TX25Config* conf);
-static int hdlc_configure (sdla_t* card, TX25Config* conf);
-static int set_hdlc_level (sdla_t* card);
-static int x25_get_err_stats (sdla_t* card);
-static int x25_get_stats (sdla_t* card);
-static int x25_set_intr_mode (sdla_t* card, int mode);
-static int x25_close_hdlc (sdla_t* card);
-static int x25_open_hdlc (sdla_t* card);
-static int x25_setup_hdlc (sdla_t* card);
-static int x25_set_dtr (sdla_t* card, int dtr);
-static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan);
-static int x25_place_call (sdla_t* card, x25_channel_t* chan);
-static int x25_accept_call (sdla_t* card, int lcn, int qdm);
-static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn);
-static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf);
-static int x25_fetch_events (sdla_t* card);
-static int x25_error (sdla_t* card, int err, int cmd, int lcn);
-
-/*=================================================
- * X.25 asynchronous event handlers
- */
-static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-
-
-/*=================================================
- * Miscellaneous functions
- */
-static int connect (sdla_t* card);
-static int disconnect (sdla_t* card);
-static struct net_device* get_dev_by_lcn(struct wan_device* wandev,
- unsigned lcn);
-static int chan_connect(struct net_device* dev);
-static int chan_disc(struct net_device* dev);
-static void set_chan_state(struct net_device* dev, int state);
-static int chan_send(struct net_device *dev, void* buff, unsigned data_len,
- unsigned char tx_intr);
-static unsigned char bps_to_speed_code (unsigned long bps);
-static unsigned int dec_to_uint (unsigned char* str, int len);
-static unsigned int hex_to_uint (unsigned char*, int);
-static void parse_call_info (unsigned char*, x25_call_info_t*);
-static struct net_device *find_channel(sdla_t *card, unsigned lcn);
-static void bind_lcn_to_dev(sdla_t *card, struct net_device *dev, unsigned lcn);
-static void setup_for_delayed_transmit(struct net_device *dev,
- void *buf, unsigned len);
-
-
-/*=================================================
- * X25 API Functions
- */
-static int wanpipe_pull_data_in_skb(sdla_t *card, struct net_device *dev,
- struct sk_buff **);
-static void timer_intr_exec(sdla_t *, unsigned char);
-static int execute_delayed_cmd(sdla_t *card, struct net_device *dev,
- mbox_cmd_t *usr_cmd, char bad_cmd);
-static int api_incoming_call (sdla_t*, TX25Mbox *, int);
-static int alloc_and_init_skb_buf (sdla_t *,struct sk_buff **, int);
-static void send_delayed_cmd_result(sdla_t *card, struct net_device *dev,
- TX25Mbox* mbox);
-static int clear_confirm_event (sdla_t *, TX25Mbox*);
-static void send_oob_msg (sdla_t *card, struct net_device *dev, TX25Mbox *mbox);
-static int timer_intr_cmd_exec(sdla_t *card);
-static void api_oob_event (sdla_t *card,TX25Mbox *mbox);
-static int check_bad_command(sdla_t *card, struct net_device *dev);
-static int channel_disconnect(sdla_t* card, struct net_device *dev);
-static void hdlc_link_down (sdla_t*);
-
-/*=================================================
- * XPIPEMON Functions
- */
-static int process_udp_mgmt_pkt(sdla_t *);
-static int udp_pkt_type( struct sk_buff *, sdla_t*);
-static int reply_udp( unsigned char *, unsigned int);
-static void init_x25_channel_struct( x25_channel_t *);
-static void init_global_statistics( sdla_t *);
-static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t *card,
- struct net_device *dev,
- struct sk_buff *skb, int lcn);
-static unsigned short calc_checksum (char *, int);
-
-
-
-/*=================================================
- * IPX functions
- */
-static void switch_net_numbers(unsigned char *, unsigned long, unsigned char);
-static int handle_IPXWAN(unsigned char *, char *, unsigned char ,
- unsigned long , unsigned short );
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-static void S508_S514_lock(sdla_t *, unsigned long *);
-static void S508_S514_unlock(sdla_t *, unsigned long *);
-
-
-/*=================================================
- * Global Variables
- *=================================================*/
-
-
-
-/*=================================================
- * Public Functions
- *=================================================*/
-
-
-
-
-/*===================================================================
- * wpx_init: X.25 Protocol Initialization routine.
- *
- * Purpose: To initialize the protocol/firmware.
- *
- * Rationale: This function is called by setup() function, in
- * sdlamain.c, to dynamically setup the x25 protocol.
- * This is the first protocol specific function, which
- * executes once on startup.
- *
- * Description: This procedure initializes the x25 firmware and
- * sets up the mailbox, transmit and receive buffer
- * pointers. It also initializes all debugging structures
- * and sets up the X25 environment.
- *
- * Sets up hardware options defined by user in [wanpipe#]
- * section of wanpipe#.conf configuration file.
- *
- * At this point adapter is completely initialized
- * and X.25 firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the
- * adapter data space.
- *
- * Called by: setup() function in sdlamain.c
- *
- * Assumptions: None
- *
- * Warnings: None
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-
-int wpx_init (sdla_t* card, wandev_conf_t* conf)
-{
- union{
- char str[80];
- TX25Config cfg;
- } u;
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_X25){
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id)
- ;
- return -EINVAL;
- }
-
- /* Initialize protocol-specific fields */
- card->mbox = (void*)(card->hw.dpmbase + X25_MBOX_OFFS);
- card->rxmb = (void*)(card->hw.dpmbase + X25_RXMBOX_OFFS);
- card->flags = (void*)(card->hw.dpmbase + X25_STATUS_OFFS);
-
- /* Initialize for S514 Card */
- if(card->hw.type == SDLA_S514) {
- card->mbox += X25_MB_VECTOR;
- card->flags += X25_MB_VECTOR;
- card->rxmb += X25_MB_VECTOR;
- }
-
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
- if (x25_get_version(card, NULL) || x25_get_version(card, u.str))
- return -EIO;
-
-
- /* X25 firmware can run ether in X25 or LAPB HDLC mode.
- * Check the user defined option and configure accordingly */
- if (conf->u.x25.LAPB_hdlc_only == WANOPT_YES){
- if (set_hdlc_level(card) != CMD_OK){
- return -EIO;
- }else{
- printk(KERN_INFO "%s: running LAP_B HDLC firmware v%s\n",
- card->devname, u.str);
- }
- card->u.x.LAPB_hdlc = 1;
- }else{
- printk(KERN_INFO "%s: running X.25 firmware v%s\n",
- card->devname, u.str);
- card->u.x.LAPB_hdlc = 0;
- }
-
- /* Configure adapter. Here we set resonable defaults, then parse
- * device configuration structure and set configuration options.
- * Most configuration options are verified and corrected (if
- * necessary) since we can't rely on the adapter to do so.
- */
- memset(&u.cfg, 0, sizeof(u.cfg));
- u.cfg.t1 = 3;
- u.cfg.n2 = 10;
- u.cfg.autoHdlc = 1; /* automatic HDLC connection */
- u.cfg.hdlcWindow = 7;
- u.cfg.pktWindow = 2;
- u.cfg.station = 1; /* DTE */
- u.cfg.options = 0x0090; /* disable D-bit pragmatics */
- u.cfg.ccittCompat = 1988;
- u.cfg.t10t20 = 30;
- u.cfg.t11t21 = 30;
- u.cfg.t12t22 = 30;
- u.cfg.t13t23 = 30;
- u.cfg.t16t26 = 30;
- u.cfg.t28 = 30;
- u.cfg.r10r20 = 5;
- u.cfg.r12r22 = 5;
- u.cfg.r13r23 = 5;
- u.cfg.responseOpt = 1; /* RR's after every packet */
-
- if (card->u.x.LAPB_hdlc){
- u.cfg.hdlcMTU = 1027;
- }
-
- if (conf->u.x25.x25_conf_opt){
- u.cfg.options = conf->u.x25.x25_conf_opt;
- }
-
- if (conf->clocking != WANOPT_EXTERNAL)
- u.cfg.baudRate = bps_to_speed_code(conf->bps);
-
- if (conf->station != WANOPT_DTE){
- u.cfg.station = 0; /* DCE mode */
- }
-
- if (conf->interface != WANOPT_RS232 ){
- u.cfg.hdlcOptions |= 0x80; /* V35 mode */
- }
-
- /* adjust MTU */
- if (!conf->mtu || (conf->mtu >= 1024))
- card->wandev.mtu = 1024;
- else if (conf->mtu >= 512)
- card->wandev.mtu = 512;
- else if (conf->mtu >= 256)
- card->wandev.mtu = 256;
- else if (conf->mtu >= 128)
- card->wandev.mtu = 128;
- else
- card->wandev.mtu = 64;
-
- u.cfg.defPktSize = u.cfg.pktMTU = card->wandev.mtu;
-
- if (conf->u.x25.hi_pvc){
- card->u.x.hi_pvc = min_t(unsigned int, conf->u.x25.hi_pvc, MAX_LCN_NUM);
- card->u.x.lo_pvc = min_t(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc);
- }
-
- if (conf->u.x25.hi_svc){
- card->u.x.hi_svc = min_t(unsigned int, conf->u.x25.hi_svc, MAX_LCN_NUM);
- card->u.x.lo_svc = min_t(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc);
- }
-
- /* Figure out the total number of channels to configure */
- card->u.x.num_of_ch = 0;
- if (card->u.x.hi_svc != 0){
- card->u.x.num_of_ch = (card->u.x.hi_svc - card->u.x.lo_svc) + 1;
- }
- if (card->u.x.hi_pvc != 0){
- card->u.x.num_of_ch += (card->u.x.hi_pvc - card->u.x.lo_pvc) + 1;
- }
-
- if (card->u.x.num_of_ch == 0){
- printk(KERN_INFO "%s: ERROR, Minimum number of PVC/SVC channels is 1 !\n"
- "%s: Please set the Lowest/Highest PVC/SVC values !\n",
- card->devname,card->devname);
- return -ECHRNG;
- }
-
- u.cfg.loPVC = card->u.x.lo_pvc;
- u.cfg.hiPVC = card->u.x.hi_pvc;
- u.cfg.loTwoWaySVC = card->u.x.lo_svc;
- u.cfg.hiTwoWaySVC = card->u.x.hi_svc;
-
- if (conf->u.x25.hdlc_window)
- u.cfg.hdlcWindow = min_t(unsigned int, conf->u.x25.hdlc_window, 7);
- if (conf->u.x25.pkt_window)
- u.cfg.pktWindow = min_t(unsigned int, conf->u.x25.pkt_window, 7);
-
- if (conf->u.x25.t1)
- u.cfg.t1 = min_t(unsigned int, conf->u.x25.t1, 30);
- if (conf->u.x25.t2)
- u.cfg.t2 = min_t(unsigned int, conf->u.x25.t2, 29);
- if (conf->u.x25.t4)
- u.cfg.t4 = min_t(unsigned int, conf->u.x25.t4, 240);
- if (conf->u.x25.n2)
- u.cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30);
-
- if (conf->u.x25.t10_t20)
- u.cfg.t10t20 = min_t(unsigned int, conf->u.x25.t10_t20,255);
- if (conf->u.x25.t11_t21)
- u.cfg.t11t21 = min_t(unsigned int, conf->u.x25.t11_t21,255);
- if (conf->u.x25.t12_t22)
- u.cfg.t12t22 = min_t(unsigned int, conf->u.x25.t12_t22,255);
- if (conf->u.x25.t13_t23)
- u.cfg.t13t23 = min_t(unsigned int, conf->u.x25.t13_t23,255);
- if (conf->u.x25.t16_t26)
- u.cfg.t16t26 = min_t(unsigned int, conf->u.x25.t16_t26, 255);
- if (conf->u.x25.t28)
- u.cfg.t28 = min_t(unsigned int, conf->u.x25.t28, 255);
-
- if (conf->u.x25.r10_r20)
- u.cfg.r10r20 = min_t(unsigned int, conf->u.x25.r10_r20,250);
- if (conf->u.x25.r12_r22)
- u.cfg.r12r22 = min_t(unsigned int, conf->u.x25.r12_r22,250);
- if (conf->u.x25.r13_r23)
- u.cfg.r13r23 = min_t(unsigned int, conf->u.x25.r13_r23,250);
-
-
- if (conf->u.x25.ccitt_compat)
- u.cfg.ccittCompat = conf->u.x25.ccitt_compat;
-
- /* initialize adapter */
- if (card->u.x.LAPB_hdlc){
- if (hdlc_configure(card, &u.cfg) != CMD_OK)
- return -EIO;
- }else{
- if (x25_configure(card, &u.cfg) != CMD_OK)
- return -EIO;
- }
-
- if ((x25_close_hdlc(card) != CMD_OK) || /* close HDLC link */
- (x25_set_dtr(card, 0) != CMD_OK)) /* drop DTR */
- return -EIO;
-
- /* Initialize protocol-specific fields of adapter data space */
- card->wandev.bps = conf->bps;
- card->wandev.interface = conf->interface;
- card->wandev.clocking = conf->clocking;
- card->wandev.station = conf->station;
- card->isr = &wpx_isr;
- card->poll = NULL; //&wpx_poll;
- card->disable_comm = &disable_comm;
- card->exec = &wpx_exec;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = &del_if;
-
- /* WARNING: This function cannot exit with an error
- * after the change of state */
- card->wandev.state = WAN_DISCONNECTED;
-
- card->wandev.enable_tx_int = 0;
- card->irq_dis_if_send_count = 0;
- card->irq_dis_poll_count = 0;
- card->u.x.tx_dev = NULL;
- card->u.x.no_dev = 0;
-
-
- /* Configure for S514 PCI Card */
- if (card->hw.type == SDLA_S514) {
- card->u.x.hdlc_buf_status =
- (volatile unsigned char *)
- (card->hw.dpmbase + X25_MB_VECTOR+ X25_MISC_HDLC_BITS);
- }else{
- card->u.x.hdlc_buf_status =
- (volatile unsigned char *)(card->hw.dpmbase + X25_MISC_HDLC_BITS);
- }
-
- card->u.x.poll_device=NULL;
- card->wandev.udp_port = conf->udp_port;
-
- /* Enable or disable call setup logging */
- if (conf->u.x25.logging == WANOPT_YES){
- printk(KERN_INFO "%s: Enabling Call Logging.\n",
- card->devname);
- card->u.x.logging = 1;
- }else{
- card->u.x.logging = 0;
- }
-
- /* Enable or disable modem status reporting */
- if (conf->u.x25.oob_on_modem == WANOPT_YES){
- printk(KERN_INFO "%s: Enabling OOB on Modem change.\n",
- card->devname);
- card->u.x.oob_on_modem = 1;
- }else{
- card->u.x.oob_on_modem = 0;
- }
-
- init_global_statistics(card);
-
- INIT_WORK(&card->u.x.x25_poll_work, (void *)wpx_poll, card);
-
- init_timer(&card->u.x.x25_timer);
- card->u.x.x25_timer.data = (unsigned long)card;
- card->u.x.x25_timer.function = x25_timer_routine;
-
- return 0;
-}
-
-/*=========================================================
- * WAN Device Driver Entry Points
- *========================================================*/
-
-/*============================================================
- * Name: update(), Update device status & statistics.
- *
- * Purpose: To provide debugging and statitical
- * information to the /proc file system.
- * /proc/net/wanrouter/wanpipe#
- *
- * Rationale: The /proc file system is used to collect
- * information about the kernel and drivers.
- * Using the /proc file system the user
- * can see exactly what the sangoma drivers are
- * doing. And in what state they are in.
- *
- * Description: Collect all driver statistical information
- * and pass it to the top laywer.
- *
- * Since we have to execute a debugging command,
- * to obtain firmware statitics, we trigger a
- * UPDATE function within the timer interrtup.
- * We wait until the timer update is complete.
- * Once complete return the appropriate return
- * code to indicate that the update was successful.
- *
- * Called by: device_stat() in wanmain.c
- *
- * Assumptions:
- *
- * Warnings: This function will degrade the performance
- * of the router, since it uses the mailbox.
- *
- * Return: 0 OK
- * <0 Failed (or busy).
- */
-
-static int update(struct wan_device* wandev)
-{
- volatile sdla_t* card;
- TX25Status* status;
- unsigned long timeout;
-
- /* sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
-
- if (wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- if (test_bit(SEND_CRIT, (void*)&wandev->critical))
- return -EAGAIN;
-
- if (!wandev->dev)
- return -ENODEV;
-
- card = wandev->private;
- status = card->flags;
-
- card->u.x.timer_int_enabled |= TMR_INT_ENABLED_UPDATE;
- status->imask |= INTR_ON_TIMER;
- timeout = jiffies;
-
- for (;;){
- if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE)){
- break;
- }
- if (time_after(jiffies, timeout + 1*HZ)){
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE;
- return -EAGAIN;
- }
- }
- return 0;
-}
-
-
-/*===================================================================
- * Name: new_if
- *
- * Purpose: To allocate and initialize resources for a
- * new logical channel.
- *
- * Rationale: A new channel can be added dynamically via
- * ioctl call.
- *
- * Description: Allocate a private channel structure, x25_channel_t.
- * Parse the user interface options from wanpipe#.conf
- * configuration file.
- * Bind the private are into the network device private
- * area pointer (dev->priv).
- * Prepare the network device structure for registration.
- *
- * Called by: ROUTER_IFNEW Ioctl call, from wanrouter_ioctl()
- * (wanmain.c)
- *
- * Assumptions: None
- *
- * Warnings: None
- *
- * Return: 0 Ok
- * <0 Failed (channel will not be created)
- */
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf)
-{
- sdla_t* card = wandev->private;
- x25_channel_t* chan;
- int err = 0;
-
- if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)){
- printk(KERN_INFO "%s: invalid interface name!\n",
- card->devname);
- return -EINVAL;
- }
-
- if(card->wandev.new_if_cnt++ > 0 && card->u.x.LAPB_hdlc) {
- printk(KERN_INFO "%s: Error: Running LAPB HDLC Mode !\n",
- card->devname);
- printk(KERN_INFO
- "%s: Maximum number of network interfaces must be one !\n",
- card->devname);
- return -EEXIST;
- }
-
- /* allocate and initialize private data */
- chan = kmalloc(sizeof(x25_channel_t), GFP_ATOMIC);
- if (chan == NULL){
- return -ENOMEM;
- }
-
- memset(chan, 0, sizeof(x25_channel_t));
-
- /* Bug Fix: Seg Err on PVC startup
- * It must be here since bind_lcn_to_dev expects
- * it bellow */
- dev->priv = chan;
-
- strcpy(chan->name, conf->name);
- chan->card = card;
- chan->dev = dev;
- chan->common.sk = NULL;
- chan->common.func = NULL;
- chan->common.rw_bind = 0;
- chan->tx_skb = chan->rx_skb = NULL;
-
- /* verify media address */
- if (conf->addr[0] == '@'){ /* SVC */
- chan->common.svc = 1;
- strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ);
-
- /* Set channel timeouts (default if not specified) */
- chan->idle_timeout = (conf->idle_timeout) ?
- conf->idle_timeout : 90;
- chan->hold_timeout = (conf->hold_timeout) ?
- conf->hold_timeout : 10;
-
- }else if (isdigit(conf->addr[0])){ /* PVC */
- int lcn = dec_to_uint(conf->addr, 0);
-
- if ((lcn >= card->u.x.lo_pvc) && (lcn <= card->u.x.hi_pvc)){
- bind_lcn_to_dev (card, dev, lcn);
- }else{
- printk(KERN_ERR
- "%s: PVC %u is out of range on interface %s!\n",
- wandev->name, lcn, chan->name);
- err = -EINVAL;
- }
- }else{
- printk(KERN_ERR
- "%s: invalid media address on interface %s!\n",
- wandev->name, chan->name);
- err = -EINVAL;
- }
-
- if(strcmp(conf->usedby, "WANPIPE") == 0){
- printk(KERN_INFO "%s: Running in WANPIPE mode %s\n",
- wandev->name, chan->name);
- chan->common.usedby = WANPIPE;
- chan->protocol = htons(ETH_P_IP);
-
- }else if(strcmp(conf->usedby, "API") == 0){
- chan->common.usedby = API;
- printk(KERN_INFO "%s: Running in API mode %s\n",
- wandev->name, chan->name);
- chan->protocol = htons(X25_PROT);
- }
-
-
- if (err){
- kfree(chan);
- dev->priv = NULL;
- return err;
- }
-
- chan->enable_IPX = conf->enable_IPX;
-
- if (chan->enable_IPX)
- chan->protocol = htons(ETH_P_IPX);
-
- if (conf->network_number)
- chan->network_number = conf->network_number;
- else
- chan->network_number = 0xDEADBEEF;
-
- /* prepare network device data space for registration */
- strcpy(dev->name,chan->name);
-
- dev->init = &if_init;
-
- init_x25_channel_struct(chan);
-
- return 0;
-}
-
-/*===================================================================
- * Name: del_if(), Remove a logical channel.
- *
- * Purpose: To dynamically remove a logical channel.
- *
- * Rationale: Each logical channel should be dynamically
- * removable. This functin is called by an
- * IOCTL_IFDEL ioctl call or shutdown().
- *
- * Description: Do nothing.
- *
- * Called by: IOCTL_IFDEL : wanrouter_ioctl() from wanmain.c
- * shutdown() from sdlamain.c
- *
- * Assumptions:
- *
- * Warnings:
- *
- * Return: 0 Ok. Void function.
- */
-
-//FIXME Del IF Should be taken out now.
-
-static int del_if(struct wan_device* wandev, struct net_device* dev)
-{
- return 0;
-}
-
-
-/*============================================================
- * Name: wpx_exec
- *
- * Description: Execute adapter interface command.
- * This option is currently dissabled.
- *===========================================================*/
-
-static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data)
-{
- return 0;
-}
-
-/*============================================================
- * Name: disable_comm
- *
- * Description: Disable communications during shutdown.
- * Dont check return code because there is
- * nothing we can do about it.
- *
- * Warning: Dev and private areas are gone at this point.
- *===========================================================*/
-
-static void disable_comm(sdla_t* card)
-{
- disable_comm_shutdown(card);
- del_timer(&card->u.x.x25_timer);
- return;
-}
-
-
-/*============================================================
- * Network Device Interface
- *===========================================================*/
-
-/*===================================================================
- * Name: if_init(), Netowrk Interface Initialization
- *
- * Purpose: To initialize a network interface device structure.
- *
- * Rationale: During network interface startup, the if_init
- * is called by the kernel to initialize the
- * netowrk device structure. Thus a driver
- * can customze a network device.
- *
- * Description: Initialize the netowrk device call back
- * routines. This is where we tell the kernel
- * which function to use when it wants to send
- * via our interface.
- * Furthermore, we initialize the device flags,
- * MTU and physical address of the board.
- *
- * Called by: Kernel (/usr/src/linux/net/core/dev.c)
- * (dev->init())
- *
- * Assumptions: None
- *
- * Warnings: None
- *
- * Return: 0 Ok : Void function.
- */
-static int if_init(struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- struct wan_device* wandev = &card->wandev;
-
- /* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_header = &if_header;
- dev->rebuild_header = &if_rebuild_hdr;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
- dev->tx_timeout = &if_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- /* Initialize media-specific parameters */
- dev->type = ARPHRD_PPP; /* ARP h/w type */
- dev->flags |= IFF_POINTOPOINT;
- dev->flags |= IFF_NOARP;
-
- if (chan->common.usedby == API){
- dev->mtu = X25_CHAN_MTU+sizeof(x25api_hdr_t);
- }else{
- dev->mtu = card->wandev.mtu;
- }
-
- dev->hard_header_len = X25_HRDHDR_SZ; /* media header length */
- dev->addr_len = 2; /* hardware address length */
-
- if (!chan->common.svc){
- *(unsigned short*)dev->dev_addr = htons(chan->common.lcn);
- }
-
- /* Initialize hardware parameters (just for reference) */
- dev->irq = wandev->irq;
- dev->dma = wandev->dma;
- dev->base_addr = wandev->ioport;
- dev->mem_start = (unsigned long)wandev->maddr;
- dev->mem_end = wandev->maddr + wandev->msize - 1;
-
- /* Set transmit buffer queue length */
- dev->tx_queue_len = 100;
- SET_MODULE_OWNER(dev);
-
- /* FIXME Why are we doing this */
- set_chan_state(dev, WAN_DISCONNECTED);
- return 0;
-}
-
-
-/*===================================================================
- * Name: if_open(), Open/Bring up the Netowrk Interface
- *
- * Purpose: To bring up a network interface.
- *
- * Rationale:
- *
- * Description: Open network interface.
- * o prevent module from unloading by incrementing use count
- * o if link is disconnected then initiate connection
- *
- * Called by: Kernel (/usr/src/linux/net/core/dev.c)
- * (dev->open())
- *
- * Assumptions: None
- *
- * Warnings: None
- *
- * Return: 0 Ok
- * <0 Failure: Interface will not come up.
- */
-
-static int if_open(struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- struct timeval tv;
- unsigned long smp_flags;
-
- if (netif_running(dev))
- return -EBUSY;
-
- chan->tq_working = 0;
-
- /* Initialize the workqueue */
- INIT_WORK(&chan->common.wanpipe_work, (void *)x25api_bh, dev);
-
- /* Allocate and initialize BH circular buffer */
- /* Add 1 to MAX_BH_BUFF so we don't have test with (MAX_BH_BUFF-1) */
- chan->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC);
-
- if (chan->bh_head == NULL){
- printk(KERN_INFO "%s: ERROR, failed to allocate memory ! BH_BUFFERS !\n",
- card->devname);
-
- return -ENOBUFS;
- }
- memset(chan->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1)));
- atomic_set(&chan->bh_buff_used, 0);
-
- /* Increment the number of interfaces */
- ++card->u.x.no_dev;
-
- wanpipe_open(card);
-
- /* LAPB protocol only uses one interface, thus
- * start the protocol after it comes up. */
- if (card->u.x.LAPB_hdlc){
- if (card->open_cnt == 1){
- TX25Status* status = card->flags;
- S508_S514_lock(card, &smp_flags);
- x25_set_intr_mode(card, INTR_ON_TIMER);
- status->imask &= ~INTR_ON_TIMER;
- S508_S514_unlock(card, &smp_flags);
- }
- }else{
- /* X25 can have multiple interfaces thus, start the
- * protocol once all interfaces are up */
-
- //FIXME: There is a bug here. If interface is
- //brought down and up, it will try to enable comm.
- if (card->open_cnt == card->u.x.num_of_ch){
-
- S508_S514_lock(card, &smp_flags);
- connect(card);
- S508_S514_unlock(card, &smp_flags);
-
- mod_timer(&card->u.x.x25_timer, jiffies + HZ);
- }
- }
- /* Device is not up until the we are in connected state */
- do_gettimeofday( &tv );
- chan->router_start_time = tv.tv_sec;
-
- netif_start_queue(dev);
-
- return 0;
-}
-
-/*===================================================================
- * Name: if_close(), Close/Bring down the Netowrk Interface
- *
- * Purpose: To bring down a network interface.
- *
- * Rationale:
- *
- * Description: Close network interface.
- * o decrement use module use count
- *
- * Called by: Kernel (/usr/src/linux/net/core/dev.c)
- * (dev->close())
- * ifconfig <name> down: will trigger the kernel
- * which will call this function.
- *
- * Assumptions: None
- *
- * Warnings: None
- *
- * Return: 0 Ok
- * <0 Failure: Interface will not exit properly.
- */
-static int if_close(struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- unsigned long smp_flags;
-
- netif_stop_queue(dev);
-
- if ((chan->common.state == WAN_CONNECTED) ||
- (chan->common.state == WAN_CONNECTING)){
- S508_S514_lock(card, &smp_flags);
- chan_disc(dev);
- S508_S514_unlock(card, &smp_flags);
- }
-
- wanpipe_close(card);
-
- S508_S514_lock(card, &smp_flags);
- if (chan->bh_head){
- int i;
- struct sk_buff *skb;
-
- for (i=0; i<(MAX_BH_BUFF+1); i++){
- skb = ((bh_data_t *)&chan->bh_head[i])->skb;
- if (skb != NULL){
- dev_kfree_skb_any(skb);
- }
- }
- kfree(chan->bh_head);
- chan->bh_head=NULL;
- }
- S508_S514_unlock(card, &smp_flags);
-
- /* If this is the last close, disconnect physical link */
- if (!card->open_cnt){
- S508_S514_lock(card, &smp_flags);
- disconnect(card);
- x25_set_intr_mode(card, 0);
- S508_S514_unlock(card, &smp_flags);
- }
-
- /* Decrement the number of interfaces */
- --card->u.x.no_dev;
- return 0;
-}
-
-/*======================================================================
- * Build media header.
- * o encapsulate packet according to encapsulation type.
- *
- * The trick here is to put packet type (Ethertype) into 'protocol'
- * field of the socket buffer, so that we don't forget it.
- * If encapsulation fails, set skb->protocol to 0 and discard
- * packet later.
- *
- * Return: media header length.
- *======================================================================*/
-
-static int if_header(struct sk_buff* skb, struct net_device* dev,
- unsigned short type, void* daddr, void* saddr,
- unsigned len)
-{
- x25_channel_t* chan = dev->priv;
- int hdr_len = dev->hard_header_len;
-
- skb->protocol = htons(type);
- if (!chan->protocol){
- hdr_len = wanrouter_encapsulate(skb, dev, type);
- if (hdr_len < 0){
- hdr_len = 0;
- skb->protocol = htons(0);
- }
- }
- return hdr_len;
-}
-
-/*===============================================================
- * Re-build media header.
- *
- * Return: 1 physical address resolved.
- * 0 physical address not resolved
- *==============================================================*/
-
-static int if_rebuild_hdr (struct sk_buff* skb)
-{
- struct net_device *dev = skb->dev;
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",
- card->devname, dev->name);
- return 1;
-}
-
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- /* If our device stays busy for at least 5 seconds then we will
- * kick start the device by making dev->tbusy = 0. We expect
- * that our device never stays busy more than 5 seconds. So this
- * is only used as a last resort.
- */
-
- ++chan->if_send_stat.if_send_tbusy_timeout;
- printk (KERN_INFO "%s: Transmit timed out on %s\n",
- card->devname, dev->name);
- netif_wake_queue (dev);
-}
-
-
-/*=========================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission).
- * o check link state. If link is not up, then drop the packet.
- * o check channel status. If it's down then initiate a call.
- * o pass a packet to corresponding WAN device.
- * o free socket buffer
- *
- * Return: 0 complete (socket buffer must be freed)
- * non-0 packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- * bottom half" (with interrupts enabled).
- * 2. Setting tbusy flag will inhibit further transmit requests from the
- * protocol stack and can be used for flow control with protocol layer.
- *
- *========================================================================*/
-
-static int if_send(struct sk_buff* skb, struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- TX25Status* status = card->flags;
- int udp_type;
- unsigned long smp_flags=0;
-
- ++chan->if_send_stat.if_send_entry;
-
- netif_stop_queue(dev);
-
- /* No need to check frame length, since socket code
- * will perform the check for us */
-
- chan->tick_counter = jiffies;
-
- /* Critical region starts here */
- S508_S514_lock(card, &smp_flags);
-
- if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){
- printk(KERN_INFO "Hit critical in if_send()! %lx\n",card->wandev.critical);
- goto if_send_crit_exit;
- }
-
- udp_type = udp_pkt_type(skb, card);
-
- if(udp_type != UDP_INVALID_TYPE) {
-
- if(store_udp_mgmt_pkt(udp_type, UDP_PKT_FRM_STACK, card, dev, skb,
- chan->common.lcn)) {
-
- status->imask |= INTR_ON_TIMER;
- if (udp_type == UDP_XPIPE_TYPE){
- chan->if_send_stat.if_send_PIPE_request++;
- }
- }
- netif_start_queue(dev);
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
- S508_S514_unlock(card, &smp_flags);
- return 0;
- }
-
- if (chan->transmit_length){
- //FIXME: This check doesn't make sense any more
- if (chan->common.state != WAN_CONNECTED){
- chan->transmit_length=0;
- atomic_set(&chan->common.driver_busy,0);
- }else{
- netif_stop_queue(dev);
- ++card->u.x.tx_interrupts_pending;
- status->imask |= INTR_ON_TX_FRAME;
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
- S508_S514_unlock(card, &smp_flags);
- return 1;
- }
- }
-
- if (card->wandev.state != WAN_CONNECTED){
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- ++chan->if_send_stat.if_send_wan_disconnected;
-
- }else if ( chan->protocol && (chan->protocol != skb->protocol)){
- printk(KERN_INFO
- "%s: unsupported Ethertype 0x%04X on interface %s!\n",
- chan->name, htons(skb->protocol), dev->name);
-
- printk(KERN_INFO "PROTO %Xn", htons(chan->protocol));
- ++chan->ifstats.tx_errors;
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- ++chan->if_send_stat.if_send_protocol_error;
-
- }else switch (chan->common.state){
-
- case WAN_DISCONNECTED:
- /* Try to establish connection. If succeded, then start
- * transmission, else drop a packet.
- */
- if (chan->common.usedby == API){
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- break;
- }else{
- if (chan_connect(dev) != 0){
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- break;
- }
- }
- /* fall through */
-
- case WAN_CONNECTED:
- if( skb->protocol == htons(ETH_P_IPX)) {
- if(chan->enable_IPX) {
- switch_net_numbers( skb->data,
- chan->network_number, 0);
- } else {
- ++card->wandev.stats.tx_dropped;
- ++chan->ifstats.tx_dropped;
- ++chan->if_send_stat.if_send_protocol_error;
- goto if_send_crit_exit;
- }
- }
- /* We never drop here, if cannot send than, copy
- * a packet into a transmit buffer
- */
- chan_send(dev, skb->data, skb->len, 0);
- break;
-
- default:
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- break;
- }
-
-
-if_send_crit_exit:
-
- dev_kfree_skb_any(skb);
-
- netif_start_queue(dev);
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
- S508_S514_unlock(card, &smp_flags);
- return 0;
-}
-
-/*============================================================================
- * Setup so that a frame can be transmitted on the occurrence of a transmit
- * interrupt.
- *===========================================================================*/
-
-static void setup_for_delayed_transmit(struct net_device* dev, void* buf,
- unsigned len)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- TX25Status* status = card->flags;
-
- ++chan->if_send_stat.if_send_adptr_bfrs_full;
-
- if(chan->transmit_length) {
- printk(KERN_INFO "%s: Error, transmit length set in delayed transmit!\n",
- card->devname);
- return;
- }
-
- if (chan->common.usedby == API){
- if (len > X25_CHAN_MTU+sizeof(x25api_hdr_t)) {
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- printk(KERN_INFO "%s: Length is too big for delayed transmit\n",
- card->devname);
- return;
- }
- }else{
- if (len > X25_MAX_DATA) {
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- printk(KERN_INFO "%s: Length is too big for delayed transmit\n",
- card->devname);
- return;
- }
- }
-
- chan->transmit_length = len;
- atomic_set(&chan->common.driver_busy,1);
- memcpy(chan->transmit_buffer, buf, len);
-
- ++chan->if_send_stat.if_send_tx_int_enabled;
-
- /* Enable Transmit Interrupt */
- ++card->u.x.tx_interrupts_pending;
- status->imask |= INTR_ON_TX_FRAME;
-}
-
-
-/*===============================================================
- * net_device_stats
- *
- * Get ethernet-style interface statistics.
- * Return a pointer to struct enet_statistics.
- *
- *==============================================================*/
-static struct net_device_stats *if_stats(struct net_device* dev)
-{
- x25_channel_t *chan = dev->priv;
-
- if(chan == NULL)
- return NULL;
-
- return &chan->ifstats;
-}
-
-
-/*
- * Interrupt Handlers
- */
-
-/*
- * X.25 Interrupt Service Routine.
- */
-
-static void wpx_isr (sdla_t* card)
-{
- TX25Status* status = card->flags;
-
- card->in_isr = 1;
- ++card->statistics.isr_entry;
-
- if (test_bit(PERI_CRIT,(void*)&card->wandev.critical)){
- card->in_isr=0;
- status->iflags = 0;
- return;
- }
-
- if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)){
-
- printk(KERN_INFO "%s: wpx_isr: wandev.critical set to 0x%02lx, int type = 0x%02x\n",
- card->devname, card->wandev.critical, status->iflags);
- card->in_isr = 0;
- status->iflags = 0;
- return;
- }
-
- /* For all interrupts set the critical flag to CRITICAL_RX_INTR.
- * If the if_send routine is called with this flag set it will set
- * the enable transmit flag to 1. (for a delayed interrupt)
- */
- switch (status->iflags){
-
- case RX_INTR_PENDING: /* receive interrupt */
- rx_intr(card);
- break;
-
- case TX_INTR_PENDING: /* transmit interrupt */
- tx_intr(card);
- break;
-
- case MODEM_INTR_PENDING: /* modem status interrupt */
- status_intr(card);
- break;
-
- case X25_ASY_TRANS_INTR_PENDING: /* network event interrupt */
- event_intr(card);
- break;
-
- case TIMER_INTR_PENDING:
- timer_intr(card);
- break;
-
- default: /* unwanted interrupt */
- spur_intr(card);
- }
-
- card->in_isr = 0;
- status->iflags = 0; /* clear interrupt condition */
-}
-
-/*
- * Receive interrupt handler.
- * This routine handles fragmented IP packets using M-bit according to the
- * RFC1356.
- * o map ligical channel number to network interface.
- * o allocate socket buffer or append received packet to the existing one.
- * o if M-bit is reset (i.e. it's the last packet in a sequence) then
- * decapsulate packet and pass socket buffer to the protocol stack.
- *
- * Notes:
- * 1. When allocating a socket buffer, if M-bit is set then more data is
- * coming and we have to allocate buffer for the maximum IP packet size
- * expected on this channel.
- * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no
- * socket buffers available) the whole packet sequence must be discarded.
- */
-
-static void rx_intr (sdla_t* card)
-{
- TX25Mbox* rxmb = card->rxmb;
- unsigned lcn = rxmb->cmd.lcn;
- struct net_device* dev = find_channel(card,lcn);
- x25_channel_t* chan;
- struct sk_buff* skb=NULL;
-
- if (dev == NULL){
- /* Invalid channel, discard packet */
- printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
- card->devname, lcn);
- return;
- }
-
- chan = dev->priv;
- chan->i_timeout_sofar = jiffies;
-
-
- /* Copy the data from the board, into an
- * skb buffer
- */
- if (wanpipe_pull_data_in_skb(card,dev,&skb)){
- ++chan->ifstats.rx_dropped;
- ++card->wandev.stats.rx_dropped;
- ++chan->rx_intr_stat.rx_intr_no_socket;
- ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
- return;
- }
-
- dev->last_rx = jiffies; /* timestamp */
-
-
- /* ------------ API ----------------*/
-
- if (chan->common.usedby == API){
-
- if (bh_enqueue(dev, skb)){
- ++chan->ifstats.rx_dropped;
- ++card->wandev.stats.rx_dropped;
- ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
- dev_kfree_skb_any(skb);
- return;
- }
-
- ++chan->ifstats.rx_packets;
- chan->ifstats.rx_bytes += skb->len;
-
-
- chan->rx_skb = NULL;
- if (!test_and_set_bit(0, &chan->tq_working)){
- wanpipe_queue_work(&chan->common.wanpipe_work);
- }
- return;
- }
-
-
- /* ------------- WANPIPE -------------------*/
-
- /* set rx_skb to NULL so we won't access it later when kernel already owns it */
- chan->rx_skb=NULL;
-
- /* Decapsulate packet, if necessary */
- if (!skb->protocol && !wanrouter_type_trans(skb, dev)){
- /* can't decapsulate packet */
- dev_kfree_skb_any(skb);
- ++chan->ifstats.rx_errors;
- ++chan->ifstats.rx_dropped;
- ++card->wandev.stats.rx_dropped;
- ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
-
- }else{
- if( handle_IPXWAN(skb->data, chan->name,
- chan->enable_IPX, chan->network_number,
- skb->protocol)){
-
- if( chan->enable_IPX ){
- if(chan_send(dev, skb->data, skb->len,0)){
- chan->tx_skb = skb;
- }else{
- dev_kfree_skb_any(skb);
- ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
- }
- }else{
- /* increment IPX packet dropped statistic */
- ++chan->ifstats.rx_dropped;
- ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
- }
- }else{
- skb->mac.raw = skb->data;
- chan->ifstats.rx_bytes += skb->len;
- ++chan->ifstats.rx_packets;
- ++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack;
- netif_rx(skb);
- }
- }
-
- return;
-}
-
-
-static int wanpipe_pull_data_in_skb(sdla_t *card, struct net_device *dev,
- struct sk_buff **skb)
-{
- void *bufptr;
- TX25Mbox* rxmb = card->rxmb;
- unsigned len = rxmb->cmd.length; /* packet length */
- unsigned qdm = rxmb->cmd.qdm; /* Q,D and M bits */
- x25_channel_t *chan = dev->priv;
- struct sk_buff *new_skb = *skb;
-
- if (chan->common.usedby == WANPIPE){
- if (chan->drop_sequence){
- if (!(qdm & 0x01)){
- chan->drop_sequence = 0;
- }
- return 1;
- }
- new_skb = chan->rx_skb;
- }else{
- /* Add on the API header to the received
- * data
- */
- len += sizeof(x25api_hdr_t);
- }
-
- if (new_skb == NULL){
- int bufsize;
-
- if (chan->common.usedby == WANPIPE){
- bufsize = (qdm & 0x01) ? dev->mtu : len;
- }else{
- bufsize = len;
- }
-
- /* Allocate new socket buffer */
- new_skb = dev_alloc_skb(bufsize + dev->hard_header_len);
- if (new_skb == NULL){
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- chan->drop_sequence = 1; /* set flag */
- ++chan->ifstats.rx_dropped;
- return 1;
- }
- }
-
- if (skb_tailroom(new_skb) < len){
- /* No room for the packet. Call off the whole thing! */
- dev_kfree_skb_any(new_skb);
- if (chan->common.usedby == WANPIPE){
- chan->rx_skb = NULL;
- if (qdm & 0x01){
- chan->drop_sequence = 1;
- }
- }
-
- printk(KERN_INFO "%s: unexpectedly long packet sequence "
- "on interface %s!\n", card->devname, dev->name);
- ++chan->ifstats.rx_length_errors;
- return 1;
- }
-
- bufptr = skb_put(new_skb,len);
-
-
- if (chan->common.usedby == API){
- /* Fill in the x25api header
- */
- x25api_t * api_data = (x25api_t*)bufptr;
- api_data->hdr.qdm = rxmb->cmd.qdm;
- api_data->hdr.cause = rxmb->cmd.cause;
- api_data->hdr.diagn = rxmb->cmd.diagn;
- api_data->hdr.length = rxmb->cmd.length;
- memcpy(api_data->data, rxmb->data, rxmb->cmd.length);
- }else{
- memcpy(bufptr, rxmb->data, len);
- }
-
- new_skb->dev = dev;
-
- if (chan->common.usedby == API){
- new_skb->mac.raw = new_skb->data;
- new_skb->protocol = htons(X25_PROT);
- new_skb->pkt_type = WAN_PACKET_DATA;
- }else{
- new_skb->protocol = chan->protocol;
- chan->rx_skb = new_skb;
- }
-
- /* If qdm bit is set, more data is coming
- * thus, exit and wait for more data before
- * sending the packet up. (Used by router only)
- */
- if ((qdm & 0x01) && (chan->common.usedby == WANPIPE))
- return 1;
-
- *skb = new_skb;
-
- return 0;
-}
-
-/*===============================================================
- * tx_intr
- *
- * Transmit interrupt handler.
- * For each dev, check that there is something to send.
- * If data available, transmit.
- *
- *===============================================================*/
-
-static void tx_intr (sdla_t* card)
-{
- struct net_device *dev;
- TX25Status* status = card->flags;
- unsigned char more_to_tx=0;
- x25_channel_t *chan=NULL;
- int i=0;
-
- if (card->u.x.tx_dev == NULL){
- card->u.x.tx_dev = card->wandev.dev;
- }
-
- dev = card->u.x.tx_dev;
-
- for (;;){
-
- chan = dev->priv;
- if (chan->transmit_length){
- /* Device was set to transmit, check if the TX
- * buffers are available
- */
- if (chan->common.state != WAN_CONNECTED){
- chan->transmit_length = 0;
- atomic_set(&chan->common.driver_busy,0);
- chan->tx_offset=0;
- if (netif_queue_stopped(dev)){
- if (chan->common.usedby == API){
- netif_start_queue(dev);
- wakeup_sk_bh(dev);
- }else{
- netif_wake_queue(dev);
- }
- }
- dev = move_dev_to_next(card,dev);
- break;
- }
-
- if ((status->cflags[chan->ch_idx] & 0x40 || card->u.x.LAPB_hdlc) &&
- (*card->u.x.hdlc_buf_status & 0x40) ){
- /* Tx buffer available, we can send */
-
- if (tx_intr_send(card, dev)){
- more_to_tx=1;
- }
-
- /* If more than one interface present, move the
- * device pointer to the next interface, so on the
- * next TX interrupt we will try sending from it.
- */
- dev = move_dev_to_next(card,dev);
- break;
- }else{
- /* Tx buffers not available, but device set
- * the TX interrupt. Set more_to_tx and try
- * to transmit for other devices.
- */
- more_to_tx=1;
- dev = move_dev_to_next(card,dev);
- }
-
- }else{
- /* This device was not set to transmit,
- * go to next
- */
- dev = move_dev_to_next(card,dev);
- }
-
- if (++i == card->u.x.no_dev){
- if (!more_to_tx){
- DBG_PRINTK(KERN_INFO "%s: Nothing to Send in TX INTR\n",
- card->devname);
- }
- break;
- }
-
- } //End of FOR
-
- card->u.x.tx_dev = dev;
-
- if (!more_to_tx){
- /* if any other interfaces have transmit interrupts pending, */
- /* do not disable the global transmit interrupt */
- if (!(--card->u.x.tx_interrupts_pending)){
- status->imask &= ~INTR_ON_TX_FRAME;
- }
- }
- return;
-}
-
-/*===============================================================
- * move_dev_to_next
- *
- *
- *===============================================================*/
-
-
-struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev)
-{
- if (card->u.x.no_dev != 1){
- if (!*((struct net_device **)dev->priv))
- return card->wandev.dev;
- else
- return *((struct net_device **)dev->priv);
- }
- return dev;
-}
-
-/*===============================================================
- * tx_intr_send
- *
- *
- *===============================================================*/
-
-static int tx_intr_send(sdla_t *card, struct net_device *dev)
-{
- x25_channel_t* chan = dev->priv;
-
- if (chan_send (dev,chan->transmit_buffer,chan->transmit_length,1)){
-
- /* Packet was split up due to its size, do not disable
- * tx_intr
- */
- return 1;
- }
-
- chan->transmit_length=0;
- atomic_set(&chan->common.driver_busy,0);
- chan->tx_offset=0;
-
- /* If we are in API mode, wakeup the
- * sock BH handler, not the NET_BH */
- if (netif_queue_stopped(dev)){
- if (chan->common.usedby == API){
- netif_start_queue(dev);
- wakeup_sk_bh(dev);
- }else{
- netif_wake_queue(dev);
- }
- }
- return 0;
-}
-
-
-/*===============================================================
- * timer_intr
- *
- * Timer interrupt handler.
- * Check who called the timer interrupt and perform
- * action accordingly.
- *
- *===============================================================*/
-
-static void timer_intr (sdla_t *card)
-{
- TX25Status* status = card->flags;
-
- if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC){
-
- if (timer_intr_cmd_exec(card) == 0){
- card->u.x.timer_int_enabled &=
- ~TMR_INT_ENABLED_CMD_EXEC;
- }
-
- }else if(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UDP_PKT) {
-
- if ((*card->u.x.hdlc_buf_status & 0x40) &&
- card->u.x.udp_type == UDP_XPIPE_TYPE){
-
- if(process_udp_mgmt_pkt(card)) {
- card->u.x.timer_int_enabled &=
- ~TMR_INT_ENABLED_UDP_PKT;
- }
- }
-
- }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_ACTIVE) {
-
- struct net_device *dev = card->u.x.poll_device;
- x25_channel_t *chan = NULL;
-
- if (!dev){
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE;
- return;
- }
- chan = dev->priv;
-
- printk(KERN_INFO
- "%s: Closing down Idle link %s on LCN %d\n",
- card->devname,chan->name,chan->common.lcn);
- chan->i_timeout_sofar = jiffies;
- chan_disc(dev);
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE;
- card->u.x.poll_device=NULL;
-
- }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_ON) {
-
- wanpipe_set_state(card, WAN_CONNECTED);
- if (card->u.x.LAPB_hdlc){
- struct net_device *dev = card->wandev.dev;
- set_chan_state(dev,WAN_CONNECTED);
- send_delayed_cmd_result(card,dev,card->mbox);
- }
-
- /* 0x8F enable all interrupts */
- x25_set_intr_mode(card, INTR_ON_RX_FRAME|
- INTR_ON_TX_FRAME|
- INTR_ON_MODEM_STATUS_CHANGE|
- //INTR_ON_COMMAND_COMPLETE|
- X25_ASY_TRANS_INTR_PENDING |
- INTR_ON_TIMER |
- DIRECT_RX_INTR_USAGE
- );
-
- status->imask &= ~INTR_ON_TX_FRAME; /* mask Tx interrupts */
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_ON;
-
- }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_OFF) {
-
- //printk(KERN_INFO "Poll connect, Turning OFF\n");
- disconnect(card);
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_OFF;
-
- }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_DISCONNECT) {
-
- //printk(KERN_INFO "POll disconnect, trying to connect\n");
- connect(card);
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_DISCONNECT;
-
- }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE){
-
- if (*card->u.x.hdlc_buf_status & 0x40){
- x25_get_err_stats(card);
- x25_get_stats(card);
- card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE;
- }
- }
-
- if(!card->u.x.timer_int_enabled){
- //printk(KERN_INFO "Turning Timer Off \n");
- status->imask &= ~INTR_ON_TIMER;
- }
-}
-
-/*====================================================================
- * Modem status interrupt handler.
- *===================================================================*/
-static void status_intr (sdla_t* card)
-{
-
- /* Added to avoid Modem status message flooding */
- static TX25ModemStatus last_stat;
-
- TX25Mbox* mbox = card->mbox;
- TX25ModemStatus *modem_status;
- struct net_device *dev;
- x25_channel_t *chan;
- int err;
-
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_READ_MODEM_STATUS;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err){
- x25_error(card, err, X25_READ_MODEM_STATUS, 0);
- }else{
-
- modem_status = (TX25ModemStatus*)mbox->data;
-
- /* Check if the last status was the same
- * if it was, do NOT print message again */
-
- if (last_stat.status != modem_status->status){
-
- printk(KERN_INFO "%s: Modem Status Change: DCD=%s, CTS=%s\n",
- card->devname,DCD(modem_status->status),CTS(modem_status->status));
-
- last_stat.status = modem_status->status;
-
- if (card->u.x.oob_on_modem){
-
- mbox->cmd.pktType = mbox->cmd.command;
- mbox->cmd.result = 0x08;
-
- /* Send a OOB to all connected sockets */
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device**)dev->priv)) {
- chan=dev->priv;
- if (chan->common.usedby == API){
- send_oob_msg(card,dev,mbox);
- }
- }
-
- /* The modem OOB message will probably kill the
- * the link. If we don't clear the flag here,
- * a deadlock could occur */
- if (atomic_read(&card->u.x.command_busy)){
- atomic_set(&card->u.x.command_busy,0);
- }
- }
- }
- }
-
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_LINK_STATUS;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err){
- x25_error(card, err, X25_HDLC_LINK_STATUS, 0);
- }
-
-}
-
-/*====================================================================
- * Network event interrupt handler.
- *===================================================================*/
-static void event_intr (sdla_t* card)
-{
- x25_fetch_events(card);
-}
-
-/*====================================================================
- * Spurious interrupt handler.
- * o print a warning
- * o
- *====================================================================*/
-
-static void spur_intr (sdla_t* card)
-{
- printk(KERN_INFO "%s: spurious interrupt!\n", card->devname);
-}
-
-
-/*
- * Background Polling Routines
- */
-
-/*====================================================================
- * Main polling routine.
- * This routine is repeatedly called by the WANPIPE 'thread' to allow for
- * time-dependent housekeeping work.
- *
- * Notes:
- * 1. This routine may be called on interrupt context with all interrupts
- * enabled. Beware!
- *====================================================================*/
-
-static void wpx_poll (sdla_t *card)
-{
- if (!card->wandev.dev){
- goto wpx_poll_exit;
- }
-
- if (card->open_cnt != card->u.x.num_of_ch){
- goto wpx_poll_exit;
- }
-
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- goto wpx_poll_exit;
- }
-
- if (test_bit(SEND_CRIT,&card->wandev.critical)){
- goto wpx_poll_exit;
- }
-
- switch(card->wandev.state){
- case WAN_CONNECTED:
- poll_active(card);
- break;
-
- case WAN_CONNECTING:
- poll_connecting(card);
- break;
-
- case WAN_DISCONNECTED:
- poll_disconnected(card);
- break;
- }
-
-wpx_poll_exit:
- clear_bit(POLL_CRIT,&card->wandev.critical);
- return;
-}
-
-static void trigger_x25_poll(sdla_t *card)
-{
- schedule_work(&card->u.x.x25_poll_work);
-}
-
-/*====================================================================
- * Handle physical link establishment phase.
- * o if connection timed out, disconnect the link.
- *===================================================================*/
-
-static void poll_connecting (sdla_t* card)
-{
- volatile TX25Status* status = card->flags;
-
- if (status->gflags & X25_HDLC_ABM){
-
- timer_intr_exec (card, TMR_INT_ENABLED_POLL_CONNECT_ON);
-
- }else if ((jiffies - card->state_tick) > CONNECT_TIMEOUT){
-
- timer_intr_exec (card, TMR_INT_ENABLED_POLL_CONNECT_OFF);
-
- }
-}
-
-/*====================================================================
- * Handle physical link disconnected phase.
- * o if hold-down timeout has expired and there are open interfaces,
- * connect link.
- *===================================================================*/
-
-static void poll_disconnected (sdla_t* card)
-{
- struct net_device *dev;
- x25_channel_t *chan;
- TX25Status* status = card->flags;
-
- if (!card->u.x.LAPB_hdlc && card->open_cnt &&
- ((jiffies - card->state_tick) > HOLD_DOWN_TIME)){
- timer_intr_exec(card, TMR_INT_ENABLED_POLL_DISCONNECT);
- }
-
-
- if ((dev=card->wandev.dev) == NULL)
- return;
-
- if ((chan=dev->priv) == NULL)
- return;
-
- if (chan->common.usedby == API &&
- atomic_read(&chan->common.command) &&
- card->u.x.LAPB_hdlc){
-
- if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC))
- card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC;
-
- if (!(status->imask & INTR_ON_TIMER))
- status->imask |= INTR_ON_TIMER;
- }
-
-}
-
-/*====================================================================
- * Handle active link phase.
- * o fetch X.25 asynchronous events.
- * o kick off transmission on all interfaces.
- *===================================================================*/
-
-static void poll_active (sdla_t* card)
-{
- struct net_device* dev;
- TX25Status* status = card->flags;
-
- for (dev = card->wandev.dev; dev;
- dev = *((struct net_device **)dev->priv)){
- x25_channel_t* chan = dev->priv;
-
- /* If SVC has been idle long enough, close virtual circuit */
- if ( chan->common.svc &&
- chan->common.state == WAN_CONNECTED &&
- chan->common.usedby == WANPIPE ){
-
- if( (jiffies - chan->i_timeout_sofar) / HZ > chan->idle_timeout ){
- /* Close svc */
- card->u.x.poll_device=dev;
- timer_intr_exec (card, TMR_INT_ENABLED_POLL_ACTIVE);
- }
- }
-
-#ifdef PRINT_DEBUG
- chan->ifstats.tx_compressed = atomic_read(&chan->common.command);
- chan->ifstats.tx_errors = chan->common.state;
- chan->ifstats.rx_fifo_errors = atomic_read(&card->u.x.command_busy);
- ++chan->ifstats.tx_bytes;
-
- chan->ifstats.rx_fifo_errors=atomic_read(&chan->common.disconnect);
- chan->ifstats.multicast=atomic_read(&chan->bh_buff_used);
- chan->ifstats.rx_length_errors=*card->u.x.hdlc_buf_status;
-#endif
-
- if (chan->common.usedby == API &&
- atomic_read(&chan->common.command) &&
- !card->u.x.LAPB_hdlc){
-
- if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC))
- card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC;
-
- if (!(status->imask & INTR_ON_TIMER))
- status->imask |= INTR_ON_TIMER;
- }
-
- if ((chan->common.usedby == API) &&
- atomic_read(&chan->common.disconnect)){
-
- if (chan->common.state == WAN_DISCONNECTED){
- atomic_set(&chan->common.disconnect,0);
- return;
- }
-
- atomic_set(&chan->common.command,X25_CLEAR_CALL);
- if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC))
- card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC;
-
- if (!(status->imask & INTR_ON_TIMER))
- status->imask |= INTR_ON_TIMER;
- }
- }
-}
-
-static void timer_intr_exec(sdla_t *card, unsigned char TYPE)
-{
- TX25Status* status = card->flags;
- card->u.x.timer_int_enabled |= TYPE;
- if (!(status->imask & INTR_ON_TIMER))
- status->imask |= INTR_ON_TIMER;
-}
-
-
-/*====================================================================
- * SDLA Firmware-Specific Functions
- *
- * Almost all X.25 commands can unexpetedly fail due to so called 'X.25
- * asynchronous events' such as restart, interrupt, incoming call request,
- * call clear request, etc. They can't be ignored and have to be delt with
- * immediately. To tackle with this problem we execute each interface
- * command in a loop until good return code is received or maximum number
- * of retries is reached. Each interface command returns non-zero return
- * code, an asynchronous event/error handler x25_error() is called.
- *====================================================================*/
-
-/*====================================================================
- * Read X.25 firmware version.
- * Put code version as ASCII string in str.
- *===================================================================*/
-
-static int x25_get_version (sdla_t* card, char* str)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_READ_CODE_VERSION;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- &&
- x25_error(card, err, X25_READ_CODE_VERSION, 0));
-
- if (!err && str)
- {
- int len = mbox->cmd.length;
-
- memcpy(str, mbox->data, len);
- str[len] = '\0';
- }
- return err;
-}
-
-/*====================================================================
- * Configure adapter.
- *===================================================================*/
-
-static int x25_configure (sdla_t* card, TX25Config* conf)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do{
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- memcpy(mbox->data, (void*)conf, sizeof(TX25Config));
- mbox->cmd.length = sizeof(TX25Config);
- mbox->cmd.command = X25_SET_CONFIGURATION;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_SET_CONFIGURATION, 0));
- return err;
-}
-
-/*====================================================================
- * Configure adapter for HDLC only.
- *===================================================================*/
-
-static int hdlc_configure (sdla_t* card, TX25Config* conf)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do{
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- memcpy(mbox->data, (void*)conf, sizeof(TX25Config));
- mbox->cmd.length = sizeof(TX25Config);
- mbox->cmd.command = X25_HDLC_SET_CONFIG;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_SET_CONFIGURATION, 0));
-
- return err;
-}
-
-static int set_hdlc_level (sdla_t* card)
-{
-
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do{
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = SET_PROTOCOL_LEVEL;
- mbox->cmd.length = 1;
- mbox->data[0] = HDLC_LEVEL; //| DO_HDLC_LEVEL_ERROR_CHECKING;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, SET_PROTOCOL_LEVEL, 0));
-
- return err;
-}
-
-
-
-/*====================================================================
- * Get communications error statistics.
- *====================================================================*/
-
-static int x25_get_err_stats (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_READ_COMM_ERR;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_HDLC_READ_COMM_ERR, 0));
-
- if (!err)
- {
- THdlcCommErr* stats = (void*)mbox->data;
-
- card->wandev.stats.rx_over_errors = stats->rxOverrun;
- card->wandev.stats.rx_crc_errors = stats->rxBadCrc;
- card->wandev.stats.rx_missed_errors = stats->rxAborted;
- card->wandev.stats.tx_aborted_errors = stats->txAborted;
- }
- return err;
-}
-
-/*====================================================================
- * Get protocol statistics.
- *===================================================================*/
-
-static int x25_get_stats (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_READ_STATISTICS;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_READ_STATISTICS, 0)) ;
-
- if (!err)
- {
- TX25Stats* stats = (void*)mbox->data;
-
- card->wandev.stats.rx_packets = stats->rxData;
- card->wandev.stats.tx_packets = stats->txData;
- }
- return err;
-}
-
-/*====================================================================
- * Close HDLC link.
- *===================================================================*/
-
-static int x25_close_hdlc (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_LINK_CLOSE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_CLOSE, 0));
-
- return err;
-}
-
-
-/*====================================================================
- * Open HDLC link.
- *===================================================================*/
-
-static int x25_open_hdlc (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_LINK_OPEN;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_OPEN, 0));
-
- return err;
-}
-
-/*=====================================================================
- * Setup HDLC link.
- *====================================================================*/
-static int x25_setup_hdlc (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_LINK_SETUP;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_SETUP, 0));
-
- return err;
-}
-
-/*====================================================================
- * Set (raise/drop) DTR.
- *===================================================================*/
-
-static int x25_set_dtr (sdla_t* card, int dtr)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->data[0] = 0;
- mbox->data[2] = 0;
- mbox->data[1] = dtr ? 0x02 : 0x01;
- mbox->cmd.length = 3;
- mbox->cmd.command = X25_SET_GLOBAL_VARS;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_SET_GLOBAL_VARS, 0));
-
- return err;
-}
-
-/*====================================================================
- * Set interrupt mode.
- *===================================================================*/
-
-static int x25_set_intr_mode (sdla_t* card, int mode)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->data[0] = mode;
- if (card->hw.fwid == SFID_X25_508){
- mbox->data[1] = card->hw.irq;
- mbox->data[2] = 2;
- mbox->cmd.length = 3;
- }else {
- mbox->cmd.length = 1;
- }
- mbox->cmd.command = X25_SET_INTERRUPT_MODE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_SET_INTERRUPT_MODE, 0));
-
- return err;
-}
-
-/*====================================================================
- * Read X.25 channel configuration.
- *===================================================================*/
-
-static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int lcn = chan->common.lcn;
- int err;
-
- do{
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.lcn = lcn;
- mbox->cmd.command = X25_READ_CHANNEL_CONFIG;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_READ_CHANNEL_CONFIG, lcn));
-
- if (!err)
- {
- TX25Status* status = card->flags;
-
- /* calculate an offset into the array of status bytes */
- if (card->u.x.hi_svc <= X25_MAX_CHAN){
-
- chan->ch_idx = lcn - 1;
-
- }else{
- int offset;
-
- /* FIX: Apr 14 2000 : Nenad Corbic
- * The data field was being compared to 0x1F using
- * '&&' instead of '&'.
- * This caused X25API to fail for LCNs greater than 255.
- */
- switch (mbox->data[0] & 0x1F)
- {
- case 0x01:
- offset = status->pvc_map; break;
- case 0x03:
- offset = status->icc_map; break;
- case 0x07:
- offset = status->twc_map; break;
- case 0x0B:
- offset = status->ogc_map; break;
- default:
- offset = 0;
- }
- chan->ch_idx = lcn - 1 - offset;
- }
-
- /* get actual transmit packet size on this channel */
- switch(mbox->data[1] & 0x38)
- {
- case 0x00:
- chan->tx_pkt_size = 16;
- break;
- case 0x08:
- chan->tx_pkt_size = 32;
- break;
- case 0x10:
- chan->tx_pkt_size = 64;
- break;
- case 0x18:
- chan->tx_pkt_size = 128;
- break;
- case 0x20:
- chan->tx_pkt_size = 256;
- break;
- case 0x28:
- chan->tx_pkt_size = 512;
- break;
- case 0x30:
- chan->tx_pkt_size = 1024;
- break;
- }
- if (card->u.x.logging)
- printk(KERN_INFO "%s: X.25 packet size on LCN %d is %d.\n",
- card->devname, lcn, chan->tx_pkt_size);
- }
- return err;
-}
-
-/*====================================================================
- * Place X.25 call.
- *====================================================================*/
-
-static int x25_place_call (sdla_t* card, x25_channel_t* chan)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
- char str[64];
-
-
- if (chan->protocol == htons(ETH_P_IP)){
- sprintf(str, "-d%s -uCC", chan->addr);
-
- }else if (chan->protocol == htons(ETH_P_IPX)){
- sprintf(str, "-d%s -u800000008137", chan->addr);
-
- }
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- strcpy(mbox->data, str);
- mbox->cmd.length = strlen(str);
- mbox->cmd.command = X25_PLACE_CALL;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_PLACE_CALL, 0));
-
- if (!err){
- bind_lcn_to_dev (card, chan->dev, mbox->cmd.lcn);
- }
- return err;
-}
-
-/*====================================================================
- * Accept X.25 call.
- *====================================================================*/
-
-static int x25_accept_call (sdla_t* card, int lcn, int qdm)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.lcn = lcn;
- mbox->cmd.qdm = qdm;
- mbox->cmd.command = X25_ACCEPT_CALL;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_ACCEPT_CALL, lcn));
-
- return err;
-}
-
-/*====================================================================
- * Clear X.25 call.
- *====================================================================*/
-
-static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.lcn = lcn;
- mbox->cmd.cause = cause;
- mbox->cmd.diagn = diagn;
- mbox->cmd.command = X25_CLEAR_CALL;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_CLEAR_CALL, lcn));
-
- return err;
-}
-
-/*====================================================================
- * Send X.25 data packet.
- *====================================================================*/
-
-static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
- unsigned char cmd;
-
- if (card->u.x.LAPB_hdlc)
- cmd = X25_HDLC_WRITE;
- else
- cmd = X25_WRITE;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- memcpy(mbox->data, buf, len);
- mbox->cmd.length = len;
- mbox->cmd.lcn = lcn;
-
- if (card->u.x.LAPB_hdlc){
- mbox->cmd.pf = qdm;
- }else{
- mbox->cmd.qdm = qdm;
- }
-
- mbox->cmd.command = cmd;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, cmd , lcn));
-
-
- /* If buffers are busy the return code for LAPB HDLC is
- * 1. The above functions are looking for return code
- * of X25RES_NOT_READY if busy. */
-
- if (card->u.x.LAPB_hdlc && err == 1){
- err = X25RES_NOT_READY;
- }
-
- return err;
-}
-
-/*====================================================================
- * Fetch X.25 asynchronous events.
- *===================================================================*/
-
-static int x25_fetch_events (sdla_t* card)
-{
- TX25Status* status = card->flags;
- TX25Mbox* mbox = card->mbox;
- int err = 0;
-
- if (status->gflags & 0x20)
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_IS_DATA_AVAILABLE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err) x25_error(card, err, X25_IS_DATA_AVAILABLE, 0);
- }
- return err;
-}
-
-/*====================================================================
- * X.25 asynchronous event/error handler.
- * This routine is called each time interface command returns
- * non-zero return code to handle X.25 asynchronous events and
- * common errors. Return non-zero to repeat command or zero to
- * cancel it.
- *
- * Notes:
- * 1. This function may be called recursively, as handling some of the
- * asynchronous events (e.g. call request) requires execution of the
- * interface command(s) that, in turn, may also return asynchronous
- * events. To avoid re-entrancy problems we copy mailbox to dynamically
- * allocated memory before processing events.
- *====================================================================*/
-
-static int x25_error (sdla_t* card, int err, int cmd, int lcn)
-{
- int retry = 1;
- unsigned dlen = ((TX25Mbox*)card->mbox)->cmd.length;
- TX25Mbox* mb;
-
- mb = kmalloc(sizeof(TX25Mbox) + dlen, GFP_ATOMIC);
- if (mb == NULL)
- {
- printk(KERN_ERR "%s: x25_error() out of memory!\n",
- card->devname);
- return 0;
- }
- memcpy(mb, card->mbox, sizeof(TX25Mbox) + dlen);
- switch (err){
-
- case X25RES_ASYNC_PACKET: /* X.25 asynchronous packet was received */
-
- mb->data[dlen] = '\0';
-
- switch (mb->cmd.pktType & 0x7F){
-
- case ASE_CALL_RQST: /* incoming call */
- retry = incoming_call(card, cmd, lcn, mb);
- break;
-
- case ASE_CALL_ACCEPTED: /* connected */
- retry = call_accepted(card, cmd, lcn, mb);
- break;
-
- case ASE_CLEAR_RQST: /* call clear request */
- retry = call_cleared(card, cmd, lcn, mb);
- break;
-
- case ASE_RESET_RQST: /* reset request */
- printk(KERN_INFO "%s: X.25 reset request on LCN %d! "
- "Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.lcn, mb->cmd.cause,
- mb->cmd.diagn);
- api_oob_event (card,mb);
- break;
-
- case ASE_RESTART_RQST: /* restart request */
- retry = restart_event(card, cmd, lcn, mb);
- break;
-
- case ASE_CLEAR_CONFRM:
- if (clear_confirm_event (card,mb))
- break;
-
- /* I use the goto statement here so if
- * somebody inserts code between the
- * case and default, we will not have
- * ghost problems */
-
- goto dflt_1;
-
- default:
-dflt_1:
- printk(KERN_INFO "%s: X.25 event 0x%02X on LCN %d! "
- "Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.pktType,
- mb->cmd.lcn, mb->cmd.cause, mb->cmd.diagn);
- }
- break;
-
- case X25RES_PROTO_VIOLATION: /* X.25 protocol violation indication */
-
- /* Bug Fix: Mar 14 2000
- * The Protocol violation error conditions were
- * not handled previously */
-
- switch (mb->cmd.pktType & 0x7F){
-
- case PVE_CLEAR_RQST: /* Clear request */
- retry = call_cleared(card, cmd, lcn, mb);
- break;
-
- case PVE_RESET_RQST: /* Reset request */
- printk(KERN_INFO "%s: X.25 reset request on LCN %d! "
- "Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.lcn, mb->cmd.cause,
- mb->cmd.diagn);
- api_oob_event (card,mb);
- break;
-
- case PVE_RESTART_RQST: /* Restart request */
- retry = restart_event(card, cmd, lcn, mb);
- break;
-
- default :
- printk(KERN_INFO
- "%s: X.25 protocol violation on LCN %d! "
- "Packet:0x%02X Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.lcn,
- mb->cmd.pktType & 0x7F, mb->cmd.cause, mb->cmd.diagn);
- api_oob_event(card,mb);
- }
- break;
-
- case 0x42: /* X.25 timeout */
- retry = timeout_event(card, cmd, lcn, mb);
- break;
-
- case 0x43: /* X.25 retry limit exceeded */
- printk(KERN_INFO
- "%s: exceeded X.25 retry limit on LCN %d! "
- "Packet:0x%02X Diagn:0x%02X\n", card->devname,
- mb->cmd.lcn, mb->cmd.pktType, mb->cmd.diagn)
- ;
- break;
-
- case 0x08: /* modem failure */
-#ifndef MODEM_NOT_LOG
- printk(KERN_INFO "%s: modem failure!\n", card->devname);
-#endif /* MODEM_NOT_LOG */
- api_oob_event(card,mb);
- break;
-
- case 0x09: /* N2 retry limit */
- printk(KERN_INFO "%s: exceeded HDLC retry limit!\n",
- card->devname);
- api_oob_event(card,mb);
- break;
-
- case 0x06: /* unnumbered frame was received while in ABM */
- printk(KERN_INFO "%s: received Unnumbered frame 0x%02X!\n",
- card->devname, mb->data[0]);
- api_oob_event(card,mb);
- break;
-
- case CMD_TIMEOUT:
- printk(KERN_ERR "%s: command 0x%02X timed out!\n",
- card->devname, cmd)
- ;
- retry = 0; /* abort command */
- break;
-
- case X25RES_NOT_READY:
- retry = 1;
- break;
-
- case 0x01:
- if (card->u.x.LAPB_hdlc)
- break;
-
- if (mb->cmd.command == 0x16)
- break;
- /* I use the goto statement here so if
- * somebody inserts code between the
- * case and default, we will not have
- * ghost problems */
- goto dflt_2;
-
- default:
-dflt_2:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X! Lcn %i\n",
- card->devname, cmd, err, mb->cmd.lcn)
- ;
- retry = 0; /* abort command */
- }
- kfree(mb);
- return retry;
-}
-
-/*====================================================================
- * X.25 Asynchronous Event Handlers
- * These functions are called by the x25_error() and should return 0, if
- * the command resulting in the asynchronous event must be aborted.
- *====================================================================*/
-
-
-
-/*====================================================================
- *Handle X.25 incoming call request.
- * RFC 1356 establishes the following rules:
- * 1. The first octet in the Call User Data (CUD) field of the call
- * request packet contains NLPID identifying protocol encapsulation
- * 2. Calls MUST NOT be accepted unless router supports requested
- * protocol encapsulation.
- * 3. A diagnostic code 249 defined by ISO/IEC 8208 may be used
- * when clearing a call because protocol encapsulation is not
- * supported.
- * 4. If an incoming call is received while a call request is
- * pending (i.e. call collision has occurred), the incoming call
- * shall be rejected and call request shall be retried.
- *====================================================================*/
-
-static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- struct wan_device* wandev = &card->wandev;
- int new_lcn = mb->cmd.lcn;
- struct net_device* dev = get_dev_by_lcn(wandev, new_lcn);
- x25_channel_t* chan = NULL;
- int accept = 0; /* set to '1' if o.k. to accept call */
- unsigned int user_data;
- x25_call_info_t* info;
-
- /* Make sure there is no call collision */
- if (dev != NULL)
- {
- printk(KERN_INFO
- "%s: X.25 incoming call collision on LCN %d!\n",
- card->devname, new_lcn);
-
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
-
- /* Make sure D bit is not set in call request */
-//FIXME: THIS IS NOT TURE !!!! TAKE IT OUT
-// if (mb->cmd.qdm & 0x02)
-// {
-// printk(KERN_INFO
-// "%s: X.25 incoming call on LCN %d with D-bit set!\n",
-// card->devname, new_lcn);
-//
-// x25_clear_call(card, new_lcn, 0, 0);
-// return 1;
-// }
-
- /* Parse call request data */
- info = kmalloc(sizeof(x25_call_info_t), GFP_ATOMIC);
- if (info == NULL)
- {
- printk(KERN_ERR
- "%s: not enough memory to parse X.25 incoming call "
- "on LCN %d!\n", card->devname, new_lcn);
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
-
- parse_call_info(mb->data, info);
-
- if (card->u.x.logging)
- printk(KERN_INFO "\n%s: X.25 incoming call on LCN %d!\n",
- card->devname, new_lcn);
-
- /* Conver the first two ASCII characters into an
- * interger. Used to check the incoming protocol
- */
- user_data = hex_to_uint(info->user,2);
-
- /* Find available channel */
- for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv)) {
- chan = dev->priv;
-
- if (chan->common.usedby == API)
- continue;
-
- if (!chan->common.svc || (chan->common.state != WAN_DISCONNECTED))
- continue;
-
- if (user_data == NLPID_IP && chan->protocol != htons(ETH_P_IP)){
- printk(KERN_INFO "IP packet but configured for IPX : %x, %x\n",
- htons(chan->protocol), info->user[0]);
- continue;
- }
-
- if (user_data == NLPID_SNAP && chan->protocol != htons(ETH_P_IPX)){
- printk(KERN_INFO "IPX packet but configured for IP: %x\n",
- htons(chan->protocol));
- continue;
- }
- if (strcmp(info->src, chan->addr) == 0)
- break;
-
- /* If just an '@' is specified, accept all incoming calls */
- if (strcmp(chan->addr, "") == 0)
- break;
- }
-
- if (dev == NULL){
-
- /* If the call is not for any WANPIPE interfaces
- * check to see if there is an API listening queue
- * waiting for data. If there is send the packet
- * up the stack.
- */
- if (card->sk != NULL && card->func != NULL){
- if (api_incoming_call(card,mb,new_lcn)){
- x25_clear_call(card, new_lcn, 0, 0);
- }
- accept = 0;
- }else{
- printk(KERN_INFO "%s: no channels available!\n",
- card->devname);
-
- x25_clear_call(card, new_lcn, 0, 0);
- }
-
- }else if (info->nuser == 0){
-
- printk(KERN_INFO
- "%s: no user data in incoming call on LCN %d!\n",
- card->devname, new_lcn)
- ;
- x25_clear_call(card, new_lcn, 0, 0);
-
- }else switch (info->user[0]){
-
- case 0: /* multiplexed */
- chan->protocol = htons(0);
- accept = 1;
- break;
-
- case NLPID_IP: /* IP datagrams */
- accept = 1;
- break;
-
- case NLPID_SNAP: /* IPX datagrams */
- accept = 1;
- break;
-
- default:
- printk(KERN_INFO
- "%s: unsupported NLPID 0x%02X in incoming call "
- "on LCN %d!\n", card->devname, info->user[0], new_lcn);
- x25_clear_call(card, new_lcn, 0, 249);
- }
-
- if (accept && (x25_accept_call(card, new_lcn, 0) == CMD_OK)){
-
- bind_lcn_to_dev (card, chan->dev, new_lcn);
-
- if (x25_get_chan_conf(card, chan) == CMD_OK)
- set_chan_state(dev, WAN_CONNECTED);
- else
- x25_clear_call(card, new_lcn, 0, 0);
- }
- kfree(info);
- return 1;
-}
-
-/*====================================================================
- * Handle accepted call.
- *====================================================================*/
-
-static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- unsigned new_lcn = mb->cmd.lcn;
- struct net_device* dev = find_channel(card, new_lcn);
- x25_channel_t* chan;
-
- if (dev == NULL){
- printk(KERN_INFO
- "%s: clearing orphaned connection on LCN %d!\n",
- card->devname, new_lcn);
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
-
- if (card->u.x.logging)
- printk(KERN_INFO "%s: X.25 call accepted on Dev %s and LCN %d!\n",
- card->devname, dev->name, new_lcn);
-
- /* Get channel configuration and notify router */
- chan = dev->priv;
- if (x25_get_chan_conf(card, chan) != CMD_OK)
- {
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
-
- set_chan_state(dev, WAN_CONNECTED);
-
- if (chan->common.usedby == API){
- send_delayed_cmd_result(card,dev,mb);
- bind_lcn_to_dev (card, dev, new_lcn);
- }
-
- return 1;
-}
-
-/*====================================================================
- * Handle cleared call.
- *====================================================================*/
-
-static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- unsigned new_lcn = mb->cmd.lcn;
- struct net_device* dev = find_channel(card, new_lcn);
- x25_channel_t *chan;
- unsigned char old_state;
-
- if (card->u.x.logging){
- printk(KERN_INFO "%s: X.25 clear request on LCN %d! Cause:0x%02X "
- "Diagn:0x%02X\n",
- card->devname, new_lcn, mb->cmd.cause, mb->cmd.diagn);
- }
-
- if (dev == NULL){
- printk(KERN_INFO "%s: X.25 clear request : No device for clear\n",
- card->devname);
- return 1;
- }
-
- chan=dev->priv;
-
- old_state = chan->common.state;
-
- set_chan_state(dev, WAN_DISCONNECTED);
-
- if (chan->common.usedby == API){
-
- switch (old_state){
-
- case WAN_CONNECTING:
- send_delayed_cmd_result(card,dev,mb);
- break;
- case WAN_CONNECTED:
- send_oob_msg(card,dev,mb);
- break;
- }
- }
-
- return ((cmd == X25_WRITE) && (lcn == new_lcn)) ? 0 : 1;
-}
-
-/*====================================================================
- * Handle X.25 restart event.
- *====================================================================*/
-
-static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- struct wan_device* wandev = &card->wandev;
- struct net_device* dev;
- x25_channel_t *chan;
- unsigned char old_state;
-
- printk(KERN_INFO
- "%s: X.25 restart request! Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.cause, mb->cmd.diagn);
-
- /* down all logical channels */
- for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv)) {
- chan=dev->priv;
- old_state = chan->common.state;
-
- set_chan_state(dev, WAN_DISCONNECTED);
-
- if (chan->common.usedby == API){
- switch (old_state){
-
- case WAN_CONNECTING:
- send_delayed_cmd_result(card,dev,mb);
- break;
- case WAN_CONNECTED:
- send_oob_msg(card,dev,mb);
- break;
- }
- }
- }
- return (cmd == X25_WRITE) ? 0 : 1;
-}
-
-/*====================================================================
- * Handle timeout event.
- *====================================================================*/
-
-static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- unsigned new_lcn = mb->cmd.lcn;
-
- if (mb->cmd.pktType == 0x05) /* call request time out */
- {
- struct net_device* dev = find_channel(card,new_lcn);
-
- printk(KERN_INFO "%s: X.25 call timed timeout on LCN %d!\n",
- card->devname, new_lcn);
-
- if (dev){
- x25_channel_t *chan = dev->priv;
- set_chan_state(dev, WAN_DISCONNECTED);
-
- if (chan->common.usedby == API){
- send_delayed_cmd_result(card,dev,card->mbox);
- }
- }
- }else{
- printk(KERN_INFO "%s: X.25 packet 0x%02X timeout on LCN %d!\n",
- card->devname, mb->cmd.pktType, new_lcn);
- }
- return 1;
-}
-
-/*
- * Miscellaneous
- */
-
-/*====================================================================
- * Establish physical connection.
- * o open HDLC and raise DTR
- *
- * Return: 0 connection established
- * 1 connection is in progress
- * <0 error
- *===================================================================*/
-
-static int connect (sdla_t* card)
-{
- TX25Status* status = card->flags;
-
- if (x25_open_hdlc(card) || x25_setup_hdlc(card))
- return -EIO;
-
- wanpipe_set_state(card, WAN_CONNECTING);
-
- x25_set_intr_mode(card, INTR_ON_TIMER);
- status->imask &= ~INTR_ON_TIMER;
-
- return 1;
-}
-
-/*
- * Tear down physical connection.
- * o close HDLC link
- * o drop DTR
- *
- * Return: 0
- * <0 error
- */
-
-static int disconnect (sdla_t* card)
-{
- wanpipe_set_state(card, WAN_DISCONNECTED);
- x25_set_intr_mode(card, INTR_ON_TIMER); /* disable all interrupt except timer */
- x25_close_hdlc(card); /* close HDLC link */
- x25_set_dtr(card, 0); /* drop DTR */
- return 0;
-}
-
-/*
- * Find network device by its channel number.
- */
-
-static struct net_device* get_dev_by_lcn(struct wan_device* wandev,
- unsigned lcn)
-{
- struct net_device* dev;
-
- for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv))
- if (((x25_channel_t*)dev->priv)->common.lcn == lcn)
- break;
- return dev;
-}
-
-/*
- * Initiate connection on the logical channel.
- * o for PVC we just get channel configuration
- * o for SVCs place an X.25 call
- *
- * Return: 0 connected
- * >0 connection in progress
- * <0 failure
- */
-
-static int chan_connect(struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- if (chan->common.svc && chan->common.usedby == WANPIPE){
- if (!chan->addr[0]){
- printk(KERN_INFO "%s: No Destination Address\n",
- card->devname);
- return -EINVAL; /* no destination address */
- }
- printk(KERN_INFO "%s: placing X.25 call to %s ...\n",
- card->devname, chan->addr);
-
- if (x25_place_call(card, chan) != CMD_OK)
- return -EIO;
-
- set_chan_state(dev, WAN_CONNECTING);
- return 1;
- }else{
- if (x25_get_chan_conf(card, chan) != CMD_OK)
- return -EIO;
-
- set_chan_state(dev, WAN_CONNECTED);
- }
- return 0;
-}
-
-/*
- * Disconnect logical channel.
- * o if SVC then clear X.25 call
- */
-
-static int chan_disc(struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
-
- if (chan->common.svc){
- x25_clear_call(chan->card, chan->common.lcn, 0, 0);
-
- /* For API we disconnect on clear
- * confirmation.
- */
- if (chan->common.usedby == API)
- return 0;
- }
-
- set_chan_state(dev, WAN_DISCONNECTED);
-
- return 0;
-}
-
-/*
- * Set logical channel state.
- */
-
-static void set_chan_state(struct net_device* dev, int state)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- if (chan->common.state != state)
- {
- switch (state)
- {
- case WAN_CONNECTED:
- if (card->u.x.logging){
- printk (KERN_INFO
- "%s: interface %s connected, lcn %i !\n",
- card->devname, dev->name,chan->common.lcn);
- }
- *(unsigned short*)dev->dev_addr = htons(chan->common.lcn);
- chan->i_timeout_sofar = jiffies;
-
- /* LAPB is PVC Based */
- if (card->u.x.LAPB_hdlc)
- chan->common.svc=0;
- break;
-
- case WAN_CONNECTING:
- if (card->u.x.logging){
- printk (KERN_INFO
- "%s: interface %s connecting, lcn %i ...\n",
- card->devname, dev->name, chan->common.lcn);
- }
- break;
-
- case WAN_DISCONNECTED:
- if (card->u.x.logging){
- printk (KERN_INFO
- "%s: interface %s disconnected, lcn %i !\n",
- card->devname, dev->name,chan->common.lcn);
- }
- atomic_set(&chan->common.disconnect,0);
-
- if (chan->common.svc) {
- *(unsigned short*)dev->dev_addr = 0;
- card->u.x.svc_to_dev_map[(chan->common.lcn%X25_MAX_CHAN)]=NULL;
- chan->common.lcn = 0;
- }
-
- if (chan->transmit_length){
- chan->transmit_length=0;
- atomic_set(&chan->common.driver_busy,0);
- chan->tx_offset=0;
- if (netif_queue_stopped(dev)){
- netif_wake_queue(dev);
- }
- }
- atomic_set(&chan->common.command,0);
- break;
-
- case WAN_DISCONNECTING:
- if (card->u.x.logging){
- printk (KERN_INFO
- "\n%s: interface %s disconnecting, lcn %i ...\n",
- card->devname, dev->name,chan->common.lcn);
- }
- atomic_set(&chan->common.disconnect,0);
- break;
- }
- chan->common.state = state;
- }
- chan->state_tick = jiffies;
- restore_flags(flags);
-}
-
-/*
- * Send packet on a logical channel.
- * When this function is called, tx_skb field of the channel data
- * space points to the transmit socket buffer. When transmission
- * is complete, release socket buffer and reset 'tbusy' flag.
- *
- * Return: 0 - transmission complete
- * 1 - busy
- *
- * Notes:
- * 1. If packet length is greater than MTU for this channel, we'll fragment
- * the packet into 'complete sequence' using M-bit.
- * 2. When transmission is complete, an event notification should be issued
- * to the router.
- */
-
-static int chan_send(struct net_device* dev, void* buff, unsigned data_len,
- unsigned char tx_intr)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- TX25Status* status = card->flags;
- unsigned len=0, qdm=0, res=0, orig_len = 0;
- void *data;
-
- /* Check to see if channel is ready */
- if ((!(status->cflags[chan->ch_idx] & 0x40) && !card->u.x.LAPB_hdlc) ||
- !(*card->u.x.hdlc_buf_status & 0x40)){
-
- if (!tx_intr){
- setup_for_delayed_transmit (dev, buff, data_len);
- return 0;
- }else{
- /* By returning 0 to tx_intr the packet will be dropped */
- ++card->wandev.stats.tx_dropped;
- ++chan->ifstats.tx_dropped;
- printk(KERN_INFO "%s: ERROR, Tx intr could not send, dropping %s:\n",
- card->devname,dev->name);
- ++chan->if_send_stat.if_send_bfr_not_passed_to_adptr;
- return 0;
- }
- }
-
- if (chan->common.usedby == API){
- /* Remove the API Header */
- x25api_hdr_t *api_data = (x25api_hdr_t *)buff;
-
- /* Set the qdm bits from the packet header
- * User has the option to set the qdm bits
- */
- qdm = api_data->qdm;
-
- orig_len = len = data_len - sizeof(x25api_hdr_t);
- data = (unsigned char*)buff + sizeof(x25api_hdr_t);
- }else{
- data = buff;
- orig_len = len = data_len;
- }
-
- if (tx_intr){
- /* We are in tx_intr, minus the tx_offset from
- * the total length. The tx_offset part of the
- * data has already been sent. Also, move the
- * data pointer to proper offset location.
- */
- len -= chan->tx_offset;
- data = (unsigned char*)data + chan->tx_offset;
- }
-
- /* Check if the packet length is greater than MTU
- * If YES: Cut the len to MTU and set the M bit
- */
- if (len > chan->tx_pkt_size && !card->u.x.LAPB_hdlc){
- len = chan->tx_pkt_size;
- qdm |= M_BIT;
- }
-
-
- /* Pass only first three bits of the qdm byte to the send
- * routine. In case user sets any other bit which might
- * cause errors.
- */
-
- switch(x25_send(card, chan->common.lcn, (qdm&0x07), len, data)){
- case 0x00: /* success */
- chan->i_timeout_sofar = jiffies;
-
- dev->trans_start=jiffies;
-
- if ((qdm & M_BIT) && !card->u.x.LAPB_hdlc){
- if (!tx_intr){
- /* The M bit was set, which means that part of the
- * packet has been sent. Copy the packet into a buffer
- * and set the offset to len, so on next tx_inter
- * the packet will be sent using the below offset.
- */
- chan->tx_offset += len;
-
- ++chan->ifstats.tx_packets;
- chan->ifstats.tx_bytes += len;
-
- if (chan->tx_offset < orig_len){
- setup_for_delayed_transmit (dev, buff, data_len);
- }
- res=0;
- }else{
- /* We are already in tx_inter, thus data is already
- * in the buffer. Update the offset and wait for
- * next tx_intr. We add on to the offset, since data can
- * be X number of times larger than max data size.
- */
- ++chan->ifstats.tx_packets;
- chan->ifstats.tx_bytes += len;
-
- ++chan->if_send_stat.if_send_bfr_passed_to_adptr;
- chan->tx_offset += len;
-
- /* The user can set the qdm bit as well.
- * If the entire packet was sent and qdm is still
- * set, than it's the user who has set the M bit. In that,
- * case indicate that the packet was send by returning
- * 0 and wait for a new packet. Otherwise, wait for next
- * tx interrupt to send the rest of the packet */
-
- if (chan->tx_offset < orig_len){
- res=1;
- }else{
- res=0;
- }
- }
- }else{
- ++chan->ifstats.tx_packets;
- chan->ifstats.tx_bytes += len;
- ++chan->if_send_stat.if_send_bfr_passed_to_adptr;
- res=0;
- }
- break;
-
- case 0x33: /* Tx busy */
- if (tx_intr){
- printk(KERN_INFO "%s: Tx_intr: Big Error dropping packet %s\n",
- card->devname,dev->name);
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- ++chan->if_send_stat.if_send_bfr_not_passed_to_adptr;
- res=0;
- }else{
- DBG_PRINTK(KERN_INFO
- "%s: Send: Big Error should have tx: storring %s\n",
- card->devname,dev->name);
- setup_for_delayed_transmit (dev, buff, data_len);
- res=1;
- }
- break;
-
- default: /* failure */
- ++chan->ifstats.tx_errors;
- if (tx_intr){
- printk(KERN_INFO "%s: Tx_intr: Failure to send, dropping %s\n",
- card->devname,dev->name);
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- ++chan->if_send_stat.if_send_bfr_not_passed_to_adptr;
- res=0;
- }else{
- DBG_PRINTK(KERN_INFO "%s: Send: Failure to send !!!, storing %s\n",
- card->devname,dev->name);
- setup_for_delayed_transmit (dev, buff, data_len);
- res=1;
- }
- break;
- }
- return res;
-}
-
-
-/*
- * Parse X.25 call request data and fill x25_call_info_t structure.
- */
-
-static void parse_call_info (unsigned char* str, x25_call_info_t* info)
-{
- memset(info, 0, sizeof(x25_call_info_t));
- for (; *str; ++str)
- {
- int i;
- unsigned char ch;
-
- if (*str == '-') switch (str[1]) {
-
- /* Take minus 2 off the maximum size so that
- * last byte is 0. This way we can use string
- * manipulaton functions on call information.
- */
-
- case 'd': /* destination address */
- for (i = 0; i < (MAX_X25_ADDR_SIZE-2); ++i){
- ch = str[2+i];
- if (isspace(ch)) break;
- info->dest[i] = ch;
- }
- break;
-
- case 's': /* source address */
- for (i = 0; i < (MAX_X25_ADDR_SIZE-2); ++i){
- ch = str[2+i];
- if (isspace(ch)) break;
- info->src[i] = ch;
- }
- break;
-
- case 'u': /* user data */
- for (i = 0; i < (MAX_X25_DATA_SIZE-2); ++i){
- ch = str[2+i];
- if (isspace(ch)) break;
- info->user[i] = ch;
- }
- info->nuser = i;
- break;
-
- case 'f': /* facilities */
- for (i = 0; i < (MAX_X25_FACL_SIZE-2); ++i){
- ch = str[2+i];
- if (isspace(ch)) break;
- info->facil[i] = ch;
- }
- info->nfacil = i;
- break;
- }
- }
-}
-
-/*
- * Convert line speed in bps to a number used by S502 code.
- */
-
-static unsigned char bps_to_speed_code (unsigned long bps)
-{
- unsigned char number;
-
- if (bps <= 1200) number = 0x01;
- else if (bps <= 2400) number = 0x02;
- else if (bps <= 4800) number = 0x03;
- else if (bps <= 9600) number = 0x04;
- else if (bps <= 19200) number = 0x05;
- else if (bps <= 38400) number = 0x06;
- else if (bps <= 45000) number = 0x07;
- else if (bps <= 56000) number = 0x08;
- else if (bps <= 64000) number = 0x09;
- else if (bps <= 74000) number = 0x0A;
- else if (bps <= 112000) number = 0x0B;
- else if (bps <= 128000) number = 0x0C;
- else number = 0x0D;
-
- return number;
-}
-
-/*
- * Convert decimal string to unsigned integer.
- * If len != 0 then only 'len' characters of the string are converted.
- */
-
-static unsigned int dec_to_uint (unsigned char* str, int len)
-{
- unsigned val;
-
- if (!len)
- len = strlen(str);
-
- for (val = 0; len && isdigit(*str); ++str, --len)
- val = (val * 10) + (*str - (unsigned)'0');
-
- return val;
-}
-
-/*
- * Convert hex string to unsigned integer.
- * If len != 0 then only 'len' characters of the string are conferted.
- */
-
-static unsigned int hex_to_uint (unsigned char* str, int len)
-{
- unsigned val, ch;
-
- if (!len)
- len = strlen(str);
-
- for (val = 0; len; ++str, --len)
- {
- ch = *str;
- if (isdigit(ch))
- val = (val << 4) + (ch - (unsigned)'0');
- else if (isxdigit(ch))
- val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10);
- else break;
- }
- return val;
-}
-
-
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto)
-{
- int i;
-
- if( proto == ETH_P_IPX) {
- /* It's an IPX packet */
- if(!enable_IPX) {
- /* Return 1 so we don't pass it up the stack. */
- return 1;
- }
- } else {
- /* It's not IPX so pass it up the stack.*/
- return 0;
- }
-
- if( sendpacket[16] == 0x90 &&
- sendpacket[17] == 0x04)
- {
- /* It's IPXWAN */
-
- if( sendpacket[2] == 0x02 &&
- sendpacket[34] == 0x00)
- {
- /* It's a timer request packet */
- printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname);
-
- /* Go through the routing options and answer no to every
- * option except Unnumbered RIP/SAP
- */
- for(i = 41; sendpacket[i] == 0x00; i += 5)
- {
- /* 0x02 is the option for Unnumbered RIP/SAP */
- if( sendpacket[i + 4] != 0x02)
- {
- sendpacket[i + 1] = 0;
- }
- }
-
- /* Skip over the extended Node ID option */
- if( sendpacket[i] == 0x04 )
- {
- i += 8;
- }
-
- /* We also want to turn off all header compression opt. */
- for(; sendpacket[i] == 0x80 ;)
- {
- sendpacket[i + 1] = 0;
- i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4;
- }
-
- /* Set the packet type to timer response */
- sendpacket[34] = 0x01;
-
- printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname);
- }
- else if( sendpacket[34] == 0x02 )
- {
- /* This is an information request packet */
- printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname);
-
- /* Set the packet type to information response */
- sendpacket[34] = 0x03;
-
- /* Set the router name */
- sendpacket[51] = 'X';
- sendpacket[52] = 'T';
- sendpacket[53] = 'P';
- sendpacket[54] = 'I';
- sendpacket[55] = 'P';
- sendpacket[56] = 'E';
- sendpacket[57] = '-';
- sendpacket[58] = CVHexToAscii(network_number >> 28);
- sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24);
- sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20);
- sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16);
- sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12);
- sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8);
- sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4);
- sendpacket[65] = CVHexToAscii(network_number & 0x0000000F);
- for(i = 66; i < 99; i+= 1)
- {
- sendpacket[i] = 0;
- }
-
- printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname);
- }
- else
- {
- printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname);
- return 0;
- }
-
- /* Set the WNodeID to our network address */
- sendpacket[35] = (unsigned char)(network_number >> 24);
- sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16);
- sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8);
- sendpacket[38] = (unsigned char)(network_number & 0x000000FF);
-
- return 1;
- } else {
- /*If we get here it's an IPX-data packet, so it'll get passed up the stack.
- */
- /* switch the network numbers */
- switch_net_numbers(sendpacket, network_number, 1);
- return 0;
- }
-}
-
-/*
- * If incoming is 0 (outgoing)- if the net numbers is ours make it 0
- * if incoming is 1 - if the net number is 0 make it ours
- */
-
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming)
-{
- unsigned long pnetwork_number;
-
- pnetwork_number = (unsigned long)((sendpacket[6] << 24) +
- (sendpacket[7] << 16) + (sendpacket[8] << 8) +
- sendpacket[9]);
-
-
- if (!incoming) {
- /*If the destination network number is ours, make it 0 */
- if( pnetwork_number == network_number) {
- sendpacket[6] = sendpacket[7] = sendpacket[8] =
- sendpacket[9] = 0x00;
- }
- } else {
- /* If the incoming network is 0, make it ours */
- if( pnetwork_number == 0) {
- sendpacket[6] = (unsigned char)(network_number >> 24);
- sendpacket[7] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[8] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[9] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-
-
- pnetwork_number = (unsigned long)((sendpacket[18] << 24) +
- (sendpacket[19] << 16) + (sendpacket[20] << 8) +
- sendpacket[21]);
-
-
- if( !incoming ) {
- /* If the source network is ours, make it 0 */
- if( pnetwork_number == network_number) {
- sendpacket[18] = sendpacket[19] = sendpacket[20] =
- sendpacket[21] = 0x00;
- }
- } else {
- /* If the source network is 0, make it ours */
- if( pnetwork_number == 0 ) {
- sendpacket[18] = (unsigned char)(network_number >> 24);
- sendpacket[19] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[20] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[21] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-} /* switch_net_numbers */
-
-
-
-
-/********************* X25API SPECIFIC FUNCTIONS ****************/
-
-
-/*===============================================================
- * find_channel
- *
- * Manages the lcn to device map. It increases performance
- * because it eliminates the need to search through the link
- * list for a device which is bounded to a specific lcn.
- *
- *===============================================================*/
-
-
-struct net_device *find_channel(sdla_t *card, unsigned lcn)
-{
- if (card->u.x.LAPB_hdlc){
-
- return card->wandev.dev;
-
- }else{
- /* We don't know whether the incoming lcn
- * is a PVC or an SVC channel. But we do know that
- * the lcn cannot be for both the PVC and the SVC
- * channel.
-
- * If the lcn number is greater or equal to 255,
- * take the modulo 255 of that number. We only have
- * 255 locations, thus higher numbers must be mapped
- * to a number between 0 and 245.
-
- * We must separate pvc's and svc's since two don't
- * have to be contiguous. Meaning pvc's can start
- * from 1 to 10 and svc's can start from 256 to 266.
- * But 256%255 is 1, i.e. CONFLICT.
- */
-
-
- /* Highest LCN number must be less or equal to 4096 */
- if ((lcn <= MAX_LCN_NUM) && (lcn > 0)){
-
- if (lcn < X25_MAX_CHAN){
- if (card->u.x.svc_to_dev_map[lcn])
- return card->u.x.svc_to_dev_map[lcn];
-
- if (card->u.x.pvc_to_dev_map[lcn])
- return card->u.x.pvc_to_dev_map[lcn];
-
- }else{
- int new_lcn = lcn%X25_MAX_CHAN;
- if (card->u.x.svc_to_dev_map[new_lcn])
- return card->u.x.svc_to_dev_map[new_lcn];
-
- if (card->u.x.pvc_to_dev_map[new_lcn])
- return card->u.x.pvc_to_dev_map[new_lcn];
- }
- }
- return NULL;
- }
-}
-
-void bind_lcn_to_dev(sdla_t *card, struct net_device *dev, unsigned lcn)
-{
- x25_channel_t *chan = dev->priv;
-
- /* Modulo the lcn number by X25_MAX_CHAN (255)
- * because the lcn number can be greater than 255
- *
- * We need to split svc and pvc since they don't have
- * to be contigous.
- */
-
- if (chan->common.svc){
- card->u.x.svc_to_dev_map[(lcn % X25_MAX_CHAN)] = dev;
- }else{
- card->u.x.pvc_to_dev_map[(lcn % X25_MAX_CHAN)] = dev;
- }
- chan->common.lcn = lcn;
-}
-
-
-
-/*===============================================================
- * x25api_bh
- *
- *
- *==============================================================*/
-
-static void x25api_bh(struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- struct sk_buff *skb;
-
- if (atomic_read(&chan->bh_buff_used) == 0){
- printk(KERN_INFO "%s: BH Buffer Empty in BH\n",
- card->devname);
- clear_bit(0, &chan->tq_working);
- return;
- }
-
- while (atomic_read(&chan->bh_buff_used)){
-
- /* If the sock is in the process of unlinking the
- * driver from the socket, we must get out.
- * This never happends but is a sanity check. */
- if (test_bit(0,&chan->common.common_critical)){
- clear_bit(0, &chan->tq_working);
- return;
- }
-
- /* If LAPB HDLC, do not drop packets if socket is
- * not connected. Let the buffer fill up and
- * turn off rx interrupt */
- if (card->u.x.LAPB_hdlc){
- if (chan->common.sk == NULL || chan->common.func == NULL){
- clear_bit(0, &chan->tq_working);
- return;
- }
- }
-
- skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb;
-
- if (skb == NULL){
- printk(KERN_INFO "%s: BH Skb empty for read %i\n",
- card->devname,chan->bh_read);
- }else{
-
- if (chan->common.sk == NULL || chan->common.func == NULL){
- printk(KERN_INFO "%s: BH: Socket disconnected, dropping\n",
- card->devname);
- dev_kfree_skb_any(skb);
- x25api_bh_cleanup(dev);
- ++chan->ifstats.rx_dropped;
- ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
- continue;
- }
-
-
- if (chan->common.func(skb,dev,chan->common.sk) != 0){
- /* Sock full cannot send, queue us for another
- * try
- */
- printk(KERN_INFO "%s: BH: !!! Packet failed to send !!!!! \n",
- card->devname);
- atomic_set(&chan->common.receive_block,1);
- return;
- }else{
- x25api_bh_cleanup(dev);
- ++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack;
- }
- }
- }
- clear_bit(0, &chan->tq_working);
-
- return;
-}
-
-/*===============================================================
- * x25api_bh_cleanup
- *
- *
- *==============================================================*/
-
-static int x25api_bh_cleanup(struct net_device *dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t *card = chan->card;
- TX25Status* status = card->flags;
-
-
- ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL;
-
- if (chan->bh_read == MAX_BH_BUFF){
- chan->bh_read=0;
- }else{
- ++chan->bh_read;
- }
-
- /* If the Receive interrupt was off, it means
- * that we filled up our circular buffer. Check
- * that we have space in the buffer. If so
- * turn the RX interrupt back on.
- */
- if (!(status->imask & INTR_ON_RX_FRAME)){
- if (atomic_read(&chan->bh_buff_used) < (MAX_BH_BUFF+1)){
- printk(KERN_INFO "%s: BH: Turning on the interrupt\n",
- card->devname);
- status->imask |= INTR_ON_RX_FRAME;
- }
- }
-
- atomic_dec(&chan->bh_buff_used);
- return 0;
-}
-
-
-/*===============================================================
- * bh_enqueue
- *
- *
- *==============================================================*/
-
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t *card = chan->card;
- TX25Status* status = card->flags;
-
- if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){
- printk(KERN_INFO "%s: Bottom half buffer FULL\n",
- card->devname);
- return 1;
- }
-
- ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb;
-
- if (chan->bh_write == MAX_BH_BUFF){
- chan->bh_write=0;
- }else{
- ++chan->bh_write;
- }
-
- atomic_inc(&chan->bh_buff_used);
-
- if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){
- printk(KERN_INFO "%s: Buffer is now full, Turning off RX Intr\n",
- card->devname);
- status->imask &= ~INTR_ON_RX_FRAME;
- }
-
- return 0;
-}
-
-
-/*===============================================================
- * timer_intr_cmd_exec
- *
- * Called by timer interrupt to execute a command
- *===============================================================*/
-
-static int timer_intr_cmd_exec (sdla_t* card)
-{
- struct net_device *dev;
- unsigned char more_to_exec=0;
- volatile x25_channel_t *chan=NULL;
- int i=0,bad_cmd=0,err=0;
-
- if (card->u.x.cmd_dev == NULL){
- card->u.x.cmd_dev = card->wandev.dev;
- }
-
- dev = card->u.x.cmd_dev;
-
- for (;;){
-
- chan = dev->priv;
-
- if (atomic_read(&chan->common.command)){
-
- bad_cmd = check_bad_command(card,dev);
-
- if ((!chan->common.mbox || atomic_read(&chan->common.disconnect)) &&
- !bad_cmd){
-
- /* Socket has died or exited, We must bring the
- * channel down before anybody else tries to
- * use it */
- err = channel_disconnect(card,dev);
- }else{
- err = execute_delayed_cmd(card, dev,
- (mbox_cmd_t*)chan->common.mbox,
- bad_cmd);
- }
-
- switch (err){
-
- case RETURN_RESULT:
-
- /* Return the result to the socket without
- * delay. NO_WAIT Command */
- atomic_set(&chan->common.command,0);
- if (atomic_read(&card->u.x.command_busy))
- atomic_set(&card->u.x.command_busy,0);
-
- send_delayed_cmd_result(card,dev,card->mbox);
-
- more_to_exec=0;
- break;
- case DELAY_RESULT:
-
- /* Wait for the remote to respond, before
- * sending the result up to the socket.
- * WAIT command */
- if (atomic_read(&card->u.x.command_busy))
- atomic_set(&card->u.x.command_busy,0);
-
- atomic_set(&chan->common.command,0);
- more_to_exec=0;
- break;
- default:
-
- /* If command could not be executed for
- * some reason (i.e return code 0x33 busy)
- * set the more_to_exec bit which will
- * indicate that this command must be exectued
- * again during next timer interrupt
- */
- more_to_exec=1;
- if (atomic_read(&card->u.x.command_busy) == 0)
- atomic_set(&card->u.x.command_busy,1);
- break;
- }
-
- bad_cmd=0;
-
- /* If flags is set, there are no hdlc buffers,
- * thus, wait for the next pass and try the
- * same command again. Otherwise, start searching
- * from next device on the next pass.
- */
- if (!more_to_exec){
- dev = move_dev_to_next(card,dev);
- }
- break;
- }else{
- /* This device has nothing to execute,
- * go to next.
- */
- if (atomic_read(&card->u.x.command_busy))
- atomic_set(&card->u.x.command_busy,0);
- dev = move_dev_to_next(card,dev);
- }
-
- if (++i == card->u.x.no_dev){
- if (!more_to_exec){
- DBG_PRINTK(KERN_INFO "%s: Nothing to execute in Timer\n",
- card->devname);
- if (atomic_read(&card->u.x.command_busy)){
- atomic_set(&card->u.x.command_busy,0);
- }
- }
- break;
- }
-
- } //End of FOR
-
- card->u.x.cmd_dev = dev;
-
- if (more_to_exec){
- /* If more commands are pending, do not turn off timer
- * interrupt */
- return 1;
- }else{
- /* No more commands, turn off timer interrupt */
- return 0;
- }
-}
-
-/*===============================================================
- * execute_delayed_cmd
- *
- * Execute an API command which was passed down from the
- * sock. Sock is very limited in which commands it can
- * execute. Wait and No Wait commands are supported.
- * Place Call, Clear Call and Reset wait commands, where
- * Accept Call is a no_wait command.
- *
- *===============================================================*/
-
-static int execute_delayed_cmd(sdla_t* card, struct net_device *dev,
- mbox_cmd_t *usr_cmd, char bad_cmd)
-{
- TX25Mbox* mbox = card->mbox;
- int err;
- x25_channel_t *chan = dev->priv;
- int delay=RETURN_RESULT;
-
- if (!(*card->u.x.hdlc_buf_status & 0x40) && !bad_cmd){
- return TRY_CMD_AGAIN;
- }
-
- /* This way a command is guaranteed to be executed for
- * a specific lcn, the network interface is bound to. */
- usr_cmd->cmd.lcn = chan->common.lcn;
-
-
- /* If channel is pvc, instead of place call
- * run x25_channel configuration. If running LAPB HDLC
- * enable communications.
- */
- if ((!chan->common.svc) && (usr_cmd->cmd.command == X25_PLACE_CALL)){
-
- if (card->u.x.LAPB_hdlc){
- DBG_PRINTK(KERN_INFO "LAPB: Connecting\n");
- connect(card);
- set_chan_state(dev,WAN_CONNECTING);
- return DELAY_RESULT;
- }else{
- DBG_PRINTK(KERN_INFO "%s: PVC is CONNECTING\n",card->devname);
- if (x25_get_chan_conf(card, chan) == CMD_OK){
- set_chan_state(dev, WAN_CONNECTED);
- }else{
- set_chan_state(dev, WAN_DISCONNECTED);
- }
- return RETURN_RESULT;
- }
- }
-
- /* Copy the socket mbox command onto the board */
-
- memcpy(&mbox->cmd, &usr_cmd->cmd, sizeof(TX25Cmd));
- if (usr_cmd->cmd.length){
- memcpy(mbox->data, usr_cmd->data, usr_cmd->cmd.length);
- }
-
- /* Check if command is bad. We need to copy the cmd into
- * the buffer regardless since we return the, mbox to
- * the user */
- if (bad_cmd){
- mbox->cmd.result=0x01;
- return RETURN_RESULT;
- }
-
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- if (err != CMD_OK && err != X25RES_NOT_READY)
- x25_error(card, err, usr_cmd->cmd.command, usr_cmd->cmd.lcn);
-
- if (mbox->cmd.result == X25RES_NOT_READY){
- return TRY_CMD_AGAIN;
- }
-
- switch (mbox->cmd.command){
-
- case X25_PLACE_CALL:
-
- switch (mbox->cmd.result){
-
- case CMD_OK:
-
- /* Check if Place call is a wait command or a
- * no wait command */
- if (atomic_read(&chan->common.command) & 0x80)
- delay=RETURN_RESULT;
- else
- delay=DELAY_RESULT;
-
-
- DBG_PRINTK(KERN_INFO "\n%s: PLACE CALL Binding dev %s to lcn %i\n",
- card->devname,dev->name, mbox->cmd.lcn);
-
- bind_lcn_to_dev (card, dev, mbox->cmd.lcn);
- set_chan_state(dev, WAN_CONNECTING);
- break;
-
-
- default:
- delay=RETURN_RESULT;
- set_chan_state(dev, WAN_DISCONNECTED);
- break;
- }
- break;
-
- case X25_ACCEPT_CALL:
-
- switch (mbox->cmd.result){
-
- case CMD_OK:
-
- DBG_PRINTK(KERN_INFO "\n%s: ACCEPT Binding dev %s to lcn %i\n",
- card->devname,dev->name,mbox->cmd.lcn);
-
- bind_lcn_to_dev (card, dev, mbox->cmd.lcn);
-
- if (x25_get_chan_conf(card, chan) == CMD_OK){
-
- set_chan_state(dev, WAN_CONNECTED);
- delay=RETURN_RESULT;
-
- }else{
- if (x25_clear_call(card, usr_cmd->cmd.lcn, 0, 0) == CMD_OK){
- /* if clear is successful, wait for clear confirm
- */
- delay=DELAY_RESULT;
- }else{
- /* Do not change the state here. If we fail
- * the accept the return code is send up
- *the stack, which will ether retry
- * or clear the call
- */
- DBG_PRINTK(KERN_INFO
- "%s: ACCEPT: STATE MAY BE CURRUPTED 2 !!!!!\n",
- card->devname);
- delay=RETURN_RESULT;
- }
- }
- break;
-
-
- case X25RES_ASYNC_PACKET:
- delay=TRY_CMD_AGAIN;
- break;
-
- default:
- DBG_PRINTK(KERN_INFO "%s: ACCEPT FAILED\n",card->devname);
- if (x25_clear_call(card, usr_cmd->cmd.lcn, 0, 0) == CMD_OK){
- delay=DELAY_RESULT;
- }else{
- /* Do not change the state here. If we fail the accept. The
- * return code is send up the stack, which will ether retry
- * or clear the call */
- DBG_PRINTK(KERN_INFO
- "%s: ACCEPT: STATE MAY BE CORRUPTED 1 !!!!!\n",
- card->devname);
- delay=RETURN_RESULT;
- }
- }
- break;
-
- case X25_CLEAR_CALL:
-
- switch (mbox->cmd.result){
-
- case CMD_OK:
- DBG_PRINTK(KERN_INFO
- "CALL CLEAR OK: Dev %s Mbox Lcn %i Chan Lcn %i\n",
- dev->name,mbox->cmd.lcn,chan->common.lcn);
- set_chan_state(dev, WAN_DISCONNECTING);
- delay = DELAY_RESULT;
- break;
-
- case X25RES_CHANNEL_IN_USE:
- case X25RES_ASYNC_PACKET:
- delay = TRY_CMD_AGAIN;
- break;
-
- case X25RES_LINK_NOT_IN_ABM:
- case X25RES_INVAL_LCN:
- case X25RES_INVAL_STATE:
- set_chan_state(dev, WAN_DISCONNECTED);
- delay = RETURN_RESULT;
- break;
-
- default:
- /* If command did not execute because of user
- * fault, do not change the state. This will
- * signal the socket that clear command failed.
- * User can retry or close the socket.
- * When socket gets killed, it will set the
- * chan->disconnect which will signal
- * driver to clear the call */
- printk(KERN_INFO "%s: Clear Command Failed, Rc %x\n",
- card->devname,mbox->cmd.command);
- delay = RETURN_RESULT;
- }
- break;
- }
-
- return delay;
-}
-
-/*===============================================================
- * api_incoming_call
- *
- * Pass an incoming call request up the listening
- * sock. If the API sock is not listening reject the
- * call.
- *
- *===============================================================*/
-
-static int api_incoming_call (sdla_t* card, TX25Mbox *mbox, int lcn)
-{
- struct sk_buff *skb;
- int len = sizeof(TX25Cmd)+mbox->cmd.length;
-
- if (alloc_and_init_skb_buf(card, &skb, len)){
- printk(KERN_INFO "%s: API incoming call, no memory\n",card->devname);
- return 1;
- }
-
- memcpy(skb_put(skb,len),&mbox->cmd,len);
-
- skb->mac.raw = skb->data;
- skb->protocol = htons(X25_PROT);
- skb->pkt_type = WAN_PACKET_ASYNC;
-
- if (card->func(skb,card->sk) < 0){
- printk(KERN_INFO "%s: MAJOR ERROR: Failed to send up place call \n",card->devname);
- dev_kfree_skb_any(skb);
- return 1;
- }
-
- return 0;
-}
-
-/*===============================================================
- * send_delayed_cmd_result
- *
- * Wait commands like PLEACE CALL or CLEAR CALL must wait
- * until the result arrives. This function passes
- * the result to a waiting sock.
- *
- *===============================================================*/
-static void send_delayed_cmd_result(sdla_t *card, struct net_device *dev,
- TX25Mbox* mbox)
-{
- x25_channel_t *chan = dev->priv;
- mbox_cmd_t *usr_cmd = (mbox_cmd_t *)chan->common.mbox;
- struct sk_buff *skb;
- int len=sizeof(unsigned char);
-
- atomic_set(&chan->common.command,0);
-
- /* If the sock is in the process of unlinking the
- * driver from the socket, we must get out.
- * This never happends but is a sanity check. */
- if (test_bit(0,&chan->common.common_critical)){
- return;
- }
-
- if (!usr_cmd || !chan->common.sk || !chan->common.func){
- DBG_PRINTK(KERN_INFO "Delay result: Sock not bounded sk: %u, func: %u, mbox: %u\n",
- (unsigned int)chan->common.sk,
- (unsigned int)chan->common.func,
- (unsigned int)usr_cmd);
- return;
- }
-
- memcpy(&usr_cmd->cmd, &mbox->cmd, sizeof(TX25Cmd));
- if (mbox->cmd.length > 0){
- memcpy(usr_cmd->data, mbox->data, mbox->cmd.length);
- }
-
- if (alloc_and_init_skb_buf(card,&skb,len)){
- printk(KERN_INFO "Delay result: No sock buffers\n");
- return;
- }
-
- memcpy(skb_put(skb,len),&mbox->cmd.command,len);
-
- skb->mac.raw = skb->data;
- skb->pkt_type = WAN_PACKET_CMD;
-
- chan->common.func(skb,dev,chan->common.sk);
-}
-
-/*===============================================================
- * clear_confirm_event
- *
- * Pass the clear confirmation event up the sock. The
- * API will disconnect only after the clear confirmation
- * has been received.
- *
- * Depending on the state, clear confirmation could
- * be an OOB event, or a result of an API command.
- *===============================================================*/
-
-static int clear_confirm_event (sdla_t *card, TX25Mbox* mb)
-{
- struct net_device *dev;
- x25_channel_t *chan;
- unsigned char old_state;
-
- dev = find_channel(card,mb->cmd.lcn);
- if (!dev){
- DBG_PRINTK(KERN_INFO "%s: *** GOT CLEAR BUT NO DEV %i\n",
- card->devname,mb->cmd.lcn);
- return 0;
- }
-
- chan=dev->priv;
- DBG_PRINTK(KERN_INFO "%s: GOT CLEAR CONFIRM %s: Mbox lcn %i Chan lcn %i\n",
- card->devname, dev->name, mb->cmd.lcn, chan->common.lcn);
-
- /* If not API fall through to default.
- * If API, send the result to a waiting
- * socket.
- */
-
- old_state = chan->common.state;
- set_chan_state(dev, WAN_DISCONNECTED);
-
- if (chan->common.usedby == API){
- switch (old_state) {
-
- case WAN_DISCONNECTING:
- case WAN_CONNECTING:
- send_delayed_cmd_result(card,dev,mb);
- break;
- case WAN_CONNECTED:
- send_oob_msg(card,dev,mb);
- break;
- }
- return 1;
- }
-
- return 0;
-}
-
-/*===============================================================
- * send_oob_msg
- *
- * Construct an NEM Message and pass it up the connected
- * sock. If the sock is not bounded discard the NEM.
- *
- *===============================================================*/
-
-static void send_oob_msg(sdla_t *card, struct net_device *dev, TX25Mbox *mbox)
-{
- x25_channel_t *chan = dev->priv;
- mbox_cmd_t *usr_cmd = (mbox_cmd_t *)chan->common.mbox;
- struct sk_buff *skb;
- int len=sizeof(x25api_hdr_t)+mbox->cmd.length;
- x25api_t *api_hdr;
-
- /* If the sock is in the process of unlinking the
- * driver from the socket, we must get out.
- * This never happends but is a sanity check. */
- if (test_bit(0,&chan->common.common_critical)){
- return;
- }
-
- if (!usr_cmd || !chan->common.sk || !chan->common.func){
- DBG_PRINTK(KERN_INFO "OOB MSG: Sock not bounded\n");
- return;
- }
-
- memcpy(&usr_cmd->cmd, &mbox->cmd, sizeof(TX25Cmd));
- if (mbox->cmd.length > 0){
- memcpy(usr_cmd->data, mbox->data, mbox->cmd.length);
- }
-
- if (alloc_and_init_skb_buf(card,&skb,len)){
- printk(KERN_INFO "%s: OOB MSG: No sock buffers\n",card->devname);
- return;
- }
-
- api_hdr = (x25api_t*)skb_put(skb,len);
- api_hdr->hdr.pktType = mbox->cmd.pktType & 0x7F;
- api_hdr->hdr.qdm = mbox->cmd.qdm;
- api_hdr->hdr.cause = mbox->cmd.cause;
- api_hdr->hdr.diagn = mbox->cmd.diagn;
- api_hdr->hdr.length = mbox->cmd.length;
- api_hdr->hdr.result = mbox->cmd.result;
- api_hdr->hdr.lcn = mbox->cmd.lcn;
-
- if (mbox->cmd.length > 0){
- memcpy(api_hdr->data,mbox->data,mbox->cmd.length);
- }
-
- skb->mac.raw = skb->data;
- skb->pkt_type = WAN_PACKET_ERR;
-
- if (chan->common.func(skb,dev,chan->common.sk) < 0){
- if (bh_enqueue(dev,skb)){
- printk(KERN_INFO "%s: Dropping OOB MSG\n",card->devname);
- dev_kfree_skb_any(skb);
- }
- }
-
- DBG_PRINTK(KERN_INFO "%s: OOB MSG OK, %s, lcn %i\n",
- card->devname, dev->name, mbox->cmd.lcn);
-}
-
-/*===============================================================
- * alloc_and_init_skb_buf
- *
- * Allocate and initialize an skb buffer.
- *
- *===============================================================*/
-
-static int alloc_and_init_skb_buf (sdla_t *card, struct sk_buff **skb, int len)
-{
- struct sk_buff *new_skb = *skb;
-
- new_skb = dev_alloc_skb(len + X25_HRDHDR_SZ);
- if (new_skb == NULL){
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- return 1;
- }
-
- if (skb_tailroom(new_skb) < len){
- /* No room for the packet. Call off the whole thing! */
- dev_kfree_skb_any(new_skb);
- printk(KERN_INFO "%s: Listen: unexpectedly long packet sequence\n"
- ,card->devname);
- *skb = NULL;
- return 1;
- }
-
- *skb = new_skb;
- return 0;
-
-}
-
-/*===============================================================
- * api_oob_event
- *
- * Send an OOB event up to the sock
- *
- *===============================================================*/
-
-static void api_oob_event (sdla_t *card,TX25Mbox *mbox)
-{
- struct net_device *dev = find_channel(card, mbox->cmd.lcn);
- x25_channel_t *chan;
-
- if (!dev)
- return;
-
- chan=dev->priv;
-
- if (chan->common.usedby == API)
- send_oob_msg(card,dev,mbox);
-
-}
-
-
-
-
-static int channel_disconnect(sdla_t* card, struct net_device *dev)
-{
-
- int err;
- x25_channel_t *chan = dev->priv;
-
- DBG_PRINTK(KERN_INFO "%s: TIMER: %s, Device down disconnecting\n",
- card->devname,dev->name);
-
- if (chan->common.svc){
- err = x25_clear_call(card,chan->common.lcn,0,0);
- }else{
- /* If channel is PVC or LAPB HDLC, there is no call
- * to be cleared, thus drop down to the default
- * area
- */
- err = 1;
- }
-
- switch (err){
-
- case X25RES_CHANNEL_IN_USE:
- case X25RES_NOT_READY:
- err = TRY_CMD_AGAIN;
- break;
- case CMD_OK:
- DBG_PRINTK(KERN_INFO "CALL CLEAR OK: Dev %s Chan Lcn %i\n",
- dev->name,chan->common.lcn);
-
- set_chan_state(dev,WAN_DISCONNECTING);
- atomic_set(&chan->common.command,0);
- err = DELAY_RESULT;
- break;
- default:
- /* If LAPB HDLC protocol, bring the whole link down
- * once the application terminates
- */
-
- set_chan_state(dev,WAN_DISCONNECTED);
-
- if (card->u.x.LAPB_hdlc){
- DBG_PRINTK(KERN_INFO "LAPB: Disconnecting Link\n");
- hdlc_link_down (card);
- }
- atomic_set(&chan->common.command,0);
- err = RETURN_RESULT;
- break;
- }
-
- return err;
-}
-
-static void hdlc_link_down (sdla_t *card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = 5;
- int err=0;
-
- do {
- memset(mbox,0,sizeof(TX25Mbox));
- mbox->cmd.command = X25_HDLC_LINK_DISC;
- mbox->cmd.length = 1;
- mbox->data[0]=0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
- } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_DISC, 0));
-
- if (err)
- printk(KERN_INFO "%s: Hdlc Link Down Failed %x\n",card->devname,err);
-
- disconnect (card);
-
-}
-
-static int check_bad_command(sdla_t* card, struct net_device *dev)
-{
- x25_channel_t *chan = dev->priv;
- int bad_cmd = 0;
-
- switch (atomic_read(&chan->common.command)&0x7F){
-
- case X25_PLACE_CALL:
- if (chan->common.state != WAN_DISCONNECTED)
- bad_cmd=1;
- break;
- case X25_CLEAR_CALL:
- if (chan->common.state == WAN_DISCONNECTED)
- bad_cmd=1;
- break;
- case X25_ACCEPT_CALL:
- if (chan->common.state != WAN_CONNECTING)
- bad_cmd=1;
- break;
- case X25_RESET:
- if (chan->common.state != WAN_CONNECTED)
- bad_cmd=1;
- break;
- default:
- bad_cmd=1;
- break;
- }
-
- if (bad_cmd){
- printk(KERN_INFO "%s: Invalid State, BAD Command %x, dev %s, lcn %i, st %i\n",
- card->devname,atomic_read(&chan->common.command),dev->name,
- chan->common.lcn, chan->common.state);
- }
-
- return bad_cmd;
-}
-
-
-
-/*************************** XPIPEMON FUNCTIONS **************************/
-
-/*==============================================================================
- * Process UDP call of type XPIPE
- */
-
-static int process_udp_mgmt_pkt(sdla_t *card)
-{
- int c_retry = MAX_CMD_RETRY;
- unsigned int len;
- struct sk_buff *new_skb;
- TX25Mbox *mbox = card->mbox;
- int err;
- int udp_mgmt_req_valid = 1;
- struct net_device *dev;
- x25_channel_t *chan;
- unsigned short lcn;
- struct timeval tv;
-
-
- x25_udp_pkt_t *x25_udp_pkt;
- x25_udp_pkt = (x25_udp_pkt_t *)card->u.x.udp_pkt_data;
-
- dev = card->u.x.udp_dev;
- chan = dev->priv;
- lcn = chan->common.lcn;
-
- switch(x25_udp_pkt->cblock.command) {
-
- /* XPIPE_ENABLE_TRACE */
- case XPIPE_ENABLE_TRACING:
-
- /* XPIPE_GET_TRACE_INFO */
- case XPIPE_GET_TRACE_INFO:
-
- /* SET FT1 MODE */
- case XPIPE_SET_FT1_MODE:
-
- if(card->u.x.udp_pkt_src == UDP_PKT_FRM_NETWORK) {
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_direction_err;
- udp_mgmt_req_valid = 0;
- break;
- }
-
- /* XPIPE_FT1_READ_STATUS */
- case XPIPE_FT1_READ_STATUS:
-
- /* FT1 MONITOR STATUS */
- case XPIPE_FT1_STATUS_CTRL:
- if(card->hw.fwid != SFID_X25_508) {
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_type_err;
- udp_mgmt_req_valid = 0;
- break;
- }
- default:
- break;
- }
-
- if(!udp_mgmt_req_valid) {
- /* set length to 0 */
- x25_udp_pkt->cblock.length = 0;
- /* set return code */
- x25_udp_pkt->cblock.result = (card->hw.fwid != SFID_X25_508) ? 0x1F : 0xCD;
-
- } else {
-
- switch (x25_udp_pkt->cblock.command) {
-
-
- case XPIPE_FLUSH_DRIVER_STATS:
- init_x25_channel_struct(chan);
- init_global_statistics(card);
- mbox->cmd.length = 0;
- break;
-
-
- case XPIPE_DRIVER_STAT_IFSEND:
- memcpy(x25_udp_pkt->data, &chan->if_send_stat, sizeof(if_send_stat_t));
- mbox->cmd.length = sizeof(if_send_stat_t);
- x25_udp_pkt->cblock.length = mbox->cmd.length;
- break;
-
- case XPIPE_DRIVER_STAT_INTR:
- memcpy(&x25_udp_pkt->data[0], &card->statistics, sizeof(global_stats_t));
- memcpy(&x25_udp_pkt->data[sizeof(global_stats_t)],
- &chan->rx_intr_stat, sizeof(rx_intr_stat_t));
-
- mbox->cmd.length = sizeof(global_stats_t) +
- sizeof(rx_intr_stat_t);
- x25_udp_pkt->cblock.length = mbox->cmd.length;
- break;
-
- case XPIPE_DRIVER_STAT_GEN:
- memcpy(x25_udp_pkt->data,
- &chan->pipe_mgmt_stat.UDP_PIPE_mgmt_kmalloc_err,
- sizeof(pipe_mgmt_stat_t));
-
- memcpy(&x25_udp_pkt->data[sizeof(pipe_mgmt_stat_t)],
- &card->statistics, sizeof(global_stats_t));
-
- x25_udp_pkt->cblock.result = 0;
- x25_udp_pkt->cblock.length = sizeof(global_stats_t)+
- sizeof(rx_intr_stat_t);
- mbox->cmd.length = x25_udp_pkt->cblock.length;
- break;
-
- case XPIPE_ROUTER_UP_TIME:
- do_gettimeofday(&tv);
- chan->router_up_time = tv.tv_sec - chan->router_start_time;
- *(unsigned long *)&x25_udp_pkt->data = chan->router_up_time;
- x25_udp_pkt->cblock.length = mbox->cmd.length = 4;
- x25_udp_pkt->cblock.result = 0;
- break;
-
- default :
-
- do {
- memcpy(&mbox->cmd, &x25_udp_pkt->cblock.command, sizeof(TX25Cmd));
- if(mbox->cmd.length){
- memcpy(&mbox->data,
- (char *)x25_udp_pkt->data,
- mbox->cmd.length);
- }
-
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && c_retry-- && x25_error(card, err, mbox->cmd.command, 0));
-
-
- if ( err == CMD_OK ||
- (err == 1 &&
- (mbox->cmd.command == 0x06 ||
- mbox->cmd.command == 0x16) ) ){
-
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_OK;
- } else {
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_timeout;
- }
-
- /* copy the result back to our buffer */
- memcpy(&x25_udp_pkt->cblock.command, &mbox->cmd, sizeof(TX25Cmd));
-
- if(mbox->cmd.length) {
- memcpy(&x25_udp_pkt->data, &mbox->data, mbox->cmd.length);
- }
- break;
-
- } //switch
-
- }
-
- /* Fill UDP TTL */
-
- x25_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
- len = reply_udp(card->u.x.udp_pkt_data, mbox->cmd.length);
-
-
- if(card->u.x.udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
- err = x25_send(card, lcn, 0, len, card->u.x.udp_pkt_data);
- if (!err)
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_send_passed;
- else
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_send_failed;
-
- } else {
-
- /* Allocate socket buffer */
- if((new_skb = dev_alloc_skb(len)) != NULL) {
- void *buf;
-
- /* copy data into new_skb */
- buf = skb_put(new_skb, len);
- memcpy(buf, card->u.x.udp_pkt_data, len);
-
- /* Decapsulate packet and pass it up the protocol
- stack */
- new_skb->dev = dev;
-
- if (chan->common.usedby == API)
- new_skb->protocol = htons(X25_PROT);
- else
- new_skb->protocol = htons(ETH_P_IP);
-
- new_skb->mac.raw = new_skb->data;
-
- netif_rx(new_skb);
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_stack;
-
- } else {
- ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_no_socket;
- printk(KERN_INFO
- "%s: UDP mgmt cmnd, no socket buffers available!\n",
- card->devname);
- }
- }
-
- card->u.x.udp_pkt_lgth = 0;
-
- return 1;
-}
-
-
-/*==============================================================================
- * Determine what type of UDP call it is. DRVSTATS or XPIPE8ND ?
- */
-static int udp_pkt_type( struct sk_buff *skb, sdla_t* card )
-{
- x25_udp_pkt_t *x25_udp_pkt = (x25_udp_pkt_t *)skb->data;
-
- if((x25_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
- (x25_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45) &&
- (x25_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) &&
- (x25_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) {
-
- if(!strncmp(x25_udp_pkt->wp_mgmt.signature,
- UDPMGMT_XPIPE_SIGNATURE, 8)){
- return UDP_XPIPE_TYPE;
- }else{
- printk(KERN_INFO "%s: UDP Packet, Failed Signature !\n",
- card->devname);
- }
- }
-
- return UDP_INVALID_TYPE;
-}
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return nothing.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
- unsigned short len, udp_length, temp, ip_length;
- unsigned long ip_temp;
- int even_bound = 0;
-
-
- x25_udp_pkt_t *x25_udp_pkt = (x25_udp_pkt_t *)data;
-
- /* Set length of packet */
- len = sizeof(ip_pkt_t)+
- sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- mbox_len;
-
-
- /* fill in UDP reply */
- x25_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-
- /* fill in UDP length */
- udp_length = sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- mbox_len;
-
-
- /* put it on an even boundary */
- if ( udp_length & 0x0001 ) {
- udp_length += 1;
- len += 1;
- even_bound = 1;
- }
-
- temp = (udp_length<<8)|(udp_length>>8);
- x25_udp_pkt->udp_pkt.udp_length = temp;
-
- /* swap UDP ports */
- temp = x25_udp_pkt->udp_pkt.udp_src_port;
- x25_udp_pkt->udp_pkt.udp_src_port =
- x25_udp_pkt->udp_pkt.udp_dst_port;
- x25_udp_pkt->udp_pkt.udp_dst_port = temp;
-
-
-
- /* add UDP pseudo header */
- temp = 0x1100;
- *((unsigned short *)
- (x25_udp_pkt->data+mbox_len+even_bound)) = temp;
- temp = (udp_length<<8)|(udp_length>>8);
- *((unsigned short *)
- (x25_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
- /* calculate UDP checksum */
- x25_udp_pkt->udp_pkt.udp_checksum = 0;
-
- x25_udp_pkt->udp_pkt.udp_checksum =
- calc_checksum(&data[UDP_OFFSET], udp_length+UDP_OFFSET);
-
- /* fill in IP length */
- ip_length = len;
- temp = (ip_length<<8)|(ip_length>>8);
- x25_udp_pkt->ip_pkt.total_length = temp;
-
- /* swap IP addresses */
- ip_temp = x25_udp_pkt->ip_pkt.ip_src_address;
- x25_udp_pkt->ip_pkt.ip_src_address =
- x25_udp_pkt->ip_pkt.ip_dst_address;
- x25_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
-
- /* fill in IP checksum */
- x25_udp_pkt->ip_pkt.hdr_checksum = 0;
- x25_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data, sizeof(ip_pkt_t));
-
- return len;
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
- unsigned short temp;
- unsigned long sum=0;
- int i;
-
- for( i = 0; i <len; i+=2 ) {
- memcpy(&temp,&data[i],2);
- sum += (unsigned long)temp;
- }
-
- while (sum >> 16 ) {
- sum = (sum & 0xffffUL) + (sum >> 16);
- }
-
- temp = (unsigned short)sum;
- temp = ~temp;
-
- if( temp == 0 )
- temp = 0xffff;
-
- return temp;
-}
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card,
- struct net_device *dev, struct sk_buff *skb,
- int lcn)
-{
- int udp_pkt_stored = 0;
-
- if(!card->u.x.udp_pkt_lgth && (skb->len <= MAX_LGTH_UDP_MGNT_PKT)){
- card->u.x.udp_pkt_lgth = skb->len;
- card->u.x.udp_type = udp_type;
- card->u.x.udp_pkt_src = udp_pkt_src;
- card->u.x.udp_lcn = lcn;
- card->u.x.udp_dev = dev;
- memcpy(card->u.x.udp_pkt_data, skb->data, skb->len);
- card->u.x.timer_int_enabled |= TMR_INT_ENABLED_UDP_PKT;
- udp_pkt_stored = 1;
-
- }else{
- printk(KERN_INFO "%s: ERROR: UDP packet not stored for LCN %d\n",
- card->devname,lcn);
- }
-
- if(udp_pkt_src == UDP_PKT_FRM_STACK){
- dev_kfree_skb_any(skb);
- }else{
- dev_kfree_skb_any(skb);
- }
-
- return(udp_pkt_stored);
-}
-
-
-
-/*=============================================================================
- * Initial the ppp_private_area structure.
- */
-static void init_x25_channel_struct( x25_channel_t *chan )
-{
- memset(&chan->if_send_stat.if_send_entry,0,sizeof(if_send_stat_t));
- memset(&chan->rx_intr_stat.rx_intr_no_socket,0,sizeof(rx_intr_stat_t));
- memset(&chan->pipe_mgmt_stat.UDP_PIPE_mgmt_kmalloc_err,0,sizeof(pipe_mgmt_stat_t));
-}
-
-/*============================================================================
- * Initialize Global Statistics
- */
-static void init_global_statistics( sdla_t *card )
-{
- memset(&card->statistics.isr_entry,0,sizeof(global_stats_t));
-}
-
-
-/*===============================================================
- * SMP Support
- * ==============================================================*/
-
-static void S508_S514_lock(sdla_t *card, unsigned long *smp_flags)
-{
- spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-}
-static void S508_S514_unlock(sdla_t *card, unsigned long *smp_flags)
-{
- spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-}
-
-/*===============================================================
- * x25_timer_routine
- *
- * A more efficient polling routine. Each half a second
- * queue a polling task. We want to do the polling in a
- * task not timer, because timer runs in interrupt time.
- *
- * FIXME Polling should be rethinked.
- *==============================================================*/
-
-static void x25_timer_routine(unsigned long data)
-{
- sdla_t *card = (sdla_t*)data;
-
- if (!card->wandev.dev){
- printk(KERN_INFO "%s: Stopping the X25 Poll Timer: No Dev.\n",
- card->devname);
- return;
- }
-
- if (card->open_cnt != card->u.x.num_of_ch){
- printk(KERN_INFO "%s: Stopping the X25 Poll Timer: Interface down.\n",
- card->devname);
- return;
- }
-
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- printk(KERN_INFO "%s: Stopping the X25 Poll Timer: Shutting down.\n",
- card->devname);
- return;
- }
-
- if (!test_and_set_bit(POLL_CRIT,&card->wandev.critical)){
- trigger_x25_poll(card);
- }
-
- card->u.x.x25_timer.expires=jiffies+(HZ>>1);
- add_timer(&card->u.x.x25_timer);
- return;
-}
-
-void disable_comm_shutdown(sdla_t *card)
-{
- TX25Mbox* mbox = card->mbox;
- int err;
-
- /* Turn of interrutps */
- mbox->data[0] = 0;
- if (card->hw.fwid == SFID_X25_508){
- mbox->data[1] = card->hw.irq;
- mbox->data[2] = 2;
- mbox->cmd.length = 3;
- }else {
- mbox->cmd.length = 1;
- }
- mbox->cmd.command = X25_SET_INTERRUPT_MODE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err)
- printk(KERN_INFO "INTERRUPT OFF FAIED %x\n",err);
-
- /* Bring down HDLC */
- mbox->cmd.command = X25_HDLC_LINK_CLOSE;
- mbox->cmd.length = 0;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err)
- printk(KERN_INFO "LINK CLOSED FAILED %x\n",err);
-
-
- /* Brind down DTR */
- mbox->data[0] = 0;
- mbox->data[2] = 0;
- mbox->data[1] = 0x01;
- mbox->cmd.length = 3;
- mbox->cmd.command = X25_SET_GLOBAL_VARS;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err)
- printk(KERN_INFO "DTR DOWN FAILED %x\n",err);
-
-}
-
-MODULE_LICENSE("GPL");
-
-/****** End *****************************************************************/
diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
deleted file mode 100644
index 032c0f81928..00000000000
--- a/drivers/net/wan/sdladrv.c
+++ /dev/null
@@ -1,2314 +0,0 @@
-/*****************************************************************************
-* sdladrv.c SDLA Support Module. Main module.
-*
-* This module is a library of common hardware-specific functions
-* used by all Sangoma drivers.
-*
-* Author: Gideon Hack
-*
-* Copyright: (c) 1995-2000 Sangoma Technologies 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.
-* ============================================================================
-* Mar 20, 2001 Nenad Corbic Added the auto_pci_cfg filed, to support
-* the PCISLOT #0.
-* Apr 04, 2000 Nenad Corbic Fixed the auto memory detection code.
-* The memory test at address 0xC8000.
-* Mar 09, 2000 Nenad Corbic Added Gideon's Bug Fix: clear pci
-* interrupt flags on initial load.
-* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
-* Updates for Linux 2.2.X kernels.
-* Sep 17, 1998 Jaspreet Singh Updates for linux 2.2.X kernels
-* Dec 20, 1996 Gene Kozin Version 3.0.0. Complete overhaul.
-* Jul 12, 1996 Gene Kozin Changes for Linux 2.0 compatibility.
-* Jun 12, 1996 Gene Kozin Added support for S503 card.
-* Apr 30, 1996 Gene Kozin SDLA hardware interrupt is acknowledged before
-* calling protocolspecific ISR.
-* Register I/O ports with Linux kernel.
-* Miscellaneous bug fixes.
-* Dec 20, 1995 Gene Kozin Fixed a bug in interrupt routine.
-* Oct 14, 1995 Gene Kozin Initial version.
-*****************************************************************************/
-
-/*****************************************************************************
- * Notes:
- * ------
- * 1. This code is ment to be system-independent (as much as possible). To
- * achive this, various macros are used to hide system-specific interfaces.
- * To compile this code, one of the following constants must be defined:
- *
- * Platform Define
- * -------- ------
- * Linux _LINUX_
- * SCO Unix _SCO_UNIX_
- *
- * 2. Supported adapter types:
- *
- * S502A
- * ES502A (S502E)
- * S503
- * S507
- * S508 (S509)
- *
- * 3. S502A Notes:
- *
- * There is no separate DPM window enable/disable control in S502A. It
- * opens immediately after a window number it written to the HMCR
- * register. To close the window, HMCR has to be written a value
- * ????1111b (e.g. 0x0F or 0xFF).
- *
- * S502A DPM window cannot be located at offset E000 (e.g. 0xAE000).
- *
- * There should be a delay of ??? before reading back S502A status
- * register.
- *
- * 4. S502E Notes:
- *
- * S502E has a h/w bug: although default IRQ line state is HIGH, enabling
- * interrupts by setting bit 1 of the control register (BASE) to '1'
- * causes it to go LOW! Therefore, disabling interrupts by setting that
- * bit to '0' causes low-to-high transition on IRQ line (ghosty
- * interrupt). The same occurs when disabling CPU by resetting bit 0 of
- * CPU control register (BASE+3) - see the next note.
- *
- * S502E CPU and DPM control is limited:
- *
- * o CPU cannot be stopped independently. Resetting bit 0 of the CPUi
- * control register (BASE+3) shuts the board down entirely, including
- * DPM;
- *
- * o DPM access cannot be controlled dynamically. Ones CPU is started,
- * bit 1 of the control register (BASE) is used to enable/disable IRQ,
- * so that access to shared memory cannot be disabled while CPU is
- * running.
- ****************************************************************************/
-
-#define _LINUX_
-
-#if defined(_LINUX_) /****** Linux *******************************/
-
-#include <linux/config.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/module.h> /* support for loadable modules */
-#include <linux/jiffies.h> /* for jiffies, HZ, etc. */
-#include <linux/sdladrv.h> /* API definitions */
-#include <linux/sdlasfm.h> /* SDLA firmware module definitions */
-#include <linux/sdlapci.h> /* SDLA PCI hardware definitions */
-#include <linux/pci.h> /* PCI defines and function prototypes */
-#include <asm/io.h> /* for inb(), outb(), etc. */
-
-#define _INB(port) (inb(port))
-#define _OUTB(port, byte) (outb((byte),(port)))
-#define SYSTEM_TICK jiffies
-
-#include <linux/init.h>
-
-
-#elif defined(_SCO_UNIX_) /****** SCO Unix ****************************/
-
-#if !defined(INKERNEL)
-#error This code MUST be compiled in kernel mode!
-#endif
-#include <sys/sdladrv.h> /* API definitions */
-#include <sys/sdlasfm.h> /* SDLA firmware module definitions */
-#include <sys/inline.h> /* for inb(), outb(), etc. */
-#define _INB(port) (inb(port))
-#define _OUTB(port, byte) (outb((port),(byte)))
-#define SYSTEM_TICK lbolt
-
-#else
-#error Unknown system type!
-#endif
-
-#define MOD_VERSION 3
-#define MOD_RELEASE 0
-
-#define SDLA_IODELAY 100 /* I/O Rd/Wr delay, 10 works for 486DX2-66 */
-#define EXEC_DELAY 20 /* shared memory access delay, mks */
-#define EXEC_TIMEOUT (HZ*2) /* command timeout, in ticks */
-
-/* I/O port address range */
-#define S502A_IORANGE 3
-#define S502E_IORANGE 4
-#define S503_IORANGE 3
-#define S507_IORANGE 4
-#define S508_IORANGE 4
-
-/* Maximum amount of memory */
-#define S502_MAXMEM 0x10000L
-#define S503_MAXMEM 0x10000L
-#define S507_MAXMEM 0x40000L
-#define S508_MAXMEM 0x40000L
-
-/* Minimum amount of memory */
-#define S502_MINMEM 0x8000L
-#define S503_MINMEM 0x8000L
-#define S507_MINMEM 0x20000L
-#define S508_MINMEM 0x20000L
-#define NO_PORT -1
-
-
-
-
-
-/****** Function Prototypes *************************************************/
-
-/* Hardware-specific functions */
-static int sdla_detect (sdlahw_t* hw);
-static int sdla_autodpm (sdlahw_t* hw);
-static int sdla_setdpm (sdlahw_t* hw);
-static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len);
-static int sdla_init (sdlahw_t* hw);
-static unsigned long sdla_memtest (sdlahw_t* hw);
-static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo);
-static unsigned char make_config_byte (sdlahw_t* hw);
-static int sdla_start (sdlahw_t* hw, unsigned addr);
-
-static int init_s502a (sdlahw_t* hw);
-static int init_s502e (sdlahw_t* hw);
-static int init_s503 (sdlahw_t* hw);
-static int init_s507 (sdlahw_t* hw);
-static int init_s508 (sdlahw_t* hw);
-
-static int detect_s502a (int port);
-static int detect_s502e (int port);
-static int detect_s503 (int port);
-static int detect_s507 (int port);
-static int detect_s508 (int port);
-static int detect_s514 (sdlahw_t* hw);
-static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card);
-
-/* Miscellaneous functions */
-static void peek_by_4 (unsigned long src, void* buf, unsigned len);
-static void poke_by_4 (unsigned long dest, void* buf, unsigned len);
-static int calibrate_delay (int mks);
-static int get_option_index (unsigned* optlist, unsigned optval);
-static unsigned check_memregion (void* ptr, unsigned len);
-static unsigned test_memregion (void* ptr, unsigned len);
-static unsigned short checksum (unsigned char* buf, unsigned len);
-static int init_pci_slot(sdlahw_t *);
-
-static int pci_probe(sdlahw_t *hw);
-
-/****** Global Data **********************************************************
- * Note: All data must be explicitly initialized!!!
- */
-
-static struct pci_device_id sdladrv_pci_tbl[] = {
- { V3_VENDOR_ID, V3_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, },
- { } /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, sdladrv_pci_tbl);
-
-MODULE_LICENSE("GPL");
-
-/* private data */
-static char modname[] = "sdladrv";
-static char fullname[] = "SDLA Support Module";
-static char copyright[] = "(c) 1995-1999 Sangoma Technologies Inc.";
-static unsigned exec_idle;
-
-/* Hardware configuration options.
- * These are arrays of configuration options used by verification routines.
- * The first element of each array is its size (i.e. number of options).
- */
-static unsigned s502_port_options[] =
- { 4, 0x250, 0x300, 0x350, 0x360 }
-;
-static unsigned s503_port_options[] =
- { 8, 0x250, 0x254, 0x300, 0x304, 0x350, 0x354, 0x360, 0x364 }
-;
-static unsigned s508_port_options[] =
- { 8, 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390 }
-;
-
-static unsigned s502a_irq_options[] = { 0 };
-static unsigned s502e_irq_options[] = { 4, 2, 3, 5, 7 };
-static unsigned s503_irq_options[] = { 5, 2, 3, 4, 5, 7 };
-static unsigned s508_irq_options[] = { 8, 3, 4, 5, 7, 10, 11, 12, 15 };
-
-static unsigned s502a_dpmbase_options[] =
-{
- 28,
- 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000,
- 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000,
- 0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000,
- 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000,
-};
-static unsigned s507_dpmbase_options[] =
-{
- 32,
- 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,
- 0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000,
- 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
- 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000,
-};
-static unsigned s508_dpmbase_options[] = /* incl. S502E and S503 */
-{
- 32,
- 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,
- 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
- 0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000,
- 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000,
-};
-
-/*
-static unsigned s502_dpmsize_options[] = { 2, 0x2000, 0x10000 };
-static unsigned s507_dpmsize_options[] = { 2, 0x2000, 0x4000 };
-static unsigned s508_dpmsize_options[] = { 1, 0x2000 };
-*/
-
-static unsigned s502a_pclk_options[] = { 2, 3600, 7200 };
-static unsigned s502e_pclk_options[] = { 5, 3600, 5000, 7200, 8000, 10000 };
-static unsigned s503_pclk_options[] = { 3, 7200, 8000, 10000 };
-static unsigned s507_pclk_options[] = { 1, 12288 };
-static unsigned s508_pclk_options[] = { 1, 16000 };
-
-/* Host memory control register masks */
-static unsigned char s502a_hmcr[] =
-{
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, /* A0000 - AC000 */
- 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, /* C0000 - CC000 */
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, /* D0000 - DC000 */
- 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, /* E0000 - EC000 */
-};
-static unsigned char s502e_hmcr[] =
-{
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, /* A0000 - AE000 */
- 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, /* C0000 - CE000 */
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, /* D0000 - DE000 */
- 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E, /* E0000 - EE000 */
-};
-static unsigned char s507_hmcr[] =
-{
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, /* A0000 - AE000 */
- 0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, /* B0000 - BE000 */
- 0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E, /* C0000 - CE000 */
- 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, /* E0000 - EE000 */
-};
-static unsigned char s508_hmcr[] =
-{
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* A0000 - AE000 */
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* C0000 - CE000 */
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* D0000 - DE000 */
- 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* E0000 - EE000 */
-};
-
-static unsigned char s507_irqmask[] =
-{
- 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0
-};
-
-static int pci_slot_ar[MAX_S514_CARDS];
-
-/******* Kernel Loadable Module Entry Points ********************************/
-
-/*============================================================================
- * Module 'insert' entry point.
- * o print announcement
- * o initialize static data
- * o calibrate SDLA shared memory access delay.
- *
- * Return: 0 Ok
- * < 0 error.
- * Context: process
- */
-
-static int __init sdladrv_init(void)
-{
- int i=0;
-
- printk(KERN_INFO "%s v%u.%u %s\n",
- fullname, MOD_VERSION, MOD_RELEASE, copyright);
- exec_idle = calibrate_delay(EXEC_DELAY);
-#ifdef WANDEBUG
- printk(KERN_DEBUG "%s: exec_idle = %d\n", modname, exec_idle);
-#endif
-
- /* Initialize the PCI Card array, which
- * will store flags, used to mark
- * card initialization state */
- for (i=0; i<MAX_S514_CARDS; i++)
- pci_slot_ar[i] = 0xFF;
-
- return 0;
-}
-
-/*============================================================================
- * Module 'remove' entry point.
- * o release all remaining system resources
- */
-static void __exit sdladrv_cleanup(void)
-{
-}
-
-module_init(sdladrv_init);
-module_exit(sdladrv_cleanup);
-
-/******* Kernel APIs ********************************************************/
-
-/*============================================================================
- * Set up adapter.
- * o detect adapter type
- * o verify hardware configuration options
- * o check for hardware conflicts
- * o set up adapter shared memory
- * o test adapter memory
- * o load firmware
- * Return: 0 ok.
- * < 0 error
- */
-
-EXPORT_SYMBOL(sdla_setup);
-
-int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len)
-{
- unsigned* irq_opt = NULL; /* IRQ options */
- unsigned* dpmbase_opt = NULL; /* DPM window base options */
- unsigned* pclk_opt = NULL; /* CPU clock rate options */
- int err=0;
-
- if (sdla_detect(hw)) {
- if(hw->type != SDLA_S514)
- printk(KERN_INFO "%s: no SDLA card found at port 0x%X\n",
- modname, hw->port);
- return -EINVAL;
- }
-
- if(hw->type != SDLA_S514) {
- printk(KERN_INFO "%s: found S%04u card at port 0x%X.\n",
- modname, hw->type, hw->port);
-
- hw->dpmsize = SDLA_WINDOWSIZE;
- switch (hw->type) {
- case SDLA_S502A:
- hw->io_range = S502A_IORANGE;
- irq_opt = s502a_irq_options;
- dpmbase_opt = s502a_dpmbase_options;
- pclk_opt = s502a_pclk_options;
- break;
-
- case SDLA_S502E:
- hw->io_range = S502E_IORANGE;
- irq_opt = s502e_irq_options;
- dpmbase_opt = s508_dpmbase_options;
- pclk_opt = s502e_pclk_options;
- break;
-
- case SDLA_S503:
- hw->io_range = S503_IORANGE;
- irq_opt = s503_irq_options;
- dpmbase_opt = s508_dpmbase_options;
- pclk_opt = s503_pclk_options;
- break;
-
- case SDLA_S507:
- hw->io_range = S507_IORANGE;
- irq_opt = s508_irq_options;
- dpmbase_opt = s507_dpmbase_options;
- pclk_opt = s507_pclk_options;
- break;
-
- case SDLA_S508:
- hw->io_range = S508_IORANGE;
- irq_opt = s508_irq_options;
- dpmbase_opt = s508_dpmbase_options;
- pclk_opt = s508_pclk_options;
- break;
- }
-
- /* Verify IRQ configuration options */
- if (!get_option_index(irq_opt, hw->irq)) {
- printk(KERN_INFO "%s: IRQ %d is invalid!\n",
- modname, hw->irq);
- return -EINVAL;
- }
-
- /* Verify CPU clock rate configuration options */
- if (hw->pclk == 0)
- hw->pclk = pclk_opt[1]; /* use default */
-
- else if (!get_option_index(pclk_opt, hw->pclk)) {
- printk(KERN_INFO "%s: CPU clock %u is invalid!\n",
- modname, hw->pclk);
- return -EINVAL;
- }
- printk(KERN_INFO "%s: assuming CPU clock rate of %u kHz.\n",
- modname, hw->pclk);
-
- /* Setup adapter dual-port memory window and test memory */
- if (hw->dpmbase == 0) {
- err = sdla_autodpm(hw);
- if (err) {
- printk(KERN_INFO
- "%s: can't find available memory region!\n",
- modname);
- return err;
- }
- }
- else if (!get_option_index(dpmbase_opt,
- virt_to_phys(hw->dpmbase))) {
- printk(KERN_INFO
- "%s: memory address 0x%lX is invalid!\n",
- modname, virt_to_phys(hw->dpmbase));
- return -EINVAL;
- }
- else if (sdla_setdpm(hw)) {
- printk(KERN_INFO
- "%s: 8K memory region at 0x%lX is not available!\n",
- modname, virt_to_phys(hw->dpmbase));
- return -EINVAL;
- }
- printk(KERN_INFO
- "%s: dual-port memory window is set at 0x%lX.\n",
- modname, virt_to_phys(hw->dpmbase));
-
-
- /* If we find memory in 0xE**** Memory region,
- * warn the user to disable the SHADOW RAM.
- * Since memory corruption can occur if SHADOW is
- * enabled. This can causes random crashes ! */
- if (virt_to_phys(hw->dpmbase) >= 0xE0000){
- printk(KERN_WARNING "\n%s: !!!!!!!! WARNING !!!!!!!!\n",modname);
- printk(KERN_WARNING "%s: WANPIPE is using 0x%lX memory region !!!\n",
- modname, virt_to_phys(hw->dpmbase));
- printk(KERN_WARNING " Please disable the SHADOW RAM, otherwise\n");
- printk(KERN_WARNING " your system might crash randomly from time to time !\n");
- printk(KERN_WARNING "%s: !!!!!!!! WARNING !!!!!!!!\n\n",modname);
- }
- }
-
- else {
- hw->memory = test_memregion((void*)hw->dpmbase,
- MAX_SIZEOF_S514_MEMORY);
- if(hw->memory < (256 * 1024)) {
- printk(KERN_INFO
- "%s: error in testing S514 memory (0x%lX)\n",
- modname, hw->memory);
- sdla_down(hw);
- return -EINVAL;
- }
- }
-
- printk(KERN_INFO "%s: found %luK bytes of on-board memory\n",
- modname, hw->memory / 1024);
-
- /* Load firmware. If loader fails then shut down adapter */
- err = sdla_load(hw, sfm, len);
- if (err) sdla_down(hw); /* shutdown adapter */
-
- return err;
-}
-
-/*============================================================================
- * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc.
- */
-
-EXPORT_SYMBOL(sdla_down);
-
-int sdla_down (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int i;
- unsigned char CPU_no;
- u32 int_config, int_status;
-
- if(!port && (hw->type != SDLA_S514))
- return -EFAULT;
-
- switch (hw->type) {
- case SDLA_S502A:
- _OUTB(port, 0x08); /* halt CPU */
- _OUTB(port, 0x08);
- _OUTB(port, 0x08);
- hw->regs[0] = 0x08;
- _OUTB(port + 1, 0xFF); /* close memory window */
- hw->regs[1] = 0xFF;
- break;
-
- case SDLA_S502E:
- _OUTB(port + 3, 0); /* stop CPU */
- _OUTB(port, 0); /* reset board */
- for (i = 0; i < S502E_IORANGE; ++i)
- hw->regs[i] = 0
- ;
- break;
-
- case SDLA_S503:
- case SDLA_S507:
- case SDLA_S508:
- _OUTB(port, 0); /* reset board logic */
- hw->regs[0] = 0;
- break;
-
- case SDLA_S514:
- /* halt the adapter */
- *(char *)hw->vector = S514_CPU_HALT;
- CPU_no = hw->S514_cpu_no[0];
-
- /* disable the PCI IRQ and disable memory access */
- pci_read_config_dword(hw->pci_dev, PCI_INT_CONFIG, &int_config);
- int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A : ~PCI_DISABLE_IRQ_CPU_B;
- pci_write_config_dword(hw->pci_dev, PCI_INT_CONFIG, int_config);
- read_S514_int_stat(hw, &int_status);
- S514_intack(hw, int_status);
- if(CPU_no == S514_CPU_A)
- pci_write_config_dword(hw->pci_dev, PCI_MAP0_DWORD,
- PCI_CPU_A_MEM_DISABLE);
- else
- pci_write_config_dword(hw->pci_dev, PCI_MAP1_DWORD,
- PCI_CPU_B_MEM_DISABLE);
-
- /* free up the allocated virtual memory */
- iounmap((void *)hw->dpmbase);
- iounmap((void *)hw->vector);
- break;
-
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-/*============================================================================
- * Map shared memory window into SDLA address space.
- */
-
-EXPORT_SYMBOL(sdla_mapmem);
-
-int sdla_mapmem (sdlahw_t* hw, unsigned long addr)
-{
- unsigned port = hw->port;
- register int tmp;
-
- switch (hw->type) {
- case SDLA_S502A:
- case SDLA_S502E:
- if (addr < S502_MAXMEM) { /* verify parameter */
- tmp = addr >> 13; /* convert to register mask */
- _OUTB(port + 2, tmp);
- hw->regs[2] = tmp;
- }
- else return -EINVAL;
- break;
-
- case SDLA_S503:
- if (addr < S503_MAXMEM) { /* verify parameter */
- tmp = (hw->regs[0] & 0x8F) | ((addr >> 9) & 0x70);
- _OUTB(port, tmp);
- hw->regs[0] = tmp;
- }
- else return -EINVAL;
- break;
-
- case SDLA_S507:
- if (addr < S507_MAXMEM) {
- if (!(_INB(port) & 0x02))
- return -EIO;
- tmp = addr >> 13; /* convert to register mask */
- _OUTB(port + 2, tmp);
- hw->regs[2] = tmp;
- }
- else return -EINVAL;
- break;
-
- case SDLA_S508:
- if (addr < S508_MAXMEM) {
- tmp = addr >> 13; /* convert to register mask */
- _OUTB(port + 2, tmp);
- hw->regs[2] = tmp;
- }
- else return -EINVAL;
- break;
-
- case SDLA_S514:
- return 0;
-
- default:
- return -EINVAL;
- }
- hw->vector = addr & 0xFFFFE000L;
- return 0;
-}
-
-/*============================================================================
- * Enable interrupt generation.
- */
-
-static int sdla_inten (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- switch (hw->type) {
- case SDLA_S502E:
- /* Note thar interrupt control operations on S502E are allowed
- * only if CPU is enabled (bit 0 of status register is set).
- */
- if (_INB(port) & 0x01) {
- _OUTB(port, 0x02); /* bit1 = 1, bit2 = 0 */
- _OUTB(port, 0x06); /* bit1 = 1, bit2 = 1 */
- hw->regs[0] = 0x06;
- }
- else return -EIO;
- break;
-
- case SDLA_S503:
- tmp = hw->regs[0] | 0x04;
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (!(_INB(port) & 0x02)) /* verify */
- return -EIO;
- break;
-
- case SDLA_S508:
- tmp = hw->regs[0] | 0x10;
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (!(_INB(port + 1) & 0x10)) /* verify */
- return -EIO;
- break;
-
- case SDLA_S502A:
- case SDLA_S507:
- break;
-
- case SDLA_S514:
- break;
-
- default:
- return -EINVAL;
-
- }
- return 0;
-}
-
-/*============================================================================
- * Disable interrupt generation.
- */
-
-#if 0
-int sdla_intde (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- switch (hw->type) {
- case SDLA_S502E:
- /* Notes:
- * 1) interrupt control operations are allowed only if CPU is
- * enabled (bit 0 of status register is set).
- * 2) disabling interrupts using bit 1 of control register
- * causes IRQ line go high, therefore we are going to use
- * 0x04 instead: lower it to inhibit interrupts to PC.
- */
- if (_INB(port) & 0x01) {
- _OUTB(port, hw->regs[0] & ~0x04);
- hw->regs[0] &= ~0x04;
- }
- else return -EIO;
- break;
-
- case SDLA_S503:
- tmp = hw->regs[0] & ~0x04;
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) & 0x02) /* verify */
- return -EIO;
- break;
-
- case SDLA_S508:
- tmp = hw->regs[0] & ~0x10;
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) & 0x10) /* verify */
- return -EIO;
- break;
-
- case SDLA_S502A:
- case SDLA_S507:
- break;
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-#endif /* 0 */
-
-/*============================================================================
- * Acknowledge SDLA hardware interrupt.
- */
-
-static int sdla_intack (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp;
-
- switch (hw->type) {
- case SDLA_S502E:
- /* To acknoledge hardware interrupt we have to toggle bit 3 of
- * control register: \_/
- * Note that interrupt control operations on S502E are allowed
- * only if CPU is enabled (bit 1 of status register is set).
- */
- if (_INB(port) & 0x01) {
- tmp = hw->regs[0] & ~0x04;
- _OUTB(port, tmp);
- tmp |= 0x04;
- _OUTB(port, tmp);
- hw->regs[0] = tmp;
- }
- else return -EIO;
- break;
-
- case SDLA_S503:
- if (_INB(port) & 0x04) {
- tmp = hw->regs[0] & ~0x08;
- _OUTB(port, tmp);
- tmp |= 0x08;
- _OUTB(port, tmp);
- hw->regs[0] = tmp;
- }
- break;
-
- case SDLA_S502A:
- case SDLA_S507:
- case SDLA_S508:
- break;
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-
-/*============================================================================
- * Acknowledge S514 hardware interrupt.
- */
-
-EXPORT_SYMBOL(S514_intack);
-
-void S514_intack (sdlahw_t* hw, u32 int_status)
-{
- pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
-}
-
-
-/*============================================================================
- * Read the S514 hardware interrupt status.
- */
-
-EXPORT_SYMBOL(read_S514_int_stat);
-
-void read_S514_int_stat (sdlahw_t* hw, u32* int_status)
-{
- pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
-}
-
-
-/*============================================================================
- * Generate an interrupt to adapter's CPU.
- */
-
-#if 0
-int sdla_intr (sdlahw_t* hw)
-{
- unsigned port = hw->port;
-
- switch (hw->type) {
- case SDLA_S502A:
- if (!(_INB(port) & 0x40)) {
- _OUTB(port, 0x10); /* issue NMI to CPU */
- hw->regs[0] = 0x10;
- }
- else return -EIO;
- break;
-
- case SDLA_S507:
- if ((_INB(port) & 0x06) == 0x06) {
- _OUTB(port + 3, 0);
- }
- else return -EIO;
- break;
-
- case SDLA_S508:
- if (_INB(port + 1) & 0x02) {
- _OUTB(port, 0x08);
- }
- else return -EIO;
- break;
-
- case SDLA_S502E:
- case SDLA_S503:
- default:
- return -EINVAL;
- }
- return 0;
-}
-#endif /* 0 */
-
-/*============================================================================
- * Execute Adapter Command.
- * o Set exec flag.
- * o Busy-wait until flag is reset.
- * o Return number of loops made, or 0 if command timed out.
- */
-
-EXPORT_SYMBOL(sdla_exec);
-
-int sdla_exec (void* opflag)
-{
- volatile unsigned char* flag = opflag;
- unsigned long tstop;
- int nloops;
-
- if(readb(flag) != 0x00) {
- printk(KERN_INFO
- "WANPIPE: opp flag set on entry to sdla_exec\n");
- return 0;
- }
-
- writeb(0x01, flag);
-
- tstop = SYSTEM_TICK + EXEC_TIMEOUT;
-
- for (nloops = 1; (readb(flag) == 0x01); ++ nloops) {
- unsigned delay = exec_idle;
- while (-- delay); /* delay */
- if (SYSTEM_TICK > tstop) return 0; /* time is up! */
- }
- return nloops;
-}
-
-/*============================================================================
- * Read absolute adapter memory.
- * Transfer data from adapter's memory to data buffer.
- *
- * Note:
- * Care should be taken when crossing dual-port memory window boundary.
- * This function is not atomic, so caller must disable interrupt if
- * interrupt routines are accessing adapter shared memory.
- */
-
-EXPORT_SYMBOL(sdla_peek);
-
-int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
-{
-
- if (addr + len > hw->memory) /* verify arguments */
- return -EINVAL;
-
- if(hw->type == SDLA_S514) { /* copy data for the S514 adapter */
- peek_by_4 ((unsigned long)hw->dpmbase + addr, buf, len);
- return 0;
- }
-
- else { /* copy data for the S508 adapter */
- unsigned long oldvec = hw->vector;
- unsigned winsize = hw->dpmsize;
- unsigned curpos, curlen; /* current offset and block size */
- unsigned long curvec; /* current DPM window vector */
- int err = 0;
-
- while (len && !err) {
- curpos = addr % winsize; /* current window offset */
- curvec = addr - curpos; /* current window vector */
- curlen = (len > (winsize - curpos)) ?
- (winsize - curpos) : len;
- /* Relocate window and copy block of data */
- err = sdla_mapmem(hw, curvec);
- peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
- curlen);
- addr += curlen;
- buf = (char*)buf + curlen;
- len -= curlen;
- }
-
- /* Restore DPM window position */
- sdla_mapmem(hw, oldvec);
- return err;
- }
-}
-
-
-/*============================================================================
- * Read data from adapter's memory to a data buffer in 4-byte chunks.
- * Note that we ensure that the SDLA memory address is on a 4-byte boundary
- * before we begin moving the data in 4-byte chunks.
-*/
-
-static void peek_by_4 (unsigned long src, void* buf, unsigned len)
-{
-
- /* byte copy data until we get to a 4-byte boundary */
- while (len && (src & 0x03)) {
- *(char *)buf ++ = readb(src ++);
- len --;
- }
-
- /* copy data in 4-byte chunks */
- while (len >= 4) {
- *(unsigned long *)buf = readl(src);
- buf += 4;
- src += 4;
- len -= 4;
- }
-
- /* byte copy any remaining data */
- while (len) {
- *(char *)buf ++ = readb(src ++);
- len --;
- }
-}
-
-
-/*============================================================================
- * Write Absolute Adapter Memory.
- * Transfer data from data buffer to adapter's memory.
- *
- * Note:
- * Care should be taken when crossing dual-port memory window boundary.
- * This function is not atomic, so caller must disable interrupt if
- * interrupt routines are accessing adapter shared memory.
- */
-
-EXPORT_SYMBOL(sdla_poke);
-
-int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
-{
-
- if (addr + len > hw->memory) /* verify arguments */
- return -EINVAL;
-
- if(hw->type == SDLA_S514) { /* copy data for the S514 adapter */
- poke_by_4 ((unsigned long)hw->dpmbase + addr, buf, len);
- return 0;
- }
-
- else { /* copy data for the S508 adapter */
- unsigned long oldvec = hw->vector;
- unsigned winsize = hw->dpmsize;
- unsigned curpos, curlen; /* current offset and block size */
- unsigned long curvec; /* current DPM window vector */
- int err = 0;
-
- while (len && !err) {
- curpos = addr % winsize; /* current window offset */
- curvec = addr - curpos; /* current window vector */
- curlen = (len > (winsize - curpos)) ?
- (winsize - curpos) : len;
- /* Relocate window and copy block of data */
- sdla_mapmem(hw, curvec);
- poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
- curlen);
- addr += curlen;
- buf = (char*)buf + curlen;
- len -= curlen;
- }
-
- /* Restore DPM window position */
- sdla_mapmem(hw, oldvec);
- return err;
- }
-}
-
-
-/*============================================================================
- * Write from a data buffer to adapter's memory in 4-byte chunks.
- * Note that we ensure that the SDLA memory address is on a 4-byte boundary
- * before we begin moving the data in 4-byte chunks.
-*/
-
-static void poke_by_4 (unsigned long dest, void* buf, unsigned len)
-{
-
- /* byte copy data until we get to a 4-byte boundary */
- while (len && (dest & 0x03)) {
- writeb (*(char *)buf ++, dest ++);
- len --;
- }
-
- /* copy data in 4-byte chunks */
- while (len >= 4) {
- writel (*(unsigned long *)buf, dest);
- dest += 4;
- buf += 4;
- len -= 4;
- }
-
- /* byte copy any remaining data */
- while (len) {
- writeb (*(char *)buf ++ , dest ++);
- len --;
- }
-}
-
-
-#ifdef DONT_COMPIPLE_THIS
-#endif /* DONT_COMPIPLE_THIS */
-
-/****** Hardware-Specific Functions *****************************************/
-
-/*============================================================================
- * Detect adapter type.
- * o if adapter type is specified then call detection routine for that adapter
- * type. Otherwise call detection routines for every adapter types until
- * adapter is detected.
- *
- * Notes:
- * 1) Detection tests are destructive! Adapter will be left in shutdown state
- * after the test.
- */
-static int sdla_detect (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int err = 0;
-
- if (!port && (hw->type != SDLA_S514))
- return -EFAULT;
-
- switch (hw->type) {
- case SDLA_S502A:
- if (!detect_s502a(port)) err = -ENODEV;
- break;
-
- case SDLA_S502E:
- if (!detect_s502e(port)) err = -ENODEV;
- break;
-
- case SDLA_S503:
- if (!detect_s503(port)) err = -ENODEV;
- break;
-
- case SDLA_S507:
- if (!detect_s507(port)) err = -ENODEV;
- break;
-
- case SDLA_S508:
- if (!detect_s508(port)) err = -ENODEV;
- break;
-
- case SDLA_S514:
- if (!detect_s514(hw)) err = -ENODEV;
- break;
-
- default:
- if (detect_s502a(port))
- hw->type = SDLA_S502A;
- else if (detect_s502e(port))
- hw->type = SDLA_S502E;
- else if (detect_s503(port))
- hw->type = SDLA_S503;
- else if (detect_s507(port))
- hw->type = SDLA_S507;
- else if (detect_s508(port))
- hw->type = SDLA_S508;
- else err = -ENODEV;
- }
- return err;
-}
-
-/*============================================================================
- * Autoselect memory region.
- * o try all available DMP address options from the top down until success.
- */
-static int sdla_autodpm (sdlahw_t* hw)
-{
- int i, err = -EINVAL;
- unsigned* opt;
-
- switch (hw->type) {
- case SDLA_S502A:
- opt = s502a_dpmbase_options;
- break;
-
- case SDLA_S502E:
- case SDLA_S503:
- case SDLA_S508:
- opt = s508_dpmbase_options;
- break;
-
- case SDLA_S507:
- opt = s507_dpmbase_options;
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Start testing from 8th position, address
- * 0xC8000 from the 508 address table.
- * We don't want to test A**** addresses, since
- * they are usually used for Video */
- for (i = 8; i <= opt[0] && err; i++) {
- hw->dpmbase = phys_to_virt(opt[i]);
- err = sdla_setdpm(hw);
- }
- return err;
-}
-
-/*============================================================================
- * Set up adapter dual-port memory window.
- * o shut down adapter
- * o make sure that no physical memory exists in this region, i.e entire
- * region reads 0xFF and is not writable when adapter is shut down.
- * o initialize adapter hardware
- * o make sure that region is usable with SDLA card, i.e. we can write to it
- * when adapter is configured.
- */
-static int sdla_setdpm (sdlahw_t* hw)
-{
- int err;
-
- /* Shut down card and verify memory region */
- sdla_down(hw);
- if (check_memregion(hw->dpmbase, hw->dpmsize))
- return -EINVAL;
-
- /* Initialize adapter and test on-board memory segment by segment.
- * If memory size appears to be less than shared memory window size,
- * assume that memory region is unusable.
- */
- err = sdla_init(hw);
- if (err) return err;
-
- if (sdla_memtest(hw) < hw->dpmsize) { /* less than window size */
- sdla_down(hw);
- return -EIO;
- }
- sdla_mapmem(hw, 0L); /* set window vector at bottom */
- return 0;
-}
-
-/*============================================================================
- * Load adapter from the memory image of the SDLA firmware module.
- * o verify firmware integrity and compatibility
- * o start adapter up
- */
-static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len)
-{
-
- int i;
-
- /* Verify firmware signature */
- if (strcmp(sfm->signature, SFM_SIGNATURE)) {
- printk(KERN_INFO "%s: not SDLA firmware!\n",
- modname);
- return -EINVAL;
- }
-
- /* Verify firmware module format version */
- if (sfm->version != SFM_VERSION) {
- printk(KERN_INFO
- "%s: firmware format %u rejected! Expecting %u.\n",
- modname, sfm->version, SFM_VERSION);
- return -EINVAL;
- }
-
- /* Verify firmware module length and checksum */
- if ((len - offsetof(sfm_t, image) != sfm->info.codesize) ||
- (checksum((void*)&sfm->info,
- sizeof(sfm_info_t) + sfm->info.codesize) != sfm->checksum)) {
- printk(KERN_INFO "%s: firmware corrupted!\n", modname);
- return -EINVAL;
- }
-
- /* Announce */
- printk(KERN_INFO "%s: loading %s (ID=%u)...\n", modname,
- (sfm->descr[0] != '\0') ? sfm->descr : "unknown firmware",
- sfm->info.codeid);
-
- if(hw->type == SDLA_S514)
- printk(KERN_INFO "%s: loading S514 adapter, CPU %c\n",
- modname, hw->S514_cpu_no[0]);
-
- /* Scan through the list of compatible adapters and make sure our
- * adapter type is listed.
- */
- for (i = 0;
- (i < SFM_MAX_SDLA) && (sfm->info.adapter[i] != hw->type);
- ++i);
-
- if (i == SFM_MAX_SDLA) {
- printk(KERN_INFO "%s: firmware is not compatible with S%u!\n",
- modname, hw->type);
- return -EINVAL;
- }
-
-
- /* Make sure there is enough on-board memory */
- if (hw->memory < sfm->info.memsize) {
- printk(KERN_INFO
- "%s: firmware needs %lu bytes of on-board memory!\n",
- modname, sfm->info.memsize);
- return -EINVAL;
- }
-
- /* Move code onto adapter */
- if (sdla_poke(hw, sfm->info.codeoffs, sfm->image, sfm->info.codesize)) {
- printk(KERN_INFO "%s: failed to load code segment!\n",
- modname);
- return -EIO;
- }
-
- /* Prepare boot-time configuration data and kick-off CPU */
- sdla_bootcfg(hw, &sfm->info);
- if (sdla_start(hw, sfm->info.startoffs)) {
- printk(KERN_INFO "%s: Damn... Adapter won't start!\n",
- modname);
- return -EIO;
- }
-
- /* position DPM window over the mailbox and enable interrupts */
- if (sdla_mapmem(hw, sfm->info.winoffs) || sdla_inten(hw)) {
- printk(KERN_INFO "%s: adapter hardware failure!\n",
- modname);
- return -EIO;
- }
- hw->fwid = sfm->info.codeid; /* set firmware ID */
- return 0;
-}
-
-/*============================================================================
- * Initialize SDLA hardware: setup memory window, IRQ, etc.
- */
-static int sdla_init (sdlahw_t* hw)
-{
- int i;
-
- for (i = 0; i < SDLA_MAXIORANGE; ++i)
- hw->regs[i] = 0;
-
- switch (hw->type) {
- case SDLA_S502A: return init_s502a(hw);
- case SDLA_S502E: return init_s502e(hw);
- case SDLA_S503: return init_s503(hw);
- case SDLA_S507: return init_s507(hw);
- case SDLA_S508: return init_s508(hw);
- }
- return -EINVAL;
-}
-
-/*============================================================================
- * Test adapter on-board memory.
- * o slide DPM window from the bottom up and test adapter memory segment by
- * segment.
- * Return adapter memory size.
- */
-static unsigned long sdla_memtest (sdlahw_t* hw)
-{
- unsigned long memsize;
- unsigned winsize;
-
- for (memsize = 0, winsize = hw->dpmsize;
- !sdla_mapmem(hw, memsize) &&
- (test_memregion(hw->dpmbase, winsize) == winsize)
- ;
- memsize += winsize)
- ;
- hw->memory = memsize;
- return memsize;
-}
-
-/*============================================================================
- * Prepare boot-time firmware configuration data.
- * o position DPM window
- * o initialize configuration data area
- */
-static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo)
-{
- unsigned char* data;
-
- if (!sfminfo->datasize) return 0; /* nothing to do */
-
- if (sdla_mapmem(hw, sfminfo->dataoffs) != 0)
- return -EIO;
-
- if(hw->type == SDLA_S514)
- data = (void*)(hw->dpmbase + sfminfo->dataoffs);
- else
- data = (void*)((u8 *)hw->dpmbase +
- (sfminfo->dataoffs - hw->vector));
-
- memset_io (data, 0, sfminfo->datasize);
-
- writeb (make_config_byte(hw), &data[0x00]);
-
- switch (sfminfo->codeid) {
- case SFID_X25_502:
- case SFID_X25_508:
- writeb (3, &data[0x01]); /* T1 timer */
- writeb (10, &data[0x03]); /* N2 */
- writeb (7, &data[0x06]); /* HDLC window size */
- writeb (1, &data[0x0B]); /* DTE */
- writeb (2, &data[0x0C]); /* X.25 packet window size */
- writew (128, &data[0x0D]); /* default X.25 data size */
- writew (128, &data[0x0F]); /* maximum X.25 data size */
- break;
- }
- return 0;
-}
-
-/*============================================================================
- * Prepare configuration byte identifying adapter type and CPU clock rate.
- */
-static unsigned char make_config_byte (sdlahw_t* hw)
-{
- unsigned char byte = 0;
-
- switch (hw->pclk) {
- case 5000: byte = 0x01; break;
- case 7200: byte = 0x02; break;
- case 8000: byte = 0x03; break;
- case 10000: byte = 0x04; break;
- case 16000: byte = 0x05; break;
- }
-
- switch (hw->type) {
- case SDLA_S502E: byte |= 0x80; break;
- case SDLA_S503: byte |= 0x40; break;
- }
- return byte;
-}
-
-/*============================================================================
- * Start adapter's CPU.
- * o calculate a pointer to adapter's cold boot entry point
- * o position DPM window
- * o place boot instruction (jp addr) at cold boot entry point
- * o start CPU
- */
-static int sdla_start (sdlahw_t* hw, unsigned addr)
-{
- unsigned port = hw->port;
- unsigned char *bootp;
- int err, tmp, i;
-
- if (!port && (hw->type != SDLA_S514)) return -EFAULT;
-
- switch (hw->type) {
- case SDLA_S502A:
- bootp = hw->dpmbase;
- bootp += 0x66;
- break;
-
- case SDLA_S502E:
- case SDLA_S503:
- case SDLA_S507:
- case SDLA_S508:
- case SDLA_S514:
- bootp = hw->dpmbase;
- break;
-
- default:
- return -EINVAL;
- }
-
- err = sdla_mapmem(hw, 0);
- if (err) return err;
-
- writeb (0xC3, bootp); /* Z80: 'jp' opcode */
- bootp ++;
- writew (addr, bootp);
-
- switch (hw->type) {
- case SDLA_S502A:
- _OUTB(port, 0x10); /* issue NMI to CPU */
- hw->regs[0] = 0x10;
- break;
-
- case SDLA_S502E:
- _OUTB(port + 3, 0x01); /* start CPU */
- hw->regs[3] = 0x01;
- for (i = 0; i < SDLA_IODELAY; ++i);
- if (_INB(port) & 0x01) { /* verify */
- /*
- * Enabling CPU changes functionality of the
- * control register, so we have to reset its
- * mirror.
- */
- _OUTB(port, 0); /* disable interrupts */
- hw->regs[0] = 0;
- }
- else return -EIO;
- break;
-
- case SDLA_S503:
- tmp = hw->regs[0] | 0x09; /* set bits 0 and 3 */
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i);
- if (!(_INB(port) & 0x01)) /* verify */
- return -EIO;
- break;
-
- case SDLA_S507:
- tmp = hw->regs[0] | 0x02;
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i);
- if (!(_INB(port) & 0x04)) /* verify */
- return -EIO;
- break;
-
- case SDLA_S508:
- tmp = hw->regs[0] | 0x02;
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i);
- if (!(_INB(port + 1) & 0x02)) /* verify */
- return -EIO;
- break;
-
- case SDLA_S514:
- writeb (S514_CPU_START, hw->vector);
- break;
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-/*============================================================================
- * Initialize S502A adapter.
- */
-static int init_s502a (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- if (!detect_s502a(port))
- return -ENODEV;
-
- hw->regs[0] = 0x08;
- hw->regs[1] = 0xFF;
-
- /* Verify configuration options */
- i = get_option_index(s502a_dpmbase_options, virt_to_phys(hw->dpmbase));
- if (i == 0)
- return -EINVAL;
-
- tmp = s502a_hmcr[i - 1];
- switch (hw->dpmsize) {
- case 0x2000:
- tmp |= 0x01;
- break;
-
- case 0x10000L:
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Setup dual-port memory window (this also enables memory access) */
- _OUTB(port + 1, tmp);
- hw->regs[1] = tmp;
- hw->regs[0] = 0x08;
- return 0;
-}
-
-/*============================================================================
- * Initialize S502E adapter.
- */
-static int init_s502e (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- if (!detect_s502e(port))
- return -ENODEV;
-
- /* Verify configuration options */
- i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
- if (i == 0)
- return -EINVAL;
-
- tmp = s502e_hmcr[i - 1];
- switch (hw->dpmsize) {
- case 0x2000:
- tmp |= 0x01;
- break;
-
- case 0x10000L:
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Setup dual-port memory window */
- _OUTB(port + 1, tmp);
- hw->regs[1] = tmp;
-
- /* Enable memory access */
- _OUTB(port, 0x02);
- hw->regs[0] = 0x02;
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- return (_INB(port) & 0x02) ? 0 : -EIO;
-}
-
-/*============================================================================
- * Initialize S503 adapter.
- * ---------------------------------------------------------------------------
- */
-static int init_s503 (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- if (!detect_s503(port))
- return -ENODEV;
-
- /* Verify configuration options */
- i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
- if (i == 0)
- return -EINVAL;
-
- tmp = s502e_hmcr[i - 1];
- switch (hw->dpmsize) {
- case 0x2000:
- tmp |= 0x01;
- break;
-
- case 0x10000L:
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Setup dual-port memory window */
- _OUTB(port + 1, tmp);
- hw->regs[1] = tmp;
-
- /* Enable memory access */
- _OUTB(port, 0x02);
- hw->regs[0] = 0x02; /* update mirror */
- return 0;
-}
-
-/*============================================================================
- * Initialize S507 adapter.
- */
-static int init_s507 (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- if (!detect_s507(port))
- return -ENODEV;
-
- /* Verify configuration options */
- i = get_option_index(s507_dpmbase_options, virt_to_phys(hw->dpmbase));
- if (i == 0)
- return -EINVAL;
-
- tmp = s507_hmcr[i - 1];
- switch (hw->dpmsize) {
- case 0x2000:
- tmp |= 0x01;
- break;
-
- case 0x10000L:
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Enable adapter's logic */
- _OUTB(port, 0x01);
- hw->regs[0] = 0x01;
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (!(_INB(port) & 0x20))
- return -EIO;
-
- /* Setup dual-port memory window */
- _OUTB(port + 1, tmp);
- hw->regs[1] = tmp;
-
- /* Enable memory access */
- tmp = hw->regs[0] | 0x04;
- if (hw->irq) {
- i = get_option_index(s508_irq_options, hw->irq);
- if (i) tmp |= s507_irqmask[i - 1];
- }
- _OUTB(port, tmp);
- hw->regs[0] = tmp; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- return (_INB(port) & 0x08) ? 0 : -EIO;
-}
-
-/*============================================================================
- * Initialize S508 adapter.
- */
-static int init_s508 (sdlahw_t* hw)
-{
- unsigned port = hw->port;
- int tmp, i;
-
- if (!detect_s508(port))
- return -ENODEV;
-
- /* Verify configuration options */
- i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
- if (i == 0)
- return -EINVAL;
-
- /* Setup memory configuration */
- tmp = s508_hmcr[i - 1];
- _OUTB(port + 1, tmp);
- hw->regs[1] = tmp;
-
- /* Enable memory access */
- _OUTB(port, 0x04);
- hw->regs[0] = 0x04; /* update mirror */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- return (_INB(port + 1) & 0x04) ? 0 : -EIO;
-}
-
-/*============================================================================
- * Detect S502A adapter.
- * Following tests are used to detect S502A adapter:
- * 1. All registers other than status (BASE) should read 0xFF
- * 2. After writing 00001000b to control register, status register should
- * read 01000000b.
- * 3. After writing 0 to control register, status register should still
- * read 01000000b.
- * 4. After writing 00000100b to control register, status register should
- * read 01000100b.
- * Return 1 if detected o.k. or 0 if failed.
- * Note: This test is destructive! Adapter will be left in shutdown
- * state after the test.
- */
-static int detect_s502a (int port)
-{
- int i, j;
-
- if (!get_option_index(s502_port_options, port))
- return 0;
-
- for (j = 1; j < SDLA_MAXIORANGE; ++j) {
- if (_INB(port + j) != 0xFF)
- return 0;
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- }
-
- _OUTB(port, 0x08); /* halt CPU */
- _OUTB(port, 0x08);
- _OUTB(port, 0x08);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0x40)
- return 0;
- _OUTB(port, 0x00);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0x40)
- return 0;
- _OUTB(port, 0x04);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0x44)
- return 0;
-
- /* Reset adapter */
- _OUTB(port, 0x08);
- _OUTB(port, 0x08);
- _OUTB(port, 0x08);
- _OUTB(port + 1, 0xFF);
- return 1;
-}
-
-/*============================================================================
- * Detect S502E adapter.
- * Following tests are used to verify adapter presence:
- * 1. All registers other than status (BASE) should read 0xFF.
- * 2. After writing 0 to CPU control register (BASE+3), status register
- * (BASE) should read 11111000b.
- * 3. After writing 00000100b to port BASE (set bit 2), status register
- * (BASE) should read 11111100b.
- * Return 1 if detected o.k. or 0 if failed.
- * Note: This test is destructive! Adapter will be left in shutdown
- * state after the test.
- */
-static int detect_s502e (int port)
-{
- int i, j;
-
- if (!get_option_index(s502_port_options, port))
- return 0;
- for (j = 1; j < SDLA_MAXIORANGE; ++j) {
- if (_INB(port + j) != 0xFF)
- return 0;
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- }
-
- _OUTB(port + 3, 0); /* CPU control reg. */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0xF8) /* read status */
- return 0;
- _OUTB(port, 0x04); /* set bit 2 */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0xFC) /* verify */
- return 0;
-
- /* Reset adapter */
- _OUTB(port, 0);
- return 1;
-}
-
-/*============================================================================
- * Detect s503 adapter.
- * Following tests are used to verify adapter presence:
- * 1. All registers other than status (BASE) should read 0xFF.
- * 2. After writing 0 to control register (BASE), status register (BASE)
- * should read 11110000b.
- * 3. After writing 00000100b (set bit 2) to control register (BASE),
- * status register should read 11110010b.
- * Return 1 if detected o.k. or 0 if failed.
- * Note: This test is destructive! Adapter will be left in shutdown
- * state after the test.
- */
-static int detect_s503 (int port)
-{
- int i, j;
-
- if (!get_option_index(s503_port_options, port))
- return 0;
- for (j = 1; j < SDLA_MAXIORANGE; ++j) {
- if (_INB(port + j) != 0xFF)
- return 0;
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- }
-
- _OUTB(port, 0); /* reset control reg.*/
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0xF0) /* read status */
- return 0;
- _OUTB(port, 0x04); /* set bit 2 */
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if (_INB(port) != 0xF2) /* verify */
- return 0;
-
- /* Reset adapter */
- _OUTB(port, 0);
- return 1;
-}
-
-/*============================================================================
- * Detect s507 adapter.
- * Following tests are used to detect s507 adapter:
- * 1. All ports should read the same value.
- * 2. After writing 0x00 to control register, status register should read
- * ?011000?b.
- * 3. After writing 0x01 to control register, status register should read
- * ?011001?b.
- * Return 1 if detected o.k. or 0 if failed.
- * Note: This test is destructive! Adapter will be left in shutdown
- * state after the test.
- */
-static int detect_s507 (int port)
-{
- int tmp, i, j;
-
- if (!get_option_index(s508_port_options, port))
- return 0;
- tmp = _INB(port);
- for (j = 1; j < S507_IORANGE; ++j) {
- if (_INB(port + j) != tmp)
- return 0;
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- }
-
- _OUTB(port, 0x00);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if ((_INB(port) & 0x7E) != 0x30)
- return 0;
- _OUTB(port, 0x01);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if ((_INB(port) & 0x7E) != 0x32)
- return 0;
-
- /* Reset adapter */
- _OUTB(port, 0x00);
- return 1;
-}
-
-/*============================================================================
- * Detect s508 adapter.
- * Following tests are used to detect s508 adapter:
- * 1. After writing 0x00 to control register, status register should read
- * ??000000b.
- * 2. After writing 0x10 to control register, status register should read
- * ??010000b
- * Return 1 if detected o.k. or 0 if failed.
- * Note: This test is destructive! Adapter will be left in shutdown
- * state after the test.
- */
-static int detect_s508 (int port)
-{
- int i;
-
- if (!get_option_index(s508_port_options, port))
- return 0;
- _OUTB(port, 0x00);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if ((_INB(port + 1) & 0x3F) != 0x00)
- return 0;
- _OUTB(port, 0x10);
- for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
- if ((_INB(port + 1) & 0x3F) != 0x10)
- return 0;
-
- /* Reset adapter */
- _OUTB(port, 0x00);
- return 1;
-}
-
-/*============================================================================
- * Detect s514 PCI adapter.
- * Return 1 if detected o.k. or 0 if failed.
- * Note: This test is destructive! Adapter will be left in shutdown
- * state after the test.
- */
-static int detect_s514 (sdlahw_t* hw)
-{
- unsigned char CPU_no, slot_no, auto_slot_cfg;
- int number_S514_cards = 0;
- u32 S514_mem_base_addr = 0;
- u32 ut_u32;
- struct pci_dev *pci_dev;
-
-
-#ifndef CONFIG_PCI
- printk(KERN_INFO "%s: Linux not compiled for PCI usage!\n", modname);
- return 0;
-#endif
-
- /*
- The 'setup()' procedure in 'sdlamain.c' passes the CPU number and the
- slot number defined in 'router.conf' via the 'port' definition.
- */
- CPU_no = hw->S514_cpu_no[0];
- slot_no = hw->S514_slot_no;
- auto_slot_cfg = hw->auto_pci_cfg;
-
- if (auto_slot_cfg){
- printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot=Auto\n",
- modname, CPU_no);
-
- }else{
- printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot #%d\n",
- modname, CPU_no, slot_no);
- }
-
- /* check to see that CPU A or B has been selected in 'router.conf' */
- switch(CPU_no) {
- case S514_CPU_A:
- case S514_CPU_B:
- break;
-
- default:
- printk(KERN_INFO "%s: S514 CPU definition invalid.\n",
- modname);
- printk(KERN_INFO "Must be 'A' or 'B'\n");
- return 0;
- }
-
- number_S514_cards = find_s514_adapter(hw, 0);
- if(!number_S514_cards)
- return 0;
-
- /* we are using a single S514 adapter with a slot of 0 so re-read the */
- /* location of this adapter */
- if((number_S514_cards == 1) && auto_slot_cfg) {
- number_S514_cards = find_s514_adapter(hw, 1);
- if(!number_S514_cards) {
- printk(KERN_INFO "%s: Error finding PCI card\n",
- modname);
- return 0;
- }
- }
-
- pci_dev = hw->pci_dev;
- /* read the physical memory base address */
- S514_mem_base_addr = (CPU_no == S514_CPU_A) ?
- (pci_dev->resource[1].start) :
- (pci_dev->resource[2].start);
-
- printk(KERN_INFO "%s: S514 PCI memory at 0x%X\n",
- modname, S514_mem_base_addr);
- if(!S514_mem_base_addr) {
- if(CPU_no == S514_CPU_B)
- printk(KERN_INFO "%s: CPU #B not present on the card\n", modname);
- else
- printk(KERN_INFO "%s: No PCI memory allocated to card\n", modname);
- return 0;
- }
-
- /* enable the PCI memory */
- pci_read_config_dword(pci_dev,
- (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
- &ut_u32);
- pci_write_config_dword(pci_dev,
- (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
- (ut_u32 | PCI_MEMORY_ENABLE));
-
- /* check the IRQ allocated and enable IRQ usage */
- if(!(hw->irq = pci_dev->irq)) {
- printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n",
- modname);
- return 0;
- }
-
- /* BUG FIX : Mar 6 2000
- * On a initial loading of the card, we must check
- * and clear PCI interrupt bits, due to a reset
- * problem on some other boards. i.e. An interrupt
- * might be pending, even after system bootup,
- * in which case, when starting wanrouter the machine
- * would crash.
- */
- if (init_pci_slot(hw))
- return 0;
-
- pci_read_config_dword(pci_dev, PCI_INT_CONFIG, &ut_u32);
- ut_u32 |= (CPU_no == S514_CPU_A) ?
- PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B;
- pci_write_config_dword(pci_dev, PCI_INT_CONFIG, ut_u32);
-
- printk(KERN_INFO "%s: IRQ %d allocated to the S514 card\n",
- modname, hw->irq);
-
- /* map the physical PCI memory to virtual memory */
- hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr,
- (unsigned long)MAX_SIZEOF_S514_MEMORY);
- /* map the physical control register memory to virtual memory */
- hw->vector = (unsigned long)ioremap(
- (unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE),
- (unsigned long)16);
-
- if(!hw->dpmbase || !hw->vector) {
- printk(KERN_INFO "%s: PCI virtual memory allocation failed\n",
- modname);
- return 0;
- }
-
- /* halt the adapter */
- writeb (S514_CPU_HALT, hw->vector);
-
- return 1;
-}
-
-/*============================================================================
- * Find the S514 PCI adapter in the PCI bus.
- * Return the number of S514 adapters found (0 if no adapter found).
- */
-static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card)
-{
- unsigned char slot_no;
- int number_S514_cards = 0;
- char S514_found_in_slot = 0;
- u16 PCI_subsys_vendor;
-
- struct pci_dev *pci_dev = NULL;
-
- slot_no = hw->S514_slot_no;
-
- while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
- != NULL) {
-
- pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD,
- &PCI_subsys_vendor);
-
- if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
- continue;
-
- hw->pci_dev = pci_dev;
-
- if(find_first_S514_card)
- return(1);
-
- number_S514_cards ++;
-
- printk(KERN_INFO
- "%s: S514 card found, slot #%d (devfn 0x%X)\n",
- modname, ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
- pci_dev->devfn);
-
- if (hw->auto_pci_cfg){
- hw->S514_slot_no = ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK);
- slot_no = hw->S514_slot_no;
-
- }else if (((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK) == slot_no){
- S514_found_in_slot = 1;
- break;
- }
- }
-
- /* if no S514 adapter has been found, then exit */
- if (!number_S514_cards) {
- printk(KERN_INFO "%s: Error, no S514 adapters found\n", modname);
- return 0;
- }
- /* if more than one S514 card has been found, then the user must have */ /* defined a slot number so that the correct adapter is used */
- else if ((number_S514_cards > 1) && hw->auto_pci_cfg) {
- printk(KERN_INFO "%s: Error, PCI Slot autodetect Failed! \n"
- "%s: More than one S514 adapter found.\n"
- "%s: Disable the Autodetect feature and supply\n"
- "%s: the PCISLOT numbers for each card.\n",
- modname,modname,modname,modname);
- return 0;
- }
- /* if the user has specified a slot number and the S514 adapter has */
- /* not been found in that slot, then exit */
- else if (!hw->auto_pci_cfg && !S514_found_in_slot) {
- printk(KERN_INFO
- "%s: Error, S514 card not found in specified slot #%d\n",
- modname, slot_no);
- return 0;
- }
-
- return (number_S514_cards);
-}
-
-
-
-/******* Miscellaneous ******************************************************/
-
-/*============================================================================
- * Calibrate SDLA memory access delay.
- * Count number of idle loops made within 1 second and then calculate the
- * number of loops that should be made to achive desired delay.
- */
-static int calibrate_delay (int mks)
-{
- unsigned int delay;
- unsigned long stop;
-
- for (delay = 0, stop = SYSTEM_TICK + HZ; SYSTEM_TICK < stop; ++delay);
- return (delay/(1000000L/mks) + 1);
-}
-
-/*============================================================================
- * Get option's index into the options list.
- * Return option's index (1 .. N) or zero if option is invalid.
- */
-static int get_option_index (unsigned* optlist, unsigned optval)
-{
- int i;
-
- for (i = 1; i <= optlist[0]; ++i)
- if ( optlist[i] == optval)
- return i;
- return 0;
-}
-
-/*============================================================================
- * Check memory region to see if it's available.
- * Return: 0 ok.
- */
-static unsigned check_memregion (void* ptr, unsigned len)
-{
- volatile unsigned char* p = ptr;
-
- for (; len && (readb (p) == 0xFF); --len, ++p) {
- writeb (0, p); /* attempt to write 0 */
- if (readb(p) != 0xFF) { /* still has to read 0xFF */
- writeb (0xFF, p);/* restore original value */
- break; /* not good */
- }
- }
-
- return len;
-}
-
-/*============================================================================
- * Test memory region.
- * Return: size of the region that passed the test.
- * Note: Region size must be multiple of 2 !
- */
-static unsigned test_memregion (void* ptr, unsigned len)
-{
- volatile unsigned short* w_ptr;
- unsigned len_w = len >> 1; /* region len in words */
- unsigned i;
-
- for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
- writew (0xAA55, w_ptr);
-
- for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
- if (readw (w_ptr) != 0xAA55) {
- len_w = i;
- break;
- }
-
- for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
- writew (0x55AA, w_ptr);
-
- for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
- if (readw(w_ptr) != 0x55AA) {
- len_w = i;
- break;
- }
-
- for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
- writew (0, w_ptr);
-
- return len_w << 1;
-}
-
-/*============================================================================
- * Calculate 16-bit CRC using CCITT polynomial.
- */
-static unsigned short checksum (unsigned char* buf, unsigned len)
-{
- unsigned short crc = 0;
- unsigned mask, flag;
-
- for (; len; --len, ++buf) {
- for (mask = 0x80; mask; mask >>= 1) {
- flag = (crc & 0x8000);
- crc <<= 1;
- crc |= ((*buf & mask) ? 1 : 0);
- if (flag) crc ^= 0x1021;
- }
- }
- return crc;
-}
-
-static int init_pci_slot(sdlahw_t *hw)
-{
-
- u32 int_status;
- int volatile found=0;
- int i=0;
-
- /* Check if this is a very first load for a specific
- * pci card. If it is, clear the interrput bits, and
- * set the flag indicating that this card was initialized.
- */
-
- for (i=0; (i<MAX_S514_CARDS) && !found; i++){
- if (pci_slot_ar[i] == hw->S514_slot_no){
- found=1;
- break;
- }
- if (pci_slot_ar[i] == 0xFF){
- break;
- }
- }
-
- if (!found){
- read_S514_int_stat(hw,&int_status);
- S514_intack(hw,int_status);
- if (i == MAX_S514_CARDS){
- printk(KERN_INFO "%s: Critical Error !!!\n",modname);
- printk(KERN_INFO
- "%s: Number of Sangoma PCI cards exceeded maximum limit.\n",
- modname);
- printk(KERN_INFO "Please contact Sangoma Technologies\n");
- return 1;
- }
- pci_slot_ar[i] = hw->S514_slot_no;
- }
- return 0;
-}
-
-static int pci_probe(sdlahw_t *hw)
-{
-
- unsigned char slot_no;
- int number_S514_cards = 0;
- u16 PCI_subsys_vendor;
- u16 PCI_card_type;
-
- struct pci_dev *pci_dev = NULL;
- struct pci_bus *bus = NULL;
-
- slot_no = 0;
-
- while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
- != NULL) {
-
- pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD,
- &PCI_subsys_vendor);
-
- if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
- continue;
-
- pci_read_config_word(pci_dev, PCI_CARD_TYPE,
- &PCI_card_type);
-
- bus = pci_dev->bus;
-
- /* A dual cpu card can support up to 4 physical connections,
- * where a single cpu card can support up to 2 physical
- * connections. The FT1 card can only support a single
- * connection, however we cannot distinguish between a Single
- * CPU card and an FT1 card. */
- if (PCI_card_type == S514_DUAL_CPU){
- number_S514_cards += 4;
- printk(KERN_INFO
- "wanpipe: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n",
- bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
- pci_dev->irq);
- }else{
- number_S514_cards += 2;
- printk(KERN_INFO
- "wanpipe: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n",
- bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
- pci_dev->irq);
- }
- }
-
- return number_S514_cards;
-
-}
-
-
-
-EXPORT_SYMBOL(wanpipe_hw_probe);
-
-unsigned wanpipe_hw_probe(void)
-{
- sdlahw_t hw;
- unsigned* opt = s508_port_options;
- unsigned cardno=0;
- int i;
-
- memset(&hw, 0, sizeof(hw));
-
- for (i = 1; i <= opt[0]; i++) {
- if (detect_s508(opt[i])){
- /* S508 card can support up to two physical links */
- cardno+=2;
- printk(KERN_INFO "wanpipe: S508-ISA card found, port 0x%x\n",opt[i]);
- }
- }
-
- #ifdef CONFIG_PCI
- hw.S514_slot_no = 0;
- cardno += pci_probe(&hw);
- #else
- printk(KERN_INFO "wanpipe: Warning, Kernel not compiled for PCI support!\n");
- printk(KERN_INFO "wanpipe: PCI Hardware Probe Failed!\n");
- #endif
-
- return cardno;
-}
-
-/****** End *****************************************************************/
diff --git a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c
deleted file mode 100644
index 7a8b22a7ea3..00000000000
--- a/drivers/net/wan/sdlamain.c
+++ /dev/null
@@ -1,1346 +0,0 @@
-/****************************************************************************
-* sdlamain.c WANPIPE(tm) Multiprotocol WAN Link Driver. Main module.
-*
-* Author: Nenad Corbic <ncorbic@sangoma.com>
-* Gideon Hack
-*
-* Copyright: (c) 1995-2000 Sangoma Technologies 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.
-* ============================================================================
-* Dec 22, 2000 Nenad Corbic Updated for 2.4.X kernels.
-* Removed the polling routine.
-* Nov 13, 2000 Nenad Corbic Added hw probing on module load and dynamic
-* device allocation.
-* Nov 7, 2000 Nenad Corbic Fixed the Multi-Port PPP for kernels
-* 2.2.16 and above.
-* Aug 2, 2000 Nenad Corbic Block the Multi-Port PPP from running on
-* kernels 2.2.16 or greater. The SyncPPP
-* has changed.
-* Jul 25, 2000 Nenad Corbic Updated the Piggiback support for MultPPPP.
-* Jul 13, 2000 Nenad Corbic Added Multi-PPP support.
-* Feb 02, 2000 Nenad Corbic Fixed up piggyback probing and selection.
-* Sep 23, 1999 Nenad Corbic Added support for SMP
-* Sep 13, 1999 Nenad Corbic Each port is treated as a separate device.
-* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
-* Updates for Linux 2.2.X kernels.
-* Sep 17, 1998 Jaspreet Singh Updated for 2.1.121+ kernel
-* Nov 28, 1997 Jaspreet Singh Changed DRV_RELEASE to 1
-* Nov 10, 1997 Jaspreet Singh Changed sti() to restore_flags();
-* Nov 06, 1997 Jaspreet Singh Changed DRV_VERSION to 4 and DRV_RELEASE to 0
-* Oct 20, 1997 Jaspreet Singh Modified sdla_isr routine so that card->in_isr
-* assignments are taken out and placed in the
-* sdla_ppp.c, sdla_fr.c and sdla_x25.c isr
-* routines. Took out 'wandev->tx_int_enabled' and
-* replaced it with 'wandev->enable_tx_int'.
-* May 29, 1997 Jaspreet Singh Flow Control Problem
-* added "wandev->tx_int_enabled=1" line in the
-* init module. This line initializes the flag for
-* preventing Interrupt disabled with device set to
-* busy
-* Jan 15, 1997 Gene Kozin Version 3.1.0
-* o added UDP management stuff
-* Jan 02, 1997 Gene Kozin Initial version.
-*****************************************************************************/
-
-#include <linux/config.h> /* OS configuration options */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/init.h>
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/module.h> /* support for loadable modules */
-#include <linux/ioport.h> /* request_region(), release_region() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/rcupdate.h>
-
-#include <linux/in.h>
-#include <asm/io.h> /* phys_to_virt() */
-#include <linux/pci.h>
-#include <linux/sdlapci.h>
-#include <linux/if_wanpipe_common.h>
-
-#include <asm/uaccess.h> /* kernel <-> user copy */
-#include <linux/inetdevice.h>
-
-#include <linux/ip.h>
-#include <net/route.h>
-
-#define KMEM_SAFETYZONE 8
-
-
-#ifndef CONFIG_WANPIPE_FR
- #define wpf_init(a,b) (-EPROTONOSUPPORT)
-#endif
-
-#ifndef CONFIG_WANPIPE_CHDLC
- #define wpc_init(a,b) (-EPROTONOSUPPORT)
-#endif
-
-#ifndef CONFIG_WANPIPE_X25
- #define wpx_init(a,b) (-EPROTONOSUPPORT)
-#endif
-
-#ifndef CONFIG_WANPIPE_PPP
- #define wpp_init(a,b) (-EPROTONOSUPPORT)
-#endif
-
-#ifndef CONFIG_WANPIPE_MULTPPP
- #define wsppp_init(a,b) (-EPROTONOSUPPORT)
-#endif
-
-
-/***********FOR DEBUGGING PURPOSES*********************************************
-static void * dbg_kmalloc(unsigned int size, int prio, int line) {
- int i = 0;
- void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio);
- char * c1 = v;
- c1 += sizeof(unsigned int);
- *((unsigned int *)v) = size;
-
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D';
- c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F';
- c1 += 8;
- }
- c1 += size;
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G';
- c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L';
- c1 += 8;
- }
- v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8;
- printk(KERN_INFO "line %d kmalloc(%d,%d) = %p\n",line,size,prio,v);
- return v;
-}
-static void dbg_kfree(void * v, int line) {
- unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8));
- unsigned int size = *sp;
- char * c1 = ((char *)v) - KMEM_SAFETYZONE*8;
- int i = 0;
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- if ( c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D'
- || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') {
- printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v);
- printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
- c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
- }
- c1 += 8;
- }
- c1 += size;
- for (i = 0; i < KMEM_SAFETYZONE; i++) {
- if ( c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G'
- || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L'
- ) {
- printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v);
- printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
- c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
- }
- c1 += 8;
- }
- printk(KERN_INFO "line %d kfree(%p)\n",line,v);
- v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8);
- kfree(v);
-}
-
-#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)
-#define kfree(x) dbg_kfree(x,__LINE__)
-******************************************************************************/
-
-
-
-/****** Defines & Macros ****************************************************/
-
-#ifdef _DEBUG_
-#define STATIC
-#else
-#define STATIC static
-#endif
-
-#define DRV_VERSION 5 /* version number */
-#define DRV_RELEASE 0 /* release (minor version) number */
-#define MAX_CARDS 16 /* max number of adapters */
-
-#ifndef CONFIG_WANPIPE_CARDS /* configurable option */
-#define CONFIG_WANPIPE_CARDS 1
-#endif
-
-#define CMD_OK 0 /* normal firmware return code */
-#define CMD_TIMEOUT 0xFF /* firmware command timed out */
-#define MAX_CMD_RETRY 10 /* max number of firmware retries */
-/****** Function Prototypes *************************************************/
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/* WAN link driver entry points */
-static int setup(struct wan_device* wandev, wandev_conf_t* conf);
-static int shutdown(struct wan_device* wandev);
-static int ioctl(struct wan_device* wandev, unsigned cmd, unsigned long arg);
-
-/* IOCTL handlers */
-static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump);
-static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec, int);
-
-/* Miscellaneous functions */
-STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs);
-static void release_hw (sdla_t *card);
-
-static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int*);
-static int check_s514_conflicts (sdla_t* card,wandev_conf_t* conf, int*);
-
-
-/****** Global Data **********************************************************
- * Note: All data must be explicitly initialized!!!
- */
-
-/* private data */
-static char drvname[] = "wanpipe";
-static char fullname[] = "WANPIPE(tm) Multiprotocol Driver";
-static char copyright[] = "(c) 1995-2000 Sangoma Technologies Inc.";
-static int ncards;
-static sdla_t* card_array; /* adapter data space */
-
-/* Wanpipe's own workqueue, used for all API's.
- * All protocol specific tasks will be inserted
- * into the "wanpipe_wq" workqueue.
-
- * The kernel workqueue mechanism will execute
- * all pending tasks in the "wanpipe_wq" workqueue.
- */
-
-struct workqueue_struct *wanpipe_wq;
-DECLARE_WORK(wanpipe_work, NULL, NULL);
-
-static int wanpipe_bh_critical;
-
-/******* Kernel Loadable Module Entry Points ********************************/
-
-/*============================================================================
- * Module 'insert' entry point.
- * o print announcement
- * o allocate adapter data space
- * o initialize static data
- * o register all cards with WAN router
- * o calibrate SDLA shared memory access delay.
- *
- * Return: 0 Ok
- * < 0 error.
- * Context: process
- */
-
-static int __init wanpipe_init(void)
-{
- int cnt, err = 0;
-
- printk(KERN_INFO "%s v%u.%u %s\n",
- fullname, DRV_VERSION, DRV_RELEASE, copyright);
-
- wanpipe_wq = create_workqueue("wanpipe_wq");
- if (!wanpipe_wq)
- return -ENOMEM;
-
- /* Probe for wanpipe cards and return the number found */
- printk(KERN_INFO "wanpipe: Probing for WANPIPE hardware.\n");
- ncards = wanpipe_hw_probe();
- if (ncards){
- printk(KERN_INFO "wanpipe: Allocating maximum %i devices: wanpipe%i - wanpipe%i.\n",ncards,1,ncards);
- }else{
- printk(KERN_INFO "wanpipe: No S514/S508 cards found, unloading modules!\n");
- destroy_workqueue(wanpipe_wq);
- return -ENODEV;
- }
-
- /* Verify number of cards and allocate adapter data space */
- card_array = kmalloc(sizeof(sdla_t) * ncards, GFP_KERNEL);
- if (card_array == NULL) {
- destroy_workqueue(wanpipe_wq);
- return -ENOMEM;
- }
-
- memset(card_array, 0, sizeof(sdla_t) * ncards);
-
- /* Register adapters with WAN router */
- for (cnt = 0; cnt < ncards; ++ cnt) {
- sdla_t* card = &card_array[cnt];
- struct wan_device* wandev = &card->wandev;
-
- card->next = NULL;
- sprintf(card->devname, "%s%d", drvname, cnt + 1);
- wandev->magic = ROUTER_MAGIC;
- wandev->name = card->devname;
- wandev->private = card;
- wandev->enable_tx_int = 0;
- wandev->setup = &setup;
- wandev->shutdown = &shutdown;
- wandev->ioctl = &ioctl;
- err = register_wan_device(wandev);
- if (err) {
- printk(KERN_INFO
- "%s: %s registration failed with error %d!\n",
- drvname, card->devname, err);
- break;
- }
- }
- if (cnt){
- ncards = cnt; /* adjust actual number of cards */
- }else {
- kfree(card_array);
- destroy_workqueue(wanpipe_wq);
- printk(KERN_INFO "IN Init Module: NO Cards registered\n");
- err = -ENODEV;
- }
-
- return err;
-}
-
-/*============================================================================
- * Module 'remove' entry point.
- * o unregister all adapters from the WAN router
- * o release all remaining system resources
- */
-static void __exit wanpipe_cleanup(void)
-{
- int i;
-
- if (!ncards)
- return;
-
- for (i = 0; i < ncards; ++i) {
- sdla_t* card = &card_array[i];
- unregister_wan_device(card->devname);
- }
- destroy_workqueue(wanpipe_wq);
- kfree(card_array);
-
- printk(KERN_INFO "\nwanpipe: WANPIPE Modules Unloaded.\n");
-}
-
-module_init(wanpipe_init);
-module_exit(wanpipe_cleanup);
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Setup/configure WAN link driver.
- * o check adapter state
- * o make sure firmware is present in configuration
- * o make sure I/O port and IRQ are specified
- * o make sure I/O region is available
- * o allocate interrupt vector
- * o setup SDLA hardware
- * o call appropriate routine to perform protocol-specific initialization
- * o mark I/O region as used
- * o if this is the first active card, then schedule background task
- *
- * This function is called when router handles ROUTER_SETUP IOCTL. The
- * configuration structure is in kernel memory (including extended data, if
- * any).
- */
-
-static int setup(struct wan_device* wandev, wandev_conf_t* conf)
-{
- sdla_t* card;
- int err = 0;
- int irq=0;
-
- /* Sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL) || (conf == NULL)){
- printk(KERN_INFO
- "%s: Failed Sdlamain Setup wandev %u, card %u, conf %u !\n",
- wandev->name,
- (unsigned int)wandev,(unsigned int)wandev->private,
- (unsigned int)conf);
- return -EFAULT;
- }
-
- printk(KERN_INFO "%s: Starting WAN Setup\n", wandev->name);
-
- card = wandev->private;
- if (wandev->state != WAN_UNCONFIGURED){
- printk(KERN_INFO "%s: failed sdlamain setup, busy!\n",
- wandev->name);
- return -EBUSY; /* already configured */
- }
-
- printk(KERN_INFO "\nProcessing WAN device %s...\n", wandev->name);
-
- /* Initialize the counters for each wandev
- * Used for counting number of times new_if and
- * del_if get called.
- */
- wandev->del_if_cnt = 0;
- wandev->new_if_cnt = 0;
- wandev->config_id = conf->config_id;
-
- if (!conf->data_size || (conf->data == NULL)) {
- printk(KERN_INFO
- "%s: firmware not found in configuration data!\n",
- wandev->name);
- return -EINVAL;
- }
-
- /* Check for resource conflicts and setup the
- * card for piggibacking if necessary */
- if(!conf->S514_CPU_no[0]) {
- if ((err=check_s508_conflicts(card,conf,&irq)) != 0){
- return err;
- }
- }else {
- if ((err=check_s514_conflicts(card,conf,&irq)) != 0){
- return err;
- }
- }
-
- /* If the current card has already been configured
- * or it's a piggyback card, do not try to allocate
- * resources.
- */
- if (!card->wandev.piggyback && !card->configured){
-
- /* Configure hardware, load firmware, etc. */
- memset(&card->hw, 0, sizeof(sdlahw_t));
-
- /* for an S514 adapter, pass the CPU number and the slot number read */
- /* from 'router.conf' to the 'sdla_setup()' function via the 'port' */
- /* parameter */
- if (conf->S514_CPU_no[0]){
-
- card->hw.S514_cpu_no[0] = conf->S514_CPU_no[0];
- card->hw.S514_slot_no = conf->PCI_slot_no;
- card->hw.auto_pci_cfg = conf->auto_pci_cfg;
-
- if (card->hw.auto_pci_cfg == WANOPT_YES){
- printk(KERN_INFO "%s: Setting CPU to %c and Slot to Auto\n",
- card->devname, card->hw.S514_cpu_no[0]);
- }else{
- printk(KERN_INFO "%s: Setting CPU to %c and Slot to %i\n",
- card->devname, card->hw.S514_cpu_no[0], card->hw.S514_slot_no);
- }
-
- }else{
- /* 508 Card io port and irq initialization */
- card->hw.port = conf->ioport;
- card->hw.irq = (conf->irq == 9) ? 2 : conf->irq;
- }
-
-
- /* Compute the virtual address of the card in kernel space */
- if(conf->maddr){
- card->hw.dpmbase = phys_to_virt(conf->maddr);
- }else{
- card->hw.dpmbase = (void *)conf->maddr;
- }
-
- card->hw.dpmsize = SDLA_WINDOWSIZE;
-
- /* set the adapter type if using an S514 adapter */
- card->hw.type = (conf->S514_CPU_no[0]) ? SDLA_S514 : conf->hw_opt[0];
- card->hw.pclk = conf->hw_opt[1];
-
- err = sdla_setup(&card->hw, conf->data, conf->data_size);
- if (err){
- printk(KERN_INFO "%s: Hardware setup Failed %i\n",
- card->devname,err);
- return err;
- }
-
- if(card->hw.type != SDLA_S514)
- irq = (conf->irq == 2) ? 9 : conf->irq; /* IRQ2 -> IRQ9 */
- else
- irq = card->hw.irq;
-
- /* request an interrupt vector - note that interrupts may be shared */
- /* when using the S514 PCI adapter */
-
- if(request_irq(irq, sdla_isr,
- (card->hw.type == SDLA_S514) ? SA_SHIRQ : 0,
- wandev->name, card)){
-
- printk(KERN_INFO "%s: Can't reserve IRQ %d!\n", wandev->name, irq);
- return -EINVAL;
- }
-
- }else{
- printk(KERN_INFO "%s: Card Configured %lu or Piggybacking %i!\n",
- wandev->name,card->configured,card->wandev.piggyback);
- }
-
-
- if (!card->configured){
-
- /* Initialize the Spin lock */
- printk(KERN_INFO "%s: Initializing for SMP\n",wandev->name);
-
- /* Piggyback spin lock has already been initialized,
- * in check_s514/s508_conflicts() */
- if (!card->wandev.piggyback){
- spin_lock_init(&card->wandev.lock);
- }
-
- /* Intialize WAN device data space */
- wandev->irq = irq;
- wandev->dma = 0;
- if(card->hw.type != SDLA_S514){
- wandev->ioport = card->hw.port;
- }else{
- wandev->S514_cpu_no[0] = card->hw.S514_cpu_no[0];
- wandev->S514_slot_no = card->hw.S514_slot_no;
- }
- wandev->maddr = (unsigned long)card->hw.dpmbase;
- wandev->msize = card->hw.dpmsize;
- wandev->hw_opt[0] = card->hw.type;
- wandev->hw_opt[1] = card->hw.pclk;
- wandev->hw_opt[2] = card->hw.memory;
- wandev->hw_opt[3] = card->hw.fwid;
- }
-
- /* Protocol-specific initialization */
- switch (card->hw.fwid) {
-
- case SFID_X25_502:
- case SFID_X25_508:
- printk(KERN_INFO "%s: Starting X.25 Protocol Init.\n",
- card->devname);
- err = wpx_init(card, conf);
- break;
- case SFID_FR502:
- case SFID_FR508:
- printk(KERN_INFO "%s: Starting Frame Relay Protocol Init.\n",
- card->devname);
- err = wpf_init(card, conf);
- break;
- case SFID_PPP502:
- case SFID_PPP508:
- printk(KERN_INFO "%s: Starting PPP Protocol Init.\n",
- card->devname);
- err = wpp_init(card, conf);
- break;
-
- case SFID_CHDLC508:
- case SFID_CHDLC514:
- if (conf->ft1){
- printk(KERN_INFO "%s: Starting FT1 CSU/DSU Config Driver.\n",
- card->devname);
- err = wpft1_init(card, conf);
- break;
-
- }else if (conf->config_id == WANCONFIG_MPPP){
- printk(KERN_INFO "%s: Starting Multi-Port PPP Protocol Init.\n",
- card->devname);
- err = wsppp_init(card,conf);
- break;
-
- }else{
- printk(KERN_INFO "%s: Starting CHDLC Protocol Init.\n",
- card->devname);
- err = wpc_init(card, conf);
- break;
- }
- default:
- printk(KERN_INFO "%s: Error, Firmware is not supported %X %X!\n",
- wandev->name,card->hw.fwid,SFID_CHDLC508);
- err = -EPROTONOSUPPORT;
- }
-
- if (err != 0){
- if (err == -EPROTONOSUPPORT){
- printk(KERN_INFO
- "%s: Error, Protocol selected has not been compiled!\n",
- card->devname);
- printk(KERN_INFO
- "%s: Re-configure the kernel and re-build the modules!\n",
- card->devname);
- }
-
- release_hw(card);
- wandev->state = WAN_UNCONFIGURED;
- return err;
- }
-
-
- /* Reserve I/O region and schedule background task */
- if(card->hw.type != SDLA_S514 && !card->wandev.piggyback)
- if (!request_region(card->hw.port, card->hw.io_range,
- wandev->name)) {
- printk(KERN_WARNING "port 0x%04x busy\n", card->hw.port);
- release_hw(card);
- wandev->state = WAN_UNCONFIGURED;
- return -EBUSY;
- }
-
- /* Only use the polling routine for the X25 protocol */
-
- card->wandev.critical=0;
- return 0;
-}
-
-/*==================================================================
- * configure_s508_card
- *
- * For a S508 adapter, check for a possible configuration error in that
- * we are loading an adapter in the same IO port as a previously loaded S508
- * card.
- */
-
-static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int *irq)
-{
- unsigned long smp_flags;
- int i;
-
- if (conf->ioport <= 0) {
- printk(KERN_INFO
- "%s: can't configure without I/O port address!\n",
- card->wandev.name);
- return -EINVAL;
- }
-
- if (conf->irq <= 0) {
- printk(KERN_INFO "%s: can't configure without IRQ!\n",
- card->wandev.name);
- return -EINVAL;
- }
-
- if (test_bit(0,&card->configured))
- return 0;
-
-
- /* Check for already loaded card with the same IO port and IRQ
- * If found, copy its hardware configuration and use its
- * resources (i.e. piggybacking)
- */
-
- for (i = 0; i < ncards; i++) {
- sdla_t *nxt_card = &card_array[i];
-
- /* Skip the current card ptr */
- if (nxt_card == card)
- continue;
-
-
- /* Find a card that is already configured with the
- * same IO Port */
- if ((nxt_card->hw.type == SDLA_S508) &&
- (nxt_card->hw.port == conf->ioport) &&
- (nxt_card->next == NULL)){
-
- /* We found a card the card that has same configuration
- * as us. This means, that we must setup this card in
- * piggibacking mode. However, only CHDLC and MPPP protocol
- * support this setup */
-
- if ((conf->config_id == WANCONFIG_CHDLC ||
- conf->config_id == WANCONFIG_MPPP) &&
- (nxt_card->wandev.config_id == WANCONFIG_CHDLC ||
- nxt_card->wandev.config_id == WANCONFIG_MPPP)){
-
- *irq = nxt_card->hw.irq;
- memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t));
-
- /* The master could already be running, we must
- * set this as a critical area */
- lock_adapter_irq(&nxt_card->wandev.lock, &smp_flags);
-
- nxt_card->next = card;
- card->next = nxt_card;
-
- card->wandev.piggyback = WANOPT_YES;
-
- /* We must initialise the piggiback spin lock here
- * since isr will try to lock card->next if it
- * exists */
- spin_lock_init(&card->wandev.lock);
-
- unlock_adapter_irq(&nxt_card->wandev.lock, &smp_flags);
- break;
- }else{
- /* Trying to run piggibacking with a wrong protocol */
- printk(KERN_INFO "%s: ERROR: Resource busy, ioport: 0x%x\n"
- "%s: This protocol doesn't support\n"
- "%s: multi-port operation!\n",
- card->devname,nxt_card->hw.port,
- card->devname,card->devname);
- return -EEXIST;
- }
- }
- }
-
-
- /* Make sure I/O port region is available only if we are the
- * master device. If we are running in piggybacking mode,
- * we will use the resources of the master card. */
- if (!card->wandev.piggyback) {
- struct resource *rr =
- request_region(conf->ioport, SDLA_MAXIORANGE, "sdlamain");
- release_region(conf->ioport, SDLA_MAXIORANGE);
-
- if (!rr) {
- printk(KERN_INFO
- "%s: I/O region 0x%X - 0x%X is in use!\n",
- card->wandev.name, conf->ioport,
- conf->ioport + SDLA_MAXIORANGE - 1);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-/*==================================================================
- * configure_s514_card
- *
- * For a S514 adapter, check for a possible configuration error in that
- * we are loading an adapter in the same slot as a previously loaded S514
- * card.
- */
-
-
-static int check_s514_conflicts(sdla_t* card,wandev_conf_t* conf, int *irq)
-{
- unsigned long smp_flags;
- int i;
-
- if (test_bit(0,&card->configured))
- return 0;
-
-
- /* Check for already loaded card with the same IO port and IRQ
- * If found, copy its hardware configuration and use its
- * resources (i.e. piggybacking)
- */
-
- for (i = 0; i < ncards; i ++) {
-
- sdla_t* nxt_card = &card_array[i];
- if(nxt_card == card)
- continue;
-
- if((nxt_card->hw.type == SDLA_S514) &&
- (nxt_card->hw.S514_slot_no == conf->PCI_slot_no) &&
- (nxt_card->hw.S514_cpu_no[0] == conf->S514_CPU_no[0])&&
- (nxt_card->next == NULL)){
-
-
- if ((conf->config_id == WANCONFIG_CHDLC ||
- conf->config_id == WANCONFIG_MPPP) &&
- (nxt_card->wandev.config_id == WANCONFIG_CHDLC ||
- nxt_card->wandev.config_id == WANCONFIG_MPPP)){
-
- *irq = nxt_card->hw.irq;
- memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t));
-
- /* The master could already be running, we must
- * set this as a critical area */
- lock_adapter_irq(&nxt_card->wandev.lock,&smp_flags);
- nxt_card->next = card;
- card->next = nxt_card;
-
- card->wandev.piggyback = WANOPT_YES;
-
- /* We must initialise the piggiback spin lock here
- * since isr will try to lock card->next if it
- * exists */
- spin_lock_init(&card->wandev.lock);
-
- unlock_adapter_irq(&nxt_card->wandev.lock,&smp_flags);
-
- }else{
- /* Trying to run piggibacking with a wrong protocol */
- printk(KERN_INFO "%s: ERROR: Resource busy: CPU %c PCISLOT %i\n"
- "%s: This protocol doesn't support\n"
- "%s: multi-port operation!\n",
- card->devname,
- conf->S514_CPU_no[0],conf->PCI_slot_no,
- card->devname,card->devname);
- return -EEXIST;
- }
- }
- }
-
- return 0;
-}
-
-
-
-/*============================================================================
- * Shut down WAN link driver.
- * o shut down adapter hardware
- * o release system resources.
- *
- * This function is called by the router when device is being unregistered or
- * when it handles ROUTER_DOWN IOCTL.
- */
-static int shutdown(struct wan_device* wandev)
-{
- sdla_t *card;
- int err=0;
-
- /* sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL)){
- return -EFAULT;
- }
-
- if (wandev->state == WAN_UNCONFIGURED){
- return 0;
- }
-
- card = wandev->private;
-
- if (card->tty_opt){
- if (card->tty_open){
- printk(KERN_INFO
- "%s: Shutdown Failed: TTY is still open\n",
- card->devname);
- return -EBUSY;
- }
- }
-
- wandev->state = WAN_UNCONFIGURED;
-
- set_bit(PERI_CRIT,(void*)&wandev->critical);
-
- /* In case of piggibacking, make sure that
- * we never try to shutdown both devices at the same
- * time, because they depend on one another */
-
- if (card->disable_comm){
- card->disable_comm(card);
- }
-
- /* Release Resources */
- release_hw(card);
-
- /* only free the allocated I/O range if not an S514 adapter */
- if (wandev->hw_opt[0] != SDLA_S514 && !card->configured){
- release_region(card->hw.port, card->hw.io_range);
- }
-
- if (!card->configured){
- memset(&card->hw, 0, sizeof(sdlahw_t));
- if (card->next){
- memset(&card->next->hw, 0, sizeof(sdlahw_t));
- }
- }
-
-
- clear_bit(PERI_CRIT,(void*)&wandev->critical);
- return err;
-}
-
-static void release_hw (sdla_t *card)
-{
- sdla_t *nxt_card;
-
-
- /* Check if next device exists */
- if (card->next){
- nxt_card = card->next;
- /* If next device is down then release resources */
- if (nxt_card->wandev.state == WAN_UNCONFIGURED){
- if (card->wandev.piggyback){
- /* If this device is piggyback then use
- * information of the master device
- */
- printk(KERN_INFO "%s: Piggyback shutting down\n",card->devname);
- sdla_down(&card->next->hw);
- free_irq(card->wandev.irq, card->next);
- card->configured = 0;
- card->next->configured = 0;
- card->wandev.piggyback = 0;
- }else{
- /* Master device shutting down */
- printk(KERN_INFO "%s: Master shutting down\n",card->devname);
- sdla_down(&card->hw);
- free_irq(card->wandev.irq, card);
- card->configured = 0;
- card->next->configured = 0;
- }
- }else{
- printk(KERN_INFO "%s: Device still running %i\n",
- nxt_card->devname,nxt_card->wandev.state);
-
- card->configured = 1;
- }
- }else{
- printk(KERN_INFO "%s: Master shutting down\n",card->devname);
- sdla_down(&card->hw);
- free_irq(card->wandev.irq, card);
- card->configured = 0;
- }
- return;
-}
-
-
-/*============================================================================
- * Driver I/O control.
- * o verify arguments
- * o perform requested action
- *
- * This function is called when router handles one of the reserved user
- * IOCTLs. Note that 'arg' stil points to user address space.
- */
-static int ioctl(struct wan_device* wandev, unsigned cmd, unsigned long arg)
-{
- sdla_t* card;
- int err;
-
- /* sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
- if (wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- card = wandev->private;
-
- if(card->hw.type != SDLA_S514){
- disable_irq(card->hw.irq);
- }
-
- if (test_bit(SEND_CRIT, (void*)&wandev->critical)) {
- return -EAGAIN;
- }
-
- switch (cmd) {
- case WANPIPE_DUMP:
- err = ioctl_dump(wandev->private, (void*)arg);
- break;
-
- case WANPIPE_EXEC:
- err = ioctl_exec(wandev->private, (void*)arg, cmd);
- break;
- default:
- err = -EINVAL;
- }
-
- return err;
-}
-
-/****** Driver IOCTL Handlers ***********************************************/
-
-/*============================================================================
- * Dump adapter memory to user buffer.
- * o verify request structure
- * o copy request structure to kernel data space
- * o verify length/offset
- * o verify user buffer
- * o copy adapter memory image to user buffer
- *
- * Note: when dumping memory, this routine switches curent dual-port memory
- * vector, so care must be taken to avoid racing conditions.
- */
-static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump)
-{
- sdla_dump_t dump;
- unsigned winsize;
- unsigned long oldvec; /* DPM window vector */
- unsigned long smp_flags;
- int err = 0;
-
- if(copy_from_user((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t)))
- return -EFAULT;
-
- if ((dump.magic != WANPIPE_MAGIC) ||
- (dump.offset + dump.length > card->hw.memory))
- return -EINVAL;
-
- winsize = card->hw.dpmsize;
-
- if(card->hw.type != SDLA_S514) {
-
- lock_adapter_irq(&card->wandev.lock, &smp_flags);
-
- oldvec = card->hw.vector;
- while (dump.length) {
- /* current offset */
- unsigned pos = dump.offset % winsize;
- /* current vector */
- unsigned long vec = dump.offset - pos;
- unsigned len = (dump.length > (winsize - pos)) ?
- (winsize - pos) : dump.length;
- /* relocate window */
- if (sdla_mapmem(&card->hw, vec) != 0) {
- err = -EIO;
- break;
- }
-
- if(copy_to_user((void *)dump.ptr,
- (u8 *)card->hw.dpmbase + pos, len)){
-
- unlock_adapter_irq(&card->wandev.lock, &smp_flags);
- return -EFAULT;
- }
-
- dump.length -= len;
- dump.offset += len;
- dump.ptr = (char*)dump.ptr + len;
- }
-
- sdla_mapmem(&card->hw, oldvec);/* restore DPM window position */
- unlock_adapter_irq(&card->wandev.lock, &smp_flags);
-
- }else {
-
- if(copy_to_user((void *)dump.ptr,
- (u8 *)card->hw.dpmbase + dump.offset, dump.length)){
- return -EFAULT;
- }
- }
-
- return err;
-}
-
-/*============================================================================
- * Execute adapter firmware command.
- * o verify request structure
- * o copy request structure to kernel data space
- * o call protocol-specific 'exec' function
- */
-static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec, int cmd)
-{
- sdla_exec_t exec;
- int err=0;
-
- if (card->exec == NULL && cmd == WANPIPE_EXEC){
- return -ENODEV;
- }
-
- if(copy_from_user((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t)))
- return -EFAULT;
-
- if ((exec.magic != WANPIPE_MAGIC) || (exec.cmd == NULL))
- return -EINVAL;
-
- switch (cmd) {
- case WANPIPE_EXEC:
- err = card->exec(card, exec.cmd, exec.data);
- break;
- }
- return err;
-}
-
-/******* Miscellaneous ******************************************************/
-
-/*============================================================================
- * SDLA Interrupt Service Routine.
- * o acknowledge SDLA hardware interrupt.
- * o call protocol-specific interrupt service routine, if any.
- */
-STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs)
-{
-#define card ((sdla_t*)dev_id)
-
- if(card->hw.type == SDLA_S514) { /* handle interrrupt on S514 */
- u32 int_status;
- unsigned char CPU_no = card->hw.S514_cpu_no[0];
- unsigned char card_found_for_IRQ;
- u8 IRQ_count = 0;
-
- for(;;) {
-
- read_S514_int_stat(&card->hw, &int_status);
-
- /* check if the interrupt is for this device */
- if(!((unsigned char)int_status &
- (IRQ_CPU_A | IRQ_CPU_B)))
- return IRQ_HANDLED;
-
- /* if the IRQ is for both CPUs on the same adapter, */
- /* then alter the interrupt status so as to handle */
- /* one CPU at a time */
- if(((unsigned char)int_status & (IRQ_CPU_A | IRQ_CPU_B))
- == (IRQ_CPU_A | IRQ_CPU_B)) {
- int_status &= (CPU_no == S514_CPU_A) ?
- ~IRQ_CPU_B : ~IRQ_CPU_A;
- }
-
- card_found_for_IRQ = 0;
-
- /* check to see that the CPU number for this device */
- /* corresponds to the interrupt status read */
- switch (CPU_no) {
- case S514_CPU_A:
- if((unsigned char)int_status &
- IRQ_CPU_A)
- card_found_for_IRQ = 1;
- break;
-
- case S514_CPU_B:
- if((unsigned char)int_status &
- IRQ_CPU_B)
- card_found_for_IRQ = 1;
- break;
- }
-
- /* exit if the interrupt is for another CPU on the */
- /* same IRQ */
- if(!card_found_for_IRQ)
- return IRQ_HANDLED;
-
- if (!card ||
- (card->wandev.state == WAN_UNCONFIGURED && !card->configured)){
- printk(KERN_INFO
- "Received IRQ %d for CPU #%c\n",
- irq, CPU_no);
- printk(KERN_INFO
- "IRQ for unconfigured adapter\n");
- S514_intack(&card->hw, int_status);
- return IRQ_HANDLED;
- }
-
- if (card->in_isr) {
- printk(KERN_INFO
- "%s: interrupt re-entrancy on IRQ %d\n",
- card->devname, card->wandev.irq);
- S514_intack(&card->hw, int_status);
- return IRQ_HANDLED;
- }
-
- spin_lock(&card->wandev.lock);
- if (card->next){
- spin_lock(&card->next->wandev.lock);
- }
-
- S514_intack(&card->hw, int_status);
- if (card->isr)
- card->isr(card);
-
- if (card->next){
- spin_unlock(&card->next->wandev.lock);
- }
- spin_unlock(&card->wandev.lock);
-
- /* handle a maximum of two interrupts (one for each */
- /* CPU on the adapter) before returning */
- if((++ IRQ_count) == 2)
- return IRQ_HANDLED;
- }
- }
-
- else { /* handle interrupt on S508 adapter */
-
- if (!card || ((card->wandev.state == WAN_UNCONFIGURED) && !card->configured))
- return IRQ_HANDLED;
-
- if (card->in_isr) {
- printk(KERN_INFO
- "%s: interrupt re-entrancy on IRQ %d!\n",
- card->devname, card->wandev.irq);
- return IRQ_HANDLED;
- }
-
- spin_lock(&card->wandev.lock);
- if (card->next){
- spin_lock(&card->next->wandev.lock);
- }
-
- sdla_intack(&card->hw);
- if (card->isr)
- card->isr(card);
-
- if (card->next){
- spin_unlock(&card->next->wandev.lock);
- }
- spin_unlock(&card->wandev.lock);
-
- }
- return IRQ_HANDLED;
-#undef card
-}
-
-/*============================================================================
- * This routine is called by the protocol-specific modules when network
- * interface is being open. The only reason we need this, is because we
- * have to call MOD_INC_USE_COUNT, but cannot include 'module.h' where it's
- * defined more than once into the same kernel module.
- */
-void wanpipe_open (sdla_t* card)
-{
- ++card->open_cnt;
-}
-
-/*============================================================================
- * This routine is called by the protocol-specific modules when network
- * interface is being closed. The only reason we need this, is because we
- * have to call MOD_DEC_USE_COUNT, but cannot include 'module.h' where it's
- * defined more than once into the same kernel module.
- */
-void wanpipe_close (sdla_t* card)
-{
- --card->open_cnt;
-}
-
-/*============================================================================
- * Set WAN device state.
- */
-void wanpipe_set_state (sdla_t* card, int state)
-{
- if (card->wandev.state != state) {
- switch (state) {
- case WAN_CONNECTED:
- printk (KERN_INFO "%s: link connected!\n",
- card->devname);
- break;
-
- case WAN_CONNECTING:
- printk (KERN_INFO "%s: link connecting...\n",
- card->devname);
- break;
-
- case WAN_DISCONNECTED:
- printk (KERN_INFO "%s: link disconnected!\n",
- card->devname);
- break;
- }
- card->wandev.state = state;
- }
- card->state_tick = jiffies;
-}
-
-sdla_t * wanpipe_find_card (char *name)
-{
- int cnt;
- for (cnt = 0; cnt < ncards; ++ cnt) {
- sdla_t* card = &card_array[cnt];
- if (!strcmp(card->devname,name))
- return card;
- }
- return NULL;
-}
-
-sdla_t * wanpipe_find_card_num (int num)
-{
- if (num < 1 || num > ncards)
- return NULL;
- num--;
- return &card_array[num];
-}
-
-/*
- * @work_pointer: work_struct to be done;
- * should already have PREPARE_WORK() or
- * INIT_WORK() done on it by caller;
- */
-void wanpipe_queue_work (struct work_struct *work_pointer)
-{
- if (test_and_set_bit(1, (void*)&wanpipe_bh_critical))
- printk(KERN_INFO "CRITICAL IN QUEUING WORK\n");
-
- queue_work(wanpipe_wq, work_pointer);
- clear_bit(1,(void*)&wanpipe_bh_critical);
-}
-
-void wakeup_sk_bh(struct net_device *dev)
-{
- wanpipe_common_t *chan = dev->priv;
-
- if (test_bit(0,&chan->common_critical))
- return;
-
- if (chan->sk && chan->tx_timer){
- chan->tx_timer->expires=jiffies+1;
- add_timer(chan->tx_timer);
- }
-}
-
-int change_dev_flags(struct net_device *dev, unsigned flags)
-{
- struct ifreq if_info;
- mm_segment_t fs = get_fs();
- int err;
-
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
- if_info.ifr_flags = flags;
-
- set_fs(get_ds()); /* get user space block */
- err = devinet_ioctl(SIOCSIFFLAGS, &if_info);
- set_fs(fs);
-
- return err;
-}
-
-unsigned long get_ip_address(struct net_device *dev, int option)
-{
-
- struct in_ifaddr *ifaddr;
- struct in_device *in_dev;
- unsigned long addr = 0;
-
- rcu_read_lock();
- if ((in_dev = __in_dev_get_rcu(dev)) == NULL){
- goto out;
- }
-
- if ((ifaddr = in_dev->ifa_list)== NULL ){
- goto out;
- }
-
- switch (option){
-
- case WAN_LOCAL_IP:
- addr = ifaddr->ifa_local;
- break;
-
- case WAN_POINTOPOINT_IP:
- addr = ifaddr->ifa_address;
- break;
-
- case WAN_NETMASK_IP:
- addr = ifaddr->ifa_mask;
- break;
-
- case WAN_BROADCAST_IP:
- addr = ifaddr->ifa_broadcast;
- break;
- default:
- break;
- }
-
-out:
- rcu_read_unlock();
- return addr;
-}
-
-void add_gateway(sdla_t *card, struct net_device *dev)
-{
- mm_segment_t oldfs;
- struct rtentry route;
- int res;
-
- memset((char*)&route,0,sizeof(struct rtentry));
-
- ((struct sockaddr_in *)
- &(route.rt_dst))->sin_addr.s_addr = 0;
- ((struct sockaddr_in *)
- &(route.rt_dst))->sin_family = AF_INET;
-
- ((struct sockaddr_in *)
- &(route.rt_genmask))->sin_addr.s_addr = 0;
- ((struct sockaddr_in *)
- &(route.rt_genmask)) ->sin_family = AF_INET;
-
-
- route.rt_flags = 0;
- route.rt_dev = dev->name;
-
- oldfs = get_fs();
- set_fs(get_ds());
- res = ip_rt_ioctl(SIOCADDRT,&route);
- set_fs(oldfs);
-
- if (res == 0){
- printk(KERN_INFO "%s: Gateway added for %s\n",
- card->devname,dev->name);
- }
-
- return;
-}
-
-MODULE_LICENSE("GPL");
-
-/****** End *********************************************************/
diff --git a/drivers/net/wan/wanpipe_multppp.c b/drivers/net/wan/wanpipe_multppp.c
deleted file mode 100644
index 812a1183c50..00000000000
--- a/drivers/net/wan/wanpipe_multppp.c
+++ /dev/null
@@ -1,2358 +0,0 @@
-/*****************************************************************************
-* wanpipe_multppp.c Multi-Port PPP driver module.
-*
-* Authors: Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright: (c) 1995-2001 Sangoma Technologies 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.
-* ============================================================================
-* Dec 15 2000 Updated for 2.4.X kernel
-* Nov 15 2000 Fixed the SyncPPP support for kernels 2.2.16 and higher.
-* The pppstruct has changed.
-* Jul 13 2000 Using the kernel Syncppp module on top of RAW Wanpipe CHDLC
-* module.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/if_arp.h> /* ARPHRD_* defines */
-#include <linux/jiffies.h> /* time_after() macro */
-
-#include <linux/in.h> /* sockaddr_in */
-#include <linux/inet.h>
-#include <linux/if.h>
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <linux/sdlapci.h>
-#include <asm/io.h>
-
-#include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */
-#include <linux/sdla_asy.h> /* CHDLC (async) API definitions */
-
-#include <linux/if_wanpipe_common.h> /* Socket Driver common area */
-#include <linux/if_wanpipe.h>
-
-
-#include <linux/inetdevice.h>
-#include <asm/uaccess.h>
-
-#include <net/syncppp.h>
-
-
-/****** Defines & Macros ****************************************************/
-
-#ifdef _DEBUG_
-#define STATIC
-#else
-#define STATIC static
-#endif
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP 0x01
-#define TMR_INT_ENABLED_UPDATE 0x02
-#define TMR_INT_ENABLED_CONFIG 0x04
-
-#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */
-#define CHDLC_HDR_LEN 1
-
-#define IFF_POINTTOPOINT 0x10
-
-#define CHDLC_API 0x01
-
-#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
-#define MAX_BH_BUFF 10
-
-#define CRC_LENGTH 2
-#define PPP_HEADER_LEN 4
-
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following
- * structure will incorporate the card structure along with CHDLC specific data
- */
-
-typedef struct chdlc_private_area
-{
- void *if_ptr; /* General Pointer used by SPPP */
- wanpipe_common_t common;
- sdla_t *card;
- int TracingEnabled; /* For enabling Tracing */
- unsigned long curr_trace_addr; /* Used for Tracing */
- unsigned long start_trace_addr;
- unsigned long end_trace_addr;
- unsigned long base_addr_trace_buffer;
- unsigned long end_addr_trace_buffer;
- unsigned short number_trace_elements;
- unsigned available_buffer_space;
- unsigned long router_start_time;
- unsigned char route_status;
- unsigned char route_removed;
- unsigned long tick_counter; /* For 5s timeout counter */
- unsigned long router_up_time;
- u32 IP_address; /* IP addressing */
- u32 IP_netmask;
- unsigned char mc; /* Mulitcast support on/off */
- unsigned short udp_pkt_lgth; /* udp packet processing */
- char udp_pkt_src;
- char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
- unsigned short timer_int_enabled;
- char update_comms_stats; /* updating comms stats */
-
- //FIXME: add driver stats as per frame relay!
-
-} chdlc_private_area_t;
-
-/* Route Status options */
-#define NO_ROUTE 0x00
-#define ADD_ROUTE 0x01
-#define ROUTE_ADDED 0x02
-#define REMOVE_ROUTE 0x03
-
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-/* variable for tracking how many interfaces to open for WANPIPE on the
- two ports */
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/****** Function Prototypes *************************************************/
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device* wandev);
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf);
-static int del_if(struct wan_device* wandev, struct net_device* dev);
-
-/* Network device interface */
-static int if_init(struct net_device* dev);
-static int if_open(struct net_device* dev);
-static int if_close(struct net_device* dev);
-static int if_send(struct sk_buff* skb, struct net_device* dev);
-static struct net_device_stats* if_stats(struct net_device* dev);
-
-static void if_tx_timeout(struct net_device *dev);
-
-/* CHDLC Firmware interface functions */
-static int chdlc_configure (sdla_t* card, void* data);
-static int chdlc_comm_enable (sdla_t* card);
-static int chdlc_comm_disable (sdla_t* card);
-static int chdlc_read_version (sdla_t* card, char* str);
-static int chdlc_set_intr_mode (sdla_t* card, unsigned mode);
-static int chdlc_send (sdla_t* card, void* data, unsigned len);
-static int chdlc_read_comm_err_stats (sdla_t* card);
-static int chdlc_read_op_stats (sdla_t* card);
-static int config_chdlc (sdla_t *card);
-
-
-/* Miscellaneous CHDLC Functions */
-static int set_chdlc_config (sdla_t* card);
-static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev);
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
-static int process_chdlc_exception(sdla_t *card);
-static int process_global_exception(sdla_t *card);
-static int update_comms_stats(sdla_t* card,
- chdlc_private_area_t* chdlc_priv_area);
-static void port_set_state (sdla_t *card, int);
-
-/* Interrupt handlers */
-static void wsppp_isr (sdla_t* card);
-static void rx_intr (sdla_t* card);
-static void timer_intr(sdla_t *);
-
-/* Miscellaneous functions */
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-static int intr_test( sdla_t* card);
-static int udp_pkt_type( struct sk_buff *skb , sdla_t* card);
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area);
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area);
-static unsigned short calc_checksum (char *, int);
-static void s508_lock (sdla_t *card, unsigned long *smp_flags);
-static void s508_unlock (sdla_t *card, unsigned long *smp_flags);
-static void send_ppp_term_request(struct net_device *dev);
-
-
-static int Intr_test_counter;
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Cisco HDLC protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup. At this
- * point adapter is completely initialized and firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the adapter data space.
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-int wsppp_init (sdla_t* card, wandev_conf_t* conf)
-{
- unsigned char port_num;
- int err;
- unsigned long max_permitted_baud = 0;
- SHARED_MEMORY_INFO_STRUCT *flags;
-
- union
- {
- char str[80];
- } u;
- volatile CHDLC_MAILBOX_STRUCT* mb;
- CHDLC_MAILBOX_STRUCT* mb1;
- unsigned long timeout;
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_MPPP) {
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
- return -EINVAL;
- }
-
- /* Find out which Port to use */
- if ((conf->comm_port == WANOPT_PRI) || (conf->comm_port == WANOPT_SEC)){
- if (card->next){
-
- if (conf->comm_port != card->next->u.c.comm_port){
- card->u.c.comm_port = conf->comm_port;
- }else{
- printk(KERN_ERR "%s: ERROR - %s port used!\n",
- card->wandev.name, PORT(conf->comm_port));
- return -EINVAL;
- }
- }else{
- card->u.c.comm_port = conf->comm_port;
- }
- }else{
- printk(KERN_ERR "%s: ERROR - Invalid Port Selected!\n",
- card->wandev.name);
- return -EINVAL;
- }
-
-
- /* Initialize protocol-specific fields */
- if(card->hw.type != SDLA_S514){
-
- if (card->u.c.comm_port == WANOPT_PRI){
- card->mbox = (void *) card->hw.dpmbase;
- }else{
- card->mbox = (void *) card->hw.dpmbase +
- SEC_BASE_ADDR_MB_STRUCT - PRI_BASE_ADDR_MB_STRUCT;
- }
- }else{
- /* for a S514 adapter, set a pointer to the actual mailbox in the */
- /* allocated virtual memory area */
- if (card->u.c.comm_port == WANOPT_PRI){
- card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
- }else{
- card->mbox = (void *) card->hw.dpmbase + SEC_BASE_ADDR_MB_STRUCT;
- }
- }
-
- mb = mb1 = card->mbox;
-
- if (!card->configured){
-
- /* The board will place an 'I' in the return code to indicate that it is
- ready to accept commands. We expect this to be completed in less
- than 1 second. */
-
- timeout = jiffies + 1 * HZ;
- while (mb->return_code != 'I') /* Wait 1s for board to initialize */
- if (time_after(jiffies, timeout)) break;
-
- if (mb->return_code != 'I') {
- printk(KERN_INFO
- "%s: Initialization not completed by adapter\n",
- card->devname);
- printk(KERN_INFO "Please contact Sangoma representative.\n");
- return -EIO;
- }
- }
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
-
- if (chdlc_read_version(card, u.str))
- return -EIO;
-
- printk(KERN_INFO "%s: Running Raw CHDLC firmware v%s\n"
- "%s: for Multi-Port PPP protocol.\n",
- card->devname,u.str,card->devname);
-
- card->isr = &wsppp_isr;
- card->poll = NULL;
- card->exec = NULL;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = &del_if;
- card->wandev.udp_port = conf->udp_port;
-
- card->wandev.new_if_cnt = 0;
-
- /* reset the number of times the 'update()' proc has been called */
- card->u.c.update_call_count = 0;
-
- card->wandev.ttl = conf->ttl;
- card->wandev.interface = conf->interface;
-
- if ((card->u.c.comm_port == WANOPT_SEC && conf->interface == WANOPT_V35)&&
- card->hw.type != SDLA_S514){
- printk(KERN_INFO "%s: ERROR - V35 Interface not supported on S508 %s port \n",
- card->devname, PORT(card->u.c.comm_port));
- return -EIO;
- }
-
-
- card->wandev.clocking = conf->clocking;
-
- port_num = card->u.c.comm_port;
-
- /* Setup Port Bps */
-
- if(card->wandev.clocking) {
- if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
- /* For Primary Port 0 */
- max_permitted_baud =
- (card->hw.type == SDLA_S514) ?
- PRI_MAX_BAUD_RATE_S514 :
- PRI_MAX_BAUD_RATE_S508;
- }
- else if(port_num == WANOPT_SEC) {
- /* For Secondary Port 1 */
- max_permitted_baud =
- (card->hw.type == SDLA_S514) ?
- SEC_MAX_BAUD_RATE_S514 :
- SEC_MAX_BAUD_RATE_S508;
- }
-
- if(conf->bps > max_permitted_baud) {
- conf->bps = max_permitted_baud;
- printk(KERN_INFO "%s: Baud too high!\n",
- card->wandev.name);
- printk(KERN_INFO "%s: Baud rate set to %lu bps\n",
- card->wandev.name, max_permitted_baud);
- }
-
- card->wandev.bps = conf->bps;
- }else{
- card->wandev.bps = 0;
- }
-
- /* Setup the Port MTU */
- if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
-
- /* For Primary Port 0 */
- card->wandev.mtu =
- (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
- min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) :
- CHDLC_DFLT_DATA_LEN;
- } else if(port_num == WANOPT_SEC) {
- /* For Secondary Port 1 */
- card->wandev.mtu =
- (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
- min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) :
- CHDLC_DFLT_DATA_LEN;
- }
-
- /* Add on a PPP Header */
- card->wandev.mtu += PPP_HEADER_LEN;
-
- /* Set up the interrupt status area */
- /* Read the CHDLC Configuration and obtain:
- * Ptr to shared memory infor struct
- * Use this pointer to calculate the value of card->u.c.flags !
- */
- mb1->buffer_length = 0;
- mb1->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
- if(err != COMMAND_OK) {
- clear_bit(1, (void*)&card->wandev.critical);
-
- if(card->hw.type != SDLA_S514)
- enable_irq(card->hw.irq);
-
- chdlc_error(card, err, mb1);
- return -EIO;
- }
-
- if(card->hw.type == SDLA_S514){
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct));
- }else{
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
- }
-
- flags = card->u.c.flags;
-
- /* This is for the ports link state */
- card->wandev.state = WAN_DUALPORT;
- card->u.c.state = WAN_DISCONNECTED;
-
-
- if (!card->wandev.piggyback){
- err = intr_test(card);
-
- if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) {
- printk(KERN_ERR "%s: Interrupt test failed (%i)\n",
- card->devname, Intr_test_counter);
- printk(KERN_ERR "%s: Please choose another interrupt\n",
- card->devname);
- return -EIO;
- }
-
- printk(KERN_INFO "%s: Interrupt test passed (%i)\n",
- card->devname, Intr_test_counter);
- }
-
-
- if (chdlc_set_intr_mode(card, APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
- card->devname);
- return -EIO;
- }
-
- /* Mask the Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TIMER;
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics
- * This procedure is called when updating the PROC file system and returns
- * various communications statistics. These statistics are accumulated from 3
- * different locations:
- * 1) The 'if_stats' recorded for the device.
- * 2) Communication error statistics on the adapter.
- * 3) CHDLC operational statistics on the adapter.
- * The board level statistics are read during a timer interrupt. Note that we
- * read the error and operational statistics during consecitive timer ticks so
- * as to minimize the time that we are inside the interrupt handler.
- *
- */
-static int update(struct wan_device* wandev)
-{
- sdla_t* card = wandev->private;
- struct net_device* dev;
- volatile chdlc_private_area_t* chdlc_priv_area;
- SHARED_MEMORY_INFO_STRUCT *flags;
- unsigned long timeout;
-
- /* sanity checks */
- if((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
-
- if(wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- /* more sanity checks */
- if(!card->u.c.flags)
- return -ENODEV;
-
- if((dev=card->wandev.dev) == NULL)
- return -ENODEV;
-
- if((chdlc_priv_area=dev->priv) == NULL)
- return -ENODEV;
-
- flags = card->u.c.flags;
-
- if(chdlc_priv_area->update_comms_stats){
- return -EAGAIN;
- }
-
- /* we will need 2 timer interrupts to complete the */
- /* reading of the statistics */
- chdlc_priv_area->update_comms_stats = 2;
- flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
- chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE;
-
- /* wait a maximum of 1 second for the statistics to be updated */
- timeout = jiffies + 1 * HZ;
- for(;;) {
- if(chdlc_priv_area->update_comms_stats == 0)
- break;
- if (time_after(jiffies, timeout)){
- chdlc_priv_area->update_comms_stats = 0;
- chdlc_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- return -EAGAIN;
- }
- }
-
- return 0;
-}
-
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return: 0 o.k.
- * < 0 failure (channel will not be created)
- */
-static int new_if(struct wan_device* wandev, struct net_device* pdev,
- wanif_conf_t* conf)
-{
-
- struct ppp_device *pppdev = (struct ppp_device *)pdev;
- struct net_device *dev = NULL;
- struct sppp *sp;
- sdla_t* card = wandev->private;
- chdlc_private_area_t* chdlc_priv_area;
-
- if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
- printk(KERN_INFO "%s: invalid interface name!\n",
- card->devname);
- return -EINVAL;
- }
-
- /* allocate and initialize private data */
- chdlc_priv_area = kmalloc(sizeof(chdlc_private_area_t), GFP_KERNEL);
-
- if(chdlc_priv_area == NULL)
- return -ENOMEM;
-
- memset(chdlc_priv_area, 0, sizeof(chdlc_private_area_t));
-
- chdlc_priv_area->card = card;
-
- /* initialize data */
- strcpy(card->u.c.if_name, conf->name);
-
- if(card->wandev.new_if_cnt > 0) {
- kfree(chdlc_priv_area);
- return -EEXIST;
- }
-
- card->wandev.new_if_cnt++;
-
- chdlc_priv_area->TracingEnabled = 0;
-
- //We don't need this any more
- chdlc_priv_area->route_status = NO_ROUTE;
- chdlc_priv_area->route_removed = 0;
-
- printk(KERN_INFO "%s: Firmware running in HDLC STREAMING Mode\n",
- wandev->name);
-
- /* Setup wanpipe as a router (WANPIPE) or as an API */
- if( strcmp(conf->usedby, "WANPIPE") == 0) {
- printk(KERN_INFO "%s: Driver running in WANPIPE mode!\n",
- wandev->name);
- card->u.c.usedby = WANPIPE;
- } else {
- printk(KERN_INFO
- "%s: API Mode is not supported for SyncPPP!\n",
- wandev->name);
- kfree(chdlc_priv_area);
- return -EINVAL;
- }
-
- /* Get Multicast Information */
- chdlc_priv_area->mc = conf->mc;
-
-
- chdlc_priv_area->if_ptr = pppdev;
-
- /* prepare network device data space for registration */
-
- strcpy(dev->name,card->u.c.if_name);
-
- /* Attach PPP protocol layer to pppdev
- * The sppp_attach() will initilize the dev structure
- * and setup ppp layer protocols.
- * All we have to do is to bind in:
- * if_open(), if_close(), if_send() and get_stats() functions.
- */
- sppp_attach(pppdev);
- dev = pppdev->dev;
- sp = &pppdev->sppp;
-
- /* Enable PPP Debugging */
- // FIXME Fix this up somehow
- //sp->pp_flags |= PP_DEBUG;
- sp->pp_flags &= ~PP_CISCO;
-
- dev->init = &if_init;
- dev->priv = chdlc_priv_area;
-
- return 0;
-}
-
-
-
-
-/*============================================================================
- * Delete logical channel.
- */
-static int del_if(struct wan_device* wandev, struct net_device* dev)
-{
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- sdla_t *card = chdlc_priv_area->card;
- unsigned long smp_lock;
-
- /* Detach the PPP layer */
- printk(KERN_INFO "%s: Detaching SyncPPP Module from %s\n",
- wandev->name,dev->name);
-
- lock_adapter_irq(&wandev->lock,&smp_lock);
-
- sppp_detach(dev);
- chdlc_priv_area->if_ptr=NULL;
-
- chdlc_set_intr_mode(card, 0);
- if (card->u.c.comm_enabled)
- chdlc_comm_disable(card);
- unlock_adapter_irq(&wandev->lock,&smp_lock);
-
- port_set_state(card, WAN_DISCONNECTED);
-
- return 0;
-}
-
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration. Returning anything but zero will fail interface
- * registration.
- */
-static int if_init(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
- struct wan_device* wandev = &card->wandev;
-
- /* NOTE: Most of the dev initialization was
- * done in sppp_attach(), called by new_if()
- * function. All we have to do here is
- * to link four major routines below.
- */
-
- /* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
- dev->tx_timeout = &if_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
-
- /* Initialize hardware parameters */
- dev->irq = wandev->irq;
- dev->dma = wandev->dma;
- dev->base_addr = wandev->ioport;
- dev->mem_start = wandev->maddr;
- dev->mem_end = wandev->maddr + wandev->msize - 1;
-
- /* Set transmit buffer queue length
- * If we over fill this queue the packets will
- * be droped by the kernel.
- * sppp_attach() sets this to 10, but
- * 100 will give us more room at low speeds.
- */
- dev->tx_queue_len = 100;
-
- return 0;
-}
-
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
- chdlc_private_area_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- /* If our device stays busy for at least 5 seconds then we will
- * kick start the device by making dev->tbusy = 0. We expect
- * that our device never stays busy more than 5 seconds. So this
- * is only used as a last resort.
- */
-
- ++card->wandev.stats.collisions;
-
- printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
- netif_wake_queue (dev);
-}
-
-
-/*============================================================================
- * Open network interface.
- * o enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
- struct timeval tv;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
- /* Only one open per interface is allowed */
- if (netif_running(dev))
- return -EBUSY;
-
- /* Start PPP Layer */
- if (sppp_open(dev)){
- return -EIO;
- }
-
- do_gettimeofday(&tv);
- chdlc_priv_area->router_start_time = tv.tv_sec;
-
- netif_start_queue(dev);
-
- wanpipe_open(card);
-
- chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
- flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
- return 0;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last close, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
-
- /* Stop the PPP Layer */
- sppp_close(dev);
- netif_stop_queue(dev);
-
- wanpipe_close(card);
-
- return 0;
-}
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- * transmit from overlapping.
- * o check link state. If link is not up, then drop the packet.
- * o execute adapter send command.
- * o free socket buffer
- *
- * Return: 0 complete (socket buffer must be freed)
- * non-0 packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- * bottom half" (with interrupts enabled).
- * 2. Setting tbusy flag will inhibit further transmit requests from the
- * protocol stack and can be used for flow control with protocol layer.
- */
-static int if_send(struct sk_buff* skb, struct net_device* dev)
-{
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- sdla_t *card = chdlc_priv_area->card;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;
- int udp_type = 0;
- unsigned long smp_flags;
- int err=0;
-
- netif_stop_queue(dev);
-
-
- if (skb == NULL){
- /* If we get here, some higher layer thinks we've missed an
- * tx-done interrupt.
- */
- printk(KERN_INFO "%s: Received NULL skb buffer! interface %s got kicked!\n",
- card->devname, dev->name);
-
- netif_wake_queue(dev);
- return 0;
- }
-
- if (ntohs(skb->protocol) != htons(PVC_PROT)){
- /* check the udp packet type */
-
- udp_type = udp_pkt_type(skb, card);
- if (udp_type == UDP_CPIPE_TYPE){
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev,
- chdlc_priv_area)){
- chdlc_int->interrupt_permission |=
- APP_INT_ON_TIMER;
- }
- netif_start_queue(dev);
- return 0;
- }
- }
-
- /* Lock the 508 Card: SMP is supported */
- if(card->hw.type != SDLA_S514){
- s508_lock(card,&smp_flags);
- }
-
- if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){
-
- printk(KERN_INFO "%s: Critical in if_send: %lx\n",
- card->wandev.name,card->wandev.critical);
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
- goto if_send_crit_exit;
- }
-
- if (card->wandev.state != WAN_CONNECTED){
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
- goto if_send_crit_exit;
- }
-
- if (chdlc_send(card, skb->data, skb->len)){
- netif_stop_queue(dev);
-
- }else{
- ++card->wandev.stats.tx_packets;
- card->wandev.stats.tx_bytes += skb->len;
- dev->trans_start = jiffies;
- netif_start_queue(dev);
- }
-
-if_send_crit_exit:
- if (!(err=netif_queue_stopped(dev))){
- dev_kfree_skb_any(skb);
- }else{
- chdlc_priv_area->tick_counter = jiffies;
- chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
- }
-
- clear_bit(SEND_CRIT, (void*)&card->wandev.critical);
- if(card->hw.type != SDLA_S514){
- s508_unlock(card,&smp_flags);
- }
-
- return err;
-}
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return length of reply.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
-
- unsigned short len, udp_length, temp, ip_length;
- unsigned long ip_temp;
- int even_bound = 0;
- chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data;
-
- /* Set length of packet */
- len = sizeof(ip_pkt_t)+
- sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- sizeof(trace_info_t)+
- mbox_len;
-
- /* fill in UDP reply */
- c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-
- /* fill in UDP length */
- udp_length = sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- sizeof(trace_info_t)+
- mbox_len;
-
- /* put it on an even boundary */
- if ( udp_length & 0x0001 ) {
- udp_length += 1;
- len += 1;
- even_bound = 1;
- }
-
- temp = (udp_length<<8)|(udp_length>>8);
- c_udp_pkt->udp_pkt.udp_length = temp;
-
- /* swap UDP ports */
- temp = c_udp_pkt->udp_pkt.udp_src_port;
- c_udp_pkt->udp_pkt.udp_src_port =
- c_udp_pkt->udp_pkt.udp_dst_port;
- c_udp_pkt->udp_pkt.udp_dst_port = temp;
-
- /* add UDP pseudo header */
- temp = 0x1100;
- *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp;
- temp = (udp_length<<8)|(udp_length>>8);
- *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
-
- /* calculate UDP checksum */
- c_udp_pkt->udp_pkt.udp_checksum = 0;
- c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET);
-
- /* fill in IP length */
- ip_length = len;
- temp = (ip_length<<8)|(ip_length>>8);
- c_udp_pkt->ip_pkt.total_length = temp;
-
- /* swap IP addresses */
- ip_temp = c_udp_pkt->ip_pkt.ip_src_address;
- c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address;
- c_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
- /* fill in IP checksum */
- c_udp_pkt->ip_pkt.hdr_checksum = 0;
- c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t));
-
- return len;
-
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
- unsigned short temp;
- unsigned long sum=0;
- int i;
-
- for( i = 0; i <len; i+=2 ) {
- memcpy(&temp,&data[i],2);
- sum += (unsigned long)temp;
- }
-
- while (sum >> 16 ) {
- sum = (sum & 0xffffUL) + (sum >> 16);
- }
-
- temp = (unsigned short)sum;
- temp = ~temp;
-
- if( temp == 0 )
- temp = 0xffff;
-
- return temp;
-}
-
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct enet_statistics.
- */
-static struct net_device_stats* if_stats(struct net_device* dev)
-{
- sdla_t *my_card;
- chdlc_private_area_t* chdlc_priv_area;
-
- /* Shutdown bug fix. In del_if() we kill
- * dev->priv pointer. This function, gets
- * called after del_if(), thus check
- * if pointer has been deleted */
- if ((chdlc_priv_area=dev->priv) == NULL)
- return NULL;
-
- my_card = chdlc_priv_area->card;
- return &my_card->wandev.stats;
-}
-
-
-/****** Cisco HDLC Firmware Interface Functions *******************************/
-
-/*============================================================================
- * Read firmware code version.
- * Put code version as ASCII string in str.
- */
-static int chdlc_read_version (sdla_t* card, char* str)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int len;
- char err;
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CODE_VERSION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- }
- else if (str) { /* is not null */
- len = mb->buffer_length;
- memcpy(str, mb->data, len);
- str[len] = '\0';
- }
- return (err);
-}
-
-/*-----------------------------------------------------------------------------
- * Configure CHDLC firmware.
- */
-static int chdlc_configure (sdla_t* card, void* data)
-{
- int err;
- CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;
- int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT);
-
- mailbox->buffer_length = data_length;
- memcpy(mailbox->data, data, data_length);
- mailbox->command = SET_CHDLC_CONFIGURATION;
- err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;
-
- if (err != COMMAND_OK) chdlc_error (card, err, mailbox);
-
- return err;
-}
-
-
-/*============================================================================
- * Set interrupt mode -- HDLC Version.
- */
-
-static int chdlc_set_intr_mode (sdla_t* card, unsigned mode)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_INT_TRIGGERS_STRUCT* int_data =
- (CHDLC_INT_TRIGGERS_STRUCT *)mb->data;
- int err;
-
- int_data->CHDLC_interrupt_triggers = mode;
- int_data->IRQ = card->hw.irq;
- int_data->interrupt_timer = 1;
-
- mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);
- mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error (card, err, mb);
- return err;
-}
-
-
-/*============================================================================
- * Enable communications.
- */
-
-static int chdlc_comm_enable (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = ENABLE_CHDLC_COMMUNICATIONS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card, err, mb);
- else
- card->u.c.comm_enabled=1;
-
- return err;
-}
-
-/*============================================================================
- * Disable communications and Drop the Modem lines (DCD and RTS).
- */
-static int chdlc_comm_disable (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = DISABLE_CHDLC_COMMUNICATIONS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card,err,mb);
-
- return err;
-}
-
-/*============================================================================
- * Read communication error statistics.
- */
-static int chdlc_read_comm_err_stats (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = READ_COMMS_ERROR_STATS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card,err,mb);
- return err;
-}
-
-
-/*============================================================================
- * Read CHDLC operational statistics.
- */
-static int chdlc_read_op_stats (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_OPERATIONAL_STATS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card,err,mb);
- return err;
-}
-
-
-/*============================================================================
- * Update communications error and general packet statistics.
- */
-static int update_comms_stats(sdla_t* card,
- chdlc_private_area_t* chdlc_priv_area)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- COMMS_ERROR_STATS_STRUCT* err_stats;
- CHDLC_OPERATIONAL_STATS_STRUCT *op_stats;
-
- /* on the first timer interrupt, read the comms error statistics */
- if(chdlc_priv_area->update_comms_stats == 2) {
- if(chdlc_read_comm_err_stats(card))
- return 1;
- err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data;
- card->wandev.stats.rx_over_errors =
- err_stats->Rx_overrun_err_count;
- card->wandev.stats.rx_crc_errors =
- err_stats->CRC_err_count;
- card->wandev.stats.rx_frame_errors =
- err_stats->Rx_abort_count;
- card->wandev.stats.rx_fifo_errors =
- err_stats->Rx_dis_pri_bfrs_full_count;
- card->wandev.stats.rx_missed_errors =
- card->wandev.stats.rx_fifo_errors;
- card->wandev.stats.tx_aborted_errors =
- err_stats->sec_Tx_abort_count;
- }
-
- /* on the second timer interrupt, read the operational statistics */
- else {
- if(chdlc_read_op_stats(card))
- return 1;
- op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data;
- card->wandev.stats.rx_length_errors =
- (op_stats->Rx_Data_discard_short_count +
- op_stats->Rx_Data_discard_long_count);
- }
-
- return 0;
-}
-
-/*============================================================================
- * Send packet.
- * Return: 0 - o.k.
- * 1 - no transmit buffers available
- */
-static int chdlc_send (sdla_t* card, void* data, unsigned len)
-{
- CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf;
-
- if (txbuf->opp_flag)
- return 1;
-
- sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len);
-
- txbuf->frame_length = len;
- txbuf->opp_flag = 1; /* start transmission */
-
- /* Update transmit buffer control fields */
- card->u.c.txbuf = ++txbuf;
-
- if ((void*)txbuf > card->u.c.txbuf_last)
- card->u.c.txbuf = card->u.c.txbuf_base;
-
- return 0;
-}
-
-/****** Firmware Error Handler **********************************************/
-
-/*============================================================================
- * Firmware error handler.
- * This routine is called whenever firmware command returns non-zero
- * return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
-{
- unsigned cmd = mb->command;
-
- switch (err) {
-
- case CMD_TIMEOUT:
- printk(KERN_ERR "%s: command 0x%02X timed out!\n",
- card->devname, cmd);
- break;
-
- case S514_BOTH_PORTS_SAME_CLK_MODE:
- if(cmd == SET_CHDLC_CONFIGURATION) {
- printk(KERN_INFO
- "%s: Configure both ports for the same clock source\n",
- card->devname);
- break;
- }
-
- default:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
- card->devname, cmd, err);
- }
-
- return 0;
-}
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * Cisco HDLC interrupt service routine.
- */
-STATIC void wsppp_isr (sdla_t* card)
-{
- struct net_device* dev;
- SHARED_MEMORY_INFO_STRUCT* flags = NULL;
- int i;
- sdla_t *my_card;
-
-
- /* Check for which port the interrupt has been generated
- * Since Secondary Port is piggybacking on the Primary
- * the check must be done here.
- */
-
- flags = card->u.c.flags;
- if (!flags->interrupt_info_struct.interrupt_type){
- /* Check for a second port (piggybacking) */
- if((my_card = card->next)){
- flags = my_card->u.c.flags;
- if (flags->interrupt_info_struct.interrupt_type){
- card = my_card;
- card->isr(card);
- return;
- }
- }
- }
-
- dev = card->wandev.dev;
- card->in_isr = 1;
- flags = card->u.c.flags;
-
- /* If we get an interrupt with no network device, stop the interrupts
- * and issue an error */
- if ((!dev || !dev->priv) && flags->interrupt_info_struct.interrupt_type !=
- COMMAND_COMPLETE_APP_INT_PEND){
- goto isr_done;
- }
-
-
- /* if critical due to peripheral operations
- * ie. update() or getstats() then reset the interrupt and
- * wait for the board to retrigger.
- */
- if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
- flags->interrupt_info_struct.
- interrupt_type = 0;
- goto isr_done;
- }
-
-
- /* On a 508 Card, if critical due to if_send
- * Major Error !!!
- */
- if(card->hw.type != SDLA_S514) {
- if(test_bit(0, (void*)&card->wandev.critical)) {
- printk(KERN_INFO "%s: Critical while in ISR: %lx\n",
- card->devname, card->wandev.critical);
- goto isr_done;
- }
- }
-
- switch(flags->interrupt_info_struct.interrupt_type) {
-
- case RX_APP_INT_PEND: /* 0x01: receive interrupt */
- rx_intr(card);
- break;
-
- case TX_APP_INT_PEND: /* 0x02: transmit interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TX_FRAME;
-
- netif_wake_queue(dev);
- break;
-
- case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */
- ++ Intr_test_counter;
- break;
-
- case CHDLC_EXCEP_COND_APP_INT_PEND: /* 0x20 */
- process_chdlc_exception(card);
- break;
-
- case GLOBAL_EXCEP_COND_APP_INT_PEND:
- process_global_exception(card);
- break;
-
- case TIMER_APP_INT_PEND:
- timer_intr(card);
- break;
-
- default:
- printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n",
- card->devname,
- flags->interrupt_info_struct.interrupt_type);
- printk(KERN_INFO "Code name: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codename[i]);
- printk(KERN_INFO "\nCode version: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codeversion[i]);
- printk(KERN_INFO "\n");
- break;
- }
-
-isr_done:
- card->in_isr = 0;
- flags->interrupt_info_struct.interrupt_type = 0;
-}
-
-/*============================================================================
- * Receive interrupt handler.
- */
-static void rx_intr (sdla_t* card)
-{
- struct net_device *dev;
- chdlc_private_area_t *chdlc_priv_area;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb;
- struct sk_buff *skb;
- unsigned len;
- unsigned addr = rxbuf->ptr_data_bfr;
- void *buf;
- int i,udp_type;
-
- if (rxbuf->opp_flag != 0x01) {
- printk(KERN_INFO
- "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n",
- card->devname, (unsigned)rxbuf, rxbuf->opp_flag);
- printk(KERN_INFO "Code name: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codename[i]);
- printk(KERN_INFO "\nCode version: ");
- for(i = 0; i < 4; i ++)
- printk(KERN_INFO "%c",
- flags->global_info_struct.codeversion[i]);
- printk(KERN_INFO "\n");
-
-
- /* Bug Fix: Mar 6 2000
- * If we get a corrupted mailbox, it measn that driver
- * is out of sync with the firmware. There is no recovery.
- * If we don't turn off all interrupts for this card
- * the machine will crash.
- */
- printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
- printk(KERN_INFO "Please contact Sangoma Technologies !\n");
- chdlc_set_intr_mode(card,0);
- return;
- }
-
- dev = card->wandev.dev;
-
- if (!dev){
- goto rx_exit;
- }
-
- if (!netif_running(dev)){
- goto rx_exit;
- }
-
- chdlc_priv_area = dev->priv;
-
- if (rxbuf->error_flag){
- goto rx_exit;
- }
- /* Take off two CRC bytes */
-
- if (rxbuf->frame_length < 7 || rxbuf->frame_length > 1506 ){
- goto rx_exit;
- }
-
- len = rxbuf->frame_length - CRC_LENGTH;
-
- /* Allocate socket buffer */
- skb = dev_alloc_skb(len);
-
- if (skb == NULL) {
- if (net_ratelimit()){
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- }
- ++card->wandev.stats.rx_dropped;
- goto rx_exit;
- }
-
- /* Copy data to the socket buffer */
- if((addr + len) > card->u.c.rx_top + 1) {
- unsigned tmp = card->u.c.rx_top - addr + 1;
- buf = skb_put(skb, tmp);
- sdla_peek(&card->hw, addr, buf, tmp);
- addr = card->u.c.rx_base;
- len -= tmp;
- }
-
- buf = skb_put(skb, len);
- sdla_peek(&card->hw, addr, buf, len);
-
- skb->protocol = htons(ETH_P_WAN_PPP);
-
- card->wandev.stats.rx_packets ++;
- card->wandev.stats.rx_bytes += skb->len;
- udp_type = udp_pkt_type( skb, card );
-
- if(udp_type == UDP_CPIPE_TYPE) {
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK,
- card, skb, dev, chdlc_priv_area)) {
- flags->interrupt_info_struct.
- interrupt_permission |=
- APP_INT_ON_TIMER;
- }
- }else{
- /* Pass it up the protocol stack */
- skb->dev = dev;
- skb->mac.raw = skb->data;
- netif_rx(skb);
- dev->last_rx = jiffies;
- }
-
-rx_exit:
- /* Release buffer element and calculate a pointer to the next one */
- rxbuf->opp_flag = 0x00;
- card->u.c.rxmb = ++ rxbuf;
- if((void*)rxbuf > card->u.c.rxbuf_last){
- card->u.c.rxmb = card->u.c.rxbuf_base;
- }
-}
-
-/*============================================================================
- * Timer interrupt handler.
- * The timer interrupt is used for two purposes:
- * 1) Processing udp calls from 'cpipemon'.
- * 2) Reading board-level statistics for updating the proc file system.
- */
-void timer_intr(sdla_t *card)
-{
- struct net_device* dev;
- chdlc_private_area_t* chdlc_priv_area = NULL;
- SHARED_MEMORY_INFO_STRUCT* flags = NULL;
-
- dev = card->wandev.dev;
- chdlc_priv_area = dev->priv;
-
- if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) {
- if (!config_chdlc(card)){
- chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG;
- }
- }
-
- /* process a udp call if pending */
- if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) {
- process_udp_mgmt_pkt(card, dev,
- chdlc_priv_area);
- chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP;
- }
-
-
- /* read the communications statistics if required */
- if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) {
- update_comms_stats(card, chdlc_priv_area);
- if(!(-- chdlc_priv_area->update_comms_stats)) {
- chdlc_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- }
- }
-
- /* only disable the timer interrupt if there are no udp or statistic */
- /* updates pending */
- if(!chdlc_priv_area->timer_int_enabled) {
- flags = card->u.c.flags;
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TIMER;
- }
-}
-
-/*------------------------------------------------------------------------------
- Miscellaneous Functions
- - set_chdlc_config() used to set configuration options on the board
-------------------------------------------------------------------------------*/
-
-static int set_chdlc_config(sdla_t* card)
-{
-
- CHDLC_CONFIGURATION_STRUCT cfg;
-
- memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT));
-
- if(card->wandev.clocking)
- cfg.baud_rate = card->wandev.bps;
-
- cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ?
- INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35;
-
- cfg.modem_config_options = 0;
- //API OPTIONS
- cfg.CHDLC_API_options = DISCARD_RX_ERROR_FRAMES;
- cfg.modem_status_timer = 100;
- cfg.CHDLC_protocol_options = HDLC_STREAMING_MODE;
- cfg.percent_data_buffer_for_Tx = 50;
- cfg.CHDLC_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT |
- CHDLC_RX_DATA_BYTE_COUNT_STAT);
- cfg.max_CHDLC_data_field_length = card->wandev.mtu;
-
- cfg.transmit_keepalive_timer = 0;
- cfg.receive_keepalive_timer = 0;
- cfg.keepalive_error_tolerance = 0;
- cfg.SLARP_request_timer = 0;
-
- cfg.IP_address = 0;
- cfg.IP_netmask = 0;
-
- return chdlc_configure(card, &cfg);
-}
-
-/*============================================================================
- * Process global exception condition
- */
-static int process_global_exception(sdla_t *card)
-{
- CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
- int err;
-
- mbox->buffer_length = 0;
- mbox->command = READ_GLOBAL_EXCEPTION_CONDITION;
- err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT;
-
- if(err != CMD_TIMEOUT ){
-
- switch(mbox->return_code) {
-
- case EXCEP_MODEM_STATUS_CHANGE:
-
- printk(KERN_INFO "%s: Modem status change\n",
- card->devname);
-
- switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) {
- case (DCD_HIGH):
- printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname);
- break;
- case (CTS_HIGH):
- printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname);
- break;
- case ((DCD_HIGH | CTS_HIGH)):
- printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname);
- break;
- default:
- printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname);
- break;
- }
-
- if (!(mbox->data[0] & DCD_HIGH) || !(mbox->data[0] & DCD_HIGH)){
- //printk(KERN_INFO "Sending TERM Request Manually !\n");
- send_ppp_term_request(card->wandev.dev);
- }
- break;
-
- case EXCEP_TRC_DISABLED:
- printk(KERN_INFO "%s: Line trace disabled\n",
- card->devname);
- break;
-
- case EXCEP_IRQ_TIMEOUT:
- printk(KERN_INFO "%s: IRQ timeout occurred\n",
- card->devname);
- break;
-
- default:
- printk(KERN_INFO "%s: Global exception %x\n",
- card->devname, mbox->return_code);
- break;
- }
- }
- return 0;
-}
-
-
-/*============================================================================
- * Process chdlc exception condition
- */
-static int process_chdlc_exception(sdla_t *card)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int err;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_EXCEPTION_CONDITION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if(err != CMD_TIMEOUT) {
-
- switch (err) {
-
- case EXCEP_LINK_ACTIVE:
- port_set_state(card, WAN_CONNECTED);
- break;
-
- case EXCEP_LINK_INACTIVE_MODEM:
- port_set_state(card, WAN_DISCONNECTED);
- break;
-
- case EXCEP_LOOPBACK_CONDITION:
- printk(KERN_INFO "%s: Loopback Condition Detected.\n",
- card->devname);
- break;
-
- case NO_CHDLC_EXCEP_COND_TO_REPORT:
- printk(KERN_INFO "%s: No exceptions reported.\n",
- card->devname);
- break;
- default:
- printk(KERN_INFO "%s: Exception Condition %x!\n",
- card->devname,err);
- break;
- }
-
- }
- return 0;
-}
-
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area )
-{
- int udp_pkt_stored = 0;
-
- if(!chdlc_priv_area->udp_pkt_lgth &&
- (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) {
- chdlc_priv_area->udp_pkt_lgth = skb->len;
- chdlc_priv_area->udp_pkt_src = udp_pkt_src;
- memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len);
- chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP;
- udp_pkt_stored = 1;
- }
-
- if(udp_pkt_src == UDP_PKT_FRM_STACK)
- dev_kfree_skb_any(skb);
- else
- dev_kfree_skb_any(skb);
-
- return(udp_pkt_stored);
-}
-
-
-/*=============================================================================
- * Process UDP management packet.
- */
-
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area )
-{
- unsigned char *buf;
- unsigned int frames, len;
- struct sk_buff *new_skb;
- unsigned short buffer_length, real_len;
- unsigned long data_ptr;
- unsigned data_length;
- int udp_mgmt_req_valid = 1;
- CHDLC_MAILBOX_STRUCT *mb = card->mbox;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- chdlc_udp_pkt_t *chdlc_udp_pkt;
- struct timeval tv;
- int err;
- char ut_char;
-
- chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data;
-
- if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
- switch(chdlc_udp_pkt->cblock.command) {
- case READ_GLOBAL_STATISTICS:
- case READ_MODEM_STATUS:
- case READ_CHDLC_LINK_STATUS:
- case CPIPE_ROUTER_UP_TIME:
- case READ_COMMS_ERROR_STATS:
- case READ_CHDLC_OPERATIONAL_STATS:
-
- /* These two commands are executed for
- * each request */
- case READ_CHDLC_CONFIGURATION:
- case READ_CHDLC_CODE_VERSION:
- udp_mgmt_req_valid = 1;
- break;
- default:
- udp_mgmt_req_valid = 0;
- break;
- }
- }
-
- if(!udp_mgmt_req_valid) {
-
- /* set length to 0 */
- chdlc_udp_pkt->cblock.buffer_length = 0;
-
- /* set return code */
- chdlc_udp_pkt->cblock.return_code = 0xCD;
-
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Warning, Illegal UDP command attempted from network: %x\n",
- card->devname,chdlc_udp_pkt->cblock.command);
- }
-
- } else {
- unsigned long trace_status_cfg_addr = 0;
- TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct;
- TRACE_STATUS_ELEMENT_STRUCT trace_element_struct;
-
- switch(chdlc_udp_pkt->cblock.command) {
-
- case CPIPE_ENABLE_TRACING:
- if (!chdlc_priv_area->TracingEnabled) {
-
- /* OPERATE_DATALINE_MONITOR */
-
- mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
- mb->command = SET_TRACE_CONFIGURATION;
-
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_config = TRACE_ACTIVE;
- /* Trace delay mode is not used because it slows
- down transfer and results in a standoff situation
- when there is a lot of data */
-
- /* Configure the Trace based on user inputs */
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |=
- chdlc_udp_pkt->data[0];
-
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_deactivation_timer = 4000;
-
-
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- card->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = err;
- mb->buffer_length = 0;
- break;
- }
-
- /* Get the base address of the trace element list */
- mb->buffer_length = 0;
- mb->command = READ_TRACE_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if (err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- chdlc_priv_area->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = err;
- mb->buffer_length = 0;
- break;
- }
-
- trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *)
- mb->data) -> ptr_trace_stat_el_cfg_struct;
-
- sdla_peek(&card->hw, trace_status_cfg_addr,
- &trace_cfg_struct, sizeof(trace_cfg_struct));
-
- chdlc_priv_area->start_trace_addr = trace_cfg_struct.
- base_addr_trace_status_elements;
-
- chdlc_priv_area->number_trace_elements =
- trace_cfg_struct.number_trace_status_elements;
-
- chdlc_priv_area->end_trace_addr = (unsigned long)
- ((TRACE_STATUS_ELEMENT_STRUCT *)
- chdlc_priv_area->start_trace_addr +
- (chdlc_priv_area->number_trace_elements - 1));
-
- chdlc_priv_area->base_addr_trace_buffer =
- trace_cfg_struct.base_addr_trace_buffer;
-
- chdlc_priv_area->end_addr_trace_buffer =
- trace_cfg_struct.end_addr_trace_buffer;
-
- chdlc_priv_area->curr_trace_addr =
- trace_cfg_struct.next_trace_element_to_use;
-
- chdlc_priv_area->available_buffer_space = 2000 -
- sizeof(ip_pkt_t) -
- sizeof(udp_pkt_t) -
- sizeof(wp_mgmt_t) -
- sizeof(cblock_t) -
- sizeof(trace_info_t);
- }
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- mb->buffer_length = 0;
- chdlc_priv_area->TracingEnabled = 1;
- break;
-
-
- case CPIPE_DISABLE_TRACING:
- if (chdlc_priv_area->TracingEnabled) {
-
- /* OPERATE_DATALINE_MONITOR */
- mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
- mb->command = SET_TRACE_CONFIGURATION;
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_config = TRACE_INACTIVE;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- }
-
- chdlc_priv_area->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- mb->buffer_length = 0;
- break;
-
-
- case CPIPE_GET_TRACE_INFO:
-
- if (!chdlc_priv_area->TracingEnabled) {
- chdlc_udp_pkt->cblock.return_code = 1;
- mb->buffer_length = 0;
- break;
- }
-
- chdlc_udp_pkt->trace_info.ismoredata = 0x00;
- buffer_length = 0; /* offset of packet already occupied */
-
- for (frames=0; frames < chdlc_priv_area->number_trace_elements; frames++){
-
- trace_pkt_t *trace_pkt = (trace_pkt_t *)
- &chdlc_udp_pkt->data[buffer_length];
-
- sdla_peek(&card->hw, chdlc_priv_area->curr_trace_addr,
- (unsigned char *)&trace_element_struct,
- sizeof(TRACE_STATUS_ELEMENT_STRUCT));
-
- if (trace_element_struct.opp_flag == 0x00) {
- break;
- }
-
- /* get pointer to real data */
- data_ptr = trace_element_struct.ptr_data_bfr;
-
- /* See if there is actual data on the trace buffer */
- if (data_ptr){
- data_length = trace_element_struct.trace_length;
- }else{
- data_length = 0;
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- }
-
- if( (chdlc_priv_area->available_buffer_space - buffer_length)
- < ( sizeof(trace_pkt_t) + data_length) ) {
-
- /* indicate there are more frames on board & exit */
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- break;
- }
-
- trace_pkt->status = trace_element_struct.trace_type;
-
- trace_pkt->time_stamp =
- trace_element_struct.trace_time_stamp;
-
- trace_pkt->real_length =
- trace_element_struct.trace_length;
-
- /* see if we can fit the frame into the user buffer */
- real_len = trace_pkt->real_length;
-
- if (data_ptr == 0) {
- trace_pkt->data_avail = 0x00;
- } else {
- unsigned tmp = 0;
-
- /* get the data from circular buffer
- must check for end of buffer */
- trace_pkt->data_avail = 0x01;
-
- if ((data_ptr + real_len) >
- chdlc_priv_area->end_addr_trace_buffer + 1){
-
- tmp = chdlc_priv_area->end_addr_trace_buffer - data_ptr + 1;
- sdla_peek(&card->hw, data_ptr,
- trace_pkt->data,tmp);
- data_ptr = chdlc_priv_area->base_addr_trace_buffer;
- }
-
- sdla_peek(&card->hw, data_ptr,
- &trace_pkt->data[tmp], real_len - tmp);
- }
-
- /* zero the opp flag to show we got the frame */
- ut_char = 0x00;
- sdla_poke(&card->hw, chdlc_priv_area->curr_trace_addr, &ut_char, 1);
-
- /* now move onto the next frame */
- chdlc_priv_area->curr_trace_addr += sizeof(TRACE_STATUS_ELEMENT_STRUCT);
-
- /* check if we went over the last address */
- if ( chdlc_priv_area->curr_trace_addr > chdlc_priv_area->end_trace_addr ) {
- chdlc_priv_area->curr_trace_addr = chdlc_priv_area->start_trace_addr;
- }
-
- if(trace_pkt->data_avail == 0x01) {
- buffer_length += real_len - 1;
- }
-
- /* for the header */
- buffer_length += sizeof(trace_pkt_t);
-
- } /* For Loop */
-
- if (frames == chdlc_priv_area->number_trace_elements){
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- }
- chdlc_udp_pkt->trace_info.num_frames = frames;
-
- mb->buffer_length = buffer_length;
- chdlc_udp_pkt->cblock.buffer_length = buffer_length;
-
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
-
- break;
-
-
- case CPIPE_FT1_READ_STATUS:
- ((unsigned char *)chdlc_udp_pkt->data )[0] =
- flags->FT1_info_struct.parallel_port_A_input;
-
- ((unsigned char *)chdlc_udp_pkt->data )[1] =
- flags->FT1_info_struct.parallel_port_B_input;
-
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- mb->buffer_length = 2;
- break;
-
- case CPIPE_ROUTER_UP_TIME:
- do_gettimeofday( &tv );
- chdlc_priv_area->router_up_time = tv.tv_sec -
- chdlc_priv_area->router_start_time;
- *(unsigned long *)&chdlc_udp_pkt->data =
- chdlc_priv_area->router_up_time;
- mb->buffer_length = sizeof(unsigned long);
- break;
-
- case FT1_MONITOR_STATUS_CTRL:
- /* Enable FT1 MONITOR STATUS */
- if ((chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_STATUS) ||
- (chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_OP_STATS)) {
-
- if( rCount++ != 0 ) {
- chdlc_udp_pkt->cblock.
- return_code = COMMAND_OK;
- mb->buffer_length = 1;
- break;
- }
- }
-
- /* Disable FT1 MONITOR STATUS */
- if( chdlc_udp_pkt->data[0] == 0) {
-
- if( --rCount != 0) {
- chdlc_udp_pkt->cblock.
- return_code = COMMAND_OK;
- mb->buffer_length = 1;
- break;
- }
- }
-
- default:
- /* it's a board command */
- mb->command = chdlc_udp_pkt->cblock.command;
- mb->buffer_length = chdlc_udp_pkt->cblock.buffer_length;
- if (mb->buffer_length) {
- memcpy(&mb->data, (unsigned char *) chdlc_udp_pkt->
- data, mb->buffer_length);
- }
- /* run the command on the board */
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK) {
- break;
- }
-
- /* copy the result back to our buffer */
- memcpy(&chdlc_udp_pkt->cblock, mb, sizeof(cblock_t));
-
- if (mb->buffer_length) {
- memcpy(&chdlc_udp_pkt->data, &mb->data,
- mb->buffer_length);
- }
-
- } /* end of switch */
- } /* end of else */
-
- /* Fill UDP TTL */
- chdlc_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
-
- len = reply_udp(chdlc_priv_area->udp_pkt_data, mb->buffer_length);
-
- if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
- if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) {
- ++ card->wandev.stats.tx_packets;
- card->wandev.stats.tx_bytes += len;
- }
- } else {
-
- /* Pass it up the stack
- Allocate socket buffer */
- if ((new_skb = dev_alloc_skb(len)) != NULL) {
- /* copy data into new_skb */
-
- buf = skb_put(new_skb, len);
- memcpy(buf, chdlc_priv_area->udp_pkt_data, len);
-
- /* Decapsulate pkt and pass it up the protocol stack */
- new_skb->protocol = htons(ETH_P_IP);
- new_skb->dev = dev;
- new_skb->mac.raw = new_skb->data;
-
- netif_rx(new_skb);
- dev->last_rx = jiffies;
- } else {
-
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- }
- }
-
- chdlc_priv_area->udp_pkt_lgth = 0;
-
- return 0;
-}
-
-/*============================================================================
- * Initialize Receive and Transmit Buffers.
- */
-
-static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_TX_STATUS_EL_CFG_STRUCT *tx_config;
- CHDLC_RX_STATUS_EL_CFG_STRUCT *rx_config;
- char err;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- return;
- }
-
- if(card->hw.type == SDLA_S514) {
- tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Tx_stat_el_cfg_struct));
- rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Rx_stat_el_cfg_struct));
-
- /* Setup Head and Tails for buffers */
- card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
- tx_config->base_addr_Tx_status_elements);
- card->u.c.txbuf_last =
- (CHDLC_DATA_TX_STATUS_EL_STRUCT *)
- card->u.c.txbuf_base +
- (tx_config->number_Tx_status_elements - 1);
-
- card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
- rx_config->base_addr_Rx_status_elements);
- card->u.c.rxbuf_last =
- (CHDLC_DATA_RX_STATUS_EL_STRUCT *)
- card->u.c.rxbuf_base +
- (rx_config->number_Rx_status_elements - 1);
-
- /* Set up next pointer to be used */
- card->u.c.txbuf = (void *)(card->hw.dpmbase +
- tx_config->next_Tx_status_element_to_use);
- card->u.c.rxmb = (void *)(card->hw.dpmbase +
- rx_config->next_Rx_status_element_to_use);
- }
- else {
- tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Tx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
-
- rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Rx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
-
- /* Setup Head and Tails for buffers */
- card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
- (tx_config->base_addr_Tx_status_elements % SDLA_WINDOWSIZE));
- card->u.c.txbuf_last =
- (CHDLC_DATA_TX_STATUS_EL_STRUCT *)card->u.c.txbuf_base
- + (tx_config->number_Tx_status_elements - 1);
- card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
- (rx_config->base_addr_Rx_status_elements % SDLA_WINDOWSIZE));
- card->u.c.rxbuf_last =
- (CHDLC_DATA_RX_STATUS_EL_STRUCT *)card->u.c.rxbuf_base
- + (rx_config->number_Rx_status_elements - 1);
-
- /* Set up next pointer to be used */
- card->u.c.txbuf = (void *)(card->hw.dpmbase +
- (tx_config->next_Tx_status_element_to_use % SDLA_WINDOWSIZE));
- card->u.c.rxmb = (void *)(card->hw.dpmbase +
- (rx_config->next_Rx_status_element_to_use % SDLA_WINDOWSIZE));
- }
-
- /* Setup Actual Buffer Start and end addresses */
- card->u.c.rx_base = rx_config->base_addr_Rx_buffer;
- card->u.c.rx_top = rx_config->end_addr_Rx_buffer;
-
-}
-
-/*=============================================================================
- * Perform Interrupt Test by running READ_CHDLC_CODE_VERSION command MAX_INTR
- * _TEST_COUNTER times.
- */
-static int intr_test( sdla_t* card)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int err,i;
-
- Intr_test_counter = 0;
-
- /* The critical flag is unset because during initialization (if_open)
- * we want the interrupts to be enabled so that when the wpc_isr is
- * called it does not exit due to critical flag set.
- */
-
- err = chdlc_set_intr_mode(card, APP_INT_ON_COMMAND_COMPLETE);
-
- if (err == CMD_OK) {
- for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) {
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CODE_VERSION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- }
- }
- else {
- return err;
- }
-
- err = chdlc_set_intr_mode(card, 0);
-
- if (err != CMD_OK)
- return err;
-
- return 0;
-}
-
-/*==============================================================================
- * Determine what type of UDP call it is. CPIPEAB ?
- */
-static int udp_pkt_type(struct sk_buff *skb, sdla_t* card)
-{
- chdlc_udp_pkt_t *chdlc_udp_pkt = (chdlc_udp_pkt_t *)skb->data;
-
- if (!strncmp(chdlc_udp_pkt->wp_mgmt.signature,UDPMGMT_SIGNATURE,8) &&
- (chdlc_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) &&
- (chdlc_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
- (chdlc_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) {
- return UDP_CPIPE_TYPE;
- }
- else return UDP_INVALID_TYPE;
-}
-
-/*============================================================================
- * Set PORT state.
- */
-static void port_set_state (sdla_t *card, int state)
-{
- struct net_device *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
-
- if (card->u.c.state != state)
- {
- switch (state)
- {
- case WAN_CONNECTED:
- printk (KERN_INFO "%s: HDLC link connected!\n",
- card->devname);
- break;
-
- case WAN_CONNECTING:
- printk (KERN_INFO "%s: HDLC link connecting...\n",
- card->devname);
- break;
-
- case WAN_DISCONNECTED:
- printk (KERN_INFO "%s: HDLC link disconnected!\n",
- card->devname);
- break;
- }
-
- card->wandev.state = card->u.c.state = state;
- chdlc_priv_area->common.state = state;
- }
-}
-
-void s508_lock (sdla_t *card, unsigned long *smp_flags)
-{
- spin_lock_irqsave(&card->wandev.lock, *smp_flags);
- if (card->next){
- /* It is ok to use spin_lock here, since we
- * already turned off interrupts */
- spin_lock(&card->next->wandev.lock);
- }
-}
-
-void s508_unlock (sdla_t *card, unsigned long *smp_flags)
-{
- if (card->next){
- spin_unlock(&card->next->wandev.lock);
- }
- spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-}
-
-
-
-/*===========================================================================
- * config_chdlc
- *
- * Configure the chdlc protocol and enable communications.
- *
- * The if_open() function binds this function to the poll routine.
- * Therefore, this function will run every time the chdlc interface
- * is brought up. We cannot run this function from the if_open
- * because if_open does not have access to the remote IP address.
- *
- * If the communications are not enabled, proceed to configure
- * the card and enable communications.
- *
- * If the communications are enabled, it means that the interface
- * was shutdown by ether the user or driver. In this case, we
- * have to check that the IP addresses have not changed. If
- * the IP addresses have changed, we have to reconfigure the firmware
- * and update the changed IP addresses. Otherwise, just exit.
- *
- */
-
-static int config_chdlc (sdla_t *card)
-{
- struct net_device *dev = card->wandev.dev;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
- if (card->u.c.comm_enabled){
- chdlc_comm_disable(card);
- port_set_state(card, WAN_DISCONNECTED);
- }
-
- if (set_chdlc_config(card)) {
- printk(KERN_INFO "%s: CHDLC Configuration Failed!\n",
- card->devname);
- return 0;
- }
- init_chdlc_tx_rx_buff(card, dev);
-
- /* Set interrupt mode and mask */
- if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME |
- APP_INT_ON_GLOBAL_EXCEP_COND |
- APP_INT_ON_TX_FRAME |
- APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
- card->devname);
- return 0;
- }
-
-
- /* Mask the Transmit and Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER);
-
-
- if (chdlc_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable chdlc communications!\n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return 0;
- }
-
- /* Initialize Rx/Tx buffer control fields */
- port_set_state(card, WAN_CONNECTING);
- return 0;
-}
-
-
-static void send_ppp_term_request(struct net_device *dev)
-{
- struct sk_buff *new_skb;
- unsigned char *buf;
-
- if ((new_skb = dev_alloc_skb(8)) != NULL) {
- /* copy data into new_skb */
-
- buf = skb_put(new_skb, 8);
- sprintf(buf,"%c%c%c%c%c%c%c%c", 0xFF,0x03,0xC0,0x21,0x05,0x98,0x00,0x07);
-
- /* Decapsulate pkt and pass it up the protocol stack */
- new_skb->protocol = htons(ETH_P_WAN_PPP);
- new_skb->dev = dev;
- new_skb->mac.raw = new_skb->data;
-
- netif_rx(new_skb);
- dev->last_rx = jiffies;
- }
-}
-
-
-MODULE_LICENSE("GPL");
-
-/****** End ****************************************************************/
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index 9d3b51c3ef5..29a756dd979 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -577,8 +577,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
We set both dma_mask and consistent_dma_mask to 28 bits
and pray pci_alloc_consistent() will use this info. It should
work on most platforms */
- if (pci_set_consistent_dma_mask(pdev, 0x0FFFFFFF) ||
- pci_set_dma_mask(pdev, 0x0FFFFFFF)) {
+ if (pci_set_consistent_dma_mask(pdev, DMA_28BIT_MASK) ||
+ pci_set_dma_mask(pdev, DMA_28BIT_MASK)) {
printk(KERN_ERR "wanXL: No usable DMA configuration\n");
return -EIO;
}
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index fd17aa8491b..e0874cbfefe 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -6,7 +6,7 @@ menu "Wireless LAN (non-hamradio)"
depends on NETDEVICES
config NET_RADIO
- bool "Wireless LAN drivers (non-hamradio)"
+ bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions"
select WIRELESS_EXT
---help---
Support for wireless LANs and everything having to do with radio,
@@ -309,7 +309,10 @@ config APPLE_AIRPORT
Say Y here to support the Airport 802.11b wireless Ethernet hardware
built into the Macintosh iBook and other recent PowerPC-based
Macintosh machines. This is essentially a Lucent Orinoco card with
- a non-standard interface
+ a non-standard interface.
+
+ This driver does not support the Airport Extreme (802.11b/g). Use
+ the BCM43xx driver for Airport Extreme cards.
config PLX_HERMES
tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
@@ -353,7 +356,7 @@ config PCI_HERMES
config ATMEL
tristate "Atmel at76c50x chipset 802.11b support"
- depends on NET_RADIO
+ depends on NET_RADIO && (PCI || PCMCIA)
select FW_LOADER
select CRC32
---help---
@@ -401,6 +404,7 @@ config PCMCIA_HERMES
config PCMCIA_SPECTRUM
tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
depends on NET_RADIO && PCMCIA && HERMES
+ select FW_LOADER
---help---
This is a driver for 802.11b cards using RAM-loadable Symbol
@@ -500,6 +504,7 @@ config PRISM54
will be called prism54.ko.
source "drivers/net/wireless/hostap/Kconfig"
+source "drivers/net/wireless/bcm43xx/Kconfig"
# yes, this works even when no drivers are selected
config NET_WIRELESS
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 3a6f7ba326c..c8677987936 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o
obj-$(CONFIG_PRISM54) += prism54/
obj-$(CONFIG_HOSTAP) += hostap/
+obj-$(CONFIG_BCM43XX) += bcm43xx/
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 108d9fed8f0..00764ddd74d 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -3139,6 +3139,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
}
if ( status & EV_LINK ) {
union iwreq_data wrqu;
+ int scan_forceloss = 0;
/* The link status has changed, if you want to put a
monitor hook in, do it here. (Remember that
interrupts are still disabled!)
@@ -3157,7 +3158,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
code) */
#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
code) */
-#define ASSOCIATED 0x0400 /* Assocatied */
+#define ASSOCIATED 0x0400 /* Associated */
+#define REASSOCIATED 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */
#define RC_RESERVED 0 /* Reserved return code */
#define RC_NOREASON 1 /* Unspecified reason */
#define RC_AUTHINV 2 /* Previous authentication invalid */
@@ -3174,44 +3176,30 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
leaving BSS */
#define RC_NOAUTH 9 /* Station requesting (Re)Association is not
Authenticated with the responding station */
- if (newStatus != ASSOCIATED) {
- if (auto_wep && !apriv->expires) {
- apriv->expires = RUN_AT(3*HZ);
- wake_up_interruptible(&apriv->thr_wait);
- }
- } else {
- struct task_struct *task = apriv->task;
+ if (newStatus == FORCELOSS && apriv->scan_timeout > 0)
+ scan_forceloss = 1;
+ if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
if (auto_wep)
apriv->expires = 0;
- if (task)
- wake_up_process (task);
+ if (apriv->task)
+ wake_up_process (apriv->task);
set_bit(FLAG_UPDATE_UNI, &apriv->flags);
set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
- }
- /* Question : is ASSOCIATED the only status
- * that is valid ? We want to catch handover
- * and reassociations as valid status
- * Jean II */
- if(newStatus == ASSOCIATED) {
-#if 0
- /* FIXME: Grabbing scan results here
- * seems to be too early??? Just wait for
- * timeout instead. */
- if (apriv->scan_timeout > 0) {
- set_bit(JOB_SCAN_RESULTS, &apriv->flags);
- wake_up_interruptible(&apriv->thr_wait);
- }
-#endif
+
if (down_trylock(&apriv->sem) != 0) {
set_bit(JOB_EVENT, &apriv->flags);
wake_up_interruptible(&apriv->thr_wait);
} else
airo_send_event(dev);
- } else {
- memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ } else if (!scan_forceloss) {
+ if (auto_wep && !apriv->expires) {
+ apriv->expires = RUN_AT(3*HZ);
+ wake_up_interruptible(&apriv->thr_wait);
+ }
/* Send event to user space */
+ memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL);
}
}
@@ -7136,10 +7124,10 @@ static int airo_set_scan(struct net_device *dev,
goto out;
/* Initiate a scan command */
+ ai->scan_timeout = RUN_AT(3*HZ);
memset(&cmd, 0, sizeof(cmd));
cmd.cmd=CMD_LISTBSS;
issuecommand(ai, &cmd, &rsp);
- ai->scan_timeout = RUN_AT(3*HZ);
wake = 1;
out:
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index a496460ce22..af0cbb6c5c0 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -80,8 +80,8 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
event handler.
*/
-static void airo_config(dev_link_t *link);
-static void airo_release(dev_link_t *link);
+static int airo_config(struct pcmcia_device *link);
+static void airo_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -101,10 +101,10 @@ static void airo_detach(struct pcmcia_device *p_dev);
/*
A linked list of "instances" of the aironet device. Each actual
PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
+ by one struct pcmcia_device structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
+ memory card driver uses an array of struct pcmcia_device pointers, where minor
device numbers are used to derive the corresponding array index.
*/
@@ -114,7 +114,7 @@ static void airo_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally shouldn't be allocated dynamically.
@@ -141,24 +141,16 @@ typedef struct local_info_t {
======================================================================*/
-static int airo_attach(struct pcmcia_device *p_dev)
+static int airo_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
local_info_t *local;
DEBUG(0, "airo_attach()\n");
- /* Initialize the dev_link_t structure */
- link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link) {
- printk(KERN_ERR "airo_cs: no memory for new device\n");
- return -ENOMEM;
- }
-
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.Handler = NULL;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->irq.Handler = NULL;
/*
General socket configuration defaults can go here. In this
@@ -167,26 +159,18 @@ static int airo_attach(struct pcmcia_device *p_dev)
and attributes of IO windows) are fixed by the nature of the
device, and can be hard-wired here.
*/
- link->conf.Attributes = 0;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.Attributes = 0;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
/* Allocate space for private device-specific data */
local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) {
printk(KERN_ERR "airo_cs: no memory for new device\n");
- kfree (link);
return -ENOMEM;
}
- link->priv = local;
+ p_dev->priv = local;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- airo_config(link);
-
- return 0;
+ return airo_config(p_dev);
} /* airo_attach */
/*======================================================================
@@ -198,14 +182,11 @@ static int airo_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void airo_detach(struct pcmcia_device *p_dev)
+static void airo_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "airo_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- airo_release(link);
+ airo_release(link);
if ( ((local_info_t*)link->priv)->eth_dev ) {
stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 );
@@ -213,7 +194,6 @@ static void airo_detach(struct pcmcia_device *p_dev)
((local_info_t*)link->priv)->eth_dev = NULL;
kfree(link->priv);
- kfree(link);
} /* airo_detach */
/*======================================================================
@@ -227,9 +207,8 @@ static void airo_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void airo_config(dev_link_t *link)
+static int airo_config(struct pcmcia_device *link)
{
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
local_info_t *dev;
@@ -237,8 +216,7 @@ static void airo_config(dev_link_t *link)
u_char buf[64];
win_req_t req;
memreq_t map;
-
- handle = link->handle;
+
dev = link->priv;
DEBUG(0, "airo_config(0x%p)\n", link);
@@ -252,15 +230,12 @@ static void airo_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
-
- /* Configure card */
- link->state |= DEV_CONFIG;
-
+
/*
In this loop, we scan the CIS for configuration table entries,
each of which describes a valid card configuration, including
@@ -274,12 +249,12 @@ static void airo_config(dev_link_t *link)
will only use the CIS to fill in implementation-defined details.
*/
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t dflt = { 0 };
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -294,16 +269,11 @@ static void airo_config(dev_link_t *link)
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
- else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
-
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
/* Do we need to allocate an interrupt? */
@@ -329,12 +299,12 @@ static void airo_config(dev_link_t *link)
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
/*
Now set up a common memory window, if needed. There is room
- in the dev_link_t structure for one memory window handle,
+ in the struct pcmcia_device structure for one memory window handle,
but if the base addresses need to be saved, or if multiple
windows are needed, the info should go in the private data
structure for this device.
@@ -350,7 +320,7 @@ static void airo_config(dev_link_t *link)
req.Base = mem->win[0].host_addr;
req.Size = mem->win[0].len;
req.AccessSpeed = 0;
- if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+ if (pcmcia_request_window(&link, &req, &link->win) != 0)
goto next_entry;
map.Page = 0; map.CardOffset = mem->win[0].card_addr;
if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -360,7 +330,7 @@ static void airo_config(dev_link_t *link)
break;
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
/*
@@ -369,33 +339,32 @@ static void airo_config(dev_link_t *link)
irq structure is initialized.
*/
if (link->conf.Attributes & CONF_ENABLE_IRQ)
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/*
This actually configures the PCMCIA socket -- setting up
the I/O windows and the interrupt mapping, and putting the
card and host interface into "Memory and IO" mode.
*/
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
((local_info_t*)link->priv)->eth_dev =
init_airo_card( link->irq.AssignedIRQ,
- link->io.BasePort1, 1, &handle_to_dev(handle) );
+ link->io.BasePort1, 1, &handle_to_dev(link) );
if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed;
/*
At this point, the dev_node_t structure(s) need to be
- initialized and arranged in a linked list at link->dev.
+ initialized and arranged in a linked list at link->dev_node.
*/
strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
dev->node.major = dev->node.minor = 0;
- link->dev = &dev->node;
+ link->dev_node = &dev->node;
/* Finally, report what we've done */
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev->node.dev_name, link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "%s: index 0x%02x: ",
+ dev->node.dev_name, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
@@ -408,14 +377,12 @@ static void airo_config(dev_link_t *link)
printk(", mem 0x%06lx-0x%06lx", req.Base,
req.Base+req.Size-1);
printk("\n");
-
- link->state &= ~DEV_CONFIG_PENDING;
- return;
-
+ return 0;
+
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
airo_release(link);
-
+ return -ENODEV;
} /* airo_config */
/*======================================================================
@@ -426,51 +393,26 @@ static void airo_config(dev_link_t *link)
======================================================================*/
-static void airo_release(dev_link_t *link)
+static void airo_release(struct pcmcia_device *link)
{
DEBUG(0, "airo_release(0x%p)\n", link);
-
- /* Unlink the device chain */
- link->dev = NULL;
-
- /*
- In a normal driver, additional code may be needed to release
- other kernel data structures associated with this device.
- */
-
- /* Don't bother checking to see if these succeed or not */
- if (link->win)
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static int airo_suspend(struct pcmcia_device *p_dev)
+static int airo_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *local = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- netif_device_detach(local->eth_dev);
- pcmcia_release_configuration(link->handle);
- }
+ netif_device_detach(local->eth_dev);
return 0;
}
-static int airo_resume(struct pcmcia_device *p_dev)
+static int airo_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *local = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
reset_airo_card(local->eth_dev);
netif_device_attach(local->eth_dev);
}
@@ -492,7 +434,7 @@ static struct pcmcia_driver airo_driver = {
.drv = {
.name = "airo_cs",
},
- .probe = airo_attach,
+ .probe = airo_probe,
.remove = airo_detach,
.id_table = airo_ids,
.suspend = airo_suspend,
diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c
index 0e1ac338cac..bed6823d980 100644
--- a/drivers/net/wireless/arlan-main.c
+++ b/drivers/net/wireless/arlan-main.c
@@ -1838,7 +1838,7 @@ struct net_device * __init arlan_probe(int unit)
}
#ifdef MODULE
-int init_module(void)
+int __init init_module(void)
{
int i = 0;
@@ -1860,7 +1860,7 @@ int init_module(void)
}
-void cleanup_module(void)
+void __exit cleanup_module(void)
{
int i = 0;
struct net_device *dev;
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 87afa6878f2..8606c88886f 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -3463,6 +3463,7 @@ static void atmel_command_irq(struct atmel_private *priv)
u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET));
int fast_scan;
+ union iwreq_data wrqu;
if (status == CMD_STATUS_IDLE ||
status == CMD_STATUS_IN_PROGRESS)
@@ -3487,6 +3488,7 @@ static void atmel_command_irq(struct atmel_private *priv)
atmel_scan(priv, 1);
} else {
int bss_index = retrieve_bss(priv);
+ int notify_scan_complete = 1;
if (bss_index != -1) {
atmel_join_bss(priv, bss_index);
} else if (priv->operating_mode == IW_MODE_ADHOC &&
@@ -3495,8 +3497,14 @@ static void atmel_command_irq(struct atmel_private *priv)
} else {
priv->fast_scan = !fast_scan;
atmel_scan(priv, 1);
+ notify_scan_complete = 0;
}
priv->site_survey_state = SITE_SURVEY_COMPLETED;
+ if (notify_scan_complete) {
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+ }
}
break;
@@ -3509,6 +3517,9 @@ static void atmel_command_irq(struct atmel_private *priv)
priv->site_survey_state = SITE_SURVEY_COMPLETED;
if (priv->station_is_associated) {
atmel_enter_state(priv, STATION_STATE_READY);
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
} else {
atmel_scan(priv, 1);
}
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index d6f4a5a3e55..26bf1127524 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -91,8 +91,8 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
event handler.
*/
-static void atmel_config(dev_link_t *link);
-static void atmel_release(dev_link_t *link);
+static int atmel_config(struct pcmcia_device *link);
+static void atmel_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
@@ -112,10 +112,10 @@ static void atmel_detach(struct pcmcia_device *p_dev);
/*
A linked list of "instances" of the atmelnet device. Each actual
PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
+ by one struct pcmcia_device structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
+ memory card driver uses an array of struct pcmcia_device pointers, where minor
device numbers are used to derive the corresponding array index.
*/
@@ -125,7 +125,7 @@ static void atmel_detach(struct pcmcia_device *p_dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally shouldn't be allocated dynamically.
@@ -152,24 +152,16 @@ typedef struct local_info_t {
======================================================================*/
-static int atmel_attach(struct pcmcia_device *p_dev)
+static int atmel_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
local_info_t *local;
DEBUG(0, "atmel_attach()\n");
- /* Initialize the dev_link_t structure */
- link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link) {
- printk(KERN_ERR "atmel_cs: no memory for new device\n");
- return -ENOMEM;
- }
-
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.Handler = NULL;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->irq.Handler = NULL;
/*
General socket configuration defaults can go here. In this
@@ -178,26 +170,18 @@ static int atmel_attach(struct pcmcia_device *p_dev)
and attributes of IO windows) are fixed by the nature of the
device, and can be hard-wired here.
*/
- link->conf.Attributes = 0;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.Attributes = 0;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
/* Allocate space for private device-specific data */
local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) {
printk(KERN_ERR "atmel_cs: no memory for new device\n");
- kfree (link);
return -ENOMEM;
}
- link->priv = local;
+ p_dev->priv = local;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- atmel_config(link);
-
- return 0;
+ return atmel_config(p_dev);
} /* atmel_attach */
/*======================================================================
@@ -209,17 +193,13 @@ static int atmel_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void atmel_detach(struct pcmcia_device *p_dev)
+static void atmel_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "atmel_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- atmel_release(link);
+ atmel_release(link);
kfree(link->priv);
- kfree(link);
}
/*======================================================================
@@ -236,19 +216,17 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
/* Call-back function to interrogate PCMCIA-specific information
about the current existance of the card */
static int card_present(void *arg)
-{
- dev_link_t *link = (dev_link_t *)arg;
- if (link->state & DEV_SUSPEND)
- return 0;
- else if (link->state & DEV_PRESENT)
+{
+ struct pcmcia_device *link = (struct pcmcia_device *)arg;
+
+ if (pcmcia_dev_present(link))
return 1;
-
+
return 0;
}
-static void atmel_config(dev_link_t *link)
+static int atmel_config(struct pcmcia_device *link)
{
- client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
local_info_t *dev;
@@ -256,9 +234,8 @@ static void atmel_config(dev_link_t *link)
u_char buf[64];
struct pcmcia_device_id *did;
- handle = link->handle;
dev = link->priv;
- did = handle_to_dev(handle).driver_data;
+ did = handle_to_dev(link).driver_data;
DEBUG(0, "atmel_config(0x%p)\n", link);
@@ -272,15 +249,12 @@ static void atmel_config(dev_link_t *link)
registers.
*/
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
-
- /* Configure card */
- link->state |= DEV_CONFIG;
-
+
/*
In this loop, we scan the CIS for configuration table entries,
each of which describes a valid card configuration, including
@@ -294,12 +268,12 @@ static void atmel_config(dev_link_t *link)
will only use the CIS to fill in implementation-defined details.
*/
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t dflt = { 0 };
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -314,16 +288,11 @@ static void atmel_config(dev_link_t *link)
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
- else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
-
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
/* Do we need to allocate an interrupt? */
@@ -349,14 +318,14 @@ static void atmel_config(dev_link_t *link)
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
/* If we got this far, we're cool! */
break;
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
/*
@@ -365,14 +334,14 @@ static void atmel_config(dev_link_t *link)
irq structure is initialized.
*/
if (link->conf.Attributes & CONF_ENABLE_IRQ)
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/*
This actually configures the PCMCIA socket -- setting up
the I/O windows and the interrupt mapping, and putting the
card and host interface into "Memory and IO" mode.
*/
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
if (link->irq.AssignedIRQ == 0) {
printk(KERN_ALERT
@@ -384,7 +353,7 @@ static void atmel_config(dev_link_t *link)
init_atmel_card(link->irq.AssignedIRQ,
link->io.BasePort1,
did ? did->driver_info : ATMEL_FW_TYPE_NONE,
- &handle_to_dev(handle),
+ &handle_to_dev(link),
card_present,
link);
if (!((local_info_t*)link->priv)->eth_dev)
@@ -393,18 +362,18 @@ static void atmel_config(dev_link_t *link)
/*
At this point, the dev_node_t structure(s) need to be
- initialized and arranged in a linked list at link->dev.
+ initialized and arranged in a linked list at link->dev_node.
*/
strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
dev->node.major = dev->node.minor = 0;
- link->dev = &dev->node;
-
- link->state &= ~DEV_CONFIG_PENDING;
- return;
-
+ link->dev_node = &dev->node;
+
+ return 0;
+
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
atmel_release(link);
+ return -ENODEV;
}
/*======================================================================
@@ -415,53 +384,34 @@ static void atmel_config(dev_link_t *link)
======================================================================*/
-static void atmel_release(dev_link_t *link)
+static void atmel_release(struct pcmcia_device *link)
{
struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
-
+
DEBUG(0, "atmel_release(0x%p)\n", link);
-
- /* Unlink the device chain */
- link->dev = NULL;
-
- if (dev)
+
+ if (dev)
stop_atmel_card(dev);
- ((local_info_t*)link->priv)->eth_dev = NULL;
-
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ ((local_info_t*)link->priv)->eth_dev = NULL;
+
+ pcmcia_disable_device(link);
}
-static int atmel_suspend(struct pcmcia_device *dev)
+static int atmel_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
local_info_t *local = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- netif_device_detach(local->eth_dev);
- pcmcia_release_configuration(link->handle);
- }
+ netif_device_detach(local->eth_dev);
return 0;
}
-static int atmel_resume(struct pcmcia_device *dev)
+static int atmel_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
local_info_t *local = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- atmel_open(local->eth_dev);
- netif_device_attach(local->eth_dev);
- }
+ atmel_open(local->eth_dev);
+ netif_device_attach(local->eth_dev);
return 0;
}
@@ -515,7 +465,7 @@ static struct pcmcia_driver atmel_driver = {
.drv = {
.name = "atmel_cs",
},
- .probe = atmel_attach,
+ .probe = atmel_probe,
.remove = atmel_detach,
.id_table = atmel_ids,
.suspend = atmel_suspend,
diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig
new file mode 100644
index 00000000000..25ea4748f0b
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/Kconfig
@@ -0,0 +1,65 @@
+config BCM43XX
+ tristate "Broadcom BCM43xx wireless support"
+ depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL
+ select FW_LOADER
+ ---help---
+ This is an experimental driver for the Broadcom 43xx wireless chip,
+ found in the Apple Airport Extreme and various other devices.
+
+config BCM43XX_DEBUG
+ bool "Broadcom BCM43xx debugging (RECOMMENDED)"
+ depends on BCM43XX
+ default y
+ ---help---
+ Broadcom 43xx debugging messages.
+ Say Y, because the driver is still very experimental and
+ this will help you get it running.
+
+config BCM43XX_DMA
+ bool
+ depends on BCM43XX
+
+config BCM43XX_PIO
+ bool
+ depends on BCM43XX
+
+choice
+ prompt "BCM43xx data transfer mode"
+ depends on BCM43XX
+ default BCM43XX_DMA_AND_PIO_MODE
+
+config BCM43XX_DMA_AND_PIO_MODE
+ bool "DMA + PIO"
+ select BCM43XX_DMA
+ select BCM43XX_PIO
+ ---help---
+ Include both, Direct Memory Access (DMA) and Programmed I/O (PIO)
+ data transfer modes.
+ The actually used mode is selectable through the module
+ parameter "pio". If the module parameter is pio=0, DMA is used.
+ Otherwise PIO is used. DMA is default.
+
+ If unsure, choose this option.
+
+config BCM43XX_DMA_MODE
+ bool "DMA (Direct Memory Access) only"
+ select BCM43XX_DMA
+ ---help---
+ Only include Direct Memory Access (DMA).
+ This reduces the size of the driver module, by omitting the PIO code.
+
+config BCM43XX_PIO_MODE
+ bool "PIO (Programmed I/O) only"
+ select BCM43XX_PIO
+ ---help---
+ Only include Programmed I/O (PIO).
+ This reduces the size of the driver module, by omitting the DMA code.
+ Please note that PIO transfers are slow (compared to DMA).
+
+ Also note that not all devices of the 43xx series support PIO.
+ The 4306 (Apple Airport Extreme and others) supports PIO, while
+ the 4318 is known to _not_ support PIO.
+
+ Only use PIO, if DMA does not work for you.
+
+endchoice
diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile
new file mode 100644
index 00000000000..bb5220c629d
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/Makefile
@@ -0,0 +1,12 @@
+obj-$(CONFIG_BCM43XX) += bcm43xx.o
+bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o
+
+bcm43xx-obj-$(CONFIG_BCM43XX_DMA) += bcm43xx_dma.o
+bcm43xx-obj-$(CONFIG_BCM43XX_PIO) += bcm43xx_pio.o
+
+bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \
+ bcm43xx_radio.o bcm43xx_phy.o \
+ bcm43xx_power.o bcm43xx_wx.o \
+ bcm43xx_leds.o bcm43xx_ethtool.o \
+ bcm43xx_xmit.o bcm43xx_sysfs.o \
+ $(bcm43xx-obj-y)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
new file mode 100644
index 00000000000..2e83083935e
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -0,0 +1,937 @@
+#ifndef BCM43xx_H_
+#define BCM43xx_H_
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/stringify.h>
+#include <linux/pci.h>
+#include <net/ieee80211.h>
+#include <net/ieee80211softmac.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+
+
+#include "bcm43xx_debugfs.h"
+#include "bcm43xx_leds.h"
+
+
+#define PFX KBUILD_MODNAME ": "
+
+#define BCM43xx_SWITCH_CORE_MAX_RETRIES 50
+#define BCM43xx_IRQWAIT_MAX_RETRIES 50
+
+#define BCM43xx_IO_SIZE 8192
+
+/* Active Core PCI Configuration Register. */
+#define BCM43xx_PCICFG_ACTIVE_CORE 0x80
+/* SPROM control register. */
+#define BCM43xx_PCICFG_SPROMCTL 0x88
+/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */
+#define BCM43xx_PCICFG_ICR 0x94
+
+/* MMIO offsets */
+#define BCM43xx_MMIO_DMA1_REASON 0x20
+#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x24
+#define BCM43xx_MMIO_DMA2_REASON 0x28
+#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x2C
+#define BCM43xx_MMIO_DMA3_REASON 0x30
+#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x34
+#define BCM43xx_MMIO_DMA4_REASON 0x38
+#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x3C
+#define BCM43xx_MMIO_STATUS_BITFIELD 0x120
+#define BCM43xx_MMIO_STATUS2_BITFIELD 0x124
+#define BCM43xx_MMIO_GEN_IRQ_REASON 0x128
+#define BCM43xx_MMIO_GEN_IRQ_MASK 0x12C
+#define BCM43xx_MMIO_RAM_CONTROL 0x130
+#define BCM43xx_MMIO_RAM_DATA 0x134
+#define BCM43xx_MMIO_PS_STATUS 0x140
+#define BCM43xx_MMIO_RADIO_HWENABLED_HI 0x158
+#define BCM43xx_MMIO_SHM_CONTROL 0x160
+#define BCM43xx_MMIO_SHM_DATA 0x164
+#define BCM43xx_MMIO_SHM_DATA_UNALIGNED 0x166
+#define BCM43xx_MMIO_XMITSTAT_0 0x170
+#define BCM43xx_MMIO_XMITSTAT_1 0x174
+#define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */
+#define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */
+#define BCM43xx_MMIO_DMA1_BASE 0x200
+#define BCM43xx_MMIO_DMA2_BASE 0x220
+#define BCM43xx_MMIO_DMA3_BASE 0x240
+#define BCM43xx_MMIO_DMA4_BASE 0x260
+#define BCM43xx_MMIO_PIO1_BASE 0x300
+#define BCM43xx_MMIO_PIO2_BASE 0x310
+#define BCM43xx_MMIO_PIO3_BASE 0x320
+#define BCM43xx_MMIO_PIO4_BASE 0x330
+#define BCM43xx_MMIO_PHY_VER 0x3E0
+#define BCM43xx_MMIO_PHY_RADIO 0x3E2
+#define BCM43xx_MMIO_ANTENNA 0x3E8
+#define BCM43xx_MMIO_CHANNEL 0x3F0
+#define BCM43xx_MMIO_CHANNEL_EXT 0x3F4
+#define BCM43xx_MMIO_RADIO_CONTROL 0x3F6
+#define BCM43xx_MMIO_RADIO_DATA_HIGH 0x3F8
+#define BCM43xx_MMIO_RADIO_DATA_LOW 0x3FA
+#define BCM43xx_MMIO_PHY_CONTROL 0x3FC
+#define BCM43xx_MMIO_PHY_DATA 0x3FE
+#define BCM43xx_MMIO_MACFILTER_CONTROL 0x420
+#define BCM43xx_MMIO_MACFILTER_DATA 0x422
+#define BCM43xx_MMIO_RADIO_HWENABLED_LO 0x49A
+#define BCM43xx_MMIO_GPIO_CONTROL 0x49C
+#define BCM43xx_MMIO_GPIO_MASK 0x49E
+#define BCM43xx_MMIO_TSF_0 0x632 /* core rev < 3 only */
+#define BCM43xx_MMIO_TSF_1 0x634 /* core rev < 3 only */
+#define BCM43xx_MMIO_TSF_2 0x636 /* core rev < 3 only */
+#define BCM43xx_MMIO_TSF_3 0x638 /* core rev < 3 only */
+#define BCM43xx_MMIO_POWERUP_DELAY 0x6A8
+
+/* SPROM offsets. */
+#define BCM43xx_SPROM_BASE 0x1000
+#define BCM43xx_SPROM_BOARDFLAGS2 0x1c
+#define BCM43xx_SPROM_IL0MACADDR 0x24
+#define BCM43xx_SPROM_ET0MACADDR 0x27
+#define BCM43xx_SPROM_ET1MACADDR 0x2a
+#define BCM43xx_SPROM_ETHPHY 0x2d
+#define BCM43xx_SPROM_BOARDREV 0x2e
+#define BCM43xx_SPROM_PA0B0 0x2f
+#define BCM43xx_SPROM_PA0B1 0x30
+#define BCM43xx_SPROM_PA0B2 0x31
+#define BCM43xx_SPROM_WL0GPIO0 0x32
+#define BCM43xx_SPROM_WL0GPIO2 0x33
+#define BCM43xx_SPROM_MAXPWR 0x34
+#define BCM43xx_SPROM_PA1B0 0x35
+#define BCM43xx_SPROM_PA1B1 0x36
+#define BCM43xx_SPROM_PA1B2 0x37
+#define BCM43xx_SPROM_IDL_TSSI_TGT 0x38
+#define BCM43xx_SPROM_BOARDFLAGS 0x39
+#define BCM43xx_SPROM_ANTENNA_GAIN 0x3a
+#define BCM43xx_SPROM_VERSION 0x3f
+
+/* BCM43xx_SPROM_BOARDFLAGS values */
+#define BCM43xx_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */
+#define BCM43xx_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */
+#define BCM43xx_BFL_AIRLINEMODE 0x0004 /* implements GPIO 13 radio disable indication */
+#define BCM43xx_BFL_RSSI 0x0008 /* software calculates nrssi slope. */
+#define BCM43xx_BFL_ENETSPI 0x0010 /* has ephy roboswitch spi */
+#define BCM43xx_BFL_XTAL_NOSLOW 0x0020 /* no slow clock available */
+#define BCM43xx_BFL_CCKHIPWR 0x0040 /* can do high power CCK transmission */
+#define BCM43xx_BFL_ENETADM 0x0080 /* has ADMtek switch */
+#define BCM43xx_BFL_ENETVLAN 0x0100 /* can do vlan */
+#define BCM43xx_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */
+#define BCM43xx_BFL_NOPCI 0x0400 /* leaves PCI floating */
+#define BCM43xx_BFL_FEM 0x0800 /* supports the Front End Module */
+#define BCM43xx_BFL_EXTLNA 0x1000 /* has an external LNA */
+#define BCM43xx_BFL_HGPA 0x2000 /* had high gain PA */
+#define BCM43xx_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */
+#define BCM43xx_BFL_ALTIQ 0x8000 /* alternate I/Q settings */
+
+/* GPIO register offset, in both ChipCommon and PCI core. */
+#define BCM43xx_GPIO_CONTROL 0x6c
+
+/* SHM Routing */
+#define BCM43xx_SHM_SHARED 0x0001
+#define BCM43xx_SHM_WIRELESS 0x0002
+#define BCM43xx_SHM_PCM 0x0003
+#define BCM43xx_SHM_HWMAC 0x0004
+#define BCM43xx_SHM_UCODE 0x0300
+
+/* MacFilter offsets. */
+#define BCM43xx_MACFILTER_SELF 0x0000
+#define BCM43xx_MACFILTER_ASSOC 0x0003
+
+/* Chipcommon registers. */
+#define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04
+#define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0
+#define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4
+#define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8
+#define BCM43xx_CHIPCOMMON_SYSCLKCTL 0xC0
+
+/* PCI core specific registers. */
+#define BCM43xx_PCICORE_BCAST_ADDR 0x50
+#define BCM43xx_PCICORE_BCAST_DATA 0x54
+#define BCM43xx_PCICORE_SBTOPCI2 0x108
+
+/* SBTOPCI2 values. */
+#define BCM43xx_SBTOPCI2_PREFETCH 0x4
+#define BCM43xx_SBTOPCI2_BURST 0x8
+
+/* Chipcommon capabilities. */
+#define BCM43xx_CAPABILITIES_PCTL 0x00040000
+#define BCM43xx_CAPABILITIES_PLLMASK 0x00030000
+#define BCM43xx_CAPABILITIES_PLLSHIFT 16
+#define BCM43xx_CAPABILITIES_FLASHMASK 0x00000700
+#define BCM43xx_CAPABILITIES_FLASHSHIFT 8
+#define BCM43xx_CAPABILITIES_EXTBUSPRESENT 0x00000040
+#define BCM43xx_CAPABILITIES_UARTGPIO 0x00000020
+#define BCM43xx_CAPABILITIES_UARTCLOCKMASK 0x00000018
+#define BCM43xx_CAPABILITIES_UARTCLOCKSHIFT 3
+#define BCM43xx_CAPABILITIES_MIPSBIGENDIAN 0x00000004
+#define BCM43xx_CAPABILITIES_NRUARTSMASK 0x00000003
+
+/* PowerControl */
+#define BCM43xx_PCTL_IN 0xB0
+#define BCM43xx_PCTL_OUT 0xB4
+#define BCM43xx_PCTL_OUTENABLE 0xB8
+#define BCM43xx_PCTL_XTAL_POWERUP 0x40
+#define BCM43xx_PCTL_PLL_POWERDOWN 0x80
+
+/* PowerControl Clock Modes */
+#define BCM43xx_PCTL_CLK_FAST 0x00
+#define BCM43xx_PCTL_CLK_SLOW 0x01
+#define BCM43xx_PCTL_CLK_DYNAMIC 0x02
+
+#define BCM43xx_PCTL_FORCE_SLOW 0x0800
+#define BCM43xx_PCTL_FORCE_PLL 0x1000
+#define BCM43xx_PCTL_DYN_XTAL 0x2000
+
+/* COREIDs */
+#define BCM43xx_COREID_CHIPCOMMON 0x800
+#define BCM43xx_COREID_ILINE20 0x801
+#define BCM43xx_COREID_SDRAM 0x803
+#define BCM43xx_COREID_PCI 0x804
+#define BCM43xx_COREID_MIPS 0x805
+#define BCM43xx_COREID_ETHERNET 0x806
+#define BCM43xx_COREID_V90 0x807
+#define BCM43xx_COREID_USB11_HOSTDEV 0x80a
+#define BCM43xx_COREID_IPSEC 0x80b
+#define BCM43xx_COREID_PCMCIA 0x80d
+#define BCM43xx_COREID_EXT_IF 0x80f
+#define BCM43xx_COREID_80211 0x812
+#define BCM43xx_COREID_MIPS_3302 0x816
+#define BCM43xx_COREID_USB11_HOST 0x817
+#define BCM43xx_COREID_USB11_DEV 0x818
+#define BCM43xx_COREID_USB20_HOST 0x819
+#define BCM43xx_COREID_USB20_DEV 0x81a
+#define BCM43xx_COREID_SDIO_HOST 0x81b
+
+/* Core Information Registers */
+#define BCM43xx_CIR_BASE 0xf00
+#define BCM43xx_CIR_SBTPSFLAG (BCM43xx_CIR_BASE + 0x18)
+#define BCM43xx_CIR_SBIMSTATE (BCM43xx_CIR_BASE + 0x90)
+#define BCM43xx_CIR_SBINTVEC (BCM43xx_CIR_BASE + 0x94)
+#define BCM43xx_CIR_SBTMSTATELOW (BCM43xx_CIR_BASE + 0x98)
+#define BCM43xx_CIR_SBTMSTATEHIGH (BCM43xx_CIR_BASE + 0x9c)
+#define BCM43xx_CIR_SBIMCONFIGLOW (BCM43xx_CIR_BASE + 0xa8)
+#define BCM43xx_CIR_SB_ID_HI (BCM43xx_CIR_BASE + 0xfc)
+
+/* Mask to get the Backplane Flag Number from SBTPSFLAG. */
+#define BCM43xx_BACKPLANE_FLAG_NR_MASK 0x3f
+
+/* SBIMCONFIGLOW values/masks. */
+#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK 0x00000007
+#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT 0
+#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK 0x00000070
+#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT 4
+#define BCM43xx_SBIMCONFIGLOW_CONNID_MASK 0x00ff0000
+#define BCM43xx_SBIMCONFIGLOW_CONNID_SHIFT 16
+
+/* sbtmstatelow state flags */
+#define BCM43xx_SBTMSTATELOW_RESET 0x01
+#define BCM43xx_SBTMSTATELOW_REJECT 0x02
+#define BCM43xx_SBTMSTATELOW_CLOCK 0x10000
+#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000
+
+/* sbtmstatehigh state flags */
+#define BCM43xx_SBTMSTATEHIGH_SERROR 0x1
+#define BCM43xx_SBTMSTATEHIGH_BUSY 0x4
+
+/* sbimstate flags */
+#define BCM43xx_SBIMSTATE_IB_ERROR 0x20000
+#define BCM43xx_SBIMSTATE_TIMEOUT 0x40000
+
+/* PHYVersioning */
+#define BCM43xx_PHYTYPE_A 0x00
+#define BCM43xx_PHYTYPE_B 0x01
+#define BCM43xx_PHYTYPE_G 0x02
+
+/* PHYRegisters */
+#define BCM43xx_PHY_ILT_A_CTRL 0x0072
+#define BCM43xx_PHY_ILT_A_DATA1 0x0073
+#define BCM43xx_PHY_ILT_A_DATA2 0x0074
+#define BCM43xx_PHY_G_LO_CONTROL 0x0810
+#define BCM43xx_PHY_ILT_G_CTRL 0x0472
+#define BCM43xx_PHY_ILT_G_DATA1 0x0473
+#define BCM43xx_PHY_ILT_G_DATA2 0x0474
+#define BCM43xx_PHY_A_PCTL 0x007B
+#define BCM43xx_PHY_G_PCTL 0x0029
+#define BCM43xx_PHY_A_CRS 0x0029
+#define BCM43xx_PHY_RADIO_BITFIELD 0x0401
+#define BCM43xx_PHY_G_CRS 0x0429
+#define BCM43xx_PHY_NRSSILT_CTRL 0x0803
+#define BCM43xx_PHY_NRSSILT_DATA 0x0804
+
+/* RadioRegisters */
+#define BCM43xx_RADIOCTL_ID 0x01
+
+/* StatusBitField */
+#define BCM43xx_SBF_MAC_ENABLED 0x00000001
+#define BCM43xx_SBF_2 0x00000002 /*FIXME: fix name*/
+#define BCM43xx_SBF_CORE_READY 0x00000004
+#define BCM43xx_SBF_400 0x00000400 /*FIXME: fix name*/
+#define BCM43xx_SBF_4000 0x00004000 /*FIXME: fix name*/
+#define BCM43xx_SBF_8000 0x00008000 /*FIXME: fix name*/
+#define BCM43xx_SBF_XFER_REG_BYTESWAP 0x00010000
+#define BCM43xx_SBF_MODE_NOTADHOC 0x00020000
+#define BCM43xx_SBF_MODE_AP 0x00040000
+#define BCM43xx_SBF_RADIOREG_LOCK 0x00080000
+#define BCM43xx_SBF_MODE_MONITOR 0x00400000
+#define BCM43xx_SBF_MODE_PROMISC 0x01000000
+#define BCM43xx_SBF_PS1 0x02000000
+#define BCM43xx_SBF_PS2 0x04000000
+#define BCM43xx_SBF_NO_SSID_BCAST 0x08000000
+#define BCM43xx_SBF_TIME_UPDATE 0x10000000
+#define BCM43xx_SBF_80000000 0x80000000 /*FIXME: fix name*/
+
+/* MicrocodeFlagsBitfield (addr + lo-word values?)*/
+#define BCM43xx_UCODEFLAGS_OFFSET 0x005E
+
+#define BCM43xx_UCODEFLAG_AUTODIV 0x0001
+#define BCM43xx_UCODEFLAG_UNKBGPHY 0x0002
+#define BCM43xx_UCODEFLAG_UNKBPHY 0x0004
+#define BCM43xx_UCODEFLAG_UNKGPHY 0x0020
+#define BCM43xx_UCODEFLAG_UNKPACTRL 0x0040
+#define BCM43xx_UCODEFLAG_JAPAN 0x0080
+
+/* Generic-Interrupt reasons. */
+#define BCM43xx_IRQ_READY (1 << 0)
+#define BCM43xx_IRQ_BEACON (1 << 1)
+#define BCM43xx_IRQ_PS (1 << 2)
+#define BCM43xx_IRQ_REG124 (1 << 5)
+#define BCM43xx_IRQ_PMQ (1 << 6)
+#define BCM43xx_IRQ_PIO_WORKAROUND (1 << 8)
+#define BCM43xx_IRQ_XMIT_ERROR (1 << 11)
+#define BCM43xx_IRQ_RX (1 << 15)
+#define BCM43xx_IRQ_SCAN (1 << 16)
+#define BCM43xx_IRQ_NOISE (1 << 18)
+#define BCM43xx_IRQ_XMIT_STATUS (1 << 29)
+
+#define BCM43xx_IRQ_ALL 0xffffffff
+#define BCM43xx_IRQ_INITIAL (BCM43xx_IRQ_PS | \
+ BCM43xx_IRQ_REG124 | \
+ BCM43xx_IRQ_PMQ | \
+ BCM43xx_IRQ_XMIT_ERROR | \
+ BCM43xx_IRQ_RX | \
+ BCM43xx_IRQ_SCAN | \
+ BCM43xx_IRQ_NOISE | \
+ BCM43xx_IRQ_XMIT_STATUS)
+
+
+/* Initial default iw_mode */
+#define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA
+
+/* Bus type PCI. */
+#define BCM43xx_BUSTYPE_PCI 0
+/* Bus type Silicone Backplane Bus. */
+#define BCM43xx_BUSTYPE_SB 1
+/* Bus type PCMCIA. */
+#define BCM43xx_BUSTYPE_PCMCIA 2
+
+/* Threshold values. */
+#define BCM43xx_MIN_RTS_THRESHOLD 1U
+#define BCM43xx_MAX_RTS_THRESHOLD 2304U
+#define BCM43xx_DEFAULT_RTS_THRESHOLD BCM43xx_MAX_RTS_THRESHOLD
+
+#define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT 7
+#define BCM43xx_DEFAULT_LONG_RETRY_LIMIT 4
+
+/* Max size of a security key */
+#define BCM43xx_SEC_KEYSIZE 16
+/* Security algorithms. */
+enum {
+ BCM43xx_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */
+ BCM43xx_SEC_ALGO_WEP,
+ BCM43xx_SEC_ALGO_UNKNOWN,
+ BCM43xx_SEC_ALGO_AES,
+ BCM43xx_SEC_ALGO_WEP104,
+ BCM43xx_SEC_ALGO_TKIP,
+};
+
+#ifdef assert
+# undef assert
+#endif
+#ifdef CONFIG_BCM43XX_DEBUG
+#define assert(expr) \
+ do { \
+ if (unlikely(!(expr))) { \
+ printk(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", \
+ #expr, __FILE__, __LINE__, __FUNCTION__); \
+ } \
+ } while (0)
+#else
+#define assert(expr) do { /* nothing */ } while (0)
+#endif
+
+/* rate limited printk(). */
+#ifdef printkl
+# undef printkl
+#endif
+#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0)
+/* rate limited printk() for debugging */
+#ifdef dprintkl
+# undef dprintkl
+#endif
+#ifdef CONFIG_BCM43XX_DEBUG
+# define dprintkl printkl
+#else
+# define dprintkl(f, x...) do { /* nothing */ } while (0)
+#endif
+
+/* Helper macro for if branches.
+ * An if branch marked with this macro is only taken in DEBUG mode.
+ * Example:
+ * if (DEBUG_ONLY(foo == bar)) {
+ * do something
+ * }
+ * In DEBUG mode, the branch will be taken if (foo == bar).
+ * In non-DEBUG mode, the branch will never be taken.
+ */
+#ifdef DEBUG_ONLY
+# undef DEBUG_ONLY
+#endif
+#ifdef CONFIG_BCM43XX_DEBUG
+# define DEBUG_ONLY(x) (x)
+#else
+# define DEBUG_ONLY(x) 0
+#endif
+
+/* debugging printk() */
+#ifdef dprintk
+# undef dprintk
+#endif
+#ifdef CONFIG_BCM43XX_DEBUG
+# define dprintk(f, x...) do { printk(f ,##x); } while (0)
+#else
+# define dprintk(f, x...) do { /* nothing */ } while (0)
+#endif
+
+
+struct net_device;
+struct pci_dev;
+struct bcm43xx_dmaring;
+struct bcm43xx_pioqueue;
+
+struct bcm43xx_initval {
+ u16 offset;
+ u16 size;
+ u32 value;
+} __attribute__((__packed__));
+
+/* Values for bcm430x_sprominfo.locale */
+enum {
+ BCM43xx_LOCALE_WORLD = 0,
+ BCM43xx_LOCALE_THAILAND,
+ BCM43xx_LOCALE_ISRAEL,
+ BCM43xx_LOCALE_JORDAN,
+ BCM43xx_LOCALE_CHINA,
+ BCM43xx_LOCALE_JAPAN,
+ BCM43xx_LOCALE_USA_CANADA_ANZ,
+ BCM43xx_LOCALE_EUROPE,
+ BCM43xx_LOCALE_USA_LOW,
+ BCM43xx_LOCALE_JAPAN_HIGH,
+ BCM43xx_LOCALE_ALL,
+ BCM43xx_LOCALE_NONE,
+};
+
+#define BCM43xx_SPROM_SIZE 64 /* in 16-bit words. */
+struct bcm43xx_sprominfo {
+ u16 boardflags2;
+ u8 il0macaddr[6];
+ u8 et0macaddr[6];
+ u8 et1macaddr[6];
+ u8 et0phyaddr:5;
+ u8 et1phyaddr:5;
+ u8 et0mdcport:1;
+ u8 et1mdcport:1;
+ u8 boardrev;
+ u8 locale:4;
+ u8 antennas_aphy:2;
+ u8 antennas_bgphy:2;
+ u16 pa0b0;
+ u16 pa0b1;
+ u16 pa0b2;
+ u8 wl0gpio0;
+ u8 wl0gpio1;
+ u8 wl0gpio2;
+ u8 wl0gpio3;
+ u8 maxpower_aphy;
+ u8 maxpower_bgphy;
+ u16 pa1b0;
+ u16 pa1b1;
+ u16 pa1b2;
+ u8 idle_tssi_tgt_aphy;
+ u8 idle_tssi_tgt_bgphy;
+ u16 boardflags;
+ u16 antennagain_aphy;
+ u16 antennagain_bgphy;
+};
+
+/* Value pair to measure the LocalOscillator. */
+struct bcm43xx_lopair {
+ s8 low;
+ s8 high;
+ u8 used:1;
+};
+#define BCM43xx_LO_COUNT (14*4)
+
+struct bcm43xx_phyinfo {
+ /* Hardware Data */
+ u8 version;
+ u8 type;
+ u8 rev;
+ u16 antenna_diversity;
+ u16 savedpctlreg;
+ u16 minlowsig[2];
+ u16 minlowsigpos[2];
+ u8 connected:1,
+ calibrated:1,
+ is_locked:1, /* used in bcm43xx_phy_{un}lock() */
+ dyn_tssi_tbl:1; /* used in bcm43xx_phy_init_tssi2dbm_table() */
+ /* LO Measurement Data.
+ * Use bcm43xx_get_lopair() to get a value.
+ */
+ struct bcm43xx_lopair *_lo_pairs;
+
+ /* TSSI to dBm table in use */
+ const s8 *tssi2dbm;
+ /* idle TSSI value */
+ s8 idle_tssi;
+
+ /* Values from bcm43xx_calc_loopback_gain() */
+ u16 loopback_gain[2];
+
+ /* PHY lock for core.rev < 3
+ * This lock is only used by bcm43xx_phy_{un}lock()
+ */
+ spinlock_t lock;
+};
+
+
+struct bcm43xx_radioinfo {
+ u16 manufact;
+ u16 version;
+ u8 revision;
+
+ /* Desired TX power in dBm Q5.2 */
+ u16 txpower_desired;
+ /* TX Power control values. */
+ union {
+ /* B/G PHY */
+ struct {
+ u16 baseband_atten;
+ u16 radio_atten;
+ u16 txctl1;
+ u16 txctl2;
+ };
+ /* A PHY */
+ struct {
+ u16 txpwr_offset;
+ };
+ };
+
+ /* Current Interference Mitigation mode */
+ int interfmode;
+ /* Stack of saved values from the Interference Mitigation code.
+ * Each value in the stack is layed out as follows:
+ * bit 0-11: offset
+ * bit 12-15: register ID
+ * bit 16-32: value
+ * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
+ */
+#define BCM43xx_INTERFSTACK_SIZE 26
+ u32 interfstack[BCM43xx_INTERFSTACK_SIZE];
+
+ /* Saved values from the NRSSI Slope calculation */
+ s16 nrssi[2];
+ s32 nrssislope;
+ /* In memory nrssi lookup table. */
+ s8 nrssi_lt[64];
+
+ /* current channel */
+ u8 channel;
+ u8 initial_channel;
+
+ u16 lofcal;
+
+ u16 initval;
+
+ u8 enabled:1;
+ /* ACI (adjacent channel interference) flags. */
+ u8 aci_enable:1,
+ aci_wlan_automatic:1,
+ aci_hw_rssi:1;
+};
+
+/* Data structures for DMA transmission, per 80211 core. */
+struct bcm43xx_dma {
+ struct bcm43xx_dmaring *tx_ring0;
+ struct bcm43xx_dmaring *tx_ring1;
+ struct bcm43xx_dmaring *tx_ring2;
+ struct bcm43xx_dmaring *tx_ring3;
+ struct bcm43xx_dmaring *rx_ring0;
+ struct bcm43xx_dmaring *rx_ring1; /* only available on core.rev < 5 */
+};
+
+/* Data structures for PIO transmission, per 80211 core. */
+struct bcm43xx_pio {
+ struct bcm43xx_pioqueue *queue0;
+ struct bcm43xx_pioqueue *queue1;
+ struct bcm43xx_pioqueue *queue2;
+ struct bcm43xx_pioqueue *queue3;
+};
+
+#define BCM43xx_MAX_80211_CORES 2
+
+#ifdef CONFIG_BCM947XX
+#define core_offset(bcm) (bcm)->current_core_offset
+#else
+#define core_offset(bcm) 0
+#endif
+
+/* Generic information about a core. */
+struct bcm43xx_coreinfo {
+ u8 available:1,
+ enabled:1,
+ initialized:1;
+ /** core_id ID number */
+ u16 id;
+ /** core_rev revision number */
+ u8 rev;
+ /** Index number for _switch_core() */
+ u8 index;
+};
+
+/* Additional information for each 80211 core. */
+struct bcm43xx_coreinfo_80211 {
+ /* PHY device. */
+ struct bcm43xx_phyinfo phy;
+ /* Radio device. */
+ struct bcm43xx_radioinfo radio;
+ union {
+ /* DMA context. */
+ struct bcm43xx_dma dma;
+ /* PIO context. */
+ struct bcm43xx_pio pio;
+ };
+};
+
+/* Context information for a noise calculation (Link Quality). */
+struct bcm43xx_noise_calculation {
+ struct bcm43xx_coreinfo *core_at_start;
+ u8 channel_at_start;
+ u8 calculation_running:1;
+ u8 nr_samples;
+ s8 samples[8][4];
+};
+
+struct bcm43xx_stats {
+ u8 link_quality;
+ u8 noise;
+ struct iw_statistics wstats;
+ /* Store the last TX/RX times here for updating the leds. */
+ unsigned long last_tx;
+ unsigned long last_rx;
+};
+
+struct bcm43xx_key {
+ u8 enabled:1;
+ u8 algorithm;
+};
+
+struct bcm43xx_private {
+ struct ieee80211_device *ieee;
+ struct ieee80211softmac_device *softmac;
+
+ struct net_device *net_dev;
+ struct pci_dev *pci_dev;
+ unsigned int irq;
+
+ void __iomem *mmio_addr;
+ unsigned int mmio_len;
+
+ /* Do not use the lock directly. Use the bcm43xx_lock* helper
+ * functions, to be MMIO-safe. */
+ spinlock_t _lock;
+
+ /* Driver status flags. */
+ u32 initialized:1, /* init_board() succeed */
+ was_initialized:1, /* for PCI suspend/resume. */
+ shutting_down:1, /* free_board() in progress */
+ __using_pio:1, /* Internal, use bcm43xx_using_pio(). */
+ bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */
+ reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */
+ powersaving:1, /* TRUE if we are in PowerSaving mode. FALSE otherwise. */
+ short_preamble:1, /* TRUE, if short preamble is enabled. */
+ firmware_norelease:1; /* Do not release the firmware. Used on suspend. */
+
+ struct bcm43xx_stats stats;
+
+ /* Bus type we are connected to.
+ * This is currently always BCM43xx_BUSTYPE_PCI
+ */
+ u8 bustype;
+
+ u16 board_vendor;
+ u16 board_type;
+ u16 board_revision;
+
+ u16 chip_id;
+ u8 chip_rev;
+ u8 chip_package;
+
+ struct bcm43xx_sprominfo sprom;
+#define BCM43xx_NR_LEDS 4
+ struct bcm43xx_led leds[BCM43xx_NR_LEDS];
+
+ /* The currently active core. */
+ struct bcm43xx_coreinfo *current_core;
+#ifdef CONFIG_BCM947XX
+ /** current core memory offset */
+ u32 current_core_offset;
+#endif
+ struct bcm43xx_coreinfo *active_80211_core;
+ /* coreinfo structs for all possible cores follow.
+ * Note that a core might not exist.
+ * So check the coreinfo flags before using it.
+ */
+ struct bcm43xx_coreinfo core_chipcommon;
+ struct bcm43xx_coreinfo core_pci;
+ struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
+ /* Additional information, specific to the 80211 cores. */
+ struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
+ /* Index of the current 80211 core. If current_core is not
+ * an 80211 core, this is -1.
+ */
+ int current_80211_core_idx;
+ /* Number of available 80211 cores. */
+ int nr_80211_available;
+
+ u32 chipcommon_capabilities;
+
+ /* Reason code of the last interrupt. */
+ u32 irq_reason;
+ u32 dma_reason[4];
+ /* saved irq enable/disable state bitfield. */
+ u32 irq_savedstate;
+ /* Link Quality calculation context. */
+ struct bcm43xx_noise_calculation noisecalc;
+
+ /* Threshold values. */
+ //TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
+ u32 rts_threshold;
+
+ /* Interrupt Service Routine tasklet (bottom-half) */
+ struct tasklet_struct isr_tasklet;
+
+ /* Periodic tasks */
+ struct timer_list periodic_tasks;
+ unsigned int periodic_state;
+
+ struct work_struct restart_work;
+
+ /* Informational stuff. */
+ char nick[IW_ESSID_MAX_SIZE + 1];
+
+ /* encryption/decryption */
+ u16 security_offset;
+ struct bcm43xx_key key[54];
+ u8 default_key_idx;
+
+ /* Firmware. */
+ const struct firmware *ucode;
+ const struct firmware *pcm;
+ const struct firmware *initvals0;
+ const struct firmware *initvals1;
+
+ /* Debugging stuff follows. */
+#ifdef CONFIG_BCM43XX_DEBUG
+ struct bcm43xx_dfsentry *dfsentry;
+#endif
+};
+
+/* bcm43xx_(un)lock() protect struct bcm43xx_private.
+ * Note that _NO_ MMIO writes are allowed. If you want to
+ * write to the device through MMIO in the critical section, use
+ * the *_mmio lock functions.
+ * MMIO read-access is allowed, though.
+ */
+#define bcm43xx_lock(bcm, flags) spin_lock_irqsave(&(bcm)->_lock, flags)
+#define bcm43xx_unlock(bcm, flags) spin_unlock_irqrestore(&(bcm)->_lock, flags)
+/* bcm43xx_(un)lock_mmio() protect struct bcm43xx_private and MMIO.
+ * MMIO write-access to the device is allowed.
+ * All MMIO writes are flushed on unlock, so it is guaranteed to not
+ * interfere with other threads writing MMIO registers.
+ */
+#define bcm43xx_lock_mmio(bcm, flags) bcm43xx_lock(bcm, flags)
+#define bcm43xx_unlock_mmio(bcm, flags) do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0)
+
+static inline
+struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
+{
+ return ieee80211softmac_priv(dev);
+}
+
+struct device;
+
+static inline
+struct bcm43xx_private * dev_to_bcm(struct device *dev)
+{
+ struct net_device *net_dev;
+ struct bcm43xx_private *bcm;
+
+ net_dev = dev_get_drvdata(dev);
+ bcm = bcm43xx_priv(net_dev);
+
+ return bcm;
+}
+
+
+/* Helper function, which returns a boolean.
+ * TRUE, if PIO is used; FALSE, if DMA is used.
+ */
+#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
+static inline
+int bcm43xx_using_pio(struct bcm43xx_private *bcm)
+{
+ return bcm->__using_pio;
+}
+#elif defined(CONFIG_BCM43XX_DMA)
+static inline
+int bcm43xx_using_pio(struct bcm43xx_private *bcm)
+{
+ return 0;
+}
+#elif defined(CONFIG_BCM43XX_PIO)
+static inline
+int bcm43xx_using_pio(struct bcm43xx_private *bcm)
+{
+ return 1;
+}
+#else
+# error "Using neither DMA nor PIO? Confused..."
+#endif
+
+/* Helper functions to access data structures private to the 80211 cores.
+ * Note that we _must_ have an 80211 core mapped when calling
+ * any of these functions.
+ */
+static inline
+struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
+{
+ assert(bcm43xx_using_pio(bcm));
+ assert(bcm->current_80211_core_idx >= 0);
+ assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
+ return &(bcm->core_80211_ext[bcm->current_80211_core_idx].pio);
+}
+static inline
+struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm)
+{
+ assert(!bcm43xx_using_pio(bcm));
+ assert(bcm->current_80211_core_idx >= 0);
+ assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
+ return &(bcm->core_80211_ext[bcm->current_80211_core_idx].dma);
+}
+static inline
+struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm)
+{
+ assert(bcm->current_80211_core_idx >= 0);
+ assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
+ return &(bcm->core_80211_ext[bcm->current_80211_core_idx].phy);
+}
+static inline
+struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
+{
+ assert(bcm->current_80211_core_idx >= 0);
+ assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
+ return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio);
+}
+
+/* Are we running in init_board() context? */
+static inline
+int bcm43xx_is_initializing(struct bcm43xx_private *bcm)
+{
+ if (bcm->initialized)
+ return 0;
+ if (bcm->shutting_down)
+ return 0;
+ return 1;
+}
+
+static inline
+struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
+ u16 radio_attenuation,
+ u16 baseband_attenuation)
+{
+ return phy->_lo_pairs + (radio_attenuation + 14 * (baseband_attenuation / 2));
+}
+
+
+static inline
+u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset)
+{
+ return ioread16(bcm->mmio_addr + core_offset(bcm) + offset);
+}
+
+static inline
+void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value)
+{
+ iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset);
+}
+
+static inline
+u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset)
+{
+ return ioread32(bcm->mmio_addr + core_offset(bcm) + offset);
+}
+
+static inline
+void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value)
+{
+ iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset);
+}
+
+static inline
+int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value)
+{
+ return pci_read_config_word(bcm->pci_dev, offset, value);
+}
+
+static inline
+int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value)
+{
+ return pci_read_config_dword(bcm->pci_dev, offset, value);
+}
+
+static inline
+int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value)
+{
+ return pci_write_config_word(bcm->pci_dev, offset, value);
+}
+
+static inline
+int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value)
+{
+ return pci_write_config_dword(bcm->pci_dev, offset, value);
+}
+
+/** Limit a value between two limits */
+#ifdef limit_value
+# undef limit_value
+#endif
+#define limit_value(value, min, max) \
+ ({ \
+ typeof(value) __value = (value); \
+ typeof(value) __min = (min); \
+ typeof(value) __max = (max); \
+ if (__value < __min) \
+ __value = __min; \
+ else if (__value > __max) \
+ __value = __max; \
+ __value; \
+ })
+
+/** Helpers to print MAC addresses. */
+#define BCM43xx_MACFMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define BCM43xx_MACARG(x) ((u8*)(x))[0], ((u8*)(x))[1], \
+ ((u8*)(x))[2], ((u8*)(x))[3], \
+ ((u8*)(x))[4], ((u8*)(x))[5]
+
+#endif /* BCM43xx_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
new file mode 100644
index 00000000000..35a4fcb6d92
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -0,0 +1,499 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ debugfs driver debugging code
+
+ Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+
+
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include "bcm43xx.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_debugfs.h"
+#include "bcm43xx_dma.h"
+#include "bcm43xx_pio.h"
+#include "bcm43xx_xmit.h"
+
+#define REALLY_BIG_BUFFER_SIZE (1024*256)
+
+static struct bcm43xx_debugfs fs;
+static char really_big_buffer[REALLY_BIG_BUFFER_SIZE];
+static DECLARE_MUTEX(big_buffer_sem);
+
+
+static ssize_t write_file_dummy(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return count;
+}
+
+static int open_file_generic(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->u.generic_ip;
+ return 0;
+}
+
+#define fappend(fmt, x...) pos += snprintf(buf + pos, len - pos, fmt , ##x)
+
+static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ const size_t len = REALLY_BIG_BUFFER_SIZE;
+
+ struct bcm43xx_private *bcm = file->private_data;
+ char *buf = really_big_buffer;
+ size_t pos = 0;
+ ssize_t res;
+ struct net_device *net_dev;
+ struct pci_dev *pci_dev;
+ unsigned long flags;
+ u16 tmp16;
+ int i;
+
+ down(&big_buffer_sem);
+
+ bcm43xx_lock_mmio(bcm, flags);
+ if (!bcm->initialized) {
+ fappend("Board not initialized.\n");
+ goto out;
+ }
+ net_dev = bcm->net_dev;
+ pci_dev = bcm->pci_dev;
+
+ /* This is where the information is written to the "devinfo" file */
+ fappend("*** %s devinfo ***\n", net_dev->name);
+ fappend("vendor: 0x%04x device: 0x%04x\n",
+ pci_dev->vendor, pci_dev->device);
+ fappend("subsystem_vendor: 0x%04x subsystem_device: 0x%04x\n",
+ pci_dev->subsystem_vendor, pci_dev->subsystem_device);
+ fappend("IRQ: %d\n", bcm->irq);
+ fappend("mmio_addr: 0x%p mmio_len: %u\n", bcm->mmio_addr, bcm->mmio_len);
+ fappend("chip_id: 0x%04x chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev);
+ if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16)))
+ fappend("Radio disabled by hardware!\n");
+ if ((bcm->core_80211[0].rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4)))
+ fappend("Radio disabled by hardware!\n");
+ fappend("board_vendor: 0x%04x board_type: 0x%04x\n", bcm->board_vendor,
+ bcm->board_type);
+
+ fappend("\nCores:\n");
+#define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, " \
+ "rev: 0x%02x, index: 0x%02x\n", \
+ (info).available \
+ ? "available" : "nonavailable", \
+ (info).enabled \
+ ? "enabled" : "disabled", \
+ (info).id, (info).rev, (info).index)
+ fappend_core("CHIPCOMMON", bcm->core_chipcommon);
+ fappend_core("PCI", bcm->core_pci);
+ fappend_core("first 80211", bcm->core_80211[0]);
+ fappend_core("second 80211", bcm->core_80211[1]);
+#undef fappend_core
+ tmp16 = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+ fappend("LEDs: ");
+ for (i = 0; i < BCM43xx_NR_LEDS; i++)
+ fappend("%d ", !!(tmp16 & (1 << i)));
+ fappend("\n");
+
+out:
+ bcm43xx_unlock_mmio(bcm, flags);
+ res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+ up(&big_buffer_sem);
+ return res;
+}
+
+static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ const size_t len = REALLY_BIG_BUFFER_SIZE;
+
+ char *buf = really_big_buffer;
+ size_t pos = 0;
+ ssize_t res;
+
+ down(&big_buffer_sem);
+
+ /* This is where the information is written to the "driver" file */
+ fappend(KBUILD_MODNAME " driver\n");
+ fappend("Compiled at: %s %s\n", __DATE__, __TIME__);
+
+ res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+ up(&big_buffer_sem);
+ return res;
+}
+
+static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ const size_t len = REALLY_BIG_BUFFER_SIZE;
+
+ struct bcm43xx_private *bcm = file->private_data;
+ char *buf = really_big_buffer;
+ size_t pos = 0;
+ ssize_t res;
+ unsigned long flags;
+
+ down(&big_buffer_sem);
+ bcm43xx_lock_mmio(bcm, flags);
+ if (!bcm->initialized) {
+ fappend("Board not initialized.\n");
+ goto out;
+ }
+
+ /* This is where the information is written to the "sprom_dump" file */
+ fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
+
+out:
+ bcm43xx_unlock_mmio(bcm, flags);
+ res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+ up(&big_buffer_sem);
+ return res;
+}
+
+static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ const size_t len = REALLY_BIG_BUFFER_SIZE;
+
+ struct bcm43xx_private *bcm = file->private_data;
+ char *buf = really_big_buffer;
+ size_t pos = 0;
+ ssize_t res;
+ unsigned long flags;
+ u64 tsf;
+
+ down(&big_buffer_sem);
+ bcm43xx_lock_mmio(bcm, flags);
+ if (!bcm->initialized) {
+ fappend("Board not initialized.\n");
+ goto out;
+ }
+ bcm43xx_tsf_read(bcm, &tsf);
+ fappend("0x%08x%08x\n",
+ (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32),
+ (unsigned int)(tsf & 0xFFFFFFFFULL));
+
+out:
+ bcm43xx_unlock_mmio(bcm, flags);
+ res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+ up(&big_buffer_sem);
+ return res;
+}
+
+static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct bcm43xx_private *bcm = file->private_data;
+ char *buf = really_big_buffer;
+ ssize_t buf_size;
+ ssize_t res;
+ unsigned long flags;
+ u64 tsf;
+
+ buf_size = min(count, sizeof (really_big_buffer) - 1);
+ down(&big_buffer_sem);
+ if (copy_from_user(buf, user_buf, buf_size)) {
+ res = -EFAULT;
+ goto out_up;
+ }
+ bcm43xx_lock_mmio(bcm, flags);
+ if (!bcm->initialized) {
+ printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
+ res = -EFAULT;
+ goto out_unlock;
+ }
+ if (sscanf(buf, "%lli", &tsf) != 1) {
+ printk(KERN_INFO PFX "debugfs: invalid values for \"tsf\"\n");
+ res = -EINVAL;
+ goto out_unlock;
+ }
+ bcm43xx_tsf_write(bcm, tsf);
+ res = buf_size;
+
+out_unlock:
+ bcm43xx_unlock_mmio(bcm, flags);
+out_up:
+ up(&big_buffer_sem);
+ return res;
+}
+
+static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ const size_t len = REALLY_BIG_BUFFER_SIZE;
+
+ struct bcm43xx_private *bcm = file->private_data;
+ char *buf = really_big_buffer;
+ size_t pos = 0;
+ ssize_t res;
+ unsigned long flags;
+ struct bcm43xx_dfsentry *e;
+ struct bcm43xx_xmitstatus *status;
+ int i, cnt, j = 0;
+
+ down(&big_buffer_sem);
+ bcm43xx_lock(bcm, flags);
+
+ fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
+ BCM43xx_NR_LOGGED_XMITSTATUS);
+ e = bcm->dfsentry;
+ if (e->xmitstatus_printing == 0) {
+ /* At the beginning, make a copy of all data to avoid
+ * concurrency, as this function is called multiple
+ * times for big logs. Without copying, the data might
+ * change between reads. This would result in total trash.
+ */
+ e->xmitstatus_printing = 1;
+ e->saved_xmitstatus_ptr = e->xmitstatus_ptr;
+ e->saved_xmitstatus_cnt = e->xmitstatus_cnt;
+ memcpy(e->xmitstatus_print_buffer, e->xmitstatus_buffer,
+ BCM43xx_NR_LOGGED_XMITSTATUS * sizeof(*(e->xmitstatus_buffer)));
+ }
+ i = e->saved_xmitstatus_ptr - 1;
+ if (i < 0)
+ i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
+ cnt = e->saved_xmitstatus_cnt;
+ while (cnt) {
+ status = e->xmitstatus_print_buffer + i;
+ fappend("0x%02x: cookie: 0x%04x, flags: 0x%02x, "
+ "cnt1: 0x%02x, cnt2: 0x%02x, seq: 0x%04x, "
+ "unk: 0x%04x\n", j,
+ status->cookie, status->flags,
+ status->cnt1, status->cnt2, status->seq,
+ status->unknown);
+ j++;
+ cnt--;
+ i--;
+ if (i < 0)
+ i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
+ }
+
+ bcm43xx_unlock(bcm, flags);
+ res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+ bcm43xx_lock(bcm, flags);
+ if (*ppos == pos) {
+ /* Done. Drop the copied data. */
+ e->xmitstatus_printing = 0;
+ }
+ bcm43xx_unlock(bcm, flags);
+ up(&big_buffer_sem);
+ return res;
+}
+
+#undef fappend
+
+
+static struct file_operations devinfo_fops = {
+ .read = devinfo_read_file,
+ .write = write_file_dummy,
+ .open = open_file_generic,
+};
+
+static struct file_operations spromdump_fops = {
+ .read = spromdump_read_file,
+ .write = write_file_dummy,
+ .open = open_file_generic,
+};
+
+static struct file_operations drvinfo_fops = {
+ .read = drvinfo_read_file,
+ .write = write_file_dummy,
+ .open = open_file_generic,
+};
+
+static struct file_operations tsf_fops = {
+ .read = tsf_read_file,
+ .write = tsf_write_file,
+ .open = open_file_generic,
+};
+
+static struct file_operations txstat_fops = {
+ .read = txstat_read_file,
+ .write = write_file_dummy,
+ .open = open_file_generic,
+};
+
+
+void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_dfsentry *e;
+ char devdir[IFNAMSIZ];
+
+ assert(bcm);
+ e = kzalloc(sizeof(*e), GFP_KERNEL);
+ if (!e) {
+ printk(KERN_ERR PFX "out of memory\n");
+ return;
+ }
+ e->bcm = bcm;
+ e->xmitstatus_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
+ * sizeof(*(e->xmitstatus_buffer)),
+ GFP_KERNEL);
+ if (!e->xmitstatus_buffer) {
+ printk(KERN_ERR PFX "out of memory\n");
+ kfree(e);
+ return;
+ }
+ e->xmitstatus_print_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
+ * sizeof(*(e->xmitstatus_buffer)),
+ GFP_KERNEL);
+ if (!e->xmitstatus_print_buffer) {
+ printk(KERN_ERR PFX "out of memory\n");
+ kfree(e);
+ return;
+ }
+
+
+ bcm->dfsentry = e;
+
+ strncpy(devdir, bcm->net_dev->name, ARRAY_SIZE(devdir));
+ e->subdir = debugfs_create_dir(devdir, fs.root);
+ e->dentry_devinfo = debugfs_create_file("devinfo", 0444, e->subdir,
+ bcm, &devinfo_fops);
+ if (!e->dentry_devinfo)
+ printk(KERN_ERR PFX "debugfs: creating \"devinfo\" for \"%s\" failed!\n", devdir);
+ e->dentry_spromdump = debugfs_create_file("sprom_dump", 0444, e->subdir,
+ bcm, &spromdump_fops);
+ if (!e->dentry_spromdump)
+ printk(KERN_ERR PFX "debugfs: creating \"sprom_dump\" for \"%s\" failed!\n", devdir);
+ e->dentry_tsf = debugfs_create_file("tsf", 0666, e->subdir,
+ bcm, &tsf_fops);
+ if (!e->dentry_tsf)
+ printk(KERN_ERR PFX "debugfs: creating \"tsf\" for \"%s\" failed!\n", devdir);
+ e->dentry_txstat = debugfs_create_file("tx_status", 0444, e->subdir,
+ bcm, &txstat_fops);
+ if (!e->dentry_txstat)
+ printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir);
+}
+
+void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_dfsentry *e;
+
+ if (!bcm)
+ return;
+
+ e = bcm->dfsentry;
+ assert(e);
+ debugfs_remove(e->dentry_spromdump);
+ debugfs_remove(e->dentry_devinfo);
+ debugfs_remove(e->dentry_tsf);
+ debugfs_remove(e->dentry_txstat);
+ debugfs_remove(e->subdir);
+ kfree(e->xmitstatus_buffer);
+ kfree(e->xmitstatus_print_buffer);
+ kfree(e);
+}
+
+void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
+ struct bcm43xx_xmitstatus *status)
+{
+ struct bcm43xx_dfsentry *e;
+ struct bcm43xx_xmitstatus *savedstatus;
+
+ /* This is protected by bcm->_lock */
+ e = bcm->dfsentry;
+ assert(e);
+ savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr;
+ memcpy(savedstatus, status, sizeof(*status));
+ e->xmitstatus_ptr++;
+ if (e->xmitstatus_ptr >= BCM43xx_NR_LOGGED_XMITSTATUS)
+ e->xmitstatus_ptr = 0;
+ if (e->xmitstatus_cnt < BCM43xx_NR_LOGGED_XMITSTATUS)
+ e->xmitstatus_cnt++;
+}
+
+void bcm43xx_debugfs_init(void)
+{
+ memset(&fs, 0, sizeof(fs));
+ fs.root = debugfs_create_dir(KBUILD_MODNAME, NULL);
+ if (!fs.root)
+ printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "\" subdir failed!\n");
+ fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops);
+ if (!fs.dentry_driverinfo)
+ printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "/driver\" failed!\n");
+}
+
+void bcm43xx_debugfs_exit(void)
+{
+ debugfs_remove(fs.dentry_driverinfo);
+ debugfs_remove(fs.root);
+}
+
+void bcm43xx_printk_dump(const char *data,
+ size_t size,
+ const char *description)
+{
+ size_t i;
+ char c;
+
+ printk(KERN_INFO PFX "Data dump (%s, %zd bytes):",
+ description, size);
+ for (i = 0; i < size; i++) {
+ c = data[i];
+ if (i % 8 == 0)
+ printk("\n" KERN_INFO PFX "0x%08zx: 0x%02x, ", i, c & 0xff);
+ else
+ printk("0x%02x, ", c & 0xff);
+ }
+ printk("\n");
+}
+
+void bcm43xx_printk_bitdump(const unsigned char *data,
+ size_t bytes, int msb_to_lsb,
+ const char *description)
+{
+ size_t i;
+ int j;
+ const unsigned char *d;
+
+ printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***",
+ description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB");
+ for (i = 0; i < bytes; i++) {
+ d = data + i;
+ if (i % 8 == 0)
+ printk("\n" KERN_INFO PFX "0x%08zx: ", i);
+ if (msb_to_lsb) {
+ for (j = 7; j >= 0; j--) {
+ if (*d & (1 << j))
+ printk("1");
+ else
+ printk("0");
+ }
+ } else {
+ for (j = 0; j < 8; j++) {
+ if (*d & (1 << j))
+ printk("1");
+ else
+ printk("0");
+ }
+ }
+ printk(" ");
+ }
+ printk("\n");
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
new file mode 100644
index 00000000000..50ce267f794
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
@@ -0,0 +1,117 @@
+#ifndef BCM43xx_DEBUGFS_H_
+#define BCM43xx_DEBUGFS_H_
+
+struct bcm43xx_private;
+struct bcm43xx_xmitstatus;
+
+#ifdef CONFIG_BCM43XX_DEBUG
+
+#include <linux/list.h>
+#include <asm/semaphore.h>
+
+struct dentry;
+
+/* limited by the size of the "really_big_buffer" */
+#define BCM43xx_NR_LOGGED_XMITSTATUS 100
+
+struct bcm43xx_dfsentry {
+ struct dentry *subdir;
+ struct dentry *dentry_devinfo;
+ struct dentry *dentry_spromdump;
+ struct dentry *dentry_tsf;
+ struct dentry *dentry_txstat;
+
+ struct bcm43xx_private *bcm;
+
+ /* saved xmitstatus. */
+ struct bcm43xx_xmitstatus *xmitstatus_buffer;
+ int xmitstatus_ptr;
+ int xmitstatus_cnt;
+ /* We need a seperate buffer while printing to avoid
+ * concurrency issues. (New xmitstatus can arrive
+ * while we are printing).
+ */
+ struct bcm43xx_xmitstatus *xmitstatus_print_buffer;
+ int saved_xmitstatus_ptr;
+ int saved_xmitstatus_cnt;
+ int xmitstatus_printing;
+};
+
+struct bcm43xx_debugfs {
+ struct dentry *root;
+ struct dentry *dentry_driverinfo;
+};
+
+void bcm43xx_debugfs_init(void);
+void bcm43xx_debugfs_exit(void);
+void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm);
+void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm);
+void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
+ struct bcm43xx_xmitstatus *status);
+
+/* Debug helper: Dump binary data through printk. */
+void bcm43xx_printk_dump(const char *data,
+ size_t size,
+ const char *description);
+/* Debug helper: Dump bitwise binary data through printk. */
+void bcm43xx_printk_bitdump(const unsigned char *data,
+ size_t bytes, int msb_to_lsb,
+ const char *description);
+#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) \
+ do { \
+ bcm43xx_printk_bitdump((const unsigned char *)(pointer), \
+ sizeof(*(pointer)), \
+ (msb_to_lsb), \
+ (description)); \
+ } while (0)
+
+#else /* CONFIG_BCM43XX_DEBUG*/
+
+static inline
+void bcm43xx_debugfs_init(void) { }
+static inline
+void bcm43xx_debugfs_exit(void) { }
+static inline
+void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) { }
+static inline
+void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) { }
+static inline
+void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
+ struct bcm43xx_xmitstatus *status) { }
+
+static inline
+void bcm43xx_printk_dump(const char *data,
+ size_t size,
+ const char *description)
+{
+}
+static inline
+void bcm43xx_printk_bitdump(const unsigned char *data,
+ size_t bytes, int msb_to_lsb,
+ const char *description)
+{
+}
+#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) do { /* nothing */ } while (0)
+
+#endif /* CONFIG_BCM43XX_DEBUG*/
+
+/* Ugly helper macros to make incomplete code more verbose on runtime */
+#ifdef TODO
+# undef TODO
+#endif
+#define TODO() \
+ do { \
+ printk(KERN_INFO PFX "TODO: Incomplete code in %s() at %s:%d\n", \
+ __FUNCTION__, __FILE__, __LINE__); \
+ } while (0)
+
+#ifdef FIXME
+# undef FIXME
+#endif
+#define FIXME() \
+ do { \
+ printk(KERN_INFO PFX "FIXME: Possibly broken code in %s() at %s:%d\n", \
+ __FUNCTION__, __FILE__, __LINE__); \
+ } while (0)
+
+#endif /* BCM43xx_DEBUGFS_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
new file mode 100644
index 00000000000..d0318e525ba
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -0,0 +1,982 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ DMA ringbuffer and descriptor allocation/management
+
+ Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
+
+ Some code in this file is derived from the b44.c driver
+ Copyright (C) 2002 David S. Miller
+ Copyright (C) Pekka Pietikainen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx.h"
+#include "bcm43xx_dma.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_debugfs.h"
+#include "bcm43xx_power.h"
+#include "bcm43xx_xmit.h"
+
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+
+
+static inline int free_slots(struct bcm43xx_dmaring *ring)
+{
+ return (ring->nr_slots - ring->used_slots);
+}
+
+static inline int next_slot(struct bcm43xx_dmaring *ring, int slot)
+{
+ assert(slot >= -1 && slot <= ring->nr_slots - 1);
+ if (slot == ring->nr_slots - 1)
+ return 0;
+ return slot + 1;
+}
+
+static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot)
+{
+ assert(slot >= 0 && slot <= ring->nr_slots - 1);
+ if (slot == 0)
+ return ring->nr_slots - 1;
+ return slot - 1;
+}
+
+/* Request a slot for usage. */
+static inline
+int request_slot(struct bcm43xx_dmaring *ring)
+{
+ int slot;
+
+ assert(ring->tx);
+ assert(!ring->suspended);
+ assert(free_slots(ring) != 0);
+
+ slot = next_slot(ring, ring->current_slot);
+ ring->current_slot = slot;
+ ring->used_slots++;
+
+ /* Check the number of available slots and suspend TX,
+ * if we are running low on free slots.
+ */
+ if (unlikely(free_slots(ring) < ring->suspend_mark)) {
+ netif_stop_queue(ring->bcm->net_dev);
+ ring->suspended = 1;
+ }
+#ifdef CONFIG_BCM43XX_DEBUG
+ if (ring->used_slots > ring->max_used_slots)
+ ring->max_used_slots = ring->used_slots;
+#endif /* CONFIG_BCM43XX_DEBUG*/
+
+ return slot;
+}
+
+/* Return a slot to the free slots. */
+static inline
+void return_slot(struct bcm43xx_dmaring *ring, int slot)
+{
+ assert(ring->tx);
+
+ ring->used_slots--;
+
+ /* Check if TX is suspended and check if we have
+ * enough free slots to resume it again.
+ */
+ if (unlikely(ring->suspended)) {
+ if (free_slots(ring) >= ring->resume_mark) {
+ ring->suspended = 0;
+ netif_wake_queue(ring->bcm->net_dev);
+ }
+ }
+}
+
+static inline
+dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
+ unsigned char *buf,
+ size_t len,
+ int tx)
+{
+ dma_addr_t dmaaddr;
+
+ if (tx) {
+ dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+ buf, len,
+ DMA_TO_DEVICE);
+ } else {
+ dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+ buf, len,
+ DMA_FROM_DEVICE);
+ }
+
+ return dmaaddr;
+}
+
+static inline
+void unmap_descbuffer(struct bcm43xx_dmaring *ring,
+ dma_addr_t addr,
+ size_t len,
+ int tx)
+{
+ if (tx) {
+ dma_unmap_single(&ring->bcm->pci_dev->dev,
+ addr, len,
+ DMA_TO_DEVICE);
+ } else {
+ dma_unmap_single(&ring->bcm->pci_dev->dev,
+ addr, len,
+ DMA_FROM_DEVICE);
+ }
+}
+
+static inline
+void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring,
+ dma_addr_t addr,
+ size_t len)
+{
+ assert(!ring->tx);
+
+ dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev,
+ addr, len, DMA_FROM_DEVICE);
+}
+
+static inline
+void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring,
+ dma_addr_t addr,
+ size_t len)
+{
+ assert(!ring->tx);
+
+ dma_sync_single_for_device(&ring->bcm->pci_dev->dev,
+ addr, len, DMA_FROM_DEVICE);
+}
+
+/* Unmap and free a descriptor buffer. */
+static inline
+void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
+ struct bcm43xx_dmadesc *desc,
+ struct bcm43xx_dmadesc_meta *meta,
+ int irq_context)
+{
+ assert(meta->skb);
+ if (irq_context)
+ dev_kfree_skb_irq(meta->skb);
+ else
+ dev_kfree_skb(meta->skb);
+ meta->skb = NULL;
+}
+
+static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
+{
+ struct device *dev = &(ring->bcm->pci_dev->dev);
+
+ ring->vbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
+ &(ring->dmabase), GFP_KERNEL);
+ if (!ring->vbase) {
+ printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
+ return -ENOMEM;
+ }
+ if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) {
+ printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G "
+ "(0x%llx, len: %lu)\n",
+ (unsigned long long)ring->dmabase,
+ BCM43xx_DMA_RINGMEMSIZE);
+ dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
+ ring->vbase, ring->dmabase);
+ return -ENOMEM;
+ }
+ assert(!(ring->dmabase & 0x000003FF));
+ memset(ring->vbase, 0, BCM43xx_DMA_RINGMEMSIZE);
+
+ return 0;
+}
+
+static void free_ringmemory(struct bcm43xx_dmaring *ring)
+{
+ struct device *dev = &(ring->bcm->pci_dev->dev);
+
+ dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
+ ring->vbase, ring->dmabase);
+}
+
+/* Reset the RX DMA channel */
+int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
+ u16 mmio_base)
+{
+ int i;
+ u32 value;
+
+ bcm43xx_write32(bcm,
+ mmio_base + BCM43xx_DMA_RX_CONTROL,
+ 0x00000000);
+ for (i = 0; i < 1000; i++) {
+ value = bcm43xx_read32(bcm,
+ mmio_base + BCM43xx_DMA_RX_STATUS);
+ value &= BCM43xx_DMA_RXSTAT_STAT_MASK;
+ if (value == BCM43xx_DMA_RXSTAT_STAT_DISABLED) {
+ i = -1;
+ break;
+ }
+ udelay(10);
+ }
+ if (i != -1) {
+ printk(KERN_ERR PFX "Error: Wait on DMA RX status timed out.\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/* Reset the RX DMA channel */
+int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
+ u16 mmio_base)
+{
+ int i;
+ u32 value;
+
+ for (i = 0; i < 1000; i++) {
+ value = bcm43xx_read32(bcm,
+ mmio_base + BCM43xx_DMA_TX_STATUS);
+ value &= BCM43xx_DMA_TXSTAT_STAT_MASK;
+ if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED ||
+ value == BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT ||
+ value == BCM43xx_DMA_TXSTAT_STAT_STOPPED)
+ break;
+ udelay(10);
+ }
+ bcm43xx_write32(bcm,
+ mmio_base + BCM43xx_DMA_TX_CONTROL,
+ 0x00000000);
+ for (i = 0; i < 1000; i++) {
+ value = bcm43xx_read32(bcm,
+ mmio_base + BCM43xx_DMA_TX_STATUS);
+ value &= BCM43xx_DMA_TXSTAT_STAT_MASK;
+ if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED) {
+ i = -1;
+ break;
+ }
+ udelay(10);
+ }
+ if (i != -1) {
+ printk(KERN_ERR PFX "Error: Wait on DMA TX status timed out.\n");
+ return -ENODEV;
+ }
+ /* ensure the reset is completed. */
+ udelay(300);
+
+ return 0;
+}
+
+static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
+ struct bcm43xx_dmadesc *desc,
+ struct bcm43xx_dmadesc_meta *meta,
+ gfp_t gfp_flags)
+{
+ struct bcm43xx_rxhdr *rxhdr;
+ dma_addr_t dmaaddr;
+ u32 desc_addr;
+ u32 desc_ctl;
+ const int slot = (int)(desc - ring->vbase);
+ struct sk_buff *skb;
+
+ assert(slot >= 0 && slot < ring->nr_slots);
+ assert(!ring->tx);
+
+ skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
+ if (unlikely(!skb))
+ return -ENOMEM;
+ dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+ if (unlikely(dmaaddr + ring->rx_buffersize > BCM43xx_DMA_BUSADDRMAX)) {
+ unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
+ dev_kfree_skb_any(skb);
+ printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G "
+ "(0x%llx, len: %u)\n",
+ (unsigned long long)dmaaddr, ring->rx_buffersize);
+ return -ENOMEM;
+ }
+ meta->skb = skb;
+ meta->dmaaddr = dmaaddr;
+ skb->dev = ring->bcm->net_dev;
+ desc_addr = (u32)(dmaaddr + ring->memoffset);
+ desc_ctl = (BCM43xx_DMADTOR_BYTECNT_MASK &
+ (u32)(ring->rx_buffersize - ring->frameoffset));
+ if (slot == ring->nr_slots - 1)
+ desc_ctl |= BCM43xx_DMADTOR_DTABLEEND;
+ set_desc_addr(desc, desc_addr);
+ set_desc_ctl(desc, desc_ctl);
+
+ rxhdr = (struct bcm43xx_rxhdr *)(skb->data);
+ rxhdr->frame_length = 0;
+ rxhdr->flags1 = 0;
+
+ return 0;
+}
+
+/* Allocate the initial descbuffers.
+ * This is used for an RX ring only.
+ */
+static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring)
+{
+ int i, err = -ENOMEM;
+ struct bcm43xx_dmadesc *desc;
+ struct bcm43xx_dmadesc_meta *meta;
+
+ for (i = 0; i < ring->nr_slots; i++) {
+ desc = ring->vbase + i;
+ meta = ring->meta + i;
+
+ err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
+ if (err)
+ goto err_unwind;
+ }
+ ring->used_slots = ring->nr_slots;
+ err = 0;
+out:
+ return err;
+
+err_unwind:
+ for (i--; i >= 0; i--) {
+ desc = ring->vbase + i;
+ meta = ring->meta + i;
+
+ unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
+ dev_kfree_skb(meta->skb);
+ }
+ goto out;
+}
+
+/* Do initial setup of the DMA controller.
+ * Reset the controller, write the ring busaddress
+ * and switch the "enable" bit on.
+ */
+static int dmacontroller_setup(struct bcm43xx_dmaring *ring)
+{
+ int err = 0;
+ u32 value;
+
+ if (ring->tx) {
+ /* Set Transmit Control register to "transmit enable" */
+ bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL,
+ BCM43xx_DMA_TXCTRL_ENABLE);
+ /* Set Transmit Descriptor ring address. */
+ bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING,
+ ring->dmabase + ring->memoffset);
+ } else {
+ err = alloc_initial_descbuffers(ring);
+ if (err)
+ goto out;
+ /* Set Receive Control "receive enable" and frame offset */
+ value = (ring->frameoffset << BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT);
+ value |= BCM43xx_DMA_RXCTRL_ENABLE;
+ bcm43xx_dma_write(ring, BCM43xx_DMA_RX_CONTROL, value);
+ /* Set Receive Descriptor ring address. */
+ bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING,
+ ring->dmabase + ring->memoffset);
+ /* Init the descriptor pointer. */
+ bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX, 200);
+ }
+
+out:
+ return err;
+}
+
+/* Shutdown the DMA controller. */
+static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring)
+{
+ if (ring->tx) {
+ bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base);
+ /* Zero out Transmit Descriptor ring address. */
+ bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING, 0);
+ } else {
+ bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base);
+ /* Zero out Receive Descriptor ring address. */
+ bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING, 0);
+ }
+}
+
+static void free_all_descbuffers(struct bcm43xx_dmaring *ring)
+{
+ struct bcm43xx_dmadesc *desc;
+ struct bcm43xx_dmadesc_meta *meta;
+ int i;
+
+ if (!ring->used_slots)
+ return;
+ for (i = 0; i < ring->nr_slots; i++) {
+ desc = ring->vbase + i;
+ meta = ring->meta + i;
+
+ if (!meta->skb) {
+ assert(ring->tx);
+ continue;
+ }
+ if (ring->tx) {
+ unmap_descbuffer(ring, meta->dmaaddr,
+ meta->skb->len, 1);
+ } else {
+ unmap_descbuffer(ring, meta->dmaaddr,
+ ring->rx_buffersize, 0);
+ }
+ free_descriptor_buffer(ring, desc, meta, 0);
+ }
+}
+
+/* Main initialization function. */
+static
+struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
+ u16 dma_controller_base,
+ int nr_descriptor_slots,
+ int tx)
+{
+ struct bcm43xx_dmaring *ring;
+ int err;
+
+ ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+ if (!ring)
+ goto out;
+
+ ring->meta = kzalloc(sizeof(*ring->meta) * nr_descriptor_slots,
+ GFP_KERNEL);
+ if (!ring->meta)
+ goto err_kfree_ring;
+
+ ring->memoffset = BCM43xx_DMA_DMABUSADDROFFSET;
+#ifdef CONFIG_BCM947XX
+ if (bcm->pci_dev->bus->number == 0)
+ ring->memoffset = 0;
+#endif
+
+ ring->bcm = bcm;
+ ring->nr_slots = nr_descriptor_slots;
+ ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100;
+ ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100;
+ assert(ring->suspend_mark < ring->resume_mark);
+ ring->mmio_base = dma_controller_base;
+ if (tx) {
+ ring->tx = 1;
+ ring->current_slot = -1;
+ } else {
+ switch (dma_controller_base) {
+ case BCM43xx_MMIO_DMA1_BASE:
+ ring->rx_buffersize = BCM43xx_DMA1_RXBUFFERSIZE;
+ ring->frameoffset = BCM43xx_DMA1_RX_FRAMEOFFSET;
+ break;
+ case BCM43xx_MMIO_DMA4_BASE:
+ ring->rx_buffersize = BCM43xx_DMA4_RXBUFFERSIZE;
+ ring->frameoffset = BCM43xx_DMA4_RX_FRAMEOFFSET;
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ err = alloc_ringmemory(ring);
+ if (err)
+ goto err_kfree_meta;
+ err = dmacontroller_setup(ring);
+ if (err)
+ goto err_free_ringmemory;
+
+out:
+ return ring;
+
+err_free_ringmemory:
+ free_ringmemory(ring);
+err_kfree_meta:
+ kfree(ring->meta);
+err_kfree_ring:
+ kfree(ring);
+ ring = NULL;
+ goto out;
+}
+
+/* Main cleanup function. */
+static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring)
+{
+ if (!ring)
+ return;
+
+ dprintk(KERN_INFO PFX "DMA 0x%04x (%s) max used slots: %d/%d\n",
+ ring->mmio_base,
+ (ring->tx) ? "TX" : "RX",
+ ring->max_used_slots, ring->nr_slots);
+ /* Device IRQs are disabled prior entering this function,
+ * so no need to take care of concurrency with rx handler stuff.
+ */
+ dmacontroller_cleanup(ring);
+ free_all_descbuffers(ring);
+ free_ringmemory(ring);
+
+ kfree(ring->meta);
+ kfree(ring);
+}
+
+void bcm43xx_dma_free(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_dma *dma;
+
+ if (bcm43xx_using_pio(bcm))
+ return;
+ dma = bcm43xx_current_dma(bcm);
+
+ bcm43xx_destroy_dmaring(dma->rx_ring1);
+ dma->rx_ring1 = NULL;
+ bcm43xx_destroy_dmaring(dma->rx_ring0);
+ dma->rx_ring0 = NULL;
+ bcm43xx_destroy_dmaring(dma->tx_ring3);
+ dma->tx_ring3 = NULL;
+ bcm43xx_destroy_dmaring(dma->tx_ring2);
+ dma->tx_ring2 = NULL;
+ bcm43xx_destroy_dmaring(dma->tx_ring1);
+ dma->tx_ring1 = NULL;
+ bcm43xx_destroy_dmaring(dma->tx_ring0);
+ dma->tx_ring0 = NULL;
+}
+
+int bcm43xx_dma_init(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
+ struct bcm43xx_dmaring *ring;
+ int err = -ENOMEM;
+
+ /* setup TX DMA channels. */
+ ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE,
+ BCM43xx_TXRING_SLOTS, 1);
+ if (!ring)
+ goto out;
+ dma->tx_ring0 = ring;
+
+ ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA2_BASE,
+ BCM43xx_TXRING_SLOTS, 1);
+ if (!ring)
+ goto err_destroy_tx0;
+ dma->tx_ring1 = ring;
+
+ ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA3_BASE,
+ BCM43xx_TXRING_SLOTS, 1);
+ if (!ring)
+ goto err_destroy_tx1;
+ dma->tx_ring2 = ring;
+
+ ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE,
+ BCM43xx_TXRING_SLOTS, 1);
+ if (!ring)
+ goto err_destroy_tx2;
+ dma->tx_ring3 = ring;
+
+ /* setup RX DMA channels. */
+ ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE,
+ BCM43xx_RXRING_SLOTS, 0);
+ if (!ring)
+ goto err_destroy_tx3;
+ dma->rx_ring0 = ring;
+
+ if (bcm->current_core->rev < 5) {
+ ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE,
+ BCM43xx_RXRING_SLOTS, 0);
+ if (!ring)
+ goto err_destroy_rx0;
+ dma->rx_ring1 = ring;
+ }
+
+ dprintk(KERN_INFO PFX "DMA initialized\n");
+ err = 0;
+out:
+ return err;
+
+err_destroy_rx0:
+ bcm43xx_destroy_dmaring(dma->rx_ring0);
+ dma->rx_ring0 = NULL;
+err_destroy_tx3:
+ bcm43xx_destroy_dmaring(dma->tx_ring3);
+ dma->tx_ring3 = NULL;
+err_destroy_tx2:
+ bcm43xx_destroy_dmaring(dma->tx_ring2);
+ dma->tx_ring2 = NULL;
+err_destroy_tx1:
+ bcm43xx_destroy_dmaring(dma->tx_ring1);
+ dma->tx_ring1 = NULL;
+err_destroy_tx0:
+ bcm43xx_destroy_dmaring(dma->tx_ring0);
+ dma->tx_ring0 = NULL;
+ goto out;
+}
+
+/* Generate a cookie for the TX header. */
+static u16 generate_cookie(struct bcm43xx_dmaring *ring,
+ int slot)
+{
+ u16 cookie = 0xF000;
+
+ /* Use the upper 4 bits of the cookie as
+ * DMA controller ID and store the slot number
+ * in the lower 12 bits.
+ * Note that the cookie must never be 0, as this
+ * is a special value used in RX path.
+ */
+ switch (ring->mmio_base) {
+ default:
+ assert(0);
+ case BCM43xx_MMIO_DMA1_BASE:
+ cookie = 0xA000;
+ break;
+ case BCM43xx_MMIO_DMA2_BASE:
+ cookie = 0xB000;
+ break;
+ case BCM43xx_MMIO_DMA3_BASE:
+ cookie = 0xC000;
+ break;
+ case BCM43xx_MMIO_DMA4_BASE:
+ cookie = 0xD000;
+ break;
+ }
+ assert(((u16)slot & 0xF000) == 0x0000);
+ cookie |= (u16)slot;
+
+ return cookie;
+}
+
+/* Inspect a cookie and find out to which controller/slot it belongs. */
+static
+struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm,
+ u16 cookie, int *slot)
+{
+ struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
+ struct bcm43xx_dmaring *ring = NULL;
+
+ switch (cookie & 0xF000) {
+ case 0xA000:
+ ring = dma->tx_ring0;
+ break;
+ case 0xB000:
+ ring = dma->tx_ring1;
+ break;
+ case 0xC000:
+ ring = dma->tx_ring2;
+ break;
+ case 0xD000:
+ ring = dma->tx_ring3;
+ break;
+ default:
+ assert(0);
+ }
+ *slot = (cookie & 0x0FFF);
+ assert(*slot >= 0 && *slot < ring->nr_slots);
+
+ return ring;
+}
+
+static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring,
+ int slot)
+{
+ /* Everything is ready to start. Buffers are DMA mapped and
+ * associated with slots.
+ * "slot" is the last slot of the new frame we want to transmit.
+ * Close your seat belts now, please.
+ */
+ wmb();
+ slot = next_slot(ring, slot);
+ bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_INDEX,
+ (u32)(slot * sizeof(struct bcm43xx_dmadesc)));
+}
+
+static int dma_tx_fragment(struct bcm43xx_dmaring *ring,
+ struct sk_buff *skb,
+ u8 cur_frag)
+{
+ int slot;
+ struct bcm43xx_dmadesc *desc;
+ struct bcm43xx_dmadesc_meta *meta;
+ u32 desc_ctl;
+ u32 desc_addr;
+
+ assert(skb_shinfo(skb)->nr_frags == 0);
+
+ slot = request_slot(ring);
+ desc = ring->vbase + slot;
+ meta = ring->meta + slot;
+
+ /* Add a device specific TX header. */
+ assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr));
+ /* Reserve enough headroom for the device tx header. */
+ __skb_push(skb, sizeof(struct bcm43xx_txhdr));
+ /* Now calculate and add the tx header.
+ * The tx header includes the PLCP header.
+ */
+ bcm43xx_generate_txhdr(ring->bcm,
+ (struct bcm43xx_txhdr *)skb->data,
+ skb->data + sizeof(struct bcm43xx_txhdr),
+ skb->len - sizeof(struct bcm43xx_txhdr),
+ (cur_frag == 0),
+ generate_cookie(ring, slot));
+
+ meta->skb = skb;
+ meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+ if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) {
+ return_slot(ring, slot);
+ printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G "
+ "(0x%llx, len: %u)\n",
+ (unsigned long long)meta->dmaaddr, skb->len);
+ return -ENOMEM;
+ }
+
+ desc_addr = (u32)(meta->dmaaddr + ring->memoffset);
+ desc_ctl = BCM43xx_DMADTOR_FRAMESTART | BCM43xx_DMADTOR_FRAMEEND;
+ desc_ctl |= BCM43xx_DMADTOR_COMPIRQ;
+ desc_ctl |= (BCM43xx_DMADTOR_BYTECNT_MASK &
+ (u32)(meta->skb->len - ring->frameoffset));
+ if (slot == ring->nr_slots - 1)
+ desc_ctl |= BCM43xx_DMADTOR_DTABLEEND;
+
+ set_desc_ctl(desc, desc_ctl);
+ set_desc_addr(desc, desc_addr);
+ /* Now transfer the whole frame. */
+ dmacontroller_poke_tx(ring, slot);
+
+ return 0;
+}
+
+int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
+ struct ieee80211_txb *txb)
+{
+ /* We just received a packet from the kernel network subsystem.
+ * Add headers and DMA map the memory. Poke
+ * the device to send the stuff.
+ * Note that this is called from atomic context.
+ */
+ struct bcm43xx_dmaring *ring = bcm43xx_current_dma(bcm)->tx_ring1;
+ u8 i;
+ struct sk_buff *skb;
+
+ assert(ring->tx);
+ if (unlikely(free_slots(ring) < txb->nr_frags)) {
+ /* The queue should be stopped,
+ * if we are low on free slots.
+ * If this ever triggers, we have to lower the suspend_mark.
+ */
+ dprintkl(KERN_ERR PFX "Out of DMA descriptor slots!\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < txb->nr_frags; i++) {
+ skb = txb->fragments[i];
+ /* Take skb from ieee80211_txb_free */
+ txb->fragments[i] = NULL;
+ dma_tx_fragment(ring, skb, i);
+ //TODO: handle failure of dma_tx_fragment
+ }
+ ieee80211_txb_free(txb);
+
+ return 0;
+}
+
+void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
+ struct bcm43xx_xmitstatus *status)
+{
+ struct bcm43xx_dmaring *ring;
+ struct bcm43xx_dmadesc *desc;
+ struct bcm43xx_dmadesc_meta *meta;
+ int is_last_fragment;
+ int slot;
+
+ ring = parse_cookie(bcm, status->cookie, &slot);
+ assert(ring);
+ assert(ring->tx);
+ assert(get_desc_ctl(ring->vbase + slot) & BCM43xx_DMADTOR_FRAMESTART);
+ while (1) {
+ assert(slot >= 0 && slot < ring->nr_slots);
+ desc = ring->vbase + slot;
+ meta = ring->meta + slot;
+
+ is_last_fragment = !!(get_desc_ctl(desc) & BCM43xx_DMADTOR_FRAMEEND);
+ unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
+ free_descriptor_buffer(ring, desc, meta, 1);
+ /* Everything belonging to the slot is unmapped
+ * and freed, so we can return it.
+ */
+ return_slot(ring, slot);
+
+ if (is_last_fragment)
+ break;
+ slot = next_slot(ring, slot);
+ }
+ bcm->stats.last_tx = jiffies;
+}
+
+static void dma_rx(struct bcm43xx_dmaring *ring,
+ int *slot)
+{
+ struct bcm43xx_dmadesc *desc;
+ struct bcm43xx_dmadesc_meta *meta;
+ struct bcm43xx_rxhdr *rxhdr;
+ struct sk_buff *skb;
+ u16 len;
+ int err;
+ dma_addr_t dmaaddr;
+
+ desc = ring->vbase + *slot;
+ meta = ring->meta + *slot;
+
+ sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
+ skb = meta->skb;
+
+ if (ring->mmio_base == BCM43xx_MMIO_DMA4_BASE) {
+ /* We received an xmit status. */
+ struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data;
+ struct bcm43xx_xmitstatus stat;
+ int i = 0;
+
+ stat.cookie = le16_to_cpu(hw->cookie);
+ while (stat.cookie == 0) {
+ if (unlikely(++i >= 10000)) {
+ assert(0);
+ break;
+ }
+ udelay(2);
+ barrier();
+ stat.cookie = le16_to_cpu(hw->cookie);
+ }
+ stat.flags = hw->flags;
+ stat.cnt1 = hw->cnt1;
+ stat.cnt2 = hw->cnt2;
+ stat.seq = le16_to_cpu(hw->seq);
+ stat.unknown = le16_to_cpu(hw->unknown);
+
+ bcm43xx_debugfs_log_txstat(ring->bcm, &stat);
+ bcm43xx_dma_handle_xmitstatus(ring->bcm, &stat);
+ /* recycle the descriptor buffer. */
+ sync_descbuffer_for_device(ring, meta->dmaaddr, ring->rx_buffersize);
+
+ return;
+ }
+ rxhdr = (struct bcm43xx_rxhdr *)skb->data;
+ len = le16_to_cpu(rxhdr->frame_length);
+ if (len == 0) {
+ int i = 0;
+
+ do {
+ udelay(2);
+ barrier();
+ len = le16_to_cpu(rxhdr->frame_length);
+ } while (len == 0 && i++ < 5);
+ if (unlikely(len == 0)) {
+ /* recycle the descriptor buffer. */
+ sync_descbuffer_for_device(ring, meta->dmaaddr,
+ ring->rx_buffersize);
+ goto drop;
+ }
+ }
+ if (unlikely(len > ring->rx_buffersize)) {
+ /* The data did not fit into one descriptor buffer
+ * and is split over multiple buffers.
+ * This should never happen, as we try to allocate buffers
+ * big enough. So simply ignore this packet.
+ */
+ int cnt = 0;
+ s32 tmp = len;
+
+ while (1) {
+ desc = ring->vbase + *slot;
+ meta = ring->meta + *slot;
+ /* recycle the descriptor buffer. */
+ sync_descbuffer_for_device(ring, meta->dmaaddr,
+ ring->rx_buffersize);
+ *slot = next_slot(ring, *slot);
+ cnt++;
+ tmp -= ring->rx_buffersize;
+ if (tmp <= 0)
+ break;
+ }
+ printkl(KERN_ERR PFX "DMA RX buffer too small "
+ "(len: %u, buffer: %u, nr-dropped: %d)\n",
+ len, ring->rx_buffersize, cnt);
+ goto drop;
+ }
+ len -= IEEE80211_FCS_LEN;
+
+ dmaaddr = meta->dmaaddr;
+ err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC);
+ if (unlikely(err)) {
+ dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n");
+ sync_descbuffer_for_device(ring, dmaaddr,
+ ring->rx_buffersize);
+ goto drop;
+ }
+
+ unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
+ skb_put(skb, len + ring->frameoffset);
+ skb_pull(skb, ring->frameoffset);
+
+ err = bcm43xx_rx(ring->bcm, skb, rxhdr);
+ if (err) {
+ dev_kfree_skb_irq(skb);
+ goto drop;
+ }
+
+drop:
+ return;
+}
+
+void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
+{
+ u32 status;
+ u16 descptr;
+ int slot, current_slot;
+#ifdef CONFIG_BCM43XX_DEBUG
+ int used_slots = 0;
+#endif
+
+ assert(!ring->tx);
+ status = bcm43xx_dma_read(ring, BCM43xx_DMA_RX_STATUS);
+ descptr = (status & BCM43xx_DMA_RXSTAT_DPTR_MASK);
+ current_slot = descptr / sizeof(struct bcm43xx_dmadesc);
+ assert(current_slot >= 0 && current_slot < ring->nr_slots);
+
+ slot = ring->current_slot;
+ for ( ; slot != current_slot; slot = next_slot(ring, slot)) {
+ dma_rx(ring, &slot);
+#ifdef CONFIG_BCM43XX_DEBUG
+ if (++used_slots > ring->max_used_slots)
+ ring->max_used_slots = used_slots;
+#endif
+ }
+ bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX,
+ (u32)(slot * sizeof(struct bcm43xx_dmadesc)));
+ ring->current_slot = slot;
+}
+
+void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
+{
+ assert(ring->tx);
+ bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1);
+ bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL,
+ bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL)
+ | BCM43xx_DMA_TXCTRL_SUSPEND);
+}
+
+void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
+{
+ assert(ring->tx);
+ bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL,
+ bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL)
+ & ~BCM43xx_DMA_TXCTRL_SUSPEND);
+ bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1);
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
new file mode 100644
index 00000000000..b7d77638ba8
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
@@ -0,0 +1,226 @@
+#ifndef BCM43xx_DMA_H_
+#define BCM43xx_DMA_H_
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/linkage.h>
+#include <asm/atomic.h>
+
+
+/* DMA-Interrupt reasons. */
+#define BCM43xx_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
+ | (1 << 14) | (1 << 15))
+#define BCM43xx_DMAIRQ_NONFATALMASK (1 << 13)
+#define BCM43xx_DMAIRQ_RX_DONE (1 << 16)
+
+/* DMA controller register offsets. (relative to BCM43xx_DMA#_BASE) */
+#define BCM43xx_DMA_TX_CONTROL 0x00
+#define BCM43xx_DMA_TX_DESC_RING 0x04
+#define BCM43xx_DMA_TX_DESC_INDEX 0x08
+#define BCM43xx_DMA_TX_STATUS 0x0c
+#define BCM43xx_DMA_RX_CONTROL 0x10
+#define BCM43xx_DMA_RX_DESC_RING 0x14
+#define BCM43xx_DMA_RX_DESC_INDEX 0x18
+#define BCM43xx_DMA_RX_STATUS 0x1c
+
+/* DMA controller channel control word values. */
+#define BCM43xx_DMA_TXCTRL_ENABLE (1 << 0)
+#define BCM43xx_DMA_TXCTRL_SUSPEND (1 << 1)
+#define BCM43xx_DMA_TXCTRL_LOOPBACK (1 << 2)
+#define BCM43xx_DMA_TXCTRL_FLUSH (1 << 4)
+#define BCM43xx_DMA_RXCTRL_ENABLE (1 << 0)
+#define BCM43xx_DMA_RXCTRL_FRAMEOFF_MASK 0x000000fe
+#define BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT 1
+#define BCM43xx_DMA_RXCTRL_PIO (1 << 8)
+/* DMA controller channel status word values. */
+#define BCM43xx_DMA_TXSTAT_DPTR_MASK 0x00000fff
+#define BCM43xx_DMA_TXSTAT_STAT_MASK 0x0000f000
+#define BCM43xx_DMA_TXSTAT_STAT_DISABLED 0x00000000
+#define BCM43xx_DMA_TXSTAT_STAT_ACTIVE 0x00001000
+#define BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT 0x00002000
+#define BCM43xx_DMA_TXSTAT_STAT_STOPPED 0x00003000
+#define BCM43xx_DMA_TXSTAT_STAT_SUSP 0x00004000
+#define BCM43xx_DMA_TXSTAT_ERROR_MASK 0x000f0000
+#define BCM43xx_DMA_TXSTAT_FLUSHED (1 << 20)
+#define BCM43xx_DMA_RXSTAT_DPTR_MASK 0x00000fff
+#define BCM43xx_DMA_RXSTAT_STAT_MASK 0x0000f000
+#define BCM43xx_DMA_RXSTAT_STAT_DISABLED 0x00000000
+#define BCM43xx_DMA_RXSTAT_STAT_ACTIVE 0x00001000
+#define BCM43xx_DMA_RXSTAT_STAT_IDLEWAIT 0x00002000
+#define BCM43xx_DMA_RXSTAT_STAT_RESERVED 0x00003000
+#define BCM43xx_DMA_RXSTAT_STAT_ERRORS 0x00004000
+#define BCM43xx_DMA_RXSTAT_ERROR_MASK 0x000f0000
+
+/* DMA descriptor control field values. */
+#define BCM43xx_DMADTOR_BYTECNT_MASK 0x00001fff
+#define BCM43xx_DMADTOR_DTABLEEND (1 << 28) /* End of descriptor table */
+#define BCM43xx_DMADTOR_COMPIRQ (1 << 29) /* IRQ on completion request */
+#define BCM43xx_DMADTOR_FRAMEEND (1 << 30)
+#define BCM43xx_DMADTOR_FRAMESTART (1 << 31)
+
+/* Misc DMA constants */
+#define BCM43xx_DMA_RINGMEMSIZE PAGE_SIZE
+#define BCM43xx_DMA_BUSADDRMAX 0x3FFFFFFF
+#define BCM43xx_DMA_DMABUSADDROFFSET (1 << 30)
+#define BCM43xx_DMA1_RX_FRAMEOFFSET 30
+#define BCM43xx_DMA4_RX_FRAMEOFFSET 0
+
+/* DMA engine tuning knobs */
+#define BCM43xx_TXRING_SLOTS 512
+#define BCM43xx_RXRING_SLOTS 64
+#define BCM43xx_DMA1_RXBUFFERSIZE (2304 + 100)
+#define BCM43xx_DMA4_RXBUFFERSIZE 16
+/* Suspend the tx queue, if less than this percent slots are free. */
+#define BCM43xx_TXSUSPEND_PERCENT 20
+/* Resume the tx queue, if more than this percent slots are free. */
+#define BCM43xx_TXRESUME_PERCENT 50
+
+
+
+#ifdef CONFIG_BCM43XX_DMA
+
+
+struct sk_buff;
+struct bcm43xx_private;
+struct bcm43xx_xmitstatus;
+
+
+struct bcm43xx_dmadesc {
+ __le32 _control;
+ __le32 _address;
+} __attribute__((__packed__));
+
+/* Macros to access the bcm43xx_dmadesc struct */
+#define get_desc_ctl(desc) le32_to_cpu((desc)->_control)
+#define set_desc_ctl(desc, ctl) do { (desc)->_control = cpu_to_le32(ctl); } while (0)
+#define get_desc_addr(desc) le32_to_cpu((desc)->_address)
+#define set_desc_addr(desc, addr) do { (desc)->_address = cpu_to_le32(addr); } while (0)
+
+struct bcm43xx_dmadesc_meta {
+ /* The kernel DMA-able buffer. */
+ struct sk_buff *skb;
+ /* DMA base bus-address of the descriptor buffer. */
+ dma_addr_t dmaaddr;
+};
+
+struct bcm43xx_dmaring {
+ struct bcm43xx_private *bcm;
+ /* Kernel virtual base address of the ring memory. */
+ struct bcm43xx_dmadesc *vbase;
+ /* DMA memory offset */
+ dma_addr_t memoffset;
+ /* (Unadjusted) DMA base bus-address of the ring memory. */
+ dma_addr_t dmabase;
+ /* Meta data about all descriptors. */
+ struct bcm43xx_dmadesc_meta *meta;
+ /* Number of descriptor slots in the ring. */
+ int nr_slots;
+ /* Number of used descriptor slots. */
+ int used_slots;
+ /* Currently used slot in the ring. */
+ int current_slot;
+ /* Marks to suspend/resume the queue. */
+ int suspend_mark;
+ int resume_mark;
+ /* Frameoffset in octets. */
+ u32 frameoffset;
+ /* Descriptor buffer size. */
+ u16 rx_buffersize;
+ /* The MMIO base register of the DMA controller, this
+ * ring is posted to.
+ */
+ u16 mmio_base;
+ u8 tx:1, /* TRUE, if this is a TX ring. */
+ suspended:1; /* TRUE, if transfers are suspended on this ring. */
+#ifdef CONFIG_BCM43XX_DEBUG
+ /* Maximum number of used slots. */
+ int max_used_slots;
+#endif /* CONFIG_BCM43XX_DEBUG*/
+};
+
+
+static inline
+u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring,
+ u16 offset)
+{
+ return bcm43xx_read32(ring->bcm, ring->mmio_base + offset);
+}
+
+static inline
+void bcm43xx_dma_write(struct bcm43xx_dmaring *ring,
+ u16 offset, u32 value)
+{
+ bcm43xx_write32(ring->bcm, ring->mmio_base + offset, value);
+}
+
+
+int bcm43xx_dma_init(struct bcm43xx_private *bcm);
+void bcm43xx_dma_free(struct bcm43xx_private *bcm);
+
+int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
+ u16 dmacontroller_mmio_base);
+int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
+ u16 dmacontroller_mmio_base);
+
+void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring);
+void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring);
+
+void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
+ struct bcm43xx_xmitstatus *status);
+
+int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
+ struct ieee80211_txb *txb);
+void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);
+
+
+#else /* CONFIG_BCM43XX_DMA */
+
+
+static inline
+int bcm43xx_dma_init(struct bcm43xx_private *bcm)
+{
+ return 0;
+}
+static inline
+void bcm43xx_dma_free(struct bcm43xx_private *bcm)
+{
+}
+static inline
+int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
+ u16 dmacontroller_mmio_base)
+{
+ return 0;
+}
+static inline
+int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
+ u16 dmacontroller_mmio_base)
+{
+ return 0;
+}
+static inline
+int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
+ struct ieee80211_txb *txb)
+{
+ return 0;
+}
+static inline
+void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
+ struct bcm43xx_xmitstatus *status)
+{
+}
+static inline
+void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
+{
+}
+static inline
+void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
+{
+}
+static inline
+void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
+{
+}
+
+#endif /* CONFIG_BCM43XX_DMA */
+#endif /* BCM43xx_DMA_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
new file mode 100644
index 00000000000..b3ffcf50131
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
@@ -0,0 +1,50 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ ethtool support
+
+ Copyright (c) 2006 Jason Lunz <lunz@falooley.org>
+
+ Some code in this file is derived from the 8139too.c driver
+ Copyright (C) 2002 Jeff Garzik
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx.h"
+#include "bcm43xx_ethtool.h"
+
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/version.h>
+
+
+static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(dev);
+
+ strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+ strncpy(info->version, UTS_RELEASE, sizeof(info->version));
+ strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN);
+}
+
+struct ethtool_ops bcm43xx_ethtool_ops = {
+ .get_drvinfo = bcm43xx_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+};
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
new file mode 100644
index 00000000000..813704991f6
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
@@ -0,0 +1,8 @@
+#ifndef BCM43xx_ETHTOOL_H_
+#define BCM43xx_ETHTOOL_H_
+
+#include <linux/ethtool.h>
+
+extern struct ethtool_ops bcm43xx_ethtool_ops;
+
+#endif /* BCM43xx_ETHTOOL_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
new file mode 100644
index 00000000000..ad8e569d1fa
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
@@ -0,0 +1,337 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx.h"
+#include "bcm43xx_ilt.h"
+#include "bcm43xx_phy.h"
+
+
+/**** Initial Internal Lookup Tables ****/
+
+const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE] = {
+ 0xFEB93FFD, 0xFEC63FFD, /* 0 */
+ 0xFED23FFD, 0xFEDF3FFD,
+ 0xFEEC3FFE, 0xFEF83FFE,
+ 0xFF053FFE, 0xFF113FFE,
+ 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */
+ 0xFF373FFF, 0xFF443FFF,
+ 0xFF503FFF, 0xFF5D3FFF,
+ 0xFF693FFF, 0xFF763FFF,
+ 0xFF824000, 0xFF8F4000, /* 16 */
+ 0xFF9B4000, 0xFFA84000,
+ 0xFFB54000, 0xFFC14000,
+ 0xFFCE4000, 0xFFDA4000,
+ 0xFFE74000, 0xFFF34000, /* 24 */
+ 0x00004000, 0x000D4000,
+ 0x00194000, 0x00264000,
+ 0x00324000, 0x003F4000,
+ 0x004B4000, 0x00584000, /* 32 */
+ 0x00654000, 0x00714000,
+ 0x007E4000, 0x008A3FFF,
+ 0x00973FFF, 0x00A33FFF,
+ 0x00B03FFF, 0x00BC3FFF, /* 40 */
+ 0x00C93FFF, 0x00D63FFF,
+ 0x00E23FFE, 0x00EF3FFE,
+ 0x00FB3FFE, 0x01083FFE,
+ 0x01143FFE, 0x01213FFD, /* 48 */
+ 0x012E3FFD, 0x013A3FFD,
+ 0x01473FFD,
+};
+
+const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE] = {
+ 0xDB93CB87, 0xD666CF64, /* 0 */
+ 0xD1FDD358, 0xCDA6D826,
+ 0xCA38DD9F, 0xC729E2B4,
+ 0xC469E88E, 0xC26AEE2B,
+ 0xC0DEF46C, 0xC073FA62, /* 8 */
+ 0xC01D00D5, 0xC0760743,
+ 0xC1560D1E, 0xC2E51369,
+ 0xC4ED18FF, 0xC7AC1ED7,
+ 0xCB2823B2, 0xCEFA28D9, /* 16 */
+ 0xD2F62D3F, 0xD7BB3197,
+ 0xDCE53568, 0xE1FE3875,
+ 0xE7D13B35, 0xED663D35,
+ 0xF39B3EC4, 0xF98E3FA7, /* 24 */
+ 0x00004000, 0x06723FA7,
+ 0x0C653EC4, 0x129A3D35,
+ 0x182F3B35, 0x1E023875,
+ 0x231B3568, 0x28453197, /* 32 */
+ 0x2D0A2D3F, 0x310628D9,
+ 0x34D823B2, 0x38541ED7,
+ 0x3B1318FF, 0x3D1B1369,
+ 0x3EAA0D1E, 0x3F8A0743, /* 40 */
+ 0x3FE300D5, 0x3F8DFA62,
+ 0x3F22F46C, 0x3D96EE2B,
+ 0x3B97E88E, 0x38D7E2B4,
+ 0x35C8DD9F, 0x325AD826, /* 48 */
+ 0x2E03D358, 0x299ACF64,
+ 0x246DCB87,
+};
+
+const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE] = {
+ 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */
+ 0x0202, 0x0282, 0x0302, 0x0382,
+ 0x0402, 0x0482, 0x0502, 0x0582,
+ 0x05E2, 0x0662, 0x06E2, 0x0762,
+ 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */
+ 0x09C2, 0x0A22, 0x0AA2, 0x0B02,
+ 0x0B82, 0x0BE2, 0x0C62, 0x0CC2,
+ 0x0D42, 0x0DA2, 0x0E02, 0x0E62,
+ 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */
+ 0x1062, 0x10C2, 0x1122, 0x1182,
+ 0x11E2, 0x1242, 0x12A2, 0x12E2,
+ 0x1342, 0x13A2, 0x1402, 0x1442,
+ 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */
+ 0x15E2, 0x1622, 0x1662, 0x16C1,
+ 0x1701, 0x1741, 0x1781, 0x17E1,
+ 0x1821, 0x1861, 0x18A1, 0x18E1,
+ 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */
+ 0x1A21, 0x1A61, 0x1AA1, 0x1AC1,
+ 0x1B01, 0x1B41, 0x1B81, 0x1BA1,
+ 0x1BE1, 0x1C21, 0x1C41, 0x1C81,
+ 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */
+ 0x1D61, 0x1DA1, 0x1DC1, 0x1E01,
+ 0x1E21, 0x1E61, 0x1E81, 0x1EA1,
+ 0x1EE1, 0x1F01, 0x1F21, 0x1F41,
+ 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */
+ 0x2001, 0x2041, 0x2061, 0x2081,
+ 0x20A1, 0x20C1, 0x20E1, 0x2101,
+ 0x2121, 0x2141, 0x2161, 0x2181,
+ 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */
+ 0x2221, 0x2241, 0x2261, 0x2281,
+ 0x22A1, 0x22C1, 0x22C1, 0x22E1,
+ 0x2301, 0x2321, 0x2341, 0x2361,
+ 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */
+ 0x23E1, 0x23E1, 0x2401, 0x2421,
+ 0x2441, 0x2441, 0x2461, 0x2481,
+ 0x2481, 0x24A1, 0x24C1, 0x24C1,
+ 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */
+ 0x2541, 0x2541, 0x2561, 0x2561,
+ 0x2581, 0x25A1, 0x25A1, 0x25C1,
+ 0x25C1, 0x25E1, 0x2601, 0x2601,
+ 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */
+ 0x2661, 0x2661, 0x2681, 0x2681,
+ 0x26A1, 0x26A1, 0x26C1, 0x26C1,
+ 0x26E1, 0x26E1, 0x2701, 0x2701,
+ 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */
+ 0x2760, 0x2760, 0x2780, 0x2780,
+ 0x2780, 0x27A0, 0x27A0, 0x27C0,
+ 0x27C0, 0x27E0, 0x27E0, 0x27E0,
+ 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */
+ 0x2820, 0x2840, 0x2840, 0x2840,
+ 0x2860, 0x2860, 0x2880, 0x2880,
+ 0x2880, 0x28A0, 0x28A0, 0x28A0,
+ 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */
+ 0x28E0, 0x28E0, 0x2900, 0x2900,
+ 0x2900, 0x2920, 0x2920, 0x2920,
+ 0x2940, 0x2940, 0x2940, 0x2960,
+ 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */
+ 0x2980, 0x2980, 0x29A0, 0x29A0,
+ 0x29A0, 0x29A0, 0x29C0, 0x29C0,
+ 0x29C0, 0x29E0, 0x29E0, 0x29E0,
+ 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */
+ 0x2A00, 0x2A20, 0x2A20, 0x2A20,
+ 0x2A20, 0x2A40, 0x2A40, 0x2A40,
+ 0x2A40, 0x2A60, 0x2A60, 0x2A60,
+};
+
+const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE] = {
+ 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */
+ 0x05A9, 0x0669, 0x0709, 0x0789,
+ 0x0829, 0x08A9, 0x0929, 0x0989,
+ 0x0A09, 0x0A69, 0x0AC9, 0x0B29,
+ 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */
+ 0x0D09, 0x0D69, 0x0DA9, 0x0E09,
+ 0x0E69, 0x0EA9, 0x0F09, 0x0F49,
+ 0x0FA9, 0x0FE9, 0x1029, 0x1089,
+ 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */
+ 0x11E9, 0x1229, 0x1289, 0x12C9,
+ 0x1309, 0x1349, 0x1389, 0x13C9,
+ 0x1409, 0x1449, 0x14A9, 0x14E9,
+ 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */
+ 0x1629, 0x1669, 0x16A9, 0x16E8,
+ 0x1728, 0x1768, 0x17A8, 0x17E8,
+ 0x1828, 0x1868, 0x18A8, 0x18E8,
+ 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */
+ 0x1A28, 0x1A68, 0x1AA8, 0x1AE8,
+ 0x1B28, 0x1B68, 0x1BA8, 0x1BE8,
+ 0x1C28, 0x1C68, 0x1CA8, 0x1CE8,
+ 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */
+ 0x1E48, 0x1E88, 0x1EC8, 0x1F08,
+ 0x1F48, 0x1F88, 0x1FE8, 0x2028,
+ 0x2068, 0x20A8, 0x2108, 0x2148,
+ 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */
+ 0x22C8, 0x2308, 0x2348, 0x23A8,
+ 0x23E8, 0x2448, 0x24A8, 0x24E8,
+ 0x2548, 0x25A8, 0x2608, 0x2668,
+ 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */
+ 0x2847, 0x28C7, 0x2947, 0x29A7,
+ 0x2A27, 0x2AC7, 0x2B47, 0x2BE7,
+ 0x2CA7, 0x2D67, 0x2E47, 0x2F67,
+ 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */
+ 0x3806, 0x38A6, 0x3946, 0x39E6,
+ 0x3A66, 0x3AE6, 0x3B66, 0x3BC6,
+ 0x3C45, 0x3CA5, 0x3D05, 0x3D85,
+ 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */
+ 0x3F45, 0x3FA5, 0x4005, 0x4045,
+ 0x40A5, 0x40E5, 0x4145, 0x4185,
+ 0x41E5, 0x4225, 0x4265, 0x42C5,
+ 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */
+ 0x4424, 0x4464, 0x44C4, 0x4504,
+ 0x4544, 0x4584, 0x45C4, 0x4604,
+ 0x4644, 0x46A4, 0x46E4, 0x4724,
+ 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */
+ 0x4864, 0x48A4, 0x48E4, 0x4924,
+ 0x4964, 0x49A4, 0x49E4, 0x4A24,
+ 0x4A64, 0x4AA4, 0x4AE4, 0x4B23,
+ 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */
+ 0x4C63, 0x4CA3, 0x4CE3, 0x4D23,
+ 0x4D63, 0x4DA3, 0x4DE3, 0x4E23,
+ 0x4E63, 0x4EA3, 0x4EE3, 0x4F23,
+ 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */
+ 0x5083, 0x50C3, 0x5103, 0x5143,
+ 0x5183, 0x51E2, 0x5222, 0x5262,
+ 0x52A2, 0x52E2, 0x5342, 0x5382,
+ 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */
+ 0x5502, 0x5542, 0x55A2, 0x55E2,
+ 0x5642, 0x5682, 0x56E2, 0x5722,
+ 0x5782, 0x57E1, 0x5841, 0x58A1,
+ 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */
+ 0x5AA1, 0x5B01, 0x5B81, 0x5BE1,
+ 0x5C61, 0x5D01, 0x5D80, 0x5E20,
+ 0x5EE0, 0x5FA0, 0x6080, 0x61C0,
+};
+
+const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE] = {
+ 0x0001, 0x0001, 0x0001, 0xFFFE,
+ 0xFFFE, 0x3FFF, 0x1000, 0x0393,
+};
+
+const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE] = {
+ 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+ 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+};
+
+const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE] = {
+ 0x013C, 0x01F5, 0x031A, 0x0631,
+ 0x0001, 0x0001, 0x0001, 0x0001,
+};
+
+const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE] = {
+ 0x5484, 0x3C40, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE] = {
+ 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */
+ 0x2F2D, 0x2A2A, 0x2527, 0x1F21,
+ 0x1A1D, 0x1719, 0x1616, 0x1414,
+ 0x1414, 0x1400, 0x1414, 0x1614,
+ 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */
+ 0x2A27, 0x2F2A, 0x332D, 0x3B35,
+ 0x5140, 0x6C62, 0x0077,
+};
+
+const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE] = {
+ 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */
+ 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
+ 0x969B, 0x9195, 0x8F8F, 0x8A8A,
+ 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
+ 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */
+ 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7,
+ 0xCBC0, 0xD8D4, 0x00DD,
+};
+
+const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE] = {
+ 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */
+ 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+ 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+ 0xA4A4, 0xA400, 0xA4A4, 0xA4A4,
+ 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */
+ 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+ 0xA4A4, 0xA4A4, 0x00A4,
+};
+
+const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE] = {
+ 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */
+ 0x0067, 0x0063, 0x005E, 0x0059,
+ 0x0054, 0x0050, 0x004B, 0x0046,
+ 0x0042, 0x003D, 0x003D, 0x003D,
+ 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */
+ 0x003D, 0x003D, 0x003D, 0x003D,
+ 0x003D, 0x003D, 0x0000, 0x003D,
+ 0x003D, 0x003D, 0x003D, 0x003D,
+ 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */
+ 0x003D, 0x003D, 0x003D, 0x003D,
+ 0x0042, 0x0046, 0x004B, 0x0050,
+ 0x0054, 0x0059, 0x005E, 0x0063,
+ 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */
+ 0x007A,
+};
+
+const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = {
+ 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */
+ 0x00D6, 0x00D4, 0x00D2, 0x00CF,
+ 0x00CD, 0x00CA, 0x00C7, 0x00C4,
+ 0x00C1, 0x00BE, 0x00BE, 0x00BE,
+ 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */
+ 0x00BE, 0x00BE, 0x00BE, 0x00BE,
+ 0x00BE, 0x00BE, 0x0000, 0x00BE,
+ 0x00BE, 0x00BE, 0x00BE, 0x00BE,
+ 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */
+ 0x00BE, 0x00BE, 0x00BE, 0x00BE,
+ 0x00C1, 0x00C4, 0x00C7, 0x00CA,
+ 0x00CD, 0x00CF, 0x00D2, 0x00D4,
+ 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */
+ 0x00DE,
+};
+
+/**** Helper functions to access the device Internal Lookup Tables ****/
+
+void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
+{
+ if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+ mmiowb();
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val);
+ } else {
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+ mmiowb();
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val);
+ }
+}
+
+u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset)
+{
+ if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+ return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1);
+ } else {
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+ return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1);
+ }
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
new file mode 100644
index 00000000000..464521abf73
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
@@ -0,0 +1,32 @@
+#ifndef BCM43xx_ILT_H_
+#define BCM43xx_ILT_H_
+
+#define BCM43xx_ILT_ROTOR_SIZE 53
+extern const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE];
+#define BCM43xx_ILT_RETARD_SIZE 53
+extern const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE];
+#define BCM43xx_ILT_FINEFREQA_SIZE 256
+extern const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE];
+#define BCM43xx_ILT_FINEFREQG_SIZE 256
+extern const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE];
+#define BCM43xx_ILT_NOISEA2_SIZE 8
+extern const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE];
+#define BCM43xx_ILT_NOISEA3_SIZE 8
+extern const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE];
+#define BCM43xx_ILT_NOISEG1_SIZE 8
+extern const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE];
+#define BCM43xx_ILT_NOISEG2_SIZE 8
+extern const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE];
+#define BCM43xx_ILT_NOISESCALEG_SIZE 27
+extern const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE];
+extern const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE];
+extern const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE];
+#define BCM43xx_ILT_SIGMASQR_SIZE 53
+extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE];
+extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE];
+
+
+void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
+u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset);
+
+#endif /* BCM43xx_ILT_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
new file mode 100644
index 00000000000..4b2c02c0b31
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
@@ -0,0 +1,293 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx_leds.h"
+#include "bcm43xx.h"
+
+#include <asm/bitops.h>
+
+
+static void bcm43xx_led_changestate(struct bcm43xx_led *led)
+{
+ struct bcm43xx_private *bcm = led->bcm;
+ const int index = bcm43xx_led_index(led);
+ const u16 mask = (1 << index);
+ u16 ledctl;
+
+ assert(index >= 0 && index < BCM43xx_NR_LEDS);
+ assert(led->blink_interval);
+ ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+ ledctl = (ledctl & mask) ? (ledctl & ~mask) : (ledctl | mask);
+ bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+}
+
+static void bcm43xx_led_blink(unsigned long d)
+{
+ struct bcm43xx_led *led = (struct bcm43xx_led *)d;
+ struct bcm43xx_private *bcm = led->bcm;
+ unsigned long flags;
+
+ bcm43xx_lock_mmio(bcm, flags);
+ if (led->blink_interval) {
+ bcm43xx_led_changestate(led);
+ mod_timer(&led->blink_timer, jiffies + led->blink_interval);
+ }
+ bcm43xx_unlock_mmio(bcm, flags);
+}
+
+static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
+ unsigned long interval)
+{
+ if (led->blink_interval)
+ return;
+ led->blink_interval = interval;
+ bcm43xx_led_changestate(led);
+ led->blink_timer.expires = jiffies + interval;
+ add_timer(&led->blink_timer);
+}
+
+static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync)
+{
+ struct bcm43xx_private *bcm = led->bcm;
+ const int index = bcm43xx_led_index(led);
+ u16 ledctl;
+
+ if (!led->blink_interval)
+ return;
+ if (unlikely(sync))
+ del_timer_sync(&led->blink_timer);
+ else
+ del_timer(&led->blink_timer);
+ led->blink_interval = 0;
+
+ /* Make sure the LED is turned off. */
+ assert(index >= 0 && index < BCM43xx_NR_LEDS);
+ ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+ if (led->activelow)
+ ledctl |= (1 << index);
+ else
+ ledctl &= ~(1 << index);
+ bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+}
+
+static void bcm43xx_led_init_hardcoded(struct bcm43xx_private *bcm,
+ struct bcm43xx_led *led,
+ int led_index)
+{
+ /* This function is called, if the behaviour (and activelow)
+ * information for a LED is missing in the SPROM.
+ * We hardcode the behaviour values for various devices here.
+ * Note that the BCM43xx_LED_TEST_XXX behaviour values can
+ * be used to figure out which led is mapped to which index.
+ */
+
+ switch (led_index) {
+ case 0:
+ led->behaviour = BCM43xx_LED_ACTIVITY;
+ if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ)
+ led->behaviour = BCM43xx_LED_RADIO_ALL;
+ break;
+ case 1:
+ led->behaviour = BCM43xx_LED_RADIO_B;
+ if (bcm->board_vendor == PCI_VENDOR_ID_ASUSTEK)
+ led->behaviour = BCM43xx_LED_ASSOC;
+ break;
+ case 2:
+ led->behaviour = BCM43xx_LED_RADIO_A;
+ break;
+ case 3:
+ led->behaviour = BCM43xx_LED_OFF;
+ break;
+ default:
+ assert(0);
+ }
+}
+
+int bcm43xx_leds_init(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_led *led;
+ u8 sprom[4];
+ int i;
+
+ sprom[0] = bcm->sprom.wl0gpio0;
+ sprom[1] = bcm->sprom.wl0gpio1;
+ sprom[2] = bcm->sprom.wl0gpio2;
+ sprom[3] = bcm->sprom.wl0gpio3;
+
+ for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+ led = &(bcm->leds[i]);
+ led->bcm = bcm;
+ setup_timer(&led->blink_timer,
+ bcm43xx_led_blink,
+ (unsigned long)led);
+
+ if (sprom[i] == 0xFF) {
+ bcm43xx_led_init_hardcoded(bcm, led, i);
+ } else {
+ led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR;
+ led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW);
+ }
+ }
+
+ return 0;
+}
+
+void bcm43xx_leds_exit(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_led *led;
+ int i;
+
+ for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+ led = &(bcm->leds[i]);
+ bcm43xx_led_blink_stop(led, 1);
+ }
+ bcm43xx_leds_switch_all(bcm, 0);
+}
+
+void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
+{
+ struct bcm43xx_led *led;
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES;
+ int i, turn_on;
+ unsigned long interval = 0;
+ u16 ledctl;
+
+ ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+ for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+ led = &(bcm->leds[i]);
+
+ turn_on = 0;
+ switch (led->behaviour) {
+ case BCM43xx_LED_INACTIVE:
+ continue;
+ case BCM43xx_LED_OFF:
+ break;
+ case BCM43xx_LED_ON:
+ turn_on = 1;
+ break;
+ case BCM43xx_LED_ACTIVITY:
+ turn_on = activity;
+ break;
+ case BCM43xx_LED_RADIO_ALL:
+ turn_on = radio->enabled;
+ break;
+ case BCM43xx_LED_RADIO_A:
+ turn_on = (radio->enabled && phy->type == BCM43xx_PHYTYPE_A);
+ break;
+ case BCM43xx_LED_RADIO_B:
+ turn_on = (radio->enabled &&
+ (phy->type == BCM43xx_PHYTYPE_B ||
+ phy->type == BCM43xx_PHYTYPE_G));
+ break;
+ case BCM43xx_LED_MODE_BG:
+ if (phy->type == BCM43xx_PHYTYPE_G &&
+ 1/*FIXME: using G rates.*/)
+ turn_on = 1;
+ break;
+ case BCM43xx_LED_TRANSFER:
+ if (transferring)
+ bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
+ else
+ bcm43xx_led_blink_stop(led, 0);
+ continue;
+ case BCM43xx_LED_APTRANSFER:
+ if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
+ if (transferring) {
+ interval = BCM43xx_LEDBLINK_FAST;
+ turn_on = 1;
+ }
+ } else {
+ turn_on = 1;
+ if (0/*TODO: not assoc*/)
+ interval = BCM43xx_LEDBLINK_SLOW;
+ else if (transferring)
+ interval = BCM43xx_LEDBLINK_FAST;
+ else
+ turn_on = 0;
+ }
+ if (turn_on)
+ bcm43xx_led_blink_start(led, interval);
+ else
+ bcm43xx_led_blink_stop(led, 0);
+ continue;
+ case BCM43xx_LED_WEIRD:
+ //TODO
+ break;
+ case BCM43xx_LED_ASSOC:
+ if (bcm->softmac->associated)
+ turn_on = 1;
+ break;
+#ifdef CONFIG_BCM43XX_DEBUG
+ case BCM43xx_LED_TEST_BLINKSLOW:
+ bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_SLOW);
+ continue;
+ case BCM43xx_LED_TEST_BLINKMEDIUM:
+ bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
+ continue;
+ case BCM43xx_LED_TEST_BLINKFAST:
+ bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_FAST);
+ continue;
+#endif /* CONFIG_BCM43XX_DEBUG */
+ default:
+ assert(0);
+ };
+
+ if (led->activelow)
+ turn_on = !turn_on;
+ if (turn_on)
+ ledctl |= (1 << i);
+ else
+ ledctl &= ~(1 << i);
+ }
+ bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+}
+
+void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
+{
+ struct bcm43xx_led *led;
+ u16 ledctl;
+ int i;
+ int bit_on;
+
+ ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+ for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+ led = &(bcm->leds[i]);
+ if (led->behaviour == BCM43xx_LED_INACTIVE)
+ continue;
+ if (on)
+ bit_on = led->activelow ? 0 : 1;
+ else
+ bit_on = led->activelow ? 1 : 0;
+ if (bit_on)
+ ledctl |= (1 << i);
+ else
+ ledctl &= ~(1 << i);
+ }
+ bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
new file mode 100644
index 00000000000..d3716cf3aeb
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
@@ -0,0 +1,56 @@
+#ifndef BCM43xx_LEDS_H_
+#define BCM43xx_LEDS_H_
+
+#include <linux/types.h>
+#include <linux/timer.h>
+
+
+struct bcm43xx_led {
+ u8 behaviour:7;
+ u8 activelow:1;
+
+ struct bcm43xx_private *bcm;
+ struct timer_list blink_timer;
+ unsigned long blink_interval;
+};
+#define bcm43xx_led_index(led) ((int)((led) - (led)->bcm->leds))
+
+/* Delay between state changes when blinking in jiffies */
+#define BCM43xx_LEDBLINK_SLOW (HZ / 1)
+#define BCM43xx_LEDBLINK_MEDIUM (HZ / 4)
+#define BCM43xx_LEDBLINK_FAST (HZ / 8)
+
+#define BCM43xx_LED_XFER_THRES (HZ / 100)
+
+#define BCM43xx_LED_BEHAVIOUR 0x7F
+#define BCM43xx_LED_ACTIVELOW 0x80
+enum { /* LED behaviour values */
+ BCM43xx_LED_OFF,
+ BCM43xx_LED_ON,
+ BCM43xx_LED_ACTIVITY,
+ BCM43xx_LED_RADIO_ALL,
+ BCM43xx_LED_RADIO_A,
+ BCM43xx_LED_RADIO_B,
+ BCM43xx_LED_MODE_BG,
+ BCM43xx_LED_TRANSFER,
+ BCM43xx_LED_APTRANSFER,
+ BCM43xx_LED_WEIRD,//FIXME
+ BCM43xx_LED_ASSOC,
+ BCM43xx_LED_INACTIVE,
+
+ /* Behaviour values for testing.
+ * With these values it is easier to figure out
+ * the real behaviour of leds, in case the SPROM
+ * is missing information.
+ */
+ BCM43xx_LED_TEST_BLINKSLOW,
+ BCM43xx_LED_TEST_BLINKMEDIUM,
+ BCM43xx_LED_TEST_BLINKFAST,
+};
+
+int bcm43xx_leds_init(struct bcm43xx_private *bcm);
+void bcm43xx_leds_exit(struct bcm43xx_private *bcm);
+void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity);
+void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on);
+
+#endif /* BCM43xx_LEDS_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
new file mode 100644
index 00000000000..7ed18cad29f
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -0,0 +1,3984 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ Some parts of the code in this file are derived from the ipw2200
+ driver Copyright(c) 2003 - 2004 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/version.h>
+#include <linux/firmware.h>
+#include <linux/wireless.h>
+#include <linux/workqueue.h>
+#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
+#include <net/iw_handler.h>
+
+#include "bcm43xx.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_debugfs.h"
+#include "bcm43xx_radio.h"
+#include "bcm43xx_phy.h"
+#include "bcm43xx_dma.h"
+#include "bcm43xx_pio.h"
+#include "bcm43xx_power.h"
+#include "bcm43xx_wx.h"
+#include "bcm43xx_ethtool.h"
+#include "bcm43xx_xmit.h"
+#include "bcm43xx_sysfs.h"
+
+
+MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
+MODULE_AUTHOR("Martin Langer");
+MODULE_AUTHOR("Stefano Brivio");
+MODULE_AUTHOR("Michael Buesch");
+MODULE_LICENSE("GPL");
+
+#ifdef CONFIG_BCM947XX
+extern char *nvram_get(char *name);
+#endif
+
+#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
+static int modparam_pio;
+module_param_named(pio, modparam_pio, int, 0444);
+MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
+#elif defined(CONFIG_BCM43XX_DMA)
+# define modparam_pio 0
+#elif defined(CONFIG_BCM43XX_PIO)
+# define modparam_pio 1
+#endif
+
+static int modparam_bad_frames_preempt;
+module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
+MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames Preemption");
+
+static int modparam_short_retry = BCM43xx_DEFAULT_SHORT_RETRY_LIMIT;
+module_param_named(short_retry, modparam_short_retry, int, 0444);
+MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
+
+static int modparam_long_retry = BCM43xx_DEFAULT_LONG_RETRY_LIMIT;
+module_param_named(long_retry, modparam_long_retry, int, 0444);
+MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
+
+static int modparam_locale = -1;
+module_param_named(locale, modparam_locale, int, 0444);
+MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)");
+
+static int modparam_noleds;
+module_param_named(noleds, modparam_noleds, int, 0444);
+MODULE_PARM_DESC(noleds, "Turn off all LED activity");
+
+#ifdef CONFIG_BCM43XX_DEBUG
+static char modparam_fwpostfix[64];
+module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
+MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
+#else
+# define modparam_fwpostfix ""
+#endif /* CONFIG_BCM43XX_DEBUG*/
+
+
+/* If you want to debug with just a single device, enable this,
+ * where the string is the pci device ID (as given by the kernel's
+ * pci_name function) of the device to be used.
+ */
+//#define DEBUG_SINGLE_DEVICE_ONLY "0001:11:00.0"
+
+/* If you want to enable printing of each MMIO access, enable this. */
+//#define DEBUG_ENABLE_MMIO_PRINT
+
+/* If you want to enable printing of MMIO access within
+ * ucode/pcm upload, initvals write, enable this.
+ */
+//#define DEBUG_ENABLE_UCODE_MMIO_PRINT
+
+/* If you want to enable printing of PCI Config Space access, enable this */
+//#define DEBUG_ENABLE_PCILOG
+
+
+/* Detailed list maintained at:
+ * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices
+ */
+ static struct pci_device_id bcm43xx_pci_tbl[] = {
+ /* Broadcom 4303 802.11b */
+ { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4307 802.11b */
+ { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4318 802.11b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4306 802.11b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4306 802.11a */
+// { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4309 802.11a/b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 43XG 802.11b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+#ifdef CONFIG_BCM947XX
+ /* SB bus on BCM947xx */
+ { PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+#endif
+ { 0 },
+};
+MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl);
+
+static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val)
+{
+ u32 status;
+
+ status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+ if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP))
+ val = swab32(val);
+
+ bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset);
+ mmiowb();
+ bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val);
+}
+
+static inline
+void bcm43xx_shm_control_word(struct bcm43xx_private *bcm,
+ u16 routing, u16 offset)
+{
+ u32 control;
+
+ /* "offset" is the WORD offset. */
+
+ control = routing;
+ control <<= 16;
+ control |= offset;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_CONTROL, control);
+}
+
+u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
+ u16 routing, u16 offset)
+{
+ u32 ret;
+
+ if (routing == BCM43xx_SHM_SHARED) {
+ if (offset & 0x0003) {
+ /* Unaligned access */
+ bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+ ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
+ ret <<= 16;
+ bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
+ ret |= bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
+
+ return ret;
+ }
+ offset >>= 2;
+ }
+ bcm43xx_shm_control_word(bcm, routing, offset);
+ ret = bcm43xx_read32(bcm, BCM43xx_MMIO_SHM_DATA);
+
+ return ret;
+}
+
+u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
+ u16 routing, u16 offset)
+{
+ u16 ret;
+
+ if (routing == BCM43xx_SHM_SHARED) {
+ if (offset & 0x0003) {
+ /* Unaligned access */
+ bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+ ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
+
+ return ret;
+ }
+ offset >>= 2;
+ }
+ bcm43xx_shm_control_word(bcm, routing, offset);
+ ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
+
+ return ret;
+}
+
+void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
+ u16 routing, u16 offset,
+ u32 value)
+{
+ if (routing == BCM43xx_SHM_SHARED) {
+ if (offset & 0x0003) {
+ /* Unaligned access */
+ bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+ mmiowb();
+ bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
+ (value >> 16) & 0xffff);
+ mmiowb();
+ bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
+ mmiowb();
+ bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA,
+ value & 0xffff);
+ return;
+ }
+ offset >>= 2;
+ }
+ bcm43xx_shm_control_word(bcm, routing, offset);
+ mmiowb();
+ bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value);
+}
+
+void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
+ u16 routing, u16 offset,
+ u16 value)
+{
+ if (routing == BCM43xx_SHM_SHARED) {
+ if (offset & 0x0003) {
+ /* Unaligned access */
+ bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+ mmiowb();
+ bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
+ value);
+ return;
+ }
+ offset >>= 2;
+ }
+ bcm43xx_shm_control_word(bcm, routing, offset);
+ mmiowb();
+ bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value);
+}
+
+void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf)
+{
+ /* We need to be careful. As we read the TSF from multiple
+ * registers, we should take care of register overflows.
+ * In theory, the whole tsf read process should be atomic.
+ * We try to be atomic here, by restaring the read process,
+ * if any of the high registers changed (overflew).
+ */
+ if (bcm->current_core->rev >= 3) {
+ u32 low, high, high2;
+
+ do {
+ high = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
+ low = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW);
+ high2 = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
+ } while (unlikely(high != high2));
+
+ *tsf = high;
+ *tsf <<= 32;
+ *tsf |= low;
+ } else {
+ u64 tmp;
+ u16 v0, v1, v2, v3;
+ u16 test1, test2, test3;
+
+ do {
+ v3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
+ v2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
+ v1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
+ v0 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_0);
+
+ test3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
+ test2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
+ test1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
+ } while (v3 != test3 || v2 != test2 || v1 != test1);
+
+ *tsf = v3;
+ *tsf <<= 48;
+ tmp = v2;
+ tmp <<= 32;
+ *tsf |= tmp;
+ tmp = v1;
+ tmp <<= 16;
+ *tsf |= tmp;
+ *tsf |= v0;
+ }
+}
+
+void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf)
+{
+ u32 status;
+
+ status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+ status |= BCM43xx_SBF_TIME_UPDATE;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+ mmiowb();
+
+ /* Be careful with the in-progress timer.
+ * First zero out the low register, so we have a full
+ * register-overflow duration to complete the operation.
+ */
+ if (bcm->current_core->rev >= 3) {
+ u32 lo = (tsf & 0x00000000FFFFFFFFULL);
+ u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
+
+ bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0);
+ mmiowb();
+ bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi);
+ mmiowb();
+ bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo);
+ } else {
+ u16 v0 = (tsf & 0x000000000000FFFFULL);
+ u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;
+ u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;
+ u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;
+
+ bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0);
+ mmiowb();
+ bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3);
+ mmiowb();
+ bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2);
+ mmiowb();
+ bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1);
+ mmiowb();
+ bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0);
+ }
+
+ status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+ status &= ~BCM43xx_SBF_TIME_UPDATE;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+}
+
+static
+void bcm43xx_macfilter_set(struct bcm43xx_private *bcm,
+ u16 offset,
+ const u8 *mac)
+{
+ u16 data;
+
+ offset |= 0x0020;
+ bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_CONTROL, offset);
+
+ data = mac[0];
+ data |= mac[1] << 8;
+ bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
+ data = mac[2];
+ data |= mac[3] << 8;
+ bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
+ data = mac[4];
+ data |= mac[5] << 8;
+ bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
+}
+
+static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm,
+ u16 offset)
+{
+ const u8 zero_addr[ETH_ALEN] = { 0 };
+
+ bcm43xx_macfilter_set(bcm, offset, zero_addr);
+}
+
+static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm)
+{
+ const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr);
+ const u8 *bssid = (const u8 *)(bcm->ieee->bssid);
+ u8 mac_bssid[ETH_ALEN * 2];
+ int i;
+
+ memcpy(mac_bssid, mac, ETH_ALEN);
+ memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
+
+ /* Write our MAC address and BSSID to template ram */
+ for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
+ bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i)));
+ for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
+ bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i)));
+ for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
+ bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i)));
+}
+
+//FIXME: Well, we should probably call them from somewhere.
+#if 0
+static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time)
+{
+ /* slot_time is in usec. */
+ if (bcm43xx_current_phy(bcm)->type != BCM43xx_PHYTYPE_G)
+ return;
+ bcm43xx_write16(bcm, 0x684, 510 + slot_time);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time);
+}
+
+static void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm)
+{
+ bcm43xx_set_slot_time(bcm, 9);
+}
+
+static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm)
+{
+ bcm43xx_set_slot_time(bcm, 20);
+}
+#endif
+
+/* FIXME: To get the MAC-filter working, we need to implement the
+ * following functions (and rename them :)
+ */
+#if 0
+static void bcm43xx_disassociate(struct bcm43xx_private *bcm)
+{
+ bcm43xx_mac_suspend(bcm);
+ bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
+
+ bcm43xx_ram_write(bcm, 0x0026, 0x0000);
+ bcm43xx_ram_write(bcm, 0x0028, 0x0000);
+ bcm43xx_ram_write(bcm, 0x007E, 0x0000);
+ bcm43xx_ram_write(bcm, 0x0080, 0x0000);
+ bcm43xx_ram_write(bcm, 0x047E, 0x0000);
+ bcm43xx_ram_write(bcm, 0x0480, 0x0000);
+
+ if (bcm->current_core->rev < 3) {
+ bcm43xx_write16(bcm, 0x0610, 0x8000);
+ bcm43xx_write16(bcm, 0x060E, 0x0000);
+ } else
+ bcm43xx_write32(bcm, 0x0188, 0x80000000);
+
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
+
+ if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G &&
+ ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate))
+ bcm43xx_short_slot_timing_enable(bcm);
+
+ bcm43xx_mac_enable(bcm);
+}
+
+static void bcm43xx_associate(struct bcm43xx_private *bcm,
+ const u8 *mac)
+{
+ memcpy(bcm->ieee->bssid, mac, ETH_ALEN);
+
+ bcm43xx_mac_suspend(bcm);
+ bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac);
+ bcm43xx_write_mac_bssid_templates(bcm);
+ bcm43xx_mac_enable(bcm);
+}
+#endif
+
+/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
+ * Returns the _previously_ enabled IRQ mask.
+ */
+static inline u32 bcm43xx_interrupt_enable(struct bcm43xx_private *bcm, u32 mask)
+{
+ u32 old_mask;
+
+ old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask | mask);
+
+ return old_mask;
+}
+
+/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
+ * Returns the _previously_ enabled IRQ mask.
+ */
+static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mask)
+{
+ u32 old_mask;
+
+ old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
+
+ return old_mask;
+}
+
+/* Make sure we don't receive more data from the device. */
+static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate)
+{
+ u32 old;
+ unsigned long flags;
+
+ bcm43xx_lock_mmio(bcm, flags);
+ if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) {
+ bcm43xx_unlock_mmio(bcm, flags);
+ return -EBUSY;
+ }
+ old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+ tasklet_disable(&bcm->isr_tasklet);
+ bcm43xx_unlock_mmio(bcm, flags);
+ if (oldstate)
+ *oldstate = old;
+
+ return 0;
+}
+
+static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u32 radio_id;
+ u16 manufact;
+ u16 version;
+ u8 revision;
+ s8 i;
+
+ if (bcm->chip_id == 0x4317) {
+ if (bcm->chip_rev == 0x00)
+ radio_id = 0x3205017F;
+ else if (bcm->chip_rev == 0x01)
+ radio_id = 0x4205017F;
+ else
+ radio_id = 0x5205017F;
+ } else {
+ bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
+ radio_id = bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_HIGH);
+ radio_id <<= 16;
+ bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
+ radio_id |= bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
+ }
+
+ manufact = (radio_id & 0x00000FFF);
+ version = (radio_id & 0x0FFFF000) >> 12;
+ revision = (radio_id & 0xF0000000) >> 28;
+
+ dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n",
+ radio_id, manufact, version, revision);
+
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f))
+ goto err_unsupported_radio;
+ break;
+ case BCM43xx_PHYTYPE_B:
+ if ((version & 0xFFF0) != 0x2050)
+ goto err_unsupported_radio;
+ break;
+ case BCM43xx_PHYTYPE_G:
+ if (version != 0x2050)
+ goto err_unsupported_radio;
+ break;
+ }
+
+ radio->manufact = manufact;
+ radio->version = version;
+ radio->revision = revision;
+
+ /* Set default attenuation values. */
+ radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
+ radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
+ radio->txctl1 = bcm43xx_default_txctl1(bcm);
+ radio->txctl2 = 0xFFFF;
+ if (phy->type == BCM43xx_PHYTYPE_A)
+ radio->txpower_desired = bcm->sprom.maxpower_aphy;
+ else
+ radio->txpower_desired = bcm->sprom.maxpower_bgphy;
+
+ /* Initialize the in-memory nrssi Lookup Table. */
+ for (i = 0; i < 64; i++)
+ radio->nrssi_lt[i] = i;
+
+ return 0;
+
+err_unsupported_radio:
+ printk(KERN_ERR PFX "Unsupported Radio connected to the PHY!\n");
+ return -ENODEV;
+}
+
+static const char * bcm43xx_locale_iso(u8 locale)
+{
+ /* ISO 3166-1 country codes.
+ * Note that there aren't ISO 3166-1 codes for
+ * all or locales. (Not all locales are countries)
+ */
+ switch (locale) {
+ case BCM43xx_LOCALE_WORLD:
+ case BCM43xx_LOCALE_ALL:
+ return "XX";
+ case BCM43xx_LOCALE_THAILAND:
+ return "TH";
+ case BCM43xx_LOCALE_ISRAEL:
+ return "IL";
+ case BCM43xx_LOCALE_JORDAN:
+ return "JO";
+ case BCM43xx_LOCALE_CHINA:
+ return "CN";
+ case BCM43xx_LOCALE_JAPAN:
+ case BCM43xx_LOCALE_JAPAN_HIGH:
+ return "JP";
+ case BCM43xx_LOCALE_USA_CANADA_ANZ:
+ case BCM43xx_LOCALE_USA_LOW:
+ return "US";
+ case BCM43xx_LOCALE_EUROPE:
+ return "EU";
+ case BCM43xx_LOCALE_NONE:
+ return " ";
+ }
+ assert(0);
+ return " ";
+}
+
+static const char * bcm43xx_locale_string(u8 locale)
+{
+ switch (locale) {
+ case BCM43xx_LOCALE_WORLD:
+ return "World";
+ case BCM43xx_LOCALE_THAILAND:
+ return "Thailand";
+ case BCM43xx_LOCALE_ISRAEL:
+ return "Israel";
+ case BCM43xx_LOCALE_JORDAN:
+ return "Jordan";
+ case BCM43xx_LOCALE_CHINA:
+ return "China";
+ case BCM43xx_LOCALE_JAPAN:
+ return "Japan";
+ case BCM43xx_LOCALE_USA_CANADA_ANZ:
+ return "USA/Canada/ANZ";
+ case BCM43xx_LOCALE_EUROPE:
+ return "Europe";
+ case BCM43xx_LOCALE_USA_LOW:
+ return "USAlow";
+ case BCM43xx_LOCALE_JAPAN_HIGH:
+ return "JapanHigh";
+ case BCM43xx_LOCALE_ALL:
+ return "All";
+ case BCM43xx_LOCALE_NONE:
+ return "None";
+ }
+ assert(0);
+ return "";
+}
+
+static inline u8 bcm43xx_crc8(u8 crc, u8 data)
+{
+ static const u8 t[] = {
+ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
+ };
+ return t[crc ^ data];
+}
+
+static u8 bcm43xx_sprom_crc(const u16 *sprom)
+{
+ int word;
+ u8 crc = 0xFF;
+
+ for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) {
+ crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF);
+ crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8);
+ }
+ crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF);
+ crc ^= 0xFF;
+
+ return crc;
+}
+
+int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom)
+{
+ int i;
+ u8 crc, expected_crc;
+
+ for (i = 0; i < BCM43xx_SPROM_SIZE; i++)
+ sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2));
+ /* CRC-8 check. */
+ crc = bcm43xx_sprom_crc(sprom);
+ expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
+ if (crc != expected_crc) {
+ printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum "
+ "(0x%02X, expected: 0x%02X)\n",
+ crc, expected_crc);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom)
+{
+ int i, err;
+ u8 crc, expected_crc;
+ u32 spromctl;
+
+ /* CRC-8 validation of the input data. */
+ crc = bcm43xx_sprom_crc(sprom);
+ expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
+ if (crc != expected_crc) {
+ printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n");
+ return -EINVAL;
+ }
+
+ printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
+ err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl);
+ if (err)
+ goto err_ctlreg;
+ spromctl |= 0x10; /* SPROM WRITE enable. */
+ bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
+ if (err)
+ goto err_ctlreg;
+ /* We must burn lots of CPU cycles here, but that does not
+ * really matter as one does not write the SPROM every other minute...
+ */
+ printk(KERN_INFO PFX "[ 0%%");
+ mdelay(500);
+ for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+ if (i == 16)
+ printk("25%%");
+ else if (i == 32)
+ printk("50%%");
+ else if (i == 48)
+ printk("75%%");
+ else if (i % 2)
+ printk(".");
+ bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]);
+ mmiowb();
+ mdelay(20);
+ }
+ spromctl &= ~0x10; /* SPROM WRITE enable. */
+ bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
+ if (err)
+ goto err_ctlreg;
+ mdelay(500);
+ printk("100%% ]\n");
+ printk(KERN_INFO PFX "SPROM written.\n");
+ bcm43xx_controller_restart(bcm, "SPROM update");
+
+ return 0;
+err_ctlreg:
+ printk(KERN_ERR PFX "Could not access SPROM control register.\n");
+ return -ENODEV;
+}
+
+static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
+{
+ u16 value;
+ u16 *sprom;
+#ifdef CONFIG_BCM947XX
+ char *c;
+#endif
+
+ sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
+ GFP_KERNEL);
+ if (!sprom) {
+ printk(KERN_ERR PFX "sprom_extract OOM\n");
+ return -ENOMEM;
+ }
+#ifdef CONFIG_BCM947XX
+ sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2"));
+ sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags"));
+
+ if ((c = nvram_get("il0macaddr")) != NULL)
+ e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR]));
+
+ if ((c = nvram_get("et1macaddr")) != NULL)
+ e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR]));
+
+ sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0"));
+ sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1"));
+ sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2"));
+
+ sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0"));
+ sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1"));
+ sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2"));
+
+ sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev"));
+#else
+ bcm43xx_sprom_read(bcm, sprom);
+#endif
+
+ /* boardflags2 */
+ value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
+ bcm->sprom.boardflags2 = value;
+
+ /* il0macaddr */
+ value = sprom[BCM43xx_SPROM_IL0MACADDR + 0];
+ *(((u16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value);
+ value = sprom[BCM43xx_SPROM_IL0MACADDR + 1];
+ *(((u16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value);
+ value = sprom[BCM43xx_SPROM_IL0MACADDR + 2];
+ *(((u16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value);
+
+ /* et0macaddr */
+ value = sprom[BCM43xx_SPROM_ET0MACADDR + 0];
+ *(((u16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value);
+ value = sprom[BCM43xx_SPROM_ET0MACADDR + 1];
+ *(((u16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value);
+ value = sprom[BCM43xx_SPROM_ET0MACADDR + 2];
+ *(((u16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value);
+
+ /* et1macaddr */
+ value = sprom[BCM43xx_SPROM_ET1MACADDR + 0];
+ *(((u16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value);
+ value = sprom[BCM43xx_SPROM_ET1MACADDR + 1];
+ *(((u16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value);
+ value = sprom[BCM43xx_SPROM_ET1MACADDR + 2];
+ *(((u16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value);
+
+ /* ethernet phy settings */
+ value = sprom[BCM43xx_SPROM_ETHPHY];
+ bcm->sprom.et0phyaddr = (value & 0x001F);
+ bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5;
+ bcm->sprom.et0mdcport = (value & (1 << 14)) >> 14;
+ bcm->sprom.et1mdcport = (value & (1 << 15)) >> 15;
+
+ /* boardrev, antennas, locale */
+ value = sprom[BCM43xx_SPROM_BOARDREV];
+ bcm->sprom.boardrev = (value & 0x00FF);
+ bcm->sprom.locale = (value & 0x0F00) >> 8;
+ bcm->sprom.antennas_aphy = (value & 0x3000) >> 12;
+ bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14;
+ if (modparam_locale != -1) {
+ if (modparam_locale >= 0 && modparam_locale <= 11) {
+ bcm->sprom.locale = modparam_locale;
+ printk(KERN_WARNING PFX "Operating with modified "
+ "LocaleCode %u (%s)\n",
+ bcm->sprom.locale,
+ bcm43xx_locale_string(bcm->sprom.locale));
+ } else {
+ printk(KERN_WARNING PFX "Module parameter \"locale\" "
+ "invalid value. (0 - 11)\n");
+ }
+ }
+
+ /* pa0b* */
+ value = sprom[BCM43xx_SPROM_PA0B0];
+ bcm->sprom.pa0b0 = value;
+ value = sprom[BCM43xx_SPROM_PA0B1];
+ bcm->sprom.pa0b1 = value;
+ value = sprom[BCM43xx_SPROM_PA0B2];
+ bcm->sprom.pa0b2 = value;
+
+ /* wl0gpio* */
+ value = sprom[BCM43xx_SPROM_WL0GPIO0];
+ if (value == 0x0000)
+ value = 0xFFFF;
+ bcm->sprom.wl0gpio0 = value & 0x00FF;
+ bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8;
+ value = sprom[BCM43xx_SPROM_WL0GPIO2];
+ if (value == 0x0000)
+ value = 0xFFFF;
+ bcm->sprom.wl0gpio2 = value & 0x00FF;
+ bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8;
+
+ /* maxpower */
+ value = sprom[BCM43xx_SPROM_MAXPWR];
+ bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8;
+ bcm->sprom.maxpower_bgphy = value & 0x00FF;
+
+ /* pa1b* */
+ value = sprom[BCM43xx_SPROM_PA1B0];
+ bcm->sprom.pa1b0 = value;
+ value = sprom[BCM43xx_SPROM_PA1B1];
+ bcm->sprom.pa1b1 = value;
+ value = sprom[BCM43xx_SPROM_PA1B2];
+ bcm->sprom.pa1b2 = value;
+
+ /* idle tssi target */
+ value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT];
+ bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF;
+ bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8;
+
+ /* boardflags */
+ value = sprom[BCM43xx_SPROM_BOARDFLAGS];
+ if (value == 0xFFFF)
+ value = 0x0000;
+ bcm->sprom.boardflags = value;
+ /* boardflags workarounds */
+ if (bcm->board_vendor == PCI_VENDOR_ID_DELL &&
+ bcm->chip_id == 0x4301 &&
+ bcm->board_revision == 0x74)
+ bcm->sprom.boardflags |= BCM43xx_BFL_BTCOEXIST;
+ if (bcm->board_vendor == PCI_VENDOR_ID_APPLE &&
+ bcm->board_type == 0x4E &&
+ bcm->board_revision > 0x40)
+ bcm->sprom.boardflags |= BCM43xx_BFL_PACTRL;
+
+ /* antenna gain */
+ value = sprom[BCM43xx_SPROM_ANTENNA_GAIN];
+ if (value == 0x0000 || value == 0xFFFF)
+ value = 0x0202;
+ /* convert values to Q5.2 */
+ bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4;
+ bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4;
+
+ kfree(sprom);
+
+ return 0;
+}
+
+static int bcm43xx_geo_init(struct bcm43xx_private *bcm)
+{
+ struct ieee80211_geo *geo;
+ struct ieee80211_channel *chan;
+ int have_a = 0, have_bg = 0;
+ int i;
+ u8 channel;
+ struct bcm43xx_phyinfo *phy;
+ const char *iso_country;
+
+ geo = kzalloc(sizeof(*geo), GFP_KERNEL);
+ if (!geo)
+ return -ENOMEM;
+
+ for (i = 0; i < bcm->nr_80211_available; i++) {
+ phy = &(bcm->core_80211_ext[i].phy);
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_B:
+ case BCM43xx_PHYTYPE_G:
+ have_bg = 1;
+ break;
+ case BCM43xx_PHYTYPE_A:
+ have_a = 1;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
+
+ if (have_a) {
+ for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL;
+ channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) {
+ chan = &geo->a[i++];
+ chan->freq = bcm43xx_channel_to_freq_a(channel);
+ chan->channel = channel;
+ }
+ geo->a_channels = i;
+ }
+ if (have_bg) {
+ for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL;
+ channel <= IEEE80211_24GHZ_MAX_CHANNEL; channel++) {
+ chan = &geo->bg[i++];
+ chan->freq = bcm43xx_channel_to_freq_bg(channel);
+ chan->channel = channel;
+ }
+ geo->bg_channels = i;
+ }
+ memcpy(geo->name, iso_country, 2);
+ if (0 /*TODO: Outdoor use only */)
+ geo->name[2] = 'O';
+ else if (0 /*TODO: Indoor use only */)
+ geo->name[2] = 'I';
+ else
+ geo->name[2] = ' ';
+ geo->name[3] = '\0';
+
+ ieee80211_set_geo(bcm->ieee, geo);
+ kfree(geo);
+
+ return 0;
+}
+
+/* DummyTransmission function, as documented on
+ * http://bcm-specs.sipsolutions.net/DummyTransmission
+ */
+void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ unsigned int i, max_loop;
+ u16 value = 0;
+ u32 buffer[5] = {
+ 0x00000000,
+ 0x0000D400,
+ 0x00000000,
+ 0x00000001,
+ 0x00000000,
+ };
+
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ max_loop = 0x1E;
+ buffer[0] = 0xCC010200;
+ break;
+ case BCM43xx_PHYTYPE_B:
+ case BCM43xx_PHYTYPE_G:
+ max_loop = 0xFA;
+ buffer[0] = 0x6E840B00;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ for (i = 0; i < 5; i++)
+ bcm43xx_ram_write(bcm, i * 4, buffer[i]);
+
+ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+
+ bcm43xx_write16(bcm, 0x0568, 0x0000);
+ bcm43xx_write16(bcm, 0x07C0, 0x0000);
+ bcm43xx_write16(bcm, 0x050C, ((phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0));
+ bcm43xx_write16(bcm, 0x0508, 0x0000);
+ bcm43xx_write16(bcm, 0x050A, 0x0000);
+ bcm43xx_write16(bcm, 0x054C, 0x0000);
+ bcm43xx_write16(bcm, 0x056A, 0x0014);
+ bcm43xx_write16(bcm, 0x0568, 0x0826);
+ bcm43xx_write16(bcm, 0x0500, 0x0000);
+ bcm43xx_write16(bcm, 0x0502, 0x0030);
+
+ if (radio->version == 0x2050 && radio->revision <= 0x5)
+ bcm43xx_radio_write16(bcm, 0x0051, 0x0017);
+ for (i = 0x00; i < max_loop; i++) {
+ value = bcm43xx_read16(bcm, 0x050E);
+ if (value & 0x0080)
+ break;
+ udelay(10);
+ }
+ for (i = 0x00; i < 0x0A; i++) {
+ value = bcm43xx_read16(bcm, 0x050E);
+ if (value & 0x0400)
+ break;
+ udelay(10);
+ }
+ for (i = 0x00; i < 0x0A; i++) {
+ value = bcm43xx_read16(bcm, 0x0690);
+ if (!(value & 0x0100))
+ break;
+ udelay(10);
+ }
+ if (radio->version == 0x2050 && radio->revision <= 0x5)
+ bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
+}
+
+static void key_write(struct bcm43xx_private *bcm,
+ u8 index, u8 algorithm, const u16 *key)
+{
+ unsigned int i, basic_wep = 0;
+ u32 offset;
+ u16 value;
+
+ /* Write associated key information */
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x100 + (index * 2),
+ ((index << 4) | (algorithm & 0x0F)));
+
+ /* The first 4 WEP keys need extra love */
+ if (((algorithm == BCM43xx_SEC_ALGO_WEP) ||
+ (algorithm == BCM43xx_SEC_ALGO_WEP104)) && (index < 4))
+ basic_wep = 1;
+
+ /* Write key payload, 8 little endian words */
+ offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE);
+ for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) {
+ value = cpu_to_le16(key[i]);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+ offset + (i * 2), value);
+
+ if (!basic_wep)
+ continue;
+
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+ offset + (i * 2) + 4 * BCM43xx_SEC_KEYSIZE,
+ value);
+ }
+}
+
+static void keymac_write(struct bcm43xx_private *bcm,
+ u8 index, const u32 *addr)
+{
+ /* for keys 0-3 there is no associated mac address */
+ if (index < 4)
+ return;
+
+ index -= 4;
+ if (bcm->current_core->rev >= 5) {
+ bcm43xx_shm_write32(bcm,
+ BCM43xx_SHM_HWMAC,
+ index * 2,
+ cpu_to_be32(*addr));
+ bcm43xx_shm_write16(bcm,
+ BCM43xx_SHM_HWMAC,
+ (index * 2) + 1,
+ cpu_to_be16(*((u16 *)(addr + 1))));
+ } else {
+ if (index < 8) {
+ TODO(); /* Put them in the macaddress filter */
+ } else {
+ TODO();
+ /* Put them BCM43xx_SHM_SHARED, stating index 0x0120.
+ Keep in mind to update the count of keymacs in 0x003E as well! */
+ }
+ }
+}
+
+static int bcm43xx_key_write(struct bcm43xx_private *bcm,
+ u8 index, u8 algorithm,
+ const u8 *_key, int key_len,
+ const u8 *mac_addr)
+{
+ u8 key[BCM43xx_SEC_KEYSIZE] = { 0 };
+
+ if (index >= ARRAY_SIZE(bcm->key))
+ return -EINVAL;
+ if (key_len > ARRAY_SIZE(key))
+ return -EINVAL;
+ if (algorithm < 1 || algorithm > 5)
+ return -EINVAL;
+
+ memcpy(key, _key, key_len);
+ key_write(bcm, index, algorithm, (const u16 *)key);
+ keymac_write(bcm, index, (const u32 *)mac_addr);
+
+ bcm->key[index].algorithm = algorithm;
+
+ return 0;
+}
+
+static void bcm43xx_clear_keys(struct bcm43xx_private *bcm)
+{
+ static const u32 zero_mac[2] = { 0 };
+ unsigned int i,j, nr_keys = 54;
+ u16 offset;
+
+ if (bcm->current_core->rev < 5)
+ nr_keys = 16;
+ assert(nr_keys <= ARRAY_SIZE(bcm->key));
+
+ for (i = 0; i < nr_keys; i++) {
+ bcm->key[i].enabled = 0;
+ /* returns for i < 4 immediately */
+ keymac_write(bcm, i, zero_mac);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+ 0x100 + (i * 2), 0x0000);
+ for (j = 0; j < 8; j++) {
+ offset = bcm->security_offset + (j * 4) + (i * BCM43xx_SEC_KEYSIZE);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+ offset, 0x0000);
+ }
+ }
+ dprintk(KERN_INFO PFX "Keys cleared\n");
+}
+
+/* Lowlevel core-switch function. This is only to be used in
+ * bcm43xx_switch_core() and bcm43xx_probe_cores()
+ */
+static int _switch_core(struct bcm43xx_private *bcm, int core)
+{
+ int err;
+ int attempts = 0;
+ u32 current_core;
+
+ assert(core >= 0);
+ while (1) {
+ err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
+ (core * 0x1000) + 0x18000000);
+ if (unlikely(err))
+ goto error;
+ err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
+ &current_core);
+ if (unlikely(err))
+ goto error;
+ current_core = (current_core - 0x18000000) / 0x1000;
+ if (current_core == core)
+ break;
+
+ if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES))
+ goto error;
+ udelay(10);
+ }
+#ifdef CONFIG_BCM947XX
+ if (bcm->pci_dev->bus->number == 0)
+ bcm->current_core_offset = 0x1000 * core;
+ else
+ bcm->current_core_offset = 0;
+#endif
+
+ return 0;
+error:
+ printk(KERN_ERR PFX "Failed to switch to core %d\n", core);
+ return -ENODEV;
+}
+
+int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core)
+{
+ int err;
+
+ if (unlikely(!new_core))
+ return 0;
+ if (!new_core->available)
+ return -ENODEV;
+ if (bcm->current_core == new_core)
+ return 0;
+ err = _switch_core(bcm, new_core->index);
+ if (unlikely(err))
+ goto out;
+
+ bcm->current_core = new_core;
+ bcm->current_80211_core_idx = -1;
+ if (new_core->id == BCM43xx_COREID_80211)
+ bcm->current_80211_core_idx = (int)(new_core - &(bcm->core_80211[0]));
+
+out:
+ return err;
+}
+
+static int bcm43xx_core_enabled(struct bcm43xx_private *bcm)
+{
+ u32 value;
+
+ value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+ value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET
+ | BCM43xx_SBTMSTATELOW_REJECT;
+
+ return (value == BCM43xx_SBTMSTATELOW_CLOCK);
+}
+
+/* disable current core */
+static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags)
+{
+ u32 sbtmstatelow;
+ u32 sbtmstatehigh;
+ int i;
+
+ /* fetch sbtmstatelow from core information registers */
+ sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+
+ /* core is already in reset */
+ if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET)
+ goto out;
+
+ if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) {
+ sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
+ BCM43xx_SBTMSTATELOW_REJECT;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+
+ for (i = 0; i < 1000; i++) {
+ sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+ if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) {
+ i = -1;
+ break;
+ }
+ udelay(10);
+ }
+ if (i != -1) {
+ printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n");
+ return -EBUSY;
+ }
+
+ for (i = 0; i < 1000; i++) {
+ sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+ if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) {
+ i = -1;
+ break;
+ }
+ udelay(10);
+ }
+ if (i != -1) {
+ printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n");
+ return -EBUSY;
+ }
+
+ sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
+ BCM43xx_SBTMSTATELOW_REJECT |
+ BCM43xx_SBTMSTATELOW_RESET |
+ BCM43xx_SBTMSTATELOW_CLOCK |
+ core_flags;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+ udelay(10);
+ }
+
+ sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET |
+ BCM43xx_SBTMSTATELOW_REJECT |
+ core_flags;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+
+out:
+ bcm->current_core->enabled = 0;
+
+ return 0;
+}
+
+/* enable (reset) current core */
+static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags)
+{
+ u32 sbtmstatelow;
+ u32 sbtmstatehigh;
+ u32 sbimstate;
+ int err;
+
+ err = bcm43xx_core_disable(bcm, core_flags);
+ if (err)
+ goto out;
+
+ sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
+ BCM43xx_SBTMSTATELOW_RESET |
+ BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
+ core_flags;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+ udelay(1);
+
+ sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+ if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) {
+ sbtmstatehigh = 0x00000000;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh);
+ }
+
+ sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE);
+ if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) {
+ sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT);
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate);
+ }
+
+ sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
+ BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
+ core_flags;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+ udelay(1);
+
+ sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+ udelay(1);
+
+ bcm->current_core->enabled = 1;
+ assert(err == 0);
+out:
+ return err;
+}
+
+/* http://bcm-specs.sipsolutions.net/80211CoreReset */
+void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
+{
+ u32 flags = 0x00040000;
+
+ if ((bcm43xx_core_enabled(bcm)) &&
+ !bcm43xx_using_pio(bcm)) {
+//FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here?
+#ifndef CONFIG_BCM947XX
+ /* reset all used DMA controllers. */
+ bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
+ bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA2_BASE);
+ bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA3_BASE);
+ bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
+ bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
+ if (bcm->current_core->rev < 5)
+ bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
+#endif
+ }
+ if (bcm->shutting_down) {
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+ & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
+ } else {
+ if (connect_phy)
+ flags |= 0x20000000;
+ bcm43xx_phy_connect(bcm, connect_phy);
+ bcm43xx_core_enable(bcm, flags);
+ bcm43xx_write16(bcm, 0x03E6, 0x0000);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+ | BCM43xx_SBF_400);
+ }
+}
+
+static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm)
+{
+ bcm43xx_radio_turn_off(bcm);
+ bcm43xx_write16(bcm, 0x03E6, 0x00F4);
+ bcm43xx_core_disable(bcm, 0);
+}
+
+/* Mark the current 80211 core inactive.
+ * "active_80211_core" is the other 80211 core, which is used.
+ */
+static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm,
+ struct bcm43xx_coreinfo *active_80211_core)
+{
+ u32 sbtmstatelow;
+ struct bcm43xx_coreinfo *old_core;
+ int err = 0;
+
+ bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+ bcm43xx_radio_turn_off(bcm);
+ sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+ sbtmstatelow &= ~0x200a0000;
+ sbtmstatelow |= 0xa0000;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+ udelay(1);
+ sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+ sbtmstatelow &= ~0xa0000;
+ sbtmstatelow |= 0x80000;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+ udelay(1);
+
+ if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G) {
+ old_core = bcm->current_core;
+ err = bcm43xx_switch_core(bcm, active_80211_core);
+ if (err)
+ goto out;
+ sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+ sbtmstatelow &= ~0x20000000;
+ sbtmstatelow |= 0x20000000;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+ err = bcm43xx_switch_core(bcm, old_core);
+ }
+
+out:
+ return err;
+}
+
+static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
+{
+ u32 v0, v1;
+ u16 tmp;
+ struct bcm43xx_xmitstatus stat;
+
+ while (1) {
+ v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
+ if (!v0)
+ break;
+ v1 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
+
+ stat.cookie = (v0 >> 16) & 0x0000FFFF;
+ tmp = (u16)((v0 & 0xFFF0) | ((v0 & 0xF) >> 1));
+ stat.flags = tmp & 0xFF;
+ stat.cnt1 = (tmp & 0x0F00) >> 8;
+ stat.cnt2 = (tmp & 0xF000) >> 12;
+ stat.seq = (u16)(v1 & 0xFFFF);
+ stat.unknown = (u16)((v1 >> 16) & 0xFF);
+
+ bcm43xx_debugfs_log_txstat(bcm, &stat);
+
+ if (stat.flags & BCM43xx_TXSTAT_FLAG_IGNORE)
+ continue;
+ if (!(stat.flags & BCM43xx_TXSTAT_FLAG_ACK)) {
+ //TODO: packet was not acked (was lost)
+ }
+ //TODO: There are more (unknown) flags to test. see bcm43xx_main.h
+
+ if (bcm43xx_using_pio(bcm))
+ bcm43xx_pio_handle_xmitstatus(bcm, &stat);
+ else
+ bcm43xx_dma_handle_xmitstatus(bcm, &stat);
+ }
+}
+
+static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm)
+{
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
+ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4));
+ assert(bcm->noisecalc.core_at_start == bcm->current_core);
+ assert(bcm->noisecalc.channel_at_start == bcm43xx_current_radio(bcm)->channel);
+}
+
+static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm)
+{
+ /* Top half of Link Quality calculation. */
+
+ if (bcm->noisecalc.calculation_running)
+ return;
+ bcm->noisecalc.core_at_start = bcm->current_core;
+ bcm->noisecalc.channel_at_start = bcm43xx_current_radio(bcm)->channel;
+ bcm->noisecalc.calculation_running = 1;
+ bcm->noisecalc.nr_samples = 0;
+
+ bcm43xx_generate_noise_sample(bcm);
+}
+
+static void handle_irq_noise(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 tmp;
+ u8 noise[4];
+ u8 i, j;
+ s32 average;
+
+ /* Bottom half of Link Quality calculation. */
+
+ assert(bcm->noisecalc.calculation_running);
+ if (bcm->noisecalc.core_at_start != bcm->current_core ||
+ bcm->noisecalc.channel_at_start != radio->channel)
+ goto drop_calculation;
+ tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408);
+ noise[0] = (tmp & 0x00FF);
+ noise[1] = (tmp & 0xFF00) >> 8;
+ tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40A);
+ noise[2] = (tmp & 0x00FF);
+ noise[3] = (tmp & 0xFF00) >> 8;
+ if (noise[0] == 0x7F || noise[1] == 0x7F ||
+ noise[2] == 0x7F || noise[3] == 0x7F)
+ goto generate_new;
+
+ /* Get the noise samples. */
+ assert(bcm->noisecalc.nr_samples <= 8);
+ i = bcm->noisecalc.nr_samples;
+ noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+ noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+ noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+ noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+ bcm->noisecalc.samples[i][0] = radio->nrssi_lt[noise[0]];
+ bcm->noisecalc.samples[i][1] = radio->nrssi_lt[noise[1]];
+ bcm->noisecalc.samples[i][2] = radio->nrssi_lt[noise[2]];
+ bcm->noisecalc.samples[i][3] = radio->nrssi_lt[noise[3]];
+ bcm->noisecalc.nr_samples++;
+ if (bcm->noisecalc.nr_samples == 8) {
+ /* Calculate the Link Quality by the noise samples. */
+ average = 0;
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 4; j++)
+ average += bcm->noisecalc.samples[i][j];
+ }
+ average /= (8 * 4);
+ average *= 125;
+ average += 64;
+ average /= 128;
+
+ tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C);
+ tmp = (tmp / 128) & 0x1F;
+ if (tmp >= 8)
+ average += 2;
+ else
+ average -= 25;
+ if (tmp == 8)
+ average -= 72;
+ else
+ average -= 48;
+
+/* FIXME: This is wrong, but people want fancy stats. well... */
+bcm->stats.noise = average;
+ if (average > -65)
+ bcm->stats.link_quality = 0;
+ else if (average > -75)
+ bcm->stats.link_quality = 1;
+ else if (average > -85)
+ bcm->stats.link_quality = 2;
+ else
+ bcm->stats.link_quality = 3;
+// dprintk(KERN_INFO PFX "Link Quality: %u (avg was %d)\n", bcm->stats.link_quality, average);
+drop_calculation:
+ bcm->noisecalc.calculation_running = 0;
+ return;
+ }
+generate_new:
+ bcm43xx_generate_noise_sample(bcm);
+}
+
+static void handle_irq_ps(struct bcm43xx_private *bcm)
+{
+ if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
+ ///TODO: PS TBTT
+ } else {
+ if (1/*FIXME: the last PSpoll frame was sent successfully */)
+ bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+ }
+ if (bcm->ieee->iw_mode == IW_MODE_ADHOC)
+ bcm->reg124_set_0x4 = 1;
+ //FIXME else set to false?
+}
+
+static void handle_irq_reg124(struct bcm43xx_private *bcm)
+{
+ if (!bcm->reg124_set_0x4)
+ return;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
+ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD)
+ | 0x4);
+ //FIXME: reset reg124_set_0x4 to false?
+}
+
+static void handle_irq_pmq(struct bcm43xx_private *bcm)
+{
+ u32 tmp;
+
+ //TODO: AP mode.
+
+ while (1) {
+ tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_PS_STATUS);
+ if (!(tmp & 0x00000008))
+ break;
+ }
+ /* 16bit write is odd, but correct. */
+ bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002);
+}
+
+static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm,
+ u16 ram_offset, u16 shm_size_offset)
+{
+ u32 value;
+ u16 size = 0;
+
+ /* Timestamp. */
+ //FIXME: assumption: The chip sets the timestamp
+ value = 0;
+ bcm43xx_ram_write(bcm, ram_offset++, value);
+ bcm43xx_ram_write(bcm, ram_offset++, value);
+ size += 8;
+
+ /* Beacon Interval / Capability Information */
+ value = 0x0000;//FIXME: Which interval?
+ value |= (1 << 0) << 16; /* ESS */
+ value |= (1 << 2) << 16; /* CF Pollable */ //FIXME?
+ value |= (1 << 3) << 16; /* CF Poll Request */ //FIXME?
+ if (!bcm->ieee->open_wep)
+ value |= (1 << 4) << 16; /* Privacy */
+ bcm43xx_ram_write(bcm, ram_offset++, value);
+ size += 4;
+
+ /* SSID */
+ //TODO
+
+ /* FH Parameter Set */
+ //TODO
+
+ /* DS Parameter Set */
+ //TODO
+
+ /* CF Parameter Set */
+ //TODO
+
+ /* TIM */
+ //TODO
+
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size);
+}
+
+static void handle_irq_beacon(struct bcm43xx_private *bcm)
+{
+ u32 status;
+
+ bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON;
+ status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD);
+
+ if ((status & 0x1) && (status & 0x2)) {
+ /* ACK beacon IRQ. */
+ bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON,
+ BCM43xx_IRQ_BEACON);
+ bcm->irq_savedstate |= BCM43xx_IRQ_BEACON;
+ return;
+ }
+ if (!(status & 0x1)) {
+ bcm43xx_generate_beacon_template(bcm, 0x68, 0x18);
+ status |= 0x1;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
+ }
+ if (!(status & 0x2)) {
+ bcm43xx_generate_beacon_template(bcm, 0x468, 0x1A);
+ status |= 0x2;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
+ }
+}
+
+/* Interrupt handler bottom-half */
+static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
+{
+ u32 reason;
+ u32 dma_reason[4];
+ int activity = 0;
+ unsigned long flags;
+
+#ifdef CONFIG_BCM43XX_DEBUG
+ u32 _handled = 0x00000000;
+# define bcmirq_handled(irq) do { _handled |= (irq); } while (0)
+#else
+# define bcmirq_handled(irq) do { /* nothing */ } while (0)
+#endif /* CONFIG_BCM43XX_DEBUG*/
+
+ bcm43xx_lock_mmio(bcm, flags);
+ reason = bcm->irq_reason;
+ dma_reason[0] = bcm->dma_reason[0];
+ dma_reason[1] = bcm->dma_reason[1];
+ dma_reason[2] = bcm->dma_reason[2];
+ dma_reason[3] = bcm->dma_reason[3];
+
+ if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) {
+ /* TX error. We get this when Template Ram is written in wrong endianess
+ * in dummy_tx(). We also get this if something is wrong with the TX header
+ * on DMA or PIO queues.
+ * Maybe we get this in other error conditions, too.
+ */
+ printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n");
+ bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR);
+ }
+ if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_FATALMASK) |
+ (dma_reason[1] & BCM43xx_DMAIRQ_FATALMASK) |
+ (dma_reason[2] & BCM43xx_DMAIRQ_FATALMASK) |
+ (dma_reason[3] & BCM43xx_DMAIRQ_FATALMASK))) {
+ printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: "
+ "0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
+ dma_reason[0], dma_reason[1],
+ dma_reason[2], dma_reason[3]);
+ bcm43xx_controller_restart(bcm, "DMA error");
+ bcm43xx_unlock_mmio(bcm, flags);
+ return;
+ }
+ if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) |
+ (dma_reason[1] & BCM43xx_DMAIRQ_NONFATALMASK) |
+ (dma_reason[2] & BCM43xx_DMAIRQ_NONFATALMASK) |
+ (dma_reason[3] & BCM43xx_DMAIRQ_NONFATALMASK))) {
+ printkl(KERN_ERR PFX "DMA error: "
+ "0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
+ dma_reason[0], dma_reason[1],
+ dma_reason[2], dma_reason[3]);
+ }
+
+ if (reason & BCM43xx_IRQ_PS) {
+ handle_irq_ps(bcm);
+ bcmirq_handled(BCM43xx_IRQ_PS);
+ }
+
+ if (reason & BCM43xx_IRQ_REG124) {
+ handle_irq_reg124(bcm);
+ bcmirq_handled(BCM43xx_IRQ_REG124);
+ }
+
+ if (reason & BCM43xx_IRQ_BEACON) {
+ if (bcm->ieee->iw_mode == IW_MODE_MASTER)
+ handle_irq_beacon(bcm);
+ bcmirq_handled(BCM43xx_IRQ_BEACON);
+ }
+
+ if (reason & BCM43xx_IRQ_PMQ) {
+ handle_irq_pmq(bcm);
+ bcmirq_handled(BCM43xx_IRQ_PMQ);
+ }
+
+ if (reason & BCM43xx_IRQ_SCAN) {
+ /*TODO*/
+ //bcmirq_handled(BCM43xx_IRQ_SCAN);
+ }
+
+ if (reason & BCM43xx_IRQ_NOISE) {
+ handle_irq_noise(bcm);
+ bcmirq_handled(BCM43xx_IRQ_NOISE);
+ }
+
+ /* Check the DMA reason registers for received data. */
+ assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE));
+ assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE));
+ if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) {
+ if (bcm43xx_using_pio(bcm))
+ bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0);
+ else
+ bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0);
+ /* We intentionally don't set "activity" to 1, here. */
+ }
+ if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) {
+ if (bcm43xx_using_pio(bcm))
+ bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3);
+ else
+ bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring1);
+ activity = 1;
+ }
+ bcmirq_handled(BCM43xx_IRQ_RX);
+
+ if (reason & BCM43xx_IRQ_XMIT_STATUS) {
+ handle_irq_transmit_status(bcm);
+ activity = 1;
+ //TODO: In AP mode, this also causes sending of powersave responses.
+ bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS);
+ }
+
+ /* IRQ_PIO_WORKAROUND is handled in the top-half. */
+ bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND);
+#ifdef CONFIG_BCM43XX_DEBUG
+ if (unlikely(reason & ~_handled)) {
+ printkl(KERN_WARNING PFX
+ "Unhandled IRQ! Reason: 0x%08x, Unhandled: 0x%08x, "
+ "DMA: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+ reason, (reason & ~_handled),
+ dma_reason[0], dma_reason[1],
+ dma_reason[2], dma_reason[3]);
+ }
+#endif
+#undef bcmirq_handled
+
+ if (!modparam_noleds)
+ bcm43xx_leds_update(bcm, activity);
+ bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+ bcm43xx_unlock_mmio(bcm, flags);
+}
+
+static void pio_irq_workaround(struct bcm43xx_private *bcm,
+ u16 base, int queueidx)
+{
+ u16 rxctl;
+
+ rxctl = bcm43xx_read16(bcm, base + BCM43xx_PIO_RXCTL);
+ if (rxctl & BCM43xx_PIO_RXCTL_DATAAVAILABLE)
+ bcm->dma_reason[queueidx] |= BCM43xx_DMAIRQ_RX_DONE;
+ else
+ bcm->dma_reason[queueidx] &= ~BCM43xx_DMAIRQ_RX_DONE;
+}
+
+static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason)
+{
+ if (bcm43xx_using_pio(bcm) &&
+ (bcm->current_core->rev < 3) &&
+ (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) {
+ /* Apply a PIO specific workaround to the dma_reasons */
+ pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0);
+ pio_irq_workaround(bcm, BCM43xx_MMIO_PIO2_BASE, 1);
+ pio_irq_workaround(bcm, BCM43xx_MMIO_PIO3_BASE, 2);
+ pio_irq_workaround(bcm, BCM43xx_MMIO_PIO4_BASE, 3);
+ }
+
+ bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason);
+
+ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON,
+ bcm->dma_reason[0]);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON,
+ bcm->dma_reason[1]);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON,
+ bcm->dma_reason[2]);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON,
+ bcm->dma_reason[3]);
+}
+
+/* Interrupt handler top-half */
+static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ irqreturn_t ret = IRQ_HANDLED;
+ struct bcm43xx_private *bcm = dev_id;
+ u32 reason;
+
+ if (!bcm)
+ return IRQ_NONE;
+
+ spin_lock(&bcm->_lock);
+
+ reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+ if (reason == 0xffffffff) {
+ /* irq not for us (shared irq) */
+ ret = IRQ_NONE;
+ goto out;
+ }
+ reason &= bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
+ if (!reason)
+ goto out;
+
+ bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON)
+ & 0x0001dc00;
+ bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON)
+ & 0x0000dc00;
+ bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON)
+ & 0x0000dc00;
+ bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON)
+ & 0x0001dc00;
+
+ bcm43xx_interrupt_ack(bcm, reason);
+
+ /* Only accept IRQs, if we are initialized properly.
+ * This avoids an RX race while initializing.
+ * We should probably not enable IRQs before we are initialized
+ * completely, but some careful work is needed to fix this. I think it
+ * is best to stay with this cheap workaround for now... .
+ */
+ if (likely(bcm->initialized)) {
+ /* disable all IRQs. They are enabled again in the bottom half. */
+ bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+ /* save the reason code and call our bottom half. */
+ bcm->irq_reason = reason;
+ tasklet_schedule(&bcm->isr_tasklet);
+ }
+
+out:
+ mmiowb();
+ spin_unlock(&bcm->_lock);
+
+ return ret;
+}
+
+static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force)
+{
+ if (bcm->firmware_norelease && !force)
+ return; /* Suspending or controller reset. */
+ release_firmware(bcm->ucode);
+ bcm->ucode = NULL;
+ release_firmware(bcm->pcm);
+ bcm->pcm = NULL;
+ release_firmware(bcm->initvals0);
+ bcm->initvals0 = NULL;
+ release_firmware(bcm->initvals1);
+ bcm->initvals1 = NULL;
+}
+
+static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u8 rev = bcm->current_core->rev;
+ int err = 0;
+ int nr;
+ char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
+
+ if (!bcm->ucode) {
+ snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
+ (rev >= 5 ? 5 : rev),
+ modparam_fwpostfix);
+ err = request_firmware(&bcm->ucode, buf, &bcm->pci_dev->dev);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Error: Microcode \"%s\" not available or load failed.\n",
+ buf);
+ goto error;
+ }
+ }
+
+ if (!bcm->pcm) {
+ snprintf(buf, ARRAY_SIZE(buf),
+ "bcm43xx_pcm%d%s.fw",
+ (rev < 5 ? 4 : 5),
+ modparam_fwpostfix);
+ err = request_firmware(&bcm->pcm, buf, &bcm->pci_dev->dev);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Error: PCM \"%s\" not available or load failed.\n",
+ buf);
+ goto error;
+ }
+ }
+
+ if (!bcm->initvals0) {
+ if (rev == 2 || rev == 4) {
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ nr = 3;
+ break;
+ case BCM43xx_PHYTYPE_B:
+ case BCM43xx_PHYTYPE_G:
+ nr = 1;
+ break;
+ default:
+ goto err_noinitval;
+ }
+
+ } else if (rev >= 5) {
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ nr = 7;
+ break;
+ case BCM43xx_PHYTYPE_B:
+ case BCM43xx_PHYTYPE_G:
+ nr = 5;
+ break;
+ default:
+ goto err_noinitval;
+ }
+ } else
+ goto err_noinitval;
+ snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
+ nr, modparam_fwpostfix);
+
+ err = request_firmware(&bcm->initvals0, buf, &bcm->pci_dev->dev);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Error: InitVals \"%s\" not available or load failed.\n",
+ buf);
+ goto error;
+ }
+ if (bcm->initvals0->size % sizeof(struct bcm43xx_initval)) {
+ printk(KERN_ERR PFX "InitVals fileformat error.\n");
+ goto error;
+ }
+ }
+
+ if (!bcm->initvals1) {
+ if (rev >= 5) {
+ u32 sbtmstatehigh;
+
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+ if (sbtmstatehigh & 0x00010000)
+ nr = 9;
+ else
+ nr = 10;
+ break;
+ case BCM43xx_PHYTYPE_B:
+ case BCM43xx_PHYTYPE_G:
+ nr = 6;
+ break;
+ default:
+ goto err_noinitval;
+ }
+ snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
+ nr, modparam_fwpostfix);
+
+ err = request_firmware(&bcm->initvals1, buf, &bcm->pci_dev->dev);
+ if (err) {
+ printk(KERN_ERR PFX
+ "Error: InitVals \"%s\" not available or load failed.\n",
+ buf);
+ goto error;
+ }
+ if (bcm->initvals1->size % sizeof(struct bcm43xx_initval)) {
+ printk(KERN_ERR PFX "InitVals fileformat error.\n");
+ goto error;
+ }
+ }
+ }
+
+out:
+ return err;
+error:
+ bcm43xx_release_firmware(bcm, 1);
+ goto out;
+err_noinitval:
+ printk(KERN_ERR PFX "Error: No InitVals available!\n");
+ err = -ENOENT;
+ goto error;
+}
+
+static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
+{
+ const u32 *data;
+ unsigned int i, len;
+
+ /* Upload Microcode. */
+ data = (u32 *)(bcm->ucode->data);
+ len = bcm->ucode->size / sizeof(u32);
+ bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
+ for (i = 0; i < len; i++) {
+ bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
+ be32_to_cpu(data[i]));
+ udelay(10);
+ }
+
+ /* Upload PCM data. */
+ data = (u32 *)(bcm->pcm->data);
+ len = bcm->pcm->size / sizeof(u32);
+ bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
+ bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb);
+ for (i = 0; i < len; i++) {
+ bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
+ be32_to_cpu(data[i]));
+ udelay(10);
+ }
+}
+
+static int bcm43xx_write_initvals(struct bcm43xx_private *bcm,
+ const struct bcm43xx_initval *data,
+ const unsigned int len)
+{
+ u16 offset, size;
+ u32 value;
+ unsigned int i;
+
+ for (i = 0; i < len; i++) {
+ offset = be16_to_cpu(data[i].offset);
+ size = be16_to_cpu(data[i].size);
+ value = be32_to_cpu(data[i].value);
+
+ if (unlikely(offset >= 0x1000))
+ goto err_format;
+ if (size == 2) {
+ if (unlikely(value & 0xFFFF0000))
+ goto err_format;
+ bcm43xx_write16(bcm, offset, (u16)value);
+ } else if (size == 4) {
+ bcm43xx_write32(bcm, offset, value);
+ } else
+ goto err_format;
+ }
+
+ return 0;
+
+err_format:
+ printk(KERN_ERR PFX "InitVals (bcm43xx_initvalXX.fw) file-format error. "
+ "Please fix your bcm43xx firmware files.\n");
+ return -EPROTO;
+}
+
+static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
+{
+ int err;
+
+ err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data,
+ bcm->initvals0->size / sizeof(struct bcm43xx_initval));
+ if (err)
+ goto out;
+ if (bcm->initvals1) {
+ err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data,
+ bcm->initvals1->size / sizeof(struct bcm43xx_initval));
+ if (err)
+ goto out;
+ }
+out:
+ return err;
+}
+
+static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
+{
+ int res;
+ unsigned int i;
+ u32 data;
+
+ bcm->irq = bcm->pci_dev->irq;
+#ifdef CONFIG_BCM947XX
+ if (bcm->pci_dev->bus->number == 0) {
+ struct pci_dev *d = NULL;
+ /* FIXME: we will probably need more device IDs here... */
+ d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL);
+ if (d != NULL) {
+ bcm->irq = d->irq;
+ }
+ }
+#endif
+ res = request_irq(bcm->irq, bcm43xx_interrupt_handler,
+ SA_SHIRQ, KBUILD_MODNAME, bcm);
+ if (res) {
+ printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
+ return -ENODEV;
+ }
+ bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
+ i = 0;
+ while (1) {
+ data = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+ if (data == BCM43xx_IRQ_READY)
+ break;
+ i++;
+ if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
+ printk(KERN_ERR PFX "Card IRQ register not responding. "
+ "Giving up.\n");
+ free_irq(bcm->irq, bcm);
+ return -ENODEV;
+ }
+ udelay(10);
+ }
+ // dummy read
+ bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+
+ return 0;
+}
+
+/* Switch to the core used to write the GPIO register.
+ * This is either the ChipCommon, or the PCI core.
+ */
+static int switch_to_gpio_core(struct bcm43xx_private *bcm)
+{
+ int err;
+
+ /* Where to find the GPIO register depends on the chipset.
+ * If it has a ChipCommon, its register at offset 0x6c is the GPIO
+ * control register. Otherwise the register at offset 0x6c in the
+ * PCI core is the GPIO control register.
+ */
+ err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+ if (err == -ENODEV) {
+ err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+ if (unlikely(err == -ENODEV)) {
+ printk(KERN_ERR PFX "gpio error: "
+ "Neither ChipCommon nor PCI core available!\n");
+ }
+ }
+
+ return err;
+}
+
+/* Initialize the GPIOs
+ * http://bcm-specs.sipsolutions.net/GPIO
+ */
+static int bcm43xx_gpio_init(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_coreinfo *old_core;
+ int err;
+ u32 mask, set;
+
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+ & 0xFFFF3FFF);
+
+ bcm43xx_leds_switch_all(bcm, 0);
+ bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
+ bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F);
+
+ mask = 0x0000001F;
+ set = 0x0000000F;
+ if (bcm->chip_id == 0x4301) {
+ mask |= 0x0060;
+ set |= 0x0060;
+ }
+ if (0 /* FIXME: conditional unknown */) {
+ bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
+ bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
+ | 0x0100);
+ mask |= 0x0180;
+ set |= 0x0180;
+ }
+ if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
+ bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
+ bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
+ | 0x0200);
+ mask |= 0x0200;
+ set |= 0x0200;
+ }
+ if (bcm->current_core->rev >= 2)
+ mask |= 0x0010; /* FIXME: This is redundant. */
+
+ old_core = bcm->current_core;
+ err = switch_to_gpio_core(bcm);
+ if (err)
+ goto out;
+ bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL,
+ (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | set);
+ err = bcm43xx_switch_core(bcm, old_core);
+out:
+ return err;
+}
+
+/* Turn off all GPIO stuff. Call this on module unload, for example. */
+static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_coreinfo *old_core;
+ int err;
+
+ old_core = bcm->current_core;
+ err = switch_to_gpio_core(bcm);
+ if (err)
+ return err;
+ bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000);
+ err = bcm43xx_switch_core(bcm, old_core);
+ assert(err == 0);
+
+ return 0;
+}
+
+/* http://bcm-specs.sipsolutions.net/EnableMac */
+void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
+{
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+ | BCM43xx_SBF_MAC_ENABLED);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
+ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+ bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+ bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+}
+
+/* http://bcm-specs.sipsolutions.net/SuspendMAC */
+void bcm43xx_mac_suspend(struct bcm43xx_private *bcm)
+{
+ int i;
+ u32 tmp;
+
+ bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+ & ~BCM43xx_SBF_MAC_ENABLED);
+ bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+ for (i = 100000; i; i--) {
+ tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+ if (tmp & BCM43xx_IRQ_READY)
+ return;
+ udelay(10);
+ }
+ printkl(KERN_ERR PFX "MAC suspend failed\n");
+}
+
+void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
+ int iw_mode)
+{
+ unsigned long flags;
+ struct net_device *net_dev = bcm->net_dev;
+ u32 status;
+ u16 value;
+
+ spin_lock_irqsave(&bcm->ieee->lock, flags);
+ bcm->ieee->iw_mode = iw_mode;
+ spin_unlock_irqrestore(&bcm->ieee->lock, flags);
+ if (iw_mode == IW_MODE_MONITOR)
+ net_dev->type = ARPHRD_IEEE80211;
+ else
+ net_dev->type = ARPHRD_ETHER;
+
+ status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+ /* Reset status to infrastructured mode */
+ status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR);
+ status &= ~BCM43xx_SBF_MODE_PROMISC;
+ status |= BCM43xx_SBF_MODE_NOTADHOC;
+
+/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */
+status |= BCM43xx_SBF_MODE_PROMISC;
+
+ switch (iw_mode) {
+ case IW_MODE_MONITOR:
+ status |= BCM43xx_SBF_MODE_MONITOR;
+ status |= BCM43xx_SBF_MODE_PROMISC;
+ break;
+ case IW_MODE_ADHOC:
+ status &= ~BCM43xx_SBF_MODE_NOTADHOC;
+ break;
+ case IW_MODE_MASTER:
+ status |= BCM43xx_SBF_MODE_AP;
+ break;
+ case IW_MODE_SECOND:
+ case IW_MODE_REPEAT:
+ TODO(); /* TODO */
+ break;
+ case IW_MODE_INFRA:
+ /* nothing to be done here... */
+ break;
+ default:
+ dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode);
+ }
+ if (net_dev->flags & IFF_PROMISC)
+ status |= BCM43xx_SBF_MODE_PROMISC;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+
+ value = 0x0002;
+ if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) {
+ if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3)
+ value = 0x0064;
+ else
+ value = 0x0032;
+ }
+ bcm43xx_write16(bcm, 0x0612, value);
+}
+
+/* This is the opposite of bcm43xx_chip_init() */
+static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm)
+{
+ bcm43xx_radio_turn_off(bcm);
+ if (!modparam_noleds)
+ bcm43xx_leds_exit(bcm);
+ bcm43xx_gpio_cleanup(bcm);
+ free_irq(bcm->irq, bcm);
+ bcm43xx_release_firmware(bcm, 0);
+}
+
+/* Initialize the chip
+ * http://bcm-specs.sipsolutions.net/ChipInit
+ */
+static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ int err;
+ int tmp;
+ u32 value32;
+ u16 value16;
+
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+ BCM43xx_SBF_CORE_READY
+ | BCM43xx_SBF_400);
+
+ err = bcm43xx_request_firmware(bcm);
+ if (err)
+ goto out;
+ bcm43xx_upload_microcode(bcm);
+
+ err = bcm43xx_initialize_irq(bcm);
+ if (err)
+ goto err_release_fw;
+
+ err = bcm43xx_gpio_init(bcm);
+ if (err)
+ goto err_free_irq;
+
+ err = bcm43xx_upload_initvals(bcm);
+ if (err)
+ goto err_gpio_cleanup;
+ bcm43xx_radio_turn_on(bcm);
+
+ bcm43xx_write16(bcm, 0x03E6, 0x0000);
+ err = bcm43xx_phy_init(bcm);
+ if (err)
+ goto err_radio_off;
+
+ /* Select initial Interference Mitigation. */
+ tmp = radio->interfmode;
+ radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
+ bcm43xx_radio_set_interference_mitigation(bcm, tmp);
+
+ bcm43xx_phy_set_antenna_diversity(bcm);
+ bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT);
+ if (phy->type == BCM43xx_PHYTYPE_B) {
+ value16 = bcm43xx_read16(bcm, 0x005E);
+ value16 |= 0x0004;
+ bcm43xx_write16(bcm, 0x005E, value16);
+ }
+ bcm43xx_write32(bcm, 0x0100, 0x01000000);
+ if (bcm->current_core->rev < 5)
+ bcm43xx_write32(bcm, 0x010C, 0x01000000);
+
+ value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+ value32 &= ~ BCM43xx_SBF_MODE_NOTADHOC;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
+ value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+ value32 |= BCM43xx_SBF_MODE_NOTADHOC;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
+
+ value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+ value32 |= 0x100000;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
+
+ if (bcm43xx_using_pio(bcm)) {
+ bcm43xx_write32(bcm, 0x0210, 0x00000100);
+ bcm43xx_write32(bcm, 0x0230, 0x00000100);
+ bcm43xx_write32(bcm, 0x0250, 0x00000100);
+ bcm43xx_write32(bcm, 0x0270, 0x00000100);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0034, 0x0000);
+ }
+
+ /* Probe Response Timeout value */
+ /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000);
+
+ /* Initially set the wireless operation mode. */
+ bcm43xx_set_iwmode(bcm, bcm->ieee->iw_mode);
+
+ if (bcm->current_core->rev < 3) {
+ bcm43xx_write16(bcm, 0x060E, 0x0000);
+ bcm43xx_write16(bcm, 0x0610, 0x8000);
+ bcm43xx_write16(bcm, 0x0604, 0x0000);
+ bcm43xx_write16(bcm, 0x0606, 0x0200);
+ } else {
+ bcm43xx_write32(bcm, 0x0188, 0x80000000);
+ bcm43xx_write32(bcm, 0x018C, 0x02000000);
+ }
+ bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0001DC00);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0000DC00);
+ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0001DC00);
+
+ value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+ value32 |= 0x00100000;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32);
+
+ bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm));
+
+ assert(err == 0);
+ dprintk(KERN_INFO PFX "Chip initialized\n");
+out:
+ return err;
+
+err_radio_off:
+ bcm43xx_radio_turn_off(bcm);
+err_gpio_cleanup:
+ bcm43xx_gpio_cleanup(bcm);
+err_free_irq:
+ free_irq(bcm->irq, bcm);
+err_release_fw:
+ bcm43xx_release_firmware(bcm, 1);
+ goto out;
+}
+
+/* Validate chip access
+ * http://bcm-specs.sipsolutions.net/ValidateChipAccess */
+static int bcm43xx_validate_chip(struct bcm43xx_private *bcm)
+{
+ u32 value;
+ u32 shm_backup;
+
+ shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000);
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA);
+ if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA)
+ goto error;
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55);
+ if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55)
+ goto error;
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup);
+
+ value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+ if ((value | 0x80000000) != 0x80000400)
+ goto error;
+
+ value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+ if (value != 0x00000000)
+ goto error;
+
+ return 0;
+error:
+ printk(KERN_ERR PFX "Failed to validate the chipaccess\n");
+ return -ENODEV;
+}
+
+static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy)
+{
+ /* Initialize a "phyinfo" structure. The structure is already
+ * zeroed out.
+ */
+ phy->antenna_diversity = 0xFFFF;
+ phy->savedpctlreg = 0xFFFF;
+ phy->minlowsig[0] = 0xFFFF;
+ phy->minlowsig[1] = 0xFFFF;
+ spin_lock_init(&phy->lock);
+}
+
+static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio)
+{
+ /* Initialize a "radioinfo" structure. The structure is already
+ * zeroed out.
+ */
+ radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
+ radio->channel = 0xFF;
+ radio->initial_channel = 0xFF;
+ radio->lofcal = 0xFFFF;
+ radio->initval = 0xFFFF;
+ radio->nrssi[0] = -1000;
+ radio->nrssi[1] = -1000;
+}
+
+static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
+{
+ int err, i;
+ int current_core;
+ u32 core_vendor, core_id, core_rev;
+ u32 sb_id_hi, chip_id_32 = 0;
+ u16 pci_device, chip_id_16;
+ u8 core_count;
+
+ memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo));
+ memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo));
+ memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo)
+ * BCM43xx_MAX_80211_CORES);
+ memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
+ * BCM43xx_MAX_80211_CORES);
+ bcm->current_80211_core_idx = -1;
+ bcm->nr_80211_available = 0;
+ bcm->current_core = NULL;
+ bcm->active_80211_core = NULL;
+
+ /* map core 0 */
+ err = _switch_core(bcm, 0);
+ if (err)
+ goto out;
+
+ /* fetch sb_id_hi from core information registers */
+ sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
+
+ core_id = (sb_id_hi & 0xFFF0) >> 4;
+ core_rev = (sb_id_hi & 0xF);
+ core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
+
+ /* if present, chipcommon is always core 0; read the chipid from it */
+ if (core_id == BCM43xx_COREID_CHIPCOMMON) {
+ chip_id_32 = bcm43xx_read32(bcm, 0);
+ chip_id_16 = chip_id_32 & 0xFFFF;
+ bcm->core_chipcommon.available = 1;
+ bcm->core_chipcommon.id = core_id;
+ bcm->core_chipcommon.rev = core_rev;
+ bcm->core_chipcommon.index = 0;
+ /* While we are at it, also read the capabilities. */
+ bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES);
+ } else {
+ /* without a chipCommon, use a hard coded table. */
+ pci_device = bcm->pci_dev->device;
+ if (pci_device == 0x4301)
+ chip_id_16 = 0x4301;
+ else if ((pci_device >= 0x4305) && (pci_device <= 0x4307))
+ chip_id_16 = 0x4307;
+ else if ((pci_device >= 0x4402) && (pci_device <= 0x4403))
+ chip_id_16 = 0x4402;
+ else if ((pci_device >= 0x4610) && (pci_device <= 0x4615))
+ chip_id_16 = 0x4610;
+ else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
+ chip_id_16 = 0x4710;
+#ifdef CONFIG_BCM947XX
+ else if ((pci_device >= 0x4320) && (pci_device <= 0x4325))
+ chip_id_16 = 0x4309;
+#endif
+ else {
+ printk(KERN_ERR PFX "Could not determine Chip ID\n");
+ return -ENODEV;
+ }
+ }
+
+ /* ChipCommon with Core Rev >=4 encodes number of cores,
+ * otherwise consult hardcoded table */
+ if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) {
+ core_count = (chip_id_32 & 0x0F000000) >> 24;
+ } else {
+ switch (chip_id_16) {
+ case 0x4610:
+ case 0x4704:
+ case 0x4710:
+ core_count = 9;
+ break;
+ case 0x4310:
+ core_count = 8;
+ break;
+ case 0x5365:
+ core_count = 7;
+ break;
+ case 0x4306:
+ core_count = 6;
+ break;
+ case 0x4301:
+ case 0x4307:
+ core_count = 5;
+ break;
+ case 0x4402:
+ core_count = 3;
+ break;
+ default:
+ /* SOL if we get here */
+ assert(0);
+ core_count = 1;
+ }
+ }
+
+ bcm->chip_id = chip_id_16;
+ bcm->chip_rev = (chip_id_32 & 0x000F0000) >> 16;
+ bcm->chip_package = (chip_id_32 & 0x00F00000) >> 20;
+
+ dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n",
+ bcm->chip_id, bcm->chip_rev);
+ dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count);
+ if (bcm->core_chipcommon.available) {
+ dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
+ core_id, core_rev, core_vendor,
+ bcm43xx_core_enabled(bcm) ? "enabled" : "disabled");
+ }
+
+ if (bcm->core_chipcommon.available)
+ current_core = 1;
+ else
+ current_core = 0;
+ for ( ; current_core < core_count; current_core++) {
+ struct bcm43xx_coreinfo *core;
+ struct bcm43xx_coreinfo_80211 *ext_80211;
+
+ err = _switch_core(bcm, current_core);
+ if (err)
+ goto out;
+ /* Gather information */
+ /* fetch sb_id_hi from core information registers */
+ sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
+
+ /* extract core_id, core_rev, core_vendor */
+ core_id = (sb_id_hi & 0xFFF0) >> 4;
+ core_rev = (sb_id_hi & 0xF);
+ core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
+
+ dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
+ current_core, core_id, core_rev, core_vendor,
+ bcm43xx_core_enabled(bcm) ? "enabled" : "disabled" );
+
+ core = NULL;
+ switch (core_id) {
+ case BCM43xx_COREID_PCI:
+ core = &bcm->core_pci;
+ if (core->available) {
+ printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
+ continue;
+ }
+ break;
+ case BCM43xx_COREID_80211:
+ for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+ core = &(bcm->core_80211[i]);
+ ext_80211 = &(bcm->core_80211_ext[i]);
+ if (!core->available)
+ break;
+ core = NULL;
+ }
+ if (!core) {
+ printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n",
+ BCM43xx_MAX_80211_CORES);
+ continue;
+ }
+ if (i != 0) {
+ /* More than one 80211 core is only supported
+ * by special chips.
+ * There are chips with two 80211 cores, but with
+ * dangling pins on the second core. Be careful
+ * and ignore these cores here.
+ */
+ if (bcm->pci_dev->device != 0x4324) {
+ dprintk(KERN_INFO PFX "Ignoring additional 802.11 core.\n");
+ continue;
+ }
+ }
+ switch (core_rev) {
+ case 2:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 9:
+ break;
+ default:
+ printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
+ core_rev);
+ err = -ENODEV;
+ goto out;
+ }
+ bcm->nr_80211_available++;
+ bcm43xx_init_struct_phyinfo(&ext_80211->phy);
+ bcm43xx_init_struct_radioinfo(&ext_80211->radio);
+ break;
+ case BCM43xx_COREID_CHIPCOMMON:
+ printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n");
+ break;
+ }
+ if (core) {
+ core->available = 1;
+ core->id = core_id;
+ core->rev = core_rev;
+ core->index = current_core;
+ }
+ }
+
+ if (!bcm->core_80211[0].available) {
+ printk(KERN_ERR PFX "Error: No 80211 core found!\n");
+ err = -ENODEV;
+ goto out;
+ }
+
+ err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
+
+ assert(err == 0);
+out:
+ return err;
+}
+
+static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm)
+{
+ const u8 *mac = (const u8*)(bcm->net_dev->dev_addr);
+ u8 *bssid = bcm->ieee->bssid;
+
+ switch (bcm->ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ random_ether_addr(bssid);
+ break;
+ case IW_MODE_MASTER:
+ case IW_MODE_INFRA:
+ case IW_MODE_REPEAT:
+ case IW_MODE_SECOND:
+ case IW_MODE_MONITOR:
+ memcpy(bssid, mac, ETH_ALEN);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm,
+ u16 rate,
+ int is_ofdm)
+{
+ u16 offset;
+
+ if (is_ofdm) {
+ offset = 0x480;
+ offset += (bcm43xx_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2;
+ }
+ else {
+ offset = 0x4C0;
+ offset += (bcm43xx_plcp_get_ratecode_cck(rate) & 0x000F) * 2;
+ }
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, offset + 0x20,
+ bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, offset));
+}
+
+static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm)
+{
+ switch (bcm43xx_current_phy(bcm)->type) {
+ case BCM43xx_PHYTYPE_A:
+ case BCM43xx_PHYTYPE_G:
+ bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1);
+ bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_12MB, 1);
+ bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_18MB, 1);
+ bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_24MB, 1);
+ bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_36MB, 1);
+ bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_48MB, 1);
+ bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_54MB, 1);
+ case BCM43xx_PHYTYPE_B:
+ bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_1MB, 0);
+ bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_2MB, 0);
+ bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_5MB, 0);
+ bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_11MB, 0);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm)
+{
+ bcm43xx_chip_cleanup(bcm);
+ bcm43xx_pio_free(bcm);
+ bcm43xx_dma_free(bcm);
+
+ bcm->current_core->initialized = 0;
+}
+
+/* http://bcm-specs.sipsolutions.net/80211Init */
+static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u32 ucodeflags;
+ int err;
+ u32 sbimconfiglow;
+ u8 limit;
+
+ if (bcm->chip_rev < 5) {
+ sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+ sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+ sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+ if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
+ sbimconfiglow |= 0x32;
+ else if (bcm->bustype == BCM43xx_BUSTYPE_SB)
+ sbimconfiglow |= 0x53;
+ else
+ assert(0);
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
+ }
+
+ bcm43xx_phy_calibrate(bcm);
+ err = bcm43xx_chip_init(bcm);
+ if (err)
+ goto out;
+
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev);
+ ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET);
+
+ if (0 /*FIXME: which condition has to be used here? */)
+ ucodeflags |= 0x00000010;
+
+ /* HW decryption needs to be set now */
+ ucodeflags |= 0x40000000;
+
+ if (phy->type == BCM43xx_PHYTYPE_G) {
+ ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
+ if (phy->rev == 1)
+ ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY;
+ if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+ ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL;
+ } else if (phy->type == BCM43xx_PHYTYPE_B) {
+ ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
+ if (phy->rev >= 2 && radio->version == 0x2050)
+ ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY;
+ }
+
+ if (ucodeflags != bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET)) {
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET, ucodeflags);
+ }
+
+ /* Short/Long Retry Limit.
+ * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
+ * the chip-internal counter.
+ */
+ limit = limit_value(modparam_short_retry, 0, 0xF);
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0006, limit);
+ limit = limit_value(modparam_long_retry, 0, 0xF);
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0007, limit);
+
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0044, 3);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0046, 2);
+
+ bcm43xx_rate_memory_init(bcm);
+
+ /* Minimum Contention Window */
+ if (phy->type == BCM43xx_PHYTYPE_B)
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f);
+ else
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f);
+ /* Maximum Contention Window */
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
+
+ bcm43xx_gen_bssid(bcm);
+ bcm43xx_write_mac_bssid_templates(bcm);
+
+ if (bcm->current_core->rev >= 5)
+ bcm43xx_write16(bcm, 0x043C, 0x000C);
+
+ if (bcm43xx_using_pio(bcm))
+ err = bcm43xx_pio_init(bcm);
+ else
+ err = bcm43xx_dma_init(bcm);
+ if (err)
+ goto err_chip_cleanup;
+ bcm43xx_write16(bcm, 0x0612, 0x0050);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
+
+ bcm43xx_mac_enable(bcm);
+ bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+
+ bcm->current_core->initialized = 1;
+out:
+ return err;
+
+err_chip_cleanup:
+ bcm43xx_chip_cleanup(bcm);
+ goto out;
+}
+
+static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm)
+{
+ int err;
+ u16 pci_status;
+
+ err = bcm43xx_pctl_set_crystal(bcm, 1);
+ if (err)
+ goto out;
+ bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
+ bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
+
+out:
+ return err;
+}
+
+static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm)
+{
+ bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
+ bcm43xx_pctl_set_crystal(bcm, 0);
+}
+
+static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm,
+ u32 address,
+ u32 data)
+{
+ bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address);
+ bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data);
+}
+
+static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
+{
+ int err;
+ struct bcm43xx_coreinfo *old_core;
+
+ old_core = bcm->current_core;
+ err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+ if (err)
+ goto out;
+
+ bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+
+ bcm43xx_switch_core(bcm, old_core);
+ assert(err == 0);
+out:
+ return err;
+}
+
+/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
+ * To enable core 0, pass a core_mask of 1<<0
+ */
+static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
+ u32 core_mask)
+{
+ u32 backplane_flag_nr;
+ u32 value;
+ struct bcm43xx_coreinfo *old_core;
+ int err = 0;
+
+ value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG);
+ backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK;
+
+ old_core = bcm->current_core;
+ err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+ if (err)
+ goto out;
+
+ if (bcm->core_pci.rev < 6) {
+ value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
+ value |= (1 << backplane_flag_nr);
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
+ } else {
+ err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value);
+ if (err) {
+ printk(KERN_ERR PFX "Error: ICR setup failure!\n");
+ goto out_switch_back;
+ }
+ value |= core_mask << 8;
+ err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value);
+ if (err) {
+ printk(KERN_ERR PFX "Error: ICR setup failure!\n");
+ goto out_switch_back;
+ }
+ }
+
+ value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+ value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
+ bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+
+ if (bcm->core_pci.rev < 5) {
+ value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+ value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
+ & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+ value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
+ & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
+ err = bcm43xx_pcicore_commit_settings(bcm);
+ assert(err == 0);
+ }
+
+out_switch_back:
+ err = bcm43xx_switch_core(bcm, old_core);
+out:
+ return err;
+}
+
+static void bcm43xx_softmac_init(struct bcm43xx_private *bcm)
+{
+ ieee80211softmac_start(bcm->net_dev);
+}
+
+static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+ if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2)
+ return;
+
+ bcm43xx_mac_suspend(bcm);
+ bcm43xx_phy_lo_g_measure(bcm);
+ bcm43xx_mac_enable(bcm);
+}
+
+static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm)
+{
+ bcm43xx_phy_lo_mark_all_unused(bcm);
+ if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+ bcm43xx_mac_suspend(bcm);
+ bcm43xx_calc_nrssi_slope(bcm);
+ bcm43xx_mac_enable(bcm);
+ }
+}
+
+static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm)
+{
+ /* Update device statistics. */
+ bcm43xx_calculate_link_quality(bcm);
+}
+
+static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+ if (phy->type == BCM43xx_PHYTYPE_G) {
+ //TODO: update_aci_moving_average
+ if (radio->aci_enable && radio->aci_wlan_automatic) {
+ bcm43xx_mac_suspend(bcm);
+ if (!radio->aci_enable && 1 /*TODO: not scanning? */) {
+ if (0 /*TODO: bunch of conditions*/) {
+ bcm43xx_radio_set_interference_mitigation(bcm,
+ BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
+ }
+ } else if (1/*TODO*/) {
+ /*
+ if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) {
+ bcm43xx_radio_set_interference_mitigation(bcm,
+ BCM43xx_RADIO_INTERFMODE_NONE);
+ }
+ */
+ }
+ bcm43xx_mac_enable(bcm);
+ } else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN &&
+ phy->rev == 1) {
+ //TODO: implement rev1 workaround
+ }
+ }
+ bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
+ //TODO for APHY (temperature?)
+}
+
+static void bcm43xx_periodic_task_handler(unsigned long d)
+{
+ struct bcm43xx_private *bcm = (struct bcm43xx_private *)d;
+ unsigned long flags;
+ unsigned int state;
+
+ bcm43xx_lock_mmio(bcm, flags);
+
+ assert(bcm->initialized);
+ state = bcm->periodic_state;
+ if (state % 8 == 0)
+ bcm43xx_periodic_every120sec(bcm);
+ if (state % 4 == 0)
+ bcm43xx_periodic_every60sec(bcm);
+ if (state % 2 == 0)
+ bcm43xx_periodic_every30sec(bcm);
+ bcm43xx_periodic_every15sec(bcm);
+ bcm->periodic_state = state + 1;
+
+ mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15));
+
+ bcm43xx_unlock_mmio(bcm, flags);
+}
+
+static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
+{
+ del_timer_sync(&bcm->periodic_tasks);
+}
+
+static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
+{
+ struct timer_list *timer = &(bcm->periodic_tasks);
+
+ assert(bcm->initialized);
+ setup_timer(timer,
+ bcm43xx_periodic_task_handler,
+ (unsigned long)bcm);
+ timer->expires = jiffies;
+ add_timer(timer);
+}
+
+static void bcm43xx_security_init(struct bcm43xx_private *bcm)
+{
+ bcm->security_offset = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+ 0x0056) * 2;
+ bcm43xx_clear_keys(bcm);
+}
+
+/* This is the opposite of bcm43xx_init_board() */
+static void bcm43xx_free_board(struct bcm43xx_private *bcm)
+{
+ int i, err;
+ unsigned long flags;
+
+ bcm43xx_sysfs_unregister(bcm);
+
+ bcm43xx_periodic_tasks_delete(bcm);
+
+ bcm43xx_lock(bcm, flags);
+ bcm->initialized = 0;
+ bcm->shutting_down = 1;
+ bcm43xx_unlock(bcm, flags);
+
+ for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+ if (!bcm->core_80211[i].available)
+ continue;
+ if (!bcm->core_80211[i].initialized)
+ continue;
+
+ err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
+ assert(err == 0);
+ bcm43xx_wireless_core_cleanup(bcm);
+ }
+
+ bcm43xx_pctl_set_crystal(bcm, 0);
+
+ bcm43xx_lock(bcm, flags);
+ bcm->shutting_down = 0;
+ bcm43xx_unlock(bcm, flags);
+}
+
+static int bcm43xx_init_board(struct bcm43xx_private *bcm)
+{
+ int i, err;
+ int connect_phy;
+ unsigned long flags;
+
+ might_sleep();
+
+ bcm43xx_lock(bcm, flags);
+ bcm->initialized = 0;
+ bcm->shutting_down = 0;
+ bcm43xx_unlock(bcm, flags);
+
+ err = bcm43xx_pctl_set_crystal(bcm, 1);
+ if (err)
+ goto out;
+ err = bcm43xx_pctl_init(bcm);
+ if (err)
+ goto err_crystal_off;
+ err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
+ if (err)
+ goto err_crystal_off;
+
+ tasklet_enable(&bcm->isr_tasklet);
+ for (i = 0; i < bcm->nr_80211_available; i++) {
+ err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
+ assert(err != -ENODEV);
+ if (err)
+ goto err_80211_unwind;
+
+ /* Enable the selected wireless core.
+ * Connect PHY only on the first core.
+ */
+ if (!bcm43xx_core_enabled(bcm)) {
+ if (bcm->nr_80211_available == 1) {
+ connect_phy = bcm43xx_current_phy(bcm)->connected;
+ } else {
+ if (i == 0)
+ connect_phy = 1;
+ else
+ connect_phy = 0;
+ }
+ bcm43xx_wireless_core_reset(bcm, connect_phy);
+ }
+
+ if (i != 0)
+ bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]);
+
+ err = bcm43xx_wireless_core_init(bcm);
+ if (err)
+ goto err_80211_unwind;
+
+ if (i != 0) {
+ bcm43xx_mac_suspend(bcm);
+ bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+ bcm43xx_radio_turn_off(bcm);
+ }
+ }
+ bcm->active_80211_core = &bcm->core_80211[0];
+ if (bcm->nr_80211_available >= 2) {
+ bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
+ bcm43xx_mac_enable(bcm);
+ }
+ bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
+ bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
+ dprintk(KERN_INFO PFX "80211 cores initialized\n");
+ bcm43xx_security_init(bcm);
+ bcm43xx_softmac_init(bcm);
+
+ bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
+
+ if (bcm43xx_current_radio(bcm)->initial_channel != 0xFF) {
+ bcm43xx_mac_suspend(bcm);
+ bcm43xx_radio_selectchannel(bcm, bcm43xx_current_radio(bcm)->initial_channel, 0);
+ bcm43xx_mac_enable(bcm);
+ }
+
+ /* Initialization of the board is done. Flag it as such. */
+ bcm43xx_lock(bcm, flags);
+ bcm->initialized = 1;
+ bcm43xx_unlock(bcm, flags);
+
+ bcm43xx_periodic_tasks_setup(bcm);
+ bcm43xx_sysfs_register(bcm);
+ //FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though...
+
+ /*FIXME: This should be handled by softmac instead. */
+ schedule_work(&bcm->softmac->associnfo.work);
+
+ assert(err == 0);
+out:
+ return err;
+
+err_80211_unwind:
+ tasklet_disable(&bcm->isr_tasklet);
+ /* unwind all 80211 initialization */
+ for (i = 0; i < bcm->nr_80211_available; i++) {
+ if (!bcm->core_80211[i].initialized)
+ continue;
+ bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+ bcm43xx_wireless_core_cleanup(bcm);
+ }
+err_crystal_off:
+ bcm43xx_pctl_set_crystal(bcm, 0);
+ goto out;
+}
+
+static void bcm43xx_detach_board(struct bcm43xx_private *bcm)
+{
+ struct pci_dev *pci_dev = bcm->pci_dev;
+ int i;
+
+ bcm43xx_chipset_detach(bcm);
+ /* Do _not_ access the chip, after it is detached. */
+ iounmap(bcm->mmio_addr);
+
+ pci_release_regions(pci_dev);
+ pci_disable_device(pci_dev);
+
+ /* Free allocated structures/fields */
+ for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+ kfree(bcm->core_80211_ext[i].phy._lo_pairs);
+ if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
+ kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
+ }
+}
+
+static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u16 value;
+ u8 phy_version;
+ u8 phy_type;
+ u8 phy_rev;
+ int phy_rev_ok = 1;
+ void *p;
+
+ value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER);
+
+ phy_version = (value & 0xF000) >> 12;
+ phy_type = (value & 0x0F00) >> 8;
+ phy_rev = (value & 0x000F);
+
+ dprintk(KERN_INFO PFX "Detected PHY: Version: %x, Type %x, Revision %x\n",
+ phy_version, phy_type, phy_rev);
+
+ switch (phy_type) {
+ case BCM43xx_PHYTYPE_A:
+ if (phy_rev >= 4)
+ phy_rev_ok = 0;
+ /*FIXME: We need to switch the ieee->modulation, etc.. flags,
+ * if we switch 80211 cores after init is done.
+ * As we do not implement on the fly switching between
+ * wireless cores, I will leave this as a future task.
+ */
+ bcm->ieee->modulation = IEEE80211_OFDM_MODULATION;
+ bcm->ieee->mode = IEEE_A;
+ bcm->ieee->freq_band = IEEE80211_52GHZ_BAND |
+ IEEE80211_24GHZ_BAND;
+ break;
+ case BCM43xx_PHYTYPE_B:
+ if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 && phy_rev != 7)
+ phy_rev_ok = 0;
+ bcm->ieee->modulation = IEEE80211_CCK_MODULATION;
+ bcm->ieee->mode = IEEE_B;
+ bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
+ break;
+ case BCM43xx_PHYTYPE_G:
+ if (phy_rev > 7)
+ phy_rev_ok = 0;
+ bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
+ IEEE80211_CCK_MODULATION;
+ bcm->ieee->mode = IEEE_G;
+ bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
+ break;
+ default:
+ printk(KERN_ERR PFX "Error: Unknown PHY Type %x\n",
+ phy_type);
+ return -ENODEV;
+ };
+ if (!phy_rev_ok) {
+ printk(KERN_WARNING PFX "Invalid PHY Revision %x\n",
+ phy_rev);
+ }
+
+ phy->version = phy_version;
+ phy->type = phy_type;
+ phy->rev = phy_rev;
+ if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) {
+ p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT,
+ GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+ phy->_lo_pairs = p;
+ }
+
+ return 0;
+}
+
+static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
+{
+ struct pci_dev *pci_dev = bcm->pci_dev;
+ struct net_device *net_dev = bcm->net_dev;
+ int err;
+ int i;
+ unsigned long mmio_start, mmio_flags, mmio_len;
+ u32 coremask;
+
+ err = pci_enable_device(pci_dev);
+ if (err) {
+ printk(KERN_ERR PFX "unable to wake up pci device (%i)\n", err);
+ goto out;
+ }
+ mmio_start = pci_resource_start(pci_dev, 0);
+ mmio_flags = pci_resource_flags(pci_dev, 0);
+ mmio_len = pci_resource_len(pci_dev, 0);
+ if (!(mmio_flags & IORESOURCE_MEM)) {
+ printk(KERN_ERR PFX
+ "%s, region #0 not an MMIO resource, aborting\n",
+ pci_name(pci_dev));
+ err = -ENODEV;
+ goto err_pci_disable;
+ }
+ err = pci_request_regions(pci_dev, KBUILD_MODNAME);
+ if (err) {
+ printk(KERN_ERR PFX
+ "could not access PCI resources (%i)\n", err);
+ goto err_pci_disable;
+ }
+ /* enable PCI bus-mastering */
+ pci_set_master(pci_dev);
+ bcm->mmio_addr = ioremap(mmio_start, mmio_len);
+ if (!bcm->mmio_addr) {
+ printk(KERN_ERR PFX "%s: cannot remap MMIO, aborting\n",
+ pci_name(pci_dev));
+ err = -EIO;
+ goto err_pci_release;
+ }
+ bcm->mmio_len = mmio_len;
+ net_dev->base_addr = (unsigned long)bcm->mmio_addr;
+
+ bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
+ &bcm->board_vendor);
+ bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
+ &bcm->board_type);
+ bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
+ &bcm->board_revision);
+
+ err = bcm43xx_chipset_attach(bcm);
+ if (err)
+ goto err_iounmap;
+ err = bcm43xx_pctl_init(bcm);
+ if (err)
+ goto err_chipset_detach;
+ err = bcm43xx_probe_cores(bcm);
+ if (err)
+ goto err_chipset_detach;
+
+ /* Attach all IO cores to the backplane. */
+ coremask = 0;
+ for (i = 0; i < bcm->nr_80211_available; i++)
+ coremask |= (1 << bcm->core_80211[i].index);
+ //FIXME: Also attach some non80211 cores?
+ err = bcm43xx_setup_backplane_pci_connection(bcm, coremask);
+ if (err) {
+ printk(KERN_ERR PFX "Backplane->PCI connection failed!\n");
+ goto err_chipset_detach;
+ }
+
+ err = bcm43xx_sprom_extract(bcm);
+ if (err)
+ goto err_chipset_detach;
+ err = bcm43xx_leds_init(bcm);
+ if (err)
+ goto err_chipset_detach;
+
+ for (i = 0; i < bcm->nr_80211_available; i++) {
+ err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
+ assert(err != -ENODEV);
+ if (err)
+ goto err_80211_unwind;
+
+ /* Enable the selected wireless core.
+ * Connect PHY only on the first core.
+ */
+ bcm43xx_wireless_core_reset(bcm, (i == 0));
+
+ err = bcm43xx_read_phyinfo(bcm);
+ if (err && (i == 0))
+ goto err_80211_unwind;
+
+ err = bcm43xx_read_radioinfo(bcm);
+ if (err && (i == 0))
+ goto err_80211_unwind;
+
+ err = bcm43xx_validate_chip(bcm);
+ if (err && (i == 0))
+ goto err_80211_unwind;
+
+ bcm43xx_radio_turn_off(bcm);
+ err = bcm43xx_phy_init_tssi2dbm_table(bcm);
+ if (err)
+ goto err_80211_unwind;
+ bcm43xx_wireless_core_disable(bcm);
+ }
+ err = bcm43xx_geo_init(bcm);
+ if (err)
+ goto err_80211_unwind;
+ bcm43xx_pctl_set_crystal(bcm, 0);
+
+ /* Set the MAC address in the networking subsystem */
+ if (is_valid_ether_addr(bcm->sprom.et1macaddr))
+ memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
+ else
+ memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
+
+ snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
+ "Broadcom %04X", bcm->chip_id);
+
+ assert(err == 0);
+out:
+ return err;
+
+err_80211_unwind:
+ for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+ kfree(bcm->core_80211_ext[i].phy._lo_pairs);
+ if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
+ kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
+ }
+err_chipset_detach:
+ bcm43xx_chipset_detach(bcm);
+err_iounmap:
+ iounmap(bcm->mmio_addr);
+err_pci_release:
+ pci_release_regions(pci_dev);
+err_pci_disable:
+ pci_disable_device(pci_dev);
+ goto out;
+}
+
+/* Do the Hardware IO operations to send the txb */
+static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
+ struct ieee80211_txb *txb)
+{
+ int err = -ENODEV;
+
+ if (bcm43xx_using_pio(bcm))
+ err = bcm43xx_pio_tx(bcm, txb);
+ else
+ err = bcm43xx_dma_tx(bcm, txb);
+ bcm->net_dev->trans_start = jiffies;
+
+ return err;
+}
+
+static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
+ u8 channel)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ struct bcm43xx_radioinfo *radio;
+ unsigned long flags;
+
+ bcm43xx_lock_mmio(bcm, flags);
+ if (bcm->initialized) {
+ bcm43xx_mac_suspend(bcm);
+ bcm43xx_radio_selectchannel(bcm, channel, 0);
+ bcm43xx_mac_enable(bcm);
+ } else {
+ radio = bcm43xx_current_radio(bcm);
+ radio->initial_channel = channel;
+ }
+ bcm43xx_unlock_mmio(bcm, flags);
+}
+
+/* set_security() callback in struct ieee80211_device */
+static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
+ struct ieee80211_security *sec)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ struct ieee80211_security *secinfo = &bcm->ieee->sec;
+ unsigned long flags;
+ int keyidx;
+
+ dprintk(KERN_INFO PFX "set security called\n");
+
+ bcm43xx_lock_mmio(bcm, flags);
+
+ for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
+ if (sec->flags & (1<<keyidx)) {
+ secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx];
+ secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx];
+ memcpy(secinfo->keys[keyidx], sec->keys[keyidx], SCM_KEY_LEN);
+ }
+
+ if (sec->flags & SEC_ACTIVE_KEY) {
+ secinfo->active_key = sec->active_key;
+ dprintk(KERN_INFO PFX " .active_key = %d\n", sec->active_key);
+ }
+ if (sec->flags & SEC_UNICAST_GROUP) {
+ secinfo->unicast_uses_group = sec->unicast_uses_group;
+ dprintk(KERN_INFO PFX " .unicast_uses_group = %d\n", sec->unicast_uses_group);
+ }
+ if (sec->flags & SEC_LEVEL) {
+ secinfo->level = sec->level;
+ dprintk(KERN_INFO PFX " .level = %d\n", sec->level);
+ }
+ if (sec->flags & SEC_ENABLED) {
+ secinfo->enabled = sec->enabled;
+ dprintk(KERN_INFO PFX " .enabled = %d\n", sec->enabled);
+ }
+ if (sec->flags & SEC_ENCRYPT) {
+ secinfo->encrypt = sec->encrypt;
+ dprintk(KERN_INFO PFX " .encrypt = %d\n", sec->encrypt);
+ }
+ if (bcm->initialized && !bcm->ieee->host_encrypt) {
+ if (secinfo->enabled) {
+ /* upload WEP keys to hardware */
+ char null_address[6] = { 0 };
+ u8 algorithm = 0;
+ for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) {
+ if (!(sec->flags & (1<<keyidx)))
+ continue;
+ switch (sec->encode_alg[keyidx]) {
+ case SEC_ALG_NONE: algorithm = BCM43xx_SEC_ALGO_NONE; break;
+ case SEC_ALG_WEP:
+ algorithm = BCM43xx_SEC_ALGO_WEP;
+ if (secinfo->key_sizes[keyidx] == 13)
+ algorithm = BCM43xx_SEC_ALGO_WEP104;
+ break;
+ case SEC_ALG_TKIP:
+ FIXME();
+ algorithm = BCM43xx_SEC_ALGO_TKIP;
+ break;
+ case SEC_ALG_CCMP:
+ FIXME();
+ algorithm = BCM43xx_SEC_ALGO_AES;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ bcm43xx_key_write(bcm, keyidx, algorithm, sec->keys[keyidx], secinfo->key_sizes[keyidx], &null_address[0]);
+ bcm->key[keyidx].enabled = 1;
+ bcm->key[keyidx].algorithm = algorithm;
+ }
+ } else
+ bcm43xx_clear_keys(bcm);
+ }
+ bcm43xx_unlock_mmio(bcm, flags);
+}
+
+/* hard_start_xmit() callback in struct ieee80211_device */
+static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
+ struct net_device *net_dev,
+ int pri)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ int err = -ENODEV;
+ unsigned long flags;
+
+ bcm43xx_lock_mmio(bcm, flags);
+ if (likely(bcm->initialized))
+ err = bcm43xx_tx(bcm, txb);
+ bcm43xx_unlock_mmio(bcm, flags);
+
+ return err;
+}
+
+static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev)
+{
+ return &(bcm43xx_priv(net_dev)->ieee->stats);
+}
+
+static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+
+ bcm43xx_lock_mmio(bcm, flags);
+ bcm43xx_controller_restart(bcm, "TX timeout");
+ bcm43xx_unlock_mmio(bcm, flags);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void bcm43xx_net_poll_controller(struct net_device *net_dev)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+
+ local_irq_save(flags);
+ bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
+ local_irq_restore(flags);
+}
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+
+static int bcm43xx_net_open(struct net_device *net_dev)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+
+ return bcm43xx_init_board(bcm);
+}
+
+static int bcm43xx_net_stop(struct net_device *net_dev)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+
+ ieee80211softmac_stop(net_dev);
+ bcm43xx_disable_interrupts_sync(bcm, NULL);
+ bcm43xx_free_board(bcm);
+
+ return 0;
+}
+
+static int bcm43xx_init_private(struct bcm43xx_private *bcm,
+ struct net_device *net_dev,
+ struct pci_dev *pci_dev)
+{
+ int err;
+
+ bcm->ieee = netdev_priv(net_dev);
+ bcm->softmac = ieee80211_priv(net_dev);
+ bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
+
+ bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+ bcm->pci_dev = pci_dev;
+ bcm->net_dev = net_dev;
+ bcm->bad_frames_preempt = modparam_bad_frames_preempt;
+ spin_lock_init(&bcm->_lock);
+ tasklet_init(&bcm->isr_tasklet,
+ (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
+ (unsigned long)bcm);
+ tasklet_disable_nosync(&bcm->isr_tasklet);
+ if (modparam_pio) {
+ bcm->__using_pio = 1;
+ } else {
+ err = pci_set_dma_mask(pci_dev, DMA_30BIT_MASK);
+ err |= pci_set_consistent_dma_mask(pci_dev, DMA_30BIT_MASK);
+ if (err) {
+#ifdef CONFIG_BCM43XX_PIO
+ printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n");
+ bcm->__using_pio = 1;
+#else
+ printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
+ "Recompile the driver with PIO support, please.\n");
+ return -ENODEV;
+#endif /* CONFIG_BCM43XX_PIO */
+ }
+ }
+ bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;
+
+ /* default to sw encryption for now */
+ bcm->ieee->host_build_iv = 0;
+ bcm->ieee->host_encrypt = 1;
+ bcm->ieee->host_decrypt = 1;
+
+ bcm->ieee->iw_mode = BCM43xx_INITIAL_IWMODE;
+ bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr);
+ bcm->ieee->set_security = bcm43xx_ieee80211_set_security;
+ bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit;
+
+ return 0;
+}
+
+static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct net_device *net_dev;
+ struct bcm43xx_private *bcm;
+ int err;
+
+#ifdef CONFIG_BCM947XX
+ if ((pdev->bus->number == 0) && (pdev->device != 0x0800))
+ return -ENODEV;
+#endif
+
+#ifdef DEBUG_SINGLE_DEVICE_ONLY
+ if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY))
+ return -ENODEV;
+#endif
+
+ net_dev = alloc_ieee80211softmac(sizeof(*bcm));
+ if (!net_dev) {
+ printk(KERN_ERR PFX
+ "could not allocate ieee80211 device %s\n",
+ pci_name(pdev));
+ err = -ENOMEM;
+ goto out;
+ }
+ /* initialize the net_device struct */
+ SET_MODULE_OWNER(net_dev);
+ SET_NETDEV_DEV(net_dev, &pdev->dev);
+
+ net_dev->open = bcm43xx_net_open;
+ net_dev->stop = bcm43xx_net_stop;
+ net_dev->get_stats = bcm43xx_net_get_stats;
+ net_dev->tx_timeout = bcm43xx_net_tx_timeout;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ net_dev->poll_controller = bcm43xx_net_poll_controller;
+#endif
+ net_dev->wireless_handlers = &bcm43xx_wx_handlers_def;
+ net_dev->irq = pdev->irq;
+ SET_ETHTOOL_OPS(net_dev, &bcm43xx_ethtool_ops);
+
+ /* initialize the bcm43xx_private struct */
+ bcm = bcm43xx_priv(net_dev);
+ memset(bcm, 0, sizeof(*bcm));
+ err = bcm43xx_init_private(bcm, net_dev, pdev);
+ if (err)
+ goto err_free_netdev;
+
+ pci_set_drvdata(pdev, net_dev);
+
+ err = bcm43xx_attach_board(bcm);
+ if (err)
+ goto err_free_netdev;
+
+ err = register_netdev(net_dev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot register net device, "
+ "aborting.\n");
+ err = -ENOMEM;
+ goto err_detach_board;
+ }
+
+ bcm43xx_debugfs_add_device(bcm);
+
+ assert(err == 0);
+out:
+ return err;
+
+err_detach_board:
+ bcm43xx_detach_board(bcm);
+err_free_netdev:
+ free_ieee80211softmac(net_dev);
+ goto out;
+}
+
+static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *net_dev = pci_get_drvdata(pdev);
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+
+ bcm43xx_debugfs_remove_device(bcm);
+ unregister_netdev(net_dev);
+ bcm43xx_detach_board(bcm);
+ assert(bcm->ucode == NULL);
+ free_ieee80211softmac(net_dev);
+}
+
+/* Hard-reset the chip. Do not call this directly.
+ * Use bcm43xx_controller_restart()
+ */
+static void bcm43xx_chip_reset(void *_bcm)
+{
+ struct bcm43xx_private *bcm = _bcm;
+ struct net_device *net_dev = bcm->net_dev;
+ struct pci_dev *pci_dev = bcm->pci_dev;
+ int err;
+ int was_initialized = bcm->initialized;
+
+ netif_stop_queue(bcm->net_dev);
+ tasklet_disable(&bcm->isr_tasklet);
+
+ bcm->firmware_norelease = 1;
+ if (was_initialized)
+ bcm43xx_free_board(bcm);
+ bcm->firmware_norelease = 0;
+ bcm43xx_detach_board(bcm);
+ err = bcm43xx_init_private(bcm, net_dev, pci_dev);
+ if (err)
+ goto failure;
+ err = bcm43xx_attach_board(bcm);
+ if (err)
+ goto failure;
+ if (was_initialized) {
+ err = bcm43xx_init_board(bcm);
+ if (err)
+ goto failure;
+ }
+ netif_wake_queue(bcm->net_dev);
+ printk(KERN_INFO PFX "Controller restarted\n");
+
+ return;
+failure:
+ printk(KERN_ERR PFX "Controller restart failed\n");
+}
+
+/* Hard-reset the chip.
+ * This can be called from interrupt or process context.
+ * Make sure to _not_ re-enable device interrupts after this has been called.
+*/
+void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
+{
+ bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+ printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
+ INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
+ schedule_work(&bcm->restart_work);
+}
+
+#ifdef CONFIG_PM
+
+static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *net_dev = pci_get_drvdata(pdev);
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ int try_to_shutdown = 0, err;
+
+ dprintk(KERN_INFO PFX "Suspending...\n");
+
+ bcm43xx_lock(bcm, flags);
+ bcm->was_initialized = bcm->initialized;
+ if (bcm->initialized)
+ try_to_shutdown = 1;
+ bcm43xx_unlock(bcm, flags);
+
+ netif_device_detach(net_dev);
+ if (try_to_shutdown) {
+ ieee80211softmac_stop(net_dev);
+ err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate);
+ if (unlikely(err)) {
+ dprintk(KERN_ERR PFX "Suspend failed.\n");
+ return -EAGAIN;
+ }
+ bcm->firmware_norelease = 1;
+ bcm43xx_free_board(bcm);
+ bcm->firmware_norelease = 0;
+ }
+ bcm43xx_chipset_detach(bcm);
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ dprintk(KERN_INFO PFX "Device suspended.\n");
+
+ return 0;
+}
+
+static int bcm43xx_resume(struct pci_dev *pdev)
+{
+ struct net_device *net_dev = pci_get_drvdata(pdev);
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ int err = 0;
+
+ dprintk(KERN_INFO PFX "Resuming...\n");
+
+ pci_set_power_state(pdev, 0);
+ pci_enable_device(pdev);
+ pci_restore_state(pdev);
+
+ bcm43xx_chipset_attach(bcm);
+ if (bcm->was_initialized) {
+ bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+ err = bcm43xx_init_board(bcm);
+ }
+ if (err) {
+ printk(KERN_ERR PFX "Resume failed!\n");
+ return err;
+ }
+
+ netif_device_attach(net_dev);
+
+ dprintk(KERN_INFO PFX "Device resumed.\n");
+
+ return 0;
+}
+
+#endif /* CONFIG_PM */
+
+static struct pci_driver bcm43xx_pci_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = bcm43xx_pci_tbl,
+ .probe = bcm43xx_init_one,
+ .remove = __devexit_p(bcm43xx_remove_one),
+#ifdef CONFIG_PM
+ .suspend = bcm43xx_suspend,
+ .resume = bcm43xx_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init bcm43xx_init(void)
+{
+ printk(KERN_INFO KBUILD_MODNAME " driver\n");
+ bcm43xx_debugfs_init();
+ return pci_register_driver(&bcm43xx_pci_driver);
+}
+
+static void __exit bcm43xx_exit(void)
+{
+ pci_unregister_driver(&bcm43xx_pci_driver);
+ bcm43xx_debugfs_exit();
+}
+
+module_init(bcm43xx_init)
+module_exit(bcm43xx_exit)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
new file mode 100644
index 00000000000..30a202b258b
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
@@ -0,0 +1,170 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ Some parts of the code in this file are derived from the ipw2200
+ driver Copyright(c) 2003 - 2004 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef BCM43xx_MAIN_H_
+#define BCM43xx_MAIN_H_
+
+#include "bcm43xx.h"
+
+#ifdef CONFIG_BCM947XX
+#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
+
+static inline void e_aton(char *str, char *dest)
+{
+ int i = 0;
+ u16 *d = (u16 *) dest;
+
+ for (;;) {
+ dest[i++] = (char) simple_strtoul(str, NULL, 16);
+ str += 2;
+ if (!*str++ || i == 6)
+ break;
+ }
+ for (i = 0; i < 3; i++)
+ d[i] = cpu_to_be16(d[i]);
+}
+#endif
+
+#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes]
+#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes)
+/* Magic helper macro to pad structures. Ignore those above. It's magic. */
+#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
+
+
+/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
+static inline
+u8 bcm43xx_freq_to_channel_a(int freq)
+{
+ return ((freq - 5000) / 5);
+}
+static inline
+u8 bcm43xx_freq_to_channel_bg(int freq)
+{
+ u8 channel;
+
+ if (freq == 2484)
+ channel = 14;
+ else
+ channel = (freq - 2407) / 5;
+
+ return channel;
+}
+static inline
+u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm,
+ int freq)
+{
+ if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
+ return bcm43xx_freq_to_channel_a(freq);
+ return bcm43xx_freq_to_channel_bg(freq);
+}
+
+/* Lightweight function to convert a channel number to a frequency (in Mhz). */
+static inline
+int bcm43xx_channel_to_freq_a(u8 channel)
+{
+ return (5000 + (5 * channel));
+}
+static inline
+int bcm43xx_channel_to_freq_bg(u8 channel)
+{
+ int freq;
+
+ if (channel == 14)
+ freq = 2484;
+ else
+ freq = 2407 + (5 * channel);
+
+ return freq;
+}
+static inline
+int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
+ u8 channel)
+{
+ if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
+ return bcm43xx_channel_to_freq_a(channel);
+ return bcm43xx_channel_to_freq_bg(channel);
+}
+
+/* Lightweight function to check if a channel number is valid.
+ * Note that this does _NOT_ check for geographical restrictions!
+ */
+static inline
+int bcm43xx_is_valid_channel_a(u8 channel)
+{
+ return (channel >= IEEE80211_52GHZ_MIN_CHANNEL
+ && channel <= IEEE80211_52GHZ_MAX_CHANNEL);
+}
+static inline
+int bcm43xx_is_valid_channel_bg(u8 channel)
+{
+ return (channel >= IEEE80211_24GHZ_MIN_CHANNEL
+ && channel <= IEEE80211_24GHZ_MAX_CHANNEL);
+}
+static inline
+int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm,
+ u8 channel)
+{
+ if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
+ return bcm43xx_is_valid_channel_a(channel);
+ return bcm43xx_is_valid_channel_bg(channel);
+}
+
+void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf);
+void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf);
+
+void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
+ int iw_mode);
+
+u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
+ u16 routing, u16 offset);
+u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
+ u16 routing, u16 offset);
+void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
+ u16 routing, u16 offset,
+ u32 value);
+void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
+ u16 routing, u16 offset,
+ u16 value);
+
+void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm);
+
+int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
+
+void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
+
+void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
+void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
+
+void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
+
+int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom);
+int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom);
+
+#endif /* BCM43xx_MAIN_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
new file mode 100644
index 00000000000..b0abac51553
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -0,0 +1,2346 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ Some parts of the code in this file are derived from the ipw2200
+ driver Copyright(c) 2003 - 2004 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+
+#include "bcm43xx.h"
+#include "bcm43xx_phy.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_radio.h"
+#include "bcm43xx_ilt.h"
+#include "bcm43xx_power.h"
+
+
+static const s8 bcm43xx_tssi2dbm_b_table[] = {
+ 0x4D, 0x4C, 0x4B, 0x4A,
+ 0x4A, 0x49, 0x48, 0x47,
+ 0x47, 0x46, 0x45, 0x45,
+ 0x44, 0x43, 0x42, 0x42,
+ 0x41, 0x40, 0x3F, 0x3E,
+ 0x3D, 0x3C, 0x3B, 0x3A,
+ 0x39, 0x38, 0x37, 0x36,
+ 0x35, 0x34, 0x32, 0x31,
+ 0x30, 0x2F, 0x2D, 0x2C,
+ 0x2B, 0x29, 0x28, 0x26,
+ 0x25, 0x23, 0x21, 0x1F,
+ 0x1D, 0x1A, 0x17, 0x14,
+ 0x10, 0x0C, 0x06, 0x00,
+ -7, -7, -7, -7,
+ -7, -7, -7, -7,
+ -7, -7, -7, -7,
+};
+
+static const s8 bcm43xx_tssi2dbm_g_table[] = {
+ 77, 77, 77, 76,
+ 76, 76, 75, 75,
+ 74, 74, 73, 73,
+ 73, 72, 72, 71,
+ 71, 70, 70, 69,
+ 68, 68, 67, 67,
+ 66, 65, 65, 64,
+ 63, 63, 62, 61,
+ 60, 59, 58, 57,
+ 56, 55, 54, 53,
+ 52, 50, 49, 47,
+ 45, 43, 40, 37,
+ 33, 28, 22, 14,
+ 5, -7, -20, -20,
+ -20, -20, -20, -20,
+ -20, -20, -20, -20,
+};
+
+static void bcm43xx_phy_initg(struct bcm43xx_private *bcm);
+
+
+void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+ assert(irqs_disabled());
+ if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) {
+ phy->is_locked = 0;
+ return;
+ }
+ if (bcm->current_core->rev < 3) {
+ bcm43xx_mac_suspend(bcm);
+ spin_lock(&phy->lock);
+ } else {
+ if (bcm->ieee->iw_mode != IW_MODE_MASTER)
+ bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
+ }
+ phy->is_locked = 1;
+}
+
+void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+ assert(irqs_disabled());
+ if (bcm->current_core->rev < 3) {
+ if (phy->is_locked) {
+ spin_unlock(&phy->lock);
+ bcm43xx_mac_enable(bcm);
+ }
+ } else {
+ if (bcm->ieee->iw_mode != IW_MODE_MASTER)
+ bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+ }
+ phy->is_locked = 0;
+}
+
+u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset)
+{
+ bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
+ return bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_DATA);
+}
+
+void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
+{
+ bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
+ mmiowb();
+ bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val);
+}
+
+void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ unsigned long flags;
+
+ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
+ if (phy->calibrated)
+ return;
+ if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
+ /* We do not want to be preempted while calibrating
+ * the hardware.
+ */
+ local_irq_save(flags);
+
+ bcm43xx_wireless_core_reset(bcm, 0);
+ bcm43xx_phy_initg(bcm);
+ bcm43xx_wireless_core_reset(bcm, 1);
+
+ local_irq_restore(flags);
+ }
+ phy->calibrated = 1;
+}
+
+/* Connect the PHY
+ * http://bcm-specs.sipsolutions.net/SetPHY
+ */
+int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u32 flags;
+
+ if (bcm->current_core->rev < 5)
+ goto out;
+
+ flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+ if (connect) {
+ if (!(flags & 0x00010000))
+ return -ENODEV;
+ flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+ flags |= (0x800 << 18);
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
+ } else {
+ if (!(flags & 0x00020000))
+ return -ENODEV;
+ flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+ flags &= ~(0x800 << 18);
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
+ }
+out:
+ phy->connected = connect;
+ if (connect)
+ dprintk(KERN_INFO PFX "PHY connected\n");
+ else
+ dprintk(KERN_INFO PFX "PHY disconnected\n");
+
+ return 0;
+}
+
+/* intialize B PHY power control
+ * as described in http://bcm-specs.sipsolutions.net/InitPowerControl
+ */
+static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0;
+ int must_reset_txpower = 0;
+
+ assert(phy->type != BCM43xx_PHYTYPE_A);
+ if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
+ (bcm->board_type == 0x0416))
+ return;
+
+ bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
+ bcm43xx_phy_write(bcm, 0x0028, 0x8018);
+
+ if (phy->type == BCM43xx_PHYTYPE_G) {
+ if (!phy->connected)
+ return;
+ bcm43xx_phy_write(bcm, 0x047A, 0xC111);
+ }
+ if (phy->savedpctlreg != 0xFFFF)
+ return;
+
+ if (phy->type == BCM43xx_PHYTYPE_B &&
+ phy->rev >= 2 &&
+ radio->version == 0x2050) {
+ bcm43xx_radio_write16(bcm, 0x0076,
+ bcm43xx_radio_read16(bcm, 0x0076) | 0x0084);
+ } else {
+ saved_batt = radio->baseband_atten;
+ saved_ratt = radio->radio_atten;
+ saved_txctl1 = radio->txctl1;
+ if ((radio->revision >= 6) && (radio->revision <= 8)
+ && /*FIXME: incomplete specs for 5 < revision < 9 */ 0)
+ bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0);
+ else
+ bcm43xx_radio_set_txpower_bg(bcm, 0xB, 9, 0);
+ must_reset_txpower = 1;
+ }
+ bcm43xx_dummy_transmission(bcm);
+
+ phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_PCTL);
+
+ if (must_reset_txpower)
+ bcm43xx_radio_set_txpower_bg(bcm, saved_batt, saved_ratt, saved_txctl1);
+ else
+ bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) & 0xFF7B);
+ bcm43xx_radio_clear_tssi(bcm);
+}
+
+static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u16 offset = 0x0000;
+
+ if (phy->rev == 1)
+ offset = 0x4C00;
+
+ bcm43xx_ilt_write(bcm, offset, 0x00FE);
+ bcm43xx_ilt_write(bcm, offset + 1, 0x000D);
+ bcm43xx_ilt_write(bcm, offset + 2, 0x0013);
+ bcm43xx_ilt_write(bcm, offset + 3, 0x0019);
+
+ if (phy->rev == 1) {
+ bcm43xx_ilt_write(bcm, 0x1800, 0x2710);
+ bcm43xx_ilt_write(bcm, 0x1801, 0x9B83);
+ bcm43xx_ilt_write(bcm, 0x1802, 0x9B83);
+ bcm43xx_ilt_write(bcm, 0x1803, 0x0F8D);
+ bcm43xx_phy_write(bcm, 0x0455, 0x0004);
+ }
+
+ bcm43xx_phy_write(bcm, 0x04A5, (bcm43xx_phy_read(bcm, 0x04A5) & 0x00FF) | 0x5700);
+ bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xFF80) | 0x000F);
+ bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xC07F) | 0x2B80);
+ bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xF0FF) | 0x0300);
+
+ bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0008);
+
+ bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFF0) | 0x0008);
+ bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xF0FF) | 0x0600);
+ bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0700);
+ bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0100);
+
+ if (phy->rev == 1)
+ bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x0007);
+
+ bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xFF00) | 0x001C);
+ bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xC0FF) | 0x0200);
+ bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0xFF00) | 0x001C);
+ bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xFF00) | 0x0020);
+ bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xC0FF) | 0x0200);
+ bcm43xx_phy_write(bcm, 0x0482, (bcm43xx_phy_read(bcm, 0x0482) & 0xFF00) | 0x002E);
+ bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0x00FF) | 0x1A00);
+ bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0xFF00) | 0x0028);
+ bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0x00FF) | 0x2C00);
+
+ if (phy->rev == 1) {
+ bcm43xx_phy_write(bcm, 0x0430, 0x092B);
+ bcm43xx_phy_write(bcm, 0x041B, (bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1) | 0x0002);
+ } else {
+ bcm43xx_phy_write(bcm, 0x041B, bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1);
+ bcm43xx_phy_write(bcm, 0x041F, 0x287A);
+ bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0xFFF0) | 0x0004);
+ }
+
+ if (phy->rev > 2) {
+ bcm43xx_phy_write(bcm, 0x0422, 0x287A);
+ bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0x0FFF) | 0x3000);
+ }
+
+ bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0x8080) | 0x7874);
+ bcm43xx_phy_write(bcm, 0x048E, 0x1C00);
+
+ if (phy->rev == 1) {
+ bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) & 0xF0FF) | 0x0600);
+ bcm43xx_phy_write(bcm, 0x048B, 0x005E);
+ bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xFF00) | 0x001E);
+ bcm43xx_phy_write(bcm, 0x048D, 0x0002);
+ }
+
+ bcm43xx_ilt_write(bcm, offset + 0x0800, 0);
+ bcm43xx_ilt_write(bcm, offset + 0x0801, 7);
+ bcm43xx_ilt_write(bcm, offset + 0x0802, 16);
+ bcm43xx_ilt_write(bcm, offset + 0x0803, 28);
+}
+
+static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u16 i;
+
+ assert(phy->type == BCM43xx_PHYTYPE_G);
+ if (phy->rev == 1) {
+ bcm43xx_phy_write(bcm, 0x0406, 0x4F19);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+ (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0xFC3F) | 0x0340);
+ bcm43xx_phy_write(bcm, 0x042C, 0x005A);
+ bcm43xx_phy_write(bcm, 0x0427, 0x001A);
+
+ for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]);
+ for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]);
+ for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+ } else {
+ /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
+ bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654);
+
+ if (phy->rev == 2) {
+ bcm43xx_phy_write(bcm, 0x04C0, 0x1861);
+ bcm43xx_phy_write(bcm, 0x04C1, 0x0271);
+ } else if (phy->rev > 2) {
+ bcm43xx_phy_write(bcm, 0x04C0, 0x0098);
+ bcm43xx_phy_write(bcm, 0x04C1, 0x0070);
+ bcm43xx_phy_write(bcm, 0x04C9, 0x0080);
+ }
+ bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800);
+
+ for (i = 0; i < 64; i++)
+ bcm43xx_ilt_write(bcm, 0x4000 + i, i);
+ for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]);
+ }
+
+ if (phy->rev <= 2)
+ for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]);
+ else if ((phy->rev == 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
+ for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]);
+ else
+ for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]);
+
+ if (phy->rev == 2)
+ for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
+ else if ((phy->rev > 2) && (phy->rev <= 7))
+ for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]);
+
+ if (phy->rev == 1) {
+ for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+ for (i = 0; i < 4; i++) {
+ bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020);
+ bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020);
+ bcm43xx_ilt_write(bcm, 0x540C + i, 0x0020);
+ bcm43xx_ilt_write(bcm, 0x5410 + i, 0x0020);
+ }
+ bcm43xx_phy_agcsetup(bcm);
+
+ if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
+ (bcm->board_type == 0x0416) &&
+ (bcm->board_revision == 0x0017))
+ return;
+
+ bcm43xx_ilt_write(bcm, 0x5001, 0x0002);
+ bcm43xx_ilt_write(bcm, 0x5002, 0x0001);
+ } else {
+ for (i = 0; i <= 0x2F; i++)
+ bcm43xx_ilt_write(bcm, 0x1000 + i, 0x0820);
+ bcm43xx_phy_agcsetup(bcm);
+ bcm43xx_phy_read(bcm, 0x0400); /* dummy read */
+ bcm43xx_phy_write(bcm, 0x0403, 0x1000);
+ bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
+ bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
+
+ if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
+ (bcm->board_type == 0x0416) &&
+ (bcm->board_revision == 0x0017))
+ return;
+
+ bcm43xx_ilt_write(bcm, 0x0401, 0x0002);
+ bcm43xx_ilt_write(bcm, 0x0402, 0x0001);
+ }
+}
+
+/* Initialize the noisescaletable for APHY */
+static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ int i;
+
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400);
+ for (i = 0; i < 12; i++) {
+ if (phy->rev == 2)
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
+ else
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
+ }
+ if (phy->rev == 2)
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6700);
+ else
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2300);
+ for (i = 0; i < 11; i++) {
+ if (phy->rev == 2)
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
+ else
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
+ }
+ if (phy->rev == 2)
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0067);
+ else
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0023);
+}
+
+static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u16 i;
+
+ assert(phy->type == BCM43xx_PHYTYPE_A);
+ switch (phy->rev) {
+ case 2:
+ bcm43xx_phy_write(bcm, 0x008E, 0x3800);
+ bcm43xx_phy_write(bcm, 0x0035, 0x03FF);
+ bcm43xx_phy_write(bcm, 0x0036, 0x0400);
+
+ bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
+
+ bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
+ bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
+ bcm43xx_ilt_write(bcm, 0x3C0C, 0x07BF);
+ bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
+
+ bcm43xx_phy_write(bcm, 0x0024, 0x4680);
+ bcm43xx_phy_write(bcm, 0x0020, 0x0003);
+ bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
+ bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
+
+ bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
+ bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF);
+ bcm43xx_phy_write(bcm, 0x008E, 0x58C1);
+
+ bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
+ bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
+ bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
+ bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
+ bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
+
+ bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
+ bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
+ bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
+ bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
+ bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
+ bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
+ bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
+
+ bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
+ bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
+ bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
+
+ for (i = 0; i < 16; i++)
+ bcm43xx_ilt_write(bcm, 0x4000 + i, (0x8 + i) & 0x000F);
+
+ bcm43xx_ilt_write(bcm, 0x3003, 0x1044);
+ bcm43xx_ilt_write(bcm, 0x3004, 0x7201);
+ bcm43xx_ilt_write(bcm, 0x3006, 0x0040);
+ bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
+
+ for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]);
+ for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]);
+ for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+ bcm43xx_phy_init_noisescaletbl(bcm);
+ for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+ break;
+ case 3:
+ for (i = 0; i < 64; i++)
+ bcm43xx_ilt_write(bcm, 0x4000 + i, i);
+
+ bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
+
+ bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
+ bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
+ bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
+
+ bcm43xx_phy_write(bcm, 0x0024, 0x4680);
+ bcm43xx_phy_write(bcm, 0x0020, 0x0003);
+ bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
+ bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
+ bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
+
+ bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
+ for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]);
+ bcm43xx_phy_init_noisescaletbl(bcm);
+ for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
+ bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
+
+ bcm43xx_phy_write(bcm, 0x0003, 0x1808);
+
+ bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
+ bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
+ bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
+ bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
+ bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
+
+ bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
+ bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
+ bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
+ bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
+ bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
+ bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
+ bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
+
+ bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
+ bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
+ bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
+
+ bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
+ bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+/* Initialize APHY. This is also called for the GPHY in some cases. */
+static void bcm43xx_phy_inita(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 tval;
+
+ if (phy->type == BCM43xx_PHYTYPE_A) {
+ bcm43xx_phy_setupa(bcm);
+ } else {
+ bcm43xx_phy_setupg(bcm);
+ if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+ bcm43xx_phy_write(bcm, 0x046E, 0x03CF);
+ return;
+ }
+
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
+ (bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) & 0xF83C) | 0x0340);
+ bcm43xx_phy_write(bcm, 0x0034, 0x0001);
+
+ TODO();//TODO: RSSI AGC
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
+ bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) | (1 << 14));
+ bcm43xx_radio_init2060(bcm);
+
+ if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM)
+ && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) {
+ if (radio->lofcal == 0xFFFF) {
+ TODO();//TODO: LOF Cal
+ bcm43xx_radio_set_tx_iq(bcm);
+ } else
+ bcm43xx_radio_write16(bcm, 0x001E, radio->lofcal);
+ }
+
+ bcm43xx_phy_write(bcm, 0x007A, 0xF111);
+
+ if (phy->savedpctlreg == 0xFFFF) {
+ bcm43xx_radio_write16(bcm, 0x0019, 0x0000);
+ bcm43xx_radio_write16(bcm, 0x0017, 0x0020);
+
+ tval = bcm43xx_ilt_read(bcm, 0x3001);
+ if (phy->rev == 1) {
+ bcm43xx_ilt_write(bcm, 0x3001,
+ (bcm43xx_ilt_read(bcm, 0x3001) & 0xFF87)
+ | 0x0058);
+ } else {
+ bcm43xx_ilt_write(bcm, 0x3001,
+ (bcm43xx_ilt_read(bcm, 0x3001) & 0xFFC3)
+ | 0x002C);
+ }
+ bcm43xx_dummy_transmission(bcm);
+ phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL);
+ bcm43xx_ilt_write(bcm, 0x3001, tval);
+
+ bcm43xx_radio_set_txpower_a(bcm, 0x0018);
+ }
+ bcm43xx_radio_clear_tssi(bcm);
+}
+
+static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 offset, val;
+
+ bcm43xx_write16(bcm, 0x03EC, 0x3F22);
+ bcm43xx_phy_write(bcm, 0x0020, 0x301C);
+ bcm43xx_phy_write(bcm, 0x0026, 0x0000);
+ bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
+ bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
+ val = 0x3C3D;
+ for (offset = 0x0089; offset < 0x00A7; offset++) {
+ bcm43xx_phy_write(bcm, offset, val);
+ val -= 0x0202;
+ }
+ bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
+ if (radio->channel == 0xFF)
+ bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+ else
+ bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
+ if (radio->version != 0x2050) {
+ bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
+ bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
+ }
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+ if (radio->version == 0x2050) {
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+ bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+ bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+ bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+ bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
+ bcm43xx_phy_write(bcm, 0x0038, 0x0677);
+ bcm43xx_radio_init2050(bcm);
+ }
+ bcm43xx_phy_write(bcm, 0x0014, 0x0080);
+ bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
+ bcm43xx_phy_write(bcm, 0x0032, 0x00CC);
+ bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
+ bcm43xx_phy_lo_b_measure(bcm);
+ bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
+ if (radio->version != 0x2050)
+ bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1000);
+ bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
+ if (radio->version != 0x2050)
+ bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+ bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+ bcm43xx_phy_init_pctl(bcm);
+}
+
+static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 offset, val;
+
+ bcm43xx_write16(bcm, 0x03EC, 0x3F22);
+ bcm43xx_phy_write(bcm, 0x0020, 0x301C);
+ bcm43xx_phy_write(bcm, 0x0026, 0x0000);
+ bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
+ bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
+ val = 0x3C3D;
+ for (offset = 0x0089; offset < 0x00A7; offset++) {
+ bcm43xx_phy_write(bcm, offset, val);
+ val -= 0x0202;
+ }
+ bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
+ if (radio->channel == 0xFF)
+ bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+ else
+ bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
+ if (radio->version != 0x2050) {
+ bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
+ bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
+ }
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+ if (radio->version == 0x2050) {
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+ bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+ bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+ bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+ bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
+ bcm43xx_phy_write(bcm, 0x0038, 0x0677);
+ bcm43xx_radio_init2050(bcm);
+ }
+ bcm43xx_phy_write(bcm, 0x0014, 0x0080);
+ bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
+ if (radio->version == 0x2050)
+ bcm43xx_phy_write(bcm, 0x0032, 0x00E0);
+ bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
+
+ bcm43xx_phy_lo_b_measure(bcm);
+
+ bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
+ if (radio->version == 0x2050)
+ bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1100);
+ bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
+ if (radio->version == 0x2050)
+ bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+ bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+ if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+ bcm43xx_calc_nrssi_slope(bcm);
+ bcm43xx_calc_nrssi_threshold(bcm);
+ }
+ bcm43xx_phy_init_pctl(bcm);
+}
+
+static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 offset;
+
+ if (phy->version == 1 &&
+ radio->version == 0x2050) {
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A)
+ | 0x0050);
+ }
+ if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) &&
+ (bcm->board_type != 0x0416)) {
+ for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
+ bcm43xx_phy_write(bcm, offset,
+ (bcm43xx_phy_read(bcm, offset) + 0x2020)
+ & 0x3F3F);
+ }
+ }
+ bcm43xx_phy_write(bcm, 0x0035,
+ (bcm43xx_phy_read(bcm, 0x0035) & 0xF0FF)
+ | 0x0700);
+ if (radio->version == 0x2050)
+ bcm43xx_phy_write(bcm, 0x0038, 0x0667);
+
+ if (phy->connected) {
+ if (radio->version == 0x2050) {
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A)
+ | 0x0020);
+ bcm43xx_radio_write16(bcm, 0x0051,
+ bcm43xx_radio_read16(bcm, 0x0051)
+ | 0x0004);
+ }
+ bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, 0x0000);
+
+ bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
+ bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
+
+ bcm43xx_phy_write(bcm, 0x001C, 0x186A);
+
+ bcm43xx_phy_write(bcm, 0x0013, (bcm43xx_phy_read(bcm, 0x0013) & 0x00FF) | 0x1900);
+ bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFFC0) | 0x0064);
+ bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) & 0xFF80) | 0x000A);
+ }
+
+ if (bcm->bad_frames_preempt) {
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+ bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11));
+ }
+
+ if (phy->version == 1 && radio->version == 0x2050) {
+ bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
+ bcm43xx_phy_write(bcm, 0x0021, 0x3763);
+ bcm43xx_phy_write(bcm, 0x0022, 0x1BC3);
+ bcm43xx_phy_write(bcm, 0x0023, 0x06F9);
+ bcm43xx_phy_write(bcm, 0x0024, 0x037E);
+ } else
+ bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
+ bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
+ bcm43xx_write16(bcm, 0x03EC, 0x3F22);
+
+ if (phy->version == 1 && radio->version == 0x2050)
+ bcm43xx_phy_write(bcm, 0x0020, 0x3E1C);
+ else
+ bcm43xx_phy_write(bcm, 0x0020, 0x301C);
+
+ if (phy->version == 0)
+ bcm43xx_write16(bcm, 0x03E4, 0x3000);
+
+ /* Force to channel 7, even if not supported. */
+ bcm43xx_radio_selectchannel(bcm, 7, 0);
+
+ if (radio->version != 0x2050) {
+ bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
+ bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
+ }
+
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+
+ if (radio->version == 0x2050) {
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+ bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+ }
+
+ bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+ bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+
+ bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007);
+
+ bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+
+ bcm43xx_phy_write(bcm, 0x0014, 0x0080);
+ bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
+ bcm43xx_phy_write(bcm, 0x88A3, 0x002A);
+
+ bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+
+ if (radio->version == 0x2050)
+ bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
+
+ bcm43xx_write16(bcm, 0x03E4, (bcm43xx_read16(bcm, 0x03E4) & 0xFFC0) | 0x0004);
+}
+
+static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 offset, val;
+
+ bcm43xx_phy_write(bcm, 0x003E, 0x817A);
+ bcm43xx_radio_write16(bcm, 0x007A,
+ (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058));
+ if ((radio->manufact == 0x17F) &&
+ (radio->version == 0x2050) &&
+ (radio->revision == 3 ||
+ radio->revision == 4 ||
+ radio->revision == 5)) {
+ bcm43xx_radio_write16(bcm, 0x0051, 0x001F);
+ bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
+ bcm43xx_radio_write16(bcm, 0x0053, 0x005B);
+ bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+ bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
+ bcm43xx_radio_write16(bcm, 0x005B, 0x0088);
+ bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
+ bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
+ bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
+ }
+ if ((radio->manufact == 0x17F) &&
+ (radio->version == 0x2050) &&
+ (radio->revision == 6)) {
+ bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
+ bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
+ bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
+ bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+ bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
+ bcm43xx_radio_write16(bcm, 0x005B, 0x008B);
+ bcm43xx_radio_write16(bcm, 0x005C, 0x00B5);
+ bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
+ bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
+ bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
+ bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
+ bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
+ }
+ if ((radio->manufact == 0x17F) &&
+ (radio->version == 0x2050) &&
+ (radio->revision == 7)) {
+ bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
+ bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
+ bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
+ bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+ bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
+ bcm43xx_radio_write16(bcm, 0x005B, 0x00A8);
+ bcm43xx_radio_write16(bcm, 0x005C, 0x0075);
+ bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
+ bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
+ bcm43xx_radio_write16(bcm, 0x007D, 0x00E8);
+ bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
+ bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
+ bcm43xx_radio_write16(bcm, 0x007B, 0x0000);
+ }
+ if ((radio->manufact == 0x17F) &&
+ (radio->version == 0x2050) &&
+ (radio->revision == 8)) {
+ bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
+ bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
+ bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
+ bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+ bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
+ bcm43xx_radio_write16(bcm, 0x005B, 0x006B);
+ bcm43xx_radio_write16(bcm, 0x005C, 0x000F);
+ if (bcm->sprom.boardflags & 0x8000) {
+ bcm43xx_radio_write16(bcm, 0x005D, 0x00FA);
+ bcm43xx_radio_write16(bcm, 0x005E, 0x00D8);
+ } else {
+ bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
+ bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
+ }
+ bcm43xx_radio_write16(bcm, 0x0073, 0x0003);
+ bcm43xx_radio_write16(bcm, 0x007D, 0x00A8);
+ bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
+ bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
+ }
+ val = 0x1E1F;
+ for (offset = 0x0088; offset < 0x0098; offset++) {
+ bcm43xx_phy_write(bcm, offset, val);
+ val -= 0x0202;
+ }
+ val = 0x3E3F;
+ for (offset = 0x0098; offset < 0x00A8; offset++) {
+ bcm43xx_phy_write(bcm, offset, val);
+ val -= 0x0202;
+ }
+ val = 0x2120;
+ for (offset = 0x00A8; offset < 0x00C8; offset++) {
+ bcm43xx_phy_write(bcm, offset, (val & 0x3F3F));
+ val += 0x0202;
+ }
+ if (phy->type == BCM43xx_PHYTYPE_G) {
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A) | 0x0020);
+ bcm43xx_radio_write16(bcm, 0x0051,
+ bcm43xx_radio_read16(bcm, 0x0051) | 0x0004);
+ bcm43xx_phy_write(bcm, 0x0802,
+ bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
+ bcm43xx_phy_write(bcm, 0x042B,
+ bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
+ }
+
+ /* Force to channel 7, even if not supported. */
+ bcm43xx_radio_selectchannel(bcm, 7, 0);
+
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+ udelay(40);
+ bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) | 0x0002));
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+ if (radio->manufact == 0x17F &&
+ radio->version == 0x2050 &&
+ radio->revision <= 2) {
+ bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+ bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+ bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+ bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+ }
+ bcm43xx_radio_write16(bcm, 0x007A,
+ (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007);
+
+ bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+
+ bcm43xx_phy_write(bcm, 0x0014, 0x0200);
+ if (radio->version == 0x2050){
+ if (radio->revision == 3 ||
+ radio->revision == 4 ||
+ radio->revision == 5)
+ bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
+ else
+ bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+ }
+ bcm43xx_phy_write(bcm, 0x0038, 0x0668);
+ bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+ if (radio->version == 0x2050) {
+ if (radio->revision == 3 ||
+ radio->revision == 4 ||
+ radio->revision == 5)
+ bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003);
+ else if (radio->revision <= 2)
+ bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
+ }
+
+ if (phy->rev == 4)
+ bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
+ else
+ bcm43xx_write16(bcm, 0x03E4, 0x0009);
+ if (phy->type == BCM43xx_PHYTYPE_B) {
+ bcm43xx_write16(bcm, 0x03E6, 0x8140);
+ bcm43xx_phy_write(bcm, 0x0016, 0x0410);
+ bcm43xx_phy_write(bcm, 0x0017, 0x0820);
+ bcm43xx_phy_write(bcm, 0x0062, 0x0007);
+ (void) bcm43xx_radio_calibrationvalue(bcm);
+ bcm43xx_phy_lo_b_measure(bcm);
+ if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+ bcm43xx_calc_nrssi_slope(bcm);
+ bcm43xx_calc_nrssi_threshold(bcm);
+ }
+ bcm43xx_phy_init_pctl(bcm);
+ } else
+ bcm43xx_write16(bcm, 0x03E6, 0x0);
+}
+
+static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 backup_phy[15];
+ u16 backup_radio[3];
+ u16 backup_bband;
+ u16 i;
+ u16 loop1_cnt, loop1_done, loop1_omitted;
+ u16 loop2_done;
+
+ backup_phy[0] = bcm43xx_phy_read(bcm, 0x0429);
+ backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001);
+ backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811);
+ backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812);
+ backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814);
+ backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815);
+ backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A);
+ backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059);
+ backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058);
+ backup_phy[9] = bcm43xx_phy_read(bcm, 0x000A);
+ backup_phy[10] = bcm43xx_phy_read(bcm, 0x0003);
+ backup_phy[11] = bcm43xx_phy_read(bcm, 0x080F);
+ backup_phy[12] = bcm43xx_phy_read(bcm, 0x0810);
+ backup_phy[13] = bcm43xx_phy_read(bcm, 0x002B);
+ backup_phy[14] = bcm43xx_phy_read(bcm, 0x0015);
+ bcm43xx_phy_read(bcm, 0x002D); /* dummy read */
+ backup_bband = radio->baseband_atten;
+ backup_radio[0] = bcm43xx_radio_read16(bcm, 0x0052);
+ backup_radio[1] = bcm43xx_radio_read16(bcm, 0x0043);
+ backup_radio[2] = bcm43xx_radio_read16(bcm, 0x007A);
+
+ bcm43xx_phy_write(bcm, 0x0429,
+ bcm43xx_phy_read(bcm, 0x0429) & 0x3FFF);
+ bcm43xx_phy_write(bcm, 0x0001,
+ bcm43xx_phy_read(bcm, 0x0001) & 0x8000);
+ bcm43xx_phy_write(bcm, 0x0811,
+ bcm43xx_phy_read(bcm, 0x0811) | 0x0002);
+ bcm43xx_phy_write(bcm, 0x0812,
+ bcm43xx_phy_read(bcm, 0x0812) & 0xFFFD);
+ bcm43xx_phy_write(bcm, 0x0811,
+ bcm43xx_phy_read(bcm, 0x0811) | 0x0001);
+ bcm43xx_phy_write(bcm, 0x0812,
+ bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE);
+ bcm43xx_phy_write(bcm, 0x0814,
+ bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
+ bcm43xx_phy_write(bcm, 0x0815,
+ bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
+ bcm43xx_phy_write(bcm, 0x0814,
+ bcm43xx_phy_read(bcm, 0x0814) | 0x0002);
+ bcm43xx_phy_write(bcm, 0x0815,
+ bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD);
+ bcm43xx_phy_write(bcm, 0x0811,
+ bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
+ bcm43xx_phy_write(bcm, 0x0812,
+ bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
+
+ bcm43xx_phy_write(bcm, 0x0811,
+ (bcm43xx_phy_read(bcm, 0x0811)
+ & 0xFFCF) | 0x0030);
+ bcm43xx_phy_write(bcm, 0x0812,
+ (bcm43xx_phy_read(bcm, 0x0812)
+ & 0xFFCF) | 0x0010);
+
+ bcm43xx_phy_write(bcm, 0x005A, 0x0780);
+ bcm43xx_phy_write(bcm, 0x0059, 0xC810);
+ bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+ if (phy->version == 0) {
+ bcm43xx_phy_write(bcm, 0x0003, 0x0122);
+ } else {
+ bcm43xx_phy_write(bcm, 0x000A,
+ bcm43xx_phy_read(bcm, 0x000A)
+ | 0x2000);
+ }
+ bcm43xx_phy_write(bcm, 0x0814,
+ bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
+ bcm43xx_phy_write(bcm, 0x0815,
+ bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
+ bcm43xx_phy_write(bcm, 0x0003,
+ (bcm43xx_phy_read(bcm, 0x0003)
+ & 0xFF9F) | 0x0040);
+ if (radio->version == 0x2050 && radio->revision == 2) {
+ bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
+ bcm43xx_radio_write16(bcm, 0x0043,
+ (bcm43xx_radio_read16(bcm, 0x0043)
+ & 0xFFF0) | 0x0009);
+ loop1_cnt = 9;
+ } else if (radio->revision == 8) {
+ bcm43xx_radio_write16(bcm, 0x0043, 0x000F);
+ loop1_cnt = 15;
+ } else
+ loop1_cnt = 0;
+
+ bcm43xx_phy_set_baseband_attenuation(bcm, 11);
+
+ if (phy->rev >= 3)
+ bcm43xx_phy_write(bcm, 0x080F, 0xC020);
+ else
+ bcm43xx_phy_write(bcm, 0x080F, 0x8020);
+ bcm43xx_phy_write(bcm, 0x0810, 0x0000);
+
+ bcm43xx_phy_write(bcm, 0x002B,
+ (bcm43xx_phy_read(bcm, 0x002B)
+ & 0xFFC0) | 0x0001);
+ bcm43xx_phy_write(bcm, 0x002B,
+ (bcm43xx_phy_read(bcm, 0x002B)
+ & 0xC0FF) | 0x0800);
+ bcm43xx_phy_write(bcm, 0x0811,
+ bcm43xx_phy_read(bcm, 0x0811) | 0x0100);
+ bcm43xx_phy_write(bcm, 0x0812,
+ bcm43xx_phy_read(bcm, 0x0812) & 0xCFFF);
+ if (bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) {
+ if (phy->rev >= 7) {
+ bcm43xx_phy_write(bcm, 0x0811,
+ bcm43xx_phy_read(bcm, 0x0811)
+ | 0x0800);
+ bcm43xx_phy_write(bcm, 0x0812,
+ bcm43xx_phy_read(bcm, 0x0812)
+ | 0x8000);
+ }
+ }
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A)
+ & 0x00F7);
+
+ for (i = 0; i < loop1_cnt; i++) {
+ bcm43xx_radio_write16(bcm, 0x0043, loop1_cnt);
+ bcm43xx_phy_write(bcm, 0x0812,
+ (bcm43xx_phy_read(bcm, 0x0812)
+ & 0xF0FF) | (i << 8));
+ bcm43xx_phy_write(bcm, 0x0015,
+ (bcm43xx_phy_read(bcm, 0x0015)
+ & 0x0FFF) | 0xA000);
+ bcm43xx_phy_write(bcm, 0x0015,
+ (bcm43xx_phy_read(bcm, 0x0015)
+ & 0x0FFF) | 0xF000);
+ udelay(20);
+ if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
+ break;
+ }
+ loop1_done = i;
+ loop1_omitted = loop1_cnt - loop1_done;
+
+ loop2_done = 0;
+ if (loop1_done >= 8) {
+ bcm43xx_phy_write(bcm, 0x0812,
+ bcm43xx_phy_read(bcm, 0x0812)
+ | 0x0030);
+ for (i = loop1_done - 8; i < 16; i++) {
+ bcm43xx_phy_write(bcm, 0x0812,
+ (bcm43xx_phy_read(bcm, 0x0812)
+ & 0xF0FF) | (i << 8));
+ bcm43xx_phy_write(bcm, 0x0015,
+ (bcm43xx_phy_read(bcm, 0x0015)
+ & 0x0FFF) | 0xA000);
+ bcm43xx_phy_write(bcm, 0x0015,
+ (bcm43xx_phy_read(bcm, 0x0015)
+ & 0x0FFF) | 0xF000);
+ udelay(20);
+ if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
+ break;
+ }
+ }
+
+ bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]);
+ bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]);
+ bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]);
+ bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]);
+ bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]);
+ bcm43xx_phy_write(bcm, 0x000A, backup_phy[9]);
+ bcm43xx_phy_write(bcm, 0x0003, backup_phy[10]);
+ bcm43xx_phy_write(bcm, 0x080F, backup_phy[11]);
+ bcm43xx_phy_write(bcm, 0x0810, backup_phy[12]);
+ bcm43xx_phy_write(bcm, 0x002B, backup_phy[13]);
+ bcm43xx_phy_write(bcm, 0x0015, backup_phy[14]);
+
+ bcm43xx_phy_set_baseband_attenuation(bcm, backup_bband);
+
+ bcm43xx_radio_write16(bcm, 0x0052, backup_radio[0]);
+ bcm43xx_radio_write16(bcm, 0x0043, backup_radio[1]);
+ bcm43xx_radio_write16(bcm, 0x007A, backup_radio[2]);
+
+ bcm43xx_phy_write(bcm, 0x0811, backup_phy[2] | 0x0003);
+ udelay(10);
+ bcm43xx_phy_write(bcm, 0x0811, backup_phy[2]);
+ bcm43xx_phy_write(bcm, 0x0812, backup_phy[3]);
+ bcm43xx_phy_write(bcm, 0x0429, backup_phy[0]);
+ bcm43xx_phy_write(bcm, 0x0001, backup_phy[1]);
+
+ phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11;
+ phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2;
+}
+
+static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 tmp;
+
+ if (phy->rev == 1)
+ bcm43xx_phy_initb5(bcm);
+ else if (phy->rev >= 2 && phy->rev <= 7)
+ bcm43xx_phy_initb6(bcm);
+ if (phy->rev >= 2 || phy->connected)
+ bcm43xx_phy_inita(bcm);
+
+ if (phy->rev >= 2) {
+ bcm43xx_phy_write(bcm, 0x0814, 0x0000);
+ bcm43xx_phy_write(bcm, 0x0815, 0x0000);
+ if (phy->rev == 2)
+ bcm43xx_phy_write(bcm, 0x0811, 0x0000);
+ else if (phy->rev >= 3)
+ bcm43xx_phy_write(bcm, 0x0811, 0x0400);
+ bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
+ if (phy->connected) {
+ tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
+ if (tmp < 6) {
+ bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
+ bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
+ if (tmp != 3) {
+ bcm43xx_phy_write(bcm, 0x04CC,
+ (bcm43xx_phy_read(bcm, 0x04CC)
+ & 0x00FF) | 0x1F00);
+ }
+ }
+ }
+ }
+ if (phy->rev < 3 && phy->connected)
+ bcm43xx_phy_write(bcm, 0x047E, 0x0078);
+ if (phy->rev >= 6 && phy->rev <= 8) {
+ bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080);
+ bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004);
+ }
+ if (phy->rev >= 2 && phy->connected)
+ bcm43xx_calc_loopback_gain(bcm);
+ if (radio->revision != 8) {
+ if (radio->initval == 0xFFFF)
+ radio->initval = bcm43xx_radio_init2050(bcm);
+ else
+ bcm43xx_radio_write16(bcm, 0x0078, radio->initval);
+ }
+ if (radio->txctl2 == 0xFFFF) {
+ bcm43xx_phy_lo_g_measure(bcm);
+ } else {
+ if (radio->version == 0x2050 && radio->revision == 8) {
+ //FIXME
+ } else {
+ bcm43xx_radio_write16(bcm, 0x0052,
+ (bcm43xx_radio_read16(bcm, 0x0052)
+ & 0xFFF0) | radio->txctl1);
+ }
+ if (phy->rev >= 6) {
+ /*
+ bcm43xx_phy_write(bcm, 0x0036,
+ (bcm43xx_phy_read(bcm, 0x0036)
+ & 0xF000) | (FIXME << 12));
+ */
+ }
+ if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+ bcm43xx_phy_write(bcm, 0x002E, 0x8075);
+ else
+ bcm43xx_phy_write(bcm, 0x003E, 0x807F);
+ if (phy->rev < 2)
+ bcm43xx_phy_write(bcm, 0x002F, 0x0101);
+ else
+ bcm43xx_phy_write(bcm, 0x002F, 0x0202);
+ }
+ if (phy->connected) {
+ bcm43xx_phy_lo_adjust(bcm, 0);
+ bcm43xx_phy_write(bcm, 0x080F, 0x8078);
+ }
+
+ if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
+ /* The specs state to update the NRSSI LT with
+ * the value 0x7FFFFFFF here. I think that is some weird
+ * compiler optimization in the original driver.
+ * Essentially, what we do here is resetting all NRSSI LT
+ * entries to -32 (see the limit_value() in nrssi_hw_update())
+ */
+ bcm43xx_nrssi_hw_update(bcm, 0xFFFF);
+ bcm43xx_calc_nrssi_threshold(bcm);
+ } else if (phy->connected) {
+ if (radio->nrssi[0] == -1000) {
+ assert(radio->nrssi[1] == -1000);
+ bcm43xx_calc_nrssi_slope(bcm);
+ } else {
+ assert(radio->nrssi[1] != -1000);
+ bcm43xx_calc_nrssi_threshold(bcm);
+ }
+ }
+ if (radio->revision == 8)
+ bcm43xx_phy_write(bcm, 0x0805, 0x3230);
+ bcm43xx_phy_init_pctl(bcm);
+ if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) {
+ bcm43xx_phy_write(bcm, 0x0429,
+ bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF);
+ bcm43xx_phy_write(bcm, 0x04C3,
+ bcm43xx_phy_read(bcm, 0x04C3) & 0x7FFF);
+ }
+}
+
+static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
+{
+ int i;
+ u16 ret = 0;
+
+ for (i = 0; i < 10; i++){
+ bcm43xx_phy_write(bcm, 0x0015, 0xAFA0);
+ udelay(1);
+ bcm43xx_phy_write(bcm, 0x0015, 0xEFA0);
+ udelay(10);
+ bcm43xx_phy_write(bcm, 0x0015, 0xFFA0);
+ udelay(40);
+ ret += bcm43xx_phy_read(bcm, 0x002C);
+ }
+
+ return ret;
+}
+
+void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u16 regstack[12] = { 0 };
+ u16 mls;
+ u16 fval;
+ int i, j;
+
+ regstack[0] = bcm43xx_phy_read(bcm, 0x0015);
+ regstack[1] = bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0;
+
+ if (radio->version == 0x2053) {
+ regstack[2] = bcm43xx_phy_read(bcm, 0x000A);
+ regstack[3] = bcm43xx_phy_read(bcm, 0x002A);
+ regstack[4] = bcm43xx_phy_read(bcm, 0x0035);
+ regstack[5] = bcm43xx_phy_read(bcm, 0x0003);
+ regstack[6] = bcm43xx_phy_read(bcm, 0x0001);
+ regstack[7] = bcm43xx_phy_read(bcm, 0x0030);
+
+ regstack[8] = bcm43xx_radio_read16(bcm, 0x0043);
+ regstack[9] = bcm43xx_radio_read16(bcm, 0x007A);
+ regstack[10] = bcm43xx_read16(bcm, 0x03EC);
+ regstack[11] = bcm43xx_radio_read16(bcm, 0x0052) & 0x00F0;
+
+ bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
+ bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
+ bcm43xx_phy_write(bcm, 0x0035, regstack[4] & 0xFF7F);
+ bcm43xx_radio_write16(bcm, 0x007A, regstack[9] & 0xFFF0);
+ }
+ bcm43xx_phy_write(bcm, 0x0015, 0xB000);
+ bcm43xx_phy_write(bcm, 0x002B, 0x0004);
+
+ if (radio->version == 0x2053) {
+ bcm43xx_phy_write(bcm, 0x002B, 0x0203);
+ bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
+ }
+
+ phy->minlowsig[0] = 0xFFFF;
+
+ for (i = 0; i < 4; i++) {
+ bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
+ bcm43xx_phy_lo_b_r15_loop(bcm);
+ }
+ for (i = 0; i < 10; i++) {
+ bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
+ mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
+ if (mls < phy->minlowsig[0]) {
+ phy->minlowsig[0] = mls;
+ phy->minlowsigpos[0] = i;
+ }
+ }
+ bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | phy->minlowsigpos[0]);
+
+ phy->minlowsig[1] = 0xFFFF;
+
+ for (i = -4; i < 5; i += 2) {
+ for (j = -4; j < 5; j += 2) {
+ if (j < 0)
+ fval = (0x0100 * i) + j + 0x0100;
+ else
+ fval = (0x0100 * i) + j;
+ bcm43xx_phy_write(bcm, 0x002F, fval);
+ mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
+ if (mls < phy->minlowsig[1]) {
+ phy->minlowsig[1] = mls;
+ phy->minlowsigpos[1] = fval;
+ }
+ }
+ }
+ phy->minlowsigpos[1] += 0x0101;
+
+ bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]);
+ if (radio->version == 0x2053) {
+ bcm43xx_phy_write(bcm, 0x000A, regstack[2]);
+ bcm43xx_phy_write(bcm, 0x002A, regstack[3]);
+ bcm43xx_phy_write(bcm, 0x0035, regstack[4]);
+ bcm43xx_phy_write(bcm, 0x0003, regstack[5]);
+ bcm43xx_phy_write(bcm, 0x0001, regstack[6]);
+ bcm43xx_phy_write(bcm, 0x0030, regstack[7]);
+
+ bcm43xx_radio_write16(bcm, 0x0043, regstack[8]);
+ bcm43xx_radio_write16(bcm, 0x007A, regstack[9]);
+
+ bcm43xx_radio_write16(bcm, 0x0052,
+ (bcm43xx_radio_read16(bcm, 0x0052) & 0x000F)
+ | regstack[11]);
+
+ bcm43xx_write16(bcm, 0x03EC, regstack[10]);
+ }
+ bcm43xx_phy_write(bcm, 0x0015, regstack[0]);
+}
+
+static inline
+u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+ if (phy->connected) {
+ bcm43xx_phy_write(bcm, 0x15, 0xE300);
+ control <<= 8;
+ bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0);
+ udelay(5);
+ bcm43xx_phy_write(bcm, 0x0812, control | 0x00B2);
+ udelay(2);
+ bcm43xx_phy_write(bcm, 0x0812, control | 0x00B3);
+ udelay(4);
+ bcm43xx_phy_write(bcm, 0x0015, 0xF300);
+ udelay(8);
+ } else {
+ bcm43xx_phy_write(bcm, 0x0015, control | 0xEFA0);
+ udelay(2);
+ bcm43xx_phy_write(bcm, 0x0015, control | 0xEFE0);
+ udelay(4);
+ bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0);
+ udelay(8);
+ }
+
+ return bcm43xx_phy_read(bcm, 0x002D);
+}
+
+static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control)
+{
+ int i;
+ u32 ret = 0;
+
+ for (i = 0; i < 8; i++)
+ ret += bcm43xx_phy_lo_g_deviation_subval(bcm, control);
+
+ return ret;
+}
+
+/* Write the LocalOscillator CONTROL */
+static inline
+void bcm43xx_lo_write(struct bcm43xx_private *bcm,
+ struct bcm43xx_lopair *pair)
+{
+ u16 value;
+
+ value = (u8)(pair->low);
+ value |= ((u8)(pair->high)) << 8;
+
+#ifdef CONFIG_BCM43XX_DEBUG
+ /* Sanity check. */
+ if (pair->low < -8 || pair->low > 8 ||
+ pair->high < -8 || pair->high > 8) {
+ printk(KERN_WARNING PFX
+ "WARNING: Writing invalid LOpair "
+ "(low: %d, high: %d, index: %lu)\n",
+ pair->low, pair->high,
+ (unsigned long)(pair - bcm43xx_current_phy(bcm)->_lo_pairs));
+ dump_stack();
+ }
+#endif
+
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, value);
+}
+
+static inline
+struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm,
+ u16 baseband_attenuation,
+ u16 radio_attenuation,
+ u16 tx)
+{
+ static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+ if (baseband_attenuation > 6)
+ baseband_attenuation = 6;
+ assert(radio_attenuation < 10);
+
+ if (tx == 3) {
+ return bcm43xx_get_lopair(phy,
+ radio_attenuation,
+ baseband_attenuation);
+ }
+ return bcm43xx_get_lopair(phy, dict[radio_attenuation], baseband_attenuation);
+}
+
+static inline
+struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+ return bcm43xx_find_lopair(bcm,
+ radio->baseband_atten,
+ radio->radio_atten,
+ radio->txctl1);
+}
+
+/* Adjust B/G LO */
+void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed)
+{
+ struct bcm43xx_lopair *pair;
+
+ if (fixed) {
+ /* Use fixed values. Only for initialization. */
+ pair = bcm43xx_find_lopair(bcm, 2, 3, 0);
+ } else
+ pair = bcm43xx_current_lopair(bcm);
+ bcm43xx_lo_write(bcm, pair);
+}
+
+static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 txctl2 = 0, i;
+ u32 smallest, tmp;
+
+ bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
+ udelay(10);
+ smallest = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
+ for (i = 0; i < 16; i++) {
+ bcm43xx_radio_write16(bcm, 0x0052, i);
+ udelay(10);
+ tmp = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
+ if (tmp < smallest) {
+ smallest = tmp;
+ txctl2 = i;
+ }
+ }
+ radio->txctl2 = txctl2;
+}
+
+static
+void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm,
+ const struct bcm43xx_lopair *in_pair,
+ struct bcm43xx_lopair *out_pair,
+ u16 r27)
+{
+ static const struct bcm43xx_lopair transitions[8] = {
+ { .high = 1, .low = 1, },
+ { .high = 1, .low = 0, },
+ { .high = 1, .low = -1, },
+ { .high = 0, .low = -1, },
+ { .high = -1, .low = -1, },
+ { .high = -1, .low = 0, },
+ { .high = -1, .low = 1, },
+ { .high = 0, .low = 1, },
+ };
+ struct bcm43xx_lopair lowest_transition = {
+ .high = in_pair->high,
+ .low = in_pair->low,
+ };
+ struct bcm43xx_lopair tmp_pair;
+ struct bcm43xx_lopair transition;
+ int i = 12;
+ int state = 0;
+ int found_lower;
+ int j, begin, end;
+ u32 lowest_deviation;
+ u32 tmp;
+
+ /* Note that in_pair and out_pair can point to the same pair. Be careful. */
+
+ bcm43xx_lo_write(bcm, &lowest_transition);
+ lowest_deviation = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
+ do {
+ found_lower = 0;
+ assert(state >= 0 && state <= 8);
+ if (state == 0) {
+ begin = 1;
+ end = 8;
+ } else if (state % 2 == 0) {
+ begin = state - 1;
+ end = state + 1;
+ } else {
+ begin = state - 2;
+ end = state + 2;
+ }
+ if (begin < 1)
+ begin += 8;
+ if (end > 8)
+ end -= 8;
+
+ j = begin;
+ tmp_pair.high = lowest_transition.high;
+ tmp_pair.low = lowest_transition.low;
+ while (1) {
+ assert(j >= 1 && j <= 8);
+ transition.high = tmp_pair.high + transitions[j - 1].high;
+ transition.low = tmp_pair.low + transitions[j - 1].low;
+ if ((abs(transition.low) < 9) && (abs(transition.high) < 9)) {
+ bcm43xx_lo_write(bcm, &transition);
+ tmp = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
+ if (tmp < lowest_deviation) {
+ lowest_deviation = tmp;
+ state = j;
+ found_lower = 1;
+
+ lowest_transition.high = transition.high;
+ lowest_transition.low = transition.low;
+ }
+ }
+ if (j == end)
+ break;
+ if (j == 8)
+ j = 1;
+ else
+ j++;
+ }
+ } while (i-- && found_lower);
+
+ out_pair->high = lowest_transition.high;
+ out_pair->low = lowest_transition.low;
+}
+
+/* Set the baseband attenuation value on chip. */
+void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
+ u16 baseband_attenuation)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u16 value;
+
+ if (phy->version == 0) {
+ value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0);
+ value |= (baseband_attenuation & 0x000F);
+ bcm43xx_write16(bcm, 0x03E6, value);
+ return;
+ }
+
+ if (phy->version > 1) {
+ value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
+ value |= (baseband_attenuation << 2) & 0x003C;
+ } else {
+ value = bcm43xx_phy_read(bcm, 0x0060) & ~0x0078;
+ value |= (baseband_attenuation << 3) & 0x0078;
+ }
+ bcm43xx_phy_write(bcm, 0x0060, value);
+}
+
+/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */
+void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
+{
+ static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
+ const int is_initializing = bcm43xx_is_initializing(bcm);
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 h, i, oldi = 0, j;
+ struct bcm43xx_lopair control;
+ struct bcm43xx_lopair *tmp_control;
+ u16 tmp;
+ u16 regstack[16] = { 0 };
+ u8 oldchannel;
+
+ //XXX: What are these?
+ u8 r27 = 0, r31;
+
+ oldchannel = radio->channel;
+ /* Setup */
+ if (phy->connected) {
+ regstack[0] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
+ regstack[1] = bcm43xx_phy_read(bcm, 0x0802);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
+ bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
+ }
+ regstack[3] = bcm43xx_read16(bcm, 0x03E2);
+ bcm43xx_write16(bcm, 0x03E2, regstack[3] | 0x8000);
+ regstack[4] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+ regstack[5] = bcm43xx_phy_read(bcm, 0x15);
+ regstack[6] = bcm43xx_phy_read(bcm, 0x2A);
+ regstack[7] = bcm43xx_phy_read(bcm, 0x35);
+ regstack[8] = bcm43xx_phy_read(bcm, 0x60);
+ regstack[9] = bcm43xx_radio_read16(bcm, 0x43);
+ regstack[10] = bcm43xx_radio_read16(bcm, 0x7A);
+ regstack[11] = bcm43xx_radio_read16(bcm, 0x52);
+ if (phy->connected) {
+ regstack[12] = bcm43xx_phy_read(bcm, 0x0811);
+ regstack[13] = bcm43xx_phy_read(bcm, 0x0812);
+ regstack[14] = bcm43xx_phy_read(bcm, 0x0814);
+ regstack[15] = bcm43xx_phy_read(bcm, 0x0815);
+ }
+ bcm43xx_radio_selectchannel(bcm, 6, 0);
+ if (phy->connected) {
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
+ bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
+ bcm43xx_dummy_transmission(bcm);
+ }
+ bcm43xx_radio_write16(bcm, 0x0043, 0x0006);
+
+ bcm43xx_phy_set_baseband_attenuation(bcm, 2);
+
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x0000);
+ bcm43xx_phy_write(bcm, 0x002E, 0x007F);
+ bcm43xx_phy_write(bcm, 0x080F, 0x0078);
+ bcm43xx_phy_write(bcm, 0x0035, regstack[7] & ~(1 << 7));
+ bcm43xx_radio_write16(bcm, 0x007A, regstack[10] & 0xFFF0);
+ bcm43xx_phy_write(bcm, 0x002B, 0x0203);
+ bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
+ if (phy->connected) {
+ bcm43xx_phy_write(bcm, 0x0814, regstack[14] | 0x0003);
+ bcm43xx_phy_write(bcm, 0x0815, regstack[15] & 0xFFFC);
+ bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
+ bcm43xx_phy_write(bcm, 0x0812, 0x00B2);
+ }
+ if (is_initializing)
+ bcm43xx_phy_lo_g_measure_txctl2(bcm);
+ bcm43xx_phy_write(bcm, 0x080F, 0x8078);
+
+ /* Measure */
+ control.low = 0;
+ control.high = 0;
+ for (h = 0; h < 10; h++) {
+ /* Loop over each possible RadioAttenuation (0-9) */
+ i = pairorder[h];
+ if (is_initializing) {
+ if (i == 3) {
+ control.low = 0;
+ control.high = 0;
+ } else if (((i % 2 == 1) && (oldi % 2 == 1)) ||
+ ((i % 2 == 0) && (oldi % 2 == 0))) {
+ tmp_control = bcm43xx_get_lopair(phy, oldi, 0);
+ memcpy(&control, tmp_control, sizeof(control));
+ } else {
+ tmp_control = bcm43xx_get_lopair(phy, 3, 0);
+ memcpy(&control, tmp_control, sizeof(control));
+ }
+ }
+ /* Loop over each possible BasebandAttenuation/2 */
+ for (j = 0; j < 4; j++) {
+ if (is_initializing) {
+ tmp = i * 2 + j;
+ r27 = 0;
+ r31 = 0;
+ if (tmp > 14) {
+ r31 = 1;
+ if (tmp > 17)
+ r27 = 1;
+ if (tmp > 19)
+ r27 = 2;
+ }
+ } else {
+ tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
+ if (!tmp_control->used)
+ continue;
+ memcpy(&control, tmp_control, sizeof(control));
+ r27 = 3;
+ r31 = 0;
+ }
+ bcm43xx_radio_write16(bcm, 0x43, i);
+ bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
+ udelay(10);
+
+ bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
+
+ tmp = (regstack[10] & 0xFFF0);
+ if (r31)
+ tmp |= 0x0008;
+ bcm43xx_radio_write16(bcm, 0x007A, tmp);
+
+ tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
+ bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
+ }
+ oldi = i;
+ }
+ /* Loop over each possible RadioAttenuation (10-13) */
+ for (i = 10; i < 14; i++) {
+ /* Loop over each possible BasebandAttenuation/2 */
+ for (j = 0; j < 4; j++) {
+ if (is_initializing) {
+ tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
+ memcpy(&control, tmp_control, sizeof(control));
+ tmp = (i - 9) * 2 + j - 5;//FIXME: This is wrong, as the following if statement can never trigger.
+ r27 = 0;
+ r31 = 0;
+ if (tmp > 14) {
+ r31 = 1;
+ if (tmp > 17)
+ r27 = 1;
+ if (tmp > 19)
+ r27 = 2;
+ }
+ } else {
+ tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
+ if (!tmp_control->used)
+ continue;
+ memcpy(&control, tmp_control, sizeof(control));
+ r27 = 3;
+ r31 = 0;
+ }
+ bcm43xx_radio_write16(bcm, 0x43, i - 9);
+ bcm43xx_radio_write16(bcm, 0x52,
+ radio->txctl2
+ | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
+ udelay(10);
+
+ bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
+
+ tmp = (regstack[10] & 0xFFF0);
+ if (r31)
+ tmp |= 0x0008;
+ bcm43xx_radio_write16(bcm, 0x7A, tmp);
+
+ tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
+ bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
+ }
+ }
+
+ /* Restoration */
+ if (phy->connected) {
+ bcm43xx_phy_write(bcm, 0x0015, 0xE300);
+ bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA0);
+ udelay(5);
+ bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2);
+ udelay(2);
+ bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3);
+ } else
+ bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0);
+ bcm43xx_phy_lo_adjust(bcm, is_initializing);
+ bcm43xx_phy_write(bcm, 0x002E, 0x807F);
+ if (phy->connected)
+ bcm43xx_phy_write(bcm, 0x002F, 0x0202);
+ else
+ bcm43xx_phy_write(bcm, 0x002F, 0x0101);
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, regstack[4]);
+ bcm43xx_phy_write(bcm, 0x0015, regstack[5]);
+ bcm43xx_phy_write(bcm, 0x002A, regstack[6]);
+ bcm43xx_phy_write(bcm, 0x0035, regstack[7]);
+ bcm43xx_phy_write(bcm, 0x0060, regstack[8]);
+ bcm43xx_radio_write16(bcm, 0x0043, regstack[9]);
+ bcm43xx_radio_write16(bcm, 0x007A, regstack[10]);
+ regstack[11] &= 0x00F0;
+ regstack[11] |= (bcm43xx_radio_read16(bcm, 0x52) & 0x000F);
+ bcm43xx_radio_write16(bcm, 0x52, regstack[11]);
+ bcm43xx_write16(bcm, 0x03E2, regstack[3]);
+ if (phy->connected) {
+ bcm43xx_phy_write(bcm, 0x0811, regstack[12]);
+ bcm43xx_phy_write(bcm, 0x0812, regstack[13]);
+ bcm43xx_phy_write(bcm, 0x0814, regstack[14]);
+ bcm43xx_phy_write(bcm, 0x0815, regstack[15]);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0]);
+ bcm43xx_phy_write(bcm, 0x0802, regstack[1]);
+ }
+ bcm43xx_radio_selectchannel(bcm, oldchannel, 1);
+
+#ifdef CONFIG_BCM43XX_DEBUG
+ {
+ /* Sanity check for all lopairs. */
+ for (i = 0; i < BCM43xx_LO_COUNT; i++) {
+ tmp_control = phy->_lo_pairs + i;
+ if (tmp_control->low < -8 || tmp_control->low > 8 ||
+ tmp_control->high < -8 || tmp_control->high > 8) {
+ printk(KERN_WARNING PFX
+ "WARNING: Invalid LOpair (low: %d, high: %d, index: %d)\n",
+ tmp_control->low, tmp_control->high, i);
+ }
+ }
+ }
+#endif /* CONFIG_BCM43XX_DEBUG */
+}
+
+static
+void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_lopair *pair;
+
+ pair = bcm43xx_current_lopair(bcm);
+ pair->used = 1;
+}
+
+void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_lopair *pair;
+ int i;
+
+ for (i = 0; i < BCM43xx_LO_COUNT; i++) {
+ pair = phy->_lo_pairs + i;
+ pair->used = 0;
+ }
+}
+
+/* http://bcm-specs.sipsolutions.net/EstimatePowerOut
+ * This function converts a TSSI value to dBm in Q5.2
+ */
+static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ s8 dbm = 0;
+ s32 tmp;
+
+ tmp = phy->idle_tssi;
+ tmp += tssi;
+ tmp -= phy->savedpctlreg;
+
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ tmp += 0x80;
+ tmp = limit_value(tmp, 0x00, 0xFF);
+ dbm = phy->tssi2dbm[tmp];
+ TODO(); //TODO: There's a FIXME on the specs
+ break;
+ case BCM43xx_PHYTYPE_B:
+ case BCM43xx_PHYTYPE_G:
+ tmp = limit_value(tmp, 0x00, 0x3F);
+ dbm = phy->tssi2dbm[tmp];
+ break;
+ default:
+ assert(0);
+ }
+
+ return dbm;
+}
+
+/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */
+void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+ if (phy->savedpctlreg == 0xFFFF)
+ return;
+ if ((bcm->board_type == 0x0416) &&
+ (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM))
+ return;
+
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A: {
+
+ TODO(); //TODO: Nothing for A PHYs yet :-/
+
+ break;
+ }
+ case BCM43xx_PHYTYPE_B:
+ case BCM43xx_PHYTYPE_G: {
+ u16 tmp;
+ u16 txpower;
+ s8 v0, v1, v2, v3;
+ s8 average;
+ u8 max_pwr;
+ s16 desired_pwr, estimated_pwr, pwr_adjust;
+ s16 radio_att_delta, baseband_att_delta;
+ s16 radio_attenuation, baseband_attenuation;
+ unsigned long phylock_flags;
+
+ tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0058);
+ v0 = (s8)(tmp & 0x00FF);
+ v1 = (s8)((tmp & 0xFF00) >> 8);
+ tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005A);
+ v2 = (s8)(tmp & 0x00FF);
+ v3 = (s8)((tmp & 0xFF00) >> 8);
+ tmp = 0;
+
+ if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) {
+ tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0070);
+ v0 = (s8)(tmp & 0x00FF);
+ v1 = (s8)((tmp & 0xFF00) >> 8);
+ tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0072);
+ v2 = (s8)(tmp & 0x00FF);
+ v3 = (s8)((tmp & 0xFF00) >> 8);
+ if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F)
+ return;
+ v0 = (v0 + 0x20) & 0x3F;
+ v1 = (v1 + 0x20) & 0x3F;
+ v2 = (v2 + 0x20) & 0x3F;
+ v3 = (v3 + 0x20) & 0x3F;
+ tmp = 1;
+ }
+ bcm43xx_radio_clear_tssi(bcm);
+
+ average = (v0 + v1 + v2 + v3 + 2) / 4;
+
+ if (tmp && (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005E) & 0x8))
+ average -= 13;
+
+ estimated_pwr = bcm43xx_phy_estimate_power_out(bcm, average);
+
+ max_pwr = bcm->sprom.maxpower_bgphy;
+
+ if ((bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) &&
+ (phy->type == BCM43xx_PHYTYPE_G))
+ max_pwr -= 0x3;
+
+ /*TODO:
+ max_pwr = min(REG - bcm->sprom.antennagain_bgphy - 0x6, max_pwr)
+ where REG is the max power as per the regulatory domain
+ */
+
+ desired_pwr = limit_value(radio->txpower_desired, 0, max_pwr);
+ /* Check if we need to adjust the current power. */
+ pwr_adjust = desired_pwr - estimated_pwr;
+ radio_att_delta = -(pwr_adjust + 7) >> 3;
+ baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta);
+ if ((radio_att_delta == 0) && (baseband_att_delta == 0)) {
+ bcm43xx_phy_lo_mark_current_used(bcm);
+ return;
+ }
+
+ /* Calculate the new attenuation values. */
+ baseband_attenuation = radio->baseband_atten;
+ baseband_attenuation += baseband_att_delta;
+ radio_attenuation = radio->radio_atten;
+ radio_attenuation += radio_att_delta;
+
+ /* Get baseband and radio attenuation values into their permitted ranges.
+ * baseband 0-11, radio 0-9.
+ * Radio attenuation affects power level 4 times as much as baseband.
+ */
+ if (radio_attenuation < 0) {
+ baseband_attenuation -= (4 * -radio_attenuation);
+ radio_attenuation = 0;
+ } else if (radio_attenuation > 9) {
+ baseband_attenuation += (4 * (radio_attenuation - 9));
+ radio_attenuation = 9;
+ } else {
+ while (baseband_attenuation < 0 && radio_attenuation > 0) {
+ baseband_attenuation += 4;
+ radio_attenuation--;
+ }
+ while (baseband_attenuation > 11 && radio_attenuation < 9) {
+ baseband_attenuation -= 4;
+ radio_attenuation++;
+ }
+ }
+ baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
+
+ txpower = radio->txctl1;
+ if ((radio->version == 0x2050) && (radio->revision == 2)) {
+ if (radio_attenuation <= 1) {
+ if (txpower == 0) {
+ txpower = 3;
+ radio_attenuation += 2;
+ baseband_attenuation += 2;
+ } else if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
+ baseband_attenuation += 4 * (radio_attenuation - 2);
+ radio_attenuation = 2;
+ }
+ } else if (radio_attenuation > 4 && txpower != 0) {
+ txpower = 0;
+ if (baseband_attenuation < 3) {
+ radio_attenuation -= 3;
+ baseband_attenuation += 2;
+ } else {
+ radio_attenuation -= 2;
+ baseband_attenuation -= 2;
+ }
+ }
+ }
+ radio->txctl1 = txpower;
+ baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
+ radio_attenuation = limit_value(radio_attenuation, 0, 9);
+
+ bcm43xx_phy_lock(bcm, phylock_flags);
+ bcm43xx_radio_lock(bcm);
+ bcm43xx_radio_set_txpower_bg(bcm, baseband_attenuation,
+ radio_attenuation, txpower);
+ bcm43xx_phy_lo_mark_current_used(bcm);
+ bcm43xx_radio_unlock(bcm);
+ bcm43xx_phy_unlock(bcm, phylock_flags);
+ break;
+ }
+ default:
+ assert(0);
+ }
+}
+
+static inline
+s32 bcm43xx_tssi2dbm_ad(s32 num, s32 den)
+{
+ if (num < 0)
+ return num/den;
+ else
+ return (num+den/2)/den;
+}
+
+static inline
+s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2)
+{
+ s32 m1, m2, f = 256, q, delta;
+ s8 i = 0;
+
+ m1 = bcm43xx_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
+ m2 = max(bcm43xx_tssi2dbm_ad(32768 + index * pab2, 256), 1);
+ do {
+ if (i > 15)
+ return -EINVAL;
+ q = bcm43xx_tssi2dbm_ad(f * 4096 -
+ bcm43xx_tssi2dbm_ad(m2 * f, 16) * f, 2048);
+ delta = abs(q - f);
+ f = q;
+ i++;
+ } while (delta >= 2);
+ entry[index] = limit_value(bcm43xx_tssi2dbm_ad(m1 * f, 8192), -127, 128);
+ return 0;
+}
+
+/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */
+int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ s16 pab0, pab1, pab2;
+ u8 idx;
+ s8 *dyn_tssi2dbm;
+
+ if (phy->type == BCM43xx_PHYTYPE_A) {
+ pab0 = (s16)(bcm->sprom.pa1b0);
+ pab1 = (s16)(bcm->sprom.pa1b1);
+ pab2 = (s16)(bcm->sprom.pa1b2);
+ } else {
+ pab0 = (s16)(bcm->sprom.pa0b0);
+ pab1 = (s16)(bcm->sprom.pa0b1);
+ pab2 = (s16)(bcm->sprom.pa0b2);
+ }
+
+ if ((bcm->chip_id == 0x4301) && (radio->version != 0x2050)) {
+ phy->idle_tssi = 0x34;
+ phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
+ return 0;
+ }
+
+ if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
+ pab0 != -1 && pab1 != -1 && pab2 != -1) {
+ /* The pabX values are set in SPROM. Use them. */
+ if (phy->type == BCM43xx_PHYTYPE_A) {
+ if ((s8)bcm->sprom.idle_tssi_tgt_aphy != 0 &&
+ (s8)bcm->sprom.idle_tssi_tgt_aphy != -1)
+ phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_aphy);
+ else
+ phy->idle_tssi = 62;
+ } else {
+ if ((s8)bcm->sprom.idle_tssi_tgt_bgphy != 0 &&
+ (s8)bcm->sprom.idle_tssi_tgt_bgphy != -1)
+ phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_bgphy);
+ else
+ phy->idle_tssi = 62;
+ }
+ dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
+ if (dyn_tssi2dbm == NULL) {
+ printk(KERN_ERR PFX "Could not allocate memory"
+ "for tssi2dbm table\n");
+ return -ENOMEM;
+ }
+ for (idx = 0; idx < 64; idx++)
+ if (bcm43xx_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, pab1, pab2)) {
+ phy->tssi2dbm = NULL;
+ printk(KERN_ERR PFX "Could not generate "
+ "tssi2dBm table\n");
+ kfree(dyn_tssi2dbm);
+ return -ENODEV;
+ }
+ phy->tssi2dbm = dyn_tssi2dbm;
+ phy->dyn_tssi_tbl = 1;
+ } else {
+ /* pabX values not set in SPROM. */
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ /* APHY needs a generated table. */
+ phy->tssi2dbm = NULL;
+ printk(KERN_ERR PFX "Could not generate tssi2dBm "
+ "table (wrong SPROM info)!\n");
+ return -ENODEV;
+ case BCM43xx_PHYTYPE_B:
+ phy->idle_tssi = 0x34;
+ phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
+ break;
+ case BCM43xx_PHYTYPE_G:
+ phy->idle_tssi = 0x34;
+ phy->tssi2dbm = bcm43xx_tssi2dbm_g_table;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int bcm43xx_phy_init(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ int err = -ENODEV;
+ unsigned long flags;
+
+ /* We do not want to be preempted while calibrating
+ * the hardware.
+ */
+ local_irq_save(flags);
+
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ if (phy->rev == 2 || phy->rev == 3) {
+ bcm43xx_phy_inita(bcm);
+ err = 0;
+ }
+ break;
+ case BCM43xx_PHYTYPE_B:
+ switch (phy->rev) {
+ case 2:
+ bcm43xx_phy_initb2(bcm);
+ err = 0;
+ break;
+ case 4:
+ bcm43xx_phy_initb4(bcm);
+ err = 0;
+ break;
+ case 5:
+ bcm43xx_phy_initb5(bcm);
+ err = 0;
+ break;
+ case 6:
+ bcm43xx_phy_initb6(bcm);
+ err = 0;
+ break;
+ }
+ break;
+ case BCM43xx_PHYTYPE_G:
+ bcm43xx_phy_initg(bcm);
+ err = 0;
+ break;
+ }
+ local_irq_restore(flags);
+ if (err)
+ printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");
+
+ return err;
+}
+
+void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u16 antennadiv;
+ u16 offset;
+ u16 value;
+ u32 ucodeflags;
+
+ antennadiv = phy->antenna_diversity;
+
+ if (antennadiv == 0xFFFF)
+ antennadiv = 3;
+ assert(antennadiv <= 3);
+
+ ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET);
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET,
+ ucodeflags & ~BCM43xx_UCODEFLAG_AUTODIV);
+
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ case BCM43xx_PHYTYPE_G:
+ if (phy->type == BCM43xx_PHYTYPE_A)
+ offset = 0x0000;
+ else
+ offset = 0x0400;
+
+ if (antennadiv == 2)
+ value = (3/*automatic*/ << 7);
+ else
+ value = (antennadiv << 7);
+ bcm43xx_phy_write(bcm, offset + 1,
+ (bcm43xx_phy_read(bcm, offset + 1)
+ & 0x7E7F) | value);
+
+ if (antennadiv >= 2) {
+ if (antennadiv == 2)
+ value = (antennadiv << 7);
+ else
+ value = (0/*force0*/ << 7);
+ bcm43xx_phy_write(bcm, offset + 0x2B,
+ (bcm43xx_phy_read(bcm, offset + 0x2B)
+ & 0xFEFF) | value);
+ }
+
+ if (phy->type == BCM43xx_PHYTYPE_G) {
+ if (antennadiv >= 2)
+ bcm43xx_phy_write(bcm, 0x048C,
+ bcm43xx_phy_read(bcm, 0x048C)
+ | 0x2000);
+ else
+ bcm43xx_phy_write(bcm, 0x048C,
+ bcm43xx_phy_read(bcm, 0x048C)
+ & ~0x2000);
+ if (phy->rev >= 2) {
+ bcm43xx_phy_write(bcm, 0x0461,
+ bcm43xx_phy_read(bcm, 0x0461)
+ | 0x0010);
+ bcm43xx_phy_write(bcm, 0x04AD,
+ (bcm43xx_phy_read(bcm, 0x04AD)
+ & 0x00FF) | 0x0015);
+ if (phy->rev == 2)
+ bcm43xx_phy_write(bcm, 0x0427, 0x0008);
+ else
+ bcm43xx_phy_write(bcm, 0x0427,
+ (bcm43xx_phy_read(bcm, 0x0427)
+ & 0x00FF) | 0x0008);
+ }
+ else if (phy->rev >= 6)
+ bcm43xx_phy_write(bcm, 0x049B, 0x00DC);
+ } else {
+ if (phy->rev < 3)
+ bcm43xx_phy_write(bcm, 0x002B,
+ (bcm43xx_phy_read(bcm, 0x002B)
+ & 0x00FF) | 0x0024);
+ else {
+ bcm43xx_phy_write(bcm, 0x0061,
+ bcm43xx_phy_read(bcm, 0x0061)
+ | 0x0010);
+ if (phy->rev == 3) {
+ bcm43xx_phy_write(bcm, 0x0093, 0x001D);
+ bcm43xx_phy_write(bcm, 0x0027, 0x0008);
+ } else {
+ bcm43xx_phy_write(bcm, 0x0093, 0x003A);
+ bcm43xx_phy_write(bcm, 0x0027,
+ (bcm43xx_phy_read(bcm, 0x0027)
+ & 0x00FF) | 0x0008);
+ }
+ }
+ }
+ break;
+ case BCM43xx_PHYTYPE_B:
+ if (bcm->current_core->rev == 2)
+ value = (3/*automatic*/ << 7);
+ else
+ value = (antennadiv << 7);
+ bcm43xx_phy_write(bcm, 0x03E2,
+ (bcm43xx_phy_read(bcm, 0x03E2)
+ & 0xFE7F) | value);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (antennadiv >= 2) {
+ ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET);
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET,
+ ucodeflags | BCM43xx_UCODEFLAG_AUTODIV);
+ }
+
+ phy->antenna_diversity = antennadiv;
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
new file mode 100644
index 00000000000..1f321ef42be
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
@@ -0,0 +1,74 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ Some parts of the code in this file are derived from the ipw2200
+ driver Copyright(c) 2003 - 2004 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef BCM43xx_PHY_H_
+#define BCM43xx_PHY_H_
+
+#include <linux/types.h>
+
+struct bcm43xx_private;
+
+void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm);
+#define bcm43xx_phy_lock(bcm, flags) \
+ do { \
+ local_irq_save(flags); \
+ bcm43xx_raw_phy_lock(bcm); \
+ } while (0)
+void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm);
+#define bcm43xx_phy_unlock(bcm, flags) \
+ do { \
+ bcm43xx_raw_phy_unlock(bcm); \
+ local_irq_restore(flags); \
+ } while (0)
+
+u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset);
+void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
+
+int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm);
+int bcm43xx_phy_init(struct bcm43xx_private *bcm);
+
+void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm);
+void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm);
+int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect);
+
+void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm);
+void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm);
+void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm);
+
+/* Adjust the LocalOscillator to the saved values.
+ * "fixed" is only set to 1 once in initialization. Set to 0 otherwise.
+ */
+void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed);
+void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm);
+
+void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
+ u16 baseband_attenuation);
+
+#endif /* BCM43xx_PHY_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
new file mode 100644
index 00000000000..0aa1bd269a2
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
@@ -0,0 +1,638 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ PIO Transmission
+
+ Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx.h"
+#include "bcm43xx_pio.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_xmit.h"
+#include "bcm43xx_power.h"
+
+#include <linux/delay.h>
+
+
+static void tx_start(struct bcm43xx_pioqueue *queue)
+{
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+ BCM43xx_PIO_TXCTL_INIT);
+}
+
+static void tx_octet(struct bcm43xx_pioqueue *queue,
+ u8 octet)
+{
+ if (queue->need_workarounds) {
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
+ octet);
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+ BCM43xx_PIO_TXCTL_WRITELO);
+ } else {
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+ BCM43xx_PIO_TXCTL_WRITELO);
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
+ octet);
+ }
+}
+
+static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr,
+ const u8 *packet,
+ unsigned int *pos)
+{
+ const u8 *source;
+ unsigned int i = *pos;
+ u16 ret;
+
+ if (i < sizeof(*txhdr)) {
+ source = (const u8 *)txhdr;
+ } else {
+ source = packet;
+ i -= sizeof(*txhdr);
+ }
+ ret = le16_to_cpu( *((u16 *)(source + i)) );
+ *pos += 2;
+
+ return ret;
+}
+
+static void tx_data(struct bcm43xx_pioqueue *queue,
+ struct bcm43xx_txhdr *txhdr,
+ const u8 *packet,
+ unsigned int octets)
+{
+ u16 data;
+ unsigned int i = 0;
+
+ if (queue->need_workarounds) {
+ data = tx_get_next_word(txhdr, packet, &i);
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
+ }
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+ BCM43xx_PIO_TXCTL_WRITELO |
+ BCM43xx_PIO_TXCTL_WRITEHI);
+ while (i < octets - 1) {
+ data = tx_get_next_word(txhdr, packet, &i);
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
+ }
+ if (octets % 2)
+ tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]);
+}
+
+static void tx_complete(struct bcm43xx_pioqueue *queue,
+ struct sk_buff *skb)
+{
+ if (queue->need_workarounds) {
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
+ skb->data[skb->len - 1]);
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+ BCM43xx_PIO_TXCTL_WRITELO |
+ BCM43xx_PIO_TXCTL_COMPLETE);
+ } else {
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+ BCM43xx_PIO_TXCTL_COMPLETE);
+ }
+}
+
+static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
+ struct bcm43xx_pio_txpacket *packet)
+{
+ u16 cookie = 0x0000;
+ int packetindex;
+
+ /* We use the upper 4 bits for the PIO
+ * controller ID and the lower 12 bits
+ * for the packet index (in the cache).
+ */
+ switch (queue->mmio_base) {
+ case BCM43xx_MMIO_PIO1_BASE:
+ break;
+ case BCM43xx_MMIO_PIO2_BASE:
+ cookie = 0x1000;
+ break;
+ case BCM43xx_MMIO_PIO3_BASE:
+ cookie = 0x2000;
+ break;
+ case BCM43xx_MMIO_PIO4_BASE:
+ cookie = 0x3000;
+ break;
+ default:
+ assert(0);
+ }
+ packetindex = pio_txpacket_getindex(packet);
+ assert(((u16)packetindex & 0xF000) == 0x0000);
+ cookie |= (u16)packetindex;
+
+ return cookie;
+}
+
+static
+struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm,
+ u16 cookie,
+ struct bcm43xx_pio_txpacket **packet)
+{
+ struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
+ struct bcm43xx_pioqueue *queue = NULL;
+ int packetindex;
+
+ switch (cookie & 0xF000) {
+ case 0x0000:
+ queue = pio->queue0;
+ break;
+ case 0x1000:
+ queue = pio->queue1;
+ break;
+ case 0x2000:
+ queue = pio->queue2;
+ break;
+ case 0x3000:
+ queue = pio->queue3;
+ break;
+ default:
+ assert(0);
+ }
+ packetindex = (cookie & 0x0FFF);
+ assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS);
+ *packet = &(queue->tx_packets_cache[packetindex]);
+
+ return queue;
+}
+
+static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue,
+ struct sk_buff *skb,
+ struct bcm43xx_pio_txpacket *packet)
+{
+ struct bcm43xx_txhdr txhdr;
+ unsigned int octets;
+
+ assert(skb_shinfo(skb)->nr_frags == 0);
+ bcm43xx_generate_txhdr(queue->bcm,
+ &txhdr, skb->data, skb->len,
+ (packet->xmitted_frags == 0),
+ generate_cookie(queue, packet));
+
+ tx_start(queue);
+ octets = skb->len + sizeof(txhdr);
+ if (queue->need_workarounds)
+ octets--;
+ tx_data(queue, &txhdr, (u8 *)skb->data, octets);
+ tx_complete(queue, skb);
+}
+
+static void free_txpacket(struct bcm43xx_pio_txpacket *packet,
+ int irq_context)
+{
+ struct bcm43xx_pioqueue *queue = packet->queue;
+
+ ieee80211_txb_free(packet->txb);
+ list_move(&packet->list, &queue->txfree);
+ queue->nr_txfree++;
+
+ assert(queue->tx_devq_used >= packet->xmitted_octets);
+ assert(queue->tx_devq_packets >= packet->xmitted_frags);
+ queue->tx_devq_used -= packet->xmitted_octets;
+ queue->tx_devq_packets -= packet->xmitted_frags;
+}
+
+static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
+{
+ struct bcm43xx_pioqueue *queue = packet->queue;
+ struct ieee80211_txb *txb = packet->txb;
+ struct sk_buff *skb;
+ u16 octets;
+ int i;
+
+ for (i = packet->xmitted_frags; i < txb->nr_frags; i++) {
+ skb = txb->fragments[i];
+
+ octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr);
+ assert(queue->tx_devq_size >= octets);
+ assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS);
+ assert(queue->tx_devq_used <= queue->tx_devq_size);
+ /* Check if there is sufficient free space on the device
+ * TX queue. If not, return and let the TX tasklet
+ * retry later.
+ */
+ if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS)
+ return -EBUSY;
+ if (queue->tx_devq_used + octets > queue->tx_devq_size)
+ return -EBUSY;
+ /* Now poke the device. */
+ pio_tx_write_fragment(queue, skb, packet);
+
+ /* Account for the packet size.
+ * (We must not overflow the device TX queue)
+ */
+ queue->tx_devq_packets++;
+ queue->tx_devq_used += octets;
+
+ assert(packet->xmitted_frags < packet->txb->nr_frags);
+ packet->xmitted_frags++;
+ packet->xmitted_octets += octets;
+ }
+ list_move_tail(&packet->list, &queue->txrunning);
+
+ return 0;
+}
+
+static void tx_tasklet(unsigned long d)
+{
+ struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d;
+ struct bcm43xx_private *bcm = queue->bcm;
+ unsigned long flags;
+ struct bcm43xx_pio_txpacket *packet, *tmp_packet;
+ int err;
+ u16 txctl;
+
+ bcm43xx_lock_mmio(bcm, flags);
+
+ txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
+ if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
+ goto out_unlock;
+
+ list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
+ assert(packet->xmitted_frags < packet->txb->nr_frags);
+ if (packet->xmitted_frags == 0) {
+ int i;
+ struct sk_buff *skb;
+
+ /* Check if the device queue is big
+ * enough for every fragment. If not, drop the
+ * whole packet.
+ */
+ for (i = 0; i < packet->txb->nr_frags; i++) {
+ skb = packet->txb->fragments[i];
+ if (unlikely(skb->len > queue->tx_devq_size)) {
+ dprintkl(KERN_ERR PFX "PIO TX device queue too small. "
+ "Dropping packet.\n");
+ free_txpacket(packet, 1);
+ goto next_packet;
+ }
+ }
+ }
+ /* Try to transmit the packet.
+ * This may not completely succeed.
+ */
+ err = pio_tx_packet(packet);
+ if (err)
+ break;
+ next_packet:
+ continue;
+ }
+out_unlock:
+ bcm43xx_unlock_mmio(bcm, flags);
+}
+
+static void setup_txqueues(struct bcm43xx_pioqueue *queue)
+{
+ struct bcm43xx_pio_txpacket *packet;
+ int i;
+
+ queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS;
+ for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) {
+ packet = &(queue->tx_packets_cache[i]);
+
+ packet->queue = queue;
+ INIT_LIST_HEAD(&packet->list);
+
+ list_add(&packet->list, &queue->txfree);
+ }
+}
+
+static
+struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm,
+ u16 pio_mmio_base)
+{
+ struct bcm43xx_pioqueue *queue;
+ u32 value;
+ u16 qsize;
+
+ queue = kzalloc(sizeof(*queue), GFP_KERNEL);
+ if (!queue)
+ goto out;
+
+ queue->bcm = bcm;
+ queue->mmio_base = pio_mmio_base;
+ queue->need_workarounds = (bcm->current_core->rev < 3);
+
+ INIT_LIST_HEAD(&queue->txfree);
+ INIT_LIST_HEAD(&queue->txqueue);
+ INIT_LIST_HEAD(&queue->txrunning);
+ tasklet_init(&queue->txtask, tx_tasklet,
+ (unsigned long)queue);
+
+ value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+ value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
+
+ qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
+ if (qsize == 0) {
+ printk(KERN_ERR PFX "ERROR: This card does not support PIO "
+ "operation mode. Please use DMA mode "
+ "(module parameter pio=0).\n");
+ goto err_freequeue;
+ }
+ if (qsize <= BCM43xx_PIO_TXQADJUST) {
+ printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n",
+ qsize);
+ goto err_freequeue;
+ }
+ qsize -= BCM43xx_PIO_TXQADJUST;
+ queue->tx_devq_size = qsize;
+
+ setup_txqueues(queue);
+
+out:
+ return queue;
+
+err_freequeue:
+ kfree(queue);
+ queue = NULL;
+ goto out;
+}
+
+static void cancel_transfers(struct bcm43xx_pioqueue *queue)
+{
+ struct bcm43xx_pio_txpacket *packet, *tmp_packet;
+
+ netif_tx_disable(queue->bcm->net_dev);
+ assert(queue->bcm->shutting_down);
+ tasklet_disable(&queue->txtask);
+
+ list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
+ free_txpacket(packet, 0);
+ list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list)
+ free_txpacket(packet, 0);
+}
+
+static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue)
+{
+ if (!queue)
+ return;
+
+ cancel_transfers(queue);
+ kfree(queue);
+}
+
+void bcm43xx_pio_free(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_pio *pio;
+
+ if (!bcm43xx_using_pio(bcm))
+ return;
+ pio = bcm43xx_current_pio(bcm);
+
+ bcm43xx_destroy_pioqueue(pio->queue3);
+ pio->queue3 = NULL;
+ bcm43xx_destroy_pioqueue(pio->queue2);
+ pio->queue2 = NULL;
+ bcm43xx_destroy_pioqueue(pio->queue1);
+ pio->queue1 = NULL;
+ bcm43xx_destroy_pioqueue(pio->queue0);
+ pio->queue0 = NULL;
+}
+
+int bcm43xx_pio_init(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
+ struct bcm43xx_pioqueue *queue;
+ int err = -ENOMEM;
+
+ queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE);
+ if (!queue)
+ goto out;
+ pio->queue0 = queue;
+
+ queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE);
+ if (!queue)
+ goto err_destroy0;
+ pio->queue1 = queue;
+
+ queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE);
+ if (!queue)
+ goto err_destroy1;
+ pio->queue2 = queue;
+
+ queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE);
+ if (!queue)
+ goto err_destroy2;
+ pio->queue3 = queue;
+
+ if (bcm->current_core->rev < 3)
+ bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND;
+
+ dprintk(KERN_INFO PFX "PIO initialized\n");
+ err = 0;
+out:
+ return err;
+
+err_destroy2:
+ bcm43xx_destroy_pioqueue(pio->queue2);
+ pio->queue2 = NULL;
+err_destroy1:
+ bcm43xx_destroy_pioqueue(pio->queue1);
+ pio->queue1 = NULL;
+err_destroy0:
+ bcm43xx_destroy_pioqueue(pio->queue0);
+ pio->queue0 = NULL;
+ goto out;
+}
+
+int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
+ struct ieee80211_txb *txb)
+{
+ struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1;
+ struct bcm43xx_pio_txpacket *packet;
+
+ assert(!queue->tx_suspended);
+ assert(!list_empty(&queue->txfree));
+
+ packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
+ packet->txb = txb;
+ packet->xmitted_frags = 0;
+ packet->xmitted_octets = 0;
+ list_move_tail(&packet->list, &queue->txqueue);
+ queue->nr_txfree--;
+ assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
+
+ /* Suspend TX, if we are out of packets in the "free" queue. */
+ if (list_empty(&queue->txfree)) {
+ netif_stop_queue(queue->bcm->net_dev);
+ queue->tx_suspended = 1;
+ }
+
+ tasklet_schedule(&queue->txtask);
+
+ return 0;
+}
+
+void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
+ struct bcm43xx_xmitstatus *status)
+{
+ struct bcm43xx_pioqueue *queue;
+ struct bcm43xx_pio_txpacket *packet;
+
+ queue = parse_cookie(bcm, status->cookie, &packet);
+ assert(queue);
+
+ free_txpacket(packet, 1);
+ if (queue->tx_suspended) {
+ queue->tx_suspended = 0;
+ netif_wake_queue(queue->bcm->net_dev);
+ }
+ /* If there are packets on the txqueue, poke the tasklet
+ * to transmit them.
+ */
+ if (!list_empty(&queue->txqueue))
+ tasklet_schedule(&queue->txtask);
+}
+
+static void pio_rx_error(struct bcm43xx_pioqueue *queue,
+ int clear_buffers,
+ const char *error)
+{
+ int i;
+
+ printkl("PIO RX error: %s\n", error);
+ bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
+ BCM43xx_PIO_RXCTL_READY);
+ if (clear_buffers) {
+ assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE);
+ for (i = 0; i < 15; i++) {
+ /* Dummy read. */
+ bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+ }
+ }
+}
+
+void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
+{
+ u16 preamble[21] = { 0 };
+ struct bcm43xx_rxhdr *rxhdr;
+ u16 tmp, len, rxflags2;
+ int i, preamble_readwords;
+ struct sk_buff *skb;
+
+ tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
+ if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE))
+ return;
+ bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
+ BCM43xx_PIO_RXCTL_DATAAVAILABLE);
+
+ for (i = 0; i < 10; i++) {
+ tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
+ if (tmp & BCM43xx_PIO_RXCTL_READY)
+ goto data_ready;
+ udelay(10);
+ }
+ dprintkl(KERN_ERR PFX "PIO RX timed out\n");
+ return;
+data_ready:
+
+ len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+ if (unlikely(len > 0x700)) {
+ pio_rx_error(queue, 0, "len > 0x700");
+ return;
+ }
+ if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) {
+ pio_rx_error(queue, 0, "len == 0");
+ return;
+ }
+ preamble[0] = cpu_to_le16(len);
+ if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE)
+ preamble_readwords = 14 / sizeof(u16);
+ else
+ preamble_readwords = 18 / sizeof(u16);
+ for (i = 0; i < preamble_readwords; i++) {
+ tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+ preamble[i + 1] = cpu_to_le16(tmp);
+ }
+ rxhdr = (struct bcm43xx_rxhdr *)preamble;
+ rxflags2 = le16_to_cpu(rxhdr->flags2);
+ if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) {
+ pio_rx_error(queue,
+ (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE),
+ "invalid frame");
+ return;
+ }
+ if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) {
+ /* We received an xmit status. */
+ struct bcm43xx_hwxmitstatus *hw;
+ struct bcm43xx_xmitstatus stat;
+
+ hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1);
+ stat.cookie = le16_to_cpu(hw->cookie);
+ stat.flags = hw->flags;
+ stat.cnt1 = hw->cnt1;
+ stat.cnt2 = hw->cnt2;
+ stat.seq = le16_to_cpu(hw->seq);
+ stat.unknown = le16_to_cpu(hw->unknown);
+
+ bcm43xx_debugfs_log_txstat(queue->bcm, &stat);
+ bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat);
+
+ return;
+ }
+
+ skb = dev_alloc_skb(len);
+ if (unlikely(!skb)) {
+ pio_rx_error(queue, 1, "OOM");
+ return;
+ }
+ skb_put(skb, len);
+ for (i = 0; i < len - 1; i += 2) {
+ tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+ *((u16 *)(skb->data + i)) = cpu_to_le16(tmp);
+ }
+ if (len % 2) {
+ tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+ skb->data[len - 1] = (tmp & 0x00FF);
+/* The specs say the following is required, but
+ * it is wrong and corrupts the PLCP. If we don't do
+ * this, the PLCP seems to be correct. So ifdef it out for now.
+ */
+#if 0
+ if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
+ skb->data[2] = (tmp & 0xFF00) >> 8;
+ else
+ skb->data[0] = (tmp & 0xFF00) >> 8;
+#endif
+ }
+ skb_trim(skb, len - IEEE80211_FCS_LEN);
+ bcm43xx_rx(queue->bcm, skb, rxhdr);
+}
+
+void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
+{
+ bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1);
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+ bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
+ | BCM43xx_PIO_TXCTL_SUSPEND);
+}
+
+void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
+{
+ bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+ bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
+ & ~BCM43xx_PIO_TXCTL_SUSPEND);
+ bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1);
+ tasklet_schedule(&queue->txtask);
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
new file mode 100644
index 00000000000..dfc78209e3a
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
@@ -0,0 +1,150 @@
+#ifndef BCM43xx_PIO_H_
+#define BCM43xx_PIO_H_
+
+#include "bcm43xx.h"
+
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+
+
+#define BCM43xx_PIO_TXCTL 0x00
+#define BCM43xx_PIO_TXDATA 0x02
+#define BCM43xx_PIO_TXQBUFSIZE 0x04
+#define BCM43xx_PIO_RXCTL 0x08
+#define BCM43xx_PIO_RXDATA 0x0A
+
+#define BCM43xx_PIO_TXCTL_WRITELO (1 << 0)
+#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1)
+#define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2)
+#define BCM43xx_PIO_TXCTL_INIT (1 << 3)
+#define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7)
+
+#define BCM43xx_PIO_RXCTL_DATAAVAILABLE (1 << 0)
+#define BCM43xx_PIO_RXCTL_READY (1 << 1)
+
+/* PIO constants */
+#define BCM43xx_PIO_MAXTXDEVQPACKETS 31
+#define BCM43xx_PIO_TXQADJUST 80
+
+/* PIO tuning knobs */
+#define BCM43xx_PIO_MAXTXPACKETS 256
+
+
+
+#ifdef CONFIG_BCM43XX_PIO
+
+
+struct bcm43xx_pioqueue;
+struct bcm43xx_xmitstatus;
+
+struct bcm43xx_pio_txpacket {
+ struct bcm43xx_pioqueue *queue;
+ struct ieee80211_txb *txb;
+ struct list_head list;
+
+ u8 xmitted_frags;
+ u16 xmitted_octets;
+};
+
+#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache))
+
+struct bcm43xx_pioqueue {
+ struct bcm43xx_private *bcm;
+ u16 mmio_base;
+
+ u8 tx_suspended:1,
+ need_workarounds:1; /* Workarounds needed for core.rev < 3 */
+
+ /* Adjusted size of the device internal TX buffer. */
+ u16 tx_devq_size;
+ /* Used octets of the device internal TX buffer. */
+ u16 tx_devq_used;
+ /* Used packet slots in the device internal TX buffer. */
+ u8 tx_devq_packets;
+ /* Packets from the txfree list can
+ * be taken on incoming TX requests.
+ */
+ struct list_head txfree;
+ unsigned int nr_txfree;
+ /* Packets on the txqueue are queued,
+ * but not completely written to the chip, yet.
+ */
+ struct list_head txqueue;
+ /* Packets on the txrunning queue are completely
+ * posted to the device. We are waiting for the txstatus.
+ */
+ struct list_head txrunning;
+ /* Total number or packets sent.
+ * (This counter can obviously wrap).
+ */
+ unsigned int nr_tx_packets;
+ struct tasklet_struct txtask;
+ struct bcm43xx_pio_txpacket tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS];
+};
+
+static inline
+u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue,
+ u16 offset)
+{
+ return bcm43xx_read16(queue->bcm, queue->mmio_base + offset);
+}
+
+static inline
+void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue,
+ u16 offset, u16 value)
+{
+ bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value);
+ mmiowb();
+}
+
+
+int bcm43xx_pio_init(struct bcm43xx_private *bcm);
+void bcm43xx_pio_free(struct bcm43xx_private *bcm);
+
+int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
+ struct ieee80211_txb *txb);
+void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
+ struct bcm43xx_xmitstatus *status);
+void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
+
+void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue);
+void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue);
+
+#else /* CONFIG_BCM43XX_PIO */
+
+static inline
+int bcm43xx_pio_init(struct bcm43xx_private *bcm)
+{
+ return 0;
+}
+static inline
+void bcm43xx_pio_free(struct bcm43xx_private *bcm)
+{
+}
+static inline
+int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
+ struct ieee80211_txb *txb)
+{
+ return 0;
+}
+static inline
+void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
+ struct bcm43xx_xmitstatus *status)
+{
+}
+static inline
+void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
+{
+}
+static inline
+void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
+{
+}
+static inline
+void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
+{
+}
+
+#endif /* CONFIG_BCM43XX_PIO */
+#endif /* BCM43xx_PIO_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
new file mode 100644
index 00000000000..6569da3a7a3
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
@@ -0,0 +1,379 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ Some parts of the code in this file are derived from the ipw2200
+ driver Copyright(c) 2003 - 2004 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/delay.h>
+
+#include "bcm43xx.h"
+#include "bcm43xx_power.h"
+#include "bcm43xx_main.h"
+
+
+/* Get the Slow Clock Source */
+static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm)
+{
+ u32 tmp;
+ int err;
+
+ assert(bcm->current_core == &bcm->core_chipcommon);
+ if (bcm->current_core->rev < 6) {
+ if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA ||
+ bcm->bustype == BCM43xx_BUSTYPE_SB)
+ return BCM43xx_PCTL_CLKSRC_XTALOS;
+ if (bcm->bustype == BCM43xx_BUSTYPE_PCI) {
+ err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
+ assert(!err);
+ if (tmp & 0x10)
+ return BCM43xx_PCTL_CLKSRC_PCI;
+ return BCM43xx_PCTL_CLKSRC_XTALOS;
+ }
+ }
+ if (bcm->current_core->rev < 10) {
+ tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+ tmp &= 0x7;
+ if (tmp == 0)
+ return BCM43xx_PCTL_CLKSRC_LOPWROS;
+ if (tmp == 1)
+ return BCM43xx_PCTL_CLKSRC_XTALOS;
+ if (tmp == 2)
+ return BCM43xx_PCTL_CLKSRC_PCI;
+ }
+
+ return BCM43xx_PCTL_CLKSRC_XTALOS;
+}
+
+/* Get max/min slowclock frequency
+ * as described in http://bcm-specs.sipsolutions.net/PowerControl
+ */
+static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
+ int get_max)
+{
+ int limit;
+ int clocksrc;
+ int divisor;
+ u32 tmp;
+
+ assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL);
+ assert(bcm->current_core == &bcm->core_chipcommon);
+
+ clocksrc = bcm43xx_pctl_get_slowclksrc(bcm);
+ if (bcm->current_core->rev < 6) {
+ switch (clocksrc) {
+ case BCM43xx_PCTL_CLKSRC_PCI:
+ divisor = 64;
+ break;
+ case BCM43xx_PCTL_CLKSRC_XTALOS:
+ divisor = 32;
+ break;
+ default:
+ assert(0);
+ divisor = 1;
+ }
+ } else if (bcm->current_core->rev < 10) {
+ switch (clocksrc) {
+ case BCM43xx_PCTL_CLKSRC_LOPWROS:
+ divisor = 1;
+ break;
+ case BCM43xx_PCTL_CLKSRC_XTALOS:
+ case BCM43xx_PCTL_CLKSRC_PCI:
+ tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+ divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+ divisor *= 4;
+ break;
+ default:
+ assert(0);
+ divisor = 1;
+ }
+ } else {
+ tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
+ divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+ divisor *= 4;
+ }
+
+ switch (clocksrc) {
+ case BCM43xx_PCTL_CLKSRC_LOPWROS:
+ if (get_max)
+ limit = 43000;
+ else
+ limit = 25000;
+ break;
+ case BCM43xx_PCTL_CLKSRC_XTALOS:
+ if (get_max)
+ limit = 20200000;
+ else
+ limit = 19800000;
+ break;
+ case BCM43xx_PCTL_CLKSRC_PCI:
+ if (get_max)
+ limit = 34000000;
+ else
+ limit = 25000000;
+ break;
+ default:
+ assert(0);
+ limit = 0;
+ }
+ limit /= divisor;
+
+ return limit;
+}
+
+
+/* init power control
+ * as described in http://bcm-specs.sipsolutions.net/PowerControl
+ */
+int bcm43xx_pctl_init(struct bcm43xx_private *bcm)
+{
+ int err, maxfreq;
+ struct bcm43xx_coreinfo *old_core;
+
+ if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
+ return 0;
+ old_core = bcm->current_core;
+ err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+ if (err == -ENODEV)
+ return 0;
+ if (err)
+ goto out;
+
+ maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
+ (maxfreq * 150 + 999999) / 1000000);
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
+ (maxfreq * 15 + 999999) / 1000000);
+
+ err = bcm43xx_switch_core(bcm, old_core);
+ assert(err == 0);
+
+out:
+ return err;
+}
+
+u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm)
+{
+ u16 delay = 0;
+ int err;
+ u32 pll_on_delay;
+ struct bcm43xx_coreinfo *old_core;
+ int minfreq;
+
+ if (bcm->bustype != BCM43xx_BUSTYPE_PCI)
+ goto out;
+ if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
+ goto out;
+ old_core = bcm->current_core;
+ err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+ if (err == -ENODEV)
+ goto out;
+
+ minfreq = bcm43xx_pctl_clockfreqlimit(bcm, 0);
+ pll_on_delay = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY);
+ delay = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq;
+
+ err = bcm43xx_switch_core(bcm, old_core);
+ assert(err == 0);
+
+out:
+ return delay;
+}
+
+/* set the powercontrol clock
+ * as described in http://bcm-specs.sipsolutions.net/PowerControl
+ */
+int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode)
+{
+ int err;
+ struct bcm43xx_coreinfo *old_core;
+ u32 tmp;
+
+ old_core = bcm->current_core;
+ err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+ if (err == -ENODEV)
+ return 0;
+ if (err)
+ goto out;
+
+ if (bcm->core_chipcommon.rev < 6) {
+ if (mode == BCM43xx_PCTL_CLK_FAST) {
+ err = bcm43xx_pctl_set_crystal(bcm, 1);
+ if (err)
+ goto out;
+ }
+ } else {
+ if ((bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) &&
+ (bcm->core_chipcommon.rev < 10)) {
+ switch (mode) {
+ case BCM43xx_PCTL_CLK_FAST:
+ tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+ tmp = (tmp & ~BCM43xx_PCTL_FORCE_SLOW) | BCM43xx_PCTL_FORCE_PLL;
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+ break;
+ case BCM43xx_PCTL_CLK_SLOW:
+ tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+ tmp |= BCM43xx_PCTL_FORCE_SLOW;
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+ break;
+ case BCM43xx_PCTL_CLK_DYNAMIC:
+ tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+ tmp &= ~BCM43xx_PCTL_FORCE_SLOW;
+ tmp |= BCM43xx_PCTL_FORCE_PLL;
+ tmp &= ~BCM43xx_PCTL_DYN_XTAL;
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+ }
+ }
+ }
+
+ err = bcm43xx_switch_core(bcm, old_core);
+ assert(err == 0);
+
+out:
+ return err;
+}
+
+int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on)
+{
+ int err;
+ u32 in, out, outenable;
+
+ err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_IN, &in);
+ if (err)
+ goto err_pci;
+ err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &out);
+ if (err)
+ goto err_pci;
+ err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUTENABLE, &outenable);
+ if (err)
+ goto err_pci;
+
+ outenable |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
+
+ if (on) {
+ if (in & 0x40)
+ return 0;
+
+ out |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
+
+ err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
+ if (err)
+ goto err_pci;
+ err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
+ if (err)
+ goto err_pci;
+ udelay(1000);
+
+ out &= ~BCM43xx_PCTL_PLL_POWERDOWN;
+ err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
+ if (err)
+ goto err_pci;
+ udelay(5000);
+ } else {
+ if (bcm->current_core->rev < 5)
+ return 0;
+ if (bcm->sprom.boardflags & BCM43xx_BFL_XTAL_NOSLOW)
+ return 0;
+
+/* XXX: Why BCM43xx_MMIO_RADIO_HWENABLED_xx can't be read at this time?
+ * err = bcm43xx_switch_core(bcm, bcm->active_80211_core);
+ * if (err)
+ * return err;
+ * if (((bcm->current_core->rev >= 3) &&
+ * (bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) & (1 << 16))) ||
+ * ((bcm->current_core->rev < 3) &&
+ * !(bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) & (1 << 4))))
+ * return 0;
+ * err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+ * if (err)
+ * return err;
+ */
+
+ err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
+ if (err)
+ goto out;
+ out &= ~BCM43xx_PCTL_XTAL_POWERUP;
+ out |= BCM43xx_PCTL_PLL_POWERDOWN;
+ err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
+ if (err)
+ goto err_pci;
+ err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
+ if (err)
+ goto err_pci;
+ }
+
+out:
+ return err;
+
+err_pci:
+ printk(KERN_ERR PFX "Error: pctl_set_clock() could not access PCI config space!\n");
+ err = -EBUSY;
+ goto out;
+}
+
+/* Set the PowerSavingControlBits.
+ * Bitvalues:
+ * 0 => unset the bit
+ * 1 => set the bit
+ * -1 => calculate the bit
+ */
+void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
+ int bit25, int bit26)
+{
+ int i;
+ u32 status;
+
+//FIXME: Force 25 to off and 26 to on for now:
+bit25 = 0;
+bit26 = 1;
+
+ if (bit25 == -1) {
+ //TODO: If powersave is not off and FIXME is not set and we are not in adhoc
+ // and thus is not an AP and we are associated, set bit 25
+ }
+ if (bit26 == -1) {
+ //TODO: If the device is awake or this is an AP, or we are scanning, or FIXME,
+ // or we are associated, or FIXME, or the latest PS-Poll packet sent was
+ // successful, set bit26
+ }
+ status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+ if (bit25)
+ status |= BCM43xx_SBF_PS1;
+ else
+ status &= ~BCM43xx_SBF_PS1;
+ if (bit26)
+ status |= BCM43xx_SBF_PS2;
+ else
+ status &= ~BCM43xx_SBF_PS2;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+ if (bit26 && bcm->current_core->rev >= 5) {
+ for (i = 0; i < 100; i++) {
+ if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0040) != 4)
+ break;
+ udelay(10);
+ }
+ }
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
new file mode 100644
index 00000000000..c966ab3a5a8
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
@@ -0,0 +1,56 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ Some parts of the code in this file are derived from the ipw2200
+ driver Copyright(c) 2003 - 2004 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef BCM43xx_POWER_H_
+#define BCM43xx_POWER_H_
+
+#include <linux/types.h>
+
+/* Clock sources */
+enum {
+ /* PCI clock */
+ BCM43xx_PCTL_CLKSRC_PCI,
+ /* Crystal slow clock oscillator */
+ BCM43xx_PCTL_CLKSRC_XTALOS,
+ /* Low power oscillator */
+ BCM43xx_PCTL_CLKSRC_LOPWROS,
+};
+
+struct bcm43xx_private;
+
+int bcm43xx_pctl_init(struct bcm43xx_private *bcm);
+int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode);
+int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on);
+u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm);
+
+void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
+ int bit25, int bit26);
+
+#endif /* BCM43xx_POWER_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
new file mode 100644
index 00000000000..af5c0bff169
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
@@ -0,0 +1,2026 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ Some parts of the code in this file are derived from the ipw2200
+ driver Copyright(c) 2003 - 2004 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/delay.h>
+
+#include "bcm43xx.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_phy.h"
+#include "bcm43xx_radio.h"
+#include "bcm43xx_ilt.h"
+
+
+/* Table for bcm43xx_radio_calibrationvalue() */
+static const u16 rcc_table[16] = {
+ 0x0002, 0x0003, 0x0001, 0x000F,
+ 0x0006, 0x0007, 0x0005, 0x000F,
+ 0x000A, 0x000B, 0x0009, 0x000F,
+ 0x000E, 0x000F, 0x000D, 0x000F,
+};
+
+/* Reverse the bits of a 4bit value.
+ * Example: 1101 is flipped 1011
+ */
+static u16 flip_4bit(u16 value)
+{
+ u16 flipped = 0x0000;
+
+ assert((value & ~0x000F) == 0x0000);
+
+ flipped |= (value & 0x0001) << 3;
+ flipped |= (value & 0x0002) << 1;
+ flipped |= (value & 0x0004) >> 1;
+ flipped |= (value & 0x0008) >> 3;
+
+ return flipped;
+}
+
+/* Get the freq, as it has to be written to the device. */
+static inline
+u16 channel2freq_bg(u8 channel)
+{
+ /* Frequencies are given as frequencies_bg[index] + 2.4GHz
+ * Starting with channel 1
+ */
+ static const u16 frequencies_bg[14] = {
+ 12, 17, 22, 27,
+ 32, 37, 42, 47,
+ 52, 57, 62, 67,
+ 72, 84,
+ };
+
+ assert(channel >= 1 && channel <= 14);
+
+ return frequencies_bg[channel - 1];
+}
+
+/* Get the freq, as it has to be written to the device. */
+static inline
+u16 channel2freq_a(u8 channel)
+{
+ assert(channel <= 200);
+
+ return (5000 + 5 * channel);
+}
+
+void bcm43xx_radio_lock(struct bcm43xx_private *bcm)
+{
+ u32 status;
+
+ status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+ status |= BCM43xx_SBF_RADIOREG_LOCK;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+ mmiowb();
+ udelay(10);
+}
+
+void bcm43xx_radio_unlock(struct bcm43xx_private *bcm)
+{
+ u32 status;
+
+ bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); /* dummy read */
+ status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+ status &= ~BCM43xx_SBF_RADIOREG_LOCK;
+ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+ mmiowb();
+}
+
+u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ offset |= 0x0040;
+ break;
+ case BCM43xx_PHYTYPE_B:
+ if (radio->version == 0x2053) {
+ if (offset < 0x70)
+ offset += 0x80;
+ else if (offset < 0x80)
+ offset += 0x70;
+ } else if (radio->version == 0x2050) {
+ offset |= 0x80;
+ } else
+ assert(0);
+ break;
+ case BCM43xx_PHYTYPE_G:
+ offset |= 0x80;
+ break;
+ }
+
+ bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
+ return bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
+}
+
+void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val)
+{
+ bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
+ mmiowb();
+ bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val);
+}
+
+static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm,
+ s16 first, s16 second, s16 third)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u16 i;
+ u16 start = 0x08, end = 0x18;
+ u16 offset = 0x0400;
+ u16 tmp;
+
+ if (phy->rev <= 1) {
+ offset = 0x5000;
+ start = 0x10;
+ end = 0x20;
+ }
+
+ for (i = 0; i < 4; i++)
+ bcm43xx_ilt_write(bcm, offset + i, first);
+
+ for (i = start; i < end; i++)
+ bcm43xx_ilt_write(bcm, offset + i, second);
+
+ if (third != -1) {
+ tmp = ((u16)third << 14) | ((u16)third << 6);
+ bcm43xx_phy_write(bcm, 0x04A0,
+ (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | tmp);
+ bcm43xx_phy_write(bcm, 0x04A1,
+ (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | tmp);
+ bcm43xx_phy_write(bcm, 0x04A2,
+ (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | tmp);
+ }
+ bcm43xx_dummy_transmission(bcm);
+}
+
+static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u16 i, tmp;
+ u16 offset = 0x0400;
+ u16 start = 0x0008, end = 0x0018;
+
+ if (phy->rev <= 1) {
+ offset = 0x5000;
+ start = 0x0010;
+ end = 0x0020;
+ }
+
+ for (i = 0; i < 4; i++) {
+ tmp = (i & 0xFFFC);
+ tmp |= (i & 0x0001) << 1;
+ tmp |= (i & 0x0002) >> 1;
+
+ bcm43xx_ilt_write(bcm, offset + i, tmp);
+ }
+
+ for (i = start; i < end; i++)
+ bcm43xx_ilt_write(bcm, offset + i, i - start);
+
+ bcm43xx_phy_write(bcm, 0x04A0,
+ (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040);
+ bcm43xx_phy_write(bcm, 0x04A1,
+ (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | 0x4040);
+ bcm43xx_phy_write(bcm, 0x04A2,
+ (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | 0x4000);
+ bcm43xx_dummy_transmission(bcm);
+}
+
+/* Synthetic PU workaround */
+static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+ if (radio->version != 0x2050 || radio->revision >= 6) {
+ /* We do not need the workaround. */
+ return;
+ }
+
+ if (channel <= 10) {
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+ channel2freq_bg(channel + 4));
+ } else {
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+ channel2freq_bg(1));
+ }
+ udelay(100);
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+ channel2freq_bg(channel));
+}
+
+u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u8 ret = 0;
+ u16 saved, rssi, temp;
+ int i, j = 0;
+
+ saved = bcm43xx_phy_read(bcm, 0x0403);
+ bcm43xx_radio_selectchannel(bcm, channel, 0);
+ bcm43xx_phy_write(bcm, 0x0403, (saved & 0xFFF8) | 5);
+ if (radio->aci_hw_rssi)
+ rssi = bcm43xx_phy_read(bcm, 0x048A) & 0x3F;
+ else
+ rssi = saved & 0x3F;
+ /* clamp temp to signed 5bit */
+ if (rssi > 32)
+ rssi -= 64;
+ for (i = 0;i < 100; i++) {
+ temp = (bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x3F;
+ if (temp > 32)
+ temp -= 64;
+ if (temp < rssi)
+ j++;
+ if (j >= 20)
+ ret = 1;
+ }
+ bcm43xx_phy_write(bcm, 0x0403, saved);
+
+ return ret;
+}
+
+u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u8 ret[13];
+ unsigned int channel = radio->channel;
+ unsigned int i, j, start, end;
+ unsigned long phylock_flags;
+
+ if (!((phy->type == BCM43xx_PHYTYPE_G) && (phy->rev > 0)))
+ return 0;
+
+ bcm43xx_phy_lock(bcm, phylock_flags);
+ bcm43xx_radio_lock(bcm);
+ bcm43xx_phy_write(bcm, 0x0802,
+ bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+ bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
+ bcm43xx_set_all_gains(bcm, 3, 8, 1);
+
+ start = (channel - 5 > 0) ? channel - 5 : 1;
+ end = (channel + 5 < 14) ? channel + 5 : 13;
+
+ for (i = start; i <= end; i++) {
+ if (abs(channel - i) > 2)
+ ret[i-1] = bcm43xx_radio_aci_detect(bcm, i);
+ }
+ bcm43xx_radio_selectchannel(bcm, channel, 0);
+ bcm43xx_phy_write(bcm, 0x0802,
+ (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC) | 0x0003);
+ bcm43xx_phy_write(bcm, 0x0403,
+ bcm43xx_phy_read(bcm, 0x0403) & 0xFFF8);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+ bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
+ bcm43xx_set_original_gains(bcm);
+ for (i = 0; i < 13; i++) {
+ if (!ret[i])
+ continue;
+ end = (i + 5 < 13) ? i + 5 : 13;
+ for (j = i; j < end; j++)
+ ret[j] = 1;
+ }
+ bcm43xx_radio_unlock(bcm);
+ bcm43xx_phy_unlock(bcm, phylock_flags);
+
+ return ret[channel - 1];
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val)
+{
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
+ mmiowb();
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val);
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset)
+{
+ u16 val;
+
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
+ val = bcm43xx_phy_read(bcm, BCM43xx_PHY_NRSSILT_DATA);
+
+ return (s16)val;
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val)
+{
+ u16 i;
+ s16 tmp;
+
+ for (i = 0; i < 64; i++) {
+ tmp = bcm43xx_nrssi_hw_read(bcm, i);
+ tmp -= val;
+ tmp = limit_value(tmp, -32, 31);
+ bcm43xx_nrssi_hw_write(bcm, i, tmp);
+ }
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ s16 i, delta;
+ s32 tmp;
+
+ delta = 0x1F - radio->nrssi[0];
+ for (i = 0; i < 64; i++) {
+ tmp = (i - delta) * radio->nrssislope;
+ tmp /= 0x10000;
+ tmp += 0x3A;
+ tmp = limit_value(tmp, 0, 0x3F);
+ radio->nrssi_lt[i] = tmp;
+ }
+}
+
+static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u16 backup[20] = { 0 };
+ s16 v47F;
+ u16 i;
+ u16 saved = 0xFFFF;
+
+ backup[0] = bcm43xx_phy_read(bcm, 0x0001);
+ backup[1] = bcm43xx_phy_read(bcm, 0x0811);
+ backup[2] = bcm43xx_phy_read(bcm, 0x0812);
+ backup[3] = bcm43xx_phy_read(bcm, 0x0814);
+ backup[4] = bcm43xx_phy_read(bcm, 0x0815);
+ backup[5] = bcm43xx_phy_read(bcm, 0x005A);
+ backup[6] = bcm43xx_phy_read(bcm, 0x0059);
+ backup[7] = bcm43xx_phy_read(bcm, 0x0058);
+ backup[8] = bcm43xx_phy_read(bcm, 0x000A);
+ backup[9] = bcm43xx_phy_read(bcm, 0x0003);
+ backup[10] = bcm43xx_radio_read16(bcm, 0x007A);
+ backup[11] = bcm43xx_radio_read16(bcm, 0x0043);
+
+ bcm43xx_phy_write(bcm, 0x0429,
+ bcm43xx_phy_read(bcm, 0x0429) & 0x7FFF);
+ bcm43xx_phy_write(bcm, 0x0001,
+ (bcm43xx_phy_read(bcm, 0x0001) & 0x3FFF) | 0x4000);
+ bcm43xx_phy_write(bcm, 0x0811,
+ bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
+ bcm43xx_phy_write(bcm, 0x0812,
+ (bcm43xx_phy_read(bcm, 0x0812) & 0xFFF3) | 0x0004);
+ bcm43xx_phy_write(bcm, 0x0802,
+ bcm43xx_phy_read(bcm, 0x0802) & ~(0x1 | 0x2));
+ if (phy->rev >= 6) {
+ backup[12] = bcm43xx_phy_read(bcm, 0x002E);
+ backup[13] = bcm43xx_phy_read(bcm, 0x002F);
+ backup[14] = bcm43xx_phy_read(bcm, 0x080F);
+ backup[15] = bcm43xx_phy_read(bcm, 0x0810);
+ backup[16] = bcm43xx_phy_read(bcm, 0x0801);
+ backup[17] = bcm43xx_phy_read(bcm, 0x0060);
+ backup[18] = bcm43xx_phy_read(bcm, 0x0014);
+ backup[19] = bcm43xx_phy_read(bcm, 0x0478);
+
+ bcm43xx_phy_write(bcm, 0x002E, 0);
+ bcm43xx_phy_write(bcm, 0x002F, 0);
+ bcm43xx_phy_write(bcm, 0x080F, 0);
+ bcm43xx_phy_write(bcm, 0x0810, 0);
+ bcm43xx_phy_write(bcm, 0x0478,
+ bcm43xx_phy_read(bcm, 0x0478) | 0x0100);
+ bcm43xx_phy_write(bcm, 0x0801,
+ bcm43xx_phy_read(bcm, 0x0801) | 0x0040);
+ bcm43xx_phy_write(bcm, 0x0060,
+ bcm43xx_phy_read(bcm, 0x0060) | 0x0040);
+ bcm43xx_phy_write(bcm, 0x0014,
+ bcm43xx_phy_read(bcm, 0x0014) | 0x0200);
+ }
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
+ udelay(30);
+
+ v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+ if (v47F >= 0x20)
+ v47F -= 0x40;
+ if (v47F == 31) {
+ for (i = 7; i >= 4; i--) {
+ bcm43xx_radio_write16(bcm, 0x007B, i);
+ udelay(20);
+ v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+ if (v47F >= 0x20)
+ v47F -= 0x40;
+ if (v47F < 31 && saved == 0xFFFF)
+ saved = i;
+ }
+ if (saved == 0xFFFF)
+ saved = 4;
+ } else {
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
+ bcm43xx_phy_write(bcm, 0x0814,
+ bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
+ bcm43xx_phy_write(bcm, 0x0815,
+ bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
+ bcm43xx_phy_write(bcm, 0x0811,
+ bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
+ bcm43xx_phy_write(bcm, 0x0812,
+ bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
+ bcm43xx_phy_write(bcm, 0x0811,
+ bcm43xx_phy_read(bcm, 0x0811) | 0x0030);
+ bcm43xx_phy_write(bcm, 0x0812,
+ bcm43xx_phy_read(bcm, 0x0812) | 0x0030);
+ bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+ bcm43xx_phy_write(bcm, 0x0059, 0x0810);
+ bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+ if (phy->rev == 0) {
+ bcm43xx_phy_write(bcm, 0x0003, 0x0122);
+ } else {
+ bcm43xx_phy_write(bcm, 0x000A,
+ bcm43xx_phy_read(bcm, 0x000A)
+ | 0x2000);
+ }
+ bcm43xx_phy_write(bcm, 0x0814,
+ bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
+ bcm43xx_phy_write(bcm, 0x0815,
+ bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
+ bcm43xx_phy_write(bcm, 0x0003,
+ (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F)
+ | 0x0040);
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
+ bcm43xx_set_all_gains(bcm, 3, 0, 1);
+ bcm43xx_radio_write16(bcm, 0x0043,
+ (bcm43xx_radio_read16(bcm, 0x0043)
+ & 0x00F0) | 0x000F);
+ udelay(30);
+ v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+ if (v47F >= 0x20)
+ v47F -= 0x40;
+ if (v47F == -32) {
+ for (i = 0; i < 4; i++) {
+ bcm43xx_radio_write16(bcm, 0x007B, i);
+ udelay(20);
+ v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+ if (v47F >= 0x20)
+ v47F -= 0x40;
+ if (v47F > -31 && saved == 0xFFFF)
+ saved = i;
+ }
+ if (saved == 0xFFFF)
+ saved = 3;
+ } else
+ saved = 0;
+ }
+ bcm43xx_radio_write16(bcm, 0x007B, saved);
+
+ if (phy->rev >= 6) {
+ bcm43xx_phy_write(bcm, 0x002E, backup[12]);
+ bcm43xx_phy_write(bcm, 0x002F, backup[13]);
+ bcm43xx_phy_write(bcm, 0x080F, backup[14]);
+ bcm43xx_phy_write(bcm, 0x0810, backup[15]);
+ }
+ bcm43xx_phy_write(bcm, 0x0814, backup[3]);
+ bcm43xx_phy_write(bcm, 0x0815, backup[4]);
+ bcm43xx_phy_write(bcm, 0x005A, backup[5]);
+ bcm43xx_phy_write(bcm, 0x0059, backup[6]);
+ bcm43xx_phy_write(bcm, 0x0058, backup[7]);
+ bcm43xx_phy_write(bcm, 0x000A, backup[8]);
+ bcm43xx_phy_write(bcm, 0x0003, backup[9]);
+ bcm43xx_radio_write16(bcm, 0x0043, backup[11]);
+ bcm43xx_radio_write16(bcm, 0x007A, backup[10]);
+ bcm43xx_phy_write(bcm, 0x0802,
+ bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2);
+ bcm43xx_phy_write(bcm, 0x0429,
+ bcm43xx_phy_read(bcm, 0x0429) | 0x8000);
+ bcm43xx_set_original_gains(bcm);
+ if (phy->rev >= 6) {
+ bcm43xx_phy_write(bcm, 0x0801, backup[16]);
+ bcm43xx_phy_write(bcm, 0x0060, backup[17]);
+ bcm43xx_phy_write(bcm, 0x0014, backup[18]);
+ bcm43xx_phy_write(bcm, 0x0478, backup[19]);
+ }
+ bcm43xx_phy_write(bcm, 0x0001, backup[0]);
+ bcm43xx_phy_write(bcm, 0x0812, backup[2]);
+ bcm43xx_phy_write(bcm, 0x0811, backup[1]);
+}
+
+void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 backup[18] = { 0 };
+ u16 tmp;
+ s16 nrssi0, nrssi1;
+
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_B:
+ backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
+ backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
+ backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
+ backup[3] = bcm43xx_phy_read(bcm, 0x0030);
+ backup[4] = bcm43xx_phy_read(bcm, 0x0026);
+ backup[5] = bcm43xx_phy_read(bcm, 0x0015);
+ backup[6] = bcm43xx_phy_read(bcm, 0x002A);
+ backup[7] = bcm43xx_phy_read(bcm, 0x0020);
+ backup[8] = bcm43xx_phy_read(bcm, 0x005A);
+ backup[9] = bcm43xx_phy_read(bcm, 0x0059);
+ backup[10] = bcm43xx_phy_read(bcm, 0x0058);
+ backup[11] = bcm43xx_read16(bcm, 0x03E2);
+ backup[12] = bcm43xx_read16(bcm, 0x03E6);
+ backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+
+ tmp = bcm43xx_radio_read16(bcm, 0x007A);
+ tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;
+ bcm43xx_radio_write16(bcm, 0x007A, tmp);
+ bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
+ bcm43xx_write16(bcm, 0x03EC, 0x7F7F);
+ bcm43xx_phy_write(bcm, 0x0026, 0x0000);
+ bcm43xx_phy_write(bcm, 0x0015,
+ bcm43xx_phy_read(bcm, 0x0015) | 0x0020);
+ bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
+
+ nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027);
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
+ if (phy->rev >= 2) {
+ bcm43xx_write16(bcm, 0x03E6, 0x0040);
+ } else if (phy->rev == 0) {
+ bcm43xx_write16(bcm, 0x03E6, 0x0122);
+ } else {
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+ bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000);
+ }
+ bcm43xx_phy_write(bcm, 0x0020, 0x3F3F);
+ bcm43xx_phy_write(bcm, 0x0015, 0xF330);
+ bcm43xx_radio_write16(bcm, 0x005A, 0x0060);
+ bcm43xx_radio_write16(bcm, 0x0043,
+ bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0);
+ bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+ bcm43xx_phy_write(bcm, 0x0059, 0x0810);
+ bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+ udelay(20);
+
+ nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027);
+ bcm43xx_phy_write(bcm, 0x0030, backup[3]);
+ bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
+ bcm43xx_write16(bcm, 0x03E2, backup[11]);
+ bcm43xx_phy_write(bcm, 0x0026, backup[4]);
+ bcm43xx_phy_write(bcm, 0x0015, backup[5]);
+ bcm43xx_phy_write(bcm, 0x002A, backup[6]);
+ bcm43xx_synth_pu_workaround(bcm, radio->channel);
+ if (phy->rev != 0)
+ bcm43xx_write16(bcm, 0x03F4, backup[13]);
+
+ bcm43xx_phy_write(bcm, 0x0020, backup[7]);
+ bcm43xx_phy_write(bcm, 0x005A, backup[8]);
+ bcm43xx_phy_write(bcm, 0x0059, backup[9]);
+ bcm43xx_phy_write(bcm, 0x0058, backup[10]);
+ bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
+ bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
+
+ if (nrssi0 == nrssi1)
+ radio->nrssislope = 0x00010000;
+ else
+ radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
+
+ if (nrssi0 <= -4) {
+ radio->nrssi[0] = nrssi0;
+ radio->nrssi[1] = nrssi1;
+ }
+ break;
+ case BCM43xx_PHYTYPE_G:
+ if (radio->revision >= 9)
+ return;
+ if (radio->revision == 8)
+ bcm43xx_calc_nrssi_offset(bcm);
+
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+ bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
+ bcm43xx_phy_write(bcm, 0x0802,
+ bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
+ backup[7] = bcm43xx_read16(bcm, 0x03E2);
+ bcm43xx_write16(bcm, 0x03E2,
+ bcm43xx_read16(bcm, 0x03E2) | 0x8000);
+ backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
+ backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
+ backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
+ backup[3] = bcm43xx_phy_read(bcm, 0x0015);
+ backup[4] = bcm43xx_phy_read(bcm, 0x005A);
+ backup[5] = bcm43xx_phy_read(bcm, 0x0059);
+ backup[6] = bcm43xx_phy_read(bcm, 0x0058);
+ backup[8] = bcm43xx_read16(bcm, 0x03E6);
+ backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+ if (phy->rev >= 3) {
+ backup[10] = bcm43xx_phy_read(bcm, 0x002E);
+ backup[11] = bcm43xx_phy_read(bcm, 0x002F);
+ backup[12] = bcm43xx_phy_read(bcm, 0x080F);
+ backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL);
+ backup[14] = bcm43xx_phy_read(bcm, 0x0801);
+ backup[15] = bcm43xx_phy_read(bcm, 0x0060);
+ backup[16] = bcm43xx_phy_read(bcm, 0x0014);
+ backup[17] = bcm43xx_phy_read(bcm, 0x0478);
+ bcm43xx_phy_write(bcm, 0x002E, 0);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0);
+ switch (phy->rev) {
+ case 4: case 6: case 7:
+ bcm43xx_phy_write(bcm, 0x0478,
+ bcm43xx_phy_read(bcm, 0x0478)
+ | 0x0100);
+ bcm43xx_phy_write(bcm, 0x0801,
+ bcm43xx_phy_read(bcm, 0x0801)
+ | 0x0040);
+ break;
+ case 3: case 5:
+ bcm43xx_phy_write(bcm, 0x0801,
+ bcm43xx_phy_read(bcm, 0x0801)
+ & 0xFFBF);
+ break;
+ }
+ bcm43xx_phy_write(bcm, 0x0060,
+ bcm43xx_phy_read(bcm, 0x0060)
+ | 0x0040);
+ bcm43xx_phy_write(bcm, 0x0014,
+ bcm43xx_phy_read(bcm, 0x0014)
+ | 0x0200);
+ }
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
+ bcm43xx_set_all_gains(bcm, 0, 8, 0);
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7);
+ if (phy->rev >= 2) {
+ bcm43xx_phy_write(bcm, 0x0811,
+ (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030);
+ bcm43xx_phy_write(bcm, 0x0812,
+ (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010);
+ }
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
+ udelay(20);
+
+ nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+ if (nrssi0 >= 0x0020)
+ nrssi0 -= 0x0040;
+
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
+ if (phy->rev >= 2) {
+ bcm43xx_phy_write(bcm, 0x0003,
+ (bcm43xx_phy_read(bcm, 0x0003)
+ & 0xFF9F) | 0x0040);
+ }
+
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+ bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+ | 0x2000);
+ bcm43xx_radio_write16(bcm, 0x007A,
+ bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
+ bcm43xx_phy_write(bcm, 0x0015, 0xF330);
+ if (phy->rev >= 2) {
+ bcm43xx_phy_write(bcm, 0x0812,
+ (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020);
+ bcm43xx_phy_write(bcm, 0x0811,
+ (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020);
+ }
+
+ bcm43xx_set_all_gains(bcm, 3, 0, 1);
+ if (radio->revision == 8) {
+ bcm43xx_radio_write16(bcm, 0x0043, 0x001F);
+ } else {
+ tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F;
+ bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060);
+ tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0;
+ bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009);
+ }
+ bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+ bcm43xx_phy_write(bcm, 0x0059, 0x0810);
+ bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+ udelay(20);
+ nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+ if (nrssi1 >= 0x0020)
+ nrssi1 -= 0x0040;
+ if (nrssi0 == nrssi1)
+ radio->nrssislope = 0x00010000;
+ else
+ radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
+ if (nrssi0 >= -4) {
+ radio->nrssi[0] = nrssi1;
+ radio->nrssi[1] = nrssi0;
+ }
+ if (phy->rev >= 3) {
+ bcm43xx_phy_write(bcm, 0x002E, backup[10]);
+ bcm43xx_phy_write(bcm, 0x002F, backup[11]);
+ bcm43xx_phy_write(bcm, 0x080F, backup[12]);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]);
+ }
+ if (phy->rev >= 2) {
+ bcm43xx_phy_write(bcm, 0x0812,
+ bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF);
+ bcm43xx_phy_write(bcm, 0x0811,
+ bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF);
+ }
+
+ bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
+ bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
+ bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
+ bcm43xx_write16(bcm, 0x03E2, backup[7]);
+ bcm43xx_write16(bcm, 0x03E6, backup[8]);
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]);
+ bcm43xx_phy_write(bcm, 0x0015, backup[3]);
+ bcm43xx_phy_write(bcm, 0x005A, backup[4]);
+ bcm43xx_phy_write(bcm, 0x0059, backup[5]);
+ bcm43xx_phy_write(bcm, 0x0058, backup[6]);
+ bcm43xx_synth_pu_workaround(bcm, radio->channel);
+ bcm43xx_phy_write(bcm, 0x0802,
+ bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002));
+ bcm43xx_set_original_gains(bcm);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+ bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
+ if (phy->rev >= 3) {
+ bcm43xx_phy_write(bcm, 0x0801, backup[14]);
+ bcm43xx_phy_write(bcm, 0x0060, backup[15]);
+ bcm43xx_phy_write(bcm, 0x0014, backup[16]);
+ bcm43xx_phy_write(bcm, 0x0478, backup[17]);
+ }
+ bcm43xx_nrssi_mem_update(bcm);
+ bcm43xx_calc_nrssi_threshold(bcm);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ s32 threshold;
+ s32 a, b;
+ s16 tmp16;
+ u16 tmp_u16;
+
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_B: {
+ if (radio->version != 0x2050)
+ return;
+ if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI))
+ return;
+
+ if (radio->revision >= 6) {
+ threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32;
+ threshold += 20 * (radio->nrssi[0] + 1);
+ threshold /= 40;
+ } else
+ threshold = radio->nrssi[1] - 5;
+
+ threshold = limit_value(threshold, 0, 0x3E);
+ bcm43xx_phy_read(bcm, 0x0020); /* dummy read */
+ bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C);
+
+ if (radio->revision >= 6) {
+ bcm43xx_phy_write(bcm, 0x0087, 0x0E0D);
+ bcm43xx_phy_write(bcm, 0x0086, 0x0C0B);
+ bcm43xx_phy_write(bcm, 0x0085, 0x0A09);
+ bcm43xx_phy_write(bcm, 0x0084, 0x0808);
+ bcm43xx_phy_write(bcm, 0x0083, 0x0808);
+ bcm43xx_phy_write(bcm, 0x0082, 0x0604);
+ bcm43xx_phy_write(bcm, 0x0081, 0x0302);
+ bcm43xx_phy_write(bcm, 0x0080, 0x0100);
+ }
+ break;
+ }
+ case BCM43xx_PHYTYPE_G:
+ if (!phy->connected ||
+ !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
+ tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20);
+ if (tmp16 >= 0x20)
+ tmp16 -= 0x40;
+ if (tmp16 < 3) {
+ bcm43xx_phy_write(bcm, 0x048A,
+ (bcm43xx_phy_read(bcm, 0x048A)
+ & 0xF000) | 0x09EB);
+ } else {
+ bcm43xx_phy_write(bcm, 0x048A,
+ (bcm43xx_phy_read(bcm, 0x048A)
+ & 0xF000) | 0x0AED);
+ }
+ } else {
+ if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) {
+ a = 0xE;
+ b = 0xA;
+ } else if (!radio->aci_wlan_automatic && radio->aci_enable) {
+ a = 0x13;
+ b = 0x12;
+ } else {
+ a = 0xE;
+ b = 0x11;
+ }
+
+ a = a * (radio->nrssi[1] - radio->nrssi[0]);
+ a += (radio->nrssi[0] << 6);
+ if (a < 32)
+ a += 31;
+ else
+ a += 32;
+ a = a >> 6;
+ a = limit_value(a, -31, 31);
+
+ b = b * (radio->nrssi[1] - radio->nrssi[0]);
+ b += (radio->nrssi[0] << 6);
+ if (b < 32)
+ b += 31;
+ else
+ b += 32;
+ b = b >> 6;
+ b = limit_value(b, -31, 31);
+
+ tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000;
+ tmp_u16 |= ((u32)b & 0x0000003F);
+ tmp_u16 |= (((u32)a & 0x0000003F) << 6);
+ bcm43xx_phy_write(bcm, 0x048A, tmp_u16);
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+/* Stack implementation to save/restore values from the
+ * interference mitigation code.
+ * It is save to restore values in random order.
+ */
+static void _stack_save(u32 *_stackptr, size_t *stackidx,
+ u8 id, u16 offset, u16 value)
+{
+ u32 *stackptr = &(_stackptr[*stackidx]);
+
+ assert((offset & 0xF000) == 0x0000);
+ assert((id & 0xF0) == 0x00);
+ *stackptr = offset;
+ *stackptr |= ((u32)id) << 12;
+ *stackptr |= ((u32)value) << 16;
+ (*stackidx)++;
+ assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);
+}
+
+static u16 _stack_restore(u32 *stackptr,
+ u8 id, u16 offset)
+{
+ size_t i;
+
+ assert((offset & 0xF000) == 0x0000);
+ assert((id & 0xF0) == 0x00);
+ for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) {
+ if ((*stackptr & 0x00000FFF) != offset)
+ continue;
+ if (((*stackptr & 0x0000F000) >> 12) != id)
+ continue;
+ return ((*stackptr & 0xFFFF0000) >> 16);
+ }
+ assert(0);
+
+ return 0;
+}
+
+#define phy_stacksave(offset) \
+ do { \
+ _stack_save(stack, &stackidx, 0x1, (offset), \
+ bcm43xx_phy_read(bcm, (offset))); \
+ } while (0)
+#define phy_stackrestore(offset) \
+ do { \
+ bcm43xx_phy_write(bcm, (offset), \
+ _stack_restore(stack, 0x1, \
+ (offset))); \
+ } while (0)
+#define radio_stacksave(offset) \
+ do { \
+ _stack_save(stack, &stackidx, 0x2, (offset), \
+ bcm43xx_radio_read16(bcm, (offset))); \
+ } while (0)
+#define radio_stackrestore(offset) \
+ do { \
+ bcm43xx_radio_write16(bcm, (offset), \
+ _stack_restore(stack, 0x2, \
+ (offset))); \
+ } while (0)
+#define ilt_stacksave(offset) \
+ do { \
+ _stack_save(stack, &stackidx, 0x3, (offset), \
+ bcm43xx_ilt_read(bcm, (offset))); \
+ } while (0)
+#define ilt_stackrestore(offset) \
+ do { \
+ bcm43xx_ilt_write(bcm, (offset), \
+ _stack_restore(stack, 0x3, \
+ (offset))); \
+ } while (0)
+
+static void
+bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm,
+ int mode)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 tmp, flipped;
+ u32 tmp32;
+ size_t stackidx = 0;
+ u32 *stack = radio->interfstack;
+
+ switch (mode) {
+ case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+ if (phy->rev != 1) {
+ bcm43xx_phy_write(bcm, 0x042B,
+ bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+ bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000);
+ break;
+ }
+ radio_stacksave(0x0078);
+ tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E);
+ flipped = flip_4bit(tmp);
+ if (flipped < 10 && flipped >= 8)
+ flipped = 7;
+ else if (flipped >= 10)
+ flipped -= 3;
+ flipped = flip_4bit(flipped);
+ flipped = (flipped << 1) | 0x0020;
+ bcm43xx_radio_write16(bcm, 0x0078, flipped);
+
+ bcm43xx_calc_nrssi_threshold(bcm);
+
+ phy_stacksave(0x0406);
+ bcm43xx_phy_write(bcm, 0x0406, 0x7E28);
+
+ bcm43xx_phy_write(bcm, 0x042B,
+ bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+ bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000);
+
+ phy_stacksave(0x04A0);
+ bcm43xx_phy_write(bcm, 0x04A0,
+ (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008);
+ phy_stacksave(0x04A1);
+ bcm43xx_phy_write(bcm, 0x04A1,
+ (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605);
+ phy_stacksave(0x04A2);
+ bcm43xx_phy_write(bcm, 0x04A2,
+ (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204);
+ phy_stacksave(0x04A8);
+ bcm43xx_phy_write(bcm, 0x04A8,
+ (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803);
+ phy_stacksave(0x04AB);
+ bcm43xx_phy_write(bcm, 0x04AB,
+ (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605);
+
+ phy_stacksave(0x04A7);
+ bcm43xx_phy_write(bcm, 0x04A7, 0x0002);
+ phy_stacksave(0x04A3);
+ bcm43xx_phy_write(bcm, 0x04A3, 0x287A);
+ phy_stacksave(0x04A9);
+ bcm43xx_phy_write(bcm, 0x04A9, 0x2027);
+ phy_stacksave(0x0493);
+ bcm43xx_phy_write(bcm, 0x0493, 0x32F5);
+ phy_stacksave(0x04AA);
+ bcm43xx_phy_write(bcm, 0x04AA, 0x2027);
+ phy_stacksave(0x04AC);
+ bcm43xx_phy_write(bcm, 0x04AC, 0x32F5);
+ break;
+ case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+ if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800)
+ break;
+
+ radio->aci_enable = 1;
+
+ phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD);
+ phy_stacksave(BCM43xx_PHY_G_CRS);
+ if (phy->rev < 2) {
+ phy_stacksave(0x0406);
+ } else {
+ phy_stacksave(0x04C0);
+ phy_stacksave(0x04C1);
+ }
+ phy_stacksave(0x0033);
+ phy_stacksave(0x04A7);
+ phy_stacksave(0x04A3);
+ phy_stacksave(0x04A9);
+ phy_stacksave(0x04AA);
+ phy_stacksave(0x04AC);
+ phy_stacksave(0x0493);
+ phy_stacksave(0x04A1);
+ phy_stacksave(0x04A0);
+ phy_stacksave(0x04A2);
+ phy_stacksave(0x048A);
+ phy_stacksave(0x04A8);
+ phy_stacksave(0x04AB);
+ if (phy->rev == 2) {
+ phy_stacksave(0x04AD);
+ phy_stacksave(0x04AE);
+ } else if (phy->rev >= 3) {
+ phy_stacksave(0x04AD);
+ phy_stacksave(0x0415);
+ phy_stacksave(0x0416);
+ phy_stacksave(0x0417);
+ ilt_stacksave(0x1A00 + 0x2);
+ ilt_stacksave(0x1A00 + 0x3);
+ }
+ phy_stacksave(0x042B);
+ phy_stacksave(0x048C);
+
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+ bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
+ & ~0x1000);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+ (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
+ & 0xFFFC) | 0x0002);
+
+ bcm43xx_phy_write(bcm, 0x0033, 0x0800);
+ bcm43xx_phy_write(bcm, 0x04A3, 0x2027);
+ bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8);
+ bcm43xx_phy_write(bcm, 0x0493, 0x287A);
+ bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8);
+ bcm43xx_phy_write(bcm, 0x04AC, 0x287A);
+
+ bcm43xx_phy_write(bcm, 0x04A0,
+ (bcm43xx_phy_read(bcm, 0x04A0)
+ & 0xFFC0) | 0x001A);
+ bcm43xx_phy_write(bcm, 0x04A7, 0x000D);
+
+ if (phy->rev < 2) {
+ bcm43xx_phy_write(bcm, 0x0406, 0xFF0D);
+ } else if (phy->rev == 2) {
+ bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF);
+ bcm43xx_phy_write(bcm, 0x04C1, 0x00A9);
+ } else {
+ bcm43xx_phy_write(bcm, 0x04C0, 0x00C1);
+ bcm43xx_phy_write(bcm, 0x04C1, 0x0059);
+ }
+
+ bcm43xx_phy_write(bcm, 0x04A1,
+ (bcm43xx_phy_read(bcm, 0x04A1)
+ & 0xC0FF) | 0x1800);
+ bcm43xx_phy_write(bcm, 0x04A1,
+ (bcm43xx_phy_read(bcm, 0x04A1)
+ & 0xFFC0) | 0x0015);
+ bcm43xx_phy_write(bcm, 0x04A8,
+ (bcm43xx_phy_read(bcm, 0x04A8)
+ & 0xCFFF) | 0x1000);
+ bcm43xx_phy_write(bcm, 0x04A8,
+ (bcm43xx_phy_read(bcm, 0x04A8)
+ & 0xF0FF) | 0x0A00);
+ bcm43xx_phy_write(bcm, 0x04AB,
+ (bcm43xx_phy_read(bcm, 0x04AB)
+ & 0xCFFF) | 0x1000);
+ bcm43xx_phy_write(bcm, 0x04AB,
+ (bcm43xx_phy_read(bcm, 0x04AB)
+ & 0xF0FF) | 0x0800);
+ bcm43xx_phy_write(bcm, 0x04AB,
+ (bcm43xx_phy_read(bcm, 0x04AB)
+ & 0xFFCF) | 0x0010);
+ bcm43xx_phy_write(bcm, 0x04AB,
+ (bcm43xx_phy_read(bcm, 0x04AB)
+ & 0xFFF0) | 0x0005);
+ bcm43xx_phy_write(bcm, 0x04A8,
+ (bcm43xx_phy_read(bcm, 0x04A8)
+ & 0xFFCF) | 0x0010);
+ bcm43xx_phy_write(bcm, 0x04A8,
+ (bcm43xx_phy_read(bcm, 0x04A8)
+ & 0xFFF0) | 0x0006);
+ bcm43xx_phy_write(bcm, 0x04A2,
+ (bcm43xx_phy_read(bcm, 0x04A2)
+ & 0xF0FF) | 0x0800);
+ bcm43xx_phy_write(bcm, 0x04A0,
+ (bcm43xx_phy_read(bcm, 0x04A0)
+ & 0xF0FF) | 0x0500);
+ bcm43xx_phy_write(bcm, 0x04A2,
+ (bcm43xx_phy_read(bcm, 0x04A2)
+ & 0xFFF0) | 0x000B);
+
+ if (phy->rev >= 3) {
+ bcm43xx_phy_write(bcm, 0x048A,
+ bcm43xx_phy_read(bcm, 0x048A)
+ & ~0x8000);
+ bcm43xx_phy_write(bcm, 0x0415,
+ (bcm43xx_phy_read(bcm, 0x0415)
+ & 0x8000) | 0x36D8);
+ bcm43xx_phy_write(bcm, 0x0416,
+ (bcm43xx_phy_read(bcm, 0x0416)
+ & 0x8000) | 0x36D8);
+ bcm43xx_phy_write(bcm, 0x0417,
+ (bcm43xx_phy_read(bcm, 0x0417)
+ & 0xFE00) | 0x016D);
+ } else {
+ bcm43xx_phy_write(bcm, 0x048A,
+ bcm43xx_phy_read(bcm, 0x048A)
+ | 0x1000);
+ bcm43xx_phy_write(bcm, 0x048A,
+ (bcm43xx_phy_read(bcm, 0x048A)
+ & 0x9FFF) | 0x2000);
+ tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET);
+ if (!(tmp32 & 0x800)) {
+ tmp32 |= 0x800;
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET,
+ tmp32);
+ }
+ }
+ if (phy->rev >= 2) {
+ bcm43xx_phy_write(bcm, 0x042B,
+ bcm43xx_phy_read(bcm, 0x042B)
+ | 0x0800);
+ }
+ bcm43xx_phy_write(bcm, 0x048C,
+ (bcm43xx_phy_read(bcm, 0x048C)
+ & 0xF0FF) | 0x0200);
+ if (phy->rev == 2) {
+ bcm43xx_phy_write(bcm, 0x04AE,
+ (bcm43xx_phy_read(bcm, 0x04AE)
+ & 0xFF00) | 0x007F);
+ bcm43xx_phy_write(bcm, 0x04AD,
+ (bcm43xx_phy_read(bcm, 0x04AD)
+ & 0x00FF) | 0x1300);
+ } else if (phy->rev >= 6) {
+ bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F);
+ bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F);
+ bcm43xx_phy_write(bcm, 0x04AD,
+ bcm43xx_phy_read(bcm, 0x04AD)
+ & 0x00FF);
+ }
+ bcm43xx_calc_nrssi_slope(bcm);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void
+bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm,
+ int mode)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u32 tmp32;
+ u32 *stack = radio->interfstack;
+
+ switch (mode) {
+ case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+ if (phy->rev != 1) {
+ bcm43xx_phy_write(bcm, 0x042B,
+ bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+ bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
+ break;
+ }
+ phy_stackrestore(0x0078);
+ bcm43xx_calc_nrssi_threshold(bcm);
+ phy_stackrestore(0x0406);
+ bcm43xx_phy_write(bcm, 0x042B,
+ bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
+ if (!bcm->bad_frames_preempt) {
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+ bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
+ & ~(1 << 11));
+ }
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+ bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
+ phy_stackrestore(0x04A0);
+ phy_stackrestore(0x04A1);
+ phy_stackrestore(0x04A2);
+ phy_stackrestore(0x04A8);
+ phy_stackrestore(0x04AB);
+ phy_stackrestore(0x04A7);
+ phy_stackrestore(0x04A3);
+ phy_stackrestore(0x04A9);
+ phy_stackrestore(0x0493);
+ phy_stackrestore(0x04AA);
+ phy_stackrestore(0x04AC);
+ break;
+ case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+ if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800))
+ break;
+
+ radio->aci_enable = 0;
+
+ phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD);
+ phy_stackrestore(BCM43xx_PHY_G_CRS);
+ phy_stackrestore(0x0033);
+ phy_stackrestore(0x04A3);
+ phy_stackrestore(0x04A9);
+ phy_stackrestore(0x0493);
+ phy_stackrestore(0x04AA);
+ phy_stackrestore(0x04AC);
+ phy_stackrestore(0x04A0);
+ phy_stackrestore(0x04A7);
+ if (phy->rev >= 2) {
+ phy_stackrestore(0x04C0);
+ phy_stackrestore(0x04C1);
+ } else
+ phy_stackrestore(0x0406);
+ phy_stackrestore(0x04A1);
+ phy_stackrestore(0x04AB);
+ phy_stackrestore(0x04A8);
+ if (phy->rev == 2) {
+ phy_stackrestore(0x04AD);
+ phy_stackrestore(0x04AE);
+ } else if (phy->rev >= 3) {
+ phy_stackrestore(0x04AD);
+ phy_stackrestore(0x0415);
+ phy_stackrestore(0x0416);
+ phy_stackrestore(0x0417);
+ ilt_stackrestore(0x1A00 + 0x2);
+ ilt_stackrestore(0x1A00 + 0x3);
+ }
+ phy_stackrestore(0x04A2);
+ phy_stackrestore(0x04A8);
+ phy_stackrestore(0x042B);
+ phy_stackrestore(0x048C);
+ tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET);
+ if (tmp32 & 0x800) {
+ tmp32 &= ~0x800;
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET,
+ tmp32);
+ }
+ bcm43xx_calc_nrssi_slope(bcm);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+#undef phy_stacksave
+#undef phy_stackrestore
+#undef radio_stacksave
+#undef radio_stackrestore
+#undef ilt_stacksave
+#undef ilt_stackrestore
+
+int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm,
+ int mode)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ int currentmode;
+
+ if ((phy->type != BCM43xx_PHYTYPE_G) ||
+ (phy->rev == 0) ||
+ (!phy->connected))
+ return -ENODEV;
+
+ radio->aci_wlan_automatic = 0;
+ switch (mode) {
+ case BCM43xx_RADIO_INTERFMODE_AUTOWLAN:
+ radio->aci_wlan_automatic = 1;
+ if (radio->aci_enable)
+ mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
+ else
+ mode = BCM43xx_RADIO_INTERFMODE_NONE;
+ break;
+ case BCM43xx_RADIO_INTERFMODE_NONE:
+ case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+ case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ currentmode = radio->interfmode;
+ if (currentmode == mode)
+ return 0;
+ if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE)
+ bcm43xx_radio_interference_mitigation_disable(bcm, currentmode);
+
+ if (mode == BCM43xx_RADIO_INTERFMODE_NONE) {
+ radio->aci_enable = 0;
+ radio->aci_hw_rssi = 0;
+ } else
+ bcm43xx_radio_interference_mitigation_enable(bcm, mode);
+ radio->interfmode = mode;
+
+ return 0;
+}
+
+u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm)
+{
+ u16 reg, index, ret;
+
+ reg = bcm43xx_radio_read16(bcm, 0x0060);
+ index = (reg & 0x001E) >> 1;
+ ret = rcc_table[index] << 1;
+ ret |= (reg & 0x0001);
+ ret |= 0x0020;
+
+ return ret;
+}
+
+u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 backup[19] = { 0 };
+ u16 ret;
+ u16 i, j;
+ u32 tmp1 = 0, tmp2 = 0;
+
+ backup[0] = bcm43xx_radio_read16(bcm, 0x0043);
+ backup[14] = bcm43xx_radio_read16(bcm, 0x0051);
+ backup[15] = bcm43xx_radio_read16(bcm, 0x0052);
+ backup[1] = bcm43xx_phy_read(bcm, 0x0015);
+ backup[16] = bcm43xx_phy_read(bcm, 0x005A);
+ backup[17] = bcm43xx_phy_read(bcm, 0x0059);
+ backup[18] = bcm43xx_phy_read(bcm, 0x0058);
+ if (phy->type == BCM43xx_PHYTYPE_B) {
+ backup[2] = bcm43xx_phy_read(bcm, 0x0030);
+ backup[3] = bcm43xx_read16(bcm, 0x03EC);
+ bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
+ bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
+ } else {
+ if (phy->connected) {
+ backup[4] = bcm43xx_phy_read(bcm, 0x0811);
+ backup[5] = bcm43xx_phy_read(bcm, 0x0812);
+ backup[6] = bcm43xx_phy_read(bcm, 0x0814);
+ backup[7] = bcm43xx_phy_read(bcm, 0x0815);
+ backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
+ backup[9] = bcm43xx_phy_read(bcm, 0x0802);
+ bcm43xx_phy_write(bcm, 0x0814,
+ (bcm43xx_phy_read(bcm, 0x0814) | 0x0003));
+ bcm43xx_phy_write(bcm, 0x0815,
+ (bcm43xx_phy_read(bcm, 0x0815) & 0xFFFC));
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+ (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF));
+ bcm43xx_phy_write(bcm, 0x0802,
+ (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC));
+ bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
+ bcm43xx_phy_write(bcm, 0x0812, 0x0FB2);
+ }
+ bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
+ (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000));
+ }
+ backup[10] = bcm43xx_phy_read(bcm, 0x0035);
+ bcm43xx_phy_write(bcm, 0x0035,
+ (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F));
+ backup[11] = bcm43xx_read16(bcm, 0x03E6);
+ backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+
+ // Initialization
+ if (phy->version == 0) {
+ bcm43xx_write16(bcm, 0x03E6, 0x0122);
+ } else {
+ if (phy->version >= 2)
+ bcm43xx_write16(bcm, 0x03E6, 0x0040);
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+ (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000));
+ }
+
+ ret = bcm43xx_radio_calibrationvalue(bcm);
+
+ if (phy->type == BCM43xx_PHYTYPE_B)
+ bcm43xx_radio_write16(bcm, 0x0078, 0x0003);
+
+ bcm43xx_phy_write(bcm, 0x0015, 0xBFAF);
+ bcm43xx_phy_write(bcm, 0x002B, 0x1403);
+ if (phy->connected)
+ bcm43xx_phy_write(bcm, 0x0812, 0x00B2);
+ bcm43xx_phy_write(bcm, 0x0015, 0xBFA0);
+ bcm43xx_radio_write16(bcm, 0x0051,
+ (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004));
+ bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
+ bcm43xx_radio_write16(bcm, 0x0043,
+ bcm43xx_radio_read16(bcm, 0x0043) | 0x0009);
+ bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+
+ for (i = 0; i < 16; i++) {
+ bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+ bcm43xx_phy_write(bcm, 0x0059, 0xC810);
+ bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+ if (phy->connected)
+ bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+ bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+ udelay(10);
+ if (phy->connected)
+ bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+ bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
+ udelay(10);
+ if (phy->connected)
+ bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+ bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
+ udelay(10);
+ tmp1 += bcm43xx_phy_read(bcm, 0x002D);
+ bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+ if (phy->connected)
+ bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+ bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+ }
+
+ tmp1++;
+ tmp1 >>= 9;
+ udelay(10);
+ bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+
+ for (i = 0; i < 16; i++) {
+ bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020);
+ backup[13] = bcm43xx_radio_read16(bcm, 0x0078);
+ udelay(10);
+ for (j = 0; j < 16; j++) {
+ bcm43xx_phy_write(bcm, 0x005A, 0x0D80);
+ bcm43xx_phy_write(bcm, 0x0059, 0xC810);
+ bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+ if (phy->connected)
+ bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+ bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+ udelay(10);
+ if (phy->connected)
+ bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+ bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
+ udelay(10);
+ if (phy->connected)
+ bcm43xx_phy_write(bcm, 0x0812, 0x30B3); /* 0x30B3 is not a typo */
+ bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
+ udelay(10);
+ tmp2 += bcm43xx_phy_read(bcm, 0x002D);
+ bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+ if (phy->connected)
+ bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+ bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+ }
+ tmp2++;
+ tmp2 >>= 8;
+ if (tmp1 < tmp2)
+ break;
+ }
+
+ /* Restore the registers */
+ bcm43xx_phy_write(bcm, 0x0015, backup[1]);
+ bcm43xx_radio_write16(bcm, 0x0051, backup[14]);
+ bcm43xx_radio_write16(bcm, 0x0052, backup[15]);
+ bcm43xx_radio_write16(bcm, 0x0043, backup[0]);
+ bcm43xx_phy_write(bcm, 0x005A, backup[16]);
+ bcm43xx_phy_write(bcm, 0x0059, backup[17]);
+ bcm43xx_phy_write(bcm, 0x0058, backup[18]);
+ bcm43xx_write16(bcm, 0x03E6, backup[11]);
+ if (phy->version != 0)
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]);
+ bcm43xx_phy_write(bcm, 0x0035, backup[10]);
+ bcm43xx_radio_selectchannel(bcm, radio->channel, 1);
+ if (phy->type == BCM43xx_PHYTYPE_B) {
+ bcm43xx_phy_write(bcm, 0x0030, backup[2]);
+ bcm43xx_write16(bcm, 0x03EC, backup[3]);
+ } else {
+ bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
+ (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) & 0x7FFF));
+ if (phy->connected) {
+ bcm43xx_phy_write(bcm, 0x0811, backup[4]);
+ bcm43xx_phy_write(bcm, 0x0812, backup[5]);
+ bcm43xx_phy_write(bcm, 0x0814, backup[6]);
+ bcm43xx_phy_write(bcm, 0x0815, backup[7]);
+ bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]);
+ bcm43xx_phy_write(bcm, 0x0802, backup[9]);
+ }
+ }
+ if (i >= 15)
+ ret = backup[13];
+
+ return ret;
+}
+
+void bcm43xx_radio_init2060(struct bcm43xx_private *bcm)
+{
+ int err;
+
+ bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
+ bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
+ bcm43xx_radio_write16(bcm, 0x0009, 0x0040);
+ bcm43xx_radio_write16(bcm, 0x0005, 0x00AA);
+ bcm43xx_radio_write16(bcm, 0x0032, 0x008F);
+ bcm43xx_radio_write16(bcm, 0x0006, 0x008F);
+ bcm43xx_radio_write16(bcm, 0x0034, 0x008F);
+ bcm43xx_radio_write16(bcm, 0x002C, 0x0007);
+ bcm43xx_radio_write16(bcm, 0x0082, 0x0080);
+ bcm43xx_radio_write16(bcm, 0x0080, 0x0000);
+ bcm43xx_radio_write16(bcm, 0x003F, 0x00DA);
+ bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
+ bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010);
+ bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
+ bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
+ udelay(400);
+
+ bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010);
+ udelay(400);
+
+ bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008);
+ bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010);
+ bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
+ bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040);
+ bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040);
+ bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008);
+ bcm43xx_phy_write(bcm, 0x0063, 0xDDC6);
+ bcm43xx_phy_write(bcm, 0x0069, 0x07BE);
+ bcm43xx_phy_write(bcm, 0x006A, 0x0000);
+
+ err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0);
+ assert(err == 0);
+ udelay(1000);
+}
+
+static inline
+u16 freq_r3A_value(u16 frequency)
+{
+ u16 value;
+
+ if (frequency < 5091)
+ value = 0x0040;
+ else if (frequency < 5321)
+ value = 0x0000;
+ else if (frequency < 5806)
+ value = 0x0080;
+ else
+ value = 0x0040;
+
+ return value;
+}
+
+void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm)
+{
+ static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
+ static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
+ u16 tmp = bcm43xx_radio_read16(bcm, 0x001E);
+ int i, j;
+
+ for (i = 0; i < 5; i++) {
+ for (j = 0; j < 5; j++) {
+ if (tmp == (data_high[i] << 4 | data_low[j])) {
+ bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0);
+ return;
+ }
+ }
+ }
+}
+
+int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
+ u8 channel,
+ int synthetic_pu_workaround)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 r8, tmp;
+ u16 freq;
+
+ if ((radio->manufact == 0x17F) &&
+ (radio->version == 0x2060) &&
+ (radio->revision == 1)) {
+ if (channel > 200)
+ return -EINVAL;
+ freq = channel2freq_a(channel);
+
+ r8 = bcm43xx_radio_read16(bcm, 0x0008);
+ bcm43xx_write16(bcm, 0x03F0, freq);
+ bcm43xx_radio_write16(bcm, 0x0008, r8);
+
+ TODO();//TODO: write max channel TX power? to Radio 0x2D
+ tmp = bcm43xx_radio_read16(bcm, 0x002E);
+ tmp &= 0x0080;
+ TODO();//TODO: OR tmp with the Power out estimation for this channel?
+ bcm43xx_radio_write16(bcm, 0x002E, tmp);
+
+ if (freq >= 4920 && freq <= 5500) {
+ /*
+ * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
+ * = (freq * 0.025862069
+ */
+ r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
+ }
+ bcm43xx_radio_write16(bcm, 0x0007, (r8 << 4) | r8);
+ bcm43xx_radio_write16(bcm, 0x0020, (r8 << 4) | r8);
+ bcm43xx_radio_write16(bcm, 0x0021, (r8 << 4) | r8);
+ bcm43xx_radio_write16(bcm, 0x0022,
+ (bcm43xx_radio_read16(bcm, 0x0022)
+ & 0x000F) | (r8 << 4));
+ bcm43xx_radio_write16(bcm, 0x002A, (r8 << 4));
+ bcm43xx_radio_write16(bcm, 0x002B, (r8 << 4));
+ bcm43xx_radio_write16(bcm, 0x0008,
+ (bcm43xx_radio_read16(bcm, 0x0008)
+ & 0x00F0) | (r8 << 4));
+ bcm43xx_radio_write16(bcm, 0x0029,
+ (bcm43xx_radio_read16(bcm, 0x0029)
+ & 0xFF0F) | 0x00B0);
+ bcm43xx_radio_write16(bcm, 0x0035, 0x00AA);
+ bcm43xx_radio_write16(bcm, 0x0036, 0x0085);
+ bcm43xx_radio_write16(bcm, 0x003A,
+ (bcm43xx_radio_read16(bcm, 0x003A)
+ & 0xFF20) | freq_r3A_value(freq));
+ bcm43xx_radio_write16(bcm, 0x003D,
+ bcm43xx_radio_read16(bcm, 0x003D) & 0x00FF);
+ bcm43xx_radio_write16(bcm, 0x0081,
+ (bcm43xx_radio_read16(bcm, 0x0081)
+ & 0xFF7F) | 0x0080);
+ bcm43xx_radio_write16(bcm, 0x0035,
+ bcm43xx_radio_read16(bcm, 0x0035) & 0xFFEF);
+ bcm43xx_radio_write16(bcm, 0x0035,
+ (bcm43xx_radio_read16(bcm, 0x0035)
+ & 0xFFEF) | 0x0010);
+ bcm43xx_radio_set_tx_iq(bcm);
+ TODO(); //TODO: TSSI2dbm workaround
+ bcm43xx_phy_xmitpower(bcm);//FIXME correct?
+ } else {
+ if ((channel < 1) || (channel > 14))
+ return -EINVAL;
+
+ if (synthetic_pu_workaround)
+ bcm43xx_synth_pu_workaround(bcm, channel);
+
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+ channel2freq_bg(channel));
+
+ if (channel == 14) {
+ if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) {
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET,
+ bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET)
+ & ~(1 << 7));
+ } else {
+ bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET,
+ bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+ BCM43xx_UCODEFLAGS_OFFSET)
+ | (1 << 7));
+ }
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+ bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+ | (1 << 11));
+ } else {
+ bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+ bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+ & 0xF7BF);
+ }
+ }
+
+ radio->channel = channel;
+ //XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states
+ // that 2000 usecs might suffice.
+ udelay(8000);
+
+ return 0;
+}
+
+void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val)
+{
+ u16 tmp;
+
+ val <<= 8;
+ tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0022) & 0xFCFF;
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0022, tmp | val);
+ tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x03A8) & 0xFCFF;
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x03A8, tmp | val);
+ tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0054) & 0xFCFF;
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0054, tmp | val);
+}
+
+/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
+static u16 bcm43xx_get_txgain_base_band(u16 txpower)
+{
+ u16 ret;
+
+ assert(txpower <= 63);
+
+ if (txpower >= 54)
+ ret = 2;
+ else if (txpower >= 49)
+ ret = 4;
+ else if (txpower >= 44)
+ ret = 5;
+ else
+ ret = 6;
+
+ return ret;
+}
+
+/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
+static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower)
+{
+ u16 ret;
+
+ assert(txpower <= 63);
+
+ if (txpower >= 32)
+ ret = 0;
+ else if (txpower >= 25)
+ ret = 1;
+ else if (txpower >= 20)
+ ret = 2;
+ else if (txpower >= 12)
+ ret = 3;
+ else
+ ret = 4;
+
+ return ret;
+}
+
+/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
+static u16 bcm43xx_get_txgain_dac(u16 txpower)
+{
+ u16 ret;
+
+ assert(txpower <= 63);
+
+ if (txpower >= 54)
+ ret = txpower - 53;
+ else if (txpower >= 49)
+ ret = txpower - 42;
+ else if (txpower >= 44)
+ ret = txpower - 37;
+ else if (txpower >= 32)
+ ret = txpower - 32;
+ else if (txpower >= 25)
+ ret = txpower - 20;
+ else if (txpower >= 20)
+ ret = txpower - 13;
+ else if (txpower >= 12)
+ ret = txpower - 8;
+ else
+ ret = txpower;
+
+ return ret;
+}
+
+void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 pamp, base, dac, ilt;
+
+ txpower = limit_value(txpower, 0, 63);
+
+ pamp = bcm43xx_get_txgain_freq_power_amp(txpower);
+ pamp <<= 5;
+ pamp &= 0x00E0;
+ bcm43xx_phy_write(bcm, 0x0019, pamp);
+
+ base = bcm43xx_get_txgain_base_band(txpower);
+ base &= 0x000F;
+ bcm43xx_phy_write(bcm, 0x0017, base | 0x0020);
+
+ ilt = bcm43xx_ilt_read(bcm, 0x3001);
+ ilt &= 0x0007;
+
+ dac = bcm43xx_get_txgain_dac(txpower);
+ dac <<= 3;
+ dac |= ilt;
+
+ bcm43xx_ilt_write(bcm, 0x3001, dac);
+
+ radio->txpwr_offset = txpower;
+
+ TODO();
+ //TODO: FuncPlaceholder (Adjust BB loft cancel)
+}
+
+void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
+ u16 baseband_attenuation, u16 radio_attenuation,
+ u16 txpower)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+ if (baseband_attenuation == 0xFFFF)
+ baseband_attenuation = radio->baseband_atten;
+ if (radio_attenuation == 0xFFFF)
+ radio_attenuation = radio->radio_atten;
+ if (txpower == 0xFFFF)
+ txpower = radio->txctl1;
+ radio->baseband_atten = baseband_attenuation;
+ radio->radio_atten = radio_attenuation;
+ radio->txctl1 = txpower;
+
+ assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11);
+ if (radio->revision < 6)
+ assert(/*radio_attenuation >= 0 &&*/ radio_attenuation <= 9);
+ else
+ assert(/* radio_attenuation >= 0 &&*/ radio_attenuation <= 31);
+ assert(/*txpower >= 0 &&*/ txpower <= 7);
+
+ bcm43xx_phy_set_baseband_attenuation(bcm, baseband_attenuation);
+ bcm43xx_radio_write16(bcm, 0x0043, radio_attenuation);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation);
+ if (radio->version == 0x2050) {
+ bcm43xx_radio_write16(bcm, 0x0052,
+ (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070)
+ | ((txpower << 4) & 0x0070));
+ }
+ //FIXME: The spec is very weird and unclear here.
+ if (phy->type == BCM43xx_PHYTYPE_G)
+ bcm43xx_phy_lo_adjust(bcm, 0);
+}
+
+u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+ if (radio->version == 0x2050 && radio->revision < 6)
+ return 0;
+ return 2;
+}
+
+u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ u16 att = 0xFFFF;
+
+ if (phy->type == BCM43xx_PHYTYPE_A)
+ return 0x60;
+
+ switch (radio->version) {
+ case 0x2053:
+ switch (radio->revision) {
+ case 1:
+ att = 6;
+ break;
+ }
+ break;
+ case 0x2050:
+ switch (radio->revision) {
+ case 0:
+ att = 5;
+ break;
+ case 1:
+ if (phy->type == BCM43xx_PHYTYPE_G) {
+ if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+ bcm->board_type == 0x421 &&
+ bcm->board_revision >= 30)
+ att = 3;
+ else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+ bcm->board_type == 0x416)
+ att = 3;
+ else
+ att = 1;
+ } else {
+ if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+ bcm->board_type == 0x421 &&
+ bcm->board_revision >= 30)
+ att = 7;
+ else
+ att = 6;
+ }
+ break;
+ case 2:
+ if (phy->type == BCM43xx_PHYTYPE_G) {
+ if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+ bcm->board_type == 0x421 &&
+ bcm->board_revision >= 30)
+ att = 3;
+ else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+ bcm->board_type == 0x416)
+ att = 5;
+ else if (bcm->chip_id == 0x4320)
+ att = 4;
+ else
+ att = 3;
+ } else
+ att = 6;
+ break;
+ case 3:
+ att = 5;
+ break;
+ case 4:
+ case 5:
+ att = 1;
+ break;
+ case 6:
+ case 7:
+ att = 5;
+ break;
+ case 8:
+ att = 0x1A;
+ break;
+ case 9:
+ default:
+ att = 5;
+ }
+ }
+ if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+ bcm->board_type == 0x421) {
+ if (bcm->board_revision < 0x43)
+ att = 2;
+ else if (bcm->board_revision < 0x51)
+ att = 3;
+ }
+ if (att == 0xFFFF)
+ att = 5;
+
+ return att;
+}
+
+u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+ if (radio->version != 0x2050)
+ return 0;
+ if (radio->revision == 1)
+ return 3;
+ if (radio->revision < 6)
+ return 2;
+ if (radio->revision == 8)
+ return 1;
+ return 0;
+}
+
+void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ int err;
+
+ if (radio->enabled)
+ return;
+
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
+ bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
+ bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) & 0xFFF7);
+ bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) & 0xFFF7);
+ bcm43xx_radio_init2060(bcm);
+ break;
+ case BCM43xx_PHYTYPE_B:
+ case BCM43xx_PHYTYPE_G:
+ bcm43xx_phy_write(bcm, 0x0015, 0x8000);
+ bcm43xx_phy_write(bcm, 0x0015, 0xCC00);
+ bcm43xx_phy_write(bcm, 0x0015, (phy->connected ? 0x00C0 : 0x0000));
+ err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 1);
+ assert(err == 0);
+ break;
+ default:
+ assert(0);
+ }
+ radio->enabled = 1;
+ dprintk(KERN_INFO PFX "Radio turned on\n");
+}
+
+void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+ if (phy->type == BCM43xx_PHYTYPE_A) {
+ bcm43xx_radio_write16(bcm, 0x0004, 0x00FF);
+ bcm43xx_radio_write16(bcm, 0x0005, 0x00FB);
+ bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008);
+ bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008);
+ }
+ if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) {
+ bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C);
+ bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73);
+ } else
+ bcm43xx_phy_write(bcm, 0x0015, 0xAA00);
+ radio->enabled = 0;
+ dprintk(KERN_INFO PFX "Radio turned off\n");
+}
+
+void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F);
+ break;
+ case BCM43xx_PHYTYPE_B:
+ case BCM43xx_PHYTYPE_G:
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F);
+ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F);
+ break;
+ }
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
new file mode 100644
index 00000000000..9ed18039fa3
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
@@ -0,0 +1,99 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ Some parts of the code in this file are derived from the ipw2200
+ driver Copyright(c) 2003 - 2004 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef BCM43xx_RADIO_H_
+#define BCM43xx_RADIO_H_
+
+#include "bcm43xx.h"
+
+
+#define BCM43xx_RADIO_DEFAULT_CHANNEL_A 36
+#define BCM43xx_RADIO_DEFAULT_CHANNEL_BG 6
+
+/* Force antenna 0. */
+#define BCM43xx_RADIO_TXANTENNA_0 0
+/* Force antenna 1. */
+#define BCM43xx_RADIO_TXANTENNA_1 1
+/* Use the RX antenna, that was selected for the most recently
+ * received good PLCP header.
+ */
+#define BCM43xx_RADIO_TXANTENNA_LASTPLCP 3
+#define BCM43xx_RADIO_TXANTENNA_DEFAULT BCM43xx_RADIO_TXANTENNA_LASTPLCP
+
+#define BCM43xx_RADIO_INTERFMODE_NONE 0
+#define BCM43xx_RADIO_INTERFMODE_NONWLAN 1
+#define BCM43xx_RADIO_INTERFMODE_MANUALWLAN 2
+#define BCM43xx_RADIO_INTERFMODE_AUTOWLAN 3
+
+
+void bcm43xx_radio_lock(struct bcm43xx_private *bcm);
+void bcm43xx_radio_unlock(struct bcm43xx_private *bcm);
+
+u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset);
+void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val);
+
+u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm);
+void bcm43xx_radio_init2060(struct bcm43xx_private *bcm);
+
+void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm);
+void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm);
+
+int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel,
+ int synthetic_pu_workaround);
+
+void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower);
+void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
+ u16 baseband_attenuation, u16 attenuation,
+ u16 txpower);
+
+u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm);
+u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm);
+u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm);
+
+void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val);
+
+void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm);
+
+u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel);
+u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm);
+
+int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode);
+
+void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm);
+void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm);
+s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset);
+void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val);
+void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val);
+void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm);
+
+void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm);
+u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm);
+
+#endif /* BCM43xx_RADIO_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
new file mode 100644
index 00000000000..b438f48e891
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
@@ -0,0 +1,341 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ SYSFS support routines
+
+ Copyright (c) 2006 Michael Buesch <mbuesch@freenet.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx_sysfs.h"
+#include "bcm43xx.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_radio.h"
+
+#include <linux/capability.h>
+
+
+#define GENERIC_FILESIZE 64
+
+
+static int get_integer(const char *buf, size_t count)
+{
+ char tmp[10 + 1] = { 0 };
+ int ret = -EINVAL;
+
+ if (count == 0)
+ goto out;
+ count = min(count, (size_t)10);
+ memcpy(tmp, buf, count);
+ ret = simple_strtol(tmp, NULL, 10);
+out:
+ return ret;
+}
+
+static int get_boolean(const char *buf, size_t count)
+{
+ if (count != 0) {
+ if (buf[0] == '1')
+ return 1;
+ if (buf[0] == '0')
+ return 0;
+ if (count >= 4 && memcmp(buf, "true", 4) == 0)
+ return 1;
+ if (count >= 5 && memcmp(buf, "false", 5) == 0)
+ return 0;
+ if (count >= 3 && memcmp(buf, "yes", 3) == 0)
+ return 1;
+ if (count >= 2 && memcmp(buf, "no", 2) == 0)
+ return 0;
+ if (count >= 2 && memcmp(buf, "on", 2) == 0)
+ return 1;
+ if (count >= 3 && memcmp(buf, "off", 3) == 0)
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
+{
+ int i, pos = 0;
+
+ for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+ pos += snprintf(buf + pos, buf_len - pos - 1,
+ "%04X", swab16(sprom[i]) & 0xFFFF);
+ }
+ pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
+
+ return pos + 1;
+}
+
+static int hex2sprom(u16 *sprom, const char *dump, size_t len)
+{
+ char tmp[5] = { 0 };
+ int cnt = 0;
+ unsigned long parsed;
+
+ if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
+ return -EINVAL;
+
+ while (cnt < BCM43xx_SPROM_SIZE) {
+ memcpy(tmp, dump, 4);
+ dump += 4;
+ parsed = simple_strtoul(tmp, NULL, 16);
+ sprom[cnt++] = swab16((u16)parsed);
+ }
+
+ return 0;
+}
+
+static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bcm43xx_private *bcm = dev_to_bcm(dev);
+ u16 *sprom;
+ unsigned long flags;
+ int err;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ assert(BCM43xx_SPROM_SIZE * sizeof(u16) <= PAGE_SIZE);
+ sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+ GFP_KERNEL);
+ if (!sprom)
+ return -ENOMEM;
+ bcm43xx_lock_mmio(bcm, flags);
+ assert(bcm->initialized);
+ err = bcm43xx_sprom_read(bcm, sprom);
+ if (!err)
+ err = sprom2hex(sprom, buf, PAGE_SIZE);
+ bcm43xx_unlock_mmio(bcm, flags);
+ kfree(sprom);
+
+ return err;
+}
+
+static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bcm43xx_private *bcm = dev_to_bcm(dev);
+ u16 *sprom;
+ unsigned long flags;
+ int err;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+ GFP_KERNEL);
+ if (!sprom)
+ return -ENOMEM;
+ err = hex2sprom(sprom, buf, count);
+ if (err)
+ goto out_kfree;
+ bcm43xx_lock_mmio(bcm, flags);
+ assert(bcm->initialized);
+ err = bcm43xx_sprom_write(bcm, sprom);
+ bcm43xx_unlock_mmio(bcm, flags);
+out_kfree:
+ kfree(sprom);
+
+ return err ? err : count;
+
+}
+
+static DEVICE_ATTR(sprom, 0600,
+ bcm43xx_attr_sprom_show,
+ bcm43xx_attr_sprom_store);
+
+static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bcm43xx_private *bcm = dev_to_bcm(dev);
+ unsigned long flags;
+ int err;
+ ssize_t count = 0;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ bcm43xx_lock(bcm, flags);
+ assert(bcm->initialized);
+
+ switch (bcm43xx_current_radio(bcm)->interfmode) {
+ case BCM43xx_RADIO_INTERFMODE_NONE:
+ count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n");
+ break;
+ case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+ count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference Mitigation)\n");
+ break;
+ case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+ count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference Mitigation)\n");
+ break;
+ default:
+ assert(0);
+ }
+ err = 0;
+
+ bcm43xx_unlock(bcm, flags);
+
+ return err ? err : count;
+
+}
+
+static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bcm43xx_private *bcm = dev_to_bcm(dev);
+ unsigned long flags;
+ int err;
+ int mode;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ mode = get_integer(buf, count);
+ switch (mode) {
+ case 0:
+ mode = BCM43xx_RADIO_INTERFMODE_NONE;
+ break;
+ case 1:
+ mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
+ break;
+ case 2:
+ mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
+ break;
+ case 3:
+ mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ bcm43xx_lock_mmio(bcm, flags);
+ assert(bcm->initialized);
+
+ err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
+ if (err) {
+ printk(KERN_ERR PFX "Interference Mitigation not "
+ "supported by device\n");
+ }
+
+ bcm43xx_unlock_mmio(bcm, flags);
+
+ return err ? err : count;
+}
+
+static DEVICE_ATTR(interference, 0644,
+ bcm43xx_attr_interfmode_show,
+ bcm43xx_attr_interfmode_store);
+
+static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bcm43xx_private *bcm = dev_to_bcm(dev);
+ unsigned long flags;
+ int err;
+ ssize_t count;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ bcm43xx_lock(bcm, flags);
+ assert(bcm->initialized);
+
+ if (bcm->short_preamble)
+ count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
+ else
+ count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
+
+ err = 0;
+ bcm43xx_unlock(bcm, flags);
+
+ return err ? err : count;
+}
+
+static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bcm43xx_private *bcm = dev_to_bcm(dev);
+ unsigned long flags;
+ int err;
+ int value;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ value = get_boolean(buf, count);
+ if (value < 0)
+ return value;
+ bcm43xx_lock(bcm, flags);
+ assert(bcm->initialized);
+
+ bcm->short_preamble = !!value;
+
+ err = 0;
+ bcm43xx_unlock(bcm, flags);
+
+ return err ? err : count;
+}
+
+static DEVICE_ATTR(shortpreamble, 0644,
+ bcm43xx_attr_preamble_show,
+ bcm43xx_attr_preamble_store);
+
+int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
+{
+ struct device *dev = &bcm->pci_dev->dev;
+ int err;
+
+ assert(bcm->initialized);
+
+ err = device_create_file(dev, &dev_attr_sprom);
+ if (err)
+ goto out;
+ err = device_create_file(dev, &dev_attr_interference);
+ if (err)
+ goto err_remove_sprom;
+ err = device_create_file(dev, &dev_attr_shortpreamble);
+ if (err)
+ goto err_remove_interfmode;
+
+out:
+ return err;
+err_remove_interfmode:
+ device_remove_file(dev, &dev_attr_interference);
+err_remove_sprom:
+ device_remove_file(dev, &dev_attr_sprom);
+ goto out;
+}
+
+void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
+{
+ struct device *dev = &bcm->pci_dev->dev;
+
+ device_remove_file(dev, &dev_attr_shortpreamble);
+ device_remove_file(dev, &dev_attr_interference);
+ device_remove_file(dev, &dev_attr_sprom);
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
new file mode 100644
index 00000000000..cc701df71e2
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
@@ -0,0 +1,9 @@
+#ifndef BCM43xx_SYSFS_H_
+#define BCM43xx_SYSFS_H_
+
+struct bcm43xx_private;
+
+int bcm43xx_sysfs_register(struct bcm43xx_private *bcm);
+void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm);
+
+#endif /* BCM43xx_SYSFS_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
new file mode 100644
index 00000000000..b45063974ae
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -0,0 +1,1005 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ Some parts of the code in this file are derived from the ipw2200
+ driver Copyright(c) 2003 - 2004 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <net/ieee80211softmac.h>
+#include <net/ieee80211softmac_wx.h>
+#include <linux/capability.h>
+#include <linux/sched.h> /* for capable() */
+#include <linux/delay.h>
+
+#include "bcm43xx.h"
+#include "bcm43xx_wx.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_radio.h"
+#include "bcm43xx_phy.h"
+
+
+/* The WIRELESS_EXT version, which is implemented by this driver. */
+#define BCM43xx_WX_VERSION 18
+
+#define MAX_WX_STRING 80
+
+
+static int bcm43xx_wx_get_name(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ int i;
+ struct bcm43xx_phyinfo *phy;
+ char suffix[7] = { 0 };
+ int have_a = 0, have_b = 0, have_g = 0;
+
+ bcm43xx_lock(bcm, flags);
+ for (i = 0; i < bcm->nr_80211_available; i++) {
+ phy = &(bcm->core_80211_ext[i].phy);
+ switch (phy->type) {
+ case BCM43xx_PHYTYPE_A:
+ have_a = 1;
+ break;
+ case BCM43xx_PHYTYPE_G:
+ have_g = 1;
+ case BCM43xx_PHYTYPE_B:
+ have_b = 1;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ bcm43xx_unlock(bcm, flags);
+
+ i = 0;
+ if (have_a) {
+ suffix[i++] = 'a';
+ suffix[i++] = '/';
+ }
+ if (have_b) {
+ suffix[i++] = 'b';
+ suffix[i++] = '/';
+ }
+ if (have_g) {
+ suffix[i++] = 'g';
+ suffix[i++] = '/';
+ }
+ if (i != 0)
+ suffix[i - 1] = '\0';
+
+ snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix);
+
+ return 0;
+}
+
+static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ u8 channel;
+ int freq;
+ int err = -EINVAL;
+
+ bcm43xx_lock_mmio(bcm, flags);
+ if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
+ channel = data->freq.m;
+ freq = bcm43xx_channel_to_freq(bcm, channel);
+ } else {
+ channel = bcm43xx_freq_to_channel(bcm, data->freq.m);
+ freq = data->freq.m;
+ }
+ if (!bcm43xx_is_valid_channel(bcm, channel))
+ goto out_unlock;
+ if (bcm->initialized) {
+ //ieee80211softmac_disassoc(softmac, $REASON);
+ bcm43xx_mac_suspend(bcm);
+ err = bcm43xx_radio_selectchannel(bcm, channel, 0);
+ bcm43xx_mac_enable(bcm);
+ } else {
+ bcm43xx_current_radio(bcm)->initial_channel = channel;
+ err = 0;
+ }
+out_unlock:
+ bcm43xx_unlock_mmio(bcm, flags);
+
+ return err;
+}
+
+static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ struct bcm43xx_radioinfo *radio;
+ unsigned long flags;
+ int err = -ENODEV;
+ u16 channel;
+
+ bcm43xx_lock(bcm, flags);
+ radio = bcm43xx_current_radio(bcm);
+ channel = radio->channel;
+ if (channel == 0xFF) {
+ assert(!bcm->initialized);
+ channel = radio->initial_channel;
+ if (channel == 0xFF)
+ goto out_unlock;
+ }
+ assert(channel > 0 && channel <= 1000);
+ data->freq.e = 1;
+ data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000;
+ data->freq.flags = 1;
+
+ err = 0;
+out_unlock:
+ bcm43xx_unlock(bcm, flags);
+
+ return err;
+}
+
+static int bcm43xx_wx_set_mode(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ int mode;
+
+ mode = data->mode;
+ if (mode == IW_MODE_AUTO)
+ mode = BCM43xx_INITIAL_IWMODE;
+
+ bcm43xx_lock_mmio(bcm, flags);
+ if (bcm->initialized) {
+ if (bcm->ieee->iw_mode != mode)
+ bcm43xx_set_iwmode(bcm, mode);
+ } else
+ bcm->ieee->iw_mode = mode;
+ bcm43xx_unlock_mmio(bcm, flags);
+
+ return 0;
+}
+
+static int bcm43xx_wx_get_mode(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+
+ bcm43xx_lock(bcm, flags);
+ data->mode = bcm->ieee->iw_mode;
+ bcm43xx_unlock(bcm, flags);
+
+ return 0;
+}
+
+static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ struct iw_range *range = (struct iw_range *)extra;
+ const struct ieee80211_geo *geo;
+ unsigned long flags;
+ int i, j;
+ struct bcm43xx_phyinfo *phy;
+
+ data->data.length = sizeof(*range);
+ memset(range, 0, sizeof(*range));
+
+ //TODO: What about 802.11b?
+ /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
+ range->throughput = 27 * 1000 * 1000;
+
+ range->max_qual.qual = 100;
+ /* TODO: Real max RSSI */
+ range->max_qual.level = 3;
+ range->max_qual.noise = 100;
+ range->max_qual.updated = 7;
+
+ range->avg_qual.qual = 70;
+ range->avg_qual.level = 2;
+ range->avg_qual.noise = 40;
+ range->avg_qual.updated = 7;
+
+ range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
+ range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
+ range->min_frag = MIN_FRAG_THRESHOLD;
+ range->max_frag = MAX_FRAG_THRESHOLD;
+
+ range->encoding_size[0] = 5;
+ range->encoding_size[1] = 13;
+ range->num_encoding_sizes = 2;
+ range->max_encoding_tokens = WEP_KEYS;
+
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = BCM43xx_WX_VERSION;
+
+ range->enc_capa = IW_ENC_CAPA_WPA |
+ IW_ENC_CAPA_WPA2 |
+ IW_ENC_CAPA_CIPHER_TKIP |
+ IW_ENC_CAPA_CIPHER_CCMP;
+
+ bcm43xx_lock(bcm, flags);
+ phy = bcm43xx_current_phy(bcm);
+
+ range->num_bitrates = 0;
+ i = 0;
+ if (phy->type == BCM43xx_PHYTYPE_A ||
+ phy->type == BCM43xx_PHYTYPE_G) {
+ range->num_bitrates = 8;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
+ }
+ if (phy->type == BCM43xx_PHYTYPE_B ||
+ phy->type == BCM43xx_PHYTYPE_G) {
+ range->num_bitrates += 4;
+ range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
+ range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
+ range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
+ range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
+ }
+
+ geo = ieee80211_get_geo(bcm->ieee);
+ range->num_channels = geo->a_channels + geo->bg_channels;
+ j = 0;
+ for (i = 0; i < geo->a_channels; i++) {
+ if (j == IW_MAX_FREQUENCIES)
+ break;
+ range->freq[j].i = j + 1;
+ range->freq[j].m = geo->a[i].freq;//FIXME?
+ range->freq[j].e = 1;
+ j++;
+ }
+ for (i = 0; i < geo->bg_channels; i++) {
+ if (j == IW_MAX_FREQUENCIES)
+ break;
+ range->freq[j].i = j + 1;
+ range->freq[j].m = geo->bg[i].freq;//FIXME?
+ range->freq[j].e = 1;
+ j++;
+ }
+ range->num_frequency = j;
+
+ bcm43xx_unlock(bcm, flags);
+
+ return 0;
+}
+
+static int bcm43xx_wx_set_nick(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ size_t len;
+
+ bcm43xx_lock(bcm, flags);
+ len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
+ memcpy(bcm->nick, extra, len);
+ bcm->nick[len] = '\0';
+ bcm43xx_unlock(bcm, flags);
+
+ return 0;
+}
+
+static int bcm43xx_wx_get_nick(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ size_t len;
+
+ bcm43xx_lock(bcm, flags);
+ len = strlen(bcm->nick) + 1;
+ memcpy(extra, bcm->nick, len);
+ data->data.length = (__u16)len;
+ data->data.flags = 1;
+ bcm43xx_unlock(bcm, flags);
+
+ return 0;
+}
+
+static int bcm43xx_wx_set_rts(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ int err = -EINVAL;
+
+ bcm43xx_lock(bcm, flags);
+ if (data->rts.disabled) {
+ bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
+ err = 0;
+ } else {
+ if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD &&
+ data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) {
+ bcm->rts_threshold = data->rts.value;
+ err = 0;
+ }
+ }
+ bcm43xx_unlock(bcm, flags);
+
+ return err;
+}
+
+static int bcm43xx_wx_get_rts(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+
+ bcm43xx_lock(bcm, flags);
+ data->rts.value = bcm->rts_threshold;
+ data->rts.fixed = 0;
+ data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
+ bcm43xx_unlock(bcm, flags);
+
+ return 0;
+}
+
+static int bcm43xx_wx_set_frag(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ int err = -EINVAL;
+
+ bcm43xx_lock(bcm, flags);
+ if (data->frag.disabled) {
+ bcm->ieee->fts = MAX_FRAG_THRESHOLD;
+ err = 0;
+ } else {
+ if (data->frag.value >= MIN_FRAG_THRESHOLD &&
+ data->frag.value <= MAX_FRAG_THRESHOLD) {
+ bcm->ieee->fts = data->frag.value & ~0x1;
+ err = 0;
+ }
+ }
+ bcm43xx_unlock(bcm, flags);
+
+ return err;
+}
+
+static int bcm43xx_wx_get_frag(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+
+ bcm43xx_lock(bcm, flags);
+ data->frag.value = bcm->ieee->fts;
+ data->frag.fixed = 0;
+ data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
+ bcm43xx_unlock(bcm, flags);
+
+ return 0;
+}
+
+static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ struct bcm43xx_radioinfo *radio;
+ struct bcm43xx_phyinfo *phy;
+ unsigned long flags;
+ int err = -ENODEV;
+ u16 maxpower;
+
+ if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
+ printk(PFX KERN_ERR "TX power not in dBm.\n");
+ return -EOPNOTSUPP;
+ }
+
+ bcm43xx_lock_mmio(bcm, flags);
+ if (!bcm->initialized)
+ goto out_unlock;
+ radio = bcm43xx_current_radio(bcm);
+ phy = bcm43xx_current_phy(bcm);
+ if (data->txpower.disabled != (!(radio->enabled))) {
+ if (data->txpower.disabled)
+ bcm43xx_radio_turn_off(bcm);
+ else
+ bcm43xx_radio_turn_on(bcm);
+ }
+ if (data->txpower.value > 0) {
+ /* desired and maxpower dBm values are in Q5.2 */
+ if (phy->type == BCM43xx_PHYTYPE_A)
+ maxpower = bcm->sprom.maxpower_aphy;
+ else
+ maxpower = bcm->sprom.maxpower_bgphy;
+ radio->txpower_desired = limit_value(data->txpower.value << 2,
+ 0, maxpower);
+ bcm43xx_phy_xmitpower(bcm);
+ }
+ err = 0;
+
+out_unlock:
+ bcm43xx_unlock_mmio(bcm, flags);
+
+ return err;
+}
+
+static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ struct bcm43xx_radioinfo *radio;
+ unsigned long flags;
+ int err = -ENODEV;
+
+ bcm43xx_lock(bcm, flags);
+ if (!bcm->initialized)
+ goto out_unlock;
+ radio = bcm43xx_current_radio(bcm);
+ /* desired dBm value is in Q5.2 */
+ data->txpower.value = radio->txpower_desired >> 2;
+ data->txpower.fixed = 1;
+ data->txpower.flags = IW_TXPOW_DBM;
+ data->txpower.disabled = !(radio->enabled);
+
+ err = 0;
+out_unlock:
+ bcm43xx_unlock(bcm, flags);
+
+ return err;
+}
+
+static int bcm43xx_wx_set_encoding(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ int err;
+
+ err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra);
+
+ return err;
+}
+
+static int bcm43xx_wx_set_encodingext(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ int err;
+
+ err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra);
+
+ return err;
+}
+
+static int bcm43xx_wx_get_encoding(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ int err;
+
+ err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra);
+
+ return err;
+}
+
+static int bcm43xx_wx_get_encodingext(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ int err;
+
+ err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra);
+
+ return err;
+}
+
+static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ int mode, err = 0;
+
+ mode = *((int *)extra);
+ switch (mode) {
+ case 0:
+ mode = BCM43xx_RADIO_INTERFMODE_NONE;
+ break;
+ case 1:
+ mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
+ break;
+ case 2:
+ mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
+ break;
+ case 3:
+ mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
+ break;
+ default:
+ printk(KERN_ERR PFX "set_interfmode allowed parameters are: "
+ "0 => None, 1 => Non-WLAN, 2 => WLAN, "
+ "3 => Auto-WLAN\n");
+ return -EINVAL;
+ }
+
+ bcm43xx_lock_mmio(bcm, flags);
+ if (bcm->initialized) {
+ err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
+ if (err) {
+ printk(KERN_ERR PFX "Interference Mitigation not "
+ "supported by device\n");
+ }
+ } else {
+ if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) {
+ printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN "
+ "not supported while the interface is down.\n");
+ err = -ENODEV;
+ } else
+ bcm43xx_current_radio(bcm)->interfmode = mode;
+ }
+ bcm43xx_unlock_mmio(bcm, flags);
+
+ return err;
+}
+
+static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ int mode;
+
+ bcm43xx_lock(bcm, flags);
+ mode = bcm43xx_current_radio(bcm)->interfmode;
+ bcm43xx_unlock(bcm, flags);
+
+ switch (mode) {
+ case BCM43xx_RADIO_INTERFMODE_NONE:
+ strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING);
+ break;
+ case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+ strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING);
+ break;
+ case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+ strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING);
+ break;
+ default:
+ assert(0);
+ }
+ data->data.length = strlen(extra) + 1;
+
+ return 0;
+}
+
+static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ int on;
+
+ on = *((int *)extra);
+ bcm43xx_lock(bcm, flags);
+ bcm->short_preamble = !!on;
+ bcm43xx_unlock(bcm, flags);
+
+ return 0;
+}
+
+static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ int on;
+
+ bcm43xx_lock(bcm, flags);
+ on = bcm->short_preamble;
+ bcm43xx_unlock(bcm, flags);
+
+ if (on)
+ strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
+ else
+ strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING);
+ data->data.length = strlen(extra) + 1;
+
+ return 0;
+}
+
+static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ int on;
+
+ on = *((int *)extra);
+
+ bcm43xx_lock(bcm, flags);
+ bcm->ieee->host_encrypt = !!on;
+ bcm->ieee->host_decrypt = !!on;
+ bcm->ieee->host_build_iv = !on;
+ bcm43xx_unlock(bcm, flags);
+
+ return 0;
+}
+
+static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ unsigned long flags;
+ int on;
+
+ bcm43xx_lock(bcm, flags);
+ on = bcm->ieee->host_encrypt;
+ bcm43xx_unlock(bcm, flags);
+
+ if (on)
+ strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
+ else
+ strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING);
+ data->data.length = strlen(extra + 1);
+
+ return 0;
+}
+
+/* Enough buffer to hold a hexdump of the sprom data. */
+#define SPROM_BUFFERSIZE 512
+
+static int sprom2hex(const u16 *sprom, char *dump)
+{
+ int i, pos = 0;
+
+ for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+ pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1,
+ "%04X", swab16(sprom[i]) & 0xFFFF);
+ }
+
+ return pos + 1;
+}
+
+static int hex2sprom(u16 *sprom, const char *dump, unsigned int len)
+{
+ char tmp[5] = { 0 };
+ int cnt = 0;
+ unsigned long parsed;
+
+ if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
+ return -EINVAL;
+ while (cnt < BCM43xx_SPROM_SIZE) {
+ memcpy(tmp, dump, 4);
+ dump += 4;
+ parsed = simple_strtoul(tmp, NULL, 16);
+ sprom[cnt++] = swab16((u16)parsed);
+ }
+
+ return 0;
+}
+
+static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ int err = -EPERM;
+ u16 *sprom;
+ unsigned long flags;
+
+ if (!capable(CAP_SYS_RAWIO))
+ goto out;
+
+ err = -ENOMEM;
+ sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+ GFP_KERNEL);
+ if (!sprom)
+ goto out;
+
+ bcm43xx_lock_mmio(bcm, flags);
+ err = -ENODEV;
+ if (bcm->initialized)
+ err = bcm43xx_sprom_read(bcm, sprom);
+ bcm43xx_unlock_mmio(bcm, flags);
+ if (!err)
+ data->data.length = sprom2hex(sprom, extra);
+ kfree(sprom);
+out:
+ return err;
+}
+
+static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
+ struct iw_request_info *info,
+ union iwreq_data *data,
+ char *extra)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ int err = -EPERM;
+ u16 *sprom;
+ unsigned long flags;
+ char *input;
+ unsigned int len;
+
+ if (!capable(CAP_SYS_RAWIO))
+ goto out;
+
+ err = -ENOMEM;
+ sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+ GFP_KERNEL);
+ if (!sprom)
+ goto out;
+
+ len = data->data.length;
+ extra[len - 1] = '\0';
+ input = strchr(extra, ':');
+ if (input) {
+ input++;
+ len -= input - extra;
+ } else
+ input = extra;
+ err = hex2sprom(sprom, input, len);
+ if (err)
+ goto out_kfree;
+
+ bcm43xx_lock_mmio(bcm, flags);
+ err = -ENODEV;
+ if (bcm->initialized)
+ err = bcm43xx_sprom_write(bcm, sprom);
+ bcm43xx_unlock_mmio(bcm, flags);
+out_kfree:
+ kfree(sprom);
+out:
+ return err;
+}
+
+/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
+
+static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev)
+{
+ struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
+ struct iw_statistics *wstats;
+
+ wstats = &bcm->stats.wstats;
+ if (!mac->associated) {
+ wstats->miss.beacon = 0;
+// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
+ wstats->discard.retries = 0;
+// bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question
+ wstats->discard.nwid = 0;
+// bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto
+ wstats->discard.code = 0;
+// bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here
+ wstats->discard.fragment = 0;
+ wstats->discard.misc = 0;
+ wstats->qual.qual = 0;
+ wstats->qual.level = 0;
+ wstats->qual.noise = 0;
+ wstats->qual.updated = 7;
+ wstats->qual.updated |= IW_QUAL_NOISE_INVALID |
+ IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
+ return wstats;
+ }
+ /* fill in the real statistics when iface associated */
+ wstats->qual.qual = 100; // TODO: get the real signal quality
+ wstats->qual.level = 3 - bcm->stats.link_quality;
+ wstats->qual.noise = bcm->stats.noise;
+ wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
+ IW_QUAL_NOISE_UPDATED;
+ wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
+ wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
+ wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
+ wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments;
+ wstats->discard.misc = 0; // FIXME
+ wstats->miss.beacon = 0; // FIXME
+ return wstats;
+}
+
+
+#ifdef WX
+# undef WX
+#endif
+#define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
+static const iw_handler bcm43xx_wx_handlers[] = {
+ /* Wireless Identification */
+ WX(SIOCGIWNAME) = bcm43xx_wx_get_name,
+ /* Basic operations */
+ WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq,
+ WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq,
+ WX(SIOCSIWMODE) = bcm43xx_wx_set_mode,
+ WX(SIOCGIWMODE) = bcm43xx_wx_get_mode,
+ /* Informative stuff */
+ WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams,
+ /* Access Point manipulation */
+ WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
+ WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
+ WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
+ WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
+ /* 802.11 specific support */
+ WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
+ WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
+ WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick,
+ WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick,
+ /* Other parameters */
+ WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
+ WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
+ WX(SIOCSIWRTS) = bcm43xx_wx_set_rts,
+ WX(SIOCGIWRTS) = bcm43xx_wx_get_rts,
+ WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag,
+ WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag,
+ WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower,
+ WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower,
+//TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry,
+//TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry,
+ /* Encoding */
+ WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding,
+ WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding,
+ WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext,
+ WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext,
+ /* Power saving */
+//TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power,
+//TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power,
+ WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
+ WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
+ WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
+ WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
+};
+#undef WX
+
+static const iw_handler bcm43xx_priv_wx_handlers[] = {
+ /* Set Interference Mitigation Mode. */
+ bcm43xx_wx_set_interfmode,
+ /* Get Interference Mitigation Mode. */
+ bcm43xx_wx_get_interfmode,
+ /* Enable/Disable Short Preamble mode. */
+ bcm43xx_wx_set_shortpreamble,
+ /* Get Short Preamble mode. */
+ bcm43xx_wx_get_shortpreamble,
+ /* Enable/Disable Software Encryption mode */
+ bcm43xx_wx_set_swencryption,
+ /* Get Software Encryption mode */
+ bcm43xx_wx_get_swencryption,
+ /* Write SRPROM data. */
+ bcm43xx_wx_sprom_write,
+ /* Read SPROM data. */
+ bcm43xx_wx_sprom_read,
+};
+
+#define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0)
+#define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1)
+#define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2)
+#define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3)
+#define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4)
+#define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5)
+#define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6)
+#define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7)
+
+#define PRIV_WX_DUMMY(ioctl) \
+ { \
+ .cmd = (ioctl), \
+ .name = "__unused" \
+ }
+
+static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
+ {
+ .cmd = PRIV_WX_SET_INTERFMODE,
+ .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ .name = "set_interfmode",
+ },
+ {
+ .cmd = PRIV_WX_GET_INTERFMODE,
+ .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+ .name = "get_interfmode",
+ },
+ {
+ .cmd = PRIV_WX_SET_SHORTPREAMBLE,
+ .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ .name = "set_shortpreamb",
+ },
+ {
+ .cmd = PRIV_WX_GET_SHORTPREAMBLE,
+ .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+ .name = "get_shortpreamb",
+ },
+ {
+ .cmd = PRIV_WX_SET_SWENCRYPTION,
+ .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ .name = "set_swencrypt",
+ },
+ {
+ .cmd = PRIV_WX_GET_SWENCRYPTION,
+ .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+ .name = "get_swencrypt",
+ },
+ {
+ .cmd = PRIV_WX_SPROM_WRITE,
+ .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE,
+ .name = "write_sprom",
+ },
+ {
+ .cmd = PRIV_WX_SPROM_READ,
+ .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE,
+ .name = "read_sprom",
+ },
+};
+
+const struct iw_handler_def bcm43xx_wx_handlers_def = {
+ .standard = bcm43xx_wx_handlers,
+ .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers),
+ .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers),
+ .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args),
+ .private = bcm43xx_priv_wx_handlers,
+ .private_args = bcm43xx_priv_wx_args,
+ .get_wireless_stats = bcm43xx_get_wireless_stats,
+};
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
new file mode 100644
index 00000000000..1f29ff3aa4c
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
@@ -0,0 +1,36 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ Some parts of the code in this file are derived from the ipw2200
+ driver Copyright(c) 2003 - 2004 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef BCM43xx_WX_H_
+#define BCM43xx_WX_H_
+
+extern const struct iw_handler_def bcm43xx_wx_handlers_def;
+
+#endif /* BCM43xx_WX_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
new file mode 100644
index 00000000000..d8ece28c079
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
@@ -0,0 +1,582 @@
+/*
+
+ Broadcom BCM43xx wireless driver
+
+ Transmission (TX/RX) related functions.
+
+ Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+ Stefano Brivio <st3@riseup.net>
+ Michael Buesch <mbuesch@freenet.de>
+ Danny van Dyk <kugelfang@gentoo.org>
+ Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx_xmit.h"
+
+#include <linux/etherdevice.h>
+
+
+/* Extract the bitrate out of a CCK PLCP header. */
+static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp)
+{
+ switch (plcp->raw[0]) {
+ case 0x0A:
+ return IEEE80211_CCK_RATE_1MB;
+ case 0x14:
+ return IEEE80211_CCK_RATE_2MB;
+ case 0x37:
+ return IEEE80211_CCK_RATE_5MB;
+ case 0x6E:
+ return IEEE80211_CCK_RATE_11MB;
+ }
+ assert(0);
+ return 0;
+}
+
+/* Extract the bitrate out of an OFDM PLCP header. */
+static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp)
+{
+ switch (plcp->raw[0] & 0xF) {
+ case 0xB:
+ return IEEE80211_OFDM_RATE_6MB;
+ case 0xF:
+ return IEEE80211_OFDM_RATE_9MB;
+ case 0xA:
+ return IEEE80211_OFDM_RATE_12MB;
+ case 0xE:
+ return IEEE80211_OFDM_RATE_18MB;
+ case 0x9:
+ return IEEE80211_OFDM_RATE_24MB;
+ case 0xD:
+ return IEEE80211_OFDM_RATE_36MB;
+ case 0x8:
+ return IEEE80211_OFDM_RATE_48MB;
+ case 0xC:
+ return IEEE80211_OFDM_RATE_54MB;
+ }
+ assert(0);
+ return 0;
+}
+
+u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
+{
+ switch (bitrate) {
+ case IEEE80211_CCK_RATE_1MB:
+ return 0x0A;
+ case IEEE80211_CCK_RATE_2MB:
+ return 0x14;
+ case IEEE80211_CCK_RATE_5MB:
+ return 0x37;
+ case IEEE80211_CCK_RATE_11MB:
+ return 0x6E;
+ }
+ assert(0);
+ return 0;
+}
+
+u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
+{
+ switch (bitrate) {
+ case IEEE80211_OFDM_RATE_6MB:
+ return 0xB;
+ case IEEE80211_OFDM_RATE_9MB:
+ return 0xF;
+ case IEEE80211_OFDM_RATE_12MB:
+ return 0xA;
+ case IEEE80211_OFDM_RATE_18MB:
+ return 0xE;
+ case IEEE80211_OFDM_RATE_24MB:
+ return 0x9;
+ case IEEE80211_OFDM_RATE_36MB:
+ return 0xD;
+ case IEEE80211_OFDM_RATE_48MB:
+ return 0x8;
+ case IEEE80211_OFDM_RATE_54MB:
+ return 0xC;
+ }
+ assert(0);
+ return 0;
+}
+
+static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
+ const u16 octets, const u8 bitrate,
+ const int ofdm_modulation)
+{
+ __le32 *data = &(plcp->data);
+ __u8 *raw = plcp->raw;
+
+ if (ofdm_modulation) {
+ *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
+ assert(!(octets & 0xF000));
+ *data |= (octets << 5);
+ *data = cpu_to_le32(*data);
+ } else {
+ u32 plen;
+
+ plen = octets * 16 / bitrate;
+ if ((octets * 16 % bitrate) > 0) {
+ plen++;
+ if ((bitrate == IEEE80211_CCK_RATE_11MB)
+ && ((octets * 8 % 11) < 4)) {
+ raw[1] = 0x84;
+ } else
+ raw[1] = 0x04;
+ } else
+ raw[1] = 0x04;
+ *data |= cpu_to_le32(plen << 16);
+ raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
+ }
+}
+
+static u8 bcm43xx_calc_fallback_rate(u8 bitrate)
+{
+ switch (bitrate) {
+ case IEEE80211_CCK_RATE_1MB:
+ return IEEE80211_CCK_RATE_1MB;
+ case IEEE80211_CCK_RATE_2MB:
+ return IEEE80211_CCK_RATE_1MB;
+ case IEEE80211_CCK_RATE_5MB:
+ return IEEE80211_CCK_RATE_2MB;
+ case IEEE80211_CCK_RATE_11MB:
+ return IEEE80211_CCK_RATE_5MB;
+ case IEEE80211_OFDM_RATE_6MB:
+ return IEEE80211_CCK_RATE_5MB;
+ case IEEE80211_OFDM_RATE_9MB:
+ return IEEE80211_OFDM_RATE_6MB;
+ case IEEE80211_OFDM_RATE_12MB:
+ return IEEE80211_OFDM_RATE_9MB;
+ case IEEE80211_OFDM_RATE_18MB:
+ return IEEE80211_OFDM_RATE_12MB;
+ case IEEE80211_OFDM_RATE_24MB:
+ return IEEE80211_OFDM_RATE_18MB;
+ case IEEE80211_OFDM_RATE_36MB:
+ return IEEE80211_OFDM_RATE_24MB;
+ case IEEE80211_OFDM_RATE_48MB:
+ return IEEE80211_OFDM_RATE_36MB;
+ case IEEE80211_OFDM_RATE_54MB:
+ return IEEE80211_OFDM_RATE_48MB;
+ }
+ assert(0);
+ return 0;
+}
+
+static
+__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header,
+ u8 bitrate)
+{
+ const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl);
+ __le16 duration_id = wireless_header->duration_id;
+
+ switch (WLAN_FC_GET_TYPE(frame_ctl)) {
+ case IEEE80211_FTYPE_DATA:
+ case IEEE80211_FTYPE_MGMT:
+ //TODO: Steal the code from ieee80211, once it is completed there.
+ break;
+ case IEEE80211_FTYPE_CTL:
+ /* Use the original duration/id. */
+ break;
+ default:
+ assert(0);
+ }
+
+ return duration_id;
+}
+
+static inline
+u16 ceiling_div(u16 dividend, u16 divisor)
+{
+ return ((dividend + divisor - 1) / divisor);
+}
+
+static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy,
+ struct bcm43xx_txhdr *txhdr,
+ u16 *flags,
+ u8 bitrate,
+ const struct ieee80211_hdr_4addr *wlhdr)
+{
+ u16 fctl;
+ u16 dur;
+ u8 fallback_bitrate;
+ int ofdm_modulation;
+ int fallback_ofdm_modulation;
+// u8 *sa, *da;
+ u16 flen;
+
+//FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr);
+//FIXME da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr);
+ fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
+ ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
+ fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
+
+ flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN,
+ bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp),
+ flen, bitrate,
+ !ieee80211_is_cck_rate(bitrate));
+ bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp),
+ flen, fallback_bitrate,
+ !ieee80211_is_cck_rate(fallback_bitrate));
+ fctl = IEEE80211_FTYPE_CTL;
+ fctl |= IEEE80211_STYPE_RTS;
+ dur = le16_to_cpu(wlhdr->duration_id);
+/*FIXME: should we test for dur==0 here and let it unmodified in this case?
+ * The following assert checks for this case...
+ */
+assert(dur);
+/*FIXME: The duration calculation is not really correct.
+ * I am not 100% sure which bitrate to use. We use the RTS rate here,
+ * but this is likely to be wrong.
+ */
+ if (phy->type == BCM43xx_PHYTYPE_A) {
+ /* Three times SIFS */
+ dur += 16 * 3;
+ /* Add ACK duration. */
+ dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
+ bitrate * 4);
+ /* Add CTS duration. */
+ dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
+ bitrate * 4);
+ } else {
+ /* Three times SIFS */
+ dur += 10 * 3;
+ /* Add ACK duration. */
+ dur += ceiling_div(8 * (14 /*bytes*/) * 10,
+ bitrate);
+ /* Add CTS duration. */
+ dur += ceiling_div(8 * (14 /*bytes*/) * 10,
+ bitrate);
+ }
+
+ txhdr->rts_cts_frame_control = cpu_to_le16(fctl);
+ txhdr->rts_cts_dur = cpu_to_le16(dur);
+//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3));
+//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da));
+ memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME!
+// memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN);
+
+ *flags |= BCM43xx_TXHDRFLAG_RTSCTS;
+ *flags |= BCM43xx_TXHDRFLAG_RTS;
+ if (ofdm_modulation)
+ *flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM;
+ if (fallback_ofdm_modulation)
+ *flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM;
+}
+
+void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
+ struct bcm43xx_txhdr *txhdr,
+ const unsigned char *fragment_data,
+ const unsigned int fragment_len,
+ const int is_first_fragment,
+ const u16 cookie)
+{
+ const struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data;
+ const struct ieee80211_security *secinfo = &bcm->ieee->sec;
+ u8 bitrate;
+ u8 fallback_bitrate;
+ int ofdm_modulation;
+ int fallback_ofdm_modulation;
+ u16 plcp_fragment_len = fragment_len;
+ u16 flags = 0;
+ u16 control = 0;
+ u16 wsec_rate = 0;
+ u16 encrypt_frame;
+
+ /* Now construct the TX header. */
+ memset(txhdr, 0, sizeof(*txhdr));
+
+ bitrate = bcm->softmac->txrates.default_rate;
+ ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
+ fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
+ fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
+
+ /* Set Frame Control from 80211 header. */
+ txhdr->frame_control = wireless_header->frame_ctl;
+ /* Copy address1 from 80211 header. */
+ memcpy(txhdr->mac1, wireless_header->addr1, 6);
+ /* Set the fallback duration ID. */
+ txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header,
+ fallback_bitrate);
+ /* Set the cookie (used as driver internal ID for the frame) */
+ txhdr->cookie = cpu_to_le16(cookie);
+
+ /* Hardware appends FCS. */
+ plcp_fragment_len += IEEE80211_FCS_LEN;
+
+ /* Hardware encryption. */
+ encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
+ if (encrypt_frame && !bcm->ieee->host_encrypt) {
+ const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
+ memcpy(txhdr->wep_iv, hdr->payload, 4);
+ /* Hardware appends ICV. */
+ plcp_fragment_len += 4;
+
+ wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
+ & BCM43xx_TXHDR_WSEC_ALGO_MASK;
+ wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
+ & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
+ }
+
+ /* Generate the PLCP header and the fallback PLCP header. */
+ bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
+ plcp_fragment_len,
+ bitrate, ofdm_modulation);
+ bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len,
+ fallback_bitrate, fallback_ofdm_modulation);
+
+ /* Set the CONTROL field */
+ if (ofdm_modulation)
+ control |= BCM43xx_TXHDRCTL_OFDM;
+ if (bcm->short_preamble) //FIXME: could be the other way around, please test
+ control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
+ control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
+ & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
+
+ /* Set the FLAGS field */
+ if (!is_multicast_ether_addr(wireless_header->addr1) &&
+ !is_broadcast_ether_addr(wireless_header->addr1))
+ flags |= BCM43xx_TXHDRFLAG_EXPECTACK;
+ if (1 /* FIXME: PS poll?? */)
+ flags |= 0x10; // FIXME: unknown meaning.
+ if (fallback_ofdm_modulation)
+ flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
+ if (is_first_fragment)
+ flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
+
+ /* Set WSEC/RATE field */
+ wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT)
+ & BCM43xx_TXHDR_RATE_MASK;
+
+ /* Generate the RTS/CTS packet, if required. */
+ /* FIXME: We should first try with CTS-to-self,
+ * if we are on 80211g. If we get too many
+ * failures (hidden nodes), we should switch back to RTS/CTS.
+ */
+ if (0/*FIXME txctl->use_rts_cts*/) {
+ bcm43xx_generate_rts(phy, txhdr, &flags,
+ 0/*FIXME txctl->rts_cts_rate*/,
+ wireless_header);
+ }
+
+ txhdr->flags = cpu_to_le16(flags);
+ txhdr->control = cpu_to_le16(control);
+ txhdr->wsec_rate = cpu_to_le16(wsec_rate);
+}
+
+static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
+ u8 in_rssi, int ofdm,
+ int adjust_2053, int adjust_2050)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ s32 tmp;
+
+ switch (radio->version) {
+ case 0x2050:
+ if (ofdm) {
+ tmp = in_rssi;
+ if (tmp > 127)
+ tmp -= 256;
+ tmp *= 73;
+ tmp /= 64;
+ if (adjust_2050)
+ tmp += 25;
+ else
+ tmp -= 3;
+ } else {
+ if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+ if (in_rssi > 63)
+ in_rssi = 63;
+ tmp = radio->nrssi_lt[in_rssi];
+ tmp = 31 - tmp;
+ tmp *= -131;
+ tmp /= 128;
+ tmp -= 57;
+ } else {
+ tmp = in_rssi;
+ tmp = 31 - tmp;
+ tmp *= -149;
+ tmp /= 128;
+ tmp -= 68;
+ }
+ if (phy->type == BCM43xx_PHYTYPE_G &&
+ adjust_2050)
+ tmp += 25;
+ }
+ break;
+ case 0x2060:
+ if (in_rssi > 127)
+ tmp = in_rssi - 256;
+ else
+ tmp = in_rssi;
+ break;
+ default:
+ tmp = in_rssi;
+ tmp -= 11;
+ tmp *= 103;
+ tmp /= 64;
+ if (adjust_2053)
+ tmp -= 109;
+ else
+ tmp -= 83;
+ }
+
+ return (s8)tmp;
+}
+
+//TODO
+#if 0
+static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
+ u8 in_rssi)
+{
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ s8 ret;
+
+ if (phy->type == BCM43xx_PHYTYPE_A) {
+ //TODO: Incomplete specs.
+ ret = 0;
+ } else
+ ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
+
+ return ret;
+}
+#endif
+
+int bcm43xx_rx(struct bcm43xx_private *bcm,
+ struct sk_buff *skb,
+ struct bcm43xx_rxhdr *rxhdr)
+{
+ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ struct bcm43xx_plcp_hdr4 *plcp;
+ struct ieee80211_rx_stats stats;
+ struct ieee80211_hdr_4addr *wlhdr;
+ u16 frame_ctl;
+ int is_packet_for_us = 0;
+ int err = -EINVAL;
+ const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
+ const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
+ const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
+ const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
+
+ if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
+ plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
+ /* Skip two unknown bytes and the PLCP header. */
+ skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
+ } else {
+ plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
+ /* Skip the PLCP header. */
+ skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
+ }
+ /* The SKB contains the PAYLOAD (wireless header + data)
+ * at this point. The FCS at the end is stripped.
+ */
+
+ memset(&stats, 0, sizeof(stats));
+ stats.mac_time = le16_to_cpu(rxhdr->mactime);
+ stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
+ !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
+ !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
+ stats.signal = rxhdr->signal_quality; //FIXME
+//TODO stats.noise =
+ if (is_ofdm)
+ stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
+ else
+ stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
+//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate);
+ stats.received_channel = radio->channel;
+//TODO stats.control =
+ stats.mask = IEEE80211_STATMASK_SIGNAL |
+//TODO IEEE80211_STATMASK_NOISE |
+ IEEE80211_STATMASK_RATE |
+ IEEE80211_STATMASK_RSSI;
+ if (phy->type == BCM43xx_PHYTYPE_A)
+ stats.freq = IEEE80211_52GHZ_BAND;
+ else
+ stats.freq = IEEE80211_24GHZ_BAND;
+ stats.len = skb->len;
+
+ bcm->stats.last_rx = jiffies;
+ if (bcm->ieee->iw_mode == IW_MODE_MONITOR) {
+ err = ieee80211_rx(bcm->ieee, skb, &stats);
+ return (err == 0) ? -EINVAL : 0;
+ }
+
+ wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
+
+ switch (bcm->ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
+ memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
+ is_broadcast_ether_addr(wlhdr->addr1) ||
+ is_multicast_ether_addr(wlhdr->addr1) ||
+ bcm->net_dev->flags & IFF_PROMISC)
+ is_packet_for_us = 1;
+ break;
+ case IW_MODE_INFRA:
+ default:
+ /* When receiving multicast or broadcast packets, filter out
+ the packets we send ourself; we shouldn't see those */
+ if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
+ memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
+ (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
+ (is_broadcast_ether_addr(wlhdr->addr1) ||
+ is_multicast_ether_addr(wlhdr->addr1) ||
+ bcm->net_dev->flags & IFF_PROMISC)))
+ is_packet_for_us = 1;
+ break;
+ }
+
+ frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
+ if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) {
+ frame_ctl &= ~IEEE80211_FCTL_PROTECTED;
+ wlhdr->frame_ctl = cpu_to_le16(frame_ctl);
+ /* trim IV and ICV */
+ /* FIXME: this must be done only for WEP encrypted packets */
+ if (skb->len < 32) {
+ dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag "
+ "set and length < 32)\n");
+ return -EINVAL;
+ } else {
+ memmove(skb->data + 4, skb->data, 24);
+ skb_pull(skb, 4);
+ skb_trim(skb, skb->len - 4);
+ stats.len -= 8;
+ }
+ wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
+ }
+
+ switch (WLAN_FC_GET_TYPE(frame_ctl)) {
+ case IEEE80211_FTYPE_MGMT:
+ ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
+ break;
+ case IEEE80211_FTYPE_DATA:
+ if (is_packet_for_us) {
+ err = ieee80211_rx(bcm->ieee, skb, &stats);
+ err = (err == 0) ? -EINVAL : 0;
+ }
+ break;
+ case IEEE80211_FTYPE_CTL:
+ break;
+ default:
+ assert(0);
+ return -EINVAL;
+ }
+
+ return err;
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
new file mode 100644
index 00000000000..2aed19e35c7
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
@@ -0,0 +1,156 @@
+#ifndef BCM43xx_XMIT_H_
+#define BCM43xx_XMIT_H_
+
+#include "bcm43xx_main.h"
+
+
+#define _bcm43xx_declare_plcp_hdr(size) \
+ struct bcm43xx_plcp_hdr##size { \
+ union { \
+ __le32 data; \
+ __u8 raw[size]; \
+ } __attribute__((__packed__)); \
+ } __attribute__((__packed__))
+
+/* struct bcm43xx_plcp_hdr4 */
+_bcm43xx_declare_plcp_hdr(4);
+/* struct bcm43xx_plcp_hdr6 */
+_bcm43xx_declare_plcp_hdr(6);
+
+#undef _bcm43xx_declare_plcp_hdr
+
+/* Device specific TX header. To be prepended to TX frames. */
+struct bcm43xx_txhdr {
+ union {
+ struct {
+ __le16 flags;
+ __le16 wsec_rate;
+ __le16 frame_control;
+ u16 unknown_zeroed_0;
+ __le16 control;
+ u8 wep_iv[10];
+ u8 unknown_wsec_tkip_data[3]; //FIXME
+ PAD_BYTES(3);
+ u8 mac1[6];
+ u16 unknown_zeroed_1;
+ struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp;
+ __le16 rts_cts_dur_fallback;
+ struct bcm43xx_plcp_hdr4 fallback_plcp;
+ __le16 fallback_dur_id;
+ PAD_BYTES(2);
+ __le16 cookie;
+ __le16 unknown_scb_stuff; //FIXME
+ struct bcm43xx_plcp_hdr6 rts_cts_plcp;
+ __le16 rts_cts_frame_control;
+ __le16 rts_cts_dur;
+ u8 rts_cts_mac1[6];
+ u8 rts_cts_mac2[6];
+ PAD_BYTES(2);
+ struct bcm43xx_plcp_hdr6 plcp;
+ } __attribute__((__packed__));
+ u8 raw[82];
+ } __attribute__((__packed__));
+} __attribute__((__packed__));
+
+/* Values/Masks for the device TX header */
+#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001
+#define BCM43xx_TXHDRFLAG_RTSCTS 0x0002
+#define BCM43xx_TXHDRFLAG_RTS 0x0004
+#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008
+#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020
+#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM 0x0080
+#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100
+#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM 0x0200
+#define BCM43xx_TXHDRFLAG_CTS 0x0400
+#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800
+
+#define BCM43xx_TXHDRCTL_OFDM 0x0001
+#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010
+#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030
+#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8
+
+#define BCM43xx_TXHDR_RATE_MASK 0x0F00
+#define BCM43xx_TXHDR_RATE_SHIFT 8
+#define BCM43xx_TXHDR_RTSRATE_MASK 0xF000
+#define BCM43xx_TXHDR_RTSRATE_SHIFT 12
+#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0
+#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4
+#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003
+#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0
+
+void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
+ struct bcm43xx_txhdr *txhdr,
+ const unsigned char *fragment_data,
+ const unsigned int fragment_len,
+ const int is_first_fragment,
+ const u16 cookie);
+
+/* RX header as received from the hardware. */
+struct bcm43xx_rxhdr {
+ /* Frame Length. Must be generated explicitely in PIO mode. */
+ __le16 frame_length;
+ PAD_BYTES(2);
+ /* Flags field 1 */
+ __le16 flags1;
+ u8 rssi;
+ u8 signal_quality;
+ PAD_BYTES(2);
+ /* Flags field 3 */
+ __le16 flags3;
+ /* Flags field 2 */
+ __le16 flags2;
+ /* Lower 16bits of the TSF at the time the frame started. */
+ __le16 mactime;
+ PAD_BYTES(14);
+} __attribute__((__packed__));
+
+#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0)
+/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */
+#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7)
+#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14)
+
+#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0)
+#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2)
+/*FIXME: WEP related flags */
+
+#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10)
+
+/* Transmit Status as received from the hardware. */
+struct bcm43xx_hwxmitstatus {
+ PAD_BYTES(4);
+ __le16 cookie;
+ u8 flags;
+ u8 cnt1:4,
+ cnt2:4;
+ PAD_BYTES(2);
+ __le16 seq;
+ __le16 unknown; //FIXME
+} __attribute__((__packed__));
+
+/* Transmit Status in CPU byteorder. */
+struct bcm43xx_xmitstatus {
+ u16 cookie;
+ u8 flags;
+ u8 cnt1:4,
+ cnt2:4;
+ u16 seq;
+ u16 unknown; //FIXME
+};
+
+#define BCM43xx_TXSTAT_FLAG_ACK 0x01
+//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x02
+//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x04
+//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x08
+//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x10
+#define BCM43xx_TXSTAT_FLAG_IGNORE 0x20
+//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40
+//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80
+
+u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate);
+u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate);
+
+int bcm43xx_rx(struct bcm43xx_private *bcm,
+ struct sk_buff *skb,
+ struct bcm43xx_rxhdr *rxhdr);
+
+#endif /* BCM43xx_XMIT_H_ */
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
index 1fc72fe511e..cc1ee7f4f5f 100644
--- a/drivers/net/wireless/hostap/hostap_80211.h
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -92,8 +92,6 @@ void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
void hostap_dump_tx_80211(const char *name, struct sk_buff *skb);
int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev);
int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev);
-struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
- struct ieee80211_crypt_data *crypt);
int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev);
#endif /* HOSTAP_80211_H */
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 4a85e63906f..06a5214145e 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -299,8 +299,8 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Called only from software IRQ */
-struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
- struct ieee80211_crypt_data *crypt)
+static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
+ struct ieee80211_crypt_data *crypt)
{
struct hostap_interface *iface;
local_info_t *local;
@@ -317,7 +317,7 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
}
if (local->tkip_countermeasures &&
- crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
+ strcmp(crypt->ops->name, "TKIP") == 0) {
hdr = (struct ieee80211_hdr_4addr *) skb->data;
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
@@ -469,7 +469,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt &&
- !(fc & IEEE80211_FCTL_VERS)) {
+ !(fc & IEEE80211_FCTL_PROTECTED)) {
no_encrypt = 1;
PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing "
"unencrypted EAPOL frame\n", dev->name);
@@ -535,5 +535,4 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
EXPORT_SYMBOL(hostap_dump_tx_80211);
-EXPORT_SYMBOL(hostap_tx_encrypt);
EXPORT_SYMBOL(hostap_master_start_xmit);
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index d335b250923..55bed923fbe 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -42,7 +42,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry");
/* struct local_info::hw_priv */
struct hostap_cs_priv {
dev_node_t node;
- dev_link_t *link;
+ struct pcmcia_device *link;
int sandisk_connectplus;
};
@@ -204,15 +204,13 @@ static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
static void prism2_detach(struct pcmcia_device *p_dev);
static void prism2_release(u_long arg);
-static int prism2_config(dev_link_t *link);
+static int prism2_config(struct pcmcia_device *link);
static int prism2_pccard_card_present(local_info_t *local)
{
struct hostap_cs_priv *hw_priv = local->hw_priv;
- if (hw_priv != NULL && hw_priv->link != NULL &&
- ((hw_priv->link->state & (DEV_PRESENT | DEV_CONFIG)) ==
- (DEV_PRESENT | DEV_CONFIG)))
+ if (hw_priv != NULL && hw_priv->link != NULL && pcmcia_dev_present(hw_priv->link))
return 1;
return 0;
}
@@ -237,7 +235,7 @@ static void sandisk_set_iobase(local_info_t *local)
reg.Action = CS_WRITE;
reg.Offset = 0x10; /* 0x3f0 IO base 1 */
reg.Value = hw_priv->link->io.BasePort1 & 0x00ff;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -"
@@ -249,7 +247,7 @@ static void sandisk_set_iobase(local_info_t *local)
reg.Action = CS_WRITE;
reg.Offset = 0x12; /* 0x3f2 IO base 2 */
reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -"
@@ -301,9 +299,9 @@ static int sandisk_enable_wireless(struct net_device *dev)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) ||
- pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) ||
- pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) ||
+ if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
+ pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
+ pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) {
/* No SanDisk manfid found */
ret = -ENODEV;
@@ -311,9 +309,9 @@ static int sandisk_enable_wireless(struct net_device *dev)
}
tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
- if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) ||
- pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) ||
- pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) ||
+ if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
+ pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
+ pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
parse->longlink_mfc.nfn < 2) {
/* No multi-function links found */
ret = -ENODEV;
@@ -328,7 +326,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
reg.Action = CS_WRITE;
reg.Offset = CISREG_COR;
reg.Value = COR_SOFT_RESET;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
@@ -345,7 +343,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
* will be enabled during the first cor_sreset call.
*/
reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
@@ -380,7 +378,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
reg.Action = CS_READ;
reg.Offset = CISREG_COR;
reg.Value = 0;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n",
@@ -392,7 +390,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
reg.Action = CS_WRITE;
reg.Value |= COR_SOFT_RESET;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n",
@@ -405,7 +403,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
reg.Value &= ~COR_SOFT_RESET;
if (hw_priv->sandisk_connectplus)
reg.Value |= COR_IREQ_ENA;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n",
@@ -439,7 +437,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
reg.Action = CS_READ;
reg.Offset = CISREG_COR;
reg.Value = 0;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 "
@@ -452,7 +450,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
reg.Action = CS_WRITE;
reg.Value |= COR_SOFT_RESET;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 "
@@ -466,7 +464,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
reg.Action = CS_WRITE;
reg.Value = hcr;
reg.Offset = CISREG_CCSR;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 "
@@ -478,7 +476,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
reg.Action = CS_WRITE;
reg.Offset = CISREG_COR;
reg.Value = old_cor & ~COR_SOFT_RESET;
- res = pcmcia_access_configuration_register(hw_priv->link->handle,
+ res = pcmcia_access_configuration_register(hw_priv->link,
&reg);
if (res != CS_SUCCESS) {
printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 "
@@ -501,40 +499,27 @@ static struct prism2_helper_functions prism2_pccard_funcs =
/* allocate local data and register with CardServices
* initialize dev_link structure, but do not configure the card yet */
-static int prism2_attach(struct pcmcia_device *p_dev)
+static int hostap_cs_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
-
- link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
- if (link == NULL)
- return -ENOMEM;
-
- memset(link, 0, sizeof(dev_link_t));
+ int ret;
PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
- link->conf.Vcc = 33;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
- link->handle = p_dev;
- p_dev->instance = link;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- if (prism2_config(link))
+ ret = prism2_config(p_dev);
+ if (ret) {
PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
+ }
- return 0;
+ return ret;
}
-static void prism2_detach(struct pcmcia_device *p_dev)
+static void prism2_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
PDEBUG(DEBUG_FLOW, "prism2_detach\n");
- if (link->state & DEV_CONFIG) {
- prism2_release((u_long)link);
- }
+ prism2_release((u_long)link);
/* release net devices */
if (link->priv) {
@@ -547,7 +532,6 @@ static void prism2_detach(struct pcmcia_device *p_dev)
prism2_free_local_data(dev);
kfree(hw_priv);
}
- kfree(link);
}
@@ -558,7 +542,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
do { int ret = (retf); \
if (ret != 0) { \
PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", ret); \
- cs_error(link->handle, fn, ret); \
+ cs_error(link, fn, ret); \
goto next_entry; \
} \
} while (0)
@@ -566,7 +550,7 @@ if (ret != 0) { \
/* run after a CARD_INSERTION event is received to configure the PCMCIA
* socket and make the device available to the system */
-static int prism2_config(dev_link_t *link)
+static int prism2_config(struct pcmcia_device *link)
{
struct net_device *dev;
struct hostap_interface *iface;
@@ -595,27 +579,24 @@ static int prism2_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link->handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(link->handle, &tuple, parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(link->handle, &conf));
- PDEBUG(DEBUG_HW, "%s: %s Vcc=%d (from config)\n", dev_info,
- ignore_cis_vcc ? "ignoring" : "setting", conf.Vcc);
- link->conf.Vcc = conf.Vcc;
+ pcmcia_get_configuration_info(link, &conf));
/* Look for an appropriate configuration table entry in the CIS */
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
for (;;) {
cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
CFG_CHECK2(GetTupleData,
- pcmcia_get_tuple_data(link->handle, &tuple));
+ pcmcia_get_tuple_data(link, &tuple));
CFG_CHECK2(ParseTuple,
- pcmcia_parse_tuple(link->handle, &tuple, parse));
+ pcmcia_parse_tuple(link, &tuple, parse));
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
dflt = *cfg;
@@ -650,10 +631,10 @@ static int prism2_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
/* Do we need to allocate an interrupt? */
@@ -695,19 +676,19 @@ static int prism2_config(dev_link_t *link)
/* This reserves IO space but doesn't actually enable it */
CFG_CHECK2(RequestIO,
- pcmcia_request_io(link->handle, &link->io));
+ pcmcia_request_io(link, &link->io));
/* This configuration table entry is OK */
break;
next_entry:
CS_CHECK(GetNextTuple,
- pcmcia_get_next_tuple(link->handle, &tuple));
+ pcmcia_get_next_tuple(link, &tuple));
}
/* Need to allocate net_device before requesting IRQ handler */
dev = prism2_init_local_data(&prism2_pccard_funcs, 0,
- &handle_to_dev(link->handle));
+ &handle_to_dev(link));
if (dev == NULL)
goto failed;
link->priv = dev;
@@ -717,7 +698,7 @@ static int prism2_config(dev_link_t *link)
local->hw_priv = hw_priv;
hw_priv->link = link;
strcpy(hw_priv->node.dev_name, dev->name);
- link->dev = &hw_priv->node;
+ link->dev_node = &hw_priv->node;
/*
* Allocate an interrupt line. Note that this does not assign a
@@ -730,7 +711,7 @@ static int prism2_config(dev_link_t *link)
link->irq.Handler = prism2_interrupt;
link->irq.Instance = dev;
CS_CHECK(RequestIRQ,
- pcmcia_request_irq(link->handle, &link->irq));
+ pcmcia_request_irq(link, &link->irq));
}
/*
@@ -739,18 +720,17 @@ static int prism2_config(dev_link_t *link)
* card and host interface into "Memory and IO" mode.
*/
CS_CHECK(RequestConfiguration,
- pcmcia_request_configuration(link->handle, &link->conf));
+ pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
/* Finally, report what we've done */
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev_info, link->conf.ConfigIndex,
- link->conf.Vcc / 10, link->conf.Vcc % 10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
- link->conf.Vpp1 % 10);
+ printk(KERN_INFO "%s: index 0x%02x: ",
+ dev_info, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp / 10,
+ link->conf.Vpp % 10);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
@@ -761,9 +741,6 @@ static int prism2_config(dev_link_t *link)
link->io.BasePort2+link->io.NumPorts2-1);
printk("\n");
- link->state |= DEV_CONFIG;
- link->state &= ~DEV_CONFIG_PENDING;
-
local->shutdown = 0;
sandisk_enable_wireless(dev);
@@ -778,7 +755,7 @@ static int prism2_config(dev_link_t *link)
return ret;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
kfree(parse);
@@ -790,7 +767,7 @@ static int prism2_config(dev_link_t *link)
static void prism2_release(u_long arg)
{
- dev_link_t *link = (dev_link_t *)arg;
+ struct pcmcia_device *link = (struct pcmcia_device *)arg;
PDEBUG(DEBUG_FLOW, "prism2_release\n");
@@ -799,71 +776,54 @@ static void prism2_release(u_long arg)
struct hostap_interface *iface;
iface = netdev_priv(dev);
- if (link->state & DEV_CONFIG)
- prism2_hw_shutdown(dev, 0);
+ prism2_hw_shutdown(dev, 0);
iface->local->shutdown = 1;
}
- if (link->win)
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-
+ pcmcia_disable_device(link);
PDEBUG(DEBUG_FLOW, "release - done\n");
}
-static int hostap_cs_suspend(struct pcmcia_device *p_dev)
+static int hostap_cs_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = (struct net_device *) link->priv;
int dev_open = 0;
+ struct hostap_interface *iface = NULL;
- PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
-
- link->state |= DEV_SUSPEND;
+ if (dev)
+ iface = netdev_priv(dev);
- if (link->state & DEV_CONFIG) {
- struct hostap_interface *iface = netdev_priv(dev);
- if (iface && iface->local)
- dev_open = iface->local->num_dev_open > 0;
- if (dev_open) {
- netif_stop_queue(dev);
- netif_device_detach(dev);
- }
- prism2_suspend(dev);
- pcmcia_release_configuration(link->handle);
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
+ if (iface && iface->local)
+ dev_open = iface->local->num_dev_open > 0;
+ if (dev_open) {
+ netif_stop_queue(dev);
+ netif_device_detach(dev);
}
+ prism2_suspend(dev);
return 0;
}
-static int hostap_cs_resume(struct pcmcia_device *p_dev)
+static int hostap_cs_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = (struct net_device *) link->priv;
int dev_open = 0;
+ struct hostap_interface *iface = NULL;
- PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
+ if (dev)
+ iface = netdev_priv(dev);
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- struct hostap_interface *iface = netdev_priv(dev);
- if (iface && iface->local)
- dev_open = iface->local->num_dev_open > 0;
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
- pcmcia_request_configuration(link->handle, &link->conf);
+ if (iface && iface->local)
+ dev_open = iface->local->num_dev_open > 0;
- prism2_hw_shutdown(dev, 1);
- prism2_hw_config(dev, dev_open ? 0 : 1);
- if (dev_open) {
- netif_device_attach(dev);
- netif_start_queue(dev);
- }
+ prism2_hw_shutdown(dev, 1);
+ prism2_hw_config(dev, dev_open ? 0 : 1);
+ if (dev_open) {
+ netif_device_attach(dev);
+ netif_start_queue(dev);
}
return 0;
@@ -930,7 +890,7 @@ static struct pcmcia_driver hostap_driver = {
.drv = {
.name = "hostap_cs",
},
- .probe = prism2_attach,
+ .probe = hostap_cs_probe,
.remove = prism2_detach,
.owner = THIS_MODULE,
.id_table = hostap_cs_ids,
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 8b37e824dfc..8399de58189 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -1860,7 +1860,7 @@ static char * __prism2_translate_scan(local_info_t *local,
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWFREQ;
if (scan) {
- chan = scan->chid;
+ chan = le16_to_cpu(scan->chid);
} else if (bss) {
chan = bss->chan;
} else {
@@ -1868,7 +1868,7 @@ static char * __prism2_translate_scan(local_info_t *local,
}
if (chan > 0) {
- iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000;
+ iwe.u.freq.m = freq_list[chan - 1] * 100000;
iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
IW_EV_FREQ_LEN);
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 9dce522526c..bca89cff85a 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -5573,8 +5573,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
case IEEE80211_52GHZ_BAND:
network->mode = IEEE_A;
i = ieee80211_channel_to_index(priv->ieee, priv->channel);
- if (i == -1)
- BUG();
+ BUG_ON(i == -1);
if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
IPW_WARNING("Overriding invalid channel\n");
priv->channel = geo->a[0].channel;
@@ -5587,8 +5586,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
else
network->mode = IEEE_B;
i = ieee80211_channel_to_index(priv->ieee, priv->channel);
- if (i == -1)
- BUG();
+ BUG_ON(i == -1);
if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
IPW_WARNING("Overriding invalid channel\n");
priv->channel = geo->bg[0].channel;
@@ -6715,8 +6713,7 @@ static int ipw_qos_association(struct ipw_priv *priv,
switch (priv->ieee->iw_mode) {
case IW_MODE_ADHOC:
- if (!(network->capability & WLAN_CAPABILITY_IBSS))
- BUG();
+ BUG_ON(!(network->capability & WLAN_CAPABILITY_IBSS));
qos_data = &ibss_data;
break;
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 75ce6ddb0cf..9343d970537 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -190,8 +190,8 @@ module_param(mem_speed, int, 0);
/*====================================================================*/
/* PCMCIA (Card Services) related functions */
-static void netwave_release(dev_link_t *link); /* Card removal */
-static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card
+static void netwave_release(struct pcmcia_device *link); /* Card removal */
+static int netwave_pcmcia_config(struct pcmcia_device *arg); /* Runs after card
insertion */
static void netwave_detach(struct pcmcia_device *p_dev); /* Destroy instance */
@@ -221,10 +221,10 @@ static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
/*
- A dev_link_t structure has fields for most things that are needed
+ A struct pcmcia_device structure has fields for most things that are needed
to keep track of a socket, but there will usually be some device
specific information that also needs to be kept track of. The
- 'priv' pointer in a dev_link_t structure can be used to point to
+ 'priv' pointer in a struct pcmcia_device structure can be used to point to
a device-specific private data structure, like this.
A driver needs to provide a dev_node_t structure for each device
@@ -232,7 +232,7 @@ static void set_multicast_list(struct net_device *dev);
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally can't be allocated dynamically.
*/
@@ -268,7 +268,7 @@ struct site_survey {
};
typedef struct netwave_private {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
spinlock_t spinlock; /* Serialize access to the hardware (SMP) */
dev_node_t node;
u_char __iomem *ramBase;
@@ -376,20 +376,19 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
* configure the card at this point -- we wait until we receive a
* card insertion event.
*/
-static int netwave_attach(struct pcmcia_device *p_dev)
+static int netwave_probe(struct pcmcia_device *link)
{
- dev_link_t *link;
struct net_device *dev;
netwave_private *priv;
DEBUG(0, "netwave_attach()\n");
- /* Initialize the dev_link_t structure */
+ /* Initialize the struct pcmcia_device structure */
dev = alloc_etherdev(sizeof(netwave_private));
if (!dev)
return -ENOMEM;
priv = netdev_priv(dev);
- link = &priv->link;
+ priv->p_dev = link;
link->priv = dev;
/* The io structure describes IO port mapping */
@@ -406,7 +405,6 @@ static int netwave_attach(struct pcmcia_device *p_dev)
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
@@ -430,13 +428,7 @@ static int netwave_attach(struct pcmcia_device *p_dev)
dev->stop = &netwave_close;
link->irq.Instance = dev;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- netwave_pcmcia_config( link);
-
- return 0;
+ return netwave_pcmcia_config( link);
} /* netwave_attach */
/*
@@ -447,17 +439,15 @@ static int netwave_attach(struct pcmcia_device *p_dev)
* structures are freed. Otherwise, the structures will be freed
* when the device is released.
*/
-static void netwave_detach(struct pcmcia_device *p_dev)
+static void netwave_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
DEBUG(0, "netwave_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- netwave_release(link);
+ netwave_release(link);
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
free_netdev(dev);
@@ -743,8 +733,7 @@ static const struct iw_handler_def netwave_handler_def =
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void netwave_pcmcia_config(dev_link_t *link) {
- client_handle_t handle = link->handle;
+static int netwave_pcmcia_config(struct pcmcia_device *link) {
struct net_device *dev = link->priv;
netwave_private *priv = netdev_priv(dev);
tuple_t tuple;
@@ -766,15 +755,12 @@ static void netwave_pcmcia_config(dev_link_t *link) {
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/*
* Try allocating IO ports. This tries a few fixed addresses.
* If you want, you can also read the card's config table to
@@ -782,11 +768,11 @@ static void netwave_pcmcia_config(dev_link_t *link) {
*/
for (i = j = 0x0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
@@ -794,16 +780,16 @@ static void netwave_pcmcia_config(dev_link_t *link) {
* Now allocate an interrupt line. Note that this does not
* actually assign a handler to the interrupt.
*/
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/*
* This actually configures the PCMCIA socket -- setting up
* the I/O windows and the interrupt mapping.
*/
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/*
- * Allocate a 32K memory window. Note that the dev_link_t
+ * Allocate a 32K memory window. Note that the struct pcmcia_device
* structure provides space for one window handle -- if your
* device needs several windows, you'll need to keep track of
* the handles in your private data structure, dev->priv.
@@ -813,7 +799,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
req.Base = 0; req.Size = 0x8000;
req.AccessSpeed = mem_speed;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
mem.CardOffset = 0x20000; mem.Page = 0;
CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
@@ -823,7 +809,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev) != 0) {
printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n");
@@ -831,8 +817,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
}
strcpy(priv->node.dev_name, dev->name);
- link->dev = &priv->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &priv->node;
/* Reset card before reading physical address */
netwave_doreset(dev->base_addr, ramBase);
@@ -852,12 +837,13 @@ static void netwave_pcmcia_config(dev_link_t *link) {
printk(KERN_DEBUG "Netwave_reset: revision %04x %04x\n",
get_uint16(ramBase + NETWAVE_EREG_ARW),
get_uint16(ramBase + NETWAVE_EREG_ARW+2));
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
netwave_release(link);
+ return -ENODEV;
} /* netwave_pcmcia_config */
/*
@@ -867,52 +853,35 @@ failed:
* device, and release the PCMCIA configuration. If the device is
* still open, this will be postponed until it is closed.
*/
-static void netwave_release(dev_link_t *link)
+static void netwave_release(struct pcmcia_device *link)
{
- struct net_device *dev = link->priv;
- netwave_private *priv = netdev_priv(dev);
-
- DEBUG(0, "netwave_release(0x%p)\n", link);
+ struct net_device *dev = link->priv;
+ netwave_private *priv = netdev_priv(dev);
- /* Don't bother checking to see if these succeed or not */
- if (link->win) {
- iounmap(priv->ramBase);
- pcmcia_release_window(link->win);
- }
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
+ DEBUG(0, "netwave_release(0x%p)\n", link);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
+ if (link->win)
+ iounmap(priv->ramBase);
}
-static int netwave_suspend(struct pcmcia_device *p_dev)
+static int netwave_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int netwave_resume(struct pcmcia_device *p_dev)
+static int netwave_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- netwave_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ netwave_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -1119,7 +1088,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs
u_char __iomem *ramBase;
struct net_device *dev = (struct net_device *)dev_id;
struct netwave_private *priv = netdev_priv(dev);
- dev_link_t *link = &priv->link;
+ struct pcmcia_device *link = priv->p_dev;
int i;
if (!netif_device_present(dev))
@@ -1138,7 +1107,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs
status = inb(iobase + NETWAVE_REG_ASR);
- if (!DEV_OK(link)) {
+ if (!pcmcia_dev_present(link)) {
DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x "
"from removed or suspended card!\n", status);
break;
@@ -1373,11 +1342,11 @@ static int netwave_rx(struct net_device *dev)
static int netwave_open(struct net_device *dev) {
netwave_private *priv = netdev_priv(dev);
- dev_link_t *link = &priv->link;
+ struct pcmcia_device *link = priv->p_dev;
DEBUG(1, "netwave_open: starting.\n");
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
@@ -1390,7 +1359,7 @@ static int netwave_open(struct net_device *dev) {
static int netwave_close(struct net_device *dev) {
netwave_private *priv = netdev_priv(dev);
- dev_link_t *link = &priv->link;
+ struct pcmcia_device *link = priv->p_dev;
DEBUG(1, "netwave_close: finishing.\n");
@@ -1411,7 +1380,7 @@ static struct pcmcia_driver netwave_driver = {
.drv = {
.name = "netwave_cs",
},
- .probe = netwave_attach,
+ .probe = netwave_probe,
.remove = netwave_detach,
.id_table = netwave_ids,
.suspend = netwave_suspend,
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 6fd0bf73683..c2d0b09e041 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -390,7 +390,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
}
} else {
struct {
- __le16 qual, signal, noise;
+ __le16 qual, signal, noise, unused;
} __attribute__ ((packed)) cq;
err = HERMES_READ_RECORD(hw, USER_BAP,
@@ -812,7 +812,6 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
if (datalen > IEEE80211_DATA_LEN + 12) {
printk(KERN_DEBUG "%s: oversized monitor frame, "
"data length = %d\n", dev->name, datalen);
- err = -EIO;
stats->rx_length_errors++;
goto update_stats;
}
@@ -821,8 +820,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
if (!skb) {
printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
dev->name);
- err = -ENOMEM;
- goto drop;
+ goto update_stats;
}
/* Copy the 802.11 header to the skb */
@@ -3858,7 +3856,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
unsigned long flags;
/* Note : you may have realised that, as this is a SET operation,
- * this is priviledged and therefore a normal user can't
+ * this is privileged and therefore a normal user can't
* perform scanning.
* This is not an error, while the device perform scanning,
* traffic doesn't flow, so it's a perfect DoS...
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index ec6f2a48895..434f7d7ad84 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -49,7 +49,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket
/* PCMCIA specific device information (goes in the card field of
* struct orinoco_private */
struct orinoco_pccard {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
/* Used to handle hard reset */
@@ -63,8 +63,8 @@ struct orinoco_pccard {
/* Function prototypes */
/********************************************************************/
-static void orinoco_cs_config(dev_link_t *link);
-static void orinoco_cs_release(dev_link_t *link);
+static int orinoco_cs_config(struct pcmcia_device *link);
+static void orinoco_cs_release(struct pcmcia_device *link);
static void orinoco_cs_detach(struct pcmcia_device *p_dev);
/********************************************************************/
@@ -75,13 +75,13 @@ static int
orinoco_cs_hard_reset(struct orinoco_private *priv)
{
struct orinoco_pccard *card = priv->card;
- dev_link_t *link = &card->link;
+ struct pcmcia_device *link = card->p_dev;
int err;
/* We need atomic ops here, because we're not holding the lock */
set_bit(0, &card->hard_reset_in_progress);
- err = pcmcia_reset_card(link->handle, NULL);
+ err = pcmcia_reset_card(link, NULL);
if (err)
return err;
@@ -104,12 +104,11 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
* configure the card at this point -- we wait until we receive a card
* insertion event. */
static int
-orinoco_cs_attach(struct pcmcia_device *p_dev)
+orinoco_cs_probe(struct pcmcia_device *link)
{
struct net_device *dev;
struct orinoco_private *priv;
struct orinoco_pccard *card;
- dev_link_t *link;
dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
if (! dev)
@@ -118,7 +117,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev)
card = priv->card;
/* Link both structures together */
- link = &card->link;
+ card->p_dev = link;
link->priv = dev;
/* Interrupt setup */
@@ -135,16 +134,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev)
link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- link->next = NULL;
-
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- orinoco_cs_config(link);
-
- return 0;
+ return orinoco_cs_config(link);
} /* orinoco_cs_attach */
/*
@@ -153,16 +143,14 @@ orinoco_cs_attach(struct pcmcia_device *p_dev)
* are freed. Otherwise, the structures will be freed when the device
* is released.
*/
-static void orinoco_cs_detach(struct pcmcia_device *p_dev)
+static void orinoco_cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- if (link->state & DEV_CONFIG)
- orinoco_cs_release(link);
+ orinoco_cs_release(link);
- DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
- if (link->dev) {
+ DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
+ if (link->dev_node) {
DEBUG(0, PFX "About to unregister net device %p\n",
dev);
unregister_netdev(dev);
@@ -180,11 +168,10 @@ static void orinoco_cs_detach(struct pcmcia_device *p_dev)
last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
} while (0)
-static void
-orinoco_cs_config(dev_link_t *link)
+static int
+orinoco_cs_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- client_handle_t handle = link->handle;
struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card;
hermes_t *hw = &priv->hw;
@@ -196,7 +183,7 @@ orinoco_cs_config(dev_link_t *link)
cisparse_t parse;
void __iomem *mem;
- CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
+ CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
/*
* This reads the card's CONFIG tuple to find its
@@ -207,19 +194,15 @@ orinoco_cs_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Look up the current Vcc */
CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
+ pcmcia_get_configuration_info(link, &conf));
/*
* In this loop, we scan the CIS for configuration table
@@ -236,13 +219,13 @@ orinoco_cs_config(dev_link_t *link)
* implementation-defined details.
*/
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
cistpl_cftable_entry_t dflt = { .index = 0 };
- if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
- || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
+ if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
+ || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
@@ -274,10 +257,10 @@ orinoco_cs_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
/* Do we need to allocate an interrupt? */
@@ -307,7 +290,7 @@ orinoco_cs_config(dev_link_t *link)
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
@@ -317,9 +300,8 @@ orinoco_cs_config(dev_link_t *link)
break;
next_entry:
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ pcmcia_disable_device(link);
+ last_ret = pcmcia_get_next_tuple(link, &tuple);
if (last_ret == CS_NO_MORE_ITEMS) {
printk(KERN_ERR PFX "GetNextTuple(): No matching "
"CIS configuration. Maybe you need the "
@@ -333,7 +315,7 @@ orinoco_cs_config(dev_link_t *link)
* a handler to the interrupt, unless the 'Handler' member of
* the irq structure is initialized.
*/
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/* We initialize the hermes structure before completing PCMCIA
* configuration just in case the interrupt handler gets
@@ -350,7 +332,7 @@ orinoco_cs_config(dev_link_t *link)
* card and host interface into "Memory and IO" mode.
*/
CS_CHECK(RequestConfiguration,
- pcmcia_request_configuration(link->handle, &link->conf));
+ pcmcia_request_configuration(link, &link->conf));
/* Ok, we have the configuration, prepare to register the netdev */
dev->base_addr = link->io.BasePort1;
@@ -358,7 +340,7 @@ orinoco_cs_config(dev_link_t *link)
SET_MODULE_OWNER(dev);
card->node.major = card->node.minor = 0;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
/* Tell the stack we exist */
if (register_netdev(dev) != 0) {
printk(KERN_ERR PFX "register_netdev() failed\n");
@@ -366,20 +348,18 @@ orinoco_cs_config(dev_link_t *link)
}
/* At this point, the dev_node_t structure(s) needs to be
- * initialized and arranged in a linked list at link->dev. */
+ * initialized and arranged in a linked list at link->dev_node. */
strcpy(card->node.dev_name, dev->name);
- link->dev = &card->node; /* link->dev being non-NULL is also
+ link->dev_node = &card->node; /* link->dev_node being non-NULL is also
used to indicate that the
net_device has been registered */
- link->state &= ~DEV_CONFIG_PENDING;
/* Finally, report what we've done */
- printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
- dev->name, link->conf.ConfigIndex,
- link->conf.Vcc / 10, link->conf.Vcc % 10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
- link->conf.Vpp1 % 10);
+ printk(KERN_DEBUG "%s: index 0x%02x: ",
+ dev->name, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp / 10,
+ link->conf.Vpp % 10);
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
printk(", io 0x%04x-0x%04x", link->io.BasePort1,
@@ -389,13 +369,14 @@ orinoco_cs_config(dev_link_t *link)
link->io.BasePort2 + link->io.NumPorts2 - 1);
printk("\n");
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
orinoco_cs_release(link);
+ return -ENODEV;
} /* orinoco_cs_config */
/*
@@ -404,7 +385,7 @@ orinoco_cs_config(dev_link_t *link)
* still open, this will be postponed until it is closed.
*/
static void
-orinoco_cs_release(dev_link_t *link)
+orinoco_cs_release(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
@@ -416,88 +397,68 @@ orinoco_cs_release(dev_link_t *link)
priv->hw_unavailable++;
spin_unlock_irqrestore(&priv->lock, flags);
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
if (priv->hw.iobase)
ioport_unmap(priv->hw.iobase);
} /* orinoco_cs_release */
-static int orinoco_cs_suspend(struct pcmcia_device *p_dev)
+static int orinoco_cs_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card;
int err = 0;
unsigned long flags;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- /* This is probably racy, but I can't think of
- a better way, short of rewriting the PCMCIA
- layer to not suck :-( */
- if (! test_bit(0, &card->hard_reset_in_progress)) {
- spin_lock_irqsave(&priv->lock, flags);
+ /* This is probably racy, but I can't think of
+ a better way, short of rewriting the PCMCIA
+ layer to not suck :-( */
+ if (! test_bit(0, &card->hard_reset_in_progress)) {
+ spin_lock_irqsave(&priv->lock, flags);
- err = __orinoco_down(dev);
- if (err)
- printk(KERN_WARNING "%s: Error %d downing interface\n",
- dev->name, err);
+ err = __orinoco_down(dev);
+ if (err)
+ printk(KERN_WARNING "%s: Error %d downing interface\n",
+ dev->name, err);
- netif_device_detach(dev);
- priv->hw_unavailable++;
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
- spin_unlock_irqrestore(&priv->lock, flags);
- }
-
- pcmcia_release_configuration(link->handle);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
return 0;
}
-static int orinoco_cs_resume(struct pcmcia_device *p_dev)
+static int orinoco_cs_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card;
int err = 0;
unsigned long flags;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- /* FIXME: should we double check that this is
- * the same card as we had before */
- pcmcia_request_configuration(link->handle, &link->conf);
-
- if (! test_bit(0, &card->hard_reset_in_progress)) {
- err = orinoco_reinit_firmware(dev);
- if (err) {
- printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
- dev->name, err);
- return -EIO;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
+ if (! test_bit(0, &card->hard_reset_in_progress)) {
+ err = orinoco_reinit_firmware(dev);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
+ dev->name, err);
+ return -EIO;
+ }
- netif_device_attach(dev);
- priv->hw_unavailable--;
+ spin_lock_irqsave(&priv->lock, flags);
- if (priv->open && ! priv->hw_unavailable) {
- err = __orinoco_up(dev);
- if (err)
- printk(KERN_ERR "%s: Error %d restarting card\n",
- dev->name, err);
- }
+ netif_device_attach(dev);
+ priv->hw_unavailable--;
- spin_unlock_irqrestore(&priv->lock, flags);
+ if (priv->open && ! priv->hw_unavailable) {
+ err = __orinoco_up(dev);
+ if (err)
+ printk(KERN_ERR "%s: Error %d restarting card\n",
+ dev->name, err);
}
+
+ spin_unlock_irqrestore(&priv->lock, flags);
}
return 0;
@@ -604,7 +565,7 @@ static struct pcmcia_driver orinoco_driver = {
.drv = {
.name = DRIVER_NAME,
},
- .probe = orinoco_cs_attach,
+ .probe = orinoco_cs_probe,
.remove = orinoco_cs_detach,
.id_table = orinoco_cs_ids,
.suspend = orinoco_cs_suspend,
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index e5bb9f5ae42..989599ad33e 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -747,7 +747,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info,
if (essid->length) {
dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */
- /* if it is to big, trunk it */
+ /* if it is too big, trunk it */
dwrq->length = min((u8)IW_ESSID_MAX_SIZE, essid->length);
} else {
dwrq->flags = 0;
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index b41d666fea3..bfa0cc319a0 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -22,6 +22,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/init.h> /* For __init, __exit */
+#include <linux/dma-mapping.h>
#include "prismcompat.h"
#include "islpci_dev.h"
@@ -124,7 +125,7 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
/* enable PCI DMA */
- if (pci_set_dma_mask(pdev, 0xffffffff)) {
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_ERR "%s: 32-bit PCI DMA not supported", DRV_NAME);
goto do_pci_disable_device;
}
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 7880d8c31aa..879eb427607 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -90,8 +90,8 @@ module_param(pc_debug, int, 0);
#define DEBUG(n, args...)
#endif
/** Prototypes based on PCMCIA skeleton driver *******************************/
-static void ray_config(dev_link_t *link);
-static void ray_release(dev_link_t *link);
+static int ray_config(struct pcmcia_device *link);
+static void ray_release(struct pcmcia_device *link);
static void ray_detach(struct pcmcia_device *p_dev);
/***** Prototypes indicated by device structure ******************************/
@@ -190,20 +190,17 @@ static int bc;
static char *phy_addr = NULL;
-/* A linked list of "instances" of the ray device. Each actual
- PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
-*/
-static dev_link_t *dev_list = NULL;
-
-/* A dev_link_t structure has fields for most things that are needed
+/* A struct pcmcia_device structure has fields for most things that are needed
to keep track of a socket, but there will usually be some device
specific information that also needs to be kept track of. The
- 'priv' pointer in a dev_link_t structure can be used to point to
+ 'priv' pointer in a struct pcmcia_device structure can be used to point to
a device-specific private data structure, like this.
*/
static unsigned int ray_mem_speed = 500;
+/* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */
+static struct pcmcia_device *this_device = NULL;
+
MODULE_AUTHOR("Corey Thomas <corey@world.std.com>");
MODULE_DESCRIPTION("Raylink/WebGear wireless LAN driver");
MODULE_LICENSE("GPL");
@@ -306,56 +303,46 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.
configure the card at this point -- we wait until we receive a
card insertion event.
=============================================================================*/
-static int ray_attach(struct pcmcia_device *p_dev)
+static int ray_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
ray_dev_t *local;
struct net_device *dev;
-
- DEBUG(1, "ray_attach()\n");
- /* Initialize the dev_link_t structure */
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-
- if (!link)
- return -ENOMEM;
+ DEBUG(1, "ray_attach()\n");
/* Allocate space for private device-specific data */
dev = alloc_etherdev(sizeof(ray_dev_t));
-
if (!dev)
goto fail_alloc_dev;
local = dev->priv;
-
- memset(link, 0, sizeof(struct dev_link_t));
+ local->finder = p_dev;
/* The io structure describes IO port mapping. None used here */
- link->io.NumPorts1 = 0;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = 5;
+ p_dev->io.NumPorts1 = 0;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = 5;
/* Interrupt setup. For PCMCIA, driver takes what's given */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.Handler = &ray_interrupt;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->irq.Handler = &ray_interrupt;
/* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
-
- link->priv = dev;
- link->irq.Instance = dev;
+ p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.ConfigIndex = 1;
+ p_dev->conf.Present = PRESENT_OPTION;
+
+ p_dev->priv = dev;
+ p_dev->irq.Instance = dev;
- local->finder = link;
+ local->finder = p_dev;
local->card_status = CARD_INSERTED;
local->authentication_state = UNAUTHENTICATED;
local->num_multi = 0;
- DEBUG(2,"ray_attach link = %p, dev = %p, local = %p, intr = %p\n",
- link,dev,local,&ray_interrupt);
+ DEBUG(2,"ray_attach p_dev = %p, dev = %p, local = %p, intr = %p\n",
+ p_dev,dev,local,&ray_interrupt);
/* Raylink entries in the device structure */
dev->hard_start_xmit = &ray_dev_start_xmit;
@@ -379,16 +366,10 @@ static int ray_attach(struct pcmcia_device *p_dev)
init_timer(&local->timer);
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- ray_config(link);
-
- return 0;
+ this_device = p_dev;
+ return ray_config(p_dev);
fail_alloc_dev:
- kfree(link);
return -ENOMEM;
} /* ray_attach */
/*=============================================================================
@@ -397,37 +378,25 @@ fail_alloc_dev:
structures are freed. Otherwise, the structures will be freed
when the device is released.
=============================================================================*/
-static void ray_detach(struct pcmcia_device *p_dev)
+static void ray_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
- dev_link_t **linkp;
struct net_device *dev;
ray_dev_t *local;
DEBUG(1, "ray_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
+ this_device = NULL;
dev = link->priv;
- if (link->state & DEV_CONFIG) {
- ray_release(link);
+ ray_release(link);
- local = (ray_dev_t *)dev->priv;
- del_timer(&local->timer);
- }
+ local = (ray_dev_t *)dev->priv;
+ del_timer(&local->timer);
- /* Unlink device structure, free pieces */
- *linkp = link->next;
if (link->priv) {
- if (link->dev) unregister_netdev(dev);
+ if (link->dev_node) unregister_netdev(dev);
free_netdev(dev);
}
- kfree(link);
DEBUG(2,"ray_cs ray_detach ending\n");
} /* ray_detach */
/*=============================================================================
@@ -438,9 +407,8 @@ static void ray_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
#define MAX_TUPLE_SIZE 128
-static void ray_config(dev_link_t *link)
+static int ray_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
tuple_t tuple;
cisparse_t parse;
int last_fn = 0, last_ret = 0;
@@ -455,48 +423,45 @@ static void ray_config(dev_link_t *link)
/* This reads the card's CONFIG tuple to find its configuration regs */
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = buf;
tuple.TupleDataMax = MAX_TUPLE_SIZE;
tuple.TupleOffset = 0;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* Determine card type and firmware version */
buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0;
tuple.DesiredTuple = CISTPL_VERS_1;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = buf;
tuple.TupleDataMax = MAX_TUPLE_SIZE;
tuple.TupleOffset = 2;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
for (i=0; i<tuple.TupleDataLen - 4; i++)
if (buf[i] == 0) buf[i] = ' ';
printk(KERN_INFO "ray_cs Detected: %s\n",buf);
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Now allocate an interrupt line. Note that this does not
actually assign a handler to the interrupt.
*/
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
dev->irq = link->irq.AssignedIRQ;
/* This actually configures the PCMCIA socket -- setting up
the I/O windows and the interrupt mapping.
*/
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/*** Set up 32k window for shared memory (transmit and control) ************/
req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
req.Base = 0;
req.Size = 0x8000;
req.AccessSpeed = ray_mem_speed;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
mem.CardOffset = 0x0000; mem.Page = 0;
CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
local->sram = ioremap(req.Base,req.Size);
@@ -506,7 +471,7 @@ static void ray_config(dev_link_t *link)
req.Base = 0;
req.Size = 0x4000;
req.AccessSpeed = ray_mem_speed;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->rmem_handle));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->rmem_handle));
mem.CardOffset = 0x8000; mem.Page = 0;
CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem));
local->rmem = ioremap(req.Base,req.Size);
@@ -516,7 +481,7 @@ static void ray_config(dev_link_t *link)
req.Base = 0;
req.Size = 0x1000;
req.AccessSpeed = ray_mem_speed;
- CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->amem_handle));
+ CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->amem_handle));
mem.CardOffset = 0x0000; mem.Page = 0;
CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem));
local->amem = ioremap(req.Base,req.Size);
@@ -526,32 +491,32 @@ static void ray_config(dev_link_t *link)
DEBUG(3,"ray_config amem=%p\n",local->amem);
if (ray_init(dev) < 0) {
ray_release(link);
- return;
+ return -ENODEV;
}
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
i = register_netdev(dev);
if (i != 0) {
printk("ray_config register_netdev() failed\n");
ray_release(link);
- return;
+ return i;
}
strcpy(local->node.dev_name, dev->name);
- link->dev = &local->node;
+ link->dev_node = &local->node;
- link->state &= ~DEV_CONFIG_PENDING;
printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ",
dev->name, dev->irq);
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
ray_release(link);
+ return -ENODEV;
} /* ray_config */
static inline struct ccs __iomem *ccs_base(ray_dev_t *dev)
@@ -578,9 +543,9 @@ static int ray_init(struct net_device *dev)
UCHAR *p;
struct ccs __iomem *pccs;
ray_dev_t *local = (ray_dev_t *)dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
DEBUG(1, "ray_init(0x%p)\n", dev);
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(0,"ray_init - device not present\n");
return -1;
}
@@ -640,10 +605,10 @@ static int dl_startup_params(struct net_device *dev)
int ccsindex;
ray_dev_t *local = (ray_dev_t *)dev->priv;
struct ccs __iomem *pccs;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
DEBUG(1,"dl_startup_params entered\n");
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs dl_startup_params - device not present\n");
return -1;
}
@@ -747,9 +712,9 @@ static void verify_dl_startup(u_long data)
ray_dev_t *local = (ray_dev_t *)data;
struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs;
UCHAR status;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs verify_dl_startup - device not present\n");
return;
}
@@ -787,8 +752,8 @@ static void start_net(u_long data)
ray_dev_t *local = (ray_dev_t *)data;
struct ccs __iomem *pccs;
int ccsindex;
- dev_link_t *link = local->finder;
- if (!(link->state & DEV_PRESENT)) {
+ struct pcmcia_device *link = local->finder;
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs start_net - device not present\n");
return;
}
@@ -814,9 +779,9 @@ static void join_net(u_long data)
struct ccs __iomem *pccs;
int ccsindex;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs join_net - device not present\n");
return;
}
@@ -840,7 +805,7 @@ static void join_net(u_long data)
device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed.
=============================================================================*/
-static void ray_release(dev_link_t *link)
+static void ray_release(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
ray_dev_t *local = dev->priv;
@@ -849,56 +814,38 @@ static void ray_release(dev_link_t *link)
DEBUG(1, "ray_release(0x%p)\n", link);
del_timer(&local->timer);
- link->state &= ~DEV_CONFIG;
iounmap(local->sram);
iounmap(local->rmem);
iounmap(local->amem);
/* Do bother checking to see if these succeed or not */
- i = pcmcia_release_window(link->win);
- if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(link->win) ret = %x\n",i);
i = pcmcia_release_window(local->amem_handle);
if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i);
i = pcmcia_release_window(local->rmem_handle);
if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i);
- i = pcmcia_release_configuration(link->handle);
- if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseConfiguration ret = %x\n",i);
- i = pcmcia_release_irq(link->handle, &link->irq);
- if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i);
+ pcmcia_disable_device(link);
DEBUG(2,"ray_release ending\n");
}
-static int ray_suspend(struct pcmcia_device *p_dev)
+static int ray_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
-
- pcmcia_release_configuration(link->handle);
- }
-
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int ray_resume(struct pcmcia_device *p_dev)
+static int ray_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- ray_reset(dev);
- netif_device_attach(dev);
- }
- }
+ if (link->open) {
+ ray_reset(dev);
+ netif_device_attach(dev);
+ }
return 0;
}
@@ -910,10 +857,10 @@ int ray_dev_init(struct net_device *dev)
int i;
#endif /* RAY_IMMEDIATE_INIT */
ray_dev_t *local = dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
DEBUG(1,"ray_dev_init(dev=%p)\n",dev);
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_dev_init - device not present\n");
return -1;
}
@@ -944,10 +891,10 @@ int ray_dev_init(struct net_device *dev)
static int ray_dev_config(struct net_device *dev, struct ifmap *map)
{
ray_dev_t *local = dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
/* Dummy routine to satisfy device structure */
DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map);
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_dev_config - device not present\n");
return -1;
}
@@ -958,10 +905,10 @@ static int ray_dev_config(struct net_device *dev, struct ifmap *map)
static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
ray_dev_t *local = dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
short length = skb->len;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_dev_start_xmit - device not present\n");
return -1;
}
@@ -1570,7 +1517,7 @@ static int ray_commit(struct net_device *dev,
static iw_stats * ray_get_wireless_stats(struct net_device * dev)
{
ray_dev_t * local = (ray_dev_t *) dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
struct status __iomem *p = local->sram + STATUS_BASE;
if(local == (ray_dev_t *) NULL)
@@ -1588,7 +1535,7 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev)
}
#endif /* WIRELESS_SPY */
- if((link->state & DEV_PRESENT)) {
+ if(pcmcia_dev_present(link)) {
local->wstats.qual.noise = readb(&p->rxnoise);
local->wstats.qual.updated |= 4;
}
@@ -1657,18 +1604,14 @@ static const struct iw_handler_def ray_handler_def =
/*===========================================================================*/
static int ray_open(struct net_device *dev)
{
- dev_link_t *link;
ray_dev_t *local = (ray_dev_t *)dev->priv;
+ struct pcmcia_device *link;
+ link = local->finder;
DEBUG(1, "ray_open('%s')\n", dev->name);
- for (link = dev_list; link; link = link->next)
- if (link->priv == dev) break;
- if (!DEV_OK(link)) {
- return -ENODEV;
- }
-
- if (link->open == 0) local->num_multi = 0;
+ if (link->open == 0)
+ local->num_multi = 0;
link->open++;
/* If the card is not started, time to start it ! - Jean II */
@@ -1695,15 +1638,12 @@ static int ray_open(struct net_device *dev)
/*===========================================================================*/
static int ray_dev_close(struct net_device *dev)
{
- dev_link_t *link;
+ ray_dev_t *local = (ray_dev_t *)dev->priv;
+ struct pcmcia_device *link;
+ link = local->finder;
DEBUG(1, "ray_dev_close('%s')\n", dev->name);
- for (link = dev_list; link; link = link->next)
- if (link->priv == dev) break;
- if (link == NULL)
- return -ENODEV;
-
link->open--;
netif_stop_queue(dev);
@@ -1725,9 +1665,9 @@ static void ray_reset(struct net_device *dev) {
static int interrupt_ecf(ray_dev_t *local, int ccs)
{
int i = 50;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs interrupt_ecf - device not present\n");
return -1;
}
@@ -1752,9 +1692,9 @@ static int get_free_tx_ccs(ray_dev_t *local)
{
int i;
struct ccs __iomem *pccs = ccs_base(local);
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n");
return ECARDGONE;
}
@@ -1783,9 +1723,9 @@ static int get_free_ccs(ray_dev_t *local)
{
int i;
struct ccs __iomem *pccs = ccs_base(local);
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs get_free_ccs - device not present\n");
return ECARDGONE;
}
@@ -1858,9 +1798,9 @@ static int parse_addr(char *in_str, UCHAR *out)
static struct net_device_stats *ray_get_stats(struct net_device *dev)
{
ray_dev_t *local = (ray_dev_t *)dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
struct status __iomem *p = local->sram + STATUS_BASE;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs net_device_stats - device not present\n");
return &local->stats;
}
@@ -1888,12 +1828,12 @@ static struct net_device_stats *ray_get_stats(struct net_device *dev)
static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len)
{
ray_dev_t *local = (ray_dev_t *)dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
int ccsindex;
int i;
struct ccs __iomem *pccs;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_update_parm - device not present\n");
return;
}
@@ -1925,10 +1865,10 @@ static void ray_update_multi_list(struct net_device *dev, int all)
struct ccs __iomem *pccs;
int i = 0;
ray_dev_t *local = (ray_dev_t *)dev->priv;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
void __iomem *p = local->sram + HOST_TO_ECF_BASE;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_update_multi_list - device not present\n");
return;
}
@@ -2005,7 +1945,7 @@ static void set_multicast_list(struct net_device *dev)
static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct net_device *dev = (struct net_device *)dev_id;
- dev_link_t *link;
+ struct pcmcia_device *link;
ray_dev_t *local;
struct ccs __iomem *pccs;
struct rcs __iomem *prcs;
@@ -2020,8 +1960,8 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev);
local = (ray_dev_t *)dev->priv;
- link = (dev_link_t *)local->finder;
- if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) {
+ link = (struct pcmcia_device *)local->finder;
+ if (!pcmcia_dev_present(link)) {
DEBUG(2,"ray_cs interrupt from device not present or suspended.\n");
return IRQ_NONE;
}
@@ -2540,9 +2480,9 @@ static void release_frag_chain(ray_dev_t *local, struct rcs __iomem * prcs)
/*===========================================================================*/
static void authenticate(ray_dev_t *local)
{
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
DEBUG(0,"ray_cs Starting authentication.\n");
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs authenticate - device not present\n");
return;
}
@@ -2606,10 +2546,10 @@ static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs,
static void associate(ray_dev_t *local)
{
struct ccs __iomem *pccs;
- dev_link_t *link = local->finder;
+ struct pcmcia_device *link = local->finder;
struct net_device *dev = link->priv;
int ccsindex;
- if (!(link->state & DEV_PRESENT)) {
+ if (!(pcmcia_dev_present(link))) {
DEBUG(2,"ray_cs associate - device not present\n");
return;
}
@@ -2689,14 +2629,14 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len)
* eg ifconfig
*/
int i;
- dev_link_t *link;
+ struct pcmcia_device *link;
struct net_device *dev;
ray_dev_t *local;
UCHAR *p;
struct freq_hop_element *pfh;
UCHAR c[33];
- link = dev_list;
+ link = this_device;
if (!link)
return 0;
dev = (struct net_device *)link->priv;
@@ -2898,7 +2838,7 @@ static struct pcmcia_driver ray_driver = {
.drv = {
.name = "ray_cs",
},
- .probe = ray_attach,
+ .probe = ray_probe,
.remove = ray_detach,
.id_table = ray_ids,
.suspend = ray_suspend,
@@ -2940,7 +2880,6 @@ static void __exit exit_ray_cs(void)
#endif
pcmcia_unregister_driver(&ray_driver);
- BUG_ON(dev_list != NULL);
} /* exit_ray_cs */
module_init(init_ray_cs);
diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h
index 42660fe64bf..bd73ebf0334 100644
--- a/drivers/net/wireless/ray_cs.h
+++ b/drivers/net/wireless/ray_cs.h
@@ -31,7 +31,7 @@ typedef struct ray_dev_t {
void __iomem *sram; /* pointer to beginning of shared RAM */
void __iomem *amem; /* pointer to attribute mem window */
void __iomem *rmem; /* pointer to receive buffer window */
- dev_link_t *finder; /* pointer back to dev_link_t for card */
+ struct pcmcia_device *finder; /* pointer back to struct pcmcia_device for card */
struct timer_list timer;
long tx_ccs_lock;
long ccs_lock;
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 5fa6fbe35bb..f7b77ce54d7 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -63,7 +63,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket
/* PCMCIA specific device information (goes in the card field of
* struct orinoco_private */
struct orinoco_pccard {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
};
@@ -71,8 +71,8 @@ struct orinoco_pccard {
/* Function prototypes */
/********************************************************************/
-static void spectrum_cs_config(dev_link_t *link);
-static void spectrum_cs_release(dev_link_t *link);
+static int spectrum_cs_config(struct pcmcia_device *link);
+static void spectrum_cs_release(struct pcmcia_device *link);
/********************************************************************/
/* Firmware downloader */
@@ -238,14 +238,14 @@ spectrum_aux_open(hermes_t *hw)
* If IDLE is 1, stop the firmware, so that it can be safely rewritten.
*/
static int
-spectrum_reset(dev_link_t *link, int idle)
+spectrum_reset(struct pcmcia_device *link, int idle)
{
int last_ret, last_fn;
conf_reg_t reg;
u_int save_cor;
/* Doing it if hardware is gone is guaranteed crash */
- if (!(link->state & DEV_CONFIG))
+ if (pcmcia_dev_present(link))
return -ENODEV;
/* Save original COR value */
@@ -253,7 +253,7 @@ spectrum_reset(dev_link_t *link, int idle)
reg.Action = CS_READ;
reg.Offset = CISREG_COR;
CS_CHECK(AccessConfigurationRegister,
- pcmcia_access_configuration_register(link->handle, &reg));
+ pcmcia_access_configuration_register(link, &reg));
save_cor = reg.Value;
/* Soft-Reset card */
@@ -261,14 +261,14 @@ spectrum_reset(dev_link_t *link, int idle)
reg.Offset = CISREG_COR;
reg.Value = (save_cor | COR_SOFT_RESET);
CS_CHECK(AccessConfigurationRegister,
- pcmcia_access_configuration_register(link->handle, &reg));
+ pcmcia_access_configuration_register(link, &reg));
udelay(1000);
/* Read CCSR */
reg.Action = CS_READ;
reg.Offset = CISREG_CCSR;
CS_CHECK(AccessConfigurationRegister,
- pcmcia_access_configuration_register(link->handle, &reg));
+ pcmcia_access_configuration_register(link, &reg));
/*
* Start or stop the firmware. Memory width bit should be
@@ -278,7 +278,7 @@ spectrum_reset(dev_link_t *link, int idle)
reg.Offset = CISREG_CCSR;
reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16);
CS_CHECK(AccessConfigurationRegister,
- pcmcia_access_configuration_register(link->handle, &reg));
+ pcmcia_access_configuration_register(link, &reg));
udelay(1000);
/* Restore original COR configuration index */
@@ -286,12 +286,12 @@ spectrum_reset(dev_link_t *link, int idle)
reg.Offset = CISREG_COR;
reg.Value = (save_cor & ~COR_SOFT_RESET);
CS_CHECK(AccessConfigurationRegister,
- pcmcia_access_configuration_register(link->handle, &reg));
+ pcmcia_access_configuration_register(link, &reg));
udelay(1000);
return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
return -ENODEV;
}
@@ -441,7 +441,7 @@ spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block)
* care of the PDA - read it and then write it on top of the firmware.
*/
static int
-spectrum_dl_image(hermes_t *hw, dev_link_t *link,
+spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link,
const unsigned char *image)
{
int ret;
@@ -505,14 +505,13 @@ spectrum_dl_image(hermes_t *hw, dev_link_t *link,
* reset on the card, to make sure it's in a sane state.
*/
static int
-spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
+spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link)
{
int ret;
- client_handle_t handle = link->handle;
const struct firmware *fw_entry;
if (request_firmware(&fw_entry, primary_fw_name,
- &handle_to_dev(handle)) == 0) {
+ &handle_to_dev(link)) == 0) {
primsym = fw_entry->data;
} else {
printk(KERN_ERR PFX "Cannot find firmware: %s\n",
@@ -521,7 +520,7 @@ spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
}
if (request_firmware(&fw_entry, secondary_fw_name,
- &handle_to_dev(handle)) == 0) {
+ &handle_to_dev(link)) == 0) {
secsym = fw_entry->data;
} else {
printk(KERN_ERR PFX "Cannot find firmware: %s\n",
@@ -554,12 +553,12 @@ static int
spectrum_cs_hard_reset(struct orinoco_private *priv)
{
struct orinoco_pccard *card = priv->card;
- dev_link_t *link = &card->link;
+ struct pcmcia_device *link = card->p_dev;
int err;
if (!hermes_present(&priv->hw)) {
/* The firmware needs to be reloaded */
- if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) {
+ if (spectrum_dl_firmware(&priv->hw, link) != 0) {
printk(KERN_ERR PFX "Firmware download failed\n");
err = -ENODEV;
}
@@ -584,12 +583,11 @@ spectrum_cs_hard_reset(struct orinoco_private *priv)
* configure the card at this point -- we wait until we receive a card
* insertion event. */
static int
-spectrum_cs_attach(struct pcmcia_device *p_dev)
+spectrum_cs_probe(struct pcmcia_device *link)
{
struct net_device *dev;
struct orinoco_private *priv;
struct orinoco_pccard *card;
- dev_link_t *link;
dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
if (! dev)
@@ -598,7 +596,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev)
card = priv->card;
/* Link both structures together */
- link = &card->link;
+ card->p_dev = link;
link->priv = dev;
/* Interrupt setup */
@@ -615,13 +613,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev)
link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- spectrum_cs_config(link);
-
- return 0;
+ return spectrum_cs_config(link);
} /* spectrum_cs_attach */
/*
@@ -630,16 +622,14 @@ spectrum_cs_attach(struct pcmcia_device *p_dev)
* are freed. Otherwise, the structures will be freed when the device
* is released.
*/
-static void spectrum_cs_detach(struct pcmcia_device *p_dev)
+static void spectrum_cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- if (link->state & DEV_CONFIG)
- spectrum_cs_release(link);
+ spectrum_cs_release(link);
- DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
- if (link->dev) {
+ DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
+ if (link->dev_node) {
DEBUG(0, PFX "About to unregister net device %p\n",
dev);
unregister_netdev(dev);
@@ -653,11 +643,10 @@ static void spectrum_cs_detach(struct pcmcia_device *p_dev)
* device available to the system.
*/
-static void
-spectrum_cs_config(dev_link_t *link)
+static int
+spectrum_cs_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- client_handle_t handle = link->handle;
struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card;
hermes_t *hw = &priv->hw;
@@ -669,7 +658,7 @@ spectrum_cs_config(dev_link_t *link)
cisparse_t parse;
void __iomem *mem;
- CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
+ CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
/*
* This reads the card's CONFIG tuple to find its
@@ -680,19 +669,15 @@ spectrum_cs_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Look up the current Vcc */
CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
+ pcmcia_get_configuration_info(link, &conf));
/*
* In this loop, we scan the CIS for configuration table
@@ -709,13 +694,13 @@ spectrum_cs_config(dev_link_t *link)
* implementation-defined details.
*/
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
cistpl_cftable_entry_t dflt = { .index = 0 };
- if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
- || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
+ if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
+ || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
@@ -747,10 +732,10 @@ spectrum_cs_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
/* Do we need to allocate an interrupt? */
@@ -780,7 +765,7 @@ spectrum_cs_config(dev_link_t *link)
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
@@ -790,9 +775,8 @@ spectrum_cs_config(dev_link_t *link)
break;
next_entry:
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ pcmcia_disable_device(link);
+ last_ret = pcmcia_get_next_tuple(link, &tuple);
if (last_ret == CS_NO_MORE_ITEMS) {
printk(KERN_ERR PFX "GetNextTuple(): No matching "
"CIS configuration. Maybe you need the "
@@ -806,7 +790,7 @@ spectrum_cs_config(dev_link_t *link)
* a handler to the interrupt, unless the 'Handler' member of
* the irq structure is initialized.
*/
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/* We initialize the hermes structure before completing PCMCIA
* configuration just in case the interrupt handler gets
@@ -823,7 +807,7 @@ spectrum_cs_config(dev_link_t *link)
* card and host interface into "Memory and IO" mode.
*/
CS_CHECK(RequestConfiguration,
- pcmcia_request_configuration(link->handle, &link->conf));
+ pcmcia_request_configuration(link, &link->conf));
/* Ok, we have the configuration, prepare to register the netdev */
dev->base_addr = link->io.BasePort1;
@@ -836,7 +820,7 @@ spectrum_cs_config(dev_link_t *link)
goto failed;
}
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
/* Tell the stack we exist */
if (register_netdev(dev) != 0) {
printk(KERN_ERR PFX "register_netdev() failed\n");
@@ -844,20 +828,18 @@ spectrum_cs_config(dev_link_t *link)
}
/* At this point, the dev_node_t structure(s) needs to be
- * initialized and arranged in a linked list at link->dev. */
+ * initialized and arranged in a linked list at link->dev_node. */
strcpy(card->node.dev_name, dev->name);
- link->dev = &card->node; /* link->dev being non-NULL is also
+ link->dev_node = &card->node; /* link->dev_node being non-NULL is also
used to indicate that the
net_device has been registered */
- link->state &= ~DEV_CONFIG_PENDING;
/* Finally, report what we've done */
- printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
- dev->name, link->conf.ConfigIndex,
- link->conf.Vcc / 10, link->conf.Vcc % 10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
- link->conf.Vpp1 % 10);
+ printk(KERN_DEBUG "%s: index 0x%02x: ",
+ dev->name, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp / 10,
+ link->conf.Vpp % 10);
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
printk(", io 0x%04x-0x%04x", link->io.BasePort1,
@@ -867,13 +849,14 @@ spectrum_cs_config(dev_link_t *link)
link->io.BasePort2 + link->io.NumPorts2 - 1);
printk("\n");
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
spectrum_cs_release(link);
+ return -ENODEV;
} /* spectrum_cs_config */
/*
@@ -882,7 +865,7 @@ spectrum_cs_config(dev_link_t *link)
* still open, this will be postponed until it is closed.
*/
static void
-spectrum_cs_release(dev_link_t *link)
+spectrum_cs_release(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
@@ -894,64 +877,46 @@ spectrum_cs_release(dev_link_t *link)
priv->hw_unavailable++;
spin_unlock_irqrestore(&priv->lock, flags);
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
if (priv->hw.iobase)
ioport_unmap(priv->hw.iobase);
} /* spectrum_cs_release */
static int
-spectrum_cs_suspend(struct pcmcia_device *p_dev)
+spectrum_cs_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
unsigned long flags;
int err = 0;
- link->state |= DEV_SUSPEND;
/* Mark the device as stopped, to block IO until later */
- if (link->state & DEV_CONFIG) {
- spin_lock_irqsave(&priv->lock, flags);
-
- err = __orinoco_down(dev);
- if (err)
- printk(KERN_WARNING "%s: Error %d downing interface\n",
- dev->name, err);
+ spin_lock_irqsave(&priv->lock, flags);
- netif_device_detach(dev);
- priv->hw_unavailable++;
+ err = __orinoco_down(dev);
+ if (err)
+ printk(KERN_WARNING "%s: Error %d downing interface\n",
+ dev->name, err);
- spin_unlock_irqrestore(&priv->lock, flags);
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
- pcmcia_release_configuration(link->handle);
- }
+ spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
static int
-spectrum_cs_resume(struct pcmcia_device *p_dev)
+spectrum_cs_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- /* FIXME: should we double check that this is
- * the same card as we had before */
- pcmcia_request_configuration(link->handle, &link->conf);
- netif_device_attach(dev);
- priv->hw_unavailable--;
- schedule_work(&priv->reset_work);
- }
+ netif_device_attach(dev);
+ priv->hw_unavailable--;
+ schedule_work(&priv->reset_work);
+
return 0;
}
@@ -979,7 +944,7 @@ static struct pcmcia_driver orinoco_driver = {
.drv = {
.name = DRIVER_NAME,
},
- .probe = spectrum_cs_attach,
+ .probe = spectrum_cs_probe,
.remove = spectrum_cs_detach,
.suspend = spectrum_cs_suspend,
.resume = spectrum_cs_resume,
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index ff192e96268..dade4b90357 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -4306,7 +4306,7 @@ out:
* Insertion of the module
* I'm now quite proud of the multi-device support.
*/
-int init_module(void)
+int __init init_module(void)
{
int ret = -EIO; /* Return error if no cards found */
int i;
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 98122f3a4bc..f7724eb2fa7 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -1005,7 +1005,7 @@ static inline void
wv_82593_reconfig(struct net_device * dev)
{
net_local * lp = netdev_priv(dev);
- dev_link_t * link = lp->link;
+ struct pcmcia_device * link = lp->link;
unsigned long flags;
/* Arm the flag, will be cleard in wv_82593_config() */
@@ -3744,16 +3744,16 @@ wv_pcmcia_reset(struct net_device * dev)
{
int i;
conf_reg_t reg = { 0, CS_READ, CISREG_COR, 0 };
- dev_link_t * link = ((net_local *)netdev_priv(dev))->link;
+ struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link;
#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name);
#endif
- i = pcmcia_access_configuration_register(link->handle, &reg);
+ i = pcmcia_access_configuration_register(link, &reg);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, AccessConfigurationRegister, i);
+ cs_error(link, AccessConfigurationRegister, i);
return FALSE;
}
@@ -3764,19 +3764,19 @@ wv_pcmcia_reset(struct net_device * dev)
reg.Action = CS_WRITE;
reg.Value = reg.Value | COR_SW_RESET;
- i = pcmcia_access_configuration_register(link->handle, &reg);
+ i = pcmcia_access_configuration_register(link, &reg);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, AccessConfigurationRegister, i);
+ cs_error(link, AccessConfigurationRegister, i);
return FALSE;
}
reg.Action = CS_WRITE;
reg.Value = COR_LEVEL_IRQ | COR_CONFIG;
- i = pcmcia_access_configuration_register(link->handle, &reg);
+ i = pcmcia_access_configuration_register(link, &reg);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, AccessConfigurationRegister, i);
+ cs_error(link, AccessConfigurationRegister, i);
return FALSE;
}
@@ -3940,9 +3940,8 @@ wv_hw_reset(struct net_device * dev)
* (called by wavelan_event())
*/
static inline int
-wv_pcmcia_config(dev_link_t * link)
+wv_pcmcia_config(struct pcmcia_device * link)
{
- client_handle_t handle = link->handle;
tuple_t tuple;
cisparse_t parse;
struct net_device * dev = (struct net_device *) link->priv;
@@ -3965,16 +3964,16 @@ wv_pcmcia_config(dev_link_t * link)
{
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- i = pcmcia_get_first_tuple(handle, &tuple);
+ i = pcmcia_get_first_tuple(link, &tuple);
if(i != CS_SUCCESS)
break;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- i = pcmcia_get_tuple_data(handle, &tuple);
+ i = pcmcia_get_tuple_data(link, &tuple);
if(i != CS_SUCCESS)
break;
- i = pcmcia_parse_tuple(handle, &tuple, &parse);
+ i = pcmcia_parse_tuple(link, &tuple, &parse);
if(i != CS_SUCCESS)
break;
link->conf.ConfigBase = parse.config.base;
@@ -3983,19 +3982,16 @@ wv_pcmcia_config(dev_link_t * link)
while(0);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, ParseTuple, i);
- link->state &= ~DEV_CONFIG_PENDING;
+ cs_error(link, ParseTuple, i);
return FALSE;
}
-
- /* Configure card */
- link->state |= DEV_CONFIG;
+
do
{
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
break;
}
@@ -4003,10 +3999,10 @@ wv_pcmcia_config(dev_link_t * link)
* Now allocate an interrupt line. Note that this does not
* actually assign a handler to the interrupt.
*/
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
break;
}
@@ -4015,15 +4011,15 @@ wv_pcmcia_config(dev_link_t * link)
* the I/O windows and the interrupt mapping.
*/
link->conf.ConfigIndex = 1;
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
break;
}
/*
- * Allocate a small memory window. Note that the dev_link_t
+ * Allocate a small memory window. Note that the struct pcmcia_device
* structure provides space for one window handle -- if your
* device needs several windows, you'll need to keep track of
* the handles in your private data structure, link->priv.
@@ -4031,10 +4027,10 @@ wv_pcmcia_config(dev_link_t * link)
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
req.Base = req.Size = 0;
req.AccessSpeed = mem_speed;
- i = pcmcia_request_window(&link->handle, &req, &link->win);
+ i = pcmcia_request_window(&link, &req, &link->win);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, RequestWindow, i);
+ cs_error(link, RequestWindow, i);
break;
}
@@ -4046,7 +4042,7 @@ wv_pcmcia_config(dev_link_t * link)
i = pcmcia_map_mem_page(link->win, &mem);
if(i != CS_SUCCESS)
{
- cs_error(link->handle, MapMemPage, i);
+ cs_error(link, MapMemPage, i);
break;
}
@@ -4060,7 +4056,7 @@ wv_pcmcia_config(dev_link_t * link)
lp->mem, dev->irq, (u_int) dev->base_addr);
#endif
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
i = register_netdev(dev);
if(i != 0)
{
@@ -4072,7 +4068,6 @@ wv_pcmcia_config(dev_link_t * link)
}
while(0); /* Humm... Disguised goto !!! */
- link->state &= ~DEV_CONFIG_PENDING;
/* If any step failed, release any partially configured state */
if(i != 0)
{
@@ -4081,7 +4076,7 @@ wv_pcmcia_config(dev_link_t * link)
}
strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name);
- link->dev = &((net_local *) netdev_priv(dev))->node;
+ link->dev_node = &((net_local *) netdev_priv(dev))->node;
#ifdef DEBUG_CONFIG_TRACE
printk(KERN_DEBUG "<-wv_pcmcia_config()\n");
@@ -4096,26 +4091,20 @@ wv_pcmcia_config(dev_link_t * link)
* still open, this will be postponed until it is closed.
*/
static void
-wv_pcmcia_release(dev_link_t *link)
+wv_pcmcia_release(struct pcmcia_device *link)
{
- struct net_device * dev = (struct net_device *) link->priv;
- net_local * lp = netdev_priv(dev);
+ struct net_device * dev = (struct net_device *) link->priv;
+ net_local * lp = netdev_priv(dev);
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link);
+ printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link);
#endif
- /* Don't bother checking to see if these succeed or not */
- iounmap(lp->mem);
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ iounmap(lp->mem);
+ pcmcia_disable_device(link);
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name);
+ printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name);
#endif
}
@@ -4479,7 +4468,7 @@ static int
wavelan_open(struct net_device * dev)
{
net_local * lp = netdev_priv(dev);
- dev_link_t * link = lp->link;
+ struct pcmcia_device * link = lp->link;
kio_addr_t base = dev->base_addr;
#ifdef DEBUG_CALLBACK_TRACE
@@ -4533,7 +4522,7 @@ wavelan_open(struct net_device * dev)
static int
wavelan_close(struct net_device * dev)
{
- dev_link_t * link = ((net_local *)netdev_priv(dev))->link;
+ struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link;
kio_addr_t base = dev->base_addr;
#ifdef DEBUG_CALLBACK_TRACE
@@ -4587,45 +4576,36 @@ wavelan_close(struct net_device * dev)
* card insertion event.
*/
static int
-wavelan_attach(struct pcmcia_device *p_dev)
+wavelan_probe(struct pcmcia_device *p_dev)
{
- dev_link_t * link; /* Info for cardmgr */
struct net_device * dev; /* Interface generic data */
net_local * lp; /* Interface specific data */
+ int ret;
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "-> wavelan_attach()\n");
#endif
- /* Initialize the dev_link_t structure */
- link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link) return -ENOMEM;
-
/* The io structure describes IO port mapping */
- link->io.NumPorts1 = 8;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = 3;
+ p_dev->io.NumPorts1 = 8;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = 3;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.Handler = wavelan_interrupt;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->irq.Handler = wavelan_interrupt;
/* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
- /* Chain drivers */
- link->next = NULL;
+ p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
/* Allocate the generic data structure */
dev = alloc_etherdev(sizeof(net_local));
- if (!dev) {
- kfree(link);
+ if (!dev)
return -ENOMEM;
- }
- link->priv = link->irq.Instance = dev;
+
+ p_dev->priv = p_dev->irq.Instance = dev;
lp = netdev_priv(dev);
@@ -4642,7 +4622,6 @@ wavelan_attach(struct pcmcia_device *p_dev)
spin_lock_init(&lp->spinlock);
/* back links */
- lp->link = link;
lp->dev = dev;
/* wavelan NET3 callbacks */
@@ -4668,15 +4647,18 @@ wavelan_attach(struct pcmcia_device *p_dev)
/* Other specific data */
dev->mtu = WAVELAN_MTU;
- link->handle = p_dev;
- p_dev->instance = link;
+ ret = wv_pcmcia_config(p_dev);
+ if (ret)
+ return ret;
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- if(wv_pcmcia_config(link) &&
- wv_hw_config(dev))
- wv_init_info(dev);
- else
+ ret = wv_hw_config(dev);
+ if (ret) {
dev->irq = 0;
+ pcmcia_disable_device(p_dev);
+ return ret;
+ }
+
+ wv_init_info(dev);
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "<- wavelan_attach()\n");
@@ -4693,25 +4675,14 @@ wavelan_attach(struct pcmcia_device *p_dev)
* is released.
*/
static void
-wavelan_detach(struct pcmcia_device *p_dev)
+wavelan_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link);
#endif
- /*
- * If the device is currently configured and active, we won't
- * actually delete it yet. Instead, it is marked so that when the
- * release() function is called, that will trigger a proper
- * detach().
- */
- if(link->state & DEV_CONFIG)
- {
- /* Some others haven't done their job : give them another chance */
- wv_pcmcia_release(link);
- }
+ /* Some others haven't done their job : give them another chance */
+ wv_pcmcia_release(link);
/* Free pieces */
if(link->priv)
@@ -4720,23 +4691,21 @@ wavelan_detach(struct pcmcia_device *p_dev)
/* Remove ourselves from the kernel list of ethernet devices */
/* Warning : can't be called from interrupt, timer or wavelan_close() */
- if (link->dev)
+ if (link->dev_node)
unregister_netdev(dev);
- link->dev = NULL;
+ link->dev_node = NULL;
((net_local *)netdev_priv(dev))->link = NULL;
((net_local *)netdev_priv(dev))->dev = NULL;
free_netdev(dev);
}
- kfree(link);
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "<- wavelan_detach()\n");
#endif
}
-static int wavelan_suspend(struct pcmcia_device *p_dev)
+static int wavelan_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device * dev = (struct net_device *) link->priv;
/* NB: wavelan_close will be called, but too late, so we are
@@ -4748,36 +4717,22 @@ static int wavelan_suspend(struct pcmcia_device *p_dev)
/* Stop receiving new messages and wait end of transmission */
wv_ru_stop(dev);
+ if (link->open)
+ netif_device_detach(dev);
+
/* Power down the module */
hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT));
- /* The card is now suspended */
- link->state |= DEV_SUSPEND;
-
- if(link->state & DEV_CONFIG)
- {
- if(link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
-
return 0;
}
-static int wavelan_resume(struct pcmcia_device *p_dev)
+static int wavelan_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device * dev = (struct net_device *) link->priv;
- link->state &= ~DEV_SUSPEND;
- if(link->state & DEV_CONFIG)
- {
- pcmcia_request_configuration(link->handle, &link->conf);
- if(link->open) /* If RESET -> True, If RESUME -> False ? */
- {
- wv_hw_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ wv_hw_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -4798,7 +4753,7 @@ static struct pcmcia_driver wavelan_driver = {
.drv = {
.name = "wavelan_cs",
},
- .probe = wavelan_attach,
+ .probe = wavelan_probe,
.remove = wavelan_detach,
.id_table = wavelan_ids,
.suspend = wavelan_suspend,
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 451f6271dcb..c65fe7a391e 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -602,7 +602,7 @@ struct net_local
dev_node_t node; /* ???? What is this stuff ???? */
struct net_device * dev; /* Reverse link... */
spinlock_t spinlock; /* Serialize access to the hardware (SMP) */
- dev_link_t * link; /* pcmcia structure */
+ struct pcmcia_device * link; /* pcmcia structure */
en_stats stats; /* Ethernet interface statistics */
int nresets; /* Number of hw resets */
u_char configured; /* If it is configured */
@@ -733,9 +733,9 @@ static int
static inline void
wv_hw_reset(struct net_device *); /* Same, + start receiver unit */
static inline int
- wv_pcmcia_config(dev_link_t *); /* Configure the pcmcia interface */
+ wv_pcmcia_config(struct pcmcia_device *); /* Configure the pcmcia interface */
static void
- wv_pcmcia_release(dev_link_t *);/* Remove a device */
+ wv_pcmcia_release(struct pcmcia_device *);/* Remove a device */
/* ---------------------- INTERRUPT HANDLING ---------------------- */
static irqreturn_t
wavelan_interrupt(int, /* Interrupt handler */
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h
index 4303c50c2ab..65ceb088f70 100644
--- a/drivers/net/wireless/wl3501.h
+++ b/drivers/net/wireless/wl3501.h
@@ -611,5 +611,6 @@ struct wl3501_card {
struct iw_spy_data spy_data;
struct iw_public_data wireless_data;
struct dev_node_t node;
+ struct pcmcia_device *p_dev;
};
#endif
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 48e10b0c7e7..e52a650f673 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -103,8 +103,8 @@ module_param(pc_debug, int, 0);
* release a socket, in response to card insertion and ejection events. They
* are invoked from the wl24 event handler.
*/
-static void wl3501_config(dev_link_t *link);
-static void wl3501_release(dev_link_t *link);
+static int wl3501_config(struct pcmcia_device *link);
+static void wl3501_release(struct pcmcia_device *link);
/*
* The dev_info variable is the "key" that is used to match up this
@@ -226,17 +226,6 @@ static void iw_copy_mgmt_info_element(struct iw_mgmt_info_element *to,
iw_set_mgmt_info_element(from->id, to, from->data, from->len);
}
-/*
- * A linked list of "instances" of the wl24 device. Each actual PCMCIA card
- * corresponds to one device instance, and is described by one dev_link_t
- * structure (defined in ds.h).
- *
- * You may not want to use a linked list for this -- for example, the memory
- * card driver uses an array of dev_link_t pointers, where minor device numbers
- * are used to derive the corresponding array index.
- */
-static dev_link_t *wl3501_dev_list;
-
static inline void wl3501_switch_page(struct wl3501_card *this, u8 page)
{
wl3501_outb(page, this->base_addr + WL3501_NIC_BSS);
@@ -1281,15 +1270,10 @@ static int wl3501_close(struct net_device *dev)
struct wl3501_card *this = dev->priv;
int rc = -ENODEV;
unsigned long flags;
- dev_link_t *link;
+ struct pcmcia_device *link;
+ link = this->p_dev;
spin_lock_irqsave(&this->lock, flags);
- /* Check if the device is in wl3501_dev_list */
- for (link = wl3501_dev_list; link; link = link->next)
- if (link->priv == dev)
- break;
- if (!link)
- goto out;
link->open--;
/* Stop wl3501_hard_start_xmit() from now on */
@@ -1301,7 +1285,6 @@ static int wl3501_close(struct net_device *dev)
rc = 0;
printk(KERN_INFO "%s: WL3501 closed\n", dev->name);
-out:
spin_unlock_irqrestore(&this->lock, flags);
return rc;
}
@@ -1400,14 +1383,11 @@ static int wl3501_open(struct net_device *dev)
int rc = -ENODEV;
struct wl3501_card *this = dev->priv;
unsigned long flags;
- dev_link_t *link;
+ struct pcmcia_device *link;
+ link = this->p_dev;
spin_lock_irqsave(&this->lock, flags);
- /* Check if the device is in wl3501_dev_list */
- for (link = wl3501_dev_list; link; link = link->next)
- if (link->priv == dev)
- break;
- if (!DEV_OK(link))
+ if (!pcmcia_dev_present(link))
goto out;
netif_device_attach(dev);
link->open++;
@@ -1497,38 +1477,23 @@ static struct ethtool_ops ops = {
* Services. If it has been released, all local data structures are freed.
* Otherwise, the structures will be freed when the device is released.
*/
-static void wl3501_detach(struct pcmcia_device *p_dev)
+static void wl3501_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
- dev_link_t **linkp;
struct net_device *dev = link->priv;
- /* Locate device structure */
- for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
- if (!*linkp)
- goto out;
-
/* If the device is currently configured and active, we won't actually
* delete it yet. Instead, it is marked so that when the release()
* function is called, that will trigger a proper detach(). */
- if (link->state & DEV_CONFIG) {
- while (link->open > 0)
- wl3501_close(dev);
-
- netif_device_detach(dev);
- wl3501_release(link);
- }
+ while (link->open > 0)
+ wl3501_close(dev);
- /* Unlink device structure, free pieces */
- *linkp = link->next;
+ netif_device_detach(dev);
+ wl3501_release(link);
if (link->priv)
free_netdev(link->priv);
- kfree(link);
-out:
+
return;
}
@@ -1953,33 +1918,26 @@ static const struct iw_handler_def wl3501_handler_def = {
* The dev_link structure is initialized, but we don't actually configure the
* card at this point -- we wait until we receive a card insertion event.
*/
-static int wl3501_attach(struct pcmcia_device *p_dev)
+static int wl3501_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
struct net_device *dev;
struct wl3501_card *this;
- /* Initialize the dev_link_t structure */
- link = kzalloc(sizeof(*link), GFP_KERNEL);
- if (!link)
- return -ENOMEM;
-
/* The io structure describes IO port mapping */
- link->io.NumPorts1 = 16;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = 5;
+ p_dev->io.NumPorts1 = 16;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = 5;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.Handler = wl3501_interrupt;
+ p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ p_dev->irq.Handler = wl3501_interrupt;
/* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
+ p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->conf.ConfigIndex = 1;
+ p_dev->conf.Present = PRESENT_OPTION;
dev = alloc_etherdev(sizeof(struct wl3501_card));
if (!dev)
@@ -1992,22 +1950,15 @@ static int wl3501_attach(struct pcmcia_device *p_dev)
dev->get_stats = wl3501_get_stats;
this = dev->priv;
this->wireless_data.spy_data = &this->spy_data;
+ this->p_dev = p_dev;
dev->wireless_data = &this->wireless_data;
dev->wireless_handlers = (struct iw_handler_def *)&wl3501_handler_def;
SET_ETHTOOL_OPS(dev, &ops);
netif_stop_queue(dev);
- link->priv = link->irq.Instance = dev;
-
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- wl3501_config(link);
+ p_dev->priv = p_dev->irq.Instance = dev;
- return 0;
+ return wl3501_config(p_dev);
out_link:
- kfree(link);
- link = NULL;
return -ENOMEM;
}
@@ -2022,11 +1973,10 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
* received, to configure the PCMCIA socket, and to make the ethernet device
* available to the system.
*/
-static void wl3501_config(dev_link_t *link)
+static int wl3501_config(struct pcmcia_device *link)
{
tuple_t tuple;
cisparse_t parse;
- client_handle_t handle = link->handle;
struct net_device *dev = link->priv;
int i = 0, j, last_fn, last_ret;
unsigned char bf[64];
@@ -2035,18 +1985,15 @@ static void wl3501_config(dev_link_t *link)
/* This reads the card's CONFIG tuple to find its config registers. */
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = bf;
tuple.TupleDataMax = sizeof(bf);
tuple.TupleOffset = 0;
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Try allocating IO ports. This tries a few fixed addresses. If you
* want, you can also read the card's config table to pick addresses --
* see the serial driver for an example. */
@@ -2056,28 +2003,28 @@ static void wl3501_config(dev_link_t *link)
* 0x200-0x2ff, and so on, because this seems safer */
link->io.BasePort1 = j;
link->io.BasePort2 = link->io.BasePort1 + 0x10;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
goto failed;
}
/* Now allocate an interrupt line. Note that this does not actually
* assign a handler to the interrupt. */
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/* This actually configures the PCMCIA socket -- setting up the I/O
* windows and the interrupt mapping. */
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ SET_NETDEV_DEV(dev, &handle_to_dev(link));
if (register_netdev(dev)) {
printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n");
goto failed;
@@ -2088,10 +2035,9 @@ static void wl3501_config(dev_link_t *link)
this = dev->priv;
/*
* At this point, the dev_node_t structure(s) should be initialized and
- * arranged in a linked list at link->dev.
+ * arranged in a linked list at link->dev_node.
*/
- link->dev = &this->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &this->node;
this->base_addr = dev->base_addr;
@@ -2127,13 +2073,13 @@ static void wl3501_config(dev_link_t *link)
spin_lock_init(&this->lock);
init_waitqueue_head(&this->wait);
netif_start_queue(dev);
- goto out;
+ return 0;
+
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
wl3501_release(link);
-out:
- return;
+ return -ENODEV;
}
/**
@@ -2144,52 +2090,36 @@ out:
* and release the PCMCIA configuration. If the device is still open, this
* will be postponed until it is closed.
*/
-static void wl3501_release(dev_link_t *link)
+static void wl3501_release(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
/* Unlink the device chain */
- if (link->dev) {
+ if (link->dev_node)
unregister_netdev(dev);
- link->dev = NULL;
- }
- /* Don't bother checking to see if these succeed or not */
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static int wl3501_suspend(struct pcmcia_device *p_dev)
+static int wl3501_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- link->state |= DEV_SUSPEND;
-
wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
+ if (link->open)
+ netif_device_detach(dev);
return 0;
}
-static int wl3501_resume(struct pcmcia_device *p_dev)
+static int wl3501_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- wl3501_reset(dev);
- netif_device_attach(dev);
- }
+ if (link->open) {
+ wl3501_reset(dev);
+ netif_device_attach(dev);
}
return 0;
@@ -2207,7 +2137,7 @@ static struct pcmcia_driver wl3501_driver = {
.drv = {
.name = "wl3501_cs",
},
- .probe = wl3501_attach,
+ .probe = wl3501_probe,
.remove = wl3501_detach,
.id_table = wl3501_ids,
.suspend = wl3501_suspend,
@@ -2221,9 +2151,7 @@ static int __init wl3501_init_module(void)
static void __exit wl3501_exit_module(void)
{
- dprintk(0, ": unloading");
pcmcia_unregister_driver(&wl3501_driver);
- BUG_ON(wl3501_dev_list != NULL);
}
module_init(wl3501_init_module);
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 75d56bfef0e..fd0f43b7db5 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -1441,8 +1441,7 @@ static void __devexit yellowfin_remove_one (struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct yellowfin_private *np;
- if (!dev)
- BUG();
+ BUG_ON(!dev);
np = netdev_priv(dev);
pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status,
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index 330d3869b41..fc4bc9b94c7 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -217,11 +217,10 @@ static void oprofile_end_trace(struct oprofile_cpu_buffer * cpu_buf)
cpu_buf->tracing = 0;
}
-void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
+void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
+ unsigned long event, int is_kernel)
{
struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
- unsigned long pc = profile_pc(regs);
- int is_kernel = !user_mode(regs);
if (!backtrace_depth) {
log_sample(cpu_buf, pc, is_kernel, event);
@@ -238,6 +237,14 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
oprofile_end_trace(cpu_buf);
}
+void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
+{
+ int is_kernel = !user_mode(regs);
+ unsigned long pc = profile_pc(regs);
+
+ oprofile_add_ext_sample(pc, regs, event, is_kernel);
+}
+
void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
{
struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c
index e94b1e4a2a8..f0acb661c25 100644
--- a/drivers/oprofile/oprofile_stats.c
+++ b/drivers/oprofile/oprofile_stats.c
@@ -22,7 +22,7 @@ void oprofile_reset_stats(void)
struct oprofile_cpu_buffer * cpu_buf;
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
cpu_buf = &cpu_buffer[i];
cpu_buf->sample_received = 0;
cpu_buf->sample_lost_overflow = 0;
@@ -46,7 +46,7 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root)
if (!dir)
return;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
cpu_buf = &cpu_buffer[i];
snprintf(buf, 10, "cpu%d", i);
cpudir = oprofilefs_mkdir(sb, dir, buf);
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index d6bae699749..b62da9b0cbf 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -130,7 +130,7 @@ static struct file_operations ulong_ro_fops = {
static struct dentry * __oprofilefs_create_file(struct super_block * sb,
- struct dentry * root, char const * name, struct file_operations * fops,
+ struct dentry * root, char const * name, const struct file_operations * fops,
int perm)
{
struct dentry * dentry;
@@ -203,7 +203,7 @@ int oprofilefs_create_ro_atomic(struct super_block * sb, struct dentry * root,
int oprofilefs_create_file(struct super_block * sb, struct dentry * root,
- char const * name, struct file_operations * fops)
+ char const * name, const struct file_operations * fops)
{
if (!__oprofilefs_create_file(sb, root, name, fops, 0644))
return -EFAULT;
@@ -212,7 +212,7 @@ int oprofilefs_create_file(struct super_block * sb, struct dentry * root,
int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root,
- char const * name, struct file_operations * fops, int perm)
+ char const * name, const struct file_operations * fops, int perm)
{
if (!__oprofilefs_create_file(sb, root, name, fops, perm))
return -EFAULT;
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 93f8a8fa889..a5d826237b2 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -1560,7 +1560,7 @@ static int ccio_probe(struct parisc_device *dev)
*ioc_p = ioc;
ioc->hw_path = dev->hw_path;
- ioc->ioc_regs = ioremap(dev->hpa.start, 4096);
+ ioc->ioc_regs = ioremap_nocache(dev->hpa.start, 4096);
ccio_ioc_init(ioc);
ccio_init_resources(ioc);
hppa_dma_ops = &ccio_ops;
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 3d1a7f98c67..6e8ed0c81a6 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -5,6 +5,7 @@
** (c) Copyright 1999 SuSE GmbH
** (c) Copyright 1999,2000 Hewlett-Packard Company
** (c) Copyright 2000 Grant Grundler
+** (c) Copyright 2006 Helge Deller
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -785,7 +786,7 @@ dino_bridge_init(struct dino_device *dino_dev, const char *name)
if((io_addr & (1 << i)) == 0)
continue;
- start = (unsigned long)(signed int)(0xf0000000 | (i << 23));
+ start = F_EXTEND(0xf0000000UL) | (i << 23);
end = start + 8 * 1024 * 1024 - 1;
DBG("DINO RANGE %d is at 0x%lx-0x%lx\n", count,
@@ -996,7 +997,7 @@ static int __init dino_probe(struct parisc_device *dev)
}
dino_dev->hba.dev = dev;
- dino_dev->hba.base_addr = ioremap(hpa, 4096);
+ dino_dev->hba.base_addr = ioremap_nocache(hpa, 4096);
dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */
spin_lock_init(&dino_dev->dinosaur_pen);
dino_dev->hba.iommu = ccio_get_iommu(dev);
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 3d94d86c1c9..9d3bd15bf53 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -366,7 +366,7 @@ static int __devinit eisa_probe(struct parisc_device *dev)
eisa_dev.eeprom_addr = MIRAGE_EEPROM_BASE_ADDR;
}
}
- eisa_eeprom_addr = ioremap(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH);
+ eisa_eeprom_addr = ioremap_nocache(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH);
result = eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space,
&eisa_dev.hba.lmmio_space);
init_eisa_pic();
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 8d7a36392eb..7a458d5bc75 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -879,7 +879,7 @@ void *iosapic_register(unsigned long hpa)
return NULL;
}
- isi->addr = ioremap(hpa, 4096);
+ isi->addr = ioremap_nocache(hpa, 4096);
isi->isi_hpa = hpa;
isi->isi_version = iosapic_rd_version(isi);
isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index e8a2a4a852f..3fe4a77fa16 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1213,7 +1213,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
** Postable I/O port space is per PCI host adapter.
** base of 64MB PIOP region
*/
- lba_dev->iop_base = ioremap(p->start, 64 * 1024 * 1024);
+ lba_dev->iop_base = ioremap_nocache(p->start, 64 * 1024 * 1024);
sprintf(lba_dev->hba.io_name, "PCI%02lx Ports",
lba_dev->hba.bus_num.start);
@@ -1525,7 +1525,7 @@ lba_driver_probe(struct parisc_device *dev)
u32 func_class;
void *tmp_obj;
char *version;
- void __iomem *addr = ioremap(dev->hpa.start, 4096);
+ void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096);
/* Read HW Rev First */
func_class = READ_REG32(addr + LBA_FCLASS);
@@ -1619,7 +1619,7 @@ lba_driver_probe(struct parisc_device *dev)
} else {
if (!astro_iop_base) {
/* Sprockets PDC uses NPIOP region */
- astro_iop_base = ioremap(LBA_PORT_BASE, 64 * 1024);
+ astro_iop_base = ioremap_nocache(LBA_PORT_BASE, 64 * 1024);
pci_port = &lba_astro_port_ops;
}
@@ -1700,7 +1700,7 @@ void __init lba_init(void)
*/
void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask)
{
- void __iomem * base_addr = ioremap(lba->hpa.start, 4096);
+ void __iomem * base_addr = ioremap_nocache(lba->hpa.start, 4096);
imask <<= 2; /* adjust for hints - 2 more bits */
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 3627a2d7f79..298f2ddb2c1 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -499,11 +499,16 @@ static int led_halt(struct notifier_block *, unsigned long, void *);
static struct notifier_block led_notifier = {
.notifier_call = led_halt,
};
+static int notifier_disabled = 0;
static int led_halt(struct notifier_block *nb, unsigned long event, void *buf)
{
char *txt;
-
+
+ if (notifier_disabled)
+ return NOTIFY_OK;
+
+ notifier_disabled = 1;
switch (event) {
case SYS_RESTART: txt = "SYSTEM RESTART";
break;
@@ -527,7 +532,6 @@ static int led_halt(struct notifier_block *nb, unsigned long event, void *buf)
if (led_func_ptr)
led_func_ptr(0xff); /* turn all LEDs ON */
- unregister_reboot_notifier(&led_notifier);
return NOTIFY_OK;
}
@@ -758,6 +762,12 @@ not_found:
return 1;
}
+static void __exit led_exit(void)
+{
+ unregister_reboot_notifier(&led_notifier);
+ return;
+}
+
#ifdef CONFIG_PROC_FS
module_init(led_create_procfs)
#endif
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index a28e17898fb..bbeabe3fc4c 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -4,9 +4,8 @@
* Copyright (C) 2005-2006 Thibaut VARENE <varenet@parisc-linux.org>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -536,7 +535,7 @@ pdcs_auto_read(struct subsystem *entry, char *buf, int knob)
{
char *out = buf;
struct pdcspath_entry *pathentry;
-
+
if (!entry || !buf)
return -EINVAL;
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index 54b2b7f20b9..0bcab83b408 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -251,7 +251,8 @@ static int __init power_init(void)
}
/* Register a call for panic conditions. */
- notifier_chain_register(&panic_notifier_list, &parisc_panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &parisc_panic_block);
tasklet_enable(&power_tasklet);
@@ -264,7 +265,8 @@ static void __exit power_exit(void)
return;
tasklet_disable(&power_tasklet);
- notifier_chain_unregister(&panic_notifier_list, &parisc_panic_block);
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &parisc_panic_block);
power_tasklet.func = NULL;
pdc_soft_power_button(0);
}
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 0821747e44c..278f325021e 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -178,6 +178,11 @@ extern struct proc_dir_entry * proc_mckinley_root;
#define ROPE6_CTL 0x230
#define ROPE7_CTL 0x238
+#define IOC_ROPE0_CFG 0x500 /* pluto only */
+#define IOC_ROPE_AO 0x10 /* Allow "Relaxed Ordering" */
+
+
+
#define HF_ENABLE 0x40
@@ -1642,9 +1647,9 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
**
**************************************************************************/
-static void __iomem *ioc_remap(struct sba_device *sba_dev, int offset)
+static void __iomem *ioc_remap(struct sba_device *sba_dev, unsigned int offset)
{
- return ioremap(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE);
+ return ioremap_nocache(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE);
}
static void sba_hw_init(struct sba_device *sba_dev)
@@ -1759,19 +1764,33 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
sba_dev->num_ioc = num_ioc;
for (i = 0; i < num_ioc; i++) {
- /*
- ** Make sure the box crashes if we get any errors on a rope.
- */
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE0_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE1_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE2_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE3_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE4_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE5_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE6_CTL);
- WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
-
- /* flush out the writes */
+ unsigned long ioc_hpa = sba_dev->ioc[i].ioc_hpa;
+ unsigned int j;
+
+ for (j=0; j < sizeof(u64) * ROPES_PER_IOC; j+=sizeof(u64)) {
+
+ /*
+ * Clear ROPE(N)_CONFIG AO bit.
+ * Disables "NT Ordering" (~= !"Relaxed Ordering")
+ * Overrides bit 1 in DMA Hint Sets.
+ * Improves netperf UDP_STREAM by ~10% for bcm5701.
+ */
+ if (IS_PLUTO(sba_dev->iodc)) {
+ unsigned long rope_cfg, cfg_val;
+
+ rope_cfg = ioc_hpa + IOC_ROPE0_CFG + j;
+ cfg_val = READ_REG(rope_cfg);
+ cfg_val &= ~IOC_ROPE_AO;
+ WRITE_REG(cfg_val, rope_cfg);
+ }
+
+ /*
+ ** Make sure the box crashes on rope errors.
+ */
+ WRITE_REG(HF_ENABLE, ioc_hpa + ROPE0_CTL + j);
+ }
+
+ /* flush out the last writes */
READ_REG(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
DBG_INIT(" ioc[%d] ROPE_CFG 0x%Lx ROPE_DBG 0x%Lx\n",
@@ -2040,7 +2059,7 @@ sba_driver_callback(struct parisc_device *dev)
u32 func_class;
int i;
char *version;
- void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE);
+ void __iomem *sba_addr = ioremap_nocache(dev->hpa.start, SBA_FUNC_SIZE);
struct proc_dir_entry *info_entry, *bitmap_entry, *root;
sba_dump_ranges(sba_addr);
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index ad6d3b28a3a..828eb45062d 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -12,6 +12,7 @@
* (C) Copyright 2001 John Marvin <jsm fc hp com>
* (C) Copyright 2003 Grant Grundler <grundler parisc-linux org>
* (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org>
+ * (C) Copyright 2006 Helge Deller <deller@gmx.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -154,7 +155,7 @@ superio_init(struct pci_dev *pcidev)
struct pci_dev *pdev = sio->lio_pdev;
u16 word;
- if (sio->suckyio_irq_enabled)
+ if (sio->suckyio_irq_enabled)
return;
BUG_ON(!pdev);
@@ -193,7 +194,7 @@ superio_init(struct pci_dev *pcidev)
request_region (sio->acpi_base, 0x1f, "acpi");
/* Enable the legacy I/O function */
- pci_read_config_word (pdev, PCI_COMMAND, &word);
+ pci_read_config_word (pdev, PCI_COMMAND, &word);
word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO;
pci_write_config_word (pdev, PCI_COMMAND, word);
@@ -388,43 +389,34 @@ int superio_fixup_irq(struct pci_dev *pcidev)
return local_irq;
}
-static struct uart_port serial[] = {
- {
- .iotype = UPIO_PORT,
- .line = 0,
- .type = PORT_16550A,
- .uartclk = 115200*16,
- .fifosize = 16,
- },
- {
- .iotype = UPIO_PORT,
- .line = 1,
- .type = PORT_16550A,
- .uartclk = 115200*16,
- .fifosize = 16,
- }
-};
-
static void __devinit superio_serial_init(void)
{
#ifdef CONFIG_SERIAL_8250
int retval;
-
- serial[0].iobase = sio_dev.sp1_base;
- serial[0].irq = SP1_IRQ;
- spin_lock_init(&serial[0].lock);
-
- retval = early_serial_setup(&serial[0]);
+ struct uart_port serial_port;
+
+ memset(&serial_port, 0, sizeof(serial_port));
+ serial_port.iotype = UPIO_PORT;
+ serial_port.type = PORT_16550A;
+ serial_port.uartclk = 115200*16;
+ serial_port.fifosize = 16;
+ spin_lock_init(&serial_port.lock);
+
+ /* serial port #1 */
+ serial_port.iobase = sio_dev.sp1_base;
+ serial_port.irq = SP1_IRQ;
+ serial_port.line = 0;
+ retval = early_serial_setup(&serial_port);
if (retval < 0) {
printk(KERN_WARNING PFX "Register Serial #0 failed.\n");
return;
}
- serial[1].iobase = sio_dev.sp2_base;
- serial[1].irq = SP2_IRQ;
- spin_lock_init(&serial[1].lock);
- retval = early_serial_setup(&serial[1]);
-
+ /* serial port #2 */
+ serial_port.iobase = sio_dev.sp2_base;
+ serial_port.irq = SP2_IRQ;
+ serial_port.line = 1;
+ retval = early_serial_setup(&serial_port);
if (retval < 0)
printk(KERN_WARNING PFX "Register Serial #1 failed.\n");
#endif /* CONFIG_SERIAL_8250 */
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 158d9256325..b953d5907c0 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -81,15 +81,15 @@ static char *version =
#define FORCE_EPP_MODE 0x08
typedef struct parport_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
int ndev;
dev_node_t node;
struct parport *port;
} parport_info_t;
static void parport_detach(struct pcmcia_device *p_dev);
-static void parport_config(dev_link_t *link);
-static void parport_cs_release(dev_link_t *);
+static int parport_config(struct pcmcia_device *link);
+static void parport_cs_release(struct pcmcia_device *);
/*======================================================================
@@ -99,10 +99,9 @@ static void parport_cs_release(dev_link_t *);
======================================================================*/
-static int parport_attach(struct pcmcia_device *p_dev)
+static int parport_probe(struct pcmcia_device *link)
{
parport_info_t *info;
- dev_link_t *link;
DEBUG(0, "parport_attach()\n");
@@ -110,23 +109,17 @@ static int parport_attach(struct pcmcia_device *p_dev)
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) return -ENOMEM;
memset(info, 0, sizeof(*info));
- link = &info->link; link->priv = info;
+ link->priv = info;
+ info->p_dev = link;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- parport_config(link);
-
- return 0;
+ return parport_config(link);
} /* parport_attach */
/*======================================================================
@@ -138,14 +131,11 @@ static int parport_attach(struct pcmcia_device *p_dev)
======================================================================*/
-static void parport_detach(struct pcmcia_device *p_dev)
+static void parport_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "parport_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- parport_cs_release(link);
+ parport_cs_release(link);
kfree(link->priv);
} /* parport_detach */
@@ -161,14 +151,12 @@ static void parport_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-void parport_config(dev_link_t *link)
+static int parport_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
parport_info_t *info = link->priv;
tuple_t tuple;
u_short buf[128];
cisparse_t parse;
- config_info_t conf;
cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
cistpl_cftable_entry_t dflt = { 0 };
struct parport *p;
@@ -180,24 +168,18 @@ void parport_config(dev_link_t *link)
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
-
- /* Configure card */
- link->state |= DEV_CONFIG;
- /* Not sure if this is right... look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
@@ -212,7 +194,7 @@ void parport_config(dev_link_t *link)
link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = io->win[1].len;
}
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
/* If we've got this far, we're done */
break;
@@ -220,15 +202,12 @@ void parport_config(dev_link_t *link)
next_entry:
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
- release_region(link->io.BasePort1, link->io.NumPorts1);
- if (link->io.NumPorts2)
- release_region(link->io.BasePort2, link->io.NumPorts2);
p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2,
link->irq.AssignedIRQ, PARPORT_DMA_NONE,
NULL);
@@ -247,17 +226,15 @@ void parport_config(dev_link_t *link)
info->node.minor = p->number;
info->port = p;
strcpy(info->node.dev_name, p->name);
- link->dev = &info->node;
+ link->dev_node = &info->node;
+
+ return 0;
- link->state &= ~DEV_CONFIG_PENDING;
- return;
-
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
parport_cs_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
-
+ return -ENODEV;
} /* parport_config */
/*======================================================================
@@ -268,53 +245,21 @@ failed:
======================================================================*/
-void parport_cs_release(dev_link_t *link)
-{
- parport_info_t *info = link->priv;
-
- DEBUG(0, "parport_release(0x%p)\n", link);
-
- if (info->ndev) {
- struct parport *p = info->port;
- parport_pc_unregister_port(p);
- request_region(link->io.BasePort1, link->io.NumPorts1,
- info->node.dev_name);
- if (link->io.NumPorts2)
- request_region(link->io.BasePort2, link->io.NumPorts2,
- info->node.dev_name);
- }
- info->ndev = 0;
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-
-} /* parport_cs_release */
-
-static int parport_suspend(struct pcmcia_device *dev)
+void parport_cs_release(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
+ parport_info_t *info = link->priv;
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
+ DEBUG(0, "parport_release(0x%p)\n", link);
- return 0;
-}
-
-static int parport_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
+ if (info->ndev) {
+ struct parport *p = info->port;
+ parport_pc_unregister_port(p);
+ }
+ info->ndev = 0;
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
+ pcmcia_disable_device(link);
+} /* parport_cs_release */
- return 0;
-}
static struct pcmcia_device_id parport_ids[] = {
PCMCIA_DEVICE_FUNC_ID(3),
@@ -328,11 +273,9 @@ static struct pcmcia_driver parport_cs_driver = {
.drv = {
.name = "parport_cs",
},
- .probe = parport_attach,
+ .probe = parport_probe,
.remove = parport_detach,
.id_table = parport_ids,
- .suspend = parport_suspend,
- .resume = parport_resume,
};
static int __init init_parport_cs(void)
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 9302b8fd746..48bbf32fd98 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -97,7 +97,7 @@ static struct superio_struct { /* For Super-IO chips autodetection */
int io;
int irq;
int dma;
-} superios[NR_SUPERIOS] __devinitdata = { {0,},};
+} superios[NR_SUPERIOS] = { {0,},};
static int user_specified;
#if defined(CONFIG_PARPORT_PC_SUPERIO) || \
@@ -1557,7 +1557,7 @@ static int __devinit get_superio_dma (struct parport *p)
return PARPORT_DMA_NONE;
}
-static int __devinit get_superio_irq (struct parport *p)
+static int get_superio_irq (struct parport *p)
{
int i=0;
while( (superios[i].io != p->base) && (i<NR_SUPERIOS))
@@ -1579,7 +1579,7 @@ static int __devinit get_superio_irq (struct parport *p)
* this shall always be the case!)
*
*/
-static int __devinit parport_SPP_supported(struct parport *pb)
+static int parport_SPP_supported(struct parport *pb)
{
unsigned char r, w;
@@ -1660,7 +1660,7 @@ static int __devinit parport_SPP_supported(struct parport *pb)
* two bits of ECR aren't writable, so we check by writing ECR and
* reading it back to see if it's what we expect.
*/
-static int __devinit parport_ECR_present(struct parport *pb)
+static int parport_ECR_present(struct parport *pb)
{
struct parport_pc_private *priv = pb->private_data;
unsigned char r = 0xc;
@@ -1712,7 +1712,7 @@ static int __devinit parport_ECR_present(struct parport *pb)
* be misdetected here is rather academic.
*/
-static int __devinit parport_PS2_supported(struct parport *pb)
+static int parport_PS2_supported(struct parport *pb)
{
int ok = 0;
@@ -1868,7 +1868,7 @@ static int __devinit parport_ECP_supported(struct parport *pb)
}
#endif
-static int __devinit parport_ECPPS2_supported(struct parport *pb)
+static int parport_ECPPS2_supported(struct parport *pb)
{
const struct parport_pc_private *priv = pb->private_data;
int result;
@@ -1886,7 +1886,7 @@ static int __devinit parport_ECPPS2_supported(struct parport *pb)
/* EPP mode detection */
-static int __devinit parport_EPP_supported(struct parport *pb)
+static int parport_EPP_supported(struct parport *pb)
{
const struct parport_pc_private *priv = pb->private_data;
@@ -1931,7 +1931,7 @@ static int __devinit parport_EPP_supported(struct parport *pb)
return 1;
}
-static int __devinit parport_ECPEPP_supported(struct parport *pb)
+static int parport_ECPEPP_supported(struct parport *pb)
{
struct parport_pc_private *priv = pb->private_data;
int result;
@@ -2073,7 +2073,7 @@ static int __devinit irq_probe_SPP(struct parport *pb)
* When ECP is available we can autoprobe for IRQs.
* NOTE: If we can autoprobe it, we can register the IRQ.
*/
-static int __devinit parport_irq_probe(struct parport *pb)
+static int parport_irq_probe(struct parport *pb)
{
struct parport_pc_private *priv = pb->private_data;
@@ -2779,7 +2779,7 @@ static struct parport_pc_pci {
/* If set, this is called after probing for ports. If 'failed'
* is non-zero we couldn't use any of the ports. */
void (*postinit_hook) (struct pci_dev *pdev, int failed);
-} cards[] __devinitdata = {
+} cards[] = {
/* siig_1p_10x */ { 1, { { 2, 3 }, } },
/* siig_2p_10x */ { 2, { { 2, 3 }, { 4, 5 }, } },
/* siig_1p_20x */ { 1, { { 0, 1 }, } },
@@ -3126,9 +3126,9 @@ parport_pc_find_isa_ports (int autoirq, int autodma)
* autoirq is PARPORT_IRQ_NONE, PARPORT_IRQ_AUTO, or PARPORT_IRQ_PROBEONLY
* autodma is PARPORT_DMA_NONE or PARPORT_DMA_AUTO
*/
-static int __init parport_pc_find_ports (int autoirq, int autodma)
+static void __init parport_pc_find_ports (int autoirq, int autodma)
{
- int count = 0, r;
+ int count = 0, err;
#ifdef CONFIG_PARPORT_PC_SUPERIO
detect_and_report_winbond ();
@@ -3140,23 +3140,17 @@ static int __init parport_pc_find_ports (int autoirq, int autodma)
/* PnP ports, skip detection if SuperIO already found them */
if (!count) {
- r = pnp_register_driver (&parport_pc_pnp_driver);
- if (r >= 0) {
+ err = pnp_register_driver (&parport_pc_pnp_driver);
+ if (!err)
pnp_registered_parport = 1;
- count += r;
- }
}
/* ISA ports and whatever (see asm/parport.h). */
- count += parport_pc_find_nonpci_ports (autoirq, autodma);
-
- r = pci_register_driver (&parport_pc_pci_driver);
- if (r)
- return r;
- pci_registered_parport = 1;
- count += 1;
+ parport_pc_find_nonpci_ports (autoirq, autodma);
- return count;
+ err = pci_register_driver (&parport_pc_pci_driver);
+ if (!err)
+ pci_registered_parport = 1;
}
/*
@@ -3381,8 +3375,6 @@ __setup("parport_init_mode=",parport_init_mode_setup);
static int __init parport_pc_init(void)
{
- int count = 0;
-
if (parse_parport_params())
return -EINVAL;
@@ -3395,12 +3387,11 @@ static int __init parport_pc_init(void)
break;
if ((io_hi[i]) == PARPORT_IOHI_AUTO)
io_hi[i] = 0x400 + io[i];
- if (parport_pc_probe_port(io[i], io_hi[i],
- irqval[i], dmaval[i], NULL))
- count++;
+ parport_pc_probe_port(io[i], io_hi[i],
+ irqval[i], dmaval[i], NULL);
}
} else
- count += parport_pc_find_ports (irqval[0], dmaval[0]);
+ parport_pc_find_ports (irqval[0], dmaval[0]);
return 0;
}
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index d121644646b..98b83a85c60 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -100,8 +100,6 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 6e79f5675b0..63800454670 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -360,9 +360,6 @@ static int __init rpaphp_init(void)
while ((dn = of_find_node_by_type(dn, "pci")))
rpaphp_add_slot(dn);
- if (!num_slots)
- return -ENODEV;
-
return 0;
}
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index a77e79c8c82..9855c4c920b 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -504,6 +504,201 @@ void pci_scan_msi_device(struct pci_dev *dev)
nr_reserved_vectors++;
}
+#ifdef CONFIG_PM
+int pci_save_msi_state(struct pci_dev *dev)
+{
+ int pos, i = 0;
+ u16 control;
+ struct pci_cap_saved_state *save_state;
+ u32 *cap;
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ if (pos <= 0 || dev->no_msi)
+ return 0;
+
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
+ if (!(control & PCI_MSI_FLAGS_ENABLE))
+ return 0;
+
+ save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5,
+ GFP_KERNEL);
+ if (!save_state) {
+ printk(KERN_ERR "Out of memory in pci_save_msi_state\n");
+ return -ENOMEM;
+ }
+ cap = &save_state->data[0];
+
+ pci_read_config_dword(dev, pos, &cap[i++]);
+ control = cap[0] >> 16;
+ pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, &cap[i++]);
+ if (control & PCI_MSI_FLAGS_64BIT) {
+ pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, &cap[i++]);
+ pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, &cap[i++]);
+ } else
+ pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]);
+ if (control & PCI_MSI_FLAGS_MASKBIT)
+ pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]);
+ disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+ save_state->cap_nr = PCI_CAP_ID_MSI;
+ pci_add_saved_cap(dev, save_state);
+ return 0;
+}
+
+void pci_restore_msi_state(struct pci_dev *dev)
+{
+ int i = 0, pos;
+ u16 control;
+ struct pci_cap_saved_state *save_state;
+ u32 *cap;
+
+ save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI);
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ if (!save_state || pos <= 0)
+ return;
+ cap = &save_state->data[0];
+
+ control = cap[i++] >> 16;
+ pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]);
+ if (control & PCI_MSI_FLAGS_64BIT) {
+ pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]);
+ pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, cap[i++]);
+ } else
+ pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, cap[i++]);
+ if (control & PCI_MSI_FLAGS_MASKBIT)
+ pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]);
+ pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+ enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+ pci_remove_saved_cap(save_state);
+ kfree(save_state);
+}
+
+int pci_save_msix_state(struct pci_dev *dev)
+{
+ int pos;
+ u16 control;
+ struct pci_cap_saved_state *save_state;
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+ if (pos <= 0 || dev->no_msi)
+ return 0;
+
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
+ if (!(control & PCI_MSIX_FLAGS_ENABLE))
+ return 0;
+ save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16),
+ GFP_KERNEL);
+ if (!save_state) {
+ printk(KERN_ERR "Out of memory in pci_save_msix_state\n");
+ return -ENOMEM;
+ }
+ *((u16 *)&save_state->data[0]) = control;
+
+ disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+ save_state->cap_nr = PCI_CAP_ID_MSIX;
+ pci_add_saved_cap(dev, save_state);
+ return 0;
+}
+
+void pci_restore_msix_state(struct pci_dev *dev)
+{
+ u16 save;
+ int pos;
+ int vector, head, tail = 0;
+ void __iomem *base;
+ int j;
+ struct msg_address address;
+ struct msg_data data;
+ struct msi_desc *entry;
+ int temp;
+ struct pci_cap_saved_state *save_state;
+
+ save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX);
+ if (!save_state)
+ return;
+ save = *((u16 *)&save_state->data[0]);
+ pci_remove_saved_cap(save_state);
+ kfree(save_state);
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+ if (pos <= 0)
+ return;
+
+ /* route the table */
+ temp = dev->irq;
+ if (msi_lookup_vector(dev, PCI_CAP_ID_MSIX))
+ return;
+ vector = head = dev->irq;
+ while (head != tail) {
+ entry = msi_desc[vector];
+ base = entry->mask_base;
+ j = entry->msi_attrib.entry_nr;
+
+ msi_address_init(&address);
+ msi_data_init(&data, vector);
+
+ address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
+ address.lo_address.value |= entry->msi_attrib.current_cpu <<
+ MSI_TARGET_CPU_SHIFT;
+
+ writel(address.lo_address.value,
+ base + j * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+ writel(address.hi_address,
+ base + j * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
+ writel(*(u32*)&data,
+ base + j * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_DATA_OFFSET);
+
+ tail = msi_desc[vector]->link.tail;
+ vector = tail;
+ }
+ dev->irq = temp;
+
+ pci_write_config_word(dev, msi_control_reg(pos), save);
+ enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+}
+#endif
+
+static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry)
+{
+ struct msg_address address;
+ struct msg_data data;
+ int pos, vector = dev->irq;
+ u16 control;
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ pci_read_config_word(dev, msi_control_reg(pos), &control);
+ /* Configure MSI capability structure */
+ msi_address_init(&address);
+ msi_data_init(&data, vector);
+ entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
+ MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
+ pci_write_config_dword(dev, msi_lower_address_reg(pos),
+ address.lo_address.value);
+ if (is_64bit_address(control)) {
+ pci_write_config_dword(dev,
+ msi_upper_address_reg(pos), address.hi_address);
+ pci_write_config_word(dev,
+ msi_data_reg(pos, 1), *((u32*)&data));
+ } else
+ pci_write_config_word(dev,
+ msi_data_reg(pos, 0), *((u32*)&data));
+ if (entry->msi_attrib.maskbit) {
+ unsigned int maskbits, temp;
+ /* All MSIs are unmasked by default, Mask them all */
+ pci_read_config_dword(dev,
+ msi_mask_bits_reg(pos, is_64bit_address(control)),
+ &maskbits);
+ temp = (1 << multi_msi_capable(control));
+ temp = ((temp - 1) & ~temp);
+ maskbits |= temp;
+ pci_write_config_dword(dev,
+ msi_mask_bits_reg(pos, is_64bit_address(control)),
+ maskbits);
+ }
+}
+
/**
* msi_capability_init - configure device's MSI capability structure
* @dev: pointer to the pci_dev data structure of MSI device function
@@ -516,8 +711,6 @@ void pci_scan_msi_device(struct pci_dev *dev)
static int msi_capability_init(struct pci_dev *dev)
{
struct msi_desc *entry;
- struct msg_address address;
- struct msg_data data;
int pos, vector;
u16 control;
@@ -549,33 +742,8 @@ static int msi_capability_init(struct pci_dev *dev)
/* Replace with MSI handler */
irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit);
/* Configure MSI capability structure */
- msi_address_init(&address);
- msi_data_init(&data, vector);
- entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
- MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
- pci_write_config_dword(dev, msi_lower_address_reg(pos),
- address.lo_address.value);
- if (is_64bit_address(control)) {
- pci_write_config_dword(dev,
- msi_upper_address_reg(pos), address.hi_address);
- pci_write_config_word(dev,
- msi_data_reg(pos, 1), *((u32*)&data));
- } else
- pci_write_config_word(dev,
- msi_data_reg(pos, 0), *((u32*)&data));
- if (entry->msi_attrib.maskbit) {
- unsigned int maskbits, temp;
- /* All MSIs are unmasked by default, Mask them all */
- pci_read_config_dword(dev,
- msi_mask_bits_reg(pos, is_64bit_address(control)),
- &maskbits);
- temp = (1 << multi_msi_capable(control));
- temp = ((temp - 1) & ~temp);
- maskbits |= temp;
- pci_write_config_dword(dev,
- msi_mask_bits_reg(pos, is_64bit_address(control)),
- maskbits);
- }
+ msi_register_init(dev, entry);
+
attach_msi_entry(entry, vector);
/* Set MSI enabled bits */
enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
@@ -625,8 +793,10 @@ static int msix_capability_init(struct pci_dev *dev,
if (!entry)
break;
vector = get_msi_vector(dev);
- if (vector < 0)
+ if (vector < 0) {
+ kmem_cache_free(msi_cachep, entry);
break;
+ }
j = entries[i].entry;
entries[i].vector = vector;
@@ -731,6 +901,7 @@ int pci_enable_msi(struct pci_dev* dev)
vector_irq[dev->irq] = -1;
nr_released_vectors--;
spin_unlock_irqrestore(&msi_lock, flags);
+ msi_register_init(dev, msi_desc[dev->irq]);
enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
return 0;
}
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 6917c6cb091..c2ecae5ff0c 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -33,13 +33,10 @@ acpi_query_osc (
acpi_status status;
struct acpi_object_list input;
union acpi_object in_params[4];
- struct acpi_buffer output;
- union acpi_object out_obj;
+ struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+ union acpi_object *out_obj;
u32 osc_dw0;
- /* Setting up output buffer */
- output.length = sizeof(out_obj) + 3*sizeof(u32);
- output.pointer = &out_obj;
/* Setting up input parameters */
input.count = 4;
@@ -61,12 +58,15 @@ acpi_query_osc (
"Evaluate _OSC Set fails. Status = 0x%04x\n", status);
return status;
}
- if (out_obj.type != ACPI_TYPE_BUFFER) {
+ out_obj = output.pointer;
+
+ if (out_obj->type != ACPI_TYPE_BUFFER) {
printk(KERN_DEBUG
"Evaluate _OSC returns wrong type\n");
- return AE_TYPE;
+ status = AE_TYPE;
+ goto query_osc_out;
}
- osc_dw0 = *((u32 *) out_obj.buffer.pointer);
+ osc_dw0 = *((u32 *) out_obj->buffer.pointer);
if (osc_dw0) {
if (osc_dw0 & OSC_REQUEST_ERROR)
printk(KERN_DEBUG "_OSC request fails\n");
@@ -76,15 +76,21 @@ acpi_query_osc (
printk(KERN_DEBUG "_OSC invalid revision\n");
if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
/* Update Global Control Set */
- global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8));
- return AE_OK;
+ global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8));
+ status = AE_OK;
+ goto query_osc_out;
}
- return AE_ERROR;
+ status = AE_ERROR;
+ goto query_osc_out;
}
/* Update Global Control Set */
- global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8));
- return AE_OK;
+ global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8));
+ status = AE_OK;
+
+query_osc_out:
+ kfree(output.pointer);
+ return status;
}
@@ -96,14 +102,10 @@ acpi_run_osc (
acpi_status status;
struct acpi_object_list input;
union acpi_object in_params[4];
- struct acpi_buffer output;
- union acpi_object out_obj;
+ struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+ union acpi_object *out_obj;
u32 osc_dw0;
- /* Setting up output buffer */
- output.length = sizeof(out_obj) + 3*sizeof(u32);
- output.pointer = &out_obj;
-
/* Setting up input parameters */
input.count = 4;
input.pointer = in_params;
@@ -124,12 +126,14 @@ acpi_run_osc (
"Evaluate _OSC Set fails. Status = 0x%04x\n", status);
return status;
}
- if (out_obj.type != ACPI_TYPE_BUFFER) {
+ out_obj = output.pointer;
+ if (out_obj->type != ACPI_TYPE_BUFFER) {
printk(KERN_DEBUG
"Evaluate _OSC returns wrong type\n");
- return AE_TYPE;
+ status = AE_TYPE;
+ goto run_osc_out;
}
- osc_dw0 = *((u32 *) out_obj.buffer.pointer);
+ osc_dw0 = *((u32 *) out_obj->buffer.pointer);
if (osc_dw0) {
if (osc_dw0 & OSC_REQUEST_ERROR)
printk(KERN_DEBUG "_OSC request fails\n");
@@ -139,11 +143,17 @@ acpi_run_osc (
printk(KERN_DEBUG "_OSC invalid revision\n");
if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
printk(KERN_DEBUG "_OSC FW not grant req. control\n");
- return AE_SUPPORT;
+ status = AE_SUPPORT;
+ goto run_osc_out;
}
- return AE_ERROR;
+ status = AE_ERROR;
+ goto run_osc_out;
}
- return AE_OK;
+ status = AE_OK;
+
+run_osc_out:
+ kfree(output.pointer);
+ return status;
}
/**
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index f22f69ac644..10e1a905c14 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -271,10 +271,12 @@ static int pci_device_suspend(struct device * dev, pm_message_t state)
struct pci_driver * drv = pci_dev->driver;
int i = 0;
- if (drv && drv->suspend)
+ if (drv && drv->suspend) {
i = drv->suspend(pci_dev, state);
- else
+ suspend_report_result(drv->suspend, i);
+ } else {
pci_save_state(pci_dev);
+ }
return i;
}
@@ -283,9 +285,9 @@ static int pci_device_suspend(struct device * dev, pm_message_t state)
* Default resume method for devices that have no driver provided resume,
* or not even a driver at all.
*/
-static void pci_default_resume(struct pci_dev *pci_dev)
+static int pci_default_resume(struct pci_dev *pci_dev)
{
- int retval;
+ int retval = 0;
/* restore the PCI config space */
pci_restore_state(pci_dev);
@@ -295,18 +297,21 @@ static void pci_default_resume(struct pci_dev *pci_dev)
/* if the device was busmaster before the suspend, make it busmaster again */
if (pci_dev->is_busmaster)
pci_set_master(pci_dev);
+
+ return retval;
}
static int pci_device_resume(struct device * dev)
{
+ int error;
struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver;
if (drv && drv->resume)
- drv->resume(pci_dev);
+ error = drv->resume(pci_dev);
else
- pci_default_resume(pci_dev);
- return 0;
+ error = pci_default_resume(pci_dev);
+ return error;
}
static void pci_device_shutdown(struct device *dev)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index bea1ad1ad5b..12286275b1c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -307,9 +307,11 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
* Can enter D0 from any state, but if we can only go deeper
* to sleep if we're already in a low power state
*/
- if (state != PCI_D0 && dev->current_state > state)
+ if (state != PCI_D0 && dev->current_state > state) {
+ printk(KERN_ERR "%s(): %s: state=%d, current state=%d\n",
+ __FUNCTION__, pci_name(dev), state, dev->current_state);
return -EINVAL;
- else if (dev->current_state == state)
+ } else if (dev->current_state == state)
return 0; /* we're already there */
/* find PCI PM capability in list */
@@ -444,6 +446,10 @@ pci_save_state(struct pci_dev *dev)
/* XXX: 100% dword access ok here? */
for (i = 0; i < 16; i++)
pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]);
+ if ((i = pci_save_msi_state(dev)) != 0)
+ return i;
+ if ((i = pci_save_msix_state(dev)) != 0)
+ return i;
return 0;
}
@@ -455,9 +461,25 @@ int
pci_restore_state(struct pci_dev *dev)
{
int i;
+ int val;
- for (i = 0; i < 16; i++)
- pci_write_config_dword(dev,i * 4, dev->saved_config_space[i]);
+ /*
+ * The Base Address register should be programmed before the command
+ * register(s)
+ */
+ for (i = 15; i >= 0; i--) {
+ pci_read_config_dword(dev, i * 4, &val);
+ if (val != dev->saved_config_space[i]) {
+ printk(KERN_DEBUG "PM: Writing back config space on "
+ "device %s at offset %x (was %x, writing %x)\n",
+ pci_name(dev), i,
+ val, (int)dev->saved_config_space[i]);
+ pci_write_config_dword(dev,i * 4,
+ dev->saved_config_space[i]);
+ }
+ }
+ pci_restore_msi_state(dev);
+ pci_restore_msix_state(dev);
return 0;
}
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 8f3fb47ea67..30630cbe2fe 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -55,6 +55,17 @@ void pci_no_msi(void);
static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
static inline void pci_no_msi(void) { }
#endif
+#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
+int pci_save_msi_state(struct pci_dev *dev);
+int pci_save_msix_state(struct pci_dev *dev);
+void pci_restore_msi_state(struct pci_dev *dev);
+void pci_restore_msix_state(struct pci_dev *dev);
+#else
+static inline int pci_save_msi_state(struct pci_dev *dev) { return 0; }
+static inline int pci_save_msix_state(struct pci_dev *dev) { return 0; }
+static inline void pci_restore_msi_state(struct pci_dev *dev) {}
+static inline void pci_restore_msix_state(struct pci_dev *dev) {}
+#endif
extern int pcie_mch_quirk;
extern struct device_attribute pci_dev_attrs[];
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 4970f47be72..d378478612f 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -592,7 +592,7 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
pci_write_config_byte( dev, AMD8131_MISC, tmp);
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, quirk_amd_8131_ioapic );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
static void __init quirk_svw_msi(struct pci_dev *dev)
{
@@ -634,6 +634,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vi
* non-x86 architectures (yes Via exists on PPC among other places),
* we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
* interrupts delivered properly.
+ *
+ * Some of the on-chip devices are actually '586 devices' so they are
+ * listed here.
*/
static void quirk_via_irq(struct pci_dev *dev)
{
@@ -642,13 +645,19 @@ static void quirk_via_irq(struct pci_dev *dev)
new_irq = dev->irq & 0xf;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
if (new_irq != irq) {
- printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n",
+ printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n",
pci_name(dev), irq, new_irq);
udelay(15); /* unknown if delay really needed */
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
}
}
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq);
/*
* VIA VT82C598 has its device ID settable and many BIOSes
@@ -865,6 +874,36 @@ static void __init quirk_eisa_bridge(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge );
/*
+ * On the MSI-K8T-Neo2Fir Board, the internal Soundcard is disabled
+ * when a PCI-Soundcard is added. The BIOS only gives Options
+ * "Disabled" and "AUTO". This Quirk Sets the corresponding
+ * Register-Value to enable the Soundcard.
+ */
+static void __init k8t_sound_hostbridge(struct pci_dev *dev)
+{
+ unsigned char val;
+
+ printk(KERN_INFO "PCI: Quirk-MSI-K8T Soundcard On\n");
+ pci_read_config_byte(dev, 0x50, &val);
+ if (val == 0x88 || val == 0xc8) {
+ pci_write_config_byte(dev, 0x50, val & (~0x40));
+
+ /* Verify the Change for Status output */
+ pci_read_config_byte(dev, 0x50, &val);
+ if (val & 0x40)
+ printk(KERN_INFO "PCI: MSI-K8T soundcard still off\n");
+ else
+ printk(KERN_INFO "PCI: MSI-K8T soundcard on\n");
+ } else {
+ printk(KERN_INFO "PCI: Unexpected Value in PCI-Register: "
+ "no Change!\n");
+ }
+
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
+
+#ifndef CONFIG_ACPI_SLEEP
+/*
* On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge
* is not activated. The myth is that Asus said that they do not want the
* users to be irritated by just another PCI Device in the Win98 device
@@ -875,8 +914,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_e
* bridge. Unfortunately, this device has no subvendor/subdevice ID. So it
* becomes necessary to do this tweak in two steps -- I've chosen the Host
* bridge as trigger.
+ *
+ * Actually, leaving it unhidden and not redoing the quirk over suspend2ram
+ * will cause thermal management to break down, and causing machine to
+ * overheat.
*/
-static int __initdata asus_hides_smbus = 0;
+static int __initdata asus_hides_smbus;
static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
{
@@ -921,6 +964,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
switch (dev->subsystem_device) {
case 0x1882: /* M6V notebook */
+ case 0x1977: /* A6VA notebook */
asus_hides_smbus = 1;
}
}
@@ -999,6 +1043,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asu
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc );
static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
{
@@ -1017,6 +1062,8 @@ static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
+#endif
+
/*
* SiS 96x south bridge: BIOS typically hides SMBus device...
*/
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 1f4ad0e7836..61cb4b29f55 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -250,7 +250,7 @@ config M32R_CFC_NUM
config PCMCIA_VRC4171
tristate "NEC VRC4171 Card Controllers support"
- depends on VRC4171 && PCMCIA
+ depends on CPU_VR41XX && ISA && PCMCIA
config PCMCIA_VRC4173
tristate "NEC VRC4173 CARDU support"
@@ -263,6 +263,13 @@ config OMAP_CF
Say Y here to support the CompactFlash controller on OMAP.
Note that this doesn't support "True IDE" mode.
+config AT91_CF
+ tristate "AT91 CompactFlash Controller"
+ depends on PCMCIA && ARCH_AT91RM9200
+ help
+ Say Y here to support the CompactFlash controller on AT91 chips.
+ Or choose M to compile the driver as a module named "at91_cf".
+
config PCCARD_NONSTATIC
tristate
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index bcecf5133b7..4276965517f 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -10,7 +10,7 @@ pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o
pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
obj-$(CONFIG_PCCARD) += pcmcia_core.o
-pcmcia-y += ds.o pcmcia_compat.o pcmcia_resource.o
+pcmcia-y += ds.o pcmcia_resource.o
pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o
obj-$(CONFIG_PCMCIA) += pcmcia.o
@@ -36,6 +36,7 @@ obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o
obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o
obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
obj-$(CONFIG_OMAP_CF) += omap_cf.o
+obj-$(CONFIG_AT91_CF) += at91_cf.o
sa11xx_core-y += soc_common.o sa11xx_base.o
pxa2xx_core-y += soc_common.o pxa2xx_base.o
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
new file mode 100644
index 00000000000..a4d50940ebe
--- /dev/null
+++ b/drivers/pcmcia/at91_cf.c
@@ -0,0 +1,376 @@
+/*
+ * at91_cf.c -- AT91 CompactFlash controller driver
+ *
+ * Copyright (C) 2005 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+
+#include <asm/arch/at91rm9200.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+
+/*
+ * A0..A10 work in each range; A23 indicates I/O space; A25 is CFRNW;
+ * some other bit in {A24,A22..A11} is nREG to flag memory access
+ * (vs attributes). So more than 2KB/region would just be waste.
+ */
+#define CF_ATTR_PHYS (AT91_CF_BASE)
+#define CF_IO_PHYS (AT91_CF_BASE + (1 << 23))
+#define CF_MEM_PHYS (AT91_CF_BASE + 0x017ff800)
+
+/*--------------------------------------------------------------------------*/
+
+static const char driver_name[] = "at91_cf";
+
+struct at91_cf_socket {
+ struct pcmcia_socket socket;
+
+ unsigned present:1;
+
+ struct platform_device *pdev;
+ struct at91_cf_data *board;
+};
+
+#define SZ_2K (2 * SZ_1K)
+
+static inline int at91_cf_present(struct at91_cf_socket *cf)
+{
+ return !at91_get_gpio_value(cf->board->det_pin);
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int at91_cf_ss_init(struct pcmcia_socket *s)
+{
+ return 0;
+}
+
+static irqreturn_t at91_cf_irq(int irq, void *_cf, struct pt_regs *r)
+{
+ struct at91_cf_socket *cf = (struct at91_cf_socket *) _cf;
+
+ if (irq == cf->board->det_pin) {
+ unsigned present = at91_cf_present(cf);
+
+ /* kick pccard as needed */
+ if (present != cf->present) {
+ cf->present = present;
+ pr_debug("%s: card %s\n", driver_name,
+ present ? "present" : "gone");
+ pcmcia_parse_events(&cf->socket, SS_DETECT);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
+{
+ struct at91_cf_socket *cf;
+
+ if (!sp)
+ return -EINVAL;
+
+ cf = container_of(s, struct at91_cf_socket, socket);
+
+ /* NOTE: CF is always 3VCARD */
+ if (at91_cf_present(cf)) {
+ int rdy = cf->board->irq_pin; /* RDY/nIRQ */
+ int vcc = cf->board->vcc_pin;
+
+ *sp = SS_DETECT | SS_3VCARD;
+ if (!rdy || at91_get_gpio_value(rdy))
+ *sp |= SS_READY;
+ if (!vcc || at91_get_gpio_value(vcc))
+ *sp |= SS_POWERON;
+ } else
+ *sp = 0;
+
+ return 0;
+}
+
+static int
+at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
+{
+ struct at91_cf_socket *cf;
+
+ cf = container_of(sock, struct at91_cf_socket, socket);
+
+ /* switch Vcc if needed and possible */
+ if (cf->board->vcc_pin) {
+ switch (s->Vcc) {
+ case 0:
+ at91_set_gpio_value(cf->board->vcc_pin, 0);
+ break;
+ case 33:
+ at91_set_gpio_value(cf->board->vcc_pin, 1);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ /* toggle reset if needed */
+ at91_set_gpio_value(cf->board->rst_pin, s->flags & SS_RESET);
+
+ pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
+ driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+
+ return 0;
+}
+
+static int at91_cf_ss_suspend(struct pcmcia_socket *s)
+{
+ return at91_cf_set_socket(s, &dead_socket);
+}
+
+/* we already mapped the I/O region */
+static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
+{
+ struct at91_cf_socket *cf;
+ u32 csr;
+
+ cf = container_of(s, struct at91_cf_socket, socket);
+ io->flags &= (MAP_ACTIVE | MAP_16BIT | MAP_AUTOSZ);
+
+ /*
+ * Use 16 bit accesses unless/until we need 8-bit i/o space.
+ * Always set CSR4 ... PCMCIA won't always unmap things.
+ */
+ csr = at91_sys_read(AT91_SMC_CSR(4)) & ~AT91_SMC_DBW;
+
+ /*
+ * NOTE: this CF controller ignores IOIS16, so we can't really do
+ * MAP_AUTOSZ. The 16bit mode allows single byte access on either
+ * D0-D7 (even addr) or D8-D15 (odd), so it's close enough for many
+ * purposes (and handles ide-cs).
+ *
+ * The 8bit mode is needed for odd byte access on D0-D7. It seems
+ * some cards only like that way to get at the odd byte, despite
+ * CF 3.0 spec table 35 also giving the D8-D15 option.
+ */
+ if (!(io->flags & (MAP_16BIT|MAP_AUTOSZ))) {
+ csr |= AT91_SMC_DBW_8;
+ pr_debug("%s: 8bit i/o bus\n", driver_name);
+ } else {
+ csr |= AT91_SMC_DBW_16;
+ pr_debug("%s: 16bit i/o bus\n", driver_name);
+ }
+ at91_sys_write(AT91_SMC_CSR(4), csr);
+
+ io->start = cf->socket.io_offset;
+ io->stop = io->start + SZ_2K - 1;
+
+ return 0;
+}
+
+/* pcmcia layer maps/unmaps mem regions */
+static int
+at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
+{
+ struct at91_cf_socket *cf;
+
+ if (map->card_start)
+ return -EINVAL;
+
+ cf = container_of(s, struct at91_cf_socket, socket);
+
+ map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
+ if (map->flags & MAP_ATTRIB)
+ map->static_start = CF_ATTR_PHYS;
+ else
+ map->static_start = CF_MEM_PHYS;
+
+ return 0;
+}
+
+static struct pccard_operations at91_cf_ops = {
+ .init = at91_cf_ss_init,
+ .suspend = at91_cf_ss_suspend,
+ .get_status = at91_cf_get_status,
+ .set_socket = at91_cf_set_socket,
+ .set_io_map = at91_cf_set_io_map,
+ .set_mem_map = at91_cf_set_mem_map,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __init at91_cf_probe(struct device *dev)
+{
+ struct at91_cf_socket *cf;
+ struct at91_cf_data *board = dev->platform_data;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *io;
+ unsigned int csa;
+ int status;
+
+ if (!board || !board->det_pin || !board->rst_pin)
+ return -ENODEV;
+
+ io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!io)
+ return -ENODEV;
+
+ cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+ if (!cf)
+ return -ENOMEM;
+
+ cf->board = board;
+ cf->pdev = pdev;
+ dev_set_drvdata(dev, cf);
+
+ /* CF takes over CS4, CS5, CS6 */
+ csa = at91_sys_read(AT91_EBI_CSA);
+ at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH);
+
+ /* force poweron defaults for these pins ... */
+ (void) at91_set_A_periph(AT91_PIN_PC9, 0); /* A25/CFRNW */
+ (void) at91_set_A_periph(AT91_PIN_PC10, 0); /* NCS4/CFCS */
+ (void) at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */
+ (void) at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */
+
+ /* nWAIT is _not_ a default setting */
+ (void) at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */
+
+ /*
+ * Static memory controller timing adjustments.
+ * REVISIT: these timings are in terms of MCK cycles, so
+ * when MCK changes (cpufreq etc) so must these values...
+ */
+ at91_sys_write(AT91_SMC_CSR(4),
+ AT91_SMC_ACSS_STD
+ | AT91_SMC_DBW_16
+ | AT91_SMC_BAT
+ | AT91_SMC_WSEN
+ | AT91_SMC_NWS_(32) /* wait states */
+ | AT91_SMC_RWSETUP_(6) /* setup time */
+ | AT91_SMC_RWHOLD_(4) /* hold time */
+ );
+
+ /* must be a GPIO; ergo must trigger on both edges */
+ status = request_irq(board->det_pin, at91_cf_irq,
+ SA_SAMPLE_RANDOM, driver_name, cf);
+ if (status < 0)
+ goto fail0;
+
+ /*
+ * The card driver will request this irq later as needed.
+ * but it causes lots of "irqNN: nobody cared" messages
+ * unless we report that we handle everything (sigh).
+ * (Note: DK board doesn't wire the IRQ pin...)
+ */
+ if (board->irq_pin) {
+ status = request_irq(board->irq_pin, at91_cf_irq,
+ SA_SHIRQ, driver_name, cf);
+ if (status < 0)
+ goto fail0a;
+ cf->socket.pci_irq = board->irq_pin;
+ } else
+ cf->socket.pci_irq = NR_IRQS + 1;
+
+ /* pcmcia layer only remaps "real" memory not iospace */
+ cf->socket.io_offset = (unsigned long) ioremap(CF_IO_PHYS, SZ_2K);
+ if (!cf->socket.io_offset)
+ goto fail1;
+
+ /* reserve CS4, CS5, and CS6 regions; but use just CS4 */
+ if (!request_mem_region(io->start, io->end + 1 - io->start,
+ driver_name))
+ goto fail1;
+
+ pr_info("%s: irqs det #%d, io #%d\n", driver_name,
+ board->det_pin, board->irq_pin);
+
+ cf->socket.owner = THIS_MODULE;
+ cf->socket.dev.dev = dev;
+ cf->socket.ops = &at91_cf_ops;
+ cf->socket.resource_ops = &pccard_static_ops;
+ cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
+ | SS_CAP_MEM_ALIGN;
+ cf->socket.map_size = SZ_2K;
+ cf->socket.io[0].res = io;
+
+ status = pcmcia_register_socket(&cf->socket);
+ if (status < 0)
+ goto fail2;
+
+ return 0;
+
+fail2:
+ iounmap((void __iomem *) cf->socket.io_offset);
+ release_mem_region(io->start, io->end + 1 - io->start);
+fail1:
+ if (board->irq_pin)
+ free_irq(board->irq_pin, cf);
+fail0a:
+ free_irq(board->det_pin, cf);
+fail0:
+ at91_sys_write(AT91_EBI_CSA, csa);
+ kfree(cf);
+ return status;
+}
+
+static int __exit at91_cf_remove(struct device *dev)
+{
+ struct at91_cf_socket *cf = dev_get_drvdata(dev);
+ struct resource *io = cf->socket.io[0].res;
+ unsigned int csa;
+
+ pcmcia_unregister_socket(&cf->socket);
+ free_irq(cf->board->irq_pin, cf);
+ free_irq(cf->board->det_pin, cf);
+ iounmap((void __iomem *) cf->socket.io_offset);
+ release_mem_region(io->start, io->end + 1 - io->start);
+
+ csa = at91_sys_read(AT91_EBI_CSA);
+ at91_sys_write(AT91_EBI_CSA, csa & ~AT91_EBI_CS4A);
+
+ kfree(cf);
+ return 0;
+}
+
+static struct device_driver at91_cf_driver = {
+ .name = (char *) driver_name,
+ .bus = &platform_bus_type,
+ .probe = at91_cf_probe,
+ .remove = __exit_p(at91_cf_remove),
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __init at91_cf_init(void)
+{
+ return driver_register(&at91_cf_driver);
+}
+module_init(at91_cf_init);
+
+static void __exit at91_cf_exit(void)
+{
+ driver_unregister(&at91_cf_driver);
+}
+module_exit(at91_cf_exit);
+
+MODULE_DESCRIPTION("AT91 Compact Flash Driver");
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 120fa8da639..912c03e5eb0 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -12,7 +12,6 @@
* (C) 1999 David A. Hinds
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 613f2f1fbfd..3162998579c 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -16,7 +16,6 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/string.h>
#include <linux/major.h>
#include <linux/errno.h>
@@ -111,9 +110,9 @@ int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state)
list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
if (socket->dev.dev != dev)
continue;
- down(&socket->skt_sem);
+ mutex_lock(&socket->skt_mutex);
socket_suspend(socket);
- up(&socket->skt_sem);
+ mutex_unlock(&socket->skt_mutex);
}
up_read(&pcmcia_socket_list_rwsem);
@@ -129,9 +128,9 @@ int pcmcia_socket_dev_resume(struct device *dev)
list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
if (socket->dev.dev != dev)
continue;
- down(&socket->skt_sem);
+ mutex_lock(&socket->skt_mutex);
socket_resume(socket);
- up(&socket->skt_sem);
+ mutex_unlock(&socket->skt_mutex);
}
up_read(&pcmcia_socket_list_rwsem);
@@ -237,7 +236,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
init_completion(&socket->socket_released);
init_completion(&socket->thread_done);
init_waitqueue_head(&socket->thread_wait);
- init_MUTEX(&socket->skt_sem);
+ mutex_init(&socket->skt_mutex);
spin_lock_init(&socket->thread_lock);
ret = kernel_thread(pccardd, socket, CLONE_KERNEL);
@@ -406,8 +405,6 @@ static void socket_shutdown(struct pcmcia_socket *s)
cb_free(s);
#endif
s->functions = 0;
- kfree(s->config);
- s->config = NULL;
s->ops->get_status(s, &status);
if (status & SS_POWERON) {
@@ -664,7 +661,7 @@ static int pccardd(void *__skt)
spin_unlock_irqrestore(&skt->thread_lock, flags);
if (events) {
- down(&skt->skt_sem);
+ mutex_lock(&skt->skt_mutex);
if (events & SS_DETECT)
socket_detect_change(skt);
if (events & SS_BATDEAD)
@@ -673,7 +670,7 @@ static int pccardd(void *__skt)
send_event(skt, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW);
if (events & SS_READY)
send_event(skt, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW);
- up(&skt->skt_sem);
+ mutex_unlock(&skt->skt_mutex);
continue;
}
@@ -717,8 +714,8 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
{
int ret = 0;
- /* s->skt_sem also protects s->callback */
- down(&s->skt_sem);
+ /* s->skt_mutex also protects s->callback */
+ mutex_lock(&s->skt_mutex);
if (c) {
/* registration */
@@ -734,7 +731,7 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
} else
s->callback = NULL;
err:
- up(&s->skt_sem);
+ mutex_unlock(&s->skt_mutex);
return ret;
}
@@ -752,7 +749,7 @@ int pccard_reset_card(struct pcmcia_socket *skt)
cs_dbg(skt, 1, "resetting socket\n");
- down(&skt->skt_sem);
+ mutex_lock(&skt->skt_mutex);
do {
if (!(skt->state & SOCKET_PRESENT)) {
ret = CS_NO_CARD;
@@ -781,7 +778,7 @@ int pccard_reset_card(struct pcmcia_socket *skt)
ret = CS_SUCCESS;
} while (0);
- up(&skt->skt_sem);
+ mutex_unlock(&skt->skt_mutex);
return ret;
} /* reset_card */
@@ -797,7 +794,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
cs_dbg(skt, 1, "suspending socket\n");
- down(&skt->skt_sem);
+ mutex_lock(&skt->skt_mutex);
do {
if (!(skt->state & SOCKET_PRESENT)) {
ret = CS_NO_CARD;
@@ -814,7 +811,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
}
ret = socket_suspend(skt);
} while (0);
- up(&skt->skt_sem);
+ mutex_unlock(&skt->skt_mutex);
return ret;
} /* suspend_card */
@@ -827,7 +824,7 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
cs_dbg(skt, 1, "waking up socket\n");
- down(&skt->skt_sem);
+ mutex_lock(&skt->skt_mutex);
do {
if (!(skt->state & SOCKET_PRESENT)) {
ret = CS_NO_CARD;
@@ -841,7 +838,7 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
if (!ret && skt->callback)
skt->callback->resume(skt);
} while (0);
- up(&skt->skt_sem);
+ mutex_unlock(&skt->skt_mutex);
return ret;
} /* resume_card */
@@ -855,7 +852,7 @@ int pcmcia_eject_card(struct pcmcia_socket *skt)
cs_dbg(skt, 1, "user eject request\n");
- down(&skt->skt_sem);
+ mutex_lock(&skt->skt_mutex);
do {
if (!(skt->state & SOCKET_PRESENT)) {
ret = -ENODEV;
@@ -871,7 +868,7 @@ int pcmcia_eject_card(struct pcmcia_socket *skt)
socket_remove(skt);
ret = 0;
} while (0);
- up(&skt->skt_sem);
+ mutex_unlock(&skt->skt_mutex);
return ret;
} /* eject_card */
@@ -884,7 +881,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
cs_dbg(skt, 1, "user insert request\n");
- down(&skt->skt_sem);
+ mutex_lock(&skt->skt_mutex);
do {
if (skt->state & SOCKET_PRESENT) {
ret = -EBUSY;
@@ -896,7 +893,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
}
ret = 0;
} while (0);
- up(&skt->skt_sem);
+ mutex_unlock(&skt->skt_mutex);
return ret;
} /* insert_card */
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 7b37eba35bf..d6164cd583f 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -15,7 +15,7 @@
#ifndef _LINUX_CS_INTERNAL_H
#define _LINUX_CS_INTERNAL_H
-#include <linux/config.h>
+#include <linux/kref.h>
/* Flags in client state */
#define CLIENT_CONFIG_LOCKED 0x0001
@@ -23,7 +23,7 @@
#define CLIENT_IO_REQ 0x0004
#define CLIENT_UNBOUND 0x0008
#define CLIENT_STALE 0x0010
-#define CLIENT_WIN_REQ(i) (0x20<<(i))
+#define CLIENT_WIN_REQ(i) (0x1<<(i))
#define CLIENT_CARDBUS 0x8000
#define REGION_MAGIC 0xE3C9
@@ -31,7 +31,7 @@ typedef struct region_t {
u_short region_magic;
u_short state;
dev_info_t dev_info;
- client_handle_t mtd;
+ struct pcmcia_device *mtd;
u_int MediaID;
region_info_t info;
} region_t;
@@ -40,12 +40,12 @@ typedef struct region_t {
/* Each card function gets one of these guys */
typedef struct config_t {
+ struct kref ref;
u_int state;
u_int Attributes;
u_int IntType;
u_int ConfigBase;
u_char Status, Pin, Copy, Option, ExtStatus;
- u_int Present;
u_int CardValues;
io_req_t io;
struct {
@@ -95,12 +95,6 @@ static inline void cs_socket_put(struct pcmcia_socket *skt)
}
}
-#define CHECK_SOCKET(s) \
- (((s) >= sockets) || (socket_table[s]->ops == NULL))
-
-#define SOCKET(h) (h->socket)
-#define CONFIG(h) (&SOCKET(h)->config[(h)->func])
-
/* In cardbus.c */
int cb_alloc(struct pcmcia_socket *s);
void cb_free(struct pcmcia_socket *s);
@@ -133,10 +127,9 @@ extern struct class_interface pccard_sysfs_interface;
extern struct rw_semaphore pcmcia_socket_list_rwsem;
extern struct list_head pcmcia_socket_list;
int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req);
-int pccard_get_configuration_info(struct pcmcia_socket *s, unsigned int function, config_info_t *config);
+int pccard_get_configuration_info(struct pcmcia_socket *s, struct pcmcia_device *p_dev, config_info_t *config);
int pccard_reset_card(struct pcmcia_socket *skt);
-int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status);
-int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int function, conf_reg_t *reg);
+int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_status_t *status);
struct pcmcia_callback{
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index bb96ce1db08..74b3124e824 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -10,10 +10,9 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* (C) 1999 David A. Hinds
- * (C) 2003 - 2005 Dominik Brodowski
+ * (C) 2003 - 2006 Dominik Brodowski
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -23,6 +22,7 @@
#include <linux/workqueue.h>
#include <linux/crc32.h>
#include <linux/firmware.h>
+#include <linux/kref.h>
#define IN_CARD_SERVICES
#include <pcmcia/cs_types.h>
@@ -236,11 +236,11 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
/**
* pcmcia_load_firmware - load CIS from userspace if device-provided is broken
* @dev - the pcmcia device which needs a CIS override
- * @filename - requested filename in /lib/firmware/cis/
+ * @filename - requested filename in /lib/firmware/
*
* This uses the in-kernel firmware loading mechanism to use a "fake CIS" if
* the one provided by the card is broken. The firmware files reside in
- * /lib/firmware/cis/ in userspace.
+ * /lib/firmware/ in userspace.
*/
static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
{
@@ -298,9 +298,6 @@ static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filenam
*
* Registers a PCMCIA driver with the PCMCIA bus core.
*/
-static int pcmcia_device_probe(struct device *dev);
-static int pcmcia_device_remove(struct device * dev);
-
int pcmcia_register_driver(struct pcmcia_driver *driver)
{
if (!driver)
@@ -343,12 +340,19 @@ void pcmcia_put_dev(struct pcmcia_device *p_dev)
put_device(&p_dev->dev);
}
+static void pcmcia_release_function(struct kref *ref)
+{
+ struct config_t *c = container_of(ref, struct config_t, ref);
+ kfree(c);
+}
+
static void pcmcia_release_dev(struct device *dev)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
ds_dbg(1, "releasing dev %p\n", p_dev);
pcmcia_put_socket(p_dev->socket);
kfree(p_dev->devname);
+ kref_put(&p_dev->function_config->ref, pcmcia_release_function);
kfree(p_dev);
}
@@ -377,29 +381,12 @@ static int pcmcia_device_probe(struct device * dev)
p_drv = to_pcmcia_drv(dev->driver);
s = p_dev->socket;
- if ((!p_drv->probe) || (!try_module_get(p_drv->owner))) {
+ if ((!p_drv->probe) || (!p_dev->function_config) ||
+ (!try_module_get(p_drv->owner))) {
ret = -EINVAL;
goto put_dev;
}
- p_dev->state &= ~CLIENT_UNBOUND;
-
- /* set up the device configuration, if it hasn't been done before */
- if (!s->functions) {
- cistpl_longlink_mfc_t mfc;
- if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC,
- &mfc) == CS_SUCCESS)
- s->functions = mfc.nfn;
- else
- s->functions = 1;
- s->config = kzalloc(sizeof(config_t) * s->functions,
- GFP_KERNEL);
- if (!s->config) {
- ret = -ENOMEM;
- goto put_module;
- }
- }
-
ret = p_drv->probe(p_dev);
if (ret)
goto put_module;
@@ -410,7 +397,7 @@ static int pcmcia_device_probe(struct device * dev)
* call which will then check whether there are two
* pseudo devices, and if not, add the second one.
*/
- did = (struct pcmcia_device_id *) p_dev->dev.driver_data;
+ did = p_dev->dev.driver_data;
if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
(p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
pcmcia_add_pseudo_device(p_dev->socket);
@@ -425,33 +412,79 @@ static int pcmcia_device_probe(struct device * dev)
}
+/*
+ * Removes a PCMCIA card from the device tree and socket list.
+ */
+static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *leftover)
+{
+ struct pcmcia_device *p_dev;
+ struct pcmcia_device *tmp;
+ unsigned long flags;
+
+ ds_dbg(2, "unbind_request(%d)\n", s->sock);
+
+
+ if (!leftover)
+ s->device_count = 0;
+ else
+ s->device_count = 1;
+
+ /* unregister all pcmcia_devices registered with this socket, except leftover */
+ list_for_each_entry_safe(p_dev, tmp, &s->devices_list, socket_device_list) {
+ if (p_dev == leftover)
+ continue;
+
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_del(&p_dev->socket_device_list);
+ p_dev->_removed=1;
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+ device_unregister(&p_dev->dev);
+ }
+
+ return;
+}
+
static int pcmcia_device_remove(struct device * dev)
{
struct pcmcia_device *p_dev;
struct pcmcia_driver *p_drv;
+ struct pcmcia_device_id *did;
int i;
- /* detach the "instance" */
p_dev = to_pcmcia_dev(dev);
p_drv = to_pcmcia_drv(dev->driver);
+
+ /* If we're removing the primary module driving a
+ * pseudo multi-function card, we need to unbind
+ * all devices
+ */
+ did = p_dev->dev.driver_data;
+ if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
+ (p_dev->socket->device_count != 0) &&
+ (p_dev->device_no == 0))
+ pcmcia_card_remove(p_dev->socket, p_dev);
+
+ /* detach the "instance" */
if (!p_drv)
return 0;
if (p_drv->remove)
p_drv->remove(p_dev);
+ p_dev->dev_node = NULL;
+
/* check for proper unloading */
- if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
+ if (p_dev->_irq || p_dev->_io || p_dev->_locked)
printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
p_drv->drv.name);
for (i = 0; i < MAX_WIN; i++)
- if (p_dev->state & CLIENT_WIN_REQ(i))
+ if (p_dev->_win & CLIENT_WIN_REQ(i))
printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
p_drv->drv.name);
/* references from pcmcia_probe_device */
- p_dev->state = CLIENT_UNBOUND;
pcmcia_put_dev(p_dev);
module_put(p_drv->owner);
@@ -460,37 +493,6 @@ static int pcmcia_device_remove(struct device * dev)
/*
- * Removes a PCMCIA card from the device tree and socket list.
- */
-static void pcmcia_card_remove(struct pcmcia_socket *s)
-{
- struct pcmcia_device *p_dev;
- unsigned long flags;
-
- ds_dbg(2, "unbind_request(%d)\n", s->sock);
-
- s->device_count = 0;
-
- for (;;) {
- /* unregister all pcmcia_devices registered with this socket*/
- spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
- if (list_empty(&s->devices_list)) {
- spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- return;
- }
- p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
- list_del(&p_dev->socket_device_list);
- p_dev->state |= CLIENT_STALE;
- spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-
- device_unregister(&p_dev->dev);
- }
-
- return;
-} /* unbind_request */
-
-
-/*
* pcmcia_device_query -- determine information about a pcmcia device
*/
static int pcmcia_device_query(struct pcmcia_device *p_dev)
@@ -546,7 +548,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
tmp = vers1->str + vers1->ofs[i];
length = strlen(tmp) + 1;
- if ((length < 3) || (length > 255))
+ if ((length < 2) || (length > 255))
continue;
p_dev->prod_id[i] = kmalloc(sizeof(char) * length,
@@ -571,11 +573,11 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
* won't work, this doesn't matter much at the moment: the driver core doesn't
* support it either.
*/
-static DECLARE_MUTEX(device_add_lock);
+static DEFINE_MUTEX(device_add_lock);
struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function)
{
- struct pcmcia_device *p_dev;
+ struct pcmcia_device *p_dev, *tmp_dev;
unsigned long flags;
int bus_id_len;
@@ -583,7 +585,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
if (!s)
return NULL;
- down(&device_add_lock);
+ mutex_lock(&device_add_lock);
/* max of 2 devices per card */
if (s->device_count == 2)
@@ -596,6 +598,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
p_dev->socket = s;
p_dev->device_no = (s->device_count++);
p_dev->func = function;
+ if (s->functions <= function)
+ s->functions = function + 1;
p_dev->dev.bus = &pcmcia_bus_type;
p_dev->dev.parent = s->dev.dev;
@@ -608,36 +612,55 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
/* compat */
- p_dev->state = CLIENT_UNBOUND;
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+
+ /*
+ * p_dev->function_config must be the same for all card functions.
+ * Note that this is serialized by the device_add_lock, so that
+ * only one such struct will be created.
+ */
+ list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list)
+ if (p_dev->func == tmp_dev->func) {
+ p_dev->function_config = tmp_dev->function_config;
+ kref_get(&p_dev->function_config->ref);
+ }
/* Add to the list in pcmcia_bus_socket */
- spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
- list_add_tail(&p_dev->socket_device_list, &s->devices_list);
+ list_add(&p_dev->socket_device_list, &s->devices_list);
+
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ if (!p_dev->function_config) {
+ p_dev->function_config = kzalloc(sizeof(struct config_t),
+ GFP_KERNEL);
+ if (!p_dev->function_config)
+ goto err_unreg;
+ kref_init(&p_dev->function_config->ref);
+ }
+
printk(KERN_NOTICE "pcmcia: registering new device %s\n",
p_dev->devname);
pcmcia_device_query(p_dev);
- if (device_register(&p_dev->dev)) {
- spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
- list_del(&p_dev->socket_device_list);
- spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ if (device_register(&p_dev->dev))
+ goto err_unreg;
- goto err_free;
- }
-
- up(&device_add_lock);
+ mutex_unlock(&device_add_lock);
return p_dev;
+ err_unreg:
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_del(&p_dev->socket_device_list);
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
err_free:
kfree(p_dev->devname);
kfree(p_dev);
s->device_count--;
err_put:
- up(&device_add_lock);
+ mutex_unlock(&device_add_lock);
pcmcia_put_socket(s);
return NULL;
@@ -696,7 +719,7 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt)
int no_devices=0;
unsigned long flags;
- /* must be called with skt_sem held */
+ /* must be called with skt_mutex held */
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
if (list_empty(&skt->devices_list))
no_devices=1;
@@ -819,9 +842,11 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
struct pcmcia_driver * p_drv = to_pcmcia_drv(drv);
struct pcmcia_device_id *did = p_drv->id_table;
+#ifdef CONFIG_PCMCIA_IOCTL
/* matching by cardmgr */
if (p_dev->cardmgr == p_drv)
return 1;
+#endif
while (did && did->match_flags) {
if (pcmcia_devmatch(p_dev, did))
@@ -927,7 +952,7 @@ static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
- if (p_dev->dev.power.power_state.event != PM_EVENT_ON)
+ if (p_dev->suspended)
return sprintf(buf, "off\n");
else
return sprintf(buf, "on\n");
@@ -942,11 +967,9 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute
if (!count)
return -EINVAL;
- if ((p_dev->dev.power.power_state.event == PM_EVENT_ON) &&
- (!strncmp(buf, "off", 3)))
+ if ((!p_dev->suspended) && !strncmp(buf, "off", 3))
ret = dpm_runtime_suspend(dev, PMSG_SUSPEND);
- else if ((p_dev->dev.power.power_state.event != PM_EVENT_ON) &&
- (!strncmp(buf, "on", 2)))
+ else if (p_dev->suspended && !strncmp(buf, "on", 2))
dpm_runtime_resume(dev);
return ret ? ret : count;
@@ -982,9 +1005,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
if (!count)
return -EINVAL;
- down(&p_dev->socket->skt_sem);
+ mutex_lock(&p_dev->socket->skt_mutex);
p_dev->allow_func_id_match = 1;
- up(&p_dev->socket->skt_sem);
+ mutex_unlock(&p_dev->socket->skt_mutex);
bus_rescan_devices(&pcmcia_bus_type);
@@ -1012,14 +1035,27 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
struct pcmcia_driver *p_drv = NULL;
+ int ret = 0;
if (dev->driver)
p_drv = to_pcmcia_drv(dev->driver);
- if (p_drv && p_drv->suspend)
- return p_drv->suspend(p_dev);
+ if (!p_drv)
+ goto out;
- return 0;
+ if (p_drv->suspend) {
+ ret = p_drv->suspend(p_dev);
+ if (ret)
+ goto out;
+ }
+
+ if (p_dev->device_no == p_dev->func)
+ pcmcia_release_configuration(p_dev);
+
+ out:
+ if (!ret)
+ p_dev->suspended = 1;
+ return ret;
}
@@ -1027,14 +1063,27 @@ static int pcmcia_dev_resume(struct device * dev)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
struct pcmcia_driver *p_drv = NULL;
+ int ret = 0;
if (dev->driver)
p_drv = to_pcmcia_drv(dev->driver);
- if (p_drv && p_drv->resume)
- return p_drv->resume(p_dev);
+ if (!p_drv)
+ goto out;
- return 0;
+ if (p_dev->device_no == p_dev->func) {
+ ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+ if (ret)
+ goto out;
+ }
+
+ if (p_drv->resume)
+ ret = p_drv->resume(p_dev);
+
+ out:
+ if (!ret)
+ p_dev->suspended = 0;
+ return ret;
}
@@ -1094,13 +1143,19 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
{
struct pcmcia_socket *s = pcmcia_get_socket(skt);
+ if (!s) {
+ printk(KERN_ERR "PCMCIA obtaining reference to socket %p " \
+ "failed, event 0x%x lost!\n", skt, event);
+ return -ENODEV;
+ }
+
ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
event, priority, skt);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
s->pcmcia_state.present = 0;
- pcmcia_card_remove(skt);
+ pcmcia_card_remove(skt, NULL);
handle_event(skt, event);
break;
@@ -1128,6 +1183,32 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
} /* ds_event */
+struct pcmcia_device * pcmcia_dev_present(struct pcmcia_device *_p_dev)
+{
+ struct pcmcia_device *p_dev;
+ struct pcmcia_device *ret = NULL;
+
+ p_dev = pcmcia_get_dev(_p_dev);
+ if (!p_dev)
+ return NULL;
+
+ if (!p_dev->socket->pcmcia_state.present)
+ goto out;
+
+ if (p_dev->_removed)
+ goto out;
+
+ if (p_dev->suspended)
+ goto out;
+
+ ret = p_dev;
+ out:
+ pcmcia_put_dev(p_dev);
+ return ret;
+}
+EXPORT_SYMBOL(pcmcia_dev_present);
+
+
static struct pcmcia_callback pcmcia_bus_callback = {
.owner = THIS_MODULE,
.event = ds_event,
diff --git a/drivers/pcmcia/ds_internal.h b/drivers/pcmcia/ds_internal.h
index d359bd25a51..3a2b25e6ed7 100644
--- a/drivers/pcmcia/ds_internal.h
+++ b/drivers/pcmcia/ds_internal.h
@@ -8,6 +8,8 @@ extern void pcmcia_put_dev(struct pcmcia_device *p_dev);
struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function);
+extern int pcmcia_release_configuration(struct pcmcia_device *p_dev);
+
#ifdef CONFIG_PCMCIA_IOCTL
extern void __init pcmcia_setup_ioctl(void);
extern void __exit pcmcia_cleanup_ioctl(void);
@@ -15,7 +17,7 @@ extern void handle_event(struct pcmcia_socket *s, event_t event);
extern int handle_request(struct pcmcia_socket *s, event_t event);
#else
static inline void __init pcmcia_setup_ioctl(void) { return; }
-static inline void __init pcmcia_cleanup_ioctl(void) { return; }
+static inline void __exit pcmcia_cleanup_ioctl(void) { return; }
static inline void handle_event(struct pcmcia_socket *s, event_t event) { return; }
static inline int handle_request(struct pcmcia_socket *s, event_t event) { return CS_SUCCESS; }
#endif
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 7979c85df3d..d5f03a338c6 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -10,7 +10,6 @@
*/
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 35a92d1e494..a2f05f48515 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -34,7 +34,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/string.h>
@@ -510,7 +509,8 @@ static irqreturn_t i365_count_irq(int irq, void *dev, struct pt_regs *regs)
static u_int __init test_irq(u_short sock, int irq)
{
debug(2, " testing ISA irq %d\n", irq);
- if (request_irq(irq, i365_count_irq, 0, "scan", i365_count_irq) != 0)
+ if (request_irq(irq, i365_count_irq, SA_PROBEIRQ, "scan",
+ i365_count_irq) != 0)
return 1;
irq_hits = 0; irq_sock = sock;
msleep(10);
@@ -562,7 +562,7 @@ static u_int __init isa_scan(u_short sock, u_int mask0)
} else {
/* Fallback: just find interrupts that aren't in use */
for (i = 0; i < 16; i++)
- if ((mask0 & (1 << i)) && (_check_irq(i, 0) == 0))
+ if ((mask0 & (1 << i)) && (_check_irq(i, SA_PROBEIRQ) == 0))
mask1 |= (1 << i);
printk("default");
/* If scan failed, default to polled status */
@@ -726,7 +726,7 @@ static void __init add_pcic(int ns, int type)
u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
for (cs_irq = 15; cs_irq > 0; cs_irq--)
if ((cs_mask & (1 << cs_irq)) &&
- (_check_irq(cs_irq, 0) == 0))
+ (_check_irq(cs_irq, SA_PROBEIRQ) == 0))
break;
if (cs_irq) {
grab_irq = 1;
diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c
deleted file mode 100644
index ebb161c4f81..00000000000
--- a/drivers/pcmcia/pcmcia_compat.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * PCMCIA 16-bit compatibility functions
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- *
- * Copyright (C) 2004 Dominik Brodowski
- *
- * 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/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#define IN_CARD_SERVICES
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/ss.h>
-
-#include "cs_internal.h"
-
-int pcmcia_get_first_tuple(struct pcmcia_device *p_dev, tuple_t *tuple)
-{
- return pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple);
-}
-EXPORT_SYMBOL(pcmcia_get_first_tuple);
-
-int pcmcia_get_next_tuple(struct pcmcia_device *p_dev, tuple_t *tuple)
-{
- return pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple);
-}
-EXPORT_SYMBOL(pcmcia_get_next_tuple);
-
-int pcmcia_get_tuple_data(struct pcmcia_device *p_dev, tuple_t *tuple)
-{
- return pccard_get_tuple_data(p_dev->socket, tuple);
-}
-EXPORT_SYMBOL(pcmcia_get_tuple_data);
-
-int pcmcia_parse_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, cisparse_t *parse)
-{
- return pccard_parse_tuple(tuple, parse);
-}
-EXPORT_SYMBOL(pcmcia_parse_tuple);
-
-int pcmcia_validate_cis(struct pcmcia_device *p_dev, cisinfo_t *info)
-{
- return pccard_validate_cis(p_dev->socket, p_dev->func, info);
-}
-EXPORT_SYMBOL(pcmcia_validate_cis);
-
-
-int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req)
-{
- return pccard_reset_card(p_dev->socket);
-}
-EXPORT_SYMBOL(pcmcia_reset_card);
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 80969f7e7a0..738b1ef595a 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -18,7 +18,6 @@
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -70,10 +69,26 @@ extern int ds_pc_debug;
#define ds_dbg(lvl, fmt, arg...) do { } while (0)
#endif
+static struct pcmcia_device *get_pcmcia_device(struct pcmcia_socket *s,
+ unsigned int function)
+{
+ struct pcmcia_device *p_dev = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
+ if (p_dev->func == function) {
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ return pcmcia_get_dev(p_dev);
+ }
+ }
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ return NULL;
+}
/* backwards-compatible accessing of driver --- by name! */
-static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info)
+static struct pcmcia_driver *get_pcmcia_driver(dev_info_t *dev_info)
{
struct device_driver *drv;
struct pcmcia_driver *p_drv;
@@ -214,7 +229,7 @@ static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info)
* by userspace before, we need to
* return the "instance". */
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- bind_info->instance = p_dev->instance;
+ bind_info->instance = p_dev;
ret = -EBUSY;
goto err_put_module;
} else {
@@ -253,9 +268,9 @@ rescan:
/*
* Prevent this racing with a card insertion.
*/
- down(&s->skt_sem);
+ mutex_lock(&s->skt_mutex);
bus_rescan_devices(&pcmcia_bus_type);
- up(&s->skt_sem);
+ mutex_unlock(&s->skt_mutex);
/* check whether the driver indeed matched. I don't care if this
* is racy or not, because it can only happen on cardmgr access
@@ -289,6 +304,7 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int
{
dev_node_t *node;
struct pcmcia_device *p_dev;
+ struct pcmcia_driver *p_drv;
unsigned long flags;
int ret = 0;
@@ -343,16 +359,16 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int
found:
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- if ((!p_dev->instance) ||
- (p_dev->instance->state & DEV_CONFIG_PENDING)) {
+ p_drv = to_pcmcia_drv(p_dev->dev.driver);
+ if (p_drv && !p_dev->_locked) {
ret = -EAGAIN;
goto err_put;
}
if (first)
- node = p_dev->instance->dev;
+ node = p_dev->dev_node;
else
- for (node = p_dev->instance->dev; node; node = node->next)
+ for (node = p_dev->dev_node; node; node = node->next)
if (node == bind_info->next)
break;
if (!node) {
@@ -410,7 +426,7 @@ static int ds_open(struct inode *inode, struct file *file)
if (!warning_printed) {
printk(KERN_INFO "pcmcia: Detected deprecated PCMCIA ioctl "
- "usage.\n");
+ "usage from process: %s.\n", current->comm);
printk(KERN_INFO "pcmcia: This interface will soon be removed from "
"the kernel; please expect breakage unless you upgrade "
"to new tools.\n");
@@ -583,14 +599,20 @@ static int ds_ioctl(struct inode * inode, struct file * file,
if (buf->config.Function &&
(buf->config.Function >= s->functions))
ret = CS_BAD_ARGS;
- else
- ret = pccard_get_configuration_info(s,
- buf->config.Function, &buf->config);
+ else {
+ struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function);
+ if (p_dev == NULL)
+ ret = CS_BAD_ARGS;
+ else {
+ ret = pccard_get_configuration_info(s, p_dev, &buf->config);
+ pcmcia_put_dev(p_dev);
+ }
+ }
break;
case DS_GET_FIRST_TUPLE:
- down(&s->skt_sem);
+ mutex_lock(&s->skt_mutex);
pcmcia_validate_mem(s);
- up(&s->skt_sem);
+ mutex_unlock(&s->skt_mutex);
ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple);
break;
case DS_GET_NEXT_TUPLE:
@@ -609,16 +631,23 @@ static int ds_ioctl(struct inode * inode, struct file * file,
ret = pccard_reset_card(s);
break;
case DS_GET_STATUS:
- if (buf->status.Function &&
- (buf->status.Function >= s->functions))
- ret = CS_BAD_ARGS;
- else
- ret = pccard_get_status(s, buf->status.Function, &buf->status);
- break;
+ if (buf->status.Function &&
+ (buf->status.Function >= s->functions))
+ ret = CS_BAD_ARGS;
+ else {
+ struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function);
+ if (p_dev == NULL)
+ ret = CS_BAD_ARGS;
+ else {
+ ret = pccard_get_status(s, p_dev, &buf->status);
+ pcmcia_put_dev(p_dev);
+ }
+ }
+ break;
case DS_VALIDATE_CIS:
- down(&s->skt_sem);
+ mutex_lock(&s->skt_mutex);
pcmcia_validate_mem(s);
- up(&s->skt_sem);
+ mutex_unlock(&s->skt_mutex);
ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo);
break;
case DS_SUSPEND_CARD:
@@ -638,12 +667,17 @@ static int ds_ioctl(struct inode * inode, struct file * file,
err = -EPERM;
goto free_out;
}
- if (buf->conf_reg.Function &&
- (buf->conf_reg.Function >= s->functions))
- ret = CS_BAD_ARGS;
- else
- ret = pccard_access_configuration_register(s,
- buf->conf_reg.Function, &buf->conf_reg);
+
+ ret = CS_BAD_ARGS;
+
+ if (!(buf->conf_reg.Function &&
+ (buf->conf_reg.Function >= s->functions))) {
+ struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->conf_reg.Function);
+ if (p_dev) {
+ ret = pcmcia_access_configuration_register(p_dev, &buf->conf_reg);
+ pcmcia_put_dev(p_dev);
+ }
+ }
break;
case DS_GET_FIRST_REGION:
case DS_GET_NEXT_REGION:
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 89022ad5b52..3131bb0a009 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -14,7 +14,6 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
@@ -89,7 +88,6 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
}
if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) {
*base = s->io_offset | (*base & 0x0fff);
- s->io[0].Attributes = attr;
return 0;
}
/* Check for an already-allocated window that must conflict with
@@ -97,38 +95,36 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
* potential conflicts, just the most obvious ones.
*/
for (i = 0; i < MAX_IO_WIN; i++)
- if ((s->io[i].NumPorts != 0) &&
- ((s->io[i].BasePort & (align-1)) == *base))
+ if ((s->io[i].res) &&
+ ((s->io[i].res->start & (align-1)) == *base))
return 1;
for (i = 0; i < MAX_IO_WIN; i++) {
- if (s->io[i].NumPorts == 0) {
+ if (!s->io[i].res) {
s->io[i].res = pcmcia_find_io_region(*base, num, align, s);
if (s->io[i].res) {
- s->io[i].Attributes = attr;
- s->io[i].BasePort = *base = s->io[i].res->start;
- s->io[i].NumPorts = s->io[i].InUse = num;
+ *base = s->io[i].res->start;
+ s->io[i].res->flags = (s->io[i].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS);
+ s->io[i].InUse = num;
break;
} else
return 1;
- } else if (s->io[i].Attributes != attr)
+ } else if ((s->io[i].res->flags & IORESOURCE_BITS) != (attr & IORESOURCE_BITS))
continue;
/* Try to extend top of window */
- try = s->io[i].BasePort + s->io[i].NumPorts;
+ try = s->io[i].res->end + 1;
if ((*base == 0) || (*base == try))
if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start,
s->io[i].res->end + num, s) == 0) {
*base = try;
- s->io[i].NumPorts += num;
s->io[i].InUse += num;
break;
}
/* Try to extend bottom of window */
- try = s->io[i].BasePort - num;
+ try = s->io[i].res->start - num;
if ((*base == 0) || (*base == try))
if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num,
s->io[i].res->end, s) == 0) {
- s->io[i].BasePort = *base = try;
- s->io[i].NumPorts += num;
+ *base = try;
s->io[i].InUse += num;
break;
}
@@ -143,12 +139,13 @@ static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
int i;
for (i = 0; i < MAX_IO_WIN; i++) {
- if ((s->io[i].BasePort <= base) &&
- (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) {
+ if (!s->io[i].res)
+ continue;
+ if ((s->io[i].res->start <= base) &&
+ (s->io[i].res->end >= base+num-1)) {
s->io[i].InUse -= num;
/* Free the window if no one else is using it */
if (s->io[i].InUse == 0) {
- s->io[i].NumPorts = 0;
release_resource(s->io[i].res);
kfree(s->io[i].res);
s->io[i].res = NULL;
@@ -165,21 +162,19 @@ static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
* this and the tuple reading services.
*/
-int pccard_access_configuration_register(struct pcmcia_socket *s,
- unsigned int function,
+int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
conf_reg_t *reg)
{
+ struct pcmcia_socket *s;
config_t *c;
int addr;
u_char val;
- if (!s || !s->config)
+ if (!p_dev || !p_dev->function_config)
return CS_NO_CARD;
- c = &s->config[function];
-
- if (c == NULL)
- return CS_NO_CARD;
+ s = p_dev->socket;
+ c = p_dev->function_config;
if (!(c->state & CONFIG_LOCKED))
return CS_CONFIGURATION_LOCKED;
@@ -200,20 +195,12 @@ int pccard_access_configuration_register(struct pcmcia_socket *s,
break;
}
return CS_SUCCESS;
-} /* pccard_access_configuration_register */
-
-int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
- conf_reg_t *reg)
-{
- return pccard_access_configuration_register(p_dev->socket,
- p_dev->func, reg);
-}
+} /* pcmcia_access_configuration_register */
EXPORT_SYMBOL(pcmcia_access_configuration_register);
-
int pccard_get_configuration_info(struct pcmcia_socket *s,
- unsigned int function,
+ struct pcmcia_device *p_dev,
config_info_t *config)
{
config_t *c;
@@ -221,7 +208,6 @@ int pccard_get_configuration_info(struct pcmcia_socket *s,
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
- config->Function = function;
#ifdef CONFIG_CARDBUS
if (s->state & SOCKET_CARDBUS) {
@@ -235,14 +221,22 @@ int pccard_get_configuration_info(struct pcmcia_socket *s,
config->AssignedIRQ = s->irq.AssignedIRQ;
if (config->AssignedIRQ)
config->Attributes |= CONF_ENABLE_IRQ;
- config->BasePort1 = s->io[0].BasePort;
- config->NumPorts1 = s->io[0].NumPorts;
+ if (s->io[0].res) {
+ config->BasePort1 = s->io[0].res->start;
+ config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1;
+ }
}
return CS_SUCCESS;
}
#endif
- c = (s->config != NULL) ? &s->config[function] : NULL;
+ if (p_dev) {
+ c = p_dev->function_config;
+ config->Function = p_dev->func;
+ } else {
+ c = NULL;
+ config->Function = 0;
+ }
if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
config->Attributes = 0;
@@ -271,7 +265,7 @@ int pccard_get_configuration_info(struct pcmcia_socket *s,
int pcmcia_get_configuration_info(struct pcmcia_device *p_dev,
config_info_t *config)
{
- return pccard_get_configuration_info(p_dev->socket, p_dev->func,
+ return pccard_get_configuration_info(p_dev->socket, p_dev,
config);
}
EXPORT_SYMBOL(pcmcia_get_configuration_info);
@@ -317,7 +311,7 @@ EXPORT_SYMBOL(pcmcia_get_window);
* SocketState yet: I haven't seen any point for it.
*/
-int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
+int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev,
cs_status_t *status)
{
config_t *c;
@@ -334,11 +328,12 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
- c = (s->config != NULL) ? &s->config[function] : NULL;
+ c = (p_dev) ? p_dev->function_config : NULL;
+
if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
(c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
u_char reg;
- if (c->Present & PRESENT_PIN_REPLACE) {
+ if (c->CardValues & PRESENT_PIN_REPLACE) {
pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
status->CardState |=
(reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
@@ -352,7 +347,7 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
/* No PRR? Then assume we're always ready */
status->CardState |= CS_EVENT_READY_CHANGE;
}
- if (c->Present & PRESENT_EXT_STATUS) {
+ if (c->CardValues & PRESENT_EXT_STATUS) {
pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
status->CardState |=
(reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
@@ -370,11 +365,9 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
return CS_SUCCESS;
} /* pccard_get_status */
-int pcmcia_get_status(client_handle_t handle, cs_status_t *status)
+int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status)
{
- struct pcmcia_socket *s;
- s = SOCKET(handle);
- return pccard_get_status(s, handle->func, status);
+ return pccard_get_status(p_dev->socket, p_dev, status);
}
EXPORT_SYMBOL(pcmcia_get_status);
@@ -422,7 +415,8 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
config_t *c;
s = p_dev->socket;
- c = CONFIG(p_dev);
+ c = p_dev->function_config;
+
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
if (!(c->state & CONFIG_LOCKED))
@@ -454,6 +448,28 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
(mod->Attributes & CONF_VPP2_CHANGE_VALID))
return CS_BAD_VPP;
+ if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
+ pccard_io_map io_off = { 0, 0, 0, 0, 1 };
+ pccard_io_map io_on;
+ int i;
+
+ io_on.speed = io_speed;
+ for (i = 0; i < MAX_IO_WIN; i++) {
+ if (!s->io[i].res)
+ continue;
+ io_off.map = i;
+ io_on.map = i;
+
+ io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
+ io_on.start = s->io[i].res->start;
+ io_on.stop = s->io[i].res->end;
+
+ s->ops->set_io_map(s, &io_off);
+ mdelay(40);
+ s->ops->set_io_map(s, &io_on);
+ }
+ }
+
return CS_SUCCESS;
} /* modify_configuration */
EXPORT_SYMBOL(pcmcia_modify_configuration);
@@ -463,23 +479,23 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
{
pccard_io_map io = { 0, 0, 0, 0, 1 };
struct pcmcia_socket *s = p_dev->socket;
+ config_t *c = p_dev->function_config;
int i;
- if (!(p_dev->state & CLIENT_CONFIG_LOCKED))
- return CS_BAD_HANDLE;
- p_dev->state &= ~CLIENT_CONFIG_LOCKED;
-
- if (!(p_dev->state & CLIENT_STALE)) {
- config_t *c = CONFIG(p_dev);
+ if (p_dev->_locked) {
+ p_dev->_locked = 0;
if (--(s->lock_count) == 0) {
s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
s->socket.Vpp = 0;
s->socket.io_irq = 0;
s->ops->set_socket(s, &s->socket);
}
+ }
+ if (c->state & CONFIG_LOCKED) {
+ c->state &= ~CONFIG_LOCKED;
if (c->state & CONFIG_IO_REQ)
for (i = 0; i < MAX_IO_WIN; i++) {
- if (s->io[i].NumPorts == 0)
+ if (!s->io[i].res)
continue;
s->io[i].Config--;
if (s->io[i].Config != 0)
@@ -487,12 +503,10 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
io.map = i;
s->ops->set_io_map(s, &io);
}
- c->state &= ~CONFIG_LOCKED;
}
return CS_SUCCESS;
} /* pcmcia_release_configuration */
-EXPORT_SYMBOL(pcmcia_release_configuration);
/** pcmcia_release_io
@@ -503,25 +517,23 @@ EXPORT_SYMBOL(pcmcia_release_configuration);
* don't bother checking the port ranges against the current socket
* values.
*/
-int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
+static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
{
struct pcmcia_socket *s = p_dev->socket;
+ config_t *c = p_dev->function_config;
- if (!(p_dev->state & CLIENT_IO_REQ))
+ if (!p_dev->_io )
return CS_BAD_HANDLE;
- p_dev->state &= ~CLIENT_IO_REQ;
-
- if (!(p_dev->state & CLIENT_STALE)) {
- config_t *c = CONFIG(p_dev);
- if (c->state & CONFIG_LOCKED)
- return CS_CONFIGURATION_LOCKED;
- if ((c->io.BasePort1 != req->BasePort1) ||
- (c->io.NumPorts1 != req->NumPorts1) ||
- (c->io.BasePort2 != req->BasePort2) ||
- (c->io.NumPorts2 != req->NumPorts2))
- return CS_BAD_ARGS;
- c->state &= ~CONFIG_IO_REQ;
- }
+
+ p_dev->_io = 0;
+
+ if ((c->io.BasePort1 != req->BasePort1) ||
+ (c->io.NumPorts1 != req->NumPorts1) ||
+ (c->io.BasePort2 != req->BasePort2) ||
+ (c->io.NumPorts2 != req->NumPorts2))
+ return CS_BAD_ARGS;
+
+ c->state &= ~CONFIG_IO_REQ;
release_io_space(s, req->BasePort1, req->NumPorts1);
if (req->NumPorts2)
@@ -529,28 +541,26 @@ int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
return CS_SUCCESS;
} /* pcmcia_release_io */
-EXPORT_SYMBOL(pcmcia_release_io);
-int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
+static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
{
struct pcmcia_socket *s = p_dev->socket;
- if (!(p_dev->state & CLIENT_IRQ_REQ))
+ config_t *c= p_dev->function_config;
+
+ if (!p_dev->_irq)
return CS_BAD_HANDLE;
- p_dev->state &= ~CLIENT_IRQ_REQ;
-
- if (!(p_dev->state & CLIENT_STALE)) {
- config_t *c = CONFIG(p_dev);
- if (c->state & CONFIG_LOCKED)
- return CS_CONFIGURATION_LOCKED;
- if (c->irq.Attributes != req->Attributes)
- return CS_BAD_ATTRIBUTE;
- if (s->irq.AssignedIRQ != req->AssignedIRQ)
- return CS_BAD_IRQ;
- if (--s->irq.Config == 0) {
- c->state &= ~CONFIG_IRQ_REQ;
- s->irq.AssignedIRQ = 0;
- }
+ p_dev->_irq = 0;
+
+ if (c->state & CONFIG_LOCKED)
+ return CS_CONFIGURATION_LOCKED;
+ if (c->irq.Attributes != req->Attributes)
+ return CS_BAD_ATTRIBUTE;
+ if (s->irq.AssignedIRQ != req->AssignedIRQ)
+ return CS_BAD_IRQ;
+ if (--s->irq.Config == 0) {
+ c->state &= ~CONFIG_IRQ_REQ;
+ s->irq.AssignedIRQ = 0;
}
if (req->Attributes & IRQ_HANDLE_PRESENT) {
@@ -563,7 +573,6 @@ int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
return CS_SUCCESS;
} /* pcmcia_release_irq */
-EXPORT_SYMBOL(pcmcia_release_irq);
int pcmcia_release_window(window_handle_t win)
@@ -573,7 +582,7 @@ int pcmcia_release_window(window_handle_t win)
if ((win == NULL) || (win->magic != WINDOW_MAGIC))
return CS_BAD_HANDLE;
s = win->sock;
- if (!(win->handle->state & CLIENT_WIN_REQ(win->index)))
+ if (!(win->handle->_win & CLIENT_WIN_REQ(win->index)))
return CS_BAD_HANDLE;
/* Shut down memory window */
@@ -587,7 +596,7 @@ int pcmcia_release_window(window_handle_t win)
kfree(win->ctl.res);
win->ctl.res = NULL;
}
- win->handle->state &= ~CLIENT_WIN_REQ(win->index);
+ win->handle->_win &= ~CLIENT_WIN_REQ(win->index);
win->magic = 0;
@@ -610,16 +619,12 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
if (req->IntType & INT_CARDBUS)
return CS_UNSUPPORTED_MODE;
- c = CONFIG(p_dev);
+ c = p_dev->function_config;
if (c->state & CONFIG_LOCKED)
return CS_CONFIGURATION_LOCKED;
/* Do power control. We don't allow changes in Vcc. */
- if (s->socket.Vcc != req->Vcc)
- return CS_BAD_VCC;
- if (req->Vpp1 != req->Vpp2)
- return CS_BAD_VPP;
- s->socket.Vpp = req->Vpp1;
+ s->socket.Vpp = req->Vpp;
if (s->ops->set_socket(s, &s->socket))
return CS_BAD_VPP;
@@ -643,7 +648,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
/* Set up CIS configuration registers */
base = c->ConfigBase = req->ConfigBase;
- c->Present = c->CardValues = req->Present;
+ c->CardValues = req->Present;
if (req->Present & PRESENT_COPY) {
c->Copy = req->Copy;
pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
@@ -690,10 +695,10 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
if (c->state & CONFIG_IO_REQ) {
iomap.speed = io_speed;
for (i = 0; i < MAX_IO_WIN; i++)
- if (s->io[i].NumPorts != 0) {
+ if (s->io[i].res) {
iomap.map = i;
iomap.flags = MAP_ACTIVE;
- switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) {
+ switch (s->io[i].res->flags & IO_DATA_PATH_WIDTH) {
case IO_DATA_PATH_WIDTH_16:
iomap.flags |= MAP_16BIT; break;
case IO_DATA_PATH_WIDTH_AUTO:
@@ -701,15 +706,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
default:
break;
}
- iomap.start = s->io[i].BasePort;
- iomap.stop = iomap.start + s->io[i].NumPorts - 1;
+ iomap.start = s->io[i].res->start;
+ iomap.stop = s->io[i].res->end;
s->ops->set_io_map(s, &iomap);
s->io[i].Config++;
}
}
c->state |= CONFIG_LOCKED;
- p_dev->state |= CLIENT_CONFIG_LOCKED;
+ p_dev->_locked = 1;
return CS_SUCCESS;
} /* pcmcia_request_configuration */
EXPORT_SYMBOL(pcmcia_request_configuration);
@@ -730,7 +735,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
if (!req)
return CS_UNSUPPORTED_MODE;
- c = CONFIG(p_dev);
+ c = p_dev->function_config;
if (c->state & CONFIG_LOCKED)
return CS_CONFIGURATION_LOCKED;
if (c->state & CONFIG_IO_REQ)
@@ -755,7 +760,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
c->io = *req;
c->state |= CONFIG_IO_REQ;
- p_dev->state |= CLIENT_IO_REQ;
+ p_dev->_io = 1;
return CS_SUCCESS;
} /* pcmcia_request_io */
EXPORT_SYMBOL(pcmcia_request_io);
@@ -786,7 +791,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
- c = CONFIG(p_dev);
+ c = p_dev->function_config;
if (c->state & CONFIG_LOCKED)
return CS_CONFIGURATION_LOCKED;
if (c->state & CONFIG_IRQ_REQ)
@@ -851,7 +856,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
s->irq.Config++;
c->state |= CONFIG_IRQ_REQ;
- p_dev->state |= CLIENT_IRQ_REQ;
+ p_dev->_irq = 1;
#ifdef CONFIG_PCMCIA_PROBE
pcmcia_used_irq[irq]++;
@@ -911,7 +916,7 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
if (!win->ctl.res)
return CS_IN_USE;
}
- (*p_dev)->state |= CLIENT_WIN_REQ(w);
+ (*p_dev)->_win |= CLIENT_WIN_REQ(w);
/* Configure the socket controller */
win->ctl.map = w+1;
@@ -941,3 +946,12 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
return CS_SUCCESS;
} /* pcmcia_request_window */
EXPORT_SYMBOL(pcmcia_request_window);
+
+void pcmcia_disable_device(struct pcmcia_device *p_dev) {
+ pcmcia_release_configuration(p_dev);
+ pcmcia_release_io(p_dev, &p_dev->io);
+ pcmcia_release_irq(p_dev, &p_dev->irq);
+ if (&p_dev->win)
+ pcmcia_release_window(p_dev->win);
+}
+EXPORT_SYMBOL(pcmcia_disable_device);
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index f2789afb22b..247ab837f84 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -8,7 +8,6 @@
*/
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
@@ -590,7 +589,7 @@ static int pd6729_check_irq(int irq, int flags)
return 0;
}
-static u_int __init pd6729_isa_scan(void)
+static u_int __devinit pd6729_isa_scan(void)
{
u_int mask0, mask = 0;
int i;
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index fd364736895..b7b9e149c5b 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -26,14 +26,6 @@
#include "soc_common.h"
#define NO_KEEP_VS 0x0001
-
-/* PCMCIA to Scoop linkage
-
- There is no easy way to link multiple scoop devices into one
- single entity for the pxa2xx_pcmcia device so this structure
- is used which is setup by the platform code
-*/
-struct scoop_pcmcia_config *platform_scoop_config;
#define SCOOP_DEV platform_scoop_config->devs
static void sharpsl_pcmcia_init_reset(struct soc_pcmcia_socket *skt)
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 51460936983..81dfc2cac2b 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -12,7 +12,6 @@
* (C) 1999 David A. Hinds
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -22,6 +21,8 @@
#include "cs_internal.h"
+#ifdef CONFIG_PCMCIA_IOCTL
+
#ifdef CONFIG_PCMCIA_PROBE
static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
@@ -98,6 +99,8 @@ int pcmcia_adjust_resource_info(adjust_t *adj)
}
EXPORT_SYMBOL(pcmcia_adjust_resource_info);
+#endif
+
int pcmcia_validate_mem(struct pcmcia_socket *s)
{
if (s->resource_ops->validate_mem)
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 5301ac60358..0f8b157c971 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -12,7 +12,6 @@
* (C) 1999 David A. Hinds
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -61,7 +60,7 @@ struct socket_data {
unsigned int rsrc_mem_probe;
};
-static DECLARE_MUTEX(rsrc_sem);
+static DEFINE_MUTEX(rsrc_mutex);
#define MEM_PROBE_LOW (1 << 0)
#define MEM_PROBE_HIGH (1 << 1)
@@ -484,7 +483,7 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
/*
- * Locking note: Must be called with skt_sem held!
+ * Locking note: Must be called with skt_mutex held!
*/
static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
{
@@ -495,7 +494,7 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
if (!probe_mem)
return 0;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
if (s->features & SS_CAP_PAGE_REGS)
probe_mask = MEM_PROBE_HIGH;
@@ -507,7 +506,7 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
s_data->rsrc_mem_probe |= probe_mask;
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return ret;
}
@@ -585,7 +584,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
struct socket_data *s_data = s->resource_data;
int ret = -ENOMEM;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
unsigned long start = m->base;
unsigned long end = m->base + m->num - 1;
@@ -596,7 +595,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
ret = adjust_resource(res, r_start, r_end - r_start + 1);
break;
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return ret;
}
@@ -630,7 +629,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
data.offset = base & data.mask;
data.map = &s_data->io_db;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
#ifdef CONFIG_PCI
if (s->cb_dev) {
ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
@@ -639,7 +638,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
#endif
ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
1, pcmcia_align, &data);
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
if (ret != 0) {
kfree(res);
@@ -672,7 +671,7 @@ static struct resource * nonstatic_find_mem_region(u_long base, u_long num,
min = 0x100000UL + base;
}
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
#ifdef CONFIG_PCI
if (s->cb_dev) {
ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
@@ -682,7 +681,7 @@ static struct resource * nonstatic_find_mem_region(u_long base, u_long num,
#endif
ret = allocate_resource(&iomem_resource, res, num, min,
max, 1, pcmcia_align, &data);
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
if (ret == 0 || low)
break;
low = 1;
@@ -705,7 +704,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned
if (end < start)
return -EINVAL;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
switch (action) {
case ADD_MANAGED_RESOURCE:
ret = add_interval(&data->mem_db, start, size);
@@ -723,7 +722,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned
default:
ret = -EINVAL;
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return ret;
}
@@ -741,7 +740,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
if (end > IO_SPACE_LIMIT)
return -EINVAL;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
switch (action) {
case ADD_MANAGED_RESOURCE:
if (add_interval(&data->io_db, start, size) != 0) {
@@ -760,7 +759,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
ret = -EINVAL;
break;
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return ret;
}
@@ -867,7 +866,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
struct socket_data *data = s->resource_data;
struct resource_map *p, *q;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
for (p = data->mem_db.next; p != &data->mem_db; p = q) {
q = p->next;
kfree(p);
@@ -876,7 +875,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
q = p->next;
kfree(p);
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
}
@@ -901,7 +900,7 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf)
struct resource_map *p;
ssize_t ret = 0;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
data = s->resource_data;
for (p = data->io_db.next; p != &data->io_db; p = p->next) {
@@ -913,7 +912,7 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf)
((unsigned long) p->base + p->num - 1));
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return (ret);
}
@@ -953,7 +952,7 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf)
struct resource_map *p;
ssize_t ret = 0;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
data = s->resource_data;
for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
@@ -965,7 +964,7 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf)
((unsigned long) p->base + p->num - 1));
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return (ret);
}
diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c
index 2b3c2895b43..eb89928f233 100644
--- a/drivers/pcmcia/sa1100_cerf.c
+++ b/drivers/pcmcia/sa1100_cerf.c
@@ -5,7 +5,6 @@
* Based off the Assabet.
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 5ab1cdef7c4..c5d7476da47 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -12,7 +12,6 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/string.h>
#include <linux/major.h>
#include <linux/errno.h>
@@ -25,6 +24,7 @@
#include <linux/pm.h>
#include <linux/pci.h>
#include <linux/device.h>
+#include <linux/mutex.h>
#include <asm/system.h>
#include <asm/irq.h>
@@ -183,7 +183,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf,
s->resource_setup_done = 1;
spin_unlock_irqrestore(&s->lock, flags);
- down(&s->skt_sem);
+ mutex_lock(&s->skt_mutex);
if ((s->callback) &&
(s->state & SOCKET_PRESENT) &&
!(s->state & SOCKET_CARDBUS)) {
@@ -192,7 +192,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf,
module_put(s->callback->owner);
}
}
- up(&s->skt_sem);
+ mutex_unlock(&s->skt_mutex);
return count;
}
@@ -322,7 +322,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz
kfree(cis);
if (!ret) {
- down(&s->skt_sem);
+ mutex_lock(&s->skt_mutex);
if ((s->callback) && (s->state & SOCKET_PRESENT) &&
!(s->state & SOCKET_CARDBUS)) {
if (try_module_get(s->callback->owner)) {
@@ -330,7 +330,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz
module_put(s->callback->owner);
}
}
- up(&s->skt_sem);
+ mutex_unlock(&s->skt_mutex);
}
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index d5b4ff74462..7a3d1b8e16b 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -30,7 +30,6 @@
#ifndef _LINUX_TI113X_H
#define _LINUX_TI113X_H
-#include <linux/config.h>
/* Register definitions for TI 113X PCI-to-CardBus bridges */
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index 0574efd7828..459e6e1946f 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -634,7 +634,7 @@ static void vrc4171_remove_sockets(void)
static int __devinit vrc4171_card_setup(char *options)
{
if (options == NULL || *options == '\0')
- return 0;
+ return 1;
if (strncmp(options, "irq:", 4) == 0) {
int irq;
@@ -644,7 +644,7 @@ static int __devinit vrc4171_card_setup(char *options)
vrc4171_irq = irq;
if (*options != ',')
- return 0;
+ return 1;
options++;
}
@@ -663,10 +663,10 @@ static int __devinit vrc4171_card_setup(char *options)
}
if (*options != ',')
- return 0;
+ return 1;
options++;
} else
- return 0;
+ return 1;
}
@@ -688,7 +688,7 @@ static int __devinit vrc4171_card_setup(char *options)
}
if (*options != ',')
- return 0;
+ return 1;
options++;
if (strncmp(options, "memnoprobe", 10) == 0)
@@ -700,7 +700,7 @@ static int __devinit vrc4171_card_setup(char *options)
}
}
- return 0;
+ return 1;
}
__setup("vrc4171_card=", vrc4171_card_setup);
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index 57f38dba0a4..6004196f7cc 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -516,7 +516,7 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev,
static int __devinit vrc4173_cardu_setup(char *options)
{
if (options == NULL || *options == '\0')
- return 0;
+ return 1;
if (strncmp(options, "cardu1:", 7) == 0) {
options += 7;
@@ -527,9 +527,9 @@ static int __devinit vrc4173_cardu_setup(char *options)
}
if (*options != ',')
- return 0;
+ return 1;
} else
- return 0;
+ return 1;
}
if (strncmp(options, "cardu2:", 7) == 0) {
@@ -538,7 +538,7 @@ static int __devinit vrc4173_cardu_setup(char *options)
cardu_sockets[CARDU2].noprobe = 1;
}
- return 0;
+ return 1;
}
__setup("vrc4173_cardu=", vrc4173_cardu_setup);
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index b68eef25161..bb19c64073c 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -47,7 +47,7 @@ static void card_remove(struct pnp_dev * dev)
{
dev->card_link = NULL;
}
-
+
static void card_remove_first(struct pnp_dev * dev)
{
struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver);
@@ -361,7 +361,7 @@ static int card_resume(struct pnp_dev *dev)
int pnp_register_card_driver(struct pnp_card_driver * drv)
{
- int count;
+ int error;
struct list_head *pos, *temp;
drv->link.name = drv->name;
@@ -372,21 +372,19 @@ int pnp_register_card_driver(struct pnp_card_driver * drv)
drv->link.suspend = drv->suspend ? card_suspend : NULL;
drv->link.resume = drv->resume ? card_resume : NULL;
- count = pnp_register_driver(&drv->link);
- if (count < 0)
- return count;
+ error = pnp_register_driver(&drv->link);
+ if (error < 0)
+ return error;
spin_lock(&pnp_lock);
list_add_tail(&drv->global_list, &pnp_card_drivers);
spin_unlock(&pnp_lock);
- count = 0;
-
list_for_each_safe(pos,temp,&pnp_cards){
struct pnp_card *card = list_entry(pos, struct pnp_card, global_list);
- count += card_probe(card,drv);
+ card_probe(card,drv);
}
- return count;
+ return 0;
}
/**
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index 7cafacdd12b..e54c1538319 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -201,31 +201,14 @@ struct bus_type pnp_bus_type = {
.resume = pnp_bus_resume,
};
-
-static int count_devices(struct device * dev, void * c)
-{
- int * count = c;
- (*count)++;
- return 0;
-}
-
int pnp_register_driver(struct pnp_driver *drv)
{
- int count;
-
pnp_dbg("the driver '%s' has been registered", drv->name);
drv->driver.name = drv->name;
drv->driver.bus = &pnp_bus_type;
- count = driver_register(&drv->driver);
-
- /* get the number of initial matches */
- if (count >= 0){
- count = 0;
- driver_for_each_device(&drv->driver, NULL, &count, count_devices);
- }
- return count;
+ return driver_register(&drv->driver);
}
void pnp_unregister_driver(struct pnp_driver *drv)
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index c4256aa32bc..6fff109bdab 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -479,7 +479,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
int pnp_start_dev(struct pnp_dev *dev)
{
if (!pnp_can_write(dev)) {
- pnp_info("Device %s does not supported activation.", dev->dev.bus_id);
+ pnp_info("Device %s does not support activation.", dev->dev.bus_id);
return -EINVAL;
}
@@ -503,7 +503,7 @@ int pnp_start_dev(struct pnp_dev *dev)
int pnp_stop_dev(struct pnp_dev *dev)
{
if (!pnp_can_disable(dev)) {
- pnp_info("Device %s does not supported disabling.", dev->dev.bus_id);
+ pnp_info("Device %s does not support disabling.", dev->dev.bus_id);
return -EINVAL;
}
if (dev->protocol->disable(dev)<0) {
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 407b4eaddcb..3a4a644c268 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -36,13 +36,13 @@ static int irq_flags(int triggering, int polarity)
{
int flag;
if (triggering == ACPI_LEVEL_SENSITIVE) {
- if(polarity == ACPI_ACTIVE_LOW)
+ if (polarity == ACPI_ACTIVE_LOW)
flag = IORESOURCE_IRQ_LOWLEVEL;
else
flag = IORESOURCE_IRQ_HIGHLEVEL;
}
else {
- if(polarity == ACPI_ACTIVE_LOW)
+ if (polarity == ACPI_ACTIVE_LOW)
flag = IORESOURCE_IRQ_LOWEDGE;
else
flag = IORESOURCE_IRQ_HIGHEDGE;
@@ -57,7 +57,7 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity)
*triggering = ACPI_LEVEL_SENSITIVE;
*polarity = ACPI_ACTIVE_LOW;
break;
- case IORESOURCE_IRQ_HIGHLEVEL:
+ case IORESOURCE_IRQ_HIGHLEVEL:
*triggering = ACPI_LEVEL_SENSITIVE;
*polarity = ACPI_ACTIVE_HIGH;
break;
@@ -73,7 +73,7 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity)
}
static void
-pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi,
+pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi,
int triggering, int polarity)
{
int i = 0;
@@ -101,7 +101,7 @@ pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi,
}
static void
-pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma)
+pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma)
{
int i = 0;
while (i < PNP_MAX_DMA &&
@@ -119,8 +119,8 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma)
}
static void
-pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res,
- u32 io, u32 len)
+pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
+ u64 io, u64 len)
{
int i = 0;
while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
@@ -138,7 +138,7 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res,
}
static void
-pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res,
+pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
u64 mem, u64 len)
{
int i = 0;
@@ -156,11 +156,32 @@ pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res,
}
}
+static void
+pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table,
+ struct acpi_resource *res)
+{
+ struct acpi_resource_address64 addr, *p = &addr;
+ acpi_status status;
+
+ status = acpi_resource_to_address64(res, p);
+ if (!ACPI_SUCCESS(status)) {
+ pnp_warn("PnPACPI: failed to convert resource type %d",
+ res->type);
+ return;
+ }
+
+ if (p->resource_type == ACPI_MEMORY_RANGE)
+ pnpacpi_parse_allocated_memresource(res_table,
+ p->minimum, p->address_length);
+ else if (p->resource_type == ACPI_IO_RANGE)
+ pnpacpi_parse_allocated_ioresource(res_table,
+ p->minimum, p->address_length);
+}
static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
void *data)
{
- struct pnp_resource_table * res_table = (struct pnp_resource_table *)data;
+ struct pnp_resource_table *res_table = (struct pnp_resource_table *)data;
int i;
switch (res->type) {
@@ -221,19 +242,9 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
res->data.fixed_memory32.address_length);
break;
case ACPI_RESOURCE_TYPE_ADDRESS16:
- pnpacpi_parse_allocated_memresource(res_table,
- res->data.address16.minimum,
- res->data.address16.address_length);
- break;
case ACPI_RESOURCE_TYPE_ADDRESS32:
- pnpacpi_parse_allocated_memresource(res_table,
- res->data.address32.minimum,
- res->data.address32.address_length);
- break;
case ACPI_RESOURCE_TYPE_ADDRESS64:
- pnpacpi_parse_allocated_memresource(res_table,
- res->data.address64.minimum,
- res->data.address64.address_length);
+ pnpacpi_parse_allocated_address_space(res_table, res);
break;
case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
@@ -255,11 +266,11 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
pnp_warn("PnPACPI: unknown resource type %d", res->type);
return AE_ERROR;
}
-
+
return AE_OK;
}
-acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table * res)
+acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table *res)
{
/* Blank the resource table values */
pnp_init_resource_table(res);
@@ -317,17 +328,17 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso
pnp_err("Invalid DMA transfer type");
}
- pnp_register_dma_resource(option,dma);
+ pnp_register_dma_resource(option, dma);
return;
}
-
+
static void pnpacpi_parse_irq_option(struct pnp_option *option,
struct acpi_resource_irq *p)
{
int i;
- struct pnp_irq * irq;
-
+ struct pnp_irq *irq;
+
if (p->interrupt_count == 0)
return;
irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
@@ -347,7 +358,7 @@ static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
struct acpi_resource_extended_irq *p)
{
int i;
- struct pnp_irq * irq;
+ struct pnp_irq *irq;
if (p->interrupt_count == 0)
return;
@@ -368,7 +379,7 @@ static void
pnpacpi_parse_port_option(struct pnp_option *option,
struct acpi_resource_io *io)
{
- struct pnp_port * port;
+ struct pnp_port *port;
if (io->address_length == 0)
return;
@@ -381,7 +392,7 @@ pnpacpi_parse_port_option(struct pnp_option *option,
port->size = io->address_length;
port->flags = ACPI_DECODE_16 == io->io_decode ?
PNP_PORT_FLAG_16BITADDR : 0;
- pnp_register_port_resource(option,port);
+ pnp_register_port_resource(option, port);
return;
}
@@ -389,7 +400,7 @@ static void
pnpacpi_parse_fixed_port_option(struct pnp_option *option,
struct acpi_resource_fixed_io *io)
{
- struct pnp_port * port;
+ struct pnp_port *port;
if (io->address_length == 0)
return;
@@ -400,7 +411,7 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option,
port->size = io->address_length;
port->align = 0;
port->flags = PNP_PORT_FLAG_FIXED;
- pnp_register_port_resource(option,port);
+ pnp_register_port_resource(option, port);
return;
}
@@ -408,7 +419,7 @@ static void
pnpacpi_parse_mem24_option(struct pnp_option *option,
struct acpi_resource_memory24 *p)
{
- struct pnp_mem * mem;
+ struct pnp_mem *mem;
if (p->address_length == 0)
return;
@@ -423,7 +434,7 @@ pnpacpi_parse_mem24_option(struct pnp_option *option,
mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
IORESOURCE_MEM_WRITEABLE : 0;
- pnp_register_mem_resource(option,mem);
+ pnp_register_mem_resource(option, mem);
return;
}
@@ -431,7 +442,7 @@ static void
pnpacpi_parse_mem32_option(struct pnp_option *option,
struct acpi_resource_memory32 *p)
{
- struct pnp_mem * mem;
+ struct pnp_mem *mem;
if (p->address_length == 0)
return;
@@ -446,7 +457,7 @@ pnpacpi_parse_mem32_option(struct pnp_option *option,
mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
IORESOURCE_MEM_WRITEABLE : 0;
- pnp_register_mem_resource(option,mem);
+ pnp_register_mem_resource(option, mem);
return;
}
@@ -454,7 +465,7 @@ static void
pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
struct acpi_resource_fixed_memory32 *p)
{
- struct pnp_mem * mem;
+ struct pnp_mem *mem;
if (p->address_length == 0)
return;
@@ -468,7 +479,7 @@ pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
IORESOURCE_MEM_WRITEABLE : 0;
- pnp_register_mem_resource(option,mem);
+ pnp_register_mem_resource(option, mem);
return;
}
@@ -477,8 +488,8 @@ pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r)
{
struct acpi_resource_address64 addr, *p = &addr;
acpi_status status;
- struct pnp_mem * mem;
- struct pnp_port * port;
+ struct pnp_mem *mem;
+ struct pnp_port *port;
status = acpi_resource_to_address64(r, p);
if (!ACPI_SUCCESS(status)) {
@@ -498,7 +509,7 @@ pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r)
mem->align = 0;
mem->flags = (p->info.mem.write_protect ==
ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0;
- pnp_register_mem_resource(option,mem);
+ pnp_register_mem_resource(option, mem);
} else if (p->resource_type == ACPI_IO_RANGE) {
port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
@@ -507,7 +518,7 @@ pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r)
port->size = p->address_length;
port->align = 0;
port->flags = PNP_PORT_FLAG_FIXED;
- pnp_register_port_resource(option,port);
+ pnp_register_port_resource(option, port);
}
}
@@ -531,7 +542,7 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
break;
case ACPI_RESOURCE_TYPE_DMA:
- pnpacpi_parse_dma_option(option, &res->data.dma);
+ pnpacpi_parse_dma_option(option, &res->data.dma);
break;
case ACPI_RESOURCE_TYPE_START_DEPENDENT:
@@ -539,7 +550,7 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
case ACPI_GOOD_CONFIGURATION:
priority = PNP_RES_PRIORITY_PREFERRED;
break;
-
+
case ACPI_ACCEPTABLE_CONFIGURATION:
priority = PNP_RES_PRIORITY_ACCEPTABLE;
break;
@@ -555,7 +566,7 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
option = pnp_register_dependent_option(dev, priority);
if (!option)
return AE_ERROR;
- parse_data->option = option;
+ parse_data->option = option;
break;
case ACPI_RESOURCE_TYPE_END_DEPENDENT:
@@ -615,7 +626,7 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
pnp_warn("PnPACPI: unknown resource type %d", res->type);
return AE_ERROR;
}
-
+
return AE_OK;
}
@@ -636,13 +647,8 @@ acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle,
return status;
}
-/*
- * Set resource
- */
-static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
- void *data)
+static int pnpacpi_supported_resource(struct acpi_resource *res)
{
- int *res_cnt = (int *)data;
switch (res->type) {
case ACPI_RESOURCE_TYPE_IRQ:
case ACPI_RESOURCE_TYPE_DMA:
@@ -655,43 +661,32 @@ static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
case ACPI_RESOURCE_TYPE_ADDRESS32:
case ACPI_RESOURCE_TYPE_ADDRESS64:
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
- (*res_cnt) ++;
- case ACPI_RESOURCE_TYPE_START_DEPENDENT:
- case ACPI_RESOURCE_TYPE_END_DEPENDENT:
- case ACPI_RESOURCE_TYPE_VENDOR:
- case ACPI_RESOURCE_TYPE_END_TAG:
- case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
- default:
- return AE_OK;
+ return 1;
}
- return AE_OK;
+ return 0;
}
-static acpi_status pnpacpi_type_resources(struct acpi_resource *res,
+/*
+ * Set resource
+ */
+static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
void *data)
{
- struct acpi_resource **resource = (struct acpi_resource **)data;
- switch (res->type) {
- case ACPI_RESOURCE_TYPE_IRQ:
- case ACPI_RESOURCE_TYPE_DMA:
- case ACPI_RESOURCE_TYPE_IO:
- case ACPI_RESOURCE_TYPE_FIXED_IO:
- case ACPI_RESOURCE_TYPE_MEMORY24:
- case ACPI_RESOURCE_TYPE_MEMORY32:
- case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
- case ACPI_RESOURCE_TYPE_ADDRESS16:
- case ACPI_RESOURCE_TYPE_ADDRESS32:
- case ACPI_RESOURCE_TYPE_ADDRESS64:
- case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ int *res_cnt = (int *)data;
+
+ if (pnpacpi_supported_resource(res))
+ (*res_cnt)++;
+ return AE_OK;
+}
+
+static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
+{
+ struct acpi_resource **resource = (struct acpi_resource **)data;
+
+ if (pnpacpi_supported_resource(res)) {
(*resource)->type = res->type;
+ (*resource)->length = sizeof(struct acpi_resource);
(*resource)++;
- case ACPI_RESOURCE_TYPE_START_DEPENDENT:
- case ACPI_RESOURCE_TYPE_END_DEPENDENT:
- case ACPI_RESOURCE_TYPE_VENDOR:
- case ACPI_RESOURCE_TYPE_END_TAG:
- case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
- default:
- return AE_OK;
}
return AE_OK;
@@ -735,11 +730,8 @@ static void pnpacpi_encode_irq(struct acpi_resource *resource,
struct resource *p)
{
int triggering, polarity;
-
- decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering,
- &polarity);
- resource->type = ACPI_RESOURCE_TYPE_IRQ;
- resource->length = sizeof(struct acpi_resource);
+
+ decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
resource->data.irq.triggering = triggering;
resource->data.irq.polarity = polarity;
if (triggering == ACPI_EDGE_SENSITIVE)
@@ -754,11 +746,8 @@ static void pnpacpi_encode_ext_irq(struct acpi_resource *resource,
struct resource *p)
{
int triggering, polarity;
-
- decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering,
- &polarity);
- resource->type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
- resource->length = sizeof(struct acpi_resource);
+
+ decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
resource->data.extended_irq.producer_consumer = ACPI_CONSUMER;
resource->data.extended_irq.triggering = triggering;
resource->data.extended_irq.polarity = polarity;
@@ -773,8 +762,6 @@ static void pnpacpi_encode_ext_irq(struct acpi_resource *resource,
static void pnpacpi_encode_dma(struct acpi_resource *resource,
struct resource *p)
{
- resource->type = ACPI_RESOURCE_TYPE_DMA;
- resource->length = sizeof(struct acpi_resource);
/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
if (p->flags & IORESOURCE_DMA_COMPATIBLE)
resource->data.dma.type = ACPI_COMPATIBILITY;
@@ -798,8 +785,6 @@ static void pnpacpi_encode_dma(struct acpi_resource *resource,
static void pnpacpi_encode_io(struct acpi_resource *resource,
struct resource *p)
{
- resource->type = ACPI_RESOURCE_TYPE_IO;
- resource->length = sizeof(struct acpi_resource);
/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR)?
ACPI_DECODE_16 : ACPI_DECODE_10;
@@ -812,8 +797,6 @@ static void pnpacpi_encode_io(struct acpi_resource *resource,
static void pnpacpi_encode_fixed_io(struct acpi_resource *resource,
struct resource *p)
{
- resource->type = ACPI_RESOURCE_TYPE_FIXED_IO;
- resource->length = sizeof(struct acpi_resource);
resource->data.fixed_io.address = p->start;
resource->data.fixed_io.address_length = p->end - p->start + 1;
}
@@ -821,8 +804,6 @@ static void pnpacpi_encode_fixed_io(struct acpi_resource *resource,
static void pnpacpi_encode_mem24(struct acpi_resource *resource,
struct resource *p)
{
- resource->type = ACPI_RESOURCE_TYPE_MEMORY24;
- resource->length = sizeof(struct acpi_resource);
/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
resource->data.memory24.write_protect =
(p->flags & IORESOURCE_MEM_WRITEABLE) ?
@@ -836,8 +817,6 @@ static void pnpacpi_encode_mem24(struct acpi_resource *resource,
static void pnpacpi_encode_mem32(struct acpi_resource *resource,
struct resource *p)
{
- resource->type = ACPI_RESOURCE_TYPE_MEMORY32;
- resource->length = sizeof(struct acpi_resource);
resource->data.memory32.write_protect =
(p->flags & IORESOURCE_MEM_WRITEABLE) ?
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
@@ -850,8 +829,6 @@ static void pnpacpi_encode_mem32(struct acpi_resource *resource,
static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource,
struct resource *p)
{
- resource->type = ACPI_RESOURCE_TYPE_FIXED_MEMORY32;
- resource->length = sizeof(struct acpi_resource);
resource->data.fixed_memory32.write_protect =
(p->flags & IORESOURCE_MEM_WRITEABLE) ?
ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
@@ -882,37 +859,37 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
pnp_dbg("Encode dma");
pnpacpi_encode_dma(resource,
&res_table->dma_resource[dma]);
- dma ++;
+ dma++;
break;
case ACPI_RESOURCE_TYPE_IO:
pnp_dbg("Encode io");
pnpacpi_encode_io(resource,
&res_table->port_resource[port]);
- port ++;
+ port++;
break;
case ACPI_RESOURCE_TYPE_FIXED_IO:
pnp_dbg("Encode fixed io");
pnpacpi_encode_fixed_io(resource,
&res_table->port_resource[port]);
- port ++;
+ port++;
break;
case ACPI_RESOURCE_TYPE_MEMORY24:
pnp_dbg("Encode mem24");
pnpacpi_encode_mem24(resource,
&res_table->mem_resource[mem]);
- mem ++;
+ mem++;
break;
case ACPI_RESOURCE_TYPE_MEMORY32:
pnp_dbg("Encode mem32");
pnpacpi_encode_mem32(resource,
&res_table->mem_resource[mem]);
- mem ++;
+ mem++;
break;
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
pnp_dbg("Encode fixed mem32");
pnpacpi_encode_fixed_mem32(resource,
&res_table->mem_resource[mem]);
- mem ++;
+ mem++;
break;
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
pnp_dbg("Encode ext irq");
@@ -933,8 +910,8 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
pnp_warn("unknown resource type %d", resource->type);
return -EINVAL;
}
- resource ++;
- i ++;
+ resource++;
+ i++;
}
return 0;
}
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
new file mode 100644
index 00000000000..65d090dbef4
--- /dev/null
+++ b/drivers/rtc/Kconfig
@@ -0,0 +1,175 @@
+\#
+# RTC class/drivers configuration
+#
+
+menu "Real Time Clock"
+
+config RTC_LIB
+ tristate
+
+config RTC_CLASS
+ tristate "RTC class"
+ depends on EXPERIMENTAL
+ default n
+ select RTC_LIB
+ help
+ Generic RTC class support. If you say yes here, you will
+ be allowed to plug one or more RTCs to your system. You will
+ probably want to enable one of more of the interfaces below.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-class.
+
+config RTC_HCTOSYS
+ bool "Set system time from RTC on startup"
+ depends on RTC_CLASS = y
+ default y
+ help
+ If you say yes here, the system time will be set using
+ the value read from the specified RTC device. This is useful
+ in order to avoid unnecessary fschk runs.
+
+config RTC_HCTOSYS_DEVICE
+ string "The RTC to read the time from"
+ depends on RTC_HCTOSYS = y
+ default "rtc0"
+ help
+ The RTC device that will be used as the source for
+ the system time, usually rtc0.
+
+comment "RTC interfaces"
+ depends on RTC_CLASS
+
+config RTC_INTF_SYSFS
+ tristate "sysfs"
+ depends on RTC_CLASS && SYSFS
+ default RTC_CLASS
+ help
+ Say yes here if you want to use your RTC using the sysfs
+ interface, /sys/class/rtc/rtcX .
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-sysfs.
+
+config RTC_INTF_PROC
+ tristate "proc"
+ depends on RTC_CLASS && PROC_FS
+ default RTC_CLASS
+ help
+ Say yes here if you want to use your RTC using the proc
+ interface, /proc/driver/rtc .
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-proc.
+
+config RTC_INTF_DEV
+ tristate "dev"
+ depends on RTC_CLASS
+ default RTC_CLASS
+ help
+ Say yes here if you want to use your RTC using the dev
+ interface, /dev/rtc .
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-dev.
+
+comment "RTC drivers"
+ depends on RTC_CLASS
+
+config RTC_DRV_X1205
+ tristate "Xicor/Intersil X1205"
+ depends on RTC_CLASS && I2C
+ help
+ If you say yes here you get support for the
+ Xicor/Intersil X1205 RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-x1205.
+
+config RTC_DRV_DS1672
+ tristate "Dallas/Maxim DS1672"
+ depends on RTC_CLASS && I2C
+ help
+ If you say yes here you get support for the
+ Dallas/Maxim DS1672 timekeeping chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ds1672.
+
+config RTC_DRV_PCF8563
+ tristate "Philips PCF8563/Epson RTC8564"
+ depends on RTC_CLASS && I2C
+ help
+ If you say yes here you get support for the
+ Philips PCF8563 RTC chip. The Epson RTC8564
+ should work as well.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-pcf8563.
+
+config RTC_DRV_RS5C372
+ tristate "Ricoh RS5C372A/B"
+ depends on RTC_CLASS && I2C
+ help
+ If you say yes here you get support for the
+ Ricoh RS5C372A and RS5C372B RTC chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-rs5c372.
+
+config RTC_DRV_M48T86
+ tristate "ST M48T86/Dallas DS12887"
+ depends on RTC_CLASS
+ help
+ If you say Y here you will get support for the
+ ST M48T86 and Dallas DS12887 RTC chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-m48t86.
+
+config RTC_DRV_EP93XX
+ tristate "Cirrus Logic EP93XX"
+ depends on RTC_CLASS && ARCH_EP93XX
+ help
+ If you say yes here you get support for the
+ RTC embedded in the Cirrus Logic EP93XX processors.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ep93xx.
+
+config RTC_DRV_SA1100
+ tristate "SA11x0/PXA2xx"
+ depends on RTC_CLASS && (ARCH_SA1100 || ARCH_PXA)
+ help
+ If you say Y here you will get access to the real time clock
+ built into your SA11x0 or PXA2xx CPU.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rtc-sa1100.
+
+config RTC_DRV_VR41XX
+ tristate "NEC VR41XX"
+ depends on RTC_CLASS && CPU_VR41XX
+ help
+ If you say Y here you will get access to the real time clock
+ built into your NEC VR41XX CPU.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rtc-vr41xx.
+
+config RTC_DRV_TEST
+ tristate "Test driver/device"
+ depends on RTC_CLASS
+ help
+ If you say yes here you get support for the
+ RTC test driver. It's a software RTC which can be
+ used to test the RTC subsystem APIs. It gets
+ the time from the system clock.
+ You want this driver only if you are doing development
+ on the RTC subsystem. Please read the source code
+ for further details.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-test.
+
+endmenu
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
new file mode 100644
index 00000000000..a9ca0f17168
--- /dev/null
+++ b/drivers/rtc/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for RTC class/drivers.
+#
+
+obj-$(CONFIG_RTC_LIB) += rtc-lib.o
+obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o
+obj-$(CONFIG_RTC_CLASS) += rtc-core.o
+rtc-core-y := class.o interface.o
+
+obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
+obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
+obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o
+
+obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
+obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
+obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o
+obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
+obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
+obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
+obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
+obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
+obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
new file mode 100644
index 00000000000..413c7d54ea1
--- /dev/null
+++ b/drivers/rtc/class.c
@@ -0,0 +1,147 @@
+/*
+ * RTC subsystem, base class
+ *
+ * Copyright (C) 2005 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * class skeleton from drivers/hwmon/hwmon.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/kdev_t.h>
+#include <linux/idr.h>
+
+static DEFINE_IDR(rtc_idr);
+static DEFINE_MUTEX(idr_lock);
+struct class *rtc_class;
+
+static void rtc_device_release(struct class_device *class_dev)
+{
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+ mutex_lock(&idr_lock);
+ idr_remove(&rtc_idr, rtc->id);
+ mutex_unlock(&idr_lock);
+ kfree(rtc);
+}
+
+/**
+ * rtc_device_register - register w/ RTC class
+ * @dev: the device to register
+ *
+ * rtc_device_unregister() must be called when the class device is no
+ * longer needed.
+ *
+ * Returns the pointer to the new struct class device.
+ */
+struct rtc_device *rtc_device_register(const char *name, struct device *dev,
+ struct rtc_class_ops *ops,
+ struct module *owner)
+{
+ struct rtc_device *rtc;
+ int id, err;
+
+ if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+
+ mutex_lock(&idr_lock);
+ err = idr_get_new(&rtc_idr, NULL, &id);
+ mutex_unlock(&idr_lock);
+
+ if (err < 0)
+ goto exit;
+
+ id = id & MAX_ID_MASK;
+
+ rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL);
+ if (rtc == NULL) {
+ err = -ENOMEM;
+ goto exit_idr;
+ }
+
+ rtc->id = id;
+ rtc->ops = ops;
+ rtc->owner = owner;
+ rtc->class_dev.dev = dev;
+ rtc->class_dev.class = rtc_class;
+ rtc->class_dev.release = rtc_device_release;
+
+ mutex_init(&rtc->ops_lock);
+ spin_lock_init(&rtc->irq_lock);
+ spin_lock_init(&rtc->irq_task_lock);
+
+ strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
+ snprintf(rtc->class_dev.class_id, BUS_ID_SIZE, "rtc%d", id);
+
+ err = class_device_register(&rtc->class_dev);
+ if (err)
+ goto exit_kfree;
+
+ dev_info(dev, "rtc core: registered %s as %s\n",
+ rtc->name, rtc->class_dev.class_id);
+
+ return rtc;
+
+exit_kfree:
+ kfree(rtc);
+
+exit_idr:
+ idr_remove(&rtc_idr, id);
+
+exit:
+ dev_err(dev, "rtc core: unable to register %s, err = %d\n",
+ name, err);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(rtc_device_register);
+
+
+/**
+ * rtc_device_unregister - removes the previously registered RTC class device
+ *
+ * @rtc: the RTC class device to destroy
+ */
+void rtc_device_unregister(struct rtc_device *rtc)
+{
+ mutex_lock(&rtc->ops_lock);
+ rtc->ops = NULL;
+ mutex_unlock(&rtc->ops_lock);
+ class_device_unregister(&rtc->class_dev);
+}
+EXPORT_SYMBOL_GPL(rtc_device_unregister);
+
+int rtc_interface_register(struct class_interface *intf)
+{
+ intf->class = rtc_class;
+ return class_interface_register(intf);
+}
+EXPORT_SYMBOL_GPL(rtc_interface_register);
+
+static int __init rtc_init(void)
+{
+ rtc_class = class_create(THIS_MODULE, "rtc");
+ if (IS_ERR(rtc_class)) {
+ printk(KERN_ERR "%s: couldn't create class\n", __FILE__);
+ return PTR_ERR(rtc_class);
+ }
+ return 0;
+}
+
+static void __exit rtc_exit(void)
+{
+ class_destroy(rtc_class);
+}
+
+module_init(rtc_init);
+module_exit(rtc_exit);
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towerteh.it>");
+MODULE_DESCRIPTION("RTC class support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c
new file mode 100644
index 00000000000..d02fe9a0001
--- /dev/null
+++ b/drivers/rtc/hctosys.c
@@ -0,0 +1,69 @@
+/*
+ * RTC subsystem, initialize system time on startup
+ *
+ * Copyright (C) 2005 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * 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/rtc.h>
+
+/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
+ * whether it stores the most close value or the value with partial
+ * seconds truncated. However, it is important that we use it to store
+ * the truncated value. This is because otherwise it is necessary,
+ * in an rtc sync function, to read both xtime.tv_sec and
+ * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
+ * of >32bits is not possible. So storing the most close value would
+ * slow down the sync API. So here we have the truncated value and
+ * the best guess is to add 0.5s.
+ */
+
+static int __init rtc_hctosys(void)
+{
+ int err;
+ struct rtc_time tm;
+ struct class_device *class_dev = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
+
+ if (class_dev == NULL) {
+ printk("%s: unable to open rtc device (%s)\n",
+ __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
+ return -ENODEV;
+ }
+
+ err = rtc_read_time(class_dev, &tm);
+ if (err == 0) {
+ err = rtc_valid_tm(&tm);
+ if (err == 0) {
+ struct timespec tv;
+
+ tv.tv_nsec = NSEC_PER_SEC >> 1;
+
+ rtc_tm_to_time(&tm, &tv.tv_sec);
+
+ do_settimeofday(&tv);
+
+ dev_info(class_dev->dev,
+ "setting the system clock to "
+ "%d-%02d-%02d %02d:%02d:%02d (%u)\n",
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec,
+ (unsigned int) tv.tv_sec);
+ }
+ else
+ dev_err(class_dev->dev,
+ "hctosys: invalid date/time\n");
+ }
+ else
+ dev_err(class_dev->dev,
+ "hctosys: unable to read the hardware clock\n");
+
+ rtc_class_close(class_dev);
+
+ return 0;
+}
+
+late_initcall(rtc_hctosys);
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
new file mode 100644
index 00000000000..56e490709b8
--- /dev/null
+++ b/drivers/rtc/interface.c
@@ -0,0 +1,277 @@
+/*
+ * RTC subsystem, interface functions
+ *
+ * Copyright (C) 2005 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based on arch/arm/common/rtctime.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/rtc.h>
+
+int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm)
+{
+ int err;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return -EBUSY;
+
+ if (!rtc->ops)
+ err = -ENODEV;
+ else if (!rtc->ops->read_time)
+ err = -EINVAL;
+ else {
+ memset(tm, 0, sizeof(struct rtc_time));
+ err = rtc->ops->read_time(class_dev->dev, tm);
+ }
+
+ mutex_unlock(&rtc->ops_lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_read_time);
+
+int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm)
+{
+ int err;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ err = rtc_valid_tm(tm);
+ if (err != 0)
+ return err;
+
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return -EBUSY;
+
+ if (!rtc->ops)
+ err = -ENODEV;
+ else if (!rtc->ops->set_time)
+ err = -EINVAL;
+ else
+ err = rtc->ops->set_time(class_dev->dev, tm);
+
+ mutex_unlock(&rtc->ops_lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_set_time);
+
+int rtc_set_mmss(struct class_device *class_dev, unsigned long secs)
+{
+ int err;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return -EBUSY;
+
+ if (!rtc->ops)
+ err = -ENODEV;
+ else if (rtc->ops->set_mmss)
+ err = rtc->ops->set_mmss(class_dev->dev, secs);
+ else if (rtc->ops->read_time && rtc->ops->set_time) {
+ struct rtc_time new, old;
+
+ err = rtc->ops->read_time(class_dev->dev, &old);
+ if (err == 0) {
+ rtc_time_to_tm(secs, &new);
+
+ /*
+ * avoid writing when we're going to change the day of
+ * the month. We will retry in the next minute. This
+ * basically means that if the RTC must not drift
+ * by more than 1 minute in 11 minutes.
+ */
+ if (!((old.tm_hour == 23 && old.tm_min == 59) ||
+ (new.tm_hour == 23 && new.tm_min == 59)))
+ err = rtc->ops->set_time(class_dev->dev, &new);
+ }
+ }
+ else
+ err = -EINVAL;
+
+ mutex_unlock(&rtc->ops_lock);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_set_mmss);
+
+int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
+{
+ int err;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return -EBUSY;
+
+ if (rtc->ops == NULL)
+ err = -ENODEV;
+ else if (!rtc->ops->read_alarm)
+ err = -EINVAL;
+ else {
+ memset(alarm, 0, sizeof(struct rtc_wkalrm));
+ err = rtc->ops->read_alarm(class_dev->dev, alarm);
+ }
+
+ mutex_unlock(&rtc->ops_lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_read_alarm);
+
+int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
+{
+ int err;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return -EBUSY;
+
+ if (!rtc->ops)
+ err = -ENODEV;
+ else if (!rtc->ops->set_alarm)
+ err = -EINVAL;
+ else
+ err = rtc->ops->set_alarm(class_dev->dev, alarm);
+
+ mutex_unlock(&rtc->ops_lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_set_alarm);
+
+void rtc_update_irq(struct class_device *class_dev,
+ unsigned long num, unsigned long events)
+{
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ spin_lock(&rtc->irq_lock);
+ rtc->irq_data = (rtc->irq_data + (num << 8)) | events;
+ spin_unlock(&rtc->irq_lock);
+
+ spin_lock(&rtc->irq_task_lock);
+ if (rtc->irq_task)
+ rtc->irq_task->func(rtc->irq_task->private_data);
+ spin_unlock(&rtc->irq_task_lock);
+
+ wake_up_interruptible(&rtc->irq_queue);
+ kill_fasync(&rtc->async_queue, SIGIO, POLL_IN);
+}
+EXPORT_SYMBOL_GPL(rtc_update_irq);
+
+struct class_device *rtc_class_open(char *name)
+{
+ struct class_device *class_dev = NULL,
+ *class_dev_tmp;
+
+ down(&rtc_class->sem);
+ list_for_each_entry(class_dev_tmp, &rtc_class->children, node) {
+ if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) {
+ class_dev = class_dev_tmp;
+ break;
+ }
+ }
+
+ if (class_dev) {
+ if (!try_module_get(to_rtc_device(class_dev)->owner))
+ class_dev = NULL;
+ }
+ up(&rtc_class->sem);
+
+ return class_dev;
+}
+EXPORT_SYMBOL_GPL(rtc_class_open);
+
+void rtc_class_close(struct class_device *class_dev)
+{
+ module_put(to_rtc_device(class_dev)->owner);
+}
+EXPORT_SYMBOL_GPL(rtc_class_close);
+
+int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task)
+{
+ int retval = -EBUSY;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ if (task == NULL || task->func == NULL)
+ return -EINVAL;
+
+ spin_lock(&rtc->irq_task_lock);
+ if (rtc->irq_task == NULL) {
+ rtc->irq_task = task;
+ retval = 0;
+ }
+ spin_unlock(&rtc->irq_task_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL_GPL(rtc_irq_register);
+
+void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task)
+{
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ spin_lock(&rtc->irq_task_lock);
+ if (rtc->irq_task == task)
+ rtc->irq_task = NULL;
+ spin_unlock(&rtc->irq_task_lock);
+}
+EXPORT_SYMBOL_GPL(rtc_irq_unregister);
+
+int rtc_irq_set_state(struct class_device *class_dev, struct rtc_task *task, int enabled)
+{
+ int err = 0;
+ unsigned long flags;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ spin_lock_irqsave(&rtc->irq_task_lock, flags);
+ if (rtc->irq_task != task)
+ err = -ENXIO;
+ spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+
+ if (err == 0)
+ err = rtc->ops->irq_set_state(class_dev->dev, enabled);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_irq_set_state);
+
+int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int freq)
+{
+ int err = 0, tmp = 0;
+ unsigned long flags;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ /* allowed range is 2-8192 */
+ if (freq < 2 || freq > 8192)
+ return -EINVAL;
+/*
+ FIXME: this does not belong here, will move where appropriate
+ at a later stage. It cannot hurt right now, trust me :)
+ if ((freq > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE)))
+ return -EACCES;
+*/
+ /* check if freq is a power of 2 */
+ while (freq > (1 << tmp))
+ tmp++;
+
+ if (freq != (1 << tmp))
+ return -EINVAL;
+
+ spin_lock_irqsave(&rtc->irq_task_lock, flags);
+ if (rtc->irq_task != task)
+ err = -ENXIO;
+ spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+
+ if (err == 0) {
+ err = rtc->ops->irq_set_freq(class_dev->dev, freq);
+ if (err == 0)
+ rtc->irq_freq = freq;
+ }
+ return err;
+}
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
new file mode 100644
index 00000000000..2011567005f
--- /dev/null
+++ b/drivers/rtc/rtc-dev.c
@@ -0,0 +1,387 @@
+/*
+ * RTC subsystem, dev interface
+ *
+ * Copyright (C) 2005 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based on arch/arm/common/rtctime.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/rtc.h>
+
+static struct class *rtc_dev_class;
+static dev_t rtc_devt;
+
+#define RTC_DEV_MAX 16 /* 16 RTCs should be enough for everyone... */
+
+static int rtc_dev_open(struct inode *inode, struct file *file)
+{
+ int err;
+ struct rtc_device *rtc = container_of(inode->i_cdev,
+ struct rtc_device, char_dev);
+ struct rtc_class_ops *ops = rtc->ops;
+
+ /* We keep the lock as long as the device is in use
+ * and return immediately if busy
+ */
+ if (!(mutex_trylock(&rtc->char_lock)))
+ return -EBUSY;
+
+ file->private_data = &rtc->class_dev;
+
+ err = ops->open ? ops->open(rtc->class_dev.dev) : 0;
+ if (err == 0) {
+ spin_lock_irq(&rtc->irq_lock);
+ rtc->irq_data = 0;
+ spin_unlock_irq(&rtc->irq_lock);
+
+ return 0;
+ }
+
+ /* something has gone wrong, release the lock */
+ mutex_unlock(&rtc->char_lock);
+ return err;
+}
+
+
+static ssize_t
+rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ struct rtc_device *rtc = to_rtc_device(file->private_data);
+
+ DECLARE_WAITQUEUE(wait, current);
+ unsigned long data;
+ ssize_t ret;
+
+ if (count != sizeof(unsigned int) && count < sizeof(unsigned long))
+ return -EINVAL;
+
+ add_wait_queue(&rtc->irq_queue, &wait);
+ do {
+ __set_current_state(TASK_INTERRUPTIBLE);
+
+ spin_lock_irq(&rtc->irq_lock);
+ data = rtc->irq_data;
+ rtc->irq_data = 0;
+ spin_unlock_irq(&rtc->irq_lock);
+
+ if (data != 0) {
+ ret = 0;
+ break;
+ }
+ if (file->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+ schedule();
+ } while (1);
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&rtc->irq_queue, &wait);
+
+ if (ret == 0) {
+ /* Check for any data updates */
+ if (rtc->ops->read_callback)
+ data = rtc->ops->read_callback(rtc->class_dev.dev,
+ data);
+
+ if (sizeof(int) != sizeof(long) &&
+ count == sizeof(unsigned int))
+ ret = put_user(data, (unsigned int __user *)buf) ?:
+ sizeof(unsigned int);
+ else
+ ret = put_user(data, (unsigned long __user *)buf) ?:
+ sizeof(unsigned long);
+ }
+ return ret;
+}
+
+static unsigned int rtc_dev_poll(struct file *file, poll_table *wait)
+{
+ struct rtc_device *rtc = to_rtc_device(file->private_data);
+ unsigned long data;
+
+ poll_wait(file, &rtc->irq_queue, wait);
+
+ data = rtc->irq_data;
+
+ return (data != 0) ? (POLLIN | POLLRDNORM) : 0;
+}
+
+static int rtc_dev_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int err = 0;
+ struct class_device *class_dev = file->private_data;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+ struct rtc_class_ops *ops = rtc->ops;
+ struct rtc_time tm;
+ struct rtc_wkalrm alarm;
+ void __user *uarg = (void __user *) arg;
+
+ /* avoid conflicting IRQ users */
+ if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) {
+ spin_lock(&rtc->irq_task_lock);
+ if (rtc->irq_task)
+ err = -EBUSY;
+ spin_unlock(&rtc->irq_task_lock);
+
+ if (err < 0)
+ return err;
+ }
+
+ /* try the driver's ioctl interface */
+ if (ops->ioctl) {
+ err = ops->ioctl(class_dev->dev, cmd, arg);
+ if (err != -ENOIOCTLCMD)
+ return err;
+ }
+
+ /* if the driver does not provide the ioctl interface
+ * or if that particular ioctl was not implemented
+ * (-ENOIOCTLCMD), we will try to emulate here.
+ */
+
+ switch (cmd) {
+ case RTC_ALM_READ:
+ err = rtc_read_alarm(class_dev, &alarm);
+ if (err < 0)
+ return err;
+
+ if (copy_to_user(uarg, &alarm.time, sizeof(tm)))
+ return -EFAULT;
+ break;
+
+ case RTC_ALM_SET:
+ if (copy_from_user(&alarm.time, uarg, sizeof(tm)))
+ return -EFAULT;
+
+ alarm.enabled = 0;
+ alarm.pending = 0;
+ alarm.time.tm_mday = -1;
+ alarm.time.tm_mon = -1;
+ alarm.time.tm_year = -1;
+ alarm.time.tm_wday = -1;
+ alarm.time.tm_yday = -1;
+ alarm.time.tm_isdst = -1;
+ err = rtc_set_alarm(class_dev, &alarm);
+ break;
+
+ case RTC_RD_TIME:
+ err = rtc_read_time(class_dev, &tm);
+ if (err < 0)
+ return err;
+
+ if (copy_to_user(uarg, &tm, sizeof(tm)))
+ return -EFAULT;
+ break;
+
+ case RTC_SET_TIME:
+ if (!capable(CAP_SYS_TIME))
+ return -EACCES;
+
+ if (copy_from_user(&tm, uarg, sizeof(tm)))
+ return -EFAULT;
+
+ err = rtc_set_time(class_dev, &tm);
+ break;
+#if 0
+ case RTC_EPOCH_SET:
+#ifndef rtc_epoch
+ /*
+ * There were no RTC clocks before 1900.
+ */
+ if (arg < 1900) {
+ err = -EINVAL;
+ break;
+ }
+ if (!capable(CAP_SYS_TIME)) {
+ err = -EACCES;
+ break;
+ }
+ rtc_epoch = arg;
+ err = 0;
+#endif
+ break;
+
+ case RTC_EPOCH_READ:
+ err = put_user(rtc_epoch, (unsigned long __user *)uarg);
+ break;
+#endif
+ case RTC_WKALM_SET:
+ if (copy_from_user(&alarm, uarg, sizeof(alarm)))
+ return -EFAULT;
+
+ err = rtc_set_alarm(class_dev, &alarm);
+ break;
+
+ case RTC_WKALM_RD:
+ err = rtc_read_alarm(class_dev, &alarm);
+ if (err < 0)
+ return err;
+
+ if (copy_to_user(uarg, &alarm, sizeof(alarm)))
+ return -EFAULT;
+ break;
+
+ default:
+ err = -ENOTTY;
+ break;
+ }
+
+ return err;
+}
+
+static int rtc_dev_release(struct inode *inode, struct file *file)
+{
+ struct rtc_device *rtc = to_rtc_device(file->private_data);
+
+ if (rtc->ops->release)
+ rtc->ops->release(rtc->class_dev.dev);
+
+ mutex_unlock(&rtc->char_lock);
+ return 0;
+}
+
+static int rtc_dev_fasync(int fd, struct file *file, int on)
+{
+ struct rtc_device *rtc = to_rtc_device(file->private_data);
+ return fasync_helper(fd, file, on, &rtc->async_queue);
+}
+
+static struct file_operations rtc_dev_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = rtc_dev_read,
+ .poll = rtc_dev_poll,
+ .ioctl = rtc_dev_ioctl,
+ .open = rtc_dev_open,
+ .release = rtc_dev_release,
+ .fasync = rtc_dev_fasync,
+};
+
+/* insertion/removal hooks */
+
+static int rtc_dev_add_device(struct class_device *class_dev,
+ struct class_interface *class_intf)
+{
+ int err = 0;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ if (rtc->id >= RTC_DEV_MAX) {
+ dev_err(class_dev->dev, "too many RTCs\n");
+ return -EINVAL;
+ }
+
+ mutex_init(&rtc->char_lock);
+ spin_lock_init(&rtc->irq_lock);
+ init_waitqueue_head(&rtc->irq_queue);
+
+ cdev_init(&rtc->char_dev, &rtc_dev_fops);
+ rtc->char_dev.owner = rtc->owner;
+
+ if (cdev_add(&rtc->char_dev, MKDEV(MAJOR(rtc_devt), rtc->id), 1)) {
+ cdev_del(&rtc->char_dev);
+ dev_err(class_dev->dev,
+ "failed to add char device %d:%d\n",
+ MAJOR(rtc_devt), rtc->id);
+ return -ENODEV;
+ }
+
+ rtc->rtc_dev = class_device_create(rtc_dev_class, NULL,
+ MKDEV(MAJOR(rtc_devt), rtc->id),
+ class_dev->dev, "rtc%d", rtc->id);
+ if (IS_ERR(rtc->rtc_dev)) {
+ dev_err(class_dev->dev, "cannot create rtc_dev device\n");
+ err = PTR_ERR(rtc->rtc_dev);
+ goto err_cdev_del;
+ }
+
+ dev_info(class_dev->dev, "rtc intf: dev (%d:%d)\n",
+ MAJOR(rtc->rtc_dev->devt),
+ MINOR(rtc->rtc_dev->devt));
+
+ return 0;
+
+err_cdev_del:
+
+ cdev_del(&rtc->char_dev);
+ return err;
+}
+
+static void rtc_dev_remove_device(struct class_device *class_dev,
+ struct class_interface *class_intf)
+{
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ if (rtc->rtc_dev) {
+ dev_dbg(class_dev->dev, "removing char %d:%d\n",
+ MAJOR(rtc->rtc_dev->devt),
+ MINOR(rtc->rtc_dev->devt));
+
+ class_device_unregister(rtc->rtc_dev);
+ cdev_del(&rtc->char_dev);
+ }
+}
+
+/* interface registration */
+
+static struct class_interface rtc_dev_interface = {
+ .add = &rtc_dev_add_device,
+ .remove = &rtc_dev_remove_device,
+};
+
+static int __init rtc_dev_init(void)
+{
+ int err;
+
+ rtc_dev_class = class_create(THIS_MODULE, "rtc-dev");
+ if (IS_ERR(rtc_dev_class))
+ return PTR_ERR(rtc_dev_class);
+
+ err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc");
+ if (err < 0) {
+ printk(KERN_ERR "%s: failed to allocate char dev region\n",
+ __FILE__);
+ goto err_destroy_class;
+ }
+
+ err = rtc_interface_register(&rtc_dev_interface);
+ if (err < 0) {
+ printk(KERN_ERR "%s: failed to register the interface\n",
+ __FILE__);
+ goto err_unregister_chrdev;
+ }
+
+ return 0;
+
+err_unregister_chrdev:
+ unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
+
+err_destroy_class:
+ class_destroy(rtc_dev_class);
+
+ return err;
+}
+
+static void __exit rtc_dev_exit(void)
+{
+ class_interface_unregister(&rtc_dev_interface);
+ class_destroy(rtc_dev_class);
+ unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
+}
+
+module_init(rtc_dev_init);
+module_exit(rtc_dev_exit);
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("RTC class dev interface");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
new file mode 100644
index 00000000000..9be81fd4737
--- /dev/null
+++ b/drivers/rtc/rtc-ds1672.c
@@ -0,0 +1,277 @@
+/*
+ * An rtc/i2c driver for the Dallas DS1672
+ * Copyright 2005-06 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+
+#define DRV_VERSION "0.3"
+
+/* Addresses to scan: none. This chip cannot be detected. */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD;
+
+/* Registers */
+
+#define DS1672_REG_CNT_BASE 0
+#define DS1672_REG_CONTROL 4
+#define DS1672_REG_TRICKLE 5
+
+#define DS1672_REG_CONTROL_EOSC 0x80
+
+/* Prototypes */
+static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind);
+
+/*
+ * In the routines that deal directly with the ds1672 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
+ * Epoch is initialized as 2000. Time is set to UTC.
+ */
+static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ unsigned long time;
+ unsigned char addr = DS1672_REG_CNT_BASE;
+ unsigned char buf[4];
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 1, &addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 4, buf }, /* read date */
+ };
+
+ /* read date registers */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev,
+ "%s: raw read data - counters=%02x,%02x,%02x,%02x\n"
+ __FUNCTION__, buf[0], buf[1], buf[2], buf[3]);
+
+ time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+ rtc_time_to_tm(time, tm);
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ return 0;
+}
+
+static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs)
+{
+ int xfer;
+ unsigned char buf[6];
+
+ buf[0] = DS1672_REG_CNT_BASE;
+ buf[1] = secs & 0x000000FF;
+ buf[2] = (secs & 0x0000FF00) >> 8;
+ buf[3] = (secs & 0x00FF0000) >> 16;
+ buf[4] = (secs & 0xFF000000) >> 24;
+ buf[5] = 0; /* set control reg to enable counting */
+
+ xfer = i2c_master_send(client, buf, 6);
+ if (xfer != 6) {
+ dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int ds1672_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ unsigned long secs;
+
+ dev_dbg(&client->dev,
+ "%s: secs=%d, mins=%d, hours=%d, ",
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ rtc_tm_to_time(tm, &secs);
+
+ return ds1672_set_mmss(client, secs);
+}
+
+static int ds1672_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ return ds1672_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int ds1672_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return ds1672_set_datetime(to_i2c_client(dev), tm);
+}
+
+static int ds1672_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+ return ds1672_set_mmss(to_i2c_client(dev), secs);
+}
+
+static int ds1672_get_control(struct i2c_client *client, u8 *status)
+{
+ unsigned char addr = DS1672_REG_CONTROL;
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 1, &addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 1, status }, /* read control */
+ };
+
+ /* read control register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/* following are the sysfs callback functions */
+static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ u8 control;
+ int err;
+
+ err = ds1672_get_control(client, &control);
+ if (err)
+ return err;
+
+ return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC)
+ ? "disabled" : "enabled");
+}
+static DEVICE_ATTR(control, S_IRUGO, show_control, NULL);
+
+static struct rtc_class_ops ds1672_rtc_ops = {
+ .read_time = ds1672_rtc_read_time,
+ .set_time = ds1672_rtc_set_time,
+ .set_mmss = ds1672_rtc_set_mmss,
+};
+
+static int ds1672_attach(struct i2c_adapter *adapter)
+{
+ return i2c_probe(adapter, &addr_data, ds1672_probe);
+}
+
+static int ds1672_detach(struct i2c_client *client)
+{
+ int err;
+ struct rtc_device *rtc = i2c_get_clientdata(client);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ kfree(client);
+
+ return 0;
+}
+
+static struct i2c_driver ds1672_driver = {
+ .driver = {
+ .name = "ds1672",
+ },
+ .id = I2C_DRIVERID_DS1672,
+ .attach_adapter = &ds1672_attach,
+ .detach_client = &ds1672_detach,
+};
+
+static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
+{
+ int err = 0;
+ u8 control;
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ err = -ENODEV;
+ goto exit;
+ }
+
+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ /* I2C client */
+ client->addr = address;
+ client->driver = &ds1672_driver;
+ client->adapter = adapter;
+
+ strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE);
+
+ /* Inform the i2c layer */
+ if ((err = i2c_attach_client(client)))
+ goto exit_kfree;
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+ rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev,
+ &ds1672_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ err = PTR_ERR(rtc);
+ goto exit_detach;
+ }
+
+ i2c_set_clientdata(client, rtc);
+
+ /* read control register */
+ err = ds1672_get_control(client, &control);
+ if (err)
+ goto exit_detach;
+
+ if (control & DS1672_REG_CONTROL_EOSC)
+ dev_warn(&client->dev, "Oscillator not enabled. "
+ "Set time to enable.\n");
+
+ /* Register sysfs hooks */
+ device_create_file(&client->dev, &dev_attr_control);
+
+ return 0;
+
+exit_detach:
+ i2c_detach_client(client);
+
+exit_kfree:
+ kfree(client);
+
+exit:
+ return err;
+}
+
+static int __init ds1672_init(void)
+{
+ return i2c_add_driver(&ds1672_driver);
+}
+
+static void __exit ds1672_exit(void)
+{
+ i2c_del_driver(&ds1672_driver);
+}
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ds1672_init);
+module_exit(ds1672_exit);
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c
new file mode 100644
index 00000000000..e1a1169e466
--- /dev/null
+++ b/drivers/rtc/rtc-ep93xx.c
@@ -0,0 +1,160 @@
+/*
+ * A driver for the RTC embedded in the Cirrus Logic EP93XX processors
+ * Copyright (c) 2006 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * 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/rtc.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+
+#define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x))
+#define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000)
+#define EP93XX_RTC_LOAD EP93XX_RTC_REG(0x000C)
+#define EP93XX_RTC_SWCOMP EP93XX_RTC_REG(0x0108)
+
+#define DRV_VERSION "0.2"
+
+static int ep93xx_get_swcomp(struct device *dev, unsigned short *preload,
+ unsigned short *delete)
+{
+ unsigned short comp = __raw_readl(EP93XX_RTC_SWCOMP);
+
+ if (preload)
+ *preload = comp & 0xffff;
+
+ if (delete)
+ *delete = (comp >> 16) & 0x1f;
+
+ return 0;
+}
+
+static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned long time = __raw_readl(EP93XX_RTC_DATA);
+
+ rtc_time_to_tm(time, tm);
+ return 0;
+}
+
+static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+ __raw_writel(secs + 1, EP93XX_RTC_LOAD);
+ return 0;
+}
+
+static int ep93xx_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ int err;
+ unsigned long secs;
+
+ err = rtc_tm_to_time(tm, &secs);
+ if (err != 0)
+ return err;
+
+ return ep93xx_rtc_set_mmss(dev, secs);
+}
+
+static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ unsigned short preload, delete;
+
+ ep93xx_get_swcomp(dev, &preload, &delete);
+
+ seq_printf(seq, "preload\t\t: %d\n", preload);
+ seq_printf(seq, "delete\t\t: %d\n", delete);
+
+ return 0;
+}
+
+static struct rtc_class_ops ep93xx_rtc_ops = {
+ .read_time = ep93xx_rtc_read_time,
+ .set_time = ep93xx_rtc_set_time,
+ .set_mmss = ep93xx_rtc_set_mmss,
+ .proc = ep93xx_rtc_proc,
+};
+
+static ssize_t ep93xx_sysfs_show_comp_preload(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned short preload;
+
+ ep93xx_get_swcomp(dev, &preload, NULL);
+
+ return sprintf(buf, "%d\n", preload);
+}
+static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_sysfs_show_comp_preload, NULL);
+
+static ssize_t ep93xx_sysfs_show_comp_delete(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned short delete;
+
+ ep93xx_get_swcomp(dev, NULL, &delete);
+
+ return sprintf(buf, "%d\n", delete);
+}
+static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_sysfs_show_comp_delete, NULL);
+
+
+static int __devinit ep93xx_rtc_probe(struct platform_device *dev)
+{
+ struct rtc_device *rtc = rtc_device_register("ep93xx",
+ &dev->dev, &ep93xx_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ return PTR_ERR(rtc);
+ }
+
+ platform_set_drvdata(dev, rtc);
+
+ device_create_file(&dev->dev, &dev_attr_comp_preload);
+ device_create_file(&dev->dev, &dev_attr_comp_delete);
+
+ return 0;
+}
+
+static int __devexit ep93xx_rtc_remove(struct platform_device *dev)
+{
+ struct rtc_device *rtc = platform_get_drvdata(dev);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ platform_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver ep93xx_rtc_platform_driver = {
+ .driver = {
+ .name = "ep93xx-rtc",
+ .owner = THIS_MODULE,
+ },
+ .probe = ep93xx_rtc_probe,
+ .remove = __devexit_p(ep93xx_rtc_remove),
+};
+
+static int __init ep93xx_rtc_init(void)
+{
+ return platform_driver_register(&ep93xx_rtc_platform_driver);
+}
+
+static void __exit ep93xx_rtc_exit(void)
+{
+ platform_driver_unregister(&ep93xx_rtc_platform_driver);
+}
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("EP93XX RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ep93xx_rtc_init);
+module_exit(ep93xx_rtc_exit);
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
new file mode 100644
index 00000000000..cfedc1d28ee
--- /dev/null
+++ b/drivers/rtc/rtc-lib.c
@@ -0,0 +1,101 @@
+/*
+ * rtc and date/time utility functions
+ *
+ * Copyright (C) 2005-06 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based on arch/arm/common/rtctime.c and other bits
+ *
+ * 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/rtc.h>
+
+static const unsigned char rtc_days_in_month[] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
+#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400))
+
+int rtc_month_days(unsigned int month, unsigned int year)
+{
+ return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1);
+}
+EXPORT_SYMBOL(rtc_month_days);
+
+/*
+ * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
+ */
+void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
+{
+ register int days, month, year;
+
+ days = time / 86400;
+ time -= days * 86400;
+
+ /* day of the week, 1970-01-01 was a Thursday */
+ tm->tm_wday = (days + 4) % 7;
+
+ year = 1970 + days / 365;
+ days -= (year - 1970) * 365
+ + LEAPS_THRU_END_OF(year - 1)
+ - LEAPS_THRU_END_OF(1970 - 1);
+ if (days < 0) {
+ year -= 1;
+ days += 365 + LEAP_YEAR(year);
+ }
+ tm->tm_year = year - 1900;
+ tm->tm_yday = days + 1;
+
+ for (month = 0; month < 11; month++) {
+ int newdays;
+
+ newdays = days - rtc_month_days(month, year);
+ if (newdays < 0)
+ break;
+ days = newdays;
+ }
+ tm->tm_mon = month;
+ tm->tm_mday = days + 1;
+
+ tm->tm_hour = time / 3600;
+ time -= tm->tm_hour * 3600;
+ tm->tm_min = time / 60;
+ tm->tm_sec = time - tm->tm_min * 60;
+}
+EXPORT_SYMBOL(rtc_time_to_tm);
+
+/*
+ * Does the rtc_time represent a valid date/time?
+ */
+int rtc_valid_tm(struct rtc_time *tm)
+{
+ if (tm->tm_year < 70
+ || tm->tm_mon >= 12
+ || tm->tm_mday < 1
+ || tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + 1900)
+ || tm->tm_hour >= 24
+ || tm->tm_min >= 60
+ || tm->tm_sec >= 60)
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL(rtc_valid_tm);
+
+/*
+ * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
+ */
+int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
+{
+ *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ return 0;
+}
+EXPORT_SYMBOL(rtc_tm_to_time);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
new file mode 100644
index 00000000000..8c0d1a6739a
--- /dev/null
+++ b/drivers/rtc/rtc-m48t86.c
@@ -0,0 +1,204 @@
+/*
+ * ST M48T86 / Dallas DS12887 RTC driver
+ * Copyright (c) 2006 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * 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 drivers only supports the clock running in BCD and 24H mode.
+ * If it will be ever adapted to binary and 12H mode, care must be taken
+ * to not introduce bugs.
+ */
+
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/m48t86.h>
+#include <linux/bcd.h>
+
+#define M48T86_REG_SEC 0x00
+#define M48T86_REG_SECALRM 0x01
+#define M48T86_REG_MIN 0x02
+#define M48T86_REG_MINALRM 0x03
+#define M48T86_REG_HOUR 0x04
+#define M48T86_REG_HOURALRM 0x05
+#define M48T86_REG_DOW 0x06 /* 1 = sunday */
+#define M48T86_REG_DOM 0x07
+#define M48T86_REG_MONTH 0x08 /* 1 - 12 */
+#define M48T86_REG_YEAR 0x09 /* 0 - 99 */
+#define M48T86_REG_A 0x0A
+#define M48T86_REG_B 0x0B
+#define M48T86_REG_C 0x0C
+#define M48T86_REG_D 0x0D
+
+#define M48T86_REG_B_H24 (1 << 1)
+#define M48T86_REG_B_DM (1 << 2)
+#define M48T86_REG_B_SET (1 << 7)
+#define M48T86_REG_D_VRT (1 << 7)
+
+#define DRV_VERSION "0.1"
+
+
+static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned char reg;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t86_ops *ops = pdev->dev.platform_data;
+
+ reg = ops->readbyte(M48T86_REG_B);
+
+ if (reg & M48T86_REG_B_DM) {
+ /* data (binary) mode */
+ tm->tm_sec = ops->readbyte(M48T86_REG_SEC);
+ tm->tm_min = ops->readbyte(M48T86_REG_MIN);
+ tm->tm_hour = ops->readbyte(M48T86_REG_HOUR) & 0x3F;
+ tm->tm_mday = ops->readbyte(M48T86_REG_DOM);
+ /* tm_mon is 0-11 */
+ tm->tm_mon = ops->readbyte(M48T86_REG_MONTH) - 1;
+ tm->tm_year = ops->readbyte(M48T86_REG_YEAR) + 100;
+ tm->tm_wday = ops->readbyte(M48T86_REG_DOW);
+ } else {
+ /* bcd mode */
+ tm->tm_sec = BCD2BIN(ops->readbyte(M48T86_REG_SEC));
+ tm->tm_min = BCD2BIN(ops->readbyte(M48T86_REG_MIN));
+ tm->tm_hour = BCD2BIN(ops->readbyte(M48T86_REG_HOUR) & 0x3F);
+ tm->tm_mday = BCD2BIN(ops->readbyte(M48T86_REG_DOM));
+ /* tm_mon is 0-11 */
+ tm->tm_mon = BCD2BIN(ops->readbyte(M48T86_REG_MONTH)) - 1;
+ tm->tm_year = BCD2BIN(ops->readbyte(M48T86_REG_YEAR)) + 100;
+ tm->tm_wday = BCD2BIN(ops->readbyte(M48T86_REG_DOW));
+ }
+
+ /* correct the hour if the clock is in 12h mode */
+ if (!(reg & M48T86_REG_B_H24))
+ if (ops->readbyte(M48T86_REG_HOUR) & 0x80)
+ tm->tm_hour += 12;
+
+ return 0;
+}
+
+static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned char reg;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t86_ops *ops = pdev->dev.platform_data;
+
+ reg = ops->readbyte(M48T86_REG_B);
+
+ /* update flag and 24h mode */
+ reg |= M48T86_REG_B_SET | M48T86_REG_B_H24;
+ ops->writebyte(reg, M48T86_REG_B);
+
+ if (reg & M48T86_REG_B_DM) {
+ /* data (binary) mode */
+ ops->writebyte(tm->tm_sec, M48T86_REG_SEC);
+ ops->writebyte(tm->tm_min, M48T86_REG_MIN);
+ ops->writebyte(tm->tm_hour, M48T86_REG_HOUR);
+ ops->writebyte(tm->tm_mday, M48T86_REG_DOM);
+ ops->writebyte(tm->tm_mon + 1, M48T86_REG_MONTH);
+ ops->writebyte(tm->tm_year % 100, M48T86_REG_YEAR);
+ ops->writebyte(tm->tm_wday, M48T86_REG_DOW);
+ } else {
+ /* bcd mode */
+ ops->writebyte(BIN2BCD(tm->tm_sec), M48T86_REG_SEC);
+ ops->writebyte(BIN2BCD(tm->tm_min), M48T86_REG_MIN);
+ ops->writebyte(BIN2BCD(tm->tm_hour), M48T86_REG_HOUR);
+ ops->writebyte(BIN2BCD(tm->tm_mday), M48T86_REG_DOM);
+ ops->writebyte(BIN2BCD(tm->tm_mon + 1), M48T86_REG_MONTH);
+ ops->writebyte(BIN2BCD(tm->tm_year % 100), M48T86_REG_YEAR);
+ ops->writebyte(BIN2BCD(tm->tm_wday), M48T86_REG_DOW);
+ }
+
+ /* update ended */
+ reg &= ~M48T86_REG_B_SET;
+ ops->writebyte(reg, M48T86_REG_B);
+
+ return 0;
+}
+
+static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ unsigned char reg;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t86_ops *ops = pdev->dev.platform_data;
+
+ reg = ops->readbyte(M48T86_REG_B);
+
+ seq_printf(seq, "mode\t\t: %s\n",
+ (reg & M48T86_REG_B_DM) ? "binary" : "bcd");
+
+ reg = ops->readbyte(M48T86_REG_D);
+
+ seq_printf(seq, "battery\t\t: %s\n",
+ (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
+
+ return 0;
+}
+
+static struct rtc_class_ops m48t86_rtc_ops = {
+ .read_time = m48t86_rtc_read_time,
+ .set_time = m48t86_rtc_set_time,
+ .proc = m48t86_rtc_proc,
+};
+
+static int __devinit m48t86_rtc_probe(struct platform_device *dev)
+{
+ unsigned char reg;
+ struct m48t86_ops *ops = dev->dev.platform_data;
+ struct rtc_device *rtc = rtc_device_register("m48t86",
+ &dev->dev, &m48t86_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ platform_set_drvdata(dev, rtc);
+
+ /* read battery status */
+ reg = ops->readbyte(M48T86_REG_D);
+ dev_info(&dev->dev, "battery %s\n",
+ (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
+
+ return 0;
+}
+
+static int __devexit m48t86_rtc_remove(struct platform_device *dev)
+{
+ struct rtc_device *rtc = platform_get_drvdata(dev);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ platform_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver m48t86_rtc_platform_driver = {
+ .driver = {
+ .name = "rtc-m48t86",
+ .owner = THIS_MODULE,
+ },
+ .probe = m48t86_rtc_probe,
+ .remove = __devexit_p(m48t86_rtc_remove),
+};
+
+static int __init m48t86_rtc_init(void)
+{
+ return platform_driver_register(&m48t86_rtc_platform_driver);
+}
+
+static void __exit m48t86_rtc_exit(void)
+{
+ platform_driver_unregister(&m48t86_rtc_platform_driver);
+}
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("M48T86 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(m48t86_rtc_init);
+module_exit(m48t86_rtc_exit);
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
new file mode 100644
index 00000000000..ba9a583b7b6
--- /dev/null
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -0,0 +1,342 @@
+/*
+ * An I2C driver for the Philips PCF8563 RTC
+ * Copyright 2005-06 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ * based on the other drivers in this same directory.
+ *
+ * http://www.semiconductors.philips.com/acrobat/datasheets/PCF8563-04.pdf
+ *
+ * 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/i2c.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+
+#define DRV_VERSION "0.4.2"
+
+/* Addresses to scan: none
+ * This chip cannot be reliably autodetected. An empty eeprom
+ * located at 0x51 will pass the validation routine due to
+ * the way the registers are implemented.
+ */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Module parameters */
+I2C_CLIENT_INSMOD;
+
+#define PCF8563_REG_ST1 0x00 /* status */
+#define PCF8563_REG_ST2 0x01
+
+#define PCF8563_REG_SC 0x02 /* datetime */
+#define PCF8563_REG_MN 0x03
+#define PCF8563_REG_HR 0x04
+#define PCF8563_REG_DM 0x05
+#define PCF8563_REG_DW 0x06
+#define PCF8563_REG_MO 0x07
+#define PCF8563_REG_YR 0x08
+
+#define PCF8563_REG_AMN 0x09 /* alarm */
+#define PCF8563_REG_AHR 0x0A
+#define PCF8563_REG_ADM 0x0B
+#define PCF8563_REG_ADW 0x0C
+
+#define PCF8563_REG_CLKO 0x0D /* clock out */
+#define PCF8563_REG_TMRC 0x0E /* timer control */
+#define PCF8563_REG_TMR 0x0F /* timer */
+
+#define PCF8563_SC_LV 0x80 /* low voltage */
+#define PCF8563_MO_C 0x80 /* century */
+
+static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind);
+static int pcf8563_detach(struct i2c_client *client);
+
+/*
+ * In the routines that deal directly with the pcf8563 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
+ */
+static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ unsigned char buf[13] = { PCF8563_REG_ST1 };
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 1, buf }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 13, buf }, /* read status + date */
+ };
+
+ /* read registers */
+ if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)
+ dev_info(&client->dev,
+ "low voltage detected, date/time is not reliable.\n");
+
+ dev_dbg(&client->dev,
+ "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
+ "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
+ __FUNCTION__,
+ buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7],
+ buf[8]);
+
+
+ tm->tm_sec = BCD2BIN(buf[PCF8563_REG_SC] & 0x7F);
+ tm->tm_min = BCD2BIN(buf[PCF8563_REG_MN] & 0x7F);
+ tm->tm_hour = BCD2BIN(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
+ tm->tm_mday = BCD2BIN(buf[PCF8563_REG_DM] & 0x3F);
+ tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
+ tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
+ tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR])
+ + (buf[PCF8563_REG_MO] & PCF8563_MO_C ? 100 : 0);
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ /* the clock can give out invalid datetime, but we cannot return
+ * -EINVAL otherwise hwclock will refuse to set the time on bootup.
+ */
+ if (rtc_valid_tm(tm) < 0)
+ dev_err(&client->dev, "retrieved date/time is not valid.\n");
+
+ return 0;
+}
+
+static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ int i, err;
+ unsigned char buf[9];
+
+ dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ /* hours, minutes and seconds */
+ buf[PCF8563_REG_SC] = BIN2BCD(tm->tm_sec);
+ buf[PCF8563_REG_MN] = BIN2BCD(tm->tm_min);
+ buf[PCF8563_REG_HR] = BIN2BCD(tm->tm_hour);
+
+ buf[PCF8563_REG_DM] = BIN2BCD(tm->tm_mday);
+
+ /* month, 1 - 12 */
+ buf[PCF8563_REG_MO] = BIN2BCD(tm->tm_mon + 1);
+
+ /* year and century */
+ buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100);
+ if (tm->tm_year / 100)
+ buf[PCF8563_REG_MO] |= PCF8563_MO_C;
+
+ buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
+
+ /* write register's data */
+ for (i = 0; i < 7; i++) {
+ unsigned char data[2] = { PCF8563_REG_SC + i,
+ buf[PCF8563_REG_SC + i] };
+
+ err = i2c_master_send(client, data, sizeof(data));
+ if (err != sizeof(data)) {
+ dev_err(&client->dev,
+ "%s: err=%d addr=%02x, data=%02x\n",
+ __FUNCTION__, err, data[0], data[1]);
+ return -EIO;
+ }
+ };
+
+ return 0;
+}
+
+struct pcf8563_limit
+{
+ unsigned char reg;
+ unsigned char mask;
+ unsigned char min;
+ unsigned char max;
+};
+
+static int pcf8563_validate_client(struct i2c_client *client)
+{
+ int i;
+
+ static const struct pcf8563_limit pattern[] = {
+ /* register, mask, min, max */
+ { PCF8563_REG_SC, 0x7F, 0, 59 },
+ { PCF8563_REG_MN, 0x7F, 0, 59 },
+ { PCF8563_REG_HR, 0x3F, 0, 23 },
+ { PCF8563_REG_DM, 0x3F, 0, 31 },
+ { PCF8563_REG_MO, 0x1F, 0, 12 },
+ };
+
+ /* check limits (only registers with bcd values) */
+ for (i = 0; i < ARRAY_SIZE(pattern); i++) {
+ int xfer;
+ unsigned char value;
+ unsigned char buf = pattern[i].reg;
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 1, &buf },
+ { client->addr, I2C_M_RD, 1, &buf },
+ };
+
+ xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+
+ if (xfer != ARRAY_SIZE(msgs)) {
+ dev_err(&client->adapter->dev,
+ "%s: could not read register 0x%02X\n",
+ __FUNCTION__, pattern[i].reg);
+
+ return -EIO;
+ }
+
+ value = BCD2BIN(buf & pattern[i].mask);
+
+ if (value > pattern[i].max ||
+ value < pattern[i].min) {
+ dev_dbg(&client->adapter->dev,
+ "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, "
+ "max=%d, value=%d, raw=0x%02X\n",
+ __FUNCTION__, i, pattern[i].reg, pattern[i].mask,
+ pattern[i].min, pattern[i].max,
+ value, buf);
+
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ return pcf8563_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return pcf8563_set_datetime(to_i2c_client(dev), tm);
+}
+
+static struct rtc_class_ops pcf8563_rtc_ops = {
+ .read_time = pcf8563_rtc_read_time,
+ .set_time = pcf8563_rtc_set_time,
+};
+
+static int pcf8563_attach(struct i2c_adapter *adapter)
+{
+ return i2c_probe(adapter, &addr_data, pcf8563_probe);
+}
+
+static struct i2c_driver pcf8563_driver = {
+ .driver = {
+ .name = "pcf8563",
+ },
+ .id = I2C_DRIVERID_PCF8563,
+ .attach_adapter = &pcf8563_attach,
+ .detach_client = &pcf8563_detach,
+};
+
+static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+
+ int err = 0;
+
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ err = -ENODEV;
+ goto exit;
+ }
+
+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ client->addr = address;
+ client->driver = &pcf8563_driver;
+ client->adapter = adapter;
+
+ strlcpy(client->name, pcf8563_driver.driver.name, I2C_NAME_SIZE);
+
+ /* Verify the chip is really an PCF8563 */
+ if (kind < 0) {
+ if (pcf8563_validate_client(client) < 0) {
+ err = -ENODEV;
+ goto exit_kfree;
+ }
+ }
+
+ /* Inform the i2c layer */
+ if ((err = i2c_attach_client(client)))
+ goto exit_kfree;
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+ rtc = rtc_device_register(pcf8563_driver.driver.name, &client->dev,
+ &pcf8563_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ err = PTR_ERR(rtc);
+ goto exit_detach;
+ }
+
+ i2c_set_clientdata(client, rtc);
+
+ return 0;
+
+exit_detach:
+ i2c_detach_client(client);
+
+exit_kfree:
+ kfree(client);
+
+exit:
+ return err;
+}
+
+static int pcf8563_detach(struct i2c_client *client)
+{
+ int err;
+ struct rtc_device *rtc = i2c_get_clientdata(client);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ kfree(client);
+
+ return 0;
+}
+
+static int __init pcf8563_init(void)
+{
+ return i2c_add_driver(&pcf8563_driver);
+}
+
+static void __exit pcf8563_exit(void)
+{
+ i2c_del_driver(&pcf8563_driver);
+}
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(pcf8563_init);
+module_exit(pcf8563_exit);
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
new file mode 100644
index 00000000000..cef5f5a3bbf
--- /dev/null
+++ b/drivers/rtc/rtc-proc.c
@@ -0,0 +1,164 @@
+/*
+ * RTC subsystem, proc interface
+ *
+ * Copyright (C) 2005-06 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based on arch/arm/common/rtctime.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+static struct class_device *rtc_dev = NULL;
+static DEFINE_MUTEX(rtc_lock);
+
+static int rtc_proc_show(struct seq_file *seq, void *offset)
+{
+ int err;
+ struct class_device *class_dev = seq->private;
+ struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops;
+ struct rtc_wkalrm alrm;
+ struct rtc_time tm;
+
+ err = rtc_read_time(class_dev, &tm);
+ if (err == 0) {
+ seq_printf(seq,
+ "rtc_time\t: %02d:%02d:%02d\n"
+ "rtc_date\t: %04d-%02d-%02d\n",
+ tm.tm_hour, tm.tm_min, tm.tm_sec,
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
+ }
+
+ err = rtc_read_alarm(class_dev, &alrm);
+ if (err == 0) {
+ seq_printf(seq, "alrm_time\t: ");
+ if ((unsigned int)alrm.time.tm_hour <= 24)
+ seq_printf(seq, "%02d:", alrm.time.tm_hour);
+ else
+ seq_printf(seq, "**:");
+ if ((unsigned int)alrm.time.tm_min <= 59)
+ seq_printf(seq, "%02d:", alrm.time.tm_min);
+ else
+ seq_printf(seq, "**:");
+ if ((unsigned int)alrm.time.tm_sec <= 59)
+ seq_printf(seq, "%02d\n", alrm.time.tm_sec);
+ else
+ seq_printf(seq, "**\n");
+
+ seq_printf(seq, "alrm_date\t: ");
+ if ((unsigned int)alrm.time.tm_year <= 200)
+ seq_printf(seq, "%04d-", alrm.time.tm_year + 1900);
+ else
+ seq_printf(seq, "****-");
+ if ((unsigned int)alrm.time.tm_mon <= 11)
+ seq_printf(seq, "%02d-", alrm.time.tm_mon + 1);
+ else
+ seq_printf(seq, "**-");
+ if ((unsigned int)alrm.time.tm_mday <= 31)
+ seq_printf(seq, "%02d\n", alrm.time.tm_mday);
+ else
+ seq_printf(seq, "**\n");
+ seq_printf(seq, "alrm_wakeup\t: %s\n",
+ alrm.enabled ? "yes" : "no");
+ seq_printf(seq, "alrm_pending\t: %s\n",
+ alrm.pending ? "yes" : "no");
+ }
+
+ seq_printf(seq, "24hr\t\t: yes\n");
+
+ if (ops->proc)
+ ops->proc(class_dev->dev, seq);
+
+ return 0;
+}
+
+static int rtc_proc_open(struct inode *inode, struct file *file)
+{
+ struct class_device *class_dev = PDE(inode)->data;
+
+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
+ return single_open(file, rtc_proc_show, class_dev);
+}
+
+static int rtc_proc_release(struct inode *inode, struct file *file)
+{
+ int res = single_release(inode, file);
+ module_put(THIS_MODULE);
+ return res;
+}
+
+static struct file_operations rtc_proc_fops = {
+ .open = rtc_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = rtc_proc_release,
+};
+
+static int rtc_proc_add_device(struct class_device *class_dev,
+ struct class_interface *class_intf)
+{
+ mutex_lock(&rtc_lock);
+ if (rtc_dev == NULL) {
+ struct proc_dir_entry *ent;
+
+ rtc_dev = class_dev;
+
+ ent = create_proc_entry("driver/rtc", 0, NULL);
+ if (ent) {
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ ent->proc_fops = &rtc_proc_fops;
+ ent->owner = rtc->owner;
+ ent->data = class_dev;
+
+ dev_info(class_dev->dev, "rtc intf: proc\n");
+ }
+ else
+ rtc_dev = NULL;
+ }
+ mutex_unlock(&rtc_lock);
+
+ return 0;
+}
+
+static void rtc_proc_remove_device(struct class_device *class_dev,
+ struct class_interface *class_intf)
+{
+ mutex_lock(&rtc_lock);
+ if (rtc_dev == class_dev) {
+ remove_proc_entry("driver/rtc", NULL);
+ rtc_dev = NULL;
+ }
+ mutex_unlock(&rtc_lock);
+}
+
+static struct class_interface rtc_proc_interface = {
+ .add = &rtc_proc_add_device,
+ .remove = &rtc_proc_remove_device,
+};
+
+static int __init rtc_proc_init(void)
+{
+ return rtc_interface_register(&rtc_proc_interface);
+}
+
+static void __exit rtc_proc_exit(void)
+{
+ class_interface_unregister(&rtc_proc_interface);
+}
+
+module_init(rtc_proc_init);
+module_exit(rtc_proc_exit);
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("RTC class proc interface");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
new file mode 100644
index 00000000000..7553d797603
--- /dev/null
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -0,0 +1,290 @@
+/*
+ * An I2C driver for the Ricoh RS5C372 RTC
+ *
+ * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net>
+ * Copyright (C) 2006 Tower Technologies
+ *
+ * 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/i2c.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#define DRV_VERSION "0.2"
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD;
+
+#define RS5C372_REG_SECS 0
+#define RS5C372_REG_MINS 1
+#define RS5C372_REG_HOURS 2
+#define RS5C372_REG_WDAY 3
+#define RS5C372_REG_DAY 4
+#define RS5C372_REG_MONTH 5
+#define RS5C372_REG_YEAR 6
+#define RS5C372_REG_TRIM 7
+
+#define RS5C372_TRIM_XSL 0x80
+#define RS5C372_TRIM_MASK 0x7F
+
+#define RS5C372_REG_BASE 0
+
+static int rs5c372_attach(struct i2c_adapter *adapter);
+static int rs5c372_detach(struct i2c_client *client);
+static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind);
+
+static struct i2c_driver rs5c372_driver = {
+ .driver = {
+ .name = "rs5c372",
+ },
+ .attach_adapter = &rs5c372_attach,
+ .detach_client = &rs5c372_detach,
+};
+
+static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ unsigned char buf[7] = { RS5C372_REG_BASE };
+
+ /* this implements the 1st reading method, according
+ * to the datasheet. buf[0] is initialized with
+ * address ptr and transmission format register.
+ */
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 1, buf },
+ { client->addr, I2C_M_RD, 7, buf },
+ };
+
+ if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ tm->tm_sec = BCD2BIN(buf[RS5C372_REG_SECS] & 0x7f);
+ tm->tm_min = BCD2BIN(buf[RS5C372_REG_MINS] & 0x7f);
+ tm->tm_hour = BCD2BIN(buf[RS5C372_REG_HOURS] & 0x3f);
+ tm->tm_wday = BCD2BIN(buf[RS5C372_REG_WDAY] & 0x07);
+ tm->tm_mday = BCD2BIN(buf[RS5C372_REG_DAY] & 0x3f);
+
+ /* tm->tm_mon is zero-based */
+ tm->tm_mon = BCD2BIN(buf[RS5C372_REG_MONTH] & 0x1f) - 1;
+
+ /* year is 1900 + tm->tm_year */
+ tm->tm_year = BCD2BIN(buf[RS5C372_REG_YEAR]) + 100;
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ return 0;
+}
+
+static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ unsigned char buf[8] = { RS5C372_REG_BASE };
+
+ dev_dbg(&client->dev,
+ "%s: secs=%d, mins=%d, hours=%d ",
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ buf[1] = BIN2BCD(tm->tm_sec);
+ buf[2] = BIN2BCD(tm->tm_min);
+ buf[3] = BIN2BCD(tm->tm_hour);
+ buf[4] = BIN2BCD(tm->tm_wday);
+ buf[5] = BIN2BCD(tm->tm_mday);
+ buf[6] = BIN2BCD(tm->tm_mon + 1);
+ buf[7] = BIN2BCD(tm->tm_year - 100);
+
+ if ((i2c_master_send(client, buf, 8)) != 8) {
+ dev_err(&client->dev, "%s: write error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim)
+{
+ unsigned char buf = RS5C372_REG_TRIM;
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 1, &buf },
+ { client->addr, I2C_M_RD, 1, &buf },
+ };
+
+ if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, trim);
+
+ if (osc)
+ *osc = (buf & RS5C372_TRIM_XSL) ? 32000 : 32768;
+
+ if (trim)
+ *trim = buf & RS5C372_TRIM_MASK;
+
+ return 0;
+}
+
+static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ return rs5c372_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return rs5c372_set_datetime(to_i2c_client(dev), tm);
+}
+
+static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ int err, osc, trim;
+
+ err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim);
+ if (err == 0) {
+ seq_printf(seq, "%d.%03d KHz\n", osc / 1000, osc % 1000);
+ seq_printf(seq, "trim\t: %d\n", trim);
+ }
+
+ return 0;
+}
+
+static struct rtc_class_ops rs5c372_rtc_ops = {
+ .proc = rs5c372_rtc_proc,
+ .read_time = rs5c372_rtc_read_time,
+ .set_time = rs5c372_rtc_set_time,
+};
+
+static ssize_t rs5c372_sysfs_show_trim(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err, trim;
+
+ err = rs5c372_get_trim(to_i2c_client(dev), NULL, &trim);
+ if (err)
+ return err;
+
+ return sprintf(buf, "0x%2x\n", trim);
+}
+static DEVICE_ATTR(trim, S_IRUGO, rs5c372_sysfs_show_trim, NULL);
+
+static ssize_t rs5c372_sysfs_show_osc(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err, osc;
+
+ err = rs5c372_get_trim(to_i2c_client(dev), &osc, NULL);
+ if (err)
+ return err;
+
+ return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000);
+}
+static DEVICE_ATTR(osc, S_IRUGO, rs5c372_sysfs_show_osc, NULL);
+
+static int rs5c372_attach(struct i2c_adapter *adapter)
+{
+ return i2c_probe(adapter, &addr_data, rs5c372_probe);
+}
+
+static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
+{
+ int err = 0;
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ err = -ENODEV;
+ goto exit;
+ }
+
+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ /* I2C client */
+ client->addr = address;
+ client->driver = &rs5c372_driver;
+ client->adapter = adapter;
+
+ strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE);
+
+ /* Inform the i2c layer */
+ if ((err = i2c_attach_client(client)))
+ goto exit_kfree;
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+ rtc = rtc_device_register(rs5c372_driver.driver.name, &client->dev,
+ &rs5c372_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ err = PTR_ERR(rtc);
+ goto exit_detach;
+ }
+
+ i2c_set_clientdata(client, rtc);
+
+ device_create_file(&client->dev, &dev_attr_trim);
+ device_create_file(&client->dev, &dev_attr_osc);
+
+ return 0;
+
+exit_detach:
+ i2c_detach_client(client);
+
+exit_kfree:
+ kfree(client);
+
+exit:
+ return err;
+}
+
+static int rs5c372_detach(struct i2c_client *client)
+{
+ int err;
+ struct rtc_device *rtc = i2c_get_clientdata(client);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ kfree(client);
+
+ return 0;
+}
+
+static __init int rs5c372_init(void)
+{
+ return i2c_add_driver(&rs5c372_driver);
+}
+
+static __exit void rs5c372_exit(void)
+{
+ i2c_del_driver(&rs5c372_driver);
+}
+
+module_init(rs5c372_init);
+module_exit(rs5c372_exit);
+
+MODULE_AUTHOR(
+ "Pavel Mironchik <pmironchik@optifacio.net>, "
+ "Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
new file mode 100644
index 00000000000..a997529f892
--- /dev/null
+++ b/drivers/rtc/rtc-sa1100.c
@@ -0,0 +1,384 @@
+/*
+ * Real Time Clock interface for StrongARM SA1x00 and XScale PXA2xx
+ *
+ * Copyright (c) 2000 Nils Faerber
+ *
+ * Based on rtc.c by Paul Gortmaker
+ *
+ * Original Driver by Nils Faerber <nils@kernelconcepts.de>
+ *
+ * Modifications from:
+ * CIH <cih@coventive.com>
+ * Nicolas Pitre <nico@cam.org>
+ * Andrew Christian <andrew.christian@hp.com>
+ *
+ * Converted to the RTC subsystem and Driver Model
+ * by Richard Purdie <rpurdie@rpsys.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/pm.h>
+
+#include <asm/bitops.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/rtc.h>
+
+#ifdef CONFIG_ARCH_PXA
+#include <asm/arch/pxa-regs.h>
+#endif
+
+#define TIMER_FREQ CLOCK_TICK_RATE
+#define RTC_DEF_DIVIDER 32768 - 1
+#define RTC_DEF_TRIM 0
+
+static unsigned long rtc_freq = 1024;
+static struct rtc_time rtc_alarm;
+static spinlock_t sa1100_rtc_lock = SPIN_LOCK_UNLOCKED;
+
+static int rtc_update_alarm(struct rtc_time *alrm)
+{
+ struct rtc_time alarm_tm, now_tm;
+ unsigned long now, time;
+ int ret;
+
+ do {
+ now = RCNR;
+ rtc_time_to_tm(now, &now_tm);
+ rtc_next_alarm_time(&alarm_tm, &now_tm, alrm);
+ ret = rtc_tm_to_time(&alarm_tm, &time);
+ if (ret != 0)
+ break;
+
+ RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
+ RTAR = time;
+ } while (now != RCNR);
+
+ return ret;
+}
+
+static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ struct platform_device *pdev = to_platform_device(dev_id);
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+ unsigned int rtsr;
+ unsigned long events = 0;
+
+ spin_lock(&sa1100_rtc_lock);
+
+ rtsr = RTSR;
+ /* clear interrupt sources */
+ RTSR = 0;
+ RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
+
+ /* clear alarm interrupt if it has occurred */
+ if (rtsr & RTSR_AL)
+ rtsr &= ~RTSR_ALE;
+ RTSR = rtsr & (RTSR_ALE | RTSR_HZE);
+
+ /* update irq data & counter */
+ if (rtsr & RTSR_AL)
+ events |= RTC_AF | RTC_IRQF;
+ if (rtsr & RTSR_HZ)
+ events |= RTC_UF | RTC_IRQF;
+
+ rtc_update_irq(&rtc->class_dev, 1, events);
+
+ if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm))
+ rtc_update_alarm(&rtc_alarm);
+
+ spin_unlock(&sa1100_rtc_lock);
+
+ return IRQ_HANDLED;
+}
+
+static int rtc_timer1_count;
+
+static irqreturn_t timer1_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ struct platform_device *pdev = to_platform_device(dev_id);
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+ /*
+ * If we match for the first time, rtc_timer1_count will be 1.
+ * Otherwise, we wrapped around (very unlikely but
+ * still possible) so compute the amount of missed periods.
+ * The match reg is updated only when the data is actually retrieved
+ * to avoid unnecessary interrupts.
+ */
+ OSSR = OSSR_M1; /* clear match on timer1 */
+
+ rtc_update_irq(&rtc->class_dev, rtc_timer1_count, RTC_PF | RTC_IRQF);
+
+ if (rtc_timer1_count == 1)
+ rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2)));
+
+ return IRQ_HANDLED;
+}
+
+static int sa1100_rtc_read_callback(struct device *dev, int data)
+{
+ if (data & RTC_PF) {
+ /* interpolate missed periods and set match for the next */
+ unsigned long period = TIMER_FREQ/rtc_freq;
+ unsigned long oscr = OSCR;
+ unsigned long osmr1 = OSMR1;
+ unsigned long missed = (oscr - osmr1)/period;
+ data += missed << 8;
+ OSSR = OSSR_M1; /* clear match on timer 1 */
+ OSMR1 = osmr1 + (missed + 1)*period;
+ /* Ensure we didn't miss another match in the mean time.
+ * Here we compare (match - OSCR) 8 instead of 0 --
+ * see comment in pxa_timer_interrupt() for explanation.
+ */
+ while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) {
+ data += 0x100;
+ OSSR = OSSR_M1; /* clear match on timer 1 */
+ OSMR1 = osmr1 + period;
+ }
+ }
+ return data;
+}
+
+static int sa1100_rtc_open(struct device *dev)
+{
+ int ret;
+
+ ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, SA_INTERRUPT,
+ "rtc 1Hz", dev);
+ if (ret) {
+ dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
+ goto fail_ui;
+ }
+ ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, SA_INTERRUPT,
+ "rtc Alrm", dev);
+ if (ret) {
+ dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
+ goto fail_ai;
+ }
+ ret = request_irq(IRQ_OST1, timer1_interrupt, SA_INTERRUPT,
+ "rtc timer", dev);
+ if (ret) {
+ dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
+ goto fail_pi;
+ }
+ return 0;
+
+ fail_pi:
+ free_irq(IRQ_RTCAlrm, dev);
+ fail_ai:
+ free_irq(IRQ_RTC1Hz, dev);
+ fail_ui:
+ return ret;
+}
+
+static void sa1100_rtc_release(struct device *dev)
+{
+ spin_lock_irq(&sa1100_rtc_lock);
+ RTSR = 0;
+ OIER &= ~OIER_E1;
+ OSSR = OSSR_M1;
+ spin_unlock_irq(&sa1100_rtc_lock);
+
+ free_irq(IRQ_OST1, dev);
+ free_irq(IRQ_RTCAlrm, dev);
+ free_irq(IRQ_RTC1Hz, dev);
+}
+
+
+static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
+ unsigned long arg)
+{
+ switch(cmd) {
+ case RTC_AIE_OFF:
+ spin_lock_irq(&sa1100_rtc_lock);
+ RTSR &= ~RTSR_ALE;
+ spin_unlock_irq(&sa1100_rtc_lock);
+ return 0;
+ case RTC_AIE_ON:
+ spin_lock_irq(&sa1100_rtc_lock);
+ RTSR |= RTSR_ALE;
+ spin_unlock_irq(&sa1100_rtc_lock);
+ return 0;
+ case RTC_UIE_OFF:
+ spin_lock_irq(&sa1100_rtc_lock);
+ RTSR &= ~RTSR_HZE;
+ spin_unlock_irq(&sa1100_rtc_lock);
+ return 0;
+ case RTC_UIE_ON:
+ spin_lock_irq(&sa1100_rtc_lock);
+ RTSR |= RTSR_HZE;
+ spin_unlock_irq(&sa1100_rtc_lock);
+ return 0;
+ case RTC_PIE_OFF:
+ spin_lock_irq(&sa1100_rtc_lock);
+ OIER &= ~OIER_E1;
+ spin_unlock_irq(&sa1100_rtc_lock);
+ return 0;
+ case RTC_PIE_ON:
+ if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE))
+ return -EACCES;
+ spin_lock_irq(&sa1100_rtc_lock);
+ OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
+ OIER |= OIER_E1;
+ rtc_timer1_count = 1;
+ spin_unlock_irq(&sa1100_rtc_lock);
+ return 0;
+ case RTC_IRQP_READ:
+ return put_user(rtc_freq, (unsigned long *)arg);
+ case RTC_IRQP_SET:
+ if (arg < 1 || arg > TIMER_FREQ)
+ return -EINVAL;
+ if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
+ return -EACCES;
+ rtc_freq = arg;
+ return 0;
+ }
+ return -ENOIOCTLCMD;
+}
+
+static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ rtc_time_to_tm(RCNR, tm);
+ return 0;
+}
+
+static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned long time;
+ int ret;
+
+ ret = rtc_tm_to_time(tm, &time);
+ if (ret == 0)
+ RCNR = time;
+ return ret;
+}
+
+static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
+ alrm->pending = RTSR & RTSR_AL ? 1 : 0;
+ return 0;
+}
+
+static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ int ret;
+
+ spin_lock_irq(&sa1100_rtc_lock);
+ ret = rtc_update_alarm(&alrm->time);
+ if (ret == 0) {
+ memcpy(&rtc_alarm, &alrm->time, sizeof(struct rtc_time));
+
+ if (alrm->enabled)
+ enable_irq_wake(IRQ_RTCAlrm);
+ else
+ disable_irq_wake(IRQ_RTCAlrm);
+ }
+ spin_unlock_irq(&sa1100_rtc_lock);
+
+ return ret;
+}
+
+static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ seq_printf(seq, "trim/divider\t: 0x%08lx\n", RTTR);
+ seq_printf(seq, "alarm_IRQ\t: %s\n",
+ (RTSR & RTSR_ALE) ? "yes" : "no" );
+ seq_printf(seq, "update_IRQ\t: %s\n",
+ (RTSR & RTSR_HZE) ? "yes" : "no");
+ seq_printf(seq, "periodic_IRQ\t: %s\n",
+ (OIER & OIER_E1) ? "yes" : "no");
+ seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq);
+
+ return 0;
+}
+
+static struct rtc_class_ops sa1100_rtc_ops = {
+ .open = sa1100_rtc_open,
+ .read_callback = sa1100_rtc_read_callback,
+ .release = sa1100_rtc_release,
+ .ioctl = sa1100_rtc_ioctl,
+ .read_time = sa1100_rtc_read_time,
+ .set_time = sa1100_rtc_set_time,
+ .read_alarm = sa1100_rtc_read_alarm,
+ .set_alarm = sa1100_rtc_set_alarm,
+ .proc = sa1100_rtc_proc,
+};
+
+static int sa1100_rtc_probe(struct platform_device *pdev)
+{
+ struct rtc_device *rtc;
+
+ /*
+ * According to the manual we should be able to let RTTR be zero
+ * and then a default diviser for a 32.768KHz clock is used.
+ * Apparently this doesn't work, at least for my SA1110 rev 5.
+ * If the clock divider is uninitialized then reset it to the
+ * default value to get the 1Hz clock.
+ */
+ if (RTTR == 0) {
+ RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
+ dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n");
+ /* The current RTC value probably doesn't make sense either */
+ RCNR = 0;
+ }
+
+ rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
+ THIS_MODULE);
+
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ platform_set_drvdata(pdev, rtc);
+
+ return 0;
+}
+
+static int sa1100_rtc_remove(struct platform_device *pdev)
+{
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ return 0;
+}
+
+static struct platform_driver sa1100_rtc_driver = {
+ .probe = sa1100_rtc_probe,
+ .remove = sa1100_rtc_remove,
+ .driver = {
+ .name = "sa1100-rtc",
+ },
+};
+
+static int __init sa1100_rtc_init(void)
+{
+ return platform_driver_register(&sa1100_rtc_driver);
+}
+
+static void __exit sa1100_rtc_exit(void)
+{
+ platform_driver_unregister(&sa1100_rtc_driver);
+}
+
+module_init(sa1100_rtc_init);
+module_exit(sa1100_rtc_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
new file mode 100644
index 00000000000..7c1f3d2e53c
--- /dev/null
+++ b/drivers/rtc/rtc-sysfs.c
@@ -0,0 +1,124 @@
+/*
+ * RTC subsystem, sysfs interface
+ *
+ * Copyright (C) 2005 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * 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/rtc.h>
+
+/* device attributes */
+
+static ssize_t rtc_sysfs_show_name(struct class_device *dev, char *buf)
+{
+ return sprintf(buf, "%s\n", to_rtc_device(dev)->name);
+}
+static CLASS_DEVICE_ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL);
+
+static ssize_t rtc_sysfs_show_date(struct class_device *dev, char *buf)
+{
+ ssize_t retval;
+ struct rtc_time tm;
+
+ retval = rtc_read_time(dev, &tm);
+ if (retval == 0) {
+ retval = sprintf(buf, "%04d-%02d-%02d\n",
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
+ }
+
+ return retval;
+}
+static CLASS_DEVICE_ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL);
+
+static ssize_t rtc_sysfs_show_time(struct class_device *dev, char *buf)
+{
+ ssize_t retval;
+ struct rtc_time tm;
+
+ retval = rtc_read_time(dev, &tm);
+ if (retval == 0) {
+ retval = sprintf(buf, "%02d:%02d:%02d\n",
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ }
+
+ return retval;
+}
+static CLASS_DEVICE_ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL);
+
+static ssize_t rtc_sysfs_show_since_epoch(struct class_device *dev, char *buf)
+{
+ ssize_t retval;
+ struct rtc_time tm;
+
+ retval = rtc_read_time(dev, &tm);
+ if (retval == 0) {
+ unsigned long time;
+ rtc_tm_to_time(&tm, &time);
+ retval = sprintf(buf, "%lu\n", time);
+ }
+
+ return retval;
+}
+static CLASS_DEVICE_ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL);
+
+static struct attribute *rtc_attrs[] = {
+ &class_device_attr_name.attr,
+ &class_device_attr_date.attr,
+ &class_device_attr_time.attr,
+ &class_device_attr_since_epoch.attr,
+ NULL,
+};
+
+static struct attribute_group rtc_attr_group = {
+ .attrs = rtc_attrs,
+};
+
+static int __devinit rtc_sysfs_add_device(struct class_device *class_dev,
+ struct class_interface *class_intf)
+{
+ int err;
+
+ dev_info(class_dev->dev, "rtc intf: sysfs\n");
+
+ err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group);
+ if (err)
+ dev_err(class_dev->dev,
+ "failed to create sysfs attributes\n");
+
+ return err;
+}
+
+static void rtc_sysfs_remove_device(struct class_device *class_dev,
+ struct class_interface *class_intf)
+{
+ sysfs_remove_group(&class_dev->kobj, &rtc_attr_group);
+}
+
+/* interface registration */
+
+static struct class_interface rtc_sysfs_interface = {
+ .add = &rtc_sysfs_add_device,
+ .remove = &rtc_sysfs_remove_device,
+};
+
+static int __init rtc_sysfs_init(void)
+{
+ return rtc_interface_register(&rtc_sysfs_interface);
+}
+
+static void __exit rtc_sysfs_exit(void)
+{
+ class_interface_unregister(&rtc_sysfs_interface);
+}
+
+module_init(rtc_sysfs_init);
+module_exit(rtc_sysfs_exit);
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("RTC class sysfs interface");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
new file mode 100644
index 00000000000..e1fa5fe7901
--- /dev/null
+++ b/drivers/rtc/rtc-test.c
@@ -0,0 +1,201 @@
+/*
+ * An RTC test device/driver
+ * Copyright (C) 2005 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+
+static struct platform_device *test0 = NULL, *test1 = NULL;
+
+static int test_rtc_read_alarm(struct device *dev,
+ struct rtc_wkalrm *alrm)
+{
+ return 0;
+}
+
+static int test_rtc_set_alarm(struct device *dev,
+ struct rtc_wkalrm *alrm)
+{
+ return 0;
+}
+
+static int test_rtc_read_time(struct device *dev,
+ struct rtc_time *tm)
+{
+ rtc_time_to_tm(get_seconds(), tm);
+ return 0;
+}
+
+static int test_rtc_set_time(struct device *dev,
+ struct rtc_time *tm)
+{
+ return 0;
+}
+
+static int test_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+ return 0;
+}
+
+static int test_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ struct platform_device *plat_dev = to_platform_device(dev);
+
+ seq_printf(seq, "test\t\t: yes\n");
+ seq_printf(seq, "id\t\t: %d\n", plat_dev->id);
+
+ return 0;
+}
+
+static int test_rtc_ioctl(struct device *dev, unsigned int cmd,
+ unsigned long arg)
+{
+ /* We do support interrupts, they're generated
+ * using the sysfs interface.
+ */
+ switch (cmd) {
+ case RTC_PIE_ON:
+ case RTC_PIE_OFF:
+ case RTC_UIE_ON:
+ case RTC_UIE_OFF:
+ case RTC_AIE_ON:
+ case RTC_AIE_OFF:
+ return 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static struct rtc_class_ops test_rtc_ops = {
+ .proc = test_rtc_proc,
+ .read_time = test_rtc_read_time,
+ .set_time = test_rtc_set_time,
+ .read_alarm = test_rtc_read_alarm,
+ .set_alarm = test_rtc_set_alarm,
+ .set_mmss = test_rtc_set_mmss,
+ .ioctl = test_rtc_ioctl,
+};
+
+static ssize_t test_irq_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", 42);
+}
+static ssize_t test_irq_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int retval;
+ struct platform_device *plat_dev = to_platform_device(dev);
+ struct rtc_device *rtc = platform_get_drvdata(plat_dev);
+
+ retval = count;
+ if (strncmp(buf, "tick", 4) == 0)
+ rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF);
+ else if (strncmp(buf, "alarm", 5) == 0)
+ rtc_update_irq(&rtc->class_dev, 1, RTC_AF | RTC_IRQF);
+ else if (strncmp(buf, "update", 6) == 0)
+ rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF);
+ else
+ retval = -EINVAL;
+
+ return retval;
+}
+static DEVICE_ATTR(irq, S_IRUGO | S_IWUSR, test_irq_show, test_irq_store);
+
+static int test_probe(struct platform_device *plat_dev)
+{
+ int err;
+ struct rtc_device *rtc = rtc_device_register("test", &plat_dev->dev,
+ &test_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ err = PTR_ERR(rtc);
+ return err;
+ }
+ device_create_file(&plat_dev->dev, &dev_attr_irq);
+
+ platform_set_drvdata(plat_dev, rtc);
+
+ return 0;
+}
+
+static int __devexit test_remove(struct platform_device *plat_dev)
+{
+ struct rtc_device *rtc = platform_get_drvdata(plat_dev);
+
+ rtc_device_unregister(rtc);
+ device_remove_file(&plat_dev->dev, &dev_attr_irq);
+
+ return 0;
+}
+
+static struct platform_driver test_drv = {
+ .probe = test_probe,
+ .remove = __devexit_p(test_remove),
+ .driver = {
+ .name = "rtc-test",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init test_init(void)
+{
+ int err;
+
+ if ((err = platform_driver_register(&test_drv)))
+ return err;
+
+ if ((test0 = platform_device_alloc("rtc-test", 0)) == NULL) {
+ err = -ENOMEM;
+ goto exit_driver_unregister;
+ }
+
+ if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) {
+ err = -ENOMEM;
+ goto exit_free_test0;
+ }
+
+ if ((err = platform_device_add(test0)))
+ goto exit_free_test1;
+
+ if ((err = platform_device_add(test1)))
+ goto exit_device_unregister;
+
+ return 0;
+
+exit_device_unregister:
+ platform_device_unregister(test0);
+
+exit_free_test1:
+ platform_device_put(test1);
+
+exit_free_test0:
+ platform_device_put(test0);
+
+exit_driver_unregister:
+ platform_driver_unregister(&test_drv);
+ return err;
+}
+
+static void __exit test_exit(void)
+{
+ platform_device_unregister(test0);
+ platform_device_unregister(test1);
+ platform_driver_unregister(&test_drv);
+}
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("RTC test driver/device");
+MODULE_LICENSE("GPL");
+
+module_init(test_init);
+module_exit(test_exit);
diff --git a/drivers/char/vr41xx_rtc.c b/drivers/rtc/rtc-vr41xx.c
index b109d9a502d..277596c302e 100644
--- a/drivers/char/vr41xx_rtc.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -1,7 +1,7 @@
/*
- * Driver for NEC VR4100 series Real Time Clock unit.
+ * Driver for NEC VR4100 series Real Time Clock unit.
*
- * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,23 +17,18 @@
* 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/fs.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/irq.h>
-#include <linux/mc146818rtc.h>
-#include <linux/miscdevice.h>
#include <linux/module.h>
-#include <linux/poll.h>
+#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/spinlock.h>
#include <linux/types.h>
-#include <linux/wait.h>
#include <asm/div64.h>
#include <asm/io.h>
-#include <asm/time.h>
#include <asm/uaccess.h>
#include <asm/vr41xx/vr41xx.h>
@@ -99,27 +94,11 @@ static void __iomem *rtc2_base;
static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */
-static spinlock_t rtc_task_lock;
-static wait_queue_head_t rtc_wait;
-static unsigned long rtc_irq_data;
-static struct fasync_struct *rtc_async_queue;
-static rtc_task_t *rtc_callback;
+static spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
static char rtc_name[] = "RTC";
static unsigned long periodic_frequency;
static unsigned long periodic_count;
-typedef enum {
- RTC_RELEASE,
- RTC_OPEN,
-} rtc_status_t;
-
-static rtc_status_t rtc_status;
-
-typedef enum {
- FUNCTION_RTC_IOCTL,
- FUNCTION_RTC_CONTROL,
-} rtc_callfrom_t;
-
struct resource rtc_resource[2] = {
{ .name = rtc_name,
.flags = IORESOURCE_MEM, },
@@ -129,7 +108,9 @@ struct resource rtc_resource[2] = {
static inline unsigned long read_elapsed_second(void)
{
+
unsigned long first_low, first_mid, first_high;
+
unsigned long second_low, second_mid, second_high;
do {
@@ -156,50 +137,36 @@ static inline void write_elapsed_second(unsigned long sec)
spin_unlock_irq(&rtc_lock);
}
-static void set_alarm(struct rtc_time *time)
+static void vr41xx_rtc_release(struct device *dev)
{
- unsigned long alarm_sec;
-
- alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
- time->tm_hour, time->tm_min, time->tm_sec);
-
- spin_lock_irq(&rtc_lock);
-
- rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
- rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
- rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
-
- spin_unlock_irq(&rtc_lock);
-}
-
-static void read_alarm(struct rtc_time *time)
-{
- unsigned long low, mid, high;
spin_lock_irq(&rtc_lock);
- low = rtc1_read(ECMPLREG);
- mid = rtc1_read(ECMPMREG);
- high = rtc1_read(ECMPHREG);
+ rtc1_write(ECMPLREG, 0);
+ rtc1_write(ECMPMREG, 0);
+ rtc1_write(ECMPHREG, 0);
+ rtc1_write(RTCL1LREG, 0);
+ rtc1_write(RTCL1HREG, 0);
spin_unlock_irq(&rtc_lock);
- to_tm((high << 17) | (mid << 1) | (low >> 15), time);
- time->tm_year -= 1900;
+ disable_irq(ELAPSEDTIME_IRQ);
+ disable_irq(RTCLONG1_IRQ);
}
-static void read_time(struct rtc_time *time)
+static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time)
{
unsigned long epoch_sec, elapsed_sec;
epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
elapsed_sec = read_elapsed_second();
- to_tm(epoch_sec + elapsed_sec, time);
- time->tm_year -= 1900;
+ rtc_time_to_tm(epoch_sec + elapsed_sec, time);
+
+ return 0;
}
-static void set_time(struct rtc_time *time)
+static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time)
{
unsigned long epoch_sec, current_sec;
@@ -208,73 +175,49 @@ static void set_time(struct rtc_time *time)
time->tm_hour, time->tm_min, time->tm_sec);
write_elapsed_second(current_sec - epoch_sec);
+
+ return 0;
}
-static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
- DECLARE_WAITQUEUE(wait, current);
- unsigned long irq_data;
- int retval = 0;
-
- if (count != sizeof(unsigned int) && count != sizeof(unsigned long))
- return -EINVAL;
-
- add_wait_queue(&rtc_wait, &wait);
-
- do {
- __set_current_state(TASK_INTERRUPTIBLE);
+ unsigned long low, mid, high;
+ struct rtc_time *time = &wkalrm->time;
- spin_lock_irq(&rtc_lock);
- irq_data = rtc_irq_data;
- rtc_irq_data = 0;
- spin_unlock_irq(&rtc_lock);
+ spin_lock_irq(&rtc_lock);
- if (irq_data != 0)
- break;
+ low = rtc1_read(ECMPLREG);
+ mid = rtc1_read(ECMPMREG);
+ high = rtc1_read(ECMPHREG);
- if (file->f_flags & O_NONBLOCK) {
- retval = -EAGAIN;
- break;
- }
+ spin_unlock_irq(&rtc_lock);
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- } while (1);
+ rtc_time_to_tm((high << 17) | (mid << 1) | (low >> 15), time);
- if (retval == 0) {
- if (count == sizeof(unsigned int)) {
- retval = put_user(irq_data, (unsigned int __user *)buf);
- if (retval == 0)
- retval = sizeof(unsigned int);
- } else {
- retval = put_user(irq_data, (unsigned long __user *)buf);
- if (retval == 0)
- retval = sizeof(unsigned long);
- }
+ return 0;
+}
- }
+static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ unsigned long alarm_sec;
+ struct rtc_time *time = &wkalrm->time;
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&rtc_wait, &wait);
+ alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
- return retval;
-}
+ spin_lock_irq(&rtc_lock);
-static unsigned int rtc_poll(struct file *file, struct poll_table_struct *table)
-{
- poll_wait(file, &rtc_wait, table);
+ rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
+ rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
+ rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
- if (rtc_irq_data != 0)
- return POLLIN | POLLRDNORM;
+ spin_unlock_irq(&rtc_lock);
return 0;
}
-static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from)
+static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
- struct rtc_time time;
unsigned long count;
switch (cmd) {
@@ -290,33 +233,6 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from
case RTC_PIE_OFF:
disable_irq(RTCLONG1_IRQ);
break;
- case RTC_ALM_SET:
- if (copy_from_user(&time, (struct rtc_time __user *)arg,
- sizeof(struct rtc_time)))
- return -EFAULT;
-
- set_alarm(&time);
- break;
- case RTC_ALM_READ:
- memset(&time, 0, sizeof(struct rtc_time));
- read_alarm(&time);
- break;
- case RTC_RD_TIME:
- memset(&time, 0, sizeof(struct rtc_time));
- read_time(&time);
- if (copy_to_user((void __user *)arg, &time, sizeof(struct rtc_time)))
- return -EFAULT;
- break;
- case RTC_SET_TIME:
- if (capable(CAP_SYS_TIME) == 0)
- return -EACCES;
-
- if (copy_from_user(&time, (struct rtc_time __user *)arg,
- sizeof(struct rtc_time)))
- return -EFAULT;
-
- set_time(&time);
- break;
case RTC_IRQP_READ:
return put_user(periodic_frequency, (unsigned long __user *)arg);
break;
@@ -324,8 +240,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from
if (arg > MAX_PERIODIC_RATE)
return -EINVAL;
- if (from == FUNCTION_RTC_IOCTL && arg > MAX_USER_PERIODIC_RATE &&
- capable(CAP_SYS_RESOURCE) == 0)
+ if (arg > MAX_USER_PERIODIC_RATE && capable(CAP_SYS_RESOURCE) == 0)
return -EACCES;
periodic_frequency = arg;
@@ -355,211 +270,52 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from
epoch = arg;
break;
default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- return rtc_do_ioctl(cmd, arg, FUNCTION_RTC_IOCTL);
-}
-
-static int rtc_open(struct inode *inode, struct file *file)
-{
- spin_lock_irq(&rtc_lock);
-
- if (rtc_status == RTC_OPEN) {
- spin_unlock_irq(&rtc_lock);
- return -EBUSY;
+ return -ENOIOCTLCMD;
}
- rtc_status = RTC_OPEN;
- rtc_irq_data = 0;
-
- spin_unlock_irq(&rtc_lock);
-
return 0;
}
-static int rtc_release(struct inode *inode, struct file *file)
-{
- if (file->f_flags & FASYNC)
- (void)fasync_helper(-1, file, 0, &rtc_async_queue);
-
- spin_lock_irq(&rtc_lock);
-
- rtc1_write(ECMPLREG, 0);
- rtc1_write(ECMPMREG, 0);
- rtc1_write(ECMPHREG, 0);
- rtc1_write(RTCL1LREG, 0);
- rtc1_write(RTCL1HREG, 0);
-
- rtc_status = RTC_RELEASE;
-
- spin_unlock_irq(&rtc_lock);
-
- disable_irq(ELAPSEDTIME_IRQ);
- disable_irq(RTCLONG1_IRQ);
-
- return 0;
-}
-
-static int rtc_fasync(int fd, struct file *file, int on)
-{
- return fasync_helper(fd, file, on, &rtc_async_queue);
-}
-
-static struct file_operations rtc_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = rtc_read,
- .poll = rtc_poll,
- .ioctl = rtc_ioctl,
- .open = rtc_open,
- .release = rtc_release,
- .fasync = rtc_fasync,
-};
-
static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- spin_lock(&rtc_lock);
- rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
-
- rtc_irq_data += 0x100;
- rtc_irq_data &= ~0xff;
- rtc_irq_data |= RTC_AF;
- spin_unlock(&rtc_lock);
+ struct platform_device *pdev = (struct platform_device *)dev_id;
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
- spin_lock(&rtc_lock);
- if (rtc_callback)
- rtc_callback->func(rtc_callback->private_data);
- spin_unlock(&rtc_lock);
-
- wake_up_interruptible(&rtc_wait);
+ rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
- kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
+ rtc_update_irq(&rtc->class_dev, 1, RTC_AF);
return IRQ_HANDLED;
}
static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
+ struct platform_device *pdev = (struct platform_device *)dev_id;
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
unsigned long count = periodic_count;
- spin_lock(&rtc_lock);
rtc2_write(RTCINTREG, RTCLONG1_INT);
rtc1_write(RTCL1LREG, count);
rtc1_write(RTCL1HREG, count >> 16);
- rtc_irq_data += 0x100;
- rtc_irq_data &= ~0xff;
- rtc_irq_data |= RTC_PF;
- spin_unlock(&rtc_lock);
-
- spin_lock(&rtc_task_lock);
- if (rtc_callback)
- rtc_callback->func(rtc_callback->private_data);
- spin_unlock(&rtc_task_lock);
-
- wake_up_interruptible(&rtc_wait);
-
- kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
+ rtc_update_irq(&rtc->class_dev, 1, RTC_PF);
return IRQ_HANDLED;
}
-int rtc_register(rtc_task_t *task)
-{
- if (task == NULL || task->func == NULL)
- return -EINVAL;
-
- spin_lock_irq(&rtc_lock);
- if (rtc_status == RTC_OPEN) {
- spin_unlock_irq(&rtc_lock);
- return -EBUSY;
- }
-
- spin_lock(&rtc_task_lock);
- if (rtc_callback != NULL) {
- spin_unlock(&rtc_task_lock);
- spin_unlock_irq(&rtc_task_lock);
- return -EBUSY;
- }
-
- rtc_callback = task;
- spin_unlock(&rtc_task_lock);
-
- rtc_status = RTC_OPEN;
-
- spin_unlock_irq(&rtc_lock);
-
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(rtc_register);
-
-int rtc_unregister(rtc_task_t *task)
-{
- spin_lock_irq(&rtc_task_lock);
- if (task == NULL || rtc_callback != task) {
- spin_unlock_irq(&rtc_task_lock);
- return -ENXIO;
- }
-
- spin_lock(&rtc_lock);
-
- rtc1_write(ECMPLREG, 0);
- rtc1_write(ECMPMREG, 0);
- rtc1_write(ECMPHREG, 0);
- rtc1_write(RTCL1LREG, 0);
- rtc1_write(RTCL1HREG, 0);
-
- rtc_status = RTC_RELEASE;
-
- spin_unlock(&rtc_lock);
-
- rtc_callback = NULL;
-
- spin_unlock_irq(&rtc_task_lock);
-
- disable_irq(ELAPSEDTIME_IRQ);
- disable_irq(RTCLONG1_IRQ);
-
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(rtc_unregister);
-
-int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
-{
- int retval = 0;
-
- spin_lock_irq(&rtc_task_lock);
-
- if (rtc_callback != task)
- retval = -ENXIO;
- else
- rtc_do_ioctl(cmd, arg, FUNCTION_RTC_CONTROL);
-
- spin_unlock_irq(&rtc_task_lock);
-
- return retval;
-}
-
-EXPORT_SYMBOL_GPL(rtc_control);
-
-static struct miscdevice rtc_miscdevice = {
- .minor = RTC_MINOR,
- .name = rtc_name,
- .fops = &rtc_fops,
+static struct rtc_class_ops vr41xx_rtc_ops = {
+ .release = vr41xx_rtc_release,
+ .ioctl = vr41xx_rtc_ioctl,
+ .read_time = vr41xx_rtc_read_time,
+ .set_time = vr41xx_rtc_set_time,
+ .read_alarm = vr41xx_rtc_read_alarm,
+ .set_alarm = vr41xx_rtc_set_alarm,
};
static int __devinit rtc_probe(struct platform_device *pdev)
{
+ struct rtc_device *rtc;
unsigned int irq;
int retval;
@@ -577,13 +333,13 @@ static int __devinit rtc_probe(struct platform_device *pdev)
return -EBUSY;
}
- retval = misc_register(&rtc_miscdevice);
- if (retval < 0) {
+ rtc = rtc_device_register(rtc_name, &pdev->dev, &vr41xx_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
iounmap(rtc1_base);
iounmap(rtc2_base);
rtc1_base = NULL;
rtc2_base = NULL;
- return retval;
+ return PTR_ERR(rtc);
}
spin_lock_irq(&rtc_lock);
@@ -594,24 +350,20 @@ static int __devinit rtc_probe(struct platform_device *pdev)
rtc1_write(RTCL1LREG, 0);
rtc1_write(RTCL1HREG, 0);
- rtc_status = RTC_RELEASE;
- rtc_irq_data = 0;
-
spin_unlock_irq(&rtc_lock);
- init_waitqueue_head(&rtc_wait);
-
irq = ELAPSEDTIME_IRQ;
retval = request_irq(irq, elapsedtime_interrupt, SA_INTERRUPT,
- "elapsed_time", NULL);
+ "elapsed_time", pdev);
if (retval == 0) {
irq = RTCLONG1_IRQ;
retval = request_irq(irq, rtclong1_interrupt, SA_INTERRUPT,
- "rtclong1", NULL);
+ "rtclong1", pdev);
}
if (retval < 0) {
printk(KERN_ERR "rtc: IRQ%d is busy\n", irq);
+ rtc_device_unregister(rtc);
if (irq == RTCLONG1_IRQ)
free_irq(ELAPSEDTIME_IRQ, NULL);
iounmap(rtc1_base);
@@ -621,23 +373,25 @@ static int __devinit rtc_probe(struct platform_device *pdev)
return retval;
}
+ platform_set_drvdata(pdev, rtc);
+
disable_irq(ELAPSEDTIME_IRQ);
disable_irq(RTCLONG1_IRQ);
- spin_lock_init(&rtc_task_lock);
-
printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n");
return 0;
}
-static int __devexit rtc_remove(struct platform_device *dev)
+static int __devexit rtc_remove(struct platform_device *pdev)
{
- int retval;
+ struct rtc_device *rtc;
- retval = misc_deregister(&rtc_miscdevice);
- if (retval < 0)
- return retval;
+ rtc = platform_get_drvdata(pdev);
+ if (rtc != NULL)
+ rtc_device_unregister(rtc);
+
+ platform_set_drvdata(pdev, NULL);
free_irq(ELAPSEDTIME_IRQ, NULL);
free_irq(RTCLONG1_IRQ, NULL);
@@ -651,7 +405,7 @@ static int __devexit rtc_remove(struct platform_device *dev)
static struct platform_device *rtc_platform_device;
-static struct platform_driver rtc_device_driver = {
+static struct platform_driver rtc_platform_driver = {
.probe = rtc_probe,
.remove = __devexit_p(rtc_remove),
.driver = {
@@ -686,7 +440,7 @@ static int __init vr41xx_rtc_init(void)
}
rtc_platform_device = platform_device_alloc("RTC", -1);
- if (!rtc_platform_device)
+ if (rtc_platform_device == NULL)
return -ENOMEM;
retval = platform_device_add_resources(rtc_platform_device,
@@ -700,7 +454,7 @@ static int __init vr41xx_rtc_init(void)
return retval;
}
- retval = platform_driver_register(&rtc_device_driver);
+ retval = platform_driver_register(&rtc_platform_driver);
if (retval < 0)
platform_device_unregister(rtc_platform_device);
@@ -709,7 +463,7 @@ static int __init vr41xx_rtc_init(void)
static void __exit vr41xx_rtc_exit(void)
{
- platform_driver_unregister(&rtc_device_driver);
+ platform_driver_unregister(&rtc_platform_driver);
platform_device_unregister(rtc_platform_device);
}
diff --git a/drivers/i2c/chips/x1205.c b/drivers/rtc/rtc-x1205.c
index 245fffa92db..788b6d1f8f2 100644
--- a/drivers/i2c/chips/x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -1,32 +1,25 @@
/*
- * x1205.c - An i2c driver for the Xicor X1205 RTC
- * Copyright 2004 Karen Spearel
- * Copyright 2005 Alessandro Zummo
+ * An i2c driver for the Xicor/Intersil X1205 RTC
+ * Copyright 2004 Karen Spearel
+ * Copyright 2005 Alessandro Zummo
*
- * please send all reports to:
- * kas11 at tampabay dot rr dot com
- * a dot zummo at towertech dot it
+ * please send all reports to:
+ * Karen Spearel <kas111 at gmail dot com>
+ * Alessandro Zummo <a.zummo@towertech.it>
*
- * based on the other drivers in this same directory.
+ * based on a lot of other RTC drivers.
*
- * This program is free software; 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 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/i2c.h>
-#include <linux/string.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
-#include <linux/list.h>
+#include <linux/delay.h>
-#include <linux/x1205.h>
-
-#define DRV_VERSION "0.9.9"
+#define DRV_VERSION "1.0.7"
/* Addresses to scan: none. This chip is located at
* 0x6f and uses a two bytes register addressing.
@@ -40,8 +33,6 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD;
-I2C_CLIENT_MODULE_PARM(hctosys,
- "Set the system time from the hardware clock upon initialization");
/* offsets into CCR area */
@@ -101,107 +92,35 @@ I2C_CLIENT_MODULE_PARM(hctosys,
static int x1205_attach(struct i2c_adapter *adapter);
static int x1205_detach(struct i2c_client *client);
static int x1205_probe(struct i2c_adapter *adapter, int address, int kind);
-static int x1205_command(struct i2c_client *client, unsigned int cmd,
- void *arg);
static struct i2c_driver x1205_driver = {
- .driver = {
+ .driver = {
.name = "x1205",
},
+ .id = I2C_DRIVERID_X1205,
.attach_adapter = &x1205_attach,
.detach_client = &x1205_detach,
};
-struct x1205_data {
- struct i2c_client client;
- struct list_head list;
- unsigned int epoch;
-};
-
-static const unsigned char days_in_mo[] =
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
-static LIST_HEAD(x1205_clients);
-
-/* Workaround until the I2C subsytem will allow to send
- * commands to a specific client. This function will send the command
- * to the first client.
- */
-int x1205_do_command(unsigned int cmd, void *arg)
-{
- struct list_head *walk;
- struct list_head *tmp;
- struct x1205_data *data;
-
- list_for_each_safe(walk, tmp, &x1205_clients) {
- data = list_entry(walk, struct x1205_data, list);
- return x1205_command(&data->client, cmd, arg);
- }
-
- return -ENODEV;
-}
-
-#define is_leap(year) \
- ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-
-/* make sure the rtc_time values are in bounds */
-static int x1205_validate_tm(struct rtc_time *tm)
-{
- int year = tm->tm_year + 1900;
-
- if ((tm->tm_year < 70) || (tm->tm_year > 255))
- return -EINVAL;
-
- if ((tm->tm_mon > 11) || (tm->tm_mday == 0))
- return -EINVAL;
-
- if (tm->tm_mday > days_in_mo[tm->tm_mon]
- + ((tm->tm_mon == 1) && is_leap(year)))
- return -EINVAL;
-
- if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60))
- return -EINVAL;
-
- return 0;
-}
-
/*
* In the routines that deal directly with the x1205 hardware, we use
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
* Epoch is initialized as 2000. Time is set to UTC.
*/
static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
- u8 reg_base)
+ unsigned char reg_base)
{
unsigned char dt_addr[2] = { 0, reg_base };
- static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
- unsigned char buf[8], sr;
+ unsigned char buf[8];
struct i2c_msg msgs[] = {
- { client->addr, 0, 2, sr_addr }, /* setup read ptr */
- { client->addr, I2C_M_RD, 1, &sr }, /* read status */
{ client->addr, 0, 2, dt_addr }, /* setup read ptr */
{ client->addr, I2C_M_RD, 8, buf }, /* read date */
};
- struct x1205_data *data = i2c_get_clientdata(client);
-
- /* read status register */
- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
- return -EIO;
- }
-
- /* check for battery failure */
- if (sr & X1205_SR_RTCF) {
- dev_warn(&client->dev,
- "Clock had a power failure, you must set the date.\n");
- return -EINVAL;
- }
-
/* read date registers */
- if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) {
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
return -EIO;
}
@@ -217,9 +136,9 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
tm->tm_min = BCD2BIN(buf[CCR_MIN]);
tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
- tm->tm_mon = BCD2BIN(buf[CCR_MONTH]);
- data->epoch = BCD2BIN(buf[CCR_Y2K]) * 100;
- tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + data->epoch - 1900;
+ tm->tm_mon = BCD2BIN(buf[CCR_MONTH]) - 1; /* mon is 0-11 */
+ tm->tm_year = BCD2BIN(buf[CCR_YEAR])
+ + (BCD2BIN(buf[CCR_Y2K]) * 100) - 1900;
tm->tm_wday = buf[CCR_WDAY];
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
@@ -231,11 +150,28 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
return 0;
}
+static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
+{
+ static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 2, sr_addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 1, sr }, /* read status */
+ };
+
+ /* read status register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
int datetoo, u8 reg_base)
{
- int i, err, xfer;
-
+ int i, xfer;
unsigned char buf[8];
static const unsigned char wel[3] = { 0, X1205_REG_SR,
@@ -246,17 +182,10 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
- struct x1205_data *data = i2c_get_clientdata(client);
-
- /* check if all values in the tm struct are correct */
- if ((err = x1205_validate_tm(tm)) < 0)
- return err;
-
- dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
- "mday=%d, mon=%d, year=%d, wday=%d\n",
+ dev_dbg(&client->dev,
+ "%s: secs=%d, mins=%d, hours=%d\n",
__FUNCTION__,
- tm->tm_sec, tm->tm_min, tm->tm_hour,
- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+ tm->tm_sec, tm->tm_min, tm->tm_hour);
buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
buf[CCR_MIN] = BIN2BCD(tm->tm_min);
@@ -266,26 +195,29 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
/* should we also set the date? */
if (datetoo) {
+ dev_dbg(&client->dev,
+ "%s: mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
- /* month, 0 - 11 */
- buf[CCR_MONTH] = BIN2BCD(tm->tm_mon);
+ /* month, 1 - 12 */
+ buf[CCR_MONTH] = BIN2BCD(tm->tm_mon + 1);
- /* year, since 1900 */
- buf[CCR_YEAR] = BIN2BCD(tm->tm_year + 1900 - data->epoch);
+ /* year, since the rtc epoch*/
+ buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100);
buf[CCR_WDAY] = tm->tm_wday & 0x07;
- buf[CCR_Y2K] = BIN2BCD(data->epoch / 100);
+ buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100);
}
/* this sequence is required to unlock the chip */
- xfer = i2c_master_send(client, wel, 3);
- if (xfer != 3) {
+ if ((xfer = i2c_master_send(client, wel, 3)) != 3) {
dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer);
return -EIO;
}
- xfer = i2c_master_send(client, rwel, 3);
- if (xfer != 3) {
+ if ((xfer = i2c_master_send(client, rwel, 3)) != 3) {
dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer);
return -EIO;
}
@@ -305,8 +237,7 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
};
/* disable further writes */
- xfer = i2c_master_send(client, diswe, 3);
- if (xfer != 3) {
+ if ((xfer = i2c_master_send(client, diswe, 3)) != 3) {
dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer);
return -EIO;
}
@@ -314,6 +245,20 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
return 0;
}
+static int x1205_fix_osc(struct i2c_client *client)
+{
+ int err;
+ struct rtc_time tm;
+
+ tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
+
+ if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0)
+ dev_err(&client->dev,
+ "unable to restart the oscillator\n");
+
+ return err;
+}
+
static int x1205_get_dtrim(struct i2c_client *client, int *trim)
{
unsigned char dtr;
@@ -380,60 +325,9 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim)
return 0;
}
-static int x1205_hctosys(struct i2c_client *client)
-{
- int err;
-
- struct rtc_time tm;
- struct timespec tv;
-
- err = x1205_command(client, X1205_CMD_GETDATETIME, &tm);
-
- if (err) {
- dev_err(&client->dev,
- "Unable to set the system clock\n");
- return err;
- }
-
- /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
- * whether it stores the most close value or the value with partial
- * seconds truncated. However, it is important that we use it to store
- * the truncated value. This is because otherwise it is necessary,
- * in an rtc sync function, to read both xtime.tv_sec and
- * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
- * of >32bits is not possible. So storing the most close value would
- * slow down the sync API. So here we have the truncated value and
- * the best guess is to add 0.5s.
- */
-
- tv.tv_nsec = NSEC_PER_SEC >> 1;
-
- /* WARNING: this is not the C library 'mktime' call, it is a built in
- * inline function from include/linux/time.h. It expects (requires)
- * the month to be in the range 1-12
- */
-
- tv.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1,
- tm.tm_mday, tm.tm_hour,
- tm.tm_min, tm.tm_sec);
-
- do_settimeofday(&tv);
-
- dev_info(&client->dev,
- "setting the system clock to %d-%d-%d %d:%d:%d\n",
- tm.tm_year + 1900, tm.tm_mon + 1,
- tm.tm_mday, tm.tm_hour, tm.tm_min,
- tm.tm_sec);
-
- return 0;
-}
-
struct x1205_limit
{
- unsigned char reg;
- unsigned char mask;
- unsigned char min;
- unsigned char max;
+ unsigned char reg, mask, min, max;
};
static int x1205_validate_client(struct i2c_client *client)
@@ -477,11 +371,10 @@ static int x1205_validate_client(struct i2c_client *client)
{ client->addr, I2C_M_RD, 1, &buf },
};
- xfer = i2c_transfer(client->adapter, msgs, 2);
- if (xfer != 2) {
+ if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
dev_err(&client->adapter->dev,
"%s: could not read register %x\n",
- __FUNCTION__, addr[1]);
+ __FUNCTION__, probe_zero_pattern[i]);
return -EIO;
}
@@ -489,7 +382,7 @@ static int x1205_validate_client(struct i2c_client *client)
if ((buf & probe_zero_pattern[i+1]) != 0) {
dev_err(&client->adapter->dev,
"%s: register=%02x, zero pattern=%d, value=%x\n",
- __FUNCTION__, addr[1], i, buf);
+ __FUNCTION__, probe_zero_pattern[i], i, buf);
return -ENODEV;
}
@@ -506,12 +399,10 @@ static int x1205_validate_client(struct i2c_client *client)
{ client->addr, I2C_M_RD, 1, &reg },
};
- xfer = i2c_transfer(client->adapter, msgs, 2);
-
- if (xfer != 2) {
+ if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
dev_err(&client->adapter->dev,
"%s: could not read register %x\n",
- __FUNCTION__, addr[1]);
+ __FUNCTION__, probe_limits_pattern[i].reg);
return -EIO;
}
@@ -522,7 +413,8 @@ static int x1205_validate_client(struct i2c_client *client)
value < probe_limits_pattern[i].min) {
dev_dbg(&client->adapter->dev,
"%s: register=%x, lim pattern=%d, value=%d\n",
- __FUNCTION__, addr[1], i, value);
+ __FUNCTION__, probe_limits_pattern[i].reg,
+ i, value);
return -ENODEV;
}
@@ -531,37 +423,88 @@ static int x1205_validate_client(struct i2c_client *client)
return 0;
}
-static int x1205_attach(struct i2c_adapter *adapter)
+static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+ return x1205_get_datetime(to_i2c_client(dev),
+ &alrm->time, X1205_ALM0_BASE);
+}
- return i2c_probe(adapter, &addr_data, x1205_probe);
+static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ return x1205_set_datetime(to_i2c_client(dev),
+ &alrm->time, 1, X1205_ALM0_BASE);
}
-int x1205_direct_attach(int adapter_id,
- struct i2c_client_address_data *address_data)
+static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- int err;
- struct i2c_adapter *adapter = i2c_get_adapter(adapter_id);
+ return x1205_get_datetime(to_i2c_client(dev),
+ tm, X1205_CCR_BASE);
+}
+
+static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return x1205_set_datetime(to_i2c_client(dev),
+ tm, 1, X1205_CCR_BASE);
+}
+
+static int x1205_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ int err, dtrim, atrim;
- if (adapter) {
- err = i2c_probe(adapter,
- address_data, x1205_probe);
+ if ((err = x1205_get_dtrim(to_i2c_client(dev), &dtrim)) == 0)
+ seq_printf(seq, "digital_trim\t: %d ppm\n", dtrim);
- i2c_put_adapter(adapter);
+ if ((err = x1205_get_atrim(to_i2c_client(dev), &atrim)) == 0)
+ seq_printf(seq, "analog_trim\t: %d.%02d pF\n",
+ atrim / 1000, atrim % 1000);
+ return 0;
+}
+static struct rtc_class_ops x1205_rtc_ops = {
+ .proc = x1205_rtc_proc,
+ .read_time = x1205_rtc_read_time,
+ .set_time = x1205_rtc_set_time,
+ .read_alarm = x1205_rtc_read_alarm,
+ .set_alarm = x1205_rtc_set_alarm,
+};
+
+static ssize_t x1205_sysfs_show_atrim(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err, atrim;
+
+ err = x1205_get_atrim(to_i2c_client(dev), &atrim);
+ if (err)
return err;
- }
- return -ENODEV;
+ return sprintf(buf, "%d.%02d pF\n", atrim / 1000, atrim % 1000);
}
+static DEVICE_ATTR(atrim, S_IRUGO, x1205_sysfs_show_atrim, NULL);
-static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
+static ssize_t x1205_sysfs_show_dtrim(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct i2c_client *client;
- struct x1205_data *data;
+ int err, dtrim;
+
+ err = x1205_get_dtrim(to_i2c_client(dev), &dtrim);
+ if (err)
+ return err;
+ return sprintf(buf, "%d ppm\n", dtrim);
+}
+static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL);
+
+static int x1205_attach(struct i2c_adapter *adapter)
+{
+ return i2c_probe(adapter, &addr_data, x1205_probe);
+}
+
+static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
+{
int err = 0;
+ unsigned char sr;
+ struct i2c_client *client;
+ struct rtc_device *rtc;
dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
@@ -570,22 +513,17 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
goto exit;
}
- if (!(data = kzalloc(sizeof(struct x1205_data), GFP_KERNEL))) {
+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- /* Initialize our structures */
- data->epoch = 2000;
-
- client = &data->client;
+ /* I2C client */
client->addr = address;
client->driver = &x1205_driver;
client->adapter = adapter;
- strlcpy(client->name, "x1205", I2C_NAME_SIZE);
-
- i2c_set_clientdata(client, data);
+ strlcpy(client->name, x1205_driver.driver.name, I2C_NAME_SIZE);
/* Verify the chip is really an X1205 */
if (kind < 0) {
@@ -599,18 +537,41 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
if ((err = i2c_attach_client(client)))
goto exit_kfree;
- list_add(&data->list, &x1205_clients);
-
dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
- /* If requested, set the system time */
- if (hctosys)
- x1205_hctosys(client);
+ rtc = rtc_device_register(x1205_driver.driver.name, &client->dev,
+ &x1205_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ err = PTR_ERR(rtc);
+ goto exit_detach;
+ }
+
+ i2c_set_clientdata(client, rtc);
+
+ /* Check for power failures and eventualy enable the osc */
+ if ((err = x1205_get_status(client, &sr)) == 0) {
+ if (sr & X1205_SR_RTCF) {
+ dev_err(&client->dev,
+ "power failure detected, "
+ "please set the clock\n");
+ udelay(50);
+ x1205_fix_osc(client);
+ }
+ }
+ else
+ dev_err(&client->dev, "couldn't read status\n");
+
+ device_create_file(&client->dev, &dev_attr_atrim);
+ device_create_file(&client->dev, &dev_attr_dtrim);
return 0;
+exit_detach:
+ i2c_detach_client(client);
+
exit_kfree:
- kfree(data);
+ kfree(client);
exit:
return err;
@@ -619,61 +580,19 @@ exit:
static int x1205_detach(struct i2c_client *client)
{
int err;
- struct x1205_data *data = i2c_get_clientdata(client);
+ struct rtc_device *rtc = i2c_get_clientdata(client);
- dev_dbg(&client->dev, "%s\n", __FUNCTION__);
+ if (rtc)
+ rtc_device_unregister(rtc);
if ((err = i2c_detach_client(client)))
return err;
- list_del(&data->list);
-
- kfree(data);
+ kfree(client);
return 0;
}
-static int x1205_command(struct i2c_client *client, unsigned int cmd,
- void *param)
-{
- if (param == NULL)
- return -EINVAL;
-
- if (!capable(CAP_SYS_TIME))
- return -EACCES;
-
- dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
-
- switch (cmd) {
- case X1205_CMD_GETDATETIME:
- return x1205_get_datetime(client, param, X1205_CCR_BASE);
-
- case X1205_CMD_SETTIME:
- return x1205_set_datetime(client, param, 0,
- X1205_CCR_BASE);
-
- case X1205_CMD_SETDATETIME:
- return x1205_set_datetime(client, param, 1,
- X1205_CCR_BASE);
-
- case X1205_CMD_GETALARM:
- return x1205_get_datetime(client, param, X1205_ALM0_BASE);
-
- case X1205_CMD_SETALARM:
- return x1205_set_datetime(client, param, 1,
- X1205_ALM0_BASE);
-
- case X1205_CMD_GETDTRIM:
- return x1205_get_dtrim(client, param);
-
- case X1205_CMD_GETATRIM:
- return x1205_get_atrim(client, param);
-
- default:
- return -EINVAL;
- }
-}
-
static int __init x1205_init(void)
{
return i2c_add_driver(&x1205_driver);
@@ -685,14 +604,11 @@ static void __exit x1205_exit(void)
}
MODULE_AUTHOR(
- "Karen Spearel <kas11@tampabay.rr.com>, "
+ "Karen Spearel <kas111 at gmail dot com>, "
"Alessandro Zummo <a.zummo@towertech.it>");
-MODULE_DESCRIPTION("Xicor X1205 RTC driver");
+MODULE_DESCRIPTION("Xicor/Intersil X1205 RTC driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-EXPORT_SYMBOL_GPL(x1205_do_command);
-EXPORT_SYMBOL_GPL(x1205_direct_attach);
-
module_init(x1205_init);
module_exit(x1205_exit);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 0a9f12c4e91..cfb1fff3787 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -315,6 +315,11 @@ dasd_increase_state(struct dasd_device *device)
rc = dasd_state_basic_to_ready(device);
if (!rc &&
+ device->state == DASD_STATE_UNFMT &&
+ device->target > DASD_STATE_UNFMT)
+ rc = -EPERM;
+
+ if (!rc &&
device->state == DASD_STATE_READY &&
device->target >= DASD_STATE_ONLINE)
rc = dasd_state_ready_to_online(device);
@@ -1257,25 +1262,28 @@ __dasd_start_head(struct dasd_device * device)
if (list_empty(&device->ccw_queue))
return;
cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
- /* check FAILFAST */
+ if (cqr->status != DASD_CQR_QUEUED)
+ return;
+ /* Non-temporary stop condition will trigger fail fast */
if (device->stopped & ~DASD_STOPPED_PENDING &&
test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
(!dasd_eer_enabled(device))) {
cqr->status = DASD_CQR_FAILED;
dasd_schedule_bh(device);
+ return;
}
- if ((cqr->status == DASD_CQR_QUEUED) &&
- (!device->stopped)) {
- /* try to start the first I/O that can be started */
- rc = device->discipline->start_IO(cqr);
- if (rc == 0)
- dasd_set_timer(device, cqr->expires);
- else if (rc == -EACCES) {
- dasd_schedule_bh(device);
- } else
- /* Hmpf, try again in 1/2 sec */
- dasd_set_timer(device, 50);
- }
+ /* Don't try to start requests if device is stopped */
+ if (device->stopped)
+ return;
+
+ rc = device->discipline->start_IO(cqr);
+ if (rc == 0)
+ dasd_set_timer(device, cqr->expires);
+ else if (rc == -EACCES) {
+ dasd_schedule_bh(device);
+ } else
+ /* Hmpf, try again in 1/2 sec */
+ dasd_set_timer(device, 50);
}
/*
@@ -1968,7 +1976,7 @@ int
dasd_generic_set_offline (struct ccw_device *cdev)
{
struct dasd_device *device;
- int max_count;
+ int max_count, open_count;
device = dasd_device_from_cdev(cdev);
if (IS_ERR(device))
@@ -1985,10 +1993,16 @@ dasd_generic_set_offline (struct ccw_device *cdev)
* in the other openers.
*/
max_count = device->bdev ? 0 : -1;
- if (atomic_read(&device->open_count) > max_count) {
- printk (KERN_WARNING "Can't offline dasd device with open"
- " count = %i.\n",
- atomic_read(&device->open_count));
+ open_count = (int) atomic_read(&device->open_count);
+ if (open_count > max_count) {
+ if (open_count > 0)
+ printk (KERN_WARNING "Can't offline dasd device with "
+ "open count = %i.\n",
+ open_count);
+ else
+ printk (KERN_WARNING "%s",
+ "Can't offline dasd device due to internal "
+ "use\n");
clear_bit(DASD_FLAG_OFFLINE, &device->flags);
dasd_put_device(device);
return -EBUSY;
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index c1c6f138115..216bc4fba19 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -45,6 +45,7 @@ struct dasd_devmap {
unsigned int devindex;
unsigned short features;
struct dasd_device *device;
+ struct dasd_uid uid;
};
/*
@@ -716,6 +717,68 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr, char *bu
static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
+static ssize_t
+dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct dasd_devmap *devmap;
+ int alias;
+
+ devmap = dasd_find_busid(dev->bus_id);
+ spin_lock(&dasd_devmap_lock);
+ if (!IS_ERR(devmap))
+ alias = devmap->uid.alias;
+ else
+ alias = 0;
+ spin_unlock(&dasd_devmap_lock);
+
+ return sprintf(buf, alias ? "1\n" : "0\n");
+}
+
+static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
+
+static ssize_t
+dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct dasd_devmap *devmap;
+ char *vendor;
+
+ devmap = dasd_find_busid(dev->bus_id);
+ spin_lock(&dasd_devmap_lock);
+ if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
+ vendor = devmap->uid.vendor;
+ else
+ vendor = "";
+ spin_unlock(&dasd_devmap_lock);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
+}
+
+static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
+
+#define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial */ 14 + 1 +\
+ /* SSID */ 4 + 1 + /* unit addr */ 2 + 1)
+
+static ssize_t
+dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct dasd_devmap *devmap;
+ char uid[UID_STRLEN];
+
+ devmap = dasd_find_busid(dev->bus_id);
+ spin_lock(&dasd_devmap_lock);
+ if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
+ snprintf(uid, sizeof(uid), "%s.%s.%04x.%02x",
+ devmap->uid.vendor, devmap->uid.serial,
+ devmap->uid.ssid, devmap->uid.unit_addr);
+ else
+ uid[0] = 0;
+ spin_unlock(&dasd_devmap_lock);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", uid);
+}
+
+static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
+
/*
* extended error-reporting
*/
@@ -759,6 +822,9 @@ static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
static struct attribute * dasd_attrs[] = {
&dev_attr_readonly.attr,
&dev_attr_discipline.attr,
+ &dev_attr_alias.attr,
+ &dev_attr_vendor.attr,
+ &dev_attr_uid.attr,
&dev_attr_use_diag.attr,
&dev_attr_eer_enabled.attr,
NULL,
@@ -768,6 +834,42 @@ static struct attribute_group dasd_attr_group = {
.attrs = dasd_attrs,
};
+
+/*
+ * Return copy of the device unique identifier.
+ */
+int
+dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
+{
+ struct dasd_devmap *devmap;
+
+ devmap = dasd_find_busid(cdev->dev.bus_id);
+ if (IS_ERR(devmap))
+ return PTR_ERR(devmap);
+ spin_lock(&dasd_devmap_lock);
+ *uid = devmap->uid;
+ spin_unlock(&dasd_devmap_lock);
+ return 0;
+}
+
+/*
+ * Register the given device unique identifier into devmap struct.
+ */
+int
+dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
+{
+ struct dasd_devmap *devmap;
+
+ devmap = dasd_find_busid(cdev->dev.bus_id);
+ if (IS_ERR(devmap))
+ return PTR_ERR(devmap);
+ spin_lock(&dasd_devmap_lock);
+ devmap->uid = *uid;
+ spin_unlock(&dasd_devmap_lock);
+ return 0;
+}
+EXPORT_SYMBOL(dasd_set_uid);
+
/*
* Return value of the specified feature.
*/
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index ee09ef33d08..7d5a6cee4bd 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -446,6 +446,39 @@ dasd_eckd_cdl_reclen(int recid)
return LABEL_SIZE;
}
+/*
+ * Generate device unique id that specifies the physical device.
+ */
+static int
+dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid)
+{
+ struct dasd_eckd_private *private;
+ struct dasd_eckd_confdata *confdata;
+
+ private = (struct dasd_eckd_private *) device->private;
+ if (!private)
+ return -ENODEV;
+ confdata = &private->conf_data;
+ if (!confdata)
+ return -ENODEV;
+
+ memset(uid, 0, sizeof(struct dasd_uid));
+ strncpy(uid->vendor, confdata->ned1.HDA_manufacturer,
+ sizeof(uid->vendor) - 1);
+ EBCASC(uid->vendor, sizeof(uid->vendor) - 1);
+ strncpy(uid->serial, confdata->ned1.HDA_location,
+ sizeof(uid->serial) - 1);
+ EBCASC(uid->serial, sizeof(uid->serial) - 1);
+ uid->ssid = confdata->neq.subsystemID;
+ if (confdata->ned2.sneq.flags == 0x40) {
+ uid->alias = 1;
+ uid->unit_addr = confdata->ned2.sneq.base_unit_addr;
+ } else
+ uid->unit_addr = confdata->ned1.unit_addr;
+
+ return 0;
+}
+
static int
dasd_eckd_read_conf(struct dasd_device *device)
{
@@ -507,11 +540,15 @@ dasd_eckd_read_conf(struct dasd_device *device)
return 0;
}
-
+/*
+ * Check device characteristics.
+ * If the device is accessible using ECKD discipline, the device is enabled.
+ */
static int
dasd_eckd_check_characteristics(struct dasd_device *device)
{
struct dasd_eckd_private *private;
+ struct dasd_uid uid;
void *rdc_data;
int rc;
@@ -536,6 +573,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
/* Read Device Characteristics */
rdc_data = (void *) &(private->rdc_data);
+ memset(rdc_data, 0, sizeof(rdc_data));
rc = read_dev_chars(device->cdev, &rdc_data, 64);
if (rc) {
DEV_MESSAGE(KERN_WARNING, device,
@@ -556,8 +594,17 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
/* Read Configuration Data */
rc = dasd_eckd_read_conf (device);
- return rc;
+ if (rc)
+ return rc;
+
+ /* Generate device unique id and register in devmap */
+ rc = dasd_eckd_generate_uid(device, &uid);
+ if (rc)
+ return rc;
+ rc = dasd_set_uid(device->cdev, &uid);
+
+ return rc;
}
static struct dasd_ccw_req *
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index ad8524bb7bb..d5734e976e1 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -228,26 +228,36 @@ struct dasd_eckd_confdata {
unsigned char HDA_manufacturer[3];
unsigned char HDA_location[2];
unsigned char HDA_seqno[12];
- __u16 ID;
+ __u8 ID;
+ __u8 unit_addr;
} __attribute__ ((packed)) ned1;
- struct {
+ union {
struct {
- unsigned char identifier:2;
- unsigned char token_id:1;
- unsigned char sno_valid:1;
- unsigned char subst_sno:1;
- unsigned char recNED:1;
- unsigned char emuNED:1;
- unsigned char reserved:1;
- } __attribute__ ((packed)) flags;
- __u8 descriptor;
- __u8 reserved[2];
- unsigned char dev_type[6];
- unsigned char dev_model[3];
- unsigned char DASD_manufacturer[3];
- unsigned char DASD_location[2];
- unsigned char DASD_seqno[12];
- __u16 ID;
+ struct {
+ unsigned char identifier:2;
+ unsigned char token_id:1;
+ unsigned char sno_valid:1;
+ unsigned char subst_sno:1;
+ unsigned char recNED:1;
+ unsigned char emuNED:1;
+ unsigned char reserved:1;
+ } __attribute__ ((packed)) flags;
+ __u8 descriptor;
+ __u8 reserved[2];
+ unsigned char dev_type[6];
+ unsigned char dev_model[3];
+ unsigned char DASD_manufacturer[3];
+ unsigned char DASD_location[2];
+ unsigned char DASD_seqno[12];
+ __u16 ID;
+ } __attribute__ ((packed)) ned;
+ struct {
+ unsigned char flags; /* byte 0 */
+ unsigned char res2[7]; /* byte 1- 7 */
+ unsigned char sua_flags; /* byte 8 */
+ __u8 base_unit_addr; /* byte 9 */
+ unsigned char res3[22]; /* byte 10-31 */
+ } __attribute__ ((packed)) sneq;
} __attribute__ ((packed)) ned2;
struct {
struct {
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index 8fd71ab02ef..b842377cb0c 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -32,9 +32,8 @@ dasd_alloc_erp_request(char *magic, int cplength, int datasize,
int size;
/* Sanity checks */
- if ( magic == NULL || datasize > PAGE_SIZE ||
- (cplength*sizeof(struct ccw1)) > PAGE_SIZE)
- BUG();
+ BUG_ON( magic == NULL || datasize > PAGE_SIZE ||
+ (cplength*sizeof(struct ccw1)) > PAGE_SIZE);
size = (sizeof(struct dasd_ccw_req) + 7L) & -8L;
if (cplength > 0)
@@ -125,8 +124,7 @@ dasd_default_erp_postaction(struct dasd_ccw_req * cqr)
struct dasd_device *device;
int success;
- if (cqr->refers == NULL || cqr->function == NULL)
- BUG();
+ BUG_ON(cqr->refers == NULL || cqr->function == NULL);
device = cqr->device;
success = cqr->status == DASD_CQR_DONE;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 4293ba82752..d4b13e300a7 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -268,6 +268,16 @@ struct dasd_discipline {
extern struct dasd_discipline *dasd_diag_discipline_pointer;
+/*
+ * Unique identifier for dasd device.
+ */
+struct dasd_uid {
+ __u8 alias;
+ char vendor[4];
+ char serial[15];
+ __u16 ssid;
+ __u8 unit_addr;
+};
/*
* Notification numbers for extended error reporting notifications:
@@ -516,6 +526,8 @@ void dasd_devmap_exit(void);
struct dasd_device *dasd_create_device(struct ccw_device *);
void dasd_delete_device(struct dasd_device *);
+int dasd_get_uid(struct ccw_device *, struct dasd_uid *);
+int dasd_set_uid(struct ccw_device *, struct dasd_uid *);
int dasd_get_feature(struct ccw_device *, int);
int dasd_set_feature(struct ccw_device *, int, int);
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 1aa3c261718..ad23aede356 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -294,23 +294,40 @@ out_error:
#endif /* CONFIG_DASD_PROFILE */
}
+/*
+ * Create dasd proc-fs entries.
+ * In case creation failed, cleanup and return -ENOENT.
+ */
int
dasd_proc_init(void)
{
dasd_proc_root_entry = proc_mkdir("dasd", &proc_root);
+ if (!dasd_proc_root_entry)
+ goto out_nodasd;
dasd_proc_root_entry->owner = THIS_MODULE;
dasd_devices_entry = create_proc_entry("devices",
S_IFREG | S_IRUGO | S_IWUSR,
dasd_proc_root_entry);
+ if (!dasd_devices_entry)
+ goto out_nodevices;
dasd_devices_entry->proc_fops = &dasd_devices_file_ops;
dasd_devices_entry->owner = THIS_MODULE;
dasd_statistics_entry = create_proc_entry("statistics",
S_IFREG | S_IRUGO | S_IWUSR,
dasd_proc_root_entry);
+ if (!dasd_statistics_entry)
+ goto out_nostatistics;
dasd_statistics_entry->read_proc = dasd_statistics_read;
dasd_statistics_entry->write_proc = dasd_statistics_write;
dasd_statistics_entry->owner = THIS_MODULE;
return 0;
+
+ out_nostatistics:
+ remove_proc_entry("devices", dasd_proc_root_entry);
+ out_nodevices:
+ remove_proc_entry("dasd", &proc_root);
+ out_nodasd:
+ return -ENOENT;
}
void
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 6badd840340..d4d2ff0a9da 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -54,7 +54,7 @@ kbd_alloc(void) {
if (!kbd)
goto out;
kbd->key_maps = kzalloc(sizeof(key_maps), GFP_KERNEL);
- if (!key_maps)
+ if (!kbd->key_maps)
goto out_kbd;
for (i = 0; i < ARRAY_SIZE(key_maps); i++) {
if (key_maps[i]) {
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index ac10dfb20a6..91e93c78f57 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -24,7 +24,7 @@
/*
* The room for the SCCB (only for writing) is not equal to a pages size
- * (as it is specified as the maximum size in the the SCLP ducumentation)
+ * (as it is specified as the maximum size in the the SCLP documentation)
* because of the additional data structure described above.
*/
#define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer))
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index c3915f60a3a..d71ef1adea5 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -230,14 +230,16 @@ tape_3590_read_attmsg(struct tape_device *device)
* These functions are used to schedule follow-up actions from within an
* interrupt context (like unsolicited interrupts).
*/
+struct work_handler_data {
+ struct tape_device *device;
+ enum tape_op op;
+ struct work_struct work;
+};
+
static void
tape_3590_work_handler(void *data)
{
- struct {
- struct tape_device *device;
- enum tape_op op;
- struct work_struct work;
- } *p = data;
+ struct work_handler_data *p = data;
switch (p->op) {
case TO_MSEN:
@@ -257,11 +259,7 @@ tape_3590_work_handler(void *data)
static int
tape_3590_schedule_work(struct tape_device *device, enum tape_op op)
{
- struct {
- struct tape_device *device;
- enum tape_op op;
- struct work_struct work;
- } *p;
+ struct work_handler_data *p;
if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
return -ENOMEM;
@@ -316,7 +314,7 @@ tape_3590_bread(struct tape_device *device, struct request *req)
rq_for_each_bio(bio, req) {
bio_for_each_segment(bv, bio, i) {
- dst = kmap(bv->bv_page) + bv->bv_offset;
+ dst = page_address(bv->bv_page) + bv->bv_offset;
for (off = 0; off < bv->bv_len;
off += TAPEBLOCK_HSEC_SIZE) {
ccw->flags = CCW_FLAG_CC;
@@ -1168,6 +1166,7 @@ tape_3590_setup_device(struct tape_device *device)
static void
tape_3590_cleanup_device(struct tape_device *device)
{
+ flush_scheduled_work();
tape_std_unassign(device);
kfree(device->discdata);
@@ -1234,6 +1233,7 @@ static struct tape_discipline tape_discipline_3590 = {
static struct ccw_device_id tape_3590_ids[] = {
{CCW_DEVICE_DEVTYPE(0x3590, 0, 0x3590, 0), .driver_info = tape_3590},
+ {CCW_DEVICE_DEVTYPE(0x3592, 0, 0x3592, 0), .driver_info = tape_3592},
{ /* end of list */ }
};
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 5ced2725d6c..b70d9269024 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -198,9 +198,7 @@ tapeblock_request_fn(request_queue_t *queue)
device = (struct tape_device *) queue->queuedata;
DBF_LH(6, "tapeblock_request_fn(device=%p)\n", device);
- if (device == NULL)
- BUG();
-
+ BUG_ON(device == NULL);
tapeblock_trigger_requeue(device);
}
@@ -307,8 +305,7 @@ tapeblock_revalidate_disk(struct gendisk *disk)
int rc;
device = (struct tape_device *) disk->private_data;
- if (!device)
- BUG();
+ BUG_ON(!device);
if (!device->blk_data.medium_changed)
return 0;
@@ -435,16 +432,14 @@ tapeblock_ioctl(
) {
int rc;
int minor;
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct tape_device *device = disk->private_data;
+ struct gendisk *disk;
+ struct tape_device *device;
rc = 0;
disk = inode->i_bdev->bd_disk;
- if (!disk)
- BUG();
+ BUG_ON(!disk);
device = disk->private_data;
- if (!device)
- BUG();
+ BUG_ON(!device);
minor = iminor(inode);
DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command);
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 389ee2c0f44..e6e4086d322 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -210,18 +210,14 @@ tape_state_set(struct tape_device *device, enum tape_state newstate)
return;
}
DBF_EVENT(4, "ts. dev: %x\n", device->first_minor);
- if (device->tape_state < TO_SIZE && device->tape_state >= 0)
- str = tape_state_verbose[device->tape_state];
- else
- str = "UNKNOWN TS";
- DBF_EVENT(4, "old ts: %s\n", str);
- if (device->tape_state < TO_SIZE && device->tape_state >=0 )
+ DBF_EVENT(4, "old ts:\t\n");
+ if (device->tape_state < TS_SIZE && device->tape_state >=0 )
str = tape_state_verbose[device->tape_state];
else
str = "UNKNOWN TS";
DBF_EVENT(4, "%s\n", str);
DBF_EVENT(4, "new ts:\t\n");
- if (newstate < TO_SIZE && newstate >= 0)
+ if (newstate < TS_SIZE && newstate >= 0)
str = tape_state_verbose[newstate];
else
str = "UNKNOWN TS";
diff --git a/drivers/s390/char/tape_std.h b/drivers/s390/char/tape_std.h
index 2d311798edf..1fc95235934 100644
--- a/drivers/s390/char/tape_std.h
+++ b/drivers/s390/char/tape_std.h
@@ -153,6 +153,7 @@ enum s390_tape_type {
tape_3480,
tape_3490,
tape_3590,
+ tape_3592,
};
#endif // _TAPE_STD_H
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index cb8e2e672b6..0960bef7b19 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -414,11 +414,11 @@ cio_ignore_proc_init (void)
entry = create_proc_entry ("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR,
&proc_root);
if (!entry)
- return 0;
+ return -ENOENT;
entry->proc_fops = &cio_ignore_proc_fops;
- return 1;
+ return 0;
}
__initcall (cio_ignore_proc_init);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 6412b2c3edd..72187e54dca 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -242,28 +242,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
if (sch->vpm == mask)
goto out_unreg;
- if ((sch->schib.scsw.actl & (SCSW_ACTL_CLEAR_PEND |
- SCSW_ACTL_HALT_PEND |
- SCSW_ACTL_START_PEND |
- SCSW_ACTL_RESUME_PEND)) &&
- (sch->schib.pmcw.lpum == mask)) {
- int cc = cio_cancel(sch);
-
- if (cc == -ENODEV)
- goto out_unreg;
-
- if (cc == -EINVAL) {
- cc = cio_clear(sch);
- if (cc == -ENODEV)
- goto out_unreg;
- /* Call handler. */
- if (sch->driver && sch->driver->termination)
- sch->driver->termination(&sch->dev);
- goto out_unlock;
- }
- } else if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) &&
- (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) &&
- (sch->schib.pmcw.lpum == mask)) {
+ if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) &&
+ (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) &&
+ (sch->schib.pmcw.lpum == mask) &&
+ (sch->vpm == 0)) {
int cc;
cc = cio_clear(sch);
@@ -653,13 +635,13 @@ __chp_add(struct subchannel_id schid, void *data)
if (sch->schib.pmcw.chpid[i] == chp->id) {
if (stsch(sch->schid, &sch->schib) != 0) {
/* Endgame. */
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
return -ENXIO;
}
break;
}
if (i==8) {
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
return 0;
}
sch->lpm = ((sch->schib.pmcw.pim &
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index cbb86fa5f29..5b20d8c9c02 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -67,7 +67,7 @@ cio_debug_init (void)
goto out_unregister;
debug_register_view (cio_debug_msg_id, &debug_sprintf_view);
debug_set_level (cio_debug_msg_id, 2);
- cio_debug_trace_id = debug_register ("cio_trace", 16, 4, 8);
+ cio_debug_trace_id = debug_register ("cio_trace", 16, 4, 16);
if (!cio_debug_trace_id)
goto out_unregister;
debug_register_view (cio_debug_trace_id, &debug_hex_ascii_view);
diff --git a/drivers/s390/cio/cio_debug.h b/drivers/s390/cio/cio_debug.h
index 6af8b27d366..f88844adae1 100644
--- a/drivers/s390/cio/cio_debug.h
+++ b/drivers/s390/cio/cio_debug.h
@@ -3,6 +3,11 @@
#include <asm/debug.h>
+/* for use of debug feature */
+extern debug_info_t *cio_debug_msg_id;
+extern debug_info_t *cio_debug_trace_id;
+extern debug_info_t *cio_debug_crw_id;
+
#define CIO_TRACE_EVENT(imp, txt) do { \
debug_text_event(cio_debug_trace_id, imp, txt); \
} while (0)
@@ -15,18 +20,19 @@
debug_sprintf_event(cio_debug_crw_id, imp , ##args); \
} while (0)
-#define CIO_HEX_EVENT(imp, args...) do { \
- debug_event(cio_debug_trace_id, imp, ##args); \
- } while (0)
+static inline void
+CIO_HEX_EVENT(int level, void *data, int length)
+{
+ while (length > 0) {
+ debug_event(cio_debug_trace_id, level, data, length);
+ length -= cio_debug_trace_id->buf_size;
+ data += cio_debug_trace_id->buf_size;
+ }
+}
#define CIO_DEBUG(printk_level,event_level,msg...) ({ \
if (cio_show_msg) printk(printk_level msg); \
CIO_MSG_EVENT (event_level, msg); \
})
-/* for use of debug feature */
-extern debug_info_t *cio_debug_msg_id;
-extern debug_info_t *cio_debug_trace_id;
-extern debug_info_t *cio_debug_crw_id;
-
#endif
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 74a257b2338..e210f89a244 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -45,11 +45,11 @@ struct pgid {
union {
__u8 fc; /* SPID function code */
struct path_state ps; /* SNID path state */
- } inf;
+ } __attribute__ ((packed)) inf;
union {
__u32 cpu_addr : 16; /* CPU address */
struct extended_cssid ext_cssid;
- } pgid_high;
+ } __attribute__ ((packed)) pgid_high;
__u32 cpu_id : 24; /* CPU identification */
__u32 cpu_model : 16; /* CPU model */
__u32 tod_high; /* high word TOD clock */
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 180b3bf8b90..49ec562d7f6 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -749,7 +749,7 @@ ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event)
/* Unit check but no sense data. Need basic sense. */
if (ccw_device_do_sense(cdev, irb) != 0)
goto call_handler_unsol;
- memcpy(irb, &cdev->private->irb, sizeof(struct irb));
+ memcpy(&cdev->private->irb, irb, sizeof(struct irb));
cdev->private->state = DEV_STATE_W4SENSE;
cdev->private->intparm = 0;
return;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 814f9258ce0..96f519281d9 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -38,6 +38,7 @@
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/timer.h>
+#include <linux/mempool.h>
#include <asm/ccwdev.h>
#include <asm/io.h>
@@ -80,6 +81,8 @@ static int indicator_used[INDICATORS_PER_CACHELINE];
static __u32 * volatile indicators;
static __u32 volatile spare_indicator;
static atomic_t spare_indicator_usecount;
+#define QDIO_MEMPOOL_SCSSC_ELEMENTS 2
+static mempool_t *qdio_mempool_scssc;
static debug_info_t *qdio_dbf_setup;
static debug_info_t *qdio_dbf_sbal;
@@ -1637,7 +1640,7 @@ next:
}
kfree(irq_ptr->qdr);
- kfree(irq_ptr);
+ free_page((unsigned long) irq_ptr);
}
static void
@@ -2304,7 +2307,7 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
QDIO_DBF_TEXT0(0,setup,"getssqd");
qdioac = 0;
- ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ ssqd_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
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);
@@ -2364,7 +2367,7 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
out:
qdio_check_subchannel_qebsm(irq_ptr, qdioac,
ssqd_area->sch_token);
- free_page ((unsigned long) ssqd_area);
+ mempool_free(ssqd_area, qdio_mempool_scssc);
irq_ptr->qdioac = qdioac;
}
@@ -2458,7 +2461,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind);
}
- scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ scssc_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
if (!scssc_area) {
QDIO_PRINT_WARN("No memory for setting indicators on " \
"subchannel 0.%x.%x.\n",
@@ -2514,7 +2517,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
QDIO_DBF_HEX2(0,setup,&real_addr_dev_st_chg_ind,sizeof(unsigned long));
result = 0;
out:
- free_page ((unsigned long) scssc_area);
+ mempool_free(scssc_area, qdio_mempool_scssc);
return result;
}
@@ -2543,7 +2546,7 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
if (!irq_ptr->is_thinint_irq)
return -ENODEV;
- scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ scsscf_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
if (!scsscf_area) {
QDIO_PRINT_WARN("No memory for setting delay target on " \
"subchannel 0.%x.%x.\n",
@@ -2581,7 +2584,7 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
QDIO_DBF_HEX2(0,trace,&delay_target,sizeof(unsigned long));
result = 0; /* not critical */
out:
- free_page ((unsigned long) scsscf_area);
+ mempool_free(scsscf_area, qdio_mempool_scssc);
return result;
}
@@ -2980,7 +2983,7 @@ qdio_allocate(struct qdio_initialize *init_data)
qdio_allocate_do_dbf(init_data);
/* create irq */
- irq_ptr = kzalloc(sizeof(struct qdio_irq), GFP_KERNEL | GFP_DMA);
+ irq_ptr = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
QDIO_DBF_TEXT0(0,setup,"irq_ptr:");
QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*));
@@ -2995,7 +2998,7 @@ qdio_allocate(struct qdio_initialize *init_data)
/* QDR must be in DMA area since CCW data address is only 32 bit */
irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA);
if (!(irq_ptr->qdr)) {
- kfree(irq_ptr);
+ free_page((unsigned long) irq_ptr);
QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n");
return -ENOMEM;
}
@@ -3780,6 +3783,16 @@ oom:
return -ENOMEM;
}
+static void *qdio_mempool_alloc(gfp_t gfp_mask, void *size)
+{
+ return (void *) get_zeroed_page(gfp_mask|GFP_DMA);
+}
+
+static void qdio_mempool_free(void *element, void *size)
+{
+ free_page((unsigned long) element);
+}
+
static int __init
init_QDIO(void)
{
@@ -3809,6 +3822,10 @@ init_QDIO(void)
qdio_add_procfs_entry();
+ qdio_mempool_scssc = mempool_create(QDIO_MEMPOOL_SCSSC_ELEMENTS,
+ qdio_mempool_alloc,
+ qdio_mempool_free, NULL);
+
if (tiqdio_check_chsc_availability())
QDIO_PRINT_ERR("Not all CHSCs supported. Continuing.\n");
@@ -3824,6 +3841,7 @@ cleanup_QDIO(void)
qdio_remove_procfs_entry();
qdio_release_qdio_memory();
qdio_unregister_dbf_views();
+ mempool_destroy(qdio_mempool_scssc);
printk("qdio: %s: module removed\n",version);
}
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index af9f212314b..fe986af884f 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1486,13 +1486,13 @@ ch_action_iofatal(fsm_instance * fi, int event, void *arg)
}
}
-static void
+static void
ch_action_reinit(fsm_instance *fi, int event, void *arg)
{
struct channel *ch = (struct channel *)arg;
struct net_device *dev = ch->netdev;
struct ctc_priv *privptr = dev->priv;
-
+
DBF_TEXT(trace, 4, __FUNCTION__);
ch_action_iofatal(fi, event, arg);
fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
@@ -1624,7 +1624,7 @@ less_than(char *id1, char *id2)
}
dev1 = simple_strtoul(id1, &id1, 16);
dev2 = simple_strtoul(id2, &id2, 16);
-
+
return (dev1 < dev2);
}
@@ -1895,7 +1895,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
irb->scsw.dstat);
return;
}
-
+
priv = ((struct ccwgroup_device *)cdev->dev.driver_data)
->dev.driver_data;
@@ -1909,7 +1909,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
"device %s\n", cdev->dev.bus_id);
return;
}
-
+
dev = (struct net_device *) (ch->netdev);
if (dev == NULL) {
ctc_pr_crit("ctc: ctc_irq_handler dev=NULL bus_id=%s, ch=0x%p\n",
@@ -2008,12 +2008,12 @@ dev_action_stop(fsm_instance * fi, int event, void *arg)
fsm_event(ch->fsm, CH_EVENT_STOP, ch);
}
}
-static void
+static void
dev_action_restart(fsm_instance *fi, int event, void *arg)
{
struct net_device *dev = (struct net_device *)arg;
struct ctc_priv *privptr = dev->priv;
-
+
DBF_TEXT(trace, 3, __FUNCTION__);
ctc_pr_debug("%s: Restarting\n", dev->name);
dev_action_stop(fi, event, arg);
@@ -2193,7 +2193,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
DBF_TEXT(trace, 5, __FUNCTION__);
/* we need to acquire the lock for testing the state
- * otherwise we can have an IRQ changing the state to
+ * otherwise we can have an IRQ changing the state to
* TXIDLE after the test but before acquiring the lock.
*/
spin_lock_irqsave(&ch->collect_lock, saveflags);
@@ -2393,7 +2393,7 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev)
/**
* If channels are not running, try to restart them
- * and throw away packet.
+ * and throw away packet.
*/
if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
fsm_event(privptr->fsm, DEV_EVENT_START, dev);
@@ -2738,7 +2738,7 @@ ctc_remove_files(struct device *dev)
/**
* Add ctc specific attributes.
* Add ctc private data.
- *
+ *
* @param cgdev pointer to ccwgroup_device just added
*
* @returns 0 on success, !0 on failure.
@@ -2869,7 +2869,7 @@ ctc_new_device(struct ccwgroup_device *cgdev)
DBF_TEXT(setup, 3, buffer);
type = get_channel_type(&cgdev->cdev[0]->id);
-
+
snprintf(read_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
snprintf(write_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id);
@@ -2907,7 +2907,7 @@ ctc_new_device(struct ccwgroup_device *cgdev)
channel_get(type, direction == READ ? read_id : write_id,
direction);
if (privptr->channel[direction] == NULL) {
- if (direction == WRITE)
+ if (direction == WRITE)
channel_free(privptr->channel[READ]);
ctc_free_netdevice(dev, 1);
@@ -2955,7 +2955,7 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev)
{
struct ctc_priv *priv;
struct net_device *ndev;
-
+
DBF_TEXT(setup, 3, __FUNCTION__);
pr_debug("%s() called\n", __FUNCTION__);
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
index 5cdcdbf9296..af54d1de07b 100644
--- a/drivers/s390/net/ctctty.c
+++ b/drivers/s390/net/ctctty.c
@@ -130,7 +130,7 @@ ctc_tty_readmodem(ctc_tty_info *info)
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
struct sk_buff *skb;
-
+
if ((skb = skb_dequeue(&info->rx_queue))) {
int len = skb->len;
tty_insert_flip_string(tty, skb->data, len);
@@ -328,7 +328,7 @@ ctc_tty_inject(ctc_tty_info *info, char c)
{
int skb_res;
struct sk_buff *skb;
-
+
DBF_TEXT(trace, 4, __FUNCTION__);
if (ctc_tty_shuttingdown)
return;
@@ -497,7 +497,7 @@ ctc_tty_write(struct tty_struct *tty, const u_char * buf, int count)
c = (count < CTC_TTY_XMIT_SIZE) ? count : CTC_TTY_XMIT_SIZE;
if (c <= 0)
break;
-
+
skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +
+ sizeof(__u32);
skb = dev_alloc_skb(skb_res + c);
@@ -828,7 +828,7 @@ ctc_tty_block_til_ready(struct tty_struct *tty, struct file *filp, ctc_tty_info
if (tty_hung_up_p(filp) ||
(info->flags & CTC_ASYNC_CLOSING)) {
if (info->flags & CTC_ASYNC_CLOSING)
- wait_event(info->close_wait,
+ wait_event(info->close_wait,
!(info->flags & CTC_ASYNC_CLOSING));
#ifdef MODEM_DO_RESTART
if (info->flags & CTC_ASYNC_HUP_NOTIFY)
@@ -1247,7 +1247,7 @@ ctc_tty_unregister_netdev(struct net_device *dev) {
void
ctc_tty_cleanup(void) {
unsigned long saveflags;
-
+
DBF_TEXT(trace, 2, __FUNCTION__);
spin_lock_irqsave(&ctc_tty_lock, saveflags);
ctc_tty_shuttingdown = 1;
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
index b12533104c1..e965f03a729 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -20,7 +20,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
-
+
#include <linux/init.h>
#include <linux/module.h>
#include <linux/err.h>
@@ -77,7 +77,7 @@ group_write(struct device_driver *drv, const char *buf, size_t count)
int len;
if (!(end = strchr(start, delim[i])))
- return count;
+ return -EINVAL;
len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start + 1);
strlcpy (bus_ids[i], start, len);
argv[i] = bus_ids[i];
@@ -94,7 +94,7 @@ static DRIVER_ATTR(group, 0200, NULL, group_write);
/* Register-unregister for ctc&lcs */
int
-register_cu3088_discipline(struct ccwgroup_driver *dcp)
+register_cu3088_discipline(struct ccwgroup_driver *dcp)
{
int rc;
@@ -109,7 +109,7 @@ register_cu3088_discipline(struct ccwgroup_driver *dcp)
rc = driver_create_file(&dcp->driver, &driver_attr_group);
if (rc)
ccwgroup_driver_unregister(dcp);
-
+
return rc;
}
@@ -137,7 +137,7 @@ static int __init
cu3088_init (void)
{
int rc;
-
+
cu3088_root_dev = s390_root_dev_register("cu3088");
if (IS_ERR(cu3088_root_dev))
return PTR_ERR(cu3088_root_dev);
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index 6190be9dca9..e0c7deb9883 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -1,4 +1,4 @@
-/*
+/*
* IUCV network driver
*
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
@@ -28,7 +28,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
-
+
/* #define DEBUG */
#include <linux/module.h>
@@ -81,7 +81,7 @@ iucv_bus_match (struct device *dev, struct device_driver *drv)
struct bus_type iucv_bus = {
.name = "iucv",
.match = iucv_bus_match,
-};
+};
struct device *iucv_root;
@@ -297,7 +297,7 @@ MODULE_LICENSE("GPL");
/*
* Debugging stuff
*******************************************************************************/
-
+
#ifdef DEBUG
static int debuglevel = 0;
@@ -344,7 +344,7 @@ do { \
/*
* Internal functions
*******************************************************************************/
-
+
/**
* print start banner
*/
@@ -810,7 +810,7 @@ iucv_register_program (__u8 pgmname[16],
sizeof (new_handler->id.userid));
EBC_TOUPPER (new_handler->id.userid,
sizeof (new_handler->id.userid));
-
+
if (pgmmask) {
memcpy (new_handler->id.mask, pgmmask,
sizeof (new_handler->id.mask));
@@ -1229,7 +1229,7 @@ iucv_purge (__u16 pathid, __u32 msgid, __u32 srccls, __u32 *audit)
/* parm->ipaudit has only 3 bytes */
*audit >>= 8;
}
-
+
release_param(parm);
iucv_debug(1, "b2f0_result = %ld", b2f0_result);
@@ -2330,14 +2330,14 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
temp_buff1[j] &= (h->id.mask)[j];
temp_buff2[j] &= (h->id.mask)[j];
}
-
+
iucv_dumpit("temp_buff1:",
temp_buff1, sizeof(temp_buff1));
iucv_dumpit("temp_buff2",
temp_buff2, sizeof(temp_buff2));
-
+
if (!memcmp (temp_buff1, temp_buff2, 24)) {
-
+
iucv_debug(2,
"found a matching handler");
break;
@@ -2368,7 +2368,7 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
} else
iucv_sever(int_buf->ippathid, no_listener);
break;
-
+
case 0x02: /*connection complete */
if (messagesDisabled) {
iucv_setmask(~0);
@@ -2387,7 +2387,7 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
} else
iucv_sever(int_buf->ippathid, no_listener);
break;
-
+
case 0x03: /* connection severed */
if (messagesDisabled) {
iucv_setmask(~0);
@@ -2398,13 +2398,13 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
interrupt->ConnectionSevered(
(iucv_ConnectionSevered *)int_buf,
h->pgm_data);
-
+
else
iucv_sever (int_buf->ippathid, no_listener);
} else
iucv_sever(int_buf->ippathid, no_listener);
break;
-
+
case 0x04: /* connection quiesced */
if (messagesDisabled) {
iucv_setmask(~0);
@@ -2420,7 +2420,7 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
"ConnectionQuiesced not called");
}
break;
-
+
case 0x05: /* connection resumed */
if (messagesDisabled) {
iucv_setmask(~0);
@@ -2436,7 +2436,7 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
"ConnectionResumed not called");
}
break;
-
+
case 0x06: /* priority message complete */
case 0x07: /* nonpriority message complete */
if (h) {
@@ -2449,7 +2449,7 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
"MessageComplete not called");
}
break;
-
+
case 0x08: /* priority message pending */
case 0x09: /* nonpriority message pending */
if (h) {
@@ -2467,7 +2467,7 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
__FUNCTION__);
break;
} /* end switch */
-
+
iucv_debug(2, "exiting pathid %d, type %02X",
int_buf->ippathid, int_buf->iptype);
diff --git a/drivers/s390/net/iucv.h b/drivers/s390/net/iucv.h
index 0c4644d3d2f..5b6b1b7241c 100644
--- a/drivers/s390/net/iucv.h
+++ b/drivers/s390/net/iucv.h
@@ -4,7 +4,7 @@
*
* S390 version
* Copyright (C) 2000 IBM Corporation
- * Author(s):Alan Altmark (Alan_Altmark@us.ibm.com)
+ * Author(s):Alan Altmark (Alan_Altmark@us.ibm.com)
* Xenia Tkatschow (xenia@us.ibm.com)
*
*
@@ -16,17 +16,17 @@
* CP Programming Services book, also available on the web
* thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
*
- * Definition of Return Codes
- * -All positive return codes including zero are reflected back
- * from CP except for iucv_register_program. The definition of each
- * return code can be found in CP Programming Services book.
- * Also available on the web thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
- * - Return Code of:
- * (-EINVAL) Invalid value
- * (-ENOMEM) storage allocation failed
+ * Definition of Return Codes
+ * -All positive return codes including zero are reflected back
+ * from CP except for iucv_register_program. The definition of each
+ * return code can be found in CP Programming Services book.
+ * Also available on the web thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
+ * - Return Code of:
+ * (-EINVAL) Invalid value
+ * (-ENOMEM) storage allocation failed
* pgmask defined in iucv_register_program will be set depending on input
- * paramters.
- *
+ * paramters.
+ *
*/
#include <linux/types.h>
@@ -124,13 +124,13 @@ iucv_hex_dump(unsigned char *buf, size_t len)
#define iucv_handle_t void *
/* flags1:
- * All flags are defined in the field IPFLAGS1 of each function
- * and can be found in CP Programming Services.
- * IPLOCAL - Indicates the connect can only be satisfied on the
- * local system
- * IPPRTY - Indicates a priority message
- * IPQUSCE - Indicates you do not want to receive messages on a
- * path until an iucv_resume is issued
+ * All flags are defined in the field IPFLAGS1 of each function
+ * and can be found in CP Programming Services.
+ * IPLOCAL - Indicates the connect can only be satisfied on the
+ * local system
+ * IPPRTY - Indicates a priority message
+ * IPQUSCE - Indicates you do not want to receive messages on a
+ * path until an iucv_resume is issued
* IPRMDATA - Indicates that the message is in the parameter list
*/
#define IPLOCAL 0x01
@@ -154,14 +154,14 @@ iucv_hex_dump(unsigned char *buf, size_t len)
#define AllInterrupts 0xf8
/*
* Mapping of external interrupt buffers should be used with the corresponding
- * interrupt types.
- * Names: iucv_ConnectionPending -> connection pending
+ * interrupt types.
+ * Names: iucv_ConnectionPending -> connection pending
* iucv_ConnectionComplete -> connection complete
- * iucv_ConnectionSevered -> connection severed
- * iucv_ConnectionQuiesced -> connection quiesced
- * iucv_ConnectionResumed -> connection resumed
- * iucv_MessagePending -> message pending
- * iucv_MessageComplete -> message complete
+ * iucv_ConnectionSevered -> connection severed
+ * iucv_ConnectionQuiesced -> connection quiesced
+ * iucv_ConnectionResumed -> connection resumed
+ * iucv_MessagePending -> message pending
+ * iucv_MessageComplete -> message complete
*/
typedef struct {
u16 ippathid;
@@ -260,16 +260,16 @@ typedef struct {
uchar res2[3];
} iucv_MessageComplete;
-/*
- * iucv_interrupt_ops_t: Is a vector of functions that handle
- * IUCV interrupts.
- * Parameter list:
- * eib - is a pointer to a 40-byte area described
- * with one of the structures above.
- * pgm_data - this data is strictly for the
- * interrupt handler that is passed by
- * the application. This may be an address
- * or token.
+/*
+ * iucv_interrupt_ops_t: Is a vector of functions that handle
+ * IUCV interrupts.
+ * Parameter list:
+ * eib - is a pointer to a 40-byte area described
+ * with one of the structures above.
+ * pgm_data - this data is strictly for the
+ * interrupt handler that is passed by
+ * the application. This may be an address
+ * or token.
*/
typedef struct {
void (*ConnectionPending) (iucv_ConnectionPending * eib,
@@ -287,8 +287,8 @@ typedef struct {
} iucv_interrupt_ops_t;
/*
- *iucv_array_t : Defines buffer array.
- * Inside the array may be 31- bit addresses and 31-bit lengths.
+ *iucv_array_t : Defines buffer array.
+ * Inside the array may be 31- bit addresses and 31-bit lengths.
*/
typedef struct {
u32 address;
@@ -299,19 +299,19 @@ extern struct bus_type iucv_bus;
extern struct device *iucv_root;
/* -prototypes- */
-/*
- * Name: iucv_register_program
- * Purpose: Registers an application with IUCV
- * Input: prmname - user identification
+/*
+ * Name: iucv_register_program
+ * Purpose: Registers an application with IUCV
+ * Input: prmname - user identification
* userid - machine identification
* pgmmask - indicates which bits in the prmname and userid combined will be
* used to determine who is given control
- * ops - address of vector of interrupt handlers
- * pgm_data- application data passed to interrupt handlers
- * Output: NA
- * Return: address of handler
+ * ops - address of vector of interrupt handlers
+ * pgm_data- application data passed to interrupt handlers
+ * Output: NA
+ * Return: address of handler
* (0) - Error occurred, registration not completed.
- * NOTE: Exact cause of failure will be recorded in syslog.
+ * NOTE: Exact cause of failure will be recorded in syslog.
*/
iucv_handle_t iucv_register_program (uchar pgmname[16],
uchar userid[8],
@@ -319,13 +319,13 @@ iucv_handle_t iucv_register_program (uchar pgmname[16],
iucv_interrupt_ops_t * ops,
void *pgm_data);
-/*
- * Name: iucv_unregister_program
- * Purpose: Unregister application with IUCV
- * Input: address of handler
- * Output: NA
- * Return: (0) - Normal return
- * (-EINVAL) - Internal error, wild pointer
+/*
+ * Name: iucv_unregister_program
+ * Purpose: Unregister application with IUCV
+ * Input: address of handler
+ * Output: NA
+ * Return: (0) - Normal return
+ * (-EINVAL) - Internal error, wild pointer
*/
int iucv_unregister_program (iucv_handle_t handle);
@@ -333,7 +333,7 @@ int iucv_unregister_program (iucv_handle_t handle);
* Name: iucv_accept
* Purpose: This function is issued after the user receives a Connection Pending external
* interrupt and now wishes to complete the IUCV communication path.
- * Input: pathid - u16 , Path identification number
+ * Input: pathid - u16 , Path identification number
* msglim_reqstd - u16, The number of outstanding messages requested.
* user_data - uchar[16], Data specified by the iucv_connect function.
* flags1 - int, Contains options for this path.
@@ -358,34 +358,34 @@ int iucv_accept (u16 pathid,
void *pgm_data, int *flags1_out, u16 * msglim);
/*
- * Name: iucv_connect
+ * Name: iucv_connect
* Purpose: This function establishes an IUCV path. Although the connect may complete
- * successfully, you are not able to use the path until you receive an IUCV
- * Connection Complete external interrupt.
- * Input: pathid - u16 *, Path identification number
- * msglim_reqstd - u16, Number of outstanding messages requested
- * user_data - uchar[16], 16-byte user data
+ * successfully, you are not able to use the path until you receive an IUCV
+ * Connection Complete external interrupt.
+ * Input: pathid - u16 *, Path identification number
+ * msglim_reqstd - u16, Number of outstanding messages requested
+ * user_data - uchar[16], 16-byte user data
* userid - uchar[8], User identification
- * system_name - uchar[8], 8-byte identifying the system name
+ * system_name - uchar[8], 8-byte identifying the system name
* flags1 - int, Contains options for this path.
* -IPPRTY - 0x20, Specifies if you want to send priority message.
* -IPRMDATA - 0x80, Specifies whether your program can handle a message
* in the parameter list.
- * -IPQUSCE - 0x40, Specifies whether you want to quiesce the path being
+ * -IPQUSCE - 0x40, Specifies whether you want to quiesce the path being
* established.
- * -IPLOCAL - 0X01, Allows an application to force the partner to be on
+ * -IPLOCAL - 0X01, Allows an application to force the partner to be on
* the local system. If local is specified then target class cannot be
- * specified.
+ * specified.
* flags1_out - int * Contains information about the path
* - IPPRTY - 0x20, Indicates you may send priority messages.
* msglim - * u16, Number of outstanding messages
- * handle - iucv_handle_t, Address of handler
- * pgm_data - void *, Application data passed to interrupt handlers
+ * handle - iucv_handle_t, Address of handler
+ * pgm_data - void *, Application data passed to interrupt handlers
* Output: return code from CP IUCV call
* rc - return code from iucv_declare_buffer
- * -EINVAL - Invalid handle passed by application
- * -EINVAL - Pathid address is NULL
- * add_pathid_result - Return code from internal function add_pathid
+ * -EINVAL - Invalid handle passed by application
+ * -EINVAL - Pathid address is NULL
+ * add_pathid_result - Return code from internal function add_pathid
*/
int
iucv_connect (u16 * pathid,
@@ -397,16 +397,16 @@ int
int *flags1_out,
u16 * msglim, iucv_handle_t handle, void *pgm_data);
-/*
- * Name: iucv_purge
- * Purpose: This function cancels a message that you have sent.
- * Input: pathid - Path identification number.
+/*
+ * Name: iucv_purge
+ * Purpose: This function cancels a message that you have sent.
+ * Input: pathid - Path identification number.
* msgid - Specifies the message ID of the message to be purged.
- * srccls - Specifies the source message class.
- * Output: audit - Contains information about asynchronous error
- * that may have affected the normal completion
- * of this message.
- * Return: Return code from CP IUCV call.
+ * srccls - Specifies the source message class.
+ * Output: audit - Contains information about asynchronous error
+ * that may have affected the normal completion
+ * of this message.
+ * Return: Return code from CP IUCV call.
*/
int iucv_purge (u16 pathid, u32 msgid, u32 srccls, __u32 *audit);
/*
@@ -426,38 +426,38 @@ ulong iucv_query_maxconn (void);
*/
ulong iucv_query_bufsize (void);
-/*
- * Name: iucv_quiesce
- * Purpose: This function temporarily suspends incoming messages on an
- * IUCV path. You can later reactivate the path by invoking
- * the iucv_resume function.
- * Input: pathid - Path identification number
- * user_data - 16-bytes of user data
- * Output: NA
- * Return: Return code from CP IUCV call.
+/*
+ * Name: iucv_quiesce
+ * Purpose: This function temporarily suspends incoming messages on an
+ * IUCV path. You can later reactivate the path by invoking
+ * the iucv_resume function.
+ * Input: pathid - Path identification number
+ * user_data - 16-bytes of user data
+ * Output: NA
+ * Return: Return code from CP IUCV call.
*/
int iucv_quiesce (u16 pathid, uchar user_data[16]);
-/*
- * Name: iucv_receive
- * Purpose: This function receives messages that are being sent to you
+/*
+ * Name: iucv_receive
+ * Purpose: This function receives messages that are being sent to you
* over established paths. Data will be returned in buffer for length of
* buflen.
- * Input:
- * pathid - Path identification number.
- * buffer - Address of buffer to receive.
- * buflen - Length of buffer to receive.
- * msgid - Specifies the message ID.
- * trgcls - Specifies target class.
- * Output:
+ * Input:
+ * pathid - Path identification number.
+ * buffer - Address of buffer to receive.
+ * buflen - Length of buffer to receive.
+ * msgid - Specifies the message ID.
+ * trgcls - Specifies target class.
+ * Output:
* flags1_out: int *, Contains information about this path.
* IPNORPY - 0x10 Specifies this is a one-way message and no reply is
- * expected.
- * IPPRTY - 0x20 Specifies if you want to send priority message.
+ * expected.
+ * IPPRTY - 0x20 Specifies if you want to send priority message.
* IPRMDATA - 0x80 specifies the data is contained in the parameter list
* residual_buffer - address of buffer updated by the number
* of bytes you have received.
- * residual_length -
+ * residual_length -
* Contains one of the following values, if the receive buffer is:
* The same length as the message, this field is zero.
* Longer than the message, this field contains the number of
@@ -466,8 +466,8 @@ int iucv_quiesce (u16 pathid, uchar user_data[16]);
* count (that is, the number of bytes remaining in the
* message that does not fit into the buffer. In this
* case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - buffer address is pointing to NULL
+ * Return: Return code from CP IUCV call.
+ * (-EINVAL) - buffer address is pointing to NULL
*/
int iucv_receive (u16 pathid,
u32 msgid,
@@ -477,16 +477,16 @@ int iucv_receive (u16 pathid,
int *flags1_out,
ulong * residual_buffer, ulong * residual_length);
- /*
- * Name: iucv_receive_array
- * Purpose: This function receives messages that are being sent to you
+ /*
+ * Name: iucv_receive_array
+ * Purpose: This function receives messages that are being sent to you
* over established paths. Data will be returned in first buffer for
* length of first buffer.
- * Input: pathid - Path identification number.
+ * Input: pathid - Path identification number.
* msgid - specifies the message ID.
* trgcls - Specifies target class.
- * buffer - Address of array of buffers.
- * buflen - Total length of buffers.
+ * buffer - Address of array of buffers.
+ * buflen - Total length of buffers.
* Output:
* flags1_out: int *, Contains information about this path.
* IPNORPY - 0x10 Specifies this is a one-way message and no reply is
@@ -504,8 +504,8 @@ int iucv_receive (u16 pathid,
* count (that is, the number of bytes remaining in the
* message that does not fit into the buffer. In this
* case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
+ * Return: Return code from CP IUCV call.
+ * (-EINVAL) - Buffer address is NULL.
*/
int iucv_receive_array (u16 pathid,
u32 msgid,
@@ -515,44 +515,44 @@ int iucv_receive_array (u16 pathid,
int *flags1_out,
ulong * residual_buffer, ulong * residual_length);
-/*
- * Name: iucv_reject
- * Purpose: The reject function refuses a specified message. Between the
- * time you are notified of a message and the time that you
- * complete the message, the message may be rejected.
- * Input: pathid - Path identification number.
- * msgid - Specifies the message ID.
- * trgcls - Specifies target class.
- * Output: NA
- * Return: Return code from CP IUCV call.
+/*
+ * Name: iucv_reject
+ * Purpose: The reject function refuses a specified message. Between the
+ * time you are notified of a message and the time that you
+ * complete the message, the message may be rejected.
+ * Input: pathid - Path identification number.
+ * msgid - Specifies the message ID.
+ * trgcls - Specifies target class.
+ * Output: NA
+ * Return: Return code from CP IUCV call.
*/
int iucv_reject (u16 pathid, u32 msgid, u32 trgcls);
-/*
- * Name: iucv_reply
- * Purpose: This function responds to the two-way messages that you
- * receive. You must identify completely the message to
- * which you wish to reply. ie, pathid, msgid, and trgcls.
- * Input: pathid - Path identification number.
- * msgid - Specifies the message ID.
- * trgcls - Specifies target class.
+/*
+ * Name: iucv_reply
+ * Purpose: This function responds to the two-way messages that you
+ * receive. You must identify completely the message to
+ * which you wish to reply. ie, pathid, msgid, and trgcls.
+ * Input: pathid - Path identification number.
+ * msgid - Specifies the message ID.
+ * trgcls - Specifies target class.
* flags1 - Option for path.
- * IPPRTY- 0x20, Specifies if you want to send priority message.
- * buffer - Address of reply buffer.
- * buflen - Length of reply buffer.
- * Output: residual_buffer - Address of buffer updated by the number
- * of bytes you have moved.
+ * IPPRTY- 0x20, Specifies if you want to send priority message.
+ * buffer - Address of reply buffer.
+ * buflen - Length of reply buffer.
+ * Output: residual_buffer - Address of buffer updated by the number
+ * of bytes you have moved.
* residual_length - Contains one of the following values:
* If the answer buffer is the same length as the reply, this field
* contains zero.
* If the answer buffer is longer than the reply, this field contains
- * the number of bytes remaining in the buffer.
+ * the number of bytes remaining in the buffer.
* If the answer buffer is shorter than the reply, this field contains
* a residual count (that is, the number of bytes remianing in the
* reply that does not fit into the buffer. In this
* case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
+ * Return: Return code from CP IUCV call.
+ * (-EINVAL) - Buffer address is NULL.
*/
int iucv_reply (u16 pathid,
u32 msgid,
@@ -561,20 +561,20 @@ int iucv_reply (u16 pathid,
void *buffer, ulong buflen, ulong * residual_buffer,
ulong * residual_length);
-/*
- * Name: iucv_reply_array
- * Purpose: This function responds to the two-way messages that you
- * receive. You must identify completely the message to
- * which you wish to reply. ie, pathid, msgid, and trgcls.
- * The array identifies a list of addresses and lengths of
- * discontiguous buffers that contains the reply data.
- * Input: pathid - Path identification number
- * msgid - Specifies the message ID.
- * trgcls - Specifies target class.
+/*
+ * Name: iucv_reply_array
+ * Purpose: This function responds to the two-way messages that you
+ * receive. You must identify completely the message to
+ * which you wish to reply. ie, pathid, msgid, and trgcls.
+ * The array identifies a list of addresses and lengths of
+ * discontiguous buffers that contains the reply data.
+ * Input: pathid - Path identification number
+ * msgid - Specifies the message ID.
+ * trgcls - Specifies target class.
* flags1 - Option for path.
* IPPRTY- 0x20, Specifies if you want to send priority message.
- * buffer - Address of array of reply buffers.
- * buflen - Total length of reply buffers.
+ * buffer - Address of array of reply buffers.
+ * buflen - Total length of reply buffers.
* Output: residual_buffer - Address of buffer which IUCV is currently working on.
* residual_length - Contains one of the following values:
* If the answer buffer is the same length as the reply, this field
@@ -585,8 +585,8 @@ int iucv_reply (u16 pathid,
* a residual count (that is, the number of bytes remianing in the
* reply that does not fit into the buffer. In this
* case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
+ * Return: Return code from CP IUCV call.
+ * (-EINVAL) - Buffer address is NULL.
*/
int iucv_reply_array (u16 pathid,
u32 msgid,
@@ -596,77 +596,77 @@ int iucv_reply_array (u16 pathid,
ulong buflen, ulong * residual_address,
ulong * residual_length);
-/*
- * Name: iucv_reply_prmmsg
- * Purpose: This function responds to the two-way messages that you
- * receive. You must identify completely the message to
- * which you wish to reply. ie, pathid, msgid, and trgcls.
- * Prmmsg signifies the data is moved into the
- * parameter list.
- * Input: pathid - Path identification number.
- * msgid - Specifies the message ID.
- * trgcls - Specifies target class.
+/*
+ * Name: iucv_reply_prmmsg
+ * Purpose: This function responds to the two-way messages that you
+ * receive. You must identify completely the message to
+ * which you wish to reply. ie, pathid, msgid, and trgcls.
+ * Prmmsg signifies the data is moved into the
+ * parameter list.
+ * Input: pathid - Path identification number.
+ * msgid - Specifies the message ID.
+ * trgcls - Specifies target class.
* flags1 - Option for path.
* IPPRTY- 0x20 Specifies if you want to send priority message.
- * prmmsg - 8-bytes of data to be placed into the parameter.
- * list.
- * Output: NA
- * Return: Return code from CP IUCV call.
+ * prmmsg - 8-bytes of data to be placed into the parameter.
+ * list.
+ * Output: NA
+ * Return: Return code from CP IUCV call.
*/
int iucv_reply_prmmsg (u16 pathid,
u32 msgid, u32 trgcls, int flags1, uchar prmmsg[8]);
-/*
- * Name: iucv_resume
- * Purpose: This function restores communications over a quiesced path
- * Input: pathid - Path identification number.
- * user_data - 16-bytes of user data.
- * Output: NA
- * Return: Return code from CP IUCV call.
+/*
+ * Name: iucv_resume
+ * Purpose: This function restores communications over a quiesced path
+ * Input: pathid - Path identification number.
+ * user_data - 16-bytes of user data.
+ * Output: NA
+ * Return: Return code from CP IUCV call.
*/
int iucv_resume (u16 pathid, uchar user_data[16]);
-/*
- * Name: iucv_send
- * Purpose: This function transmits data to another application.
- * Data to be transmitted is in a buffer and this is a
- * one-way message and the receiver will not reply to the
- * message.
- * Input: pathid - Path identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag to be associated with the message.
+/*
+ * Name: iucv_send
+ * Purpose: This function transmits data to another application.
+ * Data to be transmitted is in a buffer and this is a
+ * one-way message and the receiver will not reply to the
+ * message.
+ * Input: pathid - Path identification number.
+ * trgcls - Specifies target class.
+ * srccls - Specifies the source message class.
+ * msgtag - Specifies a tag to be associated with the message.
* flags1 - Option for path.
* IPPRTY- 0x20 Specifies if you want to send priority message.
- * buffer - Address of send buffer.
- * buflen - Length of send buffer.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
+ * buffer - Address of send buffer.
+ * buflen - Length of send buffer.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
+ * (-EINVAL) - Buffer address is NULL.
*/
int iucv_send (u16 pathid,
u32 * msgid,
u32 trgcls,
u32 srccls, u32 msgtag, int flags1, void *buffer, ulong buflen);
-/*
- * Name: iucv_send_array
- * Purpose: This function transmits data to another application.
- * The contents of buffer is the address of the array of
- * addresses and lengths of discontiguous buffers that hold
- * the message text. This is a one-way message and the
- * receiver will not reply to the message.
- * Input: pathid - Path identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
+/*
+ * Name: iucv_send_array
+ * Purpose: This function transmits data to another application.
+ * The contents of buffer is the address of the array of
+ * addresses and lengths of discontiguous buffers that hold
+ * the message text. This is a one-way message and the
+ * receiver will not reply to the message.
+ * Input: pathid - Path identification number.
+ * trgcls - Specifies target class.
+ * srccls - Specifies the source message class.
* msgtag - Specifies a tag to be associated witht the message.
* flags1 - Option for path.
- * IPPRTY- specifies if you want to send priority message.
- * buffer - Address of array of send buffers.
- * buflen - Total length of send buffers.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
+ * IPPRTY- specifies if you want to send priority message.
+ * buffer - Address of array of send buffers.
+ * buflen - Total length of send buffers.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
+ * (-EINVAL) - Buffer address is NULL.
*/
int iucv_send_array (u16 pathid,
u32 * msgid,
@@ -675,48 +675,48 @@ int iucv_send_array (u16 pathid,
u32 msgtag,
int flags1, iucv_array_t * buffer, ulong buflen);
-/*
- * Name: iucv_send_prmmsg
- * Purpose: This function transmits data to another application.
- * Prmmsg specifies that the 8-bytes of data are to be moved
- * into the parameter list. This is a one-way message and the
- * receiver will not reply to the message.
- * Input: pathid - Path identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag to be associated with the message.
+/*
+ * Name: iucv_send_prmmsg
+ * Purpose: This function transmits data to another application.
+ * Prmmsg specifies that the 8-bytes of data are to be moved
+ * into the parameter list. This is a one-way message and the
+ * receiver will not reply to the message.
+ * Input: pathid - Path identification number.
+ * trgcls - Specifies target class.
+ * srccls - Specifies the source message class.
+ * msgtag - Specifies a tag to be associated with the message.
* flags1 - Option for path.
* IPPRTY- 0x20 specifies if you want to send priority message.
- * prmmsg - 8-bytes of data to be placed into parameter list.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
+ * prmmsg - 8-bytes of data to be placed into parameter list.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
*/
int iucv_send_prmmsg (u16 pathid,
u32 * msgid,
u32 trgcls,
u32 srccls, u32 msgtag, int flags1, uchar prmmsg[8]);
-/*
- * Name: iucv_send2way
- * Purpose: This function transmits data to another application.
- * Data to be transmitted is in a buffer. The receiver
- * of the send is expected to reply to the message and
- * a buffer is provided into which IUCV moves the reply
- * to this message.
- * Input: pathid - Path identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag associated with the message.
+/*
+ * Name: iucv_send2way
+ * Purpose: This function transmits data to another application.
+ * Data to be transmitted is in a buffer. The receiver
+ * of the send is expected to reply to the message and
+ * a buffer is provided into which IUCV moves the reply
+ * to this message.
+ * Input: pathid - Path identification number.
+ * trgcls - Specifies target class.
+ * srccls - Specifies the source message class.
+ * msgtag - Specifies a tag associated with the message.
* flags1 - Option for path.
* IPPRTY- 0x20 Specifies if you want to send priority message.
- * buffer - Address of send buffer.
- * buflen - Length of send buffer.
- * ansbuf - Address of buffer into which IUCV moves the reply of
- * this message.
- * anslen - Address of length of buffer.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer or ansbuf address is NULL.
+ * buffer - Address of send buffer.
+ * buflen - Length of send buffer.
+ * ansbuf - Address of buffer into which IUCV moves the reply of
+ * this message.
+ * anslen - Address of length of buffer.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
+ * (-EINVAL) - Buffer or ansbuf address is NULL.
*/
int iucv_send2way (u16 pathid,
u32 * msgid,
@@ -726,28 +726,28 @@ int iucv_send2way (u16 pathid,
int flags1,
void *buffer, ulong buflen, void *ansbuf, ulong anslen);
-/*
- * Name: iucv_send2way_array
- * Purpose: This function transmits data to another application.
- * The contents of buffer is the address of the array of
- * addresses and lengths of discontiguous buffers that hold
- * the message text. The receiver of the send is expected to
- * reply to the message and a buffer is provided into which
- * IUCV moves the reply to this message.
- * Input: pathid - Path identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag to be associated with the message.
+/*
+ * Name: iucv_send2way_array
+ * Purpose: This function transmits data to another application.
+ * The contents of buffer is the address of the array of
+ * addresses and lengths of discontiguous buffers that hold
+ * the message text. The receiver of the send is expected to
+ * reply to the message and a buffer is provided into which
+ * IUCV moves the reply to this message.
+ * Input: pathid - Path identification number.
+ * trgcls - Specifies target class.
+ * srccls - Specifies the source message class.
+ * msgtag - Specifies a tag to be associated with the message.
* flags1 - Option for path.
* IPPRTY- 0x20 Specifies if you want to send priority message.
- * buffer - Sddress of array of send buffers.
- * buflen - Total length of send buffers.
- * ansbuf - Address of array of buffer into which IUCV moves the reply
- * of this message.
- * anslen - Address of length reply buffers.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
+ * buffer - Sddress of array of send buffers.
+ * buflen - Total length of send buffers.
+ * ansbuf - Address of array of buffer into which IUCV moves the reply
+ * of this message.
+ * anslen - Address of length reply buffers.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
+ * (-EINVAL) - Buffer address is NULL.
*/
int iucv_send2way_array (u16 pathid,
u32 * msgid,
@@ -758,27 +758,27 @@ int iucv_send2way_array (u16 pathid,
iucv_array_t * buffer,
ulong buflen, iucv_array_t * ansbuf, ulong anslen);
-/*
- * Name: iucv_send2way_prmmsg
- * Purpose: This function transmits data to another application.
- * Prmmsg specifies that the 8-bytes of data are to be moved
- * into the parameter list. This is a two-way message and the
- * receiver of the message is expected to reply. A buffer
- * is provided into which IUCV moves the reply to this
- * message.
- * Input: pathid - Rath identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag to be associated with the message.
+/*
+ * Name: iucv_send2way_prmmsg
+ * Purpose: This function transmits data to another application.
+ * Prmmsg specifies that the 8-bytes of data are to be moved
+ * into the parameter list. This is a two-way message and the
+ * receiver of the message is expected to reply. A buffer
+ * is provided into which IUCV moves the reply to this
+ * message.
+ * Input: pathid - Rath identification number.
+ * trgcls - Specifies target class.
+ * srccls - Specifies the source message class.
+ * msgtag - Specifies a tag to be associated with the message.
* flags1 - Option for path.
* IPPRTY- 0x20 Specifies if you want to send priority message.
- * prmmsg - 8-bytes of data to be placed in parameter list.
- * ansbuf - Address of buffer into which IUCV moves the reply of
+ * prmmsg - 8-bytes of data to be placed in parameter list.
+ * ansbuf - Address of buffer into which IUCV moves the reply of
* this message.
- * anslen - Address of length of buffer.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
+ * anslen - Address of length of buffer.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
+ * (-EINVAL) - Buffer address is NULL.
*/
int iucv_send2way_prmmsg (u16 pathid,
u32 * msgid,
@@ -788,29 +788,29 @@ int iucv_send2way_prmmsg (u16 pathid,
ulong flags1,
uchar prmmsg[8], void *ansbuf, ulong anslen);
-/*
- * Name: iucv_send2way_prmmsg_array
- * Purpose: This function transmits data to another application.
- * Prmmsg specifies that the 8-bytes of data are to be moved
- * into the parameter list. This is a two-way message and the
- * receiver of the message is expected to reply. A buffer
- * is provided into which IUCV moves the reply to this
- * message. The contents of ansbuf is the address of the
- * array of addresses and lengths of discontiguous buffers
- * that contain the reply.
- * Input: pathid - Path identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag to be associated with the message.
+/*
+ * Name: iucv_send2way_prmmsg_array
+ * Purpose: This function transmits data to another application.
+ * Prmmsg specifies that the 8-bytes of data are to be moved
+ * into the parameter list. This is a two-way message and the
+ * receiver of the message is expected to reply. A buffer
+ * is provided into which IUCV moves the reply to this
+ * message. The contents of ansbuf is the address of the
+ * array of addresses and lengths of discontiguous buffers
+ * that contain the reply.
+ * Input: pathid - Path identification number.
+ * trgcls - Specifies target class.
+ * srccls - Specifies the source message class.
+ * msgtag - Specifies a tag to be associated with the message.
* flags1 - Option for path.
* IPPRTY- 0x20 specifies if you want to send priority message.
- * prmmsg - 8-bytes of data to be placed into the parameter list.
+ * prmmsg - 8-bytes of data to be placed into the parameter list.
* ansbuf - Address of array of buffer into which IUCV moves the reply
- * of this message.
- * anslen - Address of length of reply buffers.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Ansbuf address is NULL.
+ * of this message.
+ * anslen - Address of length of reply buffers.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
+ * (-EINVAL) - Ansbuf address is NULL.
*/
int iucv_send2way_prmmsg_array (u16 pathid,
u32 * msgid,
@@ -821,29 +821,29 @@ int iucv_send2way_prmmsg_array (u16 pathid,
uchar prmmsg[8],
iucv_array_t * ansbuf, ulong anslen);
-/*
- * Name: iucv_setmask
- * Purpose: This function enables or disables the following IUCV
- * external interruptions: Nonpriority and priority message
- * interrupts, nonpriority and priority reply interrupts.
+/*
+ * Name: iucv_setmask
+ * Purpose: This function enables or disables the following IUCV
+ * external interruptions: Nonpriority and priority message
+ * interrupts, nonpriority and priority reply interrupts.
* Input: SetMaskFlag - options for interrupts
- * 0x80 - Nonpriority_MessagePendingInterruptsFlag
- * 0x40 - Priority_MessagePendingInterruptsFlag
- * 0x20 - Nonpriority_MessageCompletionInterruptsFlag
- * 0x10 - Priority_MessageCompletionInterruptsFlag
+ * 0x80 - Nonpriority_MessagePendingInterruptsFlag
+ * 0x40 - Priority_MessagePendingInterruptsFlag
+ * 0x20 - Nonpriority_MessageCompletionInterruptsFlag
+ * 0x10 - Priority_MessageCompletionInterruptsFlag
* 0x08 - IUCVControlInterruptsFlag
- * Output: NA
- * Return: Return code from CP IUCV call.
+ * Output: NA
+ * Return: Return code from CP IUCV call.
*/
int iucv_setmask (int SetMaskFlag);
-/*
- * Name: iucv_sever
- * Purpose: This function terminates an IUCV path.
- * Input: pathid - Path identification number.
- * user_data - 16-bytes of user data.
- * Output: NA
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Interal error, wild pointer.
+/*
+ * Name: iucv_sever
+ * Purpose: This function terminates an IUCV path.
+ * Input: pathid - Path identification number.
+ * user_data - 16-bytes of user data.
+ * Output: NA
+ * Return: Return code from CP IUCV call.
+ * (-EINVAL) - Interal error, wild pointer.
*/
int iucv_sever (u16 pathid, uchar user_data[16]);
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index edcf05d5d56..f94419b334f 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -68,6 +68,7 @@ static void lcs_tasklet(unsigned long);
static void lcs_start_kernel_thread(struct lcs_card *card);
static void lcs_get_frames_cb(struct lcs_channel *, struct lcs_buffer *);
static int lcs_send_delipm(struct lcs_card *, struct lcs_ipm_list *);
+static int lcs_recovery(void *ptr);
/**
* Debug Facility Stuff
@@ -429,12 +430,6 @@ lcs_setup_card(struct lcs_card *card)
card->tx_buffer = NULL;
card->tx_emitted = 0;
- /* Initialize kernel thread task used for LGW commands. */
- INIT_WORK(&card->kernel_thread_starter,
- (void *)lcs_start_kernel_thread,card);
- card->thread_start_mask = 0;
- card->thread_allowed_mask = 0;
- card->thread_running_mask = 0;
init_waitqueue_head(&card->wait_q);
spin_lock_init(&card->lock);
spin_lock_init(&card->ipm_lock);
@@ -1150,8 +1145,6 @@ list_modified:
list_add_tail(&ipm->list, &card->ipm_list);
}
spin_unlock_irqrestore(&card->ipm_lock, flags);
- if (card->state == DEV_STATE_UP)
- netif_wake_queue(card->dev);
}
/**
@@ -1234,17 +1227,17 @@ lcs_set_mc_addresses(struct lcs_card *card, struct in_device *in4_dev)
if (ipm != NULL)
continue; /* Address already in list. */
ipm = (struct lcs_ipm_list *)
- kmalloc(sizeof(struct lcs_ipm_list), GFP_ATOMIC);
+ kzalloc(sizeof(struct lcs_ipm_list), GFP_ATOMIC);
if (ipm == NULL) {
PRINT_INFO("Not enough memory to add "
"new multicast entry!\n");
break;
}
- memset(ipm, 0, sizeof(struct lcs_ipm_list));
memcpy(&ipm->ipm.mac_addr, buf, LCS_MAC_LENGTH);
ipm->ipm.ip_addr = im4->multiaddr;
ipm->ipm_state = LCS_IPM_STATE_SET_REQUIRED;
spin_lock_irqsave(&card->ipm_lock, flags);
+ LCS_DBF_HEX(2,trace,&ipm->ipm.ip_addr,4);
list_add(&ipm->list, &card->ipm_list);
spin_unlock_irqrestore(&card->ipm_lock, flags);
}
@@ -1272,7 +1265,15 @@ lcs_register_mc_addresses(void *data)
read_unlock(&in4_dev->mc_list_lock);
in_dev_put(in4_dev);
+ netif_carrier_off(card->dev);
+ netif_tx_disable(card->dev);
+ wait_event(card->write.wait_q,
+ (card->write.state != CH_STATE_RUNNING));
lcs_fix_multicast_list(card);
+ if (card->state == DEV_STATE_UP) {
+ netif_carrier_on(card->dev);
+ netif_wake_queue(card->dev);
+ }
out:
lcs_clear_thread_running_bit(card, LCS_SET_MC_THREAD);
return 0;
@@ -1289,7 +1290,7 @@ lcs_set_multicast_list(struct net_device *dev)
LCS_DBF_TEXT(4, trace, "setmulti");
card = (struct lcs_card *) dev->priv;
- if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD))
+ if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD))
schedule_work(&card->kernel_thread_starter);
}
@@ -1321,6 +1322,53 @@ lcs_check_irb_error(struct ccw_device *cdev, struct irb *irb)
return PTR_ERR(irb);
}
+static int
+lcs_get_problem(struct ccw_device *cdev, struct irb *irb)
+{
+ int dstat, cstat;
+ char *sense;
+
+ sense = (char *) irb->ecw;
+ cstat = irb->scsw.cstat;
+ dstat = irb->scsw.dstat;
+
+ if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
+ SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
+ SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) {
+ LCS_DBF_TEXT(2, trace, "CGENCHK");
+ return 1;
+ }
+ if (dstat & DEV_STAT_UNIT_CHECK) {
+ if (sense[LCS_SENSE_BYTE_1] &
+ LCS_SENSE_RESETTING_EVENT) {
+ LCS_DBF_TEXT(2, trace, "REVIND");
+ return 1;
+ }
+ if (sense[LCS_SENSE_BYTE_0] &
+ LCS_SENSE_CMD_REJECT) {
+ LCS_DBF_TEXT(2, trace, "CMDREJ");
+ return 0;
+ }
+ if ((!sense[LCS_SENSE_BYTE_0]) &&
+ (!sense[LCS_SENSE_BYTE_1]) &&
+ (!sense[LCS_SENSE_BYTE_2]) &&
+ (!sense[LCS_SENSE_BYTE_3])) {
+ LCS_DBF_TEXT(2, trace, "ZEROSEN");
+ return 0;
+ }
+ LCS_DBF_TEXT(2, trace, "DGENCHK");
+ return 1;
+ }
+ return 0;
+}
+
+void
+lcs_schedule_recovery(struct lcs_card *card)
+{
+ LCS_DBF_TEXT(2, trace, "startrec");
+ if (!lcs_set_thread_start_bit(card, LCS_RECOVERY_THREAD))
+ schedule_work(&card->kernel_thread_starter);
+}
/**
* IRQ Handler for LCS channels
@@ -1330,7 +1378,8 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
{
struct lcs_card *card;
struct lcs_channel *channel;
- int index;
+ int rc, index;
+ int cstat, dstat;
if (lcs_check_irb_error(cdev, irb))
return;
@@ -1341,17 +1390,30 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
else
channel = &card->write;
+ cstat = irb->scsw.cstat;
+ dstat = irb->scsw.dstat;
LCS_DBF_TEXT_(5, trace, "Rint%s",cdev->dev.bus_id);
LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.cstat, irb->scsw.dstat);
LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.fctl, irb->scsw.actl);
+ /* Check for channel and device errors presented */
+ rc = lcs_get_problem(cdev, irb);
+ if (rc || (dstat & DEV_STAT_UNIT_EXCEP)) {
+ PRINT_WARN("check on device %s, dstat=0x%X, cstat=0x%X \n",
+ cdev->dev.bus_id, dstat, cstat);
+ if (rc) {
+ lcs_schedule_recovery(card);
+ wake_up(&card->wait_q);
+ return;
+ }
+ }
/* How far in the ccw chain have we processed? */
if ((channel->state != CH_STATE_INIT) &&
(irb->scsw.fctl & SCSW_FCTL_START_FUNC)) {
- index = (struct ccw1 *) __va((addr_t) irb->scsw.cpa)
+ index = (struct ccw1 *) __va((addr_t) irb->scsw.cpa)
- channel->ccws;
if ((irb->scsw.actl & SCSW_ACTL_SUSPENDED) ||
- (irb->scsw.cstat | SCHN_STAT_PCI))
+ (irb->scsw.cstat & SCHN_STAT_PCI))
/* Bloody io subsystem tells us lies about cpa... */
index = (index - 1) & (LCS_NUM_BUFFS - 1);
while (channel->io_idx != index) {
@@ -1370,7 +1432,6 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
else if (irb->scsw.actl & SCSW_ACTL_SUSPENDED)
/* CCW execution stopped on a suspend bit. */
channel->state = CH_STATE_SUSPENDED;
-
if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) {
if (irb->scsw.cc != 0) {
ccw_device_halt(channel->ccwdev, (addr_t) channel);
@@ -1379,7 +1440,6 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
/* The channel has been stopped by halt_IO. */
channel->state = CH_STATE_HALTED;
}
-
if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) {
channel->state = CH_STATE_CLEARED;
}
@@ -1455,7 +1515,7 @@ lcs_txbuffer_cb(struct lcs_channel *channel, struct lcs_buffer *buffer)
lcs_release_buffer(channel, buffer);
card = (struct lcs_card *)
((char *) channel - offsetof(struct lcs_card, write));
- if (netif_queue_stopped(card->dev))
+ if (netif_queue_stopped(card->dev) && netif_carrier_ok(card->dev))
netif_wake_queue(card->dev);
spin_lock(&card->lock);
card->tx_emitted--;
@@ -1491,6 +1551,10 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
card->stats.tx_carrier_errors++;
return 0;
}
+ if (skb->protocol == htons(ETH_P_IPV6)) {
+ dev_kfree_skb(skb);
+ return 0;
+ }
netif_stop_queue(card->dev);
spin_lock(&card->lock);
if (card->tx_buffer != NULL &&
@@ -1636,30 +1700,6 @@ lcs_detect(struct lcs_card *card)
}
/**
- * reset card
- */
-static int
-lcs_resetcard(struct lcs_card *card)
-{
- int retries;
-
- LCS_DBF_TEXT(2, trace, "rescard");
- for (retries = 0; retries < 10; retries++) {
- if (lcs_detect(card) == 0) {
- netif_wake_queue(card->dev);
- card->state = DEV_STATE_UP;
- PRINT_INFO("LCS device %s successfully restarted!\n",
- card->dev->name);
- return 0;
- }
- msleep(3000);
- }
- PRINT_ERR("Error in Reseting LCS card!\n");
- return -EIO;
-}
-
-
-/**
* LCS Stop card
*/
static int
@@ -1683,126 +1723,18 @@ lcs_stopcard(struct lcs_card *card)
}
/**
- * LGW initiated commands
- */
-static int
-lcs_lgw_startlan_thread(void *data)
-{
- struct lcs_card *card;
-
- card = (struct lcs_card *) data;
- daemonize("lgwstpln");
-
- if (!lcs_do_run_thread(card, LCS_STARTLAN_THREAD))
- return 0;
- LCS_DBF_TEXT(4, trace, "lgwstpln");
- if (card->dev)
- netif_stop_queue(card->dev);
- if (lcs_startlan(card) == 0) {
- netif_wake_queue(card->dev);
- card->state = DEV_STATE_UP;
- PRINT_INFO("LCS Startlan for device %s succeeded!\n",
- card->dev->name);
-
- } else
- PRINT_ERR("LCS Startlan for device %s failed!\n",
- card->dev->name);
- lcs_clear_thread_running_bit(card, LCS_STARTLAN_THREAD);
- return 0;
-}
-
-/**
- * Send startup command initiated by Lan Gateway
- */
-static int
-lcs_lgw_startup_thread(void *data)
-{
- int rc;
-
- struct lcs_card *card;
-
- card = (struct lcs_card *) data;
- daemonize("lgwstaln");
-
- if (!lcs_do_run_thread(card, LCS_STARTUP_THREAD))
- return 0;
- LCS_DBF_TEXT(4, trace, "lgwstaln");
- if (card->dev)
- netif_stop_queue(card->dev);
- rc = lcs_send_startup(card, LCS_INITIATOR_LGW);
- if (rc != 0) {
- PRINT_ERR("Startup for LCS device %s initiated " \
- "by LGW failed!\nReseting card ...\n",
- card->dev->name);
- /* do a card reset */
- rc = lcs_resetcard(card);
- if (rc == 0)
- goto Done;
- }
- rc = lcs_startlan(card);
- if (rc == 0) {
- netif_wake_queue(card->dev);
- card->state = DEV_STATE_UP;
- }
-Done:
- if (rc == 0)
- PRINT_INFO("LCS Startup for device %s succeeded!\n",
- card->dev->name);
- else
- PRINT_ERR("LCS Startup for device %s failed!\n",
- card->dev->name);
- lcs_clear_thread_running_bit(card, LCS_STARTUP_THREAD);
- return 0;
-}
-
-
-/**
- * send stoplan command initiated by Lan Gateway
- */
-static int
-lcs_lgw_stoplan_thread(void *data)
-{
- struct lcs_card *card;
- int rc;
-
- card = (struct lcs_card *) data;
- daemonize("lgwstop");
-
- if (!lcs_do_run_thread(card, LCS_STOPLAN_THREAD))
- return 0;
- LCS_DBF_TEXT(4, trace, "lgwstop");
- if (card->dev)
- netif_stop_queue(card->dev);
- if (lcs_send_stoplan(card, LCS_INITIATOR_LGW) == 0)
- PRINT_INFO("Stoplan for %s initiated by LGW succeeded!\n",
- card->dev->name);
- else
- PRINT_ERR("Stoplan %s initiated by LGW failed!\n",
- card->dev->name);
- /*Try to reset the card, stop it on failure */
- rc = lcs_resetcard(card);
- if (rc != 0)
- rc = lcs_stopcard(card);
- lcs_clear_thread_running_bit(card, LCS_STOPLAN_THREAD);
- return rc;
-}
-
-/**
* Kernel Thread helper functions for LGW initiated commands
*/
static void
lcs_start_kernel_thread(struct lcs_card *card)
{
LCS_DBF_TEXT(5, trace, "krnthrd");
- if (lcs_do_start_thread(card, LCS_STARTUP_THREAD))
- kernel_thread(lcs_lgw_startup_thread, (void *) card, SIGCHLD);
- if (lcs_do_start_thread(card, LCS_STARTLAN_THREAD))
- kernel_thread(lcs_lgw_startlan_thread, (void *) card, SIGCHLD);
- if (lcs_do_start_thread(card, LCS_STOPLAN_THREAD))
- kernel_thread(lcs_lgw_stoplan_thread, (void *) card, SIGCHLD);
+ if (lcs_do_start_thread(card, LCS_RECOVERY_THREAD))
+ kernel_thread(lcs_recovery, (void *) card, SIGCHLD);
#ifdef CONFIG_IP_MULTICAST
if (lcs_do_start_thread(card, LCS_SET_MC_THREAD))
- kernel_thread(lcs_register_mc_addresses, (void *) card, SIGCHLD);
+ kernel_thread(lcs_register_mc_addresses,
+ (void *) card, SIGCHLD);
#endif
}
@@ -1816,19 +1748,14 @@ lcs_get_control(struct lcs_card *card, struct lcs_cmd *cmd)
if (cmd->initiator == LCS_INITIATOR_LGW) {
switch(cmd->cmd_code) {
case LCS_CMD_STARTUP:
- if (!lcs_set_thread_start_bit(card,
- LCS_STARTUP_THREAD))
- schedule_work(&card->kernel_thread_starter);
- break;
case LCS_CMD_STARTLAN:
- if (!lcs_set_thread_start_bit(card,
- LCS_STARTLAN_THREAD))
- schedule_work(&card->kernel_thread_starter);
+ lcs_schedule_recovery(card);
break;
case LCS_CMD_STOPLAN:
- if (!lcs_set_thread_start_bit(card,
- LCS_STOPLAN_THREAD))
- schedule_work(&card->kernel_thread_starter);
+ PRINT_WARN("Stoplan for %s initiated by LGW.\n",
+ card->dev->name);
+ if (card->dev)
+ netif_carrier_off(card->dev);
break;
default:
PRINT_INFO("UNRECOGNIZED LGW COMMAND\n");
@@ -1944,8 +1871,11 @@ lcs_stop_device(struct net_device *dev)
LCS_DBF_TEXT(2, trace, "stopdev");
card = (struct lcs_card *) dev->priv;
- netif_stop_queue(dev);
+ netif_carrier_off(dev);
+ netif_tx_disable(dev);
dev->flags &= ~IFF_UP;
+ wait_event(card->write.wait_q,
+ (card->write.state != CH_STATE_RUNNING));
rc = lcs_stopcard(card);
if (rc)
PRINT_ERR("Try it again!\n ");
@@ -1971,6 +1901,7 @@ lcs_open_device(struct net_device *dev)
} else {
dev->flags |= IFF_UP;
+ netif_carrier_on(dev);
netif_wake_queue(dev);
card->state = DEV_STATE_UP;
}
@@ -2062,10 +1993,31 @@ lcs_timeout_store (struct device *dev, struct device_attribute *attr, const char
DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store);
+static ssize_t
+lcs_dev_recover_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct lcs_card *card = dev->driver_data;
+ char *tmp;
+ int i;
+
+ if (!card)
+ return -EINVAL;
+ if (card->state != DEV_STATE_UP)
+ return -EPERM;
+ i = simple_strtoul(buf, &tmp, 16);
+ if (i == 1)
+ lcs_schedule_recovery(card);
+ return count;
+}
+
+static DEVICE_ATTR(recover, 0200, NULL, lcs_dev_recover_store);
+
static struct attribute * lcs_attrs[] = {
&dev_attr_portno.attr,
&dev_attr_type.attr,
&dev_attr_lancmd_timeout.attr,
+ &dev_attr_recover.attr,
NULL,
};
@@ -2102,6 +2054,12 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev)
ccwgdev->dev.driver_data = card;
ccwgdev->cdev[0]->handler = lcs_irq;
ccwgdev->cdev[1]->handler = lcs_irq;
+ card->gdev = ccwgdev;
+ INIT_WORK(&card->kernel_thread_starter,
+ (void *) lcs_start_kernel_thread, card);
+ card->thread_start_mask = 0;
+ card->thread_allowed_mask = 0;
+ card->thread_running_mask = 0;
return 0;
}
@@ -2203,6 +2161,7 @@ netdev_out:
if (recover_state == DEV_STATE_RECOVER) {
lcs_set_multicast_list(card->dev);
card->dev->flags |= IFF_UP;
+ netif_carrier_on(card->dev);
netif_wake_queue(card->dev);
card->state = DEV_STATE_UP;
} else {
@@ -2232,7 +2191,7 @@ out:
* lcs_shutdown_device, called when setting the group device offline.
*/
static int
-lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
+__lcs_shutdown_device(struct ccwgroup_device *ccwgdev, int recovery_mode)
{
struct lcs_card *card;
enum lcs_dev_states recover_state;
@@ -2242,9 +2201,11 @@ lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
card = (struct lcs_card *)ccwgdev->dev.driver_data;
if (!card)
return -ENODEV;
- lcs_set_allowed_threads(card, 0);
- if (lcs_wait_for_threads(card, LCS_SET_MC_THREAD))
- return -ERESTARTSYS;
+ if (recovery_mode == 0) {
+ lcs_set_allowed_threads(card, 0);
+ if (lcs_wait_for_threads(card, LCS_SET_MC_THREAD))
+ return -ERESTARTSYS;
+ }
LCS_DBF_HEX(3, setup, &card, sizeof(void*));
recover_state = card->state;
@@ -2259,6 +2220,43 @@ lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
return 0;
}
+static int
+lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
+{
+ return __lcs_shutdown_device(ccwgdev, 0);
+}
+
+/**
+ * drive lcs recovery after startup and startlan initiated by Lan Gateway
+ */
+static int
+lcs_recovery(void *ptr)
+{
+ struct lcs_card *card;
+ struct ccwgroup_device *gdev;
+ int rc;
+
+ card = (struct lcs_card *) ptr;
+ daemonize("lcs_recover");
+
+ LCS_DBF_TEXT(4, trace, "recover1");
+ if (!lcs_do_run_thread(card, LCS_RECOVERY_THREAD))
+ return 0;
+ LCS_DBF_TEXT(4, trace, "recover2");
+ gdev = card->gdev;
+ PRINT_WARN("Recovery of device %s started...\n", gdev->dev.bus_id);
+ rc = __lcs_shutdown_device(gdev, 1);
+ rc = lcs_new_device(gdev);
+ if (!rc)
+ PRINT_INFO("Device %s successfully recovered!\n",
+ card->dev->name);
+ else
+ PRINT_INFO("Device %s could not be recovered!\n",
+ card->dev->name);
+ lcs_clear_thread_running_bit(card, LCS_RECOVERY_THREAD);
+ return 0;
+}
+
/**
* lcs_remove_device, free buffers and card
*/
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index 2fad5e40c2e..93143932983 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -73,13 +73,17 @@ do { \
/**
* LCS sense byte definitions
*/
+#define LCS_SENSE_BYTE_0 0
+#define LCS_SENSE_BYTE_1 1
+#define LCS_SENSE_BYTE_2 2
+#define LCS_SENSE_BYTE_3 3
#define LCS_SENSE_INTERFACE_DISCONNECT 0x01
#define LCS_SENSE_EQUIPMENT_CHECK 0x10
#define LCS_SENSE_BUS_OUT_CHECK 0x20
#define LCS_SENSE_INTERVENTION_REQUIRED 0x40
#define LCS_SENSE_CMD_REJECT 0x80
-#define LCS_SENSE_RESETTING_EVENT 0x0080
-#define LCS_SENSE_DEVICE_ONLINE 0x0020
+#define LCS_SENSE_RESETTING_EVENT 0x80
+#define LCS_SENSE_DEVICE_ONLINE 0x20
/**
* LCS packet type definitions
@@ -152,10 +156,9 @@ enum lcs_dev_states {
enum lcs_threads {
LCS_SET_MC_THREAD = 1,
- LCS_STARTLAN_THREAD = 2,
- LCS_STOPLAN_THREAD = 4,
- LCS_STARTUP_THREAD = 8,
+ LCS_RECOVERY_THREAD = 2,
};
+
/**
* LCS struct declarations
*/
@@ -286,6 +289,7 @@ struct lcs_card {
struct net_device_stats stats;
unsigned short (*lan_type_trans)(struct sk_buff *skb,
struct net_device *dev);
+ struct ccwgroup_device *gdev;
struct lcs_channel read;
struct lcs_channel write;
struct lcs_buffer *tx_buffer;
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 260a93c8c44..b452cc1afd5 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -30,7 +30,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
-
+
#undef DEBUG
#include <linux/module.h>
@@ -65,7 +65,7 @@ MODULE_AUTHOR
("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
-
+
#define PRINTK_HEADER " iucv: " /* for debugging */
static struct device_driver netiucv_driver = {
@@ -202,7 +202,7 @@ netiucv_printname(char *name)
*p = '\0';
return tmp;
}
-
+
/**
* States of the interface statemachine.
*/
@@ -244,7 +244,7 @@ static const char *dev_event_names[] = {
"Connection up",
"Connection down",
};
-
+
/**
* Events of the connection statemachine
*/
@@ -364,7 +364,7 @@ static const char *conn_state_names[] = {
"Connect error",
};
-
+
/**
* Debug Facility Stuff
*/
@@ -516,7 +516,7 @@ static void
fsm_action_nop(fsm_instance *fi, int event, void *arg)
{
}
-
+
/**
* Actions of the connection statemachine
*****************************************************************************/
@@ -993,7 +993,7 @@ static const fsm_node conn_fsm[] = {
static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);
-
+
/**
* Actions for interface - statemachine.
*****************************************************************************/
@@ -1182,7 +1182,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
fsm_newstate(conn->fsm, CONN_STATE_TX);
conn->prof.send_stamp = xtime;
-
+
rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */,
0, nskb->data, nskb->len);
/* Shut up, gcc! nskb is always below 2G. */
@@ -1220,7 +1220,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
return rc;
}
-
+
/**
* Interface API for upper network layers
*****************************************************************************/
@@ -1291,7 +1291,7 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
/**
* If connection is not running, try to restart it
- * and throw away packet.
+ * and throw away packet.
*/
if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
fsm_event(privptr->fsm, DEV_EVENT_START, dev);
@@ -1538,7 +1538,7 @@ static ssize_t
maxcq_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
-
+
IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
priv->conn->prof.maxcqueue = 0;
return count;
@@ -1559,7 +1559,7 @@ static ssize_t
sdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
-
+
IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
priv->conn->prof.doios_single = 0;
return count;
@@ -1580,7 +1580,7 @@ static ssize_t
mdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
-
+
IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
priv->conn->prof.doios_multi = 0;
return count;
@@ -1601,7 +1601,7 @@ static ssize_t
txlen_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
-
+
IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
priv->conn->prof.txlen = 0;
return count;
@@ -1622,7 +1622,7 @@ static ssize_t
txtime_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
-
+
IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
priv->conn->prof.tx_time = 0;
return count;
@@ -2000,7 +2000,7 @@ conn_write(struct device_driver *drv, const char *buf, size_t count)
}
PRINT_INFO("%s: '%s'\n", dev->name, netiucv_printname(username));
-
+
return count;
out_free_ndev:
@@ -2099,7 +2099,7 @@ static int __init
netiucv_init(void)
{
int ret;
-
+
ret = iucv_register_dbf_views();
if (ret) {
PRINT_WARN("netiucv_init failed, "
@@ -2128,7 +2128,7 @@ netiucv_init(void)
}
return ret;
}
-
+
module_init(netiucv_init);
module_exit(netiucv_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 4df0fcd7b10..619f4a0c716 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -376,7 +376,7 @@ struct qeth_hdr_osn {
__u8 reserved3[18];
__u32 ccid;
} __attribute__ ((packed));
-
+
struct qeth_hdr {
union {
struct qeth_hdr_layer2 l2;
@@ -825,7 +825,7 @@ struct qeth_card {
int use_hard_stop;
int (*orig_hard_header)(struct sk_buff *,struct net_device *,
unsigned short,void *,void *,unsigned);
- struct qeth_osn_info osn_info;
+ struct qeth_osn_info osn_info;
};
struct qeth_card_list_struct {
@@ -944,7 +944,7 @@ qeth_get_netdev_flags(struct qeth_card *card)
return 0;
switch (card->info.type) {
case QETH_CARD_TYPE_IQD:
- case QETH_CARD_TYPE_OSN:
+ case QETH_CARD_TYPE_OSN:
return IFF_NOARP;
#ifdef CONFIG_QETH_IPV6
default:
@@ -981,7 +981,7 @@ static inline int
qeth_get_max_mtu_for_card(int cardtype)
{
switch (cardtype) {
-
+
case QETH_CARD_TYPE_UNKNOWN:
case QETH_CARD_TYPE_OSAE:
case QETH_CARD_TYPE_OSN:
@@ -1097,9 +1097,9 @@ qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
int count = 0, rc = 0;
int in[4];
- rc = sscanf(buf, "%d.%d.%d.%d%n",
+ rc = sscanf(buf, "%d.%d.%d.%d%n",
&in[0], &in[1], &in[2], &in[3], &count);
- if (rc != 4 || count)
+ if (rc != 4 || count<=0)
return -EINVAL;
for (count = 0; count < 4; count++) {
if (in[count] > 255)
@@ -1131,7 +1131,7 @@ qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
cnt = out = found = save_cnt = num2 = 0;
end = start = (char *) buf;
- in = (__u16 *) addr;
+ in = (__u16 *) addr;
memset(in, 0, 16);
while (end) {
end = strchr(end,':');
@@ -1139,7 +1139,7 @@ qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
end = (char *)buf + (strlen(buf));
out = 1;
}
- if ((end - start)) {
+ if ((end - start)) {
memset(num, 0, 5);
memcpy(num, start, end - start);
if (!qeth_isxdigit(num))
@@ -1241,5 +1241,5 @@ qeth_osn_register(unsigned char *read_dev_no,
extern void
qeth_osn_deregister(struct net_device *);
-
+
#endif /* __QETH_H__ */
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index 44e226f211e..0bab60a2030 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -81,7 +81,7 @@ void
qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
{
struct qeth_eddp_context_reference *ref;
-
+
QETH_DBF_TEXT(trace, 6, "eddprctx");
while (!list_empty(&buf->ctx_list)){
ref = list_entry(buf->ctx_list.next,
@@ -135,7 +135,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
"buffer!\n");
goto out;
}
- }
+ }
/* check if the whole next skb fits into current buffer */
if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) -
buf->next_element_to_fill)
@@ -148,7 +148,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
* and increment ctx's refcnt */
must_refcnt = 1;
continue;
- }
+ }
if (must_refcnt){
must_refcnt = 0;
if (qeth_eddp_buf_ref_context(buf, ctx)){
@@ -266,7 +266,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
int left_in_frag;
int copy_len;
u8 *src;
-
+
QETH_DBF_TEXT(trace, 5, "eddpcdtc");
if (skb_shinfo(eddp->skb)->nr_frags == 0) {
memcpy(dst, eddp->skb->data + eddp->skb_offset, len);
@@ -408,7 +408,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
struct tcphdr *tcph;
int data_len;
u32 hcsum;
-
+
QETH_DBF_TEXT(trace, 5, "eddpftcp");
eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
@@ -465,13 +465,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
eddp->th.tcp.h.seq += data_len;
}
}
-
+
static inline int
qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
struct sk_buff *skb, struct qeth_hdr *qhdr)
{
struct qeth_eddp_data *eddp = NULL;
-
+
QETH_DBF_TEXT(trace, 5, "eddpficx");
/* create our segmentation headers and copy original headers */
if (skb->protocol == ETH_P_IP)
@@ -512,7 +512,7 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
int hdr_len)
{
int skbs_per_page;
-
+
QETH_DBF_TEXT(trace, 5, "eddpcanp");
/* can we put multiple skbs in one page? */
skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
@@ -588,7 +588,7 @@ qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *qhdr)
{
struct qeth_eddp_context *ctx = NULL;
-
+
QETH_DBF_TEXT(trace, 5, "creddpct");
if (skb->protocol == ETH_P_IP)
ctx = qeth_eddp_create_context_generic(card, skb,
diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h
index e422b41c656..61faf05517d 100644
--- a/drivers/s390/net/qeth_fs.h
+++ b/drivers/s390/net/qeth_fs.h
@@ -42,7 +42,7 @@ qeth_create_device_attributes_osn(struct device *dev);
extern void
qeth_remove_device_attributes_osn(struct device *dev);
-
+
extern int
qeth_create_driver_attributes(void);
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index b3c6e790779..9e671a48cd2 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -513,7 +513,7 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
QETH_DBF_TEXT(setup, 3, "setoffl");
QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
-
+
if (card->dev && netif_carrier_ok(card->dev))
netif_carrier_off(card->dev);
recover_flag = card->state;
@@ -604,13 +604,13 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
list_for_each_entry(addr, &card->ip_list, entry) {
if (card->options.layer2) {
if ((addr->type == todo->type) &&
- (memcmp(&addr->mac, &todo->mac,
+ (memcmp(&addr->mac, &todo->mac,
OSA_ADDR_LEN) == 0)) {
found = 1;
break;
}
continue;
- }
+ }
if ((addr->proto == QETH_PROT_IPV4) &&
(todo->proto == QETH_PROT_IPV4) &&
(addr->type == todo->type) &&
@@ -694,13 +694,13 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
if (card->options.layer2) {
if ((tmp->type == addr->type) &&
(tmp->is_multicast == addr->is_multicast) &&
- (memcmp(&tmp->mac, &addr->mac,
+ (memcmp(&tmp->mac, &addr->mac,
OSA_ADDR_LEN) == 0)) {
found = 1;
break;
}
continue;
- }
+ }
if ((tmp->proto == QETH_PROT_IPV4) &&
(addr->proto == QETH_PROT_IPV4) &&
(tmp->type == addr->type) &&
@@ -1173,7 +1173,7 @@ qeth_determine_card_type(struct qeth_card *card)
"due to hardware limitations!\n");
card->qdio.no_out_queues = 1;
card->qdio.default_out_queue = 0;
- }
+ }
return 0;
}
i++;
@@ -1198,7 +1198,7 @@ qeth_probe_device(struct ccwgroup_device *gdev)
return -ENODEV;
QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
-
+
card = qeth_alloc_card();
if (!card) {
put_device(dev);
@@ -1220,7 +1220,7 @@ qeth_probe_device(struct ccwgroup_device *gdev)
put_device(dev);
qeth_free_card(card);
return rc;
- }
+ }
if ((rc = qeth_setup_card(card))){
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
put_device(dev);
@@ -1843,7 +1843,7 @@ struct qeth_cmd_buffer *iob)
&card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
}
-
+
static int
qeth_send_control_data(struct qeth_card *card, int len,
struct qeth_cmd_buffer *iob,
@@ -1937,7 +1937,7 @@ qeth_osn_send_control_data(struct qeth_card *card, int len,
wake_up(&card->wait_q);
}
return rc;
-}
+}
static inline void
qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
@@ -1966,7 +1966,7 @@ qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
return qeth_osn_send_control_data(card, s1, iob);
}
-
+
static int
qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
int (*reply_cb)
@@ -2579,7 +2579,7 @@ qeth_process_inbound_buffer(struct qeth_card *card,
skb->dev = card->dev;
if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr);
- else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
+ else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
qeth_rebuild_skb(card, skb, hdr);
else { /*in case of OSN*/
skb_push(skb, sizeof(struct qeth_hdr));
@@ -2763,7 +2763,7 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
index = i % QDIO_MAX_BUFFERS_PER_Q;
buffer = &card->qdio.in_q->bufs[index];
if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
- qeth_check_qdio_errors(buffer->buffer,
+ qeth_check_qdio_errors(buffer->buffer,
qdio_err, siga_err,"qinerr")))
qeth_process_inbound_buffer(card, buffer, index);
/* clear buffer and give back to hardware */
@@ -3187,7 +3187,7 @@ qeth_alloc_qdio_buffers(struct qeth_card *card)
if (card->qdio.state == QETH_QDIO_ALLOCATED)
return 0;
- card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
+ card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
GFP_KERNEL|GFP_DMA);
if (!card->qdio.in_q)
return - ENOMEM;
@@ -3476,7 +3476,7 @@ qeth_halt_channels(struct qeth_card *card)
rc3 = qeth_halt_channel(&card->data);
if (rc1)
return rc1;
- if (rc2)
+ if (rc2)
return rc2;
return rc3;
}
@@ -3491,7 +3491,7 @@ qeth_clear_channels(struct qeth_card *card)
rc3 = qeth_clear_channel(&card->data);
if (rc1)
return rc1;
- if (rc2)
+ if (rc2)
return rc2;
return rc3;
}
@@ -3798,10 +3798,10 @@ qeth_open(struct net_device *dev)
QETH_DBF_TEXT(trace,4,"nomacadr");
return -EPERM;
}
- card->dev->flags |= IFF_UP;
- netif_start_queue(dev);
card->data.state = CH_STATE_UP;
card->state = CARD_STATE_UP;
+ card->dev->flags |= IFF_UP;
+ netif_start_queue(dev);
if (!card->lan_online && netif_carrier_ok(dev))
netif_carrier_off(dev);
@@ -3817,7 +3817,7 @@ qeth_stop(struct net_device *dev)
card = (struct qeth_card *) dev->priv;
- netif_stop_queue(dev);
+ netif_tx_disable(dev);
card->dev->flags &= ~IFF_UP;
if (card->state == CARD_STATE_UP)
card->state = CARD_STATE_SOFTSETUP;
@@ -3958,7 +3958,7 @@ qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
#endif
*hdr = (struct qeth_hdr *)
qeth_push_skb(card, skb, sizeof(struct qeth_hdr));
- if (hdr == NULL)
+ if (*hdr == NULL)
return -EINVAL;
return 0;
}
@@ -4098,7 +4098,7 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
}
} else { /* passthrough */
if((skb->dev->type == ARPHRD_IEEE802_TR) &&
- !memcmp(skb->data + sizeof(struct qeth_hdr) +
+ !memcmp(skb->data + sizeof(struct qeth_hdr) +
sizeof(__u16), skb->dev->broadcast, 6)) {
hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
QETH_HDR_PASSTHRU;
@@ -4385,7 +4385,7 @@ out:
}
static inline int
-qeth_get_elements_no(struct qeth_card *card, void *hdr,
+qeth_get_elements_no(struct qeth_card *card, void *hdr,
struct sk_buff *skb, int elems)
{
int elements_needed = 0;
@@ -4416,6 +4416,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
struct qeth_eddp_context *ctx = NULL;
int tx_bytes = skb->len;
+ unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
+ unsigned short tso_size = skb_shinfo(skb)->tso_size;
int rc;
QETH_DBF_TEXT(trace, 6, "sendpkt");
@@ -4441,7 +4443,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
return 0;
}
cast_type = qeth_get_cast_type(card, skb);
- if ((cast_type == RTN_BROADCAST) &&
+ if ((cast_type == RTN_BROADCAST) &&
(card->info.broadcast_capable == 0)){
card->stats.tx_dropped++;
card->stats.tx_errors++;
@@ -4463,7 +4465,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
card->stats.tx_errors++;
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
- }
+ }
elements_needed++;
} else {
if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))) {
@@ -4498,16 +4500,16 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
card->stats.tx_packets++;
card->stats.tx_bytes += tx_bytes;
#ifdef CONFIG_QETH_PERF_STATS
- if (skb_shinfo(skb)->tso_size &&
+ if (tso_size &&
!(large_send == QETH_LARGE_SEND_NO)) {
- card->perf_stats.large_send_bytes += skb->len;
+ card->perf_stats.large_send_bytes += tx_bytes;
card->perf_stats.large_send_cnt++;
}
- if (skb_shinfo(skb)->nr_frags > 0){
+ if (nr_frags > 0){
card->perf_stats.sg_skbs_sent++;
/* nr_frags + skb->data */
card->perf_stats.sg_frags_sent +=
- skb_shinfo(skb)->nr_frags + 1;
+ nr_frags + 1;
}
#endif /* CONFIG_QETH_PERF_STATS */
}
@@ -5373,7 +5375,7 @@ qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
cmd = (struct qeth_ipa_cmd *) data;
if (cmd->hdr.return_code) {
PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
- "Continuing\n",cmd->data.setdelvlan.vlan_id,
+ "Continuing\n",cmd->data.setdelvlan.vlan_id,
QETH_CARD_IFNAME(card), cmd->hdr.return_code);
QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command);
QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
@@ -5393,7 +5395,7 @@ qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
cmd->data.setdelvlan.vlan_id = i;
- return qeth_send_ipa_cmd(card, iob,
+ return qeth_send_ipa_cmd(card, iob,
qeth_layer2_send_setdelvlan_cb, NULL);
}
@@ -5457,7 +5459,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
* Examine hardware response to SET_PROMISC_MODE
*/
static int
-qeth_setadp_promisc_mode_cb(struct qeth_card *card,
+qeth_setadp_promisc_mode_cb(struct qeth_card *card,
struct qeth_reply *reply,
unsigned long data)
{
@@ -5468,10 +5470,10 @@ qeth_setadp_promisc_mode_cb(struct qeth_card *card,
cmd = (struct qeth_ipa_cmd *) data;
setparms = &(cmd->data.setadapterparms);
-
+
qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
- if (cmd->hdr.return_code) {
- QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);
+ if (cmd->hdr.return_code) {
+ QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);
setparms->data.mode = SET_PROMISC_MODE_OFF;
}
card->info.promisc_mode = setparms->data.mode;
@@ -5517,7 +5519,7 @@ qeth_set_multicast_list(struct net_device *dev)
if (card->info.type == QETH_CARD_TYPE_OSN)
return ;
-
+
QETH_DBF_TEXT(trace, 3, "setmulti");
qeth_delete_mc_addresses(card);
if (card->options.layer2) {
@@ -5575,7 +5577,7 @@ qeth_osn_assist(struct net_device *dev,
struct qeth_cmd_buffer *iob;
struct qeth_card *card;
int rc;
-
+
QETH_DBF_TEXT(trace, 2, "osnsdmc");
if (!dev)
return -ENODEV;
@@ -5654,7 +5656,7 @@ qeth_osn_deregister(struct net_device * dev)
card->osn_info.data_cb = NULL;
return;
}
-
+
static void
qeth_delete_mc_addresses(struct qeth_card *card)
{
@@ -5818,7 +5820,7 @@ qeth_add_multicast_ipv6(struct qeth_card *card)
struct inet6_dev *in6_dev;
QETH_DBF_TEXT(trace,4,"chkmcv6");
- if (!qeth_is_supported(card, IPA_IPV6))
+ if (!qeth_is_supported(card, IPA_IPV6))
return ;
in6_dev = in6_dev_get(card->dev);
if (in6_dev == NULL)
@@ -6359,12 +6361,9 @@ qeth_netdev_init(struct net_device *dev)
dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid;
#endif
- dev->hard_header = card->orig_hard_header;
if (qeth_get_netdev_flags(card) & IFF_NOARP) {
dev->rebuild_header = NULL;
dev->hard_header = NULL;
- if (card->options.fake_ll)
- dev->hard_header = qeth_fake_header;
dev->header_cache_update = NULL;
dev->hard_header_cache = NULL;
}
@@ -6373,6 +6372,9 @@ qeth_netdev_init(struct net_device *dev)
if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
card->dev->dev_id = card->info.unique_id & 0xffff;
#endif
+ if (card->options.fake_ll &&
+ (qeth_get_netdev_flags(card) & IFF_NOARP))
+ dev->hard_header = qeth_fake_header;
dev->hard_header_parse = NULL;
dev->set_mac_address = qeth_layer2_set_mac_address;
dev->flags |= qeth_get_netdev_flags(card);
@@ -6477,6 +6479,9 @@ retry:
/*network device will be recovered*/
if (card->dev) {
card->dev->hard_header = card->orig_hard_header;
+ if (card->options.fake_ll &&
+ (qeth_get_netdev_flags(card) & IFF_NOARP))
+ card->dev->hard_header = qeth_fake_header;
return 0;
}
/* at first set_online allocate netdev */
@@ -6584,7 +6589,7 @@ qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
cmd = (struct qeth_ipa_cmd *) data;
if (!card->options.layer2 || card->info.guestlan ||
- !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
+ !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
memcpy(card->dev->dev_addr,
&cmd->data.setadapterparms.data.change_addr.addr,
OSA_ADDR_LEN);
@@ -7031,14 +7036,12 @@ qeth_softsetup_ipv6(struct qeth_card *card)
QETH_DBF_TEXT(trace,3,"softipv6");
- netif_stop_queue(card->dev);
rc = qeth_send_startlan(card, QETH_PROT_IPV6);
if (rc) {
PRINT_ERR("IPv6 startlan failed on %s\n",
QETH_CARD_IFNAME(card));
return rc;
}
- netif_wake_queue(card->dev);
rc = qeth_query_ipassists(card,QETH_PROT_IPV6);
if (rc) {
PRINT_ERR("IPv6 query ipassist failed on %s\n",
@@ -7352,7 +7355,8 @@ qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
card->options.large_send = type;
return 0;
}
- netif_stop_queue(card->dev);
+ if (card->state == CARD_STATE_UP)
+ netif_tx_disable(card->dev);
card->options.large_send = type;
switch (card->options.large_send) {
case QETH_LARGE_SEND_EDDP:
@@ -7374,7 +7378,8 @@ qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
break;
}
- netif_wake_queue(card->dev);
+ if (card->state == CARD_STATE_UP)
+ netif_wake_queue(card->dev);
return rc;
}
@@ -7427,7 +7432,7 @@ qeth_softsetup_card(struct qeth_card *card)
if ((rc = qeth_setrouting_v6(card)))
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
out:
- netif_stop_queue(card->dev);
+ netif_tx_disable(card->dev);
return 0;
}
@@ -7567,7 +7572,7 @@ qeth_stop_card(struct qeth_card *card, int recovery_mode)
if (card->read.state == CH_STATE_UP &&
card->write.state == CH_STATE_UP &&
(card->state == CARD_STATE_UP)) {
- if (recovery_mode &&
+ if (recovery_mode &&
card->info.type != QETH_CARD_TYPE_OSN) {
qeth_stop(card->dev);
} else {
@@ -7736,10 +7741,8 @@ static int
qeth_register_netdev(struct qeth_card *card)
{
QETH_DBF_TEXT(setup, 3, "regnetd");
- if (card->dev->reg_state != NETREG_UNINITIALIZED) {
- qeth_netdev_init(card->dev);
+ if (card->dev->reg_state != NETREG_UNINITIALIZED)
return 0;
- }
/* sysfs magic */
SET_NETDEV_DEV(card->dev, &card->gdev->dev);
return register_netdev(card->dev);
@@ -7750,7 +7753,7 @@ qeth_start_again(struct qeth_card *card, int recovery_mode)
{
QETH_DBF_TEXT(setup ,2, "startag");
- if (recovery_mode &&
+ if (recovery_mode &&
card->info.type != QETH_CARD_TYPE_OSN) {
qeth_open(card->dev);
} else {
@@ -8014,7 +8017,6 @@ static int (*qeth_old_arp_constructor) (struct neighbour *);
static struct neigh_ops arp_direct_ops_template = {
.family = AF_INET,
- .destructor = NULL,
.solicit = NULL,
.error_report = NULL,
.output = dev_queue_xmit,
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
index 011c4104102..0477c47471c 100644
--- a/drivers/s390/net/qeth_mpc.h
+++ b/drivers/s390/net/qeth_mpc.h
@@ -445,7 +445,7 @@ enum qeth_ipa_arp_return_codes {
/* Helper functions */
#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
(cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
-
+
/*****************************************************************************/
/* END OF IP Assist related definitions */
/*****************************************************************************/
@@ -490,7 +490,7 @@ extern unsigned char ULP_ENABLE[];
/* Layer 2 defintions */
#define QETH_PROT_LAYER2 0x08
#define QETH_PROT_TCPIP 0x03
-#define QETH_PROT_OSN2 0x0a
+#define QETH_PROT_OSN2 0x0a
#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50)
#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19)
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index 360d782c7ad..66f2da14e6e 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -36,7 +36,7 @@ qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
{
struct device *dev = NULL;
loff_t nr = 0;
-
+
down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
if (*offset == 0)
return SEQ_START_TOKEN;
@@ -60,8 +60,8 @@ static void *
qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
{
struct device *prev, *next;
-
- if (it == SEQ_START_TOKEN)
+
+ if (it == SEQ_START_TOKEN)
prev = NULL;
else
prev = (struct device *) it;
@@ -180,7 +180,7 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
struct device *device;
struct qeth_card *card;
-
+
if (it == SEQ_START_TOKEN)
return 0;
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index 882d419e416..185a9cfbcbd 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -785,7 +785,7 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con
}
if (card->options.large_send == type)
return count;
- if ((rc = qeth_set_large_send(card, type)))
+ if ((rc = qeth_set_large_send(card, type)))
return rc;
return count;
}
@@ -1682,7 +1682,7 @@ qeth_create_device_attributes(struct device *dev)
if (card->info.type == QETH_CARD_TYPE_OSN)
return sysfs_create_group(&dev->kobj,
&qeth_osn_device_attr_group);
-
+
if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group)))
return ret;
if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){
@@ -1713,7 +1713,7 @@ qeth_remove_device_attributes(struct device *dev)
if (card->info.type == QETH_CARD_TYPE_OSN)
return sysfs_remove_group(&dev->kobj,
&qeth_osn_device_attr_group);
-
+
sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
index 1286ddea450..24ef40ca956 100644
--- a/drivers/s390/net/qeth_tso.h
+++ b/drivers/s390/net/qeth_tso.h
@@ -117,11 +117,11 @@ __qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
int fragno;
unsigned long addr;
int element, cnt, dlen;
-
+
fragno = skb_shinfo(skb)->nr_frags;
element = *next_element_to_fill;
dlen = 0;
-
+
if (is_tso)
buffer->element[element].flags =
SBAL_FLAGS_MIDDLE_FRAG;
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 3bf46660351..f99e55308b3 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/workqueue.h>
+#include <linux/time.h>
#include <asm/lowcore.h>
@@ -362,12 +363,19 @@ s390_revalidate_registers(struct mci *mci)
return kill_task;
}
+#define MAX_IPD_COUNT 29
+#define MAX_IPD_TIME (5 * 60 * USEC_PER_SEC) /* 5 minutes */
+
/*
* machine check handler.
*/
void
s390_do_machine_check(struct pt_regs *regs)
{
+ static DEFINE_SPINLOCK(ipd_lock);
+ static unsigned long long last_ipd;
+ static int ipd_count;
+ unsigned long long tmp;
struct mci *mci;
struct mcck_struct *mcck;
int umode;
@@ -404,11 +412,27 @@ s390_do_machine_check(struct pt_regs *regs)
s390_handle_damage("processing backup machine "
"check with damage.");
}
- if (!umode)
- s390_handle_damage("processing backup machine "
- "check in kernel mode.");
- mcck->kill_task = 1;
- mcck->mcck_code = *(unsigned long long *) mci;
+
+ /*
+ * Nullifying exigent condition, therefore we might
+ * retry this instruction.
+ */
+
+ spin_lock(&ipd_lock);
+
+ tmp = get_clock();
+
+ if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME)
+ ipd_count++;
+ else
+ ipd_count = 1;
+
+ last_ipd = tmp;
+
+ if (ipd_count == MAX_IPD_COUNT)
+ s390_handle_damage("too many ipd retries.");
+
+ spin_unlock(&ipd_lock);
}
else {
/* Processing damage -> stopping machine */
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 383a95f34a0..239e108b8ed 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -392,13 +392,16 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file,
return -ENOMEM;
}
- prom_getproperty(op.op_nodeid, str, tmp, len);
-
- tmp[len] = '\0';
+ cnt = prom_getproperty(op.op_nodeid, str, tmp, len);
+ if (cnt <= 0) {
+ error = -EINVAL;
+ } else {
+ tmp[len] = '\0';
- if (__copy_to_user(argp, &op, sizeof(op)) != 0
- || copy_to_user(op.op_buf, tmp, len) != 0)
- error = -EFAULT;
+ if (__copy_to_user(argp, &op, sizeof(op)) != 0 ||
+ copy_to_user(op.op_buf, tmp, len) != 0)
+ error = -EFAULT;
+ }
kfree(tmp);
kfree(str);
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 0ab26d01877..caeb6d246e5 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -65,6 +65,7 @@
2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher.
2.26.02.006 - Fix 9550SX pchip reset timeout.
Add big endian support.
+ 2.26.02.007 - Disable local interrupts during kmap/unmap_atomic().
*/
#include <linux/module.h>
@@ -88,7 +89,7 @@
#include "3w-9xxx.h"
/* Globals */
-#define TW_DRIVER_VERSION "2.26.02.006"
+#define TW_DRIVER_VERSION "2.26.02.007"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count;
static int twa_major = -1;
@@ -1026,7 +1027,7 @@ static void twa_free_request_id(TW_Device_Extension *tw_dev, int request_id)
tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH;
} /* End twa_free_request_id() */
-/* This function will get parameter table entires from the firmware */
+/* This function will get parameter table entries from the firmware */
static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int table_id, int parameter_id, int parameter_size_bytes)
{
TW_Command_Full *full_command_packet;
@@ -1942,9 +1943,13 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
}
if (tw_dev->srb[request_id]->use_sg == 1) {
struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
- char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ char *buf;
+ unsigned long flags = 0;
+ local_irq_save(flags);
+ buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);
kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ local_irq_restore(flags);
}
}
} /* End twa_scsiop_execute_scsi_complete() */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 25f678d0780..e8e41e6eb42 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1508,10 +1508,12 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
struct scsi_cmnd *cmd = tw_dev->srb[request_id];
void *buf;
unsigned int transfer_len;
+ unsigned long flags = 0;
if (cmd->use_sg) {
struct scatterlist *sg =
(struct scatterlist *)cmd->request_buffer;
+ local_irq_save(flags);
buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
transfer_len = min(sg->length, len);
} else {
@@ -1526,6 +1528,7 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
sg = (struct scatterlist *)cmd->request_buffer;
kunmap_atomic(buf - sg->offset, KM_IRQ0);
+ local_irq_restore(flags);
}
}
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 1c459343292..bde3d5834ad 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -41,6 +41,8 @@
#include <linux/stat.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+#include <linux/dma-mapping.h>
#include <scsi/scsicam.h>
#include <asm/dma.h>
@@ -676,7 +678,7 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd
if (pci_enable_device(PCI_Device))
continue;
- if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff))
+ if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK ))
continue;
Bus = PCI_Device->bus->number;
@@ -831,7 +833,7 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd
if (pci_enable_device(PCI_Device))
continue;
- if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff))
+ if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK))
continue;
Bus = PCI_Device->bus->number;
@@ -885,7 +887,7 @@ static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAda
if (pci_enable_device(PCI_Device))
continue;
- if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff))
+ if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK))
continue;
Bus = PCI_Device->bus->number;
@@ -2896,7 +2898,7 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
*/
if (HostAdapter->ActiveCommands[TargetID] == 0)
HostAdapter->LastSequencePoint[TargetID] = jiffies;
- else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4 * HZ) {
+ else if (time_after(jiffies, HostAdapter->LastSequencePoint[TargetID] + 4 * HZ)) {
HostAdapter->LastSequencePoint[TargetID] = jiffies;
QueueTag = BusLogic_OrderedQueueTag;
}
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 4035920ce3d..a480a3742d4 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -446,7 +446,9 @@ config SCSI_DPT_I2O
config SCSI_ADVANSYS
tristate "AdvanSys SCSI support"
- depends on (ISA || EISA || PCI) && SCSI && BROKEN
+ depends on SCSI
+ depends on ISA || EISA || PCI
+ depends on BROKEN || X86_32
help
This is a driver for all SCSI host adapters manufactured by
AdvanSys. It is documented in the kernel source in
@@ -1079,7 +1081,7 @@ config SCSI_SYM53C8XX_DMA_ADDRESSING_MODE
memory using PCI DAC cycles.
config SCSI_SYM53C8XX_DEFAULT_TAGS
- int "default tagged command queue depth"
+ int "Default tagged command queue depth"
depends on SCSI_SYM53C8XX_2
default "16"
help
@@ -1090,7 +1092,7 @@ config SCSI_SYM53C8XX_DEFAULT_TAGS
exceed CONFIG_SCSI_SYM53C8XX_MAX_TAGS.
config SCSI_SYM53C8XX_MAX_TAGS
- int "maximum number of queued commands"
+ int "Maximum number of queued commands"
depends on SCSI_SYM53C8XX_2
default "64"
help
@@ -1099,13 +1101,14 @@ config SCSI_SYM53C8XX_MAX_TAGS
possible. The driver supports up to 256 queued commands per device.
This value is used as a compiled-in hard limit.
-config SCSI_SYM53C8XX_IOMAPPED
- bool "use port IO"
+config SCSI_SYM53C8XX_MMIO
+ bool "Use memory mapped IO"
depends on SCSI_SYM53C8XX_2
+ default y
help
- If you say Y here, the driver will use port IO to access
- the card. This is significantly slower then using memory
- mapped IO. Most people should answer N.
+ Memory mapped IO is faster than Port IO. Most people should
+ answer Y here, but some machines may have problems. If you have
+ to answer N here, please report the problem to the maintainer.
config SCSI_IPR
tristate "IBM Power Linux RAID adapter support"
@@ -1309,15 +1312,6 @@ config SCSI_QLOGIC_FAS
To compile this driver as a module, choose M here: the
module will be called qlogicfas.
-config SCSI_QLOGIC_FC
- tristate "Qlogic ISP FC SCSI support"
- depends on PCI && SCSI
- help
- This is a driver for the QLogic ISP2100 SCSI-FCP host adapter.
-
- To compile this driver as a module, choose M here: the
- module will be called qlogicfc.
-
config SCSI_QLOGIC_FC_FIRMWARE
bool "Include loadable firmware in driver"
depends on SCSI_QLOGIC_FC
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index e513c3158ad..81803a16f98 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -78,7 +78,6 @@ obj-$(CONFIG_SCSI_NCR_Q720) += NCR_Q720_mod.o
obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o
obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o
obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o
-obj-$(CONFIG_SCSI_QLOGIC_FC) += qlogicfc.o
obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o
obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx/
obj-$(CONFIG_SCSI_LPFC) += lpfc/
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 9f45ae1745d..3dce21c7873 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -89,6 +89,7 @@
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/slab.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -1052,7 +1053,7 @@ static int __devinit inia100_probe_one(struct pci_dev *pdev,
if (pci_enable_device(pdev))
goto out;
- if (pci_set_dma_mask(pdev, 0xffffffffULL)) {
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "Unable to set 32bit DMA "
"on inia100 adapter, ignoring.\n");
goto out_disable_device;
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index a16f8ded8f1..642a3b4e593 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -32,6 +32,7 @@
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
@@ -148,20 +149,20 @@ static int dacmode = -1;
static int commit = -1;
-module_param(nondasd, int, 0);
+module_param(nondasd, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
-module_param(dacmode, int, 0);
+module_param(dacmode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on");
-module_param(commit, int, 0);
+module_param(commit, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");
int numacb = -1;
module_param(numacb, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid\nvalues are 512 and down. Default is to use suggestion from Firmware.");
+MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid values are 512 and down. Default is to use suggestion from Firmware.");
int acbsize = -1;
module_param(acbsize, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512,\n2048, 4096 and 8192. Default is to use suggestion from Firmware.");
+MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware.");
/**
* aac_get_config_status - check the adapter configuration
* @common: adapter to query
@@ -386,6 +387,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
struct scsi_cmnd * scsicmd;
scsicmd = (struct scsi_cmnd *) context;
+ scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies));
if (fibptr == NULL)
@@ -452,8 +454,10 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS)
+ if (status == -EINPROGRESS) {
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
return 0;
+ }
printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
aac_fib_complete(cmd_fibcontext);
@@ -906,9 +910,10 @@ static void io_callback(void *context, struct fib * fibptr)
u32 cid;
scsicmd = (struct scsi_cmnd *) context;
+ scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
- cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
+ cid = scmd_id(scsicmd);
if (nblank(dprintk(x))) {
u64 lba;
@@ -1150,8 +1155,10 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS)
+ if (status == -EINPROGRESS) {
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
return 0;
+ }
printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status);
/*
@@ -1317,8 +1324,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS)
- {
+ if (status == -EINPROGRESS) {
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
return 0;
}
@@ -1340,6 +1347,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
struct scsi_cmnd *cmd;
cmd = context;
+ cmd->SCp.phase = AAC_OWNER_MIDLEVEL;
dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n",
smp_processor_id(), jiffies));
@@ -1353,7 +1361,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
else {
struct scsi_device *sdev = cmd->device;
struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
- u32 cid = ID_LUN_TO_CONTAINER(sdev->id, sdev->lun);
+ u32 cid = sdev_id(sdev);
printk(KERN_WARNING
"synchronize_callback: synchronize failed, status = %d\n",
le32_to_cpu(synchronizereply->status));
@@ -1385,12 +1393,12 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
unsigned long flags;
/*
- * Wait for all commands to complete to this specific
- * target (block).
+ * Wait for all outstanding queued commands to complete to this
+ * specific target (block).
*/
spin_lock_irqsave(&sdev->list_lock, flags);
list_for_each_entry(cmd, &sdev->cmd_list, list)
- if (cmd != scsicmd && cmd->serial_number != 0) {
+ if (cmd != scsicmd && cmd->SCp.phase == AAC_OWNER_FIRMWARE) {
++active;
break;
}
@@ -1433,8 +1441,10 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS)
+ if (status == -EINPROGRESS) {
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
return 0;
+ }
printk(KERN_WARNING
"aac_synchronize: aac_fib_send failed with status: %d.\n", status);
@@ -1457,7 +1467,6 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
struct Scsi_Host *host = scsicmd->device->host;
struct aac_dev *dev = (struct aac_dev *)host->hostdata;
struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
- int ret;
/*
* If the bus, id or lun is out of range, return fail
@@ -1465,13 +1474,14 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
* itself.
*/
if (scmd_id(scsicmd) != host->this_id) {
- if ((scsicmd->device->channel == CONTAINER_CHANNEL)) {
- if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){
+ if ((scmd_channel(scsicmd) == CONTAINER_CHANNEL)) {
+ if((scmd_id(scsicmd) >= dev->maximum_num_containers) ||
+ (scsicmd->device->lun != 0)) {
scsicmd->result = DID_NO_CONNECT << 16;
scsicmd->scsi_done(scsicmd);
return 0;
}
- cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
+ cid = scmd_id(scsicmd);
/*
* If the target container doesn't exist, it may have
@@ -1547,7 +1557,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
{
struct inquiry_data inq_data;
- dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id));
+ dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scmd_id(scsicmd)));
memset(&inq_data, 0, sizeof (struct inquiry_data));
inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */
@@ -1597,13 +1607,14 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
cp[11] = 0;
cp[12] = 0;
aac_internal_transfer(scsicmd, cp, 0,
- min((unsigned int)scsicmd->cmnd[13], sizeof(cp)));
+ min_t(size_t, scsicmd->cmnd[13], sizeof(cp)));
if (sizeof(cp) < scsicmd->cmnd[13]) {
unsigned int len, offset = sizeof(cp);
memset(cp, 0, offset);
do {
- len = min(scsicmd->cmnd[13]-offset, sizeof(cp));
+ len = min_t(size_t, scsicmd->cmnd[13] - offset,
+ sizeof(cp));
aac_internal_transfer(scsicmd, cp, offset, len);
} while ((offset += len) < scsicmd->cmnd[13]);
}
@@ -1727,24 +1738,19 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
* containers to /dev/sd device names
*/
- spin_unlock_irq(host->host_lock);
if (scsicmd->request->rq_disk)
strlcpy(fsa_dev_ptr[cid].devname,
scsicmd->request->rq_disk->disk_name,
min(sizeof(fsa_dev_ptr[cid].devname),
sizeof(scsicmd->request->rq_disk->disk_name) + 1));
- ret = aac_read(scsicmd, cid);
- spin_lock_irq(host->host_lock);
- return ret;
+
+ return aac_read(scsicmd, cid);
case WRITE_6:
case WRITE_10:
case WRITE_12:
case WRITE_16:
- spin_unlock_irq(host->host_lock);
- ret = aac_write(scsicmd, cid);
- spin_lock_irq(host->host_lock);
- return ret;
+ return aac_write(scsicmd, cid);
case SYNCHRONIZE_CACHE:
/* Issue FIB to tell Firmware to flush it's cache */
@@ -1777,7 +1783,7 @@ static int query_disk(struct aac_dev *dev, void __user *arg)
if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk)))
return -EFAULT;
if (qd.cnum == -1)
- qd.cnum = ID_LUN_TO_CONTAINER(qd.id, qd.lun);
+ qd.cnum = qd.id;
else if ((qd.bus == -1) && (qd.id == -1) && (qd.lun == -1))
{
if (qd.cnum < 0 || qd.cnum >= dev->maximum_num_containers)
@@ -1889,6 +1895,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
struct scsi_cmnd *scsicmd;
scsicmd = (struct scsi_cmnd *) context;
+ scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
if (fibptr == NULL)
@@ -2067,14 +2074,13 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
u32 timeout;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
- if (scsicmd->device->id >= dev->maximum_num_physicals ||
+ if (scmd_id(scsicmd) >= dev->maximum_num_physicals ||
scsicmd->device->lun > 7) {
scsicmd->result = DID_NO_CONNECT << 16;
scsicmd->scsi_done(scsicmd);
return 0;
}
- dev = (struct aac_dev *)scsicmd->device->host->hostdata;
switch(scsicmd->sc_data_direction){
case DMA_TO_DEVICE:
flag = SRB_DataOut;
@@ -2102,8 +2108,8 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext);
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
- srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scsicmd->device->channel));
- srbcmd->id = cpu_to_le32(scsicmd->device->id);
+ srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scmd_channel(scsicmd)));
+ srbcmd->id = cpu_to_le32(scmd_id(scsicmd));
srbcmd->lun = cpu_to_le32(scsicmd->device->lun);
srbcmd->flags = cpu_to_le32(flag);
timeout = scsicmd->timeout_per_command/HZ;
@@ -2160,7 +2166,8 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS){
+ if (status == -EINPROGRESS) {
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
return 0;
}
@@ -2191,8 +2198,6 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
scsicmd->sc_data_direction);
psg->count = cpu_to_le32(sg_count);
- byte_count = 0;
-
for (i = 0; i < sg_count; i++) {
psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
@@ -2248,18 +2253,17 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
scsicmd->sc_data_direction);
- psg->count = cpu_to_le32(sg_count);
-
- byte_count = 0;
for (i = 0; i < sg_count; i++) {
+ int count = sg_dma_len(sg);
addr = sg_dma_address(sg);
psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
- psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
- byte_count += sg_dma_len(sg);
+ psg->sg[i].count = cpu_to_le32(count);
+ byte_count += count;
sg++;
}
+ psg->count = cpu_to_le32(sg_count);
/* hba wants the size to be exact */
if(byte_count > scsicmd->request_bufflen){
u32 temp = le32_to_cpu(psg->sg[i-1].count) -
@@ -2274,16 +2278,15 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
}
}
else if(scsicmd->request_bufflen) {
- u64 addr;
- addr = pci_map_single(dev->pdev,
+ scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
scsicmd->request_buffer,
scsicmd->request_bufflen,
scsicmd->sc_data_direction);
+ addr = scsicmd->SCp.dma_handle;
psg->count = cpu_to_le32(1);
psg->sg[0].addr[0] = cpu_to_le32(addr & 0xffffffff);
psg->sg[0].addr[1] = cpu_to_le32(addr >> 32);
psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);
- scsicmd->SCp.dma_handle = addr;
byte_count = scsicmd->request_bufflen;
}
return byte_count;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 9ce7002bd07..f773b0dcfc9 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -10,6 +10,10 @@
* D E F I N E S
*----------------------------------------------------------------------------*/
+#ifndef AAC_DRIVER_BUILD
+# define AAC_DRIVER_BUILD 2409
+# define AAC_DRIVER_BRANCH "-mh1"
+#endif
#define MAXIMUM_NUM_CONTAINERS 32
#define AAC_NUM_MGT_FIB 8
@@ -25,7 +29,6 @@
* These macros convert from physical channels to virtual channels
*/
#define CONTAINER_CHANNEL (0)
-#define ID_LUN_TO_CONTAINER(id, lun) (id)
#define CONTAINER_TO_CHANNEL(cont) (CONTAINER_CHANNEL)
#define CONTAINER_TO_ID(cont) (cont)
#define CONTAINER_TO_LUN(cont) (0)
@@ -789,6 +792,7 @@ struct fsa_dev_info {
u64 size;
u32 type;
u32 config_waiting_on;
+ unsigned long config_waiting_stamp;
u16 queue_depth;
u8 config_needed;
u8 valid;
@@ -1771,6 +1775,11 @@ static inline u32 cap_to_cyls(sector_t capacity, u32 divisor)
}
struct scsi_cmnd;
+/* SCp.phase values */
+#define AAC_OWNER_MIDLEVEL 0x101
+#define AAC_OWNER_LOWLEVEL 0x102
+#define AAC_OWNER_ERROR_HANDLER 0x103
+#define AAC_OWNER_FIRMWARE 0x106
const char *aac_driverinfo(struct Scsi_Host *);
struct fib *aac_fib_alloc(struct aac_dev *dev);
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 47fefca7269..9f75144e524 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -38,6 +38,8 @@
#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
@@ -293,6 +295,16 @@ return_fib:
status = 0;
} else {
spin_unlock_irqrestore(&dev->fib_lock, flags);
+ /* If someone killed the AIF aacraid thread, restart it */
+ status = !dev->aif_thread;
+ if (status && dev->queues && dev->fsa_dev) {
+ /* Be paranoid, be very paranoid! */
+ kthread_stop(dev->thread);
+ ssleep(1);
+ dev->aif_thread = 0;
+ dev->thread = kthread_run(aac_command_thread, dev, dev->name);
+ ssleep(1);
+ }
if (f.wait) {
if(down_interruptible(&fibctx->wait_sem) < 0) {
status = -EINTR;
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index c7f80ec7abd..9f9f4aae23c 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -767,9 +767,9 @@ void aac_printf(struct aac_dev *dev, u32 val)
if (cp[length] != 0)
cp[length] = 0;
if (level == LOG_AAC_HIGH_ERROR)
- printk(KERN_WARNING "aacraid:%s", cp);
+ printk(KERN_WARNING "%s:%s", dev->name, cp);
else
- printk(KERN_INFO "aacraid:%s", cp);
+ printk(KERN_INFO "%s:%s", dev->name, cp);
}
memset(cp, 0, 256);
}
@@ -784,6 +784,7 @@ void aac_printf(struct aac_dev *dev, u32 val)
* dispatches it to the appropriate routine for handling.
*/
+#define AIF_SNIFF_TIMEOUT (30*HZ)
static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
{
struct hw_fib * hw_fib = fibptr->hw_fib;
@@ -837,6 +838,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
if (device) {
dev->fsa_dev[container].config_needed = CHANGE;
dev->fsa_dev[container].config_waiting_on = AifEnConfigChange;
+ dev->fsa_dev[container].config_waiting_stamp = jiffies;
scsi_device_put(device);
}
}
@@ -849,13 +851,15 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
if (container != (u32)-1) {
if (container >= dev->maximum_num_containers)
break;
- if (dev->fsa_dev[container].config_waiting_on ==
- le32_to_cpu(*(u32 *)aifcmd->data))
+ if ((dev->fsa_dev[container].config_waiting_on ==
+ le32_to_cpu(*(u32 *)aifcmd->data)) &&
+ time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
dev->fsa_dev[container].config_waiting_on = 0;
} else for (container = 0;
container < dev->maximum_num_containers; ++container) {
- if (dev->fsa_dev[container].config_waiting_on ==
- le32_to_cpu(*(u32 *)aifcmd->data))
+ if ((dev->fsa_dev[container].config_waiting_on ==
+ le32_to_cpu(*(u32 *)aifcmd->data)) &&
+ time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
dev->fsa_dev[container].config_waiting_on = 0;
}
break;
@@ -872,6 +876,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
dev->fsa_dev[container].config_needed = ADD;
dev->fsa_dev[container].config_waiting_on =
AifEnConfigChange;
+ dev->fsa_dev[container].config_waiting_stamp = jiffies;
break;
/*
@@ -884,6 +889,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
dev->fsa_dev[container].config_needed = DELETE;
dev->fsa_dev[container].config_waiting_on =
AifEnConfigChange;
+ dev->fsa_dev[container].config_waiting_stamp = jiffies;
break;
/*
@@ -894,11 +900,13 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
if (container >= dev->maximum_num_containers)
break;
- if (dev->fsa_dev[container].config_waiting_on)
+ if (dev->fsa_dev[container].config_waiting_on &&
+ time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
break;
dev->fsa_dev[container].config_needed = CHANGE;
dev->fsa_dev[container].config_waiting_on =
AifEnConfigChange;
+ dev->fsa_dev[container].config_waiting_stamp = jiffies;
break;
case AifEnConfigChange:
@@ -913,13 +921,15 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
if (container != (u32)-1) {
if (container >= dev->maximum_num_containers)
break;
- if (dev->fsa_dev[container].config_waiting_on ==
- le32_to_cpu(*(u32 *)aifcmd->data))
+ if ((dev->fsa_dev[container].config_waiting_on ==
+ le32_to_cpu(*(u32 *)aifcmd->data)) &&
+ time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
dev->fsa_dev[container].config_waiting_on = 0;
} else for (container = 0;
container < dev->maximum_num_containers; ++container) {
- if (dev->fsa_dev[container].config_waiting_on ==
- le32_to_cpu(*(u32 *)aifcmd->data))
+ if ((dev->fsa_dev[container].config_waiting_on ==
+ le32_to_cpu(*(u32 *)aifcmd->data)) &&
+ time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
dev->fsa_dev[container].config_waiting_on = 0;
}
break;
@@ -946,6 +956,8 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
dev->fsa_dev[container].config_waiting_on =
AifEnContainerChange;
dev->fsa_dev[container].config_needed = ADD;
+ dev->fsa_dev[container].config_waiting_stamp =
+ jiffies;
}
}
if ((((u32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero))
@@ -961,6 +973,8 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
dev->fsa_dev[container].config_waiting_on =
AifEnContainerChange;
dev->fsa_dev[container].config_needed = DELETE;
+ dev->fsa_dev[container].config_waiting_stamp =
+ jiffies;
}
}
break;
@@ -969,8 +983,9 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
device_config_needed = NOTHING;
for (container = 0; container < dev->maximum_num_containers;
++container) {
- if ((dev->fsa_dev[container].config_waiting_on == 0)
- && (dev->fsa_dev[container].config_needed != NOTHING)) {
+ if ((dev->fsa_dev[container].config_waiting_on == 0) &&
+ (dev->fsa_dev[container].config_needed != NOTHING) &&
+ time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT)) {
device_config_needed =
dev->fsa_dev[container].config_needed;
dev->fsa_dev[container].config_needed = NOTHING;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index c2596335549..6ef89c99dd1 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -27,12 +27,6 @@
* Abstract: Linux Driver entry module for Adaptec RAID Array Controller
*/
-#define AAC_DRIVER_VERSION "1.1-4"
-#ifndef AAC_DRIVER_BRANCH
-#define AAC_DRIVER_BRANCH ""
-#endif
-#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__
-#define AAC_DRIVERNAME "aacraid"
#include <linux/compat.h>
#include <linux/blkdev.h>
@@ -45,6 +39,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
#include <linux/syscalls.h>
#include <linux/delay.h>
#include <linux/smp_lock.h>
@@ -61,6 +56,13 @@
#include "aacraid.h"
+#define AAC_DRIVER_VERSION "1.1-5"
+#ifndef AAC_DRIVER_BRANCH
+#define AAC_DRIVER_BRANCH ""
+#endif
+#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__
+#define AAC_DRIVERNAME "aacraid"
+
#ifdef AAC_DRIVER_BUILD
#define _str(x) #x
#define str(x) _str(x)
@@ -72,7 +74,7 @@
MODULE_AUTHOR("Red Hat Inc and Adaptec");
MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, "
"Adaptec Advanced Raid Products, "
- "and HP NetRAID-4M SCSI driver");
+ "HP NetRAID-4M, IBM ServeRAID & ICP SCSI driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
@@ -242,6 +244,7 @@ static struct aac_driver_ident aac_drivers[] = {
static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
cmd->scsi_done = done;
+ cmd->SCp.phase = AAC_OWNER_LOWLEVEL;
return (aac_scsi_cmd(cmd) ? FAILED : 0);
}
@@ -470,7 +473,8 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
__shost_for_each_device(dev, host) {
spin_lock_irqsave(&dev->list_lock, flags);
list_for_each_entry(command, &dev->cmd_list, list) {
- if (command->serial_number) {
+ if ((command != cmd) &&
+ (command->SCp.phase == AAC_OWNER_FIRMWARE)) {
active++;
break;
}
@@ -568,12 +572,12 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
f = compat_alloc_user_space(sizeof(*f));
ret = 0;
- if (clear_user(f, sizeof(*f) != sizeof(*f)))
+ if (clear_user(f, sizeof(*f)) != sizeof(*f))
ret = -EFAULT;
if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32)))
ret = -EFAULT;
if (!ret)
- ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
+ ret = aac_do_ioctl(dev, cmd, f);
break;
}
@@ -686,6 +690,18 @@ static ssize_t aac_show_serial_number(struct class_device *class_dev,
return len;
}
+static ssize_t aac_show_max_channel(struct class_device *class_dev, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ class_to_shost(class_dev)->max_channel);
+}
+
+static ssize_t aac_show_max_id(struct class_device *class_dev, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ class_to_shost(class_dev)->max_id);
+}
+
static struct class_device_attribute aac_model = {
.attr = {
@@ -729,6 +745,20 @@ static struct class_device_attribute aac_serial_number = {
},
.show = aac_show_serial_number,
};
+static struct class_device_attribute aac_max_channel = {
+ .attr = {
+ .name = "max_channel",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_max_channel,
+};
+static struct class_device_attribute aac_max_id = {
+ .attr = {
+ .name = "max_id",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_max_id,
+};
static struct class_device_attribute *aac_attrs[] = {
&aac_model,
@@ -737,6 +767,8 @@ static struct class_device_attribute *aac_attrs[] = {
&aac_monitor_version,
&aac_bios_version,
&aac_serial_number,
+ &aac_max_channel,
+ &aac_max_id,
NULL
};
@@ -774,6 +806,7 @@ static struct scsi_host_template aac_driver_template = {
.cmd_per_lun = AAC_NUM_IO_FIB,
#endif
.use_clustering = ENABLE_CLUSTERING,
+ .emulated = 1,
};
@@ -797,18 +830,19 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
error = pci_enable_device(pdev);
if (error)
goto out;
+ error = -ENODEV;
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))
- goto out;
+ goto out_disable_pdev;
/*
* If the quirk31 bit is set, the adapter needs adapter
* to driver communication memory to be allocated below 2gig
*/
if (aac_drivers[index].quirks & AAC_QUIRK_31BIT)
- if (pci_set_dma_mask(pdev, 0x7FFFFFFFULL) ||
- pci_set_consistent_dma_mask(pdev, 0x7FFFFFFFULL))
- goto out;
+ if (pci_set_dma_mask(pdev, DMA_31BIT_MASK) ||
+ pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK))
+ goto out_disable_pdev;
pci_set_master(pdev);
@@ -903,9 +937,9 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
* physical channels are address by their actual physical number+1
*/
if (aac->nondasd_support == 1)
- shost->max_channel = aac->maximum_num_channels + 1;
+ shost->max_channel = aac->maximum_num_channels;
else
- shost->max_channel = 1;
+ shost->max_channel = 0;
aac_get_config_status(aac);
aac_get_containers(aac);
@@ -1019,7 +1053,8 @@ static int __init aac_init(void)
static void __exit aac_exit(void)
{
- unregister_chrdev(aac_cfg_major, "aac");
+ if (aac_cfg_major > -1)
+ unregister_chrdev(aac_cfg_major, "aac");
pci_unregister_driver(&aac_pci_driver);
}
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index e9b775d6bec..7a23e027eb7 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -183,7 +183,7 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
/*
* Yield the processor in case we are slow
*/
- schedule_timeout_uninterruptible(1);
+ msleep(1);
}
if (ok != 1) {
/*
@@ -343,7 +343,7 @@ static int aac_rkt_check_health(struct aac_dev *dev)
NULL, NULL, NULL, NULL, NULL);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
- if ((buffer[0] == '0') && (buffer[1] == 'x')) {
+ if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) {
ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10);
ret <<= 4;
ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10);
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 6998bc877dd..729b9eb268c 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -183,7 +183,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
/*
* Yield the processor in case we are slow
*/
- schedule_timeout_uninterruptible(1);
+ msleep(1);
}
if (ok != 1) {
/*
@@ -342,7 +342,7 @@ static int aac_rx_check_health(struct aac_dev *dev)
NULL, NULL, NULL, NULL, NULL);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
- if ((buffer[0] == '0') && (buffer[1] == 'x')) {
+ if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) {
ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10);
ret <<= 4;
ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10);
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 466f05cfbf0..a5345490820 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -189,7 +189,7 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command,
ok = 1;
break;
}
- schedule_timeout_uninterruptible(1);
+ msleep(1);
}
if (ok != 1)
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 28b93057b60..2a419634b25 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -2051,7 +2051,7 @@ STATIC ASC_DCNT AscGetMaxDmaCount(ushort);
#define ADV_VADDR_TO_U32 virt_to_bus
#define ADV_U32_TO_VADDR bus_to_virt
-#define AdvPortAddr ulong /* Virtual memory address size */
+#define AdvPortAddr void __iomem * /* Virtual memory address size */
/*
* Define Adv Library required memory access macros.
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index ffba65656a8..b4f8fb1d628 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -207,7 +207,6 @@ static struct scsi_host_template ahci_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = AHCI_MAX_SG,
@@ -293,6 +292,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
board_ahci }, /* JMicron JMB360 */
{ 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* JMicron JMB363 */
+ { PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ATI SB600 non-raid */
+ { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ATI SB600 raid */
{ } /* terminate list */
};
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index 6c2c395554f..5517da5855f 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -86,7 +86,7 @@ config AIC7XXX_DEBUG_MASK
default "0"
help
Bit mask of debug options that is only valid if the
- CONFIG_AIC7XXX_DEBUG_ENBLE option is enabled. The bits in this mask
+ CONFIG_AIC7XXX_DEBUG_ENABLE option is enabled. The bits in this mask
are defined in the drivers/scsi/aic7xxx/aic7xxx.h - search for the
variable ahc_debug in that file to find them.
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 1d11f7e7756..bb5166da435 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -372,7 +372,7 @@ typedef enum {
AHD_CURRENT_SENSING = 0x40000,
AHD_SCB_CONFIG_USED = 0x80000,/* No SEEPROM but SCB had info. */
AHD_HP_BOARD = 0x100000,
- AHD_RESET_POLL_ACTIVE = 0x200000,
+ AHD_BUS_RESET_ACTIVE = 0x200000,
AHD_UPDATE_PEND_CMDS = 0x400000,
AHD_RUNNING_QOUTFIFO = 0x800000,
AHD_HAD_FIRST_SEL = 0x1000000
@@ -589,7 +589,7 @@ typedef enum {
SCB_PACKETIZED = 0x00800,
SCB_EXPECT_PPR_BUSFREE = 0x01000,
SCB_PKT_SENSE = 0x02000,
- SCB_CMDPHASE_ABORT = 0x04000,
+ SCB_EXTERNAL_RESET = 0x04000,/* Device was reset externally */
SCB_ON_COL_LIST = 0x08000,
SCB_SILENT = 0x10000 /*
* Be quiet about transmission type
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 326a6222623..08771f6f685 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -207,7 +207,6 @@ static void ahd_add_scb_to_free_list(struct ahd_softc *ahd,
static u_int ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
u_int prev, u_int next, u_int tid);
static void ahd_reset_current_bus(struct ahd_softc *ahd);
-static ahd_callback_t ahd_reset_poll;
static ahd_callback_t ahd_stat_timer;
#ifdef AHD_DUMP_SEQ
static void ahd_dumpseq(struct ahd_softc *ahd);
@@ -1054,12 +1053,10 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
* If a target takes us into the command phase
* assume that it has been externally reset and
* has thus lost our previous packetized negotiation
- * agreement. Since we have not sent an identify
- * message and may not have fully qualified the
- * connection, we change our command to TUR, assert
- * ATN and ABORT the task when we go to message in
- * phase. The OSM will see the REQUEUE_REQUEST
- * status and retry the command.
+ * agreement.
+ * Revert to async/narrow transfers until we
+ * can renegotiate with the device and notify
+ * the OSM about the reset.
*/
scbid = ahd_get_scbptr(ahd);
scb = ahd_lookup_scb(ahd, scbid);
@@ -1086,31 +1083,15 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_set_syncrate(ahd, &devinfo, /*period*/0,
/*offset*/0, /*ppr_options*/0,
AHD_TRANS_ACTIVE, /*paused*/TRUE);
- ahd_outb(ahd, SCB_CDB_STORE, 0);
- ahd_outb(ahd, SCB_CDB_STORE+1, 0);
- ahd_outb(ahd, SCB_CDB_STORE+2, 0);
- ahd_outb(ahd, SCB_CDB_STORE+3, 0);
- ahd_outb(ahd, SCB_CDB_STORE+4, 0);
- ahd_outb(ahd, SCB_CDB_STORE+5, 0);
- ahd_outb(ahd, SCB_CDB_LEN, 6);
- scb->hscb->control &= ~(TAG_ENB|SCB_TAG_TYPE);
- scb->hscb->control |= MK_MESSAGE;
- ahd_outb(ahd, SCB_CONTROL, scb->hscb->control);
- ahd_outb(ahd, MSG_OUT, HOST_MSG);
- ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);
- /*
- * The lun is 0, regardless of the SCB's lun
- * as we have not sent an identify message.
- */
- ahd_outb(ahd, SAVED_LUN, 0);
- ahd_outb(ahd, SEQ_FLAGS, 0);
- ahd_assert_atn(ahd);
- scb->flags &= ~SCB_PACKETIZED;
- scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;
+ scb->flags |= SCB_EXTERNAL_RESET;
ahd_freeze_devq(ahd, scb);
ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
ahd_freeze_scb(scb);
+ /* Notify XPT */
+ ahd_send_async(ahd, devinfo.channel, devinfo.target,
+ CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
+
/*
* Allow the sequencer to continue with
* non-pack processing.
@@ -1534,6 +1515,18 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
lqistat1 = ahd_inb(ahd, LQISTAT1);
lqostat0 = ahd_inb(ahd, LQOSTAT0);
busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;
+
+ /*
+ * Ignore external resets after a bus reset.
+ */
+ if (((status & SCSIRSTI) != 0) && (ahd->flags & AHD_BUS_RESET_ACTIVE))
+ return;
+
+ /*
+ * Clear bus reset flag
+ */
+ ahd->flags &= ~AHD_BUS_RESET_ACTIVE;
+
if ((status0 & (SELDI|SELDO)) != 0) {
u_int simode0;
@@ -2207,22 +2200,6 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
if (sent_msg == MSG_ABORT_TAG)
tag = SCB_GET_TAG(scb);
- if ((scb->flags & SCB_CMDPHASE_ABORT) != 0) {
- /*
- * This abort is in response to an
- * unexpected switch to command phase
- * for a packetized connection. Since
- * the identify message was never sent,
- * "saved lun" is 0. We really want to
- * abort only the SCB that encountered
- * this error, which could have a different
- * lun. The SCB will be retried so the OS
- * will see the UA after renegotiating to
- * packetized.
- */
- tag = SCB_GET_TAG(scb);
- saved_lun = scb->hscb->lun;
- }
found = ahd_abort_scbs(ahd, target, 'A', saved_lun,
tag, ROLE_INITIATOR,
CAM_REQ_ABORTED);
@@ -7847,6 +7824,17 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
int found;
u_int fifo;
u_int next_fifo;
+ uint8_t scsiseq;
+
+ /*
+ * Check if the last bus reset is cleared
+ */
+ if (ahd->flags & AHD_BUS_RESET_ACTIVE) {
+ printf("%s: bus reset still active\n",
+ ahd_name(ahd));
+ return 0;
+ }
+ ahd->flags |= AHD_BUS_RESET_ACTIVE;
ahd->pending_device = NULL;
@@ -7860,6 +7848,12 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
/* Make sure the sequencer is in a safe location. */
ahd_clear_critical_section(ahd);
+ /*
+ * Run our command complete fifos to ensure that we perform
+ * completion processing on any commands that 'completed'
+ * before the reset occurred.
+ */
+ ahd_run_qoutfifo(ahd);
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0) {
ahd_run_tqinfifo(ahd, /*paused*/TRUE);
@@ -7924,30 +7918,14 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
ahd_clear_fifo(ahd, 1);
/*
- * Revert to async/narrow transfers until we renegotiate.
+ * Reenable selections
*/
- max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
- for (target = 0; target <= max_scsiid; target++) {
-
- if (ahd->enabled_targets[target] == NULL)
- continue;
- for (initiator = 0; initiator <= max_scsiid; initiator++) {
- struct ahd_devinfo devinfo;
-
- ahd_compile_devinfo(&devinfo, target, initiator,
- CAM_LUN_WILDCARD,
- 'A', ROLE_UNKNOWN);
- ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
- AHD_TRANS_CUR, /*paused*/TRUE);
- ahd_set_syncrate(ahd, &devinfo, /*period*/0,
- /*offset*/0, /*ppr_options*/0,
- AHD_TRANS_CUR, /*paused*/TRUE);
- }
- }
+ ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST);
+ scsiseq = ahd_inb(ahd, SCSISEQ_TEMPLATE);
+ ahd_outb(ahd, SCSISEQ1, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP));
-#ifdef AHD_TARGET_MODE
max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
-
+#ifdef AHD_TARGET_MODE
/*
* Send an immediate notify ccb to all target more peripheral
* drivers affected by this action.
@@ -7975,51 +7953,31 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
/* Notify the XPT that a bus reset occurred */
ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD, AC_BUS_RESET, NULL);
- ahd_restart(ahd);
+
/*
- * Freeze the SIMQ until our poller can determine that
- * the bus reset has really gone away. We set the initial
- * timer to 0 to have the check performed as soon as possible
- * from the timer context.
+ * Revert to async/narrow transfers until we renegotiate.
*/
- if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) {
- ahd->flags |= AHD_RESET_POLL_ACTIVE;
- ahd_freeze_simq(ahd);
- ahd_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd);
- }
- return (found);
-}
+ for (target = 0; target <= max_scsiid; target++) {
+ if (ahd->enabled_targets[target] == NULL)
+ continue;
+ for (initiator = 0; initiator <= max_scsiid; initiator++) {
+ struct ahd_devinfo devinfo;
-#define AHD_RESET_POLL_US 1000
-static void
-ahd_reset_poll(void *arg)
-{
- struct ahd_softc *ahd = arg;
- u_int scsiseq1;
- u_long s;
-
- ahd_lock(ahd, &s);
- ahd_pause(ahd);
- ahd_update_modes(ahd);
- ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
- ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
- if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) {
- ahd_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US,
- ahd_reset_poll, ahd);
- ahd_unpause(ahd);
- ahd_unlock(ahd, &s);
- return;
+ ahd_compile_devinfo(&devinfo, target, initiator,
+ CAM_LUN_WILDCARD,
+ 'A', ROLE_UNKNOWN);
+ ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
+ AHD_TRANS_CUR, /*paused*/TRUE);
+ ahd_set_syncrate(ahd, &devinfo, /*period*/0,
+ /*offset*/0, /*ppr_options*/0,
+ AHD_TRANS_CUR, /*paused*/TRUE);
+ }
}
- /* Reset is now low. Complete chip reinitialization. */
- ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST);
- scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
- ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP));
- ahd_unpause(ahd);
- ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
- ahd_unlock(ahd, &s);
- ahd_release_simq(ahd);
+ ahd_restart(ahd);
+
+ return (found);
}
/**************************** Statistics Processing ***************************/
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index bcced0a417e..66e4a47bb9e 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -782,6 +782,7 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd)
{
struct ahd_softc *ahd;
int found;
+ unsigned long flags;
ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
#ifdef AHD_DEBUG
@@ -789,8 +790,11 @@ ahd_linux_bus_reset(struct scsi_cmnd *cmd)
printf("%s: Bus reset called for cmd %p\n",
ahd_name(ahd), cmd);
#endif
+ ahd_lock(ahd, &flags);
+
found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A',
/*initiate reset*/TRUE);
+ ahd_unlock(ahd, &flags);
if (bootverbose)
printf("%s: SCSI bus reset delivered. "
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index cb30d9c1153..0c9c2f400bf 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -219,6 +219,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahc->flags |= AHC_39BIT_ADDRESSING;
} else {
if (dma_set_mask(dev, DMA_32BIT_MASK)) {
+ ahc_free(ahc);
printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n");
return (-ENODEV);
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index 5f586140e05..3adecef2178 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -2036,12 +2036,12 @@ ahc_pci_resume(struct ahc_softc *ahc)
* that the OS doesn't know about and rely on our chip
* reset handler to handle the rest.
*/
- ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4,
- ahc->bus_softc.pci_softc.devconfig);
- ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1,
- ahc->bus_softc.pci_softc.command);
- ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1,
- ahc->bus_softc.pci_softc.csize_lattime);
+ ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
+ ahc->bus_softc.pci_softc.devconfig, /*bytes*/4);
+ ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
+ ahc->bus_softc.pci_softc.command, /*bytes*/1);
+ ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
+ ahc->bus_softc.pci_softc.csize_lattime, /*bytes*/1);
if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) {
struct seeprom_descriptor sd;
u_int sxfrctl1;
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 2d5be84d8bd..6dc88149f9f 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -209,7 +209,6 @@ static struct scsi_host_template piix_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
@@ -301,7 +300,7 @@ static struct piix_map_db ich6_map_db = {
.mask = 0x3,
.map = {
/* PM PS SM SS MAP */
- { P0, P1, P2, P3 }, /* 00b */
+ { P0, P2, P1, P3 }, /* 00b */
{ IDE, IDE, P1, P3 }, /* 01b */
{ P0, P2, IDE, IDE }, /* 10b */
{ RV, RV, RV, RV },
@@ -312,7 +311,7 @@ static struct piix_map_db ich6m_map_db = {
.mask = 0x3,
.map = {
/* PM PS SM SS MAP */
- { P0, P1, P2, P3 }, /* 00b */
+ { P0, P2, RV, RV }, /* 00b */
{ RV, RV, RV, RV },
{ P0, P2, IDE, IDE }, /* 10b */
{ RV, RV, RV, RV },
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 5227a779c05..a198d86667e 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -28,6 +28,7 @@
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -2631,7 +2632,7 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pci_enable_device(pdev))
return -EIO;
- if (!pci_set_dma_mask(pdev, 0xFFFFFFFFUL)) {
+ if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
} else {
printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 6e6b293dcb2..b1b704a42ef 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -57,6 +57,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
#include <linux/reboot.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
+#include <linux/dma-mapping.h>
#include <linux/timer.h>
#include <linux/string.h>
@@ -906,8 +907,8 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
}
pci_set_master(pDev);
- if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) &&
- pci_set_dma_mask(pDev, 0xffffffffULL))
+ if (pci_set_dma_mask(pDev, DMA_64BIT_MASK) &&
+ pci_set_dma_mask(pDev, DMA_32BIT_MASK))
return -EINVAL;
base_addr0_phys = pci_resource_start(pDev,0);
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index b3f9de8f759..059eeee4b55 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -490,6 +490,7 @@
#include <linux/init.h>
#include <linux/ctype.h>
#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
#include <asm/byteorder.h>
#include <asm/dma.h>
#include <asm/io.h>
@@ -1426,7 +1427,7 @@ static int port_detect(unsigned long port_base, unsigned int j,
if (ha->pdev) {
pci_set_master(ha->pdev);
- if (pci_set_dma_mask(ha->pdev, 0xffffffff))
+ if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK))
printk("%s: warning, pci_set_dma_mask failed.\n",
ha->board_name);
}
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 62e3cda859a..d5740bbdef3 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -388,6 +388,7 @@
#include <linux/proc_fs.h>
#include <linux/time.h>
#include <linux/timer.h>
+#include <linux/dma-mapping.h>
#ifdef GDTH_RTC
#include <linux/mc146818rtc.h>
#endif
@@ -671,7 +672,7 @@ static struct file_operations gdth_fops = {
static struct notifier_block gdth_notifier = {
gdth_halt, NULL, 0
};
-
+static int notifier_disabled = 0;
static void gdth_delay(int milliseconds)
{
@@ -4527,15 +4528,15 @@ static int __init gdth_detect(struct scsi_host_template *shtp)
if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)||
/* 64-bit DMA only supported from FW >= x.43 */
(!ha->dma64_support)) {
- if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) {
+ if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum);
err = TRUE;
}
} else {
shp->max_cmd_len = 16;
- if (!pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffffffffffffULL)) {
+ if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) {
printk("GDT-PCI %d: 64-bit DMA enabled\n", hanum);
- } else if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) {
+ } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum);
err = TRUE;
}
@@ -4595,13 +4596,13 @@ static int __init gdth_detect(struct scsi_host_template *shtp)
add_timer(&gdth_timer);
#endif
major = register_chrdev(0,"gdth",&gdth_fops);
+ notifier_disabled = 0;
register_reboot_notifier(&gdth_notifier);
}
gdth_polling = FALSE;
return gdth_ctr_vcount;
}
-
static int gdth_release(struct Scsi_Host *shp)
{
int hanum;
@@ -5632,10 +5633,14 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
char cmnd[MAX_COMMAND_SIZE];
#endif
+ if (notifier_disabled)
+ return NOTIFY_OK;
+
TRACE2(("gdth_halt() event %d\n",(int)event));
if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
return NOTIFY_DONE;
+ notifier_disabled = 1;
printk("GDT-HA: Flushing all host drives .. ");
for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
gdth_flush(hanum);
@@ -5679,7 +5684,6 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
#ifdef GDTH_STATISTICS
del_timer(&gdth_timer);
#endif
- unregister_reboot_notifier(&gdth_notifier);
return NOTIFY_OK;
}
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index ef57f253031..dfcb96f3e60 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -294,18 +294,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
if (sht->unchecked_isa_dma && privsize)
gfp_mask |= __GFP_DMA;
- /* Check to see if this host has any error handling facilities */
- if (!sht->eh_strategy_handler && !sht->eh_abort_handler &&
- !sht->eh_device_reset_handler && !sht->eh_bus_reset_handler &&
- !sht->eh_host_reset_handler) {
- printk(KERN_ERR "ERROR: SCSI host `%s' has no error handling\n"
- "ERROR: This is not a safe way to run your "
- "SCSI host\n"
- "ERROR: The error handling must be added to "
- "this driver\n", sht->proc_name);
- dump_stack();
- }
-
shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask);
if (!shost)
return NULL;
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index 3a8462e8d06..24eb59e143a 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -2488,7 +2488,7 @@ static int option_setup(char *str)
}
ints[0] = i - 1;
internal_ibmmca_scsi_setup(cur, ints);
- return 0;
+ return 1;
}
__setup("ibmmcascsi=", option_setup);
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index eaefeddb2b4..2e9be83a697 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -168,7 +168,7 @@ static void release_event_pool(struct event_pool *pool,
++in_use;
if (pool->events[i].ext_list) {
dma_free_coherent(hostdata->dev,
- SG_ALL * sizeof(struct memory_descriptor),
+ SG_ALL * sizeof(struct srp_direct_buf),
pool->events[i].ext_list,
pool->events[i].ext_list_token);
}
@@ -284,40 +284,37 @@ static void set_srp_direction(struct scsi_cmnd *cmd,
struct srp_cmd *srp_cmd,
int numbuf)
{
+ u8 fmt;
+
if (numbuf == 0)
return;
- if (numbuf == 1) {
+ if (numbuf == 1)
+ fmt = SRP_DATA_DESC_DIRECT;
+ else {
+ fmt = SRP_DATA_DESC_INDIRECT;
+ numbuf = min(numbuf, MAX_INDIRECT_BUFS);
+
if (cmd->sc_data_direction == DMA_TO_DEVICE)
- srp_cmd->data_out_format = SRP_DIRECT_BUFFER;
- else
- srp_cmd->data_in_format = SRP_DIRECT_BUFFER;
- } else {
- if (cmd->sc_data_direction == DMA_TO_DEVICE) {
- srp_cmd->data_out_format = SRP_INDIRECT_BUFFER;
- srp_cmd->data_out_count =
- numbuf < MAX_INDIRECT_BUFS ?
- numbuf: MAX_INDIRECT_BUFS;
- } else {
- srp_cmd->data_in_format = SRP_INDIRECT_BUFFER;
- srp_cmd->data_in_count =
- numbuf < MAX_INDIRECT_BUFS ?
- numbuf: MAX_INDIRECT_BUFS;
- }
+ srp_cmd->data_out_desc_cnt = numbuf;
+ else
+ srp_cmd->data_in_desc_cnt = numbuf;
}
+
+ if (cmd->sc_data_direction == DMA_TO_DEVICE)
+ srp_cmd->buf_fmt = fmt << 4;
+ else
+ srp_cmd->buf_fmt = fmt;
}
-static void unmap_sg_list(int num_entries,
+static void unmap_sg_list(int num_entries,
struct device *dev,
- struct memory_descriptor *md)
-{
+ struct srp_direct_buf *md)
+{
int i;
- for (i = 0; i < num_entries; ++i) {
- dma_unmap_single(dev,
- md[i].virtual_address,
- md[i].length, DMA_BIDIRECTIONAL);
- }
+ for (i = 0; i < num_entries; ++i)
+ dma_unmap_single(dev, md[i].va, md[i].len, DMA_BIDIRECTIONAL);
}
/**
@@ -330,23 +327,26 @@ static void unmap_cmd_data(struct srp_cmd *cmd,
struct srp_event_struct *evt_struct,
struct device *dev)
{
- if ((cmd->data_out_format == SRP_NO_BUFFER) &&
- (cmd->data_in_format == SRP_NO_BUFFER))
+ u8 out_fmt, in_fmt;
+
+ out_fmt = cmd->buf_fmt >> 4;
+ in_fmt = cmd->buf_fmt & ((1U << 4) - 1);
+
+ if (out_fmt == SRP_NO_DATA_DESC && in_fmt == SRP_NO_DATA_DESC)
return;
- else if ((cmd->data_out_format == SRP_DIRECT_BUFFER) ||
- (cmd->data_in_format == SRP_DIRECT_BUFFER)) {
- struct memory_descriptor *data =
- (struct memory_descriptor *)cmd->additional_data;
- dma_unmap_single(dev, data->virtual_address, data->length,
- DMA_BIDIRECTIONAL);
+ else if (out_fmt == SRP_DATA_DESC_DIRECT ||
+ in_fmt == SRP_DATA_DESC_DIRECT) {
+ struct srp_direct_buf *data =
+ (struct srp_direct_buf *) cmd->add_data;
+ dma_unmap_single(dev, data->va, data->len, DMA_BIDIRECTIONAL);
} else {
- struct indirect_descriptor *indirect =
- (struct indirect_descriptor *)cmd->additional_data;
- int num_mapped = indirect->head.length /
- sizeof(indirect->list[0]);
+ struct srp_indirect_buf *indirect =
+ (struct srp_indirect_buf *) cmd->add_data;
+ int num_mapped = indirect->table_desc.len /
+ sizeof(struct srp_direct_buf);
if (num_mapped <= MAX_INDIRECT_BUFS) {
- unmap_sg_list(num_mapped, dev, &indirect->list[0]);
+ unmap_sg_list(num_mapped, dev, &indirect->desc_list[0]);
return;
}
@@ -356,17 +356,17 @@ static void unmap_cmd_data(struct srp_cmd *cmd,
static int map_sg_list(int num_entries,
struct scatterlist *sg,
- struct memory_descriptor *md)
+ struct srp_direct_buf *md)
{
int i;
u64 total_length = 0;
for (i = 0; i < num_entries; ++i) {
- struct memory_descriptor *descr = md + i;
+ struct srp_direct_buf *descr = md + i;
struct scatterlist *sg_entry = &sg[i];
- descr->virtual_address = sg_dma_address(sg_entry);
- descr->length = sg_dma_len(sg_entry);
- descr->memory_handle = 0;
+ descr->va = sg_dma_address(sg_entry);
+ descr->len = sg_dma_len(sg_entry);
+ descr->key = 0;
total_length += sg_dma_len(sg_entry);
}
return total_length;
@@ -389,10 +389,10 @@ static int map_sg_data(struct scsi_cmnd *cmd,
int sg_mapped;
u64 total_length = 0;
struct scatterlist *sg = cmd->request_buffer;
- struct memory_descriptor *data =
- (struct memory_descriptor *)srp_cmd->additional_data;
- struct indirect_descriptor *indirect =
- (struct indirect_descriptor *)data;
+ struct srp_direct_buf *data =
+ (struct srp_direct_buf *) srp_cmd->add_data;
+ struct srp_indirect_buf *indirect =
+ (struct srp_indirect_buf *) data;
sg_mapped = dma_map_sg(dev, sg, cmd->use_sg, DMA_BIDIRECTIONAL);
@@ -403,9 +403,9 @@ static int map_sg_data(struct scsi_cmnd *cmd,
/* special case; we can use a single direct descriptor */
if (sg_mapped == 1) {
- data->virtual_address = sg_dma_address(&sg[0]);
- data->length = sg_dma_len(&sg[0]);
- data->memory_handle = 0;
+ data->va = sg_dma_address(&sg[0]);
+ data->len = sg_dma_len(&sg[0]);
+ data->key = 0;
return 1;
}
@@ -416,25 +416,26 @@ static int map_sg_data(struct scsi_cmnd *cmd,
return 0;
}
- indirect->head.virtual_address = 0;
- indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
- indirect->head.memory_handle = 0;
+ indirect->table_desc.va = 0;
+ indirect->table_desc.len = sg_mapped * sizeof(struct srp_direct_buf);
+ indirect->table_desc.key = 0;
if (sg_mapped <= MAX_INDIRECT_BUFS) {
- total_length = map_sg_list(sg_mapped, sg, &indirect->list[0]);
- indirect->total_length = total_length;
+ total_length = map_sg_list(sg_mapped, sg,
+ &indirect->desc_list[0]);
+ indirect->len = total_length;
return 1;
}
/* get indirect table */
if (!evt_struct->ext_list) {
- evt_struct->ext_list =(struct memory_descriptor*)
+ evt_struct->ext_list = (struct srp_direct_buf *)
dma_alloc_coherent(dev,
- SG_ALL * sizeof(struct memory_descriptor),
- &evt_struct->ext_list_token, 0);
+ SG_ALL * sizeof(struct srp_direct_buf),
+ &evt_struct->ext_list_token, 0);
if (!evt_struct->ext_list) {
- printk(KERN_ERR
- "ibmvscsi: Can't allocate memory for indirect table\n");
+ printk(KERN_ERR
+ "ibmvscsi: Can't allocate memory for indirect table\n");
return 0;
}
@@ -442,11 +443,11 @@ static int map_sg_data(struct scsi_cmnd *cmd,
total_length = map_sg_list(sg_mapped, sg, evt_struct->ext_list);
- indirect->total_length = total_length;
- indirect->head.virtual_address = evt_struct->ext_list_token;
- indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
- memcpy(indirect->list, evt_struct->ext_list,
- MAX_INDIRECT_BUFS * sizeof(struct memory_descriptor));
+ indirect->len = total_length;
+ indirect->table_desc.va = evt_struct->ext_list_token;
+ indirect->table_desc.len = sg_mapped * sizeof(indirect->desc_list[0]);
+ memcpy(indirect->desc_list, evt_struct->ext_list,
+ MAX_INDIRECT_BUFS * sizeof(struct srp_direct_buf));
return 1;
}
@@ -463,20 +464,20 @@ static int map_sg_data(struct scsi_cmnd *cmd,
static int map_single_data(struct scsi_cmnd *cmd,
struct srp_cmd *srp_cmd, struct device *dev)
{
- struct memory_descriptor *data =
- (struct memory_descriptor *)srp_cmd->additional_data;
+ struct srp_direct_buf *data =
+ (struct srp_direct_buf *) srp_cmd->add_data;
- data->virtual_address =
+ data->va =
dma_map_single(dev, cmd->request_buffer,
cmd->request_bufflen,
DMA_BIDIRECTIONAL);
- if (dma_mapping_error(data->virtual_address)) {
+ if (dma_mapping_error(data->va)) {
printk(KERN_ERR
"ibmvscsi: Unable to map request_buffer for command!\n");
return 0;
}
- data->length = cmd->request_bufflen;
- data->memory_handle = 0;
+ data->len = cmd->request_bufflen;
+ data->key = 0;
set_srp_direction(cmd, srp_cmd, 1);
@@ -548,7 +549,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
/* Copy the IU into the transfer area */
*evt_struct->xfer_iu = evt_struct->iu;
- evt_struct->xfer_iu->srp.generic.tag = (u64)evt_struct;
+ evt_struct->xfer_iu->srp.rsp.tag = (u64)evt_struct;
/* Add this to the sent list. We need to do this
* before we actually send
@@ -586,27 +587,27 @@ static void handle_cmd_rsp(struct srp_event_struct *evt_struct)
struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp;
struct scsi_cmnd *cmnd = evt_struct->cmnd;
- if (unlikely(rsp->type != SRP_RSP_TYPE)) {
+ if (unlikely(rsp->opcode != SRP_RSP)) {
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: bad SRP RSP type %d\n",
- rsp->type);
+ rsp->opcode);
}
if (cmnd) {
cmnd->result = rsp->status;
if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION)
memcpy(cmnd->sense_buffer,
- rsp->sense_and_response_data,
- rsp->sense_data_list_length);
+ rsp->data,
+ rsp->sense_data_len);
unmap_cmd_data(&evt_struct->iu.srp.cmd,
evt_struct,
evt_struct->hostdata->dev);
- if (rsp->doover)
- cmnd->resid = rsp->data_out_residual_count;
- else if (rsp->diover)
- cmnd->resid = rsp->data_in_residual_count;
+ if (rsp->flags & SRP_RSP_FLAG_DOOVER)
+ cmnd->resid = rsp->data_out_res_cnt;
+ else if (rsp->flags & SRP_RSP_FLAG_DIOVER)
+ cmnd->resid = rsp->data_in_res_cnt;
}
if (evt_struct->cmnd_done)
@@ -633,10 +634,11 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
{
struct srp_cmd *srp_cmd;
struct srp_event_struct *evt_struct;
- struct indirect_descriptor *indirect;
+ struct srp_indirect_buf *indirect;
struct ibmvscsi_host_data *hostdata =
(struct ibmvscsi_host_data *)&cmnd->device->host->hostdata;
u16 lun = lun_from_dev(cmnd->device);
+ u8 out_fmt, in_fmt;
evt_struct = get_event_struct(&hostdata->pool);
if (!evt_struct)
@@ -644,8 +646,8 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
/* Set up the actual SRP IU */
srp_cmd = &evt_struct->iu.srp.cmd;
- memset(srp_cmd, 0x00, sizeof(*srp_cmd));
- srp_cmd->type = SRP_CMD_TYPE;
+ memset(srp_cmd, 0x00, SRP_MAX_IU_LEN);
+ srp_cmd->opcode = SRP_CMD;
memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
srp_cmd->lun = ((u64) lun) << 48;
@@ -664,13 +666,15 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
evt_struct->cmnd_done = done;
/* Fix up dma address of the buffer itself */
- indirect = (struct indirect_descriptor *)srp_cmd->additional_data;
- if (((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) ||
- (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) &&
- (indirect->head.virtual_address == 0)) {
- indirect->head.virtual_address = evt_struct->crq.IU_data_ptr +
- offsetof(struct srp_cmd, additional_data) +
- offsetof(struct indirect_descriptor, list);
+ indirect = (struct srp_indirect_buf *) srp_cmd->add_data;
+ out_fmt = srp_cmd->buf_fmt >> 4;
+ in_fmt = srp_cmd->buf_fmt & ((1U << 4) - 1);
+ if ((in_fmt == SRP_DATA_DESC_INDIRECT ||
+ out_fmt == SRP_DATA_DESC_INDIRECT) &&
+ indirect->table_desc.va == 0) {
+ indirect->table_desc.va = evt_struct->crq.IU_data_ptr +
+ offsetof(struct srp_cmd, add_data) +
+ offsetof(struct srp_indirect_buf, desc_list);
}
return ibmvscsi_send_srp_event(evt_struct, hostdata);
@@ -735,7 +739,8 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
{
struct viosrp_adapter_info *req;
struct srp_event_struct *evt_struct;
-
+ dma_addr_t addr;
+
evt_struct = get_event_struct(&hostdata->pool);
if (!evt_struct) {
printk(KERN_ERR "ibmvscsi: couldn't allocate an event "
@@ -753,10 +758,10 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
req->common.type = VIOSRP_ADAPTER_INFO_TYPE;
req->common.length = sizeof(hostdata->madapter_info);
- req->buffer = dma_map_single(hostdata->dev,
- &hostdata->madapter_info,
- sizeof(hostdata->madapter_info),
- DMA_BIDIRECTIONAL);
+ req->buffer = addr = dma_map_single(hostdata->dev,
+ &hostdata->madapter_info,
+ sizeof(hostdata->madapter_info),
+ DMA_BIDIRECTIONAL);
if (dma_mapping_error(req->buffer)) {
printk(KERN_ERR
@@ -766,8 +771,13 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
return;
}
- if (ibmvscsi_send_srp_event(evt_struct, hostdata))
+ if (ibmvscsi_send_srp_event(evt_struct, hostdata)) {
printk(KERN_ERR "ibmvscsi: couldn't send ADAPTER_INFO_REQ!\n");
+ dma_unmap_single(hostdata->dev,
+ addr,
+ sizeof(hostdata->madapter_info),
+ DMA_BIDIRECTIONAL);
+ }
};
/**
@@ -780,10 +790,10 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
static void login_rsp(struct srp_event_struct *evt_struct)
{
struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;
- switch (evt_struct->xfer_iu->srp.generic.type) {
- case SRP_LOGIN_RSP_TYPE: /* it worked! */
+ switch (evt_struct->xfer_iu->srp.login_rsp.opcode) {
+ case SRP_LOGIN_RSP: /* it worked! */
break;
- case SRP_LOGIN_REJ_TYPE: /* refused! */
+ case SRP_LOGIN_REJ: /* refused! */
printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REJ reason %u\n",
evt_struct->xfer_iu->srp.login_rej.reason);
/* Login failed. */
@@ -792,7 +802,7 @@ static void login_rsp(struct srp_event_struct *evt_struct)
default:
printk(KERN_ERR
"ibmvscsi: Invalid login response typecode 0x%02x!\n",
- evt_struct->xfer_iu->srp.generic.type);
+ evt_struct->xfer_iu->srp.login_rsp.opcode);
/* Login failed. */
atomic_set(&hostdata->request_limit, -1);
return;
@@ -800,17 +810,17 @@ static void login_rsp(struct srp_event_struct *evt_struct)
printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
- if (evt_struct->xfer_iu->srp.login_rsp.request_limit_delta >
+ if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta >
(max_requests - 2))
- evt_struct->xfer_iu->srp.login_rsp.request_limit_delta =
+ evt_struct->xfer_iu->srp.login_rsp.req_lim_delta =
max_requests - 2;
/* Now we know what the real request-limit is */
atomic_set(&hostdata->request_limit,
- evt_struct->xfer_iu->srp.login_rsp.request_limit_delta);
+ evt_struct->xfer_iu->srp.login_rsp.req_lim_delta);
hostdata->host->can_queue =
- evt_struct->xfer_iu->srp.login_rsp.request_limit_delta - 2;
+ evt_struct->xfer_iu->srp.login_rsp.req_lim_delta - 2;
if (hostdata->host->can_queue < 1) {
printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n");
@@ -849,18 +859,19 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
login = &evt_struct->iu.srp.login_req;
memset(login, 0x00, sizeof(struct srp_login_req));
- login->type = SRP_LOGIN_REQ_TYPE;
- login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu);
- login->required_buffer_formats = 0x0006;
+ login->opcode = SRP_LOGIN_REQ;
+ login->req_it_iu_len = sizeof(union srp_iu);
+ login->req_buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT;
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
/* Start out with a request limit of 1, since this is negotiated in
* the login request we are just sending
*/
atomic_set(&hostdata->request_limit, 1);
- spin_lock_irqsave(hostdata->host->host_lock, flags);
rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ printk("ibmvscsic: sent SRP login\n");
return rc;
};
@@ -928,13 +939,13 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
/* Set up an abort SRP command */
memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
- tsk_mgmt->type = SRP_TSK_MGMT_TYPE;
+ tsk_mgmt->opcode = SRP_TSK_MGMT;
tsk_mgmt->lun = ((u64) lun) << 48;
- tsk_mgmt->task_mgmt_flags = 0x01; /* ABORT TASK */
- tsk_mgmt->managed_task_tag = (u64) found_evt;
+ tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK;
+ tsk_mgmt->task_tag = (u64) found_evt;
printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
- tsk_mgmt->lun, tsk_mgmt->managed_task_tag);
+ tsk_mgmt->lun, tsk_mgmt->task_tag);
evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
@@ -948,25 +959,25 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
wait_for_completion(&evt->comp);
/* make sure we got a good response */
- if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
+ if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) {
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: abort bad SRP RSP type %d\n",
- srp_rsp.srp.generic.type);
+ srp_rsp.srp.rsp.opcode);
return FAILED;
}
- if (srp_rsp.srp.rsp.rspvalid)
- rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
+ if (srp_rsp.srp.rsp.flags & SRP_RSP_FLAG_RSPVALID)
+ rsp_rc = *((int *)srp_rsp.srp.rsp.data);
else
rsp_rc = srp_rsp.srp.rsp.status;
if (rsp_rc) {
if (printk_ratelimit())
printk(KERN_WARNING
- "ibmvscsi: abort code %d for task tag 0x%lx\n",
+ "ibmvscsi: abort code %d for task tag 0x%lx\n",
rsp_rc,
- tsk_mgmt->managed_task_tag);
+ tsk_mgmt->task_tag);
return FAILED;
}
@@ -987,13 +998,13 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
printk(KERN_INFO
"ibmvscsi: aborted task tag 0x%lx completed\n",
- tsk_mgmt->managed_task_tag);
+ tsk_mgmt->task_tag);
return SUCCESS;
}
printk(KERN_INFO
"ibmvscsi: successfully aborted task tag 0x%lx\n",
- tsk_mgmt->managed_task_tag);
+ tsk_mgmt->task_tag);
cmd->result = (DID_ABORT << 16);
list_del(&found_evt->list);
@@ -1040,9 +1051,9 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
/* Set up a lun reset SRP command */
memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
- tsk_mgmt->type = SRP_TSK_MGMT_TYPE;
+ tsk_mgmt->opcode = SRP_TSK_MGMT;
tsk_mgmt->lun = ((u64) lun) << 48;
- tsk_mgmt->task_mgmt_flags = 0x08; /* LUN RESET */
+ tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET;
printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
tsk_mgmt->lun);
@@ -1059,16 +1070,16 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
wait_for_completion(&evt->comp);
/* make sure we got a good response */
- if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
+ if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) {
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: reset bad SRP RSP type %d\n",
- srp_rsp.srp.generic.type);
+ srp_rsp.srp.rsp.opcode);
return FAILED;
}
- if (srp_rsp.srp.rsp.rspvalid)
- rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
+ if (srp_rsp.srp.rsp.flags & SRP_RSP_FLAG_RSPVALID)
+ rsp_rc = *((int *)srp_rsp.srp.rsp.data);
else
rsp_rc = srp_rsp.srp.rsp.status;
@@ -1076,8 +1087,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: reset code %d for task tag 0x%lx\n",
- rsp_rc,
- tsk_mgmt->managed_task_tag);
+ rsp_rc, tsk_mgmt->task_tag);
return FAILED;
}
@@ -1179,6 +1189,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
/* We need to re-setup the interpartition connection */
printk(KERN_INFO
"ibmvscsi: Re-enabling adapter!\n");
+ atomic_set(&hostdata->request_limit, -1);
purge_requests(hostdata, DID_REQUEUE);
if (ibmvscsi_reenable_crq_queue(&hostdata->queue,
hostdata) == 0)
@@ -1226,7 +1237,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
}
if (crq->format == VIOSRP_SRP_FORMAT)
- atomic_add(evt_struct->xfer_iu->srp.rsp.request_limit_delta,
+ atomic_add(evt_struct->xfer_iu->srp.rsp.req_lim_delta,
&hostdata->request_limit);
if (evt_struct->done)
@@ -1254,6 +1265,7 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
{
struct viosrp_host_config *host_config;
struct srp_event_struct *evt_struct;
+ dma_addr_t addr;
int rc;
evt_struct = get_event_struct(&hostdata->pool);
@@ -1274,8 +1286,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
memset(host_config, 0x00, sizeof(*host_config));
host_config->common.type = VIOSRP_HOST_CONFIG_TYPE;
host_config->common.length = length;
- host_config->buffer = dma_map_single(hostdata->dev, buffer, length,
- DMA_BIDIRECTIONAL);
+ host_config->buffer = addr = dma_map_single(hostdata->dev, buffer,
+ length,
+ DMA_BIDIRECTIONAL);
if (dma_mapping_error(host_config->buffer)) {
printk(KERN_ERR
@@ -1286,11 +1299,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
init_completion(&evt_struct->comp);
rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
- if (rc == 0) {
+ if (rc == 0)
wait_for_completion(&evt_struct->comp);
- dma_unmap_single(hostdata->dev, host_config->buffer,
- length, DMA_BIDIRECTIONAL);
- }
+ dma_unmap_single(hostdata->dev, addr, length, DMA_BIDIRECTIONAL);
return rc;
}
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 4550d71e474..5c6d9358292 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -68,7 +68,7 @@ struct srp_event_struct {
void (*cmnd_done) (struct scsi_cmnd *);
struct completion comp;
union viosrp_iu *sync_srp;
- struct memory_descriptor *ext_list;
+ struct srp_direct_buf *ext_list;
dma_addr_t ext_list_token;
};
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index f47dd87c05e..1a9992bdfef 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -34,7 +34,6 @@
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include "ibmvscsi.h"
-#include "srp.h"
static char partition_name[97] = "UNKNOWN";
static unsigned int partition_number = -1;
@@ -80,7 +79,7 @@ void ibmvscsi_release_crq_queue(struct crq_queue *queue,
tasklet_kill(&hostdata->srp_task);
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
- } while ((rc == H_Busy) || (H_isLongBusy(rc)));
+ } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
dma_unmap_single(hostdata->dev,
queue->msg_token,
queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
@@ -230,7 +229,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
rc = plpar_hcall_norets(H_REG_CRQ,
vdev->unit_address,
queue->msg_token, PAGE_SIZE);
- if (rc == H_Resource)
+ if (rc == H_RESOURCE)
/* maybe kexecing and resource is busy. try a reset */
rc = ibmvscsi_reset_crq_queue(queue,
hostdata);
@@ -269,7 +268,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
req_irq_failed:
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
- } while ((rc == H_Busy) || (H_isLongBusy(rc)));
+ } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
reg_crq_failed:
dma_unmap_single(hostdata->dev,
queue->msg_token,
@@ -295,7 +294,7 @@ int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
/* Re-enable the CRQ */
do {
rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address);
- } while ((rc == H_InProgress) || (rc == H_Busy) || (H_isLongBusy(rc)));
+ } while ((rc == H_IN_PROGRESS) || (rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
if (rc)
printk(KERN_ERR "ibmvscsi: Error %d enabling adapter\n", rc);
@@ -317,7 +316,7 @@ int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
/* Close the CRQ */
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
- } while ((rc == H_Busy) || (H_isLongBusy(rc)));
+ } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
/* Clean out the queue */
memset(queue->msgs, 0x00, PAGE_SIZE);
diff --git a/drivers/scsi/ibmvscsi/srp.h b/drivers/scsi/ibmvscsi/srp.h
deleted file mode 100644
index 7d8e4c4accb..00000000000
--- a/drivers/scsi/ibmvscsi/srp.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/*****************************************************************************/
-/* srp.h -- SCSI RDMA Protocol definitions */
-/* */
-/* Written By: Colin Devilbis, IBM Corporation */
-/* */
-/* Copyright (C) 2003 IBM Corporation */
-/* */
-/* This program is free software; you can redistribute it and/or modify */
-/* it under the terms of the GNU General Public License as published by */
-/* the Free Software Foundation; either version 2 of the License, or */
-/* (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU General Public License */
-/* along with this program; if not, write to the Free Software */
-/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* */
-/* */
-/* This file contains structures and definitions for the SCSI RDMA Protocol */
-/* (SRP) as defined in the T10 standard available at www.t10.org. This */
-/* file was based on the 16a version of the standard */
-/* */
-/*****************************************************************************/
-#ifndef SRP_H
-#define SRP_H
-
-#define SRP_VERSION "16.a"
-
-#define PACKED __attribute__((packed))
-
-enum srp_types {
- SRP_LOGIN_REQ_TYPE = 0x00,
- SRP_LOGIN_RSP_TYPE = 0xC0,
- SRP_LOGIN_REJ_TYPE = 0xC2,
- SRP_I_LOGOUT_TYPE = 0x03,
- SRP_T_LOGOUT_TYPE = 0x80,
- SRP_TSK_MGMT_TYPE = 0x01,
- SRP_CMD_TYPE = 0x02,
- SRP_RSP_TYPE = 0xC1,
- SRP_CRED_REQ_TYPE = 0x81,
- SRP_CRED_RSP_TYPE = 0x41,
- SRP_AER_REQ_TYPE = 0x82,
- SRP_AER_RSP_TYPE = 0x42
-};
-
-enum srp_descriptor_formats {
- SRP_NO_BUFFER = 0x00,
- SRP_DIRECT_BUFFER = 0x01,
- SRP_INDIRECT_BUFFER = 0x02
-};
-
-struct memory_descriptor {
- u64 virtual_address;
- u32 memory_handle;
- u32 length;
-};
-
-struct indirect_descriptor {
- struct memory_descriptor head;
- u32 total_length;
- struct memory_descriptor list[1] PACKED;
-};
-
-struct srp_generic {
- u8 type;
- u8 reserved1[7];
- u64 tag;
-};
-
-struct srp_login_req {
- u8 type;
- u8 reserved1[7];
- u64 tag;
- u32 max_requested_initiator_to_target_iulen;
- u32 reserved2;
- u16 required_buffer_formats;
- u8 reserved3:6;
- u8 multi_channel_action:2;
- u8 reserved4;
- u32 reserved5;
- u8 initiator_port_identifier[16];
- u8 target_port_identifier[16];
-};
-
-struct srp_login_rsp {
- u8 type;
- u8 reserved1[3];
- u32 request_limit_delta;
- u64 tag;
- u32 max_initiator_to_target_iulen;
- u32 max_target_to_initiator_iulen;
- u16 supported_buffer_formats;
- u8 reserved2:6;
- u8 multi_channel_result:2;
- u8 reserved3;
- u8 reserved4[24];
-};
-
-struct srp_login_rej {
- u8 type;
- u8 reserved1[3];
- u32 reason;
- u64 tag;
- u64 reserved2;
- u16 supported_buffer_formats;
- u8 reserved3[6];
-};
-
-struct srp_i_logout {
- u8 type;
- u8 reserved1[7];
- u64 tag;
-};
-
-struct srp_t_logout {
- u8 type;
- u8 reserved1[3];
- u32 reason;
- u64 tag;
-};
-
-struct srp_tsk_mgmt {
- u8 type;
- u8 reserved1[7];
- u64 tag;
- u32 reserved2;
- u64 lun PACKED;
- u8 reserved3;
- u8 reserved4;
- u8 task_mgmt_flags;
- u8 reserved5;
- u64 managed_task_tag;
- u64 reserved6;
-};
-
-struct srp_cmd {
- u8 type;
- u32 reserved1 PACKED;
- u8 data_out_format:4;
- u8 data_in_format:4;
- u8 data_out_count;
- u8 data_in_count;
- u64 tag;
- u32 reserved2;
- u64 lun PACKED;
- u8 reserved3;
- u8 reserved4:5;
- u8 task_attribute:3;
- u8 reserved5;
- u8 additional_cdb_len;
- u8 cdb[16];
- u8 additional_data[0x100 - 0x30];
-};
-
-struct srp_rsp {
- u8 type;
- u8 reserved1[3];
- u32 request_limit_delta;
- u64 tag;
- u16 reserved2;
- u8 reserved3:2;
- u8 diunder:1;
- u8 diover:1;
- u8 dounder:1;
- u8 doover:1;
- u8 snsvalid:1;
- u8 rspvalid:1;
- u8 status;
- u32 data_in_residual_count;
- u32 data_out_residual_count;
- u32 sense_data_list_length;
- u32 response_data_list_length;
- u8 sense_and_response_data[18];
-};
-
-struct srp_cred_req {
- u8 type;
- u8 reserved1[3];
- u32 request_limit_delta;
- u64 tag;
-};
-
-struct srp_cred_rsp {
- u8 type;
- u8 reserved1[7];
- u64 tag;
-};
-
-struct srp_aer_req {
- u8 type;
- u8 reserved1[3];
- u32 request_limit_delta;
- u64 tag;
- u32 reserved2;
- u64 lun;
- u32 sense_data_list_length;
- u32 reserved3;
- u8 sense_data[20];
-};
-
-struct srp_aer_rsp {
- u8 type;
- u8 reserved1[7];
- u64 tag;
-};
-
-union srp_iu {
- struct srp_generic generic;
- struct srp_login_req login_req;
- struct srp_login_rsp login_rsp;
- struct srp_login_rej login_rej;
- struct srp_i_logout i_logout;
- struct srp_t_logout t_logout;
- struct srp_tsk_mgmt tsk_mgmt;
- struct srp_cmd cmd;
- struct srp_rsp rsp;
- struct srp_cred_req cred_req;
- struct srp_cred_rsp cred_rsp;
- struct srp_aer_req aer_req;
- struct srp_aer_rsp aer_rsp;
-};
-
-#endif
diff --git a/drivers/scsi/ibmvscsi/viosrp.h b/drivers/scsi/ibmvscsi/viosrp.h
index 6a6bba8a2f3..90f1a61283a 100644
--- a/drivers/scsi/ibmvscsi/viosrp.h
+++ b/drivers/scsi/ibmvscsi/viosrp.h
@@ -33,7 +33,22 @@
/*****************************************************************************/
#ifndef VIOSRP_H
#define VIOSRP_H
-#include "srp.h"
+#include <scsi/srp.h>
+
+#define SRP_VERSION "16.a"
+#define SRP_MAX_IU_LEN 256
+
+union srp_iu {
+ struct srp_login_req login_req;
+ struct srp_login_rsp login_rsp;
+ struct srp_login_rej login_rej;
+ struct srp_i_logout i_logout;
+ struct srp_t_logout t_logout;
+ struct srp_tsk_mgmt tsk_mgmt;
+ struct srp_cmd cmd;
+ struct srp_rsp rsp;
+ u8 reserved[SRP_MAX_IU_LEN];
+};
enum viosrp_crq_formats {
VIOSRP_SRP_FORMAT = 0x01,
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index ea6f3c0e05d..0cc7f65b584 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -127,6 +127,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <scsi/scsi.h>
@@ -2780,7 +2781,7 @@ static int tul_NewReturnNumberOfAdapters(void)
if (((dRegValue & 0xFF00) >> 8) == 0xFF)
dRegValue = 0;
wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
- if (pci_set_dma_mask(pDev, 0xffffffff)) {
+ if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) {
printk(KERN_WARNING
"i91u: Could not set 32 bit DMA mask\n");
continue;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 5890e5f92d8..8b80e59c8c5 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -164,29 +164,6 @@ MODULE_PARM_DESC(auto_create, "Auto-create single device RAID 0 arrays when init
MODULE_LICENSE("GPL");
MODULE_VERSION(IPR_DRIVER_VERSION);
-static const char *ipr_gpdd_dev_end_states[] = {
- "Command complete",
- "Terminated by host",
- "Terminated by device reset",
- "Terminated by bus reset",
- "Unknown",
- "Command not started"
-};
-
-static const char *ipr_gpdd_dev_bus_phases[] = {
- "Bus free",
- "Arbitration",
- "Selection",
- "Message out",
- "Command",
- "Message in",
- "Data out",
- "Data in",
- "Status",
- "Reselection",
- "Unknown"
-};
-
/* A constant array of IOASCs/URCs/Error Messages */
static const
struct ipr_error_table_t ipr_error_table[] = {
@@ -869,8 +846,8 @@ static void ipr_handle_config_change(struct ipr_ioa_cfg *ioa_cfg,
if (hostrcb->hcam.notify_type == IPR_HOST_RCB_NOTIF_TYPE_REM_ENTRY) {
if (res->sdev) {
- res->sdev->hostdata = NULL;
res->del_from_ml = 1;
+ res->cfgte.res_handle = IPR_INVALID_RES_HANDLE;
if (ioa_cfg->allow_ml_add_del)
schedule_work(&ioa_cfg->work_q);
} else
@@ -1356,8 +1333,8 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg,
return;
if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) {
- ipr_res_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr,
- "%s\n", ipr_error_table[error_index].error);
+ ipr_ra_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr,
+ "%s\n", ipr_error_table[error_index].error);
} else {
dev_err(&ioa_cfg->pdev->dev, "%s\n",
ipr_error_table[error_index].error);
@@ -2107,7 +2084,6 @@ restart:
did_work = 1;
sdev = res->sdev;
if (!scsi_device_get(sdev)) {
- res->sdev = NULL;
list_move_tail(&res->queue, &ioa_cfg->free_res_q);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
scsi_remove_device(sdev);
@@ -2124,6 +2100,7 @@ restart:
bus = res->cfgte.res_addr.bus;
target = res->cfgte.res_addr.target;
lun = res->cfgte.res_addr.lun;
+ res->add_to_ml = 0;
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
scsi_add_device(ioa_cfg->host, bus, target, lun);
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -3214,7 +3191,7 @@ static int ipr_slave_configure(struct scsi_device *sdev)
sdev->timeout = IPR_VSET_RW_TIMEOUT;
blk_queue_max_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS);
}
- if (IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data))
+ if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res))
sdev->allow_restart = 1;
scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
}
@@ -3304,6 +3281,44 @@ static int ipr_eh_host_reset(struct scsi_cmnd * cmd)
}
/**
+ * ipr_device_reset - Reset the device
+ * @ioa_cfg: ioa config struct
+ * @res: resource entry struct
+ *
+ * This function issues a device reset to the affected device.
+ * If the device is a SCSI device, a LUN reset will be sent
+ * to the device first. If that does not work, a target reset
+ * will be sent.
+ *
+ * Return value:
+ * 0 on success / non-zero on failure
+ **/
+static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg,
+ struct ipr_resource_entry *res)
+{
+ struct ipr_cmnd *ipr_cmd;
+ struct ipr_ioarcb *ioarcb;
+ struct ipr_cmd_pkt *cmd_pkt;
+ u32 ioasc;
+
+ ENTER;
+ ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
+ ioarcb = &ipr_cmd->ioarcb;
+ cmd_pkt = &ioarcb->cmd_pkt;
+
+ ioarcb->res_handle = res->cfgte.res_handle;
+ cmd_pkt->request_type = IPR_RQTYPE_IOACMD;
+ cmd_pkt->cdb[0] = IPR_RESET_DEVICE;
+
+ ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
+ ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+ list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+
+ LEAVE;
+ return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0);
+}
+
+/**
* ipr_eh_dev_reset - Reset the device
* @scsi_cmd: scsi command struct
*
@@ -3319,8 +3334,7 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
struct ipr_cmnd *ipr_cmd;
struct ipr_ioa_cfg *ioa_cfg;
struct ipr_resource_entry *res;
- struct ipr_cmd_pkt *cmd_pkt;
- u32 ioasc;
+ int rc;
ENTER;
ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
@@ -3347,25 +3361,12 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
}
res->resetting_device = 1;
-
- ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
-
- ipr_cmd->ioarcb.res_handle = res->cfgte.res_handle;
- cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt;
- cmd_pkt->request_type = IPR_RQTYPE_IOACMD;
- cmd_pkt->cdb[0] = IPR_RESET_DEVICE;
-
- ipr_sdev_err(scsi_cmd->device, "Resetting device\n");
- ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
-
- ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
-
+ scmd_printk(KERN_ERR, scsi_cmd, "Resetting device\n");
+ rc = ipr_device_reset(ioa_cfg, res);
res->resetting_device = 0;
- list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
-
LEAVE;
- return (IPR_IOASC_SENSE_KEY(ioasc) ? FAILED : SUCCESS);
+ return (rc ? FAILED : SUCCESS);
}
static int ipr_eh_dev_reset(struct scsi_cmnd * cmd)
@@ -3440,7 +3441,7 @@ static void ipr_abort_timeout(struct ipr_cmnd *ipr_cmd)
return;
}
- ipr_sdev_err(ipr_cmd->u.sdev, "Abort timed out. Resetting bus\n");
+ sdev_printk(KERN_ERR, ipr_cmd->u.sdev, "Abort timed out. Resetting bus.\n");
reset_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
ipr_cmd->sibling = reset_cmd;
reset_cmd->sibling = ipr_cmd;
@@ -3504,7 +3505,8 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
cmd_pkt->cdb[0] = IPR_CANCEL_ALL_REQUESTS;
ipr_cmd->u.sdev = scsi_cmd->device;
- ipr_sdev_err(scsi_cmd->device, "Aborting command: %02X\n", scsi_cmd->cmnd[0]);
+ scmd_printk(KERN_ERR, scsi_cmd, "Aborting command: %02X\n",
+ scsi_cmd->cmnd[0]);
ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT);
ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
@@ -3815,8 +3817,8 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
if (IPR_IOASC_SENSE_KEY(ioasc) > 0) {
scsi_cmd->result |= (DID_ERROR << 16);
- ipr_sdev_err(scsi_cmd->device,
- "Request Sense failed with IOASC: 0x%08X\n", ioasc);
+ scmd_printk(KERN_ERR, scsi_cmd,
+ "Request Sense failed with IOASC: 0x%08X\n", ioasc);
} else {
memcpy(scsi_cmd->sense_buffer, ipr_cmd->sense_buffer,
SCSI_SENSE_BUFFERSIZE);
@@ -3938,6 +3940,7 @@ static void ipr_erp_cancel_all(struct ipr_cmnd *ipr_cmd)
* ipr_dump_ioasa - Dump contents of IOASA
* @ioa_cfg: ioa config struct
* @ipr_cmd: ipr command struct
+ * @res: resource entry struct
*
* This function is invoked by the interrupt handler when ops
* fail. It will log the IOASA if appropriate. Only called
@@ -3947,7 +3950,7 @@ static void ipr_erp_cancel_all(struct ipr_cmnd *ipr_cmd)
* none
**/
static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
- struct ipr_cmnd *ipr_cmd)
+ struct ipr_cmnd *ipr_cmd, struct ipr_resource_entry *res)
{
int i;
u16 data_len;
@@ -3975,16 +3978,7 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
return;
}
- ipr_sdev_err(ipr_cmd->scsi_cmd->device, "%s\n",
- ipr_error_table[error_index].error);
-
- if ((ioasa->u.gpdd.end_state <= ARRAY_SIZE(ipr_gpdd_dev_end_states)) &&
- (ioasa->u.gpdd.bus_phase <= ARRAY_SIZE(ipr_gpdd_dev_bus_phases))) {
- ipr_sdev_err(ipr_cmd->scsi_cmd->device,
- "Device End state: %s Phase: %s\n",
- ipr_gpdd_dev_end_states[ioasa->u.gpdd.end_state],
- ipr_gpdd_dev_bus_phases[ioasa->u.gpdd.bus_phase]);
- }
+ ipr_res_err(ioa_cfg, res, "%s\n", ipr_error_table[error_index].error);
if (sizeof(struct ipr_ioasa) < be16_to_cpu(ioasa->ret_stat_len))
data_len = sizeof(struct ipr_ioasa);
@@ -4141,7 +4135,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
}
if (ipr_is_gscsi(res))
- ipr_dump_ioasa(ioa_cfg, ipr_cmd);
+ ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
else
ipr_gen_sense(ipr_cmd);
@@ -4540,7 +4534,7 @@ static int ipr_set_supported_devs(struct ipr_cmnd *ipr_cmd)
ipr_cmd->job_step = ipr_ioa_reset_done;
list_for_each_entry_continue(res, &ioa_cfg->used_res_q, queue) {
- if (!IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data))
+ if (!ipr_is_scsi_disk(res))
continue;
ipr_cmd->u.res = res;
@@ -4980,7 +4974,7 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd)
list_for_each_entry_safe(res, temp, &old_res, queue) {
if (res->sdev) {
res->del_from_ml = 1;
- res->sdev->hostdata = NULL;
+ res->cfgte.res_handle = IPR_INVALID_RES_HANDLE;
list_move_tail(&res->queue, &ioa_cfg->used_res_q);
} else {
list_move_tail(&res->queue, &ioa_cfg->free_res_q);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index fd360bfe56d..1ad24df69d7 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -36,8 +36,8 @@
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.1.2"
-#define IPR_DRIVER_DATE "(February 8, 2006)"
+#define IPR_DRIVER_VERSION "2.1.3"
+#define IPR_DRIVER_DATE "(March 29, 2006)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -133,6 +133,7 @@
#define IPR_MAX_SCSI_RATE(width) ((320 * 10) / ((width) / 8))
#define IPR_IOA_RES_HANDLE 0xffffffff
+#define IPR_INVALID_RES_HANDLE 0
#define IPR_IOA_RES_ADDR 0x00ffffff
/*
@@ -1191,30 +1192,17 @@ struct ipr_ucode_image_header {
*/
#define ipr_err(...) printk(KERN_ERR IPR_NAME ": "__VA_ARGS__)
#define ipr_info(...) printk(KERN_INFO IPR_NAME ": "__VA_ARGS__)
-#define ipr_crit(...) printk(KERN_CRIT IPR_NAME ": "__VA_ARGS__)
-#define ipr_warn(...) printk(KERN_WARNING IPR_NAME": "__VA_ARGS__)
#define ipr_dbg(...) IPR_DBG_CMD(printk(KERN_INFO IPR_NAME ": "__VA_ARGS__))
-#define ipr_sdev_printk(level, sdev, fmt, args...) \
- sdev_printk(level, sdev, fmt, ## args)
+#define ipr_ra_printk(level, ioa_cfg, ra, fmt, ...) \
+ printk(level IPR_NAME ": %d:%d:%d:%d: " fmt, (ioa_cfg)->host->host_no, \
+ (ra).bus, (ra).target, (ra).lun, ##__VA_ARGS__)
-#define ipr_sdev_err(sdev, fmt, ...) \
- ipr_sdev_printk(KERN_ERR, sdev, fmt, ##__VA_ARGS__)
-
-#define ipr_sdev_info(sdev, fmt, ...) \
- ipr_sdev_printk(KERN_INFO, sdev, fmt, ##__VA_ARGS__)
-
-#define ipr_sdev_dbg(sdev, fmt, ...) \
- IPR_DBG_CMD(ipr_sdev_printk(KERN_INFO, sdev, fmt, ##__VA_ARGS__))
-
-#define ipr_res_printk(level, ioa_cfg, res, fmt, ...) \
- printk(level IPR_NAME ": %d:%d:%d:%d: " fmt, ioa_cfg->host->host_no, \
- res.bus, res.target, res.lun, ##__VA_ARGS__)
+#define ipr_ra_err(ioa_cfg, ra, fmt, ...) \
+ ipr_ra_printk(KERN_ERR, ioa_cfg, ra, fmt, ##__VA_ARGS__)
#define ipr_res_err(ioa_cfg, res, fmt, ...) \
- ipr_res_printk(KERN_ERR, ioa_cfg, res, fmt, ##__VA_ARGS__)
-#define ipr_res_dbg(ioa_cfg, res, fmt, ...) \
- IPR_DBG_CMD(ipr_res_printk(KERN_INFO, ioa_cfg, res, fmt, ##__VA_ARGS__))
+ ipr_ra_err(ioa_cfg, (res)->cfgte.res_addr, fmt, ##__VA_ARGS__)
#define ipr_phys_res_err(ioa_cfg, res, fmt, ...) \
{ \
@@ -1304,6 +1292,22 @@ static inline int ipr_is_gscsi(struct ipr_resource_entry *res)
}
/**
+ * ipr_is_scsi_disk - Determine if a resource is a SCSI disk
+ * @res: resource entry struct
+ *
+ * Return value:
+ * 1 if SCSI disk / 0 if not SCSI disk
+ **/
+static inline int ipr_is_scsi_disk(struct ipr_resource_entry *res)
+{
+ if (ipr_is_af_dasd_device(res) ||
+ (ipr_is_gscsi(res) && IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data)))
+ return 1;
+ else
+ return 0;
+}
+
+/**
* ipr_is_naca_model - Determine if a resource is using NACA queueing model
* @res: resource entry struct
*
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 481708d527a..a4c0b04cfdb 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -179,6 +179,7 @@
#include <linux/blkdev.h>
#include <linux/types.h>
+#include <linux/dma-mapping.h>
#include <scsi/sg.h>
@@ -7284,10 +7285,10 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
* are guaranteed to be < 4G.
*/
if (IPS_ENABLE_DMA64 && IPS_HAS_ENH_SGLIST(ha) &&
- !pci_set_dma_mask(ha->pcidev, 0xffffffffffffffffULL)) {
+ !pci_set_dma_mask(ha->pcidev, DMA_64BIT_MASK)) {
(ha)->flags |= IPS_HA_ENH_SG;
} else {
- if (pci_set_dma_mask(ha->pcidev, 0xffffffffULL) != 0) {
+ if (pci_set_dma_mask(ha->pcidev, DMA_32BIT_MASK) != 0) {
printk(KERN_WARNING "Unable to set DMA Mask\n");
return ips_abort_init(ha, index);
}
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 459a4daebec..eb7bd310cc8 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -112,7 +112,7 @@ lasi700_probe(struct parisc_device *dev)
hostdata->dev = &dev->dev;
dma_set_mask(&dev->dev, DMA_32BIT_MASK);
- hostdata->base = ioremap(base, 0x100);
+ hostdata->base = ioremap_nocache(base, 0x100);
hostdata->differential = 0;
if (dev->id.sversion == LASI_700_SVERSION) {
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
index 95d81d86d8b..835dff0bafd 100644
--- a/drivers/scsi/libata-bmdma.c
+++ b/drivers/scsi/libata-bmdma.c
@@ -703,6 +703,7 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
struct ata_probe_ent *probe_ent =
ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
int p = 0;
+ unsigned long bmdma;
if (!probe_ent)
return NULL;
@@ -716,7 +717,12 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
probe_ent->port[p].altstatus_addr =
probe_ent->port[p].ctl_addr =
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
- probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4);
+ bmdma = pci_resource_start(pdev, 4);
+ if (bmdma) {
+ if (inb(bmdma + 2) & 0x80)
+ probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+ probe_ent->port[p].bmdma_addr = bmdma;
+ }
ata_std_ports(&probe_ent->port[p]);
p++;
}
@@ -726,7 +732,13 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
probe_ent->port[p].altstatus_addr =
probe_ent->port[p].ctl_addr =
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
- probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+ bmdma = pci_resource_start(pdev, 4);
+ if (bmdma) {
+ bmdma += 8;
+ if(inb(bmdma + 2) & 0x80)
+ probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+ probe_ent->port[p].bmdma_addr = bmdma;
+ }
ata_std_ports(&probe_ent->port[p]);
p++;
}
@@ -740,6 +752,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
struct ata_port_info *port, int port_num)
{
struct ata_probe_ent *probe_ent;
+ unsigned long bmdma;
probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
if (!probe_ent)
@@ -766,8 +779,13 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
break;
}
- probe_ent->port[0].bmdma_addr =
- pci_resource_start(pdev, 4) + 8 * port_num;
+ bmdma = pci_resource_start(pdev, 4);
+ if (bmdma != 0) {
+ bmdma += 8 * port_num;
+ probe_ent->port[0].bmdma_addr = bmdma;
+ if (inb(bmdma + 2) & 0x80)
+ probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+ }
ata_std_ports(&probe_ent->port[0]);
return probe_ent;
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index d279666dcb3..b046ffa2210 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -62,7 +62,9 @@
#include "libata.h"
static unsigned int ata_dev_init_params(struct ata_port *ap,
- struct ata_device *dev);
+ struct ata_device *dev,
+ u16 heads,
+ u16 sectors);
static void ata_set_mode(struct ata_port *ap);
static unsigned int ata_dev_set_xfermode(struct ata_port *ap,
struct ata_device *dev);
@@ -276,7 +278,7 @@ static void ata_unpack_xfermask(unsigned int xfer_mask,
}
static const struct ata_xfer_ent {
- unsigned int shift, bits;
+ int shift, bits;
u8 base;
} ata_xfer_tbl[] = {
{ ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 },
@@ -862,6 +864,9 @@ static unsigned int ata_id_xfermask(const u16 *id)
/**
* ata_port_queue_task - Queue port_task
* @ap: The ata_port to queue port_task for
+ * @fn: workqueue function to be scheduled
+ * @data: data value to pass to workqueue function
+ * @delay: delay time for workqueue function
*
* Schedule @fn(@data) for execution after @delay jiffies using
* port_task. There is one port_task per port and it's the
@@ -987,9 +992,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
qc->private_data = &wait;
qc->complete_fn = ata_qc_complete_internal;
- qc->err_mask = ata_qc_issue(qc);
- if (qc->err_mask)
- ata_qc_complete(qc);
+ ata_qc_issue(qc);
spin_unlock_irqrestore(&ap->host_set->lock, flags);
@@ -1081,9 +1084,8 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
*
* Read ID data from the specified device. ATA_CMD_ID_ATA is
* performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI
- * devices. This function also takes care of EDD signature
- * misreporting (to be removed once EDD support is gone) and
- * issues ATA_CMD_INIT_DEV_PARAMS for pre-ATA4 drives.
+ * devices. This function also issues ATA_CMD_INIT_DEV_PARAMS
+ * for pre-ATA4 drives.
*
* LOCKING:
* Kernel thread context (may sleep)
@@ -1095,7 +1097,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
unsigned int *p_class, int post_reset, u16 **p_id)
{
unsigned int class = *p_class;
- unsigned int using_edd;
struct ata_taskfile tf;
unsigned int err_mask = 0;
u16 *id;
@@ -1104,12 +1105,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno);
- if (ap->ops->probe_reset ||
- ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET))
- using_edd = 0;
- else
- using_edd = 1;
-
ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL);
@@ -1139,39 +1134,16 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
id, sizeof(id[0]) * ATA_ID_WORDS);
-
if (err_mask) {
rc = -EIO;
reason = "I/O error";
-
- if (err_mask & ~AC_ERR_DEV)
- goto err_out;
-
- /*
- * arg! EDD works for all test cases, but seems to return
- * the ATA signature for some ATAPI devices. Until the
- * reason for this is found and fixed, we fix up the mess
- * here. If IDENTIFY DEVICE returns command aborted
- * (as ATAPI devices do), then we issue an
- * IDENTIFY PACKET DEVICE.
- *
- * ATA software reset (SRST, the default) does not appear
- * to have this problem.
- */
- if ((using_edd) && (class == ATA_DEV_ATA)) {
- u8 err = tf.feature;
- if (err & ATA_ABORTED) {
- class = ATA_DEV_ATAPI;
- goto retry;
- }
- }
goto err_out;
}
swap_buf_le16(id, ATA_ID_WORDS);
/* sanity check */
- if ((class == ATA_DEV_ATA) != ata_id_is_ata(id)) {
+ if ((class == ATA_DEV_ATA) != (ata_id_is_ata(id) | ata_id_is_cfa(id))) {
rc = -EINVAL;
reason = "device reports illegal type";
goto err_out;
@@ -1187,7 +1159,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
* Some drives were very specific about that exact sequence.
*/
if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
- err_mask = ata_dev_init_params(ap, dev);
+ err_mask = ata_dev_init_params(ap, dev, id[3], id[6]);
if (err_mask) {
rc = -EIO;
reason = "INIT_DEV_PARAMS failed";
@@ -1440,7 +1412,11 @@ static int ata_bus_probe(struct ata_port *ap)
if (!found)
goto err_out_disable;
- ata_set_mode(ap);
+ if (ap->ops->set_mode)
+ ap->ops->set_mode(ap);
+ else
+ ata_set_mode(ap);
+
if (ap->flags & ATA_FLAG_PORT_DISABLED)
goto err_out_disable;
@@ -1845,7 +1821,7 @@ static void ata_host_set_dma(struct ata_port *ap)
*/
static void ata_set_mode(struct ata_port *ap)
{
- int i, rc;
+ int i, rc, used_dma = 0;
/* step 1: calculate xfer_mask */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
@@ -1863,6 +1839,9 @@ static void ata_set_mode(struct ata_port *ap)
dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);
dev->pio_mode = ata_xfer_mask2mode(pio_mask);
dev->dma_mode = ata_xfer_mask2mode(dma_mask);
+
+ if (dev->dma_mode)
+ used_dma = 1;
}
/* step 2: always set host PIO timings */
@@ -1884,6 +1863,17 @@ static void ata_set_mode(struct ata_port *ap)
goto err_out;
}
+ /*
+ * Record simplex status. If we selected DMA then the other
+ * host channels are not permitted to do so.
+ */
+
+ if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX))
+ ap->host_set->simplex_claimed = 1;
+
+ /*
+ * Chip specific finalisation
+ */
if (ap->ops->post_set_mode)
ap->ops->post_set_mode(ap);
@@ -2005,45 +1995,6 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
ap->ops->dev_select(ap, 0);
}
-/**
- * ata_bus_edd - Issue EXECUTE DEVICE DIAGNOSTIC command.
- * @ap: Port to reset and probe
- *
- * Use the EXECUTE DEVICE DIAGNOSTIC command to reset and
- * probe the bus. Not often used these days.
- *
- * LOCKING:
- * PCI/etc. bus probe sem.
- * Obtains host_set lock.
- *
- */
-
-static unsigned int ata_bus_edd(struct ata_port *ap)
-{
- struct ata_taskfile tf;
- unsigned long flags;
-
- /* set up execute-device-diag (bus reset) taskfile */
- /* also, take interrupts to a known state (disabled) */
- DPRINTK("execute-device-diag\n");
- ata_tf_init(ap, &tf, 0);
- tf.ctl |= ATA_NIEN;
- tf.command = ATA_CMD_EDD;
- tf.protocol = ATA_PROT_NODATA;
-
- /* do bus reset */
- spin_lock_irqsave(&ap->host_set->lock, flags);
- ata_tf_to_host(ap, &tf);
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
- /* spec says at least 2ms. but who knows with those
- * crazy ATAPI devices...
- */
- msleep(150);
-
- return ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
-}
-
static unsigned int ata_bus_softreset(struct ata_port *ap,
unsigned int devmask)
{
@@ -2078,13 +2029,12 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
*/
msleep(150);
-
/* Before we perform post reset processing we want to see if
- the bus shows 0xFF because the odd clown forgets the D7 pulldown
- resistor */
-
+ * the bus shows 0xFF because the odd clown forgets the D7
+ * pulldown resistor.
+ */
if (ata_check_status(ap) == 0xFF)
- return 1; /* Positive is failure for some reason */
+ return AC_ERR_OTHER;
ata_bus_post_reset(ap, devmask);
@@ -2116,7 +2066,7 @@ void ata_bus_reset(struct ata_port *ap)
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
u8 err;
- unsigned int dev0, dev1 = 0, rc = 0, devmask = 0;
+ unsigned int dev0, dev1 = 0, devmask = 0;
DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no);
@@ -2139,18 +2089,8 @@ void ata_bus_reset(struct ata_port *ap)
/* issue bus reset */
if (ap->flags & ATA_FLAG_SRST)
- rc = ata_bus_softreset(ap, devmask);
- else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) {
- /* set up device control */
- if (ap->flags & ATA_FLAG_MMIO)
- writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
- else
- outb(ap->ctl, ioaddr->ctl_addr);
- rc = ata_bus_edd(ap);
- }
-
- if (rc)
- goto err_out;
+ if (ata_bus_softreset(ap, devmask))
+ goto err_out;
/*
* determine by signature whether we have ATA or ATAPI devices
@@ -2223,9 +2163,9 @@ static int sata_phy_resume(struct ata_port *ap)
* so makes reset sequence different from the original
* ->phy_reset implementation and Jeff nervous. :-P
*/
-extern void ata_std_probeinit(struct ata_port *ap)
+void ata_std_probeinit(struct ata_port *ap)
{
- if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) {
+ if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) {
sata_phy_resume(ap);
if (sata_dev_present(ap))
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
@@ -2714,18 +2654,23 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
* known limits including host controller limits, device
* blacklist, etc...
*
+ * FIXME: The current implementation limits all transfer modes to
+ * the fastest of the lowested device on the port. This is not
+ * required on most controllers.
+ *
* LOCKING:
* None.
*/
static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev)
{
+ struct ata_host_set *hs = ap->host_set;
unsigned long xfer_mask;
int i;
xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask,
ap->udma_mask);
- /* use port-wide xfermask for now */
+ /* FIXME: Use port-wide xfermask for now */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *d = &ap->device[i];
if (!ata_dev_present(d))
@@ -2735,12 +2680,23 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev)
xfer_mask &= ata_id_xfermask(d->id);
if (ata_dma_blacklisted(d))
xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+ /* Apply cable rule here. Don't apply it early because when
+ we handle hot plug the cable type can itself change */
+ if (ap->cbl == ATA_CBL_PATA40)
+ xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
}
if (ata_dma_blacklisted(dev))
printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, "
"disabling DMA\n", ap->id, dev->devno);
+ if (hs->flags & ATA_HOST_SIMPLEX) {
+ if (hs->simplex_claimed)
+ xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+ }
+ if (ap->ops->mode_filter)
+ xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask);
+
ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
&dev->udma_mask);
}
@@ -2786,6 +2742,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap,
* ata_dev_init_params - Issue INIT DEV PARAMS command
* @ap: Port associated with device @dev
* @dev: Device to which command will be sent
+ * @heads: Number of heads (taskfile parameter)
+ * @sectors: Number of sectors (taskfile parameter)
*
* LOCKING:
* Kernel thread context (may sleep)
@@ -2795,16 +2753,16 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap,
*/
static unsigned int ata_dev_init_params(struct ata_port *ap,
- struct ata_device *dev)
+ struct ata_device *dev,
+ u16 heads,
+ u16 sectors)
{
struct ata_taskfile tf;
unsigned int err_mask;
- u16 sectors = dev->id[6];
- u16 heads = dev->id[3];
/* Number of sectors per track 1-255. Number of heads 1-16 */
if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
- return 0;
+ return AC_ERR_INVALID;
/* set up init dev params taskfile */
DPRINTK("init dev params \n");
@@ -3685,6 +3643,8 @@ static void ata_pio_block(struct ata_port *ap)
ata_pio_sector(qc);
}
+
+ ata_altstatus(ap); /* flush */
}
static void ata_pio_error(struct ata_port *ap)
@@ -3801,11 +3761,14 @@ static void atapi_packet_task(void *_data)
spin_lock_irqsave(&ap->host_set->lock, flags);
ap->flags &= ~ATA_FLAG_NOINTR;
ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
+ ata_altstatus(ap); /* flush */
+
if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
ap->ops->bmdma_start(qc); /* initiate bmdma */
spin_unlock_irqrestore(&ap->host_set->lock, flags);
} else {
ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
+ ata_altstatus(ap); /* flush */
/* PIO commands are handled by polling */
ap->hsm_task_state = HSM_ST;
@@ -4042,15 +4005,14 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
- *
- * RETURNS:
- * Zero on success, AC_ERR_* mask on failure
*/
-
-unsigned int ata_qc_issue(struct ata_queued_cmd *qc)
+void ata_qc_issue(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
+ qc->ap->active_tag = qc->tag;
+ qc->flags |= ATA_QCFLAG_ACTIVE;
+
if (ata_should_dma_map(qc)) {
if (qc->flags & ATA_QCFLAG_SG) {
if (ata_sg_setup(qc))
@@ -4065,17 +4027,18 @@ unsigned int ata_qc_issue(struct ata_queued_cmd *qc)
ap->ops->qc_prep(qc);
- qc->ap->active_tag = qc->tag;
- qc->flags |= ATA_QCFLAG_ACTIVE;
-
- return ap->ops->qc_issue(qc);
+ qc->err_mask |= ap->ops->qc_issue(qc);
+ if (unlikely(qc->err_mask))
+ goto err;
+ return;
sg_err:
qc->flags &= ~ATA_QCFLAG_DMAMAP;
- return AC_ERR_SYSTEM;
+ qc->err_mask |= AC_ERR_SYSTEM;
+err:
+ ata_qc_complete(qc);
}
-
/**
* ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
* @qc: command to issue to device
@@ -4334,6 +4297,7 @@ static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
{
if (ap->flags & ATA_FLAG_SUSPENDED) {
+ ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 200000);
ap->flags &= ~ATA_FLAG_SUSPENDED;
ata_set_mode(ap);
}
@@ -4349,6 +4313,7 @@ int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
* ata_device_suspend - prepare a device for suspend
* @ap: port the device is connected to
* @dev: the device to suspend
+ * @state: target power management state
*
* Flush the cache on the drive, if appropriate, then issue a
* standbynow command.
@@ -4536,6 +4501,14 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent,
int rc;
DPRINTK("ENTER\n");
+
+ if (!ent->port_ops->probe_reset &&
+ !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) {
+ printk(KERN_ERR "ata%u: no reset mechanism available\n",
+ port_no);
+ return NULL;
+ }
+
host = scsi_host_alloc(ent->sht, sizeof(struct ata_port));
if (!host)
return NULL;
@@ -4596,6 +4569,7 @@ int ata_device_add(const struct ata_probe_ent *ent)
host_set->mmio_base = ent->mmio_base;
host_set->private_data = ent->private_data;
host_set->ops = ent->port_ops;
+ host_set->flags = ent->host_set_flags;
/* register each port bound to this device */
for (i = 0; i < ent->n_ports; i++) {
@@ -4976,7 +4950,6 @@ EXPORT_SYMBOL_GPL(ata_busy_sleep);
EXPORT_SYMBOL_GPL(ata_port_queue_task);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
-EXPORT_SYMBOL_GPL(ata_scsi_error);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
EXPORT_SYMBOL_GPL(ata_scsi_release);
EXPORT_SYMBOL_GPL(ata_host_intr);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 628191bfd99..a0289ec3e28 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -53,6 +53,7 @@
typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
static struct ata_device *
ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev);
+static void ata_scsi_error(struct Scsi_Host *host);
enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
#define RW_RECOVERY_MPAGE 0x1
@@ -99,6 +100,7 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
* It just needs the eh_timed_out hook.
*/
struct scsi_transport_template ata_scsi_transport_template = {
+ .eh_strategy_handler = ata_scsi_error,
.eh_timed_out = ata_scsi_timed_out,
};
@@ -772,12 +774,9 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
*
* LOCKING:
* Inherited from SCSI layer (none, can sleep)
- *
- * RETURNS:
- * Zero.
*/
-int ata_scsi_error(struct Scsi_Host *host)
+static void ata_scsi_error(struct Scsi_Host *host)
{
struct ata_port *ap;
unsigned long flags;
@@ -805,7 +804,6 @@ int ata_scsi_error(struct Scsi_Host *host)
spin_unlock_irqrestore(&ap->host_set->lock, flags);
DPRINTK("EXIT\n");
- return 0;
}
static void ata_eh_scsidone(struct scsi_cmnd *scmd)
@@ -1431,9 +1429,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
goto early_finish;
/* select device, send command to hardware */
- qc->err_mask = ata_qc_issue(qc);
- if (qc->err_mask)
- ata_qc_complete(qc);
+ ata_qc_issue(qc);
VPRINTK("EXIT\n");
return;
@@ -2199,9 +2195,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
qc->complete_fn = atapi_sense_complete;
- qc->err_mask = ata_qc_issue(qc);
- if (qc->err_mask)
- ata_qc_complete(qc);
+ ata_qc_issue(qc);
DPRINTK("EXIT\n");
}
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 65f52beea88..bac8cbae06f 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -47,7 +47,7 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
extern void ata_port_flush_task(struct ata_port *ap);
extern void ata_qc_free(struct ata_queued_cmd *qc);
-extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc);
+extern void ata_qc_issue(struct ata_queued_cmd *qc);
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
extern void ata_dev_select(struct ata_port *ap, unsigned int device,
unsigned int wait, unsigned int can_sleep);
@@ -60,7 +60,6 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
extern struct scsi_transport_template ata_scsi_transport_template;
extern void ata_scsi_scan_host(struct ata_port *ap);
-extern int ata_scsi_error(struct Scsi_Host *host);
extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index fad607b2e6f..ee22173fce4 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -27,7 +27,6 @@ void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
-void lpfc_set_slim(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_t *,
uint32_t);
void lpfc_unreg_login(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 8932b1be2b6..41cf5d3ea6c 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -113,6 +113,7 @@ struct lpfc_nodelist {
#define NLP_NPR_ADISC 0x2000000 /* Issue ADISC when dq'ed from
NPR list */
#define NLP_DELAY_REMOVE 0x4000000 /* Defer removal till end of DSM */
+#define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */
/* Defines for list searchs */
#define NLP_SEARCH_MAPPED 0x1 /* search mapped */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 4813beaaca8..283b7d824c3 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -302,10 +302,6 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
if (lpfc_reg_login(phba, Fabric_DID, (uint8_t *) sp, mbox, 0))
goto fail_free_mbox;
- /*
- * set_slim mailbox command needs to execute first,
- * queue this command to be processed later.
- */
mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
mbox->context2 = ndlp;
@@ -781,25 +777,26 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
if (disc && phba->num_disc_nodes) {
/* Check to see if there are more PLOGIs to be sent */
lpfc_more_plogi(phba);
- }
- if (phba->num_disc_nodes == 0) {
- spin_lock_irq(phba->host->host_lock);
- phba->fc_flag &= ~FC_NDISC_ACTIVE;
- spin_unlock_irq(phba->host->host_lock);
+ if (phba->num_disc_nodes == 0) {
+ spin_lock_irq(phba->host->host_lock);
+ phba->fc_flag &= ~FC_NDISC_ACTIVE;
+ spin_unlock_irq(phba->host->host_lock);
- lpfc_can_disctmo(phba);
- if (phba->fc_flag & FC_RSCN_MODE) {
- /* Check to see if more RSCNs came in while we were
- * processing this one.
- */
- if ((phba->fc_rscn_id_cnt == 0) &&
- (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
- spin_lock_irq(phba->host->host_lock);
- phba->fc_flag &= ~FC_RSCN_MODE;
- spin_unlock_irq(phba->host->host_lock);
- } else {
- lpfc_els_handle_rscn(phba);
+ lpfc_can_disctmo(phba);
+ if (phba->fc_flag & FC_RSCN_MODE) {
+ /*
+ * Check to see if more RSCNs came in while
+ * we were processing this one.
+ */
+ if ((phba->fc_rscn_id_cnt == 0) &&
+ (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
+ spin_lock_irq(phba->host->host_lock);
+ phba->fc_flag &= ~FC_RSCN_MODE;
+ spin_unlock_irq(phba->host->host_lock);
+ } else {
+ lpfc_els_handle_rscn(phba);
+ }
}
}
}
@@ -1263,7 +1260,7 @@ lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
psli = &phba->sli;
pring = &psli->ring[LPFC_ELS_RING];
- cmdsize = 2 * (sizeof (uint32_t) + sizeof (struct lpfc_name));
+ cmdsize = (2 * sizeof (uint32_t)) + sizeof (struct lpfc_name);
elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
ndlp->nlp_DID, ELS_CMD_LOGO);
if (!elsiocb)
@@ -1451,22 +1448,23 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp)
* PLOGIs to be sent
*/
lpfc_more_plogi(phba);
- }
- if (phba->num_disc_nodes == 0) {
- phba->fc_flag &= ~FC_NDISC_ACTIVE;
- lpfc_can_disctmo(phba);
- if (phba->fc_flag & FC_RSCN_MODE) {
- /* Check to see if more RSCNs
- * came in while we were
- * processing this one.
- */
- if((phba->fc_rscn_id_cnt==0) &&
- (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
- phba->fc_flag &= ~FC_RSCN_MODE;
- }
- else {
- lpfc_els_handle_rscn(phba);
+ if (phba->num_disc_nodes == 0) {
+ phba->fc_flag &= ~FC_NDISC_ACTIVE;
+ lpfc_can_disctmo(phba);
+ if (phba->fc_flag & FC_RSCN_MODE) {
+ /*
+ * Check to see if more RSCNs
+ * came in while we were
+ * processing this one.
+ */
+ if((phba->fc_rscn_id_cnt==0) &&
+ !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
+ phba->fc_flag &= ~FC_RSCN_MODE;
+ }
+ else {
+ lpfc_els_handle_rscn(phba);
+ }
}
}
}
@@ -1872,9 +1870,6 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
if (mbox) {
if ((rspiocb->iocb.ulpStatus == 0)
&& (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
- /* set_slim mailbox command needs to execute first,
- * queue this command to be processed later.
- */
lpfc_unreg_rpi(phba, ndlp);
mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
mbox->context2 = ndlp;
@@ -1920,6 +1915,7 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
uint8_t *pcmd;
uint16_t cmdsize;
int rc;
+ ELS_PKT *els_pkt_ptr;
psli = &phba->sli;
pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
@@ -1958,6 +1954,23 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
pcmd += sizeof (uint32_t);
memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
break;
+ case ELS_CMD_PRLO:
+ cmdsize = sizeof (uint32_t) + sizeof (PRLO);
+ elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
+ ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
+ if (!elsiocb)
+ return 1;
+
+ icmd = &elsiocb->iocb;
+ icmd->ulpContext = oldcmd->ulpContext; /* Xri */
+ pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+
+ memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
+ sizeof (uint32_t) + sizeof (PRLO));
+ *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
+ els_pkt_ptr = (ELS_PKT *) pcmd;
+ els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
+ break;
default:
return 1;
}
@@ -2498,7 +2511,7 @@ lpfc_els_rcv_rscn(struct lpfc_hba * phba,
/* If we are about to begin discovery, just ACC the RSCN.
* Discovery processing will satisfy it.
*/
- if (phba->hba_state < LPFC_NS_QRY) {
+ if (phba->hba_state <= LPFC_NS_QRY) {
lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
newnode);
return 0;
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 6721e679df6..adb086009ae 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -311,8 +311,8 @@ lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
evtp->evt_arg2 = arg2;
evtp->evt = evt;
- list_add_tail(&evtp->evt_listp, &phba->work_list);
spin_lock_irq(phba->host->host_lock);
+ list_add_tail(&evtp->evt_listp, &phba->work_list);
if (phba->work_wait)
wake_up(phba->work_wait);
spin_unlock_irq(phba->host->host_lock);
@@ -1071,10 +1071,6 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
/* initialize static port data */
rport->maxframe_size = ndlp->nlp_maxframe;
rport->supported_classes = ndlp->nlp_class_sup;
- if ((rport->scsi_target_id != -1) &&
- (rport->scsi_target_id < MAX_FCP_TARGET)) {
- ndlp->nlp_sid = rport->scsi_target_id;
- }
rdata = rport->dd_data;
rdata->pnode = ndlp;
@@ -1087,6 +1083,10 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN)
fc_remote_port_rolechg(rport, rport_ids.roles);
+ if ((rport->scsi_target_id != -1) &&
+ (rport->scsi_target_id < MAX_FCP_TARGET)) {
+ ndlp->nlp_sid = rport->scsi_target_id;
+ }
return;
}
@@ -1238,6 +1238,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
evt_listp);
}
+ nlp->nlp_flag &= ~NLP_NODEV_REMOVE;
nlp->nlp_type |= NLP_FC_NODE;
break;
case NLP_MAPPED_LIST:
@@ -1258,6 +1259,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
evt_listp);
}
+ nlp->nlp_flag &= ~NLP_NODEV_REMOVE;
break;
case NLP_NPR_LIST:
nlp->nlp_flag |= list;
@@ -1402,6 +1404,8 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba,
if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi)
return 1;
case CMD_ELS_REQUEST64_CR:
+ if (icmd->un.elsreq64.remoteID == ndlp->nlp_DID)
+ return 1;
case CMD_XMIT_ELS_RSP64_CX:
if (iocb->context1 == (uint8_t *) ndlp)
return 1;
@@ -1901,10 +1905,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
*/
if (ndlp->nlp_flag & NLP_DELAY_TMO)
lpfc_cancel_retry_delay_tmo(phba, ndlp);
- } else {
- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+ } else
ndlp = NULL;
- }
} else {
flg = ndlp->nlp_flag & NLP_LIST_MASK;
if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST))
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 54d04188f7c..eedf9880136 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -449,6 +449,7 @@ struct serv_parm { /* Structure is in Big Endian format */
#define ELS_CMD_RRQ 0x12000000
#define ELS_CMD_PRLI 0x20100014
#define ELS_CMD_PRLO 0x21100014
+#define ELS_CMD_PRLO_ACC 0x02100014
#define ELS_CMD_PDISC 0x50000000
#define ELS_CMD_FDISC 0x51000000
#define ELS_CMD_ADISC 0x52000000
@@ -484,6 +485,7 @@ struct serv_parm { /* Structure is in Big Endian format */
#define ELS_CMD_RRQ 0x12
#define ELS_CMD_PRLI 0x14001020
#define ELS_CMD_PRLO 0x14001021
+#define ELS_CMD_PRLO_ACC 0x14001002
#define ELS_CMD_PDISC 0x50
#define ELS_CMD_FDISC 0x51
#define ELS_CMD_ADISC 0x52
@@ -1539,6 +1541,7 @@ typedef struct {
#define FLAGS_TOPOLOGY_FAILOVER 0x0400 /* Bit 10 */
#define FLAGS_LINK_SPEED 0x0800 /* Bit 11 */
+#define FLAGS_IMED_ABORT 0x04000 /* Bit 14 */
uint32_t link_speed;
#define LINK_SPEED_AUTO 0 /* Auto selection */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 66d5d003555..908d0f27706 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -294,15 +294,6 @@ lpfc_config_port_post(struct lpfc_hba * phba)
}
}
- /* This should turn on DELAYED ABTS for ELS timeouts */
- lpfc_set_slim(phba, pmb, 0x052198, 0x1);
- if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
- phba->hba_state = LPFC_HBA_ERROR;
- mempool_free( pmb, phba->mbox_mem_pool);
- return -EIO;
- }
-
-
lpfc_read_config(phba, pmb);
if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
lpfc_printf_log(phba,
@@ -804,7 +795,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
int max_speed;
char * ports;
char * bus;
- } m;
+ } m = {"<Unknown>", 0, "", ""};
pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
ports = (hdrtype == 0x80) ? "2-port " : "";
@@ -1627,7 +1618,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
error = lpfc_alloc_sysfs_attr(phba);
if (error)
- goto out_kthread_stop;
+ goto out_remove_host;
error = request_irq(phba->pcidev->irq, lpfc_intr_handler, SA_SHIRQ,
LPFC_DRIVER_NAME, phba);
@@ -1644,8 +1635,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
error = lpfc_sli_hba_setup(phba);
- if (error)
+ if (error) {
+ error = -ENODEV;
goto out_free_irq;
+ }
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
spin_lock_irq(phba->host->host_lock);
@@ -1700,6 +1693,9 @@ out_free_irq:
free_irq(phba->pcidev->irq, phba);
out_free_sysfs_attr:
lpfc_free_sysfs_attr(phba);
+out_remove_host:
+ fc_remove_host(phba->host);
+ scsi_remove_host(phba->host);
out_kthread_stop:
kthread_stop(phba->worker_thread);
out_free_iocbq:
@@ -1721,12 +1717,14 @@ out_iounmap_slim:
out_idr_remove:
idr_remove(&lpfc_hba_index, phba->brd_no);
out_put_host:
+ phba->host = NULL;
scsi_host_put(host);
out_release_regions:
pci_release_regions(pdev);
out_disable_device:
pci_disable_device(pdev);
out:
+ pci_set_drvdata(pdev, NULL);
return error;
}
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index c585e2b2e58..e42f22aaf71 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -200,6 +200,9 @@ lpfc_init_link(struct lpfc_hba * phba,
break;
}
+ /* Enable asynchronous ABTS responses from firmware */
+ mb->un.varInitLnk.link_flags |= FLAGS_IMED_ABORT;
+
/* NEW_FEATURE
* Setting up the link speed
*/
@@ -292,36 +295,6 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint32_t did, LPFC_MBOXQ_t * pmb)
return;
}
-/***********************************************/
-
-/* command to write slim */
-/***********************************************/
-void
-lpfc_set_slim(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint32_t addr,
- uint32_t value)
-{
- MAILBOX_t *mb;
-
- mb = &pmb->mb;
- memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
-
- /* addr = 0x090597 is AUTO ABTS disable for ELS commands */
- /* addr = 0x052198 is DELAYED ABTS enable for ELS commands */
-
- /*
- * Always turn on DELAYED ABTS for ELS timeouts
- */
- if ((addr == 0x052198) && (value == 0))
- value = 1;
-
- mb->un.varWords[0] = addr;
- mb->un.varWords[1] = value;
-
- mb->mbxCommand = MBX_SET_SLIM;
- mb->mbxOwner = OWN_HOST;
- return;
-}
-
/**********************************************/
/* lpfc_read_nv Issue a READ CONFIG */
/* mailbox command */
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 3d77bd999b7..27d60ad897c 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -465,14 +465,18 @@ lpfc_rcv_padisc(struct lpfc_hba * phba,
static int
lpfc_rcv_logo(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp,
- struct lpfc_iocbq *cmdiocb)
+ struct lpfc_iocbq *cmdiocb,
+ uint32_t els_cmd)
{
/* Put ndlp on NPR list with 1 sec timeout for plogi, ACC logo */
/* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
* PLOGIs during LOGO storms from a device.
*/
ndlp->nlp_flag |= NLP_LOGO_ACC;
- lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+ if (els_cmd == ELS_CMD_PRLO)
+ lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
+ else
+ lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
if (!(ndlp->nlp_type & NLP_FABRIC) ||
(ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
@@ -681,7 +685,7 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba,
/* software abort outstanding PLOGI */
lpfc_els_abort(phba, ndlp, 1);
- lpfc_rcv_logo(phba, ndlp, cmdiocb);
+ lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
@@ -788,10 +792,6 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
if (lpfc_reg_login
(phba, irsp->un.elsreq64.remoteID,
(uint8_t *) sp, mbox, 0) == 0) {
- /* set_slim mailbox command needs to
- * execute first, queue this command to
- * be processed later.
- */
switch (ndlp->nlp_DID) {
case NameServer_DID:
mbox->mbox_cmpl =
@@ -832,11 +832,17 @@ static uint32_t
lpfc_device_rm_plogi_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
{
- /* software abort outstanding PLOGI */
- lpfc_els_abort(phba, ndlp, 1);
+ if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+ ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+ return ndlp->nlp_state;
+ }
+ else {
+ /* software abort outstanding PLOGI */
+ lpfc_els_abort(phba, ndlp, 1);
- lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
- return NLP_STE_FREED_NODE;
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+ return NLP_STE_FREED_NODE;
+ }
}
static uint32_t
@@ -851,7 +857,7 @@ lpfc_device_recov_plogi_issue(struct lpfc_hba * phba,
ndlp->nlp_state = NLP_STE_NPR_NODE;
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
spin_lock_irq(phba->host->host_lock);
- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+ ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
spin_unlock_irq(phba->host->host_lock);
return ndlp->nlp_state;
@@ -905,7 +911,7 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
/* software abort outstanding ADISC */
lpfc_els_abort(phba, ndlp, 0);
- lpfc_rcv_logo(phba, ndlp, cmdiocb);
+ lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
@@ -932,7 +938,7 @@ lpfc_rcv_prlo_adisc_issue(struct lpfc_hba * phba,
cmdiocb = (struct lpfc_iocbq *) arg;
/* Treat like rcv logo */
- lpfc_rcv_logo(phba, ndlp, cmdiocb);
+ lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
return ndlp->nlp_state;
}
@@ -987,11 +993,17 @@ lpfc_device_rm_adisc_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
{
- /* software abort outstanding ADISC */
- lpfc_els_abort(phba, ndlp, 1);
+ if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+ ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+ return ndlp->nlp_state;
+ }
+ else {
+ /* software abort outstanding ADISC */
+ lpfc_els_abort(phba, ndlp, 1);
- lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
- return NLP_STE_FREED_NODE;
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+ return NLP_STE_FREED_NODE;
+ }
}
static uint32_t
@@ -1006,7 +1018,7 @@ lpfc_device_recov_adisc_issue(struct lpfc_hba * phba,
ndlp->nlp_state = NLP_STE_NPR_NODE;
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
spin_lock_irq(phba->host->host_lock);
- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+ ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
ndlp->nlp_flag |= NLP_NPR_ADISC;
spin_unlock_irq(phba->host->host_lock);
@@ -1048,7 +1060,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
cmdiocb = (struct lpfc_iocbq *) arg;
- lpfc_rcv_logo(phba, ndlp, cmdiocb);
+ lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
@@ -1073,7 +1085,7 @@ lpfc_rcv_prlo_reglogin_issue(struct lpfc_hba * phba,
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
- lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+ lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
return ndlp->nlp_state;
}
@@ -1133,8 +1145,14 @@ lpfc_device_rm_reglogin_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
{
- lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
- return NLP_STE_FREED_NODE;
+ if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+ ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+ return ndlp->nlp_state;
+ }
+ else {
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+ return NLP_STE_FREED_NODE;
+ }
}
static uint32_t
@@ -1146,7 +1164,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba,
ndlp->nlp_state = NLP_STE_NPR_NODE;
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
spin_lock_irq(phba->host->host_lock);
- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+ ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
spin_unlock_irq(phba->host->host_lock);
return ndlp->nlp_state;
}
@@ -1186,7 +1204,7 @@ lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba,
/* Software abort outstanding PRLI before sending acc */
lpfc_els_abort(phba, ndlp, 1);
- lpfc_rcv_logo(phba, ndlp, cmdiocb);
+ lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
@@ -1214,7 +1232,7 @@ lpfc_rcv_prlo_prli_issue(struct lpfc_hba * phba,
struct lpfc_iocbq *cmdiocb;
cmdiocb = (struct lpfc_iocbq *) arg;
- lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+ lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
return ndlp->nlp_state;
}
@@ -1278,11 +1296,17 @@ static uint32_t
lpfc_device_rm_prli_issue(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
{
- /* software abort outstanding PRLI */
- lpfc_els_abort(phba, ndlp, 1);
+ if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+ ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+ return ndlp->nlp_state;
+ }
+ else {
+ /* software abort outstanding PLOGI */
+ lpfc_els_abort(phba, ndlp, 1);
- lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
- return NLP_STE_FREED_NODE;
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+ return NLP_STE_FREED_NODE;
+ }
}
@@ -1313,7 +1337,7 @@ lpfc_device_recov_prli_issue(struct lpfc_hba * phba,
ndlp->nlp_state = NLP_STE_NPR_NODE;
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
spin_lock_irq(phba->host->host_lock);
- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+ ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
spin_unlock_irq(phba->host->host_lock);
return ndlp->nlp_state;
}
@@ -1351,7 +1375,7 @@ lpfc_rcv_logo_unmap_node(struct lpfc_hba * phba,
cmdiocb = (struct lpfc_iocbq *) arg;
- lpfc_rcv_logo(phba, ndlp, cmdiocb);
+ lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
@@ -1375,7 +1399,7 @@ lpfc_rcv_prlo_unmap_node(struct lpfc_hba * phba,
cmdiocb = (struct lpfc_iocbq *) arg;
- lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+ lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
return ndlp->nlp_state;
}
@@ -1386,7 +1410,7 @@ lpfc_device_recov_unmap_node(struct lpfc_hba * phba,
ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;
ndlp->nlp_state = NLP_STE_NPR_NODE;
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+ ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
lpfc_disc_set_adisc(phba, ndlp);
return ndlp->nlp_state;
@@ -1424,7 +1448,7 @@ lpfc_rcv_logo_mapped_node(struct lpfc_hba * phba,
cmdiocb = (struct lpfc_iocbq *) arg;
- lpfc_rcv_logo(phba, ndlp, cmdiocb);
+ lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
@@ -1456,7 +1480,7 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_hba * phba,
spin_unlock_irq(phba->host->host_lock);
/* Treat like rcv logo */
- lpfc_rcv_logo(phba, ndlp, cmdiocb);
+ lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
return ndlp->nlp_state;
}
@@ -1469,7 +1493,7 @@ lpfc_device_recov_mapped_node(struct lpfc_hba * phba,
ndlp->nlp_state = NLP_STE_NPR_NODE;
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
spin_lock_irq(phba->host->host_lock);
- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+ ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
spin_unlock_irq(phba->host->host_lock);
lpfc_disc_set_adisc(phba, ndlp);
return ndlp->nlp_state;
@@ -1551,7 +1575,7 @@ lpfc_rcv_logo_npr_node(struct lpfc_hba * phba,
cmdiocb = (struct lpfc_iocbq *) arg;
- lpfc_rcv_logo(phba, ndlp, cmdiocb);
+ lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
return ndlp->nlp_state;
}
@@ -1617,9 +1641,16 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb, *rspiocb;
+ IOCB_t *irsp;
cmdiocb = (struct lpfc_iocbq *) arg;
rspiocb = cmdiocb->context_un.rsp_iocb;
+
+ irsp = &rspiocb->iocb;
+ if (irsp->ulpStatus) {
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+ return NLP_STE_FREED_NODE;
+ }
return ndlp->nlp_state;
}
@@ -1628,9 +1659,16 @@ lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
{
struct lpfc_iocbq *cmdiocb, *rspiocb;
+ IOCB_t *irsp;
cmdiocb = (struct lpfc_iocbq *) arg;
rspiocb = cmdiocb->context_un.rsp_iocb;
+
+ irsp = &rspiocb->iocb;
+ if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+ return NLP_STE_FREED_NODE;
+ }
return ndlp->nlp_state;
}
@@ -1649,9 +1687,16 @@ lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba,
uint32_t evt)
{
struct lpfc_iocbq *cmdiocb, *rspiocb;
+ IOCB_t *irsp;
cmdiocb = (struct lpfc_iocbq *) arg;
rspiocb = cmdiocb->context_un.rsp_iocb;
+
+ irsp = &rspiocb->iocb;
+ if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+ return NLP_STE_FREED_NODE;
+ }
return ndlp->nlp_state;
}
@@ -1668,7 +1713,12 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba,
if (!mb->mbxStatus)
ndlp->nlp_rpi = mb->un.varWords[0];
-
+ else {
+ if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+ return NLP_STE_FREED_NODE;
+ }
+ }
return ndlp->nlp_state;
}
@@ -1677,6 +1727,10 @@ lpfc_device_rm_npr_node(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, void *arg,
uint32_t evt)
{
+ if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+ ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+ return ndlp->nlp_state;
+ }
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
return NLP_STE_FREED_NODE;
}
@@ -1687,7 +1741,7 @@ lpfc_device_recov_npr_node(struct lpfc_hba * phba,
uint32_t evt)
{
spin_lock_irq(phba->host->host_lock);
- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+ ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
spin_unlock_irq(phba->host->host_lock);
if (ndlp->nlp_flag & NLP_DELAY_TMO) {
lpfc_cancel_retry_delay_tmo(phba, ndlp);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index f9379987372..7dc4c2e6bed 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -629,8 +629,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
struct lpfc_iocbq *piocbq;
IOCB_t *piocb;
struct fcp_cmnd *fcp_cmnd;
- struct scsi_device *scsi_dev = lpfc_cmd->pCmd->device;
- struct lpfc_rport_data *rdata = scsi_dev->hostdata;
+ struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
struct lpfc_nodelist *ndlp = rdata->pnode;
if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
@@ -665,56 +664,18 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
piocb->ulpTimeout = lpfc_cmd->timeout;
}
- lpfc_cmd->rdata = rdata;
-
- switch (task_mgmt_cmd) {
- case FCP_LUN_RESET:
- /* Issue LUN Reset to TGT <num> LUN <num> */
- lpfc_printf_log(phba,
- KERN_INFO,
- LOG_FCP,
- "%d:0703 Issue LUN Reset to TGT %d LUN %d "
- "Data: x%x x%x\n",
- phba->brd_no,
- scsi_dev->id, scsi_dev->lun,
- ndlp->nlp_rpi, ndlp->nlp_flag);
-
- break;
- case FCP_ABORT_TASK_SET:
- /* Issue Abort Task Set to TGT <num> LUN <num> */
- lpfc_printf_log(phba,
- KERN_INFO,
- LOG_FCP,
- "%d:0701 Issue Abort Task Set to TGT %d LUN %d "
- "Data: x%x x%x\n",
- phba->brd_no,
- scsi_dev->id, scsi_dev->lun,
- ndlp->nlp_rpi, ndlp->nlp_flag);
-
- break;
- case FCP_TARGET_RESET:
- /* Issue Target Reset to TGT <num> */
- lpfc_printf_log(phba,
- KERN_INFO,
- LOG_FCP,
- "%d:0702 Issue Target Reset to TGT %d "
- "Data: x%x x%x\n",
- phba->brd_no,
- scsi_dev->id, ndlp->nlp_rpi,
- ndlp->nlp_flag);
- break;
- }
-
return (1);
}
static int
-lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba)
+lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
+ unsigned tgt_id, struct lpfc_rport_data *rdata)
{
struct lpfc_iocbq *iocbq;
struct lpfc_iocbq *iocbqrsp;
int ret;
+ lpfc_cmd->rdata = rdata;
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_TARGET_RESET);
if (!ret)
return FAILED;
@@ -726,6 +687,13 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba)
if (!iocbqrsp)
return FAILED;
+ /* Issue Target Reset to TGT <num> */
+ lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+ "%d:0702 Issue Target Reset to TGT %d "
+ "Data: x%x x%x\n",
+ phba->brd_no, tgt_id, rdata->pnode->nlp_rpi,
+ rdata->pnode->nlp_flag);
+
ret = lpfc_sli_issue_iocb_wait(phba,
&phba->sli.ring[phba->sli.fcp_ring],
iocbq, iocbqrsp, lpfc_cmd->timeout);
@@ -1021,6 +989,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
lpfc_cmd->pCmd = cmnd;
lpfc_cmd->timeout = 60;
lpfc_cmd->scsi_hba = phba;
+ lpfc_cmd->rdata = rdata;
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_LUN_RESET);
if (!ret)
@@ -1033,6 +1002,11 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
if (iocbqrsp == NULL)
goto out_free_scsi_buf;
+ lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+ "%d:0703 Issue LUN Reset to TGT %d LUN %d "
+ "Data: x%x x%x\n", phba->brd_no, cmnd->device->id,
+ cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
+
ret = lpfc_sli_issue_iocb_wait(phba,
&phba->sli.ring[phba->sli.fcp_ring],
iocbq, iocbqrsp, lpfc_cmd->timeout);
@@ -1104,7 +1078,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
int match;
int ret = FAILED, i, err_count = 0;
int cnt, loopcnt;
- unsigned int midlayer_id = 0;
struct lpfc_scsi_buf * lpfc_cmd;
lpfc_block_requests(phba);
@@ -1124,7 +1097,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
* targets known to the driver. Should any target reset
* fail, this routine returns failure to the midlayer.
*/
- midlayer_id = cmnd->device->id;
for (i = 0; i < MAX_FCP_TARGET; i++) {
/* Search the mapped list for this target ID */
match = 0;
@@ -1137,9 +1109,8 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
if (!match)
continue;
- lpfc_cmd->pCmd->device->id = i;
- lpfc_cmd->pCmd->device->hostdata = ndlp->rport->dd_data;
- ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba);
+ ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba,
+ i, ndlp->rport->dd_data);
if (ret != SUCCESS) {
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0713 Bus Reset on target %d failed\n",
@@ -1158,7 +1129,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
* the targets. Unfortunately, some targets do not abide by
* this forcing the driver to double check.
*/
- cmnd->device->id = midlayer_id;
cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
0, 0, LPFC_CTX_HOST);
if (cnt)
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 4cf1366108b..6b737568b83 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.1.4"
+#define LPFC_DRIVER_VERSION "8.1.6"
#define LPFC_DRIVER_NAME "lpfc"
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 7144674bc8e..de35ffe2f79 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -45,6 +45,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/dma-mapping.h>
#include <scsi/scsicam.h>
#include "scsi.h"
@@ -2094,7 +2095,7 @@ make_local_pdev(adapter_t *adapter, struct pci_dev **pdev)
memcpy(*pdev, adapter->dev, sizeof(struct pci_dev));
- if( pci_set_dma_mask(*pdev, 0xffffffff) != 0 ) {
+ if( pci_set_dma_mask(*pdev, DMA_32BIT_MASK) != 0 ) {
kfree(*pdev);
return -1;
}
@@ -4470,7 +4471,6 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
{
Scsi_Cmnd *scmd;
struct scsi_device *sdev;
- unsigned long flags = 0;
scb_t *scb;
int rval;
@@ -4859,10 +4859,10 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Set the Mode of addressing to 64 bit if we can */
if ((adapter->flag & BOARD_64BIT) && (sizeof(dma_addr_t) == 8)) {
- pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+ pci_set_dma_mask(pdev, DMA_64BIT_MASK);
adapter->has_64bit_addr = 1;
} else {
- pci_set_dma_mask(pdev, 0xffffffff);
+ pci_set_dma_mask(pdev, DMA_32BIT_MASK);
adapter->has_64bit_addr = 0;
}
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index c11e5ce6865..bec1424eda8 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -10,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*
* FILE : megaraid_mbox.c
- * Version : v2.20.4.7 (Nov 14 2005)
+ * Version : v2.20.4.8 (Apr 11 2006)
*
* Authors:
* Atul Mukker <Atul.Mukker@lsil.com>
@@ -2278,6 +2278,7 @@ megaraid_mbox_dpc(unsigned long devp)
unsigned long flags;
uint8_t c;
int status;
+ uioc_t *kioc;
if (!adapter) return;
@@ -2320,6 +2321,9 @@ megaraid_mbox_dpc(unsigned long devp)
// remove from local clist
list_del_init(&scb->list);
+ kioc = (uioc_t *)scb->gp;
+ kioc->status = 0;
+
megaraid_mbox_mm_done(adapter, scb);
continue;
@@ -2636,6 +2640,7 @@ megaraid_reset_handler(struct scsi_cmnd *scp)
int recovery_window;
int recovering;
int i;
+ uioc_t *kioc;
adapter = SCP2ADAPTER(scp);
raid_dev = ADAP2RAIDDEV(adapter);
@@ -2655,32 +2660,51 @@ megaraid_reset_handler(struct scsi_cmnd *scp)
// Also, reset all the commands currently owned by the driver
spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) {
-
list_del_init(&scb->list); // from pending list
- con_log(CL_ANN, (KERN_WARNING
- "megaraid: %ld:%d[%d:%d], reset from pending list\n",
- scp->serial_number, scb->sno,
- scb->dev_channel, scb->dev_target));
+ if (scb->sno >= MBOX_MAX_SCSI_CMDS) {
+ con_log(CL_ANN, (KERN_WARNING
+ "megaraid: IOCTL packet with %d[%d:%d] being reset\n",
+ scb->sno, scb->dev_channel, scb->dev_target));
- scp->result = (DID_RESET << 16);
- scp->scsi_done(scp);
+ scb->status = -1;
- megaraid_dealloc_scb(adapter, scb);
+ kioc = (uioc_t *)scb->gp;
+ kioc->status = -EFAULT;
+
+ megaraid_mbox_mm_done(adapter, scb);
+ } else {
+ if (scb->scp == scp) { // Found command
+ con_log(CL_ANN, (KERN_WARNING
+ "megaraid: %ld:%d[%d:%d], reset from pending list\n",
+ scp->serial_number, scb->sno,
+ scb->dev_channel, scb->dev_target));
+ } else {
+ con_log(CL_ANN, (KERN_WARNING
+ "megaraid: IO packet with %d[%d:%d] being reset\n",
+ scb->sno, scb->dev_channel, scb->dev_target));
+ }
+
+ scb->scp->result = (DID_RESET << 16);
+ scb->scp->scsi_done(scb->scp);
+
+ megaraid_dealloc_scb(adapter, scb);
+ }
}
spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
if (adapter->outstanding_cmds) {
con_log(CL_ANN, (KERN_NOTICE
"megaraid: %d outstanding commands. Max wait %d sec\n",
- adapter->outstanding_cmds, MBOX_RESET_WAIT));
+ adapter->outstanding_cmds,
+ (MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT)));
}
recovery_window = MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
recovering = adapter->outstanding_cmds;
- for (i = 0; i < recovery_window && adapter->outstanding_cmds; i++) {
+ for (i = 0; i < recovery_window; i++) {
megaraid_ack_sequence(adapter);
@@ -2689,12 +2713,11 @@ megaraid_reset_handler(struct scsi_cmnd *scp)
con_log(CL_ANN, (
"megaraid mbox: Wait for %d commands to complete:%d\n",
adapter->outstanding_cmds,
- MBOX_RESET_WAIT - i));
+ (MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT) - i));
}
// bailout if no recovery happended in reset time
- if ((i == MBOX_RESET_WAIT) &&
- (recovering == adapter->outstanding_cmds)) {
+ if (adapter->outstanding_cmds == 0) {
break;
}
@@ -2918,12 +2941,13 @@ mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
wmb();
WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
- for (i = 0; i < 0xFFFFF; i++) {
+ for (i = 0; i < MBOX_SYNC_WAIT_CNT; i++) {
if (mbox->numstatus != 0xFF) break;
rmb();
+ udelay(MBOX_SYNC_DELAY_200);
}
- if (i == 0xFFFFF) {
+ if (i == MBOX_SYNC_WAIT_CNT) {
// We may need to re-calibrate the counter
con_log(CL_ANN, (KERN_CRIT
"megaraid: fast sync command timed out\n"));
@@ -3475,7 +3499,7 @@ megaraid_cmm_register(adapter_t *adapter)
adp.drvr_data = (unsigned long)adapter;
adp.pdev = adapter->pdev;
adp.issue_uioc = megaraid_mbox_mm_handler;
- adp.timeout = 300;
+ adp.timeout = MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
adp.max_kioc = MBOX_MAX_USER_CMDS;
if ((rval = mraid_mm_register_adp(&adp)) != 0) {
@@ -3702,7 +3726,6 @@ megaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb)
unsigned long flags;
kioc = (uioc_t *)scb->gp;
- kioc->status = 0;
mbox64 = (mbox64_t *)(unsigned long)kioc->cmdbuf;
mbox64->mbox32.status = scb->status;
raw_mbox = (uint8_t *)&mbox64->mbox32;
diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
index 882fb1a0b57..868fb0ec93e 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.h
+++ b/drivers/scsi/megaraid/megaraid_mbox.h
@@ -21,8 +21,8 @@
#include "megaraid_ioctl.h"
-#define MEGARAID_VERSION "2.20.4.7"
-#define MEGARAID_EXT_VERSION "(Release Date: Mon Nov 14 12:27:22 EST 2005)"
+#define MEGARAID_VERSION "2.20.4.8"
+#define MEGARAID_EXT_VERSION "(Release Date: Mon Apr 11 12:27:22 EST 2006)"
/*
@@ -100,6 +100,9 @@
#define MBOX_BUSY_WAIT 10 // max usec to wait for busy mailbox
#define MBOX_RESET_WAIT 180 // wait these many seconds in reset
#define MBOX_RESET_EXT_WAIT 120 // extended wait reset
+#define MBOX_SYNC_WAIT_CNT 0xFFFF // wait loop index for synchronous mode
+
+#define MBOX_SYNC_DELAY_200 200 // 200 micro-seconds
/*
* maximum transfer that can happen through the firmware commands issued
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index 8f3ce043229..e8f534fb336 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -898,10 +898,8 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
adapter = kmalloc(sizeof(mraid_mmadp_t), GFP_KERNEL);
- if (!adapter) {
- rval = -ENOMEM;
- goto memalloc_error;
- }
+ if (!adapter)
+ return -ENOMEM;
memset(adapter, 0, sizeof(mraid_mmadp_t));
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index d6d2125f904..f852421002e 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1748,7 +1748,7 @@ static int mesh_host_reset(struct scsi_cmnd *cmd)
static void set_mesh_power(struct mesh_state *ms, int state)
{
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return;
if (state) {
pmac_call_feature(PMAC_FTR_MESH_ENABLE, macio_get_of_node(ms->mdev), 0, 1);
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index a279ebb6144..30ee0ef4b45 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -38,6 +38,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ctype.h>
+#include <linux/dma-mapping.h>
#include <asm/dma.h>
#include <asm/system.h>
@@ -2776,7 +2777,7 @@ static int nsp32_detect(struct scsi_host_template *sht)
/*
* setup DMA
*/
- if (pci_set_dma_mask(PCIDEV, 0xffffffffUL) != 0) {
+ if (pci_set_dma_mask(PCIDEV, DMA_32BIT_MASK) != 0) {
nsp32_msg (KERN_ERR, "failed to set PCI DMA mask");
goto scsi_unregister;
}
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 66ea47a9c53..e3bd4bc339f 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -49,6 +49,7 @@ static const char * osst_version = "0.99.4";
#include <linux/blkdev.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
+#include <linux/jiffies.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
#include <asm/system.h>
@@ -856,7 +857,7 @@ static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt
) && result >= 0)
{
#if DEBUG
- if (debugging || jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC)
+ if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
printk (OSST_DEB_MSG
"%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
name, curr, curr+minlast, STp->first_frame_position,
@@ -867,7 +868,7 @@ static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt
return 0;
}
#if DEBUG
- if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC && notyetprinted)
+ if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
{
printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
name, curr, curr+minlast, STp->first_frame_position,
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 5609847e254..ee449b29fc8 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -89,29 +89,29 @@ MODULE_LICENSE("Dual MPL/GPL");
/*====================================================================*/
typedef struct scsi_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct Scsi_Host *host;
} scsi_info_t;
-static void aha152x_release_cs(dev_link_t *link);
+static void aha152x_release_cs(struct pcmcia_device *link);
static void aha152x_detach(struct pcmcia_device *p_dev);
-static void aha152x_config_cs(dev_link_t *link);
+static int aha152x_config_cs(struct pcmcia_device *link);
-static dev_link_t *dev_list;
+static struct pcmcia_device *dev_list;
-static int aha152x_attach(struct pcmcia_device *p_dev)
+static int aha152x_probe(struct pcmcia_device *link)
{
scsi_info_t *info;
- dev_link_t *link;
-
+
DEBUG(0, "aha152x_attach()\n");
/* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) return -ENOMEM;
memset(info, 0, sizeof(*info));
- link = &info->link; link->priv = info;
+ info->p_dev = link;
+ link->priv = info;
link->io.NumPorts1 = 0x20;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -119,41 +119,22 @@ static int aha152x_attach(struct pcmcia_device *p_dev)
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- aha152x_config_cs(link);
-
- return 0;
+ return aha152x_config_cs(link);
} /* aha152x_attach */
/*====================================================================*/
-static void aha152x_detach(struct pcmcia_device *p_dev)
+static void aha152x_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
- dev_link_t **linkp;
-
DEBUG(0, "aha152x_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
- if (link->state & DEV_CONFIG)
- aha152x_release_cs(link);
+ aha152x_release_cs(link);
/* Unlink device structure, free bits */
- *linkp = link->next;
kfree(link->priv);
-
} /* aha152x_detach */
/*====================================================================*/
@@ -161,9 +142,8 @@ static void aha152x_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void aha152x_config_cs(dev_link_t *link)
+static int aha152x_config_cs(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
scsi_info_t *info = link->priv;
struct aha152x_setup s;
tuple_t tuple;
@@ -178,19 +158,16 @@ static void aha152x_config_cs(dev_link_t *link)
tuple.TupleData = tuple_data;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
- /* Configure card */
- link->state |= DEV_CONFIG;
-
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
/* For New Media T&J, look for a SCSI window */
if (parse.cftable_entry.io.win[0].len >= 0x20)
@@ -201,15 +178,15 @@ static void aha152x_config_cs(dev_link_t *link)
if ((parse.cftable_entry.io.nwin > 0) &&
(link->io.BasePort1 < 0xffff)) {
link->conf.ConfigIndex = parse.cftable_entry.index;
- i = pcmcia_request_io(handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/* Set configuration options for the aha152x driver */
memset(&s, 0, sizeof(s));
@@ -231,53 +208,30 @@ static void aha152x_config_cs(dev_link_t *link)
}
sprintf(info->node.dev_name, "scsi%d", host->host_no);
- link->dev = &info->node;
+ link->dev_node = &info->node;
info->host = host;
- link->state &= ~DEV_CONFIG_PENDING;
- return;
-
+ return 0;
+
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
aha152x_release_cs(link);
- return;
+ return -ENODEV;
}
-static void aha152x_release_cs(dev_link_t *link)
+static void aha152x_release_cs(struct pcmcia_device *link)
{
scsi_info_t *info = link->priv;
aha152x_release(info->host);
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
}
-static int aha152x_suspend(struct pcmcia_device *dev)
+static int aha152x_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int aha152x_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
scsi_info_t *info = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- aha152x_host_reset_host(info->host);
- }
+ aha152x_host_reset_host(info->host);
return 0;
}
@@ -297,10 +251,9 @@ static struct pcmcia_driver aha152x_cs_driver = {
.drv = {
.name = "aha152x_cs",
},
- .probe = aha152x_attach,
+ .probe = aha152x_probe,
.remove = aha152x_detach,
.id_table = aha152x_ids,
- .suspend = aha152x_suspend,
.resume = aha152x_resume,
};
@@ -317,4 +270,3 @@ static void __exit exit_aha152x_cs(void)
module_init(init_aha152x_cs);
module_exit(exit_aha152x_cs);
-
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 788c58d805f..85f7ffac19a 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -73,57 +73,48 @@ static char *version =
/*====================================================================*/
typedef struct scsi_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct Scsi_Host *host;
} scsi_info_t;
-static void fdomain_release(dev_link_t *link);
+static void fdomain_release(struct pcmcia_device *link);
static void fdomain_detach(struct pcmcia_device *p_dev);
-static void fdomain_config(dev_link_t *link);
+static int fdomain_config(struct pcmcia_device *link);
-static int fdomain_attach(struct pcmcia_device *p_dev)
+static int fdomain_probe(struct pcmcia_device *link)
{
- scsi_info_t *info;
- dev_link_t *link;
-
- DEBUG(0, "fdomain_attach()\n");
-
- /* Create new SCSI device */
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) return -ENOMEM;
- memset(info, 0, sizeof(*info));
- link = &info->link; link->priv = info;
- link->io.NumPorts1 = 0x10;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- link->io.IOAddrLines = 10;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.Present = PRESENT_OPTION;
-
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- fdomain_config(link);
-
- return 0;
+ scsi_info_t *info;
+
+ DEBUG(0, "fdomain_attach()\n");
+
+ /* Create new SCSI device */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->p_dev = link;
+ link->priv = info;
+ link->io.NumPorts1 = 0x10;
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ link->io.IOAddrLines = 10;
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+ link->conf.Attributes = CONF_ENABLE_IRQ;
+ link->conf.IntType = INT_MEMORY_AND_IO;
+ link->conf.Present = PRESENT_OPTION;
+
+ return fdomain_config(link);
} /* fdomain_attach */
/*====================================================================*/
-static void fdomain_detach(struct pcmcia_device *p_dev)
+static void fdomain_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "fdomain_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- fdomain_release(link);
+ fdomain_release(link);
kfree(link->priv);
} /* fdomain_detach */
@@ -133,9 +124,8 @@ static void fdomain_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void fdomain_config(dev_link_t *link)
+static int fdomain_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
scsi_info_t *info = link->priv;
tuple_t tuple;
cisparse_t parse;
@@ -150,103 +140,75 @@ static void fdomain_config(dev_link_t *link)
tuple.TupleData = tuple_data;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
- /* Configure card */
- link->state |= DEV_CONFIG;
-
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
link->conf.ConfigIndex = parse.cftable_entry.index;
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
- i = pcmcia_request_io(handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
-
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+
/* A bad hack... */
release_region(link->io.BasePort1, link->io.NumPorts1);
/* Set configuration options for the fdomain driver */
sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
fdomain_setup(str);
-
+
host = __fdomain_16x0_detect(&fdomain_driver_template);
if (!host) {
printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
goto cs_failed;
}
-
- scsi_add_host(host, NULL); /* XXX handle failure */
+
+ if (scsi_add_host(host, NULL))
+ goto cs_failed;
scsi_scan_host(host);
sprintf(info->node.dev_name, "scsi%d", host->host_no);
- link->dev = &info->node;
+ link->dev_node = &info->node;
info->host = host;
-
- link->state &= ~DEV_CONFIG_PENDING;
- return;
-
+
+ return 0;
+
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
fdomain_release(link);
- return;
-
+ return -ENODEV;
} /* fdomain_config */
/*====================================================================*/
-static void fdomain_release(dev_link_t *link)
+static void fdomain_release(struct pcmcia_device *link)
{
- scsi_info_t *info = link->priv;
+ scsi_info_t *info = link->priv;
- DEBUG(0, "fdomain_release(0x%p)\n", link);
+ DEBUG(0, "fdomain_release(0x%p)\n", link);
- scsi_remove_host(info->host);
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- scsi_unregister(info->host);
-
- link->state &= ~DEV_CONFIG;
+ scsi_remove_host(info->host);
+ pcmcia_disable_device(link);
+ scsi_unregister(info->host);
}
/*====================================================================*/
-static int fdomain_suspend(struct pcmcia_device *dev)
+static int fdomain_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int fdomain_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- fdomain_16x0_bus_reset(NULL);
- }
+ fdomain_16x0_bus_reset(NULL);
return 0;
}
@@ -264,10 +226,9 @@ static struct pcmcia_driver fdomain_cs_driver = {
.drv = {
.name = "fdomain_cs",
},
- .probe = fdomain_attach,
+ .probe = fdomain_probe,
.remove = fdomain_detach,
.id_table = fdomain_ids,
- .suspend = fdomain_suspend,
.resume = fdomain_resume,
};
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 9e3ab3fd535..231f9c311c6 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1593,11 +1593,11 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt)
configure the card at this point -- we wait until we receive a
card insertion event.
======================================================================*/
-static int nsp_cs_attach(struct pcmcia_device *p_dev)
+static int nsp_cs_probe(struct pcmcia_device *link)
{
scsi_info_t *info;
- dev_link_t *link;
nsp_hw_data *data = &nsp_data_base;
+ int ret;
nsp_dbg(NSP_DEBUG_INIT, "in");
@@ -1605,7 +1605,7 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev)
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL) { return -ENOMEM; }
memset(info, 0, sizeof(*info));
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
data->ScsiInfo = info;
@@ -1627,18 +1627,13 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev)
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- nsp_cs_config(link);
+ ret = nsp_cs_config(link);
nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
- return 0;
+ return ret;
} /* nsp_cs_attach */
@@ -1648,16 +1643,12 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev)
structures are freed. Otherwise, the structures will be freed
when the device is released.
======================================================================*/
-static void nsp_cs_detach(struct pcmcia_device *p_dev)
+static void nsp_cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
- if (link->state & DEV_CONFIG) {
- ((scsi_info_t *)link->priv)->stop = 1;
- nsp_cs_release(link);
- }
+ ((scsi_info_t *)link->priv)->stop = 1;
+ nsp_cs_release(link);
kfree(link->priv);
link->priv = NULL;
@@ -1672,9 +1663,9 @@ static void nsp_cs_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
/*====================================================================*/
-static void nsp_cs_config(dev_link_t *link)
+static int nsp_cs_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
+ int ret;
scsi_info_t *info = link->priv;
tuple_t tuple;
cisparse_t parse;
@@ -1698,26 +1689,22 @@ static void nsp_cs_config(dev_link_t *link)
tuple.TupleData = tuple_data;
tuple.TupleDataMax = sizeof(tuple_data);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
+ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { dflt = *cfg; }
@@ -1743,10 +1730,10 @@ static void nsp_cs_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
} else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
}
@@ -1773,7 +1760,7 @@ static void nsp_cs_config(dev_link_t *link)
link->io.NumPorts2 = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
@@ -1788,7 +1775,7 @@ static void nsp_cs_config(dev_link_t *link)
req.Size = 0x1000;
}
req.AccessSpeed = 0;
- if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+ if (pcmcia_request_window(&link, &req, &link->win) != 0)
goto next_entry;
map.Page = 0; map.CardOffset = mem->win[0].card_addr;
if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -1802,17 +1789,14 @@ static void nsp_cs_config(dev_link_t *link)
next_entry:
nsp_dbg(NSP_DEBUG_INIT, "next");
-
- if (link->io.NumPorts1) {
- pcmcia_release_io(link->handle, &link->io);
- }
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ pcmcia_disable_device(link);
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
if (link->conf.Attributes & CONF_ENABLE_IRQ) {
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
}
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
if (free_ports) {
if (link->io.BasePort1) {
@@ -1854,16 +1838,19 @@ static void nsp_cs_config(dev_link_t *link)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
- scsi_add_host (host, NULL);
+ ret = scsi_add_host (host, NULL);
+ if (ret)
+ goto cs_failed;
+
scsi_scan_host(host);
snprintf(info->node.dev_name, sizeof(info->node.dev_name), "scsi%d", host->host_no);
- link->dev = &info->node;
+ link->dev_node = &info->node;
info->host = host;
#else
nsp_dbg(NSP_DEBUG_INIT, "GET_SCSI_INFO");
- tail = &link->dev;
+ tail = &link->dev_node;
info->ndev = 0;
nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
@@ -1908,11 +1895,10 @@ static void nsp_cs_config(dev_link_t *link)
#endif
/* Finally, report what we've done */
- printk(KERN_INFO "nsp_cs: index 0x%02x: Vcc %d.%d",
- link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1) {
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "nsp_cs: index 0x%02x: ",
+ link->conf.ConfigIndex);
+ if (link->conf.Vpp) {
+ printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
}
if (link->conf.Attributes & CONF_ENABLE_IRQ) {
printk(", irq %d", link->irq.AssignedIRQ);
@@ -1929,15 +1915,14 @@ static void nsp_cs_config(dev_link_t *link)
req.Base+req.Size-1);
printk("\n");
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return 0;
cs_failed:
nsp_dbg(NSP_DEBUG_INIT, "config fail");
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
nsp_cs_release(link);
- return;
+ return -ENODEV;
} /* nsp_cs_config */
#undef CS_CHECK
@@ -1947,7 +1932,7 @@ static void nsp_cs_config(dev_link_t *link)
device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed.
======================================================================*/
-static void nsp_cs_release(dev_link_t *link)
+static void nsp_cs_release(struct pcmcia_device *link)
{
scsi_info_t *info = link->priv;
nsp_hw_data *data = NULL;
@@ -1968,22 +1953,15 @@ static void nsp_cs_release(dev_link_t *link)
#else
scsi_unregister_host(&nsp_driver_template);
#endif
- link->dev = NULL;
+ link->dev_node = NULL;
if (link->win) {
if (data != NULL) {
iounmap((void *)(data->MmioAddress));
}
- pcmcia_release_window(link->win);
- }
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1) {
- pcmcia_release_io(link->handle, &link->io);
}
- if (link->irq.AssignedIRQ) {
- pcmcia_release_irq(link->handle, &link->irq);
- }
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2))
if (info->host != NULL) {
scsi_host_put(info->host);
@@ -1991,14 +1969,11 @@ static void nsp_cs_release(dev_link_t *link)
#endif
} /* nsp_cs_release */
-static int nsp_cs_suspend(struct pcmcia_device *dev)
+static int nsp_cs_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
scsi_info_t *info = link->priv;
nsp_hw_data *data;
- link->state |= DEV_SUSPEND;
-
nsp_dbg(NSP_DEBUG_INIT, "event: suspend");
if (info->host != NULL) {
@@ -2011,25 +1986,16 @@ static int nsp_cs_suspend(struct pcmcia_device *dev)
info->stop = 1;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
return 0;
}
-static int nsp_cs_resume(struct pcmcia_device *dev)
+static int nsp_cs_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
scsi_info_t *info = link->priv;
nsp_hw_data *data;
nsp_dbg(NSP_DEBUG_INIT, "event: resume");
- link->state &= ~DEV_SUSPEND;
-
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
-
info->stop = 0;
if (info->host != NULL) {
@@ -2065,7 +2031,7 @@ static struct pcmcia_driver nsp_driver = {
.drv = {
.name = "nsp_cs",
},
- .probe = nsp_cs_attach,
+ .probe = nsp_cs_probe,
.remove = nsp_cs_detach,
.id_table = nsp_cs_ids,
.suspend = nsp_cs_suspend,
@@ -2098,19 +2064,7 @@ static int __init nsp_cs_init(void)
static void __exit nsp_cs_exit(void)
{
nsp_msg(KERN_INFO, "unloading...");
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
pcmcia_unregister_driver(&nsp_driver);
-#else
- unregister_pcmcia_driver(&dev_info);
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG) {
- nsp_cs_release(dev_list);
- }
- nsp_cs_detach(dev_list);
- }
-#endif
}
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index b66b140a745..8908b8e5b78 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -225,7 +225,7 @@
/*====================================================================*/
typedef struct scsi_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
struct Scsi_Host *host;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
dev_node_t node;
@@ -297,8 +297,8 @@ typedef struct _nsp_hw_data {
/* Card service functions */
static void nsp_cs_detach (struct pcmcia_device *p_dev);
-static void nsp_cs_release(dev_link_t *link);
-static void nsp_cs_config (dev_link_t *link);
+static void nsp_cs_release(struct pcmcia_device *link);
+static int nsp_cs_config (struct pcmcia_device *link);
/* Linux SCSI subsystem specific functions */
static struct Scsi_Host *nsp_detect (struct scsi_host_template *sht);
@@ -450,7 +450,7 @@ static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno)
return host;
}
-static void cs_error(client_handle_t handle, int func, int ret)
+static void cs_error(struct pcmcia_device *handle, int func, int ret)
{
error_info_t err = { func, ret };
pcmcia_report_error(handle, &err);
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index dce7e687fd4..86c2ac6ae62 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -91,18 +91,18 @@ static struct scsi_host_template qlogicfas_driver_template = {
/*====================================================================*/
typedef struct scsi_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct Scsi_Host *host;
unsigned short manf_id;
} scsi_info_t;
-static void qlogic_release(dev_link_t *link);
+static void qlogic_release(struct pcmcia_device *link);
static void qlogic_detach(struct pcmcia_device *p_dev);
-static void qlogic_config(dev_link_t * link);
+static int qlogic_config(struct pcmcia_device * link);
static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host,
- dev_link_t *link, int qbase, int qlirq)
+ struct pcmcia_device *link, int qbase, int qlirq)
{
int qltyp; /* type of chip */
int qinitid;
@@ -156,10 +156,9 @@ free_scsi_host:
err:
return NULL;
}
-static int qlogic_attach(struct pcmcia_device *p_dev)
+static int qlogic_probe(struct pcmcia_device *link)
{
scsi_info_t *info;
- dev_link_t *link;
DEBUG(0, "qlogic_attach()\n");
@@ -168,7 +167,7 @@ static int qlogic_attach(struct pcmcia_device *p_dev)
if (!info)
return -ENOMEM;
memset(info, 0, sizeof(*info));
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.NumPorts1 = 16;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -176,30 +175,19 @@ static int qlogic_attach(struct pcmcia_device *p_dev)
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- qlogic_config(link);
-
- return 0;
+ return qlogic_config(link);
} /* qlogic_attach */
/*====================================================================*/
-static void qlogic_detach(struct pcmcia_device *p_dev)
+static void qlogic_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "qlogic_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- qlogic_release(link);
-
+ qlogic_release(link);
kfree(link->priv);
} /* qlogic_detach */
@@ -209,9 +197,8 @@ static void qlogic_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void qlogic_config(dev_link_t * link)
+static int qlogic_config(struct pcmcia_device * link)
{
- client_handle_t handle = link->handle;
scsi_info_t *info = link->priv;
tuple_t tuple;
cisparse_t parse;
@@ -225,38 +212,35 @@ static void qlogic_config(dev_link_t * link)
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
tuple.DesiredTuple = CISTPL_MANFID;
- if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
+ if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS))
info->manf_id = le16_to_cpu(tuple.TupleData[0]);
- /* Configure card */
- link->state |= DEV_CONFIG;
-
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
link->conf.ConfigIndex = parse.cftable_entry.index;
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
if (link->io.BasePort1 != 0) {
- i = pcmcia_request_io(handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
/* set ATAcmd */
@@ -275,82 +259,54 @@ static void qlogic_config(dev_link_t * link)
if (!host) {
printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name);
- goto out;
+ goto cs_failed;
}
sprintf(info->node.dev_name, "scsi%d", host->host_no);
- link->dev = &info->node;
+ link->dev_node = &info->node;
info->host = host;
-out:
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
- link->dev = NULL;
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
- return;
+ cs_error(link, last_fn, last_ret);
+ pcmcia_disable_device(link);
+ return -ENODEV;
} /* qlogic_config */
/*====================================================================*/
-static void qlogic_release(dev_link_t *link)
+static void qlogic_release(struct pcmcia_device *link)
{
scsi_info_t *info = link->priv;
DEBUG(0, "qlogic_release(0x%p)\n", link);
scsi_remove_host(info->host);
- link->dev = NULL;
free_irq(link->irq.AssignedIRQ, info->host);
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
+ pcmcia_disable_device(link);
scsi_host_put(info->host);
-
- link->state &= ~DEV_CONFIG;
}
/*====================================================================*/
-static int qlogic_suspend(struct pcmcia_device *dev)
+static int qlogic_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
+ scsi_info_t *info = link->priv;
-static int qlogic_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- scsi_info_t *info = link->priv;
-
- pcmcia_request_configuration(link->handle, &link->conf);
- if ((info->manf_id == MANFID_MACNICA) ||
- (info->manf_id == MANFID_PIONEER) ||
- (info->manf_id == 0x0098)) {
- outb(0x80, link->io.BasePort1 + 0xd);
- outb(0x24, link->io.BasePort1 + 0x9);
- outb(0x04, link->io.BasePort1 + 0xd);
- }
- /* Ugggglllyyyy!!! */
- qlogicfas408_bus_reset(NULL);
+ pcmcia_request_configuration(link, &link->conf);
+ if ((info->manf_id == MANFID_MACNICA) ||
+ (info->manf_id == MANFID_PIONEER) ||
+ (info->manf_id == 0x0098)) {
+ outb(0x80, link->io.BasePort1 + 0xd);
+ outb(0x24, link->io.BasePort1 + 0x9);
+ outb(0x04, link->io.BasePort1 + 0xd);
}
+ /* Ugggglllyyyy!!! */
+ qlogicfas408_bus_reset(NULL);
return 0;
}
@@ -382,10 +338,9 @@ static struct pcmcia_driver qlogic_cs_driver = {
.drv = {
.name = "qlogic_cs",
},
- .probe = qlogic_attach,
+ .probe = qlogic_probe,
.remove = qlogic_detach,
.id_table = qlogic_ids,
- .suspend = qlogic_suspend,
.resume = qlogic_resume,
};
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 3a4dd6f5b81..9f59827707f 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -202,7 +202,7 @@ static char *version =
/* ================================================================== */
struct scsi_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct Scsi_Host *host;
unsigned short manf_id;
@@ -527,7 +527,7 @@ idle_out:
}
static void
-SYM53C500_release(dev_link_t *link)
+SYM53C500_release(struct pcmcia_device *link)
{
struct scsi_info_t *info = link->priv;
struct Scsi_Host *shost = info->host;
@@ -550,13 +550,7 @@ SYM53C500_release(dev_link_t *link)
if (shost->io_port && shost->n_io_port)
release_region(shost->io_port, shost->n_io_port);
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
scsi_host_put(shost);
} /* SYM53C500_release */
@@ -713,10 +707,9 @@ static struct scsi_host_template sym53c500_driver_template = {
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void
-SYM53C500_config(dev_link_t *link)
+static int
+SYM53C500_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct scsi_info_t *info = link->priv;
tuple_t tuple;
cisparse_t parse;
@@ -733,40 +726,37 @@ SYM53C500_config(dev_link_t *link)
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
tuple.DesiredTuple = CISTPL_MANFID;
- if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
- (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
+ if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
+ (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS))
info->manf_id = le16_to_cpu(tuple.TupleData[0]);
- /* Configure card */
- link->state |= DEV_CONFIG;
-
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
link->conf.ConfigIndex = parse.cftable_entry.index;
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
if (link->io.BasePort1 != 0) {
- i = pcmcia_request_io(handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/*
* That's the trouble with copying liberally from another driver.
@@ -835,7 +825,7 @@ next_entry:
data->fast_pio = USE_FAST_PIO;
sprintf(info->node.dev_name, "scsi%d", host->host_no);
- link->dev = &info->node;
+ link->dev_node = &info->node;
info->host = host;
if (scsi_add_host(host, NULL))
@@ -843,7 +833,7 @@ next_entry:
scsi_scan_host(host);
- goto out; /* SUCCESS */
+ return 0;
err_free_irq:
free_irq(irq_level, host);
@@ -852,74 +842,50 @@ err_free_scsi:
err_release:
release_region(port_base, 0x10);
printk(KERN_INFO "sym53c500_cs: no SCSI devices found\n");
-
-out:
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return -ENODEV;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
SYM53C500_release(link);
- return;
+ return -ENODEV;
} /* SYM53C500_config */
-static int sym53c500_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int sym53c500_resume(struct pcmcia_device *dev)
+static int sym53c500_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
struct scsi_info_t *info = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
-
- /* See earlier comment about manufacturer IDs. */
- if ((info->manf_id == MANFID_MACNICA) ||
- (info->manf_id == MANFID_PIONEER) ||
- (info->manf_id == 0x0098)) {
- outb(0x80, link->io.BasePort1 + 0xd);
- outb(0x24, link->io.BasePort1 + 0x9);
- outb(0x04, link->io.BasePort1 + 0xd);
- }
- /*
- * If things don't work after a "resume",
- * this is a good place to start looking.
- */
- SYM53C500_int_host_reset(link->io.BasePort1);
+ /* See earlier comment about manufacturer IDs. */
+ if ((info->manf_id == MANFID_MACNICA) ||
+ (info->manf_id == MANFID_PIONEER) ||
+ (info->manf_id == 0x0098)) {
+ outb(0x80, link->io.BasePort1 + 0xd);
+ outb(0x24, link->io.BasePort1 + 0x9);
+ outb(0x04, link->io.BasePort1 + 0xd);
}
+ /*
+ * If things don't work after a "resume",
+ * this is a good place to start looking.
+ */
+ SYM53C500_int_host_reset(link->io.BasePort1);
return 0;
}
static void
-SYM53C500_detach(struct pcmcia_device *p_dev)
+SYM53C500_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "SYM53C500_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- SYM53C500_release(link);
+ SYM53C500_release(link);
kfree(link->priv);
link->priv = NULL;
} /* SYM53C500_detach */
static int
-SYM53C500_attach(struct pcmcia_device *p_dev)
+SYM53C500_probe(struct pcmcia_device *link)
{
struct scsi_info_t *info;
- dev_link_t *link;
DEBUG(0, "SYM53C500_attach()\n");
@@ -928,7 +894,7 @@ SYM53C500_attach(struct pcmcia_device *p_dev)
if (!info)
return -ENOMEM;
memset(info, 0, sizeof(*info));
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.NumPorts1 = 16;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -936,17 +902,10 @@ SYM53C500_attach(struct pcmcia_device *p_dev)
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- SYM53C500_config(link);
-
- return 0;
+ return SYM53C500_config(link);
} /* SYM53C500_attach */
MODULE_AUTHOR("Bob Tracy <rct@frus.com>");
@@ -966,10 +925,9 @@ static struct pcmcia_driver sym53c500_cs_driver = {
.drv = {
.name = "sym53c500_cs",
},
- .probe = SYM53C500_attach,
+ .probe = SYM53C500_probe,
.remove = SYM53C500_detach,
.id_table = sym53c500_ids,
- .suspend = sym53c500_suspend,
.resume = sym53c500_resume,
};
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
index 3c85c4b66e1..5cda16cfacb 100644
--- a/drivers/scsi/pdc_adma.c
+++ b/drivers/scsi/pdc_adma.c
@@ -143,7 +143,6 @@ static struct scsi_host_template adma_ata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index 05347eed9dd..108910f512e 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -18,6 +18,7 @@
#include <linux/parport.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
+#include <linux/jiffies.h>
#include <asm/io.h>
#include <scsi/scsi.h>
@@ -726,7 +727,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd)
retv--;
if (retv) {
- if ((jiffies - dev->jstart) > (1 * HZ)) {
+ if (time_after(jiffies, dev->jstart + (1 * HZ))) {
printk
("ppa: Parallel port cable is unplugged!!\n");
ppa_fail(dev, DID_BUS_BUSY);
@@ -981,6 +982,12 @@ static int device_check(ppa_struct *dev)
return -ENODEV;
}
+static int ppa_adjust_queue(struct scsi_device *device)
+{
+ blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH);
+ return 0;
+}
+
static struct scsi_host_template ppa_template = {
.module = THIS_MODULE,
.proc_name = "ppa",
@@ -996,6 +1003,7 @@ static struct scsi_host_template ppa_template = {
.cmd_per_lun = 1,
.use_clustering = ENABLE_CLUSTERING,
.can_queue = 1,
+ .slave_alloc = ppa_adjust_queue,
};
/***************************************************************************
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index e0230249fa0..5a48e55f941 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -350,6 +350,7 @@
#include <linux/pci_ids.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -4321,7 +4322,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
#ifdef QLA_64BIT_PTR
if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) {
- if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
+ if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "scsi(%li): Unable to set a "
"suitable DMA mask - aborting\n", ha->host_no);
error = -ENODEV;
@@ -4331,7 +4332,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
dprintk(2, "scsi(%li): 64 Bit PCI Addressing Enabled\n",
ha->host_no);
#else
- if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
+ if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "scsi(%li): Unable to set a "
"suitable DMA mask - aborting\n", ha->host_no);
error = -ENODEV;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 017729c59a4..584fe5d8e50 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -599,6 +599,7 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
* Either SUCCESS or FAILED.
*
* Note:
+* Only return FAILED if command not returned by firmware.
**************************************************************************/
int
qla2xxx_eh_abort(struct scsi_cmnd *cmd)
@@ -609,11 +610,12 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
unsigned int id, lun;
unsigned long serial;
unsigned long flags;
+ int wait = 0;
if (!CMD_SP(cmd))
- return FAILED;
+ return SUCCESS;
- ret = FAILED;
+ ret = SUCCESS;
id = cmd->device->id;
lun = cmd->device->lun;
@@ -642,7 +644,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
} else {
DEBUG3(printk("%s(%ld): abort_command "
"mbx success.\n", __func__, ha->host_no));
- ret = SUCCESS;
+ wait = 1;
}
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -651,17 +653,18 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Wait for the command to be returned. */
- if (ret == SUCCESS) {
+ if (wait) {
if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) {
qla_printk(KERN_ERR, ha,
"scsi(%ld:%d:%d): Abort handler timed out -- %lx "
"%x.\n", ha->host_no, id, lun, serial, ret);
+ ret = FAILED;
}
}
qla_printk(KERN_INFO, ha,
- "scsi(%ld:%d:%d): Abort command issued -- %lx %x.\n", ha->host_no,
- id, lun, serial, ret);
+ "scsi(%ld:%d:%d): Abort command issued -- %d %lx %x.\n",
+ ha->host_no, id, lun, wait, serial, ret);
return ret;
}
@@ -1700,8 +1703,8 @@ qla2x00_free_device(scsi_qla_host_t *ha)
ha->flags.online = 0;
/* Detach interrupts */
- if (ha->pdev->irq)
- free_irq(ha->pdev->irq, ha);
+ if (ha->host->irq)
+ free_irq(ha->host->irq, ha);
/* release io space registers */
if (ha->iobase)
diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
deleted file mode 100644
index 94ef3f08d37..00000000000
--- a/drivers/scsi/qlogicfc.c
+++ /dev/null
@@ -1,2226 +0,0 @@
-/*
- * QLogic ISP2x00 SCSI-FCP
- * Written by Erik H. Moe, ehm@cris.com
- * Copyright 1995, Erik H. Moe
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* Renamed and updated to 1.3.x by Michael Griffith <grif@cs.ucr.edu> */
-
-/* This is a version of the isp1020 driver which was modified by
- * Chris Loveland <cwl@iol.unh.edu> to support the isp2100 and isp2200
- *
- * Big endian support and dynamic DMA mapping added
- * by Jakub Jelinek <jakub@redhat.com>.
- *
- * Conversion to final pci64 DMA interfaces
- * by David S. Miller <davem@redhat.com>.
- */
-
-/*
- * $Date: 1995/09/22 02:23:15 $
- * $Revision: 0.5 $
- *
- * $Log: isp1020.c,v $
- * Revision 0.5 1995/09/22 02:23:15 root
- * do auto request sense
- *
- * Revision 0.4 1995/08/07 04:44:33 root
- * supply firmware with driver.
- * numerous bug fixes/general cleanup of code.
- *
- * Revision 0.3 1995/07/16 16:15:39 root
- * added reset/abort code.
- *
- * Revision 0.2 1995/06/29 03:14:19 root
- * fixed biosparam.
- * added queue protocol.
- *
- * Revision 0.1 1995/06/25 01:55:45 root
- * Initial release.
- *
- */
-
-#include <linux/blkdev.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/unistd.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-
-#define pci64_dma_hi32(a) ((u32) (0xffffffff & (((u64)(a))>>32)))
-#define pci64_dma_lo32(a) ((u32) (0xffffffff & (((u64)(a)))))
-#define pci64_dma_build(hi,lo) \
- ((dma_addr_t)(((u64)(lo))|(((u64)(hi))<<32)))
-
-/*
- * With the qlogic interface, every queue slot can hold a SCSI
- * command with up to 2 scatter/gather entries. If we need more
- * than 2 entries, continuation entries can be used that hold
- * another 5 entries each. Unlike for other drivers, this means
- * that the maximum number of scatter/gather entries we can
- * support at any given time is a function of the number of queue
- * slots available. That is, host->can_queue and host->sg_tablesize
- * are dynamic and _not_ independent. This all works fine because
- * requests are queued serially and the scatter/gather limit is
- * determined for each queue request anew.
- */
-
-#define DATASEGS_PER_COMMAND 2
-#define DATASEGS_PER_CONT 5
-
-#define QLOGICFC_REQ_QUEUE_LEN 255 /* must be power of two - 1 */
-#define QLOGICFC_MAX_SG(ql) (DATASEGS_PER_COMMAND + (((ql) > 0) ? DATASEGS_PER_CONT*((ql) - 1) : 0))
-#define QLOGICFC_CMD_PER_LUN 8
-
-/* Configuration section **************************************************** */
-
-/* Set the following macro to 1 to reload the ISP2x00's firmware. This is
- version 1.17.30 of the isp2100's firmware and version 2.00.40 of the
- isp2200's firmware.
-*/
-
-#define USE_NVRAM_DEFAULTS 1
-
-#define ISP2x00_PORTDB 1
-
-/* Set the following to 1 to include fabric support, fabric support is
- * currently not as well tested as the other aspects of the driver */
-
-#define ISP2x00_FABRIC 1
-
-/* Macros used for debugging */
-#define DEBUG_ISP2x00 0
-#define DEBUG_ISP2x00_INT 0
-#define DEBUG_ISP2x00_INTR 0
-#define DEBUG_ISP2x00_SETUP 0
-#define DEBUG_ISP2x00_FABRIC 0
-#define TRACE_ISP 0
-
-
-#define DEFAULT_LOOP_COUNT 1000000000
-
-#define ISP_TIMEOUT (2*HZ)
-/* End Configuration section ************************************************ */
-
-#include <linux/module.h>
-
-#if TRACE_ISP
-
-#define TRACE_BUF_LEN (32*1024)
-
-struct {
- u_long next;
- struct {
- u_long time;
- u_int index;
- u_int addr;
- u_char *name;
- } buf[TRACE_BUF_LEN];
-} trace;
-
-#define TRACE(w, i, a) \
-{ \
- unsigned long flags; \
- \
- save_flags(flags); \
- cli(); \
- trace.buf[trace.next].name = (w); \
- trace.buf[trace.next].time = jiffies; \
- trace.buf[trace.next].index = (i); \
- trace.buf[trace.next].addr = (long) (a); \
- trace.next = (trace.next + 1) & (TRACE_BUF_LEN - 1); \
- restore_flags(flags); \
-}
-
-#else
-#define TRACE(w, i, a)
-#endif
-
-#if DEBUG_ISP2x00_FABRIC
-#define DEBUG_FABRIC(x) x
-#else
-#define DEBUG_FABRIC(x)
-#endif /* DEBUG_ISP2x00_FABRIC */
-
-
-#if DEBUG_ISP2x00
-#define ENTER(x) printk("isp2x00 : entering %s()\n", x);
-#define LEAVE(x) printk("isp2x00 : leaving %s()\n", x);
-#define DEBUG(x) x
-#else
-#define ENTER(x)
-#define LEAVE(x)
-#define DEBUG(x)
-#endif /* DEBUG_ISP2x00 */
-
-#if DEBUG_ISP2x00_INTR
-#define ENTER_INTR(x) printk("isp2x00 : entering %s()\n", x);
-#define LEAVE_INTR(x) printk("isp2x00 : leaving %s()\n", x);
-#define DEBUG_INTR(x) x
-#else
-#define ENTER_INTR(x)
-#define LEAVE_INTR(x)
-#define DEBUG_INTR(x)
-#endif /* DEBUG ISP2x00_INTR */
-
-
-#define ISP2100_REV_ID1 1
-#define ISP2100_REV_ID3 3
-#define ISP2200_REV_ID5 5
-
-/* host configuration and control registers */
-#define HOST_HCCR 0xc0 /* host command and control */
-
-/* pci bus interface registers */
-#define FLASH_BIOS_ADDR 0x00
-#define FLASH_BIOS_DATA 0x02
-#define ISP_CTRL_STATUS 0x06 /* configuration register #1 */
-#define PCI_INTER_CTL 0x08 /* pci interrupt control */
-#define PCI_INTER_STS 0x0a /* pci interrupt status */
-#define PCI_SEMAPHORE 0x0c /* pci semaphore */
-#define PCI_NVRAM 0x0e /* pci nvram interface */
-
-/* mailbox registers */
-#define MBOX0 0x10 /* mailbox 0 */
-#define MBOX1 0x12 /* mailbox 1 */
-#define MBOX2 0x14 /* mailbox 2 */
-#define MBOX3 0x16 /* mailbox 3 */
-#define MBOX4 0x18 /* mailbox 4 */
-#define MBOX5 0x1a /* mailbox 5 */
-#define MBOX6 0x1c /* mailbox 6 */
-#define MBOX7 0x1e /* mailbox 7 */
-
-/* mailbox command complete status codes */
-#define MBOX_COMMAND_COMPLETE 0x4000
-#define INVALID_COMMAND 0x4001
-#define HOST_INTERFACE_ERROR 0x4002
-#define TEST_FAILED 0x4003
-#define COMMAND_ERROR 0x4005
-#define COMMAND_PARAM_ERROR 0x4006
-#define PORT_ID_USED 0x4007
-#define LOOP_ID_USED 0x4008
-#define ALL_IDS_USED 0x4009
-
-/* async event status codes */
-#define RESET_DETECTED 0x8001
-#define SYSTEM_ERROR 0x8002
-#define REQUEST_TRANSFER_ERROR 0x8003
-#define RESPONSE_TRANSFER_ERROR 0x8004
-#define REQUEST_QUEUE_WAKEUP 0x8005
-#define LIP_OCCURRED 0x8010
-#define LOOP_UP 0x8011
-#define LOOP_DOWN 0x8012
-#define LIP_RECEIVED 0x8013
-#define PORT_DB_CHANGED 0x8014
-#define CHANGE_NOTIFICATION 0x8015
-#define SCSI_COMMAND_COMPLETE 0x8020
-#define POINT_TO_POINT_UP 0x8030
-#define CONNECTION_MODE 0x8036
-
-struct Entry_header {
- u_char entry_type;
- u_char entry_cnt;
- u_char sys_def_1;
- u_char flags;
-};
-
-/* entry header type commands */
-#define ENTRY_COMMAND 0x19
-#define ENTRY_CONTINUATION 0x0a
-
-#define ENTRY_STATUS 0x03
-#define ENTRY_MARKER 0x04
-
-
-/* entry header flag definitions */
-#define EFLAG_BUSY 2
-#define EFLAG_BAD_HEADER 4
-#define EFLAG_BAD_PAYLOAD 8
-
-struct dataseg {
- u_int d_base;
- u_int d_base_hi;
- u_int d_count;
-};
-
-struct Command_Entry {
- struct Entry_header hdr;
- u_int handle;
- u_char target_lun;
- u_char target_id;
- u_short expanded_lun;
- u_short control_flags;
- u_short rsvd2;
- u_short time_out;
- u_short segment_cnt;
- u_char cdb[16];
- u_int total_byte_cnt;
- struct dataseg dataseg[DATASEGS_PER_COMMAND];
-};
-
-/* command entry control flag definitions */
-#define CFLAG_NODISC 0x01
-#define CFLAG_HEAD_TAG 0x02
-#define CFLAG_ORDERED_TAG 0x04
-#define CFLAG_SIMPLE_TAG 0x08
-#define CFLAG_TAR_RTN 0x10
-#define CFLAG_READ 0x20
-#define CFLAG_WRITE 0x40
-
-struct Continuation_Entry {
- struct Entry_header hdr;
- struct dataseg dataseg[DATASEGS_PER_CONT];
-};
-
-struct Marker_Entry {
- struct Entry_header hdr;
- u_int reserved;
- u_char target_lun;
- u_char target_id;
- u_char modifier;
- u_char expanded_lun;
- u_char rsvds[52];
-};
-
-/* marker entry modifier definitions */
-#define SYNC_DEVICE 0
-#define SYNC_TARGET 1
-#define SYNC_ALL 2
-
-struct Status_Entry {
- struct Entry_header hdr;
- u_int handle;
- u_short scsi_status;
- u_short completion_status;
- u_short state_flags;
- u_short status_flags;
- u_short res_info_len;
- u_short req_sense_len;
- u_int residual;
- u_char res_info[8];
- u_char req_sense_data[32];
-};
-
-/* status entry completion status definitions */
-#define CS_COMPLETE 0x0000
-#define CS_DMA_ERROR 0x0002
-#define CS_RESET_OCCURRED 0x0004
-#define CS_ABORTED 0x0005
-#define CS_TIMEOUT 0x0006
-#define CS_DATA_OVERRUN 0x0007
-#define CS_DATA_UNDERRUN 0x0015
-#define CS_QUEUE_FULL 0x001c
-#define CS_PORT_UNAVAILABLE 0x0028
-#define CS_PORT_LOGGED_OUT 0x0029
-#define CS_PORT_CONFIG_CHANGED 0x002a
-
-/* status entry state flag definitions */
-#define SF_SENT_CDB 0x0400
-#define SF_TRANSFERRED_DATA 0x0800
-#define SF_GOT_STATUS 0x1000
-
-/* status entry status flag definitions */
-#define STF_BUS_RESET 0x0008
-#define STF_DEVICE_RESET 0x0010
-#define STF_ABORTED 0x0020
-#define STF_TIMEOUT 0x0040
-
-/* interrupt control commands */
-#define ISP_EN_INT 0x8000
-#define ISP_EN_RISC 0x0008
-
-/* host control commands */
-#define HCCR_NOP 0x0000
-#define HCCR_RESET 0x1000
-#define HCCR_PAUSE 0x2000
-#define HCCR_RELEASE 0x3000
-#define HCCR_SINGLE_STEP 0x4000
-#define HCCR_SET_HOST_INTR 0x5000
-#define HCCR_CLEAR_HOST_INTR 0x6000
-#define HCCR_CLEAR_RISC_INTR 0x7000
-#define HCCR_BP_ENABLE 0x8000
-#define HCCR_BIOS_DISABLE 0x9000
-#define HCCR_TEST_MODE 0xf000
-
-#define RISC_BUSY 0x0004
-
-/* mailbox commands */
-#define MBOX_NO_OP 0x0000
-#define MBOX_LOAD_RAM 0x0001
-#define MBOX_EXEC_FIRMWARE 0x0002
-#define MBOX_DUMP_RAM 0x0003
-#define MBOX_WRITE_RAM_WORD 0x0004
-#define MBOX_READ_RAM_WORD 0x0005
-#define MBOX_MAILBOX_REG_TEST 0x0006
-#define MBOX_VERIFY_CHECKSUM 0x0007
-#define MBOX_ABOUT_FIRMWARE 0x0008
-#define MBOX_LOAD_RISC_RAM 0x0009
-#define MBOX_DUMP_RISC_RAM 0x000a
-#define MBOX_CHECK_FIRMWARE 0x000e
-#define MBOX_INIT_REQ_QUEUE 0x0010
-#define MBOX_INIT_RES_QUEUE 0x0011
-#define MBOX_EXECUTE_IOCB 0x0012
-#define MBOX_WAKE_UP 0x0013
-#define MBOX_STOP_FIRMWARE 0x0014
-#define MBOX_ABORT_IOCB 0x0015
-#define MBOX_ABORT_DEVICE 0x0016
-#define MBOX_ABORT_TARGET 0x0017
-#define MBOX_BUS_RESET 0x0018
-#define MBOX_STOP_QUEUE 0x0019
-#define MBOX_START_QUEUE 0x001a
-#define MBOX_SINGLE_STEP_QUEUE 0x001b
-#define MBOX_ABORT_QUEUE 0x001c
-#define MBOX_GET_DEV_QUEUE_STATUS 0x001d
-#define MBOX_GET_FIRMWARE_STATUS 0x001f
-#define MBOX_GET_INIT_SCSI_ID 0x0020
-#define MBOX_GET_RETRY_COUNT 0x0022
-#define MBOX_GET_TARGET_PARAMS 0x0028
-#define MBOX_GET_DEV_QUEUE_PARAMS 0x0029
-#define MBOX_SET_RETRY_COUNT 0x0032
-#define MBOX_SET_TARGET_PARAMS 0x0038
-#define MBOX_SET_DEV_QUEUE_PARAMS 0x0039
-#define MBOX_EXECUTE_IOCB64 0x0054
-#define MBOX_INIT_FIRMWARE 0x0060
-#define MBOX_GET_INIT_CB 0x0061
-#define MBOX_INIT_LIP 0x0062
-#define MBOX_GET_POS_MAP 0x0063
-#define MBOX_GET_PORT_DB 0x0064
-#define MBOX_CLEAR_ACA 0x0065
-#define MBOX_TARGET_RESET 0x0066
-#define MBOX_CLEAR_TASK_SET 0x0067
-#define MBOX_ABORT_TASK_SET 0x0068
-#define MBOX_GET_FIRMWARE_STATE 0x0069
-#define MBOX_GET_PORT_NAME 0x006a
-#define MBOX_SEND_SNS 0x006e
-#define MBOX_PORT_LOGIN 0x006f
-#define MBOX_SEND_CHANGE_REQUEST 0x0070
-#define MBOX_PORT_LOGOUT 0x0071
-
-/*
- * Firmware if needed (note this is a hack, it belongs in a separate
- * module.
- */
-
-#ifdef CONFIG_SCSI_QLOGIC_FC_FIRMWARE
-#include "qlogicfc_asm.c"
-#else
-static unsigned short risc_code_addr01 = 0x1000 ;
-#endif
-
-/* Each element in mbox_param is an 8 bit bitmap where each bit indicates
- if that mbox should be copied as input. For example 0x2 would mean
- only copy mbox1. */
-
-static const u_char mbox_param[] =
-{
- 0x01, /* MBOX_NO_OP */
- 0x1f, /* MBOX_LOAD_RAM */
- 0x03, /* MBOX_EXEC_FIRMWARE */
- 0x1f, /* MBOX_DUMP_RAM */
- 0x07, /* MBOX_WRITE_RAM_WORD */
- 0x03, /* MBOX_READ_RAM_WORD */
- 0xff, /* MBOX_MAILBOX_REG_TEST */
- 0x03, /* MBOX_VERIFY_CHECKSUM */
- 0x01, /* MBOX_ABOUT_FIRMWARE */
- 0xff, /* MBOX_LOAD_RISC_RAM */
- 0xff, /* MBOX_DUMP_RISC_RAM */
- 0x00, /* 0x000b */
- 0x00, /* 0x000c */
- 0x00, /* 0x000d */
- 0x01, /* MBOX_CHECK_FIRMWARE */
- 0x00, /* 0x000f */
- 0x1f, /* MBOX_INIT_REQ_QUEUE */
- 0x2f, /* MBOX_INIT_RES_QUEUE */
- 0x0f, /* MBOX_EXECUTE_IOCB */
- 0x03, /* MBOX_WAKE_UP */
- 0x01, /* MBOX_STOP_FIRMWARE */
- 0x0f, /* MBOX_ABORT_IOCB */
- 0x03, /* MBOX_ABORT_DEVICE */
- 0x07, /* MBOX_ABORT_TARGET */
- 0x03, /* MBOX_BUS_RESET */
- 0x03, /* MBOX_STOP_QUEUE */
- 0x03, /* MBOX_START_QUEUE */
- 0x03, /* MBOX_SINGLE_STEP_QUEUE */
- 0x03, /* MBOX_ABORT_QUEUE */
- 0x03, /* MBOX_GET_DEV_QUEUE_STATUS */
- 0x00, /* 0x001e */
- 0x01, /* MBOX_GET_FIRMWARE_STATUS */
- 0x01, /* MBOX_GET_INIT_SCSI_ID */
- 0x00, /* 0x0021 */
- 0x01, /* MBOX_GET_RETRY_COUNT */
- 0x00, /* 0x0023 */
- 0x00, /* 0x0024 */
- 0x00, /* 0x0025 */
- 0x00, /* 0x0026 */
- 0x00, /* 0x0027 */
- 0x03, /* MBOX_GET_TARGET_PARAMS */
- 0x03, /* MBOX_GET_DEV_QUEUE_PARAMS */
- 0x00, /* 0x002a */
- 0x00, /* 0x002b */
- 0x00, /* 0x002c */
- 0x00, /* 0x002d */
- 0x00, /* 0x002e */
- 0x00, /* 0x002f */
- 0x00, /* 0x0030 */
- 0x00, /* 0x0031 */
- 0x07, /* MBOX_SET_RETRY_COUNT */
- 0x00, /* 0x0033 */
- 0x00, /* 0x0034 */
- 0x00, /* 0x0035 */
- 0x00, /* 0x0036 */
- 0x00, /* 0x0037 */
- 0x0f, /* MBOX_SET_TARGET_PARAMS */
- 0x0f, /* MBOX_SET_DEV_QUEUE_PARAMS */
- 0x00, /* 0x003a */
- 0x00, /* 0x003b */
- 0x00, /* 0x003c */
- 0x00, /* 0x003d */
- 0x00, /* 0x003e */
- 0x00, /* 0x003f */
- 0x00, /* 0x0040 */
- 0x00, /* 0x0041 */
- 0x00, /* 0x0042 */
- 0x00, /* 0x0043 */
- 0x00, /* 0x0044 */
- 0x00, /* 0x0045 */
- 0x00, /* 0x0046 */
- 0x00, /* 0x0047 */
- 0x00, /* 0x0048 */
- 0x00, /* 0x0049 */
- 0x00, /* 0x004a */
- 0x00, /* 0x004b */
- 0x00, /* 0x004c */
- 0x00, /* 0x004d */
- 0x00, /* 0x004e */
- 0x00, /* 0x004f */
- 0x00, /* 0x0050 */
- 0x00, /* 0x0051 */
- 0x00, /* 0x0052 */
- 0x00, /* 0x0053 */
- 0xcf, /* MBOX_EXECUTE_IOCB64 */
- 0x00, /* 0x0055 */
- 0x00, /* 0x0056 */
- 0x00, /* 0x0057 */
- 0x00, /* 0x0058 */
- 0x00, /* 0x0059 */
- 0x00, /* 0x005a */
- 0x00, /* 0x005b */
- 0x00, /* 0x005c */
- 0x00, /* 0x005d */
- 0x00, /* 0x005e */
- 0x00, /* 0x005f */
- 0xff, /* MBOX_INIT_FIRMWARE */
- 0xcd, /* MBOX_GET_INIT_CB */
- 0x01, /* MBOX_INIT_LIP */
- 0xcd, /* MBOX_GET_POS_MAP */
- 0xcf, /* MBOX_GET_PORT_DB */
- 0x03, /* MBOX_CLEAR_ACA */
- 0x03, /* MBOX_TARGET_RESET */
- 0x03, /* MBOX_CLEAR_TASK_SET */
- 0x03, /* MBOX_ABORT_TASK_SET */
- 0x01, /* MBOX_GET_FIRMWARE_STATE */
- 0x03, /* MBOX_GET_PORT_NAME */
- 0x00, /* 0x006b */
- 0x00, /* 0x006c */
- 0x00, /* 0x006d */
- 0xcf, /* MBOX_SEND_SNS */
- 0x0f, /* MBOX_PORT_LOGIN */
- 0x03, /* MBOX_SEND_CHANGE_REQUEST */
- 0x03, /* MBOX_PORT_LOGOUT */
-};
-
-#define MAX_MBOX_COMMAND (sizeof(mbox_param)/sizeof(u_short))
-
-
-struct id_name_map {
- u64 wwn;
- u_char loop_id;
-};
-
-struct sns_cb {
- u_short len;
- u_short res1;
- u_int response_low;
- u_int response_high;
- u_short sub_len;
- u_short res2;
- u_char data[44];
-};
-
-/* address of instance of this struct is passed to adapter to initialize things
- */
-struct init_cb {
- u_char version;
- u_char reseverd1[1];
- u_short firm_opts;
- u_short max_frame_len;
- u_short max_iocb;
- u_short exec_throttle;
- u_char retry_cnt;
- u_char retry_delay;
- u_short node_name[4];
- u_short hard_addr;
- u_char reserved2[10];
- u_short req_queue_out;
- u_short res_queue_in;
- u_short req_queue_len;
- u_short res_queue_len;
- u_int req_queue_addr_lo;
- u_int req_queue_addr_high;
- u_int res_queue_addr_lo;
- u_int res_queue_addr_high;
- /* the rest of this structure only applies to the isp2200 */
- u_short lun_enables;
- u_char cmd_resource_cnt;
- u_char notify_resource_cnt;
- u_short timeout;
- u_short reserved3;
- u_short add_firm_opts;
- u_char res_accum_timer;
- u_char irq_delay_timer;
- u_short special_options;
- u_short reserved4[13];
-};
-
-/*
- * The result queue can be quite a bit smaller since continuation entries
- * do not show up there:
- */
-#define RES_QUEUE_LEN ((QLOGICFC_REQ_QUEUE_LEN + 1) / 8 - 1)
-#define QUEUE_ENTRY_LEN 64
-
-#if ISP2x00_FABRIC
-#define QLOGICFC_MAX_ID 0xff
-#else
-#define QLOGICFC_MAX_ID 0x7d
-#endif
-
-#define QLOGICFC_MAX_LUN 128
-#define QLOGICFC_MAX_LOOP_ID 0x7d
-
-/* the following connection options only apply to the 2200. i have only
- * had success with LOOP_ONLY and P2P_ONLY.
- */
-
-#define LOOP_ONLY 0
-#define P2P_ONLY 1
-#define LOOP_PREFERED 2
-#define P2P_PREFERED 3
-
-#define CONNECTION_PREFERENCE LOOP_ONLY
-
-/* adapter_state values */
-#define AS_FIRMWARE_DEAD -1
-#define AS_LOOP_DOWN 0
-#define AS_LOOP_GOOD 1
-#define AS_REDO_FABRIC_PORTDB 2
-#define AS_REDO_LOOP_PORTDB 4
-
-#define RES_SIZE ((RES_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN)
-#define REQ_SIZE ((QLOGICFC_REQ_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN)
-
-struct isp2x00_hostdata {
- u_char revision;
- struct pci_dev *pci_dev;
- /* result and request queues (shared with isp2x00): */
- u_int req_in_ptr; /* index of next request slot */
- u_int res_out_ptr; /* index of next result slot */
-
- /* this is here so the queues are nicely aligned */
- long send_marker; /* do we need to send a marker? */
-
- char * res;
- char * req;
- struct init_cb control_block;
- int adapter_state;
- unsigned long int tag_ages[QLOGICFC_MAX_ID + 1];
- Scsi_Cmnd *handle_ptrs[QLOGICFC_REQ_QUEUE_LEN + 1];
- unsigned long handle_serials[QLOGICFC_REQ_QUEUE_LEN + 1];
- struct id_name_map port_db[QLOGICFC_MAX_ID + 1];
- u_char mbox_done;
- u64 wwn;
- u_int port_id;
- u_char queued;
- u_char host_id;
- struct timer_list explore_timer;
- struct id_name_map tempmap[QLOGICFC_MAX_ID + 1];
-};
-
-
-/* queue length's _must_ be power of two: */
-#define QUEUE_DEPTH(in, out, ql) ((in - out) & (ql))
-#define REQ_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, \
- QLOGICFC_REQ_QUEUE_LEN)
-#define RES_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, RES_QUEUE_LEN)
-
-static void isp2x00_enable_irqs(struct Scsi_Host *);
-static void isp2x00_disable_irqs(struct Scsi_Host *);
-static int isp2x00_init(struct Scsi_Host *);
-static int isp2x00_reset_hardware(struct Scsi_Host *);
-static int isp2x00_mbox_command(struct Scsi_Host *, u_short[]);
-static int isp2x00_return_status(Scsi_Cmnd *, struct Status_Entry *);
-static void isp2x00_intr_handler(int, void *, struct pt_regs *);
-static irqreturn_t do_isp2x00_intr_handler(int, void *, struct pt_regs *);
-static int isp2x00_make_portdb(struct Scsi_Host *);
-
-#if ISP2x00_FABRIC
-static int isp2x00_init_fabric(struct Scsi_Host *, struct id_name_map *, int);
-#endif
-
-#if USE_NVRAM_DEFAULTS
-static int isp2x00_get_nvram_defaults(struct Scsi_Host *, struct init_cb *);
-static u_short isp2x00_read_nvram_word(struct Scsi_Host *, u_short);
-#endif
-
-#if DEBUG_ISP2x00
-static void isp2x00_print_scsi_cmd(Scsi_Cmnd *);
-#endif
-
-#if DEBUG_ISP2x00_INTR
-static void isp2x00_print_status_entry(struct Status_Entry *);
-#endif
-
-static inline void isp2x00_enable_irqs(struct Scsi_Host *host)
-{
- outw(ISP_EN_INT | ISP_EN_RISC, host->io_port + PCI_INTER_CTL);
-}
-
-
-static inline void isp2x00_disable_irqs(struct Scsi_Host *host)
-{
- outw(0x0, host->io_port + PCI_INTER_CTL);
-}
-
-
-static int isp2x00_detect(struct scsi_host_template * tmpt)
-{
- int hosts = 0;
- unsigned long wait_time;
- struct Scsi_Host *host = NULL;
- struct isp2x00_hostdata *hostdata;
- struct pci_dev *pdev;
- unsigned short device_ids[2];
- dma_addr_t busaddr;
- int i;
-
-
- ENTER("isp2x00_detect");
-
- device_ids[0] = PCI_DEVICE_ID_QLOGIC_ISP2100;
- device_ids[1] = PCI_DEVICE_ID_QLOGIC_ISP2200;
-
- tmpt->proc_name = "isp2x00";
-
- for (i=0; i<2; i++){
- pdev = NULL;
- while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, device_ids[i], pdev))) {
- if (pci_enable_device(pdev))
- continue;
-
- /* Try to configure DMA attributes. */
- if (pci_set_dma_mask(pdev, 0xffffffffffffffffULL) &&
- pci_set_dma_mask(pdev, 0xffffffffULL))
- continue;
-
- host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata));
- if (!host) {
- printk("qlogicfc%d : could not register host.\n", hosts);
- continue;
- }
- host->max_id = QLOGICFC_MAX_ID + 1;
- host->max_lun = QLOGICFC_MAX_LUN;
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- memset(hostdata, 0, sizeof(struct isp2x00_hostdata));
- hostdata->pci_dev = pdev;
- hostdata->res = pci_alloc_consistent(pdev, RES_SIZE + REQ_SIZE, &busaddr);
-
- if (!hostdata->res){
- printk("qlogicfc%d : could not allocate memory for request and response queue.\n", hosts);
- scsi_unregister(host);
- continue;
- }
- hostdata->req = hostdata->res + (RES_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN;
- hostdata->queued = 0;
- /* set up the control block */
- hostdata->control_block.version = 0x1;
- hostdata->control_block.firm_opts = cpu_to_le16(0x800e);
- hostdata->control_block.max_frame_len = cpu_to_le16(2048);
- hostdata->control_block.max_iocb = cpu_to_le16(QLOGICFC_REQ_QUEUE_LEN);
- hostdata->control_block.exec_throttle = cpu_to_le16(QLOGICFC_CMD_PER_LUN);
- hostdata->control_block.retry_delay = 5;
- hostdata->control_block.retry_cnt = 1;
- hostdata->control_block.node_name[0] = cpu_to_le16(0x0020);
- hostdata->control_block.node_name[1] = cpu_to_le16(0xE000);
- hostdata->control_block.node_name[2] = cpu_to_le16(0x008B);
- hostdata->control_block.node_name[3] = cpu_to_le16(0x0000);
- hostdata->control_block.hard_addr = cpu_to_le16(0x0003);
- hostdata->control_block.req_queue_len = cpu_to_le16(QLOGICFC_REQ_QUEUE_LEN + 1);
- hostdata->control_block.res_queue_len = cpu_to_le16(RES_QUEUE_LEN + 1);
- hostdata->control_block.res_queue_addr_lo = cpu_to_le32(pci64_dma_lo32(busaddr));
- hostdata->control_block.res_queue_addr_high = cpu_to_le32(pci64_dma_hi32(busaddr));
- hostdata->control_block.req_queue_addr_lo = cpu_to_le32(pci64_dma_lo32(busaddr + RES_SIZE));
- hostdata->control_block.req_queue_addr_high = cpu_to_le32(pci64_dma_hi32(busaddr + RES_SIZE));
-
-
- hostdata->control_block.add_firm_opts |= cpu_to_le16(CONNECTION_PREFERENCE<<4);
- hostdata->adapter_state = AS_LOOP_DOWN;
- hostdata->explore_timer.data = 1;
- hostdata->host_id = hosts;
-
- if (isp2x00_init(host) || isp2x00_reset_hardware(host)) {
- pci_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
- scsi_unregister(host);
- continue;
- }
- host->this_id = 0;
-
- if (request_irq(host->irq, do_isp2x00_intr_handler, SA_INTERRUPT | SA_SHIRQ, "qlogicfc", host)) {
- printk("qlogicfc%d : interrupt %d already in use\n",
- hostdata->host_id, host->irq);
- pci_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
- scsi_unregister(host);
- continue;
- }
- if (!request_region(host->io_port, 0xff, "qlogicfc")) {
- printk("qlogicfc%d : i/o region 0x%lx-0x%lx already "
- "in use\n",
- hostdata->host_id, host->io_port, host->io_port + 0xff);
- free_irq(host->irq, host);
- pci_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
- scsi_unregister(host);
- continue;
- }
-
- outw(0x0, host->io_port + PCI_SEMAPHORE);
- outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
- isp2x00_enable_irqs(host);
- /* wait for the loop to come up */
- for (wait_time = jiffies + 10 * HZ; time_before(jiffies, wait_time) && hostdata->adapter_state == AS_LOOP_DOWN;) {
- barrier();
- cpu_relax();
- }
- if (hostdata->adapter_state == AS_LOOP_DOWN) {
- printk("qlogicfc%d : link is not up\n", hostdata->host_id);
- }
- hosts++;
- hostdata->explore_timer.data = 0;
- }
- }
-
-
- /* this busy loop should not be needed but the isp2x00 seems to need
- some time before recognizing it is attached to a fabric */
-
-#if ISP2x00_FABRIC
- if (hosts) {
- for (wait_time = jiffies + 5 * HZ; time_before(jiffies, wait_time);) {
- barrier();
- cpu_relax();
- }
- }
-#endif
-
- LEAVE("isp2x00_detect");
-
- return hosts;
-}
-
-
-static int isp2x00_make_portdb(struct Scsi_Host *host)
-{
-
- short param[8];
- int i, j;
- struct isp2x00_hostdata *hostdata;
-
- isp2x00_disable_irqs(host);
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
- memset(hostdata->tempmap, 0, sizeof(hostdata->tempmap));
-
-#if ISP2x00_FABRIC
- for (i = 0x81; i < QLOGICFC_MAX_ID; i++) {
- param[0] = MBOX_PORT_LOGOUT;
- param[1] = i << 8;
- param[2] = 0;
- param[3] = 0;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
-
- DEBUG_FABRIC(printk("qlogicfc%d : logout failed %x %x\n", hostdata->host_id, i, param[0]));
- }
- }
-#endif
-
-
- param[0] = MBOX_GET_INIT_SCSI_ID;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] == MBOX_COMMAND_COMPLETE) {
- hostdata->port_id = ((u_int) param[3]) << 16;
- hostdata->port_id |= param[2];
- hostdata->tempmap[0].loop_id = param[1];
- hostdata->tempmap[0].wwn = hostdata->wwn;
- }
- else {
- printk("qlogicfc%d : error getting scsi id.\n", hostdata->host_id);
- }
-
- for (i = 0; i <=QLOGICFC_MAX_ID; i++)
- hostdata->tempmap[i].loop_id = hostdata->tempmap[0].loop_id;
-
- for (i = 0, j = 1; i <= QLOGICFC_MAX_LOOP_ID; i++) {
- param[0] = MBOX_GET_PORT_NAME;
- param[1] = (i << 8) & 0xff00;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] == MBOX_COMMAND_COMPLETE) {
- hostdata->tempmap[j].loop_id = i;
- hostdata->tempmap[j].wwn = ((u64) (param[2] & 0xff)) << 56;
- hostdata->tempmap[j].wwn |= ((u64) ((param[2] >> 8) & 0xff)) << 48;
- hostdata->tempmap[j].wwn |= ((u64) (param[3] & 0xff)) << 40;
- hostdata->tempmap[j].wwn |= ((u64) ((param[3] >> 8) & 0xff)) << 32;
- hostdata->tempmap[j].wwn |= ((u64) (param[6] & 0xff)) << 24;
- hostdata->tempmap[j].wwn |= ((u64) ((param[6] >> 8) & 0xff)) << 16;
- hostdata->tempmap[j].wwn |= ((u64) (param[7] & 0xff)) << 8;
- hostdata->tempmap[j].wwn |= ((u64) ((param[7] >> 8) & 0xff));
-
- j++;
-
- }
- }
-
-
-#if ISP2x00_FABRIC
- isp2x00_init_fabric(host, hostdata->tempmap, j);
-#endif
-
- for (i = 0; i <= QLOGICFC_MAX_ID; i++) {
- if (hostdata->tempmap[i].wwn != hostdata->port_db[i].wwn) {
- for (j = 0; j <= QLOGICFC_MAX_ID; j++) {
- if (hostdata->tempmap[j].wwn == hostdata->port_db[i].wwn) {
- hostdata->port_db[i].loop_id = hostdata->tempmap[j].loop_id;
- break;
- }
- }
- if (j == QLOGICFC_MAX_ID + 1)
- hostdata->port_db[i].loop_id = hostdata->tempmap[0].loop_id;
-
- for (j = 0; j <= QLOGICFC_MAX_ID; j++) {
- if (hostdata->port_db[j].wwn == hostdata->tempmap[i].wwn || !hostdata->port_db[j].wwn) {
- break;
- }
- }
- if (j == QLOGICFC_MAX_ID + 1)
- printk("qlogicfc%d : Too many scsi devices, no more room in port map.\n", hostdata->host_id);
- if (!hostdata->port_db[j].wwn) {
- hostdata->port_db[j].loop_id = hostdata->tempmap[i].loop_id;
- hostdata->port_db[j].wwn = hostdata->tempmap[i].wwn;
- }
- } else
- hostdata->port_db[i].loop_id = hostdata->tempmap[i].loop_id;
-
- }
-
- isp2x00_enable_irqs(host);
-
- return 0;
-}
-
-
-#if ISP2x00_FABRIC
-
-#define FABRIC_PORT 0x7e
-#define FABRIC_CONTROLLER 0x7f
-#define FABRIC_SNS 0x80
-
-int isp2x00_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int cur_scsi_id)
-{
-
- u_short param[8];
- u64 wwn;
- int done = 0;
- u_short loop_id = 0x81;
- u_short scsi_id = cur_scsi_id;
- u_int port_id;
- struct sns_cb *req;
- u_char *sns_response;
- dma_addr_t busaddr;
- struct isp2x00_hostdata *hostdata;
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- DEBUG_FABRIC(printk("qlogicfc%d : Checking for a fabric.\n", hostdata->host_id));
- param[0] = MBOX_GET_PORT_NAME;
- param[1] = (u16)FABRIC_PORT << 8;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- DEBUG_FABRIC(printk("qlogicfc%d : fabric check result %x\n", hostdata->host_id, param[0]));
- return 0;
- }
- printk("qlogicfc%d : Fabric found.\n", hostdata->host_id);
-
- req = (struct sns_cb *)pci_alloc_consistent(hostdata->pci_dev, sizeof(*req) + 608, &busaddr);
-
- if (!req){
- printk("qlogicfc%d : Could not allocate DMA resources for fabric initialization\n", hostdata->host_id);
- return 0;
- }
- sns_response = (u_char *)(req + 1);
-
- if (hostdata->adapter_state & AS_REDO_LOOP_PORTDB){
- memset(req, 0, sizeof(*req));
-
- req->len = cpu_to_le16(8);
- req->response_low = cpu_to_le32(pci64_dma_lo32(busaddr + sizeof(*req)));
- req->response_high = cpu_to_le32(pci64_dma_hi32(busaddr + sizeof(*req)));
- req->sub_len = cpu_to_le16(22);
- req->data[0] = 0x17;
- req->data[1] = 0x02;
- req->data[8] = (u_char) (hostdata->port_id & 0xff);
- req->data[9] = (u_char) (hostdata->port_id >> 8 & 0xff);
- req->data[10] = (u_char) (hostdata->port_id >> 16 & 0xff);
- req->data[13] = 0x01;
- param[0] = MBOX_SEND_SNS;
- param[1] = 30;
- param[2] = pci64_dma_lo32(busaddr) >> 16;
- param[3] = pci64_dma_lo32(busaddr);
- param[6] = pci64_dma_hi32(busaddr) >> 16;
- param[7] = pci64_dma_hi32(busaddr);
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE)
- printk("qlogicfc%d : error sending RFC-4\n", hostdata->host_id);
- }
-
- port_id = hostdata->port_id;
- while (!done) {
- memset(req, 0, sizeof(*req));
-
- req->len = cpu_to_le16(304);
- req->response_low = cpu_to_le32(pci64_dma_lo32(busaddr + sizeof(*req)));
- req->response_high = cpu_to_le32(pci64_dma_hi32(busaddr + sizeof(*req)));
- req->sub_len = cpu_to_le16(6);
- req->data[0] = 0x00;
- req->data[1] = 0x01;
- req->data[8] = (u_char) (port_id & 0xff);
- req->data[9] = (u_char) (port_id >> 8 & 0xff);
- req->data[10] = (u_char) (port_id >> 16 & 0xff);
-
- param[0] = MBOX_SEND_SNS;
- param[1] = 14;
- param[2] = pci64_dma_lo32(busaddr) >> 16;
- param[3] = pci64_dma_lo32(busaddr);
- param[6] = pci64_dma_hi32(busaddr) >> 16;
- param[7] = pci64_dma_hi32(busaddr);
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] == MBOX_COMMAND_COMPLETE) {
- DEBUG_FABRIC(printk("qlogicfc%d : found node %02x%02x%02x%02x%02x%02x%02x%02x ", hostdata->host_id, sns_response[20], sns_response[21], sns_response[22], sns_response[23], sns_response[24], sns_response[25], sns_response[26], sns_response[27]));
- DEBUG_FABRIC(printk(" port id: %02x%02x%02x\n", sns_response[17], sns_response[18], sns_response[19]));
- port_id = ((u_int) sns_response[17]) << 16;
- port_id |= ((u_int) sns_response[18]) << 8;
- port_id |= ((u_int) sns_response[19]);
- wwn = ((u64) sns_response[20]) << 56;
- wwn |= ((u64) sns_response[21]) << 48;
- wwn |= ((u64) sns_response[22]) << 40;
- wwn |= ((u64) sns_response[23]) << 32;
- wwn |= ((u64) sns_response[24]) << 24;
- wwn |= ((u64) sns_response[25]) << 16;
- wwn |= ((u64) sns_response[26]) << 8;
- wwn |= ((u64) sns_response[27]);
- if (hostdata->port_id >> 8 != port_id >> 8) {
- DEBUG_FABRIC(printk("qlogicfc%d : adding a fabric port: %x\n", hostdata->host_id, port_id));
- param[0] = MBOX_PORT_LOGIN;
- param[1] = loop_id << 8;
- param[2] = (u_short) (port_id >> 16);
- param[3] = (u_short) (port_id);
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] == MBOX_COMMAND_COMPLETE) {
- port_db[scsi_id].wwn = wwn;
- port_db[scsi_id].loop_id = loop_id;
- loop_id++;
- scsi_id++;
- } else {
- printk("qlogicfc%d : Error performing port login %x\n", hostdata->host_id, param[0]);
- DEBUG_FABRIC(printk("qlogicfc%d : loop_id: %x\n", hostdata->host_id, loop_id));
- param[0] = MBOX_PORT_LOGOUT;
- param[1] = loop_id << 8;
- param[2] = 0;
- param[3] = 0;
-
- isp2x00_mbox_command(host, param);
-
- }
-
- }
- if (hostdata->port_id == port_id)
- done = 1;
- } else {
- printk("qlogicfc%d : Get All Next failed %x.\n", hostdata->host_id, param[0]);
- pci_free_consistent(hostdata->pci_dev, sizeof(*req) + 608, req, busaddr);
- return 0;
- }
- }
-
- pci_free_consistent(hostdata->pci_dev, sizeof(*req) + 608, req, busaddr);
- return 1;
-}
-
-#endif /* ISP2x00_FABRIC */
-
-
-static int isp2x00_release(struct Scsi_Host *host)
-{
- struct isp2x00_hostdata *hostdata;
- dma_addr_t busaddr;
-
- ENTER("isp2x00_release");
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- outw(0x0, host->io_port + PCI_INTER_CTL);
- free_irq(host->irq, host);
-
- release_region(host->io_port, 0xff);
-
- busaddr = pci64_dma_build(le32_to_cpu(hostdata->control_block.res_queue_addr_high),
- le32_to_cpu(hostdata->control_block.res_queue_addr_lo));
- pci_free_consistent(hostdata->pci_dev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
-
- LEAVE("isp2x00_release");
-
- return 0;
-}
-
-
-static const char *isp2x00_info(struct Scsi_Host *host)
-{
- static char buf[80];
- struct isp2x00_hostdata *hostdata;
- ENTER("isp2x00_info");
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
- sprintf(buf,
- "QLogic ISP%04x SCSI on PCI bus %02x device %02x irq %d base 0x%lx",
- hostdata->pci_dev->device, hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq,
- host->io_port);
-
-
- LEAVE("isp2x00_info");
-
- return buf;
-}
-
-
-/*
- * The middle SCSI layer ensures that queuecommand never gets invoked
- * concurrently with itself or the interrupt handler (though the
- * interrupt handler may call this routine as part of
- * request-completion handling).
- */
-static int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
-{
- int i, sg_count, n, num_free;
- u_int in_ptr, out_ptr;
- struct dataseg *ds;
- struct scatterlist *sg;
- struct Command_Entry *cmd;
- struct Continuation_Entry *cont;
- struct Scsi_Host *host;
- struct isp2x00_hostdata *hostdata;
-
- ENTER("isp2x00_queuecommand");
-
- host = Cmnd->device->host;
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
- Cmnd->scsi_done = done;
-
- DEBUG(isp2x00_print_scsi_cmd(Cmnd));
-
- if (hostdata->adapter_state & AS_REDO_FABRIC_PORTDB || hostdata->adapter_state & AS_REDO_LOOP_PORTDB) {
- isp2x00_make_portdb(host);
- hostdata->adapter_state = AS_LOOP_GOOD;
- printk("qlogicfc%d : Port Database\n", hostdata->host_id);
- for (i = 0; hostdata->port_db[i].wwn != 0; i++) {
- printk("wwn: %08x%08x scsi_id: %x loop_id: ", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i);
- if (hostdata->port_db[i].loop_id != hostdata->port_db[0].loop_id || i == 0)
- printk("%x", hostdata->port_db[i].loop_id);
- else
- printk("Not Available");
- printk("\n");
- }
- }
- if (hostdata->adapter_state == AS_FIRMWARE_DEAD) {
- printk("qlogicfc%d : The firmware is dead, just return.\n", hostdata->host_id);
- host->max_id = 0;
- return 0;
- }
-
- out_ptr = inw(host->io_port + MBOX4);
- in_ptr = hostdata->req_in_ptr;
-
- DEBUG(printk("qlogicfc%d : request queue depth %d\n", hostdata->host_id,
- REQ_QUEUE_DEPTH(in_ptr, out_ptr)));
-
- cmd = (struct Command_Entry *) &hostdata->req[in_ptr*QUEUE_ENTRY_LEN];
- in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
- if (in_ptr == out_ptr) {
- DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id));
- return 1;
- }
- if (hostdata->send_marker) {
- struct Marker_Entry *marker;
-
- TRACE("queue marker", in_ptr, 0);
-
- DEBUG(printk("qlogicfc%d : adding marker entry\n", hostdata->host_id));
- marker = (struct Marker_Entry *) cmd;
- memset(marker, 0, sizeof(struct Marker_Entry));
-
- marker->hdr.entry_type = ENTRY_MARKER;
- marker->hdr.entry_cnt = 1;
- marker->modifier = SYNC_ALL;
-
- hostdata->send_marker = 0;
-
- if (((in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN) == out_ptr) {
- outw(in_ptr, host->io_port + MBOX4);
- hostdata->req_in_ptr = in_ptr;
- DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id));
- return 1;
- }
- cmd = (struct Command_Entry *) &hostdata->req[in_ptr*QUEUE_ENTRY_LEN];
- in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
- }
- TRACE("queue command", in_ptr, Cmnd);
-
- memset(cmd, 0, sizeof(struct Command_Entry));
-
- /* find a free handle mapping slot */
- for (i = in_ptr; i != (in_ptr - 1) && hostdata->handle_ptrs[i]; i = ((i + 1) % (QLOGICFC_REQ_QUEUE_LEN + 1)));
-
- if (!hostdata->handle_ptrs[i]) {
- cmd->handle = cpu_to_le32(i);
- hostdata->handle_ptrs[i] = Cmnd;
- hostdata->handle_serials[i] = Cmnd->serial_number;
- } else {
- printk("qlogicfc%d : no handle slots, this should not happen.\n", hostdata->host_id);
- printk("hostdata->queued is %x, in_ptr: %x\n", hostdata->queued, in_ptr);
- for (i = 0; i <= QLOGICFC_REQ_QUEUE_LEN; i++){
- if (!hostdata->handle_ptrs[i]){
- printk("slot %d has %p\n", i, hostdata->handle_ptrs[i]);
- }
- }
- return 1;
- }
-
- cmd->hdr.entry_type = ENTRY_COMMAND;
- cmd->hdr.entry_cnt = 1;
- cmd->target_lun = Cmnd->device->lun;
- cmd->expanded_lun = cpu_to_le16(Cmnd->device->lun);
-#if ISP2x00_PORTDB
- cmd->target_id = hostdata->port_db[Cmnd->device->id].loop_id;
-#else
- cmd->target_id = Cmnd->target;
-#endif
- cmd->total_byte_cnt = cpu_to_le32(Cmnd->request_bufflen);
- cmd->time_out = 0;
- memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len);
-
- if (Cmnd->use_sg) {
- sg = (struct scatterlist *) Cmnd->request_buffer;
- sg_count = pci_map_sg(hostdata->pci_dev, sg, Cmnd->use_sg, Cmnd->sc_data_direction);
- cmd->segment_cnt = cpu_to_le16(sg_count);
- ds = cmd->dataseg;
- /* fill in first two sg entries: */
- n = sg_count;
- if (n > DATASEGS_PER_COMMAND)
- n = DATASEGS_PER_COMMAND;
-
- for (i = 0; i < n; i++) {
- ds[i].d_base = cpu_to_le32(pci64_dma_lo32(sg_dma_address(sg)));
- ds[i].d_base_hi = cpu_to_le32(pci64_dma_hi32(sg_dma_address(sg)));
- ds[i].d_count = cpu_to_le32(sg_dma_len(sg));
- ++sg;
- }
- sg_count -= DATASEGS_PER_COMMAND;
-
- while (sg_count > 0) {
- ++cmd->hdr.entry_cnt;
- cont = (struct Continuation_Entry *)
- &hostdata->req[in_ptr*QUEUE_ENTRY_LEN];
- memset(cont, 0, sizeof(struct Continuation_Entry));
- in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
- if (in_ptr == out_ptr) {
- DEBUG(printk("qlogicfc%d : unexpected request queue overflow\n", hostdata->host_id));
- return 1;
- }
- TRACE("queue continuation", in_ptr, 0);
- cont->hdr.entry_type = ENTRY_CONTINUATION;
- ds = cont->dataseg;
- n = sg_count;
- if (n > DATASEGS_PER_CONT)
- n = DATASEGS_PER_CONT;
- for (i = 0; i < n; ++i) {
- ds[i].d_base = cpu_to_le32(pci64_dma_lo32(sg_dma_address(sg)));
- ds[i].d_base_hi = cpu_to_le32(pci64_dma_hi32(sg_dma_address(sg)));
- ds[i].d_count = cpu_to_le32(sg_dma_len(sg));
- ++sg;
- }
- sg_count -= n;
- }
- } else if (Cmnd->request_bufflen && Cmnd->sc_data_direction != PCI_DMA_NONE) {
- struct page *page = virt_to_page(Cmnd->request_buffer);
- unsigned long offset = offset_in_page(Cmnd->request_buffer);
- dma_addr_t busaddr = pci_map_page(hostdata->pci_dev,
- page, offset,
- Cmnd->request_bufflen,
- Cmnd->sc_data_direction);
- Cmnd->SCp.dma_handle = busaddr;
-
- cmd->dataseg[0].d_base = cpu_to_le32(pci64_dma_lo32(busaddr));
- cmd->dataseg[0].d_base_hi = cpu_to_le32(pci64_dma_hi32(busaddr));
- cmd->dataseg[0].d_count = cpu_to_le32(Cmnd->request_bufflen);
- cmd->segment_cnt = cpu_to_le16(1);
- } else {
- cmd->dataseg[0].d_base = 0;
- cmd->dataseg[0].d_base_hi = 0;
- cmd->segment_cnt = cpu_to_le16(1); /* Shouldn't this be 0? */
- }
-
- if (Cmnd->sc_data_direction == DMA_TO_DEVICE)
- cmd->control_flags = cpu_to_le16(CFLAG_WRITE);
- else
- cmd->control_flags = cpu_to_le16(CFLAG_READ);
-
- if (Cmnd->device->tagged_supported) {
- if ((jiffies - hostdata->tag_ages[Cmnd->device->id]) > (2 * ISP_TIMEOUT)) {
- cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG);
- hostdata->tag_ages[Cmnd->device->id] = jiffies;
- } else
- switch (Cmnd->tag) {
- case HEAD_OF_QUEUE_TAG:
- cmd->control_flags |= cpu_to_le16(CFLAG_HEAD_TAG);
- break;
- case ORDERED_QUEUE_TAG:
- cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG);
- break;
- default:
- cmd->control_flags |= cpu_to_le16(CFLAG_SIMPLE_TAG);
- break;
- }
- }
- /*
- * TEST_UNIT_READY commands from scsi_scan will fail due to "overlapped
- * commands attempted" unless we setup at least a simple queue (midlayer
- * will embelish this once it can do an INQUIRY command to the device)
- */
- else
- cmd->control_flags |= cpu_to_le16(CFLAG_SIMPLE_TAG);
- outw(in_ptr, host->io_port + MBOX4);
- hostdata->req_in_ptr = in_ptr;
-
- hostdata->queued++;
-
- num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
- num_free = (num_free > 2) ? num_free - 2 : 0;
- host->can_queue = host->host_busy + num_free;
- if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN)
- host->can_queue = QLOGICFC_REQ_QUEUE_LEN;
- host->sg_tablesize = QLOGICFC_MAX_SG(num_free);
-
- LEAVE("isp2x00_queuecommand");
-
- return 0;
-}
-
-
-/* we have received an event, such as a lip or an RSCN, which may mean that
- * our port database is incorrect so the port database must be recreated.
- */
-static void redo_port_db(unsigned long arg)
-{
-
- struct Scsi_Host * host = (struct Scsi_Host *) arg;
- struct isp2x00_hostdata * hostdata;
- unsigned long flags;
- int i;
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
- hostdata->explore_timer.data = 0;
- del_timer(&hostdata->explore_timer);
-
- spin_lock_irqsave(host->host_lock, flags);
-
- if (hostdata->adapter_state & AS_REDO_FABRIC_PORTDB || hostdata->adapter_state & AS_REDO_LOOP_PORTDB) {
- isp2x00_make_portdb(host);
- printk("qlogicfc%d : Port Database\n", hostdata->host_id);
- for (i = 0; hostdata->port_db[i].wwn != 0; i++) {
- printk("wwn: %08x%08x scsi_id: %x loop_id: ", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i);
- if (hostdata->port_db[i].loop_id != hostdata->port_db[0].loop_id || i == 0)
- printk("%x", hostdata->port_db[i].loop_id);
- else
- printk("Not Available");
- printk("\n");
- }
-
- for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++){
- if (hostdata->handle_ptrs[i] && (hostdata->port_db[hostdata->handle_ptrs[i]->device->id].loop_id > QLOGICFC_MAX_LOOP_ID || hostdata->adapter_state & AS_REDO_LOOP_PORTDB)){
- if (hostdata->port_db[hostdata->handle_ptrs[i]->device->id].loop_id != hostdata->port_db[0].loop_id){
- Scsi_Cmnd *Cmnd = hostdata->handle_ptrs[i];
-
- if (Cmnd->use_sg)
- pci_unmap_sg(hostdata->pci_dev,
- (struct scatterlist *)Cmnd->buffer,
- Cmnd->use_sg,
- Cmnd->sc_data_direction);
- else if (Cmnd->request_bufflen &&
- Cmnd->sc_data_direction != PCI_DMA_NONE) {
- pci_unmap_page(hostdata->pci_dev,
- Cmnd->SCp.dma_handle,
- Cmnd->request_bufflen,
- Cmnd->sc_data_direction);
- }
-
- hostdata->handle_ptrs[i]->result = DID_SOFT_ERROR << 16;
-
- if (hostdata->handle_ptrs[i]->scsi_done){
- (*hostdata->handle_ptrs[i]->scsi_done) (hostdata->handle_ptrs[i]);
- }
- else printk("qlogicfc%d : done is null?\n", hostdata->host_id);
- hostdata->handle_ptrs[i] = NULL;
- hostdata->handle_serials[i] = 0;
- }
- }
- }
-
- hostdata->adapter_state = AS_LOOP_GOOD;
- }
-
- spin_unlock_irqrestore(host->host_lock, flags);
-
-}
-
-#define ASYNC_EVENT_INTERRUPT 0x01
-
-irqreturn_t do_isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct Scsi_Host *host = dev_id;
- unsigned long flags;
-
- spin_lock_irqsave(host->host_lock, flags);
- isp2x00_intr_handler(irq, dev_id, regs);
- spin_unlock_irqrestore(host->host_lock, flags);
-
- return IRQ_HANDLED;
-}
-
-void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
- Scsi_Cmnd *Cmnd;
- struct Status_Entry *sts;
- struct Scsi_Host *host = dev_id;
- struct isp2x00_hostdata *hostdata;
- u_int in_ptr, out_ptr, handle, num_free;
- u_short status;
-
- ENTER_INTR("isp2x00_intr_handler");
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- DEBUG_INTR(printk("qlogicfc%d : interrupt on line %d\n", hostdata->host_id, irq));
-
- if (!(inw(host->io_port + PCI_INTER_STS) & 0x08)) {
- /* spurious interrupts can happen legally */
- DEBUG_INTR(printk("qlogicfc%d : got spurious interrupt\n", hostdata->host_id));
- return;
- }
- in_ptr = inw(host->io_port + MBOX5);
- out_ptr = hostdata->res_out_ptr;
-
- if ((inw(host->io_port + PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) {
- status = inw(host->io_port + MBOX0);
-
- DEBUG_INTR(printk("qlogicfc%d : mbox completion status: %x\n",
- hostdata->host_id, status));
-
- switch (status) {
- case LOOP_UP:
- case POINT_TO_POINT_UP:
- printk("qlogicfc%d : Link is Up\n", hostdata->host_id);
- hostdata->adapter_state = AS_REDO_FABRIC_PORTDB | AS_REDO_LOOP_PORTDB;
- break;
- case LOOP_DOWN:
- printk("qlogicfc%d : Link is Down\n", hostdata->host_id);
- hostdata->adapter_state = AS_LOOP_DOWN;
- break;
- case CONNECTION_MODE:
- printk("received CONNECTION_MODE irq %x\n", inw(host->io_port + MBOX1));
- break;
- case CHANGE_NOTIFICATION:
- printk("qlogicfc%d : RSCN Received\n", hostdata->host_id);
- if (hostdata->adapter_state == AS_LOOP_GOOD)
- hostdata->adapter_state = AS_REDO_FABRIC_PORTDB;
- break;
- case LIP_OCCURRED:
- case LIP_RECEIVED:
- printk("qlogicfc%d : Loop Reinitialized\n", hostdata->host_id);
- if (hostdata->adapter_state == AS_LOOP_GOOD)
- hostdata->adapter_state = AS_REDO_LOOP_PORTDB;
- break;
- case SYSTEM_ERROR:
- printk("qlogicfc%d : The firmware just choked.\n", hostdata->host_id);
- hostdata->adapter_state = AS_FIRMWARE_DEAD;
- break;
- case SCSI_COMMAND_COMPLETE:
- handle = inw(host->io_port + MBOX1) | (inw(host->io_port + MBOX2) << 16);
- Cmnd = hostdata->handle_ptrs[handle];
- hostdata->handle_ptrs[handle] = NULL;
- hostdata->handle_serials[handle] = 0;
- hostdata->queued--;
- if (Cmnd != NULL) {
- if (Cmnd->use_sg)
- pci_unmap_sg(hostdata->pci_dev,
- (struct scatterlist *)Cmnd->buffer,
- Cmnd->use_sg,
- Cmnd->sc_data_direction);
- else if (Cmnd->request_bufflen &&
- Cmnd->sc_data_direction != PCI_DMA_NONE)
- pci_unmap_page(hostdata->pci_dev,
- Cmnd->SCp.dma_handle,
- Cmnd->request_bufflen,
- Cmnd->sc_data_direction);
- Cmnd->result = 0x0;
- (*Cmnd->scsi_done) (Cmnd);
- } else
- printk("qlogicfc%d.c : got a null value out of handle_ptrs, this sucks\n", hostdata->host_id);
- break;
- case MBOX_COMMAND_COMPLETE:
- case INVALID_COMMAND:
- case HOST_INTERFACE_ERROR:
- case TEST_FAILED:
- case COMMAND_ERROR:
- case COMMAND_PARAM_ERROR:
- case PORT_ID_USED:
- case LOOP_ID_USED:
- case ALL_IDS_USED:
- hostdata->mbox_done = 1;
- outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
- return;
- default:
- printk("qlogicfc%d : got an unknown status? %x\n", hostdata->host_id, status);
- }
- if ((hostdata->adapter_state & AS_REDO_LOOP_PORTDB || hostdata->adapter_state & AS_REDO_FABRIC_PORTDB) && hostdata->explore_timer.data == 0){
- hostdata->explore_timer.function = redo_port_db;
- hostdata->explore_timer.data = (unsigned long)host;
- hostdata->explore_timer.expires = jiffies + (HZ/4);
- init_timer(&hostdata->explore_timer);
- add_timer(&hostdata->explore_timer);
- }
- outw(0x0, host->io_port + PCI_SEMAPHORE);
- } else {
- DEBUG_INTR(printk("qlogicfc%d : response queue update\n", hostdata->host_id));
- DEBUG_INTR(printk("qlogicfc%d : response queue depth %d\n", hostdata->host_id, RES_QUEUE_DEPTH(in_ptr, out_ptr)));
-
- while (out_ptr != in_ptr) {
- unsigned le_hand;
- sts = (struct Status_Entry *) &hostdata->res[out_ptr*QUEUE_ENTRY_LEN];
- out_ptr = (out_ptr + 1) & RES_QUEUE_LEN;
-
- TRACE("done", out_ptr, Cmnd);
- DEBUG_INTR(isp2x00_print_status_entry(sts));
- le_hand = le32_to_cpu(sts->handle);
- if (sts->hdr.entry_type == ENTRY_STATUS && (Cmnd = hostdata->handle_ptrs[le_hand])) {
- Cmnd->result = isp2x00_return_status(Cmnd, sts);
- hostdata->queued--;
-
- if (Cmnd->use_sg)
- pci_unmap_sg(hostdata->pci_dev,
- (struct scatterlist *)Cmnd->buffer, Cmnd->use_sg,
- Cmnd->sc_data_direction);
- else if (Cmnd->request_bufflen && Cmnd->sc_data_direction != PCI_DMA_NONE)
- pci_unmap_page(hostdata->pci_dev,
- Cmnd->SCp.dma_handle,
- Cmnd->request_bufflen,
- Cmnd->sc_data_direction);
-
- /*
- * if any of the following are true we do not
- * call scsi_done. if the status is CS_ABORTED
- * we don't have to call done because the upper
- * level should already know its aborted.
- */
- if (hostdata->handle_serials[le_hand] != Cmnd->serial_number
- || le16_to_cpu(sts->completion_status) == CS_ABORTED){
- hostdata->handle_serials[le_hand] = 0;
- hostdata->handle_ptrs[le_hand] = NULL;
- outw(out_ptr, host->io_port + MBOX5);
- continue;
- }
- /*
- * if we get back an error indicating the port
- * is not there or if the link is down and
- * this is a device that used to be there
- * allow the command to timeout.
- * the device may well be back in a couple of
- * seconds.
- */
- if ((hostdata->adapter_state == AS_LOOP_DOWN || sts->completion_status == cpu_to_le16(CS_PORT_UNAVAILABLE) || sts->completion_status == cpu_to_le16(CS_PORT_LOGGED_OUT) || sts->completion_status == cpu_to_le16(CS_PORT_CONFIG_CHANGED)) && hostdata->port_db[Cmnd->device->id].wwn){
- outw(out_ptr, host->io_port + MBOX5);
- continue;
- }
- } else {
- outw(out_ptr, host->io_port + MBOX5);
- continue;
- }
-
- hostdata->handle_ptrs[le_hand] = NULL;
-
- if (sts->completion_status == cpu_to_le16(CS_RESET_OCCURRED)
- || (sts->status_flags & cpu_to_le16(STF_BUS_RESET)))
- hostdata->send_marker = 1;
-
- if (le16_to_cpu(sts->scsi_status) & 0x0200)
- memcpy(Cmnd->sense_buffer, sts->req_sense_data,
- sizeof(Cmnd->sense_buffer));
-
- outw(out_ptr, host->io_port + MBOX5);
-
- if (Cmnd->scsi_done != NULL) {
- (*Cmnd->scsi_done) (Cmnd);
- } else
- printk("qlogicfc%d : Ouch, scsi done is NULL\n", hostdata->host_id);
- }
- hostdata->res_out_ptr = out_ptr;
- }
-
-
- out_ptr = inw(host->io_port + MBOX4);
- in_ptr = hostdata->req_in_ptr;
-
- num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
- num_free = (num_free > 2) ? num_free - 2 : 0;
- host->can_queue = host->host_busy + num_free;
- if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN)
- host->can_queue = QLOGICFC_REQ_QUEUE_LEN;
- host->sg_tablesize = QLOGICFC_MAX_SG(num_free);
-
- outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
- LEAVE_INTR("isp2x00_intr_handler");
-}
-
-
-static int isp2x00_return_status(Scsi_Cmnd *Cmnd, struct Status_Entry *sts)
-{
- int host_status = DID_ERROR;
-#if DEBUG_ISP2x00_INTR
- static char *reason[] =
- {
- "DID_OK",
- "DID_NO_CONNECT",
- "DID_BUS_BUSY",
- "DID_TIME_OUT",
- "DID_BAD_TARGET",
- "DID_ABORT",
- "DID_PARITY",
- "DID_ERROR",
- "DID_RESET",
- "DID_BAD_INTR"
- };
-#endif /* DEBUG_ISP2x00_INTR */
-
- ENTER("isp2x00_return_status");
-
- DEBUG(printk("qlogicfc : completion status = 0x%04x\n",
- le16_to_cpu(sts->completion_status)));
-
- switch (le16_to_cpu(sts->completion_status)) {
- case CS_COMPLETE:
- host_status = DID_OK;
- break;
- case CS_DMA_ERROR:
- host_status = DID_ERROR;
- break;
- case CS_RESET_OCCURRED:
- host_status = DID_RESET;
- break;
- case CS_ABORTED:
- host_status = DID_ABORT;
- break;
- case CS_TIMEOUT:
- host_status = DID_TIME_OUT;
- break;
- case CS_DATA_OVERRUN:
- host_status = DID_ERROR;
- break;
- case CS_DATA_UNDERRUN:
- if (Cmnd->underflow <= (Cmnd->request_bufflen - le32_to_cpu(sts->residual)))
- host_status = DID_OK;
- else
- host_status = DID_ERROR;
- break;
- case CS_PORT_UNAVAILABLE:
- case CS_PORT_LOGGED_OUT:
- case CS_PORT_CONFIG_CHANGED:
- host_status = DID_BAD_TARGET;
- break;
- case CS_QUEUE_FULL:
- host_status = DID_ERROR;
- break;
- default:
- printk("qlogicfc : unknown completion status 0x%04x\n",
- le16_to_cpu(sts->completion_status));
- host_status = DID_ERROR;
- break;
- }
-
- DEBUG_INTR(printk("qlogicfc : host status (%s) scsi status %x\n",
- reason[host_status], le16_to_cpu(sts->scsi_status)));
-
- LEAVE("isp2x00_return_status");
-
- return (le16_to_cpu(sts->scsi_status) & STATUS_MASK) | (host_status << 16);
-}
-
-
-static int isp2x00_abort(Scsi_Cmnd * Cmnd)
-{
- u_short param[8];
- int i;
- struct Scsi_Host *host;
- struct isp2x00_hostdata *hostdata;
- int return_status = SUCCESS;
-
- ENTER("isp2x00_abort");
-
- host = Cmnd->device->host;
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++)
- if (hostdata->handle_ptrs[i] == Cmnd)
- break;
-
- if (i == QLOGICFC_REQ_QUEUE_LEN){
- return SUCCESS;
- }
-
- isp2x00_disable_irqs(host);
-
- param[0] = MBOX_ABORT_IOCB;
-#if ISP2x00_PORTDB
- param[1] = (((u_short) hostdata->port_db[Cmnd->device->id].loop_id) << 8) | Cmnd->device->lun;
-#else
- param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun;
-#endif
- param[2] = i & 0xffff;
- param[3] = i >> 16;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d : scsi abort failure: %x\n", hostdata->host_id, param[0]);
- if (param[0] == 0x4005)
- Cmnd->result = DID_ERROR << 16;
- if (param[0] == 0x4006)
- Cmnd->result = DID_BAD_TARGET << 16;
- return_status = FAILED;
- }
-
- if (return_status != SUCCESS){
- param[0] = MBOX_GET_FIRMWARE_STATE;
- isp2x00_mbox_command(host, param);
- printk("qlogicfc%d : abort failed\n", hostdata->host_id);
- printk("qlogicfc%d : firmware status is %x %x\n", hostdata->host_id, param[0], param[1]);
- }
-
- isp2x00_enable_irqs(host);
-
- LEAVE("isp2x00_abort");
-
- return return_status;
-}
-
-
-static int isp2x00_biosparam(struct scsi_device *sdev, struct block_device *n,
- sector_t capacity, int ip[])
-{
- int size = capacity;
-
- ENTER("isp2x00_biosparam");
-
- ip[0] = 64;
- ip[1] = 32;
- ip[2] = size >> 11;
- if (ip[2] > 1024) {
- ip[0] = 255;
- ip[1] = 63;
- ip[2] = size / (ip[0] * ip[1]);
- }
- LEAVE("isp2x00_biosparam");
-
- return 0;
-}
-
-static int isp2x00_reset_hardware(struct Scsi_Host *host)
-{
- u_short param[8];
- struct isp2x00_hostdata *hostdata;
- int loop_count;
- dma_addr_t busaddr;
-
- ENTER("isp2x00_reset_hardware");
-
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- /*
- * This cannot be right - PCI writes are posted
- * (apparently this is hardware design flaw not software ?)
- */
-
- outw(0x01, host->io_port + ISP_CTRL_STATUS);
- udelay(100);
- outw(HCCR_RESET, host->io_port + HOST_HCCR);
- udelay(100);
- outw(HCCR_RELEASE, host->io_port + HOST_HCCR);
- outw(HCCR_BIOS_DISABLE, host->io_port + HOST_HCCR);
-
- loop_count = DEFAULT_LOOP_COUNT;
- while (--loop_count && inw(host->io_port + HOST_HCCR) == RISC_BUSY) {
- barrier();
- cpu_relax();
- }
- if (!loop_count)
- printk("qlogicfc%d : reset_hardware loop timeout\n", hostdata->host_id);
-
-
-
-#if DEBUG_ISP2x00
- printk("qlogicfc%d : mbox 0 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX0));
- printk("qlogicfc%d : mbox 1 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX1));
- printk("qlogicfc%d : mbox 2 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX2));
- printk("qlogicfc%d : mbox 3 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX3));
- printk("qlogicfc%d : mbox 4 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX4));
- printk("qlogicfc%d : mbox 5 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX5));
- printk("qlogicfc%d : mbox 6 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX6));
- printk("qlogicfc%d : mbox 7 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX7));
-#endif /* DEBUG_ISP2x00 */
-
- DEBUG(printk("qlogicfc%d : verifying checksum\n", hostdata->host_id));
-
-#if defined(CONFIG_SCSI_QLOGIC_FC_FIRMWARE)
- {
- int i;
- unsigned short * risc_code = NULL;
- unsigned short risc_code_len = 0;
- if (hostdata->pci_dev->device == PCI_DEVICE_ID_QLOGIC_ISP2100){
- risc_code = risc_code2100;
- risc_code_len = risc_code_length2100;
- }
- else if (hostdata->pci_dev->device == PCI_DEVICE_ID_QLOGIC_ISP2200){
- risc_code = risc_code2200;
- risc_code_len = risc_code_length2200;
- }
-
- for (i = 0; i < risc_code_len; i++) {
- param[0] = MBOX_WRITE_RAM_WORD;
- param[1] = risc_code_addr01 + i;
- param[2] = risc_code[i];
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d : firmware load failure\n", hostdata->host_id);
- return 1;
- }
- }
- }
-#endif /* RELOAD_FIRMWARE */
-
- param[0] = MBOX_VERIFY_CHECKSUM;
- param[1] = risc_code_addr01;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d : ram checksum failure\n", hostdata->host_id);
- return 1;
- }
- DEBUG(printk("qlogicfc%d : executing firmware\n", hostdata->host_id));
-
- param[0] = MBOX_EXEC_FIRMWARE;
- param[1] = risc_code_addr01;
-
- isp2x00_mbox_command(host, param);
-
- param[0] = MBOX_ABOUT_FIRMWARE;
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d : about firmware failure\n", hostdata->host_id);
- return 1;
- }
- DEBUG(printk("qlogicfc%d : firmware major revision %d\n", hostdata->host_id, param[1]));
- DEBUG(printk("qlogicfc%d : firmware minor revision %d\n", hostdata->host_id, param[2]));
-
-#ifdef USE_NVRAM_DEFAULTS
-
- if (isp2x00_get_nvram_defaults(host, &hostdata->control_block) != 0) {
- printk("qlogicfc%d : Could not read from NVRAM\n", hostdata->host_id);
- }
-#endif
-
- hostdata->wwn = (u64) (cpu_to_le16(hostdata->control_block.node_name[0])) << 56;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[0]) & 0xff00) << 48;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[1]) & 0xff00) << 24;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[1]) & 0x00ff) << 48;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[2]) & 0x00ff) << 24;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[2]) & 0xff00) << 8;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[3]) & 0x00ff) << 8;
- hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[3]) & 0xff00) >> 8;
-
- /* FIXME: If the DMA transfer goes one way only, this should use
- * PCI_DMA_TODEVICE and below as well.
- */
- busaddr = pci_map_page(hostdata->pci_dev,
- virt_to_page(&hostdata->control_block),
- offset_in_page(&hostdata->control_block),
- sizeof(hostdata->control_block),
- PCI_DMA_BIDIRECTIONAL);
-
- param[0] = MBOX_INIT_FIRMWARE;
- param[2] = (u_short) (pci64_dma_lo32(busaddr) >> 16);
- param[3] = (u_short) (pci64_dma_lo32(busaddr) & 0xffff);
- param[4] = 0;
- param[5] = 0;
- param[6] = (u_short) (pci64_dma_hi32(busaddr) >> 16);
- param[7] = (u_short) (pci64_dma_hi32(busaddr) & 0xffff);
- isp2x00_mbox_command(host, param);
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d.c: Ouch 0x%04x\n", hostdata->host_id, param[0]);
- pci_unmap_page(hostdata->pci_dev, busaddr,
- sizeof(hostdata->control_block),
- PCI_DMA_BIDIRECTIONAL);
- return 1;
- }
- param[0] = MBOX_GET_FIRMWARE_STATE;
- isp2x00_mbox_command(host, param);
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d.c: 0x%04x\n", hostdata->host_id, param[0]);
- pci_unmap_page(hostdata->pci_dev, busaddr,
- sizeof(hostdata->control_block),
- PCI_DMA_BIDIRECTIONAL);
- return 1;
- }
-
- pci_unmap_page(hostdata->pci_dev, busaddr,
- sizeof(hostdata->control_block),
- PCI_DMA_BIDIRECTIONAL);
- LEAVE("isp2x00_reset_hardware");
-
- return 0;
-}
-
-#ifdef USE_NVRAM_DEFAULTS
-
-static int isp2x00_get_nvram_defaults(struct Scsi_Host *host, struct init_cb *control_block)
-{
-
- u_short value;
- if (isp2x00_read_nvram_word(host, 0) != 0x5349)
- return 1;
-
- value = isp2x00_read_nvram_word(host, 8);
- control_block->node_name[0] = cpu_to_le16(isp2x00_read_nvram_word(host, 9));
- control_block->node_name[1] = cpu_to_le16(isp2x00_read_nvram_word(host, 10));
- control_block->node_name[2] = cpu_to_le16(isp2x00_read_nvram_word(host, 11));
- control_block->node_name[3] = cpu_to_le16(isp2x00_read_nvram_word(host, 12));
- control_block->hard_addr = cpu_to_le16(isp2x00_read_nvram_word(host, 13));
-
- return 0;
-
-}
-
-#endif
-
-static int isp2x00_init(struct Scsi_Host *sh)
-{
- u_long io_base;
- struct isp2x00_hostdata *hostdata;
- u_char revision;
- u_int irq;
- u_short command;
- struct pci_dev *pdev;
-
-
- ENTER("isp2x00_init");
-
- hostdata = (struct isp2x00_hostdata *) sh->hostdata;
- pdev = hostdata->pci_dev;
-
- if (pci_read_config_word(pdev, PCI_COMMAND, &command)
- || pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision)) {
- printk("qlogicfc%d : error reading PCI configuration\n", hostdata->host_id);
- return 1;
- }
- io_base = pci_resource_start(pdev, 0);
- irq = pdev->irq;
-
-
- if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) {
- printk("qlogicfc%d : 0x%04x is not QLogic vendor ID\n", hostdata->host_id,
- pdev->vendor);
- return 1;
- }
- if (pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2100 && pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2200) {
- printk("qlogicfc%d : 0x%04x does not match ISP2100 or ISP2200 device id\n", hostdata->host_id,
- pdev->device);
- return 1;
- }
- if (!(command & PCI_COMMAND_IO) ||
- !(pdev->resource[0].flags & IORESOURCE_IO)) {
- printk("qlogicfc%d : i/o mapping is disabled\n", hostdata->host_id);
- return 1;
- }
-
- pci_set_master(pdev);
- if (revision != ISP2100_REV_ID1 && revision != ISP2100_REV_ID3 && revision != ISP2200_REV_ID5)
- printk("qlogicfc%d : new isp2x00 revision ID (%d)\n", hostdata->host_id, revision);
-
-
- hostdata->revision = revision;
-
- sh->irq = irq;
- sh->io_port = io_base;
-
- LEAVE("isp2x00_init");
-
- return 0;
-}
-
-#if USE_NVRAM_DEFAULTS
-
-#define NVRAM_DELAY() udelay(10) /* 10 microsecond delay */
-
-
-u_short isp2x00_read_nvram_word(struct Scsi_Host * host, u_short byte)
-{
- int i;
- u_short value, output, input;
-
- outw(0x2, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- outw(0x3, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
-
- byte &= 0xff;
- byte |= 0x0600;
- for (i = 10; i >= 0; i--) {
- output = ((byte >> i) & 0x1) ? 0x4 : 0x0;
- outw(output | 0x2, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- outw(output | 0x3, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- outw(output | 0x2, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- }
-
- for (i = 0xf, value = 0; i >= 0; i--) {
- value <<= 1;
- outw(0x3, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- input = inw(host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- outw(0x2, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
- if (input & 0x8)
- value |= 1;
- }
-
- outw(0x0, host->io_port + PCI_NVRAM);
- NVRAM_DELAY();
-
- return value;
-}
-
-
-#endif /* USE_NVRAM_DEFAULTS */
-
-
-
-/*
- * currently, this is only called during initialization or abort/reset,
- * at which times interrupts are disabled, so polling is OK, I guess...
- */
-static int isp2x00_mbox_command(struct Scsi_Host *host, u_short param[])
-{
- int loop_count;
- struct isp2x00_hostdata *hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
- if (mbox_param[param[0]] == 0 || hostdata->adapter_state == AS_FIRMWARE_DEAD)
- return 1;
-
- loop_count = DEFAULT_LOOP_COUNT;
- while (--loop_count && inw(host->io_port + HOST_HCCR) & 0x0080) {
- barrier();
- cpu_relax();
- }
- if (!loop_count) {
- printk("qlogicfc%d : mbox_command loop timeout #1\n", hostdata->host_id);
- param[0] = 0x4006;
- hostdata->adapter_state = AS_FIRMWARE_DEAD;
- return 1;
- }
- hostdata->mbox_done = 0;
-
- if (mbox_param[param[0]] == 0)
- printk("qlogicfc%d : invalid mbox command\n", hostdata->host_id);
-
- if (mbox_param[param[0]] & 0x80)
- outw(param[7], host->io_port + MBOX7);
- if (mbox_param[param[0]] & 0x40)
- outw(param[6], host->io_port + MBOX6);
- if (mbox_param[param[0]] & 0x20)
- outw(param[5], host->io_port + MBOX5);
- if (mbox_param[param[0]] & 0x10)
- outw(param[4], host->io_port + MBOX4);
- if (mbox_param[param[0]] & 0x08)
- outw(param[3], host->io_port + MBOX3);
- if (mbox_param[param[0]] & 0x04)
- outw(param[2], host->io_port + MBOX2);
- if (mbox_param[param[0]] & 0x02)
- outw(param[1], host->io_port + MBOX1);
- if (mbox_param[param[0]] & 0x01)
- outw(param[0], host->io_port + MBOX0);
-
-
- outw(HCCR_SET_HOST_INTR, host->io_port + HOST_HCCR);
-
- while (1) {
- loop_count = DEFAULT_LOOP_COUNT;
- while (--loop_count && !(inw(host->io_port + PCI_INTER_STS) & 0x08)) {
- barrier();
- cpu_relax();
- }
-
- if (!loop_count) {
- hostdata->adapter_state = AS_FIRMWARE_DEAD;
- printk("qlogicfc%d : mbox_command loop timeout #2\n", hostdata->host_id);
- break;
- }
- isp2x00_intr_handler(host->irq, host, NULL);
-
- if (hostdata->mbox_done == 1)
- break;
-
- }
-
- loop_count = DEFAULT_LOOP_COUNT;
- while (--loop_count && inw(host->io_port + MBOX0) == 0x04) {
- barrier();
- cpu_relax();
- }
- if (!loop_count)
- printk("qlogicfc%d : mbox_command loop timeout #3\n", hostdata->host_id);
-
- param[7] = inw(host->io_port + MBOX7);
- param[6] = inw(host->io_port + MBOX6);
- param[5] = inw(host->io_port + MBOX5);
- param[4] = inw(host->io_port + MBOX4);
- param[3] = inw(host->io_port + MBOX3);
- param[2] = inw(host->io_port + MBOX2);
- param[1] = inw(host->io_port + MBOX1);
- param[0] = inw(host->io_port + MBOX0);
-
-
- outw(0x0, host->io_port + PCI_SEMAPHORE);
-
- if (inw(host->io_port + HOST_HCCR) & 0x0080) {
- hostdata->adapter_state = AS_FIRMWARE_DEAD;
- printk("qlogicfc%d : mbox op is still pending\n", hostdata->host_id);
- }
- return 0;
-}
-
-#if DEBUG_ISP2x00_INTR
-
-void isp2x00_print_status_entry(struct Status_Entry *status)
-{
- printk("qlogicfc : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n",
- status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags);
- printk("qlogicfc : scsi status = 0x%04x, completion status = 0x%04x\n",
- le16_to_cpu(status->scsi_status), le16_to_cpu(status->completion_status));
- printk("qlogicfc : state flags = 0x%04x, status flags = 0x%04x\n",
- le16_to_cpu(status->state_flags), le16_to_cpu(status->status_flags));
- printk("qlogicfc : response info length = 0x%04x, request sense length = 0x%04x\n",
- le16_to_cpu(status->res_info_len), le16_to_cpu(status->req_sense_len));
- printk("qlogicfc : residual transfer length = 0x%08x, response = 0x%02x\n", le32_to_cpu(status->residual), status->res_info[3]);
-
-}
-
-#endif /* DEBUG_ISP2x00_INTR */
-
-
-#if DEBUG_ISP2x00
-
-void isp2x00_print_scsi_cmd(Scsi_Cmnd * cmd)
-{
- int i;
-
- printk("qlogicfc : target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n",
- cmd->target, cmd->lun, cmd->cmd_len);
- printk("qlogicfc : command = ");
- for (i = 0; i < cmd->cmd_len; i++)
- printk("0x%02x ", cmd->cmnd[i]);
- printk("\n");
-}
-
-#endif /* DEBUG_ISP2x00 */
-
-MODULE_LICENSE("GPL");
-
-static struct scsi_host_template driver_template = {
- .detect = isp2x00_detect,
- .release = isp2x00_release,
- .info = isp2x00_info,
- .queuecommand = isp2x00_queuecommand,
- .eh_abort_handler = isp2x00_abort,
- .bios_param = isp2x00_biosparam,
- .can_queue = QLOGICFC_REQ_QUEUE_LEN,
- .this_id = -1,
- .sg_tablesize = QLOGICFC_MAX_SG(QLOGICFC_REQ_QUEUE_LEN),
- .cmd_per_lun = QLOGICFC_CMD_PER_LUN,
- .use_clustering = ENABLE_CLUSTERING,
-};
-#include "scsi_module.c"
diff --git a/drivers/scsi/qlogicfc_asm.c b/drivers/scsi/qlogicfc_asm.c
deleted file mode 100644
index b1d45102d38..00000000000
--- a/drivers/scsi/qlogicfc_asm.c
+++ /dev/null
@@ -1,9751 +0,0 @@
-/************************************************************************
- * *
- * --- ISP2100 Fabric Initiator/Target Firmware --- *
- * with expanded LUN addressing *
- * and FcTape (FCP-2) support *
- * *
- * *
- ************************************************************************
- Copyright (C) 2000 and 2001 Qlogic Corporation
- (www.qlogic.com)
-
- 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.
-************************************************************************/
-
-/*
- * Firmware Version 1.19.16 (10:36 Nov 02, 2000)
- */
-
-static unsigned short risc_code_addr01 = 0x1000 ;
-
-static unsigned short risc_code_length2100 = 0x9260;
-static unsigned short risc_code2100[] = {
- 0x0078, 0x102d, 0x0000, 0x9260, 0x0000, 0x0001, 0x0013, 0x0010,
- 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939,
- 0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
- 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3231, 0x3030, 0x2046, 0x6972,
- 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030,
- 0x312e, 0x3139, 0x2020, 0x2020, 0x2400, 0x2091, 0x2000, 0x20c1,
- 0x0021, 0x2039, 0xffff, 0x2019, 0xaaaa, 0x2760, 0x2069, 0x7fff,
- 0x20c1, 0x0020, 0x2c2c, 0x2d34, 0x2762, 0x236a, 0x2c24, 0x2d04,
- 0x266a, 0x2562, 0xa406, 0x00c0, 0x1052, 0x20c1, 0x0021, 0x2c2c,
- 0x2362, 0x2c04, 0x2562, 0xa306, 0x0040, 0x1052, 0x20c1, 0x0020,
- 0x2039, 0x8fff, 0x20a1, 0xaa00, 0x2708, 0x810d, 0x810d, 0x810d,
- 0x810d, 0xa18c, 0x000f, 0x2001, 0x000a, 0xa112, 0xa00e, 0x21a8,
- 0x41a4, 0x3400, 0x8211, 0x00c0, 0x105f, 0x2708, 0x3400, 0xa102,
- 0x0040, 0x106f, 0x0048, 0x106f, 0x20a8, 0xa00e, 0x41a4, 0x20a1,
- 0xa260, 0x2009, 0x0000, 0x20a9, 0x07a0, 0x41a4, 0x3400, 0x20c9,
- 0xa7ff, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x255d,
- 0x2051, 0xa300, 0x2a70, 0x775e, 0xa786, 0x8fff, 0x0040, 0x1092,
- 0x705b, 0xca00, 0x7057, 0xc9f1, 0x7063, 0x0200, 0x7067, 0x0200,
- 0x0078, 0x109a, 0x7057, 0xba01, 0x7063, 0x0100, 0x7067, 0x0100,
- 0x705b, 0xba00, 0x1078, 0x12df, 0x1078, 0x13c0, 0x1078, 0x1569,
- 0x1078, 0x1ca4, 0x1078, 0x4229, 0x1078, 0x74cf, 0x1078, 0x134b,
- 0x1078, 0x2a3f, 0x1078, 0x4da2, 0x1078, 0x48b2, 0x1078, 0x57df,
- 0x1078, 0x21f7, 0x1078, 0x5abf, 0x1078, 0x5369, 0x1078, 0x210d,
- 0x1078, 0x21d4, 0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x10cf,
- 0x7820, 0xa086, 0x0002, 0x00c0, 0x10cf, 0x7823, 0x4000, 0x0068,
- 0x10c7, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70,
- 0x7003, 0x0000, 0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000,
- 0xa08e, 0x0003, 0x00c0, 0x10ef, 0x1078, 0x35bc, 0x1078, 0x2a67,
- 0x1078, 0x4df2, 0x1078, 0x4a75, 0x2009, 0x0100, 0x2104, 0xa082,
- 0x0002, 0x0048, 0x10f3, 0x1078, 0x57fb, 0x0078, 0x10d6, 0x1079,
- 0x10f7, 0x0078, 0x10dc, 0x1078, 0x6fa9, 0x0078, 0x10eb, 0x1101,
- 0x1102, 0x11be, 0x10ff, 0x1246, 0x12dc, 0x12dd, 0x12de, 0x1078,
- 0x1328, 0x007c, 0x127e, 0x0f7e, 0x2091, 0x8000, 0x7000, 0xa086,
- 0x0001, 0x00c0, 0x1198, 0x1078, 0x3a43, 0x2079, 0x0100, 0x7844,
- 0xa005, 0x00c0, 0x1198, 0x2011, 0x4129, 0x1078, 0x58d4, 0x1078,
- 0x1ab1, 0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011,
- 0x8010, 0x73c0, 0x1078, 0x3579, 0x2001, 0xffff, 0x1078, 0x5975,
- 0x7238, 0xc284, 0x723a, 0x2001, 0xa30c, 0x2014, 0xc2ac, 0x2202,
- 0x1078, 0x6db5, 0x2011, 0x0004, 0x1078, 0x8a59, 0x1078, 0x47ce,
- 0x1078, 0x4211, 0x0040, 0x1144, 0x7083, 0x0001, 0x70bb, 0x0000,
- 0x1078, 0x3bf5, 0x0078, 0x1198, 0x1078, 0x4897, 0x0040, 0x114d,
- 0x7a0c, 0xc2b4, 0x7a0e, 0x0078, 0x1159, 0x1078, 0x8ddf, 0x70c8,
- 0xd09c, 0x00c0, 0x1159, 0x7094, 0xa005, 0x0040, 0x1159, 0x1078,
- 0x41f5, 0x70d3, 0x0000, 0x70cf, 0x0000, 0x72c8, 0x2079, 0xa351,
- 0x7804, 0xd0ac, 0x0040, 0x1165, 0xc295, 0x72ca, 0xa296, 0x0004,
- 0x0040, 0x1186, 0x2011, 0x0001, 0x1078, 0x8a59, 0x708f, 0x0000,
- 0x7093, 0xffff, 0x7003, 0x0002, 0x0f7f, 0x1078, 0x260d, 0x2011,
- 0x0005, 0x1078, 0x6ef2, 0x1078, 0x6109, 0x0c7e, 0x2061, 0x0100,
- 0x60e3, 0x0008, 0x0c7f, 0x127f, 0x0078, 0x119a, 0x708f, 0x0000,
- 0x7093, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005, 0x1078, 0x6ef2,
- 0x1078, 0x6109, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f,
- 0x0f7f, 0x127f, 0x007c, 0x0c7e, 0x20a9, 0x0082, 0x2009, 0x007e,
- 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, 0x0029, 0x1078,
- 0x71e0, 0x027f, 0x1078, 0xa190, 0x037f, 0x027f, 0x017f, 0x1078,
- 0x2921, 0x8108, 0x00f0, 0x11a0, 0x0c7f, 0x706b, 0x0000, 0x706c,
- 0xa084, 0x00ff, 0x706e, 0x7097, 0x0000, 0x007c, 0x127e, 0x2091,
- 0x8000, 0x7000, 0xa086, 0x0002, 0x00c0, 0x1244, 0x7090, 0xa086,
- 0xffff, 0x0040, 0x11d1, 0x1078, 0x260d, 0x1078, 0x6109, 0x0078,
- 0x1244, 0x70c8, 0xd09c, 0x0040, 0x11fd, 0xd084, 0x0040, 0x11fd,
- 0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c,
- 0x0040, 0x11fd, 0x70cc, 0xa086, 0xffff, 0x0040, 0x11f9, 0x1078,
- 0x278a, 0x1078, 0x6109, 0x70c8, 0xd094, 0x00c0, 0x1244, 0x2011,
- 0x0001, 0x2019, 0x0000, 0x1078, 0x27c2, 0x1078, 0x6109, 0x0078,
- 0x1244, 0x70d0, 0xa005, 0x00c0, 0x1244, 0x708c, 0xa005, 0x00c0,
- 0x1244, 0x1078, 0x4897, 0x00c0, 0x1244, 0x2001, 0xa352, 0x2004,
- 0xd0ac, 0x0040, 0x1227, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009,
- 0x0000, 0x017e, 0x1078, 0x4501, 0x00c0, 0x121a, 0x6000, 0xd0ec,
- 0x00c0, 0x1222, 0x017f, 0x8108, 0x00f0, 0x1211, 0x0c7f, 0x157f,
- 0x0078, 0x1227, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x1244, 0x7003,
- 0x0003, 0x7093, 0xffff, 0x2001, 0x0000, 0x1078, 0x2480, 0x1078,
- 0x35f7, 0x2001, 0xa5ac, 0x2004, 0xa086, 0x0005, 0x00c0, 0x123c,
- 0x2011, 0x0000, 0x1078, 0x6ef2, 0x2011, 0x0000, 0x1078, 0x6efc,
- 0x1078, 0x6109, 0x1078, 0x61d3, 0x127f, 0x007c, 0x017e, 0x0f7e,
- 0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0x00f7, 0x1078,
- 0x41de, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0040,
- 0x125b, 0x7827, 0x0040, 0xd19c, 0x0040, 0x1260, 0x7827, 0x0008,
- 0x007e, 0x037e, 0x157e, 0xa006, 0x1078, 0x5975, 0x7900, 0xa18a,
- 0x0003, 0x0050, 0x1289, 0x7954, 0xd1ac, 0x00c0, 0x1289, 0x2009,
- 0x00f8, 0x1078, 0x41de, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9,
- 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x1281, 0x7824, 0xd0ac, 0x00c0,
- 0x12ca, 0x00f0, 0x1279, 0x2001, 0x0001, 0x1078, 0x2480, 0x0078,
- 0x12d5, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0050, 0x00e0,
- 0x128f, 0x2091, 0x6000, 0x00f0, 0x128f, 0x7853, 0x0400, 0x782f,
- 0x0000, 0x2009, 0x00f8, 0x1078, 0x41de, 0x20a9, 0x000e, 0x0005,
- 0x00f0, 0x129f, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843, 0x0010,
- 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040, 0x12b4,
- 0x7824, 0xd0ac, 0x00c0, 0x12ca, 0x8319, 0x00c0, 0x12aa, 0x2009,
- 0xa331, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0040, 0x12c4,
- 0x200b, 0x0000, 0x1078, 0x251e, 0x2001, 0x0001, 0x1078, 0x2480,
- 0x0078, 0x12d3, 0x2001, 0xa331, 0x2003, 0x0000, 0x7828, 0xc09d,
- 0x782a, 0x7827, 0x0048, 0x7853, 0x0400, 0x157f, 0x037f, 0x007f,
- 0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c, 0x007c, 0x2a70,
- 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, 0x12eb, 0x704f,
- 0xffff, 0x0078, 0x12ed, 0x704f, 0x0000, 0x7053, 0xffff, 0x706b,
- 0x0000, 0x706f, 0x0000, 0x1078, 0x8ddf, 0x2061, 0xa58c, 0x6003,
- 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013,
- 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061,
- 0xa594, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f,
- 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f,
- 0x0000, 0x2061, 0xa5a3, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b,
- 0x4943, 0x600f, 0x2020, 0x2001, 0xa325, 0x2003, 0x0000, 0x007c,
- 0x2091, 0x8000, 0x0068, 0x132a, 0x007e, 0x017e, 0x2079, 0x0000,
- 0x7818, 0xd084, 0x00c0, 0x1330, 0x017f, 0x792e, 0x007f, 0x782a,
- 0x007f, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001,
- 0x2091, 0x5000, 0x2091, 0x4080, 0x2079, 0xa300, 0x7803, 0x0005,
- 0x0078, 0x1348, 0x007c, 0x2071, 0xa300, 0x7158, 0x712e, 0x2021,
- 0x0001, 0xa190, 0x002d, 0xa298, 0x002d, 0x0048, 0x1361, 0x705c,
- 0xa302, 0x00c8, 0x1361, 0x220a, 0x2208, 0x2310, 0x8420, 0x0078,
- 0x1353, 0x200b, 0x0000, 0x74a6, 0x74aa, 0x007c, 0x0e7e, 0x127e,
- 0x2091, 0x8000, 0x2071, 0xa300, 0x70a8, 0xa0ea, 0x0010, 0x00c8,
- 0x1374, 0xa06e, 0x0078, 0x137e, 0x8001, 0x70aa, 0x702c, 0x2068,
- 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f,
- 0x007c, 0x0e7e, 0x2071, 0xa300, 0x127e, 0x2091, 0x8000, 0x70a8,
- 0x8001, 0x00c8, 0x138e, 0xa06e, 0x0078, 0x1397, 0x70aa, 0x702c,
- 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f,
- 0x0e7f, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa300,
- 0x702c, 0x206a, 0x2d00, 0x702e, 0x70a8, 0x8000, 0x70aa, 0x127f,
- 0x0e7f, 0x007c, 0x8dff, 0x0040, 0x13b6, 0x6804, 0x6807, 0x0000,
- 0x007e, 0x1078, 0x139a, 0x0d7f, 0x0078, 0x13aa, 0x007c, 0x0e7e,
- 0x2071, 0xa300, 0x70a8, 0xa08a, 0x0010, 0xa00d, 0x0e7f, 0x007c,
- 0x0e7e, 0x2071, 0xa5d0, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f,
- 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x0e7f,
- 0x007c, 0x0e7e, 0x2270, 0x700b, 0x0000, 0x2071, 0xa5d0, 0x7018,
- 0xa088, 0xa5d9, 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004,
- 0xa005, 0x00c0, 0x13e9, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13fa,
- 0x0f7f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa5d0, 0x7004, 0xa005,
- 0x00c0, 0x13f8, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13fa, 0x0f7f,
- 0x0e7f, 0x007c, 0x7000, 0x0079, 0x13fd, 0x1401, 0x146b, 0x1488,
- 0x1488, 0x7018, 0x711c, 0xa106, 0x00c0, 0x1409, 0x7007, 0x0000,
- 0x007c, 0x0d7e, 0xa180, 0xa5d9, 0x2004, 0x700a, 0x2068, 0x8108,
- 0xa18c, 0x0007, 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828,
- 0x7836, 0x682c, 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c,
- 0x7016, 0x6804, 0x0d7f, 0xd084, 0x0040, 0x142b, 0x7007, 0x0001,
- 0x1078, 0x1430, 0x007c, 0x7007, 0x0002, 0x1078, 0x1446, 0x007c,
- 0x017e, 0x027e, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8,
- 0x143b, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803,
- 0x0020, 0x7803, 0x0041, 0x027f, 0x017f, 0x007c, 0x017e, 0x027e,
- 0x137e, 0x147e, 0x157e, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803,
- 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x145a,
- 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803,
- 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x157f, 0x147f, 0x137f,
- 0x027f, 0x017f, 0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0xa3f9,
- 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e,
- 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084,
- 0x7002, 0x700b, 0xa3f4, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c,
- 0x137e, 0x147e, 0x157e, 0x2001, 0xa428, 0x209c, 0x20a1, 0x0014,
- 0x7803, 0x0026, 0x2001, 0xa429, 0x20ac, 0x53a6, 0x2099, 0xa42a,
- 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e,
- 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c,
- 0x7002, 0x700b, 0xa425, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c,
- 0x017e, 0x0e7e, 0x2071, 0xa5d0, 0x0f7e, 0x2079, 0x0010, 0x7904,
- 0x7803, 0x0002, 0xd1fc, 0x0040, 0x14c2, 0xa18c, 0x0700, 0x7004,
- 0x1079, 0x14c6, 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x13fa, 0x14ce,
- 0x14fb, 0x1523, 0x1556, 0x14cc, 0x0078, 0x14cc, 0xa18c, 0x0700,
- 0x00c0, 0x14f4, 0x137e, 0x147e, 0x157e, 0x7014, 0x20a0, 0x2099,
- 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016,
- 0x157f, 0x147f, 0x137f, 0x700c, 0xa005, 0x0040, 0x1510, 0x1078,
- 0x1430, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007,
- 0x0000, 0x1078, 0x13fa, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003,
- 0x0200, 0x0078, 0x14ef, 0xa18c, 0x0700, 0x00c0, 0x1506, 0x700c,
- 0xa005, 0x0040, 0x1510, 0x1078, 0x1446, 0x007c, 0x7008, 0xa080,
- 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x1078, 0x13fa, 0x007c,
- 0x0d7e, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838,
- 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000,
- 0x1078, 0x13fa, 0x007c, 0xa18c, 0x0700, 0x00c0, 0x1550, 0x137e,
- 0x147e, 0x157e, 0x2001, 0xa3f7, 0x2004, 0xa080, 0x000d, 0x20a0,
- 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001,
- 0xa3f9, 0x2004, 0xd0bc, 0x0040, 0x1546, 0x2001, 0xa402, 0x2004,
- 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x157f, 0x147f,
- 0x137f, 0x7007, 0x0000, 0x1078, 0x4e9b, 0x1078, 0x13fa, 0x007c,
- 0x2011, 0x8003, 0x1078, 0x3579, 0x0078, 0x1554, 0xa18c, 0x0700,
- 0x00c0, 0x1563, 0x2001, 0xa427, 0x2003, 0x0100, 0x7007, 0x0000,
- 0x1078, 0x13fa, 0x007c, 0x2011, 0x8004, 0x1078, 0x3579, 0x0078,
- 0x1567, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030, 0x2071, 0xa5e1,
- 0x7803, 0x0004, 0x7003, 0x0000, 0x700f, 0xa5e7, 0x7013, 0xa5e7,
- 0x780f, 0x0076, 0x7803, 0x0004, 0x127f, 0x007c, 0x6934, 0xa184,
- 0x0007, 0x0079, 0x1583, 0x158b, 0x15d1, 0x158b, 0x158b, 0x158b,
- 0x15b6, 0x159a, 0x158f, 0xa085, 0x0001, 0x0078, 0x15eb, 0x684c,
- 0xd0bc, 0x0040, 0x158b, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858,
- 0x0078, 0x15d9, 0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x158b,
- 0x684c, 0xd0bc, 0x0040, 0x158b, 0x6860, 0x682e, 0x685c, 0x682a,
- 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
- 0x2015, 0x2004, 0x6832, 0x6858, 0x0078, 0x15e1, 0xa18c, 0x00ff,
- 0xa186, 0x0015, 0x00c0, 0x158b, 0x684c, 0xd0ac, 0x0040, 0x158b,
- 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
- 0x2015, 0x2004, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078,
- 0x15e1, 0x684c, 0xd0ac, 0x0040, 0x158b, 0xa006, 0x682e, 0x682a,
- 0x6858, 0xa18c, 0x000f, 0xa188, 0x2015, 0x210c, 0x6932, 0x2d08,
- 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c,
- 0x6912, 0x6980, 0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000,
- 0x2001, 0x020a, 0x2004, 0x82ff, 0x0040, 0x160e, 0xa280, 0x0004,
- 0x0d7e, 0x206c, 0x684c, 0xd0dc, 0x00c0, 0x160a, 0x1078, 0x157e,
- 0x0040, 0x160a, 0x0d7f, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016,
- 0x0078, 0x160e, 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e,
- 0x037e, 0x027e, 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000,
- 0xa005, 0x00c0, 0x1622, 0x7206, 0x2001, 0x1643, 0x007e, 0x2260,
- 0x0078, 0x17be, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a,
- 0x8108, 0xa182, 0xa602, 0x0048, 0x162f, 0x2009, 0xa5e7, 0x710e,
- 0x7010, 0xa102, 0xa082, 0x0009, 0x0040, 0x163a, 0xa080, 0x001b,
- 0x00c0, 0x163d, 0x2009, 0x0138, 0x200a, 0x7000, 0xa005, 0x00c0,
- 0x1643, 0x1078, 0x179f, 0x127f, 0x007c, 0x127e, 0x027e, 0x037e,
- 0x0c7e, 0x007e, 0x2091, 0x2100, 0x007f, 0x047f, 0x037f, 0x027f,
- 0x0d7e, 0x0c7e, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, 0xa005,
- 0x0040, 0x16cf, 0x6808, 0xa005, 0x0040, 0x173c, 0x7000, 0xa005,
- 0x00c0, 0x1664, 0x0078, 0x16c4, 0x700c, 0x7110, 0xa106, 0x00c0,
- 0x1745, 0x7004, 0xa406, 0x00c0, 0x16c4, 0x2001, 0x0005, 0x2004,
- 0xd08c, 0x0040, 0x1681, 0x047e, 0x1078, 0x18e2, 0x047f, 0x2460,
- 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x0040, 0x173c, 0x0078,
- 0x165e, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x166d, 0x7804,
- 0xa084, 0x6000, 0x0040, 0x1692, 0xa086, 0x6000, 0x0040, 0x1692,
- 0x0078, 0x166d, 0x7100, 0xa186, 0x0002, 0x00c0, 0x16b2, 0x0e7e,
- 0x2b68, 0x6818, 0x2060, 0x1078, 0x1fea, 0x2804, 0xac70, 0x6034,
- 0xd09c, 0x00c0, 0x16a7, 0x7108, 0x720c, 0x0078, 0x16a9, 0x7110,
- 0x7214, 0x6810, 0xa100, 0x6812, 0x6814, 0xa201, 0x6816, 0x0e7f,
- 0x0078, 0x16b6, 0xa186, 0x0001, 0x00c0, 0x16be, 0x7820, 0x6910,
- 0xa100, 0x6812, 0x7824, 0x6914, 0xa101, 0x6816, 0x7803, 0x0004,
- 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x00c0,
- 0x1745, 0x2009, 0x0048, 0x1078, 0x756c, 0x0078, 0x1745, 0x6808,
- 0xa005, 0x0040, 0x173c, 0x7000, 0xa005, 0x00c0, 0x16d9, 0x0078,
- 0x173c, 0x700c, 0x7110, 0xa106, 0x00c0, 0x16e2, 0x7004, 0xa406,
- 0x00c0, 0x173c, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, 0x16f6,
- 0x047e, 0x1078, 0x18e2, 0x047f, 0x2460, 0x6010, 0xa080, 0x0002,
- 0x2004, 0xa005, 0x0040, 0x173c, 0x0078, 0x16d3, 0x2001, 0x0207,
- 0x2004, 0xd09c, 0x00c0, 0x16e2, 0x2001, 0x0005, 0x2004, 0xd08c,
- 0x00c0, 0x16e8, 0x7804, 0xa084, 0x6000, 0x0040, 0x170d, 0xa086,
- 0x6000, 0x0040, 0x170d, 0x0078, 0x16e2, 0x7007, 0x0000, 0xa016,
- 0x2218, 0x7000, 0xa08e, 0x0001, 0x0040, 0x172e, 0xa08e, 0x0002,
- 0x00c0, 0x173c, 0x0c7e, 0x0e7e, 0x6818, 0x2060, 0x1078, 0x1fea,
- 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, 0x172a, 0x7308, 0x720c,
- 0x0078, 0x172c, 0x7310, 0x7214, 0x0e7f, 0x0c7f, 0x7820, 0xa318,
- 0x7824, 0xa211, 0x6810, 0xa300, 0x6812, 0x6814, 0xa201, 0x6816,
- 0x7803, 0x0004, 0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x00c0,
- 0x1745, 0x2009, 0x0048, 0x1078, 0x756c, 0x0c7f, 0x0d7f, 0x127f,
- 0x007c, 0x0f7e, 0x0e7e, 0x027e, 0x037e, 0x047e, 0x1078, 0x1af7,
- 0x027e, 0x2071, 0xa5e1, 0x7000, 0xa086, 0x0000, 0x0040, 0x1790,
- 0x7004, 0xac06, 0x00c0, 0x1781, 0x2079, 0x0030, 0x7000, 0xa086,
- 0x0003, 0x0040, 0x1781, 0x7804, 0xd0fc, 0x00c0, 0x177d, 0x2001,
- 0x0207, 0x2004, 0xd09c, 0x00c0, 0x1763, 0x7803, 0x0004, 0x7804,
- 0xd0ac, 0x00c0, 0x176f, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003,
- 0x0003, 0x7007, 0x0000, 0x0078, 0x1781, 0x1078, 0x18e2, 0x0078,
- 0x1753, 0x157e, 0x20a9, 0x0009, 0x2009, 0xa5e7, 0x2104, 0xac06,
- 0x00c0, 0x178b, 0x200a, 0xa188, 0x0003, 0x00f0, 0x1786, 0x157f,
- 0x027f, 0x2001, 0x015d, 0x201c, 0x831a, 0x2302, 0x2001, 0x0138,
- 0x2202, 0x047f, 0x037f, 0x027f, 0x0e7f, 0x0f7f, 0x007c, 0x700c,
- 0x7110, 0xa106, 0x00c0, 0x17a7, 0x7003, 0x0000, 0x007c, 0x2104,
- 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182,
- 0xa602, 0x0048, 0x17b5, 0x2009, 0xa5e7, 0x7112, 0x700c, 0xa106,
- 0x00c0, 0x17be, 0x2001, 0x0138, 0x2003, 0x0008, 0x8cff, 0x00c0,
- 0x17c5, 0x1078, 0x1b22, 0x0078, 0x1823, 0x6010, 0x2068, 0x2d58,
- 0x6828, 0xa406, 0x00c0, 0x17d0, 0x682c, 0xa306, 0x0040, 0x17fe,
- 0x601c, 0xa086, 0x0008, 0x0040, 0x17fe, 0x6024, 0xd0f4, 0x00c0,
- 0x17fa, 0xd0d4, 0x0040, 0x17f6, 0x6038, 0xa402, 0x6034, 0xa303,
- 0x0040, 0x17e4, 0x00c8, 0x17f6, 0x643a, 0x6336, 0x6c2a, 0x6b2e,
- 0x047e, 0x037e, 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80,
- 0xa303, 0x6816, 0x037f, 0x047f, 0x0078, 0x17fa, 0x1078, 0x8d8e,
- 0x0040, 0x17c1, 0x1078, 0x2035, 0x00c0, 0x17c1, 0x0c7e, 0x7004,
- 0x2060, 0x6024, 0xc0d4, 0x6026, 0x0c7f, 0x684c, 0xd0f4, 0x0040,
- 0x180f, 0x6817, 0xffff, 0x6813, 0xffff, 0x0078, 0x17c1, 0x6824,
- 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f,
- 0x2009, 0x0011, 0x1078, 0x1824, 0x0040, 0x1822, 0x2009, 0x0001,
- 0x1078, 0x1824, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x18bb, 0xa03e,
- 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1846, 0xd0f4, 0x00c0, 0x1856,
- 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1836, 0x189d, 0x185d,
- 0x185d, 0x189d, 0x189d, 0x1895, 0x189d, 0x185d, 0x189d, 0x1863,
- 0x1863, 0x189d, 0x189d, 0x189d, 0x188c, 0x1863, 0xc0fc, 0x6852,
- 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x0d7e, 0xd99c, 0x0040, 0x18a0,
- 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x18a0, 0xc0f4, 0x6852,
- 0x6b6c, 0x6a70, 0x0d7e, 0x0078, 0x18a7, 0x6b08, 0x6a0c, 0x6d00,
- 0x6c04, 0x0078, 0x18a0, 0x7b0c, 0xd3bc, 0x0040, 0x1884, 0x7004,
- 0x0e7e, 0x2070, 0x701c, 0x0e7f, 0xa086, 0x0008, 0x00c0, 0x1884,
- 0x7b08, 0xa39c, 0x0fff, 0x2d20, 0x0d7f, 0x0d7e, 0x6a14, 0x82ff,
- 0x00c0, 0x187f, 0x6810, 0xa302, 0x0048, 0x187f, 0x6b10, 0x2011,
- 0x0000, 0x2468, 0x0078, 0x1886, 0x6b10, 0x6a14, 0x6d00, 0x6c04,
- 0x6f08, 0x6e0c, 0x0078, 0x18a0, 0x0d7f, 0x0d7e, 0x6834, 0xa084,
- 0x00ff, 0xa086, 0x001e, 0x00c0, 0x189d, 0x0d7f, 0x1078, 0x1fd1,
- 0x00c0, 0x1824, 0xa00e, 0x0078, 0x18bb, 0x0d7f, 0x1078, 0x1328,
- 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000,
- 0x8000, 0x7002, 0x0d7f, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201,
- 0x682e, 0x2300, 0x6b10, 0xa302, 0x6812, 0x2200, 0x6a14, 0xa203,
- 0x6816, 0x1078, 0x1fd1, 0x007c, 0x1078, 0x1328, 0x1078, 0x1c52,
- 0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x7003, 0x0000, 0x1078,
- 0x1ac6, 0x1078, 0x8a44, 0x0040, 0x18db, 0x6808, 0x8001, 0x680a,
- 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, 0xffff,
- 0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8758, 0x0078, 0x1aad,
- 0x1078, 0x1328, 0x127e, 0x2091, 0x2100, 0x007e, 0x017e, 0x2b68,
- 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0,
- 0x18be, 0xa184, 0x0003, 0xa086, 0x0003, 0x0040, 0x18e0, 0x7000,
- 0x0079, 0x18fa, 0x1902, 0x1904, 0x1a06, 0x1a84, 0x1a9b, 0x1902,
- 0x1902, 0x1902, 0x1078, 0x1328, 0x8001, 0x7002, 0xa184, 0x0880,
- 0x00c0, 0x1919, 0x8aff, 0x0040, 0x199b, 0x2009, 0x0001, 0x1078,
- 0x1824, 0x0040, 0x1aad, 0x2009, 0x0001, 0x1078, 0x1824, 0x0078,
- 0x1aad, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x00c0, 0x1979,
- 0x027e, 0x037e, 0x7808, 0xd0ec, 0x00c0, 0x1930, 0x7c20, 0x7d24,
- 0x7e30, 0x7f34, 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1932,
- 0x1078, 0x1b9f, 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500,
- 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x0c7e, 0x7004, 0x2060, 0x6024,
- 0xd0f4, 0x00c0, 0x1945, 0x633a, 0x6236, 0x0c7f, 0x2400, 0x6910,
- 0xa100, 0x6812, 0x2500, 0x6914, 0xa101, 0x6816, 0x037f, 0x027f,
- 0x2600, 0x681e, 0x2700, 0x6822, 0x1078, 0x1fea, 0x2a00, 0x6826,
- 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852, 0x6808,
- 0x8001, 0x680a, 0x00c0, 0x196e, 0x684c, 0xd0e4, 0x0040, 0x196e,
- 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x756c, 0x7000, 0xa086,
- 0x0004, 0x0040, 0x1aad, 0x7003, 0x0000, 0x1078, 0x179f, 0x0078,
- 0x1aad, 0x057e, 0x7d0c, 0xd5bc, 0x00c0, 0x1980, 0x1078, 0xa20c,
- 0x057f, 0x1078, 0x1ac6, 0x0f7e, 0x7004, 0x2078, 0x1078, 0x4893,
- 0x0040, 0x198d, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, 0xffff,
- 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980,
- 0x6916, 0x0078, 0x1aad, 0x7004, 0x0c7e, 0x2060, 0x6024, 0x0c7f,
- 0xd0f4, 0x0040, 0x19a8, 0x6808, 0x8001, 0x680a, 0x0078, 0x1aad,
- 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x19c0, 0x7003,
- 0x0000, 0x6808, 0x8001, 0x680a, 0x00c0, 0x19bc, 0x7004, 0x2060,
- 0x2009, 0x0048, 0x1078, 0x756c, 0x1078, 0x179f, 0x0078, 0x1aad,
- 0x7814, 0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000, 0x6816,
- 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214,
- 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b,
- 0x810b, 0x1078, 0x1b4d, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803,
- 0x0001, 0x7804, 0xd0fc, 0x0040, 0x19e1, 0x7803, 0x0002, 0x7803,
- 0x0004, 0x780f, 0x0076, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009,
- 0x0048, 0x1078, 0x756c, 0x1078, 0x1b81, 0x0040, 0x19bc, 0x7908,
- 0xd1ec, 0x00c0, 0x19ff, 0x2009, 0x0009, 0x0078, 0x1a01, 0x2009,
- 0x0019, 0x7902, 0x7003, 0x0003, 0x0078, 0x1aad, 0x8001, 0x7002,
- 0xd194, 0x0040, 0x1a18, 0x7804, 0xd0fc, 0x00c0, 0x18ea, 0x8aff,
- 0x0040, 0x1aad, 0x2009, 0x0001, 0x1078, 0x1824, 0x0078, 0x1aad,
- 0xa184, 0x0880, 0x00c0, 0x1a25, 0x8aff, 0x0040, 0x1aad, 0x2009,
- 0x0001, 0x1078, 0x1824, 0x0078, 0x1aad, 0x7803, 0x0004, 0x7003,
- 0x0000, 0xd1bc, 0x00c0, 0x1a65, 0x027e, 0x037e, 0x7808, 0xd0ec,
- 0x00c0, 0x1a38, 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1a3a,
- 0x1078, 0x1b9f, 0x6b28, 0x6a2c, 0x1078, 0x1fea, 0x0d7e, 0x0f7e,
- 0x2d78, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1a55, 0x6808,
- 0x2008, 0xa31a, 0x680c, 0xa213, 0x7810, 0xa100, 0x7812, 0x690c,
- 0x7814, 0xa101, 0x7816, 0x0078, 0x1a61, 0x6810, 0x2008, 0xa31a,
- 0x6814, 0xa213, 0x7810, 0xa100, 0x7812, 0x6914, 0x7814, 0xa101,
- 0x7816, 0x0f7f, 0x0d7f, 0x0078, 0x1934, 0x057e, 0x7d0c, 0x1078,
- 0xa20c, 0x057f, 0x1078, 0x1ac6, 0x0f7e, 0x7004, 0x2078, 0x1078,
- 0x4893, 0x0040, 0x1a76, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b,
- 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912,
- 0x6980, 0x6916, 0x0078, 0x1aad, 0x7803, 0x0004, 0x7003, 0x0000,
- 0x7004, 0xa00d, 0x0040, 0x1a97, 0x6808, 0x8001, 0x680a, 0x00c0,
- 0x1a97, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x756c, 0x1078,
- 0x179f, 0x0078, 0x1aad, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004,
- 0x2060, 0x6010, 0xa005, 0x0040, 0x1a97, 0x2068, 0x6808, 0x8000,
- 0x680a, 0x6c28, 0x6b2c, 0x1078, 0x17be, 0x017f, 0x007f, 0x127f,
- 0x007c, 0x127e, 0x2091, 0x2100, 0x7000, 0xa086, 0x0003, 0x00c0,
- 0x1ac4, 0x700c, 0x7110, 0xa106, 0x0040, 0x1ac4, 0x20e1, 0x9028,
- 0x700f, 0xa5e7, 0x7013, 0xa5e7, 0x127f, 0x007c, 0x0c7e, 0x1078,
- 0x1af7, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x0040, 0x1aed,
- 0x2104, 0xa005, 0x0040, 0x1ada, 0x2060, 0x6010, 0x2060, 0x6008,
- 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xa602, 0x0048, 0x1ae2,
- 0x2009, 0xa5e7, 0x7112, 0x700c, 0xa106, 0x00c0, 0x1acb, 0x2001,
- 0x0138, 0x2003, 0x0008, 0x0078, 0x1acb, 0x2001, 0x015d, 0x200c,
- 0x810a, 0x2102, 0x2001, 0x0138, 0x2202, 0x0c7f, 0x007c, 0x2001,
- 0x0138, 0x2014, 0x2003, 0x0000, 0x2021, 0xb015, 0x2001, 0x0141,
- 0x201c, 0xd3dc, 0x00c0, 0x1b14, 0x2001, 0x0109, 0x201c, 0xa39c,
- 0x0048, 0x00c0, 0x1b14, 0x2001, 0x0111, 0x201c, 0x83ff, 0x00c0,
- 0x1b14, 0x8421, 0x00c0, 0x1afe, 0x007c, 0x2011, 0x0201, 0x2009,
- 0x003c, 0x2204, 0xa005, 0x00c0, 0x1b21, 0x8109, 0x00c0, 0x1b19,
- 0x007c, 0x007c, 0x1078, 0x1b15, 0x0040, 0x1b4a, 0x7908, 0xd1ec,
- 0x00c0, 0x1b3a, 0x1078, 0x1b81, 0x0040, 0x1b3a, 0x7803, 0x0009,
- 0x7904, 0xd1fc, 0x0040, 0x1b30, 0x7803, 0x0006, 0x1078, 0x1b15,
- 0x0040, 0x1b4a, 0x780c, 0xd0a4, 0x00c0, 0x1b4a, 0x7007, 0x0000,
- 0x1078, 0x1b81, 0x0040, 0x1b4c, 0x7803, 0x0019, 0x7003, 0x0003,
- 0x0078, 0x1b4c, 0x1078, 0x1ac6, 0x007c, 0x0e7e, 0x2071, 0x0200,
- 0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x1af7, 0x2019, 0x5000,
- 0x8319, 0x0040, 0x1b6b, 0x2001, 0xa602, 0x2004, 0xa086, 0x0000,
- 0x0040, 0x1b6b, 0x2001, 0x0021, 0xd0fc, 0x0040, 0x1b58, 0x1078,
- 0x1e5d, 0x0078, 0x1b56, 0x20e1, 0x7000, 0x7324, 0x7420, 0x7028,
- 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, 0x0100,
- 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202, 0x0e7f,
- 0x007c, 0x7908, 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0048, 0x1b8c,
- 0xa085, 0x0001, 0x0078, 0x1b9e, 0x2001, 0x020a, 0x81ff, 0x0040,
- 0x1b97, 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x20e1,
- 0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0xa006, 0x007c, 0x7c20,
- 0x7d24, 0x7e30, 0x7f34, 0x700c, 0x7110, 0xa106, 0x0040, 0x1c24,
- 0x7004, 0x017e, 0x210c, 0xa106, 0x017f, 0x0040, 0x1c24, 0x0d7e,
- 0x0c7e, 0x216c, 0x2d00, 0xa005, 0x0040, 0x1c22, 0x6824, 0xd0d4,
- 0x00c0, 0x1c22, 0x6810, 0x2068, 0x6850, 0xd0fc, 0x0040, 0x1bec,
- 0x8108, 0x2104, 0x6b2c, 0xa306, 0x00c0, 0x1c22, 0x8108, 0x2104,
- 0x6a28, 0xa206, 0x00c0, 0x1c22, 0x6850, 0xc0fc, 0xc0f5, 0x6852,
- 0x686c, 0x7822, 0x6870, 0x7826, 0x681c, 0x7832, 0x6820, 0x7836,
- 0x6818, 0x2060, 0x6034, 0xd09c, 0x0040, 0x1be7, 0x6830, 0x2004,
- 0xac68, 0x6808, 0x783a, 0x680c, 0x783e, 0x0078, 0x1c20, 0xa006,
- 0x783a, 0x783e, 0x0078, 0x1c20, 0x8108, 0x2104, 0xa005, 0x00c0,
- 0x1c22, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c22, 0x6850, 0xc0f5,
- 0x6852, 0x6830, 0x2004, 0x6918, 0xa160, 0xa180, 0x000d, 0x2004,
- 0xd09c, 0x00c0, 0x1c12, 0x6008, 0x7822, 0x686e, 0x600c, 0x7826,
- 0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0xa006, 0x783a, 0x783e,
- 0x0078, 0x1c20, 0x6010, 0x7822, 0x686e, 0x6014, 0x7826, 0x6872,
- 0x6000, 0x7832, 0x6004, 0x7836, 0x6008, 0x783a, 0x600c, 0x783e,
- 0x7803, 0x0011, 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x017e,
- 0x027e, 0x2071, 0xa5e1, 0x2079, 0x0030, 0x2011, 0x0050, 0x7000,
- 0xa086, 0x0000, 0x0040, 0x1c4d, 0x8211, 0x0040, 0x1c4b, 0x2001,
- 0x0005, 0x2004, 0xd08c, 0x0040, 0x1c34, 0x7904, 0xa18c, 0x0780,
- 0x017e, 0x1078, 0x18e2, 0x017f, 0x81ff, 0x00c0, 0x1c4b, 0x2011,
- 0x0050, 0x0078, 0x1c2f, 0xa085, 0x0001, 0x027f, 0x017f, 0x0e7f,
- 0x0f7f, 0x007c, 0x7803, 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac,
- 0x0040, 0x1ca3, 0x8109, 0x00c0, 0x1c56, 0x2009, 0x0100, 0x210c,
- 0xa18a, 0x0003, 0x1048, 0x1328, 0x1078, 0x1f75, 0x0e7e, 0x0f7e,
- 0x2071, 0xa5d0, 0x2079, 0x0010, 0x7004, 0xa086, 0x0000, 0x0040,
- 0x1c9b, 0x7800, 0x007e, 0x7820, 0x007e, 0x7830, 0x007e, 0x7834,
- 0x007e, 0x7838, 0x007e, 0x783c, 0x007e, 0x7803, 0x0004, 0x7823,
- 0x0000, 0x0005, 0x0005, 0x2079, 0x0030, 0x7804, 0xd0ac, 0x10c0,
- 0x1328, 0x2079, 0x0010, 0x007f, 0x783e, 0x007f, 0x783a, 0x007f,
- 0x7836, 0x007f, 0x7832, 0x007f, 0x7822, 0x007f, 0x7802, 0x0f7f,
- 0x0e7f, 0x0078, 0x1ca1, 0x0f7f, 0x0e7f, 0x7804, 0xd0ac, 0x10c0,
- 0x1328, 0x1078, 0x61d3, 0x007c, 0x0e7e, 0x2071, 0xa602, 0x7003,
- 0x0000, 0x0e7f, 0x007c, 0x0d7e, 0xa280, 0x0004, 0x206c, 0x694c,
- 0xd1dc, 0x00c0, 0x1d26, 0x6934, 0xa184, 0x0007, 0x0079, 0x1cb8,
- 0x1cc0, 0x1d11, 0x1cc0, 0x1cc0, 0x1cc0, 0x1cf6, 0x1cd3, 0x1cc2,
- 0x1078, 0x1328, 0x684c, 0xd0b4, 0x0040, 0x1e34, 0x6860, 0x682e,
- 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e,
- 0x6958, 0x0078, 0x1d19, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e,
- 0x00c0, 0x1cc0, 0x684c, 0xd0b4, 0x0040, 0x1e34, 0x6860, 0x682e,
- 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e,
- 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
- 0x2015, 0x2004, 0x6832, 0x6958, 0x0078, 0x1d22, 0xa18c, 0x00ff,
- 0xa186, 0x0015, 0x00c0, 0x1d26, 0x684c, 0xd0b4, 0x0040, 0x1e34,
- 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
- 0x2015, 0x2004, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0078,
- 0x1d22, 0x684c, 0xd0b4, 0x0040, 0x18bc, 0x6958, 0xa006, 0x682e,
- 0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x2015,
- 0x2004, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x0d7f, 0x007c,
- 0x0f7e, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x10c0, 0x1e5d, 0x0e7e,
- 0x0d7e, 0x2071, 0xa602, 0x7000, 0xa005, 0x00c0, 0x1dab, 0x0c7e,
- 0x7206, 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004,
- 0x6818, 0x0d7e, 0x2068, 0x686c, 0x7812, 0x6890, 0x0f7e, 0x20e1,
- 0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6,
- 0x0f7f, 0x0d7f, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830,
- 0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0x2001, 0x04fd, 0x2004,
- 0xa086, 0x0007, 0x0040, 0x1d6d, 0xa184, 0x0007, 0x0040, 0x1d6d,
- 0x017e, 0x2009, 0x0008, 0xa102, 0x017f, 0xa108, 0x791a, 0x7116,
- 0x701e, 0x680c, 0xa081, 0x0000, 0x781e, 0x701a, 0xa006, 0x700e,
- 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, 0x00c0, 0x1d84, 0x6928,
- 0x6810, 0xa106, 0x0040, 0x1d91, 0x037e, 0x047e, 0x6b14, 0x6c10,
- 0x1078, 0x2035, 0x047f, 0x037f, 0x0040, 0x1d91, 0x0c7f, 0x0078,
- 0x1dab, 0x8aff, 0x00c0, 0x1d99, 0x0c7f, 0xa085, 0x0001, 0x0078,
- 0x1dab, 0x127e, 0x2091, 0x8000, 0x2079, 0x0020, 0x2009, 0x0001,
- 0x1078, 0x1daf, 0x0040, 0x1da8, 0x2009, 0x0001, 0x1078, 0x1daf,
- 0x127f, 0x0c7f, 0xa006, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e,
- 0x067e, 0x057e, 0x047e, 0x037e, 0x027e, 0x8aff, 0x0040, 0x1e2d,
- 0x700c, 0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, 0x0048, 0x1e2c,
- 0xa705, 0x0040, 0x1e2c, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0,
- 0x1ddf, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1dcf, 0x1e0e,
- 0x1def, 0x1def, 0x1e0e, 0x1e0e, 0x1e06, 0x1e0e, 0x1def, 0x1e0e,
- 0x1df5, 0x1df5, 0x1e0e, 0x1e0e, 0x1e0e, 0x1dfd, 0x1df5, 0xc0fc,
- 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x0040, 0x1e12,
- 0x0d7e, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x1e11, 0x6b08,
- 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1e11, 0x6b10, 0x6a14, 0x6d00,
- 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x1e11, 0x0d7f, 0x0d7e, 0x6834,
- 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1e0e, 0x0d7f, 0x1078,
- 0x1fd1, 0x00c0, 0x1db5, 0xa00e, 0x0078, 0x1e2d, 0x0d7f, 0x1078,
- 0x1328, 0x0d7f, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e,
- 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c,
- 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012,
- 0x1078, 0x1fd1, 0x0078, 0x1e2d, 0xa006, 0x027f, 0x037f, 0x047f,
- 0x057f, 0x067f, 0x077f, 0x007c, 0x1078, 0x1328, 0x027e, 0x2001,
- 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
- 0x0000, 0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44,
- 0x0040, 0x1e4d, 0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8758,
- 0x20e1, 0x9040, 0x1078, 0x719a, 0x2011, 0x0000, 0x1078, 0x6efc,
- 0x1078, 0x61d3, 0x027f, 0x0078, 0x1f29, 0x127e, 0x2091, 0x2200,
- 0x007e, 0x017e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020,
- 0x2071, 0xa602, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002,
- 0xa184, 0x0700, 0x00c0, 0x1e36, 0x7000, 0x0079, 0x1e77, 0x1f29,
- 0x1e7b, 0x1ef6, 0x1f27, 0x8001, 0x7002, 0xd19c, 0x00c0, 0x1e8f,
- 0x8aff, 0x0040, 0x1eae, 0x2009, 0x0001, 0x1078, 0x1daf, 0x0040,
- 0x1f29, 0x2009, 0x0001, 0x1078, 0x1daf, 0x0078, 0x1f29, 0x7803,
- 0x0004, 0xd194, 0x0040, 0x1e9f, 0x6850, 0xc0fc, 0x6852, 0x8aff,
- 0x00c0, 0x1ea4, 0x684c, 0xc0f5, 0x684e, 0x0078, 0x1ea4, 0x1078,
- 0x1fea, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a,
- 0x2800, 0x6832, 0x7003, 0x0000, 0x0078, 0x1f29, 0x711c, 0x81ff,
- 0x0040, 0x1ec4, 0x7918, 0x7922, 0x7827, 0x0000, 0x7803, 0x0001,
- 0x7000, 0x8000, 0x7002, 0x700c, 0xa100, 0x700e, 0x7010, 0xa081,
- 0x0000, 0x7012, 0x0078, 0x1f29, 0x0f7e, 0x027e, 0x781c, 0x007e,
- 0x7818, 0x007e, 0x2079, 0x0100, 0x7a14, 0xa284, 0x0004, 0xa085,
- 0x0012, 0x7816, 0x037e, 0x2019, 0x1000, 0x8319, 0x1040, 0x1328,
- 0x7820, 0xd0bc, 0x00c0, 0x1ed5, 0x037f, 0x79c8, 0x007f, 0xa102,
- 0x017f, 0x007e, 0x017e, 0x79c4, 0x007f, 0xa103, 0x78c6, 0x007f,
- 0x78ca, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f,
- 0x7803, 0x0008, 0x7003, 0x0000, 0x0078, 0x1f29, 0x8001, 0x7002,
- 0xd194, 0x0040, 0x1f0b, 0x7804, 0xd0fc, 0x00c0, 0x1e6d, 0xd19c,
- 0x00c0, 0x1f25, 0x8aff, 0x0040, 0x1f29, 0x2009, 0x0001, 0x1078,
- 0x1daf, 0x0078, 0x1f29, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078,
- 0x1fea, 0x0d7e, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1f1e,
- 0x6808, 0xa31a, 0x680c, 0xa213, 0x0078, 0x1f22, 0x6810, 0xa31a,
- 0x6814, 0xa213, 0x0d7f, 0x0078, 0x1e9f, 0x0078, 0x1e9f, 0x1078,
- 0x1328, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f,
- 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0xa602, 0x7000, 0xa086, 0x0000,
- 0x0040, 0x1f72, 0x2079, 0x0020, 0x017e, 0x2009, 0x0207, 0x210c,
- 0xd194, 0x0040, 0x1f4f, 0x2009, 0x020c, 0x210c, 0xa184, 0x0003,
- 0x0040, 0x1f4f, 0x20e1, 0x9040, 0x2001, 0x020c, 0x2102, 0x2009,
- 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, 0x00c0, 0x1f5a,
- 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x0040, 0x1f3d, 0x1078, 0x1e5d,
- 0x7000, 0xa086, 0x0000, 0x00c0, 0x1f3d, 0x017f, 0x7803, 0x0004,
- 0x7804, 0xd0ac, 0x00c0, 0x1f68, 0x20e1, 0x9040, 0x7803, 0x0002,
- 0x7003, 0x0000, 0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x0c7e, 0x0d7e,
- 0x0e7e, 0x0f7e, 0x2071, 0xa602, 0x2079, 0x0020, 0x7000, 0xa086,
- 0x0000, 0x0040, 0x1fae, 0x7004, 0x2060, 0x6010, 0x2068, 0x1078,
- 0x8a44, 0x0040, 0x1f98, 0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c,
- 0xa206, 0x00c0, 0x1f98, 0x6808, 0x7a18, 0xa206, 0x0040, 0x1fb4,
- 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004,
- 0x7003, 0x0000, 0x7004, 0x2060, 0x1078, 0x8758, 0x20e1, 0x9040,
- 0x1078, 0x719a, 0x2011, 0x0000, 0x1078, 0x6efc, 0x0f7f, 0x0e7f,
- 0x0d7f, 0x0c7f, 0x027f, 0x007c, 0x6810, 0x6a14, 0xa205, 0x00c0,
- 0x1f98, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x1078, 0x1cab, 0x2001,
- 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
- 0x0000, 0x2069, 0xa5ab, 0x6833, 0x0000, 0x683f, 0x0000, 0x0078,
- 0x1fae, 0x8840, 0x2804, 0xa005, 0x00c0, 0x1fe5, 0x6004, 0xa005,
- 0x0040, 0x1fe7, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080,
- 0x2015, 0x2044, 0x88ff, 0x1040, 0x1328, 0x8a51, 0x007c, 0x2051,
- 0x0000, 0x007c, 0x8a50, 0x8841, 0x2804, 0xa005, 0x00c0, 0x2004,
- 0x2c00, 0xad06, 0x0040, 0x1ff9, 0x6000, 0xa005, 0x00c0, 0x1ff9,
- 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, 0x2025,
- 0x2044, 0x88ff, 0x1040, 0x1328, 0x007c, 0x0000, 0x0011, 0x0015,
- 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, 0x0015,
- 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x200a, 0x2006,
- 0x0000, 0x0000, 0x2014, 0x0000, 0x200a, 0x0000, 0x2011, 0x200e,
- 0x0000, 0x0000, 0x0000, 0x2014, 0x2011, 0x0000, 0x200c, 0x200c,
- 0x0000, 0x0000, 0x2014, 0x0000, 0x200c, 0x0000, 0x2012, 0x2012,
- 0x0000, 0x0000, 0x0000, 0x2014, 0x2012, 0x0a7e, 0x097e, 0x087e,
- 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0040, 0x20d8, 0x2d60, 0x6034,
- 0xa0cc, 0x000f, 0xa9c0, 0x2015, 0xa986, 0x0007, 0x0040, 0x2050,
- 0xa986, 0x000e, 0x0040, 0x2050, 0xa986, 0x000f, 0x00c0, 0x2054,
- 0x605c, 0xa422, 0x6060, 0xa31a, 0x2804, 0xa045, 0x00c0, 0x2062,
- 0x0050, 0x205c, 0x0078, 0x20d8, 0x6004, 0xa065, 0x0040, 0x20d8,
- 0x0078, 0x203f, 0x2804, 0xa005, 0x0040, 0x2080, 0xac68, 0xd99c,
- 0x00c0, 0x2070, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0078, 0x2074,
- 0x6810, 0xa422, 0x6814, 0xa31b, 0x0048, 0x209f, 0x2300, 0xa405,
- 0x0040, 0x2086, 0x8a51, 0x0040, 0x20d8, 0x8840, 0x0078, 0x2062,
- 0x6004, 0xa065, 0x0040, 0x20d8, 0x0078, 0x203f, 0x8a51, 0x0040,
- 0x20d8, 0x8840, 0x2804, 0xa005, 0x00c0, 0x2099, 0x6004, 0xa065,
- 0x0040, 0x20d8, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2015, 0x2804,
- 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0078, 0x20cc, 0x8422,
- 0x8420, 0x831a, 0xa399, 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72,
- 0x0d7f, 0xd99c, 0x00c0, 0x20ba, 0x6908, 0x2400, 0xa122, 0x690c,
- 0x2300, 0xa11b, 0x1048, 0x1328, 0x6800, 0xa420, 0x6804, 0xa319,
- 0x0078, 0x20c6, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b,
- 0x1048, 0x1328, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e,
- 0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832,
- 0x2a00, 0x6826, 0x007f, 0x007f, 0x007f, 0xa006, 0x0078, 0x20dd,
- 0x087f, 0x097f, 0x0a7f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0005,
- 0x2004, 0xa084, 0x0007, 0x0079, 0x20e5, 0x20ed, 0x20ee, 0x20f1,
- 0x20f4, 0x20f9, 0x20fc, 0x2101, 0x2106, 0x007c, 0x1078, 0x1e5d,
- 0x007c, 0x1078, 0x18e2, 0x007c, 0x1078, 0x18e2, 0x1078, 0x1e5d,
- 0x007c, 0x1078, 0x14b0, 0x007c, 0x1078, 0x1e5d, 0x1078, 0x14b0,
- 0x007c, 0x1078, 0x18e2, 0x1078, 0x14b0, 0x007c, 0x1078, 0x18e2,
- 0x1078, 0x1e5d, 0x1078, 0x14b0, 0x007c, 0x127e, 0x2091, 0x2300,
- 0x2079, 0x0200, 0x2071, 0xa880, 0x2069, 0xa300, 0x2009, 0x0004,
- 0x7912, 0x7817, 0x0004, 0x1078, 0x24b5, 0x781b, 0x0002, 0x20e1,
- 0x8700, 0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x781c, 0xa084,
- 0x0007, 0x0079, 0x212b, 0x214f, 0x2133, 0x2137, 0x213b, 0x2141,
- 0x2145, 0x2149, 0x214d, 0x1078, 0x5372, 0x0078, 0x214f, 0x1078,
- 0x53b3, 0x0078, 0x214f, 0x1078, 0x5372, 0x1078, 0x53b3, 0x0078,
- 0x214f, 0x1078, 0x2151, 0x0078, 0x214f, 0x1078, 0x2151, 0x0078,
- 0x214f, 0x1078, 0x2151, 0x0078, 0x214f, 0x1078, 0x2151, 0x127f,
- 0x007c, 0x007e, 0x017e, 0x027e, 0x7930, 0xa184, 0x0003, 0x0040,
- 0x215d, 0x20e1, 0x9040, 0x0078, 0x2186, 0xa184, 0x0030, 0x0040,
- 0x216e, 0x6a00, 0xa286, 0x0003, 0x00c0, 0x2168, 0x0078, 0x216a,
- 0x1078, 0x4171, 0x20e1, 0x9010, 0x0078, 0x2186, 0xa184, 0x00c0,
- 0x0040, 0x2180, 0x0e7e, 0x037e, 0x047e, 0x057e, 0x2071, 0xa5e1,
- 0x1078, 0x1ac6, 0x057f, 0x047f, 0x037f, 0x0e7f, 0x0078, 0x2186,
- 0xa184, 0x0300, 0x0040, 0x2186, 0x20e1, 0x9020, 0x7932, 0x027f,
- 0x017f, 0x007f, 0x007c, 0x017e, 0x0e7e, 0x0f7e, 0x2071, 0xa300,
- 0x7128, 0x2001, 0xa58f, 0x2102, 0x2001, 0xa597, 0x2102, 0xa182,
- 0x0211, 0x00c8, 0x219f, 0x2009, 0x0008, 0x0078, 0x21c9, 0xa182,
- 0x0259, 0x00c8, 0x21a7, 0x2009, 0x0007, 0x0078, 0x21c9, 0xa182,
- 0x02c1, 0x00c8, 0x21af, 0x2009, 0x0006, 0x0078, 0x21c9, 0xa182,
- 0x0349, 0x00c8, 0x21b7, 0x2009, 0x0005, 0x0078, 0x21c9, 0xa182,
- 0x0421, 0x00c8, 0x21bf, 0x2009, 0x0004, 0x0078, 0x21c9, 0xa182,
- 0x0581, 0x00c8, 0x21c7, 0x2009, 0x0003, 0x0078, 0x21c9, 0x2009,
- 0x0002, 0x2079, 0x0200, 0x7912, 0x7817, 0x0004, 0x1078, 0x24b5,
- 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x127e, 0x2091, 0x2200, 0x2061,
- 0x0100, 0x2071, 0xa300, 0x6024, 0x6026, 0x6053, 0x0030, 0x6033,
- 0x00ef, 0x60e7, 0x0000, 0x60eb, 0x00ef, 0x60e3, 0x0008, 0x604b,
- 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007,
- 0x0eaf, 0x600f, 0x00ff, 0x602b, 0x002f, 0x127f, 0x007c, 0x2001,
- 0xa32f, 0x2003, 0x0000, 0x2001, 0xa32e, 0x2003, 0x0001, 0x007c,
- 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x6124, 0xa184,
- 0x002c, 0x00c0, 0x220f, 0xa184, 0x0007, 0x0079, 0x2215, 0xa195,
- 0x0004, 0xa284, 0x0007, 0x0079, 0x2215, 0x2241, 0x221d, 0x2221,
- 0x2225, 0x222b, 0x222f, 0x2235, 0x223b, 0x1078, 0x5ad2, 0x0078,
- 0x2241, 0x1078, 0x5bc1, 0x0078, 0x2241, 0x1078, 0x5bc1, 0x1078,
- 0x5ad2, 0x0078, 0x2241, 0x1078, 0x2246, 0x0078, 0x2241, 0x1078,
- 0x5ad2, 0x1078, 0x2246, 0x0078, 0x2241, 0x1078, 0x5bc1, 0x1078,
- 0x2246, 0x0078, 0x2241, 0x1078, 0x5bc1, 0x1078, 0x5ad2, 0x1078,
- 0x2246, 0x027f, 0x017f, 0x007f, 0x127f, 0x007c, 0x6124, 0xd1ac,
- 0x0040, 0x2342, 0x017e, 0x047e, 0x0c7e, 0x644c, 0xa486, 0xf0f0,
- 0x00c0, 0x2259, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043,
- 0x0010, 0x74c2, 0xa48c, 0xff00, 0x7034, 0xd084, 0x0040, 0x2271,
- 0xa186, 0xf800, 0x00c0, 0x2271, 0x7038, 0xd084, 0x00c0, 0x2271,
- 0xc085, 0x703a, 0x037e, 0x2418, 0x2011, 0x8016, 0x1078, 0x3579,
- 0x037f, 0xa196, 0xff00, 0x0040, 0x22b3, 0x6030, 0xa084, 0x00ff,
- 0x810f, 0xa116, 0x0040, 0x22b3, 0x7130, 0xd184, 0x00c0, 0x22b3,
- 0x2011, 0xa352, 0x2214, 0xd2ec, 0x0040, 0x228e, 0xc18d, 0x7132,
- 0x2011, 0xa352, 0x2214, 0xd2ac, 0x00c0, 0x22b3, 0x6240, 0xa294,
- 0x0010, 0x0040, 0x229a, 0x6248, 0xa294, 0xff00, 0xa296, 0xff00,
- 0x0040, 0x22b3, 0x7030, 0xd08c, 0x0040, 0x2305, 0x7034, 0xd08c,
- 0x00c0, 0x22aa, 0x2001, 0xa30c, 0x200c, 0xd1ac, 0x00c0, 0x2305,
- 0xc1ad, 0x2102, 0x037e, 0x73c0, 0x2011, 0x8013, 0x1078, 0x3579,
- 0x037f, 0x0078, 0x2305, 0x7034, 0xd08c, 0x00c0, 0x22bf, 0x2001,
- 0xa30c, 0x200c, 0xd1ac, 0x00c0, 0x2305, 0xc1ad, 0x2102, 0x037e,
- 0x73c0, 0x2011, 0x8013, 0x1078, 0x3579, 0x037f, 0x7130, 0xc185,
- 0x7132, 0x2011, 0xa352, 0x220c, 0xd1a4, 0x0040, 0x22e9, 0x017e,
- 0x2009, 0x0001, 0x2011, 0x0100, 0x1078, 0x5a6d, 0x2019, 0x000e,
- 0x1078, 0x9e3b, 0xa484, 0x00ff, 0xa080, 0x293f, 0x200c, 0xa18c,
- 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x1078, 0x9ec0,
- 0x017f, 0xd1ac, 0x00c0, 0x22f6, 0x017e, 0x2009, 0x0000, 0x2019,
- 0x0004, 0x1078, 0x27e2, 0x017f, 0x0078, 0x2305, 0x157e, 0x20a9,
- 0x007f, 0x2009, 0x0000, 0x1078, 0x4501, 0x00c0, 0x2301, 0x1078,
- 0x4235, 0x8108, 0x00f0, 0x22fb, 0x157f, 0x0c7f, 0x047f, 0x0f7e,
- 0x2079, 0xa5be, 0x783c, 0xa086, 0x0000, 0x0040, 0x2317, 0x6027,
- 0x0004, 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x0000, 0x0f7f,
- 0x2011, 0x0003, 0x1078, 0x6ef2, 0x2011, 0x0002, 0x1078, 0x6efc,
- 0x1078, 0x6dda, 0x1078, 0x595a, 0x037e, 0x2019, 0x0000, 0x1078,
- 0x6e6c, 0x037f, 0x60e3, 0x0000, 0x017f, 0x2001, 0xa300, 0x2014,
- 0xa296, 0x0004, 0x00c0, 0x233a, 0xd19c, 0x00c0, 0x233a, 0x6228,
- 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xa321, 0x2003, 0x0000,
- 0x6027, 0x0020, 0xd194, 0x0040, 0x2426, 0x0f7e, 0x2079, 0xa5be,
- 0x783c, 0xa086, 0x0001, 0x00c0, 0x2366, 0x017e, 0x6027, 0x0004,
- 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x1000, 0x7803, 0x0000,
- 0x2079, 0xa5ab, 0x7807, 0x0000, 0x7833, 0x0000, 0x1078, 0x6109,
- 0x1078, 0x61d3, 0x017f, 0x0f7f, 0x0078, 0x2426, 0x0f7f, 0x017e,
- 0x3900, 0xa082, 0xa6cd, 0x00c8, 0x2371, 0x017e, 0x1078, 0x728a,
- 0x017f, 0x6220, 0xd2b4, 0x0040, 0x23dc, 0x1078, 0x595a, 0x1078,
- 0x6c41, 0x6027, 0x0004, 0x0f7e, 0x2019, 0xa5b4, 0x2304, 0xa07d,
- 0x0040, 0x23b2, 0x7804, 0xa086, 0x0032, 0x00c0, 0x23b2, 0x0d7e,
- 0x0c7e, 0x0e7e, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e,
- 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x00c0,
- 0x2396, 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, 0x0000, 0x618e,
- 0x628a, 0x1078, 0x6010, 0x1078, 0x6109, 0x7810, 0x2070, 0x7037,
- 0x0103, 0x2f60, 0x1078, 0x753d, 0x0e7f, 0x0c7f, 0x0d7f, 0x0f7f,
- 0x017f, 0x007c, 0x0f7f, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084,
- 0x4000, 0x0040, 0x23bf, 0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f,
- 0x0c7e, 0x2061, 0xa5ab, 0x6028, 0xa09a, 0x00c8, 0x00c8, 0x23cf,
- 0x8000, 0x602a, 0x0c7f, 0x1078, 0x6c33, 0x0078, 0x2425, 0x2019,
- 0xa5b4, 0x2304, 0xa065, 0x0040, 0x23d9, 0x2009, 0x0027, 0x1078,
- 0x756c, 0x0c7f, 0x0078, 0x2425, 0xd2bc, 0x0040, 0x2425, 0x1078,
- 0x5967, 0x6017, 0x0010, 0x6027, 0x0004, 0x0d7e, 0x2069, 0x0140,
- 0x6804, 0xa084, 0x4000, 0x0040, 0x23f1, 0x6803, 0x1000, 0x6803,
- 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa5ab, 0x6044, 0xa09a, 0x00c8,
- 0x00c8, 0x2414, 0x8000, 0x6046, 0x603c, 0x0c7f, 0xa005, 0x0040,
- 0x2425, 0x2009, 0x07d0, 0x1078, 0x595f, 0xa080, 0x0007, 0x2004,
- 0xa086, 0x0006, 0x00c0, 0x2410, 0x6017, 0x0012, 0x0078, 0x2425,
- 0x6017, 0x0016, 0x0078, 0x2425, 0x037e, 0x2019, 0x0001, 0x1078,
- 0x6e6c, 0x037f, 0x2019, 0xa5ba, 0x2304, 0xa065, 0x0040, 0x2424,
- 0x2009, 0x004f, 0x1078, 0x756c, 0x0c7f, 0x017f, 0xd19c, 0x0040,
- 0x247c, 0x7034, 0xd0ac, 0x00c0, 0x2457, 0x017e, 0x157e, 0x6027,
- 0x0008, 0x602f, 0x0020, 0x20a9, 0x000a, 0x00f0, 0x2435, 0x602f,
- 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, 0x0320, 0x00e0,
- 0x243f, 0x2091, 0x6000, 0x6020, 0xd09c, 0x00c0, 0x244e, 0x157f,
- 0x6152, 0x017f, 0x6027, 0x0008, 0x0078, 0x247c, 0x1078, 0x250d,
- 0x00f0, 0x243f, 0x157f, 0x6152, 0x017f, 0x6027, 0x0008, 0x017e,
- 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x1078, 0x6ef2, 0x2011,
- 0x0002, 0x1078, 0x6efc, 0x1078, 0x6dda, 0x1078, 0x595a, 0x037e,
- 0x2019, 0x0000, 0x1078, 0x6e6c, 0x037f, 0x60e3, 0x0000, 0x1078,
- 0xa22a, 0x1078, 0xa248, 0x2001, 0xa300, 0x2003, 0x0004, 0x6027,
- 0x0008, 0x1078, 0x1246, 0x017f, 0xa18c, 0xffd0, 0x6126, 0x007c,
- 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e, 0x127e, 0x2091, 0x8000,
- 0x2071, 0xa300, 0x71b8, 0x70ba, 0xa116, 0x0040, 0x24ae, 0x81ff,
- 0x0040, 0x2498, 0x2011, 0x8011, 0x1078, 0x3579, 0x0078, 0x24ae,
- 0x2011, 0x8012, 0x1078, 0x3579, 0x2001, 0xa371, 0x2004, 0xd0fc,
- 0x00c0, 0x24ae, 0x037e, 0x0c7e, 0x2061, 0x0100, 0x2019, 0x0028,
- 0x2009, 0x0000, 0x1078, 0x27e2, 0x0c7f, 0x037f, 0x127f, 0x0f7f,
- 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c, 0x0c7e, 0x0f7e, 0x007e,
- 0x027e, 0x2061, 0x0100, 0xa190, 0x24d1, 0x2204, 0x60f2, 0x2011,
- 0x24de, 0x6000, 0xa082, 0x0003, 0x00c8, 0x24ca, 0x2001, 0x00ff,
- 0x0078, 0x24cb, 0x2204, 0x60ee, 0x027f, 0x007f, 0x0f7f, 0x0c7f,
- 0x007c, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, 0x0348, 0x02c0,
- 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8,
- 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, 0x2130, 0xa094,
- 0xff00, 0x00c0, 0x24ee, 0x81ff, 0x0040, 0x24f2, 0x1078, 0x5623,
- 0x0078, 0x24f9, 0xa080, 0x293f, 0x200c, 0xa18c, 0xff00, 0x810f,
- 0xa006, 0x007c, 0xa080, 0x293f, 0x200c, 0xa18c, 0x00ff, 0x007c,
- 0x0c7e, 0x2061, 0xa300, 0x6030, 0x0040, 0x2509, 0xc09d, 0x0078,
- 0x250a, 0xc09c, 0x6032, 0x0c7f, 0x007c, 0x007e, 0x157e, 0x0f7e,
- 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, 0x00c0, 0x251a,
- 0x00f0, 0x2514, 0x0f7f, 0x157f, 0x007f, 0x007c, 0x0c7e, 0x007e,
- 0x2061, 0x0100, 0x6030, 0x007e, 0x6048, 0x007e, 0x60e4, 0x007e,
- 0x60e8, 0x007e, 0x6050, 0x007e, 0x60f0, 0x007e, 0x60ec, 0x007e,
- 0x600c, 0x007e, 0x6004, 0x007e, 0x6028, 0x007e, 0x60e0, 0x007e,
- 0x602f, 0x0100, 0x602f, 0x0000, 0x0005, 0x0005, 0x0005, 0x0005,
- 0x602f, 0x0040, 0x602f, 0x0000, 0x007f, 0x60e2, 0x007f, 0x602a,
- 0x007f, 0x6006, 0x007f, 0x600e, 0x007f, 0x60ee, 0x007f, 0x60f2,
- 0x007f, 0x6052, 0x007f, 0x60ea, 0x007f, 0x60e6, 0x007f, 0x604a,
- 0x007f, 0x6032, 0x007f, 0x0c7f, 0x007c, 0x257d, 0x2581, 0x2585,
- 0x258b, 0x2591, 0x2597, 0x259d, 0x25a5, 0x25ad, 0x25b3, 0x25b9,
- 0x25c1, 0x25c9, 0x25d1, 0x25d9, 0x25e3, 0x25ed, 0x25ed, 0x25ed,
- 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed,
- 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x107e, 0x007e, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078,
- 0x2200, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e,
- 0x007e, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078,
- 0x2200, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078,
- 0x2200, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078,
- 0x2123, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, 0x2123, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, 0x2123, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, 0x2123, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x1078, 0x20de, 0x1078, 0x2123, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x1078, 0x20de, 0x1078, 0x2123, 0x0078,
- 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, 0x20de, 0x1078,
- 0x2123, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078,
- 0x20de, 0x1078, 0x2123, 0x0078, 0x2606, 0x0005, 0x0078, 0x25ed,
- 0xb084, 0x003c, 0x8004, 0x8004, 0x0079, 0x25f6, 0x2606, 0x2583,
- 0x2587, 0x258d, 0x2593, 0x2599, 0x259f, 0x25a7, 0x25af, 0x25b5,
- 0x25bb, 0x25c3, 0x25cb, 0x25d3, 0x25db, 0x25e5, 0x0008, 0x25f0,
- 0x007f, 0x107f, 0x2091, 0x8001, 0x007c, 0x0c7e, 0x027e, 0x047e,
- 0x2021, 0x0000, 0x1078, 0x4897, 0x00c0, 0x2705, 0x70c8, 0xd09c,
- 0x0040, 0x2624, 0xd084, 0x00c0, 0x2624, 0xd0bc, 0x00c0, 0x2705,
- 0x1078, 0x2709, 0x0078, 0x2705, 0xd094, 0x0040, 0x262b, 0x7093,
- 0xffff, 0x0078, 0x2705, 0x2001, 0x010c, 0x203c, 0x7280, 0xd284,
- 0x0040, 0x2694, 0xd28c, 0x00c0, 0x2694, 0x037e, 0x7390, 0xa38e,
- 0xffff, 0x0040, 0x263e, 0x83ff, 0x00c0, 0x2640, 0x2019, 0x0001,
- 0x8314, 0xa2e0, 0xa9c0, 0x2c04, 0xa38c, 0x0001, 0x0040, 0x264d,
- 0xa084, 0xff00, 0x8007, 0x0078, 0x264f, 0xa084, 0x00ff, 0xa70e,
- 0x0040, 0x2689, 0xa08e, 0x0000, 0x0040, 0x2689, 0xa08e, 0x00ff,
- 0x00c0, 0x2666, 0x7230, 0xd284, 0x00c0, 0x268f, 0x7280, 0xc28d,
- 0x7282, 0x7093, 0xffff, 0x037f, 0x0078, 0x2694, 0x2009, 0x0000,
- 0x1078, 0x24e3, 0x1078, 0x4499, 0x00c0, 0x268c, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2683, 0x7030, 0xd08c, 0x0040,
- 0x267d, 0x6000, 0xd0bc, 0x0040, 0x2683, 0x1078, 0x271f, 0x0040,
- 0x268c, 0x0078, 0x2689, 0x1078, 0x2857, 0x1078, 0x274c, 0x0040,
- 0x268c, 0x8318, 0x0078, 0x2640, 0x7392, 0x0078, 0x2691, 0x7093,
- 0xffff, 0x037f, 0x0078, 0x2705, 0xa780, 0x293f, 0x203c, 0xa7bc,
- 0xff00, 0x873f, 0x2041, 0x007e, 0x7090, 0xa096, 0xffff, 0x00c0,
- 0x26a6, 0x2009, 0x0000, 0x28a8, 0x0078, 0x26b2, 0xa812, 0x0048,
- 0x26ae, 0x2008, 0xa802, 0x20a8, 0x0078, 0x26b2, 0x7093, 0xffff,
- 0x0078, 0x2705, 0x2700, 0x157e, 0x017e, 0xa106, 0x0040, 0x26f9,
- 0xc484, 0x1078, 0x4501, 0x0040, 0x26c3, 0x1078, 0x4499, 0x00c0,
- 0x2702, 0x0078, 0x26c4, 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086,
- 0x0006, 0x00c0, 0x26d3, 0x7030, 0xd08c, 0x0040, 0x26f1, 0x6000,
- 0xd0bc, 0x00c0, 0x26f1, 0x7280, 0xd28c, 0x0040, 0x26e9, 0x6004,
- 0xa084, 0x00ff, 0xa082, 0x0006, 0x0048, 0x26f9, 0xd484, 0x00c0,
- 0x26e5, 0x1078, 0x44bc, 0x0078, 0x26e7, 0x1078, 0x2921, 0x0078,
- 0x26f9, 0x1078, 0x2857, 0x1078, 0x274c, 0x0040, 0x2702, 0x0078,
- 0x26f9, 0x1078, 0x28ec, 0x0040, 0x26f9, 0x1078, 0x271f, 0x0040,
- 0x2702, 0x017f, 0x8108, 0x157f, 0x00f0, 0x26b2, 0x7093, 0xffff,
- 0x0078, 0x2705, 0x017f, 0x157f, 0x7192, 0x047f, 0x027f, 0x0c7f,
- 0x007c, 0x0c7e, 0x017e, 0x7093, 0x0000, 0x2009, 0x007e, 0x1078,
- 0x4499, 0x00c0, 0x271c, 0x1078, 0x2857, 0x1078, 0x274c, 0x0040,
- 0x271c, 0x70c8, 0xc0bd, 0x70ca, 0x017f, 0x0c7f, 0x007c, 0x017e,
- 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x2001, 0xa356, 0x2004, 0xa084,
- 0x00ff, 0x6842, 0x1078, 0x74d7, 0x0040, 0x2747, 0x2d00, 0x601a,
- 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0000,
- 0x1078, 0x443f, 0x127e, 0x2091, 0x8000, 0x708c, 0x8000, 0x708e,
- 0x127f, 0x2009, 0x0004, 0x1078, 0x756c, 0xa085, 0x0001, 0x0c7f,
- 0x0d7f, 0x077f, 0x017f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e,
- 0x2c68, 0x2001, 0xa356, 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078,
- 0x74d7, 0x0040, 0x2785, 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802,
- 0x68a0, 0xa086, 0x007e, 0x0040, 0x276e, 0x6804, 0xa084, 0x00ff,
- 0xa086, 0x0006, 0x00c0, 0x276e, 0x1078, 0x2813, 0x601f, 0x0001,
- 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, 0x443f,
- 0x127e, 0x2091, 0x8000, 0x708c, 0x8000, 0x708e, 0x127f, 0x2009,
- 0x0002, 0x1078, 0x756c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f,
- 0x017f, 0x007c, 0x0c7e, 0x027e, 0x2009, 0x0080, 0x1078, 0x4499,
- 0x00c0, 0x2798, 0x1078, 0x279b, 0x0040, 0x2798, 0x70cf, 0xffff,
- 0x027f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68,
- 0x1078, 0x74d7, 0x0040, 0x27bd, 0x2d00, 0x601a, 0x601f, 0x0001,
- 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, 0x443f,
- 0x127e, 0x2091, 0x8000, 0x70d0, 0x8000, 0x70d2, 0x127f, 0x2009,
- 0x0002, 0x1078, 0x756c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f,
- 0x017f, 0x007c, 0x0c7e, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2009,
- 0x007f, 0x1078, 0x4499, 0x00c0, 0x27de, 0x2c68, 0x1078, 0x74d7,
- 0x0040, 0x27de, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a,
- 0x2009, 0x0022, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x0d7f,
- 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078,
- 0x5d60, 0x1078, 0x5d02, 0x1078, 0x7ddf, 0x2130, 0x81ff, 0x0040,
- 0x27f7, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0078, 0x27fb, 0x20a9,
- 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x4501, 0x00c0, 0x2804,
- 0x1078, 0x471b, 0x1078, 0x4235, 0x017f, 0x8108, 0x00f0, 0x27fb,
- 0x86ff, 0x00c0, 0x280d, 0x1078, 0x119b, 0x027f, 0x037f, 0x067f,
- 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e,
- 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x5d53,
- 0x077e, 0x2039, 0x0000, 0x1078, 0x5c78, 0x2c08, 0x1078, 0x9c38,
- 0x077f, 0x017f, 0x2e60, 0x1078, 0x471b, 0x6210, 0x6314, 0x1078,
- 0x4235, 0x6212, 0x6316, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f,
- 0x007c, 0x0e7e, 0x007e, 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc,
- 0x00c0, 0x284d, 0x2071, 0xa300, 0x708c, 0xa005, 0x0040, 0x284a,
- 0x8001, 0x708e, 0x007f, 0x0e7f, 0x007c, 0x2071, 0xa300, 0x70d0,
- 0xa005, 0x0040, 0x284a, 0x8001, 0x70d2, 0x0078, 0x284a, 0x6000,
- 0xc08c, 0x6002, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x037e, 0x027e,
- 0x017e, 0x157e, 0x2178, 0x81ff, 0x00c0, 0x286a, 0x20a9, 0x0001,
- 0x0078, 0x2885, 0x2001, 0xa352, 0x2004, 0xd0c4, 0x0040, 0x2881,
- 0xd0a4, 0x0040, 0x2881, 0x047e, 0x6018, 0xa080, 0x0028, 0x2024,
- 0xa4a4, 0x00ff, 0x8427, 0xa006, 0x2009, 0x002d, 0x1078, 0x9ec0,
- 0x047f, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x027e, 0xa28e, 0x007e,
- 0x0040, 0x28c9, 0xa28e, 0x007f, 0x0040, 0x28c9, 0xa28e, 0x0080,
- 0x0040, 0x28c9, 0xa288, 0xa434, 0x210c, 0x81ff, 0x0040, 0x28c9,
- 0x8fff, 0x1040, 0x28d5, 0x0c7e, 0x2160, 0x2001, 0x0001, 0x1078,
- 0x48a2, 0x0c7f, 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039,
- 0x0000, 0x1078, 0x5c78, 0x0c7e, 0x027e, 0x2160, 0x6204, 0xa294,
- 0x00ff, 0xa286, 0x0006, 0x00c0, 0x28b9, 0x6007, 0x0404, 0x0078,
- 0x28be, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206, 0x027f, 0x0c7f,
- 0x017e, 0x2c08, 0x1078, 0x9c38, 0x017f, 0x077f, 0x2160, 0x1078,
- 0x471b, 0x027f, 0x8210, 0x00f0, 0x2885, 0x157f, 0x017f, 0x027f,
- 0x037f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x047e, 0x027e, 0x017e,
- 0x2001, 0xa352, 0x2004, 0xd0c4, 0x0040, 0x28e8, 0xd0a4, 0x0040,
- 0x28e8, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, 0x1078, 0x9ec0,
- 0x017f, 0x027f, 0x047f, 0x007c, 0x017e, 0x027e, 0x037e, 0x0c7e,
- 0x7280, 0x82ff, 0x0040, 0x291a, 0xa290, 0xa352, 0x2214, 0xd2ac,
- 0x00c0, 0x291a, 0x2100, 0x1078, 0x24fa, 0x81ff, 0x0040, 0x291c,
- 0x2019, 0x0001, 0x8314, 0xa2e0, 0xa9c0, 0x2c04, 0xd384, 0x0040,
- 0x290e, 0xa084, 0xff00, 0x8007, 0x0078, 0x2910, 0xa084, 0x00ff,
- 0xa116, 0x0040, 0x291c, 0xa096, 0x00ff, 0x0040, 0x291a, 0x8318,
- 0x0078, 0x2902, 0xa085, 0x0001, 0x0c7f, 0x037f, 0x027f, 0x017f,
- 0x007c, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0xa180, 0xa434,
- 0x2004, 0xa065, 0x0040, 0x293b, 0x017e, 0x0c7e, 0x1078, 0x8ec0,
- 0x017f, 0x1040, 0x1328, 0x611a, 0x1078, 0x2813, 0x1078, 0x753d,
- 0x017f, 0x1078, 0x44bc, 0x127f, 0x0c7f, 0x017f, 0x007c, 0x7eef,
- 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9,
- 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd,
- 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3,
- 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2,
- 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7,
- 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098,
- 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080,
- 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072,
- 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067,
- 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055,
- 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b,
- 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a,
- 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e,
- 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025,
- 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010,
- 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800,
- 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000,
- 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000,
- 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000,
- 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000,
- 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000,
- 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000,
- 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000,
- 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000,
- 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000,
- 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500,
- 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071,
- 0xa381, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e,
- 0x7033, 0xa391, 0x7037, 0xa391, 0x7007, 0x0001, 0x2061, 0xa3d1,
- 0x6003, 0x0002, 0x007c, 0x0090, 0x2a66, 0x0068, 0x2a66, 0x2071,
- 0xa381, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2a66, 0x2a60, 0x7820,
- 0xa08e, 0x0069, 0x00c0, 0x2b56, 0x0079, 0x2aea, 0x007c, 0x2071,
- 0xa381, 0x7004, 0x0079, 0x2a6c, 0x2a70, 0x2a71, 0x2a7b, 0x2a8d,
- 0x007c, 0x0090, 0x2a7a, 0x0068, 0x2a7a, 0x2b78, 0x7818, 0xd084,
- 0x0040, 0x2a99, 0x007c, 0x2b78, 0x2061, 0xa3d1, 0x6008, 0xa08e,
- 0x0100, 0x0040, 0x2a88, 0xa086, 0x0200, 0x0040, 0x2b4e, 0x007c,
- 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, 0x2068, 0x6834,
- 0xa086, 0x0103, 0x0040, 0x2a95, 0x007c, 0x2a60, 0x2b78, 0x7018,
- 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, 0x2aa2, 0x61b8,
- 0x0079, 0x2aaa, 0x2100, 0xa08a, 0x003f, 0x00c8, 0x2b4a, 0x61b8,
- 0x0079, 0x2aea, 0x2b2c, 0x2b5e, 0x2b66, 0x2b6a, 0x2b72, 0x2b78,
- 0x2b7c, 0x2b88, 0x2b8c, 0x2b96, 0x2b9a, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b9e, 0x2b4a, 0x2bae, 0x2bc5, 0x2bdc, 0x2c58, 0x2c5d, 0x2c8a,
- 0x2ce4, 0x2cf5, 0x2d13, 0x2d54, 0x2d5e, 0x2d6b, 0x2d7e, 0x2d9d,
- 0x2da6, 0x2de3, 0x2de9, 0x2b4a, 0x2e05, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x2b4a, 0x2e0c, 0x2e16, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2e1e, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x2b4a, 0x2e30, 0x2e47, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x2b4a, 0x2e59, 0x2eb0, 0x2f0e, 0x2f1f, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x38f1, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x2b4a, 0x2b96, 0x2b9a, 0x2f36, 0x2b4a, 0x2f43, 0x397d,
- 0x39da, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a,
- 0x2b4a, 0x2b4a, 0x2f90, 0x30c5, 0x30e1, 0x30ed, 0x3150, 0x31a9,
- 0x31b4, 0x31f3, 0x3202, 0x3211, 0x3214, 0x2f47, 0x3238, 0x3284,
- 0x3291, 0x33a2, 0x34cd, 0x34f7, 0x3604, 0x3614, 0x3621, 0x365b,
- 0x372a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x3792, 0x37ae, 0x3828,
- 0x38e2, 0x713c, 0x0078, 0x2b2c, 0x2021, 0x4000, 0x1078, 0x3553,
- 0x127e, 0x2091, 0x8000, 0x0068, 0x2b39, 0x7818, 0xd084, 0x0040,
- 0x2b3c, 0x127f, 0x0078, 0x2b30, 0x7c22, 0x7926, 0x7a2a, 0x7b2e,
- 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000,
- 0x127f, 0x007c, 0x2021, 0x4001, 0x0078, 0x2b2e, 0x2021, 0x4002,
- 0x0078, 0x2b2e, 0x2021, 0x4003, 0x0078, 0x2b2e, 0x2021, 0x4005,
- 0x0078, 0x2b2e, 0x2021, 0x4006, 0x0078, 0x2b2e, 0xa02e, 0x2520,
- 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x3562, 0x7823, 0x0004,
- 0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930,
- 0x0078, 0x3566, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, 0x2b2c,
- 0x7924, 0x2114, 0x0078, 0x2b2c, 0x2099, 0x0009, 0x20a1, 0x0009,
- 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0078, 0x2b2c,
- 0x7824, 0x2060, 0x0078, 0x2ba0, 0x2009, 0x0001, 0x2011, 0x0013,
- 0x2019, 0x0010, 0x783b, 0x0017, 0x0078, 0x2b2c, 0x7d38, 0x7c3c,
- 0x0078, 0x2b60, 0x7d38, 0x7c3c, 0x0078, 0x2b6c, 0x2061, 0x1000,
- 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109, 0x00c0, 0x2ba2,
- 0x2010, 0xa005, 0x0040, 0x2b2c, 0x0078, 0x2b52, 0x2069, 0xa351,
- 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2b5a, 0x8019, 0x0040, 0x2b5a,
- 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, 0x685a,
- 0x685e, 0x1078, 0x4dbd, 0x0078, 0x2b2c, 0x2069, 0xa351, 0x7824,
- 0x7934, 0xa11a, 0x00c8, 0x2b5a, 0x8019, 0x0040, 0x2b5a, 0x684e,
- 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, 0x686e,
- 0x1078, 0x494d, 0x0078, 0x2b2c, 0xa02e, 0x2520, 0x81ff, 0x00c0,
- 0x2b56, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xa388,
- 0x41a1, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009, 0x0020, 0x1078,
- 0x3562, 0x701b, 0x2bf4, 0x007c, 0x6834, 0x2008, 0xa084, 0x00ff,
- 0xa096, 0x0011, 0x0040, 0x2c00, 0xa096, 0x0019, 0x00c0, 0x2b56,
- 0x810f, 0xa18c, 0x00ff, 0x0040, 0x2b56, 0x710e, 0x700c, 0x8001,
- 0x0040, 0x2c31, 0x700e, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009,
- 0x0020, 0x2061, 0xa3d1, 0x6224, 0x6328, 0x642c, 0x6530, 0xa290,
- 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x1078,
- 0x3562, 0x701b, 0x2c24, 0x007c, 0x6834, 0xa084, 0x00ff, 0xa096,
- 0x0002, 0x0040, 0x2c2f, 0xa096, 0x000a, 0x00c0, 0x2b56, 0x0078,
- 0x2c06, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x436e,
- 0x00c0, 0x2c3f, 0x7007, 0x0003, 0x701b, 0x2c41, 0x007c, 0x1078,
- 0x4a60, 0x127e, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xa388,
- 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
- 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x127f, 0x0078, 0x3566,
- 0x61a0, 0x7824, 0x60a2, 0x0078, 0x2b2c, 0x2091, 0x8000, 0x7823,
- 0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009,
- 0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200,
- 0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd,
- 0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080,
- 0x2071, 0x0010, 0x20c1, 0x00f0, 0xa08a, 0x0003, 0x00c8, 0x0427,
- 0x0078, 0x0423, 0x81ff, 0x00c0, 0x2b56, 0x7924, 0x810f, 0xa18c,
- 0x00ff, 0x1078, 0x4501, 0x00c0, 0x2b5a, 0x7e38, 0xa684, 0x3fff,
- 0xa082, 0x4000, 0x0048, 0x2c9e, 0x0078, 0x2b5a, 0x7c28, 0x7d2c,
- 0x1078, 0x46d6, 0xd28c, 0x00c0, 0x2ca9, 0x1078, 0x466a, 0x0078,
- 0x2cab, 0x1078, 0x46a4, 0x00c0, 0x2cd5, 0x2061, 0xaa00, 0x127e,
- 0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0040, 0x2cc3, 0x6010,
- 0xa06d, 0x0040, 0x2cc3, 0x683c, 0xa406, 0x00c0, 0x2cc3, 0x6840,
- 0xa506, 0x0040, 0x2cce, 0x127f, 0xace0, 0x0010, 0x2001, 0xa315,
- 0x2004, 0xac02, 0x00c8, 0x2b56, 0x0078, 0x2caf, 0x1078, 0x8758,
- 0x127f, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0xa00e, 0x2001, 0x0005,
- 0x1078, 0x4a60, 0x127e, 0x2091, 0x8000, 0x1078, 0x8cc0, 0x1078,
- 0x4982, 0x127f, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x1078,
- 0x3530, 0x0040, 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078,
- 0x46e4, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56,
- 0x1078, 0x3542, 0x0040, 0x2b5a, 0x1078, 0x475f, 0x0040, 0x2b56,
- 0x2019, 0x0005, 0x1078, 0x4705, 0x0040, 0x2b56, 0x7828, 0xa08a,
- 0x1000, 0x00c8, 0x2b5a, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078,
- 0x58e1, 0x0078, 0x2b2c, 0x127e, 0x2091, 0x8000, 0x81ff, 0x0040,
- 0x2d1d, 0x2009, 0x0001, 0x0078, 0x2d4e, 0x2029, 0x00ff, 0x644c,
- 0x2400, 0xa506, 0x0040, 0x2d48, 0x2508, 0x1078, 0x4501, 0x00c0,
- 0x2d48, 0x1078, 0x475f, 0x00c0, 0x2d33, 0x2009, 0x0002, 0x62a8,
- 0x2518, 0x0078, 0x2d4e, 0x2019, 0x0004, 0x1078, 0x4705, 0x00c0,
- 0x2d3d, 0x2009, 0x0006, 0x0078, 0x2d4e, 0x7824, 0xa08a, 0x1000,
- 0x00c8, 0x2d51, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x58e1,
- 0x8529, 0x00c8, 0x2d20, 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078,
- 0x2b56, 0x127f, 0x0078, 0x2b5a, 0x1078, 0x3530, 0x0040, 0x2b5a,
- 0x1078, 0x461b, 0x1078, 0x46d6, 0x0078, 0x2b2c, 0x81ff, 0x00c0,
- 0x2b56, 0x1078, 0x3530, 0x0040, 0x2b5a, 0x1078, 0x460a, 0x1078,
- 0x46d6, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530,
- 0x0040, 0x2b5a, 0x1078, 0x46a7, 0x0040, 0x2b56, 0x1078, 0x43c1,
- 0x1078, 0x4663, 0x1078, 0x46d6, 0x0078, 0x2b2c, 0x1078, 0x3530,
- 0x0040, 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x62a0, 0x2019,
- 0x0005, 0x0c7e, 0x1078, 0x471b, 0x0c7f, 0x1078, 0x5d53, 0x077e,
- 0x2039, 0x0000, 0x1078, 0x5c78, 0x2009, 0x0000, 0x1078, 0x9c38,
- 0x077f, 0x1078, 0x46d6, 0x0078, 0x2b2c, 0x1078, 0x3530, 0x0040,
- 0x2b5a, 0x1078, 0x46d6, 0x2208, 0x0078, 0x2b2c, 0x157e, 0x0d7e,
- 0x0e7e, 0x2069, 0xa413, 0x6810, 0x6914, 0xa10a, 0x00c8, 0x2db2,
- 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9,
- 0x00ff, 0x2069, 0xa434, 0x2d04, 0xa075, 0x0040, 0x2dc7, 0x704c,
- 0x1078, 0x2dd1, 0xa210, 0x7080, 0x1078, 0x2dd1, 0xa318, 0x8d68,
- 0x00f0, 0x2dbb, 0x2300, 0xa218, 0x0e7f, 0x0d7f, 0x157f, 0x0078,
- 0x2b2c, 0x0f7e, 0x017e, 0xa07d, 0x0040, 0x2de0, 0x2001, 0x0000,
- 0x8000, 0x2f0c, 0x81ff, 0x0040, 0x2de0, 0x2178, 0x0078, 0x2dd8,
- 0x017f, 0x0f7f, 0x007c, 0x2069, 0xa413, 0x6910, 0x62a4, 0x0078,
- 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x614c, 0xa190, 0x293f, 0x2214,
- 0xa294, 0x00ff, 0x606c, 0xa084, 0xff00, 0xa215, 0x6368, 0x67c8,
- 0xd79c, 0x0040, 0x2dff, 0x2031, 0x0001, 0x0078, 0x2e01, 0x2031,
- 0x0000, 0x7e3a, 0x7f3e, 0x0078, 0x2b2c, 0x613c, 0x6240, 0x2019,
- 0xa5a0, 0x231c, 0x0078, 0x2b2c, 0x127e, 0x2091, 0x8000, 0x6134,
- 0xa006, 0x2010, 0x2018, 0x127f, 0x0078, 0x2b2c, 0x1078, 0x3542,
- 0x0040, 0x2b5a, 0x6244, 0x6338, 0x0078, 0x2b2c, 0x613c, 0x6240,
- 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0xa351, 0x831f, 0xa305,
- 0x6816, 0x782c, 0x2069, 0xa5a0, 0x2d1c, 0x206a, 0x0078, 0x2b2c,
- 0x017e, 0x127e, 0x2091, 0x8000, 0x7824, 0x6036, 0xd094, 0x0040,
- 0x2e43, 0x7828, 0xa085, 0x0001, 0x2009, 0xa5a9, 0x200a, 0x2001,
- 0xffff, 0x1078, 0x5975, 0x127f, 0x017f, 0x0078, 0x2b2c, 0x1078,
- 0x3542, 0x0040, 0x2b5a, 0x7828, 0xa00d, 0x0040, 0x2b5a, 0x782c,
- 0xa005, 0x0040, 0x2b5a, 0x6244, 0x6146, 0x6338, 0x603a, 0x0078,
- 0x2b2c, 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56,
- 0x0c7e, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196,
- 0x00ff, 0x00c0, 0x2e70, 0x6030, 0xa085, 0xff00, 0x0078, 0x2e7f,
- 0xa182, 0x007f, 0x00c8, 0x2ea9, 0xa188, 0x293f, 0x210c, 0xa18c,
- 0x00ff, 0x6030, 0xa116, 0x0040, 0x2ea9, 0x810f, 0xa105, 0x127e,
- 0x2091, 0x8000, 0x007e, 0x1078, 0x74d7, 0x007f, 0x0040, 0x2ea5,
- 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x1078, 0x3518, 0x0040,
- 0x2eac, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838,
- 0xc0fd, 0x683a, 0x701b, 0x2f07, 0x2d00, 0x6012, 0x2009, 0x0032,
- 0x1078, 0x756c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078,
- 0x2b56, 0x0c7f, 0x0078, 0x2b5a, 0x1078, 0x753d, 0x0078, 0x2ea5,
- 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, 0x0c7e,
- 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff,
- 0x00c0, 0x2ec7, 0x6030, 0xa085, 0xff00, 0x0078, 0x2ed6, 0xa182,
- 0x007f, 0x00c8, 0x2f00, 0xa188, 0x293f, 0x210c, 0xa18c, 0x00ff,
- 0x6030, 0xa116, 0x0040, 0x2f00, 0x810f, 0xa105, 0x127e, 0x2091,
- 0x8000, 0x007e, 0x1078, 0x74d7, 0x007f, 0x0040, 0x2efc, 0x601a,
- 0x600b, 0xbc05, 0x601f, 0x0001, 0x1078, 0x3518, 0x0040, 0x2f03,
- 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd,
- 0x683a, 0x701b, 0x2f07, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078,
- 0x756c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2b56,
- 0x0c7f, 0x0078, 0x2b5a, 0x1078, 0x753d, 0x0078, 0x2efc, 0x6830,
- 0xa086, 0x0100, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0x2061, 0xa62d,
- 0x127e, 0x2091, 0x8000, 0x6000, 0xd084, 0x0040, 0x2f1c, 0x6104,
- 0x6208, 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, 0x2b5a, 0x81ff,
- 0x00c0, 0x2b56, 0x127e, 0x2091, 0x8000, 0x6244, 0x6060, 0xa202,
- 0x0048, 0x2f33, 0xa085, 0x0001, 0x1078, 0x2500, 0x1078, 0x3bf5,
- 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, 0x2b5a, 0x127e, 0x2091,
- 0x8000, 0x20a9, 0x0011, 0x2001, 0xa340, 0x20a0, 0xa006, 0x40a4,
- 0x127f, 0x0078, 0x2b2c, 0x7d38, 0x7c3c, 0x0078, 0x2bde, 0x7824,
- 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x2b56, 0x624c, 0xa084,
- 0xff00, 0x8007, 0xa206, 0x00c0, 0x2f5f, 0x2001, 0xa340, 0x2009,
- 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x3566, 0x81ff,
- 0x00c0, 0x2b56, 0x1078, 0x3542, 0x0040, 0x2b5a, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2b56, 0x0c7e, 0x1078, 0x3518,
- 0x0c7f, 0x0040, 0x2b56, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a,
- 0x1078, 0x8b85, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, 0x2f81,
- 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2b56, 0xad80, 0x000e,
- 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x3566,
- 0x1078, 0x3518, 0x0040, 0x2b56, 0x1078, 0x421a, 0x2009, 0x001c,
- 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3562, 0x701b, 0x2fa1,
- 0x007c, 0xade8, 0x000d, 0x6800, 0xa005, 0x0040, 0x2b5a, 0x6804,
- 0xd0ac, 0x0040, 0x2fae, 0xd0a4, 0x0040, 0x2b5a, 0xd094, 0x0040,
- 0x2fb9, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, 0xffdf, 0x6106,
- 0x0c7f, 0xd08c, 0x0040, 0x2fc4, 0x0c7e, 0x2061, 0x0100, 0x6104,
- 0xa18d, 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, 0x210c, 0xa18a,
- 0x0002, 0x0048, 0x2fd9, 0xd084, 0x0040, 0x2fd9, 0x6a28, 0xa28a,
- 0x007f, 0x00c8, 0x2b5a, 0xa288, 0x293f, 0x210c, 0xa18c, 0x00ff,
- 0x6152, 0xd0dc, 0x0040, 0x2fe2, 0x6828, 0xa08a, 0x007f, 0x00c8,
- 0x2b5a, 0x604e, 0x6808, 0xa08a, 0x0100, 0x0048, 0x2b5a, 0xa08a,
- 0x0841, 0x00c8, 0x2b5a, 0xa084, 0x0007, 0x00c0, 0x2b5a, 0x680c,
- 0xa005, 0x0040, 0x2b5a, 0x6810, 0xa005, 0x0040, 0x2b5a, 0x6848,
- 0x6940, 0xa10a, 0x00c8, 0x2b5a, 0x8001, 0x0040, 0x2b5a, 0x684c,
- 0x6944, 0xa10a, 0x00c8, 0x2b5a, 0x8001, 0x0040, 0x2b5a, 0x6804,
- 0xd0fc, 0x0040, 0x3038, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009,
- 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399,
- 0x0000, 0x1078, 0x3562, 0x701b, 0x301e, 0x007c, 0xade8, 0x000d,
- 0x20a9, 0x0014, 0x2d98, 0x2069, 0xa36d, 0x2da0, 0x53a3, 0x7010,
- 0xa0e8, 0x000d, 0x2001, 0xa371, 0x200c, 0xd1e4, 0x0040, 0x3038,
- 0x0c7e, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, 0x6006, 0x0c7f,
- 0x20a9, 0x001c, 0x2d98, 0x2069, 0xa351, 0x2da0, 0x53a3, 0x6814,
- 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084, 0x00ff, 0x6042, 0x1078,
- 0x4dbd, 0x1078, 0x48dd, 0x1078, 0x494d, 0x6000, 0xa086, 0x0000,
- 0x00c0, 0x30c3, 0x6808, 0x602a, 0x1078, 0x218b, 0x6818, 0x691c,
- 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a,
- 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0040, 0x3070, 0x6830, 0x6934,
- 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0078, 0x3072,
- 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x1078, 0x59a8,
- 0x6904, 0xd1fc, 0x0040, 0x30a5, 0x0c7e, 0x2009, 0x0000, 0x20a9,
- 0x0001, 0x6b70, 0xd384, 0x0040, 0x30a2, 0x0078, 0x308c, 0x839d,
- 0x00c8, 0x30a2, 0x3508, 0x8109, 0x1078, 0x5364, 0x6878, 0x6016,
- 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, 0x00ff,
- 0x6006, 0x8108, 0x00c0, 0x30a0, 0x6003, 0x0003, 0x0078, 0x30a2,
- 0x6003, 0x0001, 0x00f0, 0x3087, 0x0c7f, 0x0c7e, 0x2061, 0x0100,
- 0x602f, 0x0040, 0x602f, 0x0000, 0x0c7f, 0x1078, 0x3784, 0x0040,
- 0x30b3, 0x1078, 0x2500, 0x60bc, 0xa005, 0x0040, 0x30bf, 0x6003,
- 0x0001, 0x2091, 0x301d, 0x1078, 0x4171, 0x0078, 0x30c3, 0x6003,
- 0x0004, 0x2091, 0x301d, 0x0078, 0x2b2c, 0x6000, 0xa086, 0x0000,
- 0x0040, 0x2b56, 0x2069, 0xa351, 0x7830, 0x6842, 0x7834, 0x6846,
- 0x6804, 0xd0fc, 0x0040, 0x30d8, 0x2009, 0x0030, 0x0078, 0x30da,
- 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078,
- 0x3566, 0xa006, 0x1078, 0x2500, 0x81ff, 0x00c0, 0x2b56, 0x1078,
- 0x421a, 0x1078, 0x4171, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56,
- 0x6180, 0x81ff, 0x0040, 0x3107, 0x703f, 0x0000, 0x2001, 0xa9c0,
- 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x127e, 0x2091,
- 0x8000, 0x1078, 0x3566, 0x701b, 0x2b29, 0x127f, 0x007c, 0x703f,
- 0x0001, 0x0d7e, 0x2069, 0xa9c0, 0x20a9, 0x0040, 0x20a1, 0xa9c0,
- 0x2019, 0xffff, 0x43a4, 0x654c, 0xa588, 0x293f, 0x210c, 0xa18c,
- 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, 0xa506, 0x0040,
- 0x3139, 0x1078, 0x4501, 0x00c0, 0x3139, 0x6014, 0x821c, 0x0048,
- 0x3131, 0xa398, 0xa9c0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0078,
- 0x3138, 0xa398, 0xa9c0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a,
- 0x8210, 0x8108, 0xa182, 0x0080, 0x00c8, 0x3140, 0x0078, 0x311d,
- 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x0d7f, 0x20a9, 0x0040,
- 0x20a1, 0xa9c0, 0x2099, 0xa9c0, 0x1078, 0x41be, 0x0078, 0x30f6,
- 0x1078, 0x3542, 0x0040, 0x2b5a, 0x0c7e, 0x1078, 0x3518, 0x0c7f,
- 0x00c0, 0x315e, 0x2009, 0x0002, 0x0078, 0x2b56, 0x2001, 0xa352,
- 0x2004, 0xd0b4, 0x0040, 0x3185, 0x6000, 0xd08c, 0x00c0, 0x3185,
- 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x3185, 0x6837,
- 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x8bd9, 0x00c0, 0x317c,
- 0x2009, 0x0003, 0x0078, 0x2b56, 0x7007, 0x0003, 0x701b, 0x3181,
- 0x007c, 0x1078, 0x3542, 0x0040, 0x2b5a, 0x20a9, 0x002b, 0x2c98,
- 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006,
- 0x2098, 0xad80, 0x0006, 0x20a0, 0x1078, 0x41be, 0x20a9, 0x0004,
- 0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, 0x1078, 0x41be,
- 0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078,
- 0x3566, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, 0x0040, 0x2b5a,
- 0x1078, 0x46ef, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x7828,
- 0xa08a, 0x1000, 0x00c8, 0x2b5a, 0x1078, 0x3542, 0x0040, 0x2b5a,
- 0x1078, 0x475f, 0x0040, 0x2b56, 0x2019, 0x0004, 0x1078, 0x4705,
- 0x7924, 0x810f, 0x7a28, 0x1078, 0x31cf, 0x0078, 0x2b2c, 0xa186,
- 0x00ff, 0x0040, 0x31d7, 0x1078, 0x31e7, 0x0078, 0x31e6, 0x2029,
- 0x007e, 0x2061, 0xa300, 0x644c, 0x2400, 0xa506, 0x0040, 0x31e3,
- 0x2508, 0x1078, 0x31e7, 0x8529, 0x00c8, 0x31dc, 0x007c, 0x1078,
- 0x4501, 0x00c0, 0x31f2, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108,
- 0x1078, 0x58e1, 0x007c, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530,
- 0x0040, 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, 0x46fa,
- 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, 0x0040,
- 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, 0x46e4, 0x0078,
- 0x2b2c, 0x6100, 0x0078, 0x2b2c, 0x1078, 0x3542, 0x0040, 0x2b5a,
- 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, 0x0d7e,
- 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x3228, 0xace8, 0x0006,
- 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f,
- 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200, 0x0078, 0x2b2c,
- 0xa006, 0x1078, 0x2500, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff,
- 0x0040, 0x3245, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x421a, 0x7828,
- 0xa08a, 0x1000, 0x00c8, 0x2b5a, 0x7924, 0xa18c, 0xff00, 0x810f,
- 0xa186, 0x00ff, 0x0040, 0x325b, 0xa182, 0x007f, 0x00c8, 0x2b5a,
- 0x2100, 0x1078, 0x24fa, 0x027e, 0x0c7e, 0x127e, 0x2091, 0x8000,
- 0x2061, 0xa5be, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0x0100,
- 0x6030, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, 0x0090,
- 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4196, 0x1078, 0x596c,
- 0x7924, 0xa18c, 0xff00, 0x810f, 0x7a28, 0x1078, 0x31cf, 0x127f,
- 0x0c7f, 0x027f, 0x0078, 0x2b2c, 0x7924, 0xa18c, 0xff00, 0x810f,
- 0x0c7e, 0x1078, 0x4499, 0x2c08, 0x0c7f, 0x00c0, 0x2b5a, 0x0078,
- 0x2b2c, 0x81ff, 0x0040, 0x3298, 0x2009, 0x0001, 0x0078, 0x2b56,
- 0x60c8, 0xd09c, 0x00c0, 0x32a0, 0x2009, 0x0005, 0x0078, 0x2b56,
- 0x1078, 0x3518, 0x00c0, 0x32a8, 0x2009, 0x0002, 0x0078, 0x2b56,
- 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3562, 0x701b,
- 0x32b2, 0x007c, 0x2009, 0x0080, 0x1078, 0x4501, 0x00c0, 0x32bf,
- 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, 0x32c3, 0x2021,
- 0x400a, 0x0078, 0x2b2e, 0x0d7e, 0xade8, 0x000d, 0x6900, 0x6a08,
- 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0040,
- 0x3336, 0xa0be, 0x0112, 0x0040, 0x3336, 0xa0be, 0x0113, 0x0040,
- 0x3336, 0xa0be, 0x0114, 0x0040, 0x3336, 0xa0be, 0x0117, 0x0040,
- 0x3336, 0xa0be, 0x011a, 0x0040, 0x3336, 0xa0be, 0x0121, 0x0040,
- 0x332c, 0xa0be, 0x0131, 0x0040, 0x332c, 0xa0be, 0x0171, 0x0040,
- 0x3336, 0xa0be, 0x0173, 0x0040, 0x3336, 0xa0be, 0x01a1, 0x00c0,
- 0x32fe, 0x6830, 0x8007, 0x6832, 0x0078, 0x333c, 0xa0be, 0x0212,
- 0x0040, 0x3332, 0xa0be, 0x0213, 0x0040, 0x3332, 0xa0be, 0x0214,
- 0x0040, 0x3324, 0xa0be, 0x0217, 0x0040, 0x331e, 0xa0be, 0x021a,
- 0x00c0, 0x3317, 0x6838, 0x8007, 0x683a, 0x0078, 0x3336, 0xa0be,
- 0x0300, 0x0040, 0x3336, 0x0d7f, 0x0078, 0x2b5a, 0xad80, 0x0010,
- 0x20a9, 0x0007, 0x1078, 0x337e, 0xad80, 0x000e, 0x20a9, 0x0001,
- 0x1078, 0x337e, 0x0078, 0x3336, 0xad80, 0x000c, 0x1078, 0x338c,
- 0x0078, 0x333c, 0xad80, 0x000e, 0x1078, 0x338c, 0xad80, 0x000c,
- 0x20a9, 0x0001, 0x1078, 0x337e, 0x0c7e, 0x1078, 0x3518, 0x0040,
- 0x336f, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853, 0x0000,
- 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, 0x0000,
- 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, 0x0c7f,
- 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000,
- 0x6804, 0x2068, 0x1078, 0x8ba1, 0x00c0, 0x336a, 0x2009, 0x0003,
- 0x0078, 0x2b56, 0x7007, 0x0003, 0x701b, 0x3375, 0x007c, 0x0c7f,
- 0x0d7f, 0x2009, 0x0002, 0x0078, 0x2b56, 0x6820, 0xa086, 0x8001,
- 0x00c0, 0x2b2c, 0x2009, 0x0004, 0x0078, 0x2b56, 0x017e, 0x2008,
- 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108,
- 0x00f0, 0x3380, 0x017f, 0x007c, 0x017e, 0x0a7e, 0x0b7e, 0x2008,
- 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a,
- 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x0b7f, 0x0a7f,
- 0x017f, 0x007c, 0x81ff, 0x0040, 0x33a9, 0x2009, 0x0001, 0x0078,
- 0x2b56, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080,
- 0x0048, 0x2b5a, 0xa182, 0x00ff, 0x00c8, 0x2b5a, 0x7a2c, 0x7b28,
- 0x6068, 0xa306, 0x00c0, 0x33c4, 0x606c, 0xa24e, 0x0040, 0x2b5a,
- 0xa9cc, 0xff00, 0x0040, 0x2b5a, 0x0c7e, 0x1078, 0x346d, 0x2c68,
- 0x0c7f, 0x0040, 0x33fc, 0xa0c6, 0x4000, 0x00c0, 0x33e2, 0x0c7e,
- 0x007e, 0x2d60, 0x2009, 0x0000, 0x1078, 0x47cb, 0x00c0, 0x33d9,
- 0xc185, 0x6000, 0xd0bc, 0x0040, 0x33de, 0xc18d, 0x007f, 0x0c7f,
- 0x0078, 0x33f9, 0xa0c6, 0x4007, 0x00c0, 0x33e9, 0x2408, 0x0078,
- 0x33f9, 0xa0c6, 0x4008, 0x00c0, 0x33f1, 0x2708, 0x2610, 0x0078,
- 0x33f9, 0xa0c6, 0x4009, 0x00c0, 0x33f7, 0x0078, 0x33f9, 0x2001,
- 0x4006, 0x2020, 0x0078, 0x2b2e, 0x2d00, 0x7022, 0x017e, 0x0b7e,
- 0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x74d7, 0x0040, 0x3442, 0x2d00,
- 0x601a, 0x2001, 0xa356, 0x2004, 0xa084, 0x00ff, 0x6842, 0x2e58,
- 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x3518, 0x0c7f, 0x2b70, 0x00c0,
- 0x3423, 0x1078, 0x753d, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x2009,
- 0x0002, 0x0078, 0x2b56, 0x6837, 0x0000, 0x2d00, 0x6012, 0x6833,
- 0x0000, 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078,
- 0x2813, 0x127f, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x442b,
- 0x2001, 0x0002, 0x1078, 0x443f, 0x2009, 0x0002, 0x1078, 0x756c,
- 0xa085, 0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x00c0, 0x344c,
- 0x2009, 0x0003, 0x0078, 0x2b56, 0x7007, 0x0003, 0x701b, 0x3451,
- 0x007c, 0x6830, 0xa086, 0x0100, 0x7020, 0x2060, 0x00c0, 0x345f,
- 0x2009, 0x0004, 0x6204, 0xa294, 0x00ff, 0x0078, 0x2b56, 0x2009,
- 0x0000, 0x1078, 0x47cb, 0x00c0, 0x3466, 0xc185, 0x6000, 0xd0bc,
- 0x0040, 0x346b, 0xc18d, 0x0078, 0x2b2c, 0x0e7e, 0x0d7e, 0x2029,
- 0x0000, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xa4b4, 0x2e04,
- 0xa005, 0x00c0, 0x3482, 0x2100, 0xa406, 0x00c0, 0x34b3, 0x2428,
- 0x0078, 0x34b3, 0x2068, 0x6f10, 0x2700, 0xa306, 0x00c0, 0x34a4,
- 0x6e14, 0x2600, 0xa206, 0x00c0, 0x34a4, 0x2400, 0xa106, 0x00c0,
- 0x34a0, 0x2d60, 0xd884, 0x0040, 0x34c8, 0x6004, 0xa084, 0x00ff,
- 0xa086, 0x0006, 0x00c0, 0x34c8, 0x2001, 0x4000, 0x0078, 0x34c9,
- 0x2001, 0x4007, 0x0078, 0x34c9, 0x2400, 0xa106, 0x00c0, 0x34b3,
- 0x6e14, 0x87ff, 0x00c0, 0x34af, 0x86ff, 0x0040, 0x347f, 0x2001,
- 0x4008, 0x0078, 0x34c9, 0x8420, 0x8e70, 0x00f0, 0x3477, 0x85ff,
- 0x00c0, 0x34c2, 0x2001, 0x4009, 0x0078, 0x34c9, 0x2001, 0x0001,
- 0x0078, 0x34c9, 0x1078, 0x4499, 0x00c0, 0x34be, 0x6312, 0x6216,
- 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff, 0x00c0, 0x2b56,
- 0x1078, 0x3518, 0x0040, 0x2b56, 0x6837, 0x0000, 0x6838, 0xc0fd,
- 0x683a, 0x7824, 0xa005, 0x0040, 0x2b5a, 0xa096, 0x00ff, 0x0040,
- 0x34e5, 0xa092, 0x0004, 0x00c8, 0x2b5a, 0x2010, 0x2d18, 0x1078,
- 0x27c2, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, 0x34f0, 0x007c,
- 0x6830, 0xa086, 0x0100, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0x7924,
- 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, 0x2b5a, 0xa182,
- 0x00ff, 0x00c8, 0x2b5a, 0x127e, 0x2091, 0x8000, 0x1078, 0x8a89,
- 0x00c0, 0x3515, 0xa190, 0xa434, 0x2204, 0xa065, 0x0040, 0x3515,
- 0x1078, 0x4235, 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, 0x2b56,
- 0x1078, 0x1381, 0x0040, 0x352f, 0xa006, 0x6802, 0x7010, 0xa005,
- 0x00c0, 0x3527, 0x2d00, 0x7012, 0x7016, 0x0078, 0x352d, 0x7014,
- 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, 0x007c,
- 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x4501, 0x00c0, 0x353f,
- 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, 0x3540, 0xa066,
- 0x8cff, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x1078, 0x4501,
- 0x00c0, 0x3550, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0048, 0x3551,
- 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, 0x0040, 0x355e,
- 0x2168, 0x6904, 0x1078, 0x139a, 0x0078, 0x3555, 0x7112, 0x7116,
- 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x3568, 0x2031, 0x0000,
- 0x2061, 0xa3d1, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, 0x642e,
- 0x6532, 0x2c10, 0x1078, 0x13d1, 0x7007, 0x0002, 0x701b, 0x2b2c,
- 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001,
- 0xa38f, 0x2004, 0xa005, 0x00c0, 0x3594, 0x0068, 0x3594, 0x7818,
- 0xd084, 0x00c0, 0x3594, 0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001,
- 0x2091, 0x4080, 0x0078, 0x35b9, 0x017e, 0x0c7e, 0x0e7e, 0x2071,
- 0xa381, 0x7138, 0xa182, 0x0008, 0x0048, 0x35a2, 0x7030, 0x2060,
- 0x0078, 0x35b3, 0x7030, 0xa0e0, 0x0008, 0xac82, 0xa3d1, 0x0048,
- 0x35ab, 0x2061, 0xa391, 0x2c00, 0x7032, 0x81ff, 0x00c0, 0x35b1,
- 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x0e7f, 0x0c7f,
- 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, 0xa381, 0x7038,
- 0xa005, 0x0040, 0x35f5, 0x127e, 0x2091, 0x8000, 0x0068, 0x35f4,
- 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x35f3, 0x0c7e,
- 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, 0x6008, 0x782a,
- 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a, 0xa005,
- 0x00c0, 0x35e9, 0x7033, 0xa391, 0x7037, 0xa391, 0x0c7f, 0x0078,
- 0x35f3, 0xac80, 0x0008, 0xa0fa, 0xa3d1, 0x0048, 0x35f1, 0x2001,
- 0xa391, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, 0x007c, 0x027e,
- 0x2001, 0xa352, 0x2004, 0xd0c4, 0x0040, 0x3602, 0x2011, 0x8014,
- 0x1078, 0x3579, 0x027f, 0x007c, 0x81ff, 0x00c0, 0x2b56, 0x127e,
- 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x1078,
- 0x4171, 0x127f, 0x0078, 0x2b2c, 0x7824, 0x2008, 0xa18c, 0xfffd,
- 0x00c0, 0x361f, 0x61d4, 0xa10d, 0x61d6, 0x0078, 0x2b2c, 0x0078,
- 0x2b5a, 0x81ff, 0x00c0, 0x2b56, 0x6000, 0xa086, 0x0003, 0x00c0,
- 0x2b56, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x2b56, 0x1078,
- 0x3542, 0x0040, 0x2b5a, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
- 0x00c0, 0x363e, 0x7828, 0xa005, 0x0040, 0x2b2c, 0x0c7e, 0x1078,
- 0x3518, 0x0c7f, 0x0040, 0x2b56, 0x6837, 0x0000, 0x6833, 0x0000,
- 0x6838, 0xc0fd, 0x683a, 0x1078, 0x8c4d, 0x0040, 0x2b56, 0x7007,
- 0x0003, 0x701b, 0x3654, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040,
- 0x2b56, 0x0078, 0x2b2c, 0x2001, 0xa300, 0x2004, 0xa086, 0x0003,
- 0x00c0, 0x2b56, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078,
- 0x3518, 0x0040, 0x2b56, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023,
- 0x0000, 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078,
- 0x4501, 0x00c0, 0x36d8, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006,
- 0x0040, 0x3688, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x00c0, 0x36d8,
- 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x3695, 0x1078, 0x47cb,
- 0x00c0, 0x3695, 0xd79c, 0x0040, 0x36d8, 0xd794, 0x00c0, 0x369b,
- 0xd784, 0x0040, 0x36a7, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9,
- 0x0004, 0x53a3, 0x1078, 0x338c, 0xd794, 0x0040, 0x36b0, 0xac80,
- 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078, 0x338c,
- 0x21a2, 0xd794, 0x0040, 0x36d0, 0xac80, 0x0000, 0x2098, 0x94a0,
- 0x20a9, 0x0002, 0x53a3, 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80,
- 0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, 0x53a3, 0x1078, 0x337e,
- 0xac80, 0x0026, 0x2098, 0x20a9, 0x0002, 0x53a3, 0x0078, 0x36d1,
- 0x94a0, 0xd794, 0x0040, 0x36d6, 0xa6b0, 0x000b, 0xa6b0, 0x0005,
- 0x8108, 0xd78c, 0x0040, 0x36e2, 0xa186, 0x0100, 0x0040, 0x36f3,
- 0x0078, 0x36e6, 0xa186, 0x007e, 0x0040, 0x36f3, 0xd794, 0x0040,
- 0x36ed, 0xa686, 0x0020, 0x0078, 0x36ef, 0xa686, 0x0028, 0x0040,
- 0x36fc, 0x0078, 0x3677, 0x86ff, 0x00c0, 0x36fa, 0x7120, 0x810b,
- 0x0078, 0x2b2c, 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, 0x7022,
- 0x772a, 0x2061, 0xa3d1, 0x6007, 0x0000, 0x6612, 0x7024, 0x600e,
- 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13d1, 0x7007,
- 0x0002, 0x701b, 0x3714, 0x007c, 0x702c, 0xa005, 0x00c0, 0x3726,
- 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, 0xa3d1,
- 0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x3677, 0x7120, 0x810b,
- 0x0078, 0x2b2c, 0x2029, 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38,
- 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2b5a, 0xa502,
- 0x0048, 0x2b5a, 0xa184, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2b5a,
- 0xa502, 0x0048, 0x2b5a, 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020,
- 0x0048, 0x2b5a, 0xa502, 0x0048, 0x2b5a, 0xa284, 0x00ff, 0xa0e2,
- 0x0020, 0x0048, 0x2b5a, 0xa502, 0x0048, 0x2b5a, 0xa384, 0xff00,
- 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2b5a, 0xa502, 0x0048, 0x2b5a,
- 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2b5a, 0xa502, 0x0048,
- 0x2b5a, 0xa484, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2b5a,
- 0xa502, 0x0048, 0x2b5a, 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0048,
- 0x2b5a, 0xa502, 0x0048, 0x2b5a, 0x2061, 0xa5a3, 0x6102, 0x6206,
- 0x630a, 0x640e, 0x0078, 0x2b2c, 0x007e, 0x2001, 0xa352, 0x2004,
- 0xd0cc, 0x007f, 0x007c, 0x007e, 0x2001, 0xa371, 0x2004, 0xd0bc,
- 0x007f, 0x007c, 0x6160, 0x7a24, 0x6300, 0x82ff, 0x00c0, 0x379b,
- 0x7926, 0x0078, 0x2b2c, 0x83ff, 0x00c0, 0x2b5a, 0x2001, 0xfff0,
- 0xa200, 0x00c8, 0x2b5a, 0x2019, 0xffff, 0x6064, 0xa302, 0xa200,
- 0x0048, 0x2b5a, 0x7926, 0x6262, 0x0078, 0x2b2c, 0x2001, 0xa300,
- 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, 0x7c28, 0x7d24, 0x7e38,
- 0x7f2c, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009, 0x0000, 0x2019,
- 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, 0x0003, 0x7026,
- 0x20a0, 0xa1e0, 0xa434, 0x2c64, 0x8cff, 0x0040, 0x37e8, 0x6004,
- 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, 0x37dd, 0x6004, 0xa084,
- 0xff00, 0xa086, 0x0600, 0x00c0, 0x37e8, 0x6014, 0x20a2, 0x94a0,
- 0x6010, 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002,
- 0x8108, 0xa182, 0x00ff, 0x0040, 0x37f3, 0xa386, 0x002a, 0x0040,
- 0x37fc, 0x0078, 0x37c9, 0x83ff, 0x00c0, 0x37fa, 0x7120, 0x810c,
- 0x0078, 0x2b2c, 0x702f, 0x0001, 0x711e, 0x7020, 0xa300, 0x7022,
- 0x2061, 0xa3d1, 0x6007, 0x0000, 0x6312, 0x7024, 0x600e, 0x6426,
- 0x652a, 0x662e, 0x6732, 0x2c10, 0x1078, 0x13d1, 0x7007, 0x0002,
- 0x701b, 0x3813, 0x007c, 0x702c, 0xa005, 0x00c0, 0x3824, 0x711c,
- 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xa3d1, 0x6424, 0x6528,
- 0x662c, 0x6730, 0x0078, 0x37c9, 0x7120, 0x810c, 0x0078, 0x2b2c,
- 0x81ff, 0x00c0, 0x2b56, 0x60c8, 0xd09c, 0x0040, 0x2b56, 0x1078,
- 0x3518, 0x0040, 0x2b56, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
- 0x1078, 0x3562, 0x701b, 0x383d, 0x007c, 0x0d7e, 0xade8, 0x000d,
- 0x6828, 0xa0be, 0x7000, 0x0040, 0x3850, 0xa0be, 0x7100, 0x0040,
- 0x3850, 0xa0be, 0x7200, 0x0040, 0x3850, 0x0d7f, 0x0078, 0x2b5a,
- 0x6820, 0x6924, 0x1078, 0x24e3, 0x00c0, 0x387b, 0x1078, 0x4499,
- 0x00c0, 0x387b, 0x7122, 0x6612, 0x6516, 0x6e18, 0x0c7e, 0x1078,
- 0x3518, 0x0040, 0x387b, 0x1078, 0x3518, 0x0040, 0x387b, 0x0c7f,
- 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000,
- 0x6804, 0x2068, 0x1078, 0x8bbd, 0x0040, 0x2b56, 0x7007, 0x0003,
- 0x701b, 0x387e, 0x007c, 0x0d7f, 0x0078, 0x2b56, 0x7120, 0x1078,
- 0x2921, 0x6820, 0xa086, 0x8001, 0x0040, 0x2b56, 0x2d00, 0x701e,
- 0x6804, 0xa080, 0x0002, 0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0,
- 0x1078, 0x41be, 0x007f, 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10,
- 0x6d14, 0x2061, 0xa3d1, 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6,
- 0x7000, 0x00c0, 0x38a5, 0x0078, 0x38a9, 0xa7c6, 0x7100, 0x00c0,
- 0x38b1, 0xa6c2, 0x0004, 0x0048, 0x2b5a, 0x2009, 0x0004, 0x0078,
- 0x3566, 0xa7c6, 0x7200, 0x00c0, 0x2b5a, 0xa6c2, 0x0054, 0x0048,
- 0x2b5a, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, 0x642e, 0x6532,
- 0x2c10, 0x1078, 0x13d1, 0x7007, 0x0002, 0x701b, 0x38c8, 0x007c,
- 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002,
- 0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x1078, 0x41be, 0x007f,
- 0x2009, 0x002a, 0x2061, 0xa3d1, 0x6224, 0x6328, 0x642c, 0x6530,
- 0x0078, 0x3566, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, 0x0040,
- 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, 0x4710, 0x0078,
- 0x2b2c, 0x7824, 0xd084, 0x0040, 0x3150, 0x1078, 0x3542, 0x0040,
- 0x2b5a, 0x0c7e, 0x1078, 0x3518, 0x0c7f, 0x00c0, 0x3903, 0x2009,
- 0x0002, 0x0078, 0x2b56, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
- 0x0040, 0x3910, 0xa08e, 0x0004, 0x0040, 0x3910, 0xa08e, 0x0005,
- 0x00c0, 0x3934, 0x2001, 0xa352, 0x2004, 0xd0b4, 0x0040, 0x3185,
- 0x6000, 0xd08c, 0x00c0, 0x3185, 0x6837, 0x0000, 0x6838, 0xc0fd,
- 0x683a, 0x1078, 0x8bd9, 0x00c0, 0x3929, 0x2009, 0x0003, 0x0078,
- 0x2b56, 0x7007, 0x0003, 0x701b, 0x392e, 0x007c, 0x1078, 0x3542,
- 0x0040, 0x2b5a, 0x0078, 0x3185, 0x2009, 0xa32e, 0x210c, 0x81ff,
- 0x0040, 0x393e, 0x2009, 0x0001, 0x0078, 0x2b56, 0x2001, 0xa300,
- 0x2004, 0xa086, 0x0003, 0x0040, 0x3949, 0x2009, 0x0007, 0x0078,
- 0x2b56, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x0040, 0x3953, 0x2009,
- 0x0008, 0x0078, 0x2b56, 0x609c, 0xd0a4, 0x00c0, 0x395a, 0xd0ac,
- 0x00c0, 0x3185, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd,
- 0x683a, 0x1078, 0x8c4d, 0x00c0, 0x3969, 0x2009, 0x0003, 0x0078,
- 0x2b56, 0x7007, 0x0003, 0x701b, 0x396e, 0x007c, 0x6830, 0xa086,
- 0x0100, 0x00c0, 0x3977, 0x2009, 0x0004, 0x0078, 0x2b56, 0x1078,
- 0x3542, 0x0040, 0x2b5a, 0x0078, 0x3912, 0x81ff, 0x2009, 0x0001,
- 0x00c0, 0x2b56, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x00c0,
- 0x2b56, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x00c0,
- 0x2b56, 0x1078, 0x3542, 0x0040, 0x2b5a, 0x6004, 0xa084, 0x00ff,
- 0xa086, 0x0006, 0x2009, 0x0009, 0x00c0, 0x2b56, 0x0c7e, 0x1078,
- 0x3518, 0x0c7f, 0x2009, 0x0002, 0x0040, 0x2b56, 0x6837, 0x0000,
- 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00,
- 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x00c0, 0x39bc, 0xc0ed, 0x6952,
- 0x792c, 0x6956, 0x0078, 0x39c5, 0xa28e, 0x0100, 0x00c0, 0x2b5a,
- 0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, 0x683e, 0x1078, 0x8df6,
- 0x2009, 0x0003, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, 0x39d1,
- 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040, 0x2b56,
- 0x0078, 0x2b2c, 0x81ff, 0x2009, 0x0001, 0x00c0, 0x2b56, 0x6000,
- 0xa086, 0x0003, 0x2009, 0x0007, 0x00c0, 0x2b56, 0x1078, 0x3542,
- 0x0040, 0x2b5a, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009,
- 0x0009, 0x00c0, 0x2b56, 0x0c7e, 0x1078, 0x3518, 0x0c7f, 0x2009,
- 0x0002, 0x0040, 0x2b56, 0xad80, 0x000f, 0x2009, 0x0008, 0x7a2c,
- 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3562, 0x701b, 0x3a08, 0x007c,
- 0x0d7e, 0xade8, 0x000f, 0x6800, 0xa086, 0x0500, 0x00c0, 0x3a1b,
- 0x6804, 0xa005, 0x00c0, 0x3a1b, 0x6808, 0xa084, 0xff00, 0x00c0,
- 0x3a1b, 0x0078, 0x3a1e, 0x0d7f, 0x00c0, 0x2b5a, 0x0d7f, 0x6837,
- 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x0c7e, 0x1078,
- 0x3542, 0x00c0, 0x3a2e, 0x0c7f, 0x0078, 0x2b5a, 0x1078, 0x8e52,
- 0x2009, 0x0003, 0x0c7f, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b,
- 0x3a3a, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040,
- 0x2b56, 0x0078, 0x2b2c, 0x127e, 0x0c7e, 0x0e7e, 0x2061, 0x0100,
- 0x2071, 0xa300, 0x6044, 0xd0a4, 0x00c0, 0x3a6c, 0xd084, 0x0040,
- 0x3a55, 0x1078, 0x3bcc, 0x0078, 0x3a68, 0xd08c, 0x0040, 0x3a5c,
- 0x1078, 0x3ae3, 0x0078, 0x3a68, 0xd094, 0x0040, 0x3a63, 0x1078,
- 0x3ab7, 0x0078, 0x3a68, 0xd09c, 0x0040, 0x3a68, 0x1078, 0x3a76,
- 0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, 0x00c0,
- 0x3a73, 0xc19d, 0x612a, 0x017f, 0x0078, 0x3a68, 0x624c, 0xa286,
- 0xf0f0, 0x00c0, 0x3a87, 0x6048, 0xa086, 0xf0f0, 0x0040, 0x3a87,
- 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x3ab6, 0xa294,
- 0xff00, 0xa296, 0xf700, 0x0040, 0x3a9c, 0x7134, 0xd1a4, 0x00c0,
- 0x3a9c, 0x6240, 0xa294, 0x0010, 0x0040, 0x3a9c, 0x2009, 0x00f7,
- 0x1078, 0x41de, 0x0078, 0x3ab6, 0x6043, 0x0040, 0x6043, 0x0000,
- 0x7073, 0x0000, 0x708b, 0x0001, 0x70af, 0x0000, 0x70cb, 0x0000,
- 0x2009, 0xa9c0, 0x200b, 0x0000, 0x7083, 0x0000, 0x7077, 0x000f,
- 0x2009, 0x000f, 0x2011, 0x4122, 0x1078, 0x596c, 0x007c, 0x157e,
- 0x7074, 0xa005, 0x00c0, 0x3ae1, 0x2011, 0x4122, 0x1078, 0x58d4,
- 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8,
- 0x6044, 0xd08c, 0x00c0, 0x3ada, 0x00f0, 0x3ac8, 0x6242, 0x7087,
- 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242,
- 0x0078, 0x3ae1, 0x6242, 0x7087, 0x0000, 0x707b, 0x0000, 0x0078,
- 0x3ae1, 0x157f, 0x007c, 0x7078, 0xa08a, 0x0003, 0x00c8, 0x3aec,
- 0x1079, 0x3aef, 0x0078, 0x3aee, 0x1078, 0x1328, 0x007c, 0x3af2,
- 0x3b41, 0x3bcb, 0x0f7e, 0x707b, 0x0001, 0x20e1, 0xa000, 0x20e1,
- 0x8700, 0x1078, 0x218b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079,
- 0xa800, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, 0x780f,
- 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, 0x781f,
- 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, 0x782f,
- 0x0000, 0x2079, 0xa80c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099,
- 0xa305, 0x20a1, 0xa80e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0xa812,
- 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0xa800, 0x20a1, 0x020b,
- 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x1078,
- 0x4158, 0x0f7f, 0x707f, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000,
- 0x007c, 0x0d7e, 0x707c, 0x707f, 0x0000, 0xa025, 0x0040, 0x3bb5,
- 0x6020, 0xd0b4, 0x00c0, 0x3bb3, 0x7188, 0x81ff, 0x0040, 0x3ba2,
- 0xa486, 0x000c, 0x00c0, 0x3bad, 0xa480, 0x0018, 0x8004, 0x20a8,
- 0x2011, 0xa880, 0x2019, 0xa800, 0x220c, 0x2304, 0xa106, 0x00c0,
- 0x3b79, 0x8210, 0x8318, 0x00f0, 0x3b5c, 0x6043, 0x0004, 0x608b,
- 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707b, 0x0002, 0x7087,
- 0x0002, 0x2009, 0x07d0, 0x2011, 0x4129, 0x1078, 0x596c, 0x0078,
- 0x3bb3, 0x2069, 0xa880, 0x6930, 0xa18e, 0x1101, 0x00c0, 0x3bad,
- 0x6834, 0xa005, 0x00c0, 0x3bad, 0x6900, 0xa18c, 0x00ff, 0x00c0,
- 0x3b8d, 0x6804, 0xa005, 0x0040, 0x3ba2, 0x2011, 0xa88e, 0x2019,
- 0xa305, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0048, 0x3ba0,
- 0x00c0, 0x3bad, 0x8210, 0x8318, 0x00f0, 0x3b93, 0x0078, 0x3bad,
- 0x708b, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880,
- 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, 0x6043,
- 0x0000, 0x0078, 0x3bb5, 0x0d7f, 0x007c, 0x6020, 0xd0b4, 0x00c0,
- 0x3bb3, 0x60c3, 0x000c, 0x2011, 0xa5b5, 0x2013, 0x0000, 0x707f,
- 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078,
- 0x6c38, 0x0078, 0x3bb3, 0x007c, 0x7084, 0xa08a, 0x001d, 0x00c8,
- 0x3bd5, 0x1079, 0x3bd8, 0x0078, 0x3bd7, 0x1078, 0x1328, 0x007c,
- 0x3c02, 0x3c11, 0x3c40, 0x3c59, 0x3c85, 0x3cb1, 0x3cdd, 0x3d13,
- 0x3d3f, 0x3d67, 0x3daa, 0x3dd4, 0x3df6, 0x3e0c, 0x3e32, 0x3e45,
- 0x3e4e, 0x3e7e, 0x3eaa, 0x3ed6, 0x3f02, 0x3f38, 0x3f7d, 0x3fac,
- 0x3fce, 0x4010, 0x4036, 0x404f, 0x4050, 0x0c7e, 0x2061, 0xa300,
- 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, 0x6006,
- 0x0c7f, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002,
- 0x7087, 0x0001, 0x2009, 0x07d0, 0x2011, 0x4129, 0x1078, 0x596c,
- 0x007c, 0x0f7e, 0x707c, 0xa086, 0x0014, 0x00c0, 0x3c3e, 0x6043,
- 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3c3e, 0x2079, 0xa880, 0x7a30,
- 0xa296, 0x1102, 0x00c0, 0x3c3c, 0x7834, 0xa005, 0x00c0, 0x3c3c,
- 0x7a38, 0xd2fc, 0x0040, 0x3c32, 0x70ac, 0xa005, 0x00c0, 0x3c32,
- 0x70af, 0x0001, 0x2011, 0x4129, 0x1078, 0x58d4, 0x7087, 0x0010,
- 0x1078, 0x3e4e, 0x0078, 0x3c3e, 0x1078, 0x4171, 0x0f7f, 0x007c,
- 0x7087, 0x0003, 0x6043, 0x0004, 0x2011, 0x4129, 0x1078, 0x58d4,
- 0x1078, 0x41c6, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a,
- 0x20a3, 0x0000, 0x00f0, 0x3c50, 0x60c3, 0x0014, 0x1078, 0x4158,
- 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3c83, 0x2011, 0x4129,
- 0x1078, 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3c81, 0x2079, 0xa880,
- 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3c81, 0x7834, 0xa005, 0x00c0,
- 0x3c81, 0x7a38, 0xd2fc, 0x0040, 0x3c7b, 0x70ac, 0xa005, 0x00c0,
- 0x3c7b, 0x70af, 0x0001, 0x7087, 0x0004, 0x1078, 0x3c85, 0x0078,
- 0x3c83, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x0005, 0x1078,
- 0x41c6, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e,
- 0x1078, 0x4211, 0x00c0, 0x3ca3, 0x7070, 0xa005, 0x00c0, 0x3ca3,
- 0x714c, 0xa186, 0xffff, 0x0040, 0x3ca3, 0x1078, 0x40ea, 0x0040,
- 0x3ca3, 0x1078, 0x41f5, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158,
- 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3cdb, 0x2011, 0x4129,
- 0x1078, 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3cd9, 0x2079, 0xa880,
- 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3cd9, 0x7834, 0xa005, 0x00c0,
- 0x3cd9, 0x7a38, 0xd2fc, 0x0040, 0x3cd3, 0x70ac, 0xa005, 0x00c0,
- 0x3cd3, 0x70af, 0x0001, 0x7087, 0x0006, 0x1078, 0x3cdd, 0x0078,
- 0x3cdb, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x0007, 0x1078,
- 0x41c6, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e,
- 0x1078, 0x4211, 0x00c0, 0x3d05, 0x7070, 0xa005, 0x00c0, 0x3d05,
- 0x7150, 0xa186, 0xffff, 0x0040, 0x3d05, 0xa180, 0x293f, 0x200c,
- 0xa18c, 0xff00, 0x810f, 0x1078, 0x40ea, 0x0040, 0x3d05, 0x1078,
- 0x378b, 0x0040, 0x3d05, 0x1078, 0x2500, 0x20a9, 0x0008, 0x2298,
- 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
- 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3d3d,
- 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3d3b,
- 0x2079, 0xa880, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3d3b, 0x7834,
- 0xa005, 0x00c0, 0x3d3b, 0x7a38, 0xd2fc, 0x0040, 0x3d35, 0x70ac,
- 0xa005, 0x00c0, 0x3d35, 0x70af, 0x0001, 0x7087, 0x0008, 0x1078,
- 0x3d3f, 0x0078, 0x3d3d, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087,
- 0x0009, 0x1078, 0x41c6, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430,
- 0x1078, 0x4211, 0x00c0, 0x3d58, 0x7070, 0xa005, 0x00c0, 0x3d58,
- 0x1078, 0x4051, 0x00c0, 0x3d62, 0xa085, 0x0001, 0x1078, 0x2500,
- 0x20a9, 0x0008, 0x2099, 0xa88e, 0x26a0, 0x53a6, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e,
- 0x707c, 0xa005, 0x0040, 0x3da8, 0x2011, 0x4129, 0x1078, 0x58d4,
- 0xa086, 0x0014, 0x00c0, 0x3da6, 0x2079, 0xa880, 0x7a30, 0xa296,
- 0x1105, 0x00c0, 0x3da6, 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0,
- 0x3d91, 0x7a38, 0xd2fc, 0x0040, 0x3d8b, 0x70ac, 0xa005, 0x00c0,
- 0x3d8b, 0x70af, 0x0001, 0x7087, 0x000a, 0x1078, 0x3daa, 0x0078,
- 0x3da8, 0xa005, 0x00c0, 0x3da6, 0x7a38, 0xd2fc, 0x0040, 0x3d9e,
- 0x70ac, 0xa005, 0x00c0, 0x3d9e, 0x70af, 0x0001, 0x7083, 0x0000,
- 0x7087, 0x000e, 0x1078, 0x3e32, 0x0078, 0x3da8, 0x1078, 0x4171,
- 0x0f7f, 0x007c, 0x7087, 0x000b, 0x2011, 0xa80e, 0x22a0, 0x20a9,
- 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000,
- 0x41a4, 0x1078, 0x41c6, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x1078,
- 0x4211, 0x0040, 0x3dc7, 0x2013, 0x0000, 0x0078, 0x3dcb, 0x6030,
- 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3,
- 0x0084, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040,
- 0x3df4, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0084, 0x00c0,
- 0x3df2, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x3df2,
- 0x7834, 0xa005, 0x00c0, 0x3df2, 0x7087, 0x000c, 0x1078, 0x3df6,
- 0x0078, 0x3df4, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x000d,
- 0x1078, 0x41c6, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099, 0xa88e,
- 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
- 0x0084, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040,
- 0x3e30, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0084, 0x00c0,
- 0x3e2e, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x3e2e,
- 0x7834, 0xa005, 0x00c0, 0x3e2e, 0x7083, 0x0001, 0x1078, 0x41b8,
- 0x7087, 0x000e, 0x1078, 0x3e32, 0x0078, 0x3e30, 0x1078, 0x4171,
- 0x0f7f, 0x007c, 0x7087, 0x000f, 0x707f, 0x0000, 0x608b, 0xbc85,
- 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0,
- 0x2011, 0x4129, 0x1078, 0x58c7, 0x007c, 0x707c, 0xa005, 0x0040,
- 0x3e4d, 0x2011, 0x4129, 0x1078, 0x58d4, 0x007c, 0x7087, 0x0011,
- 0x1078, 0x4211, 0x00c0, 0x3e67, 0x7168, 0x81ff, 0x0040, 0x3e67,
- 0x2009, 0x0000, 0x706c, 0xa084, 0x00ff, 0x1078, 0x24e3, 0xa186,
- 0x0080, 0x0040, 0x3e67, 0x2011, 0xa88e, 0x1078, 0x40ea, 0x20e1,
- 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880, 0x20a1, 0x020b, 0x747c,
- 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8,
- 0x53a6, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c,
- 0xa005, 0x0040, 0x3ea8, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086,
- 0x0014, 0x00c0, 0x3ea6, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1103,
- 0x00c0, 0x3ea6, 0x7834, 0xa005, 0x00c0, 0x3ea6, 0x7a38, 0xd2fc,
- 0x0040, 0x3ea0, 0x70ac, 0xa005, 0x00c0, 0x3ea0, 0x70af, 0x0001,
- 0x7087, 0x0012, 0x1078, 0x3eaa, 0x0078, 0x3ea8, 0x1078, 0x4171,
- 0x0f7f, 0x007c, 0x7087, 0x0013, 0x1078, 0x41d2, 0x20a3, 0x1103,
- 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e, 0x1078, 0x4211, 0x00c0,
- 0x3ec8, 0x7070, 0xa005, 0x00c0, 0x3ec8, 0x714c, 0xa186, 0xffff,
- 0x0040, 0x3ec8, 0x1078, 0x40ea, 0x0040, 0x3ec8, 0x1078, 0x41f5,
- 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c,
- 0xa005, 0x0040, 0x3f00, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086,
- 0x0014, 0x00c0, 0x3efe, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1104,
- 0x00c0, 0x3efe, 0x7834, 0xa005, 0x00c0, 0x3efe, 0x7a38, 0xd2fc,
- 0x0040, 0x3ef8, 0x70ac, 0xa005, 0x00c0, 0x3ef8, 0x70af, 0x0001,
- 0x7087, 0x0014, 0x1078, 0x3f02, 0x0078, 0x3f00, 0x1078, 0x4171,
- 0x0f7f, 0x007c, 0x7087, 0x0015, 0x1078, 0x41d2, 0x20a3, 0x1104,
- 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e, 0x1078, 0x4211, 0x00c0,
- 0x3f2a, 0x7070, 0xa005, 0x00c0, 0x3f2a, 0x7150, 0xa186, 0xffff,
- 0x0040, 0x3f2a, 0xa180, 0x293f, 0x200c, 0xa18c, 0xff00, 0x810f,
- 0x1078, 0x40ea, 0x0040, 0x3f2a, 0x1078, 0x378b, 0x0040, 0x3f2a,
- 0x1078, 0x2500, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c,
- 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3f7b, 0x2011, 0x4129, 0x1078,
- 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3f79, 0x2079, 0xa880, 0x7a30,
- 0xa296, 0x1105, 0x00c0, 0x3f79, 0x7834, 0x2011, 0x0100, 0xa21e,
- 0x00c0, 0x3f5e, 0x7a38, 0xd2fc, 0x0040, 0x3f5c, 0x70ac, 0xa005,
- 0x00c0, 0x3f5c, 0x70af, 0x0001, 0x0078, 0x3f6d, 0xa005, 0x00c0,
- 0x3f79, 0x7a38, 0xd2fc, 0x0040, 0x3f6b, 0x70ac, 0xa005, 0x00c0,
- 0x3f6b, 0x70af, 0x0001, 0x7083, 0x0000, 0x7a38, 0xd2f4, 0x0040,
- 0x3f73, 0x70cb, 0x0008, 0x7087, 0x0016, 0x1078, 0x3f7d, 0x0078,
- 0x3f7b, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x20e1, 0x9080, 0x20e1,
- 0x4000, 0x2099, 0xa880, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6,
- 0x3430, 0x2011, 0xa88e, 0x7087, 0x0017, 0x1078, 0x4211, 0x00c0,
- 0x3f9d, 0x7070, 0xa005, 0x00c0, 0x3f9d, 0x1078, 0x4051, 0x00c0,
- 0x3fa7, 0xa085, 0x0001, 0x1078, 0x2500, 0x20a9, 0x0008, 0x2099,
- 0xa88e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
- 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040,
- 0x3fcc, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0084, 0x00c0,
- 0x3fca, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x3fca,
- 0x7834, 0xa005, 0x00c0, 0x3fca, 0x7087, 0x0018, 0x1078, 0x3fce,
- 0x0078, 0x3fcc, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x0019,
- 0x1078, 0x41d2, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099,
- 0xa88e, 0x2039, 0xa80e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x1078,
- 0x4211, 0x00c0, 0x4002, 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff,
- 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, 0x6030,
- 0x2310, 0x8214, 0xa2a0, 0xa80e, 0x2414, 0xa38c, 0x0001, 0x0040,
- 0x3ffd, 0xa294, 0xff00, 0x0078, 0x4000, 0xa294, 0x00ff, 0x8007,
- 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x1078, 0x4158, 0x007c,
- 0x0f7e, 0x707c, 0xa005, 0x0040, 0x4034, 0x2011, 0x4129, 0x1078,
- 0x58d4, 0xa086, 0x0084, 0x00c0, 0x4032, 0x2079, 0xa880, 0x7a30,
- 0xa296, 0x1107, 0x00c0, 0x4032, 0x7834, 0xa005, 0x00c0, 0x4032,
- 0x7083, 0x0001, 0x1078, 0x41b8, 0x7087, 0x001a, 0x1078, 0x4036,
- 0x0078, 0x4034, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x001b,
- 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880, 0x20a1, 0x020b,
- 0x747c, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004,
- 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078, 0x4158, 0x007c, 0x007c,
- 0x007c, 0x087e, 0x097e, 0x2029, 0xa352, 0x252c, 0x20a9, 0x0008,
- 0x2041, 0xa80e, 0x28a0, 0x2099, 0xa88e, 0x53a3, 0x20a9, 0x0008,
- 0x2011, 0x0007, 0xd5d4, 0x0040, 0x4067, 0x2011, 0x0000, 0x2800,
- 0xa200, 0x200c, 0xa1a6, 0xffff, 0x00c0, 0x4079, 0xd5d4, 0x0040,
- 0x4074, 0x8210, 0x0078, 0x4075, 0x8211, 0x00f0, 0x4067, 0x0078,
- 0x40e1, 0x82ff, 0x00c0, 0x408b, 0xd5d4, 0x0040, 0x4085, 0xa1a6,
- 0x3fff, 0x0040, 0x4071, 0x0078, 0x4089, 0xa1a6, 0x3fff, 0x0040,
- 0x40e1, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4,
- 0x0040, 0x4094, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0040, 0x409b,
- 0x8423, 0x0078, 0x409c, 0x8424, 0x00c8, 0x40a9, 0xd5d4, 0x0040,
- 0x40a4, 0x8319, 0x0078, 0x40a5, 0x8318, 0x00f0, 0x4095, 0x0078,
- 0x40e1, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x00f0, 0x40ad,
- 0x2328, 0x8529, 0xa2be, 0x0007, 0x0040, 0x40c1, 0x007e, 0x2039,
- 0x0007, 0x2200, 0xa73a, 0x007f, 0x27a8, 0xa5a8, 0x0010, 0x00f0,
- 0x40bd, 0x754e, 0xa5c8, 0x293f, 0x292c, 0xa5ac, 0x00ff, 0x6532,
- 0x60e7, 0x0000, 0x65ea, 0x706b, 0x0000, 0x756e, 0x2018, 0x2304,
- 0xa405, 0x201a, 0x7073, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008,
- 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, 0x0078,
- 0x40e7, 0xa006, 0x0078, 0x40e7, 0xa006, 0x1078, 0x1328, 0x097f,
- 0x087f, 0x007c, 0x2118, 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a,
- 0x0010, 0x0048, 0x40f7, 0x8420, 0x8001, 0x0078, 0x40ef, 0x2118,
- 0x84ff, 0x0040, 0x4100, 0xa39a, 0x0010, 0x8421, 0x00c0, 0x40fb,
- 0x2021, 0x0001, 0x83ff, 0x0040, 0x4109, 0x8423, 0x8319, 0x00c0,
- 0x4105, 0xa238, 0x2704, 0xa42c, 0x00c0, 0x4121, 0xa405, 0x203a,
- 0x714e, 0xa1a0, 0x293f, 0x242c, 0xa5ac, 0x00ff, 0x6532, 0x60e7,
- 0x0000, 0x65ea, 0x706b, 0x0000, 0x756e, 0x7073, 0x0001, 0xa084,
- 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa300, 0x7077, 0x0000, 0x0e7f,
- 0x007c, 0x0e7e, 0x0f7e, 0x2001, 0x0002, 0x1078, 0x5975, 0x2079,
- 0x0100, 0x2071, 0x0140, 0x1078, 0x6c41, 0x7004, 0xa084, 0x4000,
- 0x0040, 0x413e, 0x7003, 0x1000, 0x7003, 0x0000, 0x127e, 0x2091,
- 0x8000, 0x2071, 0xa321, 0x2073, 0x0000, 0x7840, 0x027e, 0x017e,
- 0x2009, 0x00f7, 0x1078, 0x41de, 0x017f, 0xa094, 0x0010, 0xa285,
- 0x0080, 0x7842, 0x7a42, 0x027f, 0x127f, 0x0f7f, 0x0e7f, 0x007c,
- 0x127e, 0x2091, 0x8000, 0x2011, 0xa5b5, 0x2013, 0x0000, 0x707f,
- 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575,
- 0x1078, 0x6c38, 0x2009, 0x07d0, 0x2011, 0x4129, 0x1078, 0x596c,
- 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x2009,
- 0x00f7, 0x1078, 0x41de, 0x2061, 0xa5be, 0x601b, 0x0000, 0x601f,
- 0x0000, 0x2061, 0xa300, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043,
- 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4196, 0x1078,
- 0x58c7, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c, 0x0e7e, 0x007e,
- 0x127e, 0x2091, 0x8000, 0x2001, 0x0001, 0x1078, 0x5975, 0x2071,
- 0x0100, 0x1078, 0x6c41, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000,
- 0x0040, 0x41ae, 0x7003, 0x1000, 0x7003, 0x0000, 0x2001, 0x0001,
- 0x1078, 0x2480, 0x1078, 0x4171, 0x127f, 0x007f, 0x0e7f, 0x007c,
- 0x20a9, 0x0040, 0x20a1, 0xa9c0, 0x2099, 0xa88e, 0x3304, 0x8007,
- 0x20a2, 0x9398, 0x94a0, 0x00f0, 0x41be, 0x007c, 0x20e1, 0x9080,
- 0x20e1, 0x4000, 0x2099, 0xa800, 0x20a1, 0x020b, 0x20a9, 0x000c,
- 0x53a6, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880,
- 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x0c7e, 0x007e,
- 0x2061, 0x0100, 0x810f, 0x2001, 0xa32e, 0x2004, 0xa005, 0x00c0,
- 0x41ef, 0x6030, 0xa084, 0x00ff, 0xa105, 0x0078, 0x41f1, 0xa185,
- 0x00f7, 0x604a, 0x007f, 0x0c7f, 0x007c, 0x017e, 0x047e, 0x2001,
- 0xa352, 0x2004, 0xd0a4, 0x0040, 0x4208, 0xa006, 0x2020, 0x2009,
- 0x002a, 0x1078, 0x9ec0, 0x2001, 0xa30c, 0x200c, 0xc195, 0x2102,
- 0x2019, 0x002a, 0x2009, 0x0000, 0x1078, 0x27e2, 0x047f, 0x017f,
- 0x007c, 0x007e, 0x2001, 0xa30c, 0x2004, 0xd09c, 0x0040, 0x4218,
- 0x007f, 0x007c, 0x007e, 0x017e, 0x127e, 0x2091, 0x8000, 0x2001,
- 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, 0x127f, 0x017f, 0x007f,
- 0x007c, 0x157e, 0x20a9, 0x00ff, 0x2009, 0xa434, 0xa006, 0x200a,
- 0x8108, 0x00f0, 0x422f, 0x157f, 0x007c, 0x0d7e, 0x037e, 0x157e,
- 0x137e, 0x147e, 0x2069, 0xa351, 0xa006, 0x6002, 0x6007, 0x0707,
- 0x600a, 0x600e, 0x6012, 0xa198, 0x293f, 0x231c, 0xa39c, 0x00ff,
- 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, 0x40a4, 0x20a9,
- 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, 0x6042, 0x604e,
- 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, 0x606e,
- 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, 0x608a, 0x608e,
- 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, 0x61a2, 0x0d7e, 0x60a4,
- 0xa06d, 0x0040, 0x4275, 0x1078, 0x139a, 0x60a7, 0x0000, 0x60a8,
- 0xa06d, 0x0040, 0x427d, 0x1078, 0x139a, 0x60ab, 0x0000, 0x0d7f,
- 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0x6814, 0xa084,
- 0x00ff, 0x6042, 0x147f, 0x137f, 0x157f, 0x037f, 0x0d7f, 0x007c,
- 0x127e, 0x2091, 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082,
- 0x4000, 0x00c8, 0x4361, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff,
- 0x00c8, 0x4367, 0x2001, 0xa30c, 0x2004, 0xa084, 0x0003, 0x0040,
- 0x42c2, 0x2001, 0xa30c, 0x2004, 0xd084, 0x00c0, 0x4342, 0xa188,
- 0xa434, 0x2104, 0xa065, 0x0040, 0x4342, 0x6004, 0xa084, 0x00ff,
- 0xa08e, 0x0006, 0x00c0, 0x4342, 0x6000, 0xd0c4, 0x0040, 0x4342,
- 0x0078, 0x42cf, 0xa188, 0xa434, 0x2104, 0xa065, 0x0040, 0x4326,
- 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x432c, 0x60a4,
- 0xa00d, 0x0040, 0x42d7, 0x1078, 0x4749, 0x0040, 0x4320, 0x60a8,
- 0xa00d, 0x0040, 0x42f1, 0x1078, 0x479a, 0x00c0, 0x42f1, 0x694c,
- 0xd1fc, 0x00c0, 0x42e7, 0x1078, 0x441c, 0x0078, 0x431b, 0x1078,
- 0x43d6, 0x694c, 0xd1ec, 0x00c0, 0x431b, 0x1078, 0x460a, 0x0078,
- 0x431b, 0x694c, 0xa184, 0xa000, 0x0040, 0x430b, 0xd1ec, 0x0040,
- 0x4304, 0xd1fc, 0x0040, 0x4300, 0x1078, 0x461b, 0x0078, 0x4307,
- 0x1078, 0x461b, 0x0078, 0x430b, 0xd1fc, 0x0040, 0x430b, 0x1078,
- 0x43d6, 0x0078, 0x431b, 0x6050, 0xa00d, 0x0040, 0x4316, 0x2d00,
- 0x200a, 0x6803, 0x0000, 0x6052, 0x0078, 0x431b, 0x2d00, 0x6052,
- 0x604e, 0x6803, 0x0000, 0x1078, 0x5c17, 0xa006, 0x127f, 0x007c,
- 0x2001, 0x0005, 0x2009, 0x0000, 0x0078, 0x436b, 0x2001, 0x0028,
- 0x2009, 0x0000, 0x0078, 0x436b, 0xa082, 0x0006, 0x00c8, 0x4342,
- 0x60a0, 0xd0bc, 0x00c0, 0x433e, 0x6100, 0xd1fc, 0x0040, 0x42cf,
- 0x2001, 0x0029, 0x2009, 0x1000, 0x0078, 0x436b, 0x2001, 0x0028,
- 0x0078, 0x435d, 0x2009, 0xa30c, 0x210c, 0xd18c, 0x0040, 0x434c,
- 0x2001, 0x0004, 0x0078, 0x435d, 0xd184, 0x0040, 0x4353, 0x2001,
- 0x0004, 0x0078, 0x435d, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0040,
- 0x435d, 0x2009, 0x1000, 0x0078, 0x436b, 0x2009, 0x0000, 0x0078,
- 0x436b, 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x436b, 0x2001,
- 0x0029, 0x2009, 0x0000, 0xa005, 0x127f, 0x007c, 0x6944, 0x6e48,
- 0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, 0x43bb, 0xa18c, 0xff00,
- 0x810f, 0xa182, 0x00ff, 0x00c8, 0x43a1, 0xa188, 0xa434, 0x2104,
- 0xa065, 0x0040, 0x43a1, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006,
- 0x00c0, 0x43a7, 0x684c, 0xd0ec, 0x0040, 0x4394, 0x1078, 0x461b,
- 0x1078, 0x43d6, 0x0078, 0x439c, 0x1078, 0x43d6, 0x684c, 0xd0fc,
- 0x0040, 0x439c, 0x1078, 0x460a, 0x1078, 0x4663, 0xa006, 0x0078,
- 0x43bf, 0x2001, 0x0028, 0x2009, 0x0000, 0x0078, 0x43bf, 0xa082,
- 0x0006, 0x00c8, 0x43b5, 0x6100, 0xd1fc, 0x0040, 0x438a, 0x2001,
- 0x0029, 0x2009, 0x1000, 0x0078, 0x43bf, 0x2001, 0x0029, 0x2009,
- 0x0000, 0x0078, 0x43bf, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005,
- 0x007c, 0x127e, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0040, 0x43cf,
- 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x127f, 0x007c, 0x2d00,
- 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x43cd, 0x127e, 0x2091,
- 0x8000, 0x604c, 0xa005, 0x0040, 0x43ec, 0x0e7e, 0x2071, 0xa5ab,
- 0x7004, 0xa086, 0x0002, 0x0040, 0x43f3, 0x0e7f, 0x604c, 0x6802,
- 0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803,
- 0x0000, 0x0078, 0x43ea, 0x701c, 0xac06, 0x00c0, 0x43e5, 0x604c,
- 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x0e7f, 0x127f, 0x007c,
- 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0040, 0x440e, 0x6800,
- 0xa005, 0x00c0, 0x440c, 0x6052, 0x604e, 0xad05, 0x127f, 0x007c,
- 0x604c, 0xa06d, 0x0040, 0x441b, 0x6800, 0xa005, 0x00c0, 0x4419,
- 0x6052, 0x604e, 0xad05, 0x007c, 0x6803, 0x0000, 0x6084, 0xa00d,
- 0x0040, 0x4426, 0x2d00, 0x200a, 0x6086, 0x007c, 0x2d00, 0x6086,
- 0x6082, 0x0078, 0x4425, 0x127e, 0x0c7e, 0x027e, 0x2091, 0x8000,
- 0x6218, 0x2260, 0x6200, 0xa005, 0x0040, 0x4439, 0xc285, 0x0078,
- 0x443a, 0xc284, 0x6202, 0x027f, 0x0c7f, 0x127f, 0x007c, 0x127e,
- 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x007e, 0xa086,
- 0x0006, 0x00c0, 0x445e, 0x609c, 0xd0ac, 0x0040, 0x445e, 0x2001,
- 0xa352, 0x2004, 0xd0a4, 0x0040, 0x445e, 0xa284, 0xff00, 0x8007,
- 0xa086, 0x0007, 0x00c0, 0x445e, 0x2011, 0x0600, 0x007f, 0xa294,
- 0xff00, 0xa215, 0x6206, 0x007e, 0xa086, 0x0006, 0x00c0, 0x446e,
- 0x6290, 0x82ff, 0x00c0, 0x446e, 0x1078, 0x1328, 0x007f, 0x0c7f,
- 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260,
- 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, 0x4490, 0x609c, 0xd0a4,
- 0x0040, 0x4490, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x4490,
- 0xa284, 0x00ff, 0xa086, 0x0007, 0x00c0, 0x4490, 0x2011, 0x0006,
- 0x007f, 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x0c7f, 0x127f,
- 0x007c, 0x027e, 0xa182, 0x00ff, 0x0048, 0x44a2, 0xa085, 0x0001,
- 0x0078, 0x44ba, 0xa190, 0xa434, 0x2204, 0xa065, 0x00c0, 0x44b9,
- 0x017e, 0x0d7e, 0x1078, 0x1366, 0x2d60, 0x0d7f, 0x017f, 0x0040,
- 0x449e, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab, 0x0000, 0x1078,
- 0x4235, 0xa006, 0x027f, 0x007c, 0x127e, 0x2091, 0x8000, 0x027e,
- 0xa182, 0x00ff, 0x0048, 0x44c8, 0xa085, 0x0001, 0x0078, 0x44fe,
- 0x0d7e, 0xa190, 0xa434, 0x2204, 0xa06d, 0x0040, 0x44fc, 0x2013,
- 0x0000, 0x0d7e, 0x0c7e, 0x2d60, 0x60a4, 0xa06d, 0x0040, 0x44da,
- 0x1078, 0x139a, 0x60a8, 0xa06d, 0x0040, 0x44e0, 0x1078, 0x139a,
- 0x0c7f, 0x0d7f, 0x0d7e, 0x0c7e, 0x68ac, 0x2060, 0x8cff, 0x0040,
- 0x44f8, 0x600c, 0x007e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040,
- 0x44f3, 0x1078, 0x13aa, 0x1078, 0x753d, 0x0c7f, 0x0078, 0x44e6,
- 0x0c7f, 0x0d7f, 0x1078, 0x139a, 0x0d7f, 0xa006, 0x027f, 0x127f,
- 0x007c, 0x017e, 0xa182, 0x00ff, 0x0048, 0x450a, 0xa085, 0x0001,
- 0x0078, 0x4511, 0xa188, 0xa434, 0x2104, 0xa065, 0x0040, 0x4506,
- 0xa006, 0x017f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x600b,
- 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x2069, 0xa88e,
- 0x6808, 0x605e, 0x6810, 0x6062, 0x6138, 0xa10a, 0x0048, 0x4529,
- 0x603a, 0x6814, 0x6066, 0x2099, 0xa896, 0xac88, 0x000a, 0x21a0,
- 0x20a9, 0x0004, 0x53a3, 0x2099, 0xa89a, 0xac88, 0x0006, 0x21a0,
- 0x20a9, 0x0004, 0x53a3, 0x2069, 0xa8ae, 0x6808, 0x606a, 0x690c,
- 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, 0xa182, 0x0211, 0x00c8,
- 0x454d, 0x2009, 0x0008, 0x0078, 0x4577, 0xa182, 0x0259, 0x00c8,
- 0x4555, 0x2009, 0x0007, 0x0078, 0x4577, 0xa182, 0x02c1, 0x00c8,
- 0x455d, 0x2009, 0x0006, 0x0078, 0x4577, 0xa182, 0x0349, 0x00c8,
- 0x4565, 0x2009, 0x0005, 0x0078, 0x4577, 0xa182, 0x0421, 0x00c8,
- 0x456d, 0x2009, 0x0004, 0x0078, 0x4577, 0xa182, 0x0581, 0x00c8,
- 0x4575, 0x2009, 0x0003, 0x0078, 0x4577, 0x2009, 0x0002, 0x6192,
- 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x017e, 0x027e, 0x0e7e,
- 0x2071, 0xa88d, 0x2e04, 0x6896, 0x2071, 0xa88e, 0x7004, 0x689a,
- 0x701c, 0x689e, 0x6a00, 0x2009, 0xa371, 0x210c, 0xd0bc, 0x0040,
- 0x4597, 0xd1ec, 0x0040, 0x4597, 0xc2ad, 0x0078, 0x4598, 0xc2ac,
- 0xd0c4, 0x0040, 0x45a1, 0xd1e4, 0x0040, 0x45a1, 0xc2bd, 0x0078,
- 0x45a2, 0xc2bc, 0x6a02, 0x0e7f, 0x027f, 0x017f, 0x007c, 0x0d7e,
- 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x0040, 0x45cb, 0x6900,
- 0x81ff, 0x00c0, 0x45df, 0x6a04, 0xa282, 0x0010, 0x00c8, 0x45e4,
- 0xad88, 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0040,
- 0x45c6, 0x8108, 0x00f0, 0x45bc, 0x1078, 0x1328, 0x260a, 0x8210,
- 0x6a06, 0x0078, 0x45df, 0x1078, 0x1381, 0x0040, 0x45e4, 0x2d00,
- 0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b,
- 0xffff, 0x8108, 0x00f0, 0x45d7, 0x6807, 0x0001, 0x6e12, 0xa085,
- 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x45e1, 0x127e,
- 0x2091, 0x8000, 0x0d7e, 0x60a4, 0xa00d, 0x0040, 0x4607, 0x2168,
- 0x6800, 0xa005, 0x00c0, 0x4603, 0x1078, 0x4749, 0x00c0, 0x4607,
- 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0048, 0x4603, 0x8001,
- 0x6806, 0x0078, 0x4607, 0x1078, 0x139a, 0x60a7, 0x0000, 0x0d7f,
- 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x47af, 0x0078,
- 0x4613, 0x1078, 0x43c1, 0x1078, 0x46a7, 0x00c0, 0x4611, 0x1078,
- 0x4663, 0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a8,
- 0xa06d, 0x0040, 0x463f, 0x6950, 0x81ff, 0x00c0, 0x4653, 0x6a54,
- 0xa282, 0x0010, 0x00c8, 0x4660, 0xad88, 0x0018, 0x20a9, 0x0010,
- 0x2104, 0xa086, 0xffff, 0x0040, 0x463a, 0x8108, 0x00f0, 0x4630,
- 0x1078, 0x1328, 0x260a, 0x8210, 0x6a56, 0x0078, 0x4653, 0x1078,
- 0x1381, 0x0040, 0x4660, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88,
- 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x00f0, 0x464b,
- 0x6857, 0x0001, 0x6e62, 0x0078, 0x4657, 0x1078, 0x441c, 0x1078,
- 0x466d, 0x00c0, 0x4655, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c,
- 0xa006, 0x0078, 0x465d, 0x127e, 0x2091, 0x8000, 0x1078, 0x5c17,
- 0x127f, 0x007c, 0xa01e, 0x0078, 0x466f, 0x2019, 0x0001, 0xa00e,
- 0x127e, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0,
- 0x468d, 0x8dff, 0x0040, 0x46a2, 0x83ff, 0x0040, 0x4685, 0x6848,
- 0xa606, 0x0040, 0x4692, 0x0078, 0x468d, 0x683c, 0xa406, 0x00c0,
- 0x468d, 0x6840, 0xa506, 0x0040, 0x4692, 0x2d08, 0x6800, 0x2068,
- 0x0078, 0x4679, 0x6a00, 0x604c, 0xad06, 0x00c0, 0x469a, 0x624e,
- 0x0078, 0x469d, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x46a2,
- 0x6152, 0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078, 0x46a9, 0x2019,
- 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040, 0x46d5, 0x83ff,
- 0x0040, 0x46b8, 0x6848, 0xa606, 0x0040, 0x46c5, 0x0078, 0x46c0,
- 0x683c, 0xa406, 0x00c0, 0x46c0, 0x6840, 0xa506, 0x0040, 0x46c5,
- 0x2d08, 0x6800, 0x2068, 0x0078, 0x46ac, 0x6a00, 0x6080, 0xad06,
- 0x00c0, 0x46cd, 0x6282, 0x0078, 0x46d0, 0xa180, 0x0000, 0x2202,
- 0x82ff, 0x00c0, 0x46d5, 0x6186, 0x8dff, 0x007c, 0xa016, 0x1078,
- 0x4742, 0x00c0, 0x46dd, 0x2011, 0x0001, 0x1078, 0x4793, 0x00c0,
- 0x46e3, 0xa295, 0x0002, 0x007c, 0x1078, 0x47cb, 0x0040, 0x46ec,
- 0x1078, 0x8b12, 0x0078, 0x46ee, 0xa085, 0x0001, 0x007c, 0x1078,
- 0x47cb, 0x0040, 0x46f7, 0x1078, 0x8aaa, 0x0078, 0x46f9, 0xa085,
- 0x0001, 0x007c, 0x1078, 0x47cb, 0x0040, 0x4702, 0x1078, 0x8af4,
- 0x0078, 0x4704, 0xa085, 0x0001, 0x007c, 0x1078, 0x47cb, 0x0040,
- 0x470d, 0x1078, 0x8ac6, 0x0078, 0x470f, 0xa085, 0x0001, 0x007c,
- 0x1078, 0x47cb, 0x0040, 0x4718, 0x1078, 0x8b30, 0x0078, 0x471a,
- 0xa085, 0x0001, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x8000,
- 0x6080, 0xa06d, 0x0040, 0x473a, 0x6800, 0x007e, 0x6837, 0x0103,
- 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8cb8, 0x007e, 0x6000, 0xd0fc,
- 0x0040, 0x4734, 0x1078, 0xa18c, 0x007f, 0x1078, 0x4982, 0x007f,
- 0x0078, 0x4721, 0x6083, 0x0000, 0x6087, 0x0000, 0x0d7f, 0x007f,
- 0x127f, 0x007c, 0x60a4, 0xa00d, 0x00c0, 0x4749, 0xa085, 0x0001,
- 0x007c, 0x0e7e, 0x2170, 0x7000, 0xa005, 0x00c0, 0x475c, 0x20a9,
- 0x0010, 0xae88, 0x0004, 0x2104, 0xa606, 0x0040, 0x475c, 0x8108,
- 0x00f0, 0x4753, 0xa085, 0x0001, 0xa006, 0x0e7f, 0x007c, 0x0d7e,
- 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x00c0, 0x476d, 0x1078,
- 0x1381, 0x0040, 0x477f, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807,
- 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108,
- 0x00f0, 0x4775, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006,
- 0x0078, 0x477c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d,
- 0x0040, 0x4790, 0x60a7, 0x0000, 0x1078, 0x139a, 0xa085, 0x0001,
- 0x127f, 0x0d7f, 0x007c, 0x60a8, 0xa00d, 0x00c0, 0x479a, 0xa085,
- 0x0001, 0x007c, 0x0e7e, 0x2170, 0x7050, 0xa005, 0x00c0, 0x47ad,
- 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0040, 0x47ad,
- 0x8108, 0x00f0, 0x47a4, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x127e,
- 0x2091, 0x8000, 0x1078, 0x4793, 0x00c0, 0x47c9, 0x200b, 0xffff,
- 0x0d7e, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, 0x0048, 0x47c4,
- 0x8001, 0x6856, 0x0078, 0x47c8, 0x1078, 0x139a, 0x60ab, 0x0000,
- 0x0d7f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, 0x0f7e, 0x71ac,
- 0x81ff, 0x00c0, 0x47e9, 0x71c8, 0xd19c, 0x0040, 0x47e9, 0x2001,
- 0x007e, 0xa080, 0xa434, 0x2004, 0xa07d, 0x0040, 0x47e9, 0x7804,
- 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x47e9, 0x7800, 0xc0ed,
- 0x7802, 0x2079, 0xa351, 0x7804, 0xd0a4, 0x0040, 0x480f, 0x157e,
- 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x4501,
- 0x00c0, 0x4809, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004,
- 0x0040, 0x4806, 0xa086, 0x0006, 0x00c0, 0x4809, 0x6000, 0xc0ed,
- 0x6002, 0x017f, 0x8108, 0x00f0, 0x47f5, 0x0c7f, 0x157f, 0x1078,
- 0x4897, 0x0040, 0x4818, 0x2001, 0xa59f, 0x200c, 0x0078, 0x4820,
- 0x2079, 0xa351, 0x7804, 0xd0a4, 0x0040, 0x4824, 0x2009, 0x07d0,
- 0x2011, 0x4826, 0x1078, 0x596c, 0x0f7f, 0x007c, 0x2011, 0x4826,
- 0x1078, 0x58d4, 0x1078, 0x4897, 0x0040, 0x484e, 0x2001, 0xa4b2,
- 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xa352,
- 0x2004, 0xd0a4, 0x0040, 0x4842, 0x2009, 0x07d0, 0x2011, 0x4826,
- 0x1078, 0x596c, 0x0e7e, 0x2071, 0xa300, 0x706b, 0x0000, 0x706f,
- 0x0000, 0x1078, 0x260d, 0x0e7f, 0x0078, 0x4886, 0x157e, 0x0c7e,
- 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x4501, 0x00c0,
- 0x4880, 0x6000, 0xd0ec, 0x0040, 0x4880, 0x047e, 0x62a0, 0xa294,
- 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0x9ec0, 0x6000,
- 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700,
- 0x6006, 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039, 0x0000,
- 0x1078, 0x5c78, 0x2009, 0x0000, 0x1078, 0x9c38, 0x077f, 0x047f,
- 0x017f, 0x8108, 0x00f0, 0x4854, 0x0c7f, 0x157f, 0x007c, 0x0c7e,
- 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x7818,
- 0x2004, 0xd0ac, 0x007c, 0x7818, 0x2004, 0xd0bc, 0x007c, 0x0f7e,
- 0x2001, 0xa4b2, 0x2004, 0xa07d, 0x0040, 0x48a0, 0x7800, 0xd0ec,
- 0x0f7f, 0x007c, 0x127e, 0x027e, 0x2091, 0x8000, 0x6200, 0xa005,
- 0x0040, 0x48ad, 0xc2fd, 0x0078, 0x48ae, 0xc2fc, 0x6202, 0x027f,
- 0x127f, 0x007c, 0x2071, 0xa413, 0x7003, 0x0001, 0x7007, 0x0000,
- 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000,
- 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, 0x0020,
- 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xa57c, 0x7003, 0xa413,
- 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xa55c, 0x7013, 0x0020,
- 0x7017, 0x0040, 0x7037, 0x0000, 0x007c, 0x017e, 0x0e7e, 0x2071,
- 0xa534, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, 0xa352,
- 0x2004, 0xd0fc, 0x00c0, 0x48f7, 0x2001, 0xa352, 0x2004, 0xa00e,
- 0xd09c, 0x0040, 0x48f4, 0x8108, 0x7102, 0x0078, 0x494a, 0x2001,
- 0xa371, 0x200c, 0xa184, 0x000f, 0x2009, 0xa372, 0x210c, 0x0079,
- 0x4901, 0x48ec, 0x4922, 0x492a, 0x4935, 0x493b, 0x48ec, 0x48ec,
- 0x48ec, 0x4911, 0x48ec, 0x48ec, 0x48ec, 0x48ec, 0x48ec, 0x48ec,
- 0x48ec, 0x7003, 0x0004, 0x137e, 0x147e, 0x157e, 0x2099, 0xa375,
- 0x20a1, 0xa585, 0x20a9, 0x0004, 0x53a3, 0x157f, 0x147f, 0x137f,
- 0x0078, 0x494a, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002,
- 0x0078, 0x4930, 0x708f, 0x0002, 0x7007, 0x0121, 0x2001, 0x0003,
- 0x7002, 0x7097, 0x0001, 0x0078, 0x4947, 0x7007, 0x0122, 0x2001,
- 0x0002, 0x0078, 0x493f, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002,
- 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, 0x709a, 0xa184,
- 0x00ff, 0x7092, 0x0e7f, 0x017f, 0x007c, 0x0e7e, 0x2071, 0xa413,
- 0x684c, 0xa005, 0x00c0, 0x495b, 0x7028, 0xc085, 0x702a, 0xa085,
- 0x0001, 0x0078, 0x4980, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868,
- 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844,
- 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, 0x8006,
- 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319,
- 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006,
- 0x0e7f, 0x007c, 0x0e7e, 0x027e, 0x6838, 0xd0fc, 0x00c0, 0x49d8,
- 0x6804, 0xa00d, 0x0040, 0x499e, 0x0d7e, 0x2071, 0xa300, 0xa016,
- 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x00c0,
- 0x4991, 0x702e, 0x70a8, 0xa200, 0x70aa, 0x0d7f, 0x2071, 0xa413,
- 0x701c, 0xa005, 0x00c0, 0x49ea, 0x0068, 0x49e8, 0x2071, 0xa534,
- 0x7200, 0x82ff, 0x0040, 0x49e8, 0x6934, 0xa186, 0x0103, 0x00c0,
- 0x49fb, 0x6948, 0x6844, 0xa105, 0x00c0, 0x49db, 0x2009, 0x8020,
- 0x2200, 0x0079, 0x49bb, 0x49e8, 0x49c0, 0x4a18, 0x4a26, 0x49e8,
- 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x49e8, 0x7122, 0x683c,
- 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x2071,
- 0xa300, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70a8, 0x8000, 0x70aa,
- 0x027f, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100, 0x00c0, 0x49e8,
- 0x6868, 0xa005, 0x00c0, 0x49e8, 0x2009, 0x8020, 0x0078, 0x49b8,
- 0x2071, 0xa413, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, 0x7012,
- 0x7018, 0xa06d, 0x711a, 0x0040, 0x49f8, 0x6902, 0x0078, 0x49f9,
- 0x711e, 0x0078, 0x49d8, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0040,
- 0x4a09, 0xa186, 0x001e, 0x0040, 0x4a09, 0xa18e, 0x001f, 0x00c0,
- 0x49e8, 0x684c, 0xd0cc, 0x0040, 0x49e8, 0x6850, 0xa084, 0x00ff,
- 0xa086, 0x0001, 0x00c0, 0x49e8, 0x2009, 0x8021, 0x0078, 0x49b8,
- 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x49e8, 0x7186, 0xae90,
- 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x4a36, 0x7084, 0x8008,
- 0xa092, 0x000f, 0x00c8, 0x49e8, 0x7186, 0xae90, 0x0003, 0x8003,
- 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a,
- 0x0048, 0x49cf, 0x718c, 0x7084, 0xa10a, 0x0048, 0x49cf, 0x2071,
- 0x0000, 0x7018, 0xd084, 0x00c0, 0x49cf, 0x2071, 0xa534, 0x7000,
- 0xa086, 0x0002, 0x00c0, 0x4a56, 0x1078, 0x4cd2, 0x2071, 0x0000,
- 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x49cf, 0x1078, 0x4cfd,
- 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x49cf,
- 0x007e, 0x684c, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80,
- 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0xa084, 0x00ff,
- 0x684e, 0x007f, 0x684a, 0x6952, 0x007c, 0x2071, 0xa413, 0x7004,
- 0x0079, 0x4a7a, 0x4a84, 0x4a95, 0x4ca3, 0x4ca4, 0x4ccb, 0x4cd1,
- 0x4a85, 0x4c91, 0x4c32, 0x4cb4, 0x007c, 0x127e, 0x2091, 0x8000,
- 0x0068, 0x4a94, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080,
- 0x7007, 0x0001, 0x700b, 0x0000, 0x127f, 0x2069, 0xa5be, 0x6844,
- 0xa005, 0x0050, 0x4abd, 0x00c0, 0x4abd, 0x127e, 0x2091, 0x8000,
- 0x2069, 0x0000, 0x6934, 0x2001, 0xa41f, 0x2004, 0xa10a, 0x0040,
- 0x4ab8, 0x0068, 0x4abc, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0,
- 0x4abc, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080,
- 0x2069, 0xa5be, 0x6847, 0xffff, 0x127f, 0x2069, 0xa300, 0x6844,
- 0x6960, 0xa102, 0x2069, 0xa534, 0x688a, 0x6984, 0x701c, 0xa06d,
- 0x0040, 0x4acf, 0x81ff, 0x0040, 0x4b17, 0x0078, 0x4ae5, 0x81ff,
- 0x0040, 0x4be9, 0x2071, 0xa534, 0x7184, 0x7088, 0xa10a, 0x00c8,
- 0x4ae5, 0x7190, 0x2071, 0xa5be, 0x7040, 0xa005, 0x0040, 0x4ae5,
- 0x00d0, 0x4be9, 0x7142, 0x0078, 0x4be9, 0x2071, 0xa534, 0x718c,
- 0x127e, 0x2091, 0x8000, 0x7084, 0xa10a, 0x0048, 0x4c06, 0x0068,
- 0x4b9b, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4b9b, 0x2001,
- 0xffff, 0x2071, 0xa5be, 0x7042, 0x2071, 0xa534, 0x7000, 0xa086,
- 0x0002, 0x00c0, 0x4b0d, 0x1078, 0x4cd2, 0x2071, 0x0000, 0x701b,
- 0x0001, 0x2091, 0x4080, 0x0078, 0x4b9b, 0x1078, 0x4cfd, 0x2071,
- 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4b9b, 0x2071,
- 0xa534, 0x7000, 0xa005, 0x0040, 0x4bc8, 0x6934, 0xa186, 0x0103,
- 0x00c0, 0x4b9e, 0x684c, 0xd0bc, 0x00c0, 0x4bc8, 0x6948, 0x6844,
- 0xa105, 0x00c0, 0x4bbb, 0x2009, 0x8020, 0x2071, 0xa534, 0x7000,
- 0x0079, 0x4b32, 0x4bc8, 0x4b80, 0x4b58, 0x4b6a, 0x4b37, 0x137e,
- 0x147e, 0x157e, 0x2099, 0xa375, 0x20a1, 0xa585, 0x20a9, 0x0004,
- 0x53a3, 0x157f, 0x147f, 0x137f, 0x2071, 0xa57c, 0xad80, 0x000f,
- 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, 0x2e10,
- 0x1078, 0x13d1, 0x2071, 0xa413, 0x7007, 0x0009, 0x0078, 0x4be9,
- 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4be9, 0xae90, 0x0003,
- 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xa413, 0x1078, 0x4d5b,
- 0x0078, 0x4be9, 0x7084, 0x8008, 0xa092, 0x000f, 0x00c8, 0x4be9,
- 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840,
- 0x2012, 0x7186, 0x2071, 0xa413, 0x1078, 0x4d5b, 0x0078, 0x4be9,
- 0x127e, 0x2091, 0x8000, 0x0068, 0x4b9b, 0x2071, 0x0000, 0x7018,
- 0xd084, 0x00c0, 0x4b9b, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a,
- 0x701b, 0x0001, 0x2091, 0x4080, 0x127f, 0x2071, 0xa413, 0x1078,
- 0x4d5b, 0x0078, 0x4be9, 0x127f, 0x0078, 0x4be9, 0xa18c, 0x00ff,
- 0xa186, 0x0017, 0x0040, 0x4bac, 0xa186, 0x001e, 0x0040, 0x4bac,
- 0xa18e, 0x001f, 0x00c0, 0x4bc8, 0x684c, 0xd0cc, 0x0040, 0x4bc8,
- 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4bc8, 0x2009,
- 0x8021, 0x0078, 0x4b2d, 0x6844, 0xa086, 0x0100, 0x00c0, 0x4bc8,
- 0x6868, 0xa005, 0x00c0, 0x4bc8, 0x2009, 0x8020, 0x0078, 0x4b2d,
- 0x2071, 0xa413, 0x1078, 0x4d6f, 0x0040, 0x4be9, 0x2071, 0xa413,
- 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x00c0,
- 0x4be0, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x4be0, 0x710e,
- 0x7007, 0x0003, 0x1078, 0x4d8f, 0x7050, 0xa086, 0x0100, 0x0040,
- 0x4ca4, 0x127e, 0x2091, 0x8000, 0x2071, 0xa413, 0x7008, 0xa086,
- 0x0001, 0x00c0, 0x4c04, 0x0068, 0x4c04, 0x2009, 0x000d, 0x7030,
- 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006,
- 0x00c0, 0x4c04, 0x7007, 0x0001, 0x127f, 0x007c, 0x2071, 0xa413,
- 0x1078, 0x4d6f, 0x0040, 0x4c2f, 0x2071, 0xa534, 0x7084, 0x700a,
- 0x20a9, 0x0020, 0x2099, 0xa535, 0x20a1, 0xa55c, 0x53a3, 0x7087,
- 0x0000, 0x2071, 0xa413, 0x2069, 0xa57c, 0x706c, 0x6826, 0x7070,
- 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, 0x2d10, 0x1078, 0x13d1,
- 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, 0xa5be, 0x7042, 0x127f,
- 0x0078, 0x4be9, 0x2069, 0xa57c, 0x6808, 0xa08e, 0x0000, 0x0040,
- 0x4c90, 0xa08e, 0x0200, 0x0040, 0x4c8e, 0xa08e, 0x0100, 0x00c0,
- 0x4c90, 0x127e, 0x2091, 0x8000, 0x0068, 0x4c8b, 0x2069, 0x0000,
- 0x6818, 0xd084, 0x00c0, 0x4c8b, 0x702c, 0x7130, 0x8108, 0xa102,
- 0x0048, 0x4c59, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0078,
- 0x4c63, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4c63, 0x7070,
- 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, 0x2001,
- 0xa559, 0x2004, 0xa005, 0x00c0, 0x4c82, 0x6934, 0x2069, 0xa534,
- 0x689c, 0x699e, 0x2069, 0xa5be, 0xa102, 0x00c0, 0x4c7b, 0x6844,
- 0xa005, 0x00d0, 0x4c89, 0x2001, 0xa55a, 0x200c, 0x810d, 0x6946,
- 0x0078, 0x4c89, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091,
- 0x4080, 0x7007, 0x0001, 0x127f, 0x0078, 0x4c90, 0x7007, 0x0005,
- 0x007c, 0x701c, 0xa06d, 0x0040, 0x4ca2, 0x1078, 0x4d6f, 0x0040,
- 0x4ca2, 0x7007, 0x0003, 0x1078, 0x4d8f, 0x7050, 0xa086, 0x0100,
- 0x0040, 0x4ca4, 0x007c, 0x007c, 0x7050, 0xa09e, 0x0100, 0x00c0,
- 0x4cad, 0x7007, 0x0004, 0x0078, 0x4ccb, 0xa086, 0x0200, 0x00c0,
- 0x4cb3, 0x7007, 0x0005, 0x007c, 0x2001, 0xa57e, 0x2004, 0xa08e,
- 0x0100, 0x00c0, 0x4cc0, 0x7007, 0x0001, 0x1078, 0x4d5b, 0x007c,
- 0xa08e, 0x0000, 0x0040, 0x4cbf, 0xa08e, 0x0200, 0x00c0, 0x4cbf,
- 0x7007, 0x0005, 0x007c, 0x1078, 0x4d25, 0x7006, 0x1078, 0x4d5b,
- 0x007c, 0x007c, 0x0e7e, 0x157e, 0x2071, 0xa534, 0x7184, 0x81ff,
- 0x0040, 0x4cfa, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000,
- 0x21a8, 0x2014, 0x7226, 0x8000, 0x0070, 0x4cf7, 0x2014, 0x722a,
- 0x8000, 0x0070, 0x4cf7, 0x2014, 0x722e, 0x8000, 0x0070, 0x4cf7,
- 0x2014, 0x723a, 0x8000, 0x0070, 0x4cf7, 0x2014, 0x723e, 0xa180,
- 0x8030, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x0e7e, 0x157e, 0x2071,
- 0xa534, 0x7184, 0x81ff, 0x0040, 0x4d22, 0xa006, 0x7086, 0xae80,
- 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014,
- 0x722a, 0x8000, 0x0070, 0x4d1b, 0x2014, 0x723a, 0x8000, 0x2014,
- 0x723e, 0x0078, 0x4d1f, 0x2001, 0x8020, 0x0078, 0x4d21, 0x2001,
- 0x8042, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x702c, 0x7130, 0x8108,
- 0xa102, 0x0048, 0x4d32, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072,
- 0x0078, 0x4d3c, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4d3c,
- 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, 0x700e,
- 0x00c0, 0x4d52, 0x127e, 0x2091, 0x8000, 0x0068, 0x4d55, 0x2001,
- 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b, 0x0000,
- 0x127f, 0x007c, 0x2001, 0x0007, 0x007c, 0x2001, 0x0006, 0x700b,
- 0x0001, 0x127f, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4d6e, 0x127e,
- 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0xa005,
- 0x00c0, 0x4d6b, 0x701a, 0x127f, 0x1078, 0x139a, 0x007c, 0x2019,
- 0x000d, 0x2304, 0x230c, 0xa10e, 0x0040, 0x4d7e, 0x2304, 0x230c,
- 0xa10e, 0x0040, 0x4d7e, 0xa006, 0x0078, 0x4d8e, 0x732c, 0x8319,
- 0x7130, 0xa102, 0x00c0, 0x4d88, 0x2300, 0xa005, 0x0078, 0x4d8e,
- 0x0048, 0x4d8d, 0xa302, 0x0078, 0x4d8e, 0x8002, 0x007c, 0x2d00,
- 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x127e, 0x2091,
- 0x8000, 0x2009, 0xa5d0, 0x2104, 0xc08d, 0x200a, 0x127f, 0x1078,
- 0x13eb, 0x007c, 0x2071, 0xa3e1, 0x7003, 0x0000, 0x7007, 0x0000,
- 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001,
- 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, 0x0000,
- 0x708f, 0x0001, 0x70bf, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa3e1,
- 0x6848, 0xa005, 0x00c0, 0x4dcb, 0x7028, 0xc085, 0x702a, 0xa085,
- 0x0001, 0x0078, 0x4df0, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858,
- 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840,
- 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c,
- 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376,
- 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006,
- 0x0e7f, 0x007c, 0x2b78, 0x2071, 0xa3e1, 0x7004, 0x1079, 0x4e50,
- 0x700c, 0x0079, 0x4dfb, 0x4e00, 0x4df5, 0x4df5, 0x4df5, 0x4df5,
- 0x007c, 0x700c, 0x0079, 0x4e04, 0x4e09, 0x4e4e, 0x4e4e, 0x4e4f,
- 0x4e4f, 0x7830, 0x7930, 0xa106, 0x0040, 0x4e13, 0x7830, 0x7930,
- 0xa106, 0x00c0, 0x4e39, 0x7030, 0xa10a, 0x0040, 0x4e39, 0x00c8,
- 0x4e1b, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x00c8, 0x4e3a, 0x1078,
- 0x1366, 0x0040, 0x4e39, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001,
- 0x0003, 0x7057, 0x0000, 0x127e, 0x007e, 0x2091, 0x8000, 0x2009,
- 0xa5d0, 0x2104, 0xc085, 0x200a, 0x007f, 0x700e, 0x127f, 0x1078,
- 0x13eb, 0x007c, 0x1078, 0x1366, 0x0040, 0x4e39, 0x2d00, 0x705a,
- 0x1078, 0x1366, 0x00c0, 0x4e46, 0x0078, 0x4e25, 0x2d00, 0x7086,
- 0x7063, 0x0080, 0x2001, 0x0004, 0x0078, 0x4e29, 0x007c, 0x007c,
- 0x4e61, 0x4e62, 0x4e99, 0x4e9a, 0x4e4e, 0x4ed0, 0x4ed5, 0x4f0c,
- 0x4f0d, 0x4f28, 0x4f29, 0x4f2a, 0x4f2b, 0x4f2c, 0x4f2d, 0x4fad,
- 0x4fd7, 0x007c, 0x700c, 0x0079, 0x4e65, 0x4e6a, 0x4e6d, 0x4e7d,
- 0x4e98, 0x4e98, 0x1078, 0x4e01, 0x007c, 0x127e, 0x8001, 0x700e,
- 0x7058, 0x007e, 0x1078, 0x5348, 0x0040, 0x4e7a, 0x2091, 0x8000,
- 0x1078, 0x4e01, 0x0d7f, 0x0078, 0x4e86, 0x127e, 0x8001, 0x700e,
- 0x1078, 0x5348, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000,
- 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020, 0x00c8,
- 0x4e95, 0x1079, 0x4eb0, 0x127f, 0x007c, 0x127f, 0x1078, 0x4f2e,
- 0x007c, 0x007c, 0x007c, 0x0e7e, 0x2071, 0xa3e1, 0x700c, 0x0079,
- 0x4ea1, 0x4ea6, 0x4ea6, 0x4ea6, 0x4ea8, 0x4eac, 0x0e7f, 0x007c,
- 0x700f, 0x0001, 0x0078, 0x4eae, 0x700f, 0x0002, 0x0e7f, 0x007c,
- 0x4f2e, 0x4f2e, 0x4f4a, 0x4f2e, 0x5080, 0x4f2e, 0x4f2e, 0x4f2e,
- 0x4f2e, 0x4f2e, 0x4f4a, 0x50ca, 0x5117, 0x5170, 0x5186, 0x4f2e,
- 0x4f2e, 0x4f66, 0x4f4a, 0x4f2e, 0x4f2e, 0x4f87, 0x5245, 0x5263,
- 0x4f2e, 0x4f66, 0x4f2e, 0x4f2e, 0x4f2e, 0x4f2e, 0x4f7c, 0x5263,
- 0x7020, 0x2068, 0x1078, 0x139a, 0x007c, 0x700c, 0x0079, 0x4ed8,
- 0x4edd, 0x4ee0, 0x4ef0, 0x4f0b, 0x4f0b, 0x1078, 0x4e01, 0x007c,
- 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x5348, 0x0040,
- 0x4eed, 0x2091, 0x8000, 0x1078, 0x4e01, 0x0d7f, 0x0078, 0x4ef9,
- 0x127e, 0x8001, 0x700e, 0x1078, 0x5348, 0x7058, 0x2068, 0x7084,
- 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff,
- 0xa08a, 0x001a, 0x00c8, 0x4f08, 0x1079, 0x4f0e, 0x127f, 0x007c,
- 0x127f, 0x1078, 0x4f2e, 0x007c, 0x007c, 0x007c, 0x4f2e, 0x4f4a,
- 0x506a, 0x4f2e, 0x4f4a, 0x4f2e, 0x4f4a, 0x4f4a, 0x4f2e, 0x4f4a,
- 0x506a, 0x4f4a, 0x4f4a, 0x4f4a, 0x4f4a, 0x4f4a, 0x4f2e, 0x4f4a,
- 0x506a, 0x4f2e, 0x4f2e, 0x4f4a, 0x4f2e, 0x4f2e, 0x4f2e, 0x4f4a,
- 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x7007, 0x0001,
- 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x127e, 0x2091, 0x8000,
- 0x1078, 0x4982, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084,
- 0x00ff, 0xc0e5, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4982,
- 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed,
- 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4982, 0x127f, 0x007c,
- 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x127e,
- 0x2091, 0x8000, 0x1078, 0x4982, 0x127f, 0x007c, 0x6834, 0x8007,
- 0xa084, 0x00ff, 0x0040, 0x4f3c, 0x8001, 0x00c0, 0x4f73, 0x7007,
- 0x0001, 0x0078, 0x5049, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016,
- 0x701a, 0x704b, 0x5049, 0x007c, 0x684c, 0xa084, 0x00c0, 0xa086,
- 0x00c0, 0x00c0, 0x4f87, 0x7007, 0x0001, 0x0078, 0x5280, 0x2d00,
- 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1,
- 0xa40c, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8, 0x4f58,
- 0x6884, 0xa08a, 0x0002, 0x00c8, 0x4f58, 0x82ff, 0x00c0, 0x4fa9,
- 0x6888, 0x698c, 0xa105, 0x0040, 0x4fa9, 0x2001, 0x5019, 0x0078,
- 0x4fac, 0xa280, 0x500f, 0x2004, 0x70c6, 0x7010, 0xa015, 0x0040,
- 0x4ff7, 0x1078, 0x1366, 0x00c0, 0x4fb8, 0x7007, 0x000f, 0x007c,
- 0x2d00, 0x7022, 0x70c4, 0x2060, 0x6000, 0x6836, 0x6004, 0xad00,
- 0x7096, 0x6008, 0xa20a, 0x00c8, 0x4fc7, 0xa00e, 0x2200, 0x7112,
- 0x620c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0040, 0x4fd0, 0xa108,
- 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x1078, 0x13d1, 0x7090,
- 0xa08e, 0x0100, 0x0040, 0x4feb, 0xa086, 0x0200, 0x0040, 0x4fe3,
- 0x7007, 0x0010, 0x007c, 0x7020, 0x2068, 0x1078, 0x139a, 0x7014,
- 0x2068, 0x0078, 0x4f58, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807,
- 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0078, 0x4fad, 0x7014,
- 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x00c0, 0x5006, 0x6888,
- 0x698c, 0xa105, 0x0040, 0x5006, 0x1078, 0x501d, 0x6834, 0xa084,
- 0x00ff, 0xa086, 0x001e, 0x0040, 0x5280, 0x0078, 0x5049, 0x5011,
- 0x5015, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, 0x0005,
- 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x0f7e, 0x0e7e, 0x0c7e,
- 0x077e, 0x067e, 0x6f88, 0x6e8c, 0x6804, 0x2060, 0xacf0, 0x0021,
- 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, 0x7812,
- 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, 0x0040,
- 0x503f, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0078, 0x502c, 0x6004,
- 0xa065, 0x00c0, 0x5026, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x0f7f,
- 0x007c, 0x2009, 0xa32e, 0x210c, 0x81ff, 0x00c0, 0x5064, 0x6838,
- 0xa084, 0x00ff, 0x683a, 0x1078, 0x4290, 0x00c0, 0x5058, 0x007c,
- 0x1078, 0x4a60, 0x127e, 0x2091, 0x8000, 0x1078, 0x8cb8, 0x1078,
- 0x4982, 0x127f, 0x0078, 0x5057, 0x2001, 0x0028, 0x2009, 0x0000,
- 0x0078, 0x5058, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a,
- 0x7010, 0x8001, 0x7012, 0x0040, 0x5079, 0x7007, 0x0006, 0x0078,
- 0x507f, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a, 0x007c,
- 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084,
- 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x50a9, 0x2009,
- 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0040, 0x50a9, 0xa005,
- 0x00c0, 0x50bc, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x4501,
- 0x00c0, 0x50bc, 0x067e, 0x6e50, 0x1078, 0x45e7, 0x067f, 0x0078,
- 0x50bc, 0x047e, 0x2011, 0xa30c, 0x2224, 0xc484, 0xc48c, 0x2412,
- 0x047f, 0x0c7e, 0x1078, 0x4501, 0x00c0, 0x50b8, 0x1078, 0x4782,
- 0x8108, 0x00f0, 0x50b2, 0x0c7f, 0x684c, 0xd084, 0x00c0, 0x50c3,
- 0x1078, 0x139a, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4982,
- 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001,
- 0xa352, 0x2004, 0xd0a4, 0x0040, 0x510e, 0x2061, 0xa62d, 0x6100,
- 0xd184, 0x0040, 0x50ee, 0x6858, 0xa084, 0x00ff, 0x00c0, 0x5111,
- 0x6000, 0xd084, 0x0040, 0x510e, 0x6004, 0xa005, 0x00c0, 0x5114,
- 0x6003, 0x0000, 0x600b, 0x0000, 0x0078, 0x510b, 0x2011, 0x0001,
- 0x6860, 0xa005, 0x00c0, 0x50f6, 0x2001, 0x001e, 0x8000, 0x6016,
- 0x6858, 0xa084, 0x00ff, 0x0040, 0x510e, 0x6006, 0x6858, 0x8007,
- 0xa084, 0x00ff, 0x0040, 0x510e, 0x600a, 0x6858, 0x8000, 0x00c0,
- 0x510a, 0xc28d, 0x6202, 0x127f, 0x0078, 0x5337, 0x127f, 0x0078,
- 0x532f, 0x127f, 0x0078, 0x5327, 0x127f, 0x0078, 0x532b, 0x127e,
- 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xa352, 0x2004, 0xd0a4,
- 0x0040, 0x516d, 0x2061, 0xa62d, 0x6000, 0xd084, 0x0040, 0x516d,
- 0x6204, 0x6308, 0xd08c, 0x00c0, 0x515f, 0x6c48, 0xa484, 0x0003,
- 0x0040, 0x5145, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, 0x513e,
- 0x2100, 0xa210, 0x0048, 0x516a, 0x0078, 0x5145, 0x8001, 0x00c0,
- 0x516a, 0x2100, 0xa212, 0x0048, 0x516a, 0xa484, 0x000c, 0x0040,
- 0x515f, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0,
- 0x5157, 0x2100, 0xa318, 0x0048, 0x516a, 0x0078, 0x515f, 0xa082,
- 0x0004, 0x00c0, 0x516a, 0x2100, 0xa31a, 0x0048, 0x516a, 0x6860,
- 0xa005, 0x0040, 0x5165, 0x8000, 0x6016, 0x6206, 0x630a, 0x127f,
- 0x0078, 0x5337, 0x127f, 0x0078, 0x5333, 0x127f, 0x0078, 0x532f,
- 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xa62d, 0x6300,
- 0xd38c, 0x00c0, 0x5180, 0x6308, 0x8318, 0x0048, 0x5183, 0x630a,
- 0x127f, 0x0078, 0x5345, 0x127f, 0x0078, 0x5333, 0x127e, 0x0c7e,
- 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0040, 0x519a,
- 0x0c7e, 0x2061, 0xa62d, 0x6000, 0xa084, 0xfcff, 0x6002, 0x0c7f,
- 0x0078, 0x51c9, 0x6858, 0xa005, 0x0040, 0x51e0, 0x685c, 0xa065,
- 0x0040, 0x51dc, 0x2001, 0xa32e, 0x2004, 0xa005, 0x0040, 0x51ac,
- 0x1078, 0x8c01, 0x0078, 0x51ba, 0x6013, 0x0400, 0x6037, 0x0000,
- 0x694c, 0xd1a4, 0x0040, 0x51b6, 0x6950, 0x6136, 0x2009, 0x0041,
- 0x1078, 0x756c, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, 0x00c0,
- 0x51c9, 0x027e, 0x2009, 0x0000, 0x2011, 0xfdff, 0x1078, 0x5a6d,
- 0x027f, 0x684c, 0xd0c4, 0x0040, 0x51d8, 0x2061, 0xa62d, 0x6000,
- 0xd08c, 0x00c0, 0x51d8, 0x6008, 0x8000, 0x0048, 0x51dc, 0x600a,
- 0x0c7f, 0x127f, 0x0078, 0x5337, 0x0c7f, 0x127f, 0x0078, 0x532f,
- 0x6954, 0xa186, 0x0045, 0x0040, 0x5213, 0xa186, 0x002a, 0x00c0,
- 0x51f0, 0x2001, 0xa30c, 0x200c, 0xc194, 0x2102, 0x0078, 0x51c9,
- 0xa186, 0x0020, 0x0040, 0x5209, 0xa186, 0x0029, 0x0040, 0x51fc,
- 0xa186, 0x002d, 0x00c0, 0x51dc, 0x6944, 0xa18c, 0xff00, 0x810f,
- 0x1078, 0x4501, 0x00c0, 0x51c9, 0x6000, 0xc0e4, 0x6002, 0x0078,
- 0x51c9, 0x685c, 0xa065, 0x0040, 0x51dc, 0x2001, 0xa5a1, 0x2004,
- 0x6016, 0x0078, 0x51c9, 0x685c, 0xa065, 0x0040, 0x51dc, 0x0e7e,
- 0x6860, 0xa075, 0x2001, 0xa32e, 0x2004, 0xa005, 0x0040, 0x522b,
- 0x1078, 0x8c01, 0x8eff, 0x0040, 0x5228, 0x2e60, 0x1078, 0x8c01,
- 0x0e7f, 0x0078, 0x51c9, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60,
- 0x6007, 0x003a, 0x6870, 0xa005, 0x0040, 0x523c, 0x6007, 0x003b,
- 0x6874, 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x1078, 0x5bf8,
- 0x1078, 0x6109, 0x0e7f, 0x0078, 0x51c9, 0x2061, 0xa62d, 0x6000,
- 0xd084, 0x0040, 0x525f, 0xd08c, 0x00c0, 0x5345, 0x2091, 0x8000,
- 0x6204, 0x8210, 0x0048, 0x5259, 0x6206, 0x2091, 0x8001, 0x0078,
- 0x5345, 0x2091, 0x8001, 0x6853, 0x0016, 0x0078, 0x533e, 0x6853,
- 0x0007, 0x0078, 0x533e, 0x6834, 0x8007, 0xa084, 0x00ff, 0x00c0,
- 0x526d, 0x1078, 0x4f3c, 0x0078, 0x527f, 0x2030, 0x8001, 0x00c0,
- 0x5277, 0x7007, 0x0001, 0x1078, 0x5280, 0x0078, 0x527f, 0x7007,
- 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x5280, 0x007c,
- 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2009, 0xa32e, 0x210c, 0x81ff,
- 0x00c0, 0x530b, 0x2009, 0xa30c, 0x210c, 0xd194, 0x00c0, 0x5315,
- 0x6848, 0x2070, 0xae82, 0xaa00, 0x0048, 0x52fb, 0x2001, 0xa315,
- 0x2004, 0xae02, 0x00c8, 0x52fb, 0x2061, 0xa62d, 0x6100, 0xa184,
- 0x0301, 0xa086, 0x0001, 0x00c0, 0x52de, 0x711c, 0xa186, 0x0006,
- 0x00c0, 0x52e6, 0x7018, 0xa005, 0x0040, 0x530b, 0x2004, 0xd0e4,
- 0x00c0, 0x530f, 0x7024, 0xd0dc, 0x00c0, 0x5319, 0x6853, 0x0000,
- 0x6803, 0x0000, 0x2d08, 0x7010, 0xa005, 0x00c0, 0x52ca, 0x7112,
- 0x684c, 0xd0f4, 0x00c0, 0x531d, 0x2e60, 0x1078, 0x59b6, 0x127f,
- 0x0e7f, 0x007c, 0x2068, 0x6800, 0xa005, 0x00c0, 0x52ca, 0x6902,
- 0x2168, 0x684c, 0xd0f4, 0x00c0, 0x531d, 0x127f, 0x0e7f, 0x007c,
- 0x127f, 0x0e7f, 0x6853, 0x0006, 0x0078, 0x533e, 0xd184, 0x0040,
- 0x52d8, 0xd1c4, 0x00c0, 0x52ff, 0x0078, 0x5303, 0x6944, 0xa18c,
- 0xff00, 0x810f, 0x1078, 0x4501, 0x00c0, 0x530f, 0x6000, 0xd0e4,
- 0x00c0, 0x530f, 0x711c, 0xa186, 0x0007, 0x00c0, 0x52fb, 0x6853,
- 0x0002, 0x0078, 0x5311, 0x6853, 0x0008, 0x0078, 0x5311, 0x6853,
- 0x000e, 0x0078, 0x5311, 0x6853, 0x0017, 0x0078, 0x5311, 0x6853,
- 0x0035, 0x0078, 0x5311, 0x6853, 0x0028, 0x0078, 0x5311, 0x6853,
- 0x0029, 0x127f, 0x0e7f, 0x0078, 0x533e, 0x6853, 0x002a, 0x0078,
- 0x5311, 0x6853, 0x0045, 0x0078, 0x5311, 0x2e60, 0x2019, 0x0002,
- 0x6017, 0x0014, 0x1078, 0x9a6a, 0x127f, 0x0e7f, 0x007c, 0x2009,
- 0x003e, 0x0078, 0x5339, 0x2009, 0x0004, 0x0078, 0x5339, 0x2009,
- 0x0006, 0x0078, 0x5339, 0x2009, 0x0016, 0x0078, 0x5339, 0x2009,
- 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856, 0x2091, 0x8000,
- 0x1078, 0x4982, 0x2091, 0x8001, 0x007c, 0x1078, 0x139a, 0x007c,
- 0x702c, 0x7130, 0x8108, 0xa102, 0x0048, 0x5355, 0xa00e, 0x7034,
- 0x7072, 0x7038, 0x7076, 0x0078, 0x5361, 0x7070, 0xa080, 0x0040,
- 0x7072, 0x00c8, 0x5361, 0x7074, 0xa081, 0x0000, 0x7076, 0xa085,
- 0x0001, 0x7932, 0x7132, 0x007c, 0x0d7e, 0x1078, 0x59ad, 0x0d7f,
- 0x007c, 0x0d7e, 0x2011, 0x0004, 0x2204, 0xa085, 0x8002, 0x2012,
- 0x0d7f, 0x007c, 0x20e1, 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00,
- 0xa084, 0x7000, 0x0040, 0x5380, 0xa086, 0x1000, 0x00c0, 0x53ac,
- 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00, 0x8217, 0xa084, 0xf000,
- 0xa086, 0x3000, 0x00c0, 0x5390, 0x1078, 0x5570, 0x0078, 0x53a7,
- 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x00c0, 0x5397, 0x3e60, 0xac84,
- 0x000f, 0x00c0, 0x53ac, 0xac82, 0xaa00, 0x0048, 0x53ac, 0x6854,
- 0xac02, 0x00c8, 0x53ac, 0x2009, 0x0047, 0x1078, 0x756c, 0x7a1c,
- 0xd284, 0x00c0, 0x5372, 0x007c, 0xa016, 0x1078, 0x15ec, 0x0078,
- 0x53a7, 0x0078, 0x53ac, 0x781c, 0xd08c, 0x0040, 0x53db, 0x157e,
- 0x137e, 0x147e, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076,
- 0x00c0, 0x53f1, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0, 0x53e0,
- 0x1078, 0x540c, 0x0040, 0x53f1, 0x20e1, 0x3000, 0x7828, 0x7828,
- 0x1078, 0x542a, 0x147f, 0x137f, 0x157f, 0x2009, 0xa5b3, 0x2104,
- 0xa005, 0x00c0, 0x53dc, 0x007c, 0x1078, 0x6109, 0x0078, 0x53db,
- 0xa484, 0x7000, 0x00c0, 0x53f1, 0x1078, 0x540c, 0x0040, 0x5403,
- 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x0040, 0x53cc, 0x0078,
- 0x5403, 0x1078, 0xa1ee, 0xd5a4, 0x0040, 0x53ff, 0x1078, 0x1af7,
- 0x20e1, 0x9010, 0x2001, 0x0138, 0x2202, 0x0078, 0x5407, 0x1078,
- 0x540c, 0x687f, 0x0000, 0x20e1, 0x3000, 0x7828, 0x7828, 0x147f,
- 0x137f, 0x157f, 0x0078, 0x53db, 0xa484, 0x01ff, 0x687e, 0xa005,
- 0x0040, 0x541e, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac, 0x20e1,
- 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c, 0x20a9, 0x000c,
- 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001,
- 0x0078, 0x541d, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007,
- 0xa196, 0x0000, 0x00c0, 0x5437, 0x0078, 0x567c, 0x007c, 0xa196,
- 0x2000, 0x00c0, 0x5448, 0x6900, 0xa18e, 0x0001, 0x00c0, 0x5444,
- 0x1078, 0x3a43, 0x0078, 0x5436, 0x1078, 0x5450, 0x0078, 0x5436,
- 0xa196, 0x8000, 0x00c0, 0x5436, 0x1078, 0x570c, 0x0078, 0x5436,
- 0x0c7e, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0040,
- 0x545d, 0xa196, 0x0023, 0x00c0, 0x5568, 0xa08e, 0x0023, 0x00c0,
- 0x5492, 0x1078, 0x57b2, 0x0040, 0x5568, 0x7124, 0x610a, 0x7030,
- 0xa08e, 0x0200, 0x00c0, 0x5476, 0x7034, 0xa005, 0x00c0, 0x5568,
- 0x2009, 0x0015, 0x1078, 0x756c, 0x0078, 0x5568, 0xa08e, 0x0214,
- 0x0040, 0x547e, 0xa08e, 0x0210, 0x00c0, 0x5484, 0x2009, 0x0015,
- 0x1078, 0x756c, 0x0078, 0x5568, 0xa08e, 0x0100, 0x00c0, 0x5568,
- 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009, 0x0016, 0x1078, 0x756c,
- 0x0078, 0x5568, 0xa08e, 0x0022, 0x00c0, 0x5568, 0x7030, 0xa08e,
- 0x0300, 0x00c0, 0x54a3, 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009,
- 0x0017, 0x0078, 0x5534, 0xa08e, 0x0500, 0x00c0, 0x54af, 0x7034,
- 0xa005, 0x00c0, 0x5568, 0x2009, 0x0018, 0x0078, 0x5534, 0xa08e,
- 0x2010, 0x00c0, 0x54b7, 0x2009, 0x0019, 0x0078, 0x5534, 0xa08e,
- 0x2110, 0x00c0, 0x54bf, 0x2009, 0x001a, 0x0078, 0x5534, 0xa08e,
- 0x5200, 0x00c0, 0x54cb, 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009,
- 0x001b, 0x0078, 0x5534, 0xa08e, 0x5000, 0x00c0, 0x54d7, 0x7034,
- 0xa005, 0x00c0, 0x5568, 0x2009, 0x001c, 0x0078, 0x5534, 0xa08e,
- 0x1300, 0x00c0, 0x54df, 0x2009, 0x0034, 0x0078, 0x5534, 0xa08e,
- 0x1200, 0x00c0, 0x54eb, 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009,
- 0x0024, 0x0078, 0x5534, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x00c0,
- 0x54f5, 0x2009, 0x002d, 0x0078, 0x5534, 0xa08c, 0xff00, 0xa18e,
- 0x5300, 0x00c0, 0x54ff, 0x2009, 0x002a, 0x0078, 0x5534, 0xa08e,
- 0x0f00, 0x00c0, 0x5507, 0x2009, 0x0020, 0x0078, 0x5534, 0xa08e,
- 0x5300, 0x00c0, 0x550d, 0x0078, 0x552a, 0xa08e, 0x6104, 0x00c0,
- 0x552a, 0x2011, 0xa88d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8,
- 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, 0x047e, 0x2124,
- 0x1078, 0x3579, 0x047f, 0x8108, 0x00f0, 0x551a, 0x2009, 0x0023,
- 0x0078, 0x5534, 0xa08e, 0x6000, 0x00c0, 0x5532, 0x2009, 0x003f,
- 0x0078, 0x5534, 0x2009, 0x001d, 0x017e, 0x2011, 0xa883, 0x2204,
- 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, 0x556a, 0x1078, 0x4499,
- 0x00c0, 0x556a, 0x6612, 0x6516, 0x86ff, 0x0040, 0x555a, 0x017f,
- 0x017e, 0xa186, 0x0017, 0x00c0, 0x555a, 0x6868, 0xa606, 0x00c0,
- 0x555a, 0x686c, 0xa506, 0xa084, 0xff00, 0x00c0, 0x555a, 0x6000,
- 0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x74d7, 0x0040, 0x556d, 0x017f,
- 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x756c,
- 0x0c7f, 0x007c, 0x017f, 0x0078, 0x5568, 0x0c7f, 0x0078, 0x556a,
- 0x0c7e, 0x1078, 0x55d4, 0x00c0, 0x55d2, 0xa184, 0xff00, 0x8007,
- 0xa086, 0x0008, 0x00c0, 0x55d2, 0xa28e, 0x0033, 0x00c0, 0x55a3,
- 0x1078, 0x57b2, 0x0040, 0x55d2, 0x7124, 0x610a, 0x7030, 0xa08e,
- 0x0200, 0x00c0, 0x5595, 0x7034, 0xa005, 0x00c0, 0x55d2, 0x2009,
- 0x0015, 0x1078, 0x756c, 0x0078, 0x55d2, 0xa08e, 0x0100, 0x00c0,
- 0x55d2, 0x7034, 0xa005, 0x00c0, 0x55d2, 0x2009, 0x0016, 0x1078,
- 0x756c, 0x0078, 0x55d2, 0xa28e, 0x0032, 0x00c0, 0x55d2, 0x7030,
- 0xa08e, 0x1400, 0x00c0, 0x55d2, 0x2009, 0x0038, 0x017e, 0x2011,
- 0xa883, 0x2204, 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, 0x55d1,
- 0x1078, 0x4499, 0x00c0, 0x55d1, 0x6612, 0x6516, 0x0c7e, 0x1078,
- 0x74d7, 0x0040, 0x55d0, 0x017f, 0x611a, 0x601f, 0x0004, 0x7120,
- 0x610a, 0x017f, 0x1078, 0x756c, 0x1078, 0x6109, 0x0078, 0x55d2,
- 0x0c7f, 0x017f, 0x0c7f, 0x007c, 0x0f7e, 0x0d7e, 0x027e, 0x017e,
- 0x137e, 0x147e, 0x157e, 0x3c00, 0x007e, 0x2079, 0x0030, 0x2069,
- 0x0200, 0x1078, 0x1c25, 0x00c0, 0x5615, 0x1078, 0x1b15, 0x0040,
- 0x561f, 0x7908, 0xa18c, 0x1fff, 0xa182, 0x0011, 0x00c8, 0x561f,
- 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, 0x2099, 0x020a, 0x53a5,
- 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x7a0c, 0x7808, 0xa080,
- 0x0007, 0xa084, 0x1ff8, 0xa08a, 0x0140, 0x10c8, 0x1328, 0x80ac,
- 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828,
- 0x6828, 0x7803, 0x0004, 0xa294, 0x0070, 0x007f, 0x20e0, 0x157f,
- 0x147f, 0x137f, 0x017f, 0x027f, 0x0d7f, 0x0f7f, 0x007c, 0xa085,
- 0x0001, 0x0078, 0x5615, 0x047e, 0x0e7e, 0x0d7e, 0x2028, 0x2130,
- 0xa696, 0x00ff, 0x00c0, 0x5644, 0xa596, 0xfffd, 0x00c0, 0x5634,
- 0x2009, 0x007f, 0x0078, 0x5677, 0xa596, 0xfffe, 0x00c0, 0x563c,
- 0x2009, 0x007e, 0x0078, 0x5677, 0xa596, 0xfffc, 0x00c0, 0x5644,
- 0x2009, 0x0080, 0x0078, 0x5677, 0x2011, 0x0000, 0x2021, 0x0081,
- 0x20a9, 0x007e, 0x2071, 0xa4b5, 0x2e1c, 0x83ff, 0x00c0, 0x5656,
- 0x82ff, 0x00c0, 0x566b, 0x2410, 0x0078, 0x566b, 0x2368, 0x6f10,
- 0x007e, 0x2100, 0xa706, 0x007f, 0x6b14, 0x00c0, 0x5665, 0xa346,
- 0x00c0, 0x5665, 0x2408, 0x0078, 0x5677, 0x87ff, 0x00c0, 0x566b,
- 0x83ff, 0x0040, 0x5650, 0x8420, 0x8e70, 0x00f0, 0x564c, 0x82ff,
- 0x00c0, 0x5676, 0xa085, 0x0001, 0x0078, 0x5678, 0x2208, 0xa006,
- 0x0d7f, 0x0e7f, 0x047f, 0x007c, 0xa084, 0x0007, 0x0079, 0x5681,
- 0x007c, 0x5689, 0x5689, 0x5689, 0x57c8, 0x5689, 0x568a, 0x56a3,
- 0x56f3, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x56a2, 0x7120, 0x2160,
- 0xac8c, 0x000f, 0x00c0, 0x56a2, 0xac8a, 0xaa00, 0x0048, 0x56a2,
- 0x6854, 0xac02, 0x00c8, 0x56a2, 0x7124, 0x610a, 0x2009, 0x0046,
- 0x1078, 0x756c, 0x007c, 0x0c7e, 0x7110, 0xd1bc, 0x00c0, 0x56f1,
- 0x2011, 0xa883, 0x2204, 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0,
- 0x56f1, 0x1078, 0x4499, 0x00c0, 0x56f1, 0x6612, 0x6516, 0x6000,
- 0xd0ec, 0x00c0, 0x56f1, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286,
- 0x0006, 0x00c0, 0x56d6, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040,
- 0x56f1, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6122,
- 0x2009, 0x0044, 0x1078, 0x756c, 0x0078, 0x56f1, 0x0c7e, 0x1078,
- 0x74d7, 0x017f, 0x0040, 0x56f1, 0x611a, 0x601f, 0x0004, 0x7120,
- 0x610a, 0xa286, 0x0004, 0x00c0, 0x56e9, 0x6007, 0x0005, 0x0078,
- 0x56eb, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5c45, 0x1078,
- 0x6109, 0x0c7f, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x570b, 0x7020,
- 0x2060, 0xac84, 0x000f, 0x00c0, 0x570b, 0xac82, 0xaa00, 0x0048,
- 0x570b, 0x6854, 0xac02, 0x00c8, 0x570b, 0x7124, 0x610a, 0x2009,
- 0x0045, 0x1078, 0x756c, 0x007c, 0x7110, 0xa18c, 0xff00, 0x810f,
- 0xa18e, 0x0000, 0x00c0, 0x571c, 0xa084, 0x000f, 0xa08a, 0x0006,
- 0x00c8, 0x571c, 0x1079, 0x571d, 0x007c, 0x5723, 0x5724, 0x5723,
- 0x5723, 0x5794, 0x57a3, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x572c,
- 0x702c, 0xd084, 0x0040, 0x5793, 0x700c, 0x7108, 0x1078, 0x24e3,
- 0x00c0, 0x5793, 0x1078, 0x4499, 0x00c0, 0x5793, 0x6612, 0x6516,
- 0x6204, 0x7110, 0xd1bc, 0x0040, 0x575e, 0xa28c, 0x00ff, 0xa186,
- 0x0004, 0x0040, 0x5747, 0xa186, 0x0006, 0x00c0, 0x5784, 0x0c7e,
- 0x1078, 0x57b2, 0x0c7f, 0x0040, 0x5793, 0x0c7e, 0x1078, 0x74d7,
- 0x017f, 0x0040, 0x5793, 0x611a, 0x601f, 0x0002, 0x7120, 0x610a,
- 0x2009, 0x0088, 0x1078, 0x756c, 0x0078, 0x5793, 0xa28c, 0x00ff,
- 0xa186, 0x0006, 0x0040, 0x5773, 0xa186, 0x0004, 0x0040, 0x5773,
- 0xa294, 0xff00, 0x8217, 0xa286, 0x0004, 0x0040, 0x5773, 0xa286,
- 0x0006, 0x00c0, 0x5784, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040,
- 0x5793, 0x611a, 0x601f, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088,
- 0x1078, 0x756c, 0x0078, 0x5793, 0x0c7e, 0x1078, 0x74d7, 0x017f,
- 0x0040, 0x5793, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x2009,
- 0x0001, 0x1078, 0x756c, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x57a2,
- 0x1078, 0x57b2, 0x0040, 0x57a2, 0x7124, 0x610a, 0x2009, 0x0089,
- 0x1078, 0x756c, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x57b1, 0x1078,
- 0x57b2, 0x0040, 0x57b1, 0x7124, 0x610a, 0x2009, 0x008a, 0x1078,
- 0x756c, 0x007c, 0x7020, 0x2060, 0xac84, 0x000f, 0x00c0, 0x57c5,
- 0xac82, 0xaa00, 0x0048, 0x57c5, 0x2001, 0xa315, 0x2004, 0xac02,
- 0x00c8, 0x57c5, 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x57c4,
- 0x7110, 0xd1bc, 0x00c0, 0x57de, 0x7024, 0x2060, 0xac84, 0x000f,
- 0x00c0, 0x57de, 0xac82, 0xaa00, 0x0048, 0x57de, 0x6854, 0xac02,
- 0x00c8, 0x57de, 0x2009, 0x0051, 0x1078, 0x756c, 0x007c, 0x2071,
- 0xa5be, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7012,
- 0x7017, 0xaa00, 0x7007, 0x0000, 0x7026, 0x702b, 0x6c4e, 0x7032,
- 0x7037, 0x6ca0, 0x703b, 0x0002, 0x703f, 0x0000, 0x7043, 0xffff,
- 0x7047, 0xffff, 0x007c, 0x2071, 0xa5be, 0x00e0, 0x58c1, 0x2091,
- 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, 0x5873, 0x700f, 0x0361,
- 0x7007, 0x0001, 0x127e, 0x2091, 0x8000, 0x7138, 0x8109, 0x713a,
- 0x00c0, 0x5871, 0x703b, 0x0002, 0x2009, 0x0100, 0x2104, 0xa082,
- 0x0003, 0x00c8, 0x5871, 0x703c, 0xa086, 0x0001, 0x00c0, 0x584e,
- 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x582c,
- 0x6803, 0x1000, 0x0078, 0x5833, 0x6804, 0xa084, 0x1000, 0x0040,
- 0x5833, 0x6803, 0x0100, 0x6803, 0x0000, 0x703f, 0x0000, 0x2069,
- 0xa5ab, 0x6804, 0xa082, 0x0006, 0x00c0, 0x5840, 0x6807, 0x0000,
- 0x6830, 0xa082, 0x0003, 0x00c0, 0x5847, 0x6833, 0x0000, 0x1078,
- 0x6109, 0x1078, 0x61d3, 0x0d7f, 0x0078, 0x5871, 0x0d7e, 0x2069,
- 0xa300, 0x6944, 0x6860, 0xa102, 0x00c8, 0x5870, 0x2069, 0xa5ab,
- 0x6804, 0xa086, 0x0000, 0x00c0, 0x5870, 0x6830, 0xa086, 0x0000,
- 0x00c0, 0x5870, 0x703f, 0x0001, 0x6807, 0x0006, 0x6833, 0x0003,
- 0x2069, 0x0100, 0x6830, 0x689e, 0x2069, 0x0140, 0x6803, 0x0600,
- 0x0d7f, 0x0078, 0x5876, 0x127e, 0x2091, 0x8000, 0x7024, 0xa00d,
- 0x0040, 0x588e, 0x7020, 0x8001, 0x7022, 0x00c0, 0x588e, 0x7023,
- 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, 0x00c0, 0x5889, 0x7028,
- 0x107a, 0x81ff, 0x00c0, 0x588e, 0x7028, 0x107a, 0x7030, 0xa00d,
- 0x0040, 0x589f, 0x702c, 0x8001, 0x702e, 0x00c0, 0x589f, 0x702f,
- 0x0009, 0x8109, 0x7132, 0x00c0, 0x589f, 0x7034, 0x107a, 0x7040,
- 0xa005, 0x0040, 0x58a7, 0x0050, 0x58a7, 0x8001, 0x7042, 0x7044,
- 0xa005, 0x0040, 0x58af, 0x0050, 0x58af, 0x8001, 0x7046, 0x7018,
- 0xa00d, 0x0040, 0x58c0, 0x7008, 0x8001, 0x700a, 0x00c0, 0x58c0,
- 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x58c0, 0x701c, 0x107a,
- 0x127f, 0x7004, 0x0079, 0x58c4, 0x58eb, 0x58ec, 0x5908, 0x0e7e,
- 0x2071, 0xa5be, 0x7018, 0xa005, 0x00c0, 0x58d2, 0x711a, 0x721e,
- 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x2071, 0xa5be,
- 0x701c, 0xa206, 0x00c0, 0x58de, 0x701a, 0x701e, 0x007f, 0x0e7f,
- 0x007c, 0x0e7e, 0x2071, 0xa5be, 0x6088, 0xa102, 0x0048, 0x58e9,
- 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078, 0x4501, 0x00c0,
- 0x58fe, 0x6088, 0x8001, 0x0048, 0x58fe, 0x608a, 0x00c0, 0x58fe,
- 0x127e, 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x8108, 0xa182,
- 0x00ff, 0x0048, 0x5906, 0xa00e, 0x7007, 0x0002, 0x7112, 0x007c,
- 0x7014, 0x2060, 0x127e, 0x2091, 0x8000, 0x603c, 0xa005, 0x0040,
- 0x5917, 0x8001, 0x603e, 0x00c0, 0x5917, 0x1078, 0x8cd7, 0x6014,
- 0xa005, 0x0040, 0x5941, 0x8001, 0x6016, 0x00c0, 0x5941, 0x611c,
- 0xa186, 0x0003, 0x0040, 0x5928, 0xa186, 0x0006, 0x00c0, 0x593f,
- 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x593f, 0xa082,
- 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x5938, 0x2001, 0x1999,
- 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x5941, 0x1078,
- 0x8810, 0x127f, 0xac88, 0x0010, 0x7116, 0x2001, 0xca00, 0xa102,
- 0x0048, 0x594e, 0x7017, 0xaa00, 0x7007, 0x0000, 0x007c, 0x0e7e,
- 0x2071, 0xa5be, 0x7027, 0x07d0, 0x7023, 0x0009, 0x703b, 0x0002,
- 0x0e7f, 0x007c, 0x2001, 0xa5c7, 0x2003, 0x0000, 0x007c, 0x0e7e,
- 0x2071, 0xa5be, 0x7132, 0x702f, 0x0009, 0x0e7f, 0x007c, 0x2011,
- 0xa5ca, 0x2013, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa5be, 0x711a,
- 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x027e, 0x0e7e, 0x0f7e,
- 0x2079, 0xa300, 0x7a34, 0xd294, 0x0040, 0x59a4, 0x2071, 0xa5aa,
- 0x2e14, 0xa0fe, 0x0000, 0x0040, 0x5991, 0xa0fe, 0x0001, 0x0040,
- 0x5995, 0xa0fe, 0x0002, 0x00c0, 0x59a0, 0xa292, 0x0085, 0x0078,
- 0x5997, 0xa292, 0x0005, 0x0078, 0x5997, 0xa292, 0x0002, 0x2272,
- 0x0040, 0x599c, 0x00c8, 0x59a4, 0x2011, 0x8037, 0x1078, 0x3579,
- 0x2011, 0xa5a9, 0x2204, 0x2072, 0x0f7f, 0x0e7f, 0x027f, 0x007c,
- 0x0c7e, 0x2061, 0xa62d, 0x0c7f, 0x007c, 0xa184, 0x000f, 0x8003,
- 0x8003, 0x8003, 0xa080, 0xa62d, 0x2060, 0x007c, 0x6854, 0xa08a,
- 0x199a, 0x0048, 0x59bd, 0x2001, 0x1999, 0xa005, 0x00c0, 0x59cc,
- 0x0c7e, 0x2061, 0xa62d, 0x6014, 0x0c7f, 0xa005, 0x00c0, 0x59d1,
- 0x2001, 0x001e, 0x0078, 0x59d1, 0xa08e, 0xffff, 0x00c0, 0x59d1,
- 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c,
- 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x5a24, 0xd0b4, 0x00c0, 0x59e8,
- 0xd0bc, 0x00c0, 0x5a14, 0x2009, 0x0006, 0x1078, 0x5a43, 0x007c,
- 0xd0fc, 0x0040, 0x59f3, 0xa084, 0x0003, 0x0040, 0x59f3, 0xa086,
- 0x0003, 0x00c0, 0x5a3c, 0x6024, 0xd0d4, 0x0040, 0x59fd, 0xc0d4,
- 0x6026, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xa373, 0x2104,
- 0xd084, 0x0040, 0x5a0f, 0x6118, 0xa188, 0x0027, 0x2104, 0xd08c,
- 0x00c0, 0x5a0f, 0x2009, 0x0042, 0x1078, 0x756c, 0x007c, 0x2009,
- 0x0043, 0x1078, 0x756c, 0x007c, 0xd0fc, 0x0040, 0x5a1f, 0xa084,
- 0x0003, 0x0040, 0x5a1f, 0xa086, 0x0003, 0x00c0, 0x5a3c, 0x2009,
- 0x0042, 0x1078, 0x756c, 0x007c, 0xd0fc, 0x0040, 0x5a32, 0xa084,
- 0x0003, 0xa08e, 0x0002, 0x0040, 0x5a36, 0x2009, 0x0041, 0x1078,
- 0x756c, 0x007c, 0x1078, 0x5a41, 0x0078, 0x5a31, 0x2009, 0x0043,
- 0x1078, 0x756c, 0x0078, 0x5a31, 0x2009, 0x0004, 0x1078, 0x5a43,
- 0x007c, 0x2009, 0x0001, 0x0d7e, 0x6010, 0xa0ec, 0xf000, 0x0040,
- 0x5a6b, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x00c0,
- 0x5a65, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x00c0, 0x5a65,
- 0x0c7e, 0x2061, 0xa62d, 0x6200, 0xd28c, 0x00c0, 0x5a64, 0x6204,
- 0x8210, 0x0048, 0x5a64, 0x6206, 0x0c7f, 0x1078, 0x4982, 0x6010,
- 0xa06d, 0x10c0, 0x59b6, 0x0d7f, 0x007c, 0x157e, 0x0c7e, 0x2061,
- 0xa62d, 0x6000, 0x81ff, 0x0040, 0x5a78, 0xa205, 0x0078, 0x5a79,
- 0xa204, 0x6002, 0x0c7f, 0x157f, 0x007c, 0x6800, 0xd08c, 0x00c0,
- 0x5a89, 0x6808, 0xa005, 0x0040, 0x5a89, 0x8001, 0x680a, 0xa085,
- 0x0001, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e,
- 0x00c8, 0x5a93, 0xa200, 0x00f0, 0x5a8e, 0x8086, 0x818e, 0x007c,
- 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x5ab9, 0xa11a, 0x00c8,
- 0x5ab9, 0x8213, 0x818d, 0x0048, 0x5aac, 0xa11a, 0x00c8, 0x5aad,
- 0x00f0, 0x5aa1, 0x0078, 0x5ab1, 0xa11a, 0x2308, 0x8210, 0x00f0,
- 0x5aa1, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f,
- 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x5ab5, 0x127e,
- 0x2091, 0x2200, 0x2079, 0xa5ab, 0x127f, 0x0d7e, 0x2069, 0xa5ab,
- 0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a,
- 0x0d7f, 0x007c, 0x0c7e, 0x6027, 0x0001, 0x7804, 0xa084, 0x0007,
- 0x0079, 0x5ada, 0x5ae4, 0x5b09, 0x5b64, 0x5aea, 0x5b09, 0x5ae4,
- 0x5ae2, 0x5ae2, 0x1078, 0x1328, 0x1078, 0x595a, 0x1078, 0x6109,
- 0x0c7f, 0x007c, 0x62c0, 0x82ff, 0x00c0, 0x5af0, 0x0c7f, 0x007c,
- 0x2011, 0x4129, 0x1078, 0x58d4, 0x7828, 0xa092, 0x00c8, 0x00c8,
- 0x5aff, 0x8000, 0x782a, 0x1078, 0x4168, 0x0078, 0x5aee, 0x1078,
- 0x4129, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0078,
- 0x5aee, 0x1078, 0x595a, 0x3c00, 0x007e, 0x2011, 0x0209, 0x20e1,
- 0x4000, 0x2214, 0x007f, 0x20e0, 0x82ff, 0x0040, 0x5b27, 0x62c0,
- 0x82ff, 0x00c0, 0x5b27, 0x782b, 0x0000, 0x7824, 0xa065, 0x1040,
- 0x1328, 0x2009, 0x0013, 0x1078, 0x756c, 0x0c7f, 0x007c, 0x3900,
- 0xa082, 0xa6cd, 0x00c8, 0x5b2e, 0x1078, 0x728a, 0x0c7e, 0x7824,
- 0xa065, 0x1040, 0x1328, 0x7804, 0xa086, 0x0004, 0x0040, 0x5ba9,
- 0x7828, 0xa092, 0x2710, 0x00c8, 0x5b44, 0x8000, 0x782a, 0x0c7f,
- 0x1078, 0x6c33, 0x0078, 0x5b25, 0x6104, 0xa186, 0x0003, 0x00c0,
- 0x5b5b, 0x0e7e, 0x2071, 0xa300, 0x70d4, 0x0e7f, 0xd08c, 0x0040,
- 0x5b5b, 0x0c7e, 0x0e7e, 0x2061, 0x0100, 0x2071, 0xa300, 0x1078,
- 0x4171, 0x0e7f, 0x0c7f, 0x1078, 0xa241, 0x2009, 0x0014, 0x1078,
- 0x756c, 0x0c7f, 0x0078, 0x5b25, 0x2001, 0xa5c7, 0x2003, 0x0000,
- 0x62c0, 0x82ff, 0x00c0, 0x5b78, 0x782b, 0x0000, 0x7824, 0xa065,
- 0x1040, 0x1328, 0x2009, 0x0013, 0x1078, 0x75c3, 0x0c7f, 0x007c,
- 0x0c7e, 0x0d7e, 0x3900, 0xa082, 0xa6cd, 0x00c8, 0x5b81, 0x1078,
- 0x728a, 0x7824, 0xa005, 0x1040, 0x1328, 0x781c, 0xa06d, 0x1040,
- 0x1328, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, 0x1078, 0x753d,
- 0x693c, 0x81ff, 0x1040, 0x1328, 0x8109, 0x693e, 0x6854, 0xa015,
- 0x0040, 0x5b9d, 0x7a1e, 0x0078, 0x5b9f, 0x7918, 0x791e, 0x7807,
- 0x0000, 0x7827, 0x0000, 0x0d7f, 0x0c7f, 0x1078, 0x6109, 0x0078,
- 0x5b76, 0x6104, 0xa186, 0x0002, 0x0040, 0x5bb4, 0xa186, 0x0004,
- 0x0040, 0x5bb4, 0x0078, 0x5b38, 0x7808, 0xac06, 0x0040, 0x5b38,
- 0x1078, 0x6010, 0x1078, 0x5c45, 0x0c7f, 0x1078, 0x6109, 0x0078,
- 0x5b25, 0x0c7e, 0x6027, 0x0002, 0x62c8, 0x82ff, 0x00c0, 0x5bdb,
- 0x62c4, 0x82ff, 0x00c0, 0x5bdb, 0x793c, 0xa1e5, 0x0000, 0x0040,
- 0x5bd5, 0x2009, 0x0049, 0x1078, 0x756c, 0x2011, 0xa5ca, 0x2013,
- 0x0000, 0x0c7f, 0x007c, 0x3908, 0xa192, 0xa6cd, 0x00c8, 0x5be2,
- 0x1078, 0x728a, 0x6017, 0x0010, 0x793c, 0x81ff, 0x0040, 0x5bd5,
- 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0, 0x5bf4,
- 0x6017, 0x0012, 0x0078, 0x5bd9, 0x6017, 0x0016, 0x0078, 0x5bd9,
- 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000,
- 0x2c08, 0x2061, 0xa5ab, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005,
- 0x0040, 0x5c13, 0xa080, 0x0003, 0x2102, 0x6112, 0x127f, 0x0c7f,
- 0x017f, 0x007f, 0x007c, 0x6116, 0x6112, 0x0078, 0x5c0e, 0x0d7e,
- 0x2069, 0xa5ab, 0x6000, 0xd0d4, 0x0040, 0x5c2c, 0x6820, 0x8000,
- 0x6822, 0xa086, 0x0001, 0x00c0, 0x5c27, 0x2c00, 0x681e, 0x6804,
- 0xa084, 0x0007, 0x0079, 0x6111, 0xc0d5, 0x6002, 0x6818, 0xa005,
- 0x0040, 0x5c3e, 0x6056, 0x605b, 0x0000, 0x007e, 0x2c00, 0x681a,
- 0x0d7f, 0x685a, 0x2069, 0xa5ab, 0x0078, 0x5c1e, 0x6056, 0x605a,
- 0x2c00, 0x681a, 0x681e, 0x0078, 0x5c1e, 0x007e, 0x017e, 0x0c7e,
- 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xa5ab,
- 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040, 0x5c60, 0xa080,
- 0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c,
- 0x610e, 0x610a, 0x0078, 0x5c5b, 0x0c7e, 0x600f, 0x0000, 0x2c08,
- 0x2061, 0xa5ab, 0x6034, 0xa005, 0x0040, 0x5c74, 0xa080, 0x0003,
- 0x2102, 0x6136, 0x0c7f, 0x007c, 0x613a, 0x6136, 0x0078, 0x5c72,
- 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x017e, 0x007e,
- 0x127e, 0x2071, 0xa5ab, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000,
- 0x8cff, 0x0040, 0x5ced, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
- 0x00c0, 0x5ce8, 0x87ff, 0x0040, 0x5c99, 0x6020, 0xa106, 0x00c0,
- 0x5ce8, 0x703c, 0xac06, 0x00c0, 0x5cab, 0x037e, 0x2019, 0x0001,
- 0x1078, 0x6e6c, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000,
- 0x7047, 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x5cb1, 0x660c,
- 0x763a, 0x7034, 0xac36, 0x00c0, 0x5cbf, 0x2c00, 0xaf36, 0x0040,
- 0x5cbd, 0x2f00, 0x7036, 0x0078, 0x5cbf, 0x7037, 0x0000, 0x660c,
- 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5cc8, 0x7e0e, 0x0078, 0x5cc9,
- 0x2678, 0x600f, 0x0000, 0x1078, 0x8a44, 0x0040, 0x5ce3, 0x6010,
- 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5cf7, 0x6837, 0x0103,
- 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8cb8, 0x1078, 0xa181, 0x1078,
- 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x0c7f, 0x0078, 0x5c88,
- 0x2c78, 0x600c, 0x2060, 0x0078, 0x5c88, 0x127f, 0x007f, 0x017f,
- 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c,
- 0xa086, 0x0006, 0x00c0, 0x5cd6, 0x1078, 0xa181, 0x1078, 0x9e70,
- 0x0078, 0x5ce3, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x0f7e, 0x2031,
- 0x0000, 0x127e, 0x2091, 0x8000, 0x2079, 0xa5ab, 0x7838, 0xa065,
- 0x0040, 0x5d41, 0x600c, 0x007e, 0x600f, 0x0000, 0x783c, 0xac06,
- 0x00c0, 0x5d28, 0x037e, 0x2019, 0x0001, 0x1078, 0x6e6c, 0x7833,
- 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000, 0x037f,
- 0x1078, 0x8a44, 0x0040, 0x5d3c, 0x6010, 0x2068, 0x601c, 0xa086,
- 0x0003, 0x00c0, 0x5d4a, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
- 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x007f, 0x0078,
- 0x5d0f, 0x7e3a, 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f,
- 0x007f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5d33, 0x1078,
- 0x9e70, 0x0078, 0x5d3c, 0x017e, 0x027e, 0x087e, 0x2041, 0x0000,
- 0x1078, 0x5d6d, 0x1078, 0x5e21, 0x087f, 0x027f, 0x017f, 0x007c,
- 0x0f7e, 0x127e, 0x2079, 0xa5ab, 0x2091, 0x8000, 0x1078, 0x5ebc,
- 0x1078, 0x5f32, 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e,
- 0x0c7e, 0x067e, 0x017e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
- 0xa5ab, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5e01, 0x6018,
- 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x5dfc, 0x88ff, 0x0040,
- 0x5d8d, 0x6020, 0xa106, 0x00c0, 0x5dfc, 0x7024, 0xac06, 0x00c0,
- 0x5dbd, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x5db8, 0x1078,
- 0x595a, 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, 0x7188, 0x7027,
- 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040,
- 0x5dad, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824,
- 0xd084, 0x0040, 0x5db5, 0x6827, 0x0001, 0x037f, 0x0078, 0x5dbd,
- 0x6003, 0x0009, 0x630a, 0x0078, 0x5dfc, 0x7014, 0xac36, 0x00c0,
- 0x5dc3, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x5dd1, 0x2c00,
- 0xaf36, 0x0040, 0x5dcf, 0x2f00, 0x7012, 0x0078, 0x5dd1, 0x7013,
- 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5dda, 0x7e0e,
- 0x0078, 0x5ddb, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078,
- 0x8a44, 0x0040, 0x5df5, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5e0a,
- 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8cb8, 0x1078,
- 0xa181, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x1078,
- 0x7045, 0x0c7f, 0x0078, 0x5d7c, 0x2c78, 0x600c, 0x2060, 0x0078,
- 0x5d7c, 0x127f, 0x007f, 0x017f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f,
- 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5e15, 0x1078,
- 0xa181, 0x1078, 0x9e70, 0x0078, 0x5df5, 0x601c, 0xa086, 0x0002,
- 0x00c0, 0x5df5, 0x6004, 0xa086, 0x0085, 0x0040, 0x5de8, 0x0078,
- 0x5df5, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0xa280, 0xa434,
- 0x2004, 0xa065, 0x0040, 0x5eb8, 0x0f7e, 0x0e7e, 0x0d7e, 0x067e,
- 0x2071, 0xa5ab, 0x6654, 0x7018, 0xac06, 0x00c0, 0x5e38, 0x761a,
- 0x701c, 0xac06, 0x00c0, 0x5e44, 0x86ff, 0x00c0, 0x5e43, 0x7018,
- 0x701e, 0x0078, 0x5e44, 0x761e, 0x6058, 0xa07d, 0x0040, 0x5e49,
- 0x7e56, 0xa6ed, 0x0000, 0x0040, 0x5e4f, 0x2f00, 0x685a, 0x6057,
- 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078,
- 0x4410, 0x0040, 0x5eb4, 0x7624, 0x86ff, 0x0040, 0x5ea2, 0xa680,
- 0x0004, 0x2004, 0xad06, 0x00c0, 0x5ea2, 0x0d7e, 0x2069, 0x0100,
- 0x68c0, 0xa005, 0x0040, 0x5e99, 0x1078, 0x595a, 0x1078, 0x6c41,
- 0x68c3, 0x0000, 0x1078, 0x7188, 0x7027, 0x0000, 0x037e, 0x2069,
- 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5e82, 0x6803, 0x0100,
- 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5e8a,
- 0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040,
- 0x5e93, 0x8001, 0x603e, 0x2660, 0x1078, 0x8c01, 0x0c7f, 0x0078,
- 0x5ea2, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f,
- 0x0078, 0x5e57, 0x8dff, 0x0040, 0x5eb0, 0x6837, 0x0103, 0x6b4a,
- 0x6847, 0x0000, 0x1078, 0x8cb8, 0x1078, 0xa181, 0x1078, 0x4982,
- 0x1078, 0x7045, 0x0078, 0x5e57, 0x067f, 0x0d7f, 0x0e7f, 0x0f7f,
- 0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e, 0x067e, 0x0c7e, 0x0d7e,
- 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x5f16, 0x600c, 0x007e,
- 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x5efb, 0x2069, 0x0100,
- 0x68c0, 0xa005, 0x0040, 0x5ef5, 0x1078, 0x595a, 0x1078, 0x6c41,
- 0x68c3, 0x0000, 0x1078, 0x7188, 0x7827, 0x0000, 0x037e, 0x2069,
- 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5eea, 0x6803, 0x0100,
- 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5ef2,
- 0x6827, 0x0001, 0x037f, 0x0078, 0x5efb, 0x6003, 0x0009, 0x630a,
- 0x2c30, 0x0078, 0x5f13, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040,
- 0x5f0f, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5f1d, 0x6837, 0x0103,
- 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078,
- 0x8c01, 0x1078, 0x7045, 0x007f, 0x0078, 0x5ec3, 0x7e16, 0x7e12,
- 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c, 0xa086, 0x0006,
- 0x00c0, 0x5f26, 0x1078, 0x9e70, 0x0078, 0x5f0f, 0x601c, 0xa086,
- 0x0002, 0x00c0, 0x5f0f, 0x6004, 0xa086, 0x0085, 0x0040, 0x5f06,
- 0x0078, 0x5f0f, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x7818, 0xa065,
- 0x0040, 0x5fa0, 0x6054, 0x007e, 0x6057, 0x0000, 0x605b, 0x0000,
- 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x4410, 0x0040, 0x5f9d,
- 0x7e24, 0x86ff, 0x0040, 0x5f8f, 0xa680, 0x0004, 0x2004, 0xad06,
- 0x00c0, 0x5f8f, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040,
- 0x5f86, 0x1078, 0x595a, 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078,
- 0x7188, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384,
- 0x1000, 0x0040, 0x5f6f, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069,
- 0x0100, 0x6824, 0xd084, 0x0040, 0x5f77, 0x6827, 0x0001, 0x037f,
- 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x5f80, 0x8001, 0x603e,
- 0x2660, 0x1078, 0x8c01, 0x0c7f, 0x0078, 0x5f8f, 0x0d7f, 0x0c7e,
- 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x5f44, 0x8dff,
- 0x0040, 0x5f99, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
- 0x4982, 0x1078, 0x7045, 0x0078, 0x5f44, 0x007f, 0x0078, 0x5f37,
- 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x0e7e,
- 0x0d7e, 0x067e, 0x6000, 0xd0dc, 0x0040, 0x5fc4, 0x604c, 0xa06d,
- 0x0040, 0x5fc4, 0x6848, 0xa606, 0x00c0, 0x5fc4, 0x2071, 0xa5ab,
- 0x7024, 0xa035, 0x0040, 0x5fc4, 0xa080, 0x0004, 0x2004, 0xad06,
- 0x00c0, 0x5fc4, 0x1078, 0x5fc8, 0x067f, 0x0d7f, 0x0e7f, 0x007c,
- 0x0f7e, 0x2079, 0x0100, 0x78c0, 0xa005, 0x00c0, 0x5fd7, 0x0c7e,
- 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x600e, 0x1078,
- 0x6c41, 0x78c3, 0x0000, 0x1078, 0x7188, 0x7027, 0x0000, 0x037e,
- 0x2079, 0x0140, 0x7b04, 0xa384, 0x1000, 0x0040, 0x5feb, 0x7803,
- 0x0100, 0x7803, 0x0000, 0x2079, 0x0100, 0x7824, 0xd084, 0x0040,
- 0x5ff3, 0x7827, 0x0001, 0x1078, 0x7188, 0x037f, 0x1078, 0x4410,
- 0x0c7e, 0x603c, 0xa005, 0x0040, 0x5fff, 0x8001, 0x603e, 0x2660,
- 0x1078, 0x753d, 0x0c7f, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
- 0x1078, 0x8cb8, 0x1078, 0x4982, 0x1078, 0x7045, 0x0f7f, 0x007c,
- 0x0e7e, 0x0c7e, 0x2071, 0xa5ab, 0x7004, 0xa084, 0x0007, 0x0079,
- 0x6019, 0x6023, 0x6026, 0x603f, 0x605b, 0x60a0, 0x6023, 0x6023,
- 0x6021, 0x1078, 0x1328, 0x0c7f, 0x0e7f, 0x007c, 0x7024, 0xa065,
- 0x0040, 0x6034, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0040,
- 0x603b, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000,
- 0x0c7f, 0x0e7f, 0x007c, 0x7216, 0x7212, 0x0078, 0x6034, 0x6018,
- 0x2060, 0x1078, 0x4410, 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001,
- 0x7022, 0x0040, 0x6050, 0x6054, 0xa015, 0x0040, 0x6057, 0x721e,
- 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7218,
- 0x721e, 0x0078, 0x6050, 0x7024, 0xa065, 0x0040, 0x609d, 0x700c,
- 0xac06, 0x00c0, 0x6072, 0x1078, 0x7045, 0x600c, 0xa015, 0x0040,
- 0x606e, 0x720e, 0x600f, 0x0000, 0x0078, 0x609b, 0x720e, 0x720a,
- 0x0078, 0x609b, 0x7014, 0xac06, 0x00c0, 0x6085, 0x1078, 0x7045,
- 0x600c, 0xa015, 0x0040, 0x6081, 0x7216, 0x600f, 0x0000, 0x0078,
- 0x609b, 0x7216, 0x7212, 0x0078, 0x609b, 0x6018, 0x2060, 0x1078,
- 0x4410, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x7045, 0x701c, 0xa065,
- 0x0040, 0x609b, 0x6054, 0xa015, 0x0040, 0x6099, 0x721e, 0x0078,
- 0x609b, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c,
- 0x7024, 0xa065, 0x0040, 0x60ad, 0x1078, 0x7045, 0x600c, 0xa015,
- 0x0040, 0x60b4, 0x720e, 0x600f, 0x0000, 0x1078, 0x7188, 0x7027,
- 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, 0x0078, 0x60ad,
- 0x0d7e, 0x2069, 0xa5ab, 0x6830, 0xa084, 0x0003, 0x0079, 0x60c0,
- 0x60c6, 0x60c8, 0x60ee, 0x60c6, 0x1078, 0x1328, 0x0d7f, 0x007c,
- 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x60e4, 0x683c, 0xa065,
- 0x0040, 0x60d9, 0x600c, 0xa015, 0x0040, 0x60e0, 0x6a3a, 0x600f,
- 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c7f, 0x0d7f, 0x007c,
- 0x683a, 0x6836, 0x0078, 0x60d9, 0x6843, 0x0000, 0x6838, 0xa065,
- 0x0040, 0x60d9, 0x6003, 0x0003, 0x0078, 0x60d9, 0x0c7e, 0x6843,
- 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0040, 0x6106, 0x600c,
- 0xa015, 0x0040, 0x6102, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000,
- 0x0078, 0x6106, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, 0x0d7f,
- 0x007c, 0x0d7e, 0x2069, 0xa5ab, 0x6804, 0xa084, 0x0007, 0x0079,
- 0x6111, 0x611b, 0x61c2, 0x61c2, 0x61c2, 0x61c2, 0x61c4, 0x61c2,
- 0x6119, 0x1078, 0x1328, 0x6820, 0xa005, 0x00c0, 0x6121, 0x0d7f,
- 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x6130, 0x6807, 0x0004,
- 0x6826, 0x682b, 0x0000, 0x1078, 0x620a, 0x0c7f, 0x0d7f, 0x007c,
- 0x6814, 0xa065, 0x0040, 0x613e, 0x6807, 0x0001, 0x6826, 0x682b,
- 0x0000, 0x1078, 0x620a, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, 0x037e,
- 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x61bd, 0x704c, 0xa00d, 0x0040,
- 0x614d, 0x7088, 0xa005, 0x0040, 0x6165, 0x7054, 0xa075, 0x0040,
- 0x6156, 0xa20e, 0x0040, 0x61bd, 0x0078, 0x615b, 0x6818, 0xa20e,
- 0x0040, 0x61bd, 0x2070, 0x704c, 0xa00d, 0x0040, 0x614d, 0x7088,
- 0xa005, 0x00c0, 0x614d, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302,
- 0x00c8, 0x614d, 0x1078, 0x750c, 0x0040, 0x61bd, 0x8318, 0x733e,
- 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff,
- 0x6032, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004,
- 0xa08a, 0x199a, 0x0048, 0x6186, 0x2001, 0x1999, 0x8003, 0x801b,
- 0x831b, 0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc,
- 0x0040, 0x619f, 0x7100, 0xd1f4, 0x0040, 0x619b, 0x7114, 0xa18c,
- 0x00ff, 0x0078, 0x61a4, 0x2009, 0x0000, 0x0078, 0x61a4, 0xa1e0,
- 0x293f, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078,
- 0x679b, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26,
- 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040,
- 0x0f7f, 0x0e7f, 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f,
- 0x0078, 0x61bb, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040,
- 0x61d0, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x620a,
- 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0xa5ab, 0x6830,
- 0xa086, 0x0000, 0x00c0, 0x61f1, 0x6838, 0xa07d, 0x0040, 0x61f1,
- 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x127e, 0x0f7e, 0x2091,
- 0x2200, 0x027f, 0x1078, 0x1d28, 0x00c0, 0x61f4, 0x127f, 0x1078,
- 0x6ae5, 0x0d7f, 0x0f7f, 0x007c, 0x127f, 0x6843, 0x0000, 0x7803,
- 0x0002, 0x780c, 0xa015, 0x0040, 0x6206, 0x6a3a, 0x780f, 0x0000,
- 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x61f1, 0x683a, 0x6836,
- 0x0078, 0x6200, 0x601c, 0xa084, 0x000f, 0x1079, 0x6210, 0x007c,
- 0x6219, 0x621e, 0x663f, 0x6758, 0x621e, 0x663f, 0x6758, 0x6219,
- 0x621e, 0x1078, 0x6010, 0x1078, 0x6109, 0x007c, 0x157e, 0x137e,
- 0x147e, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0044, 0x10c8, 0x1328,
- 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x623b, 0x7900, 0xd1f4,
- 0x0040, 0x6237, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x6240, 0x2009,
- 0x0000, 0x0078, 0x6240, 0xa1f8, 0x293f, 0x2f0c, 0xa18c, 0x00ff,
- 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, 0x00c8, 0x6292,
- 0x1079, 0x6250, 0x0f7f, 0x0c7f, 0x147f, 0x137f, 0x157f, 0x007c,
- 0x62f8, 0x6340, 0x6368, 0x6403, 0x6433, 0x643b, 0x6462, 0x6473,
- 0x6484, 0x648c, 0x64a4, 0x648c, 0x650f, 0x6473, 0x6530, 0x6538,
- 0x6484, 0x6538, 0x6549, 0x6290, 0x6290, 0x6290, 0x6290, 0x6290,
- 0x6290, 0x6290, 0x6290, 0x6290, 0x6290, 0x6290, 0x6d05, 0x6d2a,
- 0x6d3f, 0x6d62, 0x6d83, 0x6462, 0x6290, 0x6462, 0x648c, 0x6290,
- 0x6368, 0x6403, 0x6290, 0x72ac, 0x648c, 0x6290, 0x72cc, 0x648c,
- 0x6290, 0x6290, 0x62f3, 0x62a1, 0x6290, 0x72f1, 0x7368, 0x7450,
- 0x6290, 0x7461, 0x645c, 0x747d, 0x6290, 0x6d98, 0x6290, 0x6290,
- 0x1078, 0x1328, 0x2100, 0x1079, 0x629b, 0x0f7f, 0x0c7f, 0x147f,
- 0x137f, 0x157f, 0x007c, 0x629f, 0x629f, 0x629f, 0x62d5, 0x1078,
- 0x1328, 0x0d7e, 0x20a1, 0x020b, 0x1078, 0x6567, 0x7810, 0x2068,
- 0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x6850, 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x60c3, 0x0018, 0x1078, 0x6c2d, 0x0d7f, 0x007c, 0x0d7e, 0x7818,
- 0x2068, 0x68a0, 0xa082, 0x007e, 0x0048, 0x62d2, 0xa085, 0x0001,
- 0x0d7f, 0x007c, 0xa006, 0x0078, 0x62d0, 0x0d7e, 0x20a1, 0x020b,
- 0x1078, 0x6567, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8,
- 0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814,
- 0x20a2, 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, 0x0010, 0x1078,
- 0x6c2d, 0x0d7f, 0x007c, 0x6030, 0x609a, 0x1078, 0x6c2d, 0x007c,
- 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, 0x5200, 0x20a3, 0x0000,
- 0x0d7e, 0x2069, 0xa351, 0x6804, 0xd084, 0x0040, 0x6312, 0x6828,
- 0x20a3, 0x0000, 0x017e, 0x1078, 0x24fa, 0x21a2, 0x017f, 0x0d7f,
- 0x0078, 0x6317, 0x0d7f, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9,
- 0x0004, 0x2099, 0xa305, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa301,
- 0x53a6, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0048,
- 0x6331, 0x2001, 0xa31a, 0x20a6, 0x2001, 0xa31b, 0x20a6, 0x0078,
- 0x6337, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, 0x6c2d, 0x007c,
- 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, 0x0500, 0x20a3, 0x0000,
- 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0048, 0x6358,
- 0x2001, 0xa31a, 0x20a6, 0x2001, 0xa31b, 0x20a6, 0x0078, 0x635e,
- 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a9, 0x0004,
- 0x2099, 0xa305, 0x53a6, 0x60c3, 0x0010, 0x1078, 0x6c2d, 0x007c,
- 0x20a1, 0x020b, 0x1078, 0x6567, 0x0c7e, 0x7818, 0x2060, 0x2001,
- 0x0000, 0x1078, 0x48a2, 0x0c7f, 0x7818, 0xa080, 0x0028, 0x2004,
- 0xa086, 0x007e, 0x00c0, 0x6383, 0x20a3, 0x0400, 0x620c, 0xc2b4,
- 0x620e, 0x0078, 0x6385, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818,
- 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x63d2, 0x2099,
- 0xa58c, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, 0xa084, 0x3fff,
- 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0xa305, 0x53a6,
- 0x20a9, 0x0004, 0x2099, 0xa301, 0x53a6, 0x20a9, 0x0010, 0x20a3,
- 0x0000, 0x00f0, 0x63af, 0x2099, 0xa594, 0x3304, 0xc0dd, 0x20a2,
- 0x2001, 0xa371, 0x2004, 0xd0e4, 0x0040, 0x63ca, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, 0x20a9, 0x0004,
- 0x0078, 0x63cc, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x00f0, 0x63cc,
- 0x0078, 0x63f2, 0x2099, 0xa58c, 0x20a9, 0x0008, 0x53a6, 0x20a9,
- 0x0004, 0x2099, 0xa305, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa301,
- 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x63e3, 0x20a9,
- 0x0008, 0x20a3, 0x0000, 0x00f0, 0x63e9, 0x2099, 0xa594, 0x20a9,
- 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x63f4,
- 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x63fa, 0x60c3, 0x0074,
- 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3,
- 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006,
- 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa351,
- 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x641f, 0xa085, 0x0020, 0xd1a4,
- 0x0040, 0x6424, 0xa085, 0x0010, 0xa085, 0x0002, 0x0d7e, 0x0078,
- 0x64ed, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
- 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3,
- 0x5000, 0x0078, 0x6385, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3,
- 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
- 0x0014, 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65ef,
- 0x0078, 0x6466, 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0200,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004,
- 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3,
- 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3,
- 0x0008, 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65f8,
- 0x20a3, 0x0200, 0x0078, 0x6385, 0x20a1, 0x020b, 0x1078, 0x65f8,
- 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, 0x0040, 0x649b,
- 0x20a2, 0x0078, 0x649d, 0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3,
- 0x0008, 0x1078, 0x6c2d, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078,
- 0x65f8, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818,
- 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x64ca, 0x6998, 0xa184,
- 0xc000, 0x00c0, 0x64c6, 0xd1ec, 0x0040, 0x64c2, 0x20a3, 0x2100,
- 0x0078, 0x64cc, 0x20a3, 0x0100, 0x0078, 0x64cc, 0x20a3, 0x0400,
- 0x0078, 0x64cc, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2, 0x20a2,
- 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa351, 0x7904, 0x0f7f, 0xd1ac,
- 0x00c0, 0x64dc, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x64e1, 0xa085,
- 0x0010, 0x2009, 0xa373, 0x210c, 0xd184, 0x0040, 0x64eb, 0x699c,
- 0xd18c, 0x0040, 0x64ed, 0xa085, 0x0002, 0x027e, 0x2009, 0xa371,
- 0x210c, 0xd1e4, 0x0040, 0x64fb, 0xc0c5, 0xa094, 0x0030, 0xa296,
- 0x0010, 0x0040, 0x6505, 0xd1ec, 0x0040, 0x6505, 0xa094, 0x0030,
- 0xa296, 0x0010, 0x0040, 0x6505, 0xc0bd, 0x027f, 0x20a2, 0x20a2,
- 0x20a2, 0x60c3, 0x0014, 0x1078, 0x6c2d, 0x0d7f, 0x007c, 0x20a1,
- 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3,
- 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x6c2d, 0x007c,
- 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0200, 0x0078, 0x62fe,
- 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0100, 0x20a3, 0x0000,
- 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x1078, 0x6c2d,
- 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x1078,
- 0x65f8, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3,
- 0x0000, 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x007c, 0x027e, 0x037e,
- 0x047e, 0x2019, 0x3200, 0x2021, 0x0800, 0x0078, 0x656e, 0x027e,
- 0x037e, 0x047e, 0x2019, 0x2200, 0x2021, 0x0100, 0x20e1, 0x9080,
- 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e,
- 0x00c0, 0x6581, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffe, 0x0078,
- 0x65b6, 0xa286, 0x007f, 0x00c0, 0x658d, 0x0d7e, 0xa385, 0x00ff,
- 0x20a2, 0x20a3, 0xfffd, 0x0078, 0x65a4, 0xd2bc, 0x0040, 0x65ac,
- 0xa286, 0x0080, 0x0d7e, 0x00c0, 0x659c, 0xa385, 0x00ff, 0x20a2,
- 0x20a3, 0xfffc, 0x0078, 0x65a4, 0xa2e8, 0xa434, 0x2d6c, 0x6810,
- 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68,
- 0x2da6, 0x0d7f, 0x0078, 0x65ba, 0x0d7e, 0xa2e8, 0xa434, 0x2d6c,
- 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000,
- 0x6230, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x047f, 0x037f, 0x20a3,
- 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3,
- 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e,
- 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, 0xfffc,
- 0x22a2, 0x0d7e, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
- 0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078, 0x65c1, 0x20a3, 0x0100,
- 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x007c, 0x027e,
- 0x037e, 0x047e, 0x2019, 0x3300, 0x2021, 0x0800, 0x0078, 0x65ff,
- 0x027e, 0x037e, 0x047e, 0x2019, 0x2300, 0x2021, 0x0100, 0x20e1,
- 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092,
- 0x007e, 0x0048, 0x661c, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810,
- 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68,
- 0x2da6, 0x0d7f, 0x0078, 0x662a, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c,
- 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000,
- 0x6230, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, 0x0000, 0x047f,
- 0x037f, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
- 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0c7e,
- 0x0f7e, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1328, 0xa08a, 0x008c,
- 0x10c8, 0x1328, 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x665d,
- 0x7900, 0xd1f4, 0x0040, 0x6659, 0x7914, 0xa18c, 0x00ff, 0x0078,
- 0x6662, 0x2009, 0x0000, 0x0078, 0x6662, 0xa1f8, 0x293f, 0x2f0c,
- 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085,
- 0x1079, 0x666d, 0x0f7f, 0x0c7f, 0x007c, 0x6676, 0x6681, 0x669c,
- 0x6674, 0x6674, 0x6674, 0x6676, 0x1078, 0x1328, 0x147e, 0x20a1,
- 0x020b, 0x1078, 0x66af, 0x60c3, 0x0000, 0x1078, 0x6c2d, 0x147f,
- 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078, 0x66e3, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000,
- 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c,
- 0x1078, 0x6c2d, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078,
- 0x6724, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x60c3, 0x0004, 0x1078, 0x6c2d, 0x147f, 0x007c, 0x027e,
- 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
- 0xa092, 0x007e, 0x0048, 0x66ce, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c,
- 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a,
- 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x66dd, 0x0d7e, 0xa0e8,
- 0xa434, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2,
- 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0009, 0x20a3,
- 0x0000, 0x0078, 0x65c1, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
- 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x6702,
- 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2,
- 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
- 0x0078, 0x6711, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085,
- 0x8400, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230,
- 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2,
- 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7a10, 0x22a2, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1,
- 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048,
- 0x6743, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x8500,
- 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6,
- 0x0d7f, 0x0078, 0x6752, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810,
- 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000,
- 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x0078, 0x6715,
- 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040, 0x1048, 0x1328,
- 0xa08a, 0x0053, 0x10c8, 0x1328, 0x7918, 0x2160, 0x61a0, 0xd1bc,
- 0x0040, 0x6777, 0x6100, 0xd1f4, 0x0040, 0x6773, 0x6114, 0xa18c,
- 0x00ff, 0x0078, 0x677c, 0x2009, 0x0000, 0x0078, 0x677c, 0xa1e0,
- 0x293f, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082,
- 0x0040, 0x1079, 0x6786, 0x0f7f, 0x0c7f, 0x007c, 0x679b, 0x68a9,
- 0x684a, 0x6a59, 0x6799, 0x6799, 0x6799, 0x6799, 0x6799, 0x6799,
- 0x6799, 0x6f5e, 0x6f6f, 0x6f80, 0x6f91, 0x6799, 0x748e, 0x6799,
- 0x6f4d, 0x1078, 0x1328, 0x0d7e, 0x157e, 0x147e, 0x780b, 0xffff,
- 0x20a1, 0x020b, 0x1078, 0x6806, 0x7910, 0x2168, 0x6948, 0x7922,
- 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x000f,
- 0x00c0, 0x67b6, 0x2001, 0x0005, 0x0078, 0x67c0, 0xd184, 0x0040,
- 0x67bd, 0x2001, 0x0004, 0x0078, 0x67c0, 0xa084, 0x0006, 0x8004,
- 0x017e, 0x2008, 0x7830, 0xa084, 0x00ff, 0x8007, 0xa105, 0x017f,
- 0x20a2, 0xd1ac, 0x0040, 0x67d0, 0x20a3, 0x0002, 0x0078, 0x67dc,
- 0xd1b4, 0x0040, 0x67d7, 0x20a3, 0x0001, 0x0078, 0x67dc, 0x20a3,
- 0x0000, 0x2230, 0x0078, 0x67de, 0x6a80, 0x6e7c, 0x20a9, 0x0008,
- 0xad80, 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, 0x00f0, 0x67e2,
- 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084,
- 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xa5c7, 0x2003, 0x07d0,
- 0x2001, 0xa5c6, 0x2003, 0x0009, 0x2001, 0xa5cc, 0x2003, 0x0002,
- 0x1078, 0x157e, 0x147f, 0x157f, 0x0d7f, 0x007c, 0x20e1, 0x9080,
- 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294,
- 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc,
- 0x0040, 0x682c, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085,
- 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68,
- 0x2da6, 0x0d7f, 0x0078, 0x683b, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c,
- 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3,
- 0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2,
- 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1, 0x020b,
- 0x1078, 0x686a, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2,
- 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2,
- 0x20a2, 0x60c3, 0x000c, 0x1078, 0x6c2d, 0x147f, 0x137f, 0x157f,
- 0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
- 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6888, 0x0d7e, 0xa0e8,
- 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2,
- 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6897,
- 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2,
- 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3,
- 0x0889, 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000,
- 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f,
- 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x7810, 0xa06d, 0x1078,
- 0x488f, 0x0040, 0x68bd, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020,
- 0x00c0, 0x68bd, 0x7824, 0xc0cd, 0x7826, 0x20a1, 0x020b, 0x1078,
- 0x6a12, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810,
- 0xa084, 0xf000, 0x00c0, 0x68d4, 0x7810, 0xa084, 0x0700, 0x8007,
- 0x1079, 0x68dc, 0x0078, 0x68d7, 0xa006, 0x1079, 0x68dc, 0x147f,
- 0x137f, 0x157f, 0x0d7f, 0x007c, 0x68e6, 0x697e, 0x6989, 0x69b3,
- 0x69c7, 0x69e3, 0x69ee, 0x68e4, 0x1078, 0x1328, 0x017e, 0x037e,
- 0x694c, 0xa18c, 0x0003, 0x0040, 0x68f1, 0xa186, 0x0003, 0x00c0,
- 0x6900, 0x6b78, 0x7824, 0xd0cc, 0x0040, 0x68f7, 0xc3e5, 0x23a2,
- 0x6868, 0x20a2, 0x6864, 0x20a2, 0x037f, 0x017f, 0x0078, 0x69be,
- 0xa186, 0x0001, 0x10c0, 0x1328, 0x6b78, 0x7824, 0xd0cc, 0x0040,
- 0x690a, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2,
- 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384,
- 0x0300, 0x0040, 0x6978, 0xd3c4, 0x0040, 0x6920, 0x687c, 0xa108,
- 0xd3cc, 0x0040, 0x6925, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d,
- 0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x692a,
- 0x157f, 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x6978,
- 0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x007e, 0x7818,
- 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6958, 0x0d7e, 0xa0e8,
- 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2,
- 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6967,
- 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
- 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x007f,
- 0x7b24, 0xd3cc, 0x0040, 0x6970, 0x20a3, 0x0889, 0x0078, 0x6972,
- 0x20a3, 0x0898, 0x20a2, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000,
- 0x61c2, 0x037f, 0x017f, 0x1078, 0x6c2d, 0x007c, 0x2011, 0x0008,
- 0x7824, 0xd0cc, 0x0040, 0x6985, 0xc2e5, 0x22a2, 0xa016, 0x0078,
- 0x69bc, 0x2011, 0x0302, 0x7824, 0xd0cc, 0x0040, 0x6990, 0xc2e5,
- 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2,
- 0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000,
- 0x20a3, 0x0500, 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3,
- 0x2500, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032,
- 0x1078, 0x6c2d, 0x007c, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x0040,
- 0x69ba, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
- 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x1078, 0x6c2d, 0x007c, 0x2011,
- 0x0100, 0x7824, 0xd0cc, 0x0040, 0x69ce, 0xc2e5, 0x22a2, 0xa016,
- 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2,
- 0x7834, 0xa084, 0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, 0x0020,
- 0x1078, 0x6c2d, 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0040,
- 0x69ea, 0xc2e5, 0x22a2, 0xa016, 0x0078, 0x69bc, 0x037e, 0x7b10,
- 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x6a01,
- 0x7824, 0xd0cc, 0x0040, 0x69fd, 0xc2e5, 0x22a2, 0x037f, 0x0078,
- 0x69bc, 0x047e, 0x2021, 0x0800, 0x007e, 0x7824, 0xd0cc, 0x007f,
- 0x0040, 0x6a0b, 0xc4e5, 0x24a2, 0x047f, 0x22a2, 0x20a2, 0x037f,
- 0x0078, 0x69be, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
- 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6a30, 0x0d7e, 0xa0e8,
- 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2,
- 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6a3f,
- 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
- 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x7824,
- 0xd0cc, 0x0040, 0x6a47, 0x20a3, 0x0889, 0x0078, 0x6a49, 0x20a3,
- 0x0898, 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000,
- 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f,
- 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x017e, 0x037e, 0x7810,
- 0xa084, 0x0700, 0x8007, 0x1079, 0x6a6c, 0x037f, 0x017f, 0x147f,
- 0x137f, 0x157f, 0x0d7f, 0x007c, 0x6a74, 0x6a74, 0x6a76, 0x6a74,
- 0x6a74, 0x6a74, 0x6a9b, 0x6a74, 0x1078, 0x1328, 0x7910, 0xa18c,
- 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003,
- 0x1078, 0x6aa5, 0x0d7e, 0x2069, 0xa351, 0x6804, 0xd0bc, 0x0040,
- 0x6a90, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, 0x6a92,
- 0x20a3, 0x3f00, 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001,
- 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078,
- 0x6aa5, 0x20a3, 0x7f00, 0x0078, 0x6a93, 0x027e, 0x20e1, 0x9080,
- 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040,
- 0x6ac3, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0100,
- 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6,
- 0x0d7f, 0x0078, 0x6ad2, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810,
- 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000,
- 0x6230, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x1078,
- 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e,
- 0x057e, 0x047e, 0x037e, 0x2061, 0x0100, 0x2071, 0xa300, 0x6130,
- 0x7818, 0x2068, 0x68a0, 0x2028, 0xd0bc, 0x00c0, 0x6afc, 0x6910,
- 0x6a14, 0x6430, 0x0078, 0x6b00, 0x6910, 0x6a14, 0x7368, 0x746c,
- 0x781c, 0xa086, 0x0006, 0x0040, 0x6b5f, 0xd5bc, 0x0040, 0x6b10,
- 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6b17,
- 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x6073,
- 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e,
- 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086,
- 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6,
- 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5,
- 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x6b49, 0x6a00, 0xd2f4,
- 0x0040, 0x6b47, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6b49, 0x2011,
- 0x0000, 0x629e, 0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084,
- 0xfff0, 0xa005, 0x0040, 0x6b56, 0x2009, 0x1b58, 0x1078, 0x595f,
- 0x037f, 0x047f, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810,
- 0x2070, 0x704c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x6bb7,
- 0xd5bc, 0x0040, 0x6b73, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a,
- 0x646e, 0x0078, 0x6b7a, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b,
- 0x0000, 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000,
- 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00,
- 0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080,
- 0x60c6, 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080,
- 0x7928, 0xa109, 0x792a, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af,
- 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x6bb2, 0x6a00,
- 0xd2f4, 0x0040, 0x6bb0, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6bb2,
- 0x2011, 0x0000, 0x629e, 0x6017, 0x0012, 0x0078, 0x6b4c, 0xd5bc,
- 0x0040, 0x6bc2, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e,
- 0x0078, 0x6bc9, 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000,
- 0x646e, 0x1078, 0x488f, 0x0040, 0x6bdf, 0x0d7e, 0x7810, 0xa06d,
- 0x684c, 0x0d7f, 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6bdf,
- 0x7824, 0xc0cd, 0x7826, 0x6073, 0x0889, 0x0078, 0x6be1, 0x6073,
- 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e,
- 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082,
- 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca,
- 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000,
- 0xa582, 0x0080, 0x0048, 0x6c0f, 0x6a00, 0xd2f4, 0x0040, 0x6c0d,
- 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6c0f, 0x2011, 0x0000, 0x629e,
- 0x7824, 0xd0cc, 0x0040, 0x6c18, 0x6017, 0x0016, 0x0078, 0x6b4c,
- 0x6017, 0x0012, 0x0078, 0x6b4c, 0x7a18, 0xa280, 0x0023, 0x2014,
- 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e, 0x2069,
- 0xa5ab, 0x6843, 0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x60a3,
- 0x0056, 0x60a7, 0x9575, 0x1078, 0x6c38, 0x1078, 0x594f, 0x007c,
- 0x007e, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x007f,
- 0x007c, 0x007e, 0x0c7e, 0x2061, 0x0100, 0x6014, 0xa084, 0x0004,
- 0xa085, 0x0008, 0x6016, 0x0c7f, 0x007f, 0x007c, 0x0c7e, 0x0d7e,
- 0x017e, 0x027e, 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194,
- 0x4000, 0x0040, 0x6c89, 0x1078, 0x6c41, 0x6803, 0x1000, 0x6803,
- 0x0000, 0x0c7e, 0x2061, 0xa5ab, 0x6128, 0xa192, 0x00c8, 0x00c8,
- 0x6c76, 0x8108, 0x612a, 0x6124, 0x0c7f, 0x81ff, 0x0040, 0x6c84,
- 0x1078, 0x594f, 0x1078, 0x6c38, 0x0078, 0x6c84, 0x6124, 0xa1e5,
- 0x0000, 0x0040, 0x6c81, 0x1078, 0xa241, 0x2009, 0x0014, 0x1078,
- 0x756c, 0x0c7f, 0x0078, 0x6c84, 0x027f, 0x017f, 0x0d7f, 0x0c7f,
- 0x007c, 0x2001, 0xa5c7, 0x2004, 0xa005, 0x00c0, 0x6c84, 0x0c7e,
- 0x2061, 0xa5ab, 0x6128, 0xa192, 0x0003, 0x00c8, 0x6c76, 0x8108,
- 0x612a, 0x0c7f, 0x1078, 0x594f, 0x1078, 0x4171, 0x0078, 0x6c84,
- 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x5967, 0x2071,
- 0xa5ab, 0x713c, 0x81ff, 0x0040, 0x6cca, 0x2061, 0x0100, 0x2069,
- 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x6cd0, 0x6803, 0x1000,
- 0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x6e6c, 0x037f,
- 0x713c, 0x2160, 0x1078, 0xa241, 0x2009, 0x004a, 0x1078, 0x756c,
- 0x0078, 0x6cca, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c,
- 0x0078, 0x6cba, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e, 0x047e,
- 0x007e, 0x127e, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, 0x2071,
- 0xa5ab, 0x7018, 0x2068, 0x8dff, 0x0040, 0x6cfc, 0x68a0, 0xa406,
- 0x0040, 0x6cee, 0x6854, 0x2068, 0x0078, 0x6ce3, 0x6010, 0x2060,
- 0x643c, 0x6540, 0x6e48, 0x2d60, 0x1078, 0x466a, 0x0040, 0x6cfc,
- 0x1078, 0x7045, 0xa085, 0x0001, 0x127f, 0x007f, 0x047f, 0x057f,
- 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x20a1, 0x020b, 0x1078,
- 0x6567, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x781c,
- 0xa086, 0x0004, 0x00c0, 0x6d17, 0x6098, 0x0078, 0x6d18, 0x6030,
- 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, 0xa006,
- 0x20a2, 0x00f0, 0x6d20, 0x20a2, 0x20a2, 0x60c3, 0x002c, 0x1078,
- 0x6c2d, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x6567,
- 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2,
- 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x147f, 0x157f, 0x007c, 0x157e,
- 0x147e, 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0200, 0x20a3,
- 0x0000, 0x20a9, 0x0006, 0x2011, 0xa340, 0x2019, 0xa341, 0x23a6,
- 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x00f0, 0x6d4f, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, 0x6c2d, 0x147f,
- 0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b,
- 0x1078, 0x65cf, 0x1078, 0x65e6, 0x7810, 0xa080, 0x0000, 0x2004,
- 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6,
- 0xa080, 0x0004, 0x8003, 0x60c2, 0x1078, 0x6c2d, 0x027f, 0x017f,
- 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078,
- 0x6567, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808,
- 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x147f, 0x157f, 0x007c,
- 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x6567,
- 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808,
- 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x1078, 0x6c2d,
- 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x0e7e, 0x0c7e, 0x007e,
- 0x127e, 0x2091, 0x8000, 0x2071, 0xa5ab, 0x700c, 0x2060, 0x8cff,
- 0x0040, 0x6dd1, 0x1078, 0x8c3b, 0x00c0, 0x6dc8, 0x1078, 0x7a05,
- 0x600c, 0x007e, 0x1078, 0x753d, 0x1078, 0x7045, 0x0c7f, 0x0078,
- 0x6dbf, 0x700f, 0x0000, 0x700b, 0x0000, 0x127f, 0x007f, 0x0c7f,
- 0x0e7f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e,
- 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079,
- 0x0140, 0x2071, 0xa5ab, 0x7024, 0x2060, 0x8cff, 0x0040, 0x6e2a,
- 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, 0x595a, 0x2009, 0x0013,
- 0x1078, 0x756c, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x6e0d,
- 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x6e1f, 0x7803,
- 0x1000, 0x7803, 0x0000, 0x0078, 0x6e1f, 0xd084, 0x0040, 0x6e14,
- 0x6827, 0x0001, 0x0078, 0x6e16, 0x00f0, 0x6dfc, 0x7804, 0xa084,
- 0x1000, 0x0040, 0x6e1f, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824,
- 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f,
- 0x127f, 0x007c, 0x2001, 0xa300, 0x2004, 0xa096, 0x0001, 0x0040,
- 0x6e62, 0xa096, 0x0004, 0x0040, 0x6e62, 0x6817, 0x0008, 0x68c3,
- 0x0000, 0x2011, 0x4129, 0x1078, 0x58d4, 0x20a9, 0x01f4, 0x6824,
- 0xd094, 0x0040, 0x6e50, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000,
- 0x0040, 0x6e62, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0x6e62,
- 0xd084, 0x0040, 0x6e57, 0x6827, 0x0001, 0x0078, 0x6e59, 0x00f0,
- 0x6e3f, 0x7804, 0xa084, 0x1000, 0x0040, 0x6e62, 0x7803, 0x0100,
- 0x7803, 0x0000, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f,
- 0x0f7f, 0x157f, 0x127f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e,
- 0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069,
- 0x0100, 0x2079, 0x0140, 0x2071, 0xa5ab, 0x703c, 0x2060, 0x8cff,
- 0x0040, 0x6ee8, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x00c0,
- 0x6e86, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x1078, 0x5967, 0x1078,
- 0x1f31, 0x047e, 0x057e, 0x2009, 0x017f, 0x212c, 0x200b, 0x00a5,
- 0x2021, 0x0169, 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0,
- 0x6eb7, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x0e7e, 0x0f7e, 0x2079,
- 0x0020, 0x2071, 0xa602, 0x6814, 0xa084, 0x0004, 0xa085, 0x0012,
- 0x6816, 0x7803, 0x0008, 0x7003, 0x0000, 0x0f7f, 0x0e7f, 0x250a,
- 0x057f, 0x047f, 0xa39d, 0x0000, 0x00c0, 0x6ec2, 0x2009, 0x0049,
- 0x1078, 0x756c, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x6ed5,
- 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x6ee7, 0x7803,
- 0x1000, 0x7803, 0x0000, 0x0078, 0x6ee7, 0xd08c, 0x0040, 0x6edc,
- 0x6827, 0x0002, 0x0078, 0x6ede, 0x00f0, 0x6ec4, 0x7804, 0xa084,
- 0x1000, 0x0040, 0x6ee7, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824,
- 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f,
- 0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa5ab,
- 0x6a06, 0x127f, 0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000,
- 0x2069, 0xa5ab, 0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e,
- 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2071, 0xa5ab, 0x7614, 0x2660,
- 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x6f46, 0x601c, 0xa206,
- 0x00c0, 0x6f41, 0x7014, 0xac36, 0x00c0, 0x6f20, 0x660c, 0x7616,
- 0x7010, 0xac36, 0x00c0, 0x6f2e, 0x2c00, 0xaf36, 0x0040, 0x6f2c,
- 0x2f00, 0x7012, 0x0078, 0x6f2e, 0x7013, 0x0000, 0x660c, 0x067e,
- 0x2c00, 0xaf06, 0x0040, 0x6f37, 0x7e0e, 0x0078, 0x6f38, 0x2678,
- 0x600f, 0x0000, 0x1078, 0x8c01, 0x1078, 0x7045, 0x0c7f, 0x0078,
- 0x6f13, 0x2c78, 0x600c, 0x2060, 0x0078, 0x6f13, 0x127f, 0x007f,
- 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1,
- 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2,
- 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0078, 0x6fa0, 0x157e, 0x147e,
- 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, 0xa006, 0x20a2,
- 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0078, 0x6fa0, 0x157e,
- 0x147e, 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, 0xa006,
- 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x0078, 0x6fa0,
- 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2,
- 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078,
- 0x6fa0, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810,
- 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200,
- 0x1078, 0x7050, 0x60c3, 0x0020, 0x1078, 0x6c2d, 0x147f, 0x157f,
- 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x2061, 0x0100, 0x6120,
- 0xd1b4, 0x00c0, 0x6fb8, 0xd1bc, 0x00c0, 0x7002, 0x0078, 0x7042,
- 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069,
- 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000,
- 0x0040, 0x6ff9, 0x6020, 0xd0b4, 0x0040, 0x6ff9, 0x6024, 0xd094,
- 0x00c0, 0x6ff9, 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0,
- 0x6ff9, 0x00f0, 0x6fc5, 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107,
- 0x6130, 0xa18c, 0x00ff, 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b,
- 0xbc91, 0x6043, 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6024,
- 0xd094, 0x00c0, 0x6ff8, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x6fef,
- 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000,
- 0x0078, 0x7042, 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e,
- 0x0d7e, 0x2069, 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804,
- 0xa084, 0x4000, 0x0040, 0x703b, 0x6020, 0xd0bc, 0x0040, 0x703b,
- 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x703b, 0x00f0,
- 0x700f, 0x027e, 0x6164, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c,
- 0x00ff, 0xa10d, 0x6088, 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043,
- 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000,
- 0x00c0, 0x7035, 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f,
- 0x200b, 0x0000, 0x0c7f, 0x127f, 0x007c, 0x0e7e, 0x2071, 0xa5ab,
- 0x7020, 0xa005, 0x0040, 0x704e, 0x8001, 0x7022, 0x0e7f, 0x007c,
- 0x20a9, 0x0008, 0x20a2, 0x00f0, 0x7052, 0x20a2, 0x20a2, 0x007c,
- 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e,
- 0x2091, 0x8000, 0x2071, 0xa5ab, 0x7614, 0x2660, 0x2678, 0x2039,
- 0x0001, 0x87ff, 0x0040, 0x70f4, 0x8cff, 0x0040, 0x70f4, 0x601c,
- 0xa086, 0x0006, 0x00c0, 0x70ef, 0x88ff, 0x0040, 0x707f, 0x2800,
- 0xac06, 0x00c0, 0x70ef, 0x2039, 0x0000, 0x0078, 0x708a, 0x6018,
- 0xa206, 0x00c0, 0x70ef, 0x85ff, 0x0040, 0x708a, 0x6020, 0xa106,
- 0x00c0, 0x70ef, 0x7024, 0xac06, 0x00c0, 0x70ba, 0x2069, 0x0100,
- 0x68c0, 0xa005, 0x0040, 0x70b5, 0x1078, 0x595a, 0x6817, 0x0008,
- 0x68c3, 0x0000, 0x1078, 0x7188, 0x7027, 0x0000, 0x037e, 0x2069,
- 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x70aa, 0x6803, 0x0100,
- 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x70b2,
- 0x6827, 0x0001, 0x037f, 0x0078, 0x70ba, 0x6003, 0x0009, 0x630a,
- 0x0078, 0x70ef, 0x7014, 0xac36, 0x00c0, 0x70c0, 0x660c, 0x7616,
- 0x7010, 0xac36, 0x00c0, 0x70ce, 0x2c00, 0xaf36, 0x0040, 0x70cc,
- 0x2f00, 0x7012, 0x0078, 0x70ce, 0x7013, 0x0000, 0x660c, 0x067e,
- 0x2c00, 0xaf06, 0x0040, 0x70d7, 0x7e0e, 0x0078, 0x70d8, 0x2678,
- 0x89ff, 0x00c0, 0x70e7, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078,
- 0x8a44, 0x0040, 0x70e5, 0x1078, 0x9e70, 0x1078, 0x8c01, 0x1078,
- 0x7045, 0x88ff, 0x00c0, 0x70fe, 0x0c7f, 0x0078, 0x7069, 0x2c78,
- 0x600c, 0x2060, 0x0078, 0x7069, 0xa006, 0x127f, 0x007f, 0x067f,
- 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000,
- 0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x70f5, 0x0f7e, 0x0e7e, 0x0d7e,
- 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
- 0xa5ab, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x7177, 0x601c,
- 0xa086, 0x0006, 0x00c0, 0x7172, 0x87ff, 0x0040, 0x7125, 0x2700,
- 0xac06, 0x00c0, 0x7172, 0x0078, 0x7130, 0x6018, 0xa206, 0x00c0,
- 0x7172, 0x85ff, 0x0040, 0x7130, 0x6020, 0xa106, 0x00c0, 0x7172,
- 0x703c, 0xac06, 0x00c0, 0x7142, 0x037e, 0x2019, 0x0001, 0x1078,
- 0x6e6c, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047,
- 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x7148, 0x660c, 0x763a,
- 0x7034, 0xac36, 0x00c0, 0x7156, 0x2c00, 0xaf36, 0x0040, 0x7154,
- 0x2f00, 0x7036, 0x0078, 0x7156, 0x7037, 0x0000, 0x660c, 0x067e,
- 0x2c00, 0xaf06, 0x0040, 0x715f, 0x7e0e, 0x0078, 0x7160, 0x2678,
- 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x716a,
- 0x1078, 0x9e70, 0x1078, 0x8c01, 0x87ff, 0x00c0, 0x7181, 0x0c7f,
- 0x0078, 0x7114, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7114, 0xa006,
- 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f,
- 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa7bd, 0x0001, 0x0078, 0x7178,
- 0x0e7e, 0x2071, 0xa5ab, 0x2001, 0xa300, 0x2004, 0xa086, 0x0002,
- 0x00c0, 0x7196, 0x7007, 0x0005, 0x0078, 0x7198, 0x7007, 0x0000,
- 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x027e, 0x007e,
- 0x127e, 0x2091, 0x8000, 0x2071, 0xa5ab, 0x2c10, 0x7638, 0x2660,
- 0x2678, 0x8cff, 0x0040, 0x71d8, 0x2200, 0xac06, 0x00c0, 0x71d3,
- 0x7038, 0xac36, 0x00c0, 0x71b6, 0x660c, 0x763a, 0x7034, 0xac36,
- 0x00c0, 0x71c4, 0x2c00, 0xaf36, 0x0040, 0x71c2, 0x2f00, 0x7036,
- 0x0078, 0x71c4, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0040,
- 0x71cc, 0x7e0e, 0x0078, 0x71cd, 0x2678, 0x600f, 0x0000, 0xa085,
- 0x0001, 0x0078, 0x71d8, 0x2c78, 0x600c, 0x2060, 0x0078, 0x71a9,
- 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c,
- 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091,
- 0x8000, 0x2071, 0xa5ab, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0040,
- 0x7279, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x7274,
- 0x7024, 0xac06, 0x00c0, 0x721f, 0x2069, 0x0100, 0x68c0, 0xa005,
- 0x0040, 0x724d, 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, 0x7188,
- 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
- 0x0040, 0x7216, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
- 0x6824, 0xd084, 0x0040, 0x721e, 0x6827, 0x0001, 0x037f, 0x700c,
- 0xac36, 0x00c0, 0x7225, 0x660c, 0x760e, 0x7008, 0xac36, 0x00c0,
- 0x7233, 0x2c00, 0xaf36, 0x0040, 0x7231, 0x2f00, 0x700a, 0x0078,
- 0x7233, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040,
- 0x723c, 0x7e0e, 0x0078, 0x723d, 0x2678, 0x600f, 0x0000, 0x1078,
- 0x8c27, 0x00c0, 0x7251, 0x1078, 0x2839, 0x1078, 0x8c3b, 0x00c0,
- 0x726d, 0x1078, 0x7a05, 0x0078, 0x726d, 0x1078, 0x7188, 0x0078,
- 0x721f, 0x1078, 0x8c3b, 0x00c0, 0x7259, 0x1078, 0x7a05, 0x0078,
- 0x726d, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x726d, 0x601c,
- 0xa086, 0x0003, 0x00c0, 0x7281, 0x6837, 0x0103, 0x6b4a, 0x6847,
- 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x1078,
- 0x7045, 0x0c7f, 0x0078, 0x71ee, 0x2c78, 0x600c, 0x2060, 0x0078,
- 0x71ee, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f,
- 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x726d, 0x1078, 0x9e70,
- 0x0078, 0x726d, 0x037e, 0x157e, 0x137e, 0x147e, 0x3908, 0xa006,
- 0xa190, 0x0020, 0x221c, 0xa39e, 0x260c, 0x00c0, 0x729b, 0x8210,
- 0x8000, 0x0078, 0x7292, 0xa005, 0x0040, 0x72a7, 0x20a9, 0x0020,
- 0x2198, 0x8211, 0xa282, 0x0020, 0x20c8, 0x20a0, 0x53a3, 0x147f,
- 0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078,
- 0x65f8, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x2099, 0xa5a3, 0x20a9, 0x0004, 0x53a6,
- 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x1078, 0x6c2d, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65f8,
- 0x20a3, 0x0214, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084,
- 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6c2d,
- 0x007c, 0x0d7e, 0x017e, 0x2f68, 0x2009, 0x0035, 0x1078, 0x8ef5,
- 0x00c0, 0x7361, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, 0x1300,
- 0x20a3, 0x0000, 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0040,
- 0x733d, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0,
- 0x7317, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0078, 0x7352, 0xa286,
- 0x007f, 0x00c0, 0x7321, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0078,
- 0x7352, 0xd2bc, 0x0040, 0x7337, 0xa286, 0x0080, 0x00c0, 0x732e,
- 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0078, 0x7352, 0xa2e8, 0xa434,
- 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x0078, 0x7352, 0x20a3,
- 0x0000, 0x6098, 0x20a2, 0x0078, 0x7352, 0x7818, 0xa080, 0x0028,
- 0x2004, 0xa082, 0x007e, 0x0048, 0x734e, 0x0d7e, 0x2069, 0xa31a,
- 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x7352, 0x20a3, 0x0000,
- 0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x6c2d, 0x017f, 0x0d7f,
- 0x007c, 0x7817, 0x0001, 0x7803, 0x0006, 0x017f, 0x0d7f, 0x007c,
- 0x0d7e, 0x027e, 0x7928, 0x2168, 0x691c, 0xa186, 0x0006, 0x0040,
- 0x738a, 0xa186, 0x0003, 0x0040, 0x73e5, 0xa186, 0x0005, 0x0040,
- 0x73c8, 0xa186, 0x0004, 0x0040, 0x73b8, 0xa186, 0x0008, 0x0040,
- 0x73d2, 0x7807, 0x0037, 0x7813, 0x1700, 0x1078, 0x7450, 0x027f,
- 0x0d7f, 0x007c, 0x1078, 0x740d, 0x2009, 0x4000, 0x6800, 0x0079,
- 0x7391, 0x73a4, 0x73b2, 0x73a6, 0x73b2, 0x73ad, 0x73a4, 0x73a4,
- 0x73b2, 0x73b2, 0x73b2, 0x73b2, 0x73a4, 0x73a4, 0x73a4, 0x73a4,
- 0x73a4, 0x73b2, 0x73a4, 0x73b2, 0x1078, 0x1328, 0x6824, 0xd0e4,
- 0x0040, 0x73ad, 0xd0cc, 0x0040, 0x73b0, 0xa00e, 0x0078, 0x73b2,
- 0x2009, 0x2000, 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0078, 0x7403,
- 0x1078, 0x740d, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000,
- 0x6a00, 0xa286, 0x0002, 0x00c0, 0x73c6, 0xa00e, 0x0078, 0x7403,
- 0x1078, 0x740d, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000,
- 0x0078, 0x7403, 0x1078, 0x740d, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x2009, 0x4000, 0xa286, 0x0005, 0x0040, 0x73e2, 0xa286, 0x0002,
- 0x00c0, 0x73e3, 0xa00e, 0x0078, 0x7403, 0x1078, 0x740d, 0x6810,
- 0x2068, 0x697c, 0x6810, 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2,
- 0x22a2, 0x7928, 0xa180, 0x0000, 0x2004, 0xa08e, 0x0002, 0x0040,
- 0x7401, 0xa08e, 0x0004, 0x0040, 0x7401, 0x2009, 0x4000, 0x0078,
- 0x7403, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0018,
- 0x1078, 0x6c2d, 0x027f, 0x0d7f, 0x007c, 0x037e, 0x047e, 0x057e,
- 0x067e, 0x20a1, 0x020b, 0x1078, 0x65f8, 0xa006, 0x20a3, 0x0200,
- 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, 0x0028,
- 0x2004, 0xa092, 0x007e, 0x0048, 0x7433, 0x0d7e, 0x2069, 0xa31a,
- 0x2d2c, 0x8d68, 0x2d34, 0xa0e8, 0xa434, 0x2d6c, 0x6b10, 0x6c14,
- 0x0d7f, 0x0078, 0x7439, 0x2019, 0x0000, 0x6498, 0x2029, 0x0000,
- 0x6630, 0x7828, 0xa080, 0x0007, 0x2004, 0xa086, 0x0003, 0x00c0,
- 0x7447, 0x25a2, 0x26a2, 0x23a2, 0x24a2, 0x0078, 0x744b, 0x23a2,
- 0x24a2, 0x25a2, 0x26a2, 0x067f, 0x057f, 0x047f, 0x037f, 0x007c,
- 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0100, 0x20a3, 0x0000,
- 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6c2d,
- 0x007c, 0x20a1, 0x020b, 0x1078, 0x655e, 0x20a3, 0x1400, 0x20a3,
- 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, 0x20a2, 0x782c,
- 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x20a3, 0x0000,
- 0x60c3, 0x0010, 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078,
- 0x65ef, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0x20a2, 0x7810,
- 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x007c, 0x147e, 0x20a1,
- 0x020b, 0x1078, 0x7499, 0x60c3, 0x0000, 0x1078, 0x6c2d, 0x147f,
- 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
- 0x2004, 0xd0bc, 0x0040, 0x74b6, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c,
- 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a,
- 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x74be, 0x20a3, 0x0300,
- 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0819,
- 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x2fa2,
- 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x007c, 0x2061,
- 0xaa00, 0x2a70, 0x7060, 0x7046, 0x704b, 0xaa00, 0x007c, 0x0e7e,
- 0x127e, 0x2071, 0xa300, 0x2091, 0x8000, 0x7544, 0xa582, 0x0010,
- 0x0048, 0x7509, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040,
- 0x74f5, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8, 0x74f1, 0x0078,
- 0x74e4, 0x2061, 0xaa00, 0x0078, 0x74e4, 0x6003, 0x0008, 0x8529,
- 0x7546, 0xaca8, 0x0010, 0x7054, 0xa502, 0x00c8, 0x7505, 0x754a,
- 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704b, 0xaa00, 0x0078,
- 0x7500, 0xa006, 0x0078, 0x7502, 0x0e7e, 0x2071, 0xa300, 0x7544,
- 0xa582, 0x0010, 0x0048, 0x753a, 0x7048, 0x2060, 0x6000, 0xa086,
- 0x0000, 0x0040, 0x7527, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8,
- 0x7523, 0x0078, 0x7516, 0x2061, 0xaa00, 0x0078, 0x7516, 0x6003,
- 0x0008, 0x8529, 0x7546, 0xaca8, 0x0010, 0x7054, 0xa502, 0x00c8,
- 0x7536, 0x754a, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x704b, 0xaa00,
- 0x0078, 0x7532, 0xa006, 0x0078, 0x7534, 0xac82, 0xaa00, 0x1048,
- 0x1328, 0x2001, 0xa315, 0x2004, 0xac02, 0x10c8, 0x1328, 0xa006,
- 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000,
- 0x6003, 0x0000, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036,
- 0x603a, 0x603e, 0x2061, 0xa300, 0x6044, 0x8000, 0x6046, 0xa086,
- 0x0001, 0x0040, 0x7564, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078,
- 0x6109, 0x127f, 0x0078, 0x7563, 0x601c, 0xa084, 0x000f, 0x0079,
- 0x7571, 0x757a, 0x758b, 0x75a7, 0x75c3, 0x8f2d, 0x8f49, 0x8f65,
- 0x757a, 0x758b, 0xa186, 0x0013, 0x00c0, 0x7583, 0x1078, 0x6010,
- 0x1078, 0x6109, 0x007c, 0xa18e, 0x0047, 0x00c0, 0x758a, 0xa016,
- 0x1078, 0x15ec, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
- 0x1328, 0x1079, 0x7595, 0x067f, 0x007c, 0x75a5, 0x7891, 0x7a34,
- 0x75a5, 0x7ab8, 0x75df, 0x75a5, 0x75a5, 0x7823, 0x7e6d, 0x75a5,
- 0x75a5, 0x75a5, 0x75a5, 0x75a5, 0x75a5, 0x1078, 0x1328, 0x067e,
- 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1328, 0x1079, 0x75b1, 0x067f,
- 0x007c, 0x75c1, 0x8522, 0x75c1, 0x75c1, 0x75c1, 0x75c1, 0x75c1,
- 0x75c1, 0x84c5, 0x86a8, 0x75c1, 0x8552, 0x85d8, 0x8552, 0x85d8,
- 0x75c1, 0x1078, 0x1328, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
- 0x1328, 0x1079, 0x75cd, 0x067f, 0x007c, 0x75dd, 0x7eb4, 0x7f81,
- 0x80c6, 0x8242, 0x75dd, 0x75dd, 0x75dd, 0x7e8d, 0x846d, 0x8471,
- 0x75dd, 0x75dd, 0x75dd, 0x75dd, 0x84a1, 0x1078, 0x1328, 0xa1b6,
- 0x0015, 0x00c0, 0x75e7, 0x1078, 0x753d, 0x0078, 0x75ed, 0xa1b6,
- 0x0016, 0x10c0, 0x1328, 0x1078, 0x753d, 0x007c, 0x20a9, 0x000e,
- 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420,
- 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002,
- 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x00f0, 0x75fc,
- 0x0e7e, 0x1078, 0x8a44, 0x0040, 0x7613, 0x6010, 0x2070, 0x7007,
- 0x0000, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x753d, 0x007c, 0x0d7e,
- 0x037e, 0x7330, 0xa386, 0x0200, 0x00c0, 0x7624, 0x6018, 0x2068,
- 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0040, 0x762e,
- 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x1078, 0x753d,
- 0x037f, 0x0d7f, 0x007c, 0x017e, 0x20a9, 0x002a, 0xae80, 0x000c,
- 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a,
- 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3,
- 0x0e7e, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078,
- 0x753d, 0x017f, 0x007c, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2c68,
- 0x017e, 0x2009, 0x0035, 0x1078, 0x8ef5, 0x017f, 0x00c0, 0x766f,
- 0x027e, 0x6228, 0x2268, 0x027f, 0x2071, 0xa88c, 0x6b1c, 0xa386,
- 0x0003, 0x0040, 0x7673, 0xa386, 0x0006, 0x0040, 0x7677, 0x1078,
- 0x753d, 0x0078, 0x7679, 0x1078, 0x767c, 0x0078, 0x7679, 0x1078,
- 0x771e, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x6810, 0x2078, 0xa186,
- 0x0015, 0x0040, 0x7705, 0xa18e, 0x0016, 0x00c0, 0x771c, 0x700c,
- 0xa084, 0xff00, 0xa086, 0x1700, 0x00c0, 0x76e0, 0x8fff, 0x0040,
- 0x771a, 0x6808, 0xa086, 0xffff, 0x00c0, 0x7709, 0x784c, 0xa084,
- 0x0060, 0xa086, 0x0020, 0x00c0, 0x76a7, 0x797c, 0x7810, 0xa106,
- 0x00c0, 0x7709, 0x7980, 0x7814, 0xa106, 0x00c0, 0x7709, 0x1078,
- 0x8bf4, 0x6830, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4, 0x784e,
- 0x027e, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x1078, 0x5a98, 0x7854,
- 0xa20a, 0x0048, 0x76bc, 0x8011, 0x7a56, 0x82ff, 0x027f, 0x00c0,
- 0x76c8, 0x0c7e, 0x2d60, 0x1078, 0x8832, 0x0c7f, 0x0078, 0x771a,
- 0x0c7e, 0x0d7e, 0x2f68, 0x6838, 0xd0fc, 0x00c0, 0x76d3, 0x1078,
- 0x4290, 0x0078, 0x76d5, 0x1078, 0x436e, 0x0d7f, 0x0c7f, 0x00c0,
- 0x7709, 0x0c7e, 0x2d60, 0x1078, 0x753d, 0x0c7f, 0x0078, 0x771a,
- 0x7008, 0xa086, 0x000b, 0x00c0, 0x76fa, 0x6018, 0x200c, 0xc1bc,
- 0x2102, 0x0c7e, 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, 0x6003,
- 0x000b, 0x601f, 0x0002, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7f,
- 0x0078, 0x771a, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x7709, 0x2001,
- 0xa5a2, 0x2004, 0x683e, 0x0078, 0x771a, 0x1078, 0x7739, 0x0078,
- 0x771c, 0x8fff, 0x1040, 0x1328, 0x0c7e, 0x0d7e, 0x2d60, 0x2f68,
- 0x684b, 0x0003, 0x1078, 0x8726, 0x1078, 0x8bf4, 0x1078, 0x8c01,
- 0x0d7f, 0x0c7f, 0x1078, 0x753d, 0x0f7f, 0x007c, 0xa186, 0x0015,
- 0x00c0, 0x7728, 0x2001, 0xa5a2, 0x2004, 0x683e, 0x0078, 0x7736,
- 0xa18e, 0x0016, 0x00c0, 0x7738, 0x0c7e, 0x2d00, 0x2060, 0x1078,
- 0xa134, 0x1078, 0x5a41, 0x1078, 0x753d, 0x0c7f, 0x1078, 0x753d,
- 0x007c, 0x027e, 0x037e, 0x047e, 0x7228, 0x7c80, 0x7b7c, 0xd2f4,
- 0x0040, 0x7748, 0x2001, 0xa5a2, 0x2004, 0x683e, 0x0078, 0x77ac,
- 0x0c7e, 0x2d60, 0x1078, 0x874a, 0x0c7f, 0x6804, 0xa086, 0x0050,
- 0x00c0, 0x7760, 0x0c7e, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007,
- 0x0050, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7f, 0x0078, 0x77ac,
- 0x6800, 0xa086, 0x000f, 0x0040, 0x7782, 0x8fff, 0x1040, 0x1328,
- 0x6824, 0xd0dc, 0x00c0, 0x7782, 0x6800, 0xa086, 0x0004, 0x00c0,
- 0x7787, 0x784c, 0xd0ac, 0x0040, 0x7787, 0x784c, 0xc0dc, 0xc0f4,
- 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, 0x0001, 0x682e,
- 0x0078, 0x77a6, 0x2001, 0x0007, 0x682e, 0x0078, 0x77a6, 0x784c,
- 0xd0b4, 0x00c0, 0x7794, 0xd0ac, 0x0040, 0x7782, 0x784c, 0xd0f4,
- 0x00c0, 0x7782, 0x0078, 0x7775, 0xd2ec, 0x00c0, 0x7782, 0x7024,
- 0xa306, 0x00c0, 0x779f, 0x7020, 0xa406, 0x0040, 0x7782, 0x7020,
- 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, 0x1078, 0x8d2b,
- 0x1078, 0x6109, 0x0078, 0x77ae, 0x1078, 0x753d, 0x047f, 0x037f,
- 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x027e, 0x6034, 0x2068, 0x6a1c,
- 0xa286, 0x0007, 0x0040, 0x7806, 0xa286, 0x0002, 0x0040, 0x7806,
- 0xa286, 0x0000, 0x0040, 0x7806, 0x6808, 0x6338, 0xa306, 0x00c0,
- 0x7806, 0x2071, 0xa88c, 0xa186, 0x0015, 0x0040, 0x7800, 0xa18e,
- 0x0016, 0x00c0, 0x77e8, 0x6030, 0xa084, 0x00ff, 0xa086, 0x0001,
- 0x00c0, 0x77e8, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x77e8, 0x6034,
- 0xa080, 0x0009, 0x200c, 0xc1dd, 0xc1f5, 0x2102, 0x0078, 0x7800,
- 0x0c7e, 0x6034, 0x2060, 0x6010, 0x2068, 0x1078, 0x8a44, 0x1040,
- 0x1328, 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f,
- 0x0002, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7f, 0x0078, 0x7806,
- 0x6034, 0x2068, 0x2001, 0xa5a2, 0x2004, 0x683e, 0x1078, 0x753d,
- 0x027f, 0x0d7f, 0x0e7f, 0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98,
- 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x00c0, 0x7820, 0x6018,
- 0x2068, 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802,
- 0x0d7f, 0x0078, 0x7608, 0x2100, 0xa1b2, 0x0044, 0x10c8, 0x1328,
- 0xa1b2, 0x0040, 0x00c8, 0x7888, 0x0079, 0x782e, 0x787c, 0x7870,
- 0x787c, 0x787c, 0x787c, 0x787c, 0x786e, 0x786e, 0x786e, 0x786e,
- 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e,
- 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e,
- 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x787c, 0x786e, 0x787c,
- 0x787c, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x787c, 0x786e,
- 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e,
- 0x787c, 0x787c, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e,
- 0x786e, 0x786e, 0x786e, 0x787c, 0x786e, 0x786e, 0x1078, 0x1328,
- 0x6003, 0x0001, 0x6106, 0x1078, 0x5c45, 0x127e, 0x2091, 0x8000,
- 0x1078, 0x6109, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078,
- 0x5c45, 0x127e, 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x007c,
- 0x2600, 0x0079, 0x788b, 0x788f, 0x788f, 0x788f, 0x787c, 0x1078,
- 0x1328, 0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1328, 0xa1b6, 0x0013,
- 0x00c0, 0x78a1, 0xa0b2, 0x0040, 0x00c8, 0x79fb, 0x2008, 0x0079,
- 0x7941, 0xa1b6, 0x0027, 0x00c0, 0x78fe, 0x1078, 0x6010, 0x6004,
- 0x1078, 0x8c27, 0x0040, 0x78be, 0x1078, 0x8c3b, 0x0040, 0x78f6,
- 0xa08e, 0x0021, 0x0040, 0x78fa, 0xa08e, 0x0022, 0x0040, 0x78f6,
- 0xa08e, 0x003d, 0x0040, 0x78fa, 0x0078, 0x78f1, 0x1078, 0x2839,
- 0x2001, 0x0007, 0x1078, 0x443f, 0x6018, 0xa080, 0x0028, 0x200c,
- 0x1078, 0x7a05, 0xa186, 0x007e, 0x00c0, 0x78d3, 0x2001, 0xa332,
- 0x2014, 0xc285, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019,
- 0x0028, 0x1078, 0x5d53, 0x077e, 0x2039, 0x0000, 0x1078, 0x5c78,
- 0x0c7e, 0x6018, 0xa065, 0x0040, 0x78e7, 0x1078, 0x471b, 0x0c7f,
- 0x2c08, 0x1078, 0x9c38, 0x077f, 0x037f, 0x027f, 0x017f, 0x1078,
- 0x44bc, 0x1078, 0x753d, 0x1078, 0x6109, 0x007c, 0x1078, 0x7a05,
- 0x0078, 0x78f1, 0x1078, 0x7a28, 0x0078, 0x78f1, 0xa186, 0x0014,
- 0x00c0, 0x78f5, 0x1078, 0x6010, 0x1078, 0x2813, 0x1078, 0x8c27,
- 0x00c0, 0x791d, 0x1078, 0x2839, 0x6018, 0xa080, 0x0028, 0x200c,
- 0x1078, 0x7a05, 0xa186, 0x007e, 0x00c0, 0x791b, 0x2001, 0xa332,
- 0x200c, 0xc185, 0x2102, 0x0078, 0x78f1, 0x1078, 0x8c3b, 0x00c0,
- 0x7925, 0x1078, 0x7a05, 0x0078, 0x78f1, 0x6004, 0xa08e, 0x0032,
- 0x00c0, 0x7936, 0x0e7e, 0x0f7e, 0x2071, 0xa381, 0x2079, 0x0000,
- 0x1078, 0x2b56, 0x0f7f, 0x0e7f, 0x0078, 0x78f1, 0x6004, 0xa08e,
- 0x0021, 0x0040, 0x7921, 0xa08e, 0x0022, 0x1040, 0x7a05, 0x0078,
- 0x78f1, 0x7983, 0x7985, 0x7989, 0x798d, 0x7991, 0x7995, 0x7981,
- 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981,
- 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981,
- 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7999,
- 0x79ab, 0x7981, 0x79ad, 0x79ab, 0x7981, 0x7981, 0x7981, 0x7981,
- 0x7981, 0x79ab, 0x79ab, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981,
- 0x7981, 0x7981, 0x7981, 0x79de, 0x79ab, 0x7981, 0x79a5, 0x7981,
- 0x7981, 0x7981, 0x79a7, 0x7981, 0x7981, 0x7981, 0x79ab, 0x7981,
- 0x7981, 0x1078, 0x1328, 0x0078, 0x79ab, 0x2001, 0x000b, 0x0078,
- 0x79b8, 0x2001, 0x0003, 0x0078, 0x79b8, 0x2001, 0x0005, 0x0078,
- 0x79b8, 0x2001, 0x0001, 0x0078, 0x79b8, 0x2001, 0x0009, 0x0078,
- 0x79b8, 0x1078, 0x6010, 0x6003, 0x0005, 0x2001, 0xa5a2, 0x2004,
- 0x603e, 0x1078, 0x6109, 0x0078, 0x79b7, 0x0078, 0x79ab, 0x0078,
- 0x79ab, 0x1078, 0x443f, 0x0078, 0x79f0, 0x1078, 0x6010, 0x6003,
- 0x0004, 0x2001, 0xa5a0, 0x2004, 0x6016, 0x1078, 0x6109, 0x007c,
- 0x1078, 0x443f, 0x1078, 0x6010, 0x2001, 0xa5a2, 0x2004, 0x603e,
- 0x6003, 0x0002, 0x037e, 0x2019, 0xa35c, 0x2304, 0xa084, 0xff00,
- 0x00c0, 0x79cf, 0x2019, 0xa5a0, 0x231c, 0x0078, 0x79d8, 0x8007,
- 0xa09a, 0x0004, 0x0048, 0x79ca, 0x8003, 0x801b, 0x831b, 0xa318,
- 0x6316, 0x037f, 0x1078, 0x6109, 0x0078, 0x79b7, 0x0e7e, 0x0f7e,
- 0x2071, 0xa381, 0x2079, 0x0000, 0x1078, 0x2b56, 0x0f7f, 0x0e7f,
- 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109, 0x0078, 0x79b7,
- 0x1078, 0x6010, 0x6003, 0x0002, 0x2001, 0xa5a0, 0x2004, 0x6016,
- 0x1078, 0x6109, 0x007c, 0x2600, 0x2008, 0x0079, 0x79ff, 0x7a03,
- 0x7a03, 0x7a03, 0x79f0, 0x1078, 0x1328, 0x0e7e, 0x1078, 0x8a44,
- 0x0040, 0x7a21, 0x6010, 0x2070, 0x7038, 0xd0fc, 0x0040, 0x7a21,
- 0x7007, 0x0000, 0x017e, 0x6004, 0xa08e, 0x0021, 0x0040, 0x7a23,
- 0xa08e, 0x003d, 0x0040, 0x7a23, 0x017f, 0x7037, 0x0103, 0x7033,
- 0x0100, 0x0e7f, 0x007c, 0x017f, 0x1078, 0x7a28, 0x0078, 0x7a21,
- 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103,
- 0x7023, 0x8001, 0x0e7f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804,
- 0xa084, 0x00ff, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1328, 0x6604,
- 0xa6b6, 0x0043, 0x00c0, 0x7a48, 0x1078, 0x8e6d, 0x0078, 0x7aa7,
- 0x6604, 0xa6b6, 0x0033, 0x00c0, 0x7a51, 0x1078, 0x8e11, 0x0078,
- 0x7aa7, 0x6604, 0xa6b6, 0x0028, 0x00c0, 0x7a5a, 0x1078, 0x8c6a,
- 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x0029, 0x00c0, 0x7a63, 0x1078,
- 0x8c84, 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x001f, 0x00c0, 0x7a6c,
- 0x1078, 0x75ee, 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x0000, 0x00c0,
- 0x7a75, 0x1078, 0x780c, 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x0022,
- 0x00c0, 0x7a7e, 0x1078, 0x7617, 0x0078, 0x7aa7, 0x6604, 0xa6b6,
- 0x0035, 0x00c0, 0x7a87, 0x1078, 0x7653, 0x0078, 0x7aa7, 0x6604,
- 0xa6b6, 0x0039, 0x00c0, 0x7a90, 0x1078, 0x77b2, 0x0078, 0x7aa7,
- 0x6604, 0xa6b6, 0x003d, 0x00c0, 0x7a99, 0x1078, 0x7633, 0x0078,
- 0x7aa7, 0xa1b6, 0x0015, 0x00c0, 0x7aa1, 0x1079, 0x7aac, 0x0078,
- 0x7aa7, 0xa1b6, 0x0016, 0x00c0, 0x7aa8, 0x1079, 0x7bfd, 0x007c,
- 0x1078, 0x7583, 0x0078, 0x7aa7, 0x7ad0, 0x7ad3, 0x7ad0, 0x7b1e,
- 0x7ad0, 0x7b91, 0x7c09, 0x7ad0, 0x7ad0, 0x7bd5, 0x7ad0, 0x7beb,
- 0xa1b6, 0x0048, 0x0040, 0x7ac4, 0x20e1, 0x0005, 0x3d18, 0x3e20,
- 0x2c10, 0x1078, 0x15ec, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74,
- 0x7000, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x753d, 0x007c,
- 0x0005, 0x0005, 0x007c, 0x0e7e, 0x2071, 0xa300, 0x707c, 0xa086,
- 0x0074, 0x00c0, 0x7b07, 0x1078, 0x9c0c, 0x00c0, 0x7af9, 0x0d7e,
- 0x6018, 0x2068, 0x7030, 0xd08c, 0x0040, 0x7aec, 0x6800, 0xd0bc,
- 0x0040, 0x7aec, 0xc0c5, 0x6802, 0x1078, 0x7b0b, 0x0d7f, 0x2001,
- 0x0006, 0x1078, 0x443f, 0x1078, 0x2839, 0x1078, 0x753d, 0x0078,
- 0x7b09, 0x2001, 0x000a, 0x1078, 0x443f, 0x1078, 0x2839, 0x6003,
- 0x0001, 0x6007, 0x0001, 0x1078, 0x5c45, 0x0078, 0x7b09, 0x1078,
- 0x7b81, 0x0e7f, 0x007c, 0x6800, 0xd084, 0x0040, 0x7b1d, 0x2001,
- 0x0000, 0x1078, 0x442b, 0x2069, 0xa351, 0x6804, 0xd0a4, 0x0040,
- 0x7b1d, 0x2001, 0x0006, 0x1078, 0x4472, 0x007c, 0x0d7e, 0x2011,
- 0xa31f, 0x2204, 0xa086, 0x0074, 0x00c0, 0x7b7d, 0x6018, 0x2068,
- 0x6aa0, 0xa286, 0x007e, 0x00c0, 0x7b31, 0x1078, 0x7d17, 0x0078,
- 0x7b7f, 0x1078, 0x7d0d, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014,
- 0xa286, 0x0080, 0x00c0, 0x7b55, 0x6813, 0x00ff, 0x6817, 0xfffc,
- 0x6010, 0xa005, 0x0040, 0x7b4b, 0x2068, 0x6807, 0x0000, 0x6837,
- 0x0103, 0x6833, 0x0200, 0x2001, 0x0006, 0x1078, 0x443f, 0x1078,
- 0x2839, 0x1078, 0x753d, 0x0078, 0x7b7f, 0x0e7e, 0x2071, 0xa332,
- 0x2e04, 0xd09c, 0x0040, 0x7b70, 0x2071, 0xa880, 0x7108, 0x720c,
- 0xa18c, 0x00ff, 0x00c0, 0x7b68, 0xa284, 0xff00, 0x0040, 0x7b70,
- 0x6018, 0x2070, 0x70a0, 0xd0bc, 0x00c0, 0x7b70, 0x7112, 0x7216,
- 0x0e7f, 0x2001, 0x0004, 0x1078, 0x443f, 0x6003, 0x0001, 0x6007,
- 0x0003, 0x1078, 0x5c45, 0x0078, 0x7b7f, 0x1078, 0x7b81, 0x0d7f,
- 0x007c, 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x0040, 0x7b8c,
- 0x2001, 0x0007, 0x1078, 0x443f, 0x1078, 0x2839, 0x1078, 0x753d,
- 0x007c, 0x0e7e, 0x2071, 0xa300, 0x707c, 0xa086, 0x0014, 0x00c0,
- 0x7bcf, 0x7000, 0xa086, 0x0003, 0x00c0, 0x7ba4, 0x6010, 0xa005,
- 0x00c0, 0x7ba4, 0x1078, 0x35f7, 0x0d7e, 0x6018, 0x2068, 0x1078,
- 0x457d, 0x1078, 0x7b0b, 0x0d7f, 0x1078, 0x7dba, 0x00c0, 0x7bcf,
- 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, 0x0040, 0x7bcf,
- 0x2001, 0x0006, 0x1078, 0x443f, 0x0e7e, 0x6010, 0xa005, 0x0040,
- 0x7bc8, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, 0x7033, 0x0200,
- 0x0e7f, 0x1078, 0x2839, 0x1078, 0x753d, 0x0078, 0x7bd3, 0x1078,
- 0x7a05, 0x1078, 0x7b81, 0x0e7f, 0x007c, 0x2011, 0xa31f, 0x2204,
- 0xa086, 0x0014, 0x00c0, 0x7be8, 0x2001, 0x0002, 0x1078, 0x443f,
- 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5c45, 0x0078, 0x7bea,
- 0x1078, 0x7b81, 0x007c, 0x2011, 0xa31f, 0x2204, 0xa086, 0x0004,
- 0x00c0, 0x7bfa, 0x2001, 0x0007, 0x1078, 0x443f, 0x1078, 0x753d,
- 0x0078, 0x7bfc, 0x1078, 0x7b81, 0x007c, 0x7ad0, 0x7c11, 0x7ad0,
- 0x7c4e, 0x7ad0, 0x7cc0, 0x7c09, 0x7ad0, 0x7ad0, 0x7cd5, 0x7ad0,
- 0x7ce8, 0x6604, 0xa6b6, 0x001e, 0x00c0, 0x7c10, 0x1078, 0x753d,
- 0x007c, 0x0d7e, 0x0c7e, 0x1078, 0x7cfb, 0x00c0, 0x7c27, 0x2001,
- 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, 0x443f, 0x6003,
- 0x0001, 0x6007, 0x0002, 0x1078, 0x5c45, 0x0078, 0x7c4b, 0x2009,
- 0xa88e, 0x2104, 0xa086, 0x0009, 0x00c0, 0x7c3c, 0x6018, 0x2068,
- 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x7c49, 0x8001, 0x6842,
- 0x6017, 0x000a, 0x0078, 0x7c4b, 0x2009, 0xa88f, 0x2104, 0xa084,
- 0xff00, 0xa086, 0x1900, 0x00c0, 0x7c49, 0x1078, 0x753d, 0x0078,
- 0x7c4b, 0x1078, 0x7b81, 0x0c7f, 0x0d7f, 0x007c, 0x1078, 0x7d0a,
- 0x00c0, 0x7c62, 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002,
- 0x1078, 0x443f, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x5c45,
- 0x0078, 0x7c8e, 0x1078, 0x7a05, 0x2009, 0xa88e, 0x2134, 0xa6b4,
- 0x00ff, 0xa686, 0x0005, 0x0040, 0x7c8f, 0xa686, 0x000b, 0x0040,
- 0x7c8c, 0x2009, 0xa88f, 0x2104, 0xa084, 0xff00, 0x00c0, 0x7c7c,
- 0xa686, 0x0009, 0x0040, 0x7c8f, 0xa086, 0x1900, 0x00c0, 0x7c8c,
- 0xa686, 0x0009, 0x0040, 0x7c8f, 0x2001, 0x0004, 0x1078, 0x443f,
- 0x1078, 0x753d, 0x0078, 0x7c8e, 0x1078, 0x7b81, 0x007c, 0x0d7e,
- 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x7c9d, 0x6838, 0xd0fc,
- 0x0040, 0x7c9d, 0x0d7f, 0x0078, 0x7c8c, 0x6018, 0x2068, 0x6840,
- 0xa084, 0x00ff, 0xa005, 0x0040, 0x7cae, 0x8001, 0x6842, 0x6017,
- 0x000a, 0x6007, 0x0016, 0x0d7f, 0x0078, 0x7c8e, 0x68a0, 0xa086,
- 0x007e, 0x00c0, 0x7cbb, 0x0e7e, 0x2071, 0xa300, 0x1078, 0x41f5,
- 0x0e7f, 0x0078, 0x7cbd, 0x1078, 0x2813, 0x0d7f, 0x0078, 0x7c8c,
- 0x1078, 0x7d0a, 0x00c0, 0x7cd0, 0x2001, 0x0004, 0x1078, 0x443f,
- 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, 0x5c45, 0x0078, 0x7cd4,
- 0x1078, 0x7a05, 0x1078, 0x7b81, 0x007c, 0x1078, 0x7d0a, 0x00c0,
- 0x7ce5, 0x2001, 0x0008, 0x1078, 0x443f, 0x6003, 0x0001, 0x6007,
- 0x0005, 0x1078, 0x5c45, 0x0078, 0x7ce7, 0x1078, 0x7b81, 0x007c,
- 0x1078, 0x7d0a, 0x00c0, 0x7cf8, 0x2001, 0x000a, 0x1078, 0x443f,
- 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5c45, 0x0078, 0x7cfa,
- 0x1078, 0x7b81, 0x007c, 0x2009, 0xa88e, 0x2104, 0xa086, 0x0003,
- 0x00c0, 0x7d09, 0x2009, 0xa88f, 0x2104, 0xa084, 0xff00, 0xa086,
- 0x2a00, 0x007c, 0xa085, 0x0001, 0x007c, 0x0c7e, 0x017e, 0xac88,
- 0x0006, 0x2164, 0x1078, 0x4513, 0x017f, 0x0c7f, 0x007c, 0x0f7e,
- 0x0e7e, 0x0d7e, 0x037e, 0x017e, 0x6018, 0x2068, 0x2071, 0xa332,
- 0x2e04, 0xa085, 0x0003, 0x2072, 0x1078, 0x7d8b, 0x0040, 0x7d50,
- 0x2001, 0xa352, 0x2004, 0xd0a4, 0x0040, 0x7d39, 0xa006, 0x2020,
- 0x2009, 0x002a, 0x1078, 0x9ec0, 0x2001, 0xa30c, 0x200c, 0xc195,
- 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x1078, 0x27e2, 0x2071,
- 0xa300, 0x1078, 0x260d, 0x0c7e, 0x157e, 0x20a9, 0x0081, 0x2009,
- 0x007f, 0x1078, 0x2921, 0x8108, 0x00f0, 0x7d49, 0x157f, 0x0c7f,
- 0x1078, 0x7d0d, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0xa880,
- 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xa31a, 0x206a,
- 0x78e6, 0x007e, 0x8e70, 0x2e04, 0x2069, 0xa31b, 0x206a, 0x78ea,
- 0xa084, 0xff00, 0x017f, 0xa105, 0x2009, 0xa325, 0x200a, 0x2069,
- 0xa88e, 0x2071, 0xa59c, 0x6810, 0x2072, 0x6814, 0x7006, 0x6818,
- 0x700a, 0x681c, 0x700e, 0x1078, 0x8da9, 0x2001, 0x0006, 0x1078,
- 0x443f, 0x1078, 0x2839, 0x1078, 0x753d, 0x017f, 0x037f, 0x0d7f,
- 0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x037e, 0x0e7e, 0x157e, 0x2019,
- 0xa325, 0x231c, 0x83ff, 0x0040, 0x7db5, 0x2071, 0xa880, 0x2e14,
- 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, 0x00c0,
- 0x7db5, 0x2011, 0xa896, 0xad98, 0x000a, 0x20a9, 0x0004, 0x1078,
- 0x7e55, 0x00c0, 0x7db5, 0x2011, 0xa89a, 0xad98, 0x0006, 0x20a9,
- 0x0004, 0x1078, 0x7e55, 0x00c0, 0x7db5, 0x157f, 0x0e7f, 0x037f,
- 0x027f, 0x007c, 0x0e7e, 0x2071, 0xa88c, 0x7004, 0xa086, 0x0014,
- 0x00c0, 0x7ddd, 0x7008, 0xa086, 0x0800, 0x00c0, 0x7ddd, 0x700c,
- 0xd0ec, 0x0040, 0x7ddb, 0xa084, 0x0f00, 0xa086, 0x0100, 0x00c0,
- 0x7ddb, 0x7024, 0xd0a4, 0x00c0, 0x7dd8, 0xd0ac, 0x0040, 0x7ddb,
- 0xa006, 0x0078, 0x7ddd, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x0e7e,
- 0x0d7e, 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e, 0x007e, 0x127e,
- 0x2091, 0x8000, 0x2029, 0xa5b4, 0x252c, 0x2021, 0xa5ba, 0x2424,
- 0x2061, 0xaa00, 0x2071, 0xa300, 0x7244, 0x7060, 0xa202, 0x00c8,
- 0x7e43, 0x1078, 0x9ee5, 0x0040, 0x7e3b, 0x671c, 0xa786, 0x0001,
- 0x0040, 0x7e3b, 0xa786, 0x0007, 0x0040, 0x7e3b, 0x2500, 0xac06,
- 0x0040, 0x7e3b, 0x2400, 0xac06, 0x0040, 0x7e3b, 0x0c7e, 0x6000,
- 0xa086, 0x0004, 0x00c0, 0x7e16, 0x1078, 0x1749, 0xa786, 0x0008,
- 0x00c0, 0x7e25, 0x1078, 0x8c3b, 0x00c0, 0x7e25, 0x0c7f, 0x1078,
- 0x7a05, 0x1078, 0x8c01, 0x0078, 0x7e3b, 0x6010, 0x2068, 0x1078,
- 0x8a44, 0x0040, 0x7e38, 0xa786, 0x0003, 0x00c0, 0x7e4d, 0x6837,
- 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4,
- 0x1078, 0x8c01, 0x0c7f, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8,
- 0x7e43, 0x0078, 0x7df4, 0x127f, 0x007f, 0x027f, 0x047f, 0x057f,
- 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0,
- 0x7e2f, 0x1078, 0x9e70, 0x0078, 0x7e38, 0x220c, 0x2304, 0xa106,
- 0x00c0, 0x7e60, 0x8210, 0x8318, 0x00f0, 0x7e55, 0xa006, 0x007c,
- 0x2304, 0xa102, 0x0048, 0x7e68, 0x2001, 0x0001, 0x0078, 0x7e6a,
- 0x2001, 0x0000, 0xa18d, 0x0001, 0x007c, 0x6004, 0xa08a, 0x0044,
- 0x10c8, 0x1328, 0x1078, 0x8c27, 0x0040, 0x7e7c, 0x1078, 0x8c3b,
- 0x0040, 0x7e89, 0x0078, 0x7e82, 0x1078, 0x2839, 0x1078, 0x8c3b,
- 0x0040, 0x7e89, 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109,
- 0x007c, 0x1078, 0x7a05, 0x0078, 0x7e82, 0xa182, 0x0040, 0x0079,
- 0x7e91, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4,
- 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea6, 0x7ea6, 0x7ea6, 0x7ea6,
- 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea6, 0x1078, 0x1328, 0x600b, 0xffff,
- 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x127e, 0x2091, 0x8000,
- 0x1078, 0x6109, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x7ebd,
- 0x6004, 0xa082, 0x0040, 0x0079, 0x7f48, 0xa186, 0x0027, 0x00c0,
- 0x7edf, 0x1078, 0x6010, 0x1078, 0x2813, 0x0d7e, 0x6110, 0x2168,
- 0x1078, 0x8a44, 0x0040, 0x7ed9, 0x6837, 0x0103, 0x684b, 0x0029,
- 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x1078, 0x4982, 0x1078,
- 0x8bf4, 0x0d7f, 0x1078, 0x753d, 0x1078, 0x6109, 0x007c, 0xa186,
- 0x0014, 0x00c0, 0x7ee8, 0x6004, 0xa082, 0x0040, 0x0079, 0x7f10,
- 0xa186, 0x0046, 0x0040, 0x7ef4, 0xa186, 0x0045, 0x0040, 0x7ef4,
- 0xa186, 0x0047, 0x10c0, 0x1328, 0x2001, 0x0109, 0x2004, 0xd084,
- 0x0040, 0x7f0d, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e,
- 0x1078, 0x5ad2, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086,
- 0x0002, 0x00c0, 0x7f0d, 0x0078, 0x7f81, 0x1078, 0x7583, 0x007c,
- 0x7f25, 0x7f23, 0x7f23, 0x7f23, 0x7f23, 0x7f23, 0x7f23, 0x7f23,
- 0x7f23, 0x7f23, 0x7f23, 0x7f41, 0x7f41, 0x7f41, 0x7f41, 0x7f23,
- 0x7f41, 0x7f23, 0x7f41, 0x1078, 0x1328, 0x1078, 0x6010, 0x0d7e,
- 0x6110, 0x2168, 0x1078, 0x8a44, 0x0040, 0x7f3b, 0x6837, 0x0103,
- 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x1078,
- 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d, 0x1078, 0x6109,
- 0x007c, 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109, 0x007c,
- 0x7f5d, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b,
- 0x7f5b, 0x7f5b, 0x7f5b, 0x7f6f, 0x7f6f, 0x7f6f, 0x7f6f, 0x7f5b,
- 0x7f7a, 0x7f5b, 0x7f6f, 0x1078, 0x1328, 0x1078, 0x6010, 0x2001,
- 0xa5a2, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x6109, 0x6010,
- 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, 0x1078,
- 0x6010, 0x2001, 0xa5a2, 0x2004, 0x603e, 0x6003, 0x000f, 0x1078,
- 0x6109, 0x007c, 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109,
- 0x007c, 0xa182, 0x0040, 0x0079, 0x7f85, 0x7f98, 0x7f98, 0x7f98,
- 0x7f98, 0x7f98, 0x7f9a, 0x8095, 0x80b7, 0x7f98, 0x7f98, 0x7f98,
- 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98,
- 0x1078, 0x1328, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2071, 0xa880,
- 0x7124, 0x610a, 0x2071, 0xa88c, 0x6110, 0x2168, 0x7614, 0xa6b4,
- 0x0fff, 0x86ff, 0x0040, 0x8058, 0xa68c, 0x0c00, 0x0040, 0x7fd1,
- 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x7fcd, 0x684c,
- 0xd0ac, 0x0040, 0x7fcd, 0x6024, 0xd0dc, 0x00c0, 0x7fcd, 0x6850,
- 0xd0bc, 0x00c0, 0x7fcd, 0x7318, 0x6814, 0xa306, 0x00c0, 0x806f,
- 0x731c, 0x6810, 0xa306, 0x00c0, 0x806f, 0x7318, 0x6b62, 0x731c,
- 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x8004, 0xa186,
- 0x0028, 0x00c0, 0x7fe1, 0x1078, 0x8c15, 0x684b, 0x001c, 0x0078,
- 0x8006, 0xd6dc, 0x0040, 0x7ffd, 0x684b, 0x0015, 0x684c, 0xd0ac,
- 0x0040, 0x7ffb, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040, 0x7ffb,
- 0x7018, 0xa106, 0x00c0, 0x7ff8, 0x701c, 0xa206, 0x0040, 0x7ffb,
- 0x6962, 0x6a5e, 0xc6dc, 0x0078, 0x8006, 0xd6d4, 0x0040, 0x8004,
- 0x684b, 0x0007, 0x0078, 0x8006, 0x684b, 0x0000, 0x6837, 0x0103,
- 0x6e46, 0xa01e, 0xd6c4, 0x0040, 0x802f, 0xa686, 0x0100, 0x00c0,
- 0x801a, 0x2001, 0xa899, 0x2004, 0xa005, 0x00c0, 0x801a, 0xc6c4,
- 0x0078, 0x7fa9, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0040, 0x802f,
- 0xa38a, 0x0009, 0x0048, 0x8026, 0x2019, 0x0008, 0x037e, 0x2308,
- 0x2019, 0xa898, 0xad90, 0x0019, 0x1078, 0x8739, 0x037f, 0xd6cc,
- 0x0040, 0x8085, 0x7124, 0x695a, 0x81ff, 0x0040, 0x8085, 0xa192,
- 0x0021, 0x00c8, 0x8046, 0x2071, 0xa898, 0x831c, 0x2300, 0xae18,
- 0xad90, 0x001d, 0x1078, 0x8739, 0x0078, 0x8085, 0x6838, 0xd0fc,
- 0x0040, 0x804f, 0x2009, 0x0020, 0x695a, 0x0078, 0x803b, 0x0f7e,
- 0x2d78, 0x1078, 0x86d1, 0x0f7f, 0x1078, 0x8726, 0x0078, 0x8087,
- 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8075, 0x684c,
- 0xd0ac, 0x0040, 0x8075, 0x6024, 0xd0dc, 0x00c0, 0x8075, 0x6850,
- 0xd0bc, 0x00c0, 0x8075, 0x684c, 0xd0f4, 0x00c0, 0x8075, 0x1078,
- 0x8cfa, 0x0d7f, 0x0e7f, 0x0078, 0x8094, 0x684b, 0x0000, 0x6837,
- 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0040, 0x8085, 0x6810, 0x6914,
- 0xa115, 0x0040, 0x8085, 0x1078, 0x8233, 0x1078, 0x4982, 0x6218,
- 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x1078, 0x8cc4, 0x0d7f, 0x0e7f,
- 0x00c0, 0x8094, 0x1078, 0x753d, 0x007c, 0x0f7e, 0x6003, 0x0003,
- 0x2079, 0xa88c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078,
- 0x784c, 0xd0ac, 0x0040, 0x80a8, 0x6003, 0x0002, 0x0f7f, 0x007c,
- 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x603f, 0x0000, 0x2c10,
- 0x1078, 0x1cab, 0x1078, 0x5c64, 0x1078, 0x61d3, 0x007c, 0x2001,
- 0xa5a2, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005,
- 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15ec, 0x007c, 0xa182, 0x0040,
- 0x0079, 0x80ca, 0x80dd, 0x80dd, 0x80dd, 0x80dd, 0x80dd, 0x80df,
- 0x8182, 0x80dd, 0x80dd, 0x8198, 0x8209, 0x80dd, 0x80dd, 0x80dd,
- 0x80dd, 0x8218, 0x80dd, 0x80dd, 0x80dd, 0x1078, 0x1328, 0x077e,
- 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0xa88c, 0x6110, 0x2178, 0x7614,
- 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268,
- 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x817d, 0xa694, 0xff00,
- 0xa284, 0x0c00, 0x0040, 0x8100, 0x7018, 0x7862, 0x701c, 0x785e,
- 0xa284, 0x0300, 0x0040, 0x817d, 0x1078, 0x1381, 0x1040, 0x1328,
- 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838,
- 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00,
- 0x0040, 0x811e, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff,
- 0xa186, 0x0002, 0x0040, 0x813a, 0xa186, 0x0028, 0x00c0, 0x812c,
- 0x684b, 0x001c, 0x0078, 0x813c, 0xd6dc, 0x0040, 0x8133, 0x684b,
- 0x0015, 0x0078, 0x813c, 0xd6d4, 0x0040, 0x813a, 0x684b, 0x0007,
- 0x0078, 0x813c, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854,
- 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x815a, 0x7328, 0x732c, 0x6b56,
- 0x83ff, 0x0040, 0x815a, 0xa38a, 0x0009, 0x0048, 0x8151, 0x2019,
- 0x0008, 0x037e, 0x2308, 0x2019, 0xa898, 0xad90, 0x0019, 0x1078,
- 0x8739, 0x037f, 0xd6cc, 0x0040, 0x817d, 0x7124, 0x695a, 0x81ff,
- 0x0040, 0x817d, 0xa192, 0x0021, 0x00c8, 0x8171, 0x2071, 0xa898,
- 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x8739, 0x0078,
- 0x817d, 0x7838, 0xd0fc, 0x0040, 0x817a, 0x2009, 0x0020, 0x695a,
- 0x0078, 0x8166, 0x2d78, 0x1078, 0x86d1, 0x0d7f, 0x0e7f, 0x0f7f,
- 0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0xa88c, 0x7c04,
- 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a,
- 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x1cab, 0x1078, 0x6c26, 0x007c,
- 0x0d7e, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x81a4,
- 0x2001, 0xa5a2, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x60b8,
- 0x1078, 0x61d3, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x8207,
- 0xd1cc, 0x0040, 0x81de, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x81d6,
- 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198,
- 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318,
- 0x8210, 0x00f0, 0x81c5, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e,
- 0x017f, 0x2168, 0x1078, 0x13aa, 0x0078, 0x8201, 0x017e, 0x1078,
- 0x13aa, 0x0d7f, 0x1078, 0x8726, 0x0078, 0x8201, 0x6837, 0x0103,
- 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, 0x81fd, 0xa086,
- 0x0028, 0x00c0, 0x81ef, 0x684b, 0x001c, 0x0078, 0x81ff, 0xd1dc,
- 0x0040, 0x81f6, 0x684b, 0x0015, 0x0078, 0x81ff, 0xd1d4, 0x0040,
- 0x81fd, 0x684b, 0x0007, 0x0078, 0x81ff, 0x684b, 0x0000, 0x1078,
- 0x4982, 0x1078, 0x8cc4, 0x00c0, 0x8207, 0x1078, 0x753d, 0x0d7f,
- 0x007c, 0x2019, 0x0001, 0x1078, 0x6e6c, 0x6003, 0x0002, 0x2001,
- 0xa5a2, 0x2004, 0x603e, 0x1078, 0x60b8, 0x1078, 0x61d3, 0x007c,
- 0x1078, 0x60b8, 0x1078, 0x2813, 0x0d7e, 0x6110, 0x2168, 0x1078,
- 0x8a44, 0x0040, 0x822d, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847,
- 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d,
- 0x1078, 0x61d3, 0x007c, 0x684b, 0x0015, 0xd1fc, 0x0040, 0x823f,
- 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962,
- 0x685e, 0x007c, 0xa182, 0x0040, 0x0079, 0x8246, 0x8259, 0x8259,
- 0x8259, 0x8259, 0x8259, 0x825b, 0x8259, 0x8333, 0x833f, 0x8259,
- 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259,
- 0x8259, 0x1078, 0x1328, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071,
- 0xa88c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x0f7e, 0x2c78,
- 0x1078, 0x4893, 0x0f7f, 0x0040, 0x827e, 0xa684, 0x00ff, 0x00c0,
- 0x827e, 0x6024, 0xd0f4, 0x00c0, 0x827a, 0x7808, 0xa086, 0x0000,
- 0x00c0, 0x827e, 0x1078, 0x8cfa, 0x0078, 0x832e, 0x7e46, 0x7f4c,
- 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff,
- 0x0040, 0x8323, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040, 0x8294,
- 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040, 0x8320,
- 0xa686, 0x0100, 0x00c0, 0x82a6, 0x2001, 0xa899, 0x2004, 0xa005,
- 0x00c0, 0x82a6, 0xc6c4, 0x7e46, 0x0078, 0x8287, 0x1078, 0x1381,
- 0x1040, 0x1328, 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e,
- 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842,
- 0x6e46, 0xa68c, 0x0c00, 0x0040, 0x82c1, 0x7318, 0x6b62, 0x731c,
- 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x82dd, 0xa186,
- 0x0028, 0x00c0, 0x82cf, 0x684b, 0x001c, 0x0078, 0x82df, 0xd6dc,
- 0x0040, 0x82d6, 0x684b, 0x0015, 0x0078, 0x82df, 0xd6d4, 0x0040,
- 0x82dd, 0x684b, 0x0007, 0x0078, 0x82df, 0x684b, 0x0000, 0x6f4e,
- 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x82fd,
- 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0040, 0x82fd, 0xa38a, 0x0009,
- 0x0048, 0x82f4, 0x2019, 0x0008, 0x037e, 0x2308, 0x2019, 0xa898,
- 0xad90, 0x0019, 0x1078, 0x8739, 0x037f, 0xd6cc, 0x0040, 0x8320,
- 0x7124, 0x695a, 0x81ff, 0x0040, 0x8320, 0xa192, 0x0021, 0x00c8,
- 0x8314, 0x2071, 0xa898, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d,
- 0x1078, 0x8739, 0x0078, 0x8320, 0x7838, 0xd0fc, 0x0040, 0x831d,
- 0x2009, 0x0020, 0x695a, 0x0078, 0x8309, 0x2d78, 0x1078, 0x86d1,
- 0xd6dc, 0x00c0, 0x8326, 0xa006, 0x0078, 0x832c, 0x2001, 0x0001,
- 0x2071, 0xa88c, 0x7218, 0x731c, 0x1078, 0x1645, 0x0d7f, 0x0e7f,
- 0x0f7f, 0x077f, 0x007c, 0x2001, 0xa5a2, 0x2004, 0x603e, 0x20e1,
- 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15ec, 0x007c, 0x2001,
- 0xa5a2, 0x2004, 0x603e, 0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168,
- 0x694c, 0xd1e4, 0x0040, 0x846b, 0x603f, 0x0000, 0x0f7e, 0x2c78,
- 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8385, 0x6814, 0x6910, 0xa115,
- 0x0040, 0x8385, 0x6a60, 0xa206, 0x00c0, 0x8362, 0x685c, 0xa106,
- 0x0040, 0x8385, 0x684c, 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863,
- 0x0000, 0x685f, 0x0000, 0x6024, 0xd0f4, 0x00c0, 0x837a, 0x697c,
- 0x6810, 0xa102, 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6024,
- 0xc0f5, 0x6026, 0x0d7e, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e,
- 0x0d7f, 0x1078, 0x8cfa, 0x0078, 0x846b, 0x694c, 0xd1cc, 0x0040,
- 0x8430, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x83ea, 0x017e, 0x684c,
- 0x007e, 0x6850, 0x007e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff,
- 0xa0b6, 0x0002, 0x0040, 0x83bf, 0xa086, 0x0028, 0x00c0, 0x83a6,
- 0x684b, 0x001c, 0x784b, 0x001c, 0x0078, 0x83ca, 0xd1dc, 0x0040,
- 0x83b6, 0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x8ea5, 0x0040,
- 0x83b4, 0x7944, 0xc1dc, 0x7946, 0x0078, 0x83ca, 0xd1d4, 0x0040,
- 0x83bf, 0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x83ca, 0x684c,
- 0xd0ac, 0x0040, 0x83ca, 0x6810, 0x6914, 0xa115, 0x0040, 0x83ca,
- 0x1078, 0x8233, 0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e,
- 0xad90, 0x000d, 0xaf98, 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8,
- 0x2304, 0x2012, 0x8318, 0x8210, 0x00f0, 0x83d8, 0x157f, 0x0f7f,
- 0x007f, 0x6852, 0x007f, 0x684e, 0x017f, 0x2168, 0x1078, 0x13aa,
- 0x0078, 0x8465, 0x017e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff,
- 0xa0b6, 0x0002, 0x0040, 0x8417, 0xa086, 0x0028, 0x00c0, 0x83fe,
- 0x684b, 0x001c, 0x784b, 0x001c, 0x0078, 0x8422, 0xd1dc, 0x0040,
- 0x840e, 0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x8ea5, 0x0040,
- 0x840c, 0x7944, 0xc1dc, 0x7946, 0x0078, 0x8422, 0xd1d4, 0x0040,
- 0x8417, 0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x8422, 0x684c,
- 0xd0ac, 0x0040, 0x8422, 0x6810, 0x6914, 0xa115, 0x0040, 0x8422,
- 0x1078, 0x8233, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e,
- 0x0f7f, 0x1078, 0x13aa, 0x0d7f, 0x1078, 0x8726, 0x0078, 0x8465,
- 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040,
- 0x8456, 0xa086, 0x0028, 0x00c0, 0x8441, 0x684b, 0x001c, 0x0078,
- 0x8463, 0xd1dc, 0x0040, 0x844f, 0x684b, 0x0015, 0x1078, 0x8ea5,
- 0x0040, 0x844d, 0x6944, 0xc1dc, 0x6946, 0x0078, 0x8463, 0xd1d4,
- 0x0040, 0x8456, 0x684b, 0x0007, 0x0078, 0x8463, 0x684b, 0x0000,
- 0x684c, 0xd0ac, 0x0040, 0x8463, 0x6810, 0x6914, 0xa115, 0x0040,
- 0x8463, 0x1078, 0x8233, 0x1078, 0x4982, 0x1078, 0x8cc4, 0x00c0,
- 0x846b, 0x1078, 0x753d, 0x0d7f, 0x007c, 0x1078, 0x6010, 0x0078,
- 0x8473, 0x1078, 0x60b8, 0x1078, 0x8a44, 0x0040, 0x8492, 0x0d7e,
- 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xa30c, 0x210c, 0xd18c,
- 0x00c0, 0x849d, 0xd184, 0x00c0, 0x8499, 0x6108, 0x694a, 0xa18e,
- 0x0029, 0x00c0, 0x848d, 0x1078, 0xa181, 0x6847, 0x0000, 0x1078,
- 0x4982, 0x0d7f, 0x1078, 0x753d, 0x1078, 0x6109, 0x1078, 0x61d3,
- 0x007c, 0x684b, 0x0004, 0x0078, 0x848d, 0x684b, 0x0004, 0x0078,
- 0x848d, 0xa182, 0x0040, 0x0079, 0x84a5, 0x84b8, 0x84b8, 0x84b8,
- 0x84b8, 0x84b8, 0x84ba, 0x84b8, 0x84bd, 0x84b8, 0x84b8, 0x84b8,
- 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8,
- 0x1078, 0x1328, 0x1078, 0x753d, 0x007c, 0x007e, 0x027e, 0xa016,
- 0x1078, 0x15ec, 0x027f, 0x007f, 0x007c, 0xa182, 0x0085, 0x0079,
- 0x84c9, 0x84d2, 0x84d0, 0x84d0, 0x84de, 0x84d0, 0x84d0, 0x84d0,
- 0x1078, 0x1328, 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x127e,
- 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x007c, 0x027e, 0x057e,
- 0x0d7e, 0x0e7e, 0x2071, 0xa880, 0x7224, 0x6212, 0x7220, 0x1078,
- 0x8a30, 0x0040, 0x8503, 0x2268, 0x6800, 0xa086, 0x0000, 0x0040,
- 0x8503, 0x6018, 0x6d18, 0xa52e, 0x00c0, 0x8503, 0x0c7e, 0x2d60,
- 0x1078, 0x874a, 0x0c7f, 0x0040, 0x8503, 0x6803, 0x0002, 0x6007,
- 0x0086, 0x0078, 0x8505, 0x6007, 0x0087, 0x6003, 0x0001, 0x1078,
- 0x5bf8, 0x1078, 0x6109, 0x0f7e, 0x2278, 0x1078, 0x4893, 0x0f7f,
- 0x0040, 0x851d, 0x6824, 0xd0ec, 0x0040, 0x851d, 0x0c7e, 0x2260,
- 0x603f, 0x0000, 0x1078, 0x8cfa, 0x0c7f, 0x0e7f, 0x0d7f, 0x057f,
- 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x8533, 0x6004, 0xa08a,
- 0x0085, 0x1048, 0x1328, 0xa08a, 0x008c, 0x10c8, 0x1328, 0xa082,
- 0x0085, 0x0079, 0x8542, 0xa186, 0x0027, 0x0040, 0x853b, 0xa186,
- 0x0014, 0x10c0, 0x1328, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078,
- 0x6109, 0x007c, 0x8549, 0x854b, 0x854b, 0x8549, 0x8549, 0x8549,
- 0x8549, 0x1078, 0x1328, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078,
- 0x6109, 0x007c, 0xa186, 0x0013, 0x00c0, 0x855c, 0x6004, 0xa082,
- 0x0085, 0x2008, 0x0078, 0x8597, 0xa186, 0x0027, 0x00c0, 0x857f,
- 0x1078, 0x6010, 0x1078, 0x2813, 0x0d7e, 0x6010, 0x2068, 0x1078,
- 0x8a44, 0x0040, 0x8575, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b,
- 0x0029, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d,
- 0x1078, 0x6109, 0x007c, 0x1078, 0x7583, 0x0078, 0x857a, 0xa186,
- 0x0014, 0x00c0, 0x857b, 0x1078, 0x6010, 0x0d7e, 0x6010, 0x2068,
- 0x1078, 0x8a44, 0x0040, 0x8575, 0x6837, 0x0103, 0x6847, 0x0000,
- 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x0078, 0x8571, 0x0079,
- 0x8599, 0x85a2, 0x85a0, 0x85a0, 0x85a0, 0x85a0, 0x85a0, 0x85bd,
- 0x1078, 0x1328, 0x1078, 0x6010, 0x6030, 0xa08c, 0xff00, 0x810f,
- 0xa186, 0x0039, 0x0040, 0x85b0, 0xa186, 0x0035, 0x00c0, 0x85b4,
- 0x2001, 0xa5a0, 0x0078, 0x85b6, 0x2001, 0xa5a1, 0x2004, 0x6016,
- 0x6003, 0x000c, 0x1078, 0x6109, 0x007c, 0x1078, 0x6010, 0x6030,
- 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x85cb, 0xa186,
- 0x0035, 0x00c0, 0x85cf, 0x2001, 0xa5a0, 0x0078, 0x85d1, 0x2001,
- 0xa5a1, 0x2004, 0x6016, 0x6003, 0x000e, 0x1078, 0x6109, 0x007c,
- 0xa182, 0x008c, 0x00c8, 0x85e2, 0xa182, 0x0085, 0x0048, 0x85e2,
- 0x0079, 0x85e5, 0x1078, 0x7583, 0x007c, 0x85ec, 0x85ec, 0x85ec,
- 0x85ec, 0x85ee, 0x8643, 0x85ec, 0x1078, 0x1328, 0x0f7e, 0x2c78,
- 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8601, 0x6030, 0xa08c, 0xff00,
- 0x810f, 0xa186, 0x0039, 0x0040, 0x865a, 0xa186, 0x0035, 0x0040,
- 0x865a, 0x0d7e, 0x1078, 0x8bf4, 0x1078, 0x8a44, 0x0040, 0x8625,
- 0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x8616,
- 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0078, 0x8621, 0xd0bc, 0x0040,
- 0x861d, 0x684b, 0x0002, 0x0078, 0x8621, 0x684b, 0x0005, 0x1078,
- 0x8cc0, 0x6847, 0x0000, 0x1078, 0x4982, 0x2c68, 0x1078, 0x74d7,
- 0x0040, 0x863e, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xa88e,
- 0x210c, 0x6136, 0x2009, 0xa88f, 0x210c, 0x613a, 0x6918, 0x611a,
- 0x6920, 0x6122, 0x601f, 0x0001, 0x1078, 0x5bf8, 0x2d60, 0x1078,
- 0x753d, 0x0d7f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f,
- 0x0040, 0x8680, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035,
- 0x0040, 0x865a, 0xa186, 0x001e, 0x0040, 0x865a, 0xa186, 0x0039,
- 0x00c0, 0x8680, 0x0d7e, 0x2c68, 0x1078, 0x8ef5, 0x00c0, 0x86a4,
- 0x1078, 0x74d7, 0x0040, 0x867d, 0x6106, 0x6003, 0x0001, 0x601f,
- 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, 0x612e, 0x6930,
- 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, 0x613a, 0x6920,
- 0x6122, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x2d60, 0x0078, 0x86a4,
- 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x86a4, 0x6837,
- 0x0103, 0x6850, 0xd0b4, 0x0040, 0x8693, 0xc0ec, 0x6852, 0x684b,
- 0x0006, 0x0078, 0x869e, 0xd0bc, 0x0040, 0x869a, 0x684b, 0x0002,
- 0x0078, 0x869e, 0x684b, 0x0005, 0x1078, 0x8cc0, 0x6847, 0x0000,
- 0x1078, 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d, 0x007c,
- 0x017e, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x86b8,
- 0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x1078, 0x4982,
- 0x0d7f, 0x017f, 0xa186, 0x0013, 0x0040, 0x86ca, 0xa186, 0x0014,
- 0x0040, 0x86ca, 0xa186, 0x0027, 0x0040, 0x86ca, 0x1078, 0x7583,
- 0x0078, 0x86d0, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109,
- 0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, 0xa182,
- 0x0101, 0x00c8, 0x86dd, 0x0078, 0x86df, 0x2009, 0x0100, 0x2130,
- 0x2069, 0xa898, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90,
- 0x001d, 0x1078, 0x8739, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0040,
- 0x86f3, 0x1078, 0x13aa, 0x1078, 0x1381, 0x0040, 0x871d, 0x8528,
- 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d,
- 0x00c8, 0x8709, 0x2608, 0xad90, 0x000f, 0x1078, 0x8739, 0x0078,
- 0x871d, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f,
- 0x1078, 0x8739, 0x0078, 0x86f3, 0x0f7f, 0x852f, 0xa5ad, 0x0003,
- 0x7d36, 0xa5ac, 0x0000, 0x0078, 0x8722, 0x0f7f, 0x852f, 0xa5ad,
- 0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, 0x8dff,
- 0x0040, 0x8737, 0x6804, 0xa07d, 0x0040, 0x8735, 0x6807, 0x0000,
- 0x1078, 0x4982, 0x2f68, 0x0078, 0x872a, 0x1078, 0x4982, 0x0f7f,
- 0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x873f, 0x8108, 0x810c,
- 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, 0x8741,
- 0x157f, 0x007c, 0x067e, 0x127e, 0x2091, 0x8000, 0x2031, 0x0001,
- 0x601c, 0xa084, 0x000f, 0x1079, 0x8766, 0x127f, 0x067f, 0x007c,
- 0x127e, 0x2091, 0x8000, 0x067e, 0x2031, 0x0000, 0x601c, 0xa084,
- 0x000f, 0x1079, 0x8766, 0x067f, 0x127f, 0x007c, 0x8780, 0x876e,
- 0x877b, 0x879c, 0x876e, 0x877b, 0x879c, 0x877b, 0x1078, 0x1328,
- 0x037e, 0x2019, 0x0010, 0x1078, 0x9a6a, 0x601f, 0x0006, 0x6003,
- 0x0007, 0x037f, 0x007c, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c,
- 0x0d7e, 0x86ff, 0x00c0, 0x8797, 0x6010, 0x2068, 0x1078, 0x8a44,
- 0x0040, 0x8799, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4a60, 0x1078,
- 0x8cc0, 0x1078, 0x4982, 0x1078, 0x753d, 0xa085, 0x0001, 0x0d7f,
- 0x007c, 0xa006, 0x0078, 0x8797, 0x6000, 0xa08a, 0x0010, 0x10c8,
- 0x1328, 0x1079, 0x87a4, 0x007c, 0x87b4, 0x87d4, 0x87b6, 0x87f7,
- 0x87d0, 0x87b4, 0x877b, 0x8780, 0x8780, 0x877b, 0x877b, 0x877b,
- 0x877b, 0x877b, 0x877b, 0x877b, 0x1078, 0x1328, 0x86ff, 0x00c0,
- 0x87cd, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x87c2,
- 0x1078, 0x8cc0, 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f,
- 0x0002, 0x1078, 0x5bf8, 0x1078, 0x6109, 0xa085, 0x0001, 0x007c,
- 0x1078, 0x1749, 0x0078, 0x87b6, 0x0e7e, 0x2071, 0xa5ab, 0x7024,
- 0xac06, 0x00c0, 0x87dd, 0x1078, 0x6dda, 0x601c, 0xa084, 0x000f,
- 0xa086, 0x0006, 0x00c0, 0x87ef, 0x087e, 0x097e, 0x2049, 0x0001,
- 0x2c40, 0x1078, 0x7058, 0x097f, 0x087f, 0x0078, 0x87f1, 0x1078,
- 0x6cd2, 0x0e7f, 0x00c0, 0x87b6, 0x1078, 0x877b, 0x007c, 0x037e,
- 0x0e7e, 0x2071, 0xa5ab, 0x703c, 0xac06, 0x00c0, 0x8807, 0x2019,
- 0x0000, 0x1078, 0x6e6c, 0x0e7f, 0x037f, 0x0078, 0x87b6, 0x1078,
- 0x719a, 0x0e7f, 0x037f, 0x00c0, 0x87b6, 0x1078, 0x877b, 0x007c,
- 0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079, 0x8818, 0x0c7f, 0x007c,
- 0x8827, 0x8895, 0x89cd, 0x8832, 0x8c01, 0x8827, 0x9a5b, 0x753d,
- 0x8895, 0x1078, 0x8c3b, 0x00c0, 0x8827, 0x1078, 0x7a05, 0x007c,
- 0x1078, 0x6010, 0x1078, 0x6109, 0x1078, 0x753d, 0x007c, 0x6017,
- 0x0001, 0x007c, 0x6010, 0xa080, 0x0019, 0x2c02, 0x6000, 0xa08a,
- 0x0010, 0x10c8, 0x1328, 0x1079, 0x883e, 0x007c, 0x884e, 0x8850,
- 0x8872, 0x8884, 0x8891, 0x884e, 0x8827, 0x8827, 0x8827, 0x8884,
- 0x8884, 0x884e, 0x884e, 0x884e, 0x884e, 0x888e, 0x1078, 0x1328,
- 0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0xa5ab,
- 0x7024, 0xac06, 0x0040, 0x886e, 0x1078, 0x6cd2, 0x6007, 0x0085,
- 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xa5a1, 0x2004, 0x6016,
- 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0e7f, 0x007c, 0x6017, 0x0001,
- 0x0078, 0x886c, 0x0d7e, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852,
- 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078,
- 0x5bf8, 0x1078, 0x6109, 0x007c, 0x0d7e, 0x6017, 0x0001, 0x6010,
- 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x007c, 0x1078, 0x753d,
- 0x007c, 0x1078, 0x1749, 0x0078, 0x8872, 0x6000, 0xa08a, 0x0010,
- 0x10c8, 0x1328, 0x1079, 0x889d, 0x007c, 0x88ad, 0x882f, 0x88af,
- 0x88ad, 0x88af, 0x88af, 0x8828, 0x88ad, 0x8821, 0x8821, 0x88ad,
- 0x88ad, 0x88ad, 0x88ad, 0x88ad, 0x88ad, 0x1078, 0x1328, 0x0d7e,
- 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa08a, 0x000c,
- 0x10c8, 0x1328, 0x1079, 0x88bd, 0x007c, 0x88c9, 0x8971, 0x88cb,
- 0x890b, 0x88cb, 0x890b, 0x88cb, 0x88d8, 0x88c9, 0x890b, 0x88c9,
- 0x88f5, 0x1078, 0x1328, 0x6004, 0xa08e, 0x0016, 0x0040, 0x8906,
- 0xa08e, 0x0004, 0x0040, 0x8906, 0xa08e, 0x0002, 0x0040, 0x8906,
- 0x6004, 0x1078, 0x8c3b, 0x0040, 0x898c, 0xa08e, 0x0021, 0x0040,
- 0x8990, 0xa08e, 0x0022, 0x0040, 0x898c, 0xa08e, 0x003d, 0x0040,
- 0x8990, 0xa08e, 0x0039, 0x0040, 0x8994, 0xa08e, 0x0035, 0x0040,
- 0x8994, 0xa08e, 0x001e, 0x0040, 0x8908, 0xa08e, 0x0001, 0x00c0,
- 0x8904, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f,
- 0xa086, 0x0006, 0x0040, 0x8906, 0x1078, 0x2813, 0x1078, 0x7a05,
- 0x1078, 0x8c01, 0x007c, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016,
- 0x0040, 0x8961, 0xa186, 0x0002, 0x00c0, 0x8934, 0x6018, 0x2068,
- 0x68a0, 0xd0bc, 0x00c0, 0x89b8, 0x6840, 0xa084, 0x00ff, 0xa005,
- 0x0040, 0x8934, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007,
- 0x6017, 0x0398, 0x1078, 0x74d7, 0x0040, 0x8934, 0x2d00, 0x601a,
- 0x601f, 0x0001, 0x0078, 0x8961, 0x0d7f, 0x0c7f, 0x6004, 0xa08e,
- 0x0002, 0x00c0, 0x8952, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086,
- 0x007e, 0x00c0, 0x8952, 0x2009, 0xa332, 0x2104, 0xc085, 0x200a,
- 0x0e7e, 0x2071, 0xa300, 0x1078, 0x41f5, 0x0e7f, 0x1078, 0x7a05,
- 0x0078, 0x8956, 0x1078, 0x7a05, 0x1078, 0x2813, 0x0e7e, 0x127e,
- 0x2091, 0x8000, 0x1078, 0x2839, 0x127f, 0x0e7f, 0x1078, 0x8c01,
- 0x007c, 0x2001, 0x0002, 0x1078, 0x443f, 0x6003, 0x0001, 0x6007,
- 0x0002, 0x1078, 0x5c45, 0x1078, 0x6109, 0x0d7f, 0x0c7f, 0x0078,
- 0x8960, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, 0x0040, 0x8961,
- 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x8934,
- 0x8001, 0x6842, 0x6003, 0x0001, 0x1078, 0x5c45, 0x1078, 0x6109,
- 0x0d7f, 0x0c7f, 0x0078, 0x8960, 0x1078, 0x7a05, 0x0078, 0x8908,
- 0x1078, 0x7a28, 0x0078, 0x8908, 0x0d7e, 0x2c68, 0x6104, 0x1078,
- 0x8ef5, 0x0d7f, 0x0040, 0x89a0, 0x1078, 0x753d, 0x0078, 0x89b7,
- 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007,
- 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, 0x600a, 0x2001,
- 0xa5a1, 0x2004, 0x6016, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x007c,
- 0x0d7f, 0x0c7f, 0x1078, 0x7a05, 0x1078, 0x2813, 0x0e7e, 0x127e,
- 0x2091, 0x8000, 0x1078, 0x2839, 0x6013, 0x0000, 0x601f, 0x0007,
- 0x6017, 0x0398, 0x127f, 0x0e7f, 0x007c, 0x6000, 0xa08a, 0x0010,
- 0x10c8, 0x1328, 0x1079, 0x89d5, 0x007c, 0x89e5, 0x89e5, 0x89e5,
- 0x89e5, 0x89e5, 0x89e5, 0x89e5, 0x89e5, 0x89e5, 0x8827, 0x89e5,
- 0x882f, 0x89e7, 0x882f, 0x89f5, 0x89e5, 0x1078, 0x1328, 0x6004,
- 0xa086, 0x008b, 0x0040, 0x89f5, 0x6007, 0x008b, 0x6003, 0x000d,
- 0x1078, 0x5bf8, 0x1078, 0x6109, 0x007c, 0x1078, 0x8bf4, 0x1078,
- 0x8a44, 0x0040, 0x8a2d, 0x1078, 0x2813, 0x0d7e, 0x1078, 0x8a44,
- 0x0040, 0x8a0f, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006,
- 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x1078, 0x4982, 0x2c68,
- 0x1078, 0x74d7, 0x0040, 0x8a1d, 0x6818, 0x601a, 0x0c7e, 0x2d60,
- 0x1078, 0x8c01, 0x0c7f, 0x0078, 0x8a1e, 0x2d60, 0x0d7f, 0x6013,
- 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078,
- 0x5c45, 0x1078, 0x6109, 0x0078, 0x8a2f, 0x1078, 0x8c01, 0x007c,
- 0xa284, 0x000f, 0x00c0, 0x8a41, 0xa282, 0xaa00, 0x0048, 0x8a41,
- 0x2001, 0xa315, 0x2004, 0xa202, 0x00c8, 0x8a41, 0xa085, 0x0001,
- 0x007c, 0xa006, 0x0078, 0x8a40, 0x027e, 0x0e7e, 0x2071, 0xa300,
- 0x6210, 0x7058, 0xa202, 0x0048, 0x8a56, 0x705c, 0xa202, 0x00c8,
- 0x8a56, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c, 0xa006, 0x0078,
- 0x8a53, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e, 0x2091, 0x8000,
- 0x2061, 0xaa00, 0x2071, 0xa300, 0x7344, 0x7060, 0xa302, 0x00c8,
- 0x8a83, 0x601c, 0xa206, 0x00c0, 0x8a7b, 0x1078, 0x8d66, 0x0040,
- 0x8a7b, 0x1078, 0x8c3b, 0x00c0, 0x8a77, 0x1078, 0x7a05, 0x0c7e,
- 0x1078, 0x753d, 0x0c7f, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8,
- 0x8a83, 0x0078, 0x8a64, 0x127f, 0x007f, 0x037f, 0x0c7f, 0x0e7f,
- 0x007c, 0x0e7e, 0x0c7e, 0x017e, 0xa188, 0xa434, 0x210c, 0x81ff,
- 0x0040, 0x8aa1, 0x2061, 0xaa00, 0x2071, 0xa300, 0x017e, 0x1078,
- 0x74d7, 0x017f, 0x0040, 0x8aa4, 0x611a, 0x1078, 0x2813, 0x1078,
- 0x753d, 0xa006, 0x0078, 0x8aa6, 0xa085, 0x0001, 0x017f, 0x0c7f,
- 0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e,
- 0x1078, 0x74d7, 0x057f, 0x0040, 0x8ac3, 0x6612, 0x651a, 0x601f,
- 0x0003, 0x2009, 0x004b, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f,
- 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8abf, 0x0c7e, 0x057e,
- 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x74d7, 0x057f,
- 0x0040, 0x8af1, 0x6013, 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e,
- 0x2560, 0x1078, 0x471b, 0x0c7f, 0x1078, 0x5d53, 0x077e, 0x2039,
- 0x0000, 0x1078, 0x5c78, 0x2c08, 0x1078, 0x9c38, 0x077f, 0x2009,
- 0x004c, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f,
- 0x007c, 0xa006, 0x0078, 0x8aed, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e,
- 0x1078, 0x74d7, 0x2c78, 0x0c7f, 0x0040, 0x8b0e, 0x7e12, 0x2c00,
- 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x1078, 0x8b4e, 0x2f60,
- 0x2009, 0x004d, 0x1078, 0x756c, 0xa085, 0x0001, 0x047f, 0x0c7f,
- 0x0f7f, 0x007c, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x74d7,
- 0x2c78, 0x0c7f, 0x0040, 0x8b2c, 0x7e12, 0x2c00, 0x781a, 0x781f,
- 0x0003, 0x2021, 0x0005, 0x1078, 0x8b4e, 0x2f60, 0x2009, 0x004e,
- 0x1078, 0x756c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c,
- 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x74d7, 0x2c78, 0x0c7f,
- 0x0040, 0x8b4a, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021,
- 0x0004, 0x1078, 0x8b4e, 0x2f60, 0x2009, 0x0052, 0x1078, 0x756c,
- 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c, 0x097e, 0x077e,
- 0x127e, 0x2091, 0x8000, 0x1078, 0x46a7, 0x0040, 0x8b5b, 0x2001,
- 0x8b53, 0x0078, 0x8b61, 0x1078, 0x466d, 0x0040, 0x8b6a, 0x2001,
- 0x8b5b, 0x007e, 0xa00e, 0x2400, 0x1078, 0x4a60, 0x1078, 0x4982,
- 0x007f, 0x007a, 0x2418, 0x1078, 0x5fa7, 0x62a0, 0x087e, 0x2041,
- 0x0001, 0x2039, 0x0001, 0x2608, 0x1078, 0x5d6d, 0x087f, 0x1078,
- 0x5c78, 0x2f08, 0x2648, 0x1078, 0x9c38, 0x613c, 0x81ff, 0x1040,
- 0x5e21, 0x127f, 0x077f, 0x097f, 0x007c, 0x0c7e, 0x127e, 0x2091,
- 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8b9e, 0x660a,
- 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, 0x1078,
- 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
- 0x8b9b, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x74d7,
- 0x017f, 0x0040, 0x8bba, 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00,
- 0x6012, 0x2009, 0x0021, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f,
- 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8bb7, 0x0c7e, 0x127e, 0x2091,
- 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8bd6, 0x660a,
- 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, 0x1078,
- 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
- 0x8bd3, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x74d7,
- 0x017f, 0x0040, 0x8bf1, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012,
- 0x2009, 0x0000, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f,
- 0x007c, 0xa006, 0x0078, 0x8bee, 0x027e, 0x0d7e, 0x6218, 0x2268,
- 0x6a3c, 0x82ff, 0x0040, 0x8bfe, 0x8211, 0x6a3e, 0x0d7f, 0x027f,
- 0x007c, 0x007e, 0x6000, 0xa086, 0x0000, 0x0040, 0x8c13, 0x6013,
- 0x0000, 0x601f, 0x0007, 0x2001, 0xa5a1, 0x2004, 0x6016, 0x1078,
- 0xa134, 0x603f, 0x0000, 0x007f, 0x007c, 0x067e, 0x0c7e, 0x0d7e,
- 0x2031, 0xa352, 0x2634, 0xd6e4, 0x0040, 0x8c23, 0x6618, 0x2660,
- 0x6e48, 0x1078, 0x461b, 0x0d7f, 0x0c7f, 0x067f, 0x007c, 0x007e,
- 0x017e, 0x6004, 0xa08e, 0x0002, 0x0040, 0x8c38, 0xa08e, 0x0003,
- 0x0040, 0x8c38, 0xa08e, 0x0004, 0x0040, 0x8c38, 0xa085, 0x0001,
- 0x017f, 0x007f, 0x007c, 0x007e, 0x0d7e, 0x6010, 0xa06d, 0x0040,
- 0x8c48, 0x6838, 0xd0fc, 0x0040, 0x8c48, 0xa006, 0x0078, 0x8c4a,
- 0xa085, 0x0001, 0x0d7f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091,
- 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8c67, 0x611a,
- 0x601f, 0x0001, 0x2d00, 0x6012, 0x1078, 0x2813, 0x2009, 0x0028,
- 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006,
- 0x0078, 0x8c64, 0xa186, 0x0015, 0x00c0, 0x8c7f, 0x2011, 0xa31f,
- 0x2204, 0xa086, 0x0074, 0x00c0, 0x8c7f, 0x1078, 0x7d0d, 0x6003,
- 0x0001, 0x6007, 0x0029, 0x1078, 0x5c45, 0x0078, 0x8c83, 0x1078,
- 0x7a05, 0x1078, 0x753d, 0x007c, 0xa186, 0x0016, 0x00c0, 0x8c8e,
- 0x2001, 0x0004, 0x1078, 0x443f, 0x0078, 0x8caf, 0xa186, 0x0015,
- 0x00c0, 0x8cb3, 0x2011, 0xa31f, 0x2204, 0xa086, 0x0014, 0x00c0,
- 0x8cb3, 0x0d7e, 0x6018, 0x2068, 0x1078, 0x457d, 0x0d7f, 0x1078,
- 0x7dba, 0x00c0, 0x8cb3, 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f,
- 0xa005, 0x0040, 0x8cb3, 0x2001, 0x0006, 0x1078, 0x443f, 0x1078,
- 0x7608, 0x0078, 0x8cb7, 0x1078, 0x7a05, 0x1078, 0x753d, 0x007c,
- 0x6848, 0xa086, 0x0005, 0x00c0, 0x8cbf, 0x1078, 0x8cc0, 0x007c,
- 0x6850, 0xc0ad, 0x6852, 0x007c, 0x0e7e, 0x2071, 0xa88c, 0x7014,
- 0xd0e4, 0x0040, 0x8cd5, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007,
- 0x0050, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0e7f, 0x007c, 0x0c7e,
- 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8ce4, 0x601c,
- 0xa084, 0x000f, 0x1079, 0x8ce6, 0x0c7f, 0x007c, 0x8827, 0x8cf1,
- 0x8cf4, 0x8cf7, 0x9f00, 0x9f1c, 0x9f1f, 0x8827, 0x8827, 0x1078,
- 0x1328, 0x0005, 0x0005, 0x007c, 0x0005, 0x0005, 0x007c, 0x1078,
- 0x8cfa, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0040, 0x8d29,
- 0x1078, 0x74d7, 0x00c0, 0x8d0a, 0x2001, 0xa5a2, 0x2004, 0x783e,
- 0x0078, 0x8d29, 0x7818, 0x601a, 0x781c, 0xa086, 0x0003, 0x0040,
- 0x8d17, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0078, 0x8d1b, 0x7808,
- 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007, 0x0035,
- 0x6003, 0x0001, 0x7920, 0x6122, 0x1078, 0x5bf8, 0x1078, 0x6109,
- 0x2f60, 0x0f7f, 0x007c, 0x017e, 0x0f7e, 0x682c, 0x6032, 0xa08e,
- 0x0001, 0x0040, 0x8d3c, 0xa086, 0x0005, 0x0040, 0x8d40, 0xa006,
- 0x602a, 0x602e, 0x0078, 0x8d51, 0x6824, 0xc0f4, 0xc0d5, 0x6826,
- 0x6810, 0x2078, 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, 0xa103,
- 0x00c8, 0x8d37, 0x6834, 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a,
- 0x602e, 0x2d00, 0x6036, 0x6808, 0x603a, 0x6918, 0x611a, 0x6920,
- 0x6122, 0x601f, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, 0x1078,
- 0x5bf8, 0x6803, 0x0002, 0x0f7f, 0x017f, 0x007c, 0x007e, 0x017e,
- 0x6004, 0xa08e, 0x0034, 0x0040, 0x8d8b, 0xa08e, 0x0035, 0x0040,
- 0x8d8b, 0xa08e, 0x0036, 0x0040, 0x8d8b, 0xa08e, 0x0037, 0x0040,
- 0x8d8b, 0xa08e, 0x0038, 0x0040, 0x8d8b, 0xa08e, 0x0039, 0x0040,
- 0x8d8b, 0xa08e, 0x003a, 0x0040, 0x8d8b, 0xa08e, 0x003b, 0x0040,
- 0x8d8b, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, 0x0f7e, 0x2c78,
- 0x1078, 0x4893, 0x00c0, 0x8d98, 0xa085, 0x0001, 0x0078, 0x8da7,
- 0x6024, 0xd0f4, 0x00c0, 0x8da6, 0xc0f5, 0x6026, 0x6010, 0x2078,
- 0x7828, 0x603a, 0x782c, 0x6036, 0x1078, 0x1749, 0xa006, 0x0f7f,
- 0x007c, 0x007e, 0x017e, 0x027e, 0x037e, 0x0e7e, 0x2001, 0xa59c,
- 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x1078, 0x5a98, 0x2001,
- 0xa5a0, 0x82ff, 0x00c0, 0x8dbe, 0x2011, 0x0002, 0x2202, 0x2001,
- 0xa59e, 0x200c, 0x8000, 0x2014, 0x2071, 0xa58c, 0x711a, 0x721e,
- 0x2001, 0x0064, 0x1078, 0x5a98, 0x2001, 0xa5a1, 0x82ff, 0x00c0,
- 0x8dd3, 0x2011, 0x0002, 0x2202, 0x2009, 0xa5a2, 0xa280, 0x000a,
- 0x200a, 0x0e7f, 0x037f, 0x027f, 0x017f, 0x007f, 0x007c, 0x007e,
- 0x0e7e, 0x2001, 0xa5a0, 0x2003, 0x0028, 0x2001, 0xa5a1, 0x2003,
- 0x0014, 0x2071, 0xa58c, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001,
- 0xa5a2, 0x2003, 0x001e, 0x0e7f, 0x007f, 0x007c, 0x0c7e, 0x127e,
- 0x2091, 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8e0e,
- 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, 0x1078,
- 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
- 0x8e0b, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, 0xa300, 0xa186, 0x0015,
- 0x00c0, 0x8e40, 0x707c, 0xa086, 0x0018, 0x00c0, 0x8e40, 0x6010,
- 0x2068, 0x6a3c, 0xd2e4, 0x00c0, 0x8e34, 0x2c78, 0x1078, 0x62c6,
- 0x0040, 0x8e48, 0x7068, 0x6a50, 0xa206, 0x00c0, 0x8e3c, 0x706c,
- 0x6a54, 0xa206, 0x00c0, 0x8e3c, 0x6218, 0xa290, 0x0028, 0x2214,
- 0x2009, 0x0000, 0x1078, 0x285b, 0x1078, 0x7608, 0x0078, 0x8e44,
- 0x1078, 0x7a05, 0x1078, 0x753d, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c,
- 0x704c, 0xa080, 0x293f, 0x2004, 0x6a54, 0xa206, 0x0040, 0x8e34,
- 0x0078, 0x8e3c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078,
- 0x74d7, 0x017f, 0x0040, 0x8e6a, 0x611a, 0x601f, 0x0001, 0x2d00,
- 0x6012, 0x2009, 0x0043, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f,
- 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8e67, 0x0d7e, 0x0e7e, 0x0f7e,
- 0x2071, 0xa300, 0xa186, 0x0015, 0x00c0, 0x8e93, 0x707c, 0xa086,
- 0x0004, 0x00c0, 0x8e93, 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x1078,
- 0x62c6, 0x0040, 0x8e9b, 0x7068, 0x6a08, 0xa206, 0x00c0, 0x8e8f,
- 0x706c, 0x6a0c, 0xa206, 0x00c0, 0x8e8f, 0x1078, 0x2813, 0x1078,
- 0x7608, 0x0078, 0x8e97, 0x1078, 0x7a05, 0x1078, 0x753d, 0x0f7f,
- 0x0e7f, 0x0d7f, 0x007c, 0x704c, 0xa080, 0x293f, 0x2004, 0x6a0c,
- 0xa206, 0x0040, 0x8e8d, 0x0078, 0x8e8f, 0x017e, 0x027e, 0x684c,
- 0xd0ac, 0x0040, 0x8ebd, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040,
- 0x8ebd, 0x6860, 0xa106, 0x00c0, 0x8eb9, 0x685c, 0xa206, 0x0040,
- 0x8ebd, 0x6962, 0x6a5e, 0xa085, 0x0001, 0x027f, 0x017f, 0x007c,
- 0x0e7e, 0x127e, 0x2071, 0xa300, 0x2091, 0x8000, 0x7544, 0xa582,
- 0x0001, 0x0048, 0x8ef2, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000,
- 0x0040, 0x8ede, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8, 0x8eda,
- 0x0078, 0x8ecd, 0x2061, 0xaa00, 0x0078, 0x8ecd, 0x6003, 0x0008,
- 0x8529, 0x7546, 0xaca8, 0x0010, 0x7054, 0xa502, 0x00c8, 0x8eee,
- 0x754a, 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704b, 0xaa00,
- 0x0078, 0x8ee9, 0xa006, 0x0078, 0x8eeb, 0x0c7e, 0x027e, 0x017e,
- 0xa186, 0x0035, 0x0040, 0x8eff, 0x6a34, 0x0078, 0x8f00, 0x6a28,
- 0x1078, 0x8a30, 0x0040, 0x8f29, 0x2260, 0x611c, 0xa186, 0x0003,
- 0x0040, 0x8f0e, 0xa186, 0x0006, 0x00c0, 0x8f25, 0x6834, 0xa206,
- 0x0040, 0x8f1d, 0x6838, 0xa206, 0x00c0, 0x8f25, 0x6108, 0x6834,
- 0xa106, 0x00c0, 0x8f25, 0x0078, 0x8f22, 0x6008, 0x6938, 0xa106,
- 0x00c0, 0x8f25, 0x6018, 0x6918, 0xa106, 0x017f, 0x027f, 0x0c7f,
- 0x007c, 0xa085, 0x0001, 0x0078, 0x8f25, 0x067e, 0x6000, 0xa0b2,
- 0x0010, 0x10c8, 0x1328, 0x1079, 0x8f37, 0x067f, 0x007c, 0x8f47,
- 0x93bb, 0x94d3, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f81,
- 0x955e, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x1078,
- 0x1328, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1328, 0x1079,
- 0x8f53, 0x067f, 0x007c, 0x8f63, 0x99f6, 0x8f63, 0x8f63, 0x8f63,
- 0x8f63, 0x8f63, 0x8f63, 0x99b4, 0x9a44, 0x8f63, 0xa053, 0xa087,
- 0xa053, 0xa087, 0x8f63, 0x1078, 0x1328, 0x067e, 0x6000, 0xa0b2,
- 0x0010, 0x10c8, 0x1328, 0x1079, 0x8f6f, 0x067f, 0x007c, 0x8f7f,
- 0x969f, 0x976a, 0x9798, 0x9813, 0x8f7f, 0x9919, 0x98c1, 0x956a,
- 0x9988, 0x999e, 0x8f7f, 0x8f7f, 0x8f7f, 0x8f7f, 0x8f7f, 0x1078,
- 0x1328, 0xa1b2, 0x0044, 0x10c8, 0x1328, 0x2100, 0x0079, 0x8f88,
- 0x8fc8, 0x919a, 0x8fc8, 0x8fc8, 0x8fc8, 0x91a2, 0x8fc8, 0x8fc8,
- 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8,
- 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fca,
- 0x902d, 0x9038, 0x9081, 0x909c, 0x911b, 0x918b, 0x8fc8, 0x8fc8,
- 0x91a6, 0x8fc8, 0x8fc8, 0x91b5, 0x91bc, 0x8fc8, 0x8fc8, 0x8fc8,
- 0x8fc8, 0x8fc8, 0x91ea, 0x8fc8, 0x8fc8, 0x91f5, 0x8fc8, 0x8fc8,
- 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x920a, 0x8fc8, 0x8fc8, 0x8fc8,
- 0x9291, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x9305,
- 0x1078, 0x1328, 0x1078, 0x4897, 0x00c0, 0x8fd7, 0x2001, 0xa332,
- 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x00c0, 0x8fdf, 0x6007,
- 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0078, 0x9195, 0x1078,
- 0x4887, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270,
- 0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039,
- 0x0000, 0x1078, 0x5c78, 0x2c08, 0x1078, 0x9c38, 0x077f, 0x017f,
- 0x2e60, 0x1078, 0x471b, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f,
- 0x6618, 0x0c7e, 0x2660, 0x1078, 0x4513, 0x0c7f, 0xa6b0, 0x0001,
- 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x901f, 0x1078,
- 0x9b6c, 0x00c0, 0x907b, 0x1078, 0x9afd, 0x00c0, 0x901b, 0x6007,
- 0x0008, 0x0078, 0x9195, 0x6007, 0x0009, 0x0078, 0x9195, 0x1078,
- 0x9d45, 0x0040, 0x9029, 0x1078, 0x9b6c, 0x0040, 0x9013, 0x0078,
- 0x907b, 0x6013, 0x1900, 0x0078, 0x901b, 0x6106, 0x1078, 0x9aa8,
- 0x6007, 0x0006, 0x0078, 0x9195, 0x6007, 0x0007, 0x0078, 0x9195,
- 0x1078, 0xa0bf, 0x00c0, 0x9340, 0x0d7e, 0x6618, 0x2668, 0x6e04,
- 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x905d, 0xa686,
- 0x0004, 0x0040, 0x905d, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006,
- 0x0040, 0x905d, 0xa686, 0x0004, 0x0040, 0x905d, 0xa686, 0x0005,
- 0x0040, 0x905d, 0x0d7f, 0x0078, 0x907b, 0x1078, 0x9bd2, 0x00c0,
- 0x9076, 0xa686, 0x0006, 0x00c0, 0x906f, 0x027e, 0x6218, 0xa290,
- 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, 0x285b, 0x027f, 0x1078,
- 0x457d, 0x6007, 0x000a, 0x0d7f, 0x0078, 0x9195, 0x6007, 0x000b,
- 0x0d7f, 0x0078, 0x9195, 0x1078, 0x2813, 0x6007, 0x0001, 0x0078,
- 0x9195, 0x1078, 0xa0bf, 0x00c0, 0x9340, 0x6618, 0x0d7e, 0x2668,
- 0x6e04, 0x0d7f, 0xa686, 0x0707, 0x0040, 0x907b, 0x027e, 0x6218,
- 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, 0x285b, 0x027f,
- 0x6007, 0x000c, 0x0078, 0x9195, 0x1078, 0x4897, 0x00c0, 0x90a9,
- 0x2001, 0xa332, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x00c0,
- 0x90b1, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0078,
- 0x9195, 0x1078, 0x4887, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684,
- 0x00ff, 0xa082, 0x0006, 0x0048, 0x90f5, 0xa6b4, 0xff00, 0x8637,
- 0xa686, 0x0004, 0x0040, 0x90c8, 0xa686, 0x0006, 0x00c0, 0x907b,
- 0x1078, 0x9be1, 0x00c0, 0x90d0, 0x6007, 0x000e, 0x0078, 0x9195,
- 0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427,
- 0x047e, 0x1078, 0x2813, 0x047f, 0x017e, 0xa006, 0x2009, 0xa352,
- 0x210c, 0xd1a4, 0x0040, 0x90ef, 0x2009, 0x0029, 0x1078, 0x9ec0,
- 0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x0d7f, 0x017f,
- 0x047f, 0x6007, 0x0001, 0x0078, 0x9195, 0x2001, 0x0001, 0x1078,
- 0x442b, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019,
- 0xa305, 0x2011, 0xa890, 0x1078, 0x7e55, 0x037f, 0x027f, 0x017f,
- 0x157f, 0xa005, 0x0040, 0x9115, 0xa6b4, 0xff00, 0x8637, 0xa686,
- 0x0006, 0x0040, 0x90c8, 0x0078, 0x907b, 0x6013, 0x1900, 0x6007,
- 0x0009, 0x0078, 0x9195, 0x1078, 0x4897, 0x00c0, 0x9128, 0x2001,
- 0xa332, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x00c0, 0x9130,
- 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0078, 0x9195,
- 0x1078, 0x4887, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff,
- 0xa082, 0x0006, 0x0048, 0x9178, 0xa6b4, 0xff00, 0x8637, 0xa686,
- 0x0004, 0x0040, 0x9147, 0xa686, 0x0006, 0x00c0, 0x907b, 0x1078,
- 0x9c0c, 0x00c0, 0x9153, 0x1078, 0x9afd, 0x00c0, 0x9153, 0x6007,
- 0x0010, 0x0078, 0x9195, 0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424,
- 0xa4a4, 0x00ff, 0x8427, 0x047e, 0x1078, 0x2813, 0x047f, 0x017e,
- 0xa006, 0x2009, 0xa352, 0x210c, 0xd1a4, 0x0040, 0x9172, 0x2009,
- 0x0029, 0x1078, 0x9ec0, 0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5,
- 0x6802, 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, 0x0078, 0x9195,
- 0x1078, 0x9d45, 0x0040, 0x9185, 0xa6b4, 0xff00, 0x8637, 0xa686,
- 0x0006, 0x0040, 0x9147, 0x0078, 0x907b, 0x6013, 0x1900, 0x6007,
- 0x0009, 0x0078, 0x9195, 0x1078, 0xa0bf, 0x00c0, 0x9340, 0x1078,
- 0x9343, 0x00c0, 0x907b, 0x6007, 0x0012, 0x6003, 0x0001, 0x1078,
- 0x5c45, 0x007c, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5c45,
- 0x0078, 0x9199, 0x6007, 0x0005, 0x0078, 0x919c, 0x1078, 0xa0bf,
- 0x00c0, 0x9340, 0x1078, 0x9343, 0x00c0, 0x907b, 0x6007, 0x0020,
- 0x6003, 0x0001, 0x1078, 0x5c45, 0x007c, 0x6007, 0x0023, 0x6003,
- 0x0001, 0x1078, 0x5c45, 0x007c, 0x1078, 0xa0bf, 0x00c0, 0x9340,
- 0x1078, 0x9343, 0x00c0, 0x907b, 0x017e, 0x027e, 0x2011, 0xa890,
- 0x2214, 0x2c08, 0x1078, 0x9e8c, 0x00c0, 0x91de, 0x2160, 0x6007,
- 0x0026, 0x6013, 0x1700, 0x2011, 0xa889, 0x2214, 0xa296, 0xffff,
- 0x00c0, 0x91e3, 0x6007, 0x0025, 0x0078, 0x91e3, 0x1078, 0x753d,
- 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x5c45, 0x027f,
- 0x017f, 0x007c, 0x6106, 0x1078, 0x9363, 0x6007, 0x002b, 0x0078,
- 0x9195, 0x6007, 0x002c, 0x0078, 0x9195, 0x1078, 0xa0bf, 0x00c0,
- 0x9340, 0x1078, 0x9343, 0x00c0, 0x907b, 0x6106, 0x1078, 0x9368,
- 0x00c0, 0x9206, 0x6007, 0x002e, 0x0078, 0x9195, 0x6007, 0x002f,
- 0x0078, 0x9195, 0x0e7e, 0x0d7e, 0x0c7e, 0x6018, 0xa080, 0x0001,
- 0x200c, 0xa184, 0x00ff, 0xa086, 0x0006, 0x0040, 0x9223, 0xa184,
- 0xff00, 0x8007, 0xa086, 0x0006, 0x0040, 0x9223, 0x0c7f, 0x0d7f,
- 0x0e7f, 0x0078, 0x919a, 0x2001, 0xa371, 0x2004, 0xd0e4, 0x0040,
- 0x928d, 0x2071, 0xa88c, 0x7010, 0x6036, 0x7014, 0x603a, 0x7108,
- 0x720c, 0x2001, 0xa352, 0x2004, 0xd0a4, 0x0040, 0x9241, 0x6018,
- 0x2068, 0x6810, 0xa106, 0x00c0, 0x9241, 0x6814, 0xa206, 0x0040,
- 0x9265, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x9281, 0x2069,
- 0xa300, 0x686c, 0xa206, 0x00c0, 0x9281, 0x6868, 0xa106, 0x00c0,
- 0x9281, 0x7210, 0x1078, 0x8a30, 0x0040, 0x9287, 0x1078, 0x9f31,
- 0x0040, 0x9287, 0x622a, 0x6007, 0x0036, 0x6003, 0x0001, 0x1078,
- 0x5bf8, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7214, 0xa286, 0xffff,
- 0x0040, 0x9277, 0x1078, 0x8a30, 0x0040, 0x9287, 0xa280, 0x0002,
- 0x2004, 0x7110, 0xa106, 0x00c0, 0x9287, 0x0078, 0x9252, 0x7210,
- 0x2c08, 0x1078, 0x9e8c, 0x2c10, 0x2160, 0x0040, 0x9287, 0x0078,
- 0x9252, 0x6007, 0x0037, 0x6013, 0x1500, 0x0078, 0x925d, 0x6007,
- 0x0037, 0x6013, 0x1700, 0x0078, 0x925d, 0x6007, 0x0012, 0x0078,
- 0x925d, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, 0xff00, 0x8007,
- 0xa086, 0x0006, 0x00c0, 0x919a, 0x0e7e, 0x0d7e, 0x0c7e, 0x2001,
- 0xa371, 0x2004, 0xd0e4, 0x0040, 0x92fd, 0x2069, 0xa300, 0x2071,
- 0xa88c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, 0xffff, 0x00c0,
- 0x92ba, 0x7208, 0x0c7e, 0x2c08, 0x1078, 0x9e8c, 0x2c10, 0x0c7f,
- 0x0040, 0x92f1, 0x1078, 0x8a30, 0x0040, 0x92f1, 0x0c7e, 0x027e,
- 0x2260, 0x1078, 0x874a, 0x027f, 0x0c7f, 0x7118, 0xa18c, 0xff00,
- 0x810f, 0xa186, 0x0001, 0x0040, 0x92db, 0xa186, 0x0005, 0x0040,
- 0x92d5, 0xa186, 0x0007, 0x00c0, 0x92e5, 0xa280, 0x0004, 0x2004,
- 0xa005, 0x0040, 0x92e5, 0x057e, 0x7510, 0x7614, 0x1078, 0x9f46,
- 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x6007, 0x003b, 0x602b,
- 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x1078, 0x5bf8, 0x0078,
- 0x92e1, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x1700, 0x6003,
- 0x0001, 0x1078, 0x5bf8, 0x0078, 0x92e1, 0x6007, 0x003b, 0x602b,
- 0x000b, 0x6013, 0x0000, 0x0078, 0x925d, 0x0e7e, 0x027e, 0x1078,
- 0x4897, 0x0040, 0x933a, 0x1078, 0x4887, 0x1078, 0xa148, 0x00c0,
- 0x9338, 0x2071, 0xa300, 0x70c8, 0xc085, 0x70ca, 0x0f7e, 0x2079,
- 0x0100, 0x7294, 0xa284, 0x00ff, 0x706a, 0x78e6, 0xa284, 0xff00,
- 0x726c, 0xa205, 0x706e, 0x78ea, 0x0f7f, 0x70d3, 0x0000, 0x2001,
- 0xa352, 0x2004, 0xd0a4, 0x0040, 0x9331, 0x2011, 0xa5c4, 0x2013,
- 0x07d0, 0xd0ac, 0x00c0, 0x933a, 0x1078, 0x260d, 0x0078, 0x933a,
- 0x1078, 0xa178, 0x027f, 0x0e7f, 0x1078, 0x753d, 0x0078, 0x9199,
- 0x1078, 0x753d, 0x007c, 0x0d7e, 0x067e, 0x6618, 0x2668, 0x6e04,
- 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x9360, 0xa686,
- 0x0004, 0x0040, 0x9360, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006,
- 0x0040, 0x9360, 0xa686, 0x0004, 0x0040, 0x9360, 0xa085, 0x0001,
- 0x067f, 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x9397, 0x0d7f, 0x007c,
- 0x0d7e, 0x1078, 0x93a6, 0x00c0, 0x9390, 0x680c, 0xa08c, 0xff00,
- 0x6820, 0xa084, 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4,
- 0x0040, 0x937e, 0x2009, 0x0001, 0x0078, 0x938c, 0xd1ec, 0x0040,
- 0x9390, 0x6920, 0xa18c, 0x00ff, 0x6824, 0x1078, 0x24e3, 0x00c0,
- 0x9390, 0x2110, 0x2009, 0x0000, 0x1078, 0x285b, 0x0078, 0x9394,
- 0xa085, 0x0001, 0x0078, 0x9395, 0xa006, 0x0d7f, 0x007c, 0x2069,
- 0xa88d, 0x6800, 0xa082, 0x0010, 0x00c8, 0x93a4, 0x6013, 0x0000,
- 0xa085, 0x0001, 0x0078, 0x93a5, 0xa006, 0x007c, 0x6013, 0x0000,
- 0x2069, 0xa88c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x00c0,
- 0x93ba, 0x6800, 0xa084, 0x00ff, 0xa08e, 0x0014, 0x0040, 0x93ba,
- 0xa08e, 0x0010, 0x007c, 0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1328,
- 0xa1b6, 0x0013, 0x00c0, 0x93c7, 0x2008, 0x0079, 0x93da, 0xa1b6,
- 0x0027, 0x0040, 0x93cf, 0xa1b6, 0x0014, 0x10c0, 0x1328, 0x2001,
- 0x0007, 0x1078, 0x4472, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078,
- 0x6109, 0x007c, 0x941a, 0x941c, 0x941a, 0x941a, 0x941a, 0x941c,
- 0x9424, 0x94ae, 0x9471, 0x94ae, 0x9485, 0x94ae, 0x9424, 0x94ae,
- 0x94a6, 0x94ae, 0x94a6, 0x94ae, 0x94ae, 0x941a, 0x941a, 0x941a,
- 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a,
- 0x941c, 0x941a, 0x94ae, 0x941a, 0x941a, 0x94ae, 0x941a, 0x94ae,
- 0x94ae, 0x941a, 0x941a, 0x941a, 0x941a, 0x94ae, 0x94ae, 0x941a,
- 0x94ae, 0x94ae, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941c,
- 0x94ae, 0x94ae, 0x941a, 0x941a, 0x94ae, 0x94ae, 0x941a, 0x941a,
- 0x941a, 0x941a, 0x1078, 0x1328, 0x1078, 0x6010, 0x6003, 0x0002,
- 0x1078, 0x6109, 0x0078, 0x94b4, 0x0f7e, 0x2079, 0xa351, 0x7804,
- 0x0f7f, 0xd0ac, 0x00c0, 0x94ae, 0x2001, 0x0000, 0x1078, 0x442b,
- 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0040, 0x94ae,
- 0x0c7e, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x00c0, 0x9448, 0x6010,
- 0xa005, 0x0040, 0x9448, 0x0c7f, 0x1078, 0x35f7, 0x0078, 0x94ae,
- 0x0c7f, 0x2001, 0xa300, 0x2004, 0xa086, 0x0002, 0x00c0, 0x9457,
- 0x0f7e, 0x2079, 0xa300, 0x788c, 0x8000, 0x788e, 0x0f7f, 0x2001,
- 0x0002, 0x1078, 0x443f, 0x1078, 0x6010, 0x601f, 0x0001, 0x6003,
- 0x0001, 0x6007, 0x0002, 0x1078, 0x5c45, 0x1078, 0x6109, 0x0c7e,
- 0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x58e1, 0x0c7f, 0x0078,
- 0x94b4, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00,
- 0x8637, 0xa686, 0x0006, 0x0040, 0x94ae, 0xa686, 0x0004, 0x0040,
- 0x94ae, 0x2001, 0x0004, 0x0078, 0x94ac, 0x2001, 0xa300, 0x2004,
- 0xa086, 0x0003, 0x00c0, 0x948e, 0x1078, 0x35f7, 0x2001, 0x0006,
- 0x1078, 0x94b5, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4,
- 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x94ae, 0x2001, 0x0006,
- 0x0078, 0x94ac, 0x2001, 0x0004, 0x0078, 0x94ac, 0x2001, 0x0006,
- 0x1078, 0x94b5, 0x0078, 0x94ae, 0x1078, 0x4472, 0x1078, 0x6010,
- 0x1078, 0x753d, 0x1078, 0x6109, 0x007c, 0x017e, 0x0d7e, 0x6118,
- 0x2168, 0x6900, 0xd184, 0x0040, 0x94d0, 0x6104, 0xa18e, 0x000a,
- 0x00c0, 0x94c8, 0x699c, 0xd1a4, 0x00c0, 0x94c8, 0x2001, 0x0007,
- 0x1078, 0x443f, 0x2001, 0x0000, 0x1078, 0x442b, 0x1078, 0x2839,
- 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084,
- 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1328, 0xa1b6,
- 0x0015, 0x00c0, 0x94e7, 0x1079, 0x94ee, 0x0078, 0x94ed, 0xa1b6,
- 0x0016, 0x10c0, 0x1328, 0x1079, 0x94fa, 0x007c, 0x7ad0, 0x7ad0,
- 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x9547, 0x9506, 0x7ad0, 0x7ad0,
- 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0,
- 0x9547, 0x954f, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x0f7e, 0x2079,
- 0xa351, 0x7804, 0xd0ac, 0x00c0, 0x952d, 0x6018, 0xa07d, 0x0040,
- 0x952d, 0x7800, 0xd0f4, 0x00c0, 0x9519, 0x7810, 0xa005, 0x00c0,
- 0x952d, 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078,
- 0x443f, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078,
- 0x5c45, 0x1078, 0x6109, 0x0078, 0x9545, 0x2011, 0xa883, 0x2204,
- 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, 0x9545, 0x0c7e, 0x1078,
- 0x4501, 0x0040, 0x9540, 0x0c7f, 0x1078, 0x753d, 0x0078, 0x9545,
- 0x1078, 0x4235, 0x0c7f, 0x1078, 0x753d, 0x0f7f, 0x007c, 0x6604,
- 0xa6b6, 0x001e, 0x00c0, 0x954e, 0x1078, 0x753d, 0x007c, 0x1078,
- 0x7d0a, 0x00c0, 0x955b, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078,
- 0x5c45, 0x0078, 0x955d, 0x1078, 0x753d, 0x007c, 0x6004, 0xa08a,
- 0x0044, 0x10c8, 0x1328, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078,
- 0x6109, 0x007c, 0xa182, 0x0040, 0x0079, 0x956e, 0x9581, 0x9581,
- 0x9581, 0x9581, 0x9583, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581,
- 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581,
- 0x9581, 0x1078, 0x1328, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e,
- 0x027e, 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, 0x0040, 0x9594,
- 0x2021, 0x0000, 0x1078, 0xa111, 0x6106, 0x2071, 0xa880, 0x7444,
- 0xa4a4, 0xff00, 0x0040, 0x95eb, 0xa486, 0x2000, 0x00c0, 0x95a6,
- 0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x5a6d, 0x1078, 0x1381,
- 0x1040, 0x1328, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803,
- 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2,
- 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x017e, 0xa084,
- 0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x4982,
- 0x017f, 0xa486, 0x2000, 0x00c0, 0x95d3, 0x2019, 0x0017, 0x1078,
- 0x9e3b, 0x0078, 0x9645, 0xa486, 0x0400, 0x00c0, 0x95dd, 0x2019,
- 0x0002, 0x1078, 0x9dec, 0x0078, 0x9645, 0xa486, 0x0200, 0x00c0,
- 0x95e3, 0x1078, 0x9dd1, 0xa486, 0x1000, 0x00c0, 0x95e9, 0x1078,
- 0x9e20, 0x0078, 0x9645, 0x2069, 0xa62d, 0x6a00, 0xd284, 0x0040,
- 0x969b, 0xa284, 0x0300, 0x00c0, 0x9693, 0x6804, 0xa005, 0x0040,
- 0x9683, 0x2d78, 0x6003, 0x0007, 0x1078, 0x1366, 0x0040, 0x964c,
- 0x7800, 0xd08c, 0x00c0, 0x9607, 0x7804, 0x8001, 0x7806, 0x6013,
- 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008,
- 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130,
- 0x6986, 0x6846, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286,
- 0x0002, 0x00c0, 0x9627, 0x684f, 0x0040, 0x0078, 0x9631, 0xa286,
- 0x0001, 0x00c0, 0x962f, 0x684f, 0x0080, 0x0078, 0x9631, 0x684f,
- 0x0000, 0x20a9, 0x000a, 0x2001, 0xa890, 0xad90, 0x0015, 0x200c,
- 0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x9637, 0x200c, 0x6982,
- 0x8000, 0x200c, 0x697e, 0x1078, 0x4982, 0x027f, 0x047f, 0x157f,
- 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x6013, 0x0100, 0x6003, 0x0001,
- 0x6007, 0x0041, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0078, 0x9645,
- 0x2069, 0xa892, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, 0x00c0,
- 0x9677, 0x2069, 0xa880, 0x686c, 0xa084, 0x00ff, 0x017e, 0x6110,
- 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003, 0x0001, 0x6007,
- 0x0043, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0078, 0x9645, 0x6013,
- 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5bf8, 0x1078,
- 0x6109, 0x0078, 0x9645, 0x6013, 0x0300, 0x0078, 0x9689, 0x6013,
- 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5bf8, 0x1078,
- 0x6109, 0x0078, 0x9645, 0x6013, 0x0500, 0x0078, 0x9689, 0x6013,
- 0x0600, 0x0078, 0x9658, 0x6013, 0x0200, 0x0078, 0x9658, 0xa186,
- 0x0013, 0x00c0, 0x96b1, 0x6004, 0xa08a, 0x0040, 0x1048, 0x1328,
- 0xa08a, 0x0053, 0x10c8, 0x1328, 0xa082, 0x0040, 0x2008, 0x0079,
- 0x9725, 0xa186, 0x0051, 0x0040, 0x96be, 0xa186, 0x0047, 0x00c0,
- 0x96d7, 0x6004, 0xa086, 0x0041, 0x0040, 0x96e5, 0x2001, 0x0109,
- 0x2004, 0xd084, 0x0040, 0x96e5, 0x127e, 0x2091, 0x2200, 0x007e,
- 0x017e, 0x027e, 0x1078, 0x5ad2, 0x027f, 0x017f, 0x007f, 0x127f,
- 0x6000, 0xa086, 0x0002, 0x00c0, 0x96e5, 0x0078, 0x976a, 0xa186,
- 0x0027, 0x0040, 0x96df, 0xa186, 0x0014, 0x10c0, 0x1328, 0x6004,
- 0xa082, 0x0040, 0x2008, 0x0079, 0x96e8, 0x1078, 0x7583, 0x007c,
- 0x96fb, 0x96fd, 0x96fd, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb,
- 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb,
- 0x96fb, 0x96fb, 0x96fb, 0x1078, 0x1328, 0x1078, 0x6010, 0x1078,
- 0x6109, 0x037e, 0x0d7e, 0x6010, 0xa06d, 0x0040, 0x9722, 0xad84,
- 0xf000, 0x0040, 0x9722, 0x6003, 0x0002, 0x6018, 0x2004, 0xd0bc,
- 0x00c0, 0x9722, 0x2019, 0x0004, 0x1078, 0x9e70, 0x6013, 0x0000,
- 0x6014, 0xa005, 0x00c0, 0x9720, 0x2001, 0xa5a1, 0x2004, 0x6016,
- 0x6003, 0x0007, 0x0d7f, 0x037f, 0x007c, 0x9738, 0x9757, 0x9741,
- 0x9764, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738,
- 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738,
- 0x1078, 0x1328, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400,
- 0x200a, 0x1078, 0x6010, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4,
- 0x0040, 0x9752, 0x6003, 0x0007, 0x2009, 0x0043, 0x1078, 0x756c,
- 0x0078, 0x9754, 0x6003, 0x0002, 0x1078, 0x6109, 0x007c, 0x1078,
- 0x6010, 0x1078, 0xa0c6, 0x00c0, 0x9761, 0x1078, 0x5a41, 0x1078,
- 0x753d, 0x1078, 0x6109, 0x007c, 0x1078, 0x6010, 0x2009, 0x0041,
- 0x0078, 0x98c1, 0xa182, 0x0040, 0x0079, 0x976e, 0x9781, 0x9783,
- 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x9784, 0x9781, 0x9781,
- 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x978f,
- 0x9781, 0x1078, 0x1328, 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1,
- 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15ec, 0x007c, 0x0d7e,
- 0x1078, 0x5a41, 0x0d7f, 0x1078, 0xa134, 0x1078, 0x753d, 0x007c,
- 0xa182, 0x0040, 0x0079, 0x979c, 0x97af, 0x97af, 0x97af, 0x97af,
- 0x97af, 0x97af, 0x97af, 0x97b1, 0x97af, 0x97b4, 0x97df, 0x97af,
- 0x97af, 0x97af, 0x97af, 0x97df, 0x97af, 0x97af, 0x97af, 0x1078,
- 0x1328, 0x1078, 0x7583, 0x007c, 0x1078, 0x60b8, 0x1078, 0x61d3,
- 0x6010, 0x0d7e, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x97ca, 0xa08c,
- 0x0003, 0xa18e, 0x0002, 0x0040, 0x97d2, 0x2009, 0x0041, 0x0d7f,
- 0x0078, 0x98c1, 0x6003, 0x0007, 0x6017, 0x0000, 0x1078, 0x5a41,
- 0x0d7f, 0x007c, 0x1078, 0xa0c6, 0x0040, 0x97d8, 0x0d7f, 0x007c,
- 0x1078, 0x5a41, 0x1078, 0x753d, 0x0d7f, 0x0078, 0x97d1, 0x037e,
- 0x1078, 0x60b8, 0x1078, 0x61d3, 0x6010, 0x0d7e, 0x2068, 0x6018,
- 0x2004, 0xd0bc, 0x0040, 0x97ff, 0x684c, 0xa084, 0x0003, 0xa086,
- 0x0002, 0x0040, 0x97fb, 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880,
- 0x6328, 0xa31b, 0x632a, 0x6003, 0x0002, 0x0078, 0x9810, 0x2019,
- 0x0004, 0x1078, 0x9e70, 0x6014, 0xa005, 0x00c0, 0x980c, 0x2001,
- 0xa5a1, 0x2004, 0x8003, 0x6016, 0x6013, 0x0000, 0x6003, 0x0007,
- 0x0d7f, 0x037f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x9821, 0x6004,
- 0xa086, 0x0042, 0x10c0, 0x1328, 0x1078, 0x6010, 0x1078, 0x6109,
- 0x007c, 0xa186, 0x0027, 0x0040, 0x9829, 0xa186, 0x0014, 0x00c0,
- 0x9839, 0x6004, 0xa086, 0x0042, 0x10c0, 0x1328, 0x2001, 0x0007,
- 0x1078, 0x4472, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109,
- 0x007c, 0xa182, 0x0040, 0x0079, 0x983d, 0x9850, 0x9850, 0x9850,
- 0x9850, 0x9850, 0x9850, 0x9850, 0x9852, 0x985e, 0x9850, 0x9850,
- 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850,
- 0x1078, 0x1328, 0x037e, 0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20,
- 0x2c10, 0x1078, 0x15ec, 0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e,
- 0x2068, 0x6810, 0x6a14, 0x6118, 0x210c, 0xd1bc, 0x0040, 0x987d,
- 0x6124, 0xd1f4, 0x00c0, 0x987d, 0x007e, 0x047e, 0x057e, 0x6c7c,
- 0xa422, 0x6d80, 0x2200, 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028,
- 0xa529, 0x652a, 0x057f, 0x047f, 0x007f, 0xa20d, 0x00c0, 0x9891,
- 0x684c, 0xd0fc, 0x0040, 0x9889, 0x2009, 0x0041, 0x0d7f, 0x0078,
- 0x98c1, 0x6003, 0x0007, 0x6017, 0x0000, 0x1078, 0x5a41, 0x0d7f,
- 0x007c, 0x007e, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x007f,
- 0x0040, 0x989e, 0x6003, 0x0002, 0x0d7f, 0x007c, 0x2009, 0xa30d,
- 0x210c, 0xd19c, 0x0040, 0x98a8, 0x6003, 0x0007, 0x0078, 0x98aa,
- 0x6003, 0x0006, 0x1078, 0x98b0, 0x1078, 0x5a43, 0x0d7f, 0x007c,
- 0xd2fc, 0x0040, 0x98bc, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000,
- 0x2009, 0x0009, 0x0078, 0x98be, 0x2009, 0x0015, 0x6a6a, 0x6866,
- 0x007c, 0xa182, 0x0040, 0x0048, 0x98c7, 0x0079, 0x98d4, 0xa186,
- 0x0013, 0x0040, 0x98cf, 0xa186, 0x0014, 0x10c0, 0x1328, 0x6024,
- 0xd0dc, 0x1040, 0x1328, 0x007c, 0x98e7, 0x98ee, 0x98fa, 0x9906,
- 0x98e7, 0x98e7, 0x98e7, 0x9915, 0x98e7, 0x98e9, 0x98e9, 0x98e7,
- 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x1078,
- 0x1328, 0x6024, 0xd0dc, 0x1040, 0x1328, 0x007c, 0x6003, 0x0001,
- 0x6106, 0x1078, 0x5bf8, 0x127e, 0x2091, 0x8000, 0x1078, 0x6109,
- 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x127e,
- 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x007c, 0x6003, 0x0003,
- 0x6106, 0x2c10, 0x1078, 0x1cab, 0x127e, 0x2091, 0x8000, 0x1078,
- 0x5c64, 0x1078, 0x61d3, 0x127f, 0x007c, 0xa016, 0x1078, 0x15ec,
- 0x007c, 0x127e, 0x2091, 0x8000, 0x037e, 0x0d7e, 0xa182, 0x0040,
- 0x1079, 0x9926, 0x0d7f, 0x037f, 0x127f, 0x007c, 0x9936, 0x9938,
- 0x994d, 0x996c, 0x9936, 0x9936, 0x9936, 0x9984, 0x9936, 0x9936,
- 0x9936, 0x9936, 0x9936, 0x9936, 0x9936, 0x9936, 0x1078, 0x1328,
- 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9962, 0xa09c, 0x0003,
- 0xa39e, 0x0003, 0x0040, 0x9962, 0x6003, 0x0001, 0x6106, 0x1078,
- 0x5bf8, 0x1078, 0x6109, 0x0078, 0x9987, 0x6010, 0x2068, 0x684c,
- 0xd0fc, 0x0040, 0x9962, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040,
- 0x9962, 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x1078, 0x6109,
- 0x0078, 0x9987, 0x6013, 0x0000, 0x6017, 0x0000, 0x2019, 0x0004,
- 0x1078, 0x9e70, 0x0078, 0x9987, 0x6010, 0x2068, 0x684c, 0xd0fc,
- 0x0040, 0x9962, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, 0x9962,
- 0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, 0x1cab, 0x1078, 0x5c64,
- 0x1078, 0x61d3, 0x0078, 0x9987, 0xa016, 0x1078, 0x15ec, 0x007c,
- 0x1078, 0x6010, 0x6110, 0x81ff, 0x0040, 0x9999, 0x0d7e, 0x2168,
- 0x1078, 0xa181, 0x037e, 0x2019, 0x0029, 0x1078, 0x9e70, 0x037f,
- 0x0d7f, 0x1078, 0x8c01, 0x1078, 0x6109, 0x007c, 0x1078, 0x60b8,
- 0x6110, 0x81ff, 0x0040, 0x99af, 0x0d7e, 0x2168, 0x1078, 0xa181,
- 0x037e, 0x2019, 0x0029, 0x1078, 0x9e70, 0x037f, 0x0d7f, 0x1078,
- 0x8c01, 0x1078, 0x61d3, 0x007c, 0xa182, 0x0085, 0x0079, 0x99b8,
- 0x99c1, 0x99bf, 0x99bf, 0x99cd, 0x99bf, 0x99bf, 0x99bf, 0x1078,
- 0x1328, 0x6003, 0x000b, 0x6106, 0x1078, 0x5bf8, 0x127e, 0x2091,
- 0x8000, 0x1078, 0x6109, 0x127f, 0x007c, 0x027e, 0x0e7e, 0x1078,
- 0xa0bf, 0x0040, 0x99d7, 0x1078, 0x753d, 0x0078, 0x99f3, 0x2071,
- 0xa880, 0x7224, 0x6212, 0x7220, 0x1078, 0x9d10, 0x0040, 0x99e4,
- 0x6007, 0x0086, 0x0078, 0x99ed, 0x6007, 0x0087, 0x7224, 0xa296,
- 0xffff, 0x00c0, 0x99ed, 0x6007, 0x0086, 0x6003, 0x0001, 0x1078,
- 0x5bf8, 0x1078, 0x6109, 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013,
- 0x00c0, 0x9a07, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1328, 0xa08a,
- 0x008c, 0x10c8, 0x1328, 0xa082, 0x0085, 0x0079, 0x9a1e, 0xa186,
- 0x0027, 0x0040, 0x9a13, 0xa186, 0x0014, 0x0040, 0x9a13, 0x1078,
- 0x7583, 0x0078, 0x9a1d, 0x2001, 0x0007, 0x1078, 0x4472, 0x1078,
- 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109, 0x007c, 0x9a25, 0x9a27,
- 0x9a27, 0x9a25, 0x9a25, 0x9a25, 0x9a25, 0x1078, 0x1328, 0x1078,
- 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109, 0x007c, 0xa182, 0x0085,
- 0x1048, 0x1328, 0xa182, 0x008c, 0x10c8, 0x1328, 0xa182, 0x0085,
- 0x0079, 0x9a3a, 0x9a41, 0x9a41, 0x9a41, 0x9a43, 0x9a41, 0x9a41,
- 0x9a41, 0x1078, 0x1328, 0x007c, 0xa186, 0x0013, 0x0040, 0x9a54,
- 0xa186, 0x0014, 0x0040, 0x9a54, 0xa186, 0x0027, 0x0040, 0x9a54,
- 0x1078, 0x7583, 0x0078, 0x9a5a, 0x1078, 0x6010, 0x1078, 0x8c01,
- 0x1078, 0x6109, 0x007c, 0x037e, 0x1078, 0xa134, 0x603f, 0x0000,
- 0x2019, 0x000b, 0x1078, 0x9a6a, 0x601f, 0x0006, 0x6003, 0x0007,
- 0x037f, 0x007c, 0x127e, 0x037e, 0x2091, 0x8000, 0x087e, 0x2c40,
- 0x097e, 0x2049, 0x0000, 0x1078, 0x7058, 0x097f, 0x087f, 0x00c0,
- 0x9aa5, 0x077e, 0x2c38, 0x1078, 0x7105, 0x077f, 0x00c0, 0x9aa5,
- 0x6000, 0xa086, 0x0000, 0x0040, 0x9aa5, 0x601c, 0xa086, 0x0007,
- 0x0040, 0x9aa5, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x9a96,
- 0x1078, 0xa134, 0x601f, 0x0007, 0x1078, 0x1749, 0x6010, 0x2068,
- 0x1078, 0x8a44, 0x0040, 0x9a9e, 0x1078, 0x9e70, 0x0d7f, 0x6013,
- 0x0000, 0x1078, 0xa134, 0x601f, 0x0007, 0x037f, 0x127f, 0x007c,
- 0x0f7e, 0x0c7e, 0x037e, 0x157e, 0x2079, 0xa880, 0x7938, 0x783c,
- 0x1078, 0x24e3, 0x00c0, 0x9af6, 0x017e, 0x0c7e, 0x1078, 0x4501,
- 0x00c0, 0x9af6, 0x2011, 0xa890, 0xac98, 0x000a, 0x20a9, 0x0004,
- 0x1078, 0x7e55, 0x00c0, 0x9af6, 0x017f, 0x027f, 0x027e, 0x017e,
- 0x2019, 0x0029, 0x1078, 0x71e0, 0x1078, 0x5d53, 0x077e, 0x2039,
- 0x0000, 0x1078, 0x5c78, 0x077f, 0x017f, 0x077e, 0x2039, 0x0000,
- 0x1078, 0x9c38, 0x077f, 0x1078, 0x471b, 0x027e, 0x6204, 0xa294,
- 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x9aea, 0xa286, 0x0004,
- 0x00c0, 0x9aed, 0x62a0, 0x1078, 0x28d5, 0x027f, 0x017f, 0x1078,
- 0x4235, 0x6612, 0x6516, 0xa006, 0x0078, 0x9af8, 0x0c7f, 0x017f,
- 0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, 0x0c7e, 0x0d7e, 0x0e7e,
- 0x017e, 0x2009, 0xa31f, 0x2104, 0xa086, 0x0074, 0x00c0, 0x9b60,
- 0x2069, 0xa88e, 0x690c, 0xa182, 0x0100, 0x0048, 0x9b50, 0x6908,
- 0xa184, 0x8000, 0x0040, 0x9b5c, 0x6018, 0x2070, 0x7010, 0xa084,
- 0x00ff, 0x0040, 0x9b1f, 0x7000, 0xd0f4, 0x0040, 0x9b23, 0xa184,
- 0x0800, 0x0040, 0x9b5c, 0x6910, 0xa18a, 0x0001, 0x0048, 0x9b54,
- 0x6914, 0x2069, 0xa8ae, 0x6904, 0x81ff, 0x00c0, 0x9b48, 0x690c,
- 0xa182, 0x0100, 0x0048, 0x9b50, 0x6908, 0x81ff, 0x00c0, 0x9b4c,
- 0x6910, 0xa18a, 0x0001, 0x0048, 0x9b54, 0x6918, 0xa18a, 0x0001,
- 0x0048, 0x9b5c, 0x0078, 0x9b66, 0x6013, 0x0100, 0x0078, 0x9b62,
- 0x6013, 0x0300, 0x0078, 0x9b62, 0x6013, 0x0500, 0x0078, 0x9b62,
- 0x6013, 0x0700, 0x0078, 0x9b62, 0x6013, 0x0900, 0x0078, 0x9b62,
- 0x6013, 0x0b00, 0x0078, 0x9b62, 0x6013, 0x0f00, 0x0078, 0x9b62,
- 0x6013, 0x2d00, 0xa085, 0x0001, 0x0078, 0x9b67, 0xa006, 0x017f,
- 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x027e, 0x037e,
- 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006,
- 0x0040, 0x9b90, 0xa286, 0x0004, 0x0040, 0x9b90, 0xa394, 0xff00,
- 0x8217, 0xa286, 0x0006, 0x0040, 0x9b90, 0xa286, 0x0004, 0x0040,
- 0x9b90, 0x0c7e, 0x2d60, 0x1078, 0x4513, 0x0c7f, 0x0078, 0x9bcb,
- 0x2011, 0xa896, 0xad98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x7e55,
- 0x00c0, 0x9bcc, 0x2011, 0xa89a, 0xad98, 0x0006, 0x20a9, 0x0004,
- 0x1078, 0x7e55, 0x00c0, 0x9bcc, 0x047e, 0x017e, 0x6aa0, 0xa294,
- 0x00ff, 0x8227, 0xa006, 0x2009, 0xa352, 0x210c, 0xd1a4, 0x0040,
- 0x9bb8, 0x2009, 0x0029, 0x1078, 0x9ec0, 0x6800, 0xc0e5, 0x6802,
- 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039, 0x0000, 0x1078,
- 0x5c78, 0x2c08, 0x1078, 0x9c38, 0x077f, 0x2001, 0x0007, 0x1078,
- 0x4472, 0x017f, 0x047f, 0xa006, 0x157f, 0x037f, 0x027f, 0x0d7f,
- 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0xa88e, 0x6800, 0xa086, 0x0800,
- 0x0040, 0x9bde, 0x6013, 0x0000, 0x0078, 0x9bdf, 0xa006, 0x0d7f,
- 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2079,
- 0xa88c, 0x7930, 0x7834, 0x1078, 0x24e3, 0x00c0, 0x9c05, 0x1078,
- 0x4501, 0x00c0, 0x9c05, 0x2011, 0xa890, 0xac98, 0x000a, 0x20a9,
- 0x0004, 0x1078, 0x7e55, 0x00c0, 0x9c05, 0x2011, 0xa894, 0xac98,
- 0x0006, 0x20a9, 0x0004, 0x1078, 0x7e55, 0x157f, 0x037f, 0x027f,
- 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, 0x007e, 0x017e, 0x027e,
- 0x037e, 0x157e, 0x2011, 0xa883, 0x2204, 0x8211, 0x220c, 0x1078,
- 0x24e3, 0x00c0, 0x9c31, 0x1078, 0x4501, 0x00c0, 0x9c31, 0x2011,
- 0xa896, 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x7e55, 0x00c0,
- 0x9c31, 0x2011, 0xa89a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078,
- 0x7e55, 0x157f, 0x037f, 0x027f, 0x017f, 0x007f, 0x0c7f, 0x007c,
- 0x0e7e, 0x0c7e, 0x087e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e,
- 0x127e, 0x2091, 0x8000, 0x2740, 0x2029, 0xa5b4, 0x252c, 0x2021,
- 0xa5ba, 0x2424, 0x2061, 0xaa00, 0x2071, 0xa300, 0x7644, 0x7060,
- 0x81ff, 0x0040, 0x9c59, 0x8001, 0xa602, 0x00c8, 0x9cc3, 0x0078,
- 0x9c5c, 0xa606, 0x0040, 0x9cc3, 0x2100, 0xac06, 0x0040, 0x9cb9,
- 0x1078, 0x9ee5, 0x0040, 0x9cb9, 0x671c, 0xa786, 0x0001, 0x0040,
- 0x9cde, 0xa786, 0x0004, 0x0040, 0x9cde, 0xa786, 0x0007, 0x0040,
- 0x9cb9, 0x2500, 0xac06, 0x0040, 0x9cb9, 0x2400, 0xac06, 0x0040,
- 0x9cb9, 0x1078, 0x9ef9, 0x00c0, 0x9cb9, 0x88ff, 0x0040, 0x9c84,
- 0x6020, 0xa906, 0x00c0, 0x9cb9, 0x0d7e, 0x6000, 0xa086, 0x0004,
- 0x00c0, 0x9c8e, 0x017e, 0x1078, 0x1749, 0x017f, 0xa786, 0x0008,
- 0x00c0, 0x9c9d, 0x1078, 0x8c3b, 0x00c0, 0x9c9d, 0x1078, 0x7a05,
- 0x0d7f, 0x1078, 0x8c01, 0x0078, 0x9cb9, 0x6010, 0x2068, 0x1078,
- 0x8a44, 0x0040, 0x9cb6, 0xa786, 0x0003, 0x00c0, 0x9ccd, 0x6837,
- 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0xa181, 0x017e, 0x1078,
- 0x8cb8, 0x1078, 0x4982, 0x017f, 0x1078, 0x8bf4, 0x0d7f, 0x1078,
- 0x8c01, 0xace0, 0x0010, 0x2001, 0xa315, 0x2004, 0xac02, 0x00c8,
- 0x9cc3, 0x0078, 0x9c4c, 0x127f, 0x027f, 0x047f, 0x057f, 0x067f,
- 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0,
- 0x9ca7, 0xa386, 0x0005, 0x0040, 0x9cdb, 0x1078, 0xa181, 0x1078,
- 0x9e70, 0x0078, 0x9cb6, 0x0d7f, 0x0078, 0x9cb9, 0x1078, 0x9ef9,
- 0x00c0, 0x9cb9, 0x81ff, 0x0040, 0x9cb9, 0xa180, 0x0001, 0x2004,
- 0xa086, 0x0018, 0x0040, 0x9cf3, 0xa180, 0x0001, 0x2004, 0xa086,
- 0x002d, 0x00c0, 0x9cb9, 0x6000, 0xa086, 0x0002, 0x00c0, 0x9cb9,
- 0x1078, 0x8c27, 0x0040, 0x9d04, 0x1078, 0x8c3b, 0x00c0, 0x9cb9,
- 0x1078, 0x7a05, 0x0078, 0x9d0c, 0x1078, 0x2839, 0x1078, 0x8c3b,
- 0x00c0, 0x9d0c, 0x1078, 0x7a05, 0x1078, 0x8c01, 0x0078, 0x9cb9,
- 0x0c7e, 0x0e7e, 0x017e, 0x2c08, 0x2170, 0x1078, 0x9e8c, 0x017f,
- 0x0040, 0x9d1f, 0x601c, 0xa084, 0x000f, 0x1079, 0x9d22, 0x0e7f,
- 0x0c7f, 0x007c, 0x9d2a, 0x9d2a, 0x9d2a, 0x9d2a, 0x9d2a, 0x9d2a,
- 0x9d2c, 0x9d2a, 0xa006, 0x007c, 0x047e, 0x017e, 0x7018, 0xa080,
- 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020,
- 0x1078, 0x9ec0, 0x017f, 0x047f, 0x037e, 0x2019, 0x0002, 0x1078,
- 0x9a6a, 0x037f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0001, 0x1078,
- 0x442b, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019,
- 0xa305, 0x2011, 0xa896, 0x1078, 0x7e55, 0x037f, 0x027f, 0x017f,
- 0x157f, 0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x087e, 0x077e,
- 0x067e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, 0x2061, 0xaa00,
- 0x2079, 0x0001, 0x8fff, 0x0040, 0x9dc3, 0x2071, 0xa300, 0x7644,
- 0x7060, 0x8001, 0xa602, 0x00c8, 0x9dc3, 0x88ff, 0x0040, 0x9d7e,
- 0x2800, 0xac06, 0x00c0, 0x9db9, 0x2079, 0x0000, 0x1078, 0x9ee5,
- 0x0040, 0x9db9, 0x2400, 0xac06, 0x0040, 0x9db9, 0x671c, 0xa786,
- 0x0006, 0x00c0, 0x9db9, 0xa786, 0x0007, 0x0040, 0x9db9, 0x88ff,
- 0x00c0, 0x9d9d, 0x6018, 0xa206, 0x00c0, 0x9db9, 0x85ff, 0x0040,
- 0x9d9d, 0x6020, 0xa106, 0x00c0, 0x9db9, 0x0d7e, 0x6000, 0xa086,
- 0x0004, 0x00c0, 0x9da9, 0x1078, 0xa134, 0x601f, 0x0007, 0x1078,
- 0x1749, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x9db3, 0x047e,
- 0x1078, 0x9e70, 0x047f, 0x0d7f, 0x1078, 0x8c01, 0x88ff, 0x00c0,
- 0x9dcd, 0xace0, 0x0010, 0x2001, 0xa315, 0x2004, 0xac02, 0x00c8,
- 0x9dc3, 0x0078, 0x9d6a, 0xa006, 0x127f, 0x027f, 0x067f, 0x077f,
- 0x087f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001, 0x0078,
- 0x9dc4, 0x077e, 0x057e, 0x087e, 0x2041, 0x0000, 0x2029, 0x0001,
- 0x2c20, 0x2019, 0x0002, 0x6218, 0x097e, 0x2049, 0x0000, 0x1078,
- 0x7058, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, 0x7105, 0x1078,
- 0x9d5b, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e, 0x077e,
- 0x0c7e, 0x157e, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000,
- 0x017e, 0x037e, 0x1078, 0x4501, 0x00c0, 0x9e14, 0x2c10, 0x057e,
- 0x087e, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001, 0x097e, 0x2049,
- 0x0000, 0x1078, 0x7058, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078,
- 0x7105, 0x1078, 0x9d5b, 0x057f, 0x037f, 0x017f, 0x8108, 0x00f0,
- 0x9df8, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, 0x027f, 0x007c,
- 0x077e, 0x057e, 0x6218, 0x087e, 0x2041, 0x0000, 0x2029, 0x0001,
- 0x2019, 0x0048, 0x097e, 0x2049, 0x0000, 0x1078, 0x7058, 0x097f,
- 0x087f, 0x2039, 0x0000, 0x1078, 0x7105, 0x2c20, 0x1078, 0x9d5b,
- 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e, 0x077e, 0x0c7e,
- 0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x037e,
- 0x1078, 0x4501, 0x00c0, 0x9e64, 0x2c10, 0x087e, 0x2041, 0x0000,
- 0x2828, 0x047e, 0x2021, 0x0001, 0x1078, 0xa111, 0x047f, 0x097e,
- 0x2049, 0x0000, 0x1078, 0x7058, 0x097f, 0x087f, 0x2039, 0x0000,
- 0x1078, 0x7105, 0x1078, 0x9d5b, 0x037f, 0x017f, 0x8108, 0x00f0,
- 0x9e46, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, 0x027f, 0x007c,
- 0x017e, 0x0f7e, 0xad82, 0xca00, 0x0048, 0x9e89, 0xad82, 0xffff,
- 0x00c8, 0x9e89, 0x6800, 0xa07d, 0x0040, 0x9e86, 0x6803, 0x0000,
- 0x6b52, 0x1078, 0x4982, 0x2f68, 0x0078, 0x9e7a, 0x6b52, 0x1078,
- 0x4982, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061,
- 0xaa00, 0x2071, 0xa300, 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8,
- 0x9ebb, 0x2100, 0xac06, 0x0040, 0x9ead, 0x6000, 0xa086, 0x0000,
- 0x0040, 0x9ead, 0x6008, 0xa206, 0x00c0, 0x9ead, 0x6018, 0xa1a0,
- 0x0006, 0x2424, 0xa406, 0x0040, 0x9eb7, 0xace0, 0x0010, 0x2001,
- 0xa315, 0x2004, 0xac02, 0x00c8, 0x9ebb, 0x0078, 0x9e91, 0xa085,
- 0x0001, 0x0078, 0x9ebc, 0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c,
- 0x0d7e, 0x007e, 0x1078, 0x1381, 0x007f, 0x1040, 0x1328, 0x6837,
- 0x010d, 0x685e, 0x027e, 0x2010, 0x1078, 0x8a30, 0x2001, 0x0000,
- 0x0040, 0x9ed6, 0x2200, 0xa080, 0x0008, 0x2004, 0x027f, 0x684a,
- 0x6956, 0x6c46, 0x684f, 0x0000, 0xa006, 0x68b2, 0x6802, 0x683a,
- 0x685a, 0x1078, 0x4982, 0x0d7f, 0x007c, 0x6700, 0xa786, 0x0000,
- 0x0040, 0x9ef8, 0xa786, 0x0001, 0x0040, 0x9ef8, 0xa786, 0x000a,
- 0x0040, 0x9ef8, 0xa786, 0x0009, 0x0040, 0x9ef8, 0xa085, 0x0001,
- 0x007c, 0x0e7e, 0x6018, 0x2070, 0x70a0, 0xa206, 0x0e7f, 0x007c,
- 0x017e, 0x6004, 0xa08e, 0x001e, 0x00c0, 0x9f1a, 0x8007, 0x6130,
- 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b,
- 0x601f, 0x0005, 0x2001, 0xa5a1, 0x2004, 0x6016, 0x1078, 0x5bf8,
- 0x1078, 0x6109, 0x017f, 0x007c, 0x0005, 0x0005, 0x007c, 0x6024,
- 0xd0e4, 0x0040, 0x9f30, 0xd0cc, 0x0040, 0x9f2a, 0x1078, 0x8cfa,
- 0x0078, 0x9f30, 0x1078, 0xa134, 0x1078, 0x5a41, 0x1078, 0x753d,
- 0x007c, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, 0x0079, 0x9f38,
- 0x9f41, 0x9f41, 0x9f41, 0x9f43, 0x9f41, 0x9f43, 0x9f43, 0x9f41,
- 0x9f43, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa280, 0x0007,
- 0x2004, 0xa084, 0x000f, 0x0079, 0x9f4d, 0x9f56, 0x9f56, 0x9f56,
- 0x9f56, 0x9f56, 0x9f56, 0x9f61, 0x9f56, 0x9f56, 0x6007, 0x003b,
- 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x1078, 0x5bf8,
- 0x007c, 0x0c7e, 0x2260, 0x1078, 0xa134, 0x603f, 0x0000, 0x6024,
- 0xc0f4, 0xc0cc, 0x6026, 0x0c7f, 0x0d7e, 0x2268, 0xa186, 0x0007,
- 0x00c0, 0x9fc2, 0x6810, 0xa005, 0x0040, 0x9f7f, 0xa080, 0x0013,
- 0x2004, 0xd0fc, 0x00c0, 0x9f7f, 0x0d7f, 0x0078, 0x9f56, 0x6007,
- 0x003a, 0x6003, 0x0001, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7e,
- 0x2d60, 0x6100, 0xa186, 0x0002, 0x00c0, 0xa050, 0x6010, 0xa005,
- 0x00c0, 0x9f99, 0x6000, 0xa086, 0x0007, 0x10c0, 0x1328, 0x0078,
- 0xa050, 0xa08c, 0xf000, 0x00c0, 0x9fa5, 0x0078, 0x9fa5, 0x2068,
- 0x6800, 0xa005, 0x00c0, 0x9f9f, 0x2d00, 0xa080, 0x0013, 0x2004,
- 0xa084, 0x0003, 0xa086, 0x0002, 0x00c0, 0x9fbe, 0x6010, 0x2068,
- 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852,
- 0x2009, 0x0043, 0x1078, 0x98c1, 0x0078, 0xa050, 0x2009, 0x0041,
- 0x0078, 0xa04a, 0xa186, 0x0005, 0x00c0, 0xa009, 0x6810, 0xa080,
- 0x0013, 0x2004, 0xd0bc, 0x00c0, 0x9fd0, 0x0d7f, 0x0078, 0x9f56,
- 0xd0b4, 0x0040, 0x9fd8, 0xd0fc, 0x1040, 0x1328, 0x0078, 0x9f72,
- 0x6007, 0x003a, 0x6003, 0x0001, 0x1078, 0x5bf8, 0x1078, 0x6109,
- 0x0c7e, 0x2d60, 0x6100, 0xa186, 0x0002, 0x0040, 0x9feb, 0xa186,
- 0x0004, 0x00c0, 0xa050, 0x2071, 0xa5e1, 0x7000, 0xa086, 0x0003,
- 0x00c0, 0x9ff8, 0x7004, 0xac06, 0x00c0, 0x9ff8, 0x7003, 0x0000,
- 0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000,
- 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x2009, 0x0042, 0x0078,
- 0xa04a, 0x037e, 0x0d7e, 0x0d7e, 0x1078, 0x1381, 0x037f, 0x1040,
- 0x1328, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x685b,
- 0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, 0x6862, 0x6034, 0x6872,
- 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6018, 0xa080, 0x0028, 0x2004,
- 0xa084, 0x00ff, 0x8007, 0x6320, 0x6b4a, 0x6846, 0x684f, 0x0000,
- 0x6d6a, 0x6e66, 0x686f, 0x0001, 0x1078, 0x4982, 0x2019, 0x0045,
- 0x6008, 0x2068, 0x1078, 0x9a6a, 0x2d00, 0x600a, 0x601f, 0x0006,
- 0x6003, 0x0007, 0x6017, 0x0000, 0x603f, 0x0000, 0x0d7f, 0x037f,
- 0x0078, 0xa051, 0x603f, 0x0000, 0x6003, 0x0007, 0x1078, 0x98c1,
- 0x0c7f, 0x0d7f, 0x007c, 0xa186, 0x0013, 0x00c0, 0xa05d, 0x6004,
- 0xa082, 0x0085, 0x2008, 0x0079, 0xa077, 0xa186, 0x0027, 0x00c0,
- 0xa070, 0x1078, 0x6010, 0x037e, 0x0d7e, 0x6010, 0x2068, 0x2019,
- 0x0004, 0x1078, 0x9e70, 0x0d7f, 0x037f, 0x1078, 0x6109, 0x007c,
- 0xa186, 0x0014, 0x0040, 0xa061, 0x1078, 0x7583, 0x007c, 0xa080,
- 0xa07e, 0xa07e, 0xa07e, 0xa07e, 0xa07e, 0xa080, 0x1078, 0x1328,
- 0x1078, 0x6010, 0x6003, 0x000c, 0x1078, 0x6109, 0x007c, 0xa182,
- 0x008c, 0x00c8, 0xa091, 0xa182, 0x0085, 0x0048, 0xa091, 0x0079,
- 0xa094, 0x1078, 0x7583, 0x007c, 0xa09b, 0xa09b, 0xa09b, 0xa09b,
- 0xa09d, 0xa0bc, 0xa09b, 0x1078, 0x1328, 0x0d7e, 0x2c68, 0x1078,
- 0x74d7, 0x0040, 0xa0b7, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009,
- 0xa88e, 0x210c, 0x6136, 0x2009, 0xa88f, 0x210c, 0x613a, 0x600b,
- 0xffff, 0x6918, 0x611a, 0x601f, 0x0004, 0x1078, 0x5bf8, 0x2d60,
- 0x1078, 0x753d, 0x0d7f, 0x007c, 0x1078, 0x753d, 0x007c, 0x0e7e,
- 0x6018, 0x2070, 0x7000, 0xd0ec, 0x0e7f, 0x007c, 0x6010, 0xa080,
- 0x0013, 0x200c, 0xd1ec, 0x0040, 0xa110, 0x2001, 0xa371, 0x2004,
- 0xd0ec, 0x0040, 0xa110, 0x6003, 0x0002, 0x6024, 0xc0e5, 0x6026,
- 0xd1ac, 0x0040, 0xa0ee, 0x0f7e, 0x2c78, 0x1078, 0x488f, 0x0f7f,
- 0x0040, 0xa0ee, 0x2001, 0xa5a2, 0x2004, 0x603e, 0x2009, 0xa371,
- 0x210c, 0xd1f4, 0x00c0, 0xa10e, 0x0078, 0xa100, 0x2009, 0xa371,
- 0x210c, 0xd1f4, 0x0040, 0xa0fa, 0x6024, 0xc0e4, 0x6026, 0xa006,
- 0x0078, 0xa110, 0x2001, 0xa5a2, 0x200c, 0x8103, 0xa100, 0x603e,
- 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0040, 0xa10b, 0xa088,
- 0x0003, 0x0078, 0xa103, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001,
- 0x007c, 0x017e, 0x0c7e, 0x0e7e, 0x6120, 0xa2f0, 0x002b, 0x2e04,
- 0x2060, 0x8cff, 0x0040, 0xa130, 0x84ff, 0x00c0, 0xa123, 0x6020,
- 0xa106, 0x00c0, 0xa12b, 0x600c, 0x2072, 0x1078, 0x5a41, 0x1078,
- 0x753d, 0x0078, 0xa12d, 0xacf0, 0x0003, 0x2e64, 0x0078, 0xa119,
- 0x0e7f, 0x0c7f, 0x017f, 0x007c, 0x0d7e, 0x6018, 0xa0e8, 0x002b,
- 0x2d04, 0xa005, 0x0040, 0xa146, 0xac06, 0x0040, 0xa144, 0x2d04,
- 0xa0e8, 0x0003, 0x0078, 0xa138, 0x600c, 0x206a, 0x0d7f, 0x007c,
- 0x027e, 0x037e, 0x157e, 0x2011, 0xa325, 0x2204, 0xa084, 0x00ff,
- 0x2019, 0xa88e, 0x2334, 0xa636, 0x00c0, 0xa174, 0x8318, 0x2334,
- 0x2204, 0xa084, 0xff00, 0xa636, 0x00c0, 0xa174, 0x2011, 0xa890,
- 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004, 0x1078, 0x7e55, 0x00c0,
- 0xa174, 0x2011, 0xa894, 0x6018, 0xa098, 0x0006, 0x20a9, 0x0004,
- 0x1078, 0x7e55, 0x00c0, 0xa174, 0x157f, 0x037f, 0x027f, 0x007c,
- 0x0e7e, 0x2071, 0xa300, 0x1078, 0x41f5, 0x1078, 0x260d, 0x0e7f,
- 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0040, 0xa18a,
- 0x1078, 0xa18c, 0x0e7f, 0x007c, 0x6850, 0xc0e5, 0x6852, 0x007c,
- 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, 0x017e,
- 0x127e, 0x2091, 0x8000, 0x2029, 0xa5b4, 0x252c, 0x2021, 0xa5ba,
- 0x2424, 0x2061, 0xaa00, 0x2071, 0xa300, 0x7644, 0x7060, 0xa606,
- 0x0040, 0xa1e4, 0x671c, 0xa786, 0x0001, 0x0040, 0xa1b3, 0xa786,
- 0x0008, 0x00c0, 0xa1da, 0x2500, 0xac06, 0x0040, 0xa1da, 0x2400,
- 0xac06, 0x0040, 0xa1da, 0x1078, 0x9ee5, 0x0040, 0xa1da, 0x1078,
- 0x9ef9, 0x00c0, 0xa1da, 0x6000, 0xa086, 0x0004, 0x00c0, 0xa1cc,
- 0x017e, 0x1078, 0x1749, 0x017f, 0x1078, 0x8c27, 0x00c0, 0xa1d2,
- 0x1078, 0x2839, 0x1078, 0x8c3b, 0x00c0, 0xa1d8, 0x1078, 0x7a05,
- 0x1078, 0x8c01, 0xace0, 0x0010, 0x2001, 0xa315, 0x2004, 0xac02,
- 0x00c8, 0xa1e4, 0x0078, 0xa1a3, 0x127f, 0x017f, 0x027f, 0x047f,
- 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x007e,
- 0x0e7e, 0x2091, 0x8000, 0x2071, 0xa340, 0xd5a4, 0x0040, 0xa1fb,
- 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa201, 0x7030, 0x8000,
- 0x7032, 0xd5ac, 0x0040, 0xa208, 0x2071, 0xa34a, 0x1078, 0xa237,
- 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091,
- 0x8000, 0x2071, 0xa340, 0xd5a4, 0x0040, 0xa219, 0x7034, 0x8000,
- 0x7036, 0xd5b4, 0x0040, 0xa21f, 0x7030, 0x8000, 0x7032, 0xd5ac,
- 0x0040, 0xa226, 0x2071, 0xa34a, 0x1078, 0xa237, 0x0e7f, 0x007f,
- 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071,
- 0xa342, 0x1078, 0xa237, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x2e04,
- 0x8000, 0x2072, 0x00c8, 0xa240, 0x8e70, 0x2e04, 0x8000, 0x2072,
- 0x007c, 0x0e7e, 0x2071, 0xa340, 0x1078, 0xa237, 0x0e7f, 0x007c,
- 0x0e7e, 0x2071, 0xa344, 0x1078, 0xa237, 0x0e7f, 0x007c, 0x0001,
- 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100,
- 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x6286
-};
-
-/************************************************************************
- * *
- * --- ISP2200 Initiator/Target Firmware --- *
- * with Fabric (Public Loop), Point-point, and *
- * expanded LUN addressing for FCTAPE *
- * *
- ************************************************************************
- Copyright (C) 2000 and 2100 Qlogic Corporation
- (www.qlogic.com)
-
- 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.
-************************************************************************/
-
-/*
- * Firmware Version 2.01.27 (11:07 Dec 18, 2000)
- */
-
-static unsigned short risc_code_length2200 = 0x9cbf;
-static unsigned short risc_code2200[] = {
- 0x0470, 0x0000, 0x0000, 0x9cbf, 0x0000, 0x0002, 0x0001, 0x001b,
- 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939,
- 0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
- 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972,
- 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030,
- 0x322e, 0x3031, 0x2e32, 0x3720, 0x2020, 0x2020, 0x2400, 0x20c1,
- 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xb1ff, 0x2091,
- 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x27b5,
- 0x2051, 0xad00, 0x2a70, 0x2029, 0xe400, 0x2031, 0xffff, 0x2039,
- 0xe3e9, 0x2021, 0x0200, 0x0804, 0x1449, 0x20a1, 0xacbf, 0xa00e,
- 0x20a9, 0x0741, 0x41a4, 0x3400, 0x755e, 0x7662, 0x775a, 0x7466,
- 0x746a, 0x20a1, 0xb400, 0x7160, 0x810d, 0x810d, 0x810d, 0x810d,
- 0xa18c, 0x000f, 0x2001, 0x000b, 0xa112, 0xa00e, 0x21a8, 0x41a4,
- 0x3400, 0x8211, 0x1dd8, 0x7160, 0x3400, 0xa102, 0x0120, 0x0218,
- 0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xad00,
- 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001,
- 0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0,
- 0x2009, 0xad00, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e,
- 0x41a4, 0x080c, 0x13fc, 0x080c, 0x1613, 0x080c, 0x17ac, 0x080c,
- 0x1e67, 0x080c, 0x492e, 0x080c, 0x801a, 0x080c, 0x159c, 0x080c,
- 0x2ce6, 0x080c, 0x5a01, 0x080c, 0x5045, 0x080c, 0x6487, 0x080c,
- 0x236a, 0x080c, 0x6686, 0x080c, 0x5fae, 0x080c, 0x226b, 0x080c,
- 0x2338, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c5, 0x7820,
- 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, 0x10bd, 0x781b,
- 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000,
- 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1158, 0x080c, 0x3c98, 0x080c,
- 0x2d0d, 0x080c, 0x5a4f, 0x080c, 0x51f4, 0x080c, 0x64a2, 0x0c80,
- 0x000b, 0x0c98, 0x10e4, 0x10e5, 0x1203, 0x10e2, 0x12cc, 0x13f9,
- 0x13fa, 0x13fb, 0x080c, 0x14f6, 0x0005, 0x0126, 0x00f6, 0x2091,
- 0x8000, 0x7000, 0xa086, 0x0001, 0x1904, 0x11d1, 0x080c, 0x1569,
- 0x080c, 0x574f, 0x0150, 0x080c, 0x5775, 0x1580, 0x2079, 0x0100,
- 0x7828, 0xa085, 0x1800, 0x782a, 0x0448, 0x080c, 0x569a, 0x7000,
- 0xa086, 0x0001, 0x1904, 0x11d1, 0x7088, 0xa086, 0x0028, 0x1904,
- 0x11d1, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0xa295, 0x1e2f,
- 0x7a2a, 0x2011, 0x566e, 0x080c, 0x650d, 0x2011, 0x567b, 0x080c,
- 0x650d, 0x2011, 0x481b, 0x080c, 0x650d, 0x2011, 0x8030, 0x2019,
- 0x0000, 0x7087, 0x0000, 0x080c, 0x1d0f, 0x00e8, 0x080c, 0x41d1,
- 0x2079, 0x0100, 0x7844, 0xa005, 0x1904, 0x11d1, 0x2011, 0x481b,
- 0x080c, 0x650d, 0x2011, 0x567b, 0x080c, 0x650d, 0x080c, 0x1d0f,
- 0x2001, 0xaf8c, 0x2004, 0x780e, 0x7840, 0xa084, 0xfffb, 0x7842,
- 0x2011, 0x8010, 0x73c8, 0x080c, 0x3c5c, 0x7238, 0xc284, 0x723a,
- 0x2001, 0xad0c, 0x200c, 0xc1ac, 0x2102, 0x080c, 0x79bd, 0x2011,
- 0x0004, 0x080c, 0x959c, 0x080c, 0x4f71, 0x080c, 0x574f, 0x0158,
- 0x080c, 0x4917, 0x0140, 0x7087, 0x0001, 0x70c3, 0x0000, 0x080c,
- 0x436e, 0x0804, 0x11d1, 0x080c, 0x502d, 0x0120, 0x7a0c, 0xc2b4,
- 0x7a0e, 0x0050, 0x080c, 0x9937, 0x70d0, 0xd09c, 0x1128, 0x709c,
- 0xa005, 0x0110, 0x080c, 0x48f5, 0x70db, 0x0000, 0x70d7, 0x0000,
- 0x72d0, 0x080c, 0x574f, 0x1178, 0x2011, 0x0000, 0x0016, 0x080c,
- 0x2744, 0x2019, 0xaf8e, 0x211a, 0x001e, 0x704f, 0xffff, 0x7053,
- 0x00ef, 0x7073, 0x0000, 0x2079, 0xad51, 0x7804, 0xd0ac, 0x0108,
- 0xc295, 0x72d2, 0x080c, 0x574f, 0x0118, 0xa296, 0x0004, 0x0508,
- 0x2011, 0x0001, 0x080c, 0x959c, 0x7097, 0x0000, 0x709b, 0xffff,
- 0x7003, 0x0002, 0x00fe, 0x080c, 0x28fa, 0x2011, 0x0005, 0x080c,
- 0x7adf, 0x080c, 0x6c50, 0x080c, 0x574f, 0x0148, 0x00c6, 0x2061,
- 0x0100, 0x0016, 0x080c, 0x2744, 0x61e2, 0x001e, 0x00ce, 0x012e,
- 0x00d0, 0x7097, 0x0000, 0x709b, 0xffff, 0x7003, 0x0002, 0x2011,
- 0x0005, 0x080c, 0x7adf, 0x080c, 0x6c50, 0x080c, 0x574f, 0x0148,
- 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2744, 0x61e2, 0x001e,
- 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x574f, 0x1118,
- 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x574f, 0x1118,
- 0x2009, 0x0000, 0x0010, 0x2009, 0x007e, 0x0016, 0x0026, 0x0036,
- 0x2110, 0x0026, 0x2019, 0x0029, 0x080c, 0x7cf4, 0x002e, 0x080c,
- 0xac07, 0x003e, 0x002e, 0x001e, 0x080c, 0x2bc9, 0x8108, 0x1f04,
- 0x11e5, 0x00ce, 0x706f, 0x0000, 0x7070, 0xa084, 0x00ff, 0x7072,
- 0x709f, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, 0x7000, 0xa086,
- 0x0002, 0x1904, 0x12ca, 0x7098, 0xa086, 0xffff, 0x0130, 0x080c,
- 0x28fa, 0x080c, 0x6c50, 0x0804, 0x12ca, 0x70d0, 0xd0ac, 0x1110,
- 0xd09c, 0x0540, 0xd084, 0x0530, 0x0006, 0x0016, 0x2001, 0x0103,
- 0x2009, 0xaf8c, 0x210c, 0x2102, 0x001e, 0x000e, 0xd08c, 0x01d0,
- 0x70d4, 0xa086, 0xffff, 0x0190, 0x080c, 0x2a56, 0x080c, 0x6c50,
- 0x70d0, 0xd094, 0x1904, 0x12ca, 0x2011, 0x0001, 0x2019, 0x0000,
- 0x080c, 0x2a8c, 0x080c, 0x6c50, 0x0804, 0x12ca, 0x70d8, 0xa005,
- 0x1904, 0x12ca, 0x7094, 0xa005, 0x1904, 0x12ca, 0x70d0, 0xd0a4,
- 0x0118, 0xd0b4, 0x0904, 0x12ca, 0x080c, 0x502d, 0x1904, 0x12ca,
- 0x2001, 0xad52, 0x2004, 0xd0ac, 0x01c8, 0x0156, 0x00c6, 0x20a9,
- 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4cdc, 0x1118, 0x6000,
- 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x125b, 0x00ce, 0x015e,
- 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x12ca, 0x0006, 0x0016,
- 0x2001, 0x0103, 0x2009, 0xaf8c, 0x210c, 0x2102, 0x001e, 0x000e,
- 0xa006, 0x2009, 0x0700, 0x20a9, 0x0002, 0x20a1, 0xafb5, 0x40a1,
- 0x706c, 0x8007, 0x7170, 0x810f, 0x20a9, 0x0002, 0x40a1, 0x2009,
- 0x0000, 0x080c, 0x14dc, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002,
- 0x40a1, 0xa006, 0x2009, 0x0200, 0x20a9, 0x0002, 0x20a1, 0xafc5,
- 0x40a1, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x709b, 0xffff,
- 0x080c, 0x1562, 0xa006, 0x080c, 0x261e, 0x080c, 0x3cce, 0x00f6,
- 0x2079, 0x0100, 0x080c, 0x5775, 0x0150, 0x080c, 0x574f, 0x7828,
- 0x0118, 0xa084, 0xe1ff, 0x0010, 0xa084, 0xffdf, 0x782a, 0x00fe,
- 0x2001, 0xafc8, 0x2004, 0xa086, 0x0005, 0x1120, 0x2011, 0x0000,
- 0x080c, 0x7adf, 0x2011, 0x0000, 0x080c, 0x7ae9, 0x080c, 0x6c50,
- 0x080c, 0x6d0d, 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126,
- 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0xad33, 0x2104, 0xa005,
- 0x1110, 0x080c, 0x2770, 0x2009, 0x00f7, 0x080c, 0x48de, 0x7940,
- 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040,
- 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, 0x7954,
- 0xd1ac, 0x1904, 0x133a, 0x080c, 0x5761, 0x0158, 0x080c, 0x5775,
- 0x1128, 0x2001, 0xaf9d, 0x2003, 0x0000, 0x0070, 0x080c, 0x5757,
- 0x0dc0, 0x2001, 0xaf9d, 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003,
- 0x0001, 0x080c, 0x569a, 0x0058, 0x080c, 0x574f, 0x0140, 0x2009,
- 0x00f8, 0x080c, 0x48de, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9,
- 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x574f, 0x0138, 0x7824,
- 0xd0ac, 0x1904, 0x13e0, 0x1f04, 0x1319, 0x0070, 0x7824, 0x080c,
- 0x576b, 0x0118, 0xd0ac, 0x1904, 0x13e0, 0xa084, 0x1800, 0x0d98,
- 0x7003, 0x0001, 0x0804, 0x13e0, 0x2001, 0x0001, 0x080c, 0x261e,
- 0x0804, 0x13ef, 0x7850, 0xa084, 0x0180, 0x7852, 0x782f, 0x0020,
- 0x20a9, 0x0046, 0x1d04, 0x1342, 0x2091, 0x6000, 0x1f04, 0x1342,
- 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, 0x782f, 0x0000,
- 0x080c, 0x5761, 0x0158, 0x080c, 0x5775, 0x1128, 0x2001, 0xaf9d,
- 0x2003, 0x0000, 0x0070, 0x080c, 0x5757, 0x0dc0, 0x2001, 0xaf9d,
- 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x080c, 0x569a,
- 0x0020, 0x2009, 0x00f8, 0x080c, 0x48de, 0x20a9, 0x000e, 0xe000,
- 0x1f04, 0x136f, 0x7850, 0xa084, 0x0180, 0xa085, 0x1400, 0x7852,
- 0x080c, 0x574f, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021,
- 0xe678, 0x2019, 0xea60, 0x7820, 0xd09c, 0x1558, 0x080c, 0x574f,
- 0x05b8, 0x7824, 0xd0ac, 0x1904, 0x13e0, 0x080c, 0x5775, 0x1508,
- 0x0046, 0x2021, 0x0190, 0x8421, 0x1df0, 0x004e, 0x8421, 0x11c8,
- 0x7827, 0x0048, 0x20a9, 0x01f4, 0x1d04, 0x139c, 0x2091, 0x6000,
- 0x1f04, 0x139c, 0x7824, 0xa084, 0x0068, 0x15a8, 0x2001, 0xaf9d,
- 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x7003, 0x0001,
- 0x0478, 0x8319, 0x1980, 0x2009, 0xad33, 0x2104, 0x8000, 0x200a,
- 0xa084, 0xfff0, 0x0120, 0x200b, 0x0000, 0x080c, 0x2770, 0x00d8,
- 0x080c, 0x5761, 0x1140, 0xa4a2, 0x0064, 0x1128, 0x080c, 0x5726,
- 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0xe000, 0xe000, 0x7824,
- 0x080c, 0x576b, 0x0110, 0xd0ac, 0x1158, 0xa084, 0x1800, 0x09c8,
- 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x261e, 0x0048,
- 0x2001, 0xad33, 0x2003, 0x0000, 0x7827, 0x0048, 0x7828, 0xc09d,
- 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, 0x015e,
- 0x003e, 0x000e, 0x080c, 0x1539, 0x012e, 0x00fe, 0x004e, 0x001e,
- 0x0005, 0x0005, 0x0005, 0x0005, 0x2a70, 0x2001, 0xaf9d, 0x2003,
- 0x0000, 0x7087, 0x0000, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002,
- 0x0218, 0x704f, 0xffff, 0x0010, 0x704f, 0x0000, 0x7057, 0xffff,
- 0x706f, 0x0000, 0x7073, 0x0000, 0x080c, 0x9937, 0x2061, 0xaf8d,
- 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200,
- 0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0,
- 0x2061, 0xaf95, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000,
- 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001,
- 0x601f, 0x0000, 0x2061, 0xafa6, 0x6003, 0x514c, 0x6007, 0x4f47,
- 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0xad27, 0x2003, 0x0000,
- 0x0005, 0x04a0, 0x2011, 0x0000, 0x81ff, 0x0570, 0xa186, 0x0001,
- 0x1148, 0x2031, 0x8fff, 0x2039, 0xcc01, 0x2021, 0x0100, 0x2029,
- 0xcc00, 0x00e8, 0xa186, 0x0002, 0x1118, 0x2011, 0x0000, 0x00b8,
- 0xa186, 0x0005, 0x1118, 0x2011, 0x0001, 0x0088, 0xa186, 0x0009,
- 0x1118, 0x2011, 0x0002, 0x0058, 0xa186, 0x000a, 0x1118, 0x2011,
- 0x0002, 0x0028, 0xa186, 0x0055, 0x1110, 0x2011, 0x0003, 0x3800,
- 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0804, 0x104d, 0xa00e, 0x2011,
- 0x0003, 0x2019, 0x1485, 0x0804, 0x14d6, 0x2019, 0xaaaa, 0x2061,
- 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0xa306, 0x2262,
- 0x1110, 0xc1b5, 0xc1a5, 0x2011, 0x0000, 0x2019, 0x1498, 0x04f0,
- 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000,
- 0x2c1c, 0x2061, 0x7fff, 0xe000, 0xe000, 0x2c04, 0x2061, 0xffff,
- 0x2262, 0xa306, 0x0110, 0xc18d, 0x0008, 0xc185, 0x2011, 0x0002,
- 0x2019, 0x14b3, 0x0418, 0x2061, 0xffff, 0x2019, 0xaaaa, 0x2c14,
- 0x2362, 0xe000, 0xe000, 0x2c04, 0x2262, 0xa306, 0x1180, 0x2c14,
- 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0x2c04, 0x2061,
- 0xffff, 0x2262, 0xa306, 0x1110, 0xc195, 0x0008, 0xc19d, 0x2011,
- 0x0001, 0x2019, 0x14d4, 0x0010, 0x0804, 0x144a, 0x3800, 0xa084,
- 0xfffc, 0xa205, 0x20c0, 0x0837, 0x2011, 0x0000, 0x080c, 0x4cdc,
- 0x1178, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0128, 0xa0c4,
- 0xff00, 0xa8c6, 0x0600, 0x1120, 0xa186, 0x0080, 0x0108, 0x8210,
- 0x8108, 0xa186, 0x0100, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000,
- 0x0e04, 0x14f8, 0x0006, 0x0016, 0x2079, 0x0000, 0x7818, 0xd084,
- 0x1de8, 0x001e, 0x792e, 0x000e, 0x782a, 0x000e, 0x7826, 0x3900,
- 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, 0x0126,
- 0x0156, 0x0146, 0x20a9, 0x0010, 0x20a1, 0xb0c8, 0x2091, 0x2000,
- 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2200, 0x40a1, 0x20a9, 0x0010,
- 0x2091, 0x2400, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2600, 0x40a1,
- 0x20a9, 0x0010, 0x2091, 0x2800, 0x40a1, 0x014e, 0x015e, 0x012e,
- 0x2079, 0xad00, 0x7803, 0x0005, 0x2091, 0x4080, 0x04c9, 0x0cf8,
- 0x0005, 0x0006, 0x080c, 0x1584, 0x1518, 0x00f6, 0x2079, 0xad23,
- 0x2f04, 0x8000, 0x207a, 0xa082, 0x000f, 0x0258, 0xa006, 0x207a,
- 0x2079, 0xad25, 0x2f04, 0xa084, 0x0001, 0xa086, 0x0001, 0x207a,
- 0x0070, 0x2079, 0xad25, 0x2f7c, 0x8fff, 0x1128, 0x2001, 0x0c03,
- 0x2003, 0x0040, 0x0020, 0x2001, 0x0c03, 0x2003, 0x00c0, 0x00fe,
- 0x000e, 0x0005, 0x0409, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0080,
- 0x0005, 0x00d1, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0005,
- 0x0006, 0x0091, 0x1178, 0x2001, 0x0c03, 0x2003, 0x0040, 0x2009,
- 0x0fff, 0x00a1, 0x2001, 0x0c03, 0x2003, 0x0080, 0x2009, 0x0fff,
- 0x0069, 0x0c88, 0x000e, 0x0005, 0x00c6, 0x2061, 0x0c00, 0x2c04,
- 0xa084, 0x00ff, 0xa086, 0x00aa, 0x00ce, 0x0005, 0x0156, 0x0126,
- 0xa18c, 0x0fff, 0x21a8, 0x1d04, 0x1593, 0x2091, 0x6000, 0x1f04,
- 0x1593, 0x012e, 0x015e, 0x0005, 0x2071, 0xad00, 0x715c, 0x712e,
- 0x2021, 0x0001, 0xa190, 0x0030, 0xa298, 0x0030, 0x0240, 0x7060,
- 0xa302, 0x1228, 0x220a, 0x2208, 0x2310, 0x8420, 0x0ca8, 0x3800,
- 0xd08c, 0x0148, 0x7060, 0xa086, 0xad00, 0x0128, 0x7063, 0xad00,
- 0x2011, 0x1000, 0x0c48, 0x200b, 0x0000, 0x74ae, 0x74b2, 0x0005,
- 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xad00, 0x70b0, 0xa0ea,
- 0x0010, 0x0268, 0x8001, 0x70b2, 0x702c, 0x2068, 0x2d04, 0x702e,
- 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e,
- 0x0cd8, 0x00e6, 0x2071, 0xad00, 0x0126, 0x2091, 0x8000, 0x70b0,
- 0x8001, 0x0260, 0x70b2, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b,
- 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8,
- 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xad00, 0x702c, 0x206a,
- 0x2d00, 0x702e, 0x70b0, 0x8000, 0x70b2, 0x012e, 0x00ee, 0x0005,
- 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000, 0x0006, 0x0c49, 0x00de,
- 0x0cb8, 0x0005, 0x00e6, 0x2071, 0xad00, 0x70b0, 0xa08a, 0x0010,
- 0xa00d, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xafec, 0x7007, 0x0000,
- 0x701b, 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085,
- 0x8004, 0x7012, 0x00ee, 0x0005, 0x00e6, 0x2270, 0x700b, 0x0000,
- 0x2071, 0xafec, 0x7018, 0xa088, 0xaff5, 0x220a, 0x8000, 0xa084,
- 0x0007, 0x701a, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010,
- 0x0081, 0x00fe, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xafec, 0x7004,
- 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0019, 0x00fe, 0x00ee,
- 0x0005, 0x7000, 0x0002, 0x164f, 0x16b3, 0x16d0, 0x16d0, 0x7018,
- 0x711c, 0xa106, 0x1118, 0x7007, 0x0000, 0x0005, 0x00d6, 0xa180,
- 0xaff5, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, 0x711e,
- 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, 0x783a,
- 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, 0x00de,
- 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, 0x0002,
- 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182,
- 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, 0x7822,
- 0x7803, 0x0020, 0x7803, 0x0041, 0x002e, 0x001e, 0x0005, 0x0016,
- 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x2098, 0x20a1, 0x0014,
- 0x7803, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x1210,
- 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803,
- 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x015e, 0x014e, 0x013e,
- 0x002e, 0x001e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2099, 0xadf9,
- 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126,
- 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084,
- 0x7002, 0x700b, 0xadf4, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005,
- 0x0136, 0x0146, 0x0156, 0x2001, 0xae28, 0x209c, 0x20a1, 0x0014,
- 0x7803, 0x0026, 0x2001, 0xae29, 0x20ac, 0x53a6, 0x2099, 0xae2a,
- 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126,
- 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c,
- 0x7002, 0x700b, 0xae25, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005,
- 0x0016, 0x00e6, 0x2071, 0xafec, 0x00f6, 0x2079, 0x0010, 0x7904,
- 0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, 0x0700, 0x7004, 0x0023,
- 0x00fe, 0x00ee, 0x001e, 0x0005, 0x1649, 0x1713, 0x1741, 0x176b,
- 0x179b, 0x1712, 0x0cf8, 0xa18c, 0x0700, 0x1528, 0x0136, 0x0146,
- 0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010,
- 0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, 0x014e, 0x013e, 0x700c,
- 0xa005, 0x0570, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x167a,
- 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000,
- 0x080c, 0x1649, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200,
- 0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, 0xa005, 0x0188, 0x7830,
- 0x7832, 0x7834, 0x7836, 0x080c, 0x168f, 0x0005, 0x7008, 0xa080,
- 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x080c, 0x1649, 0x0005,
- 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838,
- 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x00de, 0x7007, 0x0000,
- 0x080c, 0x1649, 0x0005, 0xa18c, 0x0700, 0x1540, 0x0136, 0x0146,
- 0x0156, 0x2001, 0xadf7, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099,
- 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xadf9,
- 0x2004, 0xd0bc, 0x0148, 0x2001, 0xae02, 0x2004, 0xa080, 0x000d,
- 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, 0x014e, 0x013e, 0x7007,
- 0x0000, 0x080c, 0x5ae6, 0x080c, 0x1649, 0x0005, 0x2011, 0x8003,
- 0x080c, 0x3c5c, 0x0cf8, 0xa18c, 0x0700, 0x1148, 0x2001, 0xae27,
- 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x1649, 0x0005, 0x2011,
- 0x8004, 0x080c, 0x3c5c, 0x0cf8, 0x0126, 0x2091, 0x2200, 0x2079,
- 0x0030, 0x2071, 0xaffd, 0x7003, 0x0000, 0x700f, 0xb003, 0x7013,
- 0xb003, 0x780f, 0x00f6, 0x7803, 0x0004, 0x012e, 0x0005, 0x6934,
- 0xa184, 0x0007, 0x0002, 0x17cb, 0x1809, 0x17cb, 0x17cb, 0x17cb,
- 0x17f1, 0x17d8, 0x17cf, 0xa085, 0x0001, 0x0804, 0x1823, 0x684c,
- 0xd0bc, 0x0dc8, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x04c8,
- 0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d70, 0x684c, 0xd0bc, 0x0d58,
- 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, 0xa080, 0x000d,
- 0x2004, 0xa084, 0x000f, 0xa080, 0x2186, 0x2005, 0x6832, 0x6858,
- 0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x19a8, 0x684c, 0xd0ac,
- 0x0990, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f,
- 0xa080, 0x2186, 0x2005, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858,
- 0x0080, 0x684c, 0xd0ac, 0x0904, 0x17cb, 0xa006, 0x682e, 0x682a,
- 0x6858, 0xa18c, 0x000f, 0xa188, 0x2186, 0x210d, 0x6932, 0x2d08,
- 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c,
- 0x6912, 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007, 0x20e1, 0x2000,
- 0x2001, 0x020a, 0x2004, 0x82ff, 0x01a8, 0xa280, 0x0004, 0x00d6,
- 0x206c, 0x684c, 0xd0dc, 0x1150, 0x080c, 0x17bf, 0x0138, 0x00de,
- 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0020, 0x6808, 0x8000,
- 0x680a, 0x00de, 0x0126, 0x0046, 0x0036, 0x0026, 0x2091, 0x2200,
- 0x002e, 0x003e, 0x004e, 0x7000, 0xa005, 0x01d0, 0x710c, 0x220a,
- 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, 0xb01e, 0x0210,
- 0x2009, 0xb003, 0x710e, 0x7010, 0xa102, 0xa082, 0x0009, 0x0118,
- 0xa080, 0x001b, 0x1118, 0x2009, 0x0138, 0x200a, 0x012e, 0x0005,
- 0x7206, 0x2001, 0x1866, 0x0006, 0x2260, 0x0804, 0x197a, 0x0126,
- 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, 0x004e,
- 0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168, 0x6a62,
- 0x6b5e, 0xa005, 0x0904, 0x18c8, 0x6808, 0xa005, 0x0904, 0x18ff,
- 0x7000, 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, 0xa106, 0x1904,
- 0x1907, 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, 0x2004, 0xd08c,
- 0x0168, 0x0046, 0x080c, 0x1a6c, 0x004e, 0x2460, 0x6010, 0xa080,
- 0x0002, 0x2004, 0xa005, 0x0904, 0x18ff, 0x0c10, 0x2001, 0x0207,
- 0x2004, 0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, 0x0120, 0xa086,
- 0x6000, 0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803,
- 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004,
- 0x1904, 0x1907, 0x2009, 0x0048, 0x080c, 0x80a7, 0x0804, 0x1907,
- 0x6808, 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, 0x700c, 0x7110,
- 0xa106, 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, 0x0005, 0x2004,
- 0xd08c, 0x0160, 0x0046, 0x080c, 0x1a6c, 0x004e, 0x2460, 0x6010,
- 0xa080, 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, 0x2001, 0x0207,
- 0x2004, 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, 0xd08c, 0x1d50,
- 0x7804, 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, 0x19f0, 0x7818,
- 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x6100,
- 0xa18e, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x80a7, 0x00ce,
- 0x00de, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046,
- 0x0056, 0x080c, 0x1d86, 0x0026, 0x0056, 0x2071, 0xaffd, 0x7000,
- 0xa086, 0x0000, 0x0580, 0x7004, 0xac06, 0x11f8, 0x2079, 0x0030,
- 0x7000, 0xa086, 0x0003, 0x01c8, 0x7804, 0xd0fc, 0x1198, 0x2001,
- 0x0207, 0x2004, 0xd09c, 0x1dc0, 0x7803, 0x0004, 0x7804, 0xd0ac,
- 0x1de8, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007,
- 0x0000, 0x0018, 0x080c, 0x1a6c, 0x08d0, 0x0156, 0x20a9, 0x0009,
- 0x2009, 0xb003, 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003,
- 0x1f04, 0x1942, 0x015e, 0x005e, 0x002e, 0x2001, 0x015d, 0x201c,
- 0x831a, 0x2302, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202,
- 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, 0x700c,
- 0x7110, 0xa106, 0x0904, 0x19dd, 0x2104, 0x7006, 0x2060, 0x8108,
- 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0xb01e, 0x0210, 0x2009,
- 0xb003, 0x7112, 0x700c, 0xa106, 0x1128, 0x080c, 0x2744, 0x2001,
- 0x0138, 0x2102, 0x8cff, 0x0588, 0x6010, 0x2068, 0x2d58, 0x6828,
- 0xa406, 0x1580, 0x682c, 0xa306, 0x1568, 0x7004, 0x2060, 0x6020,
- 0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, 0x6817, 0xffff, 0x6813,
- 0xffff, 0x00d8, 0x6850, 0xd0f4, 0x1130, 0x7803, 0x0004, 0x6810,
- 0x781a, 0x6814, 0x781e, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830,
- 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, 0x0011, 0x04c9, 0x0118,
- 0x2009, 0x0001, 0x04a9, 0x2d58, 0x0005, 0x080c, 0x1ced, 0x0904,
- 0x195f, 0x0cd0, 0x6020, 0xd0d4, 0x01b8, 0x6038, 0xa402, 0x6034,
- 0xa303, 0x0108, 0x1288, 0x643a, 0x6336, 0x6c2a, 0x6b2e, 0x0046,
- 0x0036, 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80, 0xa303,
- 0x6816, 0x003e, 0x004e, 0x0018, 0x080c, 0x98cb, 0x09f0, 0x601c,
- 0xa08e, 0x0008, 0x0904, 0x1985, 0xa08e, 0x000a, 0x0904, 0x1985,
- 0x080c, 0x21a6, 0x1990, 0x0804, 0x1985, 0x7003, 0x0000, 0x0005,
- 0x8aff, 0x0904, 0x1a46, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11b8,
- 0xd0f4, 0x1528, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x1a30,
- 0x1a15, 0x1a15, 0x1a30, 0x1a30, 0x1a29, 0x1a30, 0x1a15, 0x1a30,
- 0x1a1a, 0x1a1a, 0x1a30, 0x1a30, 0x1a30, 0x1a21, 0x1a1a, 0x7803,
- 0x0004, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6,
- 0xd99c, 0x0548, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0420, 0xc0f4,
- 0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0428, 0x6b08, 0x6a0c, 0x6d00,
- 0x6c04, 0x00c8, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c,
- 0x0090, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e,
- 0x1138, 0x00de, 0x080c, 0x2148, 0x1904, 0x19e0, 0xa00e, 0x00b0,
- 0x00de, 0x080c, 0x14f6, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a,
- 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x00de, 0x6828, 0xa300,
- 0x682a, 0x682c, 0xa201, 0x682e, 0x080c, 0x2148, 0x0005, 0x080c,
- 0x14f6, 0x080c, 0x1e1a, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068,
- 0x7003, 0x0000, 0x080c, 0x1d22, 0x080c, 0x9596, 0x0170, 0x6808,
- 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff,
- 0x682f, 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x929c,
- 0x0804, 0x1c5e, 0x080c, 0x14f6, 0x0126, 0x2091, 0x2200, 0x0006,
- 0x0016, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184,
- 0x0700, 0x1978, 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000,
- 0x0002, 0x1a89, 0x1a8f, 0x1b92, 0x1c39, 0x1c4d, 0x1a89, 0x1a89,
- 0x1a89, 0x7804, 0xd09c, 0x1904, 0x1c5e, 0x080c, 0x14f6, 0x8001,
- 0x7002, 0xa184, 0x0880, 0x1190, 0xd19c, 0x1904, 0x1b20, 0x8aff,
- 0x0904, 0x1b20, 0x2009, 0x0001, 0x080c, 0x19e0, 0x0904, 0x1c5e,
- 0x2009, 0x0001, 0x080c, 0x19e0, 0x0804, 0x1c5e, 0x7803, 0x0004,
- 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1b00, 0x0026, 0x0036, 0x7c20,
- 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001,
- 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803,
- 0x0009, 0x7003, 0x0004, 0x0010, 0x080c, 0x1c62, 0x6b28, 0x6a2c,
- 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e,
- 0x00c6, 0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, 0x633a, 0x6236,
- 0x00ce, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x080c, 0x215e, 0x2a00,
- 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852,
- 0x6808, 0x8001, 0x680a, 0x1148, 0x684c, 0xd0e4, 0x0130, 0x7004,
- 0x2060, 0x2009, 0x0048, 0x080c, 0x80a7, 0x7000, 0xa086, 0x0004,
- 0x0904, 0x1c5e, 0x7003, 0x0000, 0x080c, 0x195f, 0x0804, 0x1c5e,
- 0x0056, 0x7d0c, 0xd5bc, 0x1110, 0x080c, 0xac73, 0x005e, 0x080c,
- 0x1d22, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5029, 0x0118, 0x7820,
- 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, 0xffff, 0x6808,
- 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, 0x1c5e,
- 0x7004, 0x00c6, 0x2060, 0x6020, 0x00ce, 0xd0f4, 0x0128, 0x6808,
- 0x8001, 0x680a, 0x0804, 0x1c5e, 0x7818, 0x6812, 0x7a1c, 0x6a16,
- 0xd19c, 0x0160, 0xa205, 0x0150, 0x7004, 0xa080, 0x0007, 0x2004,
- 0xa084, 0xfffd, 0xa086, 0x0008, 0x1904, 0x1aa6, 0x684c, 0xc0f5,
- 0x684e, 0x7814, 0xa005, 0x1180, 0x7003, 0x0000, 0x6808, 0x8001,
- 0x680a, 0x1130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x80a7,
- 0x080c, 0x195f, 0x0804, 0x1c5e, 0x7818, 0x6812, 0x781c, 0x6816,
- 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214,
- 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b,
- 0x810b, 0x080c, 0x1da5, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803,
- 0x0001, 0x7804, 0xd0fc, 0x0de8, 0x7803, 0x0002, 0x7803, 0x0004,
- 0x780f, 0x00f6, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048,
- 0x080c, 0x80a7, 0x080c, 0x1dd7, 0x0958, 0x7908, 0xd1ec, 0x1118,
- 0x2009, 0x0009, 0x0010, 0x2009, 0x0019, 0x7902, 0x7003, 0x0003,
- 0x0804, 0x1c5e, 0x8001, 0x7002, 0xd194, 0x01a8, 0x7804, 0xd0fc,
- 0x1904, 0x1c2c, 0xd09c, 0x0130, 0x7804, 0xd0fc, 0x1904, 0x1a74,
- 0xd09c, 0x11a8, 0x8aff, 0x0904, 0x1c5e, 0x2009, 0x0001, 0x080c,
- 0x19e0, 0x0804, 0x1c5e, 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904,
- 0x1c5e, 0x2009, 0x0001, 0x080c, 0x19e0, 0x0804, 0x1c5e, 0x7818,
- 0x6812, 0x7a1c, 0x6a16, 0xa205, 0x0904, 0x1b3e, 0x7803, 0x0004,
- 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1c0f, 0x6834, 0xa084, 0x00ff,
- 0xa086, 0x0029, 0x1118, 0xd19c, 0x1904, 0x1b3e, 0x0026, 0x0036,
- 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816,
- 0x2001, 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128,
- 0x7803, 0x0009, 0x7003, 0x0004, 0x0020, 0x0016, 0x080c, 0x1c62,
- 0x001e, 0x6b28, 0x6a2c, 0x080c, 0x215e, 0x00d6, 0x2805, 0xac68,
- 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020,
- 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0xd194, 0x0904, 0x1ac8,
- 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001,
- 0x680a, 0x6b2a, 0x6a2e, 0x003e, 0x002e, 0x0804, 0x1b50, 0x0056,
- 0x7d0c, 0x080c, 0xac73, 0x005e, 0x080c, 0x1d22, 0x00f6, 0x7004,
- 0x2078, 0x080c, 0x5029, 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe,
- 0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c,
- 0x791a, 0x6980, 0x791e, 0x0490, 0x7804, 0xd09c, 0x0904, 0x1a74,
- 0x7c20, 0x7824, 0xa405, 0x1904, 0x1a74, 0x7803, 0x0002, 0x0804,
- 0x1bb7, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0150,
- 0x6808, 0x8001, 0x680a, 0x1130, 0x7004, 0x2060, 0x2009, 0x0048,
- 0x080c, 0x80a7, 0x080c, 0x195f, 0x0088, 0x7803, 0x0004, 0x7003,
- 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0da0, 0x2068, 0x6808,
- 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x080c, 0x197a, 0x001e, 0x000e,
- 0x012e, 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1ce1, 0x7004,
- 0x0016, 0x210c, 0xa106, 0x001e, 0x0904, 0x1ce1, 0x00d6, 0x00c6,
- 0x216c, 0x2d00, 0xa005, 0x0904, 0x1cdf, 0x6820, 0xd0d4, 0x1904,
- 0x1cdf, 0x6810, 0x2068, 0x6850, 0xd0fc, 0x0558, 0x8108, 0x2104,
- 0x6b2c, 0xa306, 0x1904, 0x1cdf, 0x8108, 0x2104, 0x6a28, 0xa206,
- 0x1904, 0x1cdf, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822,
- 0x6870, 0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060,
- 0x6034, 0xd09c, 0x0150, 0x6830, 0x2005, 0x00d6, 0xac68, 0x6808,
- 0x783a, 0x680c, 0x783e, 0x00de, 0x04a0, 0xa006, 0x783a, 0x783e,
- 0x0480, 0x8108, 0x2104, 0xa005, 0x1590, 0x8108, 0x2104, 0xa005,
- 0x1570, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, 0x6918, 0xa160,
- 0xa180, 0x000d, 0x2004, 0xd09c, 0x1170, 0x6008, 0x7822, 0x686e,
- 0x600c, 0x7826, 0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0xa006,
- 0x783a, 0x783e, 0x0070, 0x6010, 0x7822, 0x686e, 0x6014, 0x7826,
- 0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0x6008, 0x783a, 0x600c,
- 0x783e, 0x6810, 0x781a, 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce,
- 0x00de, 0x0005, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005,
- 0x1118, 0x8109, 0x1dd8, 0x0005, 0x0005, 0x0ca1, 0x01e0, 0x7908,
- 0xd1ec, 0x1160, 0x080c, 0x1dd7, 0x0148, 0x7803, 0x0009, 0x7904,
- 0xd1fc, 0x0de8, 0x7803, 0x0006, 0x0c29, 0x0168, 0x780c, 0xd0a4,
- 0x1150, 0x7007, 0x0000, 0x080c, 0x1dd7, 0x0140, 0x7803, 0x0019,
- 0x7003, 0x0003, 0x0018, 0x00b1, 0xa085, 0x0001, 0x0005, 0x0126,
- 0x2091, 0x2200, 0x7000, 0xa086, 0x0003, 0x1150, 0x700c, 0x7110,
- 0xa106, 0x0130, 0x20e1, 0x9028, 0x700f, 0xb003, 0x7013, 0xb003,
- 0x012e, 0x0005, 0x00c6, 0x080c, 0x574f, 0x1550, 0x2001, 0x0160,
- 0x2003, 0x0000, 0x2001, 0x0138, 0x2003, 0x0000, 0x2011, 0x00c8,
- 0xe000, 0xe000, 0x8211, 0x1de0, 0x080c, 0x1d7e, 0x700c, 0x7110,
- 0xa106, 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060,
- 0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xb01e, 0x0210,
- 0x2009, 0xb003, 0x7112, 0x0c50, 0x080c, 0x57d1, 0x00ce, 0x0005,
- 0x04a9, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x01d0, 0x2104,
- 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a,
- 0xa188, 0x0003, 0xa182, 0xb01e, 0x0210, 0x2009, 0xb003, 0x7112,
- 0x700c, 0xa106, 0x1d40, 0x080c, 0x2744, 0x2001, 0x0138, 0x2102,
- 0x0c10, 0x2001, 0x015d, 0x200c, 0x810a, 0x2102, 0x2001, 0x0160,
- 0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x20e1, 0x9028,
- 0x2001, 0x015d, 0x200c, 0x810a, 0x2102, 0x0005, 0x2001, 0x0138,
- 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000,
- 0x2021, 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001,
- 0x0109, 0x201c, 0xa39c, 0x0048, 0x1138, 0x2001, 0x0111, 0x201c,
- 0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005, 0x00e6, 0x2071, 0x0200,
- 0x7808, 0xa084, 0xf000, 0xa10d, 0x08c9, 0x2019, 0x5000, 0x8319,
- 0x0168, 0x2001, 0xb01e, 0x2004, 0xa086, 0x0000, 0x0138, 0x2001,
- 0x0021, 0xd0fc, 0x0da0, 0x080c, 0x1ff4, 0x0c78, 0x20e1, 0x7000,
- 0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f,
- 0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001,
- 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x0005, 0x7908,
- 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0218, 0xa085, 0x0001, 0x0088,
- 0x2001, 0x020a, 0x81ff, 0x0130, 0x20e1, 0x6000, 0x200c, 0x200c,
- 0x200c, 0x200c, 0x20e1, 0x7000, 0x200c, 0x200c, 0x7003, 0x0000,
- 0xa006, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x0026, 0x2071, 0xaffd,
- 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, 0x0000, 0x01a8,
- 0x8211, 0x0188, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0dc8, 0x7904,
- 0xa18c, 0x0780, 0x0016, 0x080c, 0x1a6c, 0x001e, 0x81ff, 0x1118,
- 0x2011, 0x0050, 0x0c48, 0xa085, 0x0001, 0x002e, 0x001e, 0x00ee,
- 0x00fe, 0x0005, 0x7803, 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac,
- 0x0904, 0x1e66, 0x8109, 0x1dd0, 0x2009, 0x0100, 0x210c, 0xa18a,
- 0x0003, 0x0a0c, 0x14f6, 0x080c, 0x20f2, 0x00e6, 0x00f6, 0x2071,
- 0xafec, 0x2079, 0x0010, 0x7004, 0xa086, 0x0000, 0x0538, 0x7800,
- 0x0006, 0x7820, 0x0006, 0x7830, 0x0006, 0x7834, 0x0006, 0x7838,
- 0x0006, 0x783c, 0x0006, 0x7803, 0x0004, 0xe000, 0xe000, 0x2079,
- 0x0030, 0x7804, 0xd0ac, 0x190c, 0x14f6, 0x2079, 0x0010, 0x000e,
- 0x783e, 0x000e, 0x783a, 0x000e, 0x7836, 0x000e, 0x7832, 0x000e,
- 0x7822, 0x000e, 0x7802, 0x00fe, 0x00ee, 0x0030, 0x00fe, 0x00ee,
- 0x7804, 0xd0ac, 0x190c, 0x14f6, 0x080c, 0x6d0d, 0x0005, 0x00e6,
- 0x2071, 0xb01e, 0x7003, 0x0000, 0x00ee, 0x0005, 0x00d6, 0xa280,
- 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, 0x1ee4, 0x6934, 0xa184,
- 0x0007, 0x0002, 0x1e82, 0x1ecf, 0x1e82, 0x1e82, 0x1e82, 0x1eb6,
- 0x1e95, 0x1e84, 0x080c, 0x14f6, 0x684c, 0xd0b4, 0x0904, 0x1fcc,
- 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a,
- 0x6880, 0x680e, 0x6958, 0x0804, 0x1ed7, 0x6834, 0xa084, 0x00ff,
- 0xa086, 0x001e, 0x1d38, 0x684c, 0xd0b4, 0x0904, 0x1fcc, 0x6860,
- 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880,
- 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f,
- 0xa080, 0x2186, 0x2005, 0x6832, 0x6958, 0x0450, 0xa18c, 0x00ff,
- 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, 0x1fcc, 0x6804,
- 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x2186,
- 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0088, 0x684c,
- 0xd0b4, 0x0904, 0x1a47, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00,
- 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x2186, 0x2005, 0x6832,
- 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, 0x00f6, 0x2079,
- 0x0020, 0x7804, 0xd0fc, 0x190c, 0x1ff4, 0x00e6, 0x00d6, 0x2071,
- 0xb01e, 0x7000, 0xa005, 0x1904, 0x1f4c, 0x00c6, 0x7206, 0xa280,
- 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x00d6,
- 0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, 0x9040, 0x2079,
- 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, 0x00de,
- 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034,
- 0xa0cc, 0x000f, 0x6908, 0x791a, 0x7116, 0x680c, 0x781e, 0x701a,
- 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, 0x1120,
- 0x6928, 0x6810, 0xa106, 0x0158, 0x0036, 0x0046, 0x6b14, 0x6c10,
- 0x080c, 0x21a6, 0x004e, 0x003e, 0x0110, 0x00ce, 0x00a8, 0x8aff,
- 0x1120, 0x00ce, 0xa085, 0x0001, 0x0078, 0x0126, 0x2091, 0x8000,
- 0x2079, 0x0020, 0x2009, 0x0001, 0x0059, 0x0118, 0x2009, 0x0001,
- 0x0039, 0x012e, 0x00ce, 0xa006, 0x00de, 0x00ee, 0x00fe, 0x0005,
- 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904,
- 0x1fc5, 0x700c, 0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, 0x0a04,
- 0x1fc4, 0xa705, 0x0904, 0x1fc4, 0xa03e, 0x2730, 0x6850, 0xd0fc,
- 0x11a8, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x1fa7, 0x1f8c,
- 0x1f8c, 0x1fa7, 0x1fa7, 0x1fa0, 0x1fa7, 0x1f8c, 0x1fa7, 0x1f91,
- 0x1f91, 0x1fa7, 0x1fa7, 0x1fa7, 0x1f98, 0x1f91, 0xc0fc, 0x6852,
- 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x0528, 0x00d6, 0x2805,
- 0xac68, 0x6f08, 0x6e0c, 0x00f0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04,
- 0x00c8, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0090,
- 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1138,
- 0x00de, 0x080c, 0x2148, 0x1904, 0x1f56, 0xa00e, 0x00f0, 0x00de,
- 0x080c, 0x14f6, 0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a,
- 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a,
- 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201,
- 0x7012, 0x080c, 0x2148, 0x0008, 0xa006, 0x002e, 0x003e, 0x004e,
- 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x14f6, 0x0026, 0x2001,
- 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
- 0x0000, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9596,
- 0x0118, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x929c, 0x20e1,
- 0x9040, 0x080c, 0x7cb8, 0x2011, 0x0000, 0x080c, 0x7ae9, 0x080c,
- 0x6d0d, 0x002e, 0x0804, 0x20ad, 0x0126, 0x2091, 0x2400, 0x0006,
- 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071,
- 0xb01e, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184,
- 0x0700, 0x1920, 0x7000, 0x0002, 0x20ad, 0x2010, 0x2080, 0x20ab,
- 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, 0x2009, 0x0001,
- 0x080c, 0x1f50, 0x0904, 0x20ad, 0x2009, 0x0001, 0x080c, 0x1f50,
- 0x0804, 0x20ad, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, 0xc0fc,
- 0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, 0x00b8, 0x0026,
- 0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, 0x6872,
- 0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, 0x6a2e, 0x003e,
- 0x002e, 0x080c, 0x215e, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826,
- 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0804, 0x20ad,
- 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100,
- 0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, 0x0036, 0x2019,
- 0x1000, 0x8319, 0x090c, 0x14f6, 0x7820, 0xd0bc, 0x1dd0, 0x003e,
- 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e,
- 0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, 0xa085, 0x0012,
- 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, 0x0000, 0x0468,
- 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, 0x1904, 0x2004,
- 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, 0x1f50,
- 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, 0x215e, 0x00d6,
- 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c,
- 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0x0804,
- 0x2033, 0x0804, 0x202f, 0x080c, 0x14f6, 0x00ce, 0x00de, 0x00ee,
- 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071,
- 0xb01e, 0x7000, 0xa086, 0x0000, 0x0590, 0x2079, 0x0020, 0x0016,
- 0x2009, 0x0207, 0x210c, 0xd194, 0x0158, 0x2009, 0x020c, 0x210c,
- 0xa184, 0x0003, 0x0128, 0x20e1, 0x9040, 0x2001, 0x020c, 0x2102,
- 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, 0x1110,
- 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x0d18, 0x080c, 0x1ff4, 0x7000,
- 0xa086, 0x0000, 0x19e8, 0x001e, 0x7803, 0x0004, 0x7804, 0xd0ac,
- 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x00ee,
- 0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2071,
- 0xb01e, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0540, 0x7004,
- 0x2060, 0x6010, 0x2068, 0x080c, 0x9596, 0x0158, 0x6850, 0xc0b5,
- 0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, 0x7a18, 0xa206,
- 0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803,
- 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, 0x929c, 0x20e1,
- 0x9040, 0x080c, 0x7cb8, 0x2011, 0x0000, 0x080c, 0x7ae9, 0x00fe,
- 0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, 0x6a14, 0xa205,
- 0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, 0x1e6e, 0x2001,
- 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
- 0x0000, 0x2069, 0xafc7, 0x6833, 0x0000, 0x683f, 0x0000, 0x08f8,
- 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, 0x0168, 0x681a,
- 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x2186, 0x2045, 0x88ff,
- 0x090c, 0x14f6, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841,
- 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, 0x6000, 0xa005,
- 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080,
- 0x2196, 0x2045, 0x88ff, 0x090c, 0x14f6, 0x0005, 0x0000, 0x0011,
- 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f,
- 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x217b,
- 0x2177, 0x0000, 0x0000, 0x2185, 0x0000, 0x217b, 0x0000, 0x2182,
- 0x217f, 0x0000, 0x0000, 0x0000, 0x2185, 0x2182, 0x0000, 0x217d,
- 0x217d, 0x0000, 0x0000, 0x2185, 0x0000, 0x217d, 0x0000, 0x2183,
- 0x2183, 0x0000, 0x0000, 0x0000, 0x2185, 0x2183, 0x00a6, 0x0096,
- 0x0086, 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0904, 0x2237, 0x2d60,
- 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2186, 0xa986, 0x0007, 0x0130,
- 0xa986, 0x000e, 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422,
- 0x6060, 0xa31a, 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x2237,
- 0x6004, 0xa065, 0x0904, 0x2237, 0x0c18, 0x2805, 0xa005, 0x01a8,
- 0xac68, 0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020,
- 0x6810, 0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150,
- 0x8a51, 0x0904, 0x2237, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904,
- 0x2237, 0x0830, 0x8a51, 0x0904, 0x2237, 0x8840, 0x2805, 0xa005,
- 0x1158, 0x6004, 0xa065, 0x0904, 0x2237, 0x6034, 0xa0cc, 0x000f,
- 0xa9c0, 0x2186, 0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852,
- 0x0458, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68,
- 0x6c6e, 0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122,
- 0x690c, 0x2300, 0xa11b, 0x0a0c, 0x14f6, 0x6800, 0xa420, 0x6804,
- 0xa319, 0x0060, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b,
- 0x0a0c, 0x14f6, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e,
- 0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832,
- 0x2a00, 0x6826, 0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e,
- 0x009e, 0x00ae, 0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004,
- 0xa084, 0x0007, 0x0002, 0x224b, 0x224c, 0x224f, 0x2252, 0x2257,
- 0x225a, 0x225f, 0x2264, 0x0005, 0x080c, 0x1ff4, 0x0005, 0x080c,
- 0x1a6c, 0x0005, 0x080c, 0x1a6c, 0x080c, 0x1ff4, 0x0005, 0x080c,
- 0x16f8, 0x0005, 0x080c, 0x1ff4, 0x080c, 0x16f8, 0x0005, 0x080c,
- 0x1a6c, 0x080c, 0x16f8, 0x0005, 0x080c, 0x1a6c, 0x080c, 0x1ff4,
- 0x080c, 0x16f8, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200,
- 0x2071, 0xb280, 0x2069, 0xad00, 0x2009, 0x0004, 0x7912, 0x7817,
- 0x0004, 0x080c, 0x2651, 0x781b, 0x0002, 0x20e1, 0x9080, 0x20e1,
- 0x4000, 0x20a9, 0x0080, 0x782f, 0x0000, 0x1f04, 0x2283, 0x20e1,
- 0x9080, 0x783b, 0x001f, 0x20e1, 0x8700, 0x012e, 0x0005, 0x0126,
- 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, 0x2335, 0xa084, 0x0007,
- 0x0002, 0x22b3, 0x22a1, 0x22a4, 0x22a7, 0x22ac, 0x22ae, 0x22b0,
- 0x22b2, 0x080c, 0x5fb7, 0x0078, 0x080c, 0x5ff0, 0x0060, 0x080c,
- 0x5fb7, 0x080c, 0x5ff0, 0x0038, 0x0041, 0x0028, 0x0031, 0x0018,
- 0x0021, 0x0008, 0x0011, 0x012e, 0x0005, 0x0006, 0x0016, 0x0026,
- 0x7930, 0xa184, 0x0003, 0x0118, 0x20e1, 0x9040, 0x04a0, 0xa184,
- 0x0030, 0x01e0, 0x6a00, 0xa286, 0x0003, 0x1108, 0x00a0, 0x080c,
- 0x574f, 0x1178, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00,
- 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5793, 0x080c, 0x569a,
- 0x0010, 0x080c, 0x485e, 0x20e1, 0x9010, 0x00a8, 0xa184, 0x00c0,
- 0x0168, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0xaffd, 0x080c,
- 0x1d22, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0028, 0xa184, 0x0300,
- 0x0110, 0x20e1, 0x9020, 0x7932, 0x002e, 0x001e, 0x000e, 0x0005,
- 0x0016, 0x00e6, 0x00f6, 0x2071, 0xad00, 0x7128, 0x2001, 0xaf90,
- 0x2102, 0x2001, 0xaf98, 0x2102, 0xa182, 0x0211, 0x1218, 0x2009,
- 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0,
- 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349,
- 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009,
- 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010,
- 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0x7817, 0x0004, 0x080c,
- 0x2651, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x7938, 0x080c, 0x14f6,
- 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0xad00, 0x6024,
- 0x6026, 0x6053, 0x0030, 0x080c, 0x2690, 0x6050, 0xa084, 0xfe7f,
- 0x6052, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x26a0, 0x60e7,
- 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000,
- 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x0e9f, 0x601b, 0x001e,
- 0x600f, 0x00ff, 0x2001, 0xaf8c, 0x2003, 0x00ff, 0x602b, 0x002f,
- 0x012e, 0x0005, 0x2001, 0xad31, 0x2003, 0x0000, 0x2001, 0xad30,
- 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016,
- 0x0026, 0x6124, 0xa184, 0x1e2c, 0x1118, 0xa184, 0x0007, 0x002a,
- 0xa195, 0x0004, 0xa284, 0x0007, 0x0002, 0x23a7, 0x238d, 0x2390,
- 0x2393, 0x2398, 0x239a, 0x239e, 0x23a2, 0x080c, 0x6699, 0x00b8,
- 0x080c, 0x6774, 0x00a0, 0x080c, 0x6774, 0x080c, 0x6699, 0x0078,
- 0x0099, 0x0068, 0x080c, 0x6699, 0x0079, 0x0048, 0x080c, 0x6774,
- 0x0059, 0x0028, 0x080c, 0x6774, 0x080c, 0x6699, 0x0029, 0x002e,
- 0x001e, 0x000e, 0x012e, 0x0005, 0x6124, 0xd19c, 0x1904, 0x25bf,
- 0x080c, 0x574f, 0x0578, 0x7000, 0xa086, 0x0003, 0x0198, 0x6024,
- 0xa084, 0x1800, 0x0178, 0x080c, 0x5775, 0x0118, 0x080c, 0x5761,
- 0x1148, 0x6027, 0x0020, 0x6043, 0x0000, 0x2001, 0xaf9d, 0x2003,
- 0xaaaa, 0x0458, 0x080c, 0x5775, 0x15d0, 0x6024, 0xa084, 0x1800,
- 0x1108, 0x04a8, 0x2001, 0xaf9d, 0x2003, 0xaaaa, 0x2001, 0xaf9e,
- 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x080c, 0x569a,
- 0x0804, 0x25bf, 0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, 0xd0e4,
- 0x1188, 0xd0d4, 0x11a0, 0xd0cc, 0x0130, 0x7088, 0xa086, 0x0028,
- 0x1110, 0x080c, 0x58da, 0x0804, 0x25bf, 0x2001, 0xaf9e, 0x2003,
- 0x0000, 0x0048, 0x2001, 0xaf9e, 0x2003, 0x0002, 0x0020, 0x080c,
- 0x584d, 0x0804, 0x25bf, 0x080c, 0x597a, 0x0804, 0x25bf, 0xd1ac,
- 0x0904, 0x2507, 0x080c, 0x574f, 0x11d8, 0x6027, 0x0020, 0x0006,
- 0x0026, 0x0036, 0x080c, 0x576b, 0x1170, 0x2001, 0xaf9e, 0x2003,
- 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x080c, 0x569a, 0x003e,
- 0x002e, 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x5726,
- 0x0016, 0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, 0x2061,
- 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74ca, 0xa48c,
- 0xff00, 0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, 0x7038,
- 0xd084, 0x1148, 0xc085, 0x703a, 0x0036, 0x2418, 0x2011, 0x8016,
- 0x080c, 0x3c5c, 0x003e, 0xa196, 0xff00, 0x05b8, 0x7050, 0xa084,
- 0x00ff, 0x810f, 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, 0x2011,
- 0xad52, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, 0xad52,
- 0x2214, 0xd2ac, 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, 0x6248,
- 0xa294, 0xff00, 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904,
- 0x24d2, 0x7034, 0xd08c, 0x1140, 0x2001, 0xad0c, 0x200c, 0xd1ac,
- 0x1904, 0x24d2, 0xc1ad, 0x2102, 0x0036, 0x73c8, 0x2011, 0x8013,
- 0x080c, 0x3c5c, 0x003e, 0x0804, 0x24d2, 0x7034, 0xd08c, 0x1140,
- 0x2001, 0xad0c, 0x200c, 0xd1ac, 0x1904, 0x24d2, 0xc1ad, 0x2102,
- 0x0036, 0x73c8, 0x2011, 0x8013, 0x080c, 0x3c5c, 0x003e, 0x7130,
- 0xc185, 0x7132, 0x2011, 0xad52, 0x220c, 0xd1a4, 0x01d0, 0x0016,
- 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x663f, 0x2019, 0x000e,
- 0x080c, 0xa8eb, 0xa484, 0x00ff, 0xa080, 0x2be6, 0x200d, 0xa18c,
- 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0xa96c,
- 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004,
- 0x080c, 0x2aac, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009,
- 0x0000, 0x080c, 0x4cdc, 0x1110, 0x080c, 0x493a, 0x8108, 0x1f04,
- 0x24c9, 0x015e, 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x7adf,
- 0x2011, 0x0002, 0x080c, 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581,
- 0x0036, 0x2019, 0x0000, 0x080c, 0x7a64, 0x003e, 0x60e3, 0x0000,
- 0x001e, 0x2001, 0xad00, 0x2014, 0xa296, 0x0004, 0x1128, 0xd19c,
- 0x1118, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xad22,
- 0x2003, 0x0000, 0x6027, 0x0020, 0x080c, 0x5775, 0x1140, 0x0016,
- 0x2009, 0x07d0, 0x2011, 0x567b, 0x080c, 0x6593, 0x001e, 0xd194,
- 0x0904, 0x25bf, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x2570, 0x080c,
- 0x6581, 0x080c, 0x7834, 0x6027, 0x0004, 0x00f6, 0x2019, 0xafd0,
- 0x2304, 0xa07d, 0x0570, 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6,
- 0x00c6, 0x00e6, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e,
- 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0,
- 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, 0x0000, 0x618e, 0x628a,
- 0x080c, 0x6b73, 0x080c, 0x6c50, 0x7810, 0x2070, 0x7037, 0x0103,
- 0x2f60, 0x080c, 0x8078, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e,
- 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000,
- 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061,
- 0xafc7, 0x6028, 0xa09a, 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce,
- 0x080c, 0x7827, 0x0804, 0x25be, 0x2019, 0xafd0, 0x2304, 0xa065,
- 0x0120, 0x2009, 0x0027, 0x080c, 0x80a7, 0x00ce, 0x0804, 0x25be,
- 0xd2bc, 0x0904, 0x25be, 0x080c, 0x658e, 0x6014, 0xa084, 0x0184,
- 0xa085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140,
- 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, 0x6803, 0x0000,
- 0x00de, 0x00c6, 0x2061, 0xafc7, 0x6044, 0xa09a, 0x00c8, 0x12f0,
- 0x8000, 0x6046, 0x603c, 0x00ce, 0xa005, 0x0540, 0x2009, 0x07d0,
- 0x080c, 0x6586, 0xa080, 0x0007, 0x2004, 0xa086, 0x0006, 0x1138,
- 0x6114, 0xa18c, 0x0184, 0xa18d, 0x0012, 0x6116, 0x00b8, 0x6114,
- 0xa18c, 0x0184, 0xa18d, 0x0016, 0x6116, 0x0080, 0x0036, 0x2019,
- 0x0001, 0x080c, 0x7a64, 0x003e, 0x2019, 0xafd6, 0x2304, 0xa065,
- 0x0120, 0x2009, 0x004f, 0x080c, 0x80a7, 0x00ce, 0x001e, 0xd19c,
- 0x0904, 0x261a, 0x7034, 0xd0ac, 0x1560, 0x0016, 0x0156, 0x6027,
- 0x0008, 0x602f, 0x0020, 0x20a9, 0x0006, 0x1d04, 0x25cd, 0x2091,
- 0x6000, 0x1f04, 0x25cd, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400,
- 0x6052, 0x20a9, 0x0366, 0x1d04, 0x25db, 0x2091, 0x6000, 0x6020,
- 0xd09c, 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0490,
- 0x080c, 0x2760, 0x1f04, 0x25db, 0x015e, 0x6152, 0x001e, 0x6027,
- 0x0008, 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c,
- 0x7adf, 0x2011, 0x0002, 0x080c, 0x7ae9, 0x080c, 0x79e1, 0x080c,
- 0x6581, 0x0036, 0x2019, 0x0000, 0x080c, 0x7a64, 0x003e, 0x60e3,
- 0x0000, 0x080c, 0xac8d, 0x080c, 0xaca8, 0xa085, 0x0001, 0x080c,
- 0x5793, 0x2001, 0xad00, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c,
- 0x12cc, 0x001e, 0xa18c, 0xffd0, 0x6126, 0x0005, 0x0006, 0x0016,
- 0x0026, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0xad00,
- 0x71c0, 0x70c2, 0xa116, 0x01f0, 0x81ff, 0x0128, 0x2011, 0x8011,
- 0x080c, 0x3c5c, 0x00b8, 0x2011, 0x8012, 0x080c, 0x3c5c, 0x2001,
- 0xad71, 0x2004, 0xd0fc, 0x1170, 0x0036, 0x00c6, 0x080c, 0x26eb,
- 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0000, 0x080c, 0x2aac,
- 0x00ce, 0x003e, 0x012e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e,
- 0x0005, 0x00c6, 0x00f6, 0x0006, 0x0026, 0x2061, 0x0100, 0xa190,
- 0x2664, 0x2205, 0x60f2, 0x2011, 0x2671, 0x2205, 0x60ee, 0x002e,
- 0x000e, 0x00fe, 0x00ce, 0x0005, 0x0840, 0x0840, 0x0840, 0x0580,
- 0x0420, 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8,
- 0x01a8, 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c,
- 0x00ff, 0x2130, 0xa094, 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c,
- 0x6278, 0x0038, 0xa080, 0x2be6, 0x200d, 0xa18c, 0xff00, 0x810f,
- 0xa006, 0x0005, 0xa080, 0x2be6, 0x200d, 0xa18c, 0x00ff, 0x0005,
- 0x00d6, 0x2069, 0x0140, 0x2001, 0xad14, 0x2003, 0x00ef, 0x20a9,
- 0x0010, 0xa006, 0x6852, 0x6856, 0x1f04, 0x269b, 0x00de, 0x0005,
- 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0xad14, 0x2102,
- 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000,
- 0xa006, 0x82ff, 0x1128, 0xa184, 0x000f, 0xa080, 0xacae, 0x2005,
- 0x6856, 0x8211, 0x1f04, 0x26b0, 0x002e, 0x00de, 0x000e, 0x0005,
- 0x00c6, 0x2061, 0xad00, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c,
- 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006,
- 0x2069, 0x0140, 0x6980, 0xa116, 0x0180, 0xa112, 0x1230, 0x8212,
- 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404,
- 0x680e, 0x1f04, 0x26e0, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e,
- 0x00de, 0x015e, 0x0005, 0x2001, 0xad52, 0x2004, 0xd0c4, 0x0150,
- 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c,
- 0xa96c, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140,
- 0x78c4, 0xd0dc, 0x0548, 0xa084, 0x0700, 0xa08e, 0x0300, 0x1520,
- 0x2011, 0x0000, 0x2009, 0x0002, 0x2300, 0xa080, 0x0020, 0x2018,
- 0x2300, 0x080c, 0x6665, 0x2011, 0x0030, 0x2200, 0x8007, 0xa085,
- 0x004c, 0x78c2, 0x2009, 0x0204, 0x210c, 0x2200, 0xa100, 0x2009,
- 0x0138, 0x200a, 0x080c, 0x574f, 0x1118, 0x2009, 0xaf8e, 0x200a,
- 0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126,
- 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c,
- 0x8000, 0x2014, 0xa184, 0x0003, 0x0110, 0x0804, 0x1a6a, 0x002e,
- 0x001e, 0x000e, 0x012e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004,
- 0xa082, 0x0005, 0x000e, 0x0268, 0x2001, 0x0170, 0x200c, 0xa18c,
- 0x00ff, 0xa18e, 0x004c, 0x1128, 0x200c, 0xa18c, 0xff00, 0x810f,
- 0x0010, 0x2009, 0x0000, 0x2001, 0x0204, 0x2004, 0xa108, 0x0005,
- 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854,
- 0xd08c, 0x1110, 0x1f04, 0x2767, 0x00fe, 0x015e, 0x000e, 0x0005,
- 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, 0x6030, 0x0006, 0x6048,
- 0x0006, 0x60e4, 0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, 0x60f0,
- 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028,
- 0x0006, 0x60e0, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0xe000,
- 0xe000, 0xe000, 0xe000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e,
- 0x60e2, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e,
- 0x60ee, 0x000e, 0x60f2, 0x000e, 0x6052, 0x000e, 0x60ea, 0x000e,
- 0x60e6, 0x000e, 0x604a, 0x000e, 0x6032, 0x6036, 0x2008, 0x080c,
- 0x26a0, 0x000e, 0x00ce, 0x001e, 0x0005, 0x2845, 0x2849, 0x284d,
- 0x2853, 0x2859, 0x285f, 0x2865, 0x286d, 0x2875, 0x287b, 0x2881,
- 0x2889, 0x2891, 0x2899, 0x28a1, 0x28ab, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b7, 0x28b7, 0x28bc,
- 0x28bc, 0x28c3, 0x28c3, 0x28ca, 0x28ca, 0x28d3, 0x28d3, 0x28da,
- 0x28da, 0x28e3, 0x28e3, 0x28ec, 0x28ec, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
- 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x0106, 0x0006, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c,
- 0x2373, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106,
- 0x0006, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c,
- 0x2373, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c,
- 0x2373, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c,
- 0x228f, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, 0x228f, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, 0x228f, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, 0x228f, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x080c, 0x223d, 0x080c, 0x228f, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x080c, 0x223d, 0x080c, 0x228f, 0x0804,
- 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, 0x223d, 0x080c,
- 0x228f, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c,
- 0x223d, 0x080c, 0x228f, 0x0804, 0x28f7, 0xe000, 0x0cf0, 0x0106,
- 0x0006, 0x080c, 0x272f, 0x04d8, 0x0106, 0x0006, 0x080c, 0x272f,
- 0x080c, 0x2373, 0x04a0, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c,
- 0x223d, 0x0468, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c, 0x2373,
- 0x080c, 0x223d, 0x0420, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c,
- 0x228f, 0x00e8, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c, 0x2373,
- 0x080c, 0x228f, 0x00a0, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c,
- 0x223d, 0x080c, 0x228f, 0x0058, 0x0106, 0x0006, 0x080c, 0x272f,
- 0x080c, 0x2373, 0x080c, 0x223d, 0x080c, 0x228f, 0x0000, 0x000e,
- 0x010e, 0x000d, 0x00c6, 0x0026, 0x0046, 0x2021, 0x0000, 0x080c,
- 0x502d, 0x1904, 0x29d4, 0x72d0, 0x2001, 0xaf9d, 0x2004, 0xa005,
- 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x29d4,
- 0x080c, 0x29d8, 0x0804, 0x29d4, 0x080c, 0x574f, 0x1120, 0x709b,
- 0xffff, 0x0804, 0x29d4, 0xd294, 0x0120, 0x709b, 0xffff, 0x0804,
- 0x29d4, 0x2001, 0xad14, 0x203c, 0x7284, 0xd284, 0x0904, 0x2976,
- 0xd28c, 0x1904, 0x2976, 0x0036, 0x7398, 0xa38e, 0xffff, 0x1110,
- 0x2019, 0x0001, 0x8314, 0xa2e0, 0xb3c0, 0x2c04, 0xa38c, 0x0001,
- 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa70e,
- 0x0560, 0xa08e, 0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, 0x7230,
- 0xd284, 0x1538, 0x7284, 0xc28d, 0x7286, 0x709b, 0xffff, 0x003e,
- 0x0428, 0x2009, 0x0000, 0x080c, 0x2676, 0x080c, 0x4c80, 0x11b8,
- 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, 0xd08c,
- 0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, 0x29eb, 0x0140, 0x0028,
- 0x080c, 0x2b1a, 0x080c, 0x2a19, 0x0110, 0x8318, 0x0818, 0x739a,
- 0x0010, 0x709b, 0xffff, 0x003e, 0x0804, 0x29d4, 0xa780, 0x2be6,
- 0x203d, 0xa7bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x7098, 0xa096,
- 0xffff, 0x1120, 0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, 0x0220,
- 0x2008, 0xa802, 0x20a8, 0x0020, 0x709b, 0xffff, 0x0804, 0x29d4,
- 0x2700, 0x0156, 0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, 0x4cdc,
- 0x0120, 0x080c, 0x4c80, 0x15a8, 0x0008, 0xc485, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, 0x6000,
- 0xd0bc, 0x11d0, 0x7284, 0xd28c, 0x0188, 0x6004, 0xa084, 0x00ff,
- 0xa082, 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x4c9f, 0x0028,
- 0x080c, 0x2b9c, 0x0170, 0x080c, 0x2bc9, 0x0058, 0x080c, 0x2b1a,
- 0x080c, 0x2a19, 0x0170, 0x0028, 0x080c, 0x2b9c, 0x0110, 0x0419,
- 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2990, 0x709b, 0xffff,
- 0x0018, 0x001e, 0x015e, 0x719a, 0x004e, 0x002e, 0x00ce, 0x0005,
- 0x00c6, 0x0016, 0x709b, 0x0000, 0x2009, 0x007e, 0x080c, 0x4c80,
- 0x1138, 0x080c, 0x2b1a, 0x04a9, 0x0118, 0x70d0, 0xc0bd, 0x70d2,
- 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68,
- 0x2001, 0xad56, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9807,
- 0x01d8, 0x2d00, 0x601a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2001,
- 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0000, 0x080c, 0x4c30, 0x0126,
- 0x2091, 0x8000, 0x7094, 0x8000, 0x7096, 0x012e, 0x2009, 0x0004,
- 0x080c, 0x80a7, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e,
- 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xad56,
- 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9807, 0x0550, 0x2d00,
- 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, 0x0140,
- 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, 0x2ad9,
- 0x080c, 0x9956, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4c1e,
- 0x2001, 0x0002, 0x080c, 0x4c30, 0x0126, 0x2091, 0x8000, 0x7094,
- 0x8000, 0x7096, 0x012e, 0x2009, 0x0002, 0x080c, 0x80a7, 0xa085,
- 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026,
- 0x2009, 0x0080, 0x080c, 0x4c80, 0x1120, 0x0031, 0x0110, 0x70d7,
- 0xffff, 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6,
- 0x2c68, 0x080c, 0x8022, 0x01d8, 0x2d00, 0x601a, 0x080c, 0x9956,
- 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0002,
- 0x080c, 0x4c30, 0x0126, 0x2091, 0x8000, 0x70d8, 0x8000, 0x70da,
- 0x012e, 0x2009, 0x0002, 0x080c, 0x80a7, 0xa085, 0x0001, 0x00ce,
- 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091,
- 0x8000, 0x2009, 0x007f, 0x080c, 0x4c80, 0x1190, 0x2c68, 0x080c,
- 0x8022, 0x0170, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a,
- 0x080c, 0x9956, 0x2009, 0x0022, 0x080c, 0x80a7, 0xa085, 0x0001,
- 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036,
- 0x0026, 0x080c, 0x68f3, 0x080c, 0x689d, 0x080c, 0x8a15, 0x2130,
- 0x81ff, 0x0128, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0020, 0x20a9,
- 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4cdc, 0x1120, 0x080c,
- 0x4ecf, 0x080c, 0x493a, 0x001e, 0x8108, 0x1f04, 0x2ac3, 0x86ff,
- 0x1110, 0x080c, 0x11d4, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee,
- 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, 0x2270,
- 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x68e7, 0x0076, 0x2039,
- 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, 0xa712, 0x007e, 0x001e,
- 0x2e60, 0x080c, 0x4ecf, 0x6210, 0x6314, 0x080c, 0x493a, 0x6212,
- 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6,
- 0x0006, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x0080, 0x0150,
- 0x2071, 0xad00, 0x7094, 0xa005, 0x0110, 0x8001, 0x7096, 0x000e,
- 0x00ee, 0x0005, 0x2071, 0xad00, 0x70d8, 0xa005, 0x0dc0, 0x8001,
- 0x70da, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6,
- 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118,
- 0x20a9, 0x0001, 0x0098, 0x2001, 0xad52, 0x2004, 0xd0c4, 0x0150,
- 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002d, 0x080c,
- 0xa96c, 0x004e, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x0026, 0xa28e,
- 0x007e, 0x05c8, 0xa28e, 0x007f, 0x05b0, 0xa28e, 0x0080, 0x0598,
- 0xa288, 0xae34, 0x210c, 0x81ff, 0x0570, 0x8fff, 0x05c1, 0x00c6,
- 0x2160, 0x2001, 0x0001, 0x080c, 0x5037, 0x00ce, 0x2019, 0x0029,
- 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x00c6,
- 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x1118,
- 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206,
- 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, 0xa712, 0x001e, 0x007e,
- 0x2160, 0x080c, 0x4ecf, 0x002e, 0x8210, 0x1f04, 0x2b3e, 0x015e,
- 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046,
- 0x0026, 0x0016, 0x2001, 0xad52, 0x2004, 0xd0c4, 0x0148, 0xd0a4,
- 0x0138, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, 0x080c, 0xa96c,
- 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6,
- 0x7284, 0x82ff, 0x01f8, 0x2011, 0xad52, 0x2214, 0xd2ac, 0x11d0,
- 0x2100, 0x080c, 0x268a, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314,
- 0xa2e0, 0xb3c0, 0x2c04, 0xd384, 0x0120, 0xa084, 0xff00, 0x8007,
- 0x0010, 0xa084, 0x00ff, 0xa116, 0x0138, 0xa096, 0x00ff, 0x0110,
- 0x8318, 0x0c68, 0xa085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e,
- 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0xa180, 0xae34,
- 0x2004, 0xa065, 0x0178, 0x0016, 0x00c6, 0x080c, 0x9807, 0x001e,
- 0x090c, 0x14f6, 0x611a, 0x080c, 0x2ad9, 0x080c, 0x8078, 0x001e,
- 0x080c, 0x4c9f, 0x012e, 0x00ce, 0x001e, 0x0005, 0x7eef, 0x7de8,
- 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6,
- 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc,
- 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc,
- 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1,
- 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6,
- 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797,
- 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c,
- 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071,
- 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66,
- 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454,
- 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a,
- 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039,
- 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d,
- 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123,
- 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f,
- 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700,
- 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000,
- 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000,
- 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700,
- 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100,
- 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00,
- 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
- 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400,
- 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00,
- 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800,
- 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400,
- 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
- 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0xad81,
- 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e, 0x7033,
- 0xad91, 0x7037, 0xad91, 0x7007, 0x0001, 0x2061, 0xadd1, 0x6003,
- 0x0002, 0x0005, 0x1004, 0x2d0c, 0x0e04, 0x2d0c, 0x2071, 0xad81,
- 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60, 0x7820, 0xa08e, 0x0069,
- 0x1904, 0x2df1, 0x0804, 0x2d8a, 0x0005, 0x2071, 0xad81, 0x7004,
- 0x0002, 0x2d15, 0x2d16, 0x2d1f, 0x2d30, 0x0005, 0x1004, 0x2d1e,
- 0x0e04, 0x2d1e, 0x2b78, 0x7818, 0xd084, 0x01e8, 0x0005, 0x2b78,
- 0x2061, 0xadd1, 0x6008, 0xa08e, 0x0100, 0x0128, 0xa086, 0x0200,
- 0x0904, 0x2deb, 0x0005, 0x7014, 0x2068, 0x2a60, 0x7018, 0x0807,
- 0x7010, 0x2068, 0x6834, 0xa086, 0x0103, 0x0108, 0x0005, 0x2a60,
- 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x1210,
- 0x61c0, 0x0042, 0x2100, 0xa08a, 0x003f, 0x1a04, 0x2de8, 0x61c0,
- 0x0804, 0x2d8a, 0x2dcc, 0x2df7, 0x2dff, 0x2e03, 0x2e0b, 0x2e11,
- 0x2e15, 0x2e21, 0x2e24, 0x2e2e, 0x2e31, 0x2de8, 0x2de8, 0x2de8,
- 0x2e34, 0x2de8, 0x2e43, 0x2e5a, 0x2e71, 0x2ee8, 0x2eed, 0x2f16,
- 0x2f67, 0x2f78, 0x2f96, 0x2fcd, 0x2fd7, 0x2fe4, 0x2ff7, 0x3018,
- 0x3021, 0x3057, 0x305d, 0x2de8, 0x3086, 0x2de8, 0x2de8, 0x2de8,
- 0x2de8, 0x2de8, 0x308d, 0x3097, 0x2de8, 0x2de8, 0x2de8, 0x2de8,
- 0x2de8, 0x2de8, 0x2de8, 0x2de8, 0x309f, 0x2de8, 0x2de8, 0x2de8,
- 0x2de8, 0x2de8, 0x30b1, 0x30b9, 0x2de8, 0x2de8, 0x2de8, 0x2de8,
- 0x2de8, 0x2de8, 0x0002, 0x30cb, 0x311f, 0x317a, 0x318a, 0x2de8,
- 0x31a4, 0x35cb, 0x3fbb, 0x2de8, 0x2de8, 0x2de8, 0x2de8, 0x2de8,
- 0x2de8, 0x2de8, 0x2de8, 0x2e2e, 0x2e31, 0x35cd, 0x2de8, 0x35da,
- 0x403c, 0x4097, 0x40fb, 0x2de8, 0x415a, 0x4180, 0x419f, 0x2de8,
- 0x2de8, 0x2de8, 0x2de8, 0x35de, 0x376b, 0x3785, 0x37a3, 0x3804,
- 0x3858, 0x3863, 0x389a, 0x38a9, 0x38b8, 0x38bb, 0x38de, 0x3928,
- 0x398e, 0x399b, 0x3a9c, 0x3bb3, 0x3bdc, 0x3cda, 0x3cfc, 0x3d08,
- 0x3d41, 0x3e05, 0x2de8, 0x2de8, 0x2de8, 0x2de8, 0x3e6d, 0x3e88,
- 0x3efa, 0x3fac, 0x713c, 0x0000, 0x2021, 0x4000, 0x080c, 0x3c39,
- 0x0126, 0x2091, 0x8000, 0x0e04, 0x2dd8, 0x7818, 0xd084, 0x0110,
- 0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a, 0x7b2e, 0x781b, 0x0001,
- 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, 0x0005,
- 0x2021, 0x4001, 0x0c18, 0x2021, 0x4002, 0x0c00, 0x2021, 0x4003,
- 0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021, 0x4006, 0x08b8, 0xa02e,
- 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3c46, 0x7823,
- 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824,
- 0x7930, 0x0804, 0x3c49, 0x7924, 0x7828, 0x2114, 0x200a, 0x0804,
- 0x2dcc, 0x7924, 0x2114, 0x0804, 0x2dcc, 0x2099, 0x0009, 0x20a1,
- 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0804,
- 0x2dcc, 0x7824, 0x2060, 0x0090, 0x2009, 0x0002, 0x2011, 0x0001,
- 0x2019, 0x001b, 0x783b, 0x0017, 0x0804, 0x2dcc, 0x7d38, 0x7c3c,
- 0x0840, 0x7d38, 0x7c3c, 0x0888, 0x2061, 0x1000, 0xe10c, 0xa006,
- 0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0xa005, 0x0904,
- 0x2dcc, 0x0804, 0x2dee, 0x2069, 0xad51, 0x7824, 0x7930, 0xa11a,
- 0x1a04, 0x2df4, 0x8019, 0x0904, 0x2df4, 0x684a, 0x6942, 0x782c,
- 0x6852, 0x7828, 0x6856, 0xa006, 0x685a, 0x685e, 0x080c, 0x5a1c,
- 0x0804, 0x2dcc, 0x2069, 0xad51, 0x7824, 0x7934, 0xa11a, 0x1a04,
- 0x2df4, 0x8019, 0x0904, 0x2df4, 0x684e, 0x6946, 0x782c, 0x6862,
- 0x7828, 0x6866, 0xa006, 0x686a, 0x686e, 0x080c, 0x50d9, 0x0804,
- 0x2dcc, 0xa02e, 0x2520, 0x81ff, 0x1904, 0x2df1, 0x7924, 0x7b28,
- 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xad88, 0x41a1, 0x080c, 0x3c05,
- 0x0904, 0x2df1, 0x2009, 0x0020, 0x080c, 0x3c46, 0x701b, 0x2e89,
- 0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0120,
- 0xa096, 0x0019, 0x1904, 0x2df1, 0x810f, 0xa18c, 0x00ff, 0x0904,
- 0x2df1, 0x710e, 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, 0x3c05,
- 0x0904, 0x2df1, 0x2009, 0x0020, 0x2061, 0xadd1, 0x6224, 0x6328,
- 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000,
- 0xa5a9, 0x0000, 0x080c, 0x3c46, 0x701b, 0x2eb7, 0x0005, 0x6834,
- 0xa084, 0x00ff, 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, 0x1904,
- 0x2df1, 0x08c0, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c,
- 0x4b7c, 0x1128, 0x7007, 0x0003, 0x701b, 0x2ed1, 0x0005, 0x080c,
- 0x51df, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xad88,
- 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
- 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x012e, 0x0804, 0x3c49,
- 0x61a8, 0x7824, 0x60aa, 0x0804, 0x2dcc, 0x2091, 0x8000, 0x7823,
- 0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009,
- 0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200,
- 0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd,
- 0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080,
- 0x2071, 0x0010, 0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904,
- 0x2df1, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4cdc, 0x1904,
- 0x2df4, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804,
- 0x2df4, 0x7c28, 0x7d2c, 0x080c, 0x4e96, 0xd28c, 0x1118, 0x080c,
- 0x4e41, 0x0010, 0x080c, 0x4e6f, 0x1518, 0x2061, 0xb400, 0x0126,
- 0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d,
- 0x0130, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, 0x012e,
- 0xace0, 0x0018, 0x2001, 0xad16, 0x2004, 0xac02, 0x1a04, 0x2df1,
- 0x0c30, 0x080c, 0x929c, 0x012e, 0x0904, 0x2df1, 0x0804, 0x2dcc,
- 0xa00e, 0x2001, 0x0005, 0x080c, 0x51df, 0x0126, 0x2091, 0x8000,
- 0x080c, 0x9803, 0x080c, 0x510c, 0x012e, 0x0804, 0x2dcc, 0x81ff,
- 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4d96,
- 0x0904, 0x2df1, 0x080c, 0x4ea2, 0x0904, 0x2df1, 0x0804, 0x2dcc,
- 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x080c,
- 0x4f0d, 0x0904, 0x2df1, 0x2019, 0x0005, 0x080c, 0x4ebd, 0x0904,
- 0x2df1, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2df4, 0x8003, 0x800b,
- 0x810b, 0xa108, 0x080c, 0x6519, 0x0804, 0x2dcc, 0x0126, 0x2091,
- 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0448, 0x2029, 0x00ff,
- 0x644c, 0x2400, 0xa506, 0x01f0, 0x2508, 0x080c, 0x4cdc, 0x11d0,
- 0x080c, 0x4f0d, 0x1128, 0x2009, 0x0002, 0x62b0, 0x2518, 0x00b8,
- 0x2019, 0x0004, 0x080c, 0x4ebd, 0x1118, 0x2009, 0x0006, 0x0078,
- 0x7824, 0xa08a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0xa108,
- 0x080c, 0x6519, 0x8529, 0x1ae8, 0x012e, 0x0804, 0x2dcc, 0x012e,
- 0x0804, 0x2df1, 0x012e, 0x0804, 0x2df4, 0x080c, 0x3c1a, 0x0904,
- 0x2df4, 0x080c, 0x4dfc, 0x080c, 0x4e96, 0x0804, 0x2dcc, 0x81ff,
- 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4ded,
- 0x080c, 0x4e96, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x080c,
- 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4e71, 0x0904, 0x2df1, 0x080c,
- 0x4bc0, 0x080c, 0x4e3a, 0x080c, 0x4e96, 0x0804, 0x2dcc, 0x080c,
- 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4d96, 0x0904, 0x2df1, 0x62a0,
- 0x2019, 0x0005, 0x00c6, 0x080c, 0x4ecf, 0x2061, 0x0000, 0x080c,
- 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x2009, 0x0000,
- 0x080c, 0xa712, 0x007e, 0x00ce, 0x080c, 0x4e96, 0x0804, 0x2dcc,
- 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4e96, 0x2208, 0x0804,
- 0x2dcc, 0x0156, 0x00d6, 0x00e6, 0x2069, 0xae13, 0x6810, 0x6914,
- 0xa10a, 0x1210, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019,
- 0x0000, 0x20a9, 0x007e, 0x2069, 0xae34, 0x2d04, 0xa075, 0x0130,
- 0x704c, 0x0071, 0xa210, 0x7080, 0x0059, 0xa318, 0x8d68, 0x1f04,
- 0x3035, 0x2300, 0xa218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x2dcc,
- 0x00f6, 0x0016, 0xa07d, 0x0140, 0x2001, 0x0000, 0x8000, 0x2f0c,
- 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069,
- 0xae13, 0x6910, 0x62ac, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1,
- 0x614c, 0xa190, 0x2be6, 0x2215, 0xa294, 0x00ff, 0x636c, 0x83ff,
- 0x0108, 0x6270, 0x67d0, 0xd79c, 0x0118, 0x2031, 0x0001, 0x0090,
- 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, 0x2031,
- 0x0002, 0x0040, 0x080c, 0x574f, 0x1118, 0x2031, 0x0004, 0x0010,
- 0x2031, 0x0000, 0x7e3a, 0x7f3e, 0x0804, 0x2dcc, 0x613c, 0x6240,
- 0x2019, 0xafa3, 0x231c, 0x0804, 0x2dcc, 0x0126, 0x2091, 0x8000,
- 0x6134, 0xa006, 0x2010, 0x2018, 0x012e, 0x0804, 0x2dcc, 0x080c,
- 0x3c2a, 0x0904, 0x2df4, 0x6244, 0x6338, 0x0804, 0x2dcc, 0x613c,
- 0x6240, 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0xad51, 0x831f,
- 0xa305, 0x6816, 0x782c, 0x2069, 0xafa3, 0x2d1c, 0x206a, 0x0804,
- 0x2dcc, 0x0126, 0x2091, 0x8000, 0x7824, 0x6036, 0x012e, 0x0804,
- 0x2dcc, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x7828, 0xa00d, 0x0904,
- 0x2df4, 0x782c, 0xa005, 0x0904, 0x2df4, 0x6244, 0x6146, 0x6338,
- 0x603a, 0x0804, 0x2dcc, 0x2001, 0xad00, 0x2004, 0xa086, 0x0003,
- 0x1904, 0x2df1, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c,
- 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0xad14, 0x2004, 0xa085,
- 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, 0x2be6, 0x210d,
- 0xa18c, 0x00ff, 0x2001, 0xad14, 0x2004, 0xa116, 0x0550, 0x810f,
- 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x8022, 0x000e,
- 0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x080c, 0x3c05,
- 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838,
- 0xc0fd, 0x683a, 0x701b, 0x3173, 0x2d00, 0x6012, 0x2009, 0x0032,
- 0x080c, 0x80a7, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804,
- 0x2df1, 0x00ce, 0x0804, 0x2df4, 0x080c, 0x8078, 0x0cb0, 0x2001,
- 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, 0x00c6, 0x2061,
- 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130,
- 0x2001, 0xad14, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f,
- 0x16a0, 0xa188, 0x2be6, 0x210d, 0xa18c, 0x00ff, 0x2001, 0xad14,
- 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000,
- 0x0006, 0x080c, 0x8022, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc05,
- 0x601f, 0x0001, 0x080c, 0x3c05, 0x01d8, 0x6837, 0x0000, 0x7007,
- 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x3173,
- 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, 0x80a7, 0x012e, 0x00ce,
- 0x0005, 0x012e, 0x00ce, 0x0804, 0x2df1, 0x00ce, 0x0804, 0x2df4,
- 0x080c, 0x8078, 0x0cb0, 0x6830, 0xa086, 0x0100, 0x0904, 0x2df1,
- 0x0804, 0x2dcc, 0x2061, 0xb048, 0x0126, 0x2091, 0x8000, 0x6000,
- 0xd084, 0x0128, 0x6104, 0x6208, 0x012e, 0x0804, 0x2dcc, 0x012e,
- 0x0804, 0x2df4, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, 0x0904,
- 0x2df1, 0x0126, 0x2091, 0x8000, 0x6244, 0x6064, 0xa202, 0x0248,
- 0xa085, 0x0001, 0x080c, 0x26c0, 0x080c, 0x436e, 0x012e, 0x0804,
- 0x2dcc, 0x012e, 0x0804, 0x2df4, 0x0126, 0x2091, 0x8000, 0x7824,
- 0xa084, 0x0007, 0x0002, 0x31b6, 0x31bf, 0x31c6, 0x31b3, 0x31b3,
- 0x31b3, 0x31b3, 0x31b3, 0x012e, 0x0804, 0x2df4, 0x2009, 0x0114,
- 0x2104, 0xa085, 0x0800, 0x200a, 0x080c, 0x332f, 0x0070, 0x2009,
- 0x010b, 0x200b, 0x0010, 0x080c, 0x332f, 0x0038, 0x81ff, 0x0128,
- 0x012e, 0x2021, 0x400b, 0x0804, 0x2dce, 0x0086, 0x0096, 0x00a6,
- 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2009, 0x0101, 0x210c,
- 0x0016, 0x2001, 0x0138, 0x200c, 0x2003, 0x0001, 0x0016, 0x2001,
- 0x007a, 0x2034, 0x2001, 0x007b, 0x202c, 0xa006, 0x2048, 0x2050,
- 0x2058, 0x080c, 0x3570, 0x080c, 0x34da, 0xa03e, 0x2720, 0x00f6,
- 0x00e6, 0x00c6, 0x2d60, 0x2071, 0xb01e, 0x2079, 0x0020, 0x00d6,
- 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004,
- 0x783e, 0x2001, 0x007c, 0x2004, 0x783a, 0x00de, 0x2011, 0x0001,
- 0x080c, 0x3486, 0x080c, 0x3486, 0x00ce, 0x00ee, 0x00fe, 0x080c,
- 0x33d5, 0x080c, 0x34ae, 0x080c, 0x342b, 0x080c, 0x3394, 0x080c,
- 0x33c5, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, 0x0530, 0x7814,
- 0xa084, 0x0184, 0xa085, 0x0010, 0x7816, 0x2079, 0x0140, 0x080c,
- 0x330d, 0x1110, 0x00fe, 0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079,
- 0x0100, 0x7827, 0x0086, 0x7814, 0xa084, 0x0184, 0xa085, 0x0032,
- 0x7816, 0x080c, 0x330d, 0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc,
- 0x0dc0, 0x7827, 0x0080, 0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130,
- 0x8b58, 0x080c, 0x3317, 0x00fe, 0x0804, 0x32d7, 0x00fe, 0x080c,
- 0x330d, 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, 0x2001, 0x007b,
- 0x2502, 0x080c, 0x3317, 0x0088, 0x87ff, 0x0140, 0x2001, 0x0201,
- 0x2004, 0xa005, 0x1904, 0x3211, 0x8739, 0x0038, 0x2001, 0xaffd,
- 0x2004, 0xa086, 0x0000, 0x1904, 0x3211, 0x2001, 0x0033, 0x2003,
- 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, 0x0904, 0x32d7,
- 0x7824, 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, 0x1904, 0x32d7,
- 0x6033, 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac,
- 0x1148, 0x2001, 0xaffd, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003,
- 0x0009, 0x0040, 0x6027, 0x0001, 0x2001, 0x0075, 0x2004, 0xa005,
- 0x0108, 0x6026, 0x2c00, 0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a,
- 0x6833, 0x000d, 0x7824, 0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6,
- 0x20a9, 0x0004, 0x2061, 0x0020, 0x6003, 0x0008, 0x2001, 0x0203,
- 0x2004, 0x1f04, 0x32ac, 0x00ce, 0x0040, 0x6827, 0x0001, 0x2001,
- 0x0074, 0x2004, 0xa005, 0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079,
- 0x0100, 0x2061, 0x0020, 0x7827, 0x0002, 0x2001, 0x0072, 0x2004,
- 0xa084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x0073, 0x2004, 0x601e,
- 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x31ef, 0x2061,
- 0x0100, 0x6027, 0x0002, 0x001e, 0x61e2, 0x001e, 0x6106, 0x7824,
- 0xa084, 0x0003, 0xa086, 0x0002, 0x0188, 0x20e1, 0x9028, 0x6050,
- 0xa084, 0xf7ef, 0x6052, 0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e,
- 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10,
- 0x2b18, 0x2b00, 0xaa05, 0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce,
- 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, 0x2dcc,
- 0x012e, 0x2021, 0x400c, 0x0804, 0x2dce, 0xa085, 0x0001, 0x1d04,
- 0x3316, 0x2091, 0x6000, 0x8420, 0xa486, 0x0064, 0x0005, 0x2001,
- 0x0105, 0x2003, 0x0010, 0x2001, 0x0030, 0x2003, 0x0004, 0x2001,
- 0x0020, 0x2003, 0x0004, 0x2001, 0xaffd, 0x2003, 0x0000, 0x2001,
- 0xb01e, 0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6,
- 0x2079, 0x0100, 0x2001, 0xad14, 0x200c, 0x7932, 0x7936, 0x080c,
- 0x26a0, 0x7850, 0xa084, 0x0980, 0xa085, 0x0030, 0x7852, 0x2019,
- 0x01f4, 0x8319, 0x1df0, 0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad,
- 0x782e, 0x20a9, 0x0046, 0x1d04, 0x334b, 0x2091, 0x6000, 0x1f04,
- 0x334b, 0x7850, 0xa085, 0x0400, 0x7852, 0x2001, 0x0009, 0x2004,
- 0xa084, 0x0003, 0xa086, 0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e,
- 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e,
- 0xe000, 0x1f04, 0x3368, 0x7850, 0xa085, 0x1400, 0x7852, 0x2019,
- 0x61a8, 0x7854, 0xe000, 0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8,
- 0x7827, 0x0048, 0x7850, 0xa085, 0x0400, 0x7852, 0x7843, 0x0040,
- 0x2019, 0x01f4, 0xe000, 0xe000, 0x8319, 0x1de0, 0x2001, 0x0140,
- 0x2003, 0x0100, 0x7827, 0x0020, 0x7843, 0x0000, 0x2003, 0x0000,
- 0x7827, 0x0048, 0x00fe, 0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6,
- 0x00e6, 0x2071, 0xaffd, 0x2079, 0x0030, 0x2001, 0x0201, 0x2004,
- 0xa005, 0x0160, 0x7000, 0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc,
- 0x0108, 0x8738, 0x7003, 0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe,
- 0x0005, 0x780c, 0xa08c, 0x0070, 0x0178, 0x2009, 0x007a, 0x260a,
- 0x2009, 0x007b, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108,
- 0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200,
- 0x781c, 0xd084, 0x0140, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001,
- 0x020a, 0x2004, 0x0ca8, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100,
- 0x2009, 0xad14, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, 0x719e,
- 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, 0xa080,
- 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0xa006,
- 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5,
- 0x7027, 0x0080, 0x7014, 0xa084, 0x0184, 0xa085, 0x0032, 0x7016,
- 0x080c, 0x34ae, 0x080c, 0x330d, 0x1110, 0x8421, 0x0028, 0x7024,
- 0xd0bc, 0x0db0, 0x7027, 0x0080, 0x00f6, 0x00e6, 0x2071, 0xaffd,
- 0x2079, 0x0030, 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0120,
- 0x683c, 0x783e, 0x6838, 0x783a, 0x00de, 0x2011, 0x0011, 0x080c,
- 0x3486, 0x2011, 0x0001, 0x080c, 0x3486, 0x00ee, 0x00fe, 0x7017,
- 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0xaffd, 0x2079,
- 0x0030, 0x7904, 0xd1fc, 0x0904, 0x3483, 0x7803, 0x0002, 0xa026,
- 0xd19c, 0x1904, 0x347f, 0x7000, 0x0002, 0x3483, 0x3441, 0x3465,
- 0x347f, 0xd1bc, 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002, 0x2011,
- 0x0001, 0x04e1, 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000, 0x7820,
- 0x7924, 0x7803, 0x0004, 0x7822, 0x7926, 0x2001, 0x0201, 0x200c,
- 0x81ff, 0x0de8, 0x080c, 0x33b1, 0x2009, 0x0001, 0x7808, 0xd0ec,
- 0x0110, 0x2009, 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002, 0xa184,
- 0x0880, 0x1138, 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001, 0x00b1,
- 0x0090, 0x6030, 0xa092, 0x0004, 0xa086, 0x0009, 0x1120, 0x6000,
- 0x601a, 0x2011, 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870, 0x7803,
- 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024, 0xa005,
- 0x0520, 0x8001, 0x6026, 0x6018, 0x6130, 0xa140, 0x2804, 0x7832,
- 0x8840, 0x2804, 0x7836, 0x8840, 0x2804, 0x7822, 0x8840, 0x2804,
- 0x7826, 0x8840, 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018, 0xa802,
- 0xa08a, 0x0029, 0x1138, 0x6018, 0xa080, 0x0001, 0x2004, 0x601a,
- 0x2001, 0x000d, 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6,
- 0x00c6, 0x2071, 0xb01e, 0x2079, 0x0020, 0x7904, 0xd1fc, 0x01f0,
- 0x7803, 0x0002, 0x2d60, 0xa026, 0x7000, 0x0002, 0x34d6, 0x34c1,
- 0x34cd, 0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, 0x080c,
- 0x3486, 0x0160, 0x080c, 0x3486, 0x0048, 0x8001, 0x7002, 0x7804,
- 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, 0x3486, 0x00ce, 0x00ee,
- 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x601b,
- 0x0004, 0x2061, 0x0100, 0x60cf, 0x0400, 0x6004, 0xc0ac, 0xa085,
- 0x0200, 0x6006, 0x2001, 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038,
- 0x2001, 0x0076, 0x2024, 0x2001, 0x0077, 0x201c, 0x080c, 0x3c05,
- 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220,
- 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080,
- 0x000d, 0x04a1, 0x1d90, 0x2d00, 0x681a, 0x0088, 0x080c, 0x3c05,
- 0x6833, 0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001,
- 0x0076, 0x2004, 0x2072, 0x2001, 0x0077, 0x2004, 0x7006, 0x2061,
- 0x0020, 0x2079, 0x0100, 0x6013, 0x0400, 0x20e1, 0x9040, 0x2001,
- 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, 0x2001,
- 0x0073, 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, 0xa006,
- 0x603a, 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071,
- 0x0010, 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, 0x7336,
- 0xa006, 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7122,
- 0x7003, 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, 0x7003,
- 0x0040, 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, 0x00d6,
- 0x2d60, 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x6018, 0x2070, 0x2d00,
- 0x7006, 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, 0x0005,
- 0x00e6, 0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, 0x2001,
- 0x0078, 0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3c05, 0x2d60,
- 0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220,
- 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080,
- 0x000d, 0x080c, 0x353e, 0x1d88, 0x2d00, 0x681a, 0x00e0, 0x080c,
- 0x3c05, 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, 0x0001, 0x2c00,
- 0x601a, 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, 0x0079, 0x2004,
- 0x7006, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x2001,
- 0x0073, 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824,
- 0xd0ac, 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, 0x6027,
- 0x0000, 0x2001, 0xaffd, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003,
- 0x0009, 0x00ee, 0x0005, 0x0804, 0x2dcc, 0x0126, 0x2091, 0x8000,
- 0x20a9, 0x0011, 0x2001, 0xad40, 0x20a0, 0xa006, 0x40a4, 0x012e,
- 0x0804, 0x2dcc, 0x7d38, 0x7c3c, 0x0804, 0x2e73, 0x080c, 0x3c05,
- 0x0904, 0x2df1, 0x080c, 0x574f, 0x0110, 0x080c, 0x491f, 0x2009,
- 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c46, 0x701b,
- 0x35f2, 0x0005, 0xade8, 0x000d, 0x6800, 0xa005, 0x0904, 0x2df4,
- 0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2df4, 0xd094, 0x00c6,
- 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0xa292, 0x0005, 0x0218,
- 0xa18c, 0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, 0x00ce, 0xd08c,
- 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, 0x0010, 0x0010,
- 0xa18c, 0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, 0x210c, 0xa18a,
- 0x0002, 0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, 0x007f, 0x1a04,
- 0x2df4, 0xa288, 0x2be6, 0x210d, 0xa18c, 0x00ff, 0x6156, 0xd0dc,
- 0x0130, 0x6828, 0xa08a, 0x007f, 0x1a04, 0x2df4, 0x604e, 0x6808,
- 0xa08a, 0x0100, 0x0a04, 0x2df4, 0xa08a, 0x0841, 0x1a04, 0x2df4,
- 0xa084, 0x0007, 0x1904, 0x2df4, 0x680c, 0xa005, 0x0904, 0x2df4,
- 0x6810, 0xa005, 0x0904, 0x2df4, 0x6848, 0x6940, 0xa10a, 0x1a04,
- 0x2df4, 0x8001, 0x0904, 0x2df4, 0x684c, 0x6944, 0xa10a, 0x1a04,
- 0x2df4, 0x8001, 0x0904, 0x2df4, 0x6804, 0xd0fc, 0x0560, 0x080c,
- 0x3c05, 0x0904, 0x2df1, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c,
- 0x7d38, 0xa290, 0x0038, 0xa399, 0x0000, 0x080c, 0x3c46, 0x701b,
- 0x3672, 0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069,
- 0xad6d, 0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xad71,
- 0x200c, 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, 0x6004, 0xa085,
- 0x0b00, 0x6006, 0x00ce, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xad51,
- 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084,
- 0x00ff, 0x6042, 0x080c, 0x5a1c, 0x080c, 0x5070, 0x080c, 0x50d9,
- 0x6000, 0xa086, 0x0000, 0x1904, 0x3755, 0x6808, 0x602a, 0x080c,
- 0x22f8, 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e,
- 0x0268, 0x2009, 0x0170, 0x200b, 0x0080, 0xe000, 0xe000, 0x200b,
- 0x0000, 0x0036, 0x6b08, 0x080c, 0x26fb, 0x003e, 0x6818, 0x691c,
- 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a,
- 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38,
- 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0xa084, 0xf0ff,
- 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f,
- 0x20a9, 0x0004, 0x20a1, 0xafad, 0x40a1, 0x080c, 0x659c, 0x6904,
- 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, 0x20a9, 0x0001, 0x6b70,
- 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c,
- 0x5fa9, 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007,
- 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003,
- 0x0010, 0x6003, 0x0001, 0x1f04, 0x36f3, 0x00ce, 0x2069, 0xad51,
- 0x2001, 0xaf9d, 0x6a80, 0xa294, 0x0030, 0xa28e, 0x0000, 0x0170,
- 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, 0x0140, 0x2003, 0xaaaa,
- 0x080c, 0x2744, 0x2001, 0xaf8e, 0x2102, 0x0008, 0x2102, 0x00c6,
- 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c,
- 0x574f, 0x0128, 0x080c, 0x3e5f, 0x0110, 0x080c, 0x26c0, 0x60c4,
- 0xa005, 0x01b0, 0x6003, 0x0001, 0x2009, 0x373f, 0x00c0, 0x080c,
- 0x574f, 0x1158, 0x2011, 0x566e, 0x080c, 0x650d, 0x2001, 0xaf9e,
- 0x2003, 0x0000, 0x080c, 0x569a, 0x0040, 0x080c, 0x485e, 0x0028,
- 0x6003, 0x0004, 0x2009, 0x3755, 0x0010, 0x0804, 0x2dcc, 0x2001,
- 0x0100, 0x2004, 0xa082, 0x0005, 0x0258, 0x2001, 0x0170, 0x2004,
- 0xa084, 0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, 0x309d, 0x0817,
- 0x2091, 0x301d, 0x0817, 0x6000, 0xa086, 0x0000, 0x0904, 0x2df1,
- 0x2069, 0xad51, 0x7830, 0x6842, 0x7834, 0x6846, 0x6804, 0xd0fc,
- 0x0118, 0x2009, 0x0030, 0x0010, 0x2009, 0x001c, 0x2d00, 0x7a2c,
- 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, 0xa006, 0x080c, 0x26c0,
- 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, 0x1178, 0x2001, 0xaf9e,
- 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0xa085, 0x0001,
- 0x080c, 0x5793, 0x080c, 0x569a, 0x0020, 0x080c, 0x491f, 0x080c,
- 0x485e, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f,
- 0x1110, 0x0804, 0x2df1, 0x6184, 0x81ff, 0x0198, 0x703f, 0x0000,
- 0x2001, 0xb3c0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
- 0x0126, 0x2091, 0x8000, 0x080c, 0x3c49, 0x701b, 0x2dca, 0x012e,
- 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, 0xb3c0, 0x20a9, 0x0040,
- 0x20a1, 0xb3c0, 0x2019, 0xffff, 0x43a4, 0x654c, 0xa588, 0x2be6,
- 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100,
- 0xa506, 0x01a8, 0x080c, 0x4cdc, 0x1190, 0x6014, 0x821c, 0x0238,
- 0xa398, 0xb3c0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0038, 0xa398,
- 0xb3c0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, 0x8108,
- 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0xa105,
- 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0xb3c0, 0x2099, 0xb3c0,
- 0x080c, 0x48be, 0x0804, 0x37b0, 0x080c, 0x3c2a, 0x0904, 0x2df4,
- 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804,
- 0x2df1, 0x2001, 0xad52, 0x2004, 0xd0b4, 0x01f0, 0x6000, 0xd08c,
- 0x11d8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837,
- 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x970b, 0x1120, 0x2009,
- 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3830, 0x0005,
- 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x20a9, 0x002b, 0x2c98, 0xade8,
- 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098,
- 0xad80, 0x0006, 0x20a0, 0x080c, 0x48be, 0x20a9, 0x0004, 0xac80,
- 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, 0x080c, 0x48be, 0x2d00,
- 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49,
- 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c,
- 0x4eab, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x7828, 0xa08a,
- 0x1000, 0x1a04, 0x2df4, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x080c,
- 0x4f0d, 0x0904, 0x2df1, 0x2019, 0x0004, 0x080c, 0x4ebd, 0x7924,
- 0x810f, 0x7a28, 0x0011, 0x0804, 0x2dcc, 0xa186, 0x00ff, 0x0110,
- 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0xad00, 0x644c, 0x2400,
- 0xa506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c,
- 0x4cdc, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c,
- 0x6519, 0x0005, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904,
- 0x2df4, 0x080c, 0x4d96, 0x0904, 0x2df1, 0x080c, 0x4eb4, 0x0804,
- 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4,
- 0x080c, 0x4d96, 0x0904, 0x2df1, 0x080c, 0x4ea2, 0x0804, 0x2dcc,
- 0x6100, 0x0804, 0x2dcc, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x2001,
- 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, 0x00d6, 0xace8,
- 0x000a, 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007,
- 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217,
- 0x00de, 0x6100, 0xa18c, 0x0200, 0x0804, 0x2dcc, 0x7824, 0xa09c,
- 0x00ff, 0xa39a, 0x0003, 0x1a04, 0x2df1, 0x624c, 0xa294, 0x00ff,
- 0xa084, 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, 0xad40, 0x2009,
- 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, 0x81ff,
- 0x1904, 0x2df1, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x1904, 0x2df1, 0x00c6, 0x080c, 0x3c05,
- 0x00ce, 0x0904, 0x2df1, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a,
- 0x080c, 0x96b7, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3919,
- 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2df1, 0xad80, 0x000e,
- 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49,
- 0xa006, 0x080c, 0x26c0, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff,
- 0x0118, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, 0x0110, 0x080c,
- 0x491f, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2df4, 0x7924, 0xa18c,
- 0xff00, 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, 0x1a04,
- 0x2df4, 0x2100, 0x080c, 0x268a, 0x0026, 0x00c6, 0x0126, 0x2091,
- 0x8000, 0x2061, 0xafda, 0x601b, 0x0000, 0x601f, 0x0000, 0x080c,
- 0x574f, 0x1178, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00,
- 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5793, 0x080c, 0x569a,
- 0x00a0, 0x2061, 0x0100, 0x2001, 0xad14, 0x2004, 0xa084, 0x00ff,
- 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009,
- 0x002d, 0x2011, 0x4883, 0x080c, 0x6593, 0x7924, 0xa18c, 0xff00,
- 0x810f, 0x080c, 0x574f, 0x1110, 0x2009, 0x00ff, 0x7a28, 0x080c,
- 0x387d, 0x012e, 0x00ce, 0x002e, 0x0804, 0x2dcc, 0x7924, 0xa18c,
- 0xff00, 0x810f, 0x00c6, 0x080c, 0x4c80, 0x2c08, 0x00ce, 0x1904,
- 0x2df4, 0x0804, 0x2dcc, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804,
- 0x2df1, 0x60d0, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005,
- 0x0804, 0x2df1, 0x080c, 0x3c05, 0x1120, 0x2009, 0x0002, 0x0804,
- 0x2df1, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c46,
- 0x701b, 0x39bb, 0x0005, 0x2009, 0x0080, 0x080c, 0x4cdc, 0x1130,
- 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, 0x400a,
- 0x0804, 0x2dce, 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c,
- 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, 0x3a32,
- 0xa0be, 0x0112, 0x0904, 0x3a32, 0xa0be, 0x0113, 0x0904, 0x3a32,
- 0xa0be, 0x0114, 0x0904, 0x3a32, 0xa0be, 0x0117, 0x0904, 0x3a32,
- 0xa0be, 0x011a, 0x0904, 0x3a32, 0xa0be, 0x011c, 0x0904, 0x3a32,
- 0xa0be, 0x0121, 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171,
- 0x05c8, 0xa0be, 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830,
- 0x8007, 0x6832, 0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213,
- 0x0528, 0xa0be, 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be,
- 0x021a, 0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300,
- 0x01c8, 0x00de, 0x0804, 0x2df4, 0xad80, 0x0010, 0x20a9, 0x0007,
- 0x080c, 0x3a78, 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x3a78,
- 0x0048, 0xad80, 0x000c, 0x080c, 0x3a86, 0x0050, 0xad80, 0x000e,
- 0x080c, 0x3a86, 0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, 0x3a78,
- 0x00c6, 0x080c, 0x3c05, 0x0568, 0x6838, 0xc0fd, 0x683a, 0x6837,
- 0x0119, 0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b,
- 0x697e, 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996,
- 0x689b, 0x0000, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd,
- 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0x96d3, 0x1120,
- 0x2009, 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3a6f,
- 0x0005, 0x00ce, 0x00de, 0x2009, 0x0002, 0x0804, 0x2df1, 0x6820,
- 0xa086, 0x8001, 0x1904, 0x2dcc, 0x2009, 0x0004, 0x0804, 0x2df1,
- 0x0016, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108,
- 0x280a, 0x8108, 0x1f04, 0x3a7a, 0x001e, 0x0005, 0x0016, 0x00a6,
- 0x00b6, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000,
- 0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a,
- 0x00be, 0x00ae, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001,
- 0x0804, 0x2df1, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d0,
- 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2df4, 0xa182, 0x00ff,
- 0x1a04, 0x2df4, 0x7a2c, 0x7b28, 0x606c, 0xa306, 0x1140, 0x6070,
- 0xa24e, 0x0904, 0x2df4, 0xa9cc, 0xff00, 0x0904, 0x2df4, 0x00c6,
- 0x080c, 0x3b58, 0x2c68, 0x00ce, 0x0538, 0xa0c6, 0x4000, 0x1180,
- 0x00c6, 0x0006, 0x2d60, 0x2009, 0x0000, 0x080c, 0x4f6e, 0x1108,
- 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x0088,
- 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118,
- 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001,
- 0x4006, 0x2020, 0x0804, 0x2dce, 0x2d00, 0x7022, 0x0016, 0x00b6,
- 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x8022, 0x05d8, 0x2d00, 0x601a,
- 0x080c, 0x9956, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x3c05,
- 0x00ce, 0x2b70, 0x1150, 0x080c, 0x8078, 0x00ee, 0x00ce, 0x00be,
- 0x001e, 0x2009, 0x0002, 0x0804, 0x2df1, 0x6837, 0x0000, 0x683b,
- 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c,
- 0x0108, 0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2ad9,
- 0x012e, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001,
- 0x0002, 0x080c, 0x4c30, 0x2009, 0x0002, 0x080c, 0x80a7, 0xa085,
- 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, 0x2009, 0x0003,
- 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3b3f, 0x0005, 0x6830,
- 0xa086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204,
- 0xa294, 0x00ff, 0x0804, 0x2df1, 0x2009, 0x0000, 0x080c, 0x4f6e,
- 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x2dcc,
- 0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001, 0xad34, 0x2004, 0xd0ac,
- 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xae34, 0x0030,
- 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xaeb4, 0x2e04, 0xa005,
- 0x1130, 0x2100, 0xa406, 0x1548, 0x2428, 0xc5fd, 0x0430, 0x2068,
- 0x6f10, 0x2700, 0xa306, 0x11b0, 0x6e14, 0x2600, 0xa206, 0x1190,
- 0x2400, 0xa106, 0x1160, 0x2d60, 0xd884, 0x0540, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x1510, 0x2001, 0x4000, 0x0400, 0x2001,
- 0x4007, 0x00e8, 0x2400, 0xa106, 0x1140, 0x6e14, 0x87ff, 0x1110,
- 0x86ff, 0x09d0, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04,
- 0x3b6e, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001,
- 0x0030, 0x080c, 0x4c80, 0x1dd0, 0x6312, 0x6216, 0xa006, 0xa005,
- 0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c05,
- 0x0904, 0x2df1, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7824,
- 0xa005, 0x0904, 0x2df4, 0xa096, 0x00ff, 0x0120, 0xa092, 0x0004,
- 0x1a04, 0x2df4, 0x2010, 0x2d18, 0x080c, 0x2a8c, 0x0904, 0x2df1,
- 0x7007, 0x0003, 0x701b, 0x3bd5, 0x0005, 0x6830, 0xa086, 0x0100,
- 0x0904, 0x2df1, 0x0804, 0x2dcc, 0x7924, 0xa18c, 0xff00, 0x810f,
- 0x60d0, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2df4, 0xa182,
- 0x00ff, 0x1a04, 0x2df4, 0x0126, 0x2091, 0x8000, 0x080c, 0x95c6,
- 0x1188, 0xa190, 0xae34, 0x2204, 0xa065, 0x0160, 0x080c, 0x493a,
- 0x2001, 0xad34, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, 0x012e,
- 0x0804, 0x2dcc, 0x012e, 0x0804, 0x2df1, 0x080c, 0x15d9, 0x0188,
- 0xa006, 0x6802, 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, 0x7016,
- 0x0030, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80,
- 0x000d, 0x0005, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4cdc,
- 0x1130, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, 0xa066,
- 0x8cff, 0x0005, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, 0x4cdc,
- 0x1128, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, 0x8cff,
- 0x0005, 0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c,
- 0x15f0, 0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001,
- 0x0010, 0x2031, 0x0000, 0x2061, 0xadd1, 0x6606, 0x6112, 0x600e,
- 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1624, 0x7007,
- 0x0002, 0x701b, 0x2dcc, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000,
- 0x2079, 0x0000, 0x2001, 0xad8f, 0x2004, 0xa005, 0x1168, 0x0e04,
- 0x3c74, 0x7818, 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, 0x781b,
- 0x0001, 0x2091, 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, 0x2071,
- 0xad81, 0x7138, 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, 0x0078,
- 0x7030, 0xa0e0, 0x0004, 0xac82, 0xadd1, 0x0210, 0x2061, 0xad91,
- 0x2c00, 0x7032, 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, 0x2262,
- 0x6306, 0x640a, 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, 0x0005,
- 0x00e6, 0x2071, 0xad81, 0x7038, 0xa005, 0x0570, 0x0126, 0x2091,
- 0x8000, 0x0e04, 0x3ccb, 0x00f6, 0x2079, 0x0000, 0x7818, 0xd084,
- 0x1508, 0x00c6, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826,
- 0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001,
- 0x703a, 0xa005, 0x1130, 0x7033, 0xad91, 0x7037, 0xad91, 0x00ce,
- 0x0048, 0xac80, 0x0004, 0xa0fa, 0xadd1, 0x0210, 0x2001, 0xad91,
- 0x7036, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, 0x2001,
- 0xad52, 0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x3c5c,
- 0x002e, 0x0005, 0x81ff, 0x1904, 0x2df1, 0x0126, 0x2091, 0x8000,
- 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x574f, 0x1178,
- 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001,
- 0xa085, 0x0001, 0x080c, 0x5793, 0x080c, 0x569a, 0x0010, 0x080c,
- 0x485e, 0x012e, 0x0804, 0x2dcc, 0x7824, 0x2008, 0xa18c, 0xfffd,
- 0x1128, 0x61dc, 0xa10d, 0x61de, 0x0804, 0x2dcc, 0x0804, 0x2df4,
- 0x81ff, 0x1904, 0x2df1, 0x6000, 0xa086, 0x0003, 0x1904, 0x2df1,
- 0x2001, 0xad52, 0x2004, 0xd0ac, 0x1904, 0x2df1, 0x080c, 0x3c2a,
- 0x0904, 0x2df4, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120,
- 0x7828, 0xa005, 0x0904, 0x2dcc, 0x00c6, 0x080c, 0x3c05, 0x00ce,
- 0x0904, 0x2df1, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd,
- 0x683a, 0x080c, 0x979c, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b,
- 0x3d3a, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2df1, 0x0804,
- 0x2dcc, 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1,
- 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c05, 0x0904,
- 0x2df1, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f,
- 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x080c, 0x4cdc, 0x1904,
- 0x3db4, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0130, 0xa0c4,
- 0xff00, 0xa8c6, 0x0600, 0x1904, 0x3db4, 0x2001, 0xad52, 0x2004,
- 0xd0ac, 0x1128, 0x080c, 0x4f6e, 0x1110, 0xd79c, 0x05e8, 0xd794,
- 0x1110, 0xd784, 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9,
- 0x0004, 0x53a3, 0x080c, 0x3a86, 0xd794, 0x0148, 0xac80, 0x000a,
- 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3a86, 0x21a2,
- 0xd794, 0x01d8, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002,
- 0x53a3, 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098,
- 0x3400, 0x20a9, 0x0002, 0x53a3, 0x080c, 0x3a78, 0xac80, 0x0026,
- 0x2098, 0x20a9, 0x0002, 0x53a3, 0x0008, 0x94a0, 0xd794, 0x0110,
- 0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0x2001, 0xad34, 0x2004,
- 0xd0ac, 0x0118, 0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186,
- 0x0100, 0x0170, 0x0018, 0xa186, 0x007e, 0x0150, 0xd794, 0x0118,
- 0xa686, 0x0020, 0x0010, 0xa686, 0x0028, 0x0150, 0x0804, 0x3d5d,
- 0x86ff, 0x1120, 0x7120, 0x810b, 0x0804, 0x2dcc, 0x702f, 0x0001,
- 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xadd1, 0x6007,
- 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532,
- 0x2c10, 0x080c, 0x1624, 0x7007, 0x0002, 0x701b, 0x3df0, 0x0005,
- 0x702c, 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031,
- 0x0000, 0x2061, 0xadd1, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804,
- 0x3d5d, 0x7120, 0x810b, 0x0804, 0x2dcc, 0x2029, 0x007e, 0x7924,
- 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020,
- 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa184, 0x00ff, 0xa0e2,
- 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa284, 0xff00,
- 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4,
- 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04,
- 0x2df4, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2df4,
- 0xa502, 0x0a04, 0x2df4, 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0a04,
- 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa484, 0xff00, 0x8007, 0xa0e2,
- 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa484, 0x00ff,
- 0xa0e2, 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0x2061,
- 0xafa6, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2dcc, 0x0006,
- 0x2001, 0xad52, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x2001,
- 0xad71, 0x2004, 0xd0bc, 0x000e, 0x0005, 0x6164, 0x7a24, 0x6300,
- 0x82ff, 0x1118, 0x7926, 0x0804, 0x2dcc, 0x83ff, 0x1904, 0x2df4,
- 0x2001, 0xfff0, 0xa200, 0x1a04, 0x2df4, 0x2019, 0xffff, 0x6068,
- 0xa302, 0xa200, 0x0a04, 0x2df4, 0x7926, 0x6266, 0x0804, 0x2dcc,
- 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, 0x7c28,
- 0x7d24, 0x7e38, 0x7f2c, 0x080c, 0x3c05, 0x0904, 0x2df1, 0x2009,
- 0x0000, 0x2019, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80,
- 0x0003, 0x7026, 0x20a0, 0xa1e0, 0xae34, 0x2c64, 0x8cff, 0x01b8,
- 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, 0xa084,
- 0xff00, 0xa086, 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, 0x6010,
- 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108,
- 0xa182, 0x00ff, 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, 0x83ff,
- 0x1120, 0x7120, 0x810c, 0x0804, 0x2dcc, 0x702f, 0x0001, 0x711e,
- 0x7020, 0xa300, 0x7022, 0x2061, 0xadd1, 0x6007, 0x0000, 0x6312,
- 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, 0x080c,
- 0x1624, 0x7007, 0x0002, 0x701b, 0x3ee6, 0x0005, 0x702c, 0xa005,
- 0x1168, 0x711c, 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xadd1,
- 0x6424, 0x6528, 0x662c, 0x6730, 0x0804, 0x3ea3, 0x7120, 0x810c,
- 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x60d0, 0xd0ac, 0x1118,
- 0xd09c, 0x0904, 0x2df1, 0x080c, 0x3c05, 0x0904, 0x2df1, 0x7924,
- 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c46, 0x701b, 0x3f11,
- 0x0005, 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, 0x0148,
- 0xa0be, 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, 0x0804,
- 0x2df4, 0x6820, 0x6924, 0x080c, 0x2676, 0x1510, 0x080c, 0x4c80,
- 0x11f8, 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, 0x3c05,
- 0x01b8, 0x080c, 0x3c05, 0x01a0, 0x00ce, 0x00de, 0x6837, 0x0000,
- 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c,
- 0x96ef, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3f4b, 0x0005,
- 0x00de, 0x0804, 0x2df1, 0x7120, 0x080c, 0x2bc9, 0x6820, 0xa086,
- 0x8001, 0x0904, 0x2df1, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002,
- 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x48be, 0x000e,
- 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xadd1,
- 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, 0x0018,
- 0xa7c6, 0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x2df4, 0x2009,
- 0x0004, 0x0804, 0x3c49, 0xa7c6, 0x7200, 0x1904, 0x2df4, 0xa6c2,
- 0x0054, 0x0a04, 0x2df4, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a,
- 0x642e, 0x6532, 0x2c10, 0x080c, 0x1624, 0x7007, 0x0002, 0x701b,
- 0x3f92, 0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004,
- 0xa080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c,
- 0x48be, 0x000e, 0x2009, 0x002a, 0x2061, 0xadd1, 0x6224, 0x6328,
- 0x642c, 0x6530, 0x0804, 0x3c49, 0x81ff, 0x1904, 0x2df1, 0x080c,
- 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4d96, 0x0904, 0x2df1, 0x080c,
- 0x4ec6, 0x0804, 0x2dcc, 0x7824, 0xd084, 0x0904, 0x3804, 0x080c,
- 0x3c2a, 0x0904, 0x2df4, 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x1120,
- 0x2009, 0x0002, 0x0804, 0x2df1, 0x6004, 0xa084, 0x00ff, 0xa086,
- 0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa08e, 0x0005, 0x1508,
- 0x2001, 0xad52, 0x2004, 0xd0b4, 0x0904, 0x3834, 0x6000, 0xd08c,
- 0x1904, 0x3834, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c,
- 0x970b, 0x1120, 0x2009, 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003,
- 0x701b, 0x3ff3, 0x0005, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x0804,
- 0x3834, 0x2009, 0xad30, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001,
- 0x0804, 0x2df1, 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x0120,
- 0x2009, 0x0007, 0x0804, 0x2df1, 0x2001, 0xad52, 0x2004, 0xd0ac,
- 0x0120, 0x2009, 0x0008, 0x0804, 0x2df1, 0x609c, 0xd0a4, 0x1118,
- 0xd0ac, 0x1904, 0x3834, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838,
- 0xc0fd, 0x683a, 0x080c, 0x979c, 0x1120, 0x2009, 0x0003, 0x0804,
- 0x2df1, 0x7007, 0x0003, 0x701b, 0x402e, 0x0005, 0x6830, 0xa086,
- 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x2df1, 0x080c, 0x3c2a,
- 0x0904, 0x2df4, 0x0804, 0x3fd8, 0x81ff, 0x2009, 0x0001, 0x1904,
- 0x2df1, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, 0x2df1,
- 0x2001, 0xad52, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, 0x2df1,
- 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x6004, 0xa084, 0x00ff, 0xa086,
- 0x0006, 0x2009, 0x0009, 0x1904, 0x2df1, 0x00c6, 0x080c, 0x3c05,
- 0x00ce, 0x2009, 0x0002, 0x0904, 0x2df1, 0x6837, 0x0000, 0x6833,
- 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, 0xa18c,
- 0x00ff, 0xa006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, 0x6956,
- 0x0048, 0xa28e, 0x0100, 0x1904, 0x2df4, 0xc0e5, 0x6853, 0x0000,
- 0x6857, 0x0000, 0x683e, 0x080c, 0x9957, 0x2009, 0x0003, 0x0904,
- 0x2df1, 0x7007, 0x0003, 0x701b, 0x408e, 0x0005, 0x6830, 0xa086,
- 0x0100, 0x2009, 0x0004, 0x0904, 0x2df1, 0x0804, 0x2dcc, 0x81ff,
- 0x2009, 0x0001, 0x1904, 0x2df1, 0x6000, 0xa086, 0x0003, 0x2009,
- 0x0007, 0x1904, 0x2df1, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x6004,
- 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x2df1,
- 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2df1,
- 0xad80, 0x000f, 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
- 0x080c, 0x3c46, 0x701b, 0x40c5, 0x0005, 0x00d6, 0xade8, 0x000f,
- 0x6800, 0xa086, 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, 0x6808,
- 0xa084, 0xff00, 0x1108, 0x0018, 0x00de, 0x1904, 0x2df4, 0x00de,
- 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x00c6,
- 0x080c, 0x3c2a, 0x1118, 0x00ce, 0x0804, 0x2df4, 0x080c, 0x99a6,
- 0x2009, 0x0003, 0x00ce, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b,
- 0x40f2, 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0904,
- 0x2df1, 0x0804, 0x2dcc, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804,
- 0x2df1, 0x6000, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804,
- 0x2df1, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, 0x080c,
- 0x4cdc, 0x1904, 0x2df4, 0xa186, 0x007f, 0x0150, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, 0x2df1,
- 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804,
- 0x2df1, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9726,
- 0x1120, 0x2009, 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b,
- 0x413a, 0x0005, 0x6808, 0x8007, 0xa086, 0x0100, 0x1120, 0x2009,
- 0x0004, 0x0804, 0x2df1, 0x68b0, 0x6836, 0x6810, 0x8007, 0xa084,
- 0x00ff, 0x808e, 0x6814, 0x8007, 0xa084, 0x00ff, 0x8086, 0xa080,
- 0x0002, 0xa108, 0xad80, 0x0004, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
- 0x0804, 0x3c49, 0x080c, 0x3c05, 0x1120, 0x2009, 0x0002, 0x0804,
- 0x2df1, 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff,
- 0x0110, 0x0804, 0x2df4, 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c,
- 0x7d38, 0x080c, 0x3c46, 0x701b, 0x4176, 0x0005, 0xad80, 0x000d,
- 0x2098, 0x20a9, 0x001a, 0x20a1, 0xafad, 0x53a3, 0x0804, 0x2dcc,
- 0x080c, 0x3c05, 0x1120, 0x2009, 0x0002, 0x0804, 0x2df1, 0x7924,
- 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804,
- 0x2df4, 0x2099, 0xafad, 0x20a0, 0x20a9, 0x001a, 0x53a3, 0x2009,
- 0x001a, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, 0x7824,
- 0xa08a, 0x1000, 0x1a04, 0x2df4, 0x0126, 0x2091, 0x8000, 0x8003,
- 0x800b, 0x810b, 0xa108, 0x00c6, 0x2061, 0xafda, 0x6142, 0x00ce,
- 0x012e, 0x0804, 0x2dcc, 0x00c6, 0x080c, 0x574f, 0x1188, 0x2001,
- 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0xa085,
- 0x0001, 0x080c, 0x5793, 0x080c, 0x569a, 0x080c, 0x14f6, 0x0038,
- 0x2061, 0xad00, 0x6030, 0xc09d, 0x6032, 0x080c, 0x485e, 0x00ce,
- 0x0005, 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00,
- 0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, 0x4348, 0x0068,
- 0xd08c, 0x0118, 0x080c, 0x4269, 0x0040, 0xd094, 0x0118, 0x080c,
- 0x423a, 0x0018, 0xd09c, 0x0108, 0x0061, 0x00ee, 0x00ce, 0x012e,
- 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e,
- 0x0ca0, 0x624c, 0xa286, 0xf0f0, 0x1150, 0x6048, 0xa086, 0xf0f0,
- 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0xa294,
- 0xff00, 0xa296, 0xf700, 0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240,
- 0xa295, 0x0100, 0x6242, 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7,
- 0x080c, 0x48de, 0x00f0, 0x6040, 0xa084, 0x0010, 0xa085, 0x0040,
- 0x6042, 0x6043, 0x0000, 0x7077, 0x0000, 0x7093, 0x0001, 0x70b7,
- 0x0000, 0x70d3, 0x0000, 0x2009, 0xb3c0, 0x200b, 0x0000, 0x7087,
- 0x0000, 0x707b, 0x000a, 0x2009, 0x000a, 0x2011, 0x4814, 0x080c,
- 0x6593, 0x0005, 0x0156, 0x2001, 0xad73, 0x2004, 0xd08c, 0x0110,
- 0x704f, 0xffff, 0x7078, 0xa005, 0x1510, 0x2011, 0x4814, 0x080c,
- 0x650d, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9,
- 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x4251, 0x6242, 0x708b,
- 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242,
- 0x0030, 0x6242, 0x708b, 0x0000, 0x707f, 0x0000, 0x0000, 0x015e,
- 0x0005, 0x707c, 0xa08a, 0x0003, 0x1210, 0x0023, 0x0010, 0x080c,
- 0x14f6, 0x0005, 0x4275, 0x42c5, 0x4347, 0x00f6, 0x707f, 0x0001,
- 0x20e1, 0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, 0x22f8, 0x20e1,
- 0x9080, 0x20e1, 0x4000, 0x2079, 0xb200, 0x207b, 0x2200, 0x7807,
- 0x00ef, 0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817,
- 0x0000, 0x781b, 0x0000, 0x781f, 0x0000, 0x7823, 0xffff, 0x7827,
- 0xffff, 0x782b, 0x0000, 0x782f, 0x0000, 0x2079, 0xb20c, 0x207b,
- 0x1101, 0x7807, 0x0000, 0x2099, 0xad05, 0x20a1, 0xb20e, 0x20a9,
- 0x0004, 0x53a3, 0x2079, 0xb212, 0x207b, 0x0000, 0x7807, 0x0000,
- 0x2099, 0xb200, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3,
- 0x000c, 0x600f, 0x0000, 0x080c, 0x4845, 0x00fe, 0x7083, 0x0000,
- 0x6043, 0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, 0x7080, 0x7083,
- 0x0000, 0xa025, 0x0904, 0x432f, 0x6020, 0xd0b4, 0x1904, 0x432d,
- 0x7190, 0x81ff, 0x0904, 0x431d, 0xa486, 0x000c, 0x1904, 0x4328,
- 0xa480, 0x0018, 0x8004, 0x20a8, 0x2011, 0xb280, 0x2019, 0xb200,
- 0x220c, 0x2304, 0xa106, 0x11b8, 0x8210, 0x8318, 0x1f04, 0x42e0,
- 0x6043, 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006,
- 0x707f, 0x0002, 0x708b, 0x0002, 0x2009, 0x07d0, 0x2011, 0x481b,
- 0x080c, 0x6593, 0x0490, 0x2069, 0xb280, 0x6930, 0xa18e, 0x1101,
- 0x1538, 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, 0x00ff, 0x1118,
- 0x6804, 0xa005, 0x0190, 0x2011, 0xb28e, 0x2019, 0xad05, 0x20a9,
- 0x0004, 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, 0x8210, 0x8318,
- 0x1f04, 0x4311, 0x0068, 0x7093, 0x0000, 0x20e1, 0x9080, 0x20e1,
- 0x4000, 0x2099, 0xb280, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6,
- 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00de, 0x0005, 0x6040,
- 0xa085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c,
- 0x2011, 0xafd1, 0x2013, 0x0000, 0x7083, 0x0000, 0x20e1, 0x9080,
- 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x782b, 0x0c30, 0x0005,
- 0x7088, 0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, 0x080c, 0x14f6,
- 0x0005, 0x437b, 0x438a, 0x43b2, 0x43cb, 0x43ef, 0x4417, 0x443b,
- 0x446c, 0x4490, 0x44b8, 0x44ef, 0x4517, 0x4533, 0x4549, 0x4569,
- 0x457c, 0x4584, 0x45b1, 0x45d5, 0x45fd, 0x4621, 0x4652, 0x468f,
- 0x46be, 0x46da, 0x4719, 0x4739, 0x4752, 0x4753, 0x00c6, 0x2061,
- 0xad00, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9,
- 0x6006, 0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043,
- 0x0002, 0x708b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x481b, 0x080c,
- 0x6593, 0x0005, 0x00f6, 0x7080, 0xa086, 0x0014, 0x1508, 0x6043,
- 0x0000, 0x6020, 0xd0b4, 0x11e0, 0x2079, 0xb280, 0x7a30, 0xa296,
- 0x1102, 0x11a0, 0x7834, 0xa005, 0x1188, 0x7a38, 0xd2fc, 0x0128,
- 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x2011, 0x481b, 0x080c,
- 0x650d, 0x708b, 0x0010, 0x080c, 0x4584, 0x0010, 0x080c, 0x485e,
- 0x00fe, 0x0005, 0x708b, 0x0003, 0x6043, 0x0004, 0x2011, 0x481b,
- 0x080c, 0x650d, 0x080c, 0x48c6, 0x20a3, 0x1102, 0x20a3, 0x0000,
- 0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x43c2, 0x60c3, 0x0014,
- 0x080c, 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01f0, 0x2011,
- 0x481b, 0x080c, 0x650d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xb280,
- 0x7a30, 0xa296, 0x1102, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38,
- 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x708b,
- 0x0004, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x708b,
- 0x0005, 0x080c, 0x48c6, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430,
- 0x2011, 0xb28e, 0x080c, 0x4917, 0x1160, 0x7074, 0xa005, 0x1148,
- 0x714c, 0xa186, 0xffff, 0x0128, 0x080c, 0x47df, 0x0110, 0x080c,
- 0x48f5, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4845, 0x0005, 0x00f6,
- 0x7080, 0xa005, 0x01f0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086,
- 0x0014, 0x11a8, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1103, 0x1178,
- 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005,
- 0x1110, 0x70b7, 0x0001, 0x708b, 0x0006, 0x0029, 0x0010, 0x080c,
- 0x485e, 0x00fe, 0x0005, 0x708b, 0x0007, 0x080c, 0x48c6, 0x20a3,
- 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xb28e, 0x080c, 0x4917,
- 0x11a8, 0x7074, 0xa005, 0x1190, 0x7154, 0xa186, 0xffff, 0x0170,
- 0xa180, 0x2be6, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x47df,
- 0x0128, 0x080c, 0x3e66, 0x0110, 0x080c, 0x26c0, 0x20a9, 0x0008,
- 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
- 0x0014, 0x080c, 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01f0,
- 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, 0x0014, 0x11a8, 0x2079,
- 0xb280, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160,
- 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001,
- 0x708b, 0x0008, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005,
- 0x708b, 0x0009, 0x080c, 0x48c6, 0x20a3, 0x1105, 0x20a3, 0x0100,
- 0x3430, 0x080c, 0x4917, 0x1150, 0x7074, 0xa005, 0x1138, 0x080c,
- 0x4754, 0x1170, 0xa085, 0x0001, 0x080c, 0x26c0, 0x20a9, 0x0008,
- 0x2099, 0xb28e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x60c3, 0x0014, 0x080c, 0x4845, 0x0010, 0x080c, 0x436e, 0x0005,
- 0x00f6, 0x7080, 0xa005, 0x0588, 0x2011, 0x481b, 0x080c, 0x650d,
- 0xa086, 0x0014, 0x1540, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1105,
- 0x1510, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1160, 0x7a38, 0xd2fc,
- 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x708b, 0x000a,
- 0x00b1, 0x0098, 0xa005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70b4,
- 0xa005, 0x1110, 0x70b7, 0x0001, 0x7087, 0x0000, 0x708b, 0x000e,
- 0x080c, 0x4569, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x708b,
- 0x000b, 0x2011, 0xb20e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff,
- 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, 0x080c, 0x48c6,
- 0x20a3, 0x1106, 0x20a3, 0x0000, 0x080c, 0x4917, 0x0118, 0x2013,
- 0x0000, 0x0020, 0x7050, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9,
- 0x0042, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4845, 0x0005, 0x00f6,
- 0x7080, 0xa005, 0x01b0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086,
- 0x0084, 0x1168, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1106, 0x1138,
- 0x7834, 0xa005, 0x1120, 0x708b, 0x000c, 0x0029, 0x0010, 0x080c,
- 0x485e, 0x00fe, 0x0005, 0x708b, 0x000d, 0x080c, 0x48c6, 0x20a3,
- 0x1107, 0x20a3, 0x0000, 0x2099, 0xb28e, 0x20a9, 0x0040, 0x53a6,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4845,
- 0x0005, 0x00f6, 0x7080, 0xa005, 0x01d0, 0x2011, 0x481b, 0x080c,
- 0x650d, 0xa086, 0x0084, 0x1188, 0x2079, 0xb280, 0x7a30, 0xa296,
- 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c,
- 0x48b8, 0x708b, 0x000e, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe,
- 0x0005, 0x708b, 0x000f, 0x7083, 0x0000, 0x608b, 0xbc85, 0x608f,
- 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011,
- 0x481b, 0x080c, 0x6501, 0x0005, 0x7080, 0xa005, 0x0120, 0x2011,
- 0x481b, 0x080c, 0x650d, 0x0005, 0x708b, 0x0011, 0x080c, 0x4917,
- 0x1188, 0x716c, 0x81ff, 0x0170, 0x2009, 0x0000, 0x7070, 0xa084,
- 0x00ff, 0x080c, 0x2676, 0xa186, 0x0080, 0x0120, 0x2011, 0xb28e,
- 0x080c, 0x47df, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xb280,
- 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084,
- 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x080c, 0x4845,
- 0x0005, 0x00f6, 0x7080, 0xa005, 0x01f0, 0x2011, 0x481b, 0x080c,
- 0x650d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xb280, 0x7a30, 0xa296,
- 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128,
- 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x708b, 0x0012, 0x0029,
- 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x708b, 0x0013, 0x080c,
- 0x48d2, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xb28e,
- 0x080c, 0x4917, 0x1160, 0x7074, 0xa005, 0x1148, 0x714c, 0xa186,
- 0xffff, 0x0128, 0x080c, 0x47df, 0x0110, 0x080c, 0x48f5, 0x20a9,
- 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x60c3, 0x0014, 0x080c, 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005,
- 0x01f0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, 0x0014, 0x11a8,
- 0x2079, 0xb280, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005,
- 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7,
- 0x0001, 0x708b, 0x0014, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe,
- 0x0005, 0x708b, 0x0015, 0x080c, 0x48d2, 0x20a3, 0x1104, 0x20a3,
- 0x0000, 0x3430, 0x2011, 0xb28e, 0x080c, 0x4917, 0x11a8, 0x7074,
- 0xa005, 0x1190, 0x7154, 0xa186, 0xffff, 0x0170, 0xa180, 0x2be6,
- 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x47df, 0x0128, 0x080c,
- 0x3e66, 0x0110, 0x080c, 0x26c0, 0x20a9, 0x0008, 0x2298, 0x26a0,
- 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c,
- 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, 0x05b8, 0x2011, 0x481b,
- 0x080c, 0x650d, 0xa086, 0x0014, 0x1570, 0x2079, 0xb280, 0x7a30,
- 0xa296, 0x1105, 0x1540, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1148,
- 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001,
- 0x0060, 0xa005, 0x11c0, 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005,
- 0x1110, 0x70b7, 0x0001, 0x7087, 0x0000, 0x7a38, 0xd2f4, 0x0138,
- 0x2001, 0xad73, 0x2004, 0xd0a4, 0x1110, 0x70d3, 0x0008, 0x708b,
- 0x0016, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x20e1,
- 0x9080, 0x20e1, 0x4000, 0x2099, 0xb280, 0x20a1, 0x020b, 0x20a9,
- 0x000e, 0x53a6, 0x3430, 0x2011, 0xb28e, 0x708b, 0x0017, 0x080c,
- 0x4917, 0x1150, 0x7074, 0xa005, 0x1138, 0x080c, 0x4754, 0x1170,
- 0xa085, 0x0001, 0x080c, 0x26c0, 0x20a9, 0x0008, 0x2099, 0xb28e,
- 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
- 0x080c, 0x4845, 0x0010, 0x080c, 0x436e, 0x0005, 0x00f6, 0x7080,
- 0xa005, 0x01b0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, 0x0084,
- 0x1168, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834,
- 0xa005, 0x1120, 0x708b, 0x0018, 0x0029, 0x0010, 0x080c, 0x485e,
- 0x00fe, 0x0005, 0x708b, 0x0019, 0x080c, 0x48d2, 0x20a3, 0x1106,
- 0x20a3, 0x0000, 0x3430, 0x2099, 0xb28e, 0x2039, 0xb20e, 0x27a0,
- 0x20a9, 0x0040, 0x53a3, 0x080c, 0x4917, 0x11e8, 0x2728, 0x2514,
- 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007,
- 0xa205, 0x202a, 0x7050, 0x2310, 0x8214, 0xa2a0, 0xb20e, 0x2414,
- 0xa38c, 0x0001, 0x0118, 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff,
- 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4845,
- 0x0005, 0x00f6, 0x7080, 0xa005, 0x01d0, 0x2011, 0x481b, 0x080c,
- 0x650d, 0xa086, 0x0084, 0x1188, 0x2079, 0xb280, 0x7a30, 0xa296,
- 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c,
- 0x48b8, 0x708b, 0x001a, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe,
- 0x0005, 0x708b, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099,
- 0xb280, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007,
- 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c,
- 0x4845, 0x0005, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0xad52,
- 0x252c, 0x20a9, 0x0008, 0x2041, 0xb20e, 0x28a0, 0x2099, 0xb28e,
- 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011,
- 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4,
- 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x4769, 0x0804, 0x47d7,
- 0x82ff, 0x1160, 0xd5d4, 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020,
- 0xa1a6, 0x3fff, 0x0904, 0x47d7, 0xa18d, 0xc000, 0x20a9, 0x0010,
- 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4,
- 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319,
- 0x0008, 0x8318, 0x1f04, 0x478f, 0x04d0, 0x23a8, 0x2021, 0x0001,
- 0x8426, 0x8425, 0x1f04, 0x47a1, 0x2328, 0x8529, 0xa2be, 0x0007,
- 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8,
- 0xa5a8, 0x0010, 0x1f04, 0x47b0, 0x754e, 0xa5c8, 0x2be6, 0x292d,
- 0xa5ac, 0x00ff, 0x7572, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c,
- 0x26a0, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405,
- 0x201a, 0x7077, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, 0x0028, 0xa006,
- 0x0018, 0xa006, 0x080c, 0x14f6, 0x009e, 0x008e, 0x0005, 0x2118,
- 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, 0x0218, 0x8420,
- 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421,
- 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8,
- 0xa238, 0x2704, 0xa42c, 0x11b8, 0xa405, 0x203a, 0x714e, 0xa1a0,
- 0x2be6, 0x242d, 0xa5ac, 0x00ff, 0x7572, 0x6532, 0x6536, 0x0016,
- 0x2508, 0x080c, 0x26a0, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7077,
- 0x0001, 0xa084, 0x0000, 0x0005, 0x00e6, 0x2071, 0xad00, 0x707b,
- 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071,
- 0x0140, 0x080c, 0x7834, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003,
- 0x1000, 0x7003, 0x0000, 0x0126, 0x2091, 0x8000, 0x2071, 0xad22,
- 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c,
- 0x48de, 0x001e, 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42,
- 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000,
- 0x2011, 0xafd1, 0x2013, 0x0000, 0x7083, 0x0000, 0x012e, 0x20e1,
- 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x782b, 0x2009,
- 0x07d0, 0x2011, 0x481b, 0x080c, 0x6593, 0x0005, 0x0016, 0x0026,
- 0x00c6, 0x0126, 0x2091, 0x8000, 0x2009, 0x00f7, 0x080c, 0x48de,
- 0x2061, 0xafda, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0xad00,
- 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010,
- 0x2009, 0x002d, 0x2011, 0x4883, 0x080c, 0x6501, 0x012e, 0x00ce,
- 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000,
- 0x2071, 0x0100, 0x080c, 0x7834, 0x2071, 0x0140, 0x7004, 0xa084,
- 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x080c, 0x5757,
- 0x01a8, 0x080c, 0x5775, 0x1190, 0x2001, 0xaf9d, 0x2003, 0xaaaa,
- 0x0016, 0x080c, 0x2744, 0x2001, 0xaf8e, 0x2102, 0x001e, 0x2001,
- 0xaf9e, 0x2003, 0x0000, 0x080c, 0x569a, 0x0030, 0x2001, 0x0001,
- 0x080c, 0x261e, 0x080c, 0x485e, 0x012e, 0x000e, 0x00ee, 0x0005,
- 0x20a9, 0x0040, 0x20a1, 0xb3c0, 0x2099, 0xb28e, 0x3304, 0x8007,
- 0x20a2, 0x9398, 0x94a0, 0x1f04, 0x48be, 0x0005, 0x20e1, 0x9080,
- 0x20e1, 0x4000, 0x2099, 0xb200, 0x20a1, 0x020b, 0x20a9, 0x000c,
- 0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xb280,
- 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x00c6, 0x0006,
- 0x2061, 0x0100, 0x810f, 0x2001, 0xad30, 0x2004, 0xa005, 0x1138,
- 0x2001, 0xad14, 0x2004, 0xa084, 0x00ff, 0xa105, 0x0010, 0xa185,
- 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, 0x2001,
- 0xad52, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a,
- 0x080c, 0xa96c, 0x2001, 0xad0c, 0x200c, 0xc195, 0x2102, 0x2019,
- 0x002a, 0x2009, 0x0000, 0x080c, 0x2aac, 0x004e, 0x001e, 0x0005,
- 0x080c, 0x485e, 0x708b, 0x0000, 0x7083, 0x0000, 0x0005, 0x0006,
- 0x2001, 0xad0c, 0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006,
- 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d,
- 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, 0x0005, 0x0156, 0x20a9,
- 0x00ff, 0x2009, 0xae34, 0xa006, 0x200a, 0x8108, 0x1f04, 0x4934,
- 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069,
- 0xad51, 0xa006, 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012,
- 0xa198, 0x2be6, 0x231d, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004,
- 0xac98, 0x0006, 0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a,
- 0x23a0, 0x40a4, 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a,
- 0x605e, 0x6062, 0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a,
- 0x607e, 0x6082, 0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a,
- 0x609e, 0x60ae, 0x61a2, 0x00d6, 0x60a4, 0xa06d, 0x0110, 0x080c,
- 0x15f0, 0x60a7, 0x0000, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x15f0,
- 0x60ab, 0x0000, 0x00de, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c,
- 0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x014e, 0x013e, 0x015e,
- 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0x6944, 0x6e48,
- 0xa684, 0x3fff, 0xa082, 0x4000, 0x1a04, 0x4a49, 0xa18c, 0xff00,
- 0x810f, 0xa182, 0x00ff, 0x1a04, 0x4a4e, 0x2001, 0xad0c, 0x2004,
- 0xa084, 0x0003, 0x01c0, 0x2001, 0xad0c, 0x2004, 0xd084, 0x1904,
- 0x4a31, 0xa188, 0xae34, 0x2104, 0xa065, 0x0904, 0x4a31, 0x6004,
- 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, 0x4a31, 0x6000, 0xd0c4,
- 0x0904, 0x4a31, 0x0068, 0xa188, 0xae34, 0x2104, 0xa065, 0x0904,
- 0x4a15, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, 0x4a1a,
- 0x60a4, 0xa00d, 0x0118, 0x080c, 0x4ef9, 0x05d0, 0x60a8, 0xa00d,
- 0x0188, 0x080c, 0x4f43, 0x1170, 0x694c, 0xd1fc, 0x1118, 0x080c,
- 0x4c11, 0x0448, 0x080c, 0x4bd3, 0x694c, 0xd1ec, 0x1520, 0x080c,
- 0x4ded, 0x0408, 0x694c, 0xa184, 0xa000, 0x0178, 0xd1ec, 0x0140,
- 0xd1fc, 0x0118, 0x080c, 0x4dfc, 0x0028, 0x080c, 0x4dfc, 0x0028,
- 0xd1fc, 0x0118, 0x080c, 0x4bd3, 0x0070, 0x6050, 0xa00d, 0x0130,
- 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0028, 0x2d00, 0x6052,
- 0x604e, 0x6803, 0x0000, 0x080c, 0x67c5, 0xa006, 0x012e, 0x0005,
- 0x2001, 0x0005, 0x2009, 0x0000, 0x04e8, 0x2001, 0x0028, 0x2009,
- 0x0000, 0x04c0, 0xa082, 0x0006, 0x12a0, 0x2001, 0xad34, 0x2004,
- 0xd0ac, 0x1160, 0x60a0, 0xd0bc, 0x1148, 0x6100, 0xd1fc, 0x0904,
- 0x49d0, 0x2001, 0x0029, 0x2009, 0x1000, 0x0420, 0x2001, 0x0028,
- 0x00a8, 0x2009, 0xad0c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004,
- 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, 0x2001, 0x0029,
- 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0060, 0x2009, 0x0000,
- 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, 0x0020, 0x2001, 0x0029,
- 0x2009, 0x0000, 0xa005, 0x012e, 0x0005, 0x00e6, 0x0126, 0x2091,
- 0x8000, 0x6844, 0x8007, 0xa084, 0x00ff, 0x2008, 0xa182, 0x00ff,
- 0x1a04, 0x4aa8, 0xa188, 0xae34, 0x2104, 0xa065, 0x01c0, 0x6004,
- 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11a8, 0x2c70, 0x080c, 0x8022,
- 0x05e8, 0x2e00, 0x601a, 0x2d00, 0x6012, 0x600b, 0xffff, 0x601f,
- 0x000a, 0x2009, 0x0003, 0x080c, 0x80a7, 0xa006, 0x0460, 0x2001,
- 0x0028, 0x0440, 0xa082, 0x0006, 0x1298, 0x2001, 0xad34, 0x2004,
- 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, 0x09e8,
- 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090,
- 0x2009, 0xad0c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050,
- 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, 0x0010,
- 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c,
- 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2011, 0x0000,
- 0x2079, 0xad00, 0x6944, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff,
- 0x1a04, 0x4b77, 0x2001, 0xad0c, 0x2004, 0xa084, 0x0003, 0x1904,
- 0x4b65, 0x080c, 0x4cdc, 0x1180, 0x6004, 0xa084, 0x00ff, 0xa082,
- 0x0006, 0x1250, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1904, 0x4b60,
- 0x60a0, 0xd0bc, 0x1904, 0x4b60, 0x6864, 0xa0c6, 0x006f, 0x0118,
- 0x2008, 0x0804, 0x4b28, 0x6968, 0x2140, 0xa18c, 0xff00, 0x810f,
- 0x78d0, 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, 0xa182, 0x00ff,
- 0x16b8, 0x6a70, 0x6b6c, 0x786c, 0xa306, 0x1160, 0x7870, 0xa24e,
- 0x1118, 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, 0x1118, 0x2208,
- 0x2310, 0x0430, 0x080c, 0x3b58, 0x2c70, 0x0550, 0x2009, 0x0000,
- 0x2011, 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, 0x2e60, 0x080c,
- 0x4f6e, 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, 0xc18d, 0x000e,
- 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008,
- 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010,
- 0x2001, 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, 0x0030, 0x0458,
- 0x080c, 0x8022, 0x1138, 0x2001, 0x4005, 0x2009, 0x0003, 0x2011,
- 0x0000, 0x0c80, 0x2e00, 0x601a, 0x080c, 0x9956, 0x2d00, 0x6012,
- 0x601f, 0x0001, 0xa006, 0xd88c, 0x0110, 0x2001, 0x4000, 0x683a,
- 0x0126, 0x2091, 0x8000, 0x080c, 0x2ad9, 0x012e, 0x2001, 0x0000,
- 0x080c, 0x4c1e, 0x2001, 0x0002, 0x080c, 0x4c30, 0x2009, 0x0002,
- 0x080c, 0x80a7, 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, 0x0005,
- 0x2001, 0x0028, 0x2009, 0x0000, 0x0cb0, 0x2009, 0xad0c, 0x210c,
- 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001,
- 0x0004, 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, 0x2001,
- 0x0029, 0x2009, 0x0000, 0x08f8, 0x6944, 0x6e48, 0xa684, 0x3fff,
- 0xa082, 0x4000, 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff,
- 0x12e0, 0xa188, 0xae34, 0x2104, 0xa065, 0x01b8, 0x6004, 0xa084,
- 0x00ff, 0xa08e, 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, 0x080c,
- 0x4dfc, 0x04c9, 0x0030, 0x04b9, 0x684c, 0xd0fc, 0x0110, 0x080c,
- 0x4ded, 0x080c, 0x4e3a, 0xa006, 0x00c8, 0x2001, 0x0028, 0x2009,
- 0x0000, 0x00a0, 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, 0x0d20,
- 0x2001, 0x0029, 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, 0x2009,
- 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x0005,
- 0x0126, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00, 0x200a,
- 0x6803, 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e,
- 0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0xa005,
- 0x0170, 0x00e6, 0x2071, 0xafc7, 0x7004, 0xa086, 0x0002, 0x0168,
- 0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00,
- 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06, 0x1d80,
- 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e,
- 0x0005, 0x0126, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0130, 0x6800,
- 0xa005, 0x1108, 0x6052, 0x604e, 0xad05, 0x012e, 0x0005, 0x604c,
- 0xa06d, 0x0130, 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05,
- 0x0005, 0x6803, 0x0000, 0x6084, 0xa00d, 0x0120, 0x2d00, 0x200a,
- 0x6086, 0x0005, 0x2d00, 0x6086, 0x6082, 0x0cd8, 0x0126, 0x00c6,
- 0x0026, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0110,
- 0xc285, 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, 0x0005,
- 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006,
- 0xa086, 0x0006, 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, 0xad52,
- 0x2004, 0xd0a4, 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, 0x0007,
- 0x1110, 0x2011, 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, 0x6206,
- 0x0006, 0xa086, 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, 0x080c,
- 0x14f6, 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091,
- 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, 0x1178,
- 0x609c, 0xd0a4, 0x0160, 0x2001, 0xad52, 0x2004, 0xd0ac, 0x1138,
- 0xa284, 0x00ff, 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e,
- 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005,
- 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190,
- 0xae34, 0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x15c0,
- 0x2d60, 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000,
- 0x60ab, 0x0000, 0x080c, 0x493a, 0xa006, 0x002e, 0x0005, 0x0126,
- 0x2091, 0x8000, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001,
- 0x0480, 0x00d6, 0xa190, 0xae34, 0x2204, 0xa06d, 0x0540, 0x2013,
- 0x0000, 0x00d6, 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, 0x080c,
- 0x15f0, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x15f0, 0x00ce, 0x00de,
- 0x00d6, 0x00c6, 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006,
- 0x6010, 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0x1600, 0x080c,
- 0x8078, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x15f0, 0x00de,
- 0xa006, 0x002e, 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218,
- 0xa085, 0x0001, 0x0030, 0xa188, 0xae34, 0x2104, 0xa065, 0x0dc0,
- 0xa006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b,
- 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x574f,
- 0x1538, 0x60a0, 0xa086, 0x007e, 0x2069, 0xb290, 0x0130, 0x2001,
- 0xad34, 0x2004, 0xd0ac, 0x11e0, 0x0098, 0x2d04, 0xd0e4, 0x01c0,
- 0x00d6, 0x2069, 0xb28e, 0x00c6, 0x2061, 0xaf9f, 0x6810, 0x2062,
- 0x6814, 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de,
- 0x8d69, 0x2d04, 0x2069, 0x0140, 0x6886, 0x2069, 0xad00, 0x68a2,
- 0x2069, 0xb28e, 0x6808, 0x605e, 0x6810, 0x6062, 0x6138, 0xa10a,
- 0x0208, 0x603a, 0x6814, 0x6066, 0x2099, 0xb296, 0xac88, 0x000a,
- 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xb29a, 0xac88, 0x0006,
- 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xb2ae, 0x6808, 0x606a,
- 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, 0xa182, 0x0211,
- 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009,
- 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0,
- 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421,
- 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009,
- 0x0003, 0x0010, 0x2009, 0x0002, 0x6192, 0x014e, 0x013e, 0x015e,
- 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0xb28d, 0x2e04,
- 0x6896, 0x2071, 0xb28e, 0x7004, 0x689a, 0x701c, 0x689e, 0x6a00,
- 0x2009, 0xad71, 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad,
- 0x0008, 0xc2ac, 0xd0c4, 0x0120, 0xd1e4, 0x0110, 0xc2bd, 0x0008,
- 0xc2bc, 0x6a02, 0x00ee, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0126,
- 0x2091, 0x8000, 0x60a4, 0xa06d, 0x01c0, 0x6900, 0x81ff, 0x1540,
- 0x6a04, 0xa282, 0x0010, 0x1648, 0xad88, 0x0004, 0x20a9, 0x0010,
- 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x4da8, 0x080c,
- 0x14f6, 0x260a, 0x8210, 0x6a06, 0x0098, 0x080c, 0x15d9, 0x01a8,
- 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010,
- 0x200b, 0xffff, 0x8108, 0x1f04, 0x4dc0, 0x6807, 0x0001, 0x6e12,
- 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126,
- 0x2091, 0x8000, 0x00d6, 0x60a4, 0xa00d, 0x01a0, 0x2168, 0x6800,
- 0xa005, 0x1160, 0x080c, 0x4ef9, 0x1168, 0x200b, 0xffff, 0x6804,
- 0xa08a, 0x0002, 0x0218, 0x8001, 0x6806, 0x0020, 0x080c, 0x15f0,
- 0x60a7, 0x0000, 0x00de, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000,
- 0x080c, 0x4f56, 0x0010, 0x080c, 0x4bc0, 0x080c, 0x4e71, 0x1dd8,
- 0x080c, 0x4e3a, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000,
- 0x60a8, 0xa06d, 0x01c0, 0x6950, 0x81ff, 0x1540, 0x6a54, 0xa282,
- 0x0010, 0x1670, 0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086,
- 0xffff, 0x0128, 0x8108, 0x1f04, 0x4e0e, 0x080c, 0x14f6, 0x260a,
- 0x8210, 0x6a56, 0x0098, 0x080c, 0x15d9, 0x01d0, 0x2d00, 0x60aa,
- 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff,
- 0x8108, 0x1f04, 0x4e26, 0x6857, 0x0001, 0x6e62, 0x0010, 0x080c,
- 0x4c11, 0x0089, 0x1de0, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005,
- 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x080c, 0x67c5, 0x012e,
- 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, 0x0126, 0x2091,
- 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01e8,
- 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406,
- 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70,
- 0x6a00, 0x604c, 0xad06, 0x1110, 0x624e, 0x0018, 0xa180, 0x0000,
- 0x2202, 0x82ff, 0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e,
- 0x0010, 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8,
- 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406,
- 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70,
- 0x6a00, 0x6080, 0xad06, 0x1110, 0x6282, 0x0018, 0xa180, 0x0000,
- 0x2202, 0x82ff, 0x1110, 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c,
- 0x4ef3, 0x1110, 0x2011, 0x0001, 0x080c, 0x4f3d, 0x1110, 0xa295,
- 0x0002, 0x0005, 0x080c, 0x4f6e, 0x0118, 0x080c, 0x964b, 0x0010,
- 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, 0x0118, 0x080c, 0x95e4,
- 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, 0x0118, 0x080c,
- 0x962e, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, 0x0118,
- 0x080c, 0x9600, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e,
- 0x0118, 0x080c, 0x9667, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126,
- 0x0006, 0x00d6, 0x2091, 0x8000, 0x6080, 0xa06d, 0x01a0, 0x6800,
- 0x0006, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x97fd,
- 0x0006, 0x6000, 0xd0fc, 0x0110, 0x080c, 0xac03, 0x000e, 0x080c,
- 0x510c, 0x000e, 0x0c50, 0x6083, 0x0000, 0x6087, 0x0000, 0x00de,
- 0x000e, 0x012e, 0x0005, 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001,
- 0x0005, 0x00e6, 0x2170, 0x7000, 0xa005, 0x1160, 0x20a9, 0x0010,
- 0xae88, 0x0004, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x4f02,
- 0xa085, 0x0001, 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091,
- 0x8000, 0x60a4, 0xa06d, 0x1128, 0x080c, 0x15d9, 0x01a0, 0x2d00,
- 0x60a6, 0x6803, 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9,
- 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x4f21, 0xa085, 0x0001,
- 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091,
- 0x8000, 0x60a4, 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x15f0,
- 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118,
- 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160,
- 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108,
- 0x1f04, 0x4f4c, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091,
- 0x8000, 0x0c19, 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068,
- 0x6854, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c,
- 0x15f0, 0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4,
- 0x0005, 0x00f6, 0x080c, 0x574f, 0x01b0, 0x71b4, 0x81ff, 0x1198,
- 0x71d0, 0xd19c, 0x0180, 0x2001, 0x007e, 0xa080, 0xae34, 0x2004,
- 0xa07d, 0x0148, 0x7804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118,
- 0x7800, 0xc0ed, 0x7802, 0x2079, 0xad51, 0x7804, 0xd0a4, 0x01e8,
- 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c,
- 0x4cdc, 0x1168, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004,
- 0x0118, 0xa086, 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e,
- 0x8108, 0x1f04, 0x4f96, 0x00ce, 0x015e, 0x080c, 0x502d, 0x0120,
- 0x2001, 0xafa2, 0x200c, 0x0038, 0x2079, 0xad51, 0x7804, 0xd0a4,
- 0x0130, 0x2009, 0x07d0, 0x2011, 0x4fc1, 0x080c, 0x6593, 0x00fe,
- 0x0005, 0x2011, 0x4fc1, 0x080c, 0x650d, 0x080c, 0x502d, 0x01f0,
- 0x2001, 0xaeb2, 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102,
- 0x2001, 0xad52, 0x2004, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011,
- 0x4fc1, 0x080c, 0x6593, 0x00e6, 0x2071, 0xad00, 0x706f, 0x0000,
- 0x7073, 0x0000, 0x080c, 0x28fa, 0x00ee, 0x04b0, 0x0156, 0x00c6,
- 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4cdc, 0x1530,
- 0x6000, 0xd0ec, 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227,
- 0xa006, 0x2009, 0x0029, 0x080c, 0xa96c, 0x6000, 0xc0e5, 0xc0ec,
- 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019,
- 0x0029, 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d,
- 0x2009, 0x0000, 0x080c, 0xa712, 0x007e, 0x004e, 0x001e, 0x8108,
- 0x1f04, 0x4fec, 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060,
- 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x7818, 0x2004, 0xd0ac,
- 0x0005, 0x7818, 0x2004, 0xd0bc, 0x0005, 0x00f6, 0x2001, 0xaeb2,
- 0x2004, 0xa07d, 0x0110, 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126,
- 0x0026, 0x2091, 0x8000, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008,
- 0xc2fc, 0x6202, 0x002e, 0x012e, 0x0005, 0x2071, 0xae13, 0x7003,
- 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b,
- 0x0000, 0x701f, 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f,
- 0x0000, 0x705b, 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071,
- 0xaf7c, 0x7003, 0xae13, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f,
- 0xaf5c, 0x7013, 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005,
- 0x0016, 0x00e6, 0x2071, 0xaf34, 0xa00e, 0x7186, 0x718a, 0x7097,
- 0x0001, 0x2001, 0xad52, 0x2004, 0xd0fc, 0x1150, 0x2001, 0xad52,
- 0x2004, 0xa00e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x0804, 0x50d6,
- 0x2001, 0xad71, 0x200c, 0xa184, 0x000f, 0x2009, 0xad72, 0x210c,
- 0x0002, 0x507e, 0x50b1, 0x50b8, 0x50c2, 0x50c7, 0x507e, 0x507e,
- 0x507e, 0x50a1, 0x507e, 0x507e, 0x507e, 0x507e, 0x507e, 0x507e,
- 0x507e, 0x7003, 0x0004, 0x0136, 0x0146, 0x0156, 0x2099, 0xad75,
- 0x20a1, 0xaf85, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e,
- 0x0428, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030,
- 0x708f, 0x0002, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097,
- 0x0001, 0x0088, 0x7007, 0x0122, 0x2001, 0x0002, 0x0020, 0x7007,
- 0x0121, 0x2001, 0x0003, 0x7002, 0xa006, 0x7096, 0x708e, 0xa184,
- 0xff00, 0x8007, 0x709a, 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e,
- 0x0005, 0x00e6, 0x2071, 0xae13, 0x684c, 0xa005, 0x1130, 0x7028,
- 0xc085, 0x702a, 0xa085, 0x0001, 0x0428, 0x6a60, 0x7236, 0x6b64,
- 0x733a, 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c,
- 0x702e, 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000,
- 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210,
- 0x2100, 0xa319, 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007,
- 0x0001, 0xa006, 0x00ee, 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838,
- 0xd0fc, 0x1904, 0x5165, 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071,
- 0xad00, 0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00,
- 0x81ff, 0x1dc8, 0x702e, 0x70b0, 0xa200, 0x70b2, 0x00de, 0x2071,
- 0xae13, 0x701c, 0xa005, 0x1904, 0x5175, 0x20a9, 0x0032, 0x0f04,
- 0x5173, 0x0e04, 0x512f, 0x2071, 0xaf34, 0x7200, 0x82ff, 0x05d8,
- 0x6934, 0xa186, 0x0103, 0x1904, 0x5183, 0x6948, 0x6844, 0xa105,
- 0x1540, 0x2009, 0x8020, 0x2200, 0x0002, 0x5173, 0x514a, 0x519b,
- 0x51a7, 0x5173, 0x2071, 0x0000, 0x20a9, 0x0032, 0x0f04, 0x5173,
- 0x7018, 0xd084, 0x1dd8, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a,
- 0x701b, 0x0001, 0x2091, 0x4080, 0x2071, 0xad00, 0x702c, 0x206a,
- 0x2d00, 0x702e, 0x70b0, 0x8000, 0x70b2, 0x002e, 0x00ee, 0x015e,
- 0x0005, 0x6844, 0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118,
- 0x2009, 0x8020, 0x0880, 0x2071, 0xae13, 0x2d08, 0x206b, 0x0000,
- 0x7010, 0x8000, 0x7012, 0x7018, 0xa06d, 0x711a, 0x0110, 0x6902,
- 0x0008, 0x711e, 0x0c10, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130,
- 0xa186, 0x001e, 0x0118, 0xa18e, 0x001f, 0x1d28, 0x684c, 0xd0cc,
- 0x0d10, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x19e0, 0x2009,
- 0x8021, 0x0804, 0x5143, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a98,
- 0x7186, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x7084,
- 0x8008, 0xa092, 0x000f, 0x1a38, 0x7186, 0xae90, 0x0003, 0x8003,
- 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a,
- 0x0a04, 0x515c, 0x718c, 0x7084, 0xa10a, 0x0a04, 0x515c, 0x2071,
- 0x0000, 0x7018, 0xd084, 0x1904, 0x515c, 0x2071, 0xaf34, 0x7000,
- 0xa086, 0x0002, 0x1150, 0x080c, 0x5426, 0x2071, 0x0000, 0x701b,
- 0x0001, 0x2091, 0x4080, 0x0804, 0x515c, 0x080c, 0x5450, 0x2071,
- 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x515c, 0x0006,
- 0x684c, 0x0006, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011,
- 0x20a0, 0x2001, 0x0000, 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e,
- 0x000e, 0x684a, 0x6952, 0x0005, 0x2071, 0xae13, 0x7004, 0x0002,
- 0x5202, 0x5213, 0x5411, 0x5412, 0x541f, 0x5425, 0x5203, 0x5402,
- 0x5398, 0x53ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5212,
- 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001,
- 0x700b, 0x0000, 0x012e, 0x2069, 0xafda, 0x683c, 0xa005, 0x03f8,
- 0x11f0, 0x0126, 0x2091, 0x8000, 0x2069, 0x0000, 0x6934, 0x2001,
- 0xae1f, 0x2004, 0xa10a, 0x0170, 0x0e04, 0x5236, 0x2069, 0x0000,
- 0x6818, 0xd084, 0x1158, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001,
- 0x2091, 0x4080, 0x2069, 0xafda, 0x683f, 0xffff, 0x012e, 0x2069,
- 0xad00, 0x6844, 0x6964, 0xa102, 0x2069, 0xaf34, 0x688a, 0x6984,
- 0x701c, 0xa06d, 0x0120, 0x81ff, 0x0904, 0x528c, 0x00a0, 0x81ff,
- 0x0904, 0x5352, 0x2071, 0xaf34, 0x7184, 0x7088, 0xa10a, 0x1258,
- 0x7190, 0x2071, 0xafda, 0x7038, 0xa005, 0x0128, 0x1b04, 0x5352,
- 0x713a, 0x0804, 0x5352, 0x2071, 0xaf34, 0x718c, 0x0126, 0x2091,
- 0x8000, 0x7084, 0xa10a, 0x0a04, 0x536d, 0x0e04, 0x530e, 0x2071,
- 0x0000, 0x7018, 0xd084, 0x1904, 0x530e, 0x2001, 0xffff, 0x2071,
- 0xafda, 0x703a, 0x2071, 0xaf34, 0x7000, 0xa086, 0x0002, 0x1150,
- 0x080c, 0x5426, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
- 0x0804, 0x530e, 0x080c, 0x5450, 0x2071, 0x0000, 0x701b, 0x0001,
- 0x2091, 0x4080, 0x0804, 0x530e, 0x2071, 0xaf34, 0x7000, 0xa005,
- 0x0904, 0x5334, 0x6934, 0xa186, 0x0103, 0x1904, 0x5311, 0x684c,
- 0xd0bc, 0x1904, 0x5334, 0x6948, 0x6844, 0xa105, 0x1904, 0x5329,
- 0x2009, 0x8020, 0x2071, 0xaf34, 0x7000, 0x0002, 0x5334, 0x52f4,
- 0x52cc, 0x52de, 0x52ab, 0x0136, 0x0146, 0x0156, 0x2099, 0xad75,
- 0x20a1, 0xaf85, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e,
- 0x2071, 0xaf7c, 0xad80, 0x000f, 0x700e, 0x7013, 0x0002, 0x7007,
- 0x0002, 0x700b, 0x0000, 0x2e10, 0x080c, 0x1624, 0x2071, 0xae13,
- 0x7007, 0x0009, 0x0804, 0x5352, 0x7084, 0x8008, 0xa092, 0x001e,
- 0x1a04, 0x5352, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x7186,
- 0x2071, 0xae13, 0x080c, 0x54a7, 0x0804, 0x5352, 0x7084, 0x8008,
- 0xa092, 0x000f, 0x1a04, 0x5352, 0xae90, 0x0003, 0x8003, 0xa210,
- 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7186, 0x2071, 0xae13,
- 0x080c, 0x54a7, 0x0804, 0x5352, 0x0126, 0x2091, 0x8000, 0x0e04,
- 0x530e, 0x2071, 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c,
- 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e,
- 0x2071, 0xae13, 0x080c, 0x54a7, 0x0804, 0x5352, 0x012e, 0x0804,
- 0x5352, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e,
- 0x0118, 0xa18e, 0x001f, 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850,
- 0xa084, 0x00ff, 0xa086, 0x0001, 0x1178, 0x2009, 0x8021, 0x0804,
- 0x52a2, 0x6844, 0xa086, 0x0100, 0x1138, 0x6868, 0xa005, 0x1120,
- 0x2009, 0x8020, 0x0804, 0x52a2, 0x2071, 0xae13, 0x080c, 0x54b9,
- 0x01c8, 0x2071, 0xae13, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff,
- 0xa086, 0x0003, 0x1130, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108,
- 0x710e, 0x7007, 0x0003, 0x080c, 0x54d2, 0x7050, 0xa086, 0x0100,
- 0x0904, 0x5412, 0x0126, 0x2091, 0x8000, 0x2071, 0xae13, 0x7008,
- 0xa086, 0x0001, 0x1180, 0x0e04, 0x536b, 0x2009, 0x000d, 0x7030,
- 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006,
- 0x1110, 0x7007, 0x0001, 0x012e, 0x0005, 0x2071, 0xae13, 0x080c,
- 0x54b9, 0x0518, 0x2071, 0xaf34, 0x7084, 0x700a, 0x20a9, 0x0020,
- 0x2099, 0xaf35, 0x20a1, 0xaf5c, 0x53a3, 0x7087, 0x0000, 0x2071,
- 0xae13, 0x2069, 0xaf7c, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074,
- 0x682e, 0x7078, 0x6832, 0x2d10, 0x080c, 0x1624, 0x7007, 0x0008,
- 0x2001, 0xffff, 0x2071, 0xafda, 0x703a, 0x012e, 0x0804, 0x5352,
- 0x2069, 0xaf7c, 0x6808, 0xa08e, 0x0000, 0x0904, 0x53ed, 0xa08e,
- 0x0200, 0x0904, 0x53eb, 0xa08e, 0x0100, 0x1904, 0x53ed, 0x0126,
- 0x2091, 0x8000, 0x0e04, 0x53e9, 0x2069, 0x0000, 0x6818, 0xd084,
- 0x15c0, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034,
- 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e,
- 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b,
- 0x0000, 0x2001, 0xaf59, 0x2004, 0xa005, 0x1190, 0x6934, 0x2069,
- 0xaf34, 0x689c, 0x699e, 0x2069, 0xafda, 0xa102, 0x1118, 0x683c,
- 0xa005, 0x1368, 0x2001, 0xaf5a, 0x200c, 0x810d, 0x693e, 0x0038,
- 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007,
- 0x0001, 0x012e, 0x0010, 0x7007, 0x0005, 0x0005, 0x2001, 0xaf7e,
- 0x2004, 0xa08e, 0x0100, 0x1128, 0x7007, 0x0001, 0x080c, 0x54a7,
- 0x0005, 0xa08e, 0x0000, 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007,
- 0x0005, 0x0005, 0x701c, 0xa06d, 0x0158, 0x080c, 0x54b9, 0x0140,
- 0x7007, 0x0003, 0x080c, 0x54d2, 0x7050, 0xa086, 0x0100, 0x0110,
- 0x0005, 0x0005, 0x7050, 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004,
- 0x0030, 0xa086, 0x0200, 0x1110, 0x7007, 0x0005, 0x0005, 0x080c,
- 0x5475, 0x7006, 0x080c, 0x54a7, 0x0005, 0x0005, 0x00e6, 0x0156,
- 0x2071, 0xaf34, 0x7184, 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80,
- 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04,
- 0x544a, 0x2014, 0x722a, 0x8000, 0x0f04, 0x544a, 0x2014, 0x722e,
- 0x8000, 0x0f04, 0x544a, 0x2014, 0x723a, 0x8000, 0x0f04, 0x544a,
- 0x2014, 0x723e, 0xa180, 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005,
- 0x00e6, 0x0156, 0x2071, 0xaf34, 0x7184, 0x81ff, 0x01d8, 0xa006,
- 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226,
- 0x8000, 0x2014, 0x722a, 0x8000, 0x0f04, 0x546c, 0x2014, 0x723a,
- 0x8000, 0x2014, 0x723e, 0x0018, 0x2001, 0x8020, 0x0010, 0x2001,
- 0x8042, 0x7022, 0x015e, 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108,
- 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048,
- 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000,
- 0x7072, 0x7132, 0x700c, 0x8001, 0x700e, 0x1180, 0x0126, 0x2091,
- 0x8000, 0x0e04, 0x54a1, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080,
- 0x2001, 0x0001, 0x700b, 0x0000, 0x012e, 0x0005, 0x2001, 0x0007,
- 0x0005, 0x2001, 0x0006, 0x700b, 0x0001, 0x012e, 0x0005, 0x701c,
- 0xa06d, 0x0170, 0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012,
- 0x2d04, 0x701e, 0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x15f0,
- 0x0005, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304,
- 0x230c, 0xa10e, 0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130,
- 0xa102, 0x1118, 0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008,
- 0x8002, 0x0005, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053,
- 0x0000, 0x0126, 0x2091, 0x8000, 0x2009, 0xafec, 0x2104, 0xc08d,
- 0x200a, 0x012e, 0x080c, 0x163c, 0x0005, 0x7088, 0xa08a, 0x0029,
- 0x1220, 0xa082, 0x001d, 0x0033, 0x0010, 0x080c, 0x14f6, 0x6027,
- 0x1e00, 0x0005, 0x55c1, 0x555b, 0x5571, 0x5595, 0x55b4, 0x55e6,
- 0x55f8, 0x5571, 0x55d2, 0x54ff, 0x552d, 0x54fe, 0x0005, 0x00d6,
- 0x2069, 0x0200, 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518,
- 0x708b, 0x0028, 0x2069, 0xafac, 0x2d04, 0x7002, 0x080c, 0x584d,
- 0x6028, 0xa085, 0x0600, 0x602a, 0x00b0, 0x708b, 0x0028, 0x2069,
- 0xafac, 0x2d04, 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6,
- 0x0036, 0x0046, 0x0056, 0x2071, 0xaffd, 0x080c, 0x1d22, 0x005e,
- 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200,
- 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708b, 0x0028,
- 0x2069, 0xafac, 0x2d04, 0x7002, 0x080c, 0x58da, 0x6028, 0xa085,
- 0x0600, 0x602a, 0x00b0, 0x708b, 0x0028, 0x2069, 0xafac, 0x2d04,
- 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046,
- 0x0056, 0x2071, 0xaffd, 0x080c, 0x1d22, 0x005e, 0x004e, 0x003e,
- 0x00ee, 0x00de, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1180,
- 0x080c, 0x5663, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1cc, 0x0140,
- 0x708b, 0x0020, 0x0028, 0x708b, 0x001d, 0x0010, 0x708b, 0x001f,
- 0x0005, 0x6803, 0x0088, 0x6124, 0xd1cc, 0x11c8, 0xd1dc, 0x11a0,
- 0xd1e4, 0x1178, 0xa184, 0x1e00, 0x11b8, 0x60e3, 0x0001, 0x600c,
- 0xc0b4, 0x600e, 0x080c, 0x577f, 0x6803, 0x0080, 0x708b, 0x0028,
- 0x0058, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d, 0x0028, 0x708b,
- 0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x60e3, 0x0001, 0x600c,
- 0xc0b4, 0x600e, 0x080c, 0x577f, 0x6803, 0x0080, 0x6124, 0xd1d4,
- 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0xa184, 0x1e00, 0x1158,
- 0x708b, 0x0028, 0x0040, 0x708b, 0x001e, 0x0028, 0x708b, 0x001d,
- 0x0010, 0x708b, 0x001f, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1dc,
- 0x1128, 0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b, 0x001d,
- 0x0005, 0x080c, 0x568d, 0x6124, 0xd1dc, 0x1158, 0x080c, 0x5663,
- 0xd1d4, 0x1128, 0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b,
- 0x001f, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1d4, 0x1160, 0xd1cc,
- 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b, 0x001e, 0x0028,
- 0x708b, 0x001d, 0x0010, 0x708b, 0x0021, 0x0005, 0x080c, 0x568d,
- 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b,
- 0x001e, 0x0028, 0x708b, 0x001d, 0x0010, 0x708b, 0x001f, 0x0005,
- 0x6803, 0x0090, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc,
- 0x1128, 0xd1e4, 0x0158, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d,
- 0x0028, 0x708b, 0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x0016,
- 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, 0x0140,
- 0x2071, 0xad00, 0x2091, 0x8000, 0x080c, 0x574f, 0x11e8, 0x2001,
- 0xad0c, 0x200c, 0xd1b4, 0x01c0, 0xc1b4, 0x2102, 0x6027, 0x0200,
- 0xe000, 0xe000, 0x6024, 0xd0cc, 0x0158, 0x6803, 0x00a0, 0x2001,
- 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x0428,
- 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x576b, 0x0150, 0x080c,
- 0x5761, 0x1138, 0x2001, 0x0001, 0x080c, 0x261e, 0x080c, 0x5726,
- 0x00a0, 0x080c, 0x568a, 0x0178, 0x2001, 0x0001, 0x080c, 0x261e,
- 0x7088, 0xa086, 0x001e, 0x0120, 0x7088, 0xa086, 0x0022, 0x1118,
- 0x708b, 0x0025, 0x0010, 0x708b, 0x0021, 0x012e, 0x00ee, 0x00de,
- 0x00ce, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011,
- 0x566e, 0x080c, 0x6501, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6,
- 0x0016, 0x080c, 0x7834, 0x2071, 0xad00, 0x080c, 0x560f, 0x001e,
- 0x00fe, 0x00ee, 0x0005, 0x2001, 0xad00, 0x2004, 0xa086, 0x0004,
- 0x0140, 0x2001, 0xaf9d, 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003,
- 0x0000, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6803, 0x00c0, 0x0156,
- 0x20a9, 0x002d, 0x1d04, 0x5692, 0x2091, 0x6000, 0x1f04, 0x5692,
- 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069,
- 0x0140, 0x2071, 0xad00, 0x2001, 0xaf9e, 0x200c, 0xa186, 0x0000,
- 0x0158, 0xa186, 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186,
- 0x0003, 0x0158, 0x0804, 0x5714, 0x708b, 0x0022, 0x0040, 0x708b,
- 0x0021, 0x0028, 0x708b, 0x0023, 0x0020, 0x708b, 0x0024, 0x6043,
- 0x0000, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c,
- 0x26cb, 0x0026, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002,
- 0x080c, 0x7ae9, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b,
- 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000,
- 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0118, 0x012e, 0x015e, 0x04d0,
- 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, 0x1130,
- 0x6803, 0x0100, 0x1f04, 0x56e2, 0x080c, 0x57a0, 0x012e, 0x015e,
- 0x080c, 0x5761, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, 0x0006,
- 0xa085, 0x0020, 0x6052, 0x080c, 0x57a0, 0xa006, 0x8001, 0x1df0,
- 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x57a0,
- 0x2001, 0xaf9e, 0x2003, 0x0004, 0x080c, 0x54e5, 0x080c, 0x5761,
- 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, 0x2001, 0xaf9e,
- 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6,
- 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xad00, 0x2001,
- 0xaf9d, 0x2003, 0x0000, 0x2001, 0xaf8e, 0x2003, 0x0000, 0x708b,
- 0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, 0x080c,
- 0x26cb, 0x6803, 0x0000, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027,
- 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006,
- 0x2001, 0xaf9d, 0x2004, 0xa086, 0xaaaa, 0x000e, 0x0005, 0x0006,
- 0x2001, 0xad71, 0x2004, 0xa084, 0x0030, 0xa086, 0x0000, 0x000e,
- 0x0005, 0x0006, 0x2001, 0xad71, 0x2004, 0xa084, 0x0030, 0xa086,
- 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, 0xad71, 0x2004, 0xa084,
- 0x0030, 0xa086, 0x0010, 0x000e, 0x0005, 0x0006, 0x2001, 0xad71,
- 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, 0x000e, 0x0005, 0x2001,
- 0xad0c, 0x2004, 0xd0a4, 0x0170, 0x080c, 0x26eb, 0x0036, 0x0016,
- 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, 0x2aac, 0x001e, 0x003e,
- 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0xad0c, 0x2e04, 0x0118,
- 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072, 0x00ee, 0x0005,
- 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006,
- 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000,
- 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, 0x6006,
- 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, 0x60e3, 0x0000,
- 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x26cb, 0x6800, 0xa084,
- 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, 0x000e, 0x6052, 0x6050,
- 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6,
- 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xad00, 0x6020, 0xa084,
- 0x0080, 0x0138, 0x2001, 0xad0c, 0x200c, 0xc1bd, 0x2102, 0x0804,
- 0x5845, 0x2001, 0xad0c, 0x200c, 0xc1bc, 0x2102, 0x6028, 0xa084,
- 0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, 0x0090, 0x20a9, 0x0384,
- 0x6024, 0xd0cc, 0x1518, 0x1d04, 0x57f8, 0x2091, 0x6000, 0x1f04,
- 0x57f8, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c,
- 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, 0x2019, 0x0000, 0x080c,
- 0x7a64, 0x6803, 0x00a0, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001,
- 0xad00, 0x2003, 0x0001, 0xa085, 0x0001, 0x0438, 0x60e3, 0x0000,
- 0x2001, 0xaf8e, 0x2004, 0x080c, 0x26cb, 0x60e2, 0x6803, 0x0080,
- 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024,
- 0xa10c, 0x0138, 0x1d04, 0x582a, 0x2091, 0x6000, 0x1f04, 0x582a,
- 0x0840, 0x6028, 0xa085, 0x1e00, 0x602a, 0x70a0, 0xa005, 0x1118,
- 0x6887, 0x0001, 0x0008, 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce,
- 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026,
- 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00,
- 0x2069, 0x0140, 0x6020, 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005,
- 0x1904, 0x58a1, 0x6803, 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000,
- 0x2001, 0x0000, 0x080c, 0x26cb, 0x2069, 0x0200, 0x6804, 0xa005,
- 0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a,
- 0x6027, 0x0400, 0x2069, 0xafac, 0x7000, 0x206a, 0x708b, 0x0026,
- 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x5884, 0x2091, 0x6000,
- 0x1f04, 0x5884, 0x0804, 0x58d2, 0x2069, 0x0140, 0x20a9, 0x0384,
- 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0530,
- 0xa084, 0x1a00, 0x1518, 0x1d04, 0x5890, 0x2091, 0x6000, 0x1f04,
- 0x5890, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c,
- 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, 0x2019, 0x0000, 0x080c,
- 0x7a64, 0x6803, 0x00a0, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001,
- 0xad00, 0x2003, 0x0001, 0xa085, 0x0001, 0x00a0, 0x6803, 0x0080,
- 0x2069, 0x0140, 0x60e3, 0x0000, 0x70a0, 0xa005, 0x1118, 0x6887,
- 0x0001, 0x0008, 0x6886, 0x2001, 0xaf8e, 0x2004, 0x080c, 0x26cb,
- 0x60e2, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e,
- 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6,
- 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00, 0x6020, 0xa084, 0x00c0,
- 0x01f0, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c,
- 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, 0x2019, 0x0000, 0x080c,
- 0x7a64, 0x2069, 0x0140, 0x6803, 0x00a0, 0x2001, 0xaf9e, 0x2003,
- 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x0804, 0x5972, 0x2001,
- 0xad0c, 0x200c, 0xd1b4, 0x1150, 0xc1b5, 0x2102, 0x080c, 0x5663,
- 0x2069, 0x0140, 0x6803, 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200,
- 0x6804, 0xa005, 0x1118, 0x6808, 0xa005, 0x01b8, 0x6028, 0xa084,
- 0xfdff, 0x602a, 0x6027, 0x0200, 0x2069, 0xafac, 0x7000, 0x206a,
- 0x708b, 0x0027, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x592e,
- 0x2091, 0x6000, 0x1f04, 0x592e, 0x04e8, 0x6027, 0x1e00, 0x2009,
- 0x1e00, 0xe000, 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0,
- 0x1d04, 0x5935, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c,
- 0x64a2, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071,
- 0xafda, 0x7018, 0x00ee, 0xa005, 0x1d00, 0x01e0, 0x0026, 0x2011,
- 0x566e, 0x080c, 0x650d, 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000,
- 0x70a0, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001,
- 0xaf8e, 0x2004, 0x080c, 0x26cb, 0x60e2, 0x2001, 0xad0c, 0x200c,
- 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e,
- 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6,
- 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00, 0x7130, 0xd184, 0x1180,
- 0x2011, 0xad52, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011,
- 0xad52, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x59df,
- 0x7130, 0xc185, 0x7132, 0x2011, 0xad52, 0x220c, 0xd1a4, 0x0530,
- 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x663f, 0x2019,
- 0x000e, 0x080c, 0xa8eb, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000,
- 0xa186, 0x007e, 0x0170, 0xa186, 0x0080, 0x0158, 0x080c, 0x4cdc,
- 0x1140, 0x8127, 0xa006, 0x0016, 0x2009, 0x000e, 0x080c, 0xa96c,
- 0x001e, 0x8108, 0x1f04, 0x59b0, 0x015e, 0x001e, 0xd1ac, 0x1148,
- 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, 0x2aac, 0x001e,
- 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0x080c, 0x4cdc,
- 0x1110, 0x080c, 0x493a, 0x8108, 0x1f04, 0x59d6, 0x015e, 0x2011,
- 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c, 0x7ae9, 0x080c,
- 0x79e1, 0x080c, 0x6581, 0x0036, 0x2019, 0x0000, 0x080c, 0x7a64,
- 0x003e, 0x60e3, 0x0000, 0x2001, 0xad00, 0x2003, 0x0001, 0x080c,
- 0x569a, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, 0x015e,
- 0x0005, 0x2071, 0xade1, 0x7003, 0x0000, 0x7007, 0x0000, 0x700f,
- 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001, 0x705f,
- 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, 0x0000, 0x708f,
- 0x0001, 0x70bf, 0x0000, 0x0005, 0x00e6, 0x2071, 0xade1, 0x6848,
- 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0428,
- 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, 0x707a, 0x685c,
- 0x7042, 0x707e, 0x6848, 0x702e, 0x6840, 0x7032, 0x2009, 0x000c,
- 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0,
- 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, 0x7028, 0xc084, 0x702a,
- 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee, 0x0005, 0x2b78,
- 0x2071, 0xade1, 0x7004, 0x0043, 0x700c, 0x0002, 0x5a5b, 0x5a52,
- 0x5a52, 0x5a52, 0x5a52, 0x0005, 0x5ab1, 0x5ab2, 0x5ae4, 0x5ae5,
- 0x5aaf, 0x5b33, 0x5b38, 0x5b69, 0x5b6a, 0x5b85, 0x5b86, 0x5b87,
- 0x5b88, 0x5b89, 0x5b8a, 0x5c40, 0x5c67, 0x700c, 0x0002, 0x5a74,
- 0x5aaf, 0x5aaf, 0x5ab0, 0x5ab0, 0x7830, 0x7930, 0xa106, 0x0120,
- 0x7830, 0x7930, 0xa106, 0x1510, 0x7030, 0xa10a, 0x01f8, 0x1210,
- 0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0, 0x080c, 0x15c0, 0x01b0,
- 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057, 0x0000,
- 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0xafec, 0x2104, 0xc085,
- 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x163c, 0x0005, 0x080c,
- 0x15c0, 0x0de0, 0x2d00, 0x705a, 0x080c, 0x15c0, 0x1108, 0x0c10,
- 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x08f8, 0x0005,
- 0x0005, 0x0005, 0x700c, 0x0002, 0x5ab9, 0x5abc, 0x5aca, 0x5ae3,
- 0x5ae3, 0x080c, 0x5a6d, 0x0005, 0x0126, 0x8001, 0x700e, 0x7058,
- 0x0006, 0x080c, 0x5f90, 0x0120, 0x2091, 0x8000, 0x080c, 0x5a6d,
- 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x5f90, 0x7058,
- 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834,
- 0xa084, 0x00ff, 0xa08a, 0x003a, 0x1218, 0x00db, 0x012e, 0x0005,
- 0x012e, 0x080c, 0x5b8b, 0x0005, 0x0005, 0x0005, 0x00e6, 0x2071,
- 0xade1, 0x700c, 0x0002, 0x5af0, 0x5af0, 0x5af0, 0x5af2, 0x5af5,
- 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, 0x700f, 0x0002, 0x00ee,
- 0x0005, 0x5b8b, 0x5b8b, 0x5ba7, 0x5b8b, 0x5d22, 0x5b8b, 0x5b8b,
- 0x5b8b, 0x5b8b, 0x5b8b, 0x5ba7, 0x5d64, 0x5da7, 0x5df0, 0x5e04,
- 0x5b8b, 0x5b8b, 0x5bc3, 0x5ba7, 0x5b8b, 0x5b8b, 0x5c1d, 0x5ead,
- 0x5ec8, 0x5b8b, 0x5bc3, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5c13,
- 0x5ec8, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b,
- 0x5b8b, 0x5b8b, 0x5bd7, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b,
- 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b,
- 0x5b8b, 0x5b8b, 0x5bec, 0x7020, 0x2068, 0x080c, 0x15f0, 0x0005,
- 0x700c, 0x0002, 0x5b3f, 0x5b42, 0x5b50, 0x5b68, 0x5b68, 0x080c,
- 0x5a6d, 0x0005, 0x0126, 0x8001, 0x700e, 0x7058, 0x0006, 0x080c,
- 0x5f90, 0x0120, 0x2091, 0x8000, 0x080c, 0x5a6d, 0x00de, 0x0048,
- 0x0126, 0x8001, 0x700e, 0x080c, 0x5f90, 0x7058, 0x2068, 0x7084,
- 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff,
- 0xa08a, 0x001a, 0x1218, 0x003b, 0x012e, 0x0005, 0x012e, 0x0419,
- 0x0005, 0x0005, 0x0005, 0x5b8b, 0x5ba7, 0x5d0e, 0x5b8b, 0x5ba7,
- 0x5b8b, 0x5ba7, 0x5ba7, 0x5b8b, 0x5ba7, 0x5d0e, 0x5ba7, 0x5ba7,
- 0x5ba7, 0x5ba7, 0x5ba7, 0x5b8b, 0x5ba7, 0x5d0e, 0x5b8b, 0x5b8b,
- 0x5ba7, 0x5b8b, 0x5b8b, 0x5b8b, 0x5ba7, 0x0005, 0x0005, 0x0005,
- 0x0005, 0x0005, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff,
- 0xc0d5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x510c, 0x012e,
- 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a,
- 0x0126, 0x2091, 0x8000, 0x080c, 0x510c, 0x012e, 0x0005, 0x7007,
- 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x0126, 0x2091,
- 0x8000, 0x080c, 0x510c, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838,
- 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c,
- 0x510c, 0x012e, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0988,
- 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x5cd0, 0x7007, 0x0006,
- 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x5cd0, 0x0005, 0x6834,
- 0x8007, 0xa084, 0x00ff, 0x0904, 0x5b99, 0x8001, 0x1120, 0x7007,
- 0x0001, 0x0804, 0x5ced, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016,
- 0x701a, 0x704b, 0x5ced, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff,
- 0xa086, 0x0001, 0x1904, 0x5b99, 0x7007, 0x0001, 0x2009, 0xad30,
- 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, 0x683a, 0x6853,
- 0x0000, 0x080c, 0x4ab1, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000,
- 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, 0x510c, 0x012e, 0x0ca0,
- 0x2001, 0x0028, 0x0c90, 0x684c, 0xa084, 0x00c0, 0xa086, 0x00c0,
- 0x1120, 0x7007, 0x0001, 0x0804, 0x5ee0, 0x2d00, 0x7016, 0x701a,
- 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, 0xae0c, 0x53a3,
- 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, 0x5bb5, 0x6a84, 0xa28a,
- 0x0002, 0x1a04, 0x5bb5, 0x82ff, 0x1138, 0x6888, 0x698c, 0xa105,
- 0x0118, 0x2001, 0x5ca3, 0x0018, 0xa280, 0x5c99, 0x2005, 0x70c6,
- 0x7010, 0xa015, 0x0904, 0x5c85, 0x080c, 0x15c0, 0x1118, 0x7007,
- 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x2c05, 0x6836,
- 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, 0x1210, 0xa00e, 0x2200,
- 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0108, 0xa108,
- 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x080c, 0x1624, 0x7090,
- 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, 0x0118, 0x7007, 0x0010,
- 0x0005, 0x7020, 0x2068, 0x080c, 0x15f0, 0x7014, 0x2068, 0x0804,
- 0x5bb5, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08,
- 0x2068, 0x6906, 0x711a, 0x0804, 0x5c40, 0x7014, 0x2068, 0x7007,
- 0x0001, 0x6884, 0xa005, 0x1128, 0x6888, 0x698c, 0xa105, 0x0108,
- 0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0904, 0x5ee0,
- 0x04b8, 0x5c9b, 0x5c9f, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a,
- 0x000f, 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x00f6,
- 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88, 0x6e8c, 0x6804, 0x2060,
- 0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816,
- 0x7008, 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a,
- 0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0c78, 0x6004,
- 0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005,
- 0x2009, 0xad30, 0x210c, 0x81ff, 0x1198, 0x6838, 0xa084, 0x00ff,
- 0x683a, 0x080c, 0x4993, 0x1108, 0x0005, 0x080c, 0x51df, 0x0126,
- 0x2091, 0x8000, 0x080c, 0x97fd, 0x080c, 0x510c, 0x012e, 0x0ca0,
- 0x2001, 0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, 0xad30, 0x210c,
- 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01b0, 0x6838, 0xa084, 0x00ff,
- 0x683a, 0x6853, 0x0000, 0x080c, 0x4a55, 0x1108, 0x0005, 0x0126,
- 0x2091, 0x8000, 0x080c, 0x51df, 0x080c, 0x510c, 0x012e, 0x0cb0,
- 0x2001, 0x0028, 0x0ca0, 0x2001, 0x0000, 0x0c88, 0x7018, 0x6802,
- 0x2d08, 0x2068, 0x6906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118,
- 0x7007, 0x0006, 0x0030, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048,
- 0x080f, 0x0005, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff,
- 0x6848, 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x01b0,
- 0x2009, 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0178, 0xa005,
- 0x11f0, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4cdc, 0x11b8,
- 0x0066, 0x6e50, 0x080c, 0x4dcf, 0x006e, 0x0088, 0x0046, 0x2011,
- 0xad0c, 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x4cdc,
- 0x1110, 0x080c, 0x4f2d, 0x8108, 0x1f04, 0x5d4e, 0x00ce, 0x684c,
- 0xd084, 0x1118, 0x080c, 0x15f0, 0x0005, 0x0126, 0x2091, 0x8000,
- 0x080c, 0x510c, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007,
- 0x0001, 0x2001, 0xad52, 0x2004, 0xd0a4, 0x0580, 0x2061, 0xb048,
- 0x6100, 0xd184, 0x0178, 0x6858, 0xa084, 0x00ff, 0x1550, 0x6000,
- 0xd084, 0x0520, 0x6004, 0xa005, 0x1538, 0x6003, 0x0000, 0x600b,
- 0x0000, 0x00c8, 0x2011, 0x0001, 0x6860, 0xa005, 0x1110, 0x2001,
- 0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff, 0x0178, 0x6006,
- 0x6858, 0x8007, 0xa084, 0x00ff, 0x0148, 0x600a, 0x6858, 0x8000,
- 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, 0x5f7f, 0x012e, 0x0804,
- 0x5f79, 0x012e, 0x0804, 0x5f73, 0x012e, 0x0804, 0x5f76, 0x0126,
- 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xad52, 0x2004, 0xd0a4,
- 0x05e0, 0x2061, 0xb048, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308,
- 0xd08c, 0x1530, 0x6c48, 0xa484, 0x0003, 0x0170, 0x6958, 0xa18c,
- 0x00ff, 0x8001, 0x1120, 0x2100, 0xa210, 0x0620, 0x0028, 0x8001,
- 0x1508, 0x2100, 0xa212, 0x02f0, 0xa484, 0x000c, 0x0188, 0x6958,
- 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x1120, 0x2100, 0xa318,
- 0x0288, 0x0030, 0xa082, 0x0004, 0x1168, 0x2100, 0xa31a, 0x0250,
- 0x6860, 0xa005, 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, 0x012e,
- 0x0804, 0x5f7f, 0x012e, 0x0804, 0x5f7c, 0x012e, 0x0804, 0x5f79,
- 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xb048, 0x6300,
- 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, 0x0804,
- 0x5f8d, 0x012e, 0x0804, 0x5f7c, 0x0126, 0x00c6, 0x2091, 0x8000,
- 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0148, 0x00c6, 0x2061, 0xb048,
- 0x6000, 0xa084, 0xfcff, 0x6002, 0x00ce, 0x0448, 0x6858, 0xa005,
- 0x05d0, 0x685c, 0xa065, 0x0598, 0x2001, 0xad30, 0x2004, 0xa005,
- 0x0118, 0x080c, 0x974e, 0x0068, 0x6013, 0x0400, 0x6057, 0x0000,
- 0x694c, 0xd1a4, 0x0110, 0x6950, 0x6156, 0x2009, 0x0041, 0x080c,
- 0x80a7, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, 0x1140, 0x0026,
- 0x2009, 0x0000, 0x2011, 0xfdff, 0x080c, 0x663f, 0x002e, 0x684c,
- 0xd0c4, 0x0148, 0x2061, 0xb048, 0x6000, 0xd08c, 0x1120, 0x6008,
- 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, 0x0804, 0x5f7f, 0x00ce,
- 0x012e, 0x0804, 0x5f79, 0x6954, 0xa186, 0x002e, 0x0d40, 0xa186,
- 0x002d, 0x0d28, 0xa186, 0x0045, 0x0510, 0xa186, 0x002a, 0x1130,
- 0x2001, 0xad0c, 0x200c, 0xc194, 0x2102, 0x08c8, 0xa186, 0x0020,
- 0x0170, 0xa186, 0x0029, 0x1d18, 0x6944, 0xa18c, 0xff00, 0x810f,
- 0x080c, 0x4cdc, 0x1960, 0x6000, 0xc0e4, 0x6002, 0x0840, 0x685c,
- 0xa065, 0x09a8, 0x2001, 0xafa3, 0x2004, 0x6016, 0x0800, 0x685c,
- 0xa065, 0x0968, 0x00e6, 0x6860, 0xa075, 0x2001, 0xad30, 0x2004,
- 0xa005, 0x0150, 0x080c, 0x974e, 0x8eff, 0x0118, 0x2e60, 0x080c,
- 0x974e, 0x00ee, 0x0804, 0x5e3f, 0x6020, 0xc0dc, 0xc0d5, 0x6022,
- 0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b,
- 0x6874, 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x67a8,
- 0x080c, 0x6c50, 0x00ee, 0x0804, 0x5e3f, 0x2061, 0xb048, 0x6000,
- 0xd084, 0x0190, 0xd08c, 0x1904, 0x5f8d, 0x0126, 0x2091, 0x8000,
- 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x5f8d, 0x012e,
- 0x6853, 0x0016, 0x0804, 0x5f86, 0x6853, 0x0007, 0x0804, 0x5f86,
- 0x6834, 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x5b99, 0x0078,
- 0x2030, 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007,
- 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x5ee0, 0x0005,
- 0x00e6, 0x0126, 0x2091, 0x8000, 0x2009, 0xad30, 0x210c, 0x81ff,
- 0x1904, 0x5f5b, 0x2009, 0xad0c, 0x210c, 0xd194, 0x1904, 0x5f63,
- 0x6848, 0x2070, 0xae82, 0xb400, 0x0a04, 0x5f4f, 0x2001, 0xad16,
- 0x2004, 0xae02, 0x1a04, 0x5f4f, 0x2061, 0xb048, 0x6100, 0xa184,
- 0x0301, 0xa086, 0x0001, 0x15a8, 0x711c, 0xa186, 0x0006, 0x15b0,
- 0x7018, 0xa005, 0x0904, 0x5f5b, 0x2004, 0xd0e4, 0x1904, 0x5f5e,
- 0x7020, 0xd0dc, 0x1904, 0x5f66, 0x6853, 0x0000, 0x6803, 0x0000,
- 0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c, 0xd0f4, 0x1904,
- 0x5f69, 0x2e60, 0x080c, 0x65aa, 0x012e, 0x00ee, 0x0005, 0x2068,
- 0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c, 0xd0f4, 0x15c8,
- 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, 0x0006, 0x0804,
- 0x5f86, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, 0x6944, 0xa18c,
- 0xff00, 0x810f, 0x080c, 0x4cdc, 0x11c8, 0x6000, 0xd0e4, 0x11b0,
- 0x711c, 0xa186, 0x0007, 0x1118, 0x6853, 0x0002, 0x0088, 0x6853,
- 0x0008, 0x0070, 0x6853, 0x000e, 0x0058, 0x6853, 0x0017, 0x0040,
- 0x6853, 0x0035, 0x0028, 0x6853, 0x0028, 0x0010, 0x6853, 0x0029,
- 0x012e, 0x00ee, 0x0418, 0x6853, 0x002a, 0x0cd0, 0x6853, 0x0045,
- 0x0cb8, 0x2e60, 0x2019, 0x0002, 0x6017, 0x0014, 0x080c, 0xa566,
- 0x012e, 0x00ee, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004,
- 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009,
- 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856, 0x0126, 0x2091,
- 0x8000, 0x080c, 0x510c, 0x012e, 0x0005, 0x080c, 0x15f0, 0x0005,
- 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x7072,
- 0x7038, 0x7076, 0x0058, 0x7070, 0xa080, 0x0040, 0x7072, 0x1230,
- 0x7074, 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932, 0x7132,
- 0x0005, 0x00d6, 0x080c, 0x65a1, 0x00de, 0x0005, 0x00d6, 0x2011,
- 0x0004, 0x2204, 0xa085, 0x8002, 0x2012, 0x00de, 0x0005, 0x20e1,
- 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0118,
- 0xa086, 0x1000, 0x1540, 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00,
- 0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x1118, 0x080c, 0x61c6,
- 0x00b0, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x1108, 0x3e60, 0xac84,
- 0x0007, 0x1188, 0xac82, 0xb400, 0x0270, 0x6858, 0xac02, 0x1258,
- 0x6120, 0xd1f4, 0x1160, 0x2009, 0x0047, 0x080c, 0x80a7, 0x7a1c,
- 0xd284, 0x1968, 0x0005, 0xa016, 0x080c, 0x1824, 0x0cc0, 0x0cd8,
- 0x781c, 0xd08c, 0x0500, 0x0156, 0x0136, 0x0146, 0x20e1, 0x3000,
- 0x3d20, 0x3e28, 0xa584, 0x0076, 0x1530, 0xa484, 0x7000, 0xa086,
- 0x1000, 0x11a8, 0x080c, 0x604e, 0x01f0, 0x20e1, 0x3000, 0x7828,
- 0x7828, 0x080c, 0x606a, 0x014e, 0x013e, 0x015e, 0x2009, 0xafcf,
- 0x2104, 0xa005, 0x1108, 0x0005, 0x080c, 0x6c50, 0x0ce0, 0xa484,
- 0x7000, 0x1518, 0x0499, 0x01b8, 0x7000, 0xa084, 0xff00, 0xa086,
- 0x8100, 0x0d18, 0x0080, 0xd5a4, 0x0158, 0x080c, 0x1d86, 0x20e1,
- 0x9010, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0048,
- 0x00e9, 0x6883, 0x0000, 0x080c, 0xac59, 0x20e1, 0x3000, 0x7828,
- 0x7828, 0x014e, 0x013e, 0x015e, 0x08b0, 0x0081, 0x1130, 0x7000,
- 0xa084, 0xff00, 0xa086, 0x8100, 0x1d70, 0x080c, 0xac59, 0x20e1,
- 0x3000, 0x7828, 0x7828, 0x080c, 0x642d, 0x0c58, 0xa484, 0x01ff,
- 0x6882, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac,
- 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x0005, 0x20a9,
- 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085,
- 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007,
- 0xa196, 0x0000, 0x1118, 0x0804, 0x62cf, 0x0005, 0xa196, 0x2000,
- 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c, 0x41d1, 0x0ca8,
- 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c, 0x6372, 0x0c68,
- 0x00c6, 0x6a80, 0x82ff, 0x0904, 0x61c0, 0x7110, 0xa18c, 0xff00,
- 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023, 0x1904, 0x61c0,
- 0xa08e, 0x0023, 0x1570, 0x080c, 0x6408, 0x0904, 0x61c0, 0x7124,
- 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034, 0xa005, 0x1904,
- 0x61c0, 0x2009, 0x0015, 0x080c, 0x80a7, 0x0804, 0x61c0, 0xa08e,
- 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c,
- 0x80a7, 0x0804, 0x61c0, 0xa08e, 0x0100, 0x1904, 0x61c0, 0x7034,
- 0xa005, 0x1904, 0x61c0, 0x2009, 0x0016, 0x080c, 0x80a7, 0x0804,
- 0x61c0, 0xa08e, 0x0022, 0x1904, 0x61c0, 0x7030, 0xa08e, 0x0300,
- 0x1580, 0x68d0, 0xd0a4, 0x0528, 0xc0b5, 0x68d2, 0x7100, 0xa18c,
- 0x00ff, 0x696e, 0x7004, 0x6872, 0x00f6, 0x2079, 0x0100, 0x79e6,
- 0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x26a0,
- 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x2676, 0x694e,
- 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0xad00, 0x70a2,
- 0x00ee, 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, 0x0017, 0x0804,
- 0x6193, 0xa08e, 0x0400, 0x1158, 0x7034, 0xa005, 0x1904, 0x61c0,
- 0x68d0, 0xc0a5, 0x68d2, 0x2009, 0x0030, 0x0804, 0x6193, 0xa08e,
- 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, 0x0018,
- 0x0804, 0x6193, 0xa08e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804,
- 0x6193, 0xa08e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x6193,
- 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009,
- 0x001b, 0x0804, 0x6193, 0xa08e, 0x5000, 0x1140, 0x7034, 0xa005,
- 0x1904, 0x61c0, 0x2009, 0x001c, 0x0804, 0x6193, 0xa08e, 0x1300,
- 0x1120, 0x2009, 0x0034, 0x0804, 0x6193, 0xa08e, 0x1200, 0x1140,
- 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, 0x0024, 0x0804, 0x6193,
- 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1118, 0x2009, 0x002d, 0x04d8,
- 0xa08c, 0xff00, 0xa18e, 0x5300, 0x1118, 0x2009, 0x002a, 0x0498,
- 0xa08e, 0x0f00, 0x1118, 0x2009, 0x0020, 0x0468, 0xa08e, 0x5300,
- 0x1108, 0x00d8, 0xa08e, 0x6104, 0x11c0, 0x2011, 0xb28d, 0x8208,
- 0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015,
- 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3c5c, 0x004e, 0x8108,
- 0x1f04, 0x6176, 0x2009, 0x0023, 0x0070, 0xa08e, 0x6000, 0x1118,
- 0x2009, 0x003f, 0x0040, 0xa08e, 0x7800, 0x1118, 0x2009, 0x0045,
- 0x0010, 0x2009, 0x001d, 0x0016, 0x2011, 0xb283, 0x2204, 0x8211,
- 0x220c, 0x080c, 0x2676, 0x1530, 0x080c, 0x4c80, 0x1518, 0x6612,
- 0x6516, 0x86ff, 0x0180, 0x001e, 0x0016, 0xa186, 0x0017, 0x1158,
- 0x686c, 0xa606, 0x1140, 0x6870, 0xa506, 0xa084, 0xff00, 0x1118,
- 0x6000, 0xc0f5, 0x6002, 0x00c6, 0x080c, 0x8022, 0x0168, 0x001e,
- 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x80a7,
- 0x00ce, 0x0005, 0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00c6, 0x0046,
- 0x080c, 0x6221, 0x1904, 0x621e, 0xa184, 0xff00, 0x8007, 0xa086,
- 0x0008, 0x1904, 0x621e, 0xa28e, 0x0033, 0x11e8, 0x080c, 0x6408,
- 0x0904, 0x621e, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140,
- 0x7034, 0xa005, 0x15d8, 0x2009, 0x0015, 0x080c, 0x80a7, 0x04b0,
- 0xa08e, 0x0100, 0x1598, 0x7034, 0xa005, 0x1580, 0x2009, 0x0016,
- 0x080c, 0x80a7, 0x0458, 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e,
- 0x1400, 0x1520, 0x2009, 0x0038, 0x0016, 0x2011, 0xb283, 0x2204,
- 0x8211, 0x220c, 0x080c, 0x2676, 0x11c0, 0x080c, 0x4c80, 0x11a8,
- 0x6612, 0x6516, 0x00c6, 0x080c, 0x8022, 0x0170, 0x001e, 0x611a,
- 0x080c, 0x9956, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c,
- 0x80a7, 0x080c, 0x6c50, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce,
- 0x0005, 0x00f6, 0x00d6, 0x0026, 0x0016, 0x0136, 0x0146, 0x0156,
- 0x3c00, 0x0006, 0x2079, 0x0030, 0x2069, 0x0200, 0x080c, 0x1df2,
- 0x1590, 0x080c, 0x1ce2, 0x05c8, 0x04d9, 0x1130, 0x7908, 0xa18c,
- 0x1fff, 0xa182, 0x0011, 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000,
- 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a,
- 0x2004, 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0401,
- 0x1120, 0xa08a, 0x0140, 0x1a0c, 0x14f6, 0x80ac, 0x20e1, 0x6000,
- 0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803,
- 0x0004, 0xa294, 0x0070, 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e,
- 0x001e, 0x002e, 0x00de, 0x00fe, 0x0005, 0xa085, 0x0001, 0x0c98,
- 0x0006, 0x2001, 0x0111, 0x2004, 0xa084, 0x0003, 0x000e, 0x0005,
- 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0xa696, 0x00ff, 0x1198,
- 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x62ca, 0xa596,
- 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, 0xa596, 0xfffc, 0x1118,
- 0x2009, 0x0080, 0x04b8, 0x2011, 0x0000, 0x2019, 0xad34, 0x231c,
- 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xae34,
- 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, 0xaeb5, 0x2e1c,
- 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, 0xc2fd, 0x0080, 0x2368,
- 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e, 0x6b14, 0x1120, 0xa346,
- 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110, 0x83ff, 0x0d58, 0x8420,
- 0x8e70, 0x1f04, 0x62a7, 0x82ff, 0x1118, 0xa085, 0x0001, 0x0018,
- 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, 0x004e, 0x0005, 0xa084,
- 0x0007, 0x000a, 0x0005, 0x62db, 0x62db, 0x62db, 0x641a, 0x62db,
- 0x62dc, 0x62f1, 0x635d, 0x0005, 0x7110, 0xd1bc, 0x0188, 0x7120,
- 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, 0xb400, 0x0248, 0x6858,
- 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, 0x80a7,
- 0x0005, 0x00c6, 0x7110, 0xd1bc, 0x1904, 0x6344, 0x2011, 0xb283,
- 0x2204, 0x8211, 0x220c, 0x080c, 0x2676, 0x1904, 0x6344, 0x080c,
- 0x4c80, 0x1904, 0x6344, 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15e0,
- 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0160, 0x080c,
- 0x574f, 0x11d0, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x11a0,
- 0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0530,
- 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x2009,
- 0x0044, 0x080c, 0x80a7, 0x00c0, 0x00c6, 0x080c, 0x8022, 0x001e,
- 0x0198, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004,
- 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001,
- 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00ce, 0x0005, 0x00c6, 0x080c,
- 0x9807, 0x001e, 0x0dc8, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a,
- 0x7130, 0x6152, 0x6013, 0x0300, 0x6003, 0x0001, 0x6007, 0x0041,
- 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0c38, 0x7110, 0xd1bc, 0x0188,
- 0x7020, 0x2060, 0xac84, 0x0007, 0x1160, 0xac82, 0xb400, 0x0248,
- 0x6858, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0045, 0x080c,
- 0x80a7, 0x0005, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000,
- 0x1130, 0xa084, 0x000f, 0xa08a, 0x0006, 0x1208, 0x000b, 0x0005,
- 0x6386, 0x6387, 0x6386, 0x6386, 0x63f0, 0x63fc, 0x0005, 0x7110,
- 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x63ef, 0x700c, 0x7108,
- 0x080c, 0x2676, 0x1904, 0x63ef, 0x080c, 0x4c80, 0x1904, 0x63ef,
- 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x01f8, 0xa28c, 0x00ff,
- 0xa186, 0x0004, 0x0118, 0xa186, 0x0006, 0x15c8, 0x00c6, 0x080c,
- 0x6408, 0x00ce, 0x0904, 0x63ef, 0x00c6, 0x080c, 0x8022, 0x001e,
- 0x05f0, 0x611a, 0x080c, 0x9956, 0x601f, 0x0002, 0x7120, 0x610a,
- 0x2009, 0x0088, 0x080c, 0x80a7, 0x0490, 0xa28c, 0x00ff, 0xa186,
- 0x0006, 0x0160, 0xa186, 0x0004, 0x0148, 0xa294, 0xff00, 0x8217,
- 0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1188, 0x00c6, 0x080c,
- 0x8022, 0x001e, 0x01e0, 0x611a, 0x080c, 0x9956, 0x601f, 0x0005,
- 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x80a7, 0x0080, 0x00c6,
- 0x080c, 0x8022, 0x001e, 0x0158, 0x611a, 0x080c, 0x9956, 0x601f,
- 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0x80a7, 0x0005,
- 0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, 0x7124, 0x610a, 0x2009,
- 0x0089, 0x080c, 0x80a7, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x0041,
- 0x0130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x80a7, 0x0005,
- 0x7020, 0x2060, 0xac84, 0x0007, 0x1158, 0xac82, 0xb400, 0x0240,
- 0x2001, 0xad16, 0x2004, 0xac02, 0x1218, 0xa085, 0x0001, 0x0005,
- 0xa006, 0x0ce8, 0x7110, 0xd1bc, 0x1178, 0x7024, 0x2060, 0xac84,
- 0x0007, 0x1150, 0xac82, 0xb400, 0x0238, 0x6858, 0xac02, 0x1220,
- 0x2009, 0x0051, 0x080c, 0x80a7, 0x0005, 0x2031, 0x0105, 0x0069,
- 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029,
- 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, 0x00f6,
- 0x7000, 0xa084, 0xf000, 0xa086, 0xc000, 0x05b0, 0x080c, 0x8022,
- 0x0598, 0x0066, 0x00c6, 0x0046, 0x2011, 0xb283, 0x2204, 0x8211,
- 0x220c, 0x080c, 0x2676, 0x1580, 0x080c, 0x4c80, 0x1568, 0x6612,
- 0x6516, 0x2c00, 0x004e, 0x00ce, 0x601a, 0x080c, 0x9956, 0x080c,
- 0x15d9, 0x01f0, 0x2d00, 0x6056, 0x6803, 0x0000, 0x6837, 0x0000,
- 0x6c3a, 0xadf8, 0x000f, 0x20a9, 0x000e, 0x2fa0, 0x2e98, 0x53a3,
- 0x006e, 0x6612, 0x6007, 0x003e, 0x601f, 0x0001, 0x6003, 0x0001,
- 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00fe, 0x00de, 0x00ce, 0x0005,
- 0x080c, 0x8078, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x2071,
- 0xafda, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7012,
- 0x7017, 0xb400, 0x7007, 0x0000, 0x7026, 0x702b, 0x7841, 0x7032,
- 0x7037, 0x789d, 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, 0x7047,
- 0x41b3, 0x0005, 0x2071, 0xafda, 0x1d04, 0x64fc, 0x2091, 0x6000,
- 0x700c, 0x8001, 0x700e, 0x1180, 0x700f, 0x0361, 0x7007, 0x0001,
- 0x0126, 0x2091, 0x8000, 0x7040, 0xa00d, 0x0148, 0x8109, 0x7142,
- 0x1130, 0x7044, 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024,
- 0xa00d, 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009,
- 0x8109, 0x7126, 0xa186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff,
- 0x1110, 0x7028, 0x080f, 0x7030, 0xa00d, 0x0158, 0x702c, 0x8001,
- 0x702e, 0x1138, 0x702f, 0x0009, 0x8109, 0x7132, 0x1110, 0x7034,
- 0x080f, 0x7038, 0xa005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c,
- 0xa005, 0x0118, 0x0310, 0x8001, 0x703e, 0x7018, 0xa00d, 0x0158,
- 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a,
- 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x6522, 0x6523,
- 0x653b, 0x00e6, 0x2071, 0xafda, 0x7018, 0xa005, 0x1120, 0x711a,
- 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071,
- 0xafda, 0x701c, 0xa206, 0x1110, 0x701a, 0x701e, 0x000e, 0x00ee,
- 0x0005, 0x00e6, 0x2071, 0xafda, 0x6088, 0xa102, 0x0208, 0x618a,
- 0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x4cdc, 0x1158, 0x6088,
- 0x8001, 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c,
- 0x6c50, 0x012e, 0x8108, 0xa182, 0x00ff, 0x0218, 0xa00e, 0x7007,
- 0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000,
- 0x603c, 0xa005, 0x0128, 0x8001, 0x603e, 0x1110, 0x080c, 0x9846,
- 0x6014, 0xa005, 0x0500, 0x8001, 0x6016, 0x11e8, 0x611c, 0xa186,
- 0x0003, 0x0118, 0xa186, 0x0006, 0x11a0, 0x6010, 0x2068, 0x6854,
- 0xa08a, 0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a,
- 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116,
- 0x0010, 0x080c, 0x9350, 0x012e, 0xac88, 0x0018, 0x7116, 0x2001,
- 0xe400, 0xa102, 0x0220, 0x7017, 0xb400, 0x7007, 0x0000, 0x0005,
- 0x00e6, 0x2071, 0xafda, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee,
- 0x0005, 0x2001, 0xafe3, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071,
- 0xafda, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0xafe6,
- 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0xafda, 0x711a, 0x721e,
- 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x2061, 0xb048, 0x00ce,
- 0x0005, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0xb048,
- 0x2060, 0x0005, 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999,
- 0xa005, 0x1150, 0x00c6, 0x2061, 0xb048, 0x6014, 0x00ce, 0xa005,
- 0x1138, 0x2001, 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006,
- 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0,
- 0xa18e, 0x00c0, 0x05b0, 0xd0b4, 0x1138, 0xd0bc, 0x1528, 0x2009,
- 0x0006, 0x080c, 0x661a, 0x0005, 0xd0fc, 0x0130, 0xa084, 0x0003,
- 0x0118, 0xa086, 0x0003, 0x15c0, 0x6020, 0xd0d4, 0x0130, 0xc0d4,
- 0x6022, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xad73, 0x2104,
- 0xd084, 0x0128, 0x2009, 0x0042, 0x080c, 0x80a7, 0x0005, 0x2009,
- 0x0043, 0x080c, 0x80a7, 0x0005, 0xd0fc, 0x0130, 0xa084, 0x0003,
- 0x0118, 0xa086, 0x0003, 0x11c0, 0x2009, 0x0042, 0x080c, 0x80a7,
- 0x0005, 0xd0fc, 0x0150, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0138,
- 0x2009, 0x0041, 0x080c, 0x80a7, 0x0005, 0x0051, 0x0ce8, 0x2009,
- 0x0043, 0x080c, 0x80a7, 0x0cc0, 0x2009, 0x0004, 0x0019, 0x0005,
- 0x2009, 0x0001, 0x00d6, 0x6010, 0xa0ec, 0xf000, 0x01f0, 0x2068,
- 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x1188, 0x694c, 0xa18c,
- 0x8100, 0xa18e, 0x8100, 0x1158, 0x00c6, 0x2061, 0xb048, 0x6200,
- 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c,
- 0x510c, 0x6010, 0xa06d, 0x190c, 0x65aa, 0x00de, 0x0005, 0x0156,
- 0x00c6, 0x2061, 0xb048, 0x6000, 0x81ff, 0x0110, 0xa205, 0x0008,
- 0xa204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138,
- 0x6808, 0xa005, 0x0120, 0x8001, 0x680a, 0xa085, 0x0001, 0x0005,
- 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200,
- 0x1f04, 0x665c, 0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010,
- 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a,
- 0x1220, 0x1f04, 0x666c, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04,
- 0x666c, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e,
- 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, 0x0126, 0x2091,
- 0x2800, 0x2079, 0xafc7, 0x012e, 0x00d6, 0x2069, 0xafc7, 0x6803,
- 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a, 0x00de,
- 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0xa084, 0x0007, 0x0002,
- 0x66aa, 0x66cb, 0x671e, 0x66b0, 0x66cb, 0x66aa, 0x66a8, 0x66a8,
- 0x080c, 0x14f6, 0x080c, 0x6581, 0x080c, 0x6c50, 0x00ce, 0x0005,
- 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x481b, 0x080c,
- 0x650d, 0x7828, 0xa092, 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c,
- 0x4855, 0x0c88, 0x080c, 0x481b, 0x7807, 0x0003, 0x7827, 0x0000,
- 0x782b, 0x0000, 0x0c40, 0x080c, 0x6581, 0x3c00, 0x0006, 0x2011,
- 0x0209, 0x20e1, 0x4000, 0x2214, 0x000e, 0x20e0, 0x82ff, 0x0178,
- 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c,
- 0x14f6, 0x2009, 0x0013, 0x080c, 0x80a7, 0x00ce, 0x0005, 0x3900,
- 0xa082, 0xb0e8, 0x1210, 0x080c, 0x7d8d, 0x00c6, 0x7824, 0xa065,
- 0x090c, 0x14f6, 0x7804, 0xa086, 0x0004, 0x0904, 0x675e, 0x7828,
- 0xa092, 0x2710, 0x1230, 0x8000, 0x782a, 0x00ce, 0x080c, 0x7827,
- 0x0c20, 0x6104, 0xa186, 0x0003, 0x1188, 0x00e6, 0x2071, 0xad00,
- 0x70dc, 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100,
- 0x2071, 0xad00, 0x080c, 0x485e, 0x00ee, 0x00ce, 0x080c, 0xaca2,
- 0x2009, 0x0014, 0x080c, 0x80a7, 0x00ce, 0x0838, 0x2001, 0xafe3,
- 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824,
- 0xa065, 0x090c, 0x14f6, 0x2009, 0x0013, 0x080c, 0x80fb, 0x00ce,
- 0x0005, 0x00c6, 0x00d6, 0x3900, 0xa082, 0xb0e8, 0x1210, 0x080c,
- 0x7d8d, 0x7824, 0xa005, 0x090c, 0x14f6, 0x781c, 0xa06d, 0x090c,
- 0x14f6, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, 0x080c, 0x8078,
- 0x693c, 0x81ff, 0x090c, 0x14f6, 0x8109, 0x693e, 0x6854, 0xa015,
- 0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827,
- 0x0000, 0x00de, 0x00ce, 0x080c, 0x6c50, 0x0888, 0x6104, 0xa186,
- 0x0002, 0x0128, 0xa186, 0x0004, 0x0110, 0x0804, 0x66f7, 0x7808,
- 0xac06, 0x0904, 0x66f7, 0x080c, 0x6b73, 0x080c, 0x67ee, 0x00ce,
- 0x080c, 0x6c50, 0x0804, 0x66e5, 0x00c6, 0x6027, 0x0002, 0x62c8,
- 0x60c4, 0xa205, 0x1178, 0x793c, 0xa1e5, 0x0000, 0x0130, 0x2009,
- 0x0049, 0x080c, 0x80a7, 0x00ce, 0x0005, 0x2011, 0xafe6, 0x2013,
- 0x0000, 0x0cc8, 0x3908, 0xa192, 0xb0e8, 0x1210, 0x080c, 0x7d8d,
- 0x793c, 0x81ff, 0x0d90, 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e,
- 0x0006, 0x1138, 0x6014, 0xa084, 0x0184, 0xa085, 0x0012, 0x6016,
- 0x0c10, 0x6014, 0xa084, 0x0184, 0xa085, 0x0016, 0x6016, 0x08d8,
- 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000,
- 0x2c08, 0x2061, 0xafc7, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005,
- 0x0148, 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e,
- 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0xafc7,
- 0x6000, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001,
- 0x1110, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, 0x6c56,
- 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, 0x0000,
- 0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0xafc7, 0x0c18,
- 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016,
- 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061,
- 0xafc7, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, 0xa080,
- 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005,
- 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061,
- 0xafc7, 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, 0x6136,
- 0x00ce, 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6,
- 0x00c6, 0x0076, 0x0066, 0x0026, 0x0016, 0x0006, 0x0126, 0x2071,
- 0xafc7, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904,
- 0x6889, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x6884,
- 0x87ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6884, 0x703c, 0xac06,
- 0x1170, 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, 0x7033, 0x0000,
- 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x003e, 0x7038,
- 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00,
- 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c,
- 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f,
- 0x0000, 0x080c, 0x9596, 0x0198, 0x6010, 0x2068, 0x601c, 0xa086,
- 0x0003, 0x1510, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c,
- 0x97fd, 0x080c, 0xabfa, 0x080c, 0x510c, 0x080c, 0x9742, 0x080c,
- 0x974e, 0x00ce, 0x0804, 0x682e, 0x2c78, 0x600c, 0x2060, 0x0804,
- 0x682e, 0x012e, 0x000e, 0x001e, 0x002e, 0x006e, 0x007e, 0x00ce,
- 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19d0,
- 0x080c, 0xabfa, 0x080c, 0xa91f, 0x0c10, 0x0006, 0x0066, 0x00c6,
- 0x00d6, 0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, 0x2079,
- 0xafc7, 0x7838, 0xa065, 0x0558, 0x600c, 0x0006, 0x600f, 0x0000,
- 0x783c, 0xac06, 0x1170, 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64,
- 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000,
- 0x003e, 0x080c, 0x9596, 0x0178, 0x6010, 0x2068, 0x601c, 0xa086,
- 0x0003, 0x11b0, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c,
- 0x510c, 0x080c, 0x9742, 0x080c, 0x974e, 0x000e, 0x0898, 0x7e3a,
- 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005,
- 0x601c, 0xa086, 0x0006, 0x1d30, 0x080c, 0xa91f, 0x0c60, 0x0016,
- 0x0026, 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x69a9, 0x008e,
- 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0xafc7, 0x2091,
- 0x8000, 0x080c, 0x6a36, 0x080c, 0x6aa8, 0x012e, 0x00fe, 0x0005,
- 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126,
- 0x2091, 0x8000, 0x2071, 0xafc7, 0x7614, 0x2660, 0x2678, 0x8cff,
- 0x0904, 0x6985, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904,
- 0x6980, 0x88ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6980, 0x7024,
- 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c,
- 0x6581, 0x080c, 0x7834, 0x68c3, 0x0000, 0x080c, 0x7ca8, 0x7027,
- 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120,
- 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
- 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a,
- 0x04b8, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36,
- 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013,
- 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008,
- 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9596, 0x0188,
- 0x601c, 0xa086, 0x0003, 0x1510, 0x6837, 0x0103, 0x6b4a, 0x6847,
- 0x0000, 0x080c, 0x97fd, 0x080c, 0xabfa, 0x080c, 0x510c, 0x080c,
- 0x9742, 0x080c, 0x974e, 0x080c, 0x7b88, 0x00ce, 0x0804, 0x690f,
- 0x2c78, 0x600c, 0x2060, 0x0804, 0x690f, 0x012e, 0x000e, 0x001e,
- 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086,
- 0x0006, 0x1128, 0x080c, 0xabfa, 0x080c, 0xa91f, 0x0c10, 0x601c,
- 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, 0x0968, 0x08c8,
- 0x601c, 0xa086, 0x0005, 0x19a8, 0x6004, 0xa086, 0x0085, 0x0d50,
- 0x0880, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0xa280, 0xae34,
- 0x2004, 0xa065, 0x0904, 0x6a32, 0x00f6, 0x00e6, 0x00d6, 0x0066,
- 0x2071, 0xafc7, 0x6654, 0x7018, 0xac06, 0x1108, 0x761a, 0x701c,
- 0xac06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e,
- 0x6058, 0xa07d, 0x0108, 0x7e56, 0xa6ed, 0x0000, 0x0110, 0x2f00,
- 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc,
- 0x6002, 0x080c, 0x4c07, 0x0904, 0x6a2e, 0x7624, 0x86ff, 0x05e8,
- 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100,
- 0x68c0, 0xa005, 0x0548, 0x080c, 0x6581, 0x080c, 0x7834, 0x68c3,
- 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140,
- 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000,
- 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e,
- 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660,
- 0x080c, 0x974e, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003,
- 0x0009, 0x630a, 0x00ce, 0x0804, 0x69d9, 0x8dff, 0x0158, 0x6837,
- 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x97fd, 0x080c, 0xabfa,
- 0x080c, 0x510c, 0x080c, 0x7b88, 0x0804, 0x69d9, 0x006e, 0x00de,
- 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066,
- 0x00c6, 0x00d6, 0x2031, 0x0000, 0x7814, 0xa065, 0x0904, 0x6a88,
- 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, 0xac06, 0x1540, 0x2069,
- 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x6581, 0x080c, 0x7834,
- 0x68c3, 0x0000, 0x080c, 0x7ca8, 0x7827, 0x0000, 0x0036, 0x2069,
- 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803,
- 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001,
- 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6010,
- 0x2068, 0x080c, 0x9596, 0x0168, 0x601c, 0xa086, 0x0003, 0x11b8,
- 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, 0x080c,
- 0x9742, 0x080c, 0x974e, 0x080c, 0x7b88, 0x000e, 0x0804, 0x6a3d,
- 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c,
- 0xa086, 0x0006, 0x1118, 0x080c, 0xa91f, 0x0c58, 0x601c, 0xa086,
- 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, 0x09d0, 0x0c10, 0x601c,
- 0xa086, 0x0005, 0x19f0, 0x6004, 0xa086, 0x0085, 0x0d60, 0x08c8,
- 0x0006, 0x0066, 0x00c6, 0x00d6, 0x7818, 0xa065, 0x0904, 0x6b0e,
- 0x6054, 0x0006, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4,
- 0xc0dc, 0x6002, 0x080c, 0x4c07, 0x0904, 0x6b0b, 0x7e24, 0x86ff,
- 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069,
- 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, 0x6581, 0x080c, 0x7834,
- 0x68c3, 0x0000, 0x080c, 0x7ca8, 0x7827, 0x0000, 0x0036, 0x2069,
- 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803,
- 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001,
- 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e,
- 0x2660, 0x080c, 0x974e, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660,
- 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x6aba, 0x8dff, 0x0138,
- 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, 0x080c,
- 0x7b88, 0x0804, 0x6aba, 0x000e, 0x0804, 0x6aad, 0x781e, 0x781a,
- 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066,
- 0x6000, 0xd0dc, 0x0188, 0x604c, 0xa06d, 0x0170, 0x6848, 0xa606,
- 0x1158, 0x2071, 0xafc7, 0x7024, 0xa035, 0x0130, 0xa080, 0x0004,
- 0x2004, 0xad06, 0x1108, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005,
- 0x00f6, 0x2079, 0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660,
- 0x6003, 0x0009, 0x630a, 0x00ce, 0x04a0, 0x080c, 0x7834, 0x78c3,
- 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140,
- 0x7b04, 0xa384, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000,
- 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c,
- 0x7ca8, 0x003e, 0x080c, 0x4c07, 0x00c6, 0x603c, 0xa005, 0x0110,
- 0x8001, 0x603e, 0x2660, 0x080c, 0x8078, 0x00ce, 0x6837, 0x0103,
- 0x6b4a, 0x6847, 0x0000, 0x080c, 0x97fd, 0x080c, 0x510c, 0x080c,
- 0x7b88, 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2071, 0xafc7, 0x7004,
- 0xa084, 0x0007, 0x0002, 0x6b85, 0x6b88, 0x6b9e, 0x6bb7, 0x6bf0,
- 0x6b85, 0x6b83, 0x6b83, 0x080c, 0x14f6, 0x00ce, 0x00ee, 0x0005,
- 0x7024, 0xa065, 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015,
- 0x0150, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000,
- 0x00ce, 0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060,
- 0x080c, 0x4c07, 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022,
- 0x0120, 0x6054, 0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027,
- 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024,
- 0xa065, 0x0598, 0x700c, 0xac06, 0x1160, 0x080c, 0x7b88, 0x600c,
- 0xa015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0428, 0x720e, 0x720a,
- 0x0410, 0x7014, 0xac06, 0x1160, 0x080c, 0x7b88, 0x600c, 0xa015,
- 0x0120, 0x7216, 0x600f, 0x0000, 0x00b0, 0x7216, 0x7212, 0x0098,
- 0x6018, 0x2060, 0x080c, 0x4c07, 0x6000, 0xc0dc, 0x6002, 0x080c,
- 0x7b88, 0x701c, 0xa065, 0x0138, 0x6054, 0xa015, 0x0110, 0x721e,
- 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005,
- 0x7024, 0xa065, 0x0140, 0x080c, 0x7b88, 0x600c, 0xa015, 0x0150,
- 0x720e, 0x600f, 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x00ce,
- 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, 0x2069, 0xafc7,
- 0x6830, 0xa084, 0x0003, 0x0002, 0x6c12, 0x6c14, 0x6c38, 0x6c10,
- 0x080c, 0x14f6, 0x00de, 0x0005, 0x00c6, 0x6840, 0xa086, 0x0001,
- 0x01b8, 0x683c, 0xa065, 0x0130, 0x600c, 0xa015, 0x0170, 0x6a3a,
- 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, 0xafe6,
- 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, 0x0c90,
- 0x6843, 0x0000, 0x6838, 0xa065, 0x0d68, 0x6003, 0x0003, 0x0c50,
- 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0168,
- 0x600c, 0xa015, 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000,
- 0x0020, 0x683f, 0x0000, 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005,
- 0x00d6, 0x2069, 0xafc7, 0x6804, 0xa084, 0x0007, 0x0002, 0x6c61,
- 0x6cfd, 0x6cfd, 0x6cfd, 0x6cfd, 0x6cff, 0x6c5f, 0x6c5f, 0x080c,
- 0x14f6, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c,
- 0xa065, 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c,
- 0x6d49, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150, 0x6807,
- 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x6d49, 0x00ce, 0x00de,
- 0x0005, 0x00e6, 0x0036, 0x6a1c, 0xa2f5, 0x0000, 0x0904, 0x6cf9,
- 0x704c, 0xa00d, 0x0118, 0x7088, 0xa005, 0x01a0, 0x7054, 0xa075,
- 0x0120, 0xa20e, 0x0904, 0x6cf9, 0x0028, 0x6818, 0xa20e, 0x0904,
- 0x6cf9, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005, 0x1d70,
- 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x1e40, 0x080c, 0x804f,
- 0x0904, 0x6cf9, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a, 0xa180,
- 0x0014, 0x2004, 0xa084, 0x00ff, 0x605a, 0xa180, 0x0014, 0x2003,
- 0x0000, 0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0210, 0x2001,
- 0x1999, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x00f6,
- 0x2c78, 0x71a0, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1110, 0xd1bc,
- 0x0150, 0x7100, 0xd1f4, 0x0120, 0x7114, 0xa18c, 0x00ff, 0x0040,
- 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2be6, 0x2c0d, 0xa18c, 0x00ff,
- 0x2061, 0x0100, 0x619a, 0x080c, 0x736f, 0x7300, 0xc3dd, 0x7302,
- 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003,
- 0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de,
- 0x0005, 0x003e, 0x00ee, 0x00ce, 0x0cd0, 0x00de, 0x0005, 0x00c6,
- 0x680c, 0xa065, 0x0138, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000,
- 0x080c, 0x6d49, 0x00ce, 0x00de, 0x0005, 0x00f6, 0x00d6, 0x2069,
- 0xafc7, 0x6830, 0xa086, 0x0000, 0x11c0, 0x2001, 0xad0c, 0x200c,
- 0xd1bc, 0x1550, 0x6838, 0xa07d, 0x0180, 0x6833, 0x0001, 0x683e,
- 0x6847, 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c,
- 0x1ee6, 0x1130, 0x012e, 0x080c, 0x76a5, 0x00de, 0x00fe, 0x0005,
- 0x012e, 0xe000, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015,
- 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000,
- 0x0c60, 0x683a, 0x6836, 0x0cc0, 0xc1bc, 0x2102, 0x080c, 0x57d1,
- 0x0888, 0x601c, 0xa084, 0x000f, 0x000b, 0x0005, 0x6d57, 0x6d5c,
- 0x7210, 0x732c, 0x6d5c, 0x7210, 0x732c, 0x6d57, 0x6d5c, 0x080c,
- 0x6b73, 0x080c, 0x6c50, 0x0005, 0x0156, 0x0136, 0x0146, 0x00c6,
- 0x00f6, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x14f6, 0x6118, 0x2178,
- 0x79a0, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150,
- 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009,
- 0x0000, 0x0028, 0xa1f8, 0x2be6, 0x2f0d, 0xa18c, 0x00ff, 0x2c78,
- 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, 0x1a04, 0x6dd0, 0x0033,
- 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x6e7c, 0x6ec7,
- 0x6ef4, 0x6fc1, 0x6fef, 0x6ff7, 0x701d, 0x702e, 0x703f, 0x7047,
- 0x705d, 0x7047, 0x70b7, 0x702e, 0x70d8, 0x70e0, 0x703f, 0x70e0,
- 0x70f1, 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x6dce,
- 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x790d, 0x7932, 0x7947, 0x796a,
- 0x798b, 0x701d, 0x6dce, 0x701d, 0x7047, 0x6dce, 0x6ef4, 0x6fc1,
- 0x6dce, 0x7daa, 0x7047, 0x6dce, 0x7dca, 0x7047, 0x6dce, 0x703f,
- 0x6e75, 0x6de0, 0x6dce, 0x7def, 0x7e64, 0x7f3b, 0x6dce, 0x7f4c,
- 0x7018, 0x7f68, 0x6dce, 0x79a0, 0x7fc3, 0x6dce, 0x080c, 0x14f6,
- 0x2100, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005,
- 0x6dde, 0x6dde, 0x6dde, 0x6e14, 0x6e32, 0x6e48, 0x080c, 0x14f6,
- 0x00d6, 0x20a1, 0x020b, 0x080c, 0x710e, 0x7810, 0x2068, 0x20a3,
- 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6850,
- 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
- 0x0018, 0x080c, 0x7821, 0x00de, 0x0005, 0x00d6, 0x7818, 0x2068,
- 0x68a0, 0x2069, 0xad00, 0x6ad0, 0xd2ac, 0x1110, 0xd0bc, 0x0110,
- 0xa085, 0x0001, 0x00de, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c,
- 0x710e, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8, 0x000f,
- 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814, 0x20a2,
- 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, 0x0010, 0x080c, 0x7821,
- 0x00de, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x710e,
- 0x20a3, 0x7800, 0x20a3, 0x0000, 0x7808, 0x8007, 0x20a2, 0x20a3,
- 0x0000, 0x60c3, 0x0008, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005,
- 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200,
- 0x20a3, 0x0000, 0x20a3, 0xdf10, 0x20a3, 0x0034, 0x2099, 0xad05,
- 0x20a9, 0x0004, 0x53a6, 0x2099, 0xad01, 0x20a9, 0x0004, 0x53a6,
- 0x2099, 0xafad, 0x20a9, 0x001a, 0x3304, 0x8007, 0x20a2, 0x9398,
- 0x1f04, 0x6e64, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c,
- 0x080c, 0x7821, 0x014e, 0x015e, 0x0005, 0x2001, 0xad14, 0x2004,
- 0x609a, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, 0x080c, 0x710e,
- 0x20a3, 0x5200, 0x20a3, 0x0000, 0x00d6, 0x2069, 0xad51, 0x6804,
- 0xd084, 0x0150, 0x6828, 0x20a3, 0x0000, 0x0016, 0x080c, 0x268a,
- 0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a9, 0x0004, 0x2099, 0xad05, 0x53a6, 0x20a9, 0x0004,
- 0x2099, 0xad01, 0x53a6, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1138,
- 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, 0x2001,
- 0xad1b, 0x20a6, 0x2001, 0xad1c, 0x20a6, 0x0040, 0x20a3, 0x0000,
- 0x2001, 0xad14, 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7821, 0x0005, 0x20a1,
- 0x020b, 0x080c, 0x710e, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001,
- 0xad34, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004,
- 0xa082, 0x007f, 0x0238, 0x2001, 0xad1b, 0x20a6, 0x2001, 0xad1c,
- 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xad14, 0x2004, 0xa084,
- 0x00ff, 0x20a2, 0x20a9, 0x0004, 0x2099, 0xad05, 0x53a6, 0x60c3,
- 0x0010, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, 0x080c, 0x710e,
- 0x00c6, 0x7818, 0x2060, 0x2001, 0x0000, 0x080c, 0x5037, 0x00ce,
- 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1130, 0x20a3,
- 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0010, 0x20a3, 0x0300, 0x20a3,
- 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1904,
- 0x6f83, 0x2001, 0xad34, 0x2004, 0xd0a4, 0x01c8, 0x2099, 0xaf8d,
- 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x3304, 0xa084, 0x2000,
- 0x20a2, 0x9398, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x2001,
- 0x2710, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x33a6, 0x00d0, 0x2099,
- 0xaf8d, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, 0x080c, 0x574f,
- 0x1118, 0xa084, 0x37ff, 0x0010, 0xa084, 0x3fff, 0x20a2, 0x9398,
- 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a9, 0x0004, 0x2099, 0xad05, 0x53a6, 0x20a9, 0x0004,
- 0x2099, 0xad01, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04,
- 0x6f5d, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x6f63, 0x2099,
- 0xaf95, 0x3304, 0xc0dd, 0x20a2, 0x2001, 0xad71, 0x2004, 0xd0e4,
- 0x0158, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398,
- 0x33a6, 0x20a9, 0x0004, 0x0010, 0x20a9, 0x0007, 0x20a3, 0x0000,
- 0x1f04, 0x6f7e, 0x0468, 0x2001, 0xad34, 0x2004, 0xd0a4, 0x0140,
- 0x2001, 0xaf8e, 0x2004, 0x60e3, 0x0000, 0x080c, 0x26cb, 0x60e2,
- 0x2099, 0xaf8d, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099,
- 0xad05, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xad01, 0x53a6, 0x20a9,
- 0x0008, 0x20a3, 0x0000, 0x1f04, 0x6fa1, 0x20a9, 0x0008, 0x20a3,
- 0x0000, 0x1f04, 0x6fa7, 0x2099, 0xaf95, 0x20a9, 0x0008, 0x53a6,
- 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x6fb2, 0x20a9, 0x000a,
- 0x20a3, 0x0000, 0x1f04, 0x6fb8, 0x60c3, 0x0074, 0x080c, 0x7821,
- 0x0005, 0x20a1, 0x020b, 0x080c, 0x710e, 0x20a3, 0x2010, 0x20a3,
- 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2,
- 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xad51, 0x7904, 0x00fe,
- 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010,
- 0xa085, 0x0002, 0x00d6, 0x0804, 0x7099, 0x20a2, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x7821, 0x0005, 0x20a1,
- 0x020b, 0x080c, 0x710e, 0x20a3, 0x5000, 0x0804, 0x6f0f, 0x20a1,
- 0x020b, 0x080c, 0x710e, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x7821, 0x0005,
- 0x20a1, 0x020b, 0x080c, 0x71a2, 0x0020, 0x20a1, 0x020b, 0x080c,
- 0x71aa, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x60c3, 0x0004, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b,
- 0x080c, 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003,
- 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x7821, 0x0005, 0x20a1,
- 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, 0x0804, 0x6f0f, 0x20a1,
- 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828,
- 0xa005, 0x0110, 0x20a2, 0x0010, 0x20a3, 0x0003, 0x7810, 0x20a2,
- 0x60c3, 0x0008, 0x080c, 0x7821, 0x0005, 0x00d6, 0x20a1, 0x020b,
- 0x080c, 0x71aa, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800,
- 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x1178, 0x6998, 0xa184,
- 0xc000, 0x1140, 0xd1ec, 0x0118, 0x20a3, 0x2100, 0x0040, 0x20a3,
- 0x0100, 0x0028, 0x20a3, 0x0400, 0x0010, 0x20a3, 0x0700, 0xa006,
- 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xad51,
- 0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110,
- 0xa085, 0x0010, 0x2009, 0xad73, 0x210c, 0xd184, 0x1110, 0xa085,
- 0x0002, 0x0026, 0x2009, 0xad71, 0x210c, 0xd1e4, 0x0130, 0xc0c5,
- 0xa094, 0x0030, 0xa296, 0x0010, 0x0140, 0xd1ec, 0x0130, 0xa094,
- 0x0030, 0xa296, 0x0010, 0x0108, 0xc0bd, 0x002e, 0x20a2, 0x20a2,
- 0x20a2, 0x60c3, 0x0014, 0x080c, 0x7821, 0x00de, 0x0005, 0x20a1,
- 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3,
- 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x7821, 0x0005,
- 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, 0x0804, 0x6e82,
- 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000,
- 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x7821,
- 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c,
- 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3,
- 0x0000, 0x60c3, 0x0008, 0x080c, 0x7821, 0x0005, 0x0026, 0x0036,
- 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0038, 0x0026, 0x0036,
- 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1,
- 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x11a0,
- 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffe, 0x20a3, 0x0000, 0x2011,
- 0xad14, 0x2214, 0x2001, 0xaf9d, 0x2004, 0xa005, 0x0118, 0x2011,
- 0xad1c, 0x2214, 0x22a2, 0x04d0, 0xa286, 0x007f, 0x1138, 0x00d6,
- 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x00c8, 0x2001, 0xad34,
- 0x2004, 0xd0ac, 0x1110, 0xd2bc, 0x01c8, 0xa286, 0x0080, 0x00d6,
- 0x1130, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffc, 0x0040, 0xa2e8,
- 0xae34, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069,
- 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa2e8,
- 0xae34, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de,
- 0x20a3, 0x0000, 0x2011, 0xad14, 0x2214, 0x22a2, 0xa485, 0x0029,
- 0x20a2, 0x004e, 0x003e, 0x20a3, 0x0000, 0x080c, 0x7810, 0x22a2,
- 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x002e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000,
- 0x20a3, 0x02ff, 0x2011, 0xfffc, 0x22a2, 0x00d6, 0x2069, 0xad1b,
- 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000,
- 0x08e0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3,
- 0x0000, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3300, 0x2021,
- 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2300, 0x2021,
- 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
- 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e,
- 0x02d8, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa305, 0x20a2,
- 0x6814, 0x20a2, 0x6810, 0xa005, 0x1140, 0x6814, 0xa005, 0x1128,
- 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0028, 0x2069, 0xad1b, 0x2da6,
- 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa0e8, 0xae34, 0x2d6c,
- 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000,
- 0x2011, 0xad14, 0x2214, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3,
- 0x0000, 0x004e, 0x003e, 0x080c, 0x7810, 0x22a2, 0x20a3, 0x0000,
- 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e,
- 0x0005, 0x080c, 0x7810, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
- 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005,
- 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x14f6, 0xa08a,
- 0x008c, 0x1a0c, 0x14f6, 0x6118, 0x2178, 0x79a0, 0x2011, 0xad34,
- 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120,
- 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8,
- 0x2be6, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a,
- 0xa082, 0x0085, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x7247, 0x7251,
- 0x726c, 0x7245, 0x7245, 0x7245, 0x7247, 0x080c, 0x14f6, 0x0146,
- 0x20a1, 0x020b, 0x04a1, 0x60c3, 0x0000, 0x080c, 0x7821, 0x014e,
- 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x72b8, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000,
- 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c,
- 0x080c, 0x7821, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c,
- 0x72f2, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x60c3, 0x0004, 0x080c, 0x7821, 0x014e, 0x0005, 0x0026,
- 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
- 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288,
- 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2,
- 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
- 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x8100,
- 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14,
- 0x2214, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0804, 0x7175,
- 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
- 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e,
- 0x0288, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x8400,
- 0x20a2, 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6,
- 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085,
- 0x8400, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011,
- 0xad14, 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000,
- 0x0804, 0x7201, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
- 0xa080, 0x0028, 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118,
- 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810,
- 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6,
- 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c,
- 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3,
- 0x0000, 0x2011, 0xad14, 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2,
- 0x20a3, 0x0000, 0x0804, 0x7201, 0x00c6, 0x00f6, 0x2c78, 0x7804,
- 0xa08a, 0x0040, 0x0a0c, 0x14f6, 0xa08a, 0x0053, 0x1a0c, 0x14f6,
- 0x7918, 0x2160, 0x61a0, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110,
- 0xd1bc, 0x0150, 0x6100, 0xd1f4, 0x0120, 0x6114, 0xa18c, 0x00ff,
- 0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2be6, 0x2c0d, 0xa18c,
- 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, 0x0040, 0x001b, 0x00fe,
- 0x00ce, 0x0005, 0x736f, 0x747b, 0x7418, 0x761a, 0x736d, 0x736d,
- 0x736d, 0x736d, 0x736d, 0x736d, 0x736d, 0x7b41, 0x7b51, 0x7b61,
- 0x7b71, 0x736d, 0x7f79, 0x736d, 0x7b30, 0x080c, 0x14f6, 0x00d6,
- 0x0156, 0x0146, 0x780b, 0xffff, 0x20a1, 0x020b, 0x080c, 0x73cf,
- 0x7910, 0x2168, 0x6948, 0x7952, 0x21a2, 0xa016, 0x22a2, 0x22a2,
- 0x22a2, 0x694c, 0xa184, 0x000f, 0x1118, 0x2001, 0x0005, 0x0040,
- 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0xa084, 0x0006, 0x8004,
- 0x0016, 0x2008, 0x7858, 0xa084, 0x00ff, 0x8007, 0xa105, 0x001e,
- 0x20a2, 0xd1ac, 0x0118, 0x20a3, 0x0002, 0x0048, 0xd1b4, 0x0118,
- 0x20a3, 0x0001, 0x0020, 0x20a3, 0x0000, 0x2230, 0x0010, 0x6a80,
- 0x6e7c, 0x20a9, 0x0008, 0x0136, 0xad88, 0x0017, 0x2198, 0x20a1,
- 0x021b, 0x53a6, 0x013e, 0x20a1, 0x020b, 0x22a2, 0x26a2, 0x60c3,
- 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009,
- 0x6016, 0x2001, 0xafe3, 0x2003, 0x07d0, 0x2001, 0xafe2, 0x2003,
- 0x0009, 0x080c, 0x17bf, 0x014e, 0x015e, 0x00de, 0x0005, 0x20e1,
- 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210,
- 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004,
- 0x2019, 0xad34, 0x231c, 0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6,
- 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814,
- 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088,
- 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2,
- 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2009, 0xad14, 0x210c,
- 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2, 0x20a3, 0x0000,
- 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005,
- 0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1, 0x020b, 0x00c1, 0x7810,
- 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c,
- 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c,
- 0x080c, 0x7821, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0026,
- 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
- 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6,
- 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814,
- 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088,
- 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2,
- 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14, 0x2214,
- 0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x080c, 0x7810, 0x22a2,
- 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x7810,
- 0xa06d, 0x080c, 0x5025, 0x0148, 0x684c, 0xa084, 0x2020, 0xa086,
- 0x2020, 0x1118, 0x7820, 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c,
- 0x75d0, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810,
- 0xa084, 0xf000, 0x1130, 0x7810, 0xa084, 0x0700, 0x8007, 0x0043,
- 0x0010, 0xa006, 0x002b, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005,
- 0x74b2, 0x7547, 0x7550, 0x7579, 0x758c, 0x75a7, 0x75b0, 0x74b0,
- 0x080c, 0x14f6, 0x0016, 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118,
- 0xa186, 0x0003, 0x1170, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5,
- 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804,
- 0x7583, 0xa186, 0x0001, 0x190c, 0x14f6, 0x6b78, 0x7820, 0xd0cc,
- 0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2,
- 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384,
- 0x0300, 0x0904, 0x7541, 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc,
- 0x0110, 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020,
- 0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04, 0x74f0, 0x015e, 0x22a2,
- 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0904, 0x7541, 0x20a1, 0x020b,
- 0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080, 0x0028,
- 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
- 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
- 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
- 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700,
- 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14,
- 0x2214, 0x22a2, 0x000e, 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889,
- 0x0010, 0x20a3, 0x0898, 0x20a2, 0x080c, 0x7810, 0x22a2, 0x20a3,
- 0x0000, 0x61c2, 0x003e, 0x001e, 0x080c, 0x7821, 0x0005, 0x2011,
- 0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0488,
- 0x2011, 0x0302, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016,
- 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008,
- 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500,
- 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2,
- 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x080c, 0x7821,
- 0x0005, 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2,
- 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3,
- 0x0018, 0x080c, 0x7821, 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc,
- 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
- 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2,
- 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x080c, 0x7821, 0x0005, 0x2011,
- 0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888,
- 0x0036, 0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001,
- 0x1138, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808,
- 0x0046, 0x2021, 0x0800, 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108,
- 0xc4e5, 0x24a2, 0x004e, 0x22a2, 0x20a2, 0x003e, 0x0804, 0x7583,
- 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
- 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
- 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
- 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
- 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700,
- 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14,
- 0x2214, 0x22a2, 0x7820, 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010,
- 0x20a3, 0x0898, 0x20a3, 0x0000, 0x080c, 0x7810, 0x22a2, 0x20a3,
- 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x0016, 0x0036,
- 0x7810, 0xa084, 0x0700, 0x8007, 0x003b, 0x003e, 0x001e, 0x014e,
- 0x013e, 0x015e, 0x00de, 0x0005, 0x7634, 0x7634, 0x7636, 0x7634,
- 0x7634, 0x7634, 0x7658, 0x7634, 0x080c, 0x14f6, 0x7910, 0xa18c,
- 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003,
- 0x00f9, 0x00d6, 0x2069, 0xad51, 0x6804, 0xd0bc, 0x0130, 0x682c,
- 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de,
- 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x080c, 0x7821, 0x0005,
- 0x20a1, 0x020b, 0x2009, 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80,
- 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
- 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
- 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2,
- 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
- 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0100,
- 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14,
- 0x2214, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c,
- 0x7810, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6,
- 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xad00, 0x7150,
- 0x7818, 0x2068, 0x68a0, 0x2028, 0x76d0, 0xd6ac, 0x1130, 0xd0bc,
- 0x1120, 0x6910, 0x6a14, 0x7450, 0x0020, 0x6910, 0x6a14, 0x736c,
- 0x7470, 0x781c, 0xa0be, 0x0006, 0x0904, 0x775b, 0xa0be, 0x000a,
- 0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073,
- 0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e,
- 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086,
- 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6,
- 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000,
- 0x609f, 0x0000, 0x080c, 0x8014, 0x2009, 0x07d0, 0x60c4, 0xa084,
- 0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x6586, 0x003e,
- 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d0, 0xd0ac,
- 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a,
- 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000,
- 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084,
- 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082,
- 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e,
- 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5,
- 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120,
- 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c,
- 0x8014, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110,
- 0x2009, 0x1b58, 0x080c, 0x6586, 0x003e, 0x004e, 0x005e, 0x00ce,
- 0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003,
- 0xa086, 0x0002, 0x0904, 0x77b1, 0x2001, 0xad34, 0x2004, 0xd0ac,
- 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a,
- 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000,
- 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084,
- 0x00ff, 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, 0x6086,
- 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6,
- 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928,
- 0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000,
- 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294,
- 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x8011, 0x0804,
- 0x7749, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138,
- 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185,
- 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, 0x5025,
- 0x0180, 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, 0x2020,
- 0xa086, 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, 0x0889,
- 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084,
- 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086,
- 0x7808, 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6,
- 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000,
- 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294,
- 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, 0x0120,
- 0x080c, 0x8014, 0x0804, 0x7749, 0x080c, 0x8011, 0x0804, 0x7749,
- 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202,
- 0x8217, 0x0005, 0x00d6, 0x2069, 0xafc7, 0x6843, 0x0001, 0x00de,
- 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x0019,
- 0x080c, 0x6578, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, 0xa085,
- 0x0009, 0x6016, 0x000e, 0x0005, 0x0006, 0x00c6, 0x2061, 0x0100,
- 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, 0x6016, 0x00ce, 0x000e,
- 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069,
- 0x0140, 0x080c, 0x574f, 0x1178, 0x2001, 0xafe3, 0x2004, 0xa005,
- 0x1598, 0x080c, 0x57d1, 0x1118, 0x080c, 0x6578, 0x0468, 0x00c6,
- 0x2061, 0xafc7, 0x00d8, 0x6904, 0xa194, 0x4000, 0x0550, 0x08a1,
- 0x6803, 0x1000, 0x6803, 0x0000, 0x00c6, 0x2061, 0xafc7, 0x6128,
- 0xa192, 0x00c8, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff,
- 0x0198, 0x080c, 0x6578, 0x080c, 0x782b, 0x0070, 0x6124, 0xa1e5,
- 0x0000, 0x0140, 0x080c, 0xaca2, 0x2009, 0x0014, 0x080c, 0x80a7,
- 0x080c, 0x6581, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce,
- 0x0005, 0x2001, 0xafe3, 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061,
- 0xafc7, 0x6128, 0xa192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce,
- 0x080c, 0x6578, 0x080c, 0x485e, 0x0c38, 0x00c6, 0x00d6, 0x00e6,
- 0x0016, 0x0026, 0x080c, 0x658e, 0x2071, 0xafc7, 0x713c, 0x81ff,
- 0x0570, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x574f, 0x1188,
- 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, 0x003e, 0x713c, 0x2160,
- 0x080c, 0xaca2, 0x2009, 0x004a, 0x080c, 0x80a7, 0x080c, 0x57d1,
- 0x00b0, 0x6904, 0xa194, 0x4000, 0x01c0, 0x6803, 0x1000, 0x6803,
- 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, 0x003e, 0x713c,
- 0x2160, 0x080c, 0xaca2, 0x2009, 0x004a, 0x080c, 0x80a7, 0x002e,
- 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c58, 0x00e6, 0x00d6,
- 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, 0x0126, 0x2091, 0x8000,
- 0x6018, 0x2068, 0x6ca0, 0x2071, 0xafc7, 0x7018, 0x2068, 0x8dff,
- 0x0198, 0x68a0, 0xa406, 0x0118, 0x6854, 0x2068, 0x0cc0, 0x6010,
- 0x2060, 0x643c, 0x6540, 0x6e48, 0x2d60, 0x080c, 0x4e41, 0x0120,
- 0x080c, 0x7b88, 0xa085, 0x0001, 0x012e, 0x000e, 0x004e, 0x005e,
- 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x20a1, 0x020b, 0x080c,
- 0x710e, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x781c,
- 0xa086, 0x0004, 0x1110, 0x6098, 0x0018, 0x2001, 0xad14, 0x2004,
- 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, 0xa006,
- 0x20a2, 0x1f04, 0x7928, 0x20a2, 0x20a2, 0x60c3, 0x002c, 0x080c,
- 0x7821, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x710e,
- 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2,
- 0x60c3, 0x0008, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005, 0x0156,
- 0x0146, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, 0x20a3,
- 0x0000, 0x20a9, 0x0006, 0x2011, 0xad40, 0x2019, 0xad41, 0x23a6,
- 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, 0x7957, 0x20a3,
- 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7821, 0x014e,
- 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b,
- 0x080c, 0x7183, 0x080c, 0x7199, 0x7810, 0xa080, 0x0000, 0x2004,
- 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6,
- 0xa080, 0x0004, 0x8003, 0x60c2, 0x080c, 0x7821, 0x002e, 0x001e,
- 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c,
- 0x710e, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808,
- 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005,
- 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x710e,
- 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808,
- 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x080c, 0x7821,
- 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006,
- 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, 0x700c, 0x2060, 0x8cff,
- 0x0178, 0x080c, 0x9789, 0x1110, 0x080c, 0x85f3, 0x600c, 0x0006,
- 0x080c, 0x994e, 0x080c, 0x8078, 0x080c, 0x7b88, 0x00ce, 0x0c78,
- 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, 0x000e, 0x00ce, 0x00ee,
- 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026,
- 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140,
- 0x2071, 0xafc7, 0x7024, 0x2060, 0x8cff, 0x05a0, 0x080c, 0x7834,
- 0x68c3, 0x0000, 0x080c, 0x6581, 0x2009, 0x0013, 0x080c, 0x80a7,
- 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804,
- 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078,
- 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x7a02, 0x7804,
- 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824,
- 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e,
- 0x012e, 0x0005, 0x2001, 0xad00, 0x2004, 0xa096, 0x0001, 0x0550,
- 0xa096, 0x0004, 0x0538, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011,
- 0x481b, 0x080c, 0x650d, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158,
- 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000,
- 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010,
- 0x1f04, 0x7a3d, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100,
- 0x7803, 0x0000, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee,
- 0x00fe, 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6,
- 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069,
- 0x0100, 0x2079, 0x0140, 0x2071, 0xafc7, 0x703c, 0x2060, 0x8cff,
- 0x0904, 0x7ad5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0,
- 0x68c7, 0x0000, 0x68cb, 0x0008, 0x080c, 0x658e, 0x080c, 0x20b5,
- 0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404,
- 0xa084, 0x000f, 0xa086, 0x0004, 0x11b0, 0x68c7, 0x0000, 0x68cb,
- 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, 0x2071, 0xb01e, 0x6814,
- 0xa084, 0x0184, 0xa085, 0x0012, 0x6816, 0x7803, 0x0008, 0x7003,
- 0x0000, 0x00fe, 0x00ee, 0x200b, 0x0000, 0x004e, 0xa39d, 0x0000,
- 0x1120, 0x2009, 0x0049, 0x080c, 0x80a7, 0x20a9, 0x03e8, 0x6824,
- 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0,
- 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827,
- 0x0002, 0x0010, 0x1f04, 0x7ab7, 0x7804, 0xa084, 0x1000, 0x0120,
- 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e,
- 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6,
- 0x0126, 0x2091, 0x8000, 0x2069, 0xafc7, 0x6a06, 0x012e, 0x00de,
- 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0xafc7, 0x6a32,
- 0x012e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006,
- 0x0126, 0x2071, 0xafc7, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000,
- 0x8cff, 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110,
- 0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118,
- 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00,
- 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c,
- 0x974e, 0x080c, 0x7b88, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060,
- 0x08b8, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005,
- 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810, 0x20a2,
- 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804,
- 0x7b80, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810,
- 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000,
- 0x0478, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810,
- 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000,
- 0x00f8, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810,
- 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400,
- 0x0078, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810,
- 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200,
- 0x0089, 0x60c3, 0x0020, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005,
- 0x00e6, 0x2071, 0xafc7, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022,
- 0x00ee, 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x7b94, 0x20a2,
- 0x20a2, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066,
- 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, 0x7614, 0x2660,
- 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x7c24, 0x8cff, 0x0904,
- 0x7c24, 0x601c, 0xa086, 0x0006, 0x1904, 0x7c1f, 0x88ff, 0x0138,
- 0x2800, 0xac06, 0x1904, 0x7c1f, 0x2039, 0x0000, 0x0050, 0x6018,
- 0xa206, 0x1904, 0x7c1f, 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904,
- 0x7c1f, 0x7024, 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005,
- 0x01f0, 0x080c, 0x6581, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c,
- 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384,
- 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
- 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003,
- 0x0009, 0x630a, 0x0460, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616,
- 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012,
- 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110,
- 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1158, 0x600f, 0x0000, 0x6010,
- 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0xa91f, 0x080c, 0x974e,
- 0x080c, 0x7b88, 0x88ff, 0x1190, 0x00ce, 0x0804, 0x7bab, 0x2c78,
- 0x600c, 0x2060, 0x0804, 0x7bab, 0xa006, 0x012e, 0x000e, 0x006e,
- 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000,
- 0x00ce, 0xa8c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6,
- 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7,
- 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, 0x7c98, 0x601c, 0xa086,
- 0x0006, 0x1904, 0x7c93, 0x87ff, 0x0128, 0x2700, 0xac06, 0x1904,
- 0x7c93, 0x0040, 0x6018, 0xa206, 0x15f0, 0x85ff, 0x0118, 0x6050,
- 0xa106, 0x15c8, 0x703c, 0xac06, 0x1170, 0x0036, 0x2019, 0x0001,
- 0x080c, 0x7a64, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000,
- 0x7047, 0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a,
- 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036,
- 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110,
- 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c,
- 0x9596, 0x0110, 0x080c, 0xa91f, 0x080c, 0x974e, 0x87ff, 0x1190,
- 0x00ce, 0x0804, 0x7c43, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7c43,
- 0xa006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee,
- 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa7bd, 0x0001, 0x0c88,
- 0x00e6, 0x2071, 0xafc7, 0x2001, 0xad00, 0x2004, 0xa086, 0x0002,
- 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005,
- 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091,
- 0x8000, 0x2071, 0xafc7, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff,
- 0x0518, 0x2200, 0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c,
- 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00,
- 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110,
- 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020,
- 0x2c78, 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e,
- 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6,
- 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, 0x760c,
- 0x2660, 0x2678, 0x8cff, 0x0904, 0x7d7e, 0x6018, 0xa080, 0x0028,
- 0x2004, 0xa206, 0x1904, 0x7d79, 0x7024, 0xac06, 0x1508, 0x2069,
- 0x0100, 0x68c0, 0xa005, 0x0904, 0x7d55, 0x080c, 0x7834, 0x68c3,
- 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140,
- 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000,
- 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e,
- 0x700c, 0xac36, 0x1110, 0x660c, 0x760e, 0x7008, 0xac36, 0x1140,
- 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000,
- 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678,
- 0x600f, 0x0000, 0x080c, 0x9778, 0x1158, 0x080c, 0x2aff, 0x080c,
- 0x9789, 0x11f0, 0x080c, 0x85f3, 0x00d8, 0x080c, 0x7ca8, 0x08c0,
- 0x080c, 0x9789, 0x1118, 0x080c, 0x85f3, 0x0090, 0x6010, 0x2068,
- 0x080c, 0x9596, 0x0168, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837,
- 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, 0x080c, 0x9742,
- 0x080c, 0x994e, 0x080c, 0x974e, 0x080c, 0x7b88, 0x00ce, 0x0804,
- 0x7d02, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7d02, 0x012e, 0x000e,
- 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086,
- 0x0006, 0x1d30, 0x080c, 0xa91f, 0x0c18, 0x0036, 0x0156, 0x0136,
- 0x0146, 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x28f9,
- 0x1118, 0x8210, 0x8000, 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020,
- 0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e,
- 0x003e, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3,
- 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x2099, 0xafa6, 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004,
- 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x080c, 0x7821,
- 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0214,
- 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
- 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7821, 0x0005, 0x00d6,
- 0x0016, 0x2f68, 0x2009, 0x0035, 0x080c, 0x9a34, 0x1904, 0x7e5d,
- 0x20a1, 0x020b, 0x080c, 0x710e, 0x20a3, 0x1300, 0x20a3, 0x0000,
- 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0580, 0x7818, 0xa080,
- 0x0028, 0x2014, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x11d0, 0xa286,
- 0x007e, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x04b8, 0xa286,
- 0x007f, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0478, 0xd2bc,
- 0x0180, 0xa286, 0x0080, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffc,
- 0x0428, 0xa2e8, 0xae34, 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2,
- 0x00e8, 0x20a3, 0x0000, 0x6098, 0x20a2, 0x00c0, 0x2001, 0xad34,
- 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082,
- 0x007e, 0x0240, 0x00d6, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6,
- 0x00de, 0x0020, 0x20a3, 0x0000, 0x6034, 0x20a2, 0x7834, 0x20a2,
- 0x7838, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c,
- 0x080c, 0x7821, 0x001e, 0x00de, 0x0005, 0x7817, 0x0001, 0x7803,
- 0x0006, 0x001e, 0x00de, 0x0005, 0x00d6, 0x0026, 0x7928, 0x2168,
- 0x691c, 0xa186, 0x0006, 0x01c0, 0xa186, 0x0003, 0x0904, 0x7ed3,
- 0xa186, 0x0005, 0x0904, 0x7ebc, 0xa186, 0x0004, 0x05b8, 0xa186,
- 0x0008, 0x0904, 0x7ec4, 0x7807, 0x0037, 0x7813, 0x1700, 0x080c,
- 0x7f3b, 0x002e, 0x00de, 0x0005, 0x080c, 0x7ef7, 0x2009, 0x4000,
- 0x6800, 0x0002, 0x7e9d, 0x7ea8, 0x7e9f, 0x7ea8, 0x7ea4, 0x7e9d,
- 0x7e9d, 0x7ea8, 0x7ea8, 0x7ea8, 0x7ea8, 0x7e9d, 0x7e9d, 0x7e9d,
- 0x7e9d, 0x7e9d, 0x7ea8, 0x7e9d, 0x7ea8, 0x080c, 0x14f6, 0x6820,
- 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0xa00e, 0x0010, 0x2009, 0x2000,
- 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0804, 0x7eed, 0x080c, 0x7ef7,
- 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x6a00, 0xa286,
- 0x0002, 0x1108, 0xa00e, 0x0488, 0x04d1, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x2009, 0x4000, 0x0448, 0x0491, 0x20a3, 0x0000, 0x20a3,
- 0x0000, 0x2009, 0x4000, 0xa286, 0x0005, 0x0118, 0xa286, 0x0002,
- 0x1108, 0xa00e, 0x00d0, 0x0419, 0x6810, 0x2068, 0x697c, 0x6810,
- 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, 0x22a2, 0x7928, 0xa180,
- 0x0000, 0x2004, 0xa08e, 0x0002, 0x0130, 0xa08e, 0x0004, 0x0118,
- 0x2009, 0x4000, 0x0010, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000,
- 0x60c3, 0x0018, 0x080c, 0x7821, 0x002e, 0x00de, 0x0005, 0x0036,
- 0x0046, 0x0056, 0x0066, 0x20a1, 0x020b, 0x080c, 0x71aa, 0xa006,
- 0x20a3, 0x0200, 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818,
- 0xa080, 0x0028, 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118,
- 0xa092, 0x007e, 0x0268, 0x00d6, 0x2069, 0xad1b, 0x2d2c, 0x8d68,
- 0x2d34, 0xa0e8, 0xae34, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0030,
- 0x2019, 0x0000, 0x6498, 0x2029, 0x0000, 0x6634, 0x7828, 0xa080,
- 0x0007, 0x2004, 0xa086, 0x0003, 0x1128, 0x25a2, 0x26a2, 0x23a2,
- 0x24a2, 0x0020, 0x23a2, 0x24a2, 0x25a2, 0x26a2, 0x006e, 0x005e,
- 0x004e, 0x003e, 0x0005, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3,
- 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3,
- 0x0008, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7106,
- 0x20a3, 0x1400, 0x20a3, 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2,
- 0x7828, 0x20a2, 0x782c, 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007,
- 0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0010, 0x080c, 0x7821, 0x0005,
- 0x20a1, 0x020b, 0x080c, 0x71a2, 0x20a3, 0x0100, 0x20a3, 0x0000,
- 0x7828, 0x20a2, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7821,
- 0x0005, 0x0146, 0x20a1, 0x020b, 0x0031, 0x60c3, 0x0000, 0x080c,
- 0x7821, 0x014e, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
- 0xa080, 0x0028, 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110,
- 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085,
- 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68,
- 0x2da6, 0x00de, 0x0078, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810,
- 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000,
- 0x6234, 0x22a2, 0x20a3, 0x0819, 0x20a3, 0x0000, 0x080c, 0x7810,
- 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x7a08, 0x22a2, 0x20a3, 0x0000,
- 0x20a3, 0x0000, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2,
- 0x20a3, 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575,
- 0x080c, 0x782b, 0x080c, 0x6578, 0x0005, 0x0156, 0x0136, 0x0036,
- 0x00d6, 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7854, 0x2068,
- 0xadf0, 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212,
- 0x7214, 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308,
- 0xa384, 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215,
- 0x720a, 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98,
- 0x53a6, 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000,
- 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e,
- 0x0005, 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036,
- 0x6116, 0x0005, 0x2061, 0xb400, 0x2a70, 0x7064, 0x7046, 0x704b,
- 0xb400, 0x0005, 0x00e6, 0x0126, 0x2071, 0xad00, 0x2091, 0x8000,
- 0x7544, 0xa582, 0x0010, 0x0608, 0x7048, 0x2060, 0x6000, 0xa086,
- 0x0000, 0x0148, 0xace0, 0x0018, 0x7058, 0xac02, 0x1208, 0x0cb0,
- 0x2061, 0xb400, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8,
- 0x0018, 0x7058, 0xa502, 0x1230, 0x754a, 0xa085, 0x0001, 0x012e,
- 0x00ee, 0x0005, 0x704b, 0xb400, 0x0cc0, 0xa006, 0x0cc0, 0x00e6,
- 0x2071, 0xad00, 0x7544, 0xa582, 0x0010, 0x0600, 0x7048, 0x2060,
- 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, 0x7058, 0xac02,
- 0x1208, 0x0cb0, 0x2061, 0xb400, 0x0c98, 0x6003, 0x0008, 0x8529,
- 0x7546, 0xaca8, 0x0018, 0x7058, 0xa502, 0x1228, 0x754a, 0xa085,
- 0x0001, 0x00ee, 0x0005, 0x704b, 0xb400, 0x0cc8, 0xa006, 0x0cc8,
- 0xac82, 0xb400, 0x0a0c, 0x14f6, 0x2001, 0xad16, 0x2004, 0xac02,
- 0x1a0c, 0x14f6, 0xa006, 0x6006, 0x600a, 0x600e, 0x6012, 0x6016,
- 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x6052, 0x6056, 0x6022,
- 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x2061,
- 0xad00, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0108, 0x0005,
- 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, 0x0cc0, 0x601c,
- 0xa084, 0x000f, 0x0002, 0x80b6, 0x80c5, 0x80e0, 0x80fb, 0x9a61,
- 0x9a7c, 0x9a97, 0x80b6, 0x80c5, 0x80b6, 0x8116, 0xa186, 0x0013,
- 0x1128, 0x080c, 0x6b73, 0x080c, 0x6c50, 0x0005, 0xa18e, 0x0047,
- 0x1118, 0xa016, 0x080c, 0x1824, 0x0005, 0x0066, 0x6000, 0xa0b2,
- 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, 0x80de, 0x8478,
- 0x862d, 0x80de, 0x86a2, 0x81cf, 0x80de, 0x80de, 0x840a, 0x8a91,
- 0x80de, 0x80de, 0x80de, 0x80de, 0x80de, 0x80de, 0x080c, 0x14f6,
- 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e,
- 0x0005, 0x80f9, 0x909a, 0x80f9, 0x80f9, 0x80f9, 0x80f9, 0x80f9,
- 0x80f9, 0x9045, 0x9200, 0x80f9, 0x90c7, 0x913e, 0x90c7, 0x913e,
- 0x80f9, 0x080c, 0x14f6, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c,
- 0x14f6, 0x0013, 0x006e, 0x0005, 0x8114, 0x8ad2, 0x8b98, 0x8cb8,
- 0x8e12, 0x8114, 0x8114, 0x8114, 0x8aac, 0x8ff5, 0x8ff8, 0x8114,
- 0x8114, 0x8114, 0x8114, 0x9022, 0x080c, 0x14f6, 0x0066, 0x6000,
- 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, 0x812f,
- 0x812f, 0x812f, 0x8152, 0x81a5, 0x812f, 0x812f, 0x812f, 0x8131,
- 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x080c,
- 0x14f6, 0xa186, 0x0003, 0x190c, 0x14f6, 0x00d6, 0x6003, 0x0003,
- 0x6106, 0x6010, 0x2068, 0x684f, 0x0040, 0x687c, 0x680a, 0x6880,
- 0x680e, 0x6813, 0x0000, 0x6817, 0x0000, 0x00de, 0x2c10, 0x080c,
- 0x1e6e, 0x080c, 0x680b, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d0d,
- 0x012e, 0x0005, 0xa182, 0x0047, 0x0002, 0x815e, 0x815e, 0x8160,
- 0x817f, 0x815e, 0x815e, 0x815e, 0x815e, 0x8191, 0x080c, 0x14f6,
- 0x00d6, 0x0016, 0x080c, 0x6c05, 0x080c, 0x6d0d, 0x6003, 0x0004,
- 0x6110, 0x2168, 0x6854, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116,
- 0x684f, 0x0020, 0x685c, 0x685a, 0x6874, 0x687e, 0x6878, 0x6882,
- 0x6897, 0x0000, 0x689b, 0x0000, 0x001e, 0x00de, 0x0005, 0x080c,
- 0x6c05, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9596, 0x0120, 0x684b,
- 0x0006, 0x080c, 0x510c, 0x00de, 0x080c, 0x8078, 0x080c, 0x6d0d,
- 0x0005, 0x080c, 0x6c05, 0x080c, 0x2ad9, 0x00d6, 0x6110, 0x2168,
- 0x080c, 0x9596, 0x0120, 0x684b, 0x0029, 0x080c, 0x510c, 0x00de,
- 0x080c, 0x8078, 0x080c, 0x6d0d, 0x0005, 0xa182, 0x0047, 0x0002,
- 0x81b3, 0x81c2, 0x81b1, 0x81b1, 0x81b1, 0x81b1, 0x81b1, 0x81b1,
- 0x81b1, 0x080c, 0x14f6, 0x00d6, 0x6010, 0x2068, 0x684c, 0xc0f4,
- 0x684e, 0x00de, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c,
- 0x1824, 0x0005, 0x00d6, 0x6110, 0x2168, 0x684b, 0x0000, 0x6853,
- 0x0000, 0x080c, 0x510c, 0x00de, 0x080c, 0x8078, 0x0005, 0xa1b6,
- 0x0015, 0x1118, 0x080c, 0x8078, 0x0030, 0xa1b6, 0x0016, 0x190c,
- 0x14f6, 0x080c, 0x8078, 0x0005, 0x20a9, 0x000e, 0x2e98, 0x6010,
- 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0,
- 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002,
- 0xa398, 0x0002, 0xa4a0, 0x0002, 0x1f04, 0x81ea, 0x00e6, 0x080c,
- 0x9596, 0x0130, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103,
- 0x00ee, 0x080c, 0x8078, 0x0005, 0x00d6, 0x0036, 0x7330, 0xa386,
- 0x0200, 0x1130, 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd,
- 0x6010, 0xa005, 0x0130, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103,
- 0x6b32, 0x080c, 0x8078, 0x003e, 0x00de, 0x0005, 0x0016, 0x20a9,
- 0x002a, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0,
- 0x53a3, 0x20a9, 0x002a, 0x6010, 0xa080, 0x0001, 0x2004, 0xa080,
- 0x0002, 0x20a0, 0x53a3, 0x00e6, 0x6010, 0x2004, 0x2070, 0x7037,
- 0x0103, 0x00ee, 0x080c, 0x8078, 0x001e, 0x0005, 0x0016, 0x2009,
- 0x0000, 0x7030, 0xa086, 0x0100, 0x0140, 0x7038, 0xa084, 0x00ff,
- 0x808e, 0x703c, 0xa084, 0x00ff, 0x8086, 0xa080, 0x0004, 0xa108,
- 0x21a8, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0,
- 0x080c, 0x48be, 0x00e6, 0x080c, 0x9596, 0x0140, 0x6010, 0x2070,
- 0x7007, 0x0000, 0x7034, 0x70b2, 0x7037, 0x0103, 0x00ee, 0x080c,
- 0x8078, 0x001e, 0x0005, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2c68,
- 0x0016, 0x2009, 0x0035, 0x080c, 0x9a34, 0x001e, 0x1168, 0x0026,
- 0x6228, 0x2268, 0x002e, 0x2071, 0xb28c, 0x6b1c, 0xa386, 0x0003,
- 0x0130, 0xa386, 0x0006, 0x0128, 0x080c, 0x8078, 0x0020, 0x0031,
- 0x0010, 0x080c, 0x8323, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6810,
- 0x2078, 0xa186, 0x0015, 0x0904, 0x830c, 0xa18e, 0x0016, 0x1904,
- 0x8321, 0x700c, 0xa084, 0xff00, 0xa086, 0x1700, 0x1904, 0x82eb,
- 0x8fff, 0x0904, 0x831f, 0x6808, 0xa086, 0xffff, 0x1904, 0x830e,
- 0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x1150, 0x797c, 0x7810,
- 0xa106, 0x1904, 0x830e, 0x7980, 0x7814, 0xa106, 0x1904, 0x830e,
- 0x080c, 0x9742, 0x6858, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4,
- 0x784e, 0x0026, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x080c, 0x6665,
- 0x7854, 0xa20a, 0x0208, 0x8011, 0x7a56, 0x82ff, 0x002e, 0x1138,
- 0x00c6, 0x2d60, 0x080c, 0x9374, 0x00ce, 0x0804, 0x831f, 0x00c6,
- 0x00d6, 0x2f68, 0x6838, 0xd0fc, 0x1118, 0x080c, 0x4993, 0x0010,
- 0x080c, 0x4b7c, 0x00de, 0x00ce, 0x1548, 0x00c6, 0x2d60, 0x080c,
- 0x8078, 0x00ce, 0x04a0, 0x7008, 0xa086, 0x000b, 0x11a0, 0x6018,
- 0x200c, 0xc1bc, 0x2102, 0x00c6, 0x2d60, 0x7853, 0x0003, 0x6007,
- 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x67a8, 0x080c,
- 0x6c50, 0x00ce, 0x00e0, 0x700c, 0xa086, 0x2a00, 0x1138, 0x2001,
- 0xafa5, 0x2004, 0x683e, 0x0098, 0x0471, 0x0098, 0x8fff, 0x090c,
- 0x14f6, 0x00c6, 0x00d6, 0x2d60, 0x2f68, 0x684b, 0x0003, 0x080c,
- 0x926f, 0x080c, 0x9742, 0x080c, 0x974e, 0x00de, 0x00ce, 0x080c,
- 0x8078, 0x00fe, 0x0005, 0xa186, 0x0015, 0x1128, 0x2001, 0xafa5,
- 0x2004, 0x683e, 0x0068, 0xa18e, 0x0016, 0x1160, 0x00c6, 0x2d00,
- 0x2060, 0x080c, 0xabb4, 0x080c, 0x6618, 0x080c, 0x8078, 0x00ce,
- 0x080c, 0x8078, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0x7c80,
- 0x7b7c, 0xd2f4, 0x0130, 0x2001, 0xafa5, 0x2004, 0x683e, 0x0804,
- 0x839d, 0x00c6, 0x2d60, 0x080c, 0x928f, 0x00ce, 0x6804, 0xa086,
- 0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007,
- 0x0050, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ce, 0x04f0, 0x6800,
- 0xa086, 0x000f, 0x01c8, 0x8fff, 0x090c, 0x14f6, 0x6820, 0xd0dc,
- 0x1198, 0x6800, 0xa086, 0x0004, 0x1198, 0x784c, 0xd0ac, 0x0180,
- 0x784c, 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852,
- 0x2001, 0x0001, 0x682e, 0x00e0, 0x2001, 0x0007, 0x682e, 0x00c0,
- 0x784c, 0xd0b4, 0x1130, 0xd0ac, 0x0db8, 0x784c, 0xd0f4, 0x1da0,
- 0x0c38, 0xd2ec, 0x1d88, 0x7024, 0xa306, 0x1118, 0x7020, 0xa406,
- 0x0d58, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e,
- 0x080c, 0x9894, 0x080c, 0x6c50, 0x0010, 0x080c, 0x8078, 0x004e,
- 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x6034, 0x2068,
- 0x6a1c, 0xa286, 0x0007, 0x0904, 0x83ee, 0xa286, 0x0002, 0x05f0,
- 0xa286, 0x0000, 0x05d8, 0x6808, 0x6338, 0xa306, 0x15b8, 0x2071,
- 0xb28c, 0xa186, 0x0015, 0x0560, 0xa18e, 0x0016, 0x1190, 0x6030,
- 0xa084, 0x00ff, 0xa086, 0x0001, 0x1160, 0x700c, 0xa086, 0x2a00,
- 0x1140, 0x6034, 0xa080, 0x0008, 0x200c, 0xc1dd, 0xc1f5, 0x2102,
- 0x00b8, 0x00c6, 0x6034, 0x2060, 0x6010, 0x2068, 0x080c, 0x9596,
- 0x090c, 0x14f6, 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b,
- 0x601f, 0x0002, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ce, 0x0030,
- 0x6034, 0x2070, 0x2001, 0xafa5, 0x2004, 0x703e, 0x080c, 0x8078,
- 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x20a9, 0x000e, 0x2e98,
- 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x1148, 0x6018, 0x2068,
- 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802, 0x00de,
- 0x0804, 0x81f6, 0x2100, 0xa1b2, 0x0080, 0x1a0c, 0x14f6, 0xa1b2,
- 0x0040, 0x1a04, 0x846e, 0x0002, 0x8462, 0x8456, 0x8462, 0x8462,
- 0x8462, 0x8462, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454,
- 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454,
- 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454,
- 0x8454, 0x8454, 0x8454, 0x8462, 0x8454, 0x8462, 0x8462, 0x8454,
- 0x8454, 0x8454, 0x8454, 0x8454, 0x8462, 0x8454, 0x8454, 0x8454,
- 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8462, 0x8462,
- 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454,
- 0x8454, 0x8462, 0x8454, 0x8454, 0x080c, 0x14f6, 0x6003, 0x0001,
- 0x6106, 0x080c, 0x67ee, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50,
- 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x67ee, 0x0126,
- 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, 0x0005, 0x2600, 0x0002,
- 0x8462, 0x8476, 0x8476, 0x8462, 0x8462, 0x8476, 0x080c, 0x14f6,
- 0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x14f6, 0xa1b6, 0x0013, 0x0904,
- 0x8518, 0xa1b6, 0x0027, 0x1904, 0x84de, 0x080c, 0x6b73, 0x6004,
- 0x080c, 0x9778, 0x0188, 0x080c, 0x9789, 0x0904, 0x84d8, 0xa08e,
- 0x0021, 0x0904, 0x84db, 0xa08e, 0x0022, 0x0904, 0x84d8, 0xa08e,
- 0x003d, 0x0904, 0x84db, 0x04a8, 0x080c, 0x2aff, 0x2001, 0x0007,
- 0x080c, 0x4c30, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x85f3,
- 0xa186, 0x007e, 0x1148, 0x2001, 0xad34, 0x2014, 0xc285, 0x080c,
- 0x574f, 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026, 0x0036, 0x2110,
- 0x2019, 0x0028, 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c,
- 0x681d, 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c, 0x4ecf, 0x00ce,
- 0x2c08, 0x080c, 0xa712, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c,
- 0x4c9f, 0x080c, 0x994e, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005,
- 0x080c, 0x85f3, 0x0cb0, 0x080c, 0x8621, 0x0c98, 0xa186, 0x0014,
- 0x1db0, 0x080c, 0x6b73, 0x080c, 0x2ad9, 0x080c, 0x9778, 0x1188,
- 0x080c, 0x2aff, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x85f3,
- 0xa186, 0x007e, 0x1128, 0x2001, 0xad34, 0x200c, 0xc185, 0x2102,
- 0x08c0, 0x080c, 0x9789, 0x1118, 0x080c, 0x85f3, 0x0890, 0x6004,
- 0xa08e, 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0xad81, 0x2079,
- 0x0000, 0x080c, 0x2df1, 0x00fe, 0x00ee, 0x0818, 0x6004, 0xa08e,
- 0x0021, 0x0d50, 0xa08e, 0x0022, 0x090c, 0x85f3, 0x0804, 0x84d1,
- 0xa0b2, 0x0040, 0x1a04, 0x85db, 0x2008, 0x0002, 0x8560, 0x8561,
- 0x8564, 0x8567, 0x856a, 0x856d, 0x855e, 0x855e, 0x855e, 0x855e,
- 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e,
- 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e,
- 0x855e, 0x855e, 0x855e, 0x855e, 0x8570, 0x857f, 0x855e, 0x8581,
- 0x857f, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x857f, 0x857f,
- 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e,
- 0x85bb, 0x857f, 0x855e, 0x857b, 0x855e, 0x855e, 0x855e, 0x857c,
- 0x855e, 0x855e, 0x855e, 0x857f, 0x85b2, 0x855e, 0x080c, 0x14f6,
- 0x00f0, 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, 0x2001,
- 0x0005, 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, 0x0400,
- 0x080c, 0x6b73, 0x6003, 0x0005, 0x2001, 0xafa5, 0x2004, 0x603e,
- 0x080c, 0x6c50, 0x00a0, 0x0018, 0x0010, 0x080c, 0x4c30, 0x0804,
- 0x85cc, 0x080c, 0x6b73, 0x2001, 0xafa3, 0x2004, 0x6016, 0x2001,
- 0xafa5, 0x2004, 0x603e, 0x6003, 0x0004, 0x080c, 0x6c50, 0x0005,
- 0x080c, 0x4c30, 0x080c, 0x6b73, 0x6003, 0x0002, 0x2001, 0xafa5,
- 0x2004, 0x603e, 0x0036, 0x2019, 0xad5c, 0x2304, 0xa084, 0xff00,
- 0x1120, 0x2001, 0xafa3, 0x201c, 0x0040, 0x8007, 0xa09a, 0x0004,
- 0x0ec0, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x080c,
- 0x6c50, 0x08e8, 0x080c, 0x6b73, 0x080c, 0x994e, 0x080c, 0x8078,
- 0x080c, 0x6c50, 0x08a0, 0x00e6, 0x00f6, 0x2071, 0xad81, 0x2079,
- 0x0000, 0x080c, 0x2df1, 0x00fe, 0x00ee, 0x080c, 0x6b73, 0x080c,
- 0x8078, 0x080c, 0x6c50, 0x0818, 0x080c, 0x6b73, 0x2001, 0xafa5,
- 0x2004, 0x603e, 0x6003, 0x0002, 0x2001, 0xafa3, 0x2004, 0x6016,
- 0x080c, 0x6c50, 0x0005, 0x2600, 0x2008, 0x0002, 0x85e6, 0x85e4,
- 0x85e4, 0x85cc, 0x85cc, 0x85e4, 0x080c, 0x14f6, 0x080c, 0x6b73,
- 0x00d6, 0x6010, 0x2068, 0x080c, 0x15f0, 0x00de, 0x080c, 0x8078,
- 0x080c, 0x6c50, 0x0005, 0x00e6, 0x0026, 0x0016, 0x080c, 0x9596,
- 0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, 0x1148, 0x2001,
- 0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, 0x9a05, 0x0090,
- 0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, 0xa08e,
- 0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, 0x7037, 0x0103,
- 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009,
- 0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037,
- 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668,
- 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x14f6,
- 0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0x99c1, 0x0804, 0x8692,
- 0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0x9971, 0x0804, 0x8692,
- 0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0x97b9, 0x0804, 0x8692,
- 0x6604, 0xa6b6, 0x0029, 0x1118, 0x080c, 0x97d0, 0x04d8, 0x6604,
- 0xa6b6, 0x001f, 0x1118, 0x080c, 0x81dc, 0x04a0, 0x6604, 0xa6b6,
- 0x0000, 0x1118, 0x080c, 0x83f4, 0x0468, 0x6604, 0xa6b6, 0x0022,
- 0x1118, 0x080c, 0x8204, 0x0430, 0x6604, 0xa6b6, 0x0035, 0x1118,
- 0x080c, 0x826b, 0x00f8, 0x6604, 0xa6b6, 0x0039, 0x1118, 0x080c,
- 0x83a3, 0x00c0, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, 0x821e,
- 0x0088, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, 0x823e, 0x0050,
- 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, 0x1118,
- 0x0804, 0x883f, 0x0005, 0x080c, 0x80be, 0x0ce0, 0x86b9, 0x86bc,
- 0x86b9, 0x86fe, 0x86b9, 0x87cc, 0x884d, 0x86b9, 0x86b9, 0x881b,
- 0x86b9, 0x882f, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, 0x3d18,
- 0x3e20, 0x2c10, 0x080c, 0x1824, 0x0005, 0x00e6, 0xacf0, 0x0004,
- 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x8078,
- 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071, 0xad00, 0x7080,
- 0xa086, 0x0074, 0x1530, 0x080c, 0xa6e9, 0x11b0, 0x00d6, 0x6018,
- 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, 0x0110, 0xc0c5,
- 0x6802, 0x00d9, 0x00de, 0x2001, 0x0006, 0x080c, 0x4c30, 0x080c,
- 0x2aff, 0x080c, 0x8078, 0x0078, 0x2001, 0x000a, 0x080c, 0x4c30,
- 0x080c, 0x2aff, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x67ee,
- 0x0010, 0x080c, 0x87bd, 0x00ee, 0x0005, 0x6800, 0xd084, 0x0168,
- 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2069, 0xad51, 0x6804, 0xd0a4,
- 0x0120, 0x2001, 0x0006, 0x080c, 0x4c5d, 0x0005, 0x00d6, 0x2011,
- 0xad20, 0x2204, 0xa086, 0x0074, 0x1904, 0x87ba, 0x6018, 0x2068,
- 0x6aa0, 0xa286, 0x007e, 0x1120, 0x080c, 0x894d, 0x0804, 0x875e,
- 0x080c, 0x8943, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, 0xa286,
- 0x0080, 0x11c0, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005,
- 0x0138, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, 0x0200,
- 0x2001, 0x0006, 0x080c, 0x4c30, 0x080c, 0x2aff, 0x080c, 0x8078,
- 0x0804, 0x87bb, 0x00e6, 0x2071, 0xad34, 0x2e04, 0xd09c, 0x0188,
- 0x2071, 0xb280, 0x7108, 0x720c, 0xa18c, 0x00ff, 0x1118, 0xa284,
- 0xff00, 0x0138, 0x6018, 0x2070, 0x70a0, 0xd0bc, 0x1110, 0x7112,
- 0x7216, 0x00ee, 0x6010, 0xa005, 0x0128, 0x2068, 0x6838, 0xd0f4,
- 0x0108, 0x0880, 0x2001, 0x0004, 0x080c, 0x4c30, 0x6003, 0x0001,
- 0x6007, 0x0003, 0x080c, 0x67ee, 0x0804, 0x87bb, 0x685c, 0xd0e4,
- 0x01d0, 0x080c, 0x9903, 0x080c, 0x574f, 0x0110, 0xd0dc, 0x1900,
- 0x2011, 0xad34, 0x2204, 0xc0ad, 0x2012, 0x2001, 0xaf8e, 0x2004,
- 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x26cb, 0x78e2,
- 0x00fe, 0x0804, 0x8728, 0x080c, 0x9937, 0x2011, 0xad34, 0x2204,
- 0xc0a5, 0x2012, 0x0006, 0x080c, 0xa801, 0x000e, 0x1904, 0x8728,
- 0xc0b5, 0x2012, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x00c6, 0x2009,
- 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x00fe,
- 0x080c, 0x26a0, 0x00f6, 0x2079, 0xad00, 0x7972, 0x2100, 0x2009,
- 0x0000, 0x080c, 0x2676, 0x794e, 0x00fe, 0x8108, 0x080c, 0x4c80,
- 0x2c00, 0x00ce, 0x1904, 0x8728, 0x601a, 0x2001, 0x0002, 0x080c,
- 0x4c30, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c,
- 0x67ee, 0x0008, 0x0011, 0x00de, 0x0005, 0x2001, 0xad00, 0x2004,
- 0xa086, 0x0003, 0x0120, 0x2001, 0x0007, 0x080c, 0x4c30, 0x080c,
- 0x2aff, 0x080c, 0x8078, 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071,
- 0xad00, 0x7080, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, 0x0003,
- 0x1128, 0x6010, 0xa005, 0x1110, 0x080c, 0x3cce, 0x00d6, 0x6018,
- 0x2068, 0x080c, 0x4d72, 0x080c, 0x86ed, 0x00de, 0x080c, 0x89f7,
- 0x1550, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0518,
- 0x2001, 0x0006, 0x080c, 0x4c30, 0x00e6, 0x6010, 0xa075, 0x01a8,
- 0x7034, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, 0x0000,
- 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0x9a05, 0x0030, 0x7007,
- 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2aff,
- 0x080c, 0x8078, 0x0020, 0x080c, 0x85f3, 0x080c, 0x87bd, 0x001e,
- 0x002e, 0x00ee, 0x0005, 0x2011, 0xad20, 0x2204, 0xa086, 0x0014,
- 0x1158, 0x2001, 0x0002, 0x080c, 0x4c30, 0x6003, 0x0001, 0x6007,
- 0x0001, 0x080c, 0x67ee, 0x0010, 0x080c, 0x87bd, 0x0005, 0x2011,
- 0xad20, 0x2204, 0xa086, 0x0004, 0x1138, 0x2001, 0x0007, 0x080c,
- 0x4c30, 0x080c, 0x8078, 0x0010, 0x080c, 0x87bd, 0x0005, 0x000b,
- 0x0005, 0x86b9, 0x8854, 0x86b9, 0x888a, 0x86b9, 0x88ff, 0x884d,
- 0x86b9, 0x86b9, 0x8912, 0x86b9, 0x8922, 0x6604, 0xa6b6, 0x001e,
- 0x1110, 0x080c, 0x8078, 0x0005, 0x00d6, 0x00c6, 0x080c, 0x8932,
- 0x1178, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0002, 0x080c,
- 0x4c30, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x67ee, 0x00f8,
- 0x2009, 0xb28e, 0x2104, 0xa086, 0x0009, 0x1160, 0x6018, 0x2068,
- 0x6840, 0xa084, 0x00ff, 0xa005, 0x0180, 0x8001, 0x6842, 0x6017,
- 0x000a, 0x0068, 0x2009, 0xb28f, 0x2104, 0xa084, 0xff00, 0xa086,
- 0x1900, 0x1118, 0x080c, 0x8078, 0x0010, 0x080c, 0x87bd, 0x00ce,
- 0x00de, 0x0005, 0x080c, 0x8940, 0x00d6, 0x2069, 0xaf9d, 0x2d04,
- 0xa005, 0x0168, 0x6018, 0x2068, 0x68a0, 0xa086, 0x007e, 0x1138,
- 0x2069, 0xad1c, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de,
- 0x0078, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0002, 0x080c,
- 0x4c30, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x67ee, 0x0428,
- 0x080c, 0x85f3, 0x2009, 0xb28e, 0x2134, 0xa6b4, 0x00ff, 0xa686,
- 0x0005, 0x01e0, 0xa686, 0x000b, 0x01b0, 0x2009, 0xb28f, 0x2104,
- 0xa084, 0xff00, 0x1118, 0xa686, 0x0009, 0x0180, 0xa086, 0x1900,
- 0x1150, 0xa686, 0x0009, 0x0150, 0x2001, 0x0004, 0x080c, 0x4c30,
- 0x080c, 0x8078, 0x0010, 0x080c, 0x87bd, 0x0005, 0x00d6, 0x6010,
- 0x2068, 0x080c, 0x9596, 0x0128, 0x6838, 0xd0fc, 0x0110, 0x00de,
- 0x0c90, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140,
- 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, 0x0c28,
- 0x68a0, 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xad00, 0x080c,
- 0x48f5, 0x00ee, 0x0010, 0x080c, 0x2ad9, 0x00de, 0x08a0, 0x080c,
- 0x8940, 0x1158, 0x2001, 0x0004, 0x080c, 0x4c30, 0x6003, 0x0001,
- 0x6007, 0x0003, 0x080c, 0x67ee, 0x0020, 0x080c, 0x85f3, 0x080c,
- 0x87bd, 0x0005, 0x0469, 0x1158, 0x2001, 0x0008, 0x080c, 0x4c30,
- 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x67ee, 0x0010, 0x080c,
- 0x87bd, 0x0005, 0x00e9, 0x1158, 0x2001, 0x000a, 0x080c, 0x4c30,
- 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x67ee, 0x0010, 0x080c,
- 0x87bd, 0x0005, 0x2009, 0xb28e, 0x2104, 0xa086, 0x0003, 0x1138,
- 0x2009, 0xb28f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x0005,
- 0xa085, 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006, 0x2164,
- 0x080c, 0x4ceb, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6,
- 0x0036, 0x0016, 0x6018, 0x2068, 0x2071, 0xad34, 0x2e04, 0xa085,
- 0x0003, 0x2072, 0x080c, 0x89cc, 0x0538, 0x2001, 0xad52, 0x2004,
- 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, 0x080c, 0xa96c,
- 0x2001, 0xad0c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009,
- 0x0001, 0x080c, 0x2aac, 0x2071, 0xad00, 0x080c, 0x28fa, 0x00c6,
- 0x0156, 0x20a9, 0x0081, 0x2009, 0x007f, 0x080c, 0x2bc9, 0x8108,
- 0x1f04, 0x897d, 0x015e, 0x00ce, 0x080c, 0x8943, 0x6813, 0x00ff,
- 0x6817, 0xfffe, 0x2071, 0xb280, 0x2079, 0x0100, 0x2e04, 0xa084,
- 0x00ff, 0x2069, 0xad1b, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04,
- 0x2069, 0xad1c, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0xa084,
- 0xff00, 0x001e, 0xa105, 0x2009, 0xad27, 0x200a, 0x2200, 0xa084,
- 0x00ff, 0x2008, 0x080c, 0x26a0, 0x080c, 0x574f, 0x0170, 0x2069,
- 0xb28e, 0x2071, 0xaf9f, 0x6810, 0x2072, 0x6814, 0x7006, 0x6818,
- 0x700a, 0x681c, 0x700e, 0x080c, 0x9903, 0x0040, 0x2001, 0x0006,
- 0x080c, 0x4c30, 0x080c, 0x2aff, 0x080c, 0x8078, 0x001e, 0x003e,
- 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, 0x00e6, 0x0156,
- 0x2019, 0xad27, 0x231c, 0x83ff, 0x01e8, 0x2071, 0xb280, 0x2e14,
- 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, 0x1190,
- 0x2011, 0xb296, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x8a7c,
- 0x1148, 0x2011, 0xb29a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c,
- 0x8a7c, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, 0x0005, 0x00e6,
- 0x2071, 0xb28c, 0x7004, 0xa086, 0x0014, 0x11a8, 0x7008, 0xa086,
- 0x0800, 0x1188, 0x700c, 0xd0ec, 0x0160, 0xa084, 0x0f00, 0xa086,
- 0x0100, 0x1138, 0x7024, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0xa006,
- 0x0010, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6,
- 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000,
- 0x2029, 0xafd0, 0x252c, 0x2021, 0xafd6, 0x2424, 0x2061, 0xb400,
- 0x2071, 0xad00, 0x7244, 0x7064, 0xa202, 0x16f0, 0x080c, 0xa990,
- 0x05a0, 0x671c, 0xa786, 0x0001, 0x0580, 0xa786, 0x0007, 0x0568,
- 0x2500, 0xac06, 0x0550, 0x2400, 0xac06, 0x0538, 0x00c6, 0x6000,
- 0xa086, 0x0004, 0x1110, 0x080c, 0x190b, 0xa786, 0x0008, 0x1148,
- 0x080c, 0x9789, 0x1130, 0x00ce, 0x080c, 0x85f3, 0x080c, 0x974e,
- 0x00a0, 0x6010, 0x2068, 0x080c, 0x9596, 0x0160, 0xa786, 0x0003,
- 0x11e8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c,
- 0x080c, 0x9742, 0x080c, 0x974e, 0x00ce, 0xace0, 0x0018, 0x7058,
- 0xac02, 0x1210, 0x0804, 0x8a2a, 0x012e, 0x000e, 0x002e, 0x004e,
- 0x005e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0xa786, 0x0006,
- 0x1d00, 0x080c, 0xa91f, 0x0c30, 0x220c, 0x2304, 0xa106, 0x1130,
- 0x8210, 0x8318, 0x1f04, 0x8a7c, 0xa006, 0x0005, 0x2304, 0xa102,
- 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0xa18d, 0x0001,
- 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x14f6, 0x080c, 0x9778,
- 0x0120, 0x080c, 0x9789, 0x0168, 0x0028, 0x080c, 0x2aff, 0x080c,
- 0x9789, 0x0138, 0x080c, 0x6b73, 0x080c, 0x8078, 0x080c, 0x6c50,
- 0x0005, 0x080c, 0x85f3, 0x0cb0, 0xa182, 0x0040, 0x0002, 0x8ac2,
- 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2,
- 0x8ac2, 0x8ac2, 0x8ac4, 0x8ac4, 0x8ac4, 0x8ac4, 0x8ac2, 0x8ac2,
- 0x8ac2, 0x8ac4, 0x080c, 0x14f6, 0x600b, 0xffff, 0x6003, 0x0001,
- 0x6106, 0x080c, 0x67a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50,
- 0x012e, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0040,
- 0x0804, 0x8b5e, 0xa186, 0x0027, 0x11e8, 0x080c, 0x6b73, 0x080c,
- 0x2ad9, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9596, 0x0168, 0x6837,
- 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e,
- 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c, 0x8078, 0x080c,
- 0x6c50, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004, 0xa082, 0x0040,
- 0x0428, 0xa186, 0x0046, 0x0138, 0xa186, 0x0045, 0x0120, 0xa186,
- 0x0047, 0x190c, 0x14f6, 0x2001, 0x0109, 0x2004, 0xd084, 0x0198,
- 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6699,
- 0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000, 0xa086, 0x0002,
- 0x1110, 0x0804, 0x8b98, 0x080c, 0x80be, 0x0005, 0x0002, 0x8b3c,
- 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a,
- 0x8b3a, 0x8b3a, 0x8b57, 0x8b57, 0x8b57, 0x8b57, 0x8b3a, 0x8b57,
- 0x8b3a, 0x8b57, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x00d6, 0x6110,
- 0x2168, 0x080c, 0x9596, 0x0168, 0x6837, 0x0103, 0x684b, 0x0006,
- 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x080c, 0x510c, 0x080c,
- 0x9742, 0x00de, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, 0x080c,
- 0x6b73, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, 0x0002, 0x8b74,
- 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72,
- 0x8b72, 0x8b72, 0x8b86, 0x8b86, 0x8b86, 0x8b86, 0x8b72, 0x8b91,
- 0x8b72, 0x8b86, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x2001, 0xafa5,
- 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x6c50, 0x6010, 0xa088,
- 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x0005, 0x080c, 0x6b73,
- 0x2001, 0xafa5, 0x2004, 0x603e, 0x6003, 0x000f, 0x080c, 0x6c50,
- 0x0005, 0x080c, 0x6b73, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005,
- 0xa182, 0x0040, 0x0002, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae,
- 0x8bb0, 0x8c88, 0x8ca9, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae,
- 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x080c, 0x14f6,
- 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2071, 0xb280, 0x7124, 0x610a,
- 0x2071, 0xb28c, 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff,
- 0x0904, 0x8c54, 0xa68c, 0x0c00, 0x01e8, 0x00f6, 0x2c78, 0x080c,
- 0x5029, 0x00fe, 0x0198, 0x684c, 0xd0ac, 0x0180, 0x6020, 0xd0dc,
- 0x1168, 0x6850, 0xd0bc, 0x1150, 0x7318, 0x6814, 0xa306, 0x1904,
- 0x8c66, 0x731c, 0x6810, 0xa306, 0x1904, 0x8c66, 0x7318, 0x6b62,
- 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0518, 0xa186,
- 0x0028, 0x1128, 0x080c, 0x9767, 0x684b, 0x001c, 0x00e8, 0xd6dc,
- 0x01a0, 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0170, 0x6914, 0x6a10,
- 0x2100, 0xa205, 0x0148, 0x7018, 0xa106, 0x1118, 0x701c, 0xa206,
- 0x0118, 0x6962, 0x6a5e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0x684b,
- 0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e,
- 0xd6c4, 0x01f0, 0xa686, 0x0100, 0x1140, 0x2001, 0xb299, 0x2004,
- 0xa005, 0x1118, 0xc6c4, 0x0804, 0x8bbf, 0x7328, 0x732c, 0x6b56,
- 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036,
- 0x2308, 0x2019, 0xb298, 0xad90, 0x0019, 0x080c, 0x927f, 0x003e,
- 0xd6cc, 0x0904, 0x8c79, 0x7124, 0x695a, 0x81ff, 0x0904, 0x8c79,
- 0xa192, 0x0021, 0x1250, 0x2071, 0xb298, 0x831c, 0x2300, 0xae18,
- 0xad90, 0x001d, 0x080c, 0x927f, 0x04a0, 0x6838, 0xd0fc, 0x0120,
- 0x2009, 0x0020, 0x695a, 0x0c78, 0x00f6, 0x2d78, 0x080c, 0x9224,
- 0x00fe, 0x080c, 0x926f, 0x0438, 0x00f6, 0x2c78, 0x080c, 0x5029,
- 0x00fe, 0x0188, 0x684c, 0xd0ac, 0x0170, 0x6020, 0xd0dc, 0x1158,
- 0x6850, 0xd0bc, 0x1140, 0x684c, 0xd0f4, 0x1128, 0x080c, 0x9866,
- 0x00de, 0x00ee, 0x00e0, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46,
- 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c,
- 0x8e04, 0x080c, 0x510c, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
- 0x080c, 0x9834, 0x00de, 0x00ee, 0x1110, 0x080c, 0x8078, 0x0005,
- 0x00f6, 0x6003, 0x0003, 0x2079, 0xb28c, 0x7c04, 0x7b00, 0x7e0c,
- 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0120, 0x6003, 0x0002,
- 0x00fe, 0x0005, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x603f,
- 0x0000, 0x2c10, 0x080c, 0x1e6e, 0x080c, 0x680b, 0x080c, 0x6d0d,
- 0x0005, 0x2001, 0xafa5, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110,
- 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1824, 0x0005,
- 0xa182, 0x0040, 0x0002, 0x8cce, 0x8cce, 0x8cce, 0x8cce, 0x8cce,
- 0x8cd0, 0x8d61, 0x8cce, 0x8cce, 0x8d77, 0x8ddb, 0x8cce, 0x8cce,
- 0x8cce, 0x8cce, 0x8dea, 0x8cce, 0x8cce, 0x8cce, 0x080c, 0x14f6,
- 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xb28c, 0x6110, 0x2178,
- 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218,
- 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x8d5c, 0xa694,
- 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e,
- 0xa284, 0x0300, 0x0904, 0x8d5c, 0x080c, 0x15d9, 0x090c, 0x14f6,
- 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838,
- 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00,
- 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186,
- 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060,
- 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b,
- 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854,
- 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff,
- 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308,
- 0x2019, 0xb298, 0xad90, 0x0019, 0x080c, 0x927f, 0x003e, 0xd6cc,
- 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250,
- 0x2071, 0xb298, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c,
- 0x927f, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a,
- 0x0c78, 0x2d78, 0x080c, 0x9224, 0x00de, 0x00ee, 0x00fe, 0x007e,
- 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0xb28c, 0x7c04, 0x7b00,
- 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e,
- 0x00fe, 0x2c10, 0x080c, 0x1e6e, 0x080c, 0x781a, 0x0005, 0x00d6,
- 0x00f6, 0x2c78, 0x080c, 0x5029, 0x00fe, 0x0120, 0x2001, 0xafa5,
- 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x6c05, 0x080c, 0x6d0d,
- 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x8dd9, 0xd1cc, 0x0540,
- 0x6948, 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850,
- 0x0006, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156,
- 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0x8da1, 0x015e,
- 0x000e, 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1600,
- 0x0418, 0x0016, 0x080c, 0x1600, 0x00de, 0x080c, 0x926f, 0x00e0,
- 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180,
- 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc, 0x0118,
- 0x684b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0010,
- 0x684b, 0x0000, 0x080c, 0x510c, 0x080c, 0x9834, 0x1110, 0x080c,
- 0x8078, 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x7a64, 0x6003,
- 0x0002, 0x2001, 0xafa5, 0x2004, 0x603e, 0x080c, 0x6c05, 0x080c,
- 0x6d0d, 0x0005, 0x080c, 0x6c05, 0x080c, 0x2ad9, 0x00d6, 0x6110,
- 0x2168, 0x080c, 0x9596, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029,
- 0x6847, 0x0000, 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c,
- 0x8078, 0x080c, 0x6d0d, 0x0005, 0x684b, 0x0015, 0xd1fc, 0x0138,
- 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962,
- 0x685e, 0x0005, 0xa182, 0x0040, 0x0002, 0x8e28, 0x8e28, 0x8e28,
- 0x8e28, 0x8e28, 0x8e2a, 0x8e28, 0x8ee3, 0x8eef, 0x8e28, 0x8e28,
- 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28,
- 0x080c, 0x14f6, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xb28c,
- 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x00f6, 0x2c78, 0x080c,
- 0x5029, 0x00fe, 0x0150, 0xa684, 0x00ff, 0x1138, 0x6020, 0xd0f4,
- 0x0120, 0x080c, 0x9866, 0x0804, 0x8ede, 0x7e46, 0x7f4c, 0xc7e5,
- 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0904,
- 0x8ed4, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862,
- 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0x8ed2, 0xa686, 0x0100,
- 0x1140, 0x2001, 0xb299, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x7e46,
- 0x0c28, 0x080c, 0x15d9, 0x090c, 0x14f6, 0x2d00, 0x784a, 0x7f4c,
- 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c,
- 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318,
- 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180,
- 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118,
- 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010,
- 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e,
- 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a,
- 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xb298,
- 0xad90, 0x0019, 0x080c, 0x927f, 0x003e, 0xd6cc, 0x01d8, 0x7124,
- 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, 0xb298,
- 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x927f, 0x0050,
- 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78,
- 0x080c, 0x9224, 0xd6dc, 0x1110, 0xa006, 0x0030, 0x2001, 0x0001,
- 0x2071, 0xb28c, 0x7218, 0x731c, 0x080c, 0x186f, 0x00de, 0x00ee,
- 0x00fe, 0x007e, 0x0005, 0x2001, 0xafa5, 0x2004, 0x603e, 0x20e1,
- 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1824, 0x0005, 0x2001,
- 0xafa5, 0x2004, 0x603e, 0x00d6, 0x6003, 0x0002, 0x6110, 0x2168,
- 0x694c, 0xd1e4, 0x0904, 0x8ff3, 0x603f, 0x0000, 0x00f6, 0x2c78,
- 0x080c, 0x5029, 0x00fe, 0x0548, 0x6814, 0x6910, 0xa115, 0x0528,
- 0x6a60, 0xa206, 0x1118, 0x685c, 0xa106, 0x01f8, 0x684c, 0xc0e4,
- 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000, 0x697c,
- 0x6810, 0xa102, 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6020,
- 0xc0f5, 0x6022, 0x00d6, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e,
- 0x00de, 0x080c, 0x9866, 0x0804, 0x8ff3, 0x694c, 0xd1cc, 0x0904,
- 0x8fc3, 0x6948, 0x6838, 0xd0fc, 0x0904, 0x8f88, 0x0016, 0x684c,
- 0x0006, 0x6850, 0x0006, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff,
- 0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c,
- 0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b,
- 0x0015, 0x080c, 0x99ee, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080,
- 0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c,
- 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x8e04,
- 0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d,
- 0xaf98, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012,
- 0x8318, 0x8210, 0x1f04, 0x8f76, 0x015e, 0x00fe, 0x000e, 0x6852,
- 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1600, 0x0804, 0x8fee,
- 0x0016, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002,
- 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c,
- 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c,
- 0x99ee, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128,
- 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130,
- 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x8e04, 0x6860, 0x7862,
- 0x685c, 0x785e, 0x684c, 0x784e, 0x00fe, 0x080c, 0x1600, 0x00de,
- 0x080c, 0x926f, 0x0458, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff,
- 0xa0b6, 0x0002, 0x01b0, 0xa086, 0x0028, 0x1118, 0x684b, 0x001c,
- 0x00d8, 0xd1dc, 0x0148, 0x684b, 0x0015, 0x080c, 0x99ee, 0x0118,
- 0x6944, 0xc1dc, 0x6946, 0x0080, 0xd1d4, 0x0118, 0x684b, 0x0007,
- 0x0058, 0x684b, 0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914,
- 0xa115, 0x0110, 0x080c, 0x8e04, 0x080c, 0x510c, 0x080c, 0x9834,
- 0x1110, 0x080c, 0x8078, 0x00de, 0x0005, 0x080c, 0x6b73, 0x0010,
- 0x080c, 0x6c05, 0x080c, 0x9596, 0x01c0, 0x00d6, 0x6110, 0x2168,
- 0x6837, 0x0103, 0x2009, 0xad0c, 0x210c, 0xd18c, 0x11c0, 0xd184,
- 0x1198, 0x6108, 0x694a, 0xa18e, 0x0029, 0x1110, 0x080c, 0xabfa,
- 0x6847, 0x0000, 0x080c, 0x510c, 0x00de, 0x080c, 0x8078, 0x080c,
- 0x6c50, 0x080c, 0x6d0d, 0x0005, 0x684b, 0x0004, 0x0c88, 0x684b,
- 0x0004, 0x0c70, 0xa182, 0x0040, 0x0002, 0x9038, 0x9038, 0x9038,
- 0x9038, 0x9038, 0x903a, 0x9038, 0x903d, 0x9038, 0x9038, 0x9038,
- 0x9038, 0x9038, 0x9038, 0x9038, 0x9038, 0x9038, 0x9038, 0x9038,
- 0x080c, 0x14f6, 0x080c, 0x8078, 0x0005, 0x0006, 0x0026, 0xa016,
- 0x080c, 0x1824, 0x002e, 0x000e, 0x0005, 0xa182, 0x0085, 0x0002,
- 0x9051, 0x904f, 0x904f, 0x905d, 0x904f, 0x904f, 0x904f, 0x080c,
- 0x14f6, 0x6003, 0x0001, 0x6106, 0x080c, 0x67a8, 0x0126, 0x2091,
- 0x8000, 0x080c, 0x6c50, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6,
- 0x00e6, 0x2071, 0xb280, 0x7224, 0x6212, 0x7220, 0x080c, 0x9586,
- 0x01a0, 0x2268, 0x6800, 0xa086, 0x0000, 0x0178, 0x6018, 0x6d18,
- 0xa52e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0x928f, 0x00ce, 0x0128,
- 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, 0x6003,
- 0x0001, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00f6, 0x2278, 0x080c,
- 0x5029, 0x00fe, 0x0150, 0x6820, 0xd0ec, 0x0138, 0x00c6, 0x2260,
- 0x603f, 0x0000, 0x080c, 0x9866, 0x00ce, 0x00ee, 0x00de, 0x005e,
- 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085,
- 0x0a0c, 0x14f6, 0xa08a, 0x008c, 0x1a0c, 0x14f6, 0xa082, 0x0085,
- 0x0072, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x14f6,
- 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0x90be,
- 0x90c0, 0x90c0, 0x90be, 0x90be, 0x90be, 0x90be, 0x080c, 0x14f6,
- 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0xa186,
- 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x04a8, 0xa186,
- 0x0027, 0x11e8, 0x080c, 0x6b73, 0x080c, 0x2ad9, 0x00d6, 0x6010,
- 0x2068, 0x080c, 0x9596, 0x0150, 0x6837, 0x0103, 0x6847, 0x0000,
- 0x684b, 0x0029, 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c,
- 0x8078, 0x080c, 0x6c50, 0x0005, 0x080c, 0x80be, 0x0ce0, 0xa186,
- 0x0014, 0x1dd0, 0x080c, 0x6b73, 0x00d6, 0x6010, 0x2068, 0x080c,
- 0x9596, 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0006,
- 0x6850, 0xc0ec, 0x6852, 0x08f0, 0x0002, 0x910e, 0x910c, 0x910c,
- 0x910c, 0x910c, 0x910c, 0x9126, 0x080c, 0x14f6, 0x080c, 0x6b73,
- 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186,
- 0x0035, 0x1118, 0x2001, 0xafa3, 0x0010, 0x2001, 0xafa4, 0x2004,
- 0x6016, 0x6003, 0x000c, 0x080c, 0x6c50, 0x0005, 0x080c, 0x6b73,
- 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186,
- 0x0035, 0x1118, 0x2001, 0xafa3, 0x0010, 0x2001, 0xafa4, 0x2004,
- 0x6016, 0x6003, 0x000e, 0x080c, 0x6c50, 0x0005, 0xa182, 0x008c,
- 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x80be, 0x0005,
- 0x914f, 0x914f, 0x914f, 0x914f, 0x9151, 0x91a4, 0x914f, 0x080c,
- 0x14f6, 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x5029, 0x00fe, 0x0168,
- 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186,
- 0x0035, 0x1118, 0x00de, 0x0804, 0x91b7, 0x080c, 0x9742, 0x080c,
- 0x9596, 0x01c8, 0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4,
- 0x0128, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118,
- 0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9803, 0x6847,
- 0x0000, 0x080c, 0x510c, 0x2c68, 0x080c, 0x8022, 0x01c0, 0x6003,
- 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0xb28e, 0x210c,
- 0x6136, 0x2009, 0xb28f, 0x210c, 0x613a, 0x6918, 0x611a, 0x080c,
- 0x9956, 0x6950, 0x6152, 0x601f, 0x0001, 0x080c, 0x67a8, 0x2d60,
- 0x080c, 0x8078, 0x00de, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5029,
- 0x00fe, 0x0598, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035,
- 0x0130, 0xa186, 0x001e, 0x0118, 0xa186, 0x0039, 0x1530, 0x00d6,
- 0x2c68, 0x080c, 0x9a34, 0x1904, 0x91fc, 0x080c, 0x8022, 0x01d8,
- 0x6106, 0x6003, 0x0001, 0x601f, 0x0001, 0x6918, 0x611a, 0x6928,
- 0x612a, 0x692c, 0x612e, 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934,
- 0x6136, 0x6938, 0x613a, 0x6950, 0x6152, 0x080c, 0x9956, 0x080c,
- 0x67a8, 0x080c, 0x6c50, 0x2d60, 0x00f8, 0x00d6, 0x6010, 0x2068,
- 0x080c, 0x9596, 0x01c8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128,
- 0xc0ec, 0x6852, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b,
- 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9803, 0x6847, 0x0000,
- 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c, 0x8078, 0x0005,
- 0x0016, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9596, 0x0140, 0x6837,
- 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x080c, 0x510c, 0x00de,
- 0x001e, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186,
- 0x0027, 0x0118, 0x080c, 0x80be, 0x0030, 0x080c, 0x6b73, 0x080c,
- 0x974e, 0x080c, 0x6c50, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6,
- 0x2029, 0x0001, 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100,
- 0x2130, 0x2069, 0xb298, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020,
- 0xaf90, 0x001d, 0x080c, 0x927f, 0xa6b2, 0x0020, 0x7804, 0xa06d,
- 0x0110, 0x080c, 0x1600, 0x080c, 0x15d9, 0x0500, 0x8528, 0x6837,
- 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228,
- 0x2608, 0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009,
- 0x003c, 0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f,
- 0xa5ad, 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f,
- 0xa5ad, 0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6,
- 0x8dff, 0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c,
- 0x510c, 0x2f68, 0x0cb8, 0x080c, 0x510c, 0x00fe, 0x0005, 0x0156,
- 0xa184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007,
- 0x2012, 0x8318, 0x8210, 0x1f04, 0x9286, 0x015e, 0x0005, 0x0066,
- 0x0126, 0x2091, 0x8000, 0x2031, 0x0001, 0x601c, 0xa084, 0x000f,
- 0x0083, 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066,
- 0x2031, 0x0000, 0x601c, 0xa084, 0x000f, 0x001b, 0x006e, 0x012e,
- 0x0005, 0x92c3, 0x92c3, 0x92be, 0x92e5, 0x92b1, 0x92be, 0x92e5,
- 0x92be, 0x080c, 0x14f6, 0x0036, 0x2019, 0x0010, 0x080c, 0xa566,
- 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0xa006, 0x0005,
- 0xa085, 0x0001, 0x0005, 0x00d6, 0x86ff, 0x11d8, 0x6010, 0x2068,
- 0x080c, 0x9596, 0x01c0, 0x6834, 0xa086, 0x0139, 0x1128, 0x684b,
- 0x0005, 0x6853, 0x0000, 0x0028, 0xa00e, 0x2001, 0x0005, 0x080c,
- 0x51df, 0x080c, 0x9803, 0x080c, 0x510c, 0x080c, 0x8078, 0xa085,
- 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, 0xa08a, 0x0010,
- 0x1a0c, 0x14f6, 0x000b, 0x0005, 0x92fc, 0x9319, 0x92fe, 0x9338,
- 0x9316, 0x92fc, 0x92be, 0x92c3, 0x92c3, 0x92be, 0x92be, 0x92be,
- 0x92be, 0x92be, 0x92be, 0x92be, 0x080c, 0x14f6, 0x86ff, 0x1198,
- 0x00d6, 0x6010, 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0x9803,
- 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c,
- 0x67a8, 0x080c, 0x6c50, 0xa085, 0x0001, 0x0005, 0x080c, 0x190b,
- 0x0c28, 0x00e6, 0x2071, 0xafc7, 0x7024, 0xac06, 0x1110, 0x080c,
- 0x79e1, 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, 0x1150, 0x0086,
- 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x7b9a, 0x009e, 0x008e,
- 0x0010, 0x080c, 0x78de, 0x00ee, 0x1948, 0x080c, 0x92be, 0x0005,
- 0x0036, 0x00e6, 0x2071, 0xafc7, 0x703c, 0xac06, 0x1140, 0x2019,
- 0x0000, 0x080c, 0x7a64, 0x00ee, 0x003e, 0x0804, 0x92fe, 0x080c,
- 0x7cb8, 0x00ee, 0x003e, 0x1904, 0x92fe, 0x080c, 0x92be, 0x0005,
- 0x00c6, 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, 0x9369,
- 0x93d3, 0x9501, 0x9374, 0x974e, 0x9369, 0xa558, 0x8078, 0x93d3,
- 0x9362, 0x955f, 0x080c, 0x14f6, 0x080c, 0x9789, 0x1110, 0x080c,
- 0x85f3, 0x0005, 0x080c, 0x6b73, 0x080c, 0x6c50, 0x080c, 0x8078,
- 0x0005, 0x6017, 0x0001, 0x0005, 0x6010, 0xa080, 0x0019, 0x2c02,
- 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x14f6, 0x000b, 0x0005, 0x938f,
- 0x9391, 0x93b1, 0x93c3, 0x93d0, 0x938f, 0x9369, 0x9369, 0x9369,
- 0x93c3, 0x93c3, 0x938f, 0x938f, 0x938f, 0x938f, 0x93cd, 0x080c,
- 0x14f6, 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071,
- 0xafc7, 0x7024, 0xac06, 0x0190, 0x080c, 0x78de, 0x6007, 0x0085,
- 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xafa4, 0x2004, 0x6016,
- 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ee, 0x0005, 0x6017, 0x0001,
- 0x0cd8, 0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de,
- 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x67a8,
- 0x080c, 0x6c50, 0x0005, 0x00d6, 0x6017, 0x0001, 0x6010, 0x2068,
- 0x6850, 0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, 0x8078, 0x0005,
- 0x080c, 0x190b, 0x08f0, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x14f6,
- 0x000b, 0x0005, 0x93ea, 0x9371, 0x93ec, 0x93ea, 0x93ec, 0x93ec,
- 0x936a, 0x93ea, 0x9364, 0x9364, 0x93ea, 0x93ea, 0x93ea, 0x93ea,
- 0x93ea, 0x93ea, 0x080c, 0x14f6, 0x00d6, 0x6018, 0x2068, 0x6804,
- 0xa084, 0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, 0x14f6, 0x000b,
- 0x0005, 0x9405, 0x94a7, 0x9407, 0x9441, 0x9407, 0x9441, 0x9407,
- 0x9411, 0x9405, 0x9441, 0x9405, 0x942d, 0x080c, 0x14f6, 0x6004,
- 0xa08e, 0x0016, 0x0588, 0xa08e, 0x0004, 0x0570, 0xa08e, 0x0002,
- 0x0558, 0x6004, 0x080c, 0x9789, 0x0904, 0x94c0, 0xa08e, 0x0021,
- 0x0904, 0x94c4, 0xa08e, 0x0022, 0x0904, 0x94c0, 0xa08e, 0x003d,
- 0x0904, 0x94c4, 0xa08e, 0x0039, 0x0904, 0x94c8, 0xa08e, 0x0035,
- 0x0904, 0x94c8, 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, 0x1150,
- 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa086,
- 0x0006, 0x0110, 0x080c, 0x2ad9, 0x080c, 0x85f3, 0x080c, 0x974e,
- 0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, 0x9498,
- 0xa186, 0x0002, 0x1518, 0x6018, 0x2068, 0x2001, 0xad34, 0x2004,
- 0xd0ac, 0x1904, 0x94ea, 0x68a0, 0xd0bc, 0x1904, 0x94ea, 0x6840,
- 0xa084, 0x00ff, 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, 0x0000,
- 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, 0x8022,
- 0x0128, 0x2d00, 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, 0x00ce,
- 0x6004, 0xa08e, 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, 0x2004,
- 0xa086, 0x007e, 0x1170, 0x2009, 0xad34, 0x2104, 0xc085, 0x200a,
- 0x00e6, 0x2071, 0xad00, 0x080c, 0x48f5, 0x00ee, 0x080c, 0x85f3,
- 0x0020, 0x080c, 0x85f3, 0x080c, 0x2ad9, 0x00e6, 0x0126, 0x2091,
- 0x8000, 0x080c, 0x2aff, 0x012e, 0x00ee, 0x080c, 0x974e, 0x0005,
- 0x2001, 0x0002, 0x080c, 0x4c30, 0x6003, 0x0001, 0x6007, 0x0002,
- 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00de, 0x00ce, 0x0c80, 0x00c6,
- 0x00d6, 0x6104, 0xa186, 0x0016, 0x0d58, 0x6018, 0x2068, 0x6840,
- 0xa084, 0x00ff, 0xa005, 0x0904, 0x946e, 0x8001, 0x6842, 0x6003,
- 0x0001, 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00de, 0x00ce, 0x08b8,
- 0x080c, 0x85f3, 0x0804, 0x943e, 0x080c, 0x8621, 0x0804, 0x943e,
- 0x00d6, 0x2c68, 0x6104, 0x080c, 0x9a34, 0x00de, 0x0118, 0x080c,
- 0x8078, 0x00b8, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105,
- 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038,
- 0x600a, 0x2001, 0xafa4, 0x2004, 0x6016, 0x080c, 0x67a8, 0x080c,
- 0x6c50, 0x0005, 0x00de, 0x00ce, 0x080c, 0x85f3, 0x080c, 0x2ad9,
- 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2aff, 0x6013, 0x0000,
- 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x012e, 0x00ee,
- 0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x14f6, 0x000b, 0x0005,
- 0x9518, 0x9518, 0x9518, 0x9518, 0x9518, 0x9518, 0x9518, 0x9518,
- 0x9518, 0x9369, 0x9518, 0x9371, 0x951a, 0x9371, 0x9527, 0x9518,
- 0x080c, 0x14f6, 0x6004, 0xa086, 0x008b, 0x0148, 0x6007, 0x008b,
- 0x6003, 0x000d, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0005, 0x080c,
- 0x9742, 0x080c, 0x9596, 0x0580, 0x080c, 0x2ad9, 0x00d6, 0x080c,
- 0x9596, 0x0168, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006,
- 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c, 0x510c, 0x2c68,
- 0x080c, 0x8022, 0x0150, 0x6818, 0x601a, 0x080c, 0x9956, 0x00c6,
- 0x2d60, 0x080c, 0x974e, 0x00ce, 0x0008, 0x2d60, 0x00de, 0x6013,
- 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c,
- 0x67ee, 0x080c, 0x6c50, 0x0010, 0x080c, 0x974e, 0x0005, 0x6000,
- 0xa08a, 0x0010, 0x1a0c, 0x14f6, 0x000b, 0x0005, 0x9576, 0x9576,
- 0x9576, 0x9578, 0x9579, 0x9576, 0x9576, 0x9576, 0x9576, 0x9576,
- 0x9576, 0x9576, 0x9576, 0x9576, 0x9576, 0x9576, 0x080c, 0x14f6,
- 0x0005, 0x080c, 0x7cb8, 0x190c, 0x14f6, 0x6110, 0x2168, 0x684b,
- 0x0006, 0x080c, 0x510c, 0x080c, 0x8078, 0x0005, 0xa284, 0x0007,
- 0x1158, 0xa282, 0xb400, 0x0240, 0x2001, 0xad16, 0x2004, 0xa202,
- 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210,
- 0xa294, 0xf000, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006,
- 0x0126, 0x2091, 0x8000, 0x2061, 0xb400, 0x2071, 0xad00, 0x7344,
- 0x7064, 0xa302, 0x12a8, 0x601c, 0xa206, 0x1160, 0x080c, 0x98e3,
- 0x0148, 0x080c, 0x9789, 0x1110, 0x080c, 0x85f3, 0x00c6, 0x080c,
- 0x8078, 0x00ce, 0xace0, 0x0018, 0x7058, 0xac02, 0x1208, 0x0c38,
- 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6,
- 0x0016, 0xa188, 0xae34, 0x210c, 0x81ff, 0x0170, 0x2061, 0xb400,
- 0x2071, 0xad00, 0x0016, 0x080c, 0x8022, 0x001e, 0x0138, 0x611a,
- 0x080c, 0x2ad9, 0x080c, 0x8078, 0xa006, 0x0010, 0xa085, 0x0001,
- 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091,
- 0x8000, 0x00c6, 0x080c, 0x8022, 0x005e, 0x0180, 0x6612, 0x651a,
- 0x080c, 0x9956, 0x601f, 0x0003, 0x2009, 0x004b, 0x080c, 0x80a7,
- 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0,
- 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c,
- 0x8022, 0x005e, 0x0508, 0x6013, 0x0000, 0x651a, 0x080c, 0x9956,
- 0x601f, 0x0003, 0x00c6, 0x2560, 0x080c, 0x4ecf, 0x00ce, 0x080c,
- 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c,
- 0xa712, 0x007e, 0x2009, 0x004c, 0x080c, 0x80a7, 0xa085, 0x0001,
- 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00f6, 0x00c6,
- 0x0046, 0x00c6, 0x080c, 0x8022, 0x2c78, 0x00ce, 0x0180, 0x7e12,
- 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x080c, 0x9683,
- 0x2f60, 0x2009, 0x004d, 0x080c, 0x80a7, 0xa085, 0x0001, 0x004e,
- 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c,
- 0x8022, 0x2c78, 0x00ce, 0x0178, 0x7e12, 0x2c00, 0x781a, 0x781f,
- 0x0003, 0x2021, 0x0005, 0x0439, 0x2f60, 0x2009, 0x004e, 0x080c,
- 0x80a7, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6,
- 0x00c6, 0x0046, 0x00c6, 0x080c, 0x8022, 0x2c78, 0x00ce, 0x0178,
- 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0004, 0x0059,
- 0x2f60, 0x2009, 0x0052, 0x080c, 0x80a7, 0xa085, 0x0001, 0x004e,
- 0x00ce, 0x00fe, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000,
- 0x080c, 0x4e71, 0x0118, 0x2001, 0x9688, 0x0028, 0x080c, 0x4e43,
- 0x0158, 0x2001, 0x968e, 0x0006, 0xa00e, 0x2400, 0x080c, 0x51df,
- 0x080c, 0x510c, 0x000e, 0x0807, 0x2418, 0x080c, 0x6b15, 0x62a0,
- 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x6900,
- 0x008e, 0x080c, 0x681d, 0x2f08, 0x2648, 0x080c, 0xa712, 0x613c,
- 0x81ff, 0x090c, 0x69a9, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6,
- 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0188,
- 0x660a, 0x611a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012,
- 0x2009, 0x001f, 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce,
- 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6,
- 0x080c, 0x8022, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0x9956,
- 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, 0x80a7,
- 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6,
- 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0188,
- 0x660a, 0x611a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012,
- 0x2009, 0x003d, 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce,
- 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6,
- 0x080c, 0x9807, 0x001e, 0x0180, 0x611a, 0x080c, 0x9956, 0x601f,
- 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x80a7, 0xa085,
- 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126,
- 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0188, 0x660a,
- 0x611a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009,
- 0x0044, 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005,
- 0xa006, 0x0cd8, 0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff,
- 0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, 0x6000,
- 0xa086, 0x0000, 0x0190, 0x6013, 0x0000, 0x601f, 0x0007, 0x2001,
- 0xafa3, 0x2004, 0x0006, 0xa082, 0x0051, 0x000e, 0x0208, 0x8004,
- 0x6016, 0x080c, 0xabb4, 0x603f, 0x0000, 0x000e, 0x0005, 0x0066,
- 0x00c6, 0x00d6, 0x2031, 0xad52, 0x2634, 0xd6e4, 0x0128, 0x6618,
- 0x2660, 0x6e48, 0x080c, 0x4dfc, 0x00de, 0x00ce, 0x006e, 0x0005,
- 0x0006, 0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003,
- 0x0128, 0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e,
- 0x0005, 0x0006, 0x00d6, 0x6010, 0xa06d, 0x0148, 0x6834, 0xa086,
- 0x0139, 0x0138, 0x6838, 0xd0fc, 0x0110, 0xa006, 0x0010, 0xa085,
- 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000,
- 0x00c6, 0x080c, 0x8022, 0x001e, 0x0190, 0x611a, 0x080c, 0x9956,
- 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, 0x2ad9, 0x2009, 0x0028,
- 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006,
- 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, 0xad20, 0x2204, 0xa086,
- 0x0074, 0x1148, 0x080c, 0x8943, 0x6003, 0x0001, 0x6007, 0x0029,
- 0x080c, 0x67ee, 0x0020, 0x080c, 0x85f3, 0x080c, 0x8078, 0x0005,
- 0xa186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x4c30, 0x00e8,
- 0xa186, 0x0015, 0x11e8, 0x2011, 0xad20, 0x2204, 0xa086, 0x0014,
- 0x11b8, 0x00d6, 0x6018, 0x2068, 0x080c, 0x4d72, 0x00de, 0x080c,
- 0x89f7, 0x1170, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005,
- 0x0138, 0x2001, 0x0006, 0x080c, 0x4c30, 0x080c, 0x81f6, 0x0020,
- 0x080c, 0x85f3, 0x080c, 0x8078, 0x0005, 0x6848, 0xa086, 0x0005,
- 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852, 0x0005, 0x00e6,
- 0x0126, 0x2071, 0xad00, 0x2091, 0x8000, 0x7544, 0xa582, 0x0001,
- 0x0608, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0,
- 0x0018, 0x7058, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xb400, 0x0c98,
- 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x0018, 0x7058, 0xa502,
- 0x1230, 0x754a, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704b,
- 0xb400, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xb28c, 0x7014,
- 0xd0e4, 0x0150, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050,
- 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ee, 0x0005, 0x00c6, 0x00f6,
- 0x2c78, 0x080c, 0x5029, 0x00fe, 0x0120, 0x601c, 0xa084, 0x000f,
- 0x0013, 0x00ce, 0x0005, 0x9369, 0x985e, 0x9861, 0x9864, 0xa9a7,
- 0xa9c2, 0xa9c5, 0x9369, 0x9369, 0x080c, 0x14f6, 0xe000, 0xe000,
- 0x0005, 0xe000, 0xe000, 0x0005, 0x0009, 0x0005, 0x00f6, 0x2c78,
- 0x080c, 0x5029, 0x0538, 0x080c, 0x8022, 0x1128, 0x2001, 0xafa5,
- 0x2004, 0x783e, 0x00f8, 0x7818, 0x601a, 0x080c, 0x9956, 0x781c,
- 0xa086, 0x0003, 0x0128, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0020,
- 0x7808, 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007,
- 0x0035, 0x6003, 0x0001, 0x7950, 0x6152, 0x080c, 0x67a8, 0x080c,
- 0x6c50, 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x682c, 0x6032,
- 0xa08e, 0x0001, 0x0138, 0xa086, 0x0005, 0x0140, 0xa006, 0x602a,
- 0x602e, 0x00a0, 0x6820, 0xc0f4, 0xc0d5, 0x6822, 0x6810, 0x2078,
- 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x1e78, 0x6834,
- 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036,
- 0x6808, 0x603a, 0x6918, 0x611a, 0x6950, 0x6152, 0x601f, 0x0001,
- 0x6007, 0x0039, 0x6003, 0x0001, 0x080c, 0x67a8, 0x6803, 0x0002,
- 0x00fe, 0x001e, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5029, 0x1118,
- 0xa085, 0x0001, 0x0070, 0x6020, 0xd0f4, 0x1150, 0xc0f5, 0x6022,
- 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, 0x6036, 0x080c, 0x190b,
- 0xa006, 0x00fe, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0034,
- 0x01b8, 0xa08e, 0x0035, 0x01a0, 0xa08e, 0x0036, 0x0188, 0xa08e,
- 0x0037, 0x0170, 0xa08e, 0x0038, 0x0158, 0xa08e, 0x0039, 0x0140,
- 0xa08e, 0x003a, 0x0128, 0xa08e, 0x003b, 0x0110, 0xa085, 0x0001,
- 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6,
- 0x2001, 0xaf9f, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x080c,
- 0x6665, 0x2001, 0xafa3, 0x82ff, 0x1110, 0x2011, 0x0002, 0x2202,
- 0x2001, 0xafa1, 0x200c, 0x8000, 0x2014, 0x2071, 0xaf8d, 0x711a,
- 0x721e, 0x2001, 0x0064, 0x080c, 0x6665, 0x2001, 0xafa4, 0x82ff,
- 0x1110, 0x2011, 0x0002, 0x2202, 0x2009, 0xafa5, 0xa280, 0x000a,
- 0x200a, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006,
- 0x00e6, 0x2001, 0xafa3, 0x2003, 0x0028, 0x2001, 0xafa4, 0x2003,
- 0x0014, 0x2071, 0xaf8d, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001,
- 0xafa5, 0x2003, 0x001e, 0x00ee, 0x000e, 0x0005, 0x00d6, 0x6054,
- 0xa06d, 0x0110, 0x080c, 0x15f0, 0x00de, 0x0005, 0x0005, 0x00c6,
- 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0178,
- 0x611a, 0x0ca1, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033,
- 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006,
- 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xad00, 0xa186, 0x0015,
- 0x1500, 0x7080, 0xa086, 0x0018, 0x11e0, 0x6010, 0x2068, 0x6a3c,
- 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x6e05, 0x01d8, 0x706c, 0x6a50,
- 0xa206, 0x1160, 0x7070, 0x6a54, 0xa206, 0x1140, 0x6218, 0xa290,
- 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2b1e, 0x080c, 0x81f6,
- 0x0020, 0x080c, 0x85f3, 0x080c, 0x8078, 0x00fe, 0x00ee, 0x00de,
- 0x0005, 0x7050, 0x6a54, 0xa206, 0x0d48, 0x0c80, 0x00c6, 0x0126,
- 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0180, 0x611a,
- 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0043,
- 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006,
- 0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xad00, 0xa186, 0x0015,
- 0x11c0, 0x7080, 0xa086, 0x0004, 0x11a0, 0x6010, 0xa0e8, 0x000f,
- 0x2c78, 0x080c, 0x6e05, 0x01a8, 0x706c, 0x6a08, 0xa206, 0x1130,
- 0x7070, 0x6a0c, 0xa206, 0x1110, 0x080c, 0x2ad9, 0x080c, 0x81f6,
- 0x0020, 0x080c, 0x85f3, 0x080c, 0x8078, 0x00fe, 0x00ee, 0x00de,
- 0x0005, 0x7050, 0x6a0c, 0xa206, 0x0d78, 0x0c80, 0x0016, 0x0026,
- 0x684c, 0xd0ac, 0x0178, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0150,
- 0x6860, 0xa106, 0x1118, 0x685c, 0xa206, 0x0120, 0x6962, 0x6a5e,
- 0xa085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, 0x6310,
- 0x2368, 0x684a, 0x6952, 0xa29e, 0x4000, 0x1188, 0x00c6, 0x6318,
- 0x2360, 0x2009, 0x0000, 0x080c, 0x4f6e, 0x1108, 0xc185, 0x6000,
- 0xd0bc, 0x0108, 0xc18d, 0x6a66, 0x696a, 0x00ce, 0x0080, 0x6a66,
- 0x3918, 0xa398, 0x0006, 0x231c, 0x686b, 0x0004, 0x6b72, 0x00c6,
- 0x6318, 0x2360, 0x6004, 0xa084, 0x00ff, 0x686e, 0x00ce, 0x080c,
- 0x510c, 0x003e, 0x00de, 0x0005, 0x00c6, 0x0026, 0x0016, 0xa186,
- 0x0035, 0x0110, 0x6a34, 0x0008, 0x6a28, 0x080c, 0x9586, 0x01f0,
- 0x2260, 0x611c, 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x1190,
- 0x6834, 0xa206, 0x0140, 0x6838, 0xa206, 0x1160, 0x6108, 0x6834,
- 0xa106, 0x1140, 0x0020, 0x6008, 0x6938, 0xa106, 0x1118, 0x6018,
- 0x6918, 0xa106, 0x001e, 0x002e, 0x00ce, 0x0005, 0xa085, 0x0001,
- 0x0cc8, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013,
- 0x006e, 0x0005, 0x9a7a, 0x9eff, 0xa027, 0x9a7a, 0x9a7a, 0x9a7a,
- 0x9a7a, 0x9a7a, 0x9ab2, 0xa0a3, 0x9a7a, 0x9a7a, 0x9a7a, 0x9a7a,
- 0x9a7a, 0x9a7a, 0x080c, 0x14f6, 0x0066, 0x6000, 0xa0b2, 0x0010,
- 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, 0x9a95, 0xa4fd, 0x9a95,
- 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0xa4c1, 0xa545, 0x9a95,
- 0xaaea, 0xab1a, 0xaaea, 0xab1a, 0x9a95, 0x080c, 0x14f6, 0x0066,
- 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005,
- 0x9ab0, 0xa1d8, 0xa295, 0xa2c2, 0xa346, 0x9ab0, 0xa433, 0xa3de,
- 0xa0af, 0xa497, 0xa4ac, 0x9ab0, 0x9ab0, 0x9ab0, 0x9ab0, 0x9ab0,
- 0x080c, 0x14f6, 0xa1b2, 0x0080, 0x1a0c, 0x14f6, 0x2100, 0xa1b2,
- 0x0040, 0x1a04, 0x9e79, 0x0002, 0x9afc, 0x9cab, 0x9afc, 0x9afc,
- 0x9afc, 0x9cb2, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc,
- 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc,
- 0x9afc, 0x9afc, 0x9afc, 0x9afe, 0x9b5a, 0x9b65, 0x9ba6, 0x9bc0,
- 0x9c3e, 0x9c9c, 0x9afc, 0x9afc, 0x9cb5, 0x9afc, 0x9afc, 0x9cc4,
- 0x9ccb, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9d42, 0x9afc,
- 0x9afc, 0x9d4d, 0x9afc, 0x9afc, 0x9d18, 0x9afc, 0x9afc, 0x9afc,
- 0x9d61, 0x9afc, 0x9afc, 0x9afc, 0x9dd5, 0x9afc, 0x9afc, 0x9afc,
- 0x9afc, 0x9afc, 0x9afc, 0x9e40, 0x080c, 0x14f6, 0x080c, 0x502d,
- 0x1140, 0x2001, 0xad34, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008,
- 0x1140, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804,
- 0x9ca6, 0x080c, 0x501d, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016,
- 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x68e7,
- 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, 0xa712,
- 0x007e, 0x001e, 0x2e60, 0x080c, 0x4ecf, 0x001e, 0x002e, 0x003e,
- 0x00ce, 0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x4ceb, 0x00ce,
- 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278,
- 0x080c, 0xa656, 0x1904, 0x9ba0, 0x080c, 0xa5f6, 0x1120, 0x6007,
- 0x0008, 0x0804, 0x9ca6, 0x6007, 0x0009, 0x0804, 0x9ca6, 0x080c,
- 0xa801, 0x0128, 0x080c, 0xa656, 0x0d78, 0x0804, 0x9ba0, 0x6013,
- 0x1900, 0x0c88, 0x6106, 0x080c, 0xa5a6, 0x6007, 0x0006, 0x0804,
- 0x9ca6, 0x6007, 0x0007, 0x0804, 0x9ca6, 0x080c, 0xab4e, 0x1904,
- 0x9e76, 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637,
- 0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, 0xa6b4,
- 0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, 0xa686,
- 0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xa6b4, 0x11a0, 0xa686,
- 0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009,
- 0x0000, 0x080c, 0x2b1e, 0x002e, 0x080c, 0x4d72, 0x6007, 0x000a,
- 0x00de, 0x0804, 0x9ca6, 0x6007, 0x000b, 0x00de, 0x0804, 0x9ca6,
- 0x080c, 0x2ad9, 0x6007, 0x0001, 0x0804, 0x9ca6, 0x080c, 0xab4e,
- 0x1904, 0x9e76, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa686,
- 0x0707, 0x0d70, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009,
- 0x0000, 0x080c, 0x2b1e, 0x002e, 0x6007, 0x000c, 0x0804, 0x9ca6,
- 0x080c, 0x502d, 0x1140, 0x2001, 0xad34, 0x2004, 0xa084, 0x0009,
- 0xa086, 0x0008, 0x1110, 0x0804, 0x9b09, 0x080c, 0x501d, 0x6618,
- 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x06e8,
- 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x4c5d, 0x002e, 0x0050,
- 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0120, 0xa686, 0x0006,
- 0x1904, 0x9ba0, 0x080c, 0xa6c1, 0x1120, 0x6007, 0x000e, 0x0804,
- 0x9ca6, 0x0046, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff,
- 0x8427, 0x0046, 0x080c, 0x2ad9, 0x004e, 0x0016, 0xa006, 0x2009,
- 0xad52, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xa96c,
- 0x6018, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e,
- 0x004e, 0x6007, 0x0001, 0x0804, 0x9ca6, 0x2001, 0x0001, 0x080c,
- 0x4c1e, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019,
- 0xad05, 0x2011, 0xb290, 0x080c, 0x8a7c, 0x003e, 0x002e, 0x001e,
- 0x015e, 0xa005, 0x0168, 0xa6b4, 0xff00, 0x8637, 0xa682, 0x0004,
- 0x0a04, 0x9ba0, 0xa682, 0x0007, 0x0a04, 0x9bea, 0x0804, 0x9ba0,
- 0x6013, 0x1900, 0x6007, 0x0009, 0x0804, 0x9ca6, 0x080c, 0x502d,
- 0x1140, 0x2001, 0xad34, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008,
- 0x1110, 0x0804, 0x9b09, 0x080c, 0x501d, 0x6618, 0xa6b0, 0x0001,
- 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x06b0, 0xa6b4, 0xff00,
- 0x8637, 0xa686, 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0x9ba0,
- 0x080c, 0xa6e9, 0x1130, 0x080c, 0xa5f6, 0x1118, 0x6007, 0x0010,
- 0x04e8, 0x0046, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff,
- 0x8427, 0x0046, 0x080c, 0x2ad9, 0x004e, 0x0016, 0xa006, 0x2009,
- 0xad52, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xa96c,
- 0x6018, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e,
- 0x004e, 0x6007, 0x0001, 0x00d0, 0x080c, 0xa801, 0x0140, 0xa6b4,
- 0xff00, 0x8637, 0xa686, 0x0006, 0x0958, 0x0804, 0x9ba0, 0x6013,
- 0x1900, 0x6007, 0x0009, 0x0050, 0x080c, 0xab4e, 0x1904, 0x9e76,
- 0x080c, 0x9e98, 0x1904, 0x9ba0, 0x6007, 0x0012, 0x6003, 0x0001,
- 0x080c, 0x67ee, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c,
- 0x67ee, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, 0xab4e, 0x1904,
- 0x9e76, 0x080c, 0x9e98, 0x1904, 0x9ba0, 0x6007, 0x0020, 0x6003,
- 0x0001, 0x080c, 0x67ee, 0x0005, 0x6007, 0x0023, 0x6003, 0x0001,
- 0x080c, 0x67ee, 0x0005, 0x080c, 0xab4e, 0x1904, 0x9e76, 0x080c,
- 0x9e98, 0x1904, 0x9ba0, 0x0016, 0x0026, 0x2011, 0xb291, 0x2214,
- 0xa286, 0xffff, 0x0190, 0x2c08, 0x080c, 0x9586, 0x01d8, 0x2260,
- 0x2011, 0xb290, 0x2214, 0x6008, 0xa206, 0x11a0, 0x6018, 0xa190,
- 0x0006, 0x2214, 0xa206, 0x01e0, 0x0068, 0x2011, 0xb290, 0x2214,
- 0x2c08, 0x080c, 0xa940, 0x11a0, 0x2011, 0xb291, 0x2214, 0xa286,
- 0xffff, 0x01a0, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011,
- 0xb289, 0x2214, 0xa296, 0xffff, 0x1160, 0x6007, 0x0025, 0x0048,
- 0x601c, 0xa086, 0x0007, 0x1d70, 0x080c, 0x8078, 0x2160, 0x6007,
- 0x0025, 0x6003, 0x0001, 0x080c, 0x67ee, 0x002e, 0x001e, 0x0005,
- 0x2001, 0x0001, 0x080c, 0x4c1e, 0x0156, 0x0016, 0x0026, 0x0036,
- 0x20a9, 0x0004, 0x2019, 0xad05, 0x2011, 0xb296, 0x080c, 0x8a7c,
- 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804,
- 0x9ca6, 0x080c, 0x87bd, 0x080c, 0x574f, 0x1158, 0x0006, 0x0026,
- 0x0036, 0x080c, 0x576b, 0x0110, 0x080c, 0x5726, 0x003e, 0x002e,
- 0x000e, 0x0005, 0x6106, 0x080c, 0x9eb4, 0x6007, 0x002b, 0x0804,
- 0x9ca6, 0x6007, 0x002c, 0x0804, 0x9ca6, 0x080c, 0xab4e, 0x1904,
- 0x9e76, 0x080c, 0x9e98, 0x1904, 0x9ba0, 0x6106, 0x080c, 0x9eb8,
- 0x1120, 0x6007, 0x002e, 0x0804, 0x9ca6, 0x6007, 0x002f, 0x0804,
- 0x9ca6, 0x00e6, 0x00d6, 0x00c6, 0x6018, 0xa080, 0x0001, 0x200c,
- 0xa184, 0x00ff, 0xa086, 0x0006, 0x0158, 0xa184, 0xff00, 0x8007,
- 0xa086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0x9cab,
- 0x2001, 0xad71, 0x2004, 0xd0e4, 0x0904, 0x9dd2, 0x2071, 0xb28c,
- 0x7010, 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xad52,
- 0x2004, 0xd0a4, 0x0140, 0x6018, 0x2068, 0x6810, 0xa106, 0x1118,
- 0x6814, 0xa206, 0x01f8, 0x2001, 0xad52, 0x2004, 0xd0ac, 0x1580,
- 0x2069, 0xad00, 0x6870, 0xa206, 0x1558, 0x686c, 0xa106, 0x1540,
- 0x7210, 0x080c, 0x9586, 0x0548, 0x080c, 0xa9d4, 0x0530, 0x622a,
- 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x67a8, 0x00ce, 0x00de,
- 0x00ee, 0x0005, 0x7214, 0xa286, 0xffff, 0x0150, 0x080c, 0x9586,
- 0x01a0, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x1170, 0x0c08,
- 0x7210, 0x2c08, 0x080c, 0xa940, 0x2c10, 0x2160, 0x0130, 0x08c8,
- 0x6007, 0x0037, 0x6013, 0x1500, 0x08e8, 0x6007, 0x0037, 0x6013,
- 0x1700, 0x08c0, 0x6007, 0x0012, 0x08a8, 0x6018, 0xa080, 0x0001,
- 0x2004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006, 0x1904, 0x9cab,
- 0x00e6, 0x00d6, 0x00c6, 0x2001, 0xad71, 0x2004, 0xd0e4, 0x0904,
- 0x9e38, 0x2069, 0xad00, 0x2071, 0xb28c, 0x7008, 0x6036, 0x720c,
- 0x623a, 0xa286, 0xffff, 0x1140, 0x7208, 0x00c6, 0x2c08, 0x080c,
- 0xa940, 0x2c10, 0x00ce, 0x0588, 0x080c, 0x9586, 0x0570, 0x00c6,
- 0x0026, 0x2260, 0x080c, 0x928f, 0x002e, 0x00ce, 0x7118, 0xa18c,
- 0xff00, 0x810f, 0xa186, 0x0001, 0x0158, 0xa186, 0x0005, 0x0118,
- 0xa186, 0x0007, 0x1178, 0xa280, 0x0004, 0x2004, 0xa005, 0x0150,
- 0x0056, 0x7510, 0x7614, 0x080c, 0xa9eb, 0x005e, 0x00ce, 0x00de,
- 0x00ee, 0x0005, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00,
- 0x6003, 0x0001, 0x080c, 0x67a8, 0x0c88, 0x6007, 0x003b, 0x602b,
- 0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x080c, 0x67a8, 0x0c30,
- 0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0804, 0x9daa,
- 0x00e6, 0x0026, 0x080c, 0x502d, 0x0558, 0x080c, 0x501d, 0x080c,
- 0xabc5, 0x1520, 0x2071, 0xad00, 0x70d0, 0xc085, 0x70d2, 0x00f6,
- 0x2079, 0x0100, 0x729c, 0xa284, 0x00ff, 0x706e, 0x78e6, 0xa284,
- 0xff00, 0x7270, 0xa205, 0x7072, 0x78ea, 0x00fe, 0x70db, 0x0000,
- 0x2001, 0xad52, 0x2004, 0xd0a4, 0x0120, 0x2011, 0xafe0, 0x2013,
- 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x28fa, 0x0010, 0x080c, 0xabf1,
- 0x002e, 0x00ee, 0x080c, 0x8078, 0x0804, 0x9caa, 0x080c, 0x8078,
- 0x0005, 0x2600, 0x0002, 0x9e81, 0x9e81, 0x9e81, 0x9e81, 0x9e81,
- 0x9e83, 0x080c, 0x14f6, 0x080c, 0xab4e, 0x1d80, 0x0089, 0x1138,
- 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x67ee, 0x0005, 0x080c,
- 0x2ad9, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x67ee, 0x0005,
- 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637,
- 0xa686, 0x0006, 0x0170, 0xa686, 0x0004, 0x0158, 0x6e04, 0xa6b4,
- 0x00ff, 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, 0x0110, 0xa085,
- 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0449, 0x00de, 0x0005,
- 0x00d6, 0x0491, 0x11f0, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084,
- 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4, 0x0118, 0x2009,
- 0x0001, 0x0060, 0xd1ec, 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824,
- 0x080c, 0x2676, 0x1130, 0x2110, 0x2009, 0x0000, 0x080c, 0x2b1e,
- 0x0018, 0xa085, 0x0001, 0x0008, 0xa006, 0x00de, 0x0005, 0x2069,
- 0xb28d, 0x6800, 0xa082, 0x0010, 0x1228, 0x6013, 0x0000, 0xa085,
- 0x0001, 0x0008, 0xa006, 0x0005, 0x6013, 0x0000, 0x2069, 0xb28c,
- 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x1140, 0x6800, 0xa084,
- 0x00ff, 0xa08e, 0x0014, 0x0110, 0xa08e, 0x0010, 0x0005, 0x6004,
- 0xa0b2, 0x0080, 0x1a0c, 0x14f6, 0xa1b6, 0x0013, 0x1130, 0x2008,
- 0xa1b2, 0x0040, 0x1a04, 0x9ffb, 0x0092, 0xa1b6, 0x0027, 0x0120,
- 0xa1b6, 0x0014, 0x190c, 0x14f6, 0x2001, 0x0007, 0x080c, 0x4c5d,
- 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0x9f5f,
- 0x9f61, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f61, 0x9f6f, 0x9ff4, 0x9fbf,
- 0x9ff4, 0x9fd0, 0x9ff4, 0x9f6f, 0x9ff4, 0x9fec, 0x9ff4, 0x9fec,
- 0x9ff4, 0x9ff4, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f,
- 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f61, 0x9f5f, 0x9ff4,
- 0x9f5f, 0x9f5f, 0x9ff4, 0x9f5f, 0x9ff1, 0x9ff4, 0x9f5f, 0x9f5f,
- 0x9f5f, 0x9f5f, 0x9ff4, 0x9ff4, 0x9f5f, 0x9ff4, 0x9ff4, 0x9f5f,
- 0x9f69, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9ff0, 0x9ff4, 0x9f5f,
- 0x9f5f, 0x9ff4, 0x9ff4, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x080c,
- 0x14f6, 0x080c, 0x6b73, 0x6003, 0x0002, 0x080c, 0x6c50, 0x0804,
- 0x9ffa, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x0804, 0x9ff4, 0x00f6,
- 0x2079, 0xad51, 0x7804, 0x00fe, 0xd0ac, 0x1904, 0x9ff4, 0x2001,
- 0x0000, 0x080c, 0x4c1e, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086,
- 0x00ff, 0x1140, 0x00f6, 0x2079, 0xad00, 0x7894, 0x8000, 0x7896,
- 0x00fe, 0x00e0, 0x00c6, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x1140,
- 0x6010, 0xa005, 0x0128, 0x00ce, 0x080c, 0x3cce, 0x0804, 0x9ff4,
- 0x00ce, 0x2001, 0xad00, 0x2004, 0xa086, 0x0002, 0x1138, 0x00f6,
- 0x2079, 0xad00, 0x7894, 0x8000, 0x7896, 0x00fe, 0x2001, 0x0002,
- 0x080c, 0x4c30, 0x080c, 0x6b73, 0x601f, 0x0001, 0x6003, 0x0001,
- 0x6007, 0x0002, 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00c6, 0x6118,
- 0x2160, 0x2009, 0x0001, 0x080c, 0x6519, 0x00ce, 0x04d8, 0x6618,
- 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686,
- 0x0006, 0x0550, 0xa686, 0x0004, 0x0538, 0x2001, 0x0004, 0x0410,
- 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x1110, 0x080c, 0x3cce,
- 0x2001, 0x0006, 0x0489, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de,
- 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0x2001, 0x0006,
- 0x0048, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x00e9, 0x0020,
- 0x0018, 0x0010, 0x080c, 0x4c5d, 0x080c, 0x6b73, 0x080c, 0x8078,
- 0x080c, 0x6c50, 0x0005, 0x2600, 0x0002, 0xa003, 0xa003, 0xa003,
- 0xa003, 0xa003, 0xa005, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x080c,
- 0x8078, 0x080c, 0x6c50, 0x0005, 0x0016, 0x00d6, 0x6118, 0x2168,
- 0x6900, 0xd184, 0x0188, 0x6104, 0xa18e, 0x000a, 0x1128, 0x699c,
- 0xd1a4, 0x1110, 0x2001, 0x0007, 0x080c, 0x4c30, 0x2001, 0x0000,
- 0x080c, 0x4c1e, 0x080c, 0x2aff, 0x00de, 0x001e, 0x0005, 0x00d6,
- 0x6618, 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, 0xa0b2,
- 0x000c, 0x1a0c, 0x14f6, 0xa1b6, 0x0015, 0x1110, 0x003b, 0x0028,
- 0xa1b6, 0x0016, 0x190c, 0x14f6, 0x006b, 0x0005, 0x86b9, 0x86b9,
- 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0xa08f, 0xa056, 0x86b9, 0x86b9,
- 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9,
- 0xa08f, 0xa096, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x00f6, 0x2079,
- 0xad51, 0x7804, 0xd0ac, 0x11e0, 0x6018, 0xa07d, 0x01c8, 0x7800,
- 0xd0f4, 0x1118, 0x7810, 0xa005, 0x1198, 0x2001, 0x0000, 0x080c,
- 0x4c1e, 0x2001, 0x0002, 0x080c, 0x4c30, 0x601f, 0x0001, 0x6003,
- 0x0001, 0x6007, 0x0002, 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00a8,
- 0x2011, 0xb283, 0x2204, 0x8211, 0x220c, 0x080c, 0x2676, 0x1168,
- 0x00c6, 0x080c, 0x4cdc, 0x0120, 0x00ce, 0x080c, 0x8078, 0x0028,
- 0x080c, 0x493a, 0x00ce, 0x080c, 0x8078, 0x00fe, 0x0005, 0x6604,
- 0xa6b6, 0x001e, 0x1110, 0x080c, 0x8078, 0x0005, 0x080c, 0x8940,
- 0x1138, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x67ee, 0x0010,
- 0x080c, 0x8078, 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x14f6,
- 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0xa182,
- 0x0040, 0x0002, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c7, 0xa0c5,
- 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5,
- 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0x080c, 0x14f6, 0x00d6,
- 0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, 0x6218, 0xa280, 0x002b,
- 0x2004, 0xa005, 0x0120, 0x2021, 0x0000, 0x080c, 0xab96, 0x6106,
- 0x2071, 0xb280, 0x7444, 0xa4a4, 0xff00, 0x0904, 0xa129, 0xa486,
- 0x2000, 0x1130, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x663f,
- 0x080c, 0x15d9, 0x090c, 0x14f6, 0x6003, 0x0007, 0x2d00, 0x6837,
- 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e,
- 0x6008, 0x68b2, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a,
- 0x0016, 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036,
- 0x080c, 0x510c, 0x001e, 0xa486, 0x2000, 0x1130, 0x2019, 0x0017,
- 0x080c, 0xa8eb, 0x0804, 0xa186, 0xa486, 0x0400, 0x1130, 0x2019,
- 0x0002, 0x080c, 0xa89d, 0x0804, 0xa186, 0xa486, 0x0200, 0x1110,
- 0x080c, 0xa882, 0xa486, 0x1000, 0x1110, 0x080c, 0xa8d0, 0x0804,
- 0xa186, 0x2069, 0xb048, 0x6a00, 0xd284, 0x0904, 0xa1d5, 0xa284,
- 0x0300, 0x1904, 0xa1cf, 0x6804, 0xa005, 0x0904, 0xa1c0, 0x2d78,
- 0x6003, 0x0007, 0x080c, 0x15c0, 0x0904, 0xa18d, 0x7800, 0xd08c,
- 0x1118, 0x7804, 0x8001, 0x7806, 0x6013, 0x0000, 0x6803, 0x0000,
- 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, 0x68b2, 0x2c00, 0x684a,
- 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x6986, 0x6846, 0x7928,
- 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, 0x7934, 0x6996, 0x6853,
- 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, 0x0002, 0x1118, 0x684f,
- 0x0040, 0x0040, 0xa286, 0x0001, 0x1118, 0x684f, 0x0080, 0x0010,
- 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0xb290, 0xad90, 0x0015,
- 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x1f04, 0xa178, 0x200c,
- 0x6982, 0x8000, 0x200c, 0x697e, 0x080c, 0x510c, 0x002e, 0x004e,
- 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x6013, 0x0100, 0x6003,
- 0x0001, 0x6007, 0x0041, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0c70,
- 0x2069, 0xb292, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, 0x11a8,
- 0x2069, 0xb280, 0x686c, 0xa084, 0x00ff, 0x0016, 0x6110, 0xa18c,
- 0x0700, 0xa10d, 0x6112, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043,
- 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0888, 0x6013, 0x0200, 0x6003,
- 0x0001, 0x6007, 0x0041, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0830,
- 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007,
- 0x0041, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0804, 0xa186, 0x6013,
- 0x0500, 0x0c98, 0x6013, 0x0600, 0x0818, 0x6013, 0x0200, 0x0800,
- 0xa186, 0x0013, 0x1170, 0x6004, 0xa08a, 0x0040, 0x0a0c, 0x14f6,
- 0xa08a, 0x0053, 0x1a0c, 0x14f6, 0xa082, 0x0040, 0x2008, 0x0804,
- 0xa252, 0xa186, 0x0051, 0x0138, 0xa186, 0x0047, 0x11d8, 0x6004,
- 0xa086, 0x0041, 0x0518, 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0,
- 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6699,
- 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0xa086, 0x0002, 0x1170,
- 0x0804, 0xa295, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c,
- 0x14f6, 0x6004, 0xa082, 0x0040, 0x2008, 0x001a, 0x080c, 0x80be,
- 0x0005, 0xa22c, 0xa22e, 0xa22e, 0xa22c, 0xa22c, 0xa22c, 0xa22c,
- 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c,
- 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0x080c, 0x14f6, 0x080c, 0x6b73,
- 0x080c, 0x6c50, 0x0036, 0x00d6, 0x6010, 0xa06d, 0x01c0, 0xad84,
- 0xf000, 0x01a8, 0x6003, 0x0002, 0x6018, 0x2004, 0xd0bc, 0x1178,
- 0x2019, 0x0004, 0x080c, 0xa91f, 0x6013, 0x0000, 0x6014, 0xa005,
- 0x1120, 0x2001, 0xafa4, 0x2004, 0x6016, 0x6003, 0x0007, 0x00de,
- 0x003e, 0x0005, 0x0002, 0xa266, 0xa283, 0xa26f, 0xa28f, 0xa266,
- 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266,
- 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0x080c, 0x14f6,
- 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x080c,
- 0x6b73, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0138, 0x6003,
- 0x0007, 0x2009, 0x0043, 0x080c, 0x80a7, 0x0010, 0x6003, 0x0002,
- 0x080c, 0x6c50, 0x0005, 0x080c, 0x6b73, 0x080c, 0xab55, 0x1120,
- 0x080c, 0x6618, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, 0x080c,
- 0x6b73, 0x2009, 0x0041, 0x0804, 0xa3de, 0xa182, 0x0040, 0x0002,
- 0xa2ab, 0xa2ad, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ae,
- 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab,
- 0xa2ab, 0xa2b9, 0xa2ab, 0x080c, 0x14f6, 0x0005, 0x6003, 0x0004,
- 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1824,
- 0x0005, 0x00d6, 0x080c, 0x6618, 0x00de, 0x080c, 0xabb4, 0x080c,
- 0x8078, 0x0005, 0xa182, 0x0040, 0x0002, 0xa2d8, 0xa2d8, 0xa2d8,
- 0xa2d8, 0xa2d8, 0xa2d8, 0xa2d8, 0xa2da, 0xa2d8, 0xa2dd, 0xa316,
- 0xa2d8, 0xa2d8, 0xa2d8, 0xa2d8, 0xa316, 0xa2d8, 0xa2d8, 0xa2d8,
- 0x080c, 0x14f6, 0x080c, 0x80be, 0x0005, 0x2001, 0xad71, 0x2004,
- 0xd0e4, 0x0158, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x0228,
- 0x2001, 0x011f, 0x2004, 0x6036, 0x0010, 0x6037, 0x0000, 0x080c,
- 0x6c05, 0x080c, 0x6d0d, 0x6010, 0x00d6, 0x2068, 0x684c, 0xd0fc,
- 0x0150, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0168, 0x2009, 0x0041,
- 0x00de, 0x0804, 0xa3de, 0x6003, 0x0007, 0x6017, 0x0000, 0x080c,
- 0x6618, 0x00de, 0x0005, 0x080c, 0xab55, 0x0110, 0x00de, 0x0005,
- 0x080c, 0x6618, 0x080c, 0x8078, 0x00de, 0x0ca0, 0x0036, 0x080c,
- 0x6c05, 0x080c, 0x6d0d, 0x6010, 0x00d6, 0x2068, 0x6018, 0x2004,
- 0xd0bc, 0x0188, 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0140,
- 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a,
- 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xa91f, 0x6014,
- 0xa005, 0x1128, 0x2001, 0xafa4, 0x2004, 0x8003, 0x6016, 0x6013,
- 0x0000, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0xa186, 0x0013,
- 0x1150, 0x6004, 0xa086, 0x0042, 0x190c, 0x14f6, 0x080c, 0x6b73,
- 0x080c, 0x6c50, 0x0005, 0xa186, 0x0027, 0x0118, 0xa186, 0x0014,
- 0x1180, 0x6004, 0xa086, 0x0042, 0x190c, 0x14f6, 0x2001, 0x0007,
- 0x080c, 0x4c5d, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50,
- 0x0005, 0xa182, 0x0040, 0x0002, 0xa37f, 0xa37f, 0xa37f, 0xa37f,
- 0xa37f, 0xa37f, 0xa37f, 0xa381, 0xa38d, 0xa37f, 0xa37f, 0xa37f,
- 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0x080c,
- 0x14f6, 0x0036, 0x0046, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10,
- 0x080c, 0x1824, 0x004e, 0x003e, 0x0005, 0x6010, 0x00d6, 0x2068,
- 0x6810, 0x6a14, 0x0006, 0x0046, 0x0056, 0x6c7c, 0xa422, 0x6d80,
- 0x2200, 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, 0x652a,
- 0x005e, 0x004e, 0x000e, 0xa20d, 0x1178, 0x684c, 0xd0fc, 0x0120,
- 0x2009, 0x0041, 0x00de, 0x0490, 0x6003, 0x0007, 0x6017, 0x0000,
- 0x080c, 0x6618, 0x00de, 0x0005, 0x0006, 0x00f6, 0x2c78, 0x080c,
- 0x5029, 0x00fe, 0x000e, 0x0120, 0x6003, 0x0002, 0x00de, 0x0005,
- 0x2009, 0xad0d, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010,
- 0x6003, 0x0006, 0x0021, 0x080c, 0x661a, 0x00de, 0x0005, 0xd2fc,
- 0x0140, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009,
- 0x0010, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x0005, 0xa182, 0x0040,
- 0x0208, 0x0062, 0xa186, 0x0013, 0x0120, 0xa186, 0x0014, 0x190c,
- 0x14f6, 0x6020, 0xd0dc, 0x090c, 0x14f6, 0x0005, 0xa401, 0xa408,
- 0xa414, 0xa420, 0xa401, 0xa401, 0xa401, 0xa42f, 0xa401, 0xa403,
- 0xa403, 0xa401, 0xa401, 0xa401, 0xa401, 0xa403, 0xa401, 0xa403,
- 0xa401, 0x080c, 0x14f6, 0x6020, 0xd0dc, 0x090c, 0x14f6, 0x0005,
- 0x6003, 0x0001, 0x6106, 0x080c, 0x67a8, 0x0126, 0x2091, 0x8000,
- 0x080c, 0x6c50, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c,
- 0x67a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, 0x0005,
- 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1e6e, 0x0126, 0x2091,
- 0x8000, 0x080c, 0x680b, 0x080c, 0x6d0d, 0x012e, 0x0005, 0xa016,
- 0x080c, 0x1824, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x00d6,
- 0xa182, 0x0040, 0x0023, 0x00de, 0x003e, 0x012e, 0x0005, 0xa44f,
- 0xa451, 0xa463, 0xa47e, 0xa44f, 0xa44f, 0xa44f, 0xa493, 0xa44f,
- 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0x080c,
- 0x14f6, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x01f8, 0xa09c, 0x0003,
- 0xa39e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, 0x080c, 0x67a8,
- 0x080c, 0x6c50, 0x0498, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0168,
- 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106,
- 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0408, 0x6013, 0x0000, 0x6017,
- 0x0000, 0x2019, 0x0004, 0x080c, 0xa91f, 0x00c0, 0x6010, 0x2068,
- 0x684c, 0xd0fc, 0x0d90, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0d68,
- 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1e6e, 0x080c, 0x680b,
- 0x080c, 0x6d0d, 0x0018, 0xa016, 0x080c, 0x1824, 0x0005, 0x080c,
- 0x6b73, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xabfa,
- 0x0036, 0x2019, 0x0029, 0x080c, 0xa91f, 0x003e, 0x00de, 0x080c,
- 0x974e, 0x080c, 0x6c50, 0x0005, 0x080c, 0x6c05, 0x6110, 0x81ff,
- 0x0158, 0x00d6, 0x2168, 0x080c, 0xabfa, 0x0036, 0x2019, 0x0029,
- 0x080c, 0xa91f, 0x003e, 0x00de, 0x080c, 0x974e, 0x080c, 0x6d0d,
- 0x0005, 0xa182, 0x0085, 0x0002, 0xa4cd, 0xa4cb, 0xa4cb, 0xa4d9,
- 0xa4cb, 0xa4cb, 0xa4cb, 0x080c, 0x14f6, 0x6003, 0x000b, 0x6106,
- 0x080c, 0x67a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e,
- 0x0005, 0x0026, 0x00e6, 0x080c, 0xab4e, 0x0118, 0x080c, 0x8078,
- 0x00c8, 0x2071, 0xb280, 0x7224, 0x6212, 0x7220, 0x080c, 0xa7ce,
- 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0xa296,
- 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x67a8,
- 0x080c, 0x6c50, 0x00ee, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160,
- 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x14f6, 0xa08a, 0x008c, 0x1a0c,
- 0x14f6, 0xa082, 0x0085, 0x00a2, 0xa186, 0x0027, 0x0130, 0xa186,
- 0x0014, 0x0118, 0x080c, 0x80be, 0x0050, 0x2001, 0x0007, 0x080c,
- 0x4c5d, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005,
- 0xa527, 0xa529, 0xa529, 0xa527, 0xa527, 0xa527, 0xa527, 0x080c,
- 0x14f6, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005,
- 0xa182, 0x0085, 0x0a0c, 0x14f6, 0xa182, 0x008c, 0x1a0c, 0x14f6,
- 0xa182, 0x0085, 0x0002, 0xa542, 0xa542, 0xa542, 0xa544, 0xa542,
- 0xa542, 0xa542, 0x080c, 0x14f6, 0x0005, 0xa186, 0x0013, 0x0148,
- 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x80be,
- 0x0030, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005,
- 0x0036, 0x080c, 0xabb4, 0x603f, 0x0000, 0x2019, 0x000b, 0x0031,
- 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036,
- 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x2049, 0x0000, 0x080c,
- 0x7b9a, 0x009e, 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, 0x7c34,
- 0x007e, 0x1548, 0x6000, 0xa086, 0x0000, 0x0528, 0x601c, 0xa086,
- 0x0007, 0x0508, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, 0x080c,
- 0xabb4, 0x601f, 0x0007, 0x2001, 0xafa3, 0x2004, 0x6016, 0x080c,
- 0x190b, 0x6010, 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0xa91f,
- 0x00de, 0x6013, 0x0000, 0x080c, 0xabb4, 0x601f, 0x0007, 0x2001,
- 0xafa3, 0x2004, 0x6016, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6,
- 0x0036, 0x0156, 0x2079, 0xb280, 0x7938, 0x783c, 0x080c, 0x2676,
- 0x1904, 0xa5f1, 0x0016, 0x00c6, 0x080c, 0x4cdc, 0x15c0, 0x2011,
- 0xb290, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1578,
- 0x001e, 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x7cf4,
- 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x007e,
- 0x001e, 0x0076, 0x2039, 0x0000, 0x080c, 0xa712, 0x007e, 0x080c,
- 0x4ecf, 0x0026, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006,
- 0x0118, 0xa286, 0x0004, 0x1118, 0x62a0, 0x080c, 0x2b87, 0x002e,
- 0x001e, 0x080c, 0x493a, 0x6612, 0x6516, 0xa006, 0x0010, 0x00ce,
- 0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6,
- 0x00e6, 0x0016, 0x2009, 0xad20, 0x2104, 0xa086, 0x0074, 0x1904,
- 0xa64b, 0x2069, 0xb28e, 0x690c, 0xa182, 0x0100, 0x06c0, 0x6908,
- 0xa184, 0x8000, 0x05e8, 0x2001, 0xaf9d, 0x2004, 0xa005, 0x1160,
- 0x6018, 0x2070, 0x7010, 0xa084, 0x00ff, 0x0118, 0x7000, 0xd0f4,
- 0x0118, 0xa184, 0x0800, 0x0560, 0x6910, 0xa18a, 0x0001, 0x0610,
- 0x6914, 0x2069, 0xb2ae, 0x6904, 0x81ff, 0x1198, 0x690c, 0xa182,
- 0x0100, 0x02a8, 0x6908, 0x81ff, 0x1178, 0x6910, 0xa18a, 0x0001,
- 0x0288, 0x6918, 0xa18a, 0x0001, 0x0298, 0x00d0, 0x6013, 0x0100,
- 0x00a0, 0x6013, 0x0300, 0x0088, 0x6013, 0x0500, 0x0070, 0x6013,
- 0x0700, 0x0058, 0x6013, 0x0900, 0x0040, 0x6013, 0x0b00, 0x0028,
- 0x6013, 0x0f00, 0x0010, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0008,
- 0xa006, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6,
- 0x0026, 0x0036, 0x0156, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff,
- 0xa286, 0x0006, 0x0190, 0xa286, 0x0004, 0x0178, 0xa394, 0xff00,
- 0x8217, 0xa286, 0x0006, 0x0148, 0xa286, 0x0004, 0x0130, 0x00c6,
- 0x2d60, 0x080c, 0x4ceb, 0x00ce, 0x04c0, 0x2011, 0xb296, 0xad98,
- 0x000a, 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1580, 0x2011, 0xb29a,
- 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1538, 0x0046,
- 0x0016, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xad52,
- 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, 0xa96c, 0x6800,
- 0xc0e5, 0x6802, 0x2019, 0x0029, 0x080c, 0x68e7, 0x0076, 0x2039,
- 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, 0xa712, 0x007e, 0x2001,
- 0x0007, 0x080c, 0x4c5d, 0x001e, 0x004e, 0xa006, 0x015e, 0x003e,
- 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069, 0xb28e, 0x6800,
- 0xa086, 0x0800, 0x0118, 0x6013, 0x0000, 0x0008, 0xa006, 0x00de,
- 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079,
- 0xb28c, 0x7930, 0x7834, 0x080c, 0x2676, 0x11a0, 0x080c, 0x4cdc,
- 0x1188, 0x2011, 0xb290, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c,
- 0x8a7c, 0x1140, 0x2011, 0xb294, 0xac98, 0x0006, 0x20a9, 0x0004,
- 0x080c, 0x8a7c, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce,
- 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011,
- 0xb283, 0x2204, 0x8211, 0x220c, 0x080c, 0x2676, 0x11a0, 0x080c,
- 0x4cdc, 0x1188, 0x2011, 0xb296, 0xac98, 0x000a, 0x20a9, 0x0004,
- 0x080c, 0x8a7c, 0x1140, 0x2011, 0xb29a, 0xac98, 0x0006, 0x20a9,
- 0x0004, 0x080c, 0x8a7c, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e,
- 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056,
- 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0xafd0,
- 0x252c, 0x2021, 0xafd6, 0x2424, 0x2061, 0xb400, 0x2071, 0xad00,
- 0x7644, 0x7064, 0x81ff, 0x0128, 0x8001, 0xa602, 0x1a04, 0xa78e,
- 0x0018, 0xa606, 0x0904, 0xa78e, 0x2100, 0xac06, 0x0904, 0xa785,
- 0x080c, 0xa990, 0x0904, 0xa785, 0x671c, 0xa786, 0x0001, 0x0904,
- 0xa7a5, 0xa786, 0x0004, 0x0904, 0xa7a5, 0xa786, 0x0007, 0x05e8,
- 0x2500, 0xac06, 0x05d0, 0x2400, 0xac06, 0x05b8, 0x080c, 0xa9a0,
- 0x15a0, 0x88ff, 0x0118, 0x6050, 0xa906, 0x1578, 0x00d6, 0x6000,
- 0xa086, 0x0004, 0x1120, 0x0016, 0x080c, 0x190b, 0x001e, 0xa786,
- 0x0008, 0x1148, 0x080c, 0x9789, 0x1130, 0x080c, 0x85f3, 0x00de,
- 0x080c, 0x974e, 0x00d0, 0x6010, 0x2068, 0x080c, 0x9596, 0x0190,
- 0xa786, 0x0003, 0x1528, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
- 0x080c, 0xabfa, 0x0016, 0x080c, 0x97fd, 0x080c, 0x510c, 0x001e,
- 0x080c, 0x9742, 0x00de, 0x080c, 0x974e, 0xace0, 0x0018, 0x2001,
- 0xad16, 0x2004, 0xac02, 0x1210, 0x0804, 0xa726, 0x012e, 0x002e,
- 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005,
- 0xa786, 0x0006, 0x19c0, 0xa386, 0x0005, 0x0128, 0x080c, 0xabfa,
- 0x080c, 0xa91f, 0x08f8, 0x00de, 0x0c00, 0x080c, 0xa9a0, 0x19e8,
- 0x81ff, 0x09d8, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x0130,
- 0xa180, 0x0001, 0x2004, 0xa086, 0x002d, 0x1978, 0x6000, 0xa086,
- 0x0002, 0x1958, 0x080c, 0x9778, 0x0130, 0x080c, 0x9789, 0x1928,
- 0x080c, 0x85f3, 0x0038, 0x080c, 0x2aff, 0x080c, 0x9789, 0x1110,
- 0x080c, 0x85f3, 0x080c, 0x974e, 0x0804, 0xa785, 0x00c6, 0x00e6,
- 0x0016, 0x2c08, 0x2170, 0x080c, 0xa940, 0x001e, 0x0120, 0x601c,
- 0xa084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xa7e6, 0xa7e6,
- 0xa7e6, 0xa7e6, 0xa7e6, 0xa7e6, 0xa7e8, 0xa7e6, 0xa006, 0x0005,
- 0x0046, 0x0016, 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff,
- 0x8427, 0x2c00, 0x2009, 0x0020, 0x080c, 0xa96c, 0x001e, 0x004e,
- 0x0036, 0x2019, 0x0002, 0x080c, 0xa566, 0x003e, 0xa085, 0x0001,
- 0x0005, 0x2001, 0x0001, 0x080c, 0x4c1e, 0x0156, 0x0016, 0x0026,
- 0x0036, 0x20a9, 0x0004, 0x2019, 0xad05, 0x2011, 0xb296, 0x080c,
- 0x8a7c, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6,
- 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091,
- 0x8000, 0x2740, 0x2061, 0xb400, 0x2079, 0x0001, 0x8fff, 0x0904,
- 0xa875, 0x2071, 0xad00, 0x7644, 0x7064, 0x8001, 0xa602, 0x1a04,
- 0xa875, 0x88ff, 0x0128, 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000,
- 0x080c, 0xa990, 0x0588, 0x2400, 0xac06, 0x0570, 0x671c, 0xa786,
- 0x0006, 0x1550, 0xa786, 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018,
- 0xa206, 0x1510, 0x85ff, 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6,
- 0x6000, 0xa086, 0x0004, 0x1150, 0x080c, 0xabb4, 0x601f, 0x0007,
- 0x2001, 0xafa3, 0x2004, 0x6016, 0x080c, 0x190b, 0x6010, 0x2068,
- 0x080c, 0x9596, 0x0120, 0x0046, 0x080c, 0xa91f, 0x004e, 0x00de,
- 0x080c, 0x974e, 0x88ff, 0x1198, 0xace0, 0x0018, 0x2001, 0xad16,
- 0x2004, 0xac02, 0x1210, 0x0804, 0xa826, 0xa006, 0x012e, 0x002e,
- 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5,
- 0x0001, 0x0ca0, 0x0076, 0x0056, 0x0086, 0x2041, 0x0000, 0x2029,
- 0x0001, 0x2c20, 0x2019, 0x0002, 0x6218, 0x0096, 0x2049, 0x0000,
- 0x080c, 0x7b9a, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x7c34,
- 0x080c, 0xa817, 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056,
- 0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009,
- 0x0000, 0x0016, 0x0036, 0x080c, 0x4cdc, 0x11b0, 0x2c10, 0x0056,
- 0x0086, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001, 0x0096, 0x2049,
- 0x0000, 0x080c, 0x7b9a, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c,
- 0x7c34, 0x080c, 0xa817, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04,
- 0xa8a9, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005,
- 0x0076, 0x0056, 0x6218, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001,
- 0x2019, 0x0048, 0x0096, 0x2049, 0x0000, 0x080c, 0x7b9a, 0x009e,
- 0x008e, 0x2039, 0x0000, 0x080c, 0x7c34, 0x2c20, 0x080c, 0xa817,
- 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6,
- 0x0156, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036,
- 0x080c, 0x4cdc, 0x11c0, 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828,
- 0x0046, 0x2021, 0x0001, 0x080c, 0xab96, 0x004e, 0x0096, 0x2049,
- 0x0000, 0x080c, 0x7b9a, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c,
- 0x7c34, 0x080c, 0xa817, 0x003e, 0x001e, 0x8108, 0x1f04, 0xa8f6,
- 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0016,
- 0x00f6, 0x3800, 0xd08c, 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82,
- 0xad00, 0x0230, 0xad82, 0xe400, 0x0280, 0xad82, 0xffff, 0x1268,
- 0x6800, 0xa07d, 0x0138, 0x6803, 0x0000, 0x6b52, 0x080c, 0x510c,
- 0x2f68, 0x0cb0, 0x6b52, 0x080c, 0x510c, 0x00fe, 0x001e, 0x0005,
- 0x00e6, 0x0046, 0x0036, 0x2061, 0xb400, 0x2071, 0xad00, 0x7444,
- 0x7064, 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000,
- 0xa086, 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0,
- 0x0006, 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xad16,
- 0x2004, 0xac02, 0x1220, 0x0c08, 0xa085, 0x0001, 0x0008, 0xa006,
- 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15d9,
- 0x000e, 0x090c, 0x14f6, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010,
- 0x080c, 0x9586, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014,
- 0x2004, 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0xa006,
- 0x68b2, 0x6802, 0x683a, 0x685a, 0x080c, 0x510c, 0x00de, 0x0005,
- 0x6700, 0xa786, 0x0000, 0x0158, 0xa786, 0x0001, 0x0140, 0xa786,
- 0x000a, 0x0128, 0xa786, 0x0009, 0x0110, 0xa085, 0x0001, 0x0005,
- 0x00e6, 0x6018, 0x2070, 0x70a0, 0xa206, 0x00ee, 0x0005, 0x0016,
- 0x6004, 0xa08e, 0x001e, 0x11a0, 0x8007, 0x6130, 0xa18c, 0x00ff,
- 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0005,
- 0x2001, 0xafa4, 0x2004, 0x6016, 0x080c, 0x67a8, 0x080c, 0x6c50,
- 0x001e, 0x0005, 0xe000, 0xe000, 0x0005, 0x6020, 0xd0e4, 0x0158,
- 0xd0cc, 0x0118, 0x080c, 0x9866, 0x0030, 0x080c, 0xabb4, 0x080c,
- 0x6618, 0x080c, 0x8078, 0x0005, 0xa280, 0x0007, 0x2004, 0xa084,
- 0x000f, 0x0002, 0xa9e3, 0xa9e3, 0xa9e3, 0xa9e8, 0xa9e3, 0xa9e5,
- 0xa9e5, 0xa9e3, 0xa9e5, 0xa006, 0x0005, 0x00c6, 0x2260, 0x00ce,
- 0xa085, 0x0001, 0x0005, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f,
- 0x0002, 0xa9fa, 0xa9fa, 0xa9fa, 0xa9fa, 0xa9fa, 0xa9fa, 0xaa05,
- 0xa9fa, 0xa9fa, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00,
- 0x6003, 0x0001, 0x080c, 0x67a8, 0x0005, 0x00c6, 0x2260, 0x080c,
- 0xabb4, 0x603f, 0x0000, 0x6020, 0xc0f4, 0xc0cc, 0x6022, 0x6037,
- 0x0000, 0x00ce, 0x00d6, 0x2268, 0xa186, 0x0007, 0x1904, 0xaa60,
- 0x6810, 0xa005, 0x0138, 0xa080, 0x0013, 0x2004, 0xd0fc, 0x1110,
- 0x00de, 0x08c0, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, 0x67a8,
- 0x080c, 0x6c50, 0x00c6, 0x2d60, 0x6100, 0xa186, 0x0002, 0x1904,
- 0xaae7, 0x6010, 0xa005, 0x1138, 0x6000, 0xa086, 0x0007, 0x190c,
- 0x14f6, 0x0804, 0xaae7, 0xa08c, 0xf000, 0x1130, 0x0028, 0x2068,
- 0x6800, 0xa005, 0x1de0, 0x2d00, 0xa080, 0x0013, 0x2004, 0xa084,
- 0x0003, 0xa086, 0x0002, 0x1180, 0x6010, 0x2068, 0x684c, 0xc0dc,
- 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852, 0x2009, 0x0043,
- 0x080c, 0xa3de, 0x0804, 0xaae7, 0x2009, 0x0041, 0x0804, 0xaae1,
- 0xa186, 0x0005, 0x15f0, 0x6810, 0xa080, 0x0013, 0x2004, 0xd0bc,
- 0x1118, 0x00de, 0x0804, 0xa9fa, 0xd0b4, 0x0128, 0xd0fc, 0x090c,
- 0x14f6, 0x0804, 0xaa18, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c,
- 0x67a8, 0x080c, 0x6c50, 0x00c6, 0x2d60, 0x6100, 0xa186, 0x0002,
- 0x0120, 0xa186, 0x0004, 0x1904, 0xaae7, 0x2071, 0xaffd, 0x7000,
- 0xa086, 0x0003, 0x1128, 0x7004, 0xac06, 0x1110, 0x7003, 0x0000,
- 0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000,
- 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x2009, 0x0042, 0x0804,
- 0xaae1, 0x0036, 0x00d6, 0x00d6, 0x080c, 0x15d9, 0x003e, 0x090c,
- 0x14f6, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x685b,
- 0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, 0x6862, 0x6034, 0x6872,
- 0x2360, 0x6020, 0xc0dd, 0x6022, 0x6018, 0xa080, 0x0028, 0x2004,
- 0xa084, 0x00ff, 0x8007, 0x6350, 0x6b4a, 0x6846, 0x684f, 0x0000,
- 0x6d6a, 0x6e66, 0x686f, 0x0001, 0x080c, 0x510c, 0x2019, 0x0045,
- 0x6008, 0x2068, 0x080c, 0xa566, 0x2d00, 0x600a, 0x601f, 0x0006,
- 0x6003, 0x0007, 0x6017, 0x0000, 0x603f, 0x0000, 0x00de, 0x003e,
- 0x0038, 0x603f, 0x0000, 0x6003, 0x0007, 0x080c, 0xa3de, 0x00ce,
- 0x00de, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085,
- 0x2008, 0x00c2, 0xa186, 0x0027, 0x1178, 0x080c, 0x6b73, 0x0036,
- 0x00d6, 0x6010, 0x2068, 0x2019, 0x0004, 0x080c, 0xa91f, 0x00de,
- 0x003e, 0x080c, 0x6c50, 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c,
- 0x80be, 0x0005, 0xab13, 0xab11, 0xab11, 0xab11, 0xab11, 0xab11,
- 0xab13, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x6003, 0x000c, 0x080c,
- 0x6c50, 0x0005, 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208,
- 0x001a, 0x080c, 0x80be, 0x0005, 0xab2b, 0xab2b, 0xab2b, 0xab2b,
- 0xab2d, 0xab4b, 0xab2b, 0x080c, 0x14f6, 0x00d6, 0x2c68, 0x080c,
- 0x8022, 0x01a0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xb28e,
- 0x210c, 0x6136, 0x2009, 0xb28f, 0x210c, 0x613a, 0x600b, 0xffff,
- 0x6918, 0x611a, 0x601f, 0x0004, 0x080c, 0x67a8, 0x2d60, 0x080c,
- 0x8078, 0x00de, 0x0005, 0x080c, 0x8078, 0x0005, 0x00e6, 0x6018,
- 0x2070, 0x7000, 0xd0ec, 0x00ee, 0x0005, 0x6010, 0xa080, 0x0013,
- 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xad71, 0x2004, 0xd0ec, 0x05a8,
- 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, 0x0180, 0x00f6,
- 0x2c78, 0x080c, 0x5025, 0x00fe, 0x0150, 0x2001, 0xafa5, 0x2004,
- 0x603e, 0x2009, 0xad71, 0x210c, 0xd1f4, 0x11e8, 0x0080, 0x2009,
- 0xad71, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, 0x6022, 0xa006,
- 0x00a0, 0x2001, 0xafa5, 0x200c, 0x8103, 0xa100, 0x603e, 0x6018,
- 0xa088, 0x002b, 0x2104, 0xa005, 0x0118, 0xa088, 0x0003, 0x0cd0,
- 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, 0x0016, 0x00c6,
- 0x00e6, 0x6150, 0xa2f0, 0x002b, 0x2e04, 0x2060, 0x8cff, 0x0180,
- 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, 0x2072, 0x080c,
- 0x6618, 0x080c, 0x8078, 0x0010, 0xacf0, 0x0003, 0x2e64, 0x0c70,
- 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, 0xa0e8, 0x002b,
- 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, 0xa0e8, 0x0003,
- 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, 0x0156,
- 0x2011, 0xad27, 0x2204, 0xa084, 0x00ff, 0x2019, 0xb28e, 0x2334,
- 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, 0xff00, 0xa636,
- 0x11a0, 0x2011, 0xb290, 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004,
- 0x080c, 0x8a7c, 0x1150, 0x2011, 0xb294, 0x6018, 0xa098, 0x0006,
- 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1100, 0x015e, 0x003e, 0x002e,
- 0x0005, 0x00e6, 0x2071, 0xad00, 0x080c, 0x48f5, 0x080c, 0x28fa,
- 0x00ee, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0108,
- 0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, 0x0005, 0x00e6,
- 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126,
- 0x2091, 0x8000, 0x2029, 0xafd0, 0x252c, 0x2021, 0xafd6, 0x2424,
- 0x2061, 0xb400, 0x2071, 0xad00, 0x7644, 0x7064, 0xa606, 0x0578,
- 0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, 0x1500, 0x2500,
- 0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, 0xa990, 0x01b8,
- 0x080c, 0xa9a0, 0x11a0, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016,
- 0x080c, 0x190b, 0x001e, 0x080c, 0x9778, 0x1110, 0x080c, 0x2aff,
- 0x080c, 0x9789, 0x1110, 0x080c, 0x85f3, 0x080c, 0x974e, 0xace0,
- 0x0018, 0x2001, 0xad16, 0x2004, 0xac02, 0x1208, 0x0858, 0x012e,
- 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00ee,
- 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xad40,
- 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030,
- 0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071, 0xad4a, 0x0451, 0x00ee,
- 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000,
- 0x2071, 0xad40, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4,
- 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071, 0xad4a,
- 0x0081, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6,
- 0x2091, 0x8000, 0x2071, 0xad42, 0x0021, 0x00ee, 0x000e, 0x012e,
- 0x0005, 0x2e04, 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000,
- 0x2072, 0x0005, 0x00e6, 0x2071, 0xad40, 0x0c99, 0x00ee, 0x0005,
- 0x00e6, 0x2071, 0xad44, 0x0c69, 0x00ee, 0x0005, 0x0001, 0x0002,
- 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200,
- 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x8529
-};
-
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index 1fd5fc6d0fe..c7e78dcf09d 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -24,6 +24,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/jiffies.h>
#include <asm/byteorder.h>
@@ -1017,7 +1018,7 @@ static inline void cmd_frob(struct Command_Entry *cmd, struct scsi_cmnd *Cmnd,
if (Cmnd->device->tagged_supported) {
if (qpti->cmd_count[Cmnd->device->id] == 0)
qpti->tag_ages[Cmnd->device->id] = jiffies;
- if ((jiffies - qpti->tag_ages[Cmnd->device->id]) > (5*HZ)) {
+ if (time_after(jiffies, qpti->tag_ages[Cmnd->device->id] + (5*HZ))) {
cmd->control_flags = CFLAG_ORDERED_TAG;
qpti->tag_ages[Cmnd->device->id] = jiffies;
} else
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index 275ed9bd898..f16f92a6ec0 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -37,7 +37,7 @@
#include <asm/io.h>
#define DRV_NAME "sata_mv"
-#define DRV_VERSION "0.6"
+#define DRV_VERSION "0.7"
enum {
/* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -50,6 +50,12 @@ enum {
MV_PCI_REG_BASE = 0,
MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */
+ MV_IRQ_COAL_CAUSE = (MV_IRQ_COAL_REG_BASE + 0x08),
+ MV_IRQ_COAL_CAUSE_LO = (MV_IRQ_COAL_REG_BASE + 0x88),
+ MV_IRQ_COAL_CAUSE_HI = (MV_IRQ_COAL_REG_BASE + 0x8c),
+ MV_IRQ_COAL_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xcc),
+ MV_IRQ_COAL_TIME_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xd0),
+
MV_SATAHC0_REG_BASE = 0x20000,
MV_FLASH_CTL = 0x1046c,
MV_GPIO_PORT_CTL = 0x104f0,
@@ -302,9 +308,6 @@ struct mv_port_priv {
dma_addr_t crpb_dma;
struct mv_sg *sg_tbl;
dma_addr_t sg_tbl_dma;
-
- unsigned req_producer; /* cp of req_in_ptr */
- unsigned rsp_consumer; /* cp of rsp_out_ptr */
u32 pp_flags;
};
@@ -378,7 +381,6 @@ static struct scsi_host_template mv_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = MV_USE_Q_DEPTH,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = MV_MAX_SG_CT / 2,
@@ -748,7 +750,7 @@ static void mv_dump_all_regs(void __iomem *mmio_base, int port,
mv_dump_mem(mmio_base+0xf00, 0x4);
mv_dump_mem(mmio_base+0x1d00, 0x6c);
for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
- hc_base = mv_hc_base(mmio_base, port >> MV_PORT_HC_SHIFT);
+ hc_base = mv_hc_base(mmio_base, hc);
DPRINTK("HC regs (HC %i):\n", hc);
mv_dump_mem(hc_base, 0x1c);
}
@@ -938,8 +940,6 @@ static int mv_port_start(struct ata_port *ap)
writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
- pp->req_producer = pp->rsp_consumer = 0;
-
/* Don't turn on EDMA here...do it before DMA commands only. Else
* we'll be unable to send non-data, PIO, etc due to restricted access
* to shadow regs.
@@ -1010,7 +1010,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff);
pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
- pp->sg_tbl[i].flags_size = cpu_to_le32(len);
+ pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff);
sg_len -= len;
addr += len;
@@ -1023,16 +1023,16 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
}
}
-static inline unsigned mv_inc_q_index(unsigned *index)
+static inline unsigned mv_inc_q_index(unsigned index)
{
- *index = (*index + 1) & MV_MAX_Q_DEPTH_MASK;
- return *index;
+ return (index + 1) & MV_MAX_Q_DEPTH_MASK;
}
static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last)
{
- *cmdw = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
+ u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
(last ? CRQB_CMD_LAST : 0);
+ *cmdw = cpu_to_le16(tmp);
}
/**
@@ -1054,15 +1054,11 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
u16 *cw;
struct ata_taskfile *tf;
u16 flags = 0;
+ unsigned in_index;
if (ATA_PROT_DMA != qc->tf.protocol)
return;
- /* the req producer index should be the same as we remember it */
- WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
- EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
- pp->req_producer);
-
/* Fill in command request block
*/
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
@@ -1070,13 +1066,17 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
flags |= qc->tag << CRQB_TAG_SHIFT;
- pp->crqb[pp->req_producer].sg_addr =
+ /* get current queue index from hardware */
+ in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
+ >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+ pp->crqb[in_index].sg_addr =
cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
- pp->crqb[pp->req_producer].sg_addr_hi =
+ pp->crqb[in_index].sg_addr_hi =
cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
- pp->crqb[pp->req_producer].ctrl_flags = cpu_to_le16(flags);
+ pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
- cw = &pp->crqb[pp->req_producer].ata_cmd[0];
+ cw = &pp->crqb[in_index].ata_cmd[0];
tf = &qc->tf;
/* Sadly, the CRQB cannot accomodate all registers--there are
@@ -1145,16 +1145,12 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
struct mv_port_priv *pp = ap->private_data;
struct mv_crqb_iie *crqb;
struct ata_taskfile *tf;
+ unsigned in_index;
u32 flags = 0;
if (ATA_PROT_DMA != qc->tf.protocol)
return;
- /* the req producer index should be the same as we remember it */
- WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
- EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
- pp->req_producer);
-
/* Fill in Gen IIE command request block
*/
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
@@ -1163,7 +1159,11 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
flags |= qc->tag << CRQB_TAG_SHIFT;
- crqb = (struct mv_crqb_iie *) &pp->crqb[pp->req_producer];
+ /* get current queue index from hardware */
+ in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
+ >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+ crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
crqb->flags = cpu_to_le32(flags);
@@ -1211,6 +1211,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
{
void __iomem *port_mmio = mv_ap_base(qc->ap);
struct mv_port_priv *pp = qc->ap->private_data;
+ unsigned in_index;
u32 in_ptr;
if (ATA_PROT_DMA != qc->tf.protocol) {
@@ -1222,23 +1223,20 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
return ata_qc_issue_prot(qc);
}
- in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+ in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+ in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
- /* the req producer index should be the same as we remember it */
- WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
- pp->req_producer);
/* until we do queuing, the queue should be empty at this point */
- WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
- ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >>
- EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
+ WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
+ >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
- mv_inc_q_index(&pp->req_producer); /* now incr producer index */
+ in_index = mv_inc_q_index(in_index); /* now incr producer index */
mv_start_dma(port_mmio, pp);
/* and write the request in pointer to kick the EDMA to life */
in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
- in_ptr |= pp->req_producer << EDMA_REQ_Q_PTR_SHIFT;
+ in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT;
writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
return 0;
@@ -1261,28 +1259,26 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
{
void __iomem *port_mmio = mv_ap_base(ap);
struct mv_port_priv *pp = ap->private_data;
+ unsigned out_index;
u32 out_ptr;
u8 ata_status;
- out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+ out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+ out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
- /* the response consumer index should be the same as we remember it */
- WARN_ON(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
- pp->rsp_consumer);
-
- ata_status = pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT;
+ ata_status = le16_to_cpu(pp->crpb[out_index].flags)
+ >> CRPB_FLAG_STATUS_SHIFT;
/* increment our consumer index... */
- pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer);
+ out_index = mv_inc_q_index(out_index);
/* and, until we do NCQ, there should only be 1 CRPB waiting */
- WARN_ON(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >>
- EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
- pp->rsp_consumer);
+ WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
+ >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
/* write out our inc'd consumer index so EDMA knows we're caught up */
out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
- out_ptr |= pp->rsp_consumer << EDMA_RSP_Q_PTR_SHIFT;
+ out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT;
writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
/* Return ATA status register for completed CRPB */
@@ -1292,6 +1288,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
/**
* mv_err_intr - Handle error interrupts on the port
* @ap: ATA channel to manipulate
+ * @reset_allowed: bool: 0 == don't trigger from reset here
*
* In most cases, just clear the interrupt and move on. However,
* some cases require an eDMA reset, which is done right before
@@ -1302,7 +1299,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
* LOCKING:
* Inherited from caller.
*/
-static void mv_err_intr(struct ata_port *ap)
+static void mv_err_intr(struct ata_port *ap, int reset_allowed)
{
void __iomem *port_mmio = mv_ap_base(ap);
u32 edma_err_cause, serr = 0;
@@ -1324,9 +1321,8 @@ static void mv_err_intr(struct ata_port *ap)
writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
/* check for fatal here and recover if needed */
- if (EDMA_ERR_FATAL & edma_err_cause) {
+ if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause))
mv_stop_and_reset(ap);
- }
}
/**
@@ -1350,7 +1346,6 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
{
void __iomem *mmio = host_set->mmio_base;
void __iomem *hc_mmio = mv_hc_base(mmio, hc);
- struct ata_port *ap;
struct ata_queued_cmd *qc;
u32 hc_irq_cause;
int shift, port, port0, hard_port, handled;
@@ -1373,25 +1368,37 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
u8 ata_status = 0;
- ap = host_set->ports[port];
- hard_port = port & MV_PORT_MASK; /* range 0-3 */
+ struct ata_port *ap = host_set->ports[port];
+ struct mv_port_priv *pp = ap->private_data;
+
+ hard_port = mv_hardport_from_port(port); /* range 0..3 */
handled = 0; /* ensure ata_status is set if handled++ */
- if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
- /* new CRPB on the queue; just one at a time until NCQ
- */
- ata_status = mv_get_crpb_status(ap);
- handled++;
- } else if ((DEV_IRQ << hard_port) & hc_irq_cause) {
- /* received ATA IRQ; read the status reg to clear INTRQ
- */
- ata_status = readb((void __iomem *)
+ /* Note that DEV_IRQ might happen spuriously during EDMA,
+ * and should be ignored in such cases.
+ * The cause of this is still under investigation.
+ */
+ if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+ /* EDMA: check for response queue interrupt */
+ if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
+ ata_status = mv_get_crpb_status(ap);
+ handled = 1;
+ }
+ } else {
+ /* PIO: check for device (drive) interrupt */
+ if ((DEV_IRQ << hard_port) & hc_irq_cause) {
+ ata_status = readb((void __iomem *)
ap->ioaddr.status_addr);
- handled++;
+ handled = 1;
+ /* ignore spurious intr if drive still BUSY */
+ if (ata_status & ATA_BUSY) {
+ ata_status = 0;
+ handled = 0;
+ }
+ }
}
- if (ap &&
- (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))
+ if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))
continue;
err_mask = ac_err_mask(ata_status);
@@ -1401,14 +1408,14 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
shift++; /* skip bit 8 in the HC Main IRQ reg */
}
if ((PORT0_ERR << shift) & relevant) {
- mv_err_intr(ap);
+ mv_err_intr(ap, 1);
err_mask |= AC_ERR_OTHER;
- handled++;
+ handled = 1;
}
- if (handled && ap) {
+ if (handled) {
qc = ata_qc_from_tag(ap, ap->active_tag);
- if (NULL != qc) {
+ if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
VPRINTK("port %u IRQ found for qc, "
"ata_status 0x%x\n", port,ata_status);
/* mark qc status appropriately */
@@ -1443,6 +1450,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance,
struct ata_host_set *host_set = dev_instance;
unsigned int hc, handled = 0, n_hcs;
void __iomem *mmio = host_set->mmio_base;
+ struct mv_host_priv *hpriv;
u32 irq_stat;
irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
@@ -1464,6 +1472,17 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance,
handled++;
}
}
+
+ hpriv = host_set->private_data;
+ if (IS_60XX(hpriv)) {
+ /* deal with the interrupt coalescing bits */
+ if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) {
+ writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO);
+ writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI);
+ writelfl(0, mmio + MV_IRQ_COAL_CAUSE);
+ }
+ }
+
if (PCI_ERR & irq_stat) {
printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
readl(mmio + PCI_IRQ_CAUSE_OFS));
@@ -1862,7 +1881,8 @@ static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
if (IS_60XX(hpriv)) {
u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
- ifctl |= (1 << 12) | (1 << 7);
+ ifctl |= (1 << 7); /* enable gen2i speed */
+ ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
}
@@ -2015,6 +2035,7 @@ static void mv_phy_reset(struct ata_port *ap)
static void mv_eng_timeout(struct ata_port *ap)
{
struct ata_queued_cmd *qc;
+ unsigned long flags;
printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
DPRINTK("All regs @ start of eng_timeout\n");
@@ -2026,11 +2047,16 @@ static void mv_eng_timeout(struct ata_port *ap)
ap->host_set->mmio_base, ap, qc, qc->scsicmd,
&qc->scsicmd->cmnd);
- mv_err_intr(ap);
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+ mv_err_intr(ap, 0);
mv_stop_and_reset(ap);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
- qc->err_mask |= AC_ERR_TIMEOUT;
- ata_eh_qc_complete(qc);
+ WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
+ if (qc->flags & ATA_QCFLAG_ACTIVE) {
+ qc->err_mask |= AC_ERR_TIMEOUT;
+ ata_eh_qc_complete(qc);
+ }
}
/**
@@ -2224,7 +2250,8 @@ static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
void __iomem *port_mmio = mv_port_base(mmio, port);
u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
- ifctl |= (1 << 12);
+ ifctl |= (1 << 7); /* enable gen2i speed */
+ ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
}
@@ -2325,6 +2352,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc) {
return rc;
}
+ pci_set_master(pdev);
rc = pci_request_regions(pdev, DRV_NAME);
if (rc) {
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index f77bf183dfa..9f553081b5e 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -201,7 +201,6 @@ static struct scsi_host_template nv_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index cc928c68a47..7eb67a6bdc6 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -111,7 +111,6 @@ static struct scsi_host_template pdc_ata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index 9ffe1ef0d20..886f3447dd4 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -132,7 +132,6 @@ static struct scsi_host_template qs_ata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = QS_MAX_PRD,
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 18c296c5689..106627299d5 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -146,7 +146,6 @@ static struct scsi_host_template sil_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 068c98a4111..cb9082fd7e2 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -281,7 +281,6 @@ static struct scsi_host_template sil24_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
@@ -455,7 +454,7 @@ static int sil24_softreset(struct ata_port *ap, int verbose,
*/
msleep(10);
- prb->ctrl = PRB_CTRL_SRST;
+ prb->ctrl = cpu_to_le16(PRB_CTRL_SRST);
prb->fis[1] = 0; /* no PM yet */
writel((u32)paddr, port + PORT_CMD_ACTIVATE);
@@ -552,9 +551,9 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
if (qc->tf.flags & ATA_TFLAG_WRITE)
- prb->ctrl = PRB_CTRL_PACKET_WRITE;
+ prb->ctrl = cpu_to_le16(PRB_CTRL_PACKET_WRITE);
else
- prb->ctrl = PRB_CTRL_PACKET_READ;
+ prb->ctrl = cpu_to_le16(PRB_CTRL_PACKET_READ);
} else
prb->ctrl = 0;
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index acc8439dea2..728530df2e0 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -87,7 +87,6 @@ static struct scsi_host_template sis_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = ATA_MAX_PRD,
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 724f0ed6a52..53b0d5c0a61 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -290,7 +290,6 @@ static struct scsi_host_template k2_sata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index ae70f60c7c0..4139ad4b1df 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -182,7 +182,6 @@ static struct scsi_host_template pdc_sata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index 7ac5a5f5a90..38b52bd3fa3 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -81,7 +81,6 @@ static struct scsi_host_template uli_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index 791bf652ba6..9e7ae4e0db3 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -94,7 +94,6 @@ static struct scsi_host_template svia_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index 836bbbb26ff..8a29ce340b4 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -263,7 +263,6 @@ static struct scsi_host_template vsc_sata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 6913b062316..73994e2ac2c 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -565,7 +565,8 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
/*
* If SCSI-2 or lower, store the LUN value in cmnd.
*/
- if (cmd->device->scsi_level <= SCSI_2) {
+ if (cmd->device->scsi_level <= SCSI_2 &&
+ cmd->device->scsi_level != SCSI_UNKNOWN) {
cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) |
(cmd->device->lun << 5 & 0xe0);
}
@@ -1243,7 +1244,7 @@ static int __init init_scsi(void)
if (error)
goto cleanup_sysctl;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
printk(KERN_NOTICE "SCSI subsystem initialized\n");
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 84c3937ae8f..62f8cb7b3d2 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -56,6 +56,8 @@ static struct {
{"DENON", "DRD-25X", "V", BLIST_NOLUN}, /* locks up */
{"HITACHI", "DK312C", "CM81", BLIST_NOLUN}, /* responds to all lun */
{"HITACHI", "DK314C", "CR21", BLIST_NOLUN}, /* responds to all lun */
+ {"IBM", "2104-DU3", NULL, BLIST_NOLUN}, /* locks up */
+ {"IBM", "2104-TU3", NULL, BLIST_NOLUN}, /* locks up */
{"IMS", "CDD521/10", "2.06", BLIST_NOLUN}, /* locks up */
{"MAXTOR", "XT-3280", "PR02", BLIST_NOLUN}, /* locks up */
{"MAXTOR", "XT-4380S", "B3C", BLIST_NOLUN}, /* locks up */
@@ -132,7 +134,9 @@ static struct {
{"CMD", "CRA-7280", NULL, BLIST_SPARSELUN}, /* CMD RAID Controller */
{"CNSI", "G7324", NULL, BLIST_SPARSELUN}, /* Chaparral G7324 RAID */
{"CNSi", "G8324", NULL, BLIST_SPARSELUN}, /* Chaparral G8324 RAID */
- {"COMPAQ", "LOGICAL VOLUME", NULL, BLIST_FORCELUN},
+ {"COMPAQ", "ARRAY CONTROLLER", NULL, BLIST_SPARSELUN | BLIST_LARGELUN |
+ BLIST_MAX_512 | BLIST_REPORTLUN2}, /* Compaq RA4x00 */
+ {"COMPAQ", "LOGICAL VOLUME", NULL, BLIST_FORCELUN | BLIST_MAX_512}, /* Compaq RA4x00 */
{"COMPAQ", "CR3500", NULL, BLIST_FORCELUN},
{"COMPAQ", "MSA1000", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
{"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
@@ -161,6 +165,7 @@ static struct {
{"HP", "HSV100", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
{"HP", "C1557A", NULL, BLIST_FORCELUN},
{"HP", "C3323-300", "4269", BLIST_NOTQ},
+ {"HP", "C5713A", NULL, BLIST_NOREPORTLUN},
{"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN},
{"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
{"IBM", "2105", NULL, BLIST_RETRY_HWERROR},
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 5f0fdfb2618..1c75646f968 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1537,8 +1537,8 @@ int scsi_error_handler(void *data)
* what we need to do to get it up and online again (if we can).
* If we fail, we end up taking the thing offline.
*/
- if (shost->hostt->eh_strategy_handler)
- shost->hostt->eh_strategy_handler(shost);
+ if (shost->transportt->eh_strategy_handler)
+ shost->transportt->eh_strategy_handler(shost);
else
scsi_unjam_host(shost);
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 36e93006664..a89aff61d3d 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -158,180 +158,6 @@ int scsi_set_medium_removal(struct scsi_device *sdev, char state)
EXPORT_SYMBOL(scsi_set_medium_removal);
/*
- * This interface is deprecated - users should use the scsi generic (sg)
- * interface instead, as this is a more flexible approach to performing
- * generic SCSI commands on a device.
- *
- * The structure that we are passed should look like:
- *
- * struct sdata {
- * unsigned int inlen; [i] Length of data to be written to device
- * unsigned int outlen; [i] Length of data to be read from device
- * unsigned char cmd[x]; [i] SCSI command (6 <= x <= 12).
- * [o] Data read from device starts here.
- * [o] On error, sense buffer starts here.
- * unsigned char wdata[y]; [i] Data written to device starts here.
- * };
- * Notes:
- * - The SCSI command length is determined by examining the 1st byte
- * of the given command. There is no way to override this.
- * - Data transfers are limited to PAGE_SIZE (4K on i386, 8K on alpha).
- * - The length (x + y) must be at least OMAX_SB_LEN bytes long to
- * accommodate the sense buffer when an error occurs.
- * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
- * old code will not be surprised.
- * - If a Unix error occurs (e.g. ENOMEM) then the user will receive
- * a negative return and the Unix error code in 'errno'.
- * If the SCSI command succeeds then 0 is returned.
- * Positive numbers returned are the compacted SCSI error codes (4
- * bytes in one int) where the lowest byte is the SCSI status.
- * See the drivers/scsi/scsi.h file for more information on this.
- *
- */
-#define OMAX_SB_LEN 16 /* Old sense buffer length */
-
-int scsi_ioctl_send_command(struct scsi_device *sdev,
- struct scsi_ioctl_command __user *sic)
-{
- char *buf;
- unsigned char cmd[MAX_COMMAND_SIZE];
- unsigned char sense[SCSI_SENSE_BUFFERSIZE];
- char __user *cmd_in;
- unsigned char opcode;
- unsigned int inlen, outlen, cmdlen;
- unsigned int needed, buf_needed;
- int timeout, retries, result;
- int data_direction;
- gfp_t gfp_mask = GFP_KERNEL;
-
- if (!sic)
- return -EINVAL;
-
- if (sdev->host->unchecked_isa_dma)
- gfp_mask |= GFP_DMA;
-
- /*
- * Verify that we can read at least this much.
- */
- if (!access_ok(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command)))
- return -EFAULT;
-
- if(__get_user(inlen, &sic->inlen))
- return -EFAULT;
-
- if(__get_user(outlen, &sic->outlen))
- return -EFAULT;
-
- /*
- * We do not transfer more than MAX_BUF with this interface.
- * If the user needs to transfer more data than this, they
- * should use scsi_generics (sg) instead.
- */
- if (inlen > MAX_BUF)
- return -EINVAL;
- if (outlen > MAX_BUF)
- return -EINVAL;
-
- cmd_in = sic->data;
- if(get_user(opcode, cmd_in))
- return -EFAULT;
-
- needed = buf_needed = (inlen > outlen ? inlen : outlen);
- if (buf_needed) {
- buf_needed = (buf_needed + 511) & ~511;
- if (buf_needed > MAX_BUF)
- buf_needed = MAX_BUF;
- buf = kzalloc(buf_needed, gfp_mask);
- if (!buf)
- return -ENOMEM;
- if (inlen == 0) {
- data_direction = DMA_FROM_DEVICE;
- } else if (outlen == 0 ) {
- data_direction = DMA_TO_DEVICE;
- } else {
- /*
- * Can this ever happen?
- */
- data_direction = DMA_BIDIRECTIONAL;
- }
-
- } else {
- buf = NULL;
- data_direction = DMA_NONE;
- }
-
- /*
- * Obtain the command from the user's address space.
- */
- cmdlen = COMMAND_SIZE(opcode);
-
- result = -EFAULT;
-
- if (!access_ok(VERIFY_READ, cmd_in, cmdlen + inlen))
- goto error;
-
- if(__copy_from_user(cmd, cmd_in, cmdlen))
- goto error;
-
- /*
- * Obtain the data to be sent to the device (if any).
- */
-
- if(inlen && copy_from_user(buf, cmd_in + cmdlen, inlen))
- goto error;
-
- switch (opcode) {
- case SEND_DIAGNOSTIC:
- case FORMAT_UNIT:
- timeout = FORMAT_UNIT_TIMEOUT;
- retries = 1;
- break;
- case START_STOP:
- timeout = START_STOP_TIMEOUT;
- retries = NORMAL_RETRIES;
- break;
- case MOVE_MEDIUM:
- timeout = MOVE_MEDIUM_TIMEOUT;
- retries = NORMAL_RETRIES;
- break;
- case READ_ELEMENT_STATUS:
- timeout = READ_ELEMENT_STATUS_TIMEOUT;
- retries = NORMAL_RETRIES;
- break;
- case READ_DEFECT_DATA:
- timeout = READ_DEFECT_DATA_TIMEOUT;
- retries = 1;
- break;
- default:
- timeout = IOCTL_NORMAL_TIMEOUT;
- retries = NORMAL_RETRIES;
- break;
- }
-
- result = scsi_execute(sdev, cmd, data_direction, buf, needed,
- sense, timeout, retries, 0);
-
- /*
- * If there was an error condition, pass the info back to the user.
- */
- if (result) {
- int sb_len = sizeof(*sense);
-
- sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len;
- if (copy_to_user(cmd_in, sense, sb_len))
- result = -EFAULT;
- } else {
- if (outlen && copy_to_user(cmd_in, buf, outlen))
- result = -EFAULT;
- }
-
-error:
- kfree(buf);
- return result;
-}
-EXPORT_SYMBOL(scsi_ioctl_send_command);
-
-/*
* The scsi_ioctl_get_pci() function places into arg the value
* pci_dev::slot_name (8 characters) for the PCI device (if any).
* Returns: 0 on success
@@ -409,7 +235,7 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
case SCSI_IOCTL_SEND_COMMAND:
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
return -EACCES;
- return scsi_ioctl_send_command(sdev, arg);
+ return sg_scsi_ioctl(NULL, sdev->request_queue, NULL, arg);
case SCSI_IOCTL_DOORLOCK:
return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
case SCSI_IOCTL_DOORUNLOCK:
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 8f010a314a3..faee4757c03 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -367,7 +367,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
int nsegs, unsigned bufflen, gfp_t gfp)
{
struct request_queue *q = rq->q;
- int nr_pages = (bufflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned int data_len = 0, len, bytes, off;
struct page *page;
struct bio *bio = NULL;
@@ -1067,16 +1067,29 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
break;
case NOT_READY:
/*
- * If the device is in the process of becoming ready,
- * retry.
+ * If the device is in the process of becoming
+ * ready, or has a temporary blockage, retry.
*/
- if (sshdr.asc == 0x04 && sshdr.ascq == 0x01) {
- scsi_requeue_command(q, cmd);
- return;
+ if (sshdr.asc == 0x04) {
+ switch (sshdr.ascq) {
+ case 0x01: /* becoming ready */
+ case 0x04: /* format in progress */
+ case 0x05: /* rebuild in progress */
+ case 0x06: /* recalculation in progress */
+ case 0x07: /* operation in progress */
+ case 0x08: /* Long write in progress */
+ case 0x09: /* self test in progress */
+ scsi_requeue_command(q, cmd);
+ return;
+ default:
+ break;
+ }
}
- if (!(req->flags & REQ_QUIET))
+ if (!(req->flags & REQ_QUIET)) {
scmd_printk(KERN_INFO, cmd,
- "Device not ready.\n");
+ "Device not ready: ");
+ scsi_print_sense_hdr("", &sshdr);
+ }
scsi_end_request(cmd, 0, this_count, 1);
return;
case VOLUME_OVERFLOW:
@@ -1479,6 +1492,8 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
static void scsi_kill_request(struct request *req, request_queue_t *q)
{
struct scsi_cmnd *cmd = req->special;
+ struct scsi_device *sdev = cmd->device;
+ struct Scsi_Host *shost = sdev->host;
blkdev_dequeue_request(req);
@@ -1491,6 +1506,19 @@ static void scsi_kill_request(struct request *req, request_queue_t *q)
scsi_init_cmd_errh(cmd);
cmd->result = DID_NO_CONNECT << 16;
atomic_inc(&cmd->device->iorequest_cnt);
+
+ /*
+ * SCSI request completion path will do scsi_device_unbusy(),
+ * bump busy counts. To bump the counters, we need to dance
+ * with the locks as normal issue path does.
+ */
+ sdev->device_busy++;
+ spin_unlock(sdev->request_queue->queue_lock);
+ spin_lock(shost->host_lock);
+ shost->host_busy++;
+ spin_unlock(shost->host_lock);
+ spin_lock(sdev->request_queue->queue_lock);
+
__scsi_done(cmd);
}
diff --git a/drivers/scsi/scsi_sas_internal.h b/drivers/scsi/scsi_sas_internal.h
new file mode 100644
index 00000000000..d76e6e3d8ca
--- /dev/null
+++ b/drivers/scsi/scsi_sas_internal.h
@@ -0,0 +1,38 @@
+#ifndef _SCSI_SAS_INTERNAL_H
+#define _SCSI_SAS_INTERNAL_H
+
+#define SAS_HOST_ATTRS 0
+#define SAS_PORT_ATTRS 17
+#define SAS_RPORT_ATTRS 7
+#define SAS_END_DEV_ATTRS 3
+#define SAS_EXPANDER_ATTRS 7
+
+struct sas_internal {
+ struct scsi_transport_template t;
+ struct sas_function_template *f;
+ struct sas_domain_function_template *dft;
+
+ struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS];
+ struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS];
+ struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
+ struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS];
+ struct class_device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS];
+
+ struct transport_container phy_attr_cont;
+ struct transport_container rphy_attr_cont;
+ struct transport_container end_dev_attr_cont;
+ struct transport_container expander_attr_cont;
+
+ /*
+ * The array of null terminated pointers to attributes
+ * needed by scsi_sysfs.c
+ */
+ struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
+ struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1];
+ struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
+ struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1];
+ struct class_device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1];
+};
+#define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t)
+
+#endif
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index f14945996ed..1a5474bd11a 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -673,6 +673,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
case TYPE_MEDIUM_CHANGER:
case TYPE_ENCLOSURE:
case TYPE_COMM:
+ case TYPE_RAID:
case TYPE_RBC:
sdev->writeable = 1;
break;
@@ -738,6 +739,13 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
sdev->select_no_atn = 1;
/*
+ * Maximum 512 sector transfer length
+ * broken RA4x00 Compaq Disk Array
+ */
+ if (*bflags & BLIST_MAX_512)
+ blk_queue_max_sectors(sdev->request_queue, 512);
+
+ /*
* Some devices may not want to have a start command automatically
* issued when a device is added.
*/
@@ -1123,10 +1131,13 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
* Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does
* support more than 8 LUNs.
*/
- if ((bflags & BLIST_NOREPORTLUN) ||
- starget->scsi_level < SCSI_2 ||
- (starget->scsi_level < SCSI_3 &&
- (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8)) )
+ if (bflags & BLIST_NOREPORTLUN)
+ return 1;
+ if (starget->scsi_level < SCSI_2 &&
+ starget->scsi_level != SCSI_UNKNOWN)
+ return 1;
+ if (starget->scsi_level < SCSI_3 &&
+ (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8))
return 1;
if (bflags & BLIST_NOLUN)
return 0;
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 8db656214b5..95c5478dcdf 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -34,6 +34,8 @@
#include <scsi/scsi_cmnd.h>
#include "scsi_priv.h"
+static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
+
/*
* Redefine so that we can have same named attributes in the
* sdev/starget/host objects.
@@ -213,10 +215,8 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
#define FC_MGMTSRVR_PORTID 0x00000a
-static void fc_shost_remove_rports(void *data);
static void fc_timeout_deleted_rport(void *data);
static void fc_scsi_scan_rport(void *data);
-static void fc_rport_terminate(struct fc_rport *rport);
/*
* Attribute counts pre object type...
@@ -288,42 +288,58 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
struct class_device *cdev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
/*
* Set default values easily detected by the midlayer as
* failure cases. The scsi lldd is responsible for initializing
* all transport attributes to valid values per host.
*/
- fc_host_node_name(shost) = -1;
- fc_host_port_name(shost) = -1;
- fc_host_permanent_port_name(shost) = -1;
- fc_host_supported_classes(shost) = FC_COS_UNSPECIFIED;
- memset(fc_host_supported_fc4s(shost), 0,
- sizeof(fc_host_supported_fc4s(shost)));
- memset(fc_host_symbolic_name(shost), 0,
- sizeof(fc_host_symbolic_name(shost)));
- fc_host_supported_speeds(shost) = FC_PORTSPEED_UNKNOWN;
- fc_host_maxframe_size(shost) = -1;
- memset(fc_host_serial_number(shost), 0,
- sizeof(fc_host_serial_number(shost)));
-
- fc_host_port_id(shost) = -1;
- fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
- fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
- memset(fc_host_active_fc4s(shost), 0,
- sizeof(fc_host_active_fc4s(shost)));
- fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
- fc_host_fabric_name(shost) = -1;
-
- fc_host_tgtid_bind_type(shost) = FC_TGTID_BIND_BY_WWPN;
-
- INIT_LIST_HEAD(&fc_host_rports(shost));
- INIT_LIST_HEAD(&fc_host_rport_bindings(shost));
- fc_host_next_rport_number(shost) = 0;
- fc_host_next_target_id(shost) = 0;
-
- fc_host_flags(shost) = 0;
- INIT_WORK(&fc_host_rport_del_work(shost), fc_shost_remove_rports, shost);
+ fc_host->node_name = -1;
+ fc_host->port_name = -1;
+ fc_host->permanent_port_name = -1;
+ fc_host->supported_classes = FC_COS_UNSPECIFIED;
+ memset(fc_host->supported_fc4s, 0,
+ sizeof(fc_host->supported_fc4s));
+ memset(fc_host->symbolic_name, 0,
+ sizeof(fc_host->symbolic_name));
+ fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN;
+ fc_host->maxframe_size = -1;
+ memset(fc_host->serial_number, 0,
+ sizeof(fc_host->serial_number));
+
+ fc_host->port_id = -1;
+ fc_host->port_type = FC_PORTTYPE_UNKNOWN;
+ fc_host->port_state = FC_PORTSTATE_UNKNOWN;
+ memset(fc_host->active_fc4s, 0,
+ sizeof(fc_host->active_fc4s));
+ fc_host->speed = FC_PORTSPEED_UNKNOWN;
+ fc_host->fabric_name = -1;
+
+ fc_host->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN;
+
+ INIT_LIST_HEAD(&fc_host->rports);
+ INIT_LIST_HEAD(&fc_host->rport_bindings);
+ fc_host->next_rport_number = 0;
+ fc_host->next_target_id = 0;
+
+ snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d",
+ shost->host_no);
+ fc_host->work_q = create_singlethread_workqueue(
+ fc_host->work_q_name);
+ if (!fc_host->work_q)
+ return -ENOMEM;
+
+ snprintf(fc_host->devloss_work_q_name, KOBJ_NAME_LEN, "fc_dl_%d",
+ shost->host_no);
+ fc_host->devloss_work_q = create_singlethread_workqueue(
+ fc_host->devloss_work_q_name);
+ if (!fc_host->devloss_work_q) {
+ destroy_workqueue(fc_host->work_q);
+ fc_host->work_q = NULL;
+ return -ENOMEM;
+ }
+
return 0;
}
@@ -879,9 +895,9 @@ store_fc_private_host_tgtid_bind_type(struct class_device *cdev,
while (!list_empty(&fc_host_rport_bindings(shost))) {
get_list_head_entry(rport,
&fc_host_rport_bindings(shost), peers);
- spin_unlock_irqrestore(shost->host_lock, flags);
- fc_rport_terminate(rport);
- spin_lock_irqsave(shost->host_lock, flags);
+ list_del(&rport->peers);
+ rport->port_state = FC_PORTSTATE_DELETED;
+ fc_queue_work(shost, &rport->rport_delete_work);
}
spin_unlock_irqrestore(shost->host_lock, flags);
}
@@ -1262,6 +1278,90 @@ void fc_release_transport(struct scsi_transport_template *t)
}
EXPORT_SYMBOL(fc_release_transport);
+/**
+ * fc_queue_work - Queue work to the fc_host workqueue.
+ * @shost: Pointer to Scsi_Host bound to fc_host.
+ * @work: Work to queue for execution.
+ *
+ * Return value:
+ * 0 on success / != 0 for error
+ **/
+static int
+fc_queue_work(struct Scsi_Host *shost, struct work_struct *work)
+{
+ if (unlikely(!fc_host_work_q(shost))) {
+ printk(KERN_ERR
+ "ERROR: FC host '%s' attempted to queue work, "
+ "when no workqueue created.\n", shost->hostt->name);
+ dump_stack();
+
+ return -EINVAL;
+ }
+
+ return queue_work(fc_host_work_q(shost), work);
+}
+
+/**
+ * fc_flush_work - Flush a fc_host's workqueue.
+ * @shost: Pointer to Scsi_Host bound to fc_host.
+ **/
+static void
+fc_flush_work(struct Scsi_Host *shost)
+{
+ if (!fc_host_work_q(shost)) {
+ printk(KERN_ERR
+ "ERROR: FC host '%s' attempted to flush work, "
+ "when no workqueue created.\n", shost->hostt->name);
+ dump_stack();
+ return;
+ }
+
+ flush_workqueue(fc_host_work_q(shost));
+}
+
+/**
+ * fc_queue_devloss_work - Schedule work for the fc_host devloss workqueue.
+ * @shost: Pointer to Scsi_Host bound to fc_host.
+ * @work: Work to queue for execution.
+ * @delay: jiffies to delay the work queuing
+ *
+ * Return value:
+ * 0 on success / != 0 for error
+ **/
+static int
+fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work,
+ unsigned long delay)
+{
+ if (unlikely(!fc_host_devloss_work_q(shost))) {
+ printk(KERN_ERR
+ "ERROR: FC host '%s' attempted to queue work, "
+ "when no workqueue created.\n", shost->hostt->name);
+ dump_stack();
+
+ return -EINVAL;
+ }
+
+ return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay);
+}
+
+/**
+ * fc_flush_devloss - Flush a fc_host's devloss workqueue.
+ * @shost: Pointer to Scsi_Host bound to fc_host.
+ **/
+static void
+fc_flush_devloss(struct Scsi_Host *shost)
+{
+ if (!fc_host_devloss_work_q(shost)) {
+ printk(KERN_ERR
+ "ERROR: FC host '%s' attempted to flush work, "
+ "when no workqueue created.\n", shost->hostt->name);
+ dump_stack();
+ return;
+ }
+
+ flush_workqueue(fc_host_devloss_work_q(shost));
+}
+
/**
* fc_remove_host - called to terminate any fc_transport-related elements
@@ -1283,36 +1383,103 @@ void
fc_remove_host(struct Scsi_Host *shost)
{
struct fc_rport *rport, *next_rport;
+ struct workqueue_struct *work_q;
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
/* Remove any remote ports */
list_for_each_entry_safe(rport, next_rport,
- &fc_host_rports(shost), peers)
- fc_rport_terminate(rport);
+ &fc_host->rports, peers) {
+ list_del(&rport->peers);
+ rport->port_state = FC_PORTSTATE_DELETED;
+ fc_queue_work(shost, &rport->rport_delete_work);
+ }
+
list_for_each_entry_safe(rport, next_rport,
- &fc_host_rport_bindings(shost), peers)
- fc_rport_terminate(rport);
+ &fc_host->rport_bindings, peers) {
+ list_del(&rport->peers);
+ rport->port_state = FC_PORTSTATE_DELETED;
+ fc_queue_work(shost, &rport->rport_delete_work);
+ }
+
+ /* flush all scan work items */
+ scsi_flush_work(shost);
+
+ /* flush all stgt delete, and rport delete work items, then kill it */
+ if (fc_host->work_q) {
+ work_q = fc_host->work_q;
+ fc_host->work_q = NULL;
+ destroy_workqueue(work_q);
+ }
+
+ /* flush all devloss work items, then kill it */
+ if (fc_host->devloss_work_q) {
+ work_q = fc_host->devloss_work_q;
+ fc_host->devloss_work_q = NULL;
+ destroy_workqueue(work_q);
+ }
}
EXPORT_SYMBOL(fc_remove_host);
-/*
- * fc_rport_tgt_remove - Removes the scsi target on the remote port
- * @rport: The remote port to be operated on
- */
+
+/**
+ * fc_starget_delete - called to delete the scsi decendents of an rport
+ * (target and all sdevs)
+ *
+ * @data: remote port to be operated on.
+ **/
static void
-fc_rport_tgt_remove(struct fc_rport *rport)
+fc_starget_delete(void *data)
{
+ struct fc_rport *rport = (struct fc_rport *)data;
struct Scsi_Host *shost = rport_to_shost(rport);
+ unsigned long flags;
scsi_target_unblock(&rport->dev);
- /* Stop anything on the workq */
- if (!cancel_delayed_work(&rport->dev_loss_work))
- flush_scheduled_work();
- scsi_flush_work(shost);
+ spin_lock_irqsave(shost->host_lock, flags);
+ if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ if (!cancel_delayed_work(&rport->dev_loss_work))
+ fc_flush_devloss(shost);
+ spin_lock_irqsave(shost->host_lock, flags);
+ rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
scsi_remove_target(&rport->dev);
}
+
+/**
+ * fc_rport_final_delete - finish rport termination and delete it.
+ *
+ * @data: remote port to be deleted.
+ **/
+static void
+fc_rport_final_delete(void *data)
+{
+ struct fc_rport *rport = (struct fc_rport *)data;
+ struct device *dev = &rport->dev;
+ struct Scsi_Host *shost = rport_to_shost(rport);
+
+ /* Delete SCSI target and sdevs */
+ if (rport->scsi_target_id != -1)
+ fc_starget_delete(data);
+
+ /*
+ * if a scan is pending, flush the SCSI Host work_q so that
+ * that we can reclaim the rport scan work element.
+ */
+ if (rport->flags & FC_RPORT_SCAN_PENDING)
+ scsi_flush_work(shost);
+
+ transport_remove_device(dev);
+ device_del(dev);
+ transport_destroy_device(dev);
+ put_device(&shost->shost_gendev);
+}
+
+
/**
* fc_rport_create - allocates and creates a remote FC port.
* @shost: scsi host the remote port is connected to.
@@ -1330,8 +1497,7 @@ struct fc_rport *
fc_rport_create(struct Scsi_Host *shost, int channel,
struct fc_rport_identifiers *ids)
{
- struct fc_host_attrs *fc_host =
- (struct fc_host_attrs *)shost->shost_data;
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
struct fc_internal *fci = to_fc_internal(shost->transportt);
struct fc_rport *rport;
struct device *dev;
@@ -1360,6 +1526,8 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport);
INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport);
+ INIT_WORK(&rport->stgt_delete_work, fc_starget_delete, rport);
+ INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete, rport);
spin_lock_irqsave(shost->host_lock, flags);
@@ -1368,7 +1536,7 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
rport->scsi_target_id = fc_host->next_target_id++;
else
rport->scsi_target_id = -1;
- list_add_tail(&rport->peers, &fc_host_rports(shost));
+ list_add_tail(&rport->peers, &fc_host->rports);
get_device(&shost->shost_gendev);
spin_unlock_irqrestore(shost->host_lock, flags);
@@ -1389,9 +1557,11 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
transport_add_device(dev);
transport_configure_device(dev);
- if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+ if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
/* initiate a scan of the target */
+ rport->flags |= FC_RPORT_SCAN_PENDING;
scsi_queue_work(shost, &rport->scan_work);
+ }
return rport;
@@ -1451,10 +1621,14 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
struct fc_rport_identifiers *ids)
{
struct fc_internal *fci = to_fc_internal(shost->transportt);
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
struct fc_rport *rport;
unsigned long flags;
int match = 0;
+ /* ensure any stgt delete functions are done */
+ fc_flush_work(shost);
+
/*
* Search the list of "active" rports, for an rport that has been
* deleted, but we've held off the real delete while the target
@@ -1462,12 +1636,12 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
*/
spin_lock_irqsave(shost->host_lock, flags);
- list_for_each_entry(rport, &fc_host_rports(shost), peers) {
+ list_for_each_entry(rport, &fc_host->rports, peers) {
if ((rport->port_state == FC_PORTSTATE_BLOCKED) &&
(rport->channel == channel)) {
- switch (fc_host_tgtid_bind_type(shost)) {
+ switch (fc_host->tgtid_bind_type) {
case FC_TGTID_BIND_BY_WWPN:
case FC_TGTID_BIND_NONE:
if (rport->port_name == ids->port_name)
@@ -1521,27 +1695,34 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
* transaction.
*/
if (!cancel_delayed_work(work))
- flush_scheduled_work();
+ fc_flush_devloss(shost);
+
+ spin_lock_irqsave(shost->host_lock, flags);
+
+ rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
/* initiate a scan of the target */
+ rport->flags |= FC_RPORT_SCAN_PENDING;
scsi_queue_work(shost, &rport->scan_work);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
return rport;
}
}
}
/* Search the bindings array */
- if (fc_host_tgtid_bind_type(shost) != FC_TGTID_BIND_NONE) {
+ if (fc_host->tgtid_bind_type != FC_TGTID_BIND_NONE) {
/* search for a matching consistent binding */
- list_for_each_entry(rport, &fc_host_rport_bindings(shost),
+ list_for_each_entry(rport, &fc_host->rport_bindings,
peers) {
if (rport->channel != channel)
continue;
- switch (fc_host_tgtid_bind_type(shost)) {
+ switch (fc_host->tgtid_bind_type) {
case FC_TGTID_BIND_BY_WWPN:
if (rport->port_name == ids->port_name)
match = 1;
@@ -1559,8 +1740,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
}
if (match) {
- list_move_tail(&rport->peers,
- &fc_host_rports(shost));
+ list_move_tail(&rport->peers, &fc_host->rports);
break;
}
}
@@ -1574,15 +1754,17 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
rport->roles = ids->roles;
rport->port_state = FC_PORTSTATE_ONLINE;
- spin_unlock_irqrestore(shost->host_lock, flags);
-
if (fci->f->dd_fcrport_size)
memset(rport->dd_data, 0,
fci->f->dd_fcrport_size);
- if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+ if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
/* initiate a scan of the target */
+ rport->flags |= FC_RPORT_SCAN_PENDING;
scsi_queue_work(shost, &rport->scan_work);
+ }
+
+ spin_unlock_irqrestore(shost->host_lock, flags);
return rport;
}
@@ -1597,30 +1779,6 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
}
EXPORT_SYMBOL(fc_remote_port_add);
-/*
- * fc_rport_terminate - this routine tears down and deallocates a remote port.
- * @rport: The remote port to be terminated
- *
- * Notes:
- * This routine assumes no locks are held on entry.
- */
-static void
-fc_rport_terminate(struct fc_rport *rport)
-{
- struct Scsi_Host *shost = rport_to_shost(rport);
- struct device *dev = &rport->dev;
- unsigned long flags;
-
- fc_rport_tgt_remove(rport);
-
- transport_remove_device(dev);
- device_del(dev);
- transport_destroy_device(dev);
- spin_lock_irqsave(shost->host_lock, flags);
- list_del(&rport->peers);
- spin_unlock_irqrestore(shost->host_lock, flags);
- put_device(&shost->shost_gendev);
-}
/**
* fc_remote_port_delete - notifies the fc transport that a remote
@@ -1675,20 +1833,39 @@ fc_rport_terminate(struct fc_rport *rport)
void
fc_remote_port_delete(struct fc_rport *rport)
{
+ struct Scsi_Host *shost = rport_to_shost(rport);
int timeout = rport->dev_loss_tmo;
+ unsigned long flags;
+
+ /*
+ * No need to flush the fc_host work_q's, as all adds are synchronous.
+ *
+ * We do need to reclaim the rport scan work element, so eventually
+ * (in fc_rport_final_delete()) we'll flush the scsi host work_q if
+ * there's still a scan pending.
+ */
+
+ spin_lock_irqsave(shost->host_lock, flags);
/* If no scsi target id mapping, delete it */
if (rport->scsi_target_id == -1) {
- fc_rport_terminate(rport);
+ list_del(&rport->peers);
+ rport->port_state = FC_PORTSTATE_DELETED;
+ fc_queue_work(shost, &rport->rport_delete_work);
+ spin_unlock_irqrestore(shost->host_lock, flags);
return;
}
+ rport->port_state = FC_PORTSTATE_BLOCKED;
+
+ rport->flags |= FC_RPORT_DEVLOSS_PENDING;
+
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
scsi_target_block(&rport->dev);
/* cap the length the devices can be blocked until they are deleted */
- schedule_delayed_work(&rport->dev_loss_work, timeout * HZ);
-
- rport->port_state = FC_PORTSTATE_BLOCKED;
+ fc_queue_devloss_work(shost, &rport->dev_loss_work, timeout * HZ);
}
EXPORT_SYMBOL(fc_remote_port_delete);
@@ -1716,8 +1893,7 @@ void
fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
{
struct Scsi_Host *shost = rport_to_shost(rport);
- struct fc_host_attrs *fc_host =
- (struct fc_host_attrs *)shost->shost_data;
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
unsigned long flags;
int create = 0;
@@ -1729,10 +1905,11 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
} else if (!(rport->roles & FC_RPORT_ROLE_FCP_TARGET))
create = 1;
}
- spin_unlock_irqrestore(shost->host_lock, flags);
rport->roles = roles;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
if (create) {
/*
* There may have been a delete timer running on the
@@ -1747,10 +1924,20 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
* transaction.
*/
if (!cancel_delayed_work(&rport->dev_loss_work))
- flush_scheduled_work();
+ fc_flush_devloss(shost);
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ /* ensure any stgt delete functions are done */
+ fc_flush_work(shost);
/* initiate a scan of the target */
+ spin_lock_irqsave(shost->host_lock, flags);
+ rport->flags |= FC_RPORT_SCAN_PENDING;
scsi_queue_work(shost, &rport->scan_work);
+ spin_unlock_irqrestore(shost->host_lock, flags);
}
}
EXPORT_SYMBOL(fc_remote_port_rolechg);
@@ -1767,22 +1954,24 @@ fc_timeout_deleted_rport(void *data)
{
struct fc_rport *rport = (struct fc_rport *)data;
struct Scsi_Host *shost = rport_to_shost(rport);
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
+ rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
+
/*
- * If the port is ONLINE, then it came back, but was no longer an
- * FCP target. Thus we need to tear down the scsi_target on it.
+ * If the port is ONLINE, then it came back. Validate it's still an
+ * FCP target. If not, tear down the scsi_target on it.
*/
- if (rport->port_state == FC_PORTSTATE_ONLINE) {
- spin_unlock_irqrestore(shost->host_lock, flags);
-
+ if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
+ !(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
dev_printk(KERN_ERR, &rport->dev,
- "blocked FC remote port time out: removing target\n");
-
- fc_rport_tgt_remove(rport);
-
+ "blocked FC remote port time out: no longer"
+ " a FCP target, removing starget\n");
+ fc_queue_work(shost, &rport->stgt_delete_work);
+ spin_unlock_irqrestore(shost->host_lock, flags);
return;
}
@@ -1793,11 +1982,13 @@ fc_timeout_deleted_rport(void *data)
return;
}
- if (fc_host_tgtid_bind_type(shost) == FC_TGTID_BIND_NONE) {
- spin_unlock_irqrestore(shost->host_lock, flags);
+ if (fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) {
+ list_del(&rport->peers);
+ rport->port_state = FC_PORTSTATE_DELETED;
dev_printk(KERN_ERR, &rport->dev,
"blocked FC remote port time out: removing target\n");
- fc_rport_terminate(rport);
+ fc_queue_work(shost, &rport->rport_delete_work);
+ spin_unlock_irqrestore(shost->host_lock, flags);
return;
}
@@ -1805,7 +1996,7 @@ fc_timeout_deleted_rport(void *data)
"blocked FC remote port time out: removing target and "
"saving binding\n");
- list_move_tail(&rport->peers, &fc_host_rport_bindings(shost));
+ list_move_tail(&rport->peers, &fc_host->rport_bindings);
/*
* Note: We do not remove or clear the hostdata area. This allows
@@ -1819,10 +2010,10 @@ fc_timeout_deleted_rport(void *data)
rport->maxframe_size = -1;
rport->supported_classes = FC_COS_UNSPECIFIED;
rport->roles = FC_RPORT_ROLE_UNKNOWN;
- rport->port_state = FC_PORTSTATE_DELETED;
+ rport->port_state = FC_PORTSTATE_NOTPRESENT;
/* remove the identifiers that aren't used in the consisting binding */
- switch (fc_host_tgtid_bind_type(shost)) {
+ switch (fc_host->tgtid_bind_type) {
case FC_TGTID_BIND_BY_WWPN:
rport->node_name = -1;
rport->port_id = -1;
@@ -1843,17 +2034,8 @@ fc_timeout_deleted_rport(void *data)
* As this only occurs if the remote port (scsi target)
* went away and didn't come back - we'll remove
* all attached scsi devices.
- *
- * We'll schedule the shost work item to perform the actual removal
- * to avoid recursion in the different flush calls if we perform
- * the removal in each target - and there are lots of targets
- * whose timeouts fire at the same time.
*/
-
- if ( !(fc_host_flags(shost) & FC_SHOST_RPORT_DEL_SCHEDULED)) {
- fc_host_flags(shost) |= FC_SHOST_RPORT_DEL_SCHEDULED;
- scsi_queue_work(shost, &fc_host_rport_del_work(shost));
- }
+ fc_queue_work(shost, &rport->stgt_delete_work);
spin_unlock_irqrestore(shost->host_lock, flags);
}
@@ -1870,44 +2052,18 @@ static void
fc_scsi_scan_rport(void *data)
{
struct fc_rport *rport = (struct fc_rport *)data;
-
- scsi_target_unblock(&rport->dev);
- scsi_scan_target(&rport->dev, rport->channel, rport->scsi_target_id,
- SCAN_WILD_CARD, 1);
-}
-
-
-/**
- * fc_shost_remove_rports - called to remove all rports that are marked
- * as in a deleted (not connected) state.
- *
- * @data: shost whose rports are to be looked at
- **/
-static void
-fc_shost_remove_rports(void *data)
-{
- struct Scsi_Host *shost = (struct Scsi_Host *)data;
- struct fc_rport *rport, *next_rport;
+ struct Scsi_Host *shost = rport_to_shost(rport);
unsigned long flags;
- spin_lock_irqsave(shost->host_lock, flags);
- while (fc_host_flags(shost) & FC_SHOST_RPORT_DEL_SCHEDULED) {
-
- fc_host_flags(shost) &= ~FC_SHOST_RPORT_DEL_SCHEDULED;
-
-restart_search:
- list_for_each_entry_safe(rport, next_rport,
- &fc_host_rport_bindings(shost), peers) {
- if (rport->port_state == FC_PORTSTATE_DELETED) {
- rport->port_state = FC_PORTSTATE_NOTPRESENT;
- spin_unlock_irqrestore(shost->host_lock, flags);
- fc_rport_tgt_remove(rport);
- spin_lock_irqsave(shost->host_lock, flags);
- goto restart_search;
- }
- }
-
+ if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
+ (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
+ scsi_target_unblock(&rport->dev);
+ scsi_scan_target(&rport->dev, rport->channel,
+ rport->scsi_target_id, SCAN_WILD_CARD, 1);
}
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ rport->flags &= ~FC_RPORT_SCAN_PENDING;
spin_unlock_irqrestore(shost->host_lock, flags);
}
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 134c44c8538..f3b16066387 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -35,40 +35,7 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
-
-#define SAS_HOST_ATTRS 0
-#define SAS_PORT_ATTRS 17
-#define SAS_RPORT_ATTRS 7
-#define SAS_END_DEV_ATTRS 3
-#define SAS_EXPANDER_ATTRS 7
-
-struct sas_internal {
- struct scsi_transport_template t;
- struct sas_function_template *f;
-
- struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS];
- struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS];
- struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
- struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS];
- struct class_device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS];
-
- struct transport_container phy_attr_cont;
- struct transport_container rphy_attr_cont;
- struct transport_container end_dev_attr_cont;
- struct transport_container expander_attr_cont;
-
- /*
- * The array of null terminated pointers to attributes
- * needed by scsi_sysfs.c
- */
- struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
- struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1];
- struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
- struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1];
- struct class_device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1];
-};
-#define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t)
-
+#include "scsi_sas_internal.h"
struct sas_host_attrs {
struct list_head rphy_list;
struct mutex lock;
@@ -406,8 +373,6 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number)
if (!phy)
return NULL;
- get_device(parent);
-
phy->number = number;
device_initialize(&phy->dev);
@@ -459,10 +424,7 @@ EXPORT_SYMBOL(sas_phy_add);
void sas_phy_free(struct sas_phy *phy)
{
transport_destroy_device(&phy->dev);
- put_device(phy->dev.parent);
- put_device(phy->dev.parent);
- put_device(phy->dev.parent);
- kfree(phy);
+ put_device(&phy->dev);
}
EXPORT_SYMBOL(sas_phy_free);
@@ -484,7 +446,7 @@ sas_phy_delete(struct sas_phy *phy)
transport_remove_device(dev);
device_del(dev);
transport_destroy_device(dev);
- put_device(dev->parent);
+ put_device(dev);
}
EXPORT_SYMBOL(sas_phy_delete);
@@ -800,7 +762,6 @@ struct sas_rphy *sas_end_device_alloc(struct sas_phy *parent)
rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
if (!rdev) {
- put_device(&parent->dev);
return NULL;
}
@@ -836,7 +797,6 @@ struct sas_rphy *sas_expander_alloc(struct sas_phy *parent,
rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
if (!rdev) {
- put_device(&parent->dev);
return NULL;
}
@@ -885,6 +845,8 @@ int sas_rphy_add(struct sas_rphy *rphy)
(identify->target_port_protocols &
(SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA)))
rphy->scsi_target_id = sas_host->next_target_id++;
+ else if (identify->device_type == SAS_END_DEVICE)
+ rphy->scsi_target_id = -1;
mutex_unlock(&sas_host->lock);
if (identify->device_type == SAS_END_DEVICE &&
@@ -910,6 +872,7 @@ EXPORT_SYMBOL(sas_rphy_add);
*/
void sas_rphy_free(struct sas_rphy *rphy)
{
+ struct device *dev = &rphy->dev;
struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
@@ -917,21 +880,9 @@ void sas_rphy_free(struct sas_rphy *rphy)
list_del(&rphy->list);
mutex_unlock(&sas_host->lock);
- transport_destroy_device(&rphy->dev);
- put_device(rphy->dev.parent);
- put_device(rphy->dev.parent);
- put_device(rphy->dev.parent);
- if (rphy->identify.device_type == SAS_END_DEVICE) {
- struct sas_end_device *edev = rphy_to_end_device(rphy);
-
- kfree(edev);
- } else {
- /* must be expander */
- struct sas_expander_device *edev =
- rphy_to_expander_device(rphy);
+ transport_destroy_device(dev);
- kfree(edev);
- }
+ put_device(dev);
}
EXPORT_SYMBOL(sas_rphy_free);
@@ -971,7 +922,7 @@ sas_rphy_delete(struct sas_rphy *rphy)
parent->rphy = NULL;
- put_device(&parent->dev);
+ put_device(dev);
}
EXPORT_SYMBOL(sas_rphy_delete);
@@ -1004,7 +955,8 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
list_for_each_entry(rphy, &sas_host->rphy_list, list) {
struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
- if (rphy->scsi_target_id == -1)
+ if (rphy->identify.device_type != SAS_END_DEVICE ||
+ rphy->scsi_target_id == -1)
continue;
if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) &&
@@ -1026,7 +978,6 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
#define SETUP_TEMPLATE(attrb, field, perm, test) \
i->private_##attrb[count] = class_device_attr_##field; \
i->private_##attrb[count].attr.mode = perm; \
- i->private_##attrb[count].store = NULL; \
i->attrb[count] = &i->private_##attrb[count]; \
if (test) \
count++
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7405d0df95d..b098942445e 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -748,6 +748,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
/*
* most likely out of mem, but could also be a bad map
*/
+ sg_finish_rem_req(srp);
return -ENOMEM;
} else
return 0;
@@ -1044,7 +1045,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
if (!sg_allow_access(opcode, sdp->device->type))
return -EPERM;
}
- return scsi_ioctl_send_command(sdp->device, p);
+ return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p);
case SG_SET_DEBUG:
result = get_user(val, ip);
if (result)
@@ -1798,8 +1799,10 @@ sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len)
res = st_map_user_pages(schp->buffer, mx_sc_elems,
(unsigned long)hp->dxferp, dxfer_len,
(SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0);
- if (res <= 0)
+ if (res <= 0) {
+ sg_remove_scat(schp);
return 1;
+ }
schp->k_use_sg = res;
schp->dio_in_use = 1;
hp->info |= SG_INFO_DIRECT_IO;
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
index 3274ab76c8d..255886a9ac5 100644
--- a/drivers/scsi/sim710.c
+++ b/drivers/scsi/sim710.c
@@ -75,7 +75,7 @@ param_setup(char *str)
else if(!strncmp(pos, "id:", 3)) {
if(slot == -1) {
printk(KERN_WARNING "sim710: Must specify slot for id parameter\n");
- } else if(slot > MAX_SLOTS) {
+ } else if(slot >= MAX_SLOTS) {
printk(KERN_WARNING "sim710: Illegal slot %d for id %d\n", slot, val);
} else {
id_array[slot] = val;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index d40e7c871c3..56cb4900611 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4054,7 +4054,7 @@ static int st_probe(struct device *dev)
}
sdev_printk(KERN_WARNING, SDp,
- "Attached scsi tape %s", tape_name(tpnt));
+ "Attached scsi tape %s\n", tape_name(tpnt));
printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n",
tape_name(tpnt), tpnt->try_dio ? "yes" : "no",
queue_dma_alignment(SDp->request_queue) + 1);
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
index 3659dd7b9d7..defccc477d1 100644
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h
@@ -40,7 +40,7 @@
#ifndef SYM_DEFS_H
#define SYM_DEFS_H
-#define SYM_VERSION "2.2.2"
+#define SYM_VERSION "2.2.3"
#define SYM_DRIVER_NAME "sym-" SYM_VERSION
/*
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 1fffd2b3c65..9c83b4d39a2 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -134,66 +134,17 @@ static void sym2_setup_params(void)
}
}
-/*
- * We used to try to deal with 64-bit BARs here, but don't any more.
- * There are many parts of this driver which would need to be modified
- * to handle a 64-bit base address, including scripts. I'm uncomfortable
- * with making those changes when I have no way of testing it, so I'm
- * just going to disable it.
- *
- * Note that some machines (eg HP rx8620 and Superdome) have bus addresses
- * below 4GB and physical addresses above 4GB. These will continue to work.
- */
-static int __devinit
-pci_get_base_address(struct pci_dev *pdev, int index, unsigned long *basep)
-{
- u32 tmp;
- unsigned long base;
-#define PCI_BAR_OFFSET(index) (PCI_BASE_ADDRESS_0 + (index<<2))
-
- pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp);
- base = tmp;
- if ((tmp & 0x7) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
- pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp);
- if (tmp > 0) {
- dev_err(&pdev->dev,
- "BAR %d is 64-bit, disabling\n", index - 1);
- base = 0;
- }
- }
-
- if ((base & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
- base &= PCI_BASE_ADDRESS_IO_MASK;
- } else {
- base &= PCI_BASE_ADDRESS_MEM_MASK;
- }
-
- *basep = base;
- return index;
-#undef PCI_BAR_OFFSET
-}
-
static struct scsi_transport_template *sym2_transport_template = NULL;
/*
- * Used by the eh thread to wait for command completion.
- * It is allocated on the eh thread stack.
- */
-struct sym_eh_wait {
- struct completion done;
- struct timer_list timer;
- void (*old_done)(struct scsi_cmnd *);
- int to_do;
- int timed_out;
-};
-
-/*
* Driver private area in the SCSI command structure.
*/
struct sym_ucmd { /* Override the SCSI pointer structure */
- dma_addr_t data_mapping;
- u_char data_mapped;
- struct sym_eh_wait *eh_wait;
+ dma_addr_t data_mapping;
+ unsigned char data_mapped;
+ unsigned char to_do; /* For error handling */
+ void (*old_done)(struct scsi_cmnd *); /* For error handling */
+ struct completion *eh_done; /* For error handling */
};
#define SYM_UCMD_PTR(cmd) ((struct sym_ucmd *)(&(cmd)->SCp))
@@ -514,8 +465,6 @@ static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *cmd, struc
*/
int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp)
{
- struct sym_tcb *tp = &np->target[cp->target];
- struct sym_lcb *lp = sym_lp(tp, cp->lun);
u32 lastp, goalp;
int dir;
@@ -596,7 +545,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s
/*
* activate this job.
*/
- sym_start_next_ccbs(np, lp, 2);
+ sym_put_start_queue(np, cp);
return 0;
out_abort:
@@ -751,80 +700,54 @@ static void sym53c8xx_timer(unsigned long npref)
* What we will do regarding the involved SCSI command.
*/
#define SYM_EH_DO_IGNORE 0
-#define SYM_EH_DO_COMPLETE 1
#define SYM_EH_DO_WAIT 2
/*
- * Our general completion handler.
+ * scsi_done() alias when error recovery is in progress.
*/
-static void __sym_eh_done(struct scsi_cmnd *cmd, int timed_out)
+static void sym_eh_done(struct scsi_cmnd *cmd)
{
- struct sym_eh_wait *ep = SYM_UCMD_PTR(cmd)->eh_wait;
- if (!ep)
- return;
-
- /* Try to avoid a race here (not 100% safe) */
- if (!timed_out) {
- ep->timed_out = 0;
- if (ep->to_do == SYM_EH_DO_WAIT && !del_timer(&ep->timer))
- return;
- }
+ struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
+ BUILD_BUG_ON(sizeof(struct scsi_pointer) < sizeof(struct sym_ucmd));
- /* Revert everything */
- SYM_UCMD_PTR(cmd)->eh_wait = NULL;
- cmd->scsi_done = ep->old_done;
+ cmd->scsi_done = ucmd->old_done;
- /* Wake up the eh thread if it wants to sleep */
- if (ep->to_do == SYM_EH_DO_WAIT)
- complete(&ep->done);
+ if (ucmd->to_do == SYM_EH_DO_WAIT)
+ complete(ucmd->eh_done);
}
/*
- * scsi_done() alias when error recovery is in progress.
- */
-static void sym_eh_done(struct scsi_cmnd *cmd) { __sym_eh_done(cmd, 0); }
-
-/*
- * Some timeout handler to avoid waiting too long.
- */
-static void sym_eh_timeout(u_long p) { __sym_eh_done((struct scsi_cmnd *)p, 1); }
-
-/*
* Generic method for our eh processing.
* The 'op' argument tells what we have to do.
*/
static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
{
struct sym_hcb *np = SYM_SOFTC_PTR(cmd);
+ struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
+ struct Scsi_Host *host = cmd->device->host;
SYM_QUEHEAD *qp;
int to_do = SYM_EH_DO_IGNORE;
int sts = -1;
- struct sym_eh_wait eh, *ep = &eh;
+ struct completion eh_done;
dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname);
+ spin_lock_irq(host->host_lock);
/* This one is queued in some place -> to wait for completion */
FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
if (cp->cmd == cmd) {
to_do = SYM_EH_DO_WAIT;
- goto prepare;
+ break;
}
}
-prepare:
- /* Prepare stuff to either ignore, complete or wait for completion */
- switch(to_do) {
- default:
- case SYM_EH_DO_IGNORE:
- break;
- case SYM_EH_DO_WAIT:
- init_completion(&ep->done);
- /* fall through */
- case SYM_EH_DO_COMPLETE:
- ep->old_done = cmd->scsi_done;
+ if (to_do == SYM_EH_DO_WAIT) {
+ init_completion(&eh_done);
+ ucmd->old_done = cmd->scsi_done;
+ ucmd->eh_done = &eh_done;
+ wmb();
cmd->scsi_done = sym_eh_done;
- SYM_UCMD_PTR(cmd)->eh_wait = ep;
}
/* Try to proceed the operation we have been asked for */
@@ -851,29 +774,19 @@ prepare:
/* On error, restore everything and cross fingers :) */
if (sts) {
- SYM_UCMD_PTR(cmd)->eh_wait = NULL;
- cmd->scsi_done = ep->old_done;
+ cmd->scsi_done = ucmd->old_done;
to_do = SYM_EH_DO_IGNORE;
}
- ep->to_do = to_do;
- /* Complete the command with locks held as required by the driver */
- if (to_do == SYM_EH_DO_COMPLETE)
- sym_xpt_done2(np, cmd, DID_ABORT);
+ ucmd->to_do = to_do;
+ spin_unlock_irq(host->host_lock);
- /* Wait for completion with locks released, as required by kernel */
if (to_do == SYM_EH_DO_WAIT) {
- init_timer(&ep->timer);
- ep->timer.expires = jiffies + (5*HZ);
- ep->timer.function = sym_eh_timeout;
- ep->timer.data = (u_long)cmd;
- ep->timed_out = 1; /* Be pessimistic for once :) */
- add_timer(&ep->timer);
- spin_unlock_irq(np->s.host->host_lock);
- wait_for_completion(&ep->done);
- spin_lock_irq(np->s.host->host_lock);
- if (ep->timed_out)
+ if (!wait_for_completion_timeout(&eh_done, 5*HZ)) {
+ ucmd->to_do = SYM_EH_DO_IGNORE;
+ wmb();
sts = -2;
+ }
}
dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname,
sts==0 ? "complete" :sts==-2 ? "timed-out" : "failed");
@@ -886,46 +799,22 @@ prepare:
*/
static int sym53c8xx_eh_abort_handler(struct scsi_cmnd *cmd)
{
- int rc;
-
- spin_lock_irq(cmd->device->host->host_lock);
- rc = sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
- spin_unlock_irq(cmd->device->host->host_lock);
-
- return rc;
+ return sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
}
static int sym53c8xx_eh_device_reset_handler(struct scsi_cmnd *cmd)
{
- int rc;
-
- spin_lock_irq(cmd->device->host->host_lock);
- rc = sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
- spin_unlock_irq(cmd->device->host->host_lock);
-
- return rc;
+ return sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
}
static int sym53c8xx_eh_bus_reset_handler(struct scsi_cmnd *cmd)
{
- int rc;
-
- spin_lock_irq(cmd->device->host->host_lock);
- rc = sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd);
- spin_unlock_irq(cmd->device->host->host_lock);
-
- return rc;
+ return sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd);
}
static int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd)
{
- int rc;
-
- spin_lock_irq(cmd->device->host->host_lock);
- rc = sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd);
- spin_unlock_irq(cmd->device->host->host_lock);
-
- return rc;
+ return sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd);
}
/*
@@ -944,15 +833,12 @@ static void sym_tune_dev_queuing(struct sym_tcb *tp, int lun, u_short reqtags)
if (reqtags > lp->s.scdev_depth)
reqtags = lp->s.scdev_depth;
- lp->started_limit = reqtags ? reqtags : 2;
- lp->started_max = 1;
lp->s.reqtags = reqtags;
if (reqtags != oldtags) {
dev_info(&tp->starget->dev,
"tagged command queuing %s, command queue depth %d.\n",
- lp->s.reqtags ? "enabled" : "disabled",
- lp->started_limit);
+ lp->s.reqtags ? "enabled" : "disabled", reqtags);
}
}
@@ -1866,15 +1752,25 @@ static int __devinit sym_set_workarounds(struct sym_device *device)
static void __devinit
sym_init_device(struct pci_dev *pdev, struct sym_device *device)
{
- int i;
+ int i = 2;
+ struct pci_bus_region bus_addr;
device->host_id = SYM_SETUP_HOST_ID;
device->pdev = pdev;
- i = pci_get_base_address(pdev, 1, &device->mmio_base);
- pci_get_base_address(pdev, i, &device->ram_base);
+ pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[1]);
+ device->mmio_base = bus_addr.start;
+
+ /*
+ * If the BAR is 64-bit, resource 2 will be occupied by the
+ * upper 32 bits
+ */
+ if (!pdev->resource[i].flags)
+ i++;
+ pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[i]);
+ device->ram_base = bus_addr.start;
-#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
+#ifdef CONFIG_SCSI_SYM53C8XX_MMIO
if (device->mmio_base)
device->s.ioaddr = pci_iomap(pdev, 1,
pci_resource_len(pdev, 1));
@@ -1978,7 +1874,8 @@ static struct scsi_host_template sym2_template = {
.eh_bus_reset_handler = sym53c8xx_eh_bus_reset_handler,
.eh_host_reset_handler = sym53c8xx_eh_host_reset_handler,
.this_id = 7,
- .use_clustering = DISABLE_CLUSTERING,
+ .use_clustering = ENABLE_CLUSTERING,
+ .max_sectors = 0xFFFF,
#ifdef SYM_LINUX_PROC_INFO_SUPPORT
.proc_info = sym53c8xx_proc_info,
.proc_name = NAME53C8XX,
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index cc92d0c70cd..a446cda3f64 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -68,7 +68,7 @@
*/
#define SYM_CONF_TIMER_INTERVAL ((HZ+1)/2)
-#define SYM_OPT_HANDLE_DEVICE_QUEUEING
+#undef SYM_OPT_HANDLE_DEVICE_QUEUEING
#define SYM_OPT_LIMIT_COMMAND_REORDERING
/*
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 60850cbe3a8..a671bdc0745 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -72,7 +72,10 @@ static void sym_printl_hex(u_char *p, int n)
static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg)
{
- sym_print_addr(cp->cmd, "%s: ", label);
+ if (label)
+ sym_print_addr(cp->cmd, "%s: ", label);
+ else
+ sym_print_addr(cp->cmd, "");
spi_print_msg(msg);
printf("\n");
@@ -472,7 +475,7 @@ static int sym_getpciclock (struct sym_hcb *np)
* calculations more simple.
*/
#define _5M 5000000
-static u32 div_10M[] = {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M};
+static const u32 div_10M[] = {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M};
/*
* Get clock factor and sync divisor for a given
@@ -645,6 +648,37 @@ static void sym_save_initial_setting (struct sym_hcb *np)
}
/*
+ * Set SCSI BUS mode.
+ * - LVD capable chips (895/895A/896/1010) report the current BUS mode
+ * through the STEST4 IO register.
+ * - For previous generation chips (825/825A/875), the user has to tell us
+ * how to check against HVD, since a 100% safe algorithm is not possible.
+ */
+static void sym_set_bus_mode(struct sym_hcb *np, struct sym_nvram *nvram)
+{
+ if (np->scsi_mode)
+ return;
+
+ np->scsi_mode = SMODE_SE;
+ if (np->features & (FE_ULTRA2|FE_ULTRA3))
+ np->scsi_mode = (np->sv_stest4 & SMODE);
+ else if (np->features & FE_DIFF) {
+ if (SYM_SETUP_SCSI_DIFF == 1) {
+ if (np->sv_scntl3) {
+ if (np->sv_stest2 & 0x20)
+ np->scsi_mode = SMODE_HVD;
+ } else if (nvram->type == SYM_SYMBIOS_NVRAM) {
+ if (!(INB(np, nc_gpreg) & 0x08))
+ np->scsi_mode = SMODE_HVD;
+ }
+ } else if (SYM_SETUP_SCSI_DIFF == 2)
+ np->scsi_mode = SMODE_HVD;
+ }
+ if (np->scsi_mode == SMODE_HVD)
+ np->rv_stest2 |= 0x20;
+}
+
+/*
* Prepare io register values used by sym_start_up()
* according to selected and supported features.
*/
@@ -654,10 +688,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
u32 period;
int i;
- /*
- * Wide ?
- */
- np->maxwide = (np->features & FE_WIDE)? 1 : 0;
+ np->maxwide = (np->features & FE_WIDE) ? 1 : 0;
/*
* Guess the frequency of the chip's clock.
@@ -838,6 +869,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
* Get parity checking, host ID and verbose mode from NVRAM
*/
np->myaddr = 255;
+ np->scsi_mode = 0;
sym_nvram_setup_host(shost, np, nvram);
/*
@@ -854,33 +886,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
*/
sym_init_burst(np, burst_max);
- /*
- * Set SCSI BUS mode.
- * - LVD capable chips (895/895A/896/1010) report the
- * current BUS mode through the STEST4 IO register.
- * - For previous generation chips (825/825A/875),
- * user has to tell us how to check against HVD,
- * since a 100% safe algorithm is not possible.
- */
- np->scsi_mode = SMODE_SE;
- if (np->features & (FE_ULTRA2|FE_ULTRA3))
- np->scsi_mode = (np->sv_stest4 & SMODE);
- else if (np->features & FE_DIFF) {
- if (SYM_SETUP_SCSI_DIFF == 1) {
- if (np->sv_scntl3) {
- if (np->sv_stest2 & 0x20)
- np->scsi_mode = SMODE_HVD;
- }
- else if (nvram->type == SYM_SYMBIOS_NVRAM) {
- if (!(INB(np, nc_gpreg) & 0x08))
- np->scsi_mode = SMODE_HVD;
- }
- }
- else if (SYM_SETUP_SCSI_DIFF == 2)
- np->scsi_mode = SMODE_HVD;
- }
- if (np->scsi_mode == SMODE_HVD)
- np->rv_stest2 |= 0x20;
+ sym_set_bus_mode(np, nvram);
/*
* Set LED support from SCRIPTS.
@@ -973,8 +979,8 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
*
* Has to be called with interrupts disabled.
*/
-#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
-static int sym_regtest (struct sym_hcb *np)
+#ifdef CONFIG_SCSI_SYM53C8XX_MMIO
+static int sym_regtest(struct sym_hcb *np)
{
register volatile u32 data;
/*
@@ -992,20 +998,25 @@ static int sym_regtest (struct sym_hcb *np)
#endif
printf ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n",
(unsigned) data);
- return (0x10);
+ return 0x10;
}
- return (0);
+ return 0;
+}
+#else
+static inline int sym_regtest(struct sym_hcb *np)
+{
+ return 0;
}
#endif
-static int sym_snooptest (struct sym_hcb *np)
+static int sym_snooptest(struct sym_hcb *np)
{
- u32 sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat;
- int i, err=0;
-#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
- err |= sym_regtest (np);
- if (err) return (err);
-#endif
+ u32 sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat;
+ int i, err;
+
+ err = sym_regtest(np);
+ if (err)
+ return err;
restart_test:
/*
* Enable Master Parity Checking as we intend
@@ -1094,7 +1105,7 @@ restart_test:
err |= 4;
}
- return (err);
+ return err;
}
/*
@@ -1464,7 +1475,7 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp
/*
* Insert a job into the start queue.
*/
-static void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
+void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
{
u_short qidx;
@@ -4481,7 +4492,7 @@ static void sym_int_sir (struct sym_hcb *np)
switch (np->msgin [2]) {
case M_X_MODIFY_DP:
if (DEBUG_FLAGS & DEBUG_POINTER)
- sym_print_msg(cp,"modify DP",np->msgin);
+ sym_print_msg(cp, NULL, np->msgin);
tmp = (np->msgin[3]<<24) + (np->msgin[4]<<16) +
(np->msgin[5]<<8) + (np->msgin[6]);
sym_modify_dp(np, tp, cp, tmp);
@@ -4508,7 +4519,7 @@ static void sym_int_sir (struct sym_hcb *np)
*/
case M_IGN_RESIDUE:
if (DEBUG_FLAGS & DEBUG_POINTER)
- sym_print_msg(cp,"ign wide residue", np->msgin);
+ sym_print_msg(cp, NULL, np->msgin);
if (cp->host_flags & HF_SENSE)
OUTL_DSP(np, SCRIPTA_BA(np, clrack));
else
@@ -4597,7 +4608,8 @@ struct sym_ccb *sym_get_ccb (struct sym_hcb *np, struct scsi_cmnd *cmd, u_char t
* Debugging purpose.
*/
#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
- assert(lp->busy_itl == 0);
+ if (lp->busy_itl != 0)
+ goto out_free;
#endif
/*
* Allocate resources for tags if not yet.
@@ -4642,7 +4654,8 @@ struct sym_ccb *sym_get_ccb (struct sym_hcb *np, struct scsi_cmnd *cmd, u_char t
* Debugging purpose.
*/
#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
- assert(lp->busy_itl == 0 && lp->busy_itlq == 0);
+ if (lp->busy_itl != 0 || lp->busy_itlq != 0)
+ goto out_free;
#endif
/*
* Count this nexus for this LUN.
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index 2456090bb24..79ab6a17703 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -1049,6 +1049,8 @@ int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
struct sym_chip *sym_lookup_chip_table(u_short device_id, u_char revision);
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);
+#else
+void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp);
#endif
void sym_start_up(struct sym_hcb *np, int reason);
void sym_interrupt(struct sym_hcb *np);
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index b131432c677..a6cfbb3b361 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -88,7 +88,7 @@ zalon_probe(struct parisc_device *dev)
struct gsc_irq gsc_irq;
u32 zalon_vers;
int error = -ENODEV;
- void __iomem *zalon = ioremap(dev->hpa.start, 4096);
+ void __iomem *zalon = ioremap_nocache(dev->hpa.start, 4096);
void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET;
static int unit = 0;
struct Scsi_Host *host;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 5996d3cd0ed..bbf78aaf9e0 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -362,6 +362,40 @@ serial_out(struct uart_8250_port *up, int offset, int value)
#define serial_inp(up, offset) serial_in(up, offset)
#define serial_outp(up, offset, value) serial_out(up, offset, value)
+/* Uart divisor latch read */
+static inline int _serial_dl_read(struct uart_8250_port *up)
+{
+ return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
+}
+
+/* Uart divisor latch write */
+static inline void _serial_dl_write(struct uart_8250_port *up, int value)
+{
+ serial_outp(up, UART_DLL, value & 0xff);
+ serial_outp(up, UART_DLM, value >> 8 & 0xff);
+}
+
+#ifdef CONFIG_SERIAL_8250_AU1X00
+/* Au1x00 haven't got a standard divisor latch */
+static int serial_dl_read(struct uart_8250_port *up)
+{
+ if (up->port.iotype == UPIO_AU)
+ return __raw_readl(up->port.membase + 0x28);
+ else
+ return _serial_dl_read(up);
+}
+
+static void serial_dl_write(struct uart_8250_port *up, int value)
+{
+ if (up->port.iotype == UPIO_AU)
+ __raw_writel(value, up->port.membase + 0x28);
+ else
+ _serial_dl_write(up, value);
+}
+#else
+#define serial_dl_read(up) _serial_dl_read(up)
+#define serial_dl_write(up, value) _serial_dl_write(up, value)
+#endif
/*
* For the 16C950
@@ -494,7 +528,8 @@ static void disable_rsa(struct uart_8250_port *up)
*/
static int size_fifo(struct uart_8250_port *up)
{
- unsigned char old_fcr, old_mcr, old_dll, old_dlm, old_lcr;
+ unsigned char old_fcr, old_mcr, old_lcr;
+ unsigned short old_dl;
int count;
old_lcr = serial_inp(up, UART_LCR);
@@ -505,10 +540,8 @@ static int size_fifo(struct uart_8250_port *up)
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
serial_outp(up, UART_MCR, UART_MCR_LOOP);
serial_outp(up, UART_LCR, UART_LCR_DLAB);
- old_dll = serial_inp(up, UART_DLL);
- old_dlm = serial_inp(up, UART_DLM);
- serial_outp(up, UART_DLL, 0x01);
- serial_outp(up, UART_DLM, 0x00);
+ old_dl = serial_dl_read(up);
+ serial_dl_write(up, 0x0001);
serial_outp(up, UART_LCR, 0x03);
for (count = 0; count < 256; count++)
serial_outp(up, UART_TX, count);
@@ -519,8 +552,7 @@ static int size_fifo(struct uart_8250_port *up)
serial_outp(up, UART_FCR, old_fcr);
serial_outp(up, UART_MCR, old_mcr);
serial_outp(up, UART_LCR, UART_LCR_DLAB);
- serial_outp(up, UART_DLL, old_dll);
- serial_outp(up, UART_DLM, old_dlm);
+ serial_dl_write(up, old_dl);
serial_outp(up, UART_LCR, old_lcr);
return count;
@@ -750,8 +782,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
serial_outp(up, UART_LCR, 0xE0);
- quot = serial_inp(up, UART_DLM) << 8;
- quot += serial_inp(up, UART_DLL);
+ quot = serial_dl_read(up);
quot <<= 3;
status1 = serial_in(up, 0x04); /* EXCR1 */
@@ -759,8 +790,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
serial_outp(up, 0x04, status1);
- serial_outp(up, UART_DLL, quot & 0xff);
- serial_outp(up, UART_DLM, quot >> 8);
+ serial_dl_write(up, quot);
serial_outp(up, UART_LCR, 0);
@@ -1528,7 +1558,7 @@ static int serial8250_startup(struct uart_port *port)
/*
* Clear the FIFO buffers and disable them.
- * (they will be reeanbled in set_termios())
+ * (they will be reenabled in set_termios())
*/
serial8250_clear_fifos(up);
@@ -1862,8 +1892,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
}
- serial_outp(up, UART_DLL, quot & 0xff); /* LS of divisor */
- serial_outp(up, UART_DLM, quot >> 8); /* MS of divisor */
+ serial_dl_write(up, quot);
/*
* LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
@@ -1906,6 +1935,9 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
int ret = 0;
switch (up->port.iotype) {
+ case UPIO_AU:
+ size = 0x100000;
+ /* fall thru */
case UPIO_MEM:
if (!up->port.mapbase)
break;
@@ -1938,6 +1970,9 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
unsigned int size = 8 << up->port.regshift;
switch (up->port.iotype) {
+ case UPIO_AU:
+ size = 0x100000;
+ /* fall thru */
case UPIO_MEM:
if (!up->port.mapbase)
break;
@@ -2200,10 +2235,17 @@ static void
serial8250_console_write(struct console *co, const char *s, unsigned int count)
{
struct uart_8250_port *up = &serial8250_ports[co->index];
+ unsigned long flags;
unsigned int ier;
+ int locked = 1;
touch_nmi_watchdog();
+ if (oops_in_progress) {
+ locked = spin_trylock_irqsave(&up->port.lock, flags);
+ } else
+ spin_lock_irqsave(&up->port.lock, flags);
+
/*
* First save the IER then disable the interrupts
*/
@@ -2221,8 +2263,10 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
* and restore the IER
*/
wait_for_xmitr(up, BOTH_EMPTY);
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, ier | UART_IER_THRI);
+ serial_out(up, UART_IER, ier);
+
+ if (locked)
+ spin_unlock_irqrestore(&up->port.lock, flags);
}
static int serial8250_console_setup(struct console *co, char *options)
diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c
index 8d8d7a70d03..58015fd14be 100644
--- a/drivers/serial/8250_au1x00.c
+++ b/drivers/serial/8250_au1x00.c
@@ -30,13 +30,12 @@
{ \
.iobase = _base, \
.membase = (void __iomem *)_base,\
- .mapbase = _base, \
+ .mapbase = CPHYSADDR(_base), \
.irq = _irq, \
.uartclk = 0, /* filled */ \
.regshift = 2, \
.iotype = UPIO_AU, \
- .flags = UPF_SKIP_TEST | \
- UPF_IOREMAP, \
+ .flags = UPF_SKIP_TEST \
}
static struct plat_serial8250_port au1x00_data[] = {
@@ -51,7 +50,7 @@ static struct plat_serial8250_port au1x00_data[] = {
#elif defined(CONFIG_SOC_AU1100)
PORT(UART0_ADDR, AU1100_UART0_INT),
PORT(UART1_ADDR, AU1100_UART1_INT),
- PORT(UART2_ADDR, AU1100_UART2_INT),
+ /* The internal UART2 does not exist on the AU1100 processor. */
PORT(UART3_ADDR, AU1100_UART3_INT),
#elif defined(CONFIG_SOC_AU1550)
PORT(UART0_ADDR, AU1550_UART0_INT),
diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c
index 8b4947933d9..913c71cc056 100644
--- a/drivers/serial/8250_gsc.c
+++ b/drivers/serial/8250_gsc.c
@@ -52,13 +52,14 @@ serial_init_chip(struct parisc_device *dev)
address += 0x800;
}
- memset(&port, 0, sizeof(struct uart_port));
- port.mapbase = address;
- port.irq = dev->irq;
- port.iotype = UPIO_MEM;
- port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
- port.uartclk = LASI_BASE_BAUD * 16;
- port.dev = &dev->dev;
+ memset(&port, 0, sizeof(port));
+ port.iotype = UPIO_MEM;
+ port.uartclk = LASI_BASE_BAUD * 16;
+ port.mapbase = address;
+ port.membase = ioremap_nocache(address, 16);
+ port.irq = dev->irq;
+ port.flags = UPF_BOOT_AUTOCONF;
+ port.dev = &dev->dev;
err = serial8250_register_port(&port);
if (err < 0) {
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ceb3697bf84..7d22dc0478d 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -63,6 +63,33 @@ config SERIAL_8250_CONSOLE
If unsure, say N.
+config SERIAL_8250_GSC
+ tristate
+ depends on SERIAL_8250 && GSC
+ default SERIAL_8250
+
+config SERIAL_8250_PCI
+ tristate "8250/16550 PCI device support" if EMBEDDED
+ depends on SERIAL_8250 && PCI
+ default SERIAL_8250
+ help
+ This builds standard PCI serial support. You may be able to
+ disable this feature if you only need legacy serial support.
+ Saves about 9K.
+
+config SERIAL_8250_PNP
+ tristate "8250/16550 PNP device support" if EMBEDDED
+ depends on SERIAL_8250 && PNP
+ default SERIAL_8250
+ help
+ This builds standard PNP serial support. You may be able to
+ disable this feature if you only need legacy serial support.
+
+config SERIAL_8250_HP300
+ tristate
+ depends on SERIAL_8250 && HP300
+ default SERIAL_8250
+
config SERIAL_8250_CS
tristate "8250/16550 PCMCIA device support"
depends on PCMCIA && SERIAL_8250
@@ -620,22 +647,6 @@ config SERIAL_SH_SCI_CONSOLE
depends on SERIAL_SH_SCI=y
select SERIAL_CORE_CONSOLE
-config SERIAL_AU1X00
- bool "Enable Au1x00 UART Support"
- depends on MIPS && SOC_AU1X00
- select SERIAL_CORE
- help
- If you have an Alchemy AU1X00 processor (MIPS based) and you want
- to use serial ports, say Y. Otherwise, say N.
-
-config SERIAL_AU1X00_CONSOLE
- bool "Enable Au1x00 serial console"
- depends on SERIAL_AU1X00
- select SERIAL_CORE_CONSOLE
- help
- If you have an Alchemy AU1X00 processor (MIPS based) and you want
- to use a console on a serial port, say Y. Otherwise, say N.
-
config SERIAL_CORE
tristate
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index a3a4323d9c8..0a71bf68a03 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -4,15 +4,13 @@
# $Id: Makefile,v 1.8 2002/07/21 21:32:30 rmk Exp $
#
-serial-8250-y :=
-serial-8250-$(CONFIG_PNP) += 8250_pnp.o
-serial-8250-$(CONFIG_GSC) += 8250_gsc.o
-serial-8250-$(CONFIG_PCI) += 8250_pci.o
-serial-8250-$(CONFIG_HP300) += 8250_hp300.o
-
obj-$(CONFIG_SERIAL_CORE) += serial_core.o
obj-$(CONFIG_SERIAL_21285) += 21285.o
-obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y)
+obj-$(CONFIG_SERIAL_8250) += 8250.o
+obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
+obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
+obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
+obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
@@ -41,7 +39,6 @@ obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o
obj-$(CONFIG_V850E_UART) += v850e_uart.o
obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o
-obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o
obj-$(CONFIG_SERIAL_DZ) += dz.o
obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 127d6cd5de7..1631414000a 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -51,8 +51,6 @@
#include <linux/amba/serial.h>
#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
#define UART_NR 2
@@ -65,26 +63,16 @@
#define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0)
#define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0)
-#define UART_DUMMY_RSR_RX /*256*/0
+#define UART_DUMMY_RSR_RX 256
#define UART_PORT_SIZE 64
/*
- * On the Integrator platform, the port RTS and DTR are provided by
- * bits in the following SC_CTRLS register bits:
- * RTS DTR
- * UART0 7 6
- * UART1 5 4
- */
-#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
-#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
-
-/*
* We wrap our port structure around the generic uart_port.
*/
struct uart_amba_port {
struct uart_port port;
- unsigned int dtr_mask;
- unsigned int rts_mask;
+ struct amba_device *dev;
+ struct amba_pl010_data *data;
unsigned int old_status;
};
@@ -300,20 +288,9 @@ static unsigned int pl010_get_mctrl(struct uart_port *port)
static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int ctrls = 0, ctrlc = 0;
-
- if (mctrl & TIOCM_RTS)
- ctrlc |= uap->rts_mask;
- else
- ctrls |= uap->rts_mask;
- if (mctrl & TIOCM_DTR)
- ctrlc |= uap->dtr_mask;
- else
- ctrls |= uap->dtr_mask;
-
- __raw_writel(ctrls, SC_CTRLS);
- __raw_writel(ctrlc, SC_CTRLC);
+ if (uap->data)
+ uap->data->set_mctrl(uap->dev, uap->port.membase, mctrl);
}
static void pl010_break_ctl(struct uart_port *port, int break_state)
@@ -539,38 +516,7 @@ static struct uart_ops amba_pl010_pops = {
.verify_port = pl010_verify_port,
};
-static struct uart_amba_port amba_ports[UART_NR] = {
- {
- .port = {
- .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
- .mapbase = INTEGRATOR_UART0_BASE,
- .iotype = UPIO_MEM,
- .irq = IRQ_UARTINT0,
- .uartclk = 14745600,
- .fifosize = 16,
- .ops = &amba_pl010_pops,
- .flags = UPF_BOOT_AUTOCONF,
- .line = 0,
- },
- .dtr_mask = 1 << 5,
- .rts_mask = 1 << 4,
- },
- {
- .port = {
- .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
- .mapbase = INTEGRATOR_UART1_BASE,
- .iotype = UPIO_MEM,
- .irq = IRQ_UARTINT1,
- .uartclk = 14745600,
- .fifosize = 16,
- .ops = &amba_pl010_pops,
- .flags = UPF_BOOT_AUTOCONF,
- .line = 1,
- },
- .dtr_mask = 1 << 7,
- .rts_mask = 1 << 6,
- }
-};
+static struct uart_amba_port *amba_ports[UART_NR];
#ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE
@@ -588,7 +534,7 @@ static void pl010_console_putchar(struct uart_port *port, int ch)
static void
pl010_console_write(struct console *co, const char *s, unsigned int count)
{
- struct uart_port *port = &amba_ports[co->index].port;
+ struct uart_port *port = &amba_ports[co->index]->port;
unsigned int status, old_cr;
/*
@@ -651,7 +597,7 @@ static int __init pl010_console_setup(struct console *co, char *options)
*/
if (co->index >= UART_NR)
co->index = 0;
- port = &amba_ports[co->index].port;
+ port = &amba_ports[co->index]->port;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -672,24 +618,6 @@ static struct console amba_console = {
.data = &amba_reg,
};
-static int __init amba_console_init(void)
-{
- /*
- * All port initializations are done statically
- */
- register_console(&amba_console);
- return 0;
-}
-console_initcall(amba_console_init);
-
-static int __init amba_late_console_init(void)
-{
- if (!(amba_console.flags & CON_ENABLED))
- register_console(&amba_console);
- return 0;
-}
-late_initcall(amba_late_console_init);
-
#define AMBA_CONSOLE &amba_console
#else
#define AMBA_CONSOLE NULL
@@ -707,30 +635,76 @@ static struct uart_driver amba_reg = {
static int pl010_probe(struct amba_device *dev, void *id)
{
- int i;
+ struct uart_amba_port *port;
+ void __iomem *base;
+ int i, ret;
- for (i = 0; i < UART_NR; i++) {
- if (amba_ports[i].port.mapbase != dev->res.start)
- continue;
+ for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
+ if (amba_ports[i] == NULL)
+ break;
- amba_ports[i].port.dev = &dev->dev;
- uart_add_one_port(&amba_reg, &amba_ports[i].port);
- amba_set_drvdata(dev, &amba_ports[i]);
- break;
+ if (i == ARRAY_SIZE(amba_ports)) {
+ ret = -EBUSY;
+ goto out;
}
- return 0;
+ port = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
+ if (!port) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ base = ioremap(dev->res.start, PAGE_SIZE);
+ if (!base) {
+ ret = -ENOMEM;
+ goto free;
+ }
+
+ port->port.dev = &dev->dev;
+ port->port.mapbase = dev->res.start;
+ port->port.membase = base;
+ port->port.iotype = UPIO_MEM;
+ port->port.irq = dev->irq[0];
+ port->port.uartclk = 14745600;
+ port->port.fifosize = 16;
+ port->port.ops = &amba_pl010_pops;
+ port->port.flags = UPF_BOOT_AUTOCONF;
+ port->port.line = i;
+ port->dev = dev;
+ port->data = dev->dev.platform_data;
+
+ amba_ports[i] = port;
+
+ amba_set_drvdata(dev, port);
+ ret = uart_add_one_port(&amba_reg, &port->port);
+ if (ret) {
+ amba_set_drvdata(dev, NULL);
+ amba_ports[i] = NULL;
+ iounmap(base);
+ free:
+ kfree(port);
+ }
+
+ out:
+ return ret;
}
static int pl010_remove(struct amba_device *dev)
{
- struct uart_amba_port *uap = amba_get_drvdata(dev);
-
- if (uap)
- uart_remove_one_port(&amba_reg, &uap->port);
+ struct uart_amba_port *port = amba_get_drvdata(dev);
+ int i;
amba_set_drvdata(dev, NULL);
+ uart_remove_one_port(&amba_reg, &port->port);
+
+ for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
+ if (amba_ports[i] == port)
+ amba_ports[i] = NULL;
+
+ iounmap(port->port.membase);
+ kfree(port);
+
return 0;
}
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
deleted file mode 100644
index 948880ac587..00000000000
--- a/drivers/serial/au1x00_uart.c
+++ /dev/null
@@ -1,1287 +0,0 @@
-/*
- * Driver for 8250/16550-type serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright (C) 2001 Russell King.
- *
- * This program is free software; 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.
- *
- * A note about mapbase / membase
- *
- * mapbase is the physical address of the IO port. Currently, we don't
- * support this very well, and it may well be dropped from this driver
- * in future. As such, mapbase should be NULL.
- *
- * membase is an 'ioremapped' cookie. This is compatible with the old
- * serial.c driver, and is currently the preferred form.
- */
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/delay.h>
-
-#include <asm/serial.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach-au1x00/au1000.h>
-
-#if defined(CONFIG_SERIAL_AU1X00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-#include "8250.h"
-
-/*
- * Debugging.
- */
-#if 0
-#define DEBUG_AUTOCONF(fmt...) printk(fmt)
-#else
-#define DEBUG_AUTOCONF(fmt...) do { } while (0)
-#endif
-
-#if 0
-#define DEBUG_INTR(fmt...) printk(fmt)
-#else
-#define DEBUG_INTR(fmt...) do { } while (0)
-#endif
-
-#define PASS_LIMIT 256
-
-/*
- * We default to IRQ0 for the "no irq" hack. Some
- * machine types want others as well - they're free
- * to redefine this in their header file.
- */
-#define is_real_interrupt(irq) ((irq) != 0)
-
-static struct old_serial_port old_serial_port[] = {
- { .baud_base = 0,
- .iomem_base = (u8 *)UART0_ADDR,
- .irq = AU1000_UART0_INT,
- .flags = STD_COM_FLAGS,
- .iomem_reg_shift = 2,
- }, {
- .baud_base = 0,
- .iomem_base = (u8 *)UART1_ADDR,
- .irq = AU1000_UART1_INT,
- .flags = STD_COM_FLAGS,
- .iomem_reg_shift = 2
- }, {
- .baud_base = 0,
- .iomem_base = (u8 *)UART2_ADDR,
- .irq = AU1000_UART2_INT,
- .flags = STD_COM_FLAGS,
- .iomem_reg_shift = 2
- }, {
- .baud_base = 0,
- .iomem_base = (u8 *)UART3_ADDR,
- .irq = AU1000_UART3_INT,
- .flags = STD_COM_FLAGS,
- .iomem_reg_shift = 2
- }
-};
-
-#define UART_NR ARRAY_SIZE(old_serial_port)
-
-struct uart_8250_port {
- struct uart_port port;
- struct timer_list timer; /* "no irq" timer */
- struct list_head list; /* ports on this IRQ */
- unsigned short rev;
- unsigned char acr;
- unsigned char ier;
- unsigned char lcr;
- unsigned char mcr_mask; /* mask of user bits */
- unsigned char mcr_force; /* mask of forced bits */
- unsigned char lsr_break_flag;
-
- /*
- * We provide a per-port pm hook.
- */
- void (*pm)(struct uart_port *port,
- unsigned int state, unsigned int old);
-};
-
-struct irq_info {
- spinlock_t lock;
- struct list_head *head;
-};
-
-static struct irq_info irq_lists[NR_IRQS];
-
-/*
- * Here we define the default xmit fifo size used for each type of UART.
- */
-static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
- { "unknown", 1, 0 },
- { "8250", 1, 0 },
- { "16450", 1, 0 },
- { "16550", 1, 0 },
- /* PORT_16550A */
- { "AU1X00_UART",16, UART_CLEAR_FIFO | UART_USE_FIFO },
-};
-
-static unsigned int serial_in(struct uart_8250_port *up, int offset)
-{
- return au_readl((unsigned long)up->port.membase + offset);
-}
-
-static void serial_out(struct uart_8250_port *up, int offset, int value)
-{
- au_writel(value, (unsigned long)up->port.membase + offset);
-}
-
-#define serial_inp(up, offset) serial_in(up, offset)
-#define serial_outp(up, offset, value) serial_out(up, offset, value)
-
-/*
- * This routine is called by rs_init() to initialize a specific serial
- * port. It determines what type of UART chip this serial port is
- * using: 8250, 16450, 16550, 16550A. The important question is
- * whether or not this UART is a 16550A or not, since this will
- * determine whether or not we can use its FIFO features or not.
- */
-static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
-{
- unsigned char save_lcr, save_mcr;
- unsigned long flags;
-
- if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
- return;
-
- DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%08lx): ",
- up->port.line, up->port.iobase, up->port.membase);
-
- /*
- * We really do need global IRQs disabled here - we're going to
- * be frobbing the chips IRQ enable register to see if it exists.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-// save_flags(flags); cli();
-
- save_mcr = serial_in(up, UART_MCR);
- save_lcr = serial_in(up, UART_LCR);
-
- up->port.type = PORT_16550A;
- serial_outp(up, UART_LCR, save_lcr);
-
- up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
-
- if (up->port.type == PORT_UNKNOWN)
- goto out;
-
- /*
- * Reset the UART.
- */
- serial_outp(up, UART_MCR, save_mcr);
- serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT));
- serial_outp(up, UART_FCR, 0);
- (void)serial_in(up, UART_RX);
- serial_outp(up, UART_IER, 0);
-
- out:
- spin_unlock_irqrestore(&up->port.lock, flags);
-// restore_flags(flags);
- DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
-}
-
-static void serial8250_stop_tx(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
-
- if (up->ier & UART_IER_THRI) {
- up->ier &= ~UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-static void serial8250_start_tx(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
-
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-static void serial8250_stop_rx(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
-
- up->ier &= ~UART_IER_RLSI;
- up->port.read_status_mask &= ~UART_LSR_DR;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void serial8250_enable_ms(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
-
- up->ier |= UART_IER_MSI;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void
-receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
-{
- struct tty_struct *tty = up->port.info->tty;
- unsigned char ch, flag;
- int max_count = 256;
-
- do {
- ch = serial_inp(up, UART_RX);
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
- UART_LSR_FE | UART_LSR_OE))) {
- /*
- * For statistics only
- */
- if (*status & UART_LSR_BI) {
- *status &= ~(UART_LSR_FE | UART_LSR_PE);
- up->port.icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (*status & UART_LSR_PE)
- up->port.icount.parity++;
- else if (*status & UART_LSR_FE)
- up->port.icount.frame++;
- if (*status & UART_LSR_OE)
- up->port.icount.overrun++;
-
- /*
- * Mask off conditions which should be ingored.
- */
- *status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_AU1X00_CONSOLE
- if (up->port.line == up->port.cons->index) {
- /* Recover the break flag from console xmit */
- *status |= up->lsr_break_flag;
- up->lsr_break_flag = 0;
- }
-#endif
- if (*status & UART_LSR_BI) {
- DEBUG_INTR("handling break....");
- flag = TTY_BREAK;
- } else if (*status & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (*status & UART_LSR_FE)
- flag = TTY_FRAME;
- }
- if (uart_handle_sysrq_char(&up->port, ch, regs))
- goto ignore_char;
- if ((*status & up->port.ignore_status_mask) == 0)
- tty_insert_flip_char(tty, ch, flag);
- if (*status & UART_LSR_OE)
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character.
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
- ignore_char:
- *status = serial_inp(up, UART_LSR);
- } while ((*status & UART_LSR_DR) && (max_count-- > 0));
- spin_unlock(&up->port.lock);
- tty_flip_buffer_push(tty);
- spin_lock(&up->port.lock);
-}
-
-static void transmit_chars(struct uart_8250_port *up)
-{
- struct circ_buf *xmit = &up->port.info->xmit;
- int count;
-
- if (up->port.x_char) {
- serial_outp(up, UART_TX, up->port.x_char);
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- serial8250_stop_tx(&up->port);
- return;
- }
-
- count = up->port.fifosize;
- do {
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- DEBUG_INTR("THRE...");
-
- if (uart_circ_empty(xmit))
- serial8250_stop_tx(&up->port);
-}
-
-static void check_modem_status(struct uart_8250_port *up)
-{
- int status;
-
- status = serial_in(up, UART_MSR);
-
- if ((status & UART_MSR_ANY_DELTA) == 0)
- return;
-
- if (status & UART_MSR_TERI)
- up->port.icount.rng++;
- if (status & UART_MSR_DDSR)
- up->port.icount.dsr++;
- if (status & UART_MSR_DDCD)
- uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
- if (status & UART_MSR_DCTS)
- uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
- wake_up_interruptible(&up->port.info->delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline void
-serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
-{
- unsigned int status = serial_inp(up, UART_LSR);
-
- DEBUG_INTR("status = %x...", status);
-
- if (status & UART_LSR_DR)
- receive_chars(up, &status, regs);
- check_modem_status(up);
- if (status & UART_LSR_THRE)
- transmit_chars(up);
-}
-
-/*
- * This is the serial driver's interrupt routine.
- *
- * Arjan thinks the old way was overly complex, so it got simplified.
- * Alan disagrees, saying that need the complexity to handle the weird
- * nature of ISA shared interrupts. (This is a special exception.)
- *
- * In order to handle ISA shared interrupts properly, we need to check
- * that all ports have been serviced, and therefore the ISA interrupt
- * line has been de-asserted.
- *
- * This means we need to loop through all ports. checking that they
- * don't have an interrupt pending.
- */
-static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct irq_info *i = dev_id;
- struct list_head *l, *end = NULL;
- int pass_counter = 0;
-
- DEBUG_INTR("serial8250_interrupt(%d)...", irq);
-
- spin_lock(&i->lock);
-
- l = i->head;
- do {
- struct uart_8250_port *up;
- unsigned int iir;
-
- up = list_entry(l, struct uart_8250_port, list);
-
- iir = serial_in(up, UART_IIR);
- if (!(iir & UART_IIR_NO_INT)) {
- spin_lock(&up->port.lock);
- serial8250_handle_port(up, regs);
- spin_unlock(&up->port.lock);
-
- end = NULL;
- } else if (end == NULL)
- end = l;
-
- l = l->next;
-
- if (l == i->head && pass_counter++ > PASS_LIMIT) {
- /* If we hit this, we're dead. */
- printk(KERN_ERR "serial8250: too much work for "
- "irq%d\n", irq);
- break;
- }
- } while (l != end);
-
- spin_unlock(&i->lock);
-
- DEBUG_INTR("end.\n");
- /* FIXME! Was it really ours? */
- return IRQ_HANDLED;
-}
-
-/*
- * To support ISA shared interrupts, we need to have one interrupt
- * handler that ensures that the IRQ line has been deasserted
- * before returning. Failing to do this will result in the IRQ
- * line being stuck active, and, since ISA irqs are edge triggered,
- * no more IRQs will be seen.
- */
-static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
-{
- spin_lock_irq(&i->lock);
-
- if (!list_empty(i->head)) {
- if (i->head == &up->list)
- i->head = i->head->next;
- list_del(&up->list);
- } else {
- BUG_ON(i->head != &up->list);
- i->head = NULL;
- }
-
- spin_unlock_irq(&i->lock);
-}
-
-static int serial_link_irq_chain(struct uart_8250_port *up)
-{
- struct irq_info *i = irq_lists + up->port.irq;
- int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0;
-
- spin_lock_irq(&i->lock);
-
- if (i->head) {
- list_add(&up->list, i->head);
- spin_unlock_irq(&i->lock);
-
- ret = 0;
- } else {
- INIT_LIST_HEAD(&up->list);
- i->head = &up->list;
- spin_unlock_irq(&i->lock);
-
- ret = request_irq(up->port.irq, serial8250_interrupt,
- irq_flags, "serial", i);
- if (ret < 0)
- serial_do_unlink(i, up);
- }
-
- return ret;
-}
-
-static void serial_unlink_irq_chain(struct uart_8250_port *up)
-{
- struct irq_info *i = irq_lists + up->port.irq;
-
- BUG_ON(i->head == NULL);
-
- if (list_empty(i->head))
- free_irq(up->port.irq, i);
-
- serial_do_unlink(i, up);
-}
-
-/*
- * This function is used to handle ports that do not have an
- * interrupt. This doesn't work very well for 16450's, but gives
- * barely passable results for a 16550A. (Although at the expense
- * of much CPU overhead).
- */
-static void serial8250_timeout(unsigned long data)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)data;
- unsigned int timeout;
- unsigned int iir;
-
- iir = serial_in(up, UART_IIR);
- if (!(iir & UART_IIR_NO_INT)) {
- spin_lock(&up->port.lock);
- serial8250_handle_port(up, NULL);
- spin_unlock(&up->port.lock);
- }
-
- timeout = up->port.timeout;
- timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
- mod_timer(&up->timer, jiffies + timeout);
-}
-
-static unsigned int serial8250_tx_empty(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned long flags;
- unsigned int ret;
-
- spin_lock_irqsave(&up->port.lock, flags);
- ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return ret;
-}
-
-static unsigned int serial8250_get_mctrl(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned char status;
- unsigned int ret;
-
- status = serial_in(up, UART_MSR);
-
- ret = 0;
- if (status & UART_MSR_DCD)
- ret |= TIOCM_CAR;
- if (status & UART_MSR_RI)
- ret |= TIOCM_RNG;
- if (status & UART_MSR_DSR)
- ret |= TIOCM_DSR;
- if (status & UART_MSR_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned char mcr = 0;
-
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- mcr = (mcr & up->mcr_mask) | up->mcr_force;
-
- serial_out(up, UART_MCR, mcr);
-}
-
-static void serial8250_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (break_state == -1)
- up->lcr |= UART_LCR_SBC;
- else
- up->lcr &= ~UART_LCR_SBC;
- serial_out(up, UART_LCR, up->lcr);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial8250_startup(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned long flags;
- int retval;
-
- /*
- * Clear the FIFO buffers and disable them.
- * (they will be reeanbled in set_termios())
- */
- if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) {
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
- serial_outp(up, UART_FCR, 0);
- }
-
- /*
- * Clear the interrupt registers.
- */
- (void) serial_inp(up, UART_LSR);
- (void) serial_inp(up, UART_RX);
- (void) serial_inp(up, UART_IIR);
- (void) serial_inp(up, UART_MSR);
-
- /*
- * At this point, there's no way the LSR could still be 0xff;
- * if it is, then bail out, because there's likely no UART
- * here.
- */
- if (!(up->port.flags & UPF_BUGGY_UART) &&
- (serial_inp(up, UART_LSR) == 0xff)) {
- printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
- return -ENODEV;
- }
-
- retval = serial_link_irq_chain(up);
- if (retval)
- return retval;
-
- /*
- * Now, initialize the UART
- */
- serial_outp(up, UART_LCR, UART_LCR_WLEN8);
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.flags & UPF_FOURPORT) {
- if (!is_real_interrupt(up->port.irq))
- up->port.mctrl |= TIOCM_OUT1;
- } else
- /*
- * Most PC uarts need OUT2 raised to enable interrupts.
- */
- if (is_real_interrupt(up->port.irq))
- up->port.mctrl |= TIOCM_OUT2;
-
- serial8250_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Finally, enable interrupts. Note: Modem status interrupts
- * are set via set_termios(), which will be occurring imminently
- * anyway, so we don't enable them here.
- */
- up->ier = UART_IER_RLSI | UART_IER_RDI;
- serial_outp(up, UART_IER, up->ier);
-
- if (up->port.flags & UPF_FOURPORT) {
- unsigned int icp;
- /*
- * Enable interrupts on the AST Fourport board
- */
- icp = (up->port.iobase & 0xfe0) | 0x01f;
- outb_p(0x80, icp);
- (void) inb_p(icp);
- }
-
- /*
- * And clear the interrupt registers again for luck.
- */
- (void) serial_inp(up, UART_LSR);
- (void) serial_inp(up, UART_RX);
- (void) serial_inp(up, UART_IIR);
- (void) serial_inp(up, UART_MSR);
-
- return 0;
-}
-
-static void serial8250_shutdown(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned long flags;
-
- /*
- * Disable interrupts from this port
- */
- up->ier = 0;
- serial_outp(up, UART_IER, 0);
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.flags & UPF_FOURPORT) {
- /* reset interrupts on the AST Fourport board */
- inb((up->port.iobase & 0xfe0) | 0x1f);
- up->port.mctrl |= TIOCM_OUT1;
- } else
- up->port.mctrl &= ~TIOCM_OUT2;
-
- serial8250_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Disable break condition and FIFOs
- */
- serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT);
- serial_outp(up, UART_FCR, 0);
-
- /*
- * Read data port to reset things, and then unlink from
- * the IRQ chain.
- */
- (void) serial_in(up, UART_RX);
-
- if (!is_real_interrupt(up->port.irq))
- del_timer_sync(&up->timer);
- else
- serial_unlink_irq_chain(up);
-}
-
-static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
-{
- unsigned int quot;
-
- /*
- * Handle magic divisors for baud rates above baud_base on
- * SMSC SuperIO chips.
- */
- if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
- baud == (port->uartclk/4))
- quot = 0x8001;
- else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
- baud == (port->uartclk/8))
- quot = 0x8002;
- else
- quot = uart_get_divisor(port, baud);
-
- return quot;
-}
-
-static void
-serial8250_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned char cval, fcr = 0;
- unsigned long flags;
- unsigned int baud, quot;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- cval = UART_LCR_WLEN5;
- break;
- case CS6:
- cval = UART_LCR_WLEN6;
- break;
- case CS7:
- cval = UART_LCR_WLEN7;
- break;
- default:
- case CS8:
- cval = UART_LCR_WLEN8;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- cval |= UART_LCR_STOP;
- if (termios->c_cflag & PARENB)
- cval |= UART_LCR_PARITY;
- if (!(termios->c_cflag & PARODD))
- cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
- if (termios->c_cflag & CMSPAR)
- cval |= UART_LCR_SPAR;
-#endif
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = serial8250_get_divisor(port, baud);
- quot = 0x35; /* FIXME */
-
- /*
- * Work around a bug in the Oxford Semiconductor 952 rev B
- * chip which causes it to seriously miscalculate baud rates
- * when DLL is 0.
- */
- if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 &&
- up->rev == 0x5201)
- quot ++;
-
- if (uart_config[up->port.type].flags & UART_USE_FIFO) {
- if (baud < 2400)
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_1;
- else
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_8;
- }
-
- /*
- * Ok, we're now changing the port state. Do it with
- * interrupts disabled.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (termios->c_iflag & INPCK)
- up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (termios->c_iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= UART_LSR_BI;
-
- /*
- * Characteres to ignore
- */
- up->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
- if (termios->c_iflag & IGNBRK) {
- up->port.ignore_status_mask |= UART_LSR_BI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_OE;
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- up->port.ignore_status_mask |= UART_LSR_DR;
-
- /*
- * CTS flow control flag and modem status interrupts
- */
- up->ier &= ~UART_IER_MSI;
- if (UART_ENABLE_MS(&up->port, termios->c_cflag))
- up->ier |= UART_IER_MSI;
-
- serial_out(up, UART_IER, up->ier);
- serial_outp(up, 0x28, quot & 0xffff);
- up->lcr = cval; /* Save LCR */
- if (up->port.type != PORT_16750) {
- if (fcr & UART_FCR_ENABLE_FIFO) {
- /* emulated UARTs (Lucent Venus 167x) need two steps */
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- }
- serial_outp(up, UART_FCR, fcr); /* set fcr */
- }
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial8250_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- if (state) {
- /* sleep */
- if (up->pm)
- up->pm(port, state, oldstate);
- } else {
- /* wake */
- if (up->pm)
- up->pm(port, state, oldstate);
- }
-}
-
-/*
- * Resource handling. This is complicated by the fact that resources
- * depend on the port type. Maybe we should be claiming the standard
- * 8250 ports, and then trying to get other resources as necessary?
- */
-static int
-serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res)
-{
- unsigned int size = 8 << up->port.regshift;
- int ret = 0;
-
- switch (up->port.iotype) {
- case UPIO_MEM:
- if (up->port.mapbase) {
- *res = request_mem_region(up->port.mapbase, size, "serial");
- if (!*res)
- ret = -EBUSY;
- }
- break;
-
- case UPIO_HUB6:
- case UPIO_PORT:
- *res = request_region(up->port.iobase, size, "serial");
- if (!*res)
- ret = -EBUSY;
- break;
- }
- return ret;
-}
-
-
-static void serial8250_release_port(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned long start, offset = 0, size = 0;
-
- size <<= up->port.regshift;
-
- switch (up->port.iotype) {
- case UPIO_MEM:
- if (up->port.mapbase) {
- /*
- * Unmap the area.
- */
- iounmap(up->port.membase);
- up->port.membase = NULL;
-
- start = up->port.mapbase;
-
- if (size)
- release_mem_region(start + offset, size);
- release_mem_region(start, 8 << up->port.regshift);
- }
- break;
-
- case UPIO_HUB6:
- case UPIO_PORT:
- start = up->port.iobase;
-
- if (size)
- release_region(start + offset, size);
- release_region(start + offset, 8 << up->port.regshift);
- break;
-
- default:
- break;
- }
-}
-
-static int serial8250_request_port(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- struct resource *res = NULL, *res_rsa = NULL;
- int ret = 0;
-
- ret = serial8250_request_std_resource(up, &res);
-
- /*
- * If we have a mapbase, then request that as well.
- */
- if (ret == 0 && up->port.flags & UPF_IOREMAP) {
- int size = res->end - res->start + 1;
-
- up->port.membase = ioremap(up->port.mapbase, size);
- if (!up->port.membase)
- ret = -ENOMEM;
- }
-
- if (ret < 0) {
- if (res_rsa)
- release_resource(res_rsa);
- if (res)
- release_resource(res);
- }
- return ret;
-}
-
-static void serial8250_config_port(struct uart_port *port, int flags)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- struct resource *res_std = NULL, *res_rsa = NULL;
- int probeflags = PROBE_ANY;
-
- probeflags &= ~PROBE_RSA;
-
- if (flags & UART_CONFIG_TYPE)
- autoconfig(up, probeflags);
-
- /*
- * If the port wasn't an RSA port, release the resource.
- */
- if (up->port.type != PORT_RSA && res_rsa)
- release_resource(res_rsa);
-
- if (up->port.type == PORT_UNKNOWN && res_std)
- release_resource(res_std);
-}
-
-static int
-serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- if (ser->irq >= NR_IRQS || ser->irq < 0 ||
- ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
- ser->type > PORT_MAX_8250 || ser->type == PORT_CIRRUS ||
- ser->type == PORT_STARTECH)
- return -EINVAL;
- return 0;
-}
-
-static const char *
-serial8250_type(struct uart_port *port)
-{
- int type = port->type;
-
- if (type >= ARRAY_SIZE(uart_config))
- type = 0;
- return uart_config[type].name;
-}
-
-static struct uart_ops serial8250_pops = {
- .tx_empty = serial8250_tx_empty,
- .set_mctrl = serial8250_set_mctrl,
- .get_mctrl = serial8250_get_mctrl,
- .stop_tx = serial8250_stop_tx,
- .start_tx = serial8250_start_tx,
- .stop_rx = serial8250_stop_rx,
- .enable_ms = serial8250_enable_ms,
- .break_ctl = serial8250_break_ctl,
- .startup = serial8250_startup,
- .shutdown = serial8250_shutdown,
- .set_termios = serial8250_set_termios,
- .pm = serial8250_pm,
- .type = serial8250_type,
- .release_port = serial8250_release_port,
- .request_port = serial8250_request_port,
- .config_port = serial8250_config_port,
- .verify_port = serial8250_verify_port,
-};
-
-static struct uart_8250_port serial8250_ports[UART_NR];
-
-static void __init serial8250_isa_init_ports(void)
-{
- struct uart_8250_port *up;
- static int first = 1;
- int i;
-
- if (!first)
- return;
- first = 0;
-
- for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port);
- i++, up++) {
- up->port.iobase = old_serial_port[i].port;
- up->port.irq = old_serial_port[i].irq;
- up->port.uartclk = get_au1x00_uart_baud_base();
- up->port.flags = old_serial_port[i].flags;
- up->port.hub6 = old_serial_port[i].hub6;
- up->port.membase = old_serial_port[i].iomem_base;
- up->port.iotype = old_serial_port[i].io_type;
- up->port.regshift = old_serial_port[i].iomem_reg_shift;
- up->port.ops = &serial8250_pops;
- }
-}
-
-static void __init serial8250_register_ports(struct uart_driver *drv)
-{
- int i;
-
- serial8250_isa_init_ports();
-
- for (i = 0; i < UART_NR; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
-
- up->port.line = i;
- up->port.ops = &serial8250_pops;
- init_timer(&up->timer);
- up->timer.function = serial8250_timeout;
-
- /*
- * ALPHA_KLUDGE_MCR needs to be killed.
- */
- up->mcr_mask = ~ALPHA_KLUDGE_MCR;
- up->mcr_force = ALPHA_KLUDGE_MCR;
-
- uart_add_one_port(drv, &up->port);
- }
-}
-
-#ifdef CONFIG_SERIAL_AU1X00_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- * Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_8250_port *up)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- do {
- status = serial_in(up, UART_LSR);
-
- if (status & UART_LSR_BI)
- up->lsr_break_flag = UART_LSR_BI;
-
- if (--tmout == 0)
- break;
- udelay(1);
- } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- tmout = 1000000;
- while (--tmout &&
- ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
- udelay(1);
- }
-}
-
-static void au1x00_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
-
- wait_for_xmitr(up);
- serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- */
-static void
-serial8250_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_8250_port *up = &serial8250_ports[co->index];
- unsigned int ier;
-
- /*
- * First save the UER then disable the interrupts
- */
- ier = serial_in(up, UART_IER);
- serial_out(up, UART_IER, 0);
-
- uart_console_write(&up->port, s, count, au1x00_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up);
- serial_out(up, UART_IER, ier);
-}
-
-static int __init serial8250_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= UART_NR)
- co->index = 0;
- port = &serial8250_ports[co->index].port;
-
- /*
- * Temporary fix.
- */
- spin_lock_init(&port->lock);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-extern struct uart_driver serial8250_reg;
-static struct console serial8250_console = {
- .name = "ttyS",
- .write = serial8250_console_write,
- .device = uart_console_device,
- .setup = serial8250_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &serial8250_reg,
-};
-
-static int __init serial8250_console_init(void)
-{
- serial8250_isa_init_ports();
- register_console(&serial8250_console);
- return 0;
-}
-console_initcall(serial8250_console_init);
-
-#define SERIAL8250_CONSOLE &serial8250_console
-#else
-#define SERIAL8250_CONSOLE NULL
-#endif
-
-static struct uart_driver serial8250_reg = {
- .owner = THIS_MODULE,
- .driver_name = "serial",
- .devfs_name = "tts/",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .nr = UART_NR,
- .cons = SERIAL8250_CONSOLE,
-};
-
-int __init early_serial_setup(struct uart_port *port)
-{
- serial8250_isa_init_ports();
- serial8250_ports[port->line].port = *port;
- serial8250_ports[port->line].port.ops = &serial8250_pops;
- return 0;
-}
-
-/**
- * serial8250_suspend_port - suspend one serial port
- * @line: serial line number
- * @level: the level of port suspension, as per uart_suspend_port
- *
- * Suspend one serial port.
- */
-void serial8250_suspend_port(int line)
-{
- uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port);
-}
-
-/**
- * serial8250_resume_port - resume one serial port
- * @line: serial line number
- * @level: the level of port resumption, as per uart_resume_port
- *
- * Resume one serial port.
- */
-void serial8250_resume_port(int line)
-{
- uart_resume_port(&serial8250_reg, &serial8250_ports[line].port);
-}
-
-static int __init serial8250_init(void)
-{
- int ret, i;
-
- printk(KERN_INFO "Serial: Au1x00 driver\n");
-
- for (i = 0; i < NR_IRQS; i++)
- spin_lock_init(&irq_lists[i].lock);
-
- ret = uart_register_driver(&serial8250_reg);
- if (ret >= 0)
- serial8250_register_ports(&serial8250_reg);
-
- return ret;
-}
-
-static void __exit serial8250_exit(void)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++)
- uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port);
-
- uart_unregister_driver(&serial8250_reg);
-}
-
-module_init(serial8250_init);
-module_exit(serial8250_exit);
-
-EXPORT_SYMBOL(serial8250_suspend_port);
-EXPORT_SYMBOL(serial8250_resume_port);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Au1x00 serial driver\n");
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
index 73c8a088c16..3b35cb77953 100644
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -5,11 +5,20 @@
*
* Copyright (C) 2004 Freescale Semiconductor, Inc.
*
+ * 2006 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
*/
#ifndef CPM_UART_H
#define CPM_UART_H
#include <linux/config.h>
+#include <linux/platform_device.h>
+#include <linux/fs_uart_pd.h>
#if defined(CONFIG_CPM2)
#include "cpm_uart_cpm2.h"
@@ -26,14 +35,14 @@
#define FLAG_SMC 0x00000002
#define FLAG_CONSOLE 0x00000001
-#define UART_SMC1 0
-#define UART_SMC2 1
-#define UART_SCC1 2
-#define UART_SCC2 3
-#define UART_SCC3 4
-#define UART_SCC4 5
+#define UART_SMC1 fsid_smc1_uart
+#define UART_SMC2 fsid_smc2_uart
+#define UART_SCC1 fsid_scc1_uart
+#define UART_SCC2 fsid_scc2_uart
+#define UART_SCC3 fsid_scc3_uart
+#define UART_SCC4 fsid_scc4_uart
-#define UART_NR 6
+#define UART_NR fs_uart_nr
#define RX_NUM_FIFO 4
#define RX_BUF_SIZE 32
@@ -64,6 +73,7 @@ struct uart_cpm_port {
uint dp_addr;
void *mem_addr;
dma_addr_t dma_addr;
+ u32 mem_size;
/* helpers */
int baud;
int bits;
@@ -90,4 +100,38 @@ void scc2_lineif(struct uart_cpm_port *pinfo);
void scc3_lineif(struct uart_cpm_port *pinfo);
void scc4_lineif(struct uart_cpm_port *pinfo);
+/*
+ virtual to phys transtalion
+*/
+static inline unsigned long cpu2cpm_addr(void* addr, struct uart_cpm_port *pinfo)
+{
+ int offset;
+ u32 val = (u32)addr;
+ /* sane check */
+ if (likely((val >= (u32)pinfo->mem_addr)) &&
+ (val<((u32)pinfo->mem_addr + pinfo->mem_size))) {
+ offset = val - (u32)pinfo->mem_addr;
+ return pinfo->dma_addr+offset;
+ }
+ /* something nasty happened */
+ BUG();
+ return 0;
+}
+
+static inline void *cpm2cpu_addr(unsigned long addr, struct uart_cpm_port *pinfo)
+{
+ int offset;
+ u32 val = addr;
+ /* sane check */
+ if (likely((val >= pinfo->dma_addr) &&
+ (val<(pinfo->dma_addr + pinfo->mem_size)))) {
+ offset = val - (u32)pinfo->dma_addr;
+ return (void*)(pinfo->mem_addr+offset);
+ }
+ /* something nasty happened */
+ BUG();
+ return 0;
+}
+
+
#endif /* CPM_UART_H */
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index b7bf4c698a4..5cba59ad7dc 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -12,7 +12,8 @@
*
* Copyright (C) 2004 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A.
- * (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com>
+ * (C) 2005-2006 MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.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
@@ -41,6 +42,7 @@
#include <linux/device.h>
#include <linux/bootmem.h>
#include <linux/dma-mapping.h>
+#include <linux/fs_uart_pd.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -60,7 +62,7 @@
/* Track which ports are configured as uarts */
int cpm_uart_port_map[UART_NR];
/* How many ports did we config as uarts */
-int cpm_uart_nr;
+int cpm_uart_nr = 0;
/**************************************************************/
@@ -71,18 +73,51 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
/**************************************************************/
-static inline unsigned long cpu2cpm_addr(void *addr)
+
+/* Place-holder for board-specific stuff */
+struct platform_device* __attribute__ ((weak)) __init
+early_uart_get_pdev(int index)
+{
+ return NULL;
+}
+
+
+static void cpm_uart_count(void)
{
- if ((unsigned long)addr >= CPM_ADDR)
- return (unsigned long)addr;
- return virt_to_bus(addr);
+ cpm_uart_nr = 0;
+#ifdef CONFIG_SERIAL_CPM_SMC1
+ cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
+#endif
+#ifdef CONFIG_SERIAL_CPM_SMC2
+ cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
+#endif
+#ifdef CONFIG_SERIAL_CPM_SCC1
+ cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
+#endif
+#ifdef CONFIG_SERIAL_CPM_SCC2
+ cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
+#endif
+#ifdef CONFIG_SERIAL_CPM_SCC3
+ cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
+#endif
+#ifdef CONFIG_SERIAL_CPM_SCC4
+ cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
+#endif
}
-static inline void *cpm2cpu_addr(unsigned long addr)
+/* Get UART number by its id */
+static int cpm_uart_id2nr(int id)
{
- if (addr >= CPM_ADDR)
- return (void *)addr;
- return bus_to_virt(addr);
+ int i;
+ if (id < UART_NR) {
+ for (i=0; i<UART_NR; i++) {
+ if (cpm_uart_port_map[i] == id)
+ return i;
+ }
+ }
+
+ /* not found or invalid argument */
+ return -1;
}
/*
@@ -258,7 +293,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
}
/* get pointer */
- cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
/* loop through the buffer */
while (i-- > 0) {
@@ -438,7 +473,11 @@ static void cpm_uart_shutdown(struct uart_port *port)
}
/* Shut them really down and reinit buffer descriptors */
- cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+ if (IS_SMC(pinfo))
+ cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+ else
+ cpm_line_cr_cmd(line, CPM_CR_GRA_STOP_TX);
+
cpm_uart_initbd(pinfo);
}
}
@@ -601,7 +640,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
/* Pick next descriptor and fill from buffer */
bdp = pinfo->tx_cur;
- p = cpm2cpu_addr(bdp->cbd_bufaddr);
+ p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
*p++ = port->x_char;
bdp->cbd_datlen = 1;
@@ -628,7 +667,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
count = 0;
- p = cpm2cpu_addr(bdp->cbd_bufaddr);
+ p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
while (count < pinfo->tx_fifosize) {
*p++ = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -677,12 +716,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
mem_addr = pinfo->mem_addr;
bdp = pinfo->rx_cur = pinfo->rx_bd_base;
for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
- bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
mem_addr += pinfo->rx_fifosize;
}
- bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
/* Set the physical address of the host memory
@@ -692,12 +731,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
bdp = pinfo->tx_cur = pinfo->tx_bd_base;
for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
- bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
bdp->cbd_sc = BD_SC_INTRPT;
mem_addr += pinfo->tx_fifosize;
}
- bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
}
@@ -829,14 +868,6 @@ static int cpm_uart_request_port(struct uart_port *port)
if (pinfo->flags & FLAG_CONSOLE)
return 0;
- /*
- * Setup any port IO, connect any baud rate generators,
- * etc. This is expected to be handled by board
- * dependant code
- */
- if (pinfo->set_lineif)
- pinfo->set_lineif(pinfo);
-
if (IS_SMC(pinfo)) {
pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
@@ -988,6 +1019,58 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
},
};
+int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
+{
+ struct resource *r;
+ struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
+ int idx = pdata->fs_no; /* It is UART_SMCx or UART_SCCx index */
+ struct uart_cpm_port *pinfo;
+ int line;
+ u32 mem, pram;
+
+ line = cpm_uart_id2nr(idx);
+ if(line < 0) {
+ printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx);
+ return -1;
+ }
+
+ pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx];
+
+ pinfo->brg = pdata->brg;
+
+ if (!is_con) {
+ pinfo->port.line = line;
+ pinfo->port.flags = UPF_BOOT_AUTOCONF;
+ }
+
+ if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs")))
+ return -EINVAL;
+ mem = r->start;
+
+ if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram")))
+ return -EINVAL;
+ pram = r->start;
+
+ if(idx > fsid_smc2_uart) {
+ pinfo->sccp = (scc_t *)mem;
+ pinfo->sccup = (scc_uart_t *)pram;
+ } else {
+ pinfo->smcp = (smc_t *)mem;
+ pinfo->smcup = (smc_uart_t *)pram;
+ }
+ pinfo->tx_nrfifos = pdata->tx_num_fifo;
+ pinfo->tx_fifosize = pdata->tx_buf_size;
+
+ pinfo->rx_nrfifos = pdata->rx_num_fifo;
+ pinfo->rx_fifosize = pdata->rx_buf_size;
+
+ pinfo->port.uartclk = pdata->uart_clk;
+ pinfo->port.mapbase = (unsigned long)mem;
+ pinfo->port.irq = platform_get_irq(pdev, 0);
+
+ return 0;
+}
+
#ifdef CONFIG_SERIAL_CPM_CONSOLE
/*
* Print a string to the serial port trying not to disturb
@@ -1027,7 +1110,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
* If the buffer address is in the CPM DPRAM, don't
* convert it.
*/
- cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
*cp = *s;
@@ -1044,7 +1127,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
while ((bdp->cbd_sc & BD_SC_READY) != 0)
;
- cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
*cp = 13;
bdp->cbd_datlen = 1;
@@ -1067,9 +1150,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
pinfo->tx_cur = (volatile cbd_t *) bdp;
}
-/*
- * Setup console. Be careful is called early !
- */
+
static int __init cpm_uart_console_setup(struct console *co, char *options)
{
struct uart_port *port;
@@ -1080,9 +1161,29 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
int flow = 'n';
int ret;
+ struct fs_uart_platform_info *pdata;
+ struct platform_device* pdev = early_uart_get_pdev(co->index);
+
+ if (!pdev) {
+ pr_info("cpm_uart: console: compat mode\n");
+ /* compatibility - will be cleaned up */
+ cpm_uart_init_portdesc();
+ }
+
port =
(struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
pinfo = (struct uart_cpm_port *)port;
+ if (!pdev) {
+ if (pinfo->set_lineif)
+ pinfo->set_lineif(pinfo);
+ } else {
+ pdata = pdev->dev.platform_data;
+ if (pdata)
+ if (pdata->init_ioports)
+ pdata->init_ioports();
+
+ cpm_uart_drv_get_platform_data(pdev, 1);
+ }
pinfo->flags |= FLAG_CONSOLE;
@@ -1097,14 +1198,6 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
baud = 9600;
}
- /*
- * Setup any port IO, connect any baud rate generators,
- * etc. This is expected to be handled by board
- * dependant code
- */
- if (pinfo->set_lineif)
- pinfo->set_lineif(pinfo);
-
if (IS_SMC(pinfo)) {
pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
@@ -1143,11 +1236,8 @@ static struct console cpm_scc_uart_console = {
int __init cpm_uart_console_init(void)
{
- int ret = cpm_uart_init_portdesc();
-
- if (!ret)
- register_console(&cpm_scc_uart_console);
- return ret;
+ register_console(&cpm_scc_uart_console);
+ return 0;
}
console_initcall(cpm_uart_console_init);
@@ -1165,44 +1255,129 @@ static struct uart_driver cpm_reg = {
.minor = SERIAL_CPM_MINOR,
.cons = CPM_UART_CONSOLE,
};
-
-static int __init cpm_uart_init(void)
+static int cpm_uart_drv_probe(struct device *dev)
{
- int ret, i;
-
- printk(KERN_INFO "Serial: CPM driver $Revision: 0.01 $\n");
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fs_uart_platform_info *pdata;
+ int ret = -ENODEV;
-#ifndef CONFIG_SERIAL_CPM_CONSOLE
- ret = cpm_uart_init_portdesc();
- if (ret)
+ if(!pdev) {
+ printk(KERN_ERR"CPM UART: platform data missing!\n");
return ret;
-#endif
+ }
- cpm_reg.nr = cpm_uart_nr;
- ret = uart_register_driver(&cpm_reg);
+ pdata = pdev->dev.platform_data;
+ pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", cpm_uart_id2nr(pdata->fs_no));
- if (ret)
+ if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))
return ret;
- for (i = 0; i < cpm_uart_nr; i++) {
- int con = cpm_uart_port_map[i];
- cpm_uart_ports[con].port.line = i;
- cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF;
- uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port);
- }
+ if (pdata->init_ioports)
+ pdata->init_ioports();
- return ret;
+ ret = uart_add_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
+
+ return ret;
}
-static void __exit cpm_uart_exit(void)
+static int cpm_uart_drv_remove(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
+
+ pr_debug("cpm_uart_drv_remove: Removing CPM UART %d\n",
+ cpm_uart_id2nr(pdata->fs_no));
+
+ uart_remove_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
+ return 0;
+}
+
+static struct device_driver cpm_smc_uart_driver = {
+ .name = "fsl-cpm-smc:uart",
+ .bus = &platform_bus_type,
+ .probe = cpm_uart_drv_probe,
+ .remove = cpm_uart_drv_remove,
+};
+
+static struct device_driver cpm_scc_uart_driver = {
+ .name = "fsl-cpm-scc:uart",
+ .bus = &platform_bus_type,
+ .probe = cpm_uart_drv_probe,
+ .remove = cpm_uart_drv_remove,
+};
+
+/*
+ This is supposed to match uart devices on platform bus,
+ */
+static int match_is_uart (struct device* dev, void* data)
{
+ struct platform_device* pdev = container_of(dev, struct platform_device, dev);
+ int ret = 0;
+ /* this was setfunc as uart */
+ if(strstr(pdev->name,":uart")) {
+ ret = 1;
+ }
+ return ret;
+}
+
+
+static int cpm_uart_init(void) {
+
+ int ret;
int i;
+ struct device *dev;
+ printk(KERN_INFO "Serial: CPM driver $Revision: 0.02 $\n");
+
+ /* lookup the bus for uart devices */
+ dev = bus_find_device(&platform_bus_type, NULL, 0, match_is_uart);
+
+ /* There are devices on the bus - all should be OK */
+ if (dev) {
+ cpm_uart_count();
+ cpm_reg.nr = cpm_uart_nr;
+
+ if (!(ret = uart_register_driver(&cpm_reg))) {
+ if ((ret = driver_register(&cpm_smc_uart_driver))) {
+ uart_unregister_driver(&cpm_reg);
+ return ret;
+ }
+ if ((ret = driver_register(&cpm_scc_uart_driver))) {
+ driver_unregister(&cpm_scc_uart_driver);
+ uart_unregister_driver(&cpm_reg);
+ }
+ }
+ } else {
+ /* No capable platform devices found - falling back to legacy mode */
+ pr_info("cpm_uart: WARNING: no UART devices found on platform bus!\n");
+ pr_info(
+ "cpm_uart: the driver will guess configuration, but this mode is no longer supported.\n");
+#ifndef CONFIG_SERIAL_CPM_CONSOLE
+ ret = cpm_uart_init_portdesc();
+ if (ret)
+ return ret;
+#endif
+
+ cpm_reg.nr = cpm_uart_nr;
+ ret = uart_register_driver(&cpm_reg);
+
+ if (ret)
+ return ret;
+
+ for (i = 0; i < cpm_uart_nr; i++) {
+ int con = cpm_uart_port_map[i];
+ cpm_uart_ports[con].port.line = i;
+ cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF;
+ uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port);
+ }
- for (i = 0; i < cpm_uart_nr; i++) {
- int con = cpm_uart_port_map[i];
- uart_remove_one_port(&cpm_reg, &cpm_uart_ports[con].port);
}
+ return ret;
+}
+static void __exit cpm_uart_exit(void)
+{
+ driver_unregister(&cpm_scc_uart_driver);
+ driver_unregister(&cpm_smc_uart_driver);
uart_unregister_driver(&cpm_reg);
}
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index d789ee55cbb..17406a05ce1 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -8,6 +8,8 @@
*
* Copyright (C) 2004 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A.
+ * (C) 2006 MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.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
@@ -81,58 +83,11 @@ void cpm_line_cr_cmd(int line, int cmd)
void smc1_lineif(struct uart_cpm_port *pinfo)
{
- volatile cpm8xx_t *cp = cpmp;
-
- (void)cp; /* fix warning */
-#if defined (CONFIG_MPC885ADS)
- /* Enable SMC1 transceivers */
- {
- cp->cp_pepar |= 0x000000c0;
- cp->cp_pedir &= ~0x000000c0;
- cp->cp_peso &= ~0x00000040;
- cp->cp_peso |= 0x00000080;
- }
-#elif defined (CONFIG_MPC86XADS)
- unsigned int iobits = 0x000000c0;
-
- if (!pinfo->is_portb) {
- cp->cp_pbpar |= iobits;
- cp->cp_pbdir &= ~iobits;
- cp->cp_pbodr &= ~iobits;
- } else {
- ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
- ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
- ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
- }
-#endif
pinfo->brg = 1;
}
void smc2_lineif(struct uart_cpm_port *pinfo)
{
- volatile cpm8xx_t *cp = cpmp;
-
- (void)cp; /* fix warning */
-#if defined (CONFIG_MPC885ADS)
- cp->cp_pepar |= 0x00000c00;
- cp->cp_pedir &= ~0x00000c00;
- cp->cp_peso &= ~0x00000400;
- cp->cp_peso |= 0x00000800;
-#elif defined (CONFIG_MPC86XADS)
- unsigned int iobits = 0x00000c00;
-
- if (!pinfo->is_portb) {
- cp->cp_pbpar |= iobits;
- cp->cp_pbdir &= ~iobits;
- cp->cp_pbodr &= ~iobits;
- } else {
- ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
- ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
- ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
- }
-
-#endif
-
pinfo->brg = 2;
}
@@ -191,7 +146,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
/* was hostalloc but changed cause it blows away the */
/* large tlb mapping when pinning the kernel area */
mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
- dma_addr = 0;
+ dma_addr = (u32)mem_addr;
} else
mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
GFP_KERNEL);
@@ -204,8 +159,9 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
}
pinfo->dp_addr = dp_offset;
- pinfo->mem_addr = mem_addr;
- pinfo->dma_addr = dma_addr;
+ pinfo->mem_addr = mem_addr; /* virtual address*/
+ pinfo->dma_addr = dma_addr; /* physical address*/
+ pinfo->mem_size = memsz;
pinfo->rx_buf = mem_addr;
pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index fd9e53ed3fe..cdba128250a 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -8,6 +8,8 @@
*
* Copyright (C) 2004 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A.
+ * (C) 2006 MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.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
@@ -142,14 +144,6 @@ void scc2_lineif(struct uart_cpm_port *pinfo)
* be supported in a sane fashion.
*/
#ifndef CONFIG_STX_GP3
-#ifdef CONFIG_MPC8560_ADS
- volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
- io->iop_ppard |= 0x00000018;
- io->iop_psord &= ~0x00000008; /* Rx */
- io->iop_psord &= ~0x00000010; /* Tx */
- io->iop_pdird &= ~0x00000008; /* Rx */
- io->iop_pdird |= 0x00000010; /* Tx */
-#else
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
io->iop_pparb |= 0x008b0000;
io->iop_pdirb |= 0x00880000;
@@ -157,7 +151,6 @@ void scc2_lineif(struct uart_cpm_port *pinfo)
io->iop_pdirb &= ~0x00030000;
io->iop_psorb &= ~0x00030000;
#endif
-#endif
cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff;
cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;
pinfo->brg = 2;
@@ -218,8 +211,10 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
- if (is_con)
+ if (is_con) {
mem_addr = alloc_bootmem(memsz);
+ dma_addr = virt_to_bus(mem_addr);
+ }
else
mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
GFP_KERNEL);
@@ -234,6 +229,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
pinfo->dp_addr = dp_offset;
pinfo->mem_addr = mem_addr;
pinfo->dma_addr = dma_addr;
+ pinfo->mem_size = memsz;
pinfo->rx_buf = mem_addr;
pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index c3b7a6673e9..d202eb4f384 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -45,6 +45,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware.h>
+#include <asm/arch/imx-uart.h>
/* We've been assigned a range on the "Low-density serial ports" major */
#define SERIAL_IMX_MAJOR 204
@@ -73,7 +74,8 @@ struct imx_port {
struct uart_port port;
struct timer_list timer;
unsigned int old_status;
- int txirq,rxirq,rtsirq;
+ int txirq,rxirq,rtsirq;
+ int have_rtscts:1;
};
/*
@@ -491,8 +493,12 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
ucr2 = UCR2_SRST | UCR2_IRTS;
if (termios->c_cflag & CRTSCTS) {
- ucr2 &= ~UCR2_IRTS;
- ucr2 |= UCR2_CTSC;
+ if( sport->have_rtscts ) {
+ ucr2 &= ~UCR2_IRTS;
+ ucr2 |= UCR2_CTSC;
+ } else {
+ termios->c_cflag &= ~CRTSCTS;
+ }
}
if (termios->c_cflag & CSTOPB)
@@ -719,27 +725,6 @@ static void __init imx_init_ports(void)
imx_ports[i].timer.function = imx_timeout;
imx_ports[i].timer.data = (unsigned long)&imx_ports[i];
}
-
- imx_gpio_mode(PC9_PF_UART1_CTS);
- imx_gpio_mode(PC10_PF_UART1_RTS);
- imx_gpio_mode(PC11_PF_UART1_TXD);
- imx_gpio_mode(PC12_PF_UART1_RXD);
- imx_gpio_mode(PB28_PF_UART2_CTS);
- imx_gpio_mode(PB29_PF_UART2_RTS);
-
- imx_gpio_mode(PB30_PF_UART2_TXD);
- imx_gpio_mode(PB31_PF_UART2_RXD);
-
-#if 0 /* We don't need these, on the mx1 the _modem_ side of the uart
- * is implemented.
- */
- imx_gpio_mode(PD7_AF_UART2_DTR);
- imx_gpio_mode(PD8_AF_UART2_DCD);
- imx_gpio_mode(PD9_AF_UART2_RI);
- imx_gpio_mode(PD10_AF_UART2_DSR);
-#endif
-
-
}
#ifdef CONFIG_SERIAL_IMX_CONSOLE
@@ -932,7 +917,14 @@ static int serial_imx_resume(struct platform_device *dev)
static int serial_imx_probe(struct platform_device *dev)
{
+ struct imxuart_platform_data *pdata;
+
imx_ports[dev->id].port.dev = &dev->dev;
+
+ pdata = (struct imxuart_platform_data *)dev->dev.platform_data;
+ if(pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
+ imx_ports[dev->id].have_rtscts = 1;
+
uart_add_one_port(&imx_reg, &imx_ports[dev->id].port);
platform_set_drvdata(dev, &imx_ports[dev->id]);
return 0;
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
index dfc1e86d3aa..043f50b1d10 100644
--- a/drivers/serial/jsm/jsm.h
+++ b/drivers/serial/jsm/jsm.h
@@ -20,7 +20,7 @@
*
* Contact Information:
* Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com>
+ * Wendy Xiong <wendyx@us.ibm.com>
*
***********************************************************************/
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index b1b66e71d28..b3e1f71be4d 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -20,7 +20,7 @@
*
* Contact Information:
* Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com>
+ * Wendy Xiong <wendyx@us.ibm.com>
*
*
***********************************************************************/
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
index 87e4e2cf8ce..a5fc589d6ef 100644
--- a/drivers/serial/jsm/jsm_neo.c
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -20,7 +20,7 @@
*
* Contact Information:
* Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com>
+ * Wendy Xiong <wendyx@us.ibm.com>
*
***********************************************************************/
#include <linux/delay.h> /* For udelay */
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index 4d48b625cd3..7d823705193 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -142,12 +142,14 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch)
{
unsigned long lock_flags;
struct jsm_channel *channel = (struct jsm_channel *)port;
+ struct termios *termios;
spin_lock_irqsave(&port->lock, lock_flags);
- if (ch == port->info->tty->termios->c_cc[VSTART])
+ termios = port->info->tty->termios;
+ if (ch == termios->c_cc[VSTART])
channel->ch_bd->bd_ops->send_start_character(channel);
- if (ch == port->info->tty->termios->c_cc[VSTOP])
+ if (ch == termios->c_cc[VSTOP])
channel->ch_bd->bd_ops->send_stop_character(channel);
spin_unlock_irqrestore(&port->lock, lock_flags);
}
@@ -178,6 +180,7 @@ static int jsm_tty_open(struct uart_port *port)
struct jsm_board *brd;
int rc = 0;
struct jsm_channel *channel = (struct jsm_channel *)port;
+ struct termios *termios;
/* Get board pointer from our array of majors we have allocated */
brd = channel->ch_bd;
@@ -239,12 +242,13 @@ static int jsm_tty_open(struct uart_port *port)
channel->ch_cached_lsr = 0;
channel->ch_stops_sent = 0;
- channel->ch_c_cflag = port->info->tty->termios->c_cflag;
- channel->ch_c_iflag = port->info->tty->termios->c_iflag;
- channel->ch_c_oflag = port->info->tty->termios->c_oflag;
- channel->ch_c_lflag = port->info->tty->termios->c_lflag;
- channel->ch_startc = port->info->tty->termios->c_cc[VSTART];
- channel->ch_stopc = port->info->tty->termios->c_cc[VSTOP];
+ termios = port->info->tty->termios;
+ channel->ch_c_cflag = termios->c_cflag;
+ channel->ch_c_iflag = termios->c_iflag;
+ channel->ch_c_oflag = termios->c_oflag;
+ channel->ch_c_lflag = termios->c_lflag;
+ channel->ch_startc = termios->c_cc[VSTART];
+ channel->ch_stopc = termios->c_cc[VSTOP];
/* Tell UART to init itself */
brd->bd_ops->uart_init(channel);
@@ -784,6 +788,7 @@ static void jsm_carrier(struct jsm_channel *ch)
void jsm_check_queue_flow_control(struct jsm_channel *ch)
{
+ struct board_ops *bd_ops = ch->ch_bd->bd_ops;
int qleft = 0;
/* Store how much space we have left in the queue */
@@ -809,7 +814,7 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
/* HWFLOW */
if (ch->ch_c_cflag & CRTSCTS) {
if(!(ch->ch_flags & CH_RECEIVER_OFF)) {
- ch->ch_bd->bd_ops->disable_receiver(ch);
+ bd_ops->disable_receiver(ch);
ch->ch_flags |= (CH_RECEIVER_OFF);
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
"Internal queue hit hilevel mark (%d)! Turning off interrupts.\n",
@@ -819,7 +824,7 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
/* SWFLOW */
else if (ch->ch_c_iflag & IXOFF) {
if (ch->ch_stops_sent <= MAX_STOPS_SENT) {
- ch->ch_bd->bd_ops->send_stop_character(ch);
+ bd_ops->send_stop_character(ch);
ch->ch_stops_sent++;
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
"Sending stop char! Times sent: %x\n", ch->ch_stops_sent);
@@ -846,7 +851,7 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
/* HWFLOW */
if (ch->ch_c_cflag & CRTSCTS) {
if (ch->ch_flags & CH_RECEIVER_OFF) {
- ch->ch_bd->bd_ops->enable_receiver(ch);
+ bd_ops->enable_receiver(ch);
ch->ch_flags &= ~(CH_RECEIVER_OFF);
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
"Internal queue hit lowlevel mark (%d)! Turning on interrupts.\n",
@@ -856,7 +861,7 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
/* SWFLOW */
else if (ch->ch_c_iflag & IXOFF && ch->ch_stops_sent) {
ch->ch_stops_sent = 0;
- ch->ch_bd->bd_ops->send_start_character(ch);
+ bd_ops->send_start_character(ch);
jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "Sending start char!\n");
}
}
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index e9c10c0a30f..321a40f33b5 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -1057,7 +1057,6 @@ static void m32r_sio_console_write(struct console *co, const char *s,
{
struct uart_sio_port *up = &m32r_sio_ports[co->index];
unsigned int ier;
- int i;
/*
* First save the UER then disable the interrupts
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index 868eaf4a1a6..64c0e89124c 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -51,7 +51,7 @@
#define MUX_BREAK(status) ((status & 0xF000) == 0x2000)
#define MUX_NR 256
-static unsigned int port_cnt = 0;
+static unsigned int port_cnt __read_mostly;
static struct uart_port mux_ports[MUX_NR];
static struct uart_driver mux_driver = {
@@ -461,7 +461,7 @@ static int __init mux_probe(struct parisc_device *dev)
port->iobase = 0;
port->mapbase = dev->hpa.start + MUX_OFFSET +
(i * MUX_LINE_OFFSET);
- port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET);
+ port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET);
port->iotype = UPIO_MEM;
port->type = PORT_MUX;
port->irq = NO_IRQ;
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index fcd7744c425..17839e753e4 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1500,20 +1500,18 @@ uart_block_til_ready(struct file *filp, struct uart_state *state)
static struct uart_state *uart_get(struct uart_driver *drv, int line)
{
struct uart_state *state;
+ int ret = 0;
- mutex_lock(&port_mutex);
state = drv->state + line;
if (mutex_lock_interruptible(&state->mutex)) {
- state = ERR_PTR(-ERESTARTSYS);
- goto out;
+ ret = -ERESTARTSYS;
+ goto err;
}
state->count++;
- if (!state->port) {
- state->count--;
- mutex_unlock(&state->mutex);
- state = ERR_PTR(-ENXIO);
- goto out;
+ if (!state->port || state->port->flags & UPF_DEAD) {
+ ret = -ENXIO;
+ goto err_unlock;
}
if (!state->info) {
@@ -1531,15 +1529,17 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
tasklet_init(&state->info->tlet, uart_tasklet_action,
(unsigned long)state);
} else {
- state->count--;
- mutex_unlock(&state->mutex);
- state = ERR_PTR(-ENOMEM);
+ ret = -ENOMEM;
+ goto err_unlock;
}
}
-
- out:
- mutex_unlock(&port_mutex);
return state;
+
+ err_unlock:
+ state->count--;
+ mutex_unlock(&state->mutex);
+ err:
+ return ERR_PTR(ret);
}
/*
@@ -1907,9 +1907,12 @@ uart_set_options(struct uart_port *port, struct console *co,
static void uart_change_pm(struct uart_state *state, int pm_state)
{
struct uart_port *port = state->port;
- if (port->ops->pm)
- port->ops->pm(port, pm_state, state->pm_state);
- state->pm_state = pm_state;
+
+ if (state->pm_state != pm_state) {
+ if (port->ops->pm)
+ port->ops->pm(port, pm_state, state->pm_state);
+ state->pm_state = pm_state;
+ }
}
int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
@@ -2085,45 +2088,6 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
}
}
-/*
- * This reverses the effects of uart_configure_port, hanging up the
- * port before removal.
- */
-static void
-uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state)
-{
- struct uart_port *port = state->port;
- struct uart_info *info = state->info;
-
- if (info && info->tty)
- tty_vhangup(info->tty);
-
- mutex_lock(&state->mutex);
-
- state->info = NULL;
-
- /*
- * Free the port IO and memory resources, if any.
- */
- if (port->type != PORT_UNKNOWN)
- port->ops->release_port(port);
-
- /*
- * Indicate that there isn't a port here anymore.
- */
- port->type = PORT_UNKNOWN;
-
- /*
- * Kill the tasklet, and free resources.
- */
- if (info) {
- tasklet_kill(&info->tlet);
- kfree(info);
- }
-
- mutex_unlock(&state->mutex);
-}
-
static struct tty_operations uart_ops = {
.open = uart_open,
.close = uart_close,
@@ -2270,6 +2234,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
state = drv->state + port->line;
mutex_lock(&port_mutex);
+ mutex_lock(&state->mutex);
if (state->port) {
ret = -EINVAL;
goto out;
@@ -2304,7 +2269,13 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
port->cons && !(port->cons->flags & CON_ENABLED))
register_console(port->cons);
+ /*
+ * Ensure UPF_DEAD is not set.
+ */
+ port->flags &= ~UPF_DEAD;
+
out:
+ mutex_unlock(&state->mutex);
mutex_unlock(&port_mutex);
return ret;
@@ -2322,6 +2293,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
{
struct uart_state *state = drv->state + port->line;
+ struct uart_info *info;
BUG_ON(in_interrupt());
@@ -2332,11 +2304,48 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
mutex_lock(&port_mutex);
/*
+ * Mark the port "dead" - this prevents any opens from
+ * succeeding while we shut down the port.
+ */
+ mutex_lock(&state->mutex);
+ port->flags |= UPF_DEAD;
+ mutex_unlock(&state->mutex);
+
+ /*
* Remove the devices from devfs
*/
tty_unregister_device(drv->tty_driver, port->line);
- uart_unconfigure_port(drv, state);
+ info = state->info;
+ if (info && info->tty)
+ tty_vhangup(info->tty);
+
+ /*
+ * All users of this port should now be disconnected from
+ * this driver, and the port shut down. We should be the
+ * only thread fiddling with this port from now on.
+ */
+ state->info = NULL;
+
+ /*
+ * Free the port IO and memory resources, if any.
+ */
+ if (port->type != PORT_UNKNOWN)
+ port->ops->release_port(port);
+
+ /*
+ * Indicate that there isn't a port here anymore.
+ */
+ port->type = PORT_UNKNOWN;
+
+ /*
+ * Kill the tasklet, and free resources.
+ */
+ if (info) {
+ tasklet_kill(&info->tlet);
+ kfree(info);
+ }
+
state->port = NULL;
mutex_unlock(&port_mutex);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index c30333694fd..2c70773543e 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -41,6 +41,7 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/serial_core.h>
+#include <linux/delay.h>
#include <linux/major.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -97,11 +98,13 @@ static const struct multi_id multi_id[] = {
#define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id))
struct serial_info {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
int ndev;
int multi;
int slave;
int manfid;
+ int prodid;
+ int c950ctrl;
dev_node_t node[4];
int line[4];
};
@@ -113,9 +116,36 @@ struct serial_cfg_mem {
};
-static void serial_config(dev_link_t * link);
+static int serial_config(struct pcmcia_device * link);
+static void wakeup_card(struct serial_info *info)
+{
+ int ctrl = info->c950ctrl;
+
+ if (info->manfid == MANFID_OXSEMI) {
+ outb(12, ctrl + 1);
+ } else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) {
+ /* request_region? oxsemi branch does no request_region too... */
+ /* This sequence is needed to properly initialize MC45 attached to OXCF950.
+ * I tried decreasing these msleep()s, but it worked properly (survived
+ * 1000 stop/start operations) with these timeouts (or bigger). */
+ outb(0xA, ctrl + 1);
+ msleep(100);
+ outb(0xE, ctrl + 1);
+ msleep(300);
+ outb(0xC, ctrl + 1);
+ msleep(100);
+ outb(0xE, ctrl + 1);
+ msleep(200);
+ outb(0xF, ctrl + 1);
+ msleep(100);
+ outb(0xE, ctrl + 1);
+ msleep(100);
+ outb(0xC, ctrl + 1);
+ }
+}
+
/*======================================================================
After a card is removed, serial_remove() will unregister
@@ -123,67 +153,45 @@ static void serial_config(dev_link_t * link);
======================================================================*/
-static void serial_remove(dev_link_t *link)
+static void serial_remove(struct pcmcia_device *link)
{
struct serial_info *info = link->priv;
int i;
- link->state &= ~DEV_PRESENT;
-
DEBUG(0, "serial_release(0x%p)\n", link);
/*
* Recheck to see if the device is still configured.
*/
- if (info->link.state & DEV_CONFIG) {
- for (i = 0; i < info->ndev; i++)
- serial8250_unregister_port(info->line[i]);
+ for (i = 0; i < info->ndev; i++)
+ serial8250_unregister_port(info->line[i]);
- info->link.dev = NULL;
+ info->p_dev->dev_node = NULL;
- if (!info->slave) {
- pcmcia_release_configuration(info->link.handle);
- pcmcia_release_io(info->link.handle, &info->link.io);
- pcmcia_release_irq(info->link.handle, &info->link.irq);
- }
-
- info->link.state &= ~DEV_CONFIG;
- }
+ if (!info->slave)
+ pcmcia_disable_device(link);
}
-static int serial_suspend(struct pcmcia_device *dev)
+static int serial_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
- link->state |= DEV_SUSPEND;
-
- if (link->state & DEV_CONFIG) {
- struct serial_info *info = link->priv;
- int i;
-
- for (i = 0; i < info->ndev; i++)
- serial8250_suspend_port(info->line[i]);
+ struct serial_info *info = link->priv;
+ int i;
- if (!info->slave)
- pcmcia_release_configuration(link->handle);
- }
+ for (i = 0; i < info->ndev; i++)
+ serial8250_suspend_port(info->line[i]);
return 0;
}
-static int serial_resume(struct pcmcia_device *dev)
+static int serial_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
- link->state &= ~DEV_SUSPEND;
-
- if (DEV_OK(link)) {
+ if (pcmcia_dev_present(link)) {
struct serial_info *info = link->priv;
int i;
- if (!info->slave)
- pcmcia_request_configuration(link->handle, &link->conf);
-
for (i = 0; i < info->ndev; i++)
serial8250_resume_port(info->line[i]);
+ wakeup_card(info);
}
return 0;
@@ -197,10 +205,9 @@ static int serial_resume(struct pcmcia_device *dev)
======================================================================*/
-static int serial_probe(struct pcmcia_device *p_dev)
+static int serial_probe(struct pcmcia_device *link)
{
struct serial_info *info;
- dev_link_t *link;
DEBUG(0, "serial_attach()\n");
@@ -209,7 +216,7 @@ static int serial_probe(struct pcmcia_device *p_dev)
if (!info)
return -ENOMEM;
memset(info, 0, sizeof (*info));
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -223,12 +230,7 @@ static int serial_probe(struct pcmcia_device *p_dev)
}
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- serial_config(link);
-
- return 0;
+ return serial_config(link);
}
/*======================================================================
@@ -240,9 +242,8 @@ static int serial_probe(struct pcmcia_device *p_dev)
======================================================================*/
-static void serial_detach(struct pcmcia_device *p_dev)
+static void serial_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct serial_info *info = link->priv;
DEBUG(0, "serial_detach(0x%p)\n", link);
@@ -263,7 +264,7 @@ static void serial_detach(struct pcmcia_device *p_dev)
/*====================================================================*/
-static int setup_serial(client_handle_t handle, struct serial_info * info,
+static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
kio_addr_t iobase, int irq)
{
struct uart_port port;
@@ -298,7 +299,7 @@ static int setup_serial(client_handle_t handle, struct serial_info * info,
/*====================================================================*/
static int
-first_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
+first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
{
int i;
i = pcmcia_get_first_tuple(handle, tuple);
@@ -311,7 +312,7 @@ first_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
}
static int
-next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
+next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
{
int i;
i = pcmcia_get_next_tuple(handle, tuple);
@@ -325,11 +326,10 @@ next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
/*====================================================================*/
-static int simple_config(dev_link_t *link)
+static int simple_config(struct pcmcia_device *link)
{
static const kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
static const int size_table[2] = { 8, 16 };
- client_handle_t handle = link->handle;
struct serial_info *info = link->priv;
struct serial_cfg_mem *cfg_mem;
tuple_t *tuple;
@@ -350,7 +350,7 @@ static int simple_config(dev_link_t *link)
buf = cfg_mem->buf;
/* If the card is already configured, look up the port and irq */
- i = pcmcia_get_configuration_info(handle, &config);
+ i = pcmcia_get_configuration_info(link, &config);
if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
kio_addr_t port = 0;
if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
@@ -363,10 +363,9 @@ static int simple_config(dev_link_t *link)
}
if (info->slave) {
kfree(cfg_mem);
- return setup_serial(handle, info, port, config.AssignedIRQ);
+ return setup_serial(link, info, port, config.AssignedIRQ);
}
}
- link->conf.Vcc = config.Vcc;
/* First pass: look for a config entry that looks normal. */
tuple->TupleData = (cisdata_t *) buf;
@@ -377,12 +376,12 @@ static int simple_config(dev_link_t *link)
/* Two tries: without IO aliases, then with aliases */
for (s = 0; s < 2; s++) {
for (try = 0; try < 2; try++) {
- i = first_tuple(handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
while (i != CS_NO_MORE_ITEMS) {
if (i != CS_SUCCESS)
goto next_entry;
if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
(cf->io.win[0].base != 0)) {
@@ -390,19 +389,19 @@ static int simple_config(dev_link_t *link)
link->io.BasePort1 = cf->io.win[0].base;
link->io.IOAddrLines = (try == 0) ?
16 : cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
next_entry:
- i = next_tuple(handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
}
}
/* Second pass: try to find an entry that isn't picky about
its base address, then try to grab any standard serial port
address, and finally try to get any free port. */
- i = first_tuple(handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
while (i != CS_NO_MORE_ITEMS) {
if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
@@ -410,50 +409,48 @@ next_entry:
for (j = 0; j < 5; j++) {
link->io.BasePort1 = base[j];
link->io.IOAddrLines = base[j] ? 16 : 3;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
}
- i = next_tuple(handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
found_port:
if (i != CS_SUCCESS) {
printk(KERN_NOTICE
"serial_cs: no usable port range found, giving up\n");
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
kfree(cfg_mem);
return -1;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
if (info->multi && (info->manfid == MANFID_3COM))
link->conf.ConfigIndex &= ~(0x08);
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
kfree(cfg_mem);
return -1;
}
kfree(cfg_mem);
- return setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
+ return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
}
-static int multi_config(dev_link_t * link)
+static int multi_config(struct pcmcia_device * link)
{
- client_handle_t handle = link->handle;
struct serial_info *info = link->priv;
struct serial_cfg_mem *cfg_mem;
tuple_t *tuple;
u_char *buf;
cisparse_t *parse;
cistpl_cftable_entry_t *cf;
- config_info_t config;
int i, rc, base2 = 0;
cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
@@ -464,14 +461,6 @@ static int multi_config(dev_link_t * link)
cf = &parse->cftable_entry;
buf = cfg_mem->buf;
- i = pcmcia_get_configuration_info(handle, &config);
- if (i != CS_SUCCESS) {
- cs_error(handle, GetConfigurationInfo, i);
- rc = -1;
- goto free_cfg_mem;
- }
- link->conf.Vcc = config.Vcc;
-
tuple->TupleData = (cisdata_t *) buf;
tuple->TupleOffset = 0;
tuple->TupleDataMax = 255;
@@ -480,7 +469,7 @@ static int multi_config(dev_link_t * link)
/* First, look for a generic full-sized window */
link->io.NumPorts1 = info->multi * 8;
- i = first_tuple(handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
while (i != CS_NO_MORE_ITEMS) {
/* The quad port cards have bad CIS's, so just look for a
window larger than 8 ports and assume it will be right */
@@ -490,19 +479,19 @@ static int multi_config(dev_link_t * link)
link->io.BasePort1 = cf->io.win[0].base;
link->io.IOAddrLines =
cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
base2 = link->io.BasePort1 + 8;
if (i == CS_SUCCESS)
break;
}
- i = next_tuple(handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
/* If that didn't work, look for two windows */
if (i != CS_SUCCESS) {
link->io.NumPorts1 = link->io.NumPorts2 = 8;
info->multi = 2;
- i = first_tuple(handle, tuple, parse);
+ i = first_tuple(link, tuple, parse);
while (i != CS_NO_MORE_ITEMS) {
if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
link->conf.ConfigIndex = cf->index;
@@ -510,26 +499,26 @@ static int multi_config(dev_link_t * link)
link->io.BasePort2 = cf->io.win[1].base;
link->io.IOAddrLines =
cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link->handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
base2 = link->io.BasePort2;
if (i == CS_SUCCESS)
break;
}
- i = next_tuple(handle, tuple, parse);
+ i = next_tuple(link, tuple, parse);
}
}
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
+ cs_error(link, RequestIO, i);
rc = -1;
goto free_cfg_mem;
}
- i = pcmcia_request_irq(link->handle, &link->irq);
+ i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) {
printk(KERN_NOTICE
"serial_cs: no usable port range found, giving up\n");
- cs_error(link->handle, RequestIRQ, i);
+ cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
/* Socket Dual IO: this enables irq's for second port */
@@ -537,35 +526,43 @@ static int multi_config(dev_link_t * link)
link->conf.Present |= PRESENT_EXT_STATUS;
link->conf.ExtStatus = ESR_REQ_ATTN_ENA;
}
- i = pcmcia_request_configuration(link->handle, &link->conf);
+ i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
+ cs_error(link, RequestConfiguration, i);
rc = -1;
goto free_cfg_mem;
}
/* The Oxford Semiconductor OXCF950 cards are in fact single-port:
- 8 registers are for the UART, the others are extra registers */
- if (info->manfid == MANFID_OXSEMI) {
+ * 8 registers are for the UART, the others are extra registers.
+ * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
+ */
+ if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
+ info->prodid == PRODID_POSSIO_GCC)) {
+ int err;
+
if (cf->index == 1 || cf->index == 3) {
- setup_serial(handle, info, base2, link->irq.AssignedIRQ);
- outb(12, link->io.BasePort1 + 1);
+ err = setup_serial(link, info, base2,
+ link->irq.AssignedIRQ);
+ base2 = link->io.BasePort1;
} else {
- setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
- outb(12, base2 + 1);
+ err = setup_serial(link, info, link->io.BasePort1,
+ link->irq.AssignedIRQ);
}
+ info->c950ctrl = base2;
+ wakeup_card(info);
rc = 0;
goto free_cfg_mem;
}
- setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
+ setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
/* The Nokia cards are not really multiport cards */
if (info->manfid == MANFID_NOKIA) {
rc = 0;
goto free_cfg_mem;
}
for (i = 0; i < info->multi - 1; i++)
- setup_serial(handle, info, base2 + (8 * i),
+ setup_serial(link, info, base2 + (8 * i),
link->irq.AssignedIRQ);
rc = 0;
free_cfg_mem:
@@ -581,9 +578,8 @@ free_cfg_mem:
======================================================================*/
-void serial_config(dev_link_t * link)
+static int serial_config(struct pcmcia_device * link)
{
- client_handle_t handle = link->handle;
struct serial_info *info = link->priv;
struct serial_cfg_mem *cfg_mem;
tuple_t *tuple;
@@ -609,7 +605,7 @@ void serial_config(dev_link_t * link)
tuple->Attributes = 0;
/* Get configuration register information */
tuple->DesiredTuple = CISTPL_CONFIG;
- last_ret = first_tuple(handle, tuple, parse);
+ last_ret = first_tuple(link, tuple, parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
@@ -617,18 +613,16 @@ void serial_config(dev_link_t * link)
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Is this a compliant multifunction card? */
tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
- info->multi = (first_tuple(handle, tuple, parse) == CS_SUCCESS);
+ info->multi = (first_tuple(link, tuple, parse) == CS_SUCCESS);
/* Is this a multiport card? */
tuple->DesiredTuple = CISTPL_MANFID;
- if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+ if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
info->manfid = parse->manfid.manf;
+ info->prodid = le16_to_cpu(buf[1]);
for (i = 0; i < MULTI_COUNT; i++)
if ((info->manfid == multi_id[i].manfid) &&
(parse->manfid.card == multi_id[i].prodid))
@@ -641,11 +635,11 @@ void serial_config(dev_link_t * link)
multifunction cards that ask for appropriate IO port ranges */
tuple->DesiredTuple = CISTPL_FUNCID;
if ((info->multi == 0) &&
- ((first_tuple(handle, tuple, parse) != CS_SUCCESS) ||
+ ((first_tuple(link, tuple, parse) != CS_SUCCESS) ||
(parse->funcid.func == CISTPL_FUNCID_MULTI) ||
(parse->funcid.func == CISTPL_FUNCID_SERIAL))) {
tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
- if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+ if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
info->multi = cf->io.win[0].len >> 3;
if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
@@ -664,31 +658,30 @@ void serial_config(dev_link_t * link)
if (info->manfid == MANFID_IBM) {
conf_reg_t reg = { 0, CS_READ, 0x800, 0 };
- last_ret = pcmcia_access_configuration_register(link->handle, &reg);
+ last_ret = pcmcia_access_configuration_register(link, &reg);
if (last_ret) {
last_fn = AccessConfigurationRegister;
goto cs_failed;
}
reg.Action = CS_WRITE;
reg.Value = reg.Value | 1;
- last_ret = pcmcia_access_configuration_register(link->handle, &reg);
+ last_ret = pcmcia_access_configuration_register(link, &reg);
if (last_ret) {
last_fn = AccessConfigurationRegister;
goto cs_failed;
}
}
- link->dev = &info->node[0];
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &info->node[0];
kfree(cfg_mem);
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
serial_remove(link);
- link->state &= ~DEV_CONFIG_PENDING;
kfree(cfg_mem);
+ return -ENODEV;
}
static struct pcmcia_device_id serial_ids[] = {
@@ -739,6 +732,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
+ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
@@ -757,6 +751,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
+ PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index b848b7d9441..3bdee64d1a9 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -483,7 +483,7 @@ static int serial_txx9_startup(struct uart_port *port)
/*
* Clear the FIFO buffers and disable them.
- * (they will be reeanbled in set_termios())
+ * (they will be reenabled in set_termios())
*/
sio_set(up, TXX9_SIFCR,
TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 9fe2283d91e..2b4f96541b8 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -641,7 +641,7 @@ static int sunsu_startup(struct uart_port *port)
/*
* Clear the FIFO buffers and disable them.
- * (they will be reeanbled in set_termios())
+ * (they will be reenabled in set_termios())
*/
if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) {
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
@@ -1730,3 +1730,4 @@ static void __exit sunsu_exit(void)
module_init(sunsu_probe);
module_exit(sunsu_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
index 93449a1a006..501316b198e 100644
--- a/drivers/sn/ioc3.c
+++ b/drivers/sn/ioc3.c
@@ -11,6 +11,7 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
@@ -619,9 +620,9 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
pci_set_master(pdev);
#ifdef USE_64BIT_DMA
- ret = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+ ret = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
if (!ret) {
- ret = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+ ret = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
if (ret < 0) {
printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA "
"for consistent allocations\n",
@@ -677,7 +678,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
/* Track PCI-device specific data */
pci_set_drvdata(pdev, idd);
down_write(&ioc3_devices_rwsem);
- list_add(&idd->list, &ioc3_devices);
+ list_add_tail(&idd->list, &ioc3_devices);
idd->id = ioc3_counter++;
up_write(&ioc3_devices_rwsem);
diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c
index 67140a5804f..cdeff909403 100644
--- a/drivers/sn/ioc4.c
+++ b/drivers/sn/ioc4.c
@@ -310,7 +310,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
pci_set_drvdata(idd->idd_pdev, idd);
mutex_lock(&ioc4_mutex);
- list_add(&idd->idd_list, &ioc4_devices);
+ list_add_tail(&idd->idd_list, &ioc4_devices);
/* Add this IOC4 to all submodules */
list_for_each_entry(is, &ioc4_submodules, is_list) {
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 7a75faeb052..23334c8bc4c 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -75,11 +75,45 @@ config SPI_BUTTERFLY
inexpensive battery powered microcontroller evaluation board.
This same cable can be used to flash new firmware.
+config SPI_MPC83xx
+ tristate "Freescale MPC83xx SPI controller"
+ depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL
+ select SPI_BITBANG
+ help
+ This enables using the Freescale MPC83xx SPI controller in master
+ mode.
+
+ Note, this driver uniquely supports the SPI controller on the MPC83xx
+ family of PowerPC processors. The MPC83xx uses a simple set of shift
+ registers for data (opposed to the CPM based descriptor model).
+
+config SPI_PXA2XX
+ tristate "PXA2xx SSP SPI master"
+ depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL
+ help
+ This enables using a PXA2xx SSP port as a SPI master controller.
+ The driver can be configured to use any SSP port and additional
+ documentation can be found a Documentation/spi/pxa2xx.
+
+config SPI_S3C24XX_GPIO
+ tristate "Samsung S3C24XX series SPI by GPIO"
+ depends on SPI_MASTER && ARCH_S3C2410 && SPI_BITBANG && EXPERIMENTAL
+ 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.
#
# Add new SPI master controllers in alphabetical order above this line
#
+config SPI_S3C24XX
+ tristate "Samsung S3C24XX series SPI"
+ depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+ help
+ SPI driver for Samsung S3C24XX series ARM SoCs
+
#
# There are lots of SPI device types, with sensors and memory
# being probably the most widely used ones.
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index c2c87e845ab..8f4cb67997b 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -13,6 +13,10 @@ obj-$(CONFIG_SPI_MASTER) += spi.o
# SPI master controller drivers (bus)
obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
+obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_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
# ... add above this line ...
# SPI protocol drivers (device/link on bus)
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
new file mode 100644
index 00000000000..29aec77f98b
--- /dev/null
+++ b/drivers/spi/pxa2xx_spi.c
@@ -0,0 +1,1486 @@
+/*
+ * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
+ *
+ * This program is free software; 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/device.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/delay.h>
+#include <asm/dma.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx_spi.h>
+
+MODULE_AUTHOR("Stephen Street");
+MODULE_DESCRIPTION("PXA2xx SSP SPI Contoller");
+MODULE_LICENSE("GPL");
+
+#define MAX_BUSES 3
+
+#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
+#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
+#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)
+
+#define DEFINE_SSP_REG(reg, off) \
+static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \
+static inline void write_##reg(u32 v, void *p) { __raw_writel(v, p + (off)); }
+
+DEFINE_SSP_REG(SSCR0, 0x00)
+DEFINE_SSP_REG(SSCR1, 0x04)
+DEFINE_SSP_REG(SSSR, 0x08)
+DEFINE_SSP_REG(SSITR, 0x0c)
+DEFINE_SSP_REG(SSDR, 0x10)
+DEFINE_SSP_REG(SSTO, 0x28)
+DEFINE_SSP_REG(SSPSP, 0x2c)
+
+#define START_STATE ((void*)0)
+#define RUNNING_STATE ((void*)1)
+#define DONE_STATE ((void*)2)
+#define ERROR_STATE ((void*)-1)
+
+#define QUEUE_RUNNING 0
+#define QUEUE_STOPPED 1
+
+struct driver_data {
+ /* Driver model hookup */
+ struct platform_device *pdev;
+
+ /* SPI framework hookup */
+ enum pxa_ssp_type ssp_type;
+ struct spi_master *master;
+
+ /* PXA hookup */
+ struct pxa2xx_spi_master *master_info;
+
+ /* DMA setup stuff */
+ int rx_channel;
+ int tx_channel;
+ u32 *null_dma_buf;
+
+ /* SSP register addresses */
+ void *ioaddr;
+ u32 ssdr_physical;
+
+ /* SSP masks*/
+ u32 dma_cr1;
+ u32 int_cr1;
+ u32 clear_sr;
+ u32 mask_sr;
+
+ /* Driver message queue */
+ struct workqueue_struct *workqueue;
+ struct work_struct pump_messages;
+ spinlock_t lock;
+ struct list_head queue;
+ int busy;
+ int run;
+
+ /* Message Transfer pump */
+ struct tasklet_struct pump_transfers;
+
+ /* Current message transfer state info */
+ struct spi_message* cur_msg;
+ struct spi_transfer* cur_transfer;
+ struct chip_data *cur_chip;
+ size_t len;
+ void *tx;
+ void *tx_end;
+ void *rx;
+ void *rx_end;
+ int dma_mapped;
+ dma_addr_t rx_dma;
+ dma_addr_t tx_dma;
+ size_t rx_map_len;
+ size_t tx_map_len;
+ u8 n_bytes;
+ u32 dma_width;
+ int cs_change;
+ void (*write)(struct driver_data *drv_data);
+ void (*read)(struct driver_data *drv_data);
+ irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
+ void (*cs_control)(u32 command);
+};
+
+struct chip_data {
+ u32 cr0;
+ u32 cr1;
+ u32 to;
+ u32 psp;
+ u32 timeout;
+ u8 n_bytes;
+ u32 dma_width;
+ u32 dma_burst_size;
+ u32 threshold;
+ u32 dma_threshold;
+ u8 enable_dma;
+ u8 bits_per_word;
+ u32 speed_hz;
+ void (*write)(struct driver_data *drv_data);
+ void (*read)(struct driver_data *drv_data);
+ void (*cs_control)(u32 command);
+};
+
+static void pump_messages(void *data);
+
+static int flush(struct driver_data *drv_data)
+{
+ unsigned long limit = loops_per_jiffy << 1;
+
+ void *reg = drv_data->ioaddr;
+
+ do {
+ while (read_SSSR(reg) & SSSR_RNE) {
+ read_SSDR(reg);
+ }
+ } while ((read_SSSR(reg) & SSSR_BSY) && limit--);
+ write_SSSR(SSSR_ROR, reg);
+
+ return limit;
+}
+
+static void restore_state(struct driver_data *drv_data)
+{
+ void *reg = drv_data->ioaddr;
+
+ /* Clear status and disable clock */
+ write_SSSR(drv_data->clear_sr, reg);
+ write_SSCR0(drv_data->cur_chip->cr0 & ~SSCR0_SSE, reg);
+
+ /* Load the registers */
+ write_SSCR1(drv_data->cur_chip->cr1, reg);
+ write_SSCR0(drv_data->cur_chip->cr0, reg);
+ if (drv_data->ssp_type != PXA25x_SSP) {
+ write_SSTO(0, reg);
+ write_SSPSP(drv_data->cur_chip->psp, reg);
+ }
+}
+
+static void null_cs_control(u32 command)
+{
+}
+
+static void null_writer(struct driver_data *drv_data)
+{
+ void *reg = drv_data->ioaddr;
+ u8 n_bytes = drv_data->n_bytes;
+
+ while ((read_SSSR(reg) & SSSR_TNF)
+ && (drv_data->tx < drv_data->tx_end)) {
+ write_SSDR(0, reg);
+ drv_data->tx += n_bytes;
+ }
+}
+
+static void null_reader(struct driver_data *drv_data)
+{
+ void *reg = drv_data->ioaddr;
+ u8 n_bytes = drv_data->n_bytes;
+
+ while ((read_SSSR(reg) & SSSR_RNE)
+ && (drv_data->rx < drv_data->rx_end)) {
+ read_SSDR(reg);
+ drv_data->rx += n_bytes;
+ }
+}
+
+static void u8_writer(struct driver_data *drv_data)
+{
+ void *reg = drv_data->ioaddr;
+
+ while ((read_SSSR(reg) & SSSR_TNF)
+ && (drv_data->tx < drv_data->tx_end)) {
+ write_SSDR(*(u8 *)(drv_data->tx), reg);
+ ++drv_data->tx;
+ }
+}
+
+static void u8_reader(struct driver_data *drv_data)
+{
+ void *reg = drv_data->ioaddr;
+
+ while ((read_SSSR(reg) & SSSR_RNE)
+ && (drv_data->rx < drv_data->rx_end)) {
+ *(u8 *)(drv_data->rx) = read_SSDR(reg);
+ ++drv_data->rx;
+ }
+}
+
+static void u16_writer(struct driver_data *drv_data)
+{
+ void *reg = drv_data->ioaddr;
+
+ while ((read_SSSR(reg) & SSSR_TNF)
+ && (drv_data->tx < drv_data->tx_end)) {
+ write_SSDR(*(u16 *)(drv_data->tx), reg);
+ drv_data->tx += 2;
+ }
+}
+
+static void u16_reader(struct driver_data *drv_data)
+{
+ void *reg = drv_data->ioaddr;
+
+ while ((read_SSSR(reg) & SSSR_RNE)
+ && (drv_data->rx < drv_data->rx_end)) {
+ *(u16 *)(drv_data->rx) = read_SSDR(reg);
+ drv_data->rx += 2;
+ }
+}
+static void u32_writer(struct driver_data *drv_data)
+{
+ void *reg = drv_data->ioaddr;
+
+ while ((read_SSSR(reg) & SSSR_TNF)
+ && (drv_data->tx < drv_data->tx_end)) {
+ write_SSDR(*(u32 *)(drv_data->tx), reg);
+ drv_data->tx += 4;
+ }
+}
+
+static void u32_reader(struct driver_data *drv_data)
+{
+ void *reg = drv_data->ioaddr;
+
+ while ((read_SSSR(reg) & SSSR_RNE)
+ && (drv_data->rx < drv_data->rx_end)) {
+ *(u32 *)(drv_data->rx) = read_SSDR(reg);
+ drv_data->rx += 4;
+ }
+}
+
+static void *next_transfer(struct driver_data *drv_data)
+{
+ struct spi_message *msg = drv_data->cur_msg;
+ struct spi_transfer *trans = drv_data->cur_transfer;
+
+ /* Move to next transfer */
+ if (trans->transfer_list.next != &msg->transfers) {
+ drv_data->cur_transfer =
+ list_entry(trans->transfer_list.next,
+ struct spi_transfer,
+ transfer_list);
+ return RUNNING_STATE;
+ } else
+ return DONE_STATE;
+}
+
+static int map_dma_buffers(struct driver_data *drv_data)
+{
+ struct spi_message *msg = drv_data->cur_msg;
+ struct device *dev = &msg->spi->dev;
+
+ if (!drv_data->cur_chip->enable_dma)
+ return 0;
+
+ if (msg->is_dma_mapped)
+ return drv_data->rx_dma && drv_data->tx_dma;
+
+ if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
+ return 0;
+
+ /* Modify setup if rx buffer is null */
+ if (drv_data->rx == NULL) {
+ *drv_data->null_dma_buf = 0;
+ drv_data->rx = drv_data->null_dma_buf;
+ drv_data->rx_map_len = 4;
+ } else
+ drv_data->rx_map_len = drv_data->len;
+
+
+ /* Modify setup if tx buffer is null */
+ if (drv_data->tx == NULL) {
+ *drv_data->null_dma_buf = 0;
+ drv_data->tx = drv_data->null_dma_buf;
+ drv_data->tx_map_len = 4;
+ } else
+ drv_data->tx_map_len = drv_data->len;
+
+ /* Stream map the rx buffer */
+ drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
+ drv_data->rx_map_len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(drv_data->rx_dma))
+ return 0;
+
+ /* Stream map the tx buffer */
+ drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
+ drv_data->tx_map_len,
+ DMA_TO_DEVICE);
+
+ if (dma_mapping_error(drv_data->tx_dma)) {
+ dma_unmap_single(dev, drv_data->rx_dma,
+ drv_data->rx_map_len, DMA_FROM_DEVICE);
+ return 0;
+ }
+
+ return 1;
+}
+
+static void unmap_dma_buffers(struct driver_data *drv_data)
+{
+ struct device *dev;
+
+ if (!drv_data->dma_mapped)
+ return;
+
+ if (!drv_data->cur_msg->is_dma_mapped) {
+ dev = &drv_data->cur_msg->spi->dev;
+ dma_unmap_single(dev, drv_data->rx_dma,
+ drv_data->rx_map_len, DMA_FROM_DEVICE);
+ dma_unmap_single(dev, drv_data->tx_dma,
+ drv_data->tx_map_len, DMA_TO_DEVICE);
+ }
+
+ drv_data->dma_mapped = 0;
+}
+
+/* caller already set message->status; dma and pio irqs are blocked */
+static void giveback(struct driver_data *drv_data)
+{
+ struct spi_transfer* last_transfer;
+ unsigned long flags;
+ struct spi_message *msg;
+
+ spin_lock_irqsave(&drv_data->lock, flags);
+ msg = drv_data->cur_msg;
+ drv_data->cur_msg = NULL;
+ drv_data->cur_transfer = NULL;
+ drv_data->cur_chip = NULL;
+ queue_work(drv_data->workqueue, &drv_data->pump_messages);
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+
+ last_transfer = list_entry(msg->transfers.prev,
+ struct spi_transfer,
+ transfer_list);
+
+ if (!last_transfer->cs_change)
+ drv_data->cs_control(PXA2XX_CS_DEASSERT);
+
+ msg->state = NULL;
+ if (msg->complete)
+ msg->complete(msg->context);
+}
+
+static int wait_ssp_rx_stall(void *ioaddr)
+{
+ unsigned long limit = loops_per_jiffy << 1;
+
+ while ((read_SSSR(ioaddr) & SSSR_BSY) && limit--)
+ cpu_relax();
+
+ return limit;
+}
+
+static int wait_dma_channel_stop(int channel)
+{
+ unsigned long limit = loops_per_jiffy << 1;
+
+ while (!(DCSR(channel) & DCSR_STOPSTATE) && limit--)
+ cpu_relax();
+
+ return limit;
+}
+
+static void dma_handler(int channel, void *data, struct pt_regs *regs)
+{
+ struct driver_data *drv_data = data;
+ struct spi_message *msg = drv_data->cur_msg;
+ void *reg = drv_data->ioaddr;
+ u32 irq_status = DCSR(channel) & DMA_INT_MASK;
+ u32 trailing_sssr = 0;
+
+ if (irq_status & DCSR_BUSERR) {
+
+ /* Disable interrupts, clear status and reset DMA */
+ write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
+ write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(0, reg);
+ write_SSSR(drv_data->clear_sr, reg);
+ DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+ DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+
+ if (flush(drv_data) == 0)
+ dev_err(&drv_data->pdev->dev,
+ "dma_handler: flush fail\n");
+
+ unmap_dma_buffers(drv_data);
+
+ if (channel == drv_data->tx_channel)
+ dev_err(&drv_data->pdev->dev,
+ "dma_handler: bad bus address on "
+ "tx channel %d, source %x target = %x\n",
+ channel, DSADR(channel), DTADR(channel));
+ else
+ dev_err(&drv_data->pdev->dev,
+ "dma_handler: bad bus address on "
+ "rx channel %d, source %x target = %x\n",
+ channel, DSADR(channel), DTADR(channel));
+
+ msg->state = ERROR_STATE;
+ tasklet_schedule(&drv_data->pump_transfers);
+ }
+
+ /* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
+ if ((drv_data->ssp_type == PXA25x_SSP)
+ && (channel == drv_data->tx_channel)
+ && (irq_status & DCSR_ENDINTR)) {
+
+ /* Wait for rx to stall */
+ if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
+ dev_err(&drv_data->pdev->dev,
+ "dma_handler: ssp rx stall failed\n");
+
+ /* Clear and disable interrupts on SSP and DMA channels*/
+ write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+ write_SSSR(drv_data->clear_sr, reg);
+ DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+ DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+ if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
+ dev_err(&drv_data->pdev->dev,
+ "dma_handler: dma rx channel stop failed\n");
+
+ unmap_dma_buffers(drv_data);
+
+ /* Read trailing bytes */
+ /* Calculate number of trailing bytes, read them */
+ trailing_sssr = read_SSSR(reg);
+ if ((trailing_sssr & 0xf008) != 0xf000) {
+ drv_data->rx = drv_data->rx_end -
+ (((trailing_sssr >> 12) & 0x0f) + 1);
+ drv_data->read(drv_data);
+ }
+ msg->actual_length += drv_data->len;
+
+ /* Release chip select if requested, transfer delays are
+ * handled in pump_transfers */
+ if (drv_data->cs_change)
+ drv_data->cs_control(PXA2XX_CS_DEASSERT);
+
+ /* Move to next transfer */
+ msg->state = next_transfer(drv_data);
+
+ /* Schedule transfer tasklet */
+ tasklet_schedule(&drv_data->pump_transfers);
+ }
+}
+
+static irqreturn_t dma_transfer(struct driver_data *drv_data)
+{
+ u32 irq_status;
+ u32 trailing_sssr = 0;
+ struct spi_message *msg = drv_data->cur_msg;
+ void *reg = drv_data->ioaddr;
+
+ irq_status = read_SSSR(reg) & drv_data->mask_sr;
+ if (irq_status & SSSR_ROR) {
+ /* Clear and disable interrupts on SSP and DMA channels*/
+ write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
+ write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(0, reg);
+ write_SSSR(drv_data->clear_sr, reg);
+ DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+ DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+ unmap_dma_buffers(drv_data);
+
+ if (flush(drv_data) == 0)
+ dev_err(&drv_data->pdev->dev,
+ "dma_transfer: flush fail\n");
+
+ dev_warn(&drv_data->pdev->dev, "dma_transfer: fifo overun\n");
+
+ drv_data->cur_msg->state = ERROR_STATE;
+ tasklet_schedule(&drv_data->pump_transfers);
+
+ return IRQ_HANDLED;
+ }
+
+ /* Check for false positive timeout */
+ if ((irq_status & SSSR_TINT) && DCSR(drv_data->tx_channel) & DCSR_RUN) {
+ write_SSSR(SSSR_TINT, reg);
+ return IRQ_HANDLED;
+ }
+
+ if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
+
+ /* Clear and disable interrupts on SSP and DMA channels*/
+ write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(0, reg);
+ write_SSSR(drv_data->clear_sr, reg);
+ DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+ DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+
+ if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
+ dev_err(&drv_data->pdev->dev,
+ "dma_transfer: dma rx channel stop failed\n");
+
+ if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
+ dev_err(&drv_data->pdev->dev,
+ "dma_transfer: ssp rx stall failed\n");
+
+ unmap_dma_buffers(drv_data);
+
+ /* Calculate number of trailing bytes, read them */
+ trailing_sssr = read_SSSR(reg);
+ if ((trailing_sssr & 0xf008) != 0xf000) {
+ drv_data->rx = drv_data->rx_end -
+ (((trailing_sssr >> 12) & 0x0f) + 1);
+ drv_data->read(drv_data);
+ }
+ msg->actual_length += drv_data->len;
+
+ /* Release chip select if requested, transfer delays are
+ * handled in pump_transfers */
+ if (drv_data->cs_change)
+ drv_data->cs_control(PXA2XX_CS_DEASSERT);
+
+ /* Move to next transfer */
+ msg->state = next_transfer(drv_data);
+
+ /* Schedule transfer tasklet */
+ tasklet_schedule(&drv_data->pump_transfers);
+
+ return IRQ_HANDLED;
+ }
+
+ /* Opps problem detected */
+ return IRQ_NONE;
+}
+
+static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+{
+ struct spi_message *msg = drv_data->cur_msg;
+ void *reg = drv_data->ioaddr;
+ unsigned long limit = loops_per_jiffy << 1;
+ u32 irq_status;
+ u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
+ drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
+
+ while ((irq_status = read_SSSR(reg) & irq_mask)) {
+
+ if (irq_status & SSSR_ROR) {
+
+ /* Clear and disable interrupts */
+ write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
+ write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(0, reg);
+ write_SSSR(drv_data->clear_sr, reg);
+
+ if (flush(drv_data) == 0)
+ dev_err(&drv_data->pdev->dev,
+ "interrupt_transfer: flush fail\n");
+
+ /* Stop the SSP */
+
+ dev_warn(&drv_data->pdev->dev,
+ "interrupt_transfer: fifo overun\n");
+
+ msg->state = ERROR_STATE;
+ tasklet_schedule(&drv_data->pump_transfers);
+
+ return IRQ_HANDLED;
+ }
+
+ /* Look for false positive timeout */
+ if ((irq_status & SSSR_TINT)
+ && (drv_data->rx < drv_data->rx_end))
+ write_SSSR(SSSR_TINT, reg);
+
+ /* Pump data */
+ drv_data->read(drv_data);
+ drv_data->write(drv_data);
+
+ if (drv_data->tx == drv_data->tx_end) {
+ /* Disable tx interrupt */
+ write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg);
+ irq_mask = drv_data->mask_sr & ~SSSR_TFS;
+
+ /* PXA25x_SSP has no timeout, read trailing bytes */
+ if (drv_data->ssp_type == PXA25x_SSP) {
+ while ((read_SSSR(reg) & SSSR_BSY) && limit--)
+ drv_data->read(drv_data);
+
+ if (limit == 0)
+ dev_err(&drv_data->pdev->dev,
+ "interrupt_transfer: "
+ "trailing byte read failed\n");
+ }
+ }
+
+ if ((irq_status & SSSR_TINT)
+ || (drv_data->rx == drv_data->rx_end)) {
+
+ /* Clear timeout */
+ write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(0, reg);
+ write_SSSR(drv_data->clear_sr, reg);
+
+ /* Update total byte transfered */
+ msg->actual_length += drv_data->len;
+
+ /* Release chip select if requested, transfer delays are
+ * handled in pump_transfers */
+ if (drv_data->cs_change)
+ drv_data->cs_control(PXA2XX_CS_DEASSERT);
+
+ /* Move to next transfer */
+ msg->state = next_transfer(drv_data);
+
+ /* Schedule transfer tasklet */
+ tasklet_schedule(&drv_data->pump_transfers);
+ }
+ }
+
+ /* We did something */
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t ssp_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct driver_data *drv_data = (struct driver_data *)dev_id;
+ void *reg = drv_data->ioaddr;
+
+ if (!drv_data->cur_msg) {
+
+ write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
+ write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(0, reg);
+ write_SSSR(drv_data->clear_sr, reg);
+
+ dev_err(&drv_data->pdev->dev, "bad message state "
+ "in interrupt handler");
+
+ /* Never fail */
+ return IRQ_HANDLED;
+ }
+
+ return drv_data->transfer_handler(drv_data);
+}
+
+static void pump_transfers(unsigned long data)
+{
+ struct driver_data *drv_data = (struct driver_data *)data;
+ struct spi_message *message = NULL;
+ struct spi_transfer *transfer = NULL;
+ struct spi_transfer *previous = NULL;
+ struct chip_data *chip = NULL;
+ void *reg = drv_data->ioaddr;
+ u32 clk_div = 0;
+ u8 bits = 0;
+ u32 speed = 0;
+ u32 cr0;
+
+ /* Get current state information */
+ message = drv_data->cur_msg;
+ transfer = drv_data->cur_transfer;
+ chip = drv_data->cur_chip;
+
+ /* Handle for abort */
+ if (message->state == ERROR_STATE) {
+ message->status = -EIO;
+ giveback(drv_data);
+ return;
+ }
+
+ /* Handle end of message */
+ if (message->state == DONE_STATE) {
+ message->status = 0;
+ giveback(drv_data);
+ return;
+ }
+
+ /* Delay if requested at end of transfer*/
+ if (message->state == RUNNING_STATE) {
+ previous = list_entry(transfer->transfer_list.prev,
+ struct spi_transfer,
+ transfer_list);
+ if (previous->delay_usecs)
+ udelay(previous->delay_usecs);
+ }
+
+ /* Setup the transfer state based on the type of transfer */
+ if (flush(drv_data) == 0) {
+ dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
+ message->status = -EIO;
+ giveback(drv_data);
+ return;
+ }
+ drv_data->n_bytes = chip->n_bytes;
+ drv_data->dma_width = chip->dma_width;
+ drv_data->cs_control = chip->cs_control;
+ drv_data->tx = (void *)transfer->tx_buf;
+ drv_data->tx_end = drv_data->tx + transfer->len;
+ drv_data->rx = transfer->rx_buf;
+ drv_data->rx_end = drv_data->rx + transfer->len;
+ drv_data->rx_dma = transfer->rx_dma;
+ drv_data->tx_dma = transfer->tx_dma;
+ drv_data->len = transfer->len;
+ drv_data->write = drv_data->tx ? chip->write : null_writer;
+ drv_data->read = drv_data->rx ? chip->read : null_reader;
+ drv_data->cs_change = transfer->cs_change;
+
+ /* Change speed and bit per word on a per transfer */
+ if (transfer->speed_hz || transfer->bits_per_word) {
+
+ /* Disable clock */
+ write_SSCR0(chip->cr0 & ~SSCR0_SSE, reg);
+ cr0 = chip->cr0;
+ bits = chip->bits_per_word;
+ speed = chip->speed_hz;
+
+ if (transfer->speed_hz)
+ speed = transfer->speed_hz;
+
+ if (transfer->bits_per_word)
+ bits = transfer->bits_per_word;
+
+ if (reg == SSP1_VIRT)
+ clk_div = SSP1_SerClkDiv(speed);
+ else if (reg == SSP2_VIRT)
+ clk_div = SSP2_SerClkDiv(speed);
+ else if (reg == SSP3_VIRT)
+ clk_div = SSP3_SerClkDiv(speed);
+
+ if (bits <= 8) {
+ drv_data->n_bytes = 1;
+ drv_data->dma_width = DCMD_WIDTH1;
+ drv_data->read = drv_data->read != null_reader ?
+ u8_reader : null_reader;
+ drv_data->write = drv_data->write != null_writer ?
+ u8_writer : null_writer;
+ } else if (bits <= 16) {
+ drv_data->n_bytes = 2;
+ drv_data->dma_width = DCMD_WIDTH2;
+ drv_data->read = drv_data->read != null_reader ?
+ u16_reader : null_reader;
+ drv_data->write = drv_data->write != null_writer ?
+ u16_writer : null_writer;
+ } else if (bits <= 32) {
+ drv_data->n_bytes = 4;
+ drv_data->dma_width = DCMD_WIDTH4;
+ drv_data->read = drv_data->read != null_reader ?
+ u32_reader : null_reader;
+ drv_data->write = drv_data->write != null_writer ?
+ u32_writer : null_writer;
+ }
+
+ cr0 = clk_div
+ | SSCR0_Motorola
+ | SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
+ | SSCR0_SSE
+ | (bits > 16 ? SSCR0_EDSS : 0);
+
+ /* Start it back up */
+ write_SSCR0(cr0, reg);
+ }
+
+ message->state = RUNNING_STATE;
+
+ /* Try to map dma buffer and do a dma transfer if successful */
+ if ((drv_data->dma_mapped = map_dma_buffers(drv_data))) {
+
+ /* Ensure we have the correct interrupt handler */
+ drv_data->transfer_handler = dma_transfer;
+
+ /* Setup rx DMA Channel */
+ DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+ DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
+ DTADR(drv_data->rx_channel) = drv_data->rx_dma;
+ if (drv_data->rx == drv_data->null_dma_buf)
+ /* No target address increment */
+ DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
+ | drv_data->dma_width
+ | chip->dma_burst_size
+ | drv_data->len;
+ else
+ DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
+ | DCMD_FLOWSRC
+ | drv_data->dma_width
+ | chip->dma_burst_size
+ | drv_data->len;
+
+ /* Setup tx DMA Channel */
+ DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+ DSADR(drv_data->tx_channel) = drv_data->tx_dma;
+ DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
+ if (drv_data->tx == drv_data->null_dma_buf)
+ /* No source address increment */
+ DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
+ | drv_data->dma_width
+ | chip->dma_burst_size
+ | drv_data->len;
+ else
+ DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
+ | DCMD_FLOWTRG
+ | drv_data->dma_width
+ | chip->dma_burst_size
+ | drv_data->len;
+
+ /* Enable dma end irqs on SSP to detect end of transfer */
+ if (drv_data->ssp_type == PXA25x_SSP)
+ DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
+
+ /* Fix me, need to handle cs polarity */
+ drv_data->cs_control(PXA2XX_CS_ASSERT);
+
+ /* Go baby, go */
+ write_SSSR(drv_data->clear_sr, reg);
+ DCSR(drv_data->rx_channel) |= DCSR_RUN;
+ DCSR(drv_data->tx_channel) |= DCSR_RUN;
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(chip->timeout, reg);
+ write_SSCR1(chip->cr1
+ | chip->dma_threshold
+ | drv_data->dma_cr1,
+ reg);
+ } else {
+ /* Ensure we have the correct interrupt handler */
+ drv_data->transfer_handler = interrupt_transfer;
+
+ /* Fix me, need to handle cs polarity */
+ drv_data->cs_control(PXA2XX_CS_ASSERT);
+
+ /* Go baby, go */
+ write_SSSR(drv_data->clear_sr, reg);
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(chip->timeout, reg);
+ write_SSCR1(chip->cr1
+ | chip->threshold
+ | drv_data->int_cr1,
+ reg);
+ }
+}
+
+static void pump_messages(void *data)
+{
+ struct driver_data *drv_data = data;
+ unsigned long flags;
+
+ /* Lock queue and check for queue work */
+ spin_lock_irqsave(&drv_data->lock, flags);
+ if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
+ drv_data->busy = 0;
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+ return;
+ }
+
+ /* Make sure we are not already running a message */
+ if (drv_data->cur_msg) {
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+ return;
+ }
+
+ /* Extract head of queue */
+ drv_data->cur_msg = list_entry(drv_data->queue.next,
+ struct spi_message, queue);
+ list_del_init(&drv_data->cur_msg->queue);
+
+ /* Initial message state*/
+ drv_data->cur_msg->state = START_STATE;
+ drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+ struct spi_transfer,
+ transfer_list);
+
+ /* Setup the SSP using the per chip configuration */
+ drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+ restore_state(drv_data);
+
+ /* Mark as busy and launch transfers */
+ tasklet_schedule(&drv_data->pump_transfers);
+
+ drv_data->busy = 1;
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+}
+
+static int transfer(struct spi_device *spi, struct spi_message *msg)
+{
+ struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+ unsigned long flags;
+
+ spin_lock_irqsave(&drv_data->lock, flags);
+
+ if (drv_data->run == QUEUE_STOPPED) {
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+ return -ESHUTDOWN;
+ }
+
+ msg->actual_length = 0;
+ msg->status = -EINPROGRESS;
+ msg->state = START_STATE;
+
+ list_add_tail(&msg->queue, &drv_data->queue);
+
+ if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
+ queue_work(drv_data->workqueue, &drv_data->pump_messages);
+
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+
+ return 0;
+}
+
+static int setup(struct spi_device *spi)
+{
+ struct pxa2xx_spi_chip *chip_info = NULL;
+ struct chip_data *chip;
+ struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+ unsigned int clk_div;
+
+ if (!spi->bits_per_word)
+ spi->bits_per_word = 8;
+
+ if (drv_data->ssp_type != PXA25x_SSP
+ && (spi->bits_per_word < 4 || spi->bits_per_word > 32))
+ return -EINVAL;
+ else if (spi->bits_per_word < 4 || spi->bits_per_word > 16)
+ return -EINVAL;
+
+ /* Only alloc (or use chip_info) on first setup */
+ chip = spi_get_ctldata(spi);
+ if (chip == NULL) {
+ chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->cs_control = null_cs_control;
+ chip->enable_dma = 0;
+ chip->timeout = SSP_TIMEOUT(1000);
+ chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1);
+ chip->dma_burst_size = drv_data->master_info->enable_dma ?
+ DCMD_BURST8 : 0;
+
+ chip_info = spi->controller_data;
+ }
+
+ /* chip_info isn't always needed */
+ if (chip_info) {
+ if (chip_info->cs_control)
+ chip->cs_control = chip_info->cs_control;
+
+ chip->timeout = SSP_TIMEOUT(chip_info->timeout_microsecs);
+
+ chip->threshold = SSCR1_RxTresh(chip_info->rx_threshold)
+ | SSCR1_TxTresh(chip_info->tx_threshold);
+
+ chip->enable_dma = chip_info->dma_burst_size != 0
+ && drv_data->master_info->enable_dma;
+ chip->dma_threshold = 0;
+
+ if (chip->enable_dma) {
+ if (chip_info->dma_burst_size <= 8) {
+ chip->dma_threshold = SSCR1_RxTresh(8)
+ | SSCR1_TxTresh(8);
+ chip->dma_burst_size = DCMD_BURST8;
+ } else if (chip_info->dma_burst_size <= 16) {
+ chip->dma_threshold = SSCR1_RxTresh(16)
+ | SSCR1_TxTresh(16);
+ chip->dma_burst_size = DCMD_BURST16;
+ } else {
+ chip->dma_threshold = SSCR1_RxTresh(32)
+ | SSCR1_TxTresh(32);
+ chip->dma_burst_size = DCMD_BURST32;
+ }
+ }
+
+
+ if (chip_info->enable_loopback)
+ chip->cr1 = SSCR1_LBM;
+ }
+
+ if (drv_data->ioaddr == SSP1_VIRT)
+ clk_div = SSP1_SerClkDiv(spi->max_speed_hz);
+ else if (drv_data->ioaddr == SSP2_VIRT)
+ clk_div = SSP2_SerClkDiv(spi->max_speed_hz);
+ else if (drv_data->ioaddr == SSP3_VIRT)
+ clk_div = SSP3_SerClkDiv(spi->max_speed_hz);
+ else
+ return -ENODEV;
+ chip->speed_hz = spi->max_speed_hz;
+
+ chip->cr0 = clk_div
+ | SSCR0_Motorola
+ | SSCR0_DataSize(spi->bits_per_word > 16 ?
+ spi->bits_per_word - 16 : spi->bits_per_word)
+ | SSCR0_SSE
+ | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
+ chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) << 4)
+ | (((spi->mode & SPI_CPOL) != 0) << 3);
+
+ /* NOTE: PXA25x_SSP _could_ use external clocking ... */
+ if (drv_data->ssp_type != PXA25x_SSP)
+ dev_dbg(&spi->dev, "%d bits/word, %d Hz, mode %d\n",
+ spi->bits_per_word,
+ (CLOCK_SPEED_HZ)
+ / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)),
+ spi->mode & 0x3);
+ else
+ dev_dbg(&spi->dev, "%d bits/word, %d Hz, mode %d\n",
+ spi->bits_per_word,
+ (CLOCK_SPEED_HZ/2)
+ / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)),
+ spi->mode & 0x3);
+
+ if (spi->bits_per_word <= 8) {
+ chip->n_bytes = 1;
+ chip->dma_width = DCMD_WIDTH1;
+ chip->read = u8_reader;
+ chip->write = u8_writer;
+ } else if (spi->bits_per_word <= 16) {
+ chip->n_bytes = 2;
+ chip->dma_width = DCMD_WIDTH2;
+ chip->read = u16_reader;
+ chip->write = u16_writer;
+ } else if (spi->bits_per_word <= 32) {
+ chip->cr0 |= SSCR0_EDSS;
+ chip->n_bytes = 4;
+ chip->dma_width = DCMD_WIDTH4;
+ chip->read = u32_reader;
+ chip->write = u32_writer;
+ } else {
+ dev_err(&spi->dev, "invalid wordsize\n");
+ kfree(chip);
+ return -ENODEV;
+ }
+ chip->bits_per_word = spi->bits_per_word;
+
+ spi_set_ctldata(spi, chip);
+
+ return 0;
+}
+
+static void cleanup(const struct spi_device *spi)
+{
+ struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
+
+ kfree(chip);
+}
+
+static int init_queue(struct driver_data *drv_data)
+{
+ INIT_LIST_HEAD(&drv_data->queue);
+ spin_lock_init(&drv_data->lock);
+
+ drv_data->run = QUEUE_STOPPED;
+ drv_data->busy = 0;
+
+ tasklet_init(&drv_data->pump_transfers,
+ pump_transfers, (unsigned long)drv_data);
+
+ INIT_WORK(&drv_data->pump_messages, pump_messages, drv_data);
+ drv_data->workqueue = create_singlethread_workqueue(
+ drv_data->master->cdev.dev->bus_id);
+ if (drv_data->workqueue == NULL)
+ return -EBUSY;
+
+ return 0;
+}
+
+static int start_queue(struct driver_data *drv_data)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&drv_data->lock, flags);
+
+ if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+ return -EBUSY;
+ }
+
+ drv_data->run = QUEUE_RUNNING;
+ drv_data->cur_msg = NULL;
+ drv_data->cur_transfer = NULL;
+ drv_data->cur_chip = NULL;
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+
+ queue_work(drv_data->workqueue, &drv_data->pump_messages);
+
+ return 0;
+}
+
+static int stop_queue(struct driver_data *drv_data)
+{
+ unsigned long flags;
+ unsigned limit = 500;
+ int status = 0;
+
+ spin_lock_irqsave(&drv_data->lock, flags);
+
+ /* This is a bit lame, but is optimized for the common execution path.
+ * A wait_queue on the drv_data->busy could be used, but then the common
+ * execution path (pump_messages) would be required to call wake_up or
+ * friends on every SPI message. Do this instead */
+ drv_data->run = QUEUE_STOPPED;
+ while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+ msleep(10);
+ spin_lock_irqsave(&drv_data->lock, flags);
+ }
+
+ if (!list_empty(&drv_data->queue) || drv_data->busy)
+ status = -EBUSY;
+
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+
+ return status;
+}
+
+static int destroy_queue(struct driver_data *drv_data)
+{
+ int status;
+
+ status = stop_queue(drv_data);
+ if (status != 0)
+ return status;
+
+ destroy_workqueue(drv_data->workqueue);
+
+ return 0;
+}
+
+static int pxa2xx_spi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pxa2xx_spi_master *platform_info;
+ struct spi_master *master;
+ struct driver_data *drv_data = 0;
+ struct resource *memory_resource;
+ int irq;
+ int status = 0;
+
+ platform_info = dev->platform_data;
+
+ if (platform_info->ssp_type == SSP_UNDEFINED) {
+ dev_err(&pdev->dev, "undefined SSP\n");
+ return -ENODEV;
+ }
+
+ /* Allocate master with space for drv_data and null dma buffer */
+ master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
+ if (!master) {
+ dev_err(&pdev->dev, "can not alloc spi_master\n");
+ return -ENOMEM;
+ }
+ drv_data = spi_master_get_devdata(master);
+ drv_data->master = master;
+ drv_data->master_info = platform_info;
+ drv_data->pdev = pdev;
+
+ master->bus_num = pdev->id;
+ master->num_chipselect = platform_info->num_chipselect;
+ master->cleanup = cleanup;
+ master->setup = setup;
+ master->transfer = transfer;
+
+ drv_data->ssp_type = platform_info->ssp_type;
+ drv_data->null_dma_buf = (u32 *)ALIGN((u32)(drv_data +
+ sizeof(struct driver_data)), 8);
+
+ /* Setup register addresses */
+ memory_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!memory_resource) {
+ dev_err(&pdev->dev, "memory resources not defined\n");
+ status = -ENODEV;
+ goto out_error_master_alloc;
+ }
+
+ drv_data->ioaddr = (void *)io_p2v((unsigned long)(memory_resource->start));
+ drv_data->ssdr_physical = memory_resource->start + 0x00000010;
+ if (platform_info->ssp_type == PXA25x_SSP) {
+ drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
+ drv_data->dma_cr1 = 0;
+ drv_data->clear_sr = SSSR_ROR;
+ drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR;
+ } else {
+ drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
+ drv_data->dma_cr1 = SSCR1_TSRE | SSCR1_RSRE | SSCR1_TINTE;
+ drv_data->clear_sr = SSSR_ROR | SSSR_TINT;
+ drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR;
+ }
+
+ /* Attach to IRQ */
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "irq resource not defined\n");
+ status = -ENODEV;
+ goto out_error_master_alloc;
+ }
+
+ status = request_irq(irq, ssp_int, 0, dev->bus_id, drv_data);
+ if (status < 0) {
+ dev_err(&pdev->dev, "can not get IRQ\n");
+ goto out_error_master_alloc;
+ }
+
+ /* Setup DMA if requested */
+ drv_data->tx_channel = -1;
+ drv_data->rx_channel = -1;
+ if (platform_info->enable_dma) {
+
+ /* Get two DMA channels (rx and tx) */
+ drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx",
+ DMA_PRIO_HIGH,
+ dma_handler,
+ drv_data);
+ if (drv_data->rx_channel < 0) {
+ dev_err(dev, "problem (%d) requesting rx channel\n",
+ drv_data->rx_channel);
+ status = -ENODEV;
+ goto out_error_irq_alloc;
+ }
+ drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx",
+ DMA_PRIO_MEDIUM,
+ dma_handler,
+ drv_data);
+ if (drv_data->tx_channel < 0) {
+ dev_err(dev, "problem (%d) requesting tx channel\n",
+ drv_data->tx_channel);
+ status = -ENODEV;
+ goto out_error_dma_alloc;
+ }
+
+ if (drv_data->ioaddr == SSP1_VIRT) {
+ DRCMRRXSSDR = DRCMR_MAPVLD
+ | drv_data->rx_channel;
+ DRCMRTXSSDR = DRCMR_MAPVLD
+ | drv_data->tx_channel;
+ } else if (drv_data->ioaddr == SSP2_VIRT) {
+ DRCMRRXSS2DR = DRCMR_MAPVLD
+ | drv_data->rx_channel;
+ DRCMRTXSS2DR = DRCMR_MAPVLD
+ | drv_data->tx_channel;
+ } else if (drv_data->ioaddr == SSP3_VIRT) {
+ DRCMRRXSS3DR = DRCMR_MAPVLD
+ | drv_data->rx_channel;
+ DRCMRTXSS3DR = DRCMR_MAPVLD
+ | drv_data->tx_channel;
+ } else {
+ dev_err(dev, "bad SSP type\n");
+ goto out_error_dma_alloc;
+ }
+ }
+
+ /* Enable SOC clock */
+ pxa_set_cken(platform_info->clock_enable, 1);
+
+ /* Load default SSP configuration */
+ write_SSCR0(0, drv_data->ioaddr);
+ write_SSCR1(SSCR1_RxTresh(4) | SSCR1_TxTresh(12), drv_data->ioaddr);
+ write_SSCR0(SSCR0_SerClkDiv(2)
+ | SSCR0_Motorola
+ | SSCR0_DataSize(8),
+ drv_data->ioaddr);
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(0, drv_data->ioaddr);
+ write_SSPSP(0, drv_data->ioaddr);
+
+ /* Initial and start queue */
+ status = init_queue(drv_data);
+ if (status != 0) {
+ dev_err(&pdev->dev, "problem initializing queue\n");
+ goto out_error_clock_enabled;
+ }
+ status = start_queue(drv_data);
+ if (status != 0) {
+ dev_err(&pdev->dev, "problem starting queue\n");
+ goto out_error_clock_enabled;
+ }
+
+ /* Register with the SPI framework */
+ platform_set_drvdata(pdev, drv_data);
+ status = spi_register_master(master);
+ if (status != 0) {
+ dev_err(&pdev->dev, "problem registering spi master\n");
+ goto out_error_queue_alloc;
+ }
+
+ return status;
+
+out_error_queue_alloc:
+ destroy_queue(drv_data);
+
+out_error_clock_enabled:
+ pxa_set_cken(platform_info->clock_enable, 0);
+
+out_error_dma_alloc:
+ if (drv_data->tx_channel != -1)
+ pxa_free_dma(drv_data->tx_channel);
+ if (drv_data->rx_channel != -1)
+ pxa_free_dma(drv_data->rx_channel);
+
+out_error_irq_alloc:
+ free_irq(irq, drv_data);
+
+out_error_master_alloc:
+ spi_master_put(master);
+ return status;
+}
+
+static int pxa2xx_spi_remove(struct platform_device *pdev)
+{
+ struct driver_data *drv_data = platform_get_drvdata(pdev);
+ int irq;
+ int status = 0;
+
+ if (!drv_data)
+ return 0;
+
+ /* Remove the queue */
+ status = destroy_queue(drv_data);
+ if (status != 0)
+ return status;
+
+ /* Disable the SSP at the peripheral and SOC level */
+ write_SSCR0(0, drv_data->ioaddr);
+ pxa_set_cken(drv_data->master_info->clock_enable, 0);
+
+ /* Release DMA */
+ if (drv_data->master_info->enable_dma) {
+ if (drv_data->ioaddr == SSP1_VIRT) {
+ DRCMRRXSSDR = 0;
+ DRCMRTXSSDR = 0;
+ } else if (drv_data->ioaddr == SSP2_VIRT) {
+ DRCMRRXSS2DR = 0;
+ DRCMRTXSS2DR = 0;
+ } else if (drv_data->ioaddr == SSP3_VIRT) {
+ DRCMRRXSS3DR = 0;
+ DRCMRTXSS3DR = 0;
+ }
+ pxa_free_dma(drv_data->tx_channel);
+ pxa_free_dma(drv_data->rx_channel);
+ }
+
+ /* Release IRQ */
+ irq = platform_get_irq(pdev, 0);
+ if (irq >= 0)
+ free_irq(irq, drv_data);
+
+ /* Disconnect from the SPI framework */
+ spi_unregister_master(drv_data->master);
+
+ /* Prevent double remove */
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static void pxa2xx_spi_shutdown(struct platform_device *pdev)
+{
+ int status = 0;
+
+ if ((status = pxa2xx_spi_remove(pdev)) != 0)
+ dev_err(&pdev->dev, "shutdown failed with %d\n", status);
+}
+
+#ifdef CONFIG_PM
+static int suspend_devices(struct device *dev, void *pm_message)
+{
+ pm_message_t *state = pm_message;
+
+ if (dev->power.power_state.event != state->event) {
+ dev_warn(dev, "pm state does not match request\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct driver_data *drv_data = platform_get_drvdata(pdev);
+ int status = 0;
+
+ /* Check all childern for current power state */
+ if (device_for_each_child(&pdev->dev, &state, suspend_devices) != 0) {
+ dev_warn(&pdev->dev, "suspend aborted\n");
+ return -1;
+ }
+
+ status = stop_queue(drv_data);
+ if (status != 0)
+ return status;
+ write_SSCR0(0, drv_data->ioaddr);
+ pxa_set_cken(drv_data->master_info->clock_enable, 0);
+
+ return 0;
+}
+
+static int pxa2xx_spi_resume(struct platform_device *pdev)
+{
+ struct driver_data *drv_data = platform_get_drvdata(pdev);
+ int status = 0;
+
+ /* Enable the SSP clock */
+ pxa_set_cken(drv_data->master_info->clock_enable, 1);
+
+ /* Start the queue running */
+ status = start_queue(drv_data);
+ if (status != 0) {
+ dev_err(&pdev->dev, "problem starting queue (%d)\n", status);
+ return status;
+ }
+
+ return 0;
+}
+#else
+#define pxa2xx_spi_suspend NULL
+#define pxa2xx_spi_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver driver = {
+ .driver = {
+ .name = "pxa2xx-spi",
+ .bus = &platform_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = pxa2xx_spi_probe,
+ .remove = __devexit_p(pxa2xx_spi_remove),
+ .shutdown = pxa2xx_spi_shutdown,
+ .suspend = pxa2xx_spi_suspend,
+ .resume = pxa2xx_spi_resume,
+};
+
+static int __init pxa2xx_spi_init(void)
+{
+ platform_driver_register(&driver);
+
+ return 0;
+}
+module_init(pxa2xx_spi_init);
+
+static void __exit pxa2xx_spi_exit(void)
+{
+ platform_driver_unregister(&driver);
+}
+module_exit(pxa2xx_spi_exit);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 94f5e8ed83a..1cea4a6799f 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -338,18 +338,18 @@ static struct class spi_master_class = {
* spi_alloc_master - allocate SPI master controller
* @dev: the controller, possibly using the platform_bus
* @size: how much driver-private data to preallocate; the pointer to this
- * memory is in the class_data field of the returned class_device,
+ * memory is in the class_data field of the returned class_device,
* accessible with spi_master_get_devdata().
*
* This call is used only by SPI master controller drivers, which are the
* only ones directly touching chip registers. It's how they allocate
- * an spi_master structure, prior to calling spi_add_master().
+ * an spi_master structure, prior to calling spi_register_master().
*
* This must be called from context that can sleep. It returns the SPI
* master structure on success, else NULL.
*
* The caller is responsible for assigning the bus number and initializing
- * the master's methods before calling spi_add_master(); and (after errors
+ * the master's methods before calling spi_register_master(); and (after errors
* adding the device) calling spi_master_put() to prevent a memory leak.
*/
struct spi_master * __init_or_module
@@ -395,7 +395,7 @@ EXPORT_SYMBOL_GPL(spi_alloc_master);
int __init_or_module
spi_register_master(struct spi_master *master)
{
- static atomic_t dyn_bus_id = ATOMIC_INIT(0);
+ static atomic_t dyn_bus_id = ATOMIC_INIT((1<<16) - 1);
struct device *dev = master->cdev.dev;
int status = -ENODEV;
int dynamic = 0;
@@ -404,7 +404,7 @@ spi_register_master(struct spi_master *master)
return -ENODEV;
/* convention: dynamically assigned bus IDs count down from the max */
- if (master->bus_num == 0) {
+ if (master->bus_num < 0) {
master->bus_num = atomic_dec_return(&dyn_bus_id);
dynamic = 1;
}
@@ -522,7 +522,8 @@ int spi_sync(struct spi_device *spi, struct spi_message *message)
}
EXPORT_SYMBOL_GPL(spi_sync);
-#define SPI_BUFSIZ (SMP_CACHE_BYTES)
+/* portable code must never pass more than 32 bytes */
+#define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
static u8 *buf;
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index f037e559326..dd2f950b21a 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -138,6 +138,45 @@ static unsigned bitbang_txrx_32(
return t->len - count;
}
+int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+{
+ struct spi_bitbang_cs *cs = spi->controller_state;
+ u8 bits_per_word;
+ u32 hz;
+
+ if (t) {
+ bits_per_word = t->bits_per_word;
+ hz = t->speed_hz;
+ } else {
+ bits_per_word = 0;
+ hz = 0;
+ }
+
+ /* spi_transfer level calls that work per-word */
+ if (!bits_per_word)
+ bits_per_word = spi->bits_per_word;
+ if (bits_per_word <= 8)
+ cs->txrx_bufs = bitbang_txrx_8;
+ else if (bits_per_word <= 16)
+ cs->txrx_bufs = bitbang_txrx_16;
+ else if (bits_per_word <= 32)
+ cs->txrx_bufs = bitbang_txrx_32;
+ else
+ return -EINVAL;
+
+ /* nsecs = (clock period)/2 */
+ if (!hz)
+ hz = spi->max_speed_hz;
+ if (hz) {
+ cs->nsecs = (1000000000/2) / hz;
+ if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_setup_transfer);
+
/**
* spi_bitbang_setup - default setup for per-word I/O loops
*/
@@ -145,8 +184,16 @@ int spi_bitbang_setup(struct spi_device *spi)
{
struct spi_bitbang_cs *cs = spi->controller_state;
struct spi_bitbang *bitbang;
+ int retval;
- if (!spi->max_speed_hz)
+ 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.
+ */
+ if ((spi->mode & SPI_LSB_FIRST) != 0)
return -EINVAL;
if (!cs) {
@@ -155,32 +202,20 @@ int spi_bitbang_setup(struct spi_device *spi)
return -ENOMEM;
spi->controller_state = cs;
}
- bitbang = spi_master_get_devdata(spi->master);
if (!spi->bits_per_word)
spi->bits_per_word = 8;
- /* spi_transfer level calls that work per-word */
- if (spi->bits_per_word <= 8)
- cs->txrx_bufs = bitbang_txrx_8;
- else if (spi->bits_per_word <= 16)
- cs->txrx_bufs = bitbang_txrx_16;
- else if (spi->bits_per_word <= 32)
- cs->txrx_bufs = bitbang_txrx_32;
- else
- return -EINVAL;
-
/* per-word shift register access, in hardware or bitbanging */
cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];
if (!cs->txrx_word)
return -EINVAL;
- /* nsecs = (clock period)/2 */
- cs->nsecs = (1000000000/2) / (spi->max_speed_hz);
- if (cs->nsecs > MAX_UDELAY_MS * 1000)
- return -EINVAL;
+ retval = spi_bitbang_setup_transfer(spi, NULL);
+ if (retval < 0)
+ return retval;
- dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n",
+ dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
__FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA),
spi->bits_per_word, 2 * cs->nsecs);
@@ -246,6 +281,8 @@ static void bitbang_work(void *_bitbang)
unsigned tmp;
unsigned cs_change;
int status;
+ int (*setup_transfer)(struct spi_device *,
+ struct spi_transfer *);
m = container_of(bitbang->queue.next, struct spi_message,
queue);
@@ -262,6 +299,7 @@ static void bitbang_work(void *_bitbang)
tmp = 0;
cs_change = 1;
status = 0;
+ setup_transfer = NULL;
list_for_each_entry (t, &m->transfers, transfer_list) {
if (bitbang->shutdown) {
@@ -269,6 +307,20 @@ static void bitbang_work(void *_bitbang)
break;
}
+ /* override or restore speed and wordsize */
+ if (t->speed_hz || t->bits_per_word) {
+ setup_transfer = bitbang->setup_transfer;
+ if (!setup_transfer) {
+ status = -ENOPROTOOPT;
+ break;
+ }
+ }
+ if (setup_transfer) {
+ status = setup_transfer(spi, t);
+ if (status < 0)
+ break;
+ }
+
/* set up default clock polarity, and activate chip;
* this implicitly updates clock and spi modes as
* previously recorded for this device via setup().
@@ -325,6 +377,10 @@ static void bitbang_work(void *_bitbang)
m->status = status;
m->complete(m->context);
+ /* restore speed and wordsize */
+ if (setup_transfer)
+ setup_transfer(spi, NULL);
+
/* normally deactivate chipselect ... unless no error and
* cs_change has hinted that the next message will probably
* be for this chip too.
@@ -348,6 +404,7 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
{
struct spi_bitbang *bitbang;
unsigned long flags;
+ int status = 0;
m->actual_length = 0;
m->status = -EINPROGRESS;
@@ -357,11 +414,15 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
return -ESHUTDOWN;
spin_lock_irqsave(&bitbang->lock, flags);
- list_add_tail(&m->queue, &bitbang->queue);
- queue_work(bitbang->workqueue, &bitbang->work);
+ if (!spi->max_speed_hz)
+ status = -ENETDOWN;
+ else {
+ list_add_tail(&m->queue, &bitbang->queue);
+ queue_work(bitbang->workqueue, &bitbang->work);
+ }
spin_unlock_irqrestore(&bitbang->lock, flags);
- return 0;
+ return status;
}
EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
@@ -406,6 +467,9 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
bitbang->use_dma = 0;
bitbang->txrx_bufs = spi_bitbang_bufs;
if (!bitbang->master->setup) {
+ if (!bitbang->setup_transfer)
+ bitbang->setup_transfer =
+ spi_bitbang_setup_transfer;
bitbang->master->setup = spi_bitbang_setup;
bitbang->master->cleanup = spi_bitbang_cleanup;
}
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c
index ff9e5faa4dc..a006a1ee27a 100644
--- a/drivers/spi/spi_butterfly.c
+++ b/drivers/spi/spi_butterfly.c
@@ -321,6 +321,7 @@ static void butterfly_attach(struct parport *p)
* (firmware resets at45, acts as spi slave) or neither (we ignore
* both, AVR uses AT45). Here we expect firmware for the first option.
*/
+
pp->info[0].max_speed_hz = 15 * 1000 * 1000;
strcpy(pp->info[0].modalias, "mtd_dataflash");
pp->info[0].platform_data = &flash;
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
new file mode 100644
index 00000000000..5d92a7e5cb4
--- /dev/null
+++ b/drivers/spi/spi_mpc83xx.c
@@ -0,0 +1,483 @@
+/*
+ * MPC83xx SPI controller driver.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright (C) 2006 Polycom, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+
+/* SPI Controller registers */
+struct mpc83xx_spi_reg {
+ u8 res1[0x20];
+ __be32 mode;
+ __be32 event;
+ __be32 mask;
+ __be32 command;
+ __be32 transmit;
+ __be32 receive;
+};
+
+/* SPI Controller mode register definitions */
+#define SPMODE_CI_INACTIVEHIGH (1 << 29)
+#define SPMODE_CP_BEGIN_EDGECLK (1 << 28)
+#define SPMODE_DIV16 (1 << 27)
+#define SPMODE_REV (1 << 26)
+#define SPMODE_MS (1 << 25)
+#define SPMODE_ENABLE (1 << 24)
+#define SPMODE_LEN(x) ((x) << 20)
+#define SPMODE_PM(x) ((x) << 16)
+
+/*
+ * Default for SPI Mode:
+ * SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
+ */
+#define SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
+ SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
+
+/* SPIE register values */
+#define SPIE_NE 0x00000200 /* Not empty */
+#define SPIE_NF 0x00000100 /* Not full */
+
+/* SPIM register values */
+#define SPIM_NE 0x00000200 /* Not empty */
+#define SPIM_NF 0x00000100 /* Not full */
+
+/* SPI Controller driver's private data. */
+struct mpc83xx_spi {
+ /* bitbang has to be first */
+ struct spi_bitbang bitbang;
+ struct completion done;
+
+ struct mpc83xx_spi_reg __iomem *base;
+
+ /* rx & tx bufs from the spi_transfer */
+ const void *tx;
+ void *rx;
+
+ /* functions to deal with different sized buffers */
+ void (*get_rx) (u32 rx_data, struct mpc83xx_spi *);
+ u32(*get_tx) (struct mpc83xx_spi *);
+
+ unsigned int count;
+ u32 irq;
+
+ unsigned nsecs; /* (clock cycle time)/2 */
+
+ u32 sysclk;
+ void (*activate_cs) (u8 cs, u8 polarity);
+ void (*deactivate_cs) (u8 cs, u8 polarity);
+};
+
+static inline void mpc83xx_spi_write_reg(__be32 __iomem * reg, u32 val)
+{
+ out_be32(reg, val);
+}
+
+static inline u32 mpc83xx_spi_read_reg(__be32 __iomem * reg)
+{
+ return in_be32(reg);
+}
+
+#define MPC83XX_SPI_RX_BUF(type) \
+void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \
+{ \
+ type * rx = mpc83xx_spi->rx; \
+ *rx++ = (type)data; \
+ mpc83xx_spi->rx = rx; \
+}
+
+#define MPC83XX_SPI_TX_BUF(type) \
+u32 mpc83xx_spi_tx_buf_##type(struct mpc83xx_spi *mpc83xx_spi) \
+{ \
+ u32 data; \
+ const type * tx = mpc83xx_spi->tx; \
+ data = *tx++; \
+ mpc83xx_spi->tx = tx; \
+ return data; \
+}
+
+MPC83XX_SPI_RX_BUF(u8)
+MPC83XX_SPI_RX_BUF(u16)
+MPC83XX_SPI_RX_BUF(u32)
+MPC83XX_SPI_TX_BUF(u8)
+MPC83XX_SPI_TX_BUF(u16)
+MPC83XX_SPI_TX_BUF(u32)
+
+static void mpc83xx_spi_chipselect(struct spi_device *spi, int value)
+{
+ struct mpc83xx_spi *mpc83xx_spi;
+ u8 pol = spi->mode & SPI_CS_HIGH ? 1 : 0;
+
+ mpc83xx_spi = spi_master_get_devdata(spi->master);
+
+ if (value == BITBANG_CS_INACTIVE) {
+ if (mpc83xx_spi->deactivate_cs)
+ mpc83xx_spi->deactivate_cs(spi->chip_select, pol);
+ }
+
+ if (value == BITBANG_CS_ACTIVE) {
+ u32 regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode);
+ u32 len = spi->bits_per_word;
+ if (len == 32)
+ len = 0;
+ else
+ len = len - 1;
+
+ /* mask out bits we are going to set */
+ regval &= ~0x38ff0000;
+
+ if (spi->mode & SPI_CPHA)
+ regval |= SPMODE_CP_BEGIN_EDGECLK;
+ if (spi->mode & SPI_CPOL)
+ regval |= SPMODE_CI_INACTIVEHIGH;
+
+ regval |= SPMODE_LEN(len);
+
+ if ((mpc83xx_spi->sysclk / spi->max_speed_hz) >= 64) {
+ u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 64);
+ regval |= SPMODE_PM(pm) | SPMODE_DIV16;
+ } else {
+ u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 4);
+ regval |= SPMODE_PM(pm);
+ }
+
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);
+ if (mpc83xx_spi->activate_cs)
+ mpc83xx_spi->activate_cs(spi->chip_select, pol);
+ }
+}
+
+static
+int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+{
+ struct mpc83xx_spi *mpc83xx_spi;
+ u32 regval;
+ u8 bits_per_word;
+ u32 hz;
+
+ mpc83xx_spi = spi_master_get_devdata(spi->master);
+
+ if (t) {
+ bits_per_word = t->bits_per_word;
+ hz = t->speed_hz;
+ } else {
+ bits_per_word = 0;
+ hz = 0;
+ }
+
+ /* spi_transfer level calls that work per-word */
+ if (!bits_per_word)
+ bits_per_word = spi->bits_per_word;
+
+ /* Make sure its a bit width we support [4..16, 32] */
+ if ((bits_per_word < 4)
+ || ((bits_per_word > 16) && (bits_per_word != 32)))
+ return -EINVAL;
+
+ if (bits_per_word <= 8) {
+ mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
+ mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
+ } else if (bits_per_word <= 16) {
+ mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u16;
+ mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u16;
+ } else if (bits_per_word <= 32) {
+ mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u32;
+ mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u32;
+ } else
+ return -EINVAL;
+
+ /* nsecs = (clock period)/2 */
+ if (!hz)
+ hz = spi->max_speed_hz;
+ mpc83xx_spi->nsecs = (1000000000 / 2) / hz;
+ if (mpc83xx_spi->nsecs > MAX_UDELAY_MS * 1000)
+ return -EINVAL;
+
+ if (bits_per_word == 32)
+ bits_per_word = 0;
+ else
+ bits_per_word = bits_per_word - 1;
+
+ regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode);
+
+ /* Mask out bits_per_wordgth */
+ regval &= 0xff0fffff;
+ regval |= SPMODE_LEN(bits_per_word);
+
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);
+
+ return 0;
+}
+
+static int mpc83xx_spi_setup(struct spi_device *spi)
+{
+ struct spi_bitbang *bitbang;
+ struct mpc83xx_spi *mpc83xx_spi;
+ int retval;
+
+ if (!spi->max_speed_hz)
+ return -EINVAL;
+
+ bitbang = spi_master_get_devdata(spi->master);
+ mpc83xx_spi = spi_master_get_devdata(spi->master);
+
+ if (!spi->bits_per_word)
+ spi->bits_per_word = 8;
+
+ retval = mpc83xx_spi_setup_transfer(spi, NULL);
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n",
+ __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA),
+ spi->bits_per_word, 2 * mpc83xx_spi->nsecs);
+
+ /* NOTE we _need_ to call chipselect() early, ideally with adapter
+ * setup, unless the hardware defaults cooperate to avoid confusion
+ * between normal (active low) and inverted chipselects.
+ */
+
+ /* deselect chip (low or high) */
+ spin_lock(&bitbang->lock);
+ if (!bitbang->busy) {
+ bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+ ndelay(mpc83xx_spi->nsecs);
+ }
+ spin_unlock(&bitbang->lock);
+
+ return 0;
+}
+
+static int mpc83xx_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+ struct mpc83xx_spi *mpc83xx_spi;
+ u32 word;
+
+ mpc83xx_spi = spi_master_get_devdata(spi->master);
+
+ mpc83xx_spi->tx = t->tx_buf;
+ mpc83xx_spi->rx = t->rx_buf;
+ mpc83xx_spi->count = t->len;
+ INIT_COMPLETION(mpc83xx_spi->done);
+
+ /* enable rx ints */
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, SPIM_NE);
+
+ /* transmit word */
+ word = mpc83xx_spi->get_tx(mpc83xx_spi);
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->transmit, word);
+
+ wait_for_completion(&mpc83xx_spi->done);
+
+ /* disable rx ints */
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, 0);
+
+ return t->len - mpc83xx_spi->count;
+}
+
+irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data,
+ struct pt_regs * ptregs)
+{
+ struct mpc83xx_spi *mpc83xx_spi = context_data;
+ u32 event;
+ irqreturn_t ret = IRQ_NONE;
+
+ /* Get interrupt events(tx/rx) */
+ event = mpc83xx_spi_read_reg(&mpc83xx_spi->base->event);
+
+ /* We need handle RX first */
+ if (event & SPIE_NE) {
+ u32 rx_data = mpc83xx_spi_read_reg(&mpc83xx_spi->base->receive);
+
+ if (mpc83xx_spi->rx)
+ mpc83xx_spi->get_rx(rx_data, mpc83xx_spi);
+
+ ret = IRQ_HANDLED;
+ }
+
+ if ((event & SPIE_NF) == 0)
+ /* spin until TX is done */
+ while (((event =
+ mpc83xx_spi_read_reg(&mpc83xx_spi->base->event)) &
+ SPIE_NF) == 0)
+ cpu_relax();
+
+ mpc83xx_spi->count -= 1;
+ if (mpc83xx_spi->count) {
+ if (mpc83xx_spi->tx) {
+ u32 word = mpc83xx_spi->get_tx(mpc83xx_spi);
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->transmit,
+ word);
+ }
+ } else {
+ complete(&mpc83xx_spi->done);
+ }
+
+ /* Clear the events */
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->event, event);
+
+ return ret;
+}
+
+static int __init mpc83xx_spi_probe(struct platform_device *dev)
+{
+ struct spi_master *master;
+ struct mpc83xx_spi *mpc83xx_spi;
+ struct fsl_spi_platform_data *pdata;
+ struct resource *r;
+ u32 regval;
+ int ret = 0;
+
+ /* Get resources(memory, IRQ) associated with the device */
+ master = spi_alloc_master(&dev->dev, sizeof(struct mpc83xx_spi));
+
+ if (master == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ platform_set_drvdata(dev, master);
+ pdata = dev->dev.platform_data;
+
+ if (pdata == NULL) {
+ ret = -ENODEV;
+ goto free_master;
+ }
+
+ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (r == NULL) {
+ 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;
+ mpc83xx_spi->bitbang.setup_transfer = mpc83xx_spi_setup_transfer;
+ mpc83xx_spi->bitbang.txrx_bufs = mpc83xx_spi_bufs;
+ mpc83xx_spi->sysclk = pdata->sysclk;
+ mpc83xx_spi->activate_cs = pdata->activate_cs;
+ mpc83xx_spi->deactivate_cs = pdata->deactivate_cs;
+ mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
+ mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
+
+ mpc83xx_spi->bitbang.master->setup = mpc83xx_spi_setup;
+ init_completion(&mpc83xx_spi->done);
+
+ mpc83xx_spi->base = ioremap(r->start, r->end - r->start + 1);
+ if (mpc83xx_spi->base == NULL) {
+ ret = -ENOMEM;
+ goto put_master;
+ }
+
+ mpc83xx_spi->irq = platform_get_irq(dev, 0);
+
+ if (mpc83xx_spi->irq < 0) {
+ ret = -ENXIO;
+ goto unmap_io;
+ }
+
+ /* Register for SPI Interrupt */
+ ret = request_irq(mpc83xx_spi->irq, mpc83xx_spi_irq,
+ 0, "mpc83xx_spi", mpc83xx_spi);
+
+ if (ret != 0)
+ goto unmap_io;
+
+ master->bus_num = pdata->bus_num;
+ master->num_chipselect = pdata->max_chipselect;
+
+ /* SPI controller initializations */
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, 0);
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, 0);
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->command, 0);
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->event, 0xffffffff);
+
+ /* Enable SPI interface */
+ regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+ mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);
+
+ ret = spi_bitbang_start(&mpc83xx_spi->bitbang);
+
+ if (ret != 0)
+ goto free_irq;
+
+ printk(KERN_INFO
+ "%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)\n",
+ dev->dev.bus_id, mpc83xx_spi->base, mpc83xx_spi->irq);
+
+ return ret;
+
+free_irq:
+ free_irq(mpc83xx_spi->irq, mpc83xx_spi);
+unmap_io:
+ iounmap(mpc83xx_spi->base);
+put_master:
+ spi_master_put(master);
+free_master:
+ kfree(master);
+err:
+ return ret;
+}
+
+static int __devexit mpc83xx_spi_remove(struct platform_device *dev)
+{
+ struct mpc83xx_spi *mpc83xx_spi;
+ struct spi_master *master;
+
+ master = platform_get_drvdata(dev);
+ mpc83xx_spi = spi_master_get_devdata(master);
+
+ spi_bitbang_stop(&mpc83xx_spi->bitbang);
+ free_irq(mpc83xx_spi->irq, mpc83xx_spi);
+ iounmap(mpc83xx_spi->base);
+ spi_master_put(mpc83xx_spi->bitbang.master);
+
+ return 0;
+}
+
+static struct platform_driver mpc83xx_spi_driver = {
+ .probe = mpc83xx_spi_probe,
+ .remove = __devexit_p(mpc83xx_spi_remove),
+ .driver = {
+ .name = "mpc83xx_spi",
+ },
+};
+
+static int __init mpc83xx_spi_init(void)
+{
+ return platform_driver_register(&mpc83xx_spi_driver);
+}
+
+static void __exit mpc83xx_spi_exit(void)
+{
+ platform_driver_unregister(&mpc83xx_spi_driver);
+}
+
+module_init(mpc83xx_spi_init);
+module_exit(mpc83xx_spi_exit);
+
+MODULE_AUTHOR("Kumar Gala");
+MODULE_DESCRIPTION("Simple MPC83xx SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
new file mode 100644
index 00000000000..5fc14563ee3
--- /dev/null
+++ b/drivers/spi/spi_s3c24xx.c
@@ -0,0 +1,453 @@
+/* linux/drivers/spi/spi_s3c24xx.c
+ *
+ * Copyright (c) 2006 Ben Dooks
+ * Copyright (c) 2006 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.
+ *
+*/
+
+
+//#define DEBUG
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/hardware.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-spi.h>
+#include <asm/arch/spi.h>
+
+struct s3c24xx_spi {
+ /* bitbang has to be first */
+ struct spi_bitbang bitbang;
+ struct completion done;
+
+ void __iomem *regs;
+ int irq;
+ int len;
+ int count;
+
+ /* data buffers */
+ const unsigned char *tx;
+ unsigned char *rx;
+
+ struct clk *clk;
+ struct resource *ioarea;
+ struct spi_master *master;
+ struct spi_device *curdev;
+ struct device *dev;
+ struct s3c2410_spi_info *pdata;
+};
+
+#define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT)
+#define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP)
+
+static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev)
+{
+ return spi_master_get_devdata(sdev->master);
+}
+
+static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
+{
+ struct s3c24xx_spi *hw = to_hw(spi);
+ unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
+ unsigned int spcon;
+
+ switch (value) {
+ case BITBANG_CS_INACTIVE:
+ if (hw->pdata->set_cs)
+ hw->pdata->set_cs(hw->pdata, value, cspol);
+ else
+ s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol ^ 1);
+ break;
+
+ case BITBANG_CS_ACTIVE:
+ spcon = readb(hw->regs + S3C2410_SPCON);
+
+ if (spi->mode & SPI_CPHA)
+ spcon |= S3C2410_SPCON_CPHA_FMTB;
+ else
+ spcon &= ~S3C2410_SPCON_CPHA_FMTB;
+
+ if (spi->mode & SPI_CPOL)
+ spcon |= S3C2410_SPCON_CPOL_HIGH;
+ else
+ spcon &= ~S3C2410_SPCON_CPOL_HIGH;
+
+ spcon |= S3C2410_SPCON_ENSCK;
+
+ /* write new configration */
+
+ writeb(spcon, hw->regs + S3C2410_SPCON);
+
+ if (hw->pdata->set_cs)
+ hw->pdata->set_cs(hw->pdata, value, cspol);
+ else
+ s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol);
+
+ break;
+
+ }
+}
+
+static int s3c24xx_spi_setupxfer(struct spi_device *spi,
+ struct spi_transfer *t)
+{
+ struct s3c24xx_spi *hw = to_hw(spi);
+ unsigned int bpw;
+ unsigned int hz;
+ unsigned int div;
+
+ bpw = t ? t->bits_per_word : spi->bits_per_word;
+ hz = t ? t->speed_hz : spi->max_speed_hz;
+
+ if (bpw != 8) {
+ dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
+ return -EINVAL;
+ }
+
+ div = clk_get_rate(hw->clk) / hz;
+
+ /* is clk = pclk / (2 * (pre+1)), or is it
+ * clk = (pclk * 2) / ( pre + 1) */
+
+ div = (div / 2) - 1;
+
+ if (div < 0)
+ div = 1;
+
+ if (div > 255)
+ div = 255;
+
+ dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", div, hz);
+ writeb(div, hw->regs + S3C2410_SPPRE);
+
+ spin_lock(&hw->bitbang.lock);
+ if (!hw->bitbang.busy) {
+ hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
+ /* need to ndelay for 0.5 clocktick ? */
+ }
+ spin_unlock(&hw->bitbang.lock);
+
+ return 0;
+}
+
+static int s3c24xx_spi_setup(struct spi_device *spi)
+{
+ int ret;
+
+ if (!spi->bits_per_word)
+ spi->bits_per_word = 8;
+
+ if ((spi->mode & SPI_LSB_FIRST) != 0)
+ return -EINVAL;
+
+ ret = s3c24xx_spi_setupxfer(spi, NULL);
+ if (ret < 0) {
+ dev_err(&spi->dev, "setupxfer returned %d\n", ret);
+ return ret;
+ }
+
+ dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n",
+ __FUNCTION__, spi->mode, spi->bits_per_word,
+ spi->max_speed_hz);
+
+ return 0;
+}
+
+static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
+{
+ return hw->tx ? hw->tx[count] : 0xff;
+}
+
+static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+ struct s3c24xx_spi *hw = to_hw(spi);
+
+ dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
+ t->tx_buf, t->rx_buf, t->len);
+
+ hw->tx = t->tx_buf;
+ hw->rx = t->rx_buf;
+ hw->len = t->len;
+ hw->count = 0;
+
+ /* send the first byte */
+ writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);
+ wait_for_completion(&hw->done);
+
+ return hw->count;
+}
+
+static irqreturn_t s3c24xx_spi_irq(int irq, void *dev, struct pt_regs *regs)
+{
+ struct s3c24xx_spi *hw = dev;
+ unsigned int spsta = readb(hw->regs + S3C2410_SPSTA);
+ unsigned int count = hw->count;
+
+ if (spsta & S3C2410_SPSTA_DCOL) {
+ dev_dbg(hw->dev, "data-collision\n");
+ complete(&hw->done);
+ goto irq_done;
+ }
+
+ if (!(spsta & S3C2410_SPSTA_READY)) {
+ dev_dbg(hw->dev, "spi not ready for tx?\n");
+ complete(&hw->done);
+ goto irq_done;
+ }
+
+ hw->count++;
+
+ if (hw->rx)
+ hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
+
+ count++;
+
+ if (count < hw->len)
+ writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
+ else
+ complete(&hw->done);
+
+ irq_done:
+ return IRQ_HANDLED;
+}
+
+static int s3c24xx_spi_probe(struct platform_device *pdev)
+{
+ struct s3c24xx_spi *hw;
+ struct spi_master *master;
+ struct spi_board_info *bi;
+ struct resource *res;
+ int err = 0;
+ int i;
+
+ master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
+ if (master == NULL) {
+ dev_err(&pdev->dev, "No memory for spi_master\n");
+ err = -ENOMEM;
+ goto err_nomem;
+ }
+
+ hw = spi_master_get_devdata(master);
+ memset(hw, 0, sizeof(struct s3c24xx_spi));
+
+ hw->master = spi_master_get(master);
+ hw->pdata = pdev->dev.platform_data;
+ hw->dev = &pdev->dev;
+
+ if (hw->pdata == NULL) {
+ dev_err(&pdev->dev, "No platform data supplied\n");
+ err = -ENOENT;
+ goto err_no_pdata;
+ }
+
+ platform_set_drvdata(pdev, hw);
+ init_completion(&hw->done);
+
+ /* setup the state for the bitbang driver */
+
+ hw->bitbang.master = hw->master;
+ hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer;
+ hw->bitbang.chipselect = s3c24xx_spi_chipsel;
+ hw->bitbang.txrx_bufs = s3c24xx_spi_txrx;
+ hw->bitbang.master->setup = s3c24xx_spi_setup;
+
+ dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
+
+ /* find and map our resources */
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
+ err = -ENOENT;
+ goto err_no_iores;
+ }
+
+ hw->ioarea = request_mem_region(res->start, (res->end - res->start)+1,
+ pdev->name);
+
+ if (hw->ioarea == NULL) {
+ dev_err(&pdev->dev, "Cannot reserve region\n");
+ err = -ENXIO;
+ goto err_no_iores;
+ }
+
+ hw->regs = ioremap(res->start, (res->end - res->start)+1);
+ if (hw->regs == NULL) {
+ dev_err(&pdev->dev, "Cannot map IO\n");
+ err = -ENXIO;
+ goto err_no_iomap;
+ }
+
+ hw->irq = platform_get_irq(pdev, 0);
+ if (hw->irq < 0) {
+ dev_err(&pdev->dev, "No IRQ specified\n");
+ err = -ENOENT;
+ goto err_no_irq;
+ }
+
+ err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw);
+ if (err) {
+ dev_err(&pdev->dev, "Cannot claim IRQ\n");
+ goto err_no_irq;
+ }
+
+ hw->clk = clk_get(&pdev->dev, "spi");
+ if (IS_ERR(hw->clk)) {
+ dev_err(&pdev->dev, "No clock for device\n");
+ err = PTR_ERR(hw->clk);
+ goto err_no_clk;
+ }
+
+ /* for the moment, permanently enable the clock */
+
+ clk_enable(hw->clk);
+
+ /* program defaults into the registers */
+
+ writeb(0xff, hw->regs + S3C2410_SPPRE);
+ writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
+ writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
+
+ /* setup any gpio we can */
+
+ if (!hw->pdata->set_cs) {
+ s3c2410_gpio_setpin(hw->pdata->pin_cs, 1);
+ s3c2410_gpio_cfgpin(hw->pdata->pin_cs, S3C2410_GPIO_OUTPUT);
+ }
+
+ /* register our spi controller */
+
+ err = spi_bitbang_start(&hw->bitbang);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to register SPI master\n");
+ goto err_register;
+ }
+
+ dev_dbg(hw->dev, "shutdown=%d\n", hw->bitbang.shutdown);
+
+ /* register all the devices associated */
+
+ bi = &hw->pdata->board_info[0];
+ for (i = 0; i < hw->pdata->board_size; i++, bi++) {
+ dev_info(hw->dev, "registering %s\n", bi->modalias);
+
+ bi->controller_data = hw;
+ spi_new_device(master, bi);
+ }
+
+ return 0;
+
+ err_register:
+ clk_disable(hw->clk);
+ clk_put(hw->clk);
+
+ err_no_clk:
+ free_irq(hw->irq, hw);
+
+ err_no_irq:
+ iounmap(hw->regs);
+
+ err_no_iomap:
+ release_resource(hw->ioarea);
+ kfree(hw->ioarea);
+
+ err_no_iores:
+ err_no_pdata:
+ spi_master_put(hw->master);;
+
+ err_nomem:
+ return err;
+}
+
+static int s3c24xx_spi_remove(struct platform_device *dev)
+{
+ struct s3c24xx_spi *hw = platform_get_drvdata(dev);
+
+ platform_set_drvdata(dev, NULL);
+
+ spi_unregister_master(hw->master);
+
+ clk_disable(hw->clk);
+ clk_put(hw->clk);
+
+ free_irq(hw->irq, hw);
+ iounmap(hw->regs);
+
+ release_resource(hw->ioarea);
+ kfree(hw->ioarea);
+
+ spi_master_put(hw->master);
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+
+static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+ struct s3c24xx_spi *hw = platform_get_drvdata(pdev);
+
+ clk_disable(hw->clk);
+ return 0;
+}
+
+static int s3c24xx_spi_resume(struct platform_device *pdev)
+{
+ struct s3c24xx_spi *hw = platform_get_drvdata(pdev);
+
+ clk_enable(hw->clk);
+ return 0;
+}
+
+#else
+#define s3c24xx_spi_suspend NULL
+#define s3c24xx_spi_resume NULL
+#endif
+
+static struct platform_driver s3c24xx_spidrv = {
+ .probe = s3c24xx_spi_probe,
+ .remove = s3c24xx_spi_remove,
+ .suspend = s3c24xx_spi_suspend,
+ .resume = s3c24xx_spi_resume,
+ .driver = {
+ .name = "s3c2410-spi",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init s3c24xx_spi_init(void)
+{
+ return platform_driver_register(&s3c24xx_spidrv);
+}
+
+static void __exit s3c24xx_spi_exit(void)
+{
+ platform_driver_unregister(&s3c24xx_spidrv);
+}
+
+module_init(s3c24xx_spi_init);
+module_exit(s3c24xx_spi_exit);
+
+MODULE_DESCRIPTION("S3C24XX SPI Driver");
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
new file mode 100644
index 00000000000..aacdceb8f44
--- /dev/null
+++ b/drivers/spi/spi_s3c24xx_gpio.c
@@ -0,0 +1,188 @@
+/* linux/drivers/spi/spi_s3c24xx_gpio.c
+ *
+ * Copyright (c) 2006 Ben Dooks
+ * Copyright (c) 2006 Simtec Electronics
+ *
+ * S3C24XX GPIO based SPI driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/spi-gpio.h>
+#include <asm/arch/hardware.h>
+
+struct s3c2410_spigpio {
+ struct spi_bitbang bitbang;
+
+ struct s3c2410_spigpio_info *info;
+ struct platform_device *dev;
+};
+
+static inline struct s3c2410_spigpio *spidev_to_sg(struct spi_device *spi)
+{
+ return spi->controller_data;
+}
+
+static inline void setsck(struct spi_device *dev, int on)
+{
+ struct s3c2410_spigpio *sg = spidev_to_sg(dev);
+ s3c2410_gpio_setpin(sg->info->pin_clk, on ? 1 : 0);
+}
+
+static inline void setmosi(struct spi_device *dev, int on)
+{
+ struct s3c2410_spigpio *sg = spidev_to_sg(dev);
+ s3c2410_gpio_setpin(sg->info->pin_mosi, on ? 1 : 0);
+}
+
+static inline u32 getmiso(struct spi_device *dev)
+{
+ struct s3c2410_spigpio *sg = spidev_to_sg(dev);
+ return s3c2410_gpio_getpin(sg->info->pin_miso) ? 1 : 0;
+}
+
+#define spidelay(x) ndelay(x)
+
+#define EXPAND_BITBANG_TXRX
+#include <linux/spi/spi_bitbang.h>
+
+
+static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi,
+ unsigned nsecs, u32 word, u8 bits)
+{
+ return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
+}
+
+static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi,
+ unsigned nsecs, u32 word, u8 bits)
+{
+ return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
+}
+
+static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value)
+{
+ struct s3c2410_spigpio *sg = spidev_to_sg(dev);
+
+ if (sg->info && sg->info->chip_select)
+ (sg->info->chip_select)(sg->info, value);
+}
+
+static int s3c2410_spigpio_probe(struct platform_device *dev)
+{
+ struct spi_master *master;
+ struct s3c2410_spigpio *sp;
+ int ret;
+ int i;
+
+ master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio));
+ if (master == NULL) {
+ dev_err(&dev->dev, "failed to allocate spi master\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ sp = spi_master_get_devdata(master);
+
+ platform_set_drvdata(dev, sp);
+
+ /* copy in the plkatform data */
+ sp->info = dev->dev.platform_data;
+
+ /* setup spi bitbang adaptor */
+ sp->bitbang.master = spi_master_get(master);
+ sp->bitbang.chipselect = s3c2410_spigpio_chipselect;
+
+ sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
+ sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1;
+
+ /* set state of spi pins */
+ s3c2410_gpio_setpin(sp->info->pin_clk, 0);
+ s3c2410_gpio_setpin(sp->info->pin_mosi, 0);
+
+ s3c2410_gpio_cfgpin(sp->info->pin_clk, S3C2410_GPIO_OUTPUT);
+ s3c2410_gpio_cfgpin(sp->info->pin_mosi, S3C2410_GPIO_OUTPUT);
+ s3c2410_gpio_cfgpin(sp->info->pin_miso, S3C2410_GPIO_INPUT);
+
+ ret = spi_bitbang_start(&sp->bitbang);
+ if (ret)
+ goto err_no_bitbang;
+
+ /* register the chips to go with the board */
+
+ for (i = 0; i < sp->info->board_size; i++) {
+ dev_info(&dev->dev, "registering %p: %s\n",
+ &sp->info->board_info[i],
+ sp->info->board_info[i].modalias);
+
+ sp->info->board_info[i].controller_data = sp;
+ spi_new_device(master, sp->info->board_info + i);
+ }
+
+ return 0;
+
+ err_no_bitbang:
+ spi_master_put(sp->bitbang.master);
+ err:
+ return ret;
+
+}
+
+static int s3c2410_spigpio_remove(struct platform_device *dev)
+{
+ struct s3c2410_spigpio *sp = platform_get_drvdata(dev);
+
+ spi_bitbang_stop(&sp->bitbang);
+ spi_master_put(sp->bitbang.master);
+
+ return 0;
+}
+
+/* all gpio should be held over suspend/resume, so we should
+ * not need to deal with this
+*/
+
+#define s3c2410_spigpio_suspend NULL
+#define s3c2410_spigpio_resume NULL
+
+
+static struct platform_driver s3c2410_spigpio_drv = {
+ .probe = s3c2410_spigpio_probe,
+ .remove = s3c2410_spigpio_remove,
+ .suspend = s3c2410_spigpio_suspend,
+ .resume = s3c2410_spigpio_resume,
+ .driver = {
+ .name = "s3c24xx-spi-gpio",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init s3c2410_spigpio_init(void)
+{
+ return platform_driver_register(&s3c2410_spigpio_drv);
+}
+
+static void __exit s3c2410_spigpio_exit(void)
+{
+ platform_driver_unregister(&s3c2410_spigpio_drv);
+}
+
+module_init(s3c2410_spigpio_init);
+module_exit(s3c2410_spigpio_exit);
+
+MODULE_DESCRIPTION("S3C24XX SPI Driver");
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index d3a7b0c3d38..dda0ca45d90 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -35,73 +35,52 @@ typedef struct ixj_info_t {
} ixj_info_t;
static void ixj_detach(struct pcmcia_device *p_dev);
-static void ixj_config(dev_link_t * link);
-static void ixj_cs_release(dev_link_t * link);
+static int ixj_config(struct pcmcia_device * link);
+static void ixj_cs_release(struct pcmcia_device * link);
-static int ixj_attach(struct pcmcia_device *p_dev)
+static int ixj_probe(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
-
DEBUG(0, "ixj_attach()\n");
/* Create new ixj device */
- link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link)
- return -ENOMEM;
- memset(link, 0, sizeof(struct dev_link_t));
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = 3;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
- if (!link->priv) {
- kfree(link);
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = 3;
+ p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
+ if (!p_dev->priv) {
return -ENOMEM;
}
- memset(link->priv, 0, sizeof(struct ixj_info_t));
-
- link->handle = p_dev;
- p_dev->instance = link;
+ memset(p_dev->priv, 0, sizeof(struct ixj_info_t));
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- ixj_config(link);
-
- return 0;
+ return ixj_config(p_dev);
}
-static void ixj_detach(struct pcmcia_device *p_dev)
+static void ixj_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DEBUG(0, "ixj_detach(0x%p)\n", link);
- link->state &= ~DEV_RELEASE_PENDING;
- if (link->state & DEV_CONFIG)
- ixj_cs_release(link);
+ ixj_cs_release(link);
kfree(link->priv);
- kfree(link);
}
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void ixj_get_serial(dev_link_t * link, IXJ * j)
+static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)
{
- client_handle_t handle;
tuple_t tuple;
u_short buf[128];
char *str;
int last_ret, last_fn, i, place;
- handle = link->handle;
DEBUG(0, "ixj_get_serial(0x%p)\n", link);
tuple.TupleData = (cisdata_t *) buf;
tuple.TupleOffset = 0;
tuple.TupleDataMax = 80;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_VERS_1;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
str = (char *) buf;
printk("PCMCIA Version %d.%d\n", str[0], str[1]);
str += 2;
@@ -149,22 +128,19 @@ static void ixj_get_serial(dev_link_t * link, IXJ * j)
return;
}
-static void ixj_config(dev_link_t * link)
+static int ixj_config(struct pcmcia_device * link)
{
IXJ *j;
- client_handle_t handle;
ixj_info_t *info;
tuple_t tuple;
u_short buf[128];
cisparse_t parse;
- config_info_t conf;
cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
cistpl_cftable_entry_t dflt =
{
0
};
int last_ret, last_fn;
- handle = link->handle;
info = link->priv;
DEBUG(0, "ixj_config(0x%p)\n", link);
tuple.TupleData = (cisdata_t *) buf;
@@ -172,19 +148,17 @@ static void ixj_config(dev_link_t * link)
tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- link->state |= DEV_CONFIG;
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
@@ -195,7 +169,7 @@ static void ixj_config(dev_link_t * link)
link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = io->win[1].len;
}
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
/* If we've got this far, we're done */
break;
@@ -203,10 +177,10 @@ static void ixj_config(dev_link_t * link)
next_entry:
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
dflt = *cfg;
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/*
* Register the card with the core.
@@ -215,46 +189,21 @@ static void ixj_config(dev_link_t * link)
info->ndev = 1;
info->node.major = PHONE_MAJOR;
- link->dev = &info->node;
+ link->dev_node = &info->node;
ixj_get_serial(link, j);
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
ixj_cs_release(link);
+ return -ENODEV;
}
-static void ixj_cs_release(dev_link_t *link)
+static void ixj_cs_release(struct pcmcia_device *link)
{
ixj_info_t *info = link->priv;
DEBUG(0, "ixj_cs_release(0x%p)\n", link);
info->ndev = 0;
- link->dev = NULL;
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- link->state &= ~DEV_CONFIG;
-}
-
-static int ixj_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int ixj_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
-
- return 0;
+ pcmcia_disable_device(link);
}
static struct pcmcia_device_id ixj_ids[] = {
@@ -268,11 +217,9 @@ static struct pcmcia_driver ixj_driver = {
.drv = {
.name = "ixj_cs",
},
- .probe = ixj_attach,
+ .probe = ixj_probe,
.remove = ixj_detach,
.id_table = ixj_ids,
- .suspend = ixj_suspend,
- .resume = ixj_resume,
};
static int __init ixj_pcmcia_init(void)
diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c
index 7a6db1c5c8c..e166fffea86 100644
--- a/drivers/telephony/phonedev.c
+++ b/drivers/telephony/phonedev.c
@@ -49,7 +49,7 @@ static int phone_open(struct inode *inode, struct file *file)
unsigned int minor = iminor(inode);
int err = 0;
struct phone_device *p;
- struct file_operations *old_fops, *new_fops = NULL;
+ const struct file_operations *old_fops, *new_fops = NULL;
if (minor >= PHONE_NUM_DEVICES)
return -ENODEV;
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 7860c8a5800..956b7a1e8af 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -69,7 +69,7 @@ static const char speedtch_driver_name[] = "speedtch";
#define RESUBMIT_DELAY 1000 /* milliseconds */
#define DEFAULT_BULK_ALTSETTING 1
-#define DEFAULT_ISOC_ALTSETTING 2
+#define DEFAULT_ISOC_ALTSETTING 3
#define DEFAULT_DL_512_FIRST 0
#define DEFAULT_ENABLE_ISOC 0
#define DEFAULT_SW_BUFFERING 0
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 830d2c98267..b38990adf1c 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -68,7 +68,7 @@
#include "usbatm.h"
-#define EAGLEUSBVERSION "ueagle 1.2"
+#define EAGLEUSBVERSION "ueagle 1.3"
/*
@@ -243,7 +243,7 @@ enum {
#define BULK_TIMEOUT 300
#define CTRL_TIMEOUT 1000
-#define ACK_TIMEOUT msecs_to_jiffies(1500)
+#define ACK_TIMEOUT msecs_to_jiffies(3000)
#define UEA_INTR_IFACE_NO 0
#define UEA_US_IFACE_NO 1
@@ -314,6 +314,10 @@ struct cmv {
((d) & 0xff) << 16 | \
((a) & 0xff) << 8 | \
((b) & 0xff))
+#define GETSA1(a) ((a >> 8) & 0xff)
+#define GETSA2(a) (a & 0xff)
+#define GETSA3(a) ((a >> 24) & 0xff)
+#define GETSA4(a) ((a >> 16) & 0xff)
#define SA_CNTL MAKESA('C', 'N', 'T', 'L')
#define SA_DIAG MAKESA('D', 'I', 'A', 'G')
@@ -728,11 +732,12 @@ bad2:
uea_err(INS_TO_USBDEV(sc), "sending DSP block %u failed\n", i);
return;
bad1:
- uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n",pageno);
+ uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno);
}
static inline void wake_up_cmv_ack(struct uea_softc *sc)
{
+ BUG_ON(sc->cmv_ack);
sc->cmv_ack = 1;
wake_up(&sc->cmv_ack_wait);
}
@@ -743,6 +748,9 @@ static inline int wait_cmv_ack(struct uea_softc *sc)
sc->cmv_ack, ACK_TIMEOUT);
sc->cmv_ack = 0;
+ uea_dbg(INS_TO_USBDEV(sc), "wait_event_timeout : %d ms\n",
+ jiffies_to_msecs(ret));
+
if (ret < 0)
return ret;
@@ -791,6 +799,12 @@ static int uea_cmv(struct uea_softc *sc,
struct cmv cmv;
int ret;
+ uea_enters(INS_TO_USBDEV(sc));
+ uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, "
+ "offset : 0x%04x, data : 0x%08x\n",
+ FUNCTION_TYPE(function), FUNCTION_SUBTYPE(function),
+ GETSA1(address), GETSA2(address), GETSA3(address),
+ GETSA4(address), offset, data);
/* we send a request, but we expect a reply */
sc->cmv_function = function | 0x2;
sc->cmv_idx++;
@@ -808,7 +822,9 @@ static int uea_cmv(struct uea_softc *sc,
ret = uea_request(sc, UEA_SET_BLOCK, UEA_MPTX_START, CMV_SIZE, &cmv);
if (ret < 0)
return ret;
- return wait_cmv_ack(sc);
+ ret = wait_cmv_ack(sc);
+ uea_leaves(INS_TO_USBDEV(sc));
+ return ret;
}
static inline int uea_read_cmv(struct uea_softc *sc,
@@ -922,7 +938,7 @@ static int uea_stat(struct uea_softc *sc)
* we check the status again in order to detect the failure earlier
*/
if (sc->stats.phy.flags) {
- uea_dbg(INS_TO_USBDEV(sc), "Stat flag = %d\n",
+ uea_dbg(INS_TO_USBDEV(sc), "Stat flag = 0x%x\n",
sc->stats.phy.flags);
return 0;
}
@@ -1063,7 +1079,13 @@ static int uea_start_reset(struct uea_softc *sc)
uea_enters(INS_TO_USBDEV(sc));
uea_info(INS_TO_USBDEV(sc), "(re)booting started\n");
+ /* mask interrupt */
sc->booting = 1;
+ /* We need to set this here because, a ack timeout could have occured,
+ * but before we start the reboot, the ack occurs and set this to 1.
+ * So we will failed to wait Ready CMV.
+ */
+ sc->cmv_ack = 0;
UPDATE_ATM_STAT(signal, ATM_PHY_SIG_LOST);
/* reset statistics */
@@ -1089,6 +1111,7 @@ static int uea_start_reset(struct uea_softc *sc)
msleep(1000);
sc->cmv_function = MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY);
+ /* demask interrupt */
sc->booting = 0;
/* start loading DSP */
@@ -1101,6 +1124,8 @@ static int uea_start_reset(struct uea_softc *sc)
if (ret < 0)
return ret;
+ uea_vdbg(INS_TO_USBDEV(sc), "Ready CMV received\n");
+
/* Enter in R-IDLE (cmv) until instructed otherwise */
ret = uea_write_cmv(sc, SA_CNTL, 0, 1);
if (ret < 0)
@@ -1121,6 +1146,7 @@ static int uea_start_reset(struct uea_softc *sc)
}
/* Enter in R-ACT-REQ */
ret = uea_write_cmv(sc, SA_CNTL, 0, 2);
+ uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n");
out:
release_firmware(cmvs_fw);
sc->reset = 0;
@@ -1235,6 +1261,7 @@ static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
if (cmv->bFunction == MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY)) {
wake_up_cmv_ack(sc);
+ uea_leaves(INS_TO_USBDEV(sc));
return;
}
@@ -1249,6 +1276,7 @@ static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
sc->data = sc->data << 16 | sc->data >> 16;
wake_up_cmv_ack(sc);
+ uea_leaves(INS_TO_USBDEV(sc));
return;
bad2:
@@ -1256,12 +1284,14 @@ bad2:
"Function : %d, Subfunction : %d\n",
FUNCTION_TYPE(cmv->bFunction),
FUNCTION_SUBTYPE(cmv->bFunction));
+ uea_leaves(INS_TO_USBDEV(sc));
return;
bad1:
uea_err(INS_TO_USBDEV(sc), "invalid cmv received, "
"wPreamble %d, bDirection %d\n",
le16_to_cpu(cmv->wPreamble), cmv->bDirection);
+ uea_leaves(INS_TO_USBDEV(sc));
}
/*
@@ -1346,7 +1376,7 @@ static int uea_boot(struct uea_softc *sc)
if (ret < 0) {
uea_err(INS_TO_USBDEV(sc),
"urb submition failed with error %d\n", ret);
- goto err1;
+ goto err;
}
sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm");
@@ -1360,10 +1390,10 @@ static int uea_boot(struct uea_softc *sc)
err2:
usb_kill_urb(sc->urb_int);
-err1:
- kfree(intr);
err:
usb_free_urb(sc->urb_int);
+ sc->urb_int = NULL;
+ kfree(intr);
uea_leaves(INS_TO_USBDEV(sc));
return -ENOMEM;
}
@@ -1508,7 +1538,7 @@ static ssize_t read_##name(struct device *dev, \
int ret = -ENODEV; \
struct uea_softc *sc; \
\
- mutex_lock(&uea_mutex); \
+ mutex_lock(&uea_mutex); \
sc = dev_to_uea(dev); \
if (!sc) \
goto out; \
@@ -1516,7 +1546,7 @@ static ssize_t read_##name(struct device *dev, \
if (reset) \
sc->stats.phy.name = 0; \
out: \
- mutex_unlock(&uea_mutex); \
+ mutex_unlock(&uea_mutex); \
return ret; \
} \
\
@@ -1643,7 +1673,7 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
sc = kzalloc(sizeof(struct uea_softc), GFP_KERNEL);
if (!sc) {
- uea_err(INS_TO_USBDEV(sc), "uea_init: not enough memory !\n");
+ uea_err(usb, "uea_init: not enough memory !\n");
return -ENOMEM;
}
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index c1211fc037d..546249843b8 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -99,11 +99,11 @@ static const char usbatm_driver_name[] = "usbatm";
#define UDSL_MAX_RCV_URBS 16
#define UDSL_MAX_SND_URBS 16
-#define UDSL_MAX_BUF_SIZE 64 * 1024 /* bytes */
+#define UDSL_MAX_BUF_SIZE 65536
#define UDSL_DEFAULT_RCV_URBS 4
#define UDSL_DEFAULT_SND_URBS 4
-#define UDSL_DEFAULT_RCV_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */
-#define UDSL_DEFAULT_SND_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */
+#define UDSL_DEFAULT_RCV_BUF_SIZE 3392 /* 64 * ATM_CELL_SIZE */
+#define UDSL_DEFAULT_SND_BUF_SIZE 3392 /* 64 * ATM_CELL_SIZE */
#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
@@ -135,7 +135,7 @@ MODULE_PARM_DESC(rcv_buf_bytes,
module_param(snd_buf_bytes, uint, S_IRUGO);
MODULE_PARM_DESC(snd_buf_bytes,
"Size of the buffers used for transmission, in bytes (range: 1-"
- __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "
+ __MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: "
__MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index ff03184da40..a08787e253a 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -99,4 +99,11 @@ config USB_OTG_WHITELIST
normal Linux-USB hosts do (other than the warning), and is
convenient for many stages of product development.
+config USB_OTG_BLACKLIST_HUB
+ bool "Disable external hubs"
+ depends on USB_OTG
+ help
+ If you say Y here, then Linux will refuse to enumerate
+ external hubs. OTG hosts are allowed to reduce hardware
+ and software costs by not supporting external hubs.
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 37b13368c81..b263a54a13c 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -24,15 +24,15 @@
#include "usb.h"
#define MAX_USB_MINORS 256
-static struct file_operations *usb_minors[MAX_USB_MINORS];
+static const struct file_operations *usb_minors[MAX_USB_MINORS];
static DEFINE_SPINLOCK(minor_lock);
static int usb_open(struct inode * inode, struct file * file)
{
int minor = iminor(inode);
- struct file_operations *c;
+ const struct file_operations *c;
int err = -ENODEV;
- struct file_operations *old_fops, *new_fops = NULL;
+ const struct file_operations *old_fops, *new_fops = NULL;
spin_lock (&minor_lock);
c = usb_minors[minor];
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index e0afb5ad29e..66b78404ab3 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -213,11 +213,9 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
if (hcd->driver->suspend) {
retval = hcd->driver->suspend(hcd, message);
- if (retval) {
- dev_dbg (&dev->dev, "PCI pre-suspend fail, %d\n",
- retval);
+ suspend_report_result(hcd->driver->suspend, retval);
+ if (retval)
goto done;
- }
}
synchronize_irq(dev->irq);
@@ -263,6 +261,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
* some device state (e.g. as part of clock reinit).
*/
retval = pci_set_power_state (dev, PCI_D3hot);
+ suspend_report_result(pci_set_power_state, retval);
if (retval == 0) {
int wake = device_can_wakeup(&hcd->self.root_hub->dev);
@@ -296,7 +295,7 @@ done:
#ifdef CONFIG_PPC_PMAC
/* Disable ASIC clocks for USB */
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
struct device_node *of_node;
of_node = pci_device_to_OF_node (dev);
@@ -331,7 +330,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
#ifdef CONFIG_PPC_PMAC
/* Reenable ASIC clocks for USB */
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
struct device_node *of_node;
of_node = pci_device_to_OF_node (dev);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index fbd938d4ea5..e2e00ba4e1e 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1805,6 +1805,12 @@ int usb_add_hcd(struct usb_hcd *hcd,
USB_SPEED_FULL;
hcd->self.root_hub = rhdev;
+ /* wakeup flag init defaults to "everything works" for root hubs,
+ * but drivers can override it in reset() if needed, along with
+ * recording the overall controller's system wakeup capability.
+ */
+ device_init_wakeup(&rhdev->dev, 1);
+
/* "reset" is misnamed; its role is now one-time init. the controller
* should already have been reset (and boot firmware kicked off etc).
*/
@@ -1813,13 +1819,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
goto err_hcd_driver_setup;
}
- /* wakeup flag init is in transition; for now we can't rely on PCI to
- * initialize these bits properly, so we let reset() override it.
- * This init should _precede_ the reset() once PCI behaves.
- */
- device_init_wakeup(&rhdev->dev,
- device_can_wakeup(hcd->self.controller));
-
/* NOTE: root hub and controller capabilities may not be the same */
if (device_can_wakeup(hcd->self.controller)
&& device_can_wakeup(&hcd->self.root_hub->dev))
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 8e65f7a237e..90b8d43c6b3 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -836,6 +836,13 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf);
+#ifdef CONFIG_USB_OTG_BLACKLIST_HUB
+ if (hdev->parent) {
+ dev_warn(&intf->dev, "ignoring external hub\n");
+ return -ENODEV;
+ }
+#endif
+
/* Some hubs have a subclass of 1, which AFAICT according to the */
/* specs is not defined, but it works */
if ((desc->desc.bInterfaceSubClass != 0) &&
@@ -1022,7 +1029,6 @@ void usb_set_device_state(struct usb_device *udev,
recursively_mark_NOTATTACHED(udev);
spin_unlock_irqrestore(&device_state_lock, flags);
}
-EXPORT_SYMBOL(usb_set_device_state);
#ifdef CONFIG_PM
@@ -1162,19 +1168,9 @@ static inline const char *plural(int n)
static int choose_configuration(struct usb_device *udev)
{
int i;
- u16 devstatus;
- int bus_powered;
int num_configs;
struct usb_host_config *c, *best;
- /* If this fails, assume the device is bus-powered */
- devstatus = 0;
- usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
- le16_to_cpus(&devstatus);
- bus_powered = ((devstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0);
- dev_dbg(&udev->dev, "device is %s-powered\n",
- bus_powered ? "bus" : "self");
-
best = NULL;
c = udev->config;
num_configs = udev->descriptor.bNumConfigurations;
@@ -1191,6 +1187,19 @@ static int choose_configuration(struct usb_device *udev)
* similar errors in their descriptors. If the next test
* were allowed to execute, such configurations would always
* be rejected and the devices would not work as expected.
+ * In the meantime, we run the risk of selecting a config
+ * that requires external power at a time when that power
+ * isn't available. It seems to be the lesser of two evils.
+ *
+ * Bugzilla #6448 reports a device that appears to crash
+ * when it receives a GET_DEVICE_STATUS request! We don't
+ * have any other way to tell whether a device is self-powered,
+ * but since we don't use that information anywhere but here,
+ * the call has been removed.
+ *
+ * Maybe the GET_DEVICE_STATUS call and the test below can
+ * be reinstated when device firmwares become more reliable.
+ * Don't hold your breath.
*/
#if 0
/* Rule out self-powered configs for a bus-powered device */
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
index 4b55285de9a..fe0ed54fa0a 100644
--- a/drivers/usb/core/notify.c
+++ b/drivers/usb/core/notify.c
@@ -16,57 +16,7 @@
#include <linux/mutex.h>
#include "usb.h"
-
-static struct notifier_block *usb_notifier_list;
-static DEFINE_MUTEX(usb_notifier_lock);
-
-static void usb_notifier_chain_register(struct notifier_block **list,
- struct notifier_block *n)
-{
- mutex_lock(&usb_notifier_lock);
- while (*list) {
- if (n->priority > (*list)->priority)
- break;
- list = &((*list)->next);
- }
- n->next = *list;
- *list = n;
- mutex_unlock(&usb_notifier_lock);
-}
-
-static void usb_notifier_chain_unregister(struct notifier_block **nl,
- struct notifier_block *n)
-{
- mutex_lock(&usb_notifier_lock);
- while ((*nl)!=NULL) {
- if ((*nl)==n) {
- *nl = n->next;
- goto exit;
- }
- nl=&((*nl)->next);
- }
-exit:
- mutex_unlock(&usb_notifier_lock);
-}
-
-static int usb_notifier_call_chain(struct notifier_block **n,
- unsigned long val, void *v)
-{
- int ret=NOTIFY_DONE;
- struct notifier_block *nb = *n;
-
- mutex_lock(&usb_notifier_lock);
- while (nb) {
- ret = nb->notifier_call(nb,val,v);
- if (ret&NOTIFY_STOP_MASK) {
- goto exit;
- }
- nb = nb->next;
- }
-exit:
- mutex_unlock(&usb_notifier_lock);
- return ret;
-}
+static BLOCKING_NOTIFIER_HEAD(usb_notifier_list);
/**
* usb_register_notify - register a notifier callback whenever a usb change happens
@@ -76,7 +26,7 @@ exit:
*/
void usb_register_notify(struct notifier_block *nb)
{
- usb_notifier_chain_register(&usb_notifier_list, nb);
+ blocking_notifier_chain_register(&usb_notifier_list, nb);
}
EXPORT_SYMBOL_GPL(usb_register_notify);
@@ -89,27 +39,28 @@ EXPORT_SYMBOL_GPL(usb_register_notify);
*/
void usb_unregister_notify(struct notifier_block *nb)
{
- usb_notifier_chain_unregister(&usb_notifier_list, nb);
+ blocking_notifier_chain_unregister(&usb_notifier_list, nb);
}
EXPORT_SYMBOL_GPL(usb_unregister_notify);
void usb_notify_add_device(struct usb_device *udev)
{
- usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev);
+ blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev);
}
void usb_notify_remove_device(struct usb_device *udev)
{
- usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev);
+ blocking_notifier_call_chain(&usb_notifier_list,
+ USB_DEVICE_REMOVE, udev);
}
void usb_notify_add_bus(struct usb_bus *ubus)
{
- usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus);
+ blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus);
}
void usb_notify_remove_bus(struct usb_bus *ubus)
{
- usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus);
+ blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus);
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index d7352aa73b5..b7fdc1cd134 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -1194,7 +1194,6 @@ EXPORT_SYMBOL(usb_disabled);
EXPORT_SYMBOL_GPL(usb_get_intf);
EXPORT_SYMBOL_GPL(usb_put_intf);
-EXPORT_SYMBOL(usb_alloc_dev);
EXPORT_SYMBOL(usb_put_dev);
EXPORT_SYMBOL(usb_get_dev);
EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
@@ -1208,7 +1207,6 @@ EXPORT_SYMBOL(usb_ifnum_to_if);
EXPORT_SYMBOL(usb_altnum_to_altsetting);
EXPORT_SYMBOL(usb_reset_device);
-EXPORT_SYMBOL(usb_disconnect);
EXPORT_SYMBOL(__usb_get_extra_descriptor);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index d80f71877d6..363b2ad74ae 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -69,11 +69,11 @@ choice
often need board-specific hooks.
config USB_GADGET_NET2280
- boolean "NetChip 2280"
+ boolean "NetChip 228x"
depends on PCI
select USB_GADGET_DUALSPEED
help
- NetChip 2280 is a PCI based USB peripheral controller which
+ NetChip 2280 / 2282 is a PCI based USB peripheral controller which
supports both full and high speed USB 2.0 data transfers.
It has six configurable endpoints, as well as endpoint zero
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 865858cfd1c..b8d0b7825bf 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1709,7 +1709,7 @@ static int __devexit at91udc_remove(struct platform_device *dev)
}
#ifdef CONFIG_PM
-static int at91udc_suspend(struct platform_device *dev, u32 state, u32 level)
+static int at91udc_suspend(struct platform_device *dev, pm_message_t mesg)
{
struct at91_udc *udc = platform_get_drvdata(dev);
@@ -1731,7 +1731,7 @@ static int at91udc_suspend(struct platform_device *dev, u32 state, u32 level)
return 0;
}
-static int at91udc_resume(struct platform_device *dev, u32 level)
+static int at91udc_resume(struct platform_device *dev)
{
struct at91_udc *udc = platform_get_drvdata(dev);
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index c3d8e5c5bf2..9c4422ac9de 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -2338,6 +2338,9 @@ autoconf_fail:
hs_subset_descriptors();
}
+ device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+ usb_gadget_set_selfpowered (gadget);
+
/* For now RNDIS is always a second config */
if (rndis)
device_desc.bNumConfigurations = 2;
@@ -2361,9 +2364,6 @@ autoconf_fail:
#endif
#endif /* DUALSPEED */
- device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
- usb_gadget_set_selfpowered (gadget);
-
if (gadget->is_otg) {
otg_descriptor.bmAttributes |= USB_OTG_HNP,
eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index cf3be299e35..6f887478b14 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -71,6 +71,12 @@
* requirement amounts to two 16K buffers, size configurable by a parameter.
* Support is included for both full-speed and high-speed operation.
*
+ * Note that the driver is slightly non-portable in that it assumes a
+ * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
+ * interrupt-in endpoints. With most device controllers this isn't an
+ * issue, but there may be some with hardware restrictions that prevent
+ * a buffer from being used by more than one endpoint.
+ *
* Module options:
*
* file=filename[,filename...]
@@ -108,6 +114,14 @@
* setting are not allowed when the medium is loaded.
*
* This gadget driver is heavily based on "Gadget Zero" by David Brownell.
+ * The driver's SCSI command interface was based on the "Information
+ * technology - Small Computer System Interface - 2" document from
+ * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
+ * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>. The single exception
+ * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
+ * "Universal Serial Bus Mass Storage Class UFI Command Specification"
+ * document, Revision 1.0, December 14, 1998, available at
+ * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
*/
@@ -334,11 +348,9 @@ MODULE_LICENSE("Dual BSD/GPL");
#define MAX_LUNS 8
- /* Arggh! There should be a module_param_array_named macro! */
-static char *file[MAX_LUNS];
-static int ro[MAX_LUNS];
-
static struct {
+ char *file[MAX_LUNS];
+ int ro[MAX_LUNS];
int num_filenames;
int num_ros;
unsigned int nluns;
@@ -370,10 +382,11 @@ static struct {
};
-module_param_array(file, charp, &mod_data.num_filenames, S_IRUGO);
+module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
+ S_IRUGO);
MODULE_PARM_DESC(file, "names of backing files or devices");
-module_param_array(ro, bool, &mod_data.num_ros, S_IRUGO);
+module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
MODULE_PARM_DESC(ro, "true to force read-only");
module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
@@ -1795,6 +1808,7 @@ static int do_write(struct fsg_dev *fsg)
* the bulk-out maxpacket size */
bh->outreq->length = bh->bulk_out_intended_length =
amount;
+ bh->outreq->short_not_ok = 1;
start_transfer(fsg, fsg->bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next;
@@ -2398,6 +2412,7 @@ static int throw_away_data(struct fsg_dev *fsg)
* the bulk-out maxpacket size */
bh->outreq->length = bh->bulk_out_intended_length =
amount;
+ bh->outreq->short_not_ok = 1;
start_transfer(fsg, fsg->bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next;
@@ -3029,6 +3044,7 @@ static int get_next_command(struct fsg_dev *fsg)
/* Queue a request to read a Bulk-only CBW */
set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN);
+ bh->outreq->short_not_ok = 1;
start_transfer(fsg, fsg->bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state);
@@ -3859,7 +3875,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
for (i = 0; i < fsg->nluns; ++i) {
curlun = &fsg->luns[i];
- curlun->ro = ro[i];
+ curlun->ro = mod_data.ro[i];
curlun->dev.parent = &gadget->dev;
curlun->dev.driver = &fsg_driver.driver;
dev_set_drvdata(&curlun->dev, fsg);
@@ -3876,8 +3892,9 @@ static int __init fsg_bind(struct usb_gadget *gadget)
kref_get(&fsg->ref);
}
- if (file[i] && *file[i]) {
- if ((rc = open_backing_file(curlun, file[i])) != 0)
+ if (mod_data.file[i] && *mod_data.file[i]) {
+ if ((rc = open_backing_file(curlun,
+ mod_data.file[i])) != 0)
goto out;
} else if (!mod_data.removable) {
ERROR(fsg, "no file given for LUN%d\n", i);
@@ -3953,6 +3970,9 @@ static int __init fsg_bind(struct usb_gadget *gadget)
for (i = 0; i < NUM_BUFFERS; ++i) {
struct fsg_buffhd *bh = &fsg->buffhds[i];
+ /* Allocate for the bulk-in endpoint. We assume that
+ * the buffer will also work with the bulk-out (and
+ * interrupt-in) endpoint. */
bh->buf = usb_ep_alloc_buffer(fsg->bulk_in, mod_data.buflen,
&bh->dma, GFP_KERNEL);
if (!bh->buf)
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index c4081407171..aa80f091072 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -100,9 +100,9 @@
#define gadget_is_musbhsfc(g) 0
#endif
-/* Mentor high speed "dual role" controller, peripheral mode */
-#ifdef CONFIG_USB_GADGET_MUSBHDRC
-#define gadget_is_musbhdrc(g) !strcmp("musbhdrc_udc", (g)->name)
+/* Mentor high speed "dual role" controller, in peripheral role */
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+#define gadget_is_musbhdrc(g) !strcmp("musb_hdrc", (g)->name)
#else
#define gadget_is_musbhdrc(g) 0
#endif
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index b44cfda76b6..0eb010a3f5b 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -810,7 +810,7 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
if (value == 0)
data->state = STATE_EP_ENABLED;
break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_SPEED_HIGH:
/* fails if caller didn't provide that descriptor... */
value = usb_ep_enable (ep, &data->hs_desc);
@@ -982,7 +982,7 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
/* assume that was SET_CONFIGURATION */
if (dev->current_config) {
unsigned power;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (dev->gadget->speed == USB_SPEED_HIGH)
power = dev->hs_config->bMaxPower;
else
@@ -1262,7 +1262,7 @@ static struct file_operations ep0_io_operations = {
* Unrecognized ep0 requests may be handled in user space.
*/
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
static void make_qualifier (struct dev_data *dev)
{
struct usb_qualifier_descriptor qual;
@@ -1291,7 +1291,7 @@ static int
config_buf (struct dev_data *dev, u8 type, unsigned index)
{
int len;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
int hs;
#endif
@@ -1299,7 +1299,7 @@ config_buf (struct dev_data *dev, u8 type, unsigned index)
if (index > 0)
return -EINVAL;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
hs = (dev->gadget->speed == USB_SPEED_HIGH);
if (type == USB_DT_OTHER_SPEED_CONFIG)
hs = !hs;
@@ -1335,12 +1335,12 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
dev->state = STATE_CONNECTED;
dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == 0) {
ERROR (dev, "no high speed config??\n");
return -EINVAL;
}
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
INFO (dev, "connected\n");
event = next_event (dev, GADGETFS_CONNECT);
@@ -1352,11 +1352,11 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
/* ... down_trylock (&data->lock) ... */
if (data->state != STATE_EP_DEFER_ENABLE)
continue;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (gadget->speed == USB_SPEED_HIGH)
value = usb_ep_enable (ep, &data->hs_desc);
else
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
value = usb_ep_enable (ep, &data->desc);
if (value) {
ERROR (dev, "deferred %s enable --> %d\n",
@@ -1391,7 +1391,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
value = min (w_length, (u16) sizeof *dev->dev);
req->buf = dev->dev;
break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_DT_DEVICE_QUALIFIER:
if (!dev->hs_config)
break;
@@ -1428,7 +1428,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
// user mode expected to disable endpoints
} else {
u8 config, power;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (gadget->speed == USB_SPEED_HIGH) {
config = dev->hs_config->bConfigurationValue;
power = dev->hs_config->bMaxPower;
@@ -1581,7 +1581,7 @@ restart:
static struct inode *
gadgetfs_create_file (struct super_block *sb, char const *name,
- void *data, struct file_operations *fops,
+ void *data, const struct file_operations *fops,
struct dentry **dentry_p);
static int activate_ep_files (struct dev_data *dev)
@@ -1614,6 +1614,7 @@ static int activate_ep_files (struct dev_data *dev)
data, &ep_config_operations,
&data->dentry);
if (!data->inode) {
+ usb_ep_free_request(ep, data->req);
kfree (data);
goto enomem;
}
@@ -1728,7 +1729,7 @@ gadgetfs_suspend (struct usb_gadget *gadget)
}
static struct usb_gadget_driver gadgetfs_driver = {
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
.speed = USB_SPEED_HIGH,
#else
.speed = USB_SPEED_FULL,
@@ -1955,7 +1956,7 @@ module_param (default_perm, uint, 0644);
static struct inode *
gadgetfs_make_inode (struct super_block *sb,
- void *data, struct file_operations *fops,
+ void *data, const struct file_operations *fops,
int mode)
{
struct inode *inode = new_inode (sb);
@@ -1979,7 +1980,7 @@ gadgetfs_make_inode (struct super_block *sb,
*/
static struct inode *
gadgetfs_create_file (struct super_block *sb, char const *name,
- void *data, struct file_operations *fops,
+ void *data, const struct file_operations *fops,
struct dentry **dentry_p)
{
struct dentry *dentry;
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index fb73dc10053..0b929349395 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -26,6 +26,8 @@
* Copyright (C) 2003 David Brownell
* Copyright (C) 2003-2005 PLX Technology, Inc.
*
+ * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility with 2282 chip
+ *
* This program is free software; 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
@@ -71,8 +73,8 @@
#include <asm/unaligned.h>
-#define DRIVER_DESC "PLX NET2280 USB Peripheral Controller"
-#define DRIVER_VERSION "2005 Feb 03"
+#define DRIVER_DESC "PLX NET228x USB Peripheral Controller"
+#define DRIVER_VERSION "2005 Sept 27"
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define EP_DONTUSE 13 /* nonzero */
@@ -118,7 +120,7 @@ module_param (fifo_mode, ushort, 0644);
/* enable_suspend -- When enabled, the driver will respond to
* USB suspend requests by powering down the NET2280. Otherwise,
* USB suspend requests will be ignored. This is acceptible for
- * self-powered devices, and helps avoid some quirks.
+ * self-powered devices
*/
static int enable_suspend = 0;
@@ -223,6 +225,11 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
ep->is_in = (tmp & USB_DIR_IN) != 0;
if (!ep->is_in)
writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
+ else if (dev->pdev->device != 0x2280) {
+ /* Added for 2282, Don't use nak packets on an in endpoint, this was ignored on 2280 */
+ writel ((1 << CLEAR_NAK_OUT_PACKETS)
+ | (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
+ }
writel (tmp, &ep->regs->ep_cfg);
@@ -232,8 +239,9 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
writel (tmp, &dev->regs->pciirqenb0);
tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
- | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
- | readl (&ep->regs->ep_irqenb);
+ | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE);
+ if (dev->pdev->device == 0x2280)
+ tmp |= readl (&ep->regs->ep_irqenb);
writel (tmp, &ep->regs->ep_irqenb);
} else { /* dma, per-request */
tmp = (1 << (8 + ep->num)); /* completion */
@@ -314,10 +322,18 @@ static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
/* init to our chosen defaults, notably so that we NAK OUT
* packets until the driver queues a read (+note erratum 0112)
*/
- tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
+ if (!ep->is_in || ep->dev->pdev->device == 0x2280) {
+ tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
| (1 << SET_NAK_OUT_PACKETS)
| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
| (1 << CLEAR_INTERRUPT_MODE);
+ } else {
+ /* added for 2282 */
+ tmp = (1 << CLEAR_NAK_OUT_PACKETS_MODE)
+ | (1 << CLEAR_NAK_OUT_PACKETS)
+ | (1 << CLEAR_EP_HIDE_STATUS_PHASE)
+ | (1 << CLEAR_INTERRUPT_MODE);
+ }
if (ep->num != 0) {
tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
@@ -326,14 +342,18 @@ static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
writel (tmp, &ep->regs->ep_rsp);
/* scrub most status bits, and flush any fifo state */
- writel ( (1 << TIMEOUT)
+ if (ep->dev->pdev->device == 0x2280)
+ tmp = (1 << FIFO_OVERFLOW)
+ | (1 << FIFO_UNDERFLOW);
+ else
+ tmp = 0;
+
+ writel (tmp | (1 << TIMEOUT)
| (1 << USB_STALL_SENT)
| (1 << USB_IN_NAK_SENT)
| (1 << USB_IN_ACK_RCVD)
| (1 << USB_OUT_PING_NAK_SENT)
| (1 << USB_OUT_ACK_SENT)
- | (1 << FIFO_OVERFLOW)
- | (1 << FIFO_UNDERFLOW)
| (1 << FIFO_FLUSH)
| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
@@ -718,7 +738,7 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
*/
if (ep->is_in)
dmacount |= (1 << DMA_DIRECTION);
- else if ((dmacount % ep->ep.maxpacket) != 0)
+ if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) || ep->dev->pdev->device != 0x2280)
dmacount |= (1 << END_OF_CHAIN);
req->valid = valid;
@@ -760,9 +780,12 @@ static inline void stop_dma (struct net2280_dma_regs __iomem *dma)
static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
{
struct net2280_dma_regs __iomem *dma = ep->dma;
+ unsigned int tmp = (1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION);
+
+ if (ep->dev->pdev->device != 0x2280)
+ tmp |= (1 << END_OF_CHAIN);
- writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION),
- &dma->dmacount);
+ writel (tmp, &dma->dmacount);
writel (readl (&dma->dmastat), &dma->dmastat);
writel (td_dma, &dma->dmadesc);
@@ -2110,7 +2133,11 @@ static void handle_ep_small (struct net2280_ep *ep)
VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n",
ep->ep.name, t, req ? &req->req : 0);
#endif
- writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
+ if (!ep->is_in || ep->dev->pdev->device == 0x2280)
+ writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
+ else
+ /* Added for 2282 */
+ writel (t, &ep->regs->ep_stat);
/* for ep0, monitor token irqs to catch data stage length errors
* and to synchronize on status.
@@ -2139,7 +2166,7 @@ static void handle_ep_small (struct net2280_ep *ep)
ep->stopped = 1;
set_halt (ep);
mode = 2;
- } else if (!req && ep->stopped)
+ } else if (!req && !ep->stopped)
write_fifo (ep, NULL);
}
} else {
@@ -2214,7 +2241,8 @@ static void handle_ep_small (struct net2280_ep *ep)
if (likely (req)) {
req->td->dmacount = 0;
t = readl (&ep->regs->ep_avail);
- dma_done (ep, req, count, t);
+ dma_done (ep, req, count,
+ (ep->out_overflow || t) ? -EOVERFLOW : 0);
}
/* also flush to prevent erratum 0106 trouble */
@@ -2252,9 +2280,7 @@ static void handle_ep_small (struct net2280_ep *ep)
/* if we wrote it all, we're usually done */
if (req->req.actual == req->req.length) {
if (ep->num == 0) {
- /* wait for control status */
- if (mode != 2)
- req = NULL;
+ /* send zlps until the status stage */
} else if (!req->req.zero || len != ep->ep.maxpacket)
mode = 2;
}
@@ -2337,7 +2363,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
u32 raw [2];
struct usb_ctrlrequest r;
} u;
- int tmp = 0;
+ int tmp;
struct net2280_request *req;
if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
@@ -2364,14 +2390,19 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
}
ep->stopped = 0;
dev->protocol_stall = 0;
- writel ( (1 << TIMEOUT)
+
+ if (ep->dev->pdev->device == 0x2280)
+ tmp = (1 << FIFO_OVERFLOW)
+ | (1 << FIFO_UNDERFLOW);
+ else
+ tmp = 0;
+
+ writel (tmp | (1 << TIMEOUT)
| (1 << USB_STALL_SENT)
| (1 << USB_IN_NAK_SENT)
| (1 << USB_IN_ACK_RCVD)
| (1 << USB_OUT_PING_NAK_SENT)
| (1 << USB_OUT_ACK_SENT)
- | (1 << FIFO_OVERFLOW)
- | (1 << FIFO_UNDERFLOW)
| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
@@ -2385,6 +2416,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
cpu_to_le32s (&u.raw [0]);
cpu_to_le32s (&u.raw [1]);
+ tmp = 0;
+
#define w_value le16_to_cpup (&u.r.wValue)
#define w_index le16_to_cpup (&u.r.wIndex)
#define w_length le16_to_cpup (&u.r.wLength)
@@ -2594,10 +2627,17 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
writel (stat, &dev->regs->irqstat1);
/* some status we can just ignore */
- stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
- | (1 << SUSPEND_REQUEST_INTERRUPT)
- | (1 << RESUME_INTERRUPT)
- | (1 << SOF_INTERRUPT));
+ if (dev->pdev->device == 0x2280)
+ stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
+ | (1 << SUSPEND_REQUEST_INTERRUPT)
+ | (1 << RESUME_INTERRUPT)
+ | (1 << SOF_INTERRUPT));
+ else
+ stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
+ | (1 << RESUME_INTERRUPT)
+ | (1 << SOF_DOWN_INTERRUPT)
+ | (1 << SOF_INTERRUPT));
+
if (!stat)
return;
// DEBUG (dev, "irqstat1 %08x\n", stat);
@@ -2702,6 +2742,10 @@ static irqreturn_t net2280_irq (int irq, void *_dev, struct pt_regs * r)
{
struct net2280 *dev = _dev;
+ /* shared interrupt, not ours */
+ if (!(readl(&dev->regs->irqstat0) & (1 << INTA_ASSERTED)))
+ return IRQ_NONE;
+
spin_lock (&dev->lock);
/* handle disconnect, dma, and more */
@@ -2789,13 +2833,13 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
}
/* alloc, and start init */
- dev = kmalloc (sizeof *dev, SLAB_KERNEL);
+ dev = kzalloc (sizeof *dev, SLAB_KERNEL);
if (dev == NULL){
retval = -ENOMEM;
goto done;
}
- memset (dev, 0, sizeof *dev);
+ pci_set_drvdata (pdev, dev);
spin_lock_init (&dev->lock);
dev->pdev = pdev;
dev->gadget.ops = &net2280_ops;
@@ -2908,7 +2952,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff;
/* done */
- pci_set_drvdata (pdev, dev);
INFO (dev, "%s\n", driver_desc);
INFO (dev, "irq %s, pci mem %p, chip rev %04x\n",
bufp, base, dev->chiprev);
@@ -2939,6 +2982,13 @@ static struct pci_device_id pci_ids [] = { {
.device = 0x2280,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+}, {
+ .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+ .class_mask = ~0,
+ .vendor = 0x17cc,
+ .device = 0x2282,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
}, { /* end: all zeroes */ }
};
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index fff4509cf34..957d6df3401 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -22,420 +22,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/*-------------------------------------------------------------------------*/
-
-/* NET2280 MEMORY MAPPED REGISTERS
- *
- * The register layout came from the chip documentation, and the bit
- * number definitions were extracted from chip specification.
- *
- * Use the shift operator ('<<') to build bit masks, with readl/writel
- * to access the registers through PCI.
- */
-
-/* main registers, BAR0 + 0x0000 */
-struct net2280_regs {
- // offset 0x0000
- u32 devinit;
-#define LOCAL_CLOCK_FREQUENCY 8
-#define FORCE_PCI_RESET 7
-#define PCI_ID 6
-#define PCI_ENABLE 5
-#define FIFO_SOFT_RESET 4
-#define CFG_SOFT_RESET 3
-#define PCI_SOFT_RESET 2
-#define USB_SOFT_RESET 1
-#define M8051_RESET 0
- u32 eectl;
-#define EEPROM_ADDRESS_WIDTH 23
-#define EEPROM_CHIP_SELECT_ACTIVE 22
-#define EEPROM_PRESENT 21
-#define EEPROM_VALID 20
-#define EEPROM_BUSY 19
-#define EEPROM_CHIP_SELECT_ENABLE 18
-#define EEPROM_BYTE_READ_START 17
-#define EEPROM_BYTE_WRITE_START 16
-#define EEPROM_READ_DATA 8
-#define EEPROM_WRITE_DATA 0
- u32 eeclkfreq;
- u32 _unused0;
- // offset 0x0010
-
- u32 pciirqenb0; /* interrupt PCI master ... */
-#define SETUP_PACKET_INTERRUPT_ENABLE 7
-#define ENDPOINT_F_INTERRUPT_ENABLE 6
-#define ENDPOINT_E_INTERRUPT_ENABLE 5
-#define ENDPOINT_D_INTERRUPT_ENABLE 4
-#define ENDPOINT_C_INTERRUPT_ENABLE 3
-#define ENDPOINT_B_INTERRUPT_ENABLE 2
-#define ENDPOINT_A_INTERRUPT_ENABLE 1
-#define ENDPOINT_0_INTERRUPT_ENABLE 0
- u32 pciirqenb1;
-#define PCI_INTERRUPT_ENABLE 31
-#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
-#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
-#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
-#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
-#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
-#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18
-#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
-#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
-#define GPIO_INTERRUPT_ENABLE 13
-#define DMA_D_INTERRUPT_ENABLE 12
-#define DMA_C_INTERRUPT_ENABLE 11
-#define DMA_B_INTERRUPT_ENABLE 10
-#define DMA_A_INTERRUPT_ENABLE 9
-#define EEPROM_DONE_INTERRUPT_ENABLE 8
-#define VBUS_INTERRUPT_ENABLE 7
-#define CONTROL_STATUS_INTERRUPT_ENABLE 6
-#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
-#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
-#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
-#define RESUME_INTERRUPT_ENABLE 1
-#define SOF_INTERRUPT_ENABLE 0
- u32 cpu_irqenb0; /* ... or onboard 8051 */
-#define SETUP_PACKET_INTERRUPT_ENABLE 7
-#define ENDPOINT_F_INTERRUPT_ENABLE 6
-#define ENDPOINT_E_INTERRUPT_ENABLE 5
-#define ENDPOINT_D_INTERRUPT_ENABLE 4
-#define ENDPOINT_C_INTERRUPT_ENABLE 3
-#define ENDPOINT_B_INTERRUPT_ENABLE 2
-#define ENDPOINT_A_INTERRUPT_ENABLE 1
-#define ENDPOINT_0_INTERRUPT_ENABLE 0
- u32 cpu_irqenb1;
-#define CPU_INTERRUPT_ENABLE 31
-#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
-#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
-#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
-#define PCI_INTA_INTERRUPT_ENABLE 24
-#define PCI_PME_INTERRUPT_ENABLE 23
-#define PCI_SERR_INTERRUPT_ENABLE 22
-#define PCI_PERR_INTERRUPT_ENABLE 21
-#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
-#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
-#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
-#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
-#define GPIO_INTERRUPT_ENABLE 13
-#define DMA_D_INTERRUPT_ENABLE 12
-#define DMA_C_INTERRUPT_ENABLE 11
-#define DMA_B_INTERRUPT_ENABLE 10
-#define DMA_A_INTERRUPT_ENABLE 9
-#define EEPROM_DONE_INTERRUPT_ENABLE 8
-#define VBUS_INTERRUPT_ENABLE 7
-#define CONTROL_STATUS_INTERRUPT_ENABLE 6
-#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
-#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
-#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
-#define RESUME_INTERRUPT_ENABLE 1
-#define SOF_INTERRUPT_ENABLE 0
-
- // offset 0x0020
- u32 _unused1;
- u32 usbirqenb1;
-#define USB_INTERRUPT_ENABLE 31
-#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
-#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
-#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
-#define PCI_INTA_INTERRUPT_ENABLE 24
-#define PCI_PME_INTERRUPT_ENABLE 23
-#define PCI_SERR_INTERRUPT_ENABLE 22
-#define PCI_PERR_INTERRUPT_ENABLE 21
-#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
-#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
-#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
-#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
-#define GPIO_INTERRUPT_ENABLE 13
-#define DMA_D_INTERRUPT_ENABLE 12
-#define DMA_C_INTERRUPT_ENABLE 11
-#define DMA_B_INTERRUPT_ENABLE 10
-#define DMA_A_INTERRUPT_ENABLE 9
-#define EEPROM_DONE_INTERRUPT_ENABLE 8
-#define VBUS_INTERRUPT_ENABLE 7
-#define CONTROL_STATUS_INTERRUPT_ENABLE 6
-#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
-#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
-#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
-#define RESUME_INTERRUPT_ENABLE 1
-#define SOF_INTERRUPT_ENABLE 0
- u32 irqstat0;
-#define INTA_ASSERTED 12
-#define SETUP_PACKET_INTERRUPT 7
-#define ENDPOINT_F_INTERRUPT 6
-#define ENDPOINT_E_INTERRUPT 5
-#define ENDPOINT_D_INTERRUPT 4
-#define ENDPOINT_C_INTERRUPT 3
-#define ENDPOINT_B_INTERRUPT 2
-#define ENDPOINT_A_INTERRUPT 1
-#define ENDPOINT_0_INTERRUPT 0
- u32 irqstat1;
-#define POWER_STATE_CHANGE_INTERRUPT 27
-#define PCI_ARBITER_TIMEOUT_INTERRUPT 26
-#define PCI_PARITY_ERROR_INTERRUPT 25
-#define PCI_INTA_INTERRUPT 24
-#define PCI_PME_INTERRUPT 23
-#define PCI_SERR_INTERRUPT 22
-#define PCI_PERR_INTERRUPT 21
-#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20
-#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19
-#define PCI_RETRY_ABORT_INTERRUPT 17
-#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16
-#define GPIO_INTERRUPT 13
-#define DMA_D_INTERRUPT 12
-#define DMA_C_INTERRUPT 11
-#define DMA_B_INTERRUPT 10
-#define DMA_A_INTERRUPT 9
-#define EEPROM_DONE_INTERRUPT 8
-#define VBUS_INTERRUPT 7
-#define CONTROL_STATUS_INTERRUPT 6
-#define ROOT_PORT_RESET_INTERRUPT 4
-#define SUSPEND_REQUEST_INTERRUPT 3
-#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2
-#define RESUME_INTERRUPT 1
-#define SOF_INTERRUPT 0
- // offset 0x0030
- u32 idxaddr;
- u32 idxdata;
- u32 fifoctl;
-#define PCI_BASE2_RANGE 16
-#define IGNORE_FIFO_AVAILABILITY 3
-#define PCI_BASE2_SELECT 2
-#define FIFO_CONFIGURATION_SELECT 0
- u32 _unused2;
- // offset 0x0040
- u32 memaddr;
-#define START 28
-#define DIRECTION 27
-#define FIFO_DIAGNOSTIC_SELECT 24
-#define MEMORY_ADDRESS 0
- u32 memdata0;
- u32 memdata1;
- u32 _unused3;
- // offset 0x0050
- u32 gpioctl;
-#define GPIO3_LED_SELECT 12
-#define GPIO3_INTERRUPT_ENABLE 11
-#define GPIO2_INTERRUPT_ENABLE 10
-#define GPIO1_INTERRUPT_ENABLE 9
-#define GPIO0_INTERRUPT_ENABLE 8
-#define GPIO3_OUTPUT_ENABLE 7
-#define GPIO2_OUTPUT_ENABLE 6
-#define GPIO1_OUTPUT_ENABLE 5
-#define GPIO0_OUTPUT_ENABLE 4
-#define GPIO3_DATA 3
-#define GPIO2_DATA 2
-#define GPIO1_DATA 1
-#define GPIO0_DATA 0
- u32 gpiostat;
-#define GPIO3_INTERRUPT 3
-#define GPIO2_INTERRUPT 2
-#define GPIO1_INTERRUPT 1
-#define GPIO0_INTERRUPT 0
-} __attribute__ ((packed));
-
-/* usb control, BAR0 + 0x0080 */
-struct net2280_usb_regs {
- // offset 0x0080
- u32 stdrsp;
-#define STALL_UNSUPPORTED_REQUESTS 31
-#define SET_TEST_MODE 16
-#define GET_OTHER_SPEED_CONFIGURATION 15
-#define GET_DEVICE_QUALIFIER 14
-#define SET_ADDRESS 13
-#define ENDPOINT_SET_CLEAR_HALT 12
-#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11
-#define GET_STRING_DESCRIPTOR_2 10
-#define GET_STRING_DESCRIPTOR_1 9
-#define GET_STRING_DESCRIPTOR_0 8
-#define GET_SET_INTERFACE 6
-#define GET_SET_CONFIGURATION 5
-#define GET_CONFIGURATION_DESCRIPTOR 4
-#define GET_DEVICE_DESCRIPTOR 3
-#define GET_ENDPOINT_STATUS 2
-#define GET_INTERFACE_STATUS 1
-#define GET_DEVICE_STATUS 0
- u32 prodvendid;
-#define PRODUCT_ID 16
-#define VENDOR_ID 0
- u32 relnum;
- u32 usbctl;
-#define SERIAL_NUMBER_INDEX 16
-#define PRODUCT_ID_STRING_ENABLE 13
-#define VENDOR_ID_STRING_ENABLE 12
-#define USB_ROOT_PORT_WAKEUP_ENABLE 11
-#define VBUS_PIN 10
-#define TIMED_DISCONNECT 9
-#define SUSPEND_IMMEDIATELY 7
-#define SELF_POWERED_USB_DEVICE 6
-#define REMOTE_WAKEUP_SUPPORT 5
-#define PME_POLARITY 4
-#define USB_DETECT_ENABLE 3
-#define PME_WAKEUP_ENABLE 2
-#define DEVICE_REMOTE_WAKEUP_ENABLE 1
-#define SELF_POWERED_STATUS 0
- // offset 0x0090
- u32 usbstat;
-#define HIGH_SPEED 7
-#define FULL_SPEED 6
-#define GENERATE_RESUME 5
-#define GENERATE_DEVICE_REMOTE_WAKEUP 4
- u32 xcvrdiag;
-#define FORCE_HIGH_SPEED_MODE 31
-#define FORCE_FULL_SPEED_MODE 30
-#define USB_TEST_MODE 24
-#define LINE_STATE 16
-#define TRANSCEIVER_OPERATION_MODE 2
-#define TRANSCEIVER_SELECT 1
-#define TERMINATION_SELECT 0
- u32 setup0123;
- u32 setup4567;
- // offset 0x0090
- u32 _unused0;
- u32 ouraddr;
-#define FORCE_IMMEDIATE 7
-#define OUR_USB_ADDRESS 0
- u32 ourconfig;
-} __attribute__ ((packed));
-
-/* pci control, BAR0 + 0x0100 */
-struct net2280_pci_regs {
- // offset 0x0100
- u32 pcimstctl;
-#define PCI_ARBITER_PARK_SELECT 13
-#define PCI_MULTI LEVEL_ARBITER 12
-#define PCI_RETRY_ABORT_ENABLE 11
-#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10
-#define DMA_READ_MULTIPLE_ENABLE 9
-#define DMA_READ_LINE_ENABLE 8
-#define PCI_MASTER_COMMAND_SELECT 6
-#define MEM_READ_OR_WRITE 0
-#define IO_READ_OR_WRITE 1
-#define CFG_READ_OR_WRITE 2
-#define PCI_MASTER_START 5
-#define PCI_MASTER_READ_WRITE 4
-#define PCI_MASTER_WRITE 0
-#define PCI_MASTER_READ 1
-#define PCI_MASTER_BYTE_WRITE_ENABLES 0
- u32 pcimstaddr;
- u32 pcimstdata;
- u32 pcimststat;
-#define PCI_ARBITER_CLEAR 2
-#define PCI_EXTERNAL_ARBITER 1
-#define PCI_HOST_MODE 0
-} __attribute__ ((packed));
-
-/* dma control, BAR0 + 0x0180 ... array of four structs like this,
- * for channels 0..3. see also struct net2280_dma: descriptor
- * that can be loaded into some of these registers.
- */
-struct net2280_dma_regs { /* [11.7] */
- // offset 0x0180, 0x01a0, 0x01c0, 0x01e0,
- u32 dmactl;
-#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25
-#define DMA_CLEAR_COUNT_ENABLE 21
-#define DESCRIPTOR_POLLING_RATE 19
-#define POLL_CONTINUOUS 0
-#define POLL_1_USEC 1
-#define POLL_100_USEC 2
-#define POLL_1_MSEC 3
-#define DMA_VALID_BIT_POLLING_ENABLE 18
-#define DMA_VALID_BIT_ENABLE 17
-#define DMA_SCATTER_GATHER_ENABLE 16
-#define DMA_OUT_AUTO_START_ENABLE 4
-#define DMA_PREEMPT_ENABLE 3
-#define DMA_FIFO_VALIDATE 2
-#define DMA_ENABLE 1
-#define DMA_ADDRESS_HOLD 0
- u32 dmastat;
-#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25
-#define DMA_TRANSACTION_DONE_INTERRUPT 24
-#define DMA_ABORT 1
-#define DMA_START 0
- u32 _unused0 [2];
- // offset 0x0190, 0x01b0, 0x01d0, 0x01f0,
- u32 dmacount;
-#define VALID_BIT 31
-#define DMA_DIRECTION 30
-#define DMA_DONE_INTERRUPT_ENABLE 29
-#define END_OF_CHAIN 28
-#define DMA_BYTE_COUNT_MASK ((1<<24)-1)
-#define DMA_BYTE_COUNT 0
- u32 dmaaddr;
- u32 dmadesc;
- u32 _unused1;
-} __attribute__ ((packed));
-
-/* dedicated endpoint registers, BAR0 + 0x0200 */
-
-struct net2280_dep_regs { /* [11.8] */
- // offset 0x0200, 0x0210, 0x220, 0x230, 0x240
- u32 dep_cfg;
- // offset 0x0204, 0x0214, 0x224, 0x234, 0x244
- u32 dep_rsp;
- u32 _unused [2];
-} __attribute__ ((packed));
-
-/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
- * like this, for ep0 then the configurable endpoints A..F
- * ep0 reserved for control; E and F have only 64 bytes of fifo
- */
-struct net2280_ep_regs { /* [11.9] */
- // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0
- u32 ep_cfg;
-#define ENDPOINT_BYTE_COUNT 16
-#define ENDPOINT_ENABLE 10
-#define ENDPOINT_TYPE 8
-#define ENDPOINT_DIRECTION 7
-#define ENDPOINT_NUMBER 0
- u32 ep_rsp;
-#define SET_NAK_OUT_PACKETS 15
-#define SET_EP_HIDE_STATUS_PHASE 14
-#define SET_EP_FORCE_CRC_ERROR 13
-#define SET_INTERRUPT_MODE 12
-#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11
-#define SET_NAK_OUT_PACKETS_MODE 10
-#define SET_ENDPOINT_TOGGLE 9
-#define SET_ENDPOINT_HALT 8
-#define CLEAR_NAK_OUT_PACKETS 7
-#define CLEAR_EP_HIDE_STATUS_PHASE 6
-#define CLEAR_EP_FORCE_CRC_ERROR 5
-#define CLEAR_INTERRUPT_MODE 4
-#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3
-#define CLEAR_NAK_OUT_PACKETS_MODE 2
-#define CLEAR_ENDPOINT_TOGGLE 1
-#define CLEAR_ENDPOINT_HALT 0
- u32 ep_irqenb;
-#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6
-#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5
-#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3
-#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2
-#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1
-#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0
- u32 ep_stat;
-#define FIFO_VALID_COUNT 24
-#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22
-#define TIMEOUT 21
-#define USB_STALL_SENT 20
-#define USB_IN_NAK_SENT 19
-#define USB_IN_ACK_RCVD 18
-#define USB_OUT_PING_NAK_SENT 17
-#define USB_OUT_ACK_SENT 16
-#define FIFO_OVERFLOW 13
-#define FIFO_UNDERFLOW 12
-#define FIFO_FULL 11
-#define FIFO_EMPTY 10
-#define FIFO_FLUSH 9
-#define SHORT_PACKET_OUT_DONE_INTERRUPT 6
-#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5
-#define NAK_OUT_PACKETS 4
-#define DATA_PACKET_RECEIVED_INTERRUPT 3
-#define DATA_PACKET_TRANSMITTED_INTERRUPT 2
-#define DATA_OUT_PING_TOKEN_INTERRUPT 1
-#define DATA_IN_TOKEN_INTERRUPT 0
- // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0
- u32 ep_avail;
- u32 ep_data;
- u32 _unused0 [2];
-} __attribute__ ((packed));
+#include <linux/usb/net2280.h>
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 51424f66a76..68e3d8f5da8 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -572,9 +572,10 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
switch (status) {
case 0: /* normal completion? */
- if (ep == dev->out_ep)
+ if (ep == dev->out_ep) {
check_read_data (dev, ep, req);
- else
+ memset (req->buf, 0x55, req->length);
+ } else
reinit_write_data (dev, ep, req);
break;
@@ -626,6 +627,8 @@ source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags)
if (strcmp (ep->name, EP_IN_NAME) == 0)
reinit_write_data (ep->driver_data, ep, req);
+ else
+ memset (req->buf, 0x55, req->length);
status = usb_ep_queue (ep, req, gfp_flags);
if (status) {
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 1e03f1a5a5f..a1bd2bea6de 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -350,7 +350,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
/* PCI driver selection metadata; PCI hotplugging uses this */
static const struct pci_device_id pci_ids [] = { {
/* handle any USB 2.0 EHCI controller */
- PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0),
+ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0),
.driver_data = (unsigned long) &ehci_pci_hc_driver,
},
{ /* end: all zeroes */ }
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 980030d684d..6b7350b5241 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -20,7 +20,7 @@
#include <asm/arch/board.h>
#ifndef CONFIG_ARCH_AT91RM9200
-#error "This file is AT91RM9200 bus glue. CONFIG_ARCH_AT91RM9200 must be defined."
+#error "CONFIG_ARCH_AT91RM9200 must be defined."
#endif
/* interface and function clocks */
@@ -84,8 +84,6 @@ static int usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
* Allocates basic resources for this USB host controller, and
* then invokes the start() method for the HCD associated with it
* through the hotplug entry's driver_data.
- *
- * Store this function in the HCD's struct pci_driver as probe().
*/
int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev)
{
@@ -148,7 +146,6 @@ int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *
}
-/* may be called without controller electrically present */
/* may be called with controller, bus, and devices active */
/**
@@ -166,11 +163,11 @@ static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pde
usb_remove_hcd(hcd);
at91_stop_hc(pdev);
iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- clk_put(fclk);
- clk_put(iclk);
- fclk = iclk = NULL;
+ clk_put(fclk);
+ clk_put(iclk);
+ fclk = iclk = NULL;
dev_set_drvdata(&pdev->dev, NULL);
return 0;
@@ -235,8 +232,8 @@ static const struct hc_driver ohci_at91_hc_driver = {
.hub_control = ohci_hub_control,
#ifdef CONFIG_PM
- .hub_suspend = ohci_hub_suspend,
- .hub_resume = ohci_hub_resume,
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
#endif
.start_port_reset = ohci_start_port_reset,
};
@@ -254,21 +251,21 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *dev)
}
#ifdef CONFIG_PM
-static int ohci_hcd_at91_drv_suspend(struct platform_device *dev, u32 state, u32 level)
-{
- printk("%s(%s:%d): not implemented yet\n",
- __func__, __FILE__, __LINE__);
+/* REVISIT suspend/resume look "too" simple here */
+
+static int
+ohci_hcd_at91_drv_suspend(struct platform_device *dev, pm_message_t mesg)
+{
clk_disable(fclk);
+ clk_disable(iclk);
return 0;
}
-static int ohci_hcd_at91_drv_resume(struct platform_device *dev, u32 state)
+static int ohci_hcd_at91_drv_resume(struct platform_device *dev)
{
- printk("%s(%s:%d): not implemented yet\n",
- __func__, __FILE__, __LINE__);
-
+ clk_enable(iclk);
clk_enable(fclk);
return 0;
@@ -278,6 +275,8 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *dev, u32 state)
#define ohci_hcd_at91_drv_resume NULL
#endif
+MODULE_ALIAS("at91rm9200-ohci");
+
static struct platform_driver ohci_hcd_at91_driver = {
.probe = ohci_hcd_at91_drv_probe,
.remove = ohci_hcd_at91_drv_remove,
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 544f7589912..73f5a379d9b 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -863,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
i = ohci->num_ports;
while (i--)
ohci_writel (ohci, RH_PS_PSS,
- &ohci->regs->roothub.portstatus [temp]);
+ &ohci->regs->roothub.portstatus [i]);
ohci_dbg (ohci, "restart complete\n");
}
return 0;
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 1bfe96f4d04..b268537e389 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -206,7 +206,7 @@ static const struct hc_driver ohci_pci_hc_driver = {
static const struct pci_device_id pci_ids [] = { {
/* handle any USB OHCI controller */
- PCI_DEVICE_CLASS((PCI_CLASS_SERIAL_USB << 8) | 0x10, ~0),
+ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0),
.driver_data = (unsigned long) &ohci_pci_hc_driver,
}, { /* end: all zeroes */ }
};
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index acde8868da2..fafe7c1265b 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -185,6 +185,9 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
/* Select Power Management Mode */
pxa27x_ohci_select_pmm(inf->port_mode);
+ if (inf->power_budget)
+ hcd->power_budget = inf->power_budget;
+
ohci_hcd_init(hcd_to_ohci(hcd));
retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 372527a8359..1da5de573a6 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -30,6 +30,7 @@
/* clock device associated with the hcd */
static struct clk *clk;
+static struct clk *usb_clk;
/* forward definitions */
@@ -37,7 +38,7 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc);
/* conversion functions */
-struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd)
+static struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd)
{
return hcd->self.controller->platform_data;
}
@@ -47,6 +48,10 @@ static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd)
struct s3c2410_hcd_info *info = dev->dev.platform_data;
dev_dbg(&dev->dev, "s3c2410_start_hc:\n");
+
+ clk_enable(usb_clk);
+ mdelay(2); /* let the bus clock stabilise */
+
clk_enable(clk);
if (info != NULL) {
@@ -75,6 +80,7 @@ static void s3c2410_stop_hc(struct platform_device *dev)
}
clk_disable(clk);
+ clk_disable(usb_clk);
}
/* ohci_s3c2410_hub_status_data
@@ -158,7 +164,7 @@ static int ohci_s3c2410_hub_control (
"s3c2410_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n",
hcd, typeReq, wValue, wIndex, buf, wLength);
- /* if we are only an humble host without any special capabilites
+ /* if we are only an humble host without any special capabilities
* process the request straight away and exit */
if (info == NULL) {
@@ -316,7 +322,8 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc)
*
*/
-void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev)
+static void
+usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev)
{
usb_remove_hcd(hcd);
s3c2410_stop_hc(dev);
@@ -334,8 +341,8 @@ void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev)
* through the hotplug entry's driver_data.
*
*/
-int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
- struct platform_device *dev)
+static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
+ struct platform_device *dev)
{
struct usb_hcd *hcd = NULL;
int retval;
@@ -353,14 +360,21 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
dev_err(&dev->dev, "request_mem_region failed");
retval = -EBUSY;
- goto err0;
+ goto err_put;
}
- clk = clk_get(NULL, "usb-host");
+ clk = clk_get(&dev->dev, "usb-host");
if (IS_ERR(clk)) {
dev_err(&dev->dev, "cannot get usb-host clock\n");
retval = -ENOENT;
- goto err1;
+ goto err_mem;
+ }
+
+ usb_clk = clk_get(&dev->dev, "upll");
+ if (IS_ERR(usb_clk)) {
+ dev_err(&dev->dev, "cannot get usb-host clock\n");
+ retval = -ENOENT;
+ goto err_clk;
}
s3c2410_start_hc(dev, hcd);
@@ -369,26 +383,29 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
if (!hcd->regs) {
dev_err(&dev->dev, "ioremap failed\n");
retval = -ENOMEM;
- goto err2;
+ goto err_ioremap;
}
ohci_hcd_init(hcd_to_ohci(hcd));
retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
if (retval != 0)
- goto err2;
+ goto err_ioremap;
return 0;
- err2:
+ err_ioremap:
s3c2410_stop_hc(dev);
iounmap(hcd->regs);
+ clk_put(usb_clk);
+
+ err_clk:
clk_put(clk);
- err1:
+ err_mem:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err0:
+ err_put:
usb_put_hcd(hcd);
return retval;
}
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 9e81c26313f..1045f846fbe 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/acpi.h>
+#include "pci-quirks.h"
#define UHCI_USBLEGSUP 0xc0 /* legacy support */
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
new file mode 100644
index 00000000000..1564edfff6f
--- /dev/null
+++ b/drivers/usb/host/pci-quirks.h
@@ -0,0 +1,7 @@
+#ifndef __LINUX_USB_PCI_QUIRKS_H
+#define __LINUX_USB_PCI_QUIRKS_H
+
+void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
+int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
+
+#endif /* __LINUX_USB_PCI_QUIRKS_H */
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 134d2000128..302aa1ec312 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -67,11 +67,11 @@ module_param(pc_debug, int, 0644);
static const char driver_name[DEV_NAME_LEN] = "sl811_cs";
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
} local_info_t;
-static void sl811_cs_release(dev_link_t * link);
+static void sl811_cs_release(struct pcmcia_device * link);
/*====================================================================*/
@@ -138,41 +138,27 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
/*====================================================================*/
-static void sl811_cs_detach(struct pcmcia_device *p_dev)
+static void sl811_cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DBG(0, "sl811_cs_detach(0x%p)\n", link);
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- sl811_cs_release(link);
+ sl811_cs_release(link);
/* This points to the parent local_info_t struct */
kfree(link->priv);
}
-static void sl811_cs_release(dev_link_t * link)
+static void sl811_cs_release(struct pcmcia_device * link)
{
-
DBG(0, "sl811_cs_release(0x%p)\n", link);
- /* Unlink the device chain */
- link->dev = NULL;
-
+ pcmcia_disable_device(link);
platform_device_unregister(&platform_dev);
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
}
-static void sl811_cs_config(dev_link_t *link)
+static int sl811_cs_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
- struct device *parent = &handle_to_dev(handle);
+ struct device *parent = &handle_to_dev(link);
local_info_t *dev = link->priv;
tuple_t tuple;
cisparse_t parse;
@@ -188,27 +174,23 @@ static void sl811_cs_config(dev_link_t *link)
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
- /* Configure card */
- link->state |= DEV_CONFIG;
-
/* Look up the current Vcc */
CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
+ pcmcia_get_configuration_info(link, &conf));
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0
- || pcmcia_parse_tuple(handle, &tuple, &parse)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0
+ || pcmcia_parse_tuple(link, &tuple, &parse)
!= 0)
goto next_entry;
@@ -234,10 +216,10 @@ static void sl811_cs_config(dev_link_t *link)
}
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
/* we need an interrupt */
@@ -254,15 +236,14 @@ static void sl811_cs_config(dev_link_t *link)
link->io.BasePort1 = io->win[0].base;
link->io.NumPorts1 = io->win[0].len;
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
break;
next_entry:
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ pcmcia_disable_device(link);
+ last_ret = pcmcia_get_next_tuple(link, &tuple);
}
/* require an IRQ and two registers */
@@ -270,71 +251,46 @@ next_entry:
goto cs_failed;
if (link->conf.Attributes & CONF_ENABLE_IRQ)
CS_CHECK(RequestIRQ,
- pcmcia_request_irq(link->handle, &link->irq));
+ pcmcia_request_irq(link, &link->irq));
else
goto cs_failed;
CS_CHECK(RequestConfiguration,
- pcmcia_request_configuration(link->handle, &link->conf));
+ pcmcia_request_configuration(link, &link->conf));
sprintf(dev->node.dev_name, driver_name);
dev->node.major = dev->node.minor = 0;
- link->dev = &dev->node;
+ link->dev_node = &dev->node;
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev->node.dev_name, link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "%s: index 0x%02x: ",
+ dev->node.dev_name, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
printk(", irq %d", link->irq.AssignedIRQ);
printk(", io 0x%04x-0x%04x", link->io.BasePort1,
link->io.BasePort1+link->io.NumPorts1-1);
printk("\n");
- link->state &= ~DEV_CONFIG_PENDING;
-
if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ)
< 0) {
cs_failed:
printk("sl811_cs_config failed\n");
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
sl811_cs_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
+ return -ENODEV;
}
-}
-
-static int sl811_suspend(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state |= DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
- return 0;
-}
-
-static int sl811_resume(struct pcmcia_device *dev)
-{
- dev_link_t *link = dev_to_instance(dev);
-
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
-
return 0;
}
-static int sl811_cs_attach(struct pcmcia_device *p_dev)
+static int sl811_cs_probe(struct pcmcia_device *link)
{
local_info_t *local;
- dev_link_t *link;
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local)
return -ENOMEM;
memset(local, 0, sizeof(local_info_t));
- link = &local->link;
+ local->p_dev = link;
link->priv = local;
/* Initialize */
@@ -343,16 +299,9 @@ static int sl811_cs_attach(struct pcmcia_device *p_dev)
link->irq.Handler = NULL;
link->conf.Attributes = 0;
- link->conf.Vcc = 33;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- sl811_cs_config(link);
-
- return 0;
+ return sl811_cs_config(link);
}
static struct pcmcia_device_id sl811_ids[] = {
@@ -366,11 +315,9 @@ static struct pcmcia_driver sl811_cs_driver = {
.drv = {
.name = (char *)driver_name,
},
- .probe = sl811_cs_attach,
+ .probe = sl811_cs_probe,
.remove = sl811_cs_detach,
.id_table = sl811_ids,
- .suspend = sl811_suspend,
- .resume = sl811_resume,
};
/*====================================================================*/
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 4edb8330c44..d225e11f405 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -50,6 +50,7 @@
#include "../core/hcd.h"
#include "uhci-hcd.h"
+#include "pci-quirks.h"
/*
* Version Information
@@ -100,9 +101,6 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
#include "uhci-q.c"
#include "uhci-hub.c"
-extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
-extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
-
/*
* Finish up a host controller reset and update the recorded state.
*/
@@ -117,8 +115,7 @@ static void finish_reset(struct uhci_hcd *uhci)
for (port = 0; port < uhci->rh_numports; ++port)
outw(0, uhci->io_addr + USBPORTSC1 + (port * 2));
- uhci->port_c_suspend = uhci->suspended_ports =
- uhci->resuming_ports = 0;
+ uhci->port_c_suspend = uhci->resuming_ports = 0;
uhci->rh_state = UHCI_RH_RESET;
uhci->is_stopped = UHCI_IS_STOPPED;
uhci_to_hcd(uhci)->state = HC_STATE_HALT;
@@ -861,7 +858,7 @@ static const struct hc_driver uhci_driver = {
static const struct pci_device_id uhci_pci_ids[] = { {
/* handle any USB UHCI controller */
- PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x00), ~0),
+ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_UHCI, ~0),
.driver_data = (unsigned long) &uhci_driver,
}, { /* end: all zeroes */ }
};
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 4a69c7eb09b..d5c8f4d9282 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -415,7 +415,6 @@ struct uhci_hcd {
/* Support for port suspend/resume/reset */
unsigned long port_c_suspend; /* Bit-arrays of ports */
- unsigned long suspended_ports;
unsigned long resuming_ports;
unsigned long ports_timeout; /* Time to stop signalling */
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 152971d1676..c8451d9578f 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -85,11 +85,10 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
{
int status;
- if (test_bit(port, &uhci->suspended_ports)) {
+ if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
- clear_bit(port, &uhci->suspended_ports);
- clear_bit(port, &uhci->resuming_ports);
- set_bit(port, &uhci->port_c_suspend);
+ if (test_bit(port, &uhci->resuming_ports))
+ set_bit(port, &uhci->port_c_suspend);
/* The controller won't actually turn off the RD bit until
* it has had a chance to send a low-speed EOP sequence,
@@ -97,6 +96,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
* slightly longer for good luck. */
udelay(4);
}
+ clear_bit(port, &uhci->resuming_ports);
}
/* Wait for the UHCI controller in HP's iLO2 server management chip.
@@ -265,8 +265,6 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
wPortChange |= USB_PORT_STAT_C_SUSPEND;
lstatus |= 1;
}
- if (test_bit(port, &uhci->suspended_ports))
- lstatus |= 2;
if (test_bit(port, &uhci->resuming_ports))
lstatus |= 4;
@@ -309,7 +307,6 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
- set_bit(port, &uhci->suspended_ports);
SET_RH_PORTSTAT(USBPORTSC_SUSP);
OK(0);
case USB_PORT_FEAT_RESET:
@@ -343,8 +340,11 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
CLR_RH_PORTSTAT(USBPORTSC_PEC);
OK(0);
case USB_PORT_FEAT_SUSPEND:
- if (test_bit(port, &uhci->suspended_ports) &&
- !test_and_set_bit(port,
+ if (!(inw(port_addr) & USBPORTSC_SUSP)) {
+
+ /* Make certain the port isn't suspended */
+ uhci_finish_suspend(uhci, port, port_addr);
+ } else if (!test_and_set_bit(port,
&uhci->resuming_ports)) {
SET_RH_PORTSTAT(USBPORTSC_RD);
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 5246b35301d..650103bc961 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -200,45 +200,41 @@ config USB_POWERMATE
To compile this driver as a module, choose M here: the
module will be called powermate.
-config USB_MTOUCH
- tristate "MicroTouch USB Touchscreen Driver"
+config USB_TOUCHSCREEN
+ tristate "USB Touchscreen Driver"
depends on USB && INPUT
---help---
- Say Y here if you want to use a MicroTouch (Now 3M) USB
- Touchscreen controller.
+ USB Touchscreen driver for:
+ - eGalax Touchkit USB
+ - PanJit TouchSet USB
+ - 3M MicroTouch USB
+ - ITM
- See <file:Documentation/usb/mtouch.txt> for additional information.
-
- To compile this driver as a module, choose M here: the
- module will be called mtouchusb.
-
-config USB_ITMTOUCH
- tristate "ITM Touch USB Touchscreen Driver"
- depends on USB && INPUT
- ---help---
- Say Y here if you want to use a ITM Touch USB
- Touchscreen controller.
-
- This touchscreen is used in LG 1510SF monitors.
+ Have a look at <http://linux.chapter7.ch/touchkit/> for
+ a usage description and the required user-space stuff.
To compile this driver as a module, choose M here: the
- module will be called itmtouch.
+ module will be called usbtouchscreen.
-config USB_EGALAX
- tristate "eGalax TouchKit USB Touchscreen Driver"
- depends on USB && INPUT
- ---help---
- Say Y here if you want to use a eGalax TouchKit USB
- Touchscreen controller.
+config USB_TOUCHSCREEN_EGALAX
+ default y
+ bool "eGalax device support" if EMBEDDED
+ depends on USB_TOUCHSCREEN
- The driver has been tested on a Xenarc 700TSV monitor
- with eGalax touchscreen.
+config USB_TOUCHSCREEN_PANJIT
+ default y
+ bool "PanJit device support" if EMBEDDED
+ depends on USB_TOUCHSCREEN
- Have a look at <http://linux.chapter7.ch/touchkit/> for
- a usage description and the required user-space stuff.
+config USB_TOUCHSCREEN_3M
+ default y
+ bool "3M/Microtouch device support" if EMBEDDED
+ depends on USB_TOUCHSCREEN
- To compile this driver as a module, choose M here: the
- module will be called touchkitusb.
+config USB_TOUCHSCREEN_ITM
+ default y
+ bool "ITM device support" if EMBEDDED
+ depends on USB_TOUCHSCREEN
config USB_YEALINK
tristate "Yealink usb-p1k voip phone"
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index d512d9f488f..764114529c5 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_USB_MOUSE) += usbmouse.o
obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o
obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o
obj-$(CONFIG_USB_EGALAX) += touchkitusb.o
+obj-$(CONFIG_USB_TOUCHSCREEN) += usbtouchscreen.o
obj-$(CONFIG_USB_POWERMATE) += powermate.o
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_ACECAD) += acecad.o
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index d4bf1701046..435273e7c85 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1372,6 +1372,11 @@ void hid_close(struct hid_device *hid)
usb_kill_urb(hid->urbin);
}
+#define USB_VENDOR_ID_PANJIT 0x134c
+
+#define USB_VENDOR_ID_SILVERCREST 0x062a
+#define USB_DEVICE_ID_SILVERCREST_KB 0x0201
+
/*
* Initialize all reports
*/
@@ -1552,6 +1557,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_HP 0x03f0
#define USB_DEVICE_ID_HP_USBHUB_KB 0x020c
+#define USB_VENDOR_ID_IBM 0x04b3
+#define USB_DEVICE_ID_IBM_USBHUB_KB 0x3005
+
#define USB_VENDOR_ID_CREATIVELABS 0x062a
#define USB_DEVICE_ID_CREATIVELABS_SILVERCREST 0x0201
@@ -1655,9 +1663,12 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 1, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 2, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 3, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 4, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 5, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_CINTIQ, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
@@ -1673,8 +1684,10 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
{ USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVELABS_SILVERCREST, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_USBHUB_KB, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+ { USB_VENDOR_ID_SILVERCREST, USB_DEVICE_ID_SILVERCREST_KB, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE },
{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
@@ -1701,6 +1714,11 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
+
{ 0, 0 }
};
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
index 72e698658b5..d5c91ee6799 100644
--- a/drivers/usb/input/hid-ff.c
+++ b/drivers/usb/input/hid-ff.c
@@ -34,12 +34,6 @@
#include "hid.h"
-/* Drivers' initializing functions */
-extern int hid_lgff_init(struct hid_device* hid);
-extern int hid_lg3d_init(struct hid_device* hid);
-extern int hid_pid_init(struct hid_device* hid);
-extern int hid_tmff_init(struct hid_device* hid);
-
/*
* This table contains pointers to initializers. To add support for new
* devices, you need to add the USB vendor and product ids here.
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index cb0d80f4925..25bc85f8ce3 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -510,7 +510,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x025: map_key_clear(KEY_TV); break;
case 0x026: map_key_clear(KEY_MENU); break;
case 0x031: map_key_clear(KEY_AUDIO); break;
- case 0x032: map_key_clear(KEY_SUBTITLE); break;
+ case 0x032: map_key_clear(KEY_TEXT); break;
case 0x033: map_key_clear(KEY_LAST); break;
case 0x047: map_key_clear(KEY_MP3); break;
case 0x048: map_key_clear(KEY_DVD); break;
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index 4e1b784fe52..9c62837b5b8 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -533,3 +533,8 @@ static inline int hid_ff_event(struct hid_device *hid, struct input_dev *input,
return hid->ff_event(hid, input, type, code, value);
return -ENOSYS;
}
+
+int hid_lgff_init(struct hid_device* hid);
+int hid_tmff_init(struct hid_device* hid);
+int hid_pid_init(struct hid_device* hid);
+
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 6dd66669617..c4670e1d465 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -317,6 +317,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
}
schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
}
set_current_state(TASK_RUNNING);
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index b4a051b549d..3d911976f37 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -297,6 +297,8 @@ static void keyspan_check_data(struct usb_keyspan *remote, struct pt_regs *regs)
remote->data.bits_left -= 6;
} else {
err("%s - Error in message, invalid toggle.\n", __FUNCTION__);
+ remote->stage = 0;
+ return;
}
keyspan_load_tester(remote, 5);
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
new file mode 100644
index 00000000000..e9a07c1e905
--- /dev/null
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -0,0 +1,605 @@
+/******************************************************************************
+ * usbtouchscreen.c
+ * Driver for USB Touchscreens, supporting those devices:
+ * - eGalax Touchkit
+ * - 3M/Microtouch
+ * - ITM
+ * - PanJit TouchSet
+ *
+ * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
+ * Copyright (C) by Todd E. Johnson (mtouchusb.c)
+ *
+ * This program is free software; you can redistribute it and/or
+ * 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.
+ *
+ * Driver is based on touchkitusb.c
+ * - ITM parts are from itmtouch.c
+ * - 3M parts are from mtouchusb.c
+ * - PanJit parts are from an unmerged driver by Lanslott Gish
+ *
+ *****************************************************************************/
+
+//#define DEBUG
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/usb_input.h>
+
+
+#define DRIVER_VERSION "v0.3"
+#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
+#define DRIVER_DESC "USB Touchscreen Driver"
+
+static int swap_xy;
+module_param(swap_xy, bool, 0644);
+MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
+
+/* device specifc data/functions */
+struct usbtouch_usb;
+struct usbtouch_device_info {
+ int min_xc, max_xc;
+ int min_yc, max_yc;
+ int min_press, max_press;
+ int rept_size;
+ int flags;
+
+ void (*process_pkt) (struct usbtouch_usb *usbtouch, struct pt_regs *regs, unsigned char *pkt, int len);
+ int (*read_data) (unsigned char *pkt, int *x, int *y, int *touch, int *press);
+ int (*init) (struct usbtouch_usb *usbtouch);
+};
+
+#define USBTOUCH_FLG_BUFFER 0x01
+
+
+/* a usbtouch device */
+struct usbtouch_usb {
+ unsigned char *data;
+ dma_addr_t data_dma;
+ unsigned char *buffer;
+ int buf_len;
+ struct urb *irq;
+ struct usb_device *udev;
+ struct input_dev *input;
+ struct usbtouch_device_info *type;
+ char name[128];
+ char phys[64];
+};
+
+static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
+ struct pt_regs *regs, unsigned char *pkt, int len);
+
+/* device types */
+enum {
+ DEVTPYE_DUMMY = -1,
+ DEVTYPE_EGALAX,
+ DEVTYPE_PANJIT,
+ DEVTYPE_3M,
+ DEVTYPE_ITM,
+};
+
+static struct usb_device_id usbtouch_devices[] = {
+#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+ {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
+ {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
+ {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX},
+ {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+ {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT},
+ {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT},
+ {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT},
+ {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_3M
+ {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+ {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
+#endif
+
+ {}
+};
+
+
+/*****************************************************************************
+ * eGalax part
+ */
+
+#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+
+#define EGALAX_PKT_TYPE_MASK 0xFE
+#define EGALAX_PKT_TYPE_REPT 0x80
+#define EGALAX_PKT_TYPE_DIAG 0x0A
+
+static int egalax_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+ if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT)
+ return 0;
+
+ *x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F);
+ *y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F);
+ *touch = pkt[0] & 0x01;
+
+ return 1;
+
+}
+
+static int egalax_get_pkt_len(unsigned char *buf)
+{
+ switch (buf[0] & EGALAX_PKT_TYPE_MASK) {
+ case EGALAX_PKT_TYPE_REPT:
+ return 5;
+
+ case EGALAX_PKT_TYPE_DIAG:
+ return buf[1] + 2;
+ }
+
+ return 0;
+}
+
+static void egalax_process(struct usbtouch_usb *usbtouch, struct pt_regs *regs,
+ unsigned char *pkt, int len)
+{
+ unsigned char *buffer;
+ int pkt_len, buf_len, pos;
+
+ /* if the buffer contains data, append */
+ if (unlikely(usbtouch->buf_len)) {
+ int tmp;
+
+ /* if only 1 byte in buffer, add another one to get length */
+ if (usbtouch->buf_len == 1)
+ usbtouch->buffer[1] = pkt[0];
+
+ pkt_len = egalax_get_pkt_len(usbtouch->buffer);
+
+ /* unknown packet: drop everything */
+ if (!pkt_len)
+ return;
+
+ /* append, process */
+ tmp = pkt_len - usbtouch->buf_len;
+ memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
+ usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len);
+
+ buffer = pkt + tmp;
+ buf_len = len - tmp;
+ } else {
+ buffer = pkt;
+ buf_len = len;
+ }
+
+ /* only one byte left in buffer */
+ if (unlikely(buf_len == 1)) {
+ usbtouch->buffer[0] = buffer[0];
+ usbtouch->buf_len = 1;
+ return;
+ }
+
+ /* loop over the buffer */
+ pos = 0;
+ while (pos < buf_len) {
+ /* get packet len */
+ pkt_len = egalax_get_pkt_len(buffer + pos);
+
+ /* unknown packet: drop everything */
+ if (unlikely(!pkt_len))
+ return;
+
+ /* full packet: process */
+ if (likely(pkt_len <= buf_len)) {
+ usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len);
+ } else {
+ /* incomplete packet: save in buffer */
+ memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
+ usbtouch->buf_len = buf_len - pos;
+ }
+ pos += pkt_len;
+ }
+}
+#endif
+
+
+/*****************************************************************************
+ * PanJit Part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+static int panjit_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+ *x = ((pkt[2] & 0x0F) << 8) | pkt[1];
+ *y = ((pkt[4] & 0x0F) << 8) | pkt[3];
+ *touch = pkt[0] & 0x01;
+
+ return 1;
+}
+#endif
+
+
+/*****************************************************************************
+ * 3M/Microtouch Part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_3M
+
+#define MTOUCHUSB_ASYNC_REPORT 1
+#define MTOUCHUSB_RESET 7
+#define MTOUCHUSB_REQ_CTRLLR_ID 10
+
+static int mtouch_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+ *x = (pkt[8] << 8) | pkt[7];
+ *y = (pkt[10] << 8) | pkt[9];
+ *touch = (pkt[2] & 0x40) ? 1 : 0;
+
+ return 1;
+}
+
+static int mtouch_init(struct usbtouch_usb *usbtouch)
+{
+ int ret;
+
+ ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
+ MTOUCHUSB_RESET,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
+ __FUNCTION__, ret);
+ if (ret < 0)
+ return ret;
+
+ ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
+ MTOUCHUSB_ASYNC_REPORT,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
+ __FUNCTION__, ret);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+#endif
+
+
+/*****************************************************************************
+ * ITM Part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+ *x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F);
+ *x = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
+ *press = ((pkt[2] & 0x1F) << 7) | (pkt[5] & 0x7F);
+ *touch = ~pkt[7] & 0x20;
+
+ return 1;
+}
+#endif
+
+
+/*****************************************************************************
+ * the different device descriptors
+ */
+static struct usbtouch_device_info usbtouch_dev_info[] = {
+#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+ [DEVTYPE_EGALAX] = {
+ .min_xc = 0x0,
+ .max_xc = 0x07ff,
+ .min_yc = 0x0,
+ .max_yc = 0x07ff,
+ .rept_size = 16,
+ .flags = USBTOUCH_FLG_BUFFER,
+ .process_pkt = egalax_process,
+ .read_data = egalax_read_data,
+ },
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+ [DEVTYPE_PANJIT] = {
+ .min_xc = 0x0,
+ .max_xc = 0x0fff,
+ .min_yc = 0x0,
+ .max_yc = 0x0fff,
+ .rept_size = 8,
+ .read_data = panjit_read_data,
+ },
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_3M
+ [DEVTYPE_3M] = {
+ .min_xc = 0x0,
+ .max_xc = 0x4000,
+ .min_yc = 0x0,
+ .max_yc = 0x4000,
+ .rept_size = 11,
+ .read_data = mtouch_read_data,
+ .init = mtouch_init,
+ },
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+ [DEVTYPE_ITM] = {
+ .min_xc = 0x0,
+ .max_xc = 0x0fff,
+ .min_yc = 0x0,
+ .max_yc = 0x0fff,
+ .max_press = 0xff,
+ .rept_size = 8,
+ .read_data = itm_read_data,
+ },
+#endif
+};
+
+
+/*****************************************************************************
+ * Generic Part
+ */
+static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
+ struct pt_regs *regs, unsigned char *pkt, int len)
+{
+ int x, y, touch, press;
+ struct usbtouch_device_info *type = usbtouch->type;
+
+ if (!type->read_data(pkt, &x, &y, &touch, &press))
+ return;
+
+ input_regs(usbtouch->input, regs);
+ input_report_key(usbtouch->input, BTN_TOUCH, touch);
+
+ if (swap_xy) {
+ input_report_abs(usbtouch->input, ABS_X, y);
+ input_report_abs(usbtouch->input, ABS_Y, x);
+ } else {
+ input_report_abs(usbtouch->input, ABS_X, x);
+ input_report_abs(usbtouch->input, ABS_Y, y);
+ }
+ if (type->max_press)
+ input_report_abs(usbtouch->input, ABS_PRESSURE, press);
+ input_sync(usbtouch->input);
+}
+
+
+static void usbtouch_irq(struct urb *urb, struct pt_regs *regs)
+{
+ struct usbtouch_usb *usbtouch = urb->context;
+ int retval;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ETIMEDOUT:
+ /* this urb is timing out */
+ dbg("%s - urb timed out - was the device unplugged?",
+ __FUNCTION__);
+ return;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, urb->status);
+ goto exit;
+ }
+
+ usbtouch->type->process_pkt(usbtouch, regs, usbtouch->data, urb->actual_length);
+
+exit:
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ err("%s - usb_submit_urb failed with result: %d",
+ __FUNCTION__, retval);
+}
+
+static int usbtouch_open(struct input_dev *input)
+{
+ struct usbtouch_usb *usbtouch = input->private;
+
+ usbtouch->irq->dev = usbtouch->udev;
+
+ if (usb_submit_urb(usbtouch->irq, GFP_KERNEL))
+ return -EIO;
+
+ return 0;
+}
+
+static void usbtouch_close(struct input_dev *input)
+{
+ struct usbtouch_usb *usbtouch = input->private;
+
+ usb_kill_urb(usbtouch->irq);
+}
+
+
+static void usbtouch_free_buffers(struct usb_device *udev,
+ struct usbtouch_usb *usbtouch)
+{
+ if (usbtouch->data)
+ usb_buffer_free(udev, usbtouch->type->rept_size,
+ usbtouch->data, usbtouch->data_dma);
+ kfree(usbtouch->buffer);
+}
+
+
+static int usbtouch_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usbtouch_usb *usbtouch;
+ struct input_dev *input_dev;
+ struct usb_host_interface *interface;
+ struct usb_endpoint_descriptor *endpoint;
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usbtouch_device_info *type;
+ int err;
+
+ interface = intf->cur_altsetting;
+ endpoint = &interface->endpoint[0].desc;
+
+ usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!usbtouch || !input_dev)
+ goto out_free;
+
+ type = &usbtouch_dev_info[id->driver_info];
+ usbtouch->type = type;
+ if (!type->process_pkt)
+ type->process_pkt = usbtouch_process_pkt;
+
+ usbtouch->data = usb_buffer_alloc(udev, type->rept_size,
+ SLAB_KERNEL, &usbtouch->data_dma);
+ if (!usbtouch->data)
+ goto out_free;
+
+ if (type->flags & USBTOUCH_FLG_BUFFER) {
+ usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL);
+ if (!usbtouch->buffer)
+ goto out_free_buffers;
+ }
+
+ usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (!usbtouch->irq) {
+ dbg("%s - usb_alloc_urb failed: usbtouch->irq", __FUNCTION__);
+ goto out_free_buffers;
+ }
+
+ usbtouch->udev = udev;
+ usbtouch->input = input_dev;
+
+ if (udev->manufacturer)
+ strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name));
+
+ if (udev->product) {
+ if (udev->manufacturer)
+ strlcat(usbtouch->name, " ", sizeof(usbtouch->name));
+ strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name));
+ }
+
+ if (!strlen(usbtouch->name))
+ snprintf(usbtouch->name, sizeof(usbtouch->name),
+ "USB Touchscreen %04x:%04x",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys));
+ strlcpy(usbtouch->phys, "/input0", sizeof(usbtouch->phys));
+
+ input_dev->name = usbtouch->name;
+ input_dev->phys = usbtouch->phys;
+ usb_to_input_id(udev, &input_dev->id);
+ input_dev->cdev.dev = &intf->dev;
+ input_dev->private = usbtouch;
+ input_dev->open = usbtouch_open;
+ input_dev->close = usbtouch_close;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0);
+ if (type->max_press)
+ input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press,
+ type->max_press, 0, 0);
+
+ usb_fill_int_urb(usbtouch->irq, usbtouch->udev,
+ usb_rcvintpipe(usbtouch->udev, 0x81),
+ usbtouch->data, type->rept_size,
+ usbtouch_irq, usbtouch, endpoint->bInterval);
+
+ usbtouch->irq->transfer_dma = usbtouch->data_dma;
+ usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /* device specific init */
+ if (type->init) {
+ err = type->init(usbtouch);
+ if (err) {
+ dbg("%s - type->init() failed, err: %d", __FUNCTION__, err);
+ goto out_free_buffers;
+ }
+ }
+
+ err = input_register_device(usbtouch->input);
+ if (err) {
+ dbg("%s - input_register_device failed, err: %d", __FUNCTION__, err);
+ goto out_free_buffers;
+ }
+
+ usb_set_intfdata(intf, usbtouch);
+
+ return 0;
+
+out_free_buffers:
+ usbtouch_free_buffers(udev, usbtouch);
+out_free:
+ input_free_device(input_dev);
+ kfree(usbtouch);
+ return -ENOMEM;
+}
+
+static void usbtouch_disconnect(struct usb_interface *intf)
+{
+ struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
+
+ dbg("%s - called", __FUNCTION__);
+
+ if (!usbtouch)
+ return;
+
+ dbg("%s - usbtouch is initialized, cleaning up", __FUNCTION__);
+ usb_set_intfdata(intf, NULL);
+ usb_kill_urb(usbtouch->irq);
+ input_unregister_device(usbtouch->input);
+ usb_free_urb(usbtouch->irq);
+ usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch);
+ kfree(usbtouch);
+}
+
+MODULE_DEVICE_TABLE(usb, usbtouch_devices);
+
+static struct usb_driver usbtouch_driver = {
+ .name = "usbtouchscreen",
+ .probe = usbtouch_probe,
+ .disconnect = usbtouch_disconnect,
+ .id_table = usbtouch_devices,
+};
+
+static int __init usbtouch_init(void)
+{
+ return usb_register(&usbtouch_driver);
+}
+
+static void __exit usbtouch_cleanup(void)
+{
+ usb_deregister(&usbtouch_driver);
+}
+
+module_init(usbtouch_init);
+module_exit(usbtouch_cleanup);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("touchkitusb");
+MODULE_ALIAS("itmtouch");
+MODULE_ALIAS("mtouchusb");
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index d3e15df9e81..cf84c6096f2 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -9,7 +9,7 @@
* Copyright (c) 2000 Daniel Egger <egger@suse.de>
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
- * Copyright (c) 2002-2005 Ping Cheng <pingc@wacom.com>
+ * Copyright (c) 2002-2006 Ping Cheng <pingc@wacom.com>
*
* ChangeLog:
* v0.1 (vp) - Initial release
@@ -56,6 +56,8 @@
* - Merged wacom_intuos3_irq into wacom_intuos_irq
* v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc.
* - Report Device IDs
+ * v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19
+ * - Minor data report fix
*/
/*
@@ -78,7 +80,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.44"
+#define DRIVER_VERSION "v1.45"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
#define DRIVER_LICENSE "GPL"
@@ -99,6 +101,8 @@ enum {
PL,
INTUOS,
INTUOS3,
+ INTUOS312,
+ INTUOS319,
CINTIQ,
MAX_TYPE
};
@@ -127,7 +131,19 @@ struct wacom {
char phys[32];
};
+#define USB_REQ_GET_REPORT 0x01
#define USB_REQ_SET_REPORT 0x09
+
+static int usb_get_report(struct usb_interface *intf, unsigned char type,
+ unsigned char id, void *buf, int size)
+{
+ return usb_control_msg(interface_to_usbdev(intf),
+ usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
+ USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
+ buf, size, 100);
+}
+
static int usb_set_report(struct usb_interface *intf, unsigned char type,
unsigned char id, void *buf, int size)
{
@@ -206,7 +222,8 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
wacom->tool[1] = BTN_TOOL_PEN;
id = STYLUS_DEVICE_ID;
}
- input_report_key(dev, wacom->tool[1], id); /* report in proximity for tool */
+ input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */
+ input_report_abs(dev, ABS_MISC, id); /* report tool id */
input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
input_report_abs(dev, ABS_PRESSURE, pressure);
@@ -239,7 +256,7 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
struct input_dev *dev = wacom->dev;
- int retval;
+ int retval, id;
switch (urb->status) {
case 0:
@@ -263,12 +280,15 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
input_regs(dev, regs);
if (data[1] & 0x04) {
- input_report_key(dev, BTN_TOOL_RUBBER, (data[1] & 0x20) ? ERASER_DEVICE_ID : 0);
+ input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20);
input_report_key(dev, BTN_TOUCH, data[1] & 0x08);
+ id = ERASER_DEVICE_ID;
} else {
- input_report_key(dev, BTN_TOOL_PEN, (data[1] & 0x20) ? STYLUS_DEVICE_ID : 0);
+ input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20);
input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
+ id = STYLUS_DEVICE_ID;
}
+ input_report_abs(dev, ABS_MISC, id); /* report tool id */
input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2]));
input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[4]));
input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
@@ -312,7 +332,8 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs)
}
input_regs(dev, regs);
- input_report_key(dev, BTN_TOOL_PEN, STYLUS_DEVICE_ID);
+ input_report_key(dev, BTN_TOOL_PEN, 1);
+ input_report_abs(dev, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1]));
input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3]));
input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127);
@@ -350,6 +371,8 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
+ if (data[0] == 99) return; /* for Volito tablets */
+
if (data[0] != 2) {
dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
goto exit;
@@ -374,10 +397,10 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
case 2: /* Mouse with wheel */
input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
if (wacom->features->type == WACOM_G4) {
- rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03);
- input_report_rel(dev, REL_WHEEL, rw);
+ rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
+ input_report_rel(dev, REL_WHEEL, -rw);
} else
- input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
+ input_report_rel(dev, REL_WHEEL, -(signed char) data[6]);
/* fall through */
case 3: /* Mouse without wheel */
@@ -406,39 +429,27 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
}
}
- input_report_key(dev, wacom->tool[0], (data[1] & 0x10) ? id : 0);
+ if (data[1] & 0x10)
+ input_report_abs(dev, ABS_MISC, id); /* report tool id */
+ else
+ input_report_abs(dev, ABS_MISC, 0); /* reset tool id */
+ input_report_key(dev, wacom->tool[0], data[1] & 0x10);
input_sync(dev);
/* send pad data */
if (wacom->features->type == WACOM_G4) {
- /* fist time sending pad data */
- if (wacom->tool[1] != BTN_TOOL_FINGER) {
- wacom->id[1] = 0;
- wacom->serial[1] = (data[7] & 0x38) >> 2;
- }
- if (data[7] & 0xf8) {
+ if ((wacom->serial[1] & 0xc0) != (data[7] & 0xf8)) {
+ wacom->id[1] = 1;
+ wacom->serial[1] = (data[7] & 0xf8);
input_report_key(dev, BTN_0, (data[7] & 0x40));
input_report_key(dev, BTN_4, (data[7] & 0x80));
- if (((data[7] & 0x38) >> 2) == (wacom->serial[1] & 0x0e))
- /* alter REL_WHEEL value so X apps can get it */
- wacom->serial[1] += (wacom->serial[1] & 0x01) ? -1 : 1;
- else
- wacom->serial[1] = (data[7] & 0x38 ) >> 2;
-
- /* don't alter the value when there is no wheel event */
- if (wacom->serial[1] == 1)
- wacom->serial[1] = 0;
- rw = wacom->serial[1];
- rw = (rw & 0x08) ? -(rw & 0x07) : (rw & 0x07);
+ rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
input_report_rel(dev, REL_WHEEL, rw);
- wacom->tool[1] = BTN_TOOL_FINGER;
- wacom->id[1] = data[7] & 0xf8;
- input_report_key(dev, wacom->tool[1], 0xf0);
+ input_report_key(dev, BTN_TOOL_FINGER, 0xf0);
input_event(dev, EV_MSC, MSC_SERIAL, 0xf0);
} else if (wacom->id[1]) {
wacom->id[1] = 0;
- wacom->serial[1] = 0;
- input_report_key(dev, wacom->tool[1], 0);
+ input_report_key(dev, BTN_TOOL_FINGER, 0);
input_event(dev, EV_MSC, MSC_SERIAL, 0xf0);
}
input_sync(dev);
@@ -516,21 +527,31 @@ static int wacom_intuos_inout(struct urb *urb)
default: /* Unknown tool */
wacom->tool[idx] = BTN_TOOL_PEN;
}
- input_report_key(dev, wacom->tool[idx], wacom->id[idx]);
- input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
- input_sync(dev);
+ if(!((wacom->tool[idx] == BTN_TOOL_LENS) &&
+ ((wacom->features->type == INTUOS312)
+ || (wacom->features->type == INTUOS319)))) {
+ input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */
+ input_report_key(dev, wacom->tool[idx], 1);
+ input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+ input_sync(dev);
+ }
return 1;
}
/* Exit report */
if ((data[1] & 0xfe) == 0x80) {
input_report_key(dev, wacom->tool[idx], 0);
+ input_report_abs(dev, ABS_MISC, 0); /* reset tool id */
input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
input_sync(dev);
return 1;
}
- return 0;
+ if((wacom->tool[idx] == BTN_TOOL_LENS) && ((wacom->features->type == INTUOS312)
+ || (wacom->features->type == INTUOS319)))
+ return 1;
+ else
+ return 0;
}
static void wacom_intuos_general(struct urb *urb)
@@ -600,10 +621,9 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
/* pad packets. Works as a second tool and is always in prox */
if (data[0] == 12) {
/* initiate the pad as a device */
- if (wacom->tool[1] != BTN_TOOL_FINGER) {
+ if (wacom->tool[1] != BTN_TOOL_FINGER)
wacom->tool[1] = BTN_TOOL_FINGER;
- input_report_key(dev, wacom->tool[1], 1);
- }
+
input_report_key(dev, BTN_0, (data[5] & 0x01));
input_report_key(dev, BTN_1, (data[5] & 0x02));
input_report_key(dev, BTN_2, (data[5] & 0x04));
@@ -614,6 +634,11 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
input_report_key(dev, BTN_7, (data[6] & 0x08));
input_report_abs(dev, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
input_report_abs(dev, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
+
+ if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2])
+ input_report_key(dev, wacom->tool[1], 1);
+ else
+ input_report_key(dev, wacom->tool[1], 0);
input_event(dev, EV_MSC, MSC_SERIAL, 0xffffffff);
input_sync(dev);
goto exit;
@@ -676,8 +701,8 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
input_report_key(dev, BTN_LEFT, data[8] & 0x04);
input_report_key(dev, BTN_MIDDLE, data[8] & 0x08);
input_report_key(dev, BTN_RIGHT, data[8] & 0x10);
- input_report_rel(dev, REL_WHEEL, ((data[8] & 0x02) >> 1)
- - (data[8] & 0x01));
+ input_report_rel(dev, REL_WHEEL, (data[8] & 0x01)
+ - ((data[8] & 0x02) >> 1));
/* I3 2D mouse side buttons */
if (wacom->features->type == INTUOS3) {
@@ -695,7 +720,8 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
}
}
- input_report_key(dev, wacom->tool[idx], wacom->id[idx]);
+ input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */
+ input_report_key(dev, wacom->tool[idx], 1);
input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
input_sync(dev);
@@ -733,7 +759,8 @@ static struct wacom_features wacom_features[] = {
{ "Wacom PL800", 8, 7220, 5780, 511, 32, PL, wacom_pl_irq },
{ "Wacom PL700", 8, 6758, 5406, 511, 32, PL, wacom_pl_irq },
{ "Wacom PL510", 8, 6282, 4762, 511, 32, PL, wacom_pl_irq },
- { "Wacom PL710", 8, 34080, 27660, 511, 32, PL, wacom_pl_irq },
+ { "Wacom DTU710", 8, 34080, 27660, 511, 32, PL, wacom_pl_irq },
+ { "Wacom DTF521", 8, 6282, 4762, 511, 32, PL, wacom_pl_irq },
{ "Wacom DTF720", 8, 6858, 5506, 511, 32, PL, wacom_pl_irq },
{ "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, PL, wacom_ptu_irq },
{ "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq },
@@ -744,6 +771,8 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, INTUOS3, wacom_intuos_irq },
{ "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, INTUOS3, wacom_intuos_irq },
{ "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, INTUOS3, wacom_intuos_irq },
+ { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS312, wacom_intuos_irq },
+ { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS319, wacom_intuos_irq },
{ "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 15, INTUOS3, wacom_intuos_irq },
{ "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 15, CINTIQ, wacom_intuos_irq },
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq },
@@ -779,6 +808,7 @@ static struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC3) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
@@ -788,6 +818,8 @@ static struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
@@ -820,7 +852,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
struct usb_endpoint_descriptor *endpoint;
struct wacom *wacom;
struct input_dev *input_dev;
- char rep_data[2] = {0x02, 0x02};
+ char rep_data[2], limit = 0;
wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
input_dev = input_allocate_device();
@@ -857,6 +889,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
input_set_abs_params(input_dev, ABS_X, 0, wacom->features->x_max, 4, 0);
input_set_abs_params(input_dev, ABS_Y, 0, wacom->features->y_max, 4, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
+ input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC);
switch (wacom->features->type) {
case WACOM_G4:
@@ -875,6 +908,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
break;
case INTUOS3:
+ case INTUOS312:
+ case INTUOS319:
case CINTIQ:
input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
@@ -916,10 +951,13 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
input_register_device(wacom->dev);
- /* ask the tablet to report tablet data */
- usb_set_report(intf, 3, 2, rep_data, 2);
- /* repeat once (not sure why the first call often fails) */
- usb_set_report(intf, 3, 2, rep_data, 2);
+ /* Ask the tablet to report tablet data. Repeat until it succeeds */
+ do {
+ rep_data[0] = 2;
+ rep_data[1] = 2;
+ usb_set_report(intf, 3, 2, rep_data, 2);
+ usb_get_report(intf, 3, 2, rep_data, 2);
+ } while (rep_data[1] != 2 && limit++ < 5);
usb_set_intfdata(intf, wacom);
return 0;
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index 3824df33094..1fd9cb85f4c 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
+#include <linux/delay.h>
#define MAX_INTEL_HEX_RECORD_LENGTH 16
typedef struct _INTEL_HEX_RECORD
@@ -114,6 +115,7 @@ static int emi26_load_firmware (struct usb_device *dev)
/* De-assert reset (let the CPU run) */
err = emi26_set_reset(dev,0);
+ msleep(250); /* let device settle */
/* 2. We upload the FPGA firmware into the EMI
* Note: collect up to 1023 (yes!) bytes and send them with
@@ -150,6 +152,7 @@ static int emi26_load_firmware (struct usb_device *dev)
goto wraperr;
}
}
+ msleep(250); /* let device settle */
/* De-assert reset (let the CPU run) */
err = emi26_set_reset(dev,0);
@@ -192,6 +195,7 @@ static int emi26_load_firmware (struct usb_device *dev)
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
+ msleep(250); /* let device settle */
/* return 1 to fail the driver inialization
* and give real driver change to load */
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 52fea2e08db..fe351371f27 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/usb.h>
+#include <linux/delay.h>
#define MAX_INTEL_HEX_RECORD_LENGTH 16
typedef struct _INTEL_HEX_RECORD
@@ -123,6 +124,7 @@ static int emi62_load_firmware (struct usb_device *dev)
/* De-assert reset (let the CPU run) */
err = emi62_set_reset(dev,0);
+ msleep(250); /* let device settle */
/* 2. We upload the FPGA firmware into the EMI
* Note: collect up to 1023 (yes!) bytes and send them with
@@ -166,6 +168,7 @@ static int emi62_load_firmware (struct usb_device *dev)
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
+ msleep(250); /* let device settle */
/* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
@@ -228,6 +231,7 @@ static int emi62_load_firmware (struct usb_device *dev)
err("%s - error loading firmware: error = %d", __FUNCTION__, err);
goto wraperr;
}
+ msleep(250); /* let device settle */
kfree(buf);
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 9d59b901841..ccc5e8238bd 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -381,6 +381,7 @@ alloc_sglist (int nents, int max, int vary)
for (i = 0; i < nents; i++) {
char *buf;
+ unsigned j;
buf = kzalloc (size, SLAB_KERNEL);
if (!buf) {
@@ -391,6 +392,16 @@ alloc_sglist (int nents, int max, int vary)
/* kmalloc pages are always physically contiguous! */
sg_init_one(&sg[i], buf, size);
+ switch (pattern) {
+ case 0:
+ /* already zeroed */
+ break;
+ case 1:
+ for (j = 0; j < size; j++)
+ *buf++ = (u8) (j % 63);
+ break;
+ }
+
if (vary) {
size += vary;
size %= max;
@@ -425,6 +436,8 @@ static int perform_sglist (
usb_sg_wait (req);
retval = req->status;
+ /* FIXME check resulting data pattern */
+
/* FIXME if endpoint halted, clear halt (and log) */
}
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 3094970615c..12b599a0b53 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -37,7 +37,6 @@
#include "usbnet.h"
-
/* ASIX AX8817X based USB 2.0 Ethernet Devices */
#define AX_CMD_SET_SW_MII 0x06
@@ -109,7 +108,7 @@
#define AX_EEPROM_MAGIC 0xdeadbeef
/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
-struct ax8817x_data {
+struct asix_data {
u8 multi_filter[AX_MCAST_FILTER_SIZE];
};
@@ -121,7 +120,7 @@ struct ax88172_int_data {
u16 res3;
} __attribute__ ((packed));
-static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
return usb_control_msg(
@@ -136,7 +135,7 @@ static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
USB_CTRL_GET_TIMEOUT);
}
-static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
return usb_control_msg(
@@ -151,19 +150,80 @@ static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
USB_CTRL_SET_TIMEOUT);
}
-static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
+static void asix_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
{
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
if (urb->status < 0)
- printk(KERN_DEBUG "ax8817x_async_cmd_callback() failed with %d",
+ printk(KERN_DEBUG "asix_async_cmd_callback() failed with %d",
urb->status);
kfree(req);
usb_free_urb(urb);
}
-static void ax8817x_status(struct usbnet *dev, struct urb *urb)
+static inline int asix_set_sw_mii(struct usbnet *dev)
+{
+ int ret;
+ ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
+ if (ret < 0)
+ devdbg(dev, "Failed to enable software MII access");
+ return ret;
+}
+
+static inline int asix_set_hw_mii(struct usbnet *dev)
+{
+ int ret;
+ ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
+ if (ret < 0)
+ devdbg(dev, "Failed to enable hardware MII access");
+ return ret;
+}
+
+static inline int asix_get_phyid(struct usbnet *dev)
+{
+ int ret = 0;
+ void *buf;
+
+ buf = kmalloc(2, GFP_KERNEL);
+ if (!buf)
+ goto out1;
+
+ if ((ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID,
+ 0, 0, 2, buf)) < 2) {
+ devdbg(dev, "Error reading PHYID register: %02x", ret);
+ goto out2;
+ }
+ ret = *((u8 *)buf + 1);
+out2:
+ kfree(buf);
+out1:
+ return ret;
+}
+
+static int asix_sw_reset(struct usbnet *dev, u8 flags)
+{
+ int ret;
+
+ ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
+ if (ret < 0)
+ devdbg(dev,"Failed to send software reset: %02x", ret);
+
+ return ret;
+}
+
+static int asix_write_rx_ctl(struct usbnet *dev, u16 mode)
+{
+ int ret;
+
+ ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
+ if (ret < 0)
+ devdbg(dev, "Failed to write RX_CTL mode: %02x", ret);
+
+ return ret;
+}
+
+static void asix_status(struct usbnet *dev, struct urb *urb)
{
struct ax88172_int_data *event;
int link;
@@ -179,12 +239,12 @@ static void ax8817x_status(struct usbnet *dev, struct urb *urb)
usbnet_defer_kevent (dev, EVENT_LINK_RESET );
} else
netif_carrier_off(dev->net);
- devdbg(dev, "ax8817x - Link Status is: %d", link);
+ devdbg(dev, "Link Status is: %d", link);
}
}
static void
-ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
struct usb_ctrlrequest *req;
@@ -211,7 +271,7 @@ ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
usb_fill_control_urb(urb, dev->udev,
usb_sndctrlpipe(dev->udev, 0),
(void *)req, data, size,
- ax8817x_async_cmd_callback, req);
+ asix_async_cmd_callback, req);
if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
deverr(dev, "Error submitting the control message: status=%d",
@@ -221,10 +281,10 @@ ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
}
}
-static void ax8817x_set_multicast(struct net_device *net)
+static void asix_set_multicast(struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
- struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+ struct asix_data *data = (struct asix_data *)&dev->data;
u8 rx_ctl = 0x8c;
if (net->flags & IFF_PROMISC) {
@@ -255,53 +315,51 @@ static void ax8817x_set_multicast(struct net_device *net)
mc_list = mc_list->next;
}
- ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
+ asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
AX_MCAST_FILTER_SIZE, data->multi_filter);
rx_ctl |= 0x10;
}
- ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
+ asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
}
-static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
+static int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
{
struct usbnet *dev = netdev_priv(netdev);
u16 res;
- u8 buf[1];
- ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
- ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
+ asix_set_sw_mii(dev);
+ asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
(__u16)loc, 2, (u16 *)&res);
- ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
+ asix_set_hw_mii(dev);
return res & 0xffff;
}
/* same as above, but converts resulting value to cpu byte order */
-static int ax8817x_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
+static int asix_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
{
- return le16_to_cpu(ax8817x_mdio_read(netdev,phy_id, loc));
+ return le16_to_cpu(asix_mdio_read(netdev,phy_id, loc));
}
static void
-ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
+asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
{
struct usbnet *dev = netdev_priv(netdev);
u16 res = val;
- u8 buf[1];
- ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
- ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
+ asix_set_sw_mii(dev);
+ asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
(__u16)loc, 2, (u16 *)&res);
- ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
+ asix_set_hw_mii(dev);
}
/* same as above, but converts new value to le16 byte order before writing */
static void
-ax8817x_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
+asix_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
{
- ax8817x_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
+ asix_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
}
static int ax88172_link_reset(struct usbnet *dev)
@@ -312,23 +370,23 @@ static int ax88172_link_reset(struct usbnet *dev)
u8 mode;
mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
- lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
- adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
+ lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
+ adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
res = mii_nway_result(lpa|adv);
if (res & LPA_DUPLEX)
mode |= AX_MEDIUM_FULL_DUPLEX;
- ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+ asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
return 0;
}
static void
-ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
{
struct usbnet *dev = netdev_priv(net);
u8 opt;
- if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
+ if (asix_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
wolinfo->supported = 0;
wolinfo->wolopts = 0;
return;
@@ -344,7 +402,7 @@ ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
}
static int
-ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
{
struct usbnet *dev = netdev_priv(net);
u8 opt = 0;
@@ -357,19 +415,19 @@ ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
if (opt != 0)
opt |= AX_MONITOR_MODE;
- if (ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
+ if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
opt, 0, 0, &buf) < 0)
return -EINVAL;
return 0;
}
-static int ax8817x_get_eeprom_len(struct net_device *net)
+static int asix_get_eeprom_len(struct net_device *net)
{
return AX_EEPROM_LEN;
}
-static int ax8817x_get_eeprom(struct net_device *net,
+static int asix_get_eeprom(struct net_device *net,
struct ethtool_eeprom *eeprom, u8 *data)
{
struct usbnet *dev = netdev_priv(net);
@@ -386,14 +444,14 @@ static int ax8817x_get_eeprom(struct net_device *net,
/* ax8817x returns 2 bytes from eeprom on read */
for (i=0; i < eeprom->len / 2; i++) {
- if (ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
+ if (asix_read_cmd(dev, AX_CMD_READ_EEPROM,
eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
return -EINVAL;
}
return 0;
}
-static void ax8817x_get_drvinfo (struct net_device *net,
+static void asix_get_drvinfo (struct net_device *net,
struct ethtool_drvinfo *info)
{
/* Inherit standard device info */
@@ -401,14 +459,14 @@ static void ax8817x_get_drvinfo (struct net_device *net,
info->eedump_len = 0x3e;
}
-static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
+static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
{
struct usbnet *dev = netdev_priv(net);
return mii_ethtool_gset(&dev->mii,cmd);
}
-static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
+static int asix_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
{
struct usbnet *dev = netdev_priv(net);
@@ -418,27 +476,27 @@ static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
/* We need to override some ethtool_ops so we require our
own structure so we don't interfere with other usbnet
devices that may be connected at the same time. */
-static struct ethtool_ops ax8817x_ethtool_ops = {
- .get_drvinfo = ax8817x_get_drvinfo,
+static struct ethtool_ops ax88172_ethtool_ops = {
+ .get_drvinfo = asix_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_msglevel = usbnet_get_msglevel,
.set_msglevel = usbnet_set_msglevel,
- .get_wol = ax8817x_get_wol,
- .set_wol = ax8817x_set_wol,
- .get_eeprom_len = ax8817x_get_eeprom_len,
- .get_eeprom = ax8817x_get_eeprom,
- .get_settings = ax8817x_get_settings,
- .set_settings = ax8817x_set_settings,
+ .get_wol = asix_get_wol,
+ .set_wol = asix_set_wol,
+ .get_eeprom_len = asix_get_eeprom_len,
+ .get_eeprom = asix_get_eeprom,
+ .get_settings = asix_get_settings,
+ .set_settings = asix_set_settings,
};
-static int ax8817x_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
+static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
{
struct usbnet *dev = netdev_priv(net);
return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
}
-static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
+static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
{
int ret = 0;
void *buf;
@@ -455,55 +513,39 @@ static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
/* Toggle the GPIOs in a manufacturer/model specific way */
for (i = 2; i >= 0; i--) {
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+ if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
(gpio_bits >> (i * 8)) & 0xff, 0, 0,
buf)) < 0)
goto out2;
msleep(5);
}
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
- 0x80, 0, 0, buf)) < 0) {
- dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret);
+ if ((ret = asix_write_rx_ctl(dev,0x80)) < 0)
goto out2;
- }
/* Get the MAC address */
memset(buf, 0, ETH_ALEN);
- if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID,
+ if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
0, 0, 6, buf)) < 0) {
dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
goto out2;
}
memcpy(dev->net->dev_addr, buf, ETH_ALEN);
- /* Get the PHY id */
- if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID,
- 0, 0, 2, buf)) < 0) {
- dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
- goto out2;
- } else if (ret < 2) {
- /* this should always return 2 bytes */
- dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
- ret);
- ret = -EIO;
- goto out2;
- }
-
/* Initialize MII structure */
dev->mii.dev = dev->net;
- dev->mii.mdio_read = ax8817x_mdio_read;
- dev->mii.mdio_write = ax8817x_mdio_write;
+ dev->mii.mdio_read = asix_mdio_read;
+ dev->mii.mdio_write = asix_mdio_write;
dev->mii.phy_id_mask = 0x3f;
dev->mii.reg_num_mask = 0x1f;
- dev->mii.phy_id = *((u8 *)buf + 1);
- dev->net->do_ioctl = ax8817x_ioctl;
+ dev->mii.phy_id = asix_get_phyid(dev);
+ dev->net->do_ioctl = asix_ioctl;
- dev->net->set_multicast_list = ax8817x_set_multicast;
- dev->net->ethtool_ops = &ax8817x_ethtool_ops;
+ dev->net->set_multicast_list = asix_set_multicast;
+ dev->net->ethtool_ops = &ax88172_ethtool_ops;
- ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
- ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+ asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
mii_nway_restart(&dev->mii);
@@ -515,16 +557,16 @@ out1:
}
static struct ethtool_ops ax88772_ethtool_ops = {
- .get_drvinfo = ax8817x_get_drvinfo,
+ .get_drvinfo = asix_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_msglevel = usbnet_get_msglevel,
.set_msglevel = usbnet_set_msglevel,
- .get_wol = ax8817x_get_wol,
- .set_wol = ax8817x_set_wol,
- .get_eeprom_len = ax8817x_get_eeprom_len,
- .get_eeprom = ax8817x_get_eeprom,
- .get_settings = ax8817x_get_settings,
- .set_settings = ax8817x_set_settings,
+ .get_wol = asix_get_wol,
+ .set_wol = asix_set_wol,
+ .get_eeprom_len = asix_get_eeprom_len,
+ .get_eeprom = asix_get_eeprom,
+ .get_settings = asix_get_settings,
+ .set_settings = asix_set_settings,
};
static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
@@ -541,62 +583,45 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
goto out1;
}
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+ if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
0x00B0, 0, 0, buf)) < 0)
goto out2;
msleep(5);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
+ if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
0x0001, 0, 0, buf)) < 0) {
dbg("Select PHY #1 failed: %d", ret);
goto out2;
}
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD,
- 0, 0, buf)) < 0) {
- dbg("Failed to power down internal PHY: %d", ret);
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD)) < 0)
goto out2;
- }
msleep(150);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR,
- 0, 0, buf)) < 0) {
- dbg("Failed to perform software reset: %d", ret);
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_CLEAR)) < 0)
goto out2;
- }
msleep(150);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
- AX_SWRESET_IPRL | AX_SWRESET_PRL,
- 0, 0, buf)) < 0) {
- dbg("Failed to set Internal/External PHY reset control: %d",
- ret);
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0)
goto out2;
- }
msleep(150);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
- 0x0000, 0, 0, buf)) < 0) {
- dbg("Failed to reset RX_CTL: %d", ret);
+ if ((ret = asix_write_rx_ctl(dev, 0x00)) < 0)
goto out2;
- }
/* Get the MAC address */
memset(buf, 0, ETH_ALEN);
- if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
+ if ((ret = asix_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
0, 0, ETH_ALEN, buf)) < 0) {
dbg("Failed to read MAC address: %d", ret);
goto out2;
}
memcpy(dev->net->dev_addr, buf, ETH_ALEN);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII,
- 0, 0, 0, buf)) < 0) {
- dbg("Enabling software MII failed: %d", ret);
+ if ((ret = asix_set_sw_mii(dev)) < 0)
goto out2;
- }
- if (((ret = ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG,
+ if (((ret = asix_read_cmd(dev, AX_CMD_READ_MII_REG,
0x0010, 2, 2, buf)) < 0)
|| (*((u16 *)buf) != 0x003b)) {
dbg("Read PHY register 2 must be 0x3b00: %d", ret);
@@ -605,74 +630,49 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
/* Initialize MII structure */
dev->mii.dev = dev->net;
- dev->mii.mdio_read = ax8817x_mdio_read;
- dev->mii.mdio_write = ax8817x_mdio_write;
+ dev->mii.mdio_read = asix_mdio_read;
+ dev->mii.mdio_write = asix_mdio_write;
dev->mii.phy_id_mask = 0xff;
dev->mii.reg_num_mask = 0xff;
- dev->net->do_ioctl = ax8817x_ioctl;
+ dev->net->do_ioctl = asix_ioctl;
+ dev->mii.phy_id = asix_get_phyid(dev);
- /* Get the PHY id */
- if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID,
- 0, 0, 2, buf)) < 0) {
- dbg("Error reading PHY ID: %02x", ret);
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0)
goto out2;
- } else if (ret < 2) {
- /* this should always return 2 bytes */
- dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
- ret);
- ret = -EIO;
- goto out2;
- }
- dev->mii.phy_id = *((u8 *)buf + 1);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL,
- 0, 0, buf)) < 0) {
- dbg("Set external PHY reset pin level: %d", ret);
- goto out2;
- }
msleep(150);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
- AX_SWRESET_IPRL | AX_SWRESET_PRL,
- 0, 0, buf)) < 0) {
- dbg("Set Internal/External PHY reset control: %d", ret);
+
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0)
goto out2;
- }
- msleep(150);
+ msleep(150);
- dev->net->set_multicast_list = ax8817x_set_multicast;
+ dev->net->set_multicast_list = asix_set_multicast;
dev->net->ethtool_ops = &ax88772_ethtool_ops;
- ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
- ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+ asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
ADVERTISE_ALL | ADVERTISE_CSMA);
mii_nway_restart(&dev->mii);
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+ if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) {
dbg("Write medium mode register: %d", ret);
goto out2;
}
- if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
+ if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
goto out2;
}
- if ((ret =
- ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) {
- dbg("Failed to set hardware MII: %02x", ret);
+ if ((ret = asix_set_hw_mii(dev)) < 0)
goto out2;
- }
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
- if ((ret =
- ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0,
- buf)) < 0) {
- dbg("Reset RX_CTL failed: %d", ret);
+ if ((ret = asix_write_rx_ctl(dev, 0x0088)) < 0)
goto out2;
- }
kfree(buf);
@@ -794,23 +794,23 @@ static int ax88772_link_reset(struct usbnet *dev)
u16 mode;
mode = AX88772_MEDIUM_DEFAULT;
- lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
- adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
+ lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
+ adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
res = mii_nway_result(lpa|adv);
if ((res & LPA_DUPLEX) == 0)
mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
if ((res & LPA_100) == 0)
mode &= ~AX88772_MEDIUM_100MB;
- ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+ asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
return 0;
}
static const struct driver_info ax8817x_info = {
.description = "ASIX AX8817x USB 2.0 Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
+ .bind = ax88172_bind,
+ .status = asix_status,
.link_reset = ax88172_link_reset,
.reset = ax88172_link_reset,
.flags = FLAG_ETHER,
@@ -819,8 +819,8 @@ static const struct driver_info ax8817x_info = {
static const struct driver_info dlink_dub_e100_info = {
.description = "DLink DUB-E100 USB Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
+ .bind = ax88172_bind,
+ .status = asix_status,
.link_reset = ax88172_link_reset,
.reset = ax88172_link_reset,
.flags = FLAG_ETHER,
@@ -829,8 +829,8 @@ static const struct driver_info dlink_dub_e100_info = {
static const struct driver_info netgear_fa120_info = {
.description = "Netgear FA-120 USB Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
+ .bind = ax88172_bind,
+ .status = asix_status,
.link_reset = ax88172_link_reset,
.reset = ax88172_link_reset,
.flags = FLAG_ETHER,
@@ -839,8 +839,8 @@ static const struct driver_info netgear_fa120_info = {
static const struct driver_info hawking_uf200_info = {
.description = "Hawking UF200 USB Ethernet",
- .bind = ax8817x_bind,
- .status = ax8817x_status,
+ .bind = ax88172_bind,
+ .status = asix_status,
.link_reset = ax88172_link_reset,
.reset = ax88172_link_reset,
.flags = FLAG_ETHER,
@@ -850,13 +850,12 @@ static const struct driver_info hawking_uf200_info = {
static const struct driver_info ax88772_info = {
.description = "ASIX AX88772 USB 2.0 Ethernet",
.bind = ax88772_bind,
- .status = ax8817x_status,
+ .status = asix_status,
.link_reset = ax88772_link_reset,
.reset = ax88772_link_reset,
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
.rx_fixup = ax88772_rx_fixup,
.tx_fixup = ax88772_tx_fixup,
- .data = 0x00130103,
};
static const struct usb_device_id products [] = {
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 5b667568456..7683926a1b6 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -262,7 +262,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
usb_sndctrlpipe(pegasus->usb, 0),
(char *) &pegasus->dr,
- &tmp, 1, ctrl_callback, pegasus);
+ tmp, 1, ctrl_callback, pegasus);
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
@@ -318,6 +318,8 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
set_register(pegasus, PhyCtrl, (indx | PHY_READ));
for (i = 0; i < REG_TIMEOUT; i++) {
ret = get_registers(pegasus, PhyCtrl, 1, data);
+ if (ret == -ESHUTDOWN)
+ goto fail;
if (data[0] & PHY_DONE)
break;
}
@@ -326,6 +328,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
*regd = le16_to_cpu(regdi);
return ret;
}
+fail:
if (netif_msg_drv(pegasus))
dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
@@ -354,12 +357,15 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
for (i = 0; i < REG_TIMEOUT; i++) {
ret = get_registers(pegasus, PhyCtrl, 1, data);
+ if (ret == -ESHUTDOWN)
+ goto fail;
if (data[0] & PHY_DONE)
break;
}
if (i < REG_TIMEOUT)
return ret;
+fail:
if (netif_msg_drv(pegasus))
dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
return -ETIMEDOUT;
@@ -387,6 +393,8 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
if (tmp & EPROM_DONE)
break;
+ if (ret == -ESHUTDOWN)
+ goto fail;
}
if (i < REG_TIMEOUT) {
ret = get_registers(pegasus, EpromData, 2, &retdatai);
@@ -394,6 +402,7 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
return ret;
}
+fail:
if (netif_msg_drv(pegasus))
dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
return -ETIMEDOUT;
@@ -433,12 +442,15 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
for (i = 0; i < REG_TIMEOUT; i++) {
ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
+ if (ret == -ESHUTDOWN)
+ goto fail;
if (tmp & EPROM_DONE)
break;
}
disable_eprom_write(pegasus);
if (i < REG_TIMEOUT)
return ret;
+fail:
if (netif_msg_drv(pegasus))
dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
return -ETIMEDOUT;
@@ -1378,9 +1390,8 @@ static int pegasus_suspend (struct usb_interface *intf, pm_message_t message)
struct pegasus *pegasus = usb_get_intfdata(intf);
netif_device_detach (pegasus->net);
+ cancel_delayed_work(&pegasus->carrier_check);
if (netif_running(pegasus->net)) {
- cancel_delayed_work(&pegasus->carrier_check);
-
usb_kill_urb(pegasus->rx_urb);
usb_kill_urb(pegasus->intr_urb);
}
@@ -1400,10 +1411,9 @@ static int pegasus_resume (struct usb_interface *intf)
pegasus->intr_urb->status = 0;
pegasus->intr_urb->actual_length = 0;
intr_callback(pegasus->intr_urb, NULL);
-
- queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
- CARRIER_CHECK_DELAY);
}
+ queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
+ CARRIER_CHECK_DELAY);
return 0;
}
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index 49991ac1bf3..94ddfe16fdd 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -39,6 +39,20 @@
* RNDIS is NDIS remoted over USB. It's a MSFT variant of CDC ACM ... of
* course ACM was intended for modems, not Ethernet links! USB's standard
* for Ethernet links is "CDC Ethernet", which is significantly simpler.
+ *
+ * NOTE that Microsoft's "RNDIS 1.0" specification is incomplete. Issues
+ * include:
+ * - Power management in particular relies on information that's scattered
+ * through other documentation, and which is incomplete or incorrect even
+ * there.
+ * - There are various undocumented protocol requirements, such as the
+ * need to send unused garbage in control-OUT messages.
+ * - In some cases, MS-Windows will emit undocumented requests; this
+ * matters more to peripheral implementations than host ones.
+ *
+ * For these reasons and others, ** USE OF RNDIS IS STRONGLY DISCOURAGED ** in
+ * favor of such non-proprietary alternatives as CDC Ethernet or the newer (and
+ * currently rare) "Ethernet Emulation Model" (EEM).
*/
/*
@@ -72,17 +86,17 @@ struct rndis_msg_hdr {
*/
#define RNDIS_MSG_PACKET ccpu2(0x00000001) /* 1-N packets */
#define RNDIS_MSG_INIT ccpu2(0x00000002)
-#define RNDIS_MSG_INIT_C (RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_INIT_C (RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
#define RNDIS_MSG_HALT ccpu2(0x00000003)
#define RNDIS_MSG_QUERY ccpu2(0x00000004)
-#define RNDIS_MSG_QUERY_C (RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_QUERY_C (RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
#define RNDIS_MSG_SET ccpu2(0x00000005)
-#define RNDIS_MSG_SET_C (RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_SET_C (RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
#define RNDIS_MSG_RESET ccpu2(0x00000006)
-#define RNDIS_MSG_RESET_C (RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_RESET_C (RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
#define RNDIS_MSG_INDICATE ccpu2(0x00000007)
#define RNDIS_MSG_KEEPALIVE ccpu2(0x00000008)
-#define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
/* codes for "status" field of completion messages */
#define RNDIS_STATUS_SUCCESS ccpu2(0x00000000)
@@ -596,13 +610,13 @@ static struct usb_driver rndis_driver = {
static int __init rndis_init(void)
{
- return usb_register(&rndis_driver);
+ return usb_register(&rndis_driver);
}
module_init(rndis_init);
static void __exit rndis_exit(void)
{
- usb_deregister(&rndis_driver);
+ usb_deregister(&rndis_driver);
}
module_exit(rndis_exit);
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c
index 9c5ab251370..f7ac9d6b985 100644
--- a/drivers/usb/net/zaurus.c
+++ b/drivers/usb/net/zaurus.c
@@ -217,7 +217,7 @@ static int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf)
* with devices that use it and those that don't.
*/
if ((detail->bDetailData[1] & ~0x02) != 0x01) {
- /* bmDataCapabilites == 0 would be fine too,
+ /* bmDataCapabilities == 0 would be fine too,
* but framing is minidriver-coupled for now.
*/
bad_detail:
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
index fe9b60cd8d9..9b1e4ed1d07 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/usb/net/zd1201.c
@@ -1736,6 +1736,7 @@ static const struct iw_handler_def zd1201_iw_handlers = {
.standard = (iw_handler *)zd1201_iw_handler,
.private = (iw_handler *)zd1201_private_handler,
.private_args = (struct iw_priv_args *) zd1201_private_args,
+ .get_wireless_stats = zd1201_get_wireless_stats,
};
static int zd1201_probe(struct usb_interface *interface,
@@ -1796,7 +1797,6 @@ static int zd1201_probe(struct usb_interface *interface,
zd->dev->open = zd1201_net_open;
zd->dev->stop = zd1201_net_stop;
zd->dev->get_stats = zd1201_get_stats;
- zd->dev->get_wireless_stats = zd1201_get_wireless_stats;
zd->dev->wireless_handlers =
(struct iw_handler_def *)&zd1201_iw_handlers;
zd->dev->hard_start_xmit = zd1201_hard_start_xmit;
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 5a8a2c91c2b..5c60be52156 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -71,6 +71,16 @@ config USB_SERIAL_ANYDATA
To compile this driver as a module, choose M here: the
module will be called anydata.
+config USB_SERIAL_ARK3116
+ tristate "USB ARK Micro 3116 USB Serial Driver (EXPERIMENTAL)"
+ depends on USB_SERIAL && EXPERIMENTAL
+ help
+ Say Y here if you want to use a ARK Micro 3116 USB to Serial
+ device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ark3116
+
config USB_SERIAL_BELKIN
tristate "USB Belkin and Peracom Single Port Serial Driver"
depends on USB_SERIAL
@@ -158,6 +168,15 @@ config USB_SERIAL_FTDI_SIO
To compile this driver as a module, choose M here: the
module will be called ftdi_sio.
+config USB_SERIAL_FUNSOFT
+ tristate "USB Fundamental Software Dongle Driver"
+ depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use the Fundamental Software dongle.
+
+ To compile this driver as a module, choose M here: the
+ module will be called funsoft.
+
config USB_SERIAL_VISOR
tristate "USB Handspring Visor / Palm m50x / Sony Clie Driver"
depends on USB_SERIAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index f7fe4172efe..5a0960fc9d3 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -13,6 +13,7 @@ usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y)
obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o
obj-$(CONFIG_USB_SERIAL_ANYDATA) += anydata.o
+obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o
obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
@@ -22,6 +23,7 @@ obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o
obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o
obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o
+obj-$(CONFIG_USB_SERIAL_FUNSOFT) += funsoft.o
obj-$(CONFIG_USB_SERIAL_GARMIN) += garmin_gps.o
obj-$(CONFIG_USB_SERIAL_HP4X) += hp4x.o
obj-$(CONFIG_USB_SERIAL_IPAQ) += ipaq.o
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index dbf1f063098..694b205f9b7 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -18,6 +18,7 @@
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0xf3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */
{ USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
+ { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
new file mode 100644
index 00000000000..8dec796222a
--- /dev/null
+++ b/drivers/usb/serial/ark3116.c
@@ -0,0 +1,465 @@
+/*
+ * ark3116
+ * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547,
+ * productid=0x0232) (used in a datacable called KQ-U8A)
+ *
+ * - based on code by krisfx -> thanks !!
+ * (see http://www.linuxquestions.org/questions/showthread.php?p=2184457#post2184457)
+ *
+ * - based on logs created by usbsnoopy
+ *
+ * Author : Simon Schulz [ark3116_driver<AT>auctionant.de]
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+
+
+static int debug;
+
+static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x6547, 0x0232) },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+struct ark3116_private {
+ spinlock_t lock;
+ u8 termios_initialized;
+};
+
+static inline void ARK3116_SND(struct usb_serial *serial, int seq,
+ __u8 request, __u8 requesttype,
+ __u16 value, __u16 index)
+{
+ int result;
+ result = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev,0),
+ request, requesttype, value, index,
+ NULL,0x00, 1000);
+ dbg("%03d > ok",seq);
+}
+
+static inline void ARK3116_RCV(struct usb_serial *serial, int seq,
+ __u8 request, __u8 requesttype,
+ __u16 value, __u16 index, __u8 expected,
+ char *buf)
+{
+ int result;
+ result = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev,0),
+ request, requesttype, value, index,
+ buf, 0x0000001, 1000);
+ if (result)
+ dbg("%03d < %d bytes [0x%02X]",seq, result, buf[0]);
+ else
+ dbg("%03d < 0 bytes", seq);
+}
+
+
+static inline void ARK3116_RCV_QUIET(struct usb_serial *serial,
+ __u8 request, __u8 requesttype,
+ __u16 value, __u16 index, char *buf)
+{
+ usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev,0),
+ request, requesttype, value, index,
+ buf, 0x0000001, 1000);
+}
+
+
+static int ark3116_attach(struct usb_serial *serial)
+{
+ char *buf;
+ struct ark3116_private *priv;
+ int i;
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ priv = kmalloc (sizeof (struct ark3116_private), GFP_KERNEL);
+ if (!priv)
+ goto cleanup;
+ memset (priv, 0x00, sizeof (struct ark3116_private));
+ spin_lock_init(&priv->lock);
+
+ usb_set_serial_port_data(serial->port[i], priv);
+ }
+
+ buf = kmalloc(1, GFP_KERNEL);
+ if (!buf) {
+ dbg("error kmalloc -> out of mem ?");
+ goto cleanup;
+ }
+
+ /* 3 */
+ ARK3116_SND(serial, 3,0xFE,0x40,0x0008,0x0002);
+ ARK3116_SND(serial, 4,0xFE,0x40,0x0008,0x0001);
+ ARK3116_SND(serial, 5,0xFE,0x40,0x0000,0x0008);
+ ARK3116_SND(serial, 6,0xFE,0x40,0x0000,0x000B);
+
+ /* <-- seq7 */
+ ARK3116_RCV(serial, 7,0xFE,0xC0,0x0000,0x0003, 0x00, buf);
+ ARK3116_SND(serial, 8,0xFE,0x40,0x0080,0x0003);
+ ARK3116_SND(serial, 9,0xFE,0x40,0x001A,0x0000);
+ ARK3116_SND(serial,10,0xFE,0x40,0x0000,0x0001);
+ ARK3116_SND(serial,11,0xFE,0x40,0x0000,0x0003);
+
+ /* <-- seq12 */
+ ARK3116_RCV(serial,12,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+ ARK3116_SND(serial,13,0xFE,0x40,0x0000,0x0004);
+
+ /* 14 */
+ ARK3116_RCV(serial,14,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+ ARK3116_SND(serial,15,0xFE,0x40,0x0000,0x0004);
+
+ /* 16 */
+ ARK3116_RCV(serial,16,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+ /* --> seq17 */
+ ARK3116_SND(serial,17,0xFE,0x40,0x0001,0x0004);
+
+ /* <-- seq18 */
+ ARK3116_RCV(serial,18,0xFE,0xC0,0x0000,0x0004, 0x01, buf);
+
+ /* --> seq19 */
+ ARK3116_SND(serial,19,0xFE,0x40,0x0003,0x0004);
+
+
+ /* <-- seq20 */
+ /* seems like serial port status info (RTS, CTS,...) */
+ /* returns modem control line status ?! */
+ ARK3116_RCV(serial,20,0xFE,0xC0,0x0000,0x0006, 0xFF, buf);
+
+ /* set 9600 baud & do some init ?! */
+ ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003);
+ ARK3116_SND(serial,148,0xFE,0x40,0x0038,0x0000);
+ ARK3116_SND(serial,149,0xFE,0x40,0x0001,0x0001);
+ ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003);
+ ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf);
+ ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003);
+ ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf);
+ ARK3116_SND(serial,154,0xFE,0x40,0x0003,0x0003);
+
+ kfree(buf);
+ return(0);
+
+cleanup:
+ for (--i; i>=0; --i)
+ usb_set_serial_port_data(serial->port[i], NULL);
+ return -ENOMEM;
+}
+
+static void ark3116_set_termios(struct usb_serial_port *port,
+ struct termios *old_termios)
+{
+ struct usb_serial *serial = port->serial;
+ struct ark3116_private *priv = usb_get_serial_port_data(port);
+ unsigned int cflag = port->tty->termios->c_cflag;
+ unsigned long flags;
+ int baud;
+ int ark3116_baud;
+ char *buf;
+ char config;
+
+ config = 0;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if ((!port->tty) || (!port->tty->termios)) {
+ dbg("%s - no tty structures", __FUNCTION__);
+ return;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!priv->termios_initialized) {
+ *(port->tty->termios) = tty_std_termios;
+ port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ priv->termios_initialized = 1;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ cflag = port->tty->termios->c_cflag;
+
+ /* check that they really want us to change something: */
+ if (old_termios) {
+ if ((cflag == old_termios->c_cflag) &&
+ (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
+ RELEVANT_IFLAG(old_termios->c_iflag))) {
+ dbg("%s - nothing to change...", __FUNCTION__);
+ return;
+ }
+ }
+
+ buf = kmalloc(1, GFP_KERNEL);
+ if (!buf) {
+ dbg("error kmalloc");
+ return;
+ }
+
+ /* set data bit count (8/7/6/5) */
+ if (cflag & CSIZE){
+ switch (cflag & CSIZE){
+ case CS5:
+ config |= 0x00;
+ dbg("setting CS5");
+ break;
+ case CS6:
+ config |= 0x01;
+ dbg("setting CS6");
+ break;
+ case CS7:
+ config |= 0x02;
+ dbg("setting CS7");
+ break;
+ default:
+ err ("CSIZE was set but not CS5-CS8, using CS8!");
+ case CS8:
+ config |= 0x03;
+ dbg("setting CS8");
+ break;
+ }
+ }
+
+ /* set parity (NONE,EVEN,ODD) */
+ if (cflag & PARENB){
+ if (cflag & PARODD) {
+ config |= 0x08;
+ dbg("setting parity to ODD");
+ } else {
+ config |= 0x18;
+ dbg("setting parity to EVEN");
+ }
+ } else {
+ dbg("setting parity to NONE");
+ }
+
+ /* SET STOPBIT (1/2) */
+ if (cflag & CSTOPB) {
+ config |= 0x04;
+ dbg ("setting 2 stop bits");
+ } else {
+ dbg ("setting 1 stop bit");
+ }
+
+
+ /* set baudrate: */
+ baud = 0;
+ switch (cflag & CBAUD){
+ case B0:
+ err("can't set 0baud, using 9600 instead");
+ break;
+ case B75: baud = 75; break;
+ case B150: baud = 150; break;
+ case B300: baud = 300; break;
+ case B600: baud = 600; break;
+ case B1200: baud = 1200; break;
+ case B1800: baud = 1800; break;
+ case B2400: baud = 2400; break;
+ case B4800: baud = 4800; break;
+ case B9600: baud = 9600; break;
+ case B19200: baud = 19200; break;
+ case B38400: baud = 38400; break;
+ case B57600: baud = 57600; break;
+ case B115200: baud = 115200; break;
+ case B230400: baud = 230400; break;
+ case B460800: baud = 460800; break;
+ default:
+ dbg("does not support the baudrate requested (fix it)");
+ break;
+ }
+
+ /* set 9600 as default (if given baudrate is invalid for example) */
+ if (baud == 0)
+ baud = 9600;
+
+ /*
+ * found by try'n'error, be careful, maybe there are other options
+ * for multiplicator etc!
+ */
+ if (baud == 460800)
+ /* strange, for 460800 the formula is wrong
+ * (dont use round(), then 9600baud is wrong) */
+ ark3116_baud = 7;
+ else
+ ark3116_baud = 3000000 / baud;
+
+ /* ? */
+ ARK3116_RCV(serial,0,0xFE,0xC0,0x0000,0x0003, 0x03, buf);
+ /* offset = buf[0]; */
+ /* offset = 0x03; */
+ /* dbg("using 0x%04X as target for 0x0003:",0x0080+offset); */
+
+
+ /* set baudrate */
+ dbg("setting baudrate to %d (->reg=%d)",baud,ark3116_baud);
+ ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003);
+ ARK3116_SND(serial,148,0xFE,0x40,(ark3116_baud & 0x00FF) ,0x0000);
+ ARK3116_SND(serial,149,0xFE,0x40,(ark3116_baud & 0xFF00)>>8,0x0001);
+ ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003);
+
+ /* ? */
+ ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf);
+ ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003);
+
+ /* set data bit count, stop bit count & parity: */
+ dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config);
+ ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf);
+ ARK3116_SND(serial,154,0xFE,0x40,config,0x0003);
+
+ if (cflag & CRTSCTS)
+ dbg("CRTSCTS not supported by chipset ?!");
+
+ /* TEST ARK3116_SND(154,0xFE,0x40,0xFFFF, 0x0006); */
+
+ kfree(buf);
+ return;
+}
+
+static int ark3116_open(struct usb_serial_port *port, struct file *filp)
+{
+ struct termios tmp_termios;
+ struct usb_serial *serial = port->serial;
+ char *buf;
+ int result = 0;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ buf = kmalloc(1, GFP_KERNEL);
+ if (!buf) {
+ dbg("error kmalloc -> out of mem ?");
+ return -ENOMEM;
+ }
+
+ result = usb_serial_generic_open(port, filp);
+ if (result)
+ return result;
+
+ /* open */
+ ARK3116_RCV(serial,111,0xFE,0xC0,0x0000,0x0003, 0x02, buf);
+
+ ARK3116_SND(serial,112,0xFE,0x40,0x0082,0x0003);
+ ARK3116_SND(serial,113,0xFE,0x40,0x001A,0x0000);
+ ARK3116_SND(serial,114,0xFE,0x40,0x0000,0x0001);
+ ARK3116_SND(serial,115,0xFE,0x40,0x0002,0x0003);
+
+ ARK3116_RCV(serial,116,0xFE,0xC0,0x0000,0x0004, 0x03, buf);
+ ARK3116_SND(serial,117,0xFE,0x40,0x0002,0x0004);
+
+ ARK3116_RCV(serial,118,0xFE,0xC0,0x0000,0x0004, 0x02, buf);
+ ARK3116_SND(serial,119,0xFE,0x40,0x0000,0x0004);
+
+ ARK3116_RCV(serial,120,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+
+ ARK3116_SND(serial,121,0xFE,0x40,0x0001,0x0004);
+
+ ARK3116_RCV(serial,122,0xFE,0xC0,0x0000,0x0004, 0x01, buf);
+
+ ARK3116_SND(serial,123,0xFE,0x40,0x0003,0x0004);
+
+ /* returns different values (control lines ?!) */
+ ARK3116_RCV(serial,124,0xFE,0xC0,0x0000,0x0006, 0xFF, buf);
+
+ /* initialise termios: */
+ if (port->tty)
+ ark3116_set_termios(port, &tmp_termios);
+
+ kfree(buf);
+
+ return result;
+
+}
+
+static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ dbg("ioctl not supported yet...");
+ return -ENOIOCTLCMD;
+}
+
+static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+ struct usb_serial *serial = port->serial;
+ char *buf;
+ char temp;
+
+ /* seems like serial port status info (RTS, CTS,...) is stored
+ * in reg(?) 0x0006
+ * pcb connection point 11 = GND -> sets bit4 of response
+ * pcb connection point 7 = GND -> sets bit6 of response
+ */
+
+ buf = kmalloc(1, GFP_KERNEL);
+ if (!buf) {
+ dbg("error kmalloc");
+ return -ENOMEM;
+ }
+
+ /* read register: */
+ ARK3116_RCV_QUIET(serial,0xFE,0xC0,0x0000,0x0006,buf);
+ temp = buf[0];
+ kfree(buf);
+
+ /* i do not really know if bit4=CTS and bit6=DSR... was just a
+ * quick guess !!
+ */
+ return (temp & (1<<4) ? TIOCM_CTS : 0) |
+ (temp & (1<<6) ? TIOCM_DSR : 0);
+}
+
+static struct usb_driver ark3116_driver = {
+ .name = "ark3116",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+};
+
+static struct usb_serial_driver ark3116_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ark3116",
+ },
+ .id_table = id_table,
+ .num_interrupt_in = 1,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_ports = 1,
+ .attach = ark3116_attach,
+ .set_termios = ark3116_set_termios,
+ .ioctl = ark3116_ioctl,
+ .tiocmget = ark3116_tiocmget,
+ .open = ark3116_open,
+};
+
+static int __init ark3116_init(void)
+{
+ int retval;
+
+ retval = usb_serial_register(&ark3116_device);
+ if (retval)
+ return retval;
+ retval = usb_register(&ark3116_driver);
+ if (retval)
+ usb_serial_deregister(&ark3116_device);
+ return retval;
+}
+
+static void __exit ark3116_exit(void)
+{
+ usb_deregister(&ark3116_driver);
+ usb_serial_deregister(&ark3116_device);
+}
+
+module_init(ark3116_init);
+module_exit(ark3116_exit);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 167f8ec5613..8023bb7279b 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -54,7 +54,7 @@ static struct console usbcons;
* serial.c code, except that the specifier is "ttyUSB" instead
* of "ttyS".
*/
-static int __init usb_console_setup(struct console *co, char *options)
+static int usb_console_setup(struct console *co, char *options)
{
struct usbcons_info *info = &usbcons_info;
int baud = 9600;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index f3af81b4dd2..986d7622273 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -307,7 +307,9 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
static struct usb_device_id id_table_combined [] = {
+ { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
@@ -489,10 +491,15 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
{ USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TTUSB_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ECLO_COM_1WIRE_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
{ USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) },
+ { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 8da773c2744..d69a917e768 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -32,6 +32,10 @@
#define FTDI_NF_RIC_PID 0x0001 /* Product Id */
+/* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */
+#define FTDI_ACTZWAVE_PID 0xF2D0
+
+
/* www.irtrans.de device */
#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
@@ -39,6 +43,9 @@
/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */
#define FTDI_TTUSB_PID 0xFF20 /* Product Id */
+/* iPlus device */
+#define FTDI_IPLUS_PID 0xD070 /* Product Id */
+
/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
/* they use the ftdi chipset for the USB interface and the vendor id is the same */
#define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */
@@ -153,6 +160,11 @@
#define ICOM_ID1_PID 0x0004
/*
+ * ASK.fr devices
+ */
+#define FTDI_ASK_RDR400_PID 0xC991 /* ASK RDR 400 series card reader */
+
+/*
* DSS-20 Sync Station for Sony Ericsson P800
*/
@@ -399,6 +411,31 @@
#define FTDI_WESTREX_MODEL_777_PID 0xDC00 /* Model 777 */
#define FTDI_WESTREX_MODEL_8900F_PID 0xDC01 /* Model 8900F */
+/*
+ * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
+ */
+#define FTDI_RRCIRKITS_LOCOBUFFER_PID 0xc7d0 /* LocoBuffer USB */
+
+/*
+ * Eclo (http://www.eclo.pt/) product IDs.
+ * PID 0xEA90 submitted by Martin Grill.
+ */
+#define FTDI_ECLO_COM_1WIRE_PID 0xEA90 /* COM to 1-Wire USB adaptor */
+
+/*
+ * Papouch products (http://www.papouch.com/)
+ * Submitted by Folkert van Heusden
+ */
+
+#define PAPOUCH_VID 0x5050 /* Vendor ID */
+#define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */
+
+/*
+ * ACG Identification Technologies GmbH products (http://www.acg.de/).
+ * Submitted by anton -at- goto10 -dot- org.
+ */
+#define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */
+
/* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
new file mode 100644
index 00000000000..803721b97e2
--- /dev/null
+++ b/drivers/usb/serial/funsoft.c
@@ -0,0 +1,65 @@
+/*
+ * Funsoft Serial USB driver
+ *
+ * Copyright (C) 2006 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+
+static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x1404, 0xcddc) },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver funsoft_driver = {
+ .name = "funsoft",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+ .no_dynamic_id = 1,
+};
+
+static struct usb_serial_driver funsoft_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "funsoft",
+ },
+ .id_table = id_table,
+ .num_interrupt_in = NUM_DONT_CARE,
+ .num_bulk_in = NUM_DONT_CARE,
+ .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+};
+
+static int __init funsoft_init(void)
+{
+ int retval;
+
+ retval = usb_serial_register(&funsoft_device);
+ if (retval)
+ return retval;
+ retval = usb_register(&funsoft_driver);
+ if (retval)
+ usb_serial_deregister(&funsoft_device);
+ return retval;
+}
+
+static void __exit funsoft_exit(void)
+{
+ usb_deregister(&funsoft_driver);
+ usb_serial_deregister(&funsoft_device);
+}
+
+module_init(funsoft_init);
+module_exit(funsoft_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 476cda107f4..c62cc287651 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -138,6 +138,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
return result;
}
+EXPORT_SYMBOL_GPL(usb_serial_generic_open);
static void generic_cleanup (struct usb_serial_port *port)
{
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 4d40704dea2..238033a8709 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -257,14 +257,14 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
return (0);
}
- spin_lock(&port->lock);
- if (port->write_urb_busy) {
- spin_unlock(&port->lock);
+ spin_lock(&wport->lock);
+ if (wport->write_urb_busy) {
+ spin_unlock(&wport->lock);
dbg("%s - already writing", __FUNCTION__);
return 0;
}
- port->write_urb_busy = 1;
- spin_unlock(&port->lock);
+ wport->write_urb_busy = 1;
+ spin_unlock(&wport->lock);
count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
@@ -283,7 +283,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
wport->write_urb->dev = serial->dev;
result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
if (result) {
- port->write_urb_busy = 0;
+ wport->write_urb_busy = 0;
err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
} else
result = count;
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 495db5755df..5cf2b80add7 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -28,6 +28,7 @@
2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard
2005-09-20 v0.4.4 increased recv buffer size: the card sometimes
wants to send >2000 bytes.
+ 2006-04-10 v0.4.2 fixed two array overrun errors :-/
Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
@@ -582,14 +583,14 @@ static void option_setup_urbs(struct usb_serial *serial)
portdata = usb_get_serial_port_data(port);
/* Do indat endpoints first */
- for (j = 0; j <= N_IN_URB; ++j) {
+ for (j = 0; j < N_IN_URB; ++j) {
portdata->in_urbs[j] = option_setup_urb (serial,
port->bulk_in_endpointAddress, USB_DIR_IN, port,
portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
}
/* outdat endpoints */
- for (j = 0; j <= N_OUT_URB; ++j) {
+ for (j = 0; j < N_OUT_URB; ++j) {
portdata->out_urbs[j] = option_setup_urb (serial,
port->bulk_out_endpointAddress, USB_DIR_OUT, port,
portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index b3014fda645..c96714bb1cb 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -61,6 +61,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) },
{ USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) },
+ { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) },
{ USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
{ USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
@@ -78,6 +79,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) },
{ USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
{ USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
+ { USB_DEVICE(OTI_VENDOR_ID, OTI_PRODUCT_ID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 77901d14397..7f29e81d3e3 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -26,6 +26,7 @@
#define ITEGNO_VENDOR_ID 0x0eba
#define ITEGNO_PRODUCT_ID 0x1080
+#define ITEGNO_PRODUCT_ID_2080 0x2080
#define MA620_VENDOR_ID 0x0df7
#define MA620_PRODUCT_ID 0x0620
@@ -79,3 +80,7 @@
/* USB GSM cable from Speed Dragon Multimedia, Ltd */
#define SPEEDDRAGON_VENDOR_ID 0x0e55
#define SPEEDDRAGON_PRODUCT_ID 0x110b
+
+/* Ours Technology Inc DKU-5 clone, chipset: Prolific Technology Inc */
+#define OTI_VENDOR_ID 0x0ea0
+#define OTI_PRODUCT_ID 0x6858
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 097f4e8488f..9c36f0ece20 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -27,10 +27,10 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
-#include <asm/semaphore.h>
#include <linux/usb.h>
#include "usb-serial.h"
#include "pl2303.h"
@@ -189,11 +189,15 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
portNumber = tty->index - serial->minor;
port = serial->port[portNumber];
- if (!port)
- return -ENODEV;
+ if (!port) {
+ retval = -ENODEV;
+ goto bailout_kref_put;
+ }
- if (down_interruptible(&port->sem))
- return -ERESTARTSYS;
+ if (mutex_lock_interruptible(&port->mutex)) {
+ retval = -ERESTARTSYS;
+ goto bailout_kref_put;
+ }
++port->open_count;
@@ -209,7 +213,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
* safe because we are called with BKL held */
if (!try_module_get(serial->type->driver.owner)) {
retval = -ENODEV;
- goto bailout_kref_put;
+ goto bailout_mutex_unlock;
}
/* only call the device specific open if this
@@ -219,15 +223,16 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
goto bailout_module_put;
}
- up(&port->sem);
+ mutex_unlock(&port->mutex);
return 0;
bailout_module_put:
module_put(serial->type->driver.owner);
+bailout_mutex_unlock:
+ port->open_count = 0;
+ mutex_unlock(&port->mutex);
bailout_kref_put:
kref_put(&serial->kref, destroy_serial);
- port->open_count = 0;
- up(&port->sem);
return retval;
}
@@ -240,10 +245,10 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
dbg("%s - port %d", __FUNCTION__, port->number);
- down(&port->sem);
+ mutex_lock(&port->mutex);
if (port->open_count == 0) {
- up(&port->sem);
+ mutex_unlock(&port->mutex);
return;
}
@@ -262,7 +267,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
module_put(port->serial->type->driver.owner);
}
- up(&port->sem);
+ mutex_unlock(&port->mutex);
kref_put(&port->serial->kref, destroy_serial);
}
@@ -783,7 +788,7 @@ int usb_serial_probe(struct usb_interface *interface,
port->number = i + serial->minor;
port->serial = serial;
spin_lock_init(&port->lock);
- sema_init(&port->sem, 1);
+ mutex_init(&port->mutex);
INIT_WORK(&port->work, usb_serial_port_softint, port);
serial->port[i] = port;
}
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index d7d27c3385b..dc89d871046 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -16,7 +16,7 @@
#include <linux/config.h>
#include <linux/kref.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#define SERIAL_TTY_MAJOR 188 /* Nice legal number now */
#define SERIAL_TTY_MINORS 255 /* loads of devices :) */
@@ -31,7 +31,7 @@
* @serial: pointer back to the struct usb_serial owner of this port.
* @tty: pointer to the corresponding tty for this port.
* @lock: spinlock to grab when updating portions of this structure.
- * @sem: semaphore used to synchronize serial_open() and serial_close()
+ * @mutex: mutex used to synchronize serial_open() and serial_close()
* access for this port.
* @number: the number of the port (the minor number).
* @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
@@ -63,7 +63,7 @@ struct usb_serial_port {
struct usb_serial * serial;
struct tty_struct * tty;
spinlock_t lock;
- struct semaphore sem;
+ struct mutex mutex;
unsigned char number;
unsigned char * interrupt_in_buffer;
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 557411c6e7c..f806553cd9a 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -508,6 +508,7 @@ no_firmware:
err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description);
err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description);
err("%s: please contact support@connecttech.com\n", serial->type->description);
+ kfree(result);
return -ENODEV;
no_command_private:
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 92be101feba..be9eec22574 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -48,7 +48,8 @@ config USB_STORAGE_FREECOM
config USB_STORAGE_ISD200
bool "ISD-200 USB/ATA Bridge support"
- depends on USB_STORAGE && BLK_DEV_IDE
+ depends on USB_STORAGE
+ depends on BLK_DEV_IDE=y || BLK_DEV_IDE=USB_STORAGE
---help---
Say Y here if you want to use USB Mass Store devices based
on the In-Systems Design ISD-200 USB/ATA bridge.
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index c4a9dcff5f2..aec5ea8682d 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -411,7 +411,7 @@ UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133,
UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100,
"Iomega",
"USB Clik! 40",
- US_SC_8070, US_PR_BULK, NULL,
+ US_SC_8070, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
/* Yakumo Mega Image 37
@@ -773,6 +773,13 @@ UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/* Reported by Olivier Blondeau <zeitoun@gmail.com> */
+UNUSUAL_DEV( 0x0727, 0x0306, 0x0100, 0x0100,
+ "ATMEL",
+ "SND1 Storage",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE),
+
/* Submitted by Roman Hodek <roman@hodek.net> */
UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200,
"Sandisk",
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index fdebd60a325..4587087d777 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -70,6 +70,22 @@ config FB_MACMODES
depends on FB
default n
+config FB_FIRMWARE_EDID
+ bool "Enable firmware EDID"
+ depends on FB
+ default y
+ ---help---
+ This enables access to the EDID transferred from the firmware.
+ On the i386, this is from the Video BIOS. Enable this if DDC/I2C
+ transfers do not work for your driver and if you are using
+ nvidiafb, i810fb or savagefb.
+
+ In general, choosing Y for this option is safe. If you
+ experience extremely long delays while booting before you get
+ something on your display, try setting this to N. Matrox cards in
+ combination with certain motherboards and monitors are known to
+ suffer from this problem.
+
config FB_MODE_HELPERS
bool "Enable Video Mode Handling Helpers"
depends on FB
@@ -384,6 +400,8 @@ config FB_ASILIANT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the Asiliant 69030 chipset
config FB_IMSTT
bool "IMS Twin Turbo display support"
@@ -888,18 +906,6 @@ config FB_MATROX_MULTIHEAD
There is no need for enabling 'Matrox multihead support' if you have
only one Matrox card in the box.
-config FB_RADEON_OLD
- tristate "ATI Radeon display support (Old driver)"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_MACMODES if PPC
- help
- Choose this option if you want to use an ATI Radeon graphics card as
- a framebuffer device. There are both PCI and AGP versions. You
- don't need to choose this to run the Radeon in plain VGA mode.
-
config FB_RADEON
tristate "ATI Radeon display support"
depends on FB && PCI
@@ -957,7 +963,7 @@ config FB_ATY128
config FB_ATY
tristate "ATI Mach64 display support" if PCI || ATARI
- depends on FB
+ depends on FB && !SPARC32
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -1202,6 +1208,17 @@ config FB_AU1100
bool "Au1100 LCD Driver"
depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y
+config FB_AU1200
+ bool "Au1200 LCD Driver"
+ depends on FB && MIPS && SOC_AU1200
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the framebuffer driver for the AMD Au1200 SOC. It can drive
+ various panels and CRTs by passing in kernel cmd line option
+ au1200fb:panel=<name>.
+
source "drivers/video/geode/Kconfig"
config FB_FFB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index aa434e725c0..23de3b2c785 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -39,7 +39,6 @@ obj-$(CONFIG_FB_KYRO) += kyro/
obj-$(CONFIG_FB_SAVAGE) += savage/
obj-$(CONFIG_FB_GEODE) += geode/
obj-$(CONFIG_FB_I810) += vgastate.o
-obj-$(CONFIG_FB_RADEON_OLD) += radeonfb.o
obj-$(CONFIG_FB_NEOMAGIC) += neofb.o vgastate.o
obj-$(CONFIG_FB_VIRGE) += virgefb.o
obj-$(CONFIG_FB_3DFX) += tdfxfb.o
@@ -86,6 +85,7 @@ obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
obj-$(CONFIG_FB_PXA) += pxafb.o
obj-$(CONFIG_FB_W100) += w100fb.o
obj-$(CONFIG_FB_AU1100) += au1100fb.o
+obj-$(CONFIG_FB_AU1200) += au1200fb.o
obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o
obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o
obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 76448d6ae89..98baecccb3f 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -1308,7 +1308,7 @@ static int __init acornfb_probe(struct platform_device *dev)
/*
* Try to select a suitable default mode
*/
- for (i = 0; i < sizeof(modedb) / sizeof(*modedb); i++) {
+ for (i = 0; i < ARRAY_SIZE(modedb); i++) {
unsigned long hs;
hs = modedb[i].refresh *
@@ -1380,7 +1380,7 @@ static int __init acornfb_probe(struct platform_device *dev)
*/
free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE);
#endif
-
+
fb_info.fix.smem_len = size;
current_par.palette_size = VIDC_PALETTE_SIZE;
@@ -1391,7 +1391,7 @@ static int __init acornfb_probe(struct platform_device *dev)
*/
do {
rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
- sizeof(modedb) / sizeof(*modedb),
+ ARRAY_SIZE(modedb),
&acornfb_default_mode, DEFAULT_BPP);
/*
* If we found an exact match, all ok.
@@ -1408,7 +1408,7 @@ static int __init acornfb_probe(struct platform_device *dev)
break;
rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
- sizeof(modedb) / sizeof(*modedb),
+ ARRAY_SIZE(modedb),
&acornfb_default_mode, DEFAULT_BPP);
if (rc)
break;
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index c924d81f797..29f9f0dfe3b 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -353,8 +353,6 @@ struct chips_init_reg {
unsigned char data;
};
-#define N_ELTS(x) (sizeof(x) / sizeof(x[0]))
-
static struct chips_init_reg chips_init_sr[] =
{
{0x00, 0x03}, /* Reset register */
@@ -460,22 +458,22 @@ static void __devinit chips_hw_init(struct fb_info *p)
{
int i;
- for (i = 0; i < N_ELTS(chips_init_xr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i)
write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
write_xr(0x81, 0x12);
write_xr(0x82, 0x08);
write_xr(0x20, 0x00);
- for (i = 0; i < N_ELTS(chips_init_sr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i)
write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
- for (i = 0; i < N_ELTS(chips_init_gr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i)
write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
- for (i = 0; i < N_ELTS(chips_init_ar); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i)
write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
/* Enable video output in attribute index register */
writeb(0x20, mmio_base + 0x780);
- for (i = 0; i < N_ELTS(chips_init_cr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i)
write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
- for (i = 0; i < N_ELTS(chips_init_fr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i)
write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
}
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 620c9a934e0..f7bbff4ddc6 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -67,6 +67,7 @@
#include <asm/io.h>
#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
#include <asm/pmac_feature.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
@@ -1725,9 +1726,9 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id *
strcpy(video_card, "Rage128 XX ");
video_card[8] = ent->device >> 8;
video_card[9] = ent->device & 0xFF;
-
+
/* range check to make sure */
- if (ent->driver_data < (sizeof(r128_family)/sizeof(char *)))
+ if (ent->driver_data < ARRAY_SIZE(r128_family))
strncat(video_card, r128_family[ent->driver_data], sizeof(video_card));
printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
@@ -1748,7 +1749,7 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id *
var = default_var;
#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
/* Indicate sleep capability */
if (par->chip_gen == rage_M3) {
pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1);
@@ -2011,7 +2012,7 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
return 0;
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && blank)
+ if (machine_is(powermac) && blank)
set_backlight_enable(0);
#endif /* CONFIG_PMAC_BACKLIGHT */
@@ -2029,7 +2030,7 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
aty128_set_lcd_enable(par, par->lcd_on && !blank);
}
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && !blank)
+ if (machine_is(powermac) && !blank)
set_backlight_enable(1);
#endif /* CONFIG_PMAC_BACKLIGHT */
return 0;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 485be386a8f..d9d7d3c4cae 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -75,6 +75,7 @@
#include "ati_ids.h"
#ifdef __powerpc__
+#include <asm/machdep.h>
#include <asm/prom.h>
#include "../macmodes.h"
#endif
@@ -434,7 +435,7 @@ static int __devinit correct_chipset(struct atyfb_par *par)
const char *name;
int i;
- for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--)
+ for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
if (par->pci_id == aty_chips[i].pci_id)
break;
@@ -2168,10 +2169,10 @@ static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) {
refresh_tbl = ragexl_tbl;
- size = sizeof(ragexl_tbl)/sizeof(int);
+ size = ARRAY_SIZE(ragexl_tbl);
} else {
refresh_tbl = ragepro_tbl;
- size = sizeof(ragepro_tbl)/sizeof(int);
+ size = ARRAY_SIZE(ragepro_tbl);
}
for (i=0; i < size; i++) {
@@ -2298,6 +2299,10 @@ static int __init aty_init(struct fb_info *info, const char *name)
case CLK_ATI18818_1:
par->pll_ops = &aty_pll_ati18818_1;
break;
+ case CLK_IBMRGB514:
+ par->pll_ops = &aty_pll_ibm514;
+ break;
+#if 0 /* dead code */
case CLK_STG1703:
par->pll_ops = &aty_pll_stg1703;
break;
@@ -2307,9 +2312,7 @@ static int __init aty_init(struct fb_info *info, const char *name)
case CLK_ATT20C408:
par->pll_ops = &aty_pll_att20c408;
break;
- case CLK_IBMRGB514:
- par->pll_ops = &aty_pll_ibm514;
- break;
+#endif
default:
PRINTKI("aty_init: CLK type not implemented yet!");
par->pll_ops = &aty_pll_unsupported;
@@ -2516,7 +2519,7 @@ static int __init aty_init(struct fb_info *info, const char *name)
memset(&var, 0, sizeof(var));
#ifdef CONFIG_PPC
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
/*
* FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
* applies to all Mac video cards
@@ -2671,7 +2674,7 @@ static int atyfb_blank(int blank, struct fb_info *info)
return 0;
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && blank > FB_BLANK_NORMAL)
+ if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
set_backlight_enable(0);
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
if (par->lcd_table && blank > FB_BLANK_NORMAL &&
@@ -2703,7 +2706,7 @@ static int atyfb_blank(int blank, struct fb_info *info)
aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && blank <= FB_BLANK_NORMAL)
+ if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
set_backlight_enable(1);
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
@@ -3397,7 +3400,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
struct atyfb_par *par;
int i, rc = -ENOMEM;
- for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--)
+ for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
if (pdev->device == aty_chips[i].pci_id)
break;
diff --git a/drivers/video/aty/mach64_gx.c b/drivers/video/aty/mach64_gx.c
index 01fdff79483..2045639cb67 100644
--- a/drivers/video/aty/mach64_gx.c
+++ b/drivers/video/aty/mach64_gx.c
@@ -149,8 +149,7 @@ static int aty_var_to_pll_514(const struct fb_info *info, u32 vclk_per,
};
int i;
- for (i = 0; i < sizeof(RGB514_clocks) / sizeof(*RGB514_clocks);
- i++)
+ for (i = 0; i < ARRAY_SIZE(RGB514_clocks); i++)
if (vclk_per <= RGB514_clocks[i].limit) {
pll->ibm514.m = RGB514_clocks[i].m;
pll->ibm514.n = RGB514_clocks[i].n;
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index c9f0c5a07e6..387a18a47ac 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -1067,7 +1067,7 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
if (regno > 255)
- return 1;
+ return -EINVAL;
red >>= 8;
green >>= 8;
@@ -1086,9 +1086,9 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
pindex = regno * 8;
if (rinfo->depth == 16 && regno > 63)
- return 1;
+ return -EINVAL;
if (rinfo->depth == 15 && regno > 31)
- return 1;
+ return -EINVAL;
/* For 565, the green component is mixed one order
* below
@@ -2265,7 +2265,7 @@ static struct bin_attribute edid2_attr = {
};
-static int radeonfb_pci_register (struct pci_dev *pdev,
+static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct fb_info *info;
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 5886a2f1323..c7091761cef 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -20,7 +20,7 @@
#include <linux/agp_backend.h>
#ifdef CONFIG_PPC_PMAC
-#include <asm/processor.h>
+#include <asm/machdep.h>
#include <asm/prom.h>
#include <asm/pmac_feature.h>
#endif
@@ -2745,7 +2745,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
rinfo->pm_mode |= radeon_pm_off;
}
#if defined(CONFIG_PPC_PMAC)
- if (_machine == _MACH_Pmac && rinfo->of_node) {
+ if (machine_is(powermac) && rinfo->of_node) {
if (rinfo->is_mobility && rinfo->pm_reg &&
rinfo->family <= CHIP_FAMILY_RV250)
rinfo->pm_mode |= radeon_pm_d2;
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 3d04b2def0f..789450bb0bc 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -214,10 +214,13 @@ int au1100fb_setmode(struct au1100fb_device *fbdev)
*/
int au1100fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
{
- struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
- u32 *palette = fbdev->regs->lcd_pallettebase;
+ struct au1100fb_device *fbdev;
+ u32 *palette;
u32 value;
+ fbdev = to_au1100fb_device(fbi);
+ palette = fbdev->regs->lcd_pallettebase;
+
if (regno > (AU1100_LCD_NBR_PALETTE_ENTRIES - 1))
return -EINVAL;
@@ -316,9 +319,11 @@ int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
*/
int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
{
- struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+ struct au1100fb_device *fbdev;
int dy;
+ fbdev = to_au1100fb_device(fbi);
+
print_dbg("fb_pan_display %p %p", var, fbi);
if (!var || !fbdev) {
@@ -382,10 +387,12 @@ void au1100fb_fb_rotate(struct fb_info *fbi, int angle)
*/
int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
{
- struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+ struct au1100fb_device *fbdev;
unsigned int len;
unsigned long start=0, off;
+ fbdev = to_au1100fb_device(fbi);
+
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
return -EINVAL;
}
@@ -467,7 +474,7 @@ int au1100fb_drv_probe(struct device *dev)
if (!request_mem_region(au1100fb_fix.mmio_start, au1100fb_fix.mmio_len,
DRIVER_NAME)) {
- print_err("fail to lock memory region at 0x%08x",
+ print_err("fail to lock memory region at 0x%08lx",
au1100fb_fix.mmio_start);
return -EBUSY;
}
@@ -595,13 +602,13 @@ int au1100fb_drv_remove(struct device *dev)
return 0;
}
-int au1100fb_drv_suspend(struct device *dev, u32 state, u32 level)
+int au1100fb_drv_suspend(struct device *dev, pm_message_t state)
{
/* TODO */
return 0;
}
-int au1100fb_drv_resume(struct device *dev, u32 level)
+int au1100fb_drv_resume(struct device *dev)
{
/* TODO */
return 0;
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
new file mode 100644
index 00000000000..600d3e0e08b
--- /dev/null
+++ b/drivers/video/au1200fb.c
@@ -0,0 +1,1922 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1200 LCD Driver.
+ *
+ * Copyright 2004-2005 AMD
+ * Author: AMD
+ *
+ * Based on:
+ * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
+ * Created 28 Dec 1997 by Geert Uytterhoeven
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ctype.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/mach-au1x00/au1000.h>
+#include "au1200fb.h"
+
+#ifdef CONFIG_PM
+#include <asm/mach-au1x00/au1xxx_pm.h>
+#endif
+
+#ifndef CONFIG_FB_AU1200_DEVS
+#define CONFIG_FB_AU1200_DEVS 4
+#endif
+
+#define DRIVER_NAME "au1200fb"
+#define DRIVER_DESC "LCD controller driver for AU1200 processors"
+
+#define DEBUG 1
+
+#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
+#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
+#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg)
+
+#if DEBUG
+#define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg)
+#else
+#define print_dbg(f, arg...) do {} while (0)
+#endif
+
+
+#define AU1200_LCD_FB_IOCTL 0x46FF
+
+#define AU1200_LCD_SET_SCREEN 1
+#define AU1200_LCD_GET_SCREEN 2
+#define AU1200_LCD_SET_WINDOW 3
+#define AU1200_LCD_GET_WINDOW 4
+#define AU1200_LCD_SET_PANEL 5
+#define AU1200_LCD_GET_PANEL 6
+
+#define SCREEN_SIZE (1<< 1)
+#define SCREEN_BACKCOLOR (1<< 2)
+#define SCREEN_BRIGHTNESS (1<< 3)
+#define SCREEN_COLORKEY (1<< 4)
+#define SCREEN_MASK (1<< 5)
+
+struct au1200_lcd_global_regs_t {
+ unsigned int flags;
+ unsigned int xsize;
+ unsigned int ysize;
+ unsigned int backcolor;
+ unsigned int brightness;
+ unsigned int colorkey;
+ unsigned int mask;
+ unsigned int panel_choice;
+ char panel_desc[80];
+
+};
+
+#define WIN_POSITION (1<< 0)
+#define WIN_ALPHA_COLOR (1<< 1)
+#define WIN_ALPHA_MODE (1<< 2)
+#define WIN_PRIORITY (1<< 3)
+#define WIN_CHANNEL (1<< 4)
+#define WIN_BUFFER_FORMAT (1<< 5)
+#define WIN_COLOR_ORDER (1<< 6)
+#define WIN_PIXEL_ORDER (1<< 7)
+#define WIN_SIZE (1<< 8)
+#define WIN_COLORKEY_MODE (1<< 9)
+#define WIN_DOUBLE_BUFFER_MODE (1<< 10)
+#define WIN_RAM_ARRAY_MODE (1<< 11)
+#define WIN_BUFFER_SCALE (1<< 12)
+#define WIN_ENABLE (1<< 13)
+
+struct au1200_lcd_window_regs_t {
+ unsigned int flags;
+ unsigned int xpos;
+ unsigned int ypos;
+ unsigned int alpha_color;
+ unsigned int alpha_mode;
+ unsigned int priority;
+ unsigned int channel;
+ unsigned int buffer_format;
+ unsigned int color_order;
+ unsigned int pixel_order;
+ unsigned int xsize;
+ unsigned int ysize;
+ unsigned int colorkey_mode;
+ unsigned int double_buffer_mode;
+ unsigned int ram_array_mode;
+ unsigned int xscale;
+ unsigned int yscale;
+ unsigned int enable;
+};
+
+
+struct au1200_lcd_iodata_t {
+ unsigned int subcmd;
+ struct au1200_lcd_global_regs_t global;
+ struct au1200_lcd_window_regs_t window;
+};
+
+#if defined(__BIG_ENDIAN)
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11
+#else
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00
+#endif
+#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565
+
+/* Private, per-framebuffer management information (independent of the panel itself) */
+struct au1200fb_device {
+ struct fb_info fb_info; /* FB driver info record */
+
+ int plane;
+ unsigned char* fb_mem; /* FrameBuffer memory map */
+ unsigned int fb_len;
+ dma_addr_t fb_phys;
+};
+
+static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS];
+/********************************************************************/
+
+/* LCD controller restrictions */
+#define AU1200_LCD_MAX_XRES 1280
+#define AU1200_LCD_MAX_YRES 1024
+#define AU1200_LCD_MAX_BPP 32
+#define AU1200_LCD_MAX_CLK 96000000 /* fixme: this needs to go away ? */
+#define AU1200_LCD_NBR_PALETTE_ENTRIES 256
+
+/* Default number of visible screen buffer to allocate */
+#define AU1200FB_NBR_VIDEO_BUFFERS 1
+
+/********************************************************************/
+
+static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR;
+static int window_index = 2; /* default is zero */
+static int panel_index = 2; /* default is zero */
+static struct window_settings *win;
+static struct panel_settings *panel;
+static int noblanking = 1;
+static int nohwcursor = 0;
+
+struct window_settings {
+ unsigned char name[64];
+ uint32 mode_backcolor;
+ uint32 mode_colorkey;
+ uint32 mode_colorkeymsk;
+ struct {
+ int xres;
+ int yres;
+ int xpos;
+ int ypos;
+ uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */
+ uint32 mode_winenable;
+ } w[4];
+};
+
+#if defined(__BIG_ENDIAN)
+#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00
+#else
+#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01
+#endif
+
+extern int board_au1200fb_panel_init (void);
+extern int board_au1200fb_panel_shutdown (void);
+
+#ifdef CONFIG_PM
+int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
+ au1xxx_request_t request, void *data);
+au1xxx_power_dev_t *LCD_pm_dev;
+#endif
+
+/*
+ * Default window configurations
+ */
+static struct window_settings windows[] = {
+ { /* Index 0 */
+ "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
+ /* mode_backcolor */ 0x006600ff,
+ /* mode_colorkey,msk*/ 0, 0,
+ {
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ LCD_WINENABLE_WEN0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 100, 100, 100, 100,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ LCD_WINENABLE_WEN1,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ 0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0,
+ },
+ },
+ },
+
+ { /* Index 1 */
+ "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
+ /* mode_backcolor */ 0x006600ff,
+ /* mode_colorkey,msk*/ 0, 0,
+ {
+ {
+ /* xres, yres, xpos, ypos */ 320, 240, 5, 5,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP |
+ LCD_WINCTRL1_PO_00,
+ /* mode_winenable*/ LCD_WINENABLE_WEN0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565
+ | LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ 0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 100, 100, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 200, 25, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0,
+ },
+ },
+ },
+ { /* Index 2 */
+ "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
+ /* mode_backcolor */ 0x006600ff,
+ /* mode_colorkey,msk*/ 0, 0,
+ {
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ LCD_WINENABLE_WEN0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ 0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP |
+ LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0,
+ },
+ },
+ },
+ /* Need VGA 640 @ 24bpp, @ 32bpp */
+ /* Need VGA 800 @ 24bpp, @ 32bpp */
+ /* Need VGA 1024 @ 24bpp, @ 32bpp */
+};
+
+/*
+ * Controller configurations for various panels.
+ */
+
+struct panel_settings
+{
+ const char name[25]; /* Full name <vendor>_<model> */
+
+ struct fb_monspecs monspecs; /* FB monitor specs */
+
+ /* panel timings */
+ uint32 mode_screen;
+ uint32 mode_horztiming;
+ uint32 mode_verttiming;
+ uint32 mode_clkcontrol;
+ uint32 mode_pwmdiv;
+ uint32 mode_pwmhi;
+ uint32 mode_outmask;
+ uint32 mode_fifoctrl;
+ uint32 mode_toyclksrc;
+ uint32 mode_backlight;
+ uint32 mode_auxpll;
+ int (*device_init)(void);
+ int (*device_shutdown)(void);
+#define Xres min_xres
+#define Yres min_yres
+ u32 min_xres; /* Minimum horizontal resolution */
+ u32 max_xres; /* Maximum horizontal resolution */
+ u32 min_yres; /* Minimum vertical resolution */
+ u32 max_yres; /* Maximum vertical resolution */
+};
+
+/********************************************************************/
+/* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */
+
+/* List of panels known to work with the AU1200 LCD controller.
+ * To add a new panel, enter the same specifications as the
+ * Generic_TFT one, and MAKE SURE that it doesn't conflicts
+ * with the controller restrictions. Restrictions are:
+ *
+ * STN color panels: max_bpp <= 12
+ * STN mono panels: max_bpp <= 4
+ * TFT panels: max_bpp <= 16
+ * max_xres <= 800
+ * max_yres <= 600
+ */
+static struct panel_settings known_lcd_panels[] =
+{
+ [0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */
+ .name = "QVGA_320x240",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(320) |
+ LCD_SCREEN_SY_N(240),
+ .mode_horztiming = 0x00c4623b,
+ .mode_verttiming = 0x00502814,
+ .mode_clkcontrol = 0x00020002, /* /4=24Mhz */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 320, 320,
+ 240, 240,
+ },
+
+ [1] = { /* VGA 640x480 H:30.3kHz V:58Hz */
+ .name = "VGA_640x480",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x13f9df80,
+ .mode_horztiming = 0x003c5859,
+ .mode_verttiming = 0x00741201,
+ .mode_clkcontrol = 0x00020001, /* /4=24Mhz */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 640, 480,
+ 640, 480,
+ },
+
+ [2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */
+ .name = "SVGA_800x600",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x18fa5780,
+ .mode_horztiming = 0x00dc7e77,
+ .mode_verttiming = 0x00584805,
+ .mode_clkcontrol = 0x00020000, /* /2=48Mhz */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 800, 800,
+ 600, 600,
+ },
+
+ [3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */
+ .name = "XVGA_1024x768",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x1ffaff80,
+ .mode_horztiming = 0x007d0e57,
+ .mode_verttiming = 0x00740a01,
+ .mode_clkcontrol = 0x000A0000, /* /1 */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 6, /* 72MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 1024, 1024,
+ 768, 768,
+ },
+
+ [4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */
+ .name = "XVGA_1280x1024",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x27fbff80,
+ .mode_horztiming = 0x00cdb2c7,
+ .mode_verttiming = 0x00600002,
+ .mode_clkcontrol = 0x000A0000, /* /1 */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 10, /* 120MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 1280, 1280,
+ 1024, 1024,
+ },
+
+ [5] = { /* Samsung 1024x768 TFT */
+ .name = "Samsung_1024x768_TFT",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x1ffaff80,
+ .mode_horztiming = 0x018cc677,
+ .mode_verttiming = 0x00241217,
+ .mode_clkcontrol = 0x00000000, /* SCB 0x1 /4=24Mhz */
+ .mode_pwmdiv = 0x8000063f, /* SCB 0x0 */
+ .mode_pwmhi = 0x03400000, /* SCB 0x0 */
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = board_au1200fb_panel_init,
+ .device_shutdown = board_au1200fb_panel_shutdown,
+ 1024, 1024,
+ 768, 768,
+ },
+
+ [6] = { /* Toshiba 640x480 TFT */
+ .name = "Toshiba_640x480_TFT",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(640) |
+ LCD_SCREEN_SY_N(480),
+ .mode_horztiming = LCD_HORZTIMING_HPW_N(96) |
+ LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51),
+ .mode_verttiming = LCD_VERTTIMING_VPW_N(2) |
+ LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32),
+ .mode_clkcontrol = 0x00000000, /* /4=24Mhz */
+ .mode_pwmdiv = 0x8000063f,
+ .mode_pwmhi = 0x03400000,
+ .mode_outmask = 0x00fcfcfc,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = board_au1200fb_panel_init,
+ .device_shutdown = board_au1200fb_panel_shutdown,
+ 640, 480,
+ 640, 480,
+ },
+
+ [7] = { /* Sharp 320x240 TFT */
+ .name = "Sharp_320x240_TFT",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 12500,
+ .hfmax = 20000,
+ .vfmin = 38,
+ .vfmax = 81,
+ .dclkmin = 4500000,
+ .dclkmax = 6800000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(320) |
+ LCD_SCREEN_SY_N(240),
+ .mode_horztiming = LCD_HORZTIMING_HPW_N(60) |
+ LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2),
+ .mode_verttiming = LCD_VERTTIMING_VPW_N(2) |
+ LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5),
+ .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/
+ .mode_pwmdiv = 0x8000063f,
+ .mode_pwmhi = 0x03400000,
+ .mode_outmask = 0x00fcfcfc,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = board_au1200fb_panel_init,
+ .device_shutdown = board_au1200fb_panel_shutdown,
+ 320, 320,
+ 240, 240,
+ },
+
+ [8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */
+ .name = "Toppoly_TD070WGCB2",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(856) |
+ LCD_SCREEN_SY_N(480),
+ .mode_horztiming = LCD_HORZTIMING_HND2_N(43) |
+ LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114),
+ .mode_verttiming = LCD_VERTTIMING_VND2_N(20) |
+ LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4),
+ .mode_clkcontrol = 0x00020001, /* /4=24Mhz */
+ .mode_pwmdiv = 0x8000063f,
+ .mode_pwmhi = 0x03400000,
+ .mode_outmask = 0x00fcfcfc,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = board_au1200fb_panel_init,
+ .device_shutdown = board_au1200fb_panel_shutdown,
+ 856, 856,
+ 480, 480,
+ },
+};
+
+#define NUM_PANELS (ARRAY_SIZE(known_lcd_panels))
+
+/********************************************************************/
+
+#ifdef CONFIG_PM
+static int set_brightness(unsigned int brightness)
+{
+ unsigned int hi1, divider;
+
+ /* limit brightness pwm duty to >= 30/1600 */
+ if (brightness < 30) {
+ brightness = 30;
+ }
+ divider = (lcd->pwmdiv & 0x3FFFF) + 1;
+ hi1 = (lcd->pwmhi >> 16) + 1;
+ hi1 = (((brightness & 0xFF) + 1) * divider >> 8);
+ lcd->pwmhi &= 0xFFFF;
+ lcd->pwmhi |= (hi1 << 16);
+
+ return brightness;
+}
+#endif /* CONFIG_PM */
+
+static int winbpp (unsigned int winctrl1)
+{
+ int bits = 0;
+
+ /* how many bits are needed for each pixel format */
+ switch (winctrl1 & LCD_WINCTRL1_FRM) {
+ case LCD_WINCTRL1_FRM_1BPP:
+ bits = 1;
+ break;
+ case LCD_WINCTRL1_FRM_2BPP:
+ bits = 2;
+ break;
+ case LCD_WINCTRL1_FRM_4BPP:
+ bits = 4;
+ break;
+ case LCD_WINCTRL1_FRM_8BPP:
+ bits = 8;
+ break;
+ case LCD_WINCTRL1_FRM_12BPP:
+ case LCD_WINCTRL1_FRM_16BPP655:
+ case LCD_WINCTRL1_FRM_16BPP565:
+ case LCD_WINCTRL1_FRM_16BPP556:
+ case LCD_WINCTRL1_FRM_16BPPI1555:
+ case LCD_WINCTRL1_FRM_16BPPI5551:
+ case LCD_WINCTRL1_FRM_16BPPA1555:
+ case LCD_WINCTRL1_FRM_16BPPA5551:
+ bits = 16;
+ break;
+ case LCD_WINCTRL1_FRM_24BPP:
+ case LCD_WINCTRL1_FRM_32BPP:
+ bits = 32;
+ break;
+ }
+
+ return bits;
+}
+
+static int fbinfo2index (struct fb_info *fb_info)
+{
+ int i;
+
+ for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) {
+ if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info))
+ return i;
+ }
+ printk("au1200fb: ERROR: fbinfo2index failed!\n");
+ return -1;
+}
+
+static int au1200_setlocation (struct au1200fb_device *fbdev, int plane,
+ int xpos, int ypos)
+{
+ uint32 winctrl0, winctrl1, winenable, fb_offset = 0;
+ int xsz, ysz;
+
+ /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */
+
+ winctrl0 = lcd->window[plane].winctrl0;
+ winctrl1 = lcd->window[plane].winctrl1;
+ winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN);
+ winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY);
+
+ /* Check for off-screen adjustments */
+ xsz = win->w[plane].xres;
+ ysz = win->w[plane].yres;
+ if ((xpos + win->w[plane].xres) > panel->Xres) {
+ /* Off-screen to the right */
+ xsz = panel->Xres - xpos; /* off by 1 ??? */
+ /*printk("off screen right\n");*/
+ }
+
+ if ((ypos + win->w[plane].yres) > panel->Yres) {
+ /* Off-screen to the bottom */
+ ysz = panel->Yres - ypos; /* off by 1 ??? */
+ /*printk("off screen bottom\n");*/
+ }
+
+ if (xpos < 0) {
+ /* Off-screen to the left */
+ xsz = win->w[plane].xres + xpos;
+ fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8);
+ xpos = 0;
+ /*printk("off screen left\n");*/
+ }
+
+ if (ypos < 0) {
+ /* Off-screen to the top */
+ ysz = win->w[plane].yres + ypos;
+ /* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */
+ ypos = 0;
+ /*printk("off screen top\n");*/
+ }
+
+ /* record settings */
+ win->w[plane].xpos = xpos;
+ win->w[plane].ypos = ypos;
+
+ xsz -= 1;
+ ysz -= 1;
+ winctrl0 |= (xpos << 21);
+ winctrl0 |= (ypos << 10);
+ winctrl1 |= (xsz << 11);
+ winctrl1 |= (ysz << 0);
+
+ /* Disable the window while making changes, then restore WINEN */
+ winenable = lcd->winenable & (1 << plane);
+ au_sync();
+ lcd->winenable &= ~(1 << plane);
+ lcd->window[plane].winctrl0 = winctrl0;
+ lcd->window[plane].winctrl1 = winctrl1;
+ lcd->window[plane].winbuf0 =
+ lcd->window[plane].winbuf1 = fbdev->fb_phys;
+ lcd->window[plane].winbufctrl = 0; /* select winbuf0 */
+ lcd->winenable |= winenable;
+ au_sync();
+
+ return 0;
+}
+
+static void au1200_setpanel (struct panel_settings *newpanel)
+{
+ /*
+ * Perform global setup/init of LCD controller
+ */
+ uint32 winenable;
+
+ /* Make sure all windows disabled */
+ winenable = lcd->winenable;
+ lcd->winenable = 0;
+ au_sync();
+ /*
+ * Ensure everything is disabled before reconfiguring
+ */
+ if (lcd->screen & LCD_SCREEN_SEN) {
+ /* Wait for vertical sync period */
+ lcd->intstatus = LCD_INT_SS;
+ while ((lcd->intstatus & LCD_INT_SS) == 0) {
+ au_sync();
+ }
+
+ lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/
+
+ do {
+ lcd->intstatus = lcd->intstatus; /*clear interrupts*/
+ au_sync();
+ /*wait for controller to shut down*/
+ } while ((lcd->intstatus & LCD_INT_SD) == 0);
+
+ /* Call shutdown of current panel (if up) */
+ /* this must occur last, because if an external clock is driving
+ the controller, the clock cannot be turned off before first
+ shutting down the controller.
+ */
+ if (panel->device_shutdown != NULL)
+ panel->device_shutdown();
+ }
+
+ /* Newpanel == NULL indicates a shutdown operation only */
+ if (newpanel == NULL)
+ return;
+
+ panel = newpanel;
+
+ printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres);
+
+ /*
+ * Setup clocking if internal LCD clock source (assumes sys_auxpll valid)
+ */
+ if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT))
+ {
+ uint32 sys_clksrc;
+ au_writel(panel->mode_auxpll, SYS_AUXPLL);
+ sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f;
+ sys_clksrc |= panel->mode_toyclksrc;
+ au_writel(sys_clksrc, SYS_CLKSRC);
+ }
+
+ /*
+ * Configure panel timings
+ */
+ lcd->screen = panel->mode_screen;
+ lcd->horztiming = panel->mode_horztiming;
+ lcd->verttiming = panel->mode_verttiming;
+ lcd->clkcontrol = panel->mode_clkcontrol;
+ lcd->pwmdiv = panel->mode_pwmdiv;
+ lcd->pwmhi = panel->mode_pwmhi;
+ lcd->outmask = panel->mode_outmask;
+ lcd->fifoctrl = panel->mode_fifoctrl;
+ au_sync();
+
+ /* fixme: Check window settings to make sure still valid
+ * for new geometry */
+#if 0
+ au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos);
+ au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos);
+ au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos);
+ au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos);
+#endif
+ lcd->winenable = winenable;
+
+ /*
+ * Re-enable screen now that it is configured
+ */
+ lcd->screen |= LCD_SCREEN_SEN;
+ au_sync();
+
+ /* Call init of panel */
+ if (panel->device_init != NULL) panel->device_init();
+
+ /* FIX!!!! not appropriate on panel change!!! Global setup/init */
+ lcd->intenable = 0;
+ lcd->intstatus = ~0;
+ lcd->backcolor = win->mode_backcolor;
+
+ /* Setup Color Key - FIX!!! */
+ lcd->colorkey = win->mode_colorkey;
+ lcd->colorkeymsk = win->mode_colorkeymsk;
+
+ /* Setup HWCursor - FIX!!! Need to support this eventually */
+ lcd->hwc.cursorctrl = 0;
+ lcd->hwc.cursorpos = 0;
+ lcd->hwc.cursorcolor0 = 0;
+ lcd->hwc.cursorcolor1 = 0;
+ lcd->hwc.cursorcolor2 = 0;
+ lcd->hwc.cursorcolor3 = 0;
+
+
+#if 0
+#define D(X) printk("%25s: %08X\n", #X, X)
+ D(lcd->screen);
+ D(lcd->horztiming);
+ D(lcd->verttiming);
+ D(lcd->clkcontrol);
+ D(lcd->pwmdiv);
+ D(lcd->pwmhi);
+ D(lcd->outmask);
+ D(lcd->fifoctrl);
+ D(lcd->window[0].winctrl0);
+ D(lcd->window[0].winctrl1);
+ D(lcd->window[0].winctrl2);
+ D(lcd->window[0].winbuf0);
+ D(lcd->window[0].winbuf1);
+ D(lcd->window[0].winbufctrl);
+ D(lcd->window[1].winctrl0);
+ D(lcd->window[1].winctrl1);
+ D(lcd->window[1].winctrl2);
+ D(lcd->window[1].winbuf0);
+ D(lcd->window[1].winbuf1);
+ D(lcd->window[1].winbufctrl);
+ D(lcd->window[2].winctrl0);
+ D(lcd->window[2].winctrl1);
+ D(lcd->window[2].winctrl2);
+ D(lcd->window[2].winbuf0);
+ D(lcd->window[2].winbuf1);
+ D(lcd->window[2].winbufctrl);
+ D(lcd->window[3].winctrl0);
+ D(lcd->window[3].winctrl1);
+ D(lcd->window[3].winctrl2);
+ D(lcd->window[3].winbuf0);
+ D(lcd->window[3].winbuf1);
+ D(lcd->window[3].winbufctrl);
+ D(lcd->winenable);
+ D(lcd->intenable);
+ D(lcd->intstatus);
+ D(lcd->backcolor);
+ D(lcd->winenable);
+ D(lcd->colorkey);
+ D(lcd->colorkeymsk);
+ D(lcd->hwc.cursorctrl);
+ D(lcd->hwc.cursorpos);
+ D(lcd->hwc.cursorcolor0);
+ D(lcd->hwc.cursorcolor1);
+ D(lcd->hwc.cursorcolor2);
+ D(lcd->hwc.cursorcolor3);
+#endif
+}
+
+static void au1200_setmode(struct au1200fb_device *fbdev)
+{
+ int plane = fbdev->plane;
+ /* Window/plane setup */
+ lcd->window[plane].winctrl1 = ( 0
+ | LCD_WINCTRL1_PRI_N(plane)
+ | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */
+ ) ;
+
+ au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos);
+
+ lcd->window[plane].winctrl2 = ( 0
+ | LCD_WINCTRL2_CKMODE_00
+ | LCD_WINCTRL2_DBM
+ | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length)
+ | LCD_WINCTRL2_SCX_1
+ | LCD_WINCTRL2_SCY_1
+ ) ;
+ lcd->winenable |= win->w[plane].mode_winenable;
+ au_sync();
+}
+
+
+/* Inline helpers */
+
+/*#define panel_is_dual(panel) ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
+/*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
+
+#define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN)
+
+/* Bitfields format supported by the controller. */
+static struct fb_bitfield rgb_bitfields[][4] = {
+ /* Red, Green, Blue, Transp */
+ [LCD_WINCTRL1_FRM_16BPP655 >> 25] =
+ { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPP565 >> 25] =
+ { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPP556 >> 25] =
+ { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPPI1555 >> 25] =
+ { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPPI5551 >> 25] =
+ { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPPA1555 >> 25] =
+ { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPPA5551 >> 25] =
+ { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } },
+
+ [LCD_WINCTRL1_FRM_24BPP >> 25] =
+ { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_32BPP >> 25] =
+ { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } },
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Helpers */
+
+static void au1200fb_update_fbinfo(struct fb_info *fbi)
+{
+ /* FIX!!!! This also needs to take the window pixel format into account!!! */
+
+ /* Update var-dependent FB info */
+ if (panel_is_color(panel)) {
+ if (fbi->var.bits_per_pixel <= 8) {
+ /* palettized */
+ fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ fbi->fix.line_length = fbi->var.xres_virtual /
+ (8/fbi->var.bits_per_pixel);
+ } else {
+ /* non-palettized */
+ fbi->fix.visual = FB_VISUAL_TRUECOLOR;
+ fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8);
+ }
+ } else {
+ /* mono FIX!!! mono 8 and 4 bits */
+ fbi->fix.visual = FB_VISUAL_MONO10;
+ fbi->fix.line_length = fbi->var.xres_virtual / 8;
+ }
+
+ fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual;
+ print_dbg("line length: %d\n", fbi->fix.line_length);
+ print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* AU1200 framebuffer driver */
+
+/* fb_check_var
+ * Validate var settings with hardware restrictions and modify it if necessary
+ */
+static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *fbi)
+{
+ struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
+ u32 pixclock;
+ int screen_size, plane;
+
+ plane = fbdev->plane;
+
+ /* Make sure that the mode respect all LCD controller and
+ * panel restrictions. */
+ var->xres = win->w[plane].xres;
+ var->yres = win->w[plane].yres;
+
+ /* No need for virtual resolution support */
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres;
+
+ var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1);
+
+ screen_size = var->xres_virtual * var->yres_virtual;
+ if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8);
+ else screen_size /= (8/var->bits_per_pixel);
+
+ if (fbdev->fb_len < screen_size)
+ return -EINVAL; /* Virtual screen is to big, abort */
+
+ /* FIX!!!! what are the implicaitons of ignoring this for windows ??? */
+ /* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel
+ * clock can only be obtain by dividing this value by an even integer.
+ * Fallback to a slower pixel clock if necessary. */
+ pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin);
+ pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2));
+
+ if (AU1200_LCD_MAX_CLK % pixclock) {
+ int diff = AU1200_LCD_MAX_CLK % pixclock;
+ pixclock -= diff;
+ }
+
+ var->pixclock = KHZ2PICOS(pixclock/1000);
+#if 0
+ if (!panel_is_active(panel)) {
+ int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1;
+
+ if (!panel_is_color(panel)
+ && (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) {
+ /* STN 8bit mono panel support is up to 6MHz pixclock */
+ var->pixclock = KHZ2PICOS(6000);
+ } else if (!pcd) {
+ /* Other STN panel support is up to 12MHz */
+ var->pixclock = KHZ2PICOS(12000);
+ }
+ }
+#endif
+ /* Set bitfield accordingly */
+ switch (var->bits_per_pixel) {
+ case 16:
+ {
+ /* 16bpp True color.
+ * These must be set to MATCH WINCTRL[FORM] */
+ int idx;
+ idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
+ var->red = rgb_bitfields[idx][0];
+ var->green = rgb_bitfields[idx][1];
+ var->blue = rgb_bitfields[idx][2];
+ var->transp = rgb_bitfields[idx][3];
+ break;
+ }
+
+ case 32:
+ {
+ /* 32bpp True color.
+ * These must be set to MATCH WINCTRL[FORM] */
+ int idx;
+ idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
+ var->red = rgb_bitfields[idx][0];
+ var->green = rgb_bitfields[idx][1];
+ var->blue = rgb_bitfields[idx][2];
+ var->transp = rgb_bitfields[idx][3];
+ break;
+ }
+ default:
+ print_dbg("Unsupported depth %dbpp", var->bits_per_pixel);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* fb_set_par
+ * Set hardware with var settings. This will enable the controller with a
+ * specific mode, normally validated with the fb_check_var method
+ */
+static int au1200fb_fb_set_par(struct fb_info *fbi)
+{
+ struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
+
+ au1200fb_update_fbinfo(fbi);
+ au1200_setmode(fbdev);
+
+ return 0;
+}
+
+/* fb_setcolreg
+ * Set color in LCD palette.
+ */
+static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp, struct fb_info *fbi)
+{
+ volatile u32 *palette = lcd->palette;
+ u32 value;
+
+ if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1))
+ return -EINVAL;
+
+ if (fbi->var.grayscale) {
+ /* Convert color to grayscale */
+ red = green = blue =
+ (19595 * red + 38470 * green + 7471 * blue) >> 16;
+ }
+
+ if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {
+ /* Place color in the pseudopalette */
+ if (regno > 16)
+ return -EINVAL;
+
+ palette = (u32*) fbi->pseudo_palette;
+
+ red >>= (16 - fbi->var.red.length);
+ green >>= (16 - fbi->var.green.length);
+ blue >>= (16 - fbi->var.blue.length);
+
+ value = (red << fbi->var.red.offset) |
+ (green << fbi->var.green.offset)|
+ (blue << fbi->var.blue.offset);
+ value &= 0xFFFF;
+
+ } else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) {
+ /* COLOR TFT PALLETTIZED (use RGB 565) */
+ value = (red & 0xF800)|((green >> 5) &
+ 0x07E0)|((blue >> 11) & 0x001F);
+ value &= 0xFFFF;
+
+ } else if (0 /*panel_is_color(fbdev->panel)*/) {
+ /* COLOR STN MODE */
+ value = 0x1234;
+ value &= 0xFFF;
+ } else {
+ /* MONOCHROME MODE */
+ value = (green >> 12) & 0x000F;
+ value &= 0xF;
+ }
+
+ palette[regno] = value;
+
+ return 0;
+}
+
+/* fb_blank
+ * Blank the screen. Depending on the mode, the screen will be
+ * activated with the backlight color, or desactivated
+ */
+static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi)
+{
+ /* Short-circuit screen blanking */
+ if (noblanking)
+ return 0;
+
+ switch (blank_mode) {
+
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ /* printk("turn on panel\n"); */
+ au1200_setpanel(panel);
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ /* printk("turn off panel\n"); */
+ au1200_setpanel(NULL);
+ break;
+ default:
+ break;
+
+ }
+
+ /* FB_BLANK_NORMAL is a soft blank */
+ return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0;
+}
+
+/* fb_mmap
+ * Map video memory in user space. We don't use the generic fb_mmap
+ * method mainly to allow the use of the TLB streaming flag (CCA=6)
+ */
+static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+
+{
+ unsigned int len;
+ unsigned long start=0, off;
+ struct au1200fb_device *fbdev = (struct au1200fb_device *) info;
+
+#ifdef CONFIG_PM
+ au1xxx_pm_access(LCD_pm_dev);
+#endif
+
+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
+ return -EINVAL;
+ }
+
+ start = fbdev->fb_phys & PAGE_MASK;
+ len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len);
+
+ off = vma->vm_pgoff << PAGE_SHIFT;
+
+ if ((vma->vm_end - vma->vm_start + off) > len) {
+ return -EINVAL;
+ }
+
+ off += start;
+ vma->vm_pgoff = off >> PAGE_SHIFT;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */
+
+ vma->vm_flags |= VM_IO;
+
+ return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+
+ return 0;
+}
+
+static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
+{
+
+ unsigned int hi1, divider;
+
+ /* SCREEN_SIZE: user cannot reset size, must switch panel choice */
+
+ if (pdata->flags & SCREEN_BACKCOLOR)
+ lcd->backcolor = pdata->backcolor;
+
+ if (pdata->flags & SCREEN_BRIGHTNESS) {
+
+ // limit brightness pwm duty to >= 30/1600
+ if (pdata->brightness < 30) {
+ pdata->brightness = 30;
+ }
+ divider = (lcd->pwmdiv & 0x3FFFF) + 1;
+ hi1 = (lcd->pwmhi >> 16) + 1;
+ hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8);
+ lcd->pwmhi &= 0xFFFF;
+ lcd->pwmhi |= (hi1 << 16);
+ }
+
+ if (pdata->flags & SCREEN_COLORKEY)
+ lcd->colorkey = pdata->colorkey;
+
+ if (pdata->flags & SCREEN_MASK)
+ lcd->colorkeymsk = pdata->mask;
+ au_sync();
+}
+
+static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
+{
+ unsigned int hi1, divider;
+
+ pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1;
+ pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1;
+
+ pdata->backcolor = lcd->backcolor;
+ pdata->colorkey = lcd->colorkey;
+ pdata->mask = lcd->colorkeymsk;
+
+ // brightness
+ hi1 = (lcd->pwmhi >> 16) + 1;
+ divider = (lcd->pwmdiv & 0x3FFFF) + 1;
+ pdata->brightness = ((hi1 << 8) / divider) - 1;
+ au_sync();
+}
+
+static void set_window(unsigned int plane,
+ struct au1200_lcd_window_regs_t *pdata)
+{
+ unsigned int val, bpp;
+
+ /* Window control register 0 */
+ if (pdata->flags & WIN_POSITION) {
+ val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX |
+ LCD_WINCTRL0_OY);
+ val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX);
+ val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY);
+ lcd->window[plane].winctrl0 = val;
+ }
+ if (pdata->flags & WIN_ALPHA_COLOR) {
+ val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A);
+ val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A);
+ lcd->window[plane].winctrl0 = val;
+ }
+ if (pdata->flags & WIN_ALPHA_MODE) {
+ val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN);
+ val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN);
+ lcd->window[plane].winctrl0 = val;
+ }
+
+ /* Window control register 1 */
+ if (pdata->flags & WIN_PRIORITY) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI);
+ val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_CHANNEL) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE);
+ val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_BUFFER_FORMAT) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM);
+ val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_COLOR_ORDER) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO);
+ val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_PIXEL_ORDER) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO);
+ val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_SIZE) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX |
+ LCD_WINCTRL1_SZY);
+ val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX);
+ val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY);
+ lcd->window[plane].winctrl1 = val;
+ /* program buffer line width */
+ bpp = winbpp(val) / 8;
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX);
+ val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX);
+ lcd->window[plane].winctrl2 = val;
+ }
+
+ /* Window control register 2 */
+ if (pdata->flags & WIN_COLORKEY_MODE) {
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE);
+ val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE);
+ lcd->window[plane].winctrl2 = val;
+ }
+ if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) {
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM);
+ val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM);
+ lcd->window[plane].winctrl2 = val;
+ }
+ if (pdata->flags & WIN_RAM_ARRAY_MODE) {
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM);
+ val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM);
+ lcd->window[plane].winctrl2 = val;
+ }
+
+ /* Buffer line width programmed with WIN_SIZE */
+
+ if (pdata->flags & WIN_BUFFER_SCALE) {
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX |
+ LCD_WINCTRL2_SCY);
+ val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX);
+ val |= ((pdata->ysize) & LCD_WINCTRL2_SCY);
+ lcd->window[plane].winctrl2 = val;
+ }
+
+ if (pdata->flags & WIN_ENABLE) {
+ val = lcd->winenable;
+ val &= ~(1<<plane);
+ val |= (pdata->enable & 1) << plane;
+ lcd->winenable = val;
+ }
+ au_sync();
+}
+
+static void get_window(unsigned int plane,
+ struct au1200_lcd_window_regs_t *pdata)
+{
+ /* Window control register 0 */
+ pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21;
+ pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10;
+ pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2;
+ pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1;
+
+ /* Window control register 1 */
+ pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30;
+ pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29;
+ pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25;
+ pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24;
+ pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22;
+ pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1;
+ pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1;
+
+ /* Window control register 2 */
+ pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24;
+ pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23;
+ pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21;
+
+ pdata->enable = (lcd->winenable >> plane) & 1;
+ au_sync();
+}
+
+static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+{
+ int plane;
+ int val;
+
+#ifdef CONFIG_PM
+ au1xxx_pm_access(LCD_pm_dev);
+#endif
+
+ plane = fbinfo2index(info);
+ print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane);
+
+ if (cmd == AU1200_LCD_FB_IOCTL) {
+ struct au1200_lcd_iodata_t iodata;
+
+ if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata)))
+ return -EFAULT;
+
+ print_dbg("FB IOCTL called\n");
+
+ switch (iodata.subcmd) {
+ case AU1200_LCD_SET_SCREEN:
+ print_dbg("AU1200_LCD_SET_SCREEN\n");
+ set_global(cmd, &iodata.global);
+ break;
+
+ case AU1200_LCD_GET_SCREEN:
+ print_dbg("AU1200_LCD_GET_SCREEN\n");
+ get_global(cmd, &iodata.global);
+ break;
+
+ case AU1200_LCD_SET_WINDOW:
+ print_dbg("AU1200_LCD_SET_WINDOW\n");
+ set_window(plane, &iodata.window);
+ break;
+
+ case AU1200_LCD_GET_WINDOW:
+ print_dbg("AU1200_LCD_GET_WINDOW\n");
+ get_window(plane, &iodata.window);
+ break;
+
+ case AU1200_LCD_SET_PANEL:
+ print_dbg("AU1200_LCD_SET_PANEL\n");
+ if ((iodata.global.panel_choice >= 0) &&
+ (iodata.global.panel_choice <
+ NUM_PANELS))
+ {
+ struct panel_settings *newpanel;
+ panel_index = iodata.global.panel_choice;
+ newpanel = &known_lcd_panels[panel_index];
+ au1200_setpanel(newpanel);
+ }
+ break;
+
+ case AU1200_LCD_GET_PANEL:
+ print_dbg("AU1200_LCD_GET_PANEL\n");
+ iodata.global.panel_choice = panel_index;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata));
+ if (val) {
+ print_dbg("error: could not copy %d bytes\n", val);
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+
+static struct fb_ops au1200fb_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = au1200fb_fb_check_var,
+ .fb_set_par = au1200fb_fb_set_par,
+ .fb_setcolreg = au1200fb_fb_setcolreg,
+ .fb_blank = au1200fb_fb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_sync = NULL,
+ .fb_ioctl = au1200fb_ioctl,
+ .fb_mmap = au1200fb_fb_mmap,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs)
+{
+ /* Nothing to do for now, just clear any pending interrupt */
+ lcd->intstatus = lcd->intstatus;
+ au_sync();
+
+ return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* AU1200 LCD device probe helpers */
+
+static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
+{
+ struct fb_info *fbi = &fbdev->fb_info;
+ int bpp;
+
+ memset(fbi, 0, sizeof(struct fb_info));
+ fbi->fbops = &au1200fb_fb_ops;
+
+ bpp = winbpp(win->w[fbdev->plane].mode_winctrl1);
+
+ /* Copy monitor specs from panel data */
+ /* fixme: we're setting up LCD controller windows, so these dont give a
+ damn as to what the monitor specs are (the panel itself does, but that
+ isnt done here...so maybe need a generic catchall monitor setting??? */
+ memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs));
+
+ /* We first try the user mode passed in argument. If that failed,
+ * or if no one has been specified, we default to the first mode of the
+ * panel list. Note that after this call, var data will be set */
+ if (!fb_find_mode(&fbi->var,
+ fbi,
+ NULL, /* drv_info.opt_mode, */
+ fbi->monspecs.modedb,
+ fbi->monspecs.modedb_len,
+ fbi->monspecs.modedb,
+ bpp)) {
+
+ print_err("Cannot find valid mode for panel %s", panel->name);
+ return -EFAULT;
+ }
+
+ fbi->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
+ if (!fbi->pseudo_palette) {
+ return -ENOMEM;
+ }
+ memset(fbi->pseudo_palette, 0, sizeof(u32) * 16);
+
+ if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
+ print_err("Fail to allocate colormap (%d entries)",
+ AU1200_LCD_NBR_PALETTE_ENTRIES);
+ kfree(fbi->pseudo_palette);
+ return -EFAULT;
+ }
+
+ strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id));
+ fbi->fix.smem_start = fbdev->fb_phys;
+ fbi->fix.smem_len = fbdev->fb_len;
+ fbi->fix.type = FB_TYPE_PACKED_PIXELS;
+ fbi->fix.xpanstep = 0;
+ fbi->fix.ypanstep = 0;
+ fbi->fix.mmio_start = 0;
+ fbi->fix.mmio_len = 0;
+ fbi->fix.accel = FB_ACCEL_NONE;
+
+ fbi->screen_base = (char __iomem *) fbdev->fb_mem;
+
+ au1200fb_update_fbinfo(fbi);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* AU1200 LCD controller device driver */
+
+static int au1200fb_drv_probe(struct device *dev)
+{
+ struct au1200fb_device *fbdev;
+ unsigned long page;
+ int bpp, plane, ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
+ bpp = winbpp(win->w[plane].mode_winctrl1);
+ if (win->w[plane].xres == 0)
+ win->w[plane].xres = panel->Xres;
+ if (win->w[plane].yres == 0)
+ win->w[plane].yres = panel->Yres;
+
+ fbdev = &_au1200fb_devices[plane];
+ memset(fbdev, 0, sizeof(struct au1200fb_device));
+ fbdev->plane = plane;
+
+ /* Allocate the framebuffer to the maximum screen size */
+ fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
+
+ fbdev->fb_mem = dma_alloc_noncoherent(dev,
+ PAGE_ALIGN(fbdev->fb_len),
+ &fbdev->fb_phys, GFP_KERNEL);
+ if (!fbdev->fb_mem) {
+ print_err("fail to allocate frambuffer (size: %dK))",
+ fbdev->fb_len / 1024);
+ return -ENOMEM;
+ }
+
+ /*
+ * Set page reserved so that mmap will work. This is necessary
+ * since we'll be remapping normal memory.
+ */
+ for (page = (unsigned long)fbdev->fb_phys;
+ page < PAGE_ALIGN((unsigned long)fbdev->fb_phys +
+ fbdev->fb_len);
+ page += PAGE_SIZE) {
+ SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */
+ }
+ print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
+ print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
+
+ /* Init FB data */
+ if ((ret = au1200fb_init_fbinfo(fbdev)) < 0)
+ goto failed;
+
+ /* Register new framebuffer */
+ if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) {
+ print_err("cannot register new framebuffer");
+ goto failed;
+ }
+
+ au1200fb_fb_set_par(&fbdev->fb_info);
+
+#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
+ if (plane == 0)
+ if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) {
+ /* Start display and show logo on boot */
+ fb_set_cmap(&fbdev->fb_info.cmap,
+ &fbdev->fb_info);
+
+ fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR);
+ }
+#endif
+ }
+
+ /* Now hook interrupt too */
+ if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq,
+ SA_INTERRUPT | SA_SHIRQ, "lcd", (void *)dev)) < 0) {
+ print_err("fail to request interrupt line %d (err: %d)",
+ AU1200_LCD_INT, ret);
+ goto failed;
+ }
+
+ return 0;
+
+failed:
+ /* NOTE: This only does the current plane/window that failed; others are still active */
+ if (fbdev->fb_mem)
+ dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len),
+ fbdev->fb_mem, fbdev->fb_phys);
+ if (fbdev->fb_info.cmap.len != 0)
+ fb_dealloc_cmap(&fbdev->fb_info.cmap);
+ if (fbdev->fb_info.pseudo_palette)
+ kfree(fbdev->fb_info.pseudo_palette);
+ if (plane == 0)
+ free_irq(AU1200_LCD_INT, (void*)dev);
+ return ret;
+}
+
+static int au1200fb_drv_remove(struct device *dev)
+{
+ struct au1200fb_device *fbdev;
+ int plane;
+
+ if (!dev)
+ return -ENODEV;
+
+ /* Turn off the panel */
+ au1200_setpanel(NULL);
+
+ for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane)
+ {
+ fbdev = &_au1200fb_devices[plane];
+
+ /* Clean up all probe data */
+ unregister_framebuffer(&fbdev->fb_info);
+ if (fbdev->fb_mem)
+ dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len),
+ fbdev->fb_mem, fbdev->fb_phys);
+ if (fbdev->fb_info.cmap.len != 0)
+ fb_dealloc_cmap(&fbdev->fb_info.cmap);
+ if (fbdev->fb_info.pseudo_palette)
+ kfree(fbdev->fb_info.pseudo_palette);
+ }
+
+ free_irq(AU1200_LCD_INT, (void *)dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level)
+{
+ /* TODO */
+ return 0;
+}
+
+static int au1200fb_drv_resume(struct device *dev, u32 level)
+{
+ /* TODO */
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct device_driver au1200fb_driver = {
+ .name = "au1200-lcd",
+ .bus = &platform_bus_type,
+ .probe = au1200fb_drv_probe,
+ .remove = au1200fb_drv_remove,
+#ifdef CONFIG_PM
+ .suspend = au1200fb_drv_suspend,
+ .resume = au1200fb_drv_resume,
+#endif
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Kernel driver */
+
+static void au1200fb_setup(void)
+{
+ char* options = NULL;
+ char* this_opt;
+ int num_panels = ARRAY_SIZE(known_lcd_panels);
+ int panel_idx = -1;
+
+ fb_get_options(DRIVER_NAME, &options);
+
+ if (options) {
+ while ((this_opt = strsep(&options,",")) != NULL) {
+ /* Panel option - can be panel name,
+ * "bs" for board-switch, or number/index */
+ if (!strncmp(this_opt, "panel:", 6)) {
+ int i;
+ long int li;
+ char *endptr;
+ this_opt += 6;
+ /* First check for index, which allows
+ * to short circuit this mess */
+ li = simple_strtol(this_opt, &endptr, 0);
+ if (*endptr == '\0') {
+ panel_idx = (int)li;
+ }
+ else if (strcmp(this_opt, "bs") == 0) {
+ extern int board_au1200fb_panel(void);
+ panel_idx = board_au1200fb_panel();
+ }
+
+ else
+ for (i = 0; i < num_panels; i++) {
+ if (!strcmp(this_opt, known_lcd_panels[i].name)) {
+ panel_idx = i;
+ break;
+ }
+ }
+
+ if ((panel_idx < 0) || (panel_idx >= num_panels)) {
+ print_warn("Panel %s not supported!", this_opt);
+ }
+ else
+ panel_index = panel_idx;
+ }
+
+ else if (strncmp(this_opt, "nohwcursor", 10) == 0) {
+ nohwcursor = 1;
+ }
+
+ /* Unsupported option */
+ else {
+ print_warn("Unsupported option \"%s\"", this_opt);
+ }
+ }
+ }
+}
+
+#ifdef CONFIG_PM
+static int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
+ au1xxx_request_t request, void *data) {
+ int retval = -1;
+ unsigned int d = 0;
+ unsigned int brightness = 0;
+
+ if (request == AU1XXX_PM_SLEEP) {
+ board_au1200fb_panel_shutdown();
+ }
+ else if (request == AU1XXX_PM_WAKEUP) {
+ if(dev->prev_state == SLEEP_STATE)
+ {
+ int plane;
+ au1200_setpanel(panel);
+ for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
+ struct au1200fb_device *fbdev;
+ fbdev = &_au1200fb_devices[plane];
+ au1200fb_fb_set_par(&fbdev->fb_info);
+ }
+ }
+
+ d = *((unsigned int*)data);
+ if(d <=10) brightness = 26;
+ else if(d<=20) brightness = 51;
+ else if(d<=30) brightness = 77;
+ else if(d<=40) brightness = 102;
+ else if(d<=50) brightness = 128;
+ else if(d<=60) brightness = 153;
+ else if(d<=70) brightness = 179;
+ else if(d<=80) brightness = 204;
+ else if(d<=90) brightness = 230;
+ else brightness = 255;
+ set_brightness(brightness);
+ } else if (request == AU1XXX_PM_GETSTATUS) {
+ return dev->cur_state;
+ } else if (request == AU1XXX_PM_ACCESS) {
+ if (dev->cur_state != SLEEP_STATE)
+ return retval;
+ else {
+ au1200_setpanel(panel);
+ }
+ } else if (request == AU1XXX_PM_IDLE) {
+ } else if (request == AU1XXX_PM_CLEANUP) {
+ }
+
+ return retval;
+}
+#endif
+
+static int __init au1200fb_init(void)
+{
+ print_info("" DRIVER_DESC "");
+
+ /* Setup driver with options */
+ au1200fb_setup();
+
+ /* Point to the panel selected */
+ panel = &known_lcd_panels[panel_index];
+ win = &windows[window_index];
+
+ printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
+ printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
+
+ /* Kickstart the panel, the framebuffers/windows come soon enough */
+ au1200_setpanel(panel);
+
+ #ifdef CONFIG_PM
+ LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL);
+ if ( LCD_pm_dev == NULL)
+ printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n");
+ else
+ printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n");
+ #endif
+
+ return driver_register(&au1200fb_driver);
+}
+
+static void __exit au1200fb_cleanup(void)
+{
+ driver_unregister(&au1200fb_driver);
+}
+
+module_init(au1200fb_init);
+module_exit(au1200fb_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/au1200fb.h b/drivers/video/au1200fb.h
new file mode 100644
index 00000000000..e2672714d8d
--- /dev/null
+++ b/drivers/video/au1200fb.h
@@ -0,0 +1,572 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Hardware definitions for the Au1200 LCD controller
+ *
+ * Copyright 2004 AMD
+ * Author: AMD
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _AU1200LCD_H
+#define _AU1200LCD_H
+
+/********************************************************************/
+#define AU1200_LCD_ADDR 0xB5000000
+
+#define uint8 unsigned char
+#define uint32 unsigned int
+
+struct au1200_lcd {
+ volatile uint32 reserved0;
+ volatile uint32 screen;
+ volatile uint32 backcolor;
+ volatile uint32 horztiming;
+ volatile uint32 verttiming;
+ volatile uint32 clkcontrol;
+ volatile uint32 pwmdiv;
+ volatile uint32 pwmhi;
+ volatile uint32 reserved1;
+ volatile uint32 winenable;
+ volatile uint32 colorkey;
+ volatile uint32 colorkeymsk;
+ struct
+ {
+ volatile uint32 cursorctrl;
+ volatile uint32 cursorpos;
+ volatile uint32 cursorcolor0;
+ volatile uint32 cursorcolor1;
+ volatile uint32 cursorcolor2;
+ uint32 cursorcolor3;
+ } hwc;
+ volatile uint32 intstatus;
+ volatile uint32 intenable;
+ volatile uint32 outmask;
+ volatile uint32 fifoctrl;
+ uint32 reserved2[(0x0100-0x0058)/4];
+ struct
+ {
+ volatile uint32 winctrl0;
+ volatile uint32 winctrl1;
+ volatile uint32 winctrl2;
+ volatile uint32 winbuf0;
+ volatile uint32 winbuf1;
+ volatile uint32 winbufctrl;
+ uint32 winreserved0;
+ uint32 winreserved1;
+ } window[4];
+
+ uint32 reserved3[(0x0400-0x0180)/4];
+
+ volatile uint32 palette[(0x0800-0x0400)/4];
+
+ volatile uint8 cursorpattern[256];
+};
+
+/* lcd_screen */
+#define LCD_SCREEN_SEN (1<<31)
+#define LCD_SCREEN_SX (0x07FF<<19)
+#define LCD_SCREEN_SY (0x07FF<< 8)
+#define LCD_SCREEN_SWP (1<<7)
+#define LCD_SCREEN_SWD (1<<6)
+#define LCD_SCREEN_PT (7<<0)
+#define LCD_SCREEN_PT_TFT (0<<0)
+#define LCD_SCREEN_SX_N(WIDTH) ((WIDTH-1)<<19)
+#define LCD_SCREEN_SY_N(HEIGHT) ((HEIGHT-1)<<8)
+#define LCD_SCREEN_PT_CSTN (1<<0)
+#define LCD_SCREEN_PT_CDSTN (2<<0)
+#define LCD_SCREEN_PT_M8STN (3<<0)
+#define LCD_SCREEN_PT_M4STN (4<<0)
+
+/* lcd_backcolor */
+#define LCD_BACKCOLOR_SBGR (0xFF<<16)
+#define LCD_BACKCOLOR_SBGG (0xFF<<8)
+#define LCD_BACKCOLOR_SBGB (0xFF<<0)
+#define LCD_BACKCOLOR_SBGR_N(N) ((N)<<16)
+#define LCD_BACKCOLOR_SBGG_N(N) ((N)<<8)
+#define LCD_BACKCOLOR_SBGB_N(N) ((N)<<0)
+
+/* lcd_winenable */
+#define LCD_WINENABLE_WEN3 (1<<3)
+#define LCD_WINENABLE_WEN2 (1<<2)
+#define LCD_WINENABLE_WEN1 (1<<1)
+#define LCD_WINENABLE_WEN0 (1<<0)
+
+/* lcd_colorkey */
+#define LCD_COLORKEY_CKR (0xFF<<16)
+#define LCD_COLORKEY_CKG (0xFF<<8)
+#define LCD_COLORKEY_CKB (0xFF<<0)
+#define LCD_COLORKEY_CKR_N(N) ((N)<<16)
+#define LCD_COLORKEY_CKG_N(N) ((N)<<8)
+#define LCD_COLORKEY_CKB_N(N) ((N)<<0)
+
+/* lcd_colorkeymsk */
+#define LCD_COLORKEYMSK_CKMR (0xFF<<16)
+#define LCD_COLORKEYMSK_CKMG (0xFF<<8)
+#define LCD_COLORKEYMSK_CKMB (0xFF<<0)
+#define LCD_COLORKEYMSK_CKMR_N(N) ((N)<<16)
+#define LCD_COLORKEYMSK_CKMG_N(N) ((N)<<8)
+#define LCD_COLORKEYMSK_CKMB_N(N) ((N)<<0)
+
+/* lcd windows control 0 */
+#define LCD_WINCTRL0_OX (0x07FF<<21)
+#define LCD_WINCTRL0_OY (0x07FF<<10)
+#define LCD_WINCTRL0_A (0x00FF<<2)
+#define LCD_WINCTRL0_AEN (1<<1)
+#define LCD_WINCTRL0_OX_N(N) ((N)<<21)
+#define LCD_WINCTRL0_OY_N(N) ((N)<<10)
+#define LCD_WINCTRL0_A_N(N) ((N)<<2)
+
+/* lcd windows control 1 */
+#define LCD_WINCTRL1_PRI (3<<30)
+#define LCD_WINCTRL1_PIPE (1<<29)
+#define LCD_WINCTRL1_FRM (0xF<<25)
+#define LCD_WINCTRL1_CCO (1<<24)
+#define LCD_WINCTRL1_PO (3<<22)
+#define LCD_WINCTRL1_SZX (0x07FF<<11)
+#define LCD_WINCTRL1_SZY (0x07FF<<0)
+#define LCD_WINCTRL1_FRM_1BPP (0<<25)
+#define LCD_WINCTRL1_FRM_2BPP (1<<25)
+#define LCD_WINCTRL1_FRM_4BPP (2<<25)
+#define LCD_WINCTRL1_FRM_8BPP (3<<25)
+#define LCD_WINCTRL1_FRM_12BPP (4<<25)
+#define LCD_WINCTRL1_FRM_16BPP655 (5<<25)
+#define LCD_WINCTRL1_FRM_16BPP565 (6<<25)
+#define LCD_WINCTRL1_FRM_16BPP556 (7<<25)
+#define LCD_WINCTRL1_FRM_16BPPI1555 (8<<25)
+#define LCD_WINCTRL1_FRM_16BPPI5551 (9<<25)
+#define LCD_WINCTRL1_FRM_16BPPA1555 (10<<25)
+#define LCD_WINCTRL1_FRM_16BPPA5551 (11<<25)
+#define LCD_WINCTRL1_FRM_24BPP (12<<25)
+#define LCD_WINCTRL1_FRM_32BPP (13<<25)
+#define LCD_WINCTRL1_PRI_N(N) ((N)<<30)
+#define LCD_WINCTRL1_PO_00 (0<<22)
+#define LCD_WINCTRL1_PO_01 (1<<22)
+#define LCD_WINCTRL1_PO_10 (2<<22)
+#define LCD_WINCTRL1_PO_11 (3<<22)
+#define LCD_WINCTRL1_SZX_N(N) ((N-1)<<11)
+#define LCD_WINCTRL1_SZY_N(N) ((N-1)<<0)
+
+/* lcd windows control 2 */
+#define LCD_WINCTRL2_CKMODE (3<<24)
+#define LCD_WINCTRL2_DBM (1<<23)
+#define LCD_WINCTRL2_RAM (3<<21)
+#define LCD_WINCTRL2_BX (0x1FFF<<8)
+#define LCD_WINCTRL2_SCX (0xF<<4)
+#define LCD_WINCTRL2_SCY (0xF<<0)
+#define LCD_WINCTRL2_CKMODE_00 (0<<24)
+#define LCD_WINCTRL2_CKMODE_01 (1<<24)
+#define LCD_WINCTRL2_CKMODE_10 (2<<24)
+#define LCD_WINCTRL2_CKMODE_11 (3<<24)
+#define LCD_WINCTRL2_RAM_NONE (0<<21)
+#define LCD_WINCTRL2_RAM_PALETTE (1<<21)
+#define LCD_WINCTRL2_RAM_GAMMA (2<<21)
+#define LCD_WINCTRL2_RAM_BUFFER (3<<21)
+#define LCD_WINCTRL2_BX_N(N) ((N)<<8)
+#define LCD_WINCTRL2_SCX_1 (0<<4)
+#define LCD_WINCTRL2_SCX_2 (1<<4)
+#define LCD_WINCTRL2_SCX_4 (2<<4)
+#define LCD_WINCTRL2_SCY_1 (0<<0)
+#define LCD_WINCTRL2_SCY_2 (1<<0)
+#define LCD_WINCTRL2_SCY_4 (2<<0)
+
+/* lcd windows buffer control */
+#define LCD_WINBUFCTRL_DB (1<<1)
+#define LCD_WINBUFCTRL_DBN (1<<0)
+
+/* lcd_intstatus, lcd_intenable */
+#define LCD_INT_IFO (0xF<<14)
+#define LCD_INT_IFU (0xF<<10)
+#define LCD_INT_OFO (1<<9)
+#define LCD_INT_OFU (1<<8)
+#define LCD_INT_WAIT (1<<3)
+#define LCD_INT_SD (1<<2)
+#define LCD_INT_SA (1<<1)
+#define LCD_INT_SS (1<<0)
+
+/* lcd_horztiming */
+#define LCD_HORZTIMING_HND2 (0x1FF<<18)
+#define LCD_HORZTIMING_HND1 (0x1FF<<9)
+#define LCD_HORZTIMING_HPW (0x1FF<<0)
+#define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18)
+#define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9)
+#define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<0)
+
+/* lcd_verttiming */
+#define LCD_VERTTIMING_VND2 (0x1FF<<18)
+#define LCD_VERTTIMING_VND1 (0x1FF<<9)
+#define LCD_VERTTIMING_VPW (0x1FF<<0)
+#define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18)
+#define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9)
+#define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<0)
+
+/* lcd_clkcontrol */
+#define LCD_CLKCONTROL_EXT (1<<22)
+#define LCD_CLKCONTROL_DELAY (3<<20)
+#define LCD_CLKCONTROL_CDD (1<<19)
+#define LCD_CLKCONTROL_IB (1<<18)
+#define LCD_CLKCONTROL_IC (1<<17)
+#define LCD_CLKCONTROL_IH (1<<16)
+#define LCD_CLKCONTROL_IV (1<<15)
+#define LCD_CLKCONTROL_BF (0x1F<<10)
+#define LCD_CLKCONTROL_PCD (0x3FF<<0)
+#define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10)
+#define LCD_CLKCONTROL_PCD_N(N) ((N)<<0)
+
+/* lcd_pwmdiv */
+#define LCD_PWMDIV_EN (1<<31)
+#define LCD_PWMDIV_PWMDIV (0x1FFFF<<0)
+#define LCD_PWMDIV_PWMDIV_N(N) ((N)<<0)
+
+/* lcd_pwmhi */
+#define LCD_PWMHI_PWMHI1 (0xFFFF<<16)
+#define LCD_PWMHI_PWMHI0 (0xFFFF<<0)
+#define LCD_PWMHI_PWMHI1_N(N) ((N)<<16)
+#define LCD_PWMHI_PWMHI0_N(N) ((N)<<0)
+
+/* lcd_hwccon */
+#define LCD_HWCCON_EN (1<<0)
+
+/* lcd_cursorpos */
+#define LCD_CURSORPOS_HWCXOFF (0x1F<<27)
+#define LCD_CURSORPOS_HWCXPOS (0x07FF<<16)
+#define LCD_CURSORPOS_HWCYOFF (0x1F<<11)
+#define LCD_CURSORPOS_HWCYPOS (0x07FF<<0)
+#define LCD_CURSORPOS_HWCXOFF_N(N) ((N)<<27)
+#define LCD_CURSORPOS_HWCXPOS_N(N) ((N)<<16)
+#define LCD_CURSORPOS_HWCYOFF_N(N) ((N)<<11)
+#define LCD_CURSORPOS_HWCYPOS_N(N) ((N)<<0)
+
+/* lcd_cursorcolor */
+#define LCD_CURSORCOLOR_HWCA (0xFF<<24)
+#define LCD_CURSORCOLOR_HWCR (0xFF<<16)
+#define LCD_CURSORCOLOR_HWCG (0xFF<<8)
+#define LCD_CURSORCOLOR_HWCB (0xFF<<0)
+#define LCD_CURSORCOLOR_HWCA_N(N) ((N)<<24)
+#define LCD_CURSORCOLOR_HWCR_N(N) ((N)<<16)
+#define LCD_CURSORCOLOR_HWCG_N(N) ((N)<<8)
+#define LCD_CURSORCOLOR_HWCB_N(N) ((N)<<0)
+
+/* lcd_fifoctrl */
+#define LCD_FIFOCTRL_F3IF (1<<29)
+#define LCD_FIFOCTRL_F3REQ (0x1F<<24)
+#define LCD_FIFOCTRL_F2IF (1<<29)
+#define LCD_FIFOCTRL_F2REQ (0x1F<<16)
+#define LCD_FIFOCTRL_F1IF (1<<29)
+#define LCD_FIFOCTRL_F1REQ (0x1F<<8)
+#define LCD_FIFOCTRL_F0IF (1<<29)
+#define LCD_FIFOCTRL_F0REQ (0x1F<<0)
+#define LCD_FIFOCTRL_F3REQ_N(N) ((N-1)<<24)
+#define LCD_FIFOCTRL_F2REQ_N(N) ((N-1)<<16)
+#define LCD_FIFOCTRL_F1REQ_N(N) ((N-1)<<8)
+#define LCD_FIFOCTRL_F0REQ_N(N) ((N-1)<<0)
+
+/* lcd_outmask */
+#define LCD_OUTMASK_MASK (0x00FFFFFF)
+
+/********************************************************************/
+#endif /* _AU1200LCD_H */
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Hardware definitions for the Au1200 LCD controller
+ *
+ * Copyright 2004 AMD
+ * Author: AMD
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _AU1200LCD_H
+#define _AU1200LCD_H
+
+/********************************************************************/
+#define AU1200_LCD_ADDR 0xB5000000
+
+#define uint8 unsigned char
+#define uint32 unsigned int
+
+struct au1200_lcd {
+ volatile uint32 reserved0;
+ volatile uint32 screen;
+ volatile uint32 backcolor;
+ volatile uint32 horztiming;
+ volatile uint32 verttiming;
+ volatile uint32 clkcontrol;
+ volatile uint32 pwmdiv;
+ volatile uint32 pwmhi;
+ volatile uint32 reserved1;
+ volatile uint32 winenable;
+ volatile uint32 colorkey;
+ volatile uint32 colorkeymsk;
+ struct
+ {
+ volatile uint32 cursorctrl;
+ volatile uint32 cursorpos;
+ volatile uint32 cursorcolor0;
+ volatile uint32 cursorcolor1;
+ volatile uint32 cursorcolor2;
+ uint32 cursorcolor3;
+ } hwc;
+ volatile uint32 intstatus;
+ volatile uint32 intenable;
+ volatile uint32 outmask;
+ volatile uint32 fifoctrl;
+ uint32 reserved2[(0x0100-0x0058)/4];
+ struct
+ {
+ volatile uint32 winctrl0;
+ volatile uint32 winctrl1;
+ volatile uint32 winctrl2;
+ volatile uint32 winbuf0;
+ volatile uint32 winbuf1;
+ volatile uint32 winbufctrl;
+ uint32 winreserved0;
+ uint32 winreserved1;
+ } window[4];
+
+ uint32 reserved3[(0x0400-0x0180)/4];
+
+ volatile uint32 palette[(0x0800-0x0400)/4];
+
+ volatile uint8 cursorpattern[256];
+};
+
+/* lcd_screen */
+#define LCD_SCREEN_SEN (1<<31)
+#define LCD_SCREEN_SX (0x07FF<<19)
+#define LCD_SCREEN_SY (0x07FF<< 8)
+#define LCD_SCREEN_SWP (1<<7)
+#define LCD_SCREEN_SWD (1<<6)
+#define LCD_SCREEN_PT (7<<0)
+#define LCD_SCREEN_PT_TFT (0<<0)
+#define LCD_SCREEN_SX_N(WIDTH) ((WIDTH-1)<<19)
+#define LCD_SCREEN_SY_N(HEIGHT) ((HEIGHT-1)<<8)
+#define LCD_SCREEN_PT_CSTN (1<<0)
+#define LCD_SCREEN_PT_CDSTN (2<<0)
+#define LCD_SCREEN_PT_M8STN (3<<0)
+#define LCD_SCREEN_PT_M4STN (4<<0)
+
+/* lcd_backcolor */
+#define LCD_BACKCOLOR_SBGR (0xFF<<16)
+#define LCD_BACKCOLOR_SBGG (0xFF<<8)
+#define LCD_BACKCOLOR_SBGB (0xFF<<0)
+#define LCD_BACKCOLOR_SBGR_N(N) ((N)<<16)
+#define LCD_BACKCOLOR_SBGG_N(N) ((N)<<8)
+#define LCD_BACKCOLOR_SBGB_N(N) ((N)<<0)
+
+/* lcd_winenable */
+#define LCD_WINENABLE_WEN3 (1<<3)
+#define LCD_WINENABLE_WEN2 (1<<2)
+#define LCD_WINENABLE_WEN1 (1<<1)
+#define LCD_WINENABLE_WEN0 (1<<0)
+
+/* lcd_colorkey */
+#define LCD_COLORKEY_CKR (0xFF<<16)
+#define LCD_COLORKEY_CKG (0xFF<<8)
+#define LCD_COLORKEY_CKB (0xFF<<0)
+#define LCD_COLORKEY_CKR_N(N) ((N)<<16)
+#define LCD_COLORKEY_CKG_N(N) ((N)<<8)
+#define LCD_COLORKEY_CKB_N(N) ((N)<<0)
+
+/* lcd_colorkeymsk */
+#define LCD_COLORKEYMSK_CKMR (0xFF<<16)
+#define LCD_COLORKEYMSK_CKMG (0xFF<<8)
+#define LCD_COLORKEYMSK_CKMB (0xFF<<0)
+#define LCD_COLORKEYMSK_CKMR_N(N) ((N)<<16)
+#define LCD_COLORKEYMSK_CKMG_N(N) ((N)<<8)
+#define LCD_COLORKEYMSK_CKMB_N(N) ((N)<<0)
+
+/* lcd windows control 0 */
+#define LCD_WINCTRL0_OX (0x07FF<<21)
+#define LCD_WINCTRL0_OY (0x07FF<<10)
+#define LCD_WINCTRL0_A (0x00FF<<2)
+#define LCD_WINCTRL0_AEN (1<<1)
+#define LCD_WINCTRL0_OX_N(N) ((N)<<21)
+#define LCD_WINCTRL0_OY_N(N) ((N)<<10)
+#define LCD_WINCTRL0_A_N(N) ((N)<<2)
+
+/* lcd windows control 1 */
+#define LCD_WINCTRL1_PRI (3<<30)
+#define LCD_WINCTRL1_PIPE (1<<29)
+#define LCD_WINCTRL1_FRM (0xF<<25)
+#define LCD_WINCTRL1_CCO (1<<24)
+#define LCD_WINCTRL1_PO (3<<22)
+#define LCD_WINCTRL1_SZX (0x07FF<<11)
+#define LCD_WINCTRL1_SZY (0x07FF<<0)
+#define LCD_WINCTRL1_FRM_1BPP (0<<25)
+#define LCD_WINCTRL1_FRM_2BPP (1<<25)
+#define LCD_WINCTRL1_FRM_4BPP (2<<25)
+#define LCD_WINCTRL1_FRM_8BPP (3<<25)
+#define LCD_WINCTRL1_FRM_12BPP (4<<25)
+#define LCD_WINCTRL1_FRM_16BPP655 (5<<25)
+#define LCD_WINCTRL1_FRM_16BPP565 (6<<25)
+#define LCD_WINCTRL1_FRM_16BPP556 (7<<25)
+#define LCD_WINCTRL1_FRM_16BPPI1555 (8<<25)
+#define LCD_WINCTRL1_FRM_16BPPI5551 (9<<25)
+#define LCD_WINCTRL1_FRM_16BPPA1555 (10<<25)
+#define LCD_WINCTRL1_FRM_16BPPA5551 (11<<25)
+#define LCD_WINCTRL1_FRM_24BPP (12<<25)
+#define LCD_WINCTRL1_FRM_32BPP (13<<25)
+#define LCD_WINCTRL1_PRI_N(N) ((N)<<30)
+#define LCD_WINCTRL1_PO_00 (0<<22)
+#define LCD_WINCTRL1_PO_01 (1<<22)
+#define LCD_WINCTRL1_PO_10 (2<<22)
+#define LCD_WINCTRL1_PO_11 (3<<22)
+#define LCD_WINCTRL1_SZX_N(N) ((N-1)<<11)
+#define LCD_WINCTRL1_SZY_N(N) ((N-1)<<0)
+
+/* lcd windows control 2 */
+#define LCD_WINCTRL2_CKMODE (3<<24)
+#define LCD_WINCTRL2_DBM (1<<23)
+#define LCD_WINCTRL2_RAM (3<<21)
+#define LCD_WINCTRL2_BX (0x1FFF<<8)
+#define LCD_WINCTRL2_SCX (0xF<<4)
+#define LCD_WINCTRL2_SCY (0xF<<0)
+#define LCD_WINCTRL2_CKMODE_00 (0<<24)
+#define LCD_WINCTRL2_CKMODE_01 (1<<24)
+#define LCD_WINCTRL2_CKMODE_10 (2<<24)
+#define LCD_WINCTRL2_CKMODE_11 (3<<24)
+#define LCD_WINCTRL2_RAM_NONE (0<<21)
+#define LCD_WINCTRL2_RAM_PALETTE (1<<21)
+#define LCD_WINCTRL2_RAM_GAMMA (2<<21)
+#define LCD_WINCTRL2_RAM_BUFFER (3<<21)
+#define LCD_WINCTRL2_BX_N(N) ((N)<<8)
+#define LCD_WINCTRL2_SCX_1 (0<<4)
+#define LCD_WINCTRL2_SCX_2 (1<<4)
+#define LCD_WINCTRL2_SCX_4 (2<<4)
+#define LCD_WINCTRL2_SCY_1 (0<<0)
+#define LCD_WINCTRL2_SCY_2 (1<<0)
+#define LCD_WINCTRL2_SCY_4 (2<<0)
+
+/* lcd windows buffer control */
+#define LCD_WINBUFCTRL_DB (1<<1)
+#define LCD_WINBUFCTRL_DBN (1<<0)
+
+/* lcd_intstatus, lcd_intenable */
+#define LCD_INT_IFO (0xF<<14)
+#define LCD_INT_IFU (0xF<<10)
+#define LCD_INT_OFO (1<<9)
+#define LCD_INT_OFU (1<<8)
+#define LCD_INT_WAIT (1<<3)
+#define LCD_INT_SD (1<<2)
+#define LCD_INT_SA (1<<1)
+#define LCD_INT_SS (1<<0)
+
+/* lcd_horztiming */
+#define LCD_HORZTIMING_HND2 (0x1FF<<18)
+#define LCD_HORZTIMING_HND1 (0x1FF<<9)
+#define LCD_HORZTIMING_HPW (0x1FF<<0)
+#define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18)
+#define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9)
+#define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<0)
+
+/* lcd_verttiming */
+#define LCD_VERTTIMING_VND2 (0x1FF<<18)
+#define LCD_VERTTIMING_VND1 (0x1FF<<9)
+#define LCD_VERTTIMING_VPW (0x1FF<<0)
+#define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18)
+#define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9)
+#define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<0)
+
+/* lcd_clkcontrol */
+#define LCD_CLKCONTROL_EXT (1<<22)
+#define LCD_CLKCONTROL_DELAY (3<<20)
+#define LCD_CLKCONTROL_CDD (1<<19)
+#define LCD_CLKCONTROL_IB (1<<18)
+#define LCD_CLKCONTROL_IC (1<<17)
+#define LCD_CLKCONTROL_IH (1<<16)
+#define LCD_CLKCONTROL_IV (1<<15)
+#define LCD_CLKCONTROL_BF (0x1F<<10)
+#define LCD_CLKCONTROL_PCD (0x3FF<<0)
+#define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10)
+#define LCD_CLKCONTROL_PCD_N(N) ((N)<<0)
+
+/* lcd_pwmdiv */
+#define LCD_PWMDIV_EN (1<<31)
+#define LCD_PWMDIV_PWMDIV (0x1FFFF<<0)
+#define LCD_PWMDIV_PWMDIV_N(N) ((N)<<0)
+
+/* lcd_pwmhi */
+#define LCD_PWMHI_PWMHI1 (0xFFFF<<16)
+#define LCD_PWMHI_PWMHI0 (0xFFFF<<0)
+#define LCD_PWMHI_PWMHI1_N(N) ((N)<<16)
+#define LCD_PWMHI_PWMHI0_N(N) ((N)<<0)
+
+/* lcd_hwccon */
+#define LCD_HWCCON_EN (1<<0)
+
+/* lcd_cursorpos */
+#define LCD_CURSORPOS_HWCXOFF (0x1F<<27)
+#define LCD_CURSORPOS_HWCXPOS (0x07FF<<16)
+#define LCD_CURSORPOS_HWCYOFF (0x1F<<11)
+#define LCD_CURSORPOS_HWCYPOS (0x07FF<<0)
+#define LCD_CURSORPOS_HWCXOFF_N(N) ((N)<<27)
+#define LCD_CURSORPOS_HWCXPOS_N(N) ((N)<<16)
+#define LCD_CURSORPOS_HWCYOFF_N(N) ((N)<<11)
+#define LCD_CURSORPOS_HWCYPOS_N(N) ((N)<<0)
+
+/* lcd_cursorcolor */
+#define LCD_CURSORCOLOR_HWCA (0xFF<<24)
+#define LCD_CURSORCOLOR_HWCR (0xFF<<16)
+#define LCD_CURSORCOLOR_HWCG (0xFF<<8)
+#define LCD_CURSORCOLOR_HWCB (0xFF<<0)
+#define LCD_CURSORCOLOR_HWCA_N(N) ((N)<<24)
+#define LCD_CURSORCOLOR_HWCR_N(N) ((N)<<16)
+#define LCD_CURSORCOLOR_HWCG_N(N) ((N)<<8)
+#define LCD_CURSORCOLOR_HWCB_N(N) ((N)<<0)
+
+/* lcd_fifoctrl */
+#define LCD_FIFOCTRL_F3IF (1<<29)
+#define LCD_FIFOCTRL_F3REQ (0x1F<<24)
+#define LCD_FIFOCTRL_F2IF (1<<29)
+#define LCD_FIFOCTRL_F2REQ (0x1F<<16)
+#define LCD_FIFOCTRL_F1IF (1<<29)
+#define LCD_FIFOCTRL_F1REQ (0x1F<<8)
+#define LCD_FIFOCTRL_F0IF (1<<29)
+#define LCD_FIFOCTRL_F0REQ (0x1F<<0)
+#define LCD_FIFOCTRL_F3REQ_N(N) ((N-1)<<24)
+#define LCD_FIFOCTRL_F2REQ_N(N) ((N-1)<<16)
+#define LCD_FIFOCTRL_F1REQ_N(N) ((N-1)<<8)
+#define LCD_FIFOCTRL_F0REQ_N(N) ((N-1)<<0)
+
+/* lcd_outmask */
+#define LCD_OUTMASK_MASK (0x00FFFFFF)
+
+/********************************************************************/
+#endif /* _AU1200LCD_H */
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 9d996f2c10d..b895eaaa73f 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -43,11 +43,11 @@ config LCD_DEVICE
default y
config BACKLIGHT_CORGI
- tristate "Sharp Corgi Backlight Driver (SL-C7xx Series)"
+ tristate "Sharp Corgi Backlight Driver (SL Series)"
depends on BACKLIGHT_DEVICE && PXA_SHARPSL
default y
help
- If you have a Sharp Zaurus SL-C7xx, say y to enable the
+ If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the
backlight driver.
config BACKLIGHT_HP680
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 151fda8dded..27597c576ef 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -16,14 +16,12 @@
static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
{
- int rc;
+ int rc = -ENXIO;
struct backlight_device *bd = to_backlight_device(cdev);
down(&bd->sem);
- if (likely(bd->props && bd->props->get_power))
- rc = sprintf(buf, "%d\n", bd->props->get_power(bd));
- else
- rc = -ENXIO;
+ if (likely(bd->props))
+ rc = sprintf(buf, "%d\n", bd->props->power);
up(&bd->sem);
return rc;
@@ -31,21 +29,25 @@ static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count)
{
- int rc, power;
+ int rc = -ENXIO;
char *endp;
struct backlight_device *bd = to_backlight_device(cdev);
+ int power = simple_strtoul(buf, &endp, 0);
+ size_t size = endp - buf;
- power = simple_strtoul(buf, &endp, 0);
- if (*endp && !isspace(*endp))
+ if (*endp && isspace(*endp))
+ size++;
+ if (size != count)
return -EINVAL;
down(&bd->sem);
- if (likely(bd->props && bd->props->set_power)) {
+ if (likely(bd->props)) {
pr_debug("backlight: set power to %d\n", power);
- bd->props->set_power(bd, power);
+ bd->props->power = power;
+ if (likely(bd->props->update_status))
+ bd->props->update_status(bd);
rc = count;
- } else
- rc = -ENXIO;
+ }
up(&bd->sem);
return rc;
@@ -53,14 +55,12 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf,
static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf)
{
- int rc;
+ int rc = -ENXIO;
struct backlight_device *bd = to_backlight_device(cdev);
down(&bd->sem);
- if (likely(bd->props && bd->props->get_brightness))
- rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd));
- else
- rc = -ENXIO;
+ if (likely(bd->props))
+ rc = sprintf(buf, "%d\n", bd->props->brightness);
up(&bd->sem);
return rc;
@@ -68,21 +68,30 @@ static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf)
static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count)
{
- int rc, brightness;
+ int rc = -ENXIO;
char *endp;
struct backlight_device *bd = to_backlight_device(cdev);
+ int brightness = simple_strtoul(buf, &endp, 0);
+ size_t size = endp - buf;
- brightness = simple_strtoul(buf, &endp, 0);
- if (*endp && !isspace(*endp))
+ if (*endp && isspace(*endp))
+ size++;
+ if (size != count)
return -EINVAL;
down(&bd->sem);
- if (likely(bd->props && bd->props->set_brightness)) {
- pr_debug("backlight: set brightness to %d\n", brightness);
- bd->props->set_brightness(bd, brightness);
- rc = count;
- } else
- rc = -ENXIO;
+ if (likely(bd->props)) {
+ if (brightness > bd->props->max_brightness)
+ rc = -EINVAL;
+ else {
+ pr_debug("backlight: set brightness to %d\n",
+ brightness);
+ bd->props->brightness = brightness;
+ if (likely(bd->props->update_status))
+ bd->props->update_status(bd);
+ rc = count;
+ }
+ }
up(&bd->sem);
return rc;
@@ -90,14 +99,26 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char
static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf)
{
- int rc;
+ int rc = -ENXIO;
struct backlight_device *bd = to_backlight_device(cdev);
down(&bd->sem);
if (likely(bd->props))
rc = sprintf(buf, "%d\n", bd->props->max_brightness);
- else
- rc = -ENXIO;
+ up(&bd->sem);
+
+ return rc;
+}
+
+static ssize_t backlight_show_actual_brightness(struct class_device *cdev,
+ char *buf)
+{
+ int rc = -ENXIO;
+ struct backlight_device *bd = to_backlight_device(cdev);
+
+ down(&bd->sem);
+ if (likely(bd->props && bd->props->get_brightness))
+ rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd));
up(&bd->sem);
return rc;
@@ -123,7 +144,10 @@ static struct class backlight_class = {
static struct class_device_attribute bl_class_device_attributes[] = {
DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power),
- DECLARE_ATTR(brightness, 0644, backlight_show_brightness, backlight_store_brightness),
+ DECLARE_ATTR(brightness, 0644, backlight_show_brightness,
+ backlight_store_brightness),
+ DECLARE_ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
+ NULL),
DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),
};
@@ -144,8 +168,12 @@ static int fb_notifier_callback(struct notifier_block *self,
bd = container_of(self, struct backlight_device, fb_notif);
down(&bd->sem);
if (bd->props)
- if (!bd->props->check_fb || bd->props->check_fb(evdata->info))
- bd->props->set_power(bd, *(int *)evdata->data);
+ if (!bd->props->check_fb ||
+ bd->props->check_fb(evdata->info)) {
+ bd->props->fb_blank = *(int *)evdata->data;
+ if (likely(bd->props && bd->props->update_status))
+ bd->props->update_status(bd);
+ }
up(&bd->sem);
return 0;
}
@@ -231,6 +259,12 @@ void backlight_device_unregister(struct backlight_device *bd)
&bl_class_device_attributes[i]);
down(&bd->sem);
+ if (likely(bd->props && bd->props->update_status)) {
+ bd->props->brightness = 0;
+ bd->props->power = 0;
+ bd->props->update_status(bd);
+ }
+
bd->props = NULL;
up(&bd->sem);
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index d0aaf450e8c..2ebbfd95145 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -1,7 +1,7 @@
/*
- * Backlight Driver for Sharp Corgi
+ * Backlight Driver for Sharp Zaurus Handhelds (various models)
*
- * Copyright (c) 2004-2005 Richard Purdie
+ * Copyright (c) 2004-2006 Richard Purdie
*
* Based on Sharp's 2.4 Backlight Driver
*
@@ -15,80 +15,63 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <linux/fb.h>
#include <linux/backlight.h>
-
#include <asm/arch/sharpsl.h>
#include <asm/hardware/sharpsl_pm.h>
-#define CORGI_DEFAULT_INTENSITY 0x1f
-#define CORGI_LIMIT_MASK 0x0b
-
-static int corgibl_powermode = FB_BLANK_UNBLANK;
-static int current_intensity = 0;
-static int corgibl_limit = 0;
-static void (*corgibl_mach_set_intensity)(int intensity);
-static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
+static int corgibl_intensity;
+static DEFINE_MUTEX(bl_mutex);
static struct backlight_properties corgibl_data;
+static struct backlight_device *corgi_backlight_device;
+static struct corgibl_machinfo *bl_machinfo;
-static void corgibl_send_intensity(int intensity)
+static unsigned long corgibl_flags;
+#define CORGIBL_SUSPENDED 0x01
+#define CORGIBL_BATTLOW 0x02
+
+static int corgibl_send_intensity(struct backlight_device *bd)
{
- unsigned long flags;
void (*corgi_kick_batt)(void);
+ int intensity = bd->props->brightness;
- if (corgibl_powermode != FB_BLANK_UNBLANK) {
+ if (bd->props->power != FB_BLANK_UNBLANK)
intensity = 0;
- } else {
- if (corgibl_limit)
- intensity &= CORGI_LIMIT_MASK;
- }
-
- spin_lock_irqsave(&bl_lock, flags);
+ if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+ intensity = 0;
+ if (corgibl_flags & CORGIBL_SUSPENDED)
+ intensity = 0;
+ if (corgibl_flags & CORGIBL_BATTLOW)
+ intensity &= bl_machinfo->limit_mask;
- corgibl_mach_set_intensity(intensity);
+ mutex_lock(&bl_mutex);
+ bl_machinfo->set_bl_intensity(intensity);
+ mutex_unlock(&bl_mutex);
- spin_unlock_irqrestore(&bl_lock, flags);
+ corgibl_intensity = intensity;
corgi_kick_batt = symbol_get(sharpsl_battery_kick);
if (corgi_kick_batt) {
corgi_kick_batt();
symbol_put(sharpsl_battery_kick);
}
-}
-static void corgibl_blank(int blank)
-{
- switch(blank) {
-
- case FB_BLANK_NORMAL:
- case FB_BLANK_VSYNC_SUSPEND:
- case FB_BLANK_HSYNC_SUSPEND:
- case FB_BLANK_POWERDOWN:
- if (corgibl_powermode == FB_BLANK_UNBLANK) {
- corgibl_send_intensity(0);
- corgibl_powermode = blank;
- }
- break;
- case FB_BLANK_UNBLANK:
- if (corgibl_powermode != FB_BLANK_UNBLANK) {
- corgibl_powermode = blank;
- corgibl_send_intensity(current_intensity);
- }
- break;
- }
+ return 0;
}
#ifdef CONFIG_PM
static int corgibl_suspend(struct platform_device *dev, pm_message_t state)
{
- corgibl_blank(FB_BLANK_POWERDOWN);
+ corgibl_flags |= CORGIBL_SUSPENDED;
+ corgibl_send_intensity(corgi_backlight_device);
return 0;
}
static int corgibl_resume(struct platform_device *dev)
{
- corgibl_blank(FB_BLANK_UNBLANK);
+ corgibl_flags &= ~CORGIBL_SUSPENDED;
+ corgibl_send_intensity(corgi_backlight_device);
return 0;
}
#else
@@ -96,68 +79,55 @@ static int corgibl_resume(struct platform_device *dev)
#define corgibl_resume NULL
#endif
-
-static int corgibl_set_power(struct backlight_device *bd, int state)
-{
- corgibl_blank(state);
- return 0;
-}
-
-static int corgibl_get_power(struct backlight_device *bd)
+static int corgibl_get_intensity(struct backlight_device *bd)
{
- return corgibl_powermode;
+ return corgibl_intensity;
}
-static int corgibl_set_intensity(struct backlight_device *bd, int intensity)
+static int corgibl_set_intensity(struct backlight_device *bd)
{
- if (intensity > corgibl_data.max_brightness)
- intensity = corgibl_data.max_brightness;
- corgibl_send_intensity(intensity);
- current_intensity=intensity;
+ corgibl_send_intensity(corgi_backlight_device);
return 0;
}
-static int corgibl_get_intensity(struct backlight_device *bd)
-{
- return current_intensity;
-}
-
/*
* Called when the battery is low to limit the backlight intensity.
* If limit==0 clear any limit, otherwise limit the intensity
*/
void corgibl_limit_intensity(int limit)
{
- corgibl_limit = (limit ? 1 : 0);
- corgibl_send_intensity(current_intensity);
+ if (limit)
+ corgibl_flags |= CORGIBL_BATTLOW;
+ else
+ corgibl_flags &= ~CORGIBL_BATTLOW;
+ corgibl_send_intensity(corgi_backlight_device);
}
EXPORT_SYMBOL(corgibl_limit_intensity);
static struct backlight_properties corgibl_data = {
- .owner = THIS_MODULE,
- .get_power = corgibl_get_power,
- .set_power = corgibl_set_power,
+ .owner = THIS_MODULE,
.get_brightness = corgibl_get_intensity,
- .set_brightness = corgibl_set_intensity,
+ .update_status = corgibl_set_intensity,
};
-static struct backlight_device *corgi_backlight_device;
-
static int __init corgibl_probe(struct platform_device *pdev)
{
struct corgibl_machinfo *machinfo = pdev->dev.platform_data;
+ bl_machinfo = machinfo;
corgibl_data.max_brightness = machinfo->max_intensity;
- corgibl_mach_set_intensity = machinfo->set_bl_intensity;
+ if (!machinfo->limit_mask)
+ machinfo->limit_mask = -1;
corgi_backlight_device = backlight_device_register ("corgi-bl",
NULL, &corgibl_data);
if (IS_ERR (corgi_backlight_device))
return PTR_ERR (corgi_backlight_device);
- corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY);
- corgibl_limit_intensity(0);
+ corgibl_data.power = FB_BLANK_UNBLANK;
+ corgibl_data.brightness = machinfo->default_intensity;
+ corgibl_send_intensity(corgi_backlight_device);
printk("Corgi Backlight Driver Initialized.\n");
return 0;
@@ -167,8 +137,6 @@ static int corgibl_remove(struct platform_device *dev)
{
backlight_device_unregister(corgi_backlight_device);
- corgibl_set_intensity(NULL, 0);
-
printk("Corgi Backlight Driver Unloaded\n");
return 0;
}
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 95da4c9ed1f..a71e984c93d 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -13,7 +13,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/fb.h>
#include <linux/backlight.h>
@@ -25,66 +25,58 @@
#define HP680_MAX_INTENSITY 255
#define HP680_DEFAULT_INTENSITY 10
-static int hp680bl_powermode = FB_BLANK_UNBLANK;
+static int hp680bl_suspended;
static int current_intensity = 0;
static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
+static struct backlight_device *hp680_backlight_device;
-static void hp680bl_send_intensity(int intensity)
+static void hp680bl_send_intensity(struct backlight_device *bd)
{
unsigned long flags;
+ u16 v;
+ int intensity = bd->props->brightness;
- if (hp680bl_powermode != FB_BLANK_UNBLANK)
+ if (bd->props->power != FB_BLANK_UNBLANK)
+ intensity = 0;
+ if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+ intensity = 0;
+ if (hp680bl_suspended)
intensity = 0;
spin_lock_irqsave(&bl_lock, flags);
- sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
+ if (intensity && current_intensity == 0) {
+ sh_dac_enable(DAC_LCD_BRIGHTNESS);
+ v = inw(HD64461_GPBDR);
+ v &= ~HD64461_GPBDR_LCDOFF;
+ outw(v, HD64461_GPBDR);
+ sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
+ } else if (intensity == 0 && current_intensity != 0) {
+ sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
+ sh_dac_disable(DAC_LCD_BRIGHTNESS);
+ v = inw(HD64461_GPBDR);
+ v |= HD64461_GPBDR_LCDOFF;
+ outw(v, HD64461_GPBDR);
+ } else if (intensity) {
+ sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
+ }
spin_unlock_irqrestore(&bl_lock, flags);
-}
-static void hp680bl_blank(int blank)
-{
- u16 v;
-
- switch(blank) {
-
- case FB_BLANK_NORMAL:
- case FB_BLANK_VSYNC_SUSPEND:
- case FB_BLANK_HSYNC_SUSPEND:
- case FB_BLANK_POWERDOWN:
- if (hp680bl_powermode == FB_BLANK_UNBLANK) {
- hp680bl_send_intensity(0);
- hp680bl_powermode = blank;
- sh_dac_disable(DAC_LCD_BRIGHTNESS);
- v = inw(HD64461_GPBDR);
- v |= HD64461_GPBDR_LCDOFF;
- outw(v, HD64461_GPBDR);
- }
- break;
- case FB_BLANK_UNBLANK:
- if (hp680bl_powermode != FB_BLANK_UNBLANK) {
- sh_dac_enable(DAC_LCD_BRIGHTNESS);
- v = inw(HD64461_GPBDR);
- v &= ~HD64461_GPBDR_LCDOFF;
- outw(v, HD64461_GPBDR);
- hp680bl_powermode = blank;
- hp680bl_send_intensity(current_intensity);
- }
- break;
- }
+ current_intensity = intensity;
}
+
#ifdef CONFIG_PM
-static int hp680bl_suspend(struct device *dev, pm_message_t state, u32 level)
+static int hp680bl_suspend(struct platform_device *dev, pm_message_t state)
{
- if (level == SUSPEND_POWER_DOWN)
- hp680bl_blank(FB_BLANK_POWERDOWN);
+ hp680bl_suspended = 1;
+ hp680bl_send_intensity(hp680_backlight_device);
return 0;
}
-static int hp680bl_resume(struct device *dev, u32 level)
+static int hp680bl_resume(struct platform_device *dev)
{
- if (level == RESUME_POWER_ON)
- hp680bl_blank(FB_BLANK_UNBLANK);
+ hp680bl_suspended = 0;
+ hp680bl_send_intensity(hp680_backlight_device);
return 0;
}
#else
@@ -92,24 +84,9 @@ static int hp680bl_resume(struct device *dev, u32 level)
#define hp680bl_resume NULL
#endif
-
-static int hp680bl_set_power(struct backlight_device *bd, int state)
+static int hp680bl_set_intensity(struct backlight_device *bd)
{
- hp680bl_blank(state);
- return 0;
-}
-
-static int hp680bl_get_power(struct backlight_device *bd)
-{
- return hp680bl_powermode;
-}
-
-static int hp680bl_set_intensity(struct backlight_device *bd, int intensity)
-{
- if (intensity > HP680_MAX_INTENSITY)
- intensity = HP680_MAX_INTENSITY;
- hp680bl_send_intensity(intensity);
- current_intensity = intensity;
+ hp680bl_send_intensity(bd);
return 0;
}
@@ -120,65 +97,67 @@ static int hp680bl_get_intensity(struct backlight_device *bd)
static struct backlight_properties hp680bl_data = {
.owner = THIS_MODULE,
- .get_power = hp680bl_get_power,
- .set_power = hp680bl_set_power,
.max_brightness = HP680_MAX_INTENSITY,
.get_brightness = hp680bl_get_intensity,
- .set_brightness = hp680bl_set_intensity,
+ .update_status = hp680bl_set_intensity,
};
-static struct backlight_device *hp680_backlight_device;
-
-static int __init hp680bl_probe(struct device *dev)
+static int __init hp680bl_probe(struct platform_device *dev)
{
hp680_backlight_device = backlight_device_register ("hp680-bl",
NULL, &hp680bl_data);
if (IS_ERR (hp680_backlight_device))
return PTR_ERR (hp680_backlight_device);
- hp680bl_set_intensity(NULL, HP680_DEFAULT_INTENSITY);
+ hp680_backlight_device->props->brightness = HP680_DEFAULT_INTENSITY;
+ hp680bl_send_intensity(hp680_backlight_device);
return 0;
}
-static int hp680bl_remove(struct device *dev)
+static int hp680bl_remove(struct platform_device *dev)
{
backlight_device_unregister(hp680_backlight_device);
return 0;
}
-static struct device_driver hp680bl_driver = {
- .name = "hp680-bl",
- .bus = &platform_bus_type,
+static struct platform_driver hp680bl_driver = {
.probe = hp680bl_probe,
.remove = hp680bl_remove,
.suspend = hp680bl_suspend,
.resume = hp680bl_resume,
+ .driver = {
+ .name = "hp680-bl",
+ },
};
-static struct platform_device hp680bl_device = {
- .name = "hp680-bl",
- .id = -1,
-};
+static struct platform_device *hp680bl_device;
static int __init hp680bl_init(void)
{
int ret;
- ret=driver_register(&hp680bl_driver);
+ ret = platform_driver_register(&hp680bl_driver);
if (!ret) {
- ret = platform_device_register(&hp680bl_device);
- if (ret)
- driver_unregister(&hp680bl_driver);
+ hp680bl_device = platform_device_alloc("hp680-bl", -1);
+ if (!hp680bl_device)
+ return -ENOMEM;
+
+ ret = platform_device_add(hp680bl_device);
+
+ if (ret) {
+ platform_device_put(hp680bl_device);
+ platform_driver_unregister(&hp680bl_driver);
+ }
}
return ret;
}
static void __exit hp680bl_exit(void)
{
- platform_device_unregister(&hp680bl_device);
- driver_unregister(&hp680bl_driver);
+ platform_device_unregister(hp680bl_device);
+ platform_driver_unregister(&hp680bl_driver);
}
module_init(hp680bl_init);
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 86908a60c63..bc8ab005a3f 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -31,12 +31,15 @@ static ssize_t lcd_show_power(struct class_device *cdev, char *buf)
static ssize_t lcd_store_power(struct class_device *cdev, const char *buf, size_t count)
{
- int rc, power;
+ int rc = -ENXIO;
char *endp;
struct lcd_device *ld = to_lcd_device(cdev);
+ int power = simple_strtoul(buf, &endp, 0);
+ size_t size = endp - buf;
- power = simple_strtoul(buf, &endp, 0);
- if (*endp && !isspace(*endp))
+ if (*endp && isspace(*endp))
+ size++;
+ if (size != count)
return -EINVAL;
down(&ld->sem);
@@ -44,8 +47,7 @@ static ssize_t lcd_store_power(struct class_device *cdev, const char *buf, size_
pr_debug("lcd: set power to %d\n", power);
ld->props->set_power(ld, power);
rc = count;
- } else
- rc = -ENXIO;
+ }
up(&ld->sem);
return rc;
@@ -53,14 +55,12 @@ static ssize_t lcd_store_power(struct class_device *cdev, const char *buf, size_
static ssize_t lcd_show_contrast(struct class_device *cdev, char *buf)
{
- int rc;
+ int rc = -ENXIO;
struct lcd_device *ld = to_lcd_device(cdev);
down(&ld->sem);
if (likely(ld->props && ld->props->get_contrast))
rc = sprintf(buf, "%d\n", ld->props->get_contrast(ld));
- else
- rc = -ENXIO;
up(&ld->sem);
return rc;
@@ -68,12 +68,15 @@ static ssize_t lcd_show_contrast(struct class_device *cdev, char *buf)
static ssize_t lcd_store_contrast(struct class_device *cdev, const char *buf, size_t count)
{
- int rc, contrast;
+ int rc = -ENXIO;
char *endp;
struct lcd_device *ld = to_lcd_device(cdev);
+ int contrast = simple_strtoul(buf, &endp, 0);
+ size_t size = endp - buf;
- contrast = simple_strtoul(buf, &endp, 0);
- if (*endp && !isspace(*endp))
+ if (*endp && isspace(*endp))
+ size++;
+ if (size != count)
return -EINVAL;
down(&ld->sem);
@@ -81,8 +84,7 @@ static ssize_t lcd_store_contrast(struct class_device *cdev, const char *buf, si
pr_debug("lcd: set contrast to %d\n", contrast);
ld->props->set_contrast(ld, contrast);
rc = count;
- } else
- rc = -ENXIO;
+ }
up(&ld->sem);
return rc;
@@ -90,14 +92,12 @@ static ssize_t lcd_store_contrast(struct class_device *cdev, const char *buf, si
static ssize_t lcd_show_max_contrast(struct class_device *cdev, char *buf)
{
- int rc;
+ int rc = -ENXIO;
struct lcd_device *ld = to_lcd_device(cdev);
down(&ld->sem);
if (likely(ld->props))
rc = sprintf(buf, "%d\n", ld->props->max_contrast);
- else
- rc = -ENXIO;
up(&ld->sem);
return rc;
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
index 910e2338a27..8ba6152db2f 100644
--- a/drivers/video/cfbimgblt.c
+++ b/drivers/video/cfbimgblt.c
@@ -169,7 +169,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
while (j--) {
l--;
- color = (*s & 1 << (FB_BIT_NR(l))) ? fgcolor : bgcolor;
+ color = (*s & (1 << l)) ? fgcolor : bgcolor;
val |= FB_SHIFT_HIGH(color, shift);
/* Did the bitshift spill bits to the next long? */
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index bc061d4ec78..72ff6bf75e5 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -178,8 +178,6 @@ struct chips_init_reg {
unsigned char data;
};
-#define N_ELTS(x) (sizeof(x) / sizeof(x[0]))
-
static struct chips_init_reg chips_init_sr[] = {
{ 0x00, 0x03 },
{ 0x01, 0x01 },
@@ -287,18 +285,18 @@ static void __init chips_hw_init(void)
{
int i;
- for (i = 0; i < N_ELTS(chips_init_xr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i)
write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
outb(0x29, 0x3c2); /* set misc output reg */
- for (i = 0; i < N_ELTS(chips_init_sr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i)
write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
- for (i = 0; i < N_ELTS(chips_init_gr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i)
write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
- for (i = 0; i < N_ELTS(chips_init_ar); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i)
write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
- for (i = 0; i < N_ELTS(chips_init_cr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i)
write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
- for (i = 0; i < N_ELTS(chips_init_fr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i)
write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
}
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 66d6f2f0a21..1103010af54 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -60,8 +60,8 @@
#include <asm/amigahw.h>
#endif
#ifdef CONFIG_PPC_PREP
-#include <asm/processor.h>
-#define isPReP (_machine == _MACH_prep)
+#include <asm/machdep.h>
+#define isPReP (machine_is(prep))
#else
#define isPReP 0
#endif
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 6ee449858a5..4444bef68fb 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -26,6 +26,30 @@ config VGA_CONSOLE
# fi
# fi
+config VGACON_SOFT_SCROLLBACK
+ bool "Enable Scrollback Buffer in System RAM"
+ depends on VGA_CONSOLE
+ default n
+ help
+ The scrollback buffer of the standard VGA console is located in
+ the VGA RAM. The size of this RAM is fixed and is quite small.
+ If you require a larger scrollback buffer, this can be placed in
+ System RAM which is dynamically allocated during intialization.
+ Placing the scrollback buffer in System RAM will slightly slow
+ down the console.
+
+ If you want this feature, say 'Y' here and enter the amount of
+ RAM to allocate for this buffer. If unsure, say 'N'.
+
+config VGACON_SOFT_SCROLLBACK_SIZE
+ int "Scrollback Buffer Size (in KB)"
+ depends on VGACON_SOFT_SCROLLBACK
+ default "64"
+ help
+ Enter the amount of System RAM to allocate for the scrollback
+ buffer. Each 64KB will give you approximately 16 80x25
+ screenfuls of scrollback buffer
+
config VIDEO_SELECT
bool "Video mode selection support"
depends on X86 && VGA_CONSOLE
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 041d0698786..47ba1a79adc 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -466,7 +466,7 @@ static int __init fb_console_setup(char *this_opt)
int i, j;
if (!this_opt || !*this_opt)
- return 0;
+ return 1;
while ((options = strsep(&this_opt, ",")) != NULL) {
if (!strncmp(options, "font:", 5))
@@ -481,10 +481,10 @@ static int __init fb_console_setup(char *this_opt)
options++;
}
if (*options != ',')
- return 0;
+ return 1;
options++;
} else
- return 0;
+ return 1;
}
if (!strncmp(options, "map:", 4)) {
@@ -496,7 +496,7 @@ static int __init fb_console_setup(char *this_opt)
con2fb_map_boot[i] =
(options[j++]-'0') % FB_MAX;
}
- return 0;
+ return 1;
}
if (!strncmp(options, "vc:", 3)) {
@@ -518,7 +518,7 @@ static int __init fb_console_setup(char *this_opt)
rotate = 0;
}
}
- return 0;
+ return 1;
}
__setup("fbcon=", fb_console_setup);
@@ -1142,6 +1142,7 @@ static void fbcon_init(struct vc_data *vc, int init)
set_blitting_type(vc, info);
}
+ ops->p = &fb_display[fg_console];
}
static void fbcon_deinit(struct vc_data *vc)
@@ -1744,7 +1745,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
fbcon_redraw_move(vc, p, 0, t, count);
ypan_up_redraw(vc, t, count);
if (vc->vc_rows - b > 0)
- fbcon_redraw_move(vc, p, b - count,
+ fbcon_redraw_move(vc, p, b,
vc->vc_rows - b, b);
} else
fbcon_redraw_move(vc, p, t + count, b - t - count, t);
@@ -2630,7 +2631,7 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
scr_memcpyw((u16 *) q, (u16 *) p,
vc->vc_size_row);
}
- softback_in = p;
+ softback_in = softback_curr = p;
update_region(vc, vc->vc_origin,
logo_lines * vc->vc_cols);
}
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c
index 4fd07d9eca0..0cc1bfda76a 100644
--- a/drivers/video/console/fonts.c
+++ b/drivers/video/console/fonts.c
@@ -66,7 +66,7 @@ static const struct font_desc *fonts[] = {
#endif
};
-#define num_fonts (sizeof(fonts)/sizeof(*fonts))
+#define num_fonts ARRAY_SIZE(fonts)
#ifdef NO_FONTS
#error No fonts configured.
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index 762c7a59314..e99fe30e568 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -149,7 +149,7 @@ static inline void newport_clear_lines(int ystart, int yend, int ci)
newport_clear_screen(0, ystart, 1280 + 63, yend, ci);
}
-void newport_reset(void)
+static void newport_reset(void)
{
unsigned short treg;
int i;
@@ -193,7 +193,7 @@ void newport_reset(void)
* calculate the actual screen size by reading
* the video timing out of the VC2
*/
-void newport_get_screensize(void)
+static void newport_get_screensize(void)
{
int i, cols;
unsigned short ventry, treg;
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index 0339f5640a7..74ac2acaf72 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -275,7 +275,7 @@ static int __init sti_setup(char *str)
if (str)
strlcpy (default_sti_path, str, sizeof (default_sti_path));
- return 0;
+ return 1;
}
/* Assuming the machine has multiple STI consoles (=graphic cards) which
@@ -321,7 +321,7 @@ static int __init sti_font_setup(char *str)
i++;
}
- return 0;
+ return 1;
}
/* The optional linux kernel parameter "sti_font" defines which font
@@ -373,7 +373,7 @@ sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, unsigned int sti_mem_request)
glob_cfg->save_addr));
/* dump extended cfg */
- cfg = PTR_STI(glob_cfg->ext_ptr);
+ cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr);
DPRINTK(( KERN_INFO
"monitor %d\n"
"in friendly mode: %d\n"
@@ -453,25 +453,11 @@ sti_init_glob_cfg(struct sti_struct *sti,
sti->regions_phys[i] =
REGION_OFFSET_TO_PHYS(sti->regions[i], newhpa);
- /* remap virtually */
- /* FIXME: add BTLB support if btlb==1 */
len = sti->regions[i].region_desc.length * 4096;
-
-/* XXX: Enabling IOREMAP debugging causes a crash, so we must be passing
- * a virtual address to something expecting a physical address that doesn't
- * go through a readX macro */
-#if 0
- if (len)
- glob_cfg->region_ptrs[i] = (unsigned long) (
- sti->regions[i].region_desc.cache ?
- ioremap(sti->regions_phys[i], len) :
- ioremap_nocache(sti->regions_phys[i], len) );
-#else
if (len)
glob_cfg->region_ptrs[i] = sti->regions_phys[i];
-#endif
- DPRINTK(("region #%d: phys %08lx, virt %08x, len=%lukB, "
+ DPRINTK(("region #%d: phys %08lx, region_ptr %08x, len=%lukB, "
"btlb=%d, sysonly=%d, cache=%d, last=%d\n",
i, sti->regions_phys[i], glob_cfg->region_ptrs[i],
len/1024,
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 5a86978537d..d5a04b68c4d 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -93,7 +93,6 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
static unsigned long vgacon_uni_pagedir[2];
-
/* Description of the hardware situation */
static unsigned long vga_vram_base; /* Base of video memory */
static unsigned long vga_vram_end; /* End of video memory */
@@ -161,6 +160,201 @@ static inline void write_vga(unsigned char reg, unsigned int val)
spin_unlock_irqrestore(&vga_lock, flags);
}
+static inline void vga_set_mem_top(struct vc_data *c)
+{
+ write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
+}
+
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK
+#include <linux/bootmem.h>
+/* software scrollback */
+static void *vgacon_scrollback;
+static int vgacon_scrollback_tail;
+static int vgacon_scrollback_size;
+static int vgacon_scrollback_rows;
+static int vgacon_scrollback_cnt;
+static int vgacon_scrollback_cur;
+static int vgacon_scrollback_save;
+static int vgacon_scrollback_restore;
+
+static void vgacon_scrollback_init(int pitch)
+{
+ int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
+
+ if (vgacon_scrollback) {
+ vgacon_scrollback_cnt = 0;
+ vgacon_scrollback_tail = 0;
+ vgacon_scrollback_cur = 0;
+ vgacon_scrollback_rows = rows - 1;
+ vgacon_scrollback_size = rows * pitch;
+ }
+}
+
+static void __init vgacon_scrollback_startup(void)
+{
+ vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE
+ * 1024);
+ vgacon_scrollback_init(vga_video_num_columns * 2);
+}
+
+static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
+{
+ void *p;
+
+ if (!vgacon_scrollback_size || c->vc_num != fg_console)
+ return;
+
+ p = (void *) (c->vc_origin + t * c->vc_size_row);
+
+ while (count--) {
+ scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+ p, c->vc_size_row);
+ vgacon_scrollback_cnt++;
+ p += c->vc_size_row;
+ vgacon_scrollback_tail += c->vc_size_row;
+
+ if (vgacon_scrollback_tail >= vgacon_scrollback_size)
+ vgacon_scrollback_tail = 0;
+
+ if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
+ vgacon_scrollback_cnt = vgacon_scrollback_rows;
+
+ vgacon_scrollback_cur = vgacon_scrollback_cnt;
+ }
+}
+
+static void vgacon_restore_screen(struct vc_data *c)
+{
+ vgacon_scrollback_save = 0;
+
+ if (!vga_is_gfx && !vgacon_scrollback_restore) {
+ scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
+ c->vc_screenbuf_size > vga_vram_size ?
+ vga_vram_size : c->vc_screenbuf_size);
+ vgacon_scrollback_restore = 1;
+ vgacon_scrollback_cur = vgacon_scrollback_cnt;
+ }
+}
+
+static int vgacon_scrolldelta(struct vc_data *c, int lines)
+{
+ int start, end, count, soff, diff;
+ void *d, *s;
+
+ if (!lines) {
+ c->vc_visible_origin = c->vc_origin;
+ vga_set_mem_top(c);
+ return 1;
+ }
+
+ if (!vgacon_scrollback)
+ return 1;
+
+ if (!vgacon_scrollback_save) {
+ vgacon_cursor(c, CM_ERASE);
+ vgacon_save_screen(c);
+ vgacon_scrollback_save = 1;
+ }
+
+ vgacon_scrollback_restore = 0;
+ start = vgacon_scrollback_cur + lines;
+ end = start + abs(lines);
+
+ if (start < 0)
+ start = 0;
+
+ if (start > vgacon_scrollback_cnt)
+ start = vgacon_scrollback_cnt;
+
+ if (end < 0)
+ end = 0;
+
+ if (end > vgacon_scrollback_cnt)
+ end = vgacon_scrollback_cnt;
+
+ vgacon_scrollback_cur = start;
+ count = end - start;
+ soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *
+ c->vc_size_row);
+ soff -= count * c->vc_size_row;
+
+ if (soff < 0)
+ soff += vgacon_scrollback_size;
+
+ count = vgacon_scrollback_cnt - start;
+
+ if (count > c->vc_rows)
+ count = c->vc_rows;
+
+ diff = c->vc_rows - count;
+
+ d = (void *) c->vc_origin;
+ s = (void *) c->vc_screenbuf;
+
+ while (count--) {
+ scr_memcpyw(d, vgacon_scrollback + soff, c->vc_size_row);
+ d += c->vc_size_row;
+ soff += c->vc_size_row;
+
+ if (soff >= vgacon_scrollback_size)
+ soff = 0;
+ }
+
+ if (diff == c->vc_rows) {
+ vgacon_cursor(c, CM_MOVE);
+ } else {
+ while (diff--) {
+ scr_memcpyw(d, s, c->vc_size_row);
+ d += c->vc_size_row;
+ s += c->vc_size_row;
+ }
+ }
+
+ return 1;
+}
+#else
+#define vgacon_scrollback_startup(...) do { } while (0)
+#define vgacon_scrollback_init(...) do { } while (0)
+#define vgacon_scrollback_update(...) do { } while (0)
+
+static void vgacon_restore_screen(struct vc_data *c)
+{
+ if (c->vc_origin != c->vc_visible_origin)
+ vgacon_scrolldelta(c, 0);
+}
+
+static int vgacon_scrolldelta(struct vc_data *c, int lines)
+{
+ if (!lines) /* Turn scrollback off */
+ c->vc_visible_origin = c->vc_origin;
+ else {
+ int margin = c->vc_size_row * 4;
+ int ul, we, p, st;
+
+ if (vga_rolled_over >
+ (c->vc_scr_end - vga_vram_base) + margin) {
+ ul = c->vc_scr_end - vga_vram_base;
+ we = vga_rolled_over + c->vc_size_row;
+ } else {
+ ul = 0;
+ we = vga_vram_size;
+ }
+ p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
+ lines * c->vc_size_row;
+ st = (c->vc_origin - vga_vram_base - ul + we) % we;
+ if (st < 2 * margin)
+ margin = 0;
+ if (p < margin)
+ p = 0;
+ if (p > st - margin)
+ p = st;
+ c->vc_visible_origin = vga_vram_base + (p + ul) % we;
+ }
+ vga_set_mem_top(c);
+ return 1;
+}
+#endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
+
static const char __init *vgacon_startup(void)
{
const char *display_desc = NULL;
@@ -330,7 +524,7 @@ static const char __init *vgacon_startup(void)
vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH;
vgacon_yres = vga_scan_lines;
-
+ vgacon_scrollback_startup();
return display_desc;
}
@@ -357,11 +551,6 @@ static void vgacon_init(struct vc_data *c, int init)
con_set_default_unimap(c);
}
-static inline void vga_set_mem_top(struct vc_data *c)
-{
- write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
-}
-
static void vgacon_deinit(struct vc_data *c)
{
/* When closing the last console, reset video origin */
@@ -433,29 +622,37 @@ static void vgacon_set_cursor_size(int xpos, int from, int to)
cursor_size_lastto = to;
spin_lock_irqsave(&vga_lock, flags);
- outb_p(0x0a, vga_video_port_reg); /* Cursor start */
- curs = inb_p(vga_video_port_val);
- outb_p(0x0b, vga_video_port_reg); /* Cursor end */
- cure = inb_p(vga_video_port_val);
+ if (vga_video_type >= VIDEO_TYPE_VGAC) {
+ outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
+ curs = inb_p(vga_video_port_val);
+ outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
+ cure = inb_p(vga_video_port_val);
+ } else {
+ curs = 0;
+ cure = 0;
+ }
curs = (curs & 0xc0) | from;
cure = (cure & 0xe0) | to;
- outb_p(0x0a, vga_video_port_reg); /* Cursor start */
+ outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
outb_p(curs, vga_video_port_val);
- outb_p(0x0b, vga_video_port_reg); /* Cursor end */
+ outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
outb_p(cure, vga_video_port_val);
spin_unlock_irqrestore(&vga_lock, flags);
}
static void vgacon_cursor(struct vc_data *c, int mode)
{
- if (c->vc_origin != c->vc_visible_origin)
- vgacon_scrolldelta(c, 0);
+ vgacon_restore_screen(c);
+
switch (mode) {
case CM_ERASE:
write_vga(14, (c->vc_pos - vga_vram_base) / 2);
- vgacon_set_cursor_size(c->vc_x, 31, 30);
+ if (vga_video_type >= VIDEO_TYPE_VGAC)
+ vgacon_set_cursor_size(c->vc_x, 31, 30);
+ else
+ vgacon_set_cursor_size(c->vc_x, 31, 31);
break;
case CM_MOVE:
@@ -493,7 +690,10 @@ static void vgacon_cursor(struct vc_data *c, int mode)
10 ? 1 : 2));
break;
case CUR_NONE:
- vgacon_set_cursor_size(c->vc_x, 31, 30);
+ if (vga_video_type >= VIDEO_TYPE_VGAC)
+ vgacon_set_cursor_size(c->vc_x, 31, 30);
+ else
+ vgacon_set_cursor_size(c->vc_x, 31, 31);
break;
default:
vgacon_set_cursor_size(c->vc_x, 1,
@@ -595,6 +795,7 @@ static int vgacon_switch(struct vc_data *c)
vgacon_doresize(c, c->vc_cols, c->vc_rows);
}
+ vgacon_scrollback_init(c->vc_size_row);
return 0; /* Redrawing not needed */
}
@@ -1062,37 +1263,6 @@ static int vgacon_resize(struct vc_data *c, unsigned int width,
return 0;
}
-static int vgacon_scrolldelta(struct vc_data *c, int lines)
-{
- if (!lines) /* Turn scrollback off */
- c->vc_visible_origin = c->vc_origin;
- else {
- int margin = c->vc_size_row * 4;
- int ul, we, p, st;
-
- if (vga_rolled_over >
- (c->vc_scr_end - vga_vram_base) + margin) {
- ul = c->vc_scr_end - vga_vram_base;
- we = vga_rolled_over + c->vc_size_row;
- } else {
- ul = 0;
- we = vga_vram_size;
- }
- p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
- lines * c->vc_size_row;
- st = (c->vc_origin - vga_vram_base - ul + we) % we;
- if (st < 2 * margin)
- margin = 0;
- if (p < margin)
- p = 0;
- if (p > st - margin)
- p = st;
- c->vc_visible_origin = vga_vram_base + (p + ul) % we;
- }
- vga_set_mem_top(c);
- return 1;
-}
-
static int vgacon_set_origin(struct vc_data *c)
{
if (vga_is_gfx || /* We don't play origin tricks in graphic modes */
@@ -1135,15 +1305,14 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
if (t || b != c->vc_rows || vga_is_gfx)
return 0;
- if (c->vc_origin != c->vc_visible_origin)
- vgacon_scrolldelta(c, 0);
-
if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
return 0;
+ vgacon_restore_screen(c);
oldo = c->vc_origin;
delta = lines * c->vc_size_row;
if (dir == SM_UP) {
+ vgacon_scrollback_update(c, t, lines);
if (c->vc_scr_end + delta >= vga_vram_end) {
scr_memcpyw((u16 *) vga_vram_base,
(u16 *) (oldo + delta),
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index c32a2a50bfa..1f98392a43b 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -85,7 +85,7 @@ static struct fb_cmap default_16_colors = {
* Allocates memory for a colormap @cmap. @len is the
* number of entries in the palette.
*
- * Returns -1 errno on error, or zero on success.
+ * Returns negative errno on error, or zero on success.
*
*/
@@ -116,7 +116,7 @@ int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
fail:
fb_dealloc_cmap(cmap);
- return -1;
+ return -ENOMEM;
}
/**
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 07d882b1439..372aa177682 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -55,7 +55,7 @@
#define FBPIXMAPSIZE (1024 * 8)
-static struct notifier_block *fb_notifier_list;
+static BLOCKING_NOTIFIER_HEAD(fb_notifier_list);
struct fb_info *registered_fb[FB_MAX];
int num_registered_fb;
@@ -435,6 +435,11 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
depth = info->var.green.length;
}
+ if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) {
+ /* assume console colormap */
+ depth = 4;
+ }
+
if (depth >= 8) {
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
@@ -669,13 +674,19 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
total_size = info->fix.smem_len;
if (p > total_size)
- return 0;
+ return -EFBIG;
- if (count >= total_size)
+ if (count > total_size) {
+ err = -EFBIG;
count = total_size;
+ }
+
+ if (count + p > total_size) {
+ if (!err)
+ err = -ENOSPC;
- if (count + p > total_size)
count = total_size - p;
+ }
buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
GFP_KERNEL);
@@ -717,7 +728,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
kfree(buffer);
- return (err) ? err : cnt;
+ return (cnt) ? cnt : err;
}
#ifdef CONFIG_KMOD
@@ -784,7 +795,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
event.info = info;
event.data = &mode1;
- ret = notifier_call_chain(&fb_notifier_list,
+ ret = blocking_notifier_call_chain(&fb_notifier_list,
FB_EVENT_MODE_DELETE, &event);
}
@@ -830,8 +841,8 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
info->flags &= ~FBINFO_MISC_USEREVENT;
event.info = info;
- notifier_call_chain(&fb_notifier_list, evnt,
- &event);
+ blocking_notifier_call_chain(&fb_notifier_list,
+ evnt, &event);
}
}
}
@@ -854,7 +865,8 @@ fb_blank(struct fb_info *info, int blank)
event.info = info;
event.data = &blank;
- notifier_call_chain(&fb_notifier_list, FB_EVENT_BLANK, &event);
+ blocking_notifier_call_chain(&fb_notifier_list,
+ FB_EVENT_BLANK, &event);
}
return ret;
@@ -925,7 +937,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
con2fb.framebuffer = -1;
event.info = info;
event.data = &con2fb;
- notifier_call_chain(&fb_notifier_list,
+ blocking_notifier_call_chain(&fb_notifier_list,
FB_EVENT_GET_CONSOLE_MAP, &event);
return copy_to_user(argp, &con2fb,
sizeof(con2fb)) ? -EFAULT : 0;
@@ -944,7 +956,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return -EINVAL;
event.info = info;
event.data = &con2fb;
- return notifier_call_chain(&fb_notifier_list,
+ return blocking_notifier_call_chain(&fb_notifier_list,
FB_EVENT_SET_CONSOLE_MAP,
&event);
case FBIOBLANK:
@@ -1324,7 +1336,7 @@ register_framebuffer(struct fb_info *fb_info)
devfs_mk_cdev(MKDEV(FB_MAJOR, i),
S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i);
event.info = fb_info;
- notifier_call_chain(&fb_notifier_list,
+ blocking_notifier_call_chain(&fb_notifier_list,
FB_EVENT_FB_REGISTERED, &event);
return 0;
}
@@ -1366,7 +1378,7 @@ unregister_framebuffer(struct fb_info *fb_info)
*/
int fb_register_client(struct notifier_block *nb)
{
- return notifier_chain_register(&fb_notifier_list, nb);
+ return blocking_notifier_chain_register(&fb_notifier_list, nb);
}
/**
@@ -1375,7 +1387,7 @@ int fb_register_client(struct notifier_block *nb)
*/
int fb_unregister_client(struct notifier_block *nb)
{
- return notifier_chain_unregister(&fb_notifier_list, nb);
+ return blocking_notifier_chain_unregister(&fb_notifier_list, nb);
}
/**
@@ -1393,11 +1405,13 @@ void fb_set_suspend(struct fb_info *info, int state)
event.info = info;
if (state) {
- notifier_call_chain(&fb_notifier_list, FB_EVENT_SUSPEND, &event);
+ blocking_notifier_call_chain(&fb_notifier_list,
+ FB_EVENT_SUSPEND, &event);
info->state = FBINFO_STATE_SUSPENDED;
} else {
info->state = FBINFO_STATE_RUNNING;
- notifier_call_chain(&fb_notifier_list, FB_EVENT_RESUME, &event);
+ blocking_notifier_call_chain(&fb_notifier_list,
+ FB_EVENT_RESUME, &event);
}
}
@@ -1469,7 +1483,7 @@ int fb_new_modelist(struct fb_info *info)
if (!list_empty(&info->modelist)) {
event.info = info;
- err = notifier_call_chain(&fb_notifier_list,
+ err = blocking_notifier_call_chain(&fb_notifier_list,
FB_EVENT_NEW_MODELIST,
&event);
}
@@ -1495,7 +1509,7 @@ int fb_con_duit(struct fb_info *info, int event, void *data)
evnt.info = info;
evnt.data = data;
- return notifier_call_chain(&fb_notifier_list, event, &evnt);
+ return blocking_notifier_call_chain(&fb_notifier_list, event, &evnt);
}
EXPORT_SYMBOL(fb_con_duit);
@@ -1585,7 +1599,7 @@ static int __init video_setup(char *options)
}
}
- return 0;
+ return 1;
}
__setup("video=", video_setup);
#endif
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 7c74e7325d9..53beeb4a999 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -1281,7 +1281,7 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
-EINVAL : 0;
}
-#if defined(__i386__)
+#if defined(CONFIG_FB_FIRMWARE_EDID) && defined(__i386__)
#include <linux/pci.h>
/*
@@ -1311,11 +1311,11 @@ const unsigned char *fb_firmware_edid(struct device *device)
{
return NULL;
}
-#endif /* _i386_ */
+#endif
+EXPORT_SYMBOL(fb_firmware_edid);
EXPORT_SYMBOL(fb_parse_edid);
EXPORT_SYMBOL(fb_edid_to_monspecs);
-EXPORT_SYMBOL(fb_firmware_edid);
EXPORT_SYMBOL(fb_get_mode);
EXPORT_SYMBOL(fb_validate_mode);
EXPORT_SYMBOL(fb_destroy_modedb);
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 6d26057337e..34e07399756 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -305,94 +305,6 @@ static ssize_t show_stride(struct class_device *class_device, char *buf)
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
}
-/* Format for cmap is "%02x%c%4x%4x%4x\n" */
-/* %02x entry %c transp %4x red %4x blue %4x green \n */
-/* 256 rows at 16 chars equals 4096, the normal page size */
-/* the code will automatically adjust for different page sizes */
-static ssize_t store_cmap(struct class_device *class_device, const char *buf,
- size_t count)
-{
- struct fb_info *fb_info = class_get_devdata(class_device);
- int rc, i, start, length, transp = 0;
-
- if ((count > PAGE_SIZE) || ((count % 16) != 0))
- return -EINVAL;
-
- if (!fb_info->fbops->fb_setcolreg && !fb_info->fbops->fb_setcmap)
- return -EINVAL;
-
- sscanf(buf, "%02x", &start);
- length = count / 16;
-
- for (i = 0; i < length; i++)
- if (buf[i * 16 + 2] != ' ')
- transp = 1;
-
- /* If we can batch, do it */
- if (fb_info->fbops->fb_setcmap && length > 1) {
- struct fb_cmap umap;
-
- memset(&umap, 0, sizeof(umap));
- if ((rc = fb_alloc_cmap(&umap, length, transp)))
- return rc;
-
- umap.start = start;
- for (i = 0; i < length; i++) {
- sscanf(&buf[i * 16 + 3], "%4hx", &umap.red[i]);
- sscanf(&buf[i * 16 + 7], "%4hx", &umap.blue[i]);
- sscanf(&buf[i * 16 + 11], "%4hx", &umap.green[i]);
- if (transp)
- umap.transp[i] = (buf[i * 16 + 2] != ' ');
- }
- rc = fb_info->fbops->fb_setcmap(&umap, fb_info);
- fb_copy_cmap(&umap, &fb_info->cmap);
- fb_dealloc_cmap(&umap);
-
- return rc;
- }
- for (i = 0; i < length; i++) {
- u16 red, blue, green, tsp;
-
- sscanf(&buf[i * 16 + 3], "%4hx", &red);
- sscanf(&buf[i * 16 + 7], "%4hx", &blue);
- sscanf(&buf[i * 16 + 11], "%4hx", &green);
- tsp = (buf[i * 16 + 2] != ' ');
- if ((rc = fb_info->fbops->fb_setcolreg(start++,
- red, green, blue, tsp, fb_info)))
- return rc;
-
- fb_info->cmap.red[i] = red;
- fb_info->cmap.blue[i] = blue;
- fb_info->cmap.green[i] = green;
- if (transp)
- fb_info->cmap.transp[i] = tsp;
- }
- return 0;
-}
-
-static ssize_t show_cmap(struct class_device *class_device, char *buf)
-{
- struct fb_info *fb_info = class_get_devdata(class_device);
- unsigned int i;
-
- if (!fb_info->cmap.red || !fb_info->cmap.blue ||
- !fb_info->cmap.green)
- return -EINVAL;
-
- if (fb_info->cmap.len > PAGE_SIZE / 16)
- return -EINVAL;
-
- /* don't mess with the format, the buffer is PAGE_SIZE */
- /* 256 entries at 16 chars per line equals 4096 = PAGE_SIZE */
- for (i = 0; i < fb_info->cmap.len; i++) {
- snprintf(&buf[ i * 16], PAGE_SIZE - i * 16, "%02x%c%4x%4x%4x\n", i + fb_info->cmap.start,
- ((fb_info->cmap.transp && fb_info->cmap.transp[i]) ? '*' : ' '),
- fb_info->cmap.red[i], fb_info->cmap.blue[i],
- fb_info->cmap.green[i]);
- }
- return 16 * fb_info->cmap.len;
-}
-
static ssize_t store_blank(struct class_device *class_device, const char * buf,
size_t count)
{
@@ -502,10 +414,12 @@ static ssize_t show_fbstate(struct class_device *class_device, char *buf)
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
}
+/* When cmap is added back in it should be a binary attribute
+ * not a text one. Consideration should also be given to converting
+ * fbdev to use configfs instead of sysfs */
static struct class_device_attribute class_device_attrs[] = {
__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
- __ATTR(color_map, S_IRUGO|S_IWUSR, show_cmap, store_cmap),
__ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
__ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
__ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig
index 42fb9a89a79..4e173ef20a7 100644
--- a/drivers/video/geode/Kconfig
+++ b/drivers/video/geode/Kconfig
@@ -8,9 +8,24 @@ config FB_GEODE
Say 'Y' here to allow you to select framebuffer drivers for
the AMD Geode family of processors.
+config FB_GEODE_GX
+ tristate "AMD Geode GX framebuffer support (EXPERIMENTAL)"
+ depends on FB && FB_GEODE && EXPERIMENTAL
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Framebuffer driver for the display controller integrated into the
+ AMD Geode GX processors.
+
+ To compile this driver as a module, choose M here: the module will be
+ called gxfb.
+
+ If unsure, say N.
+
config FB_GEODE_GX1
tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)"
- depends on FB_GEODE && EXPERIMENTAL
+ depends on FB && FB_GEODE && EXPERIMENTAL
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile
index 13ad501ea99..f896565bc31 100644
--- a/drivers/video/geode/Makefile
+++ b/drivers/video/geode/Makefile
@@ -1,5 +1,7 @@
# Makefile for the Geode family framebuffer drivers
obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o
+obj-$(CONFIG_FB_GEODE_GX) += gxfb.o
-gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
+gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
+gxfb-objs := gxfb_core.o display_gx.o video_gx.o
diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c
new file mode 100644
index 00000000000..825c3405f5c
--- /dev/null
+++ b/drivers/video/geode/display_gx.c
@@ -0,0 +1,156 @@
+/*
+ * Geode GX display controller.
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Portions from AMD's original 2.4 driver:
+ * Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by * the
+ * Free Software Foundation; either version 2 of the License, or * (at your
+ * option) any later version.
+ */
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/div64.h>
+#include <asm/delay.h>
+
+#include "geodefb.h"
+#include "display_gx.h"
+
+int gx_frame_buffer_size(void)
+{
+ /* Assuming 16 MiB. */
+ return 16*1024*1024;
+}
+
+int gx_line_delta(int xres, int bpp)
+{
+ /* Must be a multiple of 8 bytes. */
+ return (xres * (bpp >> 3) + 7) & ~0x7;
+}
+
+static void gx_set_mode(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+ u32 gcfg, dcfg;
+ int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
+ int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
+
+ /* Unlock the display controller registers. */
+ readl(par->dc_regs + DC_UNLOCK);
+ writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
+
+ gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
+ dcfg = readl(par->dc_regs + DC_DISPLAY_CFG);
+
+ /* Disable the timing generator. */
+ dcfg &= ~(DC_DCFG_TGEN);
+ writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
+
+ /* Wait for pending memory requests before disabling the FIFO load. */
+ udelay(100);
+
+ /* Disable FIFO load and compression. */
+ gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
+ writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+ /* Setup DCLK and its divisor. */
+ par->vid_ops->set_dclk(info);
+
+ /*
+ * Setup new mode.
+ */
+
+ /* Clear all unused feature bits. */
+ gcfg &= DC_GCFG_YUVM | DC_GCFG_VDSE;
+ dcfg = 0;
+
+ /* Set FIFO priority (default 6/5) and enable. */
+ /* FIXME: increase fifo priority for 1280x1024 and higher modes? */
+ gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
+
+ /* Framebuffer start offset. */
+ writel(0, par->dc_regs + DC_FB_ST_OFFSET);
+
+ /* Line delta and line buffer length. */
+ writel(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH);
+ writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
+ par->dc_regs + DC_LINE_SIZE);
+
+ /* Enable graphics and video data and unmask address lines. */
+ dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M;
+
+ /* Set pixel format. */
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ dcfg |= DC_DCFG_DISP_MODE_8BPP;
+ break;
+ case 16:
+ dcfg |= DC_DCFG_DISP_MODE_16BPP;
+ dcfg |= DC_DCFG_16BPP_MODE_565;
+ break;
+ case 32:
+ dcfg |= DC_DCFG_DISP_MODE_24BPP;
+ dcfg |= DC_DCFG_PALB;
+ break;
+ }
+
+ /* Enable timing generator. */
+ dcfg |= DC_DCFG_TGEN;
+
+ /* Horizontal and vertical timings. */
+ hactive = info->var.xres;
+ hblankstart = hactive;
+ hsyncstart = hblankstart + info->var.right_margin;
+ hsyncend = hsyncstart + info->var.hsync_len;
+ hblankend = hsyncend + info->var.left_margin;
+ htotal = hblankend;
+
+ vactive = info->var.yres;
+ vblankstart = vactive;
+ vsyncstart = vblankstart + info->var.lower_margin;
+ vsyncend = vsyncstart + info->var.vsync_len;
+ vblankend = vsyncend + info->var.upper_margin;
+ vtotal = vblankend;
+
+ writel((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING);
+ writel((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING);
+ writel((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING);
+
+ writel((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING);
+ writel((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING);
+ writel((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING);
+
+ /* Write final register values. */
+ writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
+ writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+ par->vid_ops->configure_display(info);
+
+ /* Relock display controller registers */
+ writel(0, par->dc_regs + DC_UNLOCK);
+}
+
+static void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
+ unsigned red, unsigned green, unsigned blue)
+{
+ struct geodefb_par *par = info->par;
+ int val;
+
+ /* Hardware palette is in RGB 8-8-8 format. */
+ val = (red << 8) & 0xff0000;
+ val |= (green) & 0x00ff00;
+ val |= (blue >> 8) & 0x0000ff;
+
+ writel(regno, par->dc_regs + DC_PAL_ADDRESS);
+ writel(val, par->dc_regs + DC_PAL_DATA);
+}
+
+struct geode_dc_ops gx_dc_ops = {
+ .set_mode = gx_set_mode,
+ .set_palette_reg = gx_set_hw_palette_reg,
+};
diff --git a/drivers/video/geode/display_gx.h b/drivers/video/geode/display_gx.h
new file mode 100644
index 00000000000..86c62336130
--- /dev/null
+++ b/drivers/video/geode/display_gx.h
@@ -0,0 +1,96 @@
+/*
+ * Geode GX display controller
+ *
+ * Copyright (C) 2006 Arcom Control Systems Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __DISPLAY_GX_H__
+#define __DISPLAY_GX_H__
+
+int gx_frame_buffer_size(void);
+int gx_line_delta(int xres, int bpp);
+
+extern struct geode_dc_ops gx_dc_ops;
+
+/* Display controller registers */
+
+#define DC_UNLOCK 0x00
+# define DC_UNLOCK_CODE 0x00004758
+
+#define DC_GENERAL_CFG 0x04
+# define DC_GCFG_DFLE 0x00000001
+# define DC_GCFG_CURE 0x00000002
+# define DC_GCFG_ICNE 0x00000004
+# define DC_GCFG_VIDE 0x00000008
+# define DC_GCFG_CMPE 0x00000020
+# define DC_GCFG_DECE 0x00000040
+# define DC_GCFG_VGAE 0x00000080
+# define DC_GCFG_DFHPSL_MASK 0x00000F00
+# define DC_GCFG_DFHPSL_POS 8
+# define DC_GCFG_DFHPEL_MASK 0x0000F000
+# define DC_GCFG_DFHPEL_POS 12
+# define DC_GCFG_STFM 0x00010000
+# define DC_GCFG_FDTY 0x00020000
+# define DC_GCFG_VGAFT 0x00040000
+# define DC_GCFG_VDSE 0x00080000
+# define DC_GCFG_YUVM 0x00100000
+# define DC_GCFG_VFSL 0x00800000
+# define DC_GCFG_SIGE 0x01000000
+# define DC_GCFG_SGRE 0x02000000
+# define DC_GCFG_SGFR 0x04000000
+# define DC_GCFG_CRC_MODE 0x08000000
+# define DC_GCFG_DIAG 0x10000000
+# define DC_GCFG_CFRW 0x20000000
+
+#define DC_DISPLAY_CFG 0x08
+# define DC_DCFG_TGEN 0x00000001
+# define DC_DCFG_GDEN 0x00000008
+# define DC_DCFG_VDEN 0x00000010
+# define DC_DCFG_TRUP 0x00000040
+# define DC_DCFG_DISP_MODE_MASK 0x00000300
+# define DC_DCFG_DISP_MODE_8BPP 0x00000000
+# define DC_DCFG_DISP_MODE_16BPP 0x00000100
+# define DC_DCFG_DISP_MODE_24BPP 0x00000200
+# define DC_DCFG_16BPP_MODE_MASK 0x00000c00
+# define DC_DCFG_16BPP_MODE_565 0x00000000
+# define DC_DCFG_16BPP_MODE_555 0x00000100
+# define DC_DCFG_16BPP_MODE_444 0x00000200
+# define DC_DCFG_DCEN 0x00080000
+# define DC_DCFG_PALB 0x02000000
+# define DC_DCFG_FRLK 0x04000000
+# define DC_DCFG_VISL 0x08000000
+# define DC_DCFG_FRSL 0x20000000
+# define DC_DCFG_A18M 0x40000000
+# define DC_DCFG_A20M 0x80000000
+
+#define DC_FB_ST_OFFSET 0x10
+
+#define DC_LINE_SIZE 0x30
+# define DC_LINE_SIZE_FB_LINE_SIZE_MASK 0x000007ff
+# define DC_LINE_SIZE_FB_LINE_SIZE_POS 0
+# define DC_LINE_SIZE_CB_LINE_SIZE_MASK 0x007f0000
+# define DC_LINE_SIZE_CB_LINE_SIZE_POS 16
+# define DC_LINE_SIZE_VID_LINE_SIZE_MASK 0xff000000
+# define DC_LINE_SIZE_VID_LINE_SIZE_POS 24
+
+#define DC_GFX_PITCH 0x34
+# define DC_GFX_PITCH_FB_PITCH_MASK 0x0000ffff
+# define DC_GFX_PITCH_FB_PITCH_POS 0
+# define DC_GFX_PITCH_CB_PITCH_MASK 0xffff0000
+# define DC_GFX_PITCH_CB_PITCH_POS 16
+
+#define DC_H_ACTIVE_TIMING 0x40
+#define DC_H_BLANK_TIMING 0x44
+#define DC_H_SYNC_TIMING 0x48
+#define DC_V_ACTIVE_TIMING 0x50
+#define DC_V_BLANK_TIMING 0x54
+#define DC_V_SYNC_TIMING 0x58
+
+#define DC_PAL_ADDRESS 0x70
+#define DC_PAL_DATA 0x74
+
+#endif /* !__DISPLAY_GX1_H__ */
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
new file mode 100644
index 00000000000..89c34b15f5d
--- /dev/null
+++ b/drivers/video/geode/gxfb_core.c
@@ -0,0 +1,423 @@
+/*
+ * Geode GX framebuffer driver.
+ *
+ * Copyright (C) 2006 Arcom Control Systems Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ *
+ * This driver assumes that the BIOS has created a virtual PCI device header
+ * for the video device. The PCI header is assumed to contain the following
+ * BARs:
+ *
+ * BAR0 - framebuffer memory
+ * BAR1 - graphics processor registers
+ * BAR2 - display controller registers
+ * BAR3 - video processor and flat panel control registers.
+ *
+ * 16 MiB of framebuffer memory is assumed to be available.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include "geodefb.h"
+#include "display_gx.h"
+#include "video_gx.h"
+
+static char mode_option[32] = "640x480-16@60";
+
+/* Modes relevant to the GX (taken from modedb.c) */
+static const struct fb_videomode __initdata gx_modedb[] = {
+ /* 640x480-60 VESA */
+ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 640x480-75 VESA */
+ { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 640x480-85 VESA */
+ { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 800x600-60 VESA */
+ { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 800x600-75 VESA */
+ { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 800x600-85 VESA */
+ { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1024x768-60 VESA */
+ { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1024x768-75 VESA */
+ { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1024x768-85 VESA */
+ { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x960-60 VESA */
+ { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x960-85 VESA */
+ { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x1024-60 VESA */
+ { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x1024-75 VESA */
+ { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x1024-85 VESA */
+ { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1600x1200-60 VESA */
+ { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1600x1200-75 VESA */
+ { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1600x1200-85 VESA */
+ { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+};
+
+static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ if (var->xres > 1600 || var->yres > 1200)
+ return -EINVAL;
+ if ((var->xres > 1280 || var->yres > 1024) && var->bits_per_pixel > 16)
+ return -EINVAL;
+
+ if (var->bits_per_pixel == 32) {
+ var->red.offset = 16; var->red.length = 8;
+ var->green.offset = 8; var->green.length = 8;
+ var->blue.offset = 0; var->blue.length = 8;
+ } else if (var->bits_per_pixel == 16) {
+ var->red.offset = 11; var->red.length = 5;
+ var->green.offset = 5; var->green.length = 6;
+ var->blue.offset = 0; var->blue.length = 5;
+ } else if (var->bits_per_pixel == 8) {
+ var->red.offset = 0; var->red.length = 8;
+ var->green.offset = 0; var->green.length = 8;
+ var->blue.offset = 0; var->blue.length = 8;
+ } else
+ return -EINVAL;
+ var->transp.offset = 0; var->transp.length = 0;
+
+ /* Enough video memory? */
+ if (gx_line_delta(var->xres, var->bits_per_pixel) * var->yres > info->fix.smem_len)
+ return -EINVAL;
+
+ /* FIXME: Check timing parameters here? */
+
+ return 0;
+}
+
+static int gxfb_set_par(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+
+ if (info->var.bits_per_pixel > 8) {
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ fb_dealloc_cmap(&info->cmap);
+ } else {
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ fb_alloc_cmap(&info->cmap, 1<<info->var.bits_per_pixel, 0);
+ }
+
+ info->fix.line_length = gx_line_delta(info->var.xres, info->var.bits_per_pixel);
+
+ par->dc_ops->set_mode(info);
+
+ return 0;
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf->length;
+ return chan << bf->offset;
+}
+
+static int gxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+
+ if (info->var.grayscale) {
+ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+ }
+
+ /* Truecolor has hardware independent palette */
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+ u32 *pal = info->pseudo_palette;
+ u32 v;
+
+ if (regno >= 16)
+ return -EINVAL;
+
+ v = chan_to_field(red, &info->var.red);
+ v |= chan_to_field(green, &info->var.green);
+ v |= chan_to_field(blue, &info->var.blue);
+
+ pal[regno] = v;
+ } else {
+ if (regno >= 256)
+ return -EINVAL;
+
+ par->dc_ops->set_palette_reg(info, regno, red, green, blue);
+ }
+
+ return 0;
+}
+
+static int gxfb_blank(int blank_mode, struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+
+ return par->vid_ops->blank_display(info, blank_mode);
+}
+
+static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+{
+ struct geodefb_par *par = info->par;
+ int fb_len;
+ int ret;
+
+ ret = pci_enable_device(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = pci_request_region(dev, 3, "gxfb (video processor)");
+ if (ret < 0)
+ return ret;
+ par->vid_regs = ioremap(pci_resource_start(dev, 3),
+ pci_resource_len(dev, 3));
+ if (!par->vid_regs)
+ return -ENOMEM;
+
+ ret = pci_request_region(dev, 2, "gxfb (display controller)");
+ if (ret < 0)
+ return ret;
+ par->dc_regs = ioremap(pci_resource_start(dev, 2), pci_resource_len(dev, 2));
+ if (!par->dc_regs)
+ return -ENOMEM;
+
+ ret = pci_request_region(dev, 0, "gxfb (framebuffer)");
+ if (ret < 0)
+ return ret;
+ if ((fb_len = gx_frame_buffer_size()) < 0)
+ return -ENOMEM;
+ info->fix.smem_start = pci_resource_start(dev, 0);
+ info->fix.smem_len = fb_len;
+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+ if (!info->screen_base)
+ return -ENOMEM;
+
+ dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
+ info->fix.smem_len / 1024, info->fix.smem_start);
+
+ return 0;
+}
+
+static struct fb_ops gxfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = gxfb_check_var,
+ .fb_set_par = gxfb_set_par,
+ .fb_setcolreg = gxfb_setcolreg,
+ .fb_blank = gxfb_blank,
+ /* No HW acceleration for now. */
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
+{
+ struct geodefb_par *par;
+ struct fb_info *info;
+
+ /* Alloc enough space for the pseudo palette. */
+ info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev);
+ if (!info)
+ return NULL;
+
+ par = info->par;
+
+ strcpy(info->fix.id, "Geode GX");
+
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.type_aux = 0;
+ info->fix.xpanstep = 0;
+ info->fix.ypanstep = 0;
+ info->fix.ywrapstep = 0;
+ info->fix.accel = FB_ACCEL_NONE;
+
+ info->var.nonstd = 0;
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->var.height = -1;
+ info->var.width = -1;
+ info->var.accel_flags = 0;
+ info->var.vmode = FB_VMODE_NONINTERLACED;
+
+ info->fbops = &gxfb_ops;
+ info->flags = FBINFO_DEFAULT;
+ info->node = -1;
+
+ info->pseudo_palette = (void *)par + sizeof(struct geodefb_par);
+
+ info->var.grayscale = 0;
+
+ return info;
+}
+
+static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct geodefb_par *par;
+ struct fb_info *info;
+ int ret;
+
+ info = gxfb_init_fbinfo(&pdev->dev);
+ if (!info)
+ return -ENOMEM;
+ par = info->par;
+
+ /* GX display controller and GX video device. */
+ par->dc_ops = &gx_dc_ops;
+ par->vid_ops = &gx_vid_ops;
+
+ if ((ret = gxfb_map_video_memory(info, pdev)) < 0) {
+ dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
+ goto err;
+ }
+
+ ret = fb_find_mode(&info->var, info, mode_option,
+ gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16);
+ if (ret == 0 || ret == 4) {
+ dev_err(&pdev->dev, "could not find valid video mode\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* Clear the frame buffer of garbage. */
+ memset_io(info->screen_base, 0, info->fix.smem_len);
+
+ gxfb_check_var(&info->var, info);
+ gxfb_set_par(info);
+
+ if (register_framebuffer(info) < 0) {
+ ret = -EINVAL;
+ goto err;
+ }
+ pci_set_drvdata(pdev, info);
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
+ return 0;
+
+ err:
+ if (info->screen_base) {
+ iounmap(info->screen_base);
+ pci_release_region(pdev, 0);
+ }
+ if (par->vid_regs) {
+ iounmap(par->vid_regs);
+ pci_release_region(pdev, 3);
+ }
+ if (par->dc_regs) {
+ iounmap(par->dc_regs);
+ pci_release_region(pdev, 2);
+ }
+
+ pci_disable_device(pdev);
+
+ if (info)
+ framebuffer_release(info);
+ return ret;
+}
+
+static void gxfb_remove(struct pci_dev *pdev)
+{
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct geodefb_par *par = info->par;
+
+ unregister_framebuffer(info);
+
+ iounmap((void __iomem *)info->screen_base);
+ pci_release_region(pdev, 0);
+
+ iounmap(par->vid_regs);
+ pci_release_region(pdev, 3);
+
+ iounmap(par->dc_regs);
+ pci_release_region(pdev, 2);
+
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+
+ framebuffer_release(info);
+}
+
+static struct pci_device_id gxfb_id_table[] = {
+ { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_VIDEO,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+ 0xff0000, 0 },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, gxfb_id_table);
+
+static struct pci_driver gxfb_driver = {
+ .name = "gxfb",
+ .id_table = gxfb_id_table,
+ .probe = gxfb_probe,
+ .remove = gxfb_remove,
+};
+
+static int __init gxfb_init(void)
+{
+#ifndef MODULE
+ if (fb_get_options("gxfb", NULL))
+ return -ENODEV;
+#endif
+ return pci_register_driver(&gxfb_driver);
+}
+
+static void __exit gxfb_cleanup(void)
+{
+ pci_unregister_driver(&gxfb_driver);
+}
+
+module_init(gxfb_init);
+module_exit(gxfb_cleanup);
+
+module_param_string(mode, mode_option, sizeof(mode_option), 0444);
+MODULE_PARM_DESC(mode, "video mode (<x>x<y>[-<bpp>][@<refr>])");
+
+MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c
new file mode 100644
index 00000000000..2b2a7880ea7
--- /dev/null
+++ b/drivers/video/geode/video_gx.c
@@ -0,0 +1,262 @@
+/*
+ * Geode GX video processor device.
+ *
+ * Copyright (C) 2006 Arcom Control Systems Ltd.
+ *
+ * Portions from AMD's original 2.4 driver:
+ * Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/msr.h>
+
+#include "geodefb.h"
+#include "video_gx.h"
+
+
+/*
+ * Tables of register settings for various DOTCLKs.
+ */
+struct gx_pll_entry {
+ long pixclock; /* ps */
+ u32 sys_rstpll_bits;
+ u32 dotpll_value;
+};
+
+#define POSTDIV3 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3)
+#define PREMULT2 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPREMULT2)
+#define PREDIV2 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3)
+
+static const struct gx_pll_entry gx_pll_table_48MHz[] = {
+ { 40123, POSTDIV3, 0x00000BF2 }, /* 24.9230 */
+ { 39721, 0, 0x00000037 }, /* 25.1750 */
+ { 35308, POSTDIV3|PREMULT2, 0x00000B1A }, /* 28.3220 */
+ { 31746, POSTDIV3, 0x000002D2 }, /* 31.5000 */
+ { 27777, POSTDIV3|PREMULT2, 0x00000FE2 }, /* 36.0000 */
+ { 26666, POSTDIV3, 0x0000057A }, /* 37.5000 */
+ { 25000, POSTDIV3, 0x0000030A }, /* 40.0000 */
+ { 22271, 0, 0x00000063 }, /* 44.9000 */
+ { 20202, 0, 0x0000054B }, /* 49.5000 */
+ { 20000, 0, 0x0000026E }, /* 50.0000 */
+ { 19860, PREMULT2, 0x00000037 }, /* 50.3500 */
+ { 18518, POSTDIV3|PREMULT2, 0x00000B0D }, /* 54.0000 */
+ { 17777, 0, 0x00000577 }, /* 56.2500 */
+ { 17733, 0, 0x000007F7 }, /* 56.3916 */
+ { 17653, 0, 0x0000057B }, /* 56.6444 */
+ { 16949, PREMULT2, 0x00000707 }, /* 59.0000 */
+ { 15873, POSTDIV3|PREMULT2, 0x00000B39 }, /* 63.0000 */
+ { 15384, POSTDIV3|PREMULT2, 0x00000B45 }, /* 65.0000 */
+ { 14814, POSTDIV3|PREMULT2, 0x00000FC1 }, /* 67.5000 */
+ { 14124, POSTDIV3, 0x00000561 }, /* 70.8000 */
+ { 13888, POSTDIV3, 0x000007E1 }, /* 72.0000 */
+ { 13426, PREMULT2, 0x00000F4A }, /* 74.4810 */
+ { 13333, 0, 0x00000052 }, /* 75.0000 */
+ { 12698, 0, 0x00000056 }, /* 78.7500 */
+ { 12500, POSTDIV3|PREMULT2, 0x00000709 }, /* 80.0000 */
+ { 11135, PREMULT2, 0x00000262 }, /* 89.8000 */
+ { 10582, 0, 0x000002D2 }, /* 94.5000 */
+ { 10101, PREMULT2, 0x00000B4A }, /* 99.0000 */
+ { 10000, PREMULT2, 0x00000036 }, /* 100.0000 */
+ { 9259, 0, 0x000007E2 }, /* 108.0000 */
+ { 8888, 0, 0x000007F6 }, /* 112.5000 */
+ { 7692, POSTDIV3|PREMULT2, 0x00000FB0 }, /* 130.0000 */
+ { 7407, POSTDIV3|PREMULT2, 0x00000B50 }, /* 135.0000 */
+ { 6349, 0, 0x00000055 }, /* 157.5000 */
+ { 6172, 0, 0x000009C1 }, /* 162.0000 */
+ { 5787, PREMULT2, 0x0000002D }, /* 172.798 */
+ { 5698, 0, 0x000002C1 }, /* 175.5000 */
+ { 5291, 0, 0x000002D1 }, /* 189.0000 */
+ { 4938, 0, 0x00000551 }, /* 202.5000 */
+ { 4357, 0, 0x0000057D }, /* 229.5000 */
+};
+
+static const struct gx_pll_entry gx_pll_table_14MHz[] = {
+ { 39721, 0, 0x00000037 }, /* 25.1750 */
+ { 35308, 0, 0x00000B7B }, /* 28.3220 */
+ { 31746, 0, 0x000004D3 }, /* 31.5000 */
+ { 27777, 0, 0x00000BE3 }, /* 36.0000 */
+ { 26666, 0, 0x0000074F }, /* 37.5000 */
+ { 25000, 0, 0x0000050B }, /* 40.0000 */
+ { 22271, 0, 0x00000063 }, /* 44.9000 */
+ { 20202, 0, 0x0000054B }, /* 49.5000 */
+ { 20000, 0, 0x0000026E }, /* 50.0000 */
+ { 19860, 0, 0x000007C3 }, /* 50.3500 */
+ { 18518, 0, 0x000007E3 }, /* 54.0000 */
+ { 17777, 0, 0x00000577 }, /* 56.2500 */
+ { 17733, 0, 0x000002FB }, /* 56.3916 */
+ { 17653, 0, 0x0000057B }, /* 56.6444 */
+ { 16949, 0, 0x0000058B }, /* 59.0000 */
+ { 15873, 0, 0x0000095E }, /* 63.0000 */
+ { 15384, 0, 0x0000096A }, /* 65.0000 */
+ { 14814, 0, 0x00000BC2 }, /* 67.5000 */
+ { 14124, 0, 0x0000098A }, /* 70.8000 */
+ { 13888, 0, 0x00000BE2 }, /* 72.0000 */
+ { 13333, 0, 0x00000052 }, /* 75.0000 */
+ { 12698, 0, 0x00000056 }, /* 78.7500 */
+ { 12500, 0, 0x0000050A }, /* 80.0000 */
+ { 11135, 0, 0x0000078E }, /* 89.8000 */
+ { 10582, 0, 0x000002D2 }, /* 94.5000 */
+ { 10101, 0, 0x000011F6 }, /* 99.0000 */
+ { 10000, 0, 0x0000054E }, /* 100.0000 */
+ { 9259, 0, 0x000007E2 }, /* 108.0000 */
+ { 8888, 0, 0x000002FA }, /* 112.5000 */
+ { 7692, 0, 0x00000BB1 }, /* 130.0000 */
+ { 7407, 0, 0x00000975 }, /* 135.0000 */
+ { 6349, 0, 0x00000055 }, /* 157.5000 */
+ { 6172, 0, 0x000009C1 }, /* 162.0000 */
+ { 5698, 0, 0x000002C1 }, /* 175.5000 */
+ { 5291, 0, 0x00000539 }, /* 189.0000 */
+ { 4938, 0, 0x00000551 }, /* 202.5000 */
+ { 4357, 0, 0x0000057D }, /* 229.5000 */
+};
+
+static void gx_set_dclk_frequency(struct fb_info *info)
+{
+ const struct gx_pll_entry *pll_table;
+ int pll_table_len;
+ int i, best_i;
+ long min, diff;
+ u64 dotpll, sys_rstpll;
+ int timeout = 1000;
+
+ /* Rev. 1 Geode GXs use a 14 MHz reference clock instead of 48 MHz. */
+ if (cpu_data->x86_mask == 1) {
+ pll_table = gx_pll_table_14MHz;
+ pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
+ } else {
+ pll_table = gx_pll_table_48MHz;
+ pll_table_len = ARRAY_SIZE(gx_pll_table_48MHz);
+ }
+
+ /* Search the table for the closest pixclock. */
+ best_i = 0;
+ min = abs(pll_table[0].pixclock - info->var.pixclock);
+ for (i = 1; i < pll_table_len; i++) {
+ diff = abs(pll_table[i].pixclock - info->var.pixclock);
+ if (diff < min) {
+ min = diff;
+ best_i = i;
+ }
+ }
+
+ rdmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll);
+ rdmsrl(MSR_GLCP_DOTPLL, dotpll);
+
+ /* Program new M, N and P. */
+ dotpll &= 0x00000000ffffffffull;
+ dotpll |= (u64)pll_table[best_i].dotpll_value << 32;
+ dotpll |= MSR_GLCP_DOTPLL_DOTRESET;
+ dotpll &= ~MSR_GLCP_DOTPLL_BYPASS;
+
+ wrmsrl(MSR_GLCP_DOTPLL, dotpll);
+
+ /* Program dividers. */
+ sys_rstpll &= ~( MSR_GLCP_SYS_RSTPLL_DOTPREDIV2
+ | MSR_GLCP_SYS_RSTPLL_DOTPREMULT2
+ | MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 );
+ sys_rstpll |= pll_table[best_i].sys_rstpll_bits;
+
+ wrmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll);
+
+ /* Clear reset bit to start PLL. */
+ dotpll &= ~(MSR_GLCP_DOTPLL_DOTRESET);
+ wrmsrl(MSR_GLCP_DOTPLL, dotpll);
+
+ /* Wait for LOCK bit. */
+ do {
+ rdmsrl(MSR_GLCP_DOTPLL, dotpll);
+ } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK));
+}
+
+static void gx_configure_display(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+ u32 dcfg, fp_pm;
+
+ dcfg = readl(par->vid_regs + GX_DCFG);
+
+ /* Clear bits from existing mode. */
+ dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
+ | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL
+ | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
+
+ /* Set default sync skew. */
+ dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT;
+
+ /* Enable hsync and vsync. */
+ dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN;
+
+ /* Sync polarities. */
+ if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+ dcfg |= GX_DCFG_CRT_HSYNC_POL;
+ if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+ dcfg |= GX_DCFG_CRT_VSYNC_POL;
+
+ writel(dcfg, par->vid_regs + GX_DCFG);
+
+ /* Power on flat panel. */
+ fp_pm = readl(par->vid_regs + GX_FP_PM);
+ fp_pm |= GX_FP_PM_P;
+ writel(fp_pm, par->vid_regs + GX_FP_PM);
+}
+
+static int gx_blank_display(struct fb_info *info, int blank_mode)
+{
+ struct geodefb_par *par = info->par;
+ u32 dcfg, fp_pm;
+ int blank, hsync, vsync;
+
+ /* CRT power saving modes. */
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ blank = 0; hsync = 1; vsync = 1;
+ break;
+ case FB_BLANK_NORMAL:
+ blank = 1; hsync = 1; vsync = 1;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ blank = 1; hsync = 1; vsync = 0;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ blank = 1; hsync = 0; vsync = 1;
+ break;
+ case FB_BLANK_POWERDOWN:
+ blank = 1; hsync = 0; vsync = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ dcfg = readl(par->vid_regs + GX_DCFG);
+ dcfg &= ~(GX_DCFG_DAC_BL_EN
+ | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN);
+ if (!blank)
+ dcfg |= GX_DCFG_DAC_BL_EN;
+ if (hsync)
+ dcfg |= GX_DCFG_HSYNC_EN;
+ if (vsync)
+ dcfg |= GX_DCFG_VSYNC_EN;
+ writel(dcfg, par->vid_regs + GX_DCFG);
+
+ /* Power on/off flat panel. */
+ fp_pm = readl(par->vid_regs + GX_FP_PM);
+ if (blank_mode == FB_BLANK_POWERDOWN)
+ fp_pm &= ~GX_FP_PM_P;
+ else
+ fp_pm |= GX_FP_PM_P;
+ writel(fp_pm, par->vid_regs + GX_FP_PM);
+
+ return 0;
+}
+
+struct geode_vid_ops gx_vid_ops = {
+ .set_dclk = gx_set_dclk_frequency,
+ .configure_display = gx_configure_display,
+ .blank_display = gx_blank_display,
+};
diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h
new file mode 100644
index 00000000000..2d9211f3ed8
--- /dev/null
+++ b/drivers/video/geode/video_gx.h
@@ -0,0 +1,47 @@
+/*
+ * Geode GX video device
+ *
+ * Copyright (C) 2006 Arcom Control Systems Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __VIDEO_GX_H__
+#define __VIDEO_GX_H__
+
+extern struct geode_vid_ops gx_vid_ops;
+
+/* Geode GX video processor registers */
+
+#define GX_DCFG 0x0008
+# define GX_DCFG_CRT_EN 0x00000001
+# define GX_DCFG_HSYNC_EN 0x00000002
+# define GX_DCFG_VSYNC_EN 0x00000004
+# define GX_DCFG_DAC_BL_EN 0x00000008
+# define GX_DCFG_CRT_HSYNC_POL 0x00000100
+# define GX_DCFG_CRT_VSYNC_POL 0x00000200
+# define GX_DCFG_CRT_SYNC_SKW_MASK 0x0001C000
+# define GX_DCFG_CRT_SYNC_SKW_DFLT 0x00010000
+# define GX_DCFG_VG_CK 0x00100000
+# define GX_DCFG_GV_GAM 0x00200000
+# define GX_DCFG_DAC_VREF 0x04000000
+
+/* Geode GX flat panel display control registers */
+#define GX_FP_PM 0x410
+# define GX_FP_PM_P 0x01000000
+
+/* Geode GX clock control MSRs */
+
+#define MSR_GLCP_SYS_RSTPLL 0x4c000014
+# define MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 (0x0000000000000002ull)
+# define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 (0x0000000000000004ull)
+# define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 (0x0000000000000008ull)
+
+#define MSR_GLCP_DOTPLL 0x4c000015
+# define MSR_GLCP_DOTPLL_DOTRESET (0x0000000000000001ull)
+# define MSR_GLCP_DOTPLL_BYPASS (0x0000000000008000ull)
+# define MSR_GLCP_DOTPLL_LOCK (0x0000000002000000ull)
+
+#endif /* !__VIDEO_GX_H__ */
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index e3c8b5f1ca7..3fe3ae1aff1 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -210,8 +210,7 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
}
}
- if (out_edid)
- *out_edid = edid;
+ *out_edid = edid;
return (edid) ? 0 : 1;
}
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 788297e9d59..44aa2ffff97 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -76,8 +76,8 @@
*
* Experiment with v_offset to find out which works best for you.
*/
-static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */
-static u32 voffset __initdata = 0;
+static u32 v_offset_default __devinitdata; /* For 32 MiB Aper size, 8 should be the default */
+static u32 voffset __devinitdata;
static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
static int __devinit i810fb_init_pci (struct pci_dev *dev,
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 7db42542eb1..f73c642b50c 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -440,9 +440,9 @@ getclkMHz(struct imstt_par *par)
static void
setclkMHz(struct imstt_par *par, __u32 MHz)
{
- __u32 clk_m, clk_n, clk_p, x, stage, spilled;
+ __u32 clk_m, clk_n, x, stage, spilled;
- clk_m = clk_n = clk_p = 0;
+ clk_m = clk_n = 0;
stage = spilled = 0;
for (;;) {
switch (stage) {
@@ -453,7 +453,7 @@ setclkMHz(struct imstt_par *par, __u32 MHz)
clk_n++;
break;
}
- x = 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));
+ x = 20 * (clk_m + 1) / (clk_n + 1);
if (x == MHz)
break;
if (x > MHz) {
@@ -466,7 +466,7 @@ setclkMHz(struct imstt_par *par, __u32 MHz)
par->init.pclk_m = clk_m;
par->init.pclk_n = clk_n;
- par->init.pclk_p = clk_p;
+ par->init.pclk_p = 0;
}
static struct imstt_regvals *
@@ -1372,18 +1372,24 @@ init_imstt(struct fb_info *info)
write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1);
write_reg_le32(par->dc_regs, SSR, 0);
- /* set default values for DAC registers */
+ /* set default values for DAC registers */
if (par->ramdac == IBM) {
- par->cmap_regs[PPMASK] = 0xff; eieio();
- par->cmap_regs[PIDXHI] = 0; eieio();
- for (i = 0; i < sizeof(ibm_initregs) / sizeof(*ibm_initregs); i++) {
- par->cmap_regs[PIDXLO] = ibm_initregs[i].addr; eieio();
- par->cmap_regs[PIDXDATA] = ibm_initregs[i].value; eieio();
+ par->cmap_regs[PPMASK] = 0xff;
+ eieio();
+ par->cmap_regs[PIDXHI] = 0;
+ eieio();
+ for (i = 0; i < ARRAY_SIZE(ibm_initregs); i++) {
+ par->cmap_regs[PIDXLO] = ibm_initregs[i].addr;
+ eieio();
+ par->cmap_regs[PIDXDATA] = ibm_initregs[i].value;
+ eieio();
}
} else {
- for (i = 0; i < sizeof(tvp_initregs) / sizeof(*tvp_initregs); i++) {
- par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr; eieio();
- par->cmap_regs[TVPIDATA] = tvp_initregs[i].value; eieio();
+ for (i = 0; i < ARRAY_SIZE(tvp_initregs); i++) {
+ par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr;
+ eieio();
+ par->cmap_regs[TVPIDATA] = tvp_initregs[i].value;
+ eieio();
}
}
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
index 4ef5cd19609..b985dfad6c6 100644
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -34,7 +34,7 @@ extra-y += $(call logo-cfiles,_clut224,ppm)
extra-y += $(call logo-cfiles,_gray256,pgm)
# Create commands like "pnmtologo -t mono -n logo_mac_mono -o ..."
-quiet_cmd_logo = LOGO $@
+quiet_cmd_logo = LOGO $@
cmd_logo = scripts/pnmtologo \
-t $(patsubst $*_%,%,$(notdir $(basename $<))) \
-n $(notdir $(basename $<)) -o $@ $<
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index 2fc71081f7e..c0385c6f7db 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -380,7 +380,7 @@ int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
if (mode_option && !strncmp(mode_option, "mac", 3)) {
mode_option += 3;
db = mac_modedb;
- dbsize = sizeof(mac_modedb)/sizeof(*mac_modedb);
+ dbsize = ARRAY_SIZE(mac_modedb);
}
return fb_find_mode(var, info, mode_option, db, dbsize,
&mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp);
diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c
index 8073a73f6f3..440272ad10e 100644
--- a/drivers/video/matrox/g450_pll.c
+++ b/drivers/video/matrox/g450_pll.c
@@ -316,14 +316,24 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
case M_PIXEL_PLL_B:
case M_PIXEL_PLL_C:
{
- u_int8_t tmp;
+ u_int8_t tmp, xpwrctrl;
unsigned long flags;
matroxfb_DAC_lock_irqsave(flags);
+
+ xpwrctrl = matroxfb_DAC_in(PMINFO M1064_XPWRCTRL);
+ matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl & ~M1064_XPWRCTRL_PANELPDN);
+ mga_outb(M_SEQ_INDEX, M_SEQ1);
+ mga_outb(M_SEQ_DATA, mga_inb(M_SEQ_DATA) | M_SEQ1_SCROFF);
tmp = matroxfb_DAC_in(PMINFO M1064_XPIXCLKCTRL);
+ tmp |= M1064_XPIXCLKCTRL_DIS;
if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) {
- matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp | M1064_XPIXCLKCTRL_PLL_UP);
+ tmp |= M1064_XPIXCLKCTRL_PLL_UP;
}
+ matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp);
+ matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL, 0);
+ matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl);
+
matroxfb_DAC_unlock_irqrestore(flags);
}
{
@@ -418,6 +428,15 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
frequency to higher - with <= lowest wins, while
with < highest one wins */
if (delta <= deltaarray[idx-1]) {
+ /* all else being equal except VCO,
+ * choose VCO not near (within 1/16th or so) VCOmin
+ * (freqs near VCOmin aren't as stable)
+ */
+ if (delta == deltaarray[idx-1]
+ && vco != g450_mnp2vco(PMINFO mnparray[idx-1])
+ && vco < (pi->vcomin * 17 / 16)) {
+ break;
+ }
mnparray[idx] = mnparray[idx-1];
deltaarray[idx] = deltaarray[idx-1];
} else {
diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h
index 2e7238aa243..56513a5d220 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.h
+++ b/drivers/video/matrox/matroxfb_DAC1064.h
@@ -40,6 +40,7 @@ void DAC1064_global_restore(WPMINFO2);
#define M1064_XCURCOL1RED 0x0C
#define M1064_XCURCOL1GREEN 0x0D
#define M1064_XCURCOL1BLUE 0x0E
+#define M1064_XDVICLKCTRL 0x0F
#define M1064_XCURCOL2RED 0x10
#define M1064_XCURCOL2GREEN 0x11
#define M1064_XCURCOL2BLUE 0x12
@@ -144,6 +145,7 @@ void DAC1064_global_restore(WPMINFO2);
#define M1064_XVIDPLLN 0x8F
#define M1064_XPWRCTRL 0xA0
+#define M1064_XPWRCTRL_PANELPDN 0x04
#define M1064_XPANMODE 0xA2
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 951c9974a1d..23c1827b2d0 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -115,6 +115,7 @@
#include <asm/uaccess.h>
#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
unsigned char nvram_read_byte(int);
static int default_vmode = VMODE_NVRAM;
static int default_cmode = CMODE_NVRAM;
@@ -1833,7 +1834,7 @@ static int initMatrox2(WPMINFO struct board* b){
/* FIXME: Where to move this?! */
#if defined(CONFIG_PPC_PMAC)
#ifndef MODULE
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
struct fb_var_screeninfo var;
if (default_vmode <= 0 || default_vmode > VMODE_MAX)
default_vmode = VMODE_640_480_60;
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index 3a3e1804c56..b71737178d0 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -672,6 +672,8 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv);
#define M_SEQ_INDEX 0x1FC4
#define M_SEQ_DATA 0x1FC5
+#define M_SEQ1 0x01
+#define M_SEQ1_SCROFF 0x20
#define M_MISC_REG_READ 0x1FCC
diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c
index c122d8743dd..4d610b405d4 100644
--- a/drivers/video/matrox/matroxfb_g450.c
+++ b/drivers/video/matrox/matroxfb_g450.c
@@ -59,7 +59,7 @@ static const struct mctl g450_controls[] =
}, offsetof(struct matrox_fb_info, altout.tvo_params.testout) },
};
-#define G450CTRLS (sizeof(g450_controls)/sizeof(g450_controls[0]))
+#define G450CTRLS ARRAY_SIZE(g450_controls)
/* Return: positive number: id found
-EINVAL: id not found, return failure
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 6019710dc29..5d29a26b8cd 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -89,12 +89,12 @@ static const struct mctl maven_controls[] =
}, offsetof(struct matrox_fb_info, altout.tvo_params.hue) },
{ { V4L2_CID_GAMMA, V4L2_CTRL_TYPE_INTEGER,
"gamma",
- 0, sizeof(maven_gamma)/sizeof(maven_gamma[0])-1, 1, 3,
+ 0, ARRAY_SIZE(maven_gamma) - 1, 1, 3,
0,
}, offsetof(struct matrox_fb_info, altout.tvo_params.gamma) },
{ { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN,
"test output",
- 0, 1, 1, 0,
+ 0, 1, 1, 0,
0,
}, offsetof(struct matrox_fb_info, altout.tvo_params.testout) },
{ { MATROXFB_CID_DEFLICKER, V4L2_CTRL_TYPE_INTEGER,
@@ -105,7 +105,7 @@ static const struct mctl maven_controls[] =
};
-#define MAVCTRLS (sizeof(maven_controls)/sizeof(maven_controls[0]))
+#define MAVCTRLS ARRAY_SIZE(maven_controls)
/* Return: positive number: id found
-EINVAL: id not found, return failure
@@ -129,7 +129,7 @@ static int get_ctrl_id(__u32 v4l2_id) {
struct maven_data {
struct matrox_fb_info* primary_head;
- struct i2c_client* client;
+ struct i2c_client client;
int version;
};
@@ -970,7 +970,7 @@ static inline int maven_compute_timming(struct maven_data* md,
static int maven_program_timming(struct maven_data* md,
const struct mavenregs* m) {
- struct i2c_client* c = md->client;
+ struct i2c_client* c = &md->client;
if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) {
LR(0x80);
@@ -1007,7 +1007,7 @@ static int maven_program_timming(struct maven_data* md,
}
static inline int maven_resync(struct maven_data* md) {
- struct i2c_client* c = md->client;
+ struct i2c_client* c = &md->client;
maven_set_reg(c, 0x95, 0x20); /* start whole thing */
return 0;
}
@@ -1065,48 +1065,48 @@ static int maven_set_control (struct maven_data* md,
maven_compute_bwlevel(md, &blacklevel, &whitelevel);
blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8);
whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8);
- maven_set_reg_pair(md->client, 0x0e, blacklevel);
- maven_set_reg_pair(md->client, 0x1e, whitelevel);
+ maven_set_reg_pair(&md->client, 0x0e, blacklevel);
+ maven_set_reg_pair(&md->client, 0x1e, whitelevel);
}
break;
case V4L2_CID_SATURATION:
{
- maven_set_reg(md->client, 0x20, p->value);
- maven_set_reg(md->client, 0x22, p->value);
+ maven_set_reg(&md->client, 0x20, p->value);
+ maven_set_reg(&md->client, 0x22, p->value);
}
break;
case V4L2_CID_HUE:
{
- maven_set_reg(md->client, 0x25, p->value);
+ maven_set_reg(&md->client, 0x25, p->value);
}
break;
case V4L2_CID_GAMMA:
{
const struct maven_gamma* g;
g = maven_compute_gamma(md);
- maven_set_reg(md->client, 0x83, g->reg83);
- maven_set_reg(md->client, 0x84, g->reg84);
- maven_set_reg(md->client, 0x85, g->reg85);
- maven_set_reg(md->client, 0x86, g->reg86);
- maven_set_reg(md->client, 0x87, g->reg87);
- maven_set_reg(md->client, 0x88, g->reg88);
- maven_set_reg(md->client, 0x89, g->reg89);
- maven_set_reg(md->client, 0x8a, g->reg8a);
- maven_set_reg(md->client, 0x8b, g->reg8b);
+ maven_set_reg(&md->client, 0x83, g->reg83);
+ maven_set_reg(&md->client, 0x84, g->reg84);
+ maven_set_reg(&md->client, 0x85, g->reg85);
+ maven_set_reg(&md->client, 0x86, g->reg86);
+ maven_set_reg(&md->client, 0x87, g->reg87);
+ maven_set_reg(&md->client, 0x88, g->reg88);
+ maven_set_reg(&md->client, 0x89, g->reg89);
+ maven_set_reg(&md->client, 0x8a, g->reg8a);
+ maven_set_reg(&md->client, 0x8b, g->reg8b);
}
break;
case MATROXFB_CID_TESTOUT:
{
unsigned char val
- = maven_get_reg (md->client,0x8d);
+ = maven_get_reg(&md->client,0x8d);
if (p->value) val |= 0x10;
else val &= ~0x10;
- maven_set_reg (md->client, 0x8d, val);
+ maven_set_reg(&md->client, 0x8d, val);
}
break;
case MATROXFB_CID_DEFLICKER:
{
- maven_set_reg(md->client, 0x93, maven_compute_deflicker(md));
+ maven_set_reg(&md->client, 0x93, maven_compute_deflicker(md));
}
break;
}
@@ -1185,7 +1185,6 @@ static int maven_init_client(struct i2c_client* clnt) {
MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo);
md->primary_head = MINFO;
- md->client = clnt;
down_write(&ACCESS_FBINFO(altout.lock));
ACCESS_FBINFO(outputs[1]).output = &maven_altout;
ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src;
@@ -1243,19 +1242,17 @@ static int maven_detect_client(struct i2c_adapter* adapter, int address, int kin
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_PROTOCOL_MANGLING))
goto ERROR0;
- if (!(new_client = (struct i2c_client*)kmalloc(sizeof(*new_client) + sizeof(*data),
- GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR0;
}
- memset(new_client, 0, sizeof(*new_client) + sizeof(*data));
- data = (struct maven_data*)(new_client + 1);
+ new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &maven_driver;
new_client->flags = 0;
- strcpy(new_client->name, "maven client");
+ strlcpy(new_client->name, "maven", I2C_NAME_SIZE);
if ((err = i2c_attach_client(new_client)))
goto ERROR3;
err = maven_init_client(new_client);
@@ -1279,12 +1276,10 @@ static int maven_attach_adapter(struct i2c_adapter* adapter) {
static int maven_detach_client(struct i2c_client* client) {
int err;
- if ((err = i2c_detach_client(client))) {
- printk(KERN_ERR "maven: Cannot deregister client\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
maven_shutdown_client(client);
- kfree(client);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -1297,20 +1292,13 @@ static struct i2c_driver maven_driver={
.detach_client = maven_detach_client,
};
-/* ************************** */
-
-static int matroxfb_maven_init(void) {
- int err;
-
- err = i2c_add_driver(&maven_driver);
- if (err) {
- printk(KERN_ERR "maven: Maven driver failed to register (%d).\n", err);
- return err;
- }
- return 0;
+static int __init matroxfb_maven_init(void)
+{
+ return i2c_add_driver(&maven_driver);
}
-static void matroxfb_maven_exit(void) {
+static void __exit matroxfb_maven_exit(void)
+{
i2c_del_driver(&maven_driver);
}
diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c
index 743e7ad26ac..f85421bf7cb 100644
--- a/drivers/video/maxinefb.c
+++ b/drivers/video/maxinefb.c
@@ -55,7 +55,7 @@ static struct fb_var_screeninfo maxinefb_defined = {
};
static struct fb_fix_screeninfo maxinefb_fix = {
- .id = "Maxine onboard graphics 1024x768x8",
+ .id = "Maxine",
.smem_len = (1024*768),
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
@@ -107,8 +107,6 @@ static int maxinefb_setcolreg(unsigned regno, unsigned red, unsigned green,
static struct fb_ops maxinefb_ops = {
.owner = THIS_MODULE,
- .fb_get_fix = gen_get_fix,
- .fb_get_var = gen_get_var,
.fb_setcolreg = maxinefb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 1da2f84bdc2..26a1c618a20 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -183,6 +183,10 @@ static const struct fb_videomode modedb[] = {
NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
}, {
+ /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */
+ NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }, {
/* 1600x1200 @ 85 Hz, 105.77 kHz hsync */
NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
@@ -496,7 +500,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
/* Set up defaults */
if (!db) {
db = modedb;
- dbsize = sizeof(modedb)/sizeof(*modedb);
+ dbsize = ARRAY_SIZE(modedb);
}
if (!default_mode)
default_mode = &modedb[DEFAULT_MODEDB_INDEX];
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index b961d5601bd..24b12f71d5a 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -165,20 +165,20 @@ static int neoFindMode(int xres, int yres, int depth)
switch (depth) {
case 8:
- size = sizeof(bios8) / sizeof(biosMode);
+ size = ARRAY_SIZE(bios8);
mode = bios8;
break;
case 16:
- size = sizeof(bios16) / sizeof(biosMode);
+ size = ARRAY_SIZE(bios16);
mode = bios16;
break;
case 24:
- size = sizeof(bios24) / sizeof(biosMode);
+ size = ARRAY_SIZE(bios24);
mode = bios24;
break;
#ifdef NO_32BIT_SUPPORT_YET
case 32:
- size = sizeof(bios32) / sizeof(biosMode);
+ size = ARRAY_SIZE(bios32);
mode = bios32;
break;
#endif
diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c
index f377a29ec97..4aefb8f4163 100644
--- a/drivers/video/nvidia/nv_accel.c
+++ b/drivers/video/nvidia/nv_accel.c
@@ -300,6 +300,9 @@ int nvidiafb_sync(struct fb_info *info)
{
struct nvidia_par *par = info->par;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return 0;
+
if (!par->lockup)
NVFlush(par);
@@ -313,6 +316,9 @@ void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
struct nvidia_par *par = info->par;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+
if (par->lockup)
return cfb_copyarea(info, region);
@@ -329,6 +335,9 @@ void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
struct nvidia_par *par = info->par;
u32 color;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+
if (par->lockup)
return cfb_fillrect(info, rect);
@@ -412,6 +421,9 @@ void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct nvidia_par *par = info->par;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+
if (image->depth == 1 && !par->lockup)
nvidiafb_mono_color_expand(info, image);
else
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index bd9eca05e14..1edb1c432b7 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -218,8 +218,7 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
}
}
- if (out_edid)
- *out_edid = edid;
+ *out_edid = edid;
return (edid) ? 0 : 1;
}
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h
index e4a5b1da71c..acdc2669340 100644
--- a/drivers/video/nvidia/nv_type.h
+++ b/drivers/video/nvidia/nv_type.h
@@ -129,6 +129,7 @@ struct nvidia_par {
int fpHeight;
int PanelTweak;
int paneltweak;
+ int pm_state;
u32 crtcSync_read;
u32 fpSyncs;
u32 dmaPut;
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index a7c4e5e8ead..093ab9977c7 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -21,6 +21,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/console.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
@@ -29,6 +30,7 @@
#include <asm/pci-bridge.h>
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/machdep.h>
#include <asm/backlight.h>
#endif
@@ -296,6 +298,8 @@ static struct pci_device_id nvidiafb_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, 0x0252,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, 0x0313,
@@ -615,6 +619,30 @@ static int nvidia_panel_tweak(struct nvidia_par *par,
return tweak;
}
+static void nvidia_vga_protect(struct nvidia_par *par, int on)
+{
+ unsigned char tmp;
+
+ if (on) {
+ /*
+ * Turn off screen and disable sequencer.
+ */
+ tmp = NVReadSeq(par, 0x01);
+
+ NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */
+ NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */
+ } else {
+ /*
+ * Reenable sequencer, then turn on screen.
+ */
+
+ tmp = NVReadSeq(par, 0x01);
+
+ NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */
+ NVWriteSeq(par, 0x00, 0x03); /* End Reset */
+ }
+}
+
static void nvidia_save_vga(struct nvidia_par *par,
struct _riva_hw_state *state)
{
@@ -643,9 +671,9 @@ static void nvidia_save_vga(struct nvidia_par *par,
#undef DUMP_REG
-static void nvidia_write_regs(struct nvidia_par *par)
+static void nvidia_write_regs(struct nvidia_par *par,
+ struct _riva_hw_state *state)
{
- struct _riva_hw_state *state = &par->ModeReg;
int i;
NVTRACE_ENTER();
@@ -694,32 +722,6 @@ static void nvidia_write_regs(struct nvidia_par *par)
NVTRACE_LEAVE();
}
-static void nvidia_vga_protect(struct nvidia_par *par, int on)
-{
- unsigned char tmp;
-
- if (on) {
- /*
- * Turn off screen and disable sequencer.
- */
- tmp = NVReadSeq(par, 0x01);
-
- NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */
- NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */
- } else {
- /*
- * Reenable sequencer, then turn on screen.
- */
-
- tmp = NVReadSeq(par, 0x01);
-
- NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */
- NVWriteSeq(par, 0x00, 0x03); /* End Reset */
- }
-}
-
-
-
static int nvidia_calc_regs(struct fb_info *info)
{
struct nvidia_par *par = info->par;
@@ -1068,7 +1070,8 @@ static int nvidiafb_set_par(struct fb_info *info)
nvidia_vga_protect(par, 1);
- nvidia_write_regs(par);
+ nvidia_write_regs(par, &par->ModeReg);
+ NVSetStartAddress(par, 0);
#if defined (__BIG_ENDIAN)
/* turn on LFB swapping */
@@ -1353,7 +1356,7 @@ static int nvidiafb_blank(int blank, struct fb_info *info)
NVWriteCrtc(par, 0x1a, vesa);
#ifdef CONFIG_PMAC_BACKLIGHT
- if (par->FlatPanel && _machine == _MACH_Pmac) {
+ if (par->FlatPanel && machine_is(powermac)) {
set_backlight_enable(!blank);
}
#endif
@@ -1377,6 +1380,57 @@ static struct fb_ops nvidia_fb_ops = {
.fb_sync = nvidiafb_sync,
};
+#ifdef CONFIG_PM
+static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct nvidia_par *par = info->par;
+
+ acquire_console_sem();
+ par->pm_state = state.event;
+
+ if (state.event == PM_EVENT_FREEZE) {
+ dev->dev.power.power_state = state;
+ } else {
+ fb_set_suspend(info, 1);
+ nvidiafb_blank(FB_BLANK_POWERDOWN, info);
+ nvidia_write_regs(par, &par->SavedReg);
+ pci_save_state(dev);
+ pci_disable_device(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+ }
+
+ release_console_sem();
+ return 0;
+}
+
+static int nvidiafb_resume(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct nvidia_par *par = info->par;
+
+ acquire_console_sem();
+ pci_set_power_state(dev, PCI_D0);
+
+ if (par->pm_state != PM_EVENT_FREEZE) {
+ pci_restore_state(dev);
+ pci_enable_device(dev);
+ pci_set_master(dev);
+ }
+
+ par->pm_state = PM_EVENT_ON;
+ nvidiafb_set_par(info);
+ fb_set_suspend (info, 0);
+ nvidiafb_blank(FB_BLANK_UNBLANK, info);
+
+ release_console_sem();
+ return 0;
+}
+#else
+#define nvidiafb_suspend NULL
+#define nvidiafb_resume NULL
+#endif
+
static int __devinit nvidia_set_fbinfo(struct fb_info *info)
{
struct fb_monspecs *specs = &info->monspecs;
@@ -1688,7 +1742,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
info->fix.id,
par->FbMapSize / (1024 * 1024), info->fix.smem_start);
#ifdef CONFIG_PMAC_BACKLIGHT
- if (par->FlatPanel && _machine == _MACH_Pmac)
+ if (par->FlatPanel && machine_is(powermac))
register_backlight_controller(&nvidia_backlight_controller,
par, "mnca");
#endif
@@ -1720,8 +1774,6 @@ static void __exit nvidiafb_remove(struct pci_dev *pd)
struct nvidia_par *par = info->par;
NVTRACE_ENTER();
- if (!info)
- return;
unregister_framebuffer(info);
#ifdef CONFIG_MTRR
@@ -1798,8 +1850,10 @@ static int __devinit nvidiafb_setup(char *options)
static struct pci_driver nvidiafb_driver = {
.name = "nvidiafb",
.id_table = nvidiafb_pci_tbl,
- .probe = nvidiafb_probe,
- .remove = __exit_p(nvidiafb_remove),
+ .probe = nvidiafb_probe,
+ .suspend = nvidiafb_suspend,
+ .resume = nvidiafb_resume,
+ .remove = __exit_p(nvidiafb_remove),
};
/* ------------------------------------------------------------------------- *
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 5fe197943de..4e963930b50 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -73,8 +73,8 @@ static char *mode __devinitdata = NULL;
* these flags allow the user to specify that requests for +ve sync
* should be silently turned in -ve sync.
*/
-static int lowhsync __devinitdata = 0;
-static int lowvsync __devinitdata = 0;
+static int lowhsync;
+static int lowvsync;
/*
* The hardware state of the graphics card that isn't part of the
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index eeeac924b50..73e2d7d1660 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -228,7 +228,7 @@ static void __init pmagbbfb_osc_setup(struct fb_info *info)
freq1 = (par->osc0 * count1 + count0 / 2) / count0;
par->osc1 = freq1;
- for (i = 0; i < sizeof(pmagbbfb_freqs) / sizeof(*pmagbbfb_freqs); i++)
+ for (i = 0; i < ARRAY_SIZE(pmagbbfb_freqs); i++)
if (freq1 >= pmagbbfb_freqs[i] -
(pmagbbfb_freqs[i] + 128) / 256 &&
freq1 <= pmagbbfb_freqs[i] +
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 53ad61f1038..809fc5eefc1 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -232,9 +232,9 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
if (var->yres < MIN_YRES)
var->yres = MIN_YRES;
if (var->xres > fbi->max_xres)
- var->xres = fbi->max_xres;
+ return -EINVAL;
if (var->yres > fbi->max_yres)
- var->yres = fbi->max_yres;
+ return -EINVAL;
var->xres_virtual =
max(var->xres_virtual, var->xres);
var->yres_virtual =
@@ -781,7 +781,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */
- schedule_timeout(20 * HZ / 1000);
+ schedule_timeout(200 * HZ / 1000);
remove_wait_queue(&fbi->ctrlr_wait, &wait);
/* disable LCD controller clock */
@@ -1274,7 +1274,7 @@ int __init pxafb_probe(struct platform_device *dev)
struct pxafb_mach_info *inf;
int ret;
- dev_dbg(dev, "pxafb_probe\n");
+ dev_dbg(&dev->dev, "pxafb_probe\n");
inf = dev->dev.platform_data;
ret = -ENOMEM;
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
deleted file mode 100644
index db9fb9074db..00000000000
--- a/drivers/video/radeonfb.c
+++ /dev/null
@@ -1,3167 +0,0 @@
-/*
- * drivers/video/radeonfb.c
- * framebuffer driver for ATI Radeon chipset video boards
- *
- * Copyright 2000 Ani Joshi <ajoshi@kernel.crashing.org>
- *
- *
- * ChangeLog:
- * 2000-08-03 initial version 0.0.1
- * 2000-09-10 more bug fixes, public release 0.0.5
- * 2001-02-19 mode bug fixes, 0.0.7
- * 2001-07-05 fixed scrolling issues, engine initialization,
- * and minor mode tweaking, 0.0.9
- * 2001-09-07 Radeon VE support, Nick Kurshev
- * blanking, pan_display, and cmap fixes, 0.1.0
- * 2001-10-10 Radeon 7500 and 8500 support, and experimental
- * flat panel support, 0.1.1
- * 2001-11-17 Radeon M6 (ppc) support, Daniel Berlin, 0.1.2
- * 2001-11-18 DFP fixes, Kevin Hendricks, 0.1.3
- * 2001-11-29 more cmap, backlight fixes, Benjamin Herrenschmidt
- * 2002-01-18 DFP panel detection via BIOS, Michael Clark, 0.1.4
- * 2002-06-02 console switching, mode set fixes, accel fixes
- * 2002-06-03 MTRR support, Peter Horton, 0.1.5
- * 2002-09-21 rv250, r300, m9 initial support,
- * added mirror option, 0.1.6
- *
- * Special thanks to ATI DevRel team for their hardware donations.
- *
- */
-
-
-#define RADEON_VERSION "0.1.6"
-
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#if defined(__powerpc__)
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include "macmodes.h"
-
-#ifdef CONFIG_NVRAM
-#include <linux/nvram.h>
-#endif
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
-
-#ifdef CONFIG_BOOTX_TEXT
-#include <asm/btext.h>
-#endif
-
-#ifdef CONFIG_ADB_PMU
-#include <linux/adb.h>
-#include <linux/pmu.h>
-#endif
-
-#endif /* __powerpc__ */
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include <video/radeon.h>
-#include <linux/radeonfb.h>
-
-#define DEBUG 0
-
-#if DEBUG
-#define RTRACE printk
-#else
-#define RTRACE if(0) printk
-#endif
-
-// XXX
-#undef CONFIG_PMAC_PBOOK
-
-
-enum radeon_chips {
- RADEON_QD,
- RADEON_QE,
- RADEON_QF,
- RADEON_QG,
- RADEON_QY,
- RADEON_QZ,
- RADEON_LW,
- RADEON_LX,
- RADEON_LY,
- RADEON_LZ,
- RADEON_QL,
- RADEON_QN,
- RADEON_QO,
- RADEON_Ql,
- RADEON_BB,
- RADEON_QW,
- RADEON_QX,
- RADEON_Id,
- RADEON_Ie,
- RADEON_If,
- RADEON_Ig,
- RADEON_Ya,
- RADEON_Yd,
- RADEON_Ld,
- RADEON_Le,
- RADEON_Lf,
- RADEON_Lg,
- RADEON_ND,
- RADEON_NE,
- RADEON_NF,
- RADEON_NG,
- RADEON_QM
-};
-
-enum radeon_arch {
- RADEON_R100,
- RADEON_RV100,
- RADEON_R200,
- RADEON_RV200,
- RADEON_RV250,
- RADEON_R300,
- RADEON_M6,
- RADEON_M7,
- RADEON_M9
-};
-
-static struct radeon_chip_info {
- const char *name;
- unsigned char arch;
-} radeon_chip_info[] __devinitdata = {
- { "QD", RADEON_R100 },
- { "QE", RADEON_R100 },
- { "QF", RADEON_R100 },
- { "QG", RADEON_R100 },
- { "VE QY", RADEON_RV100 },
- { "VE QZ", RADEON_RV100 },
- { "M7 LW", RADEON_M7 },
- { "M7 LX", RADEON_M7 },
- { "M6 LY", RADEON_M6 },
- { "M6 LZ", RADEON_M6 },
- { "8500 QL", RADEON_R200 },
- { "8500 QN", RADEON_R200 },
- { "8500 QO", RADEON_R200 },
- { "8500 Ql", RADEON_R200 },
- { "8500 BB", RADEON_R200 },
- { "7500 QW", RADEON_RV200 },
- { "7500 QX", RADEON_RV200 },
- { "9000 Id", RADEON_RV250 },
- { "9000 Ie", RADEON_RV250 },
- { "9000 If", RADEON_RV250 },
- { "9000 Ig", RADEON_RV250 },
- { "M9 Ld", RADEON_M9 },
- { "M9 Le", RADEON_M9 },
- { "M9 Lf", RADEON_M9 },
- { "M9 Lg", RADEON_M9 },
- { "9700 ND", RADEON_R300 },
- { "9700 NE", RADEON_R300 },
- { "9700 NF", RADEON_R300 },
- { "9700 NG", RADEON_R300 },
- { "9100 QM", RADEON_R200 }
-};
-
-
-enum radeon_montype
-{
- MT_NONE,
- MT_CRT, /* CRT */
- MT_LCD, /* LCD */
- MT_DFP, /* DVI */
- MT_CTV, /* composite TV */
- MT_STV /* S-Video out */
-};
-
-
-static struct pci_device_id radeonfb_pci_table[] = {
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QD},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QE},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QF},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QG},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QY},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QZ},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LW},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LX},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LY},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LZ},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QL},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QN, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QN},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QO},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ql, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ql},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_BB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_BB},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QW},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QX},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Id},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ie, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ie},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_If, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_If},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ig, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ig},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ya, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ya},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Yd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Yd},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ld, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ld},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Le, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Le},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Lf, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Lf},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Lg, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Lg},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_ND, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_ND},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NE},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NF},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NG},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QM},
- { 0, }
-};
-MODULE_DEVICE_TABLE(pci, radeonfb_pci_table);
-
-
-typedef struct {
- u16 reg;
- u32 val;
-} reg_val;
-
-
-/* these common regs are cleared before mode setting so they do not
- * interfere with anything
- */
-static reg_val common_regs[] = {
- { OVR_CLR, 0 },
- { OVR_WID_LEFT_RIGHT, 0 },
- { OVR_WID_TOP_BOTTOM, 0 },
- { OV0_SCALE_CNTL, 0 },
- { SUBPIC_CNTL, 0 },
- { VIPH_CONTROL, 0 },
- { I2C_CNTL_1, 0 },
- { GEN_INT_CNTL, 0 },
- { CAP0_TRIG_CNTL, 0 },
-};
-
-static reg_val common_regs_m6[] = {
- { OVR_CLR, 0 },
- { OVR_WID_LEFT_RIGHT, 0 },
- { OVR_WID_TOP_BOTTOM, 0 },
- { OV0_SCALE_CNTL, 0 },
- { SUBPIC_CNTL, 0 },
- { GEN_INT_CNTL, 0 },
- { CAP0_TRIG_CNTL, 0 }
-};
-
-typedef struct {
- u8 clock_chip_type;
- u8 struct_size;
- u8 accelerator_entry;
- u8 VGA_entry;
- u16 VGA_table_offset;
- u16 POST_table_offset;
- u16 XCLK;
- u16 MCLK;
- u8 num_PLL_blocks;
- u8 size_PLL_blocks;
- u16 PCLK_ref_freq;
- u16 PCLK_ref_divider;
- u32 PCLK_min_freq;
- u32 PCLK_max_freq;
- u16 MCLK_ref_freq;
- u16 MCLK_ref_divider;
- u32 MCLK_min_freq;
- u32 MCLK_max_freq;
- u16 XCLK_ref_freq;
- u16 XCLK_ref_divider;
- u32 XCLK_min_freq;
- u32 XCLK_max_freq;
-} __attribute__ ((packed)) PLL_BLOCK;
-
-
-struct pll_info {
- int ppll_max;
- int ppll_min;
- int xclk;
- int ref_div;
- int ref_clk;
-};
-
-
-struct ram_info {
- int ml;
- int mb;
- int trcd;
- int trp;
- int twr;
- int cl;
- int tr2w;
- int loop_latency;
- int rloop;
-};
-
-
-struct radeon_regs {
- /* CRTC regs */
- u32 crtc_h_total_disp;
- u32 crtc_h_sync_strt_wid;
- u32 crtc_v_total_disp;
- u32 crtc_v_sync_strt_wid;
- u32 crtc_pitch;
- u32 crtc_gen_cntl;
- u32 crtc_ext_cntl;
- u32 dac_cntl;
-
- u32 flags;
- u32 pix_clock;
- int xres, yres;
-
- /* DDA regs */
- u32 dda_config;
- u32 dda_on_off;
-
- /* PLL regs */
- u32 ppll_div_3;
- u32 ppll_ref_div;
- u32 vclk_ecp_cntl;
-
- /* Flat panel regs */
- u32 fp_crtc_h_total_disp;
- u32 fp_crtc_v_total_disp;
- u32 fp_gen_cntl;
- u32 fp_h_sync_strt_wid;
- u32 fp_horz_stretch;
- u32 fp_panel_cntl;
- u32 fp_v_sync_strt_wid;
- u32 fp_vert_stretch;
- u32 lvds_gen_cntl;
- u32 lvds_pll_cntl;
- u32 tmds_crc;
- u32 tmds_transmitter_cntl;
-
-#if defined(__BIG_ENDIAN)
- u32 surface_cntl;
-#endif
-};
-
-
-struct radeonfb_info {
- struct fb_info info;
-
- struct radeon_regs state;
- struct radeon_regs init_state;
-
- char name[32];
- char ram_type[12];
-
- unsigned long mmio_base_phys;
- unsigned long fb_base_phys;
-
- void __iomem *mmio_base;
- void __iomem *fb_base;
-
- struct pci_dev *pdev;
-
- unsigned char *EDID;
- unsigned char __iomem *bios_seg;
-
- u32 pseudo_palette[17];
- struct { u8 red, green, blue, pad; } palette[256];
-
- int chipset;
- unsigned char arch;
- int video_ram;
- u8 rev;
- int pitch, bpp, depth;
- int xres, yres, pixclock;
- int xres_virtual, yres_virtual;
- u32 accel_flags;
-
- int use_default_var;
- int got_dfpinfo;
-
- int hasCRTC2;
- int crtDisp_type;
- int dviDisp_type;
-
- int panel_xres, panel_yres;
- int clock;
- int hOver_plus, hSync_width, hblank;
- int vOver_plus, vSync_width, vblank;
- int hAct_high, vAct_high, interlaced;
- int synct, misc;
-
- u32 dp_gui_master_cntl;
-
- struct pll_info pll;
- int pll_output_freq, post_div, fb_div;
-
- struct ram_info ram;
-
- int mtrr_hdl;
-
-#ifdef CONFIG_PMAC_PBOOK
- int pm_reg;
- u32 save_regs[64];
- u32 mdll, mdll2;
-#endif /* CONFIG_PMAC_PBOOK */
- int asleep;
-
- struct radeonfb_info *next;
-};
-
-
-static struct fb_var_screeninfo radeonfb_default_var = {
- 640, 480, 640, 480, 0, 0, 8, 0,
- {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 39721, 40, 24, 32, 11, 96, 2,
- 0, FB_VMODE_NONINTERLACED
-};
-
-/*
- * IO macros
- */
-
-#define INREG8(addr) readb((rinfo->mmio_base)+addr)
-#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
-#define INREG(addr) readl((rinfo->mmio_base)+addr)
-#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)
-
-#define OUTPLL(addr,val) \
- do { \
- OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000003f) | 0x00000080); \
- OUTREG(CLOCK_CNTL_DATA, val); \
- } while(0)
-
-#define OUTPLLP(addr,val,mask) \
- do { \
- unsigned int _tmp = INPLL(addr); \
- _tmp &= (mask); \
- _tmp |= (val); \
- OUTPLL(addr, _tmp); \
- } while (0)
-
-#define OUTREGP(addr,val,mask) \
- do { \
- unsigned int _tmp = INREG(addr); \
- _tmp &= (mask); \
- _tmp |= (val); \
- OUTREG(addr, _tmp); \
- } while (0)
-
-
-static __inline__ u32 _INPLL(struct radeonfb_info *rinfo, u32 addr)
-{
- OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
- return (INREG(CLOCK_CNTL_DATA));
-}
-
-#define INPLL(addr) _INPLL(rinfo, addr)
-
-#define PRIMARY_MONITOR(rinfo) ((rinfo->dviDisp_type != MT_NONE) && \
- (rinfo->dviDisp_type != MT_STV) && \
- (rinfo->dviDisp_type != MT_CTV) ? \
- rinfo->dviDisp_type : rinfo->crtDisp_type)
-
-static char *GET_MON_NAME(int type)
-{
- char *pret = NULL;
-
- switch (type) {
- case MT_NONE:
- pret = "no";
- break;
- case MT_CRT:
- pret = "CRT";
- break;
- case MT_DFP:
- pret = "DFP";
- break;
- case MT_LCD:
- pret = "LCD";
- break;
- case MT_CTV:
- pret = "CTV";
- break;
- case MT_STV:
- pret = "STV";
- break;
- }
-
- return pret;
-}
-
-
-/*
- * 2D engine routines
- */
-
-static __inline__ void radeon_engine_flush (struct radeonfb_info *rinfo)
-{
- int i;
-
- /* initiate flush */
- OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
- ~RB2D_DC_FLUSH_ALL);
-
- for (i=0; i < 2000000; i++) {
- if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
- break;
- }
-}
-
-
-static __inline__ void _radeon_fifo_wait (struct radeonfb_info *rinfo, int entries)
-{
- int i;
-
- for (i=0; i<2000000; i++)
- if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
- return;
-}
-
-
-static __inline__ void _radeon_engine_idle (struct radeonfb_info *rinfo)
-{
- int i;
-
- /* ensure FIFO is empty before waiting for idle */
- _radeon_fifo_wait (rinfo, 64);
-
- for (i=0; i<2000000; i++) {
- if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
- radeon_engine_flush (rinfo);
- return;
- }
- }
-}
-
-
-#define radeon_engine_idle() _radeon_engine_idle(rinfo)
-#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)
-
-
-
-/*
- * helper routines
- */
-
-static __inline__ u32 radeon_get_dstbpp(u16 depth)
-{
- switch (depth) {
- case 8:
- return DST_8BPP;
- case 15:
- return DST_15BPP;
- case 16:
- return DST_16BPP;
- case 32:
- return DST_32BPP;
- default:
- return 0;
- }
-}
-
-
-static inline int var_to_depth(const struct fb_var_screeninfo *var)
-{
- if (var->bits_per_pixel != 16)
- return var->bits_per_pixel;
- return (var->green.length == 6) ? 16 : 15;
-}
-
-
-static void _radeon_engine_reset(struct radeonfb_info *rinfo)
-{
- u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
-
- radeon_engine_flush (rinfo);
-
- clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
- mclk_cntl = INPLL(MCLK_CNTL);
-
- OUTPLL(MCLK_CNTL, (mclk_cntl |
- FORCEON_MCLKA |
- FORCEON_MCLKB |
- FORCEON_YCLKA |
- FORCEON_YCLKB |
- FORCEON_MC |
- FORCEON_AIC));
- rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
-
- OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
- SOFT_RESET_CP |
- SOFT_RESET_HI |
- SOFT_RESET_SE |
- SOFT_RESET_RE |
- SOFT_RESET_PP |
- SOFT_RESET_E2 |
- SOFT_RESET_RB);
- INREG(RBBM_SOFT_RESET);
- OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32)
- ~(SOFT_RESET_CP |
- SOFT_RESET_HI |
- SOFT_RESET_SE |
- SOFT_RESET_RE |
- SOFT_RESET_PP |
- SOFT_RESET_E2 |
- SOFT_RESET_RB));
- INREG(RBBM_SOFT_RESET);
-
- OUTPLL(MCLK_CNTL, mclk_cntl);
- OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
- OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
-
- return;
-}
-
-#define radeon_engine_reset() _radeon_engine_reset(rinfo)
-
-
-static __inline__ int round_div(int num, int den)
-{
- return (num + (den / 2)) / den;
-}
-
-
-
-static __inline__ int min_bits_req(int val)
-{
- int bits_req = 0;
-
- if (val == 0)
- bits_req = 1;
-
- while (val) {
- val >>= 1;
- bits_req++;
- }
-
- return (bits_req);
-}
-
-
-static __inline__ int _max(int val1, int val2)
-{
- if (val1 >= val2)
- return val1;
- else
- return val2;
-}
-
-
-
-/*
- * globals
- */
-
-#ifndef MODULE
-static char *mode_option;
-#endif
-
-static char noaccel = 0;
-static char mirror = 0;
-static int panel_yres = 0;
-static char force_dfp = 0;
-static struct radeonfb_info *board_list = NULL;
-static char nomtrr = 0;
-
-/*
- * prototypes
- */
-
-static void radeon_save_state (struct radeonfb_info *rinfo,
- struct radeon_regs *save);
-static void radeon_engine_init (struct radeonfb_info *rinfo);
-static void radeon_write_mode (struct radeonfb_info *rinfo,
- struct radeon_regs *mode);
-static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo);
-static int __devinit radeon_init_disp (struct radeonfb_info *rinfo);
-static int radeon_init_disp_var (struct radeonfb_info *rinfo, struct fb_var_screeninfo *var);
-static void __iomem *radeon_find_rom(struct radeonfb_info *rinfo);
-static void radeon_get_pllinfo(struct radeonfb_info *rinfo, void __iomem *bios_seg);
-static void radeon_get_moninfo (struct radeonfb_info *rinfo);
-static int radeon_get_dfpinfo (struct radeonfb_info *rinfo);
-static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo);
-static void radeon_get_EDID(struct radeonfb_info *rinfo);
-static int radeon_dfp_parse_EDID(struct radeonfb_info *rinfo);
-static void radeon_update_default_var(struct radeonfb_info *rinfo);
-
-#ifdef CONFIG_PPC_OF
-
-static int radeon_read_OF (struct radeonfb_info *rinfo);
-static int radeon_get_EDID_OF(struct radeonfb_info *rinfo);
-extern struct device_node *pci_device_to_OF_node(struct pci_dev *dev);
-
-#ifdef CONFIG_PMAC_PBOOK
-int radeon_sleep_notify(struct pmu_sleep_notifier *self, int when);
-static struct pmu_sleep_notifier radeon_sleep_notifier = {
- radeon_sleep_notify, SLEEP_LEVEL_VIDEO,
-};
-#endif /* CONFIG_PMAC_PBOOK */
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int radeon_set_backlight_enable(int on, int level, void *data);
-static int radeon_set_backlight_level(int level, void *data);
-static struct backlight_controller radeon_backlight_controller = {
- radeon_set_backlight_enable,
- radeon_set_backlight_level
-};
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
-#endif /* CONFIG_PPC_OF */
-
-
-static void __iomem *radeon_find_rom(struct radeonfb_info *rinfo)
-{
-#if defined(__i386__)
- u32 segstart;
- char __iomem *rom_base;
- char __iomem *rom;
- int stage;
- int i,j;
- char aty_rom_sig[] = "761295520";
- char *radeon_sig[] = {
- "RG6",
- "RADEON"
- };
-
- for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
-
- stage = 1;
-
- rom_base = ioremap(segstart, 0x1000);
-
- if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
- stage = 2;
-
-
- if (stage != 2) {
- iounmap(rom_base);
- continue;
- }
-
- rom = rom_base;
-
- for (i = 0; (i < 128 - strlen(aty_rom_sig)) && (stage != 3); i++) {
- if (aty_rom_sig[0] == *rom)
- if (strncmp(aty_rom_sig, rom,
- strlen(aty_rom_sig)) == 0)
- stage = 3;
- rom++;
- }
- if (stage != 3) {
- iounmap(rom_base);
- continue;
- }
- rom = rom_base;
-
- for (i = 0; (i < 512) && (stage != 4); i++) {
- for(j = 0;j < sizeof(radeon_sig)/sizeof(char *);j++) {
- if (radeon_sig[j][0] == *rom)
- if (strncmp(radeon_sig[j], rom,
- strlen(radeon_sig[j])) == 0) {
- stage = 4;
- break;
- }
- }
- rom++;
- }
- if (stage != 4) {
- iounmap(rom_base);
- continue;
- }
-
- return rom_base;
- }
-#endif
- return NULL;
-}
-
-
-
-
-static void radeon_get_pllinfo(struct radeonfb_info *rinfo, void __iomem *bios_seg)
-{
- void __iomem *bios_header;
- void __iomem *header_ptr;
- u16 bios_header_offset, pll_info_offset;
- PLL_BLOCK pll;
-
- if (bios_seg) {
- bios_header = bios_seg + 0x48L;
- header_ptr = bios_header;
-
- bios_header_offset = readw(header_ptr);
- bios_header = bios_seg + bios_header_offset;
- bios_header += 0x30;
-
- header_ptr = bios_header;
- pll_info_offset = readw(header_ptr);
- header_ptr = bios_seg + pll_info_offset;
-
- memcpy_fromio(&pll, header_ptr, 50);
-
- rinfo->pll.xclk = (u32)pll.XCLK;
- rinfo->pll.ref_clk = (u32)pll.PCLK_ref_freq;
- rinfo->pll.ref_div = (u32)pll.PCLK_ref_divider;
- rinfo->pll.ppll_min = pll.PCLK_min_freq;
- rinfo->pll.ppll_max = pll.PCLK_max_freq;
-
- printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d from BIOS\n",
- rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk);
- } else {
-#ifdef CONFIG_PPC_OF
- if (radeon_read_OF(rinfo)) {
- unsigned int tmp, Nx, M, ref_div, xclk;
-
- tmp = INPLL(M_SPLL_REF_FB_DIV);
- ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
-
- Nx = (tmp & 0xff00) >> 8;
- M = (tmp & 0xff);
- xclk = ((((2 * Nx * rinfo->pll.ref_clk) + (M)) /
- (2 * M)));
-
- rinfo->pll.xclk = xclk;
- rinfo->pll.ref_div = ref_div;
- rinfo->pll.ppll_min = 12000;
- rinfo->pll.ppll_max = 35000;
-
- printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d from OF\n",
- rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk);
-
- return;
- }
-#endif
- /* no BIOS or BIOS not found, use defaults */
- switch (rinfo->chipset) {
- case PCI_DEVICE_ID_ATI_RADEON_QW:
- case PCI_DEVICE_ID_ATI_RADEON_QX:
- rinfo->pll.ppll_max = 35000;
- rinfo->pll.ppll_min = 12000;
- rinfo->pll.xclk = 23000;
- rinfo->pll.ref_div = 12;
- rinfo->pll.ref_clk = 2700;
- break;
- case PCI_DEVICE_ID_ATI_RADEON_QL:
- case PCI_DEVICE_ID_ATI_RADEON_QN:
- case PCI_DEVICE_ID_ATI_RADEON_QO:
- case PCI_DEVICE_ID_ATI_RADEON_Ql:
- case PCI_DEVICE_ID_ATI_RADEON_BB:
- rinfo->pll.ppll_max = 35000;
- rinfo->pll.ppll_min = 12000;
- rinfo->pll.xclk = 27500;
- rinfo->pll.ref_div = 12;
- rinfo->pll.ref_clk = 2700;
- break;
- case PCI_DEVICE_ID_ATI_RADEON_Id:
- case PCI_DEVICE_ID_ATI_RADEON_Ie:
- case PCI_DEVICE_ID_ATI_RADEON_If:
- case PCI_DEVICE_ID_ATI_RADEON_Ig:
- rinfo->pll.ppll_max = 35000;
- rinfo->pll.ppll_min = 12000;
- rinfo->pll.xclk = 25000;
- rinfo->pll.ref_div = 12;
- rinfo->pll.ref_clk = 2700;
- break;
- case PCI_DEVICE_ID_ATI_RADEON_ND:
- case PCI_DEVICE_ID_ATI_RADEON_NE:
- case PCI_DEVICE_ID_ATI_RADEON_NF:
- case PCI_DEVICE_ID_ATI_RADEON_NG:
- rinfo->pll.ppll_max = 40000;
- rinfo->pll.ppll_min = 20000;
- rinfo->pll.xclk = 27000;
- rinfo->pll.ref_div = 12;
- rinfo->pll.ref_clk = 2700;
- break;
- case PCI_DEVICE_ID_ATI_RADEON_QD:
- case PCI_DEVICE_ID_ATI_RADEON_QE:
- case PCI_DEVICE_ID_ATI_RADEON_QF:
- case PCI_DEVICE_ID_ATI_RADEON_QG:
- default:
- rinfo->pll.ppll_max = 35000;
- rinfo->pll.ppll_min = 12000;
- rinfo->pll.xclk = 16600;
- rinfo->pll.ref_div = 67;
- rinfo->pll.ref_clk = 2700;
- break;
- }
-
- printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d defaults\n",
- rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk);
- }
-}
-
-
-static void radeon_get_moninfo (struct radeonfb_info *rinfo)
-{
- unsigned int tmp;
-
- if (force_dfp) {
- rinfo->dviDisp_type = MT_DFP;
- return;
- }
-
- tmp = INREG(BIOS_4_SCRATCH);
- printk(KERN_DEBUG "radeon_get_moninfo: bios 4 scratch = %x\n", tmp);
-
- if (rinfo->hasCRTC2) {
- /* primary DVI port */
- if (tmp & 0x08)
- rinfo->dviDisp_type = MT_DFP;
- else if (tmp & 0x4)
- rinfo->dviDisp_type = MT_LCD;
- else if (tmp & 0x200)
- rinfo->dviDisp_type = MT_CRT;
- else if (tmp & 0x10)
- rinfo->dviDisp_type = MT_CTV;
- else if (tmp & 0x20)
- rinfo->dviDisp_type = MT_STV;
-
- /* secondary CRT port */
- if (tmp & 0x2)
- rinfo->crtDisp_type = MT_CRT;
- else if (tmp & 0x800)
- rinfo->crtDisp_type = MT_DFP;
- else if (tmp & 0x400)
- rinfo->crtDisp_type = MT_LCD;
- else if (tmp & 0x1000)
- rinfo->crtDisp_type = MT_CTV;
- else if (tmp & 0x2000)
- rinfo->crtDisp_type = MT_STV;
- } else {
- rinfo->dviDisp_type = MT_NONE;
-
- tmp = INREG(FP_GEN_CNTL);
-
- if (tmp & FP_EN_TMDS)
- rinfo->crtDisp_type = MT_DFP;
- else
- rinfo->crtDisp_type = MT_CRT;
- }
-}
-
-
-
-static void radeon_get_EDID(struct radeonfb_info *rinfo)
-{
-#ifdef CONFIG_PPC_OF
- if (!radeon_get_EDID_OF(rinfo))
- RTRACE("radeonfb: could not retrieve EDID from OF\n");
-#else
- /* XXX use other methods later */
-#endif
-}
-
-
-#ifdef CONFIG_PPC_OF
-static int radeon_get_EDID_OF(struct radeonfb_info *rinfo)
-{
- struct device_node *dp;
- unsigned char *pedid = NULL;
- static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", NULL };
- int i;
-
- dp = pci_device_to_OF_node(rinfo->pdev);
- while (dp != NULL) {
- for (i = 0; propnames[i] != NULL; ++i) {
- pedid = (unsigned char *)
- get_property(dp, propnames[i], NULL);
- if (pedid != NULL) {
- rinfo->EDID = pedid;
- return 1;
- }
- }
- dp = dp->child;
- }
- return 0;
-}
-#endif /* CONFIG_PPC_OF */
-
-
-static int radeon_dfp_parse_EDID(struct radeonfb_info *rinfo)
-{
- unsigned char *block = rinfo->EDID;
-
- if (!block)
- return 0;
-
- /* jump to the detailed timing block section */
- block += 54;
-
- rinfo->clock = (block[0] + (block[1] << 8));
- rinfo->panel_xres = (block[2] + ((block[4] & 0xf0) << 4));
- rinfo->hblank = (block[3] + ((block[4] & 0x0f) << 8));
- rinfo->panel_yres = (block[5] + ((block[7] & 0xf0) << 4));
- rinfo->vblank = (block[6] + ((block[7] & 0x0f) << 8));
- rinfo->hOver_plus = (block[8] + ((block[11] & 0xc0) << 2));
- rinfo->hSync_width = (block[9] + ((block[11] & 0x30) << 4));
- rinfo->vOver_plus = ((block[10] >> 4) + ((block[11] & 0x0c) << 2));
- rinfo->vSync_width = ((block[10] & 0x0f) + ((block[11] & 0x03) << 4));
- rinfo->interlaced = ((block[17] & 0x80) >> 7);
- rinfo->synct = ((block[17] & 0x18) >> 3);
- rinfo->misc = ((block[17] & 0x06) >> 1);
- rinfo->hAct_high = rinfo->vAct_high = 0;
- if (rinfo->synct == 3) {
- if (rinfo->misc & 2)
- rinfo->hAct_high = 1;
- if (rinfo->misc & 1)
- rinfo->vAct_high = 1;
- }
-
- printk("radeonfb: detected DFP panel size from EDID: %dx%d\n",
- rinfo->panel_xres, rinfo->panel_yres);
-
- rinfo->got_dfpinfo = 1;
-
- return 1;
-}
-
-
-static void radeon_update_default_var(struct radeonfb_info *rinfo)
-{
- struct fb_var_screeninfo *var = &radeonfb_default_var;
-
- var->xres = rinfo->panel_xres;
- var->yres = rinfo->panel_yres;
- var->xres_virtual = rinfo->panel_xres;
- var->yres_virtual = rinfo->panel_yres;
- var->xoffset = var->yoffset = 0;
- var->bits_per_pixel = 8;
- var->pixclock = 100000000 / rinfo->clock;
- var->left_margin = (rinfo->hblank - rinfo->hOver_plus - rinfo->hSync_width);
- var->right_margin = rinfo->hOver_plus;
- var->upper_margin = (rinfo->vblank - rinfo->vOver_plus - rinfo->vSync_width);
- var->lower_margin = rinfo->vOver_plus;
- var->hsync_len = rinfo->hSync_width;
- var->vsync_len = rinfo->vSync_width;
- var->sync = 0;
- if (rinfo->synct == 3) {
- if (rinfo->hAct_high)
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (rinfo->vAct_high)
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
- }
-
- var->vmode = 0;
- if (rinfo->interlaced)
- var->vmode |= FB_VMODE_INTERLACED;
-
- rinfo->use_default_var = 1;
-}
-
-
-static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo)
-{
- char __iomem *fpbiosstart, *tmp, *tmp0;
- char stmp[30];
- int i;
-
- if (!rinfo->bios_seg)
- return 0;
-
- if (!(fpbiosstart = rinfo->bios_seg + readw(rinfo->bios_seg + 0x48))) {
- printk("radeonfb: Failed to detect DFP panel info using BIOS\n");
- return 0;
- }
-
- if (!(tmp = rinfo->bios_seg + readw(fpbiosstart + 0x40))) {
- printk("radeonfb: Failed to detect DFP panel info using BIOS\n");
- return 0;
- }
-
- for(i=0; i<24; i++)
- stmp[i] = readb(tmp+i+1);
- stmp[24] = 0;
- printk("radeonfb: panel ID string: %s\n", stmp);
- rinfo->panel_xres = readw(tmp + 25);
- rinfo->panel_yres = readw(tmp + 27);
- printk("radeonfb: detected DFP panel size from BIOS: %dx%d\n",
- rinfo->panel_xres, rinfo->panel_yres);
-
- for(i=0; i<32; i++) {
- tmp0 = rinfo->bios_seg + readw(tmp+64+i*2);
- if (tmp0 == 0)
- break;
- if ((readw(tmp0) == rinfo->panel_xres) &&
- (readw(tmp0+2) == rinfo->panel_yres)) {
- rinfo->hblank = (readw(tmp0+17) - readw(tmp0+19)) * 8;
- rinfo->hOver_plus = ((readw(tmp0+21) - readw(tmp0+19) -1) * 8) & 0x7fff;
- rinfo->hSync_width = readb(tmp0+23) * 8;
- rinfo->vblank = readw(tmp0+24) - readw(tmp0+26);
- rinfo->vOver_plus = (readw(tmp0+28) & 0x7ff) - readw(tmp0+26);
- rinfo->vSync_width = (readw(tmp0+28) & 0xf800) >> 11;
- rinfo->clock = readw(tmp0+9);
-
- rinfo->got_dfpinfo = 1;
- return 1;
- }
- }
-
- return 0;
-}
-
-
-
-static int radeon_get_dfpinfo (struct radeonfb_info *rinfo)
-{
- unsigned int tmp;
- unsigned short a, b;
-
- if (radeon_get_dfpinfo_BIOS(rinfo))
- radeon_update_default_var(rinfo);
-
- if (radeon_dfp_parse_EDID(rinfo))
- radeon_update_default_var(rinfo);
-
- if (!rinfo->got_dfpinfo) {
- /*
- * it seems all else has failed now and we
- * resort to probing registers for our DFP info
- */
- if (panel_yres) {
- rinfo->panel_yres = panel_yres;
- } else {
- tmp = INREG(FP_VERT_STRETCH);
- tmp &= 0x00fff000;
- rinfo->panel_yres = (unsigned short)(tmp >> 0x0c) + 1;
- }
-
- switch (rinfo->panel_yres) {
- case 480:
- rinfo->panel_xres = 640;
- break;
- case 600:
- rinfo->panel_xres = 800;
- break;
- case 768:
-#if defined(__powerpc__)
- if (rinfo->dviDisp_type == MT_LCD)
- rinfo->panel_xres = 1152;
- else
-#endif
- rinfo->panel_xres = 1024;
- break;
- case 1024:
- rinfo->panel_xres = 1280;
- break;
- case 1050:
- rinfo->panel_xres = 1400;
- break;
- case 1200:
- rinfo->panel_xres = 1600;
- break;
- default:
- printk("radeonfb: Failed to detect DFP panel size\n");
- return 0;
- }
-
- printk("radeonfb: detected DFP panel size from registers: %dx%d\n",
- rinfo->panel_xres, rinfo->panel_yres);
-
- tmp = INREG(FP_CRTC_H_TOTAL_DISP);
- a = (tmp & FP_CRTC_H_TOTAL_MASK) + 4;
- b = (tmp & 0x01ff0000) >> FP_CRTC_H_DISP_SHIFT;
- rinfo->hblank = (a - b + 1) * 8;
-
- tmp = INREG(FP_H_SYNC_STRT_WID);
- rinfo->hOver_plus = (unsigned short) ((tmp & FP_H_SYNC_STRT_CHAR_MASK) >>
- FP_H_SYNC_STRT_CHAR_SHIFT) - b - 1;
- rinfo->hOver_plus *= 8;
- rinfo->hSync_width = (unsigned short) ((tmp & FP_H_SYNC_WID_MASK) >>
- FP_H_SYNC_WID_SHIFT);
- rinfo->hSync_width *= 8;
- tmp = INREG(FP_CRTC_V_TOTAL_DISP);
- a = (tmp & FP_CRTC_V_TOTAL_MASK) + 1;
- b = (tmp & FP_CRTC_V_DISP_MASK) >> FP_CRTC_V_DISP_SHIFT;
- rinfo->vblank = a - b /* + 24 */ ;
-
- tmp = INREG(FP_V_SYNC_STRT_WID);
- rinfo->vOver_plus = (unsigned short) (tmp & FP_V_SYNC_STRT_MASK)
- - b + 1;
- rinfo->vSync_width = (unsigned short) ((tmp & FP_V_SYNC_WID_MASK) >>
- FP_V_SYNC_WID_SHIFT);
-
- return 1;
- }
-
- return 1;
-}
-
-
-#ifdef CONFIG_PPC_OF
-static int radeon_read_OF (struct radeonfb_info *rinfo)
-{
- struct device_node *dp;
- unsigned int *xtal;
-
- dp = pci_device_to_OF_node(rinfo->pdev);
-
- xtal = (unsigned int *) get_property(dp, "ATY,RefCLK", NULL);
-
- rinfo->pll.ref_clk = *xtal / 10;
-
- if (*xtal)
- return 1;
- else
- return 0;
-}
-#endif
-
-
-static void radeon_engine_init (struct radeonfb_info *rinfo)
-{
- u32 temp;
-
- /* disable 3D engine */
- OUTREG(RB3D_CNTL, 0);
-
- radeon_engine_reset ();
-
- radeon_fifo_wait (1);
- OUTREG(RB2D_DSTCACHE_MODE, 0);
-
- radeon_fifo_wait (1);
- temp = INREG(DEFAULT_PITCH_OFFSET);
- OUTREG(DEFAULT_PITCH_OFFSET, ((temp & 0xc0000000) |
- (rinfo->pitch << 0x16)));
-
- radeon_fifo_wait (1);
- OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
-
- radeon_fifo_wait (1);
- OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
- DEFAULT_SC_BOTTOM_MAX));
-
- temp = radeon_get_dstbpp(rinfo->depth);
- rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
- radeon_fifo_wait (1);
- OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |
- GMC_BRUSH_SOLID_COLOR |
- GMC_SRC_DATATYPE_COLOR));
-
- radeon_fifo_wait (7);
-
- /* clear line drawing regs */
- OUTREG(DST_LINE_START, 0);
- OUTREG(DST_LINE_END, 0);
-
- /* set brush color regs */
- OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
- OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
-
- /* set source color regs */
- OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
- OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
-
- /* default write mask */
- OUTREG(DP_WRITE_MSK, 0xffffffff);
-
- radeon_engine_idle ();
-}
-
-
-static int __devinit radeon_init_disp (struct radeonfb_info *rinfo)
-{
- struct fb_info *info = &rinfo->info;
- struct fb_var_screeninfo var;
-
- var = radeonfb_default_var;
- if ((radeon_init_disp_var(rinfo, &var)) < 0)
- return -1;
-
- rinfo->depth = var_to_depth(&var);
- rinfo->bpp = var.bits_per_pixel;
-
- info->var = var;
- fb_alloc_cmap(&info->cmap, 256, 0);
-
- var.activate = FB_ACTIVATE_NOW;
- return 0;
-}
-
-
-static int radeon_init_disp_var (struct radeonfb_info *rinfo,
- struct fb_var_screeninfo *var)
-{
-#ifndef MODULE
- if (mode_option)
- fb_find_mode (var, &rinfo->info, mode_option,
- NULL, 0, NULL, 8);
- else
-#endif
- if (rinfo->use_default_var)
- /* We will use the modified default far */
- *var = radeonfb_default_var;
- else
-
- fb_find_mode (var, &rinfo->info, "640x480-8@60",
- NULL, 0, NULL, 0);
-
- if (noaccel)
- var->accel_flags &= ~FB_ACCELF_TEXT;
- else
- var->accel_flags |= FB_ACCELF_TEXT;
-
- return 0;
-}
-
-
-static int radeon_do_maximize(struct radeonfb_info *rinfo,
- struct fb_var_screeninfo *var,
- struct fb_var_screeninfo *v,
- int nom, int den)
-{
- static struct {
- int xres, yres;
- } modes[] = {
- {1600, 1280},
- {1280, 1024},
- {1024, 768},
- {800, 600},
- {640, 480},
- {-1, -1}
- };
- int i;
-
- /* use highest possible virtual resolution */
- if (v->xres_virtual == -1 && v->yres_virtual == -1) {
- printk("radeonfb: using max available virtual resolution\n");
- for (i=0; modes[i].xres != -1; i++) {
- if (modes[i].xres * nom / den * modes[i].yres <
- rinfo->video_ram / 2)
- break;
- }
- if (modes[i].xres == -1) {
- printk("radeonfb: could not find virtual resolution that fits into video memory!\n");
- return -EINVAL;
- }
- v->xres_virtual = modes[i].xres;
- v->yres_virtual = modes[i].yres;
-
- printk("radeonfb: virtual resolution set to max of %dx%d\n",
- v->xres_virtual, v->yres_virtual);
- } else if (v->xres_virtual == -1) {
- v->xres_virtual = (rinfo->video_ram * den /
- (nom * v->yres_virtual * 2)) & ~15;
- } else if (v->yres_virtual == -1) {
- v->xres_virtual = (v->xres_virtual + 15) & ~15;
- v->yres_virtual = rinfo->video_ram * den /
- (nom * v->xres_virtual *2);
- } else {
- if (v->xres_virtual * nom / den * v->yres_virtual >
- rinfo->video_ram) {
- return -EINVAL;
- }
- }
-
- if (v->xres_virtual * nom / den >= 8192) {
- v->xres_virtual = 8192 * den / nom - 16;
- }
-
- if (v->xres_virtual < v->xres)
- return -EINVAL;
-
- if (v->yres_virtual < v->yres)
- return -EINVAL;
-
- return 0;
-}
-
-
-static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct radeonfb_info *rinfo = (struct radeonfb_info *) info->par;
- struct fb_var_screeninfo v;
- int nom, den;
-
- memcpy (&v, var, sizeof (v));
-
- switch (v.bits_per_pixel) {
- case 0 ... 8:
- v.bits_per_pixel = 8;
- break;
- case 9 ... 16:
- v.bits_per_pixel = 16;
- break;
- case 17 ... 24:
-#if 0 /* Doesn't seem to work */
- v.bits_per_pixel = 24;
- break;
-#endif
- return -EINVAL;
- case 25 ... 32:
- v.bits_per_pixel = 32;
- break;
- default:
- return -EINVAL;
- }
-
- switch (var_to_depth(&v)) {
- case 8:
- nom = den = 1;
- v.red.offset = v.green.offset = v.blue.offset = 0;
- v.red.length = v.green.length = v.blue.length = 8;
- v.transp.offset = v.transp.length = 0;
- break;
- case 15:
- nom = 2;
- den = 1;
- v.red.offset = 10;
- v.green.offset = 5;
- v.blue.offset = 0;
- v.red.length = v.green.length = v.blue.length = 5;
- v.transp.offset = v.transp.length = 0;
- break;
- case 16:
- nom = 2;
- den = 1;
- v.red.offset = 11;
- v.green.offset = 5;
- v.blue.offset = 0;
- v.red.length = 5;
- v.green.length = 6;
- v.blue.length = 5;
- v.transp.offset = v.transp.length = 0;
- break;
- case 24:
- nom = 4;
- den = 1;
- v.red.offset = 16;
- v.green.offset = 8;
- v.blue.offset = 0;
- v.red.length = v.blue.length = v.green.length = 8;
- v.transp.offset = v.transp.length = 0;
- break;
- case 32:
- nom = 4;
- den = 1;
- v.red.offset = 16;
- v.green.offset = 8;
- v.blue.offset = 0;
- v.red.length = v.blue.length = v.green.length = 8;
- v.transp.offset = 24;
- v.transp.length = 8;
- break;
- default:
- printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n",
- var->xres, var->yres, var->bits_per_pixel);
- return -EINVAL;
- }
-
- if (radeon_do_maximize(rinfo, var, &v, nom, den) < 0)
- return -EINVAL;
-
- if (v.xoffset < 0)
- v.xoffset = 0;
- if (v.yoffset < 0)
- v.yoffset = 0;
-
- if (v.xoffset > v.xres_virtual - v.xres)
- v.xoffset = v.xres_virtual - v.xres - 1;
-
- if (v.yoffset > v.yres_virtual - v.yres)
- v.yoffset = v.yres_virtual - v.yres - 1;
-
- v.red.msb_right = v.green.msb_right = v.blue.msb_right =
- v.transp.offset = v.transp.length =
- v.transp.msb_right = 0;
-
- if (noaccel)
- v.accel_flags = 0;
-
- memcpy(var, &v, sizeof(v));
-
- return 0;
-}
-
-
-static int radeonfb_pan_display (struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
-
- if ((var->xoffset + var->xres > var->xres_virtual)
- || (var->yoffset + var->yres > var->yres_virtual))
- return -EINVAL;
-
- if (rinfo->asleep)
- return 0;
-
- OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
- * var->bits_per_pixel / 8) & ~7);
- return 0;
-}
-
-
-static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
- unsigned long arg)
-{
- struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
- unsigned int tmp;
- u32 value = 0;
- int rc;
-
- switch (cmd) {
- /*
- * TODO: set mirror accordingly for non-Mobility chipsets with 2 CRTC's
- */
- case FBIO_RADEON_SET_MIRROR:
- switch (rinfo->arch) {
- case RADEON_R100:
- case RADEON_RV100:
- case RADEON_R200:
- case RADEON_RV200:
- case RADEON_RV250:
- case RADEON_R300:
- return -EINVAL;
- default:
- /* RADEON M6, RADEON_M7, RADEON_M9 */
- break;
- }
-
- rc = get_user(value, (__u32 __user *)arg);
-
- if (rc)
- return rc;
-
- if (value & 0x01) {
- tmp = INREG(LVDS_GEN_CNTL);
-
- tmp |= (LVDS_ON | LVDS_BLON);
- } else {
- tmp = INREG(LVDS_GEN_CNTL);
-
- tmp &= ~(LVDS_ON | LVDS_BLON);
- }
-
- OUTREG(LVDS_GEN_CNTL, tmp);
-
- if (value & 0x02) {
- tmp = INREG(CRTC_EXT_CNTL);
- tmp |= CRTC_CRT_ON;
-
- mirror = 1;
- } else {
- tmp = INREG(CRTC_EXT_CNTL);
- tmp &= ~CRTC_CRT_ON;
-
- mirror = 0;
- }
-
- OUTREG(CRTC_EXT_CNTL, tmp);
-
- break;
- case FBIO_RADEON_GET_MIRROR:
- switch (rinfo->arch) {
- case RADEON_R100:
- case RADEON_RV100:
- case RADEON_R200:
- case RADEON_RV200:
- case RADEON_RV250:
- case RADEON_R300:
- return -EINVAL;
- default:
- /* RADEON M6, RADEON_M7, RADEON_M9 */
- break;
- }
-
- tmp = INREG(LVDS_GEN_CNTL);
- if ((LVDS_ON | LVDS_BLON) & tmp)
- value |= 0x01;
-
- tmp = INREG(CRTC_EXT_CNTL);
- if (CRTC_CRT_ON & tmp)
- value |= 0x02;
-
- return put_user(value, (__u32 __user *)arg);
- default:
- return -EINVAL;
- }
-
- return -EINVAL;
-}
-
-
-static int radeonfb_blank (int blank, struct fb_info *info)
-{
- struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
- u32 val = INREG(CRTC_EXT_CNTL);
- u32 val2 = INREG(LVDS_GEN_CNTL);
-
- if (rinfo->asleep)
- return 0;
-
-#ifdef CONFIG_PMAC_BACKLIGHT
- if (rinfo->dviDisp_type == MT_LCD && _machine == _MACH_Pmac) {
- set_backlight_enable(!blank);
- return 0;
- }
-#endif
-
- /* reset it */
- val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
- CRTC_VSYNC_DIS);
- val2 &= ~(LVDS_DISPLAY_DIS);
-
- switch (blank) {
- case FB_BLANK_UNBLANK:
- case FB_BLANK_NORMAL:
- break;
- case FB_BLANK_VSYNC_SUSPEND:
- val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS);
- break;
- case FB_BLANK_HSYNC_SUSPEND:
- val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS);
- break;
- case FB_BLANK_POWERDOWN:
- val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS |
- CRTC_HSYNC_DIS);
- val2 |= (LVDS_DISPLAY_DIS);
- break;
- }
-
- switch (rinfo->dviDisp_type) {
- case MT_LCD:
- OUTREG(LVDS_GEN_CNTL, val2);
- break;
- case MT_CRT:
- default:
- OUTREG(CRTC_EXT_CNTL, val);
- break;
- }
-
- /* let fbcon do a soft blank for us */
- return (blank == FB_BLANK_NORMAL) ? 1 : 0;
-}
-
-
-static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp, struct fb_info *info)
-{
- struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
- u32 pindex, vclk_cntl;
- unsigned int i;
-
- if (regno > 255)
- return 1;
-
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- rinfo->palette[regno].red = red;
- rinfo->palette[regno].green = green;
- rinfo->palette[regno].blue = blue;
-
- /* default */
- pindex = regno;
-
- if (!rinfo->asleep) {
- vclk_cntl = INPLL(VCLK_ECP_CNTL);
- OUTPLL(VCLK_ECP_CNTL, vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
-
- if (rinfo->bpp == 16) {
- pindex = regno * 8;
-
- if (rinfo->depth == 16 && regno > 63)
- return 1;
- if (rinfo->depth == 15 && regno > 31)
- return 1;
-
- /* For 565, the green component is mixed one order below */
- if (rinfo->depth == 16) {
- OUTREG(PALETTE_INDEX, pindex>>1);
- OUTREG(PALETTE_DATA, (rinfo->palette[regno>>1].red << 16) |
- (green << 8) | (rinfo->palette[regno>>1].blue));
- green = rinfo->palette[regno<<1].green;
- }
- }
-
- if (rinfo->depth != 16 || regno < 32) {
- OUTREG(PALETTE_INDEX, pindex);
- OUTREG(PALETTE_DATA, (red << 16) | (green << 8) | blue);
- }
-
- OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
- }
- if (regno < 16) {
- switch (rinfo->depth) {
- case 15:
- ((u16 *) (info->pseudo_palette))[regno] =
- (regno << 10) | (regno << 5) | regno;
- break;
- case 16:
- ((u16 *) (info->pseudo_palette))[regno] =
- (regno << 11) | (regno << 6) | regno;
- break;
- case 24:
- ((u32 *) (info->pseudo_palette))[regno] =
- (regno << 16) | (regno << 8) | regno;
- break;
- case 32:
- i = (regno << 8) | regno;
- ((u32 *) (info->pseudo_palette))[regno] =
- (i << 16) | i;
- break;
- }
- }
- return 0;
-}
-
-
-
-static void radeon_save_state (struct radeonfb_info *rinfo,
- struct radeon_regs *save)
-{
- /* CRTC regs */
- save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
- save->crtc_ext_cntl = INREG(CRTC_EXT_CNTL);
- save->dac_cntl = INREG(DAC_CNTL);
- save->crtc_h_total_disp = INREG(CRTC_H_TOTAL_DISP);
- save->crtc_h_sync_strt_wid = INREG(CRTC_H_SYNC_STRT_WID);
- save->crtc_v_total_disp = INREG(CRTC_V_TOTAL_DISP);
- save->crtc_v_sync_strt_wid = INREG(CRTC_V_SYNC_STRT_WID);
- save->crtc_pitch = INREG(CRTC_PITCH);
-#if defined(__BIG_ENDIAN)
- save->surface_cntl = INREG(SURFACE_CNTL);
-#endif
-
- /* FP regs */
- save->fp_crtc_h_total_disp = INREG(FP_CRTC_H_TOTAL_DISP);
- save->fp_crtc_v_total_disp = INREG(FP_CRTC_V_TOTAL_DISP);
- save->fp_gen_cntl = INREG(FP_GEN_CNTL);
- save->fp_h_sync_strt_wid = INREG(FP_H_SYNC_STRT_WID);
- save->fp_horz_stretch = INREG(FP_HORZ_STRETCH);
- save->fp_v_sync_strt_wid = INREG(FP_V_SYNC_STRT_WID);
- save->fp_vert_stretch = INREG(FP_VERT_STRETCH);
- save->lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
- save->lvds_pll_cntl = INREG(LVDS_PLL_CNTL);
- save->tmds_crc = INREG(TMDS_CRC);
- save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL);
- save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL);
-}
-
-
-
-static int radeonfb_set_par (struct fb_info *info)
-{
- struct radeonfb_info *rinfo = (struct radeonfb_info *)info->par;
- struct fb_var_screeninfo *mode = &info->var;
- struct radeon_regs newmode;
- int hTotal, vTotal, hSyncStart, hSyncEnd,
- hSyncPol, vSyncStart, vSyncEnd, vSyncPol, cSync;
- u8 hsync_adj_tab[] = {0, 0x12, 9, 9, 6, 5};
- u8 hsync_fudge_fp[] = {2, 2, 0, 0, 5, 5};
- u32 dotClock = 1000000000 / mode->pixclock,
- sync, h_sync_pol, v_sync_pol;
- int freq = dotClock / 10; /* x 100 */
- int xclk_freq, vclk_freq, xclk_per_trans, xclk_per_trans_precise;
- int useable_precision, roff, ron;
- int min_bits, format = 0;
- int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid;
- int primary_mon = PRIMARY_MONITOR(rinfo);
- int depth = var_to_depth(mode);
- int accel = (mode->accel_flags & FB_ACCELF_TEXT) != 0;
-
- rinfo->xres = mode->xres;
- rinfo->yres = mode->yres;
- rinfo->xres_virtual = mode->xres_virtual;
- rinfo->yres_virtual = mode->yres_virtual;
- rinfo->pixclock = mode->pixclock;
-
- hSyncStart = mode->xres + mode->right_margin;
- hSyncEnd = hSyncStart + mode->hsync_len;
- hTotal = hSyncEnd + mode->left_margin;
-
- vSyncStart = mode->yres + mode->lower_margin;
- vSyncEnd = vSyncStart + mode->vsync_len;
- vTotal = vSyncEnd + mode->upper_margin;
-
- if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
- if (rinfo->panel_xres < mode->xres)
- rinfo->xres = mode->xres = rinfo->panel_xres;
- if (rinfo->panel_yres < mode->yres)
- rinfo->yres = mode->yres = rinfo->panel_yres;
-
- hTotal = mode->xres + rinfo->hblank;
- hSyncStart = mode->xres + rinfo->hOver_plus;
- hSyncEnd = hSyncStart + rinfo->hSync_width;
-
- vTotal = mode->yres + rinfo->vblank;
- vSyncStart = mode->yres + rinfo->vOver_plus;
- vSyncEnd = vSyncStart + rinfo->vSync_width;
- }
-
- sync = mode->sync;
- h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
- v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
-
- RTRACE("hStart = %d, hEnd = %d, hTotal = %d\n",
- hSyncStart, hSyncEnd, hTotal);
- RTRACE("vStart = %d, vEnd = %d, vTotal = %d\n",
- vSyncStart, vSyncEnd, vTotal);
-
- hsync_wid = (hSyncEnd - hSyncStart) / 8;
- vsync_wid = vSyncEnd - vSyncStart;
- if (hsync_wid == 0)
- hsync_wid = 1;
- else if (hsync_wid > 0x3f) /* max */
- hsync_wid = 0x3f;
-
- if (vsync_wid == 0)
- vsync_wid = 1;
- else if (vsync_wid > 0x1f) /* max */
- vsync_wid = 0x1f;
-
- hSyncPol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
- vSyncPol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
-
- cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
-
- format = radeon_get_dstbpp(depth);
- bytpp = mode->bits_per_pixel >> 3;
-
- if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD))
- hsync_fudge = hsync_fudge_fp[format-1];
- else
- hsync_fudge = hsync_adj_tab[format-1];
-
- hsync_start = hSyncStart - 8 + hsync_fudge;
-
- newmode.crtc_gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN |
- (format << 8);
-
- if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
- newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN;
- if (mirror)
- newmode.crtc_ext_cntl |= CRTC_CRT_ON;
-
- newmode.crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN |
- CRTC_INTERLACE_EN);
- } else {
- newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN |
- CRTC_CRT_ON;
- }
-
- newmode.dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN |
- DAC_8BIT_EN;
-
- newmode.crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) |
- (((mode->xres / 8) - 1) << 16));
-
- newmode.crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) |
- (hsync_wid << 16) | (h_sync_pol << 23));
-
- newmode.crtc_v_total_disp = ((vTotal - 1) & 0xffff) |
- ((mode->yres - 1) << 16);
-
- newmode.crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) |
- (vsync_wid << 16) | (v_sync_pol << 23));
-
- if (accel) {
- /* We first calculate the engine pitch */
- rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f)
- & ~(0x3f)) >> 6;
-
- /* Then, re-multiply it to get the CRTC pitch */
- newmode.crtc_pitch = (rinfo->pitch << 3) / ((mode->bits_per_pixel + 1) / 8);
- } else
- newmode.crtc_pitch = (mode->xres_virtual >> 3);
- newmode.crtc_pitch |= (newmode.crtc_pitch << 16);
-
-#if defined(__BIG_ENDIAN)
- /*
- * It looks like recent chips have a problem with SURFACE_CNTL,
- * setting SURF_TRANSLATION_DIS completely disables the
- * swapper as well, so we leave it unset now.
- */
- newmode.surface_cntl = 0;
-
- /* Setup swapping on both apertures, though we currently
- * only use aperture 0, enabling swapper on aperture 1
- * won't harm
- */
- switch (mode->bits_per_pixel) {
- case 16:
- newmode.surface_cntl |= NONSURF_AP0_SWP_16BPP;
- newmode.surface_cntl |= NONSURF_AP1_SWP_16BPP;
- break;
- case 24:
- case 32:
- newmode.surface_cntl |= NONSURF_AP0_SWP_32BPP;
- newmode.surface_cntl |= NONSURF_AP1_SWP_32BPP;
- break;
- }
-#endif
-
- rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f)
- & ~(0x3f)) / 64;
-
- RTRACE("h_total_disp = 0x%x\t hsync_strt_wid = 0x%x\n",
- newmode.crtc_h_total_disp, newmode.crtc_h_sync_strt_wid);
- RTRACE("v_total_disp = 0x%x\t vsync_strt_wid = 0x%x\n",
- newmode.crtc_v_total_disp, newmode.crtc_v_sync_strt_wid);
-
- newmode.xres = mode->xres;
- newmode.yres = mode->yres;
-
- rinfo->bpp = mode->bits_per_pixel;
- rinfo->depth = depth;
-
- if (freq > rinfo->pll.ppll_max)
- freq = rinfo->pll.ppll_max;
- if (freq*12 < rinfo->pll.ppll_min)
- freq = rinfo->pll.ppll_min / 12;
-
- {
- struct {
- int divider;
- int bitvalue;
- } *post_div,
- post_divs[] = {
- { 1, 0 },
- { 2, 1 },
- { 4, 2 },
- { 8, 3 },
- { 3, 4 },
- { 16, 5 },
- { 6, 6 },
- { 12, 7 },
- { 0, 0 },
- };
-
- for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
- rinfo->pll_output_freq = post_div->divider * freq;
- if (rinfo->pll_output_freq >= rinfo->pll.ppll_min &&
- rinfo->pll_output_freq <= rinfo->pll.ppll_max)
- break;
- }
-
- rinfo->post_div = post_div->divider;
- rinfo->fb_div = round_div(rinfo->pll.ref_div*rinfo->pll_output_freq,
- rinfo->pll.ref_clk);
- newmode.ppll_ref_div = rinfo->pll.ref_div;
- newmode.ppll_div_3 = rinfo->fb_div | (post_div->bitvalue << 16);
- }
- newmode.vclk_ecp_cntl = rinfo->init_state.vclk_ecp_cntl;
-
-#ifdef CONFIG_PPC_OF
- /* Gross hack for iBook with M7 until I find out a proper fix */
- if (machine_is_compatible("PowerBook4,3") && rinfo->arch == RADEON_M7)
- newmode.ppll_div_3 = 0x000600ad;
-#endif /* CONFIG_PPC_OF */
-
- RTRACE("post div = 0x%x\n", rinfo->post_div);
- RTRACE("fb_div = 0x%x\n", rinfo->fb_div);
- RTRACE("ppll_div_3 = 0x%x\n", newmode.ppll_div_3);
-
- /* DDA */
- vclk_freq = round_div(rinfo->pll.ref_clk * rinfo->fb_div,
- rinfo->pll.ref_div * rinfo->post_div);
- xclk_freq = rinfo->pll.xclk;
-
- xclk_per_trans = round_div(xclk_freq * 128, vclk_freq * mode->bits_per_pixel);
-
- min_bits = min_bits_req(xclk_per_trans);
- useable_precision = min_bits + 1;
-
- xclk_per_trans_precise = round_div((xclk_freq * 128) << (11 - useable_precision),
- vclk_freq * mode->bits_per_pixel);
-
- ron = (4 * rinfo->ram.mb + 3 * _max(rinfo->ram.trcd - 2, 0) +
- 2 * rinfo->ram.trp + rinfo->ram.twr + rinfo->ram.cl + rinfo->ram.tr2w +
- xclk_per_trans) << (11 - useable_precision);
- roff = xclk_per_trans_precise * (32 - 4);
-
- RTRACE("ron = %d, roff = %d\n", ron, roff);
- RTRACE("vclk_freq = %d, per = %d\n", vclk_freq, xclk_per_trans_precise);
-
- if ((ron + rinfo->ram.rloop) >= roff) {
- printk("radeonfb: error ron out of range\n");
- return -EINVAL;
- }
-
- newmode.dda_config = (xclk_per_trans_precise |
- (useable_precision << 16) |
- (rinfo->ram.rloop << 20));
- newmode.dda_on_off = (ron << 16) | roff;
-
- if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
- unsigned int hRatio, vRatio;
-
- /* We force the pixel clock to be always enabled. Allowing it
- * to be power managed during blanking would save power, but has
- * nasty interactions with the 2D engine & sleep code that haven't
- * been solved yet. --BenH
- */
- newmode.vclk_ecp_cntl &= ~PIXCLK_DAC_ALWAYS_ONb;
-
- if (mode->xres > rinfo->panel_xres)
- mode->xres = rinfo->panel_xres;
- if (mode->yres > rinfo->panel_yres)
- mode->yres = rinfo->panel_yres;
-
- newmode.fp_horz_stretch = (((rinfo->panel_xres / 8) - 1)
- << HORZ_PANEL_SHIFT);
- newmode.fp_vert_stretch = ((rinfo->panel_yres - 1)
- << VERT_PANEL_SHIFT);
-
- if (mode->xres != rinfo->panel_xres) {
- hRatio = round_div(mode->xres * HORZ_STRETCH_RATIO_MAX,
- rinfo->panel_xres);
- newmode.fp_horz_stretch = (((((unsigned long)hRatio) & HORZ_STRETCH_RATIO_MASK)) |
- (newmode.fp_horz_stretch &
- (HORZ_PANEL_SIZE | HORZ_FP_LOOP_STRETCH |
- HORZ_AUTO_RATIO_INC)));
- newmode.fp_horz_stretch |= (HORZ_STRETCH_BLEND |
- HORZ_STRETCH_ENABLE);
- }
- newmode.fp_horz_stretch &= ~HORZ_AUTO_RATIO;
-
- if (mode->yres != rinfo->panel_yres) {
- vRatio = round_div(mode->yres * VERT_STRETCH_RATIO_MAX,
- rinfo->panel_yres);
- newmode.fp_vert_stretch = (((((unsigned long)vRatio) & VERT_STRETCH_RATIO_MASK)) |
- (newmode.fp_vert_stretch &
- (VERT_PANEL_SIZE | VERT_STRETCH_RESERVED)));
- newmode.fp_vert_stretch |= (VERT_STRETCH_BLEND |
- VERT_STRETCH_ENABLE);
- }
- newmode.fp_vert_stretch &= ~VERT_AUTO_RATIO_EN;
-
- newmode.fp_gen_cntl = (rinfo->init_state.fp_gen_cntl & (u32)
- ~(FP_SEL_CRTC2 |
- FP_RMX_HVSYNC_CONTROL_EN |
- FP_DFP_SYNC_SEL |
- FP_CRT_SYNC_SEL |
- FP_CRTC_LOCK_8DOT |
- FP_USE_SHADOW_EN |
- FP_CRTC_USE_SHADOW_VEND |
- FP_CRT_SYNC_ALT));
-
- newmode.fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR |
- FP_CRTC_DONT_SHADOW_HEND);
-
- newmode.lvds_gen_cntl = rinfo->init_state.lvds_gen_cntl;
- newmode.lvds_pll_cntl = rinfo->init_state.lvds_pll_cntl;
- newmode.tmds_crc = rinfo->init_state.tmds_crc;
- newmode.tmds_transmitter_cntl = rinfo->init_state.tmds_transmitter_cntl;
-
- if (primary_mon == MT_LCD) {
- newmode.lvds_gen_cntl |= (LVDS_ON | LVDS_BLON);
- newmode.fp_gen_cntl &= ~(FP_FPON | FP_TMDS_EN);
- } else {
- /* DFP */
- newmode.fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
- newmode.tmds_transmitter_cntl = (TMDS_RAN_PAT_RST |
- TMDS_ICHCSEL | TMDS_PLL_EN) &
- ~(TMDS_PLLRST);
- newmode.crtc_ext_cntl &= ~CRTC_CRT_ON;
- }
-
- newmode.fp_crtc_h_total_disp = (((rinfo->hblank / 8) & 0x3ff) |
- (((mode->xres / 8) - 1) << 16));
- newmode.fp_crtc_v_total_disp = (rinfo->vblank & 0xffff) |
- ((mode->yres - 1) << 16);
- newmode.fp_h_sync_strt_wid = ((rinfo->hOver_plus & 0x1fff) |
- (hsync_wid << 16) | (h_sync_pol << 23));
- newmode.fp_v_sync_strt_wid = ((rinfo->vOver_plus & 0xfff) |
- (vsync_wid << 16) | (v_sync_pol << 23));
- }
-
- /* do it! */
- if (!rinfo->asleep) {
- radeon_write_mode (rinfo, &newmode);
- /* (re)initialize the engine */
- if (noaccel)
- radeon_engine_init (rinfo);
-
- }
- /* Update fix */
- if (accel)
- info->fix.line_length = rinfo->pitch*64;
- else
- info->fix.line_length = mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8);
- info->fix.visual = rinfo->depth == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-
-#ifdef CONFIG_BOOTX_TEXT
- /* Update debug text engine */
- btext_update_display(rinfo->fb_base_phys, mode->xres, mode->yres,
- rinfo->depth, info->fix.line_length);
-#endif
-
- return 0;
-}
-
-
-static void radeon_write_mode (struct radeonfb_info *rinfo,
- struct radeon_regs *mode)
-{
- int i;
- int primary_mon = PRIMARY_MONITOR(rinfo);
-
- radeonfb_blank(VESA_POWERDOWN, (struct fb_info *)rinfo);
-
-
- if (rinfo->arch == RADEON_M6) {
- for (i=0; i<7; i++)
- OUTREG(common_regs_m6[i].reg, common_regs_m6[i].val);
- } else {
- for (i=0; i<9; i++)
- OUTREG(common_regs[i].reg, common_regs[i].val);
- }
-
- OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
- OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
- CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS);
- OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
- OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
- OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
- OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
- OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
- OUTREG(CRTC_OFFSET, 0);
- OUTREG(CRTC_OFFSET_CNTL, 0);
- OUTREG(CRTC_PITCH, mode->crtc_pitch);
-
-#if defined(__BIG_ENDIAN)
- OUTREG(SURFACE_CNTL, mode->surface_cntl);
-#endif
-
- while ((INREG(CLOCK_CNTL_INDEX) & PPLL_DIV_SEL_MASK) !=
- PPLL_DIV_SEL_MASK) {
- OUTREGP(CLOCK_CNTL_INDEX, PPLL_DIV_SEL_MASK, 0xffff);
- }
-
- OUTPLLP(PPLL_CNTL, PPLL_RESET, 0xffff);
-
- while ((INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK) !=
- (mode->ppll_ref_div & PPLL_REF_DIV_MASK)) {
- OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
- }
-
- while ((INPLL(PPLL_DIV_3) & PPLL_FB3_DIV_MASK) !=
- (mode->ppll_div_3 & PPLL_FB3_DIV_MASK)) {
- OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK);
- }
-
- while ((INPLL(PPLL_DIV_3) & PPLL_POST3_DIV_MASK) !=
- (mode->ppll_div_3 & PPLL_POST3_DIV_MASK)) {
- OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK);
- }
-
- OUTPLL(HTOTAL_CNTL, 0);
-
- OUTPLLP(PPLL_CNTL, 0, ~PPLL_RESET);
-
-// OUTREG(DDA_CONFIG, mode->dda_config);
-// OUTREG(DDA_ON_OFF, mode->dda_on_off);
-
- if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
- OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);
- OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp);
- OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid);
- OUTREG(FP_V_SYNC_STRT_WID, mode->fp_v_sync_strt_wid);
- OUTREG(FP_HORZ_STRETCH, mode->fp_horz_stretch);
- OUTREG(FP_VERT_STRETCH, mode->fp_vert_stretch);
- OUTREG(FP_GEN_CNTL, mode->fp_gen_cntl);
- OUTREG(TMDS_CRC, mode->tmds_crc);
- OUTREG(TMDS_TRANSMITTER_CNTL, mode->tmds_transmitter_cntl);
-
- if (primary_mon == MT_LCD) {
- unsigned int tmp = INREG(LVDS_GEN_CNTL);
-
- mode->lvds_gen_cntl &= ~LVDS_STATE_MASK;
- mode->lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_STATE_MASK);
-
- if ((tmp & (LVDS_ON | LVDS_BLON)) ==
- (mode->lvds_gen_cntl & (LVDS_ON | LVDS_BLON))) {
- OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl);
- } else {
- if (mode->lvds_gen_cntl & (LVDS_ON | LVDS_BLON)) {
- udelay(1000);
- OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl);
- } else {
- OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl |
- LVDS_BLON);
- udelay(1000);
- OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl);
- }
- }
- }
- }
-
- radeonfb_blank(VESA_NO_BLANKING, (struct fb_info *)rinfo);
-
- OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
-
- return;
-}
-
-static struct fb_ops radeonfb_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = radeonfb_check_var,
- .fb_set_par = radeonfb_set_par,
- .fb_setcolreg = radeonfb_setcolreg,
- .fb_pan_display = radeonfb_pan_display,
- .fb_blank = radeonfb_blank,
- .fb_ioctl = radeonfb_ioctl,
-#if 0
- .fb_fillrect = radeonfb_fillrect,
- .fb_copyarea = radeonfb_copyarea,
- .fb_imageblit = radeonfb_imageblit,
- .fb_rasterimg = radeonfb_rasterimg,
-#else
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
-#endif
-};
-
-
-static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
-{
- struct fb_info *info;
-
- info = &rinfo->info;
-
- info->par = rinfo;
- info->pseudo_palette = rinfo->pseudo_palette;
- info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
- info->fbops = &radeonfb_ops;
- info->screen_base = rinfo->fb_base;
-
- /* Fill fix common fields */
- strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
- info->fix.smem_start = rinfo->fb_base_phys;
- info->fix.smem_len = rinfo->video_ram;
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- info->fix.xpanstep = 8;
- info->fix.ypanstep = 1;
- info->fix.ywrapstep = 0;
- info->fix.type_aux = 0;
- info->fix.mmio_start = rinfo->mmio_base_phys;
- info->fix.mmio_len = RADEON_REGSIZE;
- if (noaccel)
- info->fix.accel = FB_ACCEL_NONE;
- else
- info->fix.accel = FB_ACCEL_ATI_RADEON;
-
- if (radeon_init_disp (rinfo) < 0)
- return -1;
-
- return 0;
-}
-
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-
-/* TODO: Dbl check these tables, we don't go up to full ON backlight
- * in these, possibly because we noticed MacOS doesn't, but I'd prefer
- * having some more official numbers from ATI
- */
-static int backlight_conv_m6[] = {
- 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,
- 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
-};
-static int backlight_conv_m7[] = {
- 0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81,
- 0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9
-};
-
-#define BACKLIGHT_LVDS_OFF
-#undef BACKLIGHT_DAC_OFF
-
-/* We turn off the LCD completely instead of just dimming the backlight.
- * This provides some greater power saving and the display is useless
- * without backlight anyway.
- */
-
-static int radeon_set_backlight_enable(int on, int level, void *data)
-{
- struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
- unsigned int lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
- int* conv_table;
-
- /* Pardon me for that hack... maybe some day we can figure
- * out in what direction backlight should work on a given
- * panel ?
- */
- if ((rinfo->arch == RADEON_M7 || rinfo->arch == RADEON_M9)
- && !machine_is_compatible("PowerBook4,3"))
- conv_table = backlight_conv_m7;
- else
- conv_table = backlight_conv_m6;
-
- lvds_gen_cntl |= (LVDS_BL_MOD_EN | LVDS_BLON);
- if (on && (level > BACKLIGHT_OFF)) {
- lvds_gen_cntl |= LVDS_DIGON;
- if (!(lvds_gen_cntl & LVDS_ON)) {
- lvds_gen_cntl &= ~LVDS_BLON;
- OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
- (void)INREG(LVDS_GEN_CNTL);
- mdelay(10);
- lvds_gen_cntl |= LVDS_BLON;
- OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
- }
- lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
- lvds_gen_cntl |= (conv_table[level] <<
- LVDS_BL_MOD_LEVEL_SHIFT);
- lvds_gen_cntl |= (LVDS_ON | LVDS_EN);
- lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
- } else {
- lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
- lvds_gen_cntl |= (conv_table[0] <<
- LVDS_BL_MOD_LEVEL_SHIFT);
- lvds_gen_cntl |= LVDS_DISPLAY_DIS;
- OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
- udelay(10);
- lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGON);
- }
-
- OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
- rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
- rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
-
- return 0;
-}
-
-static int radeon_set_backlight_level(int level, void *data)
-{
- return radeon_set_backlight_enable(1, level, data);
-}
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
-
-#ifdef CONFIG_PMAC_PBOOK
-
-static u32 dbg_clk;
-
-/*
- * Radeon M6 Power Management code. This code currently only supports
- * the mobile chips, it's based from some informations provided by ATI
- * along with hours of tracing of MacOS drivers
- */
-
-static void radeon_pm_save_regs(struct radeonfb_info *rinfo)
-{
- rinfo->save_regs[0] = INPLL(PLL_PWRMGT_CNTL);
- rinfo->save_regs[1] = INPLL(CLK_PWRMGT_CNTL);
- rinfo->save_regs[2] = INPLL(MCLK_CNTL);
- rinfo->save_regs[3] = INPLL(SCLK_CNTL);
- rinfo->save_regs[4] = INPLL(CLK_PIN_CNTL);
- rinfo->save_regs[5] = INPLL(VCLK_ECP_CNTL);
- rinfo->save_regs[6] = INPLL(PIXCLKS_CNTL);
- rinfo->save_regs[7] = INPLL(MCLK_MISC);
- rinfo->save_regs[8] = INPLL(P2PLL_CNTL);
-
- rinfo->save_regs[9] = INREG(DISP_MISC_CNTL);
- rinfo->save_regs[10] = INREG(DISP_PWR_MAN);
- rinfo->save_regs[11] = INREG(LVDS_GEN_CNTL);
- rinfo->save_regs[12] = INREG(LVDS_PLL_CNTL);
- rinfo->save_regs[13] = INREG(TV_DAC_CNTL);
- rinfo->save_regs[14] = INREG(BUS_CNTL1);
- rinfo->save_regs[15] = INREG(CRTC_OFFSET_CNTL);
- rinfo->save_regs[16] = INREG(AGP_CNTL);
- rinfo->save_regs[17] = (INREG(CRTC_GEN_CNTL) & 0xfdffffff) | 0x04000000;
- rinfo->save_regs[18] = (INREG(CRTC2_GEN_CNTL) & 0xfdffffff) | 0x04000000;
- rinfo->save_regs[19] = INREG(GPIOPAD_A);
- rinfo->save_regs[20] = INREG(GPIOPAD_EN);
- rinfo->save_regs[21] = INREG(GPIOPAD_MASK);
- rinfo->save_regs[22] = INREG(ZV_LCDPAD_A);
- rinfo->save_regs[23] = INREG(ZV_LCDPAD_EN);
- rinfo->save_regs[24] = INREG(ZV_LCDPAD_MASK);
- rinfo->save_regs[25] = INREG(GPIO_VGA_DDC);
- rinfo->save_regs[26] = INREG(GPIO_DVI_DDC);
- rinfo->save_regs[27] = INREG(GPIO_MONID);
- rinfo->save_regs[28] = INREG(GPIO_CRT2_DDC);
-
- rinfo->save_regs[29] = INREG(SURFACE_CNTL);
- rinfo->save_regs[30] = INREG(MC_FB_LOCATION);
- rinfo->save_regs[31] = INREG(DISPLAY_BASE_ADDR);
- rinfo->save_regs[32] = INREG(MC_AGP_LOCATION);
- rinfo->save_regs[33] = INREG(CRTC2_DISPLAY_BASE_ADDR);
-}
-
-static void radeon_pm_restore_regs(struct radeonfb_info *rinfo)
-{
- OUTPLL(P2PLL_CNTL, rinfo->save_regs[8] & 0xFFFFFFFE); /* First */
-
- OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]);
- OUTPLL(CLK_PWRMGT_CNTL, rinfo->save_regs[1]);
- OUTPLL(MCLK_CNTL, rinfo->save_regs[2]);
- OUTPLL(SCLK_CNTL, rinfo->save_regs[3]);
- OUTPLL(CLK_PIN_CNTL, rinfo->save_regs[4]);
- OUTPLL(VCLK_ECP_CNTL, rinfo->save_regs[5]);
- OUTPLL(PIXCLKS_CNTL, rinfo->save_regs[6]);
- OUTPLL(MCLK_MISC, rinfo->save_regs[7]);
-
- OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
- OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]);
- OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11]);
- OUTREG(LVDS_PLL_CNTL,rinfo->save_regs[12]);
- OUTREG(TV_DAC_CNTL, rinfo->save_regs[13]);
- OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
- OUTREG(CRTC_OFFSET_CNTL, rinfo->save_regs[15]);
- OUTREG(AGP_CNTL, rinfo->save_regs[16]);
- OUTREG(CRTC_GEN_CNTL, rinfo->save_regs[17]);
- OUTREG(CRTC2_GEN_CNTL, rinfo->save_regs[18]);
-
- // wait VBL before that one ?
- OUTPLL(P2PLL_CNTL, rinfo->save_regs[8]);
-
- OUTREG(GPIOPAD_A, rinfo->save_regs[19]);
- OUTREG(GPIOPAD_EN, rinfo->save_regs[20]);
- OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]);
- OUTREG(ZV_LCDPAD_A, rinfo->save_regs[22]);
- OUTREG(ZV_LCDPAD_EN, rinfo->save_regs[23]);
- OUTREG(ZV_LCDPAD_MASK, rinfo->save_regs[24]);
- OUTREG(GPIO_VGA_DDC, rinfo->save_regs[25]);
- OUTREG(GPIO_DVI_DDC, rinfo->save_regs[26]);
- OUTREG(GPIO_MONID, rinfo->save_regs[27]);
- OUTREG(GPIO_CRT2_DDC, rinfo->save_regs[28]);
-}
-
-static void radeon_pm_disable_iopad(struct radeonfb_info *rinfo)
-{
- OUTREG(GPIOPAD_MASK, 0x0001ffff);
- OUTREG(GPIOPAD_EN, 0x00000400);
- OUTREG(GPIOPAD_A, 0x00000000);
- OUTREG(ZV_LCDPAD_MASK, 0x00000000);
- OUTREG(ZV_LCDPAD_EN, 0x00000000);
- OUTREG(ZV_LCDPAD_A, 0x00000000);
- OUTREG(GPIO_VGA_DDC, 0x00030000);
- OUTREG(GPIO_DVI_DDC, 0x00000000);
- OUTREG(GPIO_MONID, 0x00030000);
- OUTREG(GPIO_CRT2_DDC, 0x00000000);
-}
-
-static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo)
-{
-//
-// u32 reg;
-//
-// OUTPLL(P2PLL_REF_DIV, 0x0c);
-//
-// .../... figure out what macos does here
-}
-
-static void radeon_pm_low_current(struct radeonfb_info *rinfo)
-{
- u32 reg;
-
- reg = INREG(BUS_CNTL1);
- reg &= ~BUS_CNTL1_MOBILE_PLATFORM_SEL_MASK;
- reg |= BUS_CNTL1_AGPCLK_VALID | (1<<BUS_CNTL1_MOBILE_PLATFORM_SEL_SHIFT);
- OUTREG(BUS_CNTL1, reg);
-
- reg = INPLL(PLL_PWRMGT_CNTL);
- reg |= PLL_PWRMGT_CNTL_SPLL_TURNOFF | PLL_PWRMGT_CNTL_PPLL_TURNOFF |
- PLL_PWRMGT_CNTL_P2PLL_TURNOFF | PLL_PWRMGT_CNTL_TVPLL_TURNOFF;
- reg &= ~PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK;
- reg &= ~PLL_PWRMGT_CNTL_MOBILE_SU;
- OUTPLL(PLL_PWRMGT_CNTL, reg);
-
-// reg = INPLL(TV_PLL_CNTL1);
-// reg |= TV_PLL_CNTL1__TVPLL_RESET | TV_PLL_CNTL1__TVPLL_SLEEP;
-// OUTPLL(TV_PLL_CNTL1, reg);
-
- reg = INREG(TV_DAC_CNTL);
- reg &= ~(TV_DAC_CNTL_BGADJ_MASK |TV_DAC_CNTL_DACADJ_MASK);
- reg |=TV_DAC_CNTL_BGSLEEP | TV_DAC_CNTL_RDACPD | TV_DAC_CNTL_GDACPD |
- TV_DAC_CNTL_BDACPD |
- (8<<TV_DAC_CNTL_BGADJ__SHIFT) | (8<<TV_DAC_CNTL_DACADJ__SHIFT);
- OUTREG(TV_DAC_CNTL, reg);
-
- reg = INREG(TMDS_TRANSMITTER_CNTL);
- reg &= ~(TMDS_PLL_EN |TMDS_PLLRST);
- OUTREG(TMDS_TRANSMITTER_CNTL, reg);
-
-// lvds_pll_cntl = regr32(g, LVDS_PLL_CNTL);
-// lvds_pll_cntl &= ~LVDS_PLL_CNTL__LVDS_PLL_EN;
-// lvds_pll_cntl |= LVDS_PLL_CNTL__LVDS_PLL_RESET;
-// regw32(g, LVDS_PLL_CNTL, lvds_pll_cntl);
-
- reg = INREG(DAC_CNTL);
- reg &= ~DAC_CMP_EN;
- OUTREG(DAC_CNTL, reg);
-
- reg = INREG(DAC_CNTL2);
- reg &= ~DAC2_CMP_EN;
- OUTREG(DAC_CNTL2, reg);
-
- reg = INREG(TV_DAC_CNTL);
- reg &= ~TV_DAC_CNTL_DETECT;
- OUTREG(TV_DAC_CNTL, reg);
-}
-
-static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo)
-{
- /* This code is disabled. It does what is in the pm_init
- * function of the MacOS driver code ATI sent me. However,
- * it doesn't fix my sleep problem, and is causing other issues
- * on wakeup (bascially the machine dying when switching consoles
- * I haven't had time to investigate this yet
- */
-#if 0
- u32 disp_misc_cntl;
- u32 disp_pwr_man;
- u32 temp;
-
- // set SPLL, MPLL, PPLL, P2PLL, TVPLL, SCLK, MCLK, PCLK, P2CLK,
- // TCLK and TEST_MODE to 0
- temp = INPLL(CLK_PWRMGT_CNTL);
- OUTPLL(CLK_PWRMGT_CNTL , temp & ~0xc00002ff);
-
- // Turn on Power Management
- temp = INPLL(CLK_PWRMGT_CNTL);
- OUTPLL(CLK_PWRMGT_CNTL , temp | 0x00000400);
-
- // Turn off display clock if using mobile chips
- temp = INPLL(CLK_PWRMGT_CNTL);
- OUTREG(CLK_PWRMGT_CNTL , temp | 0x00100000);
-
- // Force PIXCLK_ALWAYS_ON and PIXCLK_DAC_ALWAYS_ON
- temp = INPLL(VCLK_ECP_CNTL);
- OUTPLL(VCLK_ECP_CNTL, temp & ~0x000000c0);
-
- // Force ECP_FORCE_ON to 1
- temp = INPLL(VCLK_ECP_CNTL);
- OUTPLL(VCLK_ECP_CNTL, temp | 0x00040000);
-
- // Force PIXCLK_BLEND_ALWAYS_ON and PIXCLK_GV_ALWAYS_ON
- temp = INPLL(PIXCLKS_CNTL);
- OUTPLL(PIXCLKS_CNTL, temp & ~0x00001800);
-
- // Forcing SCLK_CNTL to ON
- OUTPLL(SCLK_CNTL, (INPLL(SCLK_CNTL)& 0x00000007) | 0xffff8000 );
-
- // Set PM control over XTALIN pad
- temp = INPLL(CLK_PIN_CNTL);
- OUTPLL(CLK_PIN_CNTL, temp | 0x00080000);
-
- // Force MCLK and YCLK and MC as dynamic
- temp = INPLL(MCLK_CNTL);
- OUTPLL(MCLK_CNTL, temp & 0xffeaffff);
-
- // PLL_TURNOFF
- temp = INPLL(PLL_PWRMGT_CNTL);
- OUTPLL(PLL_PWRMGT_CNTL, temp | 0x0000001f);
-
- // set MOBILE_SU to 1 if M6 or DDR64 is detected
- temp = INPLL(PLL_PWRMGT_CNTL);
- OUTPLL(PLL_PWRMGT_CNTL, temp | 0x00010000);
-
- // select PM access mode (PM_MODE_SEL) (use ACPI mode)
-// temp = INPLL(PLL_PWRMGT_CNTL);
-// OUTPLL(PLL_PWRMGT_CNTL, temp | 0x00002000);
- temp = INPLL(PLL_PWRMGT_CNTL);
- OUTPLL(PLL_PWRMGT_CNTL, temp & ~0x00002000);
-
- // set DISP_MISC_CNTL register
- disp_misc_cntl = INREG(DISP_MISC_CNTL);
- disp_misc_cntl &= ~( DISP_MISC_CNTL_SOFT_RESET_GRPH_PP |
- DISP_MISC_CNTL_SOFT_RESET_SUBPIC_PP |
- DISP_MISC_CNTL_SOFT_RESET_OV0_PP |
- DISP_MISC_CNTL_SOFT_RESET_GRPH_SCLK |
- DISP_MISC_CNTL_SOFT_RESET_SUBPIC_SCLK |
- DISP_MISC_CNTL_SOFT_RESET_OV0_SCLK |
- DISP_MISC_CNTL_SOFT_RESET_GRPH2_PP |
- DISP_MISC_CNTL_SOFT_RESET_GRPH2_SCLK |
- DISP_MISC_CNTL_SOFT_RESET_LVDS |
- DISP_MISC_CNTL_SOFT_RESET_TMDS |
- DISP_MISC_CNTL_SOFT_RESET_DIG_TMDS |
- DISP_MISC_CNTL_SOFT_RESET_TV);
- OUTREG(DISP_MISC_CNTL, disp_misc_cntl);
-
- // set DISP_PWR_MAN register
- disp_pwr_man = INREG(DISP_PWR_MAN);
- // clau - 9.29.2000 - changes made to bit23:18 to set to 1 as requested by George
- disp_pwr_man |= (DISP_PWR_MAN_DIG_TMDS_ENABLE_RST |
- DISP_PWR_MAN_TV_ENABLE_RST |
- // DISP_PWR_MAN_AUTO_PWRUP_EN |
- DISP_PWR_MAN_DISP_D3_GRPH_RST |
- DISP_PWR_MAN_DISP_D3_SUBPIC_RST |
- DISP_PWR_MAN_DISP_D3_OV0_RST |
- DISP_PWR_MAN_DISP_D1D2_GRPH_RST |
- DISP_PWR_MAN_DISP_D1D2_SUBPIC_RST |
- DISP_PWR_MAN_DISP_D1D2_OV0_RST);
- disp_pwr_man &= ~(DISP_PWR_MAN_DISP_PWR_MAN_D3_CRTC_EN |
- DISP_PWR_MAN_DISP2_PWR_MAN_D3_CRTC2_EN|
- DISP_PWR_MAN_DISP_D3_RST |
- DISP_PWR_MAN_DISP_D3_REG_RST);
- OUTREG(DISP_PWR_MAN, disp_pwr_man);
-
- // clau - 10.24.2000
- // - add in setting for BUS_CNTL1 b27:26 = 0x01 and b31 = 0x1
- // - add in setting for AGP_CNTL b7:0 = 0x20
- // - add in setting for DVI_DDC_DATA_OUT_EN b17:16 = 0x0
-
- // the following settings (two lines) are applied at a later part of this function, only on mobile platform
- // requres -mobile flag
- OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & 0xf3ffffff) | 0x04000000);
- OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | 0x80000000);
- OUTREG(AGP_CNTL, (INREG(AGP_CNTL) & 0xffffff00) | 0x20);
- OUTREG(GPIO_DVI_DDC, INREG(GPIO_DVI_DDC) & 0xfffcffff);
-
- // yulee - 12.12.2000
- // A12 only
- // EN_MCLK_TRISTATE_IN_SUSPEND@MCLK_MISC = 1
- // ACCESS_REGS_IN_SUSPEND@CLK_PIN_CNTL = 0
- // only on mobile platform
- OUTPLL(MCLK_MISC, INPLL(MCLK_MISC) | 0x00040000 );
-
- // yulee -12.12.2000
- // AGPCLK_VALID@BUS_CNTL1 = 1
- // MOBILE_PLATFORM_SEL@BUS_CNTL1 = 01
- // CRTC_STEREO_SYNC_OUT_EN@CRTC_OFFSET_CNTL = 0
- // CG_CLK_TO_OUTPIN@CLK_PIN_CNTL = 0
- // only on mobile platform
- OUTPLL(CLK_PIN_CNTL, INPLL(CLK_PIN_CNTL ) & 0xFFFFF7FF );
- OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1 ) & 0xF3FFFFFF) | 0x84000000 );
- OUTREG(CRTC_OFFSET_CNTL, INREG(CRTC_OFFSET_CNTL ) & 0xFFEFFFFF );
-
- mdelay(100);
-#endif
-
- /* Disable CRTCs */
- OUTREG(CRTC_GEN_CNTL, (INREG(CRTC_GEN_CNTL) & ~CRTC_EN) | CRTC_DISP_REQ_EN_B);
- OUTREG(CRTC2_GEN_CNTL, (INREG(CRTC2_GEN_CNTL) & ~CRTC2_EN) | CRTC2_DISP_REQ_EN_B);
- (void)INREG(CRTC2_GEN_CNTL);
- mdelay(17);
-}
-
-static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
-{
- u16 pwr_cmd;
-
- if (!rinfo->pm_reg)
- return;
-
- /* Set the chip into appropriate suspend mode (we use D2,
- * D3 would require a compete re-initialization of the chip,
- * including PCI config registers, clocks, AGP conf, ...)
- */
- if (suspend) {
- /* According to ATI, we should program V2CLK here, I have
- * to verify what's up exactly
- */
- /* Save some registers */
- radeon_pm_save_regs(rinfo);
-
- /* Check that on M7 too, might work might not. M7 may also
- * need explicit enabling of PM
- */
- if (rinfo->arch == RADEON_M6) {
- /* Program V2CLK */
- radeon_pm_program_v2clk(rinfo);
-
- /* Disable IO PADs */
- radeon_pm_disable_iopad(rinfo);
-
- /* Set low current */
- radeon_pm_low_current(rinfo);
-
- /* Prepare chip for power management */
- radeon_pm_setup_for_suspend(rinfo);
-
- /* Reset the MDLL */
- OUTPLL(MDLL_CKO, INPLL(MDLL_CKO) | MCKOA_RESET);
- (void)INPLL(MDLL_RDCKA);
- OUTPLL(MDLL_CKO, INPLL(MDLL_CKO) & ~MCKOA_RESET);
- (void)INPLL(MDLL_RDCKA);
- }
-
- /* Switch PCI power managment to D2. */
- for (;;) {
- pci_read_config_word(
- rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
- &pwr_cmd);
- if (pwr_cmd & 2)
- break;
- pci_write_config_word(
- rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
- (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2);
- mdelay(500);
- }
- } else {
- /* Switch back PCI powermanagment to D0 */
- mdelay(200);
- pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0);
- mdelay(500);
-
- dbg_clk = INPLL(1);
-
- /* Do we need that on M7 ? */
- if (rinfo->arch == RADEON_M6) {
- /* Restore the MDLL */
- OUTPLL(MDLL_CKO, INPLL(MDLL_CKO) & ~MCKOA_RESET);
- (void)INPLL(MDLL_CKO);
- }
-
- /* Restore some registers */
- radeon_pm_restore_regs(rinfo);
- }
-}
-
-/*
- * Save the contents of the framebuffer when we go to sleep,
- * and restore it when we wake up again.
- */
-
-int radeon_sleep_notify(struct pmu_sleep_notifier *self, int when)
-{
- struct radeonfb_info *rinfo;
-
- for (rinfo = board_list; rinfo != NULL; rinfo = rinfo->next) {
- struct fb_fix_screeninfo fix;
- int nb;
- struct display *disp;
-
- disp = (rinfo->currcon < 0) ? rinfo->info.disp : &fb_display[rinfo->currcon];
-
- switch (rinfo->arch) {
- case RADEON_M6:
- case RADEON_M7:
- case RADEON_M9:
- break;
- default:
- return PBOOK_SLEEP_REFUSE;
- }
-
- radeonfb_get_fix(&fix, fg_console, (struct fb_info *)rinfo);
- nb = fb_display[fg_console].var.yres * fix.line_length;
-
- switch (when) {
- case PBOOK_SLEEP_NOW:
- acquire_console_sem();
- disp->dispsw = &fbcon_dummy;
-
- if (!noaccel) {
- /* Make sure engine is reset */
- radeon_engine_reset();
- radeon_engine_idle();
- }
-
- /* Blank display and LCD */
- radeonfb_blank(VESA_POWERDOWN+1,
- (struct fb_info *)rinfo);
-
- /* Sleep */
- rinfo->asleep = 1;
- radeon_set_suspend(rinfo, 1);
- release_console_sem();
-
- break;
- case PBOOK_WAKE:
- acquire_console_sem();
- /* Wakeup */
- radeon_set_suspend(rinfo, 0);
-
- if (!noaccel)
- radeon_engine_init(rinfo);
- rinfo->asleep = 0;
- radeon_set_dispsw(rinfo, disp);
- radeon_load_video_mode(rinfo, &disp->var);
- do_install_cmap(rinfo->currcon < 0 ? 0 : rinfo->currcon,
- (struct fb_info *)rinfo);
-
- radeonfb_blank(0, (struct fb_info *)rinfo);
- release_console_sem();
- printk("CLK_PIN_CNTL on wakeup was: %08x\n", dbg_clk);
- break;
- }
- }
-
- return PBOOK_SLEEP_OK;
-}
-
-#endif /* CONFIG_PMAC_PBOOK */
-
-static int radeonfb_pci_register (struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- struct radeonfb_info *rinfo;
- struct radeon_chip_info *rci = &radeon_chip_info[ent->driver_data];
- u32 tmp;
-
- RTRACE("radeonfb_pci_register BEGIN\n");
-
- /* Enable device in PCI config */
- if (pci_enable_device(pdev) != 0) {
- printk(KERN_ERR "radeonfb: Cannot enable PCI device\n");
- return -ENODEV;
- }
-
- rinfo = kmalloc (sizeof (struct radeonfb_info), GFP_KERNEL);
- if (!rinfo) {
- printk ("radeonfb: could not allocate memory\n");
- return -ENODEV;
- }
-
- memset (rinfo, 0, sizeof (struct radeonfb_info));
- //info = &rinfo->info;
- rinfo->pdev = pdev;
- strcpy(rinfo->name, rci->name);
- rinfo->arch = rci->arch;
-
- /* Set base addrs */
- rinfo->fb_base_phys = pci_resource_start (pdev, 0);
- rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
-
- /* request the mem regions */
- if (!request_mem_region (rinfo->fb_base_phys,
- pci_resource_len(pdev, 0), "radeonfb")) {
- printk ("radeonfb: cannot reserve FB region\n");
- kfree (rinfo);
- return -ENODEV;
- }
-
- if (!request_mem_region (rinfo->mmio_base_phys,
- pci_resource_len(pdev, 2), "radeonfb")) {
- printk ("radeonfb: cannot reserve MMIO region\n");
- release_mem_region (rinfo->fb_base_phys,
- pci_resource_len(pdev, 0));
- kfree (rinfo);
- return -ENODEV;
- }
-
- /* map the regions */
- rinfo->mmio_base = ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE);
- if (!rinfo->mmio_base) {
- printk ("radeonfb: cannot map MMIO\n");
- release_mem_region (rinfo->mmio_base_phys,
- pci_resource_len(pdev, 2));
- release_mem_region (rinfo->fb_base_phys,
- pci_resource_len(pdev, 0));
- kfree (rinfo);
- return -ENODEV;
- }
-
- rinfo->chipset = pdev->device;
-
- switch (rinfo->arch) {
- case RADEON_R100:
- rinfo->hasCRTC2 = 0;
- break;
- default:
- /* all the rest have it */
- rinfo->hasCRTC2 = 1;
- break;
- }
-#if 0
- if (rinfo->arch == RADEON_M7) {
- /*
- * Noticed some errors in accel with M7, will have to work these out...
- */
- noaccel = 1;
- }
-#endif
- if (mirror)
- printk("radeonfb: mirroring display to CRT\n");
-
- /* framebuffer size */
- tmp = INREG(CONFIG_MEMSIZE);
-
- /* mem size is bits [28:0], mask off the rest */
- rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
-
- /* ram type */
- tmp = INREG(MEM_SDRAM_MODE_REG);
- switch ((MEM_CFG_TYPE & tmp) >> 30) {
- case 0:
- /* SDR SGRAM (2:1) */
- strcpy(rinfo->ram_type, "SDR SGRAM");
- rinfo->ram.ml = 4;
- rinfo->ram.mb = 4;
- rinfo->ram.trcd = 1;
- rinfo->ram.trp = 2;
- rinfo->ram.twr = 1;
- rinfo->ram.cl = 2;
- rinfo->ram.loop_latency = 16;
- rinfo->ram.rloop = 16;
-
- break;
- case 1:
- /* DDR SGRAM */
- strcpy(rinfo->ram_type, "DDR SGRAM");
- rinfo->ram.ml = 4;
- rinfo->ram.mb = 4;
- rinfo->ram.trcd = 3;
- rinfo->ram.trp = 3;
- rinfo->ram.twr = 2;
- rinfo->ram.cl = 3;
- rinfo->ram.tr2w = 1;
- rinfo->ram.loop_latency = 16;
- rinfo->ram.rloop = 16;
-
- break;
- default:
- /* 64-bit SDR SGRAM */
- strcpy(rinfo->ram_type, "SDR SGRAM 64");
- rinfo->ram.ml = 4;
- rinfo->ram.mb = 8;
- rinfo->ram.trcd = 3;
- rinfo->ram.trp = 3;
- rinfo->ram.twr = 1;
- rinfo->ram.cl = 3;
- rinfo->ram.tr2w = 1;
- rinfo->ram.loop_latency = 17;
- rinfo->ram.rloop = 17;
-
- break;
- }
-
- rinfo->bios_seg = radeon_find_rom(rinfo);
- radeon_get_pllinfo(rinfo, rinfo->bios_seg);
-
- /*
- * Hack to get around some busted production M6's
- * reporting no ram
- */
- if (rinfo->video_ram == 0) {
- switch (pdev->device) {
- case PCI_DEVICE_ID_ATI_RADEON_LY:
- case PCI_DEVICE_ID_ATI_RADEON_LZ:
- rinfo->video_ram = 8192 * 1024;
- break;
- default:
- break;
- }
- }
-
-
- RTRACE("radeonfb: probed %s %dk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024));
-
-#if !defined(__powerpc__)
- radeon_get_moninfo(rinfo);
-#else
- switch (pdev->device) {
- case PCI_DEVICE_ID_ATI_RADEON_LW:
- case PCI_DEVICE_ID_ATI_RADEON_LX:
- case PCI_DEVICE_ID_ATI_RADEON_LY:
- case PCI_DEVICE_ID_ATI_RADEON_LZ:
- rinfo->dviDisp_type = MT_LCD;
- break;
- default:
- radeon_get_moninfo(rinfo);
- break;
- }
-#endif
-
- radeon_get_EDID(rinfo);
-
- if ((rinfo->dviDisp_type == MT_DFP) || (rinfo->dviDisp_type == MT_LCD) ||
- (rinfo->crtDisp_type == MT_DFP)) {
- if (!radeon_get_dfpinfo(rinfo)) {
- iounmap(rinfo->mmio_base);
- release_mem_region (rinfo->mmio_base_phys,
- pci_resource_len(pdev, 2));
- release_mem_region (rinfo->fb_base_phys,
- pci_resource_len(pdev, 0));
- kfree (rinfo);
- return -ENODEV;
- }
- }
-
- rinfo->fb_base = ioremap (rinfo->fb_base_phys, rinfo->video_ram);
- if (!rinfo->fb_base) {
- printk ("radeonfb: cannot map FB\n");
- iounmap(rinfo->mmio_base);
- release_mem_region (rinfo->mmio_base_phys,
- pci_resource_len(pdev, 2));
- release_mem_region (rinfo->fb_base_phys,
- pci_resource_len(pdev, 0));
- kfree (rinfo);
- return -ENODEV;
- }
-
- /* I SHOULD FIX THAT CRAP ! I should probably mimmic XFree DRI
- * driver setup here.
- *
- * On PPC, OF based cards setup the internal memory
- * mapping in strange ways. We change it so that the
- * framebuffer is mapped at 0 and given half of the card's
- * address space (2Gb). AGP is mapped high (0xe0000000) and
- * can use up to 512Mb. Once DRI is fully implemented, we
- * will have to setup the PCI remapper to remap the agp_special_page
- * memory page somewhere between those regions so that the card
- * use a normal PCI bus master cycle to access the ring read ptr.
- * --BenH.
- */
-#ifdef CONFIG_ALL_PPC
- if (rinfo->hasCRTC2)
- OUTREG(CRTC2_GEN_CNTL,
- (INREG(CRTC2_GEN_CNTL) & ~CRTC2_EN) | CRTC2_DISP_REQ_EN_B);
- OUTREG(CRTC_EXT_CNTL, INREG(CRTC_EXT_CNTL) | CRTC_DISPLAY_DIS);
- OUTREG(MC_FB_LOCATION, 0x7fff0000);
- OUTREG(MC_AGP_LOCATION, 0xffffe000);
- OUTREG(DISPLAY_BASE_ADDR, 0x00000000);
- if (rinfo->hasCRTC2)
- OUTREG(CRTC2_DISPLAY_BASE_ADDR, 0x00000000);
- OUTREG(SRC_OFFSET, 0x00000000);
- OUTREG(DST_OFFSET, 0x00000000);
- mdelay(10);
- OUTREG(CRTC_EXT_CNTL, INREG(CRTC_EXT_CNTL) & ~CRTC_DISPLAY_DIS);
-#endif /* CONFIG_ALL_PPC */
-
- /* save current mode regs before we switch into the new one
- * so we can restore this upon __exit
- */
- radeon_save_state (rinfo, &rinfo->init_state);
-
- /* set all the vital stuff */
- radeon_set_fbinfo (rinfo);
-
- pci_set_drvdata(pdev, rinfo);
- rinfo->next = board_list;
- board_list = rinfo;
- ((struct fb_info *) rinfo)->device = &pdev->dev;
- if (register_framebuffer ((struct fb_info *) rinfo) < 0) {
- printk ("radeonfb: could not register framebuffer\n");
- iounmap(rinfo->fb_base);
- iounmap(rinfo->mmio_base);
- release_mem_region (rinfo->mmio_base_phys,
- pci_resource_len(pdev, 2));
- release_mem_region (rinfo->fb_base_phys,
- pci_resource_len(pdev, 0));
- kfree (rinfo);
- return -ENODEV;
- }
-
-#ifdef CONFIG_MTRR
- rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys,
- rinfo->video_ram,
- MTRR_TYPE_WRCOMB, 1);
-#endif
-
-#ifdef CONFIG_PMAC_BACKLIGHT
- if (rinfo->dviDisp_type == MT_LCD)
- register_backlight_controller(&radeon_backlight_controller,
- rinfo, "ati");
-#endif
-
-#ifdef CONFIG_PMAC_PBOOK
- if (rinfo->dviDisp_type == MT_LCD) {
- rinfo->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
- pmu_register_sleep_notifier(&radeon_sleep_notifier);
- }
-#endif
-
- printk ("radeonfb: ATI Radeon %s %s %d MB\n", rinfo->name, rinfo->ram_type,
- (rinfo->video_ram/(1024*1024)));
-
- if (rinfo->hasCRTC2) {
- printk("radeonfb: DVI port %s monitor connected\n",
- GET_MON_NAME(rinfo->dviDisp_type));
- printk("radeonfb: CRT port %s monitor connected\n",
- GET_MON_NAME(rinfo->crtDisp_type));
- } else {
- printk("radeonfb: CRT port %s monitor connected\n",
- GET_MON_NAME(rinfo->crtDisp_type));
- }
-
- RTRACE("radeonfb_pci_register END\n");
-
- return 0;
-}
-
-
-
-static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
-{
- struct radeonfb_info *rinfo = pci_get_drvdata(pdev);
-
- if (!rinfo)
- return;
-
- /* restore original state
- *
- * Doesn't quite work yet, possibly because of the PPC hacking
- * I do on startup, disable for now. --BenH
- */
- radeon_write_mode (rinfo, &rinfo->init_state);
-
-#ifdef CONFIG_MTRR
- if (rinfo->mtrr_hdl >= 0)
- mtrr_del(rinfo->mtrr_hdl, 0, 0);
-#endif
-
- unregister_framebuffer ((struct fb_info *) rinfo);
-
- iounmap(rinfo->mmio_base);
- iounmap(rinfo->fb_base);
-
- release_mem_region (rinfo->mmio_base_phys,
- pci_resource_len(pdev, 2));
- release_mem_region (rinfo->fb_base_phys,
- pci_resource_len(pdev, 0));
-
- kfree (rinfo);
-}
-
-
-static struct pci_driver radeonfb_driver = {
- .name = "radeonfb",
- .id_table = radeonfb_pci_table,
- .probe = radeonfb_pci_register,
- .remove = __devexit_p(radeonfb_pci_unregister),
-};
-
-#ifndef MODULE
-static int __init radeonfb_old_setup (char *options)
-{
- char *this_opt;
-
- if (!options || !*options)
- return 0;
-
- while ((this_opt = strsep (&options, ",")) != NULL) {
- if (!*this_opt)
- continue;
- if (!strncmp(this_opt, "noaccel", 7)) {
- noaccel = 1;
- } else if (!strncmp(this_opt, "mirror", 6)) {
- mirror = 1;
- } else if (!strncmp(this_opt, "dfp", 3)) {
- force_dfp = 1;
- } else if (!strncmp(this_opt, "panel_yres:", 11)) {
- panel_yres = simple_strtoul((this_opt+11), NULL, 0);
- } else if (!strncmp(this_opt, "nomtrr", 6)) {
- nomtrr = 1;
- } else
- mode_option = this_opt;
- }
-
- return 0;
-}
-#endif /* MODULE */
-
-static int __init radeonfb_old_init (void)
-{
-#ifndef MODULE
- char *option = NULL;
-
- if (fb_get_options("radeonfb_old", &option))
- return -ENODEV;
- radeonfb_old_setup(option);
-#endif
- return pci_register_driver (&radeonfb_driver);
-}
-
-
-static void __exit radeonfb_old_exit (void)
-{
- pci_unregister_driver (&radeonfb_driver);
-}
-
-module_init(radeonfb_old_init);
-module_exit(radeonfb_old_exit);
-
-
-MODULE_AUTHOR("Ani Joshi");
-MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 6c19ab6afb0..3e9308f0f16 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -49,6 +49,7 @@
#include <asm/pci-bridge.h>
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/machdep.h>
#include <asm/backlight.h>
#endif
@@ -1247,7 +1248,7 @@ static int rivafb_blank(int blank, struct fb_info *info)
CRTCout(par, 0x1a, vesa);
#ifdef CONFIG_PMAC_BACKLIGHT
- if ( par->FlatPanel && _machine == _MACH_Pmac) {
+ if ( par->FlatPanel && machine_is(powermac)) {
set_backlight_enable(!blank);
}
#endif
@@ -2037,9 +2038,9 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
info->fix.smem_len / (1024 * 1024),
info->fix.smem_start);
#ifdef CONFIG_PMAC_BACKLIGHT
- if (default_par->FlatPanel && _machine == _MACH_Pmac)
- register_backlight_controller(&riva_backlight_controller,
- default_par, "mnca");
+ if (default_par->FlatPanel && machine_is(powermac))
+ register_backlight_controller(&riva_backlight_controller,
+ default_par, "mnca");
#endif
NVTRACE_LEAVE();
return 0;
@@ -2072,8 +2073,6 @@ static void __exit rivafb_remove(struct pci_dev *pd)
struct riva_par *par = info->par;
NVTRACE_ENTER();
- if (!info)
- return;
#ifdef CONFIG_FB_RIVA_I2C
riva_delete_i2c_busses(par);
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 00719a91479..21debed863a 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -273,8 +273,7 @@ int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
}
}
- if (out_edid)
- *out_edid = edid;
+ *out_edid = edid;
return (edid) ? 0 : 1;
}
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 10e6b3aab9e..0da624e6524 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -73,7 +73,7 @@
/* --------------------------------------------------------------------- */
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
#ifdef MODULE
@@ -1545,7 +1545,7 @@ static int __devinit savage_map_mmio (struct fb_info *info)
return 0;
}
-static void __devinit savage_unmap_mmio (struct fb_info *info)
+static void savage_unmap_mmio (struct fb_info *info)
{
struct savagefb_par *par = info->par;
DBG ("savage_unmap_mmio");
@@ -1597,7 +1597,7 @@ static int __devinit savage_map_video (struct fb_info *info,
return 0;
}
-static void __devinit savage_unmap_video (struct fb_info *info)
+static void savage_unmap_video (struct fb_info *info)
{
struct savagefb_par *par = info->par;
@@ -1614,7 +1614,7 @@ static void __devinit savage_unmap_video (struct fb_info *info)
}
}
-static int __devinit savage_init_hw (struct savagefb_par *par)
+static int savage_init_hw (struct savagefb_par *par)
{
unsigned char config1, m, n, n1, n2, sr8, cr3f, cr66 = 0, tmp;
diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
index 2d88f908170..c3e070a6eff 100644
--- a/drivers/video/sis/init301.c
+++ b/drivers/video/sis/init301.c
@@ -8564,11 +8564,9 @@ SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
static void
SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
{
- unsigned short temp,tempcl,tempch;
+ unsigned short temp;
SiS_LongDelay(SiS_Pr, 1);
- tempcl = 3;
- tempch = 0;
do {
temp = SiS_GetCH701x(SiS_Pr,0x66);
@@ -8582,13 +8580,6 @@ SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
SiS_SetCH701xForLCD(SiS_Pr);
- if(tempcl == 0) {
- if(tempch == 3) break;
- SiS_ChrontelResetDB(SiS_Pr);
- tempcl = 3;
- tempch++;
- }
- tempcl--;
temp = SiS_GetCH701x(SiS_Pr,0x76);
temp &= 0xfb; /* Reset PLL */
SiS_SetCH701x(SiS_Pr,0x76,temp);
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 8c1a8b5135c..c44de90ca12 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -1194,10 +1194,11 @@ static struct dac_switch dacs[] __devinitdata = {
static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par)
{
int i, ret = 0;
-
- for (i=0; i<sizeof(dacs)/sizeof(dacs[0]); i++) {
+
+ for (i = 0; i < ARRAY_SIZE(dacs); i++) {
ret = dacs[i].detect(info);
- if (ret) break;
+ if (ret)
+ break;
}
if (!ret)
return 0;
@@ -1604,8 +1605,8 @@ static int sstfb_dump_regs(struct fb_info *info)
{FBZMODE,"fbzmode"},
};
- const int pci_s = sizeof(pci_regs)/sizeof(pci_regs[0]);
- const int sst_s = sizeof(sst_regs)/sizeof(sst_regs[0]);
+ const int pci_s = ARRAY_SIZE(pci_regs);
+ const int sst_s = ARRAY_SIZE(sst_regs);
struct sstfb_par *par = info->par;
struct pci_dev *dev = par->dev;
u32 pci_res[pci_s];
diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h
index dc93336af55..1a9a60c74be 100644
--- a/drivers/video/sticore.h
+++ b/drivers/video/sticore.h
@@ -34,36 +34,20 @@
* for them to fix it and steal their solution. prumpf
*/
-#define STI_WAIT 1
-
-#include <asm/io.h> /* for USE_HPPA_IOREMAP */
-
-#if USE_HPPA_IOREMAP
+#include <asm/io.h>
-#define STI_PTR(p) (p)
-#define PTR_STI(p) (p)
-static inline int STI_CALL( unsigned long func,
- void *flags, void *inptr, void *outptr, void *glob_cfg )
-{
- int (*f)(void *,void *,void *,void *);
- f = (void*)func;
- return f(flags, inptr, outptr, glob_cfg);
-}
-
-#else /* !USE_HPPA_IOREMAP */
+#define STI_WAIT 1
#define STI_PTR(p) ( virt_to_phys(p) )
-#define PTR_STI(p) ( phys_to_virt((long)p) )
-#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \
- ({ \
- pdc_sti_call( func, (unsigned long)STI_PTR(flags), \
- (unsigned long)STI_PTR(inptr), \
- (unsigned long)STI_PTR(outptr), \
- (unsigned long)STI_PTR(glob_cfg)); \
+#define PTR_STI(p) ( phys_to_virt((unsigned long)p) )
+#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \
+ ({ \
+ pdc_sti_call( func, STI_PTR(flags), \
+ STI_PTR(inptr), \
+ STI_PTR(outptr), \
+ STI_PTR(glob_cfg)); \
})
-#endif /* USE_HPPA_IOREMAP */
-
#define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x)
#define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y)
@@ -352,8 +336,9 @@ struct sti_struct {
struct sti_conf_outptr outptr; /* configuration */
struct sti_conf_outptr_ext outptr_ext;
- /* PCI data structures (pg. 17ff from sti.pdf) */
struct pci_dev *pd;
+
+ /* PCI data structures (pg. 17ff from sti.pdf) */
u8 rm_entry[16]; /* pci region mapper array == pci config space offset */
/* pointer to the fb_info where this STI device is used */
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index 56d71d6e9a7..4a292aae6eb 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -3,7 +3,7 @@
* Low level Frame buffer driver for HP workstations with
* STI (standard text interface) video firmware.
*
- * Copyright (C) 2001-2005 Helge Deller <deller@gmx.de>
+ * Copyright (C) 2001-2006 Helge Deller <deller@gmx.de>
* Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
*
* Based on:
@@ -514,7 +514,7 @@ rattlerSetupPlanes(struct stifb_info *fb)
SETUP_HW(fb);
WRITE_BYTE(1, fb, REG_16b1);
- fb_memset(fb->info.fix.smem_start, 0xff,
+ fb_memset((void*)fb->info.fix.smem_start, 0xff,
fb->info.var.yres*fb->info.fix.line_length);
CRX24_SET_OVLY_MASK(fb);
@@ -908,83 +908,6 @@ SETUP_HCRX(struct stifb_info *fb)
/* ------------------- driver specific functions --------------------------- */
-#define TMPBUFLEN 2048
-
-static ssize_t
-stifb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-{
- unsigned long p = *ppos;
- struct inode *inode = file->f_dentry->d_inode;
- int fbidx = iminor(inode);
- struct fb_info *info = registered_fb[fbidx];
- char tmpbuf[TMPBUFLEN];
-
- if (!info || ! info->screen_base)
- return -ENODEV;
-
- if (p >= info->fix.smem_len)
- return 0;
- if (count >= info->fix.smem_len)
- count = info->fix.smem_len;
- if (count + p > info->fix.smem_len)
- count = info->fix.smem_len - p;
- if (count > sizeof(tmpbuf))
- count = sizeof(tmpbuf);
- if (count) {
- char *base_addr;
-
- base_addr = info->screen_base;
- memcpy_fromio(&tmpbuf, base_addr+p, count);
- count -= copy_to_user(buf, &tmpbuf, count);
- if (!count)
- return -EFAULT;
- *ppos += count;
- }
- return count;
-}
-
-static ssize_t
-stifb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
- struct inode *inode = file->f_dentry->d_inode;
- int fbidx = iminor(inode);
- struct fb_info *info = registered_fb[fbidx];
- unsigned long p = *ppos;
- size_t c;
- int err;
- char tmpbuf[TMPBUFLEN];
-
- if (!info || !info->screen_base)
- return -ENODEV;
-
- if (p > info->fix.smem_len)
- return -ENOSPC;
- if (count >= info->fix.smem_len)
- count = info->fix.smem_len;
- err = 0;
- if (count + p > info->fix.smem_len) {
- count = info->fix.smem_len - p;
- err = -ENOSPC;
- }
-
- p += (unsigned long)info->screen_base;
- c = count;
- while (c) {
- int len = c > sizeof(tmpbuf) ? sizeof(tmpbuf) : c;
- err = -EFAULT;
- if (copy_from_user(&tmpbuf, buf, len))
- break;
- memcpy_toio(p, &tmpbuf, len);
- c -= len;
- p += len;
- buf += len;
- *ppos += len;
- }
- if (count-c)
- return (count-c);
- return err;
-}
-
static int
stifb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp, struct fb_info *info)
@@ -1137,8 +1060,6 @@ stifb_init_display(struct stifb_info *fb)
static struct fb_ops stifb_ops = {
.owner = THIS_MODULE,
- .fb_read = stifb_read,
- .fb_write = stifb_write,
.fb_setcolreg = stifb_setcolreg,
.fb_blank = stifb_blank,
.fb_fillrect = cfb_fillrect,
@@ -1162,7 +1083,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
char *dev_name;
int bpp, xres, yres;
- fb = kmalloc(sizeof(*fb), GFP_ATOMIC);
+ fb = kzalloc(sizeof(*fb), GFP_ATOMIC);
if (!fb) {
printk(KERN_ERR "stifb: Could not allocate stifb structure\n");
return -ENODEV;
@@ -1171,7 +1092,6 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
info = &fb->info;
/* set struct to a known state */
- memset(fb, 0, sizeof(*fb));
fix = &info->fix;
var = &info->var;
@@ -1234,7 +1154,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
case S9000_ID_TOMCAT: /* Dual CRX, behaves else like a CRX */
/* FIXME: TomCat supports two heads:
* fb.iobase = REGION_BASE(fb_info,3);
- * fb.screen_base = (void*) REGION_BASE(fb_info,2);
+ * fb.screen_base = ioremap_nocache(REGION_BASE(fb_info,2),xxx);
* for now we only support the left one ! */
xres = fb->ngle_rom.x_size_visible;
yres = fb->ngle_rom.y_size_visible;
@@ -1327,7 +1247,8 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
strcpy(fix->id, "stifb");
info->fbops = &stifb_ops;
- info->screen_base = (void*) REGION_BASE(fb,1);
+ info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len);
+ info->screen_size = fix->smem_len;
info->flags = FBINFO_DEFAULT;
info->pseudo_palette = &fb->pseudo_palette;
@@ -1457,7 +1378,7 @@ stifb_setup(char *options)
int i;
if (!options || !*options)
- return 0;
+ return 1;
if (strncmp(options, "off", 3) == 0) {
stifb_disabled = 1;
@@ -1472,7 +1393,7 @@ stifb_setup(char *options)
stifb_bpp_pref[i] = simple_strtoul(options, &options, 10);
}
}
- return 0;
+ return 1;
}
__setup("stifb=", stifb_setup);
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 8982e540214..b0b9acfdd43 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -57,7 +57,7 @@ static unsigned short *pmi_base = NULL;
static void (*pmi_start)(void);
static void (*pmi_pal)(void);
static int depth;
-
+static int vga_compat;
/* --------------------------------------------------------------------- */
static int vesafb_pan_display(struct fb_var_screeninfo *var,
@@ -83,9 +83,10 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var,
static void vesa_setpalette(int regno, unsigned red, unsigned green,
unsigned blue)
{
+ int shift = 16 - depth;
+
#ifdef __i386__
struct { u_char blue, green, red, pad; } entry;
- int shift = 16 - depth;
if (pmi_setpal) {
entry.red = red >> shift;
@@ -101,14 +102,20 @@ static void vesa_setpalette(int regno, unsigned red, unsigned green,
"d" (regno), /* EDX */
"D" (&entry), /* EDI */
"S" (&pmi_pal)); /* ESI */
- } else {
- /* without protected mode interface, try VGA registers... */
+ return;
+ }
+#endif
+
+/*
+ * without protected mode interface and if VGA compatible,
+ * try VGA registers...
+ */
+ if (vga_compat) {
outb_p(regno, dac_reg);
outb_p(red >> shift, dac_val);
outb_p(green >> shift, dac_val);
outb_p(blue >> shift, dac_val);
}
-#endif
}
static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -214,6 +221,7 @@ static int __init vesafb_probe(struct platform_device *dev)
if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
return -ENODEV;
+ vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
vesafb_fix.smem_start = screen_info.lfb_base;
vesafb_defined.bits_per_pixel = screen_info.lfb_depth;
if (15 == vesafb_defined.bits_per_pixel)
@@ -318,6 +326,12 @@ static int __init vesafb_probe(struct platform_device *dev)
}
}
+ if (vesafb_defined.bits_per_pixel == 8 && !pmi_setpal && !vga_compat) {
+ printk(KERN_WARNING "vesafb: hardware palette is unchangeable,\n"
+ " colors may be incorrect\n");
+ vesafb_fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+ }
+
vesafb_defined.xres_virtual = vesafb_defined.xres;
vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length;
if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) {
@@ -354,7 +368,8 @@ static int __init vesafb_probe(struct platform_device *dev)
printk(KERN_INFO "vesafb: %s: "
"size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
(vesafb_defined.bits_per_pixel > 8) ?
- "Truecolor" : "Pseudocolor",
+ "Truecolor" : (vga_compat || pmi_setpal) ?
+ "Pseudocolor" : "Static Pseudocolor",
screen_info.rsvd_size,
screen_info.red_size,
screen_info.green_size,
diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c
index ed78747487e..5ea2345dab9 100644
--- a/drivers/video/virgefb.c
+++ b/drivers/video/virgefb.c
@@ -616,8 +616,7 @@ static struct {
#endif
};
-#define arraysize(x) (sizeof(x)/sizeof(*(x)))
-#define NUM_TOTAL_MODES arraysize(virgefb_predefined)
+#define NUM_TOTAL_MODES ARRAY_SIZE(virgefb_predefined)
/*
* Default to 800x600 for video=virge8:, virge16: or virge32:
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index f6e24ee85f0..5fc86ea2069 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -4,8 +4,9 @@
* Frame Buffer Device for ATI Imageon w100 (Wallaby)
*
* Copyright (C) 2002, ATI Corp.
- * Copyright (C) 2004-2005 Richard Purdie
+ * Copyright (C) 2004-2006 Richard Purdie
* Copyright (c) 2005 Ian Molton
+ * Copyright (c) 2006 Alberto Mardegan
*
* Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
*
@@ -14,6 +15,9 @@
*
* w32xx support by Ian Molton
*
+ * Hardware acceleration support by Alberto Mardegan
+ * <mardy@users.sourceforge.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.
@@ -47,6 +51,7 @@ static void w100_set_dispregs(struct w100fb_par*);
static void w100_update_enable(void);
static void w100_update_disable(void);
static void calc_hsync(struct w100fb_par *par);
+static void w100_init_graphic_engine(struct w100fb_par *par);
struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
/* Pseudo palette size */
@@ -248,6 +253,152 @@ static int w100fb_blank(int blank_mode, struct fb_info *info)
}
+static void w100_fifo_wait(int entries)
+{
+ union rbbm_status_u status;
+ int i;
+
+ for (i = 0; i < 2000000; i++) {
+ status.val = readl(remapped_regs + mmRBBM_STATUS);
+ if (status.f.cmdfifo_avail >= entries)
+ return;
+ udelay(1);
+ }
+ printk(KERN_ERR "w100fb: FIFO Timeout!\n");
+}
+
+
+static int w100fb_sync(struct fb_info *info)
+{
+ union rbbm_status_u status;
+ int i;
+
+ for (i = 0; i < 2000000; i++) {
+ status.val = readl(remapped_regs + mmRBBM_STATUS);
+ if (!status.f.gui_active)
+ return 0;
+ udelay(1);
+ }
+ printk(KERN_ERR "w100fb: Graphic engine timeout!\n");
+ return -EBUSY;
+}
+
+
+static void w100_init_graphic_engine(struct w100fb_par *par)
+{
+ union dp_gui_master_cntl_u gmc;
+ union dp_mix_u dp_mix;
+ union dp_datatype_u dp_datatype;
+ union dp_cntl_u dp_cntl;
+
+ w100_fifo_wait(4);
+ writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET);
+ writel(par->xres, remapped_regs + mmDST_PITCH);
+ writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET);
+ writel(par->xres, remapped_regs + mmSRC_PITCH);
+
+ w100_fifo_wait(3);
+ writel(0, remapped_regs + mmSC_TOP_LEFT);
+ writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT);
+ writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT);
+
+ w100_fifo_wait(4);
+ dp_cntl.val = 0;
+ dp_cntl.f.dst_x_dir = 1;
+ dp_cntl.f.dst_y_dir = 1;
+ dp_cntl.f.src_x_dir = 1;
+ dp_cntl.f.src_y_dir = 1;
+ dp_cntl.f.dst_major_x = 1;
+ dp_cntl.f.src_major_x = 1;
+ writel(dp_cntl.val, remapped_regs + mmDP_CNTL);
+
+ gmc.val = 0;
+ gmc.f.gmc_src_pitch_offset_cntl = 1;
+ gmc.f.gmc_dst_pitch_offset_cntl = 1;
+ gmc.f.gmc_src_clipping = 1;
+ gmc.f.gmc_dst_clipping = 1;
+ gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
+ gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */
+ gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST;
+ gmc.f.gmc_byte_pix_order = 1;
+ gmc.f.gmc_default_sel = 0;
+ gmc.f.gmc_rop3 = ROP3_SRCCOPY;
+ gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR;
+ gmc.f.gmc_clr_cmp_fcn_dis = 1;
+ gmc.f.gmc_wr_msk_dis = 1;
+ gmc.f.gmc_dp_op = DP_OP_ROP;
+ writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
+
+ dp_datatype.val = dp_mix.val = 0;
+ dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype;
+ dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype;
+ dp_datatype.f.dp_src2_type = 0;
+ dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype;
+ dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype;
+ dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order;
+ writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE);
+
+ dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source;
+ dp_mix.f.dp_src2_source = 1;
+ dp_mix.f.dp_rop3 = gmc.f.gmc_rop3;
+ dp_mix.f.dp_op = gmc.f.gmc_dp_op;
+ writel(dp_mix.val, remapped_regs + mmDP_MIX);
+}
+
+
+static void w100fb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
+{
+ union dp_gui_master_cntl_u gmc;
+
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+ if (info->flags & FBINFO_HWACCEL_DISABLED) {
+ cfb_fillrect(info, rect);
+ return;
+ }
+
+ gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
+ gmc.f.gmc_rop3 = ROP3_PATCOPY;
+ gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR;
+ w100_fifo_wait(2);
+ writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
+ writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR);
+
+ w100_fifo_wait(2);
+ writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X);
+ writel((rect->width << 16) | (rect->height & 0xffff),
+ remapped_regs + mmDST_WIDTH_HEIGHT);
+}
+
+
+static void w100fb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
+{
+ u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
+ u32 h = area->height, w = area->width;
+ union dp_gui_master_cntl_u gmc;
+
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+ if (info->flags & FBINFO_HWACCEL_DISABLED) {
+ cfb_copyarea(info, area);
+ return;
+ }
+
+ gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
+ gmc.f.gmc_rop3 = ROP3_SRCCOPY;
+ gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
+ w100_fifo_wait(1);
+ writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
+
+ w100_fifo_wait(3);
+ writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X);
+ writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X);
+ writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT);
+}
+
+
/*
* Change the resolution by calling the appropriate hardware functions
*/
@@ -265,6 +416,7 @@ static void w100fb_activate_var(struct w100fb_par *par)
w100_init_lcd(par);
w100_set_dispregs(par);
w100_update_enable();
+ w100_init_graphic_engine(par);
calc_hsync(par);
@@ -394,9 +546,10 @@ static struct fb_ops w100fb_ops = {
.fb_set_par = w100fb_set_par,
.fb_setcolreg = w100fb_setcolreg,
.fb_blank = w100fb_blank,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
+ .fb_fillrect = w100fb_fillrect,
+ .fb_copyarea = w100fb_copyarea,
.fb_imageblit = cfb_imageblit,
+ .fb_sync = w100fb_sync,
};
#ifdef CONFIG_PM
@@ -543,7 +696,8 @@ int __init w100fb_probe(struct platform_device *pdev)
}
info->fbops = &w100fb_ops;
- info->flags = FBINFO_DEFAULT;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
info->node = -1;
info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
info->screen_size = REMAPPED_FB_LEN;
diff --git a/drivers/video/w100fb.h b/drivers/video/w100fb.h
index 7a58a1e3e42..fffae7b4f6e 100644
--- a/drivers/video/w100fb.h
+++ b/drivers/video/w100fb.h
@@ -122,15 +122,32 @@
/* Block DISPLAY End: */
/* Block GFX Start: */
+#define mmDST_OFFSET 0x1004
+#define mmDST_PITCH 0x1008
+#define mmDST_Y_X 0x1038
+#define mmDST_WIDTH_HEIGHT 0x1198
+#define mmDP_GUI_MASTER_CNTL 0x106C
#define mmBRUSH_OFFSET 0x108C
#define mmBRUSH_Y_X 0x1074
+#define mmDP_BRUSH_FRGD_CLR 0x107C
+#define mmSRC_OFFSET 0x11AC
+#define mmSRC_PITCH 0x11B0
+#define mmSRC_Y_X 0x1034
#define mmDEFAULT_PITCH_OFFSET 0x10A0
#define mmDEFAULT_SC_BOTTOM_RIGHT 0x10A8
#define mmDEFAULT2_SC_BOTTOM_RIGHT 0x10AC
+#define mmSC_TOP_LEFT 0x11BC
+#define mmSC_BOTTOM_RIGHT 0x11C0
+#define mmSRC_SC_BOTTOM_RIGHT 0x11C4
#define mmGLOBAL_ALPHA 0x1210
#define mmFILTER_COEF 0x1214
#define mmMVC_CNTL_START 0x11E0
#define mmE2_ARITHMETIC_CNTL 0x1220
+#define mmDP_CNTL 0x11C8
+#define mmDP_CNTL_DST_DIR 0x11CC
+#define mmDP_DATATYPE 0x12C4
+#define mmDP_MIX 0x12C8
+#define mmDP_WRITE_MSK 0x12CC
#define mmENG_CNTL 0x13E8
#define mmENG_PERF_CNT 0x13F0
/* Block GFX End: */
@@ -179,6 +196,7 @@
/* Block RBBM Start: */
#define mmWAIT_UNTIL 0x1400
#define mmISYNC_CNTL 0x1404
+#define mmRBBM_STATUS 0x0140
#define mmRBBM_CNTL 0x0144
#define mmNQWAIT_UNTIL 0x0150
/* Block RBBM End: */
@@ -225,147 +243,147 @@
/* Register structure definitions */
struct wrap_top_dir_t {
- unsigned long top_addr : 23;
- unsigned long : 9;
+ u32 top_addr : 23;
+ u32 : 9;
} __attribute__((packed));
union wrap_top_dir_u {
- unsigned long val : 32;
+ u32 val : 32;
struct wrap_top_dir_t f;
} __attribute__((packed));
struct wrap_start_dir_t {
- unsigned long start_addr : 23;
- unsigned long : 9;
+ u32 start_addr : 23;
+ u32 : 9;
} __attribute__((packed));
union wrap_start_dir_u {
- unsigned long val : 32;
+ u32 val : 32;
struct wrap_start_dir_t f;
} __attribute__((packed));
struct cif_cntl_t {
- unsigned long swap_reg : 2;
- unsigned long swap_fbuf_1 : 2;
- unsigned long swap_fbuf_2 : 2;
- unsigned long swap_fbuf_3 : 2;
- unsigned long pmi_int_disable : 1;
- unsigned long pmi_schmen_disable : 1;
- unsigned long intb_oe : 1;
- unsigned long en_wait_to_compensate_dq_prop_dly : 1;
- unsigned long compensate_wait_rd_size : 2;
- unsigned long wait_asserted_timeout_val : 2;
- unsigned long wait_masked_val : 2;
- unsigned long en_wait_timeout : 1;
- unsigned long en_one_clk_setup_before_wait : 1;
- unsigned long interrupt_active_high : 1;
- unsigned long en_overwrite_straps : 1;
- unsigned long strap_wait_active_hi : 1;
- unsigned long lat_busy_count : 2;
- unsigned long lat_rd_pm4_sclk_busy : 1;
- unsigned long dis_system_bits : 1;
- unsigned long dis_mr : 1;
- unsigned long cif_spare_1 : 4;
+ u32 swap_reg : 2;
+ u32 swap_fbuf_1 : 2;
+ u32 swap_fbuf_2 : 2;
+ u32 swap_fbuf_3 : 2;
+ u32 pmi_int_disable : 1;
+ u32 pmi_schmen_disable : 1;
+ u32 intb_oe : 1;
+ u32 en_wait_to_compensate_dq_prop_dly : 1;
+ u32 compensate_wait_rd_size : 2;
+ u32 wait_asserted_timeout_val : 2;
+ u32 wait_masked_val : 2;
+ u32 en_wait_timeout : 1;
+ u32 en_one_clk_setup_before_wait : 1;
+ u32 interrupt_active_high : 1;
+ u32 en_overwrite_straps : 1;
+ u32 strap_wait_active_hi : 1;
+ u32 lat_busy_count : 2;
+ u32 lat_rd_pm4_sclk_busy : 1;
+ u32 dis_system_bits : 1;
+ u32 dis_mr : 1;
+ u32 cif_spare_1 : 4;
} __attribute__((packed));
union cif_cntl_u {
- unsigned long val : 32;
+ u32 val : 32;
struct cif_cntl_t f;
} __attribute__((packed));
struct cfgreg_base_t {
- unsigned long cfgreg_base : 24;
- unsigned long : 8;
+ u32 cfgreg_base : 24;
+ u32 : 8;
} __attribute__((packed));
union cfgreg_base_u {
- unsigned long val : 32;
+ u32 val : 32;
struct cfgreg_base_t f;
} __attribute__((packed));
struct cif_io_t {
- unsigned long dq_srp : 1;
- unsigned long dq_srn : 1;
- unsigned long dq_sp : 4;
- unsigned long dq_sn : 4;
- unsigned long waitb_srp : 1;
- unsigned long waitb_srn : 1;
- unsigned long waitb_sp : 4;
- unsigned long waitb_sn : 4;
- unsigned long intb_srp : 1;
- unsigned long intb_srn : 1;
- unsigned long intb_sp : 4;
- unsigned long intb_sn : 4;
- unsigned long : 2;
+ u32 dq_srp : 1;
+ u32 dq_srn : 1;
+ u32 dq_sp : 4;
+ u32 dq_sn : 4;
+ u32 waitb_srp : 1;
+ u32 waitb_srn : 1;
+ u32 waitb_sp : 4;
+ u32 waitb_sn : 4;
+ u32 intb_srp : 1;
+ u32 intb_srn : 1;
+ u32 intb_sp : 4;
+ u32 intb_sn : 4;
+ u32 : 2;
} __attribute__((packed));
union cif_io_u {
- unsigned long val : 32;
+ u32 val : 32;
struct cif_io_t f;
} __attribute__((packed));
struct cif_read_dbg_t {
- unsigned long unpacker_pre_fetch_trig_gen : 2;
- unsigned long dly_second_rd_fetch_trig : 1;
- unsigned long rst_rd_burst_id : 1;
- unsigned long dis_rd_burst_id : 1;
- unsigned long en_block_rd_when_packer_is_not_emp : 1;
- unsigned long dis_pre_fetch_cntl_sm : 1;
- unsigned long rbbm_chrncy_dis : 1;
- unsigned long rbbm_rd_after_wr_lat : 2;
- unsigned long dis_be_during_rd : 1;
- unsigned long one_clk_invalidate_pulse : 1;
- unsigned long dis_chnl_priority : 1;
- unsigned long rst_read_path_a_pls : 1;
- unsigned long rst_read_path_b_pls : 1;
- unsigned long dis_reg_rd_fetch_trig : 1;
- unsigned long dis_rd_fetch_trig_from_ind_addr : 1;
- unsigned long dis_rd_same_byte_to_trig_fetch : 1;
- unsigned long dis_dir_wrap : 1;
- unsigned long dis_ring_buf_to_force_dec : 1;
- unsigned long dis_addr_comp_in_16bit : 1;
- unsigned long clr_w : 1;
- unsigned long err_rd_tag_is_3 : 1;
- unsigned long err_load_when_ful_a : 1;
- unsigned long err_load_when_ful_b : 1;
- unsigned long : 7;
+ u32 unpacker_pre_fetch_trig_gen : 2;
+ u32 dly_second_rd_fetch_trig : 1;
+ u32 rst_rd_burst_id : 1;
+ u32 dis_rd_burst_id : 1;
+ u32 en_block_rd_when_packer_is_not_emp : 1;
+ u32 dis_pre_fetch_cntl_sm : 1;
+ u32 rbbm_chrncy_dis : 1;
+ u32 rbbm_rd_after_wr_lat : 2;
+ u32 dis_be_during_rd : 1;
+ u32 one_clk_invalidate_pulse : 1;
+ u32 dis_chnl_priority : 1;
+ u32 rst_read_path_a_pls : 1;
+ u32 rst_read_path_b_pls : 1;
+ u32 dis_reg_rd_fetch_trig : 1;
+ u32 dis_rd_fetch_trig_from_ind_addr : 1;
+ u32 dis_rd_same_byte_to_trig_fetch : 1;
+ u32 dis_dir_wrap : 1;
+ u32 dis_ring_buf_to_force_dec : 1;
+ u32 dis_addr_comp_in_16bit : 1;
+ u32 clr_w : 1;
+ u32 err_rd_tag_is_3 : 1;
+ u32 err_load_when_ful_a : 1;
+ u32 err_load_when_ful_b : 1;
+ u32 : 7;
} __attribute__((packed));
union cif_read_dbg_u {
- unsigned long val : 32;
+ u32 val : 32;
struct cif_read_dbg_t f;
} __attribute__((packed));
struct cif_write_dbg_t {
- unsigned long packer_timeout_count : 2;
- unsigned long en_upper_load_cond : 1;
- unsigned long en_chnl_change_cond : 1;
- unsigned long dis_addr_comp_cond : 1;
- unsigned long dis_load_same_byte_addr_cond : 1;
- unsigned long dis_timeout_cond : 1;
- unsigned long dis_timeout_during_rbbm : 1;
- unsigned long dis_packer_ful_during_rbbm_timeout : 1;
- unsigned long en_dword_split_to_rbbm : 1;
- unsigned long en_dummy_val : 1;
- unsigned long dummy_val_sel : 1;
- unsigned long mask_pm4_wrptr_dec : 1;
- unsigned long dis_mc_clean_cond : 1;
- unsigned long err_two_reqi_during_ful : 1;
- unsigned long err_reqi_during_idle_clk : 1;
- unsigned long err_global : 1;
- unsigned long en_wr_buf_dbg_load : 1;
- unsigned long en_wr_buf_dbg_path : 1;
- unsigned long sel_wr_buf_byte : 3;
- unsigned long dis_rd_flush_wr : 1;
- unsigned long dis_packer_ful_cond : 1;
- unsigned long dis_invalidate_by_ops_chnl : 1;
- unsigned long en_halt_when_reqi_err : 1;
- unsigned long cif_spare_2 : 5;
- unsigned long : 1;
+ u32 packer_timeout_count : 2;
+ u32 en_upper_load_cond : 1;
+ u32 en_chnl_change_cond : 1;
+ u32 dis_addr_comp_cond : 1;
+ u32 dis_load_same_byte_addr_cond : 1;
+ u32 dis_timeout_cond : 1;
+ u32 dis_timeout_during_rbbm : 1;
+ u32 dis_packer_ful_during_rbbm_timeout : 1;
+ u32 en_dword_split_to_rbbm : 1;
+ u32 en_dummy_val : 1;
+ u32 dummy_val_sel : 1;
+ u32 mask_pm4_wrptr_dec : 1;
+ u32 dis_mc_clean_cond : 1;
+ u32 err_two_reqi_during_ful : 1;
+ u32 err_reqi_during_idle_clk : 1;
+ u32 err_global : 1;
+ u32 en_wr_buf_dbg_load : 1;
+ u32 en_wr_buf_dbg_path : 1;
+ u32 sel_wr_buf_byte : 3;
+ u32 dis_rd_flush_wr : 1;
+ u32 dis_packer_ful_cond : 1;
+ u32 dis_invalidate_by_ops_chnl : 1;
+ u32 en_halt_when_reqi_err : 1;
+ u32 cif_spare_2 : 5;
+ u32 : 1;
} __attribute__((packed));
union cif_write_dbg_u {
- unsigned long val : 32;
+ u32 val : 32;
struct cif_write_dbg_t f;
} __attribute__((packed));
@@ -403,327 +421,327 @@ union cpu_defaults_u {
} __attribute__((packed));
struct crtc_total_t {
- unsigned long crtc_h_total : 10;
- unsigned long : 6;
- unsigned long crtc_v_total : 10;
- unsigned long : 6;
+ u32 crtc_h_total : 10;
+ u32 : 6;
+ u32 crtc_v_total : 10;
+ u32 : 6;
} __attribute__((packed));
union crtc_total_u {
- unsigned long val : 32;
+ u32 val : 32;
struct crtc_total_t f;
} __attribute__((packed));
struct crtc_ss_t {
- unsigned long ss_start : 10;
- unsigned long : 6;
- unsigned long ss_end : 10;
- unsigned long : 2;
- unsigned long ss_align : 1;
- unsigned long ss_pol : 1;
- unsigned long ss_run_mode : 1;
- unsigned long ss_en : 1;
+ u32 ss_start : 10;
+ u32 : 6;
+ u32 ss_end : 10;
+ u32 : 2;
+ u32 ss_align : 1;
+ u32 ss_pol : 1;
+ u32 ss_run_mode : 1;
+ u32 ss_en : 1;
} __attribute__((packed));
union crtc_ss_u {
- unsigned long val : 32;
+ u32 val : 32;
struct crtc_ss_t f;
} __attribute__((packed));
struct active_h_disp_t {
- unsigned long active_h_start : 10;
- unsigned long : 6;
- unsigned long active_h_end : 10;
- unsigned long : 6;
+ u32 active_h_start : 10;
+ u32 : 6;
+ u32 active_h_end : 10;
+ u32 : 6;
} __attribute__((packed));
union active_h_disp_u {
- unsigned long val : 32;
+ u32 val : 32;
struct active_h_disp_t f;
} __attribute__((packed));
struct active_v_disp_t {
- unsigned long active_v_start : 10;
- unsigned long : 6;
- unsigned long active_v_end : 10;
- unsigned long : 6;
+ u32 active_v_start : 10;
+ u32 : 6;
+ u32 active_v_end : 10;
+ u32 : 6;
} __attribute__((packed));
union active_v_disp_u {
- unsigned long val : 32;
+ u32 val : 32;
struct active_v_disp_t f;
} __attribute__((packed));
struct graphic_h_disp_t {
- unsigned long graphic_h_start : 10;
- unsigned long : 6;
- unsigned long graphic_h_end : 10;
- unsigned long : 6;
+ u32 graphic_h_start : 10;
+ u32 : 6;
+ u32 graphic_h_end : 10;
+ u32 : 6;
} __attribute__((packed));
union graphic_h_disp_u {
- unsigned long val : 32;
+ u32 val : 32;
struct graphic_h_disp_t f;
} __attribute__((packed));
struct graphic_v_disp_t {
- unsigned long graphic_v_start : 10;
- unsigned long : 6;
- unsigned long graphic_v_end : 10;
- unsigned long : 6;
+ u32 graphic_v_start : 10;
+ u32 : 6;
+ u32 graphic_v_end : 10;
+ u32 : 6;
} __attribute__((packed));
union graphic_v_disp_u{
- unsigned long val : 32;
+ u32 val : 32;
struct graphic_v_disp_t f;
} __attribute__((packed));
struct graphic_ctrl_t_w100 {
- unsigned long color_depth : 3;
- unsigned long portrait_mode : 2;
- unsigned long low_power_on : 1;
- unsigned long req_freq : 4;
- unsigned long en_crtc : 1;
- unsigned long en_graphic_req : 1;
- unsigned long en_graphic_crtc : 1;
- unsigned long total_req_graphic : 9;
- unsigned long lcd_pclk_on : 1;
- unsigned long lcd_sclk_on : 1;
- unsigned long pclk_running : 1;
- unsigned long sclk_running : 1;
- unsigned long : 6;
+ u32 color_depth : 3;
+ u32 portrait_mode : 2;
+ u32 low_power_on : 1;
+ u32 req_freq : 4;
+ u32 en_crtc : 1;
+ u32 en_graphic_req : 1;
+ u32 en_graphic_crtc : 1;
+ u32 total_req_graphic : 9;
+ u32 lcd_pclk_on : 1;
+ u32 lcd_sclk_on : 1;
+ u32 pclk_running : 1;
+ u32 sclk_running : 1;
+ u32 : 6;
} __attribute__((packed));
struct graphic_ctrl_t_w32xx {
- unsigned long color_depth : 3;
- unsigned long portrait_mode : 2;
- unsigned long low_power_on : 1;
- unsigned long req_freq : 4;
- unsigned long en_crtc : 1;
- unsigned long en_graphic_req : 1;
- unsigned long en_graphic_crtc : 1;
- unsigned long total_req_graphic : 10;
- unsigned long lcd_pclk_on : 1;
- unsigned long lcd_sclk_on : 1;
- unsigned long pclk_running : 1;
- unsigned long sclk_running : 1;
- unsigned long : 5;
+ u32 color_depth : 3;
+ u32 portrait_mode : 2;
+ u32 low_power_on : 1;
+ u32 req_freq : 4;
+ u32 en_crtc : 1;
+ u32 en_graphic_req : 1;
+ u32 en_graphic_crtc : 1;
+ u32 total_req_graphic : 10;
+ u32 lcd_pclk_on : 1;
+ u32 lcd_sclk_on : 1;
+ u32 pclk_running : 1;
+ u32 sclk_running : 1;
+ u32 : 5;
} __attribute__((packed));
union graphic_ctrl_u {
- unsigned long val : 32;
+ u32 val : 32;
struct graphic_ctrl_t_w100 f_w100;
struct graphic_ctrl_t_w32xx f_w32xx;
} __attribute__((packed));
struct video_ctrl_t {
- unsigned long video_mode : 1;
- unsigned long keyer_en : 1;
- unsigned long en_video_req : 1;
- unsigned long en_graphic_req_video : 1;
- unsigned long en_video_crtc : 1;
- unsigned long video_hor_exp : 2;
- unsigned long video_ver_exp : 2;
- unsigned long uv_combine : 1;
- unsigned long total_req_video : 9;
- unsigned long video_ch_sel : 1;
- unsigned long video_portrait : 2;
- unsigned long yuv2rgb_en : 1;
- unsigned long yuv2rgb_option : 1;
- unsigned long video_inv_hor : 1;
- unsigned long video_inv_ver : 1;
- unsigned long gamma_sel : 2;
- unsigned long dis_limit : 1;
- unsigned long en_uv_hblend : 1;
- unsigned long rgb_gamma_sel : 2;
+ u32 video_mode : 1;
+ u32 keyer_en : 1;
+ u32 en_video_req : 1;
+ u32 en_graphic_req_video : 1;
+ u32 en_video_crtc : 1;
+ u32 video_hor_exp : 2;
+ u32 video_ver_exp : 2;
+ u32 uv_combine : 1;
+ u32 total_req_video : 9;
+ u32 video_ch_sel : 1;
+ u32 video_portrait : 2;
+ u32 yuv2rgb_en : 1;
+ u32 yuv2rgb_option : 1;
+ u32 video_inv_hor : 1;
+ u32 video_inv_ver : 1;
+ u32 gamma_sel : 2;
+ u32 dis_limit : 1;
+ u32 en_uv_hblend : 1;
+ u32 rgb_gamma_sel : 2;
} __attribute__((packed));
union video_ctrl_u {
- unsigned long val : 32;
+ u32 val : 32;
struct video_ctrl_t f;
} __attribute__((packed));
struct disp_db_buf_cntl_rd_t {
- unsigned long en_db_buf : 1;
- unsigned long update_db_buf_done : 1;
- unsigned long db_buf_cntl : 6;
- unsigned long : 24;
+ u32 en_db_buf : 1;
+ u32 update_db_buf_done : 1;
+ u32 db_buf_cntl : 6;
+ u32 : 24;
} __attribute__((packed));
union disp_db_buf_cntl_rd_u {
- unsigned long val : 32;
+ u32 val : 32;
struct disp_db_buf_cntl_rd_t f;
} __attribute__((packed));
struct disp_db_buf_cntl_wr_t {
- unsigned long en_db_buf : 1;
- unsigned long update_db_buf : 1;
- unsigned long db_buf_cntl : 6;
- unsigned long : 24;
+ u32 en_db_buf : 1;
+ u32 update_db_buf : 1;
+ u32 db_buf_cntl : 6;
+ u32 : 24;
} __attribute__((packed));
union disp_db_buf_cntl_wr_u {
- unsigned long val : 32;
+ u32 val : 32;
struct disp_db_buf_cntl_wr_t f;
} __attribute__((packed));
struct gamma_value1_t {
- unsigned long gamma1 : 8;
- unsigned long gamma2 : 8;
- unsigned long gamma3 : 8;
- unsigned long gamma4 : 8;
+ u32 gamma1 : 8;
+ u32 gamma2 : 8;
+ u32 gamma3 : 8;
+ u32 gamma4 : 8;
} __attribute__((packed));
union gamma_value1_u {
- unsigned long val : 32;
+ u32 val : 32;
struct gamma_value1_t f;
} __attribute__((packed));
struct gamma_value2_t {
- unsigned long gamma5 : 8;
- unsigned long gamma6 : 8;
- unsigned long gamma7 : 8;
- unsigned long gamma8 : 8;
+ u32 gamma5 : 8;
+ u32 gamma6 : 8;
+ u32 gamma7 : 8;
+ u32 gamma8 : 8;
} __attribute__((packed));
union gamma_value2_u {
- unsigned long val : 32;
+ u32 val : 32;
struct gamma_value2_t f;
} __attribute__((packed));
struct gamma_slope_t {
- unsigned long slope1 : 3;
- unsigned long slope2 : 3;
- unsigned long slope3 : 3;
- unsigned long slope4 : 3;
- unsigned long slope5 : 3;
- unsigned long slope6 : 3;
- unsigned long slope7 : 3;
- unsigned long slope8 : 3;
- unsigned long : 8;
+ u32 slope1 : 3;
+ u32 slope2 : 3;
+ u32 slope3 : 3;
+ u32 slope4 : 3;
+ u32 slope5 : 3;
+ u32 slope6 : 3;
+ u32 slope7 : 3;
+ u32 slope8 : 3;
+ u32 : 8;
} __attribute__((packed));
union gamma_slope_u {
- unsigned long val : 32;
+ u32 val : 32;
struct gamma_slope_t f;
} __attribute__((packed));
struct mc_ext_mem_location_t {
- unsigned long mc_ext_mem_start : 16;
- unsigned long mc_ext_mem_top : 16;
+ u32 mc_ext_mem_start : 16;
+ u32 mc_ext_mem_top : 16;
} __attribute__((packed));
union mc_ext_mem_location_u {
- unsigned long val : 32;
+ u32 val : 32;
struct mc_ext_mem_location_t f;
} __attribute__((packed));
struct mc_fb_location_t {
- unsigned long mc_fb_start : 16;
- unsigned long mc_fb_top : 16;
+ u32 mc_fb_start : 16;
+ u32 mc_fb_top : 16;
} __attribute__((packed));
union mc_fb_location_u {
- unsigned long val : 32;
+ u32 val : 32;
struct mc_fb_location_t f;
} __attribute__((packed));
struct clk_pin_cntl_t {
- unsigned long osc_en : 1;
- unsigned long osc_gain : 5;
- unsigned long dont_use_xtalin : 1;
- unsigned long xtalin_pm_en : 1;
- unsigned long xtalin_dbl_en : 1;
- unsigned long : 7;
- unsigned long cg_debug : 16;
+ u32 osc_en : 1;
+ u32 osc_gain : 5;
+ u32 dont_use_xtalin : 1;
+ u32 xtalin_pm_en : 1;
+ u32 xtalin_dbl_en : 1;
+ u32 : 7;
+ u32 cg_debug : 16;
} __attribute__((packed));
union clk_pin_cntl_u {
- unsigned long val : 32;
+ u32 val : 32;
struct clk_pin_cntl_t f;
} __attribute__((packed));
struct pll_ref_fb_div_t {
- unsigned long pll_ref_div : 4;
- unsigned long : 4;
- unsigned long pll_fb_div_int : 6;
- unsigned long : 2;
- unsigned long pll_fb_div_frac : 3;
- unsigned long : 1;
- unsigned long pll_reset_time : 4;
- unsigned long pll_lock_time : 8;
+ u32 pll_ref_div : 4;
+ u32 : 4;
+ u32 pll_fb_div_int : 6;
+ u32 : 2;
+ u32 pll_fb_div_frac : 3;
+ u32 : 1;
+ u32 pll_reset_time : 4;
+ u32 pll_lock_time : 8;
} __attribute__((packed));
union pll_ref_fb_div_u {
- unsigned long val : 32;
+ u32 val : 32;
struct pll_ref_fb_div_t f;
} __attribute__((packed));
struct pll_cntl_t {
- unsigned long pll_pwdn : 1;
- unsigned long pll_reset : 1;
- unsigned long pll_pm_en : 1;
- unsigned long pll_mode : 1;
- unsigned long pll_refclk_sel : 1;
- unsigned long pll_fbclk_sel : 1;
- unsigned long pll_tcpoff : 1;
- unsigned long pll_pcp : 3;
- unsigned long pll_pvg : 3;
- unsigned long pll_vcofr : 1;
- unsigned long pll_ioffset : 2;
- unsigned long pll_pecc_mode : 2;
- unsigned long pll_pecc_scon : 2;
- unsigned long pll_dactal : 4;
- unsigned long pll_cp_clip : 2;
- unsigned long pll_conf : 3;
- unsigned long pll_mbctrl : 2;
- unsigned long pll_ring_off : 1;
+ u32 pll_pwdn : 1;
+ u32 pll_reset : 1;
+ u32 pll_pm_en : 1;
+ u32 pll_mode : 1;
+ u32 pll_refclk_sel : 1;
+ u32 pll_fbclk_sel : 1;
+ u32 pll_tcpoff : 1;
+ u32 pll_pcp : 3;
+ u32 pll_pvg : 3;
+ u32 pll_vcofr : 1;
+ u32 pll_ioffset : 2;
+ u32 pll_pecc_mode : 2;
+ u32 pll_pecc_scon : 2;
+ u32 pll_dactal : 4;
+ u32 pll_cp_clip : 2;
+ u32 pll_conf : 3;
+ u32 pll_mbctrl : 2;
+ u32 pll_ring_off : 1;
} __attribute__((packed));
union pll_cntl_u {
- unsigned long val : 32;
+ u32 val : 32;
struct pll_cntl_t f;
} __attribute__((packed));
struct sclk_cntl_t {
- unsigned long sclk_src_sel : 2;
- unsigned long : 2;
- unsigned long sclk_post_div_fast : 4;
- unsigned long sclk_clkon_hys : 3;
- unsigned long sclk_post_div_slow : 4;
- unsigned long disp_cg_ok2switch_en : 1;
- unsigned long sclk_force_reg : 1;
- unsigned long sclk_force_disp : 1;
- unsigned long sclk_force_mc : 1;
- unsigned long sclk_force_extmc : 1;
- unsigned long sclk_force_cp : 1;
- unsigned long sclk_force_e2 : 1;
- unsigned long sclk_force_e3 : 1;
- unsigned long sclk_force_idct : 1;
- unsigned long sclk_force_bist : 1;
- unsigned long busy_extend_cp : 1;
- unsigned long busy_extend_e2 : 1;
- unsigned long busy_extend_e3 : 1;
- unsigned long busy_extend_idct : 1;
- unsigned long : 3;
+ u32 sclk_src_sel : 2;
+ u32 : 2;
+ u32 sclk_post_div_fast : 4;
+ u32 sclk_clkon_hys : 3;
+ u32 sclk_post_div_slow : 4;
+ u32 disp_cg_ok2switch_en : 1;
+ u32 sclk_force_reg : 1;
+ u32 sclk_force_disp : 1;
+ u32 sclk_force_mc : 1;
+ u32 sclk_force_extmc : 1;
+ u32 sclk_force_cp : 1;
+ u32 sclk_force_e2 : 1;
+ u32 sclk_force_e3 : 1;
+ u32 sclk_force_idct : 1;
+ u32 sclk_force_bist : 1;
+ u32 busy_extend_cp : 1;
+ u32 busy_extend_e2 : 1;
+ u32 busy_extend_e3 : 1;
+ u32 busy_extend_idct : 1;
+ u32 : 3;
} __attribute__((packed));
union sclk_cntl_u {
- unsigned long val : 32;
+ u32 val : 32;
struct sclk_cntl_t f;
} __attribute__((packed));
struct pclk_cntl_t {
- unsigned long pclk_src_sel : 2;
- unsigned long : 2;
- unsigned long pclk_post_div : 4;
- unsigned long : 8;
- unsigned long pclk_force_disp : 1;
- unsigned long : 15;
+ u32 pclk_src_sel : 2;
+ u32 : 2;
+ u32 pclk_post_div : 4;
+ u32 : 8;
+ u32 pclk_force_disp : 1;
+ u32 : 15;
} __attribute__((packed));
union pclk_cntl_u {
- unsigned long val : 32;
+ u32 val : 32;
struct pclk_cntl_t f;
} __attribute__((packed));
@@ -735,36 +753,176 @@ union pclk_cntl_u {
#define TESTCLK_SRC_XTAL 0x06
struct clk_test_cntl_t {
- unsigned long testclk_sel : 4;
- unsigned long : 3;
- unsigned long start_check_freq : 1;
- unsigned long tstcount_rst : 1;
- unsigned long : 15;
- unsigned long test_count : 8;
+ u32 testclk_sel : 4;
+ u32 : 3;
+ u32 start_check_freq : 1;
+ u32 tstcount_rst : 1;
+ u32 : 15;
+ u32 test_count : 8;
} __attribute__((packed));
union clk_test_cntl_u {
- unsigned long val : 32;
+ u32 val : 32;
struct clk_test_cntl_t f;
} __attribute__((packed));
struct pwrmgt_cntl_t {
- unsigned long pwm_enable : 1;
- unsigned long : 1;
- unsigned long pwm_mode_req : 2;
- unsigned long pwm_wakeup_cond : 2;
- unsigned long pwm_fast_noml_hw_en : 1;
- unsigned long pwm_noml_fast_hw_en : 1;
- unsigned long pwm_fast_noml_cond : 4;
- unsigned long pwm_noml_fast_cond : 4;
- unsigned long pwm_idle_timer : 8;
- unsigned long pwm_busy_timer : 8;
+ u32 pwm_enable : 1;
+ u32 : 1;
+ u32 pwm_mode_req : 2;
+ u32 pwm_wakeup_cond : 2;
+ u32 pwm_fast_noml_hw_en : 1;
+ u32 pwm_noml_fast_hw_en : 1;
+ u32 pwm_fast_noml_cond : 4;
+ u32 pwm_noml_fast_cond : 4;
+ u32 pwm_idle_timer : 8;
+ u32 pwm_busy_timer : 8;
} __attribute__((packed));
union pwrmgt_cntl_u {
- unsigned long val : 32;
+ u32 val : 32;
struct pwrmgt_cntl_t f;
} __attribute__((packed));
+#define SRC_DATATYPE_EQU_DST 3
+
+#define ROP3_SRCCOPY 0xcc
+#define ROP3_PATCOPY 0xf0
+
+#define GMC_BRUSH_SOLID_COLOR 13
+#define GMC_BRUSH_NONE 15
+
+#define DP_SRC_MEM_RECTANGULAR 2
+
+#define DP_OP_ROP 0
+
+struct dp_gui_master_cntl_t {
+ u32 gmc_src_pitch_offset_cntl : 1;
+ u32 gmc_dst_pitch_offset_cntl : 1;
+ u32 gmc_src_clipping : 1;
+ u32 gmc_dst_clipping : 1;
+ u32 gmc_brush_datatype : 4;
+ u32 gmc_dst_datatype : 4;
+ u32 gmc_src_datatype : 3;
+ u32 gmc_byte_pix_order : 1;
+ u32 gmc_default_sel : 1;
+ u32 gmc_rop3 : 8;
+ u32 gmc_dp_src_source : 3;
+ u32 gmc_clr_cmp_fcn_dis : 1;
+ u32 : 1;
+ u32 gmc_wr_msk_dis : 1;
+ u32 gmc_dp_op : 1;
+} __attribute__((packed));
+
+union dp_gui_master_cntl_u {
+ u32 val : 32;
+ struct dp_gui_master_cntl_t f;
+} __attribute__((packed));
+
+struct rbbm_status_t {
+ u32 cmdfifo_avail : 7;
+ u32 : 1;
+ u32 hirq_on_rbb : 1;
+ u32 cprq_on_rbb : 1;
+ u32 cfrq_on_rbb : 1;
+ u32 hirq_in_rtbuf : 1;
+ u32 cprq_in_rtbuf : 1;
+ u32 cfrq_in_rtbuf : 1;
+ u32 cf_pipe_busy : 1;
+ u32 eng_ev_busy : 1;
+ u32 cp_cmdstrm_busy : 1;
+ u32 e2_busy : 1;
+ u32 rb2d_busy : 1;
+ u32 rb3d_busy : 1;
+ u32 se_busy : 1;
+ u32 re_busy : 1;
+ u32 tam_busy : 1;
+ u32 tdm_busy : 1;
+ u32 pb_busy : 1;
+ u32 : 6;
+ u32 gui_active : 1;
+} __attribute__((packed));
+
+union rbbm_status_u {
+ u32 val : 32;
+ struct rbbm_status_t f;
+} __attribute__((packed));
+
+struct dp_datatype_t {
+ u32 dp_dst_datatype : 4;
+ u32 : 4;
+ u32 dp_brush_datatype : 4;
+ u32 dp_src2_type : 1;
+ u32 dp_src2_datatype : 3;
+ u32 dp_src_datatype : 3;
+ u32 : 11;
+ u32 dp_byte_pix_order : 1;
+ u32 : 1;
+} __attribute__((packed));
+
+union dp_datatype_u {
+ u32 val : 32;
+ struct dp_datatype_t f;
+} __attribute__((packed));
+
+struct dp_mix_t {
+ u32 : 8;
+ u32 dp_src_source : 3;
+ u32 dp_src2_source : 3;
+ u32 : 2;
+ u32 dp_rop3 : 8;
+ u32 dp_op : 1;
+ u32 : 7;
+} __attribute__((packed));
+
+union dp_mix_u {
+ u32 val : 32;
+ struct dp_mix_t f;
+} __attribute__((packed));
+
+struct eng_cntl_t {
+ u32 erc_reg_rd_ws : 1;
+ u32 erc_reg_wr_ws : 1;
+ u32 erc_idle_reg_wr : 1;
+ u32 dis_engine_triggers : 1;
+ u32 dis_rop_src_uses_dst_w_h : 1;
+ u32 dis_src_uses_dst_dirmaj : 1;
+ u32 : 6;
+ u32 force_3dclk_when_2dclk : 1;
+ u32 : 19;
+} __attribute__((packed));
+
+union eng_cntl_u {
+ u32 val : 32;
+ struct eng_cntl_t f;
+} __attribute__((packed));
+
+struct dp_cntl_t {
+ u32 dst_x_dir : 1;
+ u32 dst_y_dir : 1;
+ u32 src_x_dir : 1;
+ u32 src_y_dir : 1;
+ u32 dst_major_x : 1;
+ u32 src_major_x : 1;
+ u32 : 26;
+} __attribute__((packed));
+
+union dp_cntl_u {
+ u32 val : 32;
+ struct dp_cntl_t f;
+} __attribute__((packed));
+
+struct dp_cntl_dst_dir_t {
+ u32 : 15;
+ u32 dst_y_dir : 1;
+ u32 : 15;
+ u32 dst_x_dir : 1;
+} __attribute__((packed));
+
+union dp_cntl_dst_dir_u {
+ u32 val : 32;
+ struct dp_cntl_dst_dir_t f;
+} __attribute__((packed));
+
#endif
diff --git a/fs/9p/fcall.c b/fs/9p/fcall.c
index 71742ba150c..6f2617820a4 100644
--- a/fs/9p/fcall.c
+++ b/fs/9p/fcall.c
@@ -98,23 +98,20 @@ v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc,
struct v9fs_fcall *rc, int err)
{
- int fid;
+ int fid, id;
struct v9fs_session_info *v9ses;
- if (err)
- return;
-
+ id = 0;
fid = tc->params.tclunk.fid;
- kfree(tc);
-
- if (!rc)
- return;
-
- v9ses = a;
- if (rc->id == RCLUNK)
- v9fs_put_idpool(fid, &v9ses->fidpool);
+ if (rc)
+ id = rc->id;
+ kfree(tc);
kfree(rc);
+ if (id == RCLUNK) {
+ v9ses = a;
+ v9fs_put_idpool(fid, &v9ses->fidpool);
+ }
}
/**
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
index 3e5b124a721..f4407eb276c 100644
--- a/fs/9p/mux.c
+++ b/fs/9p/mux.c
@@ -50,15 +50,23 @@ enum {
Wpending = 8, /* can write */
};
+enum {
+ None,
+ Flushing,
+ Flushed,
+};
+
struct v9fs_mux_poll_task;
struct v9fs_req {
+ spinlock_t lock;
int tag;
struct v9fs_fcall *tcall;
struct v9fs_fcall *rcall;
int err;
v9fs_mux_req_callback cb;
void *cba;
+ int flush;
struct list_head req_list;
};
@@ -96,8 +104,8 @@ struct v9fs_mux_poll_task {
struct v9fs_mux_rpc {
struct v9fs_mux_data *m;
- struct v9fs_req *req;
int err;
+ struct v9fs_fcall *tcall;
struct v9fs_fcall *rcall;
wait_queue_head_t wqueue;
};
@@ -524,10 +532,9 @@ again:
static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
{
- int ecode, tag;
+ int ecode;
struct v9fs_str *ename;
- tag = req->tag;
if (!req->err && req->rcall->id == RERROR) {
ecode = req->rcall->params.rerror.errno;
ename = &req->rcall->params.rerror.error;
@@ -553,23 +560,6 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
if (!req->err)
req->err = -EIO;
}
-
- if (req->err == ERREQFLUSH)
- return;
-
- if (req->cb) {
- dprintk(DEBUG_MUX, "calling callback tcall %p rcall %p\n",
- req->tcall, req->rcall);
-
- (*req->cb) (req->cba, req->tcall, req->rcall, req->err);
- req->cb = NULL;
- } else
- kfree(req->rcall);
-
- v9fs_mux_put_tag(m, tag);
-
- wake_up(&m->equeue);
- kfree(req);
}
/**
@@ -669,17 +659,26 @@ static void v9fs_read_work(void *a)
list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
if (rreq->tag == rcall->tag) {
req = rreq;
- req->rcall = rcall;
- list_del(&req->req_list);
- spin_unlock(&m->lock);
- process_request(m, req);
+ if (req->flush != Flushing)
+ list_del(&req->req_list);
break;
}
-
}
+ spin_unlock(&m->lock);
- if (!req) {
- spin_unlock(&m->lock);
+ if (req) {
+ req->rcall = rcall;
+ process_request(m, req);
+
+ if (req->flush != Flushing) {
+ if (req->cb)
+ (*req->cb) (req, req->cba);
+ else
+ kfree(req->rcall);
+
+ wake_up(&m->equeue);
+ }
+ } else {
if (err >= 0 && rcall->id != RFLUSH)
dprintk(DEBUG_ERROR,
"unexpected response mux %p id %d tag %d\n",
@@ -746,7 +745,6 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
return ERR_PTR(-ENOMEM);
v9fs_set_tag(tc, n);
-
if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) {
char buf[150];
@@ -754,12 +752,14 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
printk(KERN_NOTICE "<<< %p %s\n", m, buf);
}
+ spin_lock_init(&req->lock);
req->tag = n;
req->tcall = tc;
req->rcall = NULL;
req->err = 0;
req->cb = cb;
req->cba = cba;
+ req->flush = None;
spin_lock(&m->lock);
list_add_tail(&req->req_list, &m->unsent_req_list);
@@ -776,72 +776,108 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
return req;
}
-static void v9fs_mux_flush_cb(void *a, struct v9fs_fcall *tc,
- struct v9fs_fcall *rc, int err)
+static void v9fs_mux_free_request(struct v9fs_mux_data *m, struct v9fs_req *req)
+{
+ v9fs_mux_put_tag(m, req->tag);
+ kfree(req);
+}
+
+static void v9fs_mux_flush_cb(struct v9fs_req *freq, void *a)
{
v9fs_mux_req_callback cb;
int tag;
struct v9fs_mux_data *m;
- struct v9fs_req *req, *rptr;
+ struct v9fs_req *req, *rreq, *rptr;
m = a;
- dprintk(DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, tc,
- rc, err, tc->params.tflush.oldtag);
+ dprintk(DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m,
+ freq->tcall, freq->rcall, freq->err,
+ freq->tcall->params.tflush.oldtag);
spin_lock(&m->lock);
cb = NULL;
- tag = tc->params.tflush.oldtag;
- list_for_each_entry_safe(req, rptr, &m->req_list, req_list) {
- if (req->tag == tag) {
+ tag = freq->tcall->params.tflush.oldtag;
+ req = NULL;
+ list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
+ if (rreq->tag == tag) {
+ req = rreq;
list_del(&req->req_list);
- if (req->cb) {
- cb = req->cb;
- req->cb = NULL;
- spin_unlock(&m->lock);
- (*cb) (req->cba, req->tcall, req->rcall,
- req->err);
- }
- kfree(req);
- wake_up(&m->equeue);
break;
}
}
+ spin_unlock(&m->lock);
- if (!cb)
- spin_unlock(&m->lock);
+ if (req) {
+ spin_lock(&req->lock);
+ req->flush = Flushed;
+ spin_unlock(&req->lock);
+
+ if (req->cb)
+ (*req->cb) (req, req->cba);
+ else
+ kfree(req->rcall);
+
+ wake_up(&m->equeue);
+ }
- v9fs_mux_put_tag(m, tag);
- kfree(tc);
- kfree(rc);
+ kfree(freq->tcall);
+ kfree(freq->rcall);
+ v9fs_mux_free_request(m, freq);
}
-static void
+static int
v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req)
{
struct v9fs_fcall *fc;
+ struct v9fs_req *rreq, *rptr;
dprintk(DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag);
+ /* if a response was received for a request, do nothing */
+ spin_lock(&req->lock);
+ if (req->rcall || req->err) {
+ spin_unlock(&req->lock);
+ dprintk(DEBUG_MUX, "mux %p req %p response already received\n", m, req);
+ return 0;
+ }
+
+ req->flush = Flushing;
+ spin_unlock(&req->lock);
+
+ spin_lock(&m->lock);
+ /* if the request is not sent yet, just remove it from the list */
+ list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) {
+ if (rreq->tag == req->tag) {
+ dprintk(DEBUG_MUX, "mux %p req %p request is not sent yet\n", m, req);
+ list_del(&rreq->req_list);
+ req->flush = Flushed;
+ spin_unlock(&m->lock);
+ if (req->cb)
+ (*req->cb) (req, req->cba);
+ return 0;
+ }
+ }
+ spin_unlock(&m->lock);
+
+ clear_thread_flag(TIF_SIGPENDING);
fc = v9fs_create_tflush(req->tag);
v9fs_send_request(m, fc, v9fs_mux_flush_cb, m);
+ return 1;
}
static void
-v9fs_mux_rpc_cb(void *a, struct v9fs_fcall *tc, struct v9fs_fcall *rc, int err)
+v9fs_mux_rpc_cb(struct v9fs_req *req, void *a)
{
struct v9fs_mux_rpc *r;
- if (err == ERREQFLUSH) {
- kfree(rc);
- dprintk(DEBUG_MUX, "err req flush\n");
- return;
- }
-
+ dprintk(DEBUG_MUX, "req %p r %p\n", req, a);
r = a;
- dprintk(DEBUG_MUX, "mux %p req %p tc %p rc %p err %d\n", r->m, r->req,
- tc, rc, err);
- r->rcall = rc;
- r->err = err;
+ r->rcall = req->rcall;
+ r->err = req->err;
+
+ if (req->flush!=None && !req->err)
+ r->err = -ERESTARTSYS;
+
wake_up(&r->wqueue);
}
@@ -856,12 +892,13 @@ int
v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
struct v9fs_fcall **rc)
{
- int err;
+ int err, sigpending;
unsigned long flags;
struct v9fs_req *req;
struct v9fs_mux_rpc r;
r.err = 0;
+ r.tcall = tc;
r.rcall = NULL;
r.m = m;
init_waitqueue_head(&r.wqueue);
@@ -869,48 +906,50 @@ v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
if (rc)
*rc = NULL;
+ sigpending = 0;
+ if (signal_pending(current)) {
+ sigpending = 1;
+ clear_thread_flag(TIF_SIGPENDING);
+ }
+
req = v9fs_send_request(m, tc, v9fs_mux_rpc_cb, &r);
if (IS_ERR(req)) {
err = PTR_ERR(req);
dprintk(DEBUG_MUX, "error %d\n", err);
- return PTR_ERR(req);
+ return err;
}
- r.req = req;
- dprintk(DEBUG_MUX, "mux %p tc %p tag %d rpc %p req %p\n", m, tc,
- req->tag, &r, req);
err = wait_event_interruptible(r.wqueue, r.rcall != NULL || r.err < 0);
if (r.err < 0)
err = r.err;
if (err == -ERESTARTSYS && m->trans->status == Connected && m->err == 0) {
- spin_lock(&m->lock);
- req->tcall = NULL;
- req->err = ERREQFLUSH;
- spin_unlock(&m->lock);
+ if (v9fs_mux_flush_request(m, req)) {
+ /* wait until we get response of the flush message */
+ do {
+ clear_thread_flag(TIF_SIGPENDING);
+ err = wait_event_interruptible(r.wqueue,
+ r.rcall || r.err);
+ } while (!r.rcall && !r.err && err==-ERESTARTSYS &&
+ m->trans->status==Connected && !m->err);
+ }
+ sigpending = 1;
+ }
- clear_thread_flag(TIF_SIGPENDING);
- v9fs_mux_flush_request(m, req);
+ if (sigpending) {
spin_lock_irqsave(&current->sighand->siglock, flags);
recalc_sigpending();
spin_unlock_irqrestore(&current->sighand->siglock, flags);
}
- if (!err) {
- if (r.rcall)
- dprintk(DEBUG_MUX, "got response id %d tag %d\n",
- r.rcall->id, r.rcall->tag);
-
- if (rc)
- *rc = r.rcall;
- else
- kfree(r.rcall);
- } else {
+ if (rc)
+ *rc = r.rcall;
+ else
kfree(r.rcall);
- dprintk(DEBUG_MUX, "got error %d\n", err);
- if (err > 0)
- err = -EIO;
- }
+
+ v9fs_mux_free_request(m, req);
+ if (err > 0)
+ err = -EIO;
return err;
}
@@ -951,12 +990,15 @@ void v9fs_mux_cancel(struct v9fs_mux_data *m, int err)
struct v9fs_req *req, *rtmp;
LIST_HEAD(cancel_list);
- dprintk(DEBUG_MUX, "mux %p err %d\n", m, err);
+ dprintk(DEBUG_ERROR, "mux %p err %d\n", m, err);
m->err = err;
spin_lock(&m->lock);
list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
list_move(&req->req_list, &cancel_list);
}
+ list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
+ list_move(&req->req_list, &cancel_list);
+ }
spin_unlock(&m->lock);
list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
@@ -965,11 +1007,9 @@ void v9fs_mux_cancel(struct v9fs_mux_data *m, int err)
req->err = err;
if (req->cb)
- (*req->cb) (req->cba, req->tcall, req->rcall, req->err);
+ (*req->cb) (req, req->cba);
else
kfree(req->rcall);
-
- kfree(req);
}
wake_up(&m->equeue);
diff --git a/fs/9p/mux.h b/fs/9p/mux.h
index e90bfd32ea4..fb10c50186a 100644
--- a/fs/9p/mux.h
+++ b/fs/9p/mux.h
@@ -24,6 +24,7 @@
*/
struct v9fs_mux_data;
+struct v9fs_req;
/**
* v9fs_mux_req_callback - callback function that is called when the
@@ -36,8 +37,7 @@ struct v9fs_mux_data;
* @rc - response call
* @err - error code (non-zero if error occured)
*/
-typedef void (*v9fs_mux_req_callback)(void *a, struct v9fs_fcall *tc,
- struct v9fs_fcall *rc, int err);
+typedef void (*v9fs_mux_req_callback)(struct v9fs_req *req, void *a);
int v9fs_mux_global_init(void);
void v9fs_mux_global_exit(void);
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 43c9f7de031..f867b8d3e97 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -39,8 +39,8 @@
extern struct file_system_type v9fs_fs_type;
extern struct address_space_operations v9fs_addr_operations;
-extern struct file_operations v9fs_file_operations;
-extern struct file_operations v9fs_dir_operations;
+extern const struct file_operations v9fs_file_operations;
+extern const struct file_operations v9fs_dir_operations;
extern struct dentry_operations v9fs_dentry_operations;
struct inode *v9fs_get_inode(struct super_block *sb, int mode);
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 766f11f1215..e32d5971039 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -204,7 +204,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
return 0;
}
-struct file_operations v9fs_dir_operations = {
+const struct file_operations v9fs_dir_operations = {
.read = generic_read_dir,
.readdir = v9fs_dir_readdir,
.open = v9fs_file_open,
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 59e74416340..1a8e46084f0 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -72,11 +72,17 @@ int v9fs_file_open(struct inode *inode, struct file *file)
return -ENOSPC;
}
- err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, NULL);
+ err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, &fcall);
if (err < 0) {
dprintk(DEBUG_ERROR, "rewalk didn't work\n");
- goto put_fid;
+ if (fcall && fcall->id == RWALK)
+ goto clunk_fid;
+ else {
+ v9fs_put_idpool(fid, &v9ses->fidpool);
+ goto free_fcall;
+ }
}
+ kfree(fcall);
/* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
/* translate open mode appropriately */
@@ -109,8 +115,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
clunk_fid:
v9fs_t_clunk(v9ses, fid);
-put_fid:
- v9fs_put_idpool(fid, &v9ses->fidpool);
+free_fcall:
kfree(fcall);
return err;
@@ -266,7 +271,7 @@ v9fs_file_write(struct file *filp, const char __user * data,
return total;
}
-struct file_operations v9fs_file_operations = {
+const struct file_operations v9fs_file_operations = {
.llseek = generic_file_llseek,
.read = v9fs_file_read,
.write = v9fs_file_write,
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 133db366d30..2cb87ba4b1c 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -270,7 +270,10 @@ v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm,
err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall);
if (err < 0) {
PRINT_FCALL_ERROR("clone error", fcall);
- goto put_fid;
+ if (fcall && fcall->id == RWALK)
+ goto clunk_fid;
+ else
+ goto put_fid;
}
kfree(fcall);
@@ -322,6 +325,9 @@ v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
&fcall);
if (err < 0) {
+ if (fcall && fcall->id == RWALK)
+ goto clunk_fid;
+
PRINT_FCALL_ERROR("walk error", fcall);
v9fs_put_idpool(nfid, &v9ses->fidpool);
goto error;
@@ -640,19 +646,26 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
}
result = v9fs_t_walk(v9ses, dirfidnum, newfid,
- (char *)dentry->d_name.name, NULL);
+ (char *)dentry->d_name.name, &fcall);
+
if (result < 0) {
- v9fs_put_idpool(newfid, &v9ses->fidpool);
+ if (fcall && fcall->id == RWALK)
+ v9fs_t_clunk(v9ses, newfid);
+ else
+ v9fs_put_idpool(newfid, &v9ses->fidpool);
+
if (result == -ENOENT) {
d_add(dentry, NULL);
dprintk(DEBUG_VFS,
"Return negative dentry %p count %d\n",
dentry, atomic_read(&dentry->d_count));
+ kfree(fcall);
return NULL;
}
dprintk(DEBUG_ERROR, "walk error:%d\n", result);
goto FreeFcall;
}
+ kfree(fcall);
result = v9fs_t_stat(v9ses, newfid, &fcall);
if (result < 0) {
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index b0a0ae509c0..61c599b4a1e 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -127,12 +127,13 @@ static struct super_block *v9fs_get_sb(struct file_system_type
if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
dprintk(DEBUG_ERROR, "problem initiating session\n");
- kfree(v9ses);
- return ERR_PTR(newfid);
+ sb = ERR_PTR(newfid);
+ goto out_free_session;
}
sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
-
+ if (IS_ERR(sb))
+ goto out_close_session;
v9fs_fill_super(sb, v9ses, flags);
inode = v9fs_get_inode(sb, S_IFDIR | mode);
@@ -185,6 +186,12 @@ static struct super_block *v9fs_get_sb(struct file_system_type
return sb;
+out_close_session:
+ v9fs_session_close(v9ses);
+out_free_session:
+ kfree(v9ses);
+ return sb;
+
put_back_sb:
/* deactivate_super calls v9fs_kill_super which will frees the rest */
up_write(&sb->s_umount);
diff --git a/fs/Kconfig b/fs/Kconfig
index e207be68d4c..f9b5842c8d2 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -799,6 +799,7 @@ config PROC_KCORE
config PROC_VMCORE
bool "/proc/vmcore support (EXPERIMENTAL)"
depends on PROC_FS && EXPERIMENTAL && CRASH_DUMP
+ default y
help
Exports the dump image of crashed kernel in ELF format.
@@ -841,6 +842,12 @@ config TMPFS
config HUGETLBFS
bool "HugeTLB file system support"
depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
+ help
+ hugetlbfs is a filesystem backing for HugeTLB pages, based on
+ ramfs. For architectures that support it, say Y here and read
+ <file:Documentation/vm/hugetlbpage.txt> for details.
+
+ If unsure, say N.
config HUGETLB_PAGE
def_bool HUGETLBFS
@@ -861,7 +868,7 @@ config RAMFS
config CONFIGFS_FS
tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ depends on SYSFS && EXPERIMENTAL
help
configfs is a ram-based filesystem that provides the converse
of sysfs's functionality. Where sysfs is a filesystem-based
diff --git a/fs/Makefile b/fs/Makefile
index 080b3867be4..078d3d1191a 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -10,7 +10,7 @@ obj-y := open.o read_write.o file_table.o buffer.o bio.o super.o \
ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \
attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \
- ioprio.o pnode.o drop_caches.o
+ ioprio.o pnode.o drop_caches.o splice.o sync.o
obj-$(CONFIG_INOTIFY) += inotify.o
obj-$(CONFIG_EPOLL) += eventpoll.o
@@ -45,6 +45,7 @@ obj-$(CONFIG_DNOTIFY) += dnotify.o
obj-$(CONFIG_PROC_FS) += proc/
obj-y += partitions/
obj-$(CONFIG_SYSFS) += sysfs/
+obj-$(CONFIG_CONFIGFS_FS) += configfs/
obj-y += devpts/
obj-$(CONFIG_PROFILING) += dcookies.o
@@ -100,5 +101,4 @@ obj-$(CONFIG_BEFS_FS) += befs/
obj-$(CONFIG_HOSTFS) += hostfs/
obj-$(CONFIG_HPPFS) += hppfs/
obj-$(CONFIG_DEBUG_FS) += debugfs/
-obj-$(CONFIG_CONFIGFS_FS) += configfs/
obj-$(CONFIG_OCFS2_FS) += ocfs2/
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h
index f6cd01352cc..29217ff36d4 100644
--- a/fs/adfs/adfs.h
+++ b/fs/adfs/adfs.h
@@ -85,7 +85,7 @@ void __adfs_error(struct super_block *sb, const char *function,
/* dir_*.c */
extern struct inode_operations adfs_dir_inode_operations;
-extern struct file_operations adfs_dir_operations;
+extern const struct file_operations adfs_dir_operations;
extern struct dentry_operations adfs_dentry_operations;
extern struct adfs_dir_ops adfs_f_dir_ops;
extern struct adfs_dir_ops adfs_fplus_dir_ops;
@@ -94,7 +94,7 @@ extern int adfs_dir_update(struct super_block *sb, struct object_info *obj);
/* file.c */
extern struct inode_operations adfs_file_inode_operations;
-extern struct file_operations adfs_file_operations;
+extern const struct file_operations adfs_file_operations;
static inline __u32 signed_asl(__u32 val, signed int shift)
{
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index 0b4c3a02807..7b075fc397d 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -196,7 +196,7 @@ out:
return ret;
}
-struct file_operations adfs_dir_operations = {
+const struct file_operations adfs_dir_operations = {
.read = generic_read_dir,
.readdir = adfs_readdir,
.fsync = file_fsync,
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index 6af10885f9d..1014b9f2117 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -25,7 +25,7 @@
#include "adfs.h"
-struct file_operations adfs_file_operations = {
+const struct file_operations adfs_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.mmap = generic_file_mmap,
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index 0c6799f2137..a43a876742b 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -192,9 +192,9 @@ extern void affs_dir_truncate(struct inode *);
extern struct inode_operations affs_file_inode_operations;
extern struct inode_operations affs_dir_inode_operations;
extern struct inode_operations affs_symlink_inode_operations;
-extern struct file_operations affs_file_operations;
-extern struct file_operations affs_file_operations_ofs;
-extern struct file_operations affs_dir_operations;
+extern const struct file_operations affs_file_operations;
+extern const struct file_operations affs_file_operations_ofs;
+extern const struct file_operations affs_dir_operations;
extern struct address_space_operations affs_symlink_aops;
extern struct address_space_operations affs_aops;
extern struct address_space_operations affs_aops_ofs;
diff --git a/fs/affs/dir.c b/fs/affs/dir.c
index 548efd0ee98..5d9649fa181 100644
--- a/fs/affs/dir.c
+++ b/fs/affs/dir.c
@@ -17,7 +17,7 @@
static int affs_readdir(struct file *, void *, filldir_t);
-struct file_operations affs_dir_operations = {
+const struct file_operations affs_dir_operations = {
.read = generic_read_dir,
.readdir = affs_readdir,
.fsync = file_fsync,
diff --git a/fs/affs/file.c b/fs/affs/file.c
index f72fb776ecd..7076262af39 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -25,7 +25,7 @@ static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);
static int affs_file_open(struct inode *inode, struct file *filp);
static int affs_file_release(struct inode *inode, struct file *filp);
-struct file_operations affs_file_operations = {
+const struct file_operations affs_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index d4c2d636c47..a42143ca016 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -416,10 +416,9 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry,
return retval;
}
- retval = -EIO;
bh = affs_bread(sb, old_dentry->d_inode->i_ino);
if (!bh)
- goto done;
+ return -EIO;
/* Remove header from its parent directory. */
affs_lock_dir(old_dir);
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 5c61c24dab2..a6dff6a4f20 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -32,7 +32,7 @@ static int afs_d_delete(struct dentry *dentry);
static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,
loff_t fpos, ino_t ino, unsigned dtype);
-struct file_operations afs_dir_file_operations = {
+const struct file_operations afs_dir_file_operations = {
.open = afs_dir_open,
.readdir = afs_dir_readdir,
};
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index ab8f87c6631..72febdf9a35 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -64,7 +64,7 @@ extern struct cachefs_index_def afs_cache_cell_index_def;
* dir.c
*/
extern struct inode_operations afs_dir_inode_operations;
-extern struct file_operations afs_dir_file_operations;
+extern const struct file_operations afs_dir_file_operations;
/*
* file.c
@@ -105,7 +105,7 @@ extern struct cachefs_netfs afs_cache_netfs;
* mntpt.c
*/
extern struct inode_operations afs_mntpt_inode_operations;
-extern struct file_operations afs_mntpt_file_operations;
+extern const struct file_operations afs_mntpt_file_operations;
extern struct afs_timer afs_mntpt_expiry_timer;
extern struct afs_timer_ops afs_mntpt_expiry_timer_ops;
extern unsigned long afs_mntpt_expiry_timeout;
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 31ee06590de..4e6eeb59b83 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -32,7 +32,7 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir,
static int afs_mntpt_open(struct inode *inode, struct file *file);
static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd);
-struct file_operations afs_mntpt_file_operations = {
+const struct file_operations afs_mntpt_file_operations = {
.open = afs_mntpt_open,
};
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 9c81b8f7eef..101d21b6c03 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -37,7 +37,7 @@ static struct seq_operations afs_proc_cells_ops = {
.show = afs_proc_cells_show,
};
-static struct file_operations afs_proc_cells_fops = {
+static const struct file_operations afs_proc_cells_fops = {
.open = afs_proc_cells_open,
.read = seq_read,
.write = afs_proc_cells_write,
@@ -53,7 +53,7 @@ static ssize_t afs_proc_rootcell_write(struct file *file,
const char __user *buf,
size_t size, loff_t *_pos);
-static struct file_operations afs_proc_rootcell_fops = {
+static const struct file_operations afs_proc_rootcell_fops = {
.open = afs_proc_rootcell_open,
.read = afs_proc_rootcell_read,
.write = afs_proc_rootcell_write,
@@ -77,7 +77,7 @@ static struct seq_operations afs_proc_cell_volumes_ops = {
.show = afs_proc_cell_volumes_show,
};
-static struct file_operations afs_proc_cell_volumes_fops = {
+static const struct file_operations afs_proc_cell_volumes_fops = {
.open = afs_proc_cell_volumes_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -101,7 +101,7 @@ static struct seq_operations afs_proc_cell_vlservers_ops = {
.show = afs_proc_cell_vlservers_show,
};
-static struct file_operations afs_proc_cell_vlservers_fops = {
+static const struct file_operations afs_proc_cell_vlservers_fops = {
.open = afs_proc_cell_vlservers_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -124,7 +124,7 @@ static struct seq_operations afs_proc_cell_servers_ops = {
.show = afs_proc_cell_servers_show,
};
-static struct file_operations afs_proc_cell_servers_fops = {
+static const struct file_operations afs_proc_cell_servers_fops = {
.open = afs_proc_cell_servers_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 990c28da5ae..a62327f1bdf 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -146,7 +146,7 @@ struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info
extern struct inode_operations autofs_root_inode_operations;
extern struct inode_operations autofs_symlink_inode_operations;
-extern struct file_operations autofs_root_operations;
+extern const struct file_operations autofs_root_operations;
/* Initializing function */
diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c
index 5ccfcf26310..3fded389d06 100644
--- a/fs/autofs/dirhash.c
+++ b/fs/autofs/dirhash.c
@@ -92,7 +92,7 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb,
;
dput(dentry);
- if ( may_umount(mnt) == 0 ) {
+ if ( may_umount(mnt) ) {
mntput(mnt);
DPRINTK(("autofs: signaling expire on %s\n", ent->name));
return ent; /* Expirable! */
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index 870e2cf3301..9cac08d6a87 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -26,7 +26,7 @@ static int autofs_root_rmdir(struct inode *,struct dentry *);
static int autofs_root_mkdir(struct inode *,struct dentry *,int);
static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
-struct file_operations autofs_root_operations = {
+const struct file_operations autofs_root_operations = {
.read = generic_read_dir,
.readdir = autofs_root_readdir,
.ioctl = autofs_root_ioctl,
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index f54c5b21f87..d6603d02304 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -3,6 +3,7 @@
* linux/fs/autofs/autofs_i.h
*
* Copyright 1997-1998 Transmeta Corporation - All Rights Reserved
+ * Copyright 2005-2006 Ian Kent <raven@themaw.net>
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
@@ -41,14 +42,6 @@
#define AUTOFS_SUPER_MAGIC 0x0187
-/*
- * If the daemon returns a negative response (AUTOFS_IOC_FAIL) then the
- * kernel will keep the negative response cached for up to the time given
- * here, although the time can be shorter if the kernel throws the dcache
- * entry away. This probably should be settable from user space.
- */
-#define AUTOFS_NEGATIVE_TIMEOUT (60*HZ) /* 1 minute */
-
/* Unified info structure. This is pointed to by both the dentry and
inode structures. Each file in the filesystem has an instance of this
structure. It holds a reference to the dentry, so dentries are never
@@ -63,6 +56,7 @@ struct autofs_info {
struct autofs_sb_info *sbi;
unsigned long last_used;
+ atomic_t count;
mode_t mode;
size_t size;
@@ -80,26 +74,39 @@ struct autofs_wait_queue {
struct autofs_wait_queue *next;
autofs_wqt_t wait_queue_token;
/* We use the following to see what we are waiting for */
- int hash;
- int len;
+ unsigned int hash;
+ unsigned int len;
char *name;
+ u32 dev;
+ u64 ino;
+ uid_t uid;
+ gid_t gid;
+ pid_t pid;
+ pid_t tgid;
/* This is for status reporting upon return */
int status;
- atomic_t notified;
atomic_t wait_ctr;
};
#define AUTOFS_SBI_MAGIC 0x6d4a556d
+#define AUTOFS_TYPE_INDIRECT 0x0001
+#define AUTOFS_TYPE_DIRECT 0x0002
+#define AUTOFS_TYPE_OFFSET 0x0004
+
struct autofs_sb_info {
u32 magic;
struct dentry *root;
+ int pipefd;
struct file *pipe;
pid_t oz_pgrp;
int catatonic;
int version;
int sub_version;
+ int min_proto;
+ int max_proto;
unsigned long exp_timeout;
+ unsigned int type;
int reghost_enabled;
int needs_reghost;
struct super_block *sb;
@@ -166,8 +173,10 @@ int autofs4_expire_multi(struct super_block *, struct vfsmount *,
extern struct inode_operations autofs4_symlink_inode_operations;
extern struct inode_operations autofs4_dir_inode_operations;
extern struct inode_operations autofs4_root_inode_operations;
-extern struct file_operations autofs4_dir_operations;
-extern struct file_operations autofs4_root_operations;
+extern struct inode_operations autofs4_indirect_root_inode_operations;
+extern struct inode_operations autofs4_direct_root_inode_operations;
+extern const struct file_operations autofs4_dir_operations;
+extern const struct file_operations autofs4_root_operations;
/* Initializing function */
@@ -176,13 +185,6 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *, struct autofs_sb_info
/* Queue management functions */
-enum autofs_notify
-{
- NFY_NONE,
- NFY_MOUNT,
- NFY_EXPIRE
-};
-
int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify);
int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
void autofs4_catatonic_mode(struct autofs_sb_info *);
@@ -200,12 +202,22 @@ static inline int autofs4_follow_mount(struct vfsmount **mnt, struct dentry **de
return res;
}
+static inline u32 autofs4_get_dev(struct autofs_sb_info *sbi)
+{
+ return new_encode_dev(sbi->sb->s_dev);
+}
+
+static inline u64 autofs4_get_ino(struct autofs_sb_info *sbi)
+{
+ return sbi->sb->s_root->d_inode->i_ino;
+}
+
static inline int simple_positive(struct dentry *dentry)
{
return dentry->d_inode && !d_unhashed(dentry);
}
-static inline int simple_empty_nolock(struct dentry *dentry)
+static inline int __simple_empty(struct dentry *dentry)
{
struct dentry *child;
int ret = 0;
@@ -217,3 +229,6 @@ static inline int simple_empty_nolock(struct dentry *dentry)
out:
return ret;
}
+
+void autofs4_dentry_release(struct dentry *);
+
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index dc39589df16..b8ce02607d6 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -4,7 +4,7 @@
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
* Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
- * Copyright 2001-2003 Ian Kent <raven@themaw.net>
+ * Copyright 2001-2006 Ian Kent <raven@themaw.net>
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
@@ -16,7 +16,7 @@
static unsigned long now;
-/* Check if a dentry can be expired return 1 if it can else return 0 */
+/* Check if a dentry can be expired */
static inline int autofs4_can_expire(struct dentry *dentry,
unsigned long timeout, int do_now)
{
@@ -41,14 +41,14 @@ static inline int autofs4_can_expire(struct dentry *dentry,
attempts if expire fails the first time */
ino->last_used = now;
}
-
return 1;
}
-/* Check a mount point for busyness return 1 if not busy, otherwise */
-static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry)
+/* Check a mount point for busyness */
+static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
{
- int status = 0;
+ struct dentry *top = dentry;
+ int status = 1;
DPRINTK("dentry %p %.*s",
dentry, (int)dentry->d_name.len, dentry->d_name.name);
@@ -63,9 +63,14 @@ static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry)
if (is_autofs4_dentry(dentry))
goto done;
- /* The big question */
- if (may_umount_tree(mnt) == 0)
- status = 1;
+ /* Update the expiry counter if fs is busy */
+ if (!may_umount_tree(mnt)) {
+ struct autofs_info *ino = autofs4_dentry_ino(top);
+ ino->last_used = jiffies;
+ goto done;
+ }
+
+ status = 0;
done:
DPRINTK("returning = %d", status);
mntput(mnt);
@@ -73,78 +78,124 @@ done:
return status;
}
+/*
+ * Calculate next entry in top down tree traversal.
+ * From next_mnt in namespace.c - elegant.
+ */
+static struct dentry *next_dentry(struct dentry *p, struct dentry *root)
+{
+ struct list_head *next = p->d_subdirs.next;
+
+ if (next == &p->d_subdirs) {
+ while (1) {
+ if (p == root)
+ return NULL;
+ next = p->d_u.d_child.next;
+ if (next != &p->d_parent->d_subdirs)
+ break;
+ p = p->d_parent;
+ }
+ }
+ return list_entry(next, struct dentry, d_u.d_child);
+}
+
+/*
+ * Check a direct mount point for busyness.
+ * Direct mounts have similar expiry semantics to tree mounts.
+ * The tree is not busy iff no mountpoints are busy and there are no
+ * autofs submounts.
+ */
+static int autofs4_direct_busy(struct vfsmount *mnt,
+ struct dentry *top,
+ unsigned long timeout,
+ int do_now)
+{
+ DPRINTK("top %p %.*s",
+ top, (int) top->d_name.len, top->d_name.name);
+
+ /* If it's busy update the expiry counters */
+ if (!may_umount_tree(mnt)) {
+ struct autofs_info *ino = autofs4_dentry_ino(top);
+ if (ino)
+ ino->last_used = jiffies;
+ return 1;
+ }
+
+ /* Timeout of a direct mount is determined by its top dentry */
+ if (!autofs4_can_expire(top, timeout, do_now))
+ return 1;
+
+ return 0;
+}
+
/* Check a directory tree of mount points for busyness
* The tree is not busy iff no mountpoints are busy
- * Return 1 if the tree is busy or 0 otherwise
*/
-static int autofs4_check_tree(struct vfsmount *mnt,
- struct dentry *top,
- unsigned long timeout,
- int do_now)
+static int autofs4_tree_busy(struct vfsmount *mnt,
+ struct dentry *top,
+ unsigned long timeout,
+ int do_now)
{
- struct dentry *this_parent = top;
- struct list_head *next;
+ struct autofs_info *top_ino = autofs4_dentry_ino(top);
+ struct dentry *p;
- DPRINTK("parent %p %.*s",
+ DPRINTK("top %p %.*s",
top, (int)top->d_name.len, top->d_name.name);
/* Negative dentry - give up */
if (!simple_positive(top))
- return 0;
-
- /* Timeout of a tree mount is determined by its top dentry */
- if (!autofs4_can_expire(top, timeout, do_now))
- return 0;
-
- /* Is someone visiting anywhere in the tree ? */
- if (may_umount_tree(mnt))
- return 0;
+ return 1;
spin_lock(&dcache_lock);
-repeat:
- next = this_parent->d_subdirs.next;
-resume:
- while (next != &this_parent->d_subdirs) {
- struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
-
+ for (p = top; p; p = next_dentry(p, top)) {
/* Negative dentry - give up */
- if (!simple_positive(dentry)) {
- next = next->next;
+ if (!simple_positive(p))
continue;
- }
DPRINTK("dentry %p %.*s",
- dentry, (int)dentry->d_name.len, dentry->d_name.name);
-
- if (!simple_empty_nolock(dentry)) {
- this_parent = dentry;
- goto repeat;
- }
+ p, (int) p->d_name.len, p->d_name.name);
- dentry = dget(dentry);
+ p = dget(p);
spin_unlock(&dcache_lock);
- if (d_mountpoint(dentry)) {
- /* First busy => tree busy */
- if (!autofs4_check_mount(mnt, dentry)) {
- dput(dentry);
- return 0;
+ /*
+ * Is someone visiting anywhere in the subtree ?
+ * If there's no mount we need to check the usage
+ * count for the autofs dentry.
+ * If the fs is busy update the expiry counter.
+ */
+ if (d_mountpoint(p)) {
+ if (autofs4_mount_busy(mnt, p)) {
+ top_ino->last_used = jiffies;
+ dput(p);
+ return 1;
+ }
+ } else {
+ struct autofs_info *ino = autofs4_dentry_ino(p);
+ unsigned int ino_count = atomic_read(&ino->count);
+
+ /* allow for dget above and top is already dgot */
+ if (p == top)
+ ino_count += 2;
+ else
+ ino_count++;
+
+ if (atomic_read(&p->d_count) > ino_count) {
+ top_ino->last_used = jiffies;
+ dput(p);
+ return 1;
}
}
-
- dput(dentry);
+ dput(p);
spin_lock(&dcache_lock);
- next = next->next;
- }
-
- if (this_parent != top) {
- next = this_parent->d_u.d_child.next;
- this_parent = this_parent->d_parent;
- goto resume;
}
spin_unlock(&dcache_lock);
- return 1;
+ /* Timeout of a tree mount is ultimately determined by its top dentry */
+ if (!autofs4_can_expire(top, timeout, do_now))
+ return 1;
+
+ return 0;
}
static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
@@ -152,58 +203,68 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
unsigned long timeout,
int do_now)
{
- struct dentry *this_parent = parent;
- struct list_head *next;
+ struct dentry *p;
DPRINTK("parent %p %.*s",
parent, (int)parent->d_name.len, parent->d_name.name);
spin_lock(&dcache_lock);
-repeat:
- next = this_parent->d_subdirs.next;
-resume:
- while (next != &this_parent->d_subdirs) {
- struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
-
+ for (p = parent; p; p = next_dentry(p, parent)) {
/* Negative dentry - give up */
- if (!simple_positive(dentry)) {
- next = next->next;
+ if (!simple_positive(p))
continue;
- }
DPRINTK("dentry %p %.*s",
- dentry, (int)dentry->d_name.len, dentry->d_name.name);
-
- if (!list_empty(&dentry->d_subdirs)) {
- this_parent = dentry;
- goto repeat;
- }
+ p, (int) p->d_name.len, p->d_name.name);
- dentry = dget(dentry);
+ p = dget(p);
spin_unlock(&dcache_lock);
- if (d_mountpoint(dentry)) {
- /* Can we expire this guy */
- if (!autofs4_can_expire(dentry, timeout, do_now))
- goto cont;
-
+ if (d_mountpoint(p)) {
/* Can we umount this guy */
- if (autofs4_check_mount(mnt, dentry))
- return dentry;
+ if (autofs4_mount_busy(mnt, p))
+ goto cont;
+ /* Can we expire this guy */
+ if (autofs4_can_expire(p, timeout, do_now))
+ return p;
}
cont:
- dput(dentry);
+ dput(p);
spin_lock(&dcache_lock);
- next = next->next;
}
+ spin_unlock(&dcache_lock);
+ return NULL;
+}
+
+/* Check if we can expire a direct mount (possibly a tree) */
+static struct dentry *autofs4_expire_direct(struct super_block *sb,
+ struct vfsmount *mnt,
+ struct autofs_sb_info *sbi,
+ int how)
+{
+ unsigned long timeout;
+ struct dentry *root = dget(sb->s_root);
+ int do_now = how & AUTOFS_EXP_IMMEDIATE;
+
+ if (!sbi->exp_timeout || !root)
+ return NULL;
+
+ now = jiffies;
+ timeout = sbi->exp_timeout;
+
+ /* Lock the tree as we must expire as a whole */
+ spin_lock(&sbi->fs_lock);
+ if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
+ struct autofs_info *ino = autofs4_dentry_ino(root);
- if (this_parent != parent) {
- next = this_parent->d_u.d_child.next;
- this_parent = this_parent->d_parent;
- goto resume;
+ /* Set this flag early to catch sys_chdir and the like */
+ ino->flags |= AUTOFS_INF_EXPIRING;
+ spin_unlock(&sbi->fs_lock);
+ return root;
}
- spin_unlock(&dcache_lock);
+ spin_unlock(&sbi->fs_lock);
+ dput(root);
return NULL;
}
@@ -214,10 +275,10 @@ cont:
* - it is unused by any user process
* - it has been unused for exp_timeout time
*/
-static struct dentry *autofs4_expire(struct super_block *sb,
- struct vfsmount *mnt,
- struct autofs_sb_info *sbi,
- int how)
+static struct dentry *autofs4_expire_indirect(struct super_block *sb,
+ struct vfsmount *mnt,
+ struct autofs_sb_info *sbi,
+ int how)
{
unsigned long timeout;
struct dentry *root = sb->s_root;
@@ -241,7 +302,7 @@ static struct dentry *autofs4_expire(struct super_block *sb,
struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
/* Negative dentry - give up */
- if ( !simple_positive(dentry) ) {
+ if (!simple_positive(dentry)) {
next = next->next;
continue;
}
@@ -249,31 +310,36 @@ static struct dentry *autofs4_expire(struct super_block *sb,
dentry = dget(dentry);
spin_unlock(&dcache_lock);
- /* Case 1: indirect mount or top level direct mount */
+ /*
+ * Case 1: (i) indirect mount or top level pseudo direct mount
+ * (autofs-4.1).
+ * (ii) indirect mount with offset mount, check the "/"
+ * offset (autofs-5.0+).
+ */
if (d_mountpoint(dentry)) {
DPRINTK("checking mountpoint %p %.*s",
dentry, (int)dentry->d_name.len, dentry->d_name.name);
- /* Can we expire this guy */
- if (!autofs4_can_expire(dentry, timeout, do_now))
+ /* Can we umount this guy */
+ if (autofs4_mount_busy(mnt, dentry))
goto next;
- /* Can we umount this guy */
- if (autofs4_check_mount(mnt, dentry)) {
+ /* Can we expire this guy */
+ if (autofs4_can_expire(dentry, timeout, do_now)) {
expired = dentry;
break;
}
goto next;
}
- if ( simple_empty(dentry) )
+ if (simple_empty(dentry))
goto next;
/* Case 2: tree mount, expire iff entire tree is not busy */
if (!exp_leaves) {
/* Lock the tree as we must expire as a whole */
spin_lock(&sbi->fs_lock);
- if (autofs4_check_tree(mnt, dentry, timeout, do_now)) {
+ if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
struct autofs_info *inf = autofs4_dentry_ino(dentry);
/* Set this flag early to catch sys_chdir and the like */
@@ -283,7 +349,10 @@ static struct dentry *autofs4_expire(struct super_block *sb,
break;
}
spin_unlock(&sbi->fs_lock);
- /* Case 3: direct mount, expire individual leaves */
+ /*
+ * Case 3: pseudo direct mount, expire individual leaves
+ * (autofs-4.1).
+ */
} else {
expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
if (expired) {
@@ -297,7 +366,7 @@ next:
next = next->next;
}
- if ( expired ) {
+ if (expired) {
DPRINTK("returning %p %.*s",
expired, (int)expired->d_name.len, expired->d_name.name);
spin_lock(&dcache_lock);
@@ -325,7 +394,7 @@ int autofs4_expire_run(struct super_block *sb,
pkt.hdr.proto_version = sbi->version;
pkt.hdr.type = autofs_ptype_expire;
- if ((dentry = autofs4_expire(sb, mnt, sbi, 0)) == NULL)
+ if ((dentry = autofs4_expire_indirect(sb, mnt, sbi, 0)) == NULL)
return -EAGAIN;
pkt.len = dentry->d_name.len;
@@ -351,17 +420,22 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
if (arg && get_user(do_now, arg))
return -EFAULT;
- if ((dentry = autofs4_expire(sb, mnt, sbi, do_now)) != NULL) {
- struct autofs_info *de_info = autofs4_dentry_ino(dentry);
+ if (sbi->type & AUTOFS_TYPE_DIRECT)
+ dentry = autofs4_expire_direct(sb, mnt, sbi, do_now);
+ else
+ dentry = autofs4_expire_indirect(sb, mnt, sbi, do_now);
+
+ if (dentry) {
+ struct autofs_info *ino = autofs4_dentry_ino(dentry);
/* This is synchronous because it makes the daemon a
little easier */
- de_info->flags |= AUTOFS_INF_EXPIRING;
+ ino->flags |= AUTOFS_INF_EXPIRING;
ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
- de_info->flags &= ~AUTOFS_INF_EXPIRING;
+ ino->flags &= ~AUTOFS_INF_EXPIRING;
dput(dentry);
}
-
+
return ret;
}
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 1ad98d48e55..fde78b110dd 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -3,6 +3,7 @@
* linux/fs/autofs/inode.c
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
+ * Copyright 2005-2006 Ian Kent <raven@themaw.net>
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
@@ -13,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/file.h>
+#include <linux/seq_file.h>
#include <linux/pagemap.h>
#include <linux/parser.h>
#include <linux/bitops.h>
@@ -46,6 +48,7 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
ino->size = 0;
ino->last_used = jiffies;
+ atomic_set(&ino->count, 0);
ino->sbi = sbi;
@@ -64,10 +67,19 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
void autofs4_free_ino(struct autofs_info *ino)
{
+ struct autofs_info *p_ino;
+
if (ino->dentry) {
ino->dentry->d_fsdata = NULL;
- if (ino->dentry->d_inode)
+ if (ino->dentry->d_inode) {
+ struct dentry *parent = ino->dentry->d_parent;
+ if (atomic_dec_and_test(&ino->count)) {
+ p_ino = autofs4_dentry_ino(parent);
+ if (p_ino && parent != ino->dentry)
+ atomic_dec(&p_ino->count);
+ }
dput(ino->dentry);
+ }
ino->dentry = NULL;
}
if (ino->free)
@@ -145,20 +157,44 @@ static void autofs4_put_super(struct super_block *sb)
autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */
/* Clean up and release dangling references */
- if (sbi)
- autofs4_force_release(sbi);
+ autofs4_force_release(sbi);
kfree(sbi);
DPRINTK("shutting down");
}
+static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+ struct autofs_sb_info *sbi = autofs4_sbi(mnt->mnt_sb);
+
+ if (!sbi)
+ return 0;
+
+ seq_printf(m, ",fd=%d", sbi->pipefd);
+ seq_printf(m, ",pgrp=%d", sbi->oz_pgrp);
+ seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ);
+ seq_printf(m, ",minproto=%d", sbi->min_proto);
+ seq_printf(m, ",maxproto=%d", sbi->max_proto);
+
+ if (sbi->type & AUTOFS_TYPE_OFFSET)
+ seq_printf(m, ",offset");
+ else if (sbi->type & AUTOFS_TYPE_DIRECT)
+ seq_printf(m, ",direct");
+ else
+ seq_printf(m, ",indirect");
+
+ return 0;
+}
+
static struct super_operations autofs4_sops = {
.put_super = autofs4_put_super,
.statfs = simple_statfs,
+ .show_options = autofs4_show_options,
};
-enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto};
+enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto,
+ Opt_indirect, Opt_direct, Opt_offset};
static match_table_t tokens = {
{Opt_fd, "fd=%u"},
@@ -167,11 +203,15 @@ static match_table_t tokens = {
{Opt_pgrp, "pgrp=%u"},
{Opt_minproto, "minproto=%u"},
{Opt_maxproto, "maxproto=%u"},
+ {Opt_indirect, "indirect"},
+ {Opt_direct, "direct"},
+ {Opt_offset, "offset"},
{Opt_err, NULL}
};
static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
- pid_t *pgrp, int *minproto, int *maxproto)
+ pid_t *pgrp, unsigned int *type,
+ int *minproto, int *maxproto)
{
char *p;
substring_t args[MAX_OPT_ARGS];
@@ -225,6 +265,15 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
return 1;
*maxproto = option;
break;
+ case Opt_indirect:
+ *type = AUTOFS_TYPE_INDIRECT;
+ break;
+ case Opt_direct:
+ *type = AUTOFS_TYPE_DIRECT;
+ break;
+ case Opt_offset:
+ *type = AUTOFS_TYPE_DIRECT | AUTOFS_TYPE_OFFSET;
+ break;
default:
return 1;
}
@@ -243,6 +292,10 @@ static struct autofs_info *autofs4_mkroot(struct autofs_sb_info *sbi)
return ino;
}
+static struct dentry_operations autofs4_sb_dentry_operations = {
+ .d_release = autofs4_dentry_release,
+};
+
int autofs4_fill_super(struct super_block *s, void *data, int silent)
{
struct inode * root_inode;
@@ -251,7 +304,6 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
int pipefd;
struct autofs_sb_info *sbi;
struct autofs_info *ino;
- int minproto, maxproto;
sbi = (struct autofs_sb_info *) kmalloc(sizeof(*sbi), GFP_KERNEL);
if ( !sbi )
@@ -263,12 +315,16 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
s->s_fs_info = sbi;
sbi->magic = AUTOFS_SBI_MAGIC;
sbi->root = NULL;
+ sbi->pipefd = -1;
sbi->catatonic = 0;
sbi->exp_timeout = 0;
sbi->oz_pgrp = process_group(current);
sbi->sb = s;
sbi->version = 0;
sbi->sub_version = 0;
+ sbi->type = 0;
+ sbi->min_proto = 0;
+ sbi->max_proto = 0;
mutex_init(&sbi->wq_mutex);
spin_lock_init(&sbi->fs_lock);
sbi->queues = NULL;
@@ -285,38 +341,46 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
if (!ino)
goto fail_free;
root_inode = autofs4_get_inode(s, ino);
- kfree(ino);
if (!root_inode)
- goto fail_free;
+ goto fail_ino;
- root_inode->i_op = &autofs4_root_inode_operations;
- root_inode->i_fop = &autofs4_root_operations;
root = d_alloc_root(root_inode);
- pipe = NULL;
-
if (!root)
goto fail_iput;
+ pipe = NULL;
+
+ root->d_op = &autofs4_sb_dentry_operations;
+ root->d_fsdata = ino;
/* Can this call block? */
if (parse_options(data, &pipefd,
&root_inode->i_uid, &root_inode->i_gid,
- &sbi->oz_pgrp,
- &minproto, &maxproto)) {
+ &sbi->oz_pgrp, &sbi->type,
+ &sbi->min_proto, &sbi->max_proto)) {
printk("autofs: called with bogus options\n");
goto fail_dput;
}
+ root_inode->i_fop = &autofs4_root_operations;
+ root_inode->i_op = sbi->type & AUTOFS_TYPE_DIRECT ?
+ &autofs4_direct_root_inode_operations :
+ &autofs4_indirect_root_inode_operations;
+
/* Couldn't this be tested earlier? */
- if (maxproto < AUTOFS_MIN_PROTO_VERSION ||
- minproto > AUTOFS_MAX_PROTO_VERSION) {
+ if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION ||
+ sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) {
printk("autofs: kernel does not match daemon version "
"daemon (%d, %d) kernel (%d, %d)\n",
- minproto, maxproto,
+ sbi->min_proto, sbi->max_proto,
AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION);
goto fail_dput;
}
- sbi->version = maxproto > AUTOFS_MAX_PROTO_VERSION ? AUTOFS_MAX_PROTO_VERSION : maxproto;
+ /* Establish highest kernel protocol version */
+ if (sbi->max_proto > AUTOFS_MAX_PROTO_VERSION)
+ sbi->version = AUTOFS_MAX_PROTO_VERSION;
+ else
+ sbi->version = sbi->max_proto;
sbi->sub_version = AUTOFS_PROTO_SUBVERSION;
DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp);
@@ -329,6 +393,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
if ( !pipe->f_op || !pipe->f_op->write )
goto fail_fput;
sbi->pipe = pipe;
+ sbi->pipefd = pipefd;
/*
* Take a reference to the root dentry so we get a chance to
@@ -356,6 +421,8 @@ fail_dput:
fail_iput:
printk("autofs: get root dentry failed\n");
iput(root_inode);
+fail_ino:
+ kfree(ino);
fail_free:
kfree(sbi);
fail_unlock:
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 62d8d4acb8b..5100f984783 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -4,7 +4,7 @@
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
* Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
- * Copyright 2001-2003 Ian Kent <raven@themaw.net>
+ * Copyright 2001-2006 Ian Kent <raven@themaw.net>
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
@@ -30,9 +30,9 @@ static int autofs4_dir_close(struct inode *inode, struct file *file);
static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
-static int autofs4_dcache_readdir(struct file *, void *, filldir_t);
+static void *autofs4_follow_link(struct dentry *, struct nameidata *);
-struct file_operations autofs4_root_operations = {
+const struct file_operations autofs4_root_operations = {
.open = dcache_dir_open,
.release = dcache_dir_close,
.read = generic_read_dir,
@@ -40,14 +40,14 @@ struct file_operations autofs4_root_operations = {
.ioctl = autofs4_root_ioctl,
};
-struct file_operations autofs4_dir_operations = {
+const struct file_operations autofs4_dir_operations = {
.open = autofs4_dir_open,
.release = autofs4_dir_close,
.read = generic_read_dir,
.readdir = autofs4_dir_readdir,
};
-struct inode_operations autofs4_root_inode_operations = {
+struct inode_operations autofs4_indirect_root_inode_operations = {
.lookup = autofs4_lookup,
.unlink = autofs4_dir_unlink,
.symlink = autofs4_dir_symlink,
@@ -55,6 +55,14 @@ struct inode_operations autofs4_root_inode_operations = {
.rmdir = autofs4_dir_rmdir,
};
+struct inode_operations autofs4_direct_root_inode_operations = {
+ .lookup = autofs4_lookup,
+ .unlink = autofs4_dir_unlink,
+ .mkdir = autofs4_dir_mkdir,
+ .rmdir = autofs4_dir_rmdir,
+ .follow_link = autofs4_follow_link,
+};
+
struct inode_operations autofs4_dir_inode_operations = {
.lookup = autofs4_lookup,
.unlink = autofs4_dir_unlink,
@@ -82,87 +90,7 @@ static int autofs4_root_readdir(struct file *file, void *dirent,
DPRINTK("needs_reghost = %d", sbi->needs_reghost);
- return autofs4_dcache_readdir(file, dirent, filldir);
-}
-
-/* Update usage from here to top of tree, so that scan of
- top-level directories will give a useful result */
-static void autofs4_update_usage(struct vfsmount *mnt, struct dentry *dentry)
-{
- struct dentry *top = dentry->d_sb->s_root;
-
- spin_lock(&dcache_lock);
- for(; dentry != top; dentry = dentry->d_parent) {
- struct autofs_info *ino = autofs4_dentry_ino(dentry);
-
- if (ino) {
- touch_atime(mnt, dentry);
- ino->last_used = jiffies;
- }
- }
- spin_unlock(&dcache_lock);
-}
-
-/*
- * From 2.4 kernel readdir.c
- */
-static int autofs4_dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
-{
- int i;
- struct dentry *dentry = filp->f_dentry;
-
- i = filp->f_pos;
- switch (i) {
- case 0:
- if (filldir(dirent, ".", 1, i, dentry->d_inode->i_ino, DT_DIR) < 0)
- break;
- i++;
- filp->f_pos++;
- /* fallthrough */
- case 1:
- if (filldir(dirent, "..", 2, i, dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
- break;
- i++;
- filp->f_pos++;
- /* fallthrough */
- default: {
- struct list_head *list;
- int j = i-2;
-
- spin_lock(&dcache_lock);
- list = dentry->d_subdirs.next;
-
- for (;;) {
- if (list == &dentry->d_subdirs) {
- spin_unlock(&dcache_lock);
- return 0;
- }
- if (!j)
- break;
- j--;
- list = list->next;
- }
-
- while(1) {
- struct dentry *de = list_entry(list,
- struct dentry, d_u.d_child);
-
- if (!d_unhashed(de) && de->d_inode) {
- spin_unlock(&dcache_lock);
- if (filldir(dirent, de->d_name.name, de->d_name.len, filp->f_pos, de->d_inode->i_ino, DT_UNKNOWN) < 0)
- break;
- spin_lock(&dcache_lock);
- }
- filp->f_pos++;
- list = list->next;
- if (list != &dentry->d_subdirs)
- continue;
- spin_unlock(&dcache_lock);
- break;
- }
- }
- }
- return 0;
+ return dcache_readdir(file, dirent, filldir);
}
static int autofs4_dir_open(struct inode *inode, struct file *file)
@@ -170,8 +98,16 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
struct dentry *dentry = file->f_dentry;
struct vfsmount *mnt = file->f_vfsmnt;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct dentry *cursor;
int status;
+ status = dcache_dir_open(inode, file);
+ if (status)
+ goto out;
+
+ cursor = file->private_data;
+ cursor->d_fsdata = NULL;
+
DPRINTK("file=%p dentry=%p %.*s",
file, dentry, dentry->d_name.len, dentry->d_name.name);
@@ -180,12 +116,15 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
if (autofs4_ispending(dentry)) {
DPRINTK("dentry busy");
- return -EBUSY;
+ dcache_dir_close(inode, file);
+ status = -EBUSY;
+ goto out;
}
+ status = -ENOENT;
if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) {
struct nameidata nd;
- int empty;
+ int empty, ret;
/* In case there are stale directory dentrys from a failed mount */
spin_lock(&dcache_lock);
@@ -195,13 +134,13 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
if (!empty)
d_invalidate(dentry);
- nd.dentry = dentry;
- nd.mnt = mnt;
nd.flags = LOOKUP_DIRECTORY;
- status = (dentry->d_op->d_revalidate)(dentry, &nd);
+ ret = (dentry->d_op->d_revalidate)(dentry, &nd);
- if (!status)
- return -ENOENT;
+ if (!ret) {
+ dcache_dir_close(inode, file);
+ goto out;
+ }
}
if (d_mountpoint(dentry)) {
@@ -212,25 +151,29 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) {
dput(fp_dentry);
mntput(fp_mnt);
- return -ENOENT;
+ dcache_dir_close(inode, file);
+ goto out;
}
fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
status = PTR_ERR(fp);
if (IS_ERR(fp)) {
- file->private_data = NULL;
- return status;
+ dcache_dir_close(inode, file);
+ goto out;
}
- file->private_data = fp;
+ cursor->d_fsdata = fp;
}
-out:
return 0;
+out:
+ return status;
}
static int autofs4_dir_close(struct inode *inode, struct file *file)
{
struct dentry *dentry = file->f_dentry;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct dentry *cursor = file->private_data;
+ int status = 0;
DPRINTK("file=%p dentry=%p %.*s",
file, dentry, dentry->d_name.len, dentry->d_name.name);
@@ -240,26 +183,28 @@ static int autofs4_dir_close(struct inode *inode, struct file *file)
if (autofs4_ispending(dentry)) {
DPRINTK("dentry busy");
- return -EBUSY;
+ status = -EBUSY;
+ goto out;
}
if (d_mountpoint(dentry)) {
- struct file *fp = file->private_data;
-
- if (!fp)
- return -ENOENT;
-
+ struct file *fp = cursor->d_fsdata;
+ if (!fp) {
+ status = -ENOENT;
+ goto out;
+ }
filp_close(fp, current->files);
- file->private_data = NULL;
}
out:
- return 0;
+ dcache_dir_close(inode, file);
+ return status;
}
static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
{
struct dentry *dentry = file->f_dentry;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct dentry *cursor = file->private_data;
int status;
DPRINTK("file=%p dentry=%p %.*s",
@@ -274,7 +219,7 @@ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldi
}
if (d_mountpoint(dentry)) {
- struct file *fp = file->private_data;
+ struct file *fp = cursor->d_fsdata;
if (!fp)
return -ENOENT;
@@ -289,27 +234,26 @@ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldi
return status;
}
out:
- return autofs4_dcache_readdir(file, dirent, filldir);
+ return dcache_readdir(file, dirent, filldir);
}
-static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int flags)
+static int try_to_fill_dentry(struct dentry *dentry, int flags)
{
- struct super_block *sb = mnt->mnt_sb;
- struct autofs_sb_info *sbi = autofs4_sbi(sb);
- struct autofs_info *de_info = autofs4_dentry_ino(dentry);
+ struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct autofs_info *ino = autofs4_dentry_ino(dentry);
int status = 0;
/* Block on any pending expiry here; invalidate the dentry
when expiration is done to trigger mount request with a new
dentry */
- if (de_info && (de_info->flags & AUTOFS_INF_EXPIRING)) {
+ if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
DPRINTK("waiting for expire %p name=%.*s",
dentry, dentry->d_name.len, dentry->d_name.name);
status = autofs4_wait(sbi, dentry, NFY_NONE);
-
+
DPRINTK("expire done status=%d", status);
-
+
/*
* If the directory still exists the mount request must
* continue otherwise it can't be followed at the right
@@ -317,34 +261,36 @@ static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int f
*/
status = d_invalidate(dentry);
if (status != -EBUSY)
- return 0;
+ return -ENOENT;
}
DPRINTK("dentry=%p %.*s ino=%p",
dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
- /* Wait for a pending mount, triggering one if there isn't one already */
+ /*
+ * Wait for a pending mount, triggering one if there
+ * isn't one already
+ */
if (dentry->d_inode == NULL) {
DPRINTK("waiting for mount name=%.*s",
dentry->d_name.len, dentry->d_name.name);
status = autofs4_wait(sbi, dentry, NFY_MOUNT);
-
+
DPRINTK("mount done status=%d", status);
if (status && dentry->d_inode)
- return 0; /* Try to get the kernel to invalidate this dentry */
-
+ return status; /* Try to get the kernel to invalidate this dentry */
+
/* Turn this into a real negative dentry? */
if (status == -ENOENT) {
- dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT;
spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
- return 1;
+ return status;
} else if (status) {
/* Return a negative dentry, but leave it "pending" */
- return 1;
+ return status;
}
/* Trigger mount for path component or follow link */
} else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) ||
@@ -363,19 +309,83 @@ static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int f
spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
- return 0;
+ return status;
}
}
- /* We don't update the usages for the autofs daemon itself, this
- is necessary for recursive autofs mounts */
- if (!autofs4_oz_mode(sbi))
- autofs4_update_usage(mnt, dentry);
+ /* Initialize expiry counter after successful mount */
+ if (ino)
+ ino->last_used = jiffies;
spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
- return 1;
+ return status;
+}
+
+/* For autofs direct mounts the follow link triggers the mount */
+static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct autofs_info *ino = autofs4_dentry_ino(dentry);
+ int oz_mode = autofs4_oz_mode(sbi);
+ unsigned int lookup_type;
+ int status;
+
+ DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d",
+ dentry, dentry->d_name.len, dentry->d_name.name, oz_mode,
+ nd->flags);
+
+ /* If it's our master or we shouldn't trigger a mount we're done */
+ lookup_type = nd->flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY);
+ if (oz_mode || !lookup_type)
+ goto done;
+
+ /* If an expire request is pending wait for it. */
+ if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
+ DPRINTK("waiting for active request %p name=%.*s",
+ dentry, dentry->d_name.len, dentry->d_name.name);
+
+ status = autofs4_wait(sbi, dentry, NFY_NONE);
+
+ DPRINTK("request done status=%d", status);
+ }
+
+ /*
+ * If the dentry contains directories then it is an
+ * autofs multi-mount with no root mount offset. So
+ * don't try to mount it again.
+ */
+ spin_lock(&dcache_lock);
+ if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
+ spin_unlock(&dcache_lock);
+
+ status = try_to_fill_dentry(dentry, 0);
+ if (status)
+ goto out_error;
+
+ /*
+ * The mount succeeded but if there is no root mount
+ * it must be an autofs multi-mount with no root offset
+ * so we don't need to follow the mount.
+ */
+ if (d_mountpoint(dentry)) {
+ if (!autofs4_follow_mount(&nd->mnt, &nd->dentry)) {
+ status = -ENOENT;
+ goto out_error;
+ }
+ }
+
+ goto done;
+ }
+ spin_unlock(&dcache_lock);
+
+done:
+ return NULL;
+
+out_error:
+ path_release(nd);
+ return ERR_PTR(status);
}
/*
@@ -384,47 +394,43 @@ static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int f
* yet completely filled in, and revalidate has to delay such
* lookups..
*/
-static int autofs4_revalidate(struct dentry * dentry, struct nameidata *nd)
+static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
{
- struct inode * dir = dentry->d_parent->d_inode;
+ struct inode *dir = dentry->d_parent->d_inode;
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
int oz_mode = autofs4_oz_mode(sbi);
int flags = nd ? nd->flags : 0;
- int status = 1;
+ int status = 0;
/* Pending dentry */
if (autofs4_ispending(dentry)) {
if (!oz_mode)
- status = try_to_fill_dentry(nd->mnt, dentry, flags);
- return status;
+ status = try_to_fill_dentry(dentry, flags);
+ return !status;
}
/* Negative dentry.. invalidate if "old" */
if (dentry->d_inode == NULL)
- return (dentry->d_time - jiffies <= AUTOFS_NEGATIVE_TIMEOUT);
+ return 0;
/* Check for a non-mountpoint directory with no contents */
spin_lock(&dcache_lock);
if (S_ISDIR(dentry->d_inode->i_mode) &&
!d_mountpoint(dentry) &&
- list_empty(&dentry->d_subdirs)) {
+ __simple_empty(dentry)) {
DPRINTK("dentry=%p %.*s, emptydir",
dentry, dentry->d_name.len, dentry->d_name.name);
spin_unlock(&dcache_lock);
if (!oz_mode)
- status = try_to_fill_dentry(nd->mnt, dentry, flags);
- return status;
+ status = try_to_fill_dentry(dentry, flags);
+ return !status;
}
spin_unlock(&dcache_lock);
- /* Update the usage list */
- if (!oz_mode)
- autofs4_update_usage(nd->mnt, dentry);
-
return 1;
}
-static void autofs4_dentry_release(struct dentry *de)
+void autofs4_dentry_release(struct dentry *de)
{
struct autofs_info *inf;
@@ -462,12 +468,13 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
DPRINTK("name = %.*s",
dentry->d_name.len, dentry->d_name.name);
+ /* File name too long to exist */
if (dentry->d_name.len > NAME_MAX)
- return ERR_PTR(-ENAMETOOLONG);/* File name too long to exist */
+ return ERR_PTR(-ENAMETOOLONG);
sbi = autofs4_sbi(dir->i_sb);
-
oz_mode = autofs4_oz_mode(sbi);
+
DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
current->pid, process_group(current), sbi->catatonic, oz_mode);
@@ -519,7 +526,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
* doesn't do the right thing for all system calls, but it should
* be OK for the operations we permit from an autofs.
*/
- if ( dentry->d_inode && d_unhashed(dentry) )
+ if (dentry->d_inode && d_unhashed(dentry))
return ERR_PTR(-ENOENT);
return NULL;
@@ -531,6 +538,7 @@ static int autofs4_dir_symlink(struct inode *dir,
{
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
+ struct autofs_info *p_ino;
struct inode *inode;
char *cp;
@@ -564,6 +572,10 @@ static int autofs4_dir_symlink(struct inode *dir,
dentry->d_fsdata = ino;
ino->dentry = dget(dentry);
+ atomic_inc(&ino->count);
+ p_ino = autofs4_dentry_ino(dentry->d_parent);
+ if (p_ino && dentry->d_parent != dentry)
+ atomic_inc(&p_ino->count);
ino->inode = inode;
dir->i_mtime = CURRENT_TIME;
@@ -590,11 +602,17 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
{
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
+ struct autofs_info *p_ino;
/* This allows root to remove symlinks */
if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
return -EACCES;
+ if (atomic_dec_and_test(&ino->count)) {
+ p_ino = autofs4_dentry_ino(dentry->d_parent);
+ if (p_ino && dentry->d_parent != dentry)
+ atomic_dec(&p_ino->count);
+ }
dput(ino->dentry);
dentry->d_inode->i_size = 0;
@@ -611,6 +629,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
{
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
+ struct autofs_info *p_ino;
if (!autofs4_oz_mode(sbi))
return -EACCES;
@@ -625,8 +644,12 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
+ if (atomic_dec_and_test(&ino->count)) {
+ p_ino = autofs4_dentry_ino(dentry->d_parent);
+ if (p_ino && dentry->d_parent != dentry)
+ atomic_dec(&p_ino->count);
+ }
dput(ino->dentry);
-
dentry->d_inode->i_size = 0;
dentry->d_inode->i_nlink = 0;
@@ -640,6 +663,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
+ struct autofs_info *p_ino;
struct inode *inode;
if ( !autofs4_oz_mode(sbi) )
@@ -662,6 +686,10 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
dentry->d_fsdata = ino;
ino->dentry = dget(dentry);
+ atomic_inc(&ino->count);
+ p_ino = autofs4_dentry_ino(dentry->d_parent);
+ if (p_ino && dentry->d_parent != dentry)
+ atomic_inc(&p_ino->count);
ino->inode = inode;
dir->i_nlink++;
dir->i_mtime = CURRENT_TIME;
@@ -745,7 +773,7 @@ static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p)
{
int status = 0;
- if (may_umount(mnt) == 0)
+ if (may_umount(mnt))
status = 1;
DPRINTK("returning %d", status);
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index be78e9378c0..ce103e7b0bc 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -3,7 +3,7 @@
* linux/fs/autofs/waitq.c
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- * Copyright 2001-2003 Ian Kent <raven@themaw.net>
+ * Copyright 2001-2006 Ian Kent <raven@themaw.net>
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
@@ -33,7 +33,7 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
sbi->catatonic = 1;
wq = sbi->queues;
sbi->queues = NULL; /* Erase all wait queues */
- while ( wq ) {
+ while (wq) {
nwq = wq->next;
wq->status = -ENOENT; /* Magic is gone - report failure */
kfree(wq->name);
@@ -45,7 +45,6 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
fput(sbi->pipe); /* Close the pipe */
sbi->pipe = NULL;
}
-
shrink_dcache_sb(sbi->sb);
}
@@ -98,7 +97,10 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
pkt.hdr.proto_version = sbi->version;
pkt.hdr.type = type;
- if (type == autofs_ptype_missing) {
+ switch (type) {
+ /* Kernel protocol v4 missing and expire packets */
+ case autofs_ptype_missing:
+ {
struct autofs_packet_missing *mp = &pkt.missing;
pktsz = sizeof(*mp);
@@ -107,7 +109,10 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
mp->len = wq->len;
memcpy(mp->name, wq->name, wq->len);
mp->name[wq->len] = '\0';
- } else if (type == autofs_ptype_expire_multi) {
+ break;
+ }
+ case autofs_ptype_expire_multi:
+ {
struct autofs_packet_expire_multi *ep = &pkt.expire_multi;
pktsz = sizeof(*ep);
@@ -116,7 +121,34 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
ep->len = wq->len;
memcpy(ep->name, wq->name, wq->len);
ep->name[wq->len] = '\0';
- } else {
+ break;
+ }
+ /*
+ * Kernel protocol v5 packet for handling indirect and direct
+ * mount missing and expire requests
+ */
+ case autofs_ptype_missing_indirect:
+ case autofs_ptype_expire_indirect:
+ case autofs_ptype_missing_direct:
+ case autofs_ptype_expire_direct:
+ {
+ struct autofs_v5_packet *packet = &pkt.v5_packet;
+
+ pktsz = sizeof(*packet);
+
+ packet->wait_queue_token = wq->wait_queue_token;
+ packet->len = wq->len;
+ memcpy(packet->name, wq->name, wq->len);
+ packet->name[wq->len] = '\0';
+ packet->dev = wq->dev;
+ packet->ino = wq->ino;
+ packet->uid = wq->uid;
+ packet->gid = wq->gid;
+ packet->pid = wq->pid;
+ packet->tgid = wq->tgid;
+ break;
+ }
+ default:
printk("autofs4_notify_daemon: bad type %d!\n", type);
return;
}
@@ -157,50 +189,94 @@ static int autofs4_getpath(struct autofs_sb_info *sbi,
return len;
}
+static struct autofs_wait_queue *
+autofs4_find_wait(struct autofs_sb_info *sbi,
+ char *name, unsigned int hash, unsigned int len)
+{
+ struct autofs_wait_queue *wq;
+
+ for (wq = sbi->queues; wq; wq = wq->next) {
+ if (wq->hash == hash &&
+ wq->len == len &&
+ wq->name && !memcmp(wq->name, name, len))
+ break;
+ }
+ return wq;
+}
+
int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
enum autofs_notify notify)
{
+ struct autofs_info *ino;
struct autofs_wait_queue *wq;
char *name;
- int len, status;
+ unsigned int len = 0;
+ unsigned int hash = 0;
+ int status, type;
/* In catatonic mode, we don't wait for nobody */
- if ( sbi->catatonic )
+ if (sbi->catatonic)
return -ENOENT;
name = kmalloc(NAME_MAX + 1, GFP_KERNEL);
if (!name)
return -ENOMEM;
- len = autofs4_getpath(sbi, dentry, &name);
- if (!len) {
- kfree(name);
- return -ENOENT;
+ /* If this is a direct mount request create a dummy name */
+ if (IS_ROOT(dentry) && (sbi->type & AUTOFS_TYPE_DIRECT))
+ len = sprintf(name, "%p", dentry);
+ else {
+ len = autofs4_getpath(sbi, dentry, &name);
+ if (!len) {
+ kfree(name);
+ return -ENOENT;
+ }
}
+ hash = full_name_hash(name, len);
if (mutex_lock_interruptible(&sbi->wq_mutex)) {
kfree(name);
return -EINTR;
}
- for (wq = sbi->queues ; wq ; wq = wq->next) {
- if (wq->hash == dentry->d_name.hash &&
- wq->len == len &&
- wq->name && !memcmp(wq->name, name, len))
- break;
- }
+ wq = autofs4_find_wait(sbi, name, hash, len);
+ ino = autofs4_dentry_ino(dentry);
+ if (!wq && ino && notify == NFY_NONE) {
+ /*
+ * Either we've betean the pending expire to post it's
+ * wait or it finished while we waited on the mutex.
+ * So we need to wait till either, the wait appears
+ * or the expire finishes.
+ */
+
+ while (ino->flags & AUTOFS_INF_EXPIRING) {
+ mutex_unlock(&sbi->wq_mutex);
+ schedule_timeout_interruptible(HZ/10);
+ if (mutex_lock_interruptible(&sbi->wq_mutex)) {
+ kfree(name);
+ return -EINTR;
+ }
+ wq = autofs4_find_wait(sbi, name, hash, len);
+ if (wq)
+ break;
+ }
- if ( !wq ) {
- /* Can't wait for an expire if there's no mount */
- if (notify == NFY_NONE && !d_mountpoint(dentry)) {
+ /*
+ * Not ideal but the status has already gone. Of the two
+ * cases where we wait on NFY_NONE neither depend on the
+ * return status of the wait.
+ */
+ if (!wq) {
kfree(name);
mutex_unlock(&sbi->wq_mutex);
- return -ENOENT;
+ return 0;
}
+ }
+ if (!wq) {
/* Create a new wait queue */
wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
- if ( !wq ) {
+ if (!wq) {
kfree(name);
mutex_unlock(&sbi->wq_mutex);
return -ENOMEM;
@@ -212,42 +288,58 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
wq->next = sbi->queues;
sbi->queues = wq;
init_waitqueue_head(&wq->queue);
- wq->hash = dentry->d_name.hash;
+ wq->hash = hash;
wq->name = name;
wq->len = len;
+ wq->dev = autofs4_get_dev(sbi);
+ wq->ino = autofs4_get_ino(sbi);
+ wq->uid = current->uid;
+ wq->gid = current->gid;
+ wq->pid = current->pid;
+ wq->tgid = current->tgid;
wq->status = -EINTR; /* Status return if interrupted */
atomic_set(&wq->wait_ctr, 2);
- atomic_set(&wq->notified, 1);
mutex_unlock(&sbi->wq_mutex);
- } else {
- atomic_inc(&wq->wait_ctr);
- mutex_unlock(&sbi->wq_mutex);
- kfree(name);
- DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
- (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
- }
- if (notify != NFY_NONE && atomic_dec_and_test(&wq->notified)) {
- int type = (notify == NFY_MOUNT ?
- autofs_ptype_missing : autofs_ptype_expire_multi);
+ if (sbi->version < 5) {
+ if (notify == NFY_MOUNT)
+ type = autofs_ptype_missing;
+ else
+ type = autofs_ptype_expire_multi;
+ } else {
+ if (notify == NFY_MOUNT)
+ type = (sbi->type & AUTOFS_TYPE_DIRECT) ?
+ autofs_ptype_missing_direct :
+ autofs_ptype_missing_indirect;
+ else
+ type = (sbi->type & AUTOFS_TYPE_DIRECT) ?
+ autofs_ptype_expire_direct :
+ autofs_ptype_expire_indirect;
+ }
DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
/* autofs4_notify_daemon() may block */
autofs4_notify_daemon(sbi, wq, type);
+ } else {
+ atomic_inc(&wq->wait_ctr);
+ mutex_unlock(&sbi->wq_mutex);
+ kfree(name);
+ DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
+ (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
}
/* wq->name is NULL if and only if the lock is already released */
- if ( sbi->catatonic ) {
+ if (sbi->catatonic) {
/* We might have slept, so check again for catatonic mode */
wq->status = -ENOENT;
kfree(wq->name);
wq->name = NULL;
}
- if ( wq->name ) {
+ if (wq->name) {
/* Block all but "shutdown" signals while waiting */
sigset_t oldset;
unsigned long irqflags;
@@ -283,12 +375,12 @@ int autofs4_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_tok
struct autofs_wait_queue *wq, **wql;
mutex_lock(&sbi->wq_mutex);
- for ( wql = &sbi->queues ; (wq = *wql) != 0 ; wql = &wq->next ) {
- if ( wq->wait_queue_token == wait_queue_token )
+ for (wql = &sbi->queues ; (wq = *wql) != 0 ; wql = &wq->next) {
+ if (wq->wait_queue_token == wait_queue_token)
break;
}
- if ( !wq ) {
+ if (!wq) {
mutex_unlock(&sbi->wq_mutex);
return -EINVAL;
}
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index e172180a1d8..80599ae3396 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -22,7 +22,7 @@ static int return_EIO(void)
#define EIO_ERROR ((void *) (return_EIO))
-static struct file_operations bad_file_ops =
+static const struct file_operations bad_file_ops =
{
.llseek = EIO_ERROR,
.aio_read = EIO_ERROR,
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 044a5958782..68ebd10f345 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -64,7 +64,7 @@ static const struct super_operations befs_sops = {
/* slab cache for befs_inode_info objects */
static kmem_cache_t *befs_inode_cachep;
-static struct file_operations befs_dir_operations = {
+static const struct file_operations befs_dir_operations = {
.read = generic_read_dir,
.readdir = befs_readdir,
};
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h
index 1fbc53f14ab..9d791004b21 100644
--- a/fs/bfs/bfs.h
+++ b/fs/bfs/bfs.h
@@ -49,11 +49,11 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode)
/* file.c */
extern struct inode_operations bfs_file_inops;
-extern struct file_operations bfs_file_operations;
+extern const struct file_operations bfs_file_operations;
extern struct address_space_operations bfs_aops;
/* dir.c */
extern struct inode_operations bfs_dir_inops;
-extern struct file_operations bfs_dir_operations;
+extern const struct file_operations bfs_dir_operations;
#endif /* _FS_BFS_BFS_H */
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 5af928fa044..26fad962173 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -70,7 +70,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
return 0;
}
-struct file_operations bfs_dir_operations = {
+const struct file_operations bfs_dir_operations = {
.read = generic_read_dir,
.readdir = bfs_readdir,
.fsync = file_fsync,
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index 807723b65da..d83cd74a2e4 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -17,7 +17,7 @@
#define dprintf(x...)
#endif
-struct file_operations bfs_file_operations = {
+const struct file_operations bfs_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 69f44dcdb0b..b1c902e319c 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -428,7 +428,6 @@ static int load_flat_file(struct linux_binprm * bprm,
loff_t fpos;
unsigned long start_code, end_code;
int ret;
- int exec_fileno;
hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
inode = bprm->file->f_dentry->d_inode;
@@ -502,21 +501,12 @@ static int load_flat_file(struct linux_binprm * bprm,
goto err;
}
- /* check file descriptor */
- exec_fileno = get_unused_fd();
- if (exec_fileno < 0) {
- ret = -EMFILE;
- goto err;
- }
- get_file(bprm->file);
- fd_install(exec_fileno, bprm->file);
-
/* Flush all traces of the currently running executable */
if (id == 0) {
result = flush_old_exec(bprm);
if (result) {
ret = result;
- goto err_close;
+ goto err;
}
/* OK, This is the point of no return */
@@ -548,7 +538,7 @@ static int load_flat_file(struct linux_binprm * bprm,
textpos = (unsigned long) -ENOMEM;
printk("Unable to mmap process text, errno %d\n", (int)-textpos);
ret = textpos;
- goto err_close;
+ goto err;
}
down_write(&current->mm->mmap_sem);
@@ -564,7 +554,7 @@ static int load_flat_file(struct linux_binprm * bprm,
(int)-datapos);
do_munmap(current->mm, textpos, text_len);
ret = realdatastart;
- goto err_close;
+ goto err;
}
datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
@@ -587,7 +577,7 @@ static int load_flat_file(struct linux_binprm * bprm,
do_munmap(current->mm, textpos, text_len);
do_munmap(current->mm, realdatastart, data_len + extra);
ret = result;
- goto err_close;
+ goto err;
}
reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
@@ -606,7 +596,7 @@ static int load_flat_file(struct linux_binprm * bprm,
printk("Unable to allocate RAM for process text/data, errno %d\n",
(int)-textpos);
ret = textpos;
- goto err_close;
+ goto err;
}
realdatastart = textpos + ntohl(hdr->data_start);
@@ -652,7 +642,7 @@ static int load_flat_file(struct linux_binprm * bprm,
do_munmap(current->mm, textpos, text_len + data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long));
ret = result;
- goto err_close;
+ goto err;
}
}
@@ -717,7 +707,7 @@ static int load_flat_file(struct linux_binprm * bprm,
addr = calc_reloc(*rp, libinfo, id, 0);
if (addr == RELOC_FAILED) {
ret = -ENOEXEC;
- goto err_close;
+ goto err;
}
*rp = addr;
}
@@ -747,7 +737,7 @@ static int load_flat_file(struct linux_binprm * bprm,
rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
if (rp == (unsigned long *)RELOC_FAILED) {
ret = -ENOEXEC;
- goto err_close;
+ goto err;
}
/* Get the pointer's value. */
@@ -762,7 +752,7 @@ static int load_flat_file(struct linux_binprm * bprm,
addr = calc_reloc(addr, libinfo, id, 0);
if (addr == RELOC_FAILED) {
ret = -ENOEXEC;
- goto err_close;
+ goto err;
}
/* Write back the relocated pointer. */
@@ -783,8 +773,6 @@ static int load_flat_file(struct linux_binprm * bprm,
stack_len);
return 0;
-err_close:
- sys_close(exec_fileno);
err:
return ret;
}
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 6a7b730c206..d73d75591a3 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -600,7 +600,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
return count;
}
-static struct file_operations bm_entry_operations = {
+static const struct file_operations bm_entry_operations = {
.read = bm_entry_read,
.write = bm_entry_write,
};
@@ -668,7 +668,7 @@ out:
return count;
}
-static struct file_operations bm_register_operations = {
+static const struct file_operations bm_register_operations = {
.write = bm_register_write,
};
@@ -715,7 +715,7 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer,
return count;
}
-static struct file_operations bm_status_operations = {
+static const struct file_operations bm_status_operations = {
.read = bm_status_read,
.write = bm_status_write,
};
diff --git a/fs/bio.c b/fs/bio.c
index eb8fbc53f2c..098c12b2d60 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1116,6 +1116,9 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
bp->bio1.bi_io_vec = &bp->bv1;
bp->bio2.bi_io_vec = &bp->bv2;
+ bp->bio1.bi_max_vecs = 1;
+ bp->bio2.bi_max_vecs = 1;
+
bp->bio1.bi_end_io = bio_pair_end_1;
bp->bio2.bi_end_io = bio_pair_end_2;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 5983d42df01..f5958f413bd 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -266,6 +266,9 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
mutex_init(&bdev->bd_mount_mutex);
INIT_LIST_HEAD(&bdev->bd_inodes);
INIT_LIST_HEAD(&bdev->bd_list);
+#ifdef CONFIG_SYSFS
+ INIT_LIST_HEAD(&bdev->bd_holder_list);
+#endif
inode_init_once(&ei->vfs_inode);
}
}
@@ -490,6 +493,300 @@ void bd_release(struct block_device *bdev)
EXPORT_SYMBOL(bd_release);
+#ifdef CONFIG_SYSFS
+/*
+ * Functions for bd_claim_by_kobject / bd_release_from_kobject
+ *
+ * If a kobject is passed to bd_claim_by_kobject()
+ * and the kobject has a parent directory,
+ * following symlinks are created:
+ * o from the kobject to the claimed bdev
+ * o from "holders" directory of the bdev to the parent of the kobject
+ * bd_release_from_kobject() removes these symlinks.
+ *
+ * Example:
+ * If /dev/dm-0 maps to /dev/sda, kobject corresponding to
+ * /sys/block/dm-0/slaves is passed to bd_claim_by_kobject(), then:
+ * /sys/block/dm-0/slaves/sda --> /sys/block/sda
+ * /sys/block/sda/holders/dm-0 --> /sys/block/dm-0
+ */
+
+static struct kobject *bdev_get_kobj(struct block_device *bdev)
+{
+ if (bdev->bd_contains != bdev)
+ return kobject_get(&bdev->bd_part->kobj);
+ else
+ return kobject_get(&bdev->bd_disk->kobj);
+}
+
+static struct kobject *bdev_get_holder(struct block_device *bdev)
+{
+ if (bdev->bd_contains != bdev)
+ return kobject_get(bdev->bd_part->holder_dir);
+ else
+ return kobject_get(bdev->bd_disk->holder_dir);
+}
+
+static void add_symlink(struct kobject *from, struct kobject *to)
+{
+ if (!from || !to)
+ return;
+ sysfs_create_link(from, to, kobject_name(to));
+}
+
+static void del_symlink(struct kobject *from, struct kobject *to)
+{
+ if (!from || !to)
+ return;
+ sysfs_remove_link(from, kobject_name(to));
+}
+
+/*
+ * 'struct bd_holder' contains pointers to kobjects symlinked by
+ * bd_claim_by_kobject.
+ * It's connected to bd_holder_list which is protected by bdev->bd_sem.
+ */
+struct bd_holder {
+ struct list_head list; /* chain of holders of the bdev */
+ int count; /* references from the holder */
+ struct kobject *sdir; /* holder object, e.g. "/block/dm-0/slaves" */
+ struct kobject *hdev; /* e.g. "/block/dm-0" */
+ struct kobject *hdir; /* e.g. "/block/sda/holders" */
+ struct kobject *sdev; /* e.g. "/block/sda" */
+};
+
+/*
+ * Get references of related kobjects at once.
+ * Returns 1 on success. 0 on failure.
+ *
+ * Should call bd_holder_release_dirs() after successful use.
+ */
+static int bd_holder_grab_dirs(struct block_device *bdev,
+ struct bd_holder *bo)
+{
+ if (!bdev || !bo)
+ return 0;
+
+ bo->sdir = kobject_get(bo->sdir);
+ if (!bo->sdir)
+ return 0;
+
+ bo->hdev = kobject_get(bo->sdir->parent);
+ if (!bo->hdev)
+ goto fail_put_sdir;
+
+ bo->sdev = bdev_get_kobj(bdev);
+ if (!bo->sdev)
+ goto fail_put_hdev;
+
+ bo->hdir = bdev_get_holder(bdev);
+ if (!bo->hdir)
+ goto fail_put_sdev;
+
+ return 1;
+
+fail_put_sdev:
+ kobject_put(bo->sdev);
+fail_put_hdev:
+ kobject_put(bo->hdev);
+fail_put_sdir:
+ kobject_put(bo->sdir);
+
+ return 0;
+}
+
+/* Put references of related kobjects at once. */
+static void bd_holder_release_dirs(struct bd_holder *bo)
+{
+ kobject_put(bo->hdir);
+ kobject_put(bo->sdev);
+ kobject_put(bo->hdev);
+ kobject_put(bo->sdir);
+}
+
+static struct bd_holder *alloc_bd_holder(struct kobject *kobj)
+{
+ struct bd_holder *bo;
+
+ bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+ if (!bo)
+ return NULL;
+
+ bo->count = 1;
+ bo->sdir = kobj;
+
+ return bo;
+}
+
+static void free_bd_holder(struct bd_holder *bo)
+{
+ kfree(bo);
+}
+
+/**
+ * add_bd_holder - create sysfs symlinks for bd_claim() relationship
+ *
+ * @bdev: block device to be bd_claimed
+ * @bo: preallocated and initialized by alloc_bd_holder()
+ *
+ * If there is no matching entry with @bo in @bdev->bd_holder_list,
+ * add @bo to the list, create symlinks.
+ *
+ * Returns 1 if @bo was added to the list.
+ * Returns 0 if @bo wasn't used by any reason and should be freed.
+ */
+static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
+{
+ struct bd_holder *tmp;
+
+ if (!bo)
+ return 0;
+
+ list_for_each_entry(tmp, &bdev->bd_holder_list, list) {
+ if (tmp->sdir == bo->sdir) {
+ tmp->count++;
+ return 0;
+ }
+ }
+
+ if (!bd_holder_grab_dirs(bdev, bo))
+ return 0;
+
+ add_symlink(bo->sdir, bo->sdev);
+ add_symlink(bo->hdir, bo->hdev);
+ list_add_tail(&bo->list, &bdev->bd_holder_list);
+ return 1;
+}
+
+/**
+ * del_bd_holder - delete sysfs symlinks for bd_claim() relationship
+ *
+ * @bdev: block device to be bd_claimed
+ * @kobj: holder's kobject
+ *
+ * If there is matching entry with @kobj in @bdev->bd_holder_list
+ * and no other bd_claim() from the same kobject,
+ * remove the struct bd_holder from the list, delete symlinks for it.
+ *
+ * Returns a pointer to the struct bd_holder when it's removed from the list
+ * and ready to be freed.
+ * Returns NULL if matching claim isn't found or there is other bd_claim()
+ * by the same kobject.
+ */
+static struct bd_holder *del_bd_holder(struct block_device *bdev,
+ struct kobject *kobj)
+{
+ struct bd_holder *bo;
+
+ list_for_each_entry(bo, &bdev->bd_holder_list, list) {
+ if (bo->sdir == kobj) {
+ bo->count--;
+ BUG_ON(bo->count < 0);
+ if (!bo->count) {
+ list_del(&bo->list);
+ del_symlink(bo->sdir, bo->sdev);
+ del_symlink(bo->hdir, bo->hdev);
+ bd_holder_release_dirs(bo);
+ return bo;
+ }
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * bd_claim_by_kobject - bd_claim() with additional kobject signature
+ *
+ * @bdev: block device to be claimed
+ * @holder: holder's signature
+ * @kobj: holder's kobject
+ *
+ * Do bd_claim() and if it succeeds, create sysfs symlinks between
+ * the bdev and the holder's kobject.
+ * Use bd_release_from_kobject() when relesing the claimed bdev.
+ *
+ * Returns 0 on success. (same as bd_claim())
+ * Returns errno on failure.
+ */
+static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
+ struct kobject *kobj)
+{
+ int res;
+ struct bd_holder *bo;
+
+ if (!kobj)
+ return -EINVAL;
+
+ bo = alloc_bd_holder(kobj);
+ if (!bo)
+ return -ENOMEM;
+
+ mutex_lock(&bdev->bd_mutex);
+ res = bd_claim(bdev, holder);
+ if (res || !add_bd_holder(bdev, bo))
+ free_bd_holder(bo);
+ mutex_unlock(&bdev->bd_mutex);
+
+ return res;
+}
+
+/**
+ * bd_release_from_kobject - bd_release() with additional kobject signature
+ *
+ * @bdev: block device to be released
+ * @kobj: holder's kobject
+ *
+ * Do bd_release() and remove sysfs symlinks created by bd_claim_by_kobject().
+ */
+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);
+ mutex_unlock(&bdev->bd_mutex);
+}
+
+/**
+ * bd_claim_by_disk - wrapper function for bd_claim_by_kobject()
+ *
+ * @bdev: block device to be claimed
+ * @holder: holder's signature
+ * @disk: holder's gendisk
+ *
+ * Call bd_claim_by_kobject() with getting @disk->slave_dir.
+ */
+int bd_claim_by_disk(struct block_device *bdev, void *holder,
+ struct gendisk *disk)
+{
+ return bd_claim_by_kobject(bdev, holder, kobject_get(disk->slave_dir));
+}
+EXPORT_SYMBOL_GPL(bd_claim_by_disk);
+
+/**
+ * bd_release_from_disk - wrapper function for bd_release_from_kobject()
+ *
+ * @bdev: block device to be claimed
+ * @disk: holder's gendisk
+ *
+ * Call bd_release_from_kobject() and put @disk->slave_dir.
+ */
+void bd_release_from_disk(struct block_device *bdev, struct gendisk *disk)
+{
+ bd_release_from_kobject(bdev, disk->slave_dir);
+ kobject_put(disk->slave_dir);
+}
+EXPORT_SYMBOL_GPL(bd_release_from_disk);
+#endif
+
/*
* Tries to open block device by device number. Use it ONLY if you
* really do not have anything better - i.e. when you are behind a
@@ -790,7 +1087,7 @@ struct address_space_operations def_blk_aops = {
.direct_IO = blkdev_direct_IO,
};
-struct file_operations def_blk_fops = {
+const struct file_operations def_blk_fops = {
.open = blkdev_open,
.release = blkdev_close,
.llseek = block_llseek,
@@ -807,6 +1104,8 @@ struct file_operations def_blk_fops = {
.readv = generic_file_readv,
.writev = generic_file_write_nolock,
.sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
+ .splice_write = generic_file_splice_write,
};
int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
diff --git a/fs/buffer.c b/fs/buffer.c
index d597758dd12..23f1f3a6807 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -493,7 +493,7 @@ static void free_more_memory(void)
wakeup_pdflush(1024);
yield();
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones;
if (*zones)
try_to_free_pages(zones, GFP_NOFS);
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 8c6eb04d31e..f3418f7a6e9 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
+#include <linux/seq_file.h>
#include <linux/kobject.h>
#include <linux/kobj_map.h>
@@ -27,8 +28,6 @@
static struct kobj_map *cdev_map;
-#define MAX_PROBE_HASH 255 /* random */
-
static DEFINE_MUTEX(chrdevs_lock);
static struct char_device_struct {
@@ -39,93 +38,29 @@ static struct char_device_struct {
char name[64];
struct file_operations *fops;
struct cdev *cdev; /* will die */
-} *chrdevs[MAX_PROBE_HASH];
+} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
/* index in the above */
static inline int major_to_index(int major)
{
- return major % MAX_PROBE_HASH;
-}
-
-struct chrdev_info {
- int index;
- struct char_device_struct *cd;
-};
-
-void *get_next_chrdev(void *dev)
-{
- struct chrdev_info *info;
-
- if (dev == NULL) {
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info)
- goto out;
- info->index=0;
- info->cd = chrdevs[info->index];
- if (info->cd)
- goto out;
- } else {
- info = dev;
- }
-
- while (info->index < ARRAY_SIZE(chrdevs)) {
- if (info->cd)
- info->cd = info->cd->next;
- if (info->cd)
- goto out;
- /*
- * No devices on this chain, move to the next
- */
- info->index++;
- info->cd = (info->index < ARRAY_SIZE(chrdevs)) ?
- chrdevs[info->index] : NULL;
- if (info->cd)
- goto out;
- }
-
-out:
- return info;
-}
-
-void *acquire_chrdev_list(void)
-{
- mutex_lock(&chrdevs_lock);
- return get_next_chrdev(NULL);
-}
-
-void release_chrdev_list(void *dev)
-{
- mutex_unlock(&chrdevs_lock);
- kfree(dev);
+ return major % CHRDEV_MAJOR_HASH_SIZE;
}
+#ifdef CONFIG_PROC_FS
-int count_chrdev_list(void)
+void chrdev_show(struct seq_file *f, off_t offset)
{
struct char_device_struct *cd;
- int i, count;
-
- count = 0;
- for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
- for (cd = chrdevs[i]; cd; cd = cd->next)
- count++;
+ if (offset < CHRDEV_MAJOR_HASH_SIZE) {
+ mutex_lock(&chrdevs_lock);
+ for (cd = chrdevs[offset]; cd; cd = cd->next)
+ seq_printf(f, "%3d %s\n", cd->major, cd->name);
+ mutex_unlock(&chrdevs_lock);
}
-
- return count;
}
-int get_chrdev_info(void *dev, int *major, char **name)
-{
- struct chrdev_info *info = dev;
-
- if (info->cd == NULL)
- return 1;
-
- *major = info->cd->major;
- *name = info->cd->name;
- return 0;
-}
+#endif /* CONFIG_PROC_FS */
/*
* Register a single major with a specified minor range.
@@ -250,7 +185,7 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
}
int register_chrdev(unsigned int major, const char *name,
- struct file_operations *fops)
+ const struct file_operations *fops)
{
struct char_device_struct *cd;
struct cdev *cdev;
@@ -406,7 +341,7 @@ static void cdev_purge(struct cdev *cdev)
* is contain the open that then fills in the correct operations
* depending on the special file...
*/
-struct file_operations def_chr_fops = {
+const struct file_operations def_chr_fops = {
.open = chrdev_open,
};
@@ -473,7 +408,7 @@ struct cdev *cdev_alloc(void)
return p;
}
-void cdev_init(struct cdev *cdev, struct file_operations *fops)
+void cdev_init(struct cdev *cdev, const struct file_operations *fops)
{
memset(cdev, 0, sizeof *cdev);
INIT_LIST_HEAD(&cdev->list);
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index cb68efba35d..7271bb0257f 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,32 @@
+Version 1.43
+------------
+POSIX locking to servers which support CIFS POSIX Extensions
+(disabled by default controlled by proc/fs/cifs/Experimental).
+Handle conversion of long share names (especially Asian languages)
+to Unicode during mount.
+
+Version 1.42
+------------
+Fix slow oplock break when mounted to different servers at the same time and
+the tids match and we try to find matching fid on wrong server. Fix read
+looping when signing required by server (2.6.16 kernel only). Fix readdir
+vs. rename race which could cause each to hang. Return . and .. even
+if server does not. Allow searches to skip first three entries and
+begin at any location. Fix oops in find_writeable_file.
+
+Version 1.41
+------------
+Fix NTLMv2 security (can be enabled in /proc/fs/cifs) so customers can
+configure stronger authentication. Fix sfu symlinks so they can
+be followed (not just recognized). Fix wraparound of bcc on
+read responses when buffer size over 64K and also fix wrap of
+max smb buffer size when CIFSMaxBufSize over 64K. Fix oops in
+cifs_user_read and cifs_readpages (when EAGAIN on send of smb
+on socket is returned over and over). Add POSIX (advisory) byte range
+locking support (requires server with newest CIFS UNIX Extensions
+to the protocol implemented). Slow down negprot slightly in port 139
+RFC1001 case to give session_init time on buggy servers.
+
Version 1.40
------------
Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 7384947a0f9..58c77254a23 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -3,4 +3,4 @@
#
obj-$(CONFIG_CIFS) += cifs.o
-cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o
+cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o ntlmssp.o
diff --git a/fs/cifs/README b/fs/cifs/README
index b0070d1b149..0355003f4f0 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -422,6 +422,13 @@ A partial list of the supported mount options follows:
nomapchars Do not translate any of these seven characters (default).
nocase Request case insensitive path name matching (case
sensitive is the default if the server suports it).
+ posixpaths If CIFS Unix extensions are supported, attempt to
+ negotiate posix path name support which allows certain
+ characters forbidden in typical CIFS filenames, without
+ requiring remapping. (default)
+ noposixpaths If CIFS Unix extensions are supported, do not request
+ posix path name support (this may cause servers to
+ reject creatingfile with certain reserved characters).
nobrl Do not send byte range lock requests to the server.
This is necessary for certain applications that break
with cifs style mandatory byte range locks (and most
@@ -504,6 +511,14 @@ LinuxExtensionsEnabled If set to one then the client will attempt to
support and want to map the uid and gid fields
to values supplied at mount (rather than the
actual values, then set this to zero. (default 1)
+Experimental When set to 1 used to enable certain experimental
+ features (currently enables multipage writes
+ when signing is enabled, the multipage write
+ performance enhancement was disabled when
+ signing turned on in case buffer was modified
+ just before it was sent, also this flag will
+ be used to use the new experimental sessionsetup
+ code).
These experimental features and tracing can be enabled by changing flags in
/proc/fs/cifs (after the cifs module has been installed or built into the
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index a2c24858d40..e7d63737e65 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifsencrypt.c
*
- * Copyright (C) International Business Machines Corp., 2005
+ * Copyright (C) International Business Machines Corp., 2005,2006
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -36,7 +36,8 @@
extern void mdfour(unsigned char *out, unsigned char *in, int n);
extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
-static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature)
+static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
+ const char * key, char * signature)
{
struct MD5Context context;
@@ -56,9 +57,6 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
int rc = 0;
char smb_signature[20];
- /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
- /* BB remember to add code to save expected sequence number in midQ entry BB */
-
if((cifs_pdu == NULL) || (server == NULL))
return -EINVAL;
@@ -85,20 +83,33 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
const char * key, char * signature)
{
- struct MD5Context context;
-
- if((iov == NULL) || (signature == NULL))
- return -EINVAL;
+ struct MD5Context context;
+ int i;
- MD5Init(&context);
- MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+ if((iov == NULL) || (signature == NULL))
+ return -EINVAL;
-/* MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */
+ MD5Init(&context);
+ MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+ for(i=0;i<n_vec;i++) {
+ if(iov[i].iov_base == NULL) {
+ cERROR(1,("null iovec entry"));
+ return -EIO;
+ } else if(iov[i].iov_len == 0)
+ break; /* bail out if we are sent nothing to sign */
+ /* The first entry includes a length field (which does not get
+ signed that occupies the first 4 bytes before the header */
+ if(i==0) {
+ if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
+ break; /* nothing to sign or corrupt header */
+ MD5Update(&context,iov[0].iov_base+4, iov[0].iov_len-4);
+ } else
+ MD5Update(&context,iov[i].iov_base, iov[i].iov_len);
+ }
- MD5Final(signature,&context);
+ MD5Final(signature,&context);
- return -EOPNOTSUPP;
-/* return 0; */
+ return 0;
}
@@ -259,4 +270,5 @@ void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_respon
/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
hmac_md5_final(v2_session_response,&context);
+ cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); /* BB removeme BB */
}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 6b99b51d669..c262d8874ce 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -33,6 +33,7 @@
#include <linux/vfs.h>
#include <linux/mempool.h>
#include <linux/delay.h>
+#include <linux/kthread.h>
#include "cifsfs.h"
#include "cifspdu.h"
#define DECLARE_GLOBALS_HERE
@@ -75,9 +76,6 @@ unsigned int cifs_max_pending = CIFS_MAX_REQ;
module_param(cifs_max_pending, int, 0);
MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
-static DECLARE_COMPLETION(cifs_oplock_exited);
-static DECLARE_COMPLETION(cifs_dnotify_exited);
-
extern mempool_t *cifs_sm_req_poolp;
extern mempool_t *cifs_req_poolp;
extern mempool_t *cifs_mid_poolp;
@@ -93,13 +91,10 @@ cifs_read_super(struct super_block *sb, void *data,
int rc = 0;
sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
- sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
+ sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
cifs_sb = CIFS_SB(sb);
if(cifs_sb == NULL)
return -ENOMEM;
- else
- memset(cifs_sb,0,sizeof(struct cifs_sb_info));
-
rc = cifs_mount(sb, cifs_sb, data, devname);
@@ -583,7 +578,7 @@ struct inode_operations cifs_symlink_inode_ops = {
#endif
};
-struct file_operations cifs_file_ops = {
+const struct file_operations cifs_file_ops = {
.read = do_sync_read,
.write = do_sync_write,
.readv = generic_file_readv,
@@ -607,7 +602,7 @@ struct file_operations cifs_file_ops = {
#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
-struct file_operations cifs_file_direct_ops = {
+const struct file_operations cifs_file_direct_ops = {
/* no mmap, no aio, no readv -
BB reevaluate whether they can be done with directio, no cache */
.read = cifs_user_read,
@@ -626,7 +621,7 @@ struct file_operations cifs_file_direct_ops = {
.dir_notify = cifs_dir_notify,
#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
-struct file_operations cifs_file_nobrl_ops = {
+const struct file_operations cifs_file_nobrl_ops = {
.read = do_sync_read,
.write = do_sync_write,
.readv = generic_file_readv,
@@ -649,7 +644,7 @@ struct file_operations cifs_file_nobrl_ops = {
#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
-struct file_operations cifs_file_direct_nobrl_ops = {
+const struct file_operations cifs_file_direct_nobrl_ops = {
/* no mmap, no aio, no readv -
BB reevaluate whether they can be done with directio, no cache */
.read = cifs_user_read,
@@ -668,7 +663,7 @@ struct file_operations cifs_file_direct_nobrl_ops = {
#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
-struct file_operations cifs_dir_ops = {
+const struct file_operations cifs_dir_ops = {
.readdir = cifs_readdir,
.release = cifs_closedir,
.read = generic_read_dir,
@@ -844,10 +839,6 @@ static int cifs_oplock_thread(void * dummyarg)
__u16 netfid;
int rc;
- daemonize("cifsoplockd");
- allow_signal(SIGTERM);
-
- oplockThread = current;
do {
if (try_to_freeze())
continue;
@@ -903,9 +894,9 @@ static int cifs_oplock_thread(void * dummyarg)
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1); /* yield in case q were corrupt */
}
- } while(!signal_pending(current));
- oplockThread = NULL;
- complete_and_exit (&cifs_oplock_exited, 0);
+ } while (!kthread_should_stop());
+
+ return 0;
}
static int cifs_dnotify_thread(void * dummyarg)
@@ -913,10 +904,6 @@ static int cifs_dnotify_thread(void * dummyarg)
struct list_head *tmp;
struct cifsSesInfo *ses;
- daemonize("cifsdnotifyd");
- allow_signal(SIGTERM);
-
- dnotifyThread = current;
do {
if(try_to_freeze())
continue;
@@ -934,8 +921,9 @@ static int cifs_dnotify_thread(void * dummyarg)
wake_up_all(&ses->server->response_q);
}
read_unlock(&GlobalSMBSeslock);
- } while(!signal_pending(current));
- complete_and_exit (&cifs_dnotify_exited, 0);
+ } while (!kthread_should_stop());
+
+ return 0;
}
static int __init
@@ -985,32 +973,48 @@ init_cifs(void)
}
rc = cifs_init_inodecache();
- if (!rc) {
- rc = cifs_init_mids();
- if (!rc) {
- rc = cifs_init_request_bufs();
- if (!rc) {
- rc = register_filesystem(&cifs_fs_type);
- if (!rc) {
- rc = (int)kernel_thread(cifs_oplock_thread, NULL,
- CLONE_FS | CLONE_FILES | CLONE_VM);
- if(rc > 0) {
- rc = (int)kernel_thread(cifs_dnotify_thread, NULL,
- CLONE_FS | CLONE_FILES | CLONE_VM);
- if(rc > 0)
- return 0;
- else
- cERROR(1,("error %d create dnotify thread", rc));
- } else {
- cERROR(1,("error %d create oplock thread",rc));
- }
- }
- cifs_destroy_request_bufs();
- }
- cifs_destroy_mids();
- }
- cifs_destroy_inodecache();
+ if (rc)
+ goto out_clean_proc;
+
+ rc = cifs_init_mids();
+ if (rc)
+ goto out_destroy_inodecache;
+
+ rc = cifs_init_request_bufs();
+ if (rc)
+ goto out_destroy_mids;
+
+ rc = register_filesystem(&cifs_fs_type);
+ if (rc)
+ goto out_destroy_request_bufs;
+
+ oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
+ if (IS_ERR(oplockThread)) {
+ rc = PTR_ERR(oplockThread);
+ cERROR(1,("error %d create oplock thread", rc));
+ goto out_unregister_filesystem;
+ }
+
+ dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
+ if (IS_ERR(dnotifyThread)) {
+ rc = PTR_ERR(dnotifyThread);
+ cERROR(1,("error %d create dnotify thread", rc));
+ goto out_stop_oplock_thread;
}
+
+ return 0;
+
+ out_stop_oplock_thread:
+ kthread_stop(oplockThread);
+ out_unregister_filesystem:
+ unregister_filesystem(&cifs_fs_type);
+ out_destroy_request_bufs:
+ cifs_destroy_request_bufs();
+ out_destroy_mids:
+ cifs_destroy_mids();
+ out_destroy_inodecache:
+ cifs_destroy_inodecache();
+ out_clean_proc:
#ifdef CONFIG_PROC_FS
cifs_proc_clean();
#endif
@@ -1028,14 +1032,8 @@ exit_cifs(void)
cifs_destroy_inodecache();
cifs_destroy_mids();
cifs_destroy_request_bufs();
- if(oplockThread) {
- send_sig(SIGTERM, oplockThread, 1);
- wait_for_completion(&cifs_oplock_exited);
- }
- if(dnotifyThread) {
- send_sig(SIGTERM, dnotifyThread, 1);
- wait_for_completion(&cifs_dnotify_exited);
- }
+ kthread_stop(oplockThread);
+ kthread_stop(dnotifyThread);
}
MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 821a8eb2255..c98755dca86 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -61,10 +61,10 @@ extern struct inode_operations cifs_file_inode_ops;
extern struct inode_operations cifs_symlink_inode_ops;
/* Functions related to files and directories */
-extern struct file_operations cifs_file_ops;
-extern struct file_operations cifs_file_direct_ops; /* if directio mount */
-extern struct file_operations cifs_file_nobrl_ops;
-extern struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */
+extern const struct file_operations cifs_file_ops;
+extern const struct file_operations cifs_file_direct_ops; /* if directio mount */
+extern const struct file_operations cifs_file_nobrl_ops;
+extern const struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */
extern int cifs_open(struct inode *inode, struct file *file);
extern int cifs_close(struct inode *inode, struct file *file);
extern int cifs_closedir(struct inode *inode, struct file *file);
@@ -76,7 +76,7 @@ extern int cifs_lock(struct file *, int, struct file_lock *);
extern int cifs_fsync(struct file *, struct dentry *, int);
extern int cifs_flush(struct file *);
extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
-extern struct file_operations cifs_dir_ops;
+extern const struct file_operations cifs_dir_ops;
extern int cifs_dir_open(struct inode *inode, struct file *file);
extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
extern int cifs_dir_notify(struct file *, unsigned long arg);
@@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl (struct inode * inode, struct file * filep,
unsigned int command, unsigned long arg);
-#define CIFS_VERSION "1.40"
+#define CIFS_VERSION "1.43"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 7bed27601ce..006eb33bff5 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifsglob.h
*
- * Copyright (C) International Business Machines Corp., 2002,2005
+ * Copyright (C) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -430,6 +430,15 @@ struct dir_notify_req {
#define CIFS_LARGE_BUFFER 2
#define CIFS_IOVEC 4 /* array of response buffers */
+/* Type of session setup needed */
+#define CIFS_PLAINTEXT 0
+#define CIFS_LANMAN 1
+#define CIFS_NTLM 2
+#define CIFS_NTLMSSP_NEG 3
+#define CIFS_NTLMSSP_AUTH 4
+#define CIFS_SPNEGO_INIT 5
+#define CIFS_SPNEGO_TARG 6
+
/*
*****************************************************************
* All constants go here
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index cc2471094ca..b2233ac05bd 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -859,7 +859,10 @@ typedef struct smb_com_lock_req {
LOCKING_ANDX_RANGE Locks[1];
} __attribute__((packed)) LOCK_REQ;
-
+/* lock type */
+#define CIFS_RDLCK 0
+#define CIFS_WRLCK 1
+#define CIFS_UNLCK 2
typedef struct cifs_posix_lock {
__le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */
__le16 lock_flags; /* 1 = Wait (only valid for setlock) */
@@ -1786,7 +1789,13 @@ typedef struct {
#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
-#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */
+#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */
+#ifdef CONFIG_CIFS_POSIX
+#define CIFS_UNIX_CAP_MASK 0x0000001b
+#else
+#define CIFS_UNIX_CAP_MASK 0x00000013
+#endif /* CONFIG_CIFS_POSIX */
+
#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 7b25463d3c1..310ea2f0e0b 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifsproto.h
*
- * Copyright (c) International Business Machines Corp., 2002,2005
+ * Copyright (c) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -64,6 +64,14 @@ extern int map_smb_to_linux_error(struct smb_hdr *smb);
extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifsTconInfo *, int /* length of
fixed section (word count) in two byte units */);
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
+ struct cifsSesInfo *ses,
+ void ** request_buf);
+extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
+ const int stage, int * pNTLMv2_flg,
+ const struct nls_table *nls_cp);
+#endif
extern __u16 GetNextMid(struct TCP_Server_Info *server);
extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
struct cifsTconInfo *);
@@ -257,7 +265,10 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u64 offset, const __u32 numUnlock,
const __u32 numLock, const __u8 lockType,
const int waitFlag);
-
+extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
+ const __u16 smb_file_id, const int get_flag,
+ const __u64 len, struct file_lock *,
+ const __u16 lock_type, const int waitFlag);
extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index a243fe2792d..925881e00ff 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifssmb.c
*
- * Copyright (C) International Business Machines Corp., 2002,2005
+ * Copyright (C) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com)
*
* Contains the routines for constructing the SMB PDUs themselves
@@ -186,7 +186,35 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
cifs_stats_inc(&tcon->num_smbs_sent);
return rc;
-}
+}
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+int
+small_smb_init_no_tc(const int smb_command, const int wct,
+ struct cifsSesInfo *ses, void **request_buf)
+{
+ int rc;
+ struct smb_hdr * buffer;
+
+ rc = small_smb_init(smb_command, wct, NULL, request_buf);
+ if(rc)
+ return rc;
+
+ buffer = (struct smb_hdr *)*request_buf;
+ buffer->Mid = GetNextMid(ses->server);
+ if (ses->capabilities & CAP_UNICODE)
+ buffer->Flags2 |= SMBFLG2_UNICODE;
+ if (ses->capabilities & CAP_STATUS32)
+ buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+
+ /* uid, tid can stay at zero as set in header assemble */
+
+ /* BB add support for turning on the signing when
+ this function is used after 1st of session setup requests */
+
+ return rc;
+}
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
/* If the return code is zero, this function must fill in request_buf pointer */
static int
@@ -1042,7 +1070,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
}
}
- cifs_small_buf_release(pSMB);
+/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
if(*buf) {
if(resp_buf_type == CIFS_SMALL_BUFFER)
cifs_small_buf_release(iov[0].iov_base);
@@ -1246,7 +1274,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
*nbytes += le16_to_cpu(pSMBr->Count);
}
- cifs_small_buf_release(pSMB);
+/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
if(resp_buf_type == CIFS_SMALL_BUFFER)
cifs_small_buf_release(iov[0].iov_base);
else if(resp_buf_type == CIFS_LARGE_BUFFER)
@@ -1325,6 +1353,115 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
}
int
+CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
+ const __u16 smb_file_id, const int get_flag, const __u64 len,
+ struct file_lock *pLockData, const __u16 lock_type,
+ const int waitFlag)
+{
+ struct smb_com_transaction2_sfi_req *pSMB = NULL;
+ struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
+ char *data_offset;
+ struct cifs_posix_lock *parm_data;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, param_offset, offset, byte_count, count;
+
+ cFYI(1, ("Posix Lock"));
+
+ if(pLockData == NULL)
+ return EINVAL;
+
+ rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
+ if (rc)
+ return rc;
+
+ pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
+
+ params = 6;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+ offset = param_offset + params;
+
+ data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+
+ count = sizeof(struct cifs_posix_lock);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ if(get_flag)
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
+ else
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+ byte_count = 3 /* pad */ + params + count;
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ parm_data = (struct cifs_posix_lock *)
+ (((char *) &pSMB->hdr.Protocol) + offset);
+
+ parm_data->lock_type = cpu_to_le16(lock_type);
+ if(waitFlag)
+ parm_data->lock_flags = cpu_to_le16(1);
+ parm_data->pid = cpu_to_le32(current->tgid);
+ parm_data->start = cpu_to_le64(pLockData->fl_start);
+ parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
+
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->Fid = smb_file_id;
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += byte_count;
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in Posix Lock = %d", rc));
+ } else if (get_flag) {
+ /* lock structure can be returned on get */
+ __u16 data_offset;
+ __u16 data_count;
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
+ rc = -EIO; /* bad smb */
+ goto plk_err_exit;
+ }
+ if(pLockData == NULL) {
+ rc = -EINVAL;
+ goto plk_err_exit;
+ }
+ data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ data_count = le16_to_cpu(pSMBr->t2.DataCount);
+ if(data_count < sizeof(struct cifs_posix_lock)) {
+ rc = -EIO;
+ goto plk_err_exit;
+ }
+ parm_data = (struct cifs_posix_lock *)
+ ((char *)&pSMBr->hdr.Protocol + data_offset);
+ if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
+ pLockData->fl_type = F_UNLCK;
+ }
+
+plk_err_exit:
+ if (pSMB)
+ cifs_small_buf_release(pSMB);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+
+int
CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
{
int rc = 0;
@@ -2578,7 +2715,7 @@ qsec_out:
cifs_small_buf_release(iov[0].iov_base);
else if(buf_type == CIFS_LARGE_BUFFER)
cifs_buf_release(iov[0].iov_base);
- cifs_small_buf_release(pSMB);
+/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
return rc;
}
@@ -2954,7 +3091,8 @@ findFirstRetry:
pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->ParameterOffset = cpu_to_le16(
- offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
+ offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
+ - 4);
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
@@ -2977,12 +3115,12 @@ findFirstRetry:
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
cifs_stats_inc(&tcon->num_ffirst);
- if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
+ if (rc) {/* BB add logic to retry regular search if Unix search
+ rejected unexpectedly by server */
/* BB Add code to handle unsupported level rc */
cFYI(1, ("Error in FindFirst = %d", rc));
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
/* BB eventually could optimize out free and realloc of buf */
/* for this case */
@@ -2998,6 +3136,7 @@ findFirstRetry:
psrch_inf->unicode = FALSE;
psrch_inf->ntwrk_buf_start = (char *)pSMBr;
+ psrch_inf->smallBuf = 0;
psrch_inf->srch_entries_start =
(char *) &pSMBr->hdr.Protocol +
le16_to_cpu(pSMBr->t2.DataOffset);
@@ -3010,7 +3149,7 @@ findFirstRetry:
psrch_inf->endOfSearch = FALSE;
psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
- psrch_inf->index_of_last_entry =
+ psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
psrch_inf->entries_in_buffer;
*pnetfid = parms->SearchHandle;
} else {
@@ -3118,9 +3257,14 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
parms = (T2_FNEXT_RSP_PARMS *)response_data;
response_data = (char *)&pSMBr->hdr.Protocol +
le16_to_cpu(pSMBr->t2.DataOffset);
- cifs_buf_release(psrch_inf->ntwrk_buf_start);
+ if(psrch_inf->smallBuf)
+ cifs_small_buf_release(
+ psrch_inf->ntwrk_buf_start);
+ else
+ cifs_buf_release(psrch_inf->ntwrk_buf_start);
psrch_inf->srch_entries_start = response_data;
psrch_inf->ntwrk_buf_start = (char *)pSMB;
+ psrch_inf->smallBuf = 0;
if(parms->EndofSearch)
psrch_inf->endOfSearch = TRUE;
else
@@ -3834,6 +3978,7 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
cFYI(1, ("In SETFSUnixInfo"));
SETFSUnixRetry:
+ /* BB switch to small buf init to save memory */
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2a0c1f4ca0a..bae1479318d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1,7 +1,7 @@
/*
* fs/cifs/connect.c
*
- * Copyright (C) International Business Machines Corp., 2002,2005
+ * Copyright (C) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -564,7 +564,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
dump_smb(smb_buffer, length);
- if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
+ if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
continue;
}
@@ -1476,6 +1476,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
rc = smb_send(*csocket, smb_buf, 0x44,
(struct sockaddr *)psin_server);
kfree(ses_init_buf);
+ msleep(1); /* RFC1001 layer in at least one server
+ requires very short break before negprot
+ presumably because not expecting negprot
+ to follow so fast. This is a simple
+ solution that works without
+ complicating the code and causes no
+ significant slowing down on mount
+ for everyone else */
}
/* else the negprot may still work without this
even though malloc failed */
@@ -1920,27 +1928,34 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cifs_sb->tcon = tcon;
tcon->ses = pSesInfo;
- /* do not care if following two calls succeed - informational only */
+ /* do not care if following two calls succeed - informational */
CIFSSMBQFSDeviceInfo(xid, tcon);
CIFSSMBQFSAttributeInfo(xid, tcon);
+
if (tcon->ses->capabilities & CAP_UNIX) {
if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
- if(!volume_info.no_psx_acl) {
- if(CIFS_UNIX_POSIX_ACL_CAP &
- le64_to_cpu(tcon->fsUnixInfo.Capability))
- cFYI(1,("server negotiated posix acl support"));
- sb->s_flags |= MS_POSIXACL;
+ __u64 cap =
+ le64_to_cpu(tcon->fsUnixInfo.Capability);
+ cap &= CIFS_UNIX_CAP_MASK;
+ if(volume_info.no_psx_acl)
+ cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
+ else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
+ cFYI(1,("negotiated posix acl support"));
+ sb->s_flags |= MS_POSIXACL;
}
- /* Try and negotiate POSIX pathnames if we can. */
- if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
- le64_to_cpu(tcon->fsUnixInfo.Capability))) {
- if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
- cFYI(1,("negotiated posix pathnames support"));
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
- } else {
- cFYI(1,("posix pathnames support requested but not supported"));
- }
+ if(volume_info.posix_paths == 0)
+ cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
+ else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+ cFYI(1,("negotiate posix pathnames"));
+ cifs_sb->mnt_cifs_flags |=
+ CIFS_MOUNT_POSIX_PATHS;
+ }
+
+ cFYI(1,("Negotiate caps 0x%x",(int)cap));
+
+ if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
+ cFYI(1,("setting capabilities failed"));
}
}
}
@@ -2133,6 +2148,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
/* We look for obvious messed up bcc or strings in response so we do not go off
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
+ if(ses->serverOS)
+ kfree(ses->serverOS);
ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
if(ses->serverOS == NULL)
goto sesssetup_nomem;
@@ -2145,6 +2162,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *)bcc_ptr,
remaining_words-1);
+ if(ses->serverNOS)
+ kfree(ses->serverNOS);
ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
if(ses->serverNOS == NULL)
goto sesssetup_nomem;
@@ -2162,6 +2181,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2*(len+1),GFP_KERNEL);
if(ses->serverDomain == NULL)
@@ -2172,15 +2193,22 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
ses->serverDomain[2*len] = 0;
ses->serverDomain[1+(2*len)] = 0;
} /* else no more room so create dummy domain string */
- else
+ else {
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2, GFP_KERNEL);
+ }
} else { /* no room so create dummy domain and NOS string */
/* if these kcallocs fail not much we
can do, but better to not fail the
sesssetup itself */
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2, GFP_KERNEL);
+ if(ses->serverNOS)
+ kfree(ses->serverNOS);
ses->serverNOS =
kzalloc(2, GFP_KERNEL);
}
@@ -2189,6 +2217,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
if (((long) bcc_ptr + len) - (long)
pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
+ if(ses->serverOS)
+ kfree(ses->serverOS);
ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
if(ses->serverOS == NULL)
goto sesssetup_nomem;
@@ -2199,6 +2229,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
+ if(ses->serverNOS)
+ kfree(ses->serverNOS);
ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
if(ses->serverNOS == NULL)
goto sesssetup_nomem;
@@ -2208,6 +2240,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
if(ses->serverDomain == NULL)
goto sesssetup_nomem;
@@ -2278,6 +2312,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
smb_buffer->Mid = GetNextMid(ses->server);
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
pSMB->req.AndXCommand = 0xFF;
+ if(ses->server->maxBuf > 64*1024)
+ ses->server->maxBuf = (64*1023);
pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
@@ -2410,6 +2446,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
/* We look for obvious messed up bcc or strings in response so we do not go off
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
+ if(ses->serverOS)
+ kfree(ses->serverOS);
ses->serverOS =
kzalloc(2 * (len + 1), GFP_KERNEL);
cifs_strfromUCS_le(ses->serverOS,
@@ -2424,6 +2462,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
len = UniStrnlen((wchar_t *)bcc_ptr,
remaining_words
- 1);
+ if(ses->serverNOS)
+ kfree(ses->serverNOS);
ses->serverNOS =
kzalloc(2 * (len + 1),
GFP_KERNEL);
@@ -2437,7 +2477,9 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
remaining_words -= len + 1;
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
- /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+ /* last string not null terminated (e.g.Windows XP/2000) */
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
cifs_strfromUCS_le(ses->serverDomain,
(__le16 *)bcc_ptr,
@@ -2446,11 +2488,18 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
ses->serverDomain[2*len] = 0;
ses->serverDomain[1+(2*len)] = 0;
} /* else no more room so create dummy domain string */
- else
+ else {
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2,GFP_KERNEL);
- } else { /* no room so create dummy domain and NOS string */
+ }
+ } else {/* no room use dummy domain&NOS */
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain = kzalloc(2, GFP_KERNEL);
+ if(ses->serverNOS)
+ kfree(ses->serverNOS);
ses->serverNOS = kzalloc(2, GFP_KERNEL);
}
} else { /* ASCII */
@@ -2459,6 +2508,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
if (((long) bcc_ptr + len) - (long)
pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
+ if(ses->serverOS)
+ kfree(ses->serverOS);
ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
strncpy(ses->serverOS, bcc_ptr, len);
@@ -2467,6 +2518,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
+ if(ses->serverNOS)
+ kfree(ses->serverNOS);
ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
strncpy(ses->serverNOS, bcc_ptr, len);
bcc_ptr += len;
@@ -2474,6 +2527,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
strncpy(ses->serverDomain, bcc_ptr, len);
bcc_ptr += len;
@@ -2525,7 +2580,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
__u32 negotiate_flags, capabilities;
__u16 count;
- cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
+ cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
if(ses == NULL)
return -EINVAL;
domain = ses->domainName;
@@ -2575,7 +2630,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
SecurityBlob->MessageType = NtLmNegotiate;
negotiate_flags =
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
- NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
+ NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
+ NTLMSSP_NEGOTIATE_56 |
/* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
if(sign_CIFS_PDUs)
negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
@@ -2588,26 +2644,11 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
SecurityBlob->WorkstationName.Length = 0;
SecurityBlob->WorkstationName.MaximumLength = 0;
- if (domain == NULL) {
- SecurityBlob->DomainName.Buffer = 0;
- SecurityBlob->DomainName.Length = 0;
- SecurityBlob->DomainName.MaximumLength = 0;
- } else {
- __u16 len;
- negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
- strncpy(bcc_ptr, domain, 63);
- len = strnlen(domain, 64);
- SecurityBlob->DomainName.MaximumLength =
- cpu_to_le16(len);
- SecurityBlob->DomainName.Buffer =
- cpu_to_le32((long) &SecurityBlob->
- DomainString -
- (long) &SecurityBlob->Signature);
- bcc_ptr += len;
- SecurityBlobLength += len;
- SecurityBlob->DomainName.Length =
- cpu_to_le16(len);
- }
+ /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
+ along with username on auth request (ie the response to challenge) */
+ SecurityBlob->DomainName.Buffer = 0;
+ SecurityBlob->DomainName.Length = 0;
+ SecurityBlob->DomainName.MaximumLength = 0;
if (ses->capabilities & CAP_UNICODE) {
if ((long) bcc_ptr % 2) {
*bcc_ptr = 0;
@@ -2677,7 +2718,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
SecurityBlob2->MessageType));
} else if (ses) {
ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
- cFYI(1, ("UID = %d ", ses->Suid));
+ cFYI(1, ("UID = %d", ses->Suid));
if ((pSMBr->resp.hdr.WordCount == 3)
|| ((pSMBr->resp.hdr.WordCount == 4)
&& (blob_len <
@@ -2685,17 +2726,17 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
if (pSMBr->resp.hdr.WordCount == 4) {
bcc_ptr += blob_len;
- cFYI(1,
- ("Security Blob Length %d ",
+ cFYI(1, ("Security Blob Length %d",
blob_len));
}
- cFYI(1, ("NTLMSSP Challenge rcvd "));
+ cFYI(1, ("NTLMSSP Challenge rcvd"));
memcpy(ses->server->cryptKey,
SecurityBlob2->Challenge,
CIFS_CRYPTO_KEY_SIZE);
- if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
+ if(SecurityBlob2->NegotiateFlags &
+ cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
*pNTLMv2_flag = TRUE;
if((SecurityBlob2->NegotiateFlags &
@@ -2725,6 +2766,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
/* We look for obvious messed up bcc or strings in response so we do not go off
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
+ if(ses->serverOS)
+ kfree(ses->serverOS);
ses->serverOS =
kzalloc(2 * (len + 1), GFP_KERNEL);
cifs_strfromUCS_le(ses->serverOS,
@@ -2740,6 +2783,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
bcc_ptr,
remaining_words
- 1);
+ if(ses->serverNOS)
+ kfree(ses->serverNOS);
ses->serverNOS =
kzalloc(2 * (len + 1),
GFP_KERNEL);
@@ -2757,6 +2802,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2 *
(len +
@@ -2774,13 +2821,20 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
[1 + (2 * len)]
= 0;
} /* else no more room so create dummy domain string */
- else
+ else {
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2,
GFP_KERNEL);
+ }
} else { /* no room so create dummy domain and NOS string */
+ if(ses->serverDomain);
+ kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2, GFP_KERNEL);
+ if(ses->serverNOS)
+ kfree(ses->serverNOS);
ses->serverNOS =
kzalloc(2, GFP_KERNEL);
}
@@ -2789,6 +2843,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
if (((long) bcc_ptr + len) - (long)
pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
+ if(ses->serverOS)
+ kfree(ses->serverOS);
ses->serverOS =
kzalloc(len + 1,
GFP_KERNEL);
@@ -2800,6 +2856,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
+ if(ses->serverNOS)
+ kfree(ses->serverNOS);
ses->serverNOS =
kzalloc(len + 1,
GFP_KERNEL);
@@ -2809,6 +2867,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(len + 1,
GFP_KERNEL);
@@ -2818,7 +2878,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
bcc_ptr++;
} else
cFYI(1,
- ("Variable field of length %d extends beyond end of smb ",
+ ("Variable field of length %d extends beyond end of smb",
len));
}
} else {
@@ -2830,7 +2890,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
}
} else {
cERROR(1,
- (" Invalid Word count %d: ",
+ (" Invalid Word count %d:",
smb_buffer_response->WordCount));
rc = -EIO;
}
@@ -3113,6 +3173,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
/* We look for obvious messed up bcc or strings in response so we do not go off
the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */
+ if(ses->serverOS)
+ kfree(ses->serverOS);
ses->serverOS =
kzalloc(2 * (len + 1), GFP_KERNEL);
cifs_strfromUCS_le(ses->serverOS,
@@ -3128,6 +3190,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr,
remaining_words
- 1);
+ if(ses->serverNOS)
+ kfree(ses->serverNOS);
ses->serverNOS =
kzalloc(2 * (len + 1),
GFP_KERNEL);
@@ -3144,6 +3208,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
/* last string not always null terminated (e.g. for Windows XP & 2000) */
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain =
kzalloc(2 *
(len +
@@ -3169,10 +3235,17 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
len)]
= 0;
} /* else no more room so create dummy domain string */
- else
+ else {
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain = kzalloc(2,GFP_KERNEL);
+ }
} else { /* no room so create dummy domain and NOS string */
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain = kzalloc(2, GFP_KERNEL);
+ if(ses->serverNOS)
+ kfree(ses->serverNOS);
ses->serverNOS = kzalloc(2, GFP_KERNEL);
}
} else { /* ASCII */
@@ -3180,6 +3253,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
if (((long) bcc_ptr + len) -
(long) pByteArea(smb_buffer_response)
<= BCC(smb_buffer_response)) {
+ if(ses->serverOS)
+ kfree(ses->serverOS);
ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
strncpy(ses->serverOS,bcc_ptr, len);
@@ -3188,6 +3263,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
+ if(ses->serverNOS)
+ kfree(ses->serverNOS);
ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
strncpy(ses->serverNOS, bcc_ptr, len);
bcc_ptr += len;
@@ -3195,6 +3272,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr++;
len = strnlen(bcc_ptr, 1024);
+ if(ses->serverDomain)
+ kfree(ses->serverDomain);
ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
strncpy(ses->serverDomain, bcc_ptr, len);
bcc_ptr += len;
@@ -3279,7 +3358,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr++; /* align */
}
- if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ if(ses->server->secMode &
+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
if (ses->capabilities & CAP_STATUS32) {
@@ -3291,8 +3371,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
if (ses->capabilities & CAP_UNICODE) {
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
length =
- cifs_strtoUCS((__le16 *) bcc_ptr, tree, 100, nls_codepage);
- bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
+ cifs_strtoUCS((__le16 *) bcc_ptr, tree,
+ 6 /* max utf8 char length in bytes */ *
+ (/* server len*/ + 256 /* share len */), nls_codepage);
+ bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
bcc_ptr += 2; /* skip trailing null */
} else { /* ASCII */
strcpy(bcc_ptr, tree);
@@ -3444,10 +3526,16 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
pSesInfo->server->secMode,
pSesInfo->server->capabilities,
pSesInfo->server->timeZone));
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ if(experimEnabled > 1)
+ rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */,
+ &ntlmv2_flag, nls_info);
+ else
+#endif
if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == NTLMSSP)) {
- cFYI(1, ("New style sesssetup "));
+ cFYI(1, ("New style sesssetup"));
rc = CIFSSpnegoSessSetup(xid, pSesInfo,
NULL /* security blob */,
0 /* blob length */,
@@ -3455,7 +3543,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
} else if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == RawNTLMSSP)) {
- cFYI(1, ("NTLMSSP sesssetup "));
+ cFYI(1, ("NTLMSSP sesssetup"));
rc = CIFSNTLMSSPNegotiateSessSetup(xid,
pSesInfo,
&ntlmv2_flag,
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 632561dd9c5..82315edc77d 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -48,13 +48,14 @@ build_path_from_dentry(struct dentry *direntry)
struct dentry *temp;
int namelen = 0;
char *full_path;
- char dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
+ char dirsep;
if(direntry == NULL)
return NULL; /* not much we can do if dentry is freed and
we need to reopen the file after it was closed implicitly
when the server crashed */
+ dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
cifs_bp_rename_retry:
for (temp = direntry; !IS_ROOT(temp);) {
namelen += (1 + temp->d_name.len);
@@ -138,9 +139,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -255,12 +254,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
CIFSSMBClose(xid, pTcon, fileHandle);
} else if(newinode) {
pCifsFile =
- kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
+ kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
if(pCifsFile == NULL)
goto cifs_create_out;
- memset((char *)pCifsFile, 0,
- sizeof (struct cifsFileInfo));
pCifsFile->netfid = fileHandle;
pCifsFile->pid = current->tgid;
pCifsFile->pInode = newinode;
@@ -317,9 +314,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
if(full_path == NULL)
rc = -ENOMEM;
else if (pTcon->ses->capabilities & CAP_UNIX) {
@@ -441,6 +436,20 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
pTcon = cifs_sb->tcon;
+ /*
+ * Don't allow the separator character in a path component.
+ * The VFS will not allow "/", but "\" is allowed by posix.
+ */
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
+ int i;
+ for (i = 0; i < direntry->d_name.len; i++)
+ if (direntry->d_name.name[i] == '\\') {
+ cFYI(1, ("Invalid file name"));
+ FreeXid(xid);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
/* can not grab the rename sem here since it would
deadlock in the cases (beginning of sys_rename itself)
in which we already have the sb rename sem */
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index ec4dfe9bf5e..633a9381132 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -86,9 +86,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(file->f_dentry);
- mutex_unlock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
if(full_path == NULL) {
rc = -ENOMEM;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index fb49aef1f2e..e2b4ce1dad6 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -84,6 +84,8 @@ static inline int cifs_get_disposition(unsigned int flags)
return FILE_OVERWRITE_IF;
else if ((flags & O_CREAT) == O_CREAT)
return FILE_OPEN_IF;
+ else if ((flags & O_TRUNC) == O_TRUNC)
+ return FILE_OVERWRITE;
else
return FILE_OPEN;
}
@@ -203,9 +205,7 @@ int cifs_open(struct inode *inode, struct file *file)
}
}
- mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(file->f_dentry);
- mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -555,7 +555,10 @@ int cifs_closedir(struct inode *inode, struct file *file)
if (ptmp) {
cFYI(1, ("closedir free smb buf in srch struct"));
pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
- cifs_buf_release(ptmp);
+ if(pCFileStruct->srch_inf.smallBuf)
+ cifs_small_buf_release(ptmp);
+ else
+ cifs_buf_release(ptmp);
}
ptmp = pCFileStruct->search_resume_name;
if (ptmp) {
@@ -574,13 +577,14 @@ int cifs_closedir(struct inode *inode, struct file *file)
int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
{
int rc, xid;
- __u32 lockType = LOCKING_ANDX_LARGE_FILES;
__u32 numLock = 0;
__u32 numUnlock = 0;
__u64 length;
int wait_flag = FALSE;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
+ __u16 netfid;
+ __u8 lockType = LOCKING_ANDX_LARGE_FILES;
length = 1 + pfLock->fl_end - pfLock->fl_start;
rc = -EACCES;
@@ -592,11 +596,11 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
pfLock->fl_end));
if (pfLock->fl_flags & FL_POSIX)
- cFYI(1, ("Posix "));
+ cFYI(1, ("Posix"));
if (pfLock->fl_flags & FL_FLOCK)
- cFYI(1, ("Flock "));
+ cFYI(1, ("Flock"));
if (pfLock->fl_flags & FL_SLEEP) {
- cFYI(1, ("Blocking lock "));
+ cFYI(1, ("Blocking lock"));
wait_flag = TRUE;
}
if (pfLock->fl_flags & FL_ACCESS)
@@ -612,21 +616,23 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
cFYI(1, ("F_WRLCK "));
numLock = 1;
} else if (pfLock->fl_type == F_UNLCK) {
- cFYI(1, ("F_UNLCK "));
+ cFYI(1, ("F_UNLCK"));
numUnlock = 1;
+ /* Check if unlock includes more than
+ one lock range */
} else if (pfLock->fl_type == F_RDLCK) {
- cFYI(1, ("F_RDLCK "));
+ cFYI(1, ("F_RDLCK"));
lockType |= LOCKING_ANDX_SHARED_LOCK;
numLock = 1;
} else if (pfLock->fl_type == F_EXLCK) {
- cFYI(1, ("F_EXLCK "));
+ cFYI(1, ("F_EXLCK"));
numLock = 1;
} else if (pfLock->fl_type == F_SHLCK) {
- cFYI(1, ("F_SHLCK "));
+ cFYI(1, ("F_SHLCK"));
lockType |= LOCKING_ANDX_SHARED_LOCK;
numLock = 1;
} else
- cFYI(1, ("Unknown type of lock "));
+ cFYI(1, ("Unknown type of lock"));
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
@@ -635,27 +641,41 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
FreeXid(xid);
return -EBADF;
}
+ netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
+
+ /* BB add code here to normalize offset and length to
+ account for negative length which we can not accept over the
+ wire */
if (IS_GETLK(cmd)) {
- rc = CIFSSMBLock(xid, pTcon,
- ((struct cifsFileInfo *)file->
- private_data)->netfid,
- length,
- pfLock->fl_start, 0, 1, lockType,
- 0 /* wait flag */ );
+ if(experimEnabled &&
+ (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
+ (CIFS_UNIX_FCNTL_CAP &
+ le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
+ int posix_lock_type;
+ if(lockType & LOCKING_ANDX_SHARED_LOCK)
+ posix_lock_type = CIFS_RDLCK;
+ else
+ posix_lock_type = CIFS_WRLCK;
+ rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */,
+ length, pfLock,
+ posix_lock_type, wait_flag);
+ FreeXid(xid);
+ return rc;
+ }
+
+ /* BB we could chain these into one lock request BB */
+ rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
+ 0, 1, lockType, 0 /* wait flag */ );
if (rc == 0) {
- rc = CIFSSMBLock(xid, pTcon,
- ((struct cifsFileInfo *) file->
- private_data)->netfid,
- length,
+ rc = CIFSSMBLock(xid, pTcon, netfid, length,
pfLock->fl_start, 1 /* numUnlock */ ,
0 /* numLock */ , lockType,
0 /* wait flag */ );
pfLock->fl_type = F_UNLCK;
if (rc != 0)
cERROR(1, ("Error unlocking previously locked "
- "range %d during test of lock ",
- rc));
+ "range %d during test of lock", rc));
rc = 0;
} else {
@@ -667,12 +687,30 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
FreeXid(xid);
return rc;
}
-
- rc = CIFSSMBLock(xid, pTcon,
- ((struct cifsFileInfo *) file->private_data)->
- netfid, length,
- pfLock->fl_start, numUnlock, numLock, lockType,
- wait_flag);
+ if (experimEnabled &&
+ (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
+ (CIFS_UNIX_FCNTL_CAP &
+ le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
+ int posix_lock_type;
+ if(lockType & LOCKING_ANDX_SHARED_LOCK)
+ posix_lock_type = CIFS_RDLCK;
+ else
+ posix_lock_type = CIFS_WRLCK;
+
+ if(numUnlock == 1)
+ posix_lock_type = CIFS_UNLCK;
+ else if(numLock == 0) {
+ /* if no lock or unlock then nothing
+ to do since we do not know what it is */
+ FreeXid(xid);
+ return -EOPNOTSUPP;
+ }
+ rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
+ length, pfLock,
+ posix_lock_type, wait_flag);
+ } else
+ rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
+ numUnlock, numLock, lockType, wait_flag);
if (pfLock->fl_flags & FL_POSIX)
posix_lock_file_wait(file, pfLock);
FreeXid(xid);
@@ -868,9 +906,10 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
if (rc != 0)
break;
}
- /* BB FIXME We can not sign across two buffers yet */
- if((pTcon->ses->server->secMode &
- (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
+ if(experimEnabled || (pTcon->ses->server &&
+ ((pTcon->ses->server->secMode &
+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ == 0))) {
struct kvec iov[2];
unsigned int len;
@@ -885,13 +924,13 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
*poffset, &bytes_written,
iov, 1, long_op);
} else
- /* BB FIXME fixup indentation of line below */
- rc = CIFSSMBWrite(xid, pTcon,
- open_file->netfid,
- min_t(const int, cifs_sb->wsize,
- write_size - total_written),
- *poffset, &bytes_written,
- write_data + total_written, NULL, long_op);
+ rc = CIFSSMBWrite(xid, pTcon,
+ open_file->netfid,
+ min_t(const int, cifs_sb->wsize,
+ write_size - total_written),
+ *poffset, &bytes_written,
+ write_data + total_written,
+ NULL, long_op);
}
if (rc || (bytes_written == 0)) {
if (total_written)
@@ -930,6 +969,16 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
struct cifsFileInfo *open_file;
int rc;
+ /* Having a null inode here (because mapping->host was set to zero by
+ the VFS or MM) should not happen but we had reports of on oops (due to
+ it being zero) during stress testcases so we need to check for it */
+
+ if(cifs_inode == NULL) {
+ cERROR(1,("Null inode passed to cifs_writeable_file"));
+ dump_stack();
+ return NULL;
+ }
+
read_lock(&GlobalSMBSeslock);
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (open_file->closePend)
@@ -1055,12 +1104,11 @@ static int cifs_writepages(struct address_space *mapping,
if (cifs_sb->wsize < PAGE_CACHE_SIZE)
return generic_writepages(mapping, wbc);
- /* BB FIXME we do not have code to sign across multiple buffers yet,
- so go to older writepage style write which we can sign if needed */
if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
if(cifs_sb->tcon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- return generic_writepages(mapping, wbc);
+ if(!experimEnabled)
+ return generic_writepages(mapping, wbc);
/*
* BB: Is this meaningful for a non-block-device file system?
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 598eec9778f..4093764ef46 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -565,11 +565,14 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
struct cifsInodeInfo *cifsInode;
FILE_BASIC_INFO *pinfo_buf;
- cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode));
+ cFYI(1, ("cifs_unlink, inode = 0x%p", inode));
xid = GetXid();
- cifs_sb = CIFS_SB(inode->i_sb);
+ if(inode)
+ cifs_sb = CIFS_SB(inode->i_sb);
+ else
+ cifs_sb = CIFS_SB(direntry->d_sb);
pTcon = cifs_sb->tcon;
/* Unlink can be called from rename so we can not grab the sem here
@@ -609,9 +612,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
}
} else if (rc == -EACCES) {
/* try only if r/o attribute set in local lookup data? */
- pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
+ pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
if (pinfo_buf) {
- memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO));
/* ATTRS set to normal clears r/o bit */
pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
if (!(pTcon->ses->flags & CIFS_SES_NT4))
@@ -693,9 +695,11 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
when needed */
direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
}
- inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
- cifsInode = CIFS_I(inode);
- cifsInode->time = 0; /* force revalidate of dir as well */
+ if(inode) {
+ inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
+ cifsInode = CIFS_I(inode);
+ cifsInode->time = 0; /* force revalidate of dir as well */
+ }
kfree(full_path);
FreeXid(xid);
@@ -718,9 +722,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -803,9 +805,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -1137,9 +1137,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
rc = 0;
}
- mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -1167,7 +1165,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
nfid, npid, FALSE);
atomic_dec(&open_file->wrtPending);
cFYI(1,("SetFSize for attrs rc = %d", rc));
- if(rc == -EINVAL) {
+ if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
int bytes_written;
rc = CIFSSMBWrite(xid, pTcon,
nfid, 0, attrs->ia_size,
@@ -1189,7 +1187,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
- if(rc == -EINVAL) {
+ if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
__u16 netfid;
int oplock = FALSE;
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 8d0da7c87c7..2ec99f83314 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -48,10 +48,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
/* No need to check for cross device links since server will do that
BB note DFS case in future though (when we may have to check) */
- mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
fromName = build_path_from_dentry(old_file);
toName = build_path_from_dentry(direntry);
- mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if((fromName == NULL) || (toName == NULL)) {
rc = -ENOMEM;
goto cifs_hl_exit;
@@ -67,7 +65,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
cifs_sb_target->local_nls,
cifs_sb_target->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if(rc == -EIO)
+ if((rc == -EIO) || (rc == -EINVAL))
rc = -EOPNOTSUPP;
}
@@ -103,9 +101,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
xid = GetXid();
- mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
if (!full_path)
goto out_no_free;
@@ -164,9 +160,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 432ba15e2c2..fafd056426e 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -72,10 +72,9 @@ sesInfoAlloc(void)
struct cifsSesInfo *ret_buf;
ret_buf =
- (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
+ (struct cifsSesInfo *) kzalloc(sizeof (struct cifsSesInfo),
GFP_KERNEL);
if (ret_buf) {
- memset(ret_buf, 0, sizeof (struct cifsSesInfo));
write_lock(&GlobalSMBSeslock);
atomic_inc(&sesInfoAllocCount);
ret_buf->status = CifsNew;
@@ -110,10 +109,9 @@ tconInfoAlloc(void)
{
struct cifsTconInfo *ret_buf;
ret_buf =
- (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
+ (struct cifsTconInfo *) kzalloc(sizeof (struct cifsTconInfo),
GFP_KERNEL);
if (ret_buf) {
- memset(ret_buf, 0, sizeof (struct cifsTconInfo));
write_lock(&GlobalSMBSeslock);
atomic_inc(&tconInfoAllocCount);
list_add(&ret_buf->cifsConnectionList,
@@ -423,9 +421,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
{
__u32 len = smb->smb_buf_length;
__u32 clc_len; /* calculated length */
- cFYI(0,
- ("Entering checkSMB with Length: %x, smb_buf_length: %x",
- length, len));
+ cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
(len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
@@ -433,29 +429,36 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
sizeof (struct smb_hdr) - 1)
&& (smb->Status.CifsError != 0)) {
smb->WordCount = 0;
- return 0; /* some error cases do not return wct and bcc */
+ /* some error cases do not return wct and bcc */
+ return 0;
} else {
cERROR(1, ("Length less than smb header size"));
}
-
}
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
- cERROR(1,
- ("smb_buf_length greater than MaxBufSize"));
- cERROR(1,
- ("bad smb detected. Illegal length. mid=%d",
- smb->Mid));
+ cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
+ smb->Mid));
return 1;
}
if (checkSMBhdr(smb, mid))
return 1;
clc_len = smbCalcSize_LE(smb);
- if ((4 + len != clc_len)
- || (4 + len != (unsigned int)length)) {
- cERROR(1, ("Calculated size 0x%x vs actual length 0x%x",
- clc_len, 4 + len));
- cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid));
+
+ if(4 + len != (unsigned int)length) {
+ cERROR(1, ("Length read does not match RFC1001 length %d",len));
+ return 1;
+ }
+
+ if (4 + len != clc_len) {
+ /* check if bcc wrapped around for large read responses */
+ if((len > 64 * 1024) && (len > clc_len)) {
+ /* check if lengths match mod 64K */
+ if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
+ return 0; /* bcc wrapped */
+ }
+ cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d",
+ clc_len, 4 + len, smb->Mid));
/* Windows XP can return a few bytes too much, presumably
an illegal pad, at the end of byte range lock responses
so we allow for that three byte pad, as long as actual
@@ -469,8 +472,11 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
wct and bcc to minimum size and drop the t2 parms and data */
if((4+len > clc_len) && (len <= clc_len + 512))
return 0;
- else
+ else {
+ cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d",
+ len, smb->Mid));
return 1;
+ }
}
return 0;
}
diff --git a/fs/cifs/ntlmssp.c b/fs/cifs/ntlmssp.c
new file mode 100644
index 00000000000..115359cc7a3
--- /dev/null
+++ b/fs/cifs/ntlmssp.c
@@ -0,0 +1,143 @@
+/*
+ * fs/cifs/ntlmssp.h
+ *
+ * Copyright (c) International Business Machines Corp., 2006
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "ntlmssp.h"
+#include "nterr.h"
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
+{
+ __u32 capabilities = 0;
+
+ /* init fields common to all four types of SessSetup */
+ /* note that header is initialized to zero in header_assemble */
+ pSMB->req.AndXCommand = 0xFF;
+ pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+ pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+
+ /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
+
+ /* BB verify whether signing required on neg or just on auth frame
+ (and NTLM case) */
+
+ capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+ CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
+
+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+ if (ses->capabilities & CAP_UNICODE) {
+ pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
+ capabilities |= CAP_UNICODE;
+ }
+ if (ses->capabilities & CAP_STATUS32) {
+ pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
+ capabilities |= CAP_STATUS32;
+ }
+ if (ses->capabilities & CAP_DFS) {
+ pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
+ capabilities |= CAP_DFS;
+ }
+
+ /* BB check whether to init vcnum BB */
+ return capabilities;
+}
+int
+CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int type,
+ int * pNTLMv2_flg, const struct nls_table *nls_cp)
+{
+ int rc = 0;
+ int wct;
+ struct smb_hdr *smb_buffer;
+ char *bcc_ptr;
+ SESSION_SETUP_ANDX *pSMB;
+ __u32 capabilities;
+
+ if(ses == NULL)
+ return -EINVAL;
+
+ cFYI(1,("SStp type: %d",type));
+ if(type < CIFS_NTLM) {
+#ifndef CONFIG_CIFS_WEAK_PW_HASH
+ /* LANMAN and plaintext are less secure and off by default.
+ So we make this explicitly be turned on in kconfig (in the
+ build) and turned on at runtime (changed from the default)
+ in proc/fs/cifs or via mount parm. Unfortunately this is
+ needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
+ return -EOPNOTSUPP;
+#endif
+ wct = 10; /* lanman 2 style sessionsetup */
+ } else if(type < CIFS_NTLMSSP_NEG)
+ wct = 13; /* old style NTLM sessionsetup */
+ else /* same size for negotiate or auth, NTLMSSP or extended security */
+ wct = 12;
+
+ rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
+ (void **)&smb_buffer);
+ if(rc)
+ return rc;
+
+ pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
+
+ capabilities = cifs_ssetup_hdr(ses, pSMB);
+ bcc_ptr = pByteArea(smb_buffer);
+ if(type > CIFS_NTLM) {
+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ capabilities |= CAP_EXTENDED_SECURITY;
+ pSMB->req.Capabilities = cpu_to_le32(capabilities);
+ /* BB set password lengths */
+ } else if(type < CIFS_NTLM) /* lanman */ {
+ /* no capabilities flags in old lanman negotiation */
+ /* pSMB->old_req.PasswordLength = */ /* BB fixme BB */
+ } else /* type CIFS_NTLM */ {
+ pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
+ pSMB->req_no_secext.CaseInsensitivePasswordLength =
+ cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+ pSMB->req_no_secext.CaseSensitivePasswordLength =
+ cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+ }
+
+
+ /* copy session key */
+
+ /* if Unicode, align strings to two byte boundary */
+
+ /* copy user name */ /* BB Do we need to special case null user name? */
+
+ /* copy domain name */
+
+ /* copy Linux version */
+
+ /* copy network operating system name */
+
+ /* update bcc and smb buffer length */
+
+/* rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */
+ /* SMB request buf freed in SendReceive2 */
+
+ return rc;
+}
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index 803389b64a2..d39b712a11c 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -1,7 +1,7 @@
/*
* fs/cifs/ntlmssp.h
*
- * Copyright (c) International Business Machines Corp., 2002
+ * Copyright (c) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 488bd0d81dc..b689c503512 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -404,9 +404,7 @@ static int initiate_cifs_search(const int xid, struct file *file)
if(pTcon == NULL)
return -EINVAL;
- mutex_lock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(file->f_dentry);
- mutex_unlock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
if(full_path == NULL) {
return -ENOMEM;
@@ -592,6 +590,13 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
first_entry_in_buffer =
cifsFile->srch_inf.index_of_last_entry -
cifsFile->srch_inf.entries_in_buffer;
+
+ /* if first entry in buf is zero then is first buffer
+ in search response data which means it is likely . and ..
+ will be in this buffer, although some servers do not return
+ . and .. for the root of a drive and for those we need
+ to start two entries earlier */
+
/* dump_cifs_file_struct(file, "In fce ");*/
if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
is_dir_changed(file)) ||
@@ -604,7 +609,12 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
cifsFile->search_resume_name = NULL;
if(cifsFile->srch_inf.ntwrk_buf_start) {
cFYI(1,("freeing SMB ff cache buf on search rewind"));
- cifs_buf_release(cifsFile->srch_inf.ntwrk_buf_start);
+ if(cifsFile->srch_inf.smallBuf)
+ cifs_small_buf_release(cifsFile->srch_inf.
+ ntwrk_buf_start);
+ else
+ cifs_buf_release(cifsFile->srch_inf.
+ ntwrk_buf_start);
}
rc = initiate_cifs_search(xid,file);
if(rc) {
@@ -629,23 +639,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
smbCalcSize((struct smb_hdr *)
cifsFile->srch_inf.ntwrk_buf_start);
+
+ current_entry = cifsFile->srch_inf.srch_entries_start;
first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
- cifsFile->srch_inf.entries_in_buffer;
pos_in_buf = index_to_find - first_entry_in_buffer;
cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
- current_entry = cifsFile->srch_inf.srch_entries_start;
for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
/* go entry by entry figuring out which is first */
- /* if( . or ..)
- skip */
- rc = cifs_entry_is_dot(current_entry,cifsFile);
- if(rc == 1) /* is . or .. so skip */ {
- cFYI(1,("Entry is .")); /* BB removeme BB */
- /* continue; */
- } else if (rc == 2 ) {
- cFYI(1,("Entry is ..")); /* BB removeme BB */
- /* continue; */
- }
current_entry = nxt_dir_entry(current_entry,end_of_smb);
}
if((current_entry == NULL) && (i < pos_in_buf)) {
@@ -765,6 +766,11 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
if(file->f_dentry == NULL)
return -ENOENT;
+ rc = cifs_entry_is_dot(pfindEntry,pCifsF);
+ /* skip . and .. since we added them first */
+ if(rc != 0)
+ return 0;
+
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
qstring.name = scratch_buf;
@@ -893,22 +899,22 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
switch ((int) file->f_pos) {
case 0:
- /*if (filldir(direntry, ".", 1, file->f_pos,
+ if (filldir(direntry, ".", 1, file->f_pos,
file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
- cERROR(1, ("Filldir for current dir failed "));
+ cERROR(1, ("Filldir for current dir failed"));
rc = -ENOMEM;
break;
}
- file->f_pos++; */
+ file->f_pos++;
case 1:
- /* if (filldir(direntry, "..", 2, file->f_pos,
+ if (filldir(direntry, "..", 2, file->f_pos,
file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
cERROR(1, ("Filldir for parent dir failed "));
rc = -ENOMEM;
break;
}
- file->f_pos++; */
- case 2:
+ file->f_pos++;
+ default:
/* 1) If search is active,
is in current search buffer?
if it before then restart search
@@ -922,7 +928,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
return rc;
}
}
- default:
if(file->private_data == NULL) {
rc = -EINVAL;
FreeXid(xid);
@@ -942,8 +947,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
kfree(cifsFile->search_resume_name);
cifsFile->search_resume_name = NULL; */
- /* BB account for . and .. in f_pos as special case */
-
rc = find_cifs_entry(xid,pTcon, file,
&current_entry,&num_to_fill);
if(rc) {
@@ -972,7 +975,8 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
num_to_fill, i));
break;
}
-
+ /* if buggy server returns . and .. late do
+ we want to check for that here? */
rc = cifs_filldir(current_entry, file,
filldir, direntry,tmp_buf);
file->f_pos++;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index b12cb8a7da7..3da80409466 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -309,17 +309,16 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
*pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
- if (ses == NULL) {
- cERROR(1,("Null smb session"));
- return -EIO;
- }
- if(ses->server == NULL) {
- cERROR(1,("Null tcp session"));
+ if ((ses == NULL) || (ses->server == NULL)) {
+ cifs_small_buf_release(in_buf);
+ cERROR(1,("Null session"));
return -EIO;
}
- if(ses->server->tcpStatus == CifsExiting)
+ if(ses->server->tcpStatus == CifsExiting) {
+ cifs_small_buf_release(in_buf);
return -ENOENT;
+ }
/* Ensure that we do not send more than 50 overlapping requests
to the same server. We may make this configurable later or
@@ -346,6 +345,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
} else {
if(ses->server->tcpStatus == CifsExiting) {
spin_unlock(&GlobalMid_Lock);
+ cifs_small_buf_release(in_buf);
return -ENOENT;
}
@@ -385,6 +385,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
midQ = AllocMidQEntry(in_buf, ses);
if (midQ == NULL) {
up(&ses->server->tcpSem);
+ cifs_small_buf_release(in_buf);
/* If not lock req, update # of requests on wire to server */
if(long_op < 3) {
atomic_dec(&ses->server->inFlight);
@@ -408,14 +409,18 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
if(rc < 0) {
DeleteMidQEntry(midQ);
up(&ses->server->tcpSem);
+ cifs_small_buf_release(in_buf);
/* If not lock req, update # of requests on wire to server */
if(long_op < 3) {
atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q);
}
return rc;
- } else
+ } else {
up(&ses->server->tcpSem);
+ cifs_small_buf_release(in_buf);
+ }
+
if (long_op == -1)
goto cifs_no_response_exit2;
else if (long_op == 2) /* writes past end of file can take loong time */
@@ -543,6 +548,7 @@ cifs_no_response_exit2:
out_unlock2:
up(&ses->server->tcpSem);
+ cifs_small_buf_release(in_buf);
/* If not lock req, update # of requests on wire to server */
if(long_op < 3) {
atomic_dec(&ses->server->inFlight);
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 3938444d87b..7754d641775 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -62,9 +62,7 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name)
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -116,9 +114,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -223,9 +219,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -341,9 +335,7 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon;
- mutex_lock(&sb->s_vfs_rename_mutex);
full_path = build_path_from_dentry(direntry);
- mutex_unlock(&sb->s_vfs_rename_mutex);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 54f76de8a68..71f2ea632e5 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -82,7 +82,7 @@ struct inode_operations coda_dir_inode_operations =
.setattr = coda_setattr,
};
-struct file_operations coda_dir_operations = {
+const struct file_operations coda_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = coda_readdir,
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 146a991d6eb..7c2642431fa 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -288,7 +288,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
return err;
}
-struct file_operations coda_file_operations = {
+const struct file_operations coda_file_operations = {
.llseek = generic_file_llseek,
.read = coda_file_read,
.write = coda_file_write,
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index 127714936c6..214822be87b 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -36,7 +36,7 @@ struct inode_operations coda_ioctl_inode_operations =
.setattr = coda_setattr,
};
-struct file_operations coda_ioctl_operations = {
+const struct file_operations coda_ioctl_operations = {
.owner = THIS_MODULE,
.ioctl = coda_pioctl,
};
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 98c74fe2e13..6c6771db36d 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -342,7 +342,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
}
-static struct file_operations coda_psdev_fops = {
+static const struct file_operations coda_psdev_fops = {
.owner = THIS_MODULE,
.read = coda_psdev_read,
.write = coda_psdev_write,
diff --git a/fs/compat.c b/fs/compat.c
index ef5a0771592..b1f64786a61 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1217,6 +1217,10 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
if (ret < 0)
goto out;
+ ret = security_file_permission(file, type == READ ? MAY_READ:MAY_WRITE);
+ if (ret)
+ goto out;
+
fnv = NULL;
if (type == READ) {
fn = file->f_op->read;
@@ -1313,6 +1317,26 @@ out:
return ret;
}
+asmlinkage long
+compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32,
+ unsigned int nr_segs, unsigned int flags)
+{
+ unsigned i;
+ struct iovec *iov;
+ if (nr_segs > UIO_MAXIOV)
+ return -EINVAL;
+ iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
+ for (i = 0; i < nr_segs; i++) {
+ struct compat_iovec v;
+ if (get_user(v.iov_base, &iov32[i].iov_base) ||
+ get_user(v.iov_len, &iov32[i].iov_len) ||
+ put_user(compat_ptr(v.iov_base), &iov[i].iov_base) ||
+ put_user(v.iov_len, &iov[i].iov_len))
+ return -EFAULT;
+ }
+ return sys_vmsplice(fd, iov, nr_segs, flags);
+}
+
/*
* Exactly like fs/open.c:sys_open(), except that it doesn't set the
* O_LARGEFILE flag.
@@ -1639,15 +1663,6 @@ void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
* This is a virtual copy of sys_select from fs/select.c and probably
* should be compared to it from time to time
*/
-static void *select_bits_alloc(int size)
-{
- return kmalloc(6 * size, GFP_KERNEL);
-}
-
-static void select_bits_free(void *bits, int size)
-{
- kfree(bits);
-}
/*
* We can actually return ERESTARTSYS instead of EINTR, but I'd
@@ -1686,7 +1701,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
*/
ret = -ENOMEM;
size = FDS_BYTES(n);
- bits = select_bits_alloc(size);
+ bits = kmalloc(6 * size, GFP_KERNEL);
if (!bits)
goto out_nofds;
fds.in = (unsigned long *) bits;
@@ -1720,7 +1735,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
compat_set_fd_set(n, exp, fds.res_ex);
out:
- select_bits_free(bits, size);
+ kfree(bits);
out_nofds:
return ret;
}
@@ -1898,7 +1913,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
}
if (sigmask) {
- if (sigsetsize |= sizeof(compat_sigset_t))
+ if (sigsetsize != sizeof(compat_sigset_t))
return -EINVAL;
if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
return -EFAULT;
@@ -2015,109 +2030,115 @@ union compat_nfsctl_res {
struct knfsd_fh cr32_getfs;
};
-static int compat_nfs_svc_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg)
+static int compat_nfs_svc_trans(struct nfsctl_arg *karg,
+ struct compat_nfsctl_arg __user *arg)
{
- int err;
-
- err = access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc));
- err |= get_user(karg->ca_version, &arg->ca32_version);
- err |= __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port);
- err |= __get_user(karg->ca_svc.svc_nthreads, &arg->ca32_svc.svc32_nthreads);
- return (err) ? -EFAULT : 0;
+ if (!access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)) ||
+ get_user(karg->ca_version, &arg->ca32_version) ||
+ __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port) ||
+ __get_user(karg->ca_svc.svc_nthreads,
+ &arg->ca32_svc.svc32_nthreads))
+ return -EFAULT;
+ return 0;
}
-static int compat_nfs_clnt_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg)
-{
- int err;
-
- err = access_ok(VERIFY_READ, &arg->ca32_client, sizeof(arg->ca32_client));
- err |= get_user(karg->ca_version, &arg->ca32_version);
- err |= __copy_from_user(&karg->ca_client.cl_ident[0],
- &arg->ca32_client.cl32_ident[0],
- NFSCLNT_IDMAX);
- err |= __get_user(karg->ca_client.cl_naddr, &arg->ca32_client.cl32_naddr);
- err |= __copy_from_user(&karg->ca_client.cl_addrlist[0],
- &arg->ca32_client.cl32_addrlist[0],
- (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
- err |= __get_user(karg->ca_client.cl_fhkeytype,
- &arg->ca32_client.cl32_fhkeytype);
- err |= __get_user(karg->ca_client.cl_fhkeylen,
- &arg->ca32_client.cl32_fhkeylen);
- err |= __copy_from_user(&karg->ca_client.cl_fhkey[0],
- &arg->ca32_client.cl32_fhkey[0],
- NFSCLNT_KEYMAX);
+static int compat_nfs_clnt_trans(struct nfsctl_arg *karg,
+ struct compat_nfsctl_arg __user *arg)
+{
+ if (!access_ok(VERIFY_READ, &arg->ca32_client,
+ sizeof(arg->ca32_client)) ||
+ get_user(karg->ca_version, &arg->ca32_version) ||
+ __copy_from_user(&karg->ca_client.cl_ident[0],
+ &arg->ca32_client.cl32_ident[0],
+ NFSCLNT_IDMAX) ||
+ __get_user(karg->ca_client.cl_naddr,
+ &arg->ca32_client.cl32_naddr) ||
+ __copy_from_user(&karg->ca_client.cl_addrlist[0],
+ &arg->ca32_client.cl32_addrlist[0],
+ (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)) ||
+ __get_user(karg->ca_client.cl_fhkeytype,
+ &arg->ca32_client.cl32_fhkeytype) ||
+ __get_user(karg->ca_client.cl_fhkeylen,
+ &arg->ca32_client.cl32_fhkeylen) ||
+ __copy_from_user(&karg->ca_client.cl_fhkey[0],
+ &arg->ca32_client.cl32_fhkey[0],
+ NFSCLNT_KEYMAX))
+ return -EFAULT;
- return (err) ? -EFAULT : 0;
+ return 0;
}
-static int compat_nfs_exp_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg)
-{
- int err;
-
- err = access_ok(VERIFY_READ, &arg->ca32_export, sizeof(arg->ca32_export));
- err |= get_user(karg->ca_version, &arg->ca32_version);
- err |= __copy_from_user(&karg->ca_export.ex_client[0],
- &arg->ca32_export.ex32_client[0],
- NFSCLNT_IDMAX);
- err |= __copy_from_user(&karg->ca_export.ex_path[0],
- &arg->ca32_export.ex32_path[0],
- NFS_MAXPATHLEN);
- err |= __get_user(karg->ca_export.ex_dev,
- &arg->ca32_export.ex32_dev);
- err |= __get_user(karg->ca_export.ex_ino,
- &arg->ca32_export.ex32_ino);
- err |= __get_user(karg->ca_export.ex_flags,
- &arg->ca32_export.ex32_flags);
- err |= __get_user(karg->ca_export.ex_anon_uid,
- &arg->ca32_export.ex32_anon_uid);
- err |= __get_user(karg->ca_export.ex_anon_gid,
- &arg->ca32_export.ex32_anon_gid);
+static int compat_nfs_exp_trans(struct nfsctl_arg *karg,
+ struct compat_nfsctl_arg __user *arg)
+{
+ if (!access_ok(VERIFY_READ, &arg->ca32_export,
+ sizeof(arg->ca32_export)) ||
+ get_user(karg->ca_version, &arg->ca32_version) ||
+ __copy_from_user(&karg->ca_export.ex_client[0],
+ &arg->ca32_export.ex32_client[0],
+ NFSCLNT_IDMAX) ||
+ __copy_from_user(&karg->ca_export.ex_path[0],
+ &arg->ca32_export.ex32_path[0],
+ NFS_MAXPATHLEN) ||
+ __get_user(karg->ca_export.ex_dev,
+ &arg->ca32_export.ex32_dev) ||
+ __get_user(karg->ca_export.ex_ino,
+ &arg->ca32_export.ex32_ino) ||
+ __get_user(karg->ca_export.ex_flags,
+ &arg->ca32_export.ex32_flags) ||
+ __get_user(karg->ca_export.ex_anon_uid,
+ &arg->ca32_export.ex32_anon_uid) ||
+ __get_user(karg->ca_export.ex_anon_gid,
+ &arg->ca32_export.ex32_anon_gid))
+ return -EFAULT;
SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid);
SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid);
- return (err) ? -EFAULT : 0;
+ return 0;
}
-static int compat_nfs_getfd_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg)
-{
- int err;
-
- err = access_ok(VERIFY_READ, &arg->ca32_getfd, sizeof(arg->ca32_getfd));
- err |= get_user(karg->ca_version, &arg->ca32_version);
- err |= __copy_from_user(&karg->ca_getfd.gd_addr,
- &arg->ca32_getfd.gd32_addr,
- (sizeof(struct sockaddr)));
- err |= __copy_from_user(&karg->ca_getfd.gd_path,
- &arg->ca32_getfd.gd32_path,
- (NFS_MAXPATHLEN+1));
- err |= __get_user(karg->ca_getfd.gd_version,
- &arg->ca32_getfd.gd32_version);
+static int compat_nfs_getfd_trans(struct nfsctl_arg *karg,
+ struct compat_nfsctl_arg __user *arg)
+{
+ if (!access_ok(VERIFY_READ, &arg->ca32_getfd,
+ sizeof(arg->ca32_getfd)) ||
+ get_user(karg->ca_version, &arg->ca32_version) ||
+ __copy_from_user(&karg->ca_getfd.gd_addr,
+ &arg->ca32_getfd.gd32_addr,
+ (sizeof(struct sockaddr))) ||
+ __copy_from_user(&karg->ca_getfd.gd_path,
+ &arg->ca32_getfd.gd32_path,
+ (NFS_MAXPATHLEN+1)) ||
+ __get_user(karg->ca_getfd.gd_version,
+ &arg->ca32_getfd.gd32_version))
+ return -EFAULT;
- return (err) ? -EFAULT : 0;
+ return 0;
}
-static int compat_nfs_getfs_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg)
+static int compat_nfs_getfs_trans(struct nfsctl_arg *karg,
+ struct compat_nfsctl_arg __user *arg)
{
- int err;
-
- err = access_ok(VERIFY_READ, &arg->ca32_getfs, sizeof(arg->ca32_getfs));
- err |= get_user(karg->ca_version, &arg->ca32_version);
- err |= __copy_from_user(&karg->ca_getfs.gd_addr,
- &arg->ca32_getfs.gd32_addr,
- (sizeof(struct sockaddr)));
- err |= __copy_from_user(&karg->ca_getfs.gd_path,
- &arg->ca32_getfs.gd32_path,
- (NFS_MAXPATHLEN+1));
- err |= __get_user(karg->ca_getfs.gd_maxlen,
- &arg->ca32_getfs.gd32_maxlen);
+ if (!access_ok(VERIFY_READ,&arg->ca32_getfs,sizeof(arg->ca32_getfs)) ||
+ get_user(karg->ca_version, &arg->ca32_version) ||
+ __copy_from_user(&karg->ca_getfs.gd_addr,
+ &arg->ca32_getfs.gd32_addr,
+ (sizeof(struct sockaddr))) ||
+ __copy_from_user(&karg->ca_getfs.gd_path,
+ &arg->ca32_getfs.gd32_path,
+ (NFS_MAXPATHLEN+1)) ||
+ __get_user(karg->ca_getfs.gd_maxlen,
+ &arg->ca32_getfs.gd32_maxlen))
+ return -EFAULT;
- return (err) ? -EFAULT : 0;
+ return 0;
}
/* This really doesn't need translations, we are only passing
* back a union which contains opaque nfs file handle data.
*/
-static int compat_nfs_getfh_res_trans(union nfsctl_res *kres, union compat_nfsctl_res __user *res)
+static int compat_nfs_getfh_res_trans(union nfsctl_res *kres,
+ union compat_nfsctl_res __user *res)
{
int err;
@@ -2126,8 +2147,9 @@ static int compat_nfs_getfh_res_trans(union nfsctl_res *kres, union compat_nfsct
return (err) ? -EFAULT : 0;
}
-asmlinkage long compat_sys_nfsservctl(int cmd, struct compat_nfsctl_arg __user *arg,
- union compat_nfsctl_res __user *res)
+asmlinkage long compat_sys_nfsservctl(int cmd,
+ struct compat_nfsctl_arg __user *arg,
+ union compat_nfsctl_res __user *res)
{
struct nfsctl_arg *karg;
union nfsctl_res *kres;
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index f70e46951b3..3f4ff7a242b 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -72,9 +72,9 @@ extern void configfs_release_fs(void);
extern struct rw_semaphore configfs_rename_sem;
extern struct super_block * configfs_sb;
-extern struct file_operations configfs_dir_operations;
-extern struct file_operations configfs_file_operations;
-extern struct file_operations bin_fops;
+extern const struct file_operations configfs_dir_operations;
+extern const struct file_operations configfs_file_operations;
+extern const struct file_operations bin_fops;
extern struct inode_operations configfs_dir_inode_operations;
extern struct inode_operations configfs_symlink_inode_operations;
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index ca60e3abef4..5f952187fc5 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -504,14 +504,16 @@ static int populate_groups(struct config_group *group)
int ret = 0;
int i;
- if (group && group->default_groups) {
- /* FYI, we're faking mkdir here
+ if (group->default_groups) {
+ /*
+ * FYI, we're faking mkdir here
* I'm not sure we need this semaphore, as we're called
* from our parent's mkdir. That holds our parent's
* i_mutex, so afaik lookup cannot continue through our
* parent to find us, let alone mess with our tree.
* That said, taking our i_mutex is closer to mkdir
- * emulation, and shouldn't hurt. */
+ * emulation, and shouldn't hurt.
+ */
mutex_lock(&dentry->d_inode->i_mutex);
for (i = 0; group->default_groups[i]; i++) {
@@ -546,20 +548,34 @@ static void unlink_obj(struct config_item *item)
item->ci_group = NULL;
item->ci_parent = NULL;
+
+ /* Drop the reference for ci_entry */
config_item_put(item);
+ /* Drop the reference for ci_parent */
config_group_put(group);
}
}
static void link_obj(struct config_item *parent_item, struct config_item *item)
{
- /* Parent seems redundant with group, but it makes certain
- * traversals much nicer. */
+ /*
+ * Parent seems redundant with group, but it makes certain
+ * traversals much nicer.
+ */
item->ci_parent = parent_item;
+
+ /*
+ * We hold a reference on the parent for the child's ci_parent
+ * link.
+ */
item->ci_group = config_group_get(to_config_group(parent_item));
list_add_tail(&item->ci_entry, &item->ci_group->cg_children);
+ /*
+ * We hold a reference on the child for ci_entry on the parent's
+ * cg_children
+ */
config_item_get(item);
}
@@ -684,6 +700,10 @@ static void client_drop_item(struct config_item *parent_item,
type = parent_item->ci_type;
BUG_ON(!type);
+ /*
+ * If ->drop_item() exists, it is responsible for the
+ * config_item_put().
+ */
if (type->ct_group_ops && type->ct_group_ops->drop_item)
type->ct_group_ops->drop_item(to_config_group(parent_item),
item);
@@ -694,23 +714,28 @@ static void client_drop_item(struct config_item *parent_item,
static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
- int ret;
+ int ret, module_got = 0;
struct config_group *group;
struct config_item *item;
struct config_item *parent_item;
struct configfs_subsystem *subsys;
struct configfs_dirent *sd;
struct config_item_type *type;
- struct module *owner;
+ struct module *owner = NULL;
char *name;
- if (dentry->d_parent == configfs_sb->s_root)
- return -EPERM;
+ if (dentry->d_parent == configfs_sb->s_root) {
+ ret = -EPERM;
+ goto out;
+ }
sd = dentry->d_parent->d_fsdata;
- if (!(sd->s_type & CONFIGFS_USET_DIR))
- return -EPERM;
+ if (!(sd->s_type & CONFIGFS_USET_DIR)) {
+ ret = -EPERM;
+ goto out;
+ }
+ /* Get a working ref for the duration of this function */
parent_item = configfs_get_config_item(dentry->d_parent);
type = parent_item->ci_type;
subsys = to_config_group(parent_item)->cg_subsys;
@@ -719,15 +744,16 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
if (!type || !type->ct_group_ops ||
(!type->ct_group_ops->make_group &&
!type->ct_group_ops->make_item)) {
- config_item_put(parent_item);
- return -EPERM; /* What lack-of-mkdir returns */
+ ret = -EPERM; /* Lack-of-mkdir returns -EPERM */
+ goto out_put;
}
name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL);
if (!name) {
- config_item_put(parent_item);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out_put;
}
+
snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
down(&subsys->su_sem);
@@ -748,40 +774,67 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
kfree(name);
if (!item) {
- config_item_put(parent_item);
- return -ENOMEM;
+ /*
+ * If item == NULL, then link_obj() was never called.
+ * There are no extra references to clean up.
+ */
+ ret = -ENOMEM;
+ goto out_put;
}
- ret = -EINVAL;
+ /*
+ * link_obj() has been called (via link_group() for groups).
+ * From here on out, errors must clean that up.
+ */
+
type = item->ci_type;
- if (type) {
- owner = type->ct_owner;
- if (try_module_get(owner)) {
- if (group) {
- ret = configfs_attach_group(parent_item,
- item,
- dentry);
- } else {
- ret = configfs_attach_item(parent_item,
- item,
- dentry);
- }
+ if (!type) {
+ ret = -EINVAL;
+ goto out_unlink;
+ }
- if (ret) {
- down(&subsys->su_sem);
- if (group)
- unlink_group(group);
- else
- unlink_obj(item);
- client_drop_item(parent_item, item);
- up(&subsys->su_sem);
+ owner = type->ct_owner;
+ if (!try_module_get(owner)) {
+ ret = -EINVAL;
+ goto out_unlink;
+ }
- config_item_put(parent_item);
- module_put(owner);
- }
- }
+ /*
+ * I hate doing it this way, but if there is
+ * an error, module_put() probably should
+ * happen after any cleanup.
+ */
+ module_got = 1;
+
+ if (group)
+ ret = configfs_attach_group(parent_item, item, dentry);
+ else
+ ret = configfs_attach_item(parent_item, item, dentry);
+
+out_unlink:
+ if (ret) {
+ /* Tear down everything we built up */
+ down(&subsys->su_sem);
+ if (group)
+ unlink_group(group);
+ else
+ unlink_obj(item);
+ client_drop_item(parent_item, item);
+ up(&subsys->su_sem);
+
+ if (module_got)
+ module_put(owner);
}
+out_put:
+ /*
+ * link_obj()/link_group() took a reference from child->parent,
+ * so the parent is safely pinned. We can drop our working
+ * reference.
+ */
+ config_item_put(parent_item);
+
+out:
return ret;
}
@@ -801,6 +854,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
if (sd->s_type & CONFIGFS_USET_DEFAULT)
return -EPERM;
+ /* 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;
BUG_ON(!subsys);
@@ -817,6 +871,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
return ret;
}
+ /* Get a working ref for the duration of this function */
item = configfs_get_config_item(dentry);
/* Drop reference from above, item already holds one. */
@@ -1027,7 +1082,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin)
return offset;
}
-struct file_operations configfs_dir_operations = {
+const struct file_operations configfs_dir_operations = {
.open = configfs_dir_open,
.release = configfs_dir_close,
.llseek = configfs_dir_lseek,
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
index 3921920d871..f499803743e 100644
--- a/fs/configfs/file.c
+++ b/fs/configfs/file.c
@@ -322,7 +322,7 @@ static int configfs_release(struct inode * inode, struct file * filp)
return 0;
}
-struct file_operations configfs_file_operations = {
+const struct file_operations configfs_file_operations = {
.read = configfs_read_file,
.write = configfs_write_file,
.llseek = generic_file_llseek,
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index acc1b2c10a8..9efcc3a164e 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -29,7 +29,7 @@
static struct super_operations cramfs_ops;
static struct inode_operations cramfs_dir_inode_operations;
-static struct file_operations cramfs_directory_operations;
+static const struct file_operations cramfs_directory_operations;
static struct address_space_operations cramfs_aops;
static DEFINE_MUTEX(read_mutex);
@@ -512,7 +512,7 @@ static struct address_space_operations cramfs_aops = {
/*
* A directory can only readdir
*/
-static struct file_operations cramfs_directory_operations = {
+static const struct file_operations cramfs_directory_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = cramfs_readdir,
diff --git a/fs/dcache.c b/fs/dcache.c
index 19458d39950..940d188e5d1 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1101,6 +1101,32 @@ next:
}
/**
+ * d_hash_and_lookup - hash the qstr then search for a dentry
+ * @dir: Directory to search in
+ * @name: qstr of name we wish to find
+ *
+ * On hash failure or on lookup failure NULL is returned.
+ */
+struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
+{
+ struct dentry *dentry = NULL;
+
+ /*
+ * Check for a fs-specific hash function. Note that we must
+ * calculate the standard hash first, as the d_op->d_hash()
+ * routine may choose to leave the hash value unchanged.
+ */
+ name->hash = full_name_hash(name->name, name->len);
+ if (dir->d_op && dir->d_op->d_hash) {
+ if (dir->d_op->d_hash(dir, name) < 0)
+ goto out;
+ }
+ dentry = d_lookup(dir, name);
+out:
+ return dentry;
+}
+
+/**
* d_validate - verify dentry provided from insecure source
* @dentry: The dentry alleged to be valid child of @dparent
* @dparent: The parent dentry (known to be valid)
@@ -1172,11 +1198,11 @@ void d_delete(struct dentry * dentry)
spin_lock(&dentry->d_lock);
isdir = S_ISDIR(dentry->d_inode->i_mode);
if (atomic_read(&dentry->d_count) == 1) {
- /* remove this and other inotify debug checks after 2.6.18 */
- dentry->d_flags &= ~DCACHE_INOTIFY_PARENT_WATCHED;
-
dentry_iput(dentry);
fsnotify_nameremove(dentry, isdir);
+
+ /* remove this and other inotify debug checks after 2.6.18 */
+ dentry->d_flags &= ~DCACHE_INOTIFY_PARENT_WATCHED;
return;
}
@@ -1616,26 +1642,12 @@ ino_t find_inode_number(struct dentry *dir, struct qstr *name)
struct dentry * dentry;
ino_t ino = 0;
- /*
- * Check for a fs-specific hash function. Note that we must
- * calculate the standard hash first, as the d_op->d_hash()
- * routine may choose to leave the hash value unchanged.
- */
- name->hash = full_name_hash(name->name, name->len);
- if (dir->d_op && dir->d_op->d_hash)
- {
- if (dir->d_op->d_hash(dir, name) != 0)
- goto out;
- }
-
- dentry = d_lookup(dir, name);
- if (dentry)
- {
+ dentry = d_hash_and_lookup(dir, name);
+ if (dentry) {
if (dentry->d_inode)
ino = dentry->d_inode->i_ino;
dput(dentry);
}
-out:
return ino;
}
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 40c4fc973fa..66a505422e5 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -39,7 +39,7 @@ static int default_open(struct inode *inode, struct file *file)
return 0;
}
-struct file_operations debugfs_file_operations = {
+const struct file_operations debugfs_file_operations = {
.read = default_read_file,
.write = default_write_file,
.open = default_open,
@@ -213,7 +213,7 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
return count;
}
-static struct file_operations fops_bool = {
+static const struct file_operations fops_bool = {
.read = read_file_bool,
.write = write_file_bool,
.open = default_open,
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index d4f1a2cddd4..b55b4ea9a67 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -67,12 +67,13 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
int mode, dev_t dev)
{
- struct inode *inode = debugfs_get_inode(dir->i_sb, mode, dev);
+ struct inode *inode;
int error = -EPERM;
if (dentry->d_inode)
return -EEXIST;
+ inode = debugfs_get_inode(dir->i_sb, mode, dev);
if (inode) {
d_instantiate(dentry, inode);
dget(dentry);
@@ -191,7 +192,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
*/
struct dentry *debugfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
- struct file_operations *fops)
+ const struct file_operations *fops)
{
struct dentry *dentry = NULL;
int error;
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index b621521e09d..52f5059c4f3 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -856,14 +856,14 @@ static int devfsd_close(struct inode *inode, struct file *file);
#ifdef CONFIG_DEVFS_DEBUG
static ssize_t stat_read(struct file *file, char __user *buf, size_t len,
loff_t * ppos);
-static struct file_operations stat_fops = {
+static const struct file_operations stat_fops = {
.open = nonseekable_open,
.read = stat_read,
};
#endif
/* Devfs daemon file operations */
-static struct file_operations devfsd_fops = {
+static const struct file_operations devfsd_fops = {
.open = nonseekable_open,
.read = devfsd_read,
.ioctl = devfsd_ioctl,
@@ -1842,8 +1842,8 @@ static int try_modload(struct devfs_entry *parent, struct fs_info *fs_info,
static struct inode_operations devfs_iops;
static struct inode_operations devfs_dir_iops;
-static struct file_operations devfs_fops;
-static struct file_operations devfs_dir_fops;
+static const struct file_operations devfs_fops;
+static const struct file_operations devfs_dir_fops;
static struct inode_operations devfs_symlink_iops;
static int devfs_notify_change(struct dentry *dentry, struct iattr *iattr)
@@ -2061,11 +2061,11 @@ static int devfs_open(struct inode *inode, struct file *file)
return err;
} /* End Function devfs_open */
-static struct file_operations devfs_fops = {
+static const struct file_operations devfs_fops = {
.open = devfs_open,
};
-static struct file_operations devfs_dir_fops = {
+static const struct file_operations devfs_dir_fops = {
.read = generic_read_dir,
.readdir = devfs_readdir,
};
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 9d1d2aa73e4..b05d1b21877 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -524,8 +524,6 @@ static int get_more_blocks(struct dio *dio)
*/
ret = dio->page_errors;
if (ret == 0) {
- map_bh->b_state = 0;
- map_bh->b_size = 0;
BUG_ON(dio->block_in_file >= dio->final_block_in_request);
fs_startblk = dio->block_in_file >> dio->blkfactor;
dio_count = dio->final_block_in_request - dio->block_in_file;
@@ -534,6 +532,9 @@ static int get_more_blocks(struct dio *dio)
if (dio_count & blkmask)
fs_count++;
+ map_bh->b_state = 0;
+ map_bh->b_size = fs_count << dio->inode->i_blkbits;
+
create = dio->rw == WRITE;
if (dio->lock_type == DIO_LOCKING) {
if (dio->block_in_file < (i_size_read(dio->inode) >>
@@ -542,13 +543,13 @@ static int get_more_blocks(struct dio *dio)
} else if (dio->lock_type == DIO_NO_LOCKING) {
create = 0;
}
+
/*
* For writes inside i_size we forbid block creations: only
* overwrites are permitted. We fall back to buffered writes
* at a higher level for inside-i_size block-instantiating
* writes.
*/
- map_bh->b_size = fs_count << dio->blkbits;
ret = (*dio->get_block)(dio->inode, fs_startblk,
map_bh, create);
}
@@ -928,8 +929,7 @@ do_holes:
block_in_page += this_chunk_blocks;
dio->blocks_available -= this_chunk_blocks;
next_block:
- if (dio->block_in_file > dio->final_block_in_request)
- BUG();
+ BUG_ON(dio->block_in_file > dio->final_block_in_request);
if (dio->block_in_file == dio->final_block_in_request)
break;
}
diff --git a/fs/dquot.c b/fs/dquot.c
index 6b388692093..81d87a413c6 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -590,8 +590,7 @@ we_slept:
atomic_dec(&dquot->dq_count);
#ifdef __DQUOT_PARANOIA
/* sanity check */
- if (!list_empty(&dquot->dq_free))
- BUG();
+ BUG_ON(!list_empty(&dquot->dq_free));
#endif
put_dquot_last(dquot);
spin_unlock(&dq_list_lock);
@@ -666,8 +665,7 @@ we_slept:
return NODQUOT;
}
#ifdef __DQUOT_PARANOIA
- if (!dquot->dq_sb) /* Has somebody invalidated entry under us? */
- BUG();
+ BUG_ON(!dquot->dq_sb); /* Has somebody invalidated entry under us? */
#endif
return dquot;
diff --git a/fs/efs/dir.c b/fs/efs/dir.c
index 777c614ff36..17f5b2d3c16 100644
--- a/fs/efs/dir.c
+++ b/fs/efs/dir.c
@@ -10,7 +10,7 @@
static int efs_readdir(struct file *, void *, filldir_t);
-struct file_operations efs_dir_operations = {
+const struct file_operations efs_dir_operations = {
.read = generic_read_dir,
.readdir = efs_readdir,
};
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index e067a06c646..1b4491cdd11 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -290,7 +290,7 @@ static kmem_cache_t *pwq_cache __read_mostly;
static struct vfsmount *eventpoll_mnt __read_mostly;
/* File callbacks that implement the eventpoll file behaviour */
-static struct file_operations eventpoll_fops = {
+static const struct file_operations eventpoll_fops = {
.release = ep_eventpoll_close,
.poll = ep_eventpoll_poll
};
@@ -599,7 +599,7 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
switch (op) {
case EPOLL_CTL_ADD:
if (!epi) {
- epds.events |= POLLERR | POLLHUP | POLLRDHUP;
+ epds.events |= POLLERR | POLLHUP;
error = ep_insert(ep, &epds, tfile, fd);
} else
@@ -613,7 +613,7 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
break;
case EPOLL_CTL_MOD:
if (epi) {
- epds.events |= POLLERR | POLLHUP | POLLRDHUP;
+ epds.events |= POLLERR | POLLHUP;
error = ep_modify(ep, epi, &epds);
} else
error = -ENOENT;
diff --git a/fs/exec.c b/fs/exec.c
index c7397c46ad6..3a79d97ac23 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -561,7 +561,7 @@ static int exec_mmap(struct mm_struct *mm)
arch_pick_mmap_layout(mm);
if (old_mm) {
up_read(&old_mm->mmap_sem);
- if (active_mm != old_mm) BUG();
+ BUG_ON(active_mm != old_mm);
mmput(old_mm);
return 0;
}
@@ -616,6 +616,15 @@ static int de_thread(struct task_struct *tsk)
kmem_cache_free(sighand_cachep, newsighand);
return -EAGAIN;
}
+
+ /*
+ * child_reaper ignores SIGKILL, change it now.
+ * Reparenting needs write_lock on tasklist_lock,
+ * so it is safe to do it under read_lock.
+ */
+ if (unlikely(current->group_leader == child_reaper))
+ child_reaper = current;
+
zap_other_threads(current);
read_unlock(&tasklist_lock);
@@ -656,9 +665,7 @@ static int de_thread(struct task_struct *tsk)
* and to assume its PID:
*/
if (!thread_group_leader(current)) {
- struct task_struct *parent;
struct dentry *proc_dentry1, *proc_dentry2;
- unsigned long ptrace;
/*
* Wait for the thread group leader to be a zombie.
@@ -669,6 +676,18 @@ static int de_thread(struct task_struct *tsk)
while (leader->exit_state != EXIT_ZOMBIE)
yield();
+ /*
+ * The only record we have of the real-time age of a
+ * process, regardless of execs it's done, is start_time.
+ * All the past CPU time is accumulated in signal_struct
+ * from sister threads now dead. But in this non-leader
+ * exec, nothing survives from the original leader thread,
+ * whose birth marks the true age of this process now.
+ * When we take on its identity by switching to its PID, we
+ * also take its birthdate (always earlier than our own).
+ */
+ current->start_time = leader->start_time;
+
spin_lock(&leader->proc_lock);
spin_lock(&current->proc_lock);
proc_dentry1 = proc_pid_unhash(current);
@@ -683,38 +702,26 @@ static int de_thread(struct task_struct *tsk)
* two threads with a switched PID, and release
* the former thread group leader:
*/
- ptrace = leader->ptrace;
- parent = leader->parent;
- if (unlikely(ptrace) && unlikely(parent == current)) {
- /*
- * Joker was ptracing his own group leader,
- * and now he wants to be his own parent!
- * We can't have that.
- */
- ptrace = 0;
- }
-
- ptrace_unlink(current);
- ptrace_unlink(leader);
- remove_parent(current);
- remove_parent(leader);
- switch_exec_pids(leader, current);
+ /* Become a process group leader with the old leader's pid.
+ * Note: The old leader also uses thispid until release_task
+ * is called. Odd but simple and correct.
+ */
+ detach_pid(current, PIDTYPE_PID);
+ current->pid = leader->pid;
+ attach_pid(current, PIDTYPE_PID, current->pid);
+ attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
+ attach_pid(current, PIDTYPE_SID, current->signal->session);
+ list_add_tail_rcu(&current->tasks, &init_task.tasks);
- current->parent = current->real_parent = leader->real_parent;
- leader->parent = leader->real_parent = child_reaper;
current->group_leader = current;
- leader->group_leader = leader;
+ leader->group_leader = current;
- add_parent(current, current->parent);
- add_parent(leader, leader->parent);
- if (ptrace) {
- current->ptrace = ptrace;
- __ptrace_link(current, parent);
- }
+ /* Reduce leader to a thread */
+ detach_pid(leader, PIDTYPE_PGID);
+ detach_pid(leader, PIDTYPE_SID);
+ list_del_init(&leader->tasks);
- list_del(&current->tasks);
- list_add_tail(&current->tasks, &init_task.tasks);
current->exit_signal = SIGCHLD;
BUG_ON(leader->exit_state != EXIT_ZOMBIE);
@@ -751,7 +758,6 @@ no_thread_group:
/*
* Move our state over to newsighand and switch it in.
*/
- spin_lock_init(&newsighand->siglock);
atomic_set(&newsighand->count, 1);
memcpy(newsighand->action, oldsighand->action,
sizeof(newsighand->action));
@@ -768,7 +774,7 @@ no_thread_group:
write_unlock_irq(&tasklist_lock);
if (atomic_dec_and_test(&oldsighand->count))
- sighand_free(oldsighand);
+ kmem_cache_free(sighand_cachep, oldsighand);
}
BUG_ON(!thread_group_leader(current));
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index b06b54f1bbb..4c39009350f 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -102,7 +102,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
if (acceptable(context, result))
return result;
if (S_ISDIR(result->d_inode->i_mode)) {
- /* there is no other dentry, so fail */
+ err = -EACCES;
goto err_result;
}
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 0165388c425..d672aa9f406 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -658,7 +658,7 @@ not_empty:
return 0;
}
-struct file_operations ext2_dir_operations = {
+const struct file_operations ext2_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = ext2_readdir,
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 11035ac7986..9f74a62be55 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -154,12 +154,12 @@ extern void ext2_write_super (struct super_block *);
*/
/* dir.c */
-extern struct file_operations ext2_dir_operations;
+extern const struct file_operations ext2_dir_operations;
/* file.c */
extern struct inode_operations ext2_file_inode_operations;
-extern struct file_operations ext2_file_operations;
-extern struct file_operations ext2_xip_file_operations;
+extern const struct file_operations ext2_file_operations;
+extern const struct file_operations ext2_xip_file_operations;
/* inode.c */
extern struct address_space_operations ext2_aops;
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index a484412fc78..23e2c7ccec1 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -39,7 +39,7 @@ static int ext2_release_file (struct inode * inode, struct file * filp)
* We have mostly NULL's here: the current defaults are ok for
* the ext2 filesystem.
*/
-struct file_operations ext2_file_operations = {
+const struct file_operations ext2_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
@@ -53,10 +53,12 @@ struct file_operations ext2_file_operations = {
.readv = generic_file_readv,
.writev = generic_file_writev,
.sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
+ .splice_write = generic_file_splice_write,
};
#ifdef CONFIG_EXT2_FS_XIP
-struct file_operations ext2_xip_file_operations = {
+const struct file_operations ext2_xip_file_operations = {
.llseek = generic_file_llseek,
.read = xip_file_read,
.write = xip_file_write,
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index 38bd3f6ec14..f37528ed222 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -39,7 +39,7 @@ static int ext3_dx_readdir(struct file * filp,
static int ext3_release_dir (struct inode * inode,
struct file * filp);
-struct file_operations ext3_dir_operations = {
+const struct file_operations ext3_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = ext3_readdir, /* we take BKL. needed?*/
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 59098ea5671..1efefb630ea 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -105,7 +105,7 @@ force_commit:
return ret;
}
-struct file_operations ext3_file_operations = {
+const struct file_operations ext3_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
@@ -119,6 +119,8 @@ struct file_operations ext3_file_operations = {
.release = ext3_release_file,
.fsync = ext3_sync_file,
.sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
+ .splice_write = generic_file_splice_write,
};
struct inode_operations ext3_file_inode_operations = {
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 48ae0339af1..2edd7eec88f 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -711,7 +711,7 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode,
* direct blocks blocks
*/
if (num == 0 && blks > 1) {
- current_block = le32_to_cpu(where->key + 1);
+ current_block = le32_to_cpu(where->key) + 1;
for (i = 1; i < blks; i++)
*(where->p + i ) = cpu_to_le32(current_block++);
}
@@ -724,7 +724,7 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode,
if (block_i) {
block_i->last_alloc_logical_block = block + blks - 1;
block_i->last_alloc_physical_block =
- le32_to_cpu(where[num].key + blks - 1);
+ le32_to_cpu(where[num].key) + blks - 1;
}
/* We are done with atomic stuff, now do the rest of housekeeping */
@@ -814,11 +814,13 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
/* Simplest case - block found, no allocation needed */
if (!partial) {
- first_block = chain[depth - 1].key;
+ first_block = le32_to_cpu(chain[depth - 1].key);
clear_buffer_new(bh_result);
count++;
/*map more blocks*/
while (count < maxblocks && count <= blocks_to_boundary) {
+ unsigned long blk;
+
if (!verify_chain(chain, partial)) {
/*
* Indirect block might be removed by
@@ -831,8 +833,9 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
count = 0;
break;
}
- if (le32_to_cpu(*(chain[depth-1].p+count) ==
- (first_block + count)))
+ blk = le32_to_cpu(*(chain[depth-1].p + count));
+
+ if (blk == first_block + count)
count++;
else
break;
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index aaf1da17b6d..8c22aa9a7fb 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -48,6 +48,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
if (!S_ISDIR(inode->i_mode))
flags &= ~EXT3_DIRSYNC_FL;
+ mutex_lock(&inode->i_mutex);
oldflags = ei->i_flags;
/* The JOURNAL_DATA flag is modifiable only by root */
@@ -60,8 +61,10 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
* This test looks nicer. Thanks to Pauline Middelink
*/
if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
- if (!capable(CAP_LINUX_IMMUTABLE))
+ if (!capable(CAP_LINUX_IMMUTABLE)) {
+ mutex_unlock(&inode->i_mutex);
return -EPERM;
+ }
}
/*
@@ -69,14 +72,18 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
* the relevant capability.
*/
if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
- if (!capable(CAP_SYS_RESOURCE))
+ if (!capable(CAP_SYS_RESOURCE)) {
+ mutex_unlock(&inode->i_mutex);
return -EPERM;
+ }
}
handle = ext3_journal_start(inode, 1);
- if (IS_ERR(handle))
+ if (IS_ERR(handle)) {
+ mutex_unlock(&inode->i_mutex);
return PTR_ERR(handle);
+ }
if (IS_SYNC(inode))
handle->h_sync = 1;
err = ext3_reserve_inode_write(handle, inode, &iloc);
@@ -93,11 +100,14 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
err = ext3_mark_iloc_dirty(handle, inode, &iloc);
flags_err:
ext3_journal_stop(handle);
- if (err)
+ if (err) {
+ mutex_unlock(&inode->i_mutex);
return err;
+ }
if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL))
err = ext3_change_inode_journal_flag(inode, jflag);
+ mutex_unlock(&inode->i_mutex);
return err;
}
case EXT3_IOC_GETVERSION:
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
index 1041dab6de2..34b39e9a1e5 100644
--- a/fs/ext3/resize.c
+++ b/fs/ext3/resize.c
@@ -213,7 +213,7 @@ static int setup_new_group_blocks(struct super_block *sb,
goto exit_bh;
}
lock_buffer(bh);
- memcpy(gdb->b_data, sbi->s_group_desc[i], bh->b_size);
+ memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, bh->b_size);
set_buffer_uptodate(gdb);
unlock_buffer(bh);
ext3_journal_dirty_metadata(handle, gdb);
@@ -974,6 +974,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
ext3_warning(sb, __FUNCTION__,
"multiple resizers run on filesystem!");
+ unlock_super(sb);
err = -EBUSY;
goto exit_put;
}
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 4095bc149eb..698b85bb1dd 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -741,7 +741,7 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp,
return ret;
}
-struct file_operations fat_dir_operations = {
+const struct file_operations fat_dir_operations = {
.read = generic_read_dir,
.readdir = fat_readdir,
.ioctl = fat_dir_ioctl,
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 88aa1ae13f9..1ee25232e6a 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -112,7 +112,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
}
}
-struct file_operations fat_file_operations = {
+const struct file_operations fat_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 404bfc9f738..c1ce284f8a9 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -1435,9 +1435,6 @@ out_fail:
EXPORT_SYMBOL_GPL(fat_fill_super);
-int __init fat_cache_init(void);
-void fat_cache_destroy(void);
-
static int __init init_fat_fs(void)
{
int err;
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 2a2479196f9..d35cbc6bc11 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -453,8 +453,7 @@ static void send_sigio_to_task(struct task_struct *p,
/* Make sure we are called with one of the POLL_*
reasons, otherwise we could leak kernel stack into
userspace. */
- if ((reason & __SI_MASK) != __SI_POLL)
- BUG();
+ BUG_ON((reason & __SI_MASK) != __SI_POLL);
if (reason - POLL_IN >= NSIGPOLL)
si.si_band = ~0L;
else
diff --git a/fs/fifo.c b/fs/fifo.c
index d13fcd3ec80..49035b174b4 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -15,30 +15,35 @@
#include <linux/fs.h>
#include <linux/pipe_fs_i.h>
-static void wait_for_partner(struct inode* inode, unsigned int* cnt)
+static void wait_for_partner(struct inode* inode, unsigned int *cnt)
{
int cur = *cnt;
- while(cur == *cnt) {
- pipe_wait(inode);
- if(signal_pending(current))
+
+ while (cur == *cnt) {
+ pipe_wait(inode->i_pipe);
+ if (signal_pending(current))
break;
}
}
static void wake_up_partner(struct inode* inode)
{
- wake_up_interruptible(PIPE_WAIT(*inode));
+ wake_up_interruptible(&inode->i_pipe->wait);
}
static int fifo_open(struct inode *inode, struct file *filp)
{
+ struct pipe_inode_info *pipe;
int ret;
- mutex_lock(PIPE_MUTEX(*inode));
- if (!inode->i_pipe) {
+ mutex_lock(&inode->i_mutex);
+ pipe = inode->i_pipe;
+ if (!pipe) {
ret = -ENOMEM;
- if(!pipe_new(inode))
+ pipe = alloc_pipe_info(inode);
+ if (!pipe)
goto err_nocleanup;
+ inode->i_pipe = pipe;
}
filp->f_version = 0;
@@ -53,18 +58,18 @@ static int fifo_open(struct inode *inode, struct file *filp)
* opened, even when there is no process writing the FIFO.
*/
filp->f_op = &read_fifo_fops;
- PIPE_RCOUNTER(*inode)++;
- if (PIPE_READERS(*inode)++ == 0)
+ pipe->r_counter++;
+ if (pipe->readers++ == 0)
wake_up_partner(inode);
- if (!PIPE_WRITERS(*inode)) {
+ if (!pipe->writers) {
if ((filp->f_flags & O_NONBLOCK)) {
/* suppress POLLHUP until we have
* seen a writer */
- filp->f_version = PIPE_WCOUNTER(*inode);
+ filp->f_version = pipe->w_counter;
} else
{
- wait_for_partner(inode, &PIPE_WCOUNTER(*inode));
+ wait_for_partner(inode, &pipe->w_counter);
if(signal_pending(current))
goto err_rd;
}
@@ -78,16 +83,16 @@ static int fifo_open(struct inode *inode, struct file *filp)
* errno=ENXIO when there is no process reading the FIFO.
*/
ret = -ENXIO;
- if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode))
+ if ((filp->f_flags & O_NONBLOCK) && !pipe->readers)
goto err;
filp->f_op = &write_fifo_fops;
- PIPE_WCOUNTER(*inode)++;
- if (!PIPE_WRITERS(*inode)++)
+ pipe->w_counter++;
+ if (!pipe->writers++)
wake_up_partner(inode);
- if (!PIPE_READERS(*inode)) {
- wait_for_partner(inode, &PIPE_RCOUNTER(*inode));
+ if (!pipe->readers) {
+ wait_for_partner(inode, &pipe->r_counter);
if (signal_pending(current))
goto err_wr;
}
@@ -102,11 +107,11 @@ static int fifo_open(struct inode *inode, struct file *filp)
*/
filp->f_op = &rdwr_fifo_fops;
- PIPE_READERS(*inode)++;
- PIPE_WRITERS(*inode)++;
- PIPE_RCOUNTER(*inode)++;
- PIPE_WCOUNTER(*inode)++;
- if (PIPE_READERS(*inode) == 1 || PIPE_WRITERS(*inode) == 1)
+ pipe->readers++;
+ pipe->writers++;
+ pipe->r_counter++;
+ pipe->w_counter++;
+ if (pipe->readers == 1 || pipe->writers == 1)
wake_up_partner(inode);
break;
@@ -116,27 +121,27 @@ static int fifo_open(struct inode *inode, struct file *filp)
}
/* Ok! */
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_unlock(&inode->i_mutex);
return 0;
err_rd:
- if (!--PIPE_READERS(*inode))
- wake_up_interruptible(PIPE_WAIT(*inode));
+ if (!--pipe->readers)
+ wake_up_interruptible(&pipe->wait);
ret = -ERESTARTSYS;
goto err;
err_wr:
- if (!--PIPE_WRITERS(*inode))
- wake_up_interruptible(PIPE_WAIT(*inode));
+ if (!--pipe->writers)
+ wake_up_interruptible(&pipe->wait);
ret = -ERESTARTSYS;
goto err;
err:
- if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode))
+ if (!pipe->readers && !pipe->writers)
free_pipe_info(inode);
err_nocleanup:
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_unlock(&inode->i_mutex);
return ret;
}
@@ -145,6 +150,6 @@ err_nocleanup:
* is contain the open that then fills in the correct operations
* depending on the access mode of the file...
*/
-struct file_operations def_fifo_fops = {
+const struct file_operations def_fifo_fops = {
.open = fifo_open, /* will set read or write pipe_fops */
};
diff --git a/fs/file.c b/fs/file.c
index bbc74331473..55f4e702256 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -373,6 +373,6 @@ static void __devinit fdtable_defer_list_init(int cpu)
void __init files_defer_init(void)
{
int i;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
fdtable_defer_list_init(i);
}
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 927acf70c59..1cf1fe8466a 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -63,7 +63,7 @@ extern void vxfs_clear_inode(struct inode *);
/* vxfs_lookup.c */
extern struct inode_operations vxfs_dir_inode_ops;
-extern struct file_operations vxfs_dir_operations;
+extern const struct file_operations vxfs_dir_operations;
/* vxfs_olt.c */
extern int vxfs_read_olt(struct super_block *, u_long);
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 554eb455722..29cce456c7c 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -56,7 +56,7 @@ struct inode_operations vxfs_dir_inode_ops = {
.lookup = vxfs_lookup,
};
-struct file_operations vxfs_dir_operations = {
+const struct file_operations vxfs_dir_operations = {
.readdir = vxfs_readdir,
};
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
index 76a0708ae97..04950084790 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -42,24 +42,21 @@
static inline void
vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
{
- if (infp->vsi_fshino)
- BUG();
+ BUG_ON(infp->vsi_fshino);
infp->vsi_fshino = fshp->olt_fsino[0];
}
static inline void
vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
{
- if (infp->vsi_iext)
- BUG();
+ BUG_ON(infp->vsi_iext);
infp->vsi_iext = ilistp->olt_iext[0];
}
static inline u_long
vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize)
{
- if (sbp->s_blocksize % bsize)
- BUG();
+ BUG_ON(sbp->s_blocksize % bsize);
return (block * (sbp->s_blocksize / bsize));
}
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 0c9a2ee54c9..104a62dadb9 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
@@ -23,13 +23,11 @@ static kmem_cache_t *fuse_req_cachep;
static struct fuse_conn *fuse_get_conn(struct file *file)
{
- struct fuse_conn *fc;
- spin_lock(&fuse_lock);
- fc = file->private_data;
- if (fc && !fc->connected)
- fc = NULL;
- spin_unlock(&fuse_lock);
- return fc;
+ /*
+ * Lockless access is OK, because file->private data is set
+ * once during mount and is valid until the file is released.
+ */
+ return file->private_data;
}
static void fuse_request_init(struct fuse_req *req)
@@ -74,10 +72,8 @@ static void restore_sigs(sigset_t *oldset)
*/
void fuse_reset_request(struct fuse_req *req)
{
- int preallocated = req->preallocated;
BUG_ON(atomic_read(&req->count) != 1);
fuse_request_init(req);
- req->preallocated = preallocated;
}
static void __fuse_get_request(struct fuse_req *req)
@@ -92,80 +88,64 @@ static void __fuse_put_request(struct fuse_req *req)
atomic_dec(&req->count);
}
-static struct fuse_req *do_get_request(struct fuse_conn *fc)
+struct fuse_req *fuse_get_req(struct fuse_conn *fc)
{
struct fuse_req *req;
-
- spin_lock(&fuse_lock);
- BUG_ON(list_empty(&fc->unused_list));
- req = list_entry(fc->unused_list.next, struct fuse_req, list);
- list_del_init(&req->list);
- spin_unlock(&fuse_lock);
- fuse_request_init(req);
- req->preallocated = 1;
- req->in.h.uid = current->fsuid;
- req->in.h.gid = current->fsgid;
- req->in.h.pid = current->pid;
- return req;
-}
-
-/* This can return NULL, but only in case it's interrupted by a SIGKILL */
-struct fuse_req *fuse_get_request(struct fuse_conn *fc)
-{
- int intr;
sigset_t oldset;
+ int intr;
+ int err;
atomic_inc(&fc->num_waiting);
block_sigs(&oldset);
- intr = down_interruptible(&fc->outstanding_sem);
+ intr = wait_event_interruptible(fc->blocked_waitq, !fc->blocked);
restore_sigs(&oldset);
- if (intr) {
- atomic_dec(&fc->num_waiting);
- return NULL;
- }
- return do_get_request(fc);
-}
+ err = -EINTR;
+ if (intr)
+ goto out;
-/* Must be called with fuse_lock held */
-static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req)
-{
- if (req->preallocated) {
- atomic_dec(&fc->num_waiting);
- list_add(&req->list, &fc->unused_list);
- } else
- fuse_request_free(req);
+ req = fuse_request_alloc();
+ err = -ENOMEM;
+ if (!req)
+ goto out;
- /* If we are in debt decrease that first */
- if (fc->outstanding_debt)
- fc->outstanding_debt--;
- else
- up(&fc->outstanding_sem);
+ req->in.h.uid = current->fsuid;
+ req->in.h.gid = current->fsgid;
+ req->in.h.pid = current->pid;
+ req->waiting = 1;
+ return req;
+
+ out:
+ atomic_dec(&fc->num_waiting);
+ return ERR_PTR(err);
}
void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
{
if (atomic_dec_and_test(&req->count)) {
- spin_lock(&fuse_lock);
- fuse_putback_request(fc, req);
- spin_unlock(&fuse_lock);
+ if (req->waiting)
+ atomic_dec(&fc->num_waiting);
+ fuse_request_free(req);
}
}
-static void fuse_put_request_locked(struct fuse_conn *fc, struct fuse_req *req)
-{
- if (atomic_dec_and_test(&req->count))
- fuse_putback_request(fc, req);
-}
-
-void fuse_release_background(struct fuse_req *req)
+/*
+ * Called with sbput_sem held for read (request_end) or write
+ * (fuse_put_super). By the time fuse_put_super() is finished, all
+ * inodes belonging to background requests must be released, so the
+ * iputs have to be done within the locked region.
+ */
+void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req)
{
iput(req->inode);
iput(req->inode2);
- if (req->file)
- fput(req->file);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
list_del(&req->bg_entry);
- spin_unlock(&fuse_lock);
+ if (fc->num_background == FUSE_MAX_BACKGROUND) {
+ fc->blocked = 0;
+ wake_up_all(&fc->blocked_waitq);
+ }
+ fc->num_background--;
+ spin_unlock(&fc->lock);
}
/*
@@ -184,24 +164,29 @@ void fuse_release_background(struct fuse_req *req)
* interrupted and put in the background, it will return with an error
* and hence never be reset and reused.
*
- * Called with fuse_lock, unlocks it
+ * Called with fc->lock, unlocks it
*/
static void request_end(struct fuse_conn *fc, struct fuse_req *req)
{
list_del(&req->list);
req->state = FUSE_REQ_FINISHED;
if (!req->background) {
+ spin_unlock(&fc->lock);
wake_up(&req->waitq);
- fuse_put_request_locked(fc, req);
- spin_unlock(&fuse_lock);
+ fuse_put_request(fc, req);
} else {
void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
req->end = NULL;
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
down_read(&fc->sbput_sem);
if (fc->mounted)
- fuse_release_background(req);
+ fuse_release_background(fc, req);
up_read(&fc->sbput_sem);
+
+ /* fput must go outside sbput_sem, otherwise it can deadlock */
+ if (req->file)
+ fput(req->file);
+
if (end)
end(fc, req);
else
@@ -242,6 +227,9 @@ static void background_request(struct fuse_conn *fc, struct fuse_req *req)
{
req->background = 1;
list_add(&req->bg_entry, &fc->background);
+ fc->num_background++;
+ if (fc->num_background == FUSE_MAX_BACKGROUND)
+ fc->blocked = 1;
if (req->inode)
req->inode = igrab(req->inode);
if (req->inode2)
@@ -250,16 +238,16 @@ static void background_request(struct fuse_conn *fc, struct fuse_req *req)
get_file(req->file);
}
-/* Called with fuse_lock held. Releases, and then reacquires it. */
+/* Called with fc->lock held. Releases, and then reacquires it. */
static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
{
sigset_t oldset;
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
block_sigs(&oldset);
wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED);
restore_sigs(&oldset);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
if (req->state == FUSE_REQ_FINISHED && !req->interrupted)
return;
@@ -273,9 +261,9 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
locked state, there mustn't be any filesystem
operation (e.g. page fault), since that could lead
to deadlock */
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
wait_event(req->waitq, !req->locked);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
}
if (req->state == FUSE_REQ_PENDING) {
list_del(&req->list);
@@ -304,19 +292,14 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
req->in.h.unique = fc->reqctr;
req->in.h.len = sizeof(struct fuse_in_header) +
len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
- if (!req->preallocated) {
- /* If request is not preallocated (either FORGET or
- RELEASE), then still decrease outstanding_sem, so
- user can't open infinite number of files while not
- processing the RELEASE requests. However for
- efficiency do it without blocking, so if down()
- would block, just increase the debt instead */
- if (down_trylock(&fc->outstanding_sem))
- fc->outstanding_debt++;
- }
list_add_tail(&req->list, &fc->pending);
req->state = FUSE_REQ_PENDING;
+ if (!req->waiting) {
+ req->waiting = 1;
+ atomic_inc(&fc->num_waiting);
+ }
wake_up(&fc->waitq);
+ kill_fasync(&fc->fasync, SIGIO, POLL_IN);
}
/*
@@ -325,7 +308,7 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
void request_send(struct fuse_conn *fc, struct fuse_req *req)
{
req->isreply = 1;
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
if (!fc->connected)
req->out.h.error = -ENOTCONN;
else if (fc->conn_error)
@@ -338,15 +321,16 @@ void request_send(struct fuse_conn *fc, struct fuse_req *req)
request_wait_answer(fc, req);
}
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
}
static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
{
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
+ background_request(fc, req);
if (fc->connected) {
queue_request(fc, req);
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
} else {
req->out.h.error = -ENOTCONN;
request_end(fc, req);
@@ -362,9 +346,6 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req)
void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
{
req->isreply = 1;
- spin_lock(&fuse_lock);
- background_request(fc, req);
- spin_unlock(&fuse_lock);
request_send_nowait(fc, req);
}
@@ -373,16 +354,16 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
* anything that could cause a page-fault. If the request was already
* interrupted bail out.
*/
-static int lock_request(struct fuse_req *req)
+static int lock_request(struct fuse_conn *fc, struct fuse_req *req)
{
int err = 0;
if (req) {
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
if (req->interrupted)
err = -ENOENT;
else
req->locked = 1;
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
}
return err;
}
@@ -392,18 +373,19 @@ static int lock_request(struct fuse_req *req)
* requester thread is currently waiting for it to be unlocked, so
* wake it up.
*/
-static void unlock_request(struct fuse_req *req)
+static void unlock_request(struct fuse_conn *fc, struct fuse_req *req)
{
if (req) {
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
req->locked = 0;
if (req->interrupted)
wake_up(&req->waitq);
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
}
}
struct fuse_copy_state {
+ struct fuse_conn *fc;
int write;
struct fuse_req *req;
const struct iovec *iov;
@@ -416,11 +398,12 @@ struct fuse_copy_state {
unsigned len;
};
-static void fuse_copy_init(struct fuse_copy_state *cs, int write,
- struct fuse_req *req, const struct iovec *iov,
- unsigned long nr_segs)
+static void fuse_copy_init(struct fuse_copy_state *cs, struct fuse_conn *fc,
+ int write, struct fuse_req *req,
+ const struct iovec *iov, unsigned long nr_segs)
{
memset(cs, 0, sizeof(*cs));
+ cs->fc = fc;
cs->write = write;
cs->req = req;
cs->iov = iov;
@@ -450,7 +433,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
unsigned long offset;
int err;
- unlock_request(cs->req);
+ unlock_request(cs->fc, cs->req);
fuse_copy_finish(cs);
if (!cs->seglen) {
BUG_ON(!cs->nr_segs);
@@ -473,7 +456,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
cs->seglen -= cs->len;
cs->addr += cs->len;
- return lock_request(cs->req);
+ return lock_request(cs->fc, cs->req);
}
/* Do as much copy to/from userspace buffer as we can */
@@ -585,9 +568,9 @@ static void request_wait(struct fuse_conn *fc)
if (signal_pending(current))
break;
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
schedule();
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&fc->waitq, &wait);
@@ -606,18 +589,21 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
unsigned long nr_segs, loff_t *off)
{
int err;
- struct fuse_conn *fc;
struct fuse_req *req;
struct fuse_in *in;
struct fuse_copy_state cs;
unsigned reqsize;
+ struct fuse_conn *fc = fuse_get_conn(file);
+ if (!fc)
+ return -EPERM;
restart:
- spin_lock(&fuse_lock);
- fc = file->private_data;
- err = -EPERM;
- if (!fc)
+ spin_lock(&fc->lock);
+ err = -EAGAIN;
+ if ((file->f_flags & O_NONBLOCK) && fc->connected &&
+ list_empty(&fc->pending))
goto err_unlock;
+
request_wait(fc);
err = -ENODEV;
if (!fc->connected)
@@ -641,14 +627,14 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
request_end(fc, req);
goto restart;
}
- spin_unlock(&fuse_lock);
- fuse_copy_init(&cs, 1, req, iov, nr_segs);
+ spin_unlock(&fc->lock);
+ fuse_copy_init(&cs, fc, 1, req, iov, nr_segs);
err = fuse_copy_one(&cs, &in->h, sizeof(in->h));
if (!err)
err = fuse_copy_args(&cs, in->numargs, in->argpages,
(struct fuse_arg *) in->args, 0);
fuse_copy_finish(&cs);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
req->locked = 0;
if (!err && req->interrupted)
err = -ENOENT;
@@ -663,12 +649,12 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
else {
req->state = FUSE_REQ_SENT;
list_move_tail(&req->list, &fc->processing);
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
}
return reqsize;
err_unlock:
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
return err;
}
@@ -735,9 +721,9 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
struct fuse_copy_state cs;
struct fuse_conn *fc = fuse_get_conn(file);
if (!fc)
- return -ENODEV;
+ return -EPERM;
- fuse_copy_init(&cs, 0, NULL, iov, nr_segs);
+ fuse_copy_init(&cs, fc, 0, NULL, iov, nr_segs);
if (nbytes < sizeof(struct fuse_out_header))
return -EINVAL;
@@ -749,7 +735,7 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
oh.len != nbytes)
goto err_finish;
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
err = -ENOENT;
if (!fc->connected)
goto err_unlock;
@@ -760,9 +746,9 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
goto err_unlock;
if (req->interrupted) {
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
fuse_copy_finish(&cs);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
request_end(fc, req);
return -ENOENT;
}
@@ -770,12 +756,12 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
req->out.h = oh;
req->locked = 1;
cs.req = req;
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
err = copy_out_args(&cs, &req->out, nbytes);
fuse_copy_finish(&cs);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
req->locked = 0;
if (!err) {
if (req->interrupted)
@@ -787,7 +773,7 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
return err ? err : nbytes;
err_unlock:
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
err_finish:
fuse_copy_finish(&cs);
return err;
@@ -804,18 +790,19 @@ static ssize_t fuse_dev_write(struct file *file, const char __user *buf,
static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
{
- struct fuse_conn *fc = fuse_get_conn(file);
unsigned mask = POLLOUT | POLLWRNORM;
-
+ struct fuse_conn *fc = fuse_get_conn(file);
if (!fc)
- return -ENODEV;
+ return POLLERR;
poll_wait(file, &fc->waitq, wait);
- spin_lock(&fuse_lock);
- if (!list_empty(&fc->pending))
- mask |= POLLIN | POLLRDNORM;
- spin_unlock(&fuse_lock);
+ spin_lock(&fc->lock);
+ if (!fc->connected)
+ mask = POLLERR;
+ else if (!list_empty(&fc->pending))
+ mask |= POLLIN | POLLRDNORM;
+ spin_unlock(&fc->lock);
return mask;
}
@@ -823,7 +810,7 @@ static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
/*
* Abort all requests on the given list (pending or processing)
*
- * This function releases and reacquires fuse_lock
+ * This function releases and reacquires fc->lock
*/
static void end_requests(struct fuse_conn *fc, struct list_head *head)
{
@@ -832,7 +819,7 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head)
req = list_entry(head->next, struct fuse_req, list);
req->out.h.error = -ECONNABORTED;
request_end(fc, req);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
}
}
@@ -863,10 +850,10 @@ static void end_io_requests(struct fuse_conn *fc)
req->end = NULL;
/* The end function will consume this reference */
__fuse_get_request(req);
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
wait_event(req->waitq, !req->locked);
end(fc, req);
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
}
}
}
@@ -893,36 +880,45 @@ static void end_io_requests(struct fuse_conn *fc)
*/
void fuse_abort_conn(struct fuse_conn *fc)
{
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
if (fc->connected) {
fc->connected = 0;
end_io_requests(fc);
end_requests(fc, &fc->pending);
end_requests(fc, &fc->processing);
wake_up_all(&fc->waitq);
+ kill_fasync(&fc->fasync, SIGIO, POLL_IN);
}
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
}
static int fuse_dev_release(struct inode *inode, struct file *file)
{
- struct fuse_conn *fc;
-
- spin_lock(&fuse_lock);
- fc = file->private_data;
+ struct fuse_conn *fc = fuse_get_conn(file);
if (fc) {
+ spin_lock(&fc->lock);
fc->connected = 0;
end_requests(fc, &fc->pending);
end_requests(fc, &fc->processing);
- }
- spin_unlock(&fuse_lock);
- if (fc)
+ spin_unlock(&fc->lock);
+ fasync_helper(-1, file, 0, &fc->fasync);
kobject_put(&fc->kobj);
+ }
return 0;
}
-struct file_operations fuse_dev_operations = {
+static int fuse_dev_fasync(int fd, struct file *file, int on)
+{
+ struct fuse_conn *fc = fuse_get_conn(file);
+ if (!fc)
+ return -EPERM;
+
+ /* No locking - fasync_helper does its own locking */
+ return fasync_helper(fd, file, on, &fc->fasync);
+}
+
+const struct file_operations fuse_dev_operations = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = fuse_dev_read,
@@ -931,6 +927,7 @@ struct file_operations fuse_dev_operations = {
.writev = fuse_dev_writev,
.poll = fuse_dev_poll,
.release = fuse_dev_release,
+ .fasync = fuse_dev_fasync,
};
static struct miscdevice fuse_miscdevice = {
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index c72a8a97935..8d7546e832e 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -117,8 +117,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
return 0;
fc = get_fuse_conn(inode);
- req = fuse_get_request(fc);
- if (!req)
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
return 0;
fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
@@ -188,9 +188,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
if (entry->d_name.len > FUSE_NAME_MAX)
return ERR_PTR(-ENAMETOOLONG);
- req = fuse_get_request(fc);
- if (!req)
- return ERR_PTR(-EINTR);
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return ERR_PTR(PTR_ERR(req));
fuse_lookup_init(req, dir, entry, &outarg);
request_send(fc, req);
@@ -244,15 +244,14 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
struct file *file;
int flags = nd->intent.open.flags - 1;
- err = -ENOSYS;
if (fc->no_create)
- goto out;
+ return -ENOSYS;
- err = -EINTR;
- req = fuse_get_request(fc);
- if (!req)
- goto out;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+ err = -ENOMEM;
ff = fuse_file_alloc();
if (!ff)
goto out_put_request;
@@ -314,7 +313,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
fuse_file_free(ff);
out_put_request:
fuse_put_request(fc, req);
- out:
return err;
}
@@ -375,9 +373,9 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
{
struct fuse_mknod_in inarg;
struct fuse_conn *fc = get_fuse_conn(dir);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.mode = mode;
@@ -407,9 +405,9 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
{
struct fuse_mkdir_in inarg;
struct fuse_conn *fc = get_fuse_conn(dir);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.mode = mode;
@@ -427,9 +425,9 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
{
struct fuse_conn *fc = get_fuse_conn(dir);
unsigned len = strlen(link) + 1;
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
req->in.h.opcode = FUSE_SYMLINK;
req->in.numargs = 2;
@@ -444,9 +442,9 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
{
int err;
struct fuse_conn *fc = get_fuse_conn(dir);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
req->in.h.opcode = FUSE_UNLINK;
req->in.h.nodeid = get_node_id(dir);
@@ -476,9 +474,9 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
{
int err;
struct fuse_conn *fc = get_fuse_conn(dir);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
req->in.h.opcode = FUSE_RMDIR;
req->in.h.nodeid = get_node_id(dir);
@@ -504,9 +502,9 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
int err;
struct fuse_rename_in inarg;
struct fuse_conn *fc = get_fuse_conn(olddir);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.newdir = get_node_id(newdir);
@@ -553,9 +551,9 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
struct fuse_link_in inarg;
struct inode *inode = entry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.oldnodeid = get_node_id(inode);
@@ -583,9 +581,9 @@ int fuse_do_getattr(struct inode *inode)
int err;
struct fuse_attr_out arg;
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_req *req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ struct fuse_req *req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
req->in.h.opcode = FUSE_GETATTR;
req->in.h.nodeid = get_node_id(inode);
@@ -673,9 +671,9 @@ static int fuse_access(struct inode *inode, int mask)
if (fc->no_access)
return 0;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.mask = mask;
@@ -780,9 +778,9 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
if (is_bad_inode(inode))
return -EIO;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
page = alloc_page(GFP_KERNEL);
if (!page) {
@@ -809,11 +807,11 @@ static char *read_link(struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_req *req = fuse_get_request(fc);
+ struct fuse_req *req = fuse_get_req(fc);
char *link;
- if (!req)
- return ERR_PTR(-EINTR);
+ if (IS_ERR(req))
+ return ERR_PTR(PTR_ERR(req));
link = (char *) __get_free_page(GFP_KERNEL);
if (!link) {
@@ -933,9 +931,9 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
}
}
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
iattr_to_fattr(attr, &inarg);
@@ -995,9 +993,9 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
if (fc->no_setxattr)
return -EOPNOTSUPP;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
@@ -1035,9 +1033,9 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
if (fc->no_getxattr)
return -EOPNOTSUPP;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
@@ -1085,9 +1083,9 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
if (fc->no_listxattr)
return -EOPNOTSUPP;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
@@ -1131,9 +1129,9 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
if (fc->no_removexattr)
return -EOPNOTSUPP;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
req->in.h.opcode = FUSE_REMOVEXATTR;
req->in.h.nodeid = get_node_id(inode);
@@ -1170,7 +1168,7 @@ static struct inode_operations fuse_dir_inode_operations = {
.removexattr = fuse_removexattr,
};
-static struct file_operations fuse_dir_operations = {
+static const struct file_operations fuse_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = fuse_readdir,
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 6f05379b0a0..fc342cf7c2c 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
@@ -12,7 +12,7 @@
#include <linux/slab.h>
#include <linux/kernel.h>
-static struct file_operations fuse_direct_io_file_operations;
+static const struct file_operations fuse_direct_io_file_operations;
static int fuse_send_open(struct inode *inode, struct file *file, int isdir,
struct fuse_open_out *outargp)
@@ -22,9 +22,9 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir,
struct fuse_req *req;
int err;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
@@ -184,9 +184,9 @@ static int fuse_flush(struct file *file)
if (fc->no_flush)
return 0;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.fh = ff->fh;
@@ -223,9 +223,9 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
return 0;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg));
inarg.fh = ff->fh;
@@ -297,9 +297,9 @@ static int fuse_readpage(struct file *file, struct page *page)
if (is_bad_inode(inode))
goto out;
- err = -EINTR;
- req = fuse_get_request(fc);
- if (!req)
+ req = fuse_get_req(fc);
+ err = PTR_ERR(req);
+ if (IS_ERR(req))
goto out;
req->out.page_zeroing = 1;
@@ -368,10 +368,10 @@ static int fuse_readpages_fill(void *_data, struct page *page)
(req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
req->pages[req->num_pages - 1]->index + 1 != page->index)) {
fuse_send_readpages(req, data->file, inode);
- data->req = req = fuse_get_request(fc);
- if (!req) {
+ data->req = req = fuse_get_req(fc);
+ if (IS_ERR(req)) {
unlock_page(page);
- return -EINTR;
+ return PTR_ERR(req);
}
}
req->pages[req->num_pages] = page;
@@ -392,13 +392,17 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
data.file = file;
data.inode = inode;
- data.req = fuse_get_request(fc);
- if (!data.req)
- return -EINTR;
+ data.req = fuse_get_req(fc);
+ if (IS_ERR(data.req))
+ return PTR_ERR(data.req);
err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
- if (!err)
- fuse_send_readpages(data.req, file, inode);
+ if (!err) {
+ if (data.req->num_pages)
+ fuse_send_readpages(data.req, file, inode);
+ else
+ fuse_put_request(fc, data.req);
+ }
return err;
}
@@ -451,9 +455,9 @@ static int fuse_commit_write(struct file *file, struct page *page,
if (is_bad_inode(inode))
return -EIO;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
req->num_pages = 1;
req->pages[0] = page;
@@ -528,9 +532,9 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
if (is_bad_inode(inode))
return -EIO;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
while (count) {
size_t nres;
@@ -561,8 +565,12 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
buf += nres;
if (nres != nbytes)
break;
- if (count)
- fuse_reset_request(req);
+ if (count) {
+ fuse_put_request(fc, req);
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ break;
+ }
}
fuse_put_request(fc, req);
if (res > 0) {
@@ -611,7 +619,7 @@ static int fuse_set_page_dirty(struct page *page)
return 0;
}
-static struct file_operations fuse_file_operations = {
+static const struct file_operations fuse_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
@@ -623,7 +631,7 @@ static struct file_operations fuse_file_operations = {
.sendfile = generic_file_sendfile,
};
-static struct file_operations fuse_direct_io_file_operations = {
+static const struct file_operations fuse_direct_io_file_operations = {
.llseek = generic_file_llseek,
.read = fuse_direct_read,
.write = fuse_direct_write,
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 4a83adfec96..0474202cb5d 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
@@ -18,8 +18,8 @@
/** Max number of pages that can be used in a single read request */
#define FUSE_MAX_PAGES_PER_REQ 32
-/** If more requests are outstanding, then the operation will block */
-#define FUSE_MAX_OUTSTANDING 10
+/** Maximum number of outstanding background requests */
+#define FUSE_MAX_BACKGROUND 10
/** It could be as large as PATH_MAX, but would that have any uses? */
#define FUSE_NAME_MAX 1024
@@ -131,8 +131,8 @@ struct fuse_conn;
* A request to the client
*/
struct fuse_req {
- /** This can be on either unused_list, pending processing or
- io lists in fuse_conn */
+ /** This can be on either pending processing or io lists in
+ fuse_conn */
struct list_head list;
/** Entry on the background list */
@@ -144,15 +144,12 @@ struct fuse_req {
/*
* The following bitfields are either set once before the
* request is queued or setting/clearing them is protected by
- * fuse_lock
+ * fuse_conn->lock
*/
/** True if the request has reply */
unsigned isreply:1;
- /** The request is preallocated */
- unsigned preallocated:1;
-
/** The request was interrupted */
unsigned interrupted:1;
@@ -162,6 +159,9 @@ struct fuse_req {
/** Data is being copied to/from the request */
unsigned locked:1;
+ /** Request is counted as "waiting" */
+ unsigned waiting:1;
+
/** State of the request */
enum fuse_req_state state;
@@ -213,6 +213,9 @@ struct fuse_req {
* unmounted.
*/
struct fuse_conn {
+ /** Lock protecting accessess to members of this structure */
+ spinlock_t lock;
+
/** The user id for this mount */
uid_t user_id;
@@ -244,19 +247,20 @@ struct fuse_conn {
interrupted request) */
struct list_head background;
- /** Controls the maximum number of outstanding requests */
- struct semaphore outstanding_sem;
+ /** Number of requests currently in the background */
+ unsigned num_background;
- /** This counts the number of outstanding requests if
- outstanding_sem would go negative */
- unsigned outstanding_debt;
+ /** Flag indicating if connection is blocked. This will be
+ the case before the INIT reply is received, and if there
+ are too many outstading backgrounds requests */
+ int blocked;
+
+ /** waitq for blocked connection */
+ wait_queue_head_t blocked_waitq;
/** RW semaphore for exclusion with fuse_put_super() */
struct rw_semaphore sbput_sem;
- /** The list of unused requests */
- struct list_head unused_list;
-
/** The next unique request id */
u64 reqctr;
@@ -318,6 +322,9 @@ struct fuse_conn {
/** kobject */
struct kobject kobj;
+
+ /** O_ASYNC requests */
+ struct fasync_struct *fasync;
};
static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
@@ -346,22 +353,7 @@ static inline u64 get_node_id(struct inode *inode)
}
/** Device operations */
-extern struct file_operations fuse_dev_operations;
-
-/**
- * This is the single global spinlock which protects FUSE's structures
- *
- * The following data is protected by this lock:
- *
- * - the private_data field of the device file
- * - the s_fs_info field of the super block
- * - unused_list, pending, processing lists in fuse_conn
- * - background list in fuse_conn
- * - the unique request ID counter reqctr in fuse_conn
- * - the sb (super_block) field in fuse_conn
- * - the file (device file) field in fuse_conn
- */
-extern spinlock_t fuse_lock;
+extern const struct file_operations fuse_dev_operations;
/**
* Get a filled in inode
@@ -461,11 +453,11 @@ void fuse_reset_request(struct fuse_req *req);
/**
* Reserve a preallocated request
*/
-struct fuse_req *fuse_get_request(struct fuse_conn *fc);
+struct fuse_req *fuse_get_req(struct fuse_conn *fc);
/**
- * Decrement reference count of a request. If count goes to zero put
- * on unused list (preallocated) or free request (not preallocated).
+ * Decrement reference count of a request. If count goes to zero free
+ * the request.
*/
void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req);
@@ -487,7 +479,7 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
/**
* Release inodes and file associated with background request
*/
-void fuse_release_background(struct fuse_req *req);
+void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req);
/* Abort all requests */
void fuse_abort_conn(struct fuse_conn *fc);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 879e6fba948..7627022446b 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
@@ -22,7 +22,6 @@ MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
MODULE_DESCRIPTION("Filesystem in Userspace");
MODULE_LICENSE("GPL");
-spinlock_t fuse_lock;
static kmem_cache_t *fuse_inode_cachep;
static struct subsystem connections_subsys;
@@ -207,15 +206,17 @@ static void fuse_put_super(struct super_block *sb)
down_write(&fc->sbput_sem);
while (!list_empty(&fc->background))
- fuse_release_background(list_entry(fc->background.next,
+ fuse_release_background(fc,
+ list_entry(fc->background.next,
struct fuse_req, bg_entry));
- spin_lock(&fuse_lock);
+ spin_lock(&fc->lock);
fc->mounted = 0;
fc->connected = 0;
- spin_unlock(&fuse_lock);
+ spin_unlock(&fc->lock);
up_write(&fc->sbput_sem);
/* Flush all readers on this fs */
+ kill_fasync(&fc->fasync, SIGIO, POLL_IN);
wake_up_all(&fc->waitq);
kobject_del(&fc->kobj);
kobject_put(&fc->kobj);
@@ -242,9 +243,9 @@ static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
struct fuse_statfs_out outarg;
int err;
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
+ req = fuse_get_req(fc);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
memset(&outarg, 0, sizeof(outarg));
req->in.numargs = 0;
@@ -369,15 +370,7 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
static void fuse_conn_release(struct kobject *kobj)
{
- struct fuse_conn *fc = get_fuse_conn_kobj(kobj);
-
- while (!list_empty(&fc->unused_list)) {
- struct fuse_req *req;
- req = list_entry(fc->unused_list.next, struct fuse_req, list);
- list_del(&req->list);
- fuse_request_free(req);
- }
- kfree(fc);
+ kfree(get_fuse_conn_kobj(kobj));
}
static struct fuse_conn *new_conn(void)
@@ -386,64 +379,25 @@ static struct fuse_conn *new_conn(void)
fc = kzalloc(sizeof(*fc), GFP_KERNEL);
if (fc) {
- int i;
+ spin_lock_init(&fc->lock);
init_waitqueue_head(&fc->waitq);
+ init_waitqueue_head(&fc->blocked_waitq);
INIT_LIST_HEAD(&fc->pending);
INIT_LIST_HEAD(&fc->processing);
INIT_LIST_HEAD(&fc->io);
- INIT_LIST_HEAD(&fc->unused_list);
INIT_LIST_HEAD(&fc->background);
- sema_init(&fc->outstanding_sem, 1); /* One for INIT */
init_rwsem(&fc->sbput_sem);
kobj_set_kset_s(fc, connections_subsys);
kobject_init(&fc->kobj);
atomic_set(&fc->num_waiting, 0);
- for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
- struct fuse_req *req = fuse_request_alloc();
- if (!req) {
- kobject_put(&fc->kobj);
- return NULL;
- }
- list_add(&req->list, &fc->unused_list);
- }
fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
fc->bdi.unplug_io_fn = default_unplug_io_fn;
fc->reqctr = 0;
+ fc->blocked = 1;
}
return fc;
}
-static struct fuse_conn *get_conn(struct file *file, struct super_block *sb)
-{
- struct fuse_conn *fc;
- int err;
-
- err = -EINVAL;
- if (file->f_op != &fuse_dev_operations)
- goto out_err;
-
- err = -ENOMEM;
- fc = new_conn();
- if (!fc)
- goto out_err;
-
- spin_lock(&fuse_lock);
- err = -EINVAL;
- if (file->private_data)
- goto out_unlock;
-
- kobject_get(&fc->kobj);
- file->private_data = fc;
- spin_unlock(&fuse_lock);
- return fc;
-
- out_unlock:
- spin_unlock(&fuse_lock);
- kobject_put(&fc->kobj);
- out_err:
- return ERR_PTR(err);
-}
-
static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
{
struct fuse_attr attr;
@@ -467,7 +421,6 @@ static struct super_operations fuse_super_operations = {
static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
{
- int i;
struct fuse_init_out *arg = &req->misc.init_out;
if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION)
@@ -486,22 +439,13 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
fc->minor = arg->minor;
fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
}
-
- /* After INIT reply is received other requests can go
- out. So do (FUSE_MAX_OUTSTANDING - 1) number of
- up()s on outstanding_sem. The last up() is done in
- fuse_putback_request() */
- for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
- up(&fc->outstanding_sem);
-
fuse_put_request(fc, req);
+ fc->blocked = 0;
+ wake_up_all(&fc->blocked_waitq);
}
-static void fuse_send_init(struct fuse_conn *fc)
+static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
{
- /* This is called from fuse_read_super() so there's guaranteed
- to be exactly one request available */
- struct fuse_req *req = fuse_get_request(fc);
struct fuse_init_in *arg = &req->misc.init_in;
arg->major = FUSE_KERNEL_VERSION;
@@ -525,12 +469,9 @@ static void fuse_send_init(struct fuse_conn *fc)
static unsigned long long conn_id(void)
{
+ /* BKL is held for ->get_sb() */
static unsigned long long ctr = 1;
- unsigned long long val;
- spin_lock(&fuse_lock);
- val = ctr++;
- spin_unlock(&fuse_lock);
- return val;
+ return ctr++;
}
static int fuse_fill_super(struct super_block *sb, void *data, int silent)
@@ -540,6 +481,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
struct fuse_mount_data d;
struct file *file;
struct dentry *root_dentry;
+ struct fuse_req *init_req;
int err;
if (!parse_fuse_opt((char *) data, &d))
@@ -555,10 +497,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
if (!file)
return -EINVAL;
- fc = get_conn(file, sb);
- fput(file);
- if (IS_ERR(fc))
- return PTR_ERR(fc);
+ if (file->f_op != &fuse_dev_operations)
+ return -EINVAL;
+
+ fc = new_conn();
+ if (!fc)
+ return -ENOMEM;
fc->flags = d.flags;
fc->user_id = d.user_id;
@@ -579,27 +523,48 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
goto err;
}
+ init_req = fuse_request_alloc();
+ if (!init_req)
+ goto err_put_root;
+
err = kobject_set_name(&fc->kobj, "%llu", conn_id());
if (err)
- goto err_put_root;
+ goto err_free_req;
err = kobject_add(&fc->kobj);
if (err)
- goto err_put_root;
+ goto err_free_req;
+
+ /* Setting file->private_data can't race with other mount()
+ instances, since BKL is held for ->get_sb() */
+ err = -EINVAL;
+ if (file->private_data)
+ goto err_kobject_del;
sb->s_root = root_dentry;
- spin_lock(&fuse_lock);
fc->mounted = 1;
fc->connected = 1;
- spin_unlock(&fuse_lock);
+ kobject_get(&fc->kobj);
+ file->private_data = fc;
+ /*
+ * atomic_dec_and_test() in fput() provides the necessary
+ * memory barrier for file->private_data to be visible on all
+ * CPUs after this
+ */
+ fput(file);
- fuse_send_init(fc);
+ fuse_send_init(fc, init_req);
return 0;
+ err_kobject_del:
+ kobject_del(&fc->kobj);
+ err_free_req:
+ fuse_request_free(init_req);
err_put_root:
dput(root_dentry);
err:
+ fput(file);
kobject_put(&fc->kobj);
return err;
}
@@ -753,7 +718,6 @@ static int __init fuse_init(void)
printk("fuse init (API version %i.%i)\n",
FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
- spin_lock_init(&fuse_lock);
res = fuse_fs_init();
if (res)
goto err;
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index 534e5a7480e..7cd8cc03aea 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -313,7 +313,7 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
return res;
}
-struct file_operations hfs_dir_operations = {
+const struct file_operations hfs_dir_operations = {
.read = generic_read_dir,
.readdir = hfs_readdir,
.llseek = generic_file_llseek,
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 18ce47ab1b7..3ed8663a8db 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -169,7 +169,7 @@ extern int hfs_cat_move(u32, struct inode *, struct qstr *,
extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, struct qstr *);
/* dir.c */
-extern struct file_operations hfs_dir_operations;
+extern const struct file_operations hfs_dir_operations;
extern struct inode_operations hfs_dir_inode_operations;
/* extent.c */
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 2c564701724..2d4ced22201 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -17,7 +17,7 @@
#include "hfs_fs.h"
#include "btree.h"
-static struct file_operations hfs_file_operations;
+static const struct file_operations hfs_file_operations;
static struct inode_operations hfs_file_inode_operations;
/*================ Variable-like macros ================*/
@@ -601,7 +601,7 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
}
-static struct file_operations hfs_file_operations = {
+static const struct file_operations hfs_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 8f07e8fbd03..746abc9ecf7 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -466,8 +466,7 @@ void hfs_bnode_unhash(struct hfs_bnode *node)
for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
*p && *p != node; p = &(*p)->next_hash)
;
- if (!*p)
- BUG();
+ BUG_ON(!*p);
*p = node->next_hash;
node->tree->node_hash_cnt--;
}
@@ -622,8 +621,7 @@ void hfs_bnode_put(struct hfs_bnode *node)
dprint(DBG_BNODE_REFS, "put_node(%d:%d): %d\n",
node->tree->cnid, node->this, atomic_read(&node->refcnt));
- if (!atomic_read(&node->refcnt))
- BUG();
+ BUG_ON(!atomic_read(&node->refcnt));
if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
return;
for (i = 0; i < tree->pages_per_bnode; i++) {
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index a67edfa34e9..effa8991999 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -269,8 +269,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
u8 *data, byte, m;
dprint(DBG_BNODE_MOD, "btree_free_node: %u\n", node->this);
- if (!node->this)
- BUG();
+ BUG_ON(!node->this);
tree = node->tree;
nidx = node->this;
node = hfs_bnode_find(tree, 0);
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 01a6fe3a395..1f9ece0de32 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -483,7 +483,7 @@ struct inode_operations hfsplus_dir_inode_operations = {
.rename = hfsplus_rename,
};
-struct file_operations hfsplus_dir_operations = {
+const struct file_operations hfsplus_dir_operations = {
.read = generic_read_dir,
.readdir = hfsplus_readdir,
.ioctl = hfsplus_ioctl,
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 9fbe4d2aeec..acf66dba3e0 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -280,7 +280,7 @@ static struct inode_operations hfsplus_file_inode_operations = {
.listxattr = hfsplus_listxattr,
};
-static struct file_operations hfsplus_file_operations = {
+static const struct file_operations hfsplus_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index b3ad0bd0312..bf0f8e16e43 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -384,7 +384,7 @@ int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync);
}
-static struct file_operations hostfs_file_fops = {
+static const struct file_operations hostfs_file_fops = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.sendfile = generic_file_sendfile,
@@ -399,7 +399,7 @@ static struct file_operations hostfs_file_fops = {
.fsync = hostfs_fsync,
};
-static struct file_operations hostfs_dir_fops = {
+static const struct file_operations hostfs_dir_fops = {
.llseek = generic_file_llseek,
.readdir = hostfs_readdir,
.read = generic_read_dir,
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
index b97809deba6..23b7cee7212 100644
--- a/fs/hostfs/hostfs_user.c
+++ b/fs/hostfs/hostfs_user.c
@@ -360,7 +360,6 @@ int do_statfs(char *root, long *bsize_out, long long *blocks_out,
spare_out[2] = buf.f_spare[2];
spare_out[3] = buf.f_spare[3];
spare_out[4] = buf.f_spare[4];
- spare_out[5] = buf.f_spare[5];
return(0);
}
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c
index 5591f9623aa..ecc9180645a 100644
--- a/fs/hpfs/dir.c
+++ b/fs/hpfs/dir.c
@@ -310,7 +310,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
return ERR_PTR(-ENOENT);
}
-struct file_operations hpfs_dir_ops =
+const struct file_operations hpfs_dir_ops =
{
.llseek = hpfs_dir_lseek,
.read = generic_read_dir,
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 7c995ac4081..d3b9fffe45a 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -119,7 +119,7 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
return retval;
}
-struct file_operations hpfs_file_ops =
+const struct file_operations hpfs_file_ops =
{
.llseek = generic_file_llseek,
.read = generic_file_read,
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 4c6473ab3b3..29b7a3e5517 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -240,7 +240,7 @@ void hpfs_set_dentry_operations(struct dentry *);
/* dir.c */
struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *);
-extern struct file_operations hpfs_dir_ops;
+extern const struct file_operations hpfs_dir_ops;
/* dnode.c */
@@ -266,7 +266,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int);
/* file.c */
int hpfs_file_fsync(struct file *, struct dentry *, int);
-extern struct file_operations hpfs_file_ops;
+extern const struct file_operations hpfs_file_ops;
extern struct inode_operations hpfs_file_iops;
extern struct address_space_operations hpfs_aops;
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index a44dc589739..5e6363be246 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -216,10 +216,10 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
static struct inode_operations hppfs_file_iops = {
};
-static ssize_t read_proc(struct file *file, char *buf, ssize_t count,
+static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count,
loff_t *ppos, int is_user)
{
- ssize_t (*read)(struct file *, char *, size_t, loff_t *);
+ ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
ssize_t n;
read = file->f_dentry->d_inode->i_fop->read;
@@ -236,7 +236,7 @@ static ssize_t read_proc(struct file *file, char *buf, ssize_t count,
return n;
}
-static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count)
+static ssize_t hppfs_read_file(int fd, char __user *buf, ssize_t count)
{
ssize_t n;
int cur, err;
@@ -274,7 +274,7 @@ static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count)
return n;
}
-static ssize_t hppfs_read(struct file *file, char *buf, size_t count,
+static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
struct hppfs_private *hppfs = file->private_data;
@@ -313,12 +313,12 @@ static ssize_t hppfs_read(struct file *file, char *buf, size_t count,
return(count);
}
-static ssize_t hppfs_write(struct file *file, const char *buf, size_t len,
+static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len,
loff_t *ppos)
{
struct hppfs_private *data = file->private_data;
struct file *proc_file = data->proc_file;
- ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
+ ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
int err;
write = proc_file->f_dentry->d_inode->i_fop->write;
@@ -558,7 +558,7 @@ static loff_t hppfs_llseek(struct file *file, loff_t off, int where)
return(default_llseek(file, off, where));
}
-static struct file_operations hppfs_file_fops = {
+static const struct file_operations hppfs_file_fops = {
.owner = NULL,
.llseek = hppfs_llseek,
.read = hppfs_read,
@@ -609,7 +609,7 @@ static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync)
return(0);
}
-static struct file_operations hppfs_dir_fops = {
+static const struct file_operations hppfs_dir_fops = {
.owner = NULL,
.readdir = hppfs_readdir,
.open = hppfs_dir_open,
@@ -658,7 +658,7 @@ static struct super_operations hppfs_sbops = {
.statfs = hppfs_statfs,
};
-static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen)
+static int hppfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
{
struct file *proc_file;
struct dentry *proc_dentry;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 25fa8bba8cb..3a5b4e92345 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -35,7 +35,7 @@
static struct super_operations hugetlbfs_ops;
static struct address_space_operations hugetlbfs_aops;
-struct file_operations hugetlbfs_file_operations;
+const struct file_operations hugetlbfs_file_operations;
static struct inode_operations hugetlbfs_dir_inode_operations;
static struct inode_operations hugetlbfs_inode_operations;
@@ -566,7 +566,7 @@ static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
inode_init_once(&ei->vfs_inode);
}
-struct file_operations hugetlbfs_file_operations = {
+const struct file_operations hugetlbfs_file_operations = {
.mmap = hugetlbfs_file_mmap,
.fsync = simple_sync_file,
.get_unmapped_area = hugetlb_get_unmapped_area,
diff --git a/fs/inode.c b/fs/inode.c
index 1fddf2803af..3a2446a27d2 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -104,7 +104,7 @@ static struct inode *alloc_inode(struct super_block *sb)
{
static struct address_space_operations empty_aops;
static struct inode_operations empty_iops;
- static struct file_operations empty_fops;
+ static const struct file_operations empty_fops;
struct inode *inode;
if (sb->s_op->alloc_inode)
@@ -172,8 +172,7 @@ static struct inode *alloc_inode(struct super_block *sb)
void destroy_inode(struct inode *inode)
{
- if (inode_has_buffers(inode))
- BUG();
+ BUG_ON(inode_has_buffers(inode));
security_inode_free(inode);
if (inode->i_sb->s_op->destroy_inode)
inode->i_sb->s_op->destroy_inode(inode);
@@ -249,12 +248,9 @@ void clear_inode(struct inode *inode)
might_sleep();
invalidate_inode_buffers(inode);
- if (inode->i_data.nrpages)
- BUG();
- if (!(inode->i_state & I_FREEING))
- BUG();
- if (inode->i_state & I_CLEAR)
- BUG();
+ BUG_ON(inode->i_data.nrpages);
+ BUG_ON(!(inode->i_state & I_FREEING));
+ BUG_ON(inode->i_state & I_CLEAR);
wait_on_inode(inode);
DQUOT_DROP(inode);
if (inode->i_sb && inode->i_sb->s_op->clear_inode)
@@ -1054,8 +1050,7 @@ void generic_delete_inode(struct inode *inode)
hlist_del_init(&inode->i_hash);
spin_unlock(&inode_lock);
wake_up_inode(inode);
- if (inode->i_state != I_CLEAR)
- BUG();
+ BUG_ON(inode->i_state != I_CLEAR);
destroy_inode(inode);
}
diff --git a/fs/inotify.c b/fs/inotify.c
index f48a3dae071..732ec4bd577 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -538,7 +538,7 @@ void inotify_d_instantiate(struct dentry *entry, struct inode *inode)
WARN_ON(entry->d_flags & DCACHE_INOTIFY_PARENT_WATCHED);
spin_lock(&entry->d_lock);
parent = entry->d_parent;
- if (inotify_inode_watched(parent->d_inode))
+ if (parent->d_inode && inotify_inode_watched(parent->d_inode))
entry->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED;
spin_unlock(&entry->d_lock);
}
@@ -848,7 +848,11 @@ static int inotify_release(struct inode *ignored, struct file *file)
inode = watch->inode;
mutex_lock(&inode->inotify_mutex);
mutex_lock(&dev->mutex);
- remove_watch_no_event(watch, dev);
+
+ /* make sure we didn't race with another list removal */
+ if (likely(idr_find(&dev->idr, watch->wd)))
+ remove_watch_no_event(watch, dev);
+
mutex_unlock(&dev->mutex);
mutex_unlock(&inode->inotify_mutex);
put_inotify_watch(watch);
@@ -890,8 +894,7 @@ static int inotify_ignore(struct inotify_device *dev, s32 wd)
mutex_lock(&dev->mutex);
/* make sure that we did not race */
- watch = idr_find(&dev->idr, wd);
- if (likely(watch))
+ if (likely(idr_find(&dev->idr, wd) == watch))
remove_watch(watch, dev);
mutex_unlock(&dev->mutex);
@@ -920,7 +923,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd,
return ret;
}
-static struct file_operations inotify_fops = {
+static const struct file_operations inotify_fops = {
.poll = inotify_poll,
.read = inotify_read,
.release = inotify_release,
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 7901ac9f97a..5440ea292c6 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -16,7 +16,7 @@
static int isofs_readdir(struct file *, void *, filldir_t);
-struct file_operations isofs_dir_operations =
+const struct file_operations isofs_dir_operations =
{
.read = generic_read_dir,
.readdir = isofs_readdir,
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index 439a19b1bf3..b87ba066f5e 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -175,6 +175,6 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de,
}
extern struct inode_operations isofs_dir_inode_operations;
-extern struct file_operations isofs_dir_operations;
+extern const struct file_operations isofs_dir_operations;
extern struct address_space_operations isofs_symlink_aops;
extern struct export_operations isofs_export_ops;
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index 5a4519e834d..020cc097c53 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -55,9 +55,9 @@
static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
static struct super_operations jffs_ops;
-static struct file_operations jffs_file_operations;
+static const struct file_operations jffs_file_operations;
static struct inode_operations jffs_file_inode_operations;
-static struct file_operations jffs_dir_operations;
+static const struct file_operations jffs_dir_operations;
static struct inode_operations jffs_dir_inode_operations;
static struct address_space_operations jffs_address_operations;
@@ -1629,7 +1629,7 @@ static int jffs_fsync(struct file *f, struct dentry *d, int datasync)
}
-static struct file_operations jffs_file_operations =
+static const struct file_operations jffs_file_operations =
{
.open = generic_file_open,
.llseek = generic_file_llseek,
@@ -1649,7 +1649,7 @@ static struct inode_operations jffs_file_inode_operations =
};
-static struct file_operations jffs_dir_operations =
+static const struct file_operations jffs_dir_operations =
{
.readdir = jffs_readdir,
};
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 7b77a954112..ff2a872e80e 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -35,8 +35,7 @@ int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
pid_t pid;
int ret = 0;
- if (c->gc_task)
- BUG();
+ BUG_ON(c->gc_task);
init_completion(&c->gc_thread_start);
init_completion(&c->gc_thread_exit);
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index a7bf9cb2567..8bc7a5018e4 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -37,7 +37,7 @@ static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t);
static int jffs2_rename (struct inode *, struct dentry *,
struct inode *, struct dentry *);
-struct file_operations jffs2_dir_operations =
+const struct file_operations jffs2_dir_operations =
{
.read = generic_read_dir,
.readdir = jffs2_readdir,
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 935f273dc57..9f4171213e5 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -38,7 +38,7 @@ int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync)
return 0;
}
-struct file_operations jffs2_file_operations =
+const struct file_operations jffs2_file_operations =
{
.llseek = generic_file_llseek,
.open = generic_file_open,
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index d4d0c41490c..1d46677afd1 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -438,7 +438,8 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
if (c->mtd->point) {
err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
if (!err && retlen < tn->csize) {
- JFFS2_WARNING("MTD point returned len too short: %u instead of %u.\n", retlen, tn->csize);
+ JFFS2_WARNING("MTD point returned len too short: %zu "
+ "instead of %u.\n", retlen, tn->csize);
c->mtd->unpoint(c->mtd, buffer, ofs, len);
} else if (err)
JFFS2_WARNING("MTD point failed: error code %d.\n", err);
@@ -461,7 +462,8 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
}
if (retlen != len) {
- JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ofs, retlen, len);
+ JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n",
+ ofs, retlen, len);
err = -EIO;
goto free_out;
}
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 59e7a393200..d307cf54862 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -159,11 +159,11 @@ void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c);
void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c);
/* dir.c */
-extern struct file_operations jffs2_dir_operations;
+extern const struct file_operations jffs2_dir_operations;
extern struct inode_operations jffs2_dir_inode_operations;
/* file.c */
-extern struct file_operations jffs2_file_operations;
+extern const struct file_operations jffs2_file_operations;
extern struct inode_operations jffs2_file_inode_operations;
extern struct address_space_operations jffs2_file_address_operations;
int jffs2_fsync(struct file *, struct dentry *, int);
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index e1ac6e497e2..1c9745be5ad 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -100,7 +100,7 @@ struct inode_operations jfs_file_inode_operations = {
#endif
};
-struct file_operations jfs_file_operations = {
+const struct file_operations jfs_file_operations = {
.open = jfs_open,
.llseek = generic_file_llseek,
.write = generic_file_write,
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 095d471b9f9..c3007267446 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -35,9 +35,9 @@ extern void jfs_set_inode_flags(struct inode *);
extern struct address_space_operations jfs_aops;
extern struct inode_operations jfs_dir_inode_operations;
-extern struct file_operations jfs_dir_operations;
+extern const struct file_operations jfs_dir_operations;
extern struct inode_operations jfs_file_inode_operations;
-extern struct file_operations jfs_file_operations;
+extern const struct file_operations jfs_file_operations;
extern struct inode_operations jfs_symlink_inode_operations;
extern struct dentry_operations jfs_ci_dentry_operations;
#endif /* _H_JFS_INODE */
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index f28696f235c..2b220dd6b4e 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -542,7 +542,7 @@ add_failed:
static int metapage_releasepage(struct page *page, gfp_t gfp_mask)
{
struct metapage *mp;
- int busy = 0;
+ int ret = 1;
unsigned int offset;
for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
@@ -552,30 +552,20 @@ static int metapage_releasepage(struct page *page, gfp_t gfp_mask)
continue;
jfs_info("metapage_releasepage: mp = 0x%p", mp);
- if (mp->count || mp->nohomeok) {
+ if (mp->count || mp->nohomeok ||
+ test_bit(META_dirty, &mp->flag)) {
jfs_info("count = %ld, nohomeok = %d", mp->count,
mp->nohomeok);
- busy = 1;
+ ret = 0;
continue;
}
- wait_on_page_writeback(page);
- //WARN_ON(test_bit(META_dirty, &mp->flag));
- if (test_bit(META_dirty, &mp->flag)) {
- dump_mem("dirty mp in metapage_releasepage", mp,
- sizeof(struct metapage));
- dump_mem("page", page, sizeof(struct page));
- dump_stack();
- }
if (mp->lsn)
remove_from_logsync(mp);
remove_metapage(page, mp);
INCREMENT(mpStat.pagefree);
free_metapage(mp);
}
- if (busy)
- return -1;
-
- return 0;
+ return ret;
}
static void metapage_invalidatepage(struct page *page, unsigned long offset)
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 309cee575f7..09ea03f6227 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1519,7 +1519,7 @@ struct inode_operations jfs_dir_inode_operations = {
#endif
};
-struct file_operations jfs_dir_operations = {
+const struct file_operations jfs_dir_operations = {
.read = generic_read_dir,
.readdir = jfs_readdir,
.fsync = jfs_fsync,
diff --git a/fs/libfs.c b/fs/libfs.c
index 4fdeaceb892..7145ba7a48d 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -179,7 +179,7 @@ ssize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t
return -EISDIR;
}
-struct file_operations simple_dir_operations = {
+const struct file_operations simple_dir_operations = {
.open = dcache_dir_open,
.release = dcache_dir_close,
.llseek = dcache_dir_lseek,
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index d2b66bad7d5..3ef739120df 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -650,7 +650,7 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
svc_wake_up(block->b_daemon);
}
-void nlmsvc_grant_release(void *data)
+static void nlmsvc_grant_release(void *data)
{
struct nlm_rqst *call = data;
diff --git a/fs/locks.c b/fs/locks.c
index 4d9e71d43e7..ab61a8b5482 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -168,18 +168,9 @@ static void locks_release_private(struct file_lock *fl)
/* Free a lock which is not in use. */
static void locks_free_lock(struct file_lock *fl)
{
- if (fl == NULL) {
- BUG();
- return;
- }
- if (waitqueue_active(&fl->fl_wait))
- panic("Attempting to free lock with active wait queue");
-
- if (!list_empty(&fl->fl_block))
- panic("Attempting to free lock with active block list");
-
- if (!list_empty(&fl->fl_link))
- panic("Attempting to free lock on active lock list");
+ BUG_ON(waitqueue_active(&fl->fl_wait));
+ BUG_ON(!list_empty(&fl->fl_block));
+ BUG_ON(!list_empty(&fl->fl_link));
locks_release_private(fl);
kmem_cache_free(filelock_cache, fl);
@@ -455,15 +446,14 @@ static struct lock_manager_operations lease_manager_ops = {
*/
static int lease_init(struct file *filp, int type, struct file_lock *fl)
{
+ if (assign_type(fl, type) != 0)
+ return -EINVAL;
+
fl->fl_owner = current->files;
fl->fl_pid = current->tgid;
fl->fl_file = filp;
fl->fl_flags = FL_LEASE;
- if (assign_type(fl, type) != 0) {
- locks_free_lock(fl);
- return -EINVAL;
- }
fl->fl_start = 0;
fl->fl_end = OFFSET_MAX;
fl->fl_ops = NULL;
@@ -475,16 +465,19 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl)
static int lease_alloc(struct file *filp, int type, struct file_lock **flp)
{
struct file_lock *fl = locks_alloc_lock();
- int error;
+ int error = -ENOMEM;
if (fl == NULL)
- return -ENOMEM;
+ goto out;
error = lease_init(filp, type, fl);
- if (error)
- return error;
+ if (error) {
+ locks_free_lock(fl);
+ fl = NULL;
+ }
+out:
*flp = fl;
- return 0;
+ return error;
}
/* Check if two locks overlap each other.
@@ -735,8 +728,9 @@ EXPORT_SYMBOL(posix_locks_deadlock);
* at the head of the list, but that's secret knowledge known only to
* flock_lock_file and posix_lock_file.
*/
-static int flock_lock_file(struct file *filp, struct file_lock *new_fl)
+static int flock_lock_file(struct file *filp, struct file_lock *request)
{
+ struct file_lock *new_fl = NULL;
struct file_lock **before;
struct inode * inode = filp->f_dentry->d_inode;
int error = 0;
@@ -751,17 +745,20 @@ static int flock_lock_file(struct file *filp, struct file_lock *new_fl)
continue;
if (filp != fl->fl_file)
continue;
- if (new_fl->fl_type == fl->fl_type)
+ if (request->fl_type == fl->fl_type)
goto out;
found = 1;
locks_delete_lock(before);
break;
}
- unlock_kernel();
- if (new_fl->fl_type == F_UNLCK)
- return 0;
+ if (request->fl_type == F_UNLCK)
+ goto out;
+ error = -ENOMEM;
+ new_fl = locks_alloc_lock();
+ if (new_fl == NULL)
+ goto out;
/*
* If a higher-priority process was blocked on the old file lock,
* give it the opportunity to lock the file.
@@ -769,26 +766,28 @@ static int flock_lock_file(struct file *filp, struct file_lock *new_fl)
if (found)
cond_resched();
- lock_kernel();
for_each_lock(inode, before) {
struct file_lock *fl = *before;
if (IS_POSIX(fl))
break;
if (IS_LEASE(fl))
continue;
- if (!flock_locks_conflict(new_fl, fl))
+ if (!flock_locks_conflict(request, fl))
continue;
error = -EAGAIN;
- if (new_fl->fl_flags & FL_SLEEP) {
- locks_insert_block(fl, new_fl);
- }
+ if (request->fl_flags & FL_SLEEP)
+ locks_insert_block(fl, request);
goto out;
}
+ locks_copy_lock(new_fl, request);
locks_insert_lock(&inode->i_flock, new_fl);
+ new_fl = NULL;
error = 0;
out:
unlock_kernel();
+ if (new_fl)
+ locks_free_lock(new_fl);
return error;
}
@@ -1377,6 +1376,7 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
goto out;
if (my_before != NULL) {
+ *flp = *my_before;
error = lease->fl_lmops->fl_change(my_before, arg);
goto out;
}
@@ -1569,9 +1569,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
error = flock_lock_file_wait(filp, lock);
out_free:
- if (list_empty(&lock->fl_link)) {
- locks_free_lock(lock);
- }
+ locks_free_lock(lock);
out_putf:
fput(filp);
@@ -2237,7 +2235,12 @@ void steal_locks(fl_owner_t from)
lock_kernel();
j = 0;
- rcu_read_lock();
+
+ /*
+ * We are not taking a ref to the file structures, so
+ * we need to acquire ->file_lock.
+ */
+ spin_lock(&files->file_lock);
fdt = files_fdtable(files);
for (;;) {
unsigned long set;
@@ -2255,7 +2258,7 @@ void steal_locks(fl_owner_t from)
set >>= 1;
}
}
- rcu_read_unlock();
+ spin_unlock(&files->file_lock);
unlock_kernel();
}
EXPORT_SYMBOL(steal_locks);
diff --git a/fs/mbcache.c b/fs/mbcache.c
index 73e754fea2d..e4fde1ab22c 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -311,7 +311,7 @@ fail:
/*
* mb_cache_shrink()
*
- * Removes all cache entires of a device from the cache. All cache entries
+ * Removes all cache entries of a device from the cache. All cache entries
* currently in use cannot be freed, and thus remain in the cache. All others
* are freed.
*
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index 732502aabc0..69224d1fe04 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -14,7 +14,7 @@ typedef struct minix_dir_entry minix_dirent;
static int minix_readdir(struct file *, void *, filldir_t);
-struct file_operations minix_dir_operations = {
+const struct file_operations minix_dir_operations = {
.read = generic_read_dir,
.readdir = minix_readdir,
.fsync = minix_sync_file,
diff --git a/fs/minix/file.c b/fs/minix/file.c
index f1d77acb3f0..420b32882a1 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -15,7 +15,7 @@
*/
int minix_sync_file(struct file *, struct dentry *, int);
-struct file_operations minix_file_operations = {
+const struct file_operations minix_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/minix/minix.h b/fs/minix/minix.h
index e42a8bb8900..c55b77cdcc8 100644
--- a/fs/minix/minix.h
+++ b/fs/minix/minix.h
@@ -81,8 +81,8 @@ extern int minix_sync_file(struct file *, struct dentry *, int);
extern struct inode_operations minix_file_inode_operations;
extern struct inode_operations minix_dir_inode_operations;
-extern struct file_operations minix_file_operations;
-extern struct file_operations minix_dir_operations;
+extern const struct file_operations minix_file_operations;
+extern const struct file_operations minix_dir_operations;
extern struct dentry_operations minix_dentry_operations;
static inline struct minix_sb_info *minix_sb(struct super_block *sb)
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 626a367bcd8..5b76ccd19e3 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -12,14 +12,6 @@
#include <linux/msdos_fs.h>
#include <linux/smp_lock.h>
-/* MS-DOS "device special files" */
-static const unsigned char *reserved_names[] = {
- "CON ", "PRN ", "NUL ", "AUX ",
- "LPT1 ", "LPT2 ", "LPT3 ", "LPT4 ",
- "COM1 ", "COM2 ", "COM3 ", "COM4 ",
- NULL
-};
-
/* Characters that are undesirable in an MS-DOS file name */
static unsigned char bad_chars[] = "*?<>|\"";
static unsigned char bad_if_strict_pc[] = "+=,; ";
@@ -40,7 +32,6 @@ static int msdos_format_name(const unsigned char *name, int len,
*/
{
unsigned char *walk;
- const unsigned char **reserved;
unsigned char c;
int space;
@@ -127,11 +118,7 @@ static int msdos_format_name(const unsigned char *name, int len,
}
while (walk - res < MSDOS_NAME)
*walk++ = ' ';
- if (!opts->atari)
- /* GEMDOS is less stupid and has no reserved names */
- for (reserved = reserved_names; *reserved; reserved++)
- if (!strncmp(res, *reserved, 8))
- return -EINVAL;
+
return 0;
}
diff --git a/fs/namei.c b/fs/namei.c
index 98dc2e13436..d6e2ee25173 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -546,6 +546,22 @@ struct path {
struct dentry *dentry;
};
+static inline void dput_path(struct path *path, struct nameidata *nd)
+{
+ dput(path->dentry);
+ if (path->mnt != nd->mnt)
+ mntput(path->mnt);
+}
+
+static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
+{
+ dput(nd->dentry);
+ if (nd->mnt != path->mnt)
+ mntput(nd->mnt);
+ nd->mnt = path->mnt;
+ nd->dentry = path->dentry;
+}
+
static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
{
int error;
@@ -555,8 +571,11 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
touch_atime(path->mnt, dentry);
nd_set_link(nd, NULL);
- if (path->mnt == nd->mnt)
- mntget(path->mnt);
+ if (path->mnt != nd->mnt) {
+ path_to_nameidata(path, nd);
+ dget(dentry);
+ }
+ mntget(path->mnt);
cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
error = PTR_ERR(cookie);
if (!IS_ERR(cookie)) {
@@ -573,22 +592,6 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
return error;
}
-static inline void dput_path(struct path *path, struct nameidata *nd)
-{
- dput(path->dentry);
- if (path->mnt != nd->mnt)
- mntput(path->mnt);
-}
-
-static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
-{
- dput(nd->dentry);
- if (nd->mnt != path->mnt)
- mntput(nd->mnt);
- nd->mnt = path->mnt;
- nd->dentry = path->dentry;
-}
-
/*
* This limits recursive symlink follows to 8, while
* limiting consecutive symlinks to 40.
@@ -1077,8 +1080,8 @@ static int fastcall do_path_lookup(int dfd, const char *name,
nd->flags = flags;
nd->depth = 0;
- read_lock(&current->fs->lock);
if (*name=='/') {
+ read_lock(&current->fs->lock);
if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
nd->mnt = mntget(current->fs->altrootmnt);
nd->dentry = dget(current->fs->altroot);
@@ -1089,33 +1092,35 @@ static int fastcall do_path_lookup(int dfd, const char *name,
}
nd->mnt = mntget(current->fs->rootmnt);
nd->dentry = dget(current->fs->root);
+ read_unlock(&current->fs->lock);
} else if (dfd == AT_FDCWD) {
+ read_lock(&current->fs->lock);
nd->mnt = mntget(current->fs->pwdmnt);
nd->dentry = dget(current->fs->pwd);
+ read_unlock(&current->fs->lock);
} else {
struct dentry *dentry;
file = fget_light(dfd, &fput_needed);
retval = -EBADF;
if (!file)
- goto unlock_fail;
+ goto out_fail;
dentry = file->f_dentry;
retval = -ENOTDIR;
if (!S_ISDIR(dentry->d_inode->i_mode))
- goto fput_unlock_fail;
+ goto fput_fail;
retval = file_permission(file, MAY_EXEC);
if (retval)
- goto fput_unlock_fail;
+ goto fput_fail;
nd->mnt = mntget(file->f_vfsmnt);
nd->dentry = dget(dentry);
fput_light(file, fput_needed);
}
- read_unlock(&current->fs->lock);
current->total_link_count = 0;
retval = link_path_walk(name, nd);
out:
@@ -1124,13 +1129,12 @@ out:
nd->dentry->d_inode))
audit_inode(name, nd->dentry->d_inode, flags);
}
+out_fail:
return retval;
-fput_unlock_fail:
+fput_fail:
fput_light(file, fput_needed);
-unlock_fail:
- read_unlock(&current->fs->lock);
- return retval;
+ goto out_fail;
}
int fastcall path_lookup(const char *name, unsigned int flags,
@@ -1251,7 +1255,7 @@ out:
return dentry;
}
-struct dentry * lookup_hash(struct nameidata *nd)
+static struct dentry *lookup_hash(struct nameidata *nd)
{
return __lookup_hash(&nd->last, nd->dentry, nd);
}
@@ -2694,7 +2698,6 @@ EXPORT_SYMBOL(follow_up);
EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
EXPORT_SYMBOL(getname);
EXPORT_SYMBOL(lock_rename);
-EXPORT_SYMBOL(lookup_hash);
EXPORT_SYMBOL(lookup_one_len);
EXPORT_SYMBOL(page_follow_link_light);
EXPORT_SYMBOL(page_put_link);
diff --git a/fs/namespace.c b/fs/namespace.c
index e069a4c5e38..bf478addb85 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -459,9 +459,9 @@ int may_umount_tree(struct vfsmount *mnt)
spin_unlock(&vfsmount_lock);
if (actual_refs > minimum_refs)
- return -EBUSY;
+ return 0;
- return 0;
+ return 1;
}
EXPORT_SYMBOL(may_umount_tree);
@@ -481,10 +481,10 @@ EXPORT_SYMBOL(may_umount_tree);
*/
int may_umount(struct vfsmount *mnt)
{
- int ret = 0;
+ int ret = 1;
spin_lock(&vfsmount_lock);
if (propagate_mount_busy(mnt, 2))
- ret = -EBUSY;
+ ret = 0;
spin_unlock(&vfsmount_lock);
return ret;
}
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index cfd76f431dc..f0860c602d8 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -49,7 +49,7 @@ extern int ncp_symlink(struct inode *, struct dentry *, const char *);
#define ncp_symlink NULL
#endif
-struct file_operations ncp_dir_operations =
+const struct file_operations ncp_dir_operations =
{
.read = generic_read_dir,
.readdir = ncp_readdir,
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index ebdad8f6398..e6b7c67cf05 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -283,7 +283,7 @@ static int ncp_release(struct inode *inode, struct file *file) {
return 0;
}
-struct file_operations ncp_file_operations =
+const struct file_operations ncp_file_operations =
{
.llseek = remote_llseek,
.read = ncp_file_read,
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 06c48b385c9..cae74dd4c7f 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -54,7 +54,7 @@ static int nfs_rename(struct inode *, struct dentry *,
static int nfs_fsync_dir(struct file *, struct dentry *, int);
static loff_t nfs_llseek_dir(struct file *, loff_t, int);
-struct file_operations nfs_dir_operations = {
+const struct file_operations nfs_dir_operations = {
.llseek = nfs_llseek_dir,
.read = generic_read_dir,
.readdir = nfs_readdir,
@@ -128,15 +128,14 @@ struct inode_operations nfs4_dir_inode_operations = {
static int
nfs_opendir(struct inode *inode, struct file *filp)
{
- int res = 0;
+ int res;
dfprintk(VFS, "NFS: opendir(%s/%ld)\n",
inode->i_sb->s_id, inode->i_ino);
lock_kernel();
/* Call generic open code in order to cache credentials */
- if (!res)
- res = nfs_open(inode, filp);
+ res = nfs_open(inode, filp);
unlock_kernel();
return res;
}
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 0f583cb16dd..3c72b0c0728 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -112,10 +112,9 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
*/
ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs)
{
- struct dentry *dentry = iocb->ki_filp->f_dentry;
-
dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n",
- dentry->d_name.name, (long long) pos, nr_segs);
+ iocb->ki_filp->f_dentry->d_name.name,
+ (long long) pos, nr_segs);
return -EINVAL;
}
@@ -468,7 +467,6 @@ static const struct rpc_call_ops nfs_commit_direct_ops = {
static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
{
struct nfs_write_data *data = dreq->commit_data;
- struct rpc_task *task = &data->task;
data->inode = dreq->inode;
data->cred = dreq->ctx->cred;
@@ -489,7 +487,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
/* Note: task.tk_ops->rpc_release will free dreq->commit_data */
dreq->commit_data = NULL;
- dprintk("NFS: %5u initiated commit call\n", task->tk_pid);
+ dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
lock_kernel();
rpc_execute(&data->task);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index dee49a0cb99..fade02c15e6 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -49,7 +49,7 @@ static int nfs_check_flags(int flags);
static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
-struct file_operations nfs_file_operations = {
+const struct file_operations nfs_file_operations = {
.llseek = nfs_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
@@ -534,10 +534,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
*/
static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
{
- struct inode * inode = filp->f_mapping->host;
-
dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n",
- inode->i_sb->s_id, inode->i_ino,
+ filp->f_dentry->d_inode->i_sb->s_id,
+ filp->f_dentry->d_inode->i_ino,
fl->fl_type, fl->fl_flags);
/*
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 2f7656b911b..d0b991a9232 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -700,12 +700,9 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
/*
* Display superblock I/O counters
*/
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ for_each_possible_cpu(cpu) {
struct nfs_iostats *stats;
- if (!cpu_possible(cpu))
- continue;
-
preempt_disable();
stats = per_cpu_ptr(nfss->io_stats, cpu);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 47ece1dd3c6..d86c0db7b1e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1218,7 +1218,7 @@ out:
return status;
}
-static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
+static int nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
{
struct file *filp;
@@ -1227,8 +1227,10 @@ static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, st
struct nfs_open_context *ctx;
ctx = (struct nfs_open_context *)filp->private_data;
ctx->state = state;
- } else
- nfs4_close_state(state, nd->intent.open.flags);
+ return 0;
+ }
+ nfs4_close_state(state, nd->intent.open.flags);
+ return PTR_ERR(filp);
}
struct dentry *
@@ -1835,7 +1837,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
nfs_setattr_update_inode(state->inode, sattr);
}
if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN))
- nfs4_intent_set_file(nd, dentry, state);
+ status = nfs4_intent_set_file(nd, dentry, state);
else
nfs4_close_state(state, flags);
out:
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index cfe9ce88161..6e92b0fe532 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -14,46 +14,46 @@
int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
{
- struct svc_cred *cred = &rqstp->rq_cred;
+ struct svc_cred cred = rqstp->rq_cred;
int i;
int ret;
if (exp->ex_flags & NFSEXP_ALLSQUASH) {
- cred->cr_uid = exp->ex_anon_uid;
- cred->cr_gid = exp->ex_anon_gid;
- put_group_info(cred->cr_group_info);
- cred->cr_group_info = groups_alloc(0);
+ 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) {
struct group_info *gi;
- if (!cred->cr_uid)
- cred->cr_uid = exp->ex_anon_uid;
- if (!cred->cr_gid)
- cred->cr_gid = exp->ex_anon_gid;
- gi = groups_alloc(cred->cr_group_info->ngroups);
+ if (!cred.cr_uid)
+ cred.cr_uid = exp->ex_anon_uid;
+ if (!cred.cr_gid)
+ cred.cr_gid = exp->ex_anon_gid;
+ gi = groups_alloc(cred.cr_group_info->ngroups);
if (gi)
- for (i = 0; i < cred->cr_group_info->ngroups; i++) {
- if (!GROUP_AT(cred->cr_group_info, i))
+ for (i = 0; i < cred.cr_group_info->ngroups; i++) {
+ if (!GROUP_AT(cred.cr_group_info, i))
GROUP_AT(gi, i) = exp->ex_anon_gid;
else
- GROUP_AT(gi, i) = GROUP_AT(cred->cr_group_info, i);
+ GROUP_AT(gi, i) = GROUP_AT(cred.cr_group_info, i);
}
- put_group_info(cred->cr_group_info);
- cred->cr_group_info = gi;
- }
+ cred.cr_group_info = gi;
+ } else
+ get_group_info(cred.cr_group_info);
- if (cred->cr_uid != (uid_t) -1)
- current->fsuid = cred->cr_uid;
+ if (cred.cr_uid != (uid_t) -1)
+ current->fsuid = cred.cr_uid;
else
current->fsuid = exp->ex_anon_uid;
- if (cred->cr_gid != (gid_t) -1)
- current->fsgid = cred->cr_gid;
+ if (cred.cr_gid != (gid_t) -1)
+ current->fsgid = cred.cr_gid;
else
current->fsgid = exp->ex_anon_gid;
- if (!cred->cr_group_info)
+ if (!cred.cr_group_info)
return -ENOMEM;
- ret = set_current_groups(cred->cr_group_info);
- if ((cred->cr_uid)) {
+ ret = set_current_groups(cred.cr_group_info);
+ put_group_info(cred.cr_group_info);
+ if ((cred.cr_uid)) {
cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
} else {
cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 417ec02df44..3eec30000f3 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -57,27 +57,17 @@ static int exp_verify_string(char *cp, int max);
#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
static struct cache_head *expkey_table[EXPKEY_HASHMAX];
-static inline int svc_expkey_hash(struct svc_expkey *item)
+static void expkey_put(struct kref *ref)
{
- int hash = item->ek_fsidtype;
- char * cp = (char*)item->ek_fsid;
- int len = key_len(item->ek_fsidtype);
+ struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
- hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
- hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
- return hash & EXPKEY_HASHMASK;
-}
-
-void expkey_put(struct cache_head *item, struct cache_detail *cd)
-{
- if (cache_put(item, cd)) {
- struct svc_expkey *key = container_of(item, struct svc_expkey, h);
- if (test_bit(CACHE_VALID, &item->flags) &&
- !test_bit(CACHE_NEGATIVE, &item->flags))
- exp_put(key->ek_export);
- auth_domain_put(key->ek_client);
- kfree(key);
+ if (test_bit(CACHE_VALID, &key->h.flags) &&
+ !test_bit(CACHE_NEGATIVE, &key->h.flags)) {
+ dput(key->ek_dentry);
+ mntput(key->ek_mnt);
}
+ auth_domain_put(key->ek_client);
+ kfree(key);
}
static void expkey_request(struct cache_detail *cd,
@@ -95,7 +85,10 @@ static void expkey_request(struct cache_detail *cd,
(*bpp)[-1] = '\n';
}
-static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *, int);
+static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old);
+static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *);
+static struct cache_detail svc_expkey_cache;
+
static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
{
/* client fsidtype fsid [path] */
@@ -106,6 +99,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
int fsidtype;
char *ep;
struct svc_expkey key;
+ struct svc_expkey *ek;
if (mesg[mlen-1] != '\n')
return -EINVAL;
@@ -150,40 +144,38 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
key.ek_fsidtype = fsidtype;
memcpy(key.ek_fsid, buf, len);
+ ek = svc_expkey_lookup(&key);
+ err = -ENOMEM;
+ if (!ek)
+ goto out;
+
/* now we want a pathname, or empty meaning NEGATIVE */
+ err = -EINVAL;
if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0)
goto out;
dprintk("Path seems to be <%s>\n", buf);
err = 0;
if (len == 0) {
- struct svc_expkey *ek;
set_bit(CACHE_NEGATIVE, &key.h.flags);
- ek = svc_expkey_lookup(&key, 1);
+ ek = svc_expkey_update(&key, ek);
if (ek)
- expkey_put(&ek->h, &svc_expkey_cache);
+ cache_put(&ek->h, &svc_expkey_cache);
+ else err = -ENOMEM;
} else {
struct nameidata nd;
- struct svc_expkey *ek;
- struct svc_export *exp;
err = path_lookup(buf, 0, &nd);
if (err)
goto out;
dprintk("Found the path %s\n", buf);
- exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
-
- err = -ENOENT;
- if (!exp)
- goto out_nd;
- key.ek_export = exp;
- dprintk("And found export\n");
+ key.ek_mnt = nd.mnt;
+ key.ek_dentry = nd.dentry;
- ek = svc_expkey_lookup(&key, 1);
+ ek = svc_expkey_update(&key, ek);
if (ek)
- expkey_put(&ek->h, &svc_expkey_cache);
- exp_put(exp);
- err = 0;
- out_nd:
+ cache_put(&ek->h, &svc_expkey_cache);
+ else
+ err = -ENOMEM;
path_release(&nd);
}
cache_flush();
@@ -214,35 +206,31 @@ static int expkey_show(struct seq_file *m,
if (test_bit(CACHE_VALID, &h->flags) &&
!test_bit(CACHE_NEGATIVE, &h->flags)) {
seq_printf(m, " ");
- seq_path(m, ek->ek_export->ex_mnt, ek->ek_export->ex_dentry, "\\ \t\n");
+ seq_path(m, ek->ek_mnt, ek->ek_dentry, "\\ \t\n");
}
seq_printf(m, "\n");
return 0;
}
-
-struct cache_detail svc_expkey_cache = {
- .owner = THIS_MODULE,
- .hash_size = EXPKEY_HASHMAX,
- .hash_table = expkey_table,
- .name = "nfsd.fh",
- .cache_put = expkey_put,
- .cache_request = expkey_request,
- .cache_parse = expkey_parse,
- .cache_show = expkey_show,
-};
-static inline int svc_expkey_match (struct svc_expkey *a, struct svc_expkey *b)
+static inline int expkey_match (struct cache_head *a, struct cache_head *b)
{
- if (a->ek_fsidtype != b->ek_fsidtype ||
- a->ek_client != b->ek_client ||
- memcmp(a->ek_fsid, b->ek_fsid, key_len(a->ek_fsidtype)) != 0)
+ struct svc_expkey *orig = container_of(a, struct svc_expkey, h);
+ struct svc_expkey *new = container_of(b, struct svc_expkey, h);
+
+ if (orig->ek_fsidtype != new->ek_fsidtype ||
+ orig->ek_client != new->ek_client ||
+ memcmp(orig->ek_fsid, new->ek_fsid, key_len(orig->ek_fsidtype)) != 0)
return 0;
return 1;
}
-static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *item)
+static inline void expkey_init(struct cache_head *cnew,
+ struct cache_head *citem)
{
- cache_get(&item->ek_client->h);
+ struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
+ struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
+
+ kref_get(&item->ek_client->ref);
new->ek_client = item->ek_client;
new->ek_fsidtype = item->ek_fsidtype;
new->ek_fsid[0] = item->ek_fsid[0];
@@ -250,39 +238,94 @@ static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *it
new->ek_fsid[2] = item->ek_fsid[2];
}
-static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item)
+static inline void expkey_update(struct cache_head *cnew,
+ struct cache_head *citem)
{
- cache_get(&item->ek_export->h);
- new->ek_export = item->ek_export;
+ struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
+ struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
+
+ new->ek_mnt = mntget(item->ek_mnt);
+ new->ek_dentry = dget(item->ek_dentry);
}
-static DefineSimpleCacheLookup(svc_expkey,0) /* no inplace updates */
+static struct cache_head *expkey_alloc(void)
+{
+ struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL);
+ if (i)
+ return &i->h;
+ else
+ return NULL;
+}
-#define EXPORT_HASHBITS 8
-#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
-#define EXPORT_HASHMASK (EXPORT_HASHMAX -1)
+static struct cache_detail svc_expkey_cache = {
+ .owner = THIS_MODULE,
+ .hash_size = EXPKEY_HASHMAX,
+ .hash_table = expkey_table,
+ .name = "nfsd.fh",
+ .cache_put = expkey_put,
+ .cache_request = expkey_request,
+ .cache_parse = expkey_parse,
+ .cache_show = expkey_show,
+ .match = expkey_match,
+ .init = expkey_init,
+ .update = expkey_update,
+ .alloc = expkey_alloc,
+};
-static struct cache_head *export_table[EXPORT_HASHMAX];
+static struct svc_expkey *
+svc_expkey_lookup(struct svc_expkey *item)
+{
+ struct cache_head *ch;
+ int hash = item->ek_fsidtype;
+ char * cp = (char*)item->ek_fsid;
+ int len = key_len(item->ek_fsidtype);
-static inline int svc_export_hash(struct svc_export *item)
+ hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
+ hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
+ hash &= EXPKEY_HASHMASK;
+
+ ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h,
+ hash);
+ if (ch)
+ return container_of(ch, struct svc_expkey, h);
+ else
+ return NULL;
+}
+
+static struct svc_expkey *
+svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old)
{
- int rv;
+ struct cache_head *ch;
+ int hash = new->ek_fsidtype;
+ char * cp = (char*)new->ek_fsid;
+ int len = key_len(new->ek_fsidtype);
- rv = hash_ptr(item->ex_client, EXPORT_HASHBITS);
- rv ^= hash_ptr(item->ex_dentry, EXPORT_HASHBITS);
- rv ^= hash_ptr(item->ex_mnt, EXPORT_HASHBITS);
- return rv;
+ hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
+ hash ^= hash_ptr(new->ek_client, EXPKEY_HASHBITS);
+ hash &= EXPKEY_HASHMASK;
+
+ ch = sunrpc_cache_update(&svc_expkey_cache, &new->h,
+ &old->h, hash);
+ if (ch)
+ return container_of(ch, struct svc_expkey, h);
+ else
+ return NULL;
}
-void svc_export_put(struct cache_head *item, struct cache_detail *cd)
+
+#define EXPORT_HASHBITS 8
+#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
+#define EXPORT_HASHMASK (EXPORT_HASHMAX -1)
+
+static struct cache_head *export_table[EXPORT_HASHMAX];
+
+static void svc_export_put(struct kref *ref)
{
- if (cache_put(item, cd)) {
- struct svc_export *exp = container_of(item, struct svc_export, h);
- dput(exp->ex_dentry);
- mntput(exp->ex_mnt);
- auth_domain_put(exp->ex_client);
- kfree(exp);
- }
+ struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
+ dput(exp->ex_dentry);
+ mntput(exp->ex_mnt);
+ auth_domain_put(exp->ex_client);
+ kfree(exp);
}
static void svc_export_request(struct cache_detail *cd,
@@ -304,7 +347,9 @@ static void svc_export_request(struct cache_detail *cd,
(*bpp)[-1] = '\n';
}
-static struct svc_export *svc_export_lookup(struct svc_export *, int);
+static struct svc_export *svc_export_update(struct svc_export *new,
+ struct svc_export *old);
+static struct svc_export *svc_export_lookup(struct svc_export *);
static int check_export(struct inode *inode, int flags)
{
@@ -377,7 +422,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
goto out;
err = path_lookup(buf, 0, &nd);
- if (err) goto out;
+ if (err) goto out_no_path;
exp.h.flags = 0;
exp.ex_client = dom;
@@ -417,14 +462,20 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
if (err) goto out;
}
- expp = svc_export_lookup(&exp, 1);
+ expp = svc_export_lookup(&exp);
if (expp)
- exp_put(expp);
- err = 0;
+ expp = svc_export_update(&exp, expp);
+ else
+ err = -ENOMEM;
cache_flush();
+ if (expp == NULL)
+ err = -ENOMEM;
+ else
+ exp_put(expp);
out:
if (nd.dentry)
path_release(&nd);
+ out_no_path:
if (dom)
auth_domain_put(dom);
kfree(buf);
@@ -455,6 +506,46 @@ static int svc_export_show(struct seq_file *m,
seq_puts(m, ")\n");
return 0;
}
+static int svc_export_match(struct cache_head *a, struct cache_head *b)
+{
+ struct svc_export *orig = container_of(a, struct svc_export, h);
+ struct svc_export *new = container_of(b, struct svc_export, h);
+ return orig->ex_client == new->ex_client &&
+ orig->ex_dentry == new->ex_dentry &&
+ orig->ex_mnt == new->ex_mnt;
+}
+
+static void svc_export_init(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);
+
+ kref_get(&item->ex_client->ref);
+ new->ex_client = item->ex_client;
+ new->ex_dentry = dget(item->ex_dentry);
+ new->ex_mnt = mntget(item->ex_mnt);
+}
+
+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);
+
+ new->ex_flags = item->ex_flags;
+ new->ex_anon_uid = item->ex_anon_uid;
+ new->ex_anon_gid = item->ex_anon_gid;
+ new->ex_fsid = item->ex_fsid;
+}
+
+static struct cache_head *svc_export_alloc(void)
+{
+ struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL);
+ if (i)
+ return &i->h;
+ else
+ return NULL;
+}
+
struct cache_detail svc_export_cache = {
.owner = THIS_MODULE,
.hash_size = EXPORT_HASHMAX,
@@ -464,34 +555,49 @@ struct cache_detail svc_export_cache = {
.cache_request = svc_export_request,
.cache_parse = svc_export_parse,
.cache_show = svc_export_show,
+ .match = svc_export_match,
+ .init = svc_export_init,
+ .update = export_update,
+ .alloc = svc_export_alloc,
};
-static inline int svc_export_match(struct svc_export *a, struct svc_export *b)
-{
- return a->ex_client == b->ex_client &&
- a->ex_dentry == b->ex_dentry &&
- a->ex_mnt == b->ex_mnt;
-}
-static inline void svc_export_init(struct svc_export *new, struct svc_export *item)
+static struct svc_export *
+svc_export_lookup(struct svc_export *exp)
{
- cache_get(&item->ex_client->h);
- new->ex_client = item->ex_client;
- new->ex_dentry = dget(item->ex_dentry);
- new->ex_mnt = mntget(item->ex_mnt);
+ struct cache_head *ch;
+ int hash;
+ hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS);
+ hash ^= hash_ptr(exp->ex_dentry, EXPORT_HASHBITS);
+ hash ^= hash_ptr(exp->ex_mnt, EXPORT_HASHBITS);
+
+ ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h,
+ hash);
+ if (ch)
+ return container_of(ch, struct svc_export, h);
+ else
+ return NULL;
}
-static inline void svc_export_update(struct svc_export *new, struct svc_export *item)
+static struct svc_export *
+svc_export_update(struct svc_export *new, struct svc_export *old)
{
- new->ex_flags = item->ex_flags;
- new->ex_anon_uid = item->ex_anon_uid;
- new->ex_anon_gid = item->ex_anon_gid;
- new->ex_fsid = item->ex_fsid;
+ struct cache_head *ch;
+ int hash;
+ hash = hash_ptr(old->ex_client, EXPORT_HASHBITS);
+ hash ^= hash_ptr(old->ex_dentry, EXPORT_HASHBITS);
+ hash ^= hash_ptr(old->ex_mnt, EXPORT_HASHBITS);
+
+ ch = sunrpc_cache_update(&svc_export_cache, &new->h,
+ &old->h,
+ hash);
+ if (ch)
+ return container_of(ch, struct svc_export, h);
+ else
+ return NULL;
}
-static DefineSimpleCacheLookup(svc_export,1) /* allow inplace updates */
-
-struct svc_expkey *
+static struct svc_expkey *
exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
{
struct svc_expkey key, *ek;
@@ -504,7 +610,7 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
key.ek_fsidtype = fsid_type;
memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
- ek = svc_expkey_lookup(&key, 0);
+ ek = svc_expkey_lookup(&key);
if (ek != NULL)
if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp)))
ek = ERR_PTR(err);
@@ -519,13 +625,16 @@ static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
key.ek_client = clp;
key.ek_fsidtype = fsid_type;
memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
- key.ek_export = exp;
+ key.ek_mnt = exp->ex_mnt;
+ key.ek_dentry = exp->ex_dentry;
key.h.expiry_time = NEVER;
key.h.flags = 0;
- ek = svc_expkey_lookup(&key, 1);
+ ek = svc_expkey_lookup(&key);
+ if (ek)
+ ek = svc_expkey_update(&key,ek);
if (ek) {
- expkey_put(&ek->h, &svc_expkey_cache);
+ cache_put(&ek->h, &svc_expkey_cache);
return 0;
}
return -ENOMEM;
@@ -573,7 +682,7 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
key.ex_mnt = mnt;
key.ex_dentry = dentry;
- exp = svc_export_lookup(&key, 0);
+ exp = svc_export_lookup(&key);
if (exp != NULL)
switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
case 0: break;
@@ -654,7 +763,7 @@ static void exp_fsid_unhash(struct svc_export *exp)
ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
if (ek && !IS_ERR(ek)) {
ek->h.expiry_time = get_seconds()-1;
- expkey_put(&ek->h, &svc_expkey_cache);
+ cache_put(&ek->h, &svc_expkey_cache);
}
svc_expkey_cache.nextcheck = get_seconds();
}
@@ -692,7 +801,7 @@ static void exp_unhash(struct svc_export *exp)
ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
if (ek && !IS_ERR(ek)) {
ek->h.expiry_time = get_seconds()-1;
- expkey_put(&ek->h, &svc_expkey_cache);
+ cache_put(&ek->h, &svc_expkey_cache);
}
svc_expkey_cache.nextcheck = get_seconds();
}
@@ -741,8 +850,8 @@ exp_export(struct nfsctl_export *nxp)
if ((nxp->ex_flags & NFSEXP_FSID) &&
(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
!IS_ERR(fsid_key) &&
- fsid_key->ek_export &&
- fsid_key->ek_export != exp)
+ fsid_key->ek_mnt &&
+ (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) )
goto finish;
if (exp) {
@@ -775,13 +884,13 @@ exp_export(struct nfsctl_export *nxp)
new.ex_anon_gid = nxp->ex_anon_gid;
new.ex_fsid = nxp->ex_dev;
- exp = svc_export_lookup(&new, 1);
+ exp = svc_export_lookup(&new);
+ if (exp)
+ exp = svc_export_update(&new, exp);
- if (exp == NULL)
+ if (!exp)
goto finish;
- err = 0;
-
if (exp_hash(clp, exp) ||
exp_fsid_hash(clp, exp)) {
/* failed to create at least one index */
@@ -794,7 +903,7 @@ finish:
if (exp)
exp_put(exp);
if (fsid_key && !IS_ERR(fsid_key))
- expkey_put(&fsid_key->h, &svc_expkey_cache);
+ cache_put(&fsid_key->h, &svc_expkey_cache);
if (clp)
auth_domain_put(clp);
path_release(&nd);
@@ -912,6 +1021,24 @@ out:
return err;
}
+struct svc_export *
+exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
+ struct cache_req *reqp)
+{
+ struct svc_export *exp;
+ struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
+ if (!ek || 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))
+ return ERR_PTR(PTR_ERR(exp));
+ return exp;
+}
+
+
/*
* Called when we need the filehandle for the root of the pseudofs,
* for a given NFSv4 client. The root is defined to be the
@@ -922,6 +1049,7 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
struct cache_req *creq)
{
struct svc_expkey *fsid_key;
+ struct svc_export *exp;
int rv;
u32 fsidv[2];
@@ -933,9 +1061,17 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
if (!fsid_key || IS_ERR(fsid_key))
return nfserr_perm;
- rv = fh_compose(fhp, fsid_key->ek_export,
- fsid_key->ek_export->ex_dentry, NULL);
- expkey_put(&fsid_key->h, &svc_expkey_cache);
+ exp = exp_get_by_name(clp, fsid_key->ek_mnt, fsid_key->ek_dentry, creq);
+ if (exp == NULL)
+ rv = nfserr_perm;
+ else if (IS_ERR(exp))
+ rv = nfserrno(PTR_ERR(exp));
+ else {
+ rv = fh_compose(fhp, exp,
+ fsid_key->ek_dentry, NULL);
+ exp_put(exp);
+ }
+ cache_put(&fsid_key->h, &svc_expkey_cache);
return rv;
}
@@ -1054,7 +1190,7 @@ static int e_show(struct seq_file *m, void *p)
cache_get(&exp->h);
if (cache_check(&svc_export_cache, &exp->h, NULL))
return 0;
- if (cache_put(&exp->h, &svc_export_cache)) BUG();
+ cache_put(&exp->h, &svc_export_cache);
return svc_export_show(m, &svc_export_cache, cp);
}
@@ -1129,7 +1265,6 @@ exp_delclient(struct nfsctl_client *ncp)
*/
if (dom) {
err = auth_unix_forget_old(dom);
- dom->h.expiry_time = get_seconds();
auth_domain_put(dom);
}
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 6d2dfed1de0..f61142afea4 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -682,7 +682,7 @@ static struct svc_procedure nfsd_procedures3[22] = {
PROC(lookup, dirop, dirop, fhandle2, RC_NOCACHE, ST+FH+pAT+pAT),
PROC(access, access, access, fhandle, RC_NOCACHE, ST+pAT+1),
PROC(readlink, readlink, readlink, fhandle, RC_NOCACHE, ST+pAT+1+NFS3_MAXPATHLEN/4),
- PROC(read, read, read, fhandle, RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE),
+ PROC(read, read, read, fhandle, RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE/4),
PROC(write, write, write, fhandle, RC_REPLBUFF, ST+WC+4),
PROC(create, create, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
PROC(mkdir, mkdir, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 7391f4aabed..edb107e61b9 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -710,9 +710,9 @@ calculate_posix_ace_count(struct nfs4_acl *n4acl)
/* Also, the remaining entries are for named users and
* groups, and come in threes (mask, allow, deny): */
if (n4acl->naces < 7)
- return -1;
+ return -EINVAL;
if ((n4acl->naces - 7) % 3)
- return -1;
+ return -EINVAL;
return 4 + (n4acl->naces - 7)/3;
}
}
@@ -790,7 +790,7 @@ nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
continue;
error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
- ace->access_mask, ace->whotype, ace->who) == -1;
+ ace->access_mask, ace->whotype, ace->who);
if (error < 0)
goto out;
@@ -866,7 +866,7 @@ nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
struct nfs4_ace *ace;
if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
- return -1;
+ return -ENOMEM;
ace->type = type;
ace->flag = flag;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index c872bd07fc1..dbaf3f93f32 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -441,8 +441,9 @@ nfsd4_probe_callback(struct nfs4_client *clp)
goto out_clnt;
}
- /* the task holds a reference to the nfs4_client struct */
cb->cb_client = clnt;
+
+ /* the task holds a reference to the nfs4_client struct */
atomic_inc(&clp->cl_count);
msg.rpc_cred = nfsd4_lookupcred(clp,0);
@@ -460,13 +461,12 @@ nfsd4_probe_callback(struct nfs4_client *clp)
out_rpciod:
atomic_dec(&clp->cl_count);
rpciod_down();
+ cb->cb_client = NULL;
out_clnt:
rpc_shutdown_client(clnt);
- goto out_err;
out_err:
dprintk("NFSD: warning: no callback path to client %.*s\n",
(int)clp->cl_name.len, clp->cl_name.data);
- cb->cb_client = NULL;
}
static void
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 13369650cdf..4b6aa60dfce 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -76,21 +76,18 @@ struct ent {
char authname[IDMAP_NAMESZ];
};
-#define DefineSimpleCacheLookupMap(STRUCT, FUNC) \
- DefineCacheLookup(struct STRUCT, h, FUNC##_lookup, \
- (struct STRUCT *item, int set), /*no setup */, \
- & FUNC##_cache, FUNC##_hash(item), FUNC##_match(item, tmp), \
- STRUCT##_init(new, item), STRUCT##_update(tmp, item), 0)
-
/* Common entry handling */
#define ENT_HASHBITS 8
#define ENT_HASHMAX (1 << ENT_HASHBITS)
#define ENT_HASHMASK (ENT_HASHMAX - 1)
-static inline void
-ent_init(struct ent *new, struct ent *itm)
+static void
+ent_init(struct cache_head *cnew, struct cache_head *citm)
{
+ struct ent *new = container_of(cnew, struct ent, h);
+ struct ent *itm = container_of(citm, struct ent, h);
+
new->id = itm->id;
new->type = itm->type;
@@ -98,19 +95,21 @@ ent_init(struct ent *new, struct ent *itm)
strlcpy(new->authname, itm->authname, sizeof(new->name));
}
-static inline void
-ent_update(struct ent *new, struct ent *itm)
+static void
+ent_put(struct kref *ref)
{
- ent_init(new, itm);
+ struct ent *map = container_of(ref, struct ent, h.ref);
+ kfree(map);
}
-static void
-ent_put(struct cache_head *ch, struct cache_detail *cd)
+static struct cache_head *
+ent_alloc(void)
{
- if (cache_put(ch, cd)) {
- struct ent *map = container_of(ch, struct ent, h);
- kfree(map);
- }
+ struct ent *e = kmalloc(sizeof(*e), GFP_KERNEL);
+ if (e)
+ return &e->h;
+ else
+ return NULL;
}
/*
@@ -149,9 +148,12 @@ idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
(*bpp)[-1] = '\n';
}
-static inline int
-idtoname_match(struct ent *a, struct ent *b)
+static int
+idtoname_match(struct cache_head *ca, struct cache_head *cb)
{
+ struct ent *a = container_of(ca, struct ent, h);
+ struct ent *b = container_of(cb, struct ent, h);
+
return (a->id == b->id && a->type == b->type &&
strcmp(a->authname, b->authname) == 0);
}
@@ -184,7 +186,8 @@ warn_no_idmapd(struct cache_detail *detail)
static int idtoname_parse(struct cache_detail *, char *, int);
-static struct ent *idtoname_lookup(struct ent *, int);
+static struct ent *idtoname_lookup(struct ent *);
+static struct ent *idtoname_update(struct ent *, struct ent *);
static struct cache_detail idtoname_cache = {
.owner = THIS_MODULE,
@@ -196,6 +199,10 @@ static struct cache_detail idtoname_cache = {
.cache_parse = idtoname_parse,
.cache_show = idtoname_show,
.warn_no_listener = warn_no_idmapd,
+ .match = idtoname_match,
+ .init = ent_init,
+ .update = ent_init,
+ .alloc = ent_alloc,
};
int
@@ -238,6 +245,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
if (ent.h.expiry_time == 0)
goto out;
+ error = -ENOMEM;
+ res = idtoname_lookup(&ent);
+ if (!res)
+ goto out;
+
/* Name */
error = qword_get(&buf, buf1, PAGE_SIZE);
if (error == -EINVAL)
@@ -252,10 +264,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
memcpy(ent.name, buf1, sizeof(ent.name));
}
error = -ENOMEM;
- if ((res = idtoname_lookup(&ent, 1)) == NULL)
+ res = idtoname_update(&ent, res);
+ if (res == NULL)
goto out;
- ent_put(&res->h, &idtoname_cache);
+ cache_put(&res->h, &idtoname_cache);
error = 0;
out:
@@ -264,7 +277,31 @@ out:
return error;
}
-static DefineSimpleCacheLookupMap(ent, idtoname);
+
+static struct ent *
+idtoname_lookup(struct ent *item)
+{
+ struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache,
+ &item->h,
+ idtoname_hash(item));
+ if (ch)
+ return container_of(ch, struct ent, h);
+ else
+ return NULL;
+}
+
+static struct ent *
+idtoname_update(struct ent *new, struct ent *old)
+{
+ struct cache_head *ch = sunrpc_cache_update(&idtoname_cache,
+ &new->h, &old->h,
+ idtoname_hash(new));
+ if (ch)
+ return container_of(ch, struct ent, h);
+ else
+ return NULL;
+}
+
/*
* Name -> ID cache
@@ -291,9 +328,12 @@ nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
(*bpp)[-1] = '\n';
}
-static inline int
-nametoid_match(struct ent *a, struct ent *b)
+static int
+nametoid_match(struct cache_head *ca, struct cache_head *cb)
{
+ struct ent *a = container_of(ca, struct ent, h);
+ struct ent *b = container_of(cb, struct ent, h);
+
return (a->type == b->type && strcmp(a->name, b->name) == 0 &&
strcmp(a->authname, b->authname) == 0);
}
@@ -317,7 +357,8 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
return 0;
}
-static struct ent *nametoid_lookup(struct ent *, int);
+static struct ent *nametoid_lookup(struct ent *);
+static struct ent *nametoid_update(struct ent *, struct ent *);
static int nametoid_parse(struct cache_detail *, char *, int);
static struct cache_detail nametoid_cache = {
@@ -330,6 +371,10 @@ static struct cache_detail nametoid_cache = {
.cache_parse = nametoid_parse,
.cache_show = nametoid_show,
.warn_no_listener = warn_no_idmapd,
+ .match = nametoid_match,
+ .init = ent_init,
+ .update = ent_init,
+ .alloc = ent_alloc,
};
static int
@@ -379,10 +424,14 @@ nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
set_bit(CACHE_NEGATIVE, &ent.h.flags);
error = -ENOMEM;
- if ((res = nametoid_lookup(&ent, 1)) == NULL)
+ res = nametoid_lookup(&ent);
+ if (res == NULL)
+ goto out;
+ res = nametoid_update(&ent, res);
+ if (res == NULL)
goto out;
- ent_put(&res->h, &nametoid_cache);
+ cache_put(&res->h, &nametoid_cache);
error = 0;
out:
kfree(buf1);
@@ -390,7 +439,30 @@ out:
return (error);
}
-static DefineSimpleCacheLookupMap(ent, nametoid);
+
+static struct ent *
+nametoid_lookup(struct ent *item)
+{
+ struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache,
+ &item->h,
+ nametoid_hash(item));
+ if (ch)
+ return container_of(ch, struct ent, h);
+ else
+ return NULL;
+}
+
+static struct ent *
+nametoid_update(struct ent *new, struct ent *old)
+{
+ struct cache_head *ch = sunrpc_cache_update(&nametoid_cache,
+ &new->h, &old->h,
+ nametoid_hash(new));
+ if (ch)
+ return container_of(ch, struct ent, h);
+ else
+ return NULL;
+}
/*
* Exported API
@@ -458,24 +530,24 @@ idmap_defer(struct cache_req *req)
}
static inline int
-do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *, int), struct ent *key,
+do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *), struct ent *key,
struct cache_detail *detail, struct ent **item,
struct idmap_defer_req *mdr)
{
- *item = lookup_fn(key, 0);
+ *item = lookup_fn(key);
if (!*item)
return -ENOMEM;
return cache_check(detail, &(*item)->h, &mdr->req);
}
static inline int
-do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int),
+do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *),
struct ent *key, struct cache_detail *detail,
struct ent **item)
{
int ret = -ENOMEM;
- *item = lookup_fn(key, 0);
+ *item = lookup_fn(key);
if (!*item)
goto out_err;
ret = -ETIMEDOUT;
@@ -488,7 +560,7 @@ do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int),
goto out_put;
return 0;
out_put:
- ent_put(&(*item)->h, detail);
+ cache_put(&(*item)->h, detail);
out_err:
*item = NULL;
return ret;
@@ -496,7 +568,7 @@ out_err:
static int
idmap_lookup(struct svc_rqst *rqstp,
- struct ent *(*lookup_fn)(struct ent *, int), struct ent *key,
+ struct ent *(*lookup_fn)(struct ent *), struct ent *key,
struct cache_detail *detail, struct ent **item)
{
struct idmap_defer_req *mdr;
@@ -539,7 +611,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
if (ret)
return ret;
*id = item->id;
- ent_put(&item->h, &nametoid_cache);
+ cache_put(&item->h, &nametoid_cache);
return 0;
}
@@ -561,7 +633,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
ret = strlen(item->name);
BUG_ON(ret > IDMAP_NAMESZ);
memcpy(name, item->name, ret);
- ent_put(&item->h, &idtoname_cache);
+ cache_put(&item->h, &idtoname_cache);
return ret;
}
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 6d63f1d9e5f..b0e095ea0c0 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -288,8 +288,6 @@ nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh)
fh_put(current_fh);
status = exp_pseudoroot(rqstp->rq_client, current_fh,
&rqstp->rq_chandle);
- if (!status)
- status = nfserrno(nfsd_setuser(rqstp, current_fh->fh_export));
return status;
}
@@ -975,7 +973,7 @@ struct nfsd4_voidargs { int dummy; };
*/
static struct svc_procedure nfsd_procedures4[2] = {
PROC(null, void, void, void, RC_NOCACHE, 1),
- PROC(compound, compound, compound, compound, RC_NOCACHE, NFSD_BUFSIZE)
+ PROC(compound, compound, compound, compound, RC_NOCACHE, NFSD_BUFSIZE/4)
};
struct svc_version nfsd_version4 = {
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 47ec112b266..96c7578cbe1 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -147,6 +147,42 @@ get_nfs4_file(struct nfs4_file *fi)
kref_get(&fi->fi_ref);
}
+static int num_delegations;
+
+/*
+ * Open owner state (share locks)
+ */
+
+/* hash tables for nfs4_stateowner */
+#define OWNER_HASH_BITS 8
+#define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS)
+#define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1)
+
+#define ownerid_hashval(id) \
+ ((id) & OWNER_HASH_MASK)
+#define ownerstr_hashval(clientid, ownername) \
+ (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
+
+static struct list_head ownerid_hashtbl[OWNER_HASH_SIZE];
+static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
+
+/* hash table for nfs4_file */
+#define FILE_HASH_BITS 8
+#define FILE_HASH_SIZE (1 << FILE_HASH_BITS)
+#define FILE_HASH_MASK (FILE_HASH_SIZE - 1)
+/* hash table for (open)nfs4_stateid */
+#define STATEID_HASH_BITS 10
+#define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS)
+#define STATEID_HASH_MASK (STATEID_HASH_SIZE - 1)
+
+#define file_hashval(x) \
+ hash_ptr(x, FILE_HASH_BITS)
+#define stateid_hashval(owner_id, file_id) \
+ (((owner_id) + (file_id)) & STATEID_HASH_MASK)
+
+static struct list_head file_hashtbl[FILE_HASH_SIZE];
+static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
+
static struct nfs4_delegation *
alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
{
@@ -155,9 +191,12 @@ 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)
+ return NULL;
dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
if (dp == NULL)
return dp;
+ num_delegations++;
INIT_LIST_HEAD(&dp->dl_perfile);
INIT_LIST_HEAD(&dp->dl_perclnt);
INIT_LIST_HEAD(&dp->dl_recall_lru);
@@ -192,6 +231,7 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
dprintk("NFSD: freeing dp %p\n",dp);
put_nfs4_file(dp->dl_file);
kmem_cache_free(deleg_slab, dp);
+ num_delegations--;
}
}
@@ -330,22 +370,29 @@ put_nfs4_client(struct nfs4_client *clp)
}
static void
+shutdown_callback_client(struct nfs4_client *clp)
+{
+ struct rpc_clnt *clnt = clp->cl_callback.cb_client;
+
+ /* shutdown rpc client, ending any outstanding recall rpcs */
+ if (clnt) {
+ clp->cl_callback.cb_client = NULL;
+ rpc_shutdown_client(clnt);
+ rpciod_down();
+ }
+}
+
+static void
expire_client(struct nfs4_client *clp)
{
struct nfs4_stateowner *sop;
struct nfs4_delegation *dp;
- struct nfs4_callback *cb = &clp->cl_callback;
- struct rpc_clnt *clnt = clp->cl_callback.cb_client;
struct list_head reaplist;
dprintk("NFSD: expire_client cl_count %d\n",
atomic_read(&clp->cl_count));
- /* shutdown rpc client, ending any outstanding recall rpcs */
- if (atomic_read(&cb->cb_set) == 1 && clnt) {
- rpc_shutdown_client(clnt);
- clnt = clp->cl_callback.cb_client = NULL;
- }
+ shutdown_callback_client(clp);
INIT_LIST_HEAD(&reaplist);
spin_lock(&recall_lock);
@@ -936,40 +983,6 @@ out:
return status;
}
-/*
- * Open owner state (share locks)
- */
-
-/* hash tables for nfs4_stateowner */
-#define OWNER_HASH_BITS 8
-#define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS)
-#define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1)
-
-#define ownerid_hashval(id) \
- ((id) & OWNER_HASH_MASK)
-#define ownerstr_hashval(clientid, ownername) \
- (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
-
-static struct list_head ownerid_hashtbl[OWNER_HASH_SIZE];
-static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
-
-/* hash table for nfs4_file */
-#define FILE_HASH_BITS 8
-#define FILE_HASH_SIZE (1 << FILE_HASH_BITS)
-#define FILE_HASH_MASK (FILE_HASH_SIZE - 1)
-/* hash table for (open)nfs4_stateid */
-#define STATEID_HASH_BITS 10
-#define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS)
-#define STATEID_HASH_MASK (STATEID_HASH_SIZE - 1)
-
-#define file_hashval(x) \
- hash_ptr(x, FILE_HASH_BITS)
-#define stateid_hashval(owner_id, file_id) \
- (((owner_id) + (file_id)) & STATEID_HASH_MASK)
-
-static struct list_head file_hashtbl[FILE_HASH_SIZE];
-static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
-
/* OPEN Share state helper functions */
static inline struct nfs4_file *
alloc_init_file(struct inode *ino)
@@ -1186,8 +1199,7 @@ move_to_close_lru(struct nfs4_stateowner *sop)
{
dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
- unhash_stateowner(sop);
- list_add_tail(&sop->so_close_lru, &close_lru);
+ list_move_tail(&sop->so_close_lru, &close_lru);
sop->so_time = get_seconds();
}
@@ -1916,8 +1928,7 @@ nfs4_laundromat(void)
}
dprintk("NFSD: purging unused open stateowner (so_id %d)\n",
sop->so_id);
- list_del(&sop->so_close_lru);
- nfs4_put_stateowner(sop);
+ release_stateowner(sop);
}
if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT)
clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT;
@@ -2495,36 +2506,27 @@ nfs4_transform_lock_offset(struct file_lock *lock)
lock->fl_end = OFFSET_MAX;
}
-static int
-nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
-{
- struct nfs4_stateowner *local = NULL;
- int status = 0;
-
- if (hashval >= LOCK_HASH_SIZE)
- goto out;
- list_for_each_entry(local, &lock_ownerid_hashtbl[hashval], so_idhash) {
- if (local == sop) {
- status = 1;
- goto out;
- }
- }
-out:
- return status;
-}
-
+/* Hack!: For now, we're defining this just so we can use a pointer to it
+ * as a unique cookie to identify our (NFSv4's) posix locks. */
+static struct lock_manager_operations nfsd_posix_mng_ops = {
+};
static inline void
nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
{
- struct nfs4_stateowner *sop = (struct nfs4_stateowner *) fl->fl_owner;
- unsigned int hval = lockownerid_hashval(sop->so_id);
+ struct nfs4_stateowner *sop;
+ unsigned int hval;
- deny->ld_sop = NULL;
- if (nfs4_verify_lock_stateowner(sop, hval)) {
+ if (fl->fl_lmops == &nfsd_posix_mng_ops) {
+ sop = (struct nfs4_stateowner *) fl->fl_owner;
+ hval = lockownerid_hashval(sop->so_id);
kref_get(&sop->so_ref);
deny->ld_sop = sop;
deny->ld_clientid = sop->so_client->cl_clientid;
+ } else {
+ deny->ld_sop = NULL;
+ deny->ld_clientid.cl_boot = 0;
+ deny->ld_clientid.cl_id = 0;
}
deny->ld_start = fl->fl_start;
deny->ld_length = ~(u64)0;
@@ -2736,6 +2738,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
file_lock.fl_pid = current->tgid;
file_lock.fl_file = filp;
file_lock.fl_flags = FL_POSIX;
+ file_lock.fl_lmops = &nfsd_posix_mng_ops;
file_lock.fl_start = lock->lk_offset;
if ((lock->lk_length == ~(u64)0) ||
@@ -2841,6 +2844,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner;
file_lock.fl_pid = current->tgid;
file_lock.fl_flags = FL_POSIX;
+ file_lock.fl_lmops = &nfsd_posix_mng_ops;
file_lock.fl_start = lockt->lt_offset;
if ((lockt->lt_length == ~(u64)0) || LOFF_OVERFLOW(lockt->lt_offset, lockt->lt_length))
@@ -2900,6 +2904,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
file_lock.fl_pid = current->tgid;
file_lock.fl_file = filp;
file_lock.fl_flags = FL_POSIX;
+ file_lock.fl_lmops = &nfsd_posix_mng_ops;
file_lock.fl_start = locku->lu_offset;
if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length))
@@ -3211,15 +3216,8 @@ __nfs4_state_shutdown(void)
int i;
struct nfs4_client *clp = NULL;
struct nfs4_delegation *dp = NULL;
- struct nfs4_stateowner *sop = NULL;
struct list_head *pos, *next, reaplist;
- list_for_each_safe(pos, next, &close_lru) {
- sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
- list_del(&sop->so_close_lru);
- nfs4_put_stateowner(sop);
- }
-
for (i = 0; i < CLIENT_HASH_SIZE; i++) {
while (!list_empty(&conf_id_hashtbl[i])) {
clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
@@ -3244,8 +3242,6 @@ __nfs4_state_shutdown(void)
}
cancel_delayed_work(&laundromat_work);
- flush_workqueue(laundry_wq);
- destroy_workqueue(laundry_wq);
nfsd4_shutdown_recdir();
nfs4_init = 0;
}
@@ -3253,6 +3249,8 @@ __nfs4_state_shutdown(void)
void
nfs4_state_shutdown(void)
{
+ cancel_rearming_delayed_workqueue(laundry_wq, &laundromat_work);
+ destroy_workqueue(laundry_wq);
nfs4_lock_state();
nfs4_release_reclaim();
__nfs4_state_shutdown();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 03857fd8112..de3998f15f1 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -299,11 +299,10 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
buf, dummy32, &ace.who);
if (status)
goto out_nfserr;
- if (nfs4_acl_add_ace(*acl, ace.type, ace.flag,
- ace.access_mask, ace.whotype, ace.who) != 0) {
- status = -ENOMEM;
+ status = nfs4_acl_add_ace(*acl, ace.type, ace.flag,
+ ace.access_mask, ace.whotype, ace.who);
+ if (status)
goto out_nfserr;
- }
}
} else
*acl = NULL;
@@ -2085,27 +2084,20 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read
WRITE32(eof);
WRITE32(maxcount);
ADJUST_ARGS();
- resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
-
+ resp->xbuf->head[0].iov_len = (char*)p
+ - (char*)resp->xbuf->head[0].iov_base;
resp->xbuf->page_len = maxcount;
- /* read zero bytes -> don't set up tail */
- if(!maxcount)
- return 0;
-
- /* set up page for remaining responses */
- svc_take_page(resp->rqstp);
- resp->xbuf->tail[0].iov_base =
- page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
- resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
+ /* Use rest of head for padding and remaining ops: */
+ resp->rqstp->rq_restailpage = 0;
+ resp->xbuf->tail[0].iov_base = p;
resp->xbuf->tail[0].iov_len = 0;
- resp->p = resp->xbuf->tail[0].iov_base;
- resp->end = resp->p + PAGE_SIZE/4;
-
if (maxcount&3) {
- *(resp->p)++ = 0;
+ RESERVE_SPACE(4);
+ WRITE32(0);
resp->xbuf->tail[0].iov_base += maxcount&3;
resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
+ ADJUST_ARGS();
}
return 0;
}
@@ -2142,21 +2134,20 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r
WRITE32(maxcount);
ADJUST_ARGS();
- resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
+ resp->xbuf->head[0].iov_len = (char*)p
+ - (char*)resp->xbuf->head[0].iov_base;
+ resp->xbuf->page_len = maxcount;
- svc_take_page(resp->rqstp);
- resp->xbuf->tail[0].iov_base =
- page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
- resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
+ /* Use rest of head for padding and remaining ops: */
+ resp->rqstp->rq_restailpage = 0;
+ resp->xbuf->tail[0].iov_base = p;
resp->xbuf->tail[0].iov_len = 0;
- resp->p = resp->xbuf->tail[0].iov_base;
- resp->end = resp->p + PAGE_SIZE/4;
-
- resp->xbuf->page_len = maxcount;
if (maxcount&3) {
- *(resp->p)++ = 0;
+ RESERVE_SPACE(4);
+ WRITE32(0);
resp->xbuf->tail[0].iov_base += maxcount&3;
resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
+ ADJUST_ARGS();
}
return 0;
}
@@ -2166,7 +2157,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
{
int maxcount;
loff_t offset;
- u32 *page, *savep;
+ u32 *page, *savep, *tailbase;
ENCODE_HEAD;
if (nfserr)
@@ -2182,6 +2173,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
WRITE32(0);
ADJUST_ARGS();
resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
+ tailbase = p;
maxcount = PAGE_SIZE;
if (maxcount > readdir->rd_maxcount)
@@ -2226,14 +2218,12 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
*p++ = htonl(readdir->common.err == nfserr_eof);
resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
- /* allocate a page for the tail */
- svc_take_page(resp->rqstp);
- resp->xbuf->tail[0].iov_base =
- page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
- resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
+ /* Use rest of head for padding and remaining ops: */
+ resp->rqstp->rq_restailpage = 0;
+ resp->xbuf->tail[0].iov_base = tailbase;
resp->xbuf->tail[0].iov_len = 0;
resp->p = resp->xbuf->tail[0].iov_base;
- resp->end = resp->p + PAGE_SIZE/4;
+ resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4;
return 0;
err_no_verf:
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index c8960aff096..3ef017b3b5b 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -134,7 +134,7 @@ static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size
return simple_transaction_read(file, buf, size, pos);
}
-static struct file_operations transaction_ops = {
+static const struct file_operations transaction_ops = {
.write = nfsctl_transaction_write,
.read = nfsctl_transaction_read,
.release = simple_transaction_release,
@@ -146,7 +146,7 @@ static int exports_open(struct inode *inode, struct file *file)
return seq_open(file, &nfs_exports_op);
}
-static struct file_operations exports_operations = {
+static const struct file_operations exports_operations = {
.open = exports_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 7a3e397b4ed..3f2ec2e6d06 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -506,7 +506,7 @@ fh_put(struct svc_fh *fhp)
nfsd_nr_put++;
}
if (exp) {
- svc_export_put(&exp->h, &svc_export_cache);
+ cache_put(&exp->h, &svc_export_cache);
fhp->fh_export = NULL;
}
return;
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 3e6b75cd90f..06cd0db0f32 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -553,7 +553,7 @@ static struct svc_procedure nfsd_procedures2[18] = {
PROC(none, void, void, none, RC_NOCACHE, ST),
PROC(lookup, diropargs, diropres, fhandle, RC_NOCACHE, ST+FH+AT),
PROC(readlink, readlinkargs, readlinkres, none, RC_NOCACHE, ST+1+NFS_MAXPATHLEN/4),
- PROC(read, readargs, readres, fhandle, RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE),
+ PROC(read, readargs, readres, fhandle, RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE/4),
PROC(none, void, void, none, RC_NOCACHE, ST),
PROC(write, writeargs, attrstat, fhandle, RC_REPLBUFF, ST+AT),
PROC(create, createargs, diropres, fhandle, RC_REPLBUFF, ST+FH+AT),
diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
index 1cf955bcc52..57265d56380 100644
--- a/fs/nfsd/stats.c
+++ b/fs/nfsd/stats.c
@@ -80,7 +80,7 @@ static int nfsd_proc_open(struct inode *inode, struct file *file)
return single_open(file, nfsd_proc_show, NULL);
}
-static struct file_operations nfsd_proc_fops = {
+static const struct file_operations nfsd_proc_fops = {
.owner = THIS_MODULE,
.open = nfsd_proc_open,
.read = seq_read,
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 5320e5afadd..1d65f13f458 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -371,7 +371,6 @@ out_nfserr:
static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
{
ssize_t buflen;
- int error;
buflen = vfs_getxattr(dentry, key, NULL, 0);
if (buflen <= 0)
@@ -381,10 +380,7 @@ static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
if (!*buf)
return -ENOMEM;
- error = vfs_getxattr(dentry, key, *buf, buflen);
- if (error < 0)
- return error;
- return buflen;
+ return vfs_getxattr(dentry, key, *buf, buflen);
}
#endif
@@ -706,7 +702,7 @@ nfsd_close(struct file *filp)
* after it.
*/
static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
- struct file_operations *fop)
+ const struct file_operations *fop)
{
struct inode *inode = dp->d_inode;
int (*fsync) (struct file *, struct dentry *, int);
@@ -1926,11 +1922,10 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
value = kmalloc(size, GFP_KERNEL);
if (!value)
return -ENOMEM;
- size = posix_acl_to_xattr(acl, value, size);
- if (size < 0) {
- error = size;
+ error = posix_acl_to_xattr(acl, value, size);
+ if (error < 0)
goto getout;
- }
+ size = error;
} else
size = 0;
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c
index 9d9ed3fe371..d1e2c6f9f05 100644
--- a/fs/ntfs/dir.c
+++ b/fs/ntfs/dir.c
@@ -1553,7 +1553,7 @@ static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry,
#endif /* NTFS_RW */
-struct file_operations ntfs_dir_ops = {
+const struct file_operations ntfs_dir_ops = {
.llseek = generic_file_llseek, /* Seek inside directory. */
.read = generic_read_dir, /* Return -EISDIR. */
.readdir = ntfs_readdir, /* Read directory contents. */
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index f5d057e4acc..c63a83e8da9 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2294,7 +2294,7 @@ static int ntfs_file_fsync(struct file *filp, struct dentry *dentry,
#endif /* NTFS_RW */
-struct file_operations ntfs_file_ops = {
+const struct file_operations ntfs_file_ops = {
.llseek = generic_file_llseek, /* Seek inside file. */
.read = generic_file_read, /* Read from file. */
.aio_read = generic_file_aio_read, /* Async read from file. */
@@ -2337,6 +2337,6 @@ struct inode_operations ntfs_file_inode_ops = {
#endif /* NTFS_RW */
};
-struct file_operations ntfs_empty_file_ops = {};
+const struct file_operations ntfs_empty_file_ops = {};
struct inode_operations ntfs_empty_inode_ops = {};
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
index 166142960b5..bf7b3d7c093 100644
--- a/fs/ntfs/ntfs.h
+++ b/fs/ntfs/ntfs.h
@@ -60,13 +60,13 @@ extern struct kmem_cache *ntfs_index_ctx_cache;
extern struct address_space_operations ntfs_aops;
extern struct address_space_operations ntfs_mst_aops;
-extern struct file_operations ntfs_file_ops;
+extern const struct file_operations ntfs_file_ops;
extern struct inode_operations ntfs_file_inode_ops;
-extern struct file_operations ntfs_dir_ops;
+extern const struct file_operations ntfs_dir_ops;
extern struct inode_operations ntfs_dir_inode_ops;
-extern struct file_operations ntfs_empty_file_ops;
+extern const struct file_operations ntfs_empty_file_ops;
extern struct inode_operations ntfs_empty_inode_ops;
extern struct export_operations ntfs_export_ops;
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 0d858d0b25b..47152bf9a7f 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -276,13 +276,29 @@ static int ocfs2_writepage(struct page *page, struct writeback_control *wbc)
return ret;
}
+/* This can also be called from ocfs2_write_zero_page() which has done
+ * it's own cluster locking. */
+int ocfs2_prepare_write_nolock(struct inode *inode, struct page *page,
+ unsigned from, unsigned to)
+{
+ int ret;
+
+ down_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+ ret = block_prepare_write(page, from, to, ocfs2_get_block);
+
+ up_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+ return ret;
+}
+
/*
* ocfs2_prepare_write() can be an outer-most ocfs2 call when it is called
* from loopback. It must be able to perform its own locking around
* ocfs2_get_block().
*/
-int ocfs2_prepare_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int ocfs2_prepare_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
{
struct inode *inode = page->mapping->host;
int ret;
@@ -295,11 +311,7 @@ int ocfs2_prepare_write(struct file *file, struct page *page,
goto out;
}
- down_read(&OCFS2_I(inode)->ip_alloc_sem);
-
- ret = block_prepare_write(page, from, to, ocfs2_get_block);
-
- up_read(&OCFS2_I(inode)->ip_alloc_sem);
+ ret = ocfs2_prepare_write_nolock(inode, page, from, to);
ocfs2_meta_unlock(inode, 0);
out:
@@ -625,11 +637,31 @@ static ssize_t ocfs2_direct_IO(int rw,
int ret;
mlog_entry_void();
+
+ /*
+ * We get PR data locks even for O_DIRECT. This allows
+ * concurrent O_DIRECT I/O but doesn't let O_DIRECT with
+ * extending and buffered zeroing writes race. If they did
+ * race then the buffered zeroing could be written back after
+ * the O_DIRECT I/O. It's one thing to tell people not to mix
+ * buffered and O_DIRECT writes, but expecting them to
+ * understand that file extension is also an implicit buffered
+ * write is too much. By getting the PR we force writeback of
+ * the buffered zeroing before proceeding.
+ */
+ ret = ocfs2_data_lock(inode, 0);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+ ocfs2_data_unlock(inode, 0);
+
ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
inode->i_sb->s_bdev, iov, offset,
nr_segs,
ocfs2_direct_IO_get_blocks,
ocfs2_dio_end_io);
+out:
mlog_exit(ret);
return ret;
}
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index d40456d509a..e88c3f0b8fa 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -22,8 +22,8 @@
#ifndef OCFS2_AOPS_H
#define OCFS2_AOPS_H
-int ocfs2_prepare_write(struct file *file, struct page *page,
- unsigned from, unsigned to);
+int ocfs2_prepare_write_nolock(struct inode *inode, struct page *page,
+ unsigned from, unsigned to);
struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode,
struct page *page,
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index bff0f0d0686..21f38accd03 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -153,6 +153,7 @@ struct o2hb_region {
struct o2hb_bio_wait_ctxt {
atomic_t wc_num_reqs;
struct completion wc_io_complete;
+ int wc_error;
};
static void o2hb_write_timeout(void *arg)
@@ -186,6 +187,7 @@ static inline void o2hb_bio_wait_init(struct o2hb_bio_wait_ctxt *wc,
{
atomic_set(&wc->wc_num_reqs, num_ios);
init_completion(&wc->wc_io_complete);
+ wc->wc_error = 0;
}
/* Used in error paths too */
@@ -218,8 +220,10 @@ static int o2hb_bio_end_io(struct bio *bio,
{
struct o2hb_bio_wait_ctxt *wc = bio->bi_private;
- if (error)
+ if (error) {
mlog(ML_ERROR, "IO Error %d\n", error);
+ wc->wc_error = error;
+ }
if (bio->bi_size)
return 1;
@@ -390,6 +394,8 @@ static int o2hb_read_slots(struct o2hb_region *reg,
bail_and_wait:
o2hb_wait_on_io(reg, &wc);
+ if (wc.wc_error && !status)
+ status = wc.wc_error;
if (bios) {
for(i = 0; i < num_bios; i++)
@@ -790,20 +796,24 @@ static int o2hb_highest_node(unsigned long *nodes,
return highest;
}
-static void o2hb_do_disk_heartbeat(struct o2hb_region *reg)
+static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
{
int i, ret, highest_node, change = 0;
unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)];
struct bio *write_bio;
struct o2hb_bio_wait_ctxt write_wc;
- if (o2nm_configured_node_map(configured_nodes, sizeof(configured_nodes)))
- return;
+ ret = o2nm_configured_node_map(configured_nodes,
+ sizeof(configured_nodes));
+ if (ret) {
+ mlog_errno(ret);
+ return ret;
+ }
highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES);
if (highest_node >= O2NM_MAX_NODES) {
mlog(ML_NOTICE, "ocfs2_heartbeat: no configured nodes found!\n");
- return;
+ return -EINVAL;
}
/* No sense in reading the slots of nodes that don't exist
@@ -813,7 +823,7 @@ static void o2hb_do_disk_heartbeat(struct o2hb_region *reg)
ret = o2hb_read_slots(reg, highest_node + 1);
if (ret < 0) {
mlog_errno(ret);
- return;
+ return ret;
}
/* With an up to date view of the slots, we can check that no
@@ -831,7 +841,7 @@ static void o2hb_do_disk_heartbeat(struct o2hb_region *reg)
ret = o2hb_issue_node_write(reg, &write_bio, &write_wc);
if (ret < 0) {
mlog_errno(ret);
- return;
+ return ret;
}
i = -1;
@@ -847,6 +857,15 @@ static void o2hb_do_disk_heartbeat(struct o2hb_region *reg)
*/
o2hb_wait_on_io(reg, &write_wc);
bio_put(write_bio);
+ if (write_wc.wc_error) {
+ /* Do not re-arm the write timeout on I/O error - we
+ * can't be sure that the new block ever made it to
+ * disk */
+ mlog(ML_ERROR, "Write error %d on device \"%s\"\n",
+ write_wc.wc_error, reg->hr_dev_name);
+ return write_wc.wc_error;
+ }
+
o2hb_arm_write_timeout(reg);
/* let the person who launched us know when things are steady */
@@ -854,6 +873,8 @@ static void o2hb_do_disk_heartbeat(struct o2hb_region *reg)
if (atomic_dec_and_test(&reg->hr_steady_iterations))
wake_up(&o2hb_steady_queue);
}
+
+ return 0;
}
/* Subtract b from a, storing the result in a. a *must* have a larger
@@ -913,7 +934,10 @@ static int o2hb_thread(void *data)
* likely to time itself out. */
do_gettimeofday(&before_hb);
- o2hb_do_disk_heartbeat(reg);
+ i = 0;
+ do {
+ ret = o2hb_do_disk_heartbeat(reg);
+ } while (ret && ++i < 2);
do_gettimeofday(&after_hb);
elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb);
diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c
index c3764f4744e..74ca4e5f976 100644
--- a/fs/ocfs2/dlm/userdlm.c
+++ b/fs/ocfs2/dlm/userdlm.c
@@ -139,6 +139,10 @@ static void user_ast(void *opaque)
return;
}
+ mlog_bug_on_msg(lockres->l_requested == LKM_IVMODE,
+ "Lockres %s, requested ivmode. flags 0x%x\n",
+ lockres->l_name, lockres->l_flags);
+
/* we're downconverting. */
if (lockres->l_requested < lockres->l_level) {
if (lockres->l_requested <=
@@ -229,23 +233,42 @@ static void user_unlock_ast(void *opaque, enum dlm_status status)
mlog(0, "UNLOCK AST called on lock %s\n", lockres->l_name);
- if (status != DLM_NORMAL)
+ if (status != DLM_NORMAL && status != DLM_CANCELGRANT)
mlog(ML_ERROR, "Dlm returns status %d\n", status);
spin_lock(&lockres->l_lock);
- if (lockres->l_flags & USER_LOCK_IN_TEARDOWN)
+ /* The teardown flag gets set early during the unlock process,
+ * so test the cancel flag to make sure that this ast isn't
+ * for a concurrent cancel. */
+ if (lockres->l_flags & USER_LOCK_IN_TEARDOWN
+ && !(lockres->l_flags & USER_LOCK_IN_CANCEL)) {
lockres->l_level = LKM_IVMODE;
- else {
+ } else if (status == DLM_CANCELGRANT) {
+ mlog(0, "Lock %s, cancel fails, flags 0x%x\n",
+ lockres->l_name, lockres->l_flags);
+ /* We tried to cancel a convert request, but it was
+ * already granted. Don't clear the busy flag - the
+ * ast should've done this already. */
+ BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL));
+ lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
+ goto out_noclear;
+ } else {
+ BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL));
+ /* Cancel succeeded, we want to re-queue */
+ mlog(0, "Lock %s, cancel succeeds, flags 0x%x\n",
+ lockres->l_name, lockres->l_flags);
lockres->l_requested = LKM_IVMODE; /* cancel an
* upconvert
* request. */
lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
/* we want the unblock thread to look at it again
* now. */
- __user_dlm_queue_lockres(lockres);
+ if (lockres->l_flags & USER_LOCK_BLOCKED)
+ __user_dlm_queue_lockres(lockres);
}
lockres->l_flags &= ~USER_LOCK_BUSY;
+out_noclear:
spin_unlock(&lockres->l_lock);
wake_up(&lockres->l_event);
@@ -268,13 +291,26 @@ static void user_dlm_unblock_lock(void *opaque)
spin_lock(&lockres->l_lock);
- BUG_ON(!(lockres->l_flags & USER_LOCK_BLOCKED));
- BUG_ON(!(lockres->l_flags & USER_LOCK_QUEUED));
+ mlog_bug_on_msg(!(lockres->l_flags & USER_LOCK_QUEUED),
+ "Lockres %s, flags 0x%x\n",
+ lockres->l_name, lockres->l_flags);
- /* notice that we don't clear USER_LOCK_BLOCKED here. That's
- * for user_ast to do. */
+ /* notice that we don't clear USER_LOCK_BLOCKED here. If it's
+ * set, we want user_ast clear it. */
lockres->l_flags &= ~USER_LOCK_QUEUED;
+ /* It's valid to get here and no longer be blocked - if we get
+ * several basts in a row, we might be queued by the first
+ * one, the unblock thread might run and clear the queued
+ * flag, and finally we might get another bast which re-queues
+ * us before our ast for the downconvert is called. */
+ if (!(lockres->l_flags & USER_LOCK_BLOCKED)) {
+ mlog(0, "Lockres %s, flags 0x%x: queued but not blocking\n",
+ lockres->l_name, lockres->l_flags);
+ spin_unlock(&lockres->l_lock);
+ goto drop_ref;
+ }
+
if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) {
mlog(0, "lock is in teardown so we do nothing\n");
spin_unlock(&lockres->l_lock);
@@ -282,7 +318,9 @@ static void user_dlm_unblock_lock(void *opaque)
}
if (lockres->l_flags & USER_LOCK_BUSY) {
- mlog(0, "BUSY flag detected...\n");
+ mlog(0, "Cancel lock %s, flags 0x%x\n",
+ lockres->l_name, lockres->l_flags);
+
if (lockres->l_flags & USER_LOCK_IN_CANCEL) {
spin_unlock(&lockres->l_lock);
goto drop_ref;
@@ -296,14 +334,7 @@ static void user_dlm_unblock_lock(void *opaque)
LKM_CANCEL,
user_unlock_ast,
lockres);
- if (status == DLM_CANCELGRANT) {
- /* If we got this, then the ast was fired
- * before we could cancel. We cleanup our
- * state, and restart the function. */
- spin_lock(&lockres->l_lock);
- lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
- spin_unlock(&lockres->l_lock);
- } else if (status != DLM_NORMAL)
+ if (status != DLM_NORMAL)
user_log_dlm_error("dlmunlock", status, lockres);
goto drop_ref;
}
@@ -581,6 +612,14 @@ int user_dlm_destroy_lock(struct user_lock_res *lockres)
mlog(0, "asked to destroy %s\n", lockres->l_name);
spin_lock(&lockres->l_lock);
+ if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) {
+ mlog(0, "Lock is already torn down\n");
+ spin_unlock(&lockres->l_lock);
+ return 0;
+ }
+
+ lockres->l_flags |= USER_LOCK_IN_TEARDOWN;
+
while (lockres->l_flags & USER_LOCK_BUSY) {
spin_unlock(&lockres->l_lock);
@@ -606,7 +645,6 @@ int user_dlm_destroy_lock(struct user_lock_res *lockres)
lockres->l_flags &= ~USER_LOCK_ATTACHED;
lockres->l_flags |= USER_LOCK_BUSY;
- lockres->l_flags |= USER_LOCK_IN_TEARDOWN;
spin_unlock(&lockres->l_lock);
mlog(0, "unlocking lockres %s\n", lockres->l_name);
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 84f153aca69..64cd52860c8 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -2017,7 +2017,7 @@ out:
return ret;
}
-static struct file_operations ocfs2_dlm_debug_fops = {
+static const struct file_operations ocfs2_dlm_debug_fops = {
.open = ocfs2_dlm_debug_open,
.release = ocfs2_dlm_debug_release,
.read = seq_read,
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index 4601fc256f1..1a5c69071df 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -569,7 +569,7 @@ static int ocfs2_extent_map_insert(struct inode *inode,
ret = -ENOMEM;
ctxt.new_ent = kmem_cache_alloc(ocfs2_em_ent_cachep,
- GFP_KERNEL);
+ GFP_NOFS);
if (!ctxt.new_ent) {
mlog_errno(ret);
return ret;
@@ -583,14 +583,14 @@ static int ocfs2_extent_map_insert(struct inode *inode,
if (ctxt.need_left && !ctxt.left_ent) {
ctxt.left_ent =
kmem_cache_alloc(ocfs2_em_ent_cachep,
- GFP_KERNEL);
+ GFP_NOFS);
if (!ctxt.left_ent)
break;
}
if (ctxt.need_right && !ctxt.right_ent) {
ctxt.right_ent =
kmem_cache_alloc(ocfs2_em_ent_cachep,
- GFP_KERNEL);
+ GFP_NOFS);
if (!ctxt.right_ent)
break;
}
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 4b4cbadd583..a9559c87453 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -260,6 +260,17 @@ static int ocfs2_truncate_file(struct inode *inode,
if (new_i_size == le64_to_cpu(fe->i_size))
goto bail;
+ /* 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) {
+ mlog_errno(status);
+ goto bail;
+ }
+ ocfs2_data_unlock(inode, 1);
+
if (le32_to_cpu(fe->i_clusters) ==
ocfs2_clusters_for_bytes(osb->sb, new_i_size)) {
mlog(0, "fe->i_clusters = %u, so we do a simple truncate\n",
@@ -272,14 +283,6 @@ static int ocfs2_truncate_file(struct inode *inode,
goto bail;
}
- /* This forces other nodes to sync and drop their pages */
- status = ocfs2_data_lock(inode, 1);
- if (status < 0) {
- mlog_errno(status);
- goto bail;
- }
- ocfs2_data_unlock(inode, 1);
-
/* 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
@@ -610,7 +613,8 @@ leave:
/* 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 ->commit_write(). */
+ * worry about recursive locking in ->prepare_write() and
+ * ->commit_write(). */
static int ocfs2_write_zero_page(struct inode *inode,
u64 size)
{
@@ -638,7 +642,7 @@ static int ocfs2_write_zero_page(struct inode *inode,
goto out;
}
- ret = ocfs2_prepare_write(NULL, page, offset, offset);
+ ret = ocfs2_prepare_write_nolock(inode, page, offset, offset);
if (ret < 0) {
mlog_errno(ret);
goto out_unlock;
@@ -692,13 +696,26 @@ out:
return ret;
}
+/*
+ * A tail_to_skip value > 0 indicates that we're being called from
+ * ocfs2_file_aio_write(). This has the following implications:
+ *
+ * - we don't want to update i_size
+ * - di_bh will be NULL, which is fine because it's only used in the
+ * case where we want to update i_size.
+ * - ocfs2_zero_extend() will then only be filling the hole created
+ * between i_size and the start of the write.
+ */
static int ocfs2_extend_file(struct inode *inode,
struct buffer_head *di_bh,
- u64 new_i_size)
+ u64 new_i_size,
+ size_t tail_to_skip)
{
int ret = 0;
u32 clusters_to_add;
+ BUG_ON(!tail_to_skip && !di_bh);
+
/* setattr sometimes calls us like this. */
if (new_i_size == 0)
goto out;
@@ -711,27 +728,44 @@ static int ocfs2_extend_file(struct inode *inode,
OCFS2_I(inode)->ip_clusters;
if (clusters_to_add) {
- ret = ocfs2_extend_allocation(inode, clusters_to_add);
+ /*
+ * protect the pages that ocfs2_zero_extend is going to
+ * be pulling into the page cache.. we do this before the
+ * metadata extend so that we don't get into the situation
+ * where we've extended the metadata but can't get the data
+ * lock to zero.
+ */
+ ret = ocfs2_data_lock(inode, 1);
if (ret < 0) {
mlog_errno(ret);
goto out;
}
- ret = ocfs2_zero_extend(inode, new_i_size);
+ ret = ocfs2_extend_allocation(inode, clusters_to_add);
if (ret < 0) {
mlog_errno(ret);
- goto out;
+ goto out_unlock;
}
- }
- /* No allocation required, we just use this helper to
- * do a trivial update of i_size. */
- ret = ocfs2_simple_size_update(inode, di_bh, new_i_size);
- if (ret < 0) {
- mlog_errno(ret);
- goto out;
+ ret = ocfs2_zero_extend(inode, (u64)new_i_size - tail_to_skip);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out_unlock;
+ }
}
+ if (!tail_to_skip) {
+ /* We're being called from ocfs2_setattr() which wants
+ * us to update i_size */
+ ret = ocfs2_simple_size_update(inode, di_bh, new_i_size);
+ if (ret < 0)
+ mlog_errno(ret);
+ }
+
+out_unlock:
+ if (clusters_to_add) /* this is the only case in which we lock */
+ ocfs2_data_unlock(inode, 1);
+
out:
return ret;
}
@@ -790,7 +824,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
if (i_size_read(inode) > attr->ia_size)
status = ocfs2_truncate_file(inode, bh, attr->ia_size);
else
- status = ocfs2_extend_file(inode, bh, attr->ia_size);
+ status = ocfs2_extend_file(inode, bh, attr->ia_size, 0);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
@@ -1046,21 +1080,12 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
if (!clusters)
break;
- ret = ocfs2_extend_allocation(inode, clusters);
+ ret = ocfs2_extend_file(inode, NULL, newsize, count);
if (ret < 0) {
if (ret != -ENOSPC)
mlog_errno(ret);
goto out;
}
-
- /* Fill any holes which would've been created by this
- * write. If we're O_APPEND, this will wind up
- * (correctly) being a noop. */
- ret = ocfs2_zero_extend(inode, (u64) newsize - count);
- if (ret < 0) {
- mlog_errno(ret);
- goto out;
- }
break;
}
@@ -1143,6 +1168,22 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
ocfs2_iocb_set_rw_locked(iocb);
}
+ /*
+ * We're fine letting folks race truncates and extending
+ * writes with read across the cluster, just like they can
+ * locally. Hence no rw_lock during read.
+ *
+ * Take and drop the meta data lock to update inode fields
+ * like i_size. This allows the checks down below
+ * generic_file_aio_read() a chance of actually working.
+ */
+ ret = ocfs2_meta_lock(inode, NULL, NULL, 0);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto bail;
+ }
+ ocfs2_meta_unlock(inode, 0);
+
ret = generic_file_aio_read(iocb, buf, count, iocb->ki_pos);
if (ret == -EINVAL)
mlog(ML_ERROR, "generic_file_aio_read returned -EINVAL\n");
@@ -1176,7 +1217,7 @@ struct inode_operations ocfs2_special_file_iops = {
.getattr = ocfs2_getattr,
};
-struct file_operations ocfs2_fops = {
+const struct file_operations ocfs2_fops = {
.read = do_sync_read,
.write = do_sync_write,
.sendfile = generic_file_sendfile,
@@ -1188,7 +1229,7 @@ struct file_operations ocfs2_fops = {
.aio_write = ocfs2_file_aio_write,
};
-struct file_operations ocfs2_dops = {
+const struct file_operations ocfs2_dops = {
.read = generic_read_dir,
.readdir = ocfs2_readdir,
.fsync = ocfs2_sync_file,
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index a5ea33b2406..740c9e7ca59 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -26,8 +26,8 @@
#ifndef OCFS2_FILE_H
#define OCFS2_FILE_H
-extern struct file_operations ocfs2_fops;
-extern struct file_operations ocfs2_dops;
+extern const struct file_operations ocfs2_fops;
+extern const struct file_operations ocfs2_dops;
extern struct inode_operations ocfs2_file_iops;
extern struct inode_operations ocfs2_special_file_iops;
struct ocfs2_alloc_context;
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 6a610ae5358..eebc3cfa6be 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -117,7 +117,7 @@ struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb)
{
struct ocfs2_journal_handle *retval = NULL;
- retval = kcalloc(1, sizeof(*retval), GFP_KERNEL);
+ retval = kcalloc(1, sizeof(*retval), GFP_NOFS);
if (!retval) {
mlog(ML_ERROR, "Failed to allocate memory for journal "
"handle!\n");
@@ -870,9 +870,11 @@ static int ocfs2_force_read_journal(struct inode *inode)
if (p_blocks > CONCURRENT_JOURNAL_FILL)
p_blocks = CONCURRENT_JOURNAL_FILL;
+ /* We are reading journal data which should not
+ * be put in the uptodate cache */
status = ocfs2_read_blocks(OCFS2_SB(inode->i_sb),
p_blkno, p_blocks, bhs, 0,
- inode);
+ NULL);
if (status < 0) {
mlog_errno(status);
goto bail;
@@ -982,7 +984,7 @@ static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal,
{
struct ocfs2_la_recovery_item *item;
- item = kmalloc(sizeof(struct ocfs2_la_recovery_item), GFP_KERNEL);
+ item = kmalloc(sizeof(struct ocfs2_la_recovery_item), GFP_NOFS);
if (!item) {
/* Though we wish to avoid it, we are in fact safe in
* skipping local alloc cleanup as fsck.ocfs2 is more
diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c
index 04a684dfdd9..b8a00a79332 100644
--- a/fs/ocfs2/uptodate.c
+++ b/fs/ocfs2/uptodate.c
@@ -337,7 +337,7 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi,
(unsigned long long)oi->ip_blkno,
(unsigned long long)block, expand_tree);
- new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_KERNEL);
+ new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_NOFS);
if (!new) {
mlog_errno(-ENOMEM);
return;
@@ -349,7 +349,7 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi,
* has no way of tracking that. */
for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++) {
tree[i] = kmem_cache_alloc(ocfs2_uptodate_cachep,
- GFP_KERNEL);
+ GFP_NOFS);
if (!tree[i]) {
mlog_errno(-ENOMEM);
goto out_free;
diff --git a/fs/ocfs2/vote.c b/fs/ocfs2/vote.c
index 53049a20419..ee42765a855 100644
--- a/fs/ocfs2/vote.c
+++ b/fs/ocfs2/vote.c
@@ -586,7 +586,7 @@ static struct ocfs2_net_wait_ctxt *ocfs2_new_net_wait_ctxt(unsigned int response
{
struct ocfs2_net_wait_ctxt *w;
- w = kcalloc(1, sizeof(*w), GFP_KERNEL);
+ w = kcalloc(1, sizeof(*w), GFP_NOFS);
if (!w) {
mlog_errno(-ENOMEM);
goto bail;
@@ -749,7 +749,7 @@ static struct ocfs2_vote_msg * ocfs2_new_vote_request(struct ocfs2_super *osb,
BUG_ON(!ocfs2_is_valid_vote_request(type));
- request = kcalloc(1, sizeof(*request), GFP_KERNEL);
+ request = kcalloc(1, sizeof(*request), GFP_NOFS);
if (!request) {
mlog_errno(-ENOMEM);
} else {
@@ -1129,7 +1129,7 @@ static int ocfs2_handle_vote_message(struct o2net_msg *msg,
struct ocfs2_super *osb = data;
struct ocfs2_vote_work *work;
- work = kmalloc(sizeof(struct ocfs2_vote_work), GFP_KERNEL);
+ work = kmalloc(sizeof(struct ocfs2_vote_work), GFP_NOFS);
if (!work) {
status = -ENOMEM;
mlog_errno(status);
diff --git a/fs/open.c b/fs/open.c
index c32c89d6d8d..317b7c7f38a 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -331,7 +331,10 @@ out:
asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
{
- return do_sys_ftruncate(fd, length, 1);
+ long ret = do_sys_ftruncate(fd, length, 1);
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
/* LFS versions of truncate are only needed on 32 bit machines */
@@ -343,7 +346,10 @@ asmlinkage long sys_truncate64(const char __user * path, loff_t length)
asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
{
- return do_sys_ftruncate(fd, length, 0);
+ long ret = do_sys_ftruncate(fd, length, 0);
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
#endif
@@ -1093,22 +1099,31 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
asmlinkage long sys_open(const char __user *filename, int flags, int mode)
{
+ long ret;
+
if (force_o_largefile())
flags |= O_LARGEFILE;
- return do_sys_open(AT_FDCWD, filename, flags, mode);
+ ret = do_sys_open(AT_FDCWD, filename, flags, mode);
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
EXPORT_SYMBOL_GPL(sys_open);
asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
int mode)
{
+ long ret;
+
if (force_o_largefile())
flags |= O_LARGEFILE;
- return do_sys_open(dfd, filename, flags, mode);
+ ret = do_sys_open(dfd, filename, flags, mode);
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
-EXPORT_SYMBOL_GPL(sys_openat);
#ifndef __alpha__
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index aeb0106890e..0f14276a2e5 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -581,17 +581,17 @@ int property_release (struct inode *inode, struct file *filp)
return 0;
}
-static struct file_operations openpromfs_prop_ops = {
+static const struct file_operations openpromfs_prop_ops = {
.read = property_read,
.write = property_write,
.release = property_release,
};
-static struct file_operations openpromfs_nodenum_ops = {
+static const struct file_operations openpromfs_nodenum_ops = {
.read = nodenum_read,
};
-static struct file_operations openprom_operations = {
+static const struct file_operations openprom_operations = {
.read = generic_read_dir,
.readdir = openpromfs_readdir,
};
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index f924f459bdb..7ef1f094de9 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -297,6 +297,25 @@ struct kobj_type ktype_part = {
.sysfs_ops = &part_sysfs_ops,
};
+static inline void partition_sysfs_add_subdir(struct hd_struct *p)
+{
+ struct kobject *k;
+
+ k = kobject_get(&p->kobj);
+ p->holder_dir = kobject_add_dir(k, "holders");
+ kobject_put(k);
+}
+
+static inline void disk_sysfs_add_subdirs(struct gendisk *disk)
+{
+ struct kobject *k;
+
+ k = kobject_get(&disk->kobj);
+ disk->holder_dir = kobject_add_dir(k, "holders");
+ disk->slave_dir = kobject_add_dir(k, "slaves");
+ kobject_put(k);
+}
+
void delete_partition(struct gendisk *disk, int part)
{
struct hd_struct *p = disk->part[part-1];
@@ -310,7 +329,11 @@ void delete_partition(struct gendisk *disk, int part)
p->ios[0] = p->ios[1] = 0;
p->sectors[0] = p->sectors[1] = 0;
devfs_remove("%s/part%d", disk->devfs_name, part);
- kobject_unregister(&p->kobj);
+ if (p->holder_dir)
+ kobject_unregister(p->holder_dir);
+ kobject_uevent(&p->kobj, KOBJ_REMOVE);
+ kobject_del(&p->kobj);
+ kobject_put(&p->kobj);
}
void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
@@ -336,7 +359,11 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part);
p->kobj.parent = &disk->kobj;
p->kobj.ktype = &ktype_part;
- kobject_register(&p->kobj);
+ kobject_init(&p->kobj);
+ kobject_add(&p->kobj);
+ if (!disk->part_uevent_suppress)
+ kobject_uevent(&p->kobj, KOBJ_ADD);
+ partition_sysfs_add_subdir(p);
disk->part[part-1] = p;
}
@@ -345,6 +372,7 @@ static char *make_block_name(struct gendisk *disk)
char *name;
static char *block_str = "block:";
int size;
+ char *s;
size = strlen(block_str) + strlen(disk->disk_name) + 1;
name = kmalloc(size, GFP_KERNEL);
@@ -352,6 +380,10 @@ static char *make_block_name(struct gendisk *disk)
return NULL;
strcpy(name, block_str);
strcat(name, disk->disk_name);
+ /* ewww... some of these buggers have / in name... */
+ s = strchr(name, '/');
+ if (s)
+ *s = '!';
return name;
}
@@ -373,6 +405,8 @@ void register_disk(struct gendisk *disk)
{
struct block_device *bdev;
char *s;
+ int i;
+ struct hd_struct *p;
int err;
strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN);
@@ -383,13 +417,13 @@ void register_disk(struct gendisk *disk)
if ((err = kobject_add(&disk->kobj)))
return;
disk_sysfs_symlinks(disk);
- kobject_uevent(&disk->kobj, KOBJ_ADD);
+ disk_sysfs_add_subdirs(disk);
/* No minors to use for partitions */
if (disk->minors == 1) {
if (disk->devfs_name[0] != '\0')
devfs_add_disk(disk);
- return;
+ goto exit;
}
/* always add handle for the whole disk */
@@ -397,16 +431,32 @@ void register_disk(struct gendisk *disk)
/* No such device (e.g., media were just removed) */
if (!get_capacity(disk))
- return;
+ goto exit;
bdev = bdget_disk(disk, 0);
if (!bdev)
- return;
+ goto exit;
+ /* scan partition table, but suppress uevents */
bdev->bd_invalidated = 1;
- if (blkdev_get(bdev, FMODE_READ, 0) < 0)
- return;
+ disk->part_uevent_suppress = 1;
+ err = blkdev_get(bdev, FMODE_READ, 0);
+ disk->part_uevent_suppress = 0;
+ if (err < 0)
+ goto exit;
blkdev_put(bdev);
+
+exit:
+ /* announce disk after possible partitions are already created */
+ kobject_uevent(&disk->kobj, KOBJ_ADD);
+
+ /* announce possible partitions */
+ for (i = 1; i < disk->minors; i++) {
+ p = disk->part[i-1];
+ if (!p || !p->nr_sects)
+ continue;
+ kobject_uevent(&p->kobj, KOBJ_ADD);
+ }
}
int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
@@ -483,6 +533,11 @@ void del_gendisk(struct gendisk *disk)
devfs_remove_disk(disk);
+ kobject_uevent(&disk->kobj, KOBJ_REMOVE);
+ if (disk->holder_dir)
+ kobject_unregister(disk->holder_dir);
+ if (disk->slave_dir)
+ kobject_unregister(disk->slave_dir);
if (disk->driverfs_dev) {
char *disk_name = make_block_name(disk);
sysfs_remove_link(&disk->kobj, "device");
@@ -491,7 +546,7 @@ void del_gendisk(struct gendisk *disk)
kfree(disk_name);
}
put_device(disk->driverfs_dev);
+ disk->driverfs_dev = NULL;
}
- kobject_uevent(&disk->kobj, KOBJ_REMOVE);
kobject_del(&disk->kobj);
}
diff --git a/fs/partitions/mac.c b/fs/partitions/mac.c
index bb22cdd0cb1..813292f2121 100644
--- a/fs/partitions/mac.c
+++ b/fs/partitions/mac.c
@@ -12,6 +12,7 @@
#include "mac.h"
#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
extern void note_bootable_part(dev_t dev, int part, int goodness);
#endif
@@ -79,7 +80,7 @@ int mac_partition(struct parsed_partitions *state, struct block_device *bdev)
* If this is the first bootable partition, tell the
* setup code, in case it wants to make this the root.
*/
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
int goodness = 0;
mac_fix_string(part->processor, 16);
diff --git a/fs/pipe.c b/fs/pipe.c
index 4384c929094..5acd8954aaa 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -15,6 +15,7 @@
#include <linux/pipe_fs_i.h>
#include <linux/uio.h>
#include <linux/highmem.h>
+#include <linux/pagemap.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
@@ -35,7 +36,7 @@
*/
/* Drop the inode semaphore and wait for a pipe event, atomically */
-void pipe_wait(struct inode * inode)
+void pipe_wait(struct pipe_inode_info *pipe)
{
DEFINE_WAIT(wait);
@@ -43,15 +44,19 @@ void pipe_wait(struct inode * inode)
* Pipes are system-local resources, so sleeping on them
* is considered a noninteractive wait:
*/
- prepare_to_wait(PIPE_WAIT(*inode), &wait, TASK_INTERRUPTIBLE|TASK_NONINTERACTIVE);
- mutex_unlock(PIPE_MUTEX(*inode));
+ prepare_to_wait(&pipe->wait, &wait,
+ TASK_INTERRUPTIBLE | TASK_NONINTERACTIVE);
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
schedule();
- finish_wait(PIPE_WAIT(*inode), &wait);
- mutex_lock(PIPE_MUTEX(*inode));
+ finish_wait(&pipe->wait, &wait);
+ if (pipe->inode)
+ mutex_lock(&pipe->inode->i_mutex);
}
static int
-pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len)
+pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len,
+ int atomic)
{
unsigned long copy;
@@ -60,8 +65,13 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len)
iov++;
copy = min_t(unsigned long, len, iov->iov_len);
- if (copy_from_user(to, iov->iov_base, copy))
- return -EFAULT;
+ if (atomic) {
+ if (__copy_from_user_inatomic(to, iov->iov_base, copy))
+ return -EFAULT;
+ } else {
+ if (copy_from_user(to, iov->iov_base, copy))
+ return -EFAULT;
+ }
to += copy;
len -= copy;
iov->iov_base += copy;
@@ -71,7 +81,8 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len)
}
static int
-pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len)
+pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len,
+ int atomic)
{
unsigned long copy;
@@ -80,8 +91,13 @@ pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len)
iov++;
copy = min_t(unsigned long, len, iov->iov_len);
- if (copy_to_user(iov->iov_base, from, copy))
- return -EFAULT;
+ if (atomic) {
+ if (__copy_to_user_inatomic(iov->iov_base, from, copy))
+ return -EFAULT;
+ } else {
+ if (copy_to_user(iov->iov_base, from, copy))
+ return -EFAULT;
+ }
from += copy;
len -= copy;
iov->iov_base += copy;
@@ -90,32 +106,115 @@ pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len)
return 0;
}
-static void anon_pipe_buf_release(struct pipe_inode_info *info, struct pipe_buffer *buf)
+/*
+ * Attempt to pre-fault in the user memory, so we can use atomic copies.
+ * Returns the number of bytes not faulted in.
+ */
+static int iov_fault_in_pages_write(struct iovec *iov, unsigned long len)
{
- struct page *page = buf->page;
+ while (!iov->iov_len)
+ iov++;
+
+ while (len > 0) {
+ unsigned long this_len;
+
+ this_len = min_t(unsigned long, len, iov->iov_len);
+ if (fault_in_pages_writeable(iov->iov_base, this_len))
+ break;
- if (info->tmp_page) {
- __free_page(page);
- return;
+ len -= this_len;
+ iov++;
}
- info->tmp_page = page;
+
+ return len;
}
-static void *anon_pipe_buf_map(struct file *file, struct pipe_inode_info *info, struct pipe_buffer *buf)
+/*
+ * Pre-fault in the user memory, so we can use atomic copies.
+ */
+static void iov_fault_in_pages_read(struct iovec *iov, unsigned long len)
{
+ while (!iov->iov_len)
+ iov++;
+
+ while (len > 0) {
+ unsigned long this_len;
+
+ this_len = min_t(unsigned long, len, iov->iov_len);
+ fault_in_pages_readable(iov->iov_base, this_len);
+ len -= this_len;
+ iov++;
+ }
+}
+
+static void anon_pipe_buf_release(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+{
+ struct page *page = buf->page;
+
+ /*
+ * If nobody else uses this page, and we don't already have a
+ * temporary page, let's keep track of it as a one-deep
+ * allocation cache. (Otherwise just release our reference to it)
+ */
+ if (page_count(page) == 1 && !pipe->tmp_page)
+ pipe->tmp_page = page;
+ else
+ page_cache_release(page);
+}
+
+void *generic_pipe_buf_map(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf, int atomic)
+{
+ if (atomic) {
+ buf->flags |= PIPE_BUF_FLAG_ATOMIC;
+ return kmap_atomic(buf->page, KM_USER0);
+ }
+
return kmap(buf->page);
}
-static void anon_pipe_buf_unmap(struct pipe_inode_info *info, struct pipe_buffer *buf)
+void generic_pipe_buf_unmap(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf, void *map_data)
+{
+ if (buf->flags & PIPE_BUF_FLAG_ATOMIC) {
+ buf->flags &= ~PIPE_BUF_FLAG_ATOMIC;
+ kunmap_atomic(map_data, KM_USER0);
+ } else
+ kunmap(buf->page);
+}
+
+int generic_pipe_buf_steal(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+{
+ struct page *page = buf->page;
+
+ if (page_count(page) == 1) {
+ lock_page(page);
+ return 0;
+ }
+
+ return 1;
+}
+
+void generic_pipe_buf_get(struct pipe_inode_info *info, struct pipe_buffer *buf)
{
- kunmap(buf->page);
+ page_cache_get(buf->page);
+}
+
+int generic_pipe_buf_pin(struct pipe_inode_info *info, struct pipe_buffer *buf)
+{
+ return 0;
}
static struct pipe_buf_operations anon_pipe_buf_ops = {
.can_merge = 1,
- .map = anon_pipe_buf_map,
- .unmap = anon_pipe_buf_unmap,
+ .map = generic_pipe_buf_map,
+ .unmap = generic_pipe_buf_unmap,
+ .pin = generic_pipe_buf_pin,
.release = anon_pipe_buf_release,
+ .steal = generic_pipe_buf_steal,
+ .get = generic_pipe_buf_get,
};
static ssize_t
@@ -123,7 +222,7 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
unsigned long nr_segs, loff_t *ppos)
{
struct inode *inode = filp->f_dentry->d_inode;
- struct pipe_inode_info *info;
+ struct pipe_inode_info *pipe;
int do_wakeup;
ssize_t ret;
struct iovec *iov = (struct iovec *)_iov;
@@ -136,26 +235,43 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
do_wakeup = 0;
ret = 0;
- mutex_lock(PIPE_MUTEX(*inode));
- info = inode->i_pipe;
+ mutex_lock(&inode->i_mutex);
+ pipe = inode->i_pipe;
for (;;) {
- int bufs = info->nrbufs;
+ int bufs = pipe->nrbufs;
if (bufs) {
- int curbuf = info->curbuf;
- struct pipe_buffer *buf = info->bufs + curbuf;
+ int curbuf = pipe->curbuf;
+ struct pipe_buffer *buf = pipe->bufs + curbuf;
struct pipe_buf_operations *ops = buf->ops;
void *addr;
size_t chars = buf->len;
- int error;
+ int error, atomic;
if (chars > total_len)
chars = total_len;
- addr = ops->map(filp, info, buf);
- error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars);
- ops->unmap(info, buf);
+ error = ops->pin(pipe, buf);
+ if (error) {
+ if (!ret)
+ error = ret;
+ break;
+ }
+
+ atomic = !iov_fault_in_pages_write(iov, chars);
+redo:
+ addr = ops->map(pipe, buf, atomic);
+ error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic);
+ ops->unmap(pipe, buf, addr);
if (unlikely(error)) {
- if (!ret) ret = -EFAULT;
+ /*
+ * Just retry with the slow path if we failed.
+ */
+ if (atomic) {
+ atomic = 0;
+ goto redo;
+ }
+ if (!ret)
+ ret = error;
break;
}
ret += chars;
@@ -163,10 +279,10 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
buf->len -= chars;
if (!buf->len) {
buf->ops = NULL;
- ops->release(info, buf);
+ ops->release(pipe, buf);
curbuf = (curbuf + 1) & (PIPE_BUFFERS-1);
- info->curbuf = curbuf;
- info->nrbufs = --bufs;
+ pipe->curbuf = curbuf;
+ pipe->nrbufs = --bufs;
do_wakeup = 1;
}
total_len -= chars;
@@ -175,9 +291,9 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
}
if (bufs) /* More to do? */
continue;
- if (!PIPE_WRITERS(*inode))
+ if (!pipe->writers)
break;
- if (!PIPE_WAITING_WRITERS(*inode)) {
+ if (!pipe->waiting_writers) {
/* syscall merging: Usually we must not sleep
* if O_NONBLOCK is set, or if we got some data.
* But if a writer sleeps in kernel space, then
@@ -191,20 +307,22 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
}
}
if (signal_pending(current)) {
- if (!ret) ret = -ERESTARTSYS;
+ if (!ret)
+ ret = -ERESTARTSYS;
break;
}
if (do_wakeup) {
- wake_up_interruptible_sync(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
+ wake_up_interruptible_sync(&pipe->wait);
+ kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
}
- pipe_wait(inode);
+ pipe_wait(pipe);
}
- mutex_unlock(PIPE_MUTEX(*inode));
- /* Signal writers asynchronously that there is more room. */
+ mutex_unlock(&inode->i_mutex);
+
+ /* Signal writers asynchronously that there is more room. */
if (do_wakeup) {
- wake_up_interruptible(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
}
if (ret > 0)
file_accessed(filp);
@@ -215,6 +333,7 @@ static ssize_t
pipe_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
struct iovec iov = { .iov_base = buf, .iov_len = count };
+
return pipe_readv(filp, &iov, 1, ppos);
}
@@ -223,7 +342,7 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
unsigned long nr_segs, loff_t *ppos)
{
struct inode *inode = filp->f_dentry->d_inode;
- struct pipe_inode_info *info;
+ struct pipe_inode_info *pipe;
ssize_t ret;
int do_wakeup;
struct iovec *iov = (struct iovec *)_iov;
@@ -237,10 +356,10 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
do_wakeup = 0;
ret = 0;
- mutex_lock(PIPE_MUTEX(*inode));
- info = inode->i_pipe;
+ mutex_lock(&inode->i_mutex);
+ pipe = inode->i_pipe;
- if (!PIPE_READERS(*inode)) {
+ if (!pipe->readers) {
send_sig(SIGPIPE, current, 0);
ret = -EPIPE;
goto out;
@@ -248,19 +367,36 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
/* We try to merge small writes */
chars = total_len & (PAGE_SIZE-1); /* size of the last buffer */
- if (info->nrbufs && chars != 0) {
- int lastbuf = (info->curbuf + info->nrbufs - 1) & (PIPE_BUFFERS-1);
- struct pipe_buffer *buf = info->bufs + lastbuf;
+ if (pipe->nrbufs && chars != 0) {
+ int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) &
+ (PIPE_BUFFERS-1);
+ struct pipe_buffer *buf = pipe->bufs + lastbuf;
struct pipe_buf_operations *ops = buf->ops;
int offset = buf->offset + buf->len;
+
if (ops->can_merge && offset + chars <= PAGE_SIZE) {
- void *addr = ops->map(filp, info, buf);
- int error = pipe_iov_copy_from_user(offset + addr, iov, chars);
- ops->unmap(info, buf);
+ int error, atomic = 1;
+ void *addr;
+
+ error = ops->pin(pipe, buf);
+ if (error)
+ goto out;
+
+ iov_fault_in_pages_read(iov, chars);
+redo1:
+ addr = ops->map(pipe, buf, atomic);
+ error = pipe_iov_copy_from_user(offset + addr, iov,
+ chars, atomic);
+ ops->unmap(pipe, buf, addr);
ret = error;
do_wakeup = 1;
- if (error)
+ if (error) {
+ if (atomic) {
+ atomic = 0;
+ goto redo1;
+ }
goto out;
+ }
buf->len += chars;
total_len -= chars;
ret = chars;
@@ -271,17 +407,20 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
for (;;) {
int bufs;
- if (!PIPE_READERS(*inode)) {
+
+ if (!pipe->readers) {
send_sig(SIGPIPE, current, 0);
- if (!ret) ret = -EPIPE;
+ if (!ret)
+ ret = -EPIPE;
break;
}
- bufs = info->nrbufs;
+ bufs = pipe->nrbufs;
if (bufs < PIPE_BUFFERS) {
- int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS-1);
- struct pipe_buffer *buf = info->bufs + newbuf;
- struct page *page = info->tmp_page;
- int error;
+ int newbuf = (pipe->curbuf + bufs) & (PIPE_BUFFERS-1);
+ struct pipe_buffer *buf = pipe->bufs + newbuf;
+ struct page *page = pipe->tmp_page;
+ char *src;
+ int error, atomic = 1;
if (!page) {
page = alloc_page(GFP_HIGHUSER);
@@ -289,9 +428,9 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
ret = ret ? : -ENOMEM;
break;
}
- info->tmp_page = page;
+ pipe->tmp_page = page;
}
- /* Always wakeup, even if the copy fails. Otherwise
+ /* Always wake up, even if the copy fails. Otherwise
* we lock up (O_NONBLOCK-)readers that sleep due to
* syscall merging.
* FIXME! Is this really true?
@@ -301,10 +440,27 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
if (chars > total_len)
chars = total_len;
- error = pipe_iov_copy_from_user(kmap(page), iov, chars);
- kunmap(page);
+ iov_fault_in_pages_read(iov, chars);
+redo2:
+ if (atomic)
+ src = kmap_atomic(page, KM_USER0);
+ else
+ src = kmap(page);
+
+ error = pipe_iov_copy_from_user(src, iov, chars,
+ atomic);
+ if (atomic)
+ kunmap_atomic(src, KM_USER0);
+ else
+ kunmap(page);
+
if (unlikely(error)) {
- if (!ret) ret = -EFAULT;
+ if (atomic) {
+ atomic = 0;
+ goto redo2;
+ }
+ if (!ret)
+ ret = error;
break;
}
ret += chars;
@@ -314,8 +470,8 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
buf->ops = &anon_pipe_buf_ops;
buf->offset = 0;
buf->len = chars;
- info->nrbufs = ++bufs;
- info->tmp_page = NULL;
+ pipe->nrbufs = ++bufs;
+ pipe->tmp_page = NULL;
total_len -= chars;
if (!total_len)
@@ -324,27 +480,29 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
if (bufs < PIPE_BUFFERS)
continue;
if (filp->f_flags & O_NONBLOCK) {
- if (!ret) ret = -EAGAIN;
+ if (!ret)
+ ret = -EAGAIN;
break;
}
if (signal_pending(current)) {
- if (!ret) ret = -ERESTARTSYS;
+ if (!ret)
+ ret = -ERESTARTSYS;
break;
}
if (do_wakeup) {
- wake_up_interruptible_sync(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
+ wake_up_interruptible_sync(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
do_wakeup = 0;
}
- PIPE_WAITING_WRITERS(*inode)++;
- pipe_wait(inode);
- PIPE_WAITING_WRITERS(*inode)--;
+ pipe->waiting_writers++;
+ pipe_wait(pipe);
+ pipe->waiting_writers--;
}
out:
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_unlock(&inode->i_mutex);
if (do_wakeup) {
- wake_up_interruptible(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
}
if (ret > 0)
file_update_time(filp);
@@ -356,6 +514,7 @@ pipe_write(struct file *filp, const char __user *buf,
size_t count, loff_t *ppos)
{
struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
+
return pipe_writev(filp, &iov, 1, ppos);
}
@@ -366,7 +525,8 @@ bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
}
static ssize_t
-bad_pipe_w(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
+bad_pipe_w(struct file *filp, const char __user *buf, size_t count,
+ loff_t *ppos)
{
return -EBADF;
}
@@ -376,21 +536,22 @@ pipe_ioctl(struct inode *pino, struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct inode *inode = filp->f_dentry->d_inode;
- struct pipe_inode_info *info;
+ struct pipe_inode_info *pipe;
int count, buf, nrbufs;
switch (cmd) {
case FIONREAD:
- mutex_lock(PIPE_MUTEX(*inode));
- info = inode->i_pipe;
+ mutex_lock(&inode->i_mutex);
+ pipe = inode->i_pipe;
count = 0;
- buf = info->curbuf;
- nrbufs = info->nrbufs;
+ buf = pipe->curbuf;
+ nrbufs = pipe->nrbufs;
while (--nrbufs >= 0) {
- count += info->bufs[buf].len;
+ count += pipe->bufs[buf].len;
buf = (buf+1) & (PIPE_BUFFERS-1);
}
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_unlock(&inode->i_mutex);
+
return put_user(count, (int __user *)arg);
default:
return -EINVAL;
@@ -403,17 +564,17 @@ pipe_poll(struct file *filp, poll_table *wait)
{
unsigned int mask;
struct inode *inode = filp->f_dentry->d_inode;
- struct pipe_inode_info *info = inode->i_pipe;
+ struct pipe_inode_info *pipe = inode->i_pipe;
int nrbufs;
- poll_wait(filp, PIPE_WAIT(*inode), wait);
+ poll_wait(filp, &pipe->wait, wait);
/* Reading only -- no need for acquiring the semaphore. */
- nrbufs = info->nrbufs;
+ nrbufs = pipe->nrbufs;
mask = 0;
if (filp->f_mode & FMODE_READ) {
mask = (nrbufs > 0) ? POLLIN | POLLRDNORM : 0;
- if (!PIPE_WRITERS(*inode) && filp->f_version != PIPE_WCOUNTER(*inode))
+ if (!pipe->writers && filp->f_version != pipe->w_counter)
mask |= POLLHUP;
}
@@ -423,7 +584,7 @@ pipe_poll(struct file *filp, poll_table *wait)
* Most Unices do not set POLLERR for FIFOs but on Linux they
* behave exactly like pipes for poll().
*/
- if (!PIPE_READERS(*inode))
+ if (!pipe->readers)
mask |= POLLERR;
}
@@ -433,17 +594,21 @@ pipe_poll(struct file *filp, poll_table *wait)
static int
pipe_release(struct inode *inode, int decr, int decw)
{
- mutex_lock(PIPE_MUTEX(*inode));
- PIPE_READERS(*inode) -= decr;
- PIPE_WRITERS(*inode) -= decw;
- if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) {
+ struct pipe_inode_info *pipe;
+
+ mutex_lock(&inode->i_mutex);
+ pipe = inode->i_pipe;
+ pipe->readers -= decr;
+ pipe->writers -= decw;
+
+ if (!pipe->readers && !pipe->writers) {
free_pipe_info(inode);
} else {
- wake_up_interruptible(PIPE_WAIT(*inode));
- kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
- kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+ kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
}
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_unlock(&inode->i_mutex);
return 0;
}
@@ -454,9 +619,9 @@ pipe_read_fasync(int fd, struct file *filp, int on)
struct inode *inode = filp->f_dentry->d_inode;
int retval;
- mutex_lock(PIPE_MUTEX(*inode));
- retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode));
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_lock(&inode->i_mutex);
+ retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers);
+ mutex_unlock(&inode->i_mutex);
if (retval < 0)
return retval;
@@ -471,9 +636,9 @@ pipe_write_fasync(int fd, struct file *filp, int on)
struct inode *inode = filp->f_dentry->d_inode;
int retval;
- mutex_lock(PIPE_MUTEX(*inode));
- retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode));
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_lock(&inode->i_mutex);
+ retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers);
+ mutex_unlock(&inode->i_mutex);
if (retval < 0)
return retval;
@@ -486,16 +651,17 @@ static int
pipe_rdwr_fasync(int fd, struct file *filp, int on)
{
struct inode *inode = filp->f_dentry->d_inode;
+ struct pipe_inode_info *pipe = inode->i_pipe;
int retval;
- mutex_lock(PIPE_MUTEX(*inode));
+ mutex_lock(&inode->i_mutex);
- retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode));
+ retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
if (retval >= 0)
- retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode));
+ retval = fasync_helper(fd, filp, on, &pipe->fasync_writers);
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_unlock(&inode->i_mutex);
if (retval < 0)
return retval;
@@ -534,9 +700,9 @@ pipe_read_open(struct inode *inode, struct file *filp)
{
/* We could have perhaps used atomic_t, but this and friends
below are the only places. So it doesn't seem worthwhile. */
- mutex_lock(PIPE_MUTEX(*inode));
- PIPE_READERS(*inode)++;
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_lock(&inode->i_mutex);
+ inode->i_pipe->readers++;
+ mutex_unlock(&inode->i_mutex);
return 0;
}
@@ -544,9 +710,9 @@ pipe_read_open(struct inode *inode, struct file *filp)
static int
pipe_write_open(struct inode *inode, struct file *filp)
{
- mutex_lock(PIPE_MUTEX(*inode));
- PIPE_WRITERS(*inode)++;
- mutex_unlock(PIPE_MUTEX(*inode));
+ mutex_lock(&inode->i_mutex);
+ inode->i_pipe->writers++;
+ mutex_unlock(&inode->i_mutex);
return 0;
}
@@ -554,12 +720,12 @@ pipe_write_open(struct inode *inode, struct file *filp)
static int
pipe_rdwr_open(struct inode *inode, struct file *filp)
{
- mutex_lock(PIPE_MUTEX(*inode));
+ mutex_lock(&inode->i_mutex);
if (filp->f_mode & FMODE_READ)
- PIPE_READERS(*inode)++;
+ inode->i_pipe->readers++;
if (filp->f_mode & FMODE_WRITE)
- PIPE_WRITERS(*inode)++;
- mutex_unlock(PIPE_MUTEX(*inode));
+ inode->i_pipe->writers++;
+ mutex_unlock(&inode->i_mutex);
return 0;
}
@@ -568,7 +734,7 @@ pipe_rdwr_open(struct inode *inode, struct file *filp)
* The file_operations structs are not static because they
* are also used in linux/fs/fifo.c to do operations on FIFOs.
*/
-struct file_operations read_fifo_fops = {
+const struct file_operations read_fifo_fops = {
.llseek = no_llseek,
.read = pipe_read,
.readv = pipe_readv,
@@ -580,7 +746,7 @@ struct file_operations read_fifo_fops = {
.fasync = pipe_read_fasync,
};
-struct file_operations write_fifo_fops = {
+const struct file_operations write_fifo_fops = {
.llseek = no_llseek,
.read = bad_pipe_r,
.write = pipe_write,
@@ -592,7 +758,7 @@ struct file_operations write_fifo_fops = {
.fasync = pipe_write_fasync,
};
-struct file_operations rdwr_fifo_fops = {
+const struct file_operations rdwr_fifo_fops = {
.llseek = no_llseek,
.read = pipe_read,
.readv = pipe_readv,
@@ -642,37 +808,38 @@ static struct file_operations rdwr_pipe_fops = {
.fasync = pipe_rdwr_fasync,
};
-void free_pipe_info(struct inode *inode)
+struct pipe_inode_info * alloc_pipe_info(struct inode *inode)
+{
+ struct pipe_inode_info *pipe;
+
+ pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
+ if (pipe) {
+ init_waitqueue_head(&pipe->wait);
+ pipe->r_counter = pipe->w_counter = 1;
+ pipe->inode = inode;
+ }
+
+ return pipe;
+}
+
+void __free_pipe_info(struct pipe_inode_info *pipe)
{
int i;
- struct pipe_inode_info *info = inode->i_pipe;
- inode->i_pipe = NULL;
for (i = 0; i < PIPE_BUFFERS; i++) {
- struct pipe_buffer *buf = info->bufs + i;
+ struct pipe_buffer *buf = pipe->bufs + i;
if (buf->ops)
- buf->ops->release(info, buf);
+ buf->ops->release(pipe, buf);
}
- if (info->tmp_page)
- __free_page(info->tmp_page);
- kfree(info);
+ if (pipe->tmp_page)
+ __free_page(pipe->tmp_page);
+ kfree(pipe);
}
-struct inode* pipe_new(struct inode* inode)
+void free_pipe_info(struct inode *inode)
{
- struct pipe_inode_info *info;
-
- info = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
- if (!info)
- goto fail_page;
- inode->i_pipe = info;
-
- init_waitqueue_head(PIPE_WAIT(*inode));
- PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1;
-
- return inode;
-fail_page:
- return NULL;
+ __free_pipe_info(inode->i_pipe);
+ inode->i_pipe = NULL;
}
static struct vfsmount *pipe_mnt __read_mostly;
@@ -680,6 +847,7 @@ static int pipefs_delete_dentry(struct dentry *dentry)
{
return 1;
}
+
static struct dentry_operations pipefs_dentry_operations = {
.d_delete = pipefs_delete_dentry,
};
@@ -687,13 +855,17 @@ static struct dentry_operations pipefs_dentry_operations = {
static struct inode * get_pipe_inode(void)
{
struct inode *inode = new_inode(pipe_mnt->mnt_sb);
+ struct pipe_inode_info *pipe;
if (!inode)
goto fail_inode;
- if(!pipe_new(inode))
+ pipe = alloc_pipe_info(inode);
+ if (!pipe)
goto fail_iput;
- PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
+ inode->i_pipe = pipe;
+
+ pipe->readers = pipe->writers = 1;
inode->i_fop = &rdwr_pipe_fops;
/*
@@ -708,10 +880,12 @@ static struct inode * get_pipe_inode(void)
inode->i_gid = current->fsgid;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_blksize = PAGE_SIZE;
+
return inode;
fail_iput:
iput(inode);
+
fail_inode:
return NULL;
}
@@ -724,7 +898,7 @@ int do_pipe(int *fd)
struct inode * inode;
struct file *f1, *f2;
int error;
- int i,j;
+ int i, j;
error = -ENFILE;
f1 = get_empty_filp();
@@ -757,6 +931,7 @@ int do_pipe(int *fd)
dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this);
if (!dentry)
goto close_f12_inode_i_j;
+
dentry->d_op = &pipefs_dentry_operations;
d_add(dentry, inode);
f1->f_vfsmnt = f2->f_vfsmnt = mntget(mntget(pipe_mnt));
@@ -780,6 +955,7 @@ int do_pipe(int *fd)
fd_install(j, f2);
fd[0] = i;
fd[1] = j;
+
return 0;
close_f12_inode_i_j:
@@ -804,8 +980,9 @@ no_files:
* d_name - pipe: will go nicely and kill the special-casing in procfs.
*/
-static struct super_block *pipefs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+static struct super_block *
+pipefs_get_sb(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data)
{
return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC);
}
@@ -819,6 +996,7 @@ static struct file_system_type pipe_fs_type = {
static int __init init_pipe_fs(void)
{
int err = register_filesystem(&pipe_fs_type);
+
if (!err) {
pipe_mnt = kern_mount(&pipe_fs_type);
if (IS_ERR(pipe_mnt)) {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 8f1f49ceebe..6cc77dc3f3f 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -297,16 +297,20 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
files = get_files_struct(task);
if (files) {
- rcu_read_lock();
+ /*
+ * We are not taking a ref to the file structure, so we must
+ * hold ->file_lock.
+ */
+ spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
if (file) {
*mnt = mntget(file->f_vfsmnt);
*dentry = dget(file->f_dentry);
- rcu_read_unlock();
+ spin_unlock(&files->file_lock);
put_files_struct(files);
return 0;
}
- rcu_read_unlock();
+ spin_unlock(&files->file_lock);
put_files_struct(files);
}
return -ENOENT;
@@ -534,12 +538,15 @@ static int proc_oom_score(struct task_struct *task, char *buffer)
/* If the process being read is separated by chroot from the reading process,
* don't let the reader access the threads.
+ *
+ * note: this does dput(root) and mntput(vfsmnt) on exit.
*/
static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt)
{
struct dentry *de, *base;
struct vfsmount *our_vfsmnt, *mnt;
int res = 0;
+
read_lock(&current->fs->lock);
our_vfsmnt = mntget(current->fs->rootmnt);
base = dget(current->fs->root);
@@ -549,11 +556,11 @@ static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt)
de = root;
mnt = vfsmnt;
- while (vfsmnt != our_vfsmnt) {
- if (vfsmnt == vfsmnt->mnt_parent)
+ while (mnt != our_vfsmnt) {
+ if (mnt == mnt->mnt_parent)
goto out;
- de = vfsmnt->mnt_mountpoint;
- vfsmnt = vfsmnt->mnt_parent;
+ de = mnt->mnt_mountpoint;
+ mnt = mnt->mnt_parent;
}
if (!is_subdir(de, base))
@@ -564,7 +571,7 @@ exit:
dput(base);
mntput(our_vfsmnt);
dput(root);
- mntput(mnt);
+ mntput(vfsmnt);
return res;
out:
spin_unlock(&vfsmount_lock);
@@ -1520,7 +1527,12 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
if (!files)
goto out_unlock;
inode->i_mode = S_IFLNK;
- rcu_read_lock();
+
+ /*
+ * We are not taking a ref to the file structure, so we must
+ * hold ->file_lock.
+ */
+ spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
if (!file)
goto out_unlock2;
@@ -1528,7 +1540,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
inode->i_mode |= S_IRUSR | S_IXUSR;
if (file->f_mode & 2)
inode->i_mode |= S_IWUSR | S_IXUSR;
- rcu_read_unlock();
+ spin_unlock(&files->file_lock);
put_files_struct(files);
inode->i_op = &proc_pid_link_inode_operations;
inode->i_size = 64;
@@ -1538,7 +1550,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
return NULL;
out_unlock2:
- rcu_read_unlock();
+ spin_unlock(&files->file_lock);
put_files_struct(files);
out_unlock:
iput(inode);
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 47b7a20d45e..4ba03009cf7 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -560,7 +560,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de)
struct file * filp = list_entry(p, struct file, f_u.fu_list);
struct dentry * dentry = filp->f_dentry;
struct inode * inode;
- struct file_operations *fops;
+ const struct file_operations *fops;
if (dentry->d_op != &proc_dentry_operations)
continue;
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 95a1cf32b83..0502f17b860 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -30,7 +30,7 @@ do { \
#endif
-extern void create_seq_entry(char *name, mode_t mode, struct file_operations *f);
+extern void create_seq_entry(char *name, mode_t mode, const struct file_operations *f);
extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **);
extern int proc_tid_stat(struct task_struct *, char *);
extern int proc_tgid_stat(struct task_struct *, char *);
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index adc2cd95169..17f6e8fa139 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -31,7 +31,7 @@ static int open_kcore(struct inode * inode, struct file * filp)
static ssize_t read_kcore(struct file *, char __user *, size_t, loff_t *);
-struct file_operations proc_kcore_operations = {
+const struct file_operations proc_kcore_operations = {
.read = read_kcore,
.open = open_kcore,
};
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index 10d37bf2520..ff3b90b56e9 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -47,7 +47,7 @@ static unsigned int kmsg_poll(struct file *file, poll_table *wait)
}
-struct file_operations proc_kmsg_operations = {
+const struct file_operations proc_kmsg_operations = {
.read = kmsg_read,
.poll = kmsg_poll,
.open = kmsg_open,
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 596b4b4f1cc..abdf068bc27 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -52,7 +52,8 @@ static int property_read_proc(char *page, char **start, off_t off,
* Add a property to a node
*/
static struct proc_dir_entry *
-__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp)
+__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp,
+ const char *name)
{
struct proc_dir_entry *ent;
@@ -60,14 +61,14 @@ __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp)
* Unfortunately proc_register puts each new entry
* at the beginning of the list. So we rearrange them.
*/
- ent = create_proc_read_entry(pp->name,
- strncmp(pp->name, "security-", 9)
+ ent = create_proc_read_entry(name,
+ strncmp(name, "security-", 9)
? S_IRUGO : S_IRUSR, de,
property_read_proc, pp);
if (ent == NULL)
return NULL;
- if (!strncmp(pp->name, "security-", 9))
+ if (!strncmp(name, "security-", 9))
ent->size = 0; /* don't leak number of password chars */
else
ent->size = pp->length;
@@ -78,7 +79,7 @@ __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp)
void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop)
{
- __proc_device_tree_add_prop(pde, prop);
+ __proc_device_tree_add_prop(pde, prop, prop->name);
}
void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
@@ -106,6 +107,69 @@ void proc_device_tree_update_prop(struct proc_dir_entry *pde,
}
/*
+ * Various dodgy firmware might give us nodes and/or properties with
+ * conflicting names. That's generally ok, except for exporting via /proc,
+ * so munge names here to ensure they're unique.
+ */
+
+static int duplicate_name(struct proc_dir_entry *de, const char *name)
+{
+ struct proc_dir_entry *ent;
+ int found = 0;
+
+ spin_lock(&proc_subdir_lock);
+
+ for (ent = de->subdir; ent != NULL; ent = ent->next) {
+ if (strcmp(ent->name, name) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ spin_unlock(&proc_subdir_lock);
+
+ return found;
+}
+
+static const char *fixup_name(struct device_node *np, struct proc_dir_entry *de,
+ const char *name)
+{
+ char *fixed_name;
+ int fixup_len = strlen(name) + 2 + 1; /* name + #x + \0 */
+ int i = 1, size;
+
+realloc:
+ fixed_name = kmalloc(fixup_len, GFP_KERNEL);
+ if (fixed_name == NULL) {
+ printk(KERN_ERR "device-tree: Out of memory trying to fixup "
+ "name \"%s\"\n", name);
+ return name;
+ }
+
+retry:
+ size = snprintf(fixed_name, fixup_len, "%s#%d", name, i);
+ size++; /* account for NULL */
+
+ if (size > fixup_len) {
+ /* We ran out of space, free and reallocate. */
+ kfree(fixed_name);
+ fixup_len = size;
+ goto realloc;
+ }
+
+ if (duplicate_name(de, fixed_name)) {
+ /* Multiple duplicates. Retry with a different offset. */
+ i++;
+ goto retry;
+ }
+
+ printk(KERN_WARNING "device-tree: Duplicate name in %s, "
+ "renamed to \"%s\"\n", np->full_name, fixed_name);
+
+ return fixed_name;
+}
+
+/*
* Process a node, adding entries for its children and its properties.
*/
void proc_device_tree_add_node(struct device_node *np,
@@ -118,37 +182,30 @@ void proc_device_tree_add_node(struct device_node *np,
set_node_proc_entry(np, de);
for (child = NULL; (child = of_get_next_child(np, child));) {
+ /* Use everything after the last slash, or the full name */
p = strrchr(child->full_name, '/');
if (!p)
p = child->full_name;
else
++p;
+
+ if (duplicate_name(de, p))
+ p = fixup_name(np, de, p);
+
ent = proc_mkdir(p, de);
if (ent == 0)
break;
proc_device_tree_add_node(child, ent);
}
of_node_put(child);
+
for (pp = np->properties; pp != 0; pp = pp->next) {
- /*
- * Yet another Apple device-tree bogosity: on some machines,
- * they have properties & nodes with the same name. Those
- * properties are quite unimportant for us though, thus we
- * simply "skip" them here, but we do have to check.
- */
- spin_lock(&proc_subdir_lock);
- for (ent = de->subdir; ent != NULL; ent = ent->next)
- if (!strcmp(ent->name, pp->name))
- break;
- spin_unlock(&proc_subdir_lock);
- if (ent != NULL) {
- printk(KERN_WARNING "device-tree: property \"%s\" name"
- " conflicts with node in %s\n", pp->name,
- np->full_name);
- continue;
- }
+ p = pp->name;
+
+ if (duplicate_name(de, p))
+ p = fixup_name(np, de, p);
- ent = __proc_device_tree_add_prop(de, pp);
+ ent = __proc_device_tree_add_prop(de, pp, p);
if (ent == 0)
break;
}
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 1e9ea37d457..5c10ea15742 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -249,144 +249,60 @@ static int cpuinfo_open(struct inode *inode, struct file *file)
return seq_open(file, &cpuinfo_op);
}
-enum devinfo_states {
- CHR_HDR,
- CHR_LIST,
- BLK_HDR,
- BLK_LIST,
- DEVINFO_DONE
-};
-
-struct devinfo_state {
- void *chrdev;
- void *blkdev;
- unsigned int num_records;
- unsigned int cur_record;
- enum devinfo_states state;
+static struct file_operations proc_cpuinfo_operations = {
+ .open = cpuinfo_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
};
-static void *devinfo_start(struct seq_file *f, loff_t *pos)
+static int devinfo_show(struct seq_file *f, void *v)
{
- struct devinfo_state *info = f->private;
+ int i = *(loff_t *) v;
- if (*pos) {
- if ((info) && (*pos <= info->num_records))
- return info;
- return NULL;
+ if (i < CHRDEV_MAJOR_HASH_SIZE) {
+ if (i == 0)
+ seq_printf(f, "Character devices:\n");
+ chrdev_show(f, i);
+ } else {
+ i -= CHRDEV_MAJOR_HASH_SIZE;
+ if (i == 0)
+ seq_printf(f, "\nBlock devices:\n");
+ blkdev_show(f, i);
}
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- f->private = info;
- info->chrdev = acquire_chrdev_list();
- info->blkdev = acquire_blkdev_list();
- info->state = CHR_HDR;
- info->num_records = count_chrdev_list();
- info->num_records += count_blkdev_list();
- info->num_records += 2; /* Character and Block headers */
- *pos = 1;
- info->cur_record = *pos;
- return info;
+ return 0;
}
-static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
+static void *devinfo_start(struct seq_file *f, loff_t *pos)
{
- int idummy;
- char *ndummy;
- struct devinfo_state *info = f->private;
-
- switch (info->state) {
- case CHR_HDR:
- info->state = CHR_LIST;
- (*pos)++;
- /*fallthrough*/
- case CHR_LIST:
- if (get_chrdev_info(info->chrdev,&idummy,&ndummy)) {
- /*
- * The character dev list is complete
- */
- info->state = BLK_HDR;
- } else {
- info->chrdev = get_next_chrdev(info->chrdev);
- }
- (*pos)++;
- break;
- case BLK_HDR:
- info->state = BLK_LIST;
- (*pos)++;
- /*fallthrough*/
- case BLK_LIST:
- if (get_blkdev_info(info->blkdev,&idummy,&ndummy)) {
- /*
- * The block dev list is complete
- */
- info->state = DEVINFO_DONE;
- } else {
- info->blkdev = get_next_blkdev(info->blkdev);
- }
- (*pos)++;
- break;
- case DEVINFO_DONE:
- (*pos)++;
- info->cur_record = *pos;
- info = NULL;
- break;
- default:
- break;
- }
- if (info)
- info->cur_record = *pos;
- return info;
+ if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
+ return pos;
+ return NULL;
}
-static void devinfo_stop(struct seq_file *f, void *v)
+static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
{
- struct devinfo_state *info = f->private;
-
- if (info) {
- release_chrdev_list(info->chrdev);
- release_blkdev_list(info->blkdev);
- f->private = NULL;
- kfree(info);
- }
+ (*pos)++;
+ if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
+ return NULL;
+ return pos;
}
-static int devinfo_show(struct seq_file *f, void *arg)
-{
- int major;
- char *name;
- struct devinfo_state *info = f->private;
-
- switch(info->state) {
- case CHR_HDR:
- seq_printf(f,"Character devices:\n");
- /* fallthrough */
- case CHR_LIST:
- if (!get_chrdev_info(info->chrdev,&major,&name))
- seq_printf(f,"%3d %s\n",major,name);
- break;
- case BLK_HDR:
- seq_printf(f,"\nBlock devices:\n");
- /* fallthrough */
- case BLK_LIST:
- if (!get_blkdev_info(info->blkdev,&major,&name))
- seq_printf(f,"%3d %s\n",major,name);
- break;
- default:
- break;
- }
-
- return 0;
+static void devinfo_stop(struct seq_file *f, void *v)
+{
+ /* Nothing to do */
}
-static struct seq_operations devinfo_op = {
- .start = devinfo_start,
- .next = devinfo_next,
- .stop = devinfo_stop,
- .show = devinfo_show,
+static struct seq_operations devinfo_ops = {
+ .start = devinfo_start,
+ .next = devinfo_next,
+ .stop = devinfo_stop,
+ .show = devinfo_show
};
-static int devinfo_open(struct inode *inode, struct file *file)
+static int devinfo_open(struct inode *inode, struct file *filp)
{
- return seq_open(file, &devinfo_op);
+ return seq_open(filp, &devinfo_ops);
}
static struct file_operations proc_devinfo_operations = {
@@ -396,13 +312,6 @@ static struct file_operations proc_devinfo_operations = {
.release = seq_release,
};
-static struct file_operations proc_cpuinfo_operations = {
- .open = cpuinfo_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
extern struct seq_operations vmstat_op;
static int vmstat_open(struct inode *inode, struct file *file)
{
@@ -534,7 +443,7 @@ static int show_stat(struct seq_file *p, void *v)
if (wall_to_monotonic.tv_nsec)
--jif;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
int j;
user = cputime64_add(user, kstat_cpu(i).cpustat.user);
@@ -731,7 +640,7 @@ static struct file_operations proc_sysrq_trigger_operations = {
struct proc_dir_entry *proc_root_kcore;
-void create_seq_entry(char *name, mode_t mode, struct file_operations *f)
+void create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
{
struct proc_dir_entry *entry;
entry = create_proc_entry(name, mode, NULL);
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 4063fb32f78..20d4b2237fc 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -103,8 +103,8 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
size_t buflen, loff_t *fpos)
{
ssize_t acc = 0, tmp;
- size_t tsz, nr_bytes;
- u64 start;
+ size_t tsz;
+ u64 start, nr_bytes;
struct vmcore *curr_m = NULL;
if (buflen == 0 || *fpos >= vmcore_size)
@@ -172,7 +172,7 @@ static int open_vmcore(struct inode *inode, struct file *filp)
return 0;
}
-struct file_operations proc_vmcore_operations = {
+const struct file_operations proc_vmcore_operations = {
.read = read_vmcore,
.open = open_vmcore,
};
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index 7a8f5595c26..9031948fefd 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -81,7 +81,7 @@ out:
return 0;
}
-struct file_operations qnx4_dir_operations =
+const struct file_operations qnx4_dir_operations =
{
.read = generic_read_dir,
.readdir = qnx4_readdir,
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c
index c33963fded9..62af4b1348b 100644
--- a/fs/qnx4/file.c
+++ b/fs/qnx4/file.c
@@ -19,7 +19,7 @@
* We have mostly NULL's here: the current defaults are ok for
* the qnx4 filesystem.
*/
-struct file_operations qnx4_file_operations =
+const struct file_operations qnx4_file_operations =
{
.llseek = generic_file_llseek,
.read = generic_file_read,
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 6ada2095b9a..00a933eb820 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -32,7 +32,7 @@ struct address_space_operations ramfs_aops = {
.commit_write = simple_commit_write
};
-struct file_operations ramfs_file_operations = {
+const struct file_operations ramfs_file_operations = {
.read = generic_file_read,
.write = generic_file_write,
.mmap = generic_file_mmap,
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index b1ca234068f..f443a84b98a 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -33,7 +33,7 @@ struct address_space_operations ramfs_aops = {
.commit_write = simple_commit_write
};
-struct file_operations ramfs_file_operations = {
+const struct file_operations ramfs_file_operations = {
.mmap = ramfs_nommu_mmap,
.get_unmapped_area = ramfs_nommu_get_unmapped_area,
.read = generic_file_read,
diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h
index 272c8a7120b..313237631b4 100644
--- a/fs/ramfs/internal.h
+++ b/fs/ramfs/internal.h
@@ -11,5 +11,5 @@
extern struct address_space_operations ramfs_aops;
-extern struct file_operations ramfs_file_operations;
+extern const struct file_operations ramfs_file_operations;
extern struct inode_operations ramfs_file_inode_operations;
diff --git a/fs/read_write.c b/fs/read_write.c
index 34b1bf259ef..5bc0e9234f9 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -19,7 +19,7 @@
#include <asm/uaccess.h>
#include <asm/unistd.h>
-struct file_operations generic_ro_fops = {
+const struct file_operations generic_ro_fops = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.mmap = generic_file_readonly_mmap,
@@ -202,7 +202,7 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
goto Einval;
inode = file->f_dentry->d_inode;
- if (inode->i_flock && MANDATORY_LOCK(inode)) {
+ if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) {
int retval = locks_mandatory_area(
read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
inode, file, pos, count);
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
index d71ac657928..973c819f803 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -18,7 +18,7 @@ static int reiserfs_readdir(struct file *, void *, filldir_t);
static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
int datasync);
-struct file_operations reiserfs_dir_operations = {
+const struct file_operations reiserfs_dir_operations = {
.read = generic_read_dir,
.readdir = reiserfs_readdir,
.fsync = reiserfs_dir_fsync,
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index d0c1e865963..cf6e1cf4035 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1566,7 +1566,7 @@ static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user * buf,
return generic_file_aio_write(iocb, buf, count, pos);
}
-struct file_operations reiserfs_file_operations = {
+const struct file_operations reiserfs_file_operations = {
.read = generic_file_read,
.write = reiserfs_file_write,
.ioctl = reiserfs_ioctl,
@@ -1576,6 +1576,8 @@ struct file_operations reiserfs_file_operations = {
.sendfile = generic_file_sendfile,
.aio_read = generic_file_aio_read,
.aio_write = reiserfs_aio_write,
+ .splice_read = generic_file_splice_read,
+ .splice_write = generic_file_splice_write,
};
struct inode_operations reiserfs_file_inode_operations = {
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index ef6caed9336..731688e1cfe 100644
--- a/fs/reiserfs/procfs.c
+++ b/fs/reiserfs/procfs.c
@@ -470,7 +470,7 @@ static int r_open(struct inode *inode, struct file *file)
return ret;
}
-static struct file_operations r_file_operations = {
+static const struct file_operations r_file_operations = {
.open = r_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 58c418fbca2..97ae1b92bc4 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -408,8 +408,9 @@ int reiserfs_cache_default_acl(struct inode *inode)
acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
reiserfs_read_unlock_xattrs(inode->i_sb);
reiserfs_read_unlock_xattr_i(inode);
- ret = acl ? 1 : 0;
- posix_acl_release(acl);
+ ret = (acl && !IS_ERR(acl));
+ if (ret)
+ posix_acl_release(acl);
}
return ret;
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index c2fc424d7d5..9b9eda7b335 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -463,7 +463,7 @@ static struct address_space_operations romfs_aops = {
.readpage = romfs_readpage
};
-static struct file_operations romfs_dir_operations = {
+static const struct file_operations romfs_dir_operations = {
.read = generic_read_dir,
.readdir = romfs_readdir,
};
diff --git a/fs/select.c b/fs/select.c
index 1815a57d225..a8109baa5e4 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -29,12 +29,6 @@
#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
-struct poll_table_entry {
- struct file * filp;
- wait_queue_t wait;
- wait_queue_head_t * wait_address;
-};
-
struct poll_table_page {
struct poll_table_page * next;
struct poll_table_entry * entry;
@@ -64,13 +58,23 @@ void poll_initwait(struct poll_wqueues *pwq)
init_poll_funcptr(&pwq->pt, __pollwait);
pwq->error = 0;
pwq->table = NULL;
+ pwq->inline_index = 0;
}
EXPORT_SYMBOL(poll_initwait);
+static void free_poll_entry(struct poll_table_entry *entry)
+{
+ remove_wait_queue(entry->wait_address,&entry->wait);
+ fput(entry->filp);
+}
+
void poll_freewait(struct poll_wqueues *pwq)
{
struct poll_table_page * p = pwq->table;
+ int i;
+ for (i = 0; i < pwq->inline_index; i++)
+ free_poll_entry(pwq->inline_entries + i);
while (p) {
struct poll_table_entry * entry;
struct poll_table_page *old;
@@ -78,8 +82,7 @@ void poll_freewait(struct poll_wqueues *pwq)
entry = p->entry;
do {
entry--;
- remove_wait_queue(entry->wait_address,&entry->wait);
- fput(entry->filp);
+ free_poll_entry(entry);
} while (entry > p->entries);
old = p;
p = p->next;
@@ -89,12 +92,14 @@ void poll_freewait(struct poll_wqueues *pwq)
EXPORT_SYMBOL(poll_freewait);
-static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
- poll_table *_p)
+static struct poll_table_entry *poll_get_entry(poll_table *_p)
{
struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt);
struct poll_table_page *table = p->table;
+ if (p->inline_index < N_INLINE_POLL_ENTRIES)
+ return p->inline_entries + p->inline_index++;
+
if (!table || POLL_TABLE_FULL(table)) {
struct poll_table_page *new_table;
@@ -102,7 +107,7 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
if (!new_table) {
p->error = -ENOMEM;
__set_current_state(TASK_RUNNING);
- return;
+ return NULL;
}
new_table->entry = new_table->entries;
new_table->next = table;
@@ -110,16 +115,21 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
table = new_table;
}
- /* Add a new entry */
- {
- struct poll_table_entry * entry = table->entry;
- table->entry = entry+1;
- get_file(filp);
- entry->filp = filp;
- entry->wait_address = wait_address;
- init_waitqueue_entry(&entry->wait, current);
- add_wait_queue(wait_address,&entry->wait);
- }
+ return table->entry++;
+}
+
+/* Add a new entry */
+static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
+ poll_table *p)
+{
+ struct poll_table_entry *entry = poll_get_entry(p);
+ if (!entry)
+ return;
+ get_file(filp);
+ entry->filp = filp;
+ entry->wait_address = wait_address;
+ init_waitqueue_entry(&entry->wait, current);
+ add_wait_queue(wait_address,&entry->wait);
}
#define FDS_IN(fds, n) (fds->in + n)
@@ -210,7 +220,7 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout)
for (i = 0; i < n; ++rinp, ++routp, ++rexp) {
unsigned long in, out, ex, all_bits, bit = 1, mask, j;
unsigned long res_in = 0, res_out = 0, res_ex = 0;
- struct file_operations *f_op = NULL;
+ const struct file_operations *f_op = NULL;
struct file *file = NULL;
in = *inp++; out = *outp++; ex = *exp++;
@@ -221,17 +231,18 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout)
}
for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) {
+ int fput_needed;
if (i >= n)
break;
if (!(bit & all_bits))
continue;
- file = fget(i);
+ file = fget_light(i, &fput_needed);
if (file) {
f_op = file->f_op;
mask = DEFAULT_POLLMASK;
if (f_op && f_op->poll)
mask = (*f_op->poll)(file, retval ? NULL : wait);
- fput(file);
+ fput_light(file, fput_needed);
if ((mask & POLLIN_SET) && (in & bit)) {
res_in |= bit;
retval++;
@@ -284,16 +295,6 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout)
return retval;
}
-static void *select_bits_alloc(int size)
-{
- return kmalloc(6 * size, GFP_KERNEL);
-}
-
-static void select_bits_free(void *bits, int size)
-{
- kfree(bits);
-}
-
/*
* We can actually return ERESTARTSYS instead of EINTR, but I'd
* like to be certain this leads to no problems. So I return
@@ -309,9 +310,12 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
fd_set __user *exp, s64 *timeout)
{
fd_set_bits fds;
- char *bits;
- int ret, size, max_fdset;
+ void *bits;
+ int ret, max_fdset;
+ unsigned int size;
struct fdtable *fdt;
+ /* Allocate small arguments on the stack to save memory and be faster */
+ long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
ret = -EINVAL;
if (n < 0)
@@ -330,17 +334,21 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
* since we used fdset we need to allocate memory in units of
* long-words.
*/
- ret = -ENOMEM;
size = FDS_BYTES(n);
- bits = select_bits_alloc(size);
- if (!bits)
- goto out_nofds;
- fds.in = (unsigned long *) bits;
- fds.out = (unsigned long *) (bits + size);
- fds.ex = (unsigned long *) (bits + 2*size);
- fds.res_in = (unsigned long *) (bits + 3*size);
- fds.res_out = (unsigned long *) (bits + 4*size);
- fds.res_ex = (unsigned long *) (bits + 5*size);
+ bits = stack_fds;
+ if (size > sizeof(stack_fds) / 6) {
+ /* Not enough space in on-stack array; must use kmalloc */
+ ret = -ENOMEM;
+ bits = kmalloc(6 * size, GFP_KERNEL);
+ if (!bits)
+ goto out_nofds;
+ }
+ fds.in = bits;
+ fds.out = bits + size;
+ fds.ex = bits + 2*size;
+ fds.res_in = bits + 3*size;
+ fds.res_out = bits + 4*size;
+ fds.res_ex = bits + 5*size;
if ((ret = get_fd_set(n, inp, fds.in)) ||
(ret = get_fd_set(n, outp, fds.out)) ||
@@ -367,7 +375,8 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
ret = -EFAULT;
out:
- select_bits_free(bits, size);
+ if (bits != stack_fds)
+ kfree(bits);
out_nofds:
return ret;
}
@@ -551,14 +560,15 @@ static void do_pollfd(unsigned int num, struct pollfd * fdpage,
fdp = fdpage+i;
fd = fdp->fd;
if (fd >= 0) {
- struct file * file = fget(fd);
+ int fput_needed;
+ struct file * file = fget_light(fd, &fput_needed);
mask = POLLNVAL;
if (file != NULL) {
mask = DEFAULT_POLLMASK;
if (file->f_op && file->f_op->poll)
mask = file->f_op->poll(file, *pwait);
mask &= fdp->events | POLLERR | POLLHUP;
- fput(file);
+ fput_light(file, fput_needed);
}
if (mask) {
*pwait = NULL;
@@ -619,6 +629,9 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
return count;
}
+#define N_STACK_PPS ((sizeof(stack_pps) - sizeof(struct poll_list)) / \
+ sizeof(struct pollfd))
+
int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
{
struct poll_wqueues table;
@@ -628,6 +641,11 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
struct poll_list *walk;
struct fdtable *fdt;
int max_fdset;
+ /* Allocate small arguments on the stack to save memory and be
+ faster - use long to make sure the buffer is aligned properly
+ on 64 bit archs to avoid unaligned access */
+ long stack_pps[POLL_STACK_ALLOC/sizeof(long)];
+ struct poll_list *stack_pp = NULL;
/* Do a sanity check on nfds ... */
rcu_read_lock();
@@ -645,14 +663,23 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
err = -ENOMEM;
while(i!=0) {
struct poll_list *pp;
- pp = kmalloc(sizeof(struct poll_list)+
- sizeof(struct pollfd)*
- (i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i),
- GFP_KERNEL);
- if(pp==NULL)
- goto out_fds;
+ int num, size;
+ if (stack_pp == NULL)
+ num = N_STACK_PPS;
+ else
+ num = POLLFD_PER_PAGE;
+ if (num > i)
+ num = i;
+ size = sizeof(struct poll_list) + sizeof(struct pollfd)*num;
+ if (!stack_pp)
+ stack_pp = pp = (struct poll_list *)stack_pps;
+ else {
+ pp = kmalloc(size, GFP_KERNEL);
+ if (!pp)
+ goto out_fds;
+ }
pp->next=NULL;
- pp->len = (i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i);
+ pp->len = num;
if (head == NULL)
head = pp;
else
@@ -660,7 +687,7 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
walk = pp;
if (copy_from_user(pp->entries, ufds + nfds-i,
- sizeof(struct pollfd)*pp->len)) {
+ sizeof(struct pollfd)*num)) {
err = -EFAULT;
goto out_fds;
}
@@ -689,7 +716,8 @@ out_fds:
walk = head;
while(walk!=NULL) {
struct poll_list *pp = walk->next;
- kfree(walk);
+ if (walk != stack_pp)
+ kfree(walk);
walk = pp;
}
poll_freewait(&table);
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index 0424d06b147..70d9c5a37f5 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -34,7 +34,7 @@ static int smb_rename(struct inode *, struct dentry *,
static int smb_make_node(struct inode *,struct dentry *,int,dev_t);
static int smb_link(struct dentry *, struct inode *, struct dentry *);
-struct file_operations smb_dir_operations =
+const struct file_operations smb_dir_operations =
{
.read = generic_read_dir,
.readdir = smb_readdir,
@@ -434,6 +434,11 @@ smb_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
if (dentry->d_name.len > SMB_MAXNAMELEN)
goto out;
+ /* Do not allow lookup of names with backslashes in */
+ error = -EINVAL;
+ if (memchr(dentry->d_name.name, '\\', dentry->d_name.len))
+ goto out;
+
lock_kernel();
error = smb_proc_getattr(dentry, &finfo);
#ifdef SMBFS_PARANOIA
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index 7042e62726a..ed9a24d19d7 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -178,11 +178,9 @@ smb_writepage(struct page *page, struct writeback_control *wbc)
unsigned offset = PAGE_CACHE_SIZE;
int err;
- if (!mapping)
- BUG();
+ BUG_ON(!mapping);
inode = mapping->host;
- if (!inode)
- BUG();
+ BUG_ON(!inode);
end_index = inode->i_size >> PAGE_CACHE_SHIFT;
@@ -401,7 +399,7 @@ smb_file_permission(struct inode *inode, int mask, struct nameidata *nd)
return error;
}
-struct file_operations smb_file_operations =
+const struct file_operations smb_file_operations =
{
.llseek = remote_llseek,
.read = smb_file_read,
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h
index e866ec8660d..47664597e6b 100644
--- a/fs/smbfs/proto.h
+++ b/fs/smbfs/proto.h
@@ -35,7 +35,7 @@ extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const
extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry);
extern void smb_install_null_ops(struct smb_ops *ops);
/* dir.c */
-extern struct file_operations smb_dir_operations;
+extern const struct file_operations smb_dir_operations;
extern struct inode_operations smb_dir_inode_operations;
extern struct inode_operations smb_dir_inode_operations_unix;
extern void smb_new_dentry(struct dentry *dentry);
@@ -64,7 +64,7 @@ extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
/* file.c */
extern struct address_space_operations smb_file_aops;
-extern struct file_operations smb_file_operations;
+extern const struct file_operations smb_file_operations;
extern struct inode_operations smb_file_inode_operations;
/* ioctl.c */
extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c
index c71c375863c..c71dd2760d3 100644
--- a/fs/smbfs/request.c
+++ b/fs/smbfs/request.c
@@ -339,9 +339,11 @@ int smb_add_request(struct smb_request *req)
/*
* On timeout or on interrupt we want to try and remove the
* request from the recvq/xmitq.
+ * First check if the request is still part of a queue. (May
+ * have been removed by some error condition)
*/
smb_lock_server(server);
- if (!(req->rq_flags & SMB_REQ_RECEIVED)) {
+ if (!list_empty(&req->rq_queue)) {
list_del_init(&req->rq_queue);
smb_rput(req);
}
diff --git a/fs/splice.c b/fs/splice.c
new file mode 100644
index 00000000000..a285fd746dc
--- /dev/null
+++ b/fs/splice.c
@@ -0,0 +1,1490 @@
+/*
+ * "splice": joining two ropes together by interweaving their strands.
+ *
+ * This is the "extended pipe" functionality, where a pipe is used as
+ * an arbitrary in-memory buffer. Think of a pipe as a small kernel
+ * buffer that you can use to transfer data from one end to the other.
+ *
+ * The traditional unix read/write is extended with a "splice()" operation
+ * that transfers data buffers to or from a pipe buffer.
+ *
+ * Named by Larry McVoy, original implementation from Linus, extended by
+ * Jens to support splicing to files, network, direct splicing, etc and
+ * fixing lots of bugs.
+ *
+ * Copyright (C) 2005-2006 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2005-2006 Linus Torvalds <torvalds@osdl.org>
+ * Copyright (C) 2006 Ingo Molnar <mingo@elte.hu>
+ *
+ */
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/pagemap.h>
+#include <linux/pipe_fs_i.h>
+#include <linux/mm_inline.h>
+#include <linux/swap.h>
+#include <linux/writeback.h>
+#include <linux/buffer_head.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/uio.h>
+
+struct partial_page {
+ unsigned int offset;
+ unsigned int len;
+};
+
+/*
+ * Passed to splice_to_pipe
+ */
+struct splice_pipe_desc {
+ struct page **pages; /* page map */
+ struct partial_page *partial; /* pages[] may not be contig */
+ int nr_pages; /* number of pages in map */
+ unsigned int flags; /* splice flags */
+ struct pipe_buf_operations *ops;/* ops associated with output pipe */
+};
+
+/*
+ * Attempt to steal a page from a pipe buffer. This should perhaps go into
+ * a vm helper function, it's already simplified quite a bit by the
+ * addition of remove_mapping(). If success is returned, the caller may
+ * attempt to reuse this page for another destination.
+ */
+static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+{
+ struct page *page = buf->page;
+ struct address_space *mapping = page_mapping(page);
+
+ lock_page(page);
+
+ WARN_ON(!PageUptodate(page));
+
+ /*
+ * At least for ext2 with nobh option, we need to wait on writeback
+ * completing on this page, since we'll remove it from the pagecache.
+ * Otherwise truncate wont wait on the page, allowing the disk
+ * blocks to be reused by someone else before we actually wrote our
+ * data to them. fs corruption ensues.
+ */
+ wait_on_page_writeback(page);
+
+ if (PagePrivate(page))
+ try_to_release_page(page, mapping_gfp_mask(mapping));
+
+ if (!remove_mapping(mapping, page)) {
+ unlock_page(page);
+ return 1;
+ }
+
+ buf->flags |= PIPE_BUF_FLAG_LRU;
+ return 0;
+}
+
+static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+{
+ page_cache_release(buf->page);
+ buf->flags &= ~PIPE_BUF_FLAG_LRU;
+}
+
+static int page_cache_pipe_buf_pin(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+{
+ struct page *page = buf->page;
+ int err;
+
+ if (!PageUptodate(page)) {
+ lock_page(page);
+
+ /*
+ * Page got truncated/unhashed. This will cause a 0-byte
+ * splice, if this is the first page.
+ */
+ if (!page->mapping) {
+ err = -ENODATA;
+ goto error;
+ }
+
+ /*
+ * Uh oh, read-error from disk.
+ */
+ if (!PageUptodate(page)) {
+ err = -EIO;
+ goto error;
+ }
+
+ /*
+ * Page is ok afterall, we are done.
+ */
+ unlock_page(page);
+ }
+
+ return 0;
+error:
+ unlock_page(page);
+ return err;
+}
+
+static struct pipe_buf_operations page_cache_pipe_buf_ops = {
+ .can_merge = 0,
+ .map = generic_pipe_buf_map,
+ .unmap = generic_pipe_buf_unmap,
+ .pin = page_cache_pipe_buf_pin,
+ .release = page_cache_pipe_buf_release,
+ .steal = page_cache_pipe_buf_steal,
+ .get = generic_pipe_buf_get,
+};
+
+static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+{
+ if (!(buf->flags & PIPE_BUF_FLAG_GIFT))
+ return 1;
+
+ buf->flags |= PIPE_BUF_FLAG_LRU;
+ return generic_pipe_buf_steal(pipe, buf);
+}
+
+static struct pipe_buf_operations user_page_pipe_buf_ops = {
+ .can_merge = 0,
+ .map = generic_pipe_buf_map,
+ .unmap = generic_pipe_buf_unmap,
+ .pin = generic_pipe_buf_pin,
+ .release = page_cache_pipe_buf_release,
+ .steal = user_page_pipe_buf_steal,
+ .get = generic_pipe_buf_get,
+};
+
+/*
+ * Pipe output worker. This sets up our pipe format with the page cache
+ * pipe buffer operations. Otherwise very similar to the regular pipe_writev().
+ */
+static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
+ struct splice_pipe_desc *spd)
+{
+ int ret, do_wakeup, page_nr;
+
+ ret = 0;
+ do_wakeup = 0;
+ page_nr = 0;
+
+ if (pipe->inode)
+ mutex_lock(&pipe->inode->i_mutex);
+
+ for (;;) {
+ if (!pipe->readers) {
+ send_sig(SIGPIPE, current, 0);
+ if (!ret)
+ ret = -EPIPE;
+ break;
+ }
+
+ if (pipe->nrbufs < PIPE_BUFFERS) {
+ int newbuf = (pipe->curbuf + pipe->nrbufs) & (PIPE_BUFFERS - 1);
+ struct pipe_buffer *buf = pipe->bufs + newbuf;
+
+ buf->page = spd->pages[page_nr];
+ buf->offset = spd->partial[page_nr].offset;
+ buf->len = spd->partial[page_nr].len;
+ buf->ops = spd->ops;
+ if (spd->flags & SPLICE_F_GIFT)
+ buf->flags |= PIPE_BUF_FLAG_GIFT;
+
+ pipe->nrbufs++;
+ page_nr++;
+ ret += buf->len;
+
+ if (pipe->inode)
+ do_wakeup = 1;
+
+ if (!--spd->nr_pages)
+ break;
+ if (pipe->nrbufs < PIPE_BUFFERS)
+ continue;
+
+ break;
+ }
+
+ if (spd->flags & SPLICE_F_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
+
+ if (do_wakeup) {
+ smp_mb();
+ if (waitqueue_active(&pipe->wait))
+ wake_up_interruptible_sync(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+ do_wakeup = 0;
+ }
+
+ pipe->waiting_writers++;
+ pipe_wait(pipe);
+ pipe->waiting_writers--;
+ }
+
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
+
+ if (do_wakeup) {
+ smp_mb();
+ if (waitqueue_active(&pipe->wait))
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+ }
+
+ while (page_nr < spd->nr_pages)
+ page_cache_release(spd->pages[page_nr++]);
+
+ return ret;
+}
+
+static int
+__generic_file_splice_read(struct file *in, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags)
+{
+ struct address_space *mapping = in->f_mapping;
+ unsigned int loff, nr_pages;
+ struct page *pages[PIPE_BUFFERS];
+ struct partial_page partial[PIPE_BUFFERS];
+ struct page *page;
+ pgoff_t index, end_index;
+ loff_t isize;
+ size_t total_len;
+ int error, page_nr;
+ struct splice_pipe_desc spd = {
+ .pages = pages,
+ .partial = partial,
+ .flags = flags,
+ .ops = &page_cache_pipe_buf_ops,
+ };
+
+ index = *ppos >> PAGE_CACHE_SHIFT;
+ loff = *ppos & ~PAGE_CACHE_MASK;
+ nr_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
+ if (nr_pages > PIPE_BUFFERS)
+ nr_pages = PIPE_BUFFERS;
+
+ /*
+ * Initiate read-ahead on this page range. however, don't call into
+ * read-ahead if this is a non-zero offset (we are likely doing small
+ * chunk splice and the page is already there) for a single page.
+ */
+ if (!loff || nr_pages > 1)
+ page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
+
+ /*
+ * Now fill in the holes:
+ */
+ error = 0;
+ total_len = 0;
+
+ /*
+ * Lookup the (hopefully) full range of pages we need.
+ */
+ spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, pages);
+
+ /*
+ * If find_get_pages_contig() returned fewer pages than we needed,
+ * allocate the rest.
+ */
+ index += spd.nr_pages;
+ while (spd.nr_pages < nr_pages) {
+ /*
+ * Page could be there, find_get_pages_contig() breaks on
+ * the first hole.
+ */
+ page = find_get_page(mapping, index);
+ if (!page) {
+ /*
+ * Make sure the read-ahead engine is notified
+ * about this failure.
+ */
+ handle_ra_miss(mapping, &in->f_ra, index);
+
+ /*
+ * page didn't exist, allocate one.
+ */
+ page = page_cache_alloc_cold(mapping);
+ if (!page)
+ break;
+
+ error = add_to_page_cache_lru(page, mapping, index,
+ mapping_gfp_mask(mapping));
+ if (unlikely(error)) {
+ page_cache_release(page);
+ if (error == -EEXIST)
+ continue;
+ break;
+ }
+ /*
+ * add_to_page_cache() locks the page, unlock it
+ * to avoid convoluting the logic below even more.
+ */
+ unlock_page(page);
+ }
+
+ pages[spd.nr_pages++] = page;
+ index++;
+ }
+
+ /*
+ * Now loop over the map and see if we need to start IO on any
+ * pages, fill in the partial map, etc.
+ */
+ index = *ppos >> PAGE_CACHE_SHIFT;
+ nr_pages = spd.nr_pages;
+ spd.nr_pages = 0;
+ for (page_nr = 0; page_nr < nr_pages; page_nr++) {
+ unsigned int this_len;
+
+ if (!len)
+ break;
+
+ /*
+ * this_len is the max we'll use from this page
+ */
+ this_len = min_t(unsigned long, len, PAGE_CACHE_SIZE - loff);
+ page = pages[page_nr];
+
+ /*
+ * If the page isn't uptodate, we may need to start io on it
+ */
+ if (!PageUptodate(page)) {
+ /*
+ * If in nonblock mode then dont block on waiting
+ * for an in-flight io page
+ */
+ if (flags & SPLICE_F_NONBLOCK)
+ break;
+
+ lock_page(page);
+
+ /*
+ * page was truncated, stop here. if this isn't the
+ * first page, we'll just complete what we already
+ * added
+ */
+ if (!page->mapping) {
+ unlock_page(page);
+ break;
+ }
+ /*
+ * page was already under io and is now done, great
+ */
+ if (PageUptodate(page)) {
+ unlock_page(page);
+ goto fill_it;
+ }
+
+ /*
+ * need to read in the page
+ */
+ error = mapping->a_ops->readpage(in, page);
+ if (unlikely(error)) {
+ /*
+ * We really should re-lookup the page here,
+ * but it complicates things a lot. Instead
+ * lets just do what we already stored, and
+ * we'll get it the next time we are called.
+ */
+ if (error == AOP_TRUNCATED_PAGE)
+ error = 0;
+
+ break;
+ }
+
+ /*
+ * i_size must be checked after ->readpage().
+ */
+ isize = i_size_read(mapping->host);
+ end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+ if (unlikely(!isize || index > end_index))
+ break;
+
+ /*
+ * if this is the last page, see if we need to shrink
+ * the length and stop
+ */
+ if (end_index == index) {
+ loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK);
+ if (total_len + loff > isize)
+ break;
+ /*
+ * force quit after adding this page
+ */
+ len = this_len;
+ this_len = min(this_len, loff);
+ loff = 0;
+ }
+ }
+fill_it:
+ partial[page_nr].offset = loff;
+ partial[page_nr].len = this_len;
+ len -= this_len;
+ total_len += this_len;
+ loff = 0;
+ spd.nr_pages++;
+ index++;
+ }
+
+ /*
+ * Release any pages at the end, if we quit early. 'i' is how far
+ * we got, 'nr_pages' is how many pages are in the map.
+ */
+ while (page_nr < nr_pages)
+ page_cache_release(pages[page_nr++]);
+
+ if (spd.nr_pages)
+ return splice_to_pipe(pipe, &spd);
+
+ return error;
+}
+
+/**
+ * generic_file_splice_read - splice data from file to a pipe
+ * @in: file to splice from
+ * @pipe: pipe to splice to
+ * @len: number of bytes to splice
+ * @flags: splice modifier flags
+ *
+ * Will read pages from given file and fill them into a pipe.
+ */
+ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags)
+{
+ ssize_t spliced;
+ int ret;
+
+ ret = 0;
+ spliced = 0;
+
+ while (len) {
+ ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
+
+ if (ret < 0)
+ break;
+ else if (!ret) {
+ if (spliced)
+ break;
+ if (flags & SPLICE_F_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+ }
+
+ *ppos += ret;
+ len -= ret;
+ spliced += ret;
+ }
+
+ if (spliced)
+ return spliced;
+
+ return ret;
+}
+
+EXPORT_SYMBOL(generic_file_splice_read);
+
+/*
+ * Send 'sd->len' bytes to socket from 'sd->file' at position 'sd->pos'
+ * using sendpage(). Return the number of bytes sent.
+ */
+static int pipe_to_sendpage(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf, struct splice_desc *sd)
+{
+ struct file *file = sd->file;
+ loff_t pos = sd->pos;
+ int ret, more;
+
+ ret = buf->ops->pin(pipe, buf);
+ if (!ret) {
+ more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
+
+ ret = file->f_op->sendpage(file, buf->page, buf->offset,
+ sd->len, &pos, more);
+ }
+
+ return ret;
+}
+
+/*
+ * This is a little more tricky than the file -> pipe splicing. There are
+ * basically three cases:
+ *
+ * - Destination page already exists in the address space and there
+ * are users of it. For that case we have no other option that
+ * copying the data. Tough luck.
+ * - Destination page already exists in the address space, but there
+ * are no users of it. Make sure it's uptodate, then drop it. Fall
+ * through to last case.
+ * - Destination page does not exist, we can add the pipe page to
+ * the page cache and avoid the copy.
+ *
+ * If asked to move pages to the output file (SPLICE_F_MOVE is set in
+ * sd->flags), we attempt to migrate pages from the pipe to the output
+ * file address space page cache. This is possible if no one else has
+ * the pipe page referenced outside of the pipe and page cache. If
+ * SPLICE_F_MOVE isn't set, or we cannot move the page, we simply create
+ * a new page in the output file page cache and fill/dirty that.
+ */
+static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+ struct splice_desc *sd)
+{
+ struct file *file = sd->file;
+ struct address_space *mapping = file->f_mapping;
+ gfp_t gfp_mask = mapping_gfp_mask(mapping);
+ unsigned int offset, this_len;
+ struct page *page;
+ pgoff_t index;
+ int ret;
+
+ /*
+ * make sure the data in this buffer is uptodate
+ */
+ ret = buf->ops->pin(pipe, buf);
+ if (unlikely(ret))
+ return ret;
+
+ index = sd->pos >> PAGE_CACHE_SHIFT;
+ offset = sd->pos & ~PAGE_CACHE_MASK;
+
+ this_len = sd->len;
+ if (this_len + offset > PAGE_CACHE_SIZE)
+ this_len = PAGE_CACHE_SIZE - offset;
+
+ /*
+ * Reuse buf page, if SPLICE_F_MOVE is set and we are doing a full
+ * page.
+ */
+ if ((sd->flags & SPLICE_F_MOVE) && this_len == PAGE_CACHE_SIZE) {
+ /*
+ * If steal succeeds, buf->page is now pruned from the
+ * pagecache and we can reuse it. The page will also be
+ * locked on successful return.
+ */
+ if (buf->ops->steal(pipe, buf))
+ goto find_page;
+
+ page = buf->page;
+ if (add_to_page_cache(page, mapping, index, gfp_mask)) {
+ unlock_page(page);
+ goto find_page;
+ }
+
+ page_cache_get(page);
+
+ if (!(buf->flags & PIPE_BUF_FLAG_LRU))
+ lru_cache_add(page);
+ } else {
+find_page:
+ page = find_lock_page(mapping, index);
+ if (!page) {
+ ret = -ENOMEM;
+ page = page_cache_alloc_cold(mapping);
+ if (unlikely(!page))
+ goto out_nomem;
+
+ /*
+ * This will also lock the page
+ */
+ ret = add_to_page_cache_lru(page, mapping, index,
+ gfp_mask);
+ if (unlikely(ret))
+ goto out;
+ }
+
+ /*
+ * We get here with the page locked. If the page is also
+ * uptodate, we don't need to do more. If it isn't, we
+ * may need to bring it in if we are not going to overwrite
+ * the full page.
+ */
+ if (!PageUptodate(page)) {
+ if (this_len < PAGE_CACHE_SIZE) {
+ ret = mapping->a_ops->readpage(file, page);
+ if (unlikely(ret))
+ goto out;
+
+ lock_page(page);
+
+ if (!PageUptodate(page)) {
+ /*
+ * Page got invalidated, repeat.
+ */
+ if (!page->mapping) {
+ unlock_page(page);
+ page_cache_release(page);
+ goto find_page;
+ }
+ ret = -EIO;
+ goto out;
+ }
+ } else
+ SetPageUptodate(page);
+ }
+ }
+
+ ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len);
+ if (unlikely(ret)) {
+ loff_t isize = i_size_read(mapping->host);
+
+ if (ret != AOP_TRUNCATED_PAGE)
+ unlock_page(page);
+ page_cache_release(page);
+ if (ret == AOP_TRUNCATED_PAGE)
+ goto find_page;
+
+ /*
+ * prepare_write() may have instantiated a few blocks
+ * outside i_size. Trim these off again.
+ */
+ if (sd->pos + this_len > isize)
+ vmtruncate(mapping->host, isize);
+
+ goto out;
+ }
+
+ if (buf->page != page) {
+ /*
+ * Careful, ->map() uses KM_USER0!
+ */
+ char *src = buf->ops->map(pipe, buf, 1);
+ char *dst = kmap_atomic(page, KM_USER1);
+
+ memcpy(dst + offset, src + buf->offset, this_len);
+ flush_dcache_page(page);
+ kunmap_atomic(dst, KM_USER1);
+ buf->ops->unmap(pipe, buf, src);
+ }
+
+ ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len);
+ if (!ret) {
+ /*
+ * Return the number of bytes written and mark page as
+ * accessed, we are now done!
+ */
+ ret = this_len;
+ mark_page_accessed(page);
+ balance_dirty_pages_ratelimited(mapping);
+ } else if (ret == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ goto find_page;
+ }
+out:
+ page_cache_release(page);
+ unlock_page(page);
+out_nomem:
+ return ret;
+}
+
+/*
+ * Pipe input worker. Most of this logic works like a regular pipe, the
+ * key here is the 'actor' worker passed in that actually moves the data
+ * to the wanted destination. See pipe_to_file/pipe_to_sendpage above.
+ */
+ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags,
+ splice_actor *actor)
+{
+ int ret, do_wakeup, err;
+ struct splice_desc sd;
+
+ ret = 0;
+ do_wakeup = 0;
+
+ sd.total_len = len;
+ sd.flags = flags;
+ sd.file = out;
+ sd.pos = *ppos;
+
+ if (pipe->inode)
+ mutex_lock(&pipe->inode->i_mutex);
+
+ for (;;) {
+ if (pipe->nrbufs) {
+ struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
+ struct pipe_buf_operations *ops = buf->ops;
+
+ sd.len = buf->len;
+ if (sd.len > sd.total_len)
+ sd.len = sd.total_len;
+
+ err = actor(pipe, buf, &sd);
+ if (err <= 0) {
+ if (!ret && err != -ENODATA)
+ ret = err;
+
+ break;
+ }
+
+ ret += err;
+ buf->offset += err;
+ buf->len -= err;
+
+ sd.len -= err;
+ sd.pos += err;
+ sd.total_len -= err;
+ if (sd.len)
+ continue;
+
+ if (!buf->len) {
+ buf->ops = NULL;
+ ops->release(pipe, buf);
+ pipe->curbuf = (pipe->curbuf + 1) & (PIPE_BUFFERS - 1);
+ pipe->nrbufs--;
+ if (pipe->inode)
+ do_wakeup = 1;
+ }
+
+ if (!sd.total_len)
+ break;
+ }
+
+ if (pipe->nrbufs)
+ continue;
+ if (!pipe->writers)
+ break;
+ if (!pipe->waiting_writers) {
+ if (ret)
+ break;
+ }
+
+ if (flags & SPLICE_F_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
+
+ if (do_wakeup) {
+ smp_mb();
+ if (waitqueue_active(&pipe->wait))
+ wake_up_interruptible_sync(&pipe->wait);
+ kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
+ do_wakeup = 0;
+ }
+
+ pipe_wait(pipe);
+ }
+
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
+
+ if (do_wakeup) {
+ smp_mb();
+ if (waitqueue_active(&pipe->wait))
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
+ }
+
+ return ret;
+}
+
+/**
+ * generic_file_splice_write - splice data from a pipe to a file
+ * @pipe: pipe info
+ * @out: file to write to
+ * @len: number of bytes to splice
+ * @flags: splice modifier flags
+ *
+ * Will either move or copy pages (determined by @flags options) from
+ * the given pipe inode to the given file.
+ *
+ */
+ssize_t
+generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags)
+{
+ struct address_space *mapping = out->f_mapping;
+ ssize_t ret;
+
+ ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
+ if (ret > 0) {
+ struct inode *inode = mapping->host;
+
+ *ppos += ret;
+
+ /*
+ * If file or inode is SYNC and we actually wrote some data,
+ * sync it.
+ */
+ if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
+ int err;
+
+ mutex_lock(&inode->i_mutex);
+ err = generic_osync_inode(inode, mapping,
+ OSYNC_METADATA|OSYNC_DATA);
+ mutex_unlock(&inode->i_mutex);
+
+ if (err)
+ ret = err;
+ }
+ }
+
+ return ret;
+}
+
+EXPORT_SYMBOL(generic_file_splice_write);
+
+/**
+ * generic_splice_sendpage - splice data from a pipe to a socket
+ * @inode: pipe inode
+ * @out: socket to write to
+ * @len: number of bytes to splice
+ * @flags: splice modifier flags
+ *
+ * Will send @len bytes from the pipe to a network socket. No data copying
+ * is involved.
+ *
+ */
+ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags)
+{
+ return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_sendpage);
+}
+
+EXPORT_SYMBOL(generic_splice_sendpage);
+
+/*
+ * Attempt to initiate a splice from pipe to file.
+ */
+static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags)
+{
+ int ret;
+
+ if (unlikely(!out->f_op || !out->f_op->splice_write))
+ return -EINVAL;
+
+ if (unlikely(!(out->f_mode & FMODE_WRITE)))
+ return -EBADF;
+
+ ret = rw_verify_area(WRITE, out, ppos, len);
+ if (unlikely(ret < 0))
+ return ret;
+
+ return out->f_op->splice_write(pipe, out, ppos, len, flags);
+}
+
+/*
+ * Attempt to initiate a splice from a file to a pipe.
+ */
+static long do_splice_to(struct file *in, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags)
+{
+ loff_t isize, left;
+ int ret;
+
+ if (unlikely(!in->f_op || !in->f_op->splice_read))
+ return -EINVAL;
+
+ if (unlikely(!(in->f_mode & FMODE_READ)))
+ return -EBADF;
+
+ ret = rw_verify_area(READ, in, ppos, len);
+ if (unlikely(ret < 0))
+ return ret;
+
+ isize = i_size_read(in->f_mapping->host);
+ if (unlikely(*ppos >= isize))
+ return 0;
+
+ left = isize - *ppos;
+ if (unlikely(left < len))
+ len = left;
+
+ return in->f_op->splice_read(in, ppos, pipe, len, flags);
+}
+
+long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+ size_t len, unsigned int flags)
+{
+ struct pipe_inode_info *pipe;
+ long ret, bytes;
+ loff_t out_off;
+ umode_t i_mode;
+ int i;
+
+ /*
+ * We require the input being a regular file, as we don't want to
+ * randomly drop data for eg socket -> socket splicing. Use the
+ * piped splicing for that!
+ */
+ i_mode = in->f_dentry->d_inode->i_mode;
+ if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode)))
+ return -EINVAL;
+
+ /*
+ * neither in nor out is a pipe, setup an internal pipe attached to
+ * 'out' and transfer the wanted data from 'in' to 'out' through that
+ */
+ pipe = current->splice_pipe;
+ if (unlikely(!pipe)) {
+ pipe = alloc_pipe_info(NULL);
+ if (!pipe)
+ return -ENOMEM;
+
+ /*
+ * We don't have an immediate reader, but we'll read the stuff
+ * out of the pipe right after the splice_to_pipe(). So set
+ * PIPE_READERS appropriately.
+ */
+ pipe->readers = 1;
+
+ current->splice_pipe = pipe;
+ }
+
+ /*
+ * Do the splice.
+ */
+ ret = 0;
+ bytes = 0;
+ out_off = 0;
+
+ while (len) {
+ size_t read_len, max_read_len;
+
+ /*
+ * Do at most PIPE_BUFFERS pages worth of transfer:
+ */
+ max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
+
+ ret = do_splice_to(in, ppos, pipe, max_read_len, flags);
+ if (unlikely(ret < 0))
+ goto out_release;
+
+ read_len = ret;
+
+ /*
+ * NOTE: nonblocking mode only applies to the input. We
+ * must not do the output in nonblocking mode as then we
+ * could get stuck data in the internal pipe:
+ */
+ ret = do_splice_from(pipe, out, &out_off, read_len,
+ flags & ~SPLICE_F_NONBLOCK);
+ if (unlikely(ret < 0))
+ goto out_release;
+
+ bytes += ret;
+ len -= ret;
+
+ /*
+ * In nonblocking mode, if we got back a short read then
+ * that was due to either an IO error or due to the
+ * pagecache entry not being there. In the IO error case
+ * the _next_ splice attempt will produce a clean IO error
+ * return value (not a short read), so in both cases it's
+ * correct to break out of the loop here:
+ */
+ if ((flags & SPLICE_F_NONBLOCK) && (read_len < max_read_len))
+ break;
+ }
+
+ pipe->nrbufs = pipe->curbuf = 0;
+
+ return bytes;
+
+out_release:
+ /*
+ * If we did an incomplete transfer we must release
+ * the pipe buffers in question:
+ */
+ for (i = 0; i < PIPE_BUFFERS; i++) {
+ struct pipe_buffer *buf = pipe->bufs + i;
+
+ if (buf->ops) {
+ buf->ops->release(pipe, buf);
+ buf->ops = NULL;
+ }
+ }
+ pipe->nrbufs = pipe->curbuf = 0;
+
+ /*
+ * If we transferred some data, return the number of bytes:
+ */
+ if (bytes > 0)
+ return bytes;
+
+ return ret;
+}
+
+EXPORT_SYMBOL(do_splice_direct);
+
+/*
+ * Determine where to splice to/from.
+ */
+static long do_splice(struct file *in, loff_t __user *off_in,
+ struct file *out, loff_t __user *off_out,
+ size_t len, unsigned int flags)
+{
+ struct pipe_inode_info *pipe;
+ loff_t offset, *off;
+ long ret;
+
+ pipe = in->f_dentry->d_inode->i_pipe;
+ if (pipe) {
+ if (off_in)
+ return -ESPIPE;
+ if (off_out) {
+ if (out->f_op->llseek == no_llseek)
+ return -EINVAL;
+ if (copy_from_user(&offset, off_out, sizeof(loff_t)))
+ return -EFAULT;
+ off = &offset;
+ } else
+ off = &out->f_pos;
+
+ ret = do_splice_from(pipe, out, off, len, flags);
+
+ if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
+ ret = -EFAULT;
+
+ return ret;
+ }
+
+ pipe = out->f_dentry->d_inode->i_pipe;
+ if (pipe) {
+ if (off_out)
+ return -ESPIPE;
+ if (off_in) {
+ if (in->f_op->llseek == no_llseek)
+ return -EINVAL;
+ if (copy_from_user(&offset, off_in, sizeof(loff_t)))
+ return -EFAULT;
+ off = &offset;
+ } else
+ off = &in->f_pos;
+
+ ret = do_splice_to(in, off, pipe, len, flags);
+
+ if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
+ ret = -EFAULT;
+
+ return ret;
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * Map an iov into an array of pages and offset/length tupples. With the
+ * partial_page structure, we can map several non-contiguous ranges into
+ * our ones pages[] map instead of splitting that operation into pieces.
+ * Could easily be exported as a generic helper for other users, in which
+ * case one would probably want to add a 'max_nr_pages' parameter as well.
+ */
+static int get_iovec_page_array(const struct iovec __user *iov,
+ unsigned int nr_vecs, struct page **pages,
+ struct partial_page *partial, int aligned)
+{
+ int buffers = 0, error = 0;
+
+ /*
+ * It's ok to take the mmap_sem for reading, even
+ * across a "get_user()".
+ */
+ down_read(&current->mm->mmap_sem);
+
+ while (nr_vecs) {
+ unsigned long off, npages;
+ void __user *base;
+ size_t len;
+ int i;
+
+ /*
+ * Get user address base and length for this iovec.
+ */
+ error = get_user(base, &iov->iov_base);
+ if (unlikely(error))
+ break;
+ error = get_user(len, &iov->iov_len);
+ if (unlikely(error))
+ break;
+
+ /*
+ * Sanity check this iovec. 0 read succeeds.
+ */
+ if (unlikely(!len))
+ break;
+ error = -EFAULT;
+ if (unlikely(!base))
+ break;
+
+ /*
+ * Get this base offset and number of pages, then map
+ * in the user pages.
+ */
+ off = (unsigned long) base & ~PAGE_MASK;
+
+ /*
+ * If asked for alignment, the offset must be zero and the
+ * length a multiple of the PAGE_SIZE.
+ */
+ error = -EINVAL;
+ if (aligned && (off || len & ~PAGE_MASK))
+ break;
+
+ npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ if (npages > PIPE_BUFFERS - buffers)
+ npages = PIPE_BUFFERS - buffers;
+
+ error = get_user_pages(current, current->mm,
+ (unsigned long) base, npages, 0, 0,
+ &pages[buffers], NULL);
+
+ if (unlikely(error <= 0))
+ break;
+
+ /*
+ * Fill this contiguous range into the partial page map.
+ */
+ for (i = 0; i < error; i++) {
+ const int plen = min_t(size_t, len, PAGE_SIZE - off);
+
+ partial[buffers].offset = off;
+ partial[buffers].len = plen;
+
+ off = 0;
+ len -= plen;
+ buffers++;
+ }
+
+ /*
+ * We didn't complete this iov, stop here since it probably
+ * means we have to move some of this into a pipe to
+ * be able to continue.
+ */
+ if (len)
+ break;
+
+ /*
+ * Don't continue if we mapped fewer pages than we asked for,
+ * or if we mapped the max number of pages that we have
+ * room for.
+ */
+ if (error < npages || buffers == PIPE_BUFFERS)
+ break;
+
+ nr_vecs--;
+ iov++;
+ }
+
+ up_read(&current->mm->mmap_sem);
+
+ if (buffers)
+ return buffers;
+
+ return error;
+}
+
+/*
+ * vmsplice splices a user address range into a pipe. It can be thought of
+ * as splice-from-memory, where the regular splice is splice-from-file (or
+ * to file). In both cases the output is a pipe, naturally.
+ *
+ * Note that vmsplice only supports splicing _from_ user memory to a pipe,
+ * not the other way around. Splicing from user memory is a simple operation
+ * that can be supported without any funky alignment restrictions or nasty
+ * vm tricks. We simply map in the user memory and fill them into a pipe.
+ * The reverse isn't quite as easy, though. There are two possible solutions
+ * for that:
+ *
+ * - memcpy() the data internally, at which point we might as well just
+ * do a regular read() on the buffer anyway.
+ * - Lots of nasty vm tricks, that are neither fast nor flexible (it
+ * has restriction limitations on both ends of the pipe).
+ *
+ * Alas, it isn't here.
+ *
+ */
+static long do_vmsplice(struct file *file, const struct iovec __user *iov,
+ unsigned long nr_segs, unsigned int flags)
+{
+ struct pipe_inode_info *pipe = file->f_dentry->d_inode->i_pipe;
+ struct page *pages[PIPE_BUFFERS];
+ struct partial_page partial[PIPE_BUFFERS];
+ struct splice_pipe_desc spd = {
+ .pages = pages,
+ .partial = partial,
+ .flags = flags,
+ .ops = &user_page_pipe_buf_ops,
+ };
+
+ if (unlikely(!pipe))
+ return -EBADF;
+ if (unlikely(nr_segs > UIO_MAXIOV))
+ return -EINVAL;
+ else if (unlikely(!nr_segs))
+ return 0;
+
+ spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial,
+ flags & SPLICE_F_GIFT);
+ if (spd.nr_pages <= 0)
+ return spd.nr_pages;
+
+ return splice_to_pipe(pipe, &spd);
+}
+
+asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov,
+ unsigned long nr_segs, unsigned int flags)
+{
+ struct file *file;
+ long error;
+ int fput;
+
+ error = -EBADF;
+ file = fget_light(fd, &fput);
+ if (file) {
+ if (file->f_mode & FMODE_WRITE)
+ error = do_vmsplice(file, iov, nr_segs, flags);
+
+ fput_light(file, fput);
+ }
+
+ return error;
+}
+
+asmlinkage long sys_splice(int fd_in, loff_t __user *off_in,
+ int fd_out, loff_t __user *off_out,
+ size_t len, unsigned int flags)
+{
+ long error;
+ struct file *in, *out;
+ int fput_in, fput_out;
+
+ if (unlikely(!len))
+ return 0;
+
+ error = -EBADF;
+ in = fget_light(fd_in, &fput_in);
+ if (in) {
+ if (in->f_mode & FMODE_READ) {
+ out = fget_light(fd_out, &fput_out);
+ if (out) {
+ if (out->f_mode & FMODE_WRITE)
+ error = do_splice(in, off_in,
+ out, off_out,
+ len, flags);
+ fput_light(out, fput_out);
+ }
+ }
+
+ fput_light(in, fput_in);
+ }
+
+ return error;
+}
+
+/*
+ * Link contents of ipipe to opipe.
+ */
+static int link_pipe(struct pipe_inode_info *ipipe,
+ struct pipe_inode_info *opipe,
+ size_t len, unsigned int flags)
+{
+ struct pipe_buffer *ibuf, *obuf;
+ int ret, do_wakeup, i, ipipe_first;
+
+ ret = do_wakeup = ipipe_first = 0;
+
+ /*
+ * Potential ABBA deadlock, work around it by ordering lock
+ * grabbing by inode address. Otherwise two different processes
+ * could deadlock (one doing tee from A -> B, the other from B -> A).
+ */
+ if (ipipe->inode < opipe->inode) {
+ ipipe_first = 1;
+ mutex_lock(&ipipe->inode->i_mutex);
+ mutex_lock(&opipe->inode->i_mutex);
+ } else {
+ mutex_lock(&opipe->inode->i_mutex);
+ mutex_lock(&ipipe->inode->i_mutex);
+ }
+
+ for (i = 0;; i++) {
+ if (!opipe->readers) {
+ send_sig(SIGPIPE, current, 0);
+ if (!ret)
+ ret = -EPIPE;
+ break;
+ }
+ if (ipipe->nrbufs - i) {
+ ibuf = ipipe->bufs + ((ipipe->curbuf + i) & (PIPE_BUFFERS - 1));
+
+ /*
+ * If we have room, fill this buffer
+ */
+ if (opipe->nrbufs < PIPE_BUFFERS) {
+ int nbuf = (opipe->curbuf + opipe->nrbufs) & (PIPE_BUFFERS - 1);
+
+ /*
+ * Get a reference to this pipe buffer,
+ * so we can copy the contents over.
+ */
+ ibuf->ops->get(ipipe, ibuf);
+
+ obuf = opipe->bufs + nbuf;
+ *obuf = *ibuf;
+
+ /*
+ * Don't inherit the gift flag, we need to
+ * prevent multiple steals of this page.
+ */
+ obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
+
+ if (obuf->len > len)
+ obuf->len = len;
+
+ opipe->nrbufs++;
+ do_wakeup = 1;
+ ret += obuf->len;
+ len -= obuf->len;
+
+ if (!len)
+ break;
+ if (opipe->nrbufs < PIPE_BUFFERS)
+ continue;
+ }
+
+ /*
+ * We have input available, but no output room.
+ * If we already copied data, return that. If we
+ * need to drop the opipe lock, it must be ordered
+ * last to avoid deadlocks.
+ */
+ if ((flags & SPLICE_F_NONBLOCK) || !ipipe_first) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
+ if (do_wakeup) {
+ smp_mb();
+ if (waitqueue_active(&opipe->wait))
+ wake_up_interruptible(&opipe->wait);
+ kill_fasync(&opipe->fasync_readers, SIGIO, POLL_IN);
+ do_wakeup = 0;
+ }
+
+ opipe->waiting_writers++;
+ pipe_wait(opipe);
+ opipe->waiting_writers--;
+ continue;
+ }
+
+ /*
+ * No input buffers, do the usual checks for available
+ * writers and blocking and wait if necessary
+ */
+ if (!ipipe->writers)
+ break;
+ if (!ipipe->waiting_writers) {
+ if (ret)
+ break;
+ }
+ /*
+ * pipe_wait() drops the ipipe mutex. To avoid deadlocks
+ * with another process, we can only safely do that if
+ * the ipipe lock is ordered last.
+ */
+ if ((flags & SPLICE_F_NONBLOCK) || ipipe_first) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
+
+ if (waitqueue_active(&ipipe->wait))
+ wake_up_interruptible_sync(&ipipe->wait);
+ kill_fasync(&ipipe->fasync_writers, SIGIO, POLL_OUT);
+
+ pipe_wait(ipipe);
+ }
+
+ mutex_unlock(&ipipe->inode->i_mutex);
+ mutex_unlock(&opipe->inode->i_mutex);
+
+ if (do_wakeup) {
+ smp_mb();
+ if (waitqueue_active(&opipe->wait))
+ wake_up_interruptible(&opipe->wait);
+ kill_fasync(&opipe->fasync_readers, SIGIO, POLL_IN);
+ }
+
+ return ret;
+}
+
+/*
+ * This is a tee(1) implementation that works on pipes. It doesn't copy
+ * any data, it simply references the 'in' pages on the 'out' pipe.
+ * The 'flags' used are the SPLICE_F_* variants, currently the only
+ * applicable one is SPLICE_F_NONBLOCK.
+ */
+static long do_tee(struct file *in, struct file *out, size_t len,
+ unsigned int flags)
+{
+ struct pipe_inode_info *ipipe = in->f_dentry->d_inode->i_pipe;
+ struct pipe_inode_info *opipe = out->f_dentry->d_inode->i_pipe;
+
+ /*
+ * Link ipipe to the two output pipes, consuming as we go along.
+ */
+ if (ipipe && opipe)
+ return link_pipe(ipipe, opipe, len, flags);
+
+ return -EINVAL;
+}
+
+asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags)
+{
+ struct file *in;
+ int error, fput_in;
+
+ if (unlikely(!len))
+ return 0;
+
+ error = -EBADF;
+ in = fget_light(fdin, &fput_in);
+ if (in) {
+ if (in->f_mode & FMODE_READ) {
+ int fput_out;
+ struct file *out = fget_light(fdout, &fput_out);
+
+ if (out) {
+ if (out->f_mode & FMODE_WRITE)
+ error = do_tee(in, out, len, flags);
+ fput_light(out, fput_out);
+ }
+ }
+ fput_light(in, fput_in);
+ }
+
+ return error;
+}
diff --git a/fs/stat.c b/fs/stat.c
index 9948cc1685a..0f282face32 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -261,7 +261,7 @@ asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf)
return error;
}
-#ifndef __ARCH_WANT_STAT64
+#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
asmlinkage long sys_newfstatat(int dfd, char __user *filename,
struct stat __user *statbuf, int flag)
{
diff --git a/fs/sync.c b/fs/sync.c
new file mode 100644
index 00000000000..aab5ffe77e9
--- /dev/null
+++ b/fs/sync.c
@@ -0,0 +1,164 @@
+/*
+ * High-level sync()-related operations
+ */
+
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/writeback.h>
+#include <linux/syscalls.h>
+#include <linux/linkage.h>
+#include <linux/pagemap.h>
+
+#define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \
+ SYNC_FILE_RANGE_WAIT_AFTER)
+
+/*
+ * sys_sync_file_range() permits finely controlled syncing over a segment of
+ * a file in the range offset .. (offset+nbytes-1) inclusive. If nbytes is
+ * zero then sys_sync_file_range() will operate from offset out to EOF.
+ *
+ * The flag bits are:
+ *
+ * SYNC_FILE_RANGE_WAIT_BEFORE: wait upon writeout of all pages in the range
+ * before performing the write.
+ *
+ * SYNC_FILE_RANGE_WRITE: initiate writeout of all those dirty pages in the
+ * range which are not presently under writeback.
+ *
+ * SYNC_FILE_RANGE_WAIT_AFTER: wait upon writeout of all pages in the range
+ * after performing the write.
+ *
+ * Useful combinations of the flag bits are:
+ *
+ * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE: ensures that all pages
+ * in the range which were dirty on entry to sys_sync_file_range() are placed
+ * under writeout. This is a start-write-for-data-integrity operation.
+ *
+ * SYNC_FILE_RANGE_WRITE: start writeout of all dirty pages in the range which
+ * are not presently under writeout. This is an asynchronous flush-to-disk
+ * operation. Not suitable for data integrity operations.
+ *
+ * SYNC_FILE_RANGE_WAIT_BEFORE (or SYNC_FILE_RANGE_WAIT_AFTER): wait for
+ * completion of writeout of all pages in the range. This will be used after an
+ * earlier SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE operation to wait
+ * for that operation to complete and to return the result.
+ *
+ * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER:
+ * a traditional sync() operation. This is a write-for-data-integrity operation
+ * which will ensure that all pages in the range which were dirty on entry to
+ * sys_sync_file_range() are committed to disk.
+ *
+ *
+ * SYNC_FILE_RANGE_WAIT_BEFORE and SYNC_FILE_RANGE_WAIT_AFTER will detect any
+ * I/O errors or ENOSPC conditions and will return those to the caller, after
+ * clearing the EIO and ENOSPC flags in the address_space.
+ *
+ * It should be noted that none of these operations write out the file's
+ * metadata. So unless the application is strictly performing overwrites of
+ * already-instantiated disk blocks, there are no guarantees here that the data
+ * will be available after a crash.
+ */
+asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
+ unsigned int flags)
+{
+ int ret;
+ struct file *file;
+ loff_t endbyte; /* inclusive */
+ int fput_needed;
+ umode_t i_mode;
+
+ ret = -EINVAL;
+ if (flags & ~VALID_FLAGS)
+ goto out;
+
+ endbyte = offset + nbytes;
+
+ if ((s64)offset < 0)
+ goto out;
+ if ((s64)endbyte < 0)
+ goto out;
+ if (endbyte < offset)
+ goto out;
+
+ if (sizeof(pgoff_t) == 4) {
+ if (offset >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
+ /*
+ * The range starts outside a 32 bit machine's
+ * pagecache addressing capabilities. Let it "succeed"
+ */
+ ret = 0;
+ goto out;
+ }
+ if (endbyte >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
+ /*
+ * Out to EOF
+ */
+ nbytes = 0;
+ }
+ }
+
+ if (nbytes == 0)
+ endbyte = -1;
+ else
+ endbyte--; /* inclusive */
+
+ ret = -EBADF;
+ file = fget_light(fd, &fput_needed);
+ if (!file)
+ goto out;
+
+ i_mode = file->f_dentry->d_inode->i_mode;
+ ret = -ESPIPE;
+ if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) &&
+ !S_ISLNK(i_mode))
+ goto out_put;
+
+ ret = do_sync_file_range(file, offset, endbyte, flags);
+out_put:
+ fput_light(file, fput_needed);
+out:
+ return ret;
+}
+
+/*
+ * `endbyte' is inclusive
+ */
+int do_sync_file_range(struct file *file, loff_t offset, loff_t endbyte,
+ unsigned int flags)
+{
+ int ret;
+ struct address_space *mapping;
+
+ mapping = file->f_mapping;
+ if (!mapping) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = 0;
+ if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
+ ret = wait_on_page_writeback_range(mapping,
+ offset >> PAGE_CACHE_SHIFT,
+ endbyte >> PAGE_CACHE_SHIFT);
+ if (ret < 0)
+ goto out;
+ }
+
+ if (flags & SYNC_FILE_RANGE_WRITE) {
+ ret = __filemap_fdatawrite_range(mapping, offset, endbyte,
+ WB_SYNC_NONE);
+ if (ret < 0)
+ goto out;
+ }
+
+ if (flags & SYNC_FILE_RANGE_WAIT_AFTER) {
+ ret = wait_on_page_writeback_range(mapping,
+ offset >> PAGE_CACHE_SHIFT,
+ endbyte >> PAGE_CACHE_SHIFT);
+ }
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(do_sync_file_range);
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 78899eeab97..c16a93c353c 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -163,7 +163,7 @@ static int release(struct inode * inode, struct file * file)
return 0;
}
-struct file_operations bin_fops = {
+const struct file_operations bin_fops = {
.read = read,
.write = write,
.mmap = mmap,
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 9ee95686444..610b5bdbe75 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -43,6 +43,7 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd,
memset(sd, 0, sizeof(*sd));
atomic_set(&sd->s_count, 1);
+ atomic_set(&sd->s_event, 0);
INIT_LIST_HEAD(&sd->s_children);
list_add(&sd->s_sibling, &parent_sd->s_children);
sd->s_element = element;
@@ -50,7 +51,7 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd,
return sd;
}
-/**
+/*
*
* Return -EEXIST if there is already a sysfs element with the same name for
* the same parent.
@@ -503,7 +504,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
return offset;
}
-struct file_operations sysfs_dir_operations = {
+const struct file_operations sysfs_dir_operations = {
.open = sysfs_dir_open,
.release = sysfs_dir_close,
.llseek = sysfs_dir_lseek,
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 5e83e724678..cf3786625bf 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -6,6 +6,7 @@
#include <linux/fsnotify.h>
#include <linux/kobject.h>
#include <linux/namei.h>
+#include <linux/poll.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
@@ -57,6 +58,7 @@ struct sysfs_buffer {
struct sysfs_ops * ops;
struct semaphore sem;
int needs_read_fill;
+ int event;
};
@@ -72,6 +74,7 @@ struct sysfs_buffer {
*/
static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
{
+ struct sysfs_dirent * sd = dentry->d_fsdata;
struct attribute * attr = to_attr(dentry);
struct kobject * kobj = to_kobj(dentry->d_parent);
struct sysfs_ops * ops = buffer->ops;
@@ -83,6 +86,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
if (!buffer->page)
return -ENOMEM;
+ buffer->event = atomic_read(&sd->s_event);
count = ops->show(kobj,attr,buffer->page);
buffer->needs_read_fill = 0;
BUG_ON(count > (ssize_t)PAGE_SIZE);
@@ -183,7 +187,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
return -ENOMEM;
if (count >= PAGE_SIZE)
- count = PAGE_SIZE;
+ count = PAGE_SIZE - 1;
error = copy_from_user(buffer->page,buf,count);
buffer->needs_read_fill = 1;
return error ? -EFAULT : count;
@@ -348,12 +352,84 @@ static int sysfs_release(struct inode * inode, struct file * filp)
return 0;
}
-struct file_operations sysfs_file_operations = {
+/* Sysfs attribute files are pollable. The idea is that you read
+ * the content and then you use 'poll' or 'select' to wait for
+ * the content to change. When the content changes (assuming the
+ * manager for the kobject supports notification), poll will
+ * return POLLERR|POLLPRI, and select will return the fd whether
+ * it is waiting for read, write, or exceptions.
+ * Once poll/select indicates that the value has changed, you
+ * need to close and re-open the file, as simply seeking and reading
+ * again will not get new data, or reset the state of 'poll'.
+ * Reminder: this only works for attributes which actively support
+ * it, and it is not possible to test an attribute from userspace
+ * to see if it supports poll (Nether 'poll' or 'select' return
+ * an appropriate error code). When in doubt, set a suitable timeout value.
+ */
+static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
+{
+ struct sysfs_buffer * buffer = filp->private_data;
+ struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
+ struct sysfs_dirent * sd = filp->f_dentry->d_fsdata;
+ int res = 0;
+
+ poll_wait(filp, &kobj->poll, wait);
+
+ if (buffer->event != atomic_read(&sd->s_event)) {
+ res = POLLERR|POLLPRI;
+ buffer->needs_read_fill = 1;
+ }
+
+ return res;
+}
+
+
+static struct dentry *step_down(struct dentry *dir, const char * name)
+{
+ struct dentry * de;
+
+ if (dir == NULL || dir->d_inode == NULL)
+ return NULL;
+
+ mutex_lock(&dir->d_inode->i_mutex);
+ de = lookup_one_len(name, dir, strlen(name));
+ mutex_unlock(&dir->d_inode->i_mutex);
+ dput(dir);
+ if (IS_ERR(de))
+ return NULL;
+ if (de->d_inode == NULL) {
+ dput(de);
+ return NULL;
+ }
+ return de;
+}
+
+void sysfs_notify(struct kobject * k, char *dir, char *attr)
+{
+ struct dentry *de = k->dentry;
+ if (de)
+ dget(de);
+ if (de && dir)
+ de = step_down(de, dir);
+ if (de && attr)
+ de = step_down(de, attr);
+ if (de) {
+ struct sysfs_dirent * sd = de->d_fsdata;
+ if (sd)
+ atomic_inc(&sd->s_event);
+ wake_up_interruptible(&k->poll);
+ dput(de);
+ }
+}
+EXPORT_SYMBOL_GPL(sysfs_notify);
+
+const struct file_operations sysfs_file_operations = {
.read = sysfs_read_file,
.write = sysfs_write_file,
.llseek = generic_file_llseek,
.open = sysfs_open_file,
.release = sysfs_release,
+ .poll = sysfs_poll,
};
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 4c29ac41ac3..f0b347bd12c 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -175,8 +175,7 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
struct bin_attribute * bin_attr;
struct sysfs_symlink * sl;
- if (!sd || !sd->s_element)
- BUG();
+ BUG_ON(!sd || !sd->s_element);
switch (sd->s_type) {
case SYSFS_DIR:
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index cf11d5b789d..3651ffb5ec0 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -11,6 +11,7 @@ extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
+extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
extern void sysfs_remove_subdir(struct dentry *);
@@ -21,9 +22,9 @@ extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
extern struct rw_semaphore sysfs_rename_sem;
extern struct super_block * sysfs_sb;
-extern struct file_operations sysfs_dir_operations;
-extern struct file_operations sysfs_file_operations;
-extern struct file_operations bin_fops;
+extern const struct file_operations sysfs_dir_operations;
+extern const struct file_operations sysfs_file_operations;
+extern const struct file_operations bin_fops;
extern struct inode_operations sysfs_dir_inode_operations;
extern struct inode_operations sysfs_symlink_inode_operations;
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index cce8b05cba5..d7074341ee8 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -20,7 +20,7 @@
static int sysv_readdir(struct file *, void *, filldir_t);
-struct file_operations sysv_dir_operations = {
+const struct file_operations sysv_dir_operations = {
.read = generic_read_dir,
.readdir = sysv_readdir,
.fsync = sysv_sync_file,
@@ -253,8 +253,7 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
lock_page(page);
err = mapping->a_ops->prepare_write(NULL, page, from, to);
- if (err)
- BUG();
+ BUG_ON(err);
de->inode = 0;
err = dir_commit_chunk(page, from, to);
dir_put_page(page);
@@ -353,8 +352,7 @@ void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
lock_page(page);
err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
- if (err)
- BUG();
+ BUG_ON(err);
de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
err = dir_commit_chunk(page, from, to);
dir_put_page(page);
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index da69abc0624..a59e303135f 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -19,7 +19,7 @@
* We have mostly NULLs here: the current defaults are OK for
* the coh filesystem.
*/
-struct file_operations sysv_file_operations = {
+const struct file_operations sysv_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index b7f9b4a42aa..393a480e4de 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -159,8 +159,8 @@ extern ino_t sysv_inode_by_name(struct dentry *);
extern struct inode_operations sysv_file_inode_operations;
extern struct inode_operations sysv_dir_inode_operations;
extern struct inode_operations sysv_fast_symlink_inode_operations;
-extern struct file_operations sysv_file_operations;
-extern struct file_operations sysv_dir_operations;
+extern const struct file_operations sysv_file_operations;
+extern const struct file_operations sysv_dir_operations;
extern struct address_space_operations sysv_aops;
extern struct super_operations sysv_sops;
extern struct dentry_operations sysv_dentry_operations;
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index f5222527fe3..8c28efa3b8f 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -42,7 +42,7 @@ static int do_udf_readdir(struct inode *, struct file *, filldir_t, void *);
/* readdir and lookup functions */
-struct file_operations udf_dir_operations = {
+const struct file_operations udf_dir_operations = {
.read = generic_read_dir,
.readdir = udf_readdir,
.ioctl = udf_ioctl,
diff --git a/fs/udf/file.c b/fs/udf/file.c
index a6f2acc1f15..e34b00e303f 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -248,7 +248,7 @@ static int udf_release_file(struct inode * inode, struct file * filp)
return 0;
}
-struct file_operations udf_file_operations = {
+const struct file_operations udf_file_operations = {
.read = generic_file_read,
.ioctl = udf_ioctl,
.open = generic_file_open,
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 81e0e8459af..2983afd5e7f 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -312,12 +312,10 @@ static int udf_get_block(struct inode *inode, sector_t block, struct buffer_head
err = 0;
bh = inode_getblk(inode, block, &err, &phys, &new);
- if (bh)
- BUG();
+ BUG_ON(bh);
if (err)
goto abort;
- if (!phys)
- BUG();
+ BUG_ON(!phys);
if (new)
set_buffer_new(bh_result);
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 1d5800e0cbe..023e19ba5a2 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -44,9 +44,9 @@ struct buffer_head;
struct super_block;
extern struct inode_operations udf_dir_inode_operations;
-extern struct file_operations udf_dir_operations;
+extern const struct file_operations udf_dir_operations;
extern struct inode_operations udf_file_inode_operations;
-extern struct file_operations udf_file_operations;
+extern const struct file_operations udf_file_operations;
extern struct address_space_operations udf_aops;
extern struct address_space_operations udf_adinicb_aops;
extern struct address_space_operations udf_symlink_aops;
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 7c10c68902a..1a561202d3f 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -620,7 +620,7 @@ int ufs_empty_dir (struct inode * inode)
return 1;
}
-struct file_operations ufs_dir_operations = {
+const struct file_operations ufs_dir_operations = {
.read = generic_read_dir,
.readdir = ufs_readdir,
.fsync = file_fsync,
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index 62ad481810e..312fd3f8631 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -31,7 +31,7 @@
* the ufs filesystem.
*/
-struct file_operations ufs_file_operations = {
+const struct file_operations ufs_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index ef46939c0c1..a56cec3be5f 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -185,24 +185,6 @@ static int vfat_valid_longname(const unsigned char *name, unsigned int len)
return -EINVAL;
if (len >= 256)
return -ENAMETOOLONG;
-
- /* MS-DOS "device special files" */
- if (len == 3 || (len > 3 && name[3] == '.')) { /* basename == 3 */
- if (!strnicmp(name, "aux", 3) ||
- !strnicmp(name, "con", 3) ||
- !strnicmp(name, "nul", 3) ||
- !strnicmp(name, "prn", 3))
- return -EINVAL;
- }
- if (len == 4 || (len > 4 && name[4] == '.')) { /* basename == 4 */
- /* "com1", "com2", ... */
- if ('1' <= name[3] && name[3] <= '9') {
- if (!strnicmp(name, "com", 3) ||
- !strnicmp(name, "lpt", 3))
- return -EINVAL;
- }
- }
-
return 0;
}
diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h
index 16b44c3c236..1b262b790d9 100644
--- a/fs/xfs/linux-2.6/mrlock.h
+++ b/fs/xfs/linux-2.6/mrlock.h
@@ -79,7 +79,7 @@ static inline void mrdemote(mrlock_t *mrp)
* Debug-only routine, without some platform-specific asm code, we can
* now only answer requests regarding whether we hold the lock for write
* (reader state is outside our visibility, we only track writer state).
- * Note: means !ismrlocked would give false positivies, so don't do that.
+ * Note: means !ismrlocked would give false positives, so don't do that.
*/
static inline int ismrlocked(mrlock_t *mrp, int type)
{
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index c02f7c5b746..4d191ef39b6 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -372,7 +372,7 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
* assumes that all buffers on the page are started at the same time.
*
* The fix is two passes across the ioend list - one to start writeback on the
- * bufferheads, and then the second one submit them for I/O.
+ * buffer_heads, and then submit them for I/O on the second pass.
*/
STATIC void
xfs_submit_ioend(
@@ -699,7 +699,7 @@ xfs_convert_page(
/*
* page_dirty is initially a count of buffers on the page before
- * EOF and is decrememted as we move each into a cleanable state.
+ * EOF and is decremented as we move each into a cleanable state.
*
* Derivation:
*
@@ -842,7 +842,7 @@ xfs_cluster_write(
* page if possible.
* The bh->b_state's cannot know if any of the blocks or which block for
* that matter are dirty due to mmap writes, and therefore bh uptodate is
- * only vaild if the page itself isn't completely uptodate. Some layers
+ * only valid if the page itself isn't completely uptodate. Some layers
* may clear the page dirty flag prior to calling write page, under the
* assumption the entire page will be written out; by not writing out the
* whole page the page can be reused before all valid dirty data is
@@ -870,12 +870,14 @@ xfs_page_state_convert(
pgoff_t end_index, last_index, tlast;
ssize_t size, len;
int flags, err, iomap_valid = 0, uptodate = 1;
- int page_dirty, count = 0, trylock_flag = 0;
+ int page_dirty, count = 0;
+ int trylock = 0;
int all_bh = unmapped;
- /* wait for other IO threads? */
- if (startio && (wbc->sync_mode == WB_SYNC_NONE && wbc->nonblocking))
- trylock_flag |= BMAPI_TRYLOCK;
+ if (startio) {
+ if (wbc->sync_mode == WB_SYNC_NONE && wbc->nonblocking)
+ trylock |= BMAPI_TRYLOCK;
+ }
/* Is this page beyond the end of the file? */
offset = i_size_read(inode);
@@ -892,7 +894,7 @@ xfs_page_state_convert(
/*
* page_dirty is initially a count of buffers on the page before
- * EOF and is decrememted as we move each into a cleanable state.
+ * EOF and is decremented as we move each into a cleanable state.
*
* Derivation:
*
@@ -956,15 +958,13 @@ xfs_page_state_convert(
if (buffer_unwritten(bh)) {
type = IOMAP_UNWRITTEN;
- flags = BMAPI_WRITE|BMAPI_IGNSTATE;
+ flags = BMAPI_WRITE | BMAPI_IGNSTATE;
} else if (buffer_delay(bh)) {
type = IOMAP_DELAY;
- flags = BMAPI_ALLOCATE;
- if (!startio)
- flags |= trylock_flag;
+ flags = BMAPI_ALLOCATE | trylock;
} else {
type = IOMAP_NEW;
- flags = BMAPI_WRITE|BMAPI_MMAP;
+ flags = BMAPI_WRITE | BMAPI_MMAP;
}
if (!iomap_valid) {
@@ -1223,10 +1223,9 @@ free_buffers:
}
STATIC int
-__xfs_get_block(
+__xfs_get_blocks(
struct inode *inode,
sector_t iblock,
- unsigned long blocks,
struct buffer_head *bh_result,
int create,
int direct,
@@ -1236,22 +1235,17 @@ __xfs_get_block(
xfs_iomap_t iomap;
xfs_off_t offset;
ssize_t size;
- int retpbbm = 1;
+ int niomap = 1;
int error;
offset = (xfs_off_t)iblock << inode->i_blkbits;
- if (blocks)
- size = (ssize_t) min_t(xfs_off_t, LONG_MAX,
- (xfs_off_t)blocks << inode->i_blkbits);
- else
- size = 1 << inode->i_blkbits;
-
+ ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
+ size = bh_result->b_size;
VOP_BMAP(vp, offset, size,
- create ? flags : BMAPI_READ, &iomap, &retpbbm, error);
+ create ? flags : BMAPI_READ, &iomap, &niomap, error);
if (error)
return -error;
-
- if (retpbbm == 0)
+ if (niomap == 0)
return 0;
if (iomap.iomap_bn != IOMAP_DADDR_NULL) {
@@ -1271,12 +1265,16 @@ __xfs_get_block(
}
}
- /* If this is a realtime file, data might be on a new device */
+ /*
+ * If this is a realtime file, data may be on a different device.
+ * to that pointed to from the buffer_head b_bdev currently.
+ */
bh_result->b_bdev = iomap.iomap_target->bt_bdev;
- /* If we previously allocated a block out beyond eof and
- * we are now coming back to use it then we will need to
- * flag it as new even if it has a disk address.
+ /*
+ * If we previously allocated a block out beyond eof and we are
+ * now coming back to use it then we will need to flag it as new
+ * even if it has a disk address.
*/
if (create &&
((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) ||
@@ -1292,26 +1290,24 @@ __xfs_get_block(
}
}
- if (blocks) {
+ if (direct || size > (1 << inode->i_blkbits)) {
ASSERT(iomap.iomap_bsize - iomap.iomap_delta > 0);
offset = min_t(xfs_off_t,
- iomap.iomap_bsize - iomap.iomap_delta,
- (xfs_off_t)blocks << inode->i_blkbits);
- bh_result->b_size = (u32) min_t(xfs_off_t, UINT_MAX, offset);
+ iomap.iomap_bsize - iomap.iomap_delta, size);
+ bh_result->b_size = (ssize_t)min_t(xfs_off_t, LONG_MAX, offset);
}
return 0;
}
int
-xfs_get_block(
+xfs_get_blocks(
struct inode *inode,
sector_t iblock,
struct buffer_head *bh_result,
int create)
{
- return __xfs_get_block(inode, iblock,
- bh_result->b_size >> inode->i_blkbits,
+ return __xfs_get_blocks(inode, iblock,
bh_result, create, 0, BMAPI_WRITE);
}
@@ -1322,8 +1318,7 @@ xfs_get_blocks_direct(
struct buffer_head *bh_result,
int create)
{
- return __xfs_get_block(inode, iblock,
- bh_result->b_size >> inode->i_blkbits,
+ return __xfs_get_blocks(inode, iblock,
bh_result, create, 1, BMAPI_WRITE|BMAPI_DIRECT);
}
@@ -1339,9 +1334,9 @@ xfs_end_io_direct(
/*
* Non-NULL private data means we need to issue a transaction to
* convert a range from unwritten to written extents. This needs
- * to happen from process contect but aio+dio I/O completion
+ * to happen from process context but aio+dio I/O completion
* happens from irq context so we need to defer it to a workqueue.
- * This is not nessecary for synchronous direct I/O, but we do
+ * This is not necessary for synchronous direct I/O, but we do
* it anyway to keep the code uniform and simpler.
*
* The core direct I/O code might be changed to always call the
@@ -1358,7 +1353,7 @@ xfs_end_io_direct(
}
/*
- * blockdev_direct_IO can return an error even afer the I/O
+ * blockdev_direct_IO can return an error even after the I/O
* completion handler was called. Thus we need to protect
* against double-freeing.
*/
@@ -1405,7 +1400,7 @@ xfs_vm_prepare_write(
unsigned int from,
unsigned int to)
{
- return block_prepare_write(page, from, to, xfs_get_block);
+ return block_prepare_write(page, from, to, xfs_get_blocks);
}
STATIC sector_t
@@ -1422,7 +1417,7 @@ xfs_vm_bmap(
VOP_RWLOCK(vp, VRWLOCK_READ);
VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error);
VOP_RWUNLOCK(vp, VRWLOCK_READ);
- return generic_block_bmap(mapping, block, xfs_get_block);
+ return generic_block_bmap(mapping, block, xfs_get_blocks);
}
STATIC int
@@ -1430,7 +1425,7 @@ xfs_vm_readpage(
struct file *unused,
struct page *page)
{
- return mpage_readpage(page, xfs_get_block);
+ return mpage_readpage(page, xfs_get_blocks);
}
STATIC int
@@ -1440,7 +1435,7 @@ xfs_vm_readpages(
struct list_head *pages,
unsigned nr_pages)
{
- return mpage_readpages(mapping, pages, nr_pages, xfs_get_block);
+ return mpage_readpages(mapping, pages, nr_pages, xfs_get_blocks);
}
STATIC void
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h
index 795699f121d..60716543c68 100644
--- a/fs/xfs/linux-2.6/xfs_aops.h
+++ b/fs/xfs/linux-2.6/xfs_aops.h
@@ -41,6 +41,6 @@ typedef struct xfs_ioend {
} xfs_ioend_t;
extern struct address_space_operations xfs_address_space_operations;
-extern int xfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
+extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int);
#endif /* __XFS_IOPS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 9fb0312665c..26fed0756f0 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -182,7 +182,7 @@ free_address(
{
a_list_t *aentry;
- aentry = kmalloc(sizeof(a_list_t), GFP_ATOMIC & ~__GFP_HIGH);
+ aentry = kmalloc(sizeof(a_list_t), GFP_NOWAIT);
if (likely(aentry)) {
spin_lock(&as_lock);
aentry->next = as_free_head;
diff --git a/fs/xfs/linux-2.6/xfs_export.h b/fs/xfs/linux-2.6/xfs_export.h
index e5b0559700a..e794ca4efc7 100644
--- a/fs/xfs/linux-2.6/xfs_export.h
+++ b/fs/xfs/linux-2.6/xfs_export.h
@@ -54,7 +54,7 @@
* Note, the NFS filehandle also includes an fsid portion which
* may have an inode number in it. That number is hardcoded to
* 32bits and there is no way for XFS to intercept it. In
- * practice this means when exporting an XFS filesytem with 64bit
+ * practice this means when exporting an XFS filesystem with 64bit
* inodes you should either export the mountpoint (rather than
* a subdirectory) or use the "fsid" export option.
*/
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 185567a6a56..c847416f6d1 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -69,7 +69,6 @@ __xfs_file_read(
return rval;
}
-
STATIC ssize_t
xfs_file_aio_read(
struct kiocb *iocb,
@@ -90,7 +89,6 @@ xfs_file_aio_read_invis(
return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
}
-
STATIC inline ssize_t
__xfs_file_write(
struct kiocb *iocb,
@@ -113,7 +111,6 @@ __xfs_file_write(
return rval;
}
-
STATIC ssize_t
xfs_file_aio_write(
struct kiocb *iocb,
@@ -134,7 +131,6 @@ xfs_file_aio_write_invis(
return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
}
-
STATIC inline ssize_t
__xfs_file_readv(
struct file *file,
@@ -179,7 +175,6 @@ xfs_file_readv_invis(
return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos);
}
-
STATIC inline ssize_t
__xfs_file_writev(
struct file *file,
@@ -204,7 +199,6 @@ __xfs_file_writev(
return rval;
}
-
STATIC ssize_t
xfs_file_writev(
struct file *file,
@@ -228,7 +222,7 @@ xfs_file_writev_invis(
STATIC ssize_t
xfs_file_sendfile(
struct file *filp,
- loff_t *ppos,
+ loff_t *pos,
size_t count,
read_actor_t actor,
void *target)
@@ -236,10 +230,84 @@ xfs_file_sendfile(
vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode);
ssize_t rval;
- VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, rval);
+ VOP_SENDFILE(vp, filp, pos, 0, count, actor, target, NULL, rval);
+ return rval;
+}
+
+STATIC ssize_t
+xfs_file_sendfile_invis(
+ struct file *filp,
+ loff_t *pos,
+ size_t count,
+ read_actor_t actor,
+ void *target)
+{
+ vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode);
+ ssize_t rval;
+
+ VOP_SENDFILE(vp, filp, pos, IO_INVIS, count, actor, target, NULL, rval);
+ return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_read(
+ struct file *infilp,
+ loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t len,
+ unsigned int flags)
+{
+ vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode);
+ ssize_t rval;
+
+ VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, 0, NULL, rval);
+ return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_read_invis(
+ struct file *infilp,
+ loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t len,
+ unsigned int flags)
+{
+ vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode);
+ ssize_t rval;
+
+ VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, IO_INVIS, NULL, rval);
return rval;
}
+STATIC ssize_t
+xfs_file_splice_write(
+ struct pipe_inode_info *pipe,
+ struct file *outfilp,
+ loff_t *ppos,
+ size_t len,
+ unsigned int flags)
+{
+ vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode);
+ ssize_t rval;
+
+ VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, 0, NULL, rval);
+ return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_write_invis(
+ struct pipe_inode_info *pipe,
+ struct file *outfilp,
+ loff_t *ppos,
+ size_t len,
+ unsigned int flags)
+{
+ vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode);
+ ssize_t rval;
+
+ VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, IO_INVIS, NULL, rval);
+ return rval;
+}
STATIC int
xfs_file_open(
@@ -251,13 +319,10 @@ xfs_file_open(
if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
return -EFBIG;
-
- ASSERT(vp);
VOP_OPEN(vp, NULL, error);
return -error;
}
-
STATIC int
xfs_file_release(
struct inode *inode,
@@ -271,7 +336,6 @@ xfs_file_release(
return -error;
}
-
STATIC int
xfs_file_fsync(
struct file *filp,
@@ -285,21 +349,11 @@ xfs_file_fsync(
if (datasync)
flags |= FSYNC_DATA;
-
- ASSERT(vp);
VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error);
return -error;
}
-/*
- * xfs_file_readdir maps to VOP_READDIR().
- * We need to build a uio, cred, ...
- */
-
-#define nextdp(dp) ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen))
-
#ifdef CONFIG_XFS_DMAPI
-
STATIC struct page *
xfs_vm_nopage(
struct vm_area_struct *area,
@@ -319,10 +373,8 @@ xfs_vm_nopage(
return filemap_nopage(area, address, type);
}
-
#endif /* CONFIG_XFS_DMAPI */
-
STATIC int
xfs_file_readdir(
struct file *filp,
@@ -330,7 +382,7 @@ xfs_file_readdir(
filldir_t filldir)
{
int error = 0;
- vnode_t *vp;
+ vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode);
uio_t uio;
iovec_t iov;
int eof = 0;
@@ -340,9 +392,6 @@ xfs_file_readdir(
xfs_off_t start_offset, curr_offset;
xfs_dirent_t *dbp = NULL;
- vp = vn_from_inode(filp->f_dentry->d_inode);
- ASSERT(vp);
-
/* Try fairly hard to get memory */
do {
if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
@@ -387,7 +436,7 @@ xfs_file_readdir(
}
size -= dbp->d_reclen;
curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
- dbp = nextdp(dbp);
+ dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen);
}
}
done:
@@ -402,7 +451,6 @@ done:
return -error;
}
-
STATIC int
xfs_file_mmap(
struct file *filp,
@@ -457,11 +505,10 @@ xfs_file_ioctl_invis(
unsigned int cmd,
unsigned long arg)
{
- int error;
struct inode *inode = filp->f_dentry->d_inode;
vnode_t *vp = vn_from_inode(inode);
+ int error;
- ASSERT(vp);
VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error);
VMODIFY(vp);
@@ -528,7 +575,7 @@ open_exec_out:
}
#endif /* HAVE_FOP_OPEN_EXEC */
-struct file_operations xfs_file_operations = {
+const struct file_operations xfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
@@ -537,6 +584,8 @@ struct file_operations xfs_file_operations = {
.aio_read = xfs_file_aio_read,
.aio_write = xfs_file_aio_write,
.sendfile = xfs_file_sendfile,
+ .splice_read = xfs_file_splice_read,
+ .splice_write = xfs_file_splice_write,
.unlocked_ioctl = xfs_file_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = xfs_file_compat_ioctl,
@@ -550,7 +599,7 @@ struct file_operations xfs_file_operations = {
#endif
};
-struct file_operations xfs_invis_file_operations = {
+const struct file_operations xfs_invis_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
@@ -558,7 +607,9 @@ struct file_operations xfs_invis_file_operations = {
.writev = xfs_file_writev_invis,
.aio_read = xfs_file_aio_read_invis,
.aio_write = xfs_file_aio_write_invis,
- .sendfile = xfs_file_sendfile,
+ .sendfile = xfs_file_sendfile_invis,
+ .splice_read = xfs_file_splice_read_invis,
+ .splice_write = xfs_file_splice_write_invis,
.unlocked_ioctl = xfs_file_ioctl_invis,
#ifdef CONFIG_COMPAT
.compat_ioctl = xfs_file_compat_invis_ioctl,
@@ -570,7 +621,7 @@ struct file_operations xfs_invis_file_operations = {
};
-struct file_operations xfs_dir_file_operations = {
+const struct file_operations xfs_dir_file_operations = {
.read = generic_read_dir,
.readdir = xfs_file_readdir,
.unlocked_ioctl = xfs_file_ioctl,
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index b6321abd9a8..251bfe451a3 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -72,7 +72,7 @@ xfs_ioctl32_flock(
copy_in_user(&p->l_pid, &p32->l_pid, sizeof(u32)) ||
copy_in_user(&p->l_pad, &p32->l_pad, 4*sizeof(u32)))
return -EFAULT;
-
+
return (unsigned long)p;
}
@@ -107,11 +107,15 @@ xfs_ioctl32_bulkstat(
#endif
STATIC long
-xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
+xfs_compat_ioctl(
+ int mode,
+ struct file *file,
+ unsigned cmd,
+ unsigned long arg)
{
+ struct inode *inode = file->f_dentry->d_inode;
+ vnode_t *vp = vn_from_inode(inode);
int error;
- struct inode *inode = f->f_dentry->d_inode;
- vnode_t *vp = vn_to_inode(inode);
switch (cmd) {
case XFS_IOC_DIOINFO:
@@ -189,7 +193,7 @@ xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
return -ENOIOCTLCMD;
}
- VOP_IOCTL(vp, inode, f, mode, cmd, (void __user *)arg, error);
+ VOP_IOCTL(vp, inode, file, mode, cmd, (void __user *)arg, error);
VMODIFY(vp);
return error;
@@ -197,18 +201,18 @@ xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
long
xfs_file_compat_ioctl(
- struct file *f,
+ struct file *file,
unsigned cmd,
unsigned long arg)
{
- return xfs_compat_ioctl(0, f, cmd, arg);
+ return xfs_compat_ioctl(0, file, cmd, arg);
}
long
xfs_file_compat_invis_ioctl(
- struct file *f,
+ struct file *file,
unsigned cmd,
unsigned long arg)
{
- return xfs_compat_ioctl(IO_INVIS, f, cmd, arg);
+ return xfs_compat_ioctl(IO_INVIS, file, cmd, arg);
}
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index af487437bd7..2e2e275c786 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -673,8 +673,7 @@ xfs_vn_setattr(
if (ia_valid & ATTR_ATIME) {
vattr.va_mask |= XFS_AT_ATIME;
vattr.va_atime = attr->ia_atime;
- if (ia_valid & ATTR_ATIME_SET)
- inode->i_atime = attr->ia_atime;
+ inode->i_atime = attr->ia_atime;
}
if (ia_valid & ATTR_MTIME) {
vattr.va_mask |= XFS_AT_MTIME;
@@ -708,7 +707,7 @@ STATIC void
xfs_vn_truncate(
struct inode *inode)
{
- block_truncate_page(inode->i_mapping, inode->i_size, xfs_get_block);
+ block_truncate_page(inode->i_mapping, inode->i_size, xfs_get_blocks);
}
STATIC int
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h
index a8417d7af5f..ad6173da567 100644
--- a/fs/xfs/linux-2.6/xfs_iops.h
+++ b/fs/xfs/linux-2.6/xfs_iops.h
@@ -22,9 +22,9 @@ extern struct inode_operations xfs_inode_operations;
extern struct inode_operations xfs_dir_inode_operations;
extern struct inode_operations xfs_symlink_inode_operations;
-extern struct file_operations xfs_file_operations;
-extern struct file_operations xfs_dir_file_operations;
-extern struct file_operations xfs_invis_file_operations;
+extern const struct file_operations xfs_file_operations;
+extern const struct file_operations xfs_dir_file_operations;
+extern const struct file_operations xfs_invis_file_operations;
extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
int, unsigned int, void __user *);
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 1fe09f2d651..e9fe43d7476 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -103,6 +103,7 @@
*/
#undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */
#define HAVE_SENDFILE /* sendfile(2) exists in 2.6, but not in 2.4 */
+#define HAVE_SPLICE /* a splice(2) exists in 2.6, but not in 2.4 */
#ifdef CONFIG_SMP
#define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */
#else
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 0169360475c..67efe330898 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -301,36 +301,23 @@ xfs_sendfile(
void *target,
cred_t *credp)
{
+ xfs_inode_t *ip = XFS_BHVTOI(bdp);
+ xfs_mount_t *mp = ip->i_mount;
ssize_t ret;
- xfs_fsize_t n;
- xfs_inode_t *ip;
- xfs_mount_t *mp;
- vnode_t *vp;
-
- ip = XFS_BHVTOI(bdp);
- vp = BHV_TO_VNODE(bdp);
- mp = ip->i_mount;
XFS_STATS_INC(xs_read_calls);
-
- n = XFS_MAXIOFFSET(mp) - *offset;
- if ((n <= 0) || (count == 0))
- return 0;
-
- if (n < count)
- count = n;
-
- if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ if (XFS_FORCED_SHUTDOWN(mp))
return -EIO;
xfs_ilock(ip, XFS_IOLOCK_SHARED);
- if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
+ if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
(!(ioflags & IO_INVIS))) {
vrwlock_t locktype = VRWLOCK_READ;
int error;
- error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, count,
+ error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
+ *offset, count,
FILP_DELAY_FLAG(filp), &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
@@ -340,12 +327,98 @@ xfs_sendfile(
xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore,
(void *)(unsigned long)target, count, *offset, ioflags);
ret = generic_file_sendfile(filp, offset, count, actor, target);
+ if (ret > 0)
+ XFS_STATS_ADD(xs_read_bytes, ret);
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return ret;
+}
+ssize_t
+xfs_splice_read(
+ bhv_desc_t *bdp,
+ struct file *infilp,
+ loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t count,
+ int flags,
+ int ioflags,
+ cred_t *credp)
+{
+ xfs_inode_t *ip = XFS_BHVTOI(bdp);
+ xfs_mount_t *mp = ip->i_mount;
+ ssize_t ret;
+
+ XFS_STATS_INC(xs_read_calls);
+ if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ return -EIO;
+
+ xfs_ilock(ip, XFS_IOLOCK_SHARED);
+
+ if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
+ (!(ioflags & IO_INVIS))) {
+ vrwlock_t locktype = VRWLOCK_READ;
+ int error;
+
+ error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
+ *ppos, count,
+ FILP_DELAY_FLAG(infilp), &locktype);
+ if (error) {
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return -error;
+ }
+ }
+ xfs_rw_enter_trace(XFS_SPLICE_READ_ENTER, &ip->i_iocore,
+ pipe, count, *ppos, ioflags);
+ ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
if (ret > 0)
XFS_STATS_ADD(xs_read_bytes, ret);
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return ret;
+}
+
+ssize_t
+xfs_splice_write(
+ bhv_desc_t *bdp,
+ struct pipe_inode_info *pipe,
+ struct file *outfilp,
+ loff_t *ppos,
+ size_t count,
+ int flags,
+ int ioflags,
+ cred_t *credp)
+{
+ xfs_inode_t *ip = XFS_BHVTOI(bdp);
+ xfs_mount_t *mp = ip->i_mount;
+ ssize_t ret;
+
+ XFS_STATS_INC(xs_write_calls);
+ if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ return -EIO;
+
+ xfs_ilock(ip, XFS_IOLOCK_EXCL);
+
+ if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) &&
+ (!(ioflags & IO_INVIS))) {
+ vrwlock_t locktype = VRWLOCK_WRITE;
+ int error;
+
+ error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
+ *ppos, count,
+ FILP_DELAY_FLAG(outfilp), &locktype);
+ if (error) {
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ return -error;
+ }
+ }
+ xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore,
+ pipe, count, *ppos, ioflags);
+ ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
+ if (ret > 0)
+ XFS_STATS_ADD(xs_write_bytes, ret);
+
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL);
return ret;
}
@@ -363,7 +436,7 @@ xfs_zero_last_block(
xfs_fsize_t end_size)
{
xfs_fileoff_t last_fsb;
- xfs_mount_t *mp;
+ xfs_mount_t *mp = io->io_mount;
int nimaps;
int zero_offset;
int zero_len;
@@ -373,8 +446,6 @@ xfs_zero_last_block(
ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
- mp = io->io_mount;
-
zero_offset = XFS_B_FSB_OFFSET(mp, isize);
if (zero_offset == 0) {
/*
@@ -405,10 +476,9 @@ xfs_zero_last_block(
* don't deadlock when the buffer cache calls back to us.
*/
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
- loff = XFS_FSB_TO_B(mp, last_fsb);
+ loff = XFS_FSB_TO_B(mp, last_fsb);
zero_len = mp->m_sb.sb_blocksize - zero_offset;
-
error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size);
XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
@@ -441,7 +511,7 @@ xfs_zero_eof(
xfs_fileoff_t zero_count_fsb;
xfs_fileoff_t last_fsb;
xfs_extlen_t buf_len_fsb;
- xfs_mount_t *mp;
+ xfs_mount_t *mp = io->io_mount;
int nimaps;
int error = 0;
xfs_bmbt_irec_t imap;
@@ -450,8 +520,6 @@ xfs_zero_eof(
ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
ASSERT(offset > isize);
- mp = io->io_mount;
-
/*
* First handle zeroing the block on which isize resides.
* We only zero a part of that block so it is handled specially.
@@ -681,7 +749,7 @@ start:
eventsent = 1;
/*
- * The iolock was dropped and reaquired in XFS_SEND_DATA
+ * The iolock was dropped and reacquired in XFS_SEND_DATA
* so we have to recheck the size when appending.
* We will only "goto start;" once, since having sent the
* event prevents another call to XFS_SEND_DATA, which is
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index 38864a88d42..8f453995235 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -60,6 +60,8 @@ struct xfs_iomap;
#define XFS_IOMAP_ALLOC_ENTER 25
#define XFS_IOMAP_ALLOC_MAP 26
#define XFS_IOMAP_UNWRITTEN 27
+#define XFS_SPLICE_READ_ENTER 28
+#define XFS_SPLICE_WRITE_ENTER 29
extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
void *, size_t, loff_t, int);
extern void xfs_inval_cached_trace(struct xfs_iocore *,
@@ -78,6 +80,7 @@ extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int,
struct xfs_iomap *, int *);
extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
extern int xfs_bdstrat_cb(struct xfs_buf *);
+extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t,
xfs_fsize_t, xfs_fsize_t);
@@ -90,7 +93,11 @@ extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *,
extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
loff_t *, int, size_t, read_actor_t,
void *, struct cred *);
-
-extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
+extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *,
+ struct pipe_inode_info *, size_t, int, int,
+ struct cred *);
+extern ssize_t xfs_splice_write(struct bhv_desc *, struct pipe_inode_info *,
+ struct file *, loff_t *, size_t, int, int,
+ struct cred *);
#endif /* __XFS_LRW_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 1884300417e..68f4793e8a1 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -67,7 +67,8 @@ mempool_t *xfs_ioend_pool;
STATIC struct xfs_mount_args *
xfs_args_allocate(
- struct super_block *sb)
+ struct super_block *sb,
+ int silent)
{
struct xfs_mount_args *args;
@@ -80,8 +81,8 @@ xfs_args_allocate(
args->flags |= XFSMNT_DIRSYNC;
if (sb->s_flags & MS_SYNCHRONOUS)
args->flags |= XFSMNT_WSYNC;
-
- /* Default to 32 bit inodes on Linux all the time */
+ if (silent)
+ args->flags |= XFSMNT_QUIET;
args->flags |= XFSMNT_32BITINODES;
return args;
@@ -719,7 +720,7 @@ xfs_fs_remount(
char *options)
{
vfs_t *vfsp = vfs_from_sb(sb);
- struct xfs_mount_args *args = xfs_args_allocate(sb);
+ struct xfs_mount_args *args = xfs_args_allocate(sb, 0);
int error;
VFS_PARSEARGS(vfsp, options, args, 1, error);
@@ -825,7 +826,7 @@ xfs_fs_fill_super(
{
vnode_t *rootvp;
struct vfs *vfsp = vfs_allocate(sb);
- struct xfs_mount_args *args = xfs_args_allocate(sb);
+ struct xfs_mount_args *args = xfs_args_allocate(sb, silent);
struct kstatfs statvfs;
int error, error2;
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index 8fed356db05..841200c0309 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -92,7 +92,7 @@ typedef enum {
#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */
#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
-#define SYNC_QUIESCE 0x0100 /* quiesce fileystem for a snapshot */
+#define SYNC_QUIESCE 0x0100 /* quiesce filesystem for a snapshot */
typedef int (*vfs_mount_t)(bhv_desc_t *,
struct xfs_mount_args *, struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 06f5845e956..2a8e16c2235 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -173,6 +173,12 @@ typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *,
typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
loff_t *, int, size_t, read_actor_t,
void *, struct cred *);
+typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *,
+ struct pipe_inode_info *, size_t, int, int,
+ struct cred *);
+typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *,
+ struct file *, loff_t *, size_t, int, int,
+ struct cred *);
typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
int, unsigned int, void __user *);
typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int,
@@ -231,6 +237,8 @@ typedef struct vnodeops {
vop_read_t vop_read;
vop_write_t vop_write;
vop_sendfile_t vop_sendfile;
+ vop_splice_read_t vop_splice_read;
+ vop_splice_write_t vop_splice_write;
vop_ioctl_t vop_ioctl;
vop_getattr_t vop_getattr;
vop_setattr_t vop_setattr;
@@ -276,6 +284,10 @@ typedef struct vnodeops {
rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
#define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv) \
rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr)
+#define VOP_SPLICE_READ(vp,f,o,pipe,cnt,fl,iofl,cr,rv) \
+ rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr)
+#define VOP_SPLICE_WRITE(vp,f,o,pipe,cnt,fl,iofl,cr,rv) \
+ rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr)
#define VOP_BMAP(vp,of,sz,rw,b,n,rv) \
rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)
#define VOP_OPEN(vp, cr, rv) \
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index e4e5f05b841..546f48af882 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -221,7 +221,7 @@ xfs_qm_dqunpin_wait(
* as possible.
*
* We must not be holding the AIL_LOCK at this point. Calling incore() to
- * search the buffercache can be a time consuming thing, and AIL_LOCK is a
+ * search the buffer cache can be a time consuming thing, and AIL_LOCK is a
* spinlock.
*/
STATIC void
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 1fb757ef3f4..7fb5eca9bd5 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -289,7 +289,7 @@ xfs_qm_rele_quotafs_ref(
/*
* This is called at mount time from xfs_mountfs to initialize the quotainfo
- * structure and start the global quotamanager (xfs_Gqm) if it hasn't done
+ * structure and start the global quota manager (xfs_Gqm) if it hasn't done
* so already. Note that the superblock has not been read in yet.
*/
void
@@ -807,7 +807,7 @@ xfs_qm_dqattach_one(
* Given a udquot and gdquot, attach a ptr to the group dquot in the
* udquot as a hint for future lookups. The idea sounds simple, but the
* execution isn't, because the udquot might have a group dquot attached
- * already and getting rid of that gets us into lock ordering contraints.
+ * already and getting rid of that gets us into lock ordering constraints.
* The process is complicated more by the fact that the dquots may or may not
* be locked on entry.
*/
@@ -1094,10 +1094,10 @@ xfs_qm_sync(
}
/*
* If we can't grab the flush lock then if the caller
- * really wanted us to give this our best shot,
+ * really wanted us to give this our best shot, so
* see if we can give a push to the buffer before we wait
* on the flush lock. At this point, we know that
- * eventhough the dquot is being flushed,
+ * even though the dquot is being flushed,
* it has (new) dirty data.
*/
xfs_qm_dqflock_pushbuf_wait(dqp);
@@ -1491,7 +1491,7 @@ xfs_qm_reset_dqcounts(
/*
* Do a sanity check, and if needed, repair the dqblk. Don't
* output any warnings because it's perfectly possible to
- * find unitialized dquot blks. See comment in xfs_qm_dqcheck.
+ * find uninitialised dquot blks. See comment in xfs_qm_dqcheck.
*/
(void) xfs_qm_dqcheck(ddq, id+j, type, XFS_QMOPT_DQREPAIR,
"xfs_quotacheck");
@@ -1580,7 +1580,7 @@ xfs_qm_dqiterate(
error = 0;
/*
- * This looks racey, but we can't keep an inode lock across a
+ * This looks racy, but we can't keep an inode lock across a
* trans_reserve. But, this gets called during quotacheck, and that
* happens only at mount time which is single threaded.
*/
@@ -1824,7 +1824,7 @@ xfs_qm_dqusage_adjust(
* we have to start from the beginning anyway.
* Once we're done, we'll log all the dquot bufs.
*
- * The *QUOTA_ON checks below may look pretty racey, but quotachecks
+ * The *QUOTA_ON checks below may look pretty racy, but quotachecks
* and quotaoffs don't race. (Quotachecks happen at mount time only).
*/
if (XFS_IS_UQUOTA_ON(mp)) {
@@ -2624,7 +2624,7 @@ xfs_qm_vop_chown_reserve(
{
int error;
xfs_mount_t *mp;
- uint delblks, blkflags;
+ uint delblks, blkflags, prjflags = 0;
xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq;
ASSERT(XFS_ISLOCKED_INODE(ip));
@@ -2650,10 +2650,13 @@ xfs_qm_vop_chown_reserve(
}
}
if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
- if ((XFS_IS_GQUOTA_ON(ip->i_mount) &&
- ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) ||
- (XFS_IS_PQUOTA_ON(ip->i_mount) &&
- ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))) {
+ if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
+ ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))
+ prjflags = XFS_QMOPT_ENOSPC;
+
+ if (prjflags ||
+ (XFS_IS_GQUOTA_ON(ip->i_mount) &&
+ ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
delblksgdq = gdqp;
if (delblks) {
ASSERT(ip->i_gdquot);
@@ -2664,7 +2667,7 @@ xfs_qm_vop_chown_reserve(
if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
- flags | blkflags)))
+ flags | blkflags | prjflags)))
return (error);
/*
@@ -2681,7 +2684,7 @@ xfs_qm_vop_chown_reserve(
ASSERT(unresudq || unresgdq);
if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
- flags | blkflags)))
+ flags | blkflags | prjflags)))
return (error);
xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 676884394aa..c55db463bbf 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -912,7 +912,7 @@ xfs_qm_export_dquot(
/*
* Internally, we don't reset all the timers when quota enforcement
- * gets turned off. No need to confuse the userlevel code,
+ * gets turned off. No need to confuse the user level code,
* so return zeroes in that case.
*/
if (! XFS_IS_QUOTA_ENFORCED(mp)) {
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 3290975d31f..9168918db25 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -595,12 +595,19 @@ xfs_trans_unreserve_and_mod_dquots(
}
}
+STATIC int
+xfs_quota_error(uint flags)
+{
+ if (flags & XFS_QMOPT_ENOSPC)
+ return ENOSPC;
+ return EDQUOT;
+}
+
/*
* This reserves disk blocks and inodes against a dquot.
* Flags indicate if the dquot is to be locked here and also
* if the blk reservation is for RT or regular blocks.
* Sending in XFS_QMOPT_FORCE_RES flag skips the quota check.
- * Returns EDQUOT if quota is exceeded.
*/
STATIC int
xfs_trans_dqresv(
@@ -666,19 +673,15 @@ xfs_trans_dqresv(
*/
if (hardlimit > 0ULL &&
(hardlimit <= nblks + *resbcountp)) {
- error = EDQUOT;
+ error = xfs_quota_error(flags);
goto error_return;
}
if (softlimit > 0ULL &&
(softlimit <= nblks + *resbcountp)) {
- /*
- * If timer or warnings has expired,
- * return EDQUOT
- */
if ((timer != 0 && get_seconds() > timer) ||
(warns != 0 && warns >= warnlimit)) {
- error = EDQUOT;
+ error = xfs_quota_error(flags);
goto error_return;
}
}
@@ -695,16 +698,12 @@ xfs_trans_dqresv(
if (!softlimit)
softlimit = q->qi_isoftlimit;
if (hardlimit > 0ULL && count >= hardlimit) {
- error = EDQUOT;
+ error = xfs_quota_error(flags);
goto error_return;
} else if (softlimit > 0ULL && count >= softlimit) {
- /*
- * If timer or warnings has expired,
- * return EDQUOT
- */
if ((timer != 0 && get_seconds() > timer) ||
(warns != 0 && warns >= warnlimit)) {
- error = EDQUOT;
+ error = xfs_quota_error(flags);
goto error_return;
}
}
@@ -751,13 +750,14 @@ error_return:
/*
- * Given a dquot(s), make disk block and/or inode reservations against them.
+ * Given dquot(s), make disk block and/or inode reservations against them.
* The fact that this does the reservation against both the usr and
- * grp quotas is important, because this follows a both-or-nothing
+ * grp/prj quotas is important, because this follows a both-or-nothing
* approach.
*
* flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked.
* XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
+ * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota.
* XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks
* XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks
* dquots are unlocked on return, if they were not locked by caller.
@@ -772,25 +772,27 @@ xfs_trans_reserve_quota_bydquots(
long ninos,
uint flags)
{
- int resvd;
+ int resvd = 0, error;
- if (! XFS_IS_QUOTA_ON(mp))
- return (0);
+ if (!XFS_IS_QUOTA_ON(mp))
+ return 0;
if (tp && tp->t_dqinfo == NULL)
xfs_trans_alloc_dqinfo(tp);
ASSERT(flags & XFS_QMOPT_RESBLK_MASK);
- resvd = 0;
if (udqp) {
- if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags))
- return (EDQUOT);
+ error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos,
+ (flags & ~XFS_QMOPT_ENOSPC));
+ if (error)
+ return error;
resvd = 1;
}
if (gdqp) {
- if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) {
+ error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags);
+ if (error) {
/*
* can't do it, so backout previous reservation
*/
@@ -799,14 +801,14 @@ xfs_trans_reserve_quota_bydquots(
xfs_trans_dqresv(tp, mp, udqp,
-nblks, -ninos, flags);
}
- return (EDQUOT);
+ return error;
}
}
/*
- * Didnt change anything critical, so, no need to log
+ * Didn't change anything critical, so, no need to log
*/
- return (0);
+ return 0;
}
@@ -814,8 +816,6 @@ xfs_trans_reserve_quota_bydquots(
* Lock the dquot and change the reservation if we can.
* This doesn't change the actual usage, just the reservation.
* The inode sent in is locked.
- *
- * Returns 0 on success, EDQUOT or other errors otherwise
*/
STATIC int
xfs_trans_reserve_quota_nblks(
@@ -824,20 +824,24 @@ xfs_trans_reserve_quota_nblks(
xfs_inode_t *ip,
long nblks,
long ninos,
- uint type)
+ uint flags)
{
int error;
if (!XFS_IS_QUOTA_ON(mp))
- return (0);
+ return 0;
+ if (XFS_IS_PQUOTA_ON(mp))
+ flags |= XFS_QMOPT_ENOSPC;
ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
- ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS ||
- (type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_BLKS);
+ ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
+ XFS_TRANS_DQ_RES_RTBLKS ||
+ (flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
+ XFS_TRANS_DQ_RES_BLKS);
/*
* Reserve nblks against these dquots, with trans as the mediator.
@@ -845,8 +849,8 @@ xfs_trans_reserve_quota_nblks(
error = xfs_trans_reserve_quota_bydquots(tp, mp,
ip->i_udquot, ip->i_gdquot,
nblks, ninos,
- type);
- return (error);
+ flags);
+ return error;
}
/*
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 4ff0f4e41c6..2539af34eb6 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -395,7 +395,7 @@ xfs_acl_allow_set(
* The access control process to determine the access permission:
* if uid == file owner id, use the file owner bits.
* if gid == file owner group id, use the file group bits.
- * scan ACL for a maching user or group, and use matched entry
+ * scan ACL for a matching user or group, and use matched entry
* permission. Use total permissions of all matching group entries,
* until all acl entries are exhausted. The final permission produced
* by matching acl entry or entries needs to be & with group permission.
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index a96e2ffce0c..dc2361dd740 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -179,7 +179,7 @@ typedef struct xfs_perag
{
char pagf_init; /* this agf's entry is initialized */
char pagi_init; /* this agi's entry is initialized */
- char pagf_metadata; /* the agf is prefered to be metadata */
+ char pagf_metadata; /* the agf is preferred to be metadata */
char pagi_inodeok; /* The agi is ok for inodes */
__uint8_t pagf_levels[XFS_BTNUM_AGF];
/* # of levels in bno & cnt btree */
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index f4328e1e2a7..8558226281c 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -511,7 +511,7 @@ STATIC void
xfs_alloc_trace_busy(
char *name, /* function tag string */
char *str, /* additional string */
- xfs_mount_t *mp, /* file system mount poing */
+ xfs_mount_t *mp, /* file system mount point */
xfs_agnumber_t agno, /* allocation group number */
xfs_agblock_t agbno, /* a.g. relative block number */
xfs_extlen_t len, /* length of extent */
@@ -1843,7 +1843,7 @@ xfs_alloc_fix_freelist(
} else
agbp = NULL;
- /* If this is a metadata prefered pag and we are user data
+ /* If this is a metadata preferred pag and we are user data
* then try somewhere else if we are not being asked to
* try harder at this point
*/
@@ -1942,8 +1942,10 @@ xfs_alloc_fix_freelist(
/*
* Allocate as many blocks as possible at once.
*/
- if ((error = xfs_alloc_ag_vextent(&targs)))
+ if ((error = xfs_alloc_ag_vextent(&targs))) {
+ xfs_trans_brelse(tp, agflbp);
return error;
+ }
/*
* Stop if we run out. Won't happen if callers are obeying
* the restrictions correctly. Can happen for free calls
@@ -1960,6 +1962,7 @@ xfs_alloc_fix_freelist(
return error;
}
}
+ xfs_trans_brelse(tp, agflbp);
args->agbp = agbp;
return 0;
}
@@ -2458,7 +2461,7 @@ error0:
/*
* AG Busy list management
* The busy list contains block ranges that have been freed but whose
- * transacations have not yet hit disk. If any block listed in a busy
+ * transactions have not yet hit disk. If any block listed in a busy
* list is reused, the transaction that freed it must be forced to disk
* before continuing to use the block.
*
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h
index 3546dea27b7..2d1f8928b26 100644
--- a/fs/xfs/xfs_alloc.h
+++ b/fs/xfs/xfs_alloc.h
@@ -68,7 +68,7 @@ typedef struct xfs_alloc_arg {
xfs_alloctype_t otype; /* original allocation type */
char wasdel; /* set if allocation was prev delayed */
char wasfromfl; /* set if allocation is from freelist */
- char isfl; /* set if is freelist blocks - !actg */
+ char isfl; /* set if is freelist blocks - !acctg */
char userdata; /* set if this is user data */
} xfs_alloc_arg_t;
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 093fac476bd..b6e1e02bbb2 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -294,7 +294,7 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
xfs_trans_ihold(args.trans, dp);
/*
- * If the attribute list is non-existant or a shortform list,
+ * If the attribute list is non-existent or a shortform list,
* upgrade it to a single-leaf-block attribute list.
*/
if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
@@ -1584,7 +1584,7 @@ out:
* Fill in the disk block numbers in the state structure for the buffers
* that are attached to the state structure.
* This is done so that we can quickly reattach ourselves to those buffers
- * after some set of transaction commit's has released these buffers.
+ * after some set of transaction commits have released these buffers.
*/
STATIC int
xfs_attr_fillstate(xfs_da_state_t *state)
@@ -1631,7 +1631,7 @@ xfs_attr_fillstate(xfs_da_state_t *state)
/*
* Reattach the buffers to the state structure based on the disk block
* numbers stored in the state structure.
- * This is done after some set of transaction commit's has released those
+ * This is done after some set of transaction commits have released those
* buffers from our grip.
*/
STATIC int
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 717682747bd..9462be86aa1 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -524,7 +524,7 @@ xfs_attr_shortform_compare(const void *a, const void *b)
/*
* Copy out entries of shortform attribute lists for attr_list().
- * Shortform atrtribute lists are not stored in hashval sorted order.
+ * Shortform attribute lists are not stored in hashval sorted order.
* If the output buffer is not large enough to hold them all, then we
* we have to calculate each entries' hashvalue and sort them before
* we can begin returning them to the user.
@@ -1541,7 +1541,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
/*
* Check for the degenerate case of the block being empty.
* If the block is empty, we'll simply delete it, no need to
- * coalesce it with a sibling block. We choose (aribtrarily)
+ * coalesce it with a sibling block. We choose (arbitrarily)
* to merge with the forward block unless it is NULL.
*/
if (count == 0) {
diff --git a/fs/xfs/xfs_behavior.c b/fs/xfs/xfs_behavior.c
index 9880adae393..f4fe3715a80 100644
--- a/fs/xfs/xfs_behavior.c
+++ b/fs/xfs/xfs_behavior.c
@@ -31,7 +31,7 @@
* The behavior chain is ordered based on the 'position' number which
* lives in the first field of the ops vector (higher numbers first).
*
- * Attemps to insert duplicate ops result in an EINVAL return code.
+ * Attempts to insert duplicate ops result in an EINVAL return code.
* Otherwise, return 0 to indicate success.
*/
int
@@ -84,7 +84,7 @@ bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp)
/*
* Remove a behavior descriptor from a position in a behavior chain;
- * the postition is guaranteed not to be the first position.
+ * the position is guaranteed not to be the first position.
* Should only be called by the bhv_remove() macro.
*/
void
diff --git a/fs/xfs/xfs_behavior.h b/fs/xfs/xfs_behavior.h
index 2cd89bb5ab1..1d8ff103201 100644
--- a/fs/xfs/xfs_behavior.h
+++ b/fs/xfs/xfs_behavior.h
@@ -39,7 +39,7 @@
* behaviors is synchronized with operations-in-progress (oip's) so that
* the oip's always see a consistent view of the chain.
*
- * The term "interpostion" is used to refer to the act of inserting
+ * The term "interposition" is used to refer to the act of inserting
* a behavior such that it interposes on (i.e., is inserted in front
* of) a particular other behavior. A key example of this is when a
* system implementing distributed single system image wishes to
@@ -51,7 +51,7 @@
*
* Behavior synchronization is logic which is necessary under certain
* circumstances that there is no conflict between ongoing operations
- * traversing the behavior chain and those dunamically modifying the
+ * traversing the behavior chain and those dynamically modifying the
* behavior chain. Because behavior synchronization adds extra overhead
* to virtual operation invocation, we want to restrict, as much as
* we can, the requirement for this extra code, to those situations
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 2d702e4a74a..26939d364bc 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -3467,113 +3467,6 @@ done:
return error;
}
-xfs_bmbt_rec_t * /* pointer to found extent entry */
-xfs_bmap_do_search_extents(
- xfs_bmbt_rec_t *base, /* base of extent list */
- xfs_extnum_t lastx, /* last extent index used */
- xfs_extnum_t nextents, /* number of file extents */
- xfs_fileoff_t bno, /* block number searched for */
- int *eofp, /* out: end of file found */
- xfs_extnum_t *lastxp, /* out: last extent index */
- xfs_bmbt_irec_t *gotp, /* out: extent entry found */
- xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */
-{
- xfs_bmbt_rec_t *ep; /* extent list entry pointer */
- xfs_bmbt_irec_t got; /* extent list entry, decoded */
- int high; /* high index of binary search */
- int low; /* low index of binary search */
-
- /*
- * Initialize the extent entry structure to catch access to
- * uninitialized br_startblock field.
- */
- got.br_startoff = 0xffa5a5a5a5a5a5a5LL;
- got.br_blockcount = 0xa55a5a5a5a5a5a5aLL;
- got.br_state = XFS_EXT_INVALID;
-
-#if XFS_BIG_BLKNOS
- got.br_startblock = 0xffffa5a5a5a5a5a5LL;
-#else
- got.br_startblock = 0xffffa5a5;
-#endif
-
- if (lastx != NULLEXTNUM && lastx < nextents)
- ep = base + lastx;
- else
- ep = NULL;
- prevp->br_startoff = NULLFILEOFF;
- if (ep && bno >= (got.br_startoff = xfs_bmbt_get_startoff(ep)) &&
- bno < got.br_startoff +
- (got.br_blockcount = xfs_bmbt_get_blockcount(ep)))
- *eofp = 0;
- else if (ep && lastx < nextents - 1 &&
- bno >= (got.br_startoff = xfs_bmbt_get_startoff(ep + 1)) &&
- bno < got.br_startoff +
- (got.br_blockcount = xfs_bmbt_get_blockcount(ep + 1))) {
- lastx++;
- ep++;
- *eofp = 0;
- } else if (nextents == 0)
- *eofp = 1;
- else if (bno == 0 &&
- (got.br_startoff = xfs_bmbt_get_startoff(base)) == 0) {
- ep = base;
- lastx = 0;
- got.br_blockcount = xfs_bmbt_get_blockcount(ep);
- *eofp = 0;
- } else {
- low = 0;
- high = nextents - 1;
- /* binary search the extents array */
- while (low <= high) {
- XFS_STATS_INC(xs_cmp_exlist);
- lastx = (low + high) >> 1;
- ep = base + lastx;
- got.br_startoff = xfs_bmbt_get_startoff(ep);
- got.br_blockcount = xfs_bmbt_get_blockcount(ep);
- if (bno < got.br_startoff)
- high = lastx - 1;
- else if (bno >= got.br_startoff + got.br_blockcount)
- low = lastx + 1;
- else {
- got.br_startblock = xfs_bmbt_get_startblock(ep);
- got.br_state = xfs_bmbt_get_state(ep);
- *eofp = 0;
- *lastxp = lastx;
- *gotp = got;
- return ep;
- }
- }
- if (bno >= got.br_startoff + got.br_blockcount) {
- lastx++;
- if (lastx == nextents) {
- *eofp = 1;
- got.br_startblock = xfs_bmbt_get_startblock(ep);
- got.br_state = xfs_bmbt_get_state(ep);
- *prevp = got;
- ep = NULL;
- } else {
- *eofp = 0;
- xfs_bmbt_get_all(ep, prevp);
- ep++;
- got.br_startoff = xfs_bmbt_get_startoff(ep);
- got.br_blockcount = xfs_bmbt_get_blockcount(ep);
- }
- } else {
- *eofp = 0;
- if (ep > base)
- xfs_bmbt_get_all(ep - 1, prevp);
- }
- }
- if (ep) {
- got.br_startblock = xfs_bmbt_get_startblock(ep);
- got.br_state = xfs_bmbt_get_state(ep);
- }
- *lastxp = lastx;
- *gotp = got;
- return ep;
-}
-
/*
* Search the extent records for the entry containing block bno.
* If bno lies in a hole, point to the next entry. If bno lies
@@ -4826,18 +4719,17 @@ xfs_bmapi(
/*
* Make a transaction-less quota reservation for
* delayed allocation blocks. This number gets
- * adjusted later.
- * We return EDQUOT if we haven't allocated
- * blks already inside this loop;
+ * adjusted later. We return if we haven't
+ * allocated blocks already inside this loop.
*/
- if (XFS_TRANS_RESERVE_QUOTA_NBLKS(
+ if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS(
mp, NULL, ip, (long)alen, 0,
rt ? XFS_QMOPT_RES_RTBLKS :
- XFS_QMOPT_RES_REGBLKS)) {
+ XFS_QMOPT_RES_REGBLKS))) {
if (n == 0) {
*nmap = 0;
ASSERT(cur == NULL);
- return XFS_ERROR(EDQUOT);
+ return error;
}
break;
}
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 011ccaa9a1c..8e0d73d9ccc 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -353,23 +353,16 @@ xfs_check_nostate_extents(
xfs_extnum_t num);
/*
- * Call xfs_bmap_do_search_extents() to search for the extent
- * record containing block bno. If in multi-level in-core extent
- * allocation mode, find and extract the target extent buffer,
- * otherwise just use the direct extent list.
+ * Search the extent records for the entry containing block bno.
+ * If bno lies in a hole, point to the next entry. If bno lies
+ * past eof, *eofp will be set, and *prevp will contain the last
+ * entry (null if none). Else, *lastxp will be set to the index
+ * of the found entry; *gotp will contain the entry.
*/
xfs_bmbt_rec_t *
xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *,
xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *);
-/*
- * Search an extent list for the extent which includes block
- * bno.
- */
-xfs_bmbt_rec_t *xfs_bmap_do_search_extents(xfs_bmbt_rec_t *,
- xfs_extnum_t, xfs_extnum_t, xfs_fileoff_t, int *,
- xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *);
-
#endif /* __KERNEL__ */
#endif /* __XFS_BMAP_H__ */
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 07e2324152b..5fed15682dd 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -98,12 +98,12 @@ xfs_buf_item_flush_log_debug(
}
/*
- * This function is called to verify that our caller's have logged
+ * This function is called to verify that our callers have logged
* all the bytes that they changed.
*
* It does this by comparing the original copy of the buffer stored in
* the buf log item's bli_orig array to the current copy of the buffer
- * and ensuring that all bytes which miscompare are set in the bli_logged
+ * and ensuring that all bytes which mismatch are set in the bli_logged
* array of the buf log item.
*/
STATIC void
diff --git a/fs/xfs/xfs_cap.h b/fs/xfs/xfs_cap.h
index 433ec537f9b..d0035c6e951 100644
--- a/fs/xfs/xfs_cap.h
+++ b/fs/xfs/xfs_cap.h
@@ -38,7 +38,7 @@ typedef struct xfs_cap_set {
/*
* For Linux, we take the bitfields directly from capability.h
* and no longer attempt to keep this attribute ondisk compatible
- * with IRIX. Since this attribute is only set on exectuables,
+ * with IRIX. Since this attribute is only set on executables,
* it just doesn't make much sense to try. We do use a different
* named attribute though, to avoid confusion.
*/
diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h
index 022fff62085..5b7eb81453b 100644
--- a/fs/xfs/xfs_clnt.h
+++ b/fs/xfs/xfs_clnt.h
@@ -68,6 +68,7 @@ struct xfs_mount_args {
* enforcement */
#define XFSMNT_PQUOTAENF 0x00000040 /* IRIX project quota limit
* enforcement */
+#define XFSMNT_QUIET 0x00000080 /* don't report mount errors */
#define XFSMNT_NOALIGN 0x00000200 /* don't allocate at
* stripe boundaries*/
#define XFSMNT_RETERR 0x00000400 /* return error to user */
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 4bae3a76c67..8988b905117 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -840,7 +840,7 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action)
/*
* Check for the degenerate case of the block being empty.
* If the block is empty, we'll simply delete it, no need to
- * coalesce it with a sibling block. We choose (aribtrarily)
+ * coalesce it with a sibling block. We choose (arbitrarily)
* to merge with the forward block unless it is NULL.
*/
if (count == 0) {
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index bd5cee6aa51..972ded59547 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -533,7 +533,7 @@ xfs_dir2_block_getdents(
/*
* Reached the end of the block.
- * Set the offset to a nonexistent block 1 and return.
+ * Set the offset to a non-existent block 1 and return.
*/
*eofp = 1;
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 08648b18265..0f5e2f2ce6e 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -515,7 +515,7 @@ xfs_dir2_leaf_addname(
ASSERT(be32_to_cpu(leaf->ents[highstale].address) ==
XFS_DIR2_NULL_DATAPTR);
/*
- * Copy entries down to copver the stale entry
+ * Copy entries down to cover the stale entry
* and make room for the new entry.
*/
if (highstale - index > 0)
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index af556f16a0c..ac511ab9c52 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -830,7 +830,7 @@ xfs_dir2_leafn_rebalance(
state->inleaf = 1;
blk2->index = 0;
cmn_err(CE_ALERT,
- "xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting orignal leaf: "
+ "xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting original leaf: "
"blk1->index %d\n",
blk1->index);
}
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c
index ee88751c3be..6d711869262 100644
--- a/fs/xfs/xfs_dir_leaf.c
+++ b/fs/xfs/xfs_dir_leaf.c
@@ -1341,7 +1341,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action)
/*
* Check for the degenerate case of the block being empty.
* If the block is empty, we'll simply delete it, no need to
- * coalesce it with a sibling block. We choose (aribtrarily)
+ * coalesce it with a sibling block. We choose (arbitrarily)
* to merge with the forward block unless it is NULL.
*/
if (count == 0) {
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 26b8e709a56..bc43163456e 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -186,4 +186,7 @@ extern void xfs_fs_cmn_err(int level, struct xfs_mount *mp, char *fmt, ...);
#define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \
xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args)
+#define xfs_fs_mount_cmn_err(f, fmt, args...) \
+ ((f & XFS_MFSI_QUIET)? cmn_err(CE_WARN, "XFS: " fmt, ## args) : (void)0)
+
#endif /* __XFS_ERROR_H__ */
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 56caa88713a..dfa3527b20a 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -477,7 +477,7 @@ xfs_fs_counts(
*
* xfs_reserve_blocks is called to set m_resblks
* in the in-core mount table. The number of unused reserved blocks
- * is kept in m_resbls_avail.
+ * is kept in m_resblks_avail.
*
* Reserve the requested number of blocks if available. Otherwise return
* as many as possible to satisfy the request. The actual number
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 0024892841a..deddbd03c16 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -136,7 +136,7 @@ xfs_ialloc_ag_alloc(
int ninodes; /* num inodes per buf */
xfs_agino_t thisino; /* current inode number, for loop */
int version; /* inode version number to use */
- int isaligned; /* inode allocation at stripe unit */
+ int isaligned = 0; /* inode allocation at stripe unit */
/* boundary */
args.tp = tp;
@@ -152,46 +152,75 @@ xfs_ialloc_ag_alloc(
return XFS_ERROR(ENOSPC);
args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(args.mp);
/*
- * Set the alignment for the allocation.
- * If stripe alignment is turned on then align at stripe unit
- * boundary.
- * If the cluster size is smaller than a filesystem block
- * then we're doing I/O for inodes in filesystem block size pieces,
- * so don't need alignment anyway.
- */
- isaligned = 0;
- if (args.mp->m_sinoalign) {
- ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
- args.alignment = args.mp->m_dalign;
- isaligned = 1;
- } else if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) &&
- args.mp->m_sb.sb_inoalignmt >=
- XFS_B_TO_FSBT(args.mp, XFS_INODE_CLUSTER_SIZE(args.mp)))
- args.alignment = args.mp->m_sb.sb_inoalignmt;
- else
- args.alignment = 1;
+ * First try to allocate inodes contiguous with the last-allocated
+ * chunk of inodes. If the filesystem is striped, this will fill
+ * an entire stripe unit with inodes.
+ */
agi = XFS_BUF_TO_AGI(agbp);
- /*
- * Need to figure out where to allocate the inode blocks.
- * Ideally they should be spaced out through the a.g.
- * For now, just allocate blocks up front.
- */
- args.agbno = be32_to_cpu(agi->agi_root);
- args.fsbno = XFS_AGB_TO_FSB(args.mp, be32_to_cpu(agi->agi_seqno),
- args.agbno);
- /*
- * Allocate a fixed-size extent of inodes.
- */
- args.type = XFS_ALLOCTYPE_NEAR_BNO;
- args.mod = args.total = args.wasdel = args.isfl = args.userdata =
- args.minalignslop = 0;
- args.prod = 1;
- /*
- * Allow space for the inode btree to split.
- */
- args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
- if ((error = xfs_alloc_vextent(&args)))
- return error;
+ newino = be32_to_cpu(agi->agi_newino);
+ args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
+ XFS_IALLOC_BLOCKS(args.mp);
+ if (likely(newino != NULLAGINO &&
+ (args.agbno < be32_to_cpu(agi->agi_length)))) {
+ args.fsbno = XFS_AGB_TO_FSB(args.mp,
+ be32_to_cpu(agi->agi_seqno), args.agbno);
+ args.type = XFS_ALLOCTYPE_THIS_BNO;
+ args.mod = args.total = args.wasdel = args.isfl =
+ args.userdata = args.minalignslop = 0;
+ args.prod = 1;
+ args.alignment = 1;
+ /*
+ * Allow space for the inode btree to split.
+ */
+ args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
+ if ((error = xfs_alloc_vextent(&args)))
+ return error;
+ } else
+ args.fsbno = NULLFSBLOCK;
+
+ if (unlikely(args.fsbno == NULLFSBLOCK)) {
+ /*
+ * Set the alignment for the allocation.
+ * If stripe alignment is turned on then align at stripe unit
+ * boundary.
+ * If the cluster size is smaller than a filesystem block
+ * then we're doing I/O for inodes in filesystem block size
+ * pieces, so don't need alignment anyway.
+ */
+ isaligned = 0;
+ if (args.mp->m_sinoalign) {
+ ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
+ args.alignment = args.mp->m_dalign;
+ isaligned = 1;
+ } else if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) &&
+ args.mp->m_sb.sb_inoalignmt >=
+ XFS_B_TO_FSBT(args.mp,
+ XFS_INODE_CLUSTER_SIZE(args.mp)))
+ args.alignment = args.mp->m_sb.sb_inoalignmt;
+ else
+ args.alignment = 1;
+ /*
+ * Need to figure out where to allocate the inode blocks.
+ * Ideally they should be spaced out through the a.g.
+ * For now, just allocate blocks up front.
+ */
+ args.agbno = be32_to_cpu(agi->agi_root);
+ args.fsbno = XFS_AGB_TO_FSB(args.mp,
+ be32_to_cpu(agi->agi_seqno), args.agbno);
+ /*
+ * Allocate a fixed-size extent of inodes.
+ */
+ args.type = XFS_ALLOCTYPE_NEAR_BNO;
+ args.mod = args.total = args.wasdel = args.isfl =
+ args.userdata = args.minalignslop = 0;
+ args.prod = 1;
+ /*
+ * Allow space for the inode btree to split.
+ */
+ args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
+ if ((error = xfs_alloc_vextent(&args)))
+ return error;
+ }
/*
* If stripe alignment is turned on, then try again with cluster
@@ -1023,7 +1052,7 @@ xfs_difree(
rec.ir_freecount++;
/*
- * When an inode cluster is free, it becomes elgible for removal
+ * When an inode cluster is free, it becomes eligible for removal
*/
if ((mp->m_flags & XFS_MOUNT_IDELETE) &&
(rec.ir_freecount == XFS_IALLOC_INODES(mp))) {
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 3ce35a6f700..b5385432526 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -421,7 +421,10 @@ finish_inode:
ip->i_chash = chlnew;
chlnew->chl_ip = ip;
chlnew->chl_blkno = ip->i_blkno;
+ if (ch->ch_list)
+ ch->ch_list->chl_prev = chlnew;
chlnew->chl_next = ch->ch_list;
+ chlnew->chl_prev = NULL;
ch->ch_list = chlnew;
chlnew = NULL;
}
@@ -509,7 +512,7 @@ retry:
} else {
/*
* If the inode is not fully constructed due to
- * filehandle mistmatches wait for the inode to go
+ * filehandle mismatches wait for the inode to go
* away and try again.
*
* iget_locked will call __wait_on_freeing_inode
@@ -723,23 +726,15 @@ xfs_iextract(
ASSERT(ip->i_cnext == ip && ip->i_cprev == ip);
ASSERT(ip->i_chash != NULL);
chm=NULL;
- for (chl = ch->ch_list; chl != NULL; chl = chl->chl_next) {
- if (chl->chl_blkno == ip->i_blkno) {
- if (chm == NULL) {
- /* first item on the list */
- ch->ch_list = chl->chl_next;
- } else {
- chm->chl_next = chl->chl_next;
- }
- kmem_zone_free(xfs_chashlist_zone, chl);
- break;
- } else {
- ASSERT(chl->chl_ip != ip);
- chm = chl;
- }
- }
- ASSERT_ALWAYS(chl != NULL);
- } else {
+ chl = ip->i_chash;
+ if (chl->chl_prev)
+ chl->chl_prev->chl_next = chl->chl_next;
+ else
+ ch->ch_list = chl->chl_next;
+ if (chl->chl_next)
+ chl->chl_next->chl_prev = chl->chl_prev;
+ kmem_zone_free(xfs_chashlist_zone, chl);
+ } else {
/* delete one inode from a non-empty list */
iq = ip->i_cnext;
iq->i_cprev = ip->i_cprev;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 88a517fad07..94b60dd0380 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -160,7 +160,7 @@ xfs_inotobp(
xfs_dinode_t *dip;
/*
- * Call the space managment code to find the location of the
+ * Call the space management code to find the location of the
* inode on disk.
*/
imap.im_blkno = 0;
@@ -837,7 +837,7 @@ xfs_dic2xflags(
/*
* Given a mount structure and an inode number, return a pointer
- * to a newly allocated in-core inode coresponding to the given
+ * to a newly allocated in-core inode corresponding to the given
* inode number.
*
* Initialize the inode's attributes and extent pointers if it
@@ -2723,7 +2723,7 @@ xfs_ipin(
/*
* Decrement the pin count of the given inode, and wake up
* anyone in xfs_iwait_unpin() if the count goes to 0. The
- * inode must have been previoulsy pinned with a call to xfs_ipin().
+ * inode must have been previously pinned with a call to xfs_ipin().
*/
void
xfs_iunpin(
@@ -2732,16 +2732,29 @@ xfs_iunpin(
ASSERT(atomic_read(&ip->i_pincount) > 0);
if (atomic_dec_and_test(&ip->i_pincount)) {
- vnode_t *vp = XFS_ITOV_NULL(ip);
+ /*
+ * If the inode is currently being reclaimed, the
+ * linux inode _and_ the xfs vnode may have been
+ * freed so we cannot reference either of them safely.
+ * Hence we should not try to do anything to them
+ * if the xfs inode is currently in the reclaim
+ * path.
+ *
+ * However, we still need to issue the unpin wakeup
+ * call as the inode reclaim may be blocked waiting for
+ * the inode to become unpinned.
+ */
+ if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) {
+ vnode_t *vp = XFS_ITOV_NULL(ip);
- /* make sync come back and flush this inode */
- if (vp) {
- struct inode *inode = vn_to_inode(vp);
+ /* make sync come back and flush this inode */
+ if (vp) {
+ struct inode *inode = vn_to_inode(vp);
- if (!(inode->i_state & I_NEW))
- mark_inode_dirty_sync(inode);
+ if (!(inode->i_state & I_NEW))
+ mark_inode_dirty_sync(inode);
+ }
}
-
wake_up(&ip->i_ipin_wait);
}
}
@@ -3690,7 +3703,7 @@ void
xfs_iext_add(
xfs_ifork_t *ifp, /* inode fork pointer */
xfs_extnum_t idx, /* index to begin adding exts */
- int ext_diff) /* nubmer of extents to add */
+ int ext_diff) /* number of extents to add */
{
int byte_diff; /* new bytes being added */
int new_size; /* size of extents after adding */
@@ -4038,7 +4051,7 @@ xfs_iext_remove_indirect(
xfs_extnum_t ext_diff; /* extents to remove in current list */
xfs_extnum_t nex1; /* number of extents before idx */
xfs_extnum_t nex2; /* extents after idx + count */
- int nlists; /* entries in indirecton array */
+ int nlists; /* entries in indirection array */
int page_idx = idx; /* index in target extent list */
ASSERT(ifp->if_flags & XFS_IFEXTIREC);
@@ -4291,9 +4304,9 @@ xfs_iext_bno_to_ext(
xfs_filblks_t blockcount = 0; /* number of blocks in extent */
xfs_bmbt_rec_t *ep = NULL; /* pointer to target extent */
xfs_ext_irec_t *erp = NULL; /* indirection array pointer */
- int high; /* upper boundry in search */
+ int high; /* upper boundary in search */
xfs_extnum_t idx = 0; /* index of target extent */
- int low; /* lower boundry in search */
+ int low; /* lower boundary in search */
xfs_extnum_t nextents; /* number of file extents */
xfs_fileoff_t startoff = 0; /* start offset of extent */
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 39ef9c36ea5..3b544db1790 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -189,6 +189,7 @@ typedef struct xfs_ihash {
*/
typedef struct xfs_chashlist {
struct xfs_chashlist *chl_next;
+ struct xfs_chashlist *chl_prev;
struct xfs_inode *chl_ip;
xfs_daddr_t chl_blkno; /* starting block number of
* the cluster */
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 36aa1fcb90a..7497a481b2f 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -580,7 +580,7 @@ xfs_inode_item_unpin_remove(
* been or is in the process of being flushed, then (ideally) we'd like to
* see if the inode's buffer is still incore, and if so give it a nudge.
* We delay doing so until the pushbuf routine, though, to avoid holding
- * the AIL lock across a call to the blackhole which is the buffercache.
+ * the AIL lock across a call to the blackhole which is the buffer cache.
* Also we don't want to sleep in any device strategy routines, which can happen
* if we do the subsequent bawrite in here.
*/
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 32247b6bfee..94068d014f2 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -272,7 +272,7 @@ xfs_bulkstat(
size_t statstruct_size, /* sizeof struct filling */
char __user *ubuffer, /* buffer with inode stats */
int flags, /* defined in xfs_itable.h */
- int *done) /* 1 if there're more stats to get */
+ int *done) /* 1 if there are more stats to get */
{
xfs_agblock_t agbno=0;/* allocation group block number */
xfs_buf_t *agbp; /* agi header buffer */
@@ -676,7 +676,7 @@ xfs_bulkstat_single(
xfs_mount_t *mp, /* mount point for filesystem */
xfs_ino_t *lastinop, /* inode to return */
char __user *buffer, /* buffer with inode stats */
- int *done) /* 1 if there're more stats to get */
+ int *done) /* 1 if there are more stats to get */
{
int count; /* count value for bulkstat call */
int error; /* return value */
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 047d834ed21..11eb4e1b18c 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -60,7 +60,7 @@ xfs_bulkstat(
size_t statstruct_size,/* sizeof struct that we're filling */
char __user *ubuffer,/* buffer with inode stats */
int flags, /* flag to control access method */
- int *done); /* 1 if there're more stats to get */
+ int *done); /* 1 if there are more stats to get */
int
xfs_bulkstat_single(
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 9176995160e..32e841d2f26 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -59,7 +59,7 @@ STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp,
int num_bblks);
STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes);
STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog);
-STATIC void xlog_unalloc_log(xlog_t *log);
+STATIC void xlog_dealloc_log(xlog_t *log);
STATIC int xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[],
int nentries, xfs_log_ticket_t tic,
xfs_lsn_t *start_lsn,
@@ -304,7 +304,7 @@ xfs_log_done(xfs_mount_t *mp,
if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) == 0 ||
(flags & XFS_LOG_REL_PERM_RESERV)) {
/*
- * Release ticket if not permanent reservation or a specifc
+ * Release ticket if not permanent reservation or a specific
* request has been made to release a permanent reservation.
*/
xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)");
@@ -511,7 +511,7 @@ xfs_log_mount(xfs_mount_t *mp,
vfsp->vfs_flag |= VFS_RDONLY;
if (error) {
cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);
- xlog_unalloc_log(mp->m_log);
+ xlog_dealloc_log(mp->m_log);
return error;
}
}
@@ -667,7 +667,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
*
* Go through the motions of sync'ing and releasing
* the iclog, even though no I/O will actually happen,
- * we need to wait for other log I/O's that may already
+ * we need to wait for other log I/Os that may already
* be in progress. Do this as a separate section of
* code so we'll know if we ever get stuck here that
* we're in this odd situation of trying to unmount
@@ -704,7 +704,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
void
xfs_log_unmount_dealloc(xfs_mount_t *mp)
{
- xlog_unalloc_log(mp->m_log);
+ xlog_dealloc_log(mp->m_log);
}
/*
@@ -1492,7 +1492,7 @@ xlog_sync(xlog_t *log,
ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);
- /* account for internal log which does't start at block #0 */
+ /* account for internal log which doesn't start at block #0 */
XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart);
XFS_BUF_WRITE(bp);
if ((error = XFS_bwrite(bp))) {
@@ -1506,10 +1506,10 @@ xlog_sync(xlog_t *log,
/*
- * Unallocate a log structure
+ * Deallocate a log structure
*/
void
-xlog_unalloc_log(xlog_t *log)
+xlog_dealloc_log(xlog_t *log)
{
xlog_in_core_t *iclog, *next_iclog;
xlog_ticket_t *tic, *next_tic;
@@ -1539,7 +1539,7 @@ xlog_unalloc_log(xlog_t *log)
if ((log->l_ticket_cnt != log->l_ticket_tcnt) &&
!XLOG_FORCED_SHUTDOWN(log)) {
xfs_fs_cmn_err(CE_WARN, log->l_mp,
- "xlog_unalloc_log: (cnt: %d, total: %d)",
+ "xlog_dealloc_log: (cnt: %d, total: %d)",
log->l_ticket_cnt, log->l_ticket_tcnt);
/* ASSERT(log->l_ticket_cnt == log->l_ticket_tcnt); */
@@ -1562,7 +1562,7 @@ xlog_unalloc_log(xlog_t *log)
#endif
log->l_mp->m_log = NULL;
kmem_free(log, sizeof(xlog_t));
-} /* xlog_unalloc_log */
+} /* xlog_dealloc_log */
/*
* Update counters atomically now that memcpy is done.
@@ -2829,7 +2829,7 @@ xlog_state_release_iclog(xlog_t *log,
/*
* We let the log lock go, so it's possible that we hit a log I/O
- * error or someother SHUTDOWN condition that marks the iclog
+ * error or some other SHUTDOWN condition that marks the iclog
* as XLOG_STATE_IOERROR before the bwrite. However, we know that
* this iclog has consistent data, so we ignore IOERROR
* flags after this point.
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 4b2ac88dbb8..eacb3d4987f 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -27,7 +27,7 @@
#ifdef __KERNEL__
/*
- * By comparing each compnent, we don't have to worry about extra
+ * By comparing each component, we don't have to worry about extra
* endian issues in treating two 32 bit numbers as one 64 bit number
*/
static inline xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index add13f507ed..1f0016b0b4e 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -583,7 +583,7 @@ xlog_find_head(
* x | x ... | x - 1 | x
* Another case that fits this picture would be
* x | x + 1 | x ... | x
- * In this case the head really is somwhere at the end of the
+ * In this case the head really is somewhere at the end of the
* log, as one of the latest writes at the beginning was
* incomplete.
* One more case is
@@ -2799,7 +2799,7 @@ xlog_recover_do_trans(
* we don't need to worry about the block number being
* truncated in > 1 TB buffers because in user-land,
* we're now n32 or 64-bit so xfs_daddr_t is 64-bits so
- * the blkno's will get through the user-mode buffer
+ * the blknos will get through the user-mode buffer
* cache properly. The only bad case is o32 kernels
* where xfs_daddr_t is 32-bits but mount will warn us
* off a > 1 TB filesystem before we get here.
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 20e8abc16d1..c0b1c290688 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -213,7 +213,8 @@ xfs_mount_free(
STATIC int
xfs_mount_validate_sb(
xfs_mount_t *mp,
- xfs_sb_t *sbp)
+ xfs_sb_t *sbp,
+ int flags)
{
/*
* If the log device and data device have the
@@ -223,33 +224,29 @@ xfs_mount_validate_sb(
* a volume filesystem in a non-volume manner.
*/
if (sbp->sb_magicnum != XFS_SB_MAGIC) {
- cmn_err(CE_WARN, "XFS: bad magic number");
+ xfs_fs_mount_cmn_err(flags, "bad magic number");
return XFS_ERROR(EWRONGFS);
}
if (!XFS_SB_GOOD_VERSION(sbp)) {
- cmn_err(CE_WARN, "XFS: bad version");
+ xfs_fs_mount_cmn_err(flags, "bad version");
return XFS_ERROR(EWRONGFS);
}
if (unlikely(
sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
- cmn_err(CE_WARN,
- "XFS: filesystem is marked as having an external log; "
- "specify logdev on the\nmount command line.");
- XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(1)",
- XFS_ERRLEVEL_HIGH, mp, sbp);
- return XFS_ERROR(EFSCORRUPTED);
+ xfs_fs_mount_cmn_err(flags,
+ "filesystem is marked as having an external log; "
+ "specify logdev on the\nmount command line.");
+ return XFS_ERROR(EINVAL);
}
if (unlikely(
sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
- cmn_err(CE_WARN,
- "XFS: filesystem is marked as having an internal log; "
- "don't specify logdev on\nthe mount command line.");
- XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(2)",
- XFS_ERRLEVEL_HIGH, mp, sbp);
- return XFS_ERROR(EFSCORRUPTED);
+ xfs_fs_mount_cmn_err(flags,
+ "filesystem is marked as having an internal log; "
+ "do not specify logdev on\nthe mount command line.");
+ return XFS_ERROR(EINVAL);
}
/*
@@ -273,10 +270,8 @@ xfs_mount_validate_sb(
(sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) ||
(sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) ||
(sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) ||
- (sbp->sb_imax_pct > 100 || sbp->sb_imax_pct < 1))) {
- cmn_err(CE_WARN, "XFS: SB sanity check 1 failed");
- XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(3)",
- XFS_ERRLEVEL_LOW, mp, sbp);
+ (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) {
+ xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed");
return XFS_ERROR(EFSCORRUPTED);
}
@@ -289,9 +284,7 @@ xfs_mount_validate_sb(
(xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||
sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *
sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {
- cmn_err(CE_WARN, "XFS: SB sanity check 2 failed");
- XFS_ERROR_REPORT("xfs_mount_validate_sb(4)",
- XFS_ERRLEVEL_LOW, mp);
+ xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed");
return XFS_ERROR(EFSCORRUPTED);
}
@@ -307,15 +300,13 @@ xfs_mount_validate_sb(
(sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
(sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
#endif
- cmn_err(CE_WARN,
- "XFS: File system is too large to be mounted on this system.");
+ xfs_fs_mount_cmn_err(flags,
+ "file system too large to be mounted on this system.");
return XFS_ERROR(E2BIG);
}
if (unlikely(sbp->sb_inprogress)) {
- cmn_err(CE_WARN, "XFS: file system busy");
- XFS_ERROR_REPORT("xfs_mount_validate_sb(5)",
- XFS_ERRLEVEL_LOW, mp);
+ xfs_fs_mount_cmn_err(flags, "file system busy");
return XFS_ERROR(EFSCORRUPTED);
}
@@ -323,8 +314,8 @@ xfs_mount_validate_sb(
* Version 1 directory format has never worked on Linux.
*/
if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) {
- cmn_err(CE_WARN,
- "XFS: Attempted to mount file system using version 1 directory format");
+ xfs_fs_mount_cmn_err(flags,
+ "file system using version 1 directory format");
return XFS_ERROR(ENOSYS);
}
@@ -332,11 +323,11 @@ xfs_mount_validate_sb(
* Until this is fixed only page-sized or smaller data blocks work.
*/
if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
- cmn_err(CE_WARN,
- "XFS: Attempted to mount file system with blocksize %d bytes",
+ xfs_fs_mount_cmn_err(flags,
+ "file system with blocksize %d bytes",
sbp->sb_blocksize);
- cmn_err(CE_WARN,
- "XFS: Only page-sized (%ld) or less blocksizes currently work.",
+ xfs_fs_mount_cmn_err(flags,
+ "only pagesize (%ld) or less will currently work.",
PAGE_SIZE);
return XFS_ERROR(ENOSYS);
}
@@ -393,7 +384,7 @@ xfs_initialize_perag(
break;
}
- /* This ag is prefered for inodes */
+ /* This ag is preferred for inodes */
pag = &mp->m_perag[index];
pag->pagi_inodeok = 1;
if (index < max_metadata)
@@ -484,7 +475,7 @@ xfs_xlatesb(
* Does the initial read of the superblock.
*/
int
-xfs_readsb(xfs_mount_t *mp)
+xfs_readsb(xfs_mount_t *mp, int flags)
{
unsigned int sector_size;
unsigned int extra_flags;
@@ -506,7 +497,7 @@ xfs_readsb(xfs_mount_t *mp)
bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
BTOBB(sector_size), extra_flags);
if (!bp || XFS_BUF_ISERROR(bp)) {
- cmn_err(CE_WARN, "XFS: SB read failed");
+ xfs_fs_mount_cmn_err(flags, "SB read failed");
error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
goto fail;
}
@@ -520,9 +511,9 @@ xfs_readsb(xfs_mount_t *mp)
sbp = XFS_BUF_TO_SBP(bp);
xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS);
- error = xfs_mount_validate_sb(mp, &(mp->m_sb));
+ error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
if (error) {
- cmn_err(CE_WARN, "XFS: SB validate failed");
+ xfs_fs_mount_cmn_err(flags, "SB validate failed");
goto fail;
}
@@ -530,8 +521,8 @@ xfs_readsb(xfs_mount_t *mp)
* We must be able to do sector-sized and sector-aligned IO.
*/
if (sector_size > mp->m_sb.sb_sectsize) {
- cmn_err(CE_WARN,
- "XFS: device supports only %u byte sectors (not %u)",
+ xfs_fs_mount_cmn_err(flags,
+ "device supports only %u byte sectors (not %u)",
sector_size, mp->m_sb.sb_sectsize);
error = ENOSYS;
goto fail;
@@ -548,7 +539,7 @@ xfs_readsb(xfs_mount_t *mp)
bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
BTOBB(sector_size), extra_flags);
if (!bp || XFS_BUF_ISERROR(bp)) {
- cmn_err(CE_WARN, "XFS: SB re-read failed");
+ xfs_fs_mount_cmn_err(flags, "SB re-read failed");
error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
goto fail;
}
@@ -678,7 +669,7 @@ xfs_mountfs(
int error = 0;
if (mp->m_sb_bp == NULL) {
- if ((error = xfs_readsb(mp))) {
+ if ((error = xfs_readsb(mp, mfsi_flags))) {
return error;
}
}
@@ -1728,7 +1719,7 @@ xfs_mount_log_sbunit(
* We cannot use the hotcpu_register() function because it does
* not allow notifier instances. We need a notifier per filesystem
* as we need to be able to identify the filesystem to balance
- * the counters out. This is acheived by having a notifier block
+ * the counters out. This is achieved by having a notifier block
* embedded in the xfs_mount_t and doing pointer magic to get the
* mount pointer from the notifier block address.
*/
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index ebd73960e9d..668ad23fd37 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -379,7 +379,7 @@ typedef struct xfs_mount {
#endif
int m_dalign; /* stripe unit */
int m_swidth; /* stripe width */
- int m_sinoalign; /* stripe unit inode alignmnt */
+ int m_sinoalign; /* stripe unit inode alignment */
int m_attr_magicpct;/* 37% of the blocksize */
int m_dir_magicpct; /* 37% of the dir blocksize */
__uint8_t m_mk_sharedro; /* mark shared ro on unmount */
@@ -510,9 +510,12 @@ xfs_preferred_iosize(xfs_mount_t *mp)
*/
#define XFS_MFSI_SECOND 0x01 /* Secondary mount -- skip stuff */
#define XFS_MFSI_CLIENT 0x02 /* Is a client -- skip lots of stuff */
+/* XFS_MFSI_RRINODES */
#define XFS_MFSI_NOUNLINK 0x08 /* Skip unlinked inode processing in */
/* log recovery */
#define XFS_MFSI_NO_QUOTACHECK 0x10 /* Skip quotacheck processing */
+/* XFS_MFSI_CONVERT_SUNIT */
+#define XFS_MFSI_QUIET 0x40 /* Be silent if mount errors found */
/*
* Macros for getting from mount to vfs and back.
@@ -581,7 +584,7 @@ extern int xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t,
extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
uint, int);
extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
-extern int xfs_readsb(xfs_mount_t *mp);
+extern int xfs_readsb(xfs_mount_t *, int);
extern void xfs_freesb(xfs_mount_t *);
extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
extern int xfs_syncsub(xfs_mount_t *, int, int, int *);
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 82a08baf437..7fbef974bce 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -31,7 +31,7 @@
typedef __uint32_t xfs_dqid_t;
/*
- * Eventhough users may not have quota limits occupying all 64-bits,
+ * Even though users may not have quota limits occupying all 64-bits,
* they may need 64-bit accounting. Hence, 64-bit quota-counters,
* and quota-limits. This is a waste in the common case, but hey ...
*/
@@ -196,10 +196,11 @@ typedef struct xfs_qoff_logformat {
#define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */
#define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */
#define XFS_QMOPT_DOLOG 0x0000200 /* log buf changes (in quotacheck) */
-#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */
+#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if needed */
#define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */
-#define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot, if damaged. */
+#define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot if damaged */
#define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */
+#define XFS_QMOPT_ENOSPC 0x0004000 /* enospc instead of edquot (prj) */
/*
* flags to xfs_trans_mod_dquot to indicate which field needs to be
@@ -246,7 +247,7 @@ typedef struct xfs_qoff_logformat {
#ifdef __KERNEL__
/*
* This check is done typically without holding the inode lock;
- * that may seem racey, but it is harmless in the context that it is used.
+ * that may seem racy, but it is harmless in the context that it is used.
* The inode cannot go inactive as long a reference is kept, and
* therefore if dquot(s) were attached, they'll stay consistent.
* If, for example, the ownership of the inode changes while
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 81a05cfd77d..1f148762eb2 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -316,6 +316,18 @@ xfs_rename(
}
}
+ /*
+ * If we are using project inheritance, we only allow renames
+ * into our tree when the project IDs are the same; else the
+ * tree quota mechanism would be circumvented.
+ */
+ if (unlikely((target_dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
+ (target_dp->i_d.di_projid != src_ip->i_d.di_projid))) {
+ error = XFS_ERROR(EXDEV);
+ xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
+ goto rele_return;
+ }
+
new_parent = (src_dp != target_dp);
src_is_directory = ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 2918956553a..8d056cef5d1 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -490,7 +490,7 @@ xfs_trans_mod_sb(
case XFS_TRANS_SB_RES_FREXTENTS:
/*
* The allocation has already been applied to the
- * in-core superblocks's counter. This should only
+ * in-core superblock's counter. This should only
* be applied to the on-disk superblock.
*/
ASSERT(delta < 0);
@@ -611,7 +611,7 @@ xfs_trans_apply_sb_deltas(
if (whole)
/*
- * Log the whole thing, the fields are discontiguous.
+ * Log the whole thing, the fields are noncontiguous.
*/
xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_sb_t) - 1);
else
@@ -669,7 +669,7 @@ xfs_trans_unreserve_and_mod_sb(
/*
* Apply any superblock modifications to the in-core version.
* The t_res_fdblocks_delta and t_res_frextents_delta fields are
- * explicity NOT applied to the in-core superblock.
+ * explicitly NOT applied to the in-core superblock.
* The idea is that that has already been done.
*/
if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index e48befa4e33..100d9a4b38e 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -354,7 +354,7 @@ typedef struct xfs_trans {
xfs_lsn_t t_commit_lsn; /* log seq num of end of
* transaction. */
struct xfs_mount *t_mountp; /* ptr to fs mount struct */
- struct xfs_dquot_acct *t_dqinfo; /* accting info for dquots */
+ struct xfs_dquot_acct *t_dqinfo; /* acctg info for dquots */
xfs_trans_callback_t t_callback; /* transaction callback */
void *t_callarg; /* callback arg */
unsigned int t_flags; /* misc flags */
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index e341409172d..7c5894d59f8 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -272,7 +272,7 @@ xfs_trans_log_inode(
* This is to coordinate with the xfs_iflush() and xfs_iflush_done()
* routines in the eventual clearing of the ilf_fields bits.
* See the big comment in xfs_iflush() for an explanation of
- * this coorination mechanism.
+ * this coordination mechanism.
*/
flags |= ip->i_itemp->ili_last_fields;
ip->i_itemp->ili_format.ilf_fields |= flags;
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index d4ec4dfaf19..36ea1b2094f 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -442,6 +442,9 @@ xfs_mount(
p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
+ if (args->flags & XFSMNT_QUIET)
+ flags |= XFS_MFSI_QUIET;
+
/*
* Open real time and log devices - order is important.
*/
@@ -492,7 +495,7 @@ xfs_mount(
error = xfs_start_flags(vfsp, args, mp);
if (error)
goto error1;
- error = xfs_readsb(mp);
+ error = xfs_readsb(mp, flags);
if (error)
goto error1;
error = xfs_finish_flags(vfsp, args, mp);
@@ -666,31 +669,22 @@ xfs_mntupdate(
xfs_mount_t *mp = XFS_BHVTOM(bdp);
int error;
- if (args->flags & XFSMNT_BARRIER)
- mp->m_flags |= XFS_MOUNT_BARRIER;
- else
- mp->m_flags &= ~XFS_MOUNT_BARRIER;
-
- if ((vfsp->vfs_flag & VFS_RDONLY) &&
- !(*flags & MS_RDONLY)) {
- vfsp->vfs_flag &= ~VFS_RDONLY;
-
- if (args->flags & XFSMNT_BARRIER)
+ if (!(*flags & MS_RDONLY)) { /* rw/ro -> rw */
+ if (vfsp->vfs_flag & VFS_RDONLY)
+ vfsp->vfs_flag &= ~VFS_RDONLY;
+ if (args->flags & XFSMNT_BARRIER) {
+ mp->m_flags |= XFS_MOUNT_BARRIER;
xfs_mountfs_check_barriers(mp);
- }
-
- if (!(vfsp->vfs_flag & VFS_RDONLY) &&
- (*flags & MS_RDONLY)) {
+ } else {
+ mp->m_flags &= ~XFS_MOUNT_BARRIER;
+ }
+ } else if (!(vfsp->vfs_flag & VFS_RDONLY)) { /* rw -> ro */
VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error);
-
xfs_quiesce_fs(mp);
-
- /* Ok now write out an unmount record */
xfs_log_unmount_write(mp);
xfs_unmountfs_writesb(mp);
vfsp->vfs_flag |= VFS_RDONLY;
}
-
return 0;
}
@@ -880,10 +874,10 @@ xfs_statvfs(
* determine if they should be flushed sync, async, or
* delwri.
* SYNC_CLOSE - This flag is passed when the system is being
- * unmounted. We should sync and invalidate everthing.
+ * unmounted. We should sync and invalidate everything.
* SYNC_FSDATA - This indicates that the caller would like to make
* sure the superblock is safe on disk. We can ensure
- * this by simply makeing sure the log gets flushed
+ * this by simply making sure the log gets flushed
* if SYNC_BDFLUSH is set, and by actually writing it
* out otherwise.
*
@@ -908,7 +902,7 @@ xfs_sync(
*
* This routine supports all of the flags defined for the generic VFS_SYNC
* interface as explained above under xfs_sync. In the interests of not
- * changing interfaces within the 6.5 family, additional internallly-
+ * changing interfaces within the 6.5 family, additional internally-
* required functions are specified within a separate xflags parameter,
* only available by calling this routine.
*
@@ -1090,7 +1084,7 @@ xfs_sync_inodes(
* If this is just vfs_sync() or pflushd() calling
* then we can skip inodes for which it looks like
* there is nothing to do. Since we don't have the
- * inode locked this is racey, but these are periodic
+ * inode locked this is racy, but these are periodic
* calls so it doesn't matter. For the others we want
* to know for sure, so we at least try to lock them.
*/
@@ -1429,7 +1423,7 @@ xfs_sync_inodes(
*
* This routine supports all of the flags defined for the generic VFS_SYNC
* interface as explained above under xfs_sync. In the interests of not
- * changing interfaces within the 6.5 family, additional internallly-
+ * changing interfaces within the 6.5 family, additional internally-
* required functions are specified within a separate xflags parameter,
* only available by calling this routine.
*
@@ -1697,8 +1691,9 @@ xfs_parseargs(
int dsunit, dswidth, vol_dsunit, vol_dswidth;
int iosize;
- args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
args->flags |= XFSMNT_IDELETE;
+ args->flags |= XFSMNT_BARRIER;
+ args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
if (!options)
goto done;
@@ -1947,8 +1942,6 @@ xfs_showargs(
seq_printf(m, "," MNTOPT_IKEEP);
if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE))
seq_printf(m, "," MNTOPT_LARGEIO);
- if (mp->m_flags & XFS_MOUNT_BARRIER)
- seq_printf(m, "," MNTOPT_BARRIER);
if (!(vfsp->vfs_flag & VFS_32BITINODES))
seq_printf(m, "," MNTOPT_64BITINODE);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 0f0a64e81db..7027ae68ee3 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -848,7 +848,7 @@ xfs_setattr(
* If this is a synchronous mount, make sure that the
* transaction goes to disk before returning to the user.
* This is slightly sub-optimal in that truncates require
- * two sync transactions instead of one for wsync filesytems.
+ * two sync transactions instead of one for wsync filesystems.
* One for the truncate and one for the timestamps since we
* don't want to change the timestamps unless we're sure the
* truncate worked. Truncates are less than 1% of the laddis
@@ -1170,7 +1170,7 @@ xfs_fsync(
/*
* If this inode is on the RT dev we need to flush that
- * cache aswell.
+ * cache as well.
*/
if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)
xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp);
@@ -1380,7 +1380,7 @@ xfs_inactive_symlink_rmt(
*/
ntp = xfs_trans_dup(tp);
/*
- * Commit the transaction containing extent freeing and EFD's.
+ * Commit the transaction containing extent freeing and EFDs.
* If we get an error on the commit here or on the reserve below,
* we need to unlock the inode since the new transaction doesn't
* have the inode attached.
@@ -2023,7 +2023,7 @@ xfs_create(
XFS_QM_DQRELE(mp, gdqp);
/*
- * Propogate the fact that the vnode changed after the
+ * Propagate the fact that the vnode changed after the
* xfs_inode locks have been released.
*/
VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_TRUNCATED, 3);
@@ -2370,7 +2370,7 @@ xfs_remove(
* for a log reservation. Since we'll have to wait for the
* inactive code to complete before returning from xfs_iget,
* we need to make sure that we don't have log space reserved
- * when we call xfs_iget. Instead we get an unlocked referece
+ * when we call xfs_iget. Instead we get an unlocked reference
* to the inode before getting our log reservation.
*/
error = xfs_get_dir_entry(dentry, &ip);
@@ -2663,7 +2663,7 @@ xfs_link(
*/
if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
(tdp->i_d.di_projid != sip->i_d.di_projid))) {
- error = XFS_ERROR(EPERM);
+ error = XFS_ERROR(EXDEV);
goto error_return;
}
@@ -3020,7 +3020,7 @@ xfs_rmdir(
* for a log reservation. Since we'll have to wait for the
* inactive code to complete before returning from xfs_iget,
* we need to make sure that we don't have log space reserved
- * when we call xfs_iget. Instead we get an unlocked referece
+ * when we call xfs_iget. Instead we get an unlocked reference
* to the inode before getting our log reservation.
*/
error = xfs_get_dir_entry(dentry, &cdp);
@@ -4649,6 +4649,10 @@ vnodeops_t xfs_vnodeops = {
#ifdef HAVE_SENDFILE
.vop_sendfile = xfs_sendfile,
#endif
+#ifdef HAVE_SPLICE
+ .vop_splice_read = xfs_splice_read,
+ .vop_splice_write = xfs_splice_write,
+#endif
.vop_write = xfs_write,
.vop_ioctl = xfs_ioctl,
.vop_getattr = xfs_getattr,
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index e27dc8f2997..b9beceb3314 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -63,7 +63,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20060127
+#define ACPI_CA_VERSION 0x20060608
/*
* OS name, used for the _OS object. The _OS object is essentially obsolete,
@@ -81,6 +81,7 @@
#define ACPI_MAX_PARSE_CACHE_DEPTH 96 /* Parse tree objects */
#define ACPI_MAX_EXTPARSE_CACHE_DEPTH 96 /* Parse tree objects */
#define ACPI_MAX_OBJECT_CACHE_DEPTH 96 /* Interpreter operand objects */
+#define ACPI_MAX_NAMESPACE_CACHE_DEPTH 96 /* Namespace objects */
/*
* Should the subsystem abort the loading of an ACPI table if the
@@ -102,9 +103,9 @@
#define ACPI_MAX_SEMAPHORE_COUNT 256
-/* Max reference count (for debug only) */
+/* Maximum object reference count (detects object deletion issues) */
-#define ACPI_MAX_REFERENCE_COUNT 0x400
+#define ACPI_MAX_REFERENCE_COUNT 0x800
/* Size of cached memory mapping for system memory operation region */
@@ -171,12 +172,7 @@
/* Array sizes. Used for range checking also */
-#define ACPI_NUM_ACCESS_TYPES 6
-#define ACPI_NUM_UPDATE_RULES 3
-#define ACPI_NUM_LOCK_RULES 2
-#define ACPI_NUM_MATCH_OPS 6
-#define ACPI_NUM_OPCODES 256
-#define ACPI_NUM_FIELD_NAMES 2
+#define ACPI_MAX_MATCH_OPCODE 5
/* RSDP checksums */
@@ -187,10 +183,6 @@
#define ACPI_SMBUS_BUFFER_SIZE 34
-/* Number of strings associated with the _OSI reserved method */
-
-#define ACPI_NUM_OSI_STRINGS 10
-
/******************************************************************************
*
* ACPI AML Debugger
diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h
index 11a8fe39cb0..9a7d6921f53 100644
--- a/include/acpi/acdisasm.h
+++ b/include/acpi/acdisasm.h
@@ -50,26 +50,72 @@
#define BLOCK_PAREN 1
#define BLOCK_BRACE 2
#define BLOCK_COMMA_LIST 4
+#define ACPI_DEFAULT_RESNAME *(u32 *) "__RD"
struct acpi_external_list {
char *path;
+ char *internal_path;
struct acpi_external_list *next;
+ u32 value;
+ u16 length;
+ u8 type;
};
extern struct acpi_external_list *acpi_gbl_external_list;
-/* Strings used for decoding flags to ASL keywords */
+typedef const struct acpi_dmtable_info {
+ u8 opcode;
+ u8 offset;
+ char *name;
+
+} acpi_dmtable_info;
+
+/*
+ * Values for Opcode above.
+ * Note: 0-7 must not change, used as a flag shift value
+ */
+#define ACPI_DMT_FLAG0 0
+#define ACPI_DMT_FLAG1 1
+#define ACPI_DMT_FLAG2 2
+#define ACPI_DMT_FLAG3 3
+#define ACPI_DMT_FLAG4 4
+#define ACPI_DMT_FLAG5 5
+#define ACPI_DMT_FLAG6 6
+#define ACPI_DMT_FLAG7 7
+#define ACPI_DMT_FLAGS0 8
+#define ACPI_DMT_FLAGS2 9
+#define ACPI_DMT_UINT8 10
+#define ACPI_DMT_UINT16 11
+#define ACPI_DMT_UINT24 12
+#define ACPI_DMT_UINT32 13
+#define ACPI_DMT_UINT56 14
+#define ACPI_DMT_UINT64 15
+#define ACPI_DMT_STRING 16
+#define ACPI_DMT_NAME4 17
+#define ACPI_DMT_NAME6 18
+#define ACPI_DMT_NAME8 19
+#define ACPI_DMT_CHKSUM 20
+#define ACPI_DMT_SPACEID 21
+#define ACPI_DMT_GAS 22
+#define ACPI_DMT_MADT 23
+#define ACPI_DMT_SRAT 24
+#define ACPI_DMT_EXIT 25
-extern const char *acpi_gbl_word_decode[4];
-extern const char *acpi_gbl_irq_decode[2];
-extern const char *acpi_gbl_lock_rule[ACPI_NUM_LOCK_RULES];
-extern const char *acpi_gbl_access_types[ACPI_NUM_ACCESS_TYPES];
-extern const char *acpi_gbl_update_rules[ACPI_NUM_UPDATE_RULES];
-extern const char *acpi_gbl_match_ops[ACPI_NUM_MATCH_OPS];
+typedef
+void (*ACPI_TABLE_HANDLER) (struct acpi_table_header * table);
+
+struct acpi_dmtable_data {
+ char *signature;
+ struct acpi_dmtable_info *table_info;
+ ACPI_TABLE_HANDLER table_handler;
+};
struct acpi_op_walk_info {
u32 level;
+ u32 last_level;
+ u32 count;
u32 bit_offset;
+ u32 flags;
struct acpi_walk_state *walk_state;
};
@@ -77,6 +123,100 @@ typedef
acpi_status(*asl_walk_callback) (union acpi_parse_object * op,
u32 level, void *context);
+struct acpi_resource_tag {
+ u32 bit_index;
+ char *tag;
+};
+
+/* Strings used for decoding flags to ASL keywords */
+
+extern const char *acpi_gbl_word_decode[];
+extern const char *acpi_gbl_irq_decode[];
+extern const char *acpi_gbl_lock_rule[];
+extern const char *acpi_gbl_access_types[];
+extern const char *acpi_gbl_update_rules[];
+extern const char *acpi_gbl_match_ops[];
+
+extern struct acpi_dmtable_info acpi_dm_table_info_asf0[];
+extern struct acpi_dmtable_info acpi_dm_table_info_asf1[];
+extern struct acpi_dmtable_info acpi_dm_table_info_asf2[];
+extern struct acpi_dmtable_info acpi_dm_table_info_asf3[];
+extern struct acpi_dmtable_info acpi_dm_table_info_asf4[];
+extern struct acpi_dmtable_info acpi_dm_table_info_asf_hdr[];
+extern struct acpi_dmtable_info acpi_dm_table_info_boot[];
+extern struct acpi_dmtable_info acpi_dm_table_info_cpep[];
+extern struct acpi_dmtable_info acpi_dm_table_info_cpep0[];
+extern struct acpi_dmtable_info acpi_dm_table_info_dbgp[];
+extern struct acpi_dmtable_info acpi_dm_table_info_ecdt[];
+extern struct acpi_dmtable_info acpi_dm_table_info_facs[];
+extern struct acpi_dmtable_info acpi_dm_table_info_fadt1[];
+extern struct acpi_dmtable_info acpi_dm_table_info_fadt2[];
+extern struct acpi_dmtable_info acpi_dm_table_info_gas[];
+extern struct acpi_dmtable_info acpi_dm_table_info_header[];
+extern struct acpi_dmtable_info acpi_dm_table_info_hpet[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt0[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt1[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt2[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt3[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt4[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt5[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt6[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt7[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt8[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt_hdr[];
+extern struct acpi_dmtable_info acpi_dm_table_info_mcfg[];
+extern struct acpi_dmtable_info acpi_dm_table_info_mcfg0[];
+extern struct acpi_dmtable_info acpi_dm_table_info_rsdp1[];
+extern struct acpi_dmtable_info acpi_dm_table_info_rsdp2[];
+extern struct acpi_dmtable_info acpi_dm_table_info_sbst[];
+extern struct acpi_dmtable_info acpi_dm_table_info_slit[];
+extern struct acpi_dmtable_info acpi_dm_table_info_spcr[];
+extern struct acpi_dmtable_info acpi_dm_table_info_spmi[];
+extern struct acpi_dmtable_info acpi_dm_table_info_srat[];
+extern struct acpi_dmtable_info acpi_dm_table_info_srat0[];
+extern struct acpi_dmtable_info acpi_dm_table_info_srat1[];
+extern struct acpi_dmtable_info acpi_dm_table_info_tcpa[];
+extern struct acpi_dmtable_info acpi_dm_table_info_wdrt[];
+
+/*
+ * dmtable
+ */
+void acpi_dm_dump_data_table(struct acpi_table_header *table);
+
+void
+acpi_dm_dump_table(u32 table_length,
+ u32 table_offset,
+ void *table,
+ u32 sub_table_length, struct acpi_dmtable_info *info);
+
+void acpi_dm_line_header(u32 offset, u32 byte_length, char *name);
+
+void acpi_dm_line_header2(u32 offset, u32 byte_length, char *name, u32 value);
+
+/*
+ * dmtbdump
+ */
+void acpi_dm_dump_asf(struct acpi_table_header *table);
+
+void acpi_dm_dump_cpep(struct acpi_table_header *table);
+
+void acpi_dm_dump_fadt(struct acpi_table_header *table);
+
+void acpi_dm_dump_srat(struct acpi_table_header *table);
+
+void acpi_dm_dump_mcfg(struct acpi_table_header *table);
+
+void acpi_dm_dump_madt(struct acpi_table_header *table);
+
+u32 acpi_dm_dump_rsdp(struct acpi_table_header *table);
+
+void acpi_dm_dump_rsdt(struct acpi_table_header *table);
+
+void acpi_dm_dump_slit(struct acpi_table_header *table);
+
+void acpi_dm_dump_xsdt(struct acpi_table_header *table);
+
/*
* dmwalk
*/
@@ -84,6 +224,11 @@ void
acpi_dm_disassemble(struct acpi_walk_state *walk_state,
union acpi_parse_object *origin, u32 num_opcodes);
+void
+acpi_dm_walk_parse_tree(union acpi_parse_object *op,
+ asl_walk_callback descending_callback,
+ asl_walk_callback ascending_callback, void *context);
+
/*
* dmopcode
*/
@@ -166,6 +311,7 @@ void acpi_dm_dump_integer64(u64 value, char *name);
void
acpi_dm_resource_template(struct acpi_op_walk_info *info,
+ union acpi_parse_object *op,
u8 * byte_data, u32 byte_count);
u8 acpi_dm_is_resource_template(union acpi_parse_object *op);
@@ -176,6 +322,8 @@ void acpi_dm_bit_list(u16 mask);
void acpi_dm_decode_attribute(u8 attribute);
+void acpi_dm_descriptor_name(void);
+
/*
* dmresrcl
*/
@@ -248,6 +396,15 @@ acpi_dm_vendor_small_descriptor(union aml_resource *resource,
/*
* dmutils
*/
-void acpi_dm_add_to_external_list(char *path);
+void acpi_dm_add_to_external_list(char *path, u8 type, u32 value);
+
+/*
+ * dmrestag
+ */
+void acpi_dm_find_resources(union acpi_parse_object *root);
+
+void
+acpi_dm_check_resource_reference(union acpi_parse_object *op,
+ struct acpi_walk_state *walk_state);
#endif /* __ACDISASM_H__ */
diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h
index c41a926ff31..288f84903af 100644
--- a/include/acpi/acdispat.h
+++ b/include/acpi/acdispat.h
@@ -194,7 +194,9 @@ acpi_status
acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
union acpi_operand_object *return_desc);
-void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state);
+void
+acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
+ struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
@@ -302,7 +304,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
struct acpi_namespace_node *method_node,
u8 * aml_start,
u32 aml_length,
- struct acpi_parameter_info *info, u8 pass_number);
+ struct acpi_evaluate_info *info, u8 pass_number);
acpi_status
acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
diff --git a/include/acpi/acevents.h b/include/acpi/acevents.h
index f2717be4fe0..234142828e1 100644
--- a/include/acpi/acevents.h
+++ b/include/acpi/acevents.h
@@ -93,7 +93,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
*/
u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info);
-acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback);
+acpi_status acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback);
acpi_status
acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
@@ -138,7 +138,7 @@ acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
u32 function,
acpi_physical_address address,
- u32 bit_width, void *value);
+ u32 bit_width, acpi_integer * value);
acpi_status
acpi_ev_attach_region(union acpi_operand_object *handler_obj,
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index dc768aa580e..797ca1ea521 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -160,8 +160,9 @@
#define AE_AML_BAD_RESOURCE_VALUE (acpi_status) (0x001F | AE_CODE_AML)
#define AE_AML_CIRCULAR_REFERENCE (acpi_status) (0x0020 | AE_CODE_AML)
#define AE_AML_BAD_RESOURCE_LENGTH (acpi_status) (0x0021 | AE_CODE_AML)
+#define AE_AML_ILLEGAL_ADDRESS (acpi_status) (0x0022 | AE_CODE_AML)
-#define AE_CODE_AML_MAX 0x0021
+#define AE_CODE_AML_MAX 0x0022
/*
* Internal exceptions used for control
@@ -275,7 +276,8 @@ char const *acpi_gbl_exception_names_aml[] = {
"AE_AML_NO_RESOURCE_END_TAG",
"AE_AML_BAD_RESOURCE_VALUE",
"AE_AML_CIRCULAR_REFERENCE",
- "AE_AML_BAD_RESOURCE_LENGTH"
+ "AE_AML_BAD_RESOURCE_LENGTH",
+ "AE_AML_ILLEGAL_ADDRESS"
};
char const *acpi_gbl_exception_names_ctrl[] = {
diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h
index 734cc77bf2c..14531d48f6b 100644
--- a/include/acpi/acglobal.h
+++ b/include/acpi/acglobal.h
@@ -107,6 +107,7 @@ ACPI_EXTERN u32 acpi_gbl_trace_flags;
* 3) Allow access to uninitialized locals/args (auto-init to integer 0)
* 4) Allow ANY object type to be a source operand for the Store() operator
* 5) Allow unresolved references (invalid target name) in package objects
+ * 6) Enable warning messages for behavior that is not ACPI spec compliant
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE);
@@ -114,7 +115,7 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE);
* Automatically serialize ALL control methods? Default is FALSE, meaning
* to use the Serialized/not_serialized method flags on a per method basis.
* Only change this if the ASL code is poorly written and cannot handle
- * reentrancy even though methods are marked "not_serialized".
+ * reentrancy even though methods are marked "NotSerialized".
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE);
@@ -149,10 +150,10 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE);
ACPI_EXTERN u32 acpi_gbl_table_flags;
ACPI_EXTERN u32 acpi_gbl_rsdt_table_count;
ACPI_EXTERN struct rsdp_descriptor *acpi_gbl_RSDP;
-ACPI_EXTERN XSDT_DESCRIPTOR *acpi_gbl_XSDT;
-ACPI_EXTERN FADT_DESCRIPTOR *acpi_gbl_FADT;
+ACPI_EXTERN struct xsdt_descriptor *acpi_gbl_XSDT;
+ACPI_EXTERN struct fadt_descriptor *acpi_gbl_FADT;
ACPI_EXTERN struct acpi_table_header *acpi_gbl_DSDT;
-ACPI_EXTERN FACS_DESCRIPTOR *acpi_gbl_FACS;
+ACPI_EXTERN struct facs_descriptor *acpi_gbl_FACS;
ACPI_EXTERN struct acpi_common_facs acpi_gbl_common_fACS;
/*
* Since there may be multiple SSDTs and PSDTs, a single pointer is not
@@ -177,15 +178,15 @@ ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
/*
* ACPI Table info arrays
*/
-extern struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES];
-extern struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES];
+extern struct acpi_table_list acpi_gbl_table_lists[ACPI_TABLE_ID_MAX + 1];
+extern struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1];
/*
* Predefined mutex objects. This array contains the
* actual OS mutex handles, indexed by the local ACPI_MUTEX_HANDLEs.
* (The table maps local handles to the real OS handles)
*/
-ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[NUM_MUTEX];
+ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX];
/*****************************************************************************
*
@@ -203,6 +204,7 @@ ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list;
/* Object caches */
+ACPI_EXTERN acpi_cache_t *acpi_gbl_namespace_cache;
ACPI_EXTERN acpi_cache_t *acpi_gbl_state_cache;
ACPI_EXTERN acpi_cache_t *acpi_gbl_ps_node_cache;
ACPI_EXTERN acpi_cache_t *acpi_gbl_ps_node_ext_cache;
@@ -244,7 +246,6 @@ extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT];
extern const char *acpi_gbl_highest_dstate_names[4];
extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES];
extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
-extern const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS];
/*****************************************************************************
*
@@ -291,14 +292,6 @@ ACPI_EXTERN u8 acpi_gbl_cm_single_step;
/*****************************************************************************
*
- * Parser globals
- *
- ****************************************************************************/
-
-ACPI_EXTERN union acpi_parse_object *acpi_gbl_parsed_namespace_root;
-
-/*****************************************************************************
- *
* Hardware globals
*
****************************************************************************/
@@ -321,7 +314,11 @@ ACPI_EXTERN struct acpi_fixed_event_handler
ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
ACPI_EXTERN struct acpi_gpe_block_info
*acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
+
+/* Spinlocks */
+
ACPI_EXTERN acpi_handle acpi_gbl_gpe_lock;
+ACPI_EXTERN acpi_handle acpi_gbl_hardware_lock;
/*****************************************************************************
*
diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h
index 8361820d297..1eeca7adca9 100644
--- a/include/acpi/aclocal.h
+++ b/include/acpi/aclocal.h
@@ -44,7 +44,10 @@
#ifndef __ACLOCAL_H__
#define __ACLOCAL_H__
+/* acpisrc:struct_defs -- for acpisrc conversion */
+
#define ACPI_WAIT_FOREVER 0xFFFF /* u16, as per ACPI spec */
+#define ACPI_INFINITE_CONCURRENCY 0xFF
typedef void *acpi_mutex;
typedef u32 acpi_mutex_handle;
@@ -69,52 +72,55 @@ union acpi_parse_object;
* Predefined handles for the mutex objects used within the subsystem
* All mutex objects are automatically created by acpi_ut_mutex_initialize.
*
- * The acquire/release ordering protocol is implied via this list. Mutexes
+ * The acquire/release ordering protocol is implied via this list. Mutexes
* with a lower value must be acquired before mutexes with a higher value.
*
- * NOTE: any changes here must be reflected in the acpi_gbl_mutex_names table also!
+ * NOTE: any changes here must be reflected in the acpi_gbl_mutex_names
+ * table below also!
*/
-#define ACPI_MTX_EXECUTE 0
-#define ACPI_MTX_INTERPRETER 1
-#define ACPI_MTX_PARSER 2
-#define ACPI_MTX_DISPATCHER 3
-#define ACPI_MTX_TABLES 4
-#define ACPI_MTX_OP_REGIONS 5
-#define ACPI_MTX_NAMESPACE 6
-#define ACPI_MTX_EVENTS 7
-#define ACPI_MTX_HARDWARE 8
-#define ACPI_MTX_CACHES 9
-#define ACPI_MTX_MEMORY 10
-#define ACPI_MTX_DEBUG_CMD_COMPLETE 11
-#define ACPI_MTX_DEBUG_CMD_READY 12
-
-#define MAX_MUTEX 12
-#define NUM_MUTEX MAX_MUTEX+1
+#define ACPI_MTX_INTERPRETER 0 /* AML Interpreter, main lock */
+#define ACPI_MTX_CONTROL_METHOD 1 /* Control method termination [TBD: may no longer be necessary] */
+#define ACPI_MTX_TABLES 2 /* Data for ACPI tables */
+#define ACPI_MTX_NAMESPACE 3 /* ACPI Namespace */
+#define ACPI_MTX_EVENTS 4 /* Data for ACPI events */
+#define ACPI_MTX_CACHES 5 /* Internal caches, general purposes */
+#define ACPI_MTX_MEMORY 6 /* Debug memory tracking lists */
+#define ACPI_MTX_DEBUG_CMD_COMPLETE 7 /* AML debugger */
+#define ACPI_MTX_DEBUG_CMD_READY 8 /* AML debugger */
+
+#define ACPI_MAX_MUTEX 8
+#define ACPI_NUM_MUTEX ACPI_MAX_MUTEX+1
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
#ifdef DEFINE_ACPI_GLOBALS
-/* Names for the mutexes used in the subsystem */
+/* Debug names for the mutexes above */
-static char *acpi_gbl_mutex_names[] = {
- "ACPI_MTX_Execute",
+static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
"ACPI_MTX_Interpreter",
- "ACPI_MTX_Parser",
- "ACPI_MTX_Dispatcher",
+ "ACPI_MTX_Method",
"ACPI_MTX_Tables",
- "ACPI_MTX_op_regions",
"ACPI_MTX_Namespace",
"ACPI_MTX_Events",
- "ACPI_MTX_Hardware",
"ACPI_MTX_Caches",
"ACPI_MTX_Memory",
- "ACPI_MTX_debug_cmd_complete",
- "ACPI_MTX_debug_cmd_ready",
+ "ACPI_MTX_DebugCmdComplete",
+ "ACPI_MTX_DebugCmdReady"
};
#endif
#endif
+/*
+ * Predefined handles for spinlocks used within the subsystem.
+ * These spinlocks are created by acpi_ut_mutex_initialize
+ */
+#define ACPI_LOCK_GPES 0
+#define ACPI_LOCK_HARDWARE 1
+
+#define ACPI_MAX_LOCK 1
+#define ACPI_NUM_LOCK ACPI_MAX_LOCK+1
+
/* Owner IDs are used to track namespace nodes for selective deletion */
typedef u8 acpi_owner_id;
@@ -129,7 +135,7 @@ typedef u8 acpi_owner_id;
struct acpi_mutex_info {
acpi_mutex mutex;
u32 use_count;
- u32 thread_id;
+ acpi_thread_id thread_id;
};
/* Lock flag parameter for various interfaces */
@@ -144,6 +150,8 @@ struct acpi_mutex_info {
#define ACPI_FIELD_DWORD_GRANULARITY 4
#define ACPI_FIELD_QWORD_GRANULARITY 8
+#define ACPI_ENTRY_NOT_FOUND NULL
+
/*****************************************************************************
*
* Namespace typedefs and structs
@@ -158,49 +166,55 @@ typedef enum {
ACPI_IMODE_EXECUTE = 0x0E
} acpi_interpreter_mode;
-/*
- * The Node describes a named object that appears in the AML
- * An acpi_node is used to store Nodes.
- *
- * data_type is used to differentiate between internal descriptors, and MUST
- * be the first byte in this structure.
- */
union acpi_name_union {
u32 integer;
char ascii[4];
};
+/*
+ * The Namespace Node describes a named object that appears in the AML.
+ * descriptor_type is used to differentiate between internal descriptors.
+ *
+ * The node is optimized for both 32-bit and 64-bit platforms:
+ * 20 bytes for the 32-bit case, 32 bytes for the 64-bit case.
+ *
+ * Note: The descriptor_type and Type fields must appear in the identical
+ * position in both the struct acpi_namespace_node and union acpi_operand_object
+ * structures.
+ */
struct acpi_namespace_node {
- u8 descriptor; /* Used to differentiate object descriptor types */
- u8 type; /* Type associated with this name */
- u16 reference_count; /* Current count of references and children */
+ union acpi_operand_object *object; /* Interpreter object */
+ u8 descriptor_type; /* Differentiate object descriptor types */
+ u8 type; /* ACPI Type associated with this name */
+ u8 flags; /* Miscellaneous flags */
+ acpi_owner_id owner_id; /* Node creator */
union acpi_name_union name; /* ACPI Name, always 4 chars per ACPI spec */
- union acpi_operand_object *object; /* Pointer to attached ACPI object (optional) */
struct acpi_namespace_node *child; /* First child */
- struct acpi_namespace_node *peer; /* Next peer */
- u8 owner_id; /* Who created this node */
- u8 flags;
-
- /* Fields used by the ASL compiler only */
+ struct acpi_namespace_node *peer; /* Peer. Parent if ANOBJ_END_OF_PEER_LIST set */
-#ifdef ACPI_ASL_COMPILER
- u32 value;
+ /*
+ * The following fields are used by the ASL compiler and disassembler only
+ */
+#ifdef ACPI_LARGE_NAMESPACE_NODE
union acpi_parse_object *op;
+ u32 value;
+ u32 length;
#endif
};
-#define ACPI_ENTRY_NOT_FOUND NULL
+/* Namespace Node flags */
-/* Node flags */
+#define ANOBJ_END_OF_PEER_LIST 0x01 /* End-of-list, Peer field points to parent */
+#define ANOBJ_DATA_WIDTH_32 0x02 /* Parent table uses 32-bit math */
+#define ANOBJ_METHOD_ARG 0x04 /* Node is a method argument */
+#define ANOBJ_METHOD_LOCAL 0x08 /* Node is a method local */
+#define ANOBJ_SUBTREE_HAS_INI 0x10 /* Used to optimize device initialization */
-#define ANOBJ_RESERVED 0x01
-#define ANOBJ_END_OF_PEER_LIST 0x02
-#define ANOBJ_DATA_WIDTH_32 0x04 /* Parent table is 64-bits */
-#define ANOBJ_METHOD_ARG 0x08
-#define ANOBJ_METHOD_LOCAL 0x10
-#define ANOBJ_METHOD_NO_RETVAL 0x20
-#define ANOBJ_METHOD_SOME_NO_RETVAL 0x40
-#define ANOBJ_IS_BIT_OFFSET 0x80
+#define ANOBJ_IS_EXTERNAL 0x08 /* i_aSL only: This object created via External() */
+#define ANOBJ_METHOD_NO_RETVAL 0x10 /* i_aSL only: Method has no return value */
+#define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* i_aSL only: Method has at least one return value */
+#define ANOBJ_IS_BIT_OFFSET 0x40 /* i_aSL only: Reference is a bit offset */
+#define ANOBJ_IS_REFERENCED 0x80 /* i_aSL only: Object was referenced */
/*
* ACPI Table Descriptor. One per ACPI table
@@ -212,8 +226,8 @@ struct acpi_table_desc {
struct acpi_table_header *pointer;
u8 *aml_start;
u64 physical_address;
- u32 aml_length;
acpi_size length;
+ u32 aml_length;
acpi_owner_id owner_id;
u8 type;
u8 allocation;
@@ -276,6 +290,9 @@ struct acpi_create_field_info {
u8 field_type;
};
+typedef
+acpi_status(*ACPI_INTERNAL_METHOD) (struct acpi_walk_state * walk_state);
+
/*
* Bitmapped ACPI types. Used internally only
*/
@@ -377,7 +394,7 @@ struct acpi_gpe_walk_info {
struct acpi_gpe_block_info *gpe_block;
};
-typedef acpi_status(*ACPI_GPE_CALLBACK) (struct acpi_gpe_xrupt_info *
+typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *
gpe_xrupt_info,
struct acpi_gpe_block_info *
gpe_block);
@@ -416,13 +433,14 @@ struct acpi_field_info {
#define ACPI_CONTROL_PREDICATE_FALSE 0xC3
#define ACPI_CONTROL_PREDICATE_TRUE 0xC4
-#define ACPI_STATE_COMMON /* Two 32-bit fields and a pointer */\
- u8 data_type; /* To differentiate various internal objs */\
- u8 flags; \
- u16 value; \
- u16 state; \
- u16 reserved; \
- void *next;
+#define ACPI_STATE_COMMON \
+ void *next; \
+ u8 descriptor_type; /* To differentiate various internal objs */\
+ u8 flags; \
+ u16 value; \
+ u16 state;
+
+ /* There are 2 bytes available here until the next natural alignment boundary */
struct acpi_common_state {
ACPI_STATE_COMMON};
@@ -438,12 +456,12 @@ struct acpi_update_state {
* Pkg state - used to traverse nested package structures
*/
struct acpi_pkg_state {
- ACPI_STATE_COMMON union acpi_operand_object *source_object;
+ ACPI_STATE_COMMON u16 index;
+ union acpi_operand_object *source_object;
union acpi_operand_object *dest_object;
struct acpi_walk_state *walk_state;
void *this_target_obj;
u32 num_packages;
- u16 index;
};
/*
@@ -451,10 +469,10 @@ struct acpi_pkg_state {
* Allows nesting of these constructs
*/
struct acpi_control_state {
- ACPI_STATE_COMMON union acpi_parse_object *predicate_op;
+ ACPI_STATE_COMMON u16 opcode;
+ union acpi_parse_object *predicate_op;
u8 *aml_predicate_start; /* Start of if/while predicate */
u8 *package_end; /* End of if/while block */
- u16 opcode;
};
/*
@@ -465,11 +483,11 @@ struct acpi_scope_state {
};
struct acpi_pscope_state {
- ACPI_STATE_COMMON union acpi_parse_object *op; /* Current op being parsed */
+ ACPI_STATE_COMMON u32 arg_count; /* Number of fixed arguments */
+ union acpi_parse_object *op; /* Current op being parsed */
u8 *arg_end; /* Current argument end */
u8 *pkg_end; /* Current package end */
u32 arg_list; /* Next argument to parse */
- u32 arg_count; /* Number of fixed arguments */
};
/*
@@ -477,10 +495,10 @@ struct acpi_pscope_state {
* states are created when there are nested control methods executing.
*/
struct acpi_thread_state {
- ACPI_STATE_COMMON struct acpi_walk_state *walk_state_list; /* Head of list of walk_states for this thread */
+ ACPI_STATE_COMMON u8 current_sync_level; /* Mutex Sync (nested acquire) level */
+ struct acpi_walk_state *walk_state_list; /* Head of list of walk_states for this thread */
union acpi_operand_object *acquired_mutex_list; /* List of all currently acquired mutexes */
- u32 thread_id; /* Running thread ID */
- u8 current_sync_level; /* Mutex Sync (nested acquire) level */
+ acpi_thread_id thread_id; /* Running thread ID */
};
/*
@@ -488,10 +506,9 @@ struct acpi_thread_state {
* AML arguments
*/
struct acpi_result_values {
- ACPI_STATE_COMMON
- union acpi_operand_object *obj_desc[ACPI_OBJ_NUM_OPERANDS];
- u8 num_results;
+ ACPI_STATE_COMMON u8 num_results;
u8 last_insert;
+ union acpi_operand_object *obj_desc[ACPI_OBJ_NUM_OPERANDS];
};
typedef
@@ -546,7 +563,7 @@ struct acpi_opcode_info {
#endif
u32 parse_args; /* Grammar/Parse time arguments */
u32 runtime_args; /* Interpret time arguments */
- u32 flags; /* Misc flags */
+ u16 flags; /* Misc flags */
u8 object_type; /* Corresponding internal object type */
u8 class; /* Opcode class */
u8 type; /* Opcode type */
@@ -563,29 +580,31 @@ union acpi_parse_value {
};
#define ACPI_PARSE_COMMON \
- u8 data_type; /* To differentiate various internal objs */\
- u8 flags; /* Type of Op */\
- u16 aml_opcode; /* AML opcode */\
- u32 aml_offset; /* Offset of declaration in AML */\
- union acpi_parse_object *parent; /* Parent op */\
- union acpi_parse_object *next; /* Next op */\
+ union acpi_parse_object *parent; /* Parent op */\
+ u8 descriptor_type; /* To differentiate various internal objs */\
+ u8 flags; /* Type of Op */\
+ u16 aml_opcode; /* AML opcode */\
+ u32 aml_offset; /* Offset of declaration in AML */\
+ union acpi_parse_object *next; /* Next op */\
+ struct acpi_namespace_node *node; /* For use by interpreter */\
+ union acpi_parse_value value; /* Value or args associated with the opcode */\
ACPI_DISASM_ONLY_MEMBERS (\
- u8 disasm_flags; /* Used during AML disassembly */\
- u8 disasm_opcode; /* Subtype used for disassembly */\
- char aml_op_name[16]) /* Op name (debug only) */\
- /* NON-DEBUG members below: */\
- struct acpi_namespace_node *node; /* For use by interpreter */\
- union acpi_parse_value value; /* Value or args associated with the opcode */
-
-#define ACPI_DASM_BUFFER 0x00
-#define ACPI_DASM_RESOURCE 0x01
-#define ACPI_DASM_STRING 0x02
-#define ACPI_DASM_UNICODE 0x03
-#define ACPI_DASM_EISAID 0x04
-#define ACPI_DASM_MATCHOP 0x05
+ u8 disasm_flags; /* Used during AML disassembly */\
+ u8 disasm_opcode; /* Subtype used for disassembly */\
+ char aml_op_name[16]) /* Op name (debug only) */
+
+#define ACPI_DASM_BUFFER 0x00
+#define ACPI_DASM_RESOURCE 0x01
+#define ACPI_DASM_STRING 0x02
+#define ACPI_DASM_UNICODE 0x03
+#define ACPI_DASM_EISAID 0x04
+#define ACPI_DASM_MATCHOP 0x05
+#define ACPI_DASM_LNOT_PREFIX 0x06
+#define ACPI_DASM_LNOT_SUFFIX 0x07
+#define ACPI_DASM_IGNORE 0x08
/*
- * generic operation (for example: If, While, Store)
+ * Generic operation (for example: If, While, Store)
*/
struct acpi_parse_obj_common {
ACPI_PARSE_COMMON};
@@ -601,7 +620,7 @@ struct acpi_parse_obj_named {
u32 name; /* 4-byte name or zero if no name */
};
-/* The parse node is the fundamental element of the parse tree */
+/* This version is used by the i_aSL compiler only */
#define ACPI_MAX_PARSEOP_NAME 20
@@ -643,7 +662,6 @@ union acpi_parse_object {
* method.
*/
struct acpi_parse_state {
- u32 aml_size;
u8 *aml_start; /* First AML byte */
u8 *aml; /* Next AML byte */
u8 *aml_end; /* (last + 1) AML byte */
@@ -653,22 +671,23 @@ struct acpi_parse_state {
struct acpi_namespace_node *start_node;
union acpi_generic_state *scope; /* Current scope */
union acpi_parse_object *start_scope;
+ u32 aml_size;
};
/* Parse object flags */
-#define ACPI_PARSEOP_GENERIC 0x01
-#define ACPI_PARSEOP_NAMED 0x02
-#define ACPI_PARSEOP_DEFERRED 0x04
-#define ACPI_PARSEOP_BYTELIST 0x08
-#define ACPI_PARSEOP_IN_CACHE 0x80
+#define ACPI_PARSEOP_GENERIC 0x01
+#define ACPI_PARSEOP_NAMED 0x02
+#define ACPI_PARSEOP_DEFERRED 0x04
+#define ACPI_PARSEOP_BYTELIST 0x08
+#define ACPI_PARSEOP_IN_CACHE 0x80
/* Parse object disasm_flags */
-#define ACPI_PARSEOP_IGNORE 0x01
-#define ACPI_PARSEOP_PARAMLIST 0x02
-#define ACPI_PARSEOP_EMPTY_TERMLIST 0x04
-#define ACPI_PARSEOP_SPECIAL 0x10
+#define ACPI_PARSEOP_IGNORE 0x01
+#define ACPI_PARSEOP_PARAMLIST 0x02
+#define ACPI_PARSEOP_EMPTY_TERMLIST 0x04
+#define ACPI_PARSEOP_SPECIAL 0x10
/*****************************************************************************
*
@@ -676,8 +695,8 @@ struct acpi_parse_state {
*
****************************************************************************/
-#define PCI_ROOT_HID_STRING "PNP0A03"
-#define PCI_EXPRESS_ROOT_HID_STRING "PNP0A08"
+#define PCI_ROOT_HID_STRING "PNP0A03"
+#define PCI_EXPRESS_ROOT_HID_STRING "PNP0A08"
struct acpi_bit_register_info {
u8 parent_register;
@@ -710,13 +729,14 @@ struct acpi_bit_register_info {
#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */
#define ACPI_BITMASK_WAKE_STATUS 0x8000
-#define ACPI_BITMASK_ALL_FIXED_STATUS (ACPI_BITMASK_TIMER_STATUS | \
- ACPI_BITMASK_BUS_MASTER_STATUS | \
- ACPI_BITMASK_GLOBAL_LOCK_STATUS | \
- ACPI_BITMASK_POWER_BUTTON_STATUS | \
- ACPI_BITMASK_SLEEP_BUTTON_STATUS | \
- ACPI_BITMASK_RT_CLOCK_STATUS | \
- ACPI_BITMASK_WAKE_STATUS)
+#define ACPI_BITMASK_ALL_FIXED_STATUS (\
+ ACPI_BITMASK_TIMER_STATUS | \
+ ACPI_BITMASK_BUS_MASTER_STATUS | \
+ ACPI_BITMASK_GLOBAL_LOCK_STATUS | \
+ ACPI_BITMASK_POWER_BUTTON_STATUS | \
+ ACPI_BITMASK_SLEEP_BUTTON_STATUS | \
+ ACPI_BITMASK_RT_CLOCK_STATUS | \
+ ACPI_BITMASK_WAKE_STATUS)
#define ACPI_BITMASK_TIMER_ENABLE 0x0001
#define ACPI_BITMASK_GLOBAL_LOCK_ENABLE 0x0020
@@ -820,7 +840,7 @@ struct acpi_bit_register_info {
*
****************************************************************************/
-#define ACPI_ASCII_ZERO 0x30
+#define ACPI_ASCII_ZERO 0x30
/*****************************************************************************
*
@@ -842,9 +862,9 @@ struct acpi_integrity_info {
u32 objects;
};
-#define ACPI_DB_REDIRECTABLE_OUTPUT 0x01
-#define ACPI_DB_CONSOLE_OUTPUT 0x02
-#define ACPI_DB_DUPLICATE_OUTPUT 0x03
+#define ACPI_DB_REDIRECTABLE_OUTPUT 0x01
+#define ACPI_DB_CONSOLE_OUTPUT 0x02
+#define ACPI_DB_DUPLICATE_OUTPUT 0x03
/*****************************************************************************
*
@@ -854,18 +874,18 @@ struct acpi_integrity_info {
/* Entry for a memory allocation (debug only) */
-#define ACPI_MEM_MALLOC 0
-#define ACPI_MEM_CALLOC 1
-#define ACPI_MAX_MODULE_NAME 16
+#define ACPI_MEM_MALLOC 0
+#define ACPI_MEM_CALLOC 1
+#define ACPI_MAX_MODULE_NAME 16
#define ACPI_COMMON_DEBUG_MEM_HEADER \
- struct acpi_debug_mem_block *previous; \
- struct acpi_debug_mem_block *next; \
- u32 size; \
- u32 component; \
- u32 line; \
- char module[ACPI_MAX_MODULE_NAME]; \
- u8 alloc_type;
+ struct acpi_debug_mem_block *previous; \
+ struct acpi_debug_mem_block *next; \
+ u32 size; \
+ u32 component; \
+ u32 line; \
+ char module[ACPI_MAX_MODULE_NAME]; \
+ u8 alloc_type;
struct acpi_debug_mem_header {
ACPI_COMMON_DEBUG_MEM_HEADER};
diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h
index f2be2a88173..38f9aa4bef0 100644
--- a/include/acpi/acmacros.h
+++ b/include/acpi/acmacros.h
@@ -56,6 +56,10 @@
#define ACPI_CLEAR_BIT(target,bit) ((target) &= ~(bit))
#define ACPI_MIN(a,b) (((a)<(b))?(a):(b))
+/* Size calculation */
+
+#define ACPI_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
+
#if ACPI_MACHINE_WIDTH == 16
/*
@@ -99,7 +103,7 @@
* printf() format helpers
*/
-/* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */
+/* Split 64-bit integer into two 32-bit values. Use with %8.8_x%8.8_x */
#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i)
@@ -130,7 +134,6 @@
#define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void,(void *) NULL,(acpi_native_uint) i)
#define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p,(void *) NULL)
#define ACPI_OFFSET(d,f) (acpi_size) ACPI_PTR_DIFF (&(((d *)0)->f),(void *) NULL)
-#define ACPI_FADT_OFFSET(f) ACPI_OFFSET (FADT_DESCRIPTOR, f)
#if ACPI_MACHINE_WIDTH == 16
#define ACPI_STORE_POINTER(d,s) ACPI_MOVE_32_TO_32(d,s)
@@ -141,6 +144,12 @@
#define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i)
#endif
+#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
+#define ACPI_COMPARE_NAME(a,b) (*ACPI_CAST_PTR (u32,(a)) == *ACPI_CAST_PTR (u32,(b)))
+#else
+#define ACPI_COMPARE_NAME(a,b) (!ACPI_STRNCMP (ACPI_CAST_PTR (char,(a)), ACPI_CAST_PTR (char,(b)), ACPI_NAME_SIZE))
+#endif
+
/*
* Macros for moving data around to/from buffers that are possibly unaligned.
* If the hardware supports the transfer of unaligned data, just do the store.
@@ -341,29 +350,33 @@
/*
* Rounding macros (Power of two boundaries only)
*/
-#define ACPI_ROUND_DOWN(value,boundary) (((acpi_native_uint)(value)) & \
+#define ACPI_ROUND_DOWN(value,boundary) (((acpi_native_uint)(value)) & \
(~(((acpi_native_uint) boundary)-1)))
-#define ACPI_ROUND_UP(value,boundary) ((((acpi_native_uint)(value)) + \
+#define ACPI_ROUND_UP(value,boundary) ((((acpi_native_uint)(value)) + \
(((acpi_native_uint) boundary)-1)) & \
(~(((acpi_native_uint) boundary)-1)))
-#define ACPI_ROUND_DOWN_TO_32_BITS(a) ACPI_ROUND_DOWN(a,4)
-#define ACPI_ROUND_DOWN_TO_64_BITS(a) ACPI_ROUND_DOWN(a,8)
-#define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a) ACPI_ROUND_DOWN(a,ALIGNED_ADDRESS_BOUNDARY)
+/* Note: sizeof(acpi_native_uint) evaluates to either 2, 4, or 8 */
+
+#define ACPI_ROUND_DOWN_TO_32BIT(a) ACPI_ROUND_DOWN(a,4)
+#define ACPI_ROUND_DOWN_TO_64BIT(a) ACPI_ROUND_DOWN(a,8)
+#define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a) ACPI_ROUND_DOWN(a,sizeof(acpi_native_uint))
-#define ACPI_ROUND_UP_to_32_bITS(a) ACPI_ROUND_UP(a,4)
-#define ACPI_ROUND_UP_to_64_bITS(a) ACPI_ROUND_UP(a,8)
-#define ACPI_ROUND_UP_TO_NATIVE_WORD(a) ACPI_ROUND_UP(a,ALIGNED_ADDRESS_BOUNDARY)
+#define ACPI_ROUND_UP_TO_32BIT(a) ACPI_ROUND_UP(a,4)
+#define ACPI_ROUND_UP_TO_64BIT(a) ACPI_ROUND_UP(a,8)
+#define ACPI_ROUND_UP_TO_NATIVE_WORD(a) ACPI_ROUND_UP(a,sizeof(acpi_native_uint))
-#define ACPI_ROUND_BITS_UP_TO_BYTES(a) ACPI_DIV_8((a) + 7)
-#define ACPI_ROUND_BITS_DOWN_TO_BYTES(a) ACPI_DIV_8((a))
+#define ACPI_ROUND_BITS_UP_TO_BYTES(a) ACPI_DIV_8((a) + 7)
+#define ACPI_ROUND_BITS_DOWN_TO_BYTES(a) ACPI_DIV_8((a))
-#define ACPI_ROUND_UP_TO_1K(a) (((a) + 1023) >> 10)
+#define ACPI_ROUND_UP_TO_1K(a) (((a) + 1023) >> 10)
/* Generic (non-power-of-two) rounding */
-#define ACPI_ROUND_UP_TO(value,boundary) (((value) + ((boundary)-1)) / (boundary))
+#define ACPI_ROUND_UP_TO(value,boundary) (((value) + ((boundary)-1)) / (boundary))
+
+#define ACPI_IS_MISALIGNED(value) (((acpi_native_uint)value) & (sizeof(acpi_native_uint)-1))
/*
* Bitmask creation
@@ -371,10 +384,10 @@
* MASK_BITS_ABOVE creates a mask starting AT the position and above
* MASK_BITS_BELOW creates a mask starting one bit BELOW the position
*/
-#define ACPI_MASK_BITS_ABOVE(position) (~((ACPI_INTEGER_MAX) << ((u32) (position))))
-#define ACPI_MASK_BITS_BELOW(position) ((ACPI_INTEGER_MAX) << ((u32) (position)))
+#define ACPI_MASK_BITS_ABOVE(position) (~((ACPI_INTEGER_MAX) << ((u32) (position))))
+#define ACPI_MASK_BITS_BELOW(position) ((ACPI_INTEGER_MAX) << ((u32) (position)))
-#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7'))
+#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7'))
/* Bitfields within ACPI registers */
@@ -396,8 +409,8 @@
*
* The "Descriptor" field is the first field in both structures.
*/
-#define ACPI_GET_DESCRIPTOR_TYPE(d) (((union acpi_descriptor *)(void *)(d))->descriptor_id)
-#define ACPI_SET_DESCRIPTOR_TYPE(d,t) (((union acpi_descriptor *)(void *)(d))->descriptor_id = t)
+#define ACPI_GET_DESCRIPTOR_TYPE(d) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type)
+#define ACPI_SET_DESCRIPTOR_TYPE(d,t) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = t)
/* Macro to test the object type */
@@ -486,7 +499,6 @@
#define ACPI_ERROR(plist)
#define ACPI_ERROR_NAMESPACE(s,e)
#define ACPI_ERROR_METHOD(s,n,p,e)
-
#endif
/*
@@ -514,12 +526,12 @@
#define ACPI_GET_FUNCTION_NAME _acpi_function_name
/*
* The Name parameter should be the procedure name as a quoted string.
- * This is declared as a local string ("my_function_name") so that it can
+ * This is declared as a local string ("MyFunctionName") so that it can
* be also used by the function exit macros below.
* Note: (const char) is used to be compatible with the debug interfaces
* and macros such as __FUNCTION__.
*/
-#define ACPI_FUNCTION_NAME(name) const char *_acpi_function_name = name;
+#define ACPI_FUNCTION_NAME(name) const char *_acpi_function_name = #name;
#else
/* Compiler supports __FUNCTION__ (or equivalent) -- Ignore this macro */
@@ -528,13 +540,13 @@
#endif
#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
+ acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
#define ACPI_FUNCTION_TRACE_PTR(a,b) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS,(void *)b)
+ acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS,(void *)b)
#define ACPI_FUNCTION_TRACE_U32(a,b) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace_u32(ACPI_DEBUG_PARAMETERS,(u32)b)
+ acpi_ut_trace_u32(ACPI_DEBUG_PARAMETERS,(u32)b)
#define ACPI_FUNCTION_TRACE_STR(a,b) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace_str(ACPI_DEBUG_PARAMETERS,(char *)b)
+ acpi_ut_trace_str(ACPI_DEBUG_PARAMETERS,(char *)b)
#define ACPI_FUNCTION_ENTRY() acpi_ut_track_stack_ptr()
@@ -543,7 +555,7 @@
* WARNING: These macros include a return statement. This is usually considered
* bad form, but having a separate exit macro is very ugly and difficult to maintain.
* One of the FUNCTION_TRACE macros above must be used in conjunction with these macros
- * so that "_acpi_function_name" is defined.
+ * so that "_AcpiFunctionName" is defined.
*
* Note: the DO_WHILE0 macro is used to prevent some compilers from complaining
* about these constructs.
@@ -654,6 +666,7 @@
#define ACPI_DUMP_STACK_ENTRY(a)
#define ACPI_DUMP_OPERANDS(a,b,c,d,e)
#define ACPI_DUMP_ENTRY(a,b)
+#define ACPI_DUMP_TABLES(a,b)
#define ACPI_DUMP_PATHNAME(a,b,c,d)
#define ACPI_DUMP_RESOURCE_LIST(a)
#define ACPI_DUMP_BUFFER(a,b)
@@ -709,19 +722,19 @@
/* Memory allocation */
-#define ACPI_MEM_ALLOCATE(a) acpi_ut_allocate((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_MEM_CALLOCATE(a) acpi_ut_callocate((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_MEM_FREE(a) acpi_os_free(a)
+#define ACPI_ALLOCATE(a) acpi_ut_allocate((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_FREE(a) acpi_os_free(a)
#define ACPI_MEM_TRACKING(a)
#else
/* Memory allocation */
-#define ACPI_MEM_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_MEM_CALLOCATE(a) acpi_ut_callocate_and_track((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_MEM_FREE(a) acpi_ut_free_and_track(a,_COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_MEM_TRACKING(a) a
+#define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed_and_track((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_FREE(a) acpi_ut_free_and_track(a,_COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_MEM_TRACKING(a) a
#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h
index b667a804fc8..83b52f9f899 100644
--- a/include/acpi/acnamesp.h
+++ b/include/acpi/acnamesp.h
@@ -63,6 +63,8 @@
#define ACPI_NS_DONT_OPEN_SCOPE 0x02
#define ACPI_NS_NO_PEER_SEARCH 0x04
#define ACPI_NS_ERROR_IF_FOUND 0x08
+#define ACPI_NS_PREFIX_IS_SCOPE 0x10
+#define ACPI_NS_EXTERNAL 0x20
#define ACPI_NS_WALK_UNLOCK TRUE
#define ACPI_NS_WALK_NO_UNLOCK FALSE
@@ -171,19 +173,17 @@ acpi_ns_dump_objects(acpi_object_type type,
/*
* nseval - Namespace evaluation functions
*/
-acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info);
-
-acpi_status
-acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info);
-
-acpi_status
-acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info);
+acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info);
/*
* nsnames - Name and Scope manipulation
*/
u32 acpi_ns_opens_scope(acpi_object_type type);
+void
+acpi_ns_build_external_path(struct acpi_namespace_node *node,
+ acpi_size size, char *name_buffer);
+
char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node);
char *acpi_ns_name_of_current_scope(struct acpi_walk_state *walk_state);
@@ -196,9 +196,9 @@ u8
acpi_ns_pattern_match(struct acpi_namespace_node *obj_node, char *search_for);
acpi_status
-acpi_ns_get_node_by_path(char *external_pathname,
- struct acpi_namespace_node *in_prefix_node,
- u32 flags, struct acpi_namespace_node **out_node);
+acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
+ char *external_pathname,
+ u32 flags, struct acpi_namespace_node **out_node);
acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node);
@@ -241,10 +241,10 @@ acpi_ns_search_and_enter(u32 entry_name,
u32 flags, struct acpi_namespace_node **ret_node);
acpi_status
-acpi_ns_search_node(u32 entry_name,
- struct acpi_namespace_node *node,
- acpi_object_type type,
- struct acpi_namespace_node **ret_node);
+acpi_ns_search_one_scope(u32 entry_name,
+ struct acpi_namespace_node *node,
+ acpi_object_type type,
+ struct acpi_namespace_node **ret_node);
void
acpi_ns_install_node(struct acpi_walk_state *walk_state,
diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h
index d130cfed8d5..1747d94084d 100644
--- a/include/acpi/acobject.h
+++ b/include/acpi/acobject.h
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Name: acobject.h - Definition of union acpi_operand_object (Internal object only)
+ * Name: acobject.h - Definition of union acpi_operand_object (Internal object only)
*
*****************************************************************************/
@@ -45,10 +45,12 @@
#ifndef _ACOBJECT_H
#define _ACOBJECT_H
+/* acpisrc:struct_defs -- for acpisrc conversion */
+
/*
- * The union acpi_operand_object is used to pass AML operands from the dispatcher
+ * The union acpi_operand_object is used to pass AML operands from the dispatcher
* to the interpreter, and to keep track of the various handlers such as
- * address space handlers and notify handlers. The object is a constant
+ * address space handlers and notify handlers. The object is a constant
* size in order to allow it to be cached and reused.
*/
@@ -61,17 +63,25 @@
/*
* Common area for all objects.
*
- * data_type is used to differentiate between internal descriptors, and MUST
- * be the first byte in this structure.
+ * descriptor_type is used to differentiate between internal descriptors, and
+ * must be in the same place across all descriptors
+ *
+ * Note: The descriptor_type and Type fields must appear in the identical
+ * position in both the struct acpi_namespace_node and union acpi_operand_object
+ * structures.
*/
-#define ACPI_OBJECT_COMMON_HEADER /* SIZE/ALIGNMENT: 32 bits, one ptr plus trailing 8-bit flag */\
- u8 descriptor; /* To differentiate various internal objs */\
- u8 type; /* acpi_object_type */\
- u16 reference_count; /* For object deletion management */\
- union acpi_operand_object *next_object; /* Objects linked to parent NS node */\
- u8 flags;
-
-/* Values for flag byte above */
+#define ACPI_OBJECT_COMMON_HEADER \
+ union acpi_operand_object *next_object; /* Objects linked to parent NS node */\
+ u8 descriptor_type; /* To differentiate various internal objs */\
+ u8 type; /* acpi_object_type */\
+ u16 reference_count; /* For object deletion management */\
+ u8 flags;
+ /*
+ * Note: There are 3 bytes available here before the
+ * next natural alignment boundary (for both 32/64 cases)
+ */
+
+/* Values for Flag byte above */
#define AOPOBJ_AML_CONSTANT 0x01
#define AOPOBJ_STATIC_POINTER 0x02
@@ -79,36 +89,7 @@
#define AOPOBJ_OBJECT_INITIALIZED 0x08
#define AOPOBJ_SETUP_COMPLETE 0x10
#define AOPOBJ_SINGLE_DATUM 0x20
-
-/*
- * Common bitfield for the field objects
- * "Field Datum" -- a datum from the actual field object
- * "Buffer Datum" -- a datum from a user buffer, read from or to be written to the field
- */
-#define ACPI_COMMON_FIELD_INFO /* SIZE/ALIGNMENT: 24 bits + three 32-bit values */\
- u8 field_flags; /* Access, update, and lock bits */\
- u8 attribute; /* From access_as keyword */\
- u8 access_byte_width; /* Read/Write size in bytes */\
- u32 bit_length; /* Length of field in bits */\
- u32 base_byte_offset; /* Byte offset within containing object */\
- u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
- u8 access_bit_width; /* Read/Write size in bits (8-64) */\
- u32 value; /* Value to store into the Bank or Index register */\
- struct acpi_namespace_node *node; /* Link back to parent node */
-
-/*
- * Fields common to both Strings and Buffers
- */
-#define ACPI_COMMON_BUFFER_INFO \
- u32 length;
-
-/*
- * Common fields for objects that support ASL notifications
- */
-#define ACPI_COMMON_NOTIFY_INFO \
- union acpi_operand_object *system_notify; /* Handler for system notifies */\
- union acpi_operand_object *device_notify; /* Handler for driver notifies */\
- union acpi_operand_object *handler; /* Handler for Address space */
+#define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */
/******************************************************************************
*
@@ -125,25 +106,31 @@ struct acpi_object_integer {
/*
* Note: The String and Buffer object must be identical through the Pointer
- * element. There is code that depends on this.
+ * and length elements. There is code that depends on this.
+ *
+ * Fields common to both Strings and Buffers
*/
+#define ACPI_COMMON_BUFFER_INFO(_type) \
+ _type *pointer; \
+ u32 length;
+
struct acpi_object_string { /* Null terminated, ASCII characters only */
- ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO char *pointer; /* String in AML stream or allocated string */
+ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(char) /* String in AML stream or allocated string */
};
struct acpi_object_buffer {
- ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO u8 * pointer; /* Buffer in AML stream or allocated buffer */
- struct acpi_namespace_node *node; /* Link back to parent node */
- u8 *aml_start;
+ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(u8) /* Buffer in AML stream or allocated buffer */
u32 aml_length;
+ u8 *aml_start;
+ struct acpi_namespace_node *node; /* Link back to parent node */
};
struct acpi_object_package {
- ACPI_OBJECT_COMMON_HEADER u32 count; /* # of elements in package */
- u32 aml_length;
- u8 *aml_start;
- struct acpi_namespace_node *node; /* Link back to parent node */
+ ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Link back to parent node */
union acpi_operand_object **elements; /* Array of pointers to acpi_objects */
+ u8 *aml_start;
+ u32 aml_length;
+ u32 count; /* # of elements in package */
};
/******************************************************************************
@@ -156,23 +143,6 @@ struct acpi_object_event {
ACPI_OBJECT_COMMON_HEADER void *semaphore;
};
-#define ACPI_INFINITE_CONCURRENCY 0xFF
-
-typedef
-acpi_status(*ACPI_INTERNAL_METHOD) (struct acpi_walk_state * walk_state);
-
-struct acpi_object_method {
- ACPI_OBJECT_COMMON_HEADER u8 method_flags;
- u8 param_count;
- u32 aml_length;
- void *semaphore;
- u8 *aml_start;
- ACPI_INTERNAL_METHOD implementation;
- u8 concurrency;
- u8 thread_count;
- acpi_owner_id owner_id;
-};
-
struct acpi_object_mutex {
ACPI_OBJECT_COMMON_HEADER u8 sync_level; /* 0-15, specified in Mutex() call */
u16 acquisition_depth; /* Allow multiple Acquires, same thread */
@@ -186,11 +156,23 @@ struct acpi_object_mutex {
struct acpi_object_region {
ACPI_OBJECT_COMMON_HEADER u8 space_id;
- union acpi_operand_object *handler; /* Handler for region access */
struct acpi_namespace_node *node; /* Containing namespace node */
+ union acpi_operand_object *handler; /* Handler for region access */
union acpi_operand_object *next;
- u32 length;
acpi_physical_address address;
+ u32 length;
+};
+
+struct acpi_object_method {
+ ACPI_OBJECT_COMMON_HEADER u8 method_flags;
+ u8 param_count;
+ u8 concurrency;
+ void *semaphore;
+ u8 *aml_start;
+ ACPI_INTERNAL_METHOD implementation;
+ u32 aml_length;
+ u8 thread_count;
+ acpi_owner_id owner_id;
};
/******************************************************************************
@@ -199,6 +181,14 @@ struct acpi_object_region {
*
*****************************************************************************/
+/*
+ * Common fields for objects that support ASL notifications
+ */
+#define ACPI_COMMON_NOTIFY_INFO \
+ union acpi_operand_object *system_notify; /* Handler for system notifies */\
+ union acpi_operand_object *device_notify; /* Handler for driver notifies */\
+ union acpi_operand_object *handler; /* Handler for Address space */
+
struct acpi_object_notify_common { /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
@@ -213,9 +203,9 @@ struct acpi_object_power_resource {
};
struct acpi_object_processor {
- ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO u32 proc_id;
- u32 length;
- acpi_io_address address;
+ ACPI_OBJECT_COMMON_HEADER u8 proc_id;
+ u8 length;
+ ACPI_COMMON_NOTIFY_INFO acpi_io_address address;
};
struct acpi_object_thermal_zone {
@@ -227,9 +217,24 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
*
*****************************************************************************/
+/*
+ * Common bitfield for the field objects
+ * "Field Datum" -- a datum from the actual field object
+ * "Buffer Datum" -- a datum from a user buffer, read from or to be written to the field
+ */
+#define ACPI_COMMON_FIELD_INFO \
+ u8 field_flags; /* Access, update, and lock bits */\
+ u8 attribute; /* From access_as keyword */\
+ u8 access_byte_width; /* Read/Write size in bytes */\
+ struct acpi_namespace_node *node; /* Link back to parent node */\
+ u32 bit_length; /* Length of field in bits */\
+ u32 base_byte_offset; /* Byte offset within containing object */\
+ u32 value; /* Value to store into the Bank or Index register */\
+ u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
+ u8 access_bit_width; /* Read/Write size in bits (8-64) */
+
struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
- ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Containing Operation Region object */
- /* (REGION/BANK fields only) */
+ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */
};
struct acpi_object_region_field {
@@ -244,7 +249,7 @@ struct acpi_object_bank_field {
struct acpi_object_index_field {
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO
/*
- * No "region_obj" pointer needed since the Index and Data registers
+ * No "RegionObj" pointer needed since the Index and Data registers
* are each field definitions unto themselves.
*/
union acpi_operand_object *index_obj; /* Index register */
@@ -269,13 +274,9 @@ struct acpi_object_notify_handler {
void *context;
};
-/* Flags for address handler */
-
-#define ACPI_ADDR_HANDLER_DEFAULT_INSTALLED 0x1
-
struct acpi_object_addr_handler {
ACPI_OBJECT_COMMON_HEADER u8 space_id;
- u16 hflags;
+ u8 handler_flags;
acpi_adr_space_handler handler;
struct acpi_namespace_node *node; /* Parent device */
void *context;
@@ -284,6 +285,10 @@ struct acpi_object_addr_handler {
union acpi_operand_object *next;
};
+/* Flags for address handler (handler_flags) */
+
+#define ACPI_ADDR_HANDLER_DEFAULT_INSTALLED 0x01
+
/******************************************************************************
*
* Special internal objects
@@ -297,10 +302,10 @@ struct acpi_object_addr_handler {
struct acpi_object_reference {
ACPI_OBJECT_COMMON_HEADER u8 target_type; /* Used for index_op */
u16 opcode;
- u32 offset; /* Used for arg_op, local_op, and index_op */
- void *object; /* name_op=>HANDLE to obj, index_op=>union acpi_operand_object */
+ void *object; /* name_op=>HANDLE to obj, index_op=>union acpi_operand_object */
struct acpi_namespace_node *node;
union acpi_operand_object **where;
+ u32 offset; /* Used for arg_op, local_op, and index_op */
};
/*
@@ -311,12 +316,10 @@ struct acpi_object_reference {
* Currently: Region and field_unit types
*/
struct acpi_object_extra {
- ACPI_OBJECT_COMMON_HEADER u8 byte_fill1;
- u16 word_fill1;
- u32 aml_length;
- u8 *aml_start;
- struct acpi_namespace_node *method_REG; /* _REG method for this region (if any) */
+ ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *method_REG; /* _REG method for this region (if any) */
void *region_context; /* Region-specific data */
+ u8 *aml_start;
+ u32 aml_length;
};
/* Additional data that can be attached to namespace nodes */
@@ -391,8 +394,13 @@ union acpi_operand_object {
#define ACPI_DESC_TYPE_NAMED 0x0F
#define ACPI_DESC_TYPE_MAX 0x0F
+struct acpi_common_descriptor {
+ void *common_pointer;
+ u8 descriptor_type; /* To differentiate various internal objs */
+};
+
union acpi_descriptor {
- u8 descriptor_id; /* To differentiate various internal objs */
+ struct acpi_common_descriptor common;
union acpi_operand_object object;
struct acpi_namespace_node node;
union acpi_parse_object op;
diff --git a/include/acpi/acopcode.h b/include/acpi/acopcode.h
index e6d78bd9e90..7659a46bc43 100644
--- a/include/acpi/acopcode.h
+++ b/include/acpi/acopcode.h
@@ -94,7 +94,7 @@
#define ARGP_CONCAT_RES_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SUPERNAME)
#define ARGP_CONTINUE_OP ARG_NONE
-#define ARGP_COPY_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SIMPLENAME)
+#define ARGP_COPY_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SIMPLENAME)
#define ARGP_CREATE_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
#define ARGP_CREATE_BYTE_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
#define ARGP_CREATE_DWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h
index 7785d481dc3..8d5039d0b43 100644
--- a/include/acpi/acoutput.h
+++ b/include/acpi/acoutput.h
@@ -50,7 +50,7 @@
* component basis and a per-exception-type basis.
*/
-/* Component IDs are used in the global "debug_layer" */
+/* Component IDs are used in the global "DebugLayer" */
#define ACPI_UTILITIES 0x00000001
#define ACPI_HARDWARE 0x00000002
@@ -121,7 +121,7 @@
#define ACPI_LV_INTERRUPTS 0x08000000
#define ACPI_LV_VERBOSITY3 0x0F000000 | ACPI_LV_VERBOSITY2
-/* Exceptionally verbose output -- also used in the global "debug_level" */
+/* Exceptionally verbose output -- also used in the global "DebugLevel" */
#define ACPI_LV_AML_DISASSEMBLE 0x10000000
#define ACPI_LV_VERBOSE_INFO 0x20000000
@@ -135,7 +135,7 @@
*/
#define ACPI_DEBUG_LEVEL(dl) (u32) dl,ACPI_DEBUG_PARAMETERS
-/* Exception level -- used in the global "debug_level" */
+/* Exception level -- used in the global "DebugLevel" */
#define ACPI_DB_INIT ACPI_DEBUG_LEVEL (ACPI_LV_INIT)
#define ACPI_DB_DEBUG_OBJECT ACPI_DEBUG_LEVEL (ACPI_LV_DEBUG_OBJECT)
@@ -144,13 +144,13 @@
/*
* These two levels are essentially obsolete, all instances in the
- * ACPICA core code have been replaced by REPORT_ERROR and REPORT_WARNING
+ * ACPICA core code have been replaced by ACPI_ERROR and ACPI_WARNING
* (Kept here because some drivers may still use them)
*/
#define ACPI_DB_ERROR ACPI_DEBUG_LEVEL (ACPI_LV_ERROR)
#define ACPI_DB_WARN ACPI_DEBUG_LEVEL (ACPI_LV_WARN)
-/* Trace level -- also used in the global "debug_level" */
+/* Trace level -- also used in the global "DebugLevel" */
#define ACPI_DB_INIT_NAMES ACPI_DEBUG_LEVEL (ACPI_LV_INIT_NAMES)
#define ACPI_DB_THREADS ACPI_DEBUG_LEVEL (ACPI_LV_THREADS)
diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h
index 5a1ff484af3..9d49d3c41cd 100644
--- a/include/acpi/acparser.h
+++ b/include/acpi/acparser.h
@@ -46,7 +46,7 @@
#define OP_HAS_RETURN_VALUE 1
-/* variable # arguments */
+/* Variable number of arguments. This field must be 32 bits */
#define ACPI_VAR_ARGS ACPI_UINT32_MAX
@@ -71,7 +71,7 @@
/*
* psxface - Parser external interfaces
*/
-acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info);
+acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info);
/*
* psargs - Parse AML opcode arguments
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 6dca3d54208..43f8c2a23a2 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -59,7 +59,7 @@ acpi_evaluate_reference(acpi_handle handle,
#define ACPI_BUS_FILE_ROOT "acpi"
extern struct proc_dir_entry *acpi_root_dir;
-extern FADT_DESCRIPTOR acpi_fadt;
+extern struct fadt_descriptor acpi_fadt;
enum acpi_bus_removal_type {
ACPI_BUS_REMOVAL_NORMAL = 0,
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 970e9a6372c..8f473c83b7c 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -50,12 +50,16 @@
#include "platform/acenv.h"
#include "actypes.h"
-/* Priorities for acpi_os_queue_for_execution */
+/* Types for acpi_os_execute */
-#define OSD_PRIORITY_GPE 1
-#define OSD_PRIORITY_HIGH 2
-#define OSD_PRIORITY_MED 3
-#define OSD_PRIORITY_LO 4
+typedef enum {
+ OSL_GLOBAL_LOCK_HANDLER,
+ OSL_NOTIFY_HANDLER,
+ OSL_GPE_HANDLER,
+ OSL_DEBUGGER_THREAD,
+ OSL_EC_POLL_HANDLER,
+ OSL_EC_BURST_HANDLER
+} acpi_execute_type;
#define ACPI_NO_UNIT_LIMIT ((u32) -1)
#define ACPI_MUTEX_SEM 1
@@ -161,13 +165,11 @@ acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler service_routine);
/*
* Threads and Scheduling
*/
-u32 acpi_os_get_thread_id(void);
+acpi_thread_id acpi_os_get_thread_id(void);
acpi_status
-acpi_os_queue_for_execution(u32 priority,
- acpi_osd_exec_callback function, void *context);
-
-void acpi_os_wait_events_complete(void *context);
+acpi_os_execute(acpi_execute_type type,
+ acpi_osd_exec_callback function, void *context);
void acpi_os_wait_events_complete(void *context);
@@ -214,6 +216,12 @@ acpi_os_derive_pci_id(acpi_handle rhandle,
/*
* Miscellaneous
*/
+acpi_status acpi_os_validate_interface(char *interface);
+
+acpi_status
+acpi_os_validate_address(u8 space_id,
+ acpi_physical_address address, acpi_size length);
+
u8 acpi_os_readable(void *pointer, acpi_size length);
#ifdef ACPI_FUTURE_USAGE
@@ -255,11 +263,4 @@ char *acpi_os_get_next_filename(void *dir_handle);
void acpi_os_close_directory(void *dir_handle);
-/*
- * Debug
- */
-void
-acpi_os_dbg_assert(void *failed_assertion,
- void *file_name, u32 line_number, char *message);
-
#endif /* __ACPIOSXF_H__ */
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 66cf2ecef57..049e9aa1b86 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -268,7 +268,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device);
* Resource interfaces
*/
typedef
-acpi_status(*ACPI_WALK_RESOURCE_CALLBACK) (struct acpi_resource * resource,
+acpi_status(*acpi_walk_resource_callback) (struct acpi_resource * resource,
void *context);
acpi_status
@@ -290,7 +290,7 @@ acpi_get_possible_resources(acpi_handle device_handle,
acpi_status
acpi_walk_resources(acpi_handle device_handle,
char *name,
- ACPI_WALK_RESOURCE_CALLBACK user_function, void *context);
+ acpi_walk_resource_callback user_function, void *context);
acpi_status
acpi_set_current_resources(acpi_handle device_handle,
diff --git a/include/acpi/acresrc.h b/include/acpi/acresrc.h
index fa02e808338..ad11fc13fbe 100644
--- a/include/acpi/acresrc.h
+++ b/include/acpi/acresrc.h
@@ -164,23 +164,26 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
/*
* rsutils
*/
+
acpi_status
-acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer);
+acpi_rs_get_prt_method_data(struct acpi_namespace_node *node,
+ struct acpi_buffer *ret_buffer);
acpi_status
-acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer);
+acpi_rs_get_crs_method_data(struct acpi_namespace_node *node,
+ struct acpi_buffer *ret_buffer);
-#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer);
-#endif /* ACPI_FUTURE_USAGE */
+acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,
+ struct acpi_buffer *ret_buffer);
acpi_status
acpi_rs_get_method_data(acpi_handle handle,
char *path, struct acpi_buffer *ret_buffer);
acpi_status
-acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer);
+acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
+ struct acpi_buffer *ret_buffer);
/*
* rscalc
@@ -198,8 +201,9 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
acpi_size * buffer_size_needed);
acpi_status
-acpi_rs_convert_aml_to_resources(u8 * aml_buffer,
- u32 aml_buffer_length, u8 * output_buffer);
+acpi_rs_convert_aml_to_resources(u8 * aml,
+ u32 length,
+ u32 offset, u8 resource_index, void **context);
acpi_status
acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h
index d8c1c2cdac0..5e8095f0f78 100644
--- a/include/acpi/acstruct.h
+++ b/include/acpi/acstruct.h
@@ -44,6 +44,8 @@
#ifndef __ACSTRUCT_H__
#define __ACSTRUCT_H__
+/* acpisrc:struct_defs -- for acpisrc conversion */
+
/*****************************************************************************
*
* Tree walking typedefs and structs
@@ -51,67 +53,76 @@
****************************************************************************/
/*
- * Walk state - current state of a parse tree walk. Used for both a leisurely stroll through
- * the tree (for whatever reason), and for control method execution.
+ * Walk state - current state of a parse tree walk. Used for both a leisurely
+ * stroll through the tree (for whatever reason), and for control method
+ * execution.
*/
#define ACPI_NEXT_OP_DOWNWARD 1
#define ACPI_NEXT_OP_UPWARD 2
+/*
+ * Groups of definitions for walk_type used for different implementations of
+ * walkers (never simultaneously) - flags for interpreter:
+ */
#define ACPI_WALK_NON_METHOD 0
-#define ACPI_WALK_METHOD 1
-#define ACPI_WALK_METHOD_RESTART 2
-#define ACPI_WALK_CONST_REQUIRED 3
-#define ACPI_WALK_CONST_OPTIONAL 4
+#define ACPI_WALK_METHOD 0x01
+#define ACPI_WALK_METHOD_RESTART 0x02
+
+/* Flags for i_aSL compiler only */
+
+#define ACPI_WALK_CONST_REQUIRED 0x10
+#define ACPI_WALK_CONST_OPTIONAL 0x20
struct acpi_walk_state {
- u8 data_type; /* To differentiate various internal objs MUST BE FIRST! */
+ struct acpi_walk_state *next; /* Next walk_state in list */
+ u8 descriptor_type; /* To differentiate various internal objs */
u8 walk_type;
- acpi_owner_id owner_id; /* Owner of objects created during the walk */
- u8 last_predicate; /* Result of last predicate */
- u8 current_result; /* */
+ u16 opcode; /* Current AML opcode */
u8 next_op_info; /* Info about next_op */
u8 num_operands; /* Stack pointer for Operands[] array */
+ acpi_owner_id owner_id; /* Owner of objects created during the walk */
+ u8 last_predicate; /* Result of last predicate */
+ u8 current_result;
u8 return_used;
- u16 opcode; /* Current AML opcode */
u8 scope_depth;
u8 pass_number; /* Parse pass during table load */
- u32 arg_count; /* push for fixed or var args */
u32 aml_offset;
u32 arg_types;
u32 method_breakpoint; /* For single stepping */
u32 user_breakpoint; /* User AML breakpoint */
u32 parse_flags;
+
+ struct acpi_parse_state parser_state; /* Current state of parser */
u32 prev_arg_types;
+ u32 arg_count; /* push for fixed or var args */
- u8 *aml_last_while;
struct acpi_namespace_node arguments[ACPI_METHOD_NUM_ARGS]; /* Control method arguments */
+ struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */
+ union acpi_operand_object *operands[ACPI_OBJ_NUM_OPERANDS + 1]; /* Operands passed to the interpreter (+1 for NULL terminator) */
+ union acpi_operand_object **params;
+
+ u8 *aml_last_while;
union acpi_operand_object **caller_return_desc;
union acpi_generic_state *control_state; /* List of control states (nested IFs) */
struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */
struct acpi_gpe_event_info *gpe_event_info; /* Info for GPE (_Lxx/_Exx methods only */
union acpi_operand_object *implicit_return_obj;
- struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */
struct acpi_namespace_node *method_call_node; /* Called method Node */
union acpi_parse_object *method_call_op; /* method_call Op if running a method */
union acpi_operand_object *method_desc; /* Method descriptor if running a method */
struct acpi_namespace_node *method_node; /* Method node if running a method. */
union acpi_parse_object *op; /* Current parser op */
- union acpi_operand_object *operands[ACPI_OBJ_NUM_OPERANDS + 1]; /* Operands passed to the interpreter (+1 for NULL terminator) */
const struct acpi_opcode_info *op_info; /* Info on current opcode */
union acpi_parse_object *origin; /* Start of walk [Obsolete] */
- union acpi_operand_object **params;
- struct acpi_parse_state parser_state; /* Current state of parser */
union acpi_operand_object *result_obj;
union acpi_generic_state *results; /* Stack of accumulated results */
union acpi_operand_object *return_desc; /* Return object, if any */
union acpi_generic_state *scope_info; /* Stack of nested scopes */
-
union acpi_parse_object *prev_op; /* Last op that was processed */
union acpi_parse_object *next_op; /* next op to be processed */
+ struct acpi_thread_state *thread;
acpi_parse_downwards descending_callback;
acpi_parse_upwards ascending_callback;
- struct acpi_thread_state *thread;
- struct acpi_walk_state *next; /* Next walk_state in list */
};
/* Info used by acpi_ps_init_objects */
@@ -131,32 +142,6 @@ struct acpi_init_walk_info {
struct acpi_table_desc *table_desc;
};
-/* Info used by acpi_ns_initialize_devices */
-
-struct acpi_device_walk_info {
- u16 device_count;
- u16 num_STA;
- u16 num_INI;
- struct acpi_table_desc *table_desc;
-};
-
-/* TBD: [Restructure] Merge with struct above */
-
-struct acpi_walk_info {
- u32 debug_level;
- u32 count;
- acpi_owner_id owner_id;
- u8 display_type;
-};
-
-/* Display Types */
-
-#define ACPI_DISPLAY_SUMMARY (u8) 0
-#define ACPI_DISPLAY_OBJECTS (u8) 1
-#define ACPI_DISPLAY_MASK (u8) 1
-
-#define ACPI_DISPLAY_SHORT (u8) 2
-
struct acpi_get_devices_info {
acpi_walk_callback user_function;
void *context;
@@ -189,16 +174,21 @@ union acpi_aml_operands {
} mid;
};
-/* Internal method parameter list */
-
-struct acpi_parameter_info {
- struct acpi_namespace_node *node;
+/*
+ * Structure used to pass object evaluation parameters.
+ * Purpose is to reduce CPU stack use.
+ */
+struct acpi_evaluate_info {
+ struct acpi_namespace_node *prefix_node;
+ char *pathname;
union acpi_operand_object *obj_desc;
union acpi_operand_object **parameters;
+ struct acpi_namespace_node *resolved_node;
union acpi_operand_object *return_object;
u8 pass_number;
u8 parameter_type;
u8 return_object_type;
+ u8 flags;
};
/* Types for parameter_type above */
@@ -206,4 +196,35 @@ struct acpi_parameter_info {
#define ACPI_PARAM_ARGS 0
#define ACPI_PARAM_GPE 1
+/* Values for Flags above */
+
+#define ACPI_IGNORE_RETURN_VALUE 1
+
+/* Info used by acpi_ns_initialize_devices */
+
+struct acpi_device_walk_info {
+ u16 device_count;
+ u16 num_STA;
+ u16 num_INI;
+ struct acpi_table_desc *table_desc;
+ struct acpi_evaluate_info *evaluate_info;
+};
+
+/* TBD: [Restructure] Merge with struct above */
+
+struct acpi_walk_info {
+ u32 debug_level;
+ u32 count;
+ acpi_owner_id owner_id;
+ u8 display_type;
+};
+
+/* Display Types */
+
+#define ACPI_DISPLAY_SUMMARY (u8) 0
+#define ACPI_DISPLAY_OBJECTS (u8) 1
+#define ACPI_DISPLAY_MASK (u8) 1
+
+#define ACPI_DISPLAY_SHORT (u8) 2
+
#endif
diff --git a/include/acpi/actables.h b/include/acpi/actables.h
index 30a47542e1c..4dbaf02fe52 100644
--- a/include/acpi/actables.h
+++ b/include/acpi/actables.h
@@ -136,7 +136,11 @@ acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc);
acpi_status
acpi_tb_verify_table_checksum(struct acpi_table_header *table_header);
-u8 acpi_tb_generate_checksum(void *buffer, u32 length);
+u8 acpi_tb_sum_table(void *buffer, u32 length);
+
+u8 acpi_tb_generate_checksum(struct acpi_table_header *table);
+
+void acpi_tb_set_checksum(struct acpi_table_header *table);
acpi_status
acpi_tb_validate_table_header(struct acpi_table_header *table_header);
diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h
index ed53f842dad..b125ceed9cb 100644
--- a/include/acpi/actbl.h
+++ b/include/acpi/actbl.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Name: actbl.h - Table data structures defined in ACPI specification
+ * Name: actbl.h - Basic ACPI Table Definitions
*
*****************************************************************************/
@@ -45,66 +45,45 @@
#define __ACTBL_H__
/*
- * Note about bitfields: The u8 type is used for bitfields in ACPI tables.
- * This is the only type that is even remotely portable. Anything else is not
- * portable, so do not use any other bitfield types.
- */
-
-/*
- * Values for description table header signatures
+ * Values for description table header signatures. Useful because they make
+ * it more difficult to inadvertently type in the wrong signature.
*/
-#define RSDP_NAME "RSDP"
-#define RSDP_SIG "RSD PTR " /* RSDT Pointer signature */
-#define APIC_SIG "APIC" /* Multiple APIC Description Table */
#define DSDT_SIG "DSDT" /* Differentiated System Description Table */
#define FADT_SIG "FACP" /* Fixed ACPI Description Table */
#define FACS_SIG "FACS" /* Firmware ACPI Control Structure */
#define PSDT_SIG "PSDT" /* Persistent System Description Table */
+#define RSDP_SIG "RSD PTR " /* Root System Description Pointer */
#define RSDT_SIG "RSDT" /* Root System Description Table */
#define XSDT_SIG "XSDT" /* Extended System Description Table */
#define SSDT_SIG "SSDT" /* Secondary System Description Table */
-#define SBST_SIG "SBST" /* Smart Battery Specification Table */
-#define SPIC_SIG "SPIC" /* IOSAPIC table */
-#define BOOT_SIG "BOOT" /* Boot table */
-
-#define GL_OWNED 0x02 /* Ownership of global lock is bit 1 */
+#define RSDP_NAME "RSDP"
/*
- * Common table types. The base code can remain
- * constant if the underlying tables are changed
+ * All tables and structures must be byte-packed to match the ACPI
+ * specification, since the tables are provided by the system BIOS
*/
-#define RSDT_DESCRIPTOR struct rsdt_descriptor_rev2
-#define XSDT_DESCRIPTOR struct xsdt_descriptor_rev2
-#define FACS_DESCRIPTOR struct facs_descriptor_rev2
-#define FADT_DESCRIPTOR struct fadt_descriptor_rev2
-
#pragma pack(1)
/*
- * ACPI Version-independent tables
+ * These are the ACPI tables that are directly consumed by the subsystem.
+ *
+ * The RSDP and FACS do not use the common ACPI table header. All other ACPI
+ * tables use the header.
*
- * NOTE: The tables that are specific to ACPI versions (1.0, 2.0, etc.)
- * are in separate files.
+ * Note about bitfields: The u8 type is used for bitfields in ACPI tables.
+ * This is the only type that is even remotely portable. Anything else is not
+ * portable, so do not use any other bitfield types.
*/
-struct rsdp_descriptor { /* Root System Descriptor Pointer */
- char signature[8]; /* ACPI signature, contains "RSD PTR " */
- u8 checksum; /* ACPI 1.0 checksum */
- char oem_id[6]; /* OEM identification */
- u8 revision; /* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */
- u32 rsdt_physical_address; /* 32-bit physical address of the RSDT */
- u32 length; /* XSDT Length in bytes, including header */
- u64 xsdt_physical_address; /* 64-bit physical address of the XSDT */
- u8 extended_checksum; /* Checksum of entire table (ACPI 2.0) */
- char reserved[3]; /* Reserved, must be zero */
-};
-struct acpi_common_facs { /* Common FACS for internal use */
- u32 *global_lock;
- u64 *firmware_waking_vector;
- u8 vector_width;
-};
+/*******************************************************************************
+ *
+ * ACPI Table Header. This common header is used by all tables except the
+ * RSDP and FACS. The define is used for direct inclusion of header into
+ * other ACPI tables
+ *
+ ******************************************************************************/
-#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
+#define ACPI_TABLE_HEADER_DEF \
char signature[4]; /* ASCII table signature */\
u32 length; /* Length of table in bytes, including this header */\
u8 revision; /* ACPI Specification minor version # */\
@@ -112,154 +91,239 @@ struct acpi_common_facs { /* Common FACS for internal use */
char oem_id[6]; /* ASCII OEM identification */\
char oem_table_id[8]; /* ASCII OEM table identification */\
u32 oem_revision; /* OEM revision number */\
- char asl_compiler_id [4]; /* ASCII ASL compiler vendor ID */\
+ char asl_compiler_id[4]; /* ASCII ASL compiler vendor ID */\
u32 asl_compiler_revision; /* ASL compiler version */
-struct acpi_table_header { /* ACPI common table header */
+struct acpi_table_header {
ACPI_TABLE_HEADER_DEF};
/*
- * MADT values and structures
+ * GAS - Generic Address Structure (ACPI 2.0+)
*/
+struct acpi_generic_address {
+ u8 address_space_id; /* Address space where struct or register exists */
+ u8 register_bit_width; /* Size in bits of given register */
+ u8 register_bit_offset; /* Bit offset within the register */
+ u8 access_width; /* Minimum Access size (ACPI 3.0) */
+ u64 address; /* 64-bit address of struct or register */
+};
-/* Values for MADT PCATCompat */
+/*******************************************************************************
+ *
+ * RSDP - Root System Description Pointer (Signature is "RSD PTR ")
+ *
+ ******************************************************************************/
+
+struct rsdp_descriptor {
+ char signature[8]; /* ACPI signature, contains "RSD PTR " */
+ u8 checksum; /* ACPI 1.0 checksum */
+ char oem_id[6]; /* OEM identification */
+ u8 revision; /* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */
+ u32 rsdt_physical_address; /* 32-bit physical address of the RSDT */
+ u32 length; /* Table length in bytes, including header (ACPI 2.0+) */
+ u64 xsdt_physical_address; /* 64-bit physical address of the XSDT (ACPI 2.0+) */
+ u8 extended_checksum; /* Checksum of entire table (ACPI 2.0+) */
+ u8 reserved[3]; /* Reserved, must be zero */
+};
-#define DUAL_PIC 0
-#define MULTIPLE_APIC 1
+#define ACPI_RSDP_REV0_SIZE 20 /* Size of original ACPI 1.0 RSDP */
-/* Master MADT */
+/*******************************************************************************
+ *
+ * RSDT/XSDT - Root System Description Tables
+ *
+ ******************************************************************************/
-struct multiple_apic_table {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u32 local_apic_address; /* Physical address of local APIC */
+struct rsdt_descriptor {
+ ACPI_TABLE_HEADER_DEF u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */
+};
+
+struct xsdt_descriptor {
+ ACPI_TABLE_HEADER_DEF u64 table_offset_entry[1]; /* Array of pointers to ACPI tables */
+};
+
+/*******************************************************************************
+ *
+ * FACS - Firmware ACPI Control Structure (FACS)
+ *
+ ******************************************************************************/
+
+struct facs_descriptor {
+ char signature[4]; /* ASCII table signature */
+ u32 length; /* Length of structure, in bytes */
+ u32 hardware_signature; /* Hardware configuration signature */
+ u32 firmware_waking_vector; /* 32-bit physical address of the Firmware Waking Vector */
+ u32 global_lock; /* Global Lock for shared hardware resources */
/* Flags (32 bits) */
- u8 PCATcompat:1; /* 00: System also has dual 8259s */
+ u8 S4bios_f:1; /* 00: S4BIOS support is present */
u8:7; /* 01-07: Reserved, must be zero */
u8 reserved1[3]; /* 08-31: Reserved, must be zero */
-};
-/* Values for Type in APIC_HEADER_DEF */
+ u64 xfirmware_waking_vector; /* 64-bit version of the Firmware Waking Vector (ACPI 2.0+) */
+ u8 version; /* Version of this table (ACPI 2.0+) */
+ u8 reserved[31]; /* Reserved, must be zero */
+};
-#define APIC_PROCESSOR 0
-#define APIC_IO 1
-#define APIC_XRUPT_OVERRIDE 2
-#define APIC_NMI 3
-#define APIC_LOCAL_NMI 4
-#define APIC_ADDRESS_OVERRIDE 5
-#define APIC_IO_SAPIC 6
-#define APIC_LOCAL_SAPIC 7
-#define APIC_XRUPT_SOURCE 8
-#define APIC_RESERVED 9 /* 9 and greater are reserved */
+#define ACPI_GLOCK_PENDING 0x01 /* 00: Pending global lock ownership */
+#define ACPI_GLOCK_OWNED 0x02 /* 01: Global lock is owned */
/*
- * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
+ * Common FACS - This is a version-independent FACS structure used for internal use only
*/
-#define APIC_HEADER_DEF /* Common APIC sub-structure header */\
- u8 type; \
- u8 length;
-
-struct apic_header {
-APIC_HEADER_DEF};
-
-/* Values for MPS INTI flags */
-
-#define POLARITY_CONFORMS 0
-#define POLARITY_ACTIVE_HIGH 1
-#define POLARITY_RESERVED 2
-#define POLARITY_ACTIVE_LOW 3
-
-#define TRIGGER_CONFORMS 0
-#define TRIGGER_EDGE 1
-#define TRIGGER_RESERVED 2
-#define TRIGGER_LEVEL 3
-
-/* Common flag definitions (16 bits each) */
-
-#define MPS_INTI_FLAGS \
- u8 polarity : 2; /* 00-01: Polarity of APIC I/O input signals */\
- u8 trigger_mode : 2; /* 02-03: Trigger mode of APIC input signals */\
- u8 : 4; /* 04-07: Reserved, must be zero */\
- u8 reserved1; /* 08-15: Reserved, must be zero */
-
-#define LOCAL_APIC_FLAGS \
- u8 processor_enabled: 1; /* 00: Processor is usable if set */\
- u8 : 7; /* 01-07: Reserved, must be zero */\
- u8 reserved2; /* 08-15: Reserved, must be zero */
-
-/* Sub-structures for MADT */
-
-struct madt_processor_apic {
- APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */
- u8 local_apic_id; /* Processor's local APIC id */
- LOCAL_APIC_FLAGS};
-
-struct madt_io_apic {
- APIC_HEADER_DEF u8 io_apic_id; /* I/O APIC ID */
- u8 reserved; /* Reserved - must be zero */
- u32 address; /* APIC physical address */
- u32 interrupt; /* Global system interrupt where INTI
- * lines start */
+struct acpi_common_facs {
+ u32 *global_lock;
+ u64 *firmware_waking_vector;
+ u8 vector_width;
};
-struct madt_interrupt_override {
- APIC_HEADER_DEF u8 bus; /* 0 - ISA */
- u8 source; /* Interrupt source (IRQ) */
- u32 interrupt; /* Global system interrupt */
- MPS_INTI_FLAGS};
+/*******************************************************************************
+ *
+ * FADT - Fixed ACPI Description Table (Signature "FACP")
+ *
+ ******************************************************************************/
+
+/* Fields common to all versions of the FADT */
+
+#define ACPI_FADT_COMMON \
+ ACPI_TABLE_HEADER_DEF \
+ u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ \
+ u32 V1_dsdt; /* 32-bit physical address of DSDT */ \
+ u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ \
+ u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ \
+ u16 sci_int; /* System vector of SCI interrupt */ \
+ u32 smi_cmd; /* Port address of SMI command port */ \
+ u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ \
+ u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ \
+ u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ \
+ u8 pstate_cnt; /* Processor performance state control*/ \
+ u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a Event Reg Blk */ \
+ u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b Event Reg Blk */ \
+ u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ \
+ u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ \
+ u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ \
+ u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ \
+ u32 V1_gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ \
+ u32 V1_gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ \
+ u8 pm1_evt_len; /* Byte Length of ports at pm1_x_evt_blk */ \
+ u8 pm1_cnt_len; /* Byte Length of ports at pm1_x_cnt_blk */ \
+ u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ \
+ u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ \
+ u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ \
+ u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ \
+ u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ \
+ u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ \
+ u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ \
+ u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ \
+ u16 flush_size; /* Processor's memory cache line width, in bytes */ \
+ u16 flush_stride; /* Number of flush strides that need to be read */ \
+ u8 duty_offset; /* Processor's duty cycle index in processor's P_CNT reg*/ \
+ u8 duty_width; /* Processor's duty cycle value bit width in P_CNT register.*/ \
+ u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ \
+ u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ \
+ u8 century; /* Index to century in RTC CMOS RAM */ \
+ u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ \
+ u8 reserved2; /* Reserved, must be zero */
-struct madt_nmi_source {
- APIC_HEADER_DEF MPS_INTI_FLAGS u32 interrupt; /* Global system interrupt */
+/*
+ * ACPI 2.0+ FADT
+ */
+struct fadt_descriptor {
+ ACPI_FADT_COMMON
+ /* Flags (32 bits) */
+ u8 wb_invd:1; /* 00: The wbinvd instruction works properly */
+ u8 wb_invd_flush:1; /* 01: The wbinvd flushes but does not invalidate */
+ u8 proc_c1:1; /* 02: All processors support C1 state */
+ u8 plvl2_up:1; /* 03: C2 state works on MP system */
+ u8 pwr_button:1; /* 04: Power button is handled as a generic feature */
+ u8 sleep_button:1; /* 05: Sleep button is handled as a generic feature, or not present */
+ u8 fixed_rTC:1; /* 06: RTC wakeup stat not in fixed register space */
+ u8 rtcs4:1; /* 07: RTC wakeup stat not possible from S4 */
+ u8 tmr_val_ext:1; /* 08: tmr_val is 32 bits 0=24-bits */
+ u8 dock_cap:1; /* 09: Docking supported */
+ u8 reset_reg_sup:1; /* 10: System reset via the FADT RESET_REG supported */
+ u8 sealed_case:1; /* 11: No internal expansion capabilities and case is sealed */
+ u8 headless:1; /* 12: No local video capabilities or local input devices */
+ u8 cpu_sw_sleep:1; /* 13: Must execute native instruction after writing SLP_TYPx register */
+
+ u8 pci_exp_wak:1; /* 14: System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */
+ u8 use_platform_clock:1; /* 15: OSPM should use platform-provided timer (ACPI 3.0) */
+ u8 S4rtc_sts_valid:1; /* 16: Contents of RTC_STS valid after S4 wake (ACPI 3.0) */
+ u8 remote_power_on_capable:1; /* 17: System is compatible with remote power on (ACPI 3.0) */
+ u8 force_apic_cluster_model:1; /* 18: All local APICs must use cluster model (ACPI 3.0) */
+ u8 force_apic_physical_destination_mode:1; /* 19: All local x_aPICs must use physical dest mode (ACPI 3.0) */
+ u8:4; /* 20-23: Reserved, must be zero */
+ u8 reserved3; /* 24-31: Reserved, must be zero */
+
+ struct acpi_generic_address reset_register; /* Reset register address in GAS format */
+ u8 reset_value; /* Value to write to the reset_register port to reset the system */
+ u8 reserved4[3]; /* These three bytes must be zero */
+ u64 xfirmware_ctrl; /* 64-bit physical address of FACS */
+ u64 Xdsdt; /* 64-bit physical address of DSDT */
+ struct acpi_generic_address xpm1a_evt_blk; /* Extended Power Mgt 1a acpi_event Reg Blk address */
+ struct acpi_generic_address xpm1b_evt_blk; /* Extended Power Mgt 1b acpi_event Reg Blk address */
+ struct acpi_generic_address xpm1a_cnt_blk; /* Extended Power Mgt 1a Control Reg Blk address */
+ struct acpi_generic_address xpm1b_cnt_blk; /* Extended Power Mgt 1b Control Reg Blk address */
+ struct acpi_generic_address xpm2_cnt_blk; /* Extended Power Mgt 2 Control Reg Blk address */
+ struct acpi_generic_address xpm_tmr_blk; /* Extended Power Mgt Timer Ctrl Reg Blk address */
+ struct acpi_generic_address xgpe0_blk; /* Extended General Purpose acpi_event 0 Reg Blk address */
+ struct acpi_generic_address xgpe1_blk; /* Extended General Purpose acpi_event 1 Reg Blk address */
};
-struct madt_local_apic_nmi {
- APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */
- MPS_INTI_FLAGS u8 lint; /* LINTn to which NMI is connected */
+/*
+ * "Down-revved" ACPI 2.0 FADT descriptor
+ * Defined here to allow compiler to generate the length of the struct
+ */
+struct fadt_descriptor_rev2_minus {
+ ACPI_FADT_COMMON u32 flags;
+ struct acpi_generic_address reset_register; /* Reset register address in GAS format */
+ u8 reset_value; /* Value to write to the reset_register port to reset the system. */
+ u8 reserved7[3]; /* Reserved, must be zero */
};
-struct madt_address_override {
- APIC_HEADER_DEF u16 reserved; /* Reserved, must be zero */
- u64 address; /* APIC physical address */
+/*
+ * ACPI 1.0 FADT
+ * Defined here to allow compiler to generate the length of the struct
+ */
+struct fadt_descriptor_rev1 {
+ ACPI_FADT_COMMON u32 flags;
};
-struct madt_io_sapic {
- APIC_HEADER_DEF u8 io_sapic_id; /* I/O SAPIC ID */
- u8 reserved; /* Reserved, must be zero */
- u32 interrupt_base; /* Glocal interrupt for SAPIC start */
- u64 address; /* SAPIC physical address */
-};
+/* FADT: Prefered Power Management Profiles */
-struct madt_local_sapic {
- APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */
- u8 local_sapic_id; /* SAPIC ID */
- u8 local_sapic_eid; /* SAPIC EID */
- u8 reserved[3]; /* Reserved, must be zero */
- LOCAL_APIC_FLAGS u32 processor_uID; /* Numeric UID - ACPI 3.0 */
- char processor_uIDstring[1]; /* String UID - ACPI 3.0 */
-};
+#define PM_UNSPECIFIED 0
+#define PM_DESKTOP 1
+#define PM_MOBILE 2
+#define PM_WORKSTATION 3
+#define PM_ENTERPRISE_SERVER 4
+#define PM_SOHO_SERVER 5
+#define PM_APPLIANCE_PC 6
-struct madt_interrupt_source {
- APIC_HEADER_DEF MPS_INTI_FLAGS u8 interrupt_type; /* 1=PMI, 2=INIT, 3=corrected */
- u8 processor_id; /* Processor ID */
- u8 processor_eid; /* Processor EID */
- u8 io_sapic_vector; /* Vector value for PMI interrupts */
- u32 interrupt; /* Global system interrupt */
- u32 flags; /* Interrupt Source Flags */
-};
+/* FADT: Boot Arch Flags */
-/*
- * Smart Battery
- */
-struct smart_battery_table {
- ACPI_TABLE_HEADER_DEF u32 warning_level;
- u32 low_level;
- u32 critical_level;
-};
+#define BAF_LEGACY_DEVICES 0x0001
+#define BAF_8042_KEYBOARD_CONTROLLER 0x0002
+
+#define FADT2_REVISION_ID 3
+#define FADT2_MINUS_REVISION_ID 2
+
+/* Reset to default packing */
#pragma pack()
/*
+ * This macro is temporary until the table bitfield flag definitions
+ * are removed and replaced by a Flags field.
+ */
+#define ACPI_FLAG_OFFSET(d,f,o) (u8) (ACPI_OFFSET (d,f) + \
+ sizeof(((d *)0)->f) + o)
+/*
+ * Get the remaining ACPI tables
+ */
+#include "actbl1.h"
+
+/*
* ACPI Table information. We save the table address, length,
* and type of memory allocation (mapped or allocated) for each
* table for 1) when we exit, and 2) if a new table is installed
@@ -290,27 +354,17 @@ struct acpi_table_support {
u8 flags;
};
-/*
- * Get the ACPI version-specific tables
- */
-#include "actbl1.h" /* Acpi 1.0 table definitions */
-#include "actbl2.h" /* Acpi 2.0 table definitions */
-
extern u8 acpi_fadt_is_v1; /* is set to 1 if FADT is revision 1,
* needed for certain workarounds */
+/* Macros used to generate offsets to specific table fields */
-#pragma pack(1)
-/*
- * High performance timer
- */
-struct hpet_table {
- ACPI_TABLE_HEADER_DEF u32 hardware_id;
- struct acpi_generic_address base_address;
- u8 hpet_number;
- u16 clock_tick;
- u8 attributes;
-};
+#define ACPI_FACS_OFFSET(f) (u8) ACPI_OFFSET (struct facs_descriptor,f)
+#define ACPI_FADT_OFFSET(f) (u8) ACPI_OFFSET (struct fadt_descriptor, f)
+#define ACPI_GAS_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_generic_address,f)
+#define ACPI_HDR_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_header,f)
+#define ACPI_RSDP_OFFSET(f) (u8) ACPI_OFFSET (struct rsdp_descriptor,f)
-#pragma pack()
+#define ACPI_FADT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct fadt_descriptor,f,o)
+#define ACPI_FACS_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct facs_descriptor,f,o)
#endif /* __ACTBL_H__ */
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index cd428d57add..745a6445a4f 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Name: actbl1.h - ACPI 1.0 tables
+ * Name: actbl1.h - Additional ACPI table definitions
*
*****************************************************************************/
@@ -44,92 +44,599 @@
#ifndef __ACTBL1_H__
#define __ACTBL1_H__
+/*******************************************************************************
+ *
+ * Additional ACPI Tables
+ *
+ * These tables are not consumed directly by the ACPICA subsystem, but are
+ * included here to support device drivers and the AML disassembler.
+ *
+ ******************************************************************************/
+
+/*
+ * Values for description table header signatures. Useful because they make
+ * it more difficult to inadvertently type in the wrong signature.
+ */
+#define ACPI_SIG_ASF "ASF!" /* Alert Standard Format table */
+#define ACPI_SIG_BOOT "BOOT" /* Simple Boot Flag Table */
+#define ACPI_SIG_CPEP "CPEP" /* Corrected Platform Error Polling table */
+#define ACPI_SIG_DBGP "DBGP" /* Debug Port table */
+#define ACPI_SIG_ECDT "ECDT" /* Embedded Controller Boot Resources Table */
+#define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */
+#define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */
+#define ACPI_SIG_MCFG "MCFG" /* PCI Memory Mapped Configuration table */
+#define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */
+#define ACPI_SIG_SLIT "SLIT" /* System Locality Distance Information Table */
+#define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */
+#define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */
+#define ACPI_SIG_SRAT "SRAT" /* System Resource Affinity Table */
+#define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */
+#define ACPI_SIG_WDRT "WDRT" /* Watchdog Resource Table */
+
+/* Legacy names */
+
+#define APIC_SIG "APIC" /* Multiple APIC Description Table */
+#define BOOT_SIG "BOOT" /* Simple Boot Flag Table */
+#define SBST_SIG "SBST" /* Smart Battery Specification Table */
+
+/*
+ * All tables must be byte-packed to match the ACPI specification, since
+ * the tables are provided by the system BIOS.
+ */
#pragma pack(1)
/*
- * ACPI 1.0 Root System Description Table (RSDT)
+ * Note about bitfields: The u8 type is used for bitfields in ACPI tables.
+ * This is the only type that is even remotely portable. Anything else is not
+ * portable, so do not use any other bitfield types.
*/
-struct rsdt_descriptor_rev1 {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */
-};
+
+/*******************************************************************************
+ *
+ * ASF - Alert Standard Format table (Signature "ASF!")
+ *
+ ******************************************************************************/
+
+struct acpi_table_asf {
+ACPI_TABLE_HEADER_DEF};
+
+#define ACPI_ASF_HEADER_DEF \
+ u8 type; \
+ u8 reserved; \
+ u16 length;
+
+struct acpi_asf_header {
+ACPI_ASF_HEADER_DEF};
+
+/* Values for Type field */
+
+#define ASF_INFO 0
+#define ASF_ALERT 1
+#define ASF_CONTROL 2
+#define ASF_BOOT 3
+#define ASF_ADDRESS 4
+#define ASF_RESERVED 5
/*
- * ACPI 1.0 Firmware ACPI Control Structure (FACS)
+ * ASF subtables
*/
-struct facs_descriptor_rev1 {
- char signature[4]; /* ASCII table signature */
- u32 length; /* Length of structure in bytes */
- u32 hardware_signature; /* Hardware configuration signature */
- u32 firmware_waking_vector; /* ACPI OS waking vector */
- u32 global_lock; /* Global Lock */
+
+/* 0: ASF Information */
+
+struct acpi_asf_info {
+ ACPI_ASF_HEADER_DEF u8 min_reset_value;
+ u8 min_poll_interval;
+ u16 system_id;
+ u32 mfg_id;
+ u8 flags;
+ u8 reserved2[3];
+};
+
+/* 1: ASF Alerts */
+
+struct acpi_asf_alert {
+ ACPI_ASF_HEADER_DEF u8 assert_mask;
+ u8 deassert_mask;
+ u8 alerts;
+ u8 data_length;
+ u8 array[1];
+};
+
+/* 2: ASF Remote Control */
+
+struct acpi_asf_remote {
+ ACPI_ASF_HEADER_DEF u8 controls;
+ u8 data_length;
+ u16 reserved2;
+ u8 array[1];
+};
+
+/* 3: ASF RMCP Boot Options */
+
+struct acpi_asf_rmcp {
+ ACPI_ASF_HEADER_DEF u8 capabilities[7];
+ u8 completion_code;
+ u32 enterprise_id;
+ u8 command;
+ u16 parameter;
+ u16 boot_options;
+ u16 oem_parameters;
+};
+
+/* 4: ASF Address */
+
+struct acpi_asf_address {
+ ACPI_ASF_HEADER_DEF u8 eprom_address;
+ u8 devices;
+ u8 smbus_addresses[1];
+};
+
+/*******************************************************************************
+ *
+ * BOOT - Simple Boot Flag Table
+ *
+ ******************************************************************************/
+
+struct acpi_table_boot {
+ ACPI_TABLE_HEADER_DEF u8 cmos_index; /* Index in CMOS RAM for the boot register */
+ u8 reserved[3];
+};
+
+/*******************************************************************************
+ *
+ * CPEP - Corrected Platform Error Polling table
+ *
+ ******************************************************************************/
+
+struct acpi_table_cpep {
+ ACPI_TABLE_HEADER_DEF u64 reserved;
+};
+
+/* Subtable */
+
+struct acpi_cpep_polling {
+ u8 type;
+ u8 length;
+ u8 processor_id; /* Processor ID */
+ u8 processor_eid; /* Processor EID */
+ u32 polling_interval; /* Polling interval (msec) */
+};
+
+/*******************************************************************************
+ *
+ * DBGP - Debug Port table
+ *
+ ******************************************************************************/
+
+struct acpi_table_dbgp {
+ ACPI_TABLE_HEADER_DEF u8 interface_type; /* 0=full 16550, 1=subset of 16550 */
+ u8 reserved[3];
+ struct acpi_generic_address debug_port;
+};
+
+/*******************************************************************************
+ *
+ * ECDT - Embedded Controller Boot Resources Table
+ *
+ ******************************************************************************/
+
+struct ec_boot_resources {
+ ACPI_TABLE_HEADER_DEF struct acpi_generic_address ec_control; /* Address of EC command/status register */
+ struct acpi_generic_address ec_data; /* Address of EC data register */
+ u32 uid; /* Unique ID - must be same as the EC _UID method */
+ u8 gpe_bit; /* The GPE for the EC */
+ u8 ec_id[1]; /* Full namepath of the EC in the ACPI namespace */
+};
+
+/*******************************************************************************
+ *
+ * HPET - High Precision Event Timer table
+ *
+ ******************************************************************************/
+
+struct acpi_hpet_table {
+ ACPI_TABLE_HEADER_DEF u32 hardware_id; /* Hardware ID of event timer block */
+ struct acpi_generic_address base_address; /* Address of event timer block */
+ u8 hpet_number; /* HPET sequence number */
+ u16 clock_tick; /* Main counter min tick, periodic mode */
+ u8 attributes;
+};
+
+#if 0 /* HPET flags to be converted to macros */
+struct { /* Flags (8 bits) */
+ u8 page_protect:1; /* 00: No page protection */
+ u8 page_protect4:1; /* 01: 4_kB page protected */
+ u8 page_protect64:1; /* 02: 64_kB page protected */
+ u8:5; /* 03-07: Reserved, must be zero */
+} flags;
+#endif
+
+/*******************************************************************************
+ *
+ * MADT - Multiple APIC Description Table
+ *
+ ******************************************************************************/
+
+struct multiple_apic_table {
+ ACPI_TABLE_HEADER_DEF u32 local_apic_address; /* Physical address of local APIC */
/* Flags (32 bits) */
- u8 S4bios_f:1; /* 00: S4BIOS support is present */
+ u8 PCATcompat:1; /* 00: System also has dual 8259s */
u8:7; /* 01-07: Reserved, must be zero */
u8 reserved1[3]; /* 08-31: Reserved, must be zero */
-
- u8 reserved2[40]; /* Reserved, must be zero */
};
+/* Values for MADT PCATCompat */
+
+#define DUAL_PIC 0
+#define MULTIPLE_APIC 1
+
+/* Common MADT Sub-table header */
+
+#define APIC_HEADER_DEF \
+ u8 type; \
+ u8 length;
+
+struct apic_header {
+APIC_HEADER_DEF};
+
+/* Values for Type in struct apic_header */
+
+#define APIC_PROCESSOR 0
+#define APIC_IO 1
+#define APIC_XRUPT_OVERRIDE 2
+#define APIC_NMI 3
+#define APIC_LOCAL_NMI 4
+#define APIC_ADDRESS_OVERRIDE 5
+#define APIC_IO_SAPIC 6
+#define APIC_LOCAL_SAPIC 7
+#define APIC_XRUPT_SOURCE 8
+#define APIC_RESERVED 9 /* 9 and greater are reserved */
+
+/* Flag definitions for MADT sub-tables */
+
+#define ACPI_MADT_IFLAGS /* INTI flags (16 bits) */ \
+ u8 polarity : 2; /* 00-01: Polarity of APIC I/O input signals */\
+ u8 trigger_mode : 2; /* 02-03: Trigger mode of APIC input signals */\
+ u8 : 4; /* 04-07: Reserved, must be zero */\
+ u8 reserved1; /* 08-15: Reserved, must be zero */
+
+#define ACPI_MADT_LFLAGS /* Local Sapic flags (32 bits) */ \
+ u8 processor_enabled: 1; /* 00: Processor is usable if set */\
+ u8 : 7; /* 01-07: Reserved, must be zero */\
+ u8 reserved2[3]; /* 08-31: Reserved, must be zero */
+
+/* Values for MPS INTI flags */
+
+#define POLARITY_CONFORMS 0
+#define POLARITY_ACTIVE_HIGH 1
+#define POLARITY_RESERVED 2
+#define POLARITY_ACTIVE_LOW 3
+
+#define TRIGGER_CONFORMS 0
+#define TRIGGER_EDGE 1
+#define TRIGGER_RESERVED 2
+#define TRIGGER_LEVEL 3
+
/*
- * ACPI 1.0 Fixed ACPI Description Table (FADT)
+ * MADT Sub-tables, correspond to Type in struct apic_header
*/
-struct fadt_descriptor_rev1 {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u32 firmware_ctrl; /* Physical address of FACS */
- u32 dsdt; /* Physical address of DSDT */
- u8 model; /* System Interrupt Model */
- u8 reserved1; /* Reserved, must be zero */
- u16 sci_int; /* System vector of SCI interrupt */
- u32 smi_cmd; /* Port address of SMI command port */
- u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */
- u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */
- u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
- u8 reserved2; /* Reserved, must be zero */
- u32 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
- u32 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
- u32 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
- u32 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
- u32 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
- u32 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
- u32 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
- u32 gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
- u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
- u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
- u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
- u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */
- u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
- u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
- u8 gpe1_base; /* Offset in gpe model where gpe1 events start */
- u8 reserved3; /* Reserved, must be zero */
- u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
- u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
- u16 flush_size; /* Size of area read to flush caches */
- u16 flush_stride; /* Stride used in flushing caches */
- u8 duty_offset; /* Bit location of duty cycle field in p_cnt reg */
- u8 duty_width; /* Bit width of duty cycle field in p_cnt reg */
- u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
- u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
- u8 century; /* Index to century in RTC CMOS RAM */
- u8 reserved4[3]; /* Reserved, must be zero */
+
+/* 0: processor APIC */
+
+struct madt_processor_apic {
+ APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */
+ u8 local_apic_id; /* Processor's local APIC id */
+ ACPI_MADT_LFLAGS};
+
+/* 1: IO APIC */
+
+struct madt_io_apic {
+ APIC_HEADER_DEF u8 io_apic_id; /* I/O APIC ID */
+ u8 reserved; /* Reserved - must be zero */
+ u32 address; /* APIC physical address */
+ u32 interrupt; /* Global system interrupt where INTI lines start */
+};
+
+/* 2: Interrupt Override */
+
+struct madt_interrupt_override {
+ APIC_HEADER_DEF u8 bus; /* 0 - ISA */
+ u8 source; /* Interrupt source (IRQ) */
+ u32 interrupt; /* Global system interrupt */
+ ACPI_MADT_IFLAGS};
+
+/* 3: NMI Sources */
+
+struct madt_nmi_source {
+ APIC_HEADER_DEF ACPI_MADT_IFLAGS u32 interrupt; /* Global system interrupt */
+};
+
+/* 4: Local APIC NMI */
+
+struct madt_local_apic_nmi {
+ APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */
+ ACPI_MADT_IFLAGS u8 lint; /* LINTn to which NMI is connected */
+};
+
+/* 5: Address Override */
+
+struct madt_address_override {
+ APIC_HEADER_DEF u16 reserved; /* Reserved, must be zero */
+ u64 address; /* APIC physical address */
+};
+
+/* 6: I/O Sapic */
+
+struct madt_io_sapic {
+ APIC_HEADER_DEF u8 io_sapic_id; /* I/O SAPIC ID */
+ u8 reserved; /* Reserved, must be zero */
+ u32 interrupt_base; /* Glocal interrupt for SAPIC start */
+ u64 address; /* SAPIC physical address */
+};
+
+/* 7: Local Sapic */
+
+struct madt_local_sapic {
+ APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */
+ u8 local_sapic_id; /* SAPIC ID */
+ u8 local_sapic_eid; /* SAPIC EID */
+ u8 reserved[3]; /* Reserved, must be zero */
+ ACPI_MADT_LFLAGS u32 processor_uID; /* Numeric UID - ACPI 3.0 */
+ char processor_uIDstring[1]; /* String UID - ACPI 3.0 */
+};
+
+/* 8: Platform Interrupt Source */
+
+struct madt_interrupt_source {
+ APIC_HEADER_DEF ACPI_MADT_IFLAGS u8 interrupt_type; /* 1=PMI, 2=INIT, 3=corrected */
+ u8 processor_id; /* Processor ID */
+ u8 processor_eid; /* Processor EID */
+ u8 io_sapic_vector; /* Vector value for PMI interrupts */
+ u32 interrupt; /* Global system interrupt */
+ u32 flags; /* Interrupt Source Flags */
+};
+
+#ifdef DUPLICATE_DEFINITION_WITH_LINUX_ACPI_H
+/*******************************************************************************
+ *
+ * MCFG - PCI Memory Mapped Configuration table and sub-table
+ *
+ ******************************************************************************/
+
+struct acpi_table_mcfg {
+ ACPI_TABLE_HEADER_DEF u8 reserved[8];
+};
+
+struct acpi_mcfg_allocation {
+ u64 base_address; /* Base address, processor-relative */
+ u16 pci_segment; /* PCI segment group number */
+ u8 start_bus_number; /* Starting PCI Bus number */
+ u8 end_bus_number; /* Final PCI Bus number */
+ u32 reserved;
+};
+#endif
+
+/*******************************************************************************
+ *
+ * SBST - Smart Battery Specification Table
+ *
+ ******************************************************************************/
+
+struct smart_battery_table {
+ ACPI_TABLE_HEADER_DEF u32 warning_level;
+ u32 low_level;
+ u32 critical_level;
+};
+
+/*******************************************************************************
+ *
+ * SLIT - System Locality Distance Information Table
+ *
+ ******************************************************************************/
+
+struct system_locality_info {
+ ACPI_TABLE_HEADER_DEF u64 locality_count;
+ u8 entry[1][1];
+};
+
+/*******************************************************************************
+ *
+ * SPCR - Serial Port Console Redirection table
+ *
+ ******************************************************************************/
+
+struct acpi_table_spcr {
+ ACPI_TABLE_HEADER_DEF u8 interface_type; /* 0=full 16550, 1=subset of 16550 */
+ u8 reserved[3];
+ struct acpi_generic_address serial_port;
+ u8 interrupt_type;
+ u8 pc_interrupt;
+ u32 interrupt;
+ u8 baud_rate;
+ u8 parity;
+ u8 stop_bits;
+ u8 flow_control;
+ u8 terminal_type;
+ u8 reserved2;
+ u16 pci_device_id;
+ u16 pci_vendor_id;
+ u8 pci_bus;
+ u8 pci_device;
+ u8 pci_function;
+ u32 pci_flags;
+ u8 pci_segment;
+ u32 reserved3;
+};
+
+/*******************************************************************************
+ *
+ * SPMI - Server Platform Management Interface table
+ *
+ ******************************************************************************/
+
+struct acpi_table_spmi {
+ ACPI_TABLE_HEADER_DEF u8 reserved;
+ u8 interface_type;
+ u16 spec_revision; /* Version of IPMI */
+ u8 interrupt_type;
+ u8 gpe_number; /* GPE assigned */
+ u8 reserved2;
+ u8 pci_device_flag;
+ u32 interrupt;
+ struct acpi_generic_address ipmi_register;
+ u8 pci_segment;
+ u8 pci_bus;
+ u8 pci_device;
+ u8 pci_function;
+};
+
+/*******************************************************************************
+ *
+ * SRAT - System Resource Affinity Table
+ *
+ ******************************************************************************/
+
+struct system_resource_affinity {
+ ACPI_TABLE_HEADER_DEF u32 reserved1; /* Must be value '1' */
+ u64 reserved2; /* Reserved, must be zero */
+};
+
+/* SRAT common sub-table header */
+
+#define SRAT_SUBTABLE_HEADER \
+ u8 type; \
+ u8 length;
+
+/* Values for Type above */
+
+#define SRAT_CPU_AFFINITY 0
+#define SRAT_MEMORY_AFFINITY 1
+#define SRAT_RESERVED 2
+
+/* SRAT sub-tables */
+
+struct static_resource_alloc {
+ SRAT_SUBTABLE_HEADER u8 proximity_domain_lo;
+ u8 apic_id;
+
+ /* Flags (32 bits) */
+
+ u8 enabled:1; /* 00: Use affinity structure */
+ u8:7; /* 01-07: Reserved, must be zero */
+ u8 reserved3[3]; /* 08-31: Reserved, must be zero */
+
+ u8 local_sapic_eid;
+ u8 proximity_domain_hi[3];
+ u32 reserved4; /* Reserved, must be zero */
+};
+
+struct memory_affinity {
+ SRAT_SUBTABLE_HEADER u32 proximity_domain;
+ u16 reserved3;
+ u64 base_address;
+ u64 address_length;
+ u32 reserved4;
/* Flags (32 bits) */
- u8 wb_invd:1; /* 00: The wbinvd instruction works properly */
- u8 wb_invd_flush:1; /* 01: The wbinvd flushes but does not invalidate */
- u8 proc_c1:1; /* 02: All processors support C1 state */
- u8 plvl2_up:1; /* 03: C2 state works on MP system */
- u8 pwr_button:1; /* 04: Power button is handled as a generic feature */
- u8 sleep_button:1; /* 05: Sleep button is handled as a generic feature, or not present */
- u8 fixed_rTC:1; /* 06: RTC wakeup stat not in fixed register space */
- u8 rtcs4:1; /* 07: RTC wakeup stat not possible from S4 */
- u8 tmr_val_ext:1; /* 08: tmr_val width is 32 bits (0 = 24 bits) */
- u8:7; /* 09-15: Reserved, must be zero */
- u8 reserved5[2]; /* 16-31: Reserved, must be zero */
+ u8 enabled:1; /* 00: Use affinity structure */
+ u8 hot_pluggable:1; /* 01: Memory region is hot pluggable */
+ u8 non_volatile:1; /* 02: Memory is non-volatile */
+ u8:5; /* 03-07: Reserved, must be zero */
+ u8 reserved5[3]; /* 08-31: Reserved, must be zero */
+
+ u64 reserved6; /* Reserved, must be zero */
+};
+
+/*******************************************************************************
+ *
+ * TCPA - Trusted Computing Platform Alliance table
+ *
+ ******************************************************************************/
+
+struct acpi_table_tcpa {
+ ACPI_TABLE_HEADER_DEF u16 reserved;
+ u32 max_log_length; /* Maximum length for the event log area */
+ u64 log_address; /* Address of the event log area */
};
+/*******************************************************************************
+ *
+ * WDRT - Watchdog Resource Table
+ *
+ ******************************************************************************/
+
+struct acpi_table_wdrt {
+ ACPI_TABLE_HEADER_DEF u32 header_length; /* Watchdog Header Length */
+ u8 pci_segment; /* PCI Segment number */
+ u8 pci_bus; /* PCI Bus number */
+ u8 pci_device; /* PCI Device number */
+ u8 pci_function; /* PCI Function number */
+ u32 timer_period; /* Period of one timer count (msec) */
+ u32 max_count; /* Maximum counter value supported */
+ u32 min_count; /* Minimum counter value */
+ u8 flags;
+ u8 reserved[3];
+ u32 entries; /* Number of watchdog entries that follow */
+};
+
+#if 0 /* Flags, will be converted to macros */
+u8 enabled:1; /* 00: Timer enabled */
+u8:6; /* 01-06: Reserved */
+u8 sleep_stop:1; /* 07: Timer stopped in sleep state */
+#endif
+
+/* Macros used to generate offsets to specific table fields */
+
+#define ACPI_ASF0_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_info,f)
+#define ACPI_ASF1_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_alert,f)
+#define ACPI_ASF2_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_remote,f)
+#define ACPI_ASF3_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_rmcp,f)
+#define ACPI_ASF4_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_address,f)
+#define ACPI_BOOT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_boot,f)
+#define ACPI_CPEP_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_cpep,f)
+#define ACPI_CPEP0_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_cpep_polling,f)
+#define ACPI_DBGP_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_dbgp,f)
+#define ACPI_ECDT_OFFSET(f) (u8) ACPI_OFFSET (struct ec_boot_resources,f)
+#define ACPI_HPET_OFFSET(f) (u8) ACPI_OFFSET (struct hpet_table,f)
+#define ACPI_MADT_OFFSET(f) (u8) ACPI_OFFSET (struct multiple_apic_table,f)
+#define ACPI_MADT0_OFFSET(f) (u8) ACPI_OFFSET (struct madt_processor_apic,f)
+#define ACPI_MADT1_OFFSET(f) (u8) ACPI_OFFSET (struct madt_io_apic,f)
+#define ACPI_MADT2_OFFSET(f) (u8) ACPI_OFFSET (struct madt_interrupt_override,f)
+#define ACPI_MADT3_OFFSET(f) (u8) ACPI_OFFSET (struct madt_nmi_source,f)
+#define ACPI_MADT4_OFFSET(f) (u8) ACPI_OFFSET (struct madt_local_apic_nmi,f)
+#define ACPI_MADT5_OFFSET(f) (u8) ACPI_OFFSET (struct madt_address_override,f)
+#define ACPI_MADT6_OFFSET(f) (u8) ACPI_OFFSET (struct madt_io_sapic,f)
+#define ACPI_MADT7_OFFSET(f) (u8) ACPI_OFFSET (struct madt_local_sapic,f)
+#define ACPI_MADT8_OFFSET(f) (u8) ACPI_OFFSET (struct madt_interrupt_source,f)
+#define ACPI_MADTH_OFFSET(f) (u8) ACPI_OFFSET (struct apic_header,f)
+#define ACPI_MCFG_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_mcfg,f)
+#define ACPI_MCFG0_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_mcfg_allocation,f)
+#define ACPI_SBST_OFFSET(f) (u8) ACPI_OFFSET (struct smart_battery_table,f)
+#define ACPI_SLIT_OFFSET(f) (u8) ACPI_OFFSET (struct system_locality_info,f)
+#define ACPI_SPCR_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_spcr,f)
+#define ACPI_SPMI_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_spmi,f)
+#define ACPI_SRAT_OFFSET(f) (u8) ACPI_OFFSET (struct system_resource_affinity,f)
+#define ACPI_SRAT0_OFFSET(f) (u8) ACPI_OFFSET (struct static_resource_alloc,f)
+#define ACPI_SRAT1_OFFSET(f) (u8) ACPI_OFFSET (struct memory_affinity,f)
+#define ACPI_TCPA_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_tcpa,f)
+#define ACPI_WDRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_wdrt,f)
+
+#define ACPI_HPET_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct hpet_table,f,o)
+#define ACPI_SRAT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct static_resource_alloc,f,o)
+#define ACPI_SRAT1_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct memory_affinity,f,o)
+#define ACPI_MADT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct multiple_apic_table,f,o)
+#define ACPI_MADT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_processor_apic,f,o)
+#define ACPI_MADT2_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_interrupt_override,f,o)
+#define ACPI_MADT3_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_nmi_source,f,o)
+#define ACPI_MADT4_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_local_apic_nmi,f,o)
+#define ACPI_MADT7_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_local_sapic,f,o)
+#define ACPI_MADT8_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_interrupt_source,f,o)
+
+/* Reset to default packing */
+
#pragma pack()
#endif /* __ACTBL1_H__ */
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index dfc7ac1094b..67efe6cad27 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -44,234 +44,6 @@
#ifndef __ACTBL2_H__
#define __ACTBL2_H__
-/*
- * Prefered Power Management Profiles
- */
-#define PM_UNSPECIFIED 0
-#define PM_DESKTOP 1
-#define PM_MOBILE 2
-#define PM_WORKSTATION 3
-#define PM_ENTERPRISE_SERVER 4
-#define PM_SOHO_SERVER 5
-#define PM_APPLIANCE_PC 6
-
-/*
- * ACPI Boot Arch Flags
- */
-#define BAF_LEGACY_DEVICES 0x0001
-#define BAF_8042_KEYBOARD_CONTROLLER 0x0002
-
-#define FADT2_REVISION_ID 3
-#define FADT2_MINUS_REVISION_ID 2
-
-#pragma pack(1)
-
-/*
- * ACPI 2.0 Root System Description Table (RSDT)
- */
-struct rsdt_descriptor_rev2 {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */
-};
-
-/*
- * ACPI 2.0 Extended System Description Table (XSDT)
- */
-struct xsdt_descriptor_rev2 {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u64 table_offset_entry[1]; /* Array of pointers to ACPI tables */
-};
-
-/*
- * ACPI 2.0 Firmware ACPI Control Structure (FACS)
- */
-struct facs_descriptor_rev2 {
- char signature[4]; /* ASCII table signature */
- u32 length; /* Length of structure, in bytes */
- u32 hardware_signature; /* Hardware configuration signature */
- u32 firmware_waking_vector; /* 32-bit physical address of the Firmware Waking Vector. */
- u32 global_lock; /* Global Lock used to synchronize access to shared hardware resources */
-
- /* Flags (32 bits) */
-
- u8 S4bios_f:1; /* 00: S4BIOS support is present */
- u8:7; /* 01-07: Reserved, must be zero */
- u8 reserved1[3]; /* 08-31: Reserved, must be zero */
-
- u64 xfirmware_waking_vector; /* 64-bit physical address of the Firmware Waking Vector. */
- u8 version; /* Version of this table */
- u8 reserved3[31]; /* Reserved, must be zero */
-};
-
-/*
- * ACPI 2.0+ Generic Address Structure (GAS)
- */
-struct acpi_generic_address {
- u8 address_space_id; /* Address space where struct or register exists. */
- u8 register_bit_width; /* Size in bits of given register */
- u8 register_bit_offset; /* Bit offset within the register */
- u8 access_width; /* Minimum Access size (ACPI 3.0) */
- u64 address; /* 64-bit address of struct or register */
-};
-
-#define FADT_REV2_COMMON \
- u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ \
- u32 V1_dsdt; /* 32-bit physical address of DSDT */ \
- u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ \
- u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ \
- u16 sci_int; /* System vector of SCI interrupt */ \
- u32 smi_cmd; /* Port address of SMI command port */ \
- u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ \
- u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ \
- u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ \
- u8 pstate_cnt; /* Processor performance state control*/ \
- u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ \
- u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ \
- u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ \
- u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ \
- u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ \
- u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ \
- u32 V1_gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ \
- u32 V1_gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ \
- u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ \
- u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ \
- u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ \
- u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ \
- u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ \
- u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ \
- u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ \
- u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ \
- u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ \
- u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ \
- u16 flush_size; /* Number of flush strides that need to be read */ \
- u16 flush_stride; /* Processor's memory cache line width, in bytes */ \
- u8 duty_offset; /* Processor's duty cycle index in processor's P_CNT reg*/ \
- u8 duty_width; /* Processor's duty cycle value bit width in P_CNT register.*/ \
- u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ \
- u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ \
- u8 century; /* Index to century in RTC CMOS RAM */ \
- u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/
-
-/*
- * ACPI 2.0+ Fixed ACPI Description Table (FADT)
- */
-struct fadt_descriptor_rev2 {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- FADT_REV2_COMMON u8 reserved2; /* Reserved, must be zero */
-
- /* Flags (32 bits) */
-
- u8 wb_invd:1; /* 00: The wbinvd instruction works properly */
- u8 wb_invd_flush:1; /* 01: The wbinvd flushes but does not invalidate */
- u8 proc_c1:1; /* 02: All processors support C1 state */
- u8 plvl2_up:1; /* 03: C2 state works on MP system */
- u8 pwr_button:1; /* 04: Power button is handled as a generic feature */
- u8 sleep_button:1; /* 05: Sleep button is handled as a generic feature, or not present */
- u8 fixed_rTC:1; /* 06: RTC wakeup stat not in fixed register space */
- u8 rtcs4:1; /* 07: RTC wakeup stat not possible from S4 */
- u8 tmr_val_ext:1; /* 08: tmr_val is 32 bits 0=24-bits */
- u8 dock_cap:1; /* 09: Docking supported */
- u8 reset_reg_sup:1; /* 10: System reset via the FADT RESET_REG supported */
- u8 sealed_case:1; /* 11: No internal expansion capabilities and case is sealed */
- u8 headless:1; /* 12: No local video capabilities or local input devices */
- u8 cpu_sw_sleep:1; /* 13: Must execute native instruction after writing SLP_TYPx register */
-
- u8 pci_exp_wak:1; /* 14: System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */
- u8 use_platform_clock:1; /* 15: OSPM should use platform-provided timer (ACPI 3.0) */
- u8 S4rtc_sts_valid:1; /* 16: Contents of RTC_STS valid after S4 wake (ACPI 3.0) */
- u8 remote_power_on_capable:1; /* 17: System is compatible with remote power on (ACPI 3.0) */
- u8 force_apic_cluster_model:1; /* 18: All local APICs must use cluster model (ACPI 3.0) */
- u8 force_apic_physical_destination_mode:1; /* 19: all local x_aPICs must use physical dest mode (ACPI 3.0) */
- u8:4; /* 20-23: Reserved, must be zero */
- u8 reserved3; /* 24-31: Reserved, must be zero */
-
- struct acpi_generic_address reset_register; /* Reset register address in GAS format */
- u8 reset_value; /* Value to write to the reset_register port to reset the system */
- u8 reserved4[3]; /* These three bytes must be zero */
- u64 xfirmware_ctrl; /* 64-bit physical address of FACS */
- u64 Xdsdt; /* 64-bit physical address of DSDT */
- struct acpi_generic_address xpm1a_evt_blk; /* Extended Power Mgt 1a acpi_event Reg Blk address */
- struct acpi_generic_address xpm1b_evt_blk; /* Extended Power Mgt 1b acpi_event Reg Blk address */
- struct acpi_generic_address xpm1a_cnt_blk; /* Extended Power Mgt 1a Control Reg Blk address */
- struct acpi_generic_address xpm1b_cnt_blk; /* Extended Power Mgt 1b Control Reg Blk address */
- struct acpi_generic_address xpm2_cnt_blk; /* Extended Power Mgt 2 Control Reg Blk address */
- struct acpi_generic_address xpm_tmr_blk; /* Extended Power Mgt Timer Ctrl Reg Blk address */
- struct acpi_generic_address xgpe0_blk; /* Extended General Purpose acpi_event 0 Reg Blk address */
- struct acpi_generic_address xgpe1_blk; /* Extended General Purpose acpi_event 1 Reg Blk address */
-};
-
-/* "Down-revved" ACPI 2.0 FADT descriptor */
-
-struct fadt_descriptor_rev2_minus {
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- FADT_REV2_COMMON u8 reserved2; /* Reserved, must be zero */
- u32 flags;
- struct acpi_generic_address reset_register; /* Reset register address in GAS format */
- u8 reset_value; /* Value to write to the reset_register port to reset the system. */
- u8 reserved7[3]; /* Reserved, must be zero */
-};
-
-/* ECDT - Embedded Controller Boot Resources Table */
-
-struct ec_boot_resources {
- ACPI_TABLE_HEADER_DEF struct acpi_generic_address ec_control; /* Address of EC command/status register */
- struct acpi_generic_address ec_data; /* Address of EC data register */
- u32 uid; /* Unique ID - must be same as the EC _UID method */
- u8 gpe_bit; /* The GPE for the EC */
- u8 ec_id[1]; /* Full namepath of the EC in the ACPI namespace */
-};
-
-/* SRAT - System Resource Affinity Table */
-
-struct static_resource_alloc {
- u8 type;
- u8 length;
- u8 proximity_domain_lo;
- u8 apic_id;
-
- /* Flags (32 bits) */
-
- u8 enabled:1; /* 00: Use affinity structure */
- u8:7; /* 01-07: Reserved, must be zero */
- u8 reserved3[3]; /* 08-31: Reserved, must be zero */
-
- u8 local_sapic_eid;
- u8 proximity_domain_hi[3];
- u32 reserved4; /* Reserved, must be zero */
-};
-
-struct memory_affinity {
- u8 type;
- u8 length;
- u32 proximity_domain;
- u16 reserved3;
- u64 base_address;
- u64 address_length;
- u32 reserved4;
-
- /* Flags (32 bits) */
-
- u8 enabled:1; /* 00: Use affinity structure */
- u8 hot_pluggable:1; /* 01: Memory region is hot pluggable */
- u8 non_volatile:1; /* 02: Memory is non-volatile */
- u8:5; /* 03-07: Reserved, must be zero */
- u8 reserved5[3]; /* 08-31: Reserved, must be zero */
-
- u64 reserved6; /* Reserved, must be zero */
-};
-
-struct system_resource_affinity {
- ACPI_TABLE_HEADER_DEF u32 reserved1; /* Must be value '1' */
- u64 reserved2; /* Reserved, must be zero */
-};
-
-/* SLIT - System Locality Distance Information Table */
-
-struct system_locality_info {
- ACPI_TABLE_HEADER_DEF u64 locality_count;
- u8 entry[1][1];
-};
-
-#pragma pack()
+/* Code moved to both actbl.h and actbl1.h */
#endif /* __ACTBL2_H__ */
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 7ca89cde706..77cf1236b05 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -44,6 +44,8 @@
#ifndef __ACTYPES_H__
#define __ACTYPES_H__
+/* acpisrc:struct_defs -- for acpisrc conversion */
+
/*
* ACPI_MACHINE_WIDTH must be specified in an OS- or compiler-dependent header
* and must be either 16, 32, or 64
@@ -154,7 +156,6 @@ typedef u64 acpi_physical_address;
#define ACPI_MAX_PTR ACPI_UINT64_MAX
#define ACPI_SIZE_MAX ACPI_UINT64_MAX
-#define ALIGNED_ADDRESS_BOUNDARY 0x00000008
#define ACPI_USE_NATIVE_DIVIDE /* Has native 64-bit integer support */
/*
@@ -195,8 +196,6 @@ typedef u64 acpi_physical_address;
#define ACPI_MAX_PTR ACPI_UINT32_MAX
#define ACPI_SIZE_MAX ACPI_UINT32_MAX
-#define ALIGNED_ADDRESS_BOUNDARY 0x00000004
-
/*******************************************************************************
*
* Types specific to 16-bit targets
@@ -223,7 +222,6 @@ typedef char *acpi_physical_address;
#define ACPI_MAX_PTR ACPI_UINT16_MAX
#define ACPI_SIZE_MAX ACPI_UINT16_MAX
-#define ALIGNED_ADDRESS_BOUNDARY 0x00000002
#define ACPI_USE_NATIVE_DIVIDE /* No 64-bit integers, ok to use native divide */
/* 64-bit integers cannot be supported */
@@ -254,7 +252,7 @@ typedef acpi_native_uint acpi_size;
/* Use C99 uintptr_t for pointer casting if available, "void *" otherwise */
#ifndef acpi_uintptr_t
-#define acpi_uintptr_t void *
+#define acpi_uintptr_t void *
#endif
/*
@@ -263,7 +261,7 @@ typedef acpi_native_uint acpi_size;
* manager implementation is to be used (ACPI_USE_LOCAL_CACHE)
*/
#ifndef acpi_cache_t
-#define acpi_cache_t struct acpi_memory_list
+#define acpi_cache_t struct acpi_memory_list
#endif
/*
@@ -271,7 +269,7 @@ typedef acpi_native_uint acpi_size;
* lock and unlock OSL interfaces.
*/
#ifndef acpi_cpu_flags
-#define acpi_cpu_flags acpi_native_uint
+#define acpi_cpu_flags acpi_native_uint
#endif
/*
@@ -292,6 +290,21 @@ typedef acpi_native_uint acpi_size;
#define ACPI_UNUSED_VAR
#endif
+/*
+ * All ACPICA functions that are available to the rest of the kernel are
+ * tagged with this macro which can be defined as appropriate for the host.
+ */
+#ifndef ACPI_EXPORT_SYMBOL
+#define ACPI_EXPORT_SYMBOL(symbol)
+#endif
+
+/*
+ * thread_id is returned by acpi_os_get_thread_id.
+ */
+#ifndef acpi_thread_id
+#define acpi_thread_id acpi_native_uint
+#endif
+
/*******************************************************************************
*
* Independent types
@@ -477,15 +490,15 @@ typedef u64 acpi_integer;
*/
typedef u32 acpi_table_type;
-#define ACPI_TABLE_RSDP (acpi_table_type) 0
-#define ACPI_TABLE_DSDT (acpi_table_type) 1
-#define ACPI_TABLE_FADT (acpi_table_type) 2
-#define ACPI_TABLE_FACS (acpi_table_type) 3
-#define ACPI_TABLE_PSDT (acpi_table_type) 4
-#define ACPI_TABLE_SSDT (acpi_table_type) 5
-#define ACPI_TABLE_XSDT (acpi_table_type) 6
-#define ACPI_TABLE_MAX 6
-#define NUM_ACPI_TABLE_TYPES (ACPI_TABLE_MAX+1)
+#define ACPI_TABLE_ID_RSDP (acpi_table_type) 0
+#define ACPI_TABLE_ID_DSDT (acpi_table_type) 1
+#define ACPI_TABLE_ID_FADT (acpi_table_type) 2
+#define ACPI_TABLE_ID_FACS (acpi_table_type) 3
+#define ACPI_TABLE_ID_PSDT (acpi_table_type) 4
+#define ACPI_TABLE_ID_SSDT (acpi_table_type) 5
+#define ACPI_TABLE_ID_XSDT (acpi_table_type) 6
+#define ACPI_TABLE_ID_MAX 6
+#define ACPI_NUM_TABLE_TYPES (ACPI_TABLE_ID_MAX+1)
/*
* Types associated with ACPI names and objects. The first group of
@@ -816,7 +829,7 @@ struct acpi_system_info {
u32 debug_level;
u32 debug_layer;
u32 num_table_types;
- struct acpi_table_info table_info[NUM_ACPI_TABLE_TYPES];
+ struct acpi_table_info table_info[ACPI_TABLE_ID_MAX + 1];
};
/*
@@ -858,7 +871,7 @@ acpi_status(*acpi_adr_space_handler) (u32 function,
void *handler_context,
void *region_context);
-#define ACPI_DEFAULT_HANDLER NULL
+#define ACPI_DEFAULT_HANDLER NULL
typedef
acpi_status(*acpi_adr_space_setup) (acpi_handle region_handle,
@@ -911,12 +924,13 @@ struct acpi_compatible_id_list {
#define ACPI_STA_DEVICE_PRESENT 0x01
#define ACPI_STA_DEVICE_ENABLED 0x02
#define ACPI_STA_DEVICE_UI 0x04
-#define ACPI_STA_DEVICE_OK 0x08
+#define ACPI_STA_DEVICE_FUNCTIONING 0x08
+#define ACPI_STA_DEVICE_OK 0x08 /* Synonym */
#define ACPI_STA_BATTERY_PRESENT 0x10
#define ACPI_COMMON_OBJ_INFO \
- acpi_object_type type; /* ACPI object type */ \
- acpi_name name /* ACPI object Name */
+ acpi_object_type type; /* ACPI object type */ \
+ acpi_name name /* ACPI object Name */
struct acpi_obj_info_header {
ACPI_COMMON_OBJ_INFO;
@@ -957,7 +971,7 @@ struct acpi_mem_space_context {
* Definitions for Resource Attributes
*/
typedef u16 acpi_rs_length; /* Resource Length field is fixed at 16 bits */
-typedef u32 acpi_rsdesc_size; /* Max Resource Descriptor size is (length+3) = (64_k-1)+3 */
+typedef u32 acpi_rsdesc_size; /* Max Resource Descriptor size is (Length+3) = (64_k-1)+3 */
/*
* Memory Attributes
@@ -972,8 +986,8 @@ typedef u32 acpi_rsdesc_size; /* Max Resource Descriptor size is (length+3) = (6
/*
* IO Attributes
- * The ISA Io ranges are: n000-n0_ffh, n400-n4_ffh, n800-n8_ffh, n_c00-n_cFFh.
- * The non-ISA Io ranges are: n100-n3_ffh, n500-n7_ffh, n900-n_bFfh, n_cd0-n_fFFh.
+ * The ISA IO ranges are: n000-n0_fFh, n400-n4_fFh, n800-n8_fFh, n_c00-n_cFFh.
+ * The non-ISA IO ranges are: n100-n3_fFh, n500-n7_fFh, n900-n_bFFh, n_cd0-n_fFFh.
*/
#define ACPI_NON_ISA_ONLY_RANGES (u8) 0x01
#define ACPI_ISA_ONLY_RANGES (u8) 0x02
@@ -1171,12 +1185,12 @@ struct acpi_resource_source {
/* Fields common to all address descriptors, 16/32/64 bit */
#define ACPI_RESOURCE_ADDRESS_COMMON \
- u8 resource_type; \
- u8 producer_consumer; \
- u8 decode; \
- u8 min_address_fixed; \
- u8 max_address_fixed; \
- union acpi_resource_attribute info;
+ u8 resource_type; \
+ u8 producer_consumer; \
+ u8 decode; \
+ u8 min_address_fixed; \
+ u8 max_address_fixed; \
+ union acpi_resource_attribute info;
struct acpi_resource_address {
ACPI_RESOURCE_ADDRESS_COMMON};
@@ -1297,16 +1311,6 @@ struct acpi_resource {
#define ACPI_NEXT_RESOURCE(res) (struct acpi_resource *)((u8 *) res + res->length)
-#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
-#define ACPI_ALIGN_RESOURCE_SIZE(length) (length)
-#else
-#define ACPI_ALIGN_RESOURCE_SIZE(length) ACPI_ROUND_UP_TO_NATIVE_WORD(length)
-#endif
-
-/*
- * END: of definitions for Resource Attributes
- */
-
struct acpi_pci_routing_table {
u32 length;
u32 pin;
@@ -1315,8 +1319,4 @@ struct acpi_pci_routing_table {
char source[4]; /* pad to 64 bits so sizeof() works in all cases */
};
-/*
- * END: of definitions for PCI Routing tables
- */
-
#endif /* __ACTYPES_H__ */
diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h
index 0927765df6a..ba039ea1a05 100644
--- a/include/acpi/acutils.h
+++ b/include/acpi/acutils.h
@@ -50,24 +50,24 @@ extern const u8 acpi_gbl_resource_aml_sizes[];
#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
-extern const char *acpi_gbl_BMdecode[2];
-extern const char *acpi_gbl_config_decode[4];
-extern const char *acpi_gbl_consume_decode[2];
-extern const char *acpi_gbl_DECdecode[2];
-extern const char *acpi_gbl_HEdecode[2];
-extern const char *acpi_gbl_io_decode[2];
-extern const char *acpi_gbl_LLdecode[2];
-extern const char *acpi_gbl_max_decode[2];
-extern const char *acpi_gbl_MEMdecode[4];
-extern const char *acpi_gbl_min_decode[2];
-extern const char *acpi_gbl_MTPdecode[4];
-extern const char *acpi_gbl_RNGdecode[4];
-extern const char *acpi_gbl_RWdecode[2];
-extern const char *acpi_gbl_SHRdecode[2];
-extern const char *acpi_gbl_SIZdecode[4];
-extern const char *acpi_gbl_TRSdecode[2];
-extern const char *acpi_gbl_TTPdecode[2];
-extern const char *acpi_gbl_TYPdecode[4];
+extern const char *acpi_gbl_bm_decode[];
+extern const char *acpi_gbl_config_decode[];
+extern const char *acpi_gbl_consume_decode[];
+extern const char *acpi_gbl_dec_decode[];
+extern const char *acpi_gbl_he_decode[];
+extern const char *acpi_gbl_io_decode[];
+extern const char *acpi_gbl_ll_decode[];
+extern const char *acpi_gbl_max_decode[];
+extern const char *acpi_gbl_mem_decode[];
+extern const char *acpi_gbl_min_decode[];
+extern const char *acpi_gbl_mtp_decode[];
+extern const char *acpi_gbl_rng_decode[];
+extern const char *acpi_gbl_rw_decode[];
+extern const char *acpi_gbl_shr_decode[];
+extern const char *acpi_gbl_siz_decode[];
+extern const char *acpi_gbl_trs_decode[];
+extern const char *acpi_gbl_ttp_decode[];
+extern const char *acpi_gbl_typ_decode[];
#endif
/* Types for Resource descriptor entries */
@@ -78,6 +78,12 @@ extern const char *acpi_gbl_TYPdecode[4];
#define ACPI_SMALL_VARIABLE_LENGTH 3
typedef
+acpi_status(*acpi_walk_aml_callback) (u8 * aml,
+ u32 length,
+ u32 offset,
+ u8 resource_index, void **context);
+
+typedef
acpi_status(*acpi_pkg_callback) (u8 object_type,
union acpi_operand_object * source_object,
union acpi_generic_state * state,
@@ -277,6 +283,8 @@ acpi_ut_ptr_exit(u32 line_number,
void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id);
+void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display);
+
void acpi_ut_report_error(char *module_name, u32 line_number);
void acpi_ut_report_info(char *module_name, u32 line_number);
@@ -445,6 +453,8 @@ acpi_ut_short_divide(acpi_integer in_dividend,
/*
* utmisc
*/
+u8 acpi_ut_is_aml_table(struct acpi_table_header *table);
+
acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id);
void acpi_ut_release_owner_id(acpi_owner_id * owner_id);
@@ -460,7 +470,9 @@ void acpi_ut_print_string(char *string, u8 max_length);
u8 acpi_ut_valid_acpi_name(u32 name);
-u8 acpi_ut_valid_acpi_character(char character);
+acpi_name acpi_ut_repair_name(acpi_name name);
+
+u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position);
acpi_status
acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer);
@@ -469,6 +481,25 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer);
#define ACPI_ANY_BASE 0
+u32 acpi_ut_dword_byte_swap(u32 value);
+
+void acpi_ut_set_integer_width(u8 revision);
+
+#ifdef ACPI_DEBUG_OUTPUT
+void
+acpi_ut_display_init_pathname(u8 type,
+ struct acpi_namespace_node *obj_handle,
+ char *path);
+#endif
+
+/*
+ * utresrc
+ */
+acpi_status
+acpi_ut_walk_aml_resources(u8 * aml,
+ acpi_size aml_length,
+ acpi_walk_aml_callback user_function, void **context);
+
acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index);
u32 acpi_ut_get_descriptor_length(void *aml);
@@ -483,20 +514,6 @@ acpi_status
acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc,
u8 ** end_tag);
-u8 acpi_ut_generate_checksum(u8 * buffer, u32 length);
-
-u32 acpi_ut_dword_byte_swap(u32 value);
-
-void acpi_ut_set_integer_width(u8 revision);
-
-#ifdef ACPI_DEBUG_OUTPUT
-void
-acpi_ut_display_init_pathname(u8 type,
- struct acpi_namespace_node *obj_handle,
- char *path);
-
-#endif
-
/*
* utmutex - mutex support
*/
@@ -523,14 +540,15 @@ acpi_ut_initialize_buffer(struct acpi_buffer *buffer,
void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line);
-void *acpi_ut_callocate(acpi_size size, u32 component, char *module, u32 line);
+void *acpi_ut_allocate_zeroed(acpi_size size,
+ u32 component, char *module, u32 line);
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
void *acpi_ut_allocate_and_track(acpi_size size,
u32 component, char *module, u32 line);
-void *acpi_ut_callocate_and_track(acpi_size size,
- u32 component, char *module, u32 line);
+void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
+ u32 component, char *module, u32 line);
void
acpi_ut_free_and_track(void *address, u32 component, char *module, u32 line);
@@ -540,6 +558,11 @@ void acpi_ut_dump_allocation_info(void);
#endif /* ACPI_FUTURE_USAGE */
void acpi_ut_dump_allocations(u32 component, char *module);
+
+acpi_status
+acpi_ut_create_list(char *list_name,
+ u16 object_size, struct acpi_memory_list **return_cache);
+
#endif
#endif /* _ACUTILS_H */
diff --git a/include/acpi/amlcode.h b/include/acpi/amlcode.h
index 37964a59aef..cf18426a87b 100644
--- a/include/acpi/amlcode.h
+++ b/include/acpi/amlcode.h
@@ -180,8 +180,10 @@
#define AML_BANK_FIELD_OP (u16) 0x5b87
#define AML_DATA_REGION_OP (u16) 0x5b88 /* ACPI 2.0 */
-/* Bogus opcodes (they are actually two separate opcodes) */
-
+/*
+ * Combination opcodes (actually two one-byte opcodes)
+ * Used by the disassembler and i_aSL compiler
+ */
#define AML_LGREATEREQUAL_OP (u16) 0x9295
#define AML_LLESSEQUAL_OP (u16) 0x9294
#define AML_LNOTEQUAL_OP (u16) 0x9293
diff --git a/include/acpi/amlresrc.h b/include/acpi/amlresrc.h
index fb4735315ad..be03818af9d 100644
--- a/include/acpi/amlresrc.h
+++ b/include/acpi/amlresrc.h
@@ -42,39 +42,45 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
+/* acpisrc:struct_defs -- for acpisrc conversion */
+
#ifndef __AMLRESRC_H
#define __AMLRESRC_H
-#define ASL_RESNAME_ADDRESS "_ADR"
-#define ASL_RESNAME_ALIGNMENT "_ALN"
-#define ASL_RESNAME_ADDRESSSPACE "_ASI"
-#define ASL_RESNAME_ACCESSSIZE "_ASZ"
-#define ASL_RESNAME_TYPESPECIFICATTRIBUTES "_ATT"
-#define ASL_RESNAME_BASEADDRESS "_BAS"
-#define ASL_RESNAME_BUSMASTER "_BM_" /* Master(1), Slave(0) */
-#define ASL_RESNAME_DECODE "_DEC"
-#define ASL_RESNAME_DMA "_DMA"
-#define ASL_RESNAME_DMATYPE "_TYP" /* Compatible(0), A(1), B(2), F(3) */
-#define ASL_RESNAME_GRANULARITY "_GRA"
-#define ASL_RESNAME_INTERRUPT "_INT"
-#define ASL_RESNAME_INTERRUPTLEVEL "_LL_" /* active_lo(1), active_hi(0) */
-#define ASL_RESNAME_INTERRUPTSHARE "_SHR" /* Shareable(1), no_share(0) */
-#define ASL_RESNAME_INTERRUPTTYPE "_HE_" /* Edge(1), Level(0) */
-#define ASL_RESNAME_LENGTH "_LEN"
-#define ASL_RESNAME_MEMATTRIBUTES "_MTP" /* Memory(0), Reserved(1), ACPI(2), NVS(3) */
-#define ASL_RESNAME_MEMTYPE "_MEM" /* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */
-#define ASL_RESNAME_MAXADDR "_MAX"
-#define ASL_RESNAME_MINADDR "_MIN"
-#define ASL_RESNAME_MAXTYPE "_MAF"
-#define ASL_RESNAME_MINTYPE "_MIF"
-#define ASL_RESNAME_REGISTERBITOFFSET "_RBO"
-#define ASL_RESNAME_REGISTERBITWIDTH "_RBW"
-#define ASL_RESNAME_RANGETYPE "_RNG"
-#define ASL_RESNAME_READWRITETYPE "_RW_" /* read_only(0), Writeable (1) */
-#define ASL_RESNAME_TRANSLATION "_TRA"
-#define ASL_RESNAME_TRANSTYPE "_TRS" /* Sparse(1), Dense(0) */
-#define ASL_RESNAME_TYPE "_TTP" /* Translation(1), Static (0) */
-#define ASL_RESNAME_XFERTYPE "_SIz" /* 8(0), 8_and16(1), 16(2) */
+/*
+ * Resource descriptor tags, as defined in the ACPI specification.
+ * Used to symbolically reference fields within a descriptor.
+ */
+#define ACPI_RESTAG_ADDRESS "_ADR"
+#define ACPI_RESTAG_ALIGNMENT "_ALN"
+#define ACPI_RESTAG_ADDRESSSPACE "_ASI"
+#define ACPI_RESTAG_ACCESSSIZE "_ASZ"
+#define ACPI_RESTAG_TYPESPECIFICATTRIBUTES "_ATT"
+#define ACPI_RESTAG_BASEADDRESS "_BAS"
+#define ACPI_RESTAG_BUSMASTER "_BM_" /* Master(1), Slave(0) */
+#define ACPI_RESTAG_DECODE "_DEC"
+#define ACPI_RESTAG_DMA "_DMA"
+#define ACPI_RESTAG_DMATYPE "_TYP" /* Compatible(0), A(1), B(2), F(3) */
+#define ACPI_RESTAG_GRANULARITY "_GRA"
+#define ACPI_RESTAG_INTERRUPT "_INT"
+#define ACPI_RESTAG_INTERRUPTLEVEL "_LL_" /* active_lo(1), active_hi(0) */
+#define ACPI_RESTAG_INTERRUPTSHARE "_SHR" /* Shareable(1), no_share(0) */
+#define ACPI_RESTAG_INTERRUPTTYPE "_HE_" /* Edge(1), Level(0) */
+#define ACPI_RESTAG_LENGTH "_LEN"
+#define ACPI_RESTAG_MEMATTRIBUTES "_MTP" /* Memory(0), Reserved(1), ACPI(2), NVS(3) */
+#define ACPI_RESTAG_MEMTYPE "_MEM" /* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */
+#define ACPI_RESTAG_MAXADDR "_MAX"
+#define ACPI_RESTAG_MINADDR "_MIN"
+#define ACPI_RESTAG_MAXTYPE "_MAF"
+#define ACPI_RESTAG_MINTYPE "_MIF"
+#define ACPI_RESTAG_REGISTERBITOFFSET "_RBO"
+#define ACPI_RESTAG_REGISTERBITWIDTH "_RBW"
+#define ACPI_RESTAG_RANGETYPE "_RNG"
+#define ACPI_RESTAG_READWRITETYPE "_RW_" /* read_only(0), Writeable (1) */
+#define ACPI_RESTAG_TRANSLATION "_TRA"
+#define ACPI_RESTAG_TRANSTYPE "_TRS" /* Sparse(1), Dense(0) */
+#define ACPI_RESTAG_TYPE "_TTP" /* Translation(1), Static (0) */
+#define ACPI_RESTAG_XFERTYPE "_SIZ" /* 8(0), 8_and16(1), 16(2) */
/* Default sizes for "small" resource descriptors */
@@ -109,7 +115,7 @@ struct asl_resource_node {
* SMALL descriptors
*/
#define AML_RESOURCE_SMALL_HEADER_COMMON \
- u8 descriptor_type;
+ u8 descriptor_type;
struct aml_resource_small_header {
AML_RESOURCE_SMALL_HEADER_COMMON};
@@ -162,8 +168,8 @@ struct aml_resource_end_tag {
* LARGE descriptors
*/
#define AML_RESOURCE_LARGE_HEADER_COMMON \
- u8 descriptor_type;\
- u16 resource_length;
+ u8 descriptor_type;\
+ u16 resource_length;
struct aml_resource_large_header {
AML_RESOURCE_LARGE_HEADER_COMMON};
@@ -194,9 +200,9 @@ struct aml_resource_fixed_memory32 {
};
#define AML_RESOURCE_ADDRESS_COMMON \
- u8 resource_type; \
- u8 flags; \
- u8 specific_flags;
+ u8 resource_type; \
+ u8 flags; \
+ u8 specific_flags;
struct aml_resource_address {
AML_RESOURCE_LARGE_HEADER_COMMON AML_RESOURCE_ADDRESS_COMMON};
@@ -266,6 +272,7 @@ struct aml_resource_generic_register {
union aml_resource {
/* Descriptor headers */
+ u8 descriptor_type;
struct aml_resource_small_header small_header;
struct aml_resource_large_header large_header;
@@ -296,9 +303,9 @@ union aml_resource {
/* Utility overlays */
struct aml_resource_address address;
- u32 u32_item;
- u16 u16_item;
- u8 U8item;
+ u32 dword_item;
+ u16 word_item;
+ u8 byte_item;
};
#endif
diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
index 223ec646710..453a469fd39 100644
--- a/include/acpi/platform/acenv.h
+++ b/include/acpi/platform/acenv.h
@@ -49,33 +49,41 @@
*/
#ifdef ACPI_LIBRARY
+/*
+ * Note: The non-debug version of the acpi_library does not contain any
+ * debug support, for minimimal size. The debug version uses ACPI_FULL_DEBUG
+ */
#define ACPI_USE_LOCAL_CACHE
#endif
-#ifdef ACPI_DUMP_APP
-#ifndef MSDOS
+#ifdef ACPI_ASL_COMPILER
#define ACPI_DEBUG_OUTPUT
-#endif
#define ACPI_APPLICATION
#define ACPI_DISASSEMBLER
-#define ACPI_NO_METHOD_EXECUTION
+#define ACPI_CONSTANT_EVAL_ONLY
+#define ACPI_LARGE_NAMESPACE_NODE
+#define ACPI_DATA_TABLE_DISASSEMBLY
#endif
#ifdef ACPI_EXEC_APP
#undef DEBUGGER_THREADING
#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED
-#define ACPI_DEBUG_OUTPUT
+#define ACPI_FULL_DEBUG
#define ACPI_APPLICATION
#define ACPI_DEBUGGER
-#define ACPI_DISASSEMBLER
#define ACPI_MUTEX_DEBUG
+#define ACPI_DBG_TRACK_ALLOCATIONS
#endif
-#ifdef ACPI_ASL_COMPILER
+#ifdef ACPI_DASM_APP
+#ifndef MSDOS
#define ACPI_DEBUG_OUTPUT
+#endif
#define ACPI_APPLICATION
#define ACPI_DISASSEMBLER
-#define ACPI_CONSTANT_EVAL_ONLY
+#define ACPI_NO_METHOD_EXECUTION
+#define ACPI_LARGE_NAMESPACE_NODE
+#define ACPI_DATA_TABLE_DISASSEMBLY
#endif
#ifdef ACPI_APPLICATION
@@ -83,6 +91,12 @@
#define ACPI_USE_LOCAL_CACHE
#endif
+#ifdef ACPI_FULL_DEBUG
+#define ACPI_DEBUGGER
+#define ACPI_DEBUG_OUTPUT
+#define ACPI_DISASSEMBLER
+#endif
+
/*
* Environment configuration. The purpose of this file is to interface to the
* local generation environment.
@@ -137,7 +151,7 @@
#elif defined(MSDOS) /* Must appear after WIN32 and WIN64 check */
#include "acdos16.h"
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include "acfreebsd.h"
#elif defined(__NetBSD__)
@@ -163,17 +177,6 @@
#endif
-/*
- * Memory allocation tracking. Used only if
- * 1) This is the debug version
- * 2) This is NOT a 16-bit version of the code (not enough real-mode memory)
- */
-#ifdef ACPI_DEBUG_OUTPUT
-#if ACPI_MACHINE_WIDTH != 16
-#define ACPI_DBG_TRACK_ALLOCATIONS
-#endif
-#endif
-
/*! [End] no source code translation !*/
/*
@@ -271,8 +274,8 @@ typedef char *va_list;
/*
* Storage alignment properties
*/
-#define _AUPBND (sizeof (acpi_native_uint) - 1)
-#define _ADNBND (sizeof (acpi_native_uint) - 1)
+#define _AUPBND (sizeof (acpi_native_int) - 1)
+#define _ADNBND (sizeof (acpi_native_int) - 1)
/*
* Variable argument list macro definitions
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 2e6d54569ee..b5655a665ba 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -52,27 +52,22 @@
#include <linux/config.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/ctype.h>
#include <asm/system.h>
#include <asm/atomic.h>
#include <asm/div64.h>
#include <asm/acpi.h>
+#include <linux/slab.h>
-#define strtoul simple_strtoul
-
-#define ACPI_MACHINE_WIDTH BITS_PER_LONG
+/* Host-dependent types and defines */
-/* Type(s) for the OSL */
-
-#ifdef ACPI_USE_LOCAL_CACHE
-#define acpi_cache_t struct acpi_memory_list
-#else
-#include <linux/slab.h>
-#define acpi_cache_t kmem_cache_t
-#endif
+#define ACPI_MACHINE_WIDTH BITS_PER_LONG
+#define acpi_cache_t kmem_cache_t
+#define ACPI_EXPORT_SYMBOL(symbol) EXPORT_SYMBOL(symbol);
+#define strtoul simple_strtoul
/* Full namespace pathname length limit - arbitrary */
-
#define ACPI_PATHNAME_MAX 256
#else /* !__KERNEL__ */
@@ -104,4 +99,8 @@
#define acpi_cpu_flags unsigned long
+#define acpi_thread_id u32
+
+static inline acpi_thread_id acpi_os_get_thread_id(void) { return 0; }
+
#endif /* __ACLINUX_H__ */
diff --git a/include/asm-alpha/mmzone.h b/include/asm-alpha/mmzone.h
index a011ef4cf3d..192d80c875b 100644
--- a/include/asm-alpha/mmzone.h
+++ b/include/asm-alpha/mmzone.h
@@ -59,9 +59,6 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
#define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr))
#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
-#define local_mapnr(kvaddr) \
- ((__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)))
-
/*
* Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory
* and returns the kaddr corresponding to first physical page in the
@@ -86,8 +83,7 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
pte_t pte; \
unsigned long pfn; \
\
- pfn = ((unsigned long)((page)-page_zone(page)->zone_mem_map)) << 32; \
- pfn += page_zone(page)->zone_start_pfn << 32; \
+ pfn = page_to_pfn(page) << 32; \
pte_val(pte) = pfn | pgprot_val(pgprot); \
\
pte; \
@@ -104,19 +100,8 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
__xx; \
})
-#define pfn_to_page(pfn) \
-({ \
- unsigned long kaddr = (unsigned long)__va((pfn) << PAGE_SHIFT); \
- (NODE_DATA(kvaddr_to_nid(kaddr))->node_mem_map + local_mapnr(kaddr)); \
-})
-
-#define page_to_pfn(page) \
- ((page) - page_zone(page)->zone_mem_map + \
- (page_zone(page)->zone_start_pfn))
-
#define page_to_pa(page) \
- ((( (page) - page_zone(page)->zone_mem_map ) \
- + page_zone(page)->zone_start_pfn) << PAGE_SHIFT)
+ (page_to_pfn(page) << PAGE_SHIFT)
#define pfn_to_nid(pfn) pa_to_nid(((u64)(pfn) << PAGE_SHIFT))
#define pfn_valid(pfn) \
diff --git a/include/asm-alpha/numnodes.h b/include/asm-alpha/numnodes.h
deleted file mode 100644
index cd425827e4f..00000000000
--- a/include/asm-alpha/numnodes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-/* Max 128 Nodes - Marvel */
-#define NODES_SHIFT 7
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h
index fa0b41b164a..61bcf70b5ea 100644
--- a/include/asm-alpha/page.h
+++ b/include/asm-alpha/page.h
@@ -85,8 +85,6 @@ typedef unsigned long pgprot_t;
#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
#ifndef CONFIG_DISCONTIGMEM
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_valid(pfn) ((pfn) < max_mapnr)
@@ -95,9 +93,9 @@ typedef unsigned long pgprot_t;
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _ALPHA_PAGE_H */
diff --git a/include/asm-alpha/poll.h b/include/asm-alpha/poll.h
index 95707182b3e..76f89356b6a 100644
--- a/include/asm-alpha/poll.h
+++ b/include/asm-alpha/poll.h
@@ -12,8 +12,8 @@
#define POLLWRNORM (1 << 8)
#define POLLWRBAND (1 << 9)
#define POLLMSG (1 << 10)
-#define POLLREMOVE (1 << 11)
-#define POLLRDHUP (1 << 12)
+#define POLLREMOVE (1 << 12)
+#define POLLRDHUP (1 << 13)
struct pollfd {
diff --git a/include/asm-alpha/smp.h b/include/asm-alpha/smp.h
index 9950706abdf..e1432102be0 100644
--- a/include/asm-alpha/smp.h
+++ b/include/asm-alpha/smp.h
@@ -45,10 +45,8 @@ extern struct cpuinfo_alpha cpu_data[NR_CPUS];
#define hard_smp_processor_id() __hard_smp_processor_id()
#define raw_smp_processor_id() (current_thread_info()->cpu)
-extern cpumask_t cpu_present_mask;
-extern cpumask_t cpu_online_map;
extern int smp_num_cpus;
-#define cpu_possible_map cpu_present_mask
+#define cpu_possible_map cpu_present_map
int smp_call_function_on_cpu(void (*func) (void *info), void *info,int retry, int wait, cpumask_t cpu);
diff --git a/include/asm-alpha/termbits.h b/include/asm-alpha/termbits.h
index f4837fa2942..5541101b58a 100644
--- a/include/asm-alpha/termbits.h
+++ b/include/asm-alpha/termbits.h
@@ -148,6 +148,7 @@ struct termios {
#define HUPCL 00040000
#define CLOCAL 00100000
+#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
diff --git a/include/asm-arm/arch-aaec2000/debug-macro.S b/include/asm-arm/arch-aaec2000/debug-macro.S
index e4f1fa539a7..7b1fce021d8 100644
--- a/include/asm-arm/arch-aaec2000/debug-macro.S
+++ b/include/asm-arm/arch-aaec2000/debug-macro.S
@@ -9,6 +9,7 @@
* published by the Free Software Foundation.
*/
+#include "hardware.h"
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
diff --git a/include/asm-arm/arch-aaec2000/entry-macro.S b/include/asm-arm/arch-aaec2000/entry-macro.S
index df31313ab07..1eb3503bd16 100644
--- a/include/asm-arm/arch-aaec2000/entry-macro.S
+++ b/include/asm-arm/arch-aaec2000/entry-macro.S
@@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*
*/
+#include <asm/arch/irqs.h>
.macro disable_fiq
.endm
diff --git a/include/asm-arm/arch-aaec2000/uncompress.h b/include/asm-arm/arch-aaec2000/uncompress.h
index fff0c94b75c..300f4bf3bc7 100644
--- a/include/asm-arm/arch-aaec2000/uncompress.h
+++ b/include/asm-arm/arch-aaec2000/uncompress.h
@@ -15,7 +15,7 @@
#define UART(x) (*(volatile unsigned long *)(serial_port + (x)))
-static void putstr( const char *s )
+static void putc(int c)
{
unsigned long serial_port;
do {
@@ -28,17 +28,16 @@ static void putstr( const char *s )
return;
} while (0);
- for (; *s; s++) {
- /* wait for space in the UART's transmitter */
- while ((UART(UART_SR) & UART_SR_TxFF));
- /* send the character out. */
- UART(UART_DR) = *s;
- /* if a LF, also do CR... */
- if (*s == 10) {
- while ((UART(UART_SR) & UART_SR_TxFF));
- UART(UART_DR) = 13;
- }
- }
+ /* wait for space in the UART's transmitter */
+ while ((UART(UART_SR) & UART_SR_TxFF))
+ barrier();
+
+ /* send the character out. */
+ UART(UART_DR) = c;
+}
+
+static inline void flush(void)
+{
}
#define arch_decomp_setup()
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h b/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
new file mode 100644
index 00000000000..f28636d61e3
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
@@ -0,0 +1,104 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * MultiMedia Card Interface (MCI) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91RM9200_MCI_H
+#define AT91RM9200_MCI_H
+
+#define AT91_MCI_CR 0x00 /* Control Register */
+#define AT91_MCI_MCIEN (1 << 0) /* Multi-Media Interface Enable */
+#define AT91_MCI_MCIDIS (1 << 1) /* Multi-Media Interface Disable */
+#define AT91_MCI_PWSEN (1 << 2) /* Power Save Mode Enable */
+#define AT91_MCI_PWSDIS (1 << 3) /* Power Save Mode Disable */
+#define AT91_MCI_SWRST (1 << 7) /* Software Reset */
+
+#define AT91_MCI_MR 0x04 /* Mode Register */
+#define AT91_MCI_CLKDIV (0xff << 0) /* Clock Divider */
+#define AT91_MCI_PWSDIV (3 << 8) /* Power Saving Divider */
+#define AT91_MCI_PDCPADV (1 << 14) /* PDC Padding Value */
+#define AT91_MCI_PDCMODE (1 << 15) /* PDC-orientated Mode */
+#define AT91_MCI_BLKLEN (0xfff << 18) /* Data Block Length */
+
+#define AT91_MCI_DTOR 0x08 /* Data Timeout Register */
+#define AT91_MCI_DTOCYC (0xf << 0) /* Data Timeout Cycle Number */
+#define AT91_MCI_DTOMUL (7 << 4) /* Data Timeout Multiplier */
+#define AT91_MCI_DTOMUL_1 (0 << 4)
+#define AT91_MCI_DTOMUL_16 (1 << 4)
+#define AT91_MCI_DTOMUL_128 (2 << 4)
+#define AT91_MCI_DTOMUL_256 (3 << 4)
+#define AT91_MCI_DTOMUL_1K (4 << 4)
+#define AT91_MCI_DTOMUL_4K (5 << 4)
+#define AT91_MCI_DTOMUL_64K (6 << 4)
+#define AT91_MCI_DTOMUL_1M (7 << 4)
+
+#define AT91_MCI_SDCR 0x0c /* SD Card Register */
+#define AT91_MCI_SDCSEL (0xf << 0) /* SD Card Selector */
+#define AT91_MCI_SDCBUS (1 << 7) /* 1-bit or 4-bit bus */
+
+#define AT91_MCI_ARGR 0x10 /* Argument Register */
+
+#define AT91_MCI_CMDR 0x14 /* Command Register */
+#define AT91_MCI_CMDNB (0x3f << 0) /* Command Number */
+#define AT91_MCI_RSPTYP (3 << 6) /* Response Type */
+#define AT91_MCI_RSPTYP_NONE (0 << 6)
+#define AT91_MCI_RSPTYP_48 (1 << 6)
+#define AT91_MCI_RSPTYP_136 (2 << 6)
+#define AT91_MCI_SPCMD (7 << 8) /* Special Command */
+#define AT91_MCI_SPCMD_NONE (0 << 8)
+#define AT91_MCI_SPCMD_INIT (1 << 8)
+#define AT91_MCI_SPCMD_SYNC (2 << 8)
+#define AT91_MCI_SPCMD_ICMD (4 << 8)
+#define AT91_MCI_SPCMD_IRESP (5 << 8)
+#define AT91_MCI_OPDCMD (1 << 11) /* Open Drain Command */
+#define AT91_MCI_MAXLAT (1 << 12) /* Max Latency for Command to Response */
+#define AT91_MCI_TRCMD (3 << 16) /* Transfer Command */
+#define AT91_MCI_TRCMD_NONE (0 << 16)
+#define AT91_MCI_TRCMD_START (1 << 16)
+#define AT91_MCI_TRCMD_STOP (2 << 16)
+#define AT91_MCI_TRDIR (1 << 18) /* Transfer Direction */
+#define AT91_MCI_TRTYP (3 << 19) /* Transfer Type */
+#define AT91_MCI_TRTYP_BLOCK (0 << 19)
+#define AT91_MCI_TRTYP_MULTIPLE (1 << 19)
+#define AT91_MCI_TRTYP_STREAM (2 << 19)
+
+#define AT91_MCI_RSPR(n) (0x20 + ((n) * 4)) /* Response Registers 0-3 */
+#define AT91_MCR_RDR 0x30 /* Receive Data Register */
+#define AT91_MCR_TDR 0x34 /* Transmit Data Register */
+
+#define AT91_MCI_SR 0x40 /* Status Register */
+#define AT91_MCI_CMDRDY (1 << 0) /* Command Ready */
+#define AT91_MCI_RXRDY (1 << 1) /* Receiver Ready */
+#define AT91_MCI_TXRDY (1 << 2) /* Transmit Ready */
+#define AT91_MCI_BLKE (1 << 3) /* Data Block Ended */
+#define AT91_MCI_DTIP (1 << 4) /* Data Transfer in Progress */
+#define AT91_MCI_NOTBUSY (1 << 5) /* Data Not Busy */
+#define AT91_MCI_ENDRX (1 << 6) /* End of RX Buffer */
+#define AT91_MCI_ENDTX (1 << 7) /* End fo TX Buffer */
+#define AT91_MCI_RXBUFF (1 << 14) /* RX Buffer Full */
+#define AT91_MCI_TXBUFE (1 << 15) /* TX Buffer Empty */
+#define AT91_MCI_RINDE (1 << 16) /* Response Index Error */
+#define AT91_MCI_RDIRE (1 << 17) /* Response Direction Error */
+#define AT91_MCI_RCRCE (1 << 18) /* Response CRC Error */
+#define AT91_MCI_RENDE (1 << 19) /* Response End Bit Error */
+#define AT91_MCI_RTOE (1 << 20) /* Reponse Time-out Error */
+#define AT91_MCI_DCRCE (1 << 21) /* Data CRC Error */
+#define AT91_MCI_DTOE (1 << 22) /* Data Time-out Error */
+#define AT91_MCI_OVRE (1 << 30) /* Overrun */
+#define AT91_MCI_UNRE (1 << 31) /* Underrun */
+
+#define AT91_MCI_IER 0x44 /* Interrupt Enable Register */
+#define AT91_MCI_IDR 0x48 /* Interrupt Disable Register */
+#define AT91_MCI_IMR 0x4c /* Interrupt Mask Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91rm9200/board.h
index 2e7d1139a79..4fdef13d01d 100644
--- a/include/asm-arm/arch-at91rm9200/board.h
+++ b/include/asm-arm/arch-at91rm9200/board.h
@@ -38,6 +38,8 @@ extern unsigned long at91_master_clock;
extern int at91_serial_map[AT91_NR_UART];
extern int at91_console_port;
+#include <linux/mtd/partitions.h>
+
/* USB Device */
struct at91_udc_data {
u8 vbus_pin; /* high == host powering us */
@@ -77,4 +79,26 @@ struct at91_usbh_data {
};
extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
+ /* NAND / SmartMedia */
+struct at91_nand_data {
+ u8 enable_pin; /* chip enable */
+ u8 det_pin; /* card detect */
+ u8 rdy_pin; /* ready/busy */
+ u8 ale; /* address line number connected to ALE */
+ u8 cle; /* address line number connected to CLE */
+ struct mtd_partition* (*partition_info)(int, int*);
+};
+extern void __init at91_add_device_nand(struct at91_nand_data *data);
+
+ /* I2C*/
+void __init at91_add_device_i2c(void);
+
+ /* RTC */
+void __init at91_add_device_rtc(void);
+
+ /* LEDs */
+extern u8 at91_leds_cpu;
+extern u8 at91_leds_timer;
+extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
+
#endif
diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91rm9200/hardware.h
index 2646c01f8e9..59e6f44d3a0 100644
--- a/include/asm-arm/arch-at91rm9200/hardware.h
+++ b/include/asm-arm/arch-at91rm9200/hardware.h
@@ -65,6 +65,9 @@
/* SmartMedia */
#define AT91_SMARTMEDIA_BASE 0x40000000 /* NCS3: Smartmedia physical base address */
+/* Compact Flash */
+#define AT91_CF_BASE 0x50000000 /* NCS4-NCS6: Compact Flash physical base address */
+
/* Multi-Master Memory controller */
#define AT91_UHP_BASE 0x00300000 /* USB Host controller */
diff --git a/include/asm-arm/arch-at91rm9200/uncompress.h b/include/asm-arm/arch-at91rm9200/uncompress.h
index b30dd552071..7b38497c24b 100644
--- a/include/asm-arm/arch-at91rm9200/uncompress.h
+++ b/include/asm-arm/arch-at91rm9200/uncompress.h
@@ -31,21 +31,22 @@
*
* This does not append a newline
*/
-static void putstr(const char *s)
+static void putc(int c)
+{
+ void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */
+
+ while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY))
+ barrier();
+ __raw_writel(c, sys + AT91_DBGU_THR);
+}
+
+static inline void flush(void)
{
void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */
- while (*s) {
- while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY)) { barrier(); }
- __raw_writel(*s, sys + AT91_DBGU_THR);
- if (*s == '\n') {
- while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY)) { barrier(); }
- __raw_writel('\r', sys + AT91_DBGU_THR);
- }
- s++;
- }
/* wait for transmission to complete */
- while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY)) { barrier(); }
+ while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY))
+ barrier();
}
#define arch_decomp_setup()
diff --git a/include/asm-arm/arch-cl7500/hardware.h b/include/asm-arm/arch-cl7500/hardware.h
index 2339b764f69..1adfd18e615 100644
--- a/include/asm-arm/arch-cl7500/hardware.h
+++ b/include/asm-arm/arch-cl7500/hardware.h
@@ -53,16 +53,12 @@
#define SCREEN_END 0xdfc00000
#define SCREEN_BASE 0xdf800000
-#define FLUSH_BASE 0xdf000000
-
#define VIDC_BASE (void __iomem *)0xe0400000
#define IOMD_BASE IOMEM(0xe0200000)
#define IOC_BASE IOMEM(0xe0200000)
#define FLOPPYDMA_BASE IOMEM(0xe002a000)
#define PCIO_BASE IOMEM(0xe0010000)
-#define FLUSH_BASE_PHYS 0x00000000 /* ROM */
-
#define vidc_writel(val) __raw_writel(val, VIDC_BASE)
/* in/out bias for the ISA slot region */
diff --git a/include/asm-arm/arch-cl7500/memory.h b/include/asm-arm/arch-cl7500/memory.h
index 34f40a6cec3..3178140e24c 100644
--- a/include/asm-arm/arch-cl7500/memory.h
+++ b/include/asm-arm/arch-cl7500/memory.h
@@ -26,4 +26,10 @@
#define __virt_to_bus(x) __virt_to_phys(x)
#define __bus_to_virt(x) __phys_to_virt(x)
+/*
+ * Cache flushing area - ROM
+ */
+#define FLUSH_BASE_PHYS 0x00000000
+#define FLUSH_BASE 0xdf000000
+
#endif
diff --git a/include/asm-arm/arch-cl7500/uncompress.h b/include/asm-arm/arch-cl7500/uncompress.h
index 68601b3e3b9..c437e0c88c3 100644
--- a/include/asm-arm/arch-cl7500/uncompress.h
+++ b/include/asm-arm/arch-cl7500/uncompress.h
@@ -3,27 +3,19 @@
*
* Copyright (C) 1999, 2000 Nexus Electronics Ltd.
*/
-
#define BASE 0x03010000
#define SERBASE (BASE + (0x2f8 << 2))
-static __inline__ void putc(char c)
+static inline void putc(char c)
{
- while (!(*((volatile unsigned int *)(SERBASE + 0x14)) & 0x20));
+ while (!(*((volatile unsigned int *)(SERBASE + 0x14)) & 0x20))
+ barrier();
+
*((volatile unsigned int *)(SERBASE)) = c;
}
-/*
- * This does not append a newline
- */
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
static __inline__ void arch_decomp_setup(void)
diff --git a/include/asm-arm/arch-clps711x/uncompress.h b/include/asm-arm/arch-clps711x/uncompress.h
index 9fc4bcfa168..07157b7e4b2 100644
--- a/include/asm-arm/arch-clps711x/uncompress.h
+++ b/include/asm-arm/arch-clps711x/uncompress.h
@@ -25,7 +25,6 @@
#undef CLPS7111_BASE
#define CLPS7111_BASE CLPS7111_PHYS_BASE
-#define barrier() __asm__ __volatile__("": : :"memory")
#define __raw_readl(p) (*(unsigned long *)(p))
#define __raw_writel(v,p) (*(unsigned long *)(p) = (v))
@@ -40,21 +39,15 @@
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static inline void putc(int c)
{
- char c;
-
- while ((c = *s++) != '\0') {
- while (clps_readl(SYSFLGx) & SYSFLG_UTXFF)
- barrier();
- clps_writel(c, UARTDRx);
+ while (clps_readl(SYSFLGx) & SYSFLG_UTXFF)
+ barrier();
+ clps_writel(c, UARTDRx);
+}
- if (c == '\n') {
- while (clps_readl(SYSFLGx) & SYSFLG_UTXFF)
- barrier();
- clps_writel('\r', UARTDRx);
- }
- }
+static inline void flush(void)
+{
while (clps_readl(SYSFLGx) & SYSFLG_UBUSY)
barrier();
}
diff --git a/include/asm-arm/arch-ebsa110/debug-macro.S b/include/asm-arm/arch-ebsa110/debug-macro.S
index f61cadabe0e..9213bfe4831 100644
--- a/include/asm-arm/arch-ebsa110/debug-macro.S
+++ b/include/asm-arm/arch-ebsa110/debug-macro.S
@@ -18,4 +18,4 @@
#define UART_SHIFT 2
#define FLOW_CONTROL
-#include <asm/hardware/debug-8250.h>
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-ebsa110/hardware.h b/include/asm-arm/arch-ebsa110/hardware.h
index 4e41c2358f4..3ce864def41 100644
--- a/include/asm-arm/arch-ebsa110/hardware.h
+++ b/include/asm-arm/arch-ebsa110/hardware.h
@@ -57,9 +57,6 @@
/*
* RAM definitions
*/
-#define FLUSH_BASE_PHYS 0x40000000
-#define FLUSH_BASE 0xdf000000
-
#define UNCACHEABLE_ADDR 0xff000000 /* IRQ_STAT */
#endif
diff --git a/include/asm-arm/arch-ebsa110/memory.h b/include/asm-arm/arch-ebsa110/memory.h
index 02f144520c1..c7c500e176d 100644
--- a/include/asm-arm/arch-ebsa110/memory.h
+++ b/include/asm-arm/arch-ebsa110/memory.h
@@ -28,4 +28,10 @@
#define __virt_to_bus(x) (x)
#define __bus_to_virt(x) (x)
+/*
+ * Cache flushing area - SRAM
+ */
+#define FLUSH_BASE_PHYS 0x40000000
+#define FLUSH_BASE 0xdf000000
+
#endif
diff --git a/include/asm-arm/arch-ebsa110/uncompress.h b/include/asm-arm/arch-ebsa110/uncompress.h
index eee95581a92..ae5b775eb0b 100644
--- a/include/asm-arm/arch-ebsa110/uncompress.h
+++ b/include/asm-arm/arch-ebsa110/uncompress.h
@@ -8,33 +8,34 @@
* published by the Free Software Foundation.
*/
+#include <linux/serial_reg.h>
+
+#define SERIAL_BASE ((unsigned char *)0xf0000be0)
+
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static inline void putc(int c)
+{
+ unsigned char v, *base = SERIAL_BASE;
+
+ do {
+ v = base[UART_LSR << 2];
+ barrier();
+ } while (!(v & UART_LSR_THRE));
+
+ base[UART_TX << 2] = c;
+}
+
+static inline void flush(void)
{
- unsigned long tmp1, tmp2;
- __asm__ __volatile__(
- "ldrb %0, [%2], #1\n"
-" teq %0, #0\n"
-" beq 3f\n"
-"1: strb %0, [%3]\n"
-"2: ldrb %1, [%3, #0x14]\n"
-" and %1, %1, #0x60\n"
-" teq %1, #0x60\n"
-" bne 2b\n"
-" teq %0, #'\n'\n"
-" moveq %0, #'\r'\n"
-" beq 1b\n"
-" ldrb %0, [%2], #1\n"
-" teq %0, #0\n"
-" bne 1b\n"
-"3: ldrb %1, [%3, #0x14]\n"
-" and %1, %1, #0x60\n"
-" teq %1, #0x60\n"
-" bne 3b"
- : "=&r" (tmp1), "=&r" (tmp2)
- : "r" (s), "r" (0xf0000be0) : "cc");
+ unsigned char v, *base = SERIAL_BASE;
+
+ do {
+ v = base[UART_LSR << 2];
+ barrier();
+ } while ((v & (UART_LSR_TEMT|UART_LSR_THRE)) !=
+ (UART_LSR_TEMT|UART_LSR_THRE));
}
/*
diff --git a/include/asm-arm/arch-ebsa285/hardware.h b/include/asm-arm/arch-ebsa285/hardware.h
index 2ef2200f108..ec51fe92483 100644
--- a/include/asm-arm/arch-ebsa285/hardware.h
+++ b/include/asm-arm/arch-ebsa285/hardware.h
@@ -48,9 +48,6 @@
#define PCICFG0_SIZE 0x01000000
#define PCICFG0_BASE 0xfa000000
-#define FLUSH_SIZE 0x00100000
-#define FLUSH_BASE 0xf9000000
-
#define PCIMEM_SIZE 0x01000000
#define PCIMEM_BASE 0xf0000000
@@ -61,9 +58,6 @@
#define PCIMEM_SIZE 0x80000000
#define PCIMEM_BASE 0x80000000
-#define FLUSH_SIZE 0x00100000
-#define FLUSH_BASE 0x7e000000
-
#define WFLUSH_SIZE 0x01000000
#define WFLUSH_BASE 0x7d000000
@@ -94,7 +88,6 @@
#define XBUS_SWITCH_J17_11 ((*XBUS_SWITCH) & (1 << 5))
#define XBUS_SWITCH_J17_9 ((*XBUS_SWITCH) & (1 << 6))
-#define FLUSH_BASE_PHYS 0x50000000
#define UNCACHEABLE_ADDR (ARMCSR_BASE + 0x108)
diff --git a/include/asm-arm/arch-ebsa285/memory.h b/include/asm-arm/arch-ebsa285/memory.h
index 09e335cd687..99181ffc7e2 100644
--- a/include/asm-arm/arch-ebsa285/memory.h
+++ b/include/asm-arm/arch-ebsa285/memory.h
@@ -49,12 +49,22 @@ extern unsigned long __bus_to_virt(unsigned long);
#define TASK_SIZE UL(0xbf000000)
#define PAGE_OFFSET UL(0xc0000000)
+/*
+ * Cache flushing area.
+ */
+#define FLUSH_BASE 0xf9000000
+
#elif defined(CONFIG_ARCH_CO285)
/* Task size and page offset at 1.5GB */
#define TASK_SIZE UL(0x5f000000)
#define PAGE_OFFSET UL(0x60000000)
+/*
+ * Cache flushing area.
+ */
+#define FLUSH_BASE 0x7e000000
+
#else
#error "Undefined footbridge architecture"
@@ -72,4 +82,6 @@ extern unsigned long __bus_to_virt(unsigned long);
*/
#define TASK_UNMAPPED_BASE ((TASK_SIZE + 0x01000000) / 3)
+#define FLUSH_BASE_PHYS 0x50000000
+
#endif
diff --git a/include/asm-arm/arch-ebsa285/uncompress.h b/include/asm-arm/arch-ebsa285/uncompress.h
index c2fd84e2d90..86142c882b3 100644
--- a/include/asm-arm/arch-ebsa285/uncompress.h
+++ b/include/asm-arm/arch-ebsa285/uncompress.h
@@ -15,10 +15,11 @@
#define DC21285_BASE ((volatile unsigned int *)0x42000160)
#define SER0_BASE ((volatile unsigned char *)0x7c0003f8)
-static __inline__ void putc(char c)
+static inline void putc(char c)
{
if (machine_is_netwinder()) {
- while ((SER0_BASE[5] & 0x60) != 0x60);
+ while ((SER0_BASE[5] & 0x60) != 0x60)
+ barrier();
SER0_BASE[0] = c;
} else {
while (DC21285_BASE[6] & 8);
@@ -26,17 +27,8 @@ static __inline__ void putc(char c)
}
}
-/*
- * This does not append a newline
- */
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
/*
diff --git a/include/asm-arm/arch-ep93xx/ts72xx.h b/include/asm-arm/arch-ep93xx/ts72xx.h
index 412215e77f4..a94f63ff053 100644
--- a/include/asm-arm/arch-ep93xx/ts72xx.h
+++ b/include/asm-arm/arch-ep93xx/ts72xx.h
@@ -12,6 +12,8 @@
* febfc000 [67]0000000 4K NAND data register
* febfb000 [67]0400000 4K NAND control register
* febfa000 [67]0800000 4K NAND busy register
+ * febf9000 10800000 4K TS-5620 RTC index register
+ * febf8000 11700000 4K TS-5620 RTC data register
*/
#define TS72XX_MODEL_PHYS_BASE 0x22000000
@@ -58,6 +60,15 @@
#define TS72XX_NAND_BUSY_SIZE 0x00001000
+#define TS72XX_RTC_INDEX_VIRT_BASE 0xfebf9000
+#define TS72XX_RTC_INDEX_PHYS_BASE 0x10800000
+#define TS72XX_RTC_INDEX_SIZE 0x00001000
+
+#define TS72XX_RTC_DATA_VIRT_BASE 0xfebf8000
+#define TS72XX_RTC_DATA_PHYS_BASE 0x11700000
+#define TS72XX_RTC_DATA_SIZE 0x00001000
+
+
#ifndef __ASSEMBLY__
#include <asm/io.h>
diff --git a/include/asm-arm/arch-ep93xx/uncompress.h b/include/asm-arm/arch-ep93xx/uncompress.h
index 4410d217077..c15274c85d5 100644
--- a/include/asm-arm/arch-ep93xx/uncompress.h
+++ b/include/asm-arm/arch-ep93xx/uncompress.h
@@ -16,17 +16,27 @@ static unsigned char __raw_readb(unsigned int ptr)
return *((volatile unsigned char *)ptr);
}
+static unsigned int __raw_readl(unsigned int ptr)
+{
+ return *((volatile unsigned int *)ptr);
+}
+
static void __raw_writeb(unsigned char value, unsigned int ptr)
{
*((volatile unsigned char *)ptr) = value;
}
+static void __raw_writel(unsigned int value, unsigned int ptr)
+{
+ *((volatile unsigned int *)ptr) = value;
+}
+
#define PHYS_UART1_DATA 0x808c0000
#define PHYS_UART1_FLAG 0x808c0018
#define UART1_FLAG_TXFF 0x20
-static __inline__ void putc(char c)
+static inline void putc(int c)
{
int i;
@@ -39,15 +49,37 @@ static __inline__ void putc(char c)
__raw_writeb(c, PHYS_UART1_DATA);
}
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
-#define arch_decomp_setup()
+
+/*
+ * Some bootloaders don't turn off DMA from the ethernet MAC before
+ * jumping to linux, which means that we might end up with bits of RX
+ * status and packet data scribbled over the uncompressed kernel image.
+ * Work around this by resetting the ethernet MAC before we uncompress.
+ */
+#define PHYS_ETH_SELF_CTL 0x80010020
+#define ETH_SELF_CTL_RESET 0x00000001
+
+static void ethernet_reset(void)
+{
+ unsigned int v;
+
+ /* Reset the ethernet MAC. */
+ v = __raw_readl(PHYS_ETH_SELF_CTL);
+ __raw_writel(v | ETH_SELF_CTL_RESET, PHYS_ETH_SELF_CTL);
+
+ /* Wait for reset to finish. */
+ while (__raw_readl(PHYS_ETH_SELF_CTL) & ETH_SELF_CTL_RESET)
+ ;
+}
+
+
+static void arch_decomp_setup(void)
+{
+ ethernet_reset();
+}
+
#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-h720x/uncompress.h b/include/asm-arm/arch-h720x/uncompress.h
index 9535764bcc7..18c69e0f358 100644
--- a/include/asm-arm/arch-h720x/uncompress.h
+++ b/include/asm-arm/arch-h720x/uncompress.h
@@ -12,22 +12,20 @@
#define LSR 0x14
#define TEMPTY 0x40
-static void putstr(const char *s)
+static inline void putc(int c)
{
- char c;
volatile unsigned char *p = (volatile unsigned char *)(IO_PHYS+0x20000);
- while ( (c = *s++) != '\0') {
- /* wait until transmit buffer is empty */
- while((p[LSR] & TEMPTY) == 0x0);
- /* write next character */
- *p = c;
-
- if(c == '\n') {
- while((p[LSR] & TEMPTY) == 0x0);
- *p = '\r';
- }
- }
+ /* wait until transmit buffer is empty */
+ while((p[LSR] & TEMPTY) == 0x0)
+ barrier();
+
+ /* write next character */
+ *p = c;
+}
+
+static inline void flush(void)
+{
}
/*
diff --git a/include/asm-arm/arch-imx/debug-macro.S b/include/asm-arm/arch-imx/debug-macro.S
index 83f552f7bcc..c611871643a 100644
--- a/include/asm-arm/arch-imx/debug-macro.S
+++ b/include/asm-arm/arch-imx/debug-macro.S
@@ -16,7 +16,7 @@
tst \rx, #1 @ MMU enabled?
moveq \rx, #0x00000000 @ physical
movne \rx, #0xe0000000 @ virtual
- orr \rx, \rx, #0x00200000
+ orreq \rx, \rx, #0x00200000 @ physical
orr \rx, \rx, #0x00006000 @ UART1 offset
.endm
diff --git a/include/asm-arm/arch-imx/dma.h b/include/asm-arm/arch-imx/dma.h
index b45fa367d71..621ff2c730f 100644
--- a/include/asm-arm/arch-imx/dma.h
+++ b/include/asm-arm/arch-imx/dma.h
@@ -17,27 +17,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
-/*
- * DMA registration
- */
-
typedef enum {
DMA_PRIO_HIGH = 0,
- DMA_PRIO_MEDIUM = 3,
- DMA_PRIO_LOW = 6
+ DMA_PRIO_MEDIUM = 1,
+ DMA_PRIO_LOW = 2
} imx_dma_prio;
-int imx_request_dma(char *name, imx_dma_prio prio,
- void (*irq_handler) (int, void *, struct pt_regs *),
- void (*err_handler) (int, void *, struct pt_regs *),
- void *data);
-
-void imx_free_dma(int dma_ch);
-
-
#define DMA_REQ_UART3_T 2
#define DMA_REQ_UART3_R 3
#define DMA_REQ_SSI2_T 4
diff --git a/include/asm-arm/arch-imx/imx-dma.h b/include/asm-arm/arch-imx/imx-dma.h
new file mode 100644
index 00000000000..f2063c1d610
--- /dev/null
+++ b/include/asm-arm/arch-imx/imx-dma.h
@@ -0,0 +1,90 @@
+/*
+ * linux/include/asm-arm/imxads/dma.h
+ *
+ * Copyright (C) 1997,1998 Russell King
+ *
+ * This program is free software; 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 <asm/dma.h>
+
+#ifndef __ASM_ARCH_IMX_DMA_H
+#define __ASM_ARCH_IMX_DMA_H
+
+#define IMX_DMA_CHANNELS 11
+
+/*
+ * struct imx_dma_channel - i.MX specific DMA extension
+ * @name: name specified by DMA client
+ * @irq_handler: client callback for end of transfer
+ * @err_handler: client callback for error condition
+ * @data: clients context data for callbacks
+ * @dma_mode: direction of the transfer %DMA_MODE_READ or %DMA_MODE_WRITE
+ * @sg: pointer to the actual read/written chunk for scatter-gather emulation
+ * @sgbc: counter of processed bytes in the actual read/written chunk
+ * @resbytes: total residual number of bytes to transfer
+ * (it can be lower or same as sum of SG mapped chunk sizes)
+ * @sgcount: number of chunks to be read/written
+ *
+ * Structure is used for IMX DMA processing. It would be probably good
+ * @struct dma_struct in the future for external interfacing and use
+ * @struct imx_dma_channel only as extension to it.
+ */
+
+struct imx_dma_channel {
+ const char *name;
+ void (*irq_handler) (int, void *, struct pt_regs *);
+ void (*err_handler) (int, void *, struct pt_regs *);
+ void *data;
+ dmamode_t dma_mode;
+ struct scatterlist *sg;
+ unsigned int sgbc;
+ unsigned int sgcount;
+ unsigned int resbytes;
+ int dma_num;
+};
+
+extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
+
+
+/* The type to distinguish channel numbers parameter from ordinal int type */
+typedef int imx_dmach_t;
+
+int
+imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address,
+ unsigned int dma_length, unsigned int dev_addr, dmamode_t dmamode);
+
+int
+imx_dma_setup_sg(imx_dmach_t dma_ch,
+ struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length,
+ unsigned int dev_addr, dmamode_t dmamode);
+
+int
+imx_dma_setup_handlers(imx_dmach_t dma_ch,
+ void (*irq_handler) (int, void *, struct pt_regs *),
+ void (*err_handler) (int, void *, struct pt_regs *), void *data);
+
+void imx_dma_enable(imx_dmach_t dma_ch);
+
+void imx_dma_disable(imx_dmach_t dma_ch);
+
+int imx_dma_request(imx_dmach_t dma_ch, const char *name);
+
+void imx_dma_free(imx_dmach_t dma_ch);
+
+int imx_dma_request_by_prio(imx_dmach_t *pdma_ch, const char *name, imx_dma_prio prio);
+
+
+#endif /* _ASM_ARCH_IMX_DMA_H */
diff --git a/include/asm-arm/arch-imx/imx-uart.h b/include/asm-arm/arch-imx/imx-uart.h
new file mode 100644
index 00000000000..3a685e1780e
--- /dev/null
+++ b/include/asm-arm/arch-imx/imx-uart.h
@@ -0,0 +1,10 @@
+#ifndef ASMARM_ARCH_UART_H
+#define ASMARM_ARCH_UART_H
+
+#define IMXUART_HAVE_RTSCTS (1<<0)
+
+struct imxuart_platform_data {
+ unsigned int flags;
+};
+
+#endif
diff --git a/include/asm-arm/arch-imx/mmc.h b/include/asm-arm/arch-imx/mmc.h
new file mode 100644
index 00000000000..1937151665c
--- /dev/null
+++ b/include/asm-arm/arch-imx/mmc.h
@@ -0,0 +1,12 @@
+#ifndef ASMARM_ARCH_MMC_H
+#define ASMARM_ARCH_MMC_H
+
+#include <linux/mmc/protocol.h>
+
+struct imxmmc_platform_data {
+ int (*card_present)(void);
+};
+
+extern void imx_set_mmc_info(struct imxmmc_platform_data *info);
+
+#endif
diff --git a/include/asm-arm/arch-imx/uncompress.h b/include/asm-arm/arch-imx/uncompress.h
index 096077f2750..da333f69136 100644
--- a/include/asm-arm/arch-imx/uncompress.h
+++ b/include/asm-arm/arch-imx/uncompress.h
@@ -39,8 +39,7 @@
*
* This does not append a newline
*/
-static void
-putstr(const char *s)
+static void putc(int c)
{
unsigned long serial_port;
@@ -54,20 +53,14 @@ putstr(const char *s)
return;
} while(0);
- while (*s) {
- while ( !(UART(USR2) & USR2_TXFE) )
- barrier();
+ while (!(UART(USR2) & USR2_TXFE))
+ barrier();
- UART(TXR) = *s;
-
- if (*s == '\n') {
- while ( !(UART(USR2) & USR2_TXFE) )
- barrier();
+ UART(TXR) = c;
+}
- UART(TXR) = '\r';
- }
- s++;
- }
+static inline void flush(void)
+{
}
/*
diff --git a/include/asm-arm/arch-integrator/uncompress.h b/include/asm-arm/arch-integrator/uncompress.h
index 3957402741d..f61825c4d90 100644
--- a/include/asm-arm/arch-integrator/uncompress.h
+++ b/include/asm-arm/arch-integrator/uncompress.h
@@ -28,21 +28,18 @@
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static void putc(int c)
{
- while (*s) {
- while (AMBA_UART_FR & (1 << 5));
+ while (AMBA_UART_FR & (1 << 5))
+ barrier();
- AMBA_UART_DR = *s;
-
- if (*s == '\n') {
- while (AMBA_UART_FR & (1 << 5));
+ AMBA_UART_DR = c;
+}
- AMBA_UART_DR = '\r';
- }
- s++;
- }
- while (AMBA_UART_FR & (1 << 3));
+static inline void flush(void)
+{
+ while (AMBA_UART_FR & (1 << 3))
+ barrier();
}
/*
diff --git a/include/asm-arm/arch-iop3xx/uncompress.h b/include/asm-arm/arch-iop3xx/uncompress.h
index 82b88762c3c..c98eb6254b1 100644
--- a/include/asm-arm/arch-iop3xx/uncompress.h
+++ b/include/asm-arm/arch-iop3xx/uncompress.h
@@ -19,23 +19,15 @@ static volatile UTYPE uart_base;
#define TX_DONE (UART_LSR_TEMT|UART_LSR_THRE)
-static __inline__ void putc(char c)
+static inline void putc(char c)
{
- while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE);
+ while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
+ barrier();
*uart_base = c;
}
-/*
- * This does not append a newline
- */
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
static __inline__ void __arch_decomp_setup(unsigned long arch_id)
diff --git a/include/asm-arm/arch-ixp2000/uncompress.h b/include/asm-arm/arch-ixp2000/uncompress.h
index 3d3d5b2ed6e..f66b408f363 100644
--- a/include/asm-arm/arch-ixp2000/uncompress.h
+++ b/include/asm-arm/arch-ixp2000/uncompress.h
@@ -29,23 +29,18 @@
#define UARTSR PHYS(0x14) /* Status reg */
-static __inline__ void putc(char c)
+static inline void putc(int c)
{
int j = 0x1000;
- while (--j && !(*UARTSR & UART_LSR_THRE));
+ while (--j && !(*UARTSR & UART_LSR_THRE))
+ barrier();
+
*UARTDR = c;
}
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s)
- {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
#define arch_decomp_setup()
diff --git a/include/asm-arm/arch-ixp23xx/debug-macro.S b/include/asm-arm/arch-ixp23xx/debug-macro.S
new file mode 100644
index 00000000000..2b25e640247
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/debug-macro.S
@@ -0,0 +1,26 @@
+/*
+ * include/asm-arm/arch-ixp23xx/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * 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 <asm/arch/ixp23xx.h>
+
+ .macro addruart,rx
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ mmu enabled?
+ ldreq \rx, =IXP23XX_PERIPHERAL_PHYS @ physical
+ ldrne \rx, =IXP23XX_PERIPHERAL_VIRT @ virtual
+#ifdef __ARMEB__
+ orr \rx, \rx, #0x00000003
+#endif
+ .endm
+
+#define UART_SHIFT 2
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-ixp23xx/dma.h b/include/asm-arm/arch-ixp23xx/dma.h
new file mode 100644
index 00000000000..2f4335e3b83
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/dma.h
@@ -0,0 +1,3 @@
+/*
+ * include/asm-arm/arch-ixp23xx/dma.h
+ */
diff --git a/include/asm-arm/arch-ixp23xx/entry-macro.S b/include/asm-arm/arch-ixp23xx/entry-macro.S
new file mode 100644
index 00000000000..0ef4e6016ac
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/entry-macro.S
@@ -0,0 +1,31 @@
+/*
+ * include/asm-arm/arch-ixp23xx/entry-macro.S
+ */
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \irqnr, =(IXP23XX_INTC_VIRT + IXP23XX_INTR_IRQ_ENC_ST_OFFSET)
+ ldr \irqnr, [\irqnr] @ get interrupt number
+ cmp \irqnr, #0x0 @ suprious interrupt ?
+ movne \irqnr, \irqnr, lsr #2 @ skip unwanted low order bits
+ subne \irqnr, \irqnr, #1 @ convert to 0 based
+
+#if 0
+ cmp \irqnr, #IRQ_IXP23XX_PCI_INT_RPH
+ bne 1001f
+ mov \irqnr, #IRQ_IXP23XX_INTA
+
+ ldr \irqnr, =0xf5000030
+
+ mov \tmp, #(1<<26)
+ tst \irqnr, \tmp
+ movne \irqnr, #IRQ_IXP23XX_INTB
+
+ mov \tmp, #(1<<27)
+ tst \irqnr, \tmp
+ movne \irqnr, #IRQ_IXP23XX_INTA
+1001:
+#endif
+ .endm
diff --git a/include/asm-arm/arch-ixp23xx/hardware.h b/include/asm-arm/arch-ixp23xx/hardware.h
new file mode 100644
index 00000000000..c0010d21a68
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/hardware.h
@@ -0,0 +1,37 @@
+/*
+ * include/asm-arm/arch-ixp23xx/hardware.h
+ *
+ * Copyright (C) 2002-2004 Intel Corporation.
+ * Copyricht (C) 2005 MontaVista Software, 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.
+ *
+ * Hardware definitions for IXP23XX based systems
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+/* PCI IO info */
+#define PCIO_BASE IXP23XX_PCI_IO_VIRT
+#define PCIBIOS_MIN_IO 0x00000000
+#define PCIBIOS_MIN_MEM 0xe0000000
+
+#include "ixp23xx.h"
+
+#define pcibios_assign_all_busses() 0
+
+/*
+ * Platform helper functions
+ */
+#include "platform.h"
+
+/*
+ * Platform-specific headers
+ */
+#include "ixdp2351.h"
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/io.h b/include/asm-arm/arch-ixp23xx/io.h
new file mode 100644
index 00000000000..18415a81ac7
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/io.h
@@ -0,0 +1,54 @@
+/*
+ * include/asm-arm/arch-ixp23xx/io.h
+ *
+ * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2003-2005 Intel Corp.
+ * Copyright (C) 2005 MontaVista Software, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_IO_H
+#define __ASM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(p) ((void __iomem*)((p) + IXP23XX_PCI_IO_VIRT))
+#define __mem_pci(a) (a)
+
+#include <linux/kernel.h> /* For BUG */
+
+static inline void __iomem *
+ixp23xx_ioremap(unsigned long addr, unsigned long size, unsigned long flags)
+{
+ if (addr >= IXP23XX_PCI_MEM_START &&
+ addr <= IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE) {
+ if (addr + size > IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE)
+ return NULL;
+
+ return (void __iomem *)
+ ((addr - IXP23XX_PCI_MEM_START) + IXP23XX_PCI_MEM_VIRT);
+ }
+
+ return __ioremap(addr, size, flags);
+}
+
+static inline void
+ixp23xx_iounmap(void __iomem *addr)
+{
+ if ((((u32)addr) >= IXP23XX_PCI_MEM_VIRT) &&
+ (((u32)addr) < IXP23XX_PCI_MEM_VIRT + IXP23XX_PCI_MEM_SIZE))
+ return;
+
+ __iounmap(addr);
+}
+
+#define __arch_ioremap(a,s,f) ixp23xx_ioremap(a,s,f)
+#define __arch_iounmap(a) ixp23xx_iounmap(a)
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/irqs.h b/include/asm-arm/arch-ixp23xx/irqs.h
new file mode 100644
index 00000000000..e6963958572
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/irqs.h
@@ -0,0 +1,223 @@
+/*
+ * include/asm-arm/arch-ixp23xx/irqs.h
+ *
+ * IRQ definitions for IXP23XX based systems
+ *
+ * Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ *
+ * Copyright (C) 2003-2004 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define NR_IXP23XX_IRQS IRQ_IXP23XX_INTB+1
+#define IRQ_IXP23XX_EXTIRQS NR_IXP23XX_IRQS
+
+
+#define IRQ_IXP23XX_DBG0 0 /* Debug/Execution/MBox */
+#define IRQ_IXP23XX_DBG1 1 /* Debug/Execution/MBox */
+#define IRQ_IXP23XX_NPE_TRG 2 /* npe_trigger */
+#define IRQ_IXP23XX_TIMER1 3 /* Timer[0] */
+#define IRQ_IXP23XX_TIMER2 4 /* Timer[1] */
+#define IRQ_IXP23XX_TIMESTAMP 5 /* Timer[2], Time-stamp */
+#define IRQ_IXP23XX_WDOG 6 /* Time[3], Watchdog Timer */
+#define IRQ_IXP23XX_PCI_DBELL 7 /* PCI Doorbell */
+#define IRQ_IXP23XX_PCI_DMA1 8 /* PCI DMA Channel 1 */
+#define IRQ_IXP23XX_PCI_DMA2 9 /* PCI DMA Channel 2 */
+#define IRQ_IXP23XX_PCI_DMA3 10 /* PCI DMA Channel 3 */
+#define IRQ_IXP23XX_PCI_INT_RPH 11 /* pcxg_pci_int_rph */
+#define IRQ_IXP23XX_CPP_PMU 12 /* xpxg_pm_int_rpl */
+#define IRQ_IXP23XX_SWINT0 13 /* S/W Interrupt0 */
+#define IRQ_IXP23XX_SWINT1 14 /* S/W Interrupt1 */
+#define IRQ_IXP23XX_UART2 15 /* UART1 Interrupt */
+#define IRQ_IXP23XX_UART1 16 /* UART0 Interrupt */
+#define IRQ_IXP23XX_XSI_PMU_ROLLOVER 17 /* AHB Performance M. Unit counter rollover */
+#define IRQ_IXP23XX_XSI_AHB_PM0 18 /* intr_pm_o */
+#define IRQ_IXP23XX_XSI_AHB_ECE0 19 /* intr_ece_o */
+#define IRQ_IXP23XX_XSI_AHB_GASKET 20 /* gas_intr_o */
+#define IRQ_IXP23XX_XSI_CPP 21 /* xsi2cpp_int */
+#define IRQ_IXP23XX_CPP_XSI 22 /* cpp2xsi_int */
+#define IRQ_IXP23XX_ME_ATTN0 23 /* ME_ATTN */
+#define IRQ_IXP23XX_ME_ATTN1 24 /* ME_ATTN */
+#define IRQ_IXP23XX_ME_ATTN2 25 /* ME_ATTN */
+#define IRQ_IXP23XX_ME_ATTN3 26 /* ME_ATTN */
+#define IRQ_IXP23XX_PCI_ERR_RPH 27 /* PCXG_PCI_ERR_RPH */
+#define IRQ_IXP23XX_D0XG_ECC_CORR 28 /* D0XG_DRAM_ECC_CORR */
+#define IRQ_IXP23XX_D0XG_ECC_UNCORR 29 /* D0XG_DRAM_ECC_UNCORR */
+#define IRQ_IXP23XX_SRAM_ERR1 30 /* SRAM1_ERR */
+#define IRQ_IXP23XX_SRAM_ERR0 31 /* SRAM0_ERR */
+#define IRQ_IXP23XX_MEDIA_ERR 32 /* MEDIA_ERR */
+#define IRQ_IXP23XX_STH_DRAM_ECC_MAJ 33 /* STH_DRAM0_ECC_MAJ */
+#define IRQ_IXP23XX_GPIO6 34 /* GPIO0 interrupts */
+#define IRQ_IXP23XX_GPIO7 35 /* GPIO1 interrupts */
+#define IRQ_IXP23XX_GPIO8 36 /* GPIO2 interrupts */
+#define IRQ_IXP23XX_GPIO9 37 /* GPIO3 interrupts */
+#define IRQ_IXP23XX_GPIO10 38 /* GPIO4 interrupts */
+#define IRQ_IXP23XX_GPIO11 39 /* GPIO5 interrupts */
+#define IRQ_IXP23XX_GPIO12 40 /* GPIO6 interrupts */
+#define IRQ_IXP23XX_GPIO13 41 /* GPIO7 interrupts */
+#define IRQ_IXP23XX_GPIO14 42 /* GPIO8 interrupts */
+#define IRQ_IXP23XX_GPIO15 43 /* GPIO9 interrupts */
+#define IRQ_IXP23XX_SHAC_RING0 44 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING1 45 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING2 46 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING3 47 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING4 48 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING5 49 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING6 50 /* SHAC RING Full */
+#define IRQ_IXP23XX_SHAC_RING7 51 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING8 52 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING9 53 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING10 54 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING11 55 /* SHAC Ring Full */
+#define IRQ_IXP23XX_ME_THREAD_A0_ME0 56 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A1_ME0 57 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A2_ME0 58 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A3_ME0 59 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A4_ME0 60 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A5_ME0 61 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A6_ME0 62 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A7_ME0 63 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A8_ME1 64 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A9_ME1 65 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A10_ME1 66 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A11_ME1 67 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A12_ME1 68 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A13_ME1 69 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A14_ME1 70 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A15_ME1 71 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A16_ME2 72 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A17_ME2 73 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A18_ME2 74 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A19_ME2 75 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A20_ME2 76 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A21_ME2 77 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A22_ME2 78 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A23_ME2 79 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A24_ME3 80 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A25_ME3 81 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A26_ME3 82 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A27_ME3 83 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A28_ME3 84 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A29_ME3 85 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A30_ME3 86 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A31_ME3 87 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_B0_ME0 88 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B1_ME0 89 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B2_ME0 90 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B3_ME0 91 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B4_ME0 92 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B5_ME0 93 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B6_ME0 94 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B7_ME0 95 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B8_ME1 96 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B9_ME1 97 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B10_ME1 98 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B11_ME1 99 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B12_ME1 100 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B13_ME1 101 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B14_ME1 102 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B15_ME1 103 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B16_ME2 104 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B17_ME2 105 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B18_ME2 106 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B19_ME2 107 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B20_ME2 108 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B21_ME2 109 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B22_ME2 110 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B23_ME2 111 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B24_ME3 112 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B25_ME3 113 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B26_ME3 114 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B27_ME3 115 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B28_ME3 116 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B29_ME3 117 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B30_ME3 118 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B31_ME3 119 /* ME_THREAD_B */
+
+#define NUM_IXP23XX_RAW_IRQS 120
+
+#define IRQ_IXP23XX_INTA 120 /* Indirect pcxg_pci_int_rph */
+#define IRQ_IXP23XX_INTB 121 /* Indirect pcxg_pci_int_rph */
+
+#define NR_IXP23XX_IRQ (IRQ_IXP23XX_INTB + 1)
+
+/*
+ * We default to 32 per-board IRQs. Increase this number if you need
+ * more, but keep it realistic.
+ */
+#define NR_IXP23XX_MACH_IRQS 32
+
+#define NR_IRQS NR_IXP23XX_IRQS + NR_IXP23XX_MACH_IRQS
+
+#define IXP23XX_MACH_IRQ(irq) (NR_IXP23XX_IRQ + (irq))
+
+
+/*
+ * IXDP2351-specific interrupts
+ */
+
+/*
+ * External PCI interrupts signaled through INTB
+ *
+ */
+#define IXDP2351_INTB_IRQ_BASE 0
+#define IRQ_IXDP2351_INTA_82546 IXP23XX_MACH_IRQ(0)
+#define IRQ_IXDP2351_INTB_82546 IXP23XX_MACH_IRQ(1)
+#define IRQ_IXDP2351_SPCI_DB_0 IXP23XX_MACH_IRQ(2)
+#define IRQ_IXDP2351_SPCI_DB_1 IXP23XX_MACH_IRQ(3)
+#define IRQ_IXDP2351_SPCI_PMC_INTA IXP23XX_MACH_IRQ(4)
+#define IRQ_IXDP2351_SPCI_PMC_INTB IXP23XX_MACH_IRQ(5)
+#define IRQ_IXDP2351_SPCI_PMC_INTC IXP23XX_MACH_IRQ(6)
+#define IRQ_IXDP2351_SPCI_PMC_INTD IXP23XX_MACH_IRQ(7)
+#define IRQ_IXDP2351_SPCI_FIC IXP23XX_MACH_IRQ(8)
+
+#define IXDP2351_INTB_IRQ_BIT(irq) (irq - IXP23XX_MACH_IRQ(0))
+#define IXDP2351_INTB_IRQ_MASK(irq) (1 << IXDP2351_INTB_IRQ_BIT(irq))
+#define IXDP2351_INTB_IRQ_VALID 0x01FF
+#define IXDP2351_INTB_IRQ_NUM 16
+
+/*
+ * Other external interrupts signaled through INTA
+ */
+#define IXDP2351_INTA_IRQ_BASE 16
+#define IRQ_IXDP2351_IPMI_FROM IXP23XX_MACH_IRQ(16)
+#define IRQ_IXDP2351_125US IXP23XX_MACH_IRQ(17)
+#define IRQ_IXDP2351_DB_0_ADD IXP23XX_MACH_IRQ(18)
+#define IRQ_IXDP2351_DB_1_ADD IXP23XX_MACH_IRQ(19)
+#define IRQ_IXDP2351_DEBUG1 IXP23XX_MACH_IRQ(20)
+#define IRQ_IXDP2351_ADD_UART IXP23XX_MACH_IRQ(21)
+#define IRQ_IXDP2351_FIC_ADD IXP23XX_MACH_IRQ(24)
+#define IRQ_IXDP2351_CS8900 IXP23XX_MACH_IRQ(25)
+#define IRQ_IXDP2351_BBSRAM IXP23XX_MACH_IRQ(26)
+#define IRQ_IXDP2351_CONFIG_MEDIA IXP23XX_MACH_IRQ(27)
+#define IRQ_IXDP2351_CLOCK_REF IXP23XX_MACH_IRQ(28)
+#define IRQ_IXDP2351_A10_NP IXP23XX_MACH_IRQ(29)
+#define IRQ_IXDP2351_A11_NP IXP23XX_MACH_IRQ(30)
+#define IRQ_IXDP2351_DEBUG_NP IXP23XX_MACH_IRQ(31)
+
+#define IXDP2351_INTA_IRQ_BIT(irq) (irq - IXP23XX_MACH_IRQ(16))
+#define IXDP2351_INTA_IRQ_MASK(irq) (1 << IXDP2351_INTA_IRQ_BIT(irq))
+#define IXDP2351_INTA_IRQ_VALID 0xFF3F
+#define IXDP2351_INTA_IRQ_NUM 16
+
+
+/*
+ * ADI RoadRunner IRQs
+ */
+#define IRQ_ROADRUNNER_PCI_INTA IRQ_IXP23XX_INTA
+#define IRQ_ROADRUNNER_PCI_INTB IRQ_IXP23XX_INTB
+#define IRQ_ROADRUNNER_PCI_INTC IRQ_IXP23XX_GPIO11
+#define IRQ_ROADRUNNER_PCI_INTD IRQ_IXP23XX_GPIO12
+
+/*
+ * Put new board definitions here
+ */
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/ixdp2351.h b/include/asm-arm/arch-ixp23xx/ixdp2351.h
new file mode 100644
index 00000000000..4a24f8f1565
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/ixdp2351.h
@@ -0,0 +1,89 @@
+/*
+ * include/asm-arm/arch-ixp23xx/ixdp2351.h
+ *
+ * Register and other defines for IXDP2351
+ *
+ * Copyright (c) 2002-2004 Intel Corp.
+ * Copytight (c) 2005 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_ARCH_IXDP2351_H
+#define __ASM_ARCH_IXDP2351_H
+
+/*
+ * NP module memory map
+ */
+#define IXDP2351_NP_PHYS_BASE (IXP23XX_EXP_BUS_CS4_BASE)
+#define IXDP2351_NP_PHYS_SIZE 0x00100000
+#define IXDP2351_NP_VIRT_BASE 0xeff00000
+
+#define IXDP2351_VIRT_CS8900_BASE (IXDP2351_NP_VIRT_BASE)
+#define IXDP2351_VIRT_CS8900_END (IXDP2351_VIRT_CS8900_BASE + 16)
+
+#define IXDP2351_VIRT_NP_CPLD_BASE (IXP23XX_EXP_BUS_CS4_BASE_VIRT + 0x00010000)
+
+#define IXDP2351_NP_CPLD_REG(reg) ((volatile u16 *)(IXDP2351_VIRT_NP_CPLD_BASE + reg))
+
+#define IXDP2351_NP_CPLD_RESET1_REG IXDP2351_NP_CPLD_REG(0x00)
+#define IXDP2351_NP_CPLD_LED_REG IXDP2351_NP_CPLD_REG(0x02)
+#define IXDP2351_NP_CPLD_VERSION_REG IXDP2351_NP_CPLD_REG(0x04)
+
+/*
+ * Base board module memory map
+ */
+
+#define IXDP2351_BB_BASE_PHYS (IXP23XX_EXP_BUS_CS5_BASE)
+#define IXDP2351_BB_SIZE 0x01000000
+#define IXDP2351_BB_BASE_VIRT (0xee000000)
+
+#define IXDP2351_BB_AREA_BASE(offset) (IXDP2351_BB_BASE_VIRT + offset)
+
+#define IXDP2351_VIRT_NVRAM_BASE IXDP2351_BB_AREA_BASE(0x0)
+#define IXDP2351_NVRAM_SIZE (0x20000)
+
+#define IXDP2351_VIRT_MB_IXF1104_BASE IXDP3251_BB_AREA_BASE(0x00020000)
+#define IXDP2351_VIRT_ADD_UART_BASE IXDP2351_BB_AREA_BASE(0x000240C0)
+#define IXDP2351_VIRT_FIC_BASE IXDP2351_BB_AREA_BASE(0x00200000)
+#define IXDP2351_VIRT_DB0_BASE IXDP2351_BB_AREA_BASE(0x00400000)
+#define IXDP2351_VIRT_DB1_BASE IXDP2351_BB_AREA_BASE(0x00600000)
+#define IXDP2351_VIRT_CPLD_BASE IXDP2351_BB_AREA_BASE(0x00024000)
+
+/*
+ * On board CPLD registers
+ */
+#define IXDP2351_CPLD_BB_REG(reg) ((volatile u16 *)(IXDP2351_VIRT_CPLD_BASE + reg))
+
+#define IXDP2351_CPLD_RESET0_REG IXDP2351_CPLD_BB_REG(0x00)
+#define IXDP2351_CPLD_RESET1_REG IXDP2351_CPLD_BB_REG(0x04)
+
+#define IXDP2351_CPLD_RESET1_MAGIC 0x55AA
+#define IXDP2351_CPLD_RESET1_ENABLE 0x8000
+
+#define IXDP2351_CPLD_FPGA_CONFIG_REG IXDP2351_CPLD_BB_REG(0x08)
+#define IXDP2351_CPLD_INTB_MASK_SET_REG IXDP2351_CPLD_BB_REG(0x10)
+#define IXDP2351_CPLD_INTA_MASK_SET_REG IXDP2351_CPLD_BB_REG(0x14)
+#define IXDP2351_CPLD_INTB_STAT_REG IXDP2351_CPLD_BB_REG(0x18)
+#define IXDP2351_CPLD_INTA_STAT_REG IXDP2351_CPLD_BB_REG(0x1C)
+#define IXDP2351_CPLD_INTB_RAW_REG IXDP2351_CPLD_BB_REG(0x20) /* read */
+#define IXDP2351_CPLD_INTA_RAW_REG IXDP2351_CPLD_BB_REG(0x24) /* read */
+#define IXDP2351_CPLD_INTB_MASK_CLR_REG IXDP2351_CPLD_INTB_RAW_REG /* write */
+#define IXDP2351_CPLD_INTA_MASK_CLR_REG IXDP2351_CPLD_INTA_RAW_REG /* write */
+#define IXDP2351_CPLD_INTB_SIM_REG IXDP2351_CPLD_BB_REG(0x28)
+#define IXDP2351_CPLD_INTA_SIM_REG IXDP2351_CPLD_BB_REG(0x2C)
+ /* Interrupt bits are defined in irqs.h */
+#define IXDP2351_CPLD_BB_GBE0_REG IXDP2351_CPLD_BB_REG(0x30)
+#define IXDP2351_CPLD_BB_GBE1_REG IXDP2351_CPLD_BB_REG(0x34)
+
+/* #define IXDP2351_CPLD_BB_MISC_REG IXDP2351_CPLD_REG(0x1C) */
+/* #define IXDP2351_CPLD_BB_MISC_REV_MASK 0xFF */
+/* #define IXDP2351_CPLD_BB_GDXCS0_REG IXDP2351_CPLD_REG(0x24) */
+/* #define IXDP2351_CPLD_BB_GDXCS1_REG IXDP2351_CPLD_REG(0x28) */
+/* #define IXDP2351_CPLD_BB_CLOCK_REG IXDP2351_CPLD_REG(0x04) */
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/ixp23xx.h b/include/asm-arm/arch-ixp23xx/ixp23xx.h
new file mode 100644
index 00000000000..e49e1ca61b1
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/ixp23xx.h
@@ -0,0 +1,306 @@
+/*
+ * include/asm-arm/arch-ixp23xx/ixp23xx.h
+ *
+ * Register definitions for IXP23XX
+ *
+ * Copyright (C) 2003-2005 Intel Corporation.
+ * Copyright (C) 2005 MontaVista Software, Inc.
+ *
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_IXP23XX_H
+#define __ASM_ARCH_IXP23XX_H
+
+/*
+ * IXP2300 linux memory map:
+ *
+ * virt phys size
+ * fffd0000 a0000000 64K XSI2CPP_CSR
+ * fffc0000 c4000000 4K EXP_CFG
+ * fff00000 c8000000 64K PERIPHERAL
+ * fe000000 1c0000000 16M CAP_CSR
+ * fd000000 1c8000000 16M MSF_CSR
+ * fb000000 16M ---
+ * fa000000 1d8000000 32M PCI_IO
+ * f8000000 1da000000 32M PCI_CFG
+ * f6000000 1de000000 32M PCI_CREG
+ * f4000000 32M ---
+ * f0000000 1e0000000 64M PCI_MEM
+ * e[c-f]000000 per-platform mappings
+ */
+
+
+/****************************************************************************
+ * Static mappings.
+ ****************************************************************************/
+#define IXP23XX_XSI2CPP_CSR_PHYS 0xa0000000
+#define IXP23XX_XSI2CPP_CSR_VIRT 0xfffd0000
+#define IXP23XX_XSI2CPP_CSR_SIZE 0x00010000
+
+#define IXP23XX_EXP_CFG_PHYS 0xc4000000
+#define IXP23XX_EXP_CFG_VIRT 0xfffc0000
+#define IXP23XX_EXP_CFG_SIZE 0x00001000
+
+#define IXP23XX_PERIPHERAL_PHYS 0xc8000000
+#define IXP23XX_PERIPHERAL_VIRT 0xfff00000
+#define IXP23XX_PERIPHERAL_SIZE 0x00010000
+
+#define IXP23XX_CAP_CSR_PHYS 0x1c0000000ULL
+#define IXP23XX_CAP_CSR_VIRT 0xfe000000
+#define IXP23XX_CAP_CSR_SIZE 0x01000000
+
+#define IXP23XX_MSF_CSR_PHYS 0x1c8000000ULL
+#define IXP23XX_MSF_CSR_VIRT 0xfd000000
+#define IXP23XX_MSF_CSR_SIZE 0x01000000
+
+#define IXP23XX_PCI_IO_PHYS 0x1d8000000ULL
+#define IXP23XX_PCI_IO_VIRT 0xfa000000
+#define IXP23XX_PCI_IO_SIZE 0x02000000
+
+#define IXP23XX_PCI_CFG_PHYS 0x1da000000ULL
+#define IXP23XX_PCI_CFG_VIRT 0xf8000000
+#define IXP23XX_PCI_CFG_SIZE 0x02000000
+#define IXP23XX_PCI_CFG0_VIRT IXP23XX_PCI_CFG_VIRT
+#define IXP23XX_PCI_CFG1_VIRT (IXP23XX_PCI_CFG_VIRT + 0x01000000)
+
+#define IXP23XX_PCI_CREG_PHYS 0x1de000000ULL
+#define IXP23XX_PCI_CREG_VIRT 0xf6000000
+#define IXP23XX_PCI_CREG_SIZE 0x02000000
+#define IXP23XX_PCI_CSR_VIRT (IXP23XX_PCI_CREG_VIRT + 0x01000000)
+
+#define IXP23XX_PCI_MEM_START 0xe0000000
+#define IXP23XX_PCI_MEM_PHYS 0x1e0000000ULL
+#define IXP23XX_PCI_MEM_VIRT 0xf0000000
+#define IXP23XX_PCI_MEM_SIZE 0x04000000
+
+
+/****************************************************************************
+ * XSI2CPP CSRs.
+ ****************************************************************************/
+#define IXP23XX_XSI2CPP_REG(x) ((volatile unsigned long *)(IXP23XX_XSI2CPP_CSR_VIRT + (x)))
+#define IXP23XX_CPP2XSI_CURR_XFER_REG3 IXP23XX_XSI2CPP_REG(0xf8)
+#define IXP23XX_CPP2XSI_ADDR_31 (1 << 19)
+#define IXP23XX_CPP2XSI_PSH_OFF (1 << 20)
+#define IXP23XX_CPP2XSI_COH_OFF (1 << 21)
+
+
+/****************************************************************************
+ * Expansion Bus Config.
+ ****************************************************************************/
+#define IXP23XX_EXP_CFG_REG(x) ((volatile unsigned long *)(IXP23XX_EXP_CFG_VIRT + (x)))
+#define IXP23XX_EXP_CS0 IXP23XX_EXP_CFG_REG(0x00)
+#define IXP23XX_EXP_CS1 IXP23XX_EXP_CFG_REG(0x04)
+#define IXP23XX_EXP_CS2 IXP23XX_EXP_CFG_REG(0x08)
+#define IXP23XX_EXP_CS3 IXP23XX_EXP_CFG_REG(0x0c)
+#define IXP23XX_EXP_CS4 IXP23XX_EXP_CFG_REG(0x10)
+#define IXP23XX_EXP_CS5 IXP23XX_EXP_CFG_REG(0x14)
+#define IXP23XX_EXP_CS6 IXP23XX_EXP_CFG_REG(0x18)
+#define IXP23XX_EXP_CS7 IXP23XX_EXP_CFG_REG(0x1c)
+#define IXP23XX_FLASH_WRITABLE (0x2)
+#define IXP23XX_FLASH_BUS8 (0x1)
+
+#define IXP23XX_EXP_CFG0 IXP23XX_EXP_CFG_REG(0x20)
+#define IXP23XX_EXP_CFG1 IXP23XX_EXP_CFG_REG(0x24)
+#define IXP23XX_EXP_CFG0_MEM_MAP (1 << 31)
+#define IXP23XX_EXP_CFG0_XSCALE_SPEED_SEL (3 << 22)
+#define IXP23XX_EXP_CFG0_XSCALE_SPEED_EN (1 << 21)
+#define IXP23XX_EXP_CFG0_CPP_SPEED_SEL (3 << 19)
+#define IXP23XX_EXP_CFG0_CPP_SPEED_EN (1 << 18)
+#define IXP23XX_EXP_CFG0_PCI_SWIN (3 << 16)
+#define IXP23XX_EXP_CFG0_PCI_DWIN (3 << 14)
+#define IXP23XX_EXP_CFG0_PCI33_MODE (1 << 13)
+#define IXP23XX_EXP_CFG0_QDR_SPEED_SEL (1 << 12)
+#define IXP23XX_EXP_CFG0_CPP_DIV_SEL (1 << 5)
+#define IXP23XX_EXP_CFG0_XSI_NOT_PRES (1 << 4)
+#define IXP23XX_EXP_CFG0_PROM_BOOT (1 << 3)
+#define IXP23XX_EXP_CFG0_PCI_ARB (1 << 2)
+#define IXP23XX_EXP_CFG0_PCI_HOST (1 << 1)
+#define IXP23XX_EXP_CFG0_FLASH_WIDTH (1 << 0)
+
+#define IXP23XX_EXP_UNIT_FUSE IXP23XX_EXP_CFG_REG(0x28)
+#define IXP23XX_EXP_MSF_MUX IXP23XX_EXP_CFG_REG(0x30)
+
+#define IXP23XX_EXP_BUS_PHYS 0x90000000
+#define IXP23XX_EXP_BUS_WINDOW_SIZE 0x01000000
+
+#define IXP23XX_EXP_BUS_CS0_BASE (IXP23XX_EXP_BUS_PHYS + 0x00000000)
+#define IXP23XX_EXP_BUS_CS1_BASE (IXP23XX_EXP_BUS_PHYS + 0x01000000)
+#define IXP23XX_EXP_BUS_CS2_BASE (IXP23XX_EXP_BUS_PHYS + 0x02000000)
+#define IXP23XX_EXP_BUS_CS3_BASE (IXP23XX_EXP_BUS_PHYS + 0x03000000)
+#define IXP23XX_EXP_BUS_CS4_BASE (IXP23XX_EXP_BUS_PHYS + 0x04000000)
+#define IXP23XX_EXP_BUS_CS5_BASE (IXP23XX_EXP_BUS_PHYS + 0x05000000)
+#define IXP23XX_EXP_BUS_CS6_BASE (IXP23XX_EXP_BUS_PHYS + 0x06000000)
+#define IXP23XX_EXP_BUS_CS7_BASE (IXP23XX_EXP_BUS_PHYS + 0x07000000)
+
+
+/****************************************************************************
+ * Peripherals.
+ ****************************************************************************/
+#define IXP23XX_UART1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x0000)
+#define IXP23XX_UART2_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x1000)
+#define IXP23XX_PMU_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x2000)
+#define IXP23XX_INTC_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x3000)
+#define IXP23XX_GPIO_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x4000)
+#define IXP23XX_TIMER_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x5000)
+#define IXP23XX_NPE0_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x6000)
+#define IXP23XX_DSR_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x7000)
+#define IXP23XX_NPE1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x8000)
+#define IXP23XX_ETH0_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x9000)
+#define IXP23XX_ETH1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xA000)
+#define IXP23XX_GIG0_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xB000)
+#define IXP23XX_GIG1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xC000)
+#define IXP23XX_DDRS_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xD000)
+
+#define IXP23XX_UART1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x0000)
+#define IXP23XX_UART2_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x1000)
+#define IXP23XX_PMU_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x2000)
+#define IXP23XX_INTC_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x3000)
+#define IXP23XX_GPIO_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x4000)
+#define IXP23XX_TIMER_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x5000)
+#define IXP23XX_NPE0_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x6000)
+#define IXP23XX_DSR_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x7000)
+#define IXP23XX_NPE1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x8000)
+#define IXP23XX_ETH0_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x9000)
+#define IXP23XX_ETH1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xA000)
+#define IXP23XX_GIG0_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xB000)
+#define IXP23XX_GIG1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xC000)
+#define IXP23XX_DDRS_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xD000)
+
+
+/****************************************************************************
+ * Interrupt controller.
+ ****************************************************************************/
+#define IXP23XX_INTC_REG(x) ((volatile unsigned long *)(IXP23XX_INTC_VIRT + (x)))
+#define IXP23XX_INTR_ST1 IXP23XX_INTC_REG(0x00)
+#define IXP23XX_INTR_ST2 IXP23XX_INTC_REG(0x04)
+#define IXP23XX_INTR_ST3 IXP23XX_INTC_REG(0x08)
+#define IXP23XX_INTR_ST4 IXP23XX_INTC_REG(0x0c)
+#define IXP23XX_INTR_EN1 IXP23XX_INTC_REG(0x10)
+#define IXP23XX_INTR_EN2 IXP23XX_INTC_REG(0x14)
+#define IXP23XX_INTR_EN3 IXP23XX_INTC_REG(0x18)
+#define IXP23XX_INTR_EN4 IXP23XX_INTC_REG(0x1c)
+#define IXP23XX_INTR_SEL1 IXP23XX_INTC_REG(0x20)
+#define IXP23XX_INTR_SEL2 IXP23XX_INTC_REG(0x24)
+#define IXP23XX_INTR_SEL3 IXP23XX_INTC_REG(0x28)
+#define IXP23XX_INTR_SEL4 IXP23XX_INTC_REG(0x2c)
+#define IXP23XX_INTR_IRQ_ST1 IXP23XX_INTC_REG(0x30)
+#define IXP23XX_INTR_IRQ_ST2 IXP23XX_INTC_REG(0x34)
+#define IXP23XX_INTR_IRQ_ST3 IXP23XX_INTC_REG(0x38)
+#define IXP23XX_INTR_IRQ_ST4 IXP23XX_INTC_REG(0x3c)
+#define IXP23XX_INTR_IRQ_ENC_ST_OFFSET 0x54
+
+
+/****************************************************************************
+ * GPIO.
+ ****************************************************************************/
+#define IXP23XX_GPIO_REG(x) ((volatile unsigned long *)(IXP23XX_GPIO_VIRT + (x)))
+#define IXP23XX_GPIO_GPOUTR IXP23XX_GPIO_REG(0x00)
+#define IXP23XX_GPIO_GPOER IXP23XX_GPIO_REG(0x04)
+#define IXP23XX_GPIO_GPINR IXP23XX_GPIO_REG(0x08)
+#define IXP23XX_GPIO_GPISR IXP23XX_GPIO_REG(0x0c)
+#define IXP23XX_GPIO_GPIT1R IXP23XX_GPIO_REG(0x10)
+#define IXP23XX_GPIO_GPIT2R IXP23XX_GPIO_REG(0x14)
+#define IXP23XX_GPIO_GPCLKR IXP23XX_GPIO_REG(0x18)
+#define IXP23XX_GPIO_GPDBSELR IXP23XX_GPIO_REG(0x1c)
+
+#define IXP23XX_GPIO_STYLE_MASK 0x7
+#define IXP23XX_GPIO_STYLE_ACTIVE_HIGH 0x0
+#define IXP23XX_GPIO_STYLE_ACTIVE_LOW 0x1
+#define IXP23XX_GPIO_STYLE_RISING_EDGE 0x2
+#define IXP23XX_GPIO_STYLE_FALLING_EDGE 0x3
+#define IXP23XX_GPIO_STYLE_TRANSITIONAL 0x4
+
+#define IXP23XX_GPIO_STYLE_SIZE 3
+
+
+/****************************************************************************
+ * Timer.
+ ****************************************************************************/
+#define IXP23XX_TIMER_REG(x) ((volatile unsigned long *)(IXP23XX_TIMER_VIRT + (x)))
+#define IXP23XX_TIMER_CONT IXP23XX_TIMER_REG(0x00)
+#define IXP23XX_TIMER1_TIMESTAMP IXP23XX_TIMER_REG(0x04)
+#define IXP23XX_TIMER1_RELOAD IXP23XX_TIMER_REG(0x08)
+#define IXP23XX_TIMER2_TIMESTAMP IXP23XX_TIMER_REG(0x0c)
+#define IXP23XX_TIMER2_RELOAD IXP23XX_TIMER_REG(0x10)
+#define IXP23XX_TIMER_WDOG IXP23XX_TIMER_REG(0x14)
+#define IXP23XX_TIMER_WDOG_EN IXP23XX_TIMER_REG(0x18)
+#define IXP23XX_TIMER_WDOG_KEY IXP23XX_TIMER_REG(0x1c)
+#define IXP23XX_TIMER_WDOG_KEY_MAGIC 0x482e
+#define IXP23XX_TIMER_STATUS IXP23XX_TIMER_REG(0x20)
+#define IXP23XX_TIMER_SOFT_RESET IXP23XX_TIMER_REG(0x24)
+#define IXP23XX_TIMER_SOFT_RESET_EN IXP23XX_TIMER_REG(0x28)
+
+#define IXP23XX_TIMER_ENABLE (1 << 0)
+#define IXP23XX_TIMER_ONE_SHOT (1 << 1)
+/* Low order bits of reload value ignored */
+#define IXP23XX_TIMER_RELOAD_MASK (0x3)
+#define IXP23XX_TIMER_DISABLED (0x0)
+#define IXP23XX_TIMER1_INT_PEND (1 << 0)
+#define IXP23XX_TIMER2_INT_PEND (1 << 1)
+#define IXP23XX_TIMER_STATUS_TS_PEND (1 << 2)
+#define IXP23XX_TIMER_STATUS_WDOG_PEND (1 << 3)
+#define IXP23XX_TIMER_STATUS_WARM_RESET (1 << 4)
+
+
+/****************************************************************************
+ * CAP CSRs.
+ ****************************************************************************/
+#define IXP23XX_GLOBAL_REG(x) ((volatile unsigned long *)(IXP23XX_CAP_CSR_VIRT + 0x4a00 + (x)))
+#define IXP23XX_PROD_IDG IXP23XX_GLOBAL_REG(0x00)
+#define IXP23XX_MISC_CONTROL IXP23XX_GLOBAL_REG(0x04)
+#define IXP23XX_MSF_CLK_CNTRL IXP23XX_GLOBAL_REG(0x08)
+#define IXP23XX_RESET0 IXP23XX_GLOBAL_REG(0x0c)
+#define IXP23XX_RESET1 IXP23XX_GLOBAL_REG(0x10)
+#define IXP23XX_STRAP_OPTIONS IXP23XX_GLOBAL_REG(0x18)
+
+#define IXP23XX_ENABLE_WATCHDOG (1 << 24)
+#define IXP23XX_SHPC_INIT_COMP (1 << 21)
+#define IXP23XX_RST_ALL (1 << 16)
+#define IXP23XX_RESET_PCI (1 << 2)
+#define IXP23XX_PCI_UNIT_RESET (1 << 1)
+#define IXP23XX_XSCALE_RESET (1 << 0)
+
+
+/****************************************************************************
+ * PCI CSRs.
+ ****************************************************************************/
+#define IXP23XX_PCI_CREG(x) ((volatile unsigned long *)(IXP23XX_PCI_CREG_VIRT + (x)))
+#define IXP23XX_PCI_CMDSTAT IXP23XX_PCI_CREG(0x04)
+#define IXP23XX_PCI_SRAM_BAR IXP23XX_PCI_CREG(0x14)
+#define IXP23XX_PCI_SDRAM_BAR IXP23XX_PCI_CREG(0x18)
+
+
+#define IXP23XX_PCI_CSR(x) ((volatile unsigned long *)(IXP23XX_PCI_CREG_VIRT + 0x01000000 + (x)))
+#define IXP23XX_PCI_OUT_INT_STATUS IXP23XX_PCI_CSR(0x0030)
+#define IXP23XX_PCI_OUT_INT_MASK IXP23XX_PCI_CSR(0x0034)
+#define IXP23XX_PCI_SRAM_BASE_ADDR_MASK IXP23XX_PCI_CSR(0x00fc)
+#define IXP23XX_PCI_DRAM_BASE_ADDR_MASK IXP23XX_PCI_CSR(0x0100)
+#define IXP23XX_PCI_CONTROL IXP23XX_PCI_CSR(0x013c)
+#define IXP23XX_PCI_ADDR_EXT IXP23XX_PCI_CSR(0x0140)
+#define IXP23XX_PCI_ME_PUSH_STATUS IXP23XX_PCI_CSR(0x0148)
+#define IXP23XX_PCI_ME_PUSH_EN IXP23XX_PCI_CSR(0x014c)
+#define IXP23XX_PCI_ERR_STATUS IXP23XX_PCI_CSR(0x0150)
+#define IXP23XX_PCI_ERROR_STATUS IXP23XX_PCI_CSR(0x0150)
+#define IXP23XX_PCI_ERR_ENABLE IXP23XX_PCI_CSR(0x0154)
+#define IXP23XX_PCI_XSCALE_INT_STATUS IXP23XX_PCI_CSR(0x0158)
+#define IXP23XX_PCI_XSCALE_INT_ENABLE IXP23XX_PCI_CSR(0x015c)
+#define IXP23XX_PCI_CPP_ADDR_BITS IXP23XX_PCI_CSR(0x0160)
+
+
+#ifndef __ASSEMBLY__
+/*
+ * Is system memory on the XSI or CPP bus?
+ */
+static inline unsigned ixp23xx_cpp_boot(void)
+{
+ return (*IXP23XX_EXP_CFG0 & IXP23XX_EXP_CFG0_XSI_NOT_PRES);
+}
+#endif
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/memory.h b/include/asm-arm/arch-ixp23xx/memory.h
new file mode 100644
index 00000000000..c85fc06a043
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/memory.h
@@ -0,0 +1,63 @@
+/*
+ * include/asm-arm/arch-ixp23xx/memory.h
+ *
+ * Copyright (c) 2003-2004 Intel 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.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#include <asm/hardware.h>
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET (0x00000000)
+
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ * address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ * to an address that the kernel can use.
+ */
+#ifndef __ASSEMBLY__
+#include <asm/mach-types.h>
+
+#define __virt_to_bus(v) \
+ ({ unsigned int ret; \
+ ret = ((__virt_to_phys(v) - 0x00000000) + \
+ (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0)); \
+ ret; })
+
+#define __bus_to_virt(b) \
+ ({ unsigned int data; \
+ data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR); \
+ __phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); })
+
+/*
+ * Coherency support. Only supported on A2 CPUs or on A1
+ * systems that have the cache coherency workaround.
+ */
+static inline int __ixp23xx_arch_is_coherent(void)
+{
+ extern unsigned int processor_id;
+
+ if (((processor_id & 15) >= 4) || machine_is_roadrunner())
+ return 1;
+
+ return 0;
+}
+
+#define arch_is_coherent() __ixp23xx_arch_is_coherent()
+
+#endif
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/platform.h b/include/asm-arm/arch-ixp23xx/platform.h
new file mode 100644
index 00000000000..e4d99060a04
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/platform.h
@@ -0,0 +1,32 @@
+/*
+ * include/asm-arm/arch-ixp23xx/platform.h
+ *
+ * Various bits of code used by platform-level code.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 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.
+ */
+
+#ifndef __ASSEMBLY__
+
+struct pci_sys_data;
+
+void ixp23xx_map_io(void);
+void ixp23xx_init_irq(void);
+void ixp23xx_sys_init(void);
+int ixp23xx_pci_setup(int, struct pci_sys_data *);
+void ixp23xx_pci_preinit(void);
+struct pci_bus *ixp23xx_pci_scan_bus(int, struct pci_sys_data*);
+void ixp23xx_pci_slave_init(void);
+
+extern struct sys_timer ixp23xx_timer;
+
+#define IXP23XX_UART_XTAL 14745600
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/system.h b/include/asm-arm/arch-ixp23xx/system.h
new file mode 100644
index 00000000000..925e6b0c338
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/system.h
@@ -0,0 +1,33 @@
+/*
+ * include/asm-arm/arch-ixp23xx/system.h
+ *
+ * Copyright (C) 2003 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+static inline void arch_idle(void)
+{
+#if 0
+ if (!hlt_counter)
+ cpu_do_idle();
+#endif
+}
+
+static inline void arch_reset(char mode)
+{
+ /* First try machine specific support */
+ if (machine_is_ixdp2351()) {
+ *IXDP2351_CPLD_RESET1_REG = IXDP2351_CPLD_RESET1_MAGIC;
+ (void) *IXDP2351_CPLD_RESET1_REG;
+ *IXDP2351_CPLD_RESET1_REG = IXDP2351_CPLD_RESET1_ENABLE;
+ }
+
+ /* Use on-chip reset capability */
+ *IXP23XX_RESET0 |= IXP23XX_RST_ALL;
+}
diff --git a/include/asm-arm/arch-ixp23xx/time.h b/include/asm-arm/arch-ixp23xx/time.h
new file mode 100644
index 00000000000..f6828fdd288
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/time.h
@@ -0,0 +1,3 @@
+/*
+ * include/asm-arm/arch-ixp23xx/time.h
+ */
diff --git a/include/asm-arm/arch-ixp23xx/timex.h b/include/asm-arm/arch-ixp23xx/timex.h
new file mode 100644
index 00000000000..516f72fe608
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/timex.h
@@ -0,0 +1,7 @@
+/*
+ * include/asm-arm/arch-ixp23xx/timex.h
+ *
+ * XScale architecture timex specifications
+ */
+
+#define CLOCK_TICK_RATE 75000000
diff --git a/include/asm-arm/arch-ixp23xx/uncompress.h b/include/asm-arm/arch-ixp23xx/uncompress.h
new file mode 100644
index 00000000000..013575e6a9a
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/uncompress.h
@@ -0,0 +1,40 @@
+/*
+ * include/asm-arm/arch-ixp23xx/uncompress.h
+ *
+ * Copyright (C) 2002-2004 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <asm/hardware.h>
+#include <linux/serial_reg.h>
+
+#define UART_BASE ((volatile u32 *)IXP23XX_UART1_PHYS)
+
+static inline void putc(char c)
+{
+ int j;
+
+ for (j = 0; j < 0x1000; j++) {
+ if (UART_BASE[UART_LSR] & UART_LSR_THRE)
+ break;
+ barrier();
+ }
+
+ UART_BASE[UART_TX] = c;
+}
+
+static inline void flush(void)
+{
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/vmalloc.h b/include/asm-arm/arch-ixp23xx/vmalloc.h
new file mode 100644
index 00000000000..9f256665854
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/vmalloc.h
@@ -0,0 +1,10 @@
+/*
+ * include/asm-arm/arch-ixp23xx/vmalloc.h
+ *
+ * Copyright (c) 2005 MontaVista Software, Inc.
+ *
+ * NPU mappings end at 0xf0000000 and we allocate 64MB for board
+ * specific static I/O.
+ */
+
+#define VMALLOC_END (0xec000000)
diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h
index 942b622455b..b59520e56fc 100644
--- a/include/asm-arm/arch-ixp4xx/io.h
+++ b/include/asm-arm/arch-ixp4xx/io.h
@@ -260,6 +260,12 @@ out:
#endif
+#ifndef CONFIG_PCI
+
+#define __io(v) v
+
+#else
+
/*
* IXP4xx does not have a transparent cpu -> PCI I/O translation
* window. Instead, it has a set of registers that must be tweaked
@@ -578,6 +584,7 @@ __ixp4xx_iowrite32_rep(void __iomem *addr, const void *vaddr, u32 count)
#define ioport_map(port, nr) ((void __iomem*)(port + PIO_OFFSET))
#define ioport_unmap(addr)
+#endif // !CONFIG_PCI
#endif // __ASM_ARM_ARCH_IO_H
diff --git a/include/asm-arm/arch-ixp4xx/memory.h b/include/asm-arm/arch-ixp4xx/memory.h
index ee211d28a3e..af9667b57ab 100644
--- a/include/asm-arm/arch-ixp4xx/memory.h
+++ b/include/asm-arm/arch-ixp4xx/memory.h
@@ -14,7 +14,7 @@
*/
#define PHYS_OFFSET UL(0x00000000)
-#ifndef __ASSEMBLY__
+#if !defined(__ASSEMBLY__) && defined(CONFIG_PCI)
void ixp4xx_adjust_zones(int node, unsigned long *size, unsigned long *holes);
diff --git a/include/asm-arm/arch-ixp4xx/uncompress.h b/include/asm-arm/arch-ixp4xx/uncompress.h
index 960c35810a2..09ae6c91be6 100644
--- a/include/asm-arm/arch-ixp4xx/uncompress.h
+++ b/include/asm-arm/arch-ixp4xx/uncompress.h
@@ -21,26 +21,18 @@
static volatile u32* uart_base;
-static __inline__ void putc(char c)
+static inline void putc(int c)
{
/* Check THRE and TEMT bits before we transmit the character.
*/
- while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE);
+ while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
+ barrier();
+
*uart_base = c;
}
-/*
- * This does not append a newline
- */
-static void putstr(const char *s)
+static void flush(void)
{
- while (*s)
- {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
static __inline__ void __arch_decomp_setup(unsigned long arch_id)
diff --git a/include/asm-arm/arch-l7200/hardware.h b/include/asm-arm/arch-l7200/hardware.h
index b755079befa..2ab43f3a4a8 100644
--- a/include/asm-arm/arch-l7200/hardware.h
+++ b/include/asm-arm/arch-l7200/hardware.h
@@ -52,9 +52,6 @@
#define ISA_SIZE 0x20000000
#define ISA_BASE 0xe0000000
-#define FLUSH_BASE_PHYS 0x40000000 /* ROM */
-#define FLUSH_BASE 0xdf000000
-
#define PCIO_BASE IO_BASE
#endif
diff --git a/include/asm-arm/arch-l7200/memory.h b/include/asm-arm/arch-l7200/memory.h
index 9e50a171f78..402df637e74 100644
--- a/include/asm-arm/arch-l7200/memory.h
+++ b/include/asm-arm/arch-l7200/memory.h
@@ -20,4 +20,10 @@
#define __virt_to_bus(x) __virt_to_phys(x)
#define __bus_to_virt(x) __phys_to_virt(x)
+/*
+ * Cache flushing area - ROM
+ */
+#define FLUSH_BASE_PHYS 0x40000000
+#define FLUSH_BASE 0xdf000000
+
#endif
diff --git a/include/asm-arm/arch-l7200/serial_l7200.h b/include/asm-arm/arch-l7200/serial_l7200.h
index 238c595d97e..b1008a9d23e 100644
--- a/include/asm-arm/arch-l7200/serial_l7200.h
+++ b/include/asm-arm/arch-l7200/serial_l7200.h
@@ -28,7 +28,7 @@
#define UARTDR 0x00 /* Tx/Rx data */
#define RXSTAT 0x04 /* Rx status */
#define H_UBRLCR 0x08 /* mode register high */
-#define M_UBRLCR 0x0C /* mode reg mid (MSB of buad)*/
+#define M_UBRLCR 0x0C /* mode reg mid (MSB of baud)*/
#define L_UBRLCR 0x10 /* mode reg low (LSB of baud)*/
#define UARTCON 0x14 /* control register */
#define UARTFLG 0x18 /* flag register */
diff --git a/include/asm-arm/arch-l7200/uncompress.h b/include/asm-arm/arch-l7200/uncompress.h
index 1caa2b560f5..04be2a08863 100644
--- a/include/asm-arm/arch-l7200/uncompress.h
+++ b/include/asm-arm/arch-l7200/uncompress.h
@@ -6,7 +6,7 @@
* Changelog:
* 05-01-2000 SJH Created
* 05-13-2000 SJH Filled in function bodies
- * 07-26-2000 SJH Removed hard coded buad rate
+ * 07-26-2000 SJH Removed hard coded baud rate
*/
#include <asm/hardware.h>
@@ -16,22 +16,17 @@
#define __raw_writeb(v,p) (*(volatile unsigned char *)(p) = (v))
#define __raw_readb(p) (*(volatile unsigned char *)(p))
-static __inline__ void putc(char c)
+static inline void putc(int c)
{
while(__raw_readb(IO_UART + 0x18) & 0x20 ||
- __raw_readb(IO_UART + 0x18) & 0x08);
+ __raw_readb(IO_UART + 0x18) & 0x08)
+ barrier();
+
__raw_writeb(c, IO_UART + 0x00);
}
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- if (*s == 10) { /* If a LF, add CR */
- putc(10);
- putc(13);
- }
- putc(*(s++));
- }
}
static __inline__ void arch_decomp_setup(void)
diff --git a/include/asm-arm/arch-lh7a40x/memory.h b/include/asm-arm/arch-lh7a40x/memory.h
index c92bcb83762..9f1a58cbf40 100644
--- a/include/asm-arm/arch-lh7a40x/memory.h
+++ b/include/asm-arm/arch-lh7a40x/memory.h
@@ -31,8 +31,6 @@
#ifdef CONFIG_DISCONTIGMEM
-#define NODES_SHIFT 4 /* Up to 16 nodes */
-
/*
* Given a kernel address, find the home node of the underlying memory.
*/
diff --git a/include/asm-arm/arch-lh7a40x/uncompress.h b/include/asm-arm/arch-lh7a40x/uncompress.h
index ec8ab67122f..f8053346f60 100644
--- a/include/asm-arm/arch-lh7a40x/uncompress.h
+++ b/include/asm-arm/arch-lh7a40x/uncompress.h
@@ -22,20 +22,15 @@
#define UART_STATUS (*(volatile unsigned long*) (UART2_PHYS + UART_R_STATUS))
#define UART_DATA (*(volatile unsigned long*) (UART2_PHYS + UART_R_DATA))
-static __inline__ void putc (char ch)
+static inline void putc(int ch)
{
while (UART_STATUS & nTxRdy)
- ;
+ barrier();
UART_DATA = ch;
}
-static void putstr (const char* sz)
+static inline void flush(void)
{
- for (; *sz; ++sz) {
- putc (*sz);
- if (*sz == '\n')
- putc ('\r');
- }
}
/* NULL functions; we don't presently need them */
diff --git a/include/asm-arm/arch-omap/aic23.h b/include/asm-arm/arch-omap/aic23.h
index 590bac25b7c..6513065941d 100644
--- a/include/asm-arm/arch-omap/aic23.h
+++ b/include/asm-arm/arch-omap/aic23.h
@@ -57,6 +57,7 @@
#define LHV_MIN 0x0000
// Analog audio path control register
+#define STA_REG(x) ((x)<<6)
#define STE_ENABLED 0x0020
#define DAC_SELECTED 0x0010
#define BYPASS_ON 0x0008
@@ -109,4 +110,7 @@
#define TLV320AIC23ID1 (0x1a) // cs low
#define TLV320AIC23ID2 (0x1b) // cs high
+void tlv320aic23_power_up(void);
+void tlv320aic23_power_down(void);
+
#endif /* __ASM_ARCH_AIC23_H */
diff --git a/include/asm-arm/arch-omap/board-ams-delta.h b/include/asm-arm/arch-omap/board-ams-delta.h
new file mode 100644
index 00000000000..0070f6d3b75
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-ams-delta.h
@@ -0,0 +1,65 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-ams-delta.h
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __ASM_ARCH_OMAP_AMS_DELTA_H
+#define __ASM_ARCH_OMAP_AMS_DELTA_H
+
+#if defined (CONFIG_MACH_AMS_DELTA)
+
+#define AMS_DELTA_LATCH1_PHYS 0x01000000
+#define AMS_DELTA_LATCH1_VIRT 0xEA000000
+#define AMS_DELTA_MODEM_PHYS 0x04000000
+#define AMS_DELTA_MODEM_VIRT 0xEB000000
+#define AMS_DELTA_LATCH2_PHYS 0x08000000
+#define AMS_DELTA_LATCH2_VIRT 0xEC000000
+
+#define AMS_DELTA_LATCH1_LED_CAMERA 0x01
+#define AMS_DELTA_LATCH1_LED_ADVERT 0x02
+#define AMS_DELTA_LATCH1_LED_EMAIL 0x04
+#define AMS_DELTA_LATCH1_LED_HANDSFREE 0x08
+#define AMS_DELTA_LATCH1_LED_VOICEMAIL 0x10
+#define AMS_DELTA_LATCH1_LED_VOICE 0x20
+
+#define AMS_DELTA_LATCH2_LCD_VBLEN 0x0001
+#define AMS_DELTA_LATCH2_LCD_NDISP 0x0002
+#define AMS_DELTA_LATCH2_NAND_NCE 0x0004
+#define AMS_DELTA_LATCH2_NAND_NRE 0x0008
+#define AMS_DELTA_LATCH2_NAND_NWP 0x0010
+#define AMS_DELTA_LATCH2_NAND_NWE 0x0020
+#define AMS_DELTA_LATCH2_NAND_ALE 0x0040
+#define AMS_DELTA_LATCH2_NAND_CLE 0x0080
+#define AMS_DELTA_LATCH2_MODEM_NRESET 0x1000
+#define AMS_DELTA_LATCH2_MODEM_CODEC 0x2000
+
+#define AMS_DELTA_GPIO_PIN_NAND_RB 12
+
+#ifndef __ASSEMBLY__
+void ams_delta_latch1_write(u8 mask, u8 value);
+void ams_delta_latch2_write(u16 mask, u16 value);
+#endif
+
+#endif /* CONFIG_MACH_AMS_DELTA */
+
+#endif /* __ASM_ARCH_OMAP_AMS_DELTA_H */
diff --git a/include/asm-arm/arch-omap/board-apollon.h b/include/asm-arm/arch-omap/board-apollon.h
new file mode 100644
index 00000000000..de0c5b792c5
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-apollon.h
@@ -0,0 +1,45 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-apollon.h
+ *
+ * Hardware definitions for Samsung OMAP24XX Apollon board.
+ *
+ * Initial creation by Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_ARCH_OMAP_APOLLON_H
+#define __ASM_ARCH_OMAP_APOLLON_H
+
+/* Placeholder for APOLLON specific defines */
+/* GPMC CS0 */
+#define APOLLON_CS0_BASE 0x00000000
+/* GPMC CS1 */
+#define APOLLON_CS1_BASE 0x08000000
+#define APOLLON_ETHR_START (APOLLON_CS1_BASE + 0x300)
+#define APOLLON_ETHR_GPIO_IRQ 74
+/* GPMC CS2 - reserved for OneNAND */
+#define APOLLON_CS2_BASE 0x10000000
+/* GPMC CS3 - reserved for NOR or NAND */
+#define APOLLON_CS3_BASE 0x18000000
+
+#endif /* __ASM_ARCH_OMAP_APOLLON_H */
+
diff --git a/include/asm-arm/arch-omap/board-h2.h b/include/asm-arm/arch-omap/board-h2.h
index 39ca5a31aee..b2888ef9e9b 100644
--- a/include/asm-arm/arch-omap/board-h2.h
+++ b/include/asm-arm/arch-omap/board-h2.h
@@ -34,9 +34,5 @@
/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
#define OMAP1610_ETHR_START 0x04000300
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1 0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2 0x0C000000 /* CS3 */
-
#endif /* __ASM_ARCH_OMAP_H2_H */
diff --git a/include/asm-arm/arch-omap/board-h3.h b/include/asm-arm/arch-omap/board-h3.h
index 1b12c1dcc2f..761ea0a1789 100644
--- a/include/asm-arm/arch-omap/board-h3.h
+++ b/include/asm-arm/arch-omap/board-h3.h
@@ -30,10 +30,6 @@
/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
#define OMAP1710_ETHR_START 0x04000300
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1 0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2 0x0C000000 /* CS3 */
-
#define MAXIRQNUM (IH_BOARD_BASE)
#define MAXFIQNUM MAXIRQNUM
#define MAXSWINUM MAXIRQNUM
diff --git a/include/asm-arm/arch-omap/board-h4.h b/include/asm-arm/arch-omap/board-h4.h
index 33ea29a4165..7ef664bc9e3 100644
--- a/include/asm-arm/arch-omap/board-h4.h
+++ b/include/asm-arm/arch-omap/board-h4.h
@@ -33,12 +33,6 @@
/* GPMC CS1 */
#define OMAP24XX_ETHR_START 0x08000300
#define OMAP24XX_ETHR_GPIO_IRQ 92
-
-#define H4_CS0_BASE 0x04000000
-
-#define H4_CS0_BASE 0x04000000
-
-#define H4_CS0_BASE 0x04000000
-
+#define H4_CS0_BASE 0x04000000
#endif /* __ASM_ARCH_OMAP_H4_H */
diff --git a/include/asm-arm/arch-omap/board-netstar.h b/include/asm-arm/arch-omap/board-netstar.h
deleted file mode 100644
index 77cc0fb54d5..00000000000
--- a/include/asm-arm/arch-omap/board-netstar.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
- *
- * Hardware definitions for OMAP5910 based NetStar board.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_NETSTAR_H
-#define __ASM_ARCH_NETSTAR_H
-
-#include <asm/arch/tc.h>
-
-#define OMAP_NAND_FLASH_START1 OMAP_CS1_PHYS + (1 << 23)
-#define OMAP_NAND_FLASH_START2 OMAP_CS1_PHYS + (2 << 23)
-
-#endif /* __ASM_ARCH_NETSTAR_H */
diff --git a/include/asm-arm/arch-omap/board-nokia.h b/include/asm-arm/arch-omap/board-nokia.h
new file mode 100644
index 00000000000..72deea20349
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-nokia.h
@@ -0,0 +1,54 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-nokia.h
+ *
+ * Information structures for Nokia-specific board config data
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ */
+
+#ifndef _OMAP_BOARD_NOKIA_H
+#define _OMAP_BOARD_NOKIA_H
+
+#include <linux/types.h>
+
+#define OMAP_TAG_NOKIA_BT 0x4e01
+#define OMAP_TAG_WLAN_CX3110X 0x4e02
+#define OMAP_TAG_CBUS 0x4e03
+#define OMAP_TAG_EM_ASIC_BB5 0x4e04
+
+
+#define BT_CHIP_CSR 1
+#define BT_CHIP_TI 2
+
+#define BT_SYSCLK_12 1
+#define BT_SYSCLK_38_4 2
+
+struct omap_bluetooth_config {
+ u8 chip_type;
+ u8 bt_wakeup_gpio;
+ u8 host_wakeup_gpio;
+ u8 reset_gpio;
+ u8 bt_uart;
+ u8 bd_addr[6];
+ u8 bt_sysclk;
+};
+
+struct omap_wlan_cx3110x_config {
+ u8 chip_type;
+ s16 power_gpio;
+ s16 irq_gpio;
+ s16 spi_cs_gpio;
+};
+
+struct omap_cbus_config {
+ s16 clk_gpio;
+ s16 dat_gpio;
+ s16 sel_gpio;
+};
+
+struct omap_em_asic_bb5_config {
+ s16 retu_irq_gpio;
+ s16 tahvo_irq_gpio;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/board-perseus2.h b/include/asm-arm/arch-omap/board-perseus2.h
index 691e52a52b4..eb74420cb43 100644
--- a/include/asm-arm/arch-omap/board-perseus2.h
+++ b/include/asm-arm/arch-omap/board-perseus2.h
@@ -42,8 +42,4 @@
#define NR_IRQS (MAXIRQNUM + 1)
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1 0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2 0x0C000000 /* CS3 */
-
#endif
diff --git a/include/asm-arm/arch-omap/board.h b/include/asm-arm/arch-omap/board.h
index a0040cd8663..6d6240a4681 100644
--- a/include/asm-arm/arch-omap/board.h
+++ b/include/asm-arm/arch-omap/board.h
@@ -21,9 +21,12 @@
#define OMAP_TAG_LCD 0x4f05
#define OMAP_TAG_GPIO_SWITCH 0x4f06
#define OMAP_TAG_UART 0x4f07
+#define OMAP_TAG_FBMEM 0x4f08
+#define OMAP_TAG_STI_CONSOLE 0x4f09
#define OMAP_TAG_BOOT_REASON 0x4f80
#define OMAP_TAG_FLASH_PART 0x4f81
+#define OMAP_TAG_VERSION_STR 0x4f82
struct omap_clock_config {
/* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */
@@ -54,6 +57,11 @@ struct omap_serial_console_config {
u32 console_speed;
};
+struct omap_sti_console_config {
+ unsigned enable:1;
+ u8 channel;
+};
+
struct omap_usb_config {
/* Configure drivers according to the connectors on your board:
* - "A" connector (rectagular)
@@ -87,6 +95,13 @@ struct omap_lcd_config {
char ctrl_name[16];
};
+struct omap_fbmem_config {
+ u32 fb_sram_start;
+ u32 fb_sram_size;
+ u32 fb_sdram_start;
+ u32 fb_sdram_size;
+};
+
/* Cover:
* high -> closed
* low -> open
@@ -106,6 +121,12 @@ struct omap_gpio_switch_config {
int key_code:24; /* Linux key code */
};
+struct omap_uart_config {
+ /* Bit field of UARTs present; bit 0 --> UART1 */
+ unsigned int enabled_uarts;
+};
+
+
struct omap_flash_part_config {
char part_table[0];
};
@@ -114,11 +135,14 @@ struct omap_boot_reason_config {
char reason_str[12];
};
-struct omap_uart_config {
- /* Bit field of UARTs present; bit 0 --> UART1 */
- unsigned int enabled_uarts;
+struct omap_version_config {
+ char component[12];
+ char version[12];
};
+
+#include <asm-arm/arch-omap/board-nokia.h>
+
struct omap_board_config_entry {
u16 tag;
u16 len;
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
index 46a0402696d..3c4eb9fbe48 100644
--- a/include/asm-arm/arch-omap/clock.h
+++ b/include/asm-arm/arch-omap/clock.h
@@ -19,6 +19,7 @@ struct clk {
struct list_head node;
struct module *owner;
const char *name;
+ int id;
struct clk *parent;
unsigned long rate;
__u32 flags;
@@ -57,6 +58,7 @@ extern void propagate_rate(struct clk *clk);
extern void followparent_recalc(struct clk * clk);
extern void clk_allow_idle(struct clk *clk);
extern void clk_deny_idle(struct clk *clk);
+extern int clk_get_usecount(struct clk *clk);
/* Clock flags */
#define RATE_CKCTL (1 << 0) /* Main fixed ratio clocks */
@@ -80,10 +82,11 @@ extern void clk_deny_idle(struct clk *clk);
#define CM_PLL_SEL1 (1 << 18)
#define CM_PLL_SEL2 (1 << 19)
#define CM_SYSCLKOUT_SEL1 (1 << 20)
-#define CLOCK_IN_OMAP730 (1 << 21)
-#define CLOCK_IN_OMAP1510 (1 << 22)
-#define CLOCK_IN_OMAP16XX (1 << 23)
-#define CLOCK_IN_OMAP242X (1 << 24)
-#define CLOCK_IN_OMAP243X (1 << 25)
+#define CLOCK_IN_OMAP310 (1 << 21)
+#define CLOCK_IN_OMAP730 (1 << 22)
+#define CLOCK_IN_OMAP1510 (1 << 23)
+#define CLOCK_IN_OMAP16XX (1 << 24)
+#define CLOCK_IN_OMAP242X (1 << 25)
+#define CLOCK_IN_OMAP243X (1 << 26)
#endif
diff --git a/include/asm-arm/arch-omap/dma.h b/include/asm-arm/arch-omap/dma.h
index d4e73efcb81..ca1202312a4 100644
--- a/include/asm-arm/arch-omap/dma.h
+++ b/include/asm-arm/arch-omap/dma.h
@@ -404,6 +404,7 @@ extern void omap_free_lcd_dma(void);
extern void omap_setup_lcd_dma(void);
extern void omap_enable_lcd_dma(void);
extern void omap_stop_lcd_dma(void);
+extern int omap_lcd_dma_ext_running(void);
extern void omap_set_lcd_dma_ext_controller(int external);
extern void omap_set_lcd_dma_single_transfer(int single);
extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
diff --git a/include/asm-arm/arch-omap/dmtimer.h b/include/asm-arm/arch-omap/dmtimer.h
index 11772c792f3..e6522e6a383 100644
--- a/include/asm-arm/arch-omap/dmtimer.h
+++ b/include/asm-arm/arch-omap/dmtimer.h
@@ -88,5 +88,6 @@ unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
void omap_dm_timer_reset_counter(struct omap_dm_timer *timer);
int omap_dm_timers_active(void);
+u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
#endif /* __ASM_ARCH_TIMER_H */
diff --git a/include/asm-arm/arch-omap/dsp.h b/include/asm-arm/arch-omap/dsp.h
index 57bf4f39ca5..06dad83dd41 100644
--- a/include/asm-arm/arch-omap/dsp.h
+++ b/include/asm-arm/arch-omap/dsp.h
@@ -181,10 +181,16 @@ struct omap_dsp_varinfo {
#define OMAP_DSP_MBCMD_PM_ENABLE 0x01
#define OMAP_DSP_MBCMD_KFUNC_FBCTL 0x00
+#define OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR 0x01
+#define OMAP_DSP_MBCMD_FBCTL_UPD 0x0000
#define OMAP_DSP_MBCMD_FBCTL_ENABLE 0x0002
#define OMAP_DSP_MBCMD_FBCTL_DISABLE 0x0003
+#define OMAP_DSP_MBCMD_AUDIO_PWR_UP 0x0000
+#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN1 0x0001
+#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN2 0x0002
+
#define OMAP_DSP_MBCMD_TDEL_SAFE 0x0000
#define OMAP_DSP_MBCMD_TDEL_KILL 0x0001
diff --git a/include/asm-arm/arch-omap/dsp_common.h b/include/asm-arm/arch-omap/dsp_common.h
index 4fcce694405..16a459dfa71 100644
--- a/include/asm-arm/arch-omap/dsp_common.h
+++ b/include/asm-arm/arch-omap/dsp_common.h
@@ -27,11 +27,12 @@
#ifndef ASM_ARCH_DSP_COMMON_H
#define ASM_ARCH_DSP_COMMON_H
-void omap_dsp_pm_suspend(void);
-void omap_dsp_pm_resume(void);
-void omap_dsp_request_mpui(void);
-void omap_dsp_release_mpui(void);
-int omap_dsp_request_mem(void);
-int omap_dsp_release_mem(void);
+extern void omap_dsp_request_mpui(void);
+extern void omap_dsp_release_mpui(void);
+extern int omap_dsp_request_mem(void);
+extern int omap_dsp_release_mem(void);
+
+extern void (*omap_dsp_audio_pwr_up_request)(int stage);
+extern void (*omap_dsp_audio_pwr_down_request)(int stage);
#endif /* ASM_ARCH_DSP_COMMON_H */
diff --git a/include/asm-arm/arch-omap/gpioexpander.h b/include/asm-arm/arch-omap/gpioexpander.h
new file mode 100644
index 00000000000..7a43b0a912e
--- /dev/null
+++ b/include/asm-arm/arch-omap/gpioexpander.h
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-arm/arch-omap/gpioexpander.h
+ *
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __ASM_ARCH_OMAP_GPIOEXPANDER_H
+#define __ASM_ARCH_OMAP_GPIOEXPANDER_H
+
+/* Function Prototypes for GPIO Expander functions */
+
+int read_gpio_expa(u8 *, int);
+int write_gpio_expa(u8 , int);
+
+#endif /* __ASM_ARCH_OMAP_GPIOEXPANDER_H */
diff --git a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h
index 5406b875c42..7909b729826 100644
--- a/include/asm-arm/arch-omap/hardware.h
+++ b/include/asm-arm/arch-omap/hardware.h
@@ -306,6 +306,10 @@
#include "board-h4.h"
#endif
+#ifdef CONFIG_MACH_OMAP_APOLLON
+#include "board-apollon.h"
+#endif
+
#ifdef CONFIG_MACH_OMAP_OSK
#include "board-osk.h"
#endif
@@ -314,10 +318,6 @@
#include "board-voiceblue.h"
#endif
-#ifdef CONFIG_MACH_NETSTAR
-#include "board-netstar.h"
-#endif
-
#endif /* !__ASSEMBLER__ */
#endif /* __ASM_ARCH_OMAP_HARDWARE_H */
diff --git a/include/asm-arm/arch-omap/irda.h b/include/asm-arm/arch-omap/irda.h
new file mode 100644
index 00000000000..805ae3575e4
--- /dev/null
+++ b/include/asm-arm/arch-omap/irda.h
@@ -0,0 +1,36 @@
+/*
+ * linux/include/asm-arm/arch-omap/irda.h
+ *
+ * Copyright (C) 2005-2006 Komal Shah <komal_shah802003@yahoo.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 ASMARM_ARCH_IRDA_H
+#define ASMARM_ARCH_IRDA_H
+
+/* board specific transceiver capabilities */
+
+#define IR_SEL 1 /* Selects IrDA */
+#define IR_SIRMODE 2
+#define IR_FIRMODE 4
+#define IR_MIRMODE 8
+
+struct omap_irda_config {
+ int transceiver_cap;
+ int (*transceiver_mode)(struct device *dev, int mode);
+ int (*select_irda)(struct device *dev, int state);
+ /* Very specific to the needs of some platforms (h3,h4)
+ * having calls which can sleep in irda_set_speed.
+ */
+ struct work_struct gpio_expa;
+ int rx_channel;
+ int tx_channel;
+ unsigned long dest_start;
+ unsigned long src_start;
+ int tx_trigger;
+ int rx_trigger;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/irqs.h b/include/asm-arm/arch-omap/irqs.h
index 4ffce1d7775..42098d99f30 100644
--- a/include/asm-arm/arch-omap/irqs.h
+++ b/include/asm-arm/arch-omap/irqs.h
@@ -242,6 +242,11 @@
#define INT_24XX_GPIO_BANK2 30
#define INT_24XX_GPIO_BANK3 31
#define INT_24XX_GPIO_BANK4 32
+#define INT_24XX_MCBSP1_IRQ_TX 59
+#define INT_24XX_MCBSP1_IRQ_RX 60
+#define INT_24XX_MCBSP2_IRQ_TX 62
+#define INT_24XX_MCBSP2_IRQ_RX 63
+#define INT_24XX_UART3_IRQ 74
/* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
* 16 MPUIO lines */
diff --git a/include/asm-arm/arch-omap/keypad.h b/include/asm-arm/arch-omap/keypad.h
new file mode 100644
index 00000000000..8a023a984ac
--- /dev/null
+++ b/include/asm-arm/arch-omap/keypad.h
@@ -0,0 +1,36 @@
+/*
+ * linux/include/asm-arm/arch-omap/keypad.h
+ *
+ * Copyright (C) 2006 Komal Shah <komal_shah802003@yahoo.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 ASMARM_ARCH_KEYPAD_H
+#define ASMARM_ARCH_KEYPAD_H
+
+struct omap_kp_platform_data {
+ int rows;
+ int cols;
+ int *keymap;
+ unsigned int rep:1;
+ /* specific to OMAP242x*/
+ unsigned int *row_gpios;
+ unsigned int *col_gpios;
+};
+
+/* Group (0..3) -- when multiple keys are pressed, only the
+ * keys pressed in the same group are considered as pressed. This is
+ * in order to workaround certain crappy HW designs that produce ghost
+ * keypresses. */
+#define GROUP_0 (0 << 16)
+#define GROUP_1 (1 << 16)
+#define GROUP_2 (2 << 16)
+#define GROUP_3 (3 << 16)
+#define GROUP_MASK GROUP_3
+
+#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
+
+#endif
+
diff --git a/include/asm-arm/arch-omap/lcd_lph8923.h b/include/asm-arm/arch-omap/lcd_lph8923.h
new file mode 100644
index 00000000000..004e67e22ca
--- /dev/null
+++ b/include/asm-arm/arch-omap/lcd_lph8923.h
@@ -0,0 +1,14 @@
+#ifndef __LCD_LPH8923_H
+#define __LCD_LPH8923_H
+
+enum lcd_lph8923_test_num {
+ LCD_LPH8923_TEST_RGB_LINES,
+};
+
+enum lcd_lph8923_test_result {
+ LCD_LPH8923_TEST_SUCCESS,
+ LCD_LPH8923_TEST_INVALID,
+ LCD_LPH8923_TEST_FAILED,
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/mcbsp.h b/include/asm-arm/arch-omap/mcbsp.h
index e79d98ab2ab..ed0dde4f721 100644
--- a/include/asm-arm/arch-omap/mcbsp.h
+++ b/include/asm-arm/arch-omap/mcbsp.h
@@ -37,6 +37,11 @@
#define OMAP1610_MCBSP2_BASE 0xfffb1000
#define OMAP1610_MCBSP3_BASE 0xe1017000
+#define OMAP24XX_MCBSP1_BASE 0x48074000
+#define OMAP24XX_MCBSP2_BASE 0x48076000
+
+#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730)
+
#define OMAP_MCBSP_REG_DRR2 0x00
#define OMAP_MCBSP_REG_DRR1 0x02
#define OMAP_MCBSP_REG_DXR2 0x04
@@ -71,9 +76,62 @@
#define OMAP_MAX_MCBSP_COUNT 3
+#define AUDIO_MCBSP_DATAWRITE (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1)
+#define AUDIO_MCBSP_DATAREAD (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1)
+
+#define AUDIO_MCBSP OMAP_MCBSP1
+#define AUDIO_DMA_TX OMAP_DMA_MCBSP1_TX
+#define AUDIO_DMA_RX OMAP_DMA_MCBSP1_RX
+
+#elif defined(CONFIG_ARCH_OMAP24XX)
+
+#define OMAP_MCBSP_REG_DRR2 0x00
+#define OMAP_MCBSP_REG_DRR1 0x04
+#define OMAP_MCBSP_REG_DXR2 0x08
+#define OMAP_MCBSP_REG_DXR1 0x0C
+#define OMAP_MCBSP_REG_SPCR2 0x10
+#define OMAP_MCBSP_REG_SPCR1 0x14
+#define OMAP_MCBSP_REG_RCR2 0x18
+#define OMAP_MCBSP_REG_RCR1 0x1C
+#define OMAP_MCBSP_REG_XCR2 0x20
+#define OMAP_MCBSP_REG_XCR1 0x24
+#define OMAP_MCBSP_REG_SRGR2 0x28
+#define OMAP_MCBSP_REG_SRGR1 0x2C
+#define OMAP_MCBSP_REG_MCR2 0x30
+#define OMAP_MCBSP_REG_MCR1 0x34
+#define OMAP_MCBSP_REG_RCERA 0x38
+#define OMAP_MCBSP_REG_RCERB 0x3C
+#define OMAP_MCBSP_REG_XCERA 0x40
+#define OMAP_MCBSP_REG_XCERB 0x44
+#define OMAP_MCBSP_REG_PCR0 0x48
+#define OMAP_MCBSP_REG_RCERC 0x4C
+#define OMAP_MCBSP_REG_RCERD 0x50
+#define OMAP_MCBSP_REG_XCERC 0x54
+#define OMAP_MCBSP_REG_XCERD 0x58
+#define OMAP_MCBSP_REG_RCERE 0x5C
+#define OMAP_MCBSP_REG_RCERF 0x60
+#define OMAP_MCBSP_REG_XCERE 0x64
+#define OMAP_MCBSP_REG_XCERF 0x68
+#define OMAP_MCBSP_REG_RCERG 0x6C
+#define OMAP_MCBSP_REG_RCERH 0x70
+#define OMAP_MCBSP_REG_XCERG 0x74
+#define OMAP_MCBSP_REG_XCERH 0x78
+
+#define OMAP_MAX_MCBSP_COUNT 2
+
+#define AUDIO_MCBSP_DATAWRITE (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1)
+#define AUDIO_MCBSP_DATAREAD (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1)
+
+#define AUDIO_MCBSP OMAP_MCBSP2
+#define AUDIO_DMA_TX OMAP24XX_DMA_MCBSP2_TX
+#define AUDIO_DMA_RX OMAP24XX_DMA_MCBSP2_RX
+
+#endif
+
#define OMAP_MCBSP_READ(base, reg) __raw_readw((base) + OMAP_MCBSP_REG_##reg)
#define OMAP_MCBSP_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MCBSP_REG_##reg)
+
/************************** McBSP SPCR1 bit definitions ***********************/
#define RRST 0x0001
#define RRDY 0x0002
@@ -195,6 +253,10 @@ typedef enum {
OMAP_MCBSP3,
} omap_mcbsp_id;
+typedef int __bitwise omap_mcbsp_io_type_t;
+#define OMAP_MCBSP_IRQ_IO ((__force omap_mcbsp_io_type_t) 1)
+#define OMAP_MCBSP_POLL_IO ((__force omap_mcbsp_io_type_t) 2)
+
typedef enum {
OMAP_MCBSP_WORD_8 = 0,
OMAP_MCBSP_WORD_12,
@@ -246,6 +308,9 @@ u32 omap_mcbsp_recv_word(unsigned int id);
int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
+int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word);
+int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word);
+
/* SPI specific API */
void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
diff --git a/include/asm-arm/arch-omap/mcspi.h b/include/asm-arm/arch-omap/mcspi.h
new file mode 100644
index 00000000000..9e7f40a88e1
--- /dev/null
+++ b/include/asm-arm/arch-omap/mcspi.h
@@ -0,0 +1,16 @@
+#ifndef _OMAP2_MCSPI_H
+#define _OMAP2_MCSPI_H
+
+struct omap2_mcspi_platform_config {
+ unsigned long base;
+ unsigned short num_cs;
+};
+
+struct omap2_mcspi_device_config {
+ unsigned turbo_mode:1;
+
+ /* Do we want one channel enabled at the same time? */
+ unsigned single_channel:1;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/menelaus.h b/include/asm-arm/arch-omap/menelaus.h
index 46be8b8d634..88cd4c87f0d 100644
--- a/include/asm-arm/arch-omap/menelaus.h
+++ b/include/asm-arm/arch-omap/menelaus.h
@@ -7,7 +7,7 @@
#ifndef __ASM_ARCH_MENELAUS_H
#define __ASM_ARCH_MENELAUS_H
-extern void menelaus_mmc_register(void (*callback)(u8 card_mask),
+extern void menelaus_mmc_register(void (*callback)(unsigned long data, u8 card_mask),
unsigned long data);
extern void menelaus_mmc_remove(void);
extern void menelaus_mmc_opendrain(int enable);
diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
index 13415a9aab0..0dc24d4ba59 100644
--- a/include/asm-arm/arch-omap/mux.h
+++ b/include/asm-arm/arch-omap/mux.h
@@ -112,14 +112,13 @@
* as mux config
*/
#define MUX_CFG_730(desc, mux_reg, mode_offset, mode, \
- pull_reg, pull_bit, pull_status, \
- pu_pd_reg, pu_pd_status, debug_status)\
+ pull_bit, pull_status, debug_status)\
{ \
.name = desc, \
.debug = debug_status, \
MUX_REG_730(mux_reg, mode_offset, mode) \
PULL_REG_730(mux_reg, pull_bit, pull_status) \
- PU_PD_REG(pu_pd_reg, pu_pd_status) \
+ PU_PD_REG(NA, 0) \
},
#define MUX_CFG_24XX(desc, reg_offset, mode, \
@@ -172,6 +171,11 @@ enum omap730_index {
E4_730_KBC2,
F4_730_KBC3,
E3_730_KBC4,
+
+ /* USB */
+ AA17_730_USB_DM,
+ W16_730_USB_PU_EN,
+ W17_730_USB_VBUSI,
};
enum omap1xxx_index {
@@ -403,9 +407,53 @@ enum omap24xx_index {
/* 24xx Menelaus interrupt */
W19_24XX_SYS_NIRQ,
+ /* 24xx clock */
+ W14_24XX_SYS_CLKOUT,
+
+ /* 242X McBSP */
+ Y15_24XX_MCBSP2_CLKX,
+ R14_24XX_MCBSP2_FSX,
+ W15_24XX_MCBSP2_DR,
+ V15_24XX_MCBSP2_DX,
+
/* 24xx GPIO */
+ M21_242X_GPIO11,
+ AA10_242X_GPIO13,
+ AA6_242X_GPIO14,
+ AA4_242X_GPIO15,
+ Y11_242X_GPIO16,
+ AA12_242X_GPIO17,
+ AA8_242X_GPIO58,
Y20_24XX_GPIO60,
+ W4__24XX_GPIO74,
M15_24XX_GPIO92,
+ V14_24XX_GPIO117,
+
+ P20_24XX_TSC_IRQ,
+
+ /* UART3 */
+ K15_24XX_UART3_TX,
+ K14_24XX_UART3_RX,
+
+ /* Keypad GPIO*/
+ T19_24XX_KBR0,
+ R19_24XX_KBR1,
+ V18_24XX_KBR2,
+ M21_24XX_KBR3,
+ E5__24XX_KBR4,
+ M18_24XX_KBR5,
+ R20_24XX_KBC0,
+ M14_24XX_KBC1,
+ H19_24XX_KBC2,
+ V17_24XX_KBC3,
+ P21_24XX_KBC4,
+ L14_24XX_KBC5,
+ N19_24XX_KBC6,
+
+ /* 24xx Menelaus Keypad GPIO */
+ B3__24XX_KBR5,
+ AA4_24XX_KBC2,
+ B13_24XX_KBC6,
};
#ifdef CONFIG_OMAP_MUX
diff --git a/include/asm-arm/arch-omap/omap-alsa.h b/include/asm-arm/arch-omap/omap-alsa.h
new file mode 100644
index 00000000000..df4695474e3
--- /dev/null
+++ b/include/asm-arm/arch-omap/omap-alsa.h
@@ -0,0 +1,124 @@
+/*
+ * linux/include/asm-arm/arch-omap/omap-alsa.h
+ *
+ * Alsa Driver for AIC23 and TSC2101 codecs on OMAP platform boards.
+ *
+ * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
+ *
+ * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
+ * Written by Daniel Petrini, David Cohen, Anderson Briglia
+ * {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * History
+ * -------
+ *
+ * 2005/07/25 INdT-10LE Kernel Team - Alsa driver for omap osk,
+ * original version based in sa1100 driver
+ * and omap oss driver.
+ */
+
+#ifndef __OMAP_ALSA_H
+#define __OMAP_ALSA_H
+
+#include <sound/driver.h>
+#include <asm/arch/dma.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <asm/arch/mcbsp.h>
+#include <linux/platform_device.h>
+
+#define DMA_BUF_SIZE (1024 * 8)
+
+/*
+ * Buffer management for alsa and dma
+ */
+struct audio_stream {
+ char *id; /* identification string */
+ int stream_id; /* numeric identification */
+ int dma_dev; /* dma number of that device */
+ int *lch; /* Chain of channels this stream is linked to */
+ char started; /* to store if the chain was started or not */
+ int dma_q_head; /* DMA Channel Q Head */
+ int dma_q_tail; /* DMA Channel Q Tail */
+ char dma_q_count; /* DMA Channel Q Count */
+ int active:1; /* we are using this stream for transfer now */
+ int period; /* current transfer period */
+ int periods; /* current count of periods registerd in the DMA engine */
+ spinlock_t dma_lock; /* for locking in DMA operations */
+ snd_pcm_substream_t *stream; /* the pcm stream */
+ unsigned linked:1; /* dma channels linked */
+ int offset; /* store start position of the last period in the alsa buffer */
+ int (*hw_start)(void); /* interface to start HW interface, e.g. McBSP */
+ int (*hw_stop)(void); /* interface to stop HW interface, e.g. McBSP */
+};
+
+/*
+ * Alsa card structure for aic23
+ */
+struct snd_card_omap_codec {
+ snd_card_t *card;
+ snd_pcm_t *pcm;
+ long samplerate;
+ struct audio_stream s[2]; /* playback & capture */
+};
+
+/* Codec specific information and function pointers.
+ * Codec (omap-alsa-aic23.c and omap-alsa-tsc2101.c)
+ * are responsible for defining the function pointers.
+ */
+struct omap_alsa_codec_config {
+ char *name;
+ struct omap_mcbsp_reg_cfg *mcbsp_regs_alsa;
+ snd_pcm_hw_constraint_list_t *hw_constraints_rates;
+ snd_pcm_hardware_t *snd_omap_alsa_playback;
+ snd_pcm_hardware_t *snd_omap_alsa_capture;
+ void (*codec_configure_dev)(void);
+ void (*codec_set_samplerate)(long);
+ void (*codec_clock_setup)(void);
+ int (*codec_clock_on)(void);
+ int (*codec_clock_off)(void);
+ int (*get_default_samplerate)(void);
+};
+
+/*********** Mixer function prototypes *************************/
+int snd_omap_mixer(struct snd_card_omap_codec *);
+void snd_omap_init_mixer(void);
+
+#ifdef CONFIG_PM
+void snd_omap_suspend_mixer(void);
+void snd_omap_resume_mixer(void);
+#endif
+
+int snd_omap_alsa_post_probe(struct platform_device *pdev, struct omap_alsa_codec_config *config);
+int snd_omap_alsa_remove(struct platform_device *pdev);
+#ifdef CONFIG_PM
+int snd_omap_alsa_suspend(struct platform_device *pdev, pm_message_t state);
+int snd_omap_alsa_resume(struct platform_device *pdev);
+#else
+#define snd_omap_alsa_suspend NULL
+#define snd_omap_alsa_resume NULL
+#endif
+
+void callback_omap_alsa_sound_dma(void *);
+
+#endif
diff --git a/include/asm-arm/arch-omap/omapfb.h b/include/asm-arm/arch-omap/omapfb.h
index 4ba2622cc14..fccdb3db025 100644
--- a/include/asm-arm/arch-omap/omapfb.h
+++ b/include/asm-arm/arch-omap/omapfb.h
@@ -34,9 +34,10 @@
#define OMAPFB_MIRROR OMAP_IOW(31, int)
#define OMAPFB_SYNC_GFX OMAP_IO(37)
#define OMAPFB_VSYNC OMAP_IO(38)
-#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, enum omapfb_update_mode)
+#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int)
+#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(41, struct omapfb_update_window_old)
#define OMAPFB_GET_CAPS OMAP_IOR(42, unsigned long)
-#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, enum omapfb_update_mode)
+#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int)
#define OMAPFB_LCD_TEST OMAP_IOW(45, int)
#define OMAPFB_CTRL_TEST OMAP_IOW(46, int)
#define OMAPFB_UPDATE_WINDOW OMAP_IOW(47, struct omapfb_update_window)
@@ -66,9 +67,14 @@ enum omapfb_color_format {
};
struct omapfb_update_window {
- u32 x, y;
- u32 width, height;
- u32 format;
+ __u32 x, y;
+ __u32 width, height;
+ __u32 format;
+};
+
+struct omapfb_update_window_old {
+ __u32 x, y;
+ __u32 width, height;
};
enum omapfb_plane {
@@ -83,17 +89,17 @@ enum omapfb_channel_out {
};
struct omapfb_setup_plane {
- u8 plane;
- u8 channel_out;
- u32 offset;
- u32 pos_x, pos_y;
- u32 width, height;
- u32 color_mode;
+ __u8 plane;
+ __u8 channel_out;
+ __u32 offset;
+ __u32 pos_x, pos_y;
+ __u32 width, height;
+ __u32 color_mode;
};
struct omapfb_enable_plane {
- u8 plane;
- u8 enable;
+ __u8 plane;
+ __u8 enable;
};
enum omapfb_color_key_type {
@@ -103,10 +109,10 @@ enum omapfb_color_key_type {
};
struct omapfb_color_key {
- u8 channel_out;
- u32 background;
- u32 trans_key;
- u8 key_type;
+ __u8 channel_out;
+ __u32 background;
+ __u32 trans_key;
+ __u8 key_type;
};
enum omapfb_update_mode {
@@ -120,6 +126,9 @@ enum omapfb_update_mode {
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
+#include <linux/mutex.h>
+
+#include <asm/arch/board.h>
#define OMAP_LCDC_INV_VSYNC 0x0001
#define OMAP_LCDC_INV_HSYNC 0x0002
@@ -184,19 +193,38 @@ struct extif_timings {
int re_cycle_time;
int cs_pulse_width;
int access_time;
+
+ int clk_div;
+
+ u32 tim[5]; /* set by extif->convert_timings */
+
+ int converted;
};
struct lcd_ctrl_extif {
int (*init) (void);
void (*cleanup) (void);
+ void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div);
+ int (*convert_timings) (struct extif_timings *timings);
void (*set_timings) (const struct extif_timings *timings);
- void (*write_command) (u32 cmd);
- u32 (*read_data) (void);
- void (*write_data) (u32 data);
+ void (*set_bits_per_cycle)(int bpc);
+ void (*write_command) (const void *buf, unsigned int len);
+ void (*read_data) (void *buf, unsigned int len);
+ void (*write_data) (const void *buf, unsigned int len);
void (*transfer_area) (int width, int height,
void (callback)(void * data), void *data);
+ unsigned long max_transmit_size;
};
+struct omapfb_notifier_block {
+ struct notifier_block nb;
+ void *data;
+};
+
+typedef int (*omapfb_notifier_callback_t)(struct omapfb_notifier_block *,
+ unsigned long event,
+ struct omapfb_device *fbdev);
+
struct lcd_ctrl {
const char *name;
void *data;
@@ -204,9 +232,11 @@ struct lcd_ctrl {
int (*init) (struct omapfb_device *fbdev,
int ext_mode, int req_vram_size);
void (*cleanup) (void);
+ void (*bind_client) (struct omapfb_notifier_block *nb);
void (*get_vram_layout)(unsigned long *size,
void **virt_base,
dma_addr_t *phys_base);
+ int (*mmap) (struct vm_area_struct *vma);
unsigned long (*get_caps) (void);
int (*set_update_mode)(enum omapfb_update_mode mode);
enum omapfb_update_mode (*get_update_mode)(void);
@@ -240,7 +270,7 @@ struct omapfb_device {
int state;
int ext_lcdc; /* Using external
LCD controller */
- struct semaphore rqueue_sema;
+ struct mutex rqueue_mutex;
void *vram_virt_base;
dma_addr_t vram_phys_base;
@@ -261,12 +291,13 @@ struct omapfb_device {
struct device *dev;
};
-extern struct lcd_panel h3_panel;
-extern struct lcd_panel h2_panel;
-extern struct lcd_panel p2_panel;
-extern struct lcd_panel osk_panel;
-extern struct lcd_panel innovator1610_panel;
-extern struct lcd_panel innovator1510_panel;
+struct omapfb_platform_data {
+ struct omap_lcd_config lcd;
+ struct omap_fbmem_config fbmem;
+};
+
+#define OMAPFB_EVENT_READY 1
+#define OMAPFB_EVENT_DISABLED 2
#ifdef CONFIG_ARCH_OMAP1
extern struct lcd_ctrl omap1_lcd_ctrl;
@@ -274,7 +305,20 @@ extern struct lcd_ctrl omap1_lcd_ctrl;
extern struct lcd_ctrl omap2_disp_ctrl;
#endif
+extern void omapfb_register_panel(struct lcd_panel *panel);
extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
+extern void omapfb_notify_clients(struct omapfb_device *fbdev,
+ unsigned long event);
+extern int omapfb_register_client(struct omapfb_notifier_block *nb,
+ omapfb_notifier_callback_t callback,
+ void *callback_data);
+extern int omapfb_unregister_client(struct omapfb_notifier_block *nb);
+extern int omapfb_update_window_async(struct omapfb_update_window *win,
+ void (*callback)(void *),
+ void *callback_data);
+
+/* in arch/arm/plat-omap/devices.c */
+extern void omapfb_reserve_mem(void);
#endif /* __KERNEL__ */
diff --git a/include/asm-arm/arch-omap/param.h b/include/asm-arm/arch-omap/param.h
new file mode 100644
index 00000000000..face9ad41e9
--- /dev/null
+++ b/include/asm-arm/arch-omap/param.h
@@ -0,0 +1,8 @@
+/*
+ * linux/include/asm-arm/arch-omap/param.h
+ *
+ */
+
+#ifdef CONFIG_OMAP_32K_TIMER_HZ
+#define HZ CONFIG_OMAP_32K_TIMER_HZ
+#endif
diff --git a/include/asm-arm/arch-omap/pm.h b/include/asm-arm/arch-omap/pm.h
index 7c790425e36..05b003f3a94 100644
--- a/include/asm-arm/arch-omap/pm.h
+++ b/include/asm-arm/arch-omap/pm.h
@@ -49,7 +49,7 @@
/*
* ----------------------------------------------------------------------------
- * Powermanagement bitmasks
+ * Power management bitmasks
* ----------------------------------------------------------------------------
*/
#define IDLE_WAIT_CYCLES 0x00000fff
@@ -112,32 +112,59 @@
#endif
#ifndef __ASSEMBLER__
+
+#include <linux/clk.h>
+
+extern void prevent_idle_sleep(void);
+extern void allow_idle_sleep(void);
+
+/**
+ * clk_deny_idle - Prevents the clock from being idled during MPU idle
+ * @clk: clock signal handle
+ */
+void clk_deny_idle(struct clk *clk);
+
+/**
+ * clk_allow_idle - Counters previous clk_deny_idle
+ * @clk: clock signal handle
+ */
+void clk_deny_idle(struct clk *clk);
+
extern void omap_pm_idle(void);
extern void omap_pm_suspend(void);
extern void omap730_cpu_suspend(unsigned short, unsigned short);
extern void omap1510_cpu_suspend(unsigned short, unsigned short);
extern void omap1610_cpu_suspend(unsigned short, unsigned short);
+extern void omap24xx_cpu_suspend(u32 dll_ctrl, u32 cpu_revision);
extern void omap730_idle_loop_suspend(void);
extern void omap1510_idle_loop_suspend(void);
extern void omap1610_idle_loop_suspend(void);
+extern void omap24xx_idle_loop_suspend(void);
+
+extern unsigned int omap730_cpu_suspend_sz;
+extern unsigned int omap1510_cpu_suspend_sz;
+extern unsigned int omap1610_cpu_suspend_sz;
+extern unsigned int omap24xx_cpu_suspend_sz;
+extern unsigned int omap730_idle_loop_suspend_sz;
+extern unsigned int omap1510_idle_loop_suspend_sz;
+extern unsigned int omap1610_idle_loop_suspend_sz;
+extern unsigned int omap24xx_idle_loop_suspend_sz;
#ifdef CONFIG_OMAP_SERIAL_WAKE
extern void omap_serial_wake_trigger(int enable);
#else
+#define omap_serial_wakeup_init() {}
#define omap_serial_wake_trigger(x) {}
#endif /* CONFIG_OMAP_SERIAL_WAKE */
-extern unsigned int omap730_cpu_suspend_sz;
-extern unsigned int omap730_idle_loop_suspend_sz;
-extern unsigned int omap1510_cpu_suspend_sz;
-extern unsigned int omap1510_idle_loop_suspend_sz;
-extern unsigned int omap1610_cpu_suspend_sz;
-extern unsigned int omap1610_idle_loop_suspend_sz;
-
#define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x)
#define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x))
#define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x]
+#define DSP_SAVE(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] = __raw_readw(x)
+#define DSP_RESTORE(x) __raw_writew((dsp_sleep_save[DSP_SLEEP_SAVE_##x]), (x))
+#define DSP_SHOW(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x]
+
#define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x)
#define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x))
#define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]
@@ -154,6 +181,10 @@ extern unsigned int omap1610_idle_loop_suspend_sz;
#define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x))
#define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]
+#define OMAP24XX_SAVE(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] = x
+#define OMAP24XX_RESTORE(x) x = omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x]
+#define OMAP24XX_SHOW(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x]
+
/*
* List of global OMAP registers to preserve.
* More ones like CP and general purpose register values are preserved
@@ -176,6 +207,15 @@ enum arm_save_state {
ARM_SLEEP_SAVE_SIZE
};
+enum dsp_save_state {
+ DSP_SLEEP_SAVE_START = 0,
+ /*
+ * DSP registers 16 bits
+ */
+ DSP_SLEEP_SAVE_DSP_IDLECT2,
+ DSP_SLEEP_SAVE_SIZE
+};
+
enum ulpd_save_state {
ULPD_SLEEP_SAVE_START = 0,
/*
@@ -254,5 +294,30 @@ enum mpui1610_save_state {
#endif
};
+enum omap24xx_save_state {
+ OMAP24XX_SLEEP_SAVE_START = 0,
+ OMAP24XX_SLEEP_SAVE_INTC_MIR0,
+ OMAP24XX_SLEEP_SAVE_INTC_MIR1,
+ OMAP24XX_SLEEP_SAVE_INTC_MIR2,
+ OMAP24XX_SLEEP_SAVE_CM_FCLKEN1_CORE,
+ OMAP24XX_SLEEP_SAVE_CM_FCLKEN2_CORE,
+ OMAP24XX_SLEEP_SAVE_CM_ICLKEN1_CORE,
+ OMAP24XX_SLEEP_SAVE_CM_ICLKEN2_CORE,
+ OMAP24XX_SLEEP_SAVE_CM_ICLKEN4_CORE,
+ OMAP24XX_SLEEP_SAVE_GPIO1_IRQENABLE1,
+ OMAP24XX_SLEEP_SAVE_GPIO2_IRQENABLE1,
+ OMAP24XX_SLEEP_SAVE_GPIO3_IRQENABLE1,
+ OMAP24XX_SLEEP_SAVE_GPIO4_IRQENABLE1,
+ OMAP24XX_SLEEP_SAVE_GPIO3_OE,
+ OMAP24XX_SLEEP_SAVE_GPIO4_OE,
+ OMAP24XX_SLEEP_SAVE_GPIO3_RISINGDETECT,
+ OMAP24XX_SLEEP_SAVE_GPIO3_FALLINGDETECT,
+ OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SPI1_NCS2,
+ OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_MCBSP1_DX,
+ OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SSI1_FLAG_TX,
+ OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SYS_NIRQW0,
+ OMAP24XX_SLEEP_SAVE_SIZE
+};
+
#endif /* ASSEMBLER */
#endif /* __ASM_ARCH_OMAP_PM_H */
diff --git a/include/asm-arm/arch-omap/prcm.h b/include/asm-arm/arch-omap/prcm.h
index 7b48a5cbb15..7bcaf94bde9 100644
--- a/include/asm-arm/arch-omap/prcm.h
+++ b/include/asm-arm/arch-omap/prcm.h
@@ -1,5 +1,7 @@
/*
- * prcm.h - Access definations for use in OMAP24XX clock and power management
+ * linux/include/asm-arm/arch-omap/prcm.h
+ *
+ * Access definations for use in OMAP24XX clock and power management
*
* Copyright (C) 2005 Texas Instruments, Inc.
*
@@ -21,405 +23,7 @@
#ifndef __ASM_ARM_ARCH_DPM_PRCM_H
#define __ASM_ARM_ARCH_DPM_PRCM_H
-/* SET_PERFORMANCE_LEVEL PARAMETERS */
-#define PRCM_HALF_SPEED 1
-#define PRCM_FULL_SPEED 2
-
-#ifndef __ASSEMBLER__
-
-#define PRCM_REG32(offset) __REG32(OMAP24XX_PRCM_BASE + (offset))
-
-#define PRCM_REVISION PRCM_REG32(0x000)
-#define PRCM_SYSCONFIG PRCM_REG32(0x010)
-#define PRCM_IRQSTATUS_MPU PRCM_REG32(0x018)
-#define PRCM_IRQENABLE_MPU PRCM_REG32(0x01C)
-#define PRCM_VOLTCTRL PRCM_REG32(0x050)
-#define PRCM_VOLTST PRCM_REG32(0x054)
-#define PRCM_CLKSRC_CTRL PRCM_REG32(0x060)
-#define PRCM_CLKOUT_CTRL PRCM_REG32(0x070)
-#define PRCM_CLKEMUL_CTRL PRCM_REG32(0x078)
-#define PRCM_CLKCFG_CTRL PRCM_REG32(0x080)
-#define PRCM_CLKCFG_STATUS PRCM_REG32(0x084)
-#define PRCM_VOLTSETUP PRCM_REG32(0x090)
-#define PRCM_CLKSSETUP PRCM_REG32(0x094)
-#define PRCM_POLCTRL PRCM_REG32(0x098)
-
-/* GENERAL PURPOSE */
-#define GENERAL_PURPOSE1 PRCM_REG32(0x0B0)
-#define GENERAL_PURPOSE2 PRCM_REG32(0x0B4)
-#define GENERAL_PURPOSE3 PRCM_REG32(0x0B8)
-#define GENERAL_PURPOSE4 PRCM_REG32(0x0BC)
-#define GENERAL_PURPOSE5 PRCM_REG32(0x0C0)
-#define GENERAL_PURPOSE6 PRCM_REG32(0x0C4)
-#define GENERAL_PURPOSE7 PRCM_REG32(0x0C8)
-#define GENERAL_PURPOSE8 PRCM_REG32(0x0CC)
-#define GENERAL_PURPOSE9 PRCM_REG32(0x0D0)
-#define GENERAL_PURPOSE10 PRCM_REG32(0x0D4)
-#define GENERAL_PURPOSE11 PRCM_REG32(0x0D8)
-#define GENERAL_PURPOSE12 PRCM_REG32(0x0DC)
-#define GENERAL_PURPOSE13 PRCM_REG32(0x0E0)
-#define GENERAL_PURPOSE14 PRCM_REG32(0x0E4)
-#define GENERAL_PURPOSE15 PRCM_REG32(0x0E8)
-#define GENERAL_PURPOSE16 PRCM_REG32(0x0EC)
-#define GENERAL_PURPOSE17 PRCM_REG32(0x0F0)
-#define GENERAL_PURPOSE18 PRCM_REG32(0x0F4)
-#define GENERAL_PURPOSE19 PRCM_REG32(0x0F8)
-#define GENERAL_PURPOSE20 PRCM_REG32(0x0FC)
-
-/* MPU */
-#define CM_CLKSEL_MPU PRCM_REG32(0x140)
-#define CM_CLKSTCTRL_MPU PRCM_REG32(0x148)
-#define RM_RSTST_MPU PRCM_REG32(0x158)
-#define PM_WKDEP_MPU PRCM_REG32(0x1C8)
-#define PM_EVGENCTRL_MPU PRCM_REG32(0x1D4)
-#define PM_EVEGENONTIM_MPU PRCM_REG32(0x1D8)
-#define PM_EVEGENOFFTIM_MPU PRCM_REG32(0x1DC)
-#define PM_PWSTCTRL_MPU PRCM_REG32(0x1E0)
-#define PM_PWSTST_MPU PRCM_REG32(0x1E4)
-
-/* CORE */
-#define CM_FCLKEN1_CORE PRCM_REG32(0x200)
-#define CM_FCLKEN2_CORE PRCM_REG32(0x204)
-#define CM_FCLKEN3_CORE PRCM_REG32(0x208)
-#define CM_ICLKEN1_CORE PRCM_REG32(0x210)
-#define CM_ICLKEN2_CORE PRCM_REG32(0x214)
-#define CM_ICLKEN3_CORE PRCM_REG32(0x218)
-#define CM_ICLKEN4_CORE PRCM_REG32(0x21C)
-#define CM_IDLEST1_CORE PRCM_REG32(0x220)
-#define CM_IDLEST2_CORE PRCM_REG32(0x224)
-#define CM_IDLEST3_CORE PRCM_REG32(0x228)
-#define CM_IDLEST4_CORE PRCM_REG32(0x22C)
-#define CM_AUTOIDLE1_CORE PRCM_REG32(0x230)
-#define CM_AUTOIDLE2_CORE PRCM_REG32(0x234)
-#define CM_AUTOIDLE3_CORE PRCM_REG32(0x238)
-#define CM_AUTOIDLE4_CORE PRCM_REG32(0x23C)
-#define CM_CLKSEL1_CORE PRCM_REG32(0x240)
-#define CM_CLKSEL2_CORE PRCM_REG32(0x244)
-#define CM_CLKSTCTRL_CORE PRCM_REG32(0x248)
-#define PM_WKEN1_CORE PRCM_REG32(0x2A0)
-#define PM_WKEN2_CORE PRCM_REG32(0x2A4)
-#define PM_WKST1_CORE PRCM_REG32(0x2B0)
-#define PM_WKST2_CORE PRCM_REG32(0x2B4)
-#define PM_WKDEP_CORE PRCM_REG32(0x2C8)
-#define PM_PWSTCTRL_CORE PRCM_REG32(0x2E0)
-#define PM_PWSTST_CORE PRCM_REG32(0x2E4)
-
-/* GFX */
-#define CM_FCLKEN_GFX PRCM_REG32(0x300)
-#define CM_ICLKEN_GFX PRCM_REG32(0x310)
-#define CM_IDLEST_GFX PRCM_REG32(0x320)
-#define CM_CLKSEL_GFX PRCM_REG32(0x340)
-#define CM_CLKSTCTRL_GFX PRCM_REG32(0x348)
-#define RM_RSTCTRL_GFX PRCM_REG32(0x350)
-#define RM_RSTST_GFX PRCM_REG32(0x358)
-#define PM_WKDEP_GFX PRCM_REG32(0x3C8)
-#define PM_PWSTCTRL_GFX PRCM_REG32(0x3E0)
-#define PM_PWSTST_GFX PRCM_REG32(0x3E4)
-
-/* WAKE-UP */
-#define CM_FCLKEN_WKUP PRCM_REG32(0x400)
-#define CM_ICLKEN_WKUP PRCM_REG32(0x410)
-#define CM_IDLEST_WKUP PRCM_REG32(0x420)
-#define CM_AUTOIDLE_WKUP PRCM_REG32(0x430)
-#define CM_CLKSEL_WKUP PRCM_REG32(0x440)
-#define RM_RSTCTRL_WKUP PRCM_REG32(0x450)
-#define RM_RSTTIME_WKUP PRCM_REG32(0x454)
-#define RM_RSTST_WKUP PRCM_REG32(0x458)
-#define PM_WKEN_WKUP PRCM_REG32(0x4A0)
-#define PM_WKST_WKUP PRCM_REG32(0x4B0)
-
-/* CLOCKS */
-#define CM_CLKEN_PLL PRCM_REG32(0x500)
-#define CM_IDLEST_CKGEN PRCM_REG32(0x520)
-#define CM_AUTOIDLE_PLL PRCM_REG32(0x530)
-#define CM_CLKSEL1_PLL PRCM_REG32(0x540)
-#define CM_CLKSEL2_PLL PRCM_REG32(0x544)
-
-/* DSP */
-#define CM_FCLKEN_DSP PRCM_REG32(0x800)
-#define CM_ICLKEN_DSP PRCM_REG32(0x810)
-#define CM_IDLEST_DSP PRCM_REG32(0x820)
-#define CM_AUTOIDLE_DSP PRCM_REG32(0x830)
-#define CM_CLKSEL_DSP PRCM_REG32(0x840)
-#define CM_CLKSTCTRL_DSP PRCM_REG32(0x848)
-#define RM_RSTCTRL_DSP PRCM_REG32(0x850)
-#define RM_RSTST_DSP PRCM_REG32(0x858)
-#define PM_WKEN_DSP PRCM_REG32(0x8A0)
-#define PM_WKDEP_DSP PRCM_REG32(0x8C8)
-#define PM_PWSTCTRL_DSP PRCM_REG32(0x8E0)
-#define PM_PWSTST_DSP PRCM_REG32(0x8E4)
-#define PRCM_IRQSTATUS_DSP PRCM_REG32(0x8F0)
-#define PRCM_IRQENABLE_DSP PRCM_REG32(0x8F4)
-
-/* IVA */
-#define PRCM_IRQSTATUS_IVA PRCM_REG32(0x8F8)
-#define PRCM_IRQENABLE_IVA PRCM_REG32(0x8FC)
-
-/* Modem on 2430 */
-#define CM_FCLKEN_MDM PRCM_REG32(0xC00)
-#define CM_ICLKEN_MDM PRCM_REG32(0xC10)
-#define CM_IDLEST_MDM PRCM_REG32(0xC20)
-#define CM_CLKSEL_MDM PRCM_REG32(0xC40)
-
-/* FIXME: Move to header for 2430 */
-#define DISP_BASE (OMAP24XX_L4_IO_BASE+0x50000)
-#define DISP_REG32(offset) __REG32(DISP_BASE + (offset))
-
-#define OMAP24XX_GPMC_BASE (L3_24XX_BASE + 0xa000)
-#define GPMC_BASE (OMAP24XX_GPMC_BASE)
-#define GPMC_REG32(offset) __REG32(GPMC_BASE + (offset))
-
-#define GPT1_BASE (OMAP24XX_GPT1)
-#define GPT1_REG32(offset) __REG32(GPT1_BASE + (offset))
-
-/* Misc sysconfig */
-#define DISPC_SYSCONFIG DISP_REG32(0x410)
-#define SPI_BASE (OMAP24XX_L4_IO_BASE+0x98000)
-#define MCSPI1_SYSCONFIG __REG32(SPI_BASE + 0x10)
-#define MCSPI2_SYSCONFIG __REG32(SPI_BASE+0x2000 + 0x10)
-
-//#define DSP_MMU_SYSCONFIG 0x5A000010
-#define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE+0x2C10)
-//#define IVA_MMU_SYSCONFIG 0x5D000010
-//#define DSP_DMA_SYSCONFIG 0x00FCC02C
-#define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE+0x282C)
-#define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE+0x602C)
-#define GPMC_SYSCONFIG GPMC_REG32(0x010)
-#define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x94010)
-#define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6A054)
-#define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6C054)
-#define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6E054)
-//#define IVA_SYSCONFIG 0x5C060010
-#define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE+0x10)
-#define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE+0x10)
-#define SSI_SYSCONFIG __REG32(DISP_BASE+0x8010)
-//#define VLYNQ_SYSCONFIG 0x67FFFE10
-
-/* rkw - good cannidates for PM_ to start what nm was trying */
-#define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE+0x2A000)
-#define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE+0x78000)
-#define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE+0x7A000)
-#define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE+0x7C000)
-#define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE+0x7E000)
-#define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE+0x80000)
-#define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE+0x82000)
-#define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE+0x84000)
-#define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE+0x86000)
-#define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE+0x88000)
-#define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE+0x8A000)
-
-#define GPTIMER1_SYSCONFIG GPT1_REG32(0x010)
-#define GPTIMER2_SYSCONFIG __REG32(OMAP24XX_GPT2 + 0x10)
-#define GPTIMER3_SYSCONFIG __REG32(OMAP24XX_GPT3 + 0x10)
-#define GPTIMER4_SYSCONFIG __REG32(OMAP24XX_GPT4 + 0x10)
-#define GPTIMER5_SYSCONFIG __REG32(OMAP24XX_GPT5 + 0x10)
-#define GPTIMER6_SYSCONFIG __REG32(OMAP24XX_GPT6 + 0x10)
-#define GPTIMER7_SYSCONFIG __REG32(OMAP24XX_GPT7 + 0x10)
-#define GPTIMER8_SYSCONFIG __REG32(OMAP24XX_GPT8 + 0x10)
-#define GPTIMER9_SYSCONFIG __REG32(OMAP24XX_GPT9 + 0x10)
-#define GPTIMER10_SYSCONFIG __REG32(OMAP24XX_GPT10 + 0x10)
-#define GPTIMER11_SYSCONFIG __REG32(OMAP24XX_GPT11 + 0x10)
-#define GPTIMER12_SYSCONFIG __REG32(OMAP24XX_GPT12 + 0x10)
-
-#define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE+(0x2000*((X)-1)))
-
-#define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1)+0x10))
-#define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2)+0x10))
-#define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3)+0x10))
-#define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4)+0x10))
-
-/* GP TIMER 1 */
-#define GPTIMER1_TISTAT GPT1_REG32(0x014)
-#define GPTIMER1_TISR GPT1_REG32(0x018)
-#define GPTIMER1_TIER GPT1_REG32(0x01C)
-#define GPTIMER1_TWER GPT1_REG32(0x020)
-#define GPTIMER1_TCLR GPT1_REG32(0x024)
-#define GPTIMER1_TCRR GPT1_REG32(0x028)
-#define GPTIMER1_TLDR GPT1_REG32(0x02C)
-#define GPTIMER1_TTGR GPT1_REG32(0x030)
-#define GPTIMER1_TWPS GPT1_REG32(0x034)
-#define GPTIMER1_TMAR GPT1_REG32(0x038)
-#define GPTIMER1_TCAR1 GPT1_REG32(0x03C)
-#define GPTIMER1_TSICR GPT1_REG32(0x040)
-#define GPTIMER1_TCAR2 GPT1_REG32(0x044)
-
-/* rkw -- base fix up please... */
-#define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE+0x78018)
-
-/* SDRC */
-#define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE+0x060)
-#define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE+0x064)
-#define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE+0x068)
-#define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE+0x06C)
-#define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE+0x070)
-#define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE+0x084)
-
-/* GPIO 1 */
-#define GPIO1_BASE GPIOX_BASE(1)
-#define GPIO1_REG32(offset) __REG32(GPIO1_BASE + (offset))
-#define GPIO1_IRQENABLE1 GPIO1_REG32(0x01C)
-#define GPIO1_IRQSTATUS1 GPIO1_REG32(0x018)
-#define GPIO1_IRQENABLE2 GPIO1_REG32(0x02C)
-#define GPIO1_IRQSTATUS2 GPIO1_REG32(0x028)
-#define GPIO1_WAKEUPENABLE GPIO1_REG32(0x020)
-#define GPIO1_RISINGDETECT GPIO1_REG32(0x048)
-#define GPIO1_DATAIN GPIO1_REG32(0x038)
-#define GPIO1_OE GPIO1_REG32(0x034)
-#define GPIO1_DATAOUT GPIO1_REG32(0x03C)
-
-/* GPIO2 */
-#define GPIO2_BASE GPIOX_BASE(2)
-#define GPIO2_REG32(offset) __REG32(GPIO2_BASE + (offset))
-#define GPIO2_IRQENABLE1 GPIO2_REG32(0x01C)
-#define GPIO2_IRQSTATUS1 GPIO2_REG32(0x018)
-#define GPIO2_IRQENABLE2 GPIO2_REG32(0x02C)
-#define GPIO2_IRQSTATUS2 GPIO2_REG32(0x028)
-#define GPIO2_WAKEUPENABLE GPIO2_REG32(0x020)
-#define GPIO2_RISINGDETECT GPIO2_REG32(0x048)
-#define GPIO2_DATAIN GPIO2_REG32(0x038)
-#define GPIO2_OE GPIO2_REG32(0x034)
-#define GPIO2_DATAOUT GPIO2_REG32(0x03C)
-
-/* GPIO 3 */
-#define GPIO3_BASE GPIOX_BASE(3)
-#define GPIO3_REG32(offset) __REG32(GPIO3_BASE + (offset))
-#define GPIO3_IRQENABLE1 GPIO3_REG32(0x01C)
-#define GPIO3_IRQSTATUS1 GPIO3_REG32(0x018)
-#define GPIO3_IRQENABLE2 GPIO3_REG32(0x02C)
-#define GPIO3_IRQSTATUS2 GPIO3_REG32(0x028)
-#define GPIO3_WAKEUPENABLE GPIO3_REG32(0x020)
-#define GPIO3_RISINGDETECT GPIO3_REG32(0x048)
-#define GPIO3_FALLINGDETECT GPIO3_REG32(0x04C)
-#define GPIO3_DATAIN GPIO3_REG32(0x038)
-#define GPIO3_OE GPIO3_REG32(0x034)
-#define GPIO3_DATAOUT GPIO3_REG32(0x03C)
-#define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050)
-#define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054)
-
-/* GPIO 4 */
-#define GPIO4_BASE GPIOX_BASE(4)
-#define GPIO4_REG32(offset) __REG32(GPIO4_BASE + (offset))
-#define GPIO4_IRQENABLE1 GPIO4_REG32(0x01C)
-#define GPIO4_IRQSTATUS1 GPIO4_REG32(0x018)
-#define GPIO4_IRQENABLE2 GPIO4_REG32(0x02C)
-#define GPIO4_IRQSTATUS2 GPIO4_REG32(0x028)
-#define GPIO4_WAKEUPENABLE GPIO4_REG32(0x020)
-#define GPIO4_RISINGDETECT GPIO4_REG32(0x048)
-#define GPIO4_FALLINGDETECT GPIO4_REG32(0x04C)
-#define GPIO4_DATAIN GPIO4_REG32(0x038)
-#define GPIO4_OE GPIO4_REG32(0x034)
-#define GPIO4_DATAOUT GPIO4_REG32(0x03C)
-#define GPIO4_DEBOUNCENABLE GPIO4_REG32(0x050)
-#define GPIO4_DEBOUNCINGTIME GPIO4_REG32(0x054)
-
-
-/* IO CONFIG */
-#define CONTROL_BASE (OMAP24XX_CTRL_BASE)
-#define CONTROL_REG32(offset) __REG32(CONTROL_BASE + (offset))
-
-#define CONTROL_PADCONF_SPI1_NCS2 CONTROL_REG32(0x104)
-#define CONTROL_PADCONF_SYS_XTALOUT CONTROL_REG32(0x134)
-#define CONTROL_PADCONF_UART1_RX CONTROL_REG32(0x0C8)
-#define CONTROL_PADCONF_MCBSP1_DX CONTROL_REG32(0x10C)
-#define CONTROL_PADCONF_GPMC_NCS4 CONTROL_REG32(0x090)
-#define CONTROL_PADCONF_DSS_D5 CONTROL_REG32(0x0B8)
-#define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC)
-#define CONTROL_PADCONF_DSS_D13 CONTROL_REG32(0x0C0)
-#define CONTROL_PADCONF_DSS_VSYNC CONTROL_REG32(0x0CC)
-
-/* CONTROL */
-#define CONTROL_DEVCONF CONTROL_REG32(0x274)
-
-/* INTERRUPT CONTROLLER */
-#define INTC_BASE (OMAP24XX_L4_IO_BASE+0xfe000)
-#define INTC_REG32(offset) __REG32(INTC_BASE + (offset))
-
-#define INTC1_U_BASE INTC_REG32(0x000)
-#define INTC_MIR0 INTC_REG32(0x084)
-#define INTC_MIR_SET0 INTC_REG32(0x08C)
-#define INTC_MIR_CLEAR0 INTC_REG32(0x088)
-#define INTC_ISR_CLEAR0 INTC_REG32(0x094)
-#define INTC_MIR1 INTC_REG32(0x0A4)
-#define INTC_MIR_SET1 INTC_REG32(0x0AC)
-#define INTC_MIR_CLEAR1 INTC_REG32(0x0A8)
-#define INTC_ISR_CLEAR1 INTC_REG32(0x0B4)
-#define INTC_MIR2 INTC_REG32(0x0C4)
-#define INTC_MIR_SET2 INTC_REG32(0x0CC)
-#define INTC_MIR_CLEAR2 INTC_REG32(0x0C8)
-#define INTC_ISR_CLEAR2 INTC_REG32(0x0D4)
-#define INTC_SIR_IRQ INTC_REG32(0x040)
-#define INTC_CONTROL INTC_REG32(0x048)
-#define INTC_ILR11 INTC_REG32(0x12C)
-#define INTC_ILR32 INTC_REG32(0x180)
-#define INTC_ILR37 INTC_REG32(0x194)
-#define INTC_SYSCONFIG INTC_REG32(0x010)
-
-/* RAM FIREWALL */
-#define RAMFW_BASE (0x68005000)
-#define RAMFW_REG32(offset) __REG32(RAMFW_BASE + (offset))
-
-#define RAMFW_REQINFOPERM0 RAMFW_REG32(0x048)
-#define RAMFW_READPERM0 RAMFW_REG32(0x050)
-#define RAMFW_WRITEPERM0 RAMFW_REG32(0x058)
-
-/* GPMC CS1 FPGA ON USER INTERFACE MODULE */
-//#define DEBUG_BOARD_LED_REGISTER 0x04000014
-
-/* GPMC CS0 */
-#define GPMC_CONFIG1_0 GPMC_REG32(0x060)
-#define GPMC_CONFIG2_0 GPMC_REG32(0x064)
-#define GPMC_CONFIG3_0 GPMC_REG32(0x068)
-#define GPMC_CONFIG4_0 GPMC_REG32(0x06C)
-#define GPMC_CONFIG5_0 GPMC_REG32(0x070)
-#define GPMC_CONFIG6_0 GPMC_REG32(0x074)
-#define GPMC_CONFIG7_0 GPMC_REG32(0x078)
-
-/* GPMC CS1 */
-#define GPMC_CONFIG1_1 GPMC_REG32(0x090)
-#define GPMC_CONFIG2_1 GPMC_REG32(0x094)
-#define GPMC_CONFIG3_1 GPMC_REG32(0x098)
-#define GPMC_CONFIG4_1 GPMC_REG32(0x09C)
-#define GPMC_CONFIG5_1 GPMC_REG32(0x0a0)
-#define GPMC_CONFIG6_1 GPMC_REG32(0x0a4)
-#define GPMC_CONFIG7_1 GPMC_REG32(0x0a8)
-
-/* DSS */
-#define DSS_CONTROL DISP_REG32(0x040)
-#define DISPC_CONTROL DISP_REG32(0x440)
-#define DISPC_SYSSTATUS DISP_REG32(0x414)
-#define DISPC_IRQSTATUS DISP_REG32(0x418)
-#define DISPC_IRQENABLE DISP_REG32(0x41C)
-#define DISPC_CONFIG DISP_REG32(0x444)
-#define DISPC_DEFAULT_COLOR0 DISP_REG32(0x44C)
-#define DISPC_DEFAULT_COLOR1 DISP_REG32(0x450)
-#define DISPC_TRANS_COLOR0 DISP_REG32(0x454)
-#define DISPC_TRANS_COLOR1 DISP_REG32(0x458)
-#define DISPC_LINE_NUMBER DISP_REG32(0x460)
-#define DISPC_TIMING_H DISP_REG32(0x464)
-#define DISPC_TIMING_V DISP_REG32(0x468)
-#define DISPC_POL_FREQ DISP_REG32(0x46C)
-#define DISPC_DIVISOR DISP_REG32(0x470)
-#define DISPC_SIZE_DIG DISP_REG32(0x478)
-#define DISPC_SIZE_LCD DISP_REG32(0x47C)
-#define DISPC_GFX_BA0 DISP_REG32(0x480)
-#define DISPC_GFX_BA1 DISP_REG32(0x484)
-#define DISPC_GFX_POSITION DISP_REG32(0x488)
-#define DISPC_GFX_SIZE DISP_REG32(0x48C)
-#define DISPC_GFX_ATTRIBUTES DISP_REG32(0x4A0)
-#define DISPC_GFX_FIFO_THRESHOLD DISP_REG32(0x4A4)
-#define DISPC_GFX_ROW_INC DISP_REG32(0x4AC)
-#define DISPC_GFX_PIXEL_INC DISP_REG32(0x4B0)
-#define DISPC_GFX_WINDOW_SKIP DISP_REG32(0x4B4)
-#define DISPC_GFX_TABLE_BA DISP_REG32(0x4B8)
-#define DISPC_DATA_CYCLE1 DISP_REG32(0x5D4)
-#define DISPC_DATA_CYCLE2 DISP_REG32(0x5D8)
-#define DISPC_DATA_CYCLE3 DISP_REG32(0x5DC)
-
-/* Wake up define for board */
-#define GPIO97 (1 << 1)
-#define GPIO88 (1 << 24)
-
-#endif /* __ASSEMBLER__ */
+u32 omap_prcm_get_reset_sources(void);
#endif
diff --git a/include/asm-arm/arch-omap/sram.h b/include/asm-arm/arch-omap/sram.h
index e72ccbf0fe0..6fc0dd57b7c 100644
--- a/include/asm-arm/arch-omap/sram.h
+++ b/include/asm-arm/arch-omap/sram.h
@@ -20,6 +20,8 @@ extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
u32 mem_type);
extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
+extern unsigned long omap_fb_sram_start;
+extern unsigned long omap_fb_sram_size;
/* Do not use these */
extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl);
diff --git a/include/asm-arm/arch-omap/system.h b/include/asm-arm/arch-omap/system.h
index 6724a81bd10..67970d1a202 100644
--- a/include/asm-arm/arch-omap/system.h
+++ b/include/asm-arm/arch-omap/system.h
@@ -9,12 +9,13 @@
#include <asm/mach-types.h>
#include <asm/hardware.h>
-#include <asm/arch/prcm.h>
#ifndef CONFIG_MACH_VOICEBLUE
#define voiceblue_reset() do {} while (0)
#endif
+extern void omap_prcm_arch_reset(char mode);
+
static inline void arch_idle(void)
{
cpu_do_idle();
@@ -38,24 +39,12 @@ static inline void omap1_arch_reset(char mode)
omap_writew(1, ARM_RSTCT1);
}
-static inline void omap2_arch_reset(char mode)
-{
- u32 rate;
- struct clk *vclk, *sclk;
-
- vclk = clk_get(NULL, "virt_prcm_set");
- sclk = clk_get(NULL, "sys_ck");
- rate = clk_get_rate(sclk);
- clk_set_rate(vclk, rate); /* go to bypass for OMAP limitation */
- RM_RSTCTRL_WKUP |= 2;
-}
-
static inline void arch_reset(char mode)
{
if (!cpu_is_omap24xx())
omap1_arch_reset(mode);
else
- omap2_arch_reset(mode);
+ omap_prcm_arch_reset(mode);
}
#endif
diff --git a/include/asm-arm/arch-omap/uncompress.h b/include/asm-arm/arch-omap/uncompress.h
index c718264affb..ca2c8bec82e 100644
--- a/include/asm-arm/arch-omap/uncompress.h
+++ b/include/asm-arm/arch-omap/uncompress.h
@@ -30,8 +30,7 @@ unsigned int system_rev;
#define check_port(base, shift) ((base[UART_OMAP_MDR1 << shift] & 7) == 0)
#define omap_get_id() ((*(volatile unsigned int *)(0xfffed404)) >> 12) & ID_MASK
-static void
-putstr(const char *s)
+static void putc(int c)
{
volatile u8 * uart = 0;
int shift = 2;
@@ -69,16 +68,13 @@ putstr(const char *s)
/*
* Now, xmit each character
*/
- while (*s) {
- while (!(uart[UART_LSR << shift] & UART_LSR_THRE))
- barrier();
- uart[UART_TX << shift] = *s;
- if (*s++ == '\n') {
- while (!(uart[UART_LSR << shift] & UART_LSR_THRE))
- barrier();
- uart[UART_TX << shift] = '\r';
- }
- }
+ while (!(uart[UART_LSR << shift] & UART_LSR_THRE))
+ barrier();
+ uart[UART_TX << shift] = c;
+}
+
+static inline void flush(void)
+{
}
/*
diff --git a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h
index 3e88a2a02a0..a008150abc5 100644
--- a/include/asm-arm/arch-pxa/dma.h
+++ b/include/asm-arm/arch-pxa/dma.h
@@ -24,27 +24,29 @@ typedef struct pxa_dma_desc {
volatile u32 dcmd; /* DCMD value for the current transfer */
} pxa_dma_desc;
+typedef enum {
+ DMA_PRIO_HIGH = 0,
+ DMA_PRIO_MEDIUM = 1,
+ DMA_PRIO_LOW = 2
+} pxa_dma_prio;
+
#if defined(CONFIG_PXA27x)
#define PXA_DMA_CHANNELS 32
-#define PXA_DMA_NBCH(prio) ((prio == DMA_PRIO_LOW) ? 16 : 8)
-typedef enum {
- DMA_PRIO_HIGH = 0,
- DMA_PRIO_MEDIUM = 8,
- DMA_PRIO_LOW = 16
-} pxa_dma_prio;
+#define pxa_for_each_dma_prio(ch, prio) \
+for ( \
+ ch = prio * 4; \
+ ch != (4 << prio) + 16; \
+ ch = (ch + 1 == (4 << prio)) ? (prio * 4 + 16) : (ch + 1) \
+)
#elif defined(CONFIG_PXA25x)
#define PXA_DMA_CHANNELS 16
-#define PXA_DMA_NBCH(prio) ((prio == DMA_PRIO_LOW) ? 8 : 4)
-typedef enum {
- DMA_PRIO_HIGH = 0,
- DMA_PRIO_MEDIUM = 4,
- DMA_PRIO_LOW = 8
-} pxa_dma_prio;
+#define pxa_for_each_dma_prio(ch, prio) \
+ for (ch = prio * 4; ch != (4 << prio); ch++)
#endif
diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
index 05c4b702759..67af238a8f8 100644
--- a/include/asm-arm/arch-pxa/irqs.h
+++ b/include/asm-arm/arch-pxa/irqs.h
@@ -176,6 +176,7 @@
#elif defined(CONFIG_SHARP_LOCOMO)
#define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1)
#elif defined(CONFIG_ARCH_LUBBOCK) || \
+ defined(CONFIG_MACH_LOGICPD_PXA270) || \
defined(CONFIG_MACH_MAINSTONE)
#define NR_IRQS (IRQ_BOARD_END)
#else
@@ -196,6 +197,11 @@
#define LUBBOCK_USB_DISC_IRQ LUBBOCK_IRQ(6) /* usb disconnect */
#define LUBBOCK_LAST_IRQ LUBBOCK_IRQ(6)
+#define LPD270_IRQ(x) (IRQ_BOARD_START + (x))
+#define LPD270_USBC_IRQ LPD270_IRQ(2)
+#define LPD270_ETHERNET_IRQ LPD270_IRQ(3)
+#define LPD270_AC97_IRQ LPD270_IRQ(4)
+
#define MAINSTONE_IRQ(x) (IRQ_BOARD_START + (x))
#define MAINSTONE_MMC_IRQ MAINSTONE_IRQ(0)
#define MAINSTONE_USIM_IRQ MAINSTONE_IRQ(1)
diff --git a/include/asm-arm/arch-pxa/lpd270.h b/include/asm-arm/arch-pxa/lpd270.h
new file mode 100644
index 00000000000..501d240ac12
--- /dev/null
+++ b/include/asm-arm/arch-pxa/lpd270.h
@@ -0,0 +1,38 @@
+/*
+ * include/asm-arm/arch-pxa/lpd270.h
+ *
+ * Author: Lennert Buytenhek
+ * Created: Feb 10, 2006
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_LPD270_H
+#define __ASM_ARCH_LPD270_H
+
+#define LPD270_CPLD_PHYS PXA_CS2_PHYS
+#define LPD270_CPLD_VIRT 0xf0000000
+#define LPD270_CPLD_SIZE 0x00100000
+
+#define LPD270_ETH_PHYS (PXA_CS2_PHYS + 0x01000000)
+
+/* CPLD registers */
+#define LPD270_CPLD_REG(x) ((unsigned long)(LPD270_CPLD_VIRT + (x)))
+#define LPD270_CONTROL LPD270_CPLD_REG(0x00)
+#define LPD270_PERIPHERAL0 LPD270_CPLD_REG(0x04)
+#define LPD270_PERIPHERAL1 LPD270_CPLD_REG(0x08)
+#define LPD270_CPLD_REVISION LPD270_CPLD_REG(0x14)
+#define LPD270_EEPROM_SPI_ITF LPD270_CPLD_REG(0x20)
+#define LPD270_MODE_PINS LPD270_CPLD_REG(0x24)
+#define LPD270_EGPIO LPD270_CPLD_REG(0x30)
+#define LPD270_INT_MASK LPD270_CPLD_REG(0x40)
+#define LPD270_INT_STATUS LPD270_CPLD_REG(0x50)
+
+#define LPD270_INT_AC97 (1 << 4) /* AC'97 CODEC IRQ */
+#define LPD270_INT_ETHERNET (1 << 3) /* Ethernet controller IRQ */
+#define LPD270_INT_USBC (1 << 2) /* USB client cable detection IRQ */
+
+
+#endif
diff --git a/include/asm-arm/arch-pxa/ohci.h b/include/asm-arm/arch-pxa/ohci.h
index 7da89569061..e848a47128c 100644
--- a/include/asm-arm/arch-pxa/ohci.h
+++ b/include/asm-arm/arch-pxa/ohci.h
@@ -11,6 +11,8 @@ struct pxaohci_platform_data {
#define PMM_NPS_MODE 1
#define PMM_GLOBAL_MODE 2
#define PMM_PERPORT_MODE 3
+
+ int power_budget;
};
extern void pxa_set_ohci_info(struct pxaohci_platform_data *info);
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index 1409c5bd703..c8f53a71c07 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -485,7 +485,7 @@
#define SACR1_ENLBF (1 << 5) /* Enable Loopback */
#define SACR1_DRPL (1 << 4) /* Disable Replaying Function */
#define SACR1_DREC (1 << 3) /* Disable Recording Function */
-#define SACR1_AMSL (1 << 1) /* Specify Alternate Mode */
+#define SACR1_AMSL (1 << 0) /* Specify Alternate Mode */
#define SASR0_I2SOFF (1 << 7) /* Controller Status */
#define SASR0_ROR (1 << 6) /* Rx FIFO Overrun */
diff --git a/include/asm-arm/arch-pxa/pxa2xx_spi.h b/include/asm-arm/arch-pxa/pxa2xx_spi.h
new file mode 100644
index 00000000000..915590c391c
--- /dev/null
+++ b/include/asm-arm/arch-pxa/pxa2xx_spi.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
+ *
+ * This program is free software; 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 PXA2XX_SPI_H_
+#define PXA2XX_SPI_H_
+
+#define PXA2XX_CS_ASSERT (0x01)
+#define PXA2XX_CS_DEASSERT (0x02)
+
+#if defined(CONFIG_PXA25x)
+#define CLOCK_SPEED_HZ 3686400
+#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/2/(x+1))<<8)&0x0000ff00)
+#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
+#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
+#define SSP_TIMEOUT_SCALE (2712)
+#elif defined(CONFIG_PXA27x)
+#define CLOCK_SPEED_HZ 13000000
+#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
+#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
+#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
+#define SSP_TIMEOUT_SCALE (769)
+#endif
+
+#define SSP_TIMEOUT(x) ((x*10000)/SSP_TIMEOUT_SCALE)
+#define SSP1_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(1)))))
+#define SSP2_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(2)))))
+#define SSP3_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(3)))))
+
+enum pxa_ssp_type {
+ SSP_UNDEFINED = 0,
+ PXA25x_SSP, /* pxa 210, 250, 255, 26x */
+ PXA25x_NSSP, /* pxa 255, 26x (including ASSP) */
+ PXA27x_SSP,
+};
+
+/* device.platform_data for SSP controller devices */
+struct pxa2xx_spi_master {
+ enum pxa_ssp_type ssp_type;
+ u32 clock_enable;
+ u16 num_chipselect;
+ u8 enable_dma;
+};
+
+/* spi_board_info.controller_data for SPI slave devices,
+ * copied to spi_device.platform_data ... mostly for dma tuning
+ */
+struct pxa2xx_spi_chip {
+ u8 tx_threshold;
+ u8 rx_threshold;
+ u8 dma_burst_size;
+ u32 timeout_microsecs;
+ u8 enable_loopback;
+ void (*cs_control)(u32 command);
+};
+
+#endif /*PXA2XX_SPI_H_*/
diff --git a/include/asm-arm/arch-pxa/sharpsl.h b/include/asm-arm/arch-pxa/sharpsl.h
index 0b43495d24b..94cb4982af8 100644
--- a/include/asm-arm/arch-pxa/sharpsl.h
+++ b/include/asm-arm/arch-pxa/sharpsl.h
@@ -27,6 +27,8 @@ struct corgits_machinfo {
*/
struct corgibl_machinfo {
int max_intensity;
+ int default_intensity;
+ int limit_mask;
void (*set_bl_intensity)(int intensity);
};
extern void corgibl_limit_intensity(int limit);
diff --git a/include/asm-arm/arch-pxa/uncompress.h b/include/asm-arm/arch-pxa/uncompress.h
index fe38090444e..178aa2e073a 100644
--- a/include/asm-arm/arch-pxa/uncompress.h
+++ b/include/asm-arm/arch-pxa/uncompress.h
@@ -17,23 +17,18 @@
#define UART FFUART
-static __inline__ void putc(char c)
+static inline void putc(char c)
{
- while (!(UART[5] & 0x20));
+ while (!(UART[5] & 0x20))
+ barrier();
UART[0] = c;
}
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
/*
diff --git a/include/asm-arm/arch-realview/uncompress.h b/include/asm-arm/arch-realview/uncompress.h
index b5e4d360665..f05631d7674 100644
--- a/include/asm-arm/arch-realview/uncompress.h
+++ b/include/asm-arm/arch-realview/uncompress.h
@@ -27,22 +27,16 @@
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static inline void putc(int c)
{
- while (*s) {
- while (AMBA_UART_FR & (1 << 5))
- barrier();
-
- AMBA_UART_DR = *s;
+ while (AMBA_UART_FR & (1 << 5))
+ barrier();
- if (*s == '\n') {
- while (AMBA_UART_FR & (1 << 5))
- barrier();
+ AMBA_UART_DR = c;
+}
- AMBA_UART_DR = '\r';
- }
- s++;
- }
+static inline void flush(void)
+{
while (AMBA_UART_FR & (1 << 3))
barrier();
}
diff --git a/include/asm-arm/arch-rpc/hardware.h b/include/asm-arm/arch-rpc/hardware.h
index 9d7f87375aa..7480f4e8d97 100644
--- a/include/asm-arm/arch-rpc/hardware.h
+++ b/include/asm-arm/arch-rpc/hardware.h
@@ -46,7 +46,6 @@
#define SCREEN_END 0xdfc00000
#define SCREEN_BASE 0xdf800000
-#define FLUSH_BASE 0xdf000000
#define UNCACHEABLE_ADDR 0xdf010000
/*
@@ -59,8 +58,6 @@
#define PCIO_BASE IOMEM(0xe0010000)
#define FLOPPYDMA_BASE IOMEM(0xe002a000)
-#define FLUSH_BASE_PHYS 0x00000000 /* ROM */
-
#define vidc_writel(val) __raw_writel(val, VIDC_BASE)
#define IO_EC_EASI_BASE 0x81400000
diff --git a/include/asm-arm/arch-rpc/memory.h b/include/asm-arm/arch-rpc/memory.h
index 0592cb3f0c7..303c424ce67 100644
--- a/include/asm-arm/arch-rpc/memory.h
+++ b/include/asm-arm/arch-rpc/memory.h
@@ -30,4 +30,10 @@
#define __virt_to_bus(x) __virt_to_phys(x)
#define __bus_to_virt(x) __phys_to_virt(x)
+/*
+ * Cache flushing area - ROM
+ */
+#define FLUSH_BASE_PHYS 0x00000000
+#define FLUSH_BASE 0xdf000000
+
#endif
diff --git a/include/asm-arm/arch-rpc/uncompress.h b/include/asm-arm/arch-rpc/uncompress.h
index 43035fec64d..06231ede54e 100644
--- a/include/asm-arm/arch-rpc/uncompress.h
+++ b/include/asm-arm/arch-rpc/uncompress.h
@@ -67,31 +67,28 @@ extern __attribute__((pure)) struct param_struct *params(void);
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static void putc(int c)
{
extern void ll_write_char(char *, char c, char white);
int x,y;
- unsigned char c;
char *ptr;
x = params->video_x;
y = params->video_y;
- while ( ( c = *(unsigned char *)s++ ) != '\0' ) {
- if ( c == '\n' ) {
+ if (c == '\n') {
+ if (++y >= video_num_lines)
+ y--;
+ } else if (c == '\r') {
+ x = 0;
+ } else {
+ ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h);
+ ll_write_char(ptr, c, white);
+ if (++x >= video_num_columns) {
x = 0;
if ( ++y >= video_num_lines ) {
y--;
}
- } else {
- ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h);
- ll_write_char(ptr, c, white);
- if ( ++x >= video_num_columns ) {
- x = 0;
- if ( ++y >= video_num_lines ) {
- y--;
- }
- }
}
}
@@ -99,6 +96,10 @@ static void putstr(const char *s)
params->video_y = y;
}
+static inline void flush(void)
+{
+}
+
static void error(char *x);
/*
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S
index cc06b1bd37b..894c35cf3b1 100644
--- a/include/asm-arm/arch-s3c2410/entry-macro.S
+++ b/include/asm-arm/arch-s3c2410/entry-macro.S
@@ -6,116 +6,83 @@
* 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.
+*/
+
+/* We have a problem that the INTOFFSET register does not always
+ * show one interrupt. Occasionally we get two interrupts through
+ * the prioritiser, and this causes the INTOFFSET register to show
+ * what looks like the logical-or of the two interrupt numbers.
+ *
+ * Thanks to Klaus, Shannon, et al for helping to debug this problem
+*/
+
+#define INTPND (0x10)
+#define INTOFFSET (0x14)
+#define EXTINTPEND (0xa8)
+#define EXTINTMASK (0xa4)
- * Modifications:
- * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
- */
#include <asm/hardware.h>
#include <asm/arch/irqs.h>
-
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- mov \tmp, #S3C24XX_VA_IRQ
- ldr \irqnr, [ \tmp, #0x14 ] @ get irq no
-30000:
- teq \irqnr, #4
- teqne \irqnr, #5
- beq 1002f @ external irq reg
-
- @ debug check to see if interrupt reported is the same
- @ as the offset....
-
- teq \irqnr, #0
- beq 20002f
- ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
- mov \irqstat, \irqstat, lsr \irqnr
- tst \irqstat, #1
- bne 20002f
-
- /* debug/warning if we get an invalud response from the
- * INTOFFSET register */
-#if 1
- stmfd r13!, { r0 - r4 , r8-r12, r14 }
- ldr r1, [ \tmp, #0x14 ] @ INTOFFSET
- ldr r2, [ \tmp, #0x10 ] @ INTPND
- ldr r3, [ \tmp, #0x00 ] @ SRCPND
- adr r0, 20003f
- bl printk
- b 20004f
-
-20003:
- .ascii "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n"
- .byte 0
- .align 4
-20004:
- mov r1, #1
- mov \tmp, #S3C24XX_VA_IRQ
- ldmfd r13!, { r0 - r4 , r8-r12, r14 }
-#endif
-
- @ try working out interrupt number for ourselves
- mov \irqnr, #0
- ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
-10021:
- movs \irqstat, \irqstat, lsr#1
- bcs 30000b @ try and re-start the proccess
- add \irqnr, \irqnr, #1
- cmp \irqnr, #32
- ble 10021b
-
- @ found no interrupt, set Z flag and leave
- movs \irqnr, #0
- b 1001f
-
-20005:
-20002: @ exit
- @ we base the s3c2410x interrupts at 16 and above to allow
- @ isa peripherals to have their standard interrupts, also
- @ ensure that Z flag is un-set on exit
-
- @ note, we cannot be sure if we get IRQ_EINT0 (0) that
- @ there is simply no interrupt pending, so in all other
- @ cases we jump to say we have found something, otherwise
- @ we check to see if the interrupt really is assrted
- adds \irqnr, \irqnr, #IRQ_EINT0
- teq \irqnr, #IRQ_EINT0
- bne 1001f @ exit
- ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
- teq \irqstat, #0
- moveq \irqnr, #0
- b 1001f
-
- @ we get here from no main or external interrupts pending
-1002:
- add \tmp, \tmp, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
- ldr \irqstat, [ \tmp, # 0xa8 ] @ EXTINTPEND
- ldr \irqnr, [ \tmp, # 0xa4 ] @ EXTINTMASK
-
- bic \irqstat, \irqstat, \irqnr @ clear masked irqs
-
- mov \irqnr, #IRQ_EINT4 @ start extint nos
- mov \irqstat, \irqstat, lsr#4 @ ignore bottom 4 bits
-10021:
- movs \irqstat, \irqstat, lsr#1
- bcs 1004f
- add \irqnr, \irqnr, #1
- cmp \irqnr, #IRQ_EINT23
- ble 10021b
-
- @ found no interrupt, set Z flag and leave
- movs \irqnr, #0
-
-1004: @ ensure Z flag clear in case our MOVS shifted out the last bit
- teq \irqnr, #0
+ mov \base, #S3C24XX_VA_IRQ
+
+ ldr \irqstat, [ \base, #INTPND]
+ bics \irqnr, \irqstat, #3<<4 @@ only an GPIO IRQ
+ beq 2000f
+
+ @@ try the interrupt offset register, since it is there
+
+ ldr \irqnr, [ \base, #INTOFFSET ]
+ mov \tmp, #1
+ tst \irqstat, \tmp, lsl \irqnr
+ addne \irqnr, \irqnr, #IRQ_EINT0
+ bne 1001f
+
+ @@ the number specified is not a valid irq, so try
+ @@ and work it out for ourselves
+
+ mov \irqnr, #IRQ_EINT0 @@ start here
+ b 3000f
+
+2000:
+ @@ load the GPIO interrupt register, and check it
+
+ add \tmp, \base, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
+ ldr \irqstat, [ \tmp, # EXTINTPEND ]
+ ldr \irqnr, [ \tmp, # EXTINTMASK ]
+ bics \irqstat, \irqstat, \irqnr
+ beq 1001f
+
+ mov \irqnr, #(IRQ_EINT4 - 4)
+
+ @@ work out which irq (if any) we got
+3000:
+ movs \tmp, \irqstat, lsl#16
+ addeq \irqnr, \irqnr, #16
+ moveq \irqstat, \irqstat, lsr#16
+ tst \irqstat, #0xff
+ addeq \irqnr, \irqnr, #8
+ moveq \irqstat, \irqstat, lsr#8
+ tst \irqstat, #0xf
+ addeq \irqnr, \irqnr, #4
+ moveq \irqstat, \irqstat, lsr#4
+ tst \irqstat, #0x3
+ addeq \irqnr, \irqnr, #2
+ moveq \irqstat, \irqstat, lsr#2
+ tst \irqstat, #0x1
+ addeq \irqnr, \irqnr, #1
+
+ @@ we have the value
+ movs \irqnr, \irqnr
+
1001:
- @ exit irq routine
- .endm
+ @@ exit here, Z flag unset if IRQ
+ .endm
/* currently don't need an disable_fiq macro */
.macro disable_fiq
.endm
-
-
diff --git a/include/asm-arm/arch-s3c2410/leds-gpio.h b/include/asm-arm/arch-s3c2410/leds-gpio.h
new file mode 100644
index 00000000000..f07ed040622
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/leds-gpio.h
@@ -0,0 +1,28 @@
+/* linux/include/asm-arm/arch-s3c2410/leds-gpio.h
+ *
+ * (c) 2006 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX - LEDs GPIO connector
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_LEDSGPIO_H
+#define __ASM_ARCH_LEDSGPIO_H "leds-gpio.h"
+
+#define S3C24XX_LEDF_ACTLOW (1<<0) /* LED is on when GPIO low */
+#define S3C24XX_LEDF_TRISTATE (1<<1) /* tristate to turn off */
+
+struct s3c24xx_led_platdata {
+ unsigned int gpio;
+ unsigned int flags;
+
+ char *name;
+ char *def_trigger;
+};
+
+#endif /* __ASM_ARCH_LEDSGPIO_H */
diff --git a/include/asm-arm/arch-s3c2410/spi-gpio.h b/include/asm-arm/arch-s3c2410/spi-gpio.h
new file mode 100644
index 00000000000..258c00bca27
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/spi-gpio.h
@@ -0,0 +1,31 @@
+/* linux/include/asm-arm/arch-s3c2410/spi.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - SPI Controller platfrom_device info
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_SPIGPIO_H
+#define __ASM_ARCH_SPIGPIO_H __FILE__
+
+struct s3c2410_spigpio_info;
+struct spi_board_info;
+
+struct s3c2410_spigpio_info {
+ unsigned long pin_clk;
+ unsigned long pin_mosi;
+ unsigned long pin_miso;
+
+ unsigned long board_size;
+ struct spi_board_info *board_info;
+
+ void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
+};
+
+
+#endif /* __ASM_ARCH_SPIGPIO_H */
diff --git a/include/asm-arm/arch-s3c2410/spi.h b/include/asm-arm/arch-s3c2410/spi.h
new file mode 100644
index 00000000000..4029a1a1ab4
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/spi.h
@@ -0,0 +1,29 @@
+/* linux/include/asm-arm/arch-s3c2410/spi.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - SPI Controller platform_device info
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_SPI_H
+#define __ASM_ARCH_SPI_H __FILE__
+
+struct s3c2410_spi_info;
+struct spi_board_info;
+
+struct s3c2410_spi_info {
+ unsigned long pin_cs; /* simple gpio cs */
+
+ unsigned long board_size;
+ struct spi_board_info *board_info;
+
+ void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);
+};
+
+
+#endif /* __ASM_ARCH_SPI_H */
diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h
index 4367ec054b5..a6f6a0e44af 100644
--- a/include/asm-arm/arch-s3c2410/uncompress.h
+++ b/include/asm-arm/arch-s3c2410/uncompress.h
@@ -67,8 +67,7 @@ uart_rd(unsigned int reg)
* waiting for tx to happen...
*/
-static void
-putc(char ch)
+static void putc(int ch)
{
int cpuid = S3C2410_GSTATUS1_2410;
@@ -77,9 +76,6 @@ putc(char ch)
cpuid &= S3C2410_GSTATUS1_IDMASK;
#endif
- if (ch == '\n')
- putc('\r'); /* expand newline to \r\n */
-
if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
int level;
@@ -101,19 +97,16 @@ putc(char ch)
} else {
/* not using fifos */
- while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE);
+ while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)
+ barrier();
}
/* write byte to transmission register */
uart_wr(S3C2410_UTXH, ch);
}
-static void
-putstr(const char *ptr)
+static inline void flush(void)
{
- for (; *ptr != '\0'; ptr++) {
- putc(*ptr);
- }
}
#define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0)
diff --git a/include/asm-arm/arch-sa1100/hardware.h b/include/asm-arm/arch-sa1100/hardware.h
index 28711aaa496..ee008a5484f 100644
--- a/include/asm-arm/arch-sa1100/hardware.h
+++ b/include/asm-arm/arch-sa1100/hardware.h
@@ -14,10 +14,6 @@
#include <linux/config.h>
-/* Flushing areas */
-#define FLUSH_BASE_PHYS 0xe0000000 /* SA1100 zero bank */
-#define FLUSH_BASE 0xf5000000
-#define FLUSH_BASE_MINICACHE 0xf5800000
#define UNCACHEABLE_ADDR 0xfa050000
diff --git a/include/asm-arm/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h
index 018a9f0e398..a29fac1387c 100644
--- a/include/asm-arm/arch-sa1100/memory.h
+++ b/include/asm-arm/arch-sa1100/memory.h
@@ -91,4 +91,11 @@ void sa1111_adjust_zones(int node, unsigned long *size, unsigned long *holes);
#endif
+/*
+ * Cache flushing area - SA1100 zero bank
+ */
+#define FLUSH_BASE_PHYS 0xe0000000
+#define FLUSH_BASE 0xf5000000
+#define FLUSH_BASE_MINICACHE 0xf5100000
+
#endif
diff --git a/include/asm-arm/arch-sa1100/uncompress.h b/include/asm-arm/arch-sa1100/uncompress.h
index 43453501ee6..2601a77a6dd 100644
--- a/include/asm-arm/arch-sa1100/uncompress.h
+++ b/include/asm-arm/arch-sa1100/uncompress.h
@@ -17,7 +17,7 @@
#define UART(x) (*(volatile unsigned long *)(serial_port + (x)))
-static void putstr( const char *s )
+static void putc(int c)
{
unsigned long serial_port;
@@ -31,19 +31,16 @@ static void putstr( const char *s )
return;
} while (0);
- for (; *s; s++) {
- /* wait for space in the UART's transmitter */
- while (!(UART(UTSR1) & UTSR1_TNF));
+ /* wait for space in the UART's transmitter */
+ while (!(UART(UTSR1) & UTSR1_TNF))
+ barrier();
- /* send the character out. */
- UART(UTDR) = *s;
+ /* send the character out. */
+ UART(UTDR) = c;
+}
- /* if a LF, also do CR... */
- if (*s == 10) {
- while (!(UART(UTSR1) & UTSR1_TNF));
- UART(UTDR) = 13;
- }
- }
+static inline void flush(void)
+{
}
/*
diff --git a/include/asm-arm/arch-shark/hardware.h b/include/asm-arm/arch-shark/hardware.h
index 4d35f8c154c..ecba4526089 100644
--- a/include/asm-arm/arch-shark/hardware.h
+++ b/include/asm-arm/arch-shark/hardware.h
@@ -17,11 +17,6 @@
*/
#define IO_BASE 0xe0000000
-/*
- * RAM definitions
- */
-#define FLUSH_BASE_PHYS 0x80000000
-
#else
#define IO_BASE 0
@@ -33,7 +28,6 @@
#define ROMCARD_SIZE 0x08000000
#define ROMCARD_START 0x10000000
-#define FLUSH_BASE 0xdf000000
#define PCIO_BASE 0xe0000000
diff --git a/include/asm-arm/arch-shark/memory.h b/include/asm-arm/arch-shark/memory.h
index 95a29b4bc5d..6968d6103ea 100644
--- a/include/asm-arm/arch-shark/memory.h
+++ b/include/asm-arm/arch-shark/memory.h
@@ -39,4 +39,10 @@ static inline void __arch_adjust_zones(int node, unsigned long *zone_size, unsig
#define __virt_to_bus(x) __virt_to_phys(x)
#define __bus_to_virt(x) __phys_to_virt(x)
+/*
+ * Cache flushing area
+ */
+#define FLUSH_BASE_PHYS 0x80000000
+#define FLUSH_BASE 0xdf000000
+
#endif
diff --git a/include/asm-arm/arch-shark/uncompress.h b/include/asm-arm/arch-shark/uncompress.h
index 910a8e0a0ca..7eca6534f1b 100644
--- a/include/asm-arm/arch-shark/uncompress.h
+++ b/include/asm-arm/arch-shark/uncompress.h
@@ -9,7 +9,7 @@
#define SERIAL_BASE ((volatile unsigned char *)0x400003f8)
-static __inline__ void putc(char c)
+static inline void putc(int c)
{
int t;
@@ -18,17 +18,8 @@ static __inline__ void putc(char c)
while (t--);
}
-/*
- * This does not append a newline
- */
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
#ifdef DEBUG
diff --git a/include/asm-arm/arch-versatile/uncompress.h b/include/asm-arm/arch-versatile/uncompress.h
index 2f57499c7b9..7215133d051 100644
--- a/include/asm-arm/arch-versatile/uncompress.h
+++ b/include/asm-arm/arch-versatile/uncompress.h
@@ -25,22 +25,16 @@
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static inline void putc(int c)
{
- while (*s) {
- while (AMBA_UART_FR & (1 << 5))
- barrier();
-
- AMBA_UART_DR = *s;
+ while (AMBA_UART_FR & (1 << 5))
+ barrier();
- if (*s == '\n') {
- while (AMBA_UART_FR & (1 << 5))
- barrier();
+ AMBA_UART_DR = c;
+}
- AMBA_UART_DR = '\r';
- }
- s++;
- }
+static inline void flush(void)
+{
while (AMBA_UART_FR & (1 << 3))
barrier();
}
diff --git a/include/asm-arm/bug.h b/include/asm-arm/bug.h
index 7fb02138f58..5ab8216f520 100644
--- a/include/asm-arm/bug.h
+++ b/include/asm-arm/bug.h
@@ -2,6 +2,7 @@
#define _ASMARM_BUG_H
#include <linux/config.h>
+#include <linux/stddef.h>
#ifdef CONFIG_BUG
#ifdef CONFIG_DEBUG_BUGVERBOSE
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 09e19a783a5..746be56b1b7 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -71,6 +71,14 @@
# endif
#endif
+#if defined(CONFIG_CPU_XSC3)
+# ifdef _CACHE
+# define MULTI_CACHE 1
+# else
+# define _CACHE xsc3
+# endif
+#endif
+
#if defined(CONFIG_CPU_V6)
//# ifdef _CACHE
# define MULTI_CACHE 1
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
index e3e8541ee63..63ca7412a46 100644
--- a/include/asm-arm/dma-mapping.h
+++ b/include/asm-arm/dma-mapping.h
@@ -47,7 +47,7 @@ static inline int dma_get_cache_alignment(void)
static inline int dma_is_consistent(dma_addr_t handle)
{
- return 0;
+ return !!arch_is_coherent();
}
/*
@@ -145,7 +145,9 @@ static inline dma_addr_t
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction dir)
{
- consistent_sync(cpu_addr, size, dir);
+ if (!arch_is_coherent())
+ consistent_sync(cpu_addr, size, dir);
+
return virt_to_dma(dev, (unsigned long)cpu_addr);
}
#else
@@ -255,7 +257,9 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
sg->dma_address = page_to_dma(dev, sg->page) + sg->offset;
virt = page_address(sg->page) + sg->offset;
- consistent_sync(virt, sg->length, dir);
+
+ if (!arch_is_coherent())
+ consistent_sync(virt, sg->length, dir);
}
return nents;
@@ -310,14 +314,16 @@ static inline void
dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size,
enum dma_data_direction dir)
{
- consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
+ if (!arch_is_coherent())
+ consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
}
static inline void
dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size,
enum dma_data_direction dir)
{
- consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
+ if (!arch_is_coherent())
+ consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
}
#else
extern void dma_sync_single_for_cpu(struct device*, dma_addr_t, size_t, enum dma_data_direction);
@@ -347,7 +353,8 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
for (i = 0; i < nents; i++, sg++) {
char *virt = page_address(sg->page) + sg->offset;
- consistent_sync(virt, sg->length, dir);
+ if (!arch_is_coherent())
+ consistent_sync(virt, sg->length, dir);
}
}
@@ -359,7 +366,8 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
for (i = 0; i < nents; i++, sg++) {
char *virt = page_address(sg->page) + sg->offset;
- consistent_sync(virt, sg->length, dir);
+ if (!arch_is_coherent())
+ consistent_sync(virt, sg->length, dir);
}
}
#else
diff --git a/include/asm-arm/domain.h b/include/asm-arm/domain.h
index da1d960387d..f8ea2de4848 100644
--- a/include/asm-arm/domain.h
+++ b/include/asm-arm/domain.h
@@ -16,11 +16,29 @@
* DOMAIN_IO - domain 2 includes all IO only
* DOMAIN_USER - domain 1 includes all user memory only
* DOMAIN_KERNEL - domain 0 includes all kernel memory only
+ *
+ * The domain numbering depends on whether we support 36 physical
+ * address for I/O or not. Addresses above the 32 bit boundary can
+ * only be mapped using supersections and supersections can only
+ * be set for domain 0. We could just default to DOMAIN_IO as zero,
+ * but there may be systems with supersection support and no 36-bit
+ * addressing. In such cases, we want to map system memory with
+ * supersections to reduce TLB misses and footprint.
+ *
+ * 36-bit addressing and supersections are only available on
+ * CPUs based on ARMv6+ or the Intel XSC3 core.
*/
+#ifndef CONFIG_IO_36
#define DOMAIN_KERNEL 0
#define DOMAIN_TABLE 0
#define DOMAIN_USER 1
#define DOMAIN_IO 2
+#else
+#define DOMAIN_KERNEL 2
+#define DOMAIN_TABLE 2
+#define DOMAIN_USER 1
+#define DOMAIN_IO 0
+#endif
/*
* Domain types
diff --git a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h
index 6246bf83627..52bae088a18 100644
--- a/include/asm-arm/fpstate.h
+++ b/include/asm-arm/fpstate.h
@@ -26,7 +26,9 @@
struct vfp_hard_struct {
__u64 fpregs[16];
+#if __LINUX_ARM_ARCH__ < 6
__u32 fpmx_state;
+#endif
__u32 fpexc;
__u32 fpscr;
/*
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index b4e1146ab68..20928940759 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -172,12 +172,10 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
* virt_addr_valid(k) indicates whether a virtual address is valid
*/
#ifndef CONFIG_DISCONTIGMEM
-
-#define page_to_pfn(page) (((page) - mem_map) + PHYS_PFN_OFFSET)
-#define pfn_to_page(pfn) ((mem_map + (pfn)) - PHYS_PFN_OFFSET)
+#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET
#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
-#define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
+#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
#define PHYS_TO_NID(addr) (0)
@@ -189,13 +187,8 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
* around in memory.
*/
#include <linux/numa.h>
-
-#define page_to_pfn(page) \
- (( (page) - page_zone(page)->zone_mem_map) \
- + page_zone(page)->zone_start_pfn)
-
-#define pfn_to_page(pfn) \
- (PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT))
+#define arch_pfn_to_nid(pfn) PFN_TO_NID(pfn)
+#define arch_local_page_offset(pfn, nid) LOCAL_MAP_NR((pfn) << PAGE_SHIFT)
#define pfn_valid(pfn) \
({ \
@@ -241,6 +234,16 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
#define virt_to_dma(dev, addr) (__arch_virt_to_dma(dev, addr))
#endif
+/*
+ * Optional coherency support. Currently used only by selected
+ * Intel XSC3-based systems.
+ */
+#ifndef arch_is_coherent
+#define arch_is_coherent() 0
+#endif
+
#endif
+#include <asm-generic/memory_model.h>
+
#endif
diff --git a/include/asm-arm/numnodes.h b/include/asm-arm/numnodes.h
deleted file mode 100644
index 8df36818ebc..00000000000
--- a/include/asm-arm/numnodes.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * linux/include/asm-arm/numnodes.h
- *
- * Copyright (C) 2002 Russell King
- *
- * 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 declaration for the size of the NUMA (CONFIG_DISCONTIGMEM)
- * memory node table is the default.
- *
- * A good place to override this value is include/asm/arch/memory.h.
- */
-
-#ifndef __ASM_ARM_NUMNODES_H
-#define __ASM_ARM_NUMNODES_H
-
-#include <asm/memory.h>
-
-#ifndef NODES_SHIFT
-# define NODES_SHIFT 2 /* Normally, Max 4 Nodes */
-#endif
-
-#endif
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index 416320d9541..a404d2bf0c6 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -40,6 +40,7 @@
* v4wb - ARMv4 with writeback cache, without minicache
* v4_mc - ARMv4 with minicache
* xscale - Xscale
+ * xsc3 - XScalev3
*/
#undef _USER
#undef MULTI_USER
@@ -84,6 +85,14 @@
# endif
#endif
+#ifdef CONFIG_CPU_XSC3
+# ifdef _USER
+# define MULTI_USER 1
+# else
+# define _USER xsc3_mc
+# endif
+#endif
+
#ifdef CONFIG_CPU_COPY_V6
# define MULTI_USER 1
#endif
diff --git a/include/asm-arm/pgtable-hwdef.h b/include/asm-arm/pgtable-hwdef.h
index 1d033495cc7..1bc1f997bda 100644
--- a/include/asm-arm/pgtable-hwdef.h
+++ b/include/asm-arm/pgtable-hwdef.h
@@ -73,6 +73,7 @@
#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0)
#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */
#define PTE_EXT_APX (1 << 9) /* v6 */
+#define PTE_EXT_COHERENT (1 << 9) /* XScale3 */
#define PTE_EXT_SHARED (1 << 10) /* v6 */
#define PTE_EXT_NG (1 << 11) /* v6 */
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index e595ae24efe..e85c08d78dd 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -156,6 +156,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#define L_PTE_WRITE (1 << 5)
#define L_PTE_EXEC (1 << 6)
#define L_PTE_DIRTY (1 << 7)
+#define L_PTE_COHERENT (1 << 9) /* I/O coherent (xsc3) */
#define L_PTE_SHARED (1 << 10) /* shared between CPUs (v6) */
#define L_PTE_ASID (1 << 11) /* non-global (use ASID, v6) */
diff --git a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h
index 7bef2bf6be5..106045edb86 100644
--- a/include/asm-arm/proc-fns.h
+++ b/include/asm-arm/proc-fns.h
@@ -138,6 +138,14 @@
# define CPU_NAME cpu_xscale
# endif
# endif
+# ifdef CONFIG_CPU_XSC3
+# ifdef CPU_NAME
+# undef MULTI_CPU
+# define MULTI_CPU
+# else
+# define CPU_NAME cpu_xsc3
+# endif
+# endif
# ifdef CONFIG_CPU_V6
# ifdef CPU_NAME
# undef MULTI_CPU
diff --git a/include/asm-arm/procinfo.h b/include/asm-arm/procinfo.h
index a9c75b2c314..84252605522 100644
--- a/include/asm-arm/procinfo.h
+++ b/include/asm-arm/procinfo.h
@@ -45,8 +45,6 @@ extern unsigned int elf_hwcap;
#endif /* __ASSEMBLY__ */
-#define PROC_INFO_SZ 48
-
#define HWCAP_SWP 1
#define HWCAP_HALF 2
#define HWCAP_THUMB 4
diff --git a/include/asm-arm/rtc.h b/include/asm-arm/rtc.h
index 370dfe77589..1a5c9232a91 100644
--- a/include/asm-arm/rtc.h
+++ b/include/asm-arm/rtc.h
@@ -25,9 +25,6 @@ struct rtc_ops {
int (*proc)(char *buf);
};
-void rtc_time_to_tm(unsigned long, struct rtc_time *);
-int rtc_tm_to_time(struct rtc_time *, unsigned long *);
-int rtc_valid_tm(struct rtc_time *);
void rtc_next_alarm_time(struct rtc_time *, struct rtc_time *, struct rtc_time *);
void rtc_update(unsigned long, unsigned long);
int register_rtc(struct rtc_ops *);
diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h
index 43ad4e55878..406ca97a8ab 100644
--- a/include/asm-arm/spinlock.h
+++ b/include/asm-arm/spinlock.h
@@ -142,6 +142,9 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
: "cc");
}
+/* write_can_lock - would write_trylock() succeed? */
+#define __raw_write_can_lock(x) ((x)->lock == 0x80000000)
+
/*
* Read locks are a bit more hairy:
* - Exclusively load the lock value.
@@ -198,4 +201,7 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
+/* read_can_lock - would read_trylock() succeed? */
+#define __raw_read_can_lock(x) ((x)->lock < 0x80000000)
+
#endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index ec91d1ff032..7c9568d3030 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -108,6 +108,31 @@ extern void __show_regs(struct pt_regs *);
extern int cpu_architecture(void);
extern void cpu_init(void);
+/*
+ * Intel's XScale3 core supports some v6 features (supersections, L2)
+ * but advertises itself as v5 as it does not support the v6 ISA. For
+ * this reason, we need a way to explicitly test for this type of CPU.
+ */
+#ifndef CONFIG_CPU_XSC3
+#define cpu_is_xsc3() 0
+#else
+static inline int cpu_is_xsc3(void)
+{
+ extern unsigned int processor_id;
+
+ if ((processor_id & 0xffffe000) == 0x69056000)
+ return 1;
+
+ return 0;
+}
+#endif
+
+#if !defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_CPU_XSC3)
+#define cpu_is_xscale() 0
+#else
+#define cpu_is_xscale() 1
+#endif
+
#define set_cr(x) \
__asm__ __volatile__( \
"mcr p15, 0, %0, c1, c0, 0 @ set CR" \
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index 8f331bbd39a..cbf39a56dbe 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -308,8 +308,6 @@
#define __NR_mq_notify (__NR_SYSCALL_BASE+278)
#define __NR_mq_getsetattr (__NR_SYSCALL_BASE+279)
#define __NR_waitid (__NR_SYSCALL_BASE+280)
-
-#if defined(__ARM_EABI__) /* reserve these for un-muxing socketcall */
#define __NR_socket (__NR_SYSCALL_BASE+281)
#define __NR_bind (__NR_SYSCALL_BASE+282)
#define __NR_connect (__NR_SYSCALL_BASE+283)
@@ -327,9 +325,6 @@
#define __NR_getsockopt (__NR_SYSCALL_BASE+295)
#define __NR_sendmsg (__NR_SYSCALL_BASE+296)
#define __NR_recvmsg (__NR_SYSCALL_BASE+297)
-#endif
-
-#if defined(__ARM_EABI__) /* reserve these for un-muxing ipc */
#define __NR_semop (__NR_SYSCALL_BASE+298)
#define __NR_semget (__NR_SYSCALL_BASE+299)
#define __NR_semctl (__NR_SYSCALL_BASE+300)
@@ -341,16 +336,10 @@
#define __NR_shmdt (__NR_SYSCALL_BASE+306)
#define __NR_shmget (__NR_SYSCALL_BASE+307)
#define __NR_shmctl (__NR_SYSCALL_BASE+308)
-#endif
-
#define __NR_add_key (__NR_SYSCALL_BASE+309)
#define __NR_request_key (__NR_SYSCALL_BASE+310)
#define __NR_keyctl (__NR_SYSCALL_BASE+311)
-
-#if defined(__ARM_EABI__) /* reserved for un-muxing ipc */
#define __NR_semtimedop (__NR_SYSCALL_BASE+312)
-#endif
-
#define __NR_vserver (__NR_SYSCALL_BASE+313)
#define __NR_ioprio_set (__NR_SYSCALL_BASE+314)
#define __NR_ioprio_get (__NR_SYSCALL_BASE+315)
@@ -371,6 +360,24 @@
#define __ARM_NR_usr32 (__ARM_NR_BASE+4)
#define __ARM_NR_set_tls (__ARM_NR_BASE+5)
+/*
+ * The following syscalls are obsolete and no longer available for EABI.
+ */
+#if defined(__ARM_EABI__) && !defined(__KERNEL__)
+#undef __NR_time
+#undef __NR_umount
+#undef __NR_stime
+#undef __NR_alarm
+#undef __NR_utime
+#undef __NR_getrlimit
+#undef __NR_select
+#undef __NR_readdir
+#undef __NR_mmap
+#undef __NR_socketcall
+#undef __NR_syscall
+#undef __NR_ipc
+#endif
+
#define __sys2(x) #x
#define __sys1(x) __sys2(x)
@@ -403,7 +410,8 @@ type name(void) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : __SYS_REG_LIST() ); \
+ : __SYS_REG_LIST() \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -417,7 +425,8 @@ type name(type1 arg1) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0) ) ); \
+ : __SYS_REG_LIST( "0" (__r0) ) \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -432,7 +441,8 @@ type name(type1 arg1,type2 arg2) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) ); \
+ : __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -449,7 +459,8 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) ); \
+ : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -467,7 +478,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) ); \
+ : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -487,7 +499,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
__syscall(name) \
: "=r" (__res_r0) \
: __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \
- "r" (__r3), "r" (__r4) ) ); \
+ "r" (__r3), "r" (__r4) ) \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -507,7 +520,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
__syscall(name) \
: "=r" (__res_r0) \
: __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \
- "r" (__r3), "r" (__r4), "r" (__r5) ) ); \
+ "r" (__r3), "r" (__r4), "r" (__r5) ) \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
diff --git a/include/asm-arm/vfpmacros.h b/include/asm-arm/vfpmacros.h
index 15bd6e74c9c..27fe028b4e7 100644
--- a/include/asm-arm/vfpmacros.h
+++ b/include/asm-arm/vfpmacros.h
@@ -16,10 +16,18 @@
@ read all the working registers back into the VFP
.macro VFPFLDMIA, base
+#if __LINUX_ARM_ARCH__ < 6
LDC p11, cr0, [\base],#33*4 @ FLDMIAX \base!, {d0-d15}
+#else
+ LDC p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d0-d15}
+#endif
.endm
@ write all the working registers out of the VFP
.macro VFPFSTMIA, base
+#if __LINUX_ARM_ARCH__ < 6
STC p11, cr0, [\base],#33*4 @ FSTMIAX \base!, {d0-d15}
+#else
+ STC p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d0-d15}
+#endif
.endm
diff --git a/include/asm-arm26/memory.h b/include/asm-arm26/memory.h
index 20d78616f65..a65f10b80df 100644
--- a/include/asm-arm26/memory.h
+++ b/include/asm-arm26/memory.h
@@ -81,8 +81,7 @@ static inline void *phys_to_virt(unsigned long x)
* virt_to_page(k) convert a _valid_ virtual address to struct page *
* virt_addr_valid(k) indicates whether a virtual address is valid
*/
-#define page_to_pfn(page) (((page) - mem_map) + PHYS_PFN_OFFSET)
-#define pfn_to_page(pfn) ((mem_map + (pfn)) - PHYS_PFN_OFFSET)
+#define ARCH_PFN_OFFSET (PHYS_PFN_OFFSET)
#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
#define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
@@ -98,4 +97,5 @@ static inline void *phys_to_virt(unsigned long x)
*/
#define page_to_bus(page) (page_address(page))
+#include <asm-generic/memory_model.h>
#endif
diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h
index c99c478c482..3787633e620 100644
--- a/include/asm-cris/page.h
+++ b/include/asm-cris/page.h
@@ -43,8 +43,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/* On CRIS the PFN numbers doesn't start at 0 so we have to compensate */
/* for that before indexing into the page table starting at mem_map */
-#define pfn_to_page(pfn) (mem_map + ((pfn) - (PAGE_OFFSET >> PAGE_SHIFT)))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + (PAGE_OFFSET >> PAGE_SHIFT))
+#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
#define pfn_valid(pfn) (((pfn) - (PAGE_OFFSET >> PAGE_SHIFT)) < max_mapnr)
/* to index into the page map. our pages all start at physical addr PAGE_OFFSET so
@@ -77,6 +76,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _CRIS_PAGE_H */
diff --git a/include/asm-cris/system.h b/include/asm-cris/system.h
index 1d63c2aa8ec..b1c593b6dbf 100644
--- a/include/asm-cris/system.h
+++ b/include/asm-cris/system.h
@@ -8,7 +8,6 @@
*/
extern struct task_struct *resume(struct task_struct *prev, struct task_struct *next, int);
-#define prepare_to_switch() do { } while(0)
#define switch_to(prev,next,last) last = resume(prev,next, \
(int)&((struct task_struct *)0)->thread)
diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
index 2627bbdf8a1..bb2dfe48021 100644
--- a/include/asm-cris/unistd.h
+++ b/include/asm-cris/unistd.h
@@ -288,7 +288,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
+#define __NR_kexec_load 283
#define __NR_waitid 284
/* #define __NR_sys_setaltroot 285 */
#define __NR_add_key 286
diff --git a/include/asm-frv/futex.h b/include/asm-frv/futex.h
index fca9d90e32c..08b3d1da358 100644
--- a/include/asm-frv/futex.h
+++ b/include/asm-frv/futex.h
@@ -9,5 +9,11 @@
extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ return -ENOSYS;
+}
+
#endif
#endif
diff --git a/include/asm-frv/page.h b/include/asm-frv/page.h
index b8221b611b5..dc0f7e08a4c 100644
--- a/include/asm-frv/page.h
+++ b/include/asm-frv/page.h
@@ -57,13 +57,9 @@ extern unsigned long min_low_pfn;
extern unsigned long max_pfn;
#ifdef CONFIG_MMU
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long) ((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
-
#else
-#define pfn_to_page(pfn) (&mem_map[(pfn) - (PAGE_OFFSET >> PAGE_SHIFT)])
-#define page_to_pfn(page) ((PAGE_OFFSET >> PAGE_SHIFT) + (unsigned long) ((page) - mem_map))
+#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
#define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) < max_low_pfn)
#endif
@@ -87,6 +83,7 @@ extern unsigned long max_pfn;
#define WANT_PAGE_VIRTUAL 1
#endif
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _ASM_PAGE_H */
diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h
index f72ff0c4dc0..1734ed91bcd 100644
--- a/include/asm-frv/system.h
+++ b/include/asm-frv/system.h
@@ -18,8 +18,6 @@
struct thread_struct;
-#define prepare_to_switch() do { } while(0)
-
/*
* switch_to(prev, next) should switch from task `prev' to `next'
* `prev' will never be the same as `next'.
diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h
index 322531caa48..2662a3e12dc 100644
--- a/include/asm-frv/unistd.h
+++ b/include/asm-frv/unistd.h
@@ -289,7 +289,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
+#define __NR_kexec_load 283
#define __NR_waitid 284
/* #define __NR_sys_setaltroot 285 */
#define __NR_add_key 286
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
index 3ae2c734754..df893c16031 100644
--- a/include/asm-generic/futex.h
+++ b/include/asm-generic/futex.h
@@ -49,5 +49,11 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
return ret;
}
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ return -ENOSYS;
+}
+
#endif
#endif
diff --git a/include/asm-generic/local.h b/include/asm-generic/local.h
index 16fc00360f7..9291c24f581 100644
--- a/include/asm-generic/local.h
+++ b/include/asm-generic/local.h
@@ -4,28 +4,35 @@
#include <linux/config.h>
#include <linux/percpu.h>
#include <linux/hardirq.h>
+#include <asm/atomic.h>
#include <asm/types.h>
-/* An unsigned long type for operations which are atomic for a single
- * CPU. Usually used in combination with per-cpu variables. */
+/*
+ * A signed long type for operations which are atomic for a single CPU.
+ * Usually used in combination with per-cpu variables.
+ *
+ * This is the default implementation, which uses atomic_long_t. Which is
+ * rather pointless. The whole point behind local_t is that some processors
+ * can perform atomic adds and subtracts in a manner which is atomic wrt IRQs
+ * running on this CPU. local_t allows exploitation of such capabilities.
+ */
-#if BITS_PER_LONG == 32
/* Implement in terms of atomics. */
/* Don't use typedef: don't want them to be mixed with atomic_t's. */
typedef struct
{
- atomic_t a;
+ atomic_long_t a;
} local_t;
-#define LOCAL_INIT(i) { ATOMIC_INIT(i) }
+#define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) }
-#define local_read(l) ((unsigned long)atomic_read(&(l)->a))
-#define local_set(l,i) atomic_set((&(l)->a),(i))
-#define local_inc(l) atomic_inc(&(l)->a)
-#define local_dec(l) atomic_dec(&(l)->a)
-#define local_add(i,l) atomic_add((i),(&(l)->a))
-#define local_sub(i,l) atomic_sub((i),(&(l)->a))
+#define local_read(l) atomic_long_read(&(l)->a)
+#define local_set(l,i) atomic_long_set((&(l)->a),(i))
+#define local_inc(l) atomic_long_inc(&(l)->a)
+#define local_dec(l) atomic_long_dec(&(l)->a)
+#define local_add(i,l) atomic_long_add((i),(&(l)->a))
+#define local_sub(i,l) atomic_long_sub((i),(&(l)->a))
/* Non-atomic variants, ie. preemption disabled and won't be touched
* in interrupt, etc. Some archs can optimize this case well. */
@@ -34,68 +41,6 @@ typedef struct
#define __local_add(i,l) local_set((l), local_read(l) + (i))
#define __local_sub(i,l) local_set((l), local_read(l) - (i))
-#else /* ... can't use atomics. */
-/* Implement in terms of three variables.
- Another option would be to use local_irq_save/restore. */
-
-typedef struct
-{
- /* 0 = in hardirq, 1 = in softirq, 2 = usermode. */
- unsigned long v[3];
-} local_t;
-
-#define _LOCAL_VAR(l) ((l)->v[!in_interrupt() + !in_irq()])
-
-#define LOCAL_INIT(i) { { (i), 0, 0 } }
-
-static inline unsigned long local_read(local_t *l)
-{
- return l->v[0] + l->v[1] + l->v[2];
-}
-
-static inline void local_set(local_t *l, unsigned long v)
-{
- l->v[0] = v;
- l->v[1] = l->v[2] = 0;
-}
-
-static inline void local_inc(local_t *l)
-{
- preempt_disable();
- _LOCAL_VAR(l)++;
- preempt_enable();
-}
-
-static inline void local_dec(local_t *l)
-{
- preempt_disable();
- _LOCAL_VAR(l)--;
- preempt_enable();
-}
-
-static inline void local_add(unsigned long v, local_t *l)
-{
- preempt_disable();
- _LOCAL_VAR(l) += v;
- preempt_enable();
-}
-
-static inline void local_sub(unsigned long v, local_t *l)
-{
- preempt_disable();
- _LOCAL_VAR(l) -= v;
- preempt_enable();
-}
-
-/* Non-atomic variants, ie. preemption disabled and won't be touched
- * in interrupt, etc. Some archs can optimize this case well. */
-#define __local_inc(l) ((l)->v[0]++)
-#define __local_dec(l) ((l)->v[0]--)
-#define __local_add(i,l) ((l)->v[0] += (i))
-#define __local_sub(i,l) ((l)->v[0] -= (i))
-
-#endif /* Non-atomic implementation */
-
/* Use these for per-cpu local_t variables: on some archs they are
* much more efficient than these naive implementations. Note they take
* a variable (eg. mystruct.foo), not an address.
diff --git a/include/asm-generic/memory_model.h b/include/asm-generic/memory_model.h
new file mode 100644
index 00000000000..0cfb086dd37
--- /dev/null
+++ b/include/asm-generic/memory_model.h
@@ -0,0 +1,77 @@
+#ifndef __ASM_MEMORY_MODEL_H
+#define __ASM_MEMORY_MODEL_H
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#if defined(CONFIG_FLATMEM)
+
+#ifndef ARCH_PFN_OFFSET
+#define ARCH_PFN_OFFSET (0UL)
+#endif
+
+#elif defined(CONFIG_DISCONTIGMEM)
+
+#ifndef arch_pfn_to_nid
+#define arch_pfn_to_nid(pfn) pfn_to_nid(pfn)
+#endif
+
+#ifndef arch_local_page_offset
+#define arch_local_page_offset(pfn, nid) \
+ ((pfn) - NODE_DATA(nid)->node_start_pfn)
+#endif
+
+#endif /* CONFIG_DISCONTIGMEM */
+
+#ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE
+struct page;
+/* this is useful when inlined pfn_to_page is too big */
+extern struct page *pfn_to_page(unsigned long pfn);
+extern unsigned long page_to_pfn(struct page *page);
+#else
+/*
+ * supports 3 memory models.
+ */
+#if defined(CONFIG_FLATMEM)
+
+#define pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET))
+#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + \
+ ARCH_PFN_OFFSET)
+#elif defined(CONFIG_DISCONTIGMEM)
+
+#define pfn_to_page(pfn) \
+({ unsigned long __pfn = (pfn); \
+ unsigned long __nid = arch_pfn_to_nid(pfn); \
+ NODE_DATA(__nid)->node_mem_map + arch_local_page_offset(__pfn, __nid);\
+})
+
+#define page_to_pfn(pg) \
+({ struct page *__pg = (pg); \
+ struct pglist_data *__pgdat = NODE_DATA(page_to_nid(__pg)); \
+ (unsigned long)(__pg - __pgdat->node_mem_map) + \
+ __pgdat->node_start_pfn; \
+})
+
+#elif defined(CONFIG_SPARSEMEM)
+/*
+ * Note: section's mem_map is encorded to reflect its start_pfn.
+ * section[i].section_mem_map == mem_map's address - start_pfn;
+ */
+#define page_to_pfn(pg) \
+({ struct page *__pg = (pg); \
+ int __sec = page_to_section(__pg); \
+ __pg - __section_mem_map_addr(__nr_to_section(__sec)); \
+})
+
+#define pfn_to_page(pfn) \
+({ unsigned long __pfn = (pfn); \
+ struct mem_section *__sec = __pfn_to_section(__pfn); \
+ __section_mem_map_addr(__sec) + __pfn; \
+})
+#endif /* CONFIG_FLATMEM/DISCONTIGMEM/SPARSEMEM */
+#endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/asm-generic/mutex-dec.h b/include/asm-generic/mutex-dec.h
index 40c6d1f8659..29c6ac34e23 100644
--- a/include/asm-generic/mutex-dec.h
+++ b/include/asm-generic/mutex-dec.h
@@ -17,13 +17,14 @@
* it wasn't 1 originally. This function MUST leave the value lower than
* 1 even when the "1" assertion wasn't true.
*/
-#define __mutex_fastpath_lock(count, fail_fn) \
-do { \
- if (unlikely(atomic_dec_return(count) < 0)) \
- fail_fn(count); \
- else \
- smp_mb(); \
-} while (0)
+static inline void
+__mutex_fastpath_lock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
+{
+ if (unlikely(atomic_dec_return(count) < 0))
+ fail_fn(count);
+ else
+ smp_mb();
+}
/**
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
@@ -36,7 +37,7 @@ do { \
* or anything the slow path function returns.
*/
static inline int
-__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
+__mutex_fastpath_lock_retval(atomic_t *count, fastcall int (*fail_fn)(atomic_t *))
{
if (unlikely(atomic_dec_return(count) < 0))
return fail_fn(count);
@@ -59,12 +60,13 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
* __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
* to return 0 otherwise.
*/
-#define __mutex_fastpath_unlock(count, fail_fn) \
-do { \
- smp_mb(); \
- if (unlikely(atomic_inc_return(count) <= 0)) \
- fail_fn(count); \
-} while (0)
+static inline void
+__mutex_fastpath_unlock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
+{
+ smp_mb();
+ if (unlikely(atomic_inc_return(count) <= 0))
+ fail_fn(count);
+}
#define __mutex_slowpath_needs_to_unlock() 1
diff --git a/include/asm-generic/mutex-xchg.h b/include/asm-generic/mutex-xchg.h
index 1d24f47e6c4..32a2100c1ae 100644
--- a/include/asm-generic/mutex-xchg.h
+++ b/include/asm-generic/mutex-xchg.h
@@ -3,7 +3,7 @@
*
* Generic implementation of the mutex fastpath, based on xchg().
*
- * NOTE: An xchg based implementation is less optimal than an atomic
+ * NOTE: An xchg based implementation might be less optimal than an atomic
* decrement/increment based implementation. If your architecture
* has a reasonable atomic dec/inc then you should probably use
* asm-generic/mutex-dec.h instead, or you could open-code an
@@ -22,14 +22,14 @@
* wasn't 1 originally. This function MUST leave the value lower than 1
* even when the "1" assertion wasn't true.
*/
-#define __mutex_fastpath_lock(count, fail_fn) \
-do { \
- if (unlikely(atomic_xchg(count, 0) != 1)) \
- fail_fn(count); \
- else \
- smp_mb(); \
-} while (0)
-
+static inline void
+__mutex_fastpath_lock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
+{
+ if (unlikely(atomic_xchg(count, 0) != 1))
+ fail_fn(count);
+ else
+ smp_mb();
+}
/**
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
@@ -42,7 +42,7 @@ do { \
* or anything the slow path function returns
*/
static inline int
-__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
+__mutex_fastpath_lock_retval(atomic_t *count, fastcall int (*fail_fn)(atomic_t *))
{
if (unlikely(atomic_xchg(count, 0) != 1))
return fail_fn(count);
@@ -64,12 +64,13 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
* __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
* to return 0 otherwise.
*/
-#define __mutex_fastpath_unlock(count, fail_fn) \
-do { \
- smp_mb(); \
- if (unlikely(atomic_xchg(count, 1) != 0)) \
- fail_fn(count); \
-} while (0)
+static inline void
+__mutex_fastpath_unlock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
+{
+ smp_mb();
+ if (unlikely(atomic_xchg(count, 1) != 0))
+ fail_fn(count);
+}
#define __mutex_slowpath_needs_to_unlock() 0
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index 78cf45547e3..c0caf433a7d 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -19,7 +19,7 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
#define percpu_modcopy(pcpudst, src, size) \
do { \
unsigned int __i; \
- for_each_cpu(__i) \
+ for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset[__i], \
(src), (size)); \
} while (0)
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 358e4d309ce..c2059a3a062 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -159,17 +159,8 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
#define lazy_mmu_prot_update(pte) do { } while (0)
#endif
-#ifndef __HAVE_ARCH_MULTIPLE_ZERO_PAGE
+#ifndef __HAVE_ARCH_MOVE_PTE
#define move_pte(pte, prot, old_addr, new_addr) (pte)
-#else
-#define move_pte(pte, prot, old_addr, new_addr) \
-({ \
- pte_t newpte = (pte); \
- if (pte_present(pte) && pfn_valid(pte_pfn(pte)) && \
- pte_page(pte) == ZERO_PAGE(old_addr)) \
- newpte = mk_pte(ZERO_PAGE(new_addr), (prot)); \
- newpte; \
-})
#endif
/*
diff --git a/include/asm-h8300/page.h b/include/asm-h8300/page.h
index cd35b1cc6cd..6472c9f8822 100644
--- a/include/asm-h8300/page.h
+++ b/include/asm-h8300/page.h
@@ -71,8 +71,7 @@ extern unsigned long memory_end;
#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
#define pfn_valid(page) (page < max_mapnr)
-#define pfn_to_page(pfn) virt_to_page(pfn_to_virt(pfn))
-#define page_to_pfn(page) virt_to_pfn(page_to_virt(page))
+#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
((void *)(kaddr) < (void *)memory_end))
@@ -81,6 +80,7 @@ extern unsigned long memory_end;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _H8300_PAGE_H */
diff --git a/include/asm-h8300/system.h b/include/asm-h8300/system.h
index dfe96c7121c..8e81cf665e7 100644
--- a/include/asm-h8300/system.h
+++ b/include/asm-h8300/system.h
@@ -4,8 +4,6 @@
#include <linux/config.h> /* get configuration macros */
#include <linux/linkage.h>
-#define prepare_to_switch() do { } while(0)
-
/*
* switch_to(n) should switch tasks to task ptr, first checking that
* ptr isn't the current task, in which case it does nothing. This
diff --git a/include/asm-h8300/unistd.h b/include/asm-h8300/unistd.h
index 56a4a5686c8..adb05159379 100644
--- a/include/asm-h8300/unistd.h
+++ b/include/asm-h8300/unistd.h
@@ -285,7 +285,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
+#define __NR_kexec_load 283
#define __NR_waitid 284
/* #define __NR_sys_setaltroot 285 */
#define __NR_add_key 286
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index ff9ac8d19eb..288233fd77d 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -139,6 +139,8 @@ void switch_ipi_to_APIC_timer(void *cpumask);
extern int timer_over_8254;
+extern int modern_apic(void);
+
#else /* !CONFIG_X86_LOCAL_APIC */
static inline void lapic_shutdown(void) { }
diff --git a/include/asm-i386/apicdef.h b/include/asm-i386/apicdef.h
index 03185cef8e0..9f6995341fd 100644
--- a/include/asm-i386/apicdef.h
+++ b/include/asm-i386/apicdef.h
@@ -37,6 +37,7 @@
#define APIC_SPIV_FOCUS_DISABLED (1<<9)
#define APIC_SPIV_APIC_ENABLED (1<<8)
#define APIC_ISR 0x100
+#define APIC_ISR_NR 0x8 /* Number of 32 bit ISR registers. */
#define APIC_TMR 0x180
#define APIC_IRR 0x200
#define APIC_ESR 0x280
@@ -120,7 +121,6 @@
*/
#define u32 unsigned int
-#define lapic ((volatile struct local_apic *)APIC_BASE)
struct local_apic {
diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h
index 22d80ece95c..4ddce5296a7 100644
--- a/include/asm-i386/atomic.h
+++ b/include/asm-i386/atomic.h
@@ -183,6 +183,7 @@ static __inline__ int atomic_add_return(int i, atomic_t *v)
{
int __i;
#ifdef CONFIG_M386
+ unsigned long flags;
if(unlikely(boot_cpu_data.x86==3))
goto no_xadd;
#endif
@@ -196,10 +197,10 @@ static __inline__ int atomic_add_return(int i, atomic_t *v)
#ifdef CONFIG_M386
no_xadd: /* Legacy 386 processor */
- local_irq_disable();
+ local_irq_save(flags);
__i = atomic_read(v);
atomic_set(v, i + __i);
- local_irq_enable();
+ local_irq_restore(flags);
return i + __i;
#endif
}
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index 5c0b5876b93..b44bfc6239c 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -71,6 +71,7 @@
#define X86_FEATURE_P4 (3*32+ 7) /* P4 */
#define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
#define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */
+#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
diff --git a/include/asm-i386/e820.h b/include/asm-i386/e820.h
index edf65be21a9..ca82acb8cb1 100644
--- a/include/asm-i386/e820.h
+++ b/include/asm-i386/e820.h
@@ -35,6 +35,10 @@ struct e820map {
};
extern struct e820map e820;
+
+extern int e820_all_mapped(unsigned long start, unsigned long end,
+ unsigned type);
+
#endif/*!__ASSEMBLY__*/
#endif/*__E820_HEADER*/
diff --git a/include/asm-i386/floppy.h b/include/asm-i386/floppy.h
index 79727afb94c..03403045c18 100644
--- a/include/asm-i386/floppy.h
+++ b/include/asm-i386/floppy.h
@@ -56,7 +56,6 @@ static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
register unsigned char st;
#undef TRACE_FLPY_INT
-#define NO_FLOPPY_ASSEMBLER
#ifdef TRACE_FLPY_INT
static int calls=0;
@@ -71,38 +70,6 @@ static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
bytes = virtual_dma_count;
#endif
-#ifndef NO_FLOPPY_ASSEMBLER
- __asm__ (
- "testl %1,%1"
- "je 3f"
-"1: inb %w4,%b0"
- "andb $160,%b0"
- "cmpb $160,%b0"
- "jne 2f"
- "incw %w4"
- "testl %3,%3"
- "jne 4f"
- "inb %w4,%b0"
- "movb %0,(%2)"
- "jmp 5f"
-"4: movb (%2),%0"
- "outb %b0,%w4"
-"5: decw %w4"
- "outb %0,$0x80"
- "decl %1"
- "incl %2"
- "testl %1,%1"
- "jne 1b"
-"3: inb %w4,%b0"
-"2: "
- : "=a" ((char) st),
- "=c" ((long) virtual_dma_count),
- "=S" ((long) virtual_dma_addr)
- : "b" ((long) virtual_dma_mode),
- "d" ((short) virtual_dma_port+4),
- "1" ((long) virtual_dma_count),
- "2" ((long) virtual_dma_addr));
-#else
{
register int lcount;
register char *lptr;
@@ -122,7 +89,6 @@ static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
virtual_dma_addr = lptr;
st = inb(virtual_dma_port+4);
}
-#endif
#ifdef TRACE_FLPY_INT
calls++;
diff --git a/include/asm-i386/futex.h b/include/asm-i386/futex.h
index 44b9db80647..7b8ceefd010 100644
--- a/include/asm-i386/futex.h
+++ b/include/asm-i386/futex.h
@@ -104,5 +104,32 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
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;
+
+ __asm__ __volatile__(
+ "1: " LOCK_PREFIX "cmpxchgl %3, %1 \n"
+
+ "2: .section .fixup, \"ax\" \n"
+ "3: mov %2, %0 \n"
+ " jmp 2b \n"
+ " .previous \n"
+
+ " .section __ex_table, \"a\" \n"
+ " .align 8 \n"
+ " .long 1b,3b \n"
+ " .previous \n"
+
+ : "=a" (oldval), "=m" (*uaddr)
+ : "i" (-EFAULT), "r" (newval), "0" (oldval)
+ : "memory"
+ );
+
+ return oldval;
+}
+
#endif
#endif
diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h
index 16ef9f996e3..7f1a8a6ee32 100644
--- a/include/asm-i386/hpet.h
+++ b/include/asm-i386/hpet.h
@@ -89,6 +89,7 @@
* then 32 bit HPET counter wrapsaround in less than 0.5 sec.
*/
#define HPET_MIN_PERIOD (100000UL)
+#define HPET_TICK_RATE (HZ * 100000UL)
extern unsigned long hpet_tick; /* hpet clks count per tick */
extern unsigned long hpet_address; /* hpet memory map physical address */
diff --git a/include/asm-i386/i387.h b/include/asm-i386/i387.h
index 152d0baa576..bc1d6edae1e 100644
--- a/include/asm-i386/i387.h
+++ b/include/asm-i386/i387.h
@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/init.h>
+#include <linux/kernel_stat.h>
#include <asm/processor.h>
#include <asm/sigcontext.h>
#include <asm/user.h>
@@ -38,17 +39,38 @@ extern void init_fpu(struct task_struct *);
extern void kernel_fpu_begin(void);
#define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
+/* We need a safe address that is cheap to find and that is already
+ in L1 during context switch. The best choices are unfortunately
+ different for UP and SMP */
+#ifdef CONFIG_SMP
+#define safe_address (__per_cpu_offset[0])
+#else
+#define safe_address (kstat_cpu(0).cpustat.user)
+#endif
+
/*
* These must be called with preempt disabled
*/
static inline void __save_init_fpu( struct task_struct *tsk )
{
+ /* Use more nops than strictly needed in case the compiler
+ varies code */
alternative_input(
- "fnsave %1 ; fwait ;" GENERIC_NOP2,
- "fxsave %1 ; fnclex",
+ "fnsave %[fx] ;fwait;" GENERIC_NOP8 GENERIC_NOP4,
+ "fxsave %[fx]\n"
+ "bt $7,%[fsw] ; jnc 1f ; fnclex\n1:",
X86_FEATURE_FXSR,
- "m" (tsk->thread.i387.fxsave)
- :"memory");
+ [fx] "m" (tsk->thread.i387.fxsave),
+ [fsw] "m" (tsk->thread.i387.fxsave.swd) : "memory");
+ /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
+ is pending. Clear the x87 state here by setting it to fixed
+ values. safe_address is a random variable that should be in L1 */
+ alternative_input(
+ GENERIC_NOP8 GENERIC_NOP2,
+ "emms\n\t" /* clear stack tags */
+ "fildl %[addr]", /* set F?P to defined value */
+ X86_FEATURE_FXSAVE_LEAK,
+ [addr] "m" (safe_address));
task_thread_info(tsk)->status &= ~TS_USEDFPU;
}
diff --git a/include/asm-i386/io_apic.h b/include/asm-i386/io_apic.h
index 51c4e5fe606..d92e253f7f6 100644
--- a/include/asm-i386/io_apic.h
+++ b/include/asm-i386/io_apic.h
@@ -200,6 +200,7 @@ extern int io_apic_get_unique_id (int ioapic, int apic_id);
extern int io_apic_get_version (int ioapic);
extern int io_apic_get_redir_entries (int ioapic);
extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low);
+extern int timer_uses_ioapic_pin_0;
#endif /* CONFIG_ACPI */
extern int (*ioapic_renumber_irq)(int ioapic, int irq);
diff --git a/include/asm-i386/kdebug.h b/include/asm-i386/kdebug.h
index 316138e8991..96d0828ce09 100644
--- a/include/asm-i386/kdebug.h
+++ b/include/asm-i386/kdebug.h
@@ -17,11 +17,9 @@ struct die_args {
int signr;
};
-/* Note - you should never unregister because that can race with NMIs.
- If you really want to do it first unregister - then synchronize_sched - then free.
- */
-int register_die_notifier(struct notifier_block *nb);
-extern struct notifier_block *i386die_chain;
+extern int register_die_notifier(struct notifier_block *);
+extern int unregister_die_notifier(struct notifier_block *);
+extern struct atomic_notifier_head i386die_chain;
/* Grossly misnamed. */
@@ -51,7 +49,7 @@ static inline int notify_die(enum die_val val, const char *str,
.trapnr = trap,
.signr = sig
};
- return notifier_call_chain(&i386die_chain, val, &args);
+ return atomic_notifier_call_chain(&i386die_chain, val, &args);
}
#endif
diff --git a/include/asm-i386/local.h b/include/asm-i386/local.h
index 0177da80dde..e67fa08260f 100644
--- a/include/asm-i386/local.h
+++ b/include/asm-i386/local.h
@@ -5,7 +5,7 @@
typedef struct
{
- volatile unsigned long counter;
+ volatile long counter;
} local_t;
#define LOCAL_INIT(i) { (i) }
@@ -29,7 +29,7 @@ static __inline__ void local_dec(local_t *v)
:"m" (v->counter));
}
-static __inline__ void local_add(unsigned long i, local_t *v)
+static __inline__ void local_add(long i, local_t *v)
{
__asm__ __volatile__(
"addl %1,%0"
@@ -37,7 +37,7 @@ static __inline__ void local_add(unsigned long i, local_t *v)
:"ir" (i), "m" (v->counter));
}
-static __inline__ void local_sub(unsigned long i, local_t *v)
+static __inline__ void local_sub(long i, local_t *v)
{
__asm__ __volatile__(
"subl %1,%0"
diff --git a/include/asm-i386/mach-default/mach_time.h b/include/asm-i386/mach-default/mach_time.h
index b749aa44a86..31eb5de6f3d 100644
--- a/include/asm-i386/mach-default/mach_time.h
+++ b/include/asm-i386/mach-default/mach_time.h
@@ -82,21 +82,8 @@ static inline int mach_set_rtc_mmss(unsigned long nowtime)
static inline unsigned long mach_get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- int i;
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
+ do {
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
hour = CMOS_READ(RTC_HOURS);
@@ -104,16 +91,18 @@ static inline unsigned long mach_get_cmos_time(void)
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
} while (sec != CMOS_READ(RTC_SECONDS));
- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
- if ((year += 1900) < 1970)
+
+ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
+
+ year += 1900;
+ if (year < 1970)
year += 100;
return mktime(year, mon, day, hour, min, sec);
diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
index 74f595d8057..e33e9f9e4c6 100644
--- a/include/asm-i386/mmzone.h
+++ b/include/asm-i386/mmzone.h
@@ -70,8 +70,6 @@ static inline int pfn_to_nid(unsigned long pfn)
#endif
}
-#define node_localnr(pfn, nid) ((pfn) - node_data[nid]->node_start_pfn)
-
/*
* Following are macros that each numa implmentation must define.
*/
@@ -86,21 +84,6 @@ static inline int pfn_to_nid(unsigned long pfn)
/* XXX: FIXME -- wli */
#define kern_addr_valid(kaddr) (0)
-#define pfn_to_page(pfn) \
-({ \
- unsigned long __pfn = pfn; \
- int __node = pfn_to_nid(__pfn); \
- &NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)]; \
-})
-
-#define page_to_pfn(pg) \
-({ \
- struct page *__page = pg; \
- struct zone *__zone = page_zone(__page); \
- (unsigned long)(__page - __zone->zone_mem_map) \
- + __zone->zone_start_pfn; \
-})
-
#ifdef CONFIG_X86_NUMAQ /* we have contiguous memory on NUMA-Q */
#define pfn_valid(pfn) ((pfn) < num_physpages)
#else
diff --git a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h
index 62113d3bfdc..770bf6da8c3 100644
--- a/include/asm-i386/mpspec.h
+++ b/include/asm-i386/mpspec.h
@@ -18,7 +18,6 @@ extern void find_smp_config (void);
extern void get_smp_config (void);
extern int nr_ioapics;
extern int apic_version [MAX_APICS];
-extern int mp_bus_id_to_type [MAX_MP_BUSSES];
extern int mp_irq_entries;
extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
extern int mpc_default_type;
diff --git a/include/asm-i386/numnodes.h b/include/asm-i386/numnodes.h
deleted file mode 100644
index a61f38c8176..00000000000
--- a/include/asm-i386/numnodes.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-#include <linux/config.h>
-
-#ifdef CONFIG_X86_NUMAQ
-
-/* Max 16 Nodes */
-#define NODES_SHIFT 4
-
-#elif defined(CONFIG_ACPI_SRAT)
-
-/* Max 8 Nodes */
-#define NODES_SHIFT 3
-
-#endif /* CONFIG_X86_NUMAQ */
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index 997ca5d1787..30f52a2263b 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -126,8 +126,6 @@ extern int page_is_ram(unsigned long pagenr);
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
#ifdef CONFIG_FLATMEM
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#endif /* CONFIG_FLATMEM */
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
@@ -141,6 +139,7 @@ extern int page_is_ram(unsigned long pagenr);
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _I386_PAGE_H */
diff --git a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h
index 27bde973abc..2756d4b04c2 100644
--- a/include/asm-i386/pgtable-2level.h
+++ b/include/asm-i386/pgtable-2level.h
@@ -18,6 +18,9 @@
#define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
+#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
+#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0)
+
#define ptep_get_and_clear(mm,addr,xp) __pte(xchg(&(xp)->pte_low, 0))
#define pte_same(a, b) ((a).pte_low == (b).pte_low)
#define pte_page(x) pfn_to_page(pte_pfn(x))
diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
index 36a5aa63cbb..dccb1b3337a 100644
--- a/include/asm-i386/pgtable-3level.h
+++ b/include/asm-i386/pgtable-3level.h
@@ -85,6 +85,26 @@ static inline void pud_clear (pud_t * pud) { }
#define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
pmd_index(address))
+/*
+ * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
+ * entry, so clear the bottom half first and enforce ordering with a compiler
+ * barrier.
+ */
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ ptep->pte_low = 0;
+ smp_wmb();
+ ptep->pte_high = 0;
+}
+
+static inline void pmd_clear(pmd_t *pmd)
+{
+ u32 *tmp = (u32 *)pmd;
+ *tmp = 0;
+ smp_wmb();
+ *(tmp + 1) = 0;
+}
+
static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t res;
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index ee056c41a9f..672c3f76b9d 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -204,12 +204,10 @@ extern unsigned long long __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
extern unsigned long pg0[];
#define pte_present(x) ((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
/* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
#define pmd_none(x) (!(unsigned long)pmd_val(x))
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
-#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0)
#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
@@ -268,7 +266,7 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
pte_t pte;
if (full) {
pte = *ptep;
- *ptep = __pte(0);
+ pte_clear(mm, addr, ptep);
} else {
pte = ptep_get_and_clear(mm, addr, ptep);
}
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index feca5d961e2..805f0dcda46 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -20,6 +20,7 @@
#include <linux/config.h>
#include <linux/threads.h>
#include <asm/percpu.h>
+#include <linux/cpumask.h>
/* flag for disabling the tsc */
extern int tsc_disable;
@@ -67,6 +68,9 @@ struct cpuinfo_x86 {
char pad0;
int x86_power;
unsigned long loops_per_jiffy;
+#ifdef CONFIG_SMP
+ cpumask_t llc_shared_map; /* cpus sharing the last level cache */
+#endif
unsigned char x86_max_cores; /* cpuid returned max cores value */
unsigned char booted_cores; /* number of cores as seen by OS */
unsigned char apicid;
@@ -103,6 +107,7 @@ extern struct cpuinfo_x86 cpu_data[];
extern int phys_proc_id[NR_CPUS];
extern int cpu_core_id[NR_CPUS];
+extern int cpu_llc_id[NR_CPUS];
extern char ignore_fpu_irq;
extern void identify_cpu(struct cpuinfo_x86 *);
@@ -616,8 +621,6 @@ struct extended_sigtable {
unsigned int reserved[3];
struct extended_signature sigs[0];
};
-/* '6' because it used to be for P6 only (but now covers Pentium 4 as well) */
-#define MICROCODE_IOCFREE _IO('6',0)
/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
static inline void rep_nop(void)
diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h
index 826a8ca50ac..ee941457b55 100644
--- a/include/asm-i386/setup.h
+++ b/include/asm-i386/setup.h
@@ -6,9 +6,7 @@
#ifndef _i386_SETUP_H
#define _i386_SETUP_H
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
+#include <linux/pfn.h>
/*
* Reserved space for vmalloc and iomap - defined in asm/page.h
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index aa958c6ee83..b94e5eeef91 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -112,4 +112,6 @@ extern unsigned long node_remap_size[];
#endif /* CONFIG_NUMA */
+extern cpumask_t cpu_coregroup_map(int cpu);
+
#endif /* _ASM_I386_TOPOLOGY_H */
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index d8afd0e3b81..eb4b152c82f 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -288,7 +288,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
+#define __NR_kexec_load 283
#define __NR_waitid 284
/* #define __NR_sys_setaltroot 285 */
#define __NR_add_key 286
@@ -316,8 +316,14 @@
#define __NR_pselect6 308
#define __NR_ppoll 309
#define __NR_unshare 310
+#define __NR_set_robust_list 311
+#define __NR_get_robust_list 312
+#define __NR_splice 313
+#define __NR_sync_file_range 314
+#define __NR_tee 315
+#define __NR_vmsplice 316
-#define NR_syscalls 311
+#define NR_syscalls 317
/*
* user-visible error numbers are in the range -1 - -128: see
diff --git a/include/asm-ia64/acpi-ext.h b/include/asm-ia64/acpi-ext.h
index 56d2ddc97b3..734d137dda6 100644
--- a/include/asm-ia64/acpi-ext.h
+++ b/include/asm-ia64/acpi-ext.h
@@ -1,12 +1,15 @@
/*
- * ia64/platform/hp/common/hp_acpi.h
+ * (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P.
+ * Alex Williamson <alex.williamson@hp.com>
+ * Bjorn Helgaas <bjorn.helgaas@hp.com>
*
- * Copyright (C) 2003 Hewlett-Packard
- * Copyright (C) Alex Williamson
- * Copyright (C) Bjorn Helgaas
+ * 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.
*
* Vendor specific extensions to ACPI.
*/
+
#ifndef _ASM_IA64_ACPI_EXT_H
#define _ASM_IA64_ACPI_EXT_H
diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
index d734585a23c..09a5dd0e44a 100644
--- a/include/asm-ia64/acpi.h
+++ b/include/asm-ia64/acpi.h
@@ -110,9 +110,8 @@ extern void prefill_possible_map(void);
extern int additional_cpus;
#ifdef CONFIG_ACPI_NUMA
-/* Proximity bitmap length; _PXM is at most 255 (8 bit)*/
-#ifdef CONFIG_IA64_NR_NODES
-#define MAX_PXM_DOMAINS CONFIG_IA64_NR_NODES
+#if MAX_NUMNODES > 256
+#define MAX_PXM_DOMAINS MAX_NUMNODES
#else
#define MAX_PXM_DOMAINS (256)
#endif
diff --git a/include/asm-ia64/asmmacro.h b/include/asm-ia64/asmmacro.h
index d4cec32083d..edf2cebb296 100644
--- a/include/asm-ia64/asmmacro.h
+++ b/include/asm-ia64/asmmacro.h
@@ -38,6 +38,10 @@ name:
/*
* Helper macros for accessing user memory.
+ *
+ * When adding any new .section/.previous entries here, make sure to
+ * also add it to the DISCARD section in arch/ia64/kernel/gate.lds.S or
+ * unpleasant things will happen.
*/
.section "__ex_table", "a" // declare section & section attributes
diff --git a/include/asm-ia64/bitops.h b/include/asm-ia64/bitops.h
index 90921e16279..6cc517e212a 100644
--- a/include/asm-ia64/bitops.h
+++ b/include/asm-ia64/bitops.h
@@ -11,7 +11,6 @@
#include <linux/compiler.h>
#include <linux/types.h>
-#include <asm/bitops.h>
#include <asm/intrinsics.h>
/**
diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h
index c0b19106665..40d01d80610 100644
--- a/include/asm-ia64/compat.h
+++ b/include/asm-ia64/compat.h
@@ -189,6 +189,12 @@ compat_ptr (compat_uptr_t uptr)
return (void __user *) (unsigned long) uptr;
}
+static inline compat_uptr_t
+ptr_to_compat(void __user *uptr)
+{
+ return (u32)(unsigned long)uptr;
+}
+
static __inline__ void __user *
compat_alloc_user_space (long len)
{
diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h
index 8b01a083dde..c195a9ad125 100644
--- a/include/asm-ia64/kdebug.h
+++ b/include/asm-ia64/kdebug.h
@@ -40,7 +40,7 @@ struct die_args {
extern int register_die_notifier(struct notifier_block *);
extern int unregister_die_notifier(struct notifier_block *);
-extern struct notifier_block *ia64die_chain;
+extern struct atomic_notifier_head ia64die_chain;
enum die_val {
DIE_BREAK = 1,
@@ -58,6 +58,8 @@ enum die_val {
DIE_MCA_RENDZVOUS_ENTER,
DIE_MCA_RENDZVOUS_PROCESS,
DIE_MCA_RENDZVOUS_LEAVE,
+ DIE_MCA_NEW_TIMEOUT,
+ DIE_INIT_ENTER,
DIE_INIT_MONARCH_ENTER,
DIE_INIT_MONARCH_PROCESS,
DIE_INIT_MONARCH_LEAVE,
@@ -81,7 +83,7 @@ static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs,
.signr = sig
};
- return notifier_call_chain(&ia64die_chain, val, &args);
+ return atomic_notifier_call_chain(&ia64die_chain, val, &args);
}
#endif
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
index c3e4ed8a3e1..a9c995a86c2 100644
--- a/include/asm-ia64/machvec.h
+++ b/include/asm-ia64/machvec.h
@@ -347,9 +347,11 @@ extern ia64_mv_dma_supported swiotlb_dma_supported;
#endif
#ifndef platform_pci_legacy_read
# define platform_pci_legacy_read ia64_pci_legacy_read
+extern int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size);
#endif
#ifndef platform_pci_legacy_write
# define platform_pci_legacy_write ia64_pci_legacy_write
+extern int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size);
#endif
#ifndef platform_inb
# define platform_inb __ia64_inb
diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
index bfbbb8da79c..9c5389b7e62 100644
--- a/include/asm-ia64/mca.h
+++ b/include/asm-ia64/mca.h
@@ -148,6 +148,11 @@ extern int ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *)
extern void ia64_unreg_MCA_extension(void);
extern u64 ia64_get_rnat(u64 *);
+struct ia64_mca_notify_die {
+ struct ia64_sal_os_state *sos;
+ int *monarch_cpu;
+};
+
#else /* __ASSEMBLY__ */
#define IA64_MCA_CORRECTED 0x0 /* Error has been corrected by OS_MCA */
diff --git a/include/asm-ia64/mutex.h b/include/asm-ia64/mutex.h
index 5a3224f6af3..bed73a643a5 100644
--- a/include/asm-ia64/mutex.h
+++ b/include/asm-ia64/mutex.h
@@ -84,7 +84,7 @@ __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
static inline int
__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
{
- if (likely(cmpxchg_acq(count, 1, 0)) == 1)
+ if (cmpxchg_acq(count, 1, 0) == 1)
return 1;
return 0;
}
diff --git a/include/asm-ia64/numnodes.h b/include/asm-ia64/numnodes.h
deleted file mode 100644
index e9d356f549d..00000000000
--- a/include/asm-ia64/numnodes.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-#ifdef CONFIG_IA64_DIG
-/* Max 8 Nodes */
-# define NODES_SHIFT 3
-#elif defined(CONFIG_IA64_HP_ZX1) || defined(CONFIG_IA64_HP_ZX1_SWIOTLB)
-/* Max 32 Nodes */
-# define NODES_SHIFT 5
-#elif defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
-# if CONFIG_IA64_NR_NODES == 256
-# define NODES_SHIFT 8
-# elif CONFIG_IA64_NR_NODES <= 512
-# define NODES_SHIFT 9
-# elif CONFIG_IA64_NR_NODES <= 1024
-# define NODES_SHIFT 10
-# endif
-#endif
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 6e9aa23250c..2087825eefa 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -106,17 +106,25 @@ extern int ia64_pfn_valid (unsigned long pfn);
# define ia64_pfn_valid(pfn) 1
#endif
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+extern struct page *vmem_map;
+#ifdef CONFIG_DISCONTIGMEM
+# define page_to_pfn(page) ((unsigned long) (page - vmem_map))
+# define pfn_to_page(pfn) (vmem_map + (pfn))
+#endif
+#endif
+
+#if defined(CONFIG_FLATMEM) || defined(CONFIG_SPARSEMEM)
+/* FLATMEM always configures mem_map (mem_map = vmem_map if necessary) */
+#include <asm-generic/memory_model.h>
+#endif
+
#ifdef CONFIG_FLATMEM
# define pfn_valid(pfn) (((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
-# define page_to_pfn(page) ((unsigned long) (page - mem_map))
-# define pfn_to_page(pfn) (mem_map + (pfn))
#elif defined(CONFIG_DISCONTIGMEM)
-extern struct page *vmem_map;
extern unsigned long min_low_pfn;
extern unsigned long max_low_pfn;
# define pfn_valid(pfn) (((pfn) >= min_low_pfn) && ((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
-# define page_to_pfn(page) ((unsigned long) (page - vmem_map))
-# define pfn_to_page(pfn) (vmem_map + (pfn))
#endif
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
index 4e7e6f23b08..37e52a2836b 100644
--- a/include/asm-ia64/pal.h
+++ b/include/asm-ia64/pal.h
@@ -68,6 +68,7 @@
#define PAL_SHUTDOWN 40 /* enter processor shutdown state */
#define PAL_PREFETCH_VISIBILITY 41 /* Make Processor Prefetches Visible */
#define PAL_LOGICAL_TO_PHYSICAL 42 /* returns information on logical to physical processor mapping */
+#define PAL_CACHE_SHARED_INFO 43 /* returns information on caches shared by logical processor */
#define PAL_COPY_PAL 256 /* relocate PAL procedures and PAL PMI */
#define PAL_HALT_INFO 257 /* return the low power capabilities of processor */
@@ -130,7 +131,7 @@ typedef u64 pal_cache_line_state_t;
#define PAL_CACHE_LINE_STATE_MODIFIED 3 /* Modified */
typedef struct pal_freq_ratio {
- u64 den : 32, num : 32; /* numerator & denominator */
+ u32 den, num; /* numerator & denominator */
} itc_ratio, proc_ratio;
typedef union pal_cache_config_info_1_s {
@@ -151,10 +152,10 @@ typedef union pal_cache_config_info_1_s {
typedef union pal_cache_config_info_2_s {
struct {
- u64 cache_size : 32, /*cache size in bytes*/
+ u32 cache_size; /*cache size in bytes*/
- alias_boundary : 8, /* 39-32 aliased addr
+ u32 alias_boundary : 8, /* 39-32 aliased addr
* separation for max
* performance.
*/
@@ -1647,6 +1648,33 @@ ia64_pal_logical_to_phys(u64 proc_number, pal_logical_to_physical_t *mapping)
return iprv.status;
}
+
+typedef struct pal_cache_shared_info_s
+{
+ u64 num_shared;
+ pal_proc_n_log_info1_t ppli1;
+ pal_proc_n_log_info2_t ppli2;
+} pal_cache_shared_info_t;
+
+/* Get information on logical to physical processor mappings. */
+static inline s64
+ia64_pal_cache_shared_info(u64 level,
+ u64 type,
+ u64 proc_number,
+ pal_cache_shared_info_t *info)
+{
+ struct ia64_pal_retval iprv;
+
+ PAL_CALL(iprv, PAL_CACHE_SHARED_INFO, level, type, proc_number);
+
+ if (iprv.status == PAL_STATUS_SUCCESS) {
+ info->num_shared = iprv.v0;
+ info->ppli1.ppli1_data = iprv.v1;
+ info->ppli2.ppli2_data = iprv.v2;
+ }
+
+ return iprv.status;
+}
#endif /* __ASSEMBLY__ */
#endif /* _ASM_IA64_PAL_H */
diff --git a/include/asm-ia64/sn/sn2/sn_hwperf.h b/include/asm-ia64/sn/sn2/sn_hwperf.h
index 291ef3d69da..e61ebac38cd 100644
--- a/include/asm-ia64/sn/sn2/sn_hwperf.h
+++ b/include/asm-ia64/sn/sn2/sn_hwperf.h
@@ -45,8 +45,12 @@ struct sn_hwperf_object_info {
#define SN_HWPERF_IS_NODE(x) ((x) && strstr((x)->name, "SHub"))
#define SN_HWPERF_IS_NODE_SHUB2(x) ((x) && strstr((x)->name, "SHub 2."))
#define SN_HWPERF_IS_IONODE(x) ((x) && strstr((x)->name, "TIO"))
-#define SN_HWPERF_IS_ROUTER(x) ((x) && strstr((x)->name, "Router"))
#define SN_HWPERF_IS_NL3ROUTER(x) ((x) && strstr((x)->name, "NL3Router"))
+#define SN_HWPERF_IS_NL4ROUTER(x) ((x) && strstr((x)->name, "NL4Router"))
+#define SN_HWPERF_IS_OLDROUTER(x) ((x) && strstr((x)->name, "Router"))
+#define SN_HWPERF_IS_ROUTER(x) (SN_HWPERF_IS_NL3ROUTER(x) || \
+ SN_HWPERF_IS_NL4ROUTER(x) || \
+ SN_HWPERF_IS_OLDROUTER(x))
#define SN_HWPERF_FOREIGN(x) ((x) && !(x)->sn_hwp_this_part && !(x)->sn_hwp_is_shared)
#define SN_HWPERF_SAME_OBJTYPE(x,y) ((SN_HWPERF_IS_NODE(x) && SN_HWPERF_IS_NODE(y)) ||\
(SN_HWPERF_IS_IONODE(x) && SN_HWPERF_IS_IONODE(y)) ||\
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index bf4cc867a69..51aca022cf3 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -8,7 +8,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc. All rights reserved.
*/
@@ -85,6 +85,7 @@
#define SN_SAL_GET_PROM_FEATURE_SET 0x02000065
#define SN_SAL_SET_OS_FEATURE_SET 0x02000066
+#define SN_SAL_INJECT_ERROR 0x02000067
/*
* Service-specific constants
@@ -705,10 +706,8 @@ static inline int
sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array)
{
struct ia64_sal_retval ret_stuff;
- int cnodeid;
unsigned long irq_flags;
- cnodeid = nasid_to_cnodeid(get_node_number(paddr));
local_irq_save(irq_flags);
ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_MEMPROTECT, paddr, len,
(u64)nasid_array, perms, 0, 0, 0);
@@ -1140,4 +1139,16 @@ ia64_sn_set_os_feature(int feature)
return rv.status;
}
+static inline int
+sn_inject_error(u64 paddr, u64 *data, u64 *ecc)
+{
+ struct ia64_sal_retval ret_stuff;
+ unsigned long irq_flags;
+
+ local_irq_save(irq_flags);
+ ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_INJECT_ERROR, paddr, (u64)data,
+ (u64)ecc, 0, 0, 0, 0);
+ local_irq_restore(irq_flags);
+ return ret_stuff.status;
+}
#endif /* _ASM_IA64_SN_SN_SAL_H */
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 56394a2c705..e5392c4d30c 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -67,7 +67,7 @@ struct thread_info {
#define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET)
#define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
-#define alloc_task_struct() ((task_t *)__get_free_pages(GFP_KERNEL, KERNEL_STACK_SIZE_ORDER))
+#define alloc_task_struct() ((task_t *)__get_free_pages(GFP_KERNEL | __GFP_COMP, KERNEL_STACK_SIZE_ORDER))
#define free_task_struct(tsk) free_pages((unsigned long) (tsk), KERNEL_STACK_SIZE_ORDER)
#endif /* !__ASSEMBLY */
diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
index 3ee19dfa46d..616b5ed2aa7 100644
--- a/include/asm-ia64/topology.h
+++ b/include/asm-ia64/topology.h
@@ -23,6 +23,11 @@
#define PENALTY_FOR_NODE_WITH_CPUS 255
/*
+ * Distance above which we begin to use zone reclaim
+ */
+#define RECLAIM_DISTANCE 15
+
+/*
* Returns the number of the node containing CPU 'cpu'
*/
#define cpu_to_node(cpu) (int)(cpu_to_node_map[cpu])
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index 019956c613e..7107763168b 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -285,12 +285,18 @@
#define __NR_faccessat 1293
/* 1294, 1295 reserved for pselect/ppoll */
#define __NR_unshare 1296
+#define __NR_splice 1297
+#define __NR_set_robust_list 1298
+#define __NR_get_robust_list 1299
+#define __NR_sync_file_range 1300
+#define __NR_tee 1301
+#define __NR_vmsplice 1302
#ifdef __KERNEL__
#include <linux/config.h>
-#define NR_syscalls 273 /* length of syscall table */
+#define NR_syscalls 279 /* length of syscall table */
#define __ARCH_WANT_SYS_RT_SIGACTION
diff --git a/include/asm-ia64/vga.h b/include/asm-ia64/vga.h
index bc3349ffc50..091177cda22 100644
--- a/include/asm-ia64/vga.h
+++ b/include/asm-ia64/vga.h
@@ -17,7 +17,7 @@
extern unsigned long vga_console_iobase;
extern unsigned long vga_console_membase;
-#define VGA_MAP_MEM(x) ((unsigned long) ioremap(vga_console_membase + (x), 0))
+#define VGA_MAP_MEM(x) ((unsigned long) ioremap_nocache(vga_console_membase + (x), 0))
#define vga_readb(x) (*(x))
#define vga_writeb(x,y) (*(y) = (x))
diff --git a/include/asm-m32r/assembler.h b/include/asm-m32r/assembler.h
index b7f4d8aaeb4..1a1aa17edd3 100644
--- a/include/asm-m32r/assembler.h
+++ b/include/asm-m32r/assembler.h
@@ -109,6 +109,9 @@
push r13
mvfachi r13
push r13
+ ldi r13, #0
+ push r13 ; dummy push acc1h
+ push r13 ; dummy push acc1l
#else
#error unknown isa configuration
#endif
@@ -156,6 +159,8 @@
pop r13
mvtaclo r13, a1
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+ pop r13 ; dummy pop acc1h
+ pop r13 ; dummy pop acc1l
pop r13
mvtachi r13
pop r13
diff --git a/include/asm-m32r/mappi3/mappi3_pld.h b/include/asm-m32r/mappi3/mappi3_pld.h
index 1d3c25d61bc..031369a7afc 100644
--- a/include/asm-m32r/mappi3/mappi3_pld.h
+++ b/include/asm-m32r/mappi3/mappi3_pld.h
@@ -53,16 +53,14 @@
/* Power Control of MMC and CF */
#define PLD_CPCR __reg16(PLD_BASE + 0x14000)
-
-/*==== ICU ====*/
-#define M32R_IRQ_PC104 (5) /* INT4(PC/104) */
-#define M32R_IRQ_I2C (28) /* I2C-BUS */
-#define PLD_IRQ_CFIREQ (6) /* INT5 CFC Card Interrupt */
-#define PLD_IRQ_CFC_INSERT (7) /* INT6 CFC Card Insert */
-#define PLD_IRQ_IDEIREQ (8) /* INT7 IDE Interrupt */
-#define PLD_IRQ_MMCCARD (43) /* MMC Card Insert */
-#define PLD_IRQ_MMCIRQ (44) /* MMC Transfer Done */
-
+/* ICU */
+#define M32R_IRQ_PC104 (5) /* INT4(PC/104) */
+#define M32R_IRQ_I2C (28) /* I2C-BUS */
+#define PLD_IRQ_CFIREQ (6) /* INT5 CFC Card Interrupt */
+#define PLD_IRQ_CFC_INSERT (7) /* INT6 CFC Card Insert & Eject */
+#define PLD_IRQ_IDEIREQ (8) /* INT7 IDE Interrupt */
+#define PLD_IRQ_MMCCARD (43) /* MMC Card Insert */
+#define PLD_IRQ_MMCIRQ (44) /* MMC Transfer Done */
#if 0
/* LED Control
@@ -97,7 +95,6 @@
#define PLD_CRC16ADATA __reg16(PLD_BASE + 0x18008)
#define PLD_CRC16AINDATA __reg16(PLD_BASE + 0x1800a)
-
#if 0
/* RTC */
#define PLD_RTCCR __reg16(PLD_BASE + 0x1c000)
@@ -140,4 +137,7 @@
#endif
+/* Reset Control */
+#define PLD_REBOOT __reg16(PLD_BASE + 0x38000)
+
#endif /* _MAPPI3_PLD.H */
diff --git a/include/asm-m32r/mmzone.h b/include/asm-m32r/mmzone.h
index adc7970a77e..9f3b5accda8 100644
--- a/include/asm-m32r/mmzone.h
+++ b/include/asm-m32r/mmzone.h
@@ -21,20 +21,6 @@ extern struct pglist_data *node_data[];
__pgdat->node_start_pfn + __pgdat->node_spanned_pages - 1; \
})
-#define pfn_to_page(pfn) \
-({ \
- unsigned long __pfn = pfn; \
- int __node = pfn_to_nid(__pfn); \
- &NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)]; \
-})
-
-#define page_to_pfn(pg) \
-({ \
- struct page *__page = pg; \
- struct zone *__zone = page_zone(__page); \
- (unsigned long)(__page - __zone->zone_mem_map) \
- + __zone->zone_start_pfn; \
-})
#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
/*
* pfn_valid should be made as fast as possible, and the current definition
diff --git a/include/asm-m32r/numnodes.h b/include/asm-m32r/numnodes.h
deleted file mode 100644
index 479a39d49f8..00000000000
--- a/include/asm-m32r/numnodes.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef _ASM_NUMNODES_H_
-#define _ASM_NUMNODES_H_
-
-#include <linux/config.h>
-
-#ifdef CONFIG_DISCONTIGMEM
-
-#if defined(CONFIG_CHIP_M32700)
-#define NODES_SHIFT 1 /* Max 2 Nodes */
-#endif /* CONFIG_CHIP_M32700 */
-
-#endif /* CONFIG_DISCONTIGMEM */
-
-#endif /* _ASM_NUMNODES_H_ */
-
diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h
index 4ab57887636..9ddbc087dbc 100644
--- a/include/asm-m32r/page.h
+++ b/include/asm-m32r/page.h
@@ -76,9 +76,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#ifndef CONFIG_DISCONTIGMEM
#define PFN_BASE (CONFIG_MEMORY_START >> PAGE_SHIFT)
-#define pfn_to_page(pfn) (mem_map + ((pfn) - PFN_BASE))
-#define page_to_pfn(page) \
- ((unsigned long)((page) - mem_map) + PFN_BASE)
+#define ARCH_PFN_OFFSET PFN_BASE
#define pfn_valid(pfn) (((pfn) - PFN_BASE) < max_mapnr)
#endif /* !CONFIG_DISCONTIGMEM */
@@ -92,6 +90,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _ASM_M32R_PAGE_H */
diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h
index 0d058b2d844..53c792452df 100644
--- a/include/asm-m32r/ptrace.h
+++ b/include/asm-m32r/ptrace.h
@@ -43,6 +43,14 @@
#define PT_ACC1L 18
#define PT_ACCH PT_ACC0H
#define PT_ACCL PT_ACC0L
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define PT_ACCH 15
+#define PT_ACCL 16
+#define PT_DUMMY_ACC1H 17
+#define PT_DUMMY_ACC1L 18
+#else
+#error unknown isa conifiguration
+#endif
#define PT_PSW 19
#define PT_BPC 20
#define PT_BBPSW 21
@@ -52,21 +60,6 @@
#define PT_LR 25
#define PT_SPI 26
#define PT_ORIGR0 27
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define PT_ACCH 15
-#define PT_ACCL 16
-#define PT_PSW 17
-#define PT_BPC 18
-#define PT_BBPSW 19
-#define PT_BBPC 20
-#define PT_SPU 21
-#define PT_FP 22
-#define PT_LR 23
-#define PT_SPI 24
-#define PT_ORIGR0 25
-#else
-#error unknown isa conifiguration
-#endif
/* virtual pt_reg entry for gdb */
#define PT_PC 30
@@ -121,6 +114,8 @@ struct pt_regs {
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
unsigned long acch;
unsigned long accl;
+ unsigned long dummy_acc1h;
+ unsigned long dummy_acc1l;
#else
#error unknown isa configuration
#endif
diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
index bf447c52a0a..81750edc891 100644
--- a/include/asm-m32r/semaphore.h
+++ b/include/asm-m32r/semaphore.h
@@ -9,7 +9,7 @@
* SMP- and interrupt-safe semaphores..
*
* Copyright (C) 1996 Linus Torvalds
- * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2004, 2006 Hirokazu Takata <takata at linux-m32r.org>
*/
#include <linux/config.h>
@@ -77,27 +77,8 @@ asmlinkage void __up(struct semaphore * sem);
*/
static inline void down(struct semaphore * sem)
{
- unsigned long flags;
- long count;
-
might_sleep();
- local_irq_save(flags);
- __asm__ __volatile__ (
- "# down \n\t"
- DCACHE_CLEAR("%0", "r4", "%1")
- M32R_LOCK" %0, @%1; \n\t"
- "addi %0, #-1; \n\t"
- M32R_UNLOCK" %0, @%1; \n\t"
- : "=&r" (count)
- : "r" (&sem->count)
- : "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
- , "r4"
-#endif /* CONFIG_CHIP_M32700_TS1 */
- );
- local_irq_restore(flags);
-
- if (unlikely(count < 0))
+ if (unlikely(atomic_dec_return(&sem->count) < 0))
__down(sem);
}
@@ -107,28 +88,10 @@ static inline void down(struct semaphore * sem)
*/
static inline int down_interruptible(struct semaphore * sem)
{
- unsigned long flags;
- long count;
int result = 0;
might_sleep();
- local_irq_save(flags);
- __asm__ __volatile__ (
- "# down_interruptible \n\t"
- DCACHE_CLEAR("%0", "r4", "%1")
- M32R_LOCK" %0, @%1; \n\t"
- "addi %0, #-1; \n\t"
- M32R_UNLOCK" %0, @%1; \n\t"
- : "=&r" (count)
- : "r" (&sem->count)
- : "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
- , "r4"
-#endif /* CONFIG_CHIP_M32700_TS1 */
- );
- local_irq_restore(flags);
-
- if (unlikely(count < 0))
+ if (unlikely(atomic_dec_return(&sem->count) < 0))
result = __down_interruptible(sem);
return result;
@@ -174,26 +137,7 @@ static inline int down_trylock(struct semaphore * sem)
*/
static inline void up(struct semaphore * sem)
{
- unsigned long flags;
- long count;
-
- local_irq_save(flags);
- __asm__ __volatile__ (
- "# up \n\t"
- DCACHE_CLEAR("%0", "r4", "%1")
- M32R_LOCK" %0, @%1; \n\t"
- "addi %0, #1; \n\t"
- M32R_UNLOCK" %0, @%1; \n\t"
- : "=&r" (count)
- : "r" (&sem->count)
- : "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
- , "r4"
-#endif /* CONFIG_CHIP_M32700_TS1 */
- );
- local_irq_restore(flags);
-
- if (unlikely(count <= 0))
+ if (unlikely(atomic_inc_return(&sem->count) <= 0))
__up(sem);
}
diff --git a/include/asm-m32r/setup.h b/include/asm-m32r/setup.h
index 5f028dc26a9..52f4fa29abf 100644
--- a/include/asm-m32r/setup.h
+++ b/include/asm-m32r/setup.h
@@ -24,10 +24,6 @@
#define RAMDISK_PROMPT_FLAG (0x8000)
#define RAMDISK_LOAD_FLAG (0x4000)
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
-
extern unsigned long memory_start;
extern unsigned long memory_end;
diff --git a/include/asm-m32r/sigcontext.h b/include/asm-m32r/sigcontext.h
index c233e2def2a..942b8a30937 100644
--- a/include/asm-m32r/sigcontext.h
+++ b/include/asm-m32r/sigcontext.h
@@ -32,6 +32,8 @@ struct sigcontext {
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
unsigned long sc_acch;
unsigned long sc_accl;
+ unsigned long sc_dummy_acc1h;
+ unsigned long sc_dummy_acc1l;
#else
#error unknown isa configuration
#endif
diff --git a/include/asm-m32r/smp.h b/include/asm-m32r/smp.h
index 7885b7df84a..1184293e571 100644
--- a/include/asm-m32r/smp.h
+++ b/include/asm-m32r/smp.h
@@ -67,7 +67,8 @@ extern volatile int cpu_2_physid[NR_CPUS];
#define raw_smp_processor_id() (current_thread_info()->cpu)
extern cpumask_t cpu_callout_map;
-#define cpu_possible_map cpu_callout_map
+extern cpumask_t cpu_possible_map;
+extern cpumask_t cpu_present_map;
static __inline__ int hard_smp_processor_id(void)
{
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index d6a2c613be6..e55013f378e 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -6,8 +6,8 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2001 by Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
- * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2001 Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006 Hirokazu Takata <takata at linux-m32r.org>
*/
#include <linux/config.h>
@@ -19,53 +19,28 @@
* switch_to(prev, next) should switch from task `prev' to `next'
* `prev' will never be the same as `next'.
*
- * `next' and `prev' should be struct task_struct, but it isn't always defined
+ * `next' and `prev' should be task_t, but it isn't always defined
*/
-#ifndef CONFIG_SMP
-#define prepare_to_switch() do { } while(0)
-#endif /* not CONFIG_SMP */
-
#define switch_to(prev, next, last) do { \
- register unsigned long arg0 __asm__ ("r0") = (unsigned long)prev; \
- register unsigned long arg1 __asm__ ("r1") = (unsigned long)next; \
- register unsigned long *oldsp __asm__ ("r2") = &(prev->thread.sp); \
- register unsigned long *newsp __asm__ ("r3") = &(next->thread.sp); \
- register unsigned long *oldlr __asm__ ("r4") = &(prev->thread.lr); \
- register unsigned long *newlr __asm__ ("r5") = &(next->thread.lr); \
- register struct task_struct *__last __asm__ ("r6"); \
__asm__ __volatile__ ( \
- "st r8, @-r15 \n\t" \
- "st r9, @-r15 \n\t" \
- "st r10, @-r15 \n\t" \
- "st r11, @-r15 \n\t" \
- "st r12, @-r15 \n\t" \
- "st r13, @-r15 \n\t" \
- "st r14, @-r15 \n\t" \
- "seth r14, #high(1f) \n\t" \
- "or3 r14, r14, #low(1f) \n\t" \
- "st r14, @r4 ; store old LR \n\t" \
- "st r15, @r2 ; store old SP \n\t" \
- "ld r15, @r3 ; load new SP \n\t" \
- "st r0, @-r15 ; store 'prev' onto new stack \n\t" \
- "ld r14, @r5 ; load new LR \n\t" \
- "jmp r14 \n\t" \
- ".fillinsn \n " \
- "1: \n\t" \
- "ld r6, @r15+ ; load 'prev' from new stack \n\t" \
- "ld r14, @r15+ \n\t" \
- "ld r13, @r15+ \n\t" \
- "ld r12, @r15+ \n\t" \
- "ld r11, @r15+ \n\t" \
- "ld r10, @r15+ \n\t" \
- "ld r9, @r15+ \n\t" \
- "ld r8, @r15+ \n\t" \
- : "=&r" (__last) \
- : "r" (arg0), "r" (arg1), "r" (oldsp), "r" (newsp), \
- "r" (oldlr), "r" (newlr) \
- : "memory" \
+ " seth lr, #high(1f) \n" \
+ " or3 lr, lr, #low(1f) \n" \
+ " st lr, @%4 ; store old LR \n" \
+ " ld lr, @%5 ; load new LR \n" \
+ " st sp, @%2 ; store old SP \n" \
+ " ld sp, @%3 ; load new SP \n" \
+ " push %1 ; store `prev' on new stack \n" \
+ " jmp lr \n" \
+ " .fillinsn \n" \
+ "1: \n" \
+ " pop %0 ; restore `__last' from new stack \n" \
+ : "=r" (last) \
+ : "0" (prev), \
+ "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
+ "r" (&(prev->thread.lr)), "r" (&(next->thread.lr)) \
+ : "memory", "lr" \
); \
- last = __last; \
} while(0)
/*
@@ -171,8 +146,8 @@ extern void __xchg_called_with_bad_pointer(void);
#define DCACHE_CLEAR(reg0, reg1, addr)
#endif /* CONFIG_CHIP_M32700_TS1 */
-static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
- int size)
+static inline unsigned long
+__xchg(unsigned long x, volatile void * ptr, int size)
{
unsigned long flags;
unsigned long tmp = 0;
@@ -224,7 +199,7 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
#define __HAVE_ARCH_CMPXCHG 1
-static __inline__ unsigned long
+static inline unsigned long
__cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
{
unsigned long flags;
@@ -258,7 +233,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
if something tries to do an invalid cmpxchg(). */
extern void __cmpxchg_called_with_bad_pointer(void);
-static __inline__ unsigned long
+static inline unsigned long
__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
{
switch (size) {
diff --git a/include/asm-m32r/uaccess.h b/include/asm-m32r/uaccess.h
index e8ae61956a5..819cc28a94f 100644
--- a/include/asm-m32r/uaccess.h
+++ b/include/asm-m32r/uaccess.h
@@ -5,17 +5,9 @@
* linux/include/asm-m32r/uaccess.h
*
* M32R version.
- * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2004, 2006 Hirokazu Takata <takata at linux-m32r.org>
*/
-#undef UACCESS_DEBUG
-
-#ifdef UACCESS_DEBUG
-#define UAPRINTK(args...) printk(args)
-#else
-#define UAPRINTK(args...)
-#endif /* UACCESS_DEBUG */
-
/*
* User space memory access functions
*/
@@ -38,27 +30,29 @@
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
#ifdef CONFIG_MMU
+
#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
#define USER_DS MAKE_MM_SEG(PAGE_OFFSET)
-#else
-#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
-#define USER_DS MAKE_MM_SEG(0xFFFFFFFF)
-#endif /* CONFIG_MMU */
-
#define get_ds() (KERNEL_DS)
-#ifdef CONFIG_MMU
#define get_fs() (current_thread_info()->addr_limit)
#define set_fs(x) (current_thread_info()->addr_limit = (x))
-#else
+
+#else /* not CONFIG_MMU */
+
+#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
+#define USER_DS MAKE_MM_SEG(0xFFFFFFFF)
+#define get_ds() (KERNEL_DS)
+
static inline mm_segment_t get_fs(void)
{
- return USER_DS;
+ return USER_DS;
}
static inline void set_fs(mm_segment_t s)
{
}
-#endif /* CONFIG_MMU */
+
+#endif /* not CONFIG_MMU */
#define segment_eq(a,b) ((a).seg == (b).seg)
@@ -83,9 +77,9 @@ static inline void set_fs(mm_segment_t s)
" subx %0, %0\n" \
" cmpu %4, %1\n" \
" subx %0, %5\n" \
- : "=&r"(flag), "=r"(sum) \
- : "1"(addr), "r"((int)(size)), \
- "r"(current_thread_info()->addr_limit.seg), "r"(0) \
+ : "=&r" (flag), "=r" (sum) \
+ : "1" (addr), "r" ((int)(size)), \
+ "r" (current_thread_info()->addr_limit.seg), "r" (0) \
: "cbit" ); \
flag; })
@@ -113,10 +107,10 @@ static inline void set_fs(mm_segment_t s)
#else
static inline int access_ok(int type, const void *addr, unsigned long size)
{
- extern unsigned long memory_start, memory_end;
- unsigned long val = (unsigned long)addr;
+ extern unsigned long memory_start, memory_end;
+ unsigned long val = (unsigned long)addr;
- return ((val >= memory_start) && ((val + size) < memory_end));
+ return ((val >= memory_start) && ((val + size) < memory_end));
}
#endif /* CONFIG_MMU */
@@ -155,39 +149,6 @@ extern int fixup_exception(struct pt_regs *regs);
* accesses to the same area of user memory).
*/
-extern void __get_user_1(void);
-extern void __get_user_2(void);
-extern void __get_user_4(void);
-
-#ifndef MODULE
-#define __get_user_x(size,ret,x,ptr) \
- __asm__ __volatile__( \
- " mv r0, %0\n" \
- " mv r1, %1\n" \
- " bl __get_user_" #size "\n" \
- " mv %0, r0\n" \
- " mv %1, r1\n" \
- : "=r"(ret), "=r"(x) \
- : "0"(ptr) \
- : "r0", "r1", "r14" )
-#else /* MODULE */
-/*
- * Use "jl" instead of "bl" for MODULE
- */
-#define __get_user_x(size,ret,x,ptr) \
- __asm__ __volatile__( \
- " mv r0, %0\n" \
- " mv r1, %1\n" \
- " seth lr, #high(__get_user_" #size ")\n" \
- " or3 lr, lr, #low(__get_user_" #size ")\n" \
- " jl lr\n" \
- " mv %0, r0\n" \
- " mv %1, r1\n" \
- : "=r"(ret), "=r"(x) \
- : "0"(ptr) \
- : "r0", "r1", "r14" )
-#endif
-
/* Careful: we have to cast the result to the type of the pointer for sign
reasons */
/**
@@ -208,20 +169,7 @@ extern void __get_user_4(void);
* On error, the variable @x is set to zero.
*/
#define get_user(x,ptr) \
-({ int __ret_gu; \
- unsigned long __val_gu; \
- __chk_user_ptr(ptr); \
- switch(sizeof (*(ptr))) { \
- case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \
- case 2: __get_user_x(2,__ret_gu,__val_gu,ptr); break; \
- case 4: __get_user_x(4,__ret_gu,__val_gu,ptr); break; \
- default: __get_user_x(X,__ret_gu,__val_gu,ptr); break; \
- } \
- (x) = (__typeof__(*(ptr)))__val_gu; \
- __ret_gu; \
-})
-
-extern void __put_user_bad(void);
+ __get_user_check((x),(ptr),sizeof(*(ptr)))
/**
* put_user: - Write a simple value into user space.
@@ -240,8 +188,7 @@ extern void __put_user_bad(void);
* Returns zero on success, or -EFAULT on error.
*/
#define put_user(x,ptr) \
- __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
-
+ __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
/**
* __get_user: - Get a simple variable from user space, with less checking.
@@ -264,8 +211,64 @@ extern void __put_user_bad(void);
* On error, the variable @x is set to zero.
*/
#define __get_user(x,ptr) \
- __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+ __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __get_user_nocheck(x,ptr,size) \
+({ \
+ long __gu_err = 0; \
+ unsigned long __gu_val; \
+ might_sleep(); \
+ __get_user_size(__gu_val,(ptr),(size),__gu_err); \
+ (x) = (__typeof__(*(ptr)))__gu_val; \
+ __gu_err; \
+})
+
+#define __get_user_check(x,ptr,size) \
+({ \
+ long __gu_err = -EFAULT; \
+ unsigned long __gu_val = 0; \
+ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
+ might_sleep(); \
+ if (access_ok(VERIFY_READ,__gu_addr,size)) \
+ __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \
+ (x) = (__typeof__(*(ptr)))__gu_val; \
+ __gu_err; \
+})
+
+extern long __get_user_bad(void);
+
+#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,"ub"); break; \
+ case 2: __get_user_asm(x,ptr,retval,"uh"); break; \
+ case 4: __get_user_asm(x,ptr,retval,""); break; \
+ default: (x) = __get_user_bad(); \
+ } \
+} while (0)
+
+#define __get_user_asm(x, addr, err, itype) \
+ __asm__ __volatile__( \
+ " .fillinsn\n" \
+ "1: ld"itype" %1,@%2\n" \
+ " .fillinsn\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ " .balign 4\n" \
+ "3: ldi %0,%3\n" \
+ " seth r14,#high(2b)\n" \
+ " or3 r14,r14,#low(2b)\n" \
+ " jmp r14\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .balign 4\n" \
+ " .long 1b,3b\n" \
+ ".previous" \
+ : "=&r" (err), "=&r" (x) \
+ : "r" (addr), "i" (-EFAULT), "0" (err) \
+ : "r14", "memory")
/**
* __put_user: - Write a simple value into user space, with less checking.
@@ -287,11 +290,13 @@ extern void __put_user_bad(void);
* Returns zero on success, or -EFAULT on error.
*/
#define __put_user(x,ptr) \
- __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+ __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
#define __put_user_nocheck(x,ptr,size) \
({ \
long __pu_err; \
+ might_sleep(); \
__put_user_size((x),(ptr),(size),__pu_err); \
__pu_err; \
})
@@ -308,28 +313,28 @@ extern void __put_user_bad(void);
})
#if defined(__LITTLE_ENDIAN__)
-#define __put_user_u64(x, addr, err) \
- __asm__ __volatile__( \
- " .fillinsn\n" \
- "1: st %L1,@%2\n" \
- " .fillinsn\n" \
- "2: st %H1,@(4,%2)\n" \
- " .fillinsn\n" \
- "3:\n" \
- ".section .fixup,\"ax\"\n" \
- " .balign 4\n" \
- "4: ldi %0,%3\n" \
- " seth r14,#high(3b)\n" \
- " or3 r14,r14,#low(3b)\n" \
- " jmp r14\n" \
- ".previous\n" \
- ".section __ex_table,\"a\"\n" \
- " .balign 4\n" \
- " .long 1b,4b\n" \
- " .long 2b,4b\n" \
- ".previous" \
- : "=&r"(err) \
- : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err) \
+#define __put_user_u64(x, addr, err) \
+ __asm__ __volatile__( \
+ " .fillinsn\n" \
+ "1: st %L1,@%2\n" \
+ " .fillinsn\n" \
+ "2: st %H1,@(4,%2)\n" \
+ " .fillinsn\n" \
+ "3:\n" \
+ ".section .fixup,\"ax\"\n" \
+ " .balign 4\n" \
+ "4: ldi %0,%3\n" \
+ " seth r14,#high(3b)\n" \
+ " or3 r14,r14,#low(3b)\n" \
+ " jmp r14\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .balign 4\n" \
+ " .long 1b,4b\n" \
+ " .long 2b,4b\n" \
+ ".previous" \
+ : "=&r" (err) \
+ : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err) \
: "r14", "memory")
#elif defined(__BIG_ENDIAN__)
@@ -353,13 +358,15 @@ extern void __put_user_bad(void);
" .long 1b,4b\n" \
" .long 2b,4b\n" \
".previous" \
- : "=&r"(err) \
- : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err) \
+ : "=&r" (err) \
+ : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err) \
: "r14", "memory")
#else
#error no endian defined
#endif
+extern void __put_user_bad(void);
+
#define __put_user_size(x,ptr,size,retval) \
do { \
retval = 0; \
@@ -398,52 +405,8 @@ struct __large_struct { unsigned long buf[100]; };
" .balign 4\n" \
" .long 1b,3b\n" \
".previous" \
- : "=&r"(err) \
- : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err) \
- : "r14", "memory")
-
-#define __get_user_nocheck(x,ptr,size) \
-({ \
- long __gu_err; \
- unsigned long __gu_val; \
- __get_user_size(__gu_val,(ptr),(size),__gu_err); \
- (x) = (__typeof__(*(ptr)))__gu_val; \
- __gu_err; \
-})
-
-extern long __get_user_bad(void);
-
-#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,"ub"); break; \
- case 2: __get_user_asm(x,ptr,retval,"uh"); break; \
- case 4: __get_user_asm(x,ptr,retval,""); break; \
- default: (x) = __get_user_bad(); \
- } \
-} while (0)
-
-#define __get_user_asm(x, addr, err, itype) \
- __asm__ __volatile__( \
- " .fillinsn\n" \
- "1: ld"itype" %1,@%2\n" \
- " .fillinsn\n" \
- "2:\n" \
- ".section .fixup,\"ax\"\n" \
- " .balign 4\n" \
- "3: ldi %0,%3\n" \
- " seth r14,#high(2b)\n" \
- " or3 r14,r14,#low(2b)\n" \
- " jmp r14\n" \
- ".previous\n" \
- ".section __ex_table,\"a\"\n" \
- " .balign 4\n" \
- " .long 1b,3b\n" \
- ".previous" \
- : "=&r"(err), "=&r"(x) \
- : "r"(addr), "i"(-EFAULT), "0"(err) \
+ : "=&r" (err) \
+ : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err) \
: "r14", "memory")
/*
@@ -453,7 +416,6 @@ do { \
* anything, so this is accurate.
*/
-
/*
* Copy To/From Userspace
*/
@@ -511,8 +473,9 @@ do { \
" .long 2b,9b\n" \
" .long 3b,9b\n" \
".previous\n" \
- : "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c) \
- : "0"(to), "1"(from), "2"(size), "3"(size / 4) \
+ : "=&r" (__dst), "=&r" (__src), "=&r" (size), \
+ "=&r" (__c) \
+ : "0" (to), "1" (from), "2" (size), "3" (size / 4) \
: "r14", "memory"); \
} while (0)
@@ -573,8 +536,9 @@ do { \
" .long 2b,7b\n" \
" .long 3b,7b\n" \
".previous\n" \
- : "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c) \
- : "0"(to), "1"(from), "2"(size), "3"(size / 4) \
+ : "=&r" (__dst), "=&r" (__src), "=&r" (size), \
+ "=&r" (__c) \
+ : "0" (to), "1" (from), "2" (size), "3" (size / 4) \
: "r14", "memory"); \
} while (0)
@@ -676,7 +640,7 @@ unsigned long __generic_copy_from_user(void *, const void __user *, unsigned lon
#define copy_from_user(to,from,n) \
({ \
might_sleep(); \
-__generic_copy_from_user((to),(from),(n)); \
+ __generic_copy_from_user((to),(from),(n)); \
})
long __must_check strncpy_from_user(char *dst, const char __user *src,
diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
index 39be87ca2a5..be0eb014c3b 100644
--- a/include/asm-m32r/unistd.h
+++ b/include/asm-m32r/unistd.h
@@ -292,7 +292,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
+#define __NR_kexec_load 283
#define __NR_waitid 284
#define NR_syscalls 285
diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h
index 42520cc84b0..1386af1cb7d 100644
--- a/include/asm-mips/addrspace.h
+++ b/include/asm-mips/addrspace.h
@@ -129,6 +129,7 @@
#if defined (CONFIG_CPU_R4300) \
|| defined (CONFIG_CPU_R4X00) \
|| defined (CONFIG_CPU_R5000) \
+ || defined (CONFIG_CPU_RM7000) \
|| defined (CONFIG_CPU_NEVADA) \
|| defined (CONFIG_CPU_TX49XX) \
|| defined (CONFIG_CPU_MIPS64)
diff --git a/include/asm-mips/asmmacro.h b/include/asm-mips/asmmacro.h
index 30b18ea6cb1..f54aa147ec1 100644
--- a/include/asm-mips/asmmacro.h
+++ b/include/asm-mips/asmmacro.h
@@ -17,7 +17,26 @@
#ifdef CONFIG_64BIT
#include <asm/asmmacro-64.h>
#endif
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif
+#ifdef CONFIG_MIPS_MT_SMTC
+ .macro local_irq_enable reg=t0
+ mfc0 \reg, CP0_TCSTATUS
+ ori \reg, \reg, TCSTATUS_IXMT
+ xori \reg, \reg, TCSTATUS_IXMT
+ mtc0 \reg, CP0_TCSTATUS
+ ehb
+ .endm
+
+ .macro local_irq_disable reg=t0
+ mfc0 \reg, CP0_TCSTATUS
+ ori \reg, \reg, TCSTATUS_IXMT
+ mtc0 \reg, CP0_TCSTATUS
+ ehb
+ .endm
+#else
.macro local_irq_enable reg=t0
mfc0 \reg, CP0_STATUS
ori \reg, \reg, 1
@@ -32,6 +51,7 @@
mtc0 \reg, CP0_STATUS
irq_disable_hazard
.endm
+#endif /* CONFIG_MIPS_MT_SMTC */
#ifdef CONFIG_CPU_SB1
.macro fpu_enable_hazard
@@ -48,4 +68,31 @@
.endm
#endif
+/*
+ * Temporary until all gas have MT ASE support
+ */
+ .macro DMT reg=0
+ .word (0x41600bc1 | (\reg << 16))
+ .endm
+
+ .macro EMT reg=0
+ .word (0x41600be1 | (\reg << 16))
+ .endm
+
+ .macro DVPE reg=0
+ .word (0x41600001 | (\reg << 16))
+ .endm
+
+ .macro EVPE reg=0
+ .word (0x41600021 | (\reg << 16))
+ .endm
+
+ .macro MFTR rt=0, rd=0, u=0, sel=0
+ .word (0x41000000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel))
+ .endm
+
+ .macro MTTR rt=0, rd=0, u=0, sel=0
+ .word (0x41800000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel))
+ .endm
+
#endif /* _ASM_ASMMACRO_H */
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index a1728f8c070..d2f444537e4 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -467,64 +467,56 @@ static inline unsigned long __ffs(unsigned long word)
}
/*
- * ffs - find first bit set.
+ * fls - find last bit set.
* @word: The word to search
*
- * Returns 1..SZLONG
- * Returns 0 if no bit exists
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
-
-static inline unsigned long ffs(unsigned long word)
+static inline int fls(int word)
{
- if (!word)
- return 0;
+ __asm__ ("clz %0, %1" : "=r" (word) : "r" (word));
- return __ffs(word) + 1;
+ return 32 - word;
}
-/*
- * ffz - find first zero in word.
- * @word: The word to search
- *
- * Undefined if no zero exists, so code should check against ~0UL first.
- */
-static inline unsigned long ffz(unsigned long word)
+#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPS64)
+static inline int fls64(__u64 word)
{
- return __ffs (~word);
+ __asm__ ("dclz %0, %1" : "=r" (word) : "r" (word));
+
+ return 64 - word;
}
+#else
+#include <asm-generic/bitops/fls64.h>
+#endif
/*
- * fls - find last bit set.
+ * ffs - find first bit set.
* @word: The word to search
*
- * Returns 1..SZLONG
- * Returns 0 if no bit exists
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
*/
-static inline unsigned long fls(unsigned long word)
+static inline int ffs(int word)
{
-#ifdef CONFIG_CPU_MIPS32
- __asm__ ("clz %0, %1" : "=r" (word) : "r" (word));
-
- return 32 - word;
-#endif
-
-#ifdef CONFIG_CPU_MIPS64
- __asm__ ("dclz %0, %1" : "=r" (word) : "r" (word));
+ if (!word)
+ return 0;
- return 64 - word;
-#endif
+ return fls(word & -word);
}
#else
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/ffs.h>
-#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
#endif /*defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) */
-#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/find.h>
#ifdef __KERNEL__
diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h
index aeae9fabf4a..47bc8f6c20d 100644
--- a/include/asm-mips/cacheflush.h
+++ b/include/asm-mips/cacheflush.h
@@ -74,6 +74,7 @@ static inline void copy_from_user_page(struct vm_area_struct *vma,
extern void (*flush_cache_sigtramp)(unsigned long addr);
extern void (*flush_icache_all)(void);
+extern void (*local_flush_data_cache_page)(void * addr);
extern void (*flush_data_cache_page)(unsigned long addr);
/*
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index 0012bd804d2..986511db54a 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -133,6 +133,11 @@ static inline void __user *compat_ptr(compat_uptr_t uptr)
return (void __user *)(long)uptr;
}
+static inline compat_uptr_t ptr_to_compat(void __user *uptr)
+{
+ return (u32)(unsigned long)uptr;
+}
+
static inline void __user *compat_alloc_user_space(long len)
{
struct pt_regs *regs = (struct pt_regs *)
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 3f2b6d9ac45..254e11ed247 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -40,7 +40,7 @@
#define cpu_has_sb1_cache (cpu_data[0].options & MIPS_CPU_SB1_CACHE)
#endif
#ifndef cpu_has_fpu
-#define cpu_has_fpu (cpu_data[0].options & MIPS_CPU_FPU)
+#define cpu_has_fpu (current_cpu_data.options & MIPS_CPU_FPU)
#endif
#ifndef cpu_has_32fpr
#define cpu_has_32fpr (cpu_data[0].options & MIPS_CPU_32FPR)
diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h
index 140be1c67da..6572ac70366 100644
--- a/include/asm-mips/cpu-info.h
+++ b/include/asm-mips/cpu-info.h
@@ -73,6 +73,16 @@ struct cpuinfo_mips {
struct cache_desc dcache; /* Primary D or combined I/D cache */
struct cache_desc scache; /* Secondary cache */
struct cache_desc tcache; /* Tertiary/split secondary cache */
+#if defined(CONFIG_MIPS_MT_SMTC)
+ /*
+ * In the MIPS MT "SMTC" model, each TC is considered
+ * to be a "CPU" for the purposes of scheduling, but
+ * exception resources, ASID spaces, etc, are common
+ * to all TCs within the same VPE.
+ */
+ int vpe_id; /* Virtual Processor number */
+ int tc_id; /* Thread Context number */
+#endif /* CONFIG_MIPS_MT */
void *data; /* Additional data */
} __attribute__((aligned(SMP_CACHE_BYTES)));
diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h
index 818b9a97e21..dff2a0a52f8 100644
--- a/include/asm-mips/cpu.h
+++ b/include/asm-mips/cpu.h
@@ -51,6 +51,7 @@
#define PRID_IMP_R4300 0x0b00
#define PRID_IMP_VR41XX 0x0c00
#define PRID_IMP_R12000 0x0e00
+#define PRID_IMP_R14000 0x0f00
#define PRID_IMP_R8000 0x1000
#define PRID_IMP_PR4450 0x1200
#define PRID_IMP_R4600 0x2000
@@ -87,6 +88,7 @@
#define PRID_IMP_24K 0x9300
#define PRID_IMP_34K 0x9500
#define PRID_IMP_24KE 0x9600
+#define PRID_IMP_74K 0x9700
/*
* These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -196,7 +198,9 @@
#define CPU_34K 60
#define CPU_PR4450 61
#define CPU_SB1A 62
-#define CPU_LAST 62
+#define CPU_74K 63
+#define CPU_R14000 64
+#define CPU_LAST 64
/*
* ISA Level encodings
diff --git a/include/asm-mips/delay.h b/include/asm-mips/delay.h
index 64dd45150f6..928f30f8c45 100644
--- a/include/asm-mips/delay.h
+++ b/include/asm-mips/delay.h
@@ -19,20 +19,22 @@ static inline void __delay(unsigned long loops)
{
if (sizeof(long) == 4)
__asm__ __volatile__ (
- ".set\tnoreorder\n"
- "1:\tbnez\t%0,1b\n\t"
- "subu\t%0,1\n\t"
- ".set\treorder"
+ " .set noreorder \n"
+ " .align 3 \n"
+ "1: bnez %0, 1b \n"
+ " subu %0, 1 \n"
+ " .set reorder \n"
: "=r" (loops)
: "0" (loops));
else if (sizeof(long) == 8)
__asm__ __volatile__ (
- ".set\tnoreorder\n"
- "1:\tbnez\t%0,1b\n\t"
- "dsubu\t%0,1\n\t"
- ".set\treorder"
- :"=r" (loops)
- :"0" (loops));
+ " .set noreorder \n"
+ " .align 3 \n"
+ "1: bnez %0, 1b \n"
+ " dsubu %0, 1 \n"
+ " .set reorder \n"
+ : "=r" (loops)
+ : "0" (loops));
}
diff --git a/include/asm-mips/ds1742.h b/include/asm-mips/ds1742.h
new file mode 100644
index 00000000000..c2f2c32da63
--- /dev/null
+++ b/include/asm-mips/ds1742.h
@@ -0,0 +1,13 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 by Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef _ASM_DS1742_H
+#define _ASM_DS1742_H
+
+#include <ds1742.h>
+
+#endif /* _ASM_DS1742_H */
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index 851f013adad..bdc9de2df1e 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -119,8 +119,49 @@
#define SHT_MIPS_CONFLICT 0x70000002
#define SHT_MIPS_GPTAB 0x70000003
#define SHT_MIPS_UCODE 0x70000004
-
-#define SHF_MIPS_GPREL 0x10000000
+#define SHT_MIPS_DEBUG 0x70000005
+#define SHT_MIPS_REGINFO 0x70000006
+#define SHT_MIPS_PACKAGE 0x70000007
+#define SHT_MIPS_PACKSYM 0x70000008
+#define SHT_MIPS_RELD 0x70000009
+#define SHT_MIPS_IFACE 0x7000000b
+#define SHT_MIPS_CONTENT 0x7000000c
+#define SHT_MIPS_OPTIONS 0x7000000d
+#define SHT_MIPS_SHDR 0x70000010
+#define SHT_MIPS_FDESC 0x70000011
+#define SHT_MIPS_EXTSYM 0x70000012
+#define SHT_MIPS_DENSE 0x70000013
+#define SHT_MIPS_PDESC 0x70000014
+#define SHT_MIPS_LOCSYM 0x70000015
+#define SHT_MIPS_AUXSYM 0x70000016
+#define SHT_MIPS_OPTSYM 0x70000017
+#define SHT_MIPS_LOCSTR 0x70000018
+#define SHT_MIPS_LINE 0x70000019
+#define SHT_MIPS_RFDESC 0x7000001a
+#define SHT_MIPS_DELTASYM 0x7000001b
+#define SHT_MIPS_DELTAINST 0x7000001c
+#define SHT_MIPS_DELTACLASS 0x7000001d
+#define SHT_MIPS_DWARF 0x7000001e
+#define SHT_MIPS_DELTADECL 0x7000001f
+#define SHT_MIPS_SYMBOL_LIB 0x70000020
+#define SHT_MIPS_EVENTS 0x70000021
+#define SHT_MIPS_TRANSLATE 0x70000022
+#define SHT_MIPS_PIXIE 0x70000023
+#define SHT_MIPS_XLATE 0x70000024
+#define SHT_MIPS_XLATE_DEBUG 0x70000025
+#define SHT_MIPS_WHIRL 0x70000026
+#define SHT_MIPS_EH_REGION 0x70000027
+#define SHT_MIPS_XLATE_OLD 0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+
+#define SHF_MIPS_GPREL 0x10000000
+#define SHF_MIPS_MERGE 0x20000000
+#define SHF_MIPS_ADDR 0x40000000
+#define SHF_MIPS_STRING 0x80000000
+#define SHF_MIPS_NOSTRIP 0x08000000
+#define SHF_MIPS_LOCAL 0x04000000
+#define SHF_MIPS_NAMES 0x02000000
+#define SHF_MIPS_NODUPES 0x01000000
#ifndef ELF_ARCH
/* ELF register definitions */
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h
index 9c828b1f821..b0f50015e25 100644
--- a/include/asm-mips/fpu.h
+++ b/include/asm-mips/fpu.h
@@ -21,6 +21,10 @@
#include <asm/processor.h>
#include <asm/current.h>
+#ifdef CONFIG_MIPS_MT_FPAFF
+#include <asm/mips_mt.h>
+#endif
+
struct sigcontext;
struct sigcontext32;
diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h
index 2454c44a8f5..12d118f1bc9 100644
--- a/include/asm-mips/futex.h
+++ b/include/asm-mips/futex.h
@@ -7,6 +7,7 @@
#include <linux/futex.h>
#include <asm/errno.h>
#include <asm/uaccess.h>
+#include <asm/war.h>
#ifdef CONFIG_SMP
#define __FUTEX_SMP_SYNC " sync \n"
@@ -16,30 +17,58 @@
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
{ \
- __asm__ __volatile__( \
- " .set push \n" \
- " .set noat \n" \
- " .set mips3 \n" \
- "1: ll %1, (%3) # __futex_atomic_op1 \n" \
- " .set mips0 \n" \
- " " insn " \n" \
- " .set mips3 \n" \
- "2: sc $1, (%3) \n" \
- " beqzl $1, 1b \n" \
- __FUTEX_SMP_SYNC \
- "3: \n" \
- " .set pop \n" \
- " .set mips0 \n" \
- " .section .fixup,\"ax\" \n" \
- "4: li %0, %5 \n" \
- " j 2b \n" \
- " .previous \n" \
- " .section __ex_table,\"a\" \n" \
- " "__UA_ADDR "\t1b, 4b \n" \
- " "__UA_ADDR "\t2b, 4b \n" \
- " .previous \n" \
- : "=r" (ret), "=r" (oldval) \
- : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \
+ if (cpu_has_llsc && R10000_LLSC_WAR) { \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ " .set noat \n" \
+ " .set mips3 \n" \
+ "1: ll %1, (%3) # __futex_atomic_op \n" \
+ " .set mips0 \n" \
+ " " insn " \n" \
+ " .set mips3 \n" \
+ "2: sc $1, (%3) \n" \
+ " beqzl $1, 1b \n" \
+ __FUTEX_SMP_SYNC \
+ "3: \n" \
+ " .set pop \n" \
+ " .set mips0 \n" \
+ " .section .fixup,\"ax\" \n" \
+ "4: li %0, %5 \n" \
+ " j 2b \n" \
+ " .previous \n" \
+ " .section __ex_table,\"a\" \n" \
+ " "__UA_ADDR "\t1b, 4b \n" \
+ " "__UA_ADDR "\t2b, 4b \n" \
+ " .previous \n" \
+ : "=r" (ret), "=r" (oldval) \
+ : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \
+ } else if (cpu_has_llsc) { \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ " .set noat \n" \
+ " .set mips3 \n" \
+ "1: ll %1, (%3) # __futex_atomic_op \n" \
+ " .set mips0 \n" \
+ " " insn " \n" \
+ " .set mips3 \n" \
+ "2: sc $1, (%3) \n" \
+ " beqz $1, 1b \n" \
+ __FUTEX_SMP_SYNC \
+ "3: \n" \
+ " .set pop \n" \
+ " .set mips0 \n" \
+ " .section .fixup,\"ax\" \n" \
+ "4: li %0, %5 \n" \
+ " j 2b \n" \
+ " .previous \n" \
+ " .section __ex_table,\"a\" \n" \
+ " "__UA_ADDR "\t1b, 4b \n" \
+ " "__UA_ADDR "\t2b, 4b \n" \
+ " .previous \n" \
+ : "=r" (ret), "=r" (oldval) \
+ : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \
+ } else \
+ ret = -ENOSYS; \
}
static inline int
@@ -99,5 +128,73 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
return ret;
}
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ int retval;
+
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ if (cpu_has_llsc && R10000_LLSC_WAR) {
+ __asm__ __volatile__(
+ "# futex_atomic_cmpxchg_inatomic \n"
+ " .set push \n"
+ " .set noat \n"
+ " .set mips3 \n"
+ "1: ll %0, %2 \n"
+ " bne %0, %z3, 3f \n"
+ " .set mips0 \n"
+ " move $1, %z4 \n"
+ " .set mips3 \n"
+ "2: sc $1, %1 \n"
+ " beqzl $1, 1b \n"
+ __FUTEX_SMP_SYNC
+ "3: \n"
+ " .set pop \n"
+ " .section .fixup,\"ax\" \n"
+ "4: li %0, %5 \n"
+ " j 3b \n"
+ " .previous \n"
+ " .section __ex_table,\"a\" \n"
+ " "__UA_ADDR "\t1b, 4b \n"
+ " "__UA_ADDR "\t2b, 4b \n"
+ " .previous \n"
+ : "=&r" (retval), "=R" (*uaddr)
+ : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
+ : "memory");
+ } else if (cpu_has_llsc) {
+ __asm__ __volatile__(
+ "# futex_atomic_cmpxchg_inatomic \n"
+ " .set push \n"
+ " .set noat \n"
+ " .set mips3 \n"
+ "1: ll %0, %2 \n"
+ " bne %0, %z3, 3f \n"
+ " .set mips0 \n"
+ " move $1, %z4 \n"
+ " .set mips3 \n"
+ "2: sc $1, %1 \n"
+ " beqz $1, 1b \n"
+ __FUTEX_SMP_SYNC
+ "3: \n"
+ " .set pop \n"
+ " .section .fixup,\"ax\" \n"
+ "4: li %0, %5 \n"
+ " j 3b \n"
+ " .previous \n"
+ " .section __ex_table,\"a\" \n"
+ " "__UA_ADDR "\t1b, 4b \n"
+ " "__UA_ADDR "\t2b, 4b \n"
+ " .previous \n"
+ : "=&r" (retval), "=R" (*uaddr)
+ : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
+ : "memory");
+ } else
+ return -ENOSYS;
+
+ return retval;
+}
+
#endif
#endif
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index feb29a79388..dadc05188db 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -284,6 +284,8 @@ do { \
#define instruction_hazard() do { } while (0)
#endif
+extern void mips_ihb(void);
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_HAZARDS_H */
diff --git a/include/asm-mips/inst.h b/include/asm-mips/inst.h
index e0745f4ff62..1ed8d0f6257 100644
--- a/include/asm-mips/inst.h
+++ b/include/asm-mips/inst.h
@@ -6,6 +6,7 @@
* for more details.
*
* Copyright (C) 1996, 2000 by Ralf Baechle
+ * Copyright (C) 2006 by Thiemo Seufer
*/
#ifndef _ASM_INST_H
#define _ASM_INST_H
@@ -21,14 +22,14 @@ enum major_op {
cop0_op, cop1_op, cop2_op, cop1x_op,
beql_op, bnel_op, blezl_op, bgtzl_op,
daddi_op, daddiu_op, ldl_op, ldr_op,
- major_1c_op, jalx_op, major_1e_op, major_1f_op,
+ spec2_op, jalx_op, mdmx_op, spec3_op,
lb_op, lh_op, lwl_op, lw_op,
lbu_op, lhu_op, lwr_op, lwu_op,
sb_op, sh_op, swl_op, sw_op,
sdl_op, sdr_op, swr_op, cache_op,
ll_op, lwc1_op, lwc2_op, pref_op,
lld_op, ldc1_op, ldc2_op, ld_op,
- sc_op, swc1_op, swc2_op, rdhwr_op,
+ sc_op, swc1_op, swc2_op, major_3b_op,
scd_op, sdc1_op, sdc2_op, sd_op
};
@@ -37,7 +38,7 @@ enum major_op {
*/
enum spec_op {
sll_op, movc_op, srl_op, sra_op,
- sllv_op, srlv_op, srav_op, spec1_unused_op, /* Opcode 0x07 is unused */
+ sllv_op, pmon_op, srlv_op, srav_op,
jr_op, jalr_op, movz_op, movn_op,
syscall_op, break_op, spim_op, sync_op,
mfhi_op, mthi_op, mflo_op, mtlo_op,
@@ -55,6 +56,28 @@ enum spec_op {
};
/*
+ * func field of spec2 opcode.
+ */
+enum spec2_op {
+ madd_op, maddu_op, mul_op, spec2_3_unused_op,
+ msub_op, msubu_op, /* more unused ops */
+ clz_op = 0x20, clo_op,
+ dclz_op = 0x24, dclo_op,
+ sdbpp_op = 0x3f
+};
+
+/*
+ * func field of spec3 opcode.
+ */
+enum spec3_op {
+ ext_op, dextm_op, dextu_op, dext_op,
+ ins_op, dinsm_op, dinsu_op, dins_op,
+ bshfl_op = 0x20,
+ dbshfl_op = 0x24,
+ rdhwr_op = 0x3f
+};
+
+/*
* rt field of bcond opcodes.
*/
enum rt_op {
@@ -151,8 +174,8 @@ enum cop1x_func {
* func field for mad opcodes (MIPS IV).
*/
enum mad_func {
- madd_op = 0x08, msub_op = 0x0a,
- nmadd_op = 0x0c, nmsub_op = 0x0e
+ madd_fp_op = 0x08, msub_fp_op = 0x0a,
+ nmadd_fp_op = 0x0c, nmsub_fp_op = 0x0e
};
/*
diff --git a/include/asm-mips/interrupt.h b/include/asm-mips/interrupt.h
index 774348734fa..4bb9c06f441 100644
--- a/include/asm-mips/interrupt.h
+++ b/include/asm-mips/interrupt.h
@@ -19,7 +19,12 @@ __asm__ (
" .set push \n"
" .set reorder \n"
" .set noat \n"
-#ifdef CONFIG_CPU_MIPSR2
+#ifdef CONFIG_MIPS_MT_SMTC
+ " mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n"
+ " ori $1, 0x400 \n"
+ " xori $1, 0x400 \n"
+ " mtc0 $1, $2, 1 \n"
+#elif defined(CONFIG_CPU_MIPSR2)
" ei \n"
#else
" mfc0 $1,$12 \n"
@@ -62,7 +67,12 @@ __asm__ (
" .macro local_irq_disable\n"
" .set push \n"
" .set noat \n"
-#ifdef CONFIG_CPU_MIPSR2
+#ifdef CONFIG_MIPS_MT_SMTC
+ " mfc0 $1, $2, 1 \n"
+ " ori $1, 0x400 \n"
+ " .set noreorder \n"
+ " mtc0 $1, $2, 1 \n"
+#elif defined(CONFIG_CPU_MIPSR2)
" di \n"
#else
" mfc0 $1,$12 \n"
@@ -88,7 +98,11 @@ __asm__ (
" .macro local_save_flags flags \n"
" .set push \n"
" .set reorder \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+ " mfc0 \\flags, $2, 1 \n"
+#else
" mfc0 \\flags, $12 \n"
+#endif
" .set pop \n"
" .endm \n");
@@ -102,7 +116,13 @@ __asm__ (
" .set push \n"
" .set reorder \n"
" .set noat \n"
-#ifdef CONFIG_CPU_MIPSR2
+#ifdef CONFIG_MIPS_MT_SMTC
+ " mfc0 \\result, $2, 1 \n"
+ " ori $1, \\result, 0x400 \n"
+ " .set noreorder \n"
+ " mtc0 $1, $2, 1 \n"
+ " andi \\result, \\result, 0x400 \n"
+#elif defined(CONFIG_CPU_MIPSR2)
" di \\result \n"
" andi \\result, 1 \n"
#else
@@ -128,7 +148,14 @@ __asm__ (
" .set push \n"
" .set noreorder \n"
" .set noat \n"
-#if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+#ifdef CONFIG_MIPS_MT_SMTC
+ "mfc0 $1, $2, 1 \n"
+ "andi \\flags, 0x400 \n"
+ "ori $1, 0x400 \n"
+ "xori $1, 0x400 \n"
+ "or \\flags, $1 \n"
+ "mtc0 \\flags, $2, 1 \n"
+#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
/*
* Slow, but doesn't suffer from a relativly unlikely race
* condition we're having since days 1.
@@ -167,11 +194,29 @@ do { \
: "memory"); \
} while(0)
-#define irqs_disabled() \
-({ \
- unsigned long flags; \
- local_save_flags(flags); \
- !(flags & 1); \
-})
+static inline int irqs_disabled(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU
+ */
+ unsigned long __result;
+
+ __asm__ __volatile__(
+ " .set noreorder \n"
+ " mfc0 %0, $2, 1 \n"
+ " andi %0, 0x400 \n"
+ " slt %0, $0, %0 \n"
+ " .set reorder \n"
+ : "=r" (__result));
+
+ return __result;
+#else
+ unsigned long flags;
+ local_save_flags(flags);
+
+ return !(flags & 1);
+#endif
+}
#endif /* _ASM_INTERRUPT_H */
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index 8a342ccb34a..dde677f02bc 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -11,6 +11,9 @@
#include <linux/config.h>
#include <linux/linkage.h>
+
+#include <asm/mipsmtregs.h>
+
#include <irq.h>
#ifdef CONFIG_I8259
@@ -26,6 +29,23 @@ struct pt_regs;
extern asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs);
+#ifdef CONFIG_MIPS_MT_SMTC
+/*
+ * Clear interrupt mask handling "backstop" if irq_hwmask
+ * entry so indicates. This implies that the ack() or end()
+ * functions will take over re-enabling the low-level mask.
+ * Otherwise it will be done on return from exception.
+ */
+#define __DO_IRQ_SMTC_HOOK() \
+do { \
+ if (irq_hwmask[irq] & 0x0000ff00) \
+ write_c0_tccontext(read_c0_tccontext() & \
+ ~(irq_hwmask[irq] & 0x0000ff00)); \
+} while (0)
+#else
+#define __DO_IRQ_SMTC_HOOK() do { } while (0)
+#endif
+
#ifdef CONFIG_PREEMPT
/*
@@ -39,6 +59,7 @@ extern asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs);
#define do_IRQ(irq, regs) \
do { \
irq_enter(); \
+ __DO_IRQ_SMTC_HOOK(); \
__do_IRQ((irq), (regs)); \
irq_exit(); \
} while (0)
@@ -46,5 +67,14 @@ do { \
#endif
extern void arch_init_irq(void);
+extern void spurious_interrupt(struct pt_regs *regs);
+
+#ifdef CONFIG_MIPS_MT_SMTC
+struct irqaction;
+
+extern unsigned long irq_hwmask[];
+extern int setup_irq_smtc(unsigned int irq, struct irqaction * new,
+ unsigned long hwmask);
+#endif /* CONFIG_MIPS_MT_SMTC */
#endif /* _ASM_IRQ_H */
diff --git a/include/asm-mips/kspd.h b/include/asm-mips/kspd.h
new file mode 100644
index 00000000000..4e9e724c893
--- /dev/null
+++ b/include/asm-mips/kspd.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _ASM_KSPD_H
+#define _ASM_KSPD_H
+
+struct kspd_notifications {
+ void (*kspd_sp_exit)(int sp_id);
+
+ struct list_head list;
+};
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+extern void kspd_notify(struct kspd_notifications *notify);
+#else
+static inline void kspd_notify(struct kspd_notifications *notify)
+{
+}
+#endif
+
+#endif
diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h
index 550979a9ea9..e3315359500 100644
--- a/include/asm-mips/mach-generic/ide.h
+++ b/include/asm-mips/mach-generic/ide.h
@@ -104,65 +104,107 @@ static __inline__ unsigned long ide_default_io_base(int index)
#endif
/* MIPS port and memory-mapped I/O string operations. */
+static inline void __ide_flush_prologue(void)
+{
+#ifdef CONFIG_SMP
+ if (cpu_has_dc_aliases)
+ preempt_disable();
+#endif
+}
+
+static inline void __ide_flush_epilogue(void)
+{
+#ifdef CONFIG_SMP
+ if (cpu_has_dc_aliases)
+ preempt_enable();
+#endif
+}
static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
{
if (cpu_has_dc_aliases) {
unsigned long end = addr + size;
- for (; addr < end; addr += PAGE_SIZE)
- flush_dcache_page(virt_to_page(addr));
+
+ while (addr < end) {
+ local_flush_data_cache_page((void *)addr);
+ addr += PAGE_SIZE;
+ }
}
}
+/*
+ * insw() and gang might be called with interrupts disabled, so we can't
+ * send IPIs for flushing due to the potencial of deadlocks, see the comment
+ * above smp_call_function() in arch/mips/kernel/smp.c. We work around the
+ * problem by disabling preemption so we know we actually perform the flush
+ * on the processor that actually has the lines to be flushed which hopefully
+ * is even better for performance anyway.
+ */
static inline void __ide_insw(unsigned long port, void *addr,
unsigned int count)
{
+ __ide_flush_prologue();
insw(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 2);
+ __ide_flush_epilogue();
}
static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
{
+ __ide_flush_prologue();
insl(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 4);
+ __ide_flush_epilogue();
}
static inline void __ide_outsw(unsigned long port, const void *addr,
unsigned long count)
{
+ __ide_flush_prologue();
outsw(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 2);
+ __ide_flush_epilogue();
}
static inline void __ide_outsl(unsigned long port, const void *addr,
unsigned long count)
{
+ __ide_flush_prologue();
outsl(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 4);
+ __ide_flush_epilogue();
}
static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
{
+ __ide_flush_prologue();
readsw(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 2);
+ __ide_flush_epilogue();
}
static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
{
+ __ide_flush_prologue();
readsl(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 4);
+ __ide_flush_epilogue();
}
static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
{
+ __ide_flush_prologue();
writesw(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 2);
+ __ide_flush_epilogue();
}
static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
{
+ __ide_flush_prologue();
writesl(port, addr, count);
__ide_flush_dcache_range((unsigned long)addr, count * 4);
+ __ide_flush_epilogue();
}
/* ide_insw calls insw, not __ide_insw. Why? */
diff --git a/include/asm-mips/mach-jmr3927/ds1742.h b/include/asm-mips/mach-jmr3927/ds1742.h
index cff6192d4bd..8a8fef6d07f 100644
--- a/include/asm-mips/mach-jmr3927/ds1742.h
+++ b/include/asm-mips/mach-jmr3927/ds1742.h
@@ -3,14 +3,14 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2003 by Ralf Baechle
+ * Copyright (C) 2003, 06 by Ralf Baechle
*/
#ifndef __ASM_MACH_JMR3927_DS1742_H
#define __ASM_MACH_JMR3927_DS1742_H
#include <asm/jmr3927/jmr3927.h>
-#define rtc_read(reg) (jmr3927_nvram_in(addr))
+#define rtc_read(reg) (jmr3927_nvram_in(reg))
#define rtc_write(data, reg) (jmr3927_nvram_out((data),(reg)))
#endif /* __ASM_MACH_JMR3927_DS1742_H */
diff --git a/include/asm-mips/mach-mips/param.h b/include/asm-mips/mach-mips/param.h
new file mode 100644
index 00000000000..805ef6d27d3
--- /dev/null
+++ b/include/asm-mips/mach-mips/param.h
@@ -0,0 +1,13 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_MIPS_PARAM_H
+#define __ASM_MACH_MIPS_PARAM_H
+
+#define HZ 100 /* Internal kernel timer frequency */
+
+#endif /* __ASM_MACH_MIPS_PARAM_H */
diff --git a/include/asm-mips/marvell.h b/include/asm-mips/marvell.h
index 9225b3397a4..6bb2125bb05 100644
--- a/include/asm-mips/marvell.h
+++ b/include/asm-mips/marvell.h
@@ -53,4 +53,6 @@ struct mv_pci_controller {
unsigned long config_vreg;
};
+extern void ll_mv64340_irq(struct pt_regs *regs);
+
#endif /* __ASM_MIPS_MARVELL_H */
diff --git a/include/asm-mips/mc146818-time.h b/include/asm-mips/mc146818-time.h
index 47214861093..41ac8d363c6 100644
--- a/include/asm-mips/mc146818-time.h
+++ b/include/asm-mips/mc146818-time.h
@@ -86,43 +86,14 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime)
return retval;
}
-/*
- * Returns true if a clock update is in progress
- */
-static inline unsigned char rtc_is_updating(void)
-{
- unsigned char uip;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
- spin_unlock_irqrestore(&rtc_lock, flags);
- return uip;
-}
-
static inline unsigned long mc146818_get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- int i;
unsigned long flags;
- /*
- * The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
-
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (rtc_is_updating())
- break;
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!rtc_is_updating())
- break;
-
spin_lock_irqsave(&rtc_lock, flags);
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
+
+ do {
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
hour = CMOS_READ(RTC_HOURS);
diff --git a/include/asm-mips/mips-boards/atlas.h b/include/asm-mips/mips-boards/atlas.h
index 0998151fb3a..a8ae12d120e 100644
--- a/include/asm-mips/mips-boards/atlas.h
+++ b/include/asm-mips/mips-boards/atlas.h
@@ -33,13 +33,29 @@
#define ATLAS_RTC_ADR_REG 0x1f000800
#define ATLAS_RTC_DAT_REG 0x1f000808
-
/*
* Atlas interrupt controller register base.
*/
#define ATLAS_ICTRL_REGS_BASE 0x1f000000
/*
+ * Atlas registers are memory mapped on 64-bit aligned boundaries and
+ * only word access are allowed.
+ */
+struct atlas_ictrl_regs {
+ volatile unsigned int intraw;
+ int dummy1;
+ volatile unsigned int intseten;
+ int dummy2;
+ volatile unsigned int intrsten;
+ int dummy3;
+ volatile unsigned int intenable;
+ int dummy4;
+ volatile unsigned int intstatus;
+ int dummy5;
+};
+
+/*
* Atlas UART register base.
*/
#define ATLAS_UART_REGS_BASE 0x1f000900
diff --git a/include/asm-mips/mips-boards/atlasint.h b/include/asm-mips/mips-boards/atlasint.h
index bba35c183d0..fd7ebc54fa9 100644
--- a/include/asm-mips/mips-boards/atlasint.h
+++ b/include/asm-mips/mips-boards/atlasint.h
@@ -62,23 +62,4 @@
#define ATLASINT_RES31 (ATLASINT_BASE+31)
#define ATLASINT_END (ATLASINT_BASE+31)
-/*
- * Atlas registers are memory mapped on 64-bit aligned boundaries and
- * only word access are allowed.
- */
-struct atlas_ictrl_regs {
- volatile unsigned int intraw;
- int dummy1;
- volatile unsigned int intseten;
- int dummy2;
- volatile unsigned int intrsten;
- int dummy3;
- volatile unsigned int intenable;
- int dummy4;
- volatile unsigned int intstatus;
- int dummy5;
-};
-
-extern void atlasint_init(void);
-
#endif /* !(_MIPS_ATLASINT_H) */
diff --git a/include/asm-mips/mips-boards/generic.h b/include/asm-mips/mips-boards/generic.h
index 25b6ffc2662..fa8b913cc3e 100644
--- a/include/asm-mips/mips-boards/generic.h
+++ b/include/asm-mips/mips-boards/generic.h
@@ -67,6 +67,7 @@
#define MIPS_REVISION_CORID_CORE_FPGA2 7
#define MIPS_REVISION_CORID_CORE_FPGAR2 8
#define MIPS_REVISION_CORID_CORE_FPGA3 9
+#define MIPS_REVISION_CORID_CORE_24K 10
/**** Artificial corid defines ****/
/*
diff --git a/include/asm-mips/mips_mt.h b/include/asm-mips/mips_mt.h
new file mode 100644
index 00000000000..c31a312b978
--- /dev/null
+++ b/include/asm-mips/mips_mt.h
@@ -0,0 +1,15 @@
+/*
+ * Definitions and decalrations for MIPS MT support
+ * that are common between SMTC, VSMP, and/or AP/SP
+ * kernel models.
+ */
+#ifndef __ASM_MIPS_MT_H
+#define __ASM_MIPS_MT_H
+
+extern cpumask_t mt_fpu_cpumask;
+extern unsigned long mt_fpemul_threshold;
+
+extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value);
+extern void mips_mt_set_cpuoptions(void);
+
+#endif /* __ASM_MIPS_MT_H */
diff --git a/include/asm-mips/mipsmtregs.h b/include/asm-mips/mipsmtregs.h
index a669c0702c6..f637ce70758 100644
--- a/include/asm-mips/mipsmtregs.h
+++ b/include/asm-mips/mipsmtregs.h
@@ -165,7 +165,7 @@
#ifndef __ASSEMBLY__
-extern void mips_mt_regdump(void);
+extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value);
static inline unsigned int dvpe(void)
{
@@ -234,7 +234,7 @@ static inline void __raw_emt(void)
__asm__ __volatile__(
" .set noreorder \n"
" .set mips32r2 \n"
- " emt \n"
+ " .word 0x41600be1 # emt \n"
" ehb \n"
" .set mips0 \n"
" .set reorder");
@@ -282,8 +282,11 @@ static inline void ehb(void)
\
__asm__ __volatile__( \
" .set push \n" \
+ " .set noat \n" \
" .set mips32r2 \n" \
- " mftgpr %0," #rt " \n" \
+ " # mftgpr $1," #rt " \n" \
+ " .word 0x41000820 | (" #rt " << 16) \n" \
+ " move %0, $1 \n" \
" .set pop \n" \
: "=r" (__res)); \
\
@@ -295,9 +298,7 @@ static inline void ehb(void)
unsigned long __res; \
\
__asm__ __volatile__( \
- ".set noat\n\t" \
- "mftr\t%0, " #rt ", " #u ", " #sel "\n\t" \
- ".set at\n\t" \
+ " mftr %0, " #rt ", " #u ", " #sel " \n" \
: "=r" (__res)); \
\
__res; \
@@ -364,6 +365,9 @@ do { \
#define read_vpe_c0_ebase() mftc0(15,1)
#define write_vpe_c0_ebase(val) mttc0(15, 1, val)
#define write_vpe_c0_compare(val) mttc0(11, 0, val)
+#define read_vpe_c0_badvaddr() mftc0(8, 0)
+#define read_vpe_c0_epc() mftc0(14, 0)
+#define write_vpe_c0_epc(val) mttc0(14, 0, val)
/* TC */
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 035ba0a9b0d..5af7517fce8 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -291,7 +291,7 @@
#define ST0_DL (_ULCAST_(1) << 24)
/*
- * Enable the MIPS DSP ASE
+ * Enable the MIPS MDMX and DSP ASEs
*/
#define ST0_MX 0x01000000
@@ -836,6 +836,9 @@ do { \
#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */
#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val)
+#define read_c0_badvaddr() __read_ulong_c0_register($8, 0)
+#define write_c0_badvaddr(val) __write_ulong_c0_register($8, 0, val)
+
#define read_c0_count() __read_32bit_c0_register($9, 0)
#define write_c0_count(val) __write_32bit_c0_register($9, 0, val)
@@ -858,7 +861,19 @@ do { \
#define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val)
#define read_c0_status() __read_32bit_c0_register($12, 0)
+#ifdef CONFIG_MIPS_MT_SMTC
+#define write_c0_status(val) \
+do { \
+ __write_32bit_c0_register($12, 0, val); \
+ __ehb(); \
+} while (0)
+#else
+/*
+ * Legacy non-SMTC code, which may be hazardous
+ * but which might not support EHB
+ */
#define write_c0_status(val) __write_32bit_c0_register($12, 0, val)
+#endif /* CONFIG_MIPS_MT_SMTC */
#define read_c0_cause() __read_32bit_c0_register($13, 0)
#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val)
@@ -1001,6 +1016,9 @@ do { \
#define read_c0_taglo() __read_32bit_c0_register($28, 0)
#define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val)
+#define read_c0_dtaglo() __read_32bit_c0_register($28, 2)
+#define write_c0_dtaglo(val) __write_32bit_c0_register($28, 2, val)
+
#define read_c0_taghi() __read_32bit_c0_register($29, 0)
#define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val)
@@ -1354,15 +1372,119 @@ static inline void tlb_write_random(void)
/*
* Manipulate bits in a c0 register.
*/
+#ifndef CONFIG_MIPS_MT_SMTC
+/*
+ * SMTC Linux requires shutting-down microthread scheduling
+ * during CP0 register read-modify-write sequences.
+ */
+#define __BUILD_SET_C0(name) \
+static inline unsigned int \
+set_c0_##name(unsigned int set) \
+{ \
+ unsigned int res; \
+ \
+ res = read_c0_##name(); \
+ res |= set; \
+ write_c0_##name(res); \
+ \
+ return res; \
+} \
+ \
+static inline unsigned int \
+clear_c0_##name(unsigned int clear) \
+{ \
+ unsigned int res; \
+ \
+ res = read_c0_##name(); \
+ res &= ~clear; \
+ write_c0_##name(res); \
+ \
+ return res; \
+} \
+ \
+static inline unsigned int \
+change_c0_##name(unsigned int change, unsigned int new) \
+{ \
+ unsigned int res; \
+ \
+ res = read_c0_##name(); \
+ res &= ~change; \
+ res |= (new & change); \
+ write_c0_##name(res); \
+ \
+ return res; \
+}
+
+#else /* SMTC versions that manage MT scheduling */
+
+#include <asm/interrupt.h>
+
+/*
+ * This is a duplicate of dmt() in mipsmtregs.h to avoid problems with
+ * header file recursion.
+ */
+static inline unsigned int __dmt(void)
+{
+ int res;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set mips32r2 \n"
+ " .set noat \n"
+ " .word 0x41610BC1 # dmt $1 \n"
+ " ehb \n"
+ " move %0, $1 \n"
+ " .set pop \n"
+ : "=r" (res));
+
+ instruction_hazard();
+
+ return res;
+}
+
+#define __VPECONTROL_TE_SHIFT 15
+#define __VPECONTROL_TE (1UL << __VPECONTROL_TE_SHIFT)
+
+#define __EMT_ENABLE __VPECONTROL_TE
+
+static inline void __emt(unsigned int previous)
+{
+ if ((previous & __EMT_ENABLE))
+ __asm__ __volatile__(
+ " .set noreorder \n"
+ " .set mips32r2 \n"
+ " .word 0x41600be1 # emt \n"
+ " ehb \n"
+ " .set mips0 \n"
+ " .set reorder \n");
+}
+
+static inline void __ehb(void)
+{
+ __asm__ __volatile__(
+ " ehb \n");
+}
+
+/*
+ * Note that local_irq_save/restore affect TC-specific IXMT state,
+ * not Status.IE as in non-SMTC kernel.
+ */
+
#define __BUILD_SET_C0(name) \
static inline unsigned int \
set_c0_##name(unsigned int set) \
{ \
unsigned int res; \
+ unsigned int omt; \
+ unsigned int flags; \
\
+ local_irq_save(flags); \
+ omt = __dmt(); \
res = read_c0_##name(); \
res |= set; \
write_c0_##name(res); \
+ __emt(omt); \
+ local_irq_restore(flags); \
\
return res; \
} \
@@ -1371,10 +1493,16 @@ static inline unsigned int \
clear_c0_##name(unsigned int clear) \
{ \
unsigned int res; \
+ unsigned int omt; \
+ unsigned int flags; \
\
+ local_irq_save(flags); \
+ omt = __dmt(); \
res = read_c0_##name(); \
res &= ~clear; \
write_c0_##name(res); \
+ __emt(omt); \
+ local_irq_restore(flags); \
\
return res; \
} \
@@ -1383,14 +1511,22 @@ static inline unsigned int \
change_c0_##name(unsigned int change, unsigned int new) \
{ \
unsigned int res; \
+ unsigned int omt; \
+ unsigned int flags; \
\
+ local_irq_save(flags); \
+ \
+ omt = __dmt(); \
res = read_c0_##name(); \
res &= ~change; \
res |= (new & change); \
write_c0_##name(res); \
+ __emt(omt); \
+ local_irq_restore(flags); \
\
return res; \
}
+#endif
__BUILD_SET_C0(status)
__BUILD_SET_C0(cause)
diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h
index 61cf2258813..6e09f4c8721 100644
--- a/include/asm-mips/mmu_context.h
+++ b/include/asm-mips/mmu_context.h
@@ -17,6 +17,10 @@
#include <linux/slab.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#include <asm/smtc.h>
+#endif /* SMTC */
/*
* For the fast tlb miss handlers, we keep a per cpu array of pointers
@@ -54,6 +58,14 @@ extern unsigned long pgd_current[];
#define ASID_INC 0x1
#define ASID_MASK 0xfff
+/* SMTC/34K debug hack - but maybe we'll keep it */
+#elif defined(CONFIG_MIPS_MT_SMTC)
+
+#define ASID_INC 0x1
+extern unsigned long smtc_asid_mask;
+#define ASID_MASK (smtc_asid_mask)
+#define HW_ASID_MASK 0xff
+/* End SMTC/34K debug hack */
#else /* FIXME: not correct for R6000 */
#define ASID_INC 0x1
@@ -76,6 +88,8 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
#define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
+#ifndef CONFIG_MIPS_MT_SMTC
+/* Normal, classic MIPS get_new_mmu_context */
static inline void
get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
{
@@ -91,6 +105,12 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
cpu_context(cpu, mm) = asid_cache(cpu) = asid;
}
+#else /* CONFIG_MIPS_MT_SMTC */
+
+#define get_new_mmu_context(mm,cpu) smtc_get_new_mmu_context((mm),(cpu))
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+
/*
* Initialize the context related info for a new mm_struct
* instance.
@@ -111,14 +131,46 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
{
unsigned int cpu = smp_processor_id();
unsigned long flags;
-
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned long oldasid;
+ unsigned long mtflags;
+ int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
local_irq_save(flags);
+ mtflags = dvpe();
+#else /* Not SMTC */
+ local_irq_save(flags);
+#endif /* CONFIG_MIPS_MT_SMTC */
/* Check if our ASID is of an older version and thus invalid */
if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
get_new_mmu_context(next, cpu);
-
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * If the EntryHi ASID being replaced happens to be
+ * the value flagged at ASID recycling time as having
+ * an extended life, clear the bit showing it being
+ * in use by this "CPU", and if that's the last bit,
+ * free up the ASID value for use and flush any old
+ * instances of it from the TLB.
+ */
+ oldasid = (read_c0_entryhi() & ASID_MASK);
+ if(smtc_live_asid[mytlb][oldasid]) {
+ smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+ if(smtc_live_asid[mytlb][oldasid] == 0)
+ smtc_flush_tlb_asid(oldasid);
+ }
+ /*
+ * Tread softly on EntryHi, and so long as we support
+ * having ASID_MASK smaller than the hardware maximum,
+ * make sure no "soft" bits become "hard"...
+ */
+ write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
+ | (cpu_context(cpu, next) & ASID_MASK));
+ ehb(); /* Make sure it propagates to TCStatus */
+ evpe(mtflags);
+#else
write_c0_entryhi(cpu_context(cpu, next));
+#endif /* CONFIG_MIPS_MT_SMTC */
TLBMISS_HANDLER_SETUP_PGD(next->pgd);
/*
@@ -151,12 +203,34 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
unsigned long flags;
unsigned int cpu = smp_processor_id();
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned long oldasid;
+ unsigned long mtflags;
+ int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
+#endif /* CONFIG_MIPS_MT_SMTC */
+
local_irq_save(flags);
/* Unconditionally get a new ASID. */
get_new_mmu_context(next, cpu);
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* See comments for similar code above */
+ mtflags = dvpe();
+ oldasid = read_c0_entryhi() & ASID_MASK;
+ if(smtc_live_asid[mytlb][oldasid]) {
+ smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+ if(smtc_live_asid[mytlb][oldasid] == 0)
+ smtc_flush_tlb_asid(oldasid);
+ }
+ /* See comments for similar code above */
+ write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
+ (cpu_context(cpu, next) & ASID_MASK));
+ ehb(); /* Make sure it propagates to TCStatus */
+ evpe(mtflags);
+#else
write_c0_entryhi(cpu_context(cpu, next));
+#endif /* CONFIG_MIPS_MT_SMTC */
TLBMISS_HANDLER_SETUP_PGD(next->pgd);
/* mark mmu ownership change */
@@ -174,17 +248,49 @@ static inline void
drop_mmu_context(struct mm_struct *mm, unsigned cpu)
{
unsigned long flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned long oldasid;
+ /* Can't use spinlock because called from TLB flush within DVPE */
+ unsigned int prevvpe;
+ int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
+#endif /* CONFIG_MIPS_MT_SMTC */
local_irq_save(flags);
if (cpu_isset(cpu, mm->cpu_vm_mask)) {
get_new_mmu_context(mm, cpu);
+#ifdef CONFIG_MIPS_MT_SMTC
+ /* See comments for similar code above */
+ prevvpe = dvpe();
+ oldasid = (read_c0_entryhi() & ASID_MASK);
+ if(smtc_live_asid[mytlb][oldasid]) {
+ smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+ if(smtc_live_asid[mytlb][oldasid] == 0)
+ smtc_flush_tlb_asid(oldasid);
+ }
+ /* See comments for similar code above */
+ write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
+ | cpu_asid(cpu, mm));
+ ehb(); /* Make sure it propagates to TCStatus */
+ evpe(prevvpe);
+#else /* not CONFIG_MIPS_MT_SMTC */
write_c0_entryhi(cpu_asid(cpu, mm));
+#endif /* CONFIG_MIPS_MT_SMTC */
} else {
/* will get a new context next time */
+#ifndef CONFIG_MIPS_MT_SMTC
cpu_context(cpu, mm) = 0;
+#else /* SMTC */
+ int i;
+
+ /* SMTC shares the TLB (and ASIDs) across VPEs */
+ for (i = 0; i < num_online_cpus(); i++) {
+ if((smtc_status & SMTC_TLB_SHARED)
+ || (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
+ cpu_context(i, mm) = 0;
+ }
+#endif /* CONFIG_MIPS_MT_SMTC */
}
-
local_irq_restore(flags);
}
diff --git a/include/asm-mips/mmzone.h b/include/asm-mips/mmzone.h
index 011caebac36..7bde4432092 100644
--- a/include/asm-mips/mmzone.h
+++ b/include/asm-mips/mmzone.h
@@ -22,20 +22,6 @@
NODE_DATA(__n)->node_spanned_pages) : 0);\
})
-#define pfn_to_page(pfn) \
-({ \
- unsigned long __pfn = (pfn); \
- pg_data_t *__pg = NODE_DATA(pfn_to_nid(__pfn)); \
- __pg->node_mem_map + (__pfn - __pg->node_start_pfn); \
-})
-
-#define page_to_pfn(p) \
-({ \
- struct page *__p = (p); \
- struct zone *__z = page_zone(__p); \
- ((__p - __z->zone_mem_map) + __z->zone_start_pfn); \
-})
-
/* XXX: FIXME -- wli */
#define kern_addr_valid(addr) (0)
diff --git a/include/asm-mips/numnodes.h b/include/asm-mips/numnodes.h
deleted file mode 100644
index 4f00c16ceeb..00000000000
--- a/include/asm-mips/numnodes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-/* Max 128 Nodes */
-#define NODES_SHIFT 6
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index ee25a779bf4..4035ec79ecd 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -139,11 +139,11 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
+#ifndef CONFIG_SPARSEMEM
#ifndef CONFIG_NEED_MULTIPLE_NODES
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#endif
+#endif
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
@@ -160,6 +160,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define WANT_PAGE_VIRTUAL
#endif
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _ASM_PAGE_H */
diff --git a/include/asm-mips/pgtable-32.h b/include/asm-mips/pgtable-32.h
index 4d6bc45df59..087c2076925 100644
--- a/include/asm-mips/pgtable-32.h
+++ b/include/asm-mips/pgtable-32.h
@@ -177,48 +177,67 @@ pfn_pte(unsigned long pfn, pgprot_t prot)
((swp_entry_t) { ((type) << 10) | ((offset) << 15) })
/*
- * Bits 0, 1, 2, 9 and 10 are taken, split up the 27 bits of offset
- * into this range:
+ * Bits 0, 4, 8, and 9 are taken, split up 28 bits of offset into this range:
*/
-#define PTE_FILE_MAX_BITS 27
+#define PTE_FILE_MAX_BITS 28
-#define pte_to_pgoff(_pte) \
- ((((_pte).pte >> 3) & 0x3f ) + (((_pte).pte >> 11) << 8 ))
+#define pte_to_pgoff(_pte) ((((_pte).pte >> 1 ) & 0x07) | \
+ (((_pte).pte >> 2 ) & 0x38) | \
+ (((_pte).pte >> 10) << 6 ))
-#define pgoff_to_pte(off) \
- ((pte_t) { (((off) & 0x3f) << 3) + (((off) >> 8) << 11) + _PAGE_FILE })
+#define pgoff_to_pte(off) ((pte_t) { (((off) & 0x07) << 1 ) | \
+ (((off) & 0x38) << 2 ) | \
+ (((off) >> 6 ) << 10) | \
+ _PAGE_FILE })
#else
/* Swap entries must have VALID and GLOBAL bits cleared. */
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#define __swp_type(x) (((x).val >> 2) & 0x1f)
+#define __swp_offset(x) ((x).val >> 7)
+#define __swp_entry(type,offset) \
+ ((swp_entry_t) { ((type) << 2) | ((offset) << 7) })
+#else
#define __swp_type(x) (((x).val >> 8) & 0x1f)
-#define __swp_offset(x) ((x).val >> 13)
+#define __swp_offset(x) ((x).val >> 13)
#define __swp_entry(type,offset) \
- ((swp_entry_t) { ((type) << 8) | ((offset) << 13) })
+ ((swp_entry_t) { ((type) << 8) | ((offset) << 13) })
+#endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) */
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
/*
- * Bits 0, 1, 2, 7 and 8 are taken, split up the 27 bits of offset
- * into this range:
+ * Bits 0 and 1 of pte_high are taken, use the rest for the page offset...
*/
-#define PTE_FILE_MAX_BITS 27
+#define PTE_FILE_MAX_BITS 30
-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
- /* fixme */
-#define pte_to_pgoff(_pte) (((_pte).pte_high >> 6) + ((_pte).pte_high & 0x3f))
-#define pgoff_to_pte(off) \
- ((pte_t){(((off) & 0x3f) + ((off) << 6) + _PAGE_FILE)})
+#define pte_to_pgoff(_pte) ((_pte).pte_high >> 2)
+#define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) << 2 })
#else
-#define pte_to_pgoff(_pte) \
- ((((_pte).pte >> 3) & 0x1f ) + (((_pte).pte >> 9) << 6 ))
+/*
+ * Bits 0, 4, 6, and 7 are taken, split up 28 bits of offset into this range:
+ */
+#define PTE_FILE_MAX_BITS 28
+
+#define pte_to_pgoff(_pte) ((((_pte).pte >> 1) & 0x7) | \
+ (((_pte).pte >> 2) & 0x8) | \
+ (((_pte).pte >> 8) << 4))
-#define pgoff_to_pte(off) \
- ((pte_t) { (((off) & 0x1f) << 3) + (((off) >> 6) << 9) + _PAGE_FILE })
+#define pgoff_to_pte(off) ((pte_t) { (((off) & 0x7) << 1) | \
+ (((off) & 0x8) << 2) | \
+ (((off) >> 4) << 8) | \
+ _PAGE_FILE })
#endif
#endif
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high })
+#define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val })
+#else
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+#endif
#endif /* _ASM_PGTABLE_32_H */
diff --git a/include/asm-mips/pgtable-64.h b/include/asm-mips/pgtable-64.h
index 82166b254b2..2faf5c9ff12 100644
--- a/include/asm-mips/pgtable-64.h
+++ b/include/asm-mips/pgtable-64.h
@@ -224,15 +224,12 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
/*
- * Bits 0, 1, 2, 7 and 8 are taken, split up the 32 bits of offset
- * into this range:
+ * Bits 0, 4, 6, and 7 are taken. Let's leave bits 1, 2, 3, and 5 alone to
+ * make things easier, and only use the upper 56 bits for the page offset...
*/
-#define PTE_FILE_MAX_BITS 32
+#define PTE_FILE_MAX_BITS 56
-#define pte_to_pgoff(_pte) \
- ((((_pte).pte >> 3) & 0x1f ) + (((_pte).pte >> 9) << 6 ))
-
-#define pgoff_to_pte(off) \
- ((pte_t) { (((off) & 0x1f) << 3) + (((off) >> 6) << 9) + _PAGE_FILE })
+#define pte_to_pgoff(_pte) ((_pte).pte >> 8)
+#define pgoff_to_pte(off) ((pte_t) { ((off) << 8) | _PAGE_FILE })
#endif /* _ASM_PGTABLE_64_H */
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index 702a28fa7a3..d0af2a3b015 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -70,7 +70,15 @@ extern unsigned long zero_page_mask;
#define ZERO_PAGE(vaddr) \
(virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))
-#define __HAVE_ARCH_MULTIPLE_ZERO_PAGE
+#define __HAVE_ARCH_MOVE_PTE
+#define move_pte(pte, prot, old_addr, new_addr) \
+({ \
+ pte_t newpte = (pte); \
+ if (pte_present(pte) && pfn_valid(pte_pfn(pte)) && \
+ pte_page(pte) == ZERO_PAGE(old_addr)) \
+ newpte = mk_pte(ZERO_PAGE(new_addr), (prot)); \
+ newpte; \
+})
extern void paging_init(void);
@@ -82,10 +90,11 @@ extern void paging_init(void);
#define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
#define pmd_page_kernel(pmd) pmd_val(pmd)
-#define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL))
-#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT)
-
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
+
+#define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL))
+#define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT)
+
static inline void set_pte(pte_t *ptep, pte_t pte)
{
ptep->pte_high = pte.pte_high;
@@ -93,27 +102,35 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
ptep->pte_low = pte.pte_low;
//printk("pte_high %x pte_low %x\n", ptep->pte_high, ptep->pte_low);
- if (pte_val(pte) & _PAGE_GLOBAL) {
+ if (pte.pte_low & _PAGE_GLOBAL) {
pte_t *buddy = ptep_buddy(ptep);
/*
* Make sure the buddy is global too (if it's !none,
* it better already be global)
*/
- if (pte_none(*buddy))
- buddy->pte_low |= _PAGE_GLOBAL;
+ if (pte_none(*buddy)) {
+ buddy->pte_low |= _PAGE_GLOBAL;
+ buddy->pte_high |= _PAGE_GLOBAL;
+ }
}
}
#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
+ pte_t null = __pte(0);
+
/* Preserve global status for the pair */
- if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
- set_pte_at(mm, addr, ptep, __pte(_PAGE_GLOBAL));
- else
- set_pte_at(mm, addr, ptep, __pte(0));
+ if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL)
+ null.pte_low = null.pte_high = _PAGE_GLOBAL;
+
+ set_pte_at(mm, addr, ptep, null);
}
#else
+
+#define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL))
+#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT)
+
/*
* Certain architectures need to do special things when pte's
* within a page table are directly modified. Thus, the following
@@ -174,75 +191,76 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
*/
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; }
-static inline int pte_file(pte_t pte) { return (pte).pte_low & _PAGE_FILE; }
+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; }
+static inline int pte_file(pte_t pte) { return pte.pte_low & _PAGE_FILE; }
+
static inline pte_t pte_wrprotect(pte_t pte)
{
- (pte).pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
- (pte).pte_high &= ~_PAGE_SILENT_WRITE;
+ pte.pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+ pte.pte_high &= ~_PAGE_SILENT_WRITE;
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;
+ 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);
- (pte).pte_high &= ~_PAGE_SILENT_WRITE;
+ pte.pte_low &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
+ pte.pte_high &= ~_PAGE_SILENT_WRITE;
return pte;
}
static inline pte_t pte_mkold(pte_t pte)
{
- (pte).pte_low &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
- (pte).pte_high &= ~_PAGE_SILENT_READ;
+ pte.pte_low &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ);
+ pte.pte_high &= ~_PAGE_SILENT_READ;
return pte;
}
static inline pte_t pte_mkwrite(pte_t pte)
{
- (pte).pte_low |= _PAGE_WRITE;
- if ((pte).pte_low & _PAGE_MODIFIED) {
- (pte).pte_low |= _PAGE_SILENT_WRITE;
- (pte).pte_high |= _PAGE_SILENT_WRITE;
+ pte.pte_low |= _PAGE_WRITE;
+ if (pte.pte_low & _PAGE_MODIFIED) {
+ pte.pte_low |= _PAGE_SILENT_WRITE;
+ pte.pte_high |= _PAGE_SILENT_WRITE;
}
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;
+ 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;
- if ((pte).pte_low & _PAGE_WRITE) {
- (pte).pte_low |= _PAGE_SILENT_WRITE;
- (pte).pte_high |= _PAGE_SILENT_WRITE;
+ pte.pte_low |= _PAGE_MODIFIED;
+ if (pte.pte_low & _PAGE_WRITE) {
+ pte.pte_low |= _PAGE_SILENT_WRITE;
+ pte.pte_high |= _PAGE_SILENT_WRITE;
}
return pte;
}
static inline pte_t pte_mkyoung(pte_t pte)
{
- (pte).pte_low |= _PAGE_ACCESSED;
- if ((pte).pte_low & _PAGE_READ)
- (pte).pte_low |= _PAGE_SILENT_READ;
- (pte).pte_high |= _PAGE_SILENT_READ;
+ pte.pte_low |= _PAGE_ACCESSED;
+ if (pte.pte_low & _PAGE_READ)
+ pte.pte_low |= _PAGE_SILENT_READ;
+ pte.pte_high |= _PAGE_SILENT_READ;
return pte;
}
#else
@@ -335,8 +353,9 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot)
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
- pte.pte_low &= _PAGE_CHG_MASK;
- pte.pte_low |= pgprot_val(newprot);
+ pte.pte_low &= _PAGE_CHG_MASK;
+ pte.pte_high &= ~0x3f;
+ pte.pte_low |= pgprot_val(newprot);
pte.pte_high |= pgprot_val(newprot) & 0x3f;
return pte;
}
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index 39d2bd50fec..0fb75f0762e 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -12,6 +12,7 @@
#define _ASM_PROCESSOR_H
#include <linux/config.h>
+#include <linux/cpumask.h>
#include <linux/threads.h>
#include <asm/cachectl.h>
@@ -107,6 +108,10 @@ struct mips_dsp_state {
#define INIT_DSP {{0,},}
+#define INIT_CPUMASK { \
+ {0,} \
+}
+
typedef struct {
unsigned long seg;
} mm_segment_t;
@@ -129,6 +134,12 @@ struct thread_struct {
/* Saved fpu/fpu emulator stuff. */
union mips_fpu_union fpu;
+#ifdef CONFIG_MIPS_MT_FPAFF
+ /* Emulated instruction count */
+ unsigned long emulated_fp;
+ /* Saved per-thread scheduler affinity mask */
+ cpumask_t user_cpus_allowed;
+#endif /* CONFIG_MIPS_MT_FPAFF */
/* Saved state of the DSP ASE, if available. */
struct mips_dsp_state dsp;
@@ -142,6 +153,7 @@ struct thread_struct {
#define MF_LOGADE 2 /* Log address errors to syslog */
#define MF_32BIT_REGS 4 /* also implies 16/32 fprs */
#define MF_32BIT_ADDR 8 /* 32-bit address space (o32/n32) */
+#define MF_FPUBOUND 0x10 /* thread bound to FPU-full CPU set */
unsigned long mflags;
unsigned long irix_trampoline; /* Wheee... */
unsigned long irix_oldctx;
@@ -153,6 +165,12 @@ struct thread_struct {
#define MF_N32 MF_32BIT_ADDR
#define MF_N64 0
+#ifdef CONFIG_MIPS_MT_FPAFF
+#define FPAFF_INIT 0, INIT_CPUMASK,
+#else
+#define FPAFF_INIT
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
#define INIT_THREAD { \
/* \
* saved main processor registers \
@@ -168,6 +186,10 @@ struct thread_struct {
*/ \
INIT_FPU, \
/* \
+ * fpu affinity state (null if not FPAFF) \
+ */ \
+ FPAFF_INIT \
+ /* \
* saved dsp/dsp emulator stuff \
*/ \
INIT_DSP, \
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 95c5839ac46..fa9d8713c12 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -45,6 +45,10 @@ struct pt_regs {
unsigned long cp0_badvaddr;
unsigned long cp0_cause;
unsigned long cp0_epc;
+#ifdef CONFIG_MIPS_MT_SMTC
+ unsigned long cp0_tcstatus;
+ unsigned long smtc_pad;
+#endif /* CONFIG_MIPS_MT_SMTC */
};
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h
index 90c37470097..3c8e3c8d1a9 100644
--- a/include/asm-mips/r4kcache.h
+++ b/include/asm-mips/r4kcache.h
@@ -15,6 +15,7 @@
#include <asm/asm.h>
#include <asm/cacheops.h>
#include <asm/cpu-features.h>
+#include <asm/mipsmtregs.h>
/*
* This macro return a properly sign-extended address suitable as base address
@@ -37,16 +38,120 @@
" cache %0, %1 \n" \
" .set pop \n" \
: \
- : "i" (op), "m" (*(unsigned char *)(addr)))
+ : "i" (op), "R" (*(unsigned char *)(addr)))
+
+#ifdef CONFIG_MIPS_MT
+/*
+ * Temporary hacks for SMTC debug. Optionally force single-threaded
+ * execution during I-cache flushes.
+ */
+
+#define PROTECT_CACHE_FLUSHES 1
+
+#ifdef PROTECT_CACHE_FLUSHES
+
+extern int mt_protiflush;
+extern int mt_protdflush;
+extern void mt_cflush_lockdown(void);
+extern void mt_cflush_release(void);
+
+#define BEGIN_MT_IPROT \
+ unsigned long flags = 0; \
+ unsigned long mtflags = 0; \
+ if(mt_protiflush) { \
+ local_irq_save(flags); \
+ ehb(); \
+ mtflags = dvpe(); \
+ mt_cflush_lockdown(); \
+ }
+
+#define END_MT_IPROT \
+ if(mt_protiflush) { \
+ mt_cflush_release(); \
+ evpe(mtflags); \
+ local_irq_restore(flags); \
+ }
+
+#define BEGIN_MT_DPROT \
+ unsigned long flags = 0; \
+ unsigned long mtflags = 0; \
+ if(mt_protdflush) { \
+ local_irq_save(flags); \
+ ehb(); \
+ mtflags = dvpe(); \
+ mt_cflush_lockdown(); \
+ }
+
+#define END_MT_DPROT \
+ if(mt_protdflush) { \
+ mt_cflush_release(); \
+ evpe(mtflags); \
+ local_irq_restore(flags); \
+ }
+
+#else
+
+#define BEGIN_MT_IPROT
+#define BEGIN_MT_DPROT
+#define END_MT_IPROT
+#define END_MT_DPROT
+
+#endif /* PROTECT_CACHE_FLUSHES */
+
+#define __iflush_prologue \
+ unsigned long redundance; \
+ extern int mt_n_iflushes; \
+ BEGIN_MT_IPROT \
+ for (redundance = 0; redundance < mt_n_iflushes; redundance++) {
+
+#define __iflush_epilogue \
+ END_MT_IPROT \
+ }
+
+#define __dflush_prologue \
+ unsigned long redundance; \
+ extern int mt_n_dflushes; \
+ BEGIN_MT_DPROT \
+ for (redundance = 0; redundance < mt_n_dflushes; redundance++) {
+
+#define __dflush_epilogue \
+ END_MT_DPROT \
+ }
+
+#define __inv_dflush_prologue __dflush_prologue
+#define __inv_dflush_epilogue __dflush_epilogue
+#define __sflush_prologue {
+#define __sflush_epilogue }
+#define __inv_sflush_prologue __sflush_prologue
+#define __inv_sflush_epilogue __sflush_epilogue
+
+#else /* CONFIG_MIPS_MT */
+
+#define __iflush_prologue {
+#define __iflush_epilogue }
+#define __dflush_prologue {
+#define __dflush_epilogue }
+#define __inv_dflush_prologue {
+#define __inv_dflush_epilogue }
+#define __sflush_prologue {
+#define __sflush_epilogue }
+#define __inv_sflush_prologue {
+#define __inv_sflush_epilogue }
+
+#endif /* CONFIG_MIPS_MT */
static inline void flush_icache_line_indexed(unsigned long addr)
{
+ __iflush_prologue
cache_op(Index_Invalidate_I, addr);
+ __iflush_epilogue
}
static inline void flush_dcache_line_indexed(unsigned long addr)
{
+ __dflush_prologue
cache_op(Index_Writeback_Inv_D, addr);
+ __dflush_epilogue
}
static inline void flush_scache_line_indexed(unsigned long addr)
@@ -56,17 +161,23 @@ static inline void flush_scache_line_indexed(unsigned long addr)
static inline void flush_icache_line(unsigned long addr)
{
+ __iflush_prologue
cache_op(Hit_Invalidate_I, addr);
+ __iflush_epilogue
}
static inline void flush_dcache_line(unsigned long addr)
{
+ __dflush_prologue
cache_op(Hit_Writeback_Inv_D, addr);
+ __dflush_epilogue
}
static inline void invalidate_dcache_line(unsigned long addr)
{
+ __dflush_prologue
cache_op(Hit_Invalidate_D, addr);
+ __dflush_epilogue
}
static inline void invalidate_scache_line(unsigned long addr)
@@ -239,9 +350,13 @@ static inline void blast_##pfx##cache##lsize(void) \
current_cpu_data.desc.waybit; \
unsigned long ws, addr; \
\
+ __##pfx##flush_prologue \
+ \
for (ws = 0; ws < ws_end; ws += ws_inc) \
for (addr = start; addr < end; addr += lsize * 32) \
cache##lsize##_unroll32(addr|ws,indexop); \
+ \
+ __##pfx##flush_epilogue \
} \
\
static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
@@ -249,10 +364,14 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
unsigned long start = page; \
unsigned long end = page + PAGE_SIZE; \
\
+ __##pfx##flush_prologue \
+ \
do { \
cache##lsize##_unroll32(start,hitop); \
start += lsize * 32; \
} while (start < end); \
+ \
+ __##pfx##flush_epilogue \
} \
\
static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
@@ -265,9 +384,13 @@ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page)
current_cpu_data.desc.waybit; \
unsigned long ws, addr; \
\
+ __##pfx##flush_prologue \
+ \
for (ws = 0; ws < ws_end; ws += ws_inc) \
for (addr = start; addr < end; addr += lsize * 32) \
cache##lsize##_unroll32(addr|ws,indexop); \
+ \
+ __##pfx##flush_epilogue \
}
__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
@@ -288,12 +411,17 @@ static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
unsigned long lsize = cpu_##desc##_line_size(); \
unsigned long addr = start & ~(lsize - 1); \
unsigned long aend = (end - 1) & ~(lsize - 1); \
+ \
+ __##pfx##flush_prologue \
+ \
while (1) { \
prot##cache_op(hitop, addr); \
if (addr == aend) \
break; \
addr += lsize; \
} \
+ \
+ __##pfx##flush_epilogue \
}
__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
diff --git a/include/asm-mips/rtc.h b/include/asm-mips/rtc.h
index a2abc4572b6..82ad401c7dc 100644
--- a/include/asm-mips/rtc.h
+++ b/include/asm-mips/rtc.h
@@ -32,7 +32,7 @@ static inline unsigned int get_rtc_time(struct rtc_time *time)
{
unsigned long nowtime;
- nowtime = rtc_get_time();
+ nowtime = rtc_mips_get_time();
to_tm(nowtime, time);
time->tm_year -= 1900;
@@ -47,7 +47,7 @@ static inline int set_rtc_time(struct rtc_time *time)
nowtime = mktime(time->tm_year+1900, time->tm_mon+1,
time->tm_mday, time->tm_hour, time->tm_min,
time->tm_sec);
- ret = rtc_set_time(nowtime);
+ ret = rtc_mips_set_time(nowtime);
return ret;
}
diff --git a/include/asm-mips/rtlx.h b/include/asm-mips/rtlx.h
index 1298c3fdf6c..76cd51c6be3 100644
--- a/include/asm-mips/rtlx.h
+++ b/include/asm-mips/rtlx.h
@@ -3,32 +3,46 @@
*
*/
-#ifndef _RTLX_H
-#define _RTLX_H_
+#ifndef __ASM_RTLX_H
+#define __ASM_RTLX_H_
#define LX_NODE_BASE 10
#define MIPSCPU_INT_BASE 16
#define MIPS_CPU_RTLX_IRQ 0
-#define RTLX_VERSION 1
+#define RTLX_VERSION 2
#define RTLX_xID 0x12345600
#define RTLX_ID (RTLX_xID | RTLX_VERSION)
#define RTLX_CHANNELS 8
-#define RTLX_BUFFER_SIZE 1024
+#define RTLX_CHANNEL_STDIO 0
+#define RTLX_CHANNEL_DBG 1
+#define RTLX_CHANNEL_SYSIO 2
-/*
- * lx_state bits
- */
-#define RTLX_STATE_OPENED 1UL
+extern int rtlx_open(int index, int can_sleep);
+extern int rtlx_release(int index);
+extern ssize_t rtlx_read(int index, void *buff, size_t count, int user);
+extern ssize_t rtlx_write(int index, void *buffer, size_t count, int user);
+extern unsigned int rtlx_read_poll(int index, int can_sleep);
+extern unsigned int rtlx_write_poll(int index);
+
+enum rtlx_state {
+ RTLX_STATE_UNUSED,
+ RTLX_STATE_INITIALISED,
+ RTLX_STATE_REMOTE_READY,
+ RTLX_STATE_OPENED
+};
+
+#define RTLX_BUFFER_SIZE 1024
/* each channel supports read and write.
linux (vpe0) reads lx_buffer and writes rt_buffer
SP (vpe1) reads rt_buffer and writes lx_buffer
*/
struct rtlx_channel {
- unsigned long lx_state;
+ enum rtlx_state rt_state;
+ enum rtlx_state lx_state;
int buffer_size;
@@ -38,15 +52,13 @@ struct rtlx_channel {
int lx_write, lx_read;
char *lx_buffer;
-
- void *queues;
-
};
struct rtlx_info {
unsigned long id;
+ enum rtlx_state state;
struct rtlx_channel channel[RTLX_CHANNELS];
};
-#endif /* _RTLX_H_ */
+#endif /* __ASM_RTLX_H_ */
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h
index e796d75f027..7196ceb0e94 100644
--- a/include/asm-mips/serial.h
+++ b/include/asm-mips/serial.h
@@ -77,15 +77,15 @@
#include <asm/it8712.h>
#define ITE_SERIAL_PORT_DEFNS \
{ .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_UART_BASE), \
- .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+ .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
{ .baud_base = (24000000/(16*13)), .port = (IT8172_PCI_IO_BASE + IT8712_UART1_PORT), \
- .irq = IT8172_SERIRQ_4, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+ .irq = IT8172_SERIRQ_4, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
/* Smart Card Reader 0 */ \
{ .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_SCR0_BASE), \
- .irq = IT8172_SCR0_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+ .irq = IT8172_SCR0_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
/* Smart Card Reader 1 */ \
{ .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_SCR1_BASE), \
- .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 },
+ .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 },
#else
#define ITE_SERIAL_PORT_DEFNS
#endif
@@ -95,96 +95,14 @@
#include <asm/it8172/it8172_int.h>
#define IVR_SERIAL_PORT_DEFNS \
{ .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_UART_BASE), \
- .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+ .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
/* Smart Card Reader 1 */ \
{ .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_SCR1_BASE), \
- .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 },
+ .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 },
#else
#define IVR_SERIAL_PORT_DEFNS
#endif
-#ifdef CONFIG_SERIAL_AU1X00
-#include <asm/mach-au1x00/au1000.h>
-#ifdef CONFIG_SOC_AU1000
-#define AU1000_SERIAL_PORT_DEFNS \
- { .baud_base = 0, .port = UART0_ADDR, \
- .iomem_base = (unsigned char *)UART0_ADDR, \
- .irq = AU1000_UART0_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART1_ADDR, \
- .iomem_base = (unsigned char *)UART1_ADDR, \
- .irq = AU1000_UART1_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART2_ADDR, \
- .iomem_base = (unsigned char *)UART2_ADDR, \
- .irq = AU1000_UART2_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART3_ADDR, \
- .iomem_base = (unsigned char *)UART3_ADDR, \
- .irq = AU1000_UART3_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 },
-#endif
-
-#ifdef CONFIG_SOC_AU1500
-#define AU1000_SERIAL_PORT_DEFNS \
- { .baud_base = 0, .port = UART0_ADDR, \
- .iomem_base = (unsigned char *)UART0_ADDR, \
- .irq = AU1500_UART0_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART3_ADDR, \
- .iomem_base = (unsigned char *)UART3_ADDR, \
- .irq = AU1500_UART3_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 },
-#endif
-
-#ifdef CONFIG_SOC_AU1100
-#define AU1000_SERIAL_PORT_DEFNS \
- { .baud_base = 0, .port = UART0_ADDR, \
- .iomem_base = (unsigned char *)UART0_ADDR, \
- .irq = AU1100_UART0_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART1_ADDR, \
- .iomem_base = (unsigned char *)UART1_ADDR, \
- .irq = AU1100_UART1_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART3_ADDR, \
- .iomem_base = (unsigned char *)UART3_ADDR, \
- .irq = AU1100_UART3_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 },
-#endif
-
-#ifdef CONFIG_SOC_AU1550
-#define AU1000_SERIAL_PORT_DEFNS \
- { .baud_base = 0, .port = UART0_ADDR, \
- .iomem_base = (unsigned char *)UART0_ADDR, \
- .irq = AU1550_UART0_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART1_ADDR, \
- .iomem_base = (unsigned char *)UART1_ADDR, \
- .irq = AU1550_UART1_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART3_ADDR, \
- .iomem_base = (unsigned char *)UART3_ADDR, \
- .irq = AU1550_UART3_INT, .flags = STD_COM_FLAGS,\
- .iomem_reg_shift = 2 },
-#endif
-
-#ifdef CONFIG_SOC_AU1200
-#define AU1000_SERIAL_PORT_DEFNS \
- { .baud_base = 0, .port = UART0_ADDR, \
- .iomem_base = (unsigned char *)UART0_ADDR, \
- .irq = AU1200_UART0_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART1_ADDR, \
- .iomem_base = (unsigned char *)UART1_ADDR, \
- .irq = AU1200_UART1_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 },
-#endif
-
-#else
-#define AU1000_SERIAL_PORT_DEFNS
-#endif
-
#ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT
#define STD_SERIAL_PORT_DEFNS \
/* UART CLK PORT IRQ FLAGS */ \
@@ -331,7 +249,6 @@
MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS \
MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS \
MOMENCO_OCELOT_SERIAL_PORT_DEFNS \
- MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS \
- AU1000_SERIAL_PORT_DEFNS
+ MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS
#endif /* _ASM_SERIAL_H */
diff --git a/include/asm-mips/sigcontext.h b/include/asm-mips/sigcontext.h
index 8edabb0be23..cefa657dd04 100644
--- a/include/asm-mips/sigcontext.h
+++ b/include/asm-mips/sigcontext.h
@@ -55,8 +55,14 @@ struct sigcontext {
struct sigcontext {
unsigned long sc_regs[32];
unsigned long sc_fpregs[32];
- unsigned long sc_hi[4];
- unsigned long sc_lo[4];
+ unsigned long sc_mdhi;
+ unsigned long sc_hi1;
+ unsigned long sc_hi2;
+ unsigned long sc_hi3;
+ unsigned long sc_mdlo;
+ unsigned long sc_lo1;
+ unsigned long sc_lo2;
+ unsigned long sc_lo3;
unsigned long sc_pc;
unsigned int sc_fpc_csr;
unsigned int sc_used_math;
diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h
index 75c6fe7c212..e14e4b69de2 100644
--- a/include/asm-mips/smp.h
+++ b/include/asm-mips/smp.h
@@ -48,7 +48,6 @@ extern struct call_data_struct *call_data;
#define SMP_CALL_FUNCTION 0x2
extern cpumask_t phys_cpu_present_map;
-extern cpumask_t cpu_online_map;
#define cpu_possible_map phys_cpu_present_map
extern cpumask_t cpu_callout_map;
@@ -86,9 +85,9 @@ extern void prom_init_secondary(void);
extern void plat_smp_setup(void);
/*
- * Called after init_IRQ but before __cpu_up.
+ * Called in smp_prepare_cpus.
*/
-extern void prom_prepare_cpus(unsigned int max_cpus);
+extern void plat_prepare_cpus(unsigned int max_cpus);
/*
* Last chance for the board code to finish SMP initialization before
diff --git a/include/asm-mips/smtc.h b/include/asm-mips/smtc.h
new file mode 100644
index 00000000000..e1941d1b872
--- /dev/null
+++ b/include/asm-mips/smtc.h
@@ -0,0 +1,55 @@
+#ifndef _ASM_SMTC_MT_H
+#define _ASM_SMTC_MT_H
+
+/*
+ * Definitions for SMTC multitasking on MIPS MT cores
+ */
+
+#include <asm/mips_mt.h>
+
+/*
+ * System-wide SMTC status information
+ */
+
+extern unsigned int smtc_status;
+
+#define SMTC_TLB_SHARED 0x00000001
+#define SMTC_MTC_ACTIVE 0x00000002
+
+/*
+ * TLB/ASID Management information
+ */
+
+#define MAX_SMTC_TLBS 2
+#define MAX_SMTC_ASIDS 256
+#if NR_CPUS <= 8
+typedef char asiduse;
+#else
+#if NR_CPUS <= 16
+typedef short asiduse;
+#else
+typedef long asiduse;
+#endif
+#endif
+
+extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
+
+void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu);
+
+void smtc_flush_tlb_asid(unsigned long asid);
+extern int mipsmt_build_cpu_map(int startslot);
+extern void mipsmt_prepare_cpus(void);
+extern void smtc_smp_finish(void);
+extern void smtc_boot_secondary(int cpu, struct task_struct *t);
+
+/*
+ * Sharing the TLB between multiple VPEs means that the
+ * "random" index selection function is not allowed to
+ * select the current value of the Index register. To
+ * avoid additional TLB pressure, the Index registers
+ * are "parked" with an non-Valid value.
+ */
+
+#define PARKED_INDEX ((unsigned int)0x80000000)
+
+#endif /* _ASM_SMTC_MT_H */
diff --git a/include/asm-mips/smtc_ipi.h b/include/asm-mips/smtc_ipi.h
new file mode 100644
index 00000000000..f22c3e2f993
--- /dev/null
+++ b/include/asm-mips/smtc_ipi.h
@@ -0,0 +1,118 @@
+/*
+ * Definitions used in MIPS MT SMTC "Interprocessor Interrupt" code.
+ */
+#ifndef __ASM_SMTC_IPI_H
+#define __ASM_SMTC_IPI_H
+
+//#define SMTC_IPI_DEBUG
+
+#ifdef SMTC_IPI_DEBUG
+#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
+#endif /* SMTC_IPI_DEBUG */
+
+/*
+ * An IPI "message"
+ */
+
+struct smtc_ipi {
+ struct smtc_ipi *flink;
+ int type;
+ void *arg;
+ int dest;
+#ifdef SMTC_IPI_DEBUG
+ int sender;
+ long stamp;
+#endif /* SMTC_IPI_DEBUG */
+};
+
+/*
+ * Defined IPI Types
+ */
+
+#define LINUX_SMP_IPI 1
+#define SMTC_CLOCK_TICK 2
+
+/*
+ * A queue of IPI messages
+ */
+
+struct smtc_ipi_q {
+ struct smtc_ipi *head;
+ spinlock_t lock;
+ struct smtc_ipi *tail;
+ int depth;
+};
+
+extern struct smtc_ipi_q IPIQ[NR_CPUS];
+extern struct smtc_ipi_q freeIPIq;
+
+static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
+{
+ long flags;
+
+ spin_lock_irqsave(&q->lock, flags);
+ if (q->head == NULL)
+ q->head = q->tail = p;
+ else
+ q->tail->flink = p;
+ p->flink = NULL;
+ q->tail = p;
+ q->depth++;
+#ifdef SMTC_IPI_DEBUG
+ p->sender = read_c0_tcbind();
+ p->stamp = read_c0_count();
+#endif /* SMTC_IPI_DEBUG */
+ spin_unlock_irqrestore(&q->lock, flags);
+}
+
+static inline struct smtc_ipi *smtc_ipi_dq(struct smtc_ipi_q *q)
+{
+ struct smtc_ipi *p;
+ long flags;
+
+ spin_lock_irqsave(&q->lock, flags);
+ if (q->head == NULL)
+ p = NULL;
+ else {
+ p = q->head;
+ q->head = q->head->flink;
+ q->depth--;
+ /* Arguably unnecessary, but leaves queue cleaner */
+ if (q->head == NULL)
+ q->tail = NULL;
+ }
+ spin_unlock_irqrestore(&q->lock, flags);
+ return p;
+}
+
+static inline void smtc_ipi_req(struct smtc_ipi_q *q, struct smtc_ipi *p)
+{
+ long flags;
+
+ spin_lock_irqsave(&q->lock, flags);
+ if (q->head == NULL) {
+ q->head = q->tail = p;
+ p->flink = NULL;
+ } else {
+ p->flink = q->head;
+ q->head = p;
+ }
+ q->depth++;
+ spin_unlock_irqrestore(&q->lock, flags);
+}
+
+static inline int smtc_ipi_qdepth(struct smtc_ipi_q *q)
+{
+ long flags;
+ int retval;
+
+ spin_lock_irqsave(&q->lock, flags);
+ retval = q->depth;
+ spin_unlock_irqrestore(&q->lock, flags);
+ return retval;
+}
+
+extern void smtc_send_ipi(int cpu, int type, unsigned int action);
+
+#endif /* __ASM_SMTC_IPI_H */
diff --git a/include/asm-mips/smtc_proc.h b/include/asm-mips/smtc_proc.h
new file mode 100644
index 00000000000..25da651f1f5
--- /dev/null
+++ b/include/asm-mips/smtc_proc.h
@@ -0,0 +1,23 @@
+/*
+ * Definitions for SMTC /proc entries
+ * Copyright(C) 2005 MIPS Technologies Inc.
+ */
+#ifndef __ASM_SMTC_PROC_H
+#define __ASM_SMTC_PROC_H
+
+/*
+ * per-"CPU" statistics
+ */
+
+struct smtc_cpu_proc {
+ unsigned long timerints;
+ unsigned long selfipis;
+};
+
+extern struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS];
+
+/* Count of number of recoveries of "stolen" FPU access rights on 34K */
+
+extern atomic_t smtc_fpu_recoveries;
+
+#endif /* __ASM_SMTC_PROC_H */
diff --git a/include/asm-mips/sparsemem.h b/include/asm-mips/sparsemem.h
new file mode 100644
index 00000000000..795ac6c2320
--- /dev/null
+++ b/include/asm-mips/sparsemem.h
@@ -0,0 +1,14 @@
+#ifndef _MIPS_SPARSEMEM_H
+#define _MIPS_SPARSEMEM_H
+#ifdef CONFIG_SPARSEMEM
+
+/*
+ * SECTION_SIZE_BITS 2^N: how big each section will be
+ * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space
+ */
+#define SECTION_SIZE_BITS 28
+#define MAX_PHYSMEM_BITS 35
+
+#endif /* CONFIG_SPARSEMEM */
+#endif /* _MIPS_SPARSEMEM_H */
+
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 2acf3e844f0..c4856a87496 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -14,9 +14,14 @@
#include <linux/threads.h>
#include <asm/asm.h>
+#include <asm/asmmacro.h>
#include <asm/mipsregs.h>
#include <asm/asm-offsets.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
.macro SAVE_AT
.set push
.set noat
@@ -57,13 +62,30 @@
#ifdef CONFIG_SMP
.macro get_saved_sp /* SMP variation */
#ifdef CONFIG_32BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+ .set mips32
+ mfc0 k0, CP0_TCBIND;
+ .set mips0
+ lui k1, %hi(kernelsp)
+ srl k0, k0, 19
+ /* No need to shift down and up to clear bits 0-1 */
+#else
mfc0 k0, CP0_CONTEXT
lui k1, %hi(kernelsp)
srl k0, k0, 23
+#endif
addu k1, k0
LONG_L k1, %lo(kernelsp)(k1)
#endif
#ifdef CONFIG_64BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+ .set mips64
+ mfc0 k0, CP0_TCBIND;
+ .set mips0
+ lui k0, %highest(kernelsp)
+ dsrl k1, 19
+ /* No need to shift down and up to clear bits 0-2 */
+#else
MFC0 k1, CP0_CONTEXT
lui k0, %highest(kernelsp)
dsrl k1, 23
@@ -71,20 +93,31 @@
dsll k0, k0, 16
daddiu k0, %hi(kernelsp)
dsll k0, k0, 16
+#endif /* CONFIG_MIPS_MT_SMTC */
daddu k1, k1, k0
LONG_L k1, %lo(kernelsp)(k1)
-#endif
+#endif /* CONFIG_64BIT */
.endm
.macro set_saved_sp stackp temp temp2
#ifdef CONFIG_32BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+ mfc0 \temp, CP0_TCBIND
+ srl \temp, 19
+#else
mfc0 \temp, CP0_CONTEXT
srl \temp, 23
#endif
+#endif
#ifdef CONFIG_64BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+ mfc0 \temp, CP0_TCBIND
+ dsrl \temp, 19
+#else
MFC0 \temp, CP0_CONTEXT
dsrl \temp, 23
#endif
+#endif
LONG_S \stackp, kernelsp(\temp)
.endm
#else
@@ -122,10 +155,25 @@
PTR_SUBU sp, k1, PT_SIZE
LONG_S k0, PT_R29(sp)
LONG_S $3, PT_R3(sp)
+ /*
+ * You might think that you don't need to save $0,
+ * but the FPU emulator and gdb remote debug stub
+ * need it to operate correctly
+ */
LONG_S $0, PT_R0(sp)
mfc0 v1, CP0_STATUS
LONG_S $2, PT_R2(sp)
LONG_S v1, PT_STATUS(sp)
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * Ideally, these instructions would be shuffled in
+ * to cover the pipeline delay.
+ */
+ .set mips32
+ mfc0 v1, CP0_TCSTATUS
+ .set mips0
+ LONG_S v1, PT_TCSTATUS(sp)
+#endif /* CONFIG_MIPS_MT_SMTC */
LONG_S $4, PT_R4(sp)
mfc0 v1, CP0_CAUSE
LONG_S $5, PT_R5(sp)
@@ -234,14 +282,36 @@
.endm
#else
+/*
+ * For SMTC kernel, global IE should be left set, and interrupts
+ * controlled exclusively via IXMT.
+ */
+#ifdef CONFIG_MIPS_MT_SMTC
+#define STATMASK 0x1e
+#else
+#define STATMASK 0x1f
+#endif
.macro RESTORE_SOME
.set push
.set reorder
.set noat
+#ifdef CONFIG_MIPS_MT_SMTC
+ .set mips32r2
+ /*
+ * This may not really be necessary if ints are already
+ * inhibited here.
+ */
+ mfc0 v0, CP0_TCSTATUS
+ ori v0, TCSTATUS_IXMT
+ mtc0 v0, CP0_TCSTATUS
+ ehb
+ DMT 5 # dmt a1
+ jal mips_ihb
+#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 a0, CP0_STATUS
- ori a0, 0x1f
- xori a0, 0x1f
+ ori a0, STATMASK
+ xori a0, STATMASK
mtc0 a0, CP0_STATUS
li v1, 0xff00
and a0, v1
@@ -250,6 +320,26 @@
and v0, v1
or v0, a0
mtc0 v0, CP0_STATUS
+#ifdef CONFIG_MIPS_MT_SMTC
+/*
+ * Only after EXL/ERL have been restored to status can we
+ * restore TCStatus.IXMT.
+ */
+ LONG_L v1, PT_TCSTATUS(sp)
+ ehb
+ mfc0 v0, CP0_TCSTATUS
+ andi v1, TCSTATUS_IXMT
+ /* We know that TCStatua.IXMT should be set from above */
+ xori v0, v0, TCSTATUS_IXMT
+ or v0, v0, v1
+ mtc0 v0, CP0_TCSTATUS
+ ehb
+ andi a1, a1, VPECONTROL_TE
+ beqz a1, 1f
+ emt
+1:
+ .set mips0
+#endif /* CONFIG_MIPS_MT_SMTC */
LONG_L v1, PT_EPC(sp)
MTC0 v1, CP0_EPC
LONG_L $31, PT_R31(sp)
@@ -302,11 +392,33 @@
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro CLI
+#if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | 0x1f
or t0, t1
xori t0, 0x1f
mtc0 t0, CP0_STATUS
+#else /* CONFIG_MIPS_MT_SMTC */
+ /*
+ * For SMTC, we need to set privilege
+ * and disable interrupts only for the
+ * current TC, using the TCStatus register.
+ */
+ mfc0 t0,CP0_TCSTATUS
+ /* Fortunately CU 0 is in the same place in both registers */
+ /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
+ li t1, ST0_CU0 | 0x08001c00
+ or t0,t1
+ /* Clear TKSU, leave IXMT */
+ xori t0, 0x00001800
+ mtc0 t0, CP0_TCSTATUS
+ ehb
+ /* We need to leave the global IE bit set, but clear EXL...*/
+ mfc0 t0, CP0_STATUS
+ ori t0, ST0_EXL | ST0_ERL
+ xori t0, ST0_EXL | ST0_ERL
+ mtc0 t0, CP0_STATUS
+#endif /* CONFIG_MIPS_MT_SMTC */
irq_disable_hazard
.endm
@@ -315,11 +427,35 @@
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro STI
+#if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | 0x1f
or t0, t1
xori t0, 0x1e
mtc0 t0, CP0_STATUS
+#else /* CONFIG_MIPS_MT_SMTC */
+ /*
+ * For SMTC, we need to set privilege
+ * and enable interrupts only for the
+ * current TC, using the TCStatus register.
+ */
+ ehb
+ mfc0 t0,CP0_TCSTATUS
+ /* Fortunately CU 0 is in the same place in both registers */
+ /* Set TCU0, TKSU (for later inversion) and IXMT */
+ li t1, ST0_CU0 | 0x08001c00
+ or t0,t1
+ /* Clear TKSU *and* IXMT */
+ xori t0, 0x00001c00
+ mtc0 t0, CP0_TCSTATUS
+ ehb
+ /* We need to leave the global IE bit set, but clear EXL...*/
+ mfc0 t0, CP0_STATUS
+ ori t0, ST0_EXL
+ xori t0, ST0_EXL
+ mtc0 t0, CP0_STATUS
+ /* irq_enable_hazard below should expand to EHB for 24K/34K cpus */
+#endif /* CONFIG_MIPS_MT_SMTC */
irq_enable_hazard
.endm
@@ -328,11 +464,56 @@
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro KMODE
+#ifdef CONFIG_MIPS_MT_SMTC
+ /*
+ * This gets baroque in SMTC. We want to
+ * protect the non-atomic clearing of EXL
+ * with DMT/EMT, but we don't want to take
+ * an interrupt while DMT is still in effect.
+ */
+
+ /* KMODE gets invoked from both reorder and noreorder code */
+ .set push
+ .set mips32r2
+ .set noreorder
+ mfc0 v0, CP0_TCSTATUS
+ andi v1, v0, TCSTATUS_IXMT
+ ori v0, TCSTATUS_IXMT
+ mtc0 v0, CP0_TCSTATUS
+ ehb
+ DMT 2 # dmt v0
+ /*
+ * We don't know a priori if ra is "live"
+ */
+ move t0, ra
+ jal mips_ihb
+ nop /* delay slot */
+ move ra, t0
+#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | 0x1e
or t0, t1
xori t0, 0x1e
mtc0 t0, CP0_STATUS
+#ifdef CONFIG_MIPS_MT_SMTC
+ ehb
+ andi v0, v0, VPECONTROL_TE
+ beqz v0, 2f
+ nop /* delay slot */
+ emt
+2:
+ mfc0 v0, CP0_TCSTATUS
+ /* Clear IXMT, then OR in previous value */
+ ori v0, TCSTATUS_IXMT
+ xori v0, TCSTATUS_IXMT
+ or v0, v1, v0
+ mtc0 v0, CP0_TCSTATUS
+ /*
+ * irq_disable_hazard below should expand to EHB
+ * on 24K/34K CPUS
+ */
+ .set pop
+#endif /* CONFIG_MIPS_MT_SMTC */
irq_disable_hazard
.endm
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 4097fac5ac3..261f71d16a0 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -155,6 +155,37 @@ extern asmlinkage void *resume(void *last, void *next, void *next_ti);
struct task_struct;
+#ifdef CONFIG_MIPS_MT_FPAFF
+
+/*
+ * Handle the scheduler resume end of FPU affinity management. We do this
+ * inline to try to keep the overhead down. If we have been forced to run on
+ * a "CPU" with an FPU because of a previous high level of FP computation,
+ * but did not actually use the FPU during the most recent time-slice (CU1
+ * isn't set), we undo the restriction on cpus_allowed.
+ *
+ * We're not calling set_cpus_allowed() here, because we have no need to
+ * force prompt migration - we're already switching the current CPU to a
+ * different thread.
+ */
+
+#define switch_to(prev,next,last) \
+do { \
+ if (cpu_has_fpu && \
+ (prev->thread.mflags & MF_FPUBOUND) && \
+ (!(KSTK_STATUS(prev) & ST0_CU1))) { \
+ prev->thread.mflags &= ~MF_FPUBOUND; \
+ prev->cpus_allowed = prev->thread.user_cpus_allowed; \
+ } \
+ if (cpu_has_dsp) \
+ __save_dsp(prev); \
+ next->thread.emulated_fp = 0; \
+ (last) = resume(prev, next, next->thread_info); \
+ if (cpu_has_dsp) \
+ __restore_dsp(current); \
+} while(0)
+
+#else
#define switch_to(prev,next,last) \
do { \
if (cpu_has_dsp) \
@@ -163,6 +194,7 @@ do { \
if (cpu_has_dsp) \
__restore_dsp(current); \
} while(0)
+#endif
/*
* On SMP systems, when the scheduler does migration-cost autodetection,
@@ -440,8 +472,8 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
extern void set_handler (unsigned long offset, void *addr, unsigned long len);
extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len);
extern void *set_vi_handler (int n, void *addr);
-extern void *set_vi_srs_handler (int n, void *addr, int regset);
extern void *set_except_vector(int n, void *addr);
+extern unsigned long ebase;
extern void per_cpu_trap_init(void);
extern NORET_TYPE void die(const char *, struct pt_regs *);
diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h
index 9cc3564cc2c..d897c8bb554 100644
--- a/include/asm-mips/time.h
+++ b/include/asm-mips/time.h
@@ -26,14 +26,14 @@ extern spinlock_t rtc_lock;
/*
* RTC ops. By default, they point to no-RTC functions.
- * rtc_get_time - mktime(year, mon, day, hour, min, sec) in seconds.
- * rtc_set_time - reverse the above translation and set time to RTC.
- * rtc_set_mmss - similar to rtc_set_time, but only min and sec need
+ * rtc_mips_get_time - mktime(year, mon, day, hour, min, sec) in seconds.
+ * rtc_mips_set_time - reverse the above translation and set time to RTC.
+ * rtc_mips_set_mmss - similar to rtc_set_time, but only min and sec need
* to be set. Used by RTC sync-up.
*/
-extern unsigned long (*rtc_get_time)(void);
-extern int (*rtc_set_time)(unsigned long);
-extern int (*rtc_set_mmss)(unsigned long);
+extern unsigned long (*rtc_mips_get_time)(void);
+extern int (*rtc_mips_set_time)(unsigned long);
+extern int (*rtc_mips_set_mmss)(unsigned long);
/*
* Timer interrupt functions.
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index b5c78a4a019..1068fe9a0a5 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -324,16 +324,18 @@
#define __NR_pselect6 (__NR_Linux + 301)
#define __NR_ppoll (__NR_Linux + 302)
#define __NR_unshare (__NR_Linux + 303)
+#define __NR_splice (__NR_Linux + 304)
+#define __NR_sync_file_range (__NR_Linux + 305)
/*
* Offset of the last Linux o32 flavoured syscall
*/
-#define __NR_Linux_syscalls 303
+#define __NR_Linux_syscalls 305
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 303
+#define __NR_O32_Linux_syscalls 305
#if _MIPS_SIM == _MIPS_SIM_ABI64
@@ -604,16 +606,18 @@
#define __NR_pselect6 (__NR_Linux + 260)
#define __NR_ppoll (__NR_Linux + 261)
#define __NR_unshare (__NR_Linux + 262)
+#define __NR_splice (__NR_Linux + 263)
+#define __NR_sync_file_range (__NR_Linux + 264)
/*
* Offset of the last Linux 64-bit flavoured syscall
*/
-#define __NR_Linux_syscalls 262
+#define __NR_Linux_syscalls 264
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 262
+#define __NR_64_Linux_syscalls 264
#if _MIPS_SIM == _MIPS_SIM_NABI32
@@ -888,16 +892,18 @@
#define __NR_pselect6 (__NR_Linux + 264)
#define __NR_ppoll (__NR_Linux + 265)
#define __NR_unshare (__NR_Linux + 266)
+#define __NR_splice (__NR_Linux + 267)
+#define __NR_sync_file_range (__NR_Linux + 268)
/*
* Offset of the last N32 flavoured syscall
*/
-#define __NR_Linux_syscalls 266
+#define __NR_Linux_syscalls 268
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 266
+#define __NR_N32_Linux_syscalls 268
#ifndef __ASSEMBLY__
diff --git a/include/asm-mips/vpe.h b/include/asm-mips/vpe.h
new file mode 100644
index 00000000000..c6e1b961537
--- /dev/null
+++ b/include/asm-mips/vpe.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _ASM_VPE_H
+#define _ASM_VPE_H
+
+struct vpe_notifications {
+ void (*start)(int vpe);
+ void (*stop)(int vpe);
+
+ struct list_head list;
+};
+
+
+extern int vpe_notify(int index, struct vpe_notifications *notify);
+
+extern void *vpe_get_shared(int index);
+extern int vpe_getuid(int index);
+extern int vpe_getgid(int index);
+extern char *vpe_getcwd(int index);
+
+#endif /* _ASM_VPE_H */
diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h
index 4dc7253ff5d..403ea97316c 100644
--- a/include/asm-parisc/atomic.h
+++ b/include/asm-parisc/atomic.h
@@ -210,6 +210,8 @@ static __inline__ int atomic_read(const atomic_t *v)
#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
+#define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0)
+
#define ATOMIC_INIT(i) ((atomic_t) { (i) })
#define smp_mb__before_atomic_dec() smp_mb()
@@ -267,6 +269,7 @@ atomic64_read(const atomic64_t *v)
#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)
#define atomic64_dec_and_test(v) (atomic64_dec_return(v) == 0)
+#define atomic64_sub_and_test(i,v) (atomic64_sub_return((i),(v)) == 0)
#endif /* __LP64__ */
diff --git a/include/asm-parisc/cache.h b/include/asm-parisc/cache.h
index ae50f8e12ee..c831665473c 100644
--- a/include/asm-parisc/cache.h
+++ b/include/asm-parisc/cache.h
@@ -48,7 +48,7 @@ extern void flush_user_icache_range_asm(unsigned long, unsigned long);
extern void flush_kernel_icache_range_asm(unsigned long, unsigned long);
extern void flush_user_dcache_range_asm(unsigned long, unsigned long);
extern void flush_kernel_dcache_range_asm(unsigned long, unsigned long);
-extern void flush_kernel_dcache_page(void *);
+extern void flush_kernel_dcache_page_asm(void *);
extern void flush_kernel_icache_page(void *);
extern void disable_sr_hashing(void); /* turns off space register hashing */
extern void disable_sr_hashing_asm(int); /* low level support for above */
diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
index c53af9ff41b..76b6b7d6046 100644
--- a/include/asm-parisc/cacheflush.h
+++ b/include/asm-parisc/cacheflush.h
@@ -62,7 +62,7 @@ extern void flush_dcache_page(struct page *page);
#define flush_dcache_mmap_unlock(mapping) \
write_unlock_irq(&(mapping)->tree_lock)
-#define flush_icache_page(vma,page) do { flush_kernel_dcache_page(page_address(page)); flush_kernel_icache_page(page_address(page)); } while (0)
+#define flush_icache_page(vma,page) do { flush_kernel_dcache_page(page); flush_kernel_icache_page(page_address(page)); } while (0)
#define flush_icache_range(s,e) do { flush_kernel_dcache_range_asm(s,e); flush_kernel_icache_range_asm(s,e); } while (0)
@@ -184,6 +184,21 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
}
+static inline void
+flush_anon_page(struct page *page, unsigned long vmaddr)
+{
+ if (PageAnon(page))
+ flush_user_dcache_page(vmaddr);
+}
+#define ARCH_HAS_FLUSH_ANON_PAGE
+
+static inline void
+flush_kernel_dcache_page(struct page *page)
+{
+ flush_kernel_dcache_page_asm(page_address(page));
+}
+#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+
#ifdef CONFIG_DEBUG_RODATA
void mark_rodata_ro(void);
#endif
diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
index 38b918feead..289624d8b2d 100644
--- a/include/asm-parisc/compat.h
+++ b/include/asm-parisc/compat.h
@@ -138,6 +138,11 @@ static inline void __user *compat_ptr(compat_uptr_t uptr)
return (void __user *)(unsigned long)uptr;
}
+static inline compat_uptr_t ptr_to_compat(void __user *uptr)
+{
+ return (u32)(unsigned long)uptr;
+}
+
static __inline__ void __user *compat_alloc_user_space(long len)
{
struct pt_regs *regs = &current->thread.regs;
diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h
index be0c7234a6d..244f6b8883f 100644
--- a/include/asm-parisc/io.h
+++ b/include/asm-parisc/io.h
@@ -25,35 +25,11 @@ extern unsigned long parisc_vmerge_max_size;
* eg dev->hpa or 0xfee00000.
*/
-#ifdef CONFIG_DEBUG_IOREMAP
-#ifdef CONFIG_64BIT
-#define NYBBLE_SHIFT 60
-#else
-#define NYBBLE_SHIFT 28
-#endif
-extern void gsc_bad_addr(unsigned long addr);
-extern void __raw_bad_addr(const volatile void __iomem *addr);
-#define gsc_check_addr(addr) \
- if ((addr >> NYBBLE_SHIFT) != 0xf) { \
- gsc_bad_addr(addr); \
- addr |= 0xfUL << NYBBLE_SHIFT; \
- }
-#define __raw_check_addr(addr) \
- if (((unsigned long)addr >> NYBBLE_SHIFT) != 0xe) \
- __raw_bad_addr(addr); \
- addr = (void __iomem *)((unsigned long)addr | (0xfUL << NYBBLE_SHIFT));
-#else
-#define gsc_check_addr(addr)
-#define __raw_check_addr(addr)
-#endif
-
static inline unsigned char gsc_readb(unsigned long addr)
{
long flags;
unsigned char ret;
- gsc_check_addr(addr);
-
__asm__ __volatile__(
" rsm 2,%0\n"
" ldbx 0(%2),%1\n"
@@ -68,8 +44,6 @@ static inline unsigned short gsc_readw(unsigned long addr)
long flags;
unsigned short ret;
- gsc_check_addr(addr);
-
__asm__ __volatile__(
" rsm 2,%0\n"
" ldhx 0(%2),%1\n"
@@ -83,8 +57,6 @@ static inline unsigned int gsc_readl(unsigned long addr)
{
u32 ret;
- gsc_check_addr(addr);
-
__asm__ __volatile__(
" ldwax 0(%1),%0\n"
: "=r" (ret) : "r" (addr) );
@@ -95,7 +67,6 @@ static inline unsigned int gsc_readl(unsigned long addr)
static inline unsigned long long gsc_readq(unsigned long addr)
{
unsigned long long ret;
- gsc_check_addr(addr);
#ifdef __LP64__
__asm__ __volatile__(
@@ -112,8 +83,6 @@ static inline unsigned long long gsc_readq(unsigned long addr)
static inline void gsc_writeb(unsigned char val, unsigned long addr)
{
long flags;
- gsc_check_addr(addr);
-
__asm__ __volatile__(
" rsm 2,%0\n"
" stbs %1,0(%2)\n"
@@ -124,8 +93,6 @@ static inline void gsc_writeb(unsigned char val, unsigned long addr)
static inline void gsc_writew(unsigned short val, unsigned long addr)
{
long flags;
- gsc_check_addr(addr);
-
__asm__ __volatile__(
" rsm 2,%0\n"
" sths %1,0(%2)\n"
@@ -135,8 +102,6 @@ static inline void gsc_writew(unsigned short val, unsigned long addr)
static inline void gsc_writel(unsigned int val, unsigned long addr)
{
- gsc_check_addr(addr);
-
__asm__ __volatile__(
" stwas %0,0(%1)\n"
: : "r" (val), "r" (addr) );
@@ -144,8 +109,6 @@ static inline void gsc_writel(unsigned int val, unsigned long addr)
static inline void gsc_writeq(unsigned long long val, unsigned long addr)
{
- gsc_check_addr(addr);
-
#ifdef __LP64__
__asm__ __volatile__(
" stda %0,0(%1)\n"
@@ -163,31 +126,17 @@ static inline void gsc_writeq(unsigned long long val, unsigned long addr)
extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
-extern inline void __iomem * ioremap(unsigned long offset, unsigned long size)
-{
- return __ioremap(offset, size, 0);
-}
-
-/*
- * This one maps high address device memory and turns off caching for that area.
- * it's useful if some control registers are in such an area and write combining
- * or read caching is not desirable:
+/* Most machines react poorly to I/O-space being cacheable... Instead let's
+ * define ioremap() in terms of ioremap_nocache().
*/
-extern inline void * ioremap_nocache(unsigned long offset, unsigned long size)
+extern inline void __iomem * ioremap(unsigned long offset, unsigned long size)
{
- return __ioremap(offset, size, _PAGE_NO_CACHE /* _PAGE_PCD */);
+ return __ioremap(offset, size, _PAGE_NO_CACHE);
}
+#define ioremap_nocache(off, sz) ioremap((off), (sz))
extern void iounmap(void __iomem *addr);
-/*
- * USE_HPPA_IOREMAP is the magic flag to enable or disable real ioremap()
- * functionality. It's currently disabled because it may not work on some
- * machines.
- */
-#define USE_HPPA_IOREMAP 0
-
-#if USE_HPPA_IOREMAP
static inline unsigned char __raw_readb(const volatile void __iomem *addr)
{
return (*(volatile unsigned char __force *) (addr));
@@ -221,57 +170,6 @@ static inline void __raw_writeq(unsigned long long b, volatile void __iomem *add
{
*(volatile unsigned long long __force *) addr = b;
}
-#else /* !USE_HPPA_IOREMAP */
-static inline unsigned char __raw_readb(const volatile void __iomem *addr)
-{
- __raw_check_addr(addr);
-
- return gsc_readb((unsigned long) addr);
-}
-static inline unsigned short __raw_readw(const volatile void __iomem *addr)
-{
- __raw_check_addr(addr);
-
- return gsc_readw((unsigned long) addr);
-}
-static inline unsigned int __raw_readl(const volatile void __iomem *addr)
-{
- __raw_check_addr(addr);
-
- return gsc_readl((unsigned long) addr);
-}
-static inline unsigned long long __raw_readq(const volatile void __iomem *addr)
-{
- __raw_check_addr(addr);
-
- return gsc_readq((unsigned long) addr);
-}
-
-static inline void __raw_writeb(unsigned char b, volatile void __iomem *addr)
-{
- __raw_check_addr(addr);
-
- gsc_writeb(b, (unsigned long) addr);
-}
-static inline void __raw_writew(unsigned short b, volatile void __iomem *addr)
-{
- __raw_check_addr(addr);
-
- gsc_writew(b, (unsigned long) addr);
-}
-static inline void __raw_writel(unsigned int b, volatile void __iomem *addr)
-{
- __raw_check_addr(addr);
-
- gsc_writel(b, (unsigned long) addr);
-}
-static inline void __raw_writeq(unsigned long long b, volatile void __iomem *addr)
-{
- __raw_check_addr(addr);
-
- gsc_writeq(b, (unsigned long) addr);
-}
-#endif /* !USE_HPPA_IOREMAP */
/* readb can never be const, so use __fswab instead of le*_to_cpu */
#define readb(addr) __raw_readb(addr)
diff --git a/include/asm-parisc/local.h b/include/asm-parisc/local.h
index 892b3b2c496..d0f55091275 100644
--- a/include/asm-parisc/local.h
+++ b/include/asm-parisc/local.h
@@ -4,16 +4,16 @@
#include <linux/percpu.h>
#include <asm/atomic.h>
-typedef atomic_t local_t;
+typedef atomic_long_t local_t;
-#define LOCAL_INIT(i) ATOMIC_INIT(i)
-#define local_read(v) atomic_read(v)
-#define local_set(v,i) atomic_set(v,i)
+#define LOCAL_INIT(i) ATOMIC_LONG_INIT(i)
+#define local_read(v) atomic_long_read(v)
+#define local_set(v,i) atomic_long_set(v,i)
-#define local_inc(v) atomic_inc(v)
-#define local_dec(v) atomic_dec(v)
-#define local_add(i, v) atomic_add(i, v)
-#define local_sub(i, v) atomic_sub(i, v)
+#define local_inc(v) atomic_long_inc(v)
+#define local_dec(v) atomic_long_dec(v)
+#define local_add(i, v) atomic_long_add(i, v)
+#define local_sub(i, v) atomic_long_sub(i, v)
#define __local_inc(v) ((v)->counter++)
#define __local_dec(v) ((v)->counter--)
diff --git a/include/asm-parisc/mmzone.h b/include/asm-parisc/mmzone.h
index ae039f4fd71..ceb9b73199d 100644
--- a/include/asm-parisc/mmzone.h
+++ b/include/asm-parisc/mmzone.h
@@ -25,23 +25,6 @@ extern struct node_map_data node_data[];
pg_data_t *__pgdat = NODE_DATA(nid); \
__pgdat->node_start_pfn + __pgdat->node_spanned_pages; \
})
-#define node_localnr(pfn, nid) ((pfn) - node_start_pfn(nid))
-
-#define pfn_to_page(pfn) \
-({ \
- unsigned long __pfn = (pfn); \
- int __node = pfn_to_nid(__pfn); \
- &NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)]; \
-})
-
-#define page_to_pfn(pg) \
-({ \
- struct page *__page = pg; \
- struct zone *__zone = page_zone(__page); \
- BUG_ON(__zone == NULL); \
- (unsigned long)(__page - __zone->zone_mem_map) \
- + __zone->zone_start_pfn; \
-})
/* We have these possible memory map layouts:
* Astro: 0-3.75, 67.75-68, 4-64
diff --git a/include/asm-parisc/numnodes.h b/include/asm-parisc/numnodes.h
deleted file mode 100644
index 6c67651efd1..00000000000
--- a/include/asm-parisc/numnodes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-/* Max 8 Nodes */
-#define NODES_SHIFT 3
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h
index 4a6752b0afe..c0dd461fb8f 100644
--- a/include/asm-parisc/page.h
+++ b/include/asm-parisc/page.h
@@ -1,13 +1,30 @@
#ifndef _PARISC_PAGE_H
#define _PARISC_PAGE_H
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT 12
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#if !defined(__KERNEL__)
+/* this is for userspace applications (4k page size) */
+# define PAGE_SHIFT 12 /* 4k */
+# define PAGE_SIZE (1UL << PAGE_SHIFT)
+# define PAGE_MASK (~(PAGE_SIZE-1))
+#endif
+
#ifdef __KERNEL__
#include <linux/config.h>
+
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
+# define PAGE_SHIFT 12 /* 4k */
+#elif defined(CONFIG_PARISC_PAGE_SIZE_16KB)
+# define PAGE_SHIFT 14 /* 16k */
+#elif defined(CONFIG_PARISC_PAGE_SIZE_64KB)
+# define PAGE_SHIFT 16 /* 64k */
+#else
+# error "unknown default kernel page size"
+#endif
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+
#ifndef __ASSEMBLY__
#include <asm/types.h>
@@ -26,7 +43,7 @@ static inline void
copy_user_page(void *vto, void *vfrom, unsigned long vaddr, struct page *pg)
{
copy_user_page_asm(vto, vfrom);
- flush_kernel_dcache_page(vto);
+ flush_kernel_dcache_page_asm(vto);
/* XXX: ppc flushes icache too, should we? */
}
@@ -40,14 +57,19 @@ clear_user_page(void *page, unsigned long vaddr, struct page *pg)
/*
* These are used to make use of C type-checking..
*/
-#ifdef __LP64__
-typedef struct { unsigned long pte; } pte_t;
-#else
-typedef struct {
- unsigned long pte;
- unsigned long flags;
-} pte_t;
+#define STRICT_MM_TYPECHECKS
+#ifdef STRICT_MM_TYPECHECKS
+typedef struct { unsigned long pte;
+#if !defined(CONFIG_64BIT)
+ unsigned long future_flags;
+ /* XXX: it's possible to remove future_flags and change BITS_PER_PTE_ENTRY
+ to 2, but then strangely the identical 32bit kernel boots on a
+ c3000(pa20), but not any longer on a 715(pa11).
+ Still investigating... HelgeD.
+ */
#endif
+} pte_t; /* either 32 or 64bit */
+
/* NOTE: even on 64 bits, these entries are __u32 because we allocate
* the pmd and pgd in ZONE_DMA (i.e. under 4GB) */
typedef struct { __u32 pmd; } pmd_t;
@@ -55,25 +77,44 @@ typedef struct { __u32 pgd; } pgd_t;
typedef struct { unsigned long pgprot; } pgprot_t;
#define pte_val(x) ((x).pte)
-#ifdef __LP64__
-#define pte_flags(x) (*(__u32 *)&((x).pte))
-#else
-#define pte_flags(x) ((x).flags)
-#endif
-
/* These do not work lvalues, so make sure we don't use them as such. */
#define pmd_val(x) ((x).pmd + 0)
#define pgd_val(x) ((x).pgd + 0)
#define pgprot_val(x) ((x).pgprot)
-#define __pmd_val_set(x,n) (x).pmd = (n)
-#define __pgd_val_set(x,n) (x).pgd = (n)
-
#define __pte(x) ((pte_t) { (x) } )
#define __pmd(x) ((pmd_t) { (x) } )
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
+#define __pmd_val_set(x,n) (x).pmd = (n)
+#define __pgd_val_set(x,n) (x).pgd = (n)
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef __u32 pmd_t;
+typedef __u32 pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x) (x)
+#define pmd_val(x) (x)
+#define pgd_val(x) (x)
+#define pgprot_val(x) (x)
+
+#define __pte(x) (x)
+#define __pmd(x) (x)
+#define __pgd(x) (x)
+#define __pgprot(x) (x)
+
+#define __pmd_val_set(x,n) (x) = (n)
+#define __pgd_val_set(x,n) (x) = (n)
+
+#endif /* STRICT_MM_TYPECHECKS */
+
+
typedef struct __physmem_range {
unsigned long start_pfn;
unsigned long pages; /* PAGE_SIZE pages */
@@ -130,8 +171,6 @@ extern int npmem_ranges;
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
#ifndef CONFIG_DISCONTIGMEM
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#endif /* CONFIG_DISCONTIGMEM */
@@ -152,6 +191,7 @@ extern int npmem_ranges;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _PARISC_PAGE_H */
diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
index fe7f6a2f5aa..77bbafb7f73 100644
--- a/include/asm-parisc/pci.h
+++ b/include/asm-parisc/pci.h
@@ -289,4 +289,9 @@ static inline void pcibios_add_platform_entries(struct pci_dev *dev)
{
}
+static inline void pcibios_penalize_isa_irq(int irq, int active)
+{
+ /* We don't need to penalize isa irq's */
+}
+
#endif /* __ASM_PARISC_PCI_H */
diff --git a/include/asm-parisc/pdc.h b/include/asm-parisc/pdc.h
index 8e23e4c674f..0a3face6c48 100644
--- a/include/asm-parisc/pdc.h
+++ b/include/asm-parisc/pdc.h
@@ -333,7 +333,7 @@ struct pdc_model { /* for PDC_MODEL */
unsigned long curr_key;
};
-/* Values for PDC_MODEL_CAPABILITES non-equivalent virtual aliasing support */
+/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */
#define PDC_MODEL_IOPDIR_FDC (1 << 2) /* see sba_iommu.c */
#define PDC_MODEL_NVA_MASK (3 << 4)
diff --git a/include/asm-parisc/pdc_chassis.h b/include/asm-parisc/pdc_chassis.h
index adac9ac2743..a609273dc6b 100644
--- a/include/asm-parisc/pdc_chassis.h
+++ b/include/asm-parisc/pdc_chassis.h
@@ -6,9 +6,8 @@
*
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
+ * 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
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index 4e34c6b4405..aec089eb8b8 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -59,16 +59,15 @@
#define ISTACK_SIZE 32768 /* Interrupt Stack Size */
#define ISTACK_ORDER 3
-/* This is the size of the initially mapped kernel memory (i.e. currently
- * 0 to 1<<23 == 8MB */
+/* This is the size of the initially mapped kernel memory */
#ifdef CONFIG_64BIT
-#define KERNEL_INITIAL_ORDER 24
+#define KERNEL_INITIAL_ORDER 24 /* 0 to 1<<24 = 16MB */
#else
-#define KERNEL_INITIAL_ORDER 23
+#define KERNEL_INITIAL_ORDER 23 /* 0 to 1<<23 = 8MB */
#endif
#define KERNEL_INITIAL_SIZE (1 << KERNEL_INITIAL_ORDER)
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && defined(CONFIG_PARISC_PAGE_SIZE_4KB)
#define PT_NLEVELS 3
#define PGD_ORDER 1 /* Number of pages per pgd */
#define PMD_ORDER 1 /* Number of pages per pmd */
@@ -111,11 +110,15 @@
#define MAX_ADDRBITS (PGDIR_SHIFT + BITS_PER_PGD)
#define MAX_ADDRESS (1UL << MAX_ADDRBITS)
-#define SPACEID_SHIFT (MAX_ADDRBITS - 32)
+#define SPACEID_SHIFT (MAX_ADDRBITS - 32)
/* This calculates the number of initial pages we need for the initial
* page tables */
-#define PT_INITIAL (1 << (KERNEL_INITIAL_ORDER - PMD_SHIFT))
+#if (KERNEL_INITIAL_ORDER) >= (PMD_SHIFT)
+# define PT_INITIAL (1 << (KERNEL_INITIAL_ORDER - PMD_SHIFT))
+#else
+# define PT_INITIAL (1) /* all initial PTEs fit into one page */
+#endif
/*
* pgd entries used up by user/kernel:
@@ -160,6 +163,10 @@ extern void *vmalloc_start;
* to zero */
#define PTE_SHIFT xlate_pabit(_PAGE_USER_BIT)
+/* PFN_PTE_SHIFT defines the shift of a PTE value to access the PFN field */
+#define PFN_PTE_SHIFT 12
+
+
/* this is how many bits may be used by the file functions */
#define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_SHIFT)
@@ -188,7 +195,8 @@ extern void *vmalloc_start;
/* The pgd/pmd contains a ptr (in phys addr space); since all pgds/pmds
* are page-aligned, we don't care about the PAGE_OFFSET bits, except
* for a few meta-information bits, so we shift the address to be
- * able to effectively address 40-bits of physical address space. */
+ * able to effectively address 40/42/44-bits of physical address space
+ * depending on 4k/16k/64k PAGE_SIZE */
#define _PxD_PRESENT_BIT 31
#define _PxD_ATTACHED_BIT 30
#define _PxD_VALID_BIT 29
@@ -198,7 +206,7 @@ extern void *vmalloc_start;
#define PxD_FLAG_VALID (1 << xlate_pabit(_PxD_VALID_BIT))
#define PxD_FLAG_MASK (0xf)
#define PxD_FLAG_SHIFT (4)
-#define PxD_VALUE_SHIFT (8)
+#define PxD_VALUE_SHIFT (8) /* (PAGE_SHIFT-PxD_FLAG_SHIFT) */
#ifndef __ASSEMBLY__
@@ -246,6 +254,7 @@ extern void *vmalloc_start;
#define __S110 PAGE_RWX
#define __S111 PAGE_RWX
+
extern pgd_t swapper_pg_dir[]; /* declared in init_task.c */
/* initial page tables for 0-8MB for kernel */
@@ -272,7 +281,7 @@ extern unsigned long *empty_zero_page;
#define pgd_flag(x) (pgd_val(x) & PxD_FLAG_MASK)
#define pgd_address(x) ((unsigned long)(pgd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT)
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
/* The first entry of the permanent pmd is not there if it contains
* the gateway marker */
#define pmd_none(x) (!pmd_val(x) || pmd_flag(x) == PxD_FLAG_ATTACHED)
@@ -282,7 +291,7 @@ extern unsigned long *empty_zero_page;
#define pmd_bad(x) (!(pmd_flag(x) & PxD_FLAG_VALID))
#define pmd_present(x) (pmd_flag(x) & PxD_FLAG_PRESENT)
static inline void pmd_clear(pmd_t *pmd) {
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
if (pmd_flag(*pmd) & PxD_FLAG_ATTACHED)
/* This is the entry pointing to the permanent pmd
* attached to the pgd; cannot clear it */
@@ -303,7 +312,7 @@ static inline void pmd_clear(pmd_t *pmd) {
#define pgd_bad(x) (!(pgd_flag(x) & PxD_FLAG_VALID))
#define pgd_present(x) (pgd_flag(x) & PxD_FLAG_PRESENT)
static inline void pgd_clear(pgd_t *pgd) {
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
if(pgd_flag(*pgd) & PxD_FLAG_ATTACHED)
/* This is the permanent pmd attached to the pgd; cannot
* free it */
@@ -351,7 +360,7 @@ extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return
({ \
pte_t __pte; \
\
- pte_val(__pte) = ((addr)+pgprot_val(pgprot)); \
+ pte_val(__pte) = ((((addr)>>PAGE_SHIFT)<<PFN_PTE_SHIFT) + pgprot_val(pgprot)); \
\
__pte; \
})
@@ -361,20 +370,16 @@ extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return
static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
{
pte_t pte;
- pte_val(pte) = (pfn << PAGE_SHIFT) | pgprot_val(pgprot);
+ pte_val(pte) = (pfn << PFN_PTE_SHIFT) | pgprot_val(pgprot);
return pte;
}
-/* This takes a physical page address that is used by the remapping functions */
-#define mk_pte_phys(physpage, pgprot) \
-({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; })
-
extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
/* Permanent address of a page. On parisc we don't have highmem. */
-#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
+#define pte_pfn(x) (pte_val(x) >> PFN_PTE_SHIFT)
#define pte_page(pte) (pfn_to_page(pte_pfn(pte)))
@@ -499,6 +504,26 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
#endif /* !__ASSEMBLY__ */
+
+/* TLB page size encoding - see table 3-1 in parisc20.pdf */
+#define _PAGE_SIZE_ENCODING_4K 0
+#define _PAGE_SIZE_ENCODING_16K 1
+#define _PAGE_SIZE_ENCODING_64K 2
+#define _PAGE_SIZE_ENCODING_256K 3
+#define _PAGE_SIZE_ENCODING_1M 4
+#define _PAGE_SIZE_ENCODING_4M 5
+#define _PAGE_SIZE_ENCODING_16M 6
+#define _PAGE_SIZE_ENCODING_64M 7
+
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
+# define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_4K
+#elif defined(CONFIG_PARISC_PAGE_SIZE_16KB)
+# define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_16K
+#elif defined(CONFIG_PARISC_PAGE_SIZE_64KB)
+# define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_64K
+#endif
+
+
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-parisc/spinlock.h b/include/asm-parisc/spinlock.h
index 16c2ac075fc..a93960e232c 100644
--- a/include/asm-parisc/spinlock.h
+++ b/include/asm-parisc/spinlock.h
@@ -134,14 +134,22 @@ static __inline__ int __raw_write_trylock(raw_rwlock_t *rw)
return 1;
}
-static __inline__ int __raw_is_read_locked(raw_rwlock_t *rw)
+/*
+ * read_can_lock - would read_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+static __inline__ int __raw_read_can_lock(raw_rwlock_t *rw)
{
- return rw->counter > 0;
+ return rw->counter >= 0;
}
-static __inline__ int __raw_is_write_locked(raw_rwlock_t *rw)
+/*
+ * write_can_lock - would write_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+static __inline__ int __raw_write_can_lock(raw_rwlock_t *rw)
{
- return rw->counter < 0;
+ return !rw->counter;
}
#endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h
index ac32f140b83..f2f83b04cd8 100644
--- a/include/asm-parisc/thread_info.h
+++ b/include/asm-parisc/thread_info.h
@@ -49,7 +49,8 @@ struct thread_info {
#endif /* !__ASSEMBLY */
-#define PREEMPT_ACTIVE 0x10000000
+#define PREEMPT_ACTIVE_BIT 28
+#define PREEMPT_ACTIVE (1 << PREEMPT_ACTIVE_BIT)
/*
* thread information flags
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
index c56fccbf34a..0e1a30be2e3 100644
--- a/include/asm-parisc/unistd.h
+++ b/include/asm-parisc/unistd.h
@@ -780,8 +780,14 @@
#define __NR_readlinkat (__NR_Linux + 285)
#define __NR_fchmodat (__NR_Linux + 286)
#define __NR_faccessat (__NR_Linux + 287)
+#define __NR_unshare (__NR_Linux + 288)
+#define __NR_set_robust_list (__NR_Linux + 289)
+#define __NR_get_robust_list (__NR_Linux + 290)
+#define __NR_splice (__NR_Linux + 291)
+#define __NR_sync_file_range (__NR_Linux + 292)
+#define __NR_tee (__NR_Linux + 293)
-#define __NR_Linux_syscalls 288
+#define __NR_Linux_syscalls 294
#define HPUX_GATEWAY_ADDR 0xC0000004
#define LINUX_GATEWAY_ADDR 0x100
diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h
index 99817a802ca..f44b529e329 100644
--- a/include/asm-powerpc/bug.h
+++ b/include/asm-powerpc/bug.h
@@ -30,34 +30,60 @@ struct bug_entry *find_bug(unsigned long bugaddr);
#ifdef CONFIG_BUG
+/*
+ * BUG_ON() and WARN_ON() do their best to cooperate with compile-time
+ * optimisations. However depending on the complexity of the condition
+ * some compiler versions may not produce optimal results.
+ */
+
#define BUG() do { \
__asm__ __volatile__( \
"1: twi 31,0,0\n" \
".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%0,%1,%2\n" \
+ "\t"PPC_LONG" 1b,%0,%1,%2\n" \
".previous" \
: : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \
} while (0)
#define BUG_ON(x) do { \
- __asm__ __volatile__( \
+ if (__builtin_constant_p(x)) { \
+ if (x) \
+ BUG(); \
+ } else { \
+ __asm__ __volatile__( \
"1: "PPC_TLNEI" %0,0\n" \
".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%1,%2,%3\n" \
+ "\t"PPC_LONG" 1b,%1,%2,%3\n" \
".previous" \
: : "r" ((long)(x)), "i" (__LINE__), \
"i" (__FILE__), "i" (__FUNCTION__)); \
+ } \
} while (0)
-#define WARN_ON(x) do { \
+#define __WARN() do { \
__asm__ __volatile__( \
+ "1: twi 31,0,0\n" \
+ ".section __bug_table,\"a\"\n" \
+ "\t"PPC_LONG" 1b,%0,%1,%2\n" \
+ ".previous" \
+ : : "i" (__LINE__ + BUG_WARNING_TRAP), \
+ "i" (__FILE__), "i" (__FUNCTION__)); \
+} while (0)
+
+#define WARN_ON(x) do { \
+ if (__builtin_constant_p(x)) { \
+ if (x) \
+ __WARN(); \
+ } else { \
+ __asm__ __volatile__( \
"1: "PPC_TLNEI" %0,0\n" \
".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%1,%2,%3\n" \
+ "\t"PPC_LONG" 1b,%1,%2,%3\n" \
".previous" \
: : "r" ((long)(x)), \
"i" (__LINE__ + BUG_WARNING_TRAP), \
"i" (__FILE__), "i" (__FUNCTION__)); \
+ } \
} while (0)
#define HAVE_ARCH_BUG
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index fe45f6f3a4b..9fcf0162d85 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -22,6 +22,7 @@
#define PPC_FEATURE_BOOKE 0x00008000
#define PPC_FEATURE_SMT 0x00004000
#define PPC_FEATURE_ICACHE_SNOOP 0x00002000
+#define PPC_FEATURE_ARCH_2_05 0x00001000
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
@@ -188,153 +189,159 @@ extern void do_cpu_ftr_fixups(unsigned long offset);
!defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
!defined(CONFIG_BOOKE))
-enum {
- CPU_FTRS_PPC601 = CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE,
- CPU_FTRS_603 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
- CPU_FTR_MAYBE_CAN_NAP,
- CPU_FTRS_604 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE,
- CPU_FTRS_740_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
- CPU_FTRS_740 = 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_FTRS_750 = 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_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_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_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_FTRS_750GX = 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_FTRS_7400_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- 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_FTRS_7400 = 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_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
- CPU_FTR_MAYBE_CAN_NAP,
- CPU_FTRS_7450_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- 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_FTRS_7450_21 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- 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_FTRS_7450_23 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- 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_FTRS_7455_1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- 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_FTRS_7455_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- 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_FTRS_7455 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- 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_FTRS_7447_10 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- 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_FTRS_7447 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- 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_FTRS_7447A = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- 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_FTRS_82XX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB,
- CPU_FTRS_G2_LE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
- CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
- CPU_FTRS_E300 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
- CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS |
- CPU_FTR_COMMON,
- CPU_FTRS_CLASSIC32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
- CPU_FTRS_POWER3_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
- CPU_FTRS_POWER4_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_NODSISRALIGN,
- CPU_FTRS_970_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN,
- CPU_FTRS_8XX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
- CPU_FTRS_40X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_NODSISRALIGN,
- CPU_FTRS_44X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_NODSISRALIGN,
- CPU_FTRS_E200 = CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN,
- CPU_FTRS_E500 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_NODSISRALIGN,
- CPU_FTRS_E500_2 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN,
- CPU_FTRS_GENERIC_32 = CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN,
+#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 | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
+ CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_604 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE)
+#define CPU_FTRS_740_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_740 (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)
+#define CPU_FTRS_750 (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)
+#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)
+#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)
+#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)
+#define CPU_FTRS_750GX (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)
+#define CPU_FTRS_7400_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ 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)
+#define CPU_FTRS_7400 (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_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
+ CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_7450_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ 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)
+#define CPU_FTRS_7450_21 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ 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)
+#define CPU_FTRS_7450_23 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ 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)
+#define CPU_FTRS_7455_1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ 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)
+#define CPU_FTRS_7455_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ 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)
+#define CPU_FTRS_7455 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ 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)
+#define CPU_FTRS_7447_10 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ 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)
+#define CPU_FTRS_7447 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ 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)
+#define CPU_FTRS_7447A (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ 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)
+#define CPU_FTRS_82XX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
+#define CPU_FTRS_G2_LE (CPU_FTR_SPLIT_ID_CACHE | 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 | \
+ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
+ CPU_FTR_COMMON)
+#define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
+#define CPU_FTRS_POWER3_32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
+#define CPU_FTRS_POWER4_32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_970_32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP | \
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN)
+#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 | \
+ CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
#ifdef __powerpc64__
- CPU_FTRS_POWER3 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_IABR,
- CPU_FTRS_RS64 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
- CPU_FTR_MMCRA | CPU_FTR_CTRL,
- CPU_FTRS_POWER4 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA,
- CPU_FTRS_PPC970 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
- CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA,
- CPU_FTRS_POWER5 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
- CPU_FTR_MMCRA | CPU_FTR_SMT |
- CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
- CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR,
- CPU_FTRS_CELL = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
- CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT |
- CPU_FTR_CTRL | CPU_FTR_PAUSE_ZERO,
- CPU_FTRS_COMPATIBLE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2,
+#define CPU_FTRS_POWER3 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_IABR)
+#define CPU_FTRS_RS64 (CPU_FTR_SPLIT_ID_CACHE | 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 | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA)
+#define CPU_FTRS_PPC970 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
+#define CPU_FTRS_POWER5 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_MMCRA | CPU_FTR_SMT | \
+ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
+ CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR)
+#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_MMCRA | CPU_FTR_SMT | \
+ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
+ CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE)
+#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
+ CPU_FTR_CTRL | CPU_FTR_PAUSE_ZERO)
+#define CPU_FTRS_COMPATIBLE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
#endif
- CPU_FTRS_POSSIBLE =
#ifdef __powerpc64__
- CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |
- CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL |
- CPU_FTR_CI_LARGE_PAGE |
+#define CPU_FTRS_POSSIBLE \
+ (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \
+ CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 | \
+ CPU_FTRS_CELL | CPU_FTR_CI_LARGE_PAGE)
#else
+enum {
+ CPU_FTRS_POSSIBLE =
#if CLASSIC_PPC
CPU_FTRS_PPC601 | CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU |
CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 |
@@ -368,14 +375,18 @@ enum {
#ifdef CONFIG_E500
CPU_FTRS_E500 | CPU_FTRS_E500_2 |
#endif
-#endif /* __powerpc64__ */
0,
+};
+#endif /* __powerpc64__ */
- CPU_FTRS_ALWAYS =
#ifdef __powerpc64__
- CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 &
- CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_CELL &
+#define CPU_FTRS_ALWAYS \
+ (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 & \
+ CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_POWER6 & \
+ CPU_FTRS_CELL & CPU_FTRS_POSSIBLE)
#else
+enum {
+ CPU_FTRS_ALWAYS =
#if CLASSIC_PPC
CPU_FTRS_PPC601 & CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU &
CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 &
@@ -409,9 +420,9 @@ enum {
#ifdef CONFIG_E500
CPU_FTRS_E500 & CPU_FTRS_E500_2 &
#endif
-#endif /* __powerpc64__ */
CPU_FTRS_POSSIBLE,
};
+#endif /* __powerpc64__ */
static inline int cpu_has_feature(unsigned long feature)
{
diff --git a/include/asm-powerpc/eeh.h b/include/asm-powerpc/eeh.h
index 5207758a6dd..868c7139dbf 100644
--- a/include/asm-powerpc/eeh.h
+++ b/include/asm-powerpc/eeh.h
@@ -60,24 +60,10 @@ void __init pci_addr_cache_build(void);
* device (including config space i/o). Call eeh_add_device_late
* to finish the eeh setup for this device.
*/
-void eeh_add_device_early(struct device_node *);
-void eeh_add_device_late(struct pci_dev *dev);
void eeh_add_device_tree_early(struct device_node *);
void eeh_add_device_tree_late(struct pci_bus *);
/**
- * eeh_remove_device - undo EEH setup for the indicated pci device
- * @dev: pci device to be removed
- *
- * This routine should be called when a device is removed from
- * a running system (e.g. by hotplug or dlpar). It unregisters
- * the PCI device from the EEH subsystem. I/O errors affecting
- * this device will no longer be detected after this call; thus,
- * i/o errors affecting this slot may leave this device unusable.
- */
-void eeh_remove_device(struct pci_dev *);
-
-/**
* eeh_remove_device_recursive - undo EEH for device & children.
* @dev: pci device to be removed
*
@@ -116,12 +102,6 @@ static inline int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *d
static inline void pci_addr_cache_build(void) { }
-static inline void eeh_add_device_early(struct device_node *dn) { }
-
-static inline void eeh_add_device_late(struct pci_dev *dev) { }
-
-static inline void eeh_remove_device(struct pci_dev *dev) { }
-
static inline void eeh_add_device_tree_early(struct device_node *dn) { }
static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h
index ce3788224ed..77069df92bf 100644
--- a/include/asm-powerpc/firmware.h
+++ b/include/asm-powerpc/firmware.h
@@ -82,13 +82,11 @@ enum {
/* This is used to identify firmware features which are available
* to the kernel.
*/
-extern unsigned long ppc64_firmware_features;
+extern unsigned long powerpc_firmware_features;
-static inline unsigned long firmware_has_feature(unsigned long feature)
-{
- return (FW_FEATURE_ALWAYS & feature) ||
- (FW_FEATURE_POSSIBLE & ppc64_firmware_features & feature);
-}
+#define firmware_has_feature(feature) \
+ ((FW_FEATURE_ALWAYS & (feature)) || \
+ (FW_FEATURE_POSSIBLE & powerpc_firmware_features & (feature)))
extern void system_reset_fwnmi(void);
extern void machine_check_fwnmi(void);
diff --git a/include/asm-powerpc/floppy.h b/include/asm-powerpc/floppy.h
index e258778ca42..608164c39ef 100644
--- a/include/asm-powerpc/floppy.h
+++ b/include/asm-powerpc/floppy.h
@@ -35,6 +35,7 @@
#ifdef CONFIG_PCI
#include <linux/pci.h>
+#include <asm/ppc-pci.h> /* for ppc64_isabridge_dev */
#define fd_dma_setup(addr,size,mode,io) powerpc_fd_dma_setup(addr,size,mode,io)
@@ -52,12 +53,12 @@ static __inline__ int powerpc_fd_dma_setup(char *addr, unsigned long size,
if (bus_addr
&& (addr != prev_addr || size != prev_size || dir != prev_dir)) {
/* different from last time -- unmap prev */
- pci_unmap_single(NULL, bus_addr, prev_size, prev_dir);
+ pci_unmap_single(ppc64_isabridge_dev, bus_addr, prev_size, prev_dir);
bus_addr = 0;
}
if (!bus_addr) /* need to map it */
- bus_addr = pci_map_single(NULL, addr, size, dir);
+ bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir);
/* remember this one as prev */
prev_addr = addr;
diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h
index 39e85f320a7..f1b3c00bc1c 100644
--- a/include/asm-powerpc/futex.h
+++ b/include/asm-powerpc/futex.h
@@ -81,5 +81,11 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
return ret;
}
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ return -ENOSYS;
+}
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_FUTEX_H */
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index 38ca9ad6110..6cc7e1fb7bf 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -4,46 +4,88 @@
#define HVSC .long 0x44000022
-#define H_Success 0
-#define H_Busy 1 /* Hardware busy -- retry later */
-#define H_Closed 2 /* Resource closed */
-#define H_Constrained 4 /* Resource request constrained to max allowed */
-#define H_InProgress 14 /* Kind of like busy */
-#define H_Continue 18 /* Returned from H_Join on success */
-#define H_LongBusyStartRange 9900 /* Start of long busy range */
-#define H_LongBusyOrder1msec 9900 /* Long busy, hint that 1msec is a good time to retry */
-#define H_LongBusyOrder10msec 9901 /* Long busy, hint that 10msec is a good time to retry */
-#define H_LongBusyOrder100msec 9902 /* Long busy, hint that 100msec is a good time to retry */
-#define H_LongBusyOrder1sec 9903 /* Long busy, hint that 1sec is a good time to retry */
-#define H_LongBusyOrder10sec 9904 /* Long busy, hint that 10sec is a good time to retry */
-#define H_LongBusyOrder100sec 9905 /* Long busy, hint that 100sec is a good time to retry */
-#define H_LongBusyEndRange 9905 /* End of long busy range */
-#define H_Hardware -1 /* Hardware error */
-#define H_Function -2 /* Function not supported */
-#define H_Privilege -3 /* Caller not privileged */
-#define H_Parameter -4 /* Parameter invalid, out-of-range or conflicting */
-#define H_Bad_Mode -5 /* Illegal msr value */
-#define H_PTEG_Full -6 /* PTEG is full */
-#define H_Not_Found -7 /* PTE was not found" */
-#define H_Reserved_DABR -8 /* DABR address is reserved by the hypervisor on this processor" */
-#define H_NoMem -9
-#define H_Authority -10
-#define H_Permission -11
-#define H_Dropped -12
-#define H_SourceParm -13
-#define H_DestParm -14
-#define H_RemoteParm -15
-#define H_Resource -16
+#define H_SUCCESS 0
+#define H_BUSY 1 /* Hardware busy -- retry later */
+#define H_CLOSED 2 /* Resource closed */
+#define H_NOT_AVAILABLE 3
+#define H_CONSTRAINED 4 /* Resource request constrained to max allowed */
+#define H_PARTIAL 5
+#define H_IN_PROGRESS 14 /* Kind of like busy */
+#define H_PAGE_REGISTERED 15
+#define H_PARTIAL_STORE 16
+#define H_PENDING 17 /* returned from H_POLL_PENDING */
+#define H_CONTINUE 18 /* Returned from H_Join on success */
+#define H_LONG_BUSY_START_RANGE 9900 /* Start of long busy range */
+#define H_LONG_BUSY_ORDER_1_MSEC 9900 /* Long busy, hint that 1msec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_10_MSEC 9901 /* Long busy, hint that 10msec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_100_MSEC 9902 /* Long busy, hint that 100msec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_1_SEC 9903 /* Long busy, hint that 1sec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_10_SEC 9904 /* Long busy, hint that 10sec \
+ is a good time to retry */
+#define H_LONG_BUSY_ORDER_100_SEC 9905 /* Long busy, hint that 100sec \
+ is a good time to retry */
+#define H_LONG_BUSY_END_RANGE 9905 /* End of long busy range */
+#define H_HARDWARE -1 /* Hardware error */
+#define H_FUNCTION -2 /* Function not supported */
+#define H_PRIVILEGE -3 /* Caller not privileged */
+#define H_PARAMETER -4 /* Parameter invalid, out-of-range or conflicting */
+#define H_BAD_MODE -5 /* Illegal msr value */
+#define H_PTEG_FULL -6 /* PTEG is full */
+#define H_NOT_FOUND -7 /* PTE was not found" */
+#define H_RESERVED_DABR -8 /* DABR address is reserved by the hypervisor on this processor" */
+#define H_NO_MEM -9
+#define H_AUTHORITY -10
+#define H_PERMISSION -11
+#define H_DROPPED -12
+#define H_SOURCE_PARM -13
+#define H_DEST_PARM -14
+#define H_REMOTE_PARM -15
+#define H_RESOURCE -16
+#define H_ADAPTER_PARM -17
+#define H_RH_PARM -18
+#define H_RCQ_PARM -19
+#define H_SCQ_PARM -20
+#define H_EQ_PARM -21
+#define H_RT_PARM -22
+#define H_ST_PARM -23
+#define H_SIGT_PARM -24
+#define H_TOKEN_PARM -25
+#define H_MLENGTH_PARM -27
+#define H_MEM_PARM -28
+#define H_MEM_ACCESS_PARM -29
+#define H_ATTR_PARM -30
+#define H_PORT_PARM -31
+#define H_MCG_PARM -32
+#define H_VL_PARM -33
+#define H_TSIZE_PARM -34
+#define H_TRACE_PARM -35
+
+#define H_MASK_PARM -37
+#define H_MCG_FULL -38
+#define H_ALIAS_EXIST -39
+#define H_P_COUNTER -40
+#define H_TABLE_FULL -41
+#define H_ALT_TABLE -42
+#define H_MR_CONDITION -43
+#define H_NOT_ENOUGH_RESOURCES -44
+#define H_R_STATE -45
+#define H_RESCINDEND -46
+
/* Long Busy is a condition that can be returned by the firmware
* when a call cannot be completed now, but the identical call
* should be retried later. This prevents calls blocking in the
- * firmware for long periods of time. Annoyingly the firmware can return
+ * firmware for long periods of time. Annoyingly the firmware can return
* a range of return codes, hinting at how long we should wait before
* retrying. If you don't care for the hint, the macro below is a good
* way to check for the long_busy return codes
*/
-#define H_isLongBusy(x) ((x >= H_LongBusyStartRange) && (x <= H_LongBusyEndRange))
+#define H_IS_LONG_BUSY(x) ((x >= H_LONG_BUSY_START_RANGE) \
+ && (x <= H_LONG_BUSY_END_RANGE))
/* Flags */
#define H_LARGE_PAGE (1UL<<(63-16))
@@ -65,6 +107,9 @@
#define H_DABRX_KERNEL (1UL<<(63-62))
#define H_DABRX_USER (1UL<<(63-63))
+/* Each control block has to be on a 4K bondary */
+#define H_CB_ALIGNMENT 4096
+
/* pSeries hypervisor opcodes */
#define H_REMOVE 0x04
#define H_ENTER 0x08
@@ -98,25 +143,52 @@
#define H_PERFMON 0x7c
#define H_MIGRATE_DMA 0x78
#define H_REGISTER_VPA 0xDC
-#define H_CEDE 0xE0
+#define H_CEDE 0xE0
#define H_CONFER 0xE4
-#define H_PROD 0xE8
+#define H_PROD 0xE8
#define H_GET_PPP 0xEC
#define H_SET_PPP 0xF0
#define H_PURR 0xF4
-#define H_PIC 0xF8
+#define H_PIC 0xF8
#define H_REG_CRQ 0xFC
#define H_FREE_CRQ 0x100
#define H_VIO_SIGNAL 0x104
#define H_SEND_CRQ 0x108
-#define H_COPY_RDMA 0x110
+#define H_COPY_RDMA 0x110
#define H_SET_XDABR 0x134
#define H_STUFF_TCE 0x138
#define H_PUT_TCE_INDIRECT 0x13C
#define H_VTERM_PARTNER_INFO 0x150
#define H_REGISTER_VTERM 0x154
#define H_FREE_VTERM 0x158
-#define H_POLL_PENDING 0x1D8
+#define H_RESET_EVENTS 0x15C
+#define H_ALLOC_RESOURCE 0x160
+#define H_FREE_RESOURCE 0x164
+#define H_MODIFY_QP 0x168
+#define H_QUERY_QP 0x16C
+#define H_REREGISTER_PMR 0x170
+#define H_REGISTER_SMR 0x174
+#define H_QUERY_MR 0x178
+#define H_QUERY_MW 0x17C
+#define H_QUERY_HCA 0x180
+#define H_QUERY_PORT 0x184
+#define H_MODIFY_PORT 0x188
+#define H_DEFINE_AQP1 0x18C
+#define H_GET_TRACE_BUFFER 0x190
+#define H_DEFINE_AQP0 0x194
+#define H_RESIZE_MR 0x198
+#define H_ATTACH_MCQP 0x19C
+#define H_DETACH_MCQP 0x1A0
+#define H_CREATE_RPT 0x1A4
+#define H_REMOVE_RPT 0x1A8
+#define H_REGISTER_RPAGES 0x1AC
+#define H_DISABLE_AND_GETC 0x1B0
+#define H_ERROR_DATA 0x1B4
+#define H_GET_HCA_INFO 0x1B8
+#define H_GET_PERF_COUNT 0x1BC
+#define H_MANAGE_TRACE 0x1C0
+#define H_QUERY_INT_STATE 0x1E4
+#define H_POLL_PENDING 0x1D8
#define H_JOIN 0x298
#define H_ENABLE_CRQ 0x2B0
@@ -151,7 +223,7 @@ long plpar_hcall_norets(unsigned long opcode, ...);
*/
long plpar_hcall_8arg_2ret(unsigned long opcode,
unsigned long arg1,
- unsigned long arg2,
+ unsigned long arg2,
unsigned long arg3,
unsigned long arg4,
unsigned long arg5,
@@ -175,6 +247,42 @@ long plpar_hcall_4out(unsigned long opcode,
unsigned long *out3,
unsigned long *out4);
+long plpar_hcall_7arg_7ret(unsigned long opcode,
+ unsigned long arg1,
+ unsigned long arg2,
+ unsigned long arg3,
+ unsigned long arg4,
+ unsigned long arg5,
+ unsigned long arg6,
+ unsigned long arg7,
+ unsigned long *out1,
+ unsigned long *out2,
+ unsigned long *out3,
+ unsigned long *out4,
+ unsigned long *out5,
+ unsigned long *out6,
+ unsigned long *out7);
+
+long plpar_hcall_9arg_9ret(unsigned long opcode,
+ unsigned long arg1,
+ unsigned long arg2,
+ unsigned long arg3,
+ unsigned long arg4,
+ unsigned long arg5,
+ unsigned long arg6,
+ unsigned long arg7,
+ unsigned long arg8,
+ unsigned long arg9,
+ unsigned long *out1,
+ unsigned long *out2,
+ unsigned long *out3,
+ unsigned long *out4,
+ unsigned long *out5,
+ unsigned long *out6,
+ unsigned long *out7,
+ unsigned long *out8,
+ unsigned long *out9);
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_HVCALL_H */
diff --git a/include/asm-powerpc/hvconsole.h b/include/asm-powerpc/hvconsole.h
index 34daf7b9b62..35ea69e8121 100644
--- a/include/asm-powerpc/hvconsole.h
+++ b/include/asm-powerpc/hvconsole.h
@@ -24,28 +24,18 @@
#ifdef __KERNEL__
/*
- * This is the max number of console adapters that can/will be found as
- * console devices on first stage console init. Any number beyond this range
- * can't be used as a console device but is still a valid tty device.
+ * PSeries firmware will only send/recv up to 16 bytes of character data per
+ * hcall.
*/
-#define MAX_NR_HVC_CONSOLES 16
+#define MAX_VIO_PUT_CHARS 16
+#define SIZE_VIO_GET_CHARS 16
-/* implemented by a low level driver */
-struct hv_ops {
- int (*get_chars)(uint32_t vtermno, char *buf, int count);
- int (*put_chars)(uint32_t vtermno, const char *buf, int count);
-};
+/*
+ * Vio firmware always attempts to fetch MAX_VIO_GET_CHARS chars. The 'count'
+ * parm is included to conform to put_chars() function pointer template
+ */
extern int hvc_get_chars(uint32_t vtermno, char *buf, int count);
extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count);
-struct hvc_struct;
-
-/* Register a vterm and a slot index for use as a console (console_init) */
-extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops);
-/* register a vterm for hvc tty operation (module_init or hotplug add) */
-extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq,
- struct hv_ops *ops);
-/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */
-extern int __devexit hvc_remove(struct hvc_struct *hp);
#endif /* __KERNEL__ */
#endif /* _PPC64_HVCONSOLE_H */
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index 68efbea379c..f1c2469b884 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -9,6 +9,9 @@
* 2 of the License, or (at your option) any later version.
*/
+/* Check of existence of legacy devices */
+extern int check_legacy_ioport(unsigned long base_port);
+
#ifndef CONFIG_PPC64
#include <asm-ppc/io.h>
#else
@@ -437,9 +440,6 @@ out:
#define dma_cache_wback(_start,_size) do { } while (0)
#define dma_cache_wback_inv(_start,_size) do { } while (0)
-/* Check of existence of legacy devices */
-extern int check_legacy_ioport(unsigned long base_port);
-
/*
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
index d5677cbec20..18ca29e9105 100644
--- a/include/asm-powerpc/iommu.h
+++ b/include/asm-powerpc/iommu.h
@@ -70,17 +70,18 @@ extern void iommu_free_table(struct device_node *dn);
extern struct iommu_table *iommu_init_table(struct iommu_table * tbl);
extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
- struct scatterlist *sglist, int nelems,
+ struct scatterlist *sglist, int nelems, unsigned long mask,
enum dma_data_direction direction);
extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction);
extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
- dma_addr_t *dma_handle, gfp_t flag);
+ dma_addr_t *dma_handle, unsigned long mask, gfp_t flag);
extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
void *vaddr, dma_addr_t dma_handle);
extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
- size_t size, enum dma_data_direction direction);
+ size_t size, unsigned long mask,
+ enum dma_data_direction direction);
extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction);
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 51f87d9993b..7bc6d73b282 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -54,6 +54,13 @@
*/
extern unsigned int virt_irq_to_real_map[NR_IRQS];
+/* The maximum virtual IRQ number that we support. This
+ * can be set by the platform and will be reduced by the
+ * value of __irq_offset_value. It defaults to and is
+ * capped by (NR_IRQS - 1).
+ */
+extern unsigned int virt_irq_max;
+
/* Create a mapping for a real_irq if it doesn't already exist.
* Return the virtual irq as a convenience.
*/
diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h
index 7c16265568e..c01786ab5fa 100644
--- a/include/asm-powerpc/kdebug.h
+++ b/include/asm-powerpc/kdebug.h
@@ -16,13 +16,9 @@ struct die_args {
int signr;
};
-/*
- Note - you should never unregister because that can race with NMIs.
- If you really want to do it first unregister - then synchronize_sched -
- then free.
- */
-int register_die_notifier(struct notifier_block *nb);
-extern struct notifier_block *powerpc_die_chain;
+extern int register_die_notifier(struct notifier_block *);
+extern int unregister_die_notifier(struct notifier_block *);
+extern struct atomic_notifier_head powerpc_die_chain;
/* Grossly misnamed. */
enum die_val {
@@ -37,7 +33,7 @@ enum die_val {
static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
{
struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig };
- return notifier_call_chain(&powerpc_die_chain, val, &args);
+ return atomic_notifier_call_chain(&powerpc_die_chain, val, &args);
}
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 5348b820788..0f9254c1891 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -47,6 +47,7 @@ struct smp_ops_t {
#endif
struct machdep_calls {
+ char *name;
#ifdef CONFIG_PPC64
void (*hpte_invalidate)(unsigned long slot,
unsigned long va,
@@ -85,9 +86,9 @@ struct machdep_calls {
void (*iommu_dev_setup)(struct pci_dev *dev);
void (*iommu_bus_setup)(struct pci_bus *bus);
void (*irq_bus_setup)(struct pci_bus *bus);
-#endif
+#endif /* CONFIG_PPC64 */
- int (*probe)(int platform);
+ int (*probe)(void);
void (*setup_arch)(void);
void (*init_early)(void);
/* Optional, may be NULL. */
@@ -158,6 +159,12 @@ struct machdep_calls {
/* Idle loop for this platform, leave empty for default idle loop */
void (*idle_loop)(void);
+ /*
+ * Function for waiting for work with reduced power in idle loop;
+ * called with interrupts disabled.
+ */
+ void (*power_save)(void);
+
/* Function to enable performance monitor counters for this
platform, called once per cpu. */
void (*enable_pmcs)(void);
@@ -170,13 +177,6 @@ struct machdep_calls {
May be NULL. */
void (*init)(void);
- void (*idle)(void);
- void (*power_save)(void);
-
- void (*heartbeat)(void);
- unsigned long heartbeat_reset;
- unsigned long heartbeat_count;
-
void (*setup_io_mappings)(void);
void (*early_serial_map)(void);
@@ -208,8 +208,6 @@ struct machdep_calls {
/* Called at then very end of pcibios_init() */
void (*pcibios_after_init)(void);
- /* this is for modules, since _machine can be a define -- Cort */
- int ppc_machine;
#endif /* CONFIG_PPC32 */
/* Called to shutdown machine specific hardware not already controlled
@@ -242,10 +240,33 @@ struct machdep_calls {
#endif /* CONFIG_KEXEC */
};
-extern void default_idle(void);
-extern void native_idle(void);
+extern void power4_idle(void);
+extern void ppc6xx_idle(void);
+/*
+ * ppc_md contains a copy of the machine description structure for the
+ * current platform. machine_id contains the initial address where the
+ * description was found during boot.
+ */
extern struct machdep_calls ppc_md;
+extern struct machdep_calls *machine_id;
+
+#define __machine_desc __attribute__ ((__section__ (".machine.desc")))
+
+#define define_machine(name) \
+ extern struct machdep_calls mach_##name; \
+ EXPORT_SYMBOL(mach_##name); \
+ struct machdep_calls mach_##name __machine_desc =
+
+#define machine_is(name) \
+ ({ \
+ extern struct machdep_calls mach_##name \
+ __attribute__((weak)); \
+ machine_id == &mach_##name; \
+ })
+
+extern void probe_machine(void);
+
extern char cmd_line[COMMAND_LINE_SIZE];
#ifdef CONFIG_PPC_PMAC
diff --git a/include/asm-powerpc/numnodes.h b/include/asm-powerpc/numnodes.h
deleted file mode 100644
index e138edae09d..00000000000
--- a/include/asm-powerpc/numnodes.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _ASM_POWERPC_MAX_NUMNODES_H
-#define _ASM_POWERPC_MAX_NUMNODES_H
-#ifdef __KERNEL__
-
-/* Max 16 Nodes */
-#define NODES_SHIFT 4
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_MAX_NUMNODES_H */
diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h
index 338e6a7cff4..5b33994cd48 100644
--- a/include/asm-powerpc/oprofile_impl.h
+++ b/include/asm-powerpc/oprofile_impl.h
@@ -17,9 +17,6 @@
/* Per-counter configuration as set via oprofilefs. */
struct op_counter_config {
-#ifdef __powerpc64__
- unsigned long valid;
-#endif
unsigned long enabled;
unsigned long event;
unsigned long count;
@@ -38,9 +35,6 @@ struct op_system_config {
#endif
unsigned long enable_kernel;
unsigned long enable_user;
-#ifdef CONFIG_PPC64
- unsigned long backtrace_spinlocks;
-#endif
};
/* Per-arch configuration */
@@ -56,17 +50,12 @@ struct op_powerpc_model {
int num_counters;
};
-#ifdef CONFIG_FSL_BOOKE
extern struct op_powerpc_model op_model_fsl_booke;
-#else /* Otherwise, it's classic */
-
-#ifdef CONFIG_PPC64
extern struct op_powerpc_model op_model_rs64;
extern struct op_powerpc_model op_model_power4;
-
-#else /* Otherwise, CONFIG_PPC32 */
extern struct op_powerpc_model op_model_7450;
-#endif
+
+#ifndef CONFIG_FSL_BOOKE
/* All the classic PPC parts use these */
static inline unsigned int ctr_read(unsigned int i)
@@ -134,5 +123,7 @@ static inline void ctr_write(unsigned int i, unsigned int val)
}
#endif /* !CONFIG_FSL_BOOKE */
+extern void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth);
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_OPROFILE_IMPL_H */
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h
index 4465b95ebef..706325f99a8 100644
--- a/include/asm-powerpc/paca.h
+++ b/include/asm-powerpc/paca.h
@@ -105,5 +105,7 @@ struct paca_struct {
extern struct paca_struct paca[];
+void setup_boot_paca(void);
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_PACA_H */
diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h
index 0b82df483f7..2fbecebe1c9 100644
--- a/include/asm-powerpc/page.h
+++ b/include/asm-powerpc/page.h
@@ -69,8 +69,6 @@
#endif
#ifdef CONFIG_FLATMEM
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#endif
@@ -200,6 +198,7 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr,
struct page *p);
extern int page_is_ram(unsigned long pfn);
+#include <asm-generic/memory_model.h>
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/page_64.h b/include/asm-powerpc/page_64.h
index 3fb061bab9e..eab779c2199 100644
--- a/include/asm-powerpc/page_64.h
+++ b/include/asm-powerpc/page_64.h
@@ -101,6 +101,7 @@ extern unsigned int HPAGE_SHIFT;
- (1U << GET_HTLB_AREA(addr))) & 0xffff)
#define ARCH_HAS_HUGEPAGE_ONLY_RANGE
+#define ARCH_HAS_HUGETLB_FREE_PGD_RANGE
#define ARCH_HAS_PREPARE_HUGEPAGE_RANGE
#define ARCH_HAS_SETCLEAR_HUGE_PTE
diff --git a/include/asm-powerpc/percpu.h b/include/asm-powerpc/percpu.h
index 464301cd0d0..184a7a4d2fd 100644
--- a/include/asm-powerpc/percpu.h
+++ b/include/asm-powerpc/percpu.h
@@ -27,7 +27,7 @@
#define percpu_modcopy(pcpudst, src, size) \
do { \
unsigned int __i; \
- for_each_cpu(__i) \
+ for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset(__i), \
(src), (size)); \
} while (0)
diff --git a/include/asm-powerpc/pgalloc.h b/include/asm-powerpc/pgalloc.h
index a00ee002cd1..9f0917c6865 100644
--- a/include/asm-powerpc/pgalloc.h
+++ b/include/asm-powerpc/pgalloc.h
@@ -17,11 +17,13 @@ extern kmem_cache_t *pgtable_cache[];
#define PTE_CACHE_NUM 0
#define PMD_CACHE_NUM 1
#define PGD_CACHE_NUM 2
+#define HUGEPTE_CACHE_NUM 3
#else
#define PTE_CACHE_NUM 0
#define PMD_CACHE_NUM 1
#define PUD_CACHE_NUM 1
#define PGD_CACHE_NUM 0
+#define HUGEPTE_CACHE_NUM 2
#endif
/*
diff --git a/include/asm-powerpc/pmac_feature.h b/include/asm-powerpc/pmac_feature.h
index 3221628130c..d3599cc9aa7 100644
--- a/include/asm-powerpc/pmac_feature.h
+++ b/include/asm-powerpc/pmac_feature.h
@@ -305,7 +305,7 @@ extern void pmac_feature_init(void);
extern void pmac_set_early_video_resume(void (*proc)(void *data), void *data);
extern void pmac_call_early_video_resume(void);
-#define PMAC_FTR_DEF(x) ((_MACH_Pmac << 16) | (x))
+#define PMAC_FTR_DEF(x) ((0x6660000) | (x))
/* The AGP driver registers itself here */
extern void pmac_register_agp_pm(struct pci_dev *bridge,
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index 1c64a211cf1..93f83efeb31 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -22,22 +22,6 @@
* -- BenH.
*/
-/* Platforms codes (to be obsoleted) */
-#define PLATFORM_PSERIES 0x0100
-#define PLATFORM_PSERIES_LPAR 0x0101
-#define PLATFORM_ISERIES_LPAR 0x0201
-#define PLATFORM_LPAR 0x0001
-#define PLATFORM_POWERMAC 0x0400
-#define PLATFORM_MAPLE 0x0500
-#define PLATFORM_PREP 0x0600
-#define PLATFORM_CHRP 0x0700
-#define PLATFORM_CELL 0x1000
-
-/* Compat platform codes for 32 bits */
-#define _MACH_prep PLATFORM_PREP
-#define _MACH_Pmac PLATFORM_POWERMAC
-#define _MACH_chrp PLATFORM_CHRP
-
/* PREP sub-platform types see residual.h for these */
#define _PREP_Motorola 0x01 /* motorola prep */
#define _PREP_Firm 0x02 /* firmworks prep */
@@ -49,18 +33,14 @@
#define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */
#define _CHRP_Pegasos 0x06 /* Genesi/bplan's Pegasos and Pegasos2 */
-#ifdef __KERNEL__
-#define platform_is_pseries() (_machine == PLATFORM_PSERIES || \
- _machine == PLATFORM_PSERIES_LPAR)
+#if defined(__KERNEL__) && defined(CONFIG_PPC32)
-#if defined(CONFIG_PPC_MULTIPLATFORM)
-extern int _machine;
+extern int _chrp_type;
-#ifdef CONFIG_PPC32
+#ifdef CONFIG_PPC_PREP
/* what kind of prep workstation we are */
extern int _prep_type;
-extern int _chrp_type;
/*
* This is used to identify the board type from a given PReP board
@@ -70,17 +50,14 @@ extern int _chrp_type;
extern unsigned char ucBoardRev;
extern unsigned char ucBoardRevMaj, ucBoardRevMin;
-#endif /* CONFIG_PPC32 */
+#endif /* CONFIG_PPC_PREP */
-#elif defined(CONFIG_PPC_ISERIES)
-/*
- * iSeries is soon to become MULTIPLATFORM hopefully ...
- */
-#define _machine PLATFORM_ISERIES_LPAR
-#else
+#ifndef CONFIG_PPC_MULTIPLATFORM
#define _machine 0
#endif /* CONFIG_PPC_MULTIPLATFORM */
-#endif /* __KERNEL__ */
+
+#endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */
+
/*
* Default implementation of macro that returns current
* instruction pointer ("program counter").
@@ -251,6 +228,10 @@ static inline unsigned long __pack_fe01(unsigned int fpmode)
#define cpu_relax() barrier()
#endif
+/* Check that a certain kernel stack pointer is valid in task_struct p */
+int validate_sp(unsigned long sp, struct task_struct *p,
+ unsigned long nbytes);
+
/*
* Prefetch macros.
*/
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 782e13a070a..97ef1cd71a4 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -149,12 +149,14 @@ extern struct device_node *of_node_get(struct device_node *node);
extern void of_node_put(struct device_node *node);
/* For scanning the flat device-tree at boot time */
-int __init of_scan_flat_dt(int (*it)(unsigned long node,
- const char *uname, int depth,
- void *data),
- void *data);
-void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
- unsigned long *size);
+extern int __init of_scan_flat_dt(int (*it)(unsigned long node,
+ const char *uname, int depth,
+ void *data),
+ void *data);
+extern void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
+ unsigned long *size);
+extern int __init of_flat_dt_is_compatible(unsigned long node, const char *name);
+extern unsigned long __init of_get_flat_dt_root(void);
/* For updating the device tree at runtime */
extern void of_attach_node(struct device_node *);
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 72bfe3af046..bd467bf5cf5 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -622,6 +622,10 @@ extern void ppc64_runlatch_off(void);
extern unsigned long scom970_read(unsigned int address);
extern void scom970_write(unsigned int address, unsigned long value);
+#else
+#define ppc64_runlatch_on()
+#define ppc64_runlatch_off()
+
#endif /* CONFIG_PPC64 */
#define __get_SP() ({unsigned long sp; \
diff --git a/include/asm-powerpc/smp.h b/include/asm-powerpc/smp.h
index 98581e5a827..4a716f707cf 100644
--- a/include/asm-powerpc/smp.h
+++ b/include/asm-powerpc/smp.h
@@ -29,7 +29,6 @@
#endif
extern int boot_cpuid;
-extern int boot_cpuid_phys;
extern void cpu_die(void);
@@ -99,6 +98,7 @@ extern void smp_release_cpus(void);
#else
/* 32-bit */
#ifndef CONFIG_SMP
+extern int boot_cpuid_phys;
#define get_hard_smp_processor_id(cpu) boot_cpuid_phys
#define set_hard_smp_processor_id(cpu, phys)
#endif
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index 38bacf2f6e0..7cfcff3ef02 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -110,12 +110,14 @@ struct spu {
char *name;
unsigned long local_store_phys;
u8 *local_store;
+ unsigned long problem_phys;
struct spu_problem __iomem *problem;
struct spu_priv1 __iomem *priv1;
struct spu_priv2 __iomem *priv2;
struct list_head list;
struct list_head sched_list;
int number;
+ int nid;
u32 isrc;
u32 node;
u64 flags;
@@ -137,6 +139,7 @@ struct spu {
void (* wbox_callback)(struct spu *spu);
void (* ibox_callback)(struct spu *spu);
void (* stop_callback)(struct spu *spu);
+ void (* mfc_callback)(struct spu *spu);
char irq_c0[8];
char irq_c1[8];
@@ -149,6 +152,14 @@ int spu_irq_class_0_bottom(struct spu *spu);
int spu_irq_class_1_bottom(struct spu *spu);
void spu_irq_setaffinity(struct spu *spu, int cpu);
+/* system callbacks from the SPU */
+struct spu_syscall_block {
+ u64 nr_ret;
+ u64 parm[6];
+};
+extern long spu_sys_callback(struct spu_syscall_block *s);
+
+/* syscalls implemented in spufs */
extern struct spufs_calls {
asmlinkage long (*create_thread)(const char __user *name,
unsigned int flags, mode_t mode);
@@ -399,7 +410,6 @@ struct spu_priv1 {
#define SPU_GET_REVISION_BITS(vr) (vr & SPU_REVISION_BITS)
u8 pad_0x28_0x100[0x100 - 0x28]; /* 0x28 */
-
/* Interrupt Area */
u64 int_mask_RW[3]; /* 0x100 */
#define CLASS0_ENABLE_DMA_ALIGNMENT_INTR 0x1L
diff --git a/include/asm-powerpc/syscalls.h b/include/asm-powerpc/syscalls.h
new file mode 100644
index 00000000000..c2fe79d4f90
--- /dev/null
+++ b/include/asm-powerpc/syscalls.h
@@ -0,0 +1,58 @@
+#ifndef __ASM_POWERPC_SYSCALLS_H
+#define __ASM_POWERPC_SYSCALLS_H
+#ifdef __KERNEL__
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <asm/signal.h>
+
+struct new_utsname;
+struct pt_regs;
+struct rtas_args;
+struct sigaction;
+
+asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, off_t offset);
+asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_execve(unsigned long a0, unsigned long a1,
+ unsigned long a2, unsigned long a3, unsigned long a4,
+ unsigned long a5, struct pt_regs *regs);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long usp,
+ int __user *parent_tidp, void __user *child_threadptr,
+ int __user *child_tidp, int p6, struct pt_regs *regs);
+asmlinkage int sys_fork(unsigned long p1, unsigned long p2,
+ unsigned long p3, unsigned long p4, unsigned long p5,
+ unsigned long p6, struct pt_regs *regs);
+asmlinkage int sys_vfork(unsigned long p1, unsigned long p2,
+ unsigned long p3, unsigned long p4, unsigned long p5,
+ unsigned long p6, struct pt_regs *regs);
+asmlinkage int sys_pipe(int __user *fildes);
+asmlinkage long sys_rt_sigaction(int sig,
+ const struct sigaction __user *act,
+ struct sigaction __user *oact, size_t sigsetsize);
+asmlinkage int sys_ipc(uint call, int first, unsigned long second,
+ long third, void __user *ptr, long fifth);
+asmlinkage long ppc64_personality(unsigned long personality);
+asmlinkage int ppc_rtas(struct rtas_args __user *uargs);
+asmlinkage time_t sys64_time(time_t __user * tloc);
+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 65f5a7b2646..d075725bf44 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -365,8 +365,11 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
* powers of 2 writes until it reaches sufficient alignment).
*
* Based on this we disable the IP header alignment in network drivers.
+ * We also modify NET_SKB_PAD to be a cacheline in size, thus maintaining
+ * cacheline alignment of buffers.
*/
-#define NET_IP_ALIGN 0
+#define NET_IP_ALIGN 0
+#define NET_SKB_PAD L1_CACHE_BYTES
#endif
#define arch_align_stack(x) (x)
diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h
index ebf6055481d..6d533b07aaf 100644
--- a/include/asm-powerpc/termbits.h
+++ b/include/asm-powerpc/termbits.h
@@ -153,6 +153,7 @@ struct termios {
#define HUPCL 00040000
#define CLOCAL 00100000
+#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index ffc7462d77b..88b553c6b26 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -37,6 +37,8 @@ struct thread_info {
int preempt_count; /* 0 => preemptable,
<0 => BUG */
struct restart_block restart_block;
+ unsigned long local_flags; /* private flags for thread */
+
/* low level flags - has atomic operations done on it */
unsigned long flags ____cacheline_aligned_in_smp;
};
@@ -143,6 +145,12 @@ static inline struct thread_info *current_thread_info(void)
_TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR)
+/* Bits in local_flags */
+/* Don't move TLF_NAPPING without adjusting the code in entry_32.S */
+#define TLF_NAPPING 0 /* idle thread enabled NAP mode */
+
+#define _TLF_NAPPING (1 << TLF_NAPPING)
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_THREAD_INFO_H */
diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h
index 1e19cd00af2..87362a05542 100644
--- a/include/asm-powerpc/topology.h
+++ b/include/asm-powerpc/topology.h
@@ -4,6 +4,9 @@
#include <linux/config.h>
+struct sys_device;
+struct device_node;
+
#ifdef CONFIG_NUMA
#include <asm/mmzone.h>
@@ -27,6 +30,8 @@ static inline int node_to_first_cpu(int node)
return first_cpu(tmp);
}
+int of_node_to_nid(struct device_node *device);
+
#define pcibus_to_node(node) (-1)
#define pcibus_to_cpumask(bus) (cpu_online_map)
@@ -57,10 +62,29 @@ static inline int node_to_first_cpu(int node)
extern void __init dump_numa_cpu_topology(void);
+extern int sysfs_add_device_to_node(struct sys_device *dev, int nid);
+extern void sysfs_remove_device_from_node(struct sys_device *dev, int nid);
+
#else
+static inline int of_node_to_nid(struct device_node *device)
+{
+ return 0;
+}
+
static inline void dump_numa_cpu_topology(void) {}
+static inline int sysfs_add_device_to_node(struct sys_device *dev, int nid)
+{
+ return 0;
+}
+
+static inline void sysfs_remove_device_from_node(struct sys_device *dev,
+ int nid)
+{
+}
+
+
#include <asm-generic/topology.h>
#endif /* CONFIG_NUMA */
diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h
index 3872e924cdd..d83fc29c2bb 100644
--- a/include/asm-powerpc/uaccess.h
+++ b/include/asm-powerpc/uaccess.h
@@ -7,6 +7,7 @@
#include <linux/sched.h>
#include <linux/errno.h>
#include <asm/processor.h>
+#include <asm/page.h>
#define VERIFY_READ 0
#define VERIFY_WRITE 1
@@ -179,9 +180,11 @@ do { \
#define __put_user_nocheck(x, ptr, size) \
({ \
long __pu_err; \
- might_sleep(); \
+ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
+ if (!is_kernel_addr((unsigned long)__pu_addr)) \
+ might_sleep(); \
__chk_user_ptr(ptr); \
- __put_user_size((x), (ptr), (size), __pu_err); \
+ __put_user_size((x), __pu_addr, (size), __pu_err); \
__pu_err; \
})
@@ -258,9 +261,11 @@ do { \
({ \
long __gu_err; \
unsigned long __gu_val; \
+ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
__chk_user_ptr(ptr); \
- might_sleep(); \
- __get_user_size(__gu_val, (ptr), (size), __gu_err); \
+ if (!is_kernel_addr((unsigned long)__gu_addr)) \
+ might_sleep(); \
+ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
@@ -270,9 +275,11 @@ do { \
({ \
long __gu_err; \
long long __gu_val; \
+ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
__chk_user_ptr(ptr); \
- might_sleep(); \
- __get_user_size(__gu_val, (ptr), (size), __gu_err); \
+ if (!is_kernel_addr((unsigned long)__gu_addr)) \
+ might_sleep(); \
+ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index 35556993f06..edde2462bf5 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -301,8 +301,30 @@
#define __NR_pselect6 280
#define __NR_ppoll 281
#define __NR_unshare 282
+#define __NR_splice 283
+#define __NR_tee 284
+#define __NR_vmsplice 285
+#define __NR_openat 286
+#define __NR_mkdirat 287
+#define __NR_mknodat 288
+#define __NR_fchownat 289
+#define __NR_futimesat 290
+#ifdef __powerpc64__
+#define __NR_newfstatat 291
+#else
+#define __NR_fstatat64 291
+#endif
+#define __NR_unlinkat 292
+#define __NR_renameat 293
+#define __NR_linkat 294
+#define __NR_symlinkat 295
+#define __NR_readlinkat 296
+#define __NR_fchmodat 297
+#define __NR_faccessat 298
+#define __NR_get_robust_list 299
+#define __NR_set_robust_list 300
-#define __NR_syscalls 283
+#define __NR_syscalls 301
#ifdef __KERNEL__
#define __NR__exit __NR_exit
@@ -425,6 +447,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
#include <linux/types.h>
#include <linux/compiler.h>
#include <linux/linkage.h>
+#include <asm/syscalls.h>
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
@@ -454,50 +477,17 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
#ifdef CONFIG_PPC64
#define __ARCH_WANT_COMPAT_SYS_TIME
#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_NEWFSTATAT
#endif
/*
* System call prototypes.
*/
#ifdef __KERNEL_SYSCALLS__
-extern pid_t setsid(void);
-extern int write(int fd, const char *buf, off_t count);
-extern int read(int fd, char *buf, off_t count);
-extern off_t lseek(int fd, off_t offset, int count);
-extern int dup(int fd);
extern int execve(const char *file, char **argv, char **envp);
-extern int open(const char *file, int flag, int mode);
-extern int close(int fd);
-extern pid_t waitpid(pid_t pid, int *wait_stat, int options);
#endif /* __KERNEL_SYSCALLS__ */
/*
- * Functions that implement syscalls.
- */
-unsigned long sys_mmap(unsigned long addr, size_t len, unsigned long prot,
- unsigned long flags, unsigned long fd, off_t offset);
-unsigned long sys_mmap2(unsigned long addr, size_t len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff);
-struct pt_regs;
-int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
- unsigned long a3, unsigned long a4, unsigned long a5,
- struct pt_regs *regs);
-int sys_clone(unsigned long clone_flags, unsigned long usp,
- int __user *parent_tidp, void __user *child_threadptr,
- int __user *child_tidp, int p6, struct pt_regs *regs);
-int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
- unsigned long p4, unsigned long p5, unsigned long p6,
- struct pt_regs *regs);
-int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
- unsigned long p4, unsigned long p5, unsigned long p6,
- struct pt_regs *regs);
-int sys_pipe(int __user *fildes);
-struct sigaction;
-long sys_rt_sigaction(int sig, const struct sigaction __user *act,
- struct sigaction __user *oact, size_t sigsetsize);
-
-/*
* "Conditional" syscalls
*
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
diff --git a/include/asm-powerpc/vdso_datapage.h b/include/asm-powerpc/vdso_datapage.h
index 7aa92086c3f..8a94f0eba5e 100644
--- a/include/asm-powerpc/vdso_datapage.h
+++ b/include/asm-powerpc/vdso_datapage.h
@@ -55,6 +55,9 @@ struct vdso_data {
__u32 minor; /* Minor number 0x14 */
} version;
+ /* Note about the platform flags: it now only contains the lpar
+ * bit. The actual platform number is dead and burried
+ */
__u32 platform; /* Platform flags 0x18 */
__u32 processor; /* Processor type 0x1C */
__u64 processorCount; /* # of physical processors 0x20 */
diff --git a/include/asm-ppc/commproc.h b/include/asm-ppc/commproc.h
index 973e6090823..31f362966a5 100644
--- a/include/asm-ppc/commproc.h
+++ b/include/asm-ppc/commproc.h
@@ -35,6 +35,7 @@
#define CPM_CR_INIT_TX ((ushort)0x0002)
#define CPM_CR_HUNT_MODE ((ushort)0x0003)
#define CPM_CR_STOP_TX ((ushort)0x0004)
+#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
#define CPM_CR_RESTART_TX ((ushort)0x0006)
#define CPM_CR_CLOSE_RX_BD ((ushort)0x0007)
#define CPM_CR_SET_GADDR ((ushort)0x0008)
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
index b638b87cebe..c70344b9104 100644
--- a/include/asm-ppc/cpm2.h
+++ b/include/asm-ppc/cpm2.h
@@ -69,7 +69,7 @@
#define CPM_CR_INIT_TX ((ushort)0x0002)
#define CPM_CR_HUNT_MODE ((ushort)0x0003)
#define CPM_CR_STOP_TX ((ushort)0x0004)
-#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
+#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
#define CPM_CR_RESTART_TX ((ushort)0x0006)
#define CPM_CR_SET_GADDR ((ushort)0x0008)
#define CPM_CR_START_IDMA ((ushort)0x0009)
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index a3e8a45e45a..e1a0a7b213d 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -19,6 +19,18 @@ struct pci_dev;
struct seq_file;
struct file;
+/*
+ * This is for compatibility with ARCH=powerpc.
+ */
+#define machine_is(x) __MACHINE_IS_##x
+#define __MACHINE_IS_powermac 0
+#define __MACHINE_IS_chrp 0
+#ifdef CONFIG_PPC_PREP
+#define __MACHINE_IS_prep 1
+#else
+#define __MACHINE_IS_prep 0
+#endif
+
/* We export this macro for external modules like Alsa to know if
* ppc_md.feature_call is implemented or not
*/
@@ -44,7 +56,7 @@ struct machdep_calls {
void (*power_off)(void);
void (*halt)(void);
- void (*idle)(void);
+ void (*idle_loop)(void);
void (*power_save)(void);
long (*time_init)(void); /* Optional, may be NULL */
@@ -104,9 +116,6 @@ struct machdep_calls {
unsigned long size,
pgprot_t vma_prot);
- /* this is for modules, since _machine can be a define -- Cort */
- int ppc_machine;
-
/* Motherboard/chipset features. This is a kind of general purpose
* hook used to control some machine specific features (like reset
* lines, chip power control, etc...).
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index 6167f74635f..7e9842805a2 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -355,6 +355,7 @@ struct mpc52xx_xlb {
u32 snoop_window; /* XLB + 0x70 */
};
+#define MPC52xx_XLB_CFG_PLDIS (1 << 31)
#define MPC52xx_XLB_CFG_SNOOP (1 << 15)
/* Clock Distribution control */
@@ -427,6 +428,9 @@ extern void mpc52xx_calibrate_decr(void);
extern void mpc52xx_find_bridges(void);
+extern void mpc52xx_setup_cpu(void);
+
+
/* Matching of PSC function */
struct mpc52xx_psc_func {
diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h
index 538e0c8ab24..0fb68a0b018 100644
--- a/include/asm-ppc/page.h
+++ b/include/asm-ppc/page.h
@@ -20,6 +20,7 @@
/* This must match what is in arch/ppc/Makefile */
#define PAGE_OFFSET CONFIG_KERNEL_START
#define KERNELBASE PAGE_OFFSET
+#define is_kernel_addr(x) ((x) >= PAGE_OFFSET)
#ifndef __ASSEMBLY__
@@ -149,8 +150,7 @@ extern int page_is_ram(unsigned long pfn);
#define __pa(x) ___pa((unsigned long)(x))
#define __va(x) ((void *)(___va((unsigned long)(x))))
-#define pfn_to_page(pfn) (mem_map + ((pfn) - PPC_PGSTART))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + PPC_PGSTART)
+#define ARCH_PFN_OFFSET (PPC_PGSTART)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
@@ -175,5 +175,6 @@ extern __inline__ int get_order(unsigned long size)
/* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */
#define __HAVE_ARCH_GATE_AREA 1
+#include <asm-generic/memory_model.h>
#endif /* __KERNEL__ */
#endif /* _PPC_PAGE_H */
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index e1c62da12e7..570b355162f 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -837,7 +837,8 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
*/
#define pgtable_cache_init() do { } while (0)
-extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
+extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep,
+ pmd_t **pmdp);
#include <asm-generic/pgtable.h>
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
index 4b94f7059eb..40f197af650 100644
--- a/include/asm-ppc/ppc_sys.h
+++ b/include/asm-ppc/ppc_sys.h
@@ -39,6 +39,8 @@
#error "need definition of ppc_sys_devices"
#endif
+#define PPC_SYS_IORESOURCE_FIXUPPED 0x00000001
+
struct ppc_sys_spec {
/* PPC sys is matched via (ID & mask) == value, id could be
* PVR, SVR, IMMR, * etc. */
diff --git a/include/asm-ppc/prom.h b/include/asm-ppc/prom.h
index 6d431d6fb02..adc5ae78492 100644
--- a/include/asm-ppc/prom.h
+++ b/include/asm-ppc/prom.h
@@ -8,126 +8,19 @@
#ifndef _PPC_PROM_H
#define _PPC_PROM_H
-#include <linux/config.h>
-#include <linux/types.h>
-
-typedef u32 phandle;
-typedef u32 ihandle;
-
-struct address_range {
- unsigned int space;
- unsigned int address;
- unsigned int size;
-};
-
-struct interrupt_info {
- int line;
- int sense; /* +ve/-ve logic, edge or level, etc. */
-};
-
+/* This is used in arch/ppc/mm/mem_pieces.h */
struct reg_property {
unsigned int address;
unsigned int size;
};
-struct property {
- char *name;
- int length;
- unsigned char *value;
- struct property *next;
-};
-
-/*
- * Note: don't change this structure for now or you'll break BootX !
- */
-struct device_node {
- char *name;
- char *type;
- phandle node;
- int n_addrs;
- struct address_range *addrs;
- int n_intrs;
- struct interrupt_info *intrs;
- char *full_name;
- struct property *properties;
- struct device_node *parent;
- struct device_node *child;
- struct device_node *sibling;
- struct device_node *next; /* next device of same type */
- struct device_node *allnext; /* next in list of all nodes */
-};
-
-struct prom_args;
-typedef void (*prom_entry)(struct prom_args *);
-
-/* OBSOLETE: Old style node lookup */
-extern struct device_node *find_devices(const char *name);
-extern struct device_node *find_type_devices(const char *type);
-extern struct device_node *find_path_device(const char *path);
-extern struct device_node *find_compatible_devices(const char *type,
- const char *compat);
-extern struct device_node *find_all_nodes(void);
-
-/* New style node lookup */
-extern struct device_node *of_find_node_by_name(struct device_node *from,
- const char *name);
-extern struct device_node *of_find_node_by_type(struct device_node *from,
- const char *type);
-extern struct device_node *of_find_compatible_node(struct device_node *from,
- const char *type, const char *compat);
-extern struct device_node *of_find_node_by_path(const char *path);
-extern struct device_node *of_find_all_nodes(struct device_node *prev);
-extern struct device_node *of_get_parent(const struct device_node *node);
-extern struct device_node *of_get_next_child(const struct device_node *node,
- struct device_node *prev);
-extern struct device_node *of_node_get(struct device_node *node);
-extern void of_node_put(struct device_node *node);
-
-/* Other Prototypes */
-extern void abort(void);
-extern unsigned long prom_init(int, int, prom_entry);
-extern void prom_print(const char *msg);
-extern void relocate_nodes(void);
-extern void finish_device_tree(void);
-extern int device_is_compatible(struct device_node *device, const char *);
-extern int machine_is_compatible(const char *compat);
-extern unsigned char *get_property(struct device_node *node, const char *name,
- int *lenp);
-extern int prom_add_property(struct device_node* np, struct property* prop);
-extern void prom_get_irq_senses(unsigned char *, int, int);
-extern int prom_n_addr_cells(struct device_node* np);
-extern int prom_n_size_cells(struct device_node* np);
-
-extern struct resource*
-request_OF_resource(struct device_node* node, int index, const char* name_postfix);
-extern int release_OF_resource(struct device_node* node, int index);
-
-extern void print_properties(struct device_node *node);
-extern int call_rtas(const char *service, int nargs, int nret,
- unsigned long *outputs, ...);
-
/*
- * PCI <-> OF matching functions
- */
-struct pci_bus;
-struct pci_dev;
-extern int pci_device_from_OF_node(struct device_node *node,
- u8* bus, u8* devfn);
-extern struct device_node* pci_busdev_to_OF_node(struct pci_bus *, int);
-extern struct device_node* pci_device_to_OF_node(struct pci_dev *);
-extern void pci_create_OF_bus_map(void);
-
-/*
- * When we call back to the Open Firmware client interface, we usually
- * have to do that before the kernel is relocated to its final location
- * (this is because we can't use OF after we have overwritten the
- * exception vectors with our exception handlers). These macros assist
- * in performing the address calculations that we need to do to access
- * data when the kernel is running at an address that is different from
- * the address that the kernel is linked at. The reloc_offset() function
- * returns the difference between these two addresses and the macros
- * simplify the process of adding or subtracting this offset to/from
- * pointer values. See arch/ppc/kernel/prom.c for how these are used.
+ * These macros assist in performing the address calculations that we
+ * need to do to access data when the kernel is running at an address
+ * that is different from the address that the kernel is linked at.
+ * The reloc_offset() function returns the difference between these
+ * two addresses and the macros simplify the process of adding or
+ * subtracting this offset to/from pointer values.
*/
extern unsigned long reloc_offset(void);
extern unsigned long add_reloc_offset(unsigned long);
@@ -136,45 +29,12 @@ extern unsigned long sub_reloc_offset(unsigned long);
#define PTRRELOC(x) ((typeof(x))add_reloc_offset((unsigned long)(x)))
#define PTRUNRELOC(x) ((typeof(x))sub_reloc_offset((unsigned long)(x)))
-
-/*
- * OF address retreival & translation
- */
-
-
-/* Translate an OF address block into a CPU physical address
- */
-#define OF_BAD_ADDR ((u64)-1)
-extern u64 of_translate_address(struct device_node *np, u32 *addr);
-
-/* Extract an address from a device, returns the region size and
- * the address space flags too. The PCI version uses a BAR number
- * instead of an absolute index
- */
-extern u32 *of_get_address(struct device_node *dev, int index,
- u64 *size, unsigned int *flags);
-extern u32 *of_get_pci_address(struct device_node *dev, int bar_no,
- u64 *size, unsigned int *flags);
-
-/* Get an address as a resource. Note that if your address is
- * a PIO address, the conversion will fail if the physical address
- * can't be internally converted to an IO token with
- * pci_address_to_pio(), that is because it's either called to early
- * or it can't be matched to any host bridge IO space
- */
-extern int of_address_to_resource(struct device_node *dev, int index,
- struct resource *r);
-extern int of_pci_address_to_resource(struct device_node *dev, int bar,
- struct resource *r);
-
-#ifndef CONFIG_PPC_OF
/*
- * Fallback definitions for builds where we don't have prom.c included.
+ * Fallback definitions since we don't support OF in arch/ppc any more.
*/
#define machine_is_compatible(x) 0
#define of_find_compatible_node(f, t, c) NULL
#define get_property(p, n, l) NULL
-#endif
#endif /* _PPC_PROM_H */
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
index 00ad9c754c7..4944c0fb8be 100644
--- a/include/asm-ppc/reg_booke.h
+++ b/include/asm-ppc/reg_booke.h
@@ -237,6 +237,7 @@ do { \
#endif
/* Bit definitions for CCR1. */
+#define CCR1_DPC 0x00000100 /* Disable L1 I-Cache/D-Cache parity checking */
#define CCR1_TCS 0x00000080 /* Timer Clock Select */
/* Bit definitions for the MCSR. */
diff --git a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h
index 485a924e4d0..b74af546156 100644
--- a/include/asm-ppc/serial.h
+++ b/include/asm-ppc/serial.h
@@ -41,15 +41,10 @@
#else
/*
- * XXX Assume for now it has PC-style ISA serial ports.
- * This is true for PReP and CHRP at least.
+ * XXX Assume it has PC-style ISA serial ports - true for PReP at least.
*/
#include <asm/pc_serial.h>
-#if defined(CONFIG_MAC_SERIAL)
-#define SERIAL_DEV_OFFSET ((_machine == _MACH_prep || _machine == _MACH_chrp) ? 0 : 2)
-#endif
-
#endif /* !CONFIG_GEMINI and others */
#endif /* __ASM_SERIAL_H__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index de1d9926aa6..399bf02894d 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -1,6 +1,8 @@
#ifndef __ARCH_S390_ATOMIC__
#define __ARCH_S390_ATOMIC__
+#include <linux/compiler.h>
+
/*
* include/asm-s390/atomic.h
*
diff --git a/include/asm-s390/cache.h b/include/asm-s390/cache.h
index e20cdd9074d..cdf431b061b 100644
--- a/include/asm-s390/cache.h
+++ b/include/asm-s390/cache.h
@@ -16,4 +16,6 @@
#define ARCH_KMALLOC_MINALIGN 8
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+
#endif
diff --git a/include/asm-s390/compat.h b/include/asm-s390/compat.h
index a007715f4ae..356a0b18353 100644
--- a/include/asm-s390/compat.h
+++ b/include/asm-s390/compat.h
@@ -128,6 +128,11 @@ static inline void __user *compat_ptr(compat_uptr_t uptr)
return (void __user *)(unsigned long)(uptr & 0x7fffffffUL);
}
+static inline compat_uptr_t ptr_to_compat(void __user *uptr)
+{
+ return (u32)(unsigned long)uptr;
+}
+
static inline void __user *compat_alloc_user_space(long len)
{
unsigned long stack;
diff --git a/include/asm-s390/ebcdic.h b/include/asm-s390/ebcdic.h
index 4cbc336e4d6..15fd2eda6c9 100644
--- a/include/asm-s390/ebcdic.h
+++ b/include/asm-s390/ebcdic.h
@@ -14,12 +14,12 @@
#include <types.h>
#endif
-extern __u8 _ascebc_500[]; /* ASCII -> EBCDIC 500 conversion table */
-extern __u8 _ebcasc_500[]; /* EBCDIC 500 -> ASCII conversion table */
-extern __u8 _ascebc[]; /* ASCII -> EBCDIC conversion table */
-extern __u8 _ebcasc[]; /* EBCDIC -> ASCII conversion table */
-extern __u8 _ebc_tolower[]; /* EBCDIC -> lowercase */
-extern __u8 _ebc_toupper[]; /* EBCDIC -> uppercase */
+extern __u8 _ascebc_500[256]; /* ASCII -> EBCDIC 500 conversion table */
+extern __u8 _ebcasc_500[256]; /* EBCDIC 500 -> ASCII conversion table */
+extern __u8 _ascebc[256]; /* ASCII -> EBCDIC conversion table */
+extern __u8 _ebcasc[256]; /* EBCDIC -> ASCII conversion table */
+extern __u8 _ebc_tolower[256]; /* EBCDIC -> lowercase */
+extern __u8 _ebc_toupper[256]; /* EBCDIC -> uppercase */
static inline void
codepage_convert(const __u8 *codepage, volatile __u8 * addr, unsigned long nr)
diff --git a/include/asm-s390/futex.h b/include/asm-s390/futex.h
index 6a332a9f099..1802775568b 100644
--- a/include/asm-s390/futex.h
+++ b/include/asm-s390/futex.h
@@ -1,6 +1,122 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
+#ifndef _ASM_S390_FUTEX_H
+#define _ASM_S390_FUTEX_H
-#include <asm-generic/futex.h>
+#ifdef __KERNEL__
-#endif
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+#ifndef __s390x__
+#define __futex_atomic_fixup \
+ ".section __ex_table,\"a\"\n" \
+ " .align 4\n" \
+ " .long 0b,4b,2b,4b,3b,4b\n" \
+ ".previous"
+#else /* __s390x__ */
+#define __futex_atomic_fixup \
+ ".section __ex_table,\"a\"\n" \
+ " .align 8\n" \
+ " .quad 0b,4b,2b,4b,3b,4b\n" \
+ ".previous"
+#endif /* __s390x__ */
+
+#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg) \
+ asm volatile(" sacf 256\n" \
+ "0: l %1,0(%6)\n" \
+ "1: " insn \
+ "2: cs %1,%2,0(%6)\n" \
+ "3: jl 1b\n" \
+ " lhi %0,0\n" \
+ "4: sacf 0\n" \
+ __futex_atomic_fixup \
+ : "=d" (ret), "=&d" (oldval), "=&d" (newval), \
+ "=m" (*uaddr) \
+ : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
+ "m" (*uaddr) : "cc" );
+
+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, newval, ret;
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+ oparg = 1 << oparg;
+
+ if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ inc_preempt_count();
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ __futex_atomic_op("lr %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ADD:
+ __futex_atomic_op("lr %2,%1\nar %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ case FUTEX_OP_OR:
+ __futex_atomic_op("lr %2,%1\nor %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ANDN:
+ __futex_atomic_op("lr %2,%1\nnr %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ case FUTEX_OP_XOR:
+ __futex_atomic_op("lr %2,%1\nxr %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+
+ dec_preempt_count();
+
+ if (!ret) {
+ switch (cmp) {
+ case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+ case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+ case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+ case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+ case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+ case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+ default: ret = -ENOSYS;
+ }
+ }
+ return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ int ret;
+
+ if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+ asm volatile(" cs %1,%4,0(%5)\n"
+ "0: lr %0,%1\n"
+ "1:\n"
+#ifndef __s390x__
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 0b,1b\n"
+ ".previous"
+#else /* __s390x__ */
+ ".section __ex_table,\"a\"\n"
+ " .align 8\n"
+ " .quad 0b,1b\n"
+ ".previous"
+#endif /* __s390x__ */
+ : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
+ : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
+ : "cc", "memory" );
+ return oldval;
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_S390_FUTEX_H */
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index db0606c1abd..bea72790428 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -98,8 +98,8 @@
#define __LC_KERNEL_ASCE 0xD58
#define __LC_USER_ASCE 0xD60
#define __LC_PANIC_STACK 0xD68
-#define __LC_CPUID 0xD90
-#define __LC_CPUADDR 0xD98
+#define __LC_CPUID 0xD80
+#define __LC_CPUADDR 0xD88
#define __LC_IPLDEV 0xDB8
#define __LC_JIFFY_TIMER 0xDC0
#define __LC_CURRENT 0xDD8
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index 2430c561e02..3b1138ac7e7 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -181,8 +181,6 @@ page_get_storage_key(unsigned long addr)
#define PAGE_OFFSET 0x0UL
#define __pa(x) (unsigned long)(x)
#define __va(x) (void *)(unsigned long)(x)
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_valid(pfn) ((pfn) < max_mapnr)
@@ -193,6 +191,7 @@ page_get_storage_key(unsigned long addr)
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _S390_PAGE_H */
diff --git a/include/asm-s390/percpu.h b/include/asm-s390/percpu.h
index e10ed87094f..436d216601e 100644
--- a/include/asm-s390/percpu.h
+++ b/include/asm-s390/percpu.h
@@ -46,7 +46,7 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
#define percpu_modcopy(pcpudst, src, size) \
do { \
unsigned int __i; \
- for_each_cpu(__i) \
+ for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset[__i], \
(src), (size)); \
} while (0)
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index 657d582e814..41c2792ff6b 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -296,8 +296,14 @@
#define __NR_pselect6 301
#define __NR_ppoll 302
#define __NR_unshare 303
+#define __NR_set_robust_list 304
+#define __NR_get_robust_list 305
+#define __NR_splice 306
+#define __NR_sync_file_range 307
+#define __NR_tee 308
+#define __NR_vmsplice 309
-#define NR_syscalls 304
+#define NR_syscalls 310
/*
* There are some system calls that are not present on 64 bit, some
diff --git a/include/asm-sh/addrspace.h b/include/asm-sh/addrspace.h
index dbb05d1a26d..720afc11c2c 100644
--- a/include/asm-sh/addrspace.h
+++ b/include/asm-sh/addrspace.h
@@ -13,7 +13,7 @@
#include <asm/cpu/addrspace.h>
-/* Memory segments (32bit Priviledged mode addresses) */
+/* Memory segments (32bit Privileged mode addresses) */
#define P0SEG 0x00000000
#define P1SEG 0x80000000
#define P2SEG 0xa0000000
diff --git a/include/asm-sh/numnodes.h b/include/asm-sh/numnodes.h
deleted file mode 100644
index f73e85b72ec..00000000000
--- a/include/asm-sh/numnodes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-/* Max 2 Nodes */
-#define NODES_SHIFT 1
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 972c3f655b2..9c89287c3e5 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -105,9 +105,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/* PFN start number, because of __MEMORY_START */
#define PFN_START (__MEMORY_START >> PAGE_SHIFT)
-
-#define pfn_to_page(pfn) (mem_map + (pfn) - PFN_START)
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + PFN_START)
+#define ARCH_PFN_OFFSET (FPN_START)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_valid(pfn) (((pfn) - PFN_START) < max_mapnr)
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
@@ -117,6 +115,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* __ASM_SH_PAGE_H */
diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
index f2c8e14d1fd..05520cebda1 100644
--- a/include/asm-sh/unistd.h
+++ b/include/asm-sh/unistd.h
@@ -290,7 +290,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
+#define __NR_kexec_load 283
#define __NR_waitid 284
#define __NR_add_key 285
#define __NR_request_key 286
diff --git a/include/asm-sh64/page.h b/include/asm-sh64/page.h
index c86df90f7cb..e4937cdabeb 100644
--- a/include/asm-sh64/page.h
+++ b/include/asm-sh64/page.h
@@ -105,9 +105,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/* PFN start number, because of __MEMORY_START */
#define PFN_START (__MEMORY_START >> PAGE_SHIFT)
-
-#define pfn_to_page(pfn) (mem_map + (pfn) - PFN_START)
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + PFN_START)
+#define ARCH_PFN_OFFSET (PFN_START)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_valid(pfn) (((pfn) - PFN_START) < max_mapnr)
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
@@ -117,6 +115,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* __ASM_SH64_PAGE_H */
diff --git a/include/asm-sh64/platform.h b/include/asm-sh64/platform.h
index 7046a901402..bd0d9c405a8 100644
--- a/include/asm-sh64/platform.h
+++ b/include/asm-sh64/platform.h
@@ -61,9 +61,4 @@ extern int platform_int_priority[NR_INTC_IRQS];
#define code_resource (platform_parms.kram_res_p[STANDARD_KRAM_RESOURCES - 2])
#define data_resource (platform_parms.kram_res_p[STANDARD_KRAM_RESOURCES - 1])
-/* Be prepared to 64-bit sign extensions */
-#define PFN_UP(x) ((((x) + PAGE_SIZE-1) >> PAGE_SHIFT) & 0x000fffff)
-#define PFN_DOWN(x) (((x) >> PAGE_SHIFT) & 0x000fffff)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
-
#endif /* __ASM_SH64_PLATFORM_H */
diff --git a/include/asm-sh64/unistd.h b/include/asm-sh64/unistd.h
index 2a1cfa404ea..1f8f394ae37 100644
--- a/include/asm-sh64/unistd.h
+++ b/include/asm-sh64/unistd.h
@@ -333,7 +333,7 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 311
+#define __NR_kexec_load 311
#define __NR_waitid 312
#define __NR_add_key 313
#define __NR_request_key 314
diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h
index 9122684f6c1..ec3274b7ddf 100644
--- a/include/asm-sparc/page.h
+++ b/include/asm-sparc/page.h
@@ -152,8 +152,7 @@ extern unsigned long pfn_base;
#define virt_to_phys __pa
#define phys_to_virt __va
-#define pfn_to_page(pfn) (mem_map + ((pfn)-(pfn_base)))
-#define page_to_pfn(page) ((unsigned long)(((page) - mem_map) + pfn_base))
+#define ARCH_PFN_OFFSET (pfn_base)
#define virt_to_page(kaddr) (mem_map + ((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT)))
#define pfn_valid(pfn) (((pfn) >= (pfn_base)) && (((pfn)-(pfn_base)) < max_mapnr))
@@ -164,6 +163,7 @@ extern unsigned long pfn_base;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _SPARC_PAGE_H */
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index 64ec640a40e..45a57650778 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -41,7 +41,7 @@
#define __NR_capset 22 /* Linux Specific */
#define __NR_setuid 23 /* Implemented via setreuid in SunOS */
#define __NR_getuid 24 /* Common */
-/* #define __NR_time alias 25 ENOSYS under SunOS */
+#define __NR_vmsplice 25 /* ENOSYS under SunOS */
#define __NR_ptrace 26 /* Common */
#define __NR_alarm 27 /* Implemented via setitimer in SunOS */
#define __NR_sigaltstack 28 /* Common */
@@ -180,7 +180,7 @@
#define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS */
#define __NR_getdomainname 162 /* SunOS Specific */
#define __NR_setdomainname 163 /* Common */
-/* #define __NR_ni_syscall 164 ENOSYS under SunOS */
+/* #define __NR_utrap_install 164 Linux sparc64 specific */
#define __NR_quotactl 165 /* Common */
#define __NR_set_tid_address 166 /* Linux specific, exportfs under SunOS */
#define __NR_mount 167 /* Common */
@@ -248,7 +248,7 @@
#define __NR_setfsgid 229 /* Linux Specific */
#define __NR__newselect 230 /* Linux Specific */
#define __NR_time 231 /* Linux Specific */
-/* #define __NR_oldstat 232 Linux Specific */
+#define __NR_splice 232 /* Linux Specific */
#define __NR_stime 233 /* Linux Specific */
#define __NR_statfs64 234 /* Linux Specific */
#define __NR_fstatfs64 235 /* Linux Specific */
@@ -271,7 +271,7 @@
#define __NR_getsid 252
#define __NR_fdatasync 253
#define __NR_nfsservctl 254
-#define __NR_aplib 255
+#define __NR_sync_file_range 255
#define __NR_clock_settime 256
#define __NR_clock_gettime 257
#define __NR_clock_getres 258
@@ -296,7 +296,7 @@
#define __NR_mq_notify 277
#define __NR_mq_getsetattr 278
#define __NR_waitid 279
-#define __NR_sys_setaltroot 280
+#define __NR_tee 280
#define __NR_add_key 281
#define __NR_request_key 282
#define __NR_keyctl 283
@@ -316,11 +316,13 @@
#define __NR_pselect6 297
#define __NR_ppoll 298
#define __NR_unshare 299
+#define __NR_set_robust_list 300
+#define __NR_get_robust_list 301
-/* WARNING: You MAY NOT add syscall numbers larger than 299, since
+/* WARNING: You MAY NOT add syscall numbers larger than 301, since
* all of the syscall tables in the Sparc kernel are
- * sized to have 299 entries (starting at zero). Therefore
- * find a free slot in the 0-299 range.
+ * sized to have 301 entries (starting at zero). Therefore
+ * find a free slot in the 0-301 range.
*/
#define _syscall0(type,name) \
diff --git a/include/asm-sparc/vga.h b/include/asm-sparc/vga.h
new file mode 100644
index 00000000000..c69d5b2ba19
--- /dev/null
+++ b/include/asm-sparc/vga.h
@@ -0,0 +1,33 @@
+/*
+ * Access to VGA videoram
+ *
+ * (c) 1998 Martin Mares <mj@ucw.cz>
+ */
+
+#ifndef _LINUX_ASM_VGA_H_
+#define _LINUX_ASM_VGA_H_
+
+#include <asm/types.h>
+
+#define VT_BUF_HAVE_RW
+
+#undef scr_writew
+#undef scr_readw
+
+static inline void scr_writew(u16 val, u16 *addr)
+{
+ BUG_ON((long) addr >= 0);
+
+ *addr = val;
+}
+
+static inline u16 scr_readw(const u16 *addr)
+{
+ BUG_ON((long) addr >= 0);
+
+ return *addr;
+}
+
+#define VGA_MAP_MEM(x,s) (x)
+
+#endif
diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h
index c7d5804ba76..a8d39f23d43 100644
--- a/include/asm-sparc64/dma-mapping.h
+++ b/include/asm-sparc64/dma-mapping.h
@@ -4,7 +4,146 @@
#include <linux/config.h>
#ifdef CONFIG_PCI
-#include <asm-generic/dma-mapping.h>
+
+/* we implement the API below in terms of the existing PCI one,
+ * so include it */
+#include <linux/pci.h>
+/* need struct page definitions */
+#include <linux/mm.h>
+
+static inline int
+dma_supported(struct device *dev, u64 mask)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ return pci_dma_supported(to_pci_dev(dev), mask);
+}
+
+static inline int
+dma_set_mask(struct device *dev, u64 dma_mask)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
+}
+
+static inline void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ gfp_t flag)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ return pci_iommu_ops->alloc_consistent(to_pci_dev(dev), size, dma_handle, flag);
+}
+
+static inline void
+dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t dma_handle)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
+}
+
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
+}
+
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
+}
+
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
+}
+
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
+}
+
+static inline int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
+}
+
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+ enum dma_data_direction direction)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
+}
+
+static inline void
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
+ size, (int)direction);
+}
+
+static inline void
+dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
+ size, (int)direction);
+}
+
+static inline void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction);
+}
+
+static inline void
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ BUG_ON(dev->bus != &pci_bus_type);
+
+ pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
+}
+
+static inline int
+dma_mapping_error(dma_addr_t dma_addr)
+{
+ return pci_dma_mapping_error(dma_addr);
+}
+
#else
struct device;
diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h
index 49d49a28594..6a95d5d0c57 100644
--- a/include/asm-sparc64/floppy.h
+++ b/include/asm-sparc64/floppy.h
@@ -738,7 +738,7 @@ static unsigned long __init sun_floppy_init(void)
if (!sun_floppy_types[0] && sun_floppy_types[1]) {
/*
* Set the drive exchange bit in FCR on NS87303,
- * make shure other bits are sane before doing so.
+ * make sure other bits are sane before doing so.
*/
ns87303_modify(config, FER, FER_EDM, 0);
ns87303_modify(config, ASC, ASC_DRV2_SEL, 0);
diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h
index 34c4b43d3f9..dee40206b22 100644
--- a/include/asm-sparc64/futex.h
+++ b/include/asm-sparc64/futex.h
@@ -83,4 +83,28 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
return ret;
}
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ __asm__ __volatile__(
+ "\n1: lduwa [%2] %%asi, %0\n"
+ "2: casa [%2] %%asi, %0, %1\n"
+ "3:\n"
+ " .section .fixup,#alloc,#execinstr\n"
+ " .align 4\n"
+ "4: ba 3b\n"
+ " mov %3, %0\n"
+ " .previous\n"
+ " .section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .word 1b, 4b\n"
+ " .word 2b, 4b\n"
+ " .previous\n"
+ : "=&r" (oldval)
+ : "r" (newval), "r" (uaddr), "i" (-EFAULT)
+ : "memory");
+
+ return oldval;
+}
+
#endif /* !(_SPARC64_FUTEX_H) */
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
index 6321f5a0198..4040d127ac3 100644
--- a/include/asm-sparc64/kdebug.h
+++ b/include/asm-sparc64/kdebug.h
@@ -15,12 +15,9 @@ struct die_args {
int signr;
};
-/* Note - you should never unregister because that can race with NMIs.
- * If you really want to do it first unregister - then synchronize_sched
- * - then free.
- */
-int register_die_notifier(struct notifier_block *nb);
-extern struct notifier_block *sparc64die_chain;
+extern int register_die_notifier(struct notifier_block *);
+extern int unregister_die_notifier(struct notifier_block *);
+extern struct atomic_notifier_head sparc64die_chain;
extern void bad_trap(struct pt_regs *, long);
@@ -46,7 +43,7 @@ static inline int notify_die(enum die_val val,char *str, struct pt_regs *regs,
.trapnr = trap,
.signr = sig };
- return notifier_call_chain(&sparc64die_chain, val, &args);
+ return atomic_notifier_call_chain(&sparc64die_chain, val, &args);
}
#endif
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h
index 66fe4ac59fd..aabb2190672 100644
--- a/include/asm-sparc64/page.h
+++ b/include/asm-sparc64/page.h
@@ -111,6 +111,8 @@ typedef unsigned long pgprot_t;
(_AC(0x0000000070000000,UL)) : \
(_AC(0xfffff80000000000,UL) + (1UL << 32UL)))
+#include <asm-generic/memory_model.h>
+
#endif /* !(__ASSEMBLY__) */
/* to align the pointer to the (next) page boundary */
diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h
index 7c5a589ea43..e1ea67bc32f 100644
--- a/include/asm-sparc64/pci.h
+++ b/include/asm-sparc64/pci.h
@@ -42,7 +42,7 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
struct pci_dev;
struct pci_iommu_ops {
- void *(*alloc_consistent)(struct pci_dev *, size_t, dma_addr_t *);
+ void *(*alloc_consistent)(struct pci_dev *, size_t, dma_addr_t *, gfp_t);
void (*free_consistent)(struct pci_dev *, size_t, void *, dma_addr_t);
dma_addr_t (*map_single)(struct pci_dev *, void *, size_t, int);
void (*unmap_single)(struct pci_dev *, dma_addr_t, size_t, int);
@@ -59,7 +59,7 @@ extern struct pci_iommu_ops *pci_iommu_ops;
*/
static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
{
- return pci_iommu_ops->alloc_consistent(hwdev, size, dma_handle);
+ return pci_iommu_ops->alloc_consistent(hwdev, size, dma_handle, GFP_ATOMIC);
}
/* Free and unmap a consistent DMA buffer.
diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
index 82032e159a7..baef13b5895 100644
--- a/include/asm-sparc64/percpu.h
+++ b/include/asm-sparc64/percpu.h
@@ -26,7 +26,7 @@ register unsigned long __local_per_cpu_offset asm("g5");
#define percpu_modcopy(pcpudst, src, size) \
do { \
unsigned int __i; \
- for_each_cpu(__i) \
+ for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset(__i), \
(src), (size)); \
} while (0)
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index c44e7466534..cd464f469a2 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -689,6 +689,23 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *p
#define pte_clear(mm,addr,ptep) \
set_pte_at((mm), (addr), (ptep), __pte(0UL))
+#ifdef DCACHE_ALIASING_POSSIBLE
+#define __HAVE_ARCH_MOVE_PTE
+#define move_pte(pte, prot, old_addr, new_addr) \
+({ \
+ pte_t newpte = (pte); \
+ if (tlb_type != hypervisor && pte_present(pte)) { \
+ unsigned long this_pfn = pte_pfn(pte); \
+ \
+ if (pfn_valid(this_pfn) && \
+ (((old_addr) ^ (new_addr)) & (1 << 13))) \
+ flush_dcache_page_all(current->mm, \
+ pfn_to_page(this_pfn)); \
+ } \
+ newpte; \
+})
+#endif
+
extern pgd_t swapper_pg_dir[2048];
extern pmd_t swapper_low_pmd_dir[2048];
diff --git a/include/asm-sparc64/tlbflush.h b/include/asm-sparc64/tlbflush.h
index 9ad5d9c51d4..e3a7c453b50 100644
--- a/include/asm-sparc64/tlbflush.h
+++ b/include/asm-sparc64/tlbflush.h
@@ -22,8 +22,6 @@ extern void flush_tlb_pending(void);
/* Local cpu only. */
extern void __flush_tlb_all(void);
-extern void __flush_tlb_page(unsigned long context, unsigned long page, unsigned long r);
-
extern void __flush_tlb_kernel_range(unsigned long start, unsigned long end);
#ifndef CONFIG_SMP
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index a284986b154..998ef4ab0e0 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -41,7 +41,7 @@
#define __NR_capset 22 /* Linux Specific */
#define __NR_setuid 23 /* Implemented via setreuid in SunOS */
#define __NR_getuid 24 /* Common */
-/* #define __NR_time alias 25 ENOSYS under SunOS */
+#define __NR_vmsplice 25 /* ENOSYS under SunOS */
#define __NR_ptrace 26 /* Common */
#define __NR_alarm 27 /* Implemented via setitimer in SunOS */
#define __NR_sigaltstack 28 /* Common */
@@ -250,7 +250,7 @@
#ifdef __KERNEL__
#define __NR_time 231 /* Linux sparc32 */
#endif
-/* #define __NR_oldstat 232 Linux Specific */
+#define __NR_splice 232 /* Linux Specific */
#define __NR_stime 233 /* Linux Specific */
#define __NR_statfs64 234 /* Linux Specific */
#define __NR_fstatfs64 235 /* Linux Specific */
@@ -273,7 +273,7 @@
#define __NR_getsid 252
#define __NR_fdatasync 253
#define __NR_nfsservctl 254
-#define __NR_aplib 255
+#define __NR_sync_file_range 255
#define __NR_clock_settime 256
#define __NR_clock_gettime 257
#define __NR_clock_getres 258
@@ -298,7 +298,7 @@
#define __NR_mq_notify 277
#define __NR_mq_getsetattr 278
#define __NR_waitid 279
-/*#define __NR_sys_setaltroot 280 available (was setaltroot) */
+#define __NR_tee 280
#define __NR_add_key 281
#define __NR_request_key 282
#define __NR_keyctl 283
@@ -318,11 +318,13 @@
#define __NR_pselect6 297
#define __NR_ppoll 298
#define __NR_unshare 299
+#define __NR_set_robust_list 300
+#define __NR_get_robust_list 301
-/* WARNING: You MAY NOT add syscall numbers larger than 299, since
+/* WARNING: You MAY NOT add syscall numbers larger than 301, since
* all of the syscall tables in the Sparc kernel are
- * sized to have 299 entries (starting at zero). Therefore
- * find a free slot in the 0-299 range.
+ * sized to have 301 entries (starting at zero). Therefore
+ * find a free slot in the 0-301 range.
*/
#define _syscall0(type,name) \
diff --git a/include/asm-um/desc.h b/include/asm-um/desc.h
index ac1d2a20d17..4ec34a51b62 100644
--- a/include/asm-um/desc.h
+++ b/include/asm-um/desc.h
@@ -1,6 +1,16 @@
#ifndef __UM_DESC_H
#define __UM_DESC_H
-#include "asm/arch/desc.h"
+/* Taken from asm-i386/desc.h, it's the only thing we need. The rest wouldn't
+ * compile, and has never been used. */
+#define LDT_empty(info) (\
+ (info)->base_addr == 0 && \
+ (info)->limit == 0 && \
+ (info)->contents == 0 && \
+ (info)->read_exec_only == 1 && \
+ (info)->seg_32bit == 0 && \
+ (info)->limit_in_pages == 0 && \
+ (info)->seg_not_present == 1 && \
+ (info)->useable == 0 )
#endif
diff --git a/include/asm-um/host_ldt-i386.h b/include/asm-um/host_ldt-i386.h
new file mode 100644
index 00000000000..b27cb0a9dd3
--- /dev/null
+++ b/include/asm-um/host_ldt-i386.h
@@ -0,0 +1,34 @@
+#ifndef __ASM_HOST_LDT_I386_H
+#define __ASM_HOST_LDT_I386_H
+
+#include "asm/arch/ldt.h"
+
+/*
+ * macros stolen from include/asm-i386/desc.h
+ */
+#define LDT_entry_a(info) \
+ ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+
+#define LDT_entry_b(info) \
+ (((info)->base_addr & 0xff000000) | \
+ (((info)->base_addr & 0x00ff0000) >> 16) | \
+ ((info)->limit & 0xf0000) | \
+ (((info)->read_exec_only ^ 1) << 9) | \
+ ((info)->contents << 10) | \
+ (((info)->seg_not_present ^ 1) << 15) | \
+ ((info)->seg_32bit << 22) | \
+ ((info)->limit_in_pages << 23) | \
+ ((info)->useable << 20) | \
+ 0x7000)
+
+#define LDT_empty(info) (\
+ (info)->base_addr == 0 && \
+ (info)->limit == 0 && \
+ (info)->contents == 0 && \
+ (info)->read_exec_only == 1 && \
+ (info)->seg_32bit == 0 && \
+ (info)->limit_in_pages == 0 && \
+ (info)->seg_not_present == 1 && \
+ (info)->useable == 0 )
+
+#endif
diff --git a/include/asm-um/ldt-x86_64.h b/include/asm-um/host_ldt-x86_64.h
index 96b35aada79..74a63f7d9a9 100644
--- a/include/asm-um/ldt-x86_64.h
+++ b/include/asm-um/host_ldt-x86_64.h
@@ -1,43 +1,8 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Licensed under the GPL
- *
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- */
+#ifndef __ASM_HOST_LDT_X86_64_H
+#define __ASM_HOST_LDT_X86_64_H
-#ifndef __ASM_LDT_X86_64_H
-#define __ASM_LDT_X86_64_H
-
-#include "asm/semaphore.h"
#include "asm/arch/ldt.h"
-struct mmu_context_skas;
-extern void ldt_host_info(void);
-extern long init_new_ldt(struct mmu_context_skas * to_mm,
- struct mmu_context_skas * from_mm);
-extern void free_ldt(struct mmu_context_skas * mm);
-
-#define LDT_PAGES_MAX \
- ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
-#define LDT_ENTRIES_PER_PAGE \
- (PAGE_SIZE/LDT_ENTRY_SIZE)
-#define LDT_DIRECT_ENTRIES \
- ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
-
-struct ldt_entry {
- __u32 a;
- __u32 b;
-};
-
-typedef struct uml_ldt {
- int entry_count;
- struct semaphore semaphore;
- union {
- struct ldt_entry * pages[LDT_PAGES_MAX];
- struct ldt_entry entries[LDT_DIRECT_ENTRIES];
- } u;
-} uml_ldt_t;
-
/*
* macros stolen from include/asm-x86_64/desc.h
*/
diff --git a/include/asm-um/irqflags.h b/include/asm-um/irqflags.h
new file mode 100644
index 00000000000..659b9abdfdb
--- /dev/null
+++ b/include/asm-um/irqflags.h
@@ -0,0 +1,6 @@
+#ifndef __UM_IRQFLAGS_H
+#define __UM_IRQFLAGS_H
+
+/* Empty for now */
+
+#endif
diff --git a/include/asm-um/ldt-i386.h b/include/asm-um/ldt-i386.h
deleted file mode 100644
index 175722a9116..00000000000
--- a/include/asm-um/ldt-i386.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Licensed under the GPL
- *
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- */
-
-#ifndef __ASM_LDT_I386_H
-#define __ASM_LDT_I386_H
-
-#include "asm/semaphore.h"
-#include "asm/arch/ldt.h"
-
-struct mmu_context_skas;
-extern void ldt_host_info(void);
-extern long init_new_ldt(struct mmu_context_skas * to_mm,
- struct mmu_context_skas * from_mm);
-extern void free_ldt(struct mmu_context_skas * mm);
-
-#define LDT_PAGES_MAX \
- ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
-#define LDT_ENTRIES_PER_PAGE \
- (PAGE_SIZE/LDT_ENTRY_SIZE)
-#define LDT_DIRECT_ENTRIES \
- ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
-
-struct ldt_entry {
- __u32 a;
- __u32 b;
-};
-
-typedef struct uml_ldt {
- int entry_count;
- struct semaphore semaphore;
- union {
- struct ldt_entry * pages[LDT_PAGES_MAX];
- struct ldt_entry entries[LDT_DIRECT_ENTRIES];
- } u;
-} uml_ldt_t;
-
-/*
- * macros stolen from include/asm-i386/desc.h
- */
-#define LDT_entry_a(info) \
- ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-#define LDT_entry_b(info) \
- (((info)->base_addr & 0xff000000) | \
- (((info)->base_addr & 0x00ff0000) >> 16) | \
- ((info)->limit & 0xf0000) | \
- (((info)->read_exec_only ^ 1) << 9) | \
- ((info)->contents << 10) | \
- (((info)->seg_not_present ^ 1) << 15) | \
- ((info)->seg_32bit << 22) | \
- ((info)->limit_in_pages << 23) | \
- ((info)->useable << 20) | \
- 0x7000)
-
-#define LDT_empty(info) (\
- (info)->base_addr == 0 && \
- (info)->limit == 0 && \
- (info)->contents == 0 && \
- (info)->read_exec_only == 1 && \
- (info)->seg_32bit == 0 && \
- (info)->limit_in_pages == 0 && \
- (info)->seg_not_present == 1 && \
- (info)->useable == 0 )
-
-#endif
diff --git a/include/asm-um/ldt.h b/include/asm-um/ldt.h
new file mode 100644
index 00000000000..96f82a456ce
--- /dev/null
+++ b/include/asm-um/ldt.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Licensed under the GPL
+ *
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ */
+
+#ifndef __ASM_LDT_H
+#define __ASM_LDT_H
+
+#include "asm/semaphore.h"
+#include "asm/host_ldt.h"
+
+struct mmu_context_skas;
+extern void ldt_host_info(void);
+extern long init_new_ldt(struct mmu_context_skas * to_mm,
+ struct mmu_context_skas * from_mm);
+extern void free_ldt(struct mmu_context_skas * mm);
+
+#define LDT_PAGES_MAX \
+ ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
+#define LDT_ENTRIES_PER_PAGE \
+ (PAGE_SIZE/LDT_ENTRY_SIZE)
+#define LDT_DIRECT_ENTRIES \
+ ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
+
+struct ldt_entry {
+ __u32 a;
+ __u32 b;
+};
+
+typedef struct uml_ldt {
+ int entry_count;
+ struct semaphore semaphore;
+ union {
+ struct ldt_entry * pages[LDT_PAGES_MAX];
+ struct ldt_entry entries[LDT_DIRECT_ENTRIES];
+ } u;
+} uml_ldt_t;
+
+#endif
diff --git a/include/asm-um/page.h b/include/asm-um/page.h
index 0229814af31..41364330aff 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -106,9 +106,6 @@ extern unsigned long uml_physmem;
#define __pa(virt) to_phys((void *) (unsigned long) (virt))
#define __va(phys) to_virt((unsigned long) (phys))
-#define page_to_pfn(page) ((page) - mem_map)
-#define pfn_to_page(pfn) (mem_map + (pfn))
-
#define phys_to_pfn(p) ((p) >> PAGE_SHIFT)
#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
@@ -121,6 +118,7 @@ extern struct page *arch_validate(struct page *page, gfp_t mask, int order);
extern void arch_free_page(struct page *page, int order);
#define HAVE_ARCH_FREE_PAGE
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif
diff --git a/include/asm-um/processor-i386.h b/include/asm-um/processor-i386.h
index 4108a579eb9..595f1c3e1e4 100644
--- a/include/asm-um/processor-i386.h
+++ b/include/asm-um/processor-i386.h
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -6,21 +6,48 @@
#ifndef __UM_PROCESSOR_I386_H
#define __UM_PROCESSOR_I386_H
+#include "linux/string.h"
+#include "asm/host_ldt.h"
+#include "asm/segment.h"
+
extern int host_has_xmm;
extern int host_has_cmov;
/* include faultinfo structure */
#include "sysdep/faultinfo.h"
+struct uml_tls_struct {
+ struct user_desc tls;
+ unsigned flushed:1;
+ unsigned present:1;
+};
+
struct arch_thread {
+ struct uml_tls_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
unsigned long debugregs[8];
int debugregs_seq;
struct faultinfo faultinfo;
};
-#define INIT_ARCH_THREAD { .debugregs = { [ 0 ... 7 ] = 0 }, \
- .debugregs_seq = 0, \
- .faultinfo = { 0, 0, 0 } }
+#define INIT_ARCH_THREAD { \
+ .tls_array = { [ 0 ... GDT_ENTRY_TLS_ENTRIES - 1 ] = \
+ { .present = 0, .flushed = 0 } }, \
+ .debugregs = { [ 0 ... 7 ] = 0 }, \
+ .debugregs_seq = 0, \
+ .faultinfo = { 0, 0, 0 } \
+}
+
+static inline void arch_flush_thread(struct arch_thread *thread)
+{
+ /* Clear any TLS still hanging */
+ memset(&thread->tls_array, 0, sizeof(thread->tls_array));
+}
+
+static inline void arch_copy_thread(struct arch_thread *from,
+ struct arch_thread *to)
+{
+ memcpy(&to->tls_array, &from->tls_array, sizeof(from->tls_array));
+}
#include "asm/arch/user.h"
diff --git a/include/asm-um/processor-x86_64.h b/include/asm-um/processor-x86_64.h
index e1e1255a1d3..10609af376c 100644
--- a/include/asm-um/processor-x86_64.h
+++ b/include/asm-um/processor-x86_64.h
@@ -28,6 +28,15 @@ extern inline void rep_nop(void)
.debugregs_seq = 0, \
.faultinfo = { 0, 0, 0 } }
+static inline void arch_flush_thread(struct arch_thread *thread)
+{
+}
+
+static inline void arch_copy_thread(struct arch_thread *from,
+ struct arch_thread *to)
+{
+}
+
#include "asm/arch/user.h"
#define current_text_addr() \
diff --git a/include/asm-um/ptrace-generic.h b/include/asm-um/ptrace-generic.h
index 46599ac4403..503484305e6 100644
--- a/include/asm-um/ptrace-generic.h
+++ b/include/asm-um/ptrace-generic.h
@@ -28,7 +28,7 @@ struct pt_regs {
union uml_pt_regs regs;
};
-#define EMPTY_REGS { regs : EMPTY_UML_PT_REGS }
+#define EMPTY_REGS { .regs = EMPTY_UML_PT_REGS }
#define PT_REGS_IP(r) UPT_IP(&(r)->regs)
#define PT_REGS_SP(r) UPT_SP(&(r)->regs)
@@ -60,17 +60,9 @@ extern void show_regs(struct pt_regs *regs);
extern void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs,
int error_code);
-#endif
+extern int arch_copy_tls(struct task_struct *new);
+extern void clear_flushed_tls(struct task_struct *task);
#endif
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+#endif
diff --git a/include/asm-um/ptrace-i386.h b/include/asm-um/ptrace-i386.h
index fe882b9d917..6e2528bb008 100644
--- a/include/asm-um/ptrace-i386.h
+++ b/include/asm-um/ptrace-i386.h
@@ -8,8 +8,11 @@
#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
+#include "linux/compiler.h"
#include "sysdep/ptrace.h"
#include "asm/ptrace-generic.h"
+#include "asm/host_ldt.h"
+#include "choose-mode.h"
#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
@@ -38,15 +41,34 @@
#define user_mode(r) UPT_IS_USER(&(r)->regs)
-#endif
+extern int ptrace_get_thread_area(struct task_struct *child, int idx,
+ struct user_desc __user *user_desc);
-/*
- * 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:
- */
+extern int ptrace_set_thread_area(struct task_struct *child, int idx,
+ struct user_desc __user *user_desc);
+
+extern int do_set_thread_area_skas(struct user_desc *info);
+extern int do_get_thread_area_skas(struct user_desc *info);
+
+extern int do_set_thread_area_tt(struct user_desc *info);
+extern int do_get_thread_area_tt(struct user_desc *info);
+
+extern int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to);
+extern int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to);
+
+extern void arch_switch_to_tt(struct task_struct *from, struct task_struct *to);
+extern void arch_switch_to_skas(struct task_struct *from, struct task_struct *to);
+
+static inline int do_get_thread_area(struct user_desc *info)
+{
+ return CHOOSE_MODE_PROC(do_get_thread_area_tt, do_get_thread_area_skas, info);
+}
+
+static inline int do_set_thread_area(struct user_desc *info)
+{
+ return CHOOSE_MODE_PROC(do_set_thread_area_tt, do_set_thread_area_skas, info);
+}
+
+struct task_struct;
+
+#endif
diff --git a/include/asm-um/ptrace-x86_64.h b/include/asm-um/ptrace-x86_64.h
index be51219a8ff..c894e68b1f9 100644
--- a/include/asm-um/ptrace-x86_64.h
+++ b/include/asm-um/ptrace-x86_64.h
@@ -8,6 +8,8 @@
#define __UM_PTRACE_X86_64_H
#include "linux/compiler.h"
+#include "asm/errno.h"
+#include "asm/host_ldt.h"
#define signal_fault signal_fault_x86_64
#define __FRAME_OFFSETS /* Needed to get the R* macros */
@@ -63,15 +65,26 @@ void signal_fault(struct pt_regs_subarch *regs, void *frame, char *where);
#define profile_pc(regs) PT_REGS_IP(regs)
-#endif
+static inline int ptrace_get_thread_area(struct task_struct *child, int idx,
+ struct user_desc __user *user_desc)
+{
+ return -ENOSYS;
+}
-/*
- * 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:
- */
+static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
+ struct user_desc __user *user_desc)
+{
+ return -ENOSYS;
+}
+
+static inline void arch_switch_to_tt(struct task_struct *from,
+ struct task_struct *to)
+{
+}
+
+static inline void arch_switch_to_skas(struct task_struct *from,
+ struct task_struct *to)
+{
+}
+
+#endif
diff --git a/include/asm-um/segment.h b/include/asm-um/segment.h
index 55e40301f62..45183fcd10b 100644
--- a/include/asm-um/segment.h
+++ b/include/asm-um/segment.h
@@ -1,4 +1,10 @@
#ifndef __UM_SEGMENT_H
#define __UM_SEGMENT_H
+extern int host_gdt_entry_tls_min;
+
+#define GDT_ENTRY_TLS_ENTRIES 3
+#define GDT_ENTRY_TLS_MIN host_gdt_entry_tls_min
+#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
+
#endif
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 17b6b07c433..f166b9837c6 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -27,14 +27,14 @@ struct thread_info {
#define INIT_THREAD_INFO(tsk) \
{ \
- task: &tsk, \
- exec_domain: &default_exec_domain, \
- flags: 0, \
- cpu: 0, \
- preempt_count: 1, \
- addr_limit: KERNEL_DS, \
- restart_block: { \
- fn: do_no_restart_syscall, \
+ .task = &tsk, \
+ .exec_domain = &default_exec_domain, \
+ .flags = 0, \
+ .cpu = 0, \
+ .preempt_count = 1, \
+ .addr_limit = KERNEL_DS, \
+ .restart_block = { \
+ .fn = do_no_restart_syscall, \
}, \
}
diff --git a/include/asm-um/uaccess.h b/include/asm-um/uaccess.h
index 2ee028b8de9..16c734af919 100644
--- a/include/asm-um/uaccess.h
+++ b/include/asm-um/uaccess.h
@@ -41,28 +41,28 @@
#define __get_user(x, ptr) \
({ \
- const __typeof__(ptr) __private_ptr = ptr; \
- __typeof__(*(__private_ptr)) __private_val; \
- int __private_ret = -EFAULT; \
- (x) = (__typeof__(*(__private_ptr)))0; \
- if (__copy_from_user(&__private_val, (__private_ptr), \
- sizeof(*(__private_ptr))) == 0) {\
- (x) = (__typeof__(*(__private_ptr))) __private_val; \
- __private_ret = 0; \
- } \
- __private_ret; \
+ const __typeof__(*(ptr)) __user *__private_ptr = (ptr); \
+ __typeof__(x) __private_val; \
+ int __private_ret = -EFAULT; \
+ (x) = (__typeof__(*(__private_ptr)))0; \
+ if (__copy_from_user((__force void *)&__private_val, (__private_ptr),\
+ sizeof(*(__private_ptr))) == 0) { \
+ (x) = (__typeof__(*(__private_ptr))) __private_val; \
+ __private_ret = 0; \
+ } \
+ __private_ret; \
})
#define get_user(x, ptr) \
({ \
const __typeof__((*(ptr))) __user *private_ptr = (ptr); \
(access_ok(VERIFY_READ, private_ptr, sizeof(*private_ptr)) ? \
- __get_user(x, private_ptr) : ((x) = 0, -EFAULT)); \
+ __get_user(x, private_ptr) : ((x) = (__typeof__(*ptr))0, -EFAULT)); \
})
#define __put_user(x, ptr) \
({ \
- __typeof__(ptr) __private_ptr = ptr; \
+ __typeof__(*(ptr)) __user *__private_ptr = ptr; \
__typeof__(*(__private_ptr)) __private_val; \
int __private_ret = -EFAULT; \
__private_val = (__typeof__(*(__private_ptr))) (x); \
@@ -89,14 +89,3 @@ struct exception_table_entry
};
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/include/asm-v850/page.h b/include/asm-v850/page.h
index b4bc85e7b91..ad03c46a1f9 100644
--- a/include/asm-v850/page.h
+++ b/include/asm-v850/page.h
@@ -111,8 +111,7 @@ typedef unsigned long pgprot_t;
#define page_to_virt(page) \
((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
-#define pfn_to_page(pfn) virt_to_page (pfn_to_virt (pfn))
-#define page_to_pfn(page) virt_to_pfn (page_to_virt (page))
+#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#define virt_addr_valid(kaddr) \
@@ -125,6 +124,7 @@ typedef unsigned long pgprot_t;
#endif /* KERNEL */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* __V850_PAGE_H__ */
diff --git a/include/asm-v850/system.h b/include/asm-v850/system.h
index 107decbd6e6..7091af4b786 100644
--- a/include/asm-v850/system.h
+++ b/include/asm-v850/system.h
@@ -18,8 +18,6 @@
#include <asm/ptrace.h>
-#define prepare_to_switch() do { } while (0)
-
/*
* switch_to(n) should switch tasks to task ptr, first checking that
* ptr isn't the current task, in which case it does nothing.
diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h
index 5a48e9bcf21..1dd40067c67 100644
--- a/include/asm-x86_64/apicdef.h
+++ b/include/asm-x86_64/apicdef.h
@@ -137,8 +137,6 @@
*/
#define u32 unsigned int
-#define lapic ((volatile struct local_apic *)APIC_BASE)
-
struct local_apic {
/*000*/ struct { u32 __reserved[4]; } __reserved_01;
diff --git a/include/asm-x86_64/cache.h b/include/asm-x86_64/cache.h
index c8043a16152..f8dff1c6753 100644
--- a/include/asm-x86_64/cache.h
+++ b/include/asm-x86_64/cache.h
@@ -20,8 +20,8 @@
__attribute__((__section__(".data.page_aligned")))
#endif
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
-
#endif
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+
#endif
diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h
index 76bb6193ae9..662964b74e3 100644
--- a/include/asm-x86_64/cpufeature.h
+++ b/include/asm-x86_64/cpufeature.h
@@ -64,6 +64,7 @@
#define X86_FEATURE_REP_GOOD (3*32+ 4) /* rep microcode works well on this CPU */
#define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */
#define X86_FEATURE_SYNC_RDTSC (3*32+6) /* RDTSC syncs CPU core */
+#define X86_FEATURE_FXSAVE_LEAK (3*32+7) /* FIP/FOP/FDP leaks through FXSAVE */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h
index 8dcc3266524..670a3388e70 100644
--- a/include/asm-x86_64/e820.h
+++ b/include/asm-x86_64/e820.h
@@ -47,7 +47,8 @@ extern void contig_e820_setup(void);
extern unsigned long e820_end_of_ram(void);
extern void e820_reserve_resources(void);
extern void e820_print_map(char *who);
-extern int e820_mapped(unsigned long start, unsigned long end, unsigned type);
+extern int e820_any_mapped(unsigned long start, unsigned long end, unsigned type);
+extern int e820_all_mapped(unsigned long start, unsigned long end, unsigned type);
extern void e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end);
extern void e820_setup_gap(void);
@@ -58,6 +59,8 @@ extern void __init parse_memopt(char *p, char **end);
extern void __init parse_memmapopt(char *p, char **end);
extern struct e820map e820;
+
+extern unsigned ebda_addr, ebda_size;
#endif/*!__ASSEMBLY__*/
#endif/*__E820_HEADER*/
diff --git a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h
index c98633af07d..b4f8f4a41a6 100644
--- a/include/asm-x86_64/elf.h
+++ b/include/asm-x86_64/elf.h
@@ -159,7 +159,7 @@ extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
/* 1GB for 64bit, 8MB for 32bit */
-#define STACK_RND_MASK (is_compat_task() ? 0x7ff : 0x3fffff)
+#define STACK_RND_MASK (test_thread_flag(TIF_IA32) ? 0x7ff : 0x3fffff)
#endif
diff --git a/include/asm-x86_64/futex.h b/include/asm-x86_64/futex.h
index 8602c09bf89..9804bf07b09 100644
--- a/include/asm-x86_64/futex.h
+++ b/include/asm-x86_64/futex.h
@@ -94,5 +94,32 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
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;
+
+ __asm__ __volatile__(
+ "1: " LOCK_PREFIX "cmpxchgl %3, %1 \n"
+
+ "2: .section .fixup, \"ax\" \n"
+ "3: mov %2, %0 \n"
+ " jmp 2b \n"
+ " .previous \n"
+
+ " .section __ex_table, \"a\" \n"
+ " .align 8 \n"
+ " .quad 1b,3b \n"
+ " .previous \n"
+
+ : "=a" (oldval), "=m" (*uaddr)
+ : "i" (-EFAULT), "r" (newval), "0" (oldval)
+ : "memory"
+ );
+
+ return oldval;
+}
+
#endif
#endif
diff --git a/include/asm-x86_64/hpet.h b/include/asm-x86_64/hpet.h
index 08b75c15269..18ff7ee9e77 100644
--- a/include/asm-x86_64/hpet.h
+++ b/include/asm-x86_64/hpet.h
@@ -51,6 +51,8 @@
#define HPET_TN_ROUTE_SHIFT 9
+#define HPET_TICK_RATE (HZ * 100000UL)
+
extern int is_hpet_enabled(void);
extern int hpet_rtc_timer_init(void);
extern int oem_force_hpet_timer(void);
diff --git a/include/asm-x86_64/i387.h b/include/asm-x86_64/i387.h
index 876eb9a2fe7..cba8a3b0cde 100644
--- a/include/asm-x86_64/i387.h
+++ b/include/asm-x86_64/i387.h
@@ -72,6 +72,23 @@ extern int set_fpregs(struct task_struct *tsk,
#define set_fpu_swd(t,val) ((t)->thread.i387.fxsave.swd = (val))
#define set_fpu_fxsr_twd(t,val) ((t)->thread.i387.fxsave.twd = (val))
+#define X87_FSW_ES (1 << 7) /* Exception Summary */
+
+/* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
+ is pending. Clear the x87 state here by setting it to fixed
+ values. The kernel data segment can be sometimes 0 and sometimes
+ new user value. Both should be ok.
+ Use the PDA as safe address because it should be already in L1. */
+static inline void clear_fpu_state(struct i387_fxsave_struct *fx)
+{
+ if (unlikely(fx->swd & X87_FSW_ES))
+ asm volatile("fnclex");
+ alternative_input(ASM_NOP8 ASM_NOP2,
+ " emms\n" /* clear stack tags */
+ " fildl %%gs:0", /* load to clear state */
+ X86_FEATURE_FXSAVE_LEAK);
+}
+
static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
{
int err;
@@ -119,6 +136,7 @@ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
#endif
if (unlikely(err))
__clear_user(fx, sizeof(struct i387_fxsave_struct));
+ /* No need to clear here because the caller clears USED_MATH */
return err;
}
@@ -149,7 +167,7 @@ static inline void __fxsave_clear(struct task_struct *tsk)
"i" (offsetof(__typeof__(*tsk),
thread.i387.fxsave)));
#endif
- __asm__ __volatile__("fnclex");
+ clear_fpu_state(&tsk->thread.i387.fxsave);
}
static inline void kernel_fpu_begin(void)
diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h
index eeb2bcd635d..b4f4b172b15 100644
--- a/include/asm-x86_64/ia32_unistd.h
+++ b/include/asm-x86_64/ia32_unistd.h
@@ -317,6 +317,4 @@
#define __NR_ia32_ppoll 309
#define __NR_ia32_unshare 310
-#define IA32_NR_syscalls 315 /* must be > than biggest syscall! */
-
#endif /* _ASM_X86_64_IA32_UNISTD_H_ */
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index cafdfb37f0d..a05da8a50bf 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -177,7 +177,7 @@ static inline __u16 __readw(const volatile void __iomem *addr)
{
return *(__force volatile __u16 *)addr;
}
-static inline __u32 __readl(const volatile void __iomem *addr)
+static __always_inline __u32 __readl(const volatile void __iomem *addr)
{
return *(__force volatile __u32 *)addr;
}
diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h
index ee1bc69aec9..52484e82c64 100644
--- a/include/asm-x86_64/io_apic.h
+++ b/include/asm-x86_64/io_apic.h
@@ -205,6 +205,7 @@ extern int skip_ioapic_setup;
extern int io_apic_get_version (int ioapic);
extern int io_apic_get_redir_entries (int ioapic);
extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int, int);
+extern int timer_uses_ioapic_pin_0;
#endif
extern int sis_apic_bug; /* dummy */
diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h
index b9ed4c0c878..cf795631d9b 100644
--- a/include/asm-x86_64/kdebug.h
+++ b/include/asm-x86_64/kdebug.h
@@ -5,21 +5,20 @@
struct pt_regs;
-struct die_args {
+struct die_args {
struct pt_regs *regs;
const char *str;
- long err;
+ long err;
int trapnr;
int signr;
-};
+};
+
+extern int register_die_notifier(struct notifier_block *);
+extern int unregister_die_notifier(struct notifier_block *);
+extern struct atomic_notifier_head die_chain;
-/* Note - you should never unregister because that can race with NMIs.
- If you really want to do it first unregister - then synchronize_sched - then free.
- */
-int register_die_notifier(struct notifier_block *nb);
-extern struct notifier_block *die_chain;
/* Grossly misnamed. */
-enum die_val {
+enum die_val {
DIE_OOPS = 1,
DIE_INT3,
DIE_DEBUG,
@@ -33,8 +32,8 @@ enum die_val {
DIE_CALL,
DIE_NMI_IPI,
DIE_PAGE_FAULT,
-};
-
+};
+
static inline int notify_die(enum die_val val, const char *str,
struct pt_regs *regs, long err, int trap, int sig)
{
@@ -45,7 +44,7 @@ static inline int notify_die(enum die_val val, const char *str,
.trapnr = trap,
.signr = sig
};
- return notifier_call_chain(&die_chain, val, &args);
+ return atomic_notifier_call_chain(&die_chain, val, &args);
}
extern int printk_address(unsigned long address);
diff --git a/include/asm-x86_64/local.h b/include/asm-x86_64/local.h
index bf148037d4e..cd17945bf21 100644
--- a/include/asm-x86_64/local.h
+++ b/include/asm-x86_64/local.h
@@ -5,7 +5,7 @@
typedef struct
{
- volatile unsigned long counter;
+ volatile long counter;
} local_t;
#define LOCAL_INIT(i) { (i) }
@@ -13,7 +13,7 @@ typedef struct
#define local_read(v) ((v)->counter)
#define local_set(v,i) (((v)->counter) = (i))
-static __inline__ void local_inc(local_t *v)
+static inline void local_inc(local_t *v)
{
__asm__ __volatile__(
"incq %0"
@@ -21,7 +21,7 @@ static __inline__ void local_inc(local_t *v)
:"m" (v->counter));
}
-static __inline__ void local_dec(local_t *v)
+static inline void local_dec(local_t *v)
{
__asm__ __volatile__(
"decq %0"
@@ -29,7 +29,7 @@ static __inline__ void local_dec(local_t *v)
:"m" (v->counter));
}
-static __inline__ void local_add(unsigned int i, local_t *v)
+static inline void local_add(long i, local_t *v)
{
__asm__ __volatile__(
"addq %1,%0"
@@ -37,7 +37,7 @@ static __inline__ void local_add(unsigned int i, local_t *v)
:"ir" (i), "m" (v->counter));
}
-static __inline__ void local_sub(unsigned int i, local_t *v)
+static inline void local_sub(long i, local_t *v)
{
__asm__ __volatile__(
"subq %1,%0"
diff --git a/include/asm-x86_64/mce.h b/include/asm-x86_64/mce.h
index 5d298b799a9..7229785094e 100644
--- a/include/asm-x86_64/mce.h
+++ b/include/asm-x86_64/mce.h
@@ -70,6 +70,9 @@ struct mce_log {
#define MCE_THRESHOLD_BASE MCE_EXTENDED_BANK + 1 /* MCE_AMD */
#define MCE_THRESHOLD_DRAM_ECC MCE_THRESHOLD_BASE + 4
+#ifdef __KERNEL__
+#include <asm/atomic.h>
+
void mce_log(struct mce *m);
#ifdef CONFIG_X86_MCE_INTEL
void mce_intel_feature_init(struct cpuinfo_x86 *c);
@@ -87,4 +90,8 @@ static inline void mce_amd_feature_init(struct cpuinfo_x86 *c)
}
#endif
+extern atomic_t mce_entry;
+
+#endif
+
#endif
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
index 937f99b2688..6944e7122df 100644
--- a/include/asm-x86_64/mmzone.h
+++ b/include/asm-x86_64/mmzone.h
@@ -12,7 +12,8 @@
#include <asm/smp.h>
-#define NODEMAPSIZE 0xfff
+/* Should really switch to dynamic allocation at some point */
+#define NODEMAPSIZE 0x4fff
/* Simple perfect hash to map physical addresses to node numbers */
struct memnode {
@@ -44,12 +45,8 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
#define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT)
#define kvaddr_to_nid(kaddr) phys_to_nid(__pa(kaddr))
-extern struct page *pfn_to_page(unsigned long pfn);
-extern unsigned long page_to_pfn(struct page *page);
extern int pfn_valid(unsigned long pfn);
#endif
-#define local_mapnr(kvaddr) \
- ( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) )
#endif
#endif
diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h
index f6cbb4cbb5a..1cc92fe0250 100644
--- a/include/asm-x86_64/numa.h
+++ b/include/asm-x86_64/numa.h
@@ -2,7 +2,6 @@
#define _ASM_X8664_NUMA_H 1
#include <linux/nodemask.h>
-#include <asm/numnodes.h>
struct bootnode {
u64 start,end;
@@ -18,6 +17,8 @@ extern void numa_init_array(void);
extern int numa_off;
extern void numa_set_node(int cpu, int node);
+extern void srat_reserve_add_area(int nodeid);
+extern int hotadd_percent;
extern unsigned char apicid_to_node[256];
#ifdef CONFIG_NUMA
diff --git a/include/asm-x86_64/numnodes.h b/include/asm-x86_64/numnodes.h
deleted file mode 100644
index 32be16b8ae9..00000000000
--- a/include/asm-x86_64/numnodes.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASM_X8664_NUMNODES_H
-#define _ASM_X8664_NUMNODES_H 1
-
-#include <linux/config.h>
-
-#ifdef CONFIG_NUMA
-#define NODES_SHIFT 6
-#else
-#define NODES_SHIFT 0
-#endif
-
-#endif
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index 615e3e49492..408185bac35 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -123,8 +123,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define __boot_va(x) __va(x)
#define __boot_pa(x) __pa(x)
#ifdef CONFIG_FLATMEM
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < end_pfn)
#endif
@@ -140,6 +138,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _X86_64_PAGE_H */
diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h
index 4405b4adeab..7f33aaf9f7b 100644
--- a/include/asm-x86_64/percpu.h
+++ b/include/asm-x86_64/percpu.h
@@ -26,7 +26,7 @@
#define percpu_modcopy(pcpudst, src, size) \
do { \
unsigned int __i; \
- for_each_cpu(__i) \
+ for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset(__i), \
(src), (size)); \
} while (0)
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 8c8d88c036e..37a3ec433ee 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -20,6 +20,7 @@
#include <asm/mmsegment.h>
#include <asm/percpu.h>
#include <linux/personality.h>
+#include <linux/cpumask.h>
#define TF_MASK 0x00000100
#define IF_MASK 0x00000200
@@ -65,6 +66,9 @@ struct cpuinfo_x86 {
__u32 x86_power;
__u32 extended_cpuid_level; /* Max extended CPUID function supported */
unsigned long loops_per_jiffy;
+#ifdef CONFIG_SMP
+ cpumask_t llc_shared_map; /* cpus sharing the last level cache */
+#endif
__u8 apicid;
__u8 booted_cores; /* number of cores as seen by OS */
} ____cacheline_aligned;
@@ -354,9 +358,6 @@ struct extended_sigtable {
struct extended_signature sigs[0];
};
-/* '6' because it used to be for P6 only (but now covers Pentium 4 as well) */
-#define MICROCODE_IOCFREE _IO('6',0)
-
#define ASM_NOP1 K8_NOP1
#define ASM_NOP2 K8_NOP2
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index 9ccbb2cfd5c..a4fdaeb5c39 100644
--- a/include/asm-x86_64/smp.h
+++ b/include/asm-x86_64/smp.h
@@ -56,6 +56,7 @@ extern cpumask_t cpu_sibling_map[NR_CPUS];
extern cpumask_t cpu_core_map[NR_CPUS];
extern u8 phys_proc_id[NR_CPUS];
extern u8 cpu_core_id[NR_CPUS];
+extern u8 cpu_llc_id[NR_CPUS];
#define SMP_TRAMPOLINE_BASE 0x6000
diff --git a/include/asm-x86_64/timex.h b/include/asm-x86_64/timex.h
index f18443fcdf0..b9e5320b762 100644
--- a/include/asm-x86_64/timex.h
+++ b/include/asm-x86_64/timex.h
@@ -33,7 +33,7 @@ static __always_inline cycles_t get_cycles_sync(void)
unsigned eax;
/* Don't do an additional sync on CPUs where we know
RDTSC is already synchronous. */
- alternative_io(ASM_NOP2, "cpuid", X86_FEATURE_SYNC_RDTSC,
+ alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC,
"=a" (eax), "0" (1) : "ebx","ecx","edx","memory");
rdtscll(ret);
return ret;
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h
index c642f5d9882..9db54e9d17b 100644
--- a/include/asm-x86_64/topology.h
+++ b/include/asm-x86_64/topology.h
@@ -68,4 +68,6 @@ extern int __node_distance(int, int);
#include <asm-generic/topology.h>
+extern cpumask_t cpu_coregroup_map(int cpu);
+
#endif
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index da0341c5794..feb77cb8c04 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -605,8 +605,20 @@ __SYSCALL(__NR_pselect6, sys_ni_syscall) /* for now */
__SYSCALL(__NR_ppoll, sys_ni_syscall) /* for now */
#define __NR_unshare 272
__SYSCALL(__NR_unshare, sys_unshare)
-
-#define __NR_syscall_max __NR_unshare
+#define __NR_set_robust_list 273
+__SYSCALL(__NR_set_robust_list, sys_set_robust_list)
+#define __NR_get_robust_list 274
+__SYSCALL(__NR_get_robust_list, sys_get_robust_list)
+#define __NR_splice 275
+__SYSCALL(__NR_splice, sys_splice)
+#define __NR_tee 276
+__SYSCALL(__NR_tee, sys_tee)
+#define __NR_sync_file_range 277
+__SYSCALL(__NR_sync_file_range, sys_sync_file_range)
+#define __NR_vmsplice 278
+__SYSCALL(__NR_vmsplice, sys_vmsplice)
+
+#define __NR_syscall_max __NR_vmsplice
#ifndef __NO_STUBS
diff --git a/include/asm-xtensa/ioctls.h b/include/asm-xtensa/ioctls.h
index 10c443435c1..3b89a772d0a 100644
--- a/include/asm-xtensa/ioctls.h
+++ b/include/asm-xtensa/ioctls.h
@@ -107,6 +107,6 @@
#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
#define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT _IOR('T', 93, struct async_icount) /* read serial port inline interrupt counts */
+#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#endif /* _XTENSA_IOCTLS_H */
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
index 8ded36f255a..992bac5c125 100644
--- a/include/asm-xtensa/page.h
+++ b/include/asm-xtensa/page.h
@@ -109,10 +109,7 @@ void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page);
#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
#define pfn_valid(pfn) ((unsigned long)pfn < max_mapnr)
-#ifndef CONFIG_DISCONTIGMEM
-# define pfn_to_page(pfn) (mem_map + (pfn))
-# define page_to_pfn(page) ((unsigned long)((page) - mem_map))
-#else
+#ifdef CONFIG_DISCONTIGMEM
# error CONFIG_DISCONTIGMEM not supported
#endif
@@ -130,4 +127,5 @@ void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page);
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#endif /* _XTENSA_PAGE_H */
diff --git a/include/asm-xtensa/signal.h b/include/asm-xtensa/signal.h
index 5d6fc9cdf58..a99c9aec64e 100644
--- a/include/asm-xtensa/signal.h
+++ b/include/asm-xtensa/signal.h
@@ -118,9 +118,9 @@ typedef struct {
* SA_INTERRUPT is also used by the irq handling routines.
* SA_SHIRQ is for shared interrupt support on PCI and EISA.
*/
-#define SA_PROBE SA_ONESHOT
#define SA_SAMPLE_RANDOM SA_RESTART
#define SA_SHIRQ 0x04000000
+#define SA_PROBEIRQ 0x08000000
#endif
#define SIG_BLOCK 0 /* for blocking signals */
diff --git a/include/asm-xtensa/system.h b/include/asm-xtensa/system.h
index 9284867f1cb..b29f7ae6a08 100644
--- a/include/asm-xtensa/system.h
+++ b/include/asm-xtensa/system.h
@@ -111,8 +111,6 @@ extern void *_switch_to(void *last, void *next);
#endif /* __ASSEMBLY__ */
-#define prepare_to_switch() do { } while(0)
-
#define switch_to(prev,next,last) \
do { \
clear_cpenable(); \
diff --git a/include/linux/adb.h b/include/linux/adb.h
index e9fdc63483c..b7305b17827 100644
--- a/include/linux/adb.h
+++ b/include/linux/adb.h
@@ -85,7 +85,7 @@ enum adb_message {
ADB_MSG_POST_RESET /* Called after resetting the bus (re-do init & register) */
};
extern struct adb_driver *adb_controller;
-extern struct notifier_block *adb_client_list;
+extern struct blocking_notifier_head adb_client_list;
int adb_request(struct adb_request *req, void (*done)(struct adb_request *),
int flags, int nbytes, ...);
diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
index dc726ffcceb..48ee32a18ac 100644
--- a/include/linux/amba/serial.h
+++ b/include/linux/amba/serial.h
@@ -158,4 +158,10 @@
#define UART01x_RSR_ANY (UART01x_RSR_OE|UART01x_RSR_BE|UART01x_RSR_PE|UART01x_RSR_FE)
#define UART01x_FR_MODEM_ANY (UART01x_FR_DCD|UART01x_FR_DSR|UART01x_FR_CTS)
+#ifndef __ASSEMBLY__
+struct amba_pl010_data {
+ void (*set_mctrl)(struct amba_device *dev, void __iomem *base, unsigned int mctrl);
+};
+#endif
+
#endif
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 1c47c59058c..b74c148f14e 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -83,6 +83,7 @@
#define AUDIT_CONFIG_CHANGE 1305 /* Audit system configuration change */
#define AUDIT_SOCKADDR 1306 /* sockaddr copied as syscall arg */
#define AUDIT_CWD 1307 /* Current working directory */
+#define AUDIT_IPC_SET_PERM 1311 /* IPC new permissions record type */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -145,6 +146,11 @@
#define AUDIT_PERS 10
#define AUDIT_ARCH 11
#define AUDIT_MSGTYPE 12
+#define AUDIT_SE_USER 13 /* security label user */
+#define AUDIT_SE_ROLE 14 /* security label role */
+#define AUDIT_SE_TYPE 15 /* security label type */
+#define AUDIT_SE_SEN 16 /* security label sensitivity label */
+#define AUDIT_SE_CLR 17 /* security label clearance label */
/* These are ONLY useful when checking
* at syscall exit time (AUDIT_AT_EXIT). */
@@ -287,10 +293,10 @@ struct netlink_skb_parms;
/* Public API */
extern int audit_alloc(struct task_struct *task);
extern void audit_free(struct task_struct *task);
-extern void audit_syscall_entry(struct task_struct *task, int arch,
+extern void audit_syscall_entry(int arch,
int major, unsigned long a0, unsigned long a1,
unsigned long a2, unsigned long a3);
-extern void audit_syscall_exit(struct task_struct *task, int failed, long return_code);
+extern void audit_syscall_exit(int failed, long return_code);
extern void audit_getname(const char *name);
extern void audit_putname(const char *name);
extern void __audit_inode(const char *name, const struct inode *inode, unsigned flags);
@@ -314,7 +320,8 @@ extern void auditsc_get_stamp(struct audit_context *ctx,
struct timespec *t, unsigned int *serial);
extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid);
extern uid_t audit_get_loginuid(struct audit_context *ctx);
-extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp);
+extern int audit_ipc_obj(struct kern_ipc_perm *ipcp);
+extern int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp);
extern int audit_socketcall(int nargs, unsigned long *args);
extern int audit_sockaddr(int len, void *addr);
extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
@@ -323,8 +330,8 @@ extern int audit_set_macxattr(const char *name);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
-#define audit_syscall_entry(t,ta,a,b,c,d,e) do { ; } while (0)
-#define audit_syscall_exit(t,f,r) do { ; } while (0)
+#define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0)
+#define audit_syscall_exit(f,r) do { ; } while (0)
#define audit_getname(n) do { ; } while (0)
#define audit_putname(n) do { ; } while (0)
#define __audit_inode(n,i,f) do { ; } while (0)
@@ -333,7 +340,8 @@ extern int audit_set_macxattr(const char *name);
#define audit_inode_child(d,i,p) do { ; } while (0)
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; })
-#define audit_ipc_perms(q,u,g,m,i) ({ 0; })
+#define audit_ipc_obj(i) ({ 0; })
+#define audit_ipc_set_perm(q,u,g,m,i) ({ 0; })
#define audit_socketcall(n,a) ({ 0; })
#define audit_sockaddr(len, addr) ({ 0; })
#define audit_avc_path(dentry, mnt) ({ 0; })
@@ -366,7 +374,7 @@ extern void audit_log_d_path(struct audit_buffer *ab,
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);
+ void *data, size_t datasz, uid_t loginuid, u32 sid);
#else
#define audit_log(c,g,t,f,...) do { ; } while (0)
#define audit_log_start(c,g,t) ({ NULL; })
diff --git a/include/linux/auto_fs4.h b/include/linux/auto_fs4.h
index 9343c89d843..0a6bc52ffe8 100644
--- a/include/linux/auto_fs4.h
+++ b/include/linux/auto_fs4.h
@@ -19,18 +19,37 @@
#undef AUTOFS_MIN_PROTO_VERSION
#undef AUTOFS_MAX_PROTO_VERSION
-#define AUTOFS_PROTO_VERSION 4
+#define AUTOFS_PROTO_VERSION 5
#define AUTOFS_MIN_PROTO_VERSION 3
-#define AUTOFS_MAX_PROTO_VERSION 4
+#define AUTOFS_MAX_PROTO_VERSION 5
-#define AUTOFS_PROTO_SUBVERSION 7
+#define AUTOFS_PROTO_SUBVERSION 0
/* Mask for expire behaviour */
#define AUTOFS_EXP_IMMEDIATE 1
#define AUTOFS_EXP_LEAVES 2
-/* New message type */
-#define autofs_ptype_expire_multi 2 /* Expire entry (umount request) */
+/* Daemon notification packet types */
+enum autofs_notify {
+ NFY_NONE,
+ NFY_MOUNT,
+ NFY_EXPIRE
+};
+
+/* Kernel protocol version 4 packet types */
+
+/* Expire entry (umount request) */
+#define autofs_ptype_expire_multi 2
+
+/* Kernel protocol version 5 packet types */
+
+/* Indirect mount missing and expire requests. */
+#define autofs_ptype_missing_indirect 3
+#define autofs_ptype_expire_indirect 4
+
+/* Direct mount missing and expire requests */
+#define autofs_ptype_missing_direct 5
+#define autofs_ptype_expire_direct 6
/* v4 multi expire (via pipe) */
struct autofs_packet_expire_multi {
@@ -40,14 +59,36 @@ struct autofs_packet_expire_multi {
char name[NAME_MAX+1];
};
+/* autofs v5 common packet struct */
+struct autofs_v5_packet {
+ struct autofs_packet_hdr hdr;
+ autofs_wqt_t wait_queue_token;
+ __u32 dev;
+ __u64 ino;
+ __u32 uid;
+ __u32 gid;
+ __u32 pid;
+ __u32 tgid;
+ __u32 len;
+ char name[NAME_MAX+1];
+};
+
+typedef struct autofs_v5_packet autofs_packet_missing_indirect_t;
+typedef struct autofs_v5_packet autofs_packet_expire_indirect_t;
+typedef struct autofs_v5_packet autofs_packet_missing_direct_t;
+typedef struct autofs_v5_packet autofs_packet_expire_direct_t;
+
union autofs_packet_union {
struct autofs_packet_hdr hdr;
struct autofs_packet_missing missing;
struct autofs_packet_expire expire;
struct autofs_packet_expire_multi expire_multi;
+ struct autofs_v5_packet v5_packet;
};
#define AUTOFS_IOC_EXPIRE_MULTI _IOW(0x93,0x66,int)
+#define AUTOFS_IOC_EXPIRE_INDIRECT AUTOFS_IOC_EXPIRE_MULTI
+#define AUTOFS_IOC_EXPIRE_DIRECT AUTOFS_IOC_EXPIRE_MULTI
#define AUTOFS_IOC_PROTOSUBVER _IOR(0x93,0x67,int)
#define AUTOFS_IOC_ASKREGHOST _IOR(0x93,0x68,int)
#define AUTOFS_IOC_TOGGLEREGHOST _IOR(0x93,0x69,int)
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index bb9e5432232..75e91f5b6a0 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -19,20 +19,25 @@ struct fb_info;
struct backlight_properties {
/* Owner module */
struct module *owner;
- /* Get the backlight power status (0: full on, 1..3: power saving
- modes; 4: full off), see FB_BLANK_XXX */
- int (*get_power)(struct backlight_device *);
- /* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */
- int (*set_power)(struct backlight_device *, int power);
- /* Maximal value for brightness (read-only) */
- int max_brightness;
- /* Get current backlight brightness */
+
+ /* Notify the backlight driver some property has changed */
+ int (*update_status)(struct backlight_device *);
+ /* Return the current backlight brightness (accounting for power,
+ fb_blank etc.) */
int (*get_brightness)(struct backlight_device *);
- /* Set backlight brightness (0..max_brightness) */
- int (*set_brightness)(struct backlight_device *, int brightness);
/* Check if given framebuffer device is the one bound to this backlight;
return 0 if not, !=0 if it is. If NULL, backlight always matches the fb. */
int (*check_fb)(struct fb_info *);
+
+ /* Current User requested brightness (0 - max_brightness) */
+ int brightness;
+ /* Maximal value for brightness (read-only) */
+ int max_brightness;
+ /* Current FB Power mode (0: full on, 1..3: power saving
+ modes; 4: full off), see FB_BLANK_XXX */
+ int power;
+ /* FB Blanking active? (values as for power) */
+ int fb_blank;
};
struct backlight_device {
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index c179966f1a2..59e1259b1c4 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -17,6 +17,8 @@
#include <asm/scatterlist.h>
+struct scsi_ioctl_command;
+
struct request_queue;
typedef struct request_queue request_queue_t;
struct elevator_queue;
@@ -55,25 +57,29 @@ struct as_io_context {
struct cfq_queue;
struct cfq_io_context {
- /*
- * circular list of cfq_io_contexts belonging to a process io context
- */
- struct list_head list;
- struct cfq_queue *cfqq[2];
+ struct rb_node rb_node;
void *key;
+ struct cfq_queue *cfqq[2];
+
struct io_context *ioc;
unsigned long last_end_request;
- unsigned long last_queue;
+ sector_t last_request_pos;
+ unsigned long last_queue;
+
unsigned long ttime_total;
unsigned long ttime_samples;
unsigned long ttime_mean;
+ unsigned int seek_samples;
+ u64 seek_total;
+ sector_t seek_mean;
+
struct list_head queue_list;
- void (*dtor)(struct cfq_io_context *);
- void (*exit)(struct cfq_io_context *);
+ void (*dtor)(struct io_context *); /* destructor */
+ void (*exit)(struct io_context *); /* called on task exit */
};
/*
@@ -94,7 +100,7 @@ struct io_context {
int nr_batch_requests; /* Number of requests left in the batch */
struct as_io_context *aic;
- struct cfq_io_context *cic;
+ struct rb_root cic_root;
};
void put_io_context(struct io_context *ioc);
@@ -607,6 +613,8 @@ 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 sg_scsi_ioctl(struct file *, struct request_queue *,
+ struct gendisk *, struct scsi_ioctl_command __user *);
extern void blk_start_queue(request_queue_t *q);
extern void blk_stop_queue(request_queue_t *q);
extern void blk_sync_queue(struct request_queue *q);
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 7155452fb4a..da2d107fe2c 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -38,12 +38,14 @@ typedef struct bootmem_data {
unsigned long last_pos;
unsigned long last_success; /* Previous allocation point. To speed
* up searching */
+ struct list_head list;
} bootmem_data_t;
extern unsigned long __init bootmem_bootmap_pages (unsigned long);
extern unsigned long __init init_bootmem (unsigned long addr, unsigned long memend);
extern void __init free_bootmem (unsigned long addr, unsigned long size);
extern void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal);
+extern void * __init __alloc_bootmem_nopanic (unsigned long size, unsigned long align, unsigned long goal);
extern void * __init __alloc_bootmem_low(unsigned long size,
unsigned long align,
unsigned long goal);
diff --git a/include/linux/cdev.h b/include/linux/cdev.h
index 8da37e29cb8..2216638962d 100644
--- a/include/linux/cdev.h
+++ b/include/linux/cdev.h
@@ -5,13 +5,13 @@
struct cdev {
struct kobject kobj;
struct module *owner;
- struct file_operations *ops;
+ const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
-void cdev_init(struct cdev *, struct file_operations *);
+void cdev_init(struct cdev *, const struct file_operations *);
struct cdev *cdev_alloc(void);
diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
index cc621ec409d..b3ecf8f71d9 100644
--- a/include/linux/coda_linux.h
+++ b/include/linux/coda_linux.h
@@ -30,9 +30,9 @@ extern struct inode_operations coda_ioctl_inode_operations;
extern struct address_space_operations coda_file_aops;
extern struct address_space_operations coda_symlink_aops;
-extern struct file_operations coda_dir_operations;
-extern struct file_operations coda_file_operations;
-extern struct file_operations coda_ioctl_operations;
+extern const struct file_operations coda_dir_operations;
+extern const struct file_operations coda_file_operations;
+extern const struct file_operations coda_ioctl_operations;
/* operations shared over more than one file */
int coda_open(struct inode *i, struct file *f);
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 24d659cdbaf..6d3a654be1a 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -147,6 +147,24 @@ typedef struct compat_sigevent {
} _sigev_un;
} compat_sigevent_t;
+struct compat_robust_list {
+ compat_uptr_t next;
+};
+
+struct compat_robust_list_head {
+ struct compat_robust_list list;
+ compat_long_t futex_offset;
+ compat_uptr_t list_op_pending;
+};
+
+extern void compat_exit_robust_list(struct task_struct *curr);
+
+asmlinkage long
+compat_sys_set_robust_list(struct compat_robust_list_head __user *head,
+ compat_size_t len);
+asmlinkage long
+compat_sys_get_robust_list(int pid, compat_uptr_t *head_ptr,
+ compat_size_t __user *len_ptr);
long compat_sys_semctl(int first, int second, int third, void __user *uptr);
long compat_sys_msgsnd(int first, int second, int third, void __user *uptr);
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
index efb518f16bb..89ab677cb99 100644
--- a/include/linux/compat_ioctl.h
+++ b/include/linux/compat_ioctl.h
@@ -140,6 +140,7 @@ COMPATIBLE_IOCTL(DM_TABLE_DEPS_32)
COMPATIBLE_IOCTL(DM_TABLE_STATUS_32)
COMPATIBLE_IOCTL(DM_LIST_VERSIONS_32)
COMPATIBLE_IOCTL(DM_TARGET_MSG_32)
+COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY_32)
COMPATIBLE_IOCTL(DM_VERSION)
COMPATIBLE_IOCTL(DM_REMOVE_ALL)
COMPATIBLE_IOCTL(DM_LIST_DEVICES)
@@ -155,6 +156,7 @@ COMPATIBLE_IOCTL(DM_TABLE_DEPS)
COMPATIBLE_IOCTL(DM_TABLE_STATUS)
COMPATIBLE_IOCTL(DM_LIST_VERSIONS)
COMPATIBLE_IOCTL(DM_TARGET_MSG)
+COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY)
/* Big K */
COMPATIBLE_IOCTL(PIO_FONT)
COMPATIBLE_IOCTL(GIO_FONT)
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 99e6115d8e5..9cbb781d6f8 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -67,7 +67,7 @@
*
* int any_online_cpu(mask) First online cpu in mask
*
- * for_each_cpu(cpu) for-loop cpu over cpu_possible_map
+ * for_each_possible_cpu(cpu) for-loop cpu over cpu_possible_map
* for_each_online_cpu(cpu) for-loop cpu over cpu_online_map
* for_each_present_cpu(cpu) for-loop cpu over cpu_present_map
*
@@ -405,7 +405,8 @@ int __any_online_cpu(const cpumask_t *mask);
#define any_online_cpu(mask) 0
#endif
-#define for_each_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map)
+#define for_each_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map)
+#define for_each_possible_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map)
#define for_each_online_cpu(cpu) for_each_cpu_mask((cpu), cpu_online_map)
#define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map)
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
index 534d750d922..32503657f14 100644
--- a/include/linux/crash_dump.h
+++ b/include/linux/crash_dump.h
@@ -11,7 +11,7 @@
extern unsigned long long elfcorehdr_addr;
extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
unsigned long, int);
-extern struct file_operations proc_vmcore_operations;
+extern const struct file_operations proc_vmcore_operations;
extern struct proc_dir_entry *proc_vmcore;
#endif /* CONFIG_CRASH_DUMP */
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index d10bd30c337..836325ee093 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -275,6 +275,7 @@ extern void d_move(struct dentry *, struct dentry *);
/* appendix may either be NULL or be used for transname suffixes */
extern struct dentry * d_lookup(struct dentry *, struct qstr *);
extern struct dentry * __d_lookup(struct dentry *, struct qstr *);
+extern struct dentry * d_hash_and_lookup(struct dentry *, struct qstr *);
/* validate "insecure" dentry pointer */
extern int d_validate(struct dentry *, struct dentry *);
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 4b0428e335b..047567d34ca 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -29,7 +29,7 @@ struct debugfs_blob_wrapper {
#if defined(CONFIG_DEBUG_FS)
struct dentry *debugfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
- struct file_operations *fops);
+ const struct file_operations *fops);
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
@@ -58,9 +58,8 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
*/
static inline struct dentry *debugfs_create_file(const char *name, mode_t mode,
- struct dentry *parent,
- void *data,
- struct file_operations *fops)
+ struct dentry *parent, void *data,
+ const struct file_operations *fops)
{
return ERR_PTR(-ENODEV);
}
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 51e0e95a421..aee10b2ea4c 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -97,6 +97,7 @@ struct io_restrictions {
unsigned short hardsect_size;
unsigned int max_segment_size;
unsigned long seg_boundary_mask;
+ unsigned char no_cluster; /* inverted so that 0 is default */
};
struct dm_target {
diff --git a/include/linux/device.h b/include/linux/device.h
index f6e72a65a3f..e8e53b9accc 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -200,6 +200,7 @@ extern int class_device_create_file(struct class_device *,
* @node: for internal use by the driver core only.
* @kobj: for internal use by the driver core only.
* @devt_attr: for internal use by the driver core only.
+ * @groups: optional additional groups to be created
* @dev: if set, a symlink to the struct device is created in the sysfs
* directory for this struct class device.
* @class_data: pointer to whatever you want to store here for this struct
@@ -228,6 +229,7 @@ struct class_device {
struct device * dev; /* not necessary, but nice to have */
void * class_data; /* class-specific data */
struct class_device *parent; /* parent of this child device, if there is one */
+ struct attribute_group ** groups; /* optional groups */
void (*release)(struct class_device *dev);
int (*uevent)(struct class_device *dev, char **envp,
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index fa75ba0d635..c67c6786612 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -80,6 +80,16 @@
*
* DM_TARGET_MSG:
* Pass a message string to the target at a specific offset of a device.
+ *
+ * DM_DEV_SET_GEOMETRY:
+ * Set the geometry of a device by passing in a string in this format:
+ *
+ * "cylinders heads sectors_per_track start_sector"
+ *
+ * Beware that CHS geometry is nearly obsolete and only provided
+ * for compatibility with dm devices that can be booted by a PC
+ * BIOS. See struct hd_geometry for range limits. Also note that
+ * the geometry is erased if the device size changes.
*/
/*
@@ -218,6 +228,7 @@ enum {
/* Added later */
DM_LIST_VERSIONS_CMD,
DM_TARGET_MSG_CMD,
+ DM_DEV_SET_GEOMETRY_CMD
};
/*
@@ -247,6 +258,7 @@ typedef char ioctl_struct[308];
#define DM_TABLE_STATUS_32 _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, ioctl_struct)
#define DM_LIST_VERSIONS_32 _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, ioctl_struct)
#define DM_TARGET_MSG_32 _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, ioctl_struct)
+#define DM_DEV_SET_GEOMETRY_32 _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, ioctl_struct)
#endif
#define DM_IOCTL 0xfd
@@ -270,11 +282,12 @@ typedef char ioctl_struct[308];
#define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl)
#define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl)
+#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4
-#define DM_VERSION_MINOR 5
+#define DM_VERSION_MINOR 6
#define DM_VERSION_PATCHLEVEL 0
-#define DM_VERSION_EXTRA "-ioctl (2005-10-04)"
+#define DM_VERSION_EXTRA "-ioctl (2006-02-17)"
/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index a8731062a74..635690cf3e3 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -14,6 +14,7 @@ enum dma_data_direction {
};
#define DMA_64BIT_MASK 0xffffffffffffffffULL
+#define DMA_48BIT_MASK 0x0000ffffffffffffULL
#define DMA_40BIT_MASK 0x000000ffffffffffULL
#define DMA_39BIT_MASK 0x0000007fffffffffULL
#define DMA_32BIT_MASK 0x00000000ffffffffULL
@@ -21,6 +22,7 @@ enum dma_data_direction {
#define DMA_30BIT_MASK 0x000000003fffffffULL
#define DMA_29BIT_MASK 0x000000001fffffffULL
#define DMA_28BIT_MASK 0x000000000fffffffULL
+#define DMA_24BIT_MASK 0x0000000000ffffffULL
#include <asm/dma-mapping.h>
diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h
index 28f368c526f..fbfa6b52e2f 100644
--- a/include/linux/efs_fs.h
+++ b/include/linux/efs_fs.h
@@ -37,7 +37,7 @@ static inline struct efs_sb_info *SUPER_INFO(struct super_block *sb)
struct statfs;
extern struct inode_operations efs_dir_inode_operations;
-extern struct file_operations efs_dir_operations;
+extern const struct file_operations efs_dir_operations;
extern struct address_space_operations efs_symlink_aops;
extern void efs_read_inode(struct inode *);
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index ad133fcfb23..1713ace808b 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -21,7 +21,7 @@ typedef void (elevator_put_req_fn) (request_queue_t *, struct request *);
typedef void (elevator_activate_req_fn) (request_queue_t *, struct request *);
typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *);
-typedef int (elevator_init_fn) (request_queue_t *, elevator_t *);
+typedef void *(elevator_init_fn) (request_queue_t *, elevator_t *);
typedef void (elevator_exit_fn) (elevator_t *);
struct elevator_ops
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 8bb4f842cde..3ade6a4e3bd 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -833,11 +833,11 @@ do { \
*/
/* dir.c */
-extern struct file_operations ext3_dir_operations;
+extern const struct file_operations ext3_dir_operations;
/* file.c */
extern struct inode_operations ext3_file_inode_operations;
-extern struct file_operations ext3_file_operations;
+extern const struct file_operations ext3_file_operations;
/* namei.c */
extern struct inode_operations ext3_dir_inode_operations;
diff --git a/include/linux/fadvise.h b/include/linux/fadvise.h
index b2913bba35d..e8e747139b9 100644
--- a/include/linux/fadvise.h
+++ b/include/linux/fadvise.h
@@ -18,10 +18,4 @@
#define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */
#endif
-/*
- * Linux-specific fadvise() extensions:
- */
-#define LINUX_FADV_ASYNC_WRITE 32 /* Start writeout on range */
-#define LINUX_FADV_WRITE_WAIT 33 /* Wait upon writeout to range */
-
#endif /* FADVISE_H_INCLUDED */
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 2cb19e6503a..315d89740dd 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -734,7 +734,7 @@ struct fb_tile_ops {
/* A driver may set this flag to indicate that it does want a set_par to be
* called every time when fbcon_switch is executed. The advantage is that with
- * this flag set you can really be shure that set_par is always called before
+ * this flag set you can really be sure that set_par is always called before
* any of the functions dependant on the correct hardware state or altering
* that state, even if you are using some broken X releases. The disadvantage
* is that it introduces unwanted delays to every console switch if set_par
@@ -839,12 +839,10 @@ struct fb_info {
#define FB_LEFT_POS(bpp) (32 - bpp)
#define FB_SHIFT_HIGH(val, bits) ((val) >> (bits))
#define FB_SHIFT_LOW(val, bits) ((val) << (bits))
-#define FB_BIT_NR(b) (7 - (b))
#else
#define FB_LEFT_POS(bpp) (0)
#define FB_SHIFT_HIGH(val, bits) ((val) << (bits))
#define FB_SHIFT_LOW(val, bits) ((val) >> (bits))
-#define FB_BIT_NR(b) (b)
#endif
/*
diff --git a/include/linux/firmware.h b/include/linux/firmware.h
index 2d716080be4..33d8f2087b6 100644
--- a/include/linux/firmware.h
+++ b/include/linux/firmware.h
@@ -19,5 +19,4 @@ int request_firmware_nowait(
void (*cont)(const struct firmware *fw, void *context));
void release_firmware(const struct firmware *fw);
-void register_firmware(const char *name, const u8 *data, size_t size);
#endif
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9d967494695..f813bc8266a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -213,6 +213,10 @@ extern int dir_notify_enable;
#define FIBMAP _IO(0x00,1) /* bmap access */
#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */
+#define SYNC_FILE_RANGE_WAIT_BEFORE 1
+#define SYNC_FILE_RANGE_WRITE 2
+#define SYNC_FILE_RANGE_WAIT_AFTER 4
+
#ifdef __KERNEL__
#include <linux/linkage.h>
@@ -410,6 +414,9 @@ struct block_device {
struct list_head bd_inodes;
void * bd_holder;
int bd_holders;
+#ifdef CONFIG_SYSFS
+ struct list_head bd_holder_list;
+#endif
struct block_device * bd_contains;
unsigned bd_block_size;
struct hd_struct * bd_part;
@@ -493,7 +500,7 @@ struct inode {
struct mutex i_mutex;
struct rw_semaphore i_alloc_sem;
struct inode_operations *i_op;
- struct file_operations *i_fop; /* former ->i_op->default_file_ops */
+ const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
struct super_block *i_sb;
struct file_lock *i_flock;
struct address_space *i_mapping;
@@ -633,7 +640,7 @@ struct file {
} f_u;
struct dentry *f_dentry;
struct vfsmount *f_vfsmnt;
- struct file_operations *f_op;
+ const struct file_operations *f_op;
atomic_t f_count;
unsigned int f_flags;
mode_t f_mode;
@@ -754,6 +761,10 @@ extern void send_sigio(struct fown_struct *fown, int fd, int band);
extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg);
extern int fcntl_getlease(struct file *filp);
+/* fs/sync.c */
+extern int do_sync_file_range(struct file *file, loff_t offset, loff_t endbyte,
+ unsigned int flags);
+
/* fs/locks.c */
extern void locks_init_lock(struct file_lock *);
extern void locks_copy_lock(struct file_lock *, struct file_lock *);
@@ -854,7 +865,7 @@ struct super_block {
*/
struct mutex s_vfs_rename_mutex; /* Kludge */
- /* Granuality of c/m/atime in ns.
+ /* Granularity of c/m/atime in ns.
Cannot be worse than a second */
u32 s_time_gran;
};
@@ -1029,6 +1040,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 *, loff_t *, size_t, unsigned int);
+ ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
};
struct inode_operations {
@@ -1387,11 +1400,11 @@ extern void bd_set_size(struct block_device *, loff_t size);
extern void bd_forget(struct inode *inode);
extern void bdput(struct block_device *);
extern struct block_device *open_by_devnum(dev_t, unsigned);
-extern struct file_operations def_blk_fops;
+extern const struct file_operations def_blk_fops;
extern struct address_space_operations def_blk_aops;
-extern struct file_operations def_chr_fops;
-extern struct file_operations bad_sock_fops;
-extern struct file_operations def_fifo_fops;
+extern const struct file_operations def_chr_fops;
+extern const struct file_operations bad_sock_fops;
+extern const struct file_operations def_fifo_fops;
extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long);
extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long);
@@ -1399,34 +1412,34 @@ extern int blkdev_get(struct block_device *, mode_t, unsigned);
extern int blkdev_put(struct block_device *);
extern int bd_claim(struct block_device *, void *);
extern void bd_release(struct block_device *);
+#ifdef CONFIG_SYSFS
+extern int bd_claim_by_disk(struct block_device *, void *, struct gendisk *);
+extern void bd_release_from_disk(struct block_device *, struct gendisk *);
+#else
+#define bd_claim_by_disk(bdev, holder, disk) bd_claim(bdev, holder)
+#define bd_release_from_disk(bdev, disk) bd_release(bdev)
+#endif
/* fs/char_dev.c */
+#define CHRDEV_MAJOR_HASH_SIZE 255
extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);
extern int register_chrdev_region(dev_t, unsigned, const char *);
extern int register_chrdev(unsigned int, const char *,
- struct file_operations *);
+ const struct file_operations *);
extern int unregister_chrdev(unsigned int, const char *);
extern void unregister_chrdev_region(dev_t, unsigned);
extern int chrdev_open(struct inode *, struct file *);
-extern int get_chrdev_list(char *);
-extern void *acquire_chrdev_list(void);
-extern int count_chrdev_list(void);
-extern void *get_next_chrdev(void *);
-extern int get_chrdev_info(void *, int *, char **);
-extern void release_chrdev_list(void *);
+extern void chrdev_show(struct seq_file *,off_t);
/* fs/block_dev.c */
+#define BLKDEV_MAJOR_HASH_SIZE 255
#define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */
extern const char *__bdevname(dev_t, char *buffer);
extern const char *bdevname(struct block_device *bdev, char *buffer);
extern struct block_device *lookup_bdev(const char *);
extern struct block_device *open_bdev_excl(const char *, int, void *);
extern void close_bdev_excl(struct block_device *);
-extern void *acquire_blkdev_list(void);
-extern int count_blkdev_list(void);
-extern void *get_next_blkdev(void *);
-extern int get_blkdev_info(void *, int *, char **);
-extern void release_blkdev_list(void *);
+extern void blkdev_show(struct seq_file *,off_t);
extern void init_special_inode(struct inode *, umode_t, dev_t);
@@ -1434,9 +1447,9 @@ extern void init_special_inode(struct inode *, umode_t, dev_t);
extern void make_bad_inode(struct inode *);
extern int is_bad_inode(struct inode *);
-extern struct file_operations read_fifo_fops;
-extern struct file_operations write_fifo_fops;
-extern struct file_operations rdwr_fifo_fops;
+extern const struct file_operations read_fifo_fops;
+extern const struct file_operations write_fifo_fops;
+extern const struct file_operations rdwr_fifo_fops;
extern int fs_may_remount_ro(struct super_block *);
@@ -1599,6 +1612,17 @@ extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor
extern void do_generic_mapping_read(struct address_space *mapping,
struct file_ra_state *, struct file *,
loff_t *, read_descriptor_t *, read_actor_t);
+
+/* fs/splice.c */
+extern ssize_t generic_file_splice_read(struct file *, loff_t *,
+ struct pipe_inode_info *, size_t, unsigned int);
+extern ssize_t generic_file_splice_write(struct pipe_inode_info *,
+ struct file *, loff_t *, size_t, unsigned int);
+extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
+ struct file *out, loff_t *, size_t len, unsigned int flags);
+extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+ size_t len, unsigned int flags);
+
extern void
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov,
@@ -1678,7 +1702,7 @@ static inline ssize_t blockdev_direct_IO_own_locking(int rw, struct kiocb *iocb,
nr_segs, get_block, end_io, DIO_OWN_LOCKING);
}
-extern struct file_operations generic_ro_fops;
+extern const struct file_operations generic_ro_fops;
#define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
@@ -1734,9 +1758,9 @@ extern int simple_commit_write(struct file *file, struct page *page,
extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *);
extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
-extern struct file_operations simple_dir_operations;
+extern const struct file_operations simple_dir_operations;
extern struct inode_operations simple_dir_inode_operations;
-struct tree_descr { char *name; struct file_operations *ops; int mode; };
+struct tree_descr { char *name; const struct file_operations *ops; int mode; };
struct dentry *d_alloc_name(struct dentry *, const char *);
extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count);
diff --git a/include/linux/fs_uart_pd.h b/include/linux/fs_uart_pd.h
new file mode 100644
index 00000000000..f5975126b71
--- /dev/null
+++ b/include/linux/fs_uart_pd.h
@@ -0,0 +1,60 @@
+/*
+ * Platform information definitions for the CPM Uart driver.
+ *
+ * 2006 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef FS_UART_PD_H
+#define FS_UART_PD_H
+
+#include <linux/version.h>
+#include <asm/types.h>
+
+enum fs_uart_id {
+ fsid_smc1_uart,
+ fsid_smc2_uart,
+ fsid_scc1_uart,
+ fsid_scc2_uart,
+ fsid_scc3_uart,
+ fsid_scc4_uart,
+ fs_uart_nr,
+};
+
+static inline int fs_uart_id_scc2fsid(int id)
+{
+ return fsid_scc1_uart + id - 1;
+}
+
+static inline int fs_uart_id_fsid2scc(int id)
+{
+ return id - fsid_scc1_uart + 1;
+}
+
+static inline int fs_uart_id_smc2fsid(int id)
+{
+ return fsid_smc1_uart + id - 1;
+}
+
+static inline int fs_uart_id_fsid2smc(int id)
+{
+ return id - fsid_smc1_uart + 1;
+}
+
+struct fs_uart_platform_info {
+ void(*init_ioports)(void);
+ /* device specific information */
+ int fs_no; /* controller index */
+ u32 uart_clk;
+ u8 tx_num_fifo;
+ u8 tx_buf_size;
+ u8 rx_num_fifo;
+ u8 rx_buf_size;
+ u8 brg;
+};
+
+#endif
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index a3a0e078f79..16fbe59edeb 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -110,5 +110,16 @@ struct fsl_usb2_platform_data {
#define FSL_USB2_PORT0_ENABLED 0x00000001
#define FSL_USB2_PORT1_ENABLED 0x00000002
+struct fsl_spi_platform_data {
+ u32 initial_spmode; /* initial SPMODE value */
+ u16 bus_num;
+
+ /* board specific information */
+ u16 max_chipselect;
+ void (*activate_cs)(u8 cs, u8 polarity);
+ void (*deactivate_cs)(u8 cs, u8 polarity);
+ u32 sysclk;
+};
+
#endif /* _FSL_DEVICE_H_ */
#endif /* __KERNEL__ */
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 10f96c31971..966a5b3da43 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -1,6 +1,8 @@
#ifndef _LINUX_FUTEX_H
#define _LINUX_FUTEX_H
+#include <linux/sched.h>
+
/* Second argument to futex syscall */
@@ -11,10 +13,97 @@
#define FUTEX_CMP_REQUEUE 4
#define FUTEX_WAKE_OP 5
+/*
+ * Support for robust futexes: the kernel cleans up held futexes at
+ * thread exit time.
+ */
+
+/*
+ * Per-lock list entry - embedded in user-space locks, somewhere close
+ * to the futex field. (Note: user-space uses a double-linked list to
+ * achieve O(1) list add and remove, but the kernel only needs to know
+ * about the forward link)
+ *
+ * NOTE: this structure is part of the syscall ABI, and must not be
+ * changed.
+ */
+struct robust_list {
+ struct robust_list __user *next;
+};
+
+/*
+ * Per-thread list head:
+ *
+ * NOTE: this structure is part of the syscall ABI, and must only be
+ * changed if the change is first communicated with the glibc folks.
+ * (When an incompatible change is done, we'll increase the structure
+ * size, which glibc will detect)
+ */
+struct robust_list_head {
+ /*
+ * The head of the list. Points back to itself if empty:
+ */
+ struct robust_list list;
+
+ /*
+ * This relative offset is set by user-space, it gives the kernel
+ * the relative position of the futex field to examine. This way
+ * we keep userspace flexible, to freely shape its data-structure,
+ * without hardcoding any particular offset into the kernel:
+ */
+ long futex_offset;
+
+ /*
+ * The death of the thread may race with userspace setting
+ * up a lock's links. So to handle this race, userspace first
+ * sets this field to the address of the to-be-taken lock,
+ * then does the lock acquire, and then adds itself to the
+ * list, and then clears this field. Hence the kernel will
+ * always have full knowledge of all locks that the thread
+ * _might_ have taken. We check the owner TID in any case,
+ * so only truly owned locks will be handled.
+ */
+ struct robust_list __user *list_op_pending;
+};
+
+/*
+ * Are there any waiters for this robust futex:
+ */
+#define FUTEX_WAITERS 0x80000000
+
+/*
+ * The kernel signals via this bit that a thread holding a futex
+ * has exited without unlocking the futex. The kernel also does
+ * a FUTEX_WAKE on such futexes, after setting the bit, to wake
+ * up any possible waiters:
+ */
+#define FUTEX_OWNER_DIED 0x40000000
+
+/*
+ * The rest of the robust-futex field is for the TID:
+ */
+#define FUTEX_TID_MASK 0x3fffffff
+
+/*
+ * This limit protects against a deliberately circular list.
+ * (Not worth introducing an rlimit for it)
+ */
+#define ROBUST_LIST_LIMIT 2048
+
long do_futex(unsigned long uaddr, int op, int val,
unsigned long timeout, unsigned long uaddr2, int val2,
int val3);
+extern int handle_futex_death(u32 __user *uaddr, struct task_struct *curr);
+
+#ifdef CONFIG_FUTEX
+extern void exit_robust_list(struct task_struct *curr);
+#else
+static inline void exit_robust_list(struct task_struct *curr)
+{
+}
+#endif
+
#define FUTEX_OP_SET 0 /* *(int *)UADDR2 = OPARG; */
#define FUTEX_OP_ADD 1 /* *(int *)UADDR2 += OPARG; */
#define FUTEX_OP_OR 2 /* *(int *)UADDR2 |= OPARG; */
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index 9c8e6da2393..71e7b2847cb 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -11,6 +11,7 @@
#include <asm/io.h>
#include <linux/list.h>
+#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/timer.h>
@@ -40,7 +41,7 @@ struct gameport {
struct gameport *parent, *child;
struct gameport_driver *drv;
- struct semaphore drv_sem; /* protects serio->drv so attributes can pin driver */
+ struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */
struct device dev;
unsigned int registered; /* port has been fully registered with driver core */
@@ -137,12 +138,12 @@ static inline void gameport_set_drvdata(struct gameport *gameport, void *data)
*/
static inline int gameport_pin_driver(struct gameport *gameport)
{
- return down_interruptible(&gameport->drv_sem);
+ return mutex_lock_interruptible(&gameport->drv_mutex);
}
static inline void gameport_unpin_driver(struct gameport *gameport)
{
- up(&gameport->drv_sem);
+ mutex_unlock(&gameport->drv_mutex);
}
void __gameport_register_driver(struct gameport_driver *drv, struct module *owner);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index fd647fde5ec..2ef845b3517 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -78,6 +78,7 @@ struct hd_struct {
sector_t start_sect;
sector_t nr_sects;
struct kobject kobj;
+ struct kobject *holder_dir;
unsigned ios[2], sectors[2]; /* READs and WRITEs */
int policy, partno;
};
@@ -89,12 +90,12 @@ struct hd_struct {
#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
struct disk_stats {
- unsigned sectors[2]; /* READs and WRITEs */
- unsigned ios[2];
- unsigned merges[2];
- unsigned ticks[2];
- unsigned io_ticks;
- unsigned time_in_queue;
+ unsigned long sectors[2]; /* READs and WRITEs */
+ unsigned long ios[2];
+ unsigned long merges[2];
+ unsigned long ticks[2];
+ unsigned long io_ticks;
+ unsigned long time_in_queue;
};
struct gendisk {
@@ -104,6 +105,7 @@ struct gendisk {
* disks that can't be partitioned. */
char disk_name[32]; /* name of major driver */
struct hd_struct **part; /* [indexed by minor] */
+ int part_uevent_suppress;
struct block_device_operations *fops;
struct request_queue *queue;
void *private_data;
@@ -114,6 +116,8 @@ struct gendisk {
int number; /* more of the same */
struct device *driverfs_dev;
struct kobject kobj;
+ struct kobject *holder_dir;
+ struct kobject *slave_dir;
struct timer_rand_state *random;
int policy;
@@ -149,14 +153,14 @@ struct disk_attribute {
({ \
typeof(gendiskp->dkstats->field) res = 0; \
int i; \
- for_each_cpu(i) \
+ for_each_possible_cpu(i) \
res += per_cpu_ptr(gendiskp->dkstats, i)->field; \
res; \
})
static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) {
int i;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
memset(per_cpu_ptr(gendiskp->dkstats, i), value,
sizeof (struct disk_stats));
}
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 7851e6b520c..3ac452945a7 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -57,6 +57,8 @@ struct vm_area_struct;
__GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \
__GFP_NOMEMALLOC|__GFP_HARDWALL)
+/* This equals 0, but use constants in case they ever change */
+#define GFP_NOWAIT (GFP_ATOMIC & ~__GFP_HIGH)
/* GFP_ATOMIC means both !wait (__GFP_WAIT not set) and use emergency pool */
#define GFP_ATOMIC (__GFP_HIGH)
#define GFP_NOIO (__GFP_WAIT)
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 93830158348..306acf1dc6d 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -58,6 +58,19 @@ struct hrtimer {
};
/**
+ * struct hrtimer_sleeper - simple sleeper structure
+ *
+ * @timer: embedded timer structure
+ * @task: task to wake up
+ *
+ * task is set to NULL, when the timer expires.
+ */
+struct hrtimer_sleeper {
+ struct hrtimer timer;
+ struct task_struct *task;
+};
+
+/**
* struct hrtimer_base - the timer base for a specific clock
*
* @index: clock type index for per_cpu support when moving a timer
@@ -67,7 +80,7 @@ struct hrtimer {
* @first: pointer to the timer node which expires first
* @resolution: the resolution of the clock, in nanoseconds
* @get_time: function to retrieve the current time of the clock
- * @get_sofirq_time: function to retrieve the current time from the softirq
+ * @get_softirq_time: function to retrieve the current time from the softirq
* @curr_timer: the timer which is executing a callback right now
* @softirq_time: the time when running the hrtimer queue in the softirq
*/
@@ -127,6 +140,9 @@ extern long hrtimer_nanosleep(struct timespec *rqtp,
const enum hrtimer_mode mode,
const clockid_t clockid);
+extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
+ struct task_struct *tsk);
+
/* Soft interrupt function to run the hrtimer queues: */
extern void hrtimer_run_queues(void);
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index d6f1019625a..4c5e610fe44 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -154,7 +154,7 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb)
return sb->s_fs_info;
}
-extern struct file_operations hugetlbfs_file_operations;
+extern const struct file_operations hugetlbfs_file_operations;
extern struct vm_operations_struct hugetlb_vm_ops;
struct file *hugetlb_zero_setup(size_t);
int hugetlb_extend_reservation(struct hugetlbfs_inode_info *info,
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 679b46a6a56..c8b81f419fd 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -108,6 +108,10 @@
#define I2C_DRIVERID_UPD64083 78 /* upd64083 video processor */
#define I2C_DRIVERID_UPD64031A 79 /* upd64031a video processor */
#define I2C_DRIVERID_SAA717X 80 /* saa717x video encoder */
+#define I2C_DRIVERID_DS1672 81 /* Dallas/Maxim DS1672 RTC */
+#define I2C_DRIVERID_X1205 82 /* Xicor/Intersil X1205 RTC */
+#define I2C_DRIVERID_PCF8563 83 /* Philips PCF8563 RTC */
+#define I2C_DRIVERID_RS5C372 84 /* Ricoh RS5C372 RTC */
#define I2C_DRIVERID_I2CDEV 900
#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index dd7d627bf66..c115e9e840b 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -1114,8 +1114,11 @@ static inline struct i2o_message *i2o_msg_get(struct i2o_controller *c)
mmsg->mfa = readl(c->in_port);
if (unlikely(mmsg->mfa >= c->in_queue.len)) {
+ u32 mfa = mmsg->mfa;
+
mempool_free(mmsg, c->in_msg.mempool);
- if(mmsg->mfa == I2O_QUEUE_EMPTY)
+
+ if (mfa == I2O_QUEUE_EMPTY)
return ERR_PTR(-EBUSY);
return ERR_PTR(-EFAULT);
}
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 8d2db412ba9..a8bef1d1371 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1220,7 +1220,6 @@ typedef struct ide_pci_enablebit_s {
enum {
/* Uses ISA control ports not PCI ones. */
IDEPCI_FLAG_ISA_PORTS = (1 << 0),
- IDEPCI_FLAG_FORCE_PDC = (1 << 1),
};
typedef struct ide_pci_device_s {
diff --git a/include/linux/init.h b/include/linux/init.h
index ed0ac7c39fd..93dcbe1abb4 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -245,7 +245,8 @@ void __init parse_early_param(void);
#define __cpuexitdata __exitdata
#endif
-#ifdef CONFIG_MEMORY_HOTPLUG
+#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
+ || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
#define __meminit
#define __meminitdata
#define __memexit
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 92146f3b742..41ecbb847f3 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -62,6 +62,8 @@
.posix_timers = LIST_HEAD_INIT(sig.posix_timers), \
.cpu_timers = INIT_CPU_TIMERS(sig.cpu_timers), \
.rlim = INIT_RLIMITS, \
+ .pgrp = 1, \
+ .session = 1, \
}
#define INIT_SIGHAND(sighand) { \
diff --git a/include/linux/input.h b/include/linux/input.h
index 6d4cc3c110d..ce1a756c4c3 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -12,8 +12,6 @@
#ifdef __KERNEL__
#include <linux/time.h>
#include <linux/list.h>
-#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#else
#include <sys/time.h>
#include <sys/ioctl.h>
@@ -58,6 +56,8 @@ struct input_absinfo {
#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */
+#define EVIOCGREP _IOR('E', 0x03, int[2]) /* get repeat settings */
+#define EVIOCSREP _IOW('E', 0x03, int[2]) /* set repeat settings */
#define EVIOCGKEYCODE _IOR('E', 0x04, int[2]) /* get keycode */
#define EVIOCSKEYCODE _IOW('E', 0x04, int[2]) /* set keycode */
@@ -345,6 +345,8 @@ struct input_absinfo {
#define KEY_SAVE 234
#define KEY_DOCUMENTS 235
+#define KEY_BATTERY 236
+
#define KEY_UNKNOWN 240
#define BTN_MISC 0x100
@@ -421,7 +423,7 @@ struct input_absinfo {
#define BTN_GEAR_UP 0x151
#define KEY_OK 0x160
-#define KEY_SELECT 0x161
+#define KEY_SELECT 0x161
#define KEY_GOTO 0x162
#define KEY_CLEAR 0x163
#define KEY_POWER2 0x164
@@ -512,6 +514,15 @@ struct input_absinfo {
#define KEY_FN_S 0x1e3
#define KEY_FN_B 0x1e4
+#define KEY_BRL_DOT1 0x1f1
+#define KEY_BRL_DOT2 0x1f2
+#define KEY_BRL_DOT3 0x1f3
+#define KEY_BRL_DOT4 0x1f4
+#define KEY_BRL_DOT5 0x1f5
+#define KEY_BRL_DOT6 0x1f6
+#define KEY_BRL_DOT7 0x1f7
+#define KEY_BRL_DOT8 0x1f8
+
/* We avoid low common keys in module aliases so they don't get huge. */
#define KEY_MIN_INTERESTING KEY_MUTE
#define KEY_MAX 0x1ff
@@ -568,15 +579,10 @@ struct input_absinfo {
* Switch events
*/
-#define SW_0 0x00
-#define SW_1 0x01
-#define SW_2 0x02
-#define SW_3 0x03
-#define SW_4 0x04
-#define SW_5 0x05
-#define SW_6 0x06
-#define SW_7 0x07
-#define SW_MAX 0x0f
+#define SW_LID 0x00 /* set = lid shut */
+#define SW_TABLET_MODE 0x01 /* set = tablet mode */
+#define SW_HEADPHONE_INSERT 0x02 /* set = inserted */
+#define SW_MAX 0x0f
/*
* Misc events
@@ -796,52 +802,16 @@ struct ff_effect {
#define FF_MAX 0x7f
-struct input_device_id {
-
- kernel_ulong_t flags;
-
- struct input_id id;
-
- kernel_ulong_t evbit[EV_MAX/BITS_PER_LONG+1];
- kernel_ulong_t keybit[KEY_MAX/BITS_PER_LONG+1];
- kernel_ulong_t relbit[REL_MAX/BITS_PER_LONG+1];
- kernel_ulong_t absbit[ABS_MAX/BITS_PER_LONG+1];
- kernel_ulong_t mscbit[MSC_MAX/BITS_PER_LONG+1];
- kernel_ulong_t ledbit[LED_MAX/BITS_PER_LONG+1];
- kernel_ulong_t sndbit[SND_MAX/BITS_PER_LONG+1];
- kernel_ulong_t ffbit[FF_MAX/BITS_PER_LONG+1];
- kernel_ulong_t swbit[SW_MAX/BITS_PER_LONG+1];
-
- kernel_ulong_t driver_info;
-};
-
-/*
- * Structure for hotplug & device<->driver matching.
- */
-
-#define INPUT_DEVICE_ID_MATCH_BUS 1
-#define INPUT_DEVICE_ID_MATCH_VENDOR 2
-#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
-#define INPUT_DEVICE_ID_MATCH_VERSION 8
-
-#define INPUT_DEVICE_ID_MATCH_EVBIT 0x010
-#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x020
-#define INPUT_DEVICE_ID_MATCH_RELBIT 0x040
-#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x080
-#define INPUT_DEVICE_ID_MATCH_MSCIT 0x100
-#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200
-#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400
-#define INPUT_DEVICE_ID_MATCH_FFBIT 0x800
-#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000
-
#ifdef __KERNEL__
/*
* In-kernel definitions.
*/
+#include <linux/device.h>
#include <linux/fs.h>
#include <linux/timer.h>
+#include <linux/mod_devicetable.h>
#define NBITS(x) (((x)/BITS_PER_LONG)+1)
#define BIT(x) (1UL<<((x)%BITS_PER_LONG))
@@ -929,7 +899,7 @@ struct input_dev {
struct input_handle *grab;
- struct semaphore sem; /* serializes open and close operations */
+ struct mutex mutex; /* serializes open and close operations */
unsigned int users;
struct class_device cdev;
@@ -942,9 +912,49 @@ struct input_dev {
};
#define to_input_dev(d) container_of(d, struct input_dev, cdev)
-#define INPUT_DEVICE_ID_MATCH_DEVICE\
+/*
+ * Verify that we are in sync with input_device_id mod_devicetable.h #defines
+ */
+
+#if EV_MAX != INPUT_DEVICE_ID_EV_MAX
+#error "EV_MAX and INPUT_DEVICE_ID_EV_MAX do not match"
+#endif
+
+#if KEY_MAX != INPUT_DEVICE_ID_KEY_MAX
+#error "KEY_MAX and INPUT_DEVICE_ID_KEY_MAX do not match"
+#endif
+
+#if REL_MAX != INPUT_DEVICE_ID_REL_MAX
+#error "REL_MAX and INPUT_DEVICE_ID_REL_MAX do not match"
+#endif
+
+#if ABS_MAX != INPUT_DEVICE_ID_ABS_MAX
+#error "ABS_MAX and INPUT_DEVICE_ID_ABS_MAX do not match"
+#endif
+
+#if MSC_MAX != INPUT_DEVICE_ID_MSC_MAX
+#error "MSC_MAX and INPUT_DEVICE_ID_MSC_MAX do not match"
+#endif
+
+#if LED_MAX != INPUT_DEVICE_ID_LED_MAX
+#error "LED_MAX and INPUT_DEVICE_ID_LED_MAX do not match"
+#endif
+
+#if SND_MAX != INPUT_DEVICE_ID_SND_MAX
+#error "SND_MAX and INPUT_DEVICE_ID_SND_MAX do not match"
+#endif
+
+#if FF_MAX != INPUT_DEVICE_ID_FF_MAX
+#error "FF_MAX and INPUT_DEVICE_ID_FF_MAX do not match"
+#endif
+
+#if SW_MAX != INPUT_DEVICE_ID_SW_MAX
+#error "SW_MAX and INPUT_DEVICE_ID_SW_MAX do not match"
+#endif
+
+#define INPUT_DEVICE_ID_MATCH_DEVICE \
(INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
-#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
+#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION \
(INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
struct input_handle;
@@ -957,7 +967,7 @@ struct input_handler {
struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id);
void (*disconnect)(struct input_handle *handle);
- struct file_operations *fops;
+ const struct file_operations *fops;
int minor;
char *name;
@@ -995,11 +1005,6 @@ static inline void init_input_dev(struct input_dev *dev)
struct input_dev *input_allocate_device(void);
-static inline void input_free_device(struct input_dev *dev)
-{
- kfree(dev);
-}
-
static inline struct input_dev *input_get_device(struct input_dev *dev)
{
return to_input_dev(class_device_get(&dev->cdev));
@@ -1010,6 +1015,12 @@ static inline void input_put_device(struct input_dev *dev)
class_device_put(&dev->cdev);
}
+static inline void input_free_device(struct input_dev *dev)
+{
+ if (dev)
+ input_put_device(dev);
+}
+
int input_register_device(struct input_dev *);
void input_unregister_device(struct input_dev *);
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
index 53571288a9f..6d9c7e4da47 100644
--- a/include/linux/ipmi_smi.h
+++ b/include/linux/ipmi_smi.h
@@ -82,6 +82,13 @@ struct ipmi_smi_handlers
{
struct module *owner;
+ /* The low-level interface cannot start sending messages to
+ the upper layer until this function is called. This may
+ not be NULL, the lower layer must take the interface from
+ this call. */
+ int (*start_processing)(void *send_info,
+ ipmi_smi_t new_intf);
+
/* Called to enqueue an SMI message to be sent. This
operation is not allowed to fail. If an error occurs, it
should report back the error in a received message. It may
@@ -157,13 +164,16 @@ static inline void ipmi_demangle_device_id(unsigned char *data,
}
/* Add a low-level interface to the IPMI driver. Note that if the
- interface doesn't know its slave address, it should pass in zero. */
+ interface doesn't know its slave address, it should pass in zero.
+ The low-level interface should not deliver any messages to the
+ upper layer until the start_processing() function in the handlers
+ is called, and the lower layer must get the interface from that
+ call. */
int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
void *send_info,
struct ipmi_device_id *device_id,
struct device *dev,
- unsigned char slave_addr,
- ipmi_smi_t *intf);
+ unsigned char slave_addr);
/*
* Remove a low-level interface from the IPMI driver. This will
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 99905e18053..043376920f5 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -36,6 +36,8 @@
/* LATCH is used in the interval timer and ftape setup. */
#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
+#define LATCH_HPET ((HPET_TICK_RATE + HZ/2) / HZ)
+
/* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can
* improve accuracy by shifting LSH bits, hence calculating:
* (NOM << LSH) / DEN
@@ -51,9 +53,13 @@
/* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */
#define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8))
+#define ACTHZ_HPET (SH_DIV (HPET_TICK_RATE, LATCH_HPET, 8))
+
/* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */
#define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8))
+#define TICK_NSEC_HPET (SH_DIV(1000000UL * 1000, ACTHZ_HPET, 8))
+
/* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */
#define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ)
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index e87c32a5c86..4eb851ece08 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -135,6 +135,8 @@ static inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag)
#define U(x) ((x) ^ 0xf000)
+#define BRL_UC_ROW 0x2800
+
/* keyboard.c */
struct console;
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 03d6cfaa5b8..f4fc576ed4c 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -87,7 +87,7 @@ extern int cond_resched(void);
(__x < 0) ? -__x : __x; \
})
-extern struct notifier_block *panic_notifier_list;
+extern struct atomic_notifier_head panic_notifier_list;
extern long (*panic_blink)(long time);
NORET_TYPE void panic(const char * fmt, ...)
__attribute__ ((NORET_AND format (printf, 1, 2)));
@@ -124,6 +124,7 @@ extern int get_option(char **str, int *pint);
extern char *get_options(const char *str, int nints, int *ints);
extern unsigned long long memparse(char *ptr, char **retptr);
+extern int core_kernel_text(unsigned long addr);
extern int __kernel_text_address(unsigned long addr);
extern int kernel_text_address(unsigned long addr);
extern int session_of_pgrp(int pgrp);
@@ -176,7 +177,7 @@ static inline void console_verbose(void)
extern void bust_spinlocks(int yes);
extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */
-extern __deprecated_for_modules int panic_timeout;
+extern int panic_timeout;
extern int panic_on_oops;
extern int tainted;
extern const char *print_tainted(void);
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index a484572c302..b46249082cc 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -46,7 +46,7 @@ static inline int kstat_irqs(int irq)
{
int cpu, sum = 0;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
sum += kstat_cpu(cpu).irqs[irq];
return sum;
diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h
index 08488042d74..de76843bbe8 100644
--- a/include/linux/keyboard.h
+++ b/include/linux/keyboard.h
@@ -44,6 +44,7 @@ extern unsigned short plain_map[NR_KEYS];
#define KT_ASCII 9
#define KT_LOCK 10
#define KT_SLOCK 12
+#define KT_BRL 14
#define K(t,v) (((t)<<8)|(v))
#define KTYP(x) ((x) >> 8)
@@ -427,5 +428,17 @@ extern unsigned short plain_map[NR_KEYS];
#define NR_LOCK 8
+#define K_BRL_BLANK K(KT_BRL, 0)
+#define K_BRL_DOT1 K(KT_BRL, 1)
+#define K_BRL_DOT2 K(KT_BRL, 2)
+#define K_BRL_DOT3 K(KT_BRL, 3)
+#define K_BRL_DOT4 K(KT_BRL, 4)
+#define K_BRL_DOT5 K(KT_BRL, 5)
+#define K_BRL_DOT6 K(KT_BRL, 6)
+#define K_BRL_DOT7 K(KT_BRL, 7)
+#define K_BRL_DOT8 K(KT_BRL, 8)
+
+#define NR_BRL 9
+
#define MAX_DIACR 256
#endif
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 4cb1214ec29..c187c53cecd 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -24,6 +24,7 @@
#include <linux/rwsem.h>
#include <linux/kref.h>
#include <linux/kernel.h>
+#include <linux/wait.h>
#include <asm/atomic.h>
#define KOBJ_NAME_LEN 20
@@ -56,6 +57,7 @@ struct kobject {
struct kset * kset;
struct kobj_type * ktype;
struct dentry * dentry;
+ wait_queue_head_t poll;
};
extern int kobject_set_name(struct kobject *, const char *, ...)
@@ -255,9 +257,8 @@ struct subsys_attribute {
};
extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
-extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
-#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
+#if defined(CONFIG_HOTPLUG)
void kobject_uevent(struct kobject *kobj, enum kobject_action action);
int add_uevent_var(char **envp, int num_envp, int *cur_index,
diff --git a/include/linux/leds.h b/include/linux/leds.h
new file mode 100644
index 00000000000..dc23c7c639f
--- /dev/null
+++ b/include/linux/leds.h
@@ -0,0 +1,110 @@
+/*
+ * Driver model for leds and led triggers
+ *
+ * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu>
+ * Copyright (C) 2005 Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __LINUX_LEDS_H_INCLUDED
+#define __LINUX_LEDS_H_INCLUDED
+
+struct device;
+struct class_device;
+/*
+ * LED Core
+ */
+
+enum led_brightness {
+ LED_OFF = 0,
+ LED_HALF = 127,
+ LED_FULL = 255,
+};
+
+struct led_classdev {
+ const char *name;
+ int brightness;
+ int flags;
+
+#define LED_SUSPENDED (1 << 0)
+
+ /* Set LED brightness level */
+ void (*brightness_set)(struct led_classdev *led_cdev,
+ enum led_brightness brightness);
+
+ struct class_device *class_dev;
+ struct list_head node; /* LED Device list */
+ char *default_trigger; /* Trigger to use */
+
+#ifdef CONFIG_LEDS_TRIGGERS
+ /* Protects the trigger data below */
+ rwlock_t trigger_lock;
+
+ struct led_trigger *trigger;
+ struct list_head trig_list;
+ void *trigger_data;
+#endif
+};
+
+extern int led_classdev_register(struct device *parent,
+ struct led_classdev *led_cdev);
+extern void led_classdev_unregister(struct led_classdev *led_cdev);
+extern void led_classdev_suspend(struct led_classdev *led_cdev);
+extern void led_classdev_resume(struct led_classdev *led_cdev);
+
+/*
+ * LED Triggers
+ */
+#ifdef CONFIG_LEDS_TRIGGERS
+
+#define TRIG_NAME_MAX 50
+
+struct led_trigger {
+ /* Trigger Properties */
+ const char *name;
+ void (*activate)(struct led_classdev *led_cdev);
+ void (*deactivate)(struct led_classdev *led_cdev);
+
+ /* LEDs under control by this trigger (for simple triggers) */
+ rwlock_t leddev_list_lock;
+ struct list_head led_cdevs;
+
+ /* Link to next registered trigger */
+ struct list_head next_trig;
+};
+
+/* Registration functions for complex triggers */
+extern int led_trigger_register(struct led_trigger *trigger);
+extern void led_trigger_unregister(struct led_trigger *trigger);
+
+/* Registration functions for simple triggers */
+#define DEFINE_LED_TRIGGER(x) static struct led_trigger *x;
+#define DEFINE_LED_TRIGGER_GLOBAL(x) struct led_trigger *x;
+extern void led_trigger_register_simple(const char *name,
+ struct led_trigger **trigger);
+extern void led_trigger_unregister_simple(struct led_trigger *trigger);
+extern void led_trigger_event(struct led_trigger *trigger,
+ enum led_brightness event);
+
+#else
+
+/* Triggers aren't active - null macros */
+#define DEFINE_LED_TRIGGER(x)
+#define DEFINE_LED_TRIGGER_GLOBAL(x)
+#define led_trigger_register_simple(x, y) do {} while(0)
+#define led_trigger_unregister_simple(x) do {} while(0)
+#define led_trigger_event(x, y) do {} while(0)
+
+#endif
+
+/* Trigger specific functions */
+#ifdef CONFIG_LEDS_TRIGGER_IDE_DISK
+extern void ledtrig_ide_activity(void);
+#else
+#define ledtrig_ide_activity() do {} while(0)
+#endif
+
+#endif /* __LINUX_LEDS_H_INCLUDED */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 047192253c3..b80d2e7fa6d 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -160,8 +160,10 @@ enum {
ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */
+ /* host set flags */
+ ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */
+
/* various lengths of time */
- ATA_TMOUT_EDD = 5 * HZ, /* heuristic */
ATA_TMOUT_PIO = 30 * HZ,
ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */
ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* heuristic */
@@ -279,6 +281,7 @@ struct ata_probe_ent {
unsigned long irq;
unsigned int irq_flags;
unsigned long host_flags;
+ unsigned long host_set_flags;
void __iomem *mmio_base;
void *private_data;
};
@@ -291,6 +294,9 @@ struct ata_host_set {
unsigned int n_ports;
void *private_data;
const struct ata_port_operations *ops;
+ unsigned long flags;
+ int simplex_claimed; /* Keep seperate in case we
+ ever need to do this locked */
struct ata_port * ports[0];
};
@@ -420,6 +426,7 @@ struct ata_port_operations {
void (*set_piomode) (struct ata_port *, struct ata_device *);
void (*set_dmamode) (struct ata_port *, struct ata_device *);
+ unsigned long (*mode_filter) (const struct ata_port *, struct ata_device *, unsigned long);
void (*tf_load) (struct ata_port *ap, const struct ata_taskfile *tf);
void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
@@ -430,6 +437,7 @@ struct ata_port_operations {
void (*dev_select)(struct ata_port *ap, unsigned int device);
void (*phy_reset) (struct ata_port *ap); /* obsolete */
+ void (*set_mode) (struct ata_port *ap);
int (*probe_reset) (struct ata_port *ap, unsigned int *classes);
void (*post_set_mode) (struct ata_port *ap);
@@ -515,7 +523,6 @@ extern void ata_host_set_remove(struct ata_host_set *host_set);
extern int ata_scsi_detect(struct scsi_host_template *sht);
extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
-extern int ata_scsi_error(struct Scsi_Host *host);
extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
extern int ata_scsi_release(struct Scsi_Host *host);
diff --git a/include/linux/libps2.h b/include/linux/libps2.h
index a710bddda4e..08a450a9dbf 100644
--- a/include/linux/libps2.h
+++ b/include/linux/libps2.h
@@ -28,7 +28,7 @@ struct ps2dev {
struct serio *serio;
/* Ensures that only one command is executing at a time */
- struct semaphore cmd_sem;
+ struct mutex cmd_mutex;
/* Used to signal completion from interrupt handler */
wait_queue_head_t wait;
diff --git a/include/linux/list.h b/include/linux/list.h
index 67258b47e9c..76f05718342 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -619,7 +619,7 @@ static inline void hlist_del_rcu(struct hlist_node *n)
static inline void hlist_del_init(struct hlist_node *n)
{
- if (n->pprev) {
+ if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
diff --git a/include/linux/m48t86.h b/include/linux/m48t86.h
new file mode 100644
index 00000000000..915d6b4f0f8
--- /dev/null
+++ b/include/linux/m48t86.h
@@ -0,0 +1,16 @@
+/*
+ * ST M48T86 / Dallas DS12887 RTC driver
+ * Copyright (c) 2006 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct m48t86_ops
+{
+ void (*writebyte)(unsigned char value, unsigned long addr);
+ unsigned char (*readbyte)(unsigned long addr);
+};
diff --git a/include/linux/memory.h b/include/linux/memory.h
index e251dc43d0f..8f04143ca36 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -77,7 +77,6 @@ extern int remove_memory_block(unsigned long, struct mem_section *, int);
#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
-struct notifier_block;
#endif /* CONFIG_MEMORY_HOTPLUG */
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 968b1aa3732..91120638617 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -58,8 +58,6 @@ extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
/* need some defines for these for archs that don't support it */
extern void online_page(struct page *page);
/* VM interface that may be used by firmware interface */
-extern int add_memory(u64 start, u64 size);
-extern int remove_memory(u64 start, u64 size);
extern int online_pages(unsigned long, unsigned long);
/* reasonably generic interface to expand the physical pages in a zone */
@@ -92,11 +90,6 @@ static inline int mhp_notimplemented(const char *func)
return -ENOSYS;
}
-static inline int __add_pages(struct zone *zone, unsigned long start_pfn,
- unsigned long nr_pages)
-{
- return mhp_notimplemented(__FUNCTION__);
-}
#endif /* ! CONFIG_MEMORY_HOTPLUG */
static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
unsigned long nr_pages)
@@ -105,4 +98,8 @@ static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
dump_stack();
return -ENOSYS;
}
+
+extern int add_memory(u64 start, u64 size);
+extern int remove_memory(u64 start, u64 size);
+
#endif /* __LINUX_MEMORY_HOTPLUG_H */
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 6a7621b2b12..f5fdca1d67e 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -36,6 +36,7 @@
#include <linux/nodemask.h>
struct vm_area_struct;
+struct mm_struct;
#ifdef CONFIG_NUMA
diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index 7d09962c3c0..ff0a64073eb 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -12,7 +12,7 @@ extern void migrate_page_copy(struct page *, struct page *);
extern int migrate_page_remove_references(struct page *, struct page *, int);
extern int migrate_pages(struct list_head *l, struct list_head *t,
struct list_head *moved, struct list_head *failed);
-int migrate_pages_to(struct list_head *pagelist,
+extern int migrate_pages_to(struct list_head *pagelist,
struct vm_area_struct *vma, int dest);
extern int fail_migrate_page(struct page *, struct page *);
@@ -26,6 +26,9 @@ static inline int putback_lru_pages(struct list_head *l) { return 0; }
static inline int migrate_pages(struct list_head *l, struct list_head *t,
struct list_head *moved, struct list_head *failed) { return -ENOSYS; }
+static inline int migrate_pages_to(struct list_head *pagelist,
+ struct vm_area_struct *vma, int dest) { return 0; }
+
static inline int migrate_prep(void) { return -ENOSYS; }
/* Possible settings for the migrate_page() method in address_operations */
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index 14ceebfc1ef..5b584dafb5a 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -36,7 +36,7 @@ struct class_device;
struct miscdevice {
int minor;
const char *name;
- struct file_operations *fops;
+ const struct file_operations *fops;
struct list_head list;
struct device *dev;
struct class_device *class;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 6aa016f1d3a..1154684209a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -229,10 +229,9 @@ struct page {
unsigned long private; /* Mapping-private opaque data:
* usually used for buffer_heads
* if PagePrivate set; used for
- * swp_entry_t if PageSwapCache.
- * When page is free, this
+ * swp_entry_t if PageSwapCache;
* indicates order in the buddy
- * system.
+ * system if PG_buddy is set.
*/
struct address_space *mapping; /* If low bit clear, points to
* inode address_space, or NULL.
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 30dd978c1ec..991a37382a2 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -28,6 +28,7 @@ struct mmc_csd {
unsigned short cmdclass;
unsigned short tacc_clks;
unsigned int tacc_ns;
+ unsigned int r2w_factor;
unsigned int max_dtr;
unsigned int read_blkbits;
unsigned int write_blkbits;
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index bdc556d8849..03a14a30c46 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -69,6 +69,7 @@ struct mmc_data {
unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */
unsigned int timeout_clks; /* data timeout (in clocks) */
unsigned int blksz_bits; /* data block size */
+ unsigned int blksz; /* data block size */
unsigned int blocks; /* number of blocks */
unsigned int error; /* data error */
unsigned int flags;
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index ebfc238cc24..2d833715049 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -13,7 +13,9 @@
#include <linux/numa.h>
#include <linux/init.h>
#include <linux/seqlock.h>
+#include <linux/nodemask.h>
#include <asm/atomic.h>
+#include <asm/page.h>
/* Free memory management - zoned buddy allocator. */
#ifndef CONFIG_FORCE_MAX_ZONEORDER
@@ -21,6 +23,7 @@
#else
#define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
#endif
+#define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1))
struct free_area {
struct list_head free_list;
@@ -225,7 +228,6 @@ struct zone {
* Discontig memory support fields.
*/
struct pglist_data *zone_pgdat;
- struct page *zone_mem_map;
/* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
unsigned long zone_start_pfn;
@@ -307,7 +309,6 @@ typedef struct pglist_data {
unsigned long node_spanned_pages; /* total size of physical page
range, including holes */
int node_id;
- struct pglist_data *pgdat_next;
wait_queue_head_t kswapd_wait;
struct task_struct *kswapd;
int kswapd_max_order;
@@ -324,8 +325,6 @@ typedef struct pglist_data {
#include <linux/memory_hotplug.h>
-extern struct pglist_data *pgdat_list;
-
void __get_zone_counts(unsigned long *active, unsigned long *inactive,
unsigned long *free, struct pglist_data *pgdat);
void get_zone_counts(unsigned long *active, unsigned long *inactive,
@@ -350,57 +349,6 @@ unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
*/
#define zone_idx(zone) ((zone) - (zone)->zone_pgdat->node_zones)
-/**
- * for_each_pgdat - helper macro to iterate over all nodes
- * @pgdat - pointer to a pg_data_t variable
- *
- * Meant to help with common loops of the form
- * pgdat = pgdat_list;
- * while(pgdat) {
- * ...
- * pgdat = pgdat->pgdat_next;
- * }
- */
-#define for_each_pgdat(pgdat) \
- for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next)
-
-/*
- * next_zone - helper magic for for_each_zone()
- * Thanks to William Lee Irwin III for this piece of ingenuity.
- */
-static inline struct zone *next_zone(struct zone *zone)
-{
- pg_data_t *pgdat = zone->zone_pgdat;
-
- if (zone < pgdat->node_zones + MAX_NR_ZONES - 1)
- zone++;
- else if (pgdat->pgdat_next) {
- pgdat = pgdat->pgdat_next;
- zone = pgdat->node_zones;
- } else
- zone = NULL;
-
- return zone;
-}
-
-/**
- * for_each_zone - helper macro to iterate over all memory zones
- * @zone - pointer to struct zone variable
- *
- * The user only needs to declare the zone variable, for_each_zone
- * fills it in. This basically means for_each_zone() is an
- * easier to read version of this piece of code:
- *
- * for (pgdat = pgdat_list; pgdat; pgdat = pgdat->node_next)
- * for (i = 0; i < MAX_NR_ZONES; ++i) {
- * struct zone * z = pgdat->node_zones + i;
- * ...
- * }
- * }
- */
-#define for_each_zone(zone) \
- for (zone = pgdat_list->node_zones; zone; zone = next_zone(zone))
-
static inline int populated_zone(struct zone *zone)
{
return (!!zone->present_pages);
@@ -472,6 +420,30 @@ extern struct pglist_data contig_page_data;
#endif /* !CONFIG_NEED_MULTIPLE_NODES */
+extern struct pglist_data *first_online_pgdat(void);
+extern struct pglist_data *next_online_pgdat(struct pglist_data *pgdat);
+extern struct zone *next_zone(struct zone *zone);
+
+/**
+ * for_each_pgdat - helper macro to iterate over all nodes
+ * @pgdat - pointer to a pg_data_t variable
+ */
+#define for_each_online_pgdat(pgdat) \
+ for (pgdat = first_online_pgdat(); \
+ pgdat; \
+ pgdat = next_online_pgdat(pgdat))
+/**
+ * for_each_zone - helper macro to iterate over all memory zones
+ * @zone - pointer to struct zone variable
+ *
+ * The user only needs to declare the zone variable, for_each_zone
+ * fills it in.
+ */
+#define for_each_zone(zone) \
+ for (zone = (first_online_pgdat())->node_zones; \
+ zone; \
+ zone = next_zone(zone))
+
#ifdef CONFIG_SPARSEMEM
#include <asm/sparsemem.h>
#endif
@@ -602,17 +574,6 @@ static inline struct mem_section *__pfn_to_section(unsigned long pfn)
return __nr_to_section(pfn_to_section_nr(pfn));
}
-#define pfn_to_page(pfn) \
-({ \
- unsigned long __pfn = (pfn); \
- __section_mem_map_addr(__pfn_to_section(__pfn)) + __pfn; \
-})
-#define page_to_pfn(page) \
-({ \
- page - __section_mem_map_addr(__nr_to_section( \
- page_to_section(page))); \
-})
-
static inline int pfn_valid(unsigned long pfn)
{
if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 7b08c11ec4c..f6977708585 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -249,4 +249,52 @@ struct i2c_device_id {
__u16 id;
};
+/* Input */
+#define INPUT_DEVICE_ID_EV_MAX 0x1f
+#define INPUT_DEVICE_ID_KEY_MAX 0x1ff
+#define INPUT_DEVICE_ID_REL_MAX 0x0f
+#define INPUT_DEVICE_ID_ABS_MAX 0x3f
+#define INPUT_DEVICE_ID_MSC_MAX 0x07
+#define INPUT_DEVICE_ID_LED_MAX 0x0f
+#define INPUT_DEVICE_ID_SND_MAX 0x07
+#define INPUT_DEVICE_ID_FF_MAX 0x7f
+#define INPUT_DEVICE_ID_SW_MAX 0x0f
+
+#define INPUT_DEVICE_ID_MATCH_BUS 1
+#define INPUT_DEVICE_ID_MATCH_VENDOR 2
+#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
+#define INPUT_DEVICE_ID_MATCH_VERSION 8
+
+#define INPUT_DEVICE_ID_MATCH_EVBIT 0x0010
+#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x0020
+#define INPUT_DEVICE_ID_MATCH_RELBIT 0x0040
+#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x0080
+#define INPUT_DEVICE_ID_MATCH_MSCIT 0x0100
+#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x0200
+#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x0400
+#define INPUT_DEVICE_ID_MATCH_FFBIT 0x0800
+#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000
+
+struct input_device_id {
+
+ kernel_ulong_t flags;
+
+ __u16 bustype;
+ __u16 vendor;
+ __u16 product;
+ __u16 version;
+
+ kernel_ulong_t evbit[INPUT_DEVICE_ID_EV_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t keybit[INPUT_DEVICE_ID_KEY_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t relbit[INPUT_DEVICE_ID_REL_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t absbit[INPUT_DEVICE_ID_ABS_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t mscbit[INPUT_DEVICE_ID_MSC_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t ledbit[INPUT_DEVICE_ID_LED_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];
+
+ kernel_ulong_t driver_info;
+};
+
#endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 779e6a5744c..d9035c73e5d 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -334,7 +334,7 @@ extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
unsigned long *mapped_blocks);
/* fat/dir.c */
-extern struct file_operations fat_dir_operations;
+extern const struct file_operations fat_dir_operations;
extern int fat_search_long(struct inode *inode, const unsigned char *name,
int name_len, struct fat_slot_info *sinfo);
extern int fat_dir_empty(struct inode *dir);
@@ -397,7 +397,7 @@ extern int fat_count_free_clusters(struct super_block *sb);
/* fat/file.c */
extern int fat_generic_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern struct file_operations fat_file_operations;
+extern const struct file_operations fat_file_operations;
extern struct inode_operations fat_file_inode_operations;
extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
extern void fat_truncate(struct inode *inode);
@@ -420,6 +420,9 @@ extern int date_dos2unix(unsigned short time, unsigned short date);
extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date);
extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
+int fat_cache_init(void);
+void fat_cache_destroy(void);
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
index f46afec6fbf..72fc68c5ee9 100644
--- a/include/linux/mtd/blktrans.h
+++ b/include/linux/mtd/blktrans.h
@@ -10,7 +10,7 @@
#ifndef __MTD_TRANS_H__
#define __MTD_TRANS_H__
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
struct hd_geometry;
struct mtd_info;
@@ -22,7 +22,7 @@ struct mtd_blktrans_dev {
struct mtd_blktrans_ops *tr;
struct list_head list;
struct mtd_info *mtd;
- struct semaphore sem;
+ struct mutex lock;
int devnum;
int blksize;
unsigned long size;
diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h
index 386a52cf8b1..9addd073bf1 100644
--- a/include/linux/mtd/doc2000.h
+++ b/include/linux/mtd/doc2000.h
@@ -15,7 +15,7 @@
#define __MTD_DOC2000_H__
#include <linux/mtd/mtd.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#define DoC_Sig1 0
#define DoC_Sig2 1
@@ -187,7 +187,7 @@ struct DiskOnChip {
int numchips;
struct Nand *chips;
struct mtd_info *nextdoc;
- struct semaphore lock;
+ struct mutex lock;
};
int doc_decode_ecc(unsigned char sector[512], unsigned char ecc1[6]);
diff --git a/include/linux/mtd/inftl.h b/include/linux/mtd/inftl.h
index 0268125a627..d7eaa40e5ab 100644
--- a/include/linux/mtd/inftl.h
+++ b/include/linux/mtd/inftl.h
@@ -52,6 +52,11 @@ struct INFTLrecord {
int INFTL_mount(struct INFTLrecord *s);
int INFTL_formatblock(struct INFTLrecord *s, int block);
+extern char inftlmountrev[];
+
+void INFTL_dumptables(struct INFTLrecord *s);
+void INFTL_dumpVUchains(struct INFTLrecord *s);
+
#endif /* __KERNEL__ */
#endif /* __MTD_INFTL_H__ */
diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h
index 955d3069d72..edfa012fad3 100644
--- a/include/linux/mv643xx.h
+++ b/include/linux/mv643xx.h
@@ -13,7 +13,7 @@
#ifndef __ASM_MV643XX_H
#define __ASM_MV643XX_H
-#ifdef __MIPS__
+#ifdef __mips__
#include <asm/addrspace.h>
#include <asm/marvell.h>
#endif
diff --git a/include/linux/namei.h b/include/linux/namei.h
index e6698013e4d..58cb3d3d44b 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -75,7 +75,6 @@ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
extern void release_open_intent(struct nameidata *);
extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
-extern __deprecated_for_modules struct dentry * lookup_hash(struct nameidata *);
extern int follow_down(struct vfsmount **, struct dentry **);
extern int follow_up(struct vfsmount **, struct dentry **);
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index e0134256853..96dc237b8f0 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -209,7 +209,7 @@ void ncp_update_inode2(struct inode *, struct ncp_entry_info *);
/* linux/fs/ncpfs/dir.c */
extern struct inode_operations ncp_dir_inode_operations;
-extern struct file_operations ncp_dir_operations;
+extern const struct file_operations ncp_dir_operations;
int ncp_conn_logged_in(struct super_block *);
int ncp_date_dos2unix(__le16 time, __le16 date);
void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date);
@@ -230,7 +230,7 @@ void ncp_unlock_server(struct ncp_server *server);
/* linux/fs/ncpfs/file.c */
extern struct inode_operations ncp_file_inode_operations;
-extern struct file_operations ncp_file_operations;
+extern const struct file_operations ncp_file_operations;
int ncp_make_open(struct inode *, int);
/* linux/fs/ncpfs/mmap.c */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 950dc55e519..f4169bbb60e 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -433,8 +433,7 @@ struct net_device
/* register/unregister state machine */
enum { NETREG_UNINITIALIZED=0,
- NETREG_REGISTERING, /* called register_netdevice */
- NETREG_REGISTERED, /* completed register todo */
+ NETREG_REGISTERED, /* completed register_netdevice */
NETREG_UNREGISTERING, /* called unregister_netdevice */
NETREG_UNREGISTERED, /* completed unregister todo */
NETREG_RELEASED, /* called free_netdev */
@@ -506,6 +505,8 @@ struct net_device
/* class/net/name entry */
struct class_device class_dev;
+ /* space for optional statistics and wireless sysfs groups */
+ struct attribute_group *sysfs_groups[3];
};
#define NETDEV_ALIGN 32
@@ -598,20 +599,7 @@ DECLARE_PER_CPU(struct softnet_data,softnet_data);
#define HAVE_NETIF_QUEUE
-static inline void __netif_schedule(struct net_device *dev)
-{
- if (!test_and_set_bit(__LINK_STATE_SCHED, &dev->state)) {
- unsigned long flags;
- struct softnet_data *sd;
-
- local_irq_save(flags);
- sd = &__get_cpu_var(softnet_data);
- dev->next_sched = sd->output_queue;
- sd->output_queue = dev;
- raise_softirq_irqoff(NET_TX_SOFTIRQ);
- local_irq_restore(flags);
- }
-}
+extern void __netif_schedule(struct net_device *dev);
static inline void netif_schedule(struct net_device *dev)
{
@@ -675,13 +663,7 @@ static inline void dev_kfree_skb_irq(struct sk_buff *skb)
/* Use this variant in places where it could be invoked
* either from interrupt or non-interrupt context.
*/
-static inline void dev_kfree_skb_any(struct sk_buff *skb)
-{
- if (in_irq() || irqs_disabled())
- dev_kfree_skb_irq(skb);
- else
- dev_kfree_skb(skb);
-}
+extern void dev_kfree_skb_any(struct sk_buff *skb);
#define HAVE_NETIF_RX 1
extern int netif_rx(struct sk_buff *skb);
@@ -768,22 +750,9 @@ static inline int netif_device_present(struct net_device *dev)
return test_bit(__LINK_STATE_PRESENT, &dev->state);
}
-static inline void netif_device_detach(struct net_device *dev)
-{
- if (test_and_clear_bit(__LINK_STATE_PRESENT, &dev->state) &&
- netif_running(dev)) {
- netif_stop_queue(dev);
- }
-}
+extern void netif_device_detach(struct net_device *dev);
-static inline void netif_device_attach(struct net_device *dev)
-{
- if (!test_and_set_bit(__LINK_STATE_PRESENT, &dev->state) &&
- netif_running(dev)) {
- netif_wake_queue(dev);
- __netdev_watchdog_up(dev);
- }
-}
+extern void netif_device_attach(struct net_device *dev);
/*
* Network interface message level settings
@@ -851,20 +820,7 @@ static inline int netif_rx_schedule_prep(struct net_device *dev)
* already been called and returned 1.
*/
-static inline void __netif_rx_schedule(struct net_device *dev)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- dev_hold(dev);
- list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
- if (dev->quota < 0)
- dev->quota += dev->weight;
- else
- dev->quota = dev->weight;
- __raise_softirq_irqoff(NET_RX_SOFTIRQ);
- local_irq_restore(flags);
-}
+extern void __netif_rx_schedule(struct net_device *dev);
/* Try to reschedule poll. Called by irq handler. */
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 412e52ca972..b31a9bca936 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -110,6 +110,8 @@ struct nf_info
/* Function to register/unregister hook points. */
int nf_register_hook(struct nf_hook_ops *reg);
void nf_unregister_hook(struct nf_hook_ops *reg);
+int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n);
+void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n);
/* Functions to register get/setsockopt ranges (non-inclusive). You
need to check permissions yourself! */
@@ -281,16 +283,42 @@ extern void nf_invalidate_cache(int pf);
Returns true or false. */
extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
-struct nf_queue_rerouter {
- void (*save)(const struct sk_buff *skb, struct nf_info *info);
- int (*reroute)(struct sk_buff **skb, const struct nf_info *info);
- int rer_size;
+struct nf_afinfo {
+ unsigned short family;
+ unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, u_int8_t protocol);
+ void (*saveroute)(const struct sk_buff *skb,
+ struct nf_info *info);
+ int (*reroute)(struct sk_buff **skb,
+ const struct nf_info *info);
+ int route_key_size;
};
-#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info))
+extern struct nf_afinfo *nf_afinfo[];
+static inline struct nf_afinfo *nf_get_afinfo(unsigned short family)
+{
+ return rcu_dereference(nf_afinfo[family]);
+}
+
+static inline unsigned int
+nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff,
+ u_int8_t protocol, unsigned short family)
+{
+ struct nf_afinfo *afinfo;
+ unsigned int csum = 0;
+
+ rcu_read_lock();
+ afinfo = nf_get_afinfo(family);
+ if (afinfo)
+ csum = afinfo->checksum(skb, hook, dataoff, protocol);
+ rcu_read_unlock();
+ return csum;
+}
-extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer);
-extern int nf_unregister_queue_rerouter(int pf);
+extern int nf_register_afinfo(struct nf_afinfo *afinfo);
+extern void nf_unregister_afinfo(struct nf_afinfo *afinfo);
+
+#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info))
#include <net/flow.h>
extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 1350e47b023..48cc32d83f7 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -142,6 +142,12 @@ struct xt_counters_info
#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/listhelp.h>
+#ifdef CONFIG_COMPAT
+#define COMPAT_TO_USER 1
+#define COMPAT_FROM_USER -1
+#define COMPAT_CALC_SIZE 0
+#endif
+
struct xt_match
{
struct list_head list;
@@ -175,6 +181,9 @@ struct xt_match
void (*destroy)(const struct xt_match *match, void *matchinfo,
unsigned int matchinfosize);
+ /* Called when userspace align differs from kernel space one */
+ int (*compat)(void *match, void **dstptr, int *size, int convert);
+
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
struct module *me;
@@ -220,6 +229,9 @@ struct xt_target
void (*destroy)(const struct xt_target *target, void *targinfo,
unsigned int targinfosize);
+ /* Called when userspace align differs from kernel space one */
+ int (*compat)(void *target, void **dstptr, int *size, int convert);
+
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
struct module *me;
@@ -314,6 +326,73 @@ extern void xt_proto_fini(int af);
extern struct xt_table_info *xt_alloc_table_info(unsigned int size);
extern void xt_free_table_info(struct xt_table_info *info);
+#ifdef CONFIG_COMPAT
+#include <net/compat.h>
+
+struct compat_xt_entry_match
+{
+ union {
+ struct {
+ u_int16_t match_size;
+ char name[XT_FUNCTION_MAXNAMELEN - 1];
+ u_int8_t revision;
+ } user;
+ struct {
+ u_int16_t match_size;
+ compat_uptr_t match;
+ } kernel;
+ u_int16_t match_size;
+ } u;
+ unsigned char data[0];
+};
+
+struct compat_xt_entry_target
+{
+ union {
+ struct {
+ u_int16_t target_size;
+ char name[XT_FUNCTION_MAXNAMELEN - 1];
+ u_int8_t revision;
+ } user;
+ struct {
+ u_int16_t target_size;
+ compat_uptr_t target;
+ } kernel;
+ u_int16_t target_size;
+ } u;
+ unsigned char data[0];
+};
+
+/* FIXME: this works only on 32 bit tasks
+ * need to change whole approach in order to calculate align as function of
+ * current task alignment */
+
+struct compat_xt_counters
+{
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+ u_int32_t cnt[4];
+#else
+ u_int64_t cnt[2];
+#endif
+};
+
+struct compat_xt_counters_info
+{
+ char name[XT_TABLE_MAXNAMELEN];
+ compat_uint_t num_counters;
+ struct compat_xt_counters counters[0];
+};
+
+#define COMPAT_XT_ALIGN(s) (((s) + (__alignof__(struct compat_xt_counters)-1)) \
+ & ~(__alignof__(struct compat_xt_counters)-1))
+
+extern void xt_compat_lock(int af);
+extern void xt_compat_unlock(int af);
+extern int xt_compat_match(void *match, void **dstptr, int *size, int convert);
+extern int xt_compat_target(void *target, void **dstptr, int *size,
+ int convert);
+
+#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
#endif /* _X_TABLES_H */
diff --git a/include/linux/netfilter/xt_esp.h b/include/linux/netfilter/xt_esp.h
new file mode 100644
index 00000000000..9380fb1c27d
--- /dev/null
+++ b/include/linux/netfilter/xt_esp.h
@@ -0,0 +1,14 @@
+#ifndef _XT_ESP_H
+#define _XT_ESP_H
+
+struct xt_esp
+{
+ u_int32_t spis[2]; /* Security Parameter Index */
+ u_int8_t invflags; /* Inverse flags */
+};
+
+/* Values for "invflags" field in struct xt_esp. */
+#define XT_ESP_INV_SPI 0x01 /* Invert the sense of spi. */
+#define XT_ESP_INV_MASK 0x01 /* All possible flags. */
+
+#endif /*_XT_ESP_H*/
diff --git a/include/linux/netfilter/xt_multiport.h b/include/linux/netfilter/xt_multiport.h
new file mode 100644
index 00000000000..d49ee418371
--- /dev/null
+++ b/include/linux/netfilter/xt_multiport.h
@@ -0,0 +1,30 @@
+#ifndef _XT_MULTIPORT_H
+#define _XT_MULTIPORT_H
+
+enum xt_multiport_flags
+{
+ XT_MULTIPORT_SOURCE,
+ XT_MULTIPORT_DESTINATION,
+ XT_MULTIPORT_EITHER
+};
+
+#define XT_MULTI_PORTS 15
+
+/* Must fit inside union xt_matchinfo: 16 bytes */
+struct xt_multiport
+{
+ u_int8_t flags; /* Type of comparison */
+ u_int8_t count; /* Number of ports */
+ u_int16_t ports[XT_MULTI_PORTS]; /* Ports */
+};
+
+struct xt_multiport_v1
+{
+ u_int8_t flags; /* Type of comparison */
+ u_int8_t count; /* Number of ports */
+ u_int16_t ports[XT_MULTI_PORTS]; /* Ports */
+ u_int8_t pflags[XT_MULTI_PORTS]; /* Port flags */
+ u_int8_t invert; /* Invert flag */
+};
+
+#endif /*_XT_MULTIPORT_H*/
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 43c09d790b8..85301c5e8d2 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -80,6 +80,8 @@ enum nf_ip_hook_priorities {
#ifdef __KERNEL__
extern int ip_route_me_harder(struct sk_buff **pskb);
extern int ip_xfrm_me_harder(struct sk_buff **pskb);
+extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, u_int8_t protocol);
#endif /*__KERNEL__*/
#endif /*__LINUX_IP_NETFILTER_H*/
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index f32d75c4f4c..d54d7b278e9 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -308,29 +308,30 @@ DECLARE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache);
#define CONNTRACK_ECACHE(x) (__get_cpu_var(ip_conntrack_ecache).x)
-extern struct notifier_block *ip_conntrack_chain;
-extern struct notifier_block *ip_conntrack_expect_chain;
+extern struct atomic_notifier_head ip_conntrack_chain;
+extern struct atomic_notifier_head ip_conntrack_expect_chain;
static inline int ip_conntrack_register_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&ip_conntrack_chain, nb);
+ return atomic_notifier_chain_register(&ip_conntrack_chain, nb);
}
static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&ip_conntrack_chain, nb);
+ return atomic_notifier_chain_unregister(&ip_conntrack_chain, nb);
}
static inline int
ip_conntrack_expect_register_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&ip_conntrack_expect_chain, nb);
+ return atomic_notifier_chain_register(&ip_conntrack_expect_chain, nb);
}
static inline int
ip_conntrack_expect_unregister_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&ip_conntrack_expect_chain, nb);
+ return atomic_notifier_chain_unregister(&ip_conntrack_expect_chain,
+ nb);
}
extern void ip_ct_deliver_cached_events(const struct ip_conntrack *ct);
@@ -355,14 +356,14 @@ static inline void ip_conntrack_event(enum ip_conntrack_events event,
struct ip_conntrack *ct)
{
if (is_confirmed(ct) && !is_dying(ct))
- notifier_call_chain(&ip_conntrack_chain, event, ct);
+ atomic_notifier_call_chain(&ip_conntrack_chain, event, ct);
}
static inline void
ip_conntrack_expect_event(enum ip_conntrack_expect_events event,
struct ip_conntrack_expect *exp)
{
- notifier_call_chain(&ip_conntrack_expect_chain, event, exp);
+ atomic_notifier_call_chain(&ip_conntrack_expect_chain, event, exp);
}
#else /* CONFIG_IP_NF_CONNTRACK_EVENTS */
static inline void ip_conntrack_event_cache(enum ip_conntrack_events event,
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
index 0987cea5384..eace86bd2ad 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_h323.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
@@ -3,6 +3,8 @@
#ifdef __KERNEL__
+#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
+
#define RAS_PORT 1719
#define Q931_PORT 1720
#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */
@@ -25,6 +27,56 @@ struct ip_ct_h323_master {
};
};
+struct ip_conntrack_expect;
+
+extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
+ u_int32_t * ip, u_int16_t * port);
+extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
+ struct ip_conntrack_expect *this);
+extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
+ struct ip_conntrack_expect *this);
+extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr,
+ u_int32_t ip, u_int16_t port);
+extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
+ unsigned char **data, int dataoff,
+ TransportAddress * addr,
+ u_int32_t ip, u_int16_t port);
+extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
+ struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress * addr, int count);
+extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
+ struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress * addr, int count);
+extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
+ struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr,
+ u_int16_t port, u_int16_t rtp_port,
+ struct ip_conntrack_expect * rtp_exp,
+ struct ip_conntrack_expect * rtcp_exp);
+extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr, u_int16_t port,
+ struct ip_conntrack_expect * exp);
+extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress * addr, u_int16_t port,
+ struct ip_conntrack_expect * exp);
+extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, TransportAddress * addr,
+ int idx, u_int16_t port,
+ struct ip_conntrack_expect * exp);
+
#endif
#endif
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
index 0bd828081c0..c6e9a0b6d30 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
@@ -2,7 +2,7 @@
* ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323
* conntrack/NAT module.
*
- * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
+ * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
*
* This source code is licensed under General Public License version 2.
*
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
index cc98f7aa5ab..cc98f7aa5ab 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index d5b8c0d6a12..c0dac16e190 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -316,5 +316,23 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb,
void *userdata);
#define IPT_ALIGN(s) XT_ALIGN(s)
+
+#ifdef CONFIG_COMPAT
+#include <net/compat.h>
+
+struct compat_ipt_entry
+{
+ struct ipt_ip ip;
+ compat_uint_t nfcache;
+ u_int16_t target_offset;
+ u_int16_t next_offset;
+ compat_uint_t comefrom;
+ struct compat_xt_counters counters;
+ unsigned char elems[0];
+};
+
+#define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s)
+
+#endif /* CONFIG_COMPAT */
#endif /*__KERNEL__*/
#endif /* _IPTABLES_H */
diff --git a/include/linux/netfilter_ipv4/ipt_esp.h b/include/linux/netfilter_ipv4/ipt_esp.h
index c782a83e53e..78296e7eeff 100644
--- a/include/linux/netfilter_ipv4/ipt_esp.h
+++ b/include/linux/netfilter_ipv4/ipt_esp.h
@@ -1,16 +1,10 @@
#ifndef _IPT_ESP_H
#define _IPT_ESP_H
-struct ipt_esp
-{
- u_int32_t spis[2]; /* Security Parameter Index */
- u_int8_t invflags; /* Inverse flags */
-};
+#include <linux/netfilter/xt_esp.h>
-
-
-/* Values for "invflags" field in struct ipt_esp. */
-#define IPT_ESP_INV_SPI 0x01 /* Invert the sense of spi. */
-#define IPT_ESP_INV_MASK 0x01 /* All possible flags. */
+#define ipt_esp xt_esp
+#define IPT_ESP_INV_SPI XT_ESP_INV_SPI
+#define IPT_ESP_INV_MASK XT_ESP_INV_MASK
#endif /*_IPT_ESP_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_multiport.h b/include/linux/netfilter_ipv4/ipt_multiport.h
index e6b6fff811d..55fe85eca88 100644
--- a/include/linux/netfilter_ipv4/ipt_multiport.h
+++ b/include/linux/netfilter_ipv4/ipt_multiport.h
@@ -1,30 +1,15 @@
#ifndef _IPT_MULTIPORT_H
#define _IPT_MULTIPORT_H
-#include <linux/netfilter_ipv4/ip_tables.h>
-enum ipt_multiport_flags
-{
- IPT_MULTIPORT_SOURCE,
- IPT_MULTIPORT_DESTINATION,
- IPT_MULTIPORT_EITHER
-};
+#include <linux/netfilter/xt_multiport.h>
-#define IPT_MULTI_PORTS 15
+#define IPT_MULTIPORT_SOURCE XT_MULTIPORT_SOURCE
+#define IPT_MULTIPORT_DESTINATION XT_MULTIPORT_DESTINATION
+#define IPT_MULTIPORT_EITHER XT_MULTIPORT_EITHER
-/* Must fit inside union ipt_matchinfo: 16 bytes */
-struct ipt_multiport
-{
- u_int8_t flags; /* Type of comparison */
- u_int8_t count; /* Number of ports */
- u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
-};
+#define IPT_MULTI_PORTS XT_MULTI_PORTS
+
+#define ipt_multiport xt_multiport
+#define ipt_multiport_v1 xt_multiport_v1
-struct ipt_multiport_v1
-{
- u_int8_t flags; /* Type of comparison */
- u_int8_t count; /* Number of ports */
- u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
- u_int8_t pflags[IPT_MULTI_PORTS]; /* Port flags */
- u_int8_t invert; /* Invert flag */
-};
#endif /*_IPT_MULTIPORT_H*/
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index 14f2bd01088..52a7b9e7642 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -73,6 +73,9 @@ enum nf_ip6_hook_priorities {
};
#ifdef CONFIG_NETFILTER
+extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, u_int8_t protocol);
+
extern int ipv6_netfilter_init(void);
extern void ipv6_netfilter_fini(void);
#else /* CONFIG_NETFILTER */
diff --git a/include/linux/netfilter_ipv6/ip6t_esp.h b/include/linux/netfilter_ipv6/ip6t_esp.h
index a91b6abc807..f62eaf53c16 100644
--- a/include/linux/netfilter_ipv6/ip6t_esp.h
+++ b/include/linux/netfilter_ipv6/ip6t_esp.h
@@ -1,14 +1,10 @@
#ifndef _IP6T_ESP_H
#define _IP6T_ESP_H
-struct ip6t_esp
-{
- u_int32_t spis[2]; /* Security Parameter Index */
- u_int8_t invflags; /* Inverse flags */
-};
+#include <linux/netfilter/xt_esp.h>
-/* Values for "invflags" field in struct ip6t_esp. */
-#define IP6T_ESP_INV_SPI 0x01 /* Invert the sense of spi. */
-#define IP6T_ESP_INV_MASK 0x01 /* All possible flags. */
+#define ip6t_esp xt_esp
+#define IP6T_ESP_INV_SPI XT_ESP_INV_SPI
+#define IP6T_ESP_INV_MASK XT_ESP_INV_MASK
#endif /*_IP6T_ESP_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_multiport.h b/include/linux/netfilter_ipv6/ip6t_multiport.h
index efe4954a868..042c92661ce 100644
--- a/include/linux/netfilter_ipv6/ip6t_multiport.h
+++ b/include/linux/netfilter_ipv6/ip6t_multiport.h
@@ -1,21 +1,14 @@
#ifndef _IP6T_MULTIPORT_H
#define _IP6T_MULTIPORT_H
-#include <linux/netfilter_ipv6/ip6_tables.h>
-enum ip6t_multiport_flags
-{
- IP6T_MULTIPORT_SOURCE,
- IP6T_MULTIPORT_DESTINATION,
- IP6T_MULTIPORT_EITHER
-};
+#include <linux/netfilter/xt_multiport.h>
-#define IP6T_MULTI_PORTS 15
+#define IP6T_MULTIPORT_SOURCE XT_MULTIPORT_SOURCE
+#define IP6T_MULTIPORT_DESTINATION XT_MULTIPORT_DESTINATION
+#define IP6T_MULTIPORT_EITHER XT_MULTIPORT_EITHER
-/* Must fit inside union ip6t_matchinfo: 16 bytes */
-struct ip6t_multiport
-{
- u_int8_t flags; /* Type of comparison */
- u_int8_t count; /* Number of ports */
- u_int16_t ports[IP6T_MULTI_PORTS]; /* Ports */
-};
-#endif /*_IPT_MULTIPORT_H*/
+#define IP6T_MULTI_PORTS XT_MULTI_PORTS
+
+#define ip6t_multiport xt_multiport
+
+#endif /*_IP6T_MULTIPORT_H*/
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index f8f3d1c927f..87b8a5703eb 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -143,6 +143,7 @@ struct netlink_skb_parms
__u32 dst_group;
kernel_cap_t eff_cap;
__u32 loginuid; /* Login (audit) uid */
+ __u32 sid; /* SELinux security id */
};
#define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb))
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index cbebd7d1b9e..c71227dd438 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -324,7 +324,7 @@ extern struct inode_operations nfs_file_inode_operations;
#ifdef CONFIG_NFS_V3
extern struct inode_operations nfs3_file_inode_operations;
#endif /* CONFIG_NFS_V3 */
-extern struct file_operations nfs_file_operations;
+extern const struct file_operations nfs_file_operations;
extern struct address_space_operations nfs_file_aops;
static inline struct rpc_cred *nfs_file_cred(struct file *file)
@@ -371,7 +371,7 @@ extern struct inode_operations nfs_dir_inode_operations;
#ifdef CONFIG_NFS_V3
extern struct inode_operations nfs3_dir_inode_operations;
#endif /* CONFIG_NFS_V3 */
-extern struct file_operations nfs_dir_operations;
+extern const struct file_operations nfs_dir_operations;
extern struct dentry_operations nfs_dentry_operations;
extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr);
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 6bad4766d3d..d2a8abb5011 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -67,7 +67,8 @@ struct svc_expkey {
int ek_fsidtype;
u32 ek_fsid[3];
- struct svc_export * ek_export;
+ struct vfsmount * ek_mnt;
+ struct dentry * ek_dentry;
};
#define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
@@ -85,9 +86,6 @@ void nfsd_export_shutdown(void);
void nfsd_export_flush(void);
void exp_readlock(void);
void exp_readunlock(void);
-struct svc_expkey * exp_find_key(struct auth_domain *clp,
- int fsid_type, u32 *fsidv,
- struct cache_req *reqp);
struct svc_export * exp_get_by_name(struct auth_domain *clp,
struct vfsmount *mnt,
struct dentry *dentry,
@@ -101,35 +99,20 @@ int exp_rootfh(struct auth_domain *,
int exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq);
int nfserrno(int errno);
-extern void expkey_put(struct cache_head *item, struct cache_detail *cd);
-extern void svc_export_put(struct cache_head *item, struct cache_detail *cd);
-extern struct cache_detail svc_export_cache, svc_expkey_cache;
+extern struct cache_detail svc_export_cache;
static inline void exp_put(struct svc_export *exp)
{
- svc_export_put(&exp->h, &svc_export_cache);
+ cache_put(&exp->h, &svc_export_cache);
}
static inline void exp_get(struct svc_export *exp)
{
cache_get(&exp->h);
}
-static inline struct svc_export *
+extern struct svc_export *
exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
- struct cache_req *reqp)
-{
- struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
- if (ek && !IS_ERR(ek)) {
- struct svc_export *exp = ek->ek_export;
- int err;
- exp_get(exp);
- expkey_put(&ek->h, &svc_expkey_cache);
- if ((err = cache_check(&svc_export_cache, &exp->h, reqp)))
- exp = ERR_PTR(err);
- return exp;
- } else
- return ERR_PTR(PTR_ERR(ek));
-}
+ struct cache_req *reqp);
#endif /* __KERNEL__ */
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index b959a4525cb..1a9ef3e627d 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -350,11 +350,15 @@ extern nodemask_t node_possible_map;
#define num_possible_nodes() nodes_weight(node_possible_map)
#define node_online(node) node_isset((node), node_online_map)
#define node_possible(node) node_isset((node), node_possible_map)
+#define first_online_node first_node(node_online_map)
+#define next_online_node(nid) next_node((nid), node_online_map)
#else
#define num_online_nodes() 1
#define num_possible_nodes() 1
#define node_online(node) ((node) == 0)
#define node_possible(node) ((node) == 0)
+#define first_online_node 0
+#define next_online_node(nid) (MAX_NUMNODES)
#endif
#define any_online_node(mask) \
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 5937dd6053c..51dbab9710c 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -10,25 +10,107 @@
#ifndef _LINUX_NOTIFIER_H
#define _LINUX_NOTIFIER_H
#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/rwsem.h>
-struct notifier_block
-{
- int (*notifier_call)(struct notifier_block *self, unsigned long, void *);
+/*
+ * Notifier chains are of three types:
+ *
+ * Atomic notifier chains: Chain callbacks run in interrupt/atomic
+ * context. Callouts are not allowed to block.
+ * Blocking notifier chains: Chain callbacks run in process context.
+ * Callouts are allowed to block.
+ * Raw notifier chains: There are no restrictions on callbacks,
+ * registration, or unregistration. All locking and protection
+ * must be provided by the caller.
+ *
+ * atomic_notifier_chain_register() may be called from an atomic context,
+ * but blocking_notifier_chain_register() must be called from a process
+ * context. Ditto for the corresponding _unregister() routines.
+ *
+ * atomic_notifier_chain_unregister() and blocking_notifier_chain_unregister()
+ * _must not_ be called from within the call chain.
+ */
+
+struct notifier_block {
+ int (*notifier_call)(struct notifier_block *, unsigned long, void *);
struct notifier_block *next;
int priority;
};
+struct atomic_notifier_head {
+ spinlock_t lock;
+ struct notifier_block *head;
+};
+
+struct blocking_notifier_head {
+ struct rw_semaphore rwsem;
+ struct notifier_block *head;
+};
+
+struct raw_notifier_head {
+ struct notifier_block *head;
+};
+
+#define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \
+ spin_lock_init(&(name)->lock); \
+ (name)->head = NULL; \
+ } while (0)
+#define BLOCKING_INIT_NOTIFIER_HEAD(name) do { \
+ init_rwsem(&(name)->rwsem); \
+ (name)->head = NULL; \
+ } while (0)
+#define RAW_INIT_NOTIFIER_HEAD(name) do { \
+ (name)->head = NULL; \
+ } while (0)
+
+#define ATOMIC_NOTIFIER_INIT(name) { \
+ .lock = SPIN_LOCK_UNLOCKED, \
+ .head = NULL }
+#define BLOCKING_NOTIFIER_INIT(name) { \
+ .rwsem = __RWSEM_INITIALIZER((name).rwsem), \
+ .head = NULL }
+#define RAW_NOTIFIER_INIT(name) { \
+ .head = NULL }
+
+#define ATOMIC_NOTIFIER_HEAD(name) \
+ struct atomic_notifier_head name = \
+ ATOMIC_NOTIFIER_INIT(name)
+#define BLOCKING_NOTIFIER_HEAD(name) \
+ struct blocking_notifier_head name = \
+ BLOCKING_NOTIFIER_INIT(name)
+#define RAW_NOTIFIER_HEAD(name) \
+ struct raw_notifier_head name = \
+ RAW_NOTIFIER_INIT(name)
#ifdef __KERNEL__
-extern int notifier_chain_register(struct notifier_block **list, struct notifier_block *n);
-extern int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n);
-extern int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v);
+extern int atomic_notifier_chain_register(struct atomic_notifier_head *,
+ struct notifier_block *);
+extern int blocking_notifier_chain_register(struct blocking_notifier_head *,
+ struct notifier_block *);
+extern int raw_notifier_chain_register(struct raw_notifier_head *,
+ struct notifier_block *);
+
+extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *,
+ struct notifier_block *);
+extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *,
+ struct notifier_block *);
+extern int raw_notifier_chain_unregister(struct raw_notifier_head *,
+ struct notifier_block *);
+
+extern int atomic_notifier_call_chain(struct atomic_notifier_head *,
+ unsigned long val, void *v);
+extern int blocking_notifier_call_chain(struct blocking_notifier_head *,
+ unsigned long val, void *v);
+extern int raw_notifier_call_chain(struct raw_notifier_head *,
+ unsigned long val, void *v);
#define NOTIFY_DONE 0x0000 /* Don't care */
#define NOTIFY_OK 0x0001 /* Suits me */
#define NOTIFY_STOP_MASK 0x8000 /* Don't call further */
-#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002) /* Bad/Veto action */
+#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002)
+ /* Bad/Veto action */
/*
* Clean way to return from the notifier and stop further calls.
*/
diff --git a/include/linux/numa.h b/include/linux/numa.h
index f0c539bd3cf..e481feb1bfd 100644
--- a/include/linux/numa.h
+++ b/include/linux/numa.h
@@ -3,11 +3,9 @@
#include <linux/config.h>
-#ifndef CONFIG_FLATMEM
-#include <asm/numnodes.h>
-#endif
-
-#ifndef NODES_SHIFT
+#ifdef CONFIG_NODES_SHIFT
+#define NODES_SHIFT CONFIG_NODES_SHIFT
+#else
#define NODES_SHIFT 0
#endif
diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h
index 559c4c38a9c..0d514b25245 100644
--- a/include/linux/oprofile.h
+++ b/include/linux/oprofile.h
@@ -61,6 +61,16 @@ void oprofile_arch_exit(void);
*/
void oprofile_add_sample(struct pt_regs * const regs, unsigned long event);
+/**
+ * Add an extended sample. Use this when the PC is not from the regs, and
+ * we cannot determine if we're in kernel mode from the regs.
+ *
+ * This function does perform a backtrace.
+ *
+ */
+void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
+ unsigned long event, int is_kernel);
+
/* Use this instead when the PC value is not from the regs. Doesn't
* backtrace. */
void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event);
@@ -74,10 +84,10 @@ void oprofile_add_trace(unsigned long eip);
* the specified file operations.
*/
int oprofilefs_create_file(struct super_block * sb, struct dentry * root,
- char const * name, struct file_operations * fops);
+ char const * name, const struct file_operations * fops);
int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root,
- char const * name, struct file_operations * fops, int perm);
+ char const * name, const struct file_operations * fops, int perm);
/** Create a file for read/write access to an unsigned long. */
int oprofilefs_create_ulong(struct super_block * sb, struct dentry * root,
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 9ea629c02a4..d276a4e2f82 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -48,8 +48,20 @@
/*
* Don't use the *_dontuse flags. Use the macros. Otherwise you'll break
- * locked- and dirty-page accounting. The top eight bits of page->flags are
- * used for page->zone, so putting flag bits there doesn't work.
+ * locked- and dirty-page accounting.
+ *
+ * The page flags field is split into two parts, the main flags area
+ * which extends from the low bits upwards, and the fields area which
+ * extends from the high bits downwards.
+ *
+ * | FIELD | ... | FLAGS |
+ * N-1 ^ 0
+ * (N-FLAGS_RESERVED)
+ *
+ * The fields area is reserved for fields mapping zone, node and SPARSEMEM
+ * section. The boundry between these two areas is defined by
+ * FLAGS_RESERVED which defines the width of the fields section
+ * (see linux/mmzone.h). New flags must _not_ overlap with this area.
*/
#define PG_locked 0 /* Page is locked. Don't touch. */
#define PG_error 1
@@ -74,7 +86,9 @@
#define PG_mappedtodisk 16 /* Has blocks allocated on-disk */
#define PG_reclaim 17 /* To be reclaimed asap */
#define PG_nosave_free 18 /* Free, should not be written */
-#define PG_uncached 19 /* Page has been mapped as uncached */
+#define PG_buddy 19 /* Page is free, on buddy lists */
+
+#define PG_uncached 20 /* Page has been mapped as uncached */
/*
* Global page accounting. One instance per CPU. Only unsigned longs are
@@ -317,6 +331,10 @@ extern void __mod_page_state_offset(unsigned long offset, unsigned long delta);
#define SetPageNosaveFree(page) set_bit(PG_nosave_free, &(page)->flags)
#define ClearPageNosaveFree(page) clear_bit(PG_nosave_free, &(page)->flags)
+#define PageBuddy(page) test_bit(PG_buddy, &(page)->flags)
+#define __SetPageBuddy(page) __set_bit(PG_buddy, &(page)->flags)
+#define __ClearPageBuddy(page) __clear_bit(PG_buddy, &(page)->flags)
+
#define PageMappedToDisk(page) test_bit(PG_mappedtodisk, &(page)->flags)
#define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags)
#define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags)
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 839f0b3c23a..7a1af574ded 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -72,12 +72,14 @@ extern struct page * find_get_page(struct address_space *mapping,
unsigned long index);
extern struct page * find_lock_page(struct address_space *mapping,
unsigned long index);
-extern struct page * find_trylock_page(struct address_space *mapping,
- unsigned long index);
+extern __deprecated_for_modules struct page * find_trylock_page(
+ struct address_space *mapping, unsigned long index);
extern struct page * find_or_create_page(struct address_space *mapping,
unsigned long index, gfp_t gfp_mask);
unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
unsigned int nr_pages, struct page **pages);
+unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start,
+ unsigned int nr_pages, struct page **pages);
unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
int tag, unsigned int nr_pages, struct page **pages);
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 4877e35ae20..936ef82ed76 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -50,7 +50,7 @@
extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags);
extern acpi_status pci_osc_support_set(u32 flags);
#else
-#if !defined(acpi_status)
+#if !defined(AE_ERROR)
typedef u32 acpi_status;
#define AE_ERROR (acpi_status) (0x0001)
#endif
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0aad5a378e9..3a6a4e37a48 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -97,7 +97,13 @@ enum pci_channel_state {
typedef unsigned short __bitwise pci_bus_flags_t;
enum pci_bus_flags {
- PCI_BUS_FLAGS_NO_MSI = (pci_bus_flags_t) 1,
+ PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
+};
+
+struct pci_cap_saved_state {
+ struct hlist_node next;
+ char cap_nr;
+ u32 data[0];
};
/*
@@ -159,6 +165,7 @@ struct pci_dev {
unsigned int block_ucfg_access:1; /* userspace config space access is blocked */
u32 saved_config_space[16]; /* config space saved at suspend time */
+ struct hlist_head saved_cap_space;
struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
int rom_attr_enabled; /* has display of the rom attribute been enabled? */
struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
@@ -169,6 +176,30 @@ struct pci_dev {
#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
#define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
+static inline struct pci_cap_saved_state *pci_find_saved_cap(
+ struct pci_dev *pci_dev,char cap)
+{
+ struct pci_cap_saved_state *tmp;
+ struct hlist_node *pos;
+
+ hlist_for_each_entry(tmp, pos, &pci_dev->saved_cap_space, next) {
+ if (tmp->cap_nr == cap)
+ return tmp;
+ }
+ return NULL;
+}
+
+static inline void pci_add_saved_cap(struct pci_dev *pci_dev,
+ struct pci_cap_saved_state *new_cap)
+{
+ hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space);
+}
+
+static inline void pci_remove_saved_cap(struct pci_cap_saved_state *cap)
+{
+ hlist_del(&cap->next);
+}
+
/*
* For PCI devices, the region numbers are assigned this way:
*
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 6f080ae5928..590dc6dca31 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -356,6 +356,10 @@
#define PCI_DEVICE_ID_ATI_IXP300_SATA 0x436e
#define PCI_DEVICE_ID_ATI_IXP400_IDE 0x4376
#define PCI_DEVICE_ID_ATI_IXP400_SATA 0x4379
+#define PCI_DEVICE_ID_ATI_IXP400_SATA2 0x437a
+#define PCI_DEVICE_ID_ATI_IXP600_SATA 0x4380
+#define PCI_DEVICE_ID_ATI_IXP600_SRAID 0x4381
+#define PCI_DEVICE_ID_ATI_IXP600_IDE 0x438c
#define PCI_VENDOR_ID_VLSI 0x1004
#define PCI_DEVICE_ID_VLSI_82C592 0x0005
@@ -497,7 +501,8 @@
#define PCI_DEVICE_ID_AMD_8111_SMBUS 0x746b
#define PCI_DEVICE_ID_AMD_8111_AUDIO 0x746d
#define PCI_DEVICE_ID_AMD_8151_0 0x7454
-#define PCI_DEVICE_ID_AMD_8131_APIC 0x7450
+#define PCI_DEVICE_ID_AMD_8131_BRIDGE 0x7450
+#define PCI_DEVICE_ID_AMD_8131_APIC 0x7451
#define PCI_DEVICE_ID_AMD_CS5536_ISA 0x2090
#define PCI_DEVICE_ID_AMD_CS5536_FLASH 0x2091
#define PCI_DEVICE_ID_AMD_CS5536_AUDIO 0x2093
@@ -642,6 +647,7 @@
#define PCI_DEVICE_ID_SI_965 0x0965
#define PCI_DEVICE_ID_SI_5511 0x5511
#define PCI_DEVICE_ID_SI_5513 0x5513
+#define PCI_DEVICE_ID_SI_5517 0x5517
#define PCI_DEVICE_ID_SI_5518 0x5518
#define PCI_DEVICE_ID_SI_5571 0x5571
#define PCI_DEVICE_ID_SI_5581 0x5581
@@ -772,6 +778,7 @@
#define PCI_DEVICE_ID_MOTOROLA_HAWK 0x4803
#define PCI_DEVICE_ID_MOTOROLA_HARRIER 0x480b
#define PCI_DEVICE_ID_MOTOROLA_MPC5200 0x5803
+#define PCI_DEVICE_ID_MOTOROLA_MPC5200B 0x5809
#define PCI_VENDOR_ID_PROMISE 0x105a
#define PCI_DEVICE_ID_PROMISE_20265 0x0d30
@@ -1052,6 +1059,7 @@
#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2
#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3
#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x00f9
+#define PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280 0x00fd
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101
#define PCI_DEVICE_ID_NVIDIA_QUADRO 0x0103
@@ -1223,6 +1231,7 @@
#define PCI_DEVICE_ID_VIA_8380_0 0x0204
#define PCI_DEVICE_ID_VIA_3238_0 0x0238
#define PCI_DEVICE_ID_VIA_PT880 0x0258
+#define PCI_DEVICE_ID_VIA_PT880ULTRA 0x0308
#define PCI_DEVICE_ID_VIA_PX8X0_0 0x0259
#define PCI_DEVICE_ID_VIA_3269_0 0x0269
#define PCI_DEVICE_ID_VIA_K8T800PRO_0 0x0282
diff --git a/include/linux/pfn.h b/include/linux/pfn.h
new file mode 100644
index 00000000000..bb01f8b92b5
--- /dev/null
+++ b/include/linux/pfn.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_PFN_H_
+#define _LINUX_PFN_H_
+
+#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
+
+#endif
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 5b2fcb19d2d..29960b03bef 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -1,55 +1,119 @@
#ifndef _LINUX_PID_H
#define _LINUX_PID_H
+#include <linux/rcupdate.h>
+
enum pid_type
{
PIDTYPE_PID,
- PIDTYPE_TGID,
PIDTYPE_PGID,
PIDTYPE_SID,
PIDTYPE_MAX
};
+/*
+ * What is struct pid?
+ *
+ * A struct pid is the kernel's internal notion of a process identifier.
+ * It refers to individual tasks, process groups, and sessions. While
+ * there are processes attached to it the struct pid lives in a hash
+ * table, so it and then the processes that it refers to can be found
+ * quickly from the numeric pid value. The attached processes may be
+ * quickly accessed by following pointers from struct pid.
+ *
+ * Storing pid_t values in the kernel and refering to them later has a
+ * problem. The process originally with that pid may have exited and the
+ * pid allocator wrapped, and another process could have come along
+ * and been assigned that pid.
+ *
+ * Referring to user space processes by holding a reference to struct
+ * task_struct has a problem. When the user space process exits
+ * the now useless task_struct is still kept. A task_struct plus a
+ * stack consumes around 10K of low kernel memory. More precisely
+ * this is THREAD_SIZE + sizeof(struct task_struct). By comparison
+ * a struct pid is about 64 bytes.
+ *
+ * Holding a reference to struct pid solves both of these problems.
+ * It is small so holding a reference does not consume a lot of
+ * resources, and since a new struct pid is allocated when the numeric
+ * pid value is reused we don't mistakenly refer to new processes.
+ */
+
struct pid
{
+ atomic_t count;
/* Try to keep pid_chain in the same cacheline as nr for find_pid */
int nr;
struct hlist_node pid_chain;
- /* list of pids with the same nr, only one of them is in the hash */
- struct list_head pid_list;
+ /* lists of tasks that use this pid */
+ struct hlist_head tasks[PIDTYPE_MAX];
+ struct rcu_head rcu;
};
-#define pid_task(elem, type) \
- list_entry(elem, struct task_struct, pids[type].pid_list)
+struct pid_link
+{
+ struct hlist_node node;
+ struct pid *pid;
+};
+
+static inline struct pid *get_pid(struct pid *pid)
+{
+ if (pid)
+ atomic_inc(&pid->count);
+ return pid;
+}
+
+extern void FASTCALL(put_pid(struct pid *pid));
+extern struct task_struct *FASTCALL(pid_task(struct pid *pid, enum pid_type));
+extern struct task_struct *FASTCALL(get_pid_task(struct pid *pid,
+ enum pid_type));
/*
* attach_pid() and detach_pid() must be called with the tasklist_lock
* write-held.
*/
-extern int FASTCALL(attach_pid(struct task_struct *task, enum pid_type type, int nr));
+extern int FASTCALL(attach_pid(struct task_struct *task,
+ enum pid_type type, int nr));
extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
/*
* look up a PID in the hash table. Must be called with the tasklist_lock
- * held.
+ * or rcu_read_lock() held.
+ */
+extern struct pid *FASTCALL(find_pid(int nr));
+
+/*
+ * Lookup a PID in the hash table, and return with it's count elevated.
*/
-extern struct pid *FASTCALL(find_pid(enum pid_type, int));
+extern struct pid *find_get_pid(int nr);
-extern int alloc_pidmap(void);
-extern void FASTCALL(free_pidmap(int));
-extern void switch_exec_pids(struct task_struct *leader, struct task_struct *thread);
+extern struct pid *alloc_pid(void);
+extern void FASTCALL(free_pid(struct pid *pid));
+#define pid_next(task, type) \
+ ((task)->pids[(type)].node.next)
+
+#define pid_next_task(task, type) \
+ hlist_entry(pid_next(task, type), struct task_struct, \
+ pids[(type)].node)
+
+
+/* We could use hlist_for_each_entry_rcu here but it takes more arguments
+ * than the do_each_task_pid/while_each_task_pid. So we roll our own
+ * to preserve the existing interface.
+ */
#define do_each_task_pid(who, type, task) \
if ((task = find_task_by_pid_type(type, who))) { \
- prefetch((task)->pids[type].pid_list.next); \
+ prefetch(pid_next(task, type)); \
do {
#define while_each_task_pid(who, type, task) \
- } while (task = pid_task((task)->pids[type].pid_list.next,\
- type), \
- prefetch((task)->pids[type].pid_list.next), \
- hlist_unhashed(&(task)->pids[type].pid_chain)); \
- } \
+ } while (pid_next(task, type) && ({ \
+ task = pid_next_task(task, type); \
+ rcu_dereference(task); \
+ prefetch(pid_next(task, type)); \
+ 1; }) ); \
+ }
#endif /* _LINUX_PID_H */
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index b12e59c7575..ea4f7cd7bfd 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -5,17 +5,37 @@
#define PIPE_BUFFERS (16)
+#define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */
+#define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */
+#define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */
+
struct pipe_buffer {
struct page *page;
unsigned int offset, len;
struct pipe_buf_operations *ops;
+ unsigned int flags;
};
+/*
+ * Note on the nesting of these functions:
+ *
+ * ->pin()
+ * ->steal()
+ * ...
+ * ->map()
+ * ...
+ * ->unmap()
+ *
+ * That is, ->map() must be called on a pinned buffer, same goes for ->steal().
+ */
struct pipe_buf_operations {
int can_merge;
- void * (*map)(struct file *, struct pipe_inode_info *, struct pipe_buffer *);
- void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *);
+ void * (*map)(struct pipe_inode_info *, struct pipe_buffer *, int);
+ void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *, void *);
+ int (*pin)(struct pipe_inode_info *, struct pipe_buffer *);
void (*release)(struct pipe_inode_info *, struct pipe_buffer *);
+ int (*steal)(struct pipe_inode_info *, struct pipe_buffer *);
+ void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
};
struct pipe_inode_info {
@@ -31,26 +51,53 @@ struct pipe_inode_info {
unsigned int w_counter;
struct fasync_struct *fasync_readers;
struct fasync_struct *fasync_writers;
+ struct inode *inode;
};
/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
memory allocation, whereas PIPE_BUF makes atomicity guarantees. */
#define PIPE_SIZE PAGE_SIZE
-#define PIPE_MUTEX(inode) (&(inode).i_mutex)
-#define PIPE_WAIT(inode) (&(inode).i_pipe->wait)
-#define PIPE_READERS(inode) ((inode).i_pipe->readers)
-#define PIPE_WRITERS(inode) ((inode).i_pipe->writers)
-#define PIPE_WAITING_WRITERS(inode) ((inode).i_pipe->waiting_writers)
-#define PIPE_RCOUNTER(inode) ((inode).i_pipe->r_counter)
-#define PIPE_WCOUNTER(inode) ((inode).i_pipe->w_counter)
-#define PIPE_FASYNC_READERS(inode) (&((inode).i_pipe->fasync_readers))
-#define PIPE_FASYNC_WRITERS(inode) (&((inode).i_pipe->fasync_writers))
-
/* Drop the inode semaphore and wait for a pipe event, atomically */
-void pipe_wait(struct inode * inode);
+void pipe_wait(struct pipe_inode_info *pipe);
+
+struct pipe_inode_info * alloc_pipe_info(struct inode * inode);
+void free_pipe_info(struct inode * inode);
+void __free_pipe_info(struct pipe_inode_info *);
+
+/* Generic pipe buffer ops functions */
+void *generic_pipe_buf_map(struct pipe_inode_info *, struct pipe_buffer *, int);
+void generic_pipe_buf_unmap(struct pipe_inode_info *, struct pipe_buffer *, void *);
+void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *);
+int generic_pipe_buf_pin(struct pipe_inode_info *, struct pipe_buffer *);
+int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *);
+
+/*
+ * splice is tied to pipes as a transport (at least for now), so we'll just
+ * add the splice flags here.
+ */
+#define SPLICE_F_MOVE (0x01) /* move pages instead of copying */
+#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
+ /* we may still block on the fd we splice */
+ /* from/to, of course */
+#define SPLICE_F_MORE (0x04) /* expect more data */
+#define SPLICE_F_GIFT (0x08) /* pages passed in are a gift */
+
+/*
+ * Passed to the actors
+ */
+struct splice_desc {
+ unsigned int len, total_len; /* current and remaining length */
+ unsigned int flags; /* splice flags */
+ struct file *file; /* file to read/write */
+ loff_t pos; /* file position */
+};
+
+typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
+ struct splice_desc *);
-struct inode* pipe_new(struct inode* inode);
-void free_pipe_info(struct inode* inode);
+extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
+ loff_t *, size_t, unsigned int,
+ splice_actor *);
#endif
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 6df2585c016..66be58902b1 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -199,6 +199,12 @@ extern int device_suspend(pm_message_t state);
extern int dpm_runtime_suspend(struct device *, pm_message_t);
extern void dpm_runtime_resume(struct device *);
+extern void __suspend_report_result(const char *function, void *fn, int ret);
+
+#define suspend_report_result(fn, ret) \
+ do { \
+ __suspend_report_result(__FUNCTION__, fn, ret); \
+ } while (0)
#else /* !CONFIG_PM */
@@ -219,6 +225,8 @@ static inline void dpm_runtime_resume(struct device * dev)
{
}
+#define suspend_report_result(fn, ret) do { } while (0)
+
#endif
/* changes to device_may_wakeup take effect on the next pm state change.
diff --git a/include/linux/pm_legacy.h b/include/linux/pm_legacy.h
index 1252b45face..008932d73c3 100644
--- a/include/linux/pm_legacy.h
+++ b/include/linux/pm_legacy.h
@@ -16,11 +16,6 @@ struct pm_dev __deprecated *
pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
/*
- * Unregister a device with power management
- */
-void __deprecated pm_unregister(struct pm_dev *dev);
-
-/*
* Unregister all devices with matching callback
*/
void __deprecated pm_unregister_all(pm_callback callback);
@@ -41,8 +36,6 @@ static inline struct pm_dev *pm_register(pm_dev_t type,
return NULL;
}
-static inline void pm_unregister(struct pm_dev *dev) {}
-
static inline void pm_unregister_all(pm_callback callback) {}
static inline int pm_send_all(pm_request_t rqst, void *data)
diff --git a/include/linux/poll.h b/include/linux/poll.h
index 8e8f6098508..51e1b56741f 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -11,6 +11,15 @@
#include <linux/mm.h>
#include <asm/uaccess.h>
+/* ~832 bytes of stack space used max in sys_select/sys_poll before allocating
+ additional memory. */
+#define MAX_STACK_ALLOC 832
+#define FRONTEND_STACK_ALLOC 256
+#define SELECT_STACK_ALLOC FRONTEND_STACK_ALLOC
+#define POLL_STACK_ALLOC FRONTEND_STACK_ALLOC
+#define WQUEUES_STACK_ALLOC (MAX_STACK_ALLOC - FRONTEND_STACK_ALLOC)
+#define N_INLINE_POLL_ENTRIES (WQUEUES_STACK_ALLOC / sizeof(struct poll_table_entry))
+
struct poll_table_struct;
/*
@@ -33,6 +42,12 @@ static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc)
pt->qproc = qproc;
}
+struct poll_table_entry {
+ struct file * filp;
+ wait_queue_t wait;
+ wait_queue_head_t * wait_address;
+};
+
/*
* Structures and helpers for sys_poll/sys_poll
*/
@@ -40,6 +55,8 @@ struct poll_wqueues {
poll_table pt;
struct poll_table_page * table;
int error;
+ int inline_index;
+ struct poll_table_entry inline_entries[N_INLINE_POLL_ENTRIES];
};
extern void poll_initwait(struct poll_wqueues *pwq);
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index cb224cf653b..4b47a025342 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -58,7 +58,7 @@ struct proc_dir_entry {
gid_t gid;
loff_t size;
struct inode_operations * proc_iops;
- struct file_operations * proc_fops;
+ const struct file_operations * proc_fops;
get_info_t *get_info;
struct module *owner;
struct proc_dir_entry *next, *parent, *subdir;
@@ -79,7 +79,7 @@ struct kcore_list {
struct vmcore {
struct list_head list;
unsigned long long paddr;
- unsigned long size;
+ unsigned long long size;
loff_t offset;
};
@@ -128,9 +128,9 @@ extern int proc_match(int, const char *,struct proc_dir_entry *);
extern int proc_readdir(struct file *, void *, filldir_t);
extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
-extern struct file_operations proc_kcore_operations;
-extern struct file_operations proc_kmsg_operations;
-extern struct file_operations ppc_htab_operations;
+extern const struct file_operations proc_kcore_operations;
+extern const struct file_operations proc_kmsg_operations;
+extern const struct file_operations ppc_htab_operations;
/*
* proc_tty.c
@@ -189,7 +189,7 @@ static inline struct proc_dir_entry *proc_net_create(const char *name,
}
static inline struct proc_dir_entry *proc_net_fops_create(const char *name,
- mode_t mode, struct file_operations *fops)
+ mode_t mode, const struct file_operations *fops)
{
struct proc_dir_entry *res = create_proc_entry(name, mode, proc_net);
if (res)
diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h
index fc610bb0f73..27f49c85d5d 100644
--- a/include/linux/qnx4_fs.h
+++ b/include/linux/qnx4_fs.h
@@ -118,8 +118,8 @@ extern struct buffer_head *qnx4_bread(struct inode *, int, int);
extern struct inode_operations qnx4_file_inode_operations;
extern struct inode_operations qnx4_dir_inode_operations;
-extern struct file_operations qnx4_file_operations;
-extern struct file_operations qnx4_dir_operations;
+extern const struct file_operations qnx4_file_operations;
+extern const struct file_operations qnx4_dir_operations;
extern int qnx4_is_free(struct super_block *sb, long block);
extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy);
extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode, struct nameidata *nd);
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index b6e0bcad84e..66b44e5e0d6 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -92,7 +92,10 @@ extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
extern void md_super_wait(mddev_t *mddev);
extern int sync_page_io(struct block_device *bdev, sector_t sector, int size,
struct page *page, int rw);
+extern void md_do_sync(mddev_t *mddev);
+extern void md_new_event(mddev_t *mddev);
+extern void md_update_sb(mddev_t * mddev);
#define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); }
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 617b9506c76..e2df61f5b09 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -132,6 +132,14 @@ struct mddev_s
char uuid[16];
+ /* If the array is being reshaped, we need to record the
+ * new shape and an indication of where we are up to.
+ * This is written to the superblock.
+ * If reshape_position is MaxSector, then no reshape is happening (yet).
+ */
+ sector_t reshape_position;
+ int delta_disks, new_level, new_layout, new_chunk;
+
struct mdk_thread_s *thread; /* management thread */
struct mdk_thread_s *sync_thread; /* doing resync or reconstruct */
sector_t curr_resync; /* blocks scheduled */
@@ -143,6 +151,10 @@ struct mddev_s
sector_t resync_mismatches; /* count of sectors where
* parity/replica mismatch found
*/
+
+ /* allow user-space to request suspension of IO to regions of the array */
+ sector_t suspend_lo;
+ sector_t suspend_hi;
/* if zero, use the system-wide default */
int sync_speed_min;
int sync_speed_max;
@@ -157,6 +169,9 @@ struct mddev_s
* DONE: thread is done and is waiting to be reaped
* REQUEST: user-space has requested a sync (used with SYNC)
* CHECK: user-space request for for check-only, no repair
+ * RESHAPE: A reshape is happening
+ *
+ * If neither SYNC or RESHAPE are set, then it is a recovery.
*/
#define MD_RECOVERY_RUNNING 0
#define MD_RECOVERY_SYNC 1
@@ -166,10 +181,11 @@ struct mddev_s
#define MD_RECOVERY_NEEDED 5
#define MD_RECOVERY_REQUESTED 6
#define MD_RECOVERY_CHECK 7
+#define MD_RECOVERY_RESHAPE 8
unsigned long recovery;
int in_sync; /* know to not need resync */
- struct semaphore reconfig_sem;
+ struct mutex reconfig_mutex;
atomic_t active;
int changed; /* true if we might need to reread partition info */
@@ -249,7 +265,8 @@ struct mdk_personality
int (*spare_active) (mddev_t *mddev);
sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
int (*resize) (mddev_t *mddev, sector_t sectors);
- int (*reshape) (mddev_t *mddev, int raid_disks);
+ int (*check_reshape) (mddev_t *mddev);
+ int (*start_reshape) (mddev_t *mddev);
int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
/* quiesce moves between quiescence states
* 0 - fully active
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index c100fa5d4bf..f1fbae7e390 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -102,6 +102,18 @@ typedef struct mdp_device_descriptor_s {
#define MD_SB_ERRORS 1
#define MD_SB_BITMAP_PRESENT 8 /* bitmap may be present nearby */
+
+/*
+ * Notes:
+ * - if an array is being reshaped (restriped) in order to change the
+ * the number of active devices in the array, 'raid_disks' will be
+ * the larger of the old and new numbers. 'delta_disks' will
+ * be the "new - old". So if +ve, raid_disks is the new value, and
+ * "raid_disks-delta_disks" is the old. If -ve, raid_disks is the
+ * old value and "raid_disks+delta_disks" is the new (smaller) value.
+ */
+
+
typedef struct mdp_superblock_s {
/*
* Constant generic information
@@ -146,7 +158,13 @@ typedef struct mdp_superblock_s {
__u32 cp_events_hi; /* 10 high-order of checkpoint update count */
#endif
__u32 recovery_cp; /* 11 recovery checkpoint sector count */
- __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 12];
+ /* There are only valid for minor_version > 90 */
+ __u64 reshape_position; /* 12,13 next address in array-space for reshape */
+ __u32 new_level; /* 14 new level we are reshaping to */
+ __u32 delta_disks; /* 15 change in number of raid_disks */
+ __u32 new_layout; /* 16 new layout */
+ __u32 new_chunk; /* 17 new chunk size (bytes) */
+ __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18];
/*
* Personality information
@@ -207,7 +225,14 @@ struct mdp_superblock_1 {
* NOTE: signed, so bitmap can be before superblock
* only meaningful of feature_map[0] is set.
*/
- __u8 pad1[128-100]; /* set to 0 when written */
+
+ /* These are only valid with feature bit '4' */
+ __u32 new_level; /* new level we are reshaping to */
+ __u64 reshape_position; /* next address in array-space for reshape */
+ __u32 delta_disks; /* change in number of raid_disks */
+ __u32 new_layout; /* new layout */
+ __u32 new_chunk; /* new chunk size (bytes) */
+ __u8 pad1[128-124]; /* set to 0 when written */
/* constant this-device information - 64 bytes */
__u64 data_offset; /* sector start of data, often 0 */
@@ -240,8 +265,9 @@ struct mdp_superblock_1 {
/* feature_map bits */
#define MD_FEATURE_BITMAP_OFFSET 1
+#define MD_FEATURE_RESHAPE_ACTIVE 4
-#define MD_FEATURE_ALL 1
+#define MD_FEATURE_ALL 5
#endif
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
index 394da8207b3..914af667044 100644
--- a/include/linux/raid/raid5.h
+++ b/include/linux/raid/raid5.h
@@ -135,6 +135,7 @@ struct stripe_head {
atomic_t count; /* nr of active thread/requests */
spinlock_t lock;
int bm_seq; /* sequence number for bitmap flushes */
+ int disks; /* disks in stripe */
struct r5dev {
struct bio req;
struct bio_vec vec;
@@ -156,6 +157,7 @@ struct stripe_head {
#define R5_ReadError 8 /* seen a read error here recently */
#define R5_ReWrite 9 /* have tried to over-write the readerror */
+#define R5_Expanded 10 /* This block now has post-expand data */
/*
* Write method
*/
@@ -174,7 +176,9 @@ struct stripe_head {
#define STRIPE_DELAYED 6
#define STRIPE_DEGRADED 7
#define STRIPE_BIT_DELAY 8
-
+#define STRIPE_EXPANDING 9
+#define STRIPE_EXPAND_SOURCE 10
+#define STRIPE_EXPAND_READY 11
/*
* Plugging:
*
@@ -211,12 +215,24 @@ struct raid5_private_data {
int raid_disks, working_disks, failed_disks;
int max_nr_stripes;
+ /* used during an expand */
+ sector_t expand_progress; /* MaxSector when no expand happening */
+ sector_t expand_lo; /* from here up to expand_progress it out-of-bounds
+ * as we haven't flushed the metadata yet
+ */
+ int previous_raid_disks;
+
struct list_head handle_list; /* stripes needing handling */
struct list_head delayed_list; /* stripes that have plugged requests */
struct list_head bitmap_list; /* stripes delaying awaiting bitmap update */
atomic_t preread_active_stripes; /* stripes with scheduled io */
- char cache_name[20];
+ atomic_t reshape_stripes; /* stripes with pending writes for reshape */
+ /* unfortunately we need two cache names as we temporarily have
+ * two caches.
+ */
+ int active_name;
+ char cache_name[2][20];
kmem_cache_t *slab_cache; /* for allocating stripes */
int seq_flush, seq_write;
@@ -238,9 +254,10 @@ struct raid5_private_data {
wait_queue_head_t wait_for_overlap;
int inactive_blocked; /* release of inactive stripes blocked,
* waiting for 25% to be free
- */
+ */
+ int pool_size; /* number of disks in stripeheads in pool */
spinlock_t device_lock;
- struct disk_info disks[0];
+ struct disk_info *disks;
};
typedef struct raid5_private_data raid5_conf_t;
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
index 953b6df5d03..78ecfa28b1c 100644
--- a/include/linux/ramfs.h
+++ b/include/linux/ramfs.h
@@ -15,7 +15,7 @@ extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
extern int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma);
#endif
-extern struct file_operations ramfs_file_operations;
+extern const struct file_operations ramfs_file_operations;
extern struct vm_operations_struct generic_file_vm_ops;
#endif
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 5673008b61e..970284f571a 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -132,6 +132,7 @@ static inline void rcu_bh_qsctr_inc(int cpu)
}
extern int rcu_pending(int cpu);
+extern int rcu_needs_cpu(int cpu);
/**
* rcu_read_lock - mark the beginning of an RCU read-side critical section.
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 912f1b7cb18..5676c4210e2 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1960,7 +1960,7 @@ int reiserfs_global_version_in_proc(char *buffer, char **start, off_t offset,
extern struct inode_operations reiserfs_dir_inode_operations;
extern struct inode_operations reiserfs_symlink_inode_operations;
extern struct inode_operations reiserfs_special_inode_operations;
-extern struct file_operations reiserfs_dir_operations;
+extern const struct file_operations reiserfs_dir_operations;
/* tail_conversion.c */
int direct2indirect(struct reiserfs_transaction_handle *, struct inode *,
@@ -1972,7 +1972,7 @@ void reiserfs_unmap_buffer(struct buffer_head *);
/* file.c */
extern struct inode_operations reiserfs_file_inode_operations;
-extern struct file_operations reiserfs_file_operations;
+extern const struct file_operations reiserfs_file_operations;
extern struct address_space_operations reiserfs_address_space_operations;
/* fix_nodes.c */
diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
deleted file mode 100644
index 7342e66247f..00000000000
--- a/include/linux/relayfs_fs.h
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * linux/include/linux/relayfs_fs.h
- *
- * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
- * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com)
- *
- * RelayFS definitions and declarations
- */
-
-#ifndef _LINUX_RELAYFS_FS_H
-#define _LINUX_RELAYFS_FS_H
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/kref.h>
-
-/*
- * Tracks changes to rchan/rchan_buf structs
- */
-#define RELAYFS_CHANNEL_VERSION 6
-
-/*
- * Per-cpu relay channel buffer
- */
-struct rchan_buf
-{
- void *start; /* start of channel buffer */
- void *data; /* start of current sub-buffer */
- size_t offset; /* current offset into sub-buffer */
- size_t subbufs_produced; /* count of sub-buffers produced */
- size_t subbufs_consumed; /* count of sub-buffers consumed */
- struct rchan *chan; /* associated channel */
- wait_queue_head_t read_wait; /* reader wait queue */
- struct work_struct wake_readers; /* reader wake-up work struct */
- struct dentry *dentry; /* channel file dentry */
- struct kref kref; /* channel buffer refcount */
- struct page **page_array; /* array of current buffer pages */
- unsigned int page_count; /* number of current buffer pages */
- unsigned int finalized; /* buffer has been finalized */
- size_t *padding; /* padding counts per sub-buffer */
- size_t prev_padding; /* temporary variable */
- size_t bytes_consumed; /* bytes consumed in cur read subbuf */
- unsigned int cpu; /* this buf's cpu */
-} ____cacheline_aligned;
-
-/*
- * Relay channel data structure
- */
-struct rchan
-{
- u32 version; /* the version of this struct */
- size_t subbuf_size; /* sub-buffer size */
- size_t n_subbufs; /* number of sub-buffers per buffer */
- size_t alloc_size; /* total buffer size allocated */
- struct rchan_callbacks *cb; /* client callbacks */
- struct kref kref; /* channel refcount */
- void *private_data; /* for user-defined data */
- size_t last_toobig; /* tried to log event > subbuf size */
- struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */
-};
-
-/*
- * Relay channel client callbacks
- */
-struct rchan_callbacks
-{
- /*
- * subbuf_start - called on buffer-switch to a new sub-buffer
- * @buf: the channel buffer containing the new sub-buffer
- * @subbuf: the start of the new sub-buffer
- * @prev_subbuf: the start of the previous sub-buffer
- * @prev_padding: unused space at the end of previous sub-buffer
- *
- * The client should return 1 to continue logging, 0 to stop
- * logging.
- *
- * NOTE: subbuf_start will also be invoked when the buffer is
- * created, so that the first sub-buffer can be initialized
- * if necessary. In this case, prev_subbuf will be NULL.
- *
- * NOTE: the client can reserve bytes at the beginning of the new
- * sub-buffer by calling subbuf_start_reserve() in this callback.
- */
- int (*subbuf_start) (struct rchan_buf *buf,
- void *subbuf,
- void *prev_subbuf,
- size_t prev_padding);
-
- /*
- * buf_mapped - relayfs buffer mmap notification
- * @buf: the channel buffer
- * @filp: relayfs file pointer
- *
- * Called when a relayfs file is successfully mmapped
- */
- void (*buf_mapped)(struct rchan_buf *buf,
- struct file *filp);
-
- /*
- * buf_unmapped - relayfs buffer unmap notification
- * @buf: the channel buffer
- * @filp: relayfs file pointer
- *
- * Called when a relayfs file is successfully unmapped
- */
- void (*buf_unmapped)(struct rchan_buf *buf,
- struct file *filp);
- /*
- * create_buf_file - create file to represent a relayfs channel buffer
- * @filename: the name of the file to create
- * @parent: the parent of the file to create
- * @mode: the mode of the file to create
- * @buf: the channel buffer
- * @is_global: outparam - set non-zero if the buffer should be global
- *
- * Called during relay_open(), once for each per-cpu buffer,
- * to allow the client to create a file to be used to
- * represent the corresponding channel buffer. If the file is
- * created outside of relayfs, the parent must also exist in
- * that filesystem.
- *
- * The callback should return the dentry of the file created
- * to represent the relay buffer.
- *
- * Setting the is_global outparam to a non-zero value will
- * cause relay_open() to create a single global buffer rather
- * than the default set of per-cpu buffers.
- *
- * See Documentation/filesystems/relayfs.txt for more info.
- */
- struct dentry *(*create_buf_file)(const char *filename,
- struct dentry *parent,
- int mode,
- struct rchan_buf *buf,
- int *is_global);
-
- /*
- * remove_buf_file - remove file representing a relayfs channel buffer
- * @dentry: the dentry of the file to remove
- *
- * Called during relay_close(), once for each per-cpu buffer,
- * to allow the client to remove a file used to represent a
- * channel buffer.
- *
- * The callback should return 0 if successful, negative if not.
- */
- int (*remove_buf_file)(struct dentry *dentry);
-};
-
-/*
- * relayfs kernel API, fs/relayfs/relay.c
- */
-
-struct rchan *relay_open(const char *base_filename,
- struct dentry *parent,
- size_t subbuf_size,
- size_t n_subbufs,
- struct rchan_callbacks *cb);
-extern void relay_close(struct rchan *chan);
-extern void relay_flush(struct rchan *chan);
-extern void relay_subbufs_consumed(struct rchan *chan,
- unsigned int cpu,
- size_t consumed);
-extern void relay_reset(struct rchan *chan);
-extern int relay_buf_full(struct rchan_buf *buf);
-
-extern size_t relay_switch_subbuf(struct rchan_buf *buf,
- size_t length);
-extern struct dentry *relayfs_create_dir(const char *name,
- struct dentry *parent);
-extern int relayfs_remove_dir(struct dentry *dentry);
-extern struct dentry *relayfs_create_file(const char *name,
- struct dentry *parent,
- int mode,
- struct file_operations *fops,
- void *data);
-extern int relayfs_remove_file(struct dentry *dentry);
-
-/**
- * relay_write - write data into the channel
- * @chan: relay channel
- * @data: data to be written
- * @length: number of bytes to write
- *
- * Writes data into the current cpu's channel buffer.
- *
- * Protects the buffer by disabling interrupts. Use this
- * if you might be logging from interrupt context. Try
- * __relay_write() if you know you won't be logging from
- * interrupt context.
- */
-static inline void relay_write(struct rchan *chan,
- const void *data,
- size_t length)
-{
- unsigned long flags;
- struct rchan_buf *buf;
-
- local_irq_save(flags);
- buf = chan->buf[smp_processor_id()];
- if (unlikely(buf->offset + length > chan->subbuf_size))
- length = relay_switch_subbuf(buf, length);
- memcpy(buf->data + buf->offset, data, length);
- buf->offset += length;
- local_irq_restore(flags);
-}
-
-/**
- * __relay_write - write data into the channel
- * @chan: relay channel
- * @data: data to be written
- * @length: number of bytes to write
- *
- * Writes data into the current cpu's channel buffer.
- *
- * Protects the buffer by disabling preemption. Use
- * relay_write() if you might be logging from interrupt
- * context.
- */
-static inline void __relay_write(struct rchan *chan,
- const void *data,
- size_t length)
-{
- struct rchan_buf *buf;
-
- buf = chan->buf[get_cpu()];
- if (unlikely(buf->offset + length > buf->chan->subbuf_size))
- length = relay_switch_subbuf(buf, length);
- memcpy(buf->data + buf->offset, data, length);
- buf->offset += length;
- put_cpu();
-}
-
-/**
- * relay_reserve - reserve slot in channel buffer
- * @chan: relay channel
- * @length: number of bytes to reserve
- *
- * Returns pointer to reserved slot, NULL if full.
- *
- * Reserves a slot in the current cpu's channel buffer.
- * Does not protect the buffer at all - caller must provide
- * appropriate synchronization.
- */
-static inline void *relay_reserve(struct rchan *chan, size_t length)
-{
- void *reserved;
- struct rchan_buf *buf = chan->buf[smp_processor_id()];
-
- if (unlikely(buf->offset + length > buf->chan->subbuf_size)) {
- length = relay_switch_subbuf(buf, length);
- if (!length)
- return NULL;
- }
- reserved = buf->data + buf->offset;
- buf->offset += length;
-
- return reserved;
-}
-
-/**
- * subbuf_start_reserve - reserve bytes at the start of a sub-buffer
- * @buf: relay channel buffer
- * @length: number of bytes to reserve
- *
- * Helper function used to reserve bytes at the beginning of
- * a sub-buffer in the subbuf_start() callback.
- */
-static inline void subbuf_start_reserve(struct rchan_buf *buf,
- size_t length)
-{
- BUG_ON(length >= buf->chan->subbuf_size - 1);
- buf->offset = length;
-}
-
-/*
- * exported relay file operations, fs/relayfs/inode.c
- */
-extern struct file_operations relay_file_operations;
-
-#endif /* _LINUX_RELAYFS_FS_H */
-
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index b739ac1f7ca..ab61cd1199f 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -91,10 +91,102 @@ struct rtc_pll_info {
#define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */
#define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */
+/* interrupt flags */
+#define RTC_IRQF 0x80 /* any of the following is active */
+#define RTC_PF 0x40
+#define RTC_AF 0x20
+#define RTC_UF 0x10
+
#ifdef __KERNEL__
#include <linux/interrupt.h>
+extern int rtc_month_days(unsigned int month, unsigned int year);
+extern int rtc_valid_tm(struct rtc_time *tm);
+extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
+extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
+
+#include <linux/device.h>
+#include <linux/seq_file.h>
+#include <linux/cdev.h>
+#include <linux/poll.h>
+#include <linux/mutex.h>
+
+extern struct class *rtc_class;
+
+struct rtc_class_ops {
+ int (*open)(struct device *);
+ void (*release)(struct device *);
+ int (*ioctl)(struct device *, unsigned int, unsigned long);
+ int (*read_time)(struct device *, struct rtc_time *);
+ int (*set_time)(struct device *, struct rtc_time *);
+ int (*read_alarm)(struct device *, struct rtc_wkalrm *);
+ int (*set_alarm)(struct device *, struct rtc_wkalrm *);
+ int (*proc)(struct device *, struct seq_file *);
+ int (*set_mmss)(struct device *, unsigned long secs);
+ int (*irq_set_state)(struct device *, int enabled);
+ int (*irq_set_freq)(struct device *, int freq);
+ int (*read_callback)(struct device *, int data);
+};
+
+#define RTC_DEVICE_NAME_SIZE 20
+struct rtc_task;
+
+struct rtc_device
+{
+ struct class_device class_dev;
+ struct module *owner;
+
+ int id;
+ char name[RTC_DEVICE_NAME_SIZE];
+
+ struct rtc_class_ops *ops;
+ struct mutex ops_lock;
+
+ struct class_device *rtc_dev;
+ struct cdev char_dev;
+ struct mutex char_lock;
+
+ unsigned long irq_data;
+ spinlock_t irq_lock;
+ wait_queue_head_t irq_queue;
+ struct fasync_struct *async_queue;
+
+ struct rtc_task *irq_task;
+ spinlock_t irq_task_lock;
+ int irq_freq;
+};
+#define to_rtc_device(d) container_of(d, struct rtc_device, class_dev)
+
+extern struct rtc_device *rtc_device_register(const char *name,
+ struct device *dev,
+ struct rtc_class_ops *ops,
+ struct module *owner);
+extern void rtc_device_unregister(struct rtc_device *rdev);
+extern int rtc_interface_register(struct class_interface *intf);
+
+extern int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm);
+extern int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm);
+extern int rtc_set_mmss(struct class_device *class_dev, unsigned long secs);
+extern int rtc_read_alarm(struct class_device *class_dev,
+ struct rtc_wkalrm *alrm);
+extern int rtc_set_alarm(struct class_device *class_dev,
+ struct rtc_wkalrm *alrm);
+extern void rtc_update_irq(struct class_device *class_dev,
+ unsigned long num, unsigned long events);
+
+extern struct class_device *rtc_class_open(char *name);
+extern void rtc_class_close(struct class_device *class_dev);
+
+extern int rtc_irq_register(struct class_device *class_dev,
+ struct rtc_task *task);
+extern void rtc_irq_unregister(struct class_device *class_dev,
+ struct rtc_task *task);
+extern int rtc_irq_set_state(struct class_device *class_dev,
+ struct rtc_task *task, int enabled);
+extern int rtc_irq_set_freq(struct class_device *class_dev,
+ struct rtc_task *task, int freq);
+
typedef struct rtc_task {
void (*func)(void *private_data);
void *private_data;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 036d14d2bf9..29b7d4f87d2 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -35,6 +35,7 @@
#include <linux/topology.h>
#include <linux/seccomp.h>
#include <linux/rcupdate.h>
+#include <linux/futex.h>
#include <linux/auxvec.h> /* For AT_VECTOR_SIZE */
@@ -99,6 +100,7 @@ DECLARE_PER_CPU(unsigned long, process_counts);
extern int nr_processes(void);
extern unsigned long nr_running(void);
extern unsigned long nr_uninterruptible(void);
+extern unsigned long nr_active(void);
extern unsigned long nr_iowait(void);
#include <linux/time.h>
@@ -354,16 +356,8 @@ struct sighand_struct {
atomic_t count;
struct k_sigaction action[_NSIG];
spinlock_t siglock;
- struct rcu_head rcu;
};
-extern void sighand_free_cb(struct rcu_head *rhp);
-
-static inline void sighand_free(struct sighand_struct *sp)
-{
- call_rcu(&sp->rcu, sighand_free_cb);
-}
-
/*
* NOTE! "signal_struct" does not have it's own
* locking, because a shared signal_struct always
@@ -490,6 +484,7 @@ struct signal_struct {
#define MAX_PRIO (MAX_RT_PRIO + 40)
#define rt_task(p) (unlikely((p)->prio < MAX_RT_PRIO))
+#define batch_task(p) (unlikely((p)->policy == SCHED_BATCH))
/*
* Some day this will be a full-fledged user tracking system..
@@ -689,6 +684,14 @@ static inline void prefetch_stack(struct task_struct *t) { }
struct audit_context; /* See audit.c */
struct mempolicy;
+struct pipe_inode_info;
+
+enum sleep_type {
+ SLEEP_NORMAL,
+ SLEEP_NONINTERACTIVE,
+ SLEEP_INTERACTIVE,
+ SLEEP_INTERRUPTED,
+};
struct task_struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
@@ -712,7 +715,7 @@ struct task_struct {
unsigned long sleep_avg;
unsigned long long timestamp, last_ran;
unsigned long long sched_time; /* sched_clock time spent running */
- int activated;
+ enum sleep_type sleep_type;
unsigned long policy;
cpumask_t cpus_allowed;
@@ -758,7 +761,8 @@ struct task_struct {
struct task_struct *group_leader; /* threadgroup leader */
/* PID/PID hash table linkage. */
- struct pid pids[PIDTYPE_MAX];
+ struct pid_link pids[PIDTYPE_MAX];
+ struct list_head thread_group;
struct completion *vfork_done; /* for vfork() */
int __user *set_child_tid; /* CLONE_CHILD_SETTID */
@@ -872,8 +876,18 @@ struct task_struct {
int cpuset_mems_generation;
int cpuset_mem_spread_rotor;
#endif
+ struct robust_list_head __user *robust_list;
+#ifdef CONFIG_COMPAT
+ struct compat_robust_list_head __user *compat_robust_list;
+#endif
+
atomic_t fs_excl; /* holding fs exclusive resources */
struct rcu_head rcu;
+
+ /*
+ * cache last used pipe for splice
+ */
+ struct pipe_inode_info *splice_pipe;
};
static inline pid_t process_group(struct task_struct *tsk)
@@ -891,18 +905,18 @@ static inline pid_t process_group(struct task_struct *tsk)
*/
static inline int pid_alive(struct task_struct *p)
{
- return p->pids[PIDTYPE_PID].nr != 0;
+ return p->pids[PIDTYPE_PID].pid != NULL;
}
extern void free_task(struct task_struct *tsk);
#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
-extern void __put_task_struct_cb(struct rcu_head *rhp);
+extern void __put_task_struct(struct task_struct *t);
static inline void put_task_struct(struct task_struct *t)
{
if (atomic_dec_and_test(&t->usage))
- call_rcu(&t->rcu, __put_task_struct_cb);
+ __put_task_struct(t);
}
/*
@@ -1095,7 +1109,6 @@ extern void force_sig_specific(int, struct task_struct *);
extern int send_sig(int, struct task_struct *, int);
extern void zap_other_threads(struct task_struct *p);
extern int kill_pg(pid_t, int, int);
-extern int kill_sl(pid_t, int, int);
extern int kill_proc(pid_t, int, int);
extern struct sigqueue *sigqueue_alloc(void);
extern void sigqueue_free(struct sigqueue *);
@@ -1152,10 +1165,8 @@ extern void flush_thread(void);
extern void exit_thread(void);
extern void exit_files(struct task_struct *);
-extern void exit_signal(struct task_struct *);
-extern void __exit_signal(struct task_struct *);
-extern void exit_sighand(struct task_struct *);
-extern void __exit_sighand(struct task_struct *);
+extern void __cleanup_signal(struct signal_struct *);
+extern void __cleanup_sighand(struct sighand_struct *);
extern void exit_itimers(struct signal_struct *);
extern NORET_TYPE void do_group_exit(int);
@@ -1179,22 +1190,9 @@ extern void wait_task_inactive(task_t * p);
#endif
#define remove_parent(p) list_del_init(&(p)->sibling)
-#define add_parent(p, parent) list_add_tail(&(p)->sibling,&(parent)->children)
-
-#define REMOVE_LINKS(p) do { \
- if (thread_group_leader(p)) \
- list_del_init(&(p)->tasks); \
- remove_parent(p); \
- } while (0)
-
-#define SET_LINKS(p) do { \
- if (thread_group_leader(p)) \
- list_add_tail(&(p)->tasks,&init_task.tasks); \
- add_parent(p, (p)->parent); \
- } while (0)
+#define add_parent(p) list_add_tail(&(p)->sibling,&(p)->parent->children)
-#define next_task(p) list_entry((p)->tasks.next, struct task_struct, tasks)
-#define prev_task(p) list_entry((p)->tasks.prev, struct task_struct, tasks)
+#define next_task(p) list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
#define for_each_process(p) \
for (p = &init_task ; (p = next_task(p)) != &init_task ; )
@@ -1209,20 +1207,23 @@ extern void wait_task_inactive(task_t * p);
#define while_each_thread(g, t) \
while ((t = next_thread(t)) != g)
-extern task_t * FASTCALL(next_thread(const task_t *p));
+/* de_thread depends on thread_group_leader not being a pid based check */
+#define thread_group_leader(p) (p == p->group_leader)
-#define thread_group_leader(p) (p->pid == p->tgid)
+static inline task_t *next_thread(const task_t *p)
+{
+ return list_entry(rcu_dereference(p->thread_group.next),
+ task_t, thread_group);
+}
static inline int thread_group_empty(task_t *p)
{
- return list_empty(&p->pids[PIDTYPE_TGID].pid_list);
+ return list_empty(&p->thread_group);
}
#define delay_group_leader(p) \
(thread_group_leader(p) && !thread_group_empty(p))
-extern void unhash_process(struct task_struct *p);
-
/*
* Protects ->fs, ->files, ->mm, ->ptrace, ->group_info, ->comm, keyring
* subscriptions and synchronises with wait4(). Also used in procfs. Also
@@ -1242,6 +1243,15 @@ static inline void task_unlock(struct task_struct *p)
spin_unlock(&p->alloc_lock);
}
+extern struct sighand_struct *lock_task_sighand(struct task_struct *tsk,
+ unsigned long *flags);
+
+static inline void unlock_task_sighand(struct task_struct *tsk,
+ unsigned long *flags)
+{
+ spin_unlock_irqrestore(&tsk->sighand->siglock, *flags);
+}
+
#ifndef __HAVE_THREAD_FUNCTIONS
#define task_thread_info(task) (task)->thread_info
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 6336987dae6..2925e66a673 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -41,7 +41,8 @@ struct screen_info {
u16 vesapm_off; /* 0x30 */
u16 pages; /* 0x32 */
u16 vesa_attributes; /* 0x34 */
- /* 0x36 -- 0x3f reserved for future expansion */
+ u32 capabilities; /* 0x36 */
+ /* 0x3a -- 0x3f reserved for future expansion */
};
extern struct screen_info screen_info;
diff --git a/include/linux/sdla_asy.h b/include/linux/sdla_asy.h
deleted file mode 100644
index f62242537c8..00000000000
--- a/include/linux/sdla_asy.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/*****************************************************************************
-* sdla_asy.h Header file for the Sangoma S508/S514 asynchronous code API
-*
-* Author: Gideon Hack
-*
-* Copyright: (c) 2000 Sangoma Technologies 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.
-* ============================================================================
-*
-* Jan 28, 2000 Gideon Hack Initial Version
-*
-*****************************************************************************/
-
-
-#ifndef _WANPIPE_ASYNC_H
-#define _WANPIPE_ASYNC_H
-
-/* ----------------------------------------------------------------------------
- * Interface commands
- * --------------------------------------------------------------------------*/
-
-#define SET_ASY_CONFIGURATION 0xE2 /* set the asychronous operational configuration */
-#define READ_ASY_CONFIGURATION 0xE3 /* read the current asychronous operational configuration */
-#define ENABLE_ASY_COMMUNICATIONS 0xE4 /* enable asychronous communications */
-#define DISABLE_ASY_COMMUNICATIONS 0xE5 /* disable asychronous communications */
-#define READ_ASY_OPERATIONAL_STATS 0xE7 /* retrieve the asychronous operational statistics */
-#define FLUSH_ASY_OPERATIONAL_STATS 0xE8 /* flush the asychronous operational statistics */
-#define TRANSMIT_ASY_BREAK_SIGNAL 0xEC /* transmit an asychronous break signal */
-
-
-
-/* ----------------------------------------------------------------------------
- * Return codes from interface commands
- * --------------------------------------------------------------------------*/
-
-#define COMMAND_INVALID_FOR_PORT 0x50 /* the command is invalid for the selected port */
-#define DISABLE_ASY_COMMS_BEFORE_CFG 0xE1 /* communications must be disabled before setting the configuration */
-#define ASY_COMMS_ENABLED 0xE1 /* communications are currently enabled */
-#define ASY_COMMS_DISABLED 0xE1 /* communications are currently disabled */
-#define ASY_CFG_BEFORE_COMMS_ENABLED 0xE2 /* perform a SET_ASY_CONFIGURATION before enabling comms */
-#define LGTH_ASY_CFG_DATA_INVALID 0xE2 /* the length of the passed configuration data is invalid */
-#define INVALID_ASY_CFG_DATA 0xE3 /* the passed configuration data is invalid */
-#define ASY_BREAK_SIGNAL_BUSY 0xEC /* a break signal is being transmitted */
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the SET_ASY_CONFIGURATION/READ_ASY_CONFIGURATION command
- * --------------------------------------------------------------------------*/
-
-/* the asynchronous configuration structure */
-typedef struct {
- unsigned long baud_rate PACKED; /* the baud rate */
- unsigned short line_config_options PACKED; /* line configuration options */
- unsigned short modem_config_options PACKED; /* modem configuration options */
- unsigned short asy_API_options PACKED; /* asynchronous API options */
- unsigned short asy_protocol_options PACKED; /* asynchronous protocol options */
- unsigned short Tx_bits_per_char PACKED; /* number of bits per tx character */
- unsigned short Rx_bits_per_char PACKED; /* number of bits per received character */
- unsigned short stop_bits PACKED; /* number of stop bits per character */
- unsigned short parity PACKED; /* parity definition */
- unsigned short break_timer PACKED; /* the break signal timer */
- unsigned short asy_Rx_inter_char_timer PACKED; /* the receive inter-character timer */
- unsigned short asy_Rx_complete_length PACKED; /* the receive 'buffer complete' length */
- unsigned short XON_char PACKED; /* the XON character */
- unsigned short XOFF_char PACKED; /* the XOFF character */
- unsigned short asy_statistics_options PACKED; /* async operational stat options */
- unsigned long ptr_shared_mem_info_struct PACKED;/* ptr to the shared memory area information structure */
- unsigned long ptr_asy_Tx_stat_el_cfg_struct PACKED;/* ptr to the transmit status element configuration structure */
- unsigned long ptr_asy_Rx_stat_el_cfg_struct PACKED;/* ptr to the receive status element configuration structure */
-} ASY_CONFIGURATION_STRUCT;
-
-/* permitted minimum and maximum values for setting the asynchronous configuration */
-#define MIN_ASY_BAUD_RATE 50 /* maximum baud rate */
-#define MAX_ASY_BAUD_RATE 250000 /* minimum baud rate */
-#define MIN_ASY_BITS_PER_CHAR 5 /* minimum number of bits per character */
-#define MAX_ASY_BITS_PER_CHAR 8 /* maximum number of bits per character */
-#define MIN_BREAK_TMR_VAL 0 /* minimum break signal timer */
-#define MAX_BREAK_TMR_VAL 5000 /* maximum break signal timer */
-#define MIN_ASY_RX_INTER_CHAR_TMR 0 /* minimum receive inter-character timer */
-#define MAX_ASY_RX_INTER_CHAR_TMR 30000 /* maximum receive inter-character timer */
-#define MIN_ASY_RX_CPLT_LENGTH 0 /* minimum receive 'length complete' value */
-#define MAX_ASY_RX_CPLT_LENGTH 2000 /* maximum receive 'length complete' value */
-
-/* bit settings for the 'asy_API_options' */
-#define ASY_RX_DATA_TRANSPARENT 0x0001 /* do not strip parity and unused bits from received characters */
-
-/* bit settings for the 'asy_protocol_options' */
-#define ASY_RTS_HS_FOR_RX 0x0001 /* RTS handshaking is used for reception control */
-#define ASY_XON_XOFF_HS_FOR_RX 0x0002 /* XON/XOFF handshaking is used for reception control */
-#define ASY_XON_XOFF_HS_FOR_TX 0x0004 /* XON/XOFF handshaking is used for transmission control */
-#define ASY_DCD_HS_FOR_TX 0x0008 /* DCD handshaking is used for transmission control */
-#define ASY_CTS_HS_FOR_TX 0x0020 /* CTS handshaking is used for transmission control */
-
-/* bit settings for the 'stop_bits' definition */
-#define ONE_STOP_BIT 1 /* representation for 1 stop bit */
-#define TWO_STOP_BITS 2 /* representation for 2 stop bits */
-#define ONE_AND_A_HALF_STOP_BITS 3 /* representation for 1.5 stop bits */
-
-/* bit settings for the 'parity' definition */
-#define NO_PARITY 0 /* representation for no parity */
-#define ODD_PARITY 1 /* representation for odd parity */
-#define EVEN_PARITY 2 /* representation for even parity */
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the READ_COMMS_ERROR_STATS command (asynchronous mode)
- * --------------------------------------------------------------------------*/
-
-/* the communications error statistics structure */
-typedef struct {
- unsigned short Rx_overrun_err_count PACKED; /* receiver overrun error count */
- unsigned short Rx_parity_err_count PACKED; /* parity errors received count */
- unsigned short Rx_framing_err_count PACKED; /* framing errors received count */
- unsigned short comms_err_stat_reserved_1 PACKED;/* reserved for later use */
- unsigned short comms_err_stat_reserved_2 PACKED;/* reserved for later use */
- unsigned short comms_err_stat_reserved_3 PACKED;/* reserved for later use */
- unsigned short comms_err_stat_reserved_4 PACKED;/* reserved for later use */
- unsigned short comms_err_stat_reserved_5 PACKED;/* reserved for later use */
- unsigned short DCD_state_change_count PACKED; /* DCD state change count */
- unsigned short CTS_state_change_count PACKED; /* CTS state change count */
-} ASY_COMMS_ERROR_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the READ_ASY_OPERATIONAL_STATS command
- * --------------------------------------------------------------------------*/
-
-/* the asynchronous operational statistics structure */
-typedef struct {
-
- /* Data transmission statistics */
- unsigned long Data_blocks_Tx_count PACKED;/* number of blocks transmitted */
- unsigned long Data_bytes_Tx_count PACKED;/* number of bytes transmitted */
- unsigned long Data_Tx_throughput PACKED;/* transmit throughput */
- unsigned long no_ms_for_Data_Tx_thruput_comp PACKED;/* millisecond time used for the Tx throughput computation */
- unsigned long Tx_Data_discard_lgth_err_count PACKED;/* number of Data blocks discarded (length error) */
- unsigned long reserved_Data_frm_Tx_stat1 PACKED;/* reserved for later use */
- unsigned long reserved_Data_frm_Tx_stat2 PACKED;/* reserved for later use */
- unsigned long reserved_Data_frm_Tx_stat3 PACKED;/* reserved for later use */
-
- /* Data reception statistics */
- unsigned long Data_blocks_Rx_count PACKED;/* number of blocks received */
- unsigned long Data_bytes_Rx_count PACKED;/* number of bytes received */
- unsigned long Data_Rx_throughput PACKED;/* receive throughput */
- unsigned long no_ms_for_Data_Rx_thruput_comp PACKED;/* millisecond time used for the Rx throughput computation */
- unsigned long Rx_Data_bytes_discard_count PACKED;/* received Data bytes discarded */
- unsigned long reserved_Data_frm_Rx_stat1 PACKED;/* reserved for later use */
-
- /* handshaking protocol statistics */
- unsigned short XON_chars_Tx_count PACKED; /* number of XON characters transmitted */
- unsigned short XOFF_chars_Tx_count PACKED; /* number of XOFF characters transmitted */
- unsigned short XON_chars_Rx_count PACKED; /* number of XON characters received */
- unsigned short XOFF_chars_Rx_count PACKED; /* number of XOFF characters received */
- unsigned short Tx_halt_modem_low_count PACKED; /* number of times Tx halted (modem line low) */
- unsigned short Rx_halt_RTS_low_count PACKED; /* number of times Rx halted by setting RTS low */
- unsigned long reserved_handshaking_stat1 PACKED;/* reserved for later use */
-
- /* break statistics */
- unsigned short break_Tx_count PACKED; /* number of break sequences transmitted */
- unsigned short break_Rx_count PACKED; /* number of break sequences received */
- unsigned long reserved_break_stat1 PACKED;/* reserved for later use */
-
- /* miscellaneous statistics */
- unsigned long reserved_misc_stat1 PACKED; /* reserved for later use */
- unsigned long reserved_misc_stat2 PACKED; /* reserved for later use */
-
-} ASY_OPERATIONAL_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for Data transmission
- * --------------------------------------------------------------------------*/
-
-/* the Data block transmit status element configuration structure */
-typedef struct {
- unsigned short number_Tx_status_elements PACKED; /* number of transmit status elements */
- unsigned long base_addr_Tx_status_elements PACKED; /* base address of the transmit element list */
- unsigned long next_Tx_status_element_to_use PACKED; /* pointer to the next transmit element to be used */
-} ASY_TX_STATUS_EL_CFG_STRUCT;
-
-
-/* the Data block transmit status element structure */
-typedef struct {
- unsigned char opp_flag PACKED; /* opp flag */
- unsigned short data_length PACKED; /* length of the block to be transmitted */
- unsigned char reserved_1 PACKED; /* reserved for internal use */
- unsigned long reserved_2 PACKED; /* reserved for internal use */
- unsigned long reserved_3 PACKED; /* reserved for internal use */
- unsigned long ptr_data_bfr PACKED; /* pointer to the data area */
-} ASY_DATA_TX_STATUS_EL_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for Data reception
- * --------------------------------------------------------------------------*/
-
-/* the Data block receive status element configuration structure */
-typedef struct {
- unsigned short number_Rx_status_elements PACKED;/* number of receive status elements */
- unsigned long base_addr_Rx_status_elements PACKED;/* base address of the receive element list */
- unsigned long next_Rx_status_element_to_use PACKED;/* pointer to the next receive element to be used */
- unsigned long base_addr_Rx_buffer PACKED;/* base address of the receive data buffer */
- unsigned long end_addr_Rx_buffer PACKED;/* end address of the receive data buffer */
-} ASY_RX_STATUS_EL_CFG_STRUCT;
-
-/* the Data block receive status element structure */
-typedef struct {
- unsigned char opp_flag PACKED; /* opp flag */
- unsigned short data_length PACKED; /* length of the received data block */
- unsigned char reserved_1 PACKED; /* reserved for internal use */
- unsigned short time_stamp PACKED; /* receive time stamp (HDLC_STREAMING_MODE) */
- unsigned short data_buffered PACKED; /* the number of data bytes still buffered */
- unsigned long reserved_2 PACKED; /* reserved for internal use */
- unsigned long ptr_data_bfr PACKED; /* pointer to the data area */
-} ASY_DATA_RX_STATUS_EL_STRUCT;
-
-#endif
diff --git a/include/linux/sdla_chdlc.h b/include/linux/sdla_chdlc.h
deleted file mode 100644
index d2e35a29903..00000000000
--- a/include/linux/sdla_chdlc.h
+++ /dev/null
@@ -1,813 +0,0 @@
-/*************************************************************************
- sdla_chdlc.h Sangoma Cisco HDLC firmware API definitions
-
- Author: Gideon Hack
- Nenad Corbic <ncorbic@sangoma.com>
-
- Copyright: (c) 1995-2000 Sangoma Technologies Inc.
-
- This program is free software; you can redistribute it and/or
- modify it under the term 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.
-
-===========================================================================
- Oct 04, 1999 Nenad Corbic Updated API support
- Jun 02, 1999 Gideon Hack Changes for S514 usage.
- Oct 28, 1998 Jaspreet Singh Made changes for Dual Port CHDLC.
- Jun 11, 1998 David Fong Initial version.
-===========================================================================
-
- Organization
- - Compatibility notes
- - Constants defining the shared memory control block (mailbox)
- - Interface commands
- - Return code from interface commands
- - Constants for the commands (structures for casting data)
- - UDP Management constants and structures
-
-*************************************************************************/
-
-#ifndef _SDLA_CHDLC_H
-# define _SDLC_CHDLC_H
-
-/*------------------------------------------------------------------------
- Notes:
-
- All structres defined in this file are byte-aligned.
-
- Compiler Platform
- ------------------------
- GNU C Linux
-
-------------------------------------------------------------------------*/
-
-#ifndef PACKED
-#define PACKED __attribute__((packed))
-#endif /* PACKED */
-
-
-/* ----------------------------------------------------------------------------
- * Constants defining the shared memory control block (mailbox)
- * --------------------------------------------------------------------------*/
-
-#define PRI_BASE_ADDR_MB_STRUCT 0xE000 /* the base address of the mailbox structure on the adapter */
-#define SEC_BASE_ADDR_MB_STRUCT 0xE800 /* the base address of the mailbox structure on the adapter */
-#define SIZEOF_MB_DATA_BFR 2032 /* the size of the actual mailbox data area */
-#define NUMBER_MB_RESERVED_BYTES 0x0B /* the number of reserved bytes in the mailbox header area */
-
-
-#define MIN_LGTH_CHDLC_DATA_CFG 300 /* min length of the CHDLC data field (for configuration purposes) */
-#define PRI_MAX_NO_DATA_BYTES_IN_FRAME 15354 /* PRIMARY - max length of the CHDLC data field */
-
-typedef struct {
- unsigned char opp_flag PACKED; /* the opp flag */
- unsigned char command PACKED; /* the user command */
- unsigned short buffer_length PACKED; /* the data length */
- unsigned char return_code PACKED; /* the return code */
- unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED; /* reserved for later */
- unsigned char data[SIZEOF_MB_DATA_BFR] PACKED; /* the data area */
-} CHDLC_MAILBOX_STRUCT;
-
-typedef struct {
- pid_t pid_num PACKED;
- CHDLC_MAILBOX_STRUCT cmdarea PACKED;
-
-} CMDBLOCK_STRUCT;
-
-
-
-
-/* ----------------------------------------------------------------------------
- * Interface commands
- * --------------------------------------------------------------------------*/
-
-/* global interface commands */
-#define READ_GLOBAL_EXCEPTION_CONDITION 0x01
-#define SET_GLOBAL_CONFIGURATION 0x02
-#define READ_GLOBAL_CONFIGURATION 0x03
-#define READ_GLOBAL_STATISTICS 0x04
-#define FLUSH_GLOBAL_STATISTICS 0x05
-#define SET_MODEM_STATUS 0x06 /* set status of DTR or RTS */
-#define READ_MODEM_STATUS 0x07 /* read status of CTS and DCD */
-#define READ_COMMS_ERROR_STATS 0x08
-#define FLUSH_COMMS_ERROR_STATS 0x09
-#define SET_TRACE_CONFIGURATION 0x0A /* set the line trace config */
-#define READ_TRACE_CONFIGURATION 0x0B /* read the line trace config */
-#define READ_TRACE_STATISTICS 0x0C /* read the trace statistics */
-#define FLUSH_TRACE_STATISTICS 0x0D /* flush the trace statistics */
-#define FT1_MONITOR_STATUS_CTRL 0x1C /* set the status of the S508/FT1 monitoring */
-#define SET_FT1_CONFIGURATION 0x18 /* set the FT1 configuration */
-#define READ_FT1_CONFIGURATION 0x19 /* read the FT1 configuration */
-#define TRANSMIT_ASYNC_DATA_TO_FT1 0x1A /* output asynchronous data to the FT1 */
-#define RECEIVE_ASYNC_DATA_FROM_FT1 0x1B /* receive asynchronous data from the FT1 */
-#define FT1_MONITOR_STATUS_CTRL 0x1C /* set the status of the FT1 monitoring */
-
-#define READ_FT1_OPERATIONAL_STATS 0x1D /* read the S508/FT1 operational statistics */
-#define SET_FT1_MODE 0x1E /* set the operational mode of the S508/FT1 module */
-
-/* CHDLC-level interface commands */
-#define READ_CHDLC_CODE_VERSION 0x20
-#define READ_CHDLC_EXCEPTION_CONDITION 0x21 /* read exception condition from the adapter */
-#define SET_CHDLC_CONFIGURATION 0x22
-#define READ_CHDLC_CONFIGURATION 0x23
-#define ENABLE_CHDLC_COMMUNICATIONS 0x24
-#define DISABLE_CHDLC_COMMUNICATIONS 0x25
-#define READ_CHDLC_LINK_STATUS 0x26
-#define READ_CHDLC_OPERATIONAL_STATS 0x27
-#define FLUSH_CHDLC_OPERATIONAL_STATS 0x28
-#define SET_CHDLC_INTERRUPT_TRIGGERS 0x30 /* set application interrupt triggers */
-#define READ_CHDLC_INTERRUPT_TRIGGERS 0x31 /* read application interrupt trigger configuration */
-
-/* Special UDP drivers management commands */
-#define CPIPE_ENABLE_TRACING 0x50
-#define CPIPE_DISABLE_TRACING 0x51
-#define CPIPE_GET_TRACE_INFO 0x52
-#define CPIPE_GET_IBA_DATA 0x53
-#define CPIPE_FT1_READ_STATUS 0x54
-#define CPIPE_DRIVER_STAT_IFSEND 0x55
-#define CPIPE_DRIVER_STAT_INTR 0x56
-#define CPIPE_DRIVER_STAT_GEN 0x57
-#define CPIPE_FLUSH_DRIVER_STATS 0x58
-#define CPIPE_ROUTER_UP_TIME 0x59
-
-/* Driver specific commands for API */
-#define CHDLC_READ_TRACE_DATA 0xE4 /* read trace data */
-#define TRACE_ALL 0x00
-#define TRACE_PROT 0x01
-#define TRACE_DATA 0x02
-
-#define DISCARD_RX_ERROR_FRAMES 0x0001
-
-/* ----------------------------------------------------------------------------
- * Return codes from interface commands
- * --------------------------------------------------------------------------*/
-
-#define COMMAND_OK 0x00
-
-/* return codes from global interface commands */
-#define NO_GLOBAL_EXCEP_COND_TO_REPORT 0x01 /* there is no CHDLC exception condition to report */
-#define LGTH_GLOBAL_CFG_DATA_INVALID 0x01 /* the length of the passed global configuration data is invalid */
-#define LGTH_TRACE_CFG_DATA_INVALID 0x01 /* the length of the passed trace configuration data is invalid */
-#define IRQ_TIMEOUT_VALUE_INVALID 0x02 /* an invalid application IRQ timeout value was selected */
-#define TRACE_CONFIG_INVALID 0x02 /* the passed line trace configuration is invalid */
-#define ADAPTER_OPERATING_FREQ_INVALID 0x03 /* an invalid adapter operating frequency was selected */
-#define TRC_DEAC_TMR_INVALID 0x03 /* the trace deactivation timer is invalid */
-#define S508_FT1_ADPTR_NOT_PRESENT 0x0C /* the S508/FT1 adapter is not present */
-#define INVALID_FT1_STATUS_SELECTION 0x0D /* the S508/FT1 status selection is invalid */
-#define FT1_OP_STATS_NOT_ENABLED 0x0D /* the FT1 operational statistics have not been enabled */
-#define FT1_OP_STATS_NOT_AVAILABLE 0x0E /* the FT1 operational statistics are not currently available */
-#define S508_FT1_MODE_SELECTION_BUSY 0x0E /* the S508/FT1 adapter is busy selecting the operational mode */
-
-/* return codes from command READ_GLOBAL_EXCEPTION_CONDITION */
-#define EXCEP_MODEM_STATUS_CHANGE 0x10 /* a modem status change occurred */
-#define EXCEP_TRC_DISABLED 0x11 /* the trace has been disabled */
-#define EXCEP_IRQ_TIMEOUT 0x12 /* IRQ timeout */
-
-/* return codes from CHDLC-level interface commands */
-#define NO_CHDLC_EXCEP_COND_TO_REPORT 0x21 /* there is no CHDLC exception condition to report */
-#define CHDLC_COMMS_DISABLED 0x21 /* communications are not currently enabled */
-#define CHDLC_COMMS_ENABLED 0x21 /* communications are currently enabled */
-#define DISABLE_CHDLC_COMMS_BEFORE_CFG 0x21 /* CHDLC communications must be disabled before setting the configuration */
-#define ENABLE_CHDLC_COMMS_BEFORE_CONN 0x21 /* communications must be enabled before using the CHDLC_CONNECT conmmand */
-#define CHDLC_CFG_BEFORE_COMMS_ENABLED 0x22 /* perform a SET_CHDLC_CONFIGURATION before enabling comms */
-#define LGTH_CHDLC_CFG_DATA_INVALID 0x22 /* the length of the passed CHDLC configuration data is invalid */
-#define LGTH_INT_TRIGGERS_DATA_INVALID 0x22 /* the length of the passed interrupt trigger data is invalid */
-#define INVALID_IRQ_SELECTED 0x23 /* in invalid IRQ was selected in the SET_CHDLC_INTERRUPT_TRIGGERS */
-#define INVALID_CHDLC_CFG_DATA 0x23 /* the passed CHDLC configuration data is invalid */
-#define IRQ_TMR_VALUE_INVALID 0x24 /* an invalid application IRQ timer value was selected */
-#define LARGER_PERCENT_TX_BFR_REQUIRED 0x24 /* a larger Tx buffer percentage is required */
-#define LARGER_PERCENT_RX_BFR_REQUIRED 0x25 /* a larger Rx buffer percentage is required */
-#define S514_BOTH_PORTS_SAME_CLK_MODE 0x26 /* S514 - both ports must have same clock mode */
-#define INVALID_CMND_HDLC_STREAM_MODE 0x4E /* the CHDLC interface command is invalid for HDLC streaming mode */
-#define INVALID_CHDLC_COMMAND 0x4F /* the defined CHDLC interface command is invalid */
-
-/* return codes from command READ_CHDLC_EXCEPTION_CONDITION */
-#define EXCEP_LINK_ACTIVE 0x30 /* the CHDLC link has become active */
-#define EXCEP_LINK_INACTIVE_MODEM 0x31 /* the CHDLC link has become inactive (modem status) */
-#define EXCEP_LINK_INACTIVE_KPALV 0x32 /* the CHDLC link has become inactive (keepalive status) */
-#define EXCEP_IP_ADDRESS_DISCOVERED 0x33 /* the IP address has been discovered */
-#define EXCEP_LOOPBACK_CONDITION 0x34 /* a loopback condition has occurred */
-
-
-/* return code from command CHDLC_SEND_WAIT and CHDLC_SEND_NO_WAIT */
-#define LINK_DISCONNECTED 0x21
-#define NO_TX_BFRS_AVAIL 0x24
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the SET_GLOBAL_CONFIGURATION/READ_GLOBAL_CONFIGURATION commands
- * --------------------------------------------------------------------------*/
-
-/* the global configuration structure */
-typedef struct {
- unsigned short adapter_config_options PACKED; /* adapter config options */
- unsigned short app_IRQ_timeout PACKED; /* application IRQ timeout */
- unsigned long adapter_operating_frequency PACKED; /* adapter operating frequency */
-} GLOBAL_CONFIGURATION_STRUCT;
-
-/* settings for the 'app_IRQ_timeout' */
-#define MAX_APP_IRQ_TIMEOUT_VALUE 5000 /* the maximum permitted IRQ timeout */
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the READ_GLOBAL_STATISTICS command
- * --------------------------------------------------------------------------*/
-
-/* the global statistics structure */
-typedef struct {
- unsigned short app_IRQ_timeout_count PACKED;
-} GLOBAL_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the READ_COMMS_ERROR_STATS command
- * --------------------------------------------------------------------------*/
-
-/* the communications error statistics structure */
-typedef struct {
- unsigned short Rx_overrun_err_count PACKED;
- unsigned short CRC_err_count PACKED; /* receiver CRC error count */
- unsigned short Rx_abort_count PACKED; /* abort frames recvd count */
- unsigned short Rx_dis_pri_bfrs_full_count PACKED;/* receiver disabled */
- unsigned short comms_err_stat_reserved_1 PACKED;/* reserved for later */
- unsigned short sec_Tx_abort_msd_Tx_int_count PACKED; /* secondary - abort frames transmitted count (missed Tx interrupt) */
- unsigned short missed_Tx_und_int_count PACKED; /* missed tx underrun interrupt count */
- unsigned short sec_Tx_abort_count PACKED; /*secondary-abort frames tx count */
- unsigned short DCD_state_change_count PACKED; /* DCD state change */
- unsigned short CTS_state_change_count PACKED; /* CTS state change */
-} COMMS_ERROR_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants used for line tracing
- * --------------------------------------------------------------------------*/
-
-/* the trace configuration structure (SET_TRACE_CONFIGURATION/READ_TRACE_CONFIGURATION commands) */
-typedef struct {
- unsigned char trace_config PACKED; /* trace configuration */
- unsigned short trace_deactivation_timer PACKED; /* trace deactivation timer */
- unsigned long ptr_trace_stat_el_cfg_struct PACKED; /* a pointer to the line trace element configuration structure */
-} LINE_TRACE_CONFIG_STRUCT;
-
-/* 'trace_config' bit settings */
-#define TRACE_INACTIVE 0x00 /* trace is inactive */
-#define TRACE_ACTIVE 0x01 /* trace is active */
-#define TRACE_DELAY_MODE 0x04 /* operate the trace in delay mode */
-#define TRACE_DATA_FRAMES 0x08 /* trace Data frames */
-#define TRACE_SLARP_FRAMES 0x10 /* trace SLARP frames */
-#define TRACE_CDP_FRAMES 0x20 /* trace CDP frames */
-
-/* the line trace status element configuration structure */
-typedef struct {
- unsigned short number_trace_status_elements PACKED; /* number of line trace elements */
- unsigned long base_addr_trace_status_elements PACKED; /* base address of the trace element list */
- unsigned long next_trace_element_to_use PACKED; /* pointer to the next trace element to be used */
- unsigned long base_addr_trace_buffer PACKED; /* base address of the trace data buffer */
- unsigned long end_addr_trace_buffer PACKED; /* end address of the trace data buffer */
-} TRACE_STATUS_EL_CFG_STRUCT;
-
-/* the line trace status element structure */
-typedef struct {
- unsigned char opp_flag PACKED; /* opp flag */
- unsigned short trace_length PACKED; /* trace length */
- unsigned char trace_type PACKED; /* trace type */
- unsigned short trace_time_stamp PACKED; /* time stamp */
- unsigned short trace_reserved_1 PACKED; /* reserved for later use */
- unsigned long trace_reserved_2 PACKED; /* reserved for later use */
- unsigned long ptr_data_bfr PACKED; /* ptr to the trace data buffer */
-} TRACE_STATUS_ELEMENT_STRUCT;
-
-/* "trace_type" bit settings */
-#define TRACE_INCOMING 0x00
-#define TRACE_OUTGOINGING 0x01
-#define TRACE_INCOMING_ABORTED 0x10
-#define TRACE_INCOMING_CRC_ERROR 0x20
-#define TRACE_INCOMING_OVERRUN_ERROR 0x40
-
-
-
-/* the line trace statistics structure */
-typedef struct {
- unsigned long frames_traced_count PACKED; /* number of frames traced */
- unsigned long trc_frms_not_recorded_count PACKED; /* number of trace frames discarded */
-} LINE_TRACE_STATS_STRUCT;
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the FT1_MONITOR_STATUS_CTRL command
- * --------------------------------------------------------------------------*/
-
-#define DISABLE_FT1_STATUS_STATISTICS 0x00 /* disable the FT1 status and statistics monitoring */
-#define ENABLE_READ_FT1_STATUS 0x01 /* read the FT1 operational status */
-#define ENABLE_READ_FT1_OP_STATS 0x02 /* read the FT1 operational statistics */
-#define FLUSH_FT1_OP_STATS 0x04 /* flush the FT1 operational statistics */
-
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the SET_CHDLC_CONFIGURATION command
- * --------------------------------------------------------------------------*/
-
-/* the CHDLC configuration structure */
-typedef struct {
- unsigned long baud_rate PACKED; /* the baud rate */
- unsigned short line_config_options PACKED; /* line configuration options */
- unsigned short modem_config_options PACKED; /* modem configration options */
- unsigned short modem_status_timer PACKED; /* timer for monitoring modem status changes */
- unsigned short CHDLC_API_options PACKED; /* CHDLC API options */
- unsigned short CHDLC_protocol_options PACKED; /* CHDLC protocol options */
- unsigned short percent_data_buffer_for_Tx PACKED; /* percentage data buffering used for Tx */
- unsigned short CHDLC_statistics_options PACKED; /* CHDLC operational statistics options */
- unsigned short max_CHDLC_data_field_length PACKED; /* the maximum length of the CHDLC Data field */
- unsigned short transmit_keepalive_timer PACKED; /* the transmit keepalive timer */
- unsigned short receive_keepalive_timer PACKED; /* the receive keepalive timer */
- unsigned short keepalive_error_tolerance PACKED; /* the receive keepalive error tolerance */
- unsigned short SLARP_request_timer PACKED; /* the SLARP request timer */
- unsigned long IP_address PACKED; /* the IP address */
- unsigned long IP_netmask PACKED; /* the IP netmask */
- unsigned long ptr_shared_mem_info_struct PACKED; /* a pointer to the shared memory area information structure */
- unsigned long ptr_CHDLC_Tx_stat_el_cfg_struct PACKED; /* a pointer to the transmit status element configuration structure */
- unsigned long ptr_CHDLC_Rx_stat_el_cfg_struct PACKED; /* a pointer to the receive status element configuration structure */
-} CHDLC_CONFIGURATION_STRUCT;
-
-/* settings for the 'line_config_options' */
-#define INTERFACE_LEVEL_V35 0x0000 /* V.35 interface level */
-#define INTERFACE_LEVEL_RS232 0x0001 /* RS-232 interface level */
-
-/* settings for the 'modem_config_options' */
-
-#define DONT_RAISE_DTR_RTS_ON_EN_COMMS 0x0001
-/* don't automatically raise DTR and RTS when performing an
- ENABLE_CHDLC_COMMUNICATIONS command */
-
-#define DONT_REPORT_CHG_IN_MODEM_STAT 0x0002
-/* don't report changes in modem status to the application */
-
-
-/* bit settings for the 'CHDLC_protocol_options' byte */
-
-#define IGNORE_DCD_FOR_LINK_STAT 0x0001
-/* ignore DCD in determining the CHDLC link status */
-
-#define IGNORE_CTS_FOR_LINK_STAT 0x0002
-/* ignore CTS in determining the CHDLC link status */
-
-#define IGNORE_KPALV_FOR_LINK_STAT 0x0004
-/* ignore keepalive frames in determining the CHDLC link status */
-
-#define SINGLE_TX_BUFFER 0x4000
-/* configure a single transmit buffer */
-
-#define HDLC_STREAMING_MODE 0x8000
-
-/* settings for the 'CHDLC_statistics_options' */
-
-#define CHDLC_TX_DATA_BYTE_COUNT_STAT 0x0001
-/* record the number of Data bytes transmitted */
-
-#define CHDLC_RX_DATA_BYTE_COUNT_STAT 0x0002
-/* record the number of Data bytes received */
-
-#define CHDLC_TX_THROUGHPUT_STAT 0x0004
-/* compute the Data frame transmit throughput */
-
-#define CHDLC_RX_THROUGHPUT_STAT 0x0008
-/* compute the Data frame receive throughput */
-
-
-/* permitted minimum and maximum values for setting the CHDLC configuration */
-#define PRI_MAX_BAUD_RATE_S508 2666666 /* PRIMARY - maximum baud rate (S508) */
-#define SEC_MAX_BAUD_RATE_S508 258064 /* SECONDARY - maximum baud rate (S508) */
-#define PRI_MAX_BAUD_RATE_S514 2750000 /* PRIMARY - maximum baud rate (S508) */
-#define SEC_MAX_BAUD_RATE_S514 515625 /* SECONDARY - maximum baud rate (S508) */
-
-#define MIN_MODEM_TIMER 0 /* minimum modem status timer */
-#define MAX_MODEM_TIMER 5000 /* maximum modem status timer */
-
-#define SEC_MAX_NO_DATA_BYTES_IN_FRAME 2048 /* SECONDARY - max length of the CHDLC data field */
-
-#define MIN_Tx_KPALV_TIMER 0 /* minimum transmit keepalive timer */
-#define MAX_Tx_KPALV_TIMER 60000 /* maximum transmit keepalive timer */
-#define DEFAULT_Tx_KPALV_TIMER 10000 /* default transmit keepalive timer */
-
-#define MIN_Rx_KPALV_TIMER 10 /* minimum receive keepalive timer */
-#define MAX_Rx_KPALV_TIMER 60000 /* maximum receive keepalive timer */
-#define DEFAULT_Rx_KPALV_TIMER 10000 /* default receive keepalive timer */
-
-#define MIN_KPALV_ERR_TOL 1 /* min kpalv error tolerance count */
-#define MAX_KPALV_ERR_TOL 20 /* max kpalv error tolerance count */
-#define DEFAULT_KPALV_ERR_TOL 3 /* default value */
-
-#define MIN_SLARP_REQ_TIMER 0 /* min transmit SLARP Request timer */
-#define MAX_SLARP_REQ_TIMER 60000 /* max transmit SLARP Request timer */
-#define DEFAULT_SLARP_REQ_TIMER 0 /* default value -- no SLARP */
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the READ_CHDLC_LINK_STATUS command
- * --------------------------------------------------------------------------*/
-
-/* the CHDLC status structure */
-typedef struct {
- unsigned char CHDLC_link_status PACKED; /* CHDLC link status */
- unsigned char no_Data_frms_for_app PACKED; /* number of Data frames available for the application */
- unsigned char receiver_status PACKED; /* enabled/disabled */
- unsigned char SLARP_state PACKED; /* internal SLARP state */
-} CHDLC_LINK_STATUS_STRUCT;
-
-/* settings for the 'CHDLC_link_status' variable */
-#define CHDLC_LINK_INACTIVE 0x00 /* the CHDLC link is inactive */
-#define CHDLC_LINK_ACTIVE 0x01 /* the CHDLC link is active */
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the READ_CHDLC_OPERATIONAL_STATS command
- * --------------------------------------------------------------------------*/
-
-/* the CHDLC operational statistics structure */
-typedef struct {
-
- /* Data frame transmission statistics */
- unsigned long Data_frames_Tx_count PACKED; /* # of frames transmitted */
- unsigned long Data_bytes_Tx_count PACKED; /* # of bytes transmitted */
- unsigned long Data_Tx_throughput PACKED; /* transmit throughput */
- unsigned long no_ms_for_Data_Tx_thruput_comp PACKED; /* millisecond time used for the Tx throughput computation */
- unsigned long Tx_Data_discard_lgth_err_count PACKED; /* number of Data frames discarded (length error) */
- unsigned long reserved_Data_frm_Tx_stat1 PACKED; /* reserved for later */
- unsigned long reserved_Data_frm_Tx_stat2 PACKED; /* reserved for later */
- unsigned long reserved_Data_frm_Tx_stat3 PACKED; /* reserved for later */
-
- /* Data frame reception statistics */
- unsigned long Data_frames_Rx_count PACKED; /* number of frames received */
- unsigned long Data_bytes_Rx_count PACKED; /* number of bytes received */
- unsigned long Data_Rx_throughput PACKED; /* receive throughput */
- unsigned long no_ms_for_Data_Rx_thruput_comp PACKED; /* millisecond time used for the Rx throughput computation */
- unsigned long Rx_Data_discard_short_count PACKED; /* received Data frames discarded (too short) */
- unsigned long Rx_Data_discard_long_count PACKED; /* received Data frames discarded (too long) */
- unsigned long Rx_Data_discard_inactive_count PACKED; /* received Data frames discarded (link inactive) */
- unsigned long reserved_Data_frm_Rx_stat1 PACKED; /* reserved for later */
-
- /* SLARP frame transmission/reception statistics */
- unsigned long CHDLC_SLARP_REQ_Tx_count PACKED; /* number of SLARP Request frames transmitted */
- unsigned long CHDLC_SLARP_REQ_Rx_count PACKED; /* number of SLARP Request frames received */
- unsigned long CHDLC_SLARP_REPLY_Tx_count PACKED; /* number of SLARP Reply frames transmitted */
- unsigned long CHDLC_SLARP_REPLY_Rx_count PACKED; /* number of SLARP Reply frames received */
- unsigned long CHDLC_SLARP_KPALV_Tx_count PACKED; /* number of SLARP keepalive frames transmitted */
- unsigned long CHDLC_SLARP_KPALV_Rx_count PACKED; /* number of SLARP keepalive frames received */
- unsigned long reserved_SLARP_stat1 PACKED; /* reserved for later */
- unsigned long reserved_SLARP_stat2 PACKED; /* reserved for later */
-
- /* CDP frame transmission/reception statistics */
- unsigned long CHDLC_CDP_Tx_count PACKED; /* number of CDP frames transmitted */
- unsigned long CHDLC_CDP_Rx_count PACKED; /* number of CDP frames received */
- unsigned long reserved_CDP_stat1 PACKED; /* reserved for later */
- unsigned long reserved_CDP_stat2 PACKED; /* reserved for later */
- unsigned long reserved_CDP_stat3 PACKED; /* reserved for later */
- unsigned long reserved_CDP_stat4 PACKED; /* reserved for later */
- unsigned long reserved_CDP_stat5 PACKED; /* reserved for later */
- unsigned long reserved_CDP_stat6 PACKED; /* reserved for later */
-
- /* Incoming frames with a format error statistics */
- unsigned short Rx_frm_incomp_CHDLC_hdr_count PACKED; /* frames received of with incomplete Cisco HDLC header */
- unsigned short Rx_frms_too_long_count PACKED; /* frames received of excessive length count */
- unsigned short Rx_invalid_CHDLC_addr_count PACKED; /* frames received with an invalid CHDLC address count */
- unsigned short Rx_invalid_CHDLC_ctrl_count PACKED; /* frames received with an invalid CHDLC control field count */
- unsigned short Rx_invalid_CHDLC_type_count PACKED; /* frames received of an invalid CHDLC frame type count */
- unsigned short Rx_SLARP_invalid_code_count PACKED; /* SLARP frame received with an invalid packet code */
- unsigned short Rx_SLARP_Reply_bad_IP_addr PACKED; /* SLARP Reply received - bad IP address */
- unsigned short Rx_SLARP_Reply_bad_netmask PACKED; /* SLARP Reply received - bad netmask */
- unsigned long reserved_frm_format_err1 PACKED; /* reserved for later */
- unsigned long reserved_frm_format_err2 PACKED; /* reserved for later */
- unsigned long reserved_frm_format_err3 PACKED; /* reserved for later */
- unsigned long reserved_frm_format_err4 PACKED; /* reserved for later */
-
- /* CHDLC timeout/retry statistics */
- unsigned short SLARP_Rx_keepalive_TO_count PACKED; /* timeout count for incoming SLARP frames */
- unsigned short SLARP_Request_TO_count PACKED; /* timeout count for SLARP Request frames */
- unsigned long To_retry_reserved_stat1 PACKED; /* reserved for later */
- unsigned long To_retry_reserved_stat2 PACKED; /* reserved for later */
- unsigned long To_retry_reserved_stat3 PACKED; /* reserved for later */
-
- /* CHDLC link active/inactive and loopback statistics */
- unsigned short link_active_count PACKED; /* number of times that the link went active */
- unsigned short link_inactive_modem_count PACKED; /* number of times that the link went inactive (modem failure) */
- unsigned short link_inactive_keepalive_count PACKED; /* number of times that the link went inactive (keepalive failure) */
- unsigned short link_looped_count PACKED; /* link looped count */
- unsigned long link_status_reserved_stat1 PACKED; /* reserved for later use */
- unsigned long link_status_reserved_stat2 PACKED; /* reserved for later use */
-
- /* miscellaneous statistics */
- unsigned long reserved_misc_stat1 PACKED; /* reserved for later */
- unsigned long reserved_misc_stat2 PACKED; /* reserved for later */
- unsigned long reserved_misc_stat3 PACKED; /* reserved for later */
- unsigned long reserved_misc_stat4 PACKED; /* reserved for later */
-
-} CHDLC_OPERATIONAL_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for using application interrupts
- * --------------------------------------------------------------------------*/
-
-/* the structure used for the SET_CHDLC_INTERRUPT_TRIGGERS/READ_CHDLC_INTERRUPT_TRIGGERS command */
-typedef struct {
- unsigned char CHDLC_interrupt_triggers PACKED; /* CHDLC interrupt trigger configuration */
- unsigned char IRQ PACKED; /* IRQ to be used */
- unsigned short interrupt_timer PACKED; /* interrupt timer */
- unsigned short misc_interrupt_bits PACKED; /* miscellaneous bits */
-} CHDLC_INT_TRIGGERS_STRUCT;
-
-/* 'CHDLC_interrupt_triggers' bit settings */
-#define APP_INT_ON_RX_FRAME 0x01 /* interrupt on Data frame reception */
-#define APP_INT_ON_TX_FRAME 0x02 /* interrupt when an Data frame may be transmitted */
-#define APP_INT_ON_COMMAND_COMPLETE 0x04 /* interrupt when an interface command is complete */
-#define APP_INT_ON_TIMER 0x08 /* interrupt on a defined millisecond timeout */
-#define APP_INT_ON_GLOBAL_EXCEP_COND 0x10 /* interrupt on a global exception condition */
-#define APP_INT_ON_CHDLC_EXCEP_COND 0x20 /* interrupt on an CHDLC exception condition */
-#define APP_INT_ON_TRACE_DATA_AVAIL 0x80 /* interrupt when trace data is available */
-
-/* interrupt types indicated at 'interrupt_type' byte of the INTERRUPT_INFORMATION_STRUCT */
-#define NO_APP_INTS_PEND 0x00 /* no interrups are pending */
-#define RX_APP_INT_PEND 0x01 /* a receive interrupt is pending */
-#define TX_APP_INT_PEND 0x02 /* a transmit interrupt is pending */
-#define COMMAND_COMPLETE_APP_INT_PEND 0x04 /* a 'command complete' interrupt is pending */
-#define TIMER_APP_INT_PEND 0x08 /* a timer interrupt is pending */
-#define GLOBAL_EXCEP_COND_APP_INT_PEND 0x10 /* a global exception condition interrupt is pending */
-#define CHDLC_EXCEP_COND_APP_INT_PEND 0x20 /* an CHDLC exception condition interrupt is pending */
-#define TRACE_DATA_AVAIL_APP_INT_PEND 0x80 /* a trace data available interrupt is pending */
-
-
-/* modem status changes */
-#define DCD_HIGH 0x08
-#define CTS_HIGH 0x20
-
-
-/* ----------------------------------------------------------------------------
- * Constants for Data frame transmission
- * --------------------------------------------------------------------------*/
-
-/* the Data frame transmit status element configuration structure */
-typedef struct {
- unsigned short number_Tx_status_elements PACKED; /* number of transmit status elements */
- unsigned long base_addr_Tx_status_elements PACKED; /* base address of the transmit element list */
- unsigned long next_Tx_status_element_to_use PACKED; /* pointer to the next transmit element to be used */
-} CHDLC_TX_STATUS_EL_CFG_STRUCT;
-
-/* the Data frame transmit status element structure */
-typedef struct {
- unsigned char opp_flag PACKED; /* opp flag */
- unsigned short frame_length PACKED; /* length of the frame to be transmitted */
- unsigned char reserved_1 PACKED; /* reserved for internal use */
- unsigned long reserved_2 PACKED; /* reserved for internal use */
- unsigned long reserved_3 PACKED; /* reserved for internal use */
- unsigned long ptr_data_bfr PACKED; /* pointer to the data area */
-} CHDLC_DATA_TX_STATUS_EL_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants for Data frame reception
- * --------------------------------------------------------------------------*/
-
-/* the Data frame receive status element configuration structure */
-typedef struct {
- unsigned short number_Rx_status_elements PACKED; /* number of receive status elements */
- unsigned long base_addr_Rx_status_elements PACKED; /* base address of the receive element list */
- unsigned long next_Rx_status_element_to_use PACKED; /* pointer to the next receive element to be used */
- unsigned long base_addr_Rx_buffer PACKED; /* base address of the receive data buffer */
- unsigned long end_addr_Rx_buffer PACKED; /* end address of the receive data buffer */
-} CHDLC_RX_STATUS_EL_CFG_STRUCT;
-
-/* the Data frame receive status element structure */
-typedef struct {
- unsigned char opp_flag PACKED; /* opp flag */
- unsigned short frame_length PACKED; /* length of the received frame */
- unsigned char error_flag PACKED; /* frame errors (HDLC_STREAMING_MODE)*/
- unsigned short time_stamp PACKED; /* receive time stamp (HDLC_STREAMING_MODE) */
- unsigned long reserved_1 PACKED; /* reserved for internal use */
- unsigned short reserved_2 PACKED; /* reserved for internal use */
- unsigned long ptr_data_bfr PACKED; /* pointer to the data area */
-} CHDLC_DATA_RX_STATUS_EL_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- * Constants defining the shared memory information area
- * --------------------------------------------------------------------------*/
-
-/* the global information structure */
-typedef struct {
- unsigned char global_status PACKED; /* global status */
- unsigned char modem_status PACKED; /* current modem status */
- unsigned char global_excep_conditions PACKED; /* global exception conditions */
- unsigned char glob_info_reserved[5] PACKED; /* reserved */
- unsigned char codename[4] PACKED; /* Firmware name */
- unsigned char codeversion[4] PACKED; /* Firmware version */
-} GLOBAL_INFORMATION_STRUCT;
-
-/* the CHDLC information structure */
-typedef struct {
- unsigned char CHDLC_status PACKED; /* CHDLC status */
- unsigned char CHDLC_excep_conditions PACKED; /* CHDLC exception conditions */
- unsigned char CHDLC_info_reserved[14] PACKED; /* reserved */
-} CHDLC_INFORMATION_STRUCT;
-
-/* the interrupt information structure */
-typedef struct {
- unsigned char interrupt_type PACKED; /* type of interrupt triggered */
- unsigned char interrupt_permission PACKED; /* interrupt permission mask */
- unsigned char int_info_reserved[14] PACKED; /* reserved */
-} INTERRUPT_INFORMATION_STRUCT;
-
-/* the S508/FT1 information structure */
-typedef struct {
- unsigned char parallel_port_A_input PACKED; /* input - parallel port A */
- unsigned char parallel_port_B_input PACKED; /* input - parallel port B */
- unsigned char FT1_info_reserved[14] PACKED; /* reserved */
-} FT1_INFORMATION_STRUCT;
-
-/* the shared memory area information structure */
-typedef struct {
- GLOBAL_INFORMATION_STRUCT global_info_struct PACKED; /* the global information structure */
- CHDLC_INFORMATION_STRUCT CHDLC_info_struct PACKED; /* the CHDLC information structure */
- INTERRUPT_INFORMATION_STRUCT interrupt_info_struct PACKED; /* the interrupt information structure */
- FT1_INFORMATION_STRUCT FT1_info_struct PACKED; /* the S508/FT1 information structure */
-} SHARED_MEMORY_INFO_STRUCT;
-
-/* ----------------------------------------------------------------------------
- * UDP Management constants and structures
- * --------------------------------------------------------------------------*/
-
-/* The embedded control block for UDP mgmt
- This is essentially a mailbox structure, without the large data field */
-
-typedef struct {
- unsigned char opp_flag PACKED; /* the opp flag */
- unsigned char command PACKED; /* the user command */
- unsigned short buffer_length PACKED; /* the data length */
- unsigned char return_code PACKED; /* the return code */
- unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED; /* reserved for later */
-} cblock_t;
-
-
-/* UDP management packet layout (data area of ip packet) */
-/*
-typedef struct {
- unsigned char signature[8] PACKED;
- unsigned char request_reply PACKED;
- unsigned char id PACKED;
- unsigned char reserved[6] PACKED;
- cblock_t cblock PACKED;
- unsigned char num_frames PACKED;
- unsigned char ismoredata PACKED;
- unsigned char data[SIZEOF_MB_DATA_BFR] PACKED;
-} udp_management_packet_t;
-
-*/
-
-typedef struct {
- unsigned char num_frames PACKED;
- unsigned char ismoredata PACKED;
-} trace_info_t;
-
-typedef struct {
- ip_pkt_t ip_pkt PACKED;
- udp_pkt_t udp_pkt PACKED;
- wp_mgmt_t wp_mgmt PACKED;
- cblock_t cblock PACKED;
- trace_info_t trace_info PACKED;
- unsigned char data[SIZEOF_MB_DATA_BFR] PACKED;
-} chdlc_udp_pkt_t;
-
-typedef struct ft1_exec_cmd{
- unsigned char command PACKED; /* the user command */
- unsigned short buffer_length PACKED; /* the data length */
- unsigned char return_code PACKED; /* the return code */
- unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED;
-} ft1_exec_cmd_t;
-
-typedef struct {
- unsigned char opp_flag PACKED;
- ft1_exec_cmd_t cmd PACKED;
- unsigned char data[SIZEOF_MB_DATA_BFR] PACKED;
-} ft1_exec_t;
-
-#define UDPMGMT_SIGNATURE "CTPIPEAB"
-
-
-/* UDP/IP packet (for UDP management) layout */
-/*
-typedef struct {
- unsigned char reserved[2] PACKED;
- unsigned short ip_length PACKED;
- unsigned char reserved2[4] PACKED;
- unsigned char ip_ttl PACKED;
- unsigned char ip_protocol PACKED;
- unsigned short ip_checksum PACKED;
- unsigned long ip_src_address PACKED;
- unsigned long ip_dst_address PACKED;
- unsigned short udp_src_port PACKED;
- unsigned short udp_dst_port PACKED;
- unsigned short udp_length PACKED;
- unsigned short udp_checksum PACKED;
- udp_management_packet_t um_packet PACKED;
-} ip_packet_t;
-*/
-
-/* valid ip_protocol for UDP management */
-#define UDPMGMT_UDP_PROTOCOL 0x11
-
-
-typedef struct {
- unsigned char status PACKED;
- unsigned char data_avail PACKED;
- unsigned short real_length PACKED;
- unsigned short time_stamp PACKED;
- unsigned char data[1] PACKED;
-} trace_pkt_t;
-
-typedef struct {
- unsigned char error_flag PACKED;
- unsigned short time_stamp PACKED;
- unsigned char reserved[13] PACKED;
-} api_rx_hdr_t;
-
-typedef struct {
- api_rx_hdr_t api_rx_hdr PACKED;
- void * data PACKED;
-} api_rx_element_t;
-
-typedef struct {
- unsigned char attr PACKED;
- unsigned char reserved[15] PACKED;
-} api_tx_hdr_t;
-
-typedef struct {
- api_tx_hdr_t api_tx_hdr PACKED;
- void * data PACKED;
-} api_tx_element_t;
-
-/* ----------------------------------------------------------------------------
- * Constants for the SET_FT1_CONFIGURATION/READ_FT1_CONFIGURATION command
- * --------------------------------------------------------------------------*/
-
-/* the FT1 configuration structure */
-typedef struct {
- unsigned short framing_mode;
- unsigned short encoding_mode;
- unsigned short line_build_out;
- unsigned short channel_base;
- unsigned short baud_rate_kbps; /* the baud rate (in kbps) */
- unsigned short clock_mode;
-} ft1_config_t;
-
-/* settings for the 'framing_mode' */
-#define ESF_FRAMING 0x00 /* ESF framing */
-#define D4_FRAMING 0x01 /* D4 framing */
-
-/* settings for the 'encoding_mode' */
-#define B8ZS_ENCODING 0x00 /* B8ZS encoding */
-#define AMI_ENCODING 0x01 /* AMI encoding */
-
-/* settings for the 'line_build_out' */
-#define LN_BLD_CSU_0dB_DSX1_0_to_133 0x00 /* set build out to CSU (0db) or DSX-1 (0-133ft) */
-#define LN_BLD_DSX1_133_to_266 0x01 /* set build out DSX-1 (133-266ft) */
-#define LN_BLD_DSX1_266_to_399 0x02 /* set build out DSX-1 (266-399ft) */
-#define LN_BLD_DSX1_399_to_533 0x03 /* set build out DSX-1 (399-533ft) */
-#define LN_BLD_DSX1_533_to_655 0x04 /* set build out DSX-1 (533-655ft) */
-#define LN_BLD_CSU_NEG_7dB 0x05 /* set build out to CSU (-7.5db) */
-#define LN_BLD_CSU_NEG_15dB 0x06 /* set build out to CSU (-15db) */
-#define LN_BLD_CSU_NEG_22dB 0x07 /* set build out to CSU (-22.5db) */
-
-/* settings for the 'channel_base' */
-#define MIN_CHANNEL_BASE_VALUE 1 /* the minimum permitted channel base value */
-#define MAX_CHANNEL_BASE_VALUE 24 /* the maximum permitted channel base value */
-
-/* settings for the 'baud_rate_kbps' */
-#define MIN_BAUD_RATE_KBPS 0 /* the minimum permitted baud rate (kbps) */
-#define MAX_BAUD_RATE_KBPS 1536 /* the maximum permitted baud rate (kbps) */
-#define BAUD_RATE_FT1_AUTO_CONFIG 0xFFFF /* the baud rate used to trigger an automatic FT1 configuration */
-
-/* settings for the 'clock_mode' */
-#define CLOCK_MODE_NORMAL 0x00 /* clock mode set to normal (slave) */
-#define CLOCK_MODE_MASTER 0x01 /* clock mode set to master */
-
-
-#define BAUD_RATE_FT1_AUTO_CONFIG 0xFFFF
-#define AUTO_FT1_CONFIG_NOT_COMPLETE 0x08
-#define AUTO_FT1_CFG_FAIL_OP_MODE 0x0C
-#define AUTO_FT1_CFG_FAIL_INVALID_LINE 0x0D
-
-
-#ifdef _MSC_
-# pragma pack()
-#endif
-#endif /* _SDLA_CHDLC_H */
diff --git a/include/linux/sdla_ppp.h b/include/linux/sdla_ppp.h
deleted file mode 100644
index 6f3923179c2..00000000000
--- a/include/linux/sdla_ppp.h
+++ /dev/null
@@ -1,575 +0,0 @@
-/*****************************************************************************
-* sdla_ppp.h Sangoma PPP firmware API definitions.
-*
-* Author: Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright: (c) 1995-1997 Sangoma Technologies 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.
-* ============================================================================
-* Feb 24, 2000 Nenad Corbic v2.1.2
-* Jan 06, 1997 Gene Kozin v2.0
-* Apr 11, 1996 Gene Kozin Initial version.
-*****************************************************************************/
-#ifndef _SDLA_PPP_H
-#define _SDLA_PPP_H
-
-/*----------------------------------------------------------------------------
- * Notes:
- * ------
- * 1. All structures defined in this file are byte-alined.
- *
- * Compiler Platform
- * -------- --------
- * GNU C Linux
- */
-
-#ifndef PACKED
-# define PACKED __attribute__((packed))
-#endif /* PACKED */
-
-/* Adapter memory layout and important constants */
-#define PPP508_MB_VECT 0xE000 /* mailbox window vector */
-#define PPP508_MB_OFFS 0 /* mailbox offset */
-#define PPP508_FLG_OFFS 0x1000 /* status flags offset */
-#define PPP508_BUF_OFFS 0x1100 /* buffer info block offset */
-#define PPP514_MB_OFFS 0xE000 /* mailbox offset */
-#define PPP514_FLG_OFFS 0xF000 /* status flags offset */
-#define PPP514_BUF_OFFS 0xF100 /* buffer info block offset */
-
-#define PPP_MAX_DATA 1008 /* command block data buffer length */
-
-/****** Data Structures *****************************************************/
-
-/*----------------------------------------------------------------------------
- * PPP Command Block.
- */
-typedef struct ppp_cmd{
- unsigned char command PACKED; /* command code */
- unsigned short length PACKED; /* length of data buffer */
- unsigned char result PACKED; /* return code */
- unsigned char rsrv[11] PACKED; /* reserved for future use */
-} ppp_cmd_t;
-
-typedef struct cblock{
- unsigned char opp_flag PACKED;
- unsigned char command PACKED; /* command code */
- unsigned short length PACKED; /* length of data buffer */
- unsigned char result PACKED; /* return code */
- unsigned char rsrv[11] PACKED; /* reserved for future use */
-} cblock_t;
-
-typedef struct ppp_udp_pkt{
- ip_pkt_t ip_pkt PACKED;
- udp_pkt_t udp_pkt PACKED;
- wp_mgmt_t wp_mgmt PACKED;
- cblock_t cblock PACKED;
- unsigned char data[MAX_LGTH_UDP_MGNT_PKT] PACKED;
-} ppp_udp_pkt_t;
-
-typedef struct {
- unsigned char status PACKED;
- unsigned char data_avail PACKED;
- unsigned short real_length PACKED;
- unsigned short time_stamp PACKED;
- unsigned char data[1] PACKED;
-} trace_pkt_t;
-
-
-typedef struct {
- unsigned char opp_flag PACKED;
- unsigned char trace_type PACKED;
- unsigned short trace_length PACKED;
- unsigned short trace_data_ptr PACKED;
- unsigned short trace_time_stamp PACKED;
-} trace_element_t;
-
-/* 'command' field defines */
-#define PPP_READ_CODE_VERSION 0x10 /* configuration commands */
-#define PPP_SET_CONFIG 0x05
-#define PPP_READ_CONFIG 0x06
-#define PPP_SET_INTR_FLAGS 0x20
-#define PPP_READ_INTR_FLAGS 0x21
-#define PPP_SET_INBOUND_AUTH 0x30
-#define PPP_SET_OUTBOUND_AUTH 0x31
-#define PPP_GET_CONNECTION_INFO 0x32
-
-#define PPP_COMM_ENABLE 0x03 /* operational commands */
-#define PPP_COMM_DISABLE 0x04
-#define PPP_SEND_SIGN_FRAME 0x23
-#define PPP_READ_SIGN_RESPONSE 0x24
-#define PPP_DATALINE_MONITOR 0x33
-
-#define PPP_READ_STATISTICS 0x07 /* statistics commands */
-#define PPP_FLUSH_STATISTICS 0x08
-#define PPP_READ_ERROR_STATS 0x09
-#define PPP_FLUSH_ERROR_STATS 0x0A
-#define PPP_READ_PACKET_STATS 0x12
-#define PPP_FLUSH_PACKET_STATS 0x13
-#define PPP_READ_LCP_STATS 0x14
-#define PPP_FLUSH_LCP_STATS 0x15
-#define PPP_READ_LPBK_STATS 0x16
-#define PPP_FLUSH_LPBK_STATS 0x17
-#define PPP_READ_IPCP_STATS 0x18
-#define PPP_FLUSH_IPCP_STATS 0x19
-#define PPP_READ_IPXCP_STATS 0x1A
-#define PPP_FLUSH_IPXCP_STATS 0x1B
-#define PPP_READ_PAP_STATS 0x1C
-#define PPP_FLUSH_PAP_STATS 0x1D
-#define PPP_READ_CHAP_STATS 0x1E
-#define PPP_FLUSH_CHAP_STATS 0x1F
-
-/* 'result' field defines */
-#define PPPRES_OK 0x00 /* command executed successfully */
-#define PPPRES_INVALID_STATE 0x09 /* invalid command in this context */
-
-/*----------------------------------------------------------------------------
- * PPP Mailbox.
- * This structure is located at offset PPP???_MB_OFFS into PPP???_MB_VECT
- */
-typedef struct ppp_mbox
-{
- unsigned char flag PACKED; /* 00h: command execution flag */
- ppp_cmd_t cmd PACKED; /* 01h: command block */
- unsigned char data[1] PACKED; /* 10h: variable length data buffer */
-} ppp_mbox_t;
-
-/*----------------------------------------------------------------------------
- * PPP Status Flags.
- * This structure is located at offset PPP???_FLG_OFFS into
- * PPP???_MB_VECT.
- */
-typedef struct ppp_flags
-{
- unsigned char iflag PACKED; /* 00: interrupt flag */
- unsigned char imask PACKED; /* 01: interrupt mask */
- unsigned char resrv PACKED;
- unsigned char mstatus PACKED; /* 03: modem status */
- unsigned char lcp_state PACKED; /* 04: LCP state */
- unsigned char ppp_phase PACKED; /* 05: PPP phase */
- unsigned char ip_state PACKED; /* 06: IPCP state */
- unsigned char ipx_state PACKED; /* 07: IPXCP state */
- unsigned char pap_state PACKED; /* 08: PAP state */
- unsigned char chap_state PACKED; /* 09: CHAP state */
- unsigned short disc_cause PACKED; /* 0A: disconnection cause */
-} ppp_flags_t;
-
-/* 'iflag' defines */
-#define PPP_INTR_RXRDY 0x01 /* Rx ready */
-#define PPP_INTR_TXRDY 0x02 /* Tx ready */
-#define PPP_INTR_MODEM 0x04 /* modem status change (DCD, CTS) */
-#define PPP_INTR_CMD 0x08 /* interface command completed */
-#define PPP_INTR_DISC 0x10 /* data link disconnected */
-#define PPP_INTR_OPEN 0x20 /* data link open */
-#define PPP_INTR_DROP_DTR 0x40 /* DTR drop timeout expired */
-#define PPP_INTR_TIMER 0x80 /* timer interrupt */
-
-
-/* 'mstatus' defines */
-#define PPP_MDM_DCD 0x08 /* mdm_status: DCD */
-#define PPP_MDM_CTS 0x20 /* mdm_status: CTS */
-
-/* 'disc_cause' defines */
-#define PPP_LOCAL_TERMINATION 0x0001 /* Local Request by PPP termination phase */
-#define PPP_DCD_CTS_DROP 0x0002 /* DCD and/or CTS dropped. Link down */
-#define PPP_REMOTE_TERMINATION 0x0800 /* Remote Request by PPP termination phase */
-
-/* 'misc_config_bits' defines */
-#define DONT_RE_TX_ABORTED_I_FRAMES 0x01
-#define TX_FRM_BYTE_COUNT_STATS 0x02
-#define RX_FRM_BYTE_COUNT_STATS 0x04
-#define TIME_STAMP_IN_RX_FRAMES 0x08
-#define NON_STD_ADPTR_FREQ 0x10
-#define INTERFACE_LEVEL_RS232 0x20
-#define AUTO_LINK_RECOVERY 0x100
-#define DONT_TERMINATE_LNK_MAX_CONFIG 0x200
-
-/* 'authentication options' defines */
-#define NO_AUTHENTICATION 0x00
-#define INBOUND_AUTH 0x80
-#define PAP_AUTH 0x01
-#define CHAP_AUTH 0x02
-
-/* 'ip options' defines */
-#define L_AND_R_IP_NO_ASSIG 0x00
-#define L_IP_LOCAL_ASSIG 0x01
-#define L_IP_REMOTE_ASSIG 0x02
-#define R_IP_LOCAL_ASSIG 0x04
-#define R_IP_REMOTE_ASSIG 0x08
-#define ENABLE_IP 0x80
-
-/* 'ipx options' defines */
-#define ROUTING_PROT_DEFAULT 0x20
-#define ENABLE_IPX 0x80
-#define DISABLE_IPX 0x00
-
-/*----------------------------------------------------------------------------
- * PPP Buffer Info.
- * This structure is located at offset PPP508_BUF_OFFS into
- * PPP508_MB_VECT.
- */
-typedef struct ppp508_buf_info
-{
- unsigned short txb_num PACKED; /* 00: number of transmit buffers */
- unsigned long txb_ptr PACKED; /* 02: pointer to the buffer ctl. */
- unsigned long txb_nxt PACKED;
- unsigned char rsrv1[22] PACKED;
- unsigned short rxb_num PACKED; /* 20: number of receive buffers */
- unsigned long rxb_ptr PACKED; /* 22: pointer to the buffer ctl. */
- unsigned long rxb1_ptr PACKED; /* 26: pointer to the first buf.ctl. */
- unsigned long rxb_base PACKED; /* 2A: pointer to the buffer base */
- unsigned char rsrv2[2] PACKED;
- unsigned long rxb_end PACKED; /* 30: pointer to the buffer end */
-} ppp508_buf_info_t;
-
-/*----------------------------------------------------------------------------
- * Transmit/Receive Buffer Control Block.
- */
-typedef struct ppp_buf_ctl
-{
- unsigned char flag PACKED; /* 00: 'buffer ready' flag */
- unsigned short length PACKED; /* 01: length of data */
- unsigned char reserved1[1] PACKED; /* 03: */
- unsigned char proto PACKED; /* 04: protocol */
- unsigned short timestamp PACKED; /* 05: time stamp (Rx only) */
- unsigned char reserved2[5] PACKED; /* 07: */
- union
- {
- unsigned short o_p[2]; /* 1C: buffer offset & page (S502) */
- unsigned long ptr; /* 1C: buffer pointer (S508) */
- } buf PACKED;
-} ppp_buf_ctl_t;
-
-/*----------------------------------------------------------------------------
- * S508 Adapter Configuration Block (passed to the PPP_SET_CONFIG command).
- */
-typedef struct ppp508_conf
-{
- unsigned long line_speed PACKED; /* 00: baud rate, bps */
- unsigned short txbuf_percent PACKED; /* 04: % of Tx buffer */
- unsigned short conf_flags PACKED; /* 06: configuration bits */
- unsigned short mtu_local PACKED; /* 08: local MTU */
- unsigned short mtu_remote PACKED; /* 0A: remote MTU */
- unsigned short restart_tmr PACKED; /* 0C: restart timer */
- unsigned short auth_rsrt_tmr PACKED; /* 0E: authentication timer */
- unsigned short auth_wait_tmr PACKED; /* 10: authentication timer */
- unsigned short mdm_fail_tmr PACKED; /* 12: modem failure timer */
- unsigned short dtr_drop_tmr PACKED; /* 14: DTR drop timer */
- unsigned short connect_tmout PACKED; /* 16: connection timeout */
- unsigned short conf_retry PACKED; /* 18: max. retry */
- unsigned short term_retry PACKED; /* 1A: max. retry */
- unsigned short fail_retry PACKED; /* 1C: max. retry */
- unsigned short auth_retry PACKED; /* 1E: max. retry */
- unsigned char auth_options PACKED; /* 20: authentication opt. */
- unsigned char ip_options PACKED; /* 21: IP options */
- unsigned long ip_local PACKED; /* 22: local IP address */
- unsigned long ip_remote PACKED; /* 26: remote IP address */
- unsigned char ipx_options PACKED; /* 2A: IPX options */
- unsigned char ipx_netno[4] PACKED; /* 2B: IPX net number */
- unsigned char ipx_local[6] PACKED; /* 2F: local IPX node number*/
- unsigned char ipx_remote[6] PACKED; /* 35: remote IPX node num.*/
- unsigned char ipx_router[48] PACKED; /* 3B: IPX router name*/
- unsigned long alt_cpu_clock PACKED; /* 6B: */
-} ppp508_conf_t;
-
-/*----------------------------------------------------------------------------
- * S508 Adapter Read Connection Information Block
- * Returned by the PPP_GET_CONNECTION_INFO command
- */
-typedef struct ppp508_connect_info
-{
- unsigned short mru PACKED; /* 00-01 Remote Max Rec' Unit */
- unsigned char ip_options PACKED; /* 02: Negotiated ip options */
- unsigned long ip_local PACKED; /* 03-06: local IP address */
- unsigned long ip_remote PACKED; /* 07-0A: remote IP address */
- unsigned char ipx_options PACKED; /* 0B: Negotiated ipx options */
- unsigned char ipx_netno[4] PACKED; /* 0C-0F: IPX net number */
- unsigned char ipx_local[6] PACKED; /* 10-1F: local IPX node # */
- unsigned char ipx_remote[6] PACKED; /* 16-1B: remote IPX node # */
- unsigned char ipx_router[48] PACKED; /* 1C-4B: IPX router name */
- unsigned char auth_status PACKED; /* 4C: Authentication Status */
- unsigned char inbd_auth_peerID[1] PACKED; /* 4D: variable length inbound authenticated peer ID */
-} ppp508_connect_info_t;
-
-/* 'line_speed' field */
-#define PPP_BITRATE_1200 0x01
-#define PPP_BITRATE_2400 0x02
-#define PPP_BITRATE_4800 0x03
-#define PPP_BITRATE_9600 0x04
-#define PPP_BITRATE_19200 0x05
-#define PPP_BITRATE_38400 0x06
-#define PPP_BITRATE_45000 0x07
-#define PPP_BITRATE_56000 0x08
-#define PPP_BITRATE_64000 0x09
-#define PPP_BITRATE_74000 0x0A
-#define PPP_BITRATE_112000 0x0B
-#define PPP_BITRATE_128000 0x0C
-#define PPP_BITRATE_156000 0x0D
-
-/* Defines for the 'conf_flags' field */
-#define PPP_IGNORE_TX_ABORT 0x01 /* don't re-transmit aborted frames */
-#define PPP_ENABLE_TX_STATS 0x02 /* enable Tx statistics */
-#define PPP_ENABLE_RX_STATS 0x04 /* enable Rx statistics */
-#define PPP_ENABLE_TIMESTAMP 0x08 /* enable timestamp */
-
-/* 'ip_options' defines */
-#define PPP_LOCAL_IP_LOCAL 0x01
-#define PPP_LOCAL_IP_REMOTE 0x02
-#define PPP_REMOTE_IP_LOCAL 0x04
-#define PPP_REMOTE_IP_REMOTE 0x08
-
-/* 'ipx_options' defines */
-#define PPP_REMOTE_IPX_NETNO 0x01
-#define PPP_REMOTE_IPX_LOCAL 0x02
-#define PPP_REMOTE_IPX_REMOTE 0x04
-#define PPP_IPX_ROUTE_RIP_SAP 0x08
-#define PPP_IPX_ROUTE_NLSP 0x10
-#define PPP_IPX_ROUTE_DEFAULT 0x20
-#define PPP_IPX_CONF_COMPLETE 0x40
-#define PPP_IPX_ENABLE 0x80
-
-/*----------------------------------------------------------------------------
- * S508 Adapter Configuration Block (returned by the PPP_READ_CONFIG command).
- */
-typedef struct ppp508_get_conf
-{
- unsigned long bps PACKED; /* 00: baud rate, bps */
- ppp508_conf_t conf PACKED; /* 04: requested config. */
- unsigned short txb_num PACKED; /* 6F: number of Tx buffers */
- unsigned short rxb_num PACKED; /* 71: number of Rx buffers */
-} ppp508_get_conf_t;
-
-/*----------------------------------------------------------------------------
- * S508 Operational Statistics (returned by the PPP_READ_STATISTIC command).
- */
-typedef struct ppp508_stats
-{
- unsigned short reserved1 PACKED; /* 00: */
- unsigned short rx_bad_len PACKED; /* 02: */
- unsigned short reserved2 PACKED; /* 04: */
- unsigned long tx_frames PACKED; /* 06: */
- unsigned long tx_bytes PACKED; /* 0A: */
- unsigned long rx_frames PACKED; /* 0E: */
- unsigned long rx_bytes PACKED; /* 12: */
-} ppp508_stats_t;
-
-/*----------------------------------------------------------------------------
- * Adapter Error Statistics (returned by the PPP_READ_ERROR_STATS command).
- */
-typedef struct ppp_err_stats
-{
- unsigned char rx_overrun PACKED; /* 00: Rx overrun errors */
- unsigned char rx_bad_crc PACKED; /* 01: Rx CRC errors */
- unsigned char rx_abort PACKED; /* 02: Rx aborted frames */
- unsigned char rx_lost PACKED; /* 03: Rx frames lost */
- unsigned char tx_abort PACKED; /* 04: Tx aborted frames */
- unsigned char tx_underrun PACKED; /* 05: Tx underrun errors */
- unsigned char tx_missed_intr PACKED; /* 06: Tx underruns missed */
- unsigned char reserved PACKED; /* 07: Tx underruns missed */
- unsigned char dcd_trans PACKED; /* 08: DCD transitions */
- unsigned char cts_trans PACKED; /* 09: CTS transitions */
-} ppp_err_stats_t;
-
-/*----------------------------------------------------------------------------
- * Packet Statistics (returned by the PPP_READ_PACKET_STATS command).
- */
-typedef struct ppp_pkt_stats
-{
- unsigned short rx_bad_header PACKED; /* 00: */
- unsigned short rx_prot_unknwn PACKED; /* 02: */
- unsigned short rx_too_large PACKED; /* 04: */
- unsigned short rx_lcp PACKED; /* 06: */
- unsigned short tx_lcp PACKED; /* 08: */
- unsigned short rx_ipcp PACKED; /* 0A: */
- unsigned short tx_ipcp PACKED; /* 0C: */
- unsigned short rx_ipxcp PACKED; /* 0E: */
- unsigned short tx_ipxcp PACKED; /* 10: */
- unsigned short rx_pap PACKED; /* 12: */
- unsigned short tx_pap PACKED; /* 14: */
- unsigned short rx_chap PACKED; /* 16: */
- unsigned short tx_chap PACKED; /* 18: */
- unsigned short rx_lqr PACKED; /* 1A: */
- unsigned short tx_lqr PACKED; /* 1C: */
- unsigned short rx_ip PACKED; /* 1E: */
- unsigned short tx_ip PACKED; /* 20: */
- unsigned short rx_ipx PACKED; /* 22: */
- unsigned short tx_ipx PACKED; /* 24: */
-} ppp_pkt_stats_t;
-
-/*----------------------------------------------------------------------------
- * LCP Statistics (returned by the PPP_READ_LCP_STATS command).
- */
-typedef struct ppp_lcp_stats
-{
- unsigned short rx_unknown PACKED; /* 00: unknown LCP type */
- unsigned short rx_conf_rqst PACKED; /* 02: Configure-Request */
- unsigned short rx_conf_ack PACKED; /* 04: Configure-Ack */
- unsigned short rx_conf_nak PACKED; /* 06: Configure-Nak */
- unsigned short rx_conf_rej PACKED; /* 08: Configure-Reject */
- unsigned short rx_term_rqst PACKED; /* 0A: Terminate-Request */
- unsigned short rx_term_ack PACKED; /* 0C: Terminate-Ack */
- unsigned short rx_code_rej PACKED; /* 0E: Code-Reject */
- unsigned short rx_proto_rej PACKED; /* 10: Protocol-Reject */
- unsigned short rx_echo_rqst PACKED; /* 12: Echo-Request */
- unsigned short rx_echo_reply PACKED; /* 14: Echo-Reply */
- unsigned short rx_disc_rqst PACKED; /* 16: Discard-Request */
- unsigned short tx_conf_rqst PACKED; /* 18: Configure-Request */
- unsigned short tx_conf_ack PACKED; /* 1A: Configure-Ack */
- unsigned short tx_conf_nak PACKED; /* 1C: Configure-Nak */
- unsigned short tx_conf_rej PACKED; /* 1E: Configure-Reject */
- unsigned short tx_term_rqst PACKED; /* 20: Terminate-Request */
- unsigned short tx_term_ack PACKED; /* 22: Terminate-Ack */
- unsigned short tx_code_rej PACKED; /* 24: Code-Reject */
- unsigned short tx_proto_rej PACKED; /* 26: Protocol-Reject */
- unsigned short tx_echo_rqst PACKED; /* 28: Echo-Request */
- unsigned short tx_echo_reply PACKED; /* 2A: Echo-Reply */
- unsigned short tx_disc_rqst PACKED; /* 2E: Discard-Request */
- unsigned short rx_too_large PACKED; /* 30: packets too large */
- unsigned short rx_ack_inval PACKED; /* 32: invalid Conf-Ack */
- unsigned short rx_rej_inval PACKED; /* 34: invalid Conf-Reject */
- unsigned short rx_rej_badid PACKED; /* 36: Conf-Reject w/bad ID */
-} ppp_lcp_stats_t;
-
-/*----------------------------------------------------------------------------
- * Loopback Error Statistics (returned by the PPP_READ_LPBK_STATS command).
- */
-typedef struct ppp_lpbk_stats
-{
- unsigned short conf_magic PACKED; /* 00: */
- unsigned short loc_echo_rqst PACKED; /* 02: */
- unsigned short rem_echo_rqst PACKED; /* 04: */
- unsigned short loc_echo_reply PACKED; /* 06: */
- unsigned short rem_echo_reply PACKED; /* 08: */
- unsigned short loc_disc_rqst PACKED; /* 0A: */
- unsigned short rem_disc_rqst PACKED; /* 0C: */
- unsigned short echo_tx_collsn PACKED; /* 0E: */
- unsigned short echo_rx_collsn PACKED; /* 10: */
-} ppp_lpbk_stats_t;
-
-/*----------------------------------------------------------------------------
- * Protocol Statistics (returned by the PPP_READ_IPCP_STATS and
- * PPP_READ_IPXCP_STATS commands).
- */
-typedef struct ppp_prot_stats
-{
- unsigned short rx_unknown PACKED; /* 00: unknown type */
- unsigned short rx_conf_rqst PACKED; /* 02: Configure-Request */
- unsigned short rx_conf_ack PACKED; /* 04: Configure-Ack */
- unsigned short rx_conf_nak PACKED; /* 06: Configure-Nak */
- unsigned short rx_conf_rej PACKED; /* 08: Configure-Reject */
- unsigned short rx_term_rqst PACKED; /* 0A: Terminate-Request */
- unsigned short rx_term_ack PACKED; /* 0C: Terminate-Ack */
- unsigned short rx_code_rej PACKED; /* 0E: Code-Reject */
- unsigned short reserved PACKED; /* 10: */
- unsigned short tx_conf_rqst PACKED; /* 12: Configure-Request */
- unsigned short tx_conf_ack PACKED; /* 14: Configure-Ack */
- unsigned short tx_conf_nak PACKED; /* 16: Configure-Nak */
- unsigned short tx_conf_rej PACKED; /* 18: Configure-Reject */
- unsigned short tx_term_rqst PACKED; /* 1A: Terminate-Request */
- unsigned short tx_term_ack PACKED; /* 1C: Terminate-Ack */
- unsigned short tx_code_rej PACKED; /* 1E: Code-Reject */
- unsigned short rx_too_large PACKED; /* 20: packets too large */
- unsigned short rx_ack_inval PACKED; /* 22: invalid Conf-Ack */
- unsigned short rx_rej_inval PACKED; /* 24: invalid Conf-Reject */
- unsigned short rx_rej_badid PACKED; /* 26: Conf-Reject w/bad ID */
-} ppp_prot_stats_t;
-
-/*----------------------------------------------------------------------------
- * PAP Statistics (returned by the PPP_READ_PAP_STATS command).
- */
-typedef struct ppp_pap_stats
-{
- unsigned short rx_unknown PACKED; /* 00: unknown type */
- unsigned short rx_auth_rqst PACKED; /* 02: Authenticate-Request */
- unsigned short rx_auth_ack PACKED; /* 04: Authenticate-Ack */
- unsigned short rx_auth_nak PACKED; /* 06: Authenticate-Nak */
- unsigned short reserved PACKED; /* 08: */
- unsigned short tx_auth_rqst PACKED; /* 0A: Authenticate-Request */
- unsigned short tx_auth_ack PACKED; /* 0C: Authenticate-Ack */
- unsigned short tx_auth_nak PACKED; /* 0E: Authenticate-Nak */
- unsigned short rx_too_large PACKED; /* 10: packets too large */
- unsigned short rx_bad_peerid PACKED; /* 12: invalid peer ID */
- unsigned short rx_bad_passwd PACKED; /* 14: invalid password */
-} ppp_pap_stats_t;
-
-/*----------------------------------------------------------------------------
- * CHAP Statistics (returned by the PPP_READ_CHAP_STATS command).
- */
-typedef struct ppp_chap_stats
-{
- unsigned short rx_unknown PACKED; /* 00: unknown type */
- unsigned short rx_challenge PACKED; /* 02: Authenticate-Request */
- unsigned short rx_response PACKED; /* 04: Authenticate-Ack */
- unsigned short rx_success PACKED; /* 06: Authenticate-Nak */
- unsigned short rx_failure PACKED; /* 08: Authenticate-Nak */
- unsigned short reserved PACKED; /* 0A: */
- unsigned short tx_challenge PACKED; /* 0C: Authenticate-Request */
- unsigned short tx_response PACKED; /* 0E: Authenticate-Ack */
- unsigned short tx_success PACKED; /* 10: Authenticate-Nak */
- unsigned short tx_failure PACKED; /* 12: Authenticate-Nak */
- unsigned short rx_too_large PACKED; /* 14: packets too large */
- unsigned short rx_bad_peerid PACKED; /* 16: invalid peer ID */
- unsigned short rx_bad_passwd PACKED; /* 18: invalid password */
- unsigned short rx_bad_md5 PACKED; /* 1A: invalid MD5 format */
- unsigned short rx_bad_resp PACKED; /* 1C: invalid response */
-} ppp_chap_stats_t;
-
-/*----------------------------------------------------------------------------
- * Connection Information (returned by the PPP_GET_CONNECTION_INFO command).
- */
-typedef struct ppp_conn_info
-{
- unsigned short remote_mru PACKED; /* 00: */
- unsigned char ip_options PACKED; /* 02: */
- unsigned char ip_local[4] PACKED; /* 03: */
- unsigned char ip_remote[4] PACKED; /* 07: */
- unsigned char ipx_options PACKED; /* 0B: */
- unsigned char ipx_network[4] PACKED; /* 0C: */
- unsigned char ipx_local[6] PACKED; /* 10: */
- unsigned char ipx_remote[6] PACKED; /* 16: */
- unsigned char ipx_router[48] PACKED; /* 1C: */
- unsigned char auth_status PACKED; /* 4C: */
- unsigned char peer_id[0] PACKED; /* 4D: */
-} ppp_conn_info_t;
-
-/* Data structure for SET_TRIGGER_INTR command
- */
-
-typedef struct ppp_intr_info{
- unsigned char i_enable PACKED; /* 0 Interrupt enable bits */
- unsigned char irq PACKED; /* 1 Irq number */
- unsigned short timer_len PACKED; /* 2 Timer delay */
-} ppp_intr_info_t;
-
-
-#define FT1_MONITOR_STATUS_CTRL 0x80
-#define SET_FT1_MODE 0x81
-
-
-
-/* Special UDP drivers management commands */
-#define PPIPE_ENABLE_TRACING 0x20
-#define PPIPE_DISABLE_TRACING 0x21
-#define PPIPE_GET_TRACE_INFO 0x22
-#define PPIPE_GET_IBA_DATA 0x23
-#define PPIPE_KILL_BOARD 0x24
-#define PPIPE_FT1_READ_STATUS 0x25
-#define PPIPE_DRIVER_STAT_IFSEND 0x26
-#define PPIPE_DRIVER_STAT_INTR 0x27
-#define PPIPE_DRIVER_STAT_GEN 0x28
-#define PPIPE_FLUSH_DRIVER_STATS 0x29
-#define PPIPE_ROUTER_UP_TIME 0x30
-
-#define DISABLE_TRACING 0x00
-#define TRACE_SIGNALLING_FRAMES 0x01
-#define TRACE_DATA_FRAMES 0x02
-
-
-
-#ifdef _MSC_
-# pragma pack()
-#endif
-#endif /* _SDLA_PPP_H */
diff --git a/include/linux/sdla_x25.h b/include/linux/sdla_x25.h
deleted file mode 100644
index 57db980e27a..00000000000
--- a/include/linux/sdla_x25.h
+++ /dev/null
@@ -1,772 +0,0 @@
-/*****************************************************************************
-* sdla_x25.h Sangoma X.25 firmware API definitions.
-*
-* Author: Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright: (c) 1995-2000 Sangoma Technologies 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.
-* ============================================================================
-* Feb 28, 2000 Nenad Corbic Updated for socket based x25api
-* Dec 13, 1996 Gene Kozin Initial version
-*****************************************************************************/
-#ifndef _SDLA_X25_H
-#define _SDLA_X25_H
-
-/*----------------------------------------------------------------------------
- * Notes:
- * ------
- * 1. All structures defined in this file are byte-alined.
- * Compiler Platform
- * -------- --------
- * GNU C Linux
- *
- */
-
-#ifndef PACKED
-# define PACKED __attribute__((packed))
-#endif /* PACKED */
-
-/****** CONSTANTS DEFINITIONS ***********************************************/
-
-#define X25_MAX_CHAN 255 /* max number of open X.25 circuits */
-#define X25_MAX_DATA 1024 /* max length of X.25 data buffer */
-/*
- * X.25 shared memory layout.
- */
-#define X25_MBOX_OFFS 0x16B0 /* general mailbox block */
-#define X25_RXMBOX_OFFS 0x1AD0 /* receive mailbox */
-#define X25_STATUS_OFFS 0x1EF0 /* X.25 status structure */
-#define X25_MB_VECTOR 0xE000 /* S514 mailbox window vecotr */
-#define X25_MISC_HDLC_BITS 0x1F00 /*X.25 miscallaneous HDLC bits */
-
-/* code levels */
-#define HDLC_LEVEL 0x01
-#define X25_LEVEL 0x02
-#define X25_AND_HDLC_LEVEL 0x03
-#define DO_HDLC_LEVEL_ERROR_CHECKING 0x04
-
-/****** DATA STRUCTURES *****************************************************/
-
-/*----------------------------------------------------------------------------
- * X.25 Command Block.
- */
-typedef struct X25Cmd
-{
- unsigned char command PACKED; /* command code */
- unsigned short length PACKED; /* transfer data length */
- unsigned char result PACKED; /* return code */
- unsigned char pf PACKED; /* P/F bit */
- unsigned short lcn PACKED; /* logical channel */
- unsigned char qdm PACKED; /* Q/D/M bits */
- unsigned char cause PACKED; /* cause field */
- unsigned char diagn PACKED; /* diagnostics */
- unsigned char pktType PACKED; /* packet type */
- unsigned char resrv[4] PACKED; /* reserved */
-} TX25Cmd;
-
-/*
- * Defines for the 'command' field.
- */
-/*----- General commands --------------*/
-#define X25_SET_GLOBAL_VARS 0x0B /* set global variables */
-#define X25_READ_MODEM_STATUS 0x0C /* read modem status */
-#define X25_READ_CODE_VERSION 0x15 /* read firmware version number */
-#define X25_TRACE_CONFIGURE 0x14 /* configure trace facility */
-#define X25_READ_TRACE_DATA 0x16 /* read trace data */
-#define X25_SET_INTERRUPT_MODE 0x17 /* set interrupt generation mode */
-#define X25_READ_INTERRUPT_MODE 0x18 /* read interrupt generation mode */
-/*----- HDLC-level commands -----------*/
-#define X25_HDLC_LINK_CONFIGURE 0x01 /* configure HDLC link level */
-#define X25_HDLC_LINK_OPEN 0x02 /* open HDLC link */
-#define X25_HDLC_LINK_CLOSE 0x03 /* close HDLC link */
-#define X25_HDLC_LINK_SETUP 0x04 /* set up HDLC link */
-#define X25_HDLC_LINK_DISC 0x05 /* disconnect DHLC link */
-#define X25_HDLC_LINK_STATUS 0x06 /* read DHLC link status */
-#define X25_HDLC_READ_STATS 0x07 /* read operational statistics */
-#define X25_HDLC_FLUSH_STATS 0x08 /* flush operational statistics */
-#define X25_HDLC_READ_COMM_ERR 0x09 /* read error statistics */
-#define X25_HDLC_FLUSH_COMM_ERR 0x0A /* flush error statistics */
-#define X25_HDLC_FLUSH_BUFFERS 0x0D /* flush HDLC-level data buffers */
-#define X25_HDLC_SPRVS_CNT_STAT 0x0F /* read surervisory count status */
-#define X25_HDLC_SEND_UI_FRAME 0x10 /* send unnumbered information frame */
-#define X25_HDLC_WRITE 0x11 /* send HDLC information frame */
-#define X25_HDLC_READ 0x21 /* read HDLC information frame */
-#define X25_HDLC_READ_CONFIG 0x12 /* read HDLC configuration */
-#define X25_HDLC_SET_CONFIG 0x13 /* set HDLC configuration */
-#define SET_PROTOCOL_LEVEL 0x1F /* set protocol level */
-/*----- X.25-level commands -----------*/
-#define X25_READ 0x22 /* read X.25 packet */
-#define X25_WRITE 0x23 /* send X.25 packet */
-#define X25_PLACE_CALL 0x30 /* place a call on SVC */
-#define X25_ACCEPT_CALL 0x31 /* accept incomming call */
-#define X25_CLEAR_CALL 0x32 /* clear call */
-#define X25_CLEAR_CONFRM 0x33 /* send clear confirmation packet */
-#define X25_RESET 0x34 /* send reset request packet */
-#define X25_RESET_CONFRM 0x35 /* send reset confirmation packet */
-#define X25_RESTART 0x36 /* send restart request packet */
-#define X25_RESTART_CONFRM 0x37 /* send restart confirmation packet */
-#define X25_INTERRUPT 0x38 /* send interrupt request packet */
-#define X25_INTERRUPT_CONFRM 0x39 /* send interrupt confirmation pkt */
-#define X25_REGISTRATION_RQST 0x3A /* send registration request packet */
-#define X25_REGISTRATION_CONFRM 0x3B /* send registration confirmation */
-#define X25_IS_DATA_AVAILABLE 0x40 /* querry receive queue */
-#define X25_INCOMMING_CALL_CTL 0x41 /* select incomming call options */
-#define X25_CONFIGURE_PVC 0x42 /* configure PVC */
-#define X25_GET_ACTIVE_CHANNELS 0x43 /* get a list of active circuits */
-#define X25_READ_CHANNEL_CONFIG 0x44 /* read virt. circuit configuration */
-#define X25_FLUSH_DATA_BUFFERS 0x45 /* flush X.25-level data buffers */
-#define X25_READ_HISTORY_TABLE 0x46 /* read asynchronous event log */
-#define X25_HISTORY_TABLE_CTL 0x47 /* control asynchronous event log */
-#define X25_GET_TX_D_BIT_STATUS 0x48 /* is packet with D-bit acknowleged */
-#define X25_READ_STATISTICS 0x49 /* read X.25-level statistics */
-#define X25_FLUSH_STATISTICS 0x4A /* flush X.25-level statistics */
-#define X25_READ_CONFIGURATION 0x50 /* read HDLC & X.25 configuration */
-#define X25_SET_CONFIGURATION 0x51 /* set HDLC & X.25 configuration */
-
-/*
- * Defines for the 'result' field.
- */
-/*----- General results ---------------*/
-#define X25RES_OK 0x00
-#define X25RES_ERROR 0x01
-#define X25RES_LINK_NOT_IN_ABM 0x02 /* link is not in ABM mode */
-#define X25RES_LINK_CLOSED 0x03
-#define X25RES_INVAL_LENGTH 0x04
-#define X25RES_INVAL_CMD 0x05
-#define X25RES_UNNUMBERED_FRAME 0x06 /* unnunbered frame received */
-#define X25RES_FRM_REJECT_MODE 0x07 /* link is in Frame Reject mode */
-#define X25RES_MODEM_FAILURE 0x08 /* DCD and/or CTS dropped */
-#define X25RES_N2_RETRY_LIMIT 0x09 /* N2 retry limit has been exceeded */
-#define X25RES_INVAL_LCN 0x30 /* invalid logical channel number */
-#define X25RES_INVAL_STATE 0x31 /* channel is not in data xfer mode */
-#define X25RES_INVAL_DATA_LEN 0x32 /* invalid data length */
-#define X25RES_NOT_READY 0x33 /* no data available / buffers full */
-#define X25RES_NETWORK_DOWN 0x34
-#define X25RES_CHANNEL_IN_USE 0x35 /* there is data queued on this LCN */
-#define X25RES_REGST_NOT_SUPPRT 0x36 /* registration not supported */
-#define X25RES_INVAL_FORMAT 0x37 /* invalid packet format */
-#define X25RES_D_BIT_NOT_SUPPRT 0x38 /* D-bit pragmatics not supported */
-#define X25RES_FACIL_NOT_SUPPRT 0x39 /* Call facility not supported */
-#define X25RES_INVAL_CALL_ARG 0x3A /* errorneous call arguments */
-#define X25RES_INVAL_CALL_DATA 0x3B /* errorneous call user data */
-#define X25RES_ASYNC_PACKET 0x40 /* asynchronous packet received */
-#define X25RES_PROTO_VIOLATION 0x41 /* protocol violation occurred */
-#define X25RES_PKT_TIMEOUT 0x42 /* X.25 packet time out */
-#define X25RES_PKT_RETRY_LIMIT 0x43 /* X.25 packet retry limit exceeded */
-/*----- Command-dependent results -----*/
-#define X25RES_LINK_DISC 0x00 /* HDLC_LINK_STATUS */
-#define X25RES_LINK_IN_ABM 0x01 /* HDLC_LINK_STATUS */
-#define X25RES_NO_DATA 0x01 /* HDLC_READ/READ_TRACE_DATA*/
-#define X25RES_TRACE_INACTIVE 0x02 /* READ_TRACE_DATA */
-#define X25RES_LINK_IS_OPEN 0x01 /* HDLC_LINK_OPEN */
-#define X25RES_LINK_IS_DISC 0x02 /* HDLC_LINK_DISC */
-#define X25RES_LINK_IS_CLOSED 0x03 /* HDLC_LINK_CLOSE */
-#define X25RES_INVAL_PARAM 0x31 /* INCOMMING_CALL_CTL */
-#define X25RES_INVAL_CONFIG 0x35 /* REGISTR_RQST/CONFRM */
-
-/*
- * Defines for the 'qdm_bits' field.
- */
-#define X25CMD_Q_BIT_MASK 0x04
-#define X25CMD_D_BIT_MASK 0x02
-#define X25CMD_M_BIT_MASK 0x01
-
-/*
- * Defines for the 'pkt_type' field.
- */
-/*----- Asynchronous events ------*/
-#define ASE_CLEAR_RQST 0x02
-#define ASE_RESET_RQST 0x04
-#define ASE_RESTART_RQST 0x08
-#define ASE_INTERRUPT 0x10
-#define ASE_DTE_REGISTR_RQST 0x20
-#define ASE_CALL_RQST 0x30
-#define ASE_CALL_ACCEPTED 0x31
-#define ASE_CLEAR_CONFRM 0x32
-#define ASE_RESET_CONFRM 0x33
-#define ASE_RESTART_CONFRM 0x34
-#define ASE_INTERRUPT_CONFRM 0x35
-#define ASE_DCE_REGISTR_CONFRM 0x36
-#define ASE_DIAGNOSTIC 0x37
-#define ASE_CALL_AUTO_CLEAR 0x38
-#define AUTO_RESPONSE_FLAG 0x80
-/*----- Time-Out events ----------*/
-#define TOE_RESTART_RQST 0x03
-#define TOE_CALL_RQST 0x05
-#define TOE_CLEAR_RQST 0x08
-#define TOE_RESET_RQST 0x0A
-/*----- Protocol Violation events */
-#define PVE_CLEAR_RQST 0x32
-#define PVE_RESET_RQST 0x33
-#define PVE_RESTART_RQST 0x34
-#define PVE_DIAGNOSTIC 0x37
-
-#define INTR_ON_RX_FRAME 0x01
-#define INTR_ON_TX_FRAME 0x02
-#define INTR_ON_MODEM_STATUS_CHANGE 0x04
-#define INTR_ON_COMMAND_COMPLETE 0x08
-#define INTR_ON_X25_ASY_TRANSACTION 0x10
-#define INTR_ON_TIMER 0x40
-#define DIRECT_RX_INTR_USAGE 0x80
-
-#define NO_INTR_PENDING 0x00
-#define RX_INTR_PENDING 0x01
-#define TX_INTR_PENDING 0x02
-#define MODEM_INTR_PENDING 0x04
-#define COMMAND_COMPLETE_INTR_PENDING 0x08
-#define X25_ASY_TRANS_INTR_PENDING 0x10
-#define TIMER_INTR_PENDING 0x40
-
-/*----------------------------------------------------------------------------
- * X.25 Mailbox.
- * This structure is located at offsets X25_MBOX_OFFS and X25_RXMBOX_OFFS
- * into shared memory window.
- */
-typedef struct X25Mbox
-{
- unsigned char opflag PACKED; /* 00h: execution flag */
- TX25Cmd cmd PACKED; /* 01h: command block */
- unsigned char data[1] PACKED; /* 10h: data buffer */
-} TX25Mbox;
-
-/*----------------------------------------------------------------------------
- * X.25 Time Stamp Structure.
- */
-typedef struct X25TimeStamp
-{
- unsigned char month PACKED;
- unsigned char date PACKED;
- unsigned char sec PACKED;
- unsigned char min PACKED;
- unsigned char hour PACKED;
-} TX25TimeStamp;
-
-/*----------------------------------------------------------------------------
- * X.25 Status Block.
- * This structure is located at offset X25_STATUS_OFF into shared memory
- * window.
- */
-typedef struct X25Status
-{
- unsigned short pvc_map PACKED; /* 00h: PVC map */
- unsigned short icc_map PACKED; /* 02h: Incomming Chan. map */
- unsigned short twc_map PACKED; /* 04h: Two-way Cnan. map */
- unsigned short ogc_map PACKED; /* 06h: Outgoing Chan. map */
- TX25TimeStamp tstamp PACKED; /* 08h: timestamp (BCD) */
- unsigned char iflags PACKED; /* 0Dh: interrupt flags */
- unsigned char imask PACKED; /* 0Eh: interrupt mask */
- unsigned char resrv PACKED; /* 0Eh: */
- unsigned char gflags PACKED; /* 10h: misc. HDLC/X25 flags */
- unsigned char cflags[X25_MAX_CHAN] PACKED; /* channel status bytes */
-} TX25Status;
-
-/*
- * Bitmasks for the 'iflags' field.
- */
-#define X25_RX_INTR 0x01 /* receive interrupt */
-#define X25_TX_INTR 0x02 /* transmit interrupt */
-#define X25_MODEM_INTR 0x04 /* modem status interrupt (CTS/DCD) */
-#define X25_EVENT_INTR 0x10 /* asyncronous event encountered */
-#define X25_CMD_INTR 0x08 /* interface command complete */
-
-/*
- * Bitmasks for the 'gflags' field.
- */
-#define X25_HDLC_ABM 0x01 /* HDLC is in ABM mode */
-#define X25_RX_READY 0x02 /* X.25 data available */
-#define X25_TRACE_READY 0x08 /* trace data available */
-#define X25_EVENT_IND 0x20 /* asynchronous event indicator */
-#define X25_TX_READY 0x40 /* space is available in Tx buf.*/
-
-/*
- * Bitmasks for the 'cflags' field.
- */
-#define X25_XFER_MODE 0x80 /* channel is in data transfer mode */
-#define X25_TXWIN_OPEN 0x40 /* transmit window open */
-#define X25_RXBUF_MASK 0x3F /* number of data buffers available */
-
-/*****************************************************************************
- * Following definitions structurize contents of the TX25Mbox.data field for
- * different X.25 interface commands.
- ****************************************************************************/
-
-/* ---------------------------------------------------------------------------
- * X25_SET_GLOBAL_VARS Command.
- */
-typedef struct X25GlobalVars
-{
- unsigned char resrv PACKED; /* 00h: reserved */
- unsigned char dtrCtl PACKED; /* 01h: DTR control code */
- unsigned char resErr PACKED; /* 01h: '1' - reset modem error */
-} TX25GlobalVars;
-
-/*
- * Defines for the 'dtrCtl' field.
- */
-#define X25_RAISE_DTR 0x01
-#define X25_DROP_DTR 0x02
-
-/* ---------------------------------------------------------------------------
- * X25_READ_MODEM_STATUS Command.
- */
-typedef struct X25ModemStatus
-{
- unsigned char status PACKED; /* 00h: modem status */
-} TX25ModemStatus;
-
-/*
- * Defines for the 'status' field.
- */
-#define X25_CTS_MASK 0x20
-#define X25_DCD_MASK 0x08
-
-/* ---------------------------------------------------------------------------
- * X25_HDLC_LINK_STATUS Command.
- */
-typedef struct X25LinkStatus
-{
- unsigned char txQueued PACKED; /* 00h: queued Tx I-frames*/
- unsigned char rxQueued PACKED; /* 01h: queued Rx I-frames*/
- unsigned char station PACKED; /* 02h: DTE/DCE config. */
- unsigned char reserved PACKED; /* 03h: reserved */
- unsigned char sfTally PACKED; /* 04h: supervisory frame tally */
-} TX25LinkStatus;
-
-/*
- * Defines for the 'station' field.
- */
-#define X25_STATION_DTE 0x01 /* station configured as DTE */
-#define X25_STATION_DCE 0x02 /* station configured as DCE */
-
-/* ---------------------------------------------------------------------------
- * X25_HDLC_READ_STATS Command.
- */
-typedef struct HdlcStats
-{ /* a number of ... */
- unsigned short rxIFrames PACKED; /* 00h: ready Rx I-frames */
- unsigned short rxNoseq PACKED; /* 02h: frms out-of-sequence */
- unsigned short rxNodata PACKED; /* 04h: I-frms without data */
- unsigned short rxDiscarded PACKED; /* 06h: discarded frames */
- unsigned short rxTooLong PACKED; /* 08h: frames too long */
- unsigned short rxBadAddr PACKED; /* 0Ah: frms with inval.addr*/
- unsigned short txAcked PACKED; /* 0Ch: acknowledged I-frms */
- unsigned short txRetransm PACKED; /* 0Eh: re-transmit. I-frms */
- unsigned short t1Timeout PACKED; /* 10h: T1 timeouts */
- unsigned short rxSABM PACKED; /* 12h: received SABM frames */
- unsigned short rxDISC PACKED; /* 14h: received DISC frames */
- unsigned short rxDM PACKED; /* 16h: received DM frames */
- unsigned short rxFRMR PACKED; /* 18h: FRMR frames received */
- unsigned short txSABM PACKED; /* 1Ah: transm. SABM frames*/
- unsigned short txDISC PACKED; /* 1Ch: transm. DISC frames*/
- unsigned short txDM PACKED; /* 1Eh: transm. DM frames */
- unsigned short txFRMR PACKED; /* 20h: transm. FRMR frames*/
-} THdlcStats;
-
-/* ---------------------------------------------------------------------------
- * X25_HDLC_READ_COMM_ERR Command.
- */
-typedef struct HdlcCommErr
-{ /* a number of ... */
- unsigned char rxOverrun PACKED; /* 00h: Rx overrun errors */
- unsigned char rxBadCrc PACKED; /* 01h: Rx CRC errors */
- unsigned char rxAborted PACKED; /* 02h: Rx aborted frames */
- unsigned char rxDropped PACKED; /* 03h: frames lost */
- unsigned char txAborted PACKED; /* 04h: Tx aborted frames */
- unsigned char txUnderrun PACKED; /* 05h: Tx underrun errors */
- unsigned char txMissIntr PACKED; /* 06h: missed underrun ints */
- unsigned char reserved PACKED; /* 07h: reserved */
- unsigned char droppedDCD PACKED; /* 08h: times DCD dropped */
- unsigned char droppedCTS PACKED; /* 09h: times CTS dropped */
-} THdlcCommErr;
-
-/* ---------------------------------------------------------------------------
- * X25_SET_CONFIGURATION & X25_READ_CONFIGURATION Commands.
- */
-typedef struct X25Config
-{
-unsigned char baudRate PACKED; /* 00h: */
- unsigned char t1 PACKED; /* 01h: */
- unsigned char t2 PACKED; /* 02h: */
- unsigned char n2 PACKED; /* 03h: */
- unsigned short hdlcMTU PACKED; /* 04h: */
- unsigned char hdlcWindow PACKED; /* 06h: */
- unsigned char t4 PACKED; /* 07h: */
- unsigned char autoModem PACKED; /* 08h: */
- unsigned char autoHdlc PACKED; /* 09h: */
- unsigned char hdlcOptions PACKED; /* 0Ah: */
- unsigned char station PACKED; /* 0Bh: */
- unsigned char pktWindow PACKED; /* 0Ch: */
- unsigned short defPktSize PACKED; /* 0Dh: */
- unsigned short pktMTU PACKED; /* 0Fh: */
- unsigned short loPVC PACKED; /* 11h: */
- unsigned short hiPVC PACKED; /* 13h: */
- unsigned short loIncommingSVC PACKED; /* 15h: */
- unsigned short hiIncommingSVC PACKED; /* 17h: */
- unsigned short loTwoWaySVC PACKED; /* 19h: */
- unsigned short hiTwoWaySVC PACKED; /* 1Bh: */
- unsigned short loOutgoingSVC PACKED; /* 1Dh: */
- unsigned short hiOutgoingSVC PACKED; /* 1Fh: */
- unsigned short options PACKED; /* 21h: */
- unsigned char responseOpt PACKED; /* 23h: */
- unsigned short facil1 PACKED; /* 24h: */
- unsigned short facil2 PACKED; /* 26h: */
- unsigned short ccittFacil PACKED; /* 28h: */
- unsigned short otherFacil PACKED; /* 2Ah: */
- unsigned short ccittCompat PACKED; /* 2Ch: */
- unsigned char t10t20 PACKED; /* 2Eh: */
- unsigned char t11t21 PACKED; /* 2Fh: */
- unsigned char t12t22 PACKED; /* 30h: */
- unsigned char t13t23 PACKED; /* 31h: */
- unsigned char t16t26 PACKED; /* 32H: */
- unsigned char t28 PACKED; /* 33h: */
- unsigned char r10r20 PACKED; /* 34h: */
- unsigned char r12r22 PACKED; /* 35h: */
- unsigned char r13r23 PACKED; /* 36h: */
-} TX25Config;
-
-/* ---------------------------------------------------------------------------
- * X25_READ_CHANNEL_CONFIG Command.
- */
-typedef struct X25ChanAlloc /*----- Channel allocation -*/
-{
- unsigned short loPVC PACKED; /* 00h: lowest PVC number */
- unsigned short hiPVC PACKED; /* 02h: highest PVC number */
- unsigned short loIncommingSVC PACKED; /* 04h: lowest incoming SVC */
- unsigned short hiIncommingSVC PACKED; /* 06h: highest incoming SVC */
- unsigned short loTwoWaySVC PACKED; /* 08h: lowest two-way SVC */
- unsigned short hiTwoWaySVC PACKED; /* 0Ah: highest two-way SVC */
- unsigned short loOutgoingSVC PACKED; /* 0Ch: lowest outgoing SVC */
- unsigned short hiOutgoingSVC PACKED; /* 0Eh: highest outgoing SVC */
-} TX25ChanAlloc;
-
-typedef struct X25ChanCfg /*------ Channel configuration -----*/
-{
- unsigned char type PACKED; /* 00h: channel type */
- unsigned char txConf PACKED; /* 01h: Tx packet and window sizes */
- unsigned char rxConf PACKED; /* 01h: Rx packet and window sizes */
-} TX25ChanCfg;
-
-/*
- * Defines for the 'type' field.
- */
-#define X25_PVC 0x01 /* PVC */
-#define X25_SVC_IN 0x03 /* Incoming SVC */
-#define X25_SVC_TWOWAY 0x07 /* Two-way SVC */
-#define X25_SVC_OUT 0x0B /* Outgoing SVC */
-
-/*----------------------------------------------------------------------------
- * X25_READ_STATISTICS Command.
- */
-typedef struct X25Stats
-{ /* number of packets Tx/Rx'ed */
- unsigned short txRestartRqst PACKED; /* 00h: Restart Request */
- unsigned short rxRestartRqst PACKED; /* 02h: Restart Request */
- unsigned short txRestartConf PACKED; /* 04h: Restart Confirmation */
- unsigned short rxRestartConf PACKED; /* 06h: Restart Confirmation */
- unsigned short txResetRqst PACKED; /* 08h: Reset Request */
- unsigned short rxResetRqst PACKED; /* 0Ah: Reset Request */
- unsigned short txResetConf PACKED; /* 0Ch: Reset Confirmation */
- unsigned short rxResetConf PACKED; /* 0Eh: Reset Confirmation */
- unsigned short txCallRequest PACKED; /* 10h: Call Request */
- unsigned short rxCallRequest PACKED; /* 12h: Call Request */
- unsigned short txCallAccept PACKED; /* 14h: Call Accept */
- unsigned short rxCallAccept PACKED; /* 16h: Call Accept */
- unsigned short txClearRqst PACKED; /* 18h: Clear Request */
- unsigned short rxClearRqst PACKED; /* 1Ah: Clear Request */
- unsigned short txClearConf PACKED; /* 1Ch: Clear Confirmation */
- unsigned short rxClearConf PACKED; /* 1Eh: Clear Confirmation */
- unsigned short txDiagnostic PACKED; /* 20h: Diagnostic */
- unsigned short rxDiagnostic PACKED; /* 22h: Diagnostic */
- unsigned short txRegRqst PACKED; /* 24h: Registration Request */
- unsigned short rxRegRqst PACKED; /* 26h: Registration Request */
- unsigned short txRegConf PACKED; /* 28h: Registration Confirm.*/
- unsigned short rxRegConf PACKED; /* 2Ah: Registration Confirm.*/
- unsigned short txInterrupt PACKED; /* 2Ch: Interrupt */
- unsigned short rxInterrupt PACKED; /* 2Eh: Interrupt */
- unsigned short txIntrConf PACKED; /* 30h: Interrupt Confirm. */
- unsigned short rxIntrConf PACKED; /* 32h: Interrupt Confirm. */
- unsigned short txData PACKED; /* 34h: Data */
- unsigned short rxData PACKED; /* 36h: Data */
- unsigned short txRR PACKED; /* 38h: RR */
- unsigned short rxRR PACKED; /* 3Ah: RR */
- unsigned short txRNR PACKED; /* 3Ch: RNR */
- unsigned short rxRNR PACKED; /* 3Eh: RNR */
-} TX25Stats;
-
-/*----------------------------------------------------------------------------
- * X25_READ_HISTORY_TABLE Command.
- */
-typedef struct X25EventLog
-{
- unsigned char type PACKED; /* 00h: transaction type */
- unsigned short lcn PACKED; /* 01h: logical channel num */
- unsigned char packet PACKED; /* 03h: async packet type */
- unsigned char cause PACKED; /* 04h: X.25 cause field */
- unsigned char diag PACKED; /* 05h: X.25 diag field */
- TX25TimeStamp ts PACKED; /* 06h: time stamp */
-} TX25EventLog;
-
-/*
- * Defines for the 'type' field.
- */
-#define X25LOG_INCOMMING 0x00
-#define X25LOG_APPLICATION 0x01
-#define X25LOG_AUTOMATIC 0x02
-#define X25LOG_ERROR 0x04
-#define X25LOG_TIMEOUT 0x08
-#define X25LOG_RECOVERY 0x10
-
-/*
- * Defines for the 'packet' field.
- */
-#define X25LOG_CALL_RQST 0x0B
-#define X25LOG_CALL_ACCEPTED 0x0F
-#define X25LOG_CLEAR_RQST 0x13
-#define X25LOG_CLEAR_CONFRM 0x17
-#define X25LOG_RESET_RQST 0x1B
-#define X25LOG_RESET_CONFRM 0x1F
-#define X25LOG_RESTART_RQST 0xFB
-#define X25LOG_RESTART_COMFRM 0xFF
-#define X25LOG_DIAGNOSTIC 0xF1
-#define X25LOG_DTE_REG_RQST 0xF3
-#define X25LOG_DTE_REG_COMFRM 0xF7
-
-/* ---------------------------------------------------------------------------
- * X25_TRACE_CONFIGURE Command.
- */
-typedef struct X25TraceCfg
-{
- unsigned char flags PACKED; /* 00h: trace configuration flags */
- unsigned char timeout PACKED; /* 01h: timeout for trace delay mode*/
-} TX25TraceCfg;
-
-/*
- * Defines for the 'flags' field.
- */
-#define X25_TRC_ENABLE 0x01 /* bit0: '1' - trace enabled */
-#define X25_TRC_TIMESTAMP 0x02 /* bit1: '1' - time stamping enabled*/
-#define X25_TRC_DELAY 0x04 /* bit2: '1' - trace delay enabled */
-#define X25_TRC_DATA 0x08 /* bit3: '1' - trace data packets */
-#define X25_TRC_SUPERVISORY 0x10 /* bit4: '1' - trace suprvisory pkts*/
-#define X25_TRC_ASYNCHRONOUS 0x20 /* bit5: '1' - trace asynch. packets*/
-#define X25_TRC_HDLC 0x40 /* bit6: '1' - trace all packets */
-#define X25_TRC_READ 0x80 /* bit7: '1' - get current config. */
-
-/* ---------------------------------------------------------------------------
- * X25_READ_TRACE_DATA Command.
- */
-typedef struct X25Trace /*----- Trace data structure -------*/
-{
- unsigned short length PACKED; /* 00h: trace data length */
- unsigned char type PACKED; /* 02h: trace type */
- unsigned char lost_cnt PACKED; /* 03h: N of traces lost */
- TX25TimeStamp tstamp PACKED; /* 04h: mon/date/sec/min/hour */
- unsigned short millisec PACKED; /* 09h: ms time stamp */
- unsigned char data[0] PACKED; /* 0Bh: traced frame */
-} TX25Trace;
-
-/*
- * Defines for the 'type' field.
- */
-#define X25_TRC_TYPE_MASK 0x0F /* bits 0..3: trace type */
-#define X25_TRC_TYPE_RX_FRAME 0x00 /* received frame trace */
-#define X25_TRC_TYPE_TX_FRAME 0x01 /* transmitted frame */
-#define X25_TRC_TYPE_ERR_FRAME 0x02 /* error frame */
-
-#define X25_TRC_ERROR_MASK 0xF0 /* bits 4..7: error code */
-#define X25_TRCERR_RX_ABORT 0x10 /* receive abort error */
-#define X25_TRCERR_RX_BADCRC 0x20 /* receive CRC error */
-#define X25_TRCERR_RX_OVERRUN 0x30 /* receiver overrun error */
-#define X25_TRCERR_RX_TOO_LONG 0x40 /* excessive frame length error */
-#define X25_TRCERR_TX_ABORT 0x70 /* aborted frame transmittion error */
-#define X25_TRCERR_TX_UNDERRUN 0x80 /* transmit underrun error */
-
-/*****************************************************************************
- * Following definitions describe HDLC frame and X.25 packet formats.
- ****************************************************************************/
-
-typedef struct HDLCFrame /*----- DHLC Frame Format ----------*/
-{
- unsigned char addr PACKED; /* address field */
- unsigned char cntl PACKED; /* control field */
- unsigned char data[0] PACKED;
-} THDLCFrame;
-
-typedef struct X25Pkt /*----- X.25 Paket Format ----------*/
-{
- unsigned char lcn_hi PACKED; /* 4 MSB of Logical Channel Number */
- unsigned char lcn_lo PACKED; /* 8 LSB of Logical Channel Number */
- unsigned char type PACKED;
- unsigned char data[0] PACKED;
-} TX25Pkt;
-
-/*
- * Defines for the 'lcn_hi' field.
- */
-#define X25_Q_BIT_MASK 0x80 /* Data Qualifier Bit mask */
-#define X25_D_BIT_MASK 0x40 /* Delivery Confirmation Bit mask */
-#define X25_M_BITS_MASK 0x30 /* Modulo Bits mask */
-#define X25_LCN_MSB_MASK 0x0F /* LCN most significant bits mask */
-
-/*
- * Defines for the 'type' field.
- */
-#define X25PKT_DATA 0x01 /* Data packet mask */
-#define X25PKT_SUPERVISORY 0x02 /* Supervisory packet mask */
-#define X25PKT_CALL_RQST 0x0B /* Call Request/Incoming */
-#define X25PKT_CALL_ACCEPTED 0x0F /* Call Accepted/Connected */
-#define X25PKT_CLEAR_RQST 0x13 /* Clear Request/Indication */
-#define X25PKT_CLEAR_CONFRM 0x17 /* Clear Confirmation */
-#define X25PKT_RESET_RQST 0x1B /* Reset Request/Indication */
-#define X25PKT_RESET_CONFRM 0x1F /* Reset Confirmation */
-#define X25PKT_RESTART_RQST 0xFB /* Restart Request/Indication */
-#define X25PKT_RESTART_CONFRM 0xFF /* Restart Confirmation */
-#define X25PKT_INTERRUPT 0x23 /* Interrupt */
-#define X25PKT_INTERRUPT_CONFRM 0x27 /* Interrupt Confirmation */
-#define X25PKT_DIAGNOSTIC 0xF1 /* Diagnostic */
-#define X25PKT_REGISTR_RQST 0xF3 /* Registration Request */
-#define X25PKT_REGISTR_CONFRM 0xF7 /* Registration Confirmation */
-#define X25PKT_RR_MASKED 0x01 /* Receive Ready packet after masking */
-#define X25PKT_RNR_MASKED 0x05 /* Receive Not Ready after masking */
-
-
-typedef struct {
- TX25Cmd cmd PACKED;
- char data[X25_MAX_DATA] PACKED;
-} mbox_cmd_t;
-
-
-typedef struct {
- unsigned char qdm PACKED; /* Q/D/M bits */
- unsigned char cause PACKED; /* cause field */
- unsigned char diagn PACKED; /* diagnostics */
- unsigned char pktType PACKED;
- unsigned short length PACKED;
- unsigned char result PACKED;
- unsigned short lcn PACKED;
- char reserved[7] PACKED;
-}x25api_hdr_t;
-
-
-typedef struct {
- x25api_hdr_t hdr PACKED;
- char data[X25_MAX_DATA] PACKED;
-}x25api_t;
-
-
-/*
- * XPIPEMON Definitions
- */
-
-/* valid ip_protocol for UDP management */
-#define UDPMGMT_UDP_PROTOCOL 0x11
-#define UDPMGMT_XPIPE_SIGNATURE "XLINK8ND"
-#define UDPMGMT_DRVRSTATS_SIGNATURE "DRVSTATS"
-
-/* values for request/reply byte */
-#define UDPMGMT_REQUEST 0x01
-#define UDPMGMT_REPLY 0x02
-#define UDP_OFFSET 12
-
-
-typedef struct {
- unsigned char opp_flag PACKED; /* the opp flag */
- unsigned char command PACKED; /* command code */
- unsigned short length PACKED; /* transfer data length */
- unsigned char result PACKED; /* return code */
- unsigned char pf PACKED; /* P/F bit */
- unsigned short lcn PACKED; /* logical channel */
- unsigned char qdm PACKED; /* Q/D/M bits */
- unsigned char cause PACKED; /* cause field */
- unsigned char diagn PACKED; /* diagnostics */
- unsigned char pktType PACKED; /* packet type */
- unsigned char resrv[4] PACKED; /* reserved */
-} cblock_t;
-
-typedef struct {
- ip_pkt_t ip_pkt PACKED;
- udp_pkt_t udp_pkt PACKED;
- wp_mgmt_t wp_mgmt PACKED;
- cblock_t cblock PACKED;
- unsigned char data[4080] PACKED;
-} x25_udp_pkt_t;
-
-
-typedef struct read_hdlc_stat {
- unsigned short inf_frames_rx_ok PACKED;
- unsigned short inf_frames_rx_out_of_seq PACKED;
- unsigned short inf_frames_rx_no_data PACKED;
- unsigned short inf_frames_rx_dropped PACKED;
- unsigned short inf_frames_rx_data_too_long PACKED;
- unsigned short inf_frames_rx_invalid_addr PACKED;
- unsigned short inf_frames_tx_ok PACKED;
- unsigned short inf_frames_tx_retransmit PACKED;
- unsigned short T1_timeouts PACKED;
- unsigned short SABM_frames_rx PACKED;
- unsigned short DISC_frames_rx PACKED;
- unsigned short DM_frames_rx PACKED;
- unsigned short FRMR_frames_rx PACKED;
- unsigned short SABM_frames_tx PACKED;
- unsigned short DISC_frames_tx PACKED;
- unsigned short DM_frames_tx PACKED;
- unsigned short FRMR_frames_tx PACKED;
-} read_hdlc_stat_t;
-
-typedef struct read_comms_err_stats{
- unsigned char overrun_err_rx PACKED;
- unsigned char CRC_err PACKED;
- unsigned char abort_frames_rx PACKED;
- unsigned char frames_dropped_buf_full PACKED;
- unsigned char abort_frames_tx PACKED;
- unsigned char transmit_underruns PACKED;
- unsigned char missed_tx_underruns_intr PACKED;
- unsigned char reserved PACKED;
- unsigned char DCD_drop PACKED;
- unsigned char CTS_drop PACKED;
-} read_comms_err_stats_t;
-
-typedef struct trace_data {
- unsigned short length PACKED;
- unsigned char type PACKED;
- unsigned char trace_dropped PACKED;
- unsigned char reserved[5] PACKED;
- unsigned short timestamp PACKED;
- unsigned char data PACKED;
-} trace_data_t;
-
-enum {UDP_XPIPE_TYPE};
-
-#define XPIPE_ENABLE_TRACING 0x14
-#define XPIPE_DISABLE_TRACING 0x14
-#define XPIPE_GET_TRACE_INFO 0x16
-#define XPIPE_FT1_READ_STATUS 0x74
-#define XPIPE_DRIVER_STAT_IFSEND 0x75
-#define XPIPE_DRIVER_STAT_INTR 0x76
-#define XPIPE_DRIVER_STAT_GEN 0x77
-#define XPIPE_FLUSH_DRIVER_STATS 0x78
-#define XPIPE_ROUTER_UP_TIME 0x79
-#define XPIPE_SET_FT1_MODE 0x81
-#define XPIPE_FT1_STATUS_CTRL 0x80
-
-
-/* error messages */
-#define NO_BUFFS_OR_CLOSED_WIN 0x33
-#define DATA_LENGTH_TOO_BIG 0x32
-#define NO_DATA_AVAILABLE 0x33
-#define Z80_TIMEOUT_ERROR 0x0a
-#define NO_BUFFS 0x08
-
-
-/* Trace options */
-#define TRACE_DEFAULT 0x03
-#define TRACE_SUPERVISOR_FRMS 0x10
-#define TRACE_ASYNC_FRMS 0x20
-#define TRACE_ALL_HDLC_FRMS 0x40
-#define TRACE_DATA_FRMS 0x08
-
-
-#endif /* _SDLA_X25_H */
diff --git a/include/linux/sdladrv.h b/include/linux/sdladrv.h
deleted file mode 100644
index c85e103d5e7..00000000000
--- a/include/linux/sdladrv.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*****************************************************************************
-* sdladrv.h SDLA Support Module. Kernel API Definitions.
-*
-* Author: Gideon Hack
-*
-* Copyright: (c) 1995-2000 Sangoma Technologies 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.
-* ============================================================================
-* Jun 02, 1999 Gideon Hack Added support for the S514 PCI adapter.
-* Dec 11, 1996 Gene Kozin Complete overhaul.
-* Oct 17, 1996 Gene Kozin Minor bug fixes.
-* Jun 12, 1996 Gene Kozin Added support for S503 card.
-* Dec 06, 1995 Gene Kozin Initial version.
-*****************************************************************************/
-#ifndef _SDLADRV_H
-#define _SDLADRV_H
-
-
-#define SDLA_MAXIORANGE 4 /* maximum I/O port range */
-#define SDLA_WINDOWSIZE 0x2000 /* default dual-port memory window size */
-/****** Data Structures *****************************************************/
-
-/*----------------------------------------------------------------------------
- * Adapter hardware configuration. Pointer to this structure is passed to all
- * APIs.
- */
-typedef struct sdlahw
-{
- unsigned type; /* adapter type */
- unsigned fwid; /* firmware ID */
- unsigned port; /* adapter I/O port base */
- int irq; /* interrupt request level */
- char S514_cpu_no[1]; /* PCI CPU Number */
- unsigned char S514_slot_no; /* PCI Slot Number */
- char auto_pci_cfg; /* Autodetect PCI Slot */
- struct pci_dev *pci_dev; /* PCI device */
- void * dpmbase; /* dual-port memory base */
- unsigned dpmsize; /* dual-port memory size */
- unsigned pclk; /* CPU clock rate, kHz */
- unsigned long memory; /* memory size */
- unsigned long vector; /* local offset of the DPM window */
- unsigned io_range; /* I/O port range */
- unsigned char regs[SDLA_MAXIORANGE]; /* was written to registers */
- unsigned reserved[5];
-} sdlahw_t;
-
-/****** Function Prototypes *************************************************/
-
-extern int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len);
-extern int sdla_down (sdlahw_t* hw);
-extern void S514_intack (sdlahw_t* hw, u32 int_status);
-extern void read_S514_int_stat (sdlahw_t* hw, u32* int_status);
-extern int sdla_mapmem (sdlahw_t* hw, unsigned long addr);
-extern int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf,
- unsigned len);
-extern int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf,
- unsigned len);
-extern int sdla_exec (void* opflag);
-
-extern unsigned wanpipe_hw_probe(void);
-
-#endif /* _SDLADRV_H */
diff --git a/include/linux/sdlapci.h b/include/linux/sdlapci.h
deleted file mode 100644
index 6f7c904f188..00000000000
--- a/include/linux/sdlapci.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*****************************************************************************
-* sdlapci.h WANPIPE(tm) Multiprotocol WAN Link Driver.
-* Definitions for the SDLA PCI adapter.
-*
-* Author: Gideon Hack <ghack@sangoma.com>
-*
-* Copyright: (c) 1999-2000 Sangoma Technologies 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.
-* ============================================================================
-* Jun 02, 1999 Gideon Hack Initial version.
-*****************************************************************************/
-#ifndef _SDLAPCI_H
-#define _SDLAPCI_H
-
-/****** Defines *************************************************************/
-
-/* Definitions for identifying and finding S514 PCI adapters */
-#define V3_VENDOR_ID 0x11B0 /* V3 vendor ID number */
-#define V3_DEVICE_ID 0x0002 /* V3 device ID number */
-#define SANGOMA_SUBSYS_VENDOR 0x4753 /* ID for Sangoma */
-#define PCI_DEV_SLOT_MASK 0x1F /* mask for slot numbering */
-#define PCI_IRQ_NOT_ALLOCATED 0xFF /* interrupt line for no IRQ */
-
-/* Local PCI register offsets */
-#define PCI_VENDOR_ID_WORD 0x00 /* vendor ID */
-#define PCI_IO_BASE_DWORD 0x10 /* IO base */
-#define PCI_MEM_BASE0_DWORD 0x14 /* memory base - apperture 0 */
-#define PCI_MEM_BASE1_DWORD 0x18 /* memory base - apperture 1 */
-#define PCI_SUBSYS_VENDOR_WORD 0x2C /* subsystem vendor ID */
-#define PCI_INT_LINE_BYTE 0x3C /* interrupt line */
-#define PCI_INT_PIN_BYTE 0x3D /* interrupt pin */
-#define PCI_MAP0_DWORD 0x40 /* PCI to local bus address 0 */
-#define PCI_MAP1_DWORD 0x44 /* PCI to local bus address 1 */
-#define PCI_INT_STATUS 0x48 /* interrupt status */
-#define PCI_INT_CONFIG 0x4C /* interrupt configuration */
-
-/* Local PCI register usage */
-#define PCI_MEMORY_ENABLE 0x00000003 /* enable PCI memory */
-#define PCI_CPU_A_MEM_DISABLE 0x00000002 /* disable CPU A memory */
-#define PCI_CPU_B_MEM_DISABLE 0x00100002 /* disable CPU B memory */
-#define PCI_ENABLE_IRQ_CPU_A 0x005A0004 /* enable IRQ for CPU A */
-#define PCI_ENABLE_IRQ_CPU_B 0x005A0008 /* enable IRQ for CPU B */
-#define PCI_DISABLE_IRQ_CPU_A 0x00000004 /* disable IRQ for CPU A */
-#define PCI_DISABLE_IRQ_CPU_B 0x00000008 /* disable IRQ for CPU B */
-
-/* Setting for the Interrupt Status register */
-#define IRQ_CPU_A 0x04 /* IRQ for CPU A */
-#define IRQ_CPU_B 0x08 /* IRQ for CPU B */
-
-/* The maximum size of the S514 memory */
-#define MAX_SIZEOF_S514_MEMORY (256 * 1024)
-
-/* S514 control register offsets within the memory address space */
-#define S514_CTRL_REG_BYTE 0x80000
-
-/* S514 adapter control bytes */
-#define S514_CPU_HALT 0x00
-#define S514_CPU_START 0x01
-
-/* The maximum number of S514 adapters supported */
-#define MAX_S514_CARDS 20
-
-#define PCI_CARD_TYPE 0x2E
-#define S514_DUAL_CPU 0x12
-#define S514_SINGLE_CPU 0x11
-
-#endif /* _SDLAPCI_H */
-
diff --git a/include/linux/sdlasfm.h b/include/linux/sdlasfm.h
deleted file mode 100644
index 94aaa8ada66..00000000000
--- a/include/linux/sdlasfm.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*****************************************************************************
-* sdlasfm.h WANPIPE(tm) Multiprotocol WAN Link Driver.
-* Definitions for the SDLA Firmware Module (SFM).
-*
-* Author: Gideon Hack
-*
-* Copyright: (c) 1995-1999 Sangoma Technologies 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.
-* ============================================================================
-* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
-* Dec 11, 1996 Gene Kozin Cosmetic changes
-* Apr 16, 1996 Gene Kozin Changed adapter & firmware IDs. Version 2
-* Dec 15, 1995 Gene Kozin Structures chaned
-* Nov 09, 1995 Gene Kozin Initial version.
-*****************************************************************************/
-#ifndef _SDLASFM_H
-#define _SDLASFM_H
-
-/****** Defines *************************************************************/
-
-#define SFM_VERSION 2
-#define SFM_SIGNATURE "SFM - Sangoma SDLA Firmware Module"
-
-/* min/max */
-#define SFM_IMAGE_SIZE 0x8000 /* max size of SDLA code image file */
-#define SFM_DESCR_LEN 256 /* max length of description string */
-#define SFM_MAX_SDLA 16 /* max number of compatible adapters */
-
-/* Adapter types */
-#define SDLA_S502A 5020
-#define SDLA_S502E 5021
-#define SDLA_S503 5030
-#define SDLA_S508 5080
-#define SDLA_S507 5070
-#define SDLA_S509 5090
-#define SDLA_S514 5140
-
-/* S514 PCI adapter CPU numbers */
-#define S514_CPU_A 'A'
-#define S514_CPU_B 'B'
-
-
-/* Firmware identification numbers:
- * 0 .. 999 Test & Diagnostics
- * 1000 .. 1999 Streaming HDLC
- * 2000 .. 2999 Bisync
- * 3000 .. 3999 SDLC
- * 4000 .. 4999 HDLC
- * 5000 .. 5999 X.25
- * 6000 .. 6999 Frame Relay
- * 7000 .. 7999 PPP
- * 8000 .. 8999 Cisco HDLC
- */
-#define SFID_CALIB502 200
-#define SFID_STRM502 1200
-#define SFID_STRM508 1800
-#define SFID_BSC502 2200
-#define SFID_SDLC502 3200
-#define SFID_HDLC502 4200
-#define SFID_HDLC508 4800
-#define SFID_X25_502 5200
-#define SFID_X25_508 5800
-#define SFID_FR502 6200
-#define SFID_FR508 6800
-#define SFID_PPP502 7200
-#define SFID_PPP508 7800
-#define SFID_PPP514 7140
-#define SFID_CHDLC508 8800
-#define SFID_CHDLC514 8140
-
-/****** Data Types **********************************************************/
-
-typedef struct sfm_info /* firmware module information */
-{
- unsigned short codeid; /* firmware ID */
- unsigned short version; /* firmaware version number */
- unsigned short adapter[SFM_MAX_SDLA]; /* compatible adapter types */
- unsigned long memsize; /* minimum memory size */
- unsigned short reserved[2]; /* reserved */
- unsigned short startoffs; /* entry point offset */
- unsigned short winoffs; /* dual-port memory window offset */
- unsigned short codeoffs; /* code load offset */
- unsigned short codesize; /* code size */
- unsigned short dataoffs; /* configuration data load offset */
- unsigned short datasize; /* configuration data size */
-} sfm_info_t;
-
-typedef struct sfm /* SDLA firmware file structire */
-{
- char signature[80]; /* SFM file signature */
- unsigned short version; /* file format version */
- unsigned short checksum; /* info + image */
- unsigned short reserved[6]; /* reserved */
- char descr[SFM_DESCR_LEN]; /* description string */
- sfm_info_t info; /* firmware module info */
- unsigned char image[1]; /* code image (variable size) */
-} sfm_t;
-
-#endif /* _SDLASFM_H */
-
diff --git a/include/linux/security.h b/include/linux/security.h
index aaa0a5cdbf7..1bab48f6aea 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -869,11 +869,6 @@ struct swap_info_struct;
* @ipcp contains the kernel IPC permission structure
* @flag contains the desired (requested) permission set
* Return 0 if permission is granted.
- * @ipc_getsecurity:
- * Copy the security label associated with the ipc object into
- * @buffer. @buffer may be NULL to request the size of the buffer
- * required. @size indicates the size of @buffer in bytes. Return
- * number of bytes used/required on success.
*
* Security hooks for individual messages held in System V IPC message queues
* @msg_msg_alloc_security:
@@ -1223,7 +1218,6 @@ struct security_operations {
void (*task_to_inode)(struct task_struct *p, struct inode *inode);
int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag);
- int (*ipc_getsecurity)(struct kern_ipc_perm *ipcp, void *buffer, size_t size);
int (*msg_msg_alloc_security) (struct msg_msg * msg);
void (*msg_msg_free_security) (struct msg_msg * msg);
@@ -1887,11 +1881,6 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
return security_ops->ipc_permission (ipcp, flag);
}
-static inline int security_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
-{
- return security_ops->ipc_getsecurity(ipcp, buffer, size);
-}
-
static inline int security_msg_msg_alloc (struct msg_msg * msg)
{
return security_ops->msg_msg_alloc_security (msg);
@@ -2532,11 +2521,6 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
return 0;
}
-static inline int security_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
-{
- return -EOPNOTSUPP;
-}
-
static inline int security_msg_msg_alloc (struct msg_msg * msg)
{
return 0;
diff --git a/include/linux/selinux.h b/include/linux/selinux.h
new file mode 100644
index 00000000000..4047bcde448
--- /dev/null
+++ b/include/linux/selinux.h
@@ -0,0 +1,177 @@
+/*
+ * SELinux services exported to the rest of the kernel.
+ *
+ * Author: James Morris <jmorris@redhat.com>
+ *
+ * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ * Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ * Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+#ifndef _LINUX_SELINUX_H
+#define _LINUX_SELINUX_H
+
+struct selinux_audit_rule;
+struct audit_context;
+struct inode;
+struct kern_ipc_perm;
+
+#ifdef CONFIG_SECURITY_SELINUX
+
+/**
+ * selinux_audit_rule_init - alloc/init an selinux audit rule structure.
+ * @field: the field this rule refers to
+ * @op: the operater the rule uses
+ * @rulestr: the text "target" of the rule
+ * @rule: pointer to the new rule structure returned via this
+ *
+ * Returns 0 if successful, -errno if not. On success, the rule structure
+ * will be allocated internally. The caller must free this structure with
+ * selinux_audit_rule_free() after use.
+ */
+int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
+ struct selinux_audit_rule **rule);
+
+/**
+ * selinux_audit_rule_free - free an selinux audit rule structure.
+ * @rule: pointer to the audit rule to be freed
+ *
+ * This will free all memory associated with the given rule.
+ * If @rule is NULL, no operation is performed.
+ */
+void selinux_audit_rule_free(struct selinux_audit_rule *rule);
+
+/**
+ * selinux_audit_rule_match - determine if a context ID matches a rule.
+ * @ctxid: the context ID to check
+ * @field: the field this rule refers to
+ * @op: the operater the rule uses
+ * @rule: pointer to the audit rule to check against
+ * @actx: the audit context (can be NULL) associated with the check
+ *
+ * Returns 1 if the context id matches the rule, 0 if it does not, and
+ * -errno on failure.
+ */
+int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
+ struct selinux_audit_rule *rule,
+ struct audit_context *actx);
+
+/**
+ * selinux_audit_set_callback - set the callback for policy reloads.
+ * @callback: the function to call when the policy is reloaded
+ *
+ * This sets the function callback function that will update the rules
+ * upon policy reloads. This callback should rebuild all existing rules
+ * using selinux_audit_rule_init().
+ */
+void selinux_audit_set_callback(int (*callback)(void));
+
+/**
+ * selinux_task_ctxid - determine a context ID for a process.
+ * @tsk: the task object
+ * @ctxid: ID value returned via this
+ *
+ * On return, ctxid will contain an ID for the context. This value
+ * should only be used opaquely.
+ */
+void selinux_task_ctxid(struct task_struct *tsk, u32 *ctxid);
+
+/**
+ * selinux_ctxid_to_string - map a security context ID to a string
+ * @ctxid: security context ID to be converted.
+ * @ctx: address of context string to be returned
+ * @ctxlen: length of returned context string.
+ *
+ * Returns 0 if successful, -errno if not. On success, the context
+ * string will be allocated internally, and the caller must call
+ * kfree() on it after use.
+ */
+int selinux_ctxid_to_string(u32 ctxid, char **ctx, u32 *ctxlen);
+
+/**
+ * selinux_get_inode_sid - get the inode's security context ID
+ * @inode: inode structure to get the sid from.
+ * @sid: pointer to security context ID to be filled in.
+ *
+ * Returns nothing
+ */
+void selinux_get_inode_sid(const struct inode *inode, u32 *sid);
+
+/**
+ * selinux_get_ipc_sid - get the ipc security context ID
+ * @ipcp: ipc structure to get the sid from.
+ * @sid: pointer to security context ID to be filled in.
+ *
+ * Returns nothing
+ */
+void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid);
+
+/**
+ * selinux_get_task_sid - return the SID of task
+ * @tsk: the task whose SID will be returned
+ * @sid: pointer to security context ID to be filled in.
+ *
+ * Returns nothing
+ */
+void selinux_get_task_sid(struct task_struct *tsk, u32 *sid);
+
+
+#else
+
+static inline int selinux_audit_rule_init(u32 field, u32 op,
+ char *rulestr,
+ struct selinux_audit_rule **rule)
+{
+ return -ENOTSUPP;
+}
+
+static inline void selinux_audit_rule_free(struct selinux_audit_rule *rule)
+{
+ return;
+}
+
+static inline int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
+ struct selinux_audit_rule *rule,
+ struct audit_context *actx)
+{
+ return 0;
+}
+
+static inline void selinux_audit_set_callback(int (*callback)(void))
+{
+ return;
+}
+
+static inline void selinux_task_ctxid(struct task_struct *tsk, u32 *ctxid)
+{
+ *ctxid = 0;
+}
+
+static inline int selinux_ctxid_to_string(u32 ctxid, char **ctx, u32 *ctxlen)
+{
+ *ctx = NULL;
+ *ctxlen = 0;
+ return 0;
+}
+
+static inline void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
+{
+ *sid = 0;
+}
+
+static inline void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
+{
+ *sid = 0;
+}
+
+static inline void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
+{
+ *sid = 0;
+}
+
+#endif /* CONFIG_SECURITY_SELINUX */
+
+#endif /* _LINUX_SELINUX_H */
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index fca9b0fb5b4..5a095572881 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -73,7 +73,7 @@ static inline int write_tryseqlock(seqlock_t *sl)
}
/* Start of read calculation -- fetch last complete writer token */
-static inline unsigned read_seqbegin(const seqlock_t *sl)
+static __always_inline unsigned read_seqbegin(const seqlock_t *sl)
{
unsigned ret = sl->sequence;
smp_rmb();
@@ -88,7 +88,7 @@ static inline unsigned read_seqbegin(const seqlock_t *sl)
*
* Using xor saves one conditional branch.
*/
-static inline int read_seqretry(const seqlock_t *sl, unsigned iv)
+static __always_inline int read_seqretry(const seqlock_t *sl, unsigned iv)
{
smp_rmb();
return (iv & 1) | (sl->sequence ^ iv);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index c32e60e79de..bd14858121e 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -254,6 +254,7 @@ struct uart_port {
#define UPF_CONS_FLOW ((__force upf_t) (1 << 23))
#define UPF_SHARE_IRQ ((__force upf_t) (1 << 24))
#define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28))
+#define UPF_DEAD ((__force upf_t) (1 << 30))
#define UPF_IOREMAP ((__force upf_t) (1 << 31))
#define UPF_CHANGE_MASK ((__force upf_t) (0x17fff))
diff --git a/include/linux/serio.h b/include/linux/serio.h
index 690aabca8ed..6348e833089 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/mod_devicetable.h>
@@ -42,7 +43,7 @@ struct serio {
struct serio *parent, *child;
struct serio_driver *drv; /* accessed from interrupt, must be protected by serio->lock and serio->sem */
- struct semaphore drv_sem; /* protects serio->drv so attributes can pin driver */
+ struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */
struct device dev;
unsigned int registered; /* port has been fully registered with driver core */
@@ -151,17 +152,17 @@ static inline void serio_continue_rx(struct serio *serio)
*/
static inline int serio_pin_driver(struct serio *serio)
{
- return down_interruptible(&serio->drv_sem);
+ return mutex_lock_interruptible(&serio->drv_mutex);
}
static inline void serio_pin_driver_uninterruptible(struct serio *serio)
{
- down(&serio->drv_sem);
+ mutex_lock(&serio->drv_mutex);
}
static inline void serio_unpin_driver(struct serio *serio)
{
- up(&serio->drv_sem);
+ mutex_unlock(&serio->drv_mutex);
}
diff --git a/include/linux/signal.h b/include/linux/signal.h
index b7d093520bb..70739f51a09 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -14,10 +14,12 @@
*
* SA_INTERRUPT is also used by the irq handling routines.
* SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ * SA_PROBEIRQ is set by callers when they expect sharing mismatches to occur
*/
-#define SA_PROBE SA_ONESHOT
#define SA_SAMPLE_RANDOM SA_RESTART
#define SA_SHIRQ 0x04000000
+#define SA_PROBEIRQ 0x08000000
+
/*
* As above, these correspond to the IORESOURCE_IRQ_* defines in
* linux/ioport.h to select the interrupt line behaviour. When
@@ -249,6 +251,8 @@ static inline void init_sigpending(struct sigpending *sig)
INIT_LIST_HEAD(&sig->list);
}
+extern void flush_sigqueue(struct sigpending *queue);
+
/* Test if 'sig' is valid signal. Use this instead of testing _NSIG directly */
static inline int valid_signal(unsigned long sig)
{
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 613b9513f8b..f8f234708b9 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -344,6 +344,13 @@ extern void skb_over_panic(struct sk_buff *skb, int len,
void *here);
extern void skb_under_panic(struct sk_buff *skb, int len,
void *here);
+extern void skb_truesize_bug(struct sk_buff *skb);
+
+static inline void skb_truesize_check(struct sk_buff *skb)
+{
+ if (unlikely((int)skb->truesize < sizeof(struct sk_buff) + skb->len))
+ skb_truesize_bug(skb);
+}
extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
int getfrag(void *from, char *to, int offset,
@@ -941,6 +948,25 @@ static inline void skb_reserve(struct sk_buff *skb, int len)
#define NET_IP_ALIGN 2
#endif
+/*
+ * The networking layer reserves some headroom in skb data (via
+ * dev_alloc_skb). This is used to avoid having to reallocate skb data when
+ * the header has to grow. In the default case, if the header has to grow
+ * 16 bytes or less we avoid the reallocation.
+ *
+ * Unfortunately this headroom changes the DMA alignment of the resulting
+ * network packet. As for NET_IP_ALIGN, this unaligned DMA is expensive
+ * on some architectures. An architecture can override this value,
+ * perhaps setting it to a cacheline in size (since that will maintain
+ * cacheline alignment of the DMA). It must be a power of 2.
+ *
+ * Various parts of the networking layer expect at least 16 bytes of
+ * headroom, you should not reduce this.
+ */
+#ifndef NET_SKB_PAD
+#define NET_SKB_PAD 16
+#endif
+
extern int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc);
static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
@@ -1030,9 +1056,9 @@ static inline void __skb_queue_purge(struct sk_buff_head *list)
static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
gfp_t gfp_mask)
{
- struct sk_buff *skb = alloc_skb(length + 16, gfp_mask);
+ struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
if (likely(skb))
- skb_reserve(skb, 16);
+ skb_reserve(skb, NET_SKB_PAD);
return skb;
}
#else
@@ -1070,13 +1096,15 @@ static inline struct sk_buff *dev_alloc_skb(unsigned int length)
*/
static inline int skb_cow(struct sk_buff *skb, unsigned int headroom)
{
- int delta = (headroom > 16 ? headroom : 16) - skb_headroom(skb);
+ int delta = (headroom > NET_SKB_PAD ? headroom : NET_SKB_PAD) -
+ skb_headroom(skb);
if (delta < 0)
delta = 0;
if (delta || skb_cloned(skb))
- return pskb_expand_head(skb, (delta + 15) & ~15, 0, GFP_ATOMIC);
+ return pskb_expand_head(skb, (delta + (NET_SKB_PAD-1)) &
+ ~(NET_SKB_PAD-1), 0, GFP_ATOMIC);
return 0;
}
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 15e1d9736b1..2d985d59c7b 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -150,6 +150,7 @@ static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
extern void kfree(const void *);
extern unsigned int ksize(const void *);
+extern int slab_is_available(void);
#ifdef CONFIG_NUMA
extern void *kmem_cache_alloc_node(kmem_cache_t *, gfp_t flags, int node);
@@ -210,7 +211,6 @@ extern kmem_cache_t *names_cachep;
extern kmem_cache_t *files_cachep;
extern kmem_cache_t *filp_cachep;
extern kmem_cache_t *fs_cachep;
-extern kmem_cache_t *signal_cachep;
extern kmem_cache_t *sighand_cachep;
extern kmem_cache_t *bio_cachep;
diff --git a/include/linux/sound.h b/include/linux/sound.h
index 72b9af4c3fd..f63d8342ffa 100644
--- a/include/linux/sound.h
+++ b/include/linux/sound.h
@@ -30,12 +30,12 @@
*/
struct device;
-extern int register_sound_special(struct file_operations *fops, int unit);
-extern int register_sound_special_device(struct file_operations *fops, int unit, struct device *dev);
-extern int register_sound_mixer(struct file_operations *fops, int dev);
-extern int register_sound_midi(struct file_operations *fops, int dev);
-extern int register_sound_dsp(struct file_operations *fops, int dev);
-extern int register_sound_synth(struct file_operations *fops, int dev);
+extern int register_sound_special(const struct file_operations *fops, int unit);
+extern int register_sound_special_device(const struct file_operations *fops, int unit, struct device *dev);
+extern int register_sound_mixer(const struct file_operations *fops, int dev);
+extern int register_sound_midi(const struct file_operations *fops, int dev);
+extern int register_sound_dsp(const struct file_operations *fops, int dev);
+extern int register_sound_synth(const struct file_operations *fops, int dev);
extern void unregister_sound_special(int unit);
extern void unregister_sound_mixer(int unit);
diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h
index 72261e0f2ac..adb3dafd33e 100644
--- a/include/linux/spi/ads7846.h
+++ b/include/linux/spi/ads7846.h
@@ -14,5 +14,12 @@ struct ads7846_platform_data {
u16 x_min, x_max;
u16 y_min, y_max;
u16 pressure_min, pressure_max;
+
+ u16 debounce_max; /* max number of additional readings
+ * per sample */
+ u16 debounce_tol; /* tolerance used for filtering */
+ u16 debounce_rep; /* additional consecutive good readings
+ * required after the first two */
+ int (*get_pendown_state)(void);
};
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index b05f1463a26..e928c0dcc29 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -31,18 +31,23 @@ extern struct bus_type spi_bus_type;
* @master: SPI controller used with the device.
* @max_speed_hz: Maximum clock rate to be used with this chip
* (on this board); may be changed by the device's driver.
+ * The spi_transfer.speed_hz can override this for each transfer.
* @chip-select: Chipselect, distinguishing chips handled by "master".
* @mode: The spi mode defines how data is clocked out and in.
* This may be changed by the device's driver.
+ * The "active low" default for chipselect mode can be overridden,
+ * as can the "MSB first" default for each word in a transfer.
* @bits_per_word: Data transfers involve one or more words; word sizes
- * like eight or 12 bits are common. In-memory wordsizes are
+ * like eight or 12 bits are common. In-memory wordsizes are
* powers of two bytes (e.g. 20 bit samples use 32 bits).
- * This may be changed by the device's driver.
+ * This may be changed by the device's driver, or left at the
+ * default (0) indicating protocol words are eight bit bytes.
+ * The spi_transfer.bits_per_word can override this for each transfer.
* @irq: Negative, or the number passed to request_irq() to receive
- * interrupts from this device.
+ * interrupts from this device.
* @controller_state: Controller's runtime state
* @controller_data: Board-specific definitions for controller, such as
- * FIFO initialization parameters; from board_info.controller_data
+ * FIFO initialization parameters; from board_info.controller_data
*
* An spi_device is used to interchange data between an SPI slave
* (usually a discrete chip) and CPU memory.
@@ -65,6 +70,7 @@ struct spi_device {
#define SPI_MODE_2 (SPI_CPOL|0)
#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 */
u8 bits_per_word;
int irq;
void *controller_state;
@@ -73,7 +79,6 @@ struct spi_device {
// likely need more hooks for more protocol options affecting how
// the controller talks to each chip, like:
- // - bit order (default is wordwise msb-first)
// - memory packing (12 bit samples into low bits, others zeroed)
// - priority
// - drop chipselect after each word
@@ -143,13 +148,13 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* struct spi_master - interface to SPI master controller
* @cdev: class interface to this driver
* @bus_num: board-specific (and often SOC-specific) identifier for a
- * given SPI controller.
+ * given SPI controller.
* @num_chipselect: chipselects are used to distinguish individual
- * SPI slaves, and are numbered from zero to num_chipselects.
- * each slave has a chipselect signal, but it's common that not
- * every chipselect is connected to a slave.
+ * SPI slaves, and are numbered from zero to num_chipselects.
+ * each slave has a chipselect signal, but it's common that not
+ * every chipselect is connected to a slave.
* @setup: updates the device mode and clocking records used by a
- * device's SPI controller; protocol code may call this.
+ * device's SPI controller; protocol code may call this.
* @transfer: adds a message to the controller's transfer queue.
* @cleanup: frees controller-specific state
*
@@ -167,13 +172,13 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
struct spi_master {
struct class_device cdev;
- /* other than zero (== assign one dynamically), bus_num is fully
+ /* other than negative (== assign one dynamically), bus_num is fully
* board-specific. usually that simplifies to being SOC-specific.
- * example: one SOC has three SPI controllers, numbered 1..3,
+ * example: one SOC has three SPI controllers, numbered 0..2,
* and one board's schematics might show it using SPI-2. software
* would normally use bus_num=2 for that controller.
*/
- u16 bus_num;
+ s16 bus_num;
/* chipselects will be integral to many controllers; some others
* might use board-specific GPIOs.
@@ -268,10 +273,14 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
* @tx_dma: DMA address of tx_buf, if spi_message.is_dma_mapped
* @rx_dma: DMA address of rx_buf, if spi_message.is_dma_mapped
* @len: size of rx and tx buffers (in bytes)
+ * @speed_hz: Select a speed other then the device default for this
+ * transfer. If 0 the default (from spi_device) is used.
+ * @bits_per_word: select a bits_per_word other then the device default
+ * for this transfer. If 0 the default (from spi_device) is used.
* @cs_change: affects chipselect after this transfer completes
* @delay_usecs: microseconds to delay after this transfer before
- * (optionally) changing the chipselect status, then starting
- * the next transfer or completing this spi_message.
+ * (optionally) changing the chipselect status, then starting
+ * the next transfer or completing this spi_message.
* @transfer_list: transfers are sequenced through spi_message.transfers
*
* SPI transfers always write the same number of bytes as they read.
@@ -322,7 +331,9 @@ struct spi_transfer {
dma_addr_t rx_dma;
unsigned cs_change:1;
+ u8 bits_per_word;
u16 delay_usecs;
+ u32 speed_hz;
struct list_head transfer_list;
};
@@ -356,7 +367,7 @@ struct spi_transfer {
* and its transfers, ignore them until its completion callback.
*/
struct spi_message {
- struct list_head transfers;
+ struct list_head transfers;
struct spi_device *spi;
@@ -374,7 +385,7 @@ struct spi_message {
*/
/* completion is reported through a callback */
- void (*complete)(void *context);
+ void (*complete)(void *context);
void *context;
unsigned actual_length;
int status;
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
index c961fe9bf3e..16ce178f54d 100644
--- a/include/linux/spi/spi_bitbang.h
+++ b/include/linux/spi/spi_bitbang.h
@@ -30,6 +30,12 @@ struct spi_bitbang {
struct spi_master *master;
+ /* setup_transfer() changes clock and/or wordsize to match settings
+ * for this transfer; zeroes restore defaults from spi_device.
+ */
+ int (*setup_transfer)(struct spi_device *spi,
+ struct spi_transfer *t);
+
void (*chipselect)(struct spi_device *spi, int is_on);
#define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */
#define BITBANG_CS_INACTIVE 0
@@ -51,6 +57,8 @@ struct spi_bitbang {
extern int spi_bitbang_setup(struct spi_device *spi);
extern void spi_bitbang_cleanup(const struct spi_device *spi);
extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m);
+extern int spi_bitbang_setup_transfer(struct spi_device *spi,
+ struct spi_transfer *t);
/* start or stop queue processing */
extern int spi_bitbang_start(struct spi_bitbang *spi);
diff --git a/include/linux/string.h b/include/linux/string.h
index dee221429ad..c61306da8c5 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -13,11 +13,6 @@
extern "C" {
#endif
-extern char * strpbrk(const char *,const char *);
-extern char * strsep(char **,const char *);
-extern __kernel_size_t strspn(const char *,const char *);
-extern __kernel_size_t strcspn(const char *,const char *);
-
extern char *strndup_user(const char __user *, long);
/*
@@ -70,6 +65,18 @@ extern __kernel_size_t strlen(const char *);
#ifndef __HAVE_ARCH_STRNLEN
extern __kernel_size_t strnlen(const char *,__kernel_size_t);
#endif
+#ifndef __HAVE_ARCH_STRPBRK
+extern char * strpbrk(const char *,const char *);
+#endif
+#ifndef __HAVE_ARCH_STRSEP
+extern char * strsep(char **,const char *);
+#endif
+#ifndef __HAVE_ARCH_STRSPN
+extern __kernel_size_t strspn(const char *,const char *);
+#endif
+#ifndef __HAVE_ARCH_STRCSPN
+extern __kernel_size_t strcspn(const char *,const char *);
+#endif
#ifndef __HAVE_ARCH_MEMSET
extern void * memset(void *,int,__kernel_size_t);
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index c4e3ea7cf15..b5612c958cc 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -50,7 +50,7 @@ struct cache_head {
time_t last_refresh; /* If CACHE_PENDING, this is when upcall
* was sent, else this is when update was received
*/
- atomic_t refcnt;
+ struct kref ref;
unsigned long flags;
};
#define CACHE_VALID 0 /* Entry contains valid data */
@@ -68,8 +68,7 @@ struct cache_detail {
atomic_t inuse; /* active user-space update or lookup */
char *name;
- void (*cache_put)(struct cache_head *,
- struct cache_detail*);
+ void (*cache_put)(struct kref *);
void (*cache_request)(struct cache_detail *cd,
struct cache_head *h,
@@ -81,6 +80,11 @@ struct cache_detail {
struct cache_detail *cd,
struct cache_head *h);
+ struct cache_head * (*alloc)(void);
+ int (*match)(struct cache_head *orig, struct cache_head *new);
+ void (*init)(struct cache_head *orig, struct cache_head *new);
+ void (*update)(struct cache_head *orig, struct cache_head *new);
+
/* fields below this comment are for internal use
* and should not be touched by cache owners
*/
@@ -123,126 +127,14 @@ struct cache_deferred_req {
int too_many);
};
-/*
- * just like a template in C++, this macro does cache lookup
- * for us.
- * The function is passed some sort of HANDLE from which a cache_detail
- * structure can be determined (via SETUP, DETAIL), a template
- * cache entry (type RTN*), and a "set" flag. Using the HASHFN and the
- * TEST, the function will try to find a matching cache entry in the cache.
- * If "set" == 0 :
- * If an entry is found, it is returned
- * If no entry is found, a new non-VALID entry is created.
- * If "set" == 1 and INPLACE == 0 :
- * If no entry is found a new one is inserted with data from "template"
- * If a non-CACHE_VALID entry is found, it is updated from template using UPDATE
- * If a CACHE_VALID entry is found, a new entry is swapped in with data
- * from "template"
- * If set == 1, and INPLACE == 1 :
- * As above, except that if a CACHE_VALID entry is found, we UPDATE in place
- * instead of swapping in a new entry.
- *
- * If the passed handle has the CACHE_NEGATIVE flag set, then UPDATE is not
- * run but insteead CACHE_NEGATIVE is set in any new item.
- * In any case, the new entry is returned with a reference count.
- *
- *
- * RTN is a struct type for a cache entry
- * MEMBER is the member of the cache which is cache_head, which must be first
- * FNAME is the name for the function
- * ARGS are arguments to function and must contain RTN *item, int set. May
- * also contain something to be usedby SETUP or DETAIL to find cache_detail.
- * SETUP locates the cache detail and makes it available as...
- * DETAIL identifies the cache detail, possibly set up by SETUP
- * HASHFN returns a hash value of the cache entry "item"
- * TEST tests if "tmp" matches "item"
- * INIT copies key information from "item" to "new"
- * UPDATE copies content information from "item" to "tmp"
- * INPLACE is true if updates can happen inplace rather than allocating a new structure
- *
- * WARNING: any substantial changes to this must be reflected in
- * net/sunrpc/svcauth.c(auth_domain_lookup)
- * which is a similar routine that is open-coded.
- */
-#define DefineCacheLookup(RTN,MEMBER,FNAME,ARGS,SETUP,DETAIL,HASHFN,TEST,INIT,UPDATE,INPLACE) \
-RTN *FNAME ARGS \
-{ \
- RTN *tmp, *new=NULL; \
- struct cache_head **hp, **head; \
- SETUP; \
- head = &(DETAIL)->hash_table[HASHFN]; \
- retry: \
- if (set||new) write_lock(&(DETAIL)->hash_lock); \
- else read_lock(&(DETAIL)->hash_lock); \
- for(hp=head; *hp != NULL; hp = &tmp->MEMBER.next) { \
- tmp = container_of(*hp, RTN, MEMBER); \
- if (TEST) { /* found a match */ \
- \
- if (set && !INPLACE && test_bit(CACHE_VALID, &tmp->MEMBER.flags) && !new) \
- break; \
- \
- if (new) \
- {INIT;} \
- if (set) { \
- if (!INPLACE && test_bit(CACHE_VALID, &tmp->MEMBER.flags))\
- { /* need to swap in new */ \
- RTN *t2; \
- \
- new->MEMBER.next = tmp->MEMBER.next; \
- *hp = &new->MEMBER; \
- tmp->MEMBER.next = NULL; \
- t2 = tmp; tmp = new; new = t2; \
- } \
- if (test_bit(CACHE_NEGATIVE, &item->MEMBER.flags)) \
- set_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags); \
- else { \
- UPDATE; \
- clear_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags); \
- } \
- } \
- cache_get(&tmp->MEMBER); \
- if (set||new) write_unlock(&(DETAIL)->hash_lock); \
- else read_unlock(&(DETAIL)->hash_lock); \
- if (set) \
- cache_fresh(DETAIL, &tmp->MEMBER, item->MEMBER.expiry_time); \
- if (set && !INPLACE && new) cache_fresh(DETAIL, &new->MEMBER, 0); \
- if (new) (DETAIL)->cache_put(&new->MEMBER, DETAIL); \
- return tmp; \
- } \
- } \
- /* Didn't find anything */ \
- if (new) { \
- INIT; \
- new->MEMBER.next = *head; \
- *head = &new->MEMBER; \
- (DETAIL)->entries ++; \
- cache_get(&new->MEMBER); \
- if (set) { \
- tmp = new; \
- if (test_bit(CACHE_NEGATIVE, &item->MEMBER.flags)) \
- set_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags); \
- else {UPDATE;} \
- } \
- } \
- if (set||new) write_unlock(&(DETAIL)->hash_lock); \
- else read_unlock(&(DETAIL)->hash_lock); \
- if (new && set) \
- cache_fresh(DETAIL, &new->MEMBER, item->MEMBER.expiry_time); \
- if (new) \
- return new; \
- new = kmalloc(sizeof(*new), GFP_KERNEL); \
- if (new) { \
- cache_init(&new->MEMBER); \
- goto retry; \
- } \
- return NULL; \
-}
+extern struct cache_head *
+sunrpc_cache_lookup(struct cache_detail *detail,
+ struct cache_head *key, int hash);
+extern struct cache_head *
+sunrpc_cache_update(struct cache_detail *detail,
+ struct cache_head *new, struct cache_head *old, int hash);
-#define DefineSimpleCacheLookup(STRUCT,INPLACE) \
- DefineCacheLookup(struct STRUCT, h, STRUCT##_lookup, (struct STRUCT *item, int set), /*no setup */, \
- & STRUCT##_cache, STRUCT##_hash(item), STRUCT##_match(item, tmp),\
- STRUCT##_init(new, item), STRUCT##_update(tmp, item),INPLACE)
#define cache_for_each(pos, detail, index, member) \
for (({read_lock(&(detail)->hash_lock); index = (detail)->hash_size;}) ; \
@@ -258,22 +150,19 @@ extern void cache_clean_deferred(void *owner);
static inline struct cache_head *cache_get(struct cache_head *h)
{
- atomic_inc(&h->refcnt);
+ kref_get(&h->ref);
return h;
}
-static inline int cache_put(struct cache_head *h, struct cache_detail *cd)
+static inline void cache_put(struct cache_head *h, struct cache_detail *cd)
{
- if (atomic_read(&h->refcnt) <= 2 &&
+ if (atomic_read(&h->ref.refcount) <= 2 &&
h->expiry_time < cd->nextcheck)
cd->nextcheck = h->expiry_time;
- return atomic_dec_and_test(&h->refcnt);
+ kref_put(&h->ref, cd->cache_put);
}
-extern void cache_init(struct cache_head *h);
-extern void cache_fresh(struct cache_detail *detail,
- struct cache_head *head, time_t expiry);
extern int cache_check(struct cache_detail *detail,
struct cache_head *h, struct cache_req *rqstp);
extern void cache_flush(void);
diff --git a/include/linux/sunrpc/metrics.h b/include/linux/sunrpc/metrics.h
index 8f96e9dc369..77f78e56c48 100644
--- a/include/linux/sunrpc/metrics.h
+++ b/include/linux/sunrpc/metrics.h
@@ -69,9 +69,21 @@ struct rpc_clnt;
/*
* EXPORTed functions for managing rpc_iostats structures
*/
+
+#ifdef CONFIG_PROC_FS
+
struct rpc_iostats * rpc_alloc_iostats(struct rpc_clnt *);
void rpc_count_iostats(struct rpc_task *);
void rpc_print_iostats(struct seq_file *, struct rpc_clnt *);
void rpc_free_iostats(struct rpc_iostats *);
+#else /* CONFIG_PROC_FS */
+
+static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; }
+static inline void rpc_count_iostats(struct rpc_task *task) {}
+static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
+static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
+
+#endif /* CONFIG_PROC_FS */
+
#endif /* _LINUX_SUNRPC_METRICS_H */
diff --git a/include/linux/sunrpc/stats.h b/include/linux/sunrpc/stats.h
index 0d6ed3c8bdc..d93c24b47f3 100644
--- a/include/linux/sunrpc/stats.h
+++ b/include/linux/sunrpc/stats.h
@@ -50,7 +50,7 @@ struct proc_dir_entry * rpc_proc_register(struct rpc_stat *);
void rpc_proc_unregister(const char *);
void rpc_proc_zero(struct rpc_program *);
struct proc_dir_entry * svc_proc_register(struct svc_stat *,
- struct file_operations *);
+ const struct file_operations *);
void svc_proc_unregister(const char *);
void svc_seq_show(struct seq_file *,
@@ -65,7 +65,7 @@ static inline void rpc_proc_unregister(const char *p) {}
static inline void rpc_proc_zero(struct rpc_program *p) {}
static inline struct proc_dir_entry *svc_proc_register(struct svc_stat *s,
- struct file_operations *f) { return NULL; }
+ const struct file_operations *f) { return NULL; }
static inline void svc_proc_unregister(const char *p) {}
static inline void svc_seq_show(struct seq_file *seq,
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 50cab2a09f2..50356438454 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -197,15 +197,16 @@ svc_take_res_page(struct svc_rqst *rqstp)
return rqstp->rq_respages[rqstp->rq_resused++];
}
-static inline int svc_take_page(struct svc_rqst *rqstp)
+static inline void svc_take_page(struct svc_rqst *rqstp)
{
- if (rqstp->rq_arghi <= rqstp->rq_argused)
- return -ENOMEM;
+ if (rqstp->rq_arghi <= rqstp->rq_argused) {
+ WARN_ON(1);
+ return;
+ }
rqstp->rq_arghi--;
rqstp->rq_respages[rqstp->rq_resused] =
rqstp->rq_argpages[rqstp->rq_arghi];
rqstp->rq_resused++;
- return 0;
}
static inline void svc_pushback_allpages(struct svc_rqst *rqstp)
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index c119ce7cbd2..2fe2087edd6 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -45,9 +45,10 @@ struct svc_rqst; /* forward decl */
* of ip addresses to the given client.
*/
struct auth_domain {
- struct cache_head h;
+ struct kref ref;
+ struct hlist_node hash;
char *name;
- int flavour;
+ struct auth_ops *flavour;
};
/*
@@ -86,6 +87,9 @@ struct auth_domain {
*
* domain_release()
* This call releases a domain.
+ * set_client()
+ * Givens a pending request (struct svc_rqst), finds and assigns
+ * an appropriate 'auth_domain' as the client.
*/
struct auth_ops {
char * name;
@@ -117,7 +121,7 @@ extern void svc_auth_unregister(rpc_authflavor_t flavor);
extern struct auth_domain *unix_domain_find(char *name);
extern void auth_domain_put(struct auth_domain *item);
extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom);
-extern struct auth_domain *auth_domain_lookup(struct auth_domain *item, int set);
+extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
extern struct auth_domain *auth_domain_find(char *name);
extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
extern int auth_unix_forget_old(struct auth_domain *dom);
@@ -160,8 +164,6 @@ static inline unsigned long hash_mem(char *buf, int length, int bits)
return hash >> (BITS_PER_LONG - bits);
}
-extern struct cache_detail auth_domain_cache, ip_map_cache;
-
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_SVCAUTH_H_ */
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 7eebbab7160..e8bbe8118de 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -53,6 +53,7 @@ struct rpc_timeout {
struct rpc_task;
struct rpc_xprt;
+struct seq_file;
/*
* This describes a complete RPC request
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 54eac8a39a4..f03c2471930 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -155,6 +155,7 @@ extern void swapin_readahead(swp_entry_t, unsigned long, struct vm_area_struct *
/* linux/mm/page_alloc.c */
extern unsigned long totalram_pages;
extern unsigned long totalhigh_pages;
+extern unsigned long totalreserve_pages;
extern long nr_swap_pages;
extern unsigned int nr_free_pages(void);
extern unsigned int nr_free_pages_pgdat(pg_data_t *pgdat);
@@ -295,7 +296,7 @@ static inline void disable_swap_token(void)
#define read_swap_cache_async(swp,vma,addr) NULL
#define lookup_swap_cache(swp) NULL
#define valid_swaphandles(swp, off) 0
-#define can_share_swap_page(p) 0
+#define can_share_swap_page(p) (page_mapcount(p) == 1)
#define move_to_swap_cache(p, swp) 1
#define move_from_swap_cache(p, i, m) 1
#define __delete_from_swap_cache(p) /*NOTHING*/
diff --git a/include/linux/synclink.h b/include/linux/synclink.h
index 1b7cd8d1a71..2993302f792 100644
--- a/include/linux/synclink.h
+++ b/include/linux/synclink.h
@@ -1,7 +1,7 @@
/*
* SyncLink Multiprotocol Serial Adapter Driver
*
- * $Id: synclink.h,v 3.10 2005/11/08 19:50:54 paulkf Exp $
+ * $Id: synclink.h,v 3.11 2006/02/06 21:20:29 paulkf Exp $
*
* Copyright (C) 1998-2000 by Microgate Corporation
*
@@ -221,6 +221,12 @@ struct mgsl_icount {
__u32 rxidle;
};
+struct gpio_desc {
+ __u32 state;
+ __u32 smask;
+ __u32 dir;
+ __u32 dmask;
+};
#define DEBUG_LEVEL_DATA 1
#define DEBUG_LEVEL_ERROR 2
@@ -276,5 +282,8 @@ struct mgsl_icount {
#define MGSL_IOCLOOPTXDONE _IO(MGSL_MAGIC_IOC,9)
#define MGSL_IOCSIF _IO(MGSL_MAGIC_IOC,10)
#define MGSL_IOCGIF _IO(MGSL_MAGIC_IOC,11)
+#define MGSL_IOCSGPIO _IOW(MGSL_MAGIC_IOC,16,struct gpio_desc)
+#define MGSL_IOCGGPIO _IOR(MGSL_MAGIC_IOC,17,struct gpio_desc)
+#define MGSL_IOCWAITGPIO _IOWR(MGSL_MAGIC_IOC,18,struct gpio_desc)
#endif /* _SYNCLINK_H_ */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index e487e3b60f6..60d49e5456e 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -52,6 +52,7 @@ struct utimbuf;
struct mq_attr;
struct compat_stat;
struct compat_timeval;
+struct robust_list_head;
#include <linux/config.h>
#include <linux/types.h>
@@ -570,4 +571,21 @@ asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
int flags, int mode);
asmlinkage long sys_unshare(unsigned long unshare_flags);
+asmlinkage long sys_splice(int fd_in, loff_t __user *off_in,
+ int fd_out, loff_t __user *off_out,
+ size_t len, unsigned int flags);
+
+asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov,
+ unsigned long nr_segs, unsigned int flags);
+
+asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags);
+
+asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
+ unsigned int flags);
+asmlinkage long sys_get_robust_list(int pid,
+ struct robust_list_head __user **head_ptr,
+ size_t __user *len_ptr);
+asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
+ size_t len);
+
#endif
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 392da5a6dac..1ea5d3cda6a 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -74,6 +74,7 @@ struct sysfs_dirent {
umode_t s_mode;
struct dentry * s_dentry;
struct iattr * s_iattr;
+ atomic_t s_event;
};
#define SYSFS_ROOT 0x0001
@@ -117,6 +118,7 @@ int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
int sysfs_create_group(struct kobject *, const struct attribute_group *);
void sysfs_remove_group(struct kobject *, const struct attribute_group *);
+void sysfs_notify(struct kobject * k, char *dir, char *attr);
#else /* CONFIG_SYSFS */
@@ -185,6 +187,10 @@ static inline void sysfs_remove_group(struct kobject * k, const struct attribute
;
}
+static inline void sysfs_notify(struct kobject * k, char *dir, char *attr)
+{
+}
+
#endif /* CONFIG_SYSFS */
#endif /* _SYSFS_H_ */
diff --git a/include/linux/threads.h b/include/linux/threads.h
index b59738ac619..e646bcdf261 100644
--- a/include/linux/threads.h
+++ b/include/linux/threads.h
@@ -28,7 +28,8 @@
#define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000)
/*
- * A maximum of 4 million PIDs should be enough for a while:
+ * A maximum of 4 million PIDs should be enough for a while.
+ * [NOTE: PID/TIDs are limited to 2^29 ~= 500+ million, see futex.h.]
*/
#define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \
(sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT))
diff --git a/include/linux/timer.h b/include/linux/timer.h
index b5caabca553..0a485beba9f 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -6,7 +6,7 @@
#include <linux/spinlock.h>
#include <linux/stddef.h>
-struct timer_base_s;
+struct tvec_t_base_s;
struct timer_list {
struct list_head entry;
@@ -15,16 +15,16 @@ struct timer_list {
void (*function)(unsigned long);
unsigned long data;
- struct timer_base_s *base;
+ struct tvec_t_base_s *base;
};
-extern struct timer_base_s __init_timer_base;
+extern struct tvec_t_base_s boot_tvec_bases;
#define TIMER_INITIALIZER(_function, _expires, _data) { \
.function = (_function), \
.expires = (_expires), \
.data = (_data), \
- .base = &__init_timer_base, \
+ .base = &boot_tvec_bases, \
}
#define DEFINE_TIMER(_name, _function, _expires, _data) \
diff --git a/include/linux/tiocl.h b/include/linux/tiocl.h
index 2c9e847f6ed..4756862c4ed 100644
--- a/include/linux/tiocl.h
+++ b/include/linux/tiocl.h
@@ -34,5 +34,6 @@ struct tiocl_selection {
#define TIOCL_SCROLLCONSOLE 13 /* scroll console */
#define TIOCL_BLANKSCREEN 14 /* keep screen blank even if a key is pressed */
#define TIOCL_BLANKEDSCREEN 15 /* return which vt was blanked */
+#define TIOCL_GETKMSGREDIRECT 17 /* get the vt the kernel messages are restricted to */
#endif /* _LINUX_TIOCL_H */
diff --git a/include/linux/topology.h b/include/linux/topology.h
index e8eb0040ce3..a305ae2e44b 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -164,6 +164,15 @@
.nr_balance_failed = 0, \
}
+#ifdef CONFIG_SCHED_MC
+#ifndef SD_MC_INIT
+/* for now its same as SD_CPU_INIT.
+ * TBD: Tune Domain parameters!
+ */
+#define SD_MC_INIT SD_CPU_INIT
+#endif
+#endif
+
#ifdef CONFIG_NUMA
#ifndef SD_NODE_INIT
#error Please define an appropriate SD_NODE_INIT in include/asm/topology.h!!!
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index 0976a163b45..31548303ee3 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -6,9 +6,10 @@ extern int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *c
extern int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size);
extern int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size);
extern int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size);
+void tty_schedule_flip(struct tty_struct *tty);
static inline int tty_insert_flip_char(struct tty_struct *tty,
- unsigned char ch, char flag)
+ unsigned char ch, char flag)
{
struct tty_buffer *tb = tty->buf.tail;
if (tb && tb->active && tb->used < tb->size) {
@@ -19,26 +20,4 @@ static inline int tty_insert_flip_char(struct tty_struct *tty,
return tty_insert_flip_string_flags(tty, &ch, &flag, 1);
}
-static inline void tty_schedule_flip(struct tty_struct *tty)
-{
- unsigned long flags;
- spin_lock_irqsave(&tty->buf.lock, flags);
- if (tty->buf.tail != NULL) {
- tty->buf.tail->active = 0;
- tty->buf.tail->commit = tty->buf.tail->used;
- }
- spin_unlock_irqrestore(&tty->buf.lock, flags);
- schedule_delayed_work(&tty->buf.work, 1);
-}
-
-#undef _INLINE_
-
-
#endif /* _LINUX_TTY_FLIP_H */
-
-
-
-
-
-
-
diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h
index b0ffe4356e5..843aeaaa79d 100644
--- a/include/linux/ufs_fs.h
+++ b/include/linux/ufs_fs.h
@@ -895,7 +895,7 @@ extern void ufs_set_link(struct inode *, struct ufs_dir_entry *, struct buffer_h
/* file.c */
extern struct inode_operations ufs_file_inode_operations;
-extern struct file_operations ufs_file_operations;
+extern const struct file_operations ufs_file_operations;
extern struct address_space_operations ufs_aops;
@@ -915,7 +915,7 @@ extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create);
/* namei.c */
-extern struct file_operations ufs_dir_operations;
+extern const struct file_operations ufs_dir_operations;
/* super.c */
extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
diff --git a/include/linux/uinput.h b/include/linux/uinput.h
index 0ff7ca68e5c..7168302f984 100644
--- a/include/linux/uinput.h
+++ b/include/linux/uinput.h
@@ -20,7 +20,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
- *
+ *
* Changes/Revisions:
* 0.2 16/10/2004 (Micah Dowty <micah@navi.cx>)
* - added force feedback support
@@ -51,7 +51,7 @@ struct uinput_request {
struct uinput_device {
struct input_dev *dev;
- struct semaphore sem;
+ struct mutex mutex;
enum uinput_state state;
wait_queue_head_t waitq;
unsigned char ready;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 130d125fda1..e34e5e3dce5 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -615,7 +615,7 @@ extern struct bus_type usb_bus_type;
*/
struct usb_class_driver {
char *name;
- struct file_operations *fops;
+ const struct file_operations *fops;
int minor_base;
};
diff --git a/include/linux/usb/net2280.h b/include/linux/usb/net2280.h
new file mode 100644
index 00000000000..c602f884f18
--- /dev/null
+++ b/include/linux/usb/net2280.h
@@ -0,0 +1,444 @@
+/*
+ * NetChip 2280 high/full speed USB device controller.
+ * Unlike many such controllers, this one talks PCI.
+ */
+#ifndef __LINUX_USB_NET2280_H
+#define __LINUX_USB_NET2280_H
+
+/*
+ * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
+ * Copyright (C) 2003 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* NET2280 MEMORY MAPPED REGISTERS
+ *
+ * The register layout came from the chip documentation, and the bit
+ * number definitions were extracted from chip specification.
+ *
+ * Use the shift operator ('<<') to build bit masks, with readl/writel
+ * to access the registers through PCI.
+ */
+
+/* main registers, BAR0 + 0x0000 */
+struct net2280_regs {
+ // offset 0x0000
+ u32 devinit;
+#define LOCAL_CLOCK_FREQUENCY 8
+#define FORCE_PCI_RESET 7
+#define PCI_ID 6
+#define PCI_ENABLE 5
+#define FIFO_SOFT_RESET 4
+#define CFG_SOFT_RESET 3
+#define PCI_SOFT_RESET 2
+#define USB_SOFT_RESET 1
+#define M8051_RESET 0
+ u32 eectl;
+#define EEPROM_ADDRESS_WIDTH 23
+#define EEPROM_CHIP_SELECT_ACTIVE 22
+#define EEPROM_PRESENT 21
+#define EEPROM_VALID 20
+#define EEPROM_BUSY 19
+#define EEPROM_CHIP_SELECT_ENABLE 18
+#define EEPROM_BYTE_READ_START 17
+#define EEPROM_BYTE_WRITE_START 16
+#define EEPROM_READ_DATA 8
+#define EEPROM_WRITE_DATA 0
+ u32 eeclkfreq;
+ u32 _unused0;
+ // offset 0x0010
+
+ u32 pciirqenb0; /* interrupt PCI master ... */
+#define SETUP_PACKET_INTERRUPT_ENABLE 7
+#define ENDPOINT_F_INTERRUPT_ENABLE 6
+#define ENDPOINT_E_INTERRUPT_ENABLE 5
+#define ENDPOINT_D_INTERRUPT_ENABLE 4
+#define ENDPOINT_C_INTERRUPT_ENABLE 3
+#define ENDPOINT_B_INTERRUPT_ENABLE 2
+#define ENDPOINT_A_INTERRUPT_ENABLE 1
+#define ENDPOINT_0_INTERRUPT_ENABLE 0
+ u32 pciirqenb1;
+#define PCI_INTERRUPT_ENABLE 31
+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
+#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18
+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
+#define GPIO_INTERRUPT_ENABLE 13
+#define DMA_D_INTERRUPT_ENABLE 12
+#define DMA_C_INTERRUPT_ENABLE 11
+#define DMA_B_INTERRUPT_ENABLE 10
+#define DMA_A_INTERRUPT_ENABLE 9
+#define EEPROM_DONE_INTERRUPT_ENABLE 8
+#define VBUS_INTERRUPT_ENABLE 7
+#define CONTROL_STATUS_INTERRUPT_ENABLE 6
+#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
+#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
+#define RESUME_INTERRUPT_ENABLE 1
+#define SOF_INTERRUPT_ENABLE 0
+ u32 cpu_irqenb0; /* ... or onboard 8051 */
+#define SETUP_PACKET_INTERRUPT_ENABLE 7
+#define ENDPOINT_F_INTERRUPT_ENABLE 6
+#define ENDPOINT_E_INTERRUPT_ENABLE 5
+#define ENDPOINT_D_INTERRUPT_ENABLE 4
+#define ENDPOINT_C_INTERRUPT_ENABLE 3
+#define ENDPOINT_B_INTERRUPT_ENABLE 2
+#define ENDPOINT_A_INTERRUPT_ENABLE 1
+#define ENDPOINT_0_INTERRUPT_ENABLE 0
+ u32 cpu_irqenb1;
+#define CPU_INTERRUPT_ENABLE 31
+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
+#define PCI_INTA_INTERRUPT_ENABLE 24
+#define PCI_PME_INTERRUPT_ENABLE 23
+#define PCI_SERR_INTERRUPT_ENABLE 22
+#define PCI_PERR_INTERRUPT_ENABLE 21
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
+#define GPIO_INTERRUPT_ENABLE 13
+#define DMA_D_INTERRUPT_ENABLE 12
+#define DMA_C_INTERRUPT_ENABLE 11
+#define DMA_B_INTERRUPT_ENABLE 10
+#define DMA_A_INTERRUPT_ENABLE 9
+#define EEPROM_DONE_INTERRUPT_ENABLE 8
+#define VBUS_INTERRUPT_ENABLE 7
+#define CONTROL_STATUS_INTERRUPT_ENABLE 6
+#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
+#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
+#define RESUME_INTERRUPT_ENABLE 1
+#define SOF_INTERRUPT_ENABLE 0
+
+ // offset 0x0020
+ u32 _unused1;
+ u32 usbirqenb1;
+#define USB_INTERRUPT_ENABLE 31
+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
+#define PCI_INTA_INTERRUPT_ENABLE 24
+#define PCI_PME_INTERRUPT_ENABLE 23
+#define PCI_SERR_INTERRUPT_ENABLE 22
+#define PCI_PERR_INTERRUPT_ENABLE 21
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
+#define GPIO_INTERRUPT_ENABLE 13
+#define DMA_D_INTERRUPT_ENABLE 12
+#define DMA_C_INTERRUPT_ENABLE 11
+#define DMA_B_INTERRUPT_ENABLE 10
+#define DMA_A_INTERRUPT_ENABLE 9
+#define EEPROM_DONE_INTERRUPT_ENABLE 8
+#define VBUS_INTERRUPT_ENABLE 7
+#define CONTROL_STATUS_INTERRUPT_ENABLE 6
+#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
+#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
+#define RESUME_INTERRUPT_ENABLE 1
+#define SOF_INTERRUPT_ENABLE 0
+ u32 irqstat0;
+#define INTA_ASSERTED 12
+#define SETUP_PACKET_INTERRUPT 7
+#define ENDPOINT_F_INTERRUPT 6
+#define ENDPOINT_E_INTERRUPT 5
+#define ENDPOINT_D_INTERRUPT 4
+#define ENDPOINT_C_INTERRUPT 3
+#define ENDPOINT_B_INTERRUPT 2
+#define ENDPOINT_A_INTERRUPT 1
+#define ENDPOINT_0_INTERRUPT 0
+ u32 irqstat1;
+#define POWER_STATE_CHANGE_INTERRUPT 27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT 26
+#define PCI_PARITY_ERROR_INTERRUPT 25
+#define PCI_INTA_INTERRUPT 24
+#define PCI_PME_INTERRUPT 23
+#define PCI_SERR_INTERRUPT 22
+#define PCI_PERR_INTERRUPT 21
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19
+#define PCI_RETRY_ABORT_INTERRUPT 17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16
+#define SOF_DOWN_INTERRUPT 14
+#define GPIO_INTERRUPT 13
+#define DMA_D_INTERRUPT 12
+#define DMA_C_INTERRUPT 11
+#define DMA_B_INTERRUPT 10
+#define DMA_A_INTERRUPT 9
+#define EEPROM_DONE_INTERRUPT 8
+#define VBUS_INTERRUPT 7
+#define CONTROL_STATUS_INTERRUPT 6
+#define ROOT_PORT_RESET_INTERRUPT 4
+#define SUSPEND_REQUEST_INTERRUPT 3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2
+#define RESUME_INTERRUPT 1
+#define SOF_INTERRUPT 0
+ // offset 0x0030
+ u32 idxaddr;
+ u32 idxdata;
+ u32 fifoctl;
+#define PCI_BASE2_RANGE 16
+#define IGNORE_FIFO_AVAILABILITY 3
+#define PCI_BASE2_SELECT 2
+#define FIFO_CONFIGURATION_SELECT 0
+ u32 _unused2;
+ // offset 0x0040
+ u32 memaddr;
+#define START 28
+#define DIRECTION 27
+#define FIFO_DIAGNOSTIC_SELECT 24
+#define MEMORY_ADDRESS 0
+ u32 memdata0;
+ u32 memdata1;
+ u32 _unused3;
+ // offset 0x0050
+ u32 gpioctl;
+#define GPIO3_LED_SELECT 12
+#define GPIO3_INTERRUPT_ENABLE 11
+#define GPIO2_INTERRUPT_ENABLE 10
+#define GPIO1_INTERRUPT_ENABLE 9
+#define GPIO0_INTERRUPT_ENABLE 8
+#define GPIO3_OUTPUT_ENABLE 7
+#define GPIO2_OUTPUT_ENABLE 6
+#define GPIO1_OUTPUT_ENABLE 5
+#define GPIO0_OUTPUT_ENABLE 4
+#define GPIO3_DATA 3
+#define GPIO2_DATA 2
+#define GPIO1_DATA 1
+#define GPIO0_DATA 0
+ u32 gpiostat;
+#define GPIO3_INTERRUPT 3
+#define GPIO2_INTERRUPT 2
+#define GPIO1_INTERRUPT 1
+#define GPIO0_INTERRUPT 0
+} __attribute__ ((packed));
+
+/* usb control, BAR0 + 0x0080 */
+struct net2280_usb_regs {
+ // offset 0x0080
+ u32 stdrsp;
+#define STALL_UNSUPPORTED_REQUESTS 31
+#define SET_TEST_MODE 16
+#define GET_OTHER_SPEED_CONFIGURATION 15
+#define GET_DEVICE_QUALIFIER 14
+#define SET_ADDRESS 13
+#define ENDPOINT_SET_CLEAR_HALT 12
+#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11
+#define GET_STRING_DESCRIPTOR_2 10
+#define GET_STRING_DESCRIPTOR_1 9
+#define GET_STRING_DESCRIPTOR_0 8
+#define GET_SET_INTERFACE 6
+#define GET_SET_CONFIGURATION 5
+#define GET_CONFIGURATION_DESCRIPTOR 4
+#define GET_DEVICE_DESCRIPTOR 3
+#define GET_ENDPOINT_STATUS 2
+#define GET_INTERFACE_STATUS 1
+#define GET_DEVICE_STATUS 0
+ u32 prodvendid;
+#define PRODUCT_ID 16
+#define VENDOR_ID 0
+ u32 relnum;
+ u32 usbctl;
+#define SERIAL_NUMBER_INDEX 16
+#define PRODUCT_ID_STRING_ENABLE 13
+#define VENDOR_ID_STRING_ENABLE 12
+#define USB_ROOT_PORT_WAKEUP_ENABLE 11
+#define VBUS_PIN 10
+#define TIMED_DISCONNECT 9
+#define SUSPEND_IMMEDIATELY 7
+#define SELF_POWERED_USB_DEVICE 6
+#define REMOTE_WAKEUP_SUPPORT 5
+#define PME_POLARITY 4
+#define USB_DETECT_ENABLE 3
+#define PME_WAKEUP_ENABLE 2
+#define DEVICE_REMOTE_WAKEUP_ENABLE 1
+#define SELF_POWERED_STATUS 0
+ // offset 0x0090
+ u32 usbstat;
+#define HIGH_SPEED 7
+#define FULL_SPEED 6
+#define GENERATE_RESUME 5
+#define GENERATE_DEVICE_REMOTE_WAKEUP 4
+ u32 xcvrdiag;
+#define FORCE_HIGH_SPEED_MODE 31
+#define FORCE_FULL_SPEED_MODE 30
+#define USB_TEST_MODE 24
+#define LINE_STATE 16
+#define TRANSCEIVER_OPERATION_MODE 2
+#define TRANSCEIVER_SELECT 1
+#define TERMINATION_SELECT 0
+ u32 setup0123;
+ u32 setup4567;
+ // offset 0x0090
+ u32 _unused0;
+ u32 ouraddr;
+#define FORCE_IMMEDIATE 7
+#define OUR_USB_ADDRESS 0
+ u32 ourconfig;
+} __attribute__ ((packed));
+
+/* pci control, BAR0 + 0x0100 */
+struct net2280_pci_regs {
+ // offset 0x0100
+ u32 pcimstctl;
+#define PCI_ARBITER_PARK_SELECT 13
+#define PCI_MULTI LEVEL_ARBITER 12
+#define PCI_RETRY_ABORT_ENABLE 11
+#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10
+#define DMA_READ_MULTIPLE_ENABLE 9
+#define DMA_READ_LINE_ENABLE 8
+#define PCI_MASTER_COMMAND_SELECT 6
+#define MEM_READ_OR_WRITE 0
+#define IO_READ_OR_WRITE 1
+#define CFG_READ_OR_WRITE 2
+#define PCI_MASTER_START 5
+#define PCI_MASTER_READ_WRITE 4
+#define PCI_MASTER_WRITE 0
+#define PCI_MASTER_READ 1
+#define PCI_MASTER_BYTE_WRITE_ENABLES 0
+ u32 pcimstaddr;
+ u32 pcimstdata;
+ u32 pcimststat;
+#define PCI_ARBITER_CLEAR 2
+#define PCI_EXTERNAL_ARBITER 1
+#define PCI_HOST_MODE 0
+} __attribute__ ((packed));
+
+/* dma control, BAR0 + 0x0180 ... array of four structs like this,
+ * for channels 0..3. see also struct net2280_dma: descriptor
+ * that can be loaded into some of these registers.
+ */
+struct net2280_dma_regs { /* [11.7] */
+ // offset 0x0180, 0x01a0, 0x01c0, 0x01e0,
+ u32 dmactl;
+#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25
+#define DMA_CLEAR_COUNT_ENABLE 21
+#define DESCRIPTOR_POLLING_RATE 19
+#define POLL_CONTINUOUS 0
+#define POLL_1_USEC 1
+#define POLL_100_USEC 2
+#define POLL_1_MSEC 3
+#define DMA_VALID_BIT_POLLING_ENABLE 18
+#define DMA_VALID_BIT_ENABLE 17
+#define DMA_SCATTER_GATHER_ENABLE 16
+#define DMA_OUT_AUTO_START_ENABLE 4
+#define DMA_PREEMPT_ENABLE 3
+#define DMA_FIFO_VALIDATE 2
+#define DMA_ENABLE 1
+#define DMA_ADDRESS_HOLD 0
+ u32 dmastat;
+#define DMA_ABORT_DONE_INTERRUPT 27
+#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25
+#define DMA_TRANSACTION_DONE_INTERRUPT 24
+#define DMA_ABORT 1
+#define DMA_START 0
+ u32 _unused0 [2];
+ // offset 0x0190, 0x01b0, 0x01d0, 0x01f0,
+ u32 dmacount;
+#define VALID_BIT 31
+#define DMA_DIRECTION 30
+#define DMA_DONE_INTERRUPT_ENABLE 29
+#define END_OF_CHAIN 28
+#define DMA_BYTE_COUNT_MASK ((1<<24)-1)
+#define DMA_BYTE_COUNT 0
+ u32 dmaaddr;
+ u32 dmadesc;
+ u32 _unused1;
+} __attribute__ ((packed));
+
+/* dedicated endpoint registers, BAR0 + 0x0200 */
+
+struct net2280_dep_regs { /* [11.8] */
+ // offset 0x0200, 0x0210, 0x220, 0x230, 0x240
+ u32 dep_cfg;
+ // offset 0x0204, 0x0214, 0x224, 0x234, 0x244
+ u32 dep_rsp;
+ u32 _unused [2];
+} __attribute__ ((packed));
+
+/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
+ * like this, for ep0 then the configurable endpoints A..F
+ * ep0 reserved for control; E and F have only 64 bytes of fifo
+ */
+struct net2280_ep_regs { /* [11.9] */
+ // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0
+ u32 ep_cfg;
+#define ENDPOINT_BYTE_COUNT 16
+#define ENDPOINT_ENABLE 10
+#define ENDPOINT_TYPE 8
+#define ENDPOINT_DIRECTION 7
+#define ENDPOINT_NUMBER 0
+ u32 ep_rsp;
+#define SET_NAK_OUT_PACKETS 15
+#define SET_EP_HIDE_STATUS_PHASE 14
+#define SET_EP_FORCE_CRC_ERROR 13
+#define SET_INTERRUPT_MODE 12
+#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11
+#define SET_NAK_OUT_PACKETS_MODE 10
+#define SET_ENDPOINT_TOGGLE 9
+#define SET_ENDPOINT_HALT 8
+#define CLEAR_NAK_OUT_PACKETS 7
+#define CLEAR_EP_HIDE_STATUS_PHASE 6
+#define CLEAR_EP_FORCE_CRC_ERROR 5
+#define CLEAR_INTERRUPT_MODE 4
+#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3
+#define CLEAR_NAK_OUT_PACKETS_MODE 2
+#define CLEAR_ENDPOINT_TOGGLE 1
+#define CLEAR_ENDPOINT_HALT 0
+ u32 ep_irqenb;
+#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6
+#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5
+#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3
+#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2
+#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1
+#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0
+ u32 ep_stat;
+#define FIFO_VALID_COUNT 24
+#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22
+#define TIMEOUT 21
+#define USB_STALL_SENT 20
+#define USB_IN_NAK_SENT 19
+#define USB_IN_ACK_RCVD 18
+#define USB_OUT_PING_NAK_SENT 17
+#define USB_OUT_ACK_SENT 16
+#define FIFO_OVERFLOW 13
+#define FIFO_UNDERFLOW 12
+#define FIFO_FULL 11
+#define FIFO_EMPTY 10
+#define FIFO_FLUSH 9
+#define SHORT_PACKET_OUT_DONE_INTERRUPT 6
+#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5
+#define NAK_OUT_PACKETS 4
+#define DATA_PACKET_RECEIVED_INTERRUPT 3
+#define DATA_PACKET_TRANSMITTED_INTERRUPT 2
+#define DATA_OUT_PING_TOKEN_INTERRUPT 1
+#define DATA_IN_TOKEN_INTERRUPT 0
+ // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0
+ u32 ep_avail;
+ u32 ep_data;
+ u32 _unused0 [2];
+} __attribute__ ((packed));
+
+#endif /* __LINUX_USB_NET2280_H */
diff --git a/include/linux/vermagic.h b/include/linux/vermagic.h
index fadc535e292..dc7c621e464 100644
--- a/include/linux/vermagic.h
+++ b/include/linux/vermagic.h
@@ -12,6 +12,11 @@
#else
#define MODULE_VERMAGIC_PREEMPT ""
#endif
+#ifdef CONFIG_MODULE_UNLOAD
+#define MODULE_VERMAGIC_MODULE_UNLOAD "mod_unload "
+#else
+#define MODULE_VERMAGIC_MODULE_UNLOAD ""
+#endif
#ifndef MODULE_ARCH_VERMAGIC
#define MODULE_ARCH_VERMAGIC ""
#endif
@@ -19,5 +24,5 @@
#define VERMAGIC_STRING \
UTS_RELEASE " " \
MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \
- MODULE_ARCH_VERMAGIC \
+ MODULE_VERMAGIC_MODULE_UNLOAD MODULE_ARCH_VERMAGIC \
"gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__)
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 2275bfec5b6..ad7fa9c86c1 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -75,7 +75,7 @@ struct video_device
int minor;
/* device ops + callbacks */
- struct file_operations *fops;
+ const struct file_operations *fops;
void (*release)(struct video_device *vfd);
@@ -966,66 +966,17 @@ struct v4l2_sliced_vbi_format
/* Teletext World System Teletext
(WST), defined on ITU-R BT.653-2 */
-#define V4L2_SLICED_TELETEXT_PAL_B (0x000001)
-#define V4L2_SLICED_TELETEXT_PAL_C (0x000002)
-#define V4L2_SLICED_TELETEXT_NTSC_B (0x000010)
-#define V4L2_SLICED_TELETEXT_SECAM (0x000020)
-
-/* Teletext North American Broadcast Teletext Specification
- (NABTS), defined on ITU-R BT.653-2 */
-#define V4L2_SLICED_TELETEXT_NTSC_C (0x000040)
-#define V4L2_SLICED_TELETEXT_NTSC_D (0x000080)
-
+#define V4L2_SLICED_TELETEXT_B (0x0001)
/* Video Program System, defined on ETS 300 231*/
-#define V4L2_SLICED_VPS (0x000400)
-
+#define V4L2_SLICED_VPS (0x0400)
/* Closed Caption, defined on EIA-608 */
-#define V4L2_SLICED_CAPTION_525 (0x001000)
-#define V4L2_SLICED_CAPTION_625 (0x002000)
-
+#define V4L2_SLICED_CAPTION_525 (0x1000)
/* Wide Screen System, defined on ITU-R BT1119.1 */
-#define V4L2_SLICED_WSS_625 (0x004000)
-
-/* Wide Screen System, defined on IEC 61880 */
-#define V4L2_SLICED_WSS_525 (0x008000)
-
-/* Vertical Interval Timecode (VITC), defined on SMPTE 12M */
-#define V4l2_SLICED_VITC_625 (0x010000)
-#define V4l2_SLICED_VITC_525 (0x020000)
-
-#define V4L2_SLICED_TELETEXT_B (V4L2_SLICED_TELETEXT_PAL_B |\
- V4L2_SLICED_TELETEXT_NTSC_B)
+#define V4L2_SLICED_WSS_625 (0x4000)
-#define V4L2_SLICED_TELETEXT (V4L2_SLICED_TELETEXT_PAL_B |\
- V4L2_SLICED_TELETEXT_PAL_C |\
- V4L2_SLICED_TELETEXT_SECAM |\
- V4L2_SLICED_TELETEXT_NTSC_B |\
- V4L2_SLICED_TELETEXT_NTSC_C |\
- V4L2_SLICED_TELETEXT_NTSC_D)
+#define V4L2_SLICED_VBI_525 (V4L2_SLICED_CAPTION_525)
+#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625)
-#define V4L2_SLICED_CAPTION (V4L2_SLICED_CAPTION_525 |\
- V4L2_SLICED_CAPTION_625)
-
-#define V4L2_SLICED_WSS (V4L2_SLICED_WSS_525 |\
- V4L2_SLICED_WSS_625)
-
-#define V4L2_SLICED_VITC (V4L2_SLICED_VITC_525 |\
- V4L2_SLICED_VITC_625)
-
-#define V4L2_SLICED_VBI_525 (V4L2_SLICED_TELETEXT_NTSC_B |\
- V4L2_SLICED_TELETEXT_NTSC_C |\
- V4L2_SLICED_TELETEXT_NTSC_D |\
- V4L2_SLICED_CAPTION_525 |\
- V4L2_SLICED_WSS_525 |\
- V4l2_SLICED_VITC_525)
-
-#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_PAL_B |\
- V4L2_SLICED_TELETEXT_PAL_C |\
- V4L2_SLICED_TELETEXT_SECAM |\
- V4L2_SLICED_VPS |\
- V4L2_SLICED_CAPTION_625 |\
- V4L2_SLICED_WSS_625 |\
- V4l2_SLICED_VITC_625)
struct v4l2_sliced_vbi_cap
{
@@ -1190,8 +1141,13 @@ extern char *v4l2_type_names[];
/* Compatibility layer interface -- v4l1-compat module */
typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file,
unsigned int cmd, void *arg);
+
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
int v4l_compat_translate_ioctl(struct inode *inode, struct file *file,
int cmd, void *arg, v4l2_kioctl driver_ioctl);
+#else
+#define v4l_compat_translate_ioctl(inode,file,cmd,arg,ioctl) -EINVAL
+#endif
/* 32 Bits compatibility layer for 64 bits processors */
extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 530ae3f4248..fab5aed8ca3 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -73,11 +73,6 @@ 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);
-#ifdef CONFIG_VT
-int is_console_suspend_safe(void);
-#else
-static inline int is_console_suspend_safe(void) { return 1; }
-#endif
/*
* vc_screen.c shares this temporary buffer with the console write code so that
diff --git a/include/linux/wanpipe.h b/include/linux/wanpipe.h
deleted file mode 100644
index dae9860091d..00000000000
--- a/include/linux/wanpipe.h
+++ /dev/null
@@ -1,483 +0,0 @@
-/*****************************************************************************
-* wanpipe.h WANPIPE(tm) Multiprotocol WAN Link Driver.
-* User-level API definitions.
-*
-* Author: Nenad Corbic <ncorbic@sangoma.com>
-* Gideon Hack
-*
-* Copyright: (c) 1995-2000 Sangoma Technologies 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.
-* ============================================================================
-* Nov 3, 2000 Nenad Corbic Added config_id to sdla_t structure.
-* Used to determine the protocol running.
-* Jul 13, 2000 Nenad Corbic Added SyncPPP Support
-* Feb 24, 2000 Nenad Corbic Added support for x25api driver
-* Oct 04, 1999 Nenad Corbic New CHDLC and FRAME RELAY code, SMP support
-* Jun 02, 1999 Gideon Hack Added 'update_call_count' for Cisco HDLC
-* support
-* Jun 26, 1998 David Fong Added 'ip_mode' in sdla_t.u.p for dynamic IP
-* routing mode configuration
-* Jun 12, 1998 David Fong Added Cisco HDLC union member in sdla_t
-* Dec 08, 1997 Jaspreet Singh Added 'authenticator' in union of 'sdla_t'
-* Nov 26, 1997 Jaspreet Singh Added 'load_sharing' structure. Also added
-* 'devs_struct','dev_to_devtint_next' to 'sdla_t'
-* Nov 24, 1997 Jaspreet Singh Added 'irq_dis_if_send_count',
-* 'irq_dis_poll_count' to 'sdla_t'.
-* Nov 06, 1997 Jaspreet Singh Added a define called 'INTR_TEST_MODE'
-* Oct 20, 1997 Jaspreet Singh Added 'buff_intr_mode_unbusy' and
-* 'dlci_intr_mode_unbusy' to 'sdla_t'
-* Oct 18, 1997 Jaspreet Singh Added structure to maintain global driver
-* statistics.
-* Jan 15, 1997 Gene Kozin Version 3.1.0
-* o added UDP management stuff
-* Jan 02, 1997 Gene Kozin Version 3.0.0
-*****************************************************************************/
-#ifndef _WANPIPE_H
-#define _WANPIPE_H
-
-#include <linux/wanrouter.h>
-
-/* Defines */
-
-#ifndef PACKED
-#define PACKED __attribute__((packed))
-#endif
-
-#define WANPIPE_MAGIC 0x414C4453L /* signature: 'SDLA' reversed */
-
-/* IOCTL numbers (up to 16) */
-#define WANPIPE_DUMP (ROUTER_USER+0) /* dump adapter's memory */
-#define WANPIPE_EXEC (ROUTER_USER+1) /* execute firmware command */
-
-#define TRACE_ALL 0x00
-#define TRACE_PROT 0x01
-#define TRACE_DATA 0x02
-
-/* values for request/reply byte */
-#define UDPMGMT_REQUEST 0x01
-#define UDPMGMT_REPLY 0x02
-#define UDP_OFFSET 12
-
-#define MAX_CMD_BUFF 10
-#define MAX_X25_LCN 255 /* Maximum number of x25 channels */
-#define MAX_LCN_NUM 4095 /* Maximum lcn number */
-#define MAX_FT1_RETRY 100
-
-#ifndef AF_WANPIPE
- #define AF_WANPIPE 25
- #ifndef PF_WANPIPE
- #define PF_WANPIPE AF_WANPIPE
- #endif
-#endif
-
-
-#define TX_TIMEOUT 5*HZ
-
-/* General Critical Flags */
-#define SEND_CRIT 0x00
-#define PERI_CRIT 0x01
-
-/* Chdlc and PPP polling critical flag */
-#define POLL_CRIT 0x03
-
-/* Frame Relay Tx IRQ send critical flag */
-#define SEND_TXIRQ_CRIT 0x02
-
-/* Frame Relay ARP critical flag */
-#define ARP_CRIT 0x03
-
-/* Bit maps for dynamic interface configuration
- * DYN_OPT_ON : turns this option on/off
- * DEV_DOWN : device was shutdown by the driver not
- * by user
- */
-#define DYN_OPT_ON 0x00
-#define DEV_DOWN 0x01
-
-/*
- * Data structures for IOCTL calls.
- */
-
-typedef struct sdla_dump /* WANPIPE_DUMP */
-{
- unsigned long magic; /* for verification */
- unsigned long offset; /* absolute adapter memory address */
- unsigned long length; /* block length */
- void* ptr; /* -> buffer */
-} sdla_dump_t;
-
-typedef struct sdla_exec /* WANPIPE_EXEC */
-{
- unsigned long magic; /* for verification */
- void* cmd; /* -> command structure */
- void* data; /* -> data buffer */
-} sdla_exec_t;
-
-/* UDP management stuff */
-
-typedef struct wum_header
-{
- unsigned char signature[8]; /* 00h: signature */
- unsigned char type; /* 08h: request/reply */
- unsigned char command; /* 09h: commnand */
- unsigned char reserved[6]; /* 0Ah: reserved */
-} wum_header_t;
-
-/*************************************************************************
- Data Structure for global statistics
-*************************************************************************/
-
-typedef struct global_stats
-{
- unsigned long isr_entry;
- unsigned long isr_already_critical;
- unsigned long isr_rx;
- unsigned long isr_tx;
- unsigned long isr_intr_test;
- unsigned long isr_spurious;
- unsigned long isr_enable_tx_int;
- unsigned long rx_intr_corrupt_rx_bfr;
- unsigned long rx_intr_on_orphaned_DLCI;
- unsigned long rx_intr_dev_not_started;
- unsigned long tx_intr_dev_not_started;
- unsigned long poll_entry;
- unsigned long poll_already_critical;
- unsigned long poll_processed;
- unsigned long poll_tbusy_bad_status;
- unsigned long poll_host_disable_irq;
- unsigned long poll_host_enable_irq;
-
-} global_stats_t;
-
-
-typedef struct{
- unsigned short udp_src_port PACKED;
- unsigned short udp_dst_port PACKED;
- unsigned short udp_length PACKED;
- unsigned short udp_checksum PACKED;
-} udp_pkt_t;
-
-
-typedef struct {
- unsigned char ver_inet_hdr_length PACKED;
- unsigned char service_type PACKED;
- unsigned short total_length PACKED;
- unsigned short identifier PACKED;
- unsigned short flags_frag_offset PACKED;
- unsigned char ttl PACKED;
- unsigned char protocol PACKED;
- unsigned short hdr_checksum PACKED;
- unsigned long ip_src_address PACKED;
- unsigned long ip_dst_address PACKED;
-} ip_pkt_t;
-
-
-typedef struct {
- unsigned char signature[8] PACKED;
- unsigned char request_reply PACKED;
- unsigned char id PACKED;
- unsigned char reserved[6] PACKED;
-} wp_mgmt_t;
-
-/*************************************************************************
- Data Structure for if_send statistics
-*************************************************************************/
-typedef struct if_send_stat{
- unsigned long if_send_entry;
- unsigned long if_send_skb_null;
- unsigned long if_send_broadcast;
- unsigned long if_send_multicast;
- unsigned long if_send_critical_ISR;
- unsigned long if_send_critical_non_ISR;
- unsigned long if_send_tbusy;
- unsigned long if_send_tbusy_timeout;
- unsigned long if_send_PIPE_request;
- unsigned long if_send_wan_disconnected;
- unsigned long if_send_dlci_disconnected;
- unsigned long if_send_no_bfrs;
- unsigned long if_send_adptr_bfrs_full;
- unsigned long if_send_bfr_passed_to_adptr;
- unsigned long if_send_protocol_error;
- unsigned long if_send_bfr_not_passed_to_adptr;
- unsigned long if_send_tx_int_enabled;
- unsigned long if_send_consec_send_fail;
-} if_send_stat_t;
-
-typedef struct rx_intr_stat{
- unsigned long rx_intr_no_socket;
- unsigned long rx_intr_dev_not_started;
- unsigned long rx_intr_PIPE_request;
- unsigned long rx_intr_bfr_not_passed_to_stack;
- unsigned long rx_intr_bfr_passed_to_stack;
-} rx_intr_stat_t;
-
-typedef struct pipe_mgmt_stat{
- unsigned long UDP_PIPE_mgmt_kmalloc_err;
- unsigned long UDP_PIPE_mgmt_direction_err;
- unsigned long UDP_PIPE_mgmt_adptr_type_err;
- unsigned long UDP_PIPE_mgmt_adptr_cmnd_OK;
- unsigned long UDP_PIPE_mgmt_adptr_cmnd_timeout;
- unsigned long UDP_PIPE_mgmt_adptr_send_passed;
- unsigned long UDP_PIPE_mgmt_adptr_send_failed;
- unsigned long UDP_PIPE_mgmt_not_passed_to_stack;
- unsigned long UDP_PIPE_mgmt_passed_to_stack;
- unsigned long UDP_PIPE_mgmt_no_socket;
- unsigned long UDP_PIPE_mgmt_passed_to_adptr;
-} pipe_mgmt_stat_t;
-
-
-typedef struct {
- struct sk_buff *skb;
-} bh_data_t, cmd_data_t;
-
-#define MAX_LGTH_UDP_MGNT_PKT 2000
-
-
-/* This is used for interrupt testing */
-#define INTR_TEST_MODE 0x02
-
-#define WUM_SIGNATURE_L 0x50495046
-#define WUM_SIGNATURE_H 0x444E3845
-
-#define WUM_KILL 0x50
-#define WUM_EXEC 0x51
-
-#define WANPIPE 0x00
-#define API 0x01
-#define BRIDGE 0x02
-#define BRIDGE_NODE 0x03
-
-#ifdef __KERNEL__
-/****** Kernel Interface ****************************************************/
-
-#include <linux/sdladrv.h> /* SDLA support module API definitions */
-#include <linux/sdlasfm.h> /* SDLA firmware module definitions */
-#include <linux/workqueue.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <asm/serial.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-
-/****** Data Structures *****************************************************/
-
-/* Adapter Data Space.
- * This structure is needed because we handle multiple cards, otherwise
- * static data would do it.
- */
-typedef struct sdla
-{
- char devname[WAN_DRVNAME_SZ+1]; /* card name */
- sdlahw_t hw; /* hardware configuration */
- struct wan_device wandev; /* WAN device data space */
-
- unsigned open_cnt; /* number of open interfaces */
- unsigned long state_tick; /* link state timestamp */
- unsigned intr_mode; /* Type of Interrupt Mode */
- char in_isr; /* interrupt-in-service flag */
- char buff_int_mode_unbusy; /* flag for carrying out dev_tint */
- char dlci_int_mode_unbusy; /* flag for carrying out dev_tint */
- long configured; /* flag for previous configurations */
-
- unsigned short irq_dis_if_send_count; /* Disabling irqs in if_send*/
- unsigned short irq_dis_poll_count; /* Disabling irqs in poll routine*/
- unsigned short force_enable_irq;
- char TracingEnabled; /* flag for enabling trace */
- global_stats_t statistics; /* global statistics */
- void* mbox; /* -> mailbox */
- void* rxmb; /* -> receive mailbox */
- void* flags; /* -> adapter status flags */
- void (*isr)(struct sdla* card); /* interrupt service routine */
- void (*poll)(struct sdla* card); /* polling routine */
- int (*exec)(struct sdla* card, void* u_cmd, void* u_data);
- /* Used by the listen() system call */
- /* Wanpipe Socket Interface */
- int (*func) (struct sk_buff *, struct sock *);
- struct sock *sk;
-
- /* Shutdown function */
- void (*disable_comm) (struct sdla *card);
-
- /* Secondary Port Device: Piggibacking */
- struct sdla *next;
-
- /* TTY driver variables */
- unsigned char tty_opt;
- struct tty_struct *tty;
- unsigned int tty_minor;
- unsigned int tty_open;
- unsigned char *tty_buf;
- unsigned char *tty_rx;
- struct work_struct tty_work;
-
- union
- {
- struct
- { /****** X.25 specific data **********/
- u32 lo_pvc;
- u32 hi_pvc;
- u32 lo_svc;
- u32 hi_svc;
- struct net_device *svc_to_dev_map[MAX_X25_LCN];
- struct net_device *pvc_to_dev_map[MAX_X25_LCN];
- struct net_device *tx_dev;
- struct net_device *cmd_dev;
- u32 no_dev;
- volatile u8 *hdlc_buf_status;
- u32 tx_interrupts_pending;
- u16 timer_int_enabled;
- struct net_device *poll_device;
- atomic_t command_busy;
-
- u16 udp_pkt_lgth;
- u32 udp_type;
- u8 udp_pkt_src;
- u32 udp_lcn;
- struct net_device *udp_dev;
- s8 udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
-
- u8 LAPB_hdlc; /* Option to turn off X25 and run only LAPB */
- u8 logging; /* Option to log call messages */
- u8 oob_on_modem; /* Option to send modem status to the api */
- u16 num_of_ch; /* Number of channels configured by the user */
-
- struct work_struct x25_poll_work;
- struct timer_list x25_timer;
- } x;
- struct
- { /****** frame relay specific data ***/
- void* rxmb_base; /* -> first Rx buffer */
- void* rxmb_last; /* -> last Rx buffer */
- unsigned rx_base; /* S508 receive buffer base */
- unsigned rx_top; /* S508 receive buffer end */
- unsigned short node_dlci[100];
- unsigned short dlci_num;
- struct net_device *dlci_to_dev_map[991 + 1];
- unsigned tx_interrupts_pending;
- unsigned short timer_int_enabled;
- unsigned short udp_pkt_lgth;
- int udp_type;
- char udp_pkt_src;
- unsigned udp_dlci;
- char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
- void* trc_el_base; /* first trace element */
- void* trc_el_last; /* last trace element */
- void *curr_trc_el; /* current trace element */
- unsigned short trc_bfr_space; /* trace buffer space */
- unsigned char update_comms_stats;
- struct net_device *arp_dev;
- spinlock_t if_send_lock;
- } f;
- struct /****** PPP-specific data ***********/
- {
- char if_name[WAN_IFNAME_SZ+1]; /* interface name */
- void* txbuf; /* -> current Tx buffer */
- void* txbuf_base; /* -> first Tx buffer */
- void* txbuf_last; /* -> last Tx buffer */
- void* rxbuf_base; /* -> first Rx buffer */
- void* rxbuf_last; /* -> last Rx buffer */
- unsigned rx_base; /* S508 receive buffer base */
- unsigned rx_top; /* S508 receive buffer end */
- char ip_mode; /* STATIC/HOST/PEER IP Mode */
- char authenticator; /* Authenticator for PAP/CHAP */
- unsigned char comm_enabled; /* Is comm enabled or not */
- unsigned char peer_route; /* Process Peer Route */
- unsigned long *txbuf_next; /* Next Tx buffer to use */
- unsigned long *rxbuf_next; /* Next Rx buffer to use */
- } p;
- struct /* Cisco HDLC-specific data */
- {
- char if_name[WAN_IFNAME_SZ+1]; /* interface name */
- unsigned char comm_port;/* Communication Port O or 1 */
- unsigned char usedby; /* Used by WANPIPE or API */
- void* rxmb; /* Receive mail box */
- void* flags; /* flags */
- void* tx_status; /* Tx status element */
- void* rx_status; /* Rx status element */
- void* txbuf; /* -> current Tx buffer */
- void* txbuf_base; /* -> first Tx buffer */
- void* txbuf_last; /* -> last Tx buffer */
- void* rxbuf_base; /* -> first Rx buffer */
- void* rxbuf_last; /* -> last Rx buffer */
- unsigned rx_base; /* S508 receive buffer base */
- unsigned rx_top; /* S508 receive buffer end */
- unsigned char receive_only; /* high speed receivers */
- unsigned short protocol_options;
- unsigned short kpalv_tx; /* Tx kpalv timer */
- unsigned short kpalv_rx; /* Rx kpalv timer */
- unsigned short kpalv_err; /* Error tolerance */
- unsigned short slarp_timer; /* SLARP req timer */
- unsigned state; /* state of the link */
- unsigned char api_status;
- unsigned char update_call_count;
- unsigned short api_options; /* for async config */
- unsigned char async_mode;
- unsigned short tx_bits_per_char;
- unsigned short rx_bits_per_char;
- unsigned short stop_bits;
- unsigned short parity;
- unsigned short break_timer;
- unsigned short inter_char_timer;
- unsigned short rx_complete_length;
- unsigned short xon_char;
- unsigned short xoff_char;
- unsigned char comm_enabled; /* Is comm enabled or not */
- unsigned char backup;
- } c;
- struct
- {
- void* tx_status; /* Tx status element */
- void* rx_status; /* Rx status element */
- void* trace_status; /* Trace status element */
- void* txbuf; /* -> current Tx buffer */
- void* txbuf_base; /* -> first Tx buffer */
- void* txbuf_last; /* -> last Tx buffer */
- void* rxbuf_base; /* -> first Rx buffer */
- void* rxbuf_last; /* -> last Rx buffer */
- void* tracebuf; /* -> current Trace buffer */
- void* tracebuf_base; /* -> current Trace buffer */
- void* tracebuf_last; /* -> current Trace buffer */
- unsigned rx_base; /* receive buffer base */
- unsigned rx_end; /* receive buffer end */
- unsigned trace_base; /* trace buffer base */
- unsigned trace_end; /* trace buffer end */
-
- } h;
- } u;
-} sdla_t;
-
-/****** Public Functions ****************************************************/
-
-void wanpipe_open (sdla_t* card); /* wpmain.c */
-void wanpipe_close (sdla_t* card); /* wpmain.c */
-void wanpipe_set_state (sdla_t* card, int state); /* wpmain.c */
-
-int wpx_init (sdla_t* card, wandev_conf_t* conf); /* wpx.c */
-int wpf_init (sdla_t* card, wandev_conf_t* conf); /* wpf.c */
-int wpp_init (sdla_t* card, wandev_conf_t* conf); /* wpp.c */
-int wpc_init (sdla_t* card, wandev_conf_t* conf); /* Cisco HDLC */
-int bsc_init (sdla_t* card, wandev_conf_t* conf); /* BSC streaming */
-int hdlc_init(sdla_t* card, wandev_conf_t* conf); /* HDLC support */
-int wpft1_init (sdla_t* card, wandev_conf_t* conf); /* FT1 Config support */
-int wsppp_init (sdla_t* card, wandev_conf_t* conf); /* Sync PPP on top of RAW CHDLC */
-
-extern sdla_t * wanpipe_find_card(char *);
-extern sdla_t * wanpipe_find_card_num (int);
-
-extern void wanpipe_queue_work (struct work_struct *);
-extern void wanpipe_mark_bh (void);
-extern void wakeup_sk_bh(struct net_device *dev);
-extern int change_dev_flags(struct net_device *dev, unsigned flags);
-extern unsigned long get_ip_address(struct net_device *dev, int option);
-extern void add_gateway(sdla_t *card, struct net_device *dev);
-
-
-#endif /* __KERNEL__ */
-#endif /* _WANPIPE_H */
-
diff --git a/include/linux/x1205.h b/include/linux/x1205.h
deleted file mode 100644
index 64fd3af894a..00000000000
--- a/include/linux/x1205.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * x1205.h - defines for drivers/i2c/chips/x1205.c
- * Copyright 2004 Karen Spearel
- * Copyright 2005 Alessandro Zummo
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __LINUX_X1205_H__
-#define __LINUX_X1205_H__
-
-/* commands */
-
-#define X1205_CMD_GETDATETIME 0
-#define X1205_CMD_SETTIME 1
-#define X1205_CMD_SETDATETIME 2
-#define X1205_CMD_GETALARM 3
-#define X1205_CMD_SETALARM 4
-#define X1205_CMD_GETDTRIM 5
-#define X1205_CMD_SETDTRIM 6
-#define X1205_CMD_GETATRIM 7
-#define X1205_CMD_SETATRIM 8
-
-extern int x1205_do_command(unsigned int cmd, void *arg);
-extern int x1205_direct_attach(int adapter_id,
- struct i2c_client_address_data *address_data);
-
-#endif /* __LINUX_X1205_H__ */
diff --git a/include/media/cx25840.h b/include/media/cx25840.h
new file mode 100644
index 00000000000..8e7e52d659a
--- /dev/null
+++ b/include/media/cx25840.h
@@ -0,0 +1,64 @@
+/*
+ cx25840.h - definition for cx25840/1/2/3 inputs
+
+ Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+ This program is free software; 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 _CX25840_H_
+#define _CX25840_H_
+
+enum cx25840_video_input {
+ /* Composite video inputs In1-In8 */
+ CX25840_COMPOSITE1 = 1,
+ CX25840_COMPOSITE2,
+ CX25840_COMPOSITE3,
+ CX25840_COMPOSITE4,
+ CX25840_COMPOSITE5,
+ CX25840_COMPOSITE6,
+ CX25840_COMPOSITE7,
+ CX25840_COMPOSITE8,
+
+ /* S-Video inputs consist of one luma input (In1-In4) ORed with one
+ chroma input (In5-In8) */
+ CX25840_SVIDEO_LUMA1 = 0x10,
+ CX25840_SVIDEO_LUMA2 = 0x20,
+ CX25840_SVIDEO_LUMA3 = 0x30,
+ CX25840_SVIDEO_LUMA4 = 0x40,
+ CX25840_SVIDEO_CHROMA4 = 0x400,
+ CX25840_SVIDEO_CHROMA5 = 0x500,
+ CX25840_SVIDEO_CHROMA6 = 0x600,
+ CX25840_SVIDEO_CHROMA7 = 0x700,
+ CX25840_SVIDEO_CHROMA8 = 0x800,
+
+ /* S-Video aliases for common luma/chroma combinations */
+ CX25840_SVIDEO1 = 0x510,
+ CX25840_SVIDEO2 = 0x620,
+ CX25840_SVIDEO3 = 0x730,
+ CX25840_SVIDEO4 = 0x840,
+};
+
+enum cx25840_audio_input {
+ /* Audio inputs: serial or In4-In8 */
+ CX25840_AUDIO_SERIAL,
+ CX25840_AUDIO4 = 4,
+ CX25840_AUDIO5,
+ CX25840_AUDIO6,
+ CX25840_AUDIO7,
+ CX25840_AUDIO8,
+};
+
+#endif
diff --git a/include/media/msp3400.h b/include/media/msp3400.h
index 0be61a021d4..6ab854931c0 100644
--- a/include/media/msp3400.h
+++ b/include/media/msp3400.h
@@ -80,16 +80,16 @@
*/
/* SCART input to DSP selection */
-#define MSP_IN_SCART_1 0 /* Pin SC1_IN */
-#define MSP_IN_SCART_2 1 /* Pin SC2_IN */
-#define MSP_IN_SCART_3 2 /* Pin SC3_IN */
-#define MSP_IN_SCART_4 3 /* Pin SC4_IN */
+#define MSP_IN_SCART1 0 /* Pin SC1_IN */
+#define MSP_IN_SCART2 1 /* Pin SC2_IN */
+#define MSP_IN_SCART3 2 /* Pin SC3_IN */
+#define MSP_IN_SCART4 3 /* Pin SC4_IN */
#define MSP_IN_MONO 6 /* Pin MONO_IN */
#define MSP_IN_MUTE 7 /* Mute DSP input */
#define MSP_SCART_TO_DSP(in) (in)
/* Tuner input to demodulator and DSP selection */
-#define MSP_IN_TUNER_1 0 /* Analog Sound IF input pin ANA_IN1 */
-#define MSP_IN_TUNER_2 1 /* Analog Sound IF input pin ANA_IN2 */
+#define MSP_IN_TUNER1 0 /* Analog Sound IF input pin ANA_IN1 */
+#define MSP_IN_TUNER2 1 /* Analog Sound IF input pin ANA_IN2 */
#define MSP_TUNER_TO_DSP(in) ((in) << 3)
/* The msp has up to 5 DSP outputs, each output can independently select
@@ -109,14 +109,14 @@
DSP. This is currently not implemented. Also not implemented is the
multi-channel capable I2S3 input of the 44x0G. If someone can demonstrate
a need for one of those features then additional support can be added. */
-#define MSP_DSP_OUT_TUNER 0 /* Tuner output */
-#define MSP_DSP_OUT_SCART 2 /* SCART output */
-#define MSP_DSP_OUT_I2S1 5 /* I2S1 output */
-#define MSP_DSP_OUT_I2S2 6 /* I2S2 output */
-#define MSP_DSP_OUT_I2S3 7 /* I2S3 output */
-#define MSP_DSP_OUT_MAIN_AVC 11 /* MAIN AVC processed output */
-#define MSP_DSP_OUT_MAIN 12 /* MAIN output */
-#define MSP_DSP_OUT_AUX 13 /* AUX output */
+#define MSP_DSP_IN_TUNER 0 /* Tuner DSP input */
+#define MSP_DSP_IN_SCART 2 /* SCART DSP input */
+#define MSP_DSP_IN_I2S1 5 /* I2S1 DSP input */
+#define MSP_DSP_IN_I2S2 6 /* I2S2 DSP input */
+#define MSP_DSP_IN_I2S3 7 /* I2S3 DSP input */
+#define MSP_DSP_IN_MAIN_AVC 11 /* MAIN AVC processed DSP input */
+#define MSP_DSP_IN_MAIN 12 /* MAIN DSP input */
+#define MSP_DSP_IN_AUX 13 /* AUX DSP input */
#define MSP_DSP_TO_MAIN(in) ((in) << 4)
#define MSP_DSP_TO_AUX(in) ((in) << 8)
#define MSP_DSP_TO_SCART1(in) ((in) << 12)
@@ -125,16 +125,16 @@
/* Output SCART select: the SCART outputs can select which input
to use. */
-#define MSP_OUT_SCART1 0 /* SCART1 input, bypassing the DSP */
-#define MSP_OUT_SCART2 1 /* SCART2 input, bypassing the DSP */
-#define MSP_OUT_SCART3 2 /* SCART3 input, bypassing the DSP */
-#define MSP_OUT_SCART4 3 /* SCART4 input, bypassing the DSP */
-#define MSP_OUT_SCART1_DA 4 /* DSP SCART1 output */
-#define MSP_OUT_SCART2_DA 5 /* DSP SCART2 output */
-#define MSP_OUT_MONO 6 /* MONO input, bypassing the DSP */
-#define MSP_OUT_MUTE 7 /* MUTE output */
-#define MSP_OUT_TO_SCART1(in) (in)
-#define MSP_OUT_TO_SCART2(in) ((in) << 4)
+#define MSP_SC_IN_SCART1 0 /* SCART1 input, bypassing the DSP */
+#define MSP_SC_IN_SCART2 1 /* SCART2 input, bypassing the DSP */
+#define MSP_SC_IN_SCART3 2 /* SCART3 input, bypassing the DSP */
+#define MSP_SC_IN_SCART4 3 /* SCART4 input, bypassing the DSP */
+#define MSP_SC_IN_DSP_SCART1 4 /* DSP SCART1 input */
+#define MSP_SC_IN_DSP_SCART2 5 /* DSP SCART2 input */
+#define MSP_SC_IN_MONO 6 /* MONO input, bypassing the DSP */
+#define MSP_SC_IN_MUTE 7 /* MUTE output */
+#define MSP_SC_TO_SCART1(in) (in)
+#define MSP_SC_TO_SCART2(in) ((in) << 4)
/* Shortcut macros */
#define MSP_INPUT(sc, t, main_aux_src, sc_i2s_src) \
@@ -145,14 +145,14 @@
MSP_DSP_TO_SCART1(sc_i2s_src) | \
MSP_DSP_TO_SCART2(sc_i2s_src) | \
MSP_DSP_TO_I2S(sc_i2s_src))
-#define MSP_INPUT_DEFAULT MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1, \
- MSP_DSP_OUT_TUNER, MSP_DSP_OUT_TUNER)
+#define MSP_INPUT_DEFAULT MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \
+ MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER)
#define MSP_OUTPUT(sc) \
- (MSP_OUT_TO_SCART1(sc) | \
- MSP_OUT_TO_SCART2(sc))
+ (MSP_SC_TO_SCART1(sc) | \
+ MSP_SC_TO_SCART2(sc))
/* This equals the RESET position of the msp3400 ACB register */
-#define MSP_OUTPUT_DEFAULT (MSP_OUT_TO_SCART1(MSP_OUT_SCART3) | \
- MSP_OUT_TO_SCART2(MSP_OUT_SCART1_DA))
+#define MSP_OUTPUT_DEFAULT (MSP_SC_TO_SCART1(MSP_SC_IN_SCART3) | \
+ MSP_SC_TO_SCART2(MSP_SC_IN_DSP_SCART1))
/* Tuner inputs vs. msp version */
/* Chip TUNER_1 TUNER_2
diff --git a/include/media/saa7115.h b/include/media/saa7115.h
new file mode 100644
index 00000000000..6b4836f3f05
--- /dev/null
+++ b/include/media/saa7115.h
@@ -0,0 +1,37 @@
+/*
+ saa7115.h - definition for saa7113/4/5 inputs
+
+ Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+ This program is free software; 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 _SAA7115_H_
+#define _SAA7115_H_
+
+/* SAA7113/4/5 HW inputs */
+#define SAA7115_COMPOSITE0 0
+#define SAA7115_COMPOSITE1 1
+#define SAA7115_COMPOSITE2 2
+#define SAA7115_COMPOSITE3 3
+#define SAA7115_COMPOSITE4 4 /* not available for the saa7113 */
+#define SAA7115_COMPOSITE5 5 /* not available for the saa7113 */
+#define SAA7115_SVIDEO0 6
+#define SAA7115_SVIDEO1 7
+#define SAA7115_SVIDEO2 8
+#define SAA7115_SVIDEO3 9
+
+#endif
+
diff --git a/include/media/saa7127.h b/include/media/saa7127.h
new file mode 100644
index 00000000000..bbcf862141a
--- /dev/null
+++ b/include/media/saa7127.h
@@ -0,0 +1,41 @@
+/*
+ saa7127.h - definition for saa7126/7/8/9 inputs/outputs
+
+ Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+ This program is free software; 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 _SAA7127_H_
+#define _SAA7127_H_
+
+/* Enumeration for the supported input types */
+enum saa7127_input_type {
+ SAA7127_INPUT_TYPE_NORMAL,
+ SAA7127_INPUT_TYPE_TEST_IMAGE
+};
+
+/* Enumeration for the supported output signal types */
+enum saa7127_output_type {
+ SAA7127_OUTPUT_TYPE_BOTH,
+ SAA7127_OUTPUT_TYPE_COMPOSITE,
+ SAA7127_OUTPUT_TYPE_SVIDEO,
+ SAA7127_OUTPUT_TYPE_RGB,
+ SAA7127_OUTPUT_TYPE_YUV_C,
+ SAA7127_OUTPUT_TYPE_YUV_V
+};
+
+#endif
+
diff --git a/include/media/upd64031a.h b/include/media/upd64031a.h
new file mode 100644
index 00000000000..3ad6a32e1bc
--- /dev/null
+++ b/include/media/upd64031a.h
@@ -0,0 +1,40 @@
+/*
+ * upd64031a - NEC Electronics Ghost Reduction input defines
+ *
+ * 2006 by Hans Verkuil (hverkuil@xs4all.nl)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _UPD64031A_H_
+#define _UPD64031A_H_
+
+/* Ghost reduction modes */
+#define UPD64031A_GR_ON 0
+#define UPD64031A_GR_OFF 1
+#define UPD64031A_GR_THROUGH 3
+
+/* Direct 3D/YCS Connection */
+#define UPD64031A_3DYCS_DISABLE (0 << 2)
+#define UPD64031A_3DYCS_COMPOSITE (2 << 2)
+#define UPD64031A_3DYCS_SVIDEO (3 << 2)
+
+/* Composite sync digital separation circuit */
+#define UPD64031A_COMPOSITE_EXTERNAL (1 << 4)
+
+/* Vertical sync digital separation circuit */
+#define UPD64031A_VERTICAL_EXTERNAL (1 << 5)
+
+#endif
diff --git a/include/media/upd64083.h b/include/media/upd64083.h
new file mode 100644
index 00000000000..59b6f32ba30
--- /dev/null
+++ b/include/media/upd64083.h
@@ -0,0 +1,58 @@
+/*
+ * upd6408x - NEC Electronics 3-Dimensional Y/C separation input defines
+ *
+ * 2006 by Hans Verkuil (hverkuil@xs4all.nl)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _UPD64083_H_
+#define _UPD64083_H_
+
+/* There are two bits of information that the driver needs in order
+ to select the correct routing: the operating mode and the selection
+ of the Y input (external or internal).
+
+ The first two operating modes expect a composite signal on the Y input,
+ the second two operating modes use both the Y and C inputs.
+
+ Normally YCS_MODE is used for tuner and composite inputs, and the
+ YCNR mode is used for S-Video inputs.
+
+ The external Y-ADC is selected when the composite input comes from a
+ upd64031a ghost reduction device. If this device is not present, or
+ the input is a S-Video signal, then the internal Y-ADC input should
+ be used. */
+
+/* Operating modes: */
+
+/* YCS mode: Y/C separation (burst locked clocking) */
+#define UPD64083_YCS_MODE 0
+/* YCS+ mode: 2D Y/C separation and YCNR (burst locked clocking) */
+#define UPD64083_YCS_PLUS_MODE 1
+
+/* Note: the following two modes cannot be used in combination with the
+ external Y-ADC. */
+/* MNNR mode: frame comb type YNR+C delay (line locked clocking) */
+#define UPD64083_MNNR_MODE 2
+/* YCNR mode: frame recursive YCNR (burst locked clocking) */
+#define UPD64083_YCNR_MODE 3
+
+/* Select external Y-ADC: this should be set if this device is used in
+ combination with the upd64031a ghost reduction device.
+ Otherwise leave at 0 (use internal Y-ADC). */
+#define UPD64083_EXT_Y_ADC (1 << 2)
+
+#endif
diff --git a/include/net/arp.h b/include/net/arp.h
index a13e30c35f4..643bded9f55 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -10,8 +10,6 @@
extern struct neigh_table arp_tbl;
extern void arp_init(void);
-extern int arp_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt, struct net_device *orig_dev);
extern int arp_find(unsigned char *haddr, struct sk_buff *skb);
extern int arp_ioctl(unsigned int cmd, void __user *arg);
extern void arp_send(int type, int ptype, u32 dest_ip,
diff --git a/include/net/ax25.h b/include/net/ax25.h
index d052b221dbc..5bd99748705 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -145,14 +145,14 @@ enum {
#define AX25_DEF_CONMODE 2 /* Connected mode allowed */
#define AX25_DEF_WINDOW 2 /* Window=2 */
#define AX25_DEF_EWINDOW 32 /* Module-128 Window=32 */
-#define AX25_DEF_T1 (10 * HZ) /* T1=10s */
-#define AX25_DEF_T2 (3 * HZ) /* T2=3s */
-#define AX25_DEF_T3 (300 * HZ) /* T3=300s */
+#define AX25_DEF_T1 10000 /* T1=10s */
+#define AX25_DEF_T2 3000 /* T2=3s */
+#define AX25_DEF_T3 300000 /* T3=300s */
#define AX25_DEF_N2 10 /* N2=10 */
-#define AX25_DEF_IDLE (0 * 60 * HZ) /* Idle=None */
+#define AX25_DEF_IDLE 0 /* Idle=None */
#define AX25_DEF_PACLEN 256 /* Paclen=256 */
#define AX25_DEF_PROTOCOL AX25_PROTO_STD_SIMPLEX /* Standard AX.25 */
-#define AX25_DEF_DS_TIMEOUT (3 * 60 * HZ) /* DAMA timeout 3 minutes */
+#define AX25_DEF_DS_TIMEOUT 180000 /* DAMA timeout 3 minutes */
typedef struct ax25_uid_assoc {
struct hlist_node uid_node;
diff --git a/include/net/compat.h b/include/net/compat.h
index 8662b8f43df..e65cbedb6ab 100644
--- a/include/net/compat.h
+++ b/include/net/compat.h
@@ -3,6 +3,8 @@
#include <linux/config.h>
+struct sock;
+
#if defined(CONFIG_COMPAT)
#include <linux/compat.h>
@@ -23,7 +25,6 @@ struct compat_cmsghdr {
compat_int_t cmsg_type;
};
-struct sock;
extern int compat_sock_get_timestamp(struct sock *, struct timeval __user *);
#else /* defined(CONFIG_COMPAT) */
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 4725ff861c5..d5926bfb1fc 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -955,11 +955,13 @@ enum ieee80211_state {
#define IEEE80211_24GHZ_MIN_CHANNEL 1
#define IEEE80211_24GHZ_MAX_CHANNEL 14
-#define IEEE80211_24GHZ_CHANNELS 14
+#define IEEE80211_24GHZ_CHANNELS (IEEE80211_24GHZ_MAX_CHANNEL - \
+ IEEE80211_24GHZ_MIN_CHANNEL + 1)
#define IEEE80211_52GHZ_MIN_CHANNEL 34
#define IEEE80211_52GHZ_MAX_CHANNEL 165
-#define IEEE80211_52GHZ_CHANNELS 131
+#define IEEE80211_52GHZ_CHANNELS (IEEE80211_52GHZ_MAX_CHANNEL - \
+ IEEE80211_52GHZ_MIN_CHANNEL + 1)
enum {
IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h
index b971d8c82bd..052ed596a4e 100644
--- a/include/net/ieee80211softmac.h
+++ b/include/net/ieee80211softmac.h
@@ -96,10 +96,13 @@ struct ieee80211softmac_assoc_info {
*
* bssvalid is true if we found a matching network
* and saved it's BSSID into the bssid above.
+ *
+ * bssfixed is used for SIOCSIWAP.
*/
u8 static_essid:1,
associating:1,
- bssvalid:1;
+ bssvalid:1,
+ bssfixed:1;
/* Scan retries remaining */
int scan_retry;
@@ -201,7 +204,8 @@ struct ieee80211softmac_device {
/* couple of flags */
u8 scanning:1, /* protects scanning from being done multiple times at once */
- associated:1;
+ associated:1,
+ running:1;
struct ieee80211softmac_scaninfo *scaninfo;
struct ieee80211softmac_assoc_info associnfo;
@@ -267,8 +271,9 @@ extern void ieee80211softmac_stop(struct net_device *dev);
#define IEEE80211SOFTMAC_EVENT_AUTH_FAILED 5
#define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT 6
#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND 7
+#define IEEE80211SOFTMAC_EVENT_DISASSOCIATED 8
/* keep this updated! */
-#define IEEE80211SOFTMAC_EVENT_LAST 7
+#define IEEE80211SOFTMAC_EVENT_LAST 8
/*
* If you want to be notified of certain events, you can call
* ieee80211softmac_notify[_atomic] with
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index 25f708ff020..59f0c83d55a 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -48,31 +48,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk)
return inet6_ehashfn(laddr, lport, faddr, fport);
}
-static inline void __inet6_hash(struct inet_hashinfo *hashinfo,
- struct sock *sk)
-{
- struct hlist_head *list;
- rwlock_t *lock;
-
- BUG_TRAP(sk_unhashed(sk));
-
- if (sk->sk_state == TCP_LISTEN) {
- list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
- lock = &hashinfo->lhash_lock;
- inet_listen_wlock(hashinfo);
- } else {
- unsigned int hash;
- sk->sk_hash = hash = inet6_sk_ehashfn(sk);
- hash &= (hashinfo->ehash_size - 1);
- list = &hashinfo->ehash[hash].chain;
- lock = &hashinfo->ehash[hash].lock;
- write_lock(lock);
- }
-
- __sk_add_node(sk, list);
- sock_prot_inc_use(sk->sk_prot);
- write_unlock(lock);
-}
+extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
/*
* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
@@ -80,52 +56,12 @@ static inline void __inet6_hash(struct inet_hashinfo *hashinfo,
*
* The sockhash lock must be held as a reader here.
*/
-static inline struct sock *
- __inet6_lookup_established(struct inet_hashinfo *hashinfo,
+extern struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr,
const u16 sport,
const struct in6_addr *daddr,
const u16 hnum,
- const int dif)
-{
- struct sock *sk;
- const struct hlist_node *node;
- const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
- /* Optimize here for direct hit, only listening connections can
- * have wildcards anyways.
- */
- unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
- struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
-
- prefetch(head->chain.first);
- read_lock(&head->lock);
- sk_for_each(sk, node, &head->chain) {
- /* For IPV6 do the cheaper port and family tests first. */
- if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
- goto hit; /* You sunk my battleship! */
- }
- /* Must check for a TIME_WAIT'er before going to listener hash. */
- sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
- const struct inet_timewait_sock *tw = inet_twsk(sk);
-
- if(*((__u32 *)&(tw->tw_dport)) == ports &&
- sk->sk_family == PF_INET6) {
- const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
-
- if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) &&
- ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
- (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
- goto hit;
- }
- }
- read_unlock(&head->lock);
- return NULL;
-
-hit:
- sock_hold(sk);
- read_unlock(&head->lock);
- return sk;
-}
+ const int dif);
extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
const struct in6_addr *daddr,
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 1da294c4752..e837f98fdb5 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -150,7 +150,7 @@ static inline void inet_twsk_add_bind_node(struct inet_timewait_sock *tw,
static inline int inet_twsk_dead_hashed(const struct inet_timewait_sock *tw)
{
- return tw->tw_death_node.pprev != NULL;
+ return !hlist_unhashed(&tw->tw_death_node);
}
static inline void inet_twsk_dead_node_init(struct inet_timewait_sock *tw)
diff --git a/include/net/ip.h b/include/net/ip.h
index 8fe6156ca9b..3d2e5ca62a5 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -95,6 +95,7 @@ extern int ip_local_deliver(struct sk_buff *skb);
extern int ip_mr_input(struct sk_buff *skb);
extern int ip_output(struct sk_buff *skb);
extern int ip_mc_output(struct sk_buff *skb);
+extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
extern int ip_do_nat(struct sk_buff *skb);
extern void ip_send_check(struct iphdr *ip);
extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 6d6f0634ae4..4abedb8eaec 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -230,7 +230,7 @@ extern int ip6_ra_control(struct sock *sk, int sel,
void (*destructor)(struct sock *));
-extern int ipv6_parse_hopopts(struct sk_buff *skb, int);
+extern int ipv6_parse_hopopts(struct sk_buff *skb);
extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h
index 86aefb1fda5..c0c895d379b 100644
--- a/include/net/irda/irlmp.h
+++ b/include/net/irda/irlmp.h
@@ -112,7 +112,7 @@ struct lsap_cb {
struct timer_list watchdog_timer;
- IRLMP_STATE lsap_state; /* Connection state */
+ LSAP_STATE lsap_state; /* Connection state */
notify_t notify; /* Indication/Confirm entry points */
struct qos_info qos; /* QoS for this connection */
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index b0666d66293..4901ee44687 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -211,6 +211,7 @@ struct neigh_table
#define NEIGH_UPDATE_F_ADMIN 0x80000000
extern void neigh_table_init(struct neigh_table *tbl);
+extern void neigh_table_init_no_netlink(struct neigh_table *tbl);
extern int neigh_table_clear(struct neigh_table *tbl);
extern struct neighbour * neigh_lookup(struct neigh_table *tbl,
const void *pkey,
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index b6f0905a4ee..916013ca4a5 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -300,29 +300,30 @@ DECLARE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
#define CONNTRACK_ECACHE(x) (__get_cpu_var(nf_conntrack_ecache).x)
-extern struct notifier_block *nf_conntrack_chain;
-extern struct notifier_block *nf_conntrack_expect_chain;
+extern struct atomic_notifier_head nf_conntrack_chain;
+extern struct atomic_notifier_head nf_conntrack_expect_chain;
static inline int nf_conntrack_register_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&nf_conntrack_chain, nb);
+ return atomic_notifier_chain_register(&nf_conntrack_chain, nb);
}
static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&nf_conntrack_chain, nb);
+ return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb);
}
static inline int
nf_conntrack_expect_register_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&nf_conntrack_expect_chain, nb);
+ return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb);
}
static inline int
nf_conntrack_expect_unregister_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&nf_conntrack_expect_chain, nb);
+ return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain,
+ nb);
}
extern void nf_ct_deliver_cached_events(const struct nf_conn *ct);
@@ -347,14 +348,14 @@ static inline void nf_conntrack_event(enum ip_conntrack_events event,
struct nf_conn *ct)
{
if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
- notifier_call_chain(&nf_conntrack_chain, event, ct);
+ atomic_notifier_call_chain(&nf_conntrack_chain, event, ct);
}
static inline void
nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
struct nf_conntrack_expect *exp)
{
- notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
+ atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
}
#else /* CONFIG_NF_CONNTRACK_EVENTS */
static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
diff --git a/include/net/netrom.h b/include/net/netrom.h
index a5ee53bce62..e0ca112024a 100644
--- a/include/net/netrom.h
+++ b/include/net/netrom.h
@@ -42,11 +42,11 @@ enum {
#define NR_COND_PEER_RX_BUSY 0x04
#define NR_COND_OWN_RX_BUSY 0x08
-#define NR_DEFAULT_T1 (120 * HZ) /* Outstanding frames - 120 seconds */
-#define NR_DEFAULT_T2 (5 * HZ) /* Response delay - 5 seconds */
+#define NR_DEFAULT_T1 120000 /* Outstanding frames - 120 seconds */
+#define NR_DEFAULT_T2 5000 /* Response delay - 5 seconds */
#define NR_DEFAULT_N2 3 /* Number of Retries - 3 */
-#define NR_DEFAULT_T4 (180 * HZ) /* Busy Delay - 180 seconds */
-#define NR_DEFAULT_IDLE (0 * 60 * HZ) /* No Activity Timeout - none */
+#define NR_DEFAULT_T4 180000 /* Busy Delay - 180 seconds */
+#define NR_DEFAULT_IDLE 0 /* No Activity Timeout - none */
#define NR_DEFAULT_WINDOW 4 /* Default Window Size - 4 */
#define NR_DEFAULT_OBS 6 /* Default Obsolescence Count - 6 */
#define NR_DEFAULT_QUAL 10 /* Default Neighbour Quality - 10 */
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 11641c9384f..c5d7f920c35 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -145,7 +145,7 @@ static inline struct request_sock *
{
struct request_sock *req = queue->rskq_accept_head;
- queue->rskq_accept_head = queue->rskq_accept_head = NULL;
+ queue->rskq_accept_head = NULL;
return req;
}
diff --git a/include/net/rose.h b/include/net/rose.h
index 3249b979605..012b09ed240 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -49,14 +49,14 @@ enum {
ROSE_STATE_5 /* Deferred Call Acceptance */
};
-#define ROSE_DEFAULT_T0 (180 * HZ) /* Default T10 T20 value */
-#define ROSE_DEFAULT_T1 (200 * HZ) /* Default T11 T21 value */
-#define ROSE_DEFAULT_T2 (180 * HZ) /* Default T12 T22 value */
-#define ROSE_DEFAULT_T3 (180 * HZ) /* Default T13 T23 value */
-#define ROSE_DEFAULT_HB (5 * HZ) /* Default Holdback value */
-#define ROSE_DEFAULT_IDLE (0 * 60 * HZ) /* No Activity Timeout - none */
+#define ROSE_DEFAULT_T0 180000 /* Default T10 T20 value */
+#define ROSE_DEFAULT_T1 200000 /* Default T11 T21 value */
+#define ROSE_DEFAULT_T2 180000 /* Default T12 T22 value */
+#define ROSE_DEFAULT_T3 180000 /* Default T13 T23 value */
+#define ROSE_DEFAULT_HB 5000 /* Default Holdback value */
+#define ROSE_DEFAULT_IDLE 0 /* No Activity Timeout - none */
#define ROSE_DEFAULT_ROUTING 1 /* Default routing flag */
-#define ROSE_DEFAULT_FAIL_TIMEOUT (120 * HZ) /* Time until link considered usable */
+#define ROSE_DEFAULT_FAIL_TIMEOUT 120000 /* Time until link considered usable */
#define ROSE_DEFAULT_MAXVC 50 /* Maximum number of VCs per neighbour */
#define ROSE_DEFAULT_WINDOW_SIZE 7 /* Default window size */
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 34a1a09e5ae..807d6f1ef4b 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -99,6 +99,7 @@ typedef enum {
SCTP_CMD_DEL_NON_PRIMARY, /* Removes non-primary peer transports. */
SCTP_CMD_T3_RTX_TIMERS_STOP, /* Stops T3-rtx pending timers */
SCTP_CMD_FORCE_PRIM_RETRAN, /* Forces retrans. over primary path. */
+ SCTP_CMD_SET_SK_ERR, /* Set sk_err */
SCTP_CMD_LAST
} sctp_verb_t;
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index e673b2c984e..aa6033ca7cd 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -461,12 +461,12 @@ static inline int sctp_frag_point(const struct sctp_sock *sp, int pmtu)
* there is room for a param header too.
*/
#define sctp_walk_params(pos, chunk, member)\
-_sctp_walk_params((pos), (chunk), WORD_ROUND(ntohs((chunk)->chunk_hdr.length)), member)
+_sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member)
#define _sctp_walk_params(pos, chunk, end, member)\
for (pos.v = chunk->member;\
pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) &&\
- pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)) &&\
+ pos.v <= (void *)chunk + end - ntohs(pos.p->length) &&\
ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\
pos.v += WORD_ROUND(ntohs(pos.p->length)))
@@ -477,7 +477,7 @@ _sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length))
for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \
sizeof(sctp_chunkhdr_t));\
(void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\
- (void *)err <= (void *)chunk_hdr + end - WORD_ROUND(ntohs(err->length)) &&\
+ (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\
ntohs(err->length) >= sizeof(sctp_errhdr_t); \
err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length))))
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index eba99f37551..7f4fea173fb 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -712,6 +712,7 @@ struct sctp_chunk {
__u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */
__s8 fast_retransmit; /* Is this chunk fast retransmitted? */
__u8 tsn_missing_report; /* Data chunk missing counter. */
+ __u8 data_accepted; /* At least 1 chunk in this packet accepted */
};
void sctp_chunk_hold(struct sctp_chunk *);
diff --git a/include/net/sock.h b/include/net/sock.h
index 2aa73c0ec6c..c9fad6fb629 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -279,7 +279,7 @@ static inline int sk_unhashed(const struct sock *sk)
static inline int sk_hashed(const struct sock *sk)
{
- return sk->sk_node.pprev != NULL;
+ return !sk_unhashed(sk);
}
static __inline__ void sk_node_init(struct hlist_node *node)
@@ -454,6 +454,7 @@ static inline void sk_stream_set_owner_r(struct sk_buff *skb, struct sock *sk)
static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb)
{
+ skb_truesize_check(skb);
sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
sk->sk_wmem_queued -= skb->truesize;
sk->sk_forward_alloc += skb->truesize;
@@ -938,28 +939,7 @@ static inline void sock_put(struct sock *sk)
sk_free(sk);
}
-static inline int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
-{
- int rc = NET_RX_SUCCESS;
-
- if (sk_filter(sk, skb, 0))
- goto discard_and_relse;
-
- skb->dev = NULL;
-
- bh_lock_sock(sk);
- if (!sock_owned_by_user(sk))
- rc = sk->sk_backlog_rcv(sk, skb);
- else
- sk_add_backlog(sk, skb);
- bh_unlock_sock(sk);
-out:
- sock_put(sk);
- return rc;
-discard_and_relse:
- kfree_skb(skb);
- goto out;
-}
+extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb);
/* Detach socket from process context.
* Announce socket dead, detach it from wait queue and inode.
@@ -1044,33 +1024,9 @@ sk_dst_reset(struct sock *sk)
write_unlock(&sk->sk_dst_lock);
}
-static inline struct dst_entry *
-__sk_dst_check(struct sock *sk, u32 cookie)
-{
- struct dst_entry *dst = sk->sk_dst_cache;
-
- if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
- sk->sk_dst_cache = NULL;
- dst_release(dst);
- return NULL;
- }
-
- return dst;
-}
-
-static inline struct dst_entry *
-sk_dst_check(struct sock *sk, u32 cookie)
-{
- struct dst_entry *dst = sk_dst_get(sk);
+extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie);
- if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
- sk_dst_reset(sk);
- dst_release(dst);
- return NULL;
- }
-
- return dst;
-}
+extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie);
static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
{
@@ -1140,45 +1096,7 @@ extern void sk_reset_timer(struct sock *sk, struct timer_list* timer,
extern void sk_stop_timer(struct sock *sk, struct timer_list* timer);
-static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
-{
- int err = 0;
- int skb_len;
-
- /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
- number of warnings when compiling with -W --ANK
- */
- if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
- (unsigned)sk->sk_rcvbuf) {
- err = -ENOMEM;
- goto out;
- }
-
- /* It would be deadlock, if sock_queue_rcv_skb is used
- with socket lock! We assume that users of this
- function are lock free.
- */
- err = sk_filter(sk, skb, 1);
- if (err)
- goto out;
-
- skb->dev = NULL;
- skb_set_owner_r(skb, sk);
-
- /* Cache the SKB length before we tack it onto the receive
- * queue. Once it is added it no longer belongs to us and
- * may be freed by other threads of control pulling packets
- * from the queue.
- */
- skb_len = skb->len;
-
- skb_queue_tail(&sk->sk_receive_queue, skb);
-
- if (!sock_flag(sk, SOCK_DEAD))
- sk->sk_data_ready(sk, skb_len);
-out:
- return err;
-}
+extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
static inline int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
{
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 9418f4d1afb..3c989db8a7a 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -405,9 +405,6 @@ extern int tcp_disconnect(struct sock *sk, int flags);
extern void tcp_unhash(struct sock *sk);
-extern int tcp_v4_hash_connecting(struct sock *sk);
-
-
/* From syncookies.c */
extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
struct ip_options *opt);
diff --git a/include/net/x25device.h b/include/net/x25device.h
index 1a318374fae..1d10c879f7e 100644
--- a/include/net/x25device.h
+++ b/include/net/x25device.h
@@ -8,6 +8,7 @@
static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev)
{
skb->mac.raw = skb->data;
+ skb->dev = dev;
skb->pkt_type = PACKET_HOST;
return htons(ETH_P_X25);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 61b7504fc2b..afa508d92c9 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -143,6 +143,11 @@ struct xfrm_state
/* Replay detection state at the time we sent the last notification */
struct xfrm_replay_state preplay;
+ /* internal flag that only holds state for delayed aevent at the
+ * moment
+ */
+ u32 xflags;
+
/* Replay detection notification settings */
u32 replay_maxage;
u32 replay_maxdiff;
@@ -168,6 +173,9 @@ struct xfrm_state
void *data;
};
+/* xflags - make enum if more show up */
+#define XFRM_TIME_DEFER 1
+
enum {
XFRM_STATE_VOID,
XFRM_STATE_ACQ,
@@ -242,7 +250,6 @@ extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
-struct xfrm_decap_state;
struct xfrm_type
{
char *description;
@@ -251,7 +258,7 @@ struct xfrm_type
int (*init_state)(struct xfrm_state *x);
void (*destructor)(struct xfrm_state *);
- int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
+ int (*input)(struct xfrm_state *, struct sk_buff *skb);
int (*output)(struct xfrm_state *, struct sk_buff *pskb);
/* Estimate maximal size of result of transformation of a dgram */
u32 (*get_max_size)(struct xfrm_state *, int size);
@@ -606,25 +613,11 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
-/* Decapsulation state, used by the input to store data during
- * decapsulation procedure, to be used later (during the policy
- * check
- */
-struct xfrm_decap_state {
- char decap_data[20];
- __u16 decap_type;
-};
-
-struct sec_decap_state {
- struct xfrm_state *xvec;
- struct xfrm_decap_state decap;
-};
-
struct sec_path
{
atomic_t refcnt;
int len;
- struct sec_decap_state x[XFRM_MAX_DEPTH];
+ struct xfrm_state *xvec[XFRM_MAX_DEPTH];
};
static inline struct sec_path *
@@ -864,13 +857,19 @@ struct xfrm_algo_desc {
/* XFRM tunnel handlers. */
struct xfrm_tunnel {
int (*handler)(struct sk_buff *skb);
- void (*err_handler)(struct sk_buff *skb, __u32 info);
+ int (*err_handler)(struct sk_buff *skb, __u32 info);
+
+ struct xfrm_tunnel *next;
+ int priority;
};
struct xfrm6_tunnel {
- int (*handler)(struct sk_buff **pskb);
- void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info);
+ int (*handler)(struct sk_buff *skb);
+ int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int type, int code, int offset, __u32 info);
+
+ struct xfrm6_tunnel *next;
+ int priority;
};
extern void xfrm_init(void);
@@ -906,7 +905,7 @@ extern int xfrm4_rcv(struct sk_buff *skb);
extern int xfrm4_output(struct sk_buff *skb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
-extern int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi);
+extern int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi);
extern int xfrm6_rcv(struct sk_buff **pskb);
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
diff --git a/include/pcmcia/bulkmem.h b/include/pcmcia/bulkmem.h
index b53b78d497b..6bc7472293b 100644
--- a/include/pcmcia/bulkmem.h
+++ b/include/pcmcia/bulkmem.h
@@ -35,7 +35,7 @@ typedef struct region_info_t {
#define REGION_BAR_MASK 0xe000
#define REGION_BAR_SHIFT 13
-int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn);
-int pcmcia_get_next_region(client_handle_t handle, region_info_t *rgn);
+int pcmcia_get_first_region(struct pcmcia_device *handle, region_info_t *rgn);
+int pcmcia_get_next_region(struct pcmcia_device *handle, region_info_t *rgn);
#endif /* _LINUX_BULKMEM_H */
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h
index da19c297dd6..c1da8558339 100644
--- a/include/pcmcia/ciscode.h
+++ b/include/pcmcia/ciscode.h
@@ -1,5 +1,5 @@
/*
- * ciscode.h -- Definitions for bulk memory services
+ * ciscode.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -122,4 +122,7 @@
#define MANFID_XIRCOM 0x0105
+#define MANFID_POSSIO 0x030c
+#define PRODID_POSSIO_GCC 0x0003
+
#endif /* _LINUX_CISCODE_H */
diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h
index c6a069554fd..d3bbb19caf8 100644
--- a/include/pcmcia/cistpl.h
+++ b/include/pcmcia/cistpl.h
@@ -586,12 +586,7 @@ typedef struct cisdump_t {
cisdata_t Data[CISTPL_MAX_CIS_SIZE];
} cisdump_t;
-int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple);
-int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple);
-int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple);
-int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse);
-int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info);
int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis);
/* don't use outside of PCMCIA core yet */
@@ -602,4 +597,20 @@ int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse);
int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_t *info);
+/* ... but use these wrappers instead */
+#define pcmcia_get_first_tuple(p_dev, tuple) \
+ pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple)
+
+#define pcmcia_get_next_tuple(p_dev, tuple) \
+ pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple)
+
+#define pcmcia_get_tuple_data(p_dev, tuple) \
+ pccard_get_tuple_data(p_dev->socket, tuple)
+
+#define pcmcia_parse_tuple(p_dev, tuple, parse) \
+ pccard_parse_tuple(tuple, parse)
+
+#define pcmcia_validate_cis(p_dev, info) \
+ pccard_validate_cis(p_dev->socket, p_dev->func, info)
+
#endif /* LINUX_CISTPL_H */
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 52660f32663..d5838c30d20 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -109,17 +109,6 @@ typedef struct client_req_t {
#define CLIENT_THIS_SOCKET 0x01
-/* For RegisterClient */
-typedef struct client_reg_t {
- dev_info_t *dev_info;
- u_int Attributes; /* UNUSED */
- u_int EventMask;
- int (*event_handler)(event_t event, int priority,
- event_callback_args_t *);
- event_callback_args_t event_callback_args;
- u_int Version;
-} client_reg_t;
-
/* ModifyConfiguration */
typedef struct modconf_t {
u_int Attributes;
@@ -127,15 +116,16 @@ typedef struct modconf_t {
} modconf_t;
/* Attributes for ModifyConfiguration */
-#define CONF_IRQ_CHANGE_VALID 0x100
-#define CONF_VCC_CHANGE_VALID 0x200
-#define CONF_VPP1_CHANGE_VALID 0x400
-#define CONF_VPP2_CHANGE_VALID 0x800
+#define CONF_IRQ_CHANGE_VALID 0x0100
+#define CONF_VCC_CHANGE_VALID 0x0200
+#define CONF_VPP1_CHANGE_VALID 0x0400
+#define CONF_VPP2_CHANGE_VALID 0x0800
+#define CONF_IO_CHANGE_WIDTH 0x1000
/* For RequestConfiguration */
typedef struct config_req_t {
u_int Attributes;
- u_int Vcc, Vpp1, Vpp2;
+ u_int Vpp; /* both Vpp1 and Vpp2 */
u_int IntType;
u_int ConfigBase;
u_char Status, Pin, Copy, ExtStatus;
@@ -389,23 +379,27 @@ int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status);
int pcmcia_get_mem_page(window_handle_t win, memreq_t *req);
int pcmcia_map_mem_page(window_handle_t win, memreq_t *req);
int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
-int pcmcia_release_configuration(struct pcmcia_device *p_dev);
-int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req);
-int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req);
int pcmcia_release_window(window_handle_t win);
int pcmcia_request_configuration(struct pcmcia_device *p_dev, config_req_t *req);
int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req);
int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req);
int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh);
-int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req);
int pcmcia_suspend_card(struct pcmcia_socket *skt);
int pcmcia_resume_card(struct pcmcia_socket *skt);
int pcmcia_eject_card(struct pcmcia_socket *skt);
int pcmcia_insert_card(struct pcmcia_socket *skt);
+int pccard_reset_card(struct pcmcia_socket *skt);
+
+struct pcmcia_device * pcmcia_dev_present(struct pcmcia_device *p_dev);
+void pcmcia_disable_device(struct pcmcia_device *p_dev);
struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt);
void pcmcia_put_socket(struct pcmcia_socket *skt);
+/* compatibility functions */
+#define pcmcia_reset_card(p_dev, req) \
+ pccard_reset_card(p_dev->socket)
+
#endif /* __KERNEL__ */
#endif /* _LINUX_CS_H */
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 8e2a9639647..8c339f5678c 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -39,7 +39,7 @@ typedef struct win_info_t {
typedef struct bind_info_t {
dev_info_t dev_info;
u_char function;
- struct dev_link_t *instance;
+ struct pcmcia_device *instance;
char name[DEV_NAME_LEN];
u_short major, minor;
void *next;
@@ -96,6 +96,7 @@ typedef union ds_ioctl_arg_t {
#ifdef __KERNEL__
#include <linux/device.h>
+#include <pcmcia/ss.h>
typedef struct dev_node_t {
char dev_name[DEV_NAME_LEN];
@@ -103,34 +104,9 @@ typedef struct dev_node_t {
struct dev_node_t *next;
} dev_node_t;
-typedef struct dev_link_t {
- dev_node_t *dev;
- u_int state, open;
- wait_queue_head_t pending;
- client_handle_t handle;
- io_req_t io;
- irq_req_t irq;
- config_req_t conf;
- window_handle_t win;
- void *priv;
- struct dev_link_t *next;
-} dev_link_t;
-
-/* Flags for device state */
-#define DEV_PRESENT 0x01
-#define DEV_CONFIG 0x02
-#define DEV_STALE_CONFIG 0x04 /* release on close */
-#define DEV_STALE_LINK 0x08 /* detach on release */
-#define DEV_CONFIG_PENDING 0x10
-#define DEV_RELEASE_PENDING 0x20
-#define DEV_SUSPEND 0x40
-#define DEV_BUSY 0x80
-
-#define DEV_OK(l) \
- ((l) && ((l->state & ~DEV_BUSY) == (DEV_CONFIG|DEV_PRESENT)))
-
struct pcmcia_socket;
+struct config_t;
struct pcmcia_driver {
int (*probe) (struct pcmcia_device *dev);
@@ -148,6 +124,7 @@ struct pcmcia_driver {
int pcmcia_register_driver(struct pcmcia_driver *driver);
void pcmcia_unregister_driver(struct pcmcia_driver *driver);
+
struct pcmcia_device {
/* the socket and the device_no [for multifunction devices]
uniquely define a pcmcia_device */
@@ -160,21 +137,40 @@ struct pcmcia_device {
/* the hardware "function" device; certain subdevices can
* share one hardware "function" device. */
u8 func;
+ struct config_t* function_config;
struct list_head socket_device_list;
- /* deprecated, a cleaned up version will be moved into this
- struct soon */
- dev_link_t *instance;
- u_int state;
+ /* deprecated, will be cleaned up soon */
+ dev_node_t *dev_node;
+ u_int open;
+ io_req_t io;
+ irq_req_t irq;
+ config_req_t conf;
+ window_handle_t win;
+
+ /* Is the device suspended, or in the process of
+ * being removed? */
+ u16 suspended:1;
+ u16 _removed:1;
+
+ /* Flags whether io, irq, win configurations were
+ * requested, and whether the configuration is "locked" */
+ u16 _irq:1;
+ u16 _io:1;
+ u16 _win:4;
+ u16 _locked:1;
+
+ /* Flag whether a "fuzzy" func_id based match is
+ * allowed. */
+ u16 allow_func_id_match:1;
/* information about this device */
- u8 has_manf_id:1;
- u8 has_card_id:1;
- u8 has_func_id:1;
+ u16 has_manf_id:1;
+ u16 has_card_id:1;
+ u16 has_func_id:1;
- u8 allow_func_id_match:1;
- u8 reserved:4;
+ u16 reserved:3;
u8 func_id;
u16 manf_id;
@@ -182,22 +178,24 @@ struct pcmcia_device {
char * prod_id[4];
+ struct device dev;
+
+#ifdef CONFIG_PCMCIA_IOCTL
/* device driver wanted by cardmgr */
struct pcmcia_driver * cardmgr;
+#endif
- struct device dev;
+ /* data private to drivers */
+ void *priv;
};
#define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev)
#define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv)
-#define handle_to_pdev(handle) (handle)
#define handle_to_dev(handle) (handle->dev)
-#define dev_to_instance(dev) (dev->instance)
-
/* error reporting */
-void cs_error(client_handle_t handle, int func, int ret);
+void cs_error(struct pcmcia_device *handle, int func, int ret);
#endif /* __KERNEL__ */
#endif /* _LINUX_DS_H */
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 2889a69a7a8..5e0a01ab221 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -18,6 +18,7 @@
#include <linux/config.h>
#include <linux/device.h>
#include <linux/sched.h> /* task_struct, completion */
+#include <linux/mutex.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
@@ -146,14 +147,15 @@ extern struct pccard_resource_ops pccard_static_ops;
/* !SS_CAP_STATIC_MAP */
extern struct pccard_resource_ops pccard_nonstatic_ops;
+/* static mem, dynamic IO sockets */
+extern struct pccard_resource_ops pccard_iodyn_ops;
+
/*
* Calls to set up low-level "Socket Services" drivers
*/
struct pcmcia_socket;
typedef struct io_window_t {
- u_int Attributes;
- kio_addr_t BasePort, NumPorts;
kio_addr_t InUse, Config;
struct resource *res;
} io_window_t;
@@ -162,7 +164,7 @@ typedef struct io_window_t {
typedef struct window_t {
u_short magic;
u_short index;
- client_handle_t handle;
+ struct pcmcia_device *handle;
struct pcmcia_socket *sock;
pccard_mem_map ctl;
} window_t;
@@ -186,7 +188,6 @@ struct pcmcia_socket {
u_short lock_count;
pccard_mem_map cis_mem;
void __iomem *cis_virt;
- struct config_t *config;
struct {
u_int AssignedIRQ;
u_int Config;
@@ -241,7 +242,7 @@ struct pcmcia_socket {
#endif
/* state thread */
- struct semaphore skt_sem; /* protects socket h/w state */
+ struct mutex skt_mutex; /* protects socket h/w state */
struct task_struct *thread;
struct completion thread_done;
diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
index 51ab8eddb29..5ff77558013 100644
--- a/include/rdma/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -3,7 +3,7 @@
* Copyright (c) 2004 Infinicon Corporation. All rights reserved.
* Copyright (c) 2004 Intel Corporation. All rights reserved.
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
- * Copyright (c) 2004 Voltaire Corporation. All rights reserved.
+ * Copyright (c) 2004-2006 Voltaire Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -55,6 +55,10 @@
#define IB_MGMT_CLASS_DEVICE_MGMT 0x06
#define IB_MGMT_CLASS_CM 0x07
#define IB_MGMT_CLASS_SNMP 0x08
+#define IB_MGMT_CLASS_DEVICE_ADM 0x10
+#define IB_MGMT_CLASS_BOOT_MGMT 0x11
+#define IB_MGMT_CLASS_BIS 0x12
+#define IB_MGMT_CLASS_CONG_MGMT 0x21
#define IB_MGMT_CLASS_VENDOR_RANGE2_START 0x30
#define IB_MGMT_CLASS_VENDOR_RANGE2_END 0x4F
@@ -117,6 +121,8 @@ enum {
IB_MGMT_VENDOR_DATA = 216,
IB_MGMT_SA_HDR = 56,
IB_MGMT_SA_DATA = 200,
+ IB_MGMT_DEVICE_HDR = 64,
+ IB_MGMT_DEVICE_DATA = 192,
};
struct ib_mad_hdr {
@@ -603,6 +609,25 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
gfp_t gfp_mask);
/**
+ * ib_is_mad_class_rmpp - returns whether given management class
+ * supports RMPP.
+ * @mgmt_class: management class
+ *
+ * This routine returns whether the management class supports RMPP.
+ */
+int ib_is_mad_class_rmpp(u8 mgmt_class);
+
+/**
+ * ib_get_mad_data_offset - returns the data offset for a given
+ * management class.
+ * @mgmt_class: management class
+ *
+ * This routine returns the data offset in the MAD for the management
+ * class requested.
+ */
+int ib_get_mad_data_offset(u8 mgmt_class);
+
+/**
* ib_get_rmpp_segment - returns the data buffer for a given RMPP segment.
* @send_buf: Previously allocated send data buffer.
* @seg_num: number of segment to return
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index f404fe21cc2..ad63c215efe 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -91,34 +91,6 @@ enum ib_sa_selector {
IB_SA_BEST = 3
};
-enum ib_sa_rate {
- IB_SA_RATE_2_5_GBPS = 2,
- IB_SA_RATE_5_GBPS = 5,
- IB_SA_RATE_10_GBPS = 3,
- IB_SA_RATE_20_GBPS = 6,
- IB_SA_RATE_30_GBPS = 4,
- IB_SA_RATE_40_GBPS = 7,
- IB_SA_RATE_60_GBPS = 8,
- IB_SA_RATE_80_GBPS = 9,
- IB_SA_RATE_120_GBPS = 10
-};
-
-static inline int ib_sa_rate_enum_to_int(enum ib_sa_rate rate)
-{
- switch (rate) {
- case IB_SA_RATE_2_5_GBPS: return 1;
- case IB_SA_RATE_5_GBPS: return 2;
- case IB_SA_RATE_10_GBPS: return 4;
- case IB_SA_RATE_20_GBPS: return 8;
- case IB_SA_RATE_30_GBPS: return 12;
- case IB_SA_RATE_40_GBPS: return 16;
- case IB_SA_RATE_60_GBPS: return 24;
- case IB_SA_RATE_80_GBPS: return 32;
- case IB_SA_RATE_120_GBPS: return 48;
- default: return -1;
- }
-}
-
/*
* Structures for SA records are named "struct ib_sa_xxx_rec." No
* attempt is made to pack structures to match the physical layout of
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index c1ad6273ac6..6bbf1b36440 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -314,6 +314,34 @@ enum ib_ah_flags {
IB_AH_GRH = 1
};
+enum ib_rate {
+ IB_RATE_PORT_CURRENT = 0,
+ IB_RATE_2_5_GBPS = 2,
+ IB_RATE_5_GBPS = 5,
+ IB_RATE_10_GBPS = 3,
+ IB_RATE_20_GBPS = 6,
+ IB_RATE_30_GBPS = 4,
+ IB_RATE_40_GBPS = 7,
+ IB_RATE_60_GBPS = 8,
+ IB_RATE_80_GBPS = 9,
+ IB_RATE_120_GBPS = 10
+};
+
+/**
+ * ib_rate_to_mult - Convert the IB rate enum to a multiple of the
+ * base rate of 2.5 Gbit/sec. For example, IB_RATE_5_GBPS will be
+ * converted to 2, since 5 Gbit/sec is 2 * 2.5 Gbit/sec.
+ * @rate: rate to convert.
+ */
+int ib_rate_to_mult(enum ib_rate rate) __attribute_const__;
+
+/**
+ * mult_to_ib_rate - Convert a multiple of 2.5 Gbit/sec to an IB rate
+ * enum.
+ * @mult: multiple to convert.
+ */
+enum ib_rate mult_to_ib_rate(int mult) __attribute_const__;
+
struct ib_ah_attr {
struct ib_global_route grh;
u16 dlid;
diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
index 174101b2069..d31b16d25a0 100644
--- a/include/scsi/scsi_devinfo.h
+++ b/include/scsi/scsi_devinfo.h
@@ -28,4 +28,5 @@
#define BLIST_NO_ULD_ATTACH 0x100000 /* device is actually for RAID config */
#define BLIST_SELECT_NO_ATN 0x200000 /* select without ATN */
#define BLIST_RETRY_HWERROR 0x400000 /* retry HARDWARE_ERROR */
+#define BLIST_MAX_512 0x800000 /* maximum 512 sector cdb length */
#endif
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index dc6862d09e5..de6ce541a04 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -140,7 +140,6 @@ struct scsi_host_template {
*
* Status: REQUIRED (at least one of them)
*/
- int (* eh_strategy_handler)(struct Scsi_Host *);
int (* eh_abort_handler)(struct scsi_cmnd *);
int (* eh_device_reset_handler)(struct scsi_cmnd *);
int (* eh_bus_reset_handler)(struct scsi_cmnd *);
diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
index d4be4d92d58..edb9525386d 100644
--- a/include/scsi/scsi_ioctl.h
+++ b/include/scsi/scsi_ioctl.h
@@ -41,8 +41,6 @@ typedef struct scsi_fctargaddress {
} Scsi_FCTargAddress;
extern int scsi_ioctl(struct scsi_device *, int, void __user *);
-extern int scsi_ioctl_send_command(struct scsi_device *,
- struct scsi_ioctl_command __user *);
extern int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
void __user *arg, struct file *filp);
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index b3657f11193..cca1d4926d2 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -50,6 +50,11 @@ struct scsi_transport_template {
unsigned int create_work_queue : 1;
/*
+ * Allows a transport to override the default error handler.
+ */
+ void (* eh_strategy_handler)(struct Scsi_Host *);
+
+ /*
* This is an optional routine that allows the transport to become
* involved when a scsi io timer fires. The return value tells the
* timer routine how to finish the io timeout handling:
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index cf3fec8be1e..5626225bd3a 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -202,12 +202,19 @@ struct fc_rport { /* aka fc_starget_attrs */
/* internal data */
unsigned int channel;
u32 number;
+ u8 flags;
struct list_head peers;
struct device dev;
struct work_struct dev_loss_work;
struct work_struct scan_work;
+ struct work_struct stgt_delete_work;
+ struct work_struct rport_delete_work;
} __attribute__((aligned(sizeof(unsigned long))));
+/* bit field values for struct fc_rport "flags" field: */
+#define FC_RPORT_DEVLOSS_PENDING 0x01
+#define FC_RPORT_SCAN_PENDING 0x02
+
#define dev_to_rport(d) \
container_of(d, struct fc_rport, dev)
#define transport_class_to_rport(classdev) \
@@ -327,13 +334,16 @@ struct fc_host_attrs {
struct list_head rport_bindings;
u32 next_rport_number;
u32 next_target_id;
- u8 flags;
- struct work_struct rport_del_work;
-};
-/* values for struct fc_host_attrs "flags" field: */
-#define FC_SHOST_RPORT_DEL_SCHEDULED 0x01
+ /* work queues for rport state manipulation */
+ char work_q_name[KOBJ_NAME_LEN];
+ struct workqueue_struct *work_q;
+ char devloss_work_q_name[KOBJ_NAME_LEN];
+ struct workqueue_struct *devloss_work_q;
+};
+#define shost_to_fc_host(x) \
+ ((struct fc_host_attrs *)(x)->shost_data)
#define fc_host_node_name(x) \
(((struct fc_host_attrs *)(x)->shost_data)->node_name)
@@ -375,10 +385,14 @@ struct fc_host_attrs {
(((struct fc_host_attrs *)(x)->shost_data)->next_rport_number)
#define fc_host_next_target_id(x) \
(((struct fc_host_attrs *)(x)->shost_data)->next_target_id)
-#define fc_host_flags(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->flags)
-#define fc_host_rport_del_work(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->rport_del_work)
+#define fc_host_work_q_name(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->work_q_name)
+#define fc_host_work_q(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->work_q)
+#define fc_host_devloss_work_q_name(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name)
+#define fc_host_devloss_work_q(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
/* The functions by which the transport class and the driver communicate */
@@ -461,10 +475,15 @@ fc_remote_port_chkready(struct fc_rport *rport)
switch (rport->port_state) {
case FC_PORTSTATE_ONLINE:
- result = 0;
+ if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+ result = 0;
+ else if (rport->flags & FC_RPORT_DEVLOSS_PENDING)
+ result = DID_IMM_RETRY << 16;
+ else
+ result = DID_NO_CONNECT << 16;
break;
case FC_PORTSTATE_BLOCKED:
- result = DID_BUS_BUSY << 16;
+ result = DID_IMM_RETRY << 16;
break;
default:
result = DID_NO_CONNECT << 16;
diff --git a/include/scsi/srp.h b/include/scsi/srp.h
index 6c2681dc5b4..637f77eccf0 100644
--- a/include/scsi/srp.h
+++ b/include/scsi/srp.h
@@ -95,14 +95,15 @@ struct srp_direct_buf {
/*
* We need the packed attribute because the SRP spec puts the list of
- * descriptors at an offset of 20, which is not aligned to the size
- * of struct srp_direct_buf.
+ * descriptors at an offset of 20, which is not aligned to the size of
+ * struct srp_direct_buf. The whole structure must be packed to avoid
+ * having the 20-byte structure padded to 24 bytes on 64-bit architectures.
*/
struct srp_indirect_buf {
struct srp_direct_buf table_desc;
__be32 len;
- struct srp_direct_buf desc_list[0] __attribute__((packed));
-};
+ struct srp_direct_buf desc_list[0];
+} __attribute__((packed));
enum {
SRP_MULTICHAN_SINGLE = 0,
@@ -122,6 +123,11 @@ struct srp_login_req {
u8 target_port_id[16];
};
+/*
+ * The SRP spec defines the size of the LOGIN_RSP structure to be 52
+ * bytes, so it needs to be packed to avoid having it padded to 56
+ * bytes on 64-bit architectures.
+ */
struct srp_login_rsp {
u8 opcode;
u8 reserved1[3];
@@ -132,7 +138,7 @@ struct srp_login_rsp {
__be16 buf_fmt;
u8 rsp_flags;
u8 reserved2[25];
-};
+} __attribute__((packed));
struct srp_login_rej {
u8 opcode;
@@ -207,6 +213,11 @@ enum {
SRP_RSP_FLAG_DIUNDER = 1 << 5
};
+/*
+ * The SRP spec defines the size of the RSP structure to be 36 bytes,
+ * so it needs to be packed to avoid having it padded to 40 bytes on
+ * 64-bit architectures.
+ */
struct srp_rsp {
u8 opcode;
u8 sol_not;
@@ -221,6 +232,6 @@ struct srp_rsp {
__be32 sense_data_len;
__be32 resp_data_len;
u8 data[0];
-};
+} __attribute__((packed));
#endif /* SCSI_SRP_H */
diff --git a/include/sound/core.h b/include/sound/core.h
index 144bdc2f217..5135147f20e 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -170,13 +170,13 @@ static inline void snd_power_change_state(struct snd_card *card, unsigned int st
}
/* init.c */
-int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file *file);
+int snd_power_wait(struct snd_card *card, unsigned int power_state);
#else /* ! CONFIG_PM */
#define snd_power_lock(card) do { (void)(card); } while (0)
#define snd_power_unlock(card) do { (void)(card); } while (0)
-static inline int snd_power_wait(struct snd_card *card, unsigned int state, struct file *file) { return 0; }
+static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; }
#define snd_power_get_state(card) SNDRV_CTL_POWER_D0
#define snd_power_change_state(card, state) do { (void)(card); } while (0)
@@ -186,7 +186,7 @@ struct snd_minor {
int type; /* SNDRV_DEVICE_TYPE_XXX */
int card; /* card number */
int device; /* device number */
- struct file_operations *f_ops; /* file operations */
+ const struct file_operations *f_ops; /* file operations */
void *private_data; /* private data for f_ops->open */
char name[0]; /* device name (keep at the end of
structure) */
@@ -200,14 +200,14 @@ extern int snd_ecards_limit;
void snd_request_card(int card);
int snd_register_device(int type, struct snd_card *card, int dev,
- struct file_operations *f_ops, void *private_data,
+ const struct file_operations *f_ops, void *private_data,
const char *name);
int snd_unregister_device(int type, struct snd_card *card, int dev);
void *snd_lookup_minor_data(unsigned int minor, int type);
#ifdef CONFIG_SND_OSSEMUL
int snd_register_oss_device(int type, struct snd_card *card, int dev,
- struct file_operations *f_ops, void *private_data,
+ const struct file_operations *f_ops, void *private_data,
const char *name);
int snd_unregister_oss_device(int type, struct snd_card *card, int dev);
void *snd_lookup_oss_minor_data(unsigned int minor, int type);
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 15b885660bf..373425895fa 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -367,27 +367,27 @@ struct snd_pcm_substream {
struct snd_pcm_group self_group; /* fake group for non linked substream (with substream lock inside) */
struct snd_pcm_group *group; /* pointer to current group */
/* -- assigned files -- */
- struct snd_pcm_file *file;
+ void *file;
struct file *ffile;
+ void (*pcm_release)(struct snd_pcm_substream *);
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
/* -- OSS things -- */
struct snd_pcm_oss_substream oss;
#endif
+#ifdef CONFIG_SND_VERBOSE_PROCFS
struct snd_info_entry *proc_root;
struct snd_info_entry *proc_info_entry;
struct snd_info_entry *proc_hw_params_entry;
struct snd_info_entry *proc_sw_params_entry;
struct snd_info_entry *proc_status_entry;
struct snd_info_entry *proc_prealloc_entry;
+#endif
/* misc flags */
unsigned int no_mmap_ctrl: 1;
+ unsigned int hw_opened: 1;
};
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL || ((substream)->oss.file != NULL))
-#else
#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL)
-#endif
struct snd_pcm_str {
@@ -402,12 +402,14 @@ struct snd_pcm_str {
struct snd_pcm_oss_stream oss;
#endif
struct snd_pcm_file *files;
+#ifdef CONFIG_SND_VERBOSE_PROCFS
struct snd_info_entry *proc_root;
struct snd_info_entry *proc_info_entry;
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
unsigned int xrun_debug; /* 0 = disabled, 1 = verbose, 2 = stacktrace */
struct snd_info_entry *proc_xrun_debug_entry;
#endif
+#endif
};
struct snd_pcm {
@@ -460,7 +462,6 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
struct snd_pcm_info __user *info);
int snd_pcm_status(struct snd_pcm_substream *substream,
struct snd_pcm_status *status);
-int snd_pcm_prepare(struct snd_pcm_substream *substream);
int snd_pcm_start(struct snd_pcm_substream *substream);
int snd_pcm_stop(struct snd_pcm_substream *substream, int status);
int snd_pcm_drain_done(struct snd_pcm_substream *substream);
@@ -468,11 +469,13 @@ int snd_pcm_drain_done(struct snd_pcm_substream *substream);
int snd_pcm_suspend(struct snd_pcm_substream *substream);
int snd_pcm_suspend_all(struct snd_pcm *pcm);
#endif
-int snd_pcm_kernel_playback_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
-int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
-int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct snd_pcm_substream **rsubstream);
+int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file,
+ struct snd_pcm_substream **rsubstream);
void snd_pcm_release_substream(struct snd_pcm_substream *substream);
+int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file,
+ struct snd_pcm_substream **rsubstream);
+void snd_pcm_detach_substream(struct snd_pcm_substream *substream);
void snd_pcm_vma_notify_data(void *client, void *data);
int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area);
@@ -899,7 +902,6 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples);
const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format);
int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames);
snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
-const char *snd_pcm_format_name(snd_pcm_format_t format);
void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, struct snd_pcm_ops *ops);
void snd_pcm_set_sync(struct snd_pcm_substream *substream);
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index bff0778e196..c854647b6f3 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -69,14 +69,15 @@ struct snd_pcm_oss_file {
struct snd_pcm_oss_substream {
unsigned oss: 1; /* oss mode */
- struct snd_pcm_oss_setup *setup; /* active setup */
- struct snd_pcm_oss_file *file;
+ struct snd_pcm_oss_setup setup; /* active setup */
};
struct snd_pcm_oss_stream {
struct snd_pcm_oss_setup *setup_list; /* setup list */
struct mutex setup_mutex;
+#ifdef CONFIG_SND_VERBOSE_PROCFS
struct snd_info_entry *proc_entry;
+#endif
};
struct snd_pcm_oss {
diff --git a/init/do_mounts.c b/init/do_mounts.c
index adb7cad3e6e..f4b7b9d278c 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -310,6 +310,11 @@ retry:
panic("VFS: Unable to mount root fs on %s", b);
}
+
+ printk("No filesystem could mount root, tried: ");
+ for (p = fs_names; *p; p += strlen(p)+1)
+ printk(" %s", p);
+ printk("\n");
panic("VFS: Unable to mount root fs on %s", __bdevname(ROOT_DEV, b));
out:
putname(fs_names);
diff --git a/init/initramfs.c b/init/initramfs.c
index 679d870d991..f81cfa40a71 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -26,10 +26,12 @@ static void __init free(void *where)
/* link hash */
+#define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
+
static __initdata struct hash {
int ino, minor, major;
struct hash *next;
- char *name;
+ char name[N_ALIGN(PATH_MAX)];
} *head[32];
static inline int hash(int major, int minor, int ino)
@@ -57,7 +59,7 @@ static char __init *find_link(int major, int minor, int ino, char *name)
q->ino = ino;
q->minor = minor;
q->major = major;
- q->name = name;
+ strcpy(q->name, name);
q->next = NULL;
*p = q;
return NULL;
@@ -133,8 +135,6 @@ static inline void eat(unsigned n)
count -= n;
}
-#define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
-
static __initdata char *collected;
static __initdata int remains;
static __initdata char *collect;
diff --git a/init/main.c b/init/main.c
index 64466ea1984..f715b9b8975 100644
--- a/init/main.c
+++ b/init/main.c
@@ -341,7 +341,7 @@ static void __init setup_per_cpu_areas(void)
#endif
ptr = alloc_bootmem(size * nr_possible_cpus);
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
__per_cpu_offset[i] = ptr - __per_cpu_start;
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
ptr += size;
@@ -582,7 +582,7 @@ static void __init do_initcalls(void)
result = (*call)();
- if (result && (result != -ENODEV || initcall_debug)) {
+ if (result && result != -ENODEV && initcall_debug) {
sprintf(msgbuf, "error code %d", result);
msg = msgbuf;
}
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 532ec3bf18d..41ecbd440fe 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -762,7 +762,7 @@ out_unlock:
* The receiver accepts the message and returns without grabbing the queue
* spinlock. Therefore an intermediate STATE_PENDING state and memory barriers
* are necessary. The same algorithm is used for sysv semaphores, see
- * ipc/sem.c fore more details.
+ * ipc/sem.c for more details.
*
* The same algorithm is used for senders.
*/
diff --git a/ipc/msg.c b/ipc/msg.c
index 48a7f17a723..7d1340ccb16 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -13,6 +13,9 @@
* mostly rewritten, threaded and wake-one semantics added
* MSGMAX limit removed, sysctl's added
* (c) 1999 Manfred Spraul <manfred@colorfullife.com>
+ *
+ * support for audit of ipc object properties and permission changes
+ * Dustin Kirkland <dustin.kirkland@us.ibm.com>
*/
#include <linux/capability.h>
@@ -447,6 +450,11 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
if (msg_checkid(msq,msqid))
goto out_unlock_up;
ipcp = &msq->q_perm;
+
+ err = audit_ipc_obj(ipcp);
+ if (err)
+ goto out_unlock_up;
+
err = -EPERM;
if (current->euid != ipcp->cuid &&
current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
@@ -460,7 +468,8 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
switch (cmd) {
case IPC_SET:
{
- if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp)))
+ err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp);
+ if (err)
goto out_unlock_up;
err = -EPERM;
diff --git a/ipc/sem.c b/ipc/sem.c
index 642659cd596..7919f8ece6b 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -61,6 +61,9 @@
* (c) 2001 Red Hat Inc <alan@redhat.com>
* Lockless wakeup
* (c) 2003 Manfred Spraul <manfred@colorfullife.com>
+ *
+ * support for audit of ipc object properties and permission changes
+ * Dustin Kirkland <dustin.kirkland@us.ibm.com>
*/
#include <linux/config.h>
@@ -820,6 +823,11 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
goto out_unlock;
}
ipcp = &sma->sem_perm;
+
+ err = audit_ipc_obj(ipcp);
+ if (err)
+ goto out_unlock;
+
if (current->euid != ipcp->cuid &&
current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
err=-EPERM;
@@ -836,7 +844,8 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
err = 0;
break;
case IPC_SET:
- if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp)))
+ err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp);
+ if (err)
goto out_unlock;
ipcp->uid = setbuf.uid;
ipcp->gid = setbuf.gid;
diff --git a/ipc/shm.c b/ipc/shm.c
index f806a2e314e..80989685190 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -13,6 +13,8 @@
* Shared /dev/zero support, Kanoj Sarcar <kanoj@sgi.com>
* Move the mm functionality over to mm/shmem.c, Christoph Rohland <cr@sap.com>
*
+ * support for audit of ipc object properties and permission changes
+ * Dustin Kirkland <dustin.kirkland@us.ibm.com>
*/
#include <linux/config.h>
@@ -91,8 +93,8 @@ static inline int shm_addid(struct shmid_kernel *shp)
static inline void shm_inc (int id) {
struct shmid_kernel *shp;
- if(!(shp = shm_lock(id)))
- BUG();
+ shp = shm_lock(id);
+ BUG_ON(!shp);
shp->shm_atim = get_seconds();
shp->shm_lprid = current->tgid;
shp->shm_nattch++;
@@ -142,8 +144,8 @@ static void shm_close (struct vm_area_struct *shmd)
mutex_lock(&shm_ids.mutex);
/* remove from the list of attaches of the shm segment */
- if(!(shp = shm_lock(id)))
- BUG();
+ shp = shm_lock(id);
+ BUG_ON(!shp);
shp->shm_lprid = current->tgid;
shp->shm_dtim = get_seconds();
shp->shm_nattch--;
@@ -162,6 +164,8 @@ static int shm_mmap(struct file * file, struct vm_area_struct * vma)
ret = shmem_mmap(file, vma);
if (ret == 0) {
vma->vm_ops = &shm_vm_ops;
+ if (!(vma->vm_flags & VM_WRITE))
+ vma->vm_flags &= ~VM_MAYWRITE;
shm_inc(file->f_dentry->d_inode->i_ino);
}
@@ -283,8 +287,7 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
err = -EEXIST;
} else {
shp = shm_lock(id);
- if(shp==NULL)
- BUG();
+ BUG_ON(shp==NULL);
if (shp->shm_segsz < size)
err = -EINVAL;
else if (ipcperms(&shp->shm_perm, shmflg))
@@ -541,6 +544,10 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
if(err)
goto out_unlock;
+ err = audit_ipc_obj(&(shp->shm_perm));
+ if (err)
+ goto out_unlock;
+
if (!capable(CAP_IPC_LOCK)) {
err = -EPERM;
if (current->euid != shp->shm_perm.uid &&
@@ -593,6 +600,10 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
if(err)
goto out_unlock_up;
+ err = audit_ipc_obj(&(shp->shm_perm));
+ if (err)
+ goto out_unlock_up;
+
if (current->euid != shp->shm_perm.uid &&
current->euid != shp->shm_perm.cuid &&
!capable(CAP_SYS_ADMIN)) {
@@ -626,12 +637,15 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
err=-EINVAL;
if(shp==NULL)
goto out_up;
- if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid,
- setbuf.mode, &(shp->shm_perm))))
- goto out_unlock_up;
err = shm_checkid(shp,shmid);
if(err)
goto out_unlock_up;
+ err = audit_ipc_obj(&(shp->shm_perm));
+ if (err)
+ goto out_unlock_up;
+ err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode, &(shp->shm_perm));
+ if (err)
+ goto out_unlock_up;
err=-EPERM;
if (current->euid != shp->shm_perm.uid &&
current->euid != shp->shm_perm.cuid &&
@@ -774,8 +788,8 @@ invalid:
up_write(&current->mm->mmap_sem);
mutex_lock(&shm_ids.mutex);
- if(!(shp = shm_lock(shmid)))
- BUG();
+ shp = shm_lock(shmid);
+ BUG_ON(!shp);
shp->shm_nattch--;
if(shp->shm_nattch == 0 &&
shp->shm_perm.mode & SHM_DEST)
diff --git a/ipc/util.c b/ipc/util.c
index 23151ef3259..8193299f45f 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -10,6 +10,8 @@
* Manfred Spraul <manfred@colorfullife.com>
* Oct 2002 - One lock per IPC id. RCU ipc_free for lock-free grow_ary().
* Mingming Cao <cmm@us.ibm.com>
+ * Mar 2006 - support for audit of ipc object properties
+ * Dustin Kirkland <dustin.kirkland@us.ibm.com>
*/
#include <linux/config.h>
@@ -27,6 +29,7 @@
#include <linux/workqueue.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
+#include <linux/audit.h>
#include <asm/unistd.h>
@@ -183,8 +186,7 @@ static int grow_ary(struct ipc_ids* ids, int newsize)
if(new == NULL)
return size;
new->size = newsize;
- memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size +
- sizeof(struct ipc_id_ary));
+ memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size);
for(i=size;i<newsize;i++) {
new->p[i] = NULL;
}
@@ -266,8 +268,7 @@ struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)
{
struct kern_ipc_perm* p;
int lid = id % SEQ_MULTIPLIER;
- if(lid >= ids->entries->size)
- BUG();
+ BUG_ON(lid >= ids->entries->size);
/*
* do not need a rcu_dereference()() here to force ordering
@@ -275,8 +276,7 @@ struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)
*/
p = ids->entries->p[lid];
ids->entries->p[lid] = NULL;
- if(p==NULL)
- BUG();
+ BUG_ON(p==NULL);
ids->in_use--;
if (lid == ids->max_id) {
@@ -467,8 +467,10 @@ void ipc_rcu_putref(void *ptr)
int ipcperms (struct kern_ipc_perm *ipcp, short flag)
{ /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
- int requested_mode, granted_mode;
+ int requested_mode, granted_mode, err;
+ if (unlikely((err = audit_ipc_obj(ipcp))))
+ return err;
requested_mode = (flag >> 6) | (flag >> 3) | flag;
granted_mode = ipcp->mode;
if (current->euid == ipcp->cuid || current->euid == ipcp->uid)
diff --git a/kernel/Makefile b/kernel/Makefile
index ff1c11dc12c..58908f9d156 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -12,6 +12,9 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
obj-$(CONFIG_FUTEX) += futex.o
+ifeq ($(CONFIG_COMPAT),y)
+obj-$(CONFIG_FUTEX) += futex_compat.o
+endif
obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
obj-$(CONFIG_SMP) += cpu.o spinlock.o
obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
diff --git a/kernel/acct.c b/kernel/acct.c
index 065d8b4e51e..b327f4d2010 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -449,8 +449,8 @@ static void do_acct_process(long exitcode, struct file *file)
/* calculate run_time in nsec*/
do_posix_clock_monotonic_gettime(&uptime);
run_time = (u64)uptime.tv_sec*NSEC_PER_SEC + uptime.tv_nsec;
- run_time -= (u64)current->start_time.tv_sec*NSEC_PER_SEC
- + current->start_time.tv_nsec;
+ run_time -= (u64)current->group_leader->start_time.tv_sec * NSEC_PER_SEC
+ + current->group_leader->start_time.tv_nsec;
/* convert nsec -> AHZ */
elapsed = nsec_to_AHZ(run_time);
#if ACCT_VERSION==3
@@ -469,10 +469,10 @@ static void do_acct_process(long exitcode, struct file *file)
#endif
do_div(elapsed, AHZ);
ac.ac_btime = xtime.tv_sec - elapsed;
- jiffies = cputime_to_jiffies(cputime_add(current->group_leader->utime,
+ jiffies = cputime_to_jiffies(cputime_add(current->utime,
current->signal->utime));
ac.ac_utime = encode_comp_t(jiffies_to_AHZ(jiffies));
- jiffies = cputime_to_jiffies(cputime_add(current->group_leader->stime,
+ jiffies = cputime_to_jiffies(cputime_add(current->stime,
current->signal->stime));
ac.ac_stime = encode_comp_t(jiffies_to_AHZ(jiffies));
/* we really need to bite the bullet and change layout */
@@ -522,9 +522,9 @@ static void do_acct_process(long exitcode, struct file *file)
ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */
ac.ac_rw = encode_comp_t(ac.ac_io / 1024);
ac.ac_minflt = encode_comp_t(current->signal->min_flt +
- current->group_leader->min_flt);
+ current->min_flt);
ac.ac_majflt = encode_comp_t(current->signal->maj_flt +
- current->group_leader->maj_flt);
+ current->maj_flt);
ac.ac_swaps = encode_comp_t(0);
ac.ac_exitcode = exitcode;
diff --git a/kernel/audit.c b/kernel/audit.c
index 04fe2e301b6..df57b493e1c 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -55,6 +55,9 @@
#include <net/netlink.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
+#include <linux/selinux.h>
+
+#include "audit.h"
/* No auditing will take place until audit_initialized != 0.
* (Initialization happens after skb_init is called.) */
@@ -227,49 +230,103 @@ void audit_log_lost(const char *message)
}
}
-static int audit_set_rate_limit(int limit, uid_t loginuid)
+static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
{
- int old = audit_rate_limit;
- audit_rate_limit = limit;
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ int old = audit_rate_limit;
+
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_rate_limit=%d old=%d by auid=%u subj=%s",
+ limit, old, loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_rate_limit=%d old=%d by auid=%u",
- audit_rate_limit, old, loginuid);
+ limit, old, loginuid);
+ audit_rate_limit = limit;
return old;
}
-static int audit_set_backlog_limit(int limit, uid_t loginuid)
+static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
{
- int old = audit_backlog_limit;
- audit_backlog_limit = limit;
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ int old = audit_backlog_limit;
+
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_backlog_limit=%d old=%d by auid=%u subj=%s",
+ limit, old, loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_backlog_limit=%d old=%d by auid=%u",
- audit_backlog_limit, old, loginuid);
+ limit, old, loginuid);
+ audit_backlog_limit = limit;
return old;
}
-static int audit_set_enabled(int state, uid_t loginuid)
+static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
{
- int old = audit_enabled;
+ int old = audit_enabled;
+
if (state != 0 && state != 1)
return -EINVAL;
- audit_enabled = state;
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_enabled=%d old=%d by auid=%u subj=%s",
+ state, old, loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_enabled=%d old=%d by auid=%u",
- audit_enabled, old, loginuid);
+ state, old, loginuid);
+ audit_enabled = state;
return old;
}
-static int audit_set_failure(int state, uid_t loginuid)
+static int audit_set_failure(int state, uid_t loginuid, u32 sid)
{
- int old = audit_failure;
+ int old = audit_failure;
+
if (state != AUDIT_FAIL_SILENT
&& state != AUDIT_FAIL_PRINTK
&& state != AUDIT_FAIL_PANIC)
return -EINVAL;
- audit_failure = state;
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_failure=%d old=%d by auid=%u subj=%s",
+ state, old, loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_failure=%d old=%d by auid=%u",
- audit_failure, old, loginuid);
+ state, old, loginuid);
+ audit_failure = state;
return old;
}
@@ -387,7 +444,7 @@ static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type)
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
- u32 uid, pid, seq;
+ u32 uid, pid, seq, sid;
void *data;
struct audit_status *status_get, status_set;
int err;
@@ -413,6 +470,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
pid = NETLINK_CREDS(skb)->pid;
uid = NETLINK_CREDS(skb)->uid;
loginuid = NETLINK_CB(skb).loginuid;
+ sid = NETLINK_CB(skb).sid;
seq = nlh->nlmsg_seq;
data = NLMSG_DATA(nlh);
@@ -433,25 +491,43 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
return -EINVAL;
status_get = (struct audit_status *)data;
if (status_get->mask & AUDIT_STATUS_ENABLED) {
- err = audit_set_enabled(status_get->enabled, loginuid);
+ err = audit_set_enabled(status_get->enabled,
+ loginuid, sid);
if (err < 0) return err;
}
if (status_get->mask & AUDIT_STATUS_FAILURE) {
- err = audit_set_failure(status_get->failure, loginuid);
+ err = audit_set_failure(status_get->failure,
+ loginuid, sid);
if (err < 0) return err;
}
if (status_get->mask & AUDIT_STATUS_PID) {
int old = audit_pid;
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(
+ sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL,
+ AUDIT_CONFIG_CHANGE,
+ "audit_pid=%d old=%d by auid=%u subj=%s",
+ status_get->pid, old,
+ loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_pid=%d old=%d by auid=%u",
+ status_get->pid, old, loginuid);
audit_pid = status_get->pid;
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_pid=%d old=%d by auid=%u",
- audit_pid, old, loginuid);
}
if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
- audit_set_rate_limit(status_get->rate_limit, loginuid);
+ audit_set_rate_limit(status_get->rate_limit,
+ loginuid, sid);
if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
audit_set_backlog_limit(status_get->backlog_limit,
- loginuid);
+ loginuid, sid);
break;
case AUDIT_USER:
case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
@@ -465,8 +541,23 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
if (ab) {
audit_log_format(ab,
- "user pid=%d uid=%u auid=%u msg='%.1024s'",
- pid, uid, loginuid, (char *)data);
+ "user pid=%d uid=%u auid=%u",
+ pid, uid, loginuid);
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(
+ sid, &ctx, &len)) {
+ audit_log_format(ab,
+ " ssid=%u", sid);
+ /* Maybe call audit_panic? */
+ } else
+ audit_log_format(ab,
+ " subj=%s", ctx);
+ kfree(ctx);
+ }
+ audit_log_format(ab, " msg='%.1024s'",
+ (char *)data);
audit_set_pid(ab, pid);
audit_log_end(ab);
}
@@ -480,7 +571,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_LIST:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
uid, seq, data, nlmsg_len(nlh),
- loginuid);
+ loginuid, sid);
break;
case AUDIT_ADD_RULE:
case AUDIT_DEL_RULE:
@@ -490,7 +581,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_LIST_RULES:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
uid, seq, data, nlmsg_len(nlh),
- loginuid);
+ loginuid, sid);
break;
case AUDIT_SIGNAL_INFO:
sig_data.uid = audit_sig_uid;
@@ -564,6 +655,11 @@ static int __init audit_init(void)
skb_queue_head_init(&audit_skb_queue);
audit_initialized = 1;
audit_enabled = audit_default;
+
+ /* Register the callback with selinux. This callback will be invoked
+ * when a new policy is loaded. */
+ selinux_audit_set_callback(&selinux_audit_rule_update);
+
audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
return 0;
}
@@ -578,7 +674,7 @@ static int __init audit_enable(char *str)
audit_initialized ? "" : " (after initialization)");
if (audit_initialized)
audit_enabled = audit_default;
- return 0;
+ return 1;
}
__setup("audit=", audit_enable);
diff --git a/kernel/audit.h b/kernel/audit.h
index bc5392076e2..6f733920fd3 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -54,9 +54,11 @@ enum audit_state {
/* Rule lists */
struct audit_field {
- u32 type;
- u32 val;
- u32 op;
+ u32 type;
+ u32 val;
+ u32 op;
+ char *se_str;
+ struct selinux_audit_rule *se_rule;
};
struct audit_krule {
@@ -86,3 +88,5 @@ extern void audit_send_reply(int pid, int seq, int type,
extern void audit_log_lost(const char *message);
extern void audit_panic(const char *message);
extern struct mutex audit_netlink_mutex;
+
+extern int selinux_audit_rule_update(void);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index d3a8539f3a8..7c134906d68 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -23,6 +23,7 @@
#include <linux/audit.h>
#include <linux/kthread.h>
#include <linux/netlink.h>
+#include <linux/selinux.h>
#include "audit.h"
/* There are three lists of rules -- one to search at task creation
@@ -42,6 +43,13 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
static inline void audit_free_rule(struct audit_entry *e)
{
+ int i;
+ if (e->rule.fields)
+ for (i = 0; i < e->rule.field_count; i++) {
+ struct audit_field *f = &e->rule.fields[i];
+ kfree(f->se_str);
+ selinux_audit_rule_free(f->se_rule);
+ }
kfree(e->rule.fields);
kfree(e);
}
@@ -52,9 +60,29 @@ static inline void audit_free_rule_rcu(struct rcu_head *head)
audit_free_rule(e);
}
+/* Initialize an audit filterlist entry. */
+static inline struct audit_entry *audit_init_entry(u32 field_count)
+{
+ struct audit_entry *entry;
+ struct audit_field *fields;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (unlikely(!entry))
+ return NULL;
+
+ fields = kzalloc(sizeof(*fields) * field_count, GFP_KERNEL);
+ if (unlikely(!fields)) {
+ kfree(entry);
+ return NULL;
+ }
+ entry->rule.fields = fields;
+
+ return entry;
+}
+
/* Unpack a filter field's string representation from user-space
* buffer. */
-static __attribute__((unused)) char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
+static char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
{
char *str;
@@ -84,7 +112,6 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
{
unsigned listnr;
struct audit_entry *entry;
- struct audit_field *fields;
int i, err;
err = -EINVAL;
@@ -108,23 +135,14 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
goto exit_err;
err = -ENOMEM;
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
- if (unlikely(!entry))
- goto exit_err;
- fields = kmalloc(sizeof(*fields) * rule->field_count, GFP_KERNEL);
- if (unlikely(!fields)) {
- kfree(entry);
+ entry = audit_init_entry(rule->field_count);
+ if (!entry)
goto exit_err;
- }
-
- memset(&entry->rule, 0, sizeof(struct audit_krule));
- memset(fields, 0, sizeof(struct audit_field));
entry->rule.flags = rule->flags & AUDIT_FILTER_PREPEND;
entry->rule.listnr = listnr;
entry->rule.action = rule->action;
entry->rule.field_count = rule->field_count;
- entry->rule.fields = fields;
for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
entry->rule.mask[i] = rule->mask[i];
@@ -150,15 +168,20 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
for (i = 0; i < rule->field_count; i++) {
struct audit_field *f = &entry->rule.fields[i];
- if (rule->fields[i] & AUDIT_UNUSED_BITS) {
- err = -EINVAL;
- goto exit_free;
- }
-
f->op = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
f->val = rule->values[i];
+ if (f->type & AUDIT_UNUSED_BITS ||
+ f->type == AUDIT_SE_USER ||
+ f->type == AUDIT_SE_ROLE ||
+ f->type == AUDIT_SE_TYPE ||
+ f->type == AUDIT_SE_SEN ||
+ f->type == AUDIT_SE_CLR) {
+ err = -EINVAL;
+ goto exit_free;
+ }
+
entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
/* Support for legacy operators where
@@ -188,8 +211,9 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
int err = 0;
struct audit_entry *entry;
void *bufp;
- /* size_t remain = datasz - sizeof(struct audit_rule_data); */
+ size_t remain = datasz - sizeof(struct audit_rule_data);
int i;
+ char *str;
entry = audit_to_entry_common((struct audit_rule *)data);
if (IS_ERR(entry))
@@ -207,10 +231,35 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
f->op = data->fieldflags[i] & AUDIT_OPERATORS;
f->type = data->fields[i];
+ f->val = data->values[i];
+ f->se_str = NULL;
+ f->se_rule = NULL;
switch(f->type) {
- /* call type-specific conversion routines here */
- default:
- f->val = data->values[i];
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ str = audit_unpack_string(&bufp, &remain, f->val);
+ if (IS_ERR(str))
+ goto exit_free;
+ entry->rule.buflen += f->val;
+
+ err = selinux_audit_rule_init(f->type, f->op, str,
+ &f->se_rule);
+ /* Keep currently invalid fields around in case they
+ * become valid after a policy reload. */
+ if (err == -EINVAL) {
+ printk(KERN_WARNING "audit rule for selinux "
+ "\'%s\' is invalid\n", str);
+ err = 0;
+ }
+ if (err) {
+ kfree(str);
+ goto exit_free;
+ } else
+ f->se_str = str;
+ break;
}
}
@@ -286,7 +335,14 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
data->fields[i] = f->type;
data->fieldflags[i] = f->op;
switch(f->type) {
- /* call type-specific conversion routines here */
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ data->buflen += data->values[i] =
+ audit_pack_string(&bufp, f->se_str);
+ break;
default:
data->values[i] = f->val;
}
@@ -314,7 +370,14 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
return 1;
switch(a->fields[i].type) {
- /* call type-specific comparison routines here */
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
+ return 1;
+ break;
default:
if (a->fields[i].val != b->fields[i].val)
return 1;
@@ -328,6 +391,81 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
return 0;
}
+/* Duplicate selinux field information. The se_rule is opaque, so must be
+ * re-initialized. */
+static inline int audit_dupe_selinux_field(struct audit_field *df,
+ struct audit_field *sf)
+{
+ int ret = 0;
+ char *se_str;
+
+ /* our own copy of se_str */
+ se_str = kstrdup(sf->se_str, GFP_KERNEL);
+ if (unlikely(IS_ERR(se_str)))
+ return -ENOMEM;
+ df->se_str = se_str;
+
+ /* our own (refreshed) copy of se_rule */
+ ret = selinux_audit_rule_init(df->type, df->op, df->se_str,
+ &df->se_rule);
+ /* Keep currently invalid fields around in case they
+ * become valid after a policy reload. */
+ if (ret == -EINVAL) {
+ printk(KERN_WARNING "audit rule for selinux \'%s\' is "
+ "invalid\n", df->se_str);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/* Duplicate an audit rule. This will be a deep copy with the exception
+ * of the watch - that pointer is carried over. The selinux specific fields
+ * will be updated in the copy. The point is to be able to replace the old
+ * rule with the new rule in the filterlist, then free the old rule. */
+static struct audit_entry *audit_dupe_rule(struct audit_krule *old)
+{
+ u32 fcount = old->field_count;
+ struct audit_entry *entry;
+ struct audit_krule *new;
+ int i, err = 0;
+
+ entry = audit_init_entry(fcount);
+ if (unlikely(!entry))
+ return ERR_PTR(-ENOMEM);
+
+ new = &entry->rule;
+ new->vers_ops = old->vers_ops;
+ new->flags = old->flags;
+ new->listnr = old->listnr;
+ new->action = old->action;
+ for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
+ new->mask[i] = old->mask[i];
+ new->buflen = old->buflen;
+ new->field_count = old->field_count;
+ memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount);
+
+ /* deep copy this information, updating the se_rule fields, because
+ * the originals will all be freed when the old rule is freed. */
+ for (i = 0; i < fcount; i++) {
+ switch (new->fields[i].type) {
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ err = audit_dupe_selinux_field(&new->fields[i],
+ &old->fields[i]);
+ }
+ if (err) {
+ audit_free_rule(entry);
+ return ERR_PTR(err);
+ }
+ }
+
+ return entry;
+}
+
/* Add rule to given filterlist if not a duplicate. Protected by
* audit_netlink_mutex. */
static inline int audit_add_rule(struct audit_entry *entry,
@@ -448,9 +586,10 @@ static int audit_list_rules(void *_dest)
* @data: payload data
* @datasz: size of payload data
* @loginuid: loginuid of sender
+ * @sid: SE Linux Security ID of sender
*/
int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
- size_t datasz, uid_t loginuid)
+ size_t datasz, uid_t loginuid, u32 sid)
{
struct task_struct *tsk;
int *dest;
@@ -493,9 +632,23 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
err = audit_add_rule(entry,
&audit_filter_list[entry->rule.listnr]);
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "auid=%u add rule to list=%d res=%d\n",
- loginuid, entry->rule.listnr, !err);
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(sid, &ctx, &len)) {
+ /* Maybe call audit_panic? */
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u ssid=%u add rule to list=%d res=%d",
+ loginuid, sid, entry->rule.listnr, !err);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u subj=%s add rule to list=%d res=%d",
+ loginuid, ctx, entry->rule.listnr, !err);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u add rule to list=%d res=%d",
+ loginuid, entry->rule.listnr, !err);
if (err)
audit_free_rule(entry);
@@ -511,9 +664,24 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
err = audit_del_rule(entry,
&audit_filter_list[entry->rule.listnr]);
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "auid=%u remove rule from list=%d res=%d\n",
- loginuid, entry->rule.listnr, !err);
+
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(sid, &ctx, &len)) {
+ /* Maybe call audit_panic? */
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u ssid=%u remove rule from list=%d res=%d",
+ loginuid, sid, entry->rule.listnr, !err);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u subj=%s remove rule from list=%d res=%d",
+ loginuid, ctx, entry->rule.listnr, !err);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u remove rule from list=%d res=%d",
+ loginuid, entry->rule.listnr, !err);
audit_free_rule(entry);
break;
@@ -628,3 +796,62 @@ unlock_and_return:
rcu_read_unlock();
return result;
}
+
+/* Check to see if the rule contains any selinux fields. Returns 1 if there
+ are selinux fields specified in the rule, 0 otherwise. */
+static inline int audit_rule_has_selinux(struct audit_krule *rule)
+{
+ int i;
+
+ for (i = 0; i < rule->field_count; i++) {
+ struct audit_field *f = &rule->fields[i];
+ switch (f->type) {
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* This function will re-initialize the se_rule field of all applicable rules.
+ * It will traverse the filter lists serarching for rules that contain selinux
+ * specific filter fields. When such a rule is found, it is copied, the
+ * selinux field is re-initialized, and the old rule is replaced with the
+ * updated rule. */
+int selinux_audit_rule_update(void)
+{
+ struct audit_entry *entry, *n, *nentry;
+ int i, err = 0;
+
+ /* audit_netlink_mutex synchronizes the writers */
+ mutex_lock(&audit_netlink_mutex);
+
+ for (i = 0; i < AUDIT_NR_FILTERS; i++) {
+ list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
+ if (!audit_rule_has_selinux(&entry->rule))
+ continue;
+
+ nentry = audit_dupe_rule(&entry->rule);
+ if (unlikely(IS_ERR(nentry))) {
+ /* save the first error encountered for the
+ * return value */
+ if (!err)
+ err = PTR_ERR(nentry);
+ audit_panic("error updating selinux filters");
+ list_del_rcu(&entry->list);
+ } else {
+ list_replace_rcu(&entry->list, &nentry->list);
+ }
+ call_rcu(&entry->rcu, audit_free_rule_rcu);
+ }
+ }
+
+ mutex_unlock(&audit_netlink_mutex);
+
+ return err;
+}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 7f160df21a2..1c03a4ed1b2 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -58,6 +58,7 @@
#include <linux/security.h>
#include <linux/list.h>
#include <linux/tty.h>
+#include <linux/selinux.h>
#include "audit.h"
@@ -89,7 +90,7 @@ struct audit_names {
uid_t uid;
gid_t gid;
dev_t rdev;
- char *ctx;
+ u32 osid;
};
struct audit_aux_data {
@@ -106,7 +107,7 @@ struct audit_aux_data_ipcctl {
uid_t uid;
gid_t gid;
mode_t mode;
- char *ctx;
+ u32 osid;
};
struct audit_aux_data_socketcall {
@@ -167,7 +168,8 @@ static int audit_filter_rules(struct task_struct *tsk,
struct audit_context *ctx,
enum audit_state *state)
{
- int i, j;
+ int i, j, need_sid = 1;
+ u32 sid;
for (i = 0; i < rule->field_count; i++) {
struct audit_field *f = &rule->fields[i];
@@ -257,6 +259,27 @@ static int audit_filter_rules(struct task_struct *tsk,
if (ctx)
result = audit_comparator(ctx->loginuid, f->op, f->val);
break;
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ /* NOTE: this may return negative values indicating
+ a temporary error. We simply treat this as a
+ match for now to avoid losing information that
+ may be wanted. An error message will also be
+ logged upon error */
+ if (f->se_rule) {
+ if (need_sid) {
+ selinux_task_ctxid(tsk, &sid);
+ need_sid = 0;
+ }
+ result = selinux_audit_rule_match(sid, f->type,
+ f->op,
+ f->se_rule,
+ ctx);
+ }
+ break;
case AUDIT_ARG0:
case AUDIT_ARG1:
case AUDIT_ARG2:
@@ -329,7 +352,6 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
return AUDIT_BUILD_CONTEXT;
}
-/* This should be called with task_lock() held. */
static inline struct audit_context *audit_get_context(struct task_struct *tsk,
int return_valid,
int return_code)
@@ -391,9 +413,6 @@ static inline void audit_free_names(struct audit_context *context)
#endif
for (i = 0; i < context->name_count; i++) {
- char *p = context->names[i].ctx;
- context->names[i].ctx = NULL;
- kfree(p);
if (context->names[i].name)
__putname(context->names[i].name);
}
@@ -416,11 +435,6 @@ static inline void audit_free_aux(struct audit_context *context)
dput(axi->dentry);
mntput(axi->mnt);
}
- if ( aux->type == AUDIT_IPC ) {
- struct audit_aux_data_ipcctl *axi = (void *)aux;
- if (axi->ctx)
- kfree(axi->ctx);
- }
context->aux = aux->next;
kfree(aux);
@@ -506,7 +520,7 @@ static inline void audit_free_context(struct audit_context *context)
printk(KERN_ERR "audit: freed %d contexts\n", count);
}
-static void audit_log_task_context(struct audit_buffer *ab, gfp_t gfp_mask)
+static void audit_log_task_context(struct audit_buffer *ab)
{
char *ctx = NULL;
ssize_t len = 0;
@@ -518,7 +532,7 @@ static void audit_log_task_context(struct audit_buffer *ab, gfp_t gfp_mask)
return;
}
- ctx = kmalloc(len, gfp_mask);
+ ctx = kmalloc(len, GFP_KERNEL);
if (!ctx)
goto error_path;
@@ -536,47 +550,46 @@ error_path:
return;
}
-static void audit_log_task_info(struct audit_buffer *ab, gfp_t gfp_mask)
+static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
{
- char name[sizeof(current->comm)];
- struct mm_struct *mm = current->mm;
+ char name[sizeof(tsk->comm)];
+ struct mm_struct *mm = tsk->mm;
struct vm_area_struct *vma;
- get_task_comm(name, current);
+ /* tsk == current */
+
+ get_task_comm(name, tsk);
audit_log_format(ab, " comm=");
audit_log_untrustedstring(ab, name);
- if (!mm)
- return;
-
- /*
- * this is brittle; all callers that pass GFP_ATOMIC will have
- * NULL current->mm and we won't get here.
- */
- down_read(&mm->mmap_sem);
- vma = mm->mmap;
- while (vma) {
- if ((vma->vm_flags & VM_EXECUTABLE) &&
- vma->vm_file) {
- audit_log_d_path(ab, "exe=",
- vma->vm_file->f_dentry,
- vma->vm_file->f_vfsmnt);
- break;
+ if (mm) {
+ down_read(&mm->mmap_sem);
+ vma = mm->mmap;
+ while (vma) {
+ if ((vma->vm_flags & VM_EXECUTABLE) &&
+ vma->vm_file) {
+ audit_log_d_path(ab, "exe=",
+ vma->vm_file->f_dentry,
+ vma->vm_file->f_vfsmnt);
+ break;
+ }
+ vma = vma->vm_next;
}
- vma = vma->vm_next;
+ up_read(&mm->mmap_sem);
}
- up_read(&mm->mmap_sem);
- audit_log_task_context(ab, gfp_mask);
+ audit_log_task_context(ab);
}
-static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
+static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
{
- int i;
+ int i, call_panic = 0;
struct audit_buffer *ab;
struct audit_aux_data *aux;
const char *tty;
- ab = audit_log_start(context, gfp_mask, AUDIT_SYSCALL);
+ /* tsk == current */
+
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
if (!ab)
return; /* audit_panic has been called */
audit_log_format(ab, "arch=%x syscall=%d",
@@ -587,8 +600,8 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
audit_log_format(ab, " success=%s exit=%ld",
(context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
context->return_code);
- if (current->signal->tty && current->signal->tty->name)
- tty = current->signal->tty->name;
+ if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
+ tty = tsk->signal->tty->name;
else
tty = "(none)";
audit_log_format(ab,
@@ -607,12 +620,12 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
context->gid,
context->euid, context->suid, context->fsuid,
context->egid, context->sgid, context->fsgid, tty);
- audit_log_task_info(ab, gfp_mask);
+ audit_log_task_info(ab, tsk);
audit_log_end(ab);
for (aux = context->aux; aux; aux = aux->next) {
- ab = audit_log_start(context, gfp_mask, aux->type);
+ ab = audit_log_start(context, GFP_KERNEL, aux->type);
if (!ab)
continue; /* audit_panic has been called */
@@ -620,8 +633,39 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
case AUDIT_IPC: {
struct audit_aux_data_ipcctl *axi = (void *)aux;
audit_log_format(ab,
- " qbytes=%lx iuid=%u igid=%u mode=%x obj=%s",
- axi->qbytes, axi->uid, axi->gid, axi->mode, axi->ctx);
+ " qbytes=%lx iuid=%u igid=%u mode=%x",
+ axi->qbytes, axi->uid, axi->gid, axi->mode);
+ if (axi->osid != 0) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(
+ axi->osid, &ctx, &len)) {
+ audit_log_format(ab, " osid=%u",
+ axi->osid);
+ call_panic = 1;
+ } else
+ audit_log_format(ab, " obj=%s", ctx);
+ kfree(ctx);
+ }
+ break; }
+
+ case AUDIT_IPC_SET_PERM: {
+ struct audit_aux_data_ipcctl *axi = (void *)aux;
+ audit_log_format(ab,
+ " new qbytes=%lx new iuid=%u new igid=%u new mode=%x",
+ axi->qbytes, axi->uid, axi->gid, axi->mode);
+ if (axi->osid != 0) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(
+ axi->osid, &ctx, &len)) {
+ audit_log_format(ab, " osid=%u",
+ axi->osid);
+ call_panic = 1;
+ } else
+ audit_log_format(ab, " obj=%s", ctx);
+ kfree(ctx);
+ }
break; }
case AUDIT_SOCKETCALL: {
@@ -649,7 +693,7 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
}
if (context->pwd && context->pwdmnt) {
- ab = audit_log_start(context, gfp_mask, AUDIT_CWD);
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
if (ab) {
audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt);
audit_log_end(ab);
@@ -659,7 +703,7 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
unsigned long ino = context->names[i].ino;
unsigned long pino = context->names[i].pino;
- ab = audit_log_start(context, gfp_mask, AUDIT_PATH);
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
if (!ab)
continue; /* audit_panic has been called */
@@ -685,32 +729,35 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
context->names[i].gid,
MAJOR(context->names[i].rdev),
MINOR(context->names[i].rdev));
- if (context->names[i].ctx) {
- audit_log_format(ab, " obj=%s",
- context->names[i].ctx);
+ if (context->names[i].osid != 0) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(
+ context->names[i].osid, &ctx, &len)) {
+ audit_log_format(ab, " osid=%u",
+ context->names[i].osid);
+ call_panic = 2;
+ } else
+ audit_log_format(ab, " obj=%s", ctx);
+ kfree(ctx);
}
audit_log_end(ab);
}
+ if (call_panic)
+ audit_panic("error converting sid to string");
}
/**
* audit_free - free a per-task audit context
* @tsk: task whose audit context block to free
*
- * Called from copy_process and __put_task_struct.
+ * Called from copy_process and do_exit
*/
void audit_free(struct task_struct *tsk)
{
struct audit_context *context;
- /*
- * No need to lock the task - when we execute audit_free()
- * then the task has no external references anymore, and
- * we are tearing it down. (The locking also confuses
- * DEBUG_LOCKDEP - this freeing may occur in softirq
- * contexts as well, via RCU.)
- */
context = audit_get_context(tsk, 0, 0);
if (likely(!context))
return;
@@ -719,8 +766,9 @@ void audit_free(struct task_struct *tsk)
* function (e.g., exit_group), then free context block.
* We use GFP_ATOMIC here because we might be doing this
* in the context of the idle thread */
+ /* that can happen only if we are called from do_exit() */
if (context->in_syscall && context->auditable)
- audit_log_exit(context, GFP_ATOMIC);
+ audit_log_exit(context, tsk);
audit_free_context(context);
}
@@ -743,10 +791,11 @@ void audit_free(struct task_struct *tsk)
* will only be written if another part of the kernel requests that it
* be written).
*/
-void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
+void audit_syscall_entry(int arch, int major,
unsigned long a1, unsigned long a2,
unsigned long a3, unsigned long a4)
{
+ struct task_struct *tsk = current;
struct audit_context *context = tsk->audit_context;
enum audit_state state;
@@ -824,22 +873,18 @@ void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
* message), then write out the syscall information. In call cases,
* free the names stored from getname().
*/
-void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
+void audit_syscall_exit(int valid, long return_code)
{
+ struct task_struct *tsk = current;
struct audit_context *context;
- get_task_struct(tsk);
- task_lock(tsk);
context = audit_get_context(tsk, valid, return_code);
- task_unlock(tsk);
- /* Not having a context here is ok, since the parent may have
- * called __put_task_struct. */
if (likely(!context))
- goto out;
+ return;
if (context->in_syscall && context->auditable)
- audit_log_exit(context, GFP_KERNEL);
+ audit_log_exit(context, tsk);
context->in_syscall = 0;
context->auditable = 0;
@@ -854,8 +899,6 @@ void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
audit_free_aux(context);
tsk->audit_context = context;
}
- out:
- put_task_struct(tsk);
}
/**
@@ -936,40 +979,11 @@ void audit_putname(const char *name)
#endif
}
-void audit_inode_context(int idx, const struct inode *inode)
+static void audit_inode_context(int idx, const struct inode *inode)
{
struct audit_context *context = current->audit_context;
- const char *suffix = security_inode_xattr_getsuffix();
- char *ctx = NULL;
- int len = 0;
-
- if (!suffix)
- goto ret;
-
- len = security_inode_getsecurity(inode, suffix, NULL, 0, 0);
- if (len == -EOPNOTSUPP)
- goto ret;
- if (len < 0)
- goto error_path;
-
- ctx = kmalloc(len, GFP_KERNEL);
- if (!ctx)
- goto error_path;
- len = security_inode_getsecurity(inode, suffix, ctx, len, 0);
- if (len < 0)
- goto error_path;
-
- kfree(context->names[idx].ctx);
- context->names[idx].ctx = ctx;
- goto ret;
-
-error_path:
- if (ctx)
- kfree(ctx);
- audit_panic("error in audit_inode_context");
-ret:
- return;
+ selinux_get_inode_sid(inode, &context->names[idx].osid);
}
@@ -1155,40 +1169,37 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
return ctx ? ctx->loginuid : -1;
}
-static char *audit_ipc_context(struct kern_ipc_perm *ipcp)
+/**
+ * audit_ipc_obj - record audit data for ipc object
+ * @ipcp: ipc permissions
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
+ struct audit_aux_data_ipcctl *ax;
struct audit_context *context = current->audit_context;
- char *ctx = NULL;
- int len = 0;
if (likely(!context))
- return NULL;
-
- len = security_ipc_getsecurity(ipcp, NULL, 0);
- if (len == -EOPNOTSUPP)
- goto ret;
- if (len < 0)
- goto error_path;
-
- ctx = kmalloc(len, GFP_ATOMIC);
- if (!ctx)
- goto error_path;
+ return 0;
- len = security_ipc_getsecurity(ipcp, ctx, len);
- if (len < 0)
- goto error_path;
+ ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+ if (!ax)
+ return -ENOMEM;
- return ctx;
+ ax->uid = ipcp->uid;
+ ax->gid = ipcp->gid;
+ ax->mode = ipcp->mode;
+ selinux_get_ipc_sid(ipcp, &ax->osid);
-error_path:
- kfree(ctx);
- audit_panic("error in audit_ipc_context");
-ret:
- return NULL;
+ ax->d.type = AUDIT_IPC;
+ ax->d.next = context->aux;
+ context->aux = (void *)ax;
+ return 0;
}
/**
- * audit_ipc_perms - record audit data for ipc
+ * audit_ipc_set_perm - record audit data for new ipc permissions
* @qbytes: msgq bytes
* @uid: msgq user id
* @gid: msgq group id
@@ -1196,7 +1207,7 @@ ret:
*
* Returns 0 for success or NULL context or < 0 on error.
*/
-int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp)
+int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp)
{
struct audit_aux_data_ipcctl *ax;
struct audit_context *context = current->audit_context;
@@ -1212,9 +1223,9 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, str
ax->uid = uid;
ax->gid = gid;
ax->mode = mode;
- ax->ctx = audit_ipc_context(ipcp);
+ selinux_get_ipc_sid(ipcp, &ax->osid);
- ax->d.type = AUDIT_IPC;
+ ax->d.type = AUDIT_IPC_SET_PERM;
ax->d.next = context->aux;
context->aux = (void *)ax;
return 0;
diff --git a/kernel/compat.c b/kernel/compat.c
index b9bdd1271f4..c1601a84f8d 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -17,7 +17,6 @@
#include <linux/time.h>
#include <linux/signal.h>
#include <linux/sched.h> /* for MAX_SCHEDULE_TIMEOUT */
-#include <linux/futex.h> /* for FUTEX_WAIT */
#include <linux/syscalls.h>
#include <linux/unistd.h>
#include <linux/security.h>
@@ -239,28 +238,6 @@ asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set,
return ret;
}
-#ifdef CONFIG_FUTEX
-asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, int val,
- struct compat_timespec __user *utime, u32 __user *uaddr2,
- int val3)
-{
- struct timespec t;
- unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
- int val2 = 0;
-
- if ((op == FUTEX_WAIT) && utime) {
- if (get_compat_timespec(&t, utime))
- return -EFAULT;
- timeout = timespec_to_jiffies(&t) + 1;
- }
- if (op >= FUTEX_REQUEUE)
- val2 = (int) (unsigned long) utime;
-
- return do_futex((unsigned long)uaddr, op, val, timeout,
- (unsigned long)uaddr2, val2, val3);
-}
-#endif
-
asmlinkage long compat_sys_setrlimit(unsigned int resource,
struct compat_rlimit __user *rlim)
{
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 8be22bd8093..fe2b8d0bfe4 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -18,7 +18,7 @@
/* This protects CPUs going up and down... */
static DECLARE_MUTEX(cpucontrol);
-static struct notifier_block *cpu_chain;
+static BLOCKING_NOTIFIER_HEAD(cpu_chain);
#ifdef CONFIG_HOTPLUG_CPU
static struct task_struct *lock_cpu_hotplug_owner;
@@ -71,21 +71,13 @@ EXPORT_SYMBOL_GPL(lock_cpu_hotplug_interruptible);
/* Need to know about CPUs going up/down? */
int register_cpu_notifier(struct notifier_block *nb)
{
- int ret;
-
- if ((ret = lock_cpu_hotplug_interruptible()) != 0)
- return ret;
- ret = notifier_chain_register(&cpu_chain, nb);
- unlock_cpu_hotplug();
- return ret;
+ return blocking_notifier_chain_register(&cpu_chain, nb);
}
EXPORT_SYMBOL(register_cpu_notifier);
void unregister_cpu_notifier(struct notifier_block *nb)
{
- lock_cpu_hotplug();
- notifier_chain_unregister(&cpu_chain, nb);
- unlock_cpu_hotplug();
+ blocking_notifier_chain_unregister(&cpu_chain, nb);
}
EXPORT_SYMBOL(unregister_cpu_notifier);
@@ -141,7 +133,7 @@ int cpu_down(unsigned int cpu)
goto out;
}
- err = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE,
+ err = blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE,
(void *)(long)cpu);
if (err == NOTIFY_BAD) {
printk("%s: attempt to take down CPU %u failed\n",
@@ -159,7 +151,7 @@ int cpu_down(unsigned int cpu)
p = __stop_machine_run(take_cpu_down, NULL, cpu);
if (IS_ERR(p)) {
/* CPU didn't die: tell everyone. Can't complain. */
- if (notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED,
+ if (blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED,
(void *)(long)cpu) == NOTIFY_BAD)
BUG();
@@ -182,8 +174,8 @@ int cpu_down(unsigned int cpu)
put_cpu();
/* CPU is completely dead: tell everyone. Too late to complain. */
- if (notifier_call_chain(&cpu_chain, CPU_DEAD, (void *)(long)cpu)
- == NOTIFY_BAD)
+ if (blocking_notifier_call_chain(&cpu_chain, CPU_DEAD,
+ (void *)(long)cpu) == NOTIFY_BAD)
BUG();
check_for_tasks(cpu);
@@ -211,7 +203,7 @@ int __devinit cpu_up(unsigned int cpu)
goto out;
}
- ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
+ ret = blocking_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
if (ret == NOTIFY_BAD) {
printk("%s: attempt to bring up CPU %u failed\n",
__FUNCTION__, cpu);
@@ -226,11 +218,12 @@ int __devinit cpu_up(unsigned int cpu)
BUG_ON(!cpu_online(cpu));
/* Now call notifier in preparation. */
- notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
+ blocking_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
out_notify:
if (ret != 0)
- notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu);
+ blocking_notifier_call_chain(&cpu_chain,
+ CPU_UP_CANCELED, hcpu);
out:
unlock_cpu_hotplug();
return ret;
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 18aea1bd128..ab81fdd4572 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -616,12 +616,10 @@ static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
* current->cpuset if a task has its memory placement changed.
* Do not call this routine if in_interrupt().
*
- * Call without callback_mutex or task_lock() held. May be called
- * with or without manage_mutex held. Doesn't need task_lock to guard
- * against another task changing a non-NULL cpuset pointer to NULL,
- * as that is only done by a task on itself, and if the current task
- * is here, it is not simultaneously in the exit code NULL'ing its
- * cpuset pointer. This routine also might acquire callback_mutex and
+ * Call without callback_mutex or task_lock() held. May be
+ * called with or without manage_mutex held. Thanks in part to
+ * 'the_top_cpuset_hack', the tasks cpuset pointer will never
+ * be NULL. This routine also might acquire callback_mutex and
* current->mm->mmap_sem during call.
*
* Reading current->cpuset->mems_generation doesn't need task_lock
@@ -836,6 +834,55 @@ static int update_cpumask(struct cpuset *cs, char *buf)
}
/*
+ * cpuset_migrate_mm
+ *
+ * Migrate memory region from one set of nodes to another.
+ *
+ * Temporarilly set tasks mems_allowed to target nodes of migration,
+ * so that the migration code can allocate pages on these nodes.
+ *
+ * Call holding manage_mutex, so our current->cpuset won't change
+ * during this call, as manage_mutex holds off any attach_task()
+ * calls. Therefore we don't need to take task_lock around the
+ * call to guarantee_online_mems(), as we know no one is changing
+ * our tasks cpuset.
+ *
+ * Hold callback_mutex around the two modifications of our tasks
+ * mems_allowed to synchronize with cpuset_mems_allowed().
+ *
+ * While the mm_struct we are migrating is typically from some
+ * other task, the task_struct mems_allowed that we are hacking
+ * is for our current task, which must allocate new pages for that
+ * migrating memory region.
+ *
+ * We call cpuset_update_task_memory_state() before hacking
+ * our tasks mems_allowed, so that we are assured of being in
+ * sync with our tasks cpuset, and in particular, callbacks to
+ * cpuset_update_task_memory_state() from nested page allocations
+ * won't see any mismatch of our cpuset and task mems_generation
+ * values, so won't overwrite our hacked tasks mems_allowed
+ * nodemask.
+ */
+
+static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
+ const nodemask_t *to)
+{
+ struct task_struct *tsk = current;
+
+ cpuset_update_task_memory_state();
+
+ mutex_lock(&callback_mutex);
+ tsk->mems_allowed = *to;
+ mutex_unlock(&callback_mutex);
+
+ do_migrate_pages(mm, from, to, MPOL_MF_MOVE_ALL);
+
+ mutex_lock(&callback_mutex);
+ guarantee_online_mems(tsk->cpuset, &tsk->mems_allowed);
+ mutex_unlock(&callback_mutex);
+}
+
+/*
* Handle user request to change the 'mems' memory placement
* of a cpuset. Needs to validate the request, update the
* cpusets mems_allowed and mems_generation, and for each
@@ -947,10 +994,8 @@ static int update_nodemask(struct cpuset *cs, char *buf)
struct mm_struct *mm = mmarray[i];
mpol_rebind_mm(mm, &cs->mems_allowed);
- if (migrate) {
- do_migrate_pages(mm, &oldmem, &cs->mems_allowed,
- MPOL_MF_MOVE_ALL);
- }
+ if (migrate)
+ cpuset_migrate_mm(mm, &oldmem, &cs->mems_allowed);
mmput(mm);
}
@@ -1185,11 +1230,11 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
mm = get_task_mm(tsk);
if (mm) {
mpol_rebind_mm(mm, &to);
+ if (is_memory_migrate(cs))
+ cpuset_migrate_mm(mm, &from, &to);
mmput(mm);
}
- if (is_memory_migrate(cs))
- do_migrate_pages(tsk->mm, &from, &to, MPOL_MF_MOVE_ALL);
put_task_struct(tsk);
synchronize_rcu();
if (atomic_dec_and_test(&oldcs->count))
@@ -2186,19 +2231,25 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
* So only GFP_KERNEL allocations, if all nodes in the cpuset are
* short of memory, might require taking the callback_mutex mutex.
*
- * The first loop over the zonelist in mm/page_alloc.c:__alloc_pages()
- * calls here with __GFP_HARDWALL always set in gfp_mask, enforcing
- * hardwall cpusets - no allocation on a node outside the cpuset is
- * allowed (unless in interrupt, of course).
+ * The first call here from mm/page_alloc:get_page_from_freelist()
+ * has __GFP_HARDWALL set in gfp_mask, enforcing hardwall cpusets, so
+ * no allocation on a node outside the cpuset is allowed (unless in
+ * interrupt, of course).
*
- * The second loop doesn't even call here for GFP_ATOMIC requests
- * (if the __alloc_pages() local variable 'wait' is set). That check
- * and the checks below have the combined affect in the second loop of
- * the __alloc_pages() routine that:
+ * The second pass through get_page_from_freelist() doesn't even call
+ * here for GFP_ATOMIC calls. For those calls, the __alloc_pages()
+ * variable 'wait' is not set, and the bit ALLOC_CPUSET is not set
+ * in alloc_flags. That logic and the checks below have the combined
+ * affect that:
* in_interrupt - any node ok (current task context irrelevant)
* GFP_ATOMIC - any node ok
* GFP_KERNEL - any node in enclosing mem_exclusive cpuset ok
* GFP_USER - only nodes in current tasks mems allowed ok.
+ *
+ * Rule:
+ * Don't call cpuset_zone_allowed() if you can't sleep, unless you
+ * pass in the __GFP_HARDWALL flag set in gfp_flag, which disables
+ * the code that might scan up ancestor cpusets and sleep.
**/
int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
@@ -2210,6 +2261,7 @@ int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
if (in_interrupt())
return 1;
node = z->zone_pgdat->node_id;
+ might_sleep_if(!(gfp_mask & __GFP_HARDWALL));
if (node_isset(node, current->mems_allowed))
return 1;
if (gfp_mask & __GFP_HARDWALL) /* If hardwall request, stop here */
diff --git a/kernel/exit.c b/kernel/exit.c
index 8037405e136..e95b9328221 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -29,8 +29,13 @@
#include <linux/cpuset.h>
#include <linux/syscalls.h>
#include <linux/signal.h>
+#include <linux/posix-timers.h>
#include <linux/cn_proc.h>
#include <linux/mutex.h>
+#include <linux/futex.h>
+#include <linux/compat.h>
+#include <linux/pipe_fs_i.h>
+#include <linux/audit.h> /* for audit_free() */
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -48,15 +53,85 @@ static void __unhash_process(struct task_struct *p)
{
nr_threads--;
detach_pid(p, PIDTYPE_PID);
- detach_pid(p, PIDTYPE_TGID);
if (thread_group_leader(p)) {
detach_pid(p, PIDTYPE_PGID);
detach_pid(p, PIDTYPE_SID);
- if (p->pid)
- __get_cpu_var(process_counts)--;
+
+ list_del_rcu(&p->tasks);
+ __get_cpu_var(process_counts)--;
}
+ list_del_rcu(&p->thread_group);
+ remove_parent(p);
+}
+
+/*
+ * This function expects the tasklist_lock write-locked.
+ */
+static void __exit_signal(struct task_struct *tsk)
+{
+ struct signal_struct *sig = tsk->signal;
+ struct sighand_struct *sighand;
+
+ BUG_ON(!sig);
+ BUG_ON(!atomic_read(&sig->count));
+
+ rcu_read_lock();
+ sighand = rcu_dereference(tsk->sighand);
+ spin_lock(&sighand->siglock);
- REMOVE_LINKS(p);
+ posix_cpu_timers_exit(tsk);
+ if (atomic_dec_and_test(&sig->count))
+ posix_cpu_timers_exit_group(tsk);
+ else {
+ /*
+ * If there is any task waiting for the group exit
+ * then notify it:
+ */
+ if (sig->group_exit_task && atomic_read(&sig->count) == sig->notify_count) {
+ wake_up_process(sig->group_exit_task);
+ sig->group_exit_task = NULL;
+ }
+ if (tsk == sig->curr_target)
+ sig->curr_target = next_thread(tsk);
+ /*
+ * Accumulate here the counters for all threads but the
+ * group leader as they die, so they can be added into
+ * the process-wide totals when those are taken.
+ * The group leader stays around as a zombie as long
+ * as there are other threads. When it gets reaped,
+ * the exit.c code will add its counts into these totals.
+ * We won't ever get here for the group leader, since it
+ * will have been the last reference on the signal_struct.
+ */
+ sig->utime = cputime_add(sig->utime, tsk->utime);
+ sig->stime = cputime_add(sig->stime, tsk->stime);
+ sig->min_flt += tsk->min_flt;
+ sig->maj_flt += tsk->maj_flt;
+ sig->nvcsw += tsk->nvcsw;
+ sig->nivcsw += tsk->nivcsw;
+ sig->sched_time += tsk->sched_time;
+ sig = NULL; /* Marker for below. */
+ }
+
+ __unhash_process(tsk);
+
+ tsk->signal = NULL;
+ tsk->sighand = NULL;
+ spin_unlock(&sighand->siglock);
+ rcu_read_unlock();
+
+ __cleanup_sighand(sighand);
+ clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
+ flush_sigqueue(&tsk->pending);
+ if (sig) {
+ flush_sigqueue(&sig->shared_pending);
+ __cleanup_signal(sig);
+ }
+}
+
+static void delayed_put_task_struct(struct rcu_head *rhp)
+{
+ put_task_struct(container_of(rhp, struct task_struct, rcu));
}
void release_task(struct task_struct * p)
@@ -65,21 +140,14 @@ void release_task(struct task_struct * p)
task_t *leader;
struct dentry *proc_dentry;
-repeat:
+repeat:
atomic_dec(&p->user->processes);
spin_lock(&p->proc_lock);
proc_dentry = proc_pid_unhash(p);
write_lock_irq(&tasklist_lock);
- if (unlikely(p->ptrace))
- __ptrace_unlink(p);
+ ptrace_unlink(p);
BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
__exit_signal(p);
- /*
- * Note that the fastpath in sys_times depends on __exit_signal having
- * updated the counters before a task is removed from the tasklist of
- * the process by __unhash_process.
- */
- __unhash_process(p);
/*
* If we are the last non-leader member of the thread
@@ -107,28 +175,13 @@ repeat:
spin_unlock(&p->proc_lock);
proc_pid_flush(proc_dentry);
release_thread(p);
- put_task_struct(p);
+ call_rcu(&p->rcu, delayed_put_task_struct);
p = leader;
if (unlikely(zap_leader))
goto repeat;
}
-/* we are using it only for SMP init */
-
-void unhash_process(struct task_struct *p)
-{
- struct dentry *proc_dentry;
-
- spin_lock(&p->proc_lock);
- proc_dentry = proc_pid_unhash(p);
- write_lock_irq(&tasklist_lock);
- __unhash_process(p);
- write_unlock_irq(&tasklist_lock);
- spin_unlock(&p->proc_lock);
- proc_pid_flush(proc_dentry);
-}
-
/*
* This checks not only the pgrp, but falls back on the pid if no
* satisfactory pgrp is found. I dunno - gdb doesn't work correctly
@@ -236,10 +289,10 @@ static void reparent_to_init(void)
ptrace_unlink(current);
/* Reparent to init */
- REMOVE_LINKS(current);
+ remove_parent(current);
current->parent = child_reaper;
current->real_parent = child_reaper;
- SET_LINKS(current);
+ add_parent(current);
/* Set the exit signal to SIGCHLD so we signal init on exit */
current->exit_signal = SIGCHLD;
@@ -536,13 +589,13 @@ static void exit_mm(struct task_struct * tsk)
mmput(mm);
}
-static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_reaper)
+static inline void choose_new_parent(task_t *p, task_t *reaper)
{
/*
* Make sure we're not reparenting to ourselves and that
* the parent is not a zombie.
*/
- BUG_ON(p == reaper || reaper->exit_state >= EXIT_ZOMBIE);
+ BUG_ON(p == reaper || reaper->exit_state);
p->real_parent = reaper;
}
@@ -567,9 +620,9 @@ static void reparent_thread(task_t *p, task_t *father, int traced)
* anyway, so let go of it.
*/
p->ptrace = 0;
- list_del_init(&p->sibling);
+ remove_parent(p);
p->parent = p->real_parent;
- list_add_tail(&p->sibling, &p->parent->children);
+ add_parent(p);
/* If we'd notified the old parent about this child's death,
* also notify the new parent.
@@ -643,7 +696,7 @@ static void forget_original_parent(struct task_struct * father,
if (father == p->real_parent) {
/* reparent with a reaper, real father it's us */
- choose_new_parent(p, reaper, child_reaper);
+ choose_new_parent(p, reaper);
reparent_thread(p, father, 0);
} else {
/* reparent ptraced task to its real parent */
@@ -664,7 +717,7 @@ static void forget_original_parent(struct task_struct * father,
}
list_for_each_safe(_p, _n, &father->ptrace_children) {
p = list_entry(_p,struct task_struct,ptrace_list);
- choose_new_parent(p, reaper, child_reaper);
+ choose_new_parent(p, reaper);
reparent_thread(p, father, 1);
}
}
@@ -805,7 +858,7 @@ fastcall NORET_TYPE void do_exit(long code)
panic("Aiee, killing interrupt handler!");
if (unlikely(!tsk->pid))
panic("Attempted to kill the idle task!");
- if (unlikely(tsk->pid == 1))
+ if (unlikely(tsk == child_reaper))
panic("Attempted to kill init!");
if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
@@ -852,6 +905,14 @@ fastcall NORET_TYPE void do_exit(long code)
exit_itimers(tsk->signal);
acct_process(code);
}
+ if (unlikely(tsk->robust_list))
+ exit_robust_list(tsk);
+#ifdef CONFIG_COMPAT
+ if (unlikely(tsk->compat_robust_list))
+ compat_exit_robust_list(tsk);
+#endif
+ if (unlikely(tsk->audit_context))
+ audit_free(tsk);
exit_mm(tsk);
exit_sem(tsk);
@@ -884,6 +945,9 @@ fastcall NORET_TYPE void do_exit(long code)
if (tsk->io_context)
exit_io_context();
+ if (tsk->splice_pipe)
+ __free_pipe_info(tsk->splice_pipe);
+
/* PF_DEAD causes final put_task_struct after we schedule. */
preempt_disable();
BUG_ON(tsk->flags & PF_DEAD);
@@ -912,13 +976,6 @@ asmlinkage long sys_exit(int error_code)
do_exit((error_code&0xff)<<8);
}
-task_t fastcall *next_thread(const task_t *p)
-{
- return pid_task(p->pids[PIDTYPE_TGID].pid_list.next, PIDTYPE_TGID);
-}
-
-EXPORT_SYMBOL(next_thread);
-
/*
* Take down every thread in the group. This is called by fatal signals
* as well as by sys_exit_group (below).
@@ -933,7 +990,6 @@ do_group_exit(int exit_code)
else if (!thread_group_empty(current)) {
struct signal_struct *const sig = current->signal;
struct sighand_struct *const sighand = current->sighand;
- read_lock(&tasklist_lock);
spin_lock_irq(&sighand->siglock);
if (sig->flags & SIGNAL_GROUP_EXIT)
/* Another thread got here before we took the lock. */
@@ -943,7 +999,6 @@ do_group_exit(int exit_code)
zap_other_threads(current);
}
spin_unlock_irq(&sighand->siglock);
- read_unlock(&tasklist_lock);
}
do_exit(exit_code);
@@ -1273,7 +1328,7 @@ bail_ref:
/* move to end of parent's list to avoid starvation */
remove_parent(p);
- add_parent(p, p->parent);
+ add_parent(p);
write_unlock_irq(&tasklist_lock);
diff --git a/kernel/extable.c b/kernel/extable.c
index 7501b531cee..7fe26285531 100644
--- a/kernel/extable.c
+++ b/kernel/extable.c
@@ -40,7 +40,7 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr)
return e;
}
-static int core_kernel_text(unsigned long addr)
+int core_kernel_text(unsigned long addr)
{
if (addr >= (unsigned long)_stext &&
addr <= (unsigned long)_etext)
diff --git a/kernel/fork.c b/kernel/fork.c
index e0a2b449dea..ac8100e3088 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -84,7 +84,7 @@ static kmem_cache_t *task_struct_cachep;
#endif
/* SLAB cache for signal_struct structures (tsk->signal) */
-kmem_cache_t *signal_cachep;
+static kmem_cache_t *signal_cachep;
/* SLAB cache for sighand_struct structures (tsk->sighand) */
kmem_cache_t *sighand_cachep;
@@ -108,16 +108,12 @@ void free_task(struct task_struct *tsk)
}
EXPORT_SYMBOL(free_task);
-void __put_task_struct_cb(struct rcu_head *rhp)
+void __put_task_struct(struct task_struct *tsk)
{
- struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
-
WARN_ON(!(tsk->exit_state & (EXIT_DEAD | EXIT_ZOMBIE)));
WARN_ON(atomic_read(&tsk->usage));
WARN_ON(tsk == current);
- if (unlikely(tsk->audit_context))
- audit_free(tsk);
security_task_free(tsk);
free_uid(tsk->user);
put_group_info(tsk->group_info);
@@ -182,6 +178,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
atomic_set(&tsk->usage,2);
atomic_set(&tsk->fs_excl, 0);
tsk->btrace_seq = 0;
+ tsk->splice_pipe = NULL;
return tsk;
}
@@ -721,7 +718,7 @@ out_release:
free_fdset (new_fdt->open_fds, new_fdt->max_fdset);
free_fd_array(new_fdt->fd, new_fdt->max_fds);
kmem_cache_free(files_cachep, newf);
- goto out;
+ return NULL;
}
static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
@@ -786,14 +783,6 @@ int unshare_files(void)
EXPORT_SYMBOL(unshare_files);
-void sighand_free_cb(struct rcu_head *rhp)
-{
- struct sighand_struct *sp;
-
- sp = container_of(rhp, struct sighand_struct, rcu);
- kmem_cache_free(sighand_cachep, sp);
-}
-
static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk)
{
struct sighand_struct *sig;
@@ -806,12 +795,17 @@ static inline int copy_sighand(unsigned long clone_flags, struct task_struct * t
rcu_assign_pointer(tsk->sighand, sig);
if (!sig)
return -ENOMEM;
- spin_lock_init(&sig->siglock);
atomic_set(&sig->count, 1);
memcpy(sig->action, current->sighand->action, sizeof(sig->action));
return 0;
}
+void __cleanup_sighand(struct sighand_struct *sighand)
+{
+ if (atomic_dec_and_test(&sighand->count))
+ kmem_cache_free(sighand_cachep, sighand);
+}
+
static inline int copy_signal(unsigned long clone_flags, struct task_struct * tsk)
{
struct signal_struct *sig;
@@ -881,6 +875,22 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
return 0;
}
+void __cleanup_signal(struct signal_struct *sig)
+{
+ exit_thread_group_keys(sig);
+ kmem_cache_free(signal_cachep, sig);
+}
+
+static inline void cleanup_signal(struct task_struct *tsk)
+{
+ struct signal_struct *sig = tsk->signal;
+
+ atomic_dec(&sig->live);
+
+ if (atomic_dec_and_test(&sig->count))
+ __cleanup_signal(sig);
+}
+
static inline void copy_flags(unsigned long clone_flags, struct task_struct *p)
{
unsigned long new_flags = p->flags;
@@ -1061,7 +1071,10 @@ static task_t *copy_process(unsigned long clone_flags,
* Clear TID on mm_release()?
*/
p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL;
-
+ p->robust_list = NULL;
+#ifdef CONFIG_COMPAT
+ p->compat_robust_list = NULL;
+#endif
/*
* sigaltstack should be cleared when sharing the same VM
*/
@@ -1092,6 +1105,7 @@ static task_t *copy_process(unsigned long clone_flags,
* We dont wake it up yet.
*/
p->group_leader = p;
+ INIT_LIST_HEAD(&p->thread_group);
INIT_LIST_HEAD(&p->ptrace_children);
INIT_LIST_HEAD(&p->ptrace_list);
@@ -1115,16 +1129,6 @@ static task_t *copy_process(unsigned long clone_flags,
!cpu_online(task_cpu(p))))
set_task_cpu(p, smp_processor_id());
- /*
- * Check for pending SIGKILL! The new thread should not be allowed
- * to slip out of an OOM kill. (or normal SIGKILL.)
- */
- if (sigismember(&current->pending.signal, SIGKILL)) {
- write_unlock_irq(&tasklist_lock);
- retval = -EINTR;
- goto bad_fork_cleanup_namespace;
- }
-
/* CLONE_PARENT re-uses the old parent */
if (clone_flags & (CLONE_PARENT|CLONE_THREAD))
p->real_parent = current->real_parent;
@@ -1133,6 +1137,23 @@ static task_t *copy_process(unsigned long clone_flags,
p->parent = p->real_parent;
spin_lock(&current->sighand->siglock);
+
+ /*
+ * Process group and session signals need to be delivered to just the
+ * parent before the fork or both the parent and the child after the
+ * fork. Restart if a signal comes in before we add the new process to
+ * it's process group.
+ * A fatal signal pending means that current will exit, so the new
+ * thread can't slip out of an OOM kill (or normal SIGKILL).
+ */
+ recalc_sigpending();
+ if (signal_pending(current)) {
+ spin_unlock(&current->sighand->siglock);
+ write_unlock_irq(&tasklist_lock);
+ retval = -ERESTARTNOINTR;
+ goto bad_fork_cleanup_namespace;
+ }
+
if (clone_flags & CLONE_THREAD) {
/*
* Important: if an exit-all has been started then
@@ -1145,17 +1166,9 @@ static task_t *copy_process(unsigned long clone_flags,
retval = -EAGAIN;
goto bad_fork_cleanup_namespace;
}
- p->group_leader = current->group_leader;
- if (current->signal->group_stop_count > 0) {
- /*
- * There is an all-stop in progress for the group.
- * We ourselves will stop as soon as we check signals.
- * Make the new thread part of that group stop too.
- */
- current->signal->group_stop_count++;
- set_tsk_thread_flag(p, TIF_SIGPENDING);
- }
+ p->group_leader = current->group_leader;
+ list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
if (!cputime_eq(current->signal->it_virt_expires,
cputime_zero) ||
@@ -1178,23 +1191,25 @@ static task_t *copy_process(unsigned long clone_flags,
*/
p->ioprio = current->ioprio;
- SET_LINKS(p);
- if (unlikely(p->ptrace & PT_PTRACED))
- __ptrace_link(p, current->parent);
-
- if (thread_group_leader(p)) {
- p->signal->tty = current->signal->tty;
- p->signal->pgrp = process_group(current);
- p->signal->session = current->signal->session;
- attach_pid(p, PIDTYPE_PGID, process_group(p));
- attach_pid(p, PIDTYPE_SID, p->signal->session);
- if (p->pid)
+ if (likely(p->pid)) {
+ add_parent(p);
+ if (unlikely(p->ptrace & PT_PTRACED))
+ __ptrace_link(p, current->parent);
+
+ if (thread_group_leader(p)) {
+ p->signal->tty = current->signal->tty;
+ p->signal->pgrp = process_group(current);
+ p->signal->session = current->signal->session;
+ attach_pid(p, PIDTYPE_PGID, process_group(p));
+ attach_pid(p, PIDTYPE_SID, p->signal->session);
+
+ list_add_tail_rcu(&p->tasks, &init_task.tasks);
__get_cpu_var(process_counts)++;
+ }
+ attach_pid(p, PIDTYPE_PID, p->pid);
+ nr_threads++;
}
- attach_pid(p, PIDTYPE_TGID, p->tgid);
- attach_pid(p, PIDTYPE_PID, p->pid);
- nr_threads++;
total_forks++;
spin_unlock(&current->sighand->siglock);
write_unlock_irq(&tasklist_lock);
@@ -1209,9 +1224,9 @@ bad_fork_cleanup_mm:
if (p->mm)
mmput(p->mm);
bad_fork_cleanup_signal:
- exit_signal(p);
+ cleanup_signal(p);
bad_fork_cleanup_sighand:
- exit_sighand(p);
+ __cleanup_sighand(p->sighand);
bad_fork_cleanup_fs:
exit_fs(p); /* blocking */
bad_fork_cleanup_files:
@@ -1258,7 +1273,7 @@ task_t * __devinit fork_idle(int cpu)
if (!task)
return ERR_PTR(-ENOMEM);
init_idle(task, cpu);
- unhash_process(task);
+
return task;
}
@@ -1293,17 +1308,19 @@ long do_fork(unsigned long clone_flags,
{
struct task_struct *p;
int trace = 0;
- long pid = alloc_pidmap();
+ struct pid *pid = alloc_pid();
+ long nr;
- if (pid < 0)
+ if (!pid)
return -EAGAIN;
+ nr = pid->nr;
if (unlikely(current->ptrace)) {
trace = fork_traceflag (clone_flags);
if (trace)
clone_flags |= CLONE_PTRACE;
}
- p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);
+ p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, nr);
/*
* Do this prior waking up the new thread - the thread pointer
* might get invalid after that point, if the thread exits quickly.
@@ -1330,7 +1347,7 @@ long do_fork(unsigned long clone_flags,
p->state = TASK_STOPPED;
if (unlikely (trace)) {
- current->ptrace_message = pid;
+ current->ptrace_message = nr;
ptrace_notify ((trace << 8) | SIGTRAP);
}
@@ -1340,21 +1357,31 @@ long do_fork(unsigned long clone_flags,
ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
}
} else {
- free_pidmap(pid);
- pid = PTR_ERR(p);
+ free_pid(pid);
+ nr = PTR_ERR(p);
}
- return pid;
+ return nr;
}
#ifndef ARCH_MIN_MMSTRUCT_ALIGN
#define ARCH_MIN_MMSTRUCT_ALIGN 0
#endif
+static void sighand_ctor(void *data, kmem_cache_t *cachep, unsigned long flags)
+{
+ struct sighand_struct *sighand = data;
+
+ if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR)
+ spin_lock_init(&sighand->siglock);
+}
+
void __init proc_caches_init(void)
{
sighand_cachep = kmem_cache_create("sighand_cache",
sizeof(struct sighand_struct), 0,
- SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+ SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_DESTROY_BY_RCU,
+ sighand_ctor, NULL);
signal_cachep = kmem_cache_create("signal_cache",
sizeof(struct signal_struct), 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
diff --git a/kernel/futex.c b/kernel/futex.c
index 5efa2f97803..5699c512057 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -8,6 +8,10 @@
* Removed page pinning, fix privately mapped COW pages and other cleanups
* (C) Copyright 2003, 2004 Jamie Lokier
*
+ * Robust futex support started by Ingo Molnar
+ * (C) Copyright 2006 Red Hat Inc, All Rights Reserved
+ * Thanks to Thomas Gleixner for suggestions, analysis and fixes.
+ *
* Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly
* enough at me, Linus for the original (flawed) idea, Matthew
* Kirkwood for proof-of-concept implementation.
@@ -829,6 +833,172 @@ error:
goto out;
}
+/*
+ * Support for robust futexes: the kernel cleans up held futexes at
+ * thread exit time.
+ *
+ * Implementation: user-space maintains a per-thread list of locks it
+ * is holding. Upon do_exit(), the kernel carefully walks this list,
+ * and marks all locks that are owned by this thread with the
+ * FUTEX_OWNER_DEAD bit, and wakes up a waiter (if any). The list is
+ * always manipulated with the lock held, so the list is private and
+ * per-thread. Userspace also maintains a per-thread 'list_op_pending'
+ * field, to allow the kernel to clean up if the thread dies after
+ * acquiring the lock, but just before it could have added itself to
+ * the list. There can only be one such pending lock.
+ */
+
+/**
+ * sys_set_robust_list - set the robust-futex list head of a task
+ * @head: pointer to the list-head
+ * @len: length of the list-head, as userspace expects
+ */
+asmlinkage long
+sys_set_robust_list(struct robust_list_head __user *head,
+ size_t len)
+{
+ /*
+ * The kernel knows only one size for now:
+ */
+ if (unlikely(len != sizeof(*head)))
+ return -EINVAL;
+
+ current->robust_list = head;
+
+ return 0;
+}
+
+/**
+ * sys_get_robust_list - get the robust-futex list head of a task
+ * @pid: pid of the process [zero for current task]
+ * @head_ptr: pointer to a list-head pointer, the kernel fills it in
+ * @len_ptr: pointer to a length field, the kernel fills in the header size
+ */
+asmlinkage long
+sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr,
+ size_t __user *len_ptr)
+{
+ struct robust_list_head *head;
+ unsigned long ret;
+
+ if (!pid)
+ head = current->robust_list;
+ else {
+ struct task_struct *p;
+
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (!p)
+ goto err_unlock;
+ ret = -EPERM;
+ if ((current->euid != p->euid) && (current->euid != p->uid) &&
+ !capable(CAP_SYS_PTRACE))
+ goto err_unlock;
+ head = p->robust_list;
+ read_unlock(&tasklist_lock);
+ }
+
+ if (put_user(sizeof(*head), len_ptr))
+ return -EFAULT;
+ return put_user(head, head_ptr);
+
+err_unlock:
+ read_unlock(&tasklist_lock);
+
+ return ret;
+}
+
+/*
+ * Process a futex-list entry, check whether it's owned by the
+ * dying task, and do notification if so:
+ */
+int handle_futex_death(u32 __user *uaddr, struct task_struct *curr)
+{
+ u32 uval;
+
+retry:
+ if (get_user(uval, uaddr))
+ return -1;
+
+ if ((uval & FUTEX_TID_MASK) == curr->pid) {
+ /*
+ * Ok, this dying thread is truly holding a futex
+ * of interest. Set the OWNER_DIED bit atomically
+ * via cmpxchg, and if the value had FUTEX_WAITERS
+ * set, wake up a waiter (if any). (We have to do a
+ * futex_wake() even if OWNER_DIED is already set -
+ * to handle the rare but possible case of recursive
+ * thread-death.) The rest of the cleanup is done in
+ * userspace.
+ */
+ if (futex_atomic_cmpxchg_inatomic(uaddr, uval,
+ uval | FUTEX_OWNER_DIED) != uval)
+ goto retry;
+
+ if (uval & FUTEX_WAITERS)
+ futex_wake((unsigned long)uaddr, 1);
+ }
+ return 0;
+}
+
+/*
+ * Walk curr->robust_list (very carefully, it's a userspace list!)
+ * and mark any locks found there dead, and notify any waiters.
+ *
+ * We silently return on any sign of list-walking problem.
+ */
+void exit_robust_list(struct task_struct *curr)
+{
+ struct robust_list_head __user *head = curr->robust_list;
+ struct robust_list __user *entry, *pending;
+ unsigned int limit = ROBUST_LIST_LIMIT;
+ unsigned long futex_offset;
+
+ /*
+ * Fetch the list head (which was registered earlier, via
+ * sys_set_robust_list()):
+ */
+ if (get_user(entry, &head->list.next))
+ return;
+ /*
+ * Fetch the relative futex offset:
+ */
+ if (get_user(futex_offset, &head->futex_offset))
+ return;
+ /*
+ * Fetch any possibly pending lock-add first, and handle it
+ * if it exists:
+ */
+ if (get_user(pending, &head->list_op_pending))
+ return;
+ if (pending)
+ handle_futex_death((void *)pending + futex_offset, curr);
+
+ while (entry != &head->list) {
+ /*
+ * A pending lock might already be on the list, so
+ * dont process it twice:
+ */
+ if (entry != pending)
+ if (handle_futex_death((void *)entry + futex_offset,
+ curr))
+ return;
+ /*
+ * Fetch the next entry in the list:
+ */
+ if (get_user(entry, &entry->next))
+ return;
+ /*
+ * Avoid excessively long or circular lists:
+ */
+ if (!--limit)
+ break;
+
+ cond_resched();
+ }
+}
+
long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout,
unsigned long uaddr2, int val2, int val3)
{
@@ -869,9 +1039,11 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, int val,
unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
int val2 = 0;
- if ((op == FUTEX_WAIT) && utime) {
+ if (utime && (op == FUTEX_WAIT)) {
if (copy_from_user(&t, utime, sizeof(t)) != 0)
return -EFAULT;
+ if (!timespec_valid(&t))
+ return -EINVAL;
timeout = timespec_to_jiffies(&t) + 1;
}
/*
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
new file mode 100644
index 00000000000..1ab6a0ea3d1
--- /dev/null
+++ b/kernel/futex_compat.c
@@ -0,0 +1,144 @@
+/*
+ * linux/kernel/futex_compat.c
+ *
+ * Futex compatibililty routines.
+ *
+ * Copyright 2006, Red Hat, Inc., Ingo Molnar
+ */
+
+#include <linux/linkage.h>
+#include <linux/compat.h>
+#include <linux/futex.h>
+
+#include <asm/uaccess.h>
+
+/*
+ * Walk curr->robust_list (very carefully, it's a userspace list!)
+ * and mark any locks found there dead, and notify any waiters.
+ *
+ * We silently return on any sign of list-walking problem.
+ */
+void compat_exit_robust_list(struct task_struct *curr)
+{
+ struct compat_robust_list_head __user *head = curr->compat_robust_list;
+ struct robust_list __user *entry, *pending;
+ compat_uptr_t uentry, upending;
+ unsigned int limit = ROBUST_LIST_LIMIT;
+ compat_long_t futex_offset;
+
+ /*
+ * Fetch the list head (which was registered earlier, via
+ * sys_set_robust_list()):
+ */
+ if (get_user(uentry, &head->list.next))
+ return;
+ entry = compat_ptr(uentry);
+ /*
+ * Fetch the relative futex offset:
+ */
+ if (get_user(futex_offset, &head->futex_offset))
+ return;
+ /*
+ * Fetch any possibly pending lock-add first, and handle it
+ * if it exists:
+ */
+ if (get_user(upending, &head->list_op_pending))
+ return;
+ pending = compat_ptr(upending);
+ if (upending)
+ handle_futex_death((void *)pending + futex_offset, curr);
+
+ while (compat_ptr(uentry) != &head->list) {
+ /*
+ * A pending lock might already be on the list, so
+ * dont process it twice:
+ */
+ if (entry != pending)
+ if (handle_futex_death((void *)entry + futex_offset,
+ curr))
+ return;
+
+ /*
+ * Fetch the next entry in the list:
+ */
+ if (get_user(uentry, (compat_uptr_t *)&entry->next))
+ return;
+ entry = compat_ptr(uentry);
+ /*
+ * Avoid excessively long or circular lists:
+ */
+ if (!--limit)
+ break;
+
+ cond_resched();
+ }
+}
+
+asmlinkage long
+compat_sys_set_robust_list(struct compat_robust_list_head __user *head,
+ compat_size_t len)
+{
+ if (unlikely(len != sizeof(*head)))
+ return -EINVAL;
+
+ current->compat_robust_list = head;
+
+ return 0;
+}
+
+asmlinkage long
+compat_sys_get_robust_list(int pid, compat_uptr_t *head_ptr,
+ compat_size_t __user *len_ptr)
+{
+ struct compat_robust_list_head *head;
+ unsigned long ret;
+
+ if (!pid)
+ head = current->compat_robust_list;
+ else {
+ struct task_struct *p;
+
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (!p)
+ goto err_unlock;
+ ret = -EPERM;
+ if ((current->euid != p->euid) && (current->euid != p->uid) &&
+ !capable(CAP_SYS_PTRACE))
+ goto err_unlock;
+ head = p->compat_robust_list;
+ read_unlock(&tasklist_lock);
+ }
+
+ if (put_user(sizeof(*head), len_ptr))
+ return -EFAULT;
+ return put_user(ptr_to_compat(head), head_ptr);
+
+err_unlock:
+ read_unlock(&tasklist_lock);
+
+ return ret;
+}
+
+asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
+ struct compat_timespec __user *utime, u32 __user *uaddr2,
+ u32 val3)
+{
+ struct timespec t;
+ unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
+ int val2 = 0;
+
+ if (utime && (op == FUTEX_WAIT)) {
+ if (get_compat_timespec(&t, utime))
+ return -EFAULT;
+ if (!timespec_valid(&t))
+ return -EINVAL;
+ timeout = timespec_to_jiffies(&t) + 1;
+ }
+ if (op >= FUTEX_REQUEUE)
+ val2 = (int) (unsigned long) utime;
+
+ return do_futex((unsigned long)uaddr, op, val, timeout,
+ (unsigned long)uaddr2, val2, val3);
+}
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 0237a556eb1..01fa2ae98a8 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -456,6 +456,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
return ret;
}
+EXPORT_SYMBOL_GPL(hrtimer_start);
/**
* hrtimer_try_to_cancel - try to deactivate a timer
@@ -484,6 +485,7 @@ int hrtimer_try_to_cancel(struct hrtimer *timer)
return ret;
}
+EXPORT_SYMBOL_GPL(hrtimer_try_to_cancel);
/**
* hrtimer_cancel - cancel a timer and wait for the handler to finish.
@@ -501,8 +503,10 @@ int hrtimer_cancel(struct hrtimer *timer)
if (ret >= 0)
return ret;
+ cpu_relax();
}
}
+EXPORT_SYMBOL_GPL(hrtimer_cancel);
/**
* hrtimer_get_remaining - get remaining time for the timer
@@ -521,6 +525,7 @@ ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
return rem;
}
+EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
#ifdef CONFIG_NO_IDLE_HZ
/**
@@ -579,6 +584,7 @@ void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
timer->base = &bases[clock_id];
timer->node.rb_parent = HRTIMER_INACTIVE;
}
+EXPORT_SYMBOL_GPL(hrtimer_init);
/**
* hrtimer_get_res - get the timer resolution for a clock
@@ -598,6 +604,7 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
return 0;
}
+EXPORT_SYMBOL_GPL(hrtimer_get_res);
/*
* Expire the per base hrtimer-queue:
@@ -606,6 +613,9 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base)
{
struct rb_node *node;
+ if (!base->first)
+ return;
+
if (base->get_softirq_time)
base->softirq_time = base->get_softirq_time();
@@ -655,29 +665,28 @@ void hrtimer_run_queues(void)
/*
* Sleep related functions:
*/
-
-struct sleep_hrtimer {
- struct hrtimer timer;
- struct task_struct *task;
- int expired;
-};
-
-static int nanosleep_wakeup(struct hrtimer *timer)
+static int hrtimer_wakeup(struct hrtimer *timer)
{
- struct sleep_hrtimer *t =
- container_of(timer, struct sleep_hrtimer, timer);
+ struct hrtimer_sleeper *t =
+ container_of(timer, struct hrtimer_sleeper, timer);
+ struct task_struct *task = t->task;
- t->expired = 1;
- wake_up_process(t->task);
+ t->task = NULL;
+ if (task)
+ wake_up_process(task);
return HRTIMER_NORESTART;
}
-static int __sched do_nanosleep(struct sleep_hrtimer *t, enum hrtimer_mode mode)
+void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, task_t *task)
{
- t->timer.function = nanosleep_wakeup;
- t->task = current;
- t->expired = 0;
+ sl->timer.function = hrtimer_wakeup;
+ sl->task = task;
+}
+
+static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
+{
+ hrtimer_init_sleeper(t, current);
do {
set_current_state(TASK_INTERRUPTIBLE);
@@ -685,18 +694,17 @@ static int __sched do_nanosleep(struct sleep_hrtimer *t, enum hrtimer_mode mode)
schedule();
- if (unlikely(!t->expired)) {
- hrtimer_cancel(&t->timer);
- mode = HRTIMER_ABS;
- }
- } while (!t->expired && !signal_pending(current));
+ hrtimer_cancel(&t->timer);
+ mode = HRTIMER_ABS;
+
+ } while (t->task && !signal_pending(current));
- return t->expired;
+ return t->task == NULL;
}
static long __sched nanosleep_restart(struct restart_block *restart)
{
- struct sleep_hrtimer t;
+ struct hrtimer_sleeper t;
struct timespec __user *rmtp;
struct timespec tu;
ktime_t time;
@@ -729,7 +737,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
const enum hrtimer_mode mode, const clockid_t clockid)
{
struct restart_block *restart;
- struct sleep_hrtimer t;
+ struct hrtimer_sleeper t;
struct timespec tu;
ktime_t rem;
@@ -834,7 +842,7 @@ static void migrate_hrtimers(int cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
-static int __devinit hrtimer_cpu_notify(struct notifier_block *self,
+static int hrtimer_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
long cpu = (long)hcpu;
@@ -858,7 +866,7 @@ static int __devinit hrtimer_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata hrtimers_nb = {
+static struct notifier_block hrtimers_nb = {
.notifier_call = hrtimer_cpu_notify,
};
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 2b33f852be3..9f77f50d814 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -1,4 +1,5 @@
-obj-y := handle.o manage.o spurious.o migration.o
+obj-y := handle.o manage.o spurious.o
obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
obj-$(CONFIG_PROC_FS) += proc.o
+obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index ac766ad573e..1279e349953 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -246,8 +246,10 @@ int setup_irq(unsigned int irq, struct irqaction * new)
mismatch:
spin_unlock_irqrestore(&desc->lock, flags);
- printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__);
- dump_stack();
+ if (!(new->flags & SA_PROBEIRQ)) {
+ printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__);
+ dump_stack();
+ }
return -EBUSY;
}
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index 52a8655fa08..134f9f2e0e3 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -1,6 +1,5 @@
-#include <linux/irq.h>
-#if defined(CONFIG_GENERIC_PENDING_IRQ)
+#include <linux/irq.h>
void set_pending_irq(unsigned int irq, cpumask_t mask)
{
@@ -61,5 +60,3 @@ void move_native_irq(int irq)
}
cpus_clear(pending_irq_cpumask[irq]);
}
-
-#endif
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 51a892063aa..20a997c73c3 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -170,7 +170,7 @@ static int wait_for_helper(void *data)
sa.sa.sa_handler = SIG_IGN;
sa.sa.sa_flags = 0;
siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD));
- do_sigaction(SIGCHLD, &sa, (struct k_sigaction *)0);
+ do_sigaction(SIGCHLD, &sa, NULL);
allow_signal(SIGCHLD);
pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 1156eb0977d..1fbf466a29a 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -585,6 +585,9 @@ int __kprobes register_kretprobe(struct kretprobe *rp)
int i;
rp->kp.pre_handler = pre_handler_kretprobe;
+ rp->kp.post_handler = NULL;
+ rp->kp.fault_handler = NULL;
+ rp->kp.break_handler = NULL;
/* Pre-allocate memory for max kretprobe instances */
if (rp->maxactive <= 0) {
diff --git a/kernel/module.c b/kernel/module.c
index ddfe45ac2fd..bbe04862e1b 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -64,26 +64,17 @@ static DEFINE_SPINLOCK(modlist_lock);
static DEFINE_MUTEX(module_mutex);
static LIST_HEAD(modules);
-static DEFINE_MUTEX(notify_mutex);
-static struct notifier_block * module_notify_list;
+static BLOCKING_NOTIFIER_HEAD(module_notify_list);
int register_module_notifier(struct notifier_block * nb)
{
- int err;
- mutex_lock(&notify_mutex);
- err = notifier_chain_register(&module_notify_list, nb);
- mutex_unlock(&notify_mutex);
- return err;
+ return blocking_notifier_chain_register(&module_notify_list, nb);
}
EXPORT_SYMBOL(register_module_notifier);
int unregister_module_notifier(struct notifier_block * nb)
{
- int err;
- mutex_lock(&notify_mutex);
- err = notifier_chain_unregister(&module_notify_list, nb);
- mutex_unlock(&notify_mutex);
- return err;
+ return blocking_notifier_chain_unregister(&module_notify_list, nb);
}
EXPORT_SYMBOL(unregister_module_notifier);
@@ -136,7 +127,7 @@ extern const unsigned long __start___kcrctab_gpl_future[];
#ifndef CONFIG_MODVERSIONS
#define symversion(base, idx) NULL
#else
-#define symversion(base, idx) ((base) ? ((base) + (idx)) : NULL)
+#define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL)
#endif
/* lookup symbol in given range of kernel_symbols */
@@ -714,14 +705,14 @@ EXPORT_SYMBOL(__symbol_put);
void symbol_put_addr(void *addr)
{
- unsigned long flags;
+ struct module *modaddr;
- spin_lock_irqsave(&modlist_lock, flags);
- if (!kernel_text_address((unsigned long)addr))
- BUG();
+ if (core_kernel_text((unsigned long)addr))
+ return;
- module_put(module_text_address((unsigned long)addr));
- spin_unlock_irqrestore(&modlist_lock, flags);
+ if (!(modaddr = module_text_address((unsigned long)addr)))
+ BUG();
+ module_put(modaddr);
}
EXPORT_SYMBOL_GPL(symbol_put_addr);
@@ -1263,6 +1254,7 @@ static inline int license_is_gpl_compatible(const char *license)
|| strcmp(license, "GPL v2") == 0
|| strcmp(license, "GPL and additional rights") == 0
|| strcmp(license, "Dual BSD/GPL") == 0
+ || strcmp(license, "Dual MIT/GPL") == 0
|| strcmp(license, "Dual MPL/GPL") == 0);
}
@@ -1816,9 +1808,8 @@ sys_init_module(void __user *umod,
/* Drop lock so they can recurse */
mutex_unlock(&module_mutex);
- mutex_lock(&notify_mutex);
- notifier_call_chain(&module_notify_list, MODULE_STATE_COMING, mod);
- mutex_unlock(&notify_mutex);
+ blocking_notifier_call_chain(&module_notify_list,
+ MODULE_STATE_COMING, mod);
/* Start the module */
if (mod->init != NULL)
diff --git a/kernel/panic.c b/kernel/panic.c
index acd95adddb9..cc2a4c9c36a 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -27,9 +27,8 @@ static int pause_on_oops_flag;
static DEFINE_SPINLOCK(pause_on_oops_lock);
int panic_timeout;
-EXPORT_SYMBOL(panic_timeout);
-struct notifier_block *panic_notifier_list;
+ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
EXPORT_SYMBOL(panic_notifier_list);
@@ -97,7 +96,7 @@ NORET_TYPE void panic(const char * fmt, ...)
smp_send_stop();
#endif
- notifier_call_chain(&panic_notifier_list, 0, buf);
+ atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
if (!panic_blink)
panic_blink = no_blink;
diff --git a/kernel/params.c b/kernel/params.c
index 9de637a5c8b..af43ecdc8d9 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -31,7 +31,7 @@
#define DEBUGP(fmt, a...)
#endif
-static inline int dash2underscore(char c)
+static inline char dash2underscore(char c)
{
if (c == '-')
return '_';
diff --git a/kernel/pid.c b/kernel/pid.c
index 1acc0724699..eeb836b65ca 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -28,8 +28,9 @@
#include <linux/hash.h>
#define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
-static struct hlist_head *pid_hash[PIDTYPE_MAX];
+static struct hlist_head *pid_hash;
static int pidhash_shift;
+static kmem_cache_t *pid_cachep;
int pid_max = PID_MAX_DEFAULT;
int last_pid;
@@ -60,9 +61,22 @@ typedef struct pidmap {
static pidmap_t pidmap_array[PIDMAP_ENTRIES] =
{ [ 0 ... PIDMAP_ENTRIES-1 ] = { ATOMIC_INIT(BITS_PER_PAGE), NULL } };
+/*
+ * Note: disable interrupts while the pidmap_lock is held as an
+ * interrupt might come in and do read_lock(&tasklist_lock).
+ *
+ * If we don't disable interrupts there is a nasty deadlock between
+ * detach_pid()->free_pid() and another cpu that does
+ * spin_lock(&pidmap_lock) followed by an interrupt routine that does
+ * read_lock(&tasklist_lock);
+ *
+ * After we clean up the tasklist_lock and know there are no
+ * irq handlers that take it we can leave the interrupts enabled.
+ * For now it is easier to be safe than to prove it can't happen.
+ */
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(pidmap_lock);
-fastcall void free_pidmap(int pid)
+static fastcall void free_pidmap(int pid)
{
pidmap_t *map = pidmap_array + pid / BITS_PER_PAGE;
int offset = pid & BITS_PER_PAGE_MASK;
@@ -71,7 +85,7 @@ fastcall void free_pidmap(int pid)
atomic_inc(&map->nr_free);
}
-int alloc_pidmap(void)
+static int alloc_pidmap(void)
{
int i, offset, max_scan, pid, last = last_pid;
pidmap_t *map;
@@ -89,12 +103,12 @@ int alloc_pidmap(void)
* Free the page if someone raced with us
* installing it:
*/
- spin_lock(&pidmap_lock);
+ spin_lock_irq(&pidmap_lock);
if (map->page)
free_page(page);
else
map->page = (void *)page;
- spin_unlock(&pidmap_lock);
+ spin_unlock_irq(&pidmap_lock);
if (unlikely(!map->page))
break;
}
@@ -131,13 +145,73 @@ int alloc_pidmap(void)
return -1;
}
-struct pid * fastcall find_pid(enum pid_type type, int nr)
+fastcall void put_pid(struct pid *pid)
+{
+ if (!pid)
+ return;
+ if ((atomic_read(&pid->count) == 1) ||
+ atomic_dec_and_test(&pid->count))
+ kmem_cache_free(pid_cachep, pid);
+}
+
+static void delayed_put_pid(struct rcu_head *rhp)
+{
+ struct pid *pid = container_of(rhp, struct pid, rcu);
+ put_pid(pid);
+}
+
+fastcall void free_pid(struct pid *pid)
+{
+ /* We can be called with write_lock_irq(&tasklist_lock) held */
+ unsigned long flags;
+
+ spin_lock_irqsave(&pidmap_lock, flags);
+ hlist_del_rcu(&pid->pid_chain);
+ spin_unlock_irqrestore(&pidmap_lock, flags);
+
+ free_pidmap(pid->nr);
+ call_rcu(&pid->rcu, delayed_put_pid);
+}
+
+struct pid *alloc_pid(void)
+{
+ struct pid *pid;
+ enum pid_type type;
+ int nr = -1;
+
+ pid = kmem_cache_alloc(pid_cachep, GFP_KERNEL);
+ if (!pid)
+ goto out;
+
+ nr = alloc_pidmap();
+ if (nr < 0)
+ goto out_free;
+
+ atomic_set(&pid->count, 1);
+ pid->nr = nr;
+ for (type = 0; type < PIDTYPE_MAX; ++type)
+ INIT_HLIST_HEAD(&pid->tasks[type]);
+
+ spin_lock_irq(&pidmap_lock);
+ hlist_add_head_rcu(&pid->pid_chain, &pid_hash[pid_hashfn(pid->nr)]);
+ spin_unlock_irq(&pidmap_lock);
+
+out:
+ return pid;
+
+out_free:
+ kmem_cache_free(pid_cachep, pid);
+ pid = NULL;
+ goto out;
+}
+
+struct pid * fastcall find_pid(int nr)
{
struct hlist_node *elem;
struct pid *pid;
hlist_for_each_entry_rcu(pid, elem,
- &pid_hash[type][pid_hashfn(nr)], pid_chain) {
+ &pid_hash[pid_hashfn(nr)], pid_chain) {
if (pid->nr == nr)
return pid;
}
@@ -146,105 +220,80 @@ struct pid * fastcall find_pid(enum pid_type type, int nr)
int fastcall attach_pid(task_t *task, enum pid_type type, int nr)
{
- struct pid *pid, *task_pid;
-
- task_pid = &task->pids[type];
- pid = find_pid(type, nr);
- task_pid->nr = nr;
- if (pid == NULL) {
- INIT_LIST_HEAD(&task_pid->pid_list);
- hlist_add_head_rcu(&task_pid->pid_chain,
- &pid_hash[type][pid_hashfn(nr)]);
- } else {
- INIT_HLIST_NODE(&task_pid->pid_chain);
- list_add_tail_rcu(&task_pid->pid_list, &pid->pid_list);
- }
-
- return 0;
-}
-
-static fastcall int __detach_pid(task_t *task, enum pid_type type)
-{
- struct pid *pid, *pid_next;
- int nr = 0;
-
- pid = &task->pids[type];
- if (!hlist_unhashed(&pid->pid_chain)) {
+ struct pid_link *link;
+ struct pid *pid;
- if (list_empty(&pid->pid_list)) {
- nr = pid->nr;
- hlist_del_rcu(&pid->pid_chain);
- } else {
- pid_next = list_entry(pid->pid_list.next,
- struct pid, pid_list);
- /* insert next pid from pid_list to hash */
- hlist_replace_rcu(&pid->pid_chain,
- &pid_next->pid_chain);
- }
- }
+ WARN_ON(!task->pid); /* to be removed soon */
+ WARN_ON(!nr); /* to be removed soon */
- list_del_rcu(&pid->pid_list);
- pid->nr = 0;
+ link = &task->pids[type];
+ link->pid = pid = find_pid(nr);
+ hlist_add_head_rcu(&link->node, &pid->tasks[type]);
- return nr;
+ return 0;
}
void fastcall detach_pid(task_t *task, enum pid_type type)
{
- int tmp, nr;
+ struct pid_link *link;
+ struct pid *pid;
+ int tmp;
- nr = __detach_pid(task, type);
- if (!nr)
- return;
+ link = &task->pids[type];
+ pid = link->pid;
+
+ hlist_del_rcu(&link->node);
+ link->pid = NULL;
for (tmp = PIDTYPE_MAX; --tmp >= 0; )
- if (tmp != type && find_pid(tmp, nr))
+ if (!hlist_empty(&pid->tasks[tmp]))
return;
- free_pidmap(nr);
+ free_pid(pid);
}
-task_t *find_task_by_pid_type(int type, int nr)
+struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type)
{
- struct pid *pid;
-
- pid = find_pid(type, nr);
- if (!pid)
- return NULL;
+ struct task_struct *result = NULL;
+ if (pid) {
+ struct hlist_node *first;
+ first = rcu_dereference(pid->tasks[type].first);
+ if (first)
+ result = hlist_entry(first, struct task_struct, pids[(type)].node);
+ }
+ return result;
+}
- return pid_task(&pid->pid_list, type);
+/*
+ * Must be called under rcu_read_lock() or with tasklist_lock read-held.
+ */
+task_t *find_task_by_pid_type(int type, int nr)
+{
+ return pid_task(find_pid(nr), type);
}
EXPORT_SYMBOL(find_task_by_pid_type);
-/*
- * This function switches the PIDs if a non-leader thread calls
- * sys_execve() - this must be done without releasing the PID.
- * (which a detach_pid() would eventually do.)
- */
-void switch_exec_pids(task_t *leader, task_t *thread)
+struct task_struct *fastcall get_pid_task(struct pid *pid, enum pid_type type)
+{
+ struct task_struct *result;
+ rcu_read_lock();
+ result = pid_task(pid, type);
+ if (result)
+ get_task_struct(result);
+ rcu_read_unlock();
+ return result;
+}
+
+struct pid *find_get_pid(pid_t nr)
{
- __detach_pid(leader, PIDTYPE_PID);
- __detach_pid(leader, PIDTYPE_TGID);
- __detach_pid(leader, PIDTYPE_PGID);
- __detach_pid(leader, PIDTYPE_SID);
-
- __detach_pid(thread, PIDTYPE_PID);
- __detach_pid(thread, PIDTYPE_TGID);
-
- leader->pid = leader->tgid = thread->pid;
- thread->pid = thread->tgid;
-
- attach_pid(thread, PIDTYPE_PID, thread->pid);
- attach_pid(thread, PIDTYPE_TGID, thread->tgid);
- attach_pid(thread, PIDTYPE_PGID, thread->signal->pgrp);
- attach_pid(thread, PIDTYPE_SID, thread->signal->session);
- list_add_tail(&thread->tasks, &init_task.tasks);
-
- attach_pid(leader, PIDTYPE_PID, leader->pid);
- attach_pid(leader, PIDTYPE_TGID, leader->tgid);
- attach_pid(leader, PIDTYPE_PGID, leader->signal->pgrp);
- attach_pid(leader, PIDTYPE_SID, leader->signal->session);
+ struct pid *pid;
+
+ rcu_read_lock();
+ pid = get_pid(find_pid(nr));
+ rcu_read_unlock();
+
+ return pid;
}
/*
@@ -254,7 +303,7 @@ void switch_exec_pids(task_t *leader, task_t *thread)
*/
void __init pidhash_init(void)
{
- int i, j, pidhash_size;
+ int i, pidhash_size;
unsigned long megabytes = nr_kernel_pages >> (20 - PAGE_SHIFT);
pidhash_shift = max(4, fls(megabytes * 4));
@@ -263,30 +312,23 @@ void __init pidhash_init(void)
printk("PID hash table entries: %d (order: %d, %Zd bytes)\n",
pidhash_size, pidhash_shift,
- PIDTYPE_MAX * pidhash_size * sizeof(struct hlist_head));
-
- for (i = 0; i < PIDTYPE_MAX; i++) {
- pid_hash[i] = alloc_bootmem(pidhash_size *
- sizeof(*(pid_hash[i])));
- if (!pid_hash[i])
- panic("Could not alloc pidhash!\n");
- for (j = 0; j < pidhash_size; j++)
- INIT_HLIST_HEAD(&pid_hash[i][j]);
- }
+ pidhash_size * sizeof(struct hlist_head));
+
+ pid_hash = alloc_bootmem(pidhash_size * sizeof(*(pid_hash)));
+ if (!pid_hash)
+ panic("Could not alloc pidhash!\n");
+ for (i = 0; i < pidhash_size; i++)
+ INIT_HLIST_HEAD(&pid_hash[i]);
}
void __init pidmap_init(void)
{
- int i;
-
pidmap_array->page = (void *)get_zeroed_page(GFP_KERNEL);
+ /* Reserve PID 0. We never call free_pidmap(0) */
set_bit(0, pidmap_array->page);
atomic_dec(&pidmap_array->nr_free);
- /*
- * Allocate PID 0, and hash it via all PID types:
- */
-
- for (i = 0; i < PIDTYPE_MAX; i++)
- attach_pid(current, i, 0);
+ pid_cachep = kmem_cache_create("pid", sizeof(struct pid),
+ __alignof__(struct pid),
+ SLAB_PANIC, NULL, NULL);
}
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 9fd8d4f0359..ce0dfb8f4a4 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -41,7 +41,7 @@ config SOFTWARE_SUSPEND
depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)
---help---
Enable the possibility of suspending the machine.
- It doesn't need APM.
+ It doesn't need ACPI or APM.
You may suspend your machine by 'swsusp' or 'shutdown -z <time>'
(patch for sysvinit needed).
diff --git a/kernel/power/main.c b/kernel/power/main.c
index ee371f50cca..a6d9ef46009 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -272,7 +272,7 @@ static ssize_t state_store(struct subsystem * subsys, const char * buf, size_t n
if (*s && !strncmp(buf, *s, len))
break;
}
- if (*s)
+ if (state < PM_SUSPEND_MAX && *s)
error = enter_state(state);
else
error = -EINVAL;
diff --git a/kernel/power/pm.c b/kernel/power/pm.c
index 0f6908cce1d..84063ac8fcf 100644
--- a/kernel/power/pm.c
+++ b/kernel/power/pm.c
@@ -75,25 +75,6 @@ struct pm_dev *pm_register(pm_dev_t type,
return dev;
}
-/**
- * pm_unregister - unregister a device with power management
- * @dev: device to unregister
- *
- * Remove a device from the power management notification lists. The
- * dev passed must be a handle previously returned by pm_register.
- */
-
-void pm_unregister(struct pm_dev *dev)
-{
- if (dev) {
- mutex_lock(&pm_devs_lock);
- list_del(&dev->entry);
- mutex_unlock(&pm_devs_lock);
-
- kfree(dev);
- }
-}
-
static void __pm_unregister(struct pm_dev *dev)
{
if (dev) {
@@ -258,7 +239,6 @@ int pm_send_all(pm_request_t rqst, void *data)
}
EXPORT_SYMBOL(pm_register);
-EXPORT_SYMBOL(pm_unregister);
EXPORT_SYMBOL(pm_unregister_all);
EXPORT_SYMBOL(pm_send_all);
EXPORT_SYMBOL(pm_active);
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 8ac7c35fad7..b2a5f671d6c 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -26,8 +26,7 @@ static inline int freezeable(struct task_struct * p)
(p->flags & PF_NOFREEZE) ||
(p->exit_state == EXIT_ZOMBIE) ||
(p->exit_state == EXIT_DEAD) ||
- (p->state == TASK_STOPPED) ||
- (p->state == TASK_TRACED))
+ (p->state == TASK_STOPPED))
return 0;
return 1;
}
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index c5863d02c89..3eeedbb13b7 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -240,14 +240,15 @@ static void copy_data_pages(struct pbe *pblist)
* free_pagedir - free pages allocated with alloc_pagedir()
*/
-static void free_pagedir(struct pbe *pblist)
+static void free_pagedir(struct pbe *pblist, int clear_nosave_free)
{
struct pbe *pbe;
while (pblist) {
pbe = (pblist + PB_PAGE_SKIP)->next;
ClearPageNosave(virt_to_page(pblist));
- ClearPageNosaveFree(virt_to_page(pblist));
+ if (clear_nosave_free)
+ ClearPageNosaveFree(virt_to_page(pblist));
free_page((unsigned long)pblist);
pblist = pbe;
}
@@ -389,7 +390,7 @@ struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask, int safe_needed
pbe->next = alloc_image_page(gfp_mask, safe_needed);
}
if (!pbe) { /* get_zeroed_page() failed */
- free_pagedir(pblist);
+ free_pagedir(pblist, 1);
pblist = NULL;
} else
create_pbe_list(pblist, nr_pages);
@@ -736,7 +737,7 @@ static int create_image(struct snapshot_handle *handle)
pblist = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 1);
if (pblist)
copy_page_backup_list(pblist, p);
- free_pagedir(p);
+ free_pagedir(p, 0);
if (!pblist)
error = -ENOMEM;
}
diff --git a/kernel/printk.c b/kernel/printk.c
index 8cc19431e74..c056f332443 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -360,8 +360,7 @@ static void call_console_drivers(unsigned long start, unsigned long end)
unsigned long cur_index, start_print;
static int msg_level = -1;
- if (((long)(start - end)) > 0)
- BUG();
+ BUG_ON(((long)(start - end)) > 0);
cur_index = start;
start_print = start;
@@ -708,8 +707,7 @@ int __init add_preferred_console(char *name, int idx, char *options)
*/
void acquire_console_sem(void)
{
- if (in_interrupt())
- BUG();
+ BUG_ON(in_interrupt());
down(&console_sem);
console_locked = 1;
console_may_schedule = 1;
diff --git a/kernel/profile.c b/kernel/profile.c
index ad81f799a9b..68afe121e50 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -87,72 +87,52 @@ void __init profile_init(void)
#ifdef CONFIG_PROFILING
-static DECLARE_RWSEM(profile_rwsem);
-static DEFINE_RWLOCK(handoff_lock);
-static struct notifier_block * task_exit_notifier;
-static struct notifier_block * task_free_notifier;
-static struct notifier_block * munmap_notifier;
+static BLOCKING_NOTIFIER_HEAD(task_exit_notifier);
+static ATOMIC_NOTIFIER_HEAD(task_free_notifier);
+static BLOCKING_NOTIFIER_HEAD(munmap_notifier);
void profile_task_exit(struct task_struct * task)
{
- down_read(&profile_rwsem);
- notifier_call_chain(&task_exit_notifier, 0, task);
- up_read(&profile_rwsem);
+ blocking_notifier_call_chain(&task_exit_notifier, 0, task);
}
int profile_handoff_task(struct task_struct * task)
{
int ret;
- read_lock(&handoff_lock);
- ret = notifier_call_chain(&task_free_notifier, 0, task);
- read_unlock(&handoff_lock);
+ ret = atomic_notifier_call_chain(&task_free_notifier, 0, task);
return (ret == NOTIFY_OK) ? 1 : 0;
}
void profile_munmap(unsigned long addr)
{
- down_read(&profile_rwsem);
- notifier_call_chain(&munmap_notifier, 0, (void *)addr);
- up_read(&profile_rwsem);
+ blocking_notifier_call_chain(&munmap_notifier, 0, (void *)addr);
}
int task_handoff_register(struct notifier_block * n)
{
- int err = -EINVAL;
-
- write_lock(&handoff_lock);
- err = notifier_chain_register(&task_free_notifier, n);
- write_unlock(&handoff_lock);
- return err;
+ return atomic_notifier_chain_register(&task_free_notifier, n);
}
int task_handoff_unregister(struct notifier_block * n)
{
- int err = -EINVAL;
-
- write_lock(&handoff_lock);
- err = notifier_chain_unregister(&task_free_notifier, n);
- write_unlock(&handoff_lock);
- return err;
+ return atomic_notifier_chain_unregister(&task_free_notifier, n);
}
int profile_event_register(enum profile_type type, struct notifier_block * n)
{
int err = -EINVAL;
- down_write(&profile_rwsem);
-
switch (type) {
case PROFILE_TASK_EXIT:
- err = notifier_chain_register(&task_exit_notifier, n);
+ err = blocking_notifier_chain_register(
+ &task_exit_notifier, n);
break;
case PROFILE_MUNMAP:
- err = notifier_chain_register(&munmap_notifier, n);
+ err = blocking_notifier_chain_register(
+ &munmap_notifier, n);
break;
}
- up_write(&profile_rwsem);
-
return err;
}
@@ -161,18 +141,17 @@ int profile_event_unregister(enum profile_type type, struct notifier_block * n)
{
int err = -EINVAL;
- down_write(&profile_rwsem);
-
switch (type) {
case PROFILE_TASK_EXIT:
- err = notifier_chain_unregister(&task_exit_notifier, n);
+ err = blocking_notifier_chain_unregister(
+ &task_exit_notifier, n);
break;
case PROFILE_MUNMAP:
- err = notifier_chain_unregister(&munmap_notifier, n);
+ err = blocking_notifier_chain_unregister(
+ &munmap_notifier, n);
break;
}
- up_write(&profile_rwsem);
return err;
}
@@ -320,7 +299,7 @@ out:
}
#ifdef CONFIG_HOTPLUG_CPU
-static int __devinit profile_cpu_callback(struct notifier_block *info,
+static int profile_cpu_callback(struct notifier_block *info,
unsigned long action, void *__cpu)
{
int node, cpu = (unsigned long)__cpu;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index d95a72c9279..921c22ad16e 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -30,14 +30,13 @@
*/
void __ptrace_link(task_t *child, task_t *new_parent)
{
- if (!list_empty(&child->ptrace_list))
- BUG();
+ BUG_ON(!list_empty(&child->ptrace_list));
if (child->parent == new_parent)
return;
list_add(&child->ptrace_list, &child->parent->ptrace_children);
- REMOVE_LINKS(child);
+ remove_parent(child);
child->parent = new_parent;
- SET_LINKS(child);
+ add_parent(child);
}
/*
@@ -57,10 +56,6 @@ void ptrace_untrace(task_t *child)
signal_wake_up(child, 1);
}
}
- if (child->signal->flags & SIGNAL_GROUP_EXIT) {
- sigaddset(&child->pending.signal, SIGKILL);
- signal_wake_up(child, 1);
- }
spin_unlock(&child->sighand->siglock);
}
@@ -77,12 +72,13 @@ void __ptrace_unlink(task_t *child)
child->ptrace = 0;
if (!list_empty(&child->ptrace_list)) {
list_del_init(&child->ptrace_list);
- REMOVE_LINKS(child);
+ remove_parent(child);
child->parent = child->real_parent;
- SET_LINKS(child);
+ add_parent(child);
}
- ptrace_untrace(child);
+ if (child->state == TASK_TRACED)
+ ptrace_untrace(child);
}
/*
@@ -152,12 +148,34 @@ int ptrace_may_attach(struct task_struct *task)
int ptrace_attach(struct task_struct *task)
{
int retval;
- task_lock(task);
+
retval = -EPERM;
if (task->pid <= 1)
- goto bad;
+ goto out;
if (task->tgid == current->tgid)
- goto bad;
+ goto out;
+
+repeat:
+ /*
+ * Nasty, nasty.
+ *
+ * We want to hold both the task-lock and the
+ * tasklist_lock for writing at the same time.
+ * But that's against the rules (tasklist_lock
+ * is taken for reading by interrupts on other
+ * cpu's that may have task_lock).
+ */
+ task_lock(task);
+ local_irq_disable();
+ if (!write_trylock(&tasklist_lock)) {
+ local_irq_enable();
+ task_unlock(task);
+ do {
+ cpu_relax();
+ } while (!write_can_lock(&tasklist_lock));
+ goto repeat;
+ }
+
/* the same process cannot be attached many times */
if (task->ptrace & PT_PTRACED)
goto bad;
@@ -170,17 +188,15 @@ int ptrace_attach(struct task_struct *task)
? PT_ATTACHED : 0);
if (capable(CAP_SYS_PTRACE))
task->ptrace |= PT_PTRACE_CAP;
- task_unlock(task);
- write_lock_irq(&tasklist_lock);
__ptrace_link(task, current);
- write_unlock_irq(&tasklist_lock);
force_sig_specific(SIGSTOP, task);
- return 0;
bad:
+ write_unlock_irq(&tasklist_lock);
task_unlock(task);
+out:
return retval;
}
@@ -421,21 +437,22 @@ int ptrace_request(struct task_struct *child, long request,
*/
int ptrace_traceme(void)
{
- int ret;
+ int ret = -EPERM;
/*
* Are we already being traced?
*/
- if (current->ptrace & PT_PTRACED)
- return -EPERM;
- ret = security_ptrace(current->parent, current);
- if (ret)
- return -EPERM;
- /*
- * Set the ptrace bit in the process ptrace flags.
- */
- current->ptrace |= PT_PTRACED;
- return 0;
+ task_lock(current);
+ if (!(current->ptrace & PT_PTRACED)) {
+ ret = security_ptrace(current->parent, current);
+ /*
+ * Set the ptrace bit in the process ptrace flags.
+ */
+ if (!ret)
+ current->ptrace |= PT_PTRACED;
+ }
+ task_unlock(current);
+ return ret;
}
/**
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 13458bbaa1b..2058f88c7bb 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -479,12 +479,31 @@ static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp)
return 0;
}
+/*
+ * Check to see if there is any immediate RCU-related work to be done
+ * by the current CPU, returning 1 if so. This function is part of the
+ * RCU implementation; it is -not- an exported member of the RCU API.
+ */
int rcu_pending(int cpu)
{
return __rcu_pending(&rcu_ctrlblk, &per_cpu(rcu_data, cpu)) ||
__rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu));
}
+/*
+ * Check to see if any future RCU-related work will need to be done
+ * by the current CPU, even if none need be done immediately, returning
+ * 1 if so. This function is part of the RCU implementation; it is -not-
+ * an exported member of the RCU API.
+ */
+int rcu_needs_cpu(int cpu)
+{
+ struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
+ struct rcu_data *rdp_bh = &per_cpu(rcu_bh_data, cpu);
+
+ return (!!rdp->curlist || !!rdp_bh->curlist || rcu_pending(cpu));
+}
+
void rcu_check_callbacks(int cpu, int user)
{
if (user ||
@@ -520,7 +539,7 @@ static void __devinit rcu_online_cpu(int cpu)
tasklet_init(&per_cpu(rcu_tasklet, cpu), rcu_process_callbacks, 0UL);
}
-static int __devinit rcu_cpu_notify(struct notifier_block *self,
+static int rcu_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
long cpu = (long)hcpu;
@@ -537,7 +556,7 @@ static int __devinit rcu_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata rcu_nb = {
+static struct notifier_block rcu_nb = {
.notifier_call = rcu_cpu_notify,
};
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index b4b362b5baf..8154e7589d1 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -301,7 +301,7 @@ rcu_torture_printk(char *page)
long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
pipesummary[i] += per_cpu(rcu_torture_count, cpu)[i];
batchsummary[i] += per_cpu(rcu_torture_batch, cpu)[i];
@@ -535,7 +535,7 @@ rcu_torture_init(void)
atomic_set(&n_rcu_torture_error, 0);
for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
atomic_set(&rcu_torture_wcount[i], 0);
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
per_cpu(rcu_torture_count, cpu)[i] = 0;
per_cpu(rcu_torture_batch, cpu)[i] = 0;
diff --git a/kernel/sched.c b/kernel/sched.c
index 78acdefeccc..c13f1bd2df7 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -145,7 +145,8 @@
(v1) * (v2_max) / (v1_max)
#define DELTA(p) \
- (SCALE(TASK_NICE(p), 40, MAX_BONUS) + INTERACTIVE_DELTA)
+ (SCALE(TASK_NICE(p) + 20, 40, MAX_BONUS) - 20 * MAX_BONUS / 40 + \
+ INTERACTIVE_DELTA)
#define TASK_INTERACTIVE(p) \
((p)->prio <= (p)->static_prio - DELTA(p))
@@ -666,9 +667,13 @@ static int effective_prio(task_t *p)
/*
* __activate_task - move a task to the runqueue.
*/
-static inline void __activate_task(task_t *p, runqueue_t *rq)
+static void __activate_task(task_t *p, runqueue_t *rq)
{
- enqueue_task(p, rq->active);
+ prio_array_t *target = rq->active;
+
+ if (batch_task(p))
+ target = rq->expired;
+ enqueue_task(p, target);
rq->nr_running++;
}
@@ -687,7 +692,7 @@ static int recalc_task_prio(task_t *p, unsigned long long now)
unsigned long long __sleep_time = now - p->timestamp;
unsigned long sleep_time;
- if (unlikely(p->policy == SCHED_BATCH))
+ if (batch_task(p))
sleep_time = 0;
else {
if (__sleep_time > NS_MAX_SLEEP_AVG)
@@ -699,21 +704,25 @@ static int recalc_task_prio(task_t *p, unsigned long long now)
if (likely(sleep_time > 0)) {
/*
* User tasks that sleep a long time are categorised as
- * idle and will get just interactive status to stay active &
- * prevent them suddenly becoming cpu hogs and starving
- * other processes.
+ * idle. They will only have their sleep_avg increased to a
+ * level that makes them just interactive priority to stay
+ * active yet prevent them suddenly becoming cpu hogs and
+ * starving other processes.
*/
- if (p->mm && p->activated != -1 &&
- sleep_time > INTERACTIVE_SLEEP(p)) {
- p->sleep_avg = JIFFIES_TO_NS(MAX_SLEEP_AVG -
- DEF_TIMESLICE);
+ if (p->mm && sleep_time > INTERACTIVE_SLEEP(p)) {
+ unsigned long ceiling;
+
+ ceiling = JIFFIES_TO_NS(MAX_SLEEP_AVG -
+ DEF_TIMESLICE);
+ if (p->sleep_avg < ceiling)
+ p->sleep_avg = ceiling;
} else {
/*
* Tasks waking from uninterruptible sleep are
* limited in their sleep_avg rise as they
* are likely to be waiting on I/O
*/
- if (p->activated == -1 && p->mm) {
+ if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) {
if (p->sleep_avg >= INTERACTIVE_SLEEP(p))
sleep_time = 0;
else if (p->sleep_avg + sleep_time >=
@@ -768,7 +777,7 @@ static void activate_task(task_t *p, runqueue_t *rq, int local)
* This checks to make sure it's not an uninterruptible task
* that is now waking up.
*/
- if (!p->activated) {
+ if (p->sleep_type == SLEEP_NORMAL) {
/*
* Tasks which were woken up by interrupts (ie. hw events)
* are most likely of interactive nature. So we give them
@@ -777,13 +786,13 @@ static void activate_task(task_t *p, runqueue_t *rq, int local)
* on a CPU, first time around:
*/
if (in_interrupt())
- p->activated = 2;
+ p->sleep_type = SLEEP_INTERRUPTED;
else {
/*
* Normal first-time wakeups get a credit too for
* on-runqueue time, but it will be weighted down:
*/
- p->activated = 1;
+ p->sleep_type = SLEEP_INTERACTIVE;
}
}
p->timestamp = now;
@@ -1271,19 +1280,19 @@ out_activate:
* Tasks on involuntary sleep don't earn
* sleep_avg beyond just interactive state.
*/
- p->activated = -1;
- }
+ p->sleep_type = SLEEP_NONINTERACTIVE;
+ } else
/*
* Tasks that have marked their sleep as noninteractive get
- * woken up without updating their sleep average. (i.e. their
- * sleep is handled in a priority-neutral manner, no priority
- * boost and no penalty.)
+ * woken up with their sleep average not weighted in an
+ * interactive way.
*/
- if (old_state & TASK_NONINTERACTIVE)
- __activate_task(p, rq);
- else
- activate_task(p, rq, cpu == this_cpu);
+ if (old_state & TASK_NONINTERACTIVE)
+ p->sleep_type = SLEEP_NONINTERACTIVE;
+
+
+ activate_task(p, rq, cpu == this_cpu);
/*
* Sync wakeups (i.e. those types of wakeups where the waker
* has indicated that it will leave the CPU in short order)
@@ -1624,7 +1633,7 @@ unsigned long nr_uninterruptible(void)
{
unsigned long i, sum = 0;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
sum += cpu_rq(i)->nr_uninterruptible;
/*
@@ -1641,7 +1650,7 @@ unsigned long long nr_context_switches(void)
{
unsigned long long i, sum = 0;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
sum += cpu_rq(i)->nr_switches;
return sum;
@@ -1651,12 +1660,27 @@ unsigned long nr_iowait(void)
{
unsigned long i, sum = 0;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
sum += atomic_read(&cpu_rq(i)->nr_iowait);
return sum;
}
+unsigned long nr_active(void)
+{
+ unsigned long i, running = 0, uninterruptible = 0;
+
+ for_each_online_cpu(i) {
+ running += cpu_rq(i)->nr_running;
+ uninterruptible += cpu_rq(i)->nr_uninterruptible;
+ }
+
+ if (unlikely((long)uninterruptible < 0))
+ uninterruptible = 0;
+
+ return running + uninterruptible;
+}
+
#ifdef CONFIG_SMP
/*
@@ -2859,6 +2883,12 @@ EXPORT_SYMBOL(sub_preempt_count);
#endif
+static inline int interactive_sleep(enum sleep_type sleep_type)
+{
+ return (sleep_type == SLEEP_INTERACTIVE ||
+ sleep_type == SLEEP_INTERRUPTED);
+}
+
/*
* schedule() is the main scheduler function.
*/
@@ -2878,13 +2908,11 @@ asmlinkage void __sched schedule(void)
* schedule() atomically, we ignore that path for now.
* Otherwise, whine if we are scheduling when we should not be.
*/
- if (likely(!current->exit_state)) {
- if (unlikely(in_atomic())) {
- printk(KERN_ERR "BUG: scheduling while atomic: "
- "%s/0x%08x/%d\n",
- current->comm, preempt_count(), current->pid);
- dump_stack();
- }
+ if (unlikely(in_atomic() && !current->exit_state)) {
+ printk(KERN_ERR "BUG: scheduling while atomic: "
+ "%s/0x%08x/%d\n",
+ current->comm, preempt_count(), current->pid);
+ dump_stack();
}
profile_hit(SCHED_PROFILING, __builtin_return_address(0));
@@ -2984,12 +3012,12 @@ go_idle:
queue = array->queue + idx;
next = list_entry(queue->next, task_t, run_list);
- if (!rt_task(next) && next->activated > 0) {
+ if (!rt_task(next) && interactive_sleep(next->sleep_type)) {
unsigned long long delta = now - next->timestamp;
if (unlikely((long long)(now - next->timestamp) < 0))
delta = 0;
- if (next->activated == 1)
+ if (next->sleep_type == SLEEP_INTERACTIVE)
delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;
array = next->array;
@@ -2999,10 +3027,9 @@ go_idle:
dequeue_task(next, array);
next->prio = new_prio;
enqueue_task(next, array);
- } else
- requeue_task(next, array);
+ }
}
- next->activated = 0;
+ next->sleep_type = SLEEP_NORMAL;
switch_tasks:
if (next == rq->idle)
schedstat_inc(rq, sched_goidle);
@@ -4761,7 +4788,7 @@ static int migration_call(struct notifier_block *nfb, unsigned long action,
/* Register at highest priority so that task migration (migrate_all_tasks)
* happens before everything else.
*/
-static struct notifier_block __devinitdata migration_notifier = {
+static struct notifier_block migration_notifier = {
.notifier_call = migration_call,
.priority = 10
};
@@ -5575,11 +5602,31 @@ static int cpu_to_cpu_group(int cpu)
}
#endif
+#ifdef CONFIG_SCHED_MC
+static DEFINE_PER_CPU(struct sched_domain, core_domains);
+static struct sched_group sched_group_core[NR_CPUS];
+#endif
+
+#if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT)
+static int cpu_to_core_group(int cpu)
+{
+ return first_cpu(cpu_sibling_map[cpu]);
+}
+#elif defined(CONFIG_SCHED_MC)
+static int cpu_to_core_group(int cpu)
+{
+ return cpu;
+}
+#endif
+
static DEFINE_PER_CPU(struct sched_domain, phys_domains);
static struct sched_group sched_group_phys[NR_CPUS];
static int cpu_to_phys_group(int cpu)
{
-#ifdef CONFIG_SCHED_SMT
+#if defined(CONFIG_SCHED_MC)
+ cpumask_t mask = cpu_coregroup_map(cpu);
+ return first_cpu(mask);
+#elif defined(CONFIG_SCHED_SMT)
return first_cpu(cpu_sibling_map[cpu]);
#else
return cpu;
@@ -5602,6 +5649,32 @@ static int cpu_to_allnodes_group(int cpu)
{
return cpu_to_node(cpu);
}
+static void init_numa_sched_groups_power(struct sched_group *group_head)
+{
+ struct sched_group *sg = group_head;
+ int j;
+
+ if (!sg)
+ return;
+next_sg:
+ for_each_cpu_mask(j, sg->cpumask) {
+ struct sched_domain *sd;
+
+ sd = &per_cpu(phys_domains, j);
+ if (j != first_cpu(sd->groups->cpumask)) {
+ /*
+ * Only add "power" once for each
+ * physical package.
+ */
+ continue;
+ }
+
+ sg->cpu_power += sd->groups->cpu_power;
+ }
+ sg = sg->next;
+ if (sg != group_head)
+ goto next_sg;
+}
#endif
/*
@@ -5677,6 +5750,17 @@ void build_sched_domains(const cpumask_t *cpu_map)
sd->parent = p;
sd->groups = &sched_group_phys[group];
+#ifdef CONFIG_SCHED_MC
+ p = sd;
+ sd = &per_cpu(core_domains, i);
+ group = cpu_to_core_group(i);
+ *sd = SD_MC_INIT;
+ sd->span = cpu_coregroup_map(i);
+ cpus_and(sd->span, sd->span, *cpu_map);
+ sd->parent = p;
+ sd->groups = &sched_group_core[group];
+#endif
+
#ifdef CONFIG_SCHED_SMT
p = sd;
sd = &per_cpu(cpu_domains, i);
@@ -5702,6 +5786,19 @@ void build_sched_domains(const cpumask_t *cpu_map)
}
#endif
+#ifdef CONFIG_SCHED_MC
+ /* Set up multi-core groups */
+ for_each_cpu_mask(i, *cpu_map) {
+ cpumask_t this_core_map = cpu_coregroup_map(i);
+ cpus_and(this_core_map, this_core_map, *cpu_map);
+ if (i != first_cpu(this_core_map))
+ continue;
+ init_sched_build_groups(sched_group_core, this_core_map,
+ &cpu_to_core_group);
+ }
+#endif
+
+
/* Set up physical groups */
for (i = 0; i < MAX_NUMNODES; i++) {
cpumask_t nodemask = node_to_cpumask(i);
@@ -5798,51 +5895,38 @@ void build_sched_domains(const cpumask_t *cpu_map)
power = SCHED_LOAD_SCALE;
sd->groups->cpu_power = power;
#endif
+#ifdef CONFIG_SCHED_MC
+ sd = &per_cpu(core_domains, i);
+ power = SCHED_LOAD_SCALE + (cpus_weight(sd->groups->cpumask)-1)
+ * SCHED_LOAD_SCALE / 10;
+ sd->groups->cpu_power = power;
sd = &per_cpu(phys_domains, i);
+
+ /*
+ * This has to be < 2 * SCHED_LOAD_SCALE
+ * Lets keep it SCHED_LOAD_SCALE, so that
+ * while calculating NUMA group's cpu_power
+ * we can simply do
+ * numa_group->cpu_power += phys_group->cpu_power;
+ *
+ * See "only add power once for each physical pkg"
+ * comment below
+ */
+ sd->groups->cpu_power = SCHED_LOAD_SCALE;
+#else
+ sd = &per_cpu(phys_domains, i);
power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
(cpus_weight(sd->groups->cpumask)-1) / 10;
sd->groups->cpu_power = power;
-
-#ifdef CONFIG_NUMA
- sd = &per_cpu(allnodes_domains, i);
- if (sd->groups) {
- power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
- (cpus_weight(sd->groups->cpumask)-1) / 10;
- sd->groups->cpu_power = power;
- }
#endif
}
#ifdef CONFIG_NUMA
- for (i = 0; i < MAX_NUMNODES; i++) {
- struct sched_group *sg = sched_group_nodes[i];
- int j;
+ for (i = 0; i < MAX_NUMNODES; i++)
+ init_numa_sched_groups_power(sched_group_nodes[i]);
- if (sg == NULL)
- continue;
-next_sg:
- for_each_cpu_mask(j, sg->cpumask) {
- struct sched_domain *sd;
- int power;
-
- sd = &per_cpu(phys_domains, j);
- if (j != first_cpu(sd->groups->cpumask)) {
- /*
- * Only add "power" once for each
- * physical package.
- */
- continue;
- }
- power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
- (cpus_weight(sd->groups->cpumask)-1) / 10;
-
- sg->cpu_power += power;
- }
- sg = sg->next;
- if (sg != sched_group_nodes[i])
- goto next_sg;
- }
+ init_numa_sched_groups_power(sched_group_allnodes);
#endif
/* Attach the domains */
@@ -5850,6 +5934,8 @@ next_sg:
struct sched_domain *sd;
#ifdef CONFIG_SCHED_SMT
sd = &per_cpu(cpu_domains, i);
+#elif defined(CONFIG_SCHED_MC)
+ sd = &per_cpu(core_domains, i);
#else
sd = &per_cpu(phys_domains, i);
#endif
@@ -6022,7 +6108,7 @@ void __init sched_init(void)
runqueue_t *rq;
int i, j, k;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
prio_array_t *array;
rq = cpu_rq(i);
diff --git a/kernel/signal.c b/kernel/signal.c
index 75f7341b0c3..e5f8aea78ff 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -22,7 +22,6 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/ptrace.h>
-#include <linux/posix-timers.h>
#include <linux/signal.h>
#include <linux/audit.h>
#include <linux/capability.h>
@@ -147,6 +146,8 @@ static kmem_cache_t *sigqueue_cachep;
#define sig_kernel_stop(sig) \
(((sig) < SIGRTMIN) && T(sig, SIG_KERNEL_STOP_MASK))
+#define sig_needs_tasklist(sig) ((sig) == SIGCONT)
+
#define sig_user_defined(t, signr) \
(((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_DFL) && \
((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_IGN))
@@ -292,7 +293,7 @@ static void __sigqueue_free(struct sigqueue *q)
kmem_cache_free(sigqueue_cachep, q);
}
-static void flush_sigqueue(struct sigpending *queue)
+void flush_sigqueue(struct sigpending *queue)
{
struct sigqueue *q;
@@ -307,9 +308,7 @@ static void flush_sigqueue(struct sigpending *queue)
/*
* Flush all pending signals for a task.
*/
-
-void
-flush_signals(struct task_struct *t)
+void flush_signals(struct task_struct *t)
{
unsigned long flags;
@@ -321,109 +320,6 @@ flush_signals(struct task_struct *t)
}
/*
- * This function expects the tasklist_lock write-locked.
- */
-void __exit_sighand(struct task_struct *tsk)
-{
- struct sighand_struct * sighand = tsk->sighand;
-
- /* Ok, we're done with the signal handlers */
- tsk->sighand = NULL;
- if (atomic_dec_and_test(&sighand->count))
- sighand_free(sighand);
-}
-
-void exit_sighand(struct task_struct *tsk)
-{
- write_lock_irq(&tasklist_lock);
- rcu_read_lock();
- if (tsk->sighand != NULL) {
- struct sighand_struct *sighand = rcu_dereference(tsk->sighand);
- spin_lock(&sighand->siglock);
- __exit_sighand(tsk);
- spin_unlock(&sighand->siglock);
- }
- rcu_read_unlock();
- write_unlock_irq(&tasklist_lock);
-}
-
-/*
- * This function expects the tasklist_lock write-locked.
- */
-void __exit_signal(struct task_struct *tsk)
-{
- struct signal_struct * sig = tsk->signal;
- struct sighand_struct * sighand;
-
- if (!sig)
- BUG();
- if (!atomic_read(&sig->count))
- BUG();
- rcu_read_lock();
- sighand = rcu_dereference(tsk->sighand);
- spin_lock(&sighand->siglock);
- posix_cpu_timers_exit(tsk);
- if (atomic_dec_and_test(&sig->count)) {
- posix_cpu_timers_exit_group(tsk);
- tsk->signal = NULL;
- __exit_sighand(tsk);
- spin_unlock(&sighand->siglock);
- flush_sigqueue(&sig->shared_pending);
- } else {
- /*
- * If there is any task waiting for the group exit
- * then notify it:
- */
- if (sig->group_exit_task && atomic_read(&sig->count) == sig->notify_count) {
- wake_up_process(sig->group_exit_task);
- sig->group_exit_task = NULL;
- }
- if (tsk == sig->curr_target)
- sig->curr_target = next_thread(tsk);
- tsk->signal = NULL;
- /*
- * Accumulate here the counters for all threads but the
- * group leader as they die, so they can be added into
- * the process-wide totals when those are taken.
- * The group leader stays around as a zombie as long
- * as there are other threads. When it gets reaped,
- * the exit.c code will add its counts into these totals.
- * We won't ever get here for the group leader, since it
- * will have been the last reference on the signal_struct.
- */
- sig->utime = cputime_add(sig->utime, tsk->utime);
- sig->stime = cputime_add(sig->stime, tsk->stime);
- sig->min_flt += tsk->min_flt;
- sig->maj_flt += tsk->maj_flt;
- sig->nvcsw += tsk->nvcsw;
- sig->nivcsw += tsk->nivcsw;
- sig->sched_time += tsk->sched_time;
- __exit_sighand(tsk);
- spin_unlock(&sighand->siglock);
- sig = NULL; /* Marker for below. */
- }
- rcu_read_unlock();
- clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
- flush_sigqueue(&tsk->pending);
- if (sig) {
- /*
- * We are cleaning up the signal_struct here.
- */
- exit_thread_group_keys(sig);
- kmem_cache_free(signal_cachep, sig);
- }
-}
-
-void exit_signal(struct task_struct *tsk)
-{
- atomic_dec(&tsk->signal->live);
-
- write_lock_irq(&tasklist_lock);
- __exit_signal(tsk);
- write_unlock_irq(&tasklist_lock);
-}
-
-/*
* Flush all handlers for a task.
*/
@@ -695,9 +591,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
}
/* forward decl */
-static void do_notify_parent_cldstop(struct task_struct *tsk,
- int to_self,
- int why);
+static void do_notify_parent_cldstop(struct task_struct *tsk, int why);
/*
* Handle magic process-wide effects of stop/continue signals.
@@ -747,7 +641,7 @@ static void handle_stop_signal(int sig, struct task_struct *p)
p->signal->group_stop_count = 0;
p->signal->flags = SIGNAL_STOP_CONTINUED;
spin_unlock(&p->sighand->siglock);
- do_notify_parent_cldstop(p, (p->ptrace & PT_PTRACED), CLD_STOPPED);
+ do_notify_parent_cldstop(p, CLD_STOPPED);
spin_lock(&p->sighand->siglock);
}
rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
@@ -788,7 +682,7 @@ static void handle_stop_signal(int sig, struct task_struct *p)
p->signal->flags = SIGNAL_STOP_CONTINUED;
p->signal->group_exit_code = 0;
spin_unlock(&p->sighand->siglock);
- do_notify_parent_cldstop(p, (p->ptrace & PT_PTRACED), CLD_CONTINUED);
+ do_notify_parent_cldstop(p, CLD_CONTINUED);
spin_lock(&p->sighand->siglock);
} else {
/*
@@ -875,8 +769,7 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
{
int ret = 0;
- if (!irqs_disabled())
- BUG();
+ BUG_ON(!irqs_disabled());
assert_spin_locked(&t->sighand->siglock);
/* Short-circuit ignored signals. */
@@ -975,7 +868,6 @@ __group_complete_signal(int sig, struct task_struct *p)
if (t == NULL)
/* restart balancing at this thread */
t = p->signal->curr_target = p;
- BUG_ON(t->tgid != p->tgid);
while (!wants_signal(sig, t)) {
t = next_thread(t);
@@ -1120,27 +1012,37 @@ void zap_other_threads(struct task_struct *p)
/*
* Must be called under rcu_read_lock() or with tasklist_lock read-held.
*/
+struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long *flags)
+{
+ struct sighand_struct *sighand;
+
+ for (;;) {
+ sighand = rcu_dereference(tsk->sighand);
+ if (unlikely(sighand == NULL))
+ break;
+
+ spin_lock_irqsave(&sighand->siglock, *flags);
+ if (likely(sighand == tsk->sighand))
+ break;
+ spin_unlock_irqrestore(&sighand->siglock, *flags);
+ }
+
+ return sighand;
+}
+
int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
{
unsigned long flags;
- struct sighand_struct *sp;
int ret;
-retry:
ret = check_kill_permission(sig, info, p);
- if (!ret && sig && (sp = rcu_dereference(p->sighand))) {
- spin_lock_irqsave(&sp->siglock, flags);
- if (p->sighand != sp) {
- spin_unlock_irqrestore(&sp->siglock, flags);
- goto retry;
- }
- if ((atomic_read(&sp->count) == 0) ||
- (atomic_read(&p->usage) == 0)) {
- spin_unlock_irqrestore(&sp->siglock, flags);
- return -ESRCH;
+
+ if (!ret && sig) {
+ ret = -ESRCH;
+ if (lock_task_sighand(p, &flags)) {
+ ret = __group_send_sig_info(sig, info, p);
+ unlock_task_sighand(p, &flags);
}
- ret = __group_send_sig_info(sig, info, p);
- spin_unlock_irqrestore(&sp->siglock, flags);
}
return ret;
@@ -1189,7 +1091,7 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid)
struct task_struct *p;
rcu_read_lock();
- if (unlikely(sig_kernel_stop(sig) || sig == SIGCONT)) {
+ if (unlikely(sig_needs_tasklist(sig))) {
read_lock(&tasklist_lock);
acquired_tasklist_lock = 1;
}
@@ -1405,12 +1307,10 @@ void sigqueue_free(struct sigqueue *q)
__sigqueue_free(q);
}
-int
-send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
+int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
{
unsigned long flags;
int ret = 0;
- struct sighand_struct *sh;
BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
@@ -1424,48 +1324,17 @@ send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
*/
rcu_read_lock();
- if (unlikely(p->flags & PF_EXITING)) {
+ if (!likely(lock_task_sighand(p, &flags))) {
ret = -1;
goto out_err;
}
-retry:
- sh = rcu_dereference(p->sighand);
-
- spin_lock_irqsave(&sh->siglock, flags);
- if (p->sighand != sh) {
- /* We raced with exec() in a multithreaded process... */
- spin_unlock_irqrestore(&sh->siglock, flags);
- goto retry;
- }
-
- /*
- * We do the check here again to handle the following scenario:
- *
- * CPU 0 CPU 1
- * send_sigqueue
- * check PF_EXITING
- * interrupt exit code running
- * __exit_signal
- * lock sighand->siglock
- * unlock sighand->siglock
- * lock sh->siglock
- * add(tsk->pending) flush_sigqueue(tsk->pending)
- *
- */
-
- if (unlikely(p->flags & PF_EXITING)) {
- ret = -1;
- goto out;
- }
-
if (unlikely(!list_empty(&q->list))) {
/*
* If an SI_TIMER entry is already queue just increment
* the overrun count.
*/
- if (q->info.si_code != SI_TIMER)
- BUG();
+ BUG_ON(q->info.si_code != SI_TIMER);
q->info.si_overrun++;
goto out;
}
@@ -1481,7 +1350,7 @@ retry:
signal_wake_up(p, sig == SIGKILL);
out:
- spin_unlock_irqrestore(&sh->siglock, flags);
+ unlock_task_sighand(p, &flags);
out_err:
rcu_read_unlock();
@@ -1513,8 +1382,7 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
* the overrun count. Other uses should not try to
* send the signal multiple times.
*/
- if (q->info.si_code != SI_TIMER)
- BUG();
+ BUG_ON(q->info.si_code != SI_TIMER);
q->info.si_overrun++;
goto out;
}
@@ -1613,14 +1481,14 @@ void do_notify_parent(struct task_struct *tsk, int sig)
spin_unlock_irqrestore(&psig->siglock, flags);
}
-static void do_notify_parent_cldstop(struct task_struct *tsk, int to_self, int why)
+static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
{
struct siginfo info;
unsigned long flags;
struct task_struct *parent;
struct sighand_struct *sighand;
- if (to_self)
+ if (tsk->ptrace & PT_PTRACED)
parent = tsk->parent;
else {
tsk = tsk->group_leader;
@@ -1689,13 +1557,14 @@ static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info)
/* Let the debugger run. */
set_current_state(TASK_TRACED);
spin_unlock_irq(&current->sighand->siglock);
+ try_to_freeze();
read_lock(&tasklist_lock);
if (likely(current->ptrace & PT_PTRACED) &&
likely(current->parent != current->real_parent ||
!(current->ptrace & PT_ATTACHED)) &&
(likely(current->parent->signal != current->signal) ||
!unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))) {
- do_notify_parent_cldstop(current, 1, CLD_TRAPPED);
+ do_notify_parent_cldstop(current, CLD_TRAPPED);
read_unlock(&tasklist_lock);
schedule();
} else {
@@ -1744,25 +1613,17 @@ void ptrace_notify(int exit_code)
static void
finish_stop(int stop_count)
{
- int to_self;
-
/*
* If there are no other threads in the group, or if there is
* a group stop in progress and we are the last to stop,
* report to the parent. When ptraced, every thread reports itself.
*/
- if (stop_count < 0 || (current->ptrace & PT_PTRACED))
- to_self = 1;
- else if (stop_count == 0)
- to_self = 0;
- else
- goto out;
-
- read_lock(&tasklist_lock);
- do_notify_parent_cldstop(current, to_self, CLD_STOPPED);
- read_unlock(&tasklist_lock);
+ if (stop_count == 0 || (current->ptrace & PT_PTRACED)) {
+ read_lock(&tasklist_lock);
+ do_notify_parent_cldstop(current, CLD_STOPPED);
+ read_unlock(&tasklist_lock);
+ }
-out:
schedule();
/*
* Now we don't run again until continued.
@@ -1776,12 +1637,10 @@ out:
* Returns nonzero if we've actually stopped and released the siglock.
* Returns zero if we didn't stop and still hold the siglock.
*/
-static int
-do_signal_stop(int signr)
+static int do_signal_stop(int signr)
{
struct signal_struct *sig = current->signal;
- struct sighand_struct *sighand = current->sighand;
- int stop_count = -1;
+ int stop_count;
if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED))
return 0;
@@ -1791,86 +1650,37 @@ do_signal_stop(int signr)
* There is a group stop in progress. We don't need to
* start another one.
*/
- signr = sig->group_exit_code;
stop_count = --sig->group_stop_count;
- current->exit_code = signr;
- set_current_state(TASK_STOPPED);
- if (stop_count == 0)
- sig->flags = SIGNAL_STOP_STOPPED;
- spin_unlock_irq(&sighand->siglock);
- }
- else if (thread_group_empty(current)) {
- /*
- * Lock must be held through transition to stopped state.
- */
- current->exit_code = current->signal->group_exit_code = signr;
- set_current_state(TASK_STOPPED);
- sig->flags = SIGNAL_STOP_STOPPED;
- spin_unlock_irq(&sighand->siglock);
- }
- else {
+ } else {
/*
* There is no group stop already in progress.
- * We must initiate one now, but that requires
- * dropping siglock to get both the tasklist lock
- * and siglock again in the proper order. Note that
- * this allows an intervening SIGCONT to be posted.
- * We need to check for that and bail out if necessary.
+ * We must initiate one now.
*/
struct task_struct *t;
- spin_unlock_irq(&sighand->siglock);
+ sig->group_exit_code = signr;
- /* signals can be posted during this window */
-
- read_lock(&tasklist_lock);
- spin_lock_irq(&sighand->siglock);
-
- if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED)) {
+ stop_count = 0;
+ for (t = next_thread(current); t != current; t = next_thread(t))
/*
- * Another stop or continue happened while we
- * didn't have the lock. We can just swallow this
- * signal now. If we raced with a SIGCONT, that
- * should have just cleared it now. If we raced
- * with another processor delivering a stop signal,
- * then the SIGCONT that wakes us up should clear it.
+ * Setting state to TASK_STOPPED for a group
+ * stop is always done with the siglock held,
+ * so this check has no races.
*/
- read_unlock(&tasklist_lock);
- return 0;
- }
-
- if (sig->group_stop_count == 0) {
- sig->group_exit_code = signr;
- stop_count = 0;
- for (t = next_thread(current); t != current;
- t = next_thread(t))
- /*
- * Setting state to TASK_STOPPED for a group
- * stop is always done with the siglock held,
- * so this check has no races.
- */
- if (!t->exit_state &&
- !(t->state & (TASK_STOPPED|TASK_TRACED))) {
- stop_count++;
- signal_wake_up(t, 0);
- }
- sig->group_stop_count = stop_count;
- }
- else {
- /* A race with another thread while unlocked. */
- signr = sig->group_exit_code;
- stop_count = --sig->group_stop_count;
- }
-
- current->exit_code = signr;
- set_current_state(TASK_STOPPED);
- if (stop_count == 0)
- sig->flags = SIGNAL_STOP_STOPPED;
-
- spin_unlock_irq(&sighand->siglock);
- read_unlock(&tasklist_lock);
+ if (!t->exit_state &&
+ !(t->state & (TASK_STOPPED|TASK_TRACED))) {
+ stop_count++;
+ signal_wake_up(t, 0);
+ }
+ sig->group_stop_count = stop_count;
}
+ if (stop_count == 0)
+ sig->flags = SIGNAL_STOP_STOPPED;
+ current->exit_code = sig->group_exit_code;
+ __set_current_state(TASK_STOPPED);
+
+ spin_unlock_irq(&current->sighand->siglock);
finish_stop(stop_count);
return 1;
}
@@ -1944,9 +1754,9 @@ relock:
/* Let the debugger run. */
ptrace_stop(signr, signr, info);
- /* We're back. Did the debugger cancel the sig or group_exit? */
+ /* We're back. Did the debugger cancel the sig? */
signr = current->exit_code;
- if (signr == 0 || current->signal->flags & SIGNAL_GROUP_EXIT)
+ if (signr == 0)
continue;
current->exit_code = 0;
@@ -1990,7 +1800,7 @@ relock:
continue;
/* Init gets no signals it doesn't want. */
- if (current->pid == 1)
+ if (current == child_reaper)
continue;
if (sig_kernel_stop(signr)) {
@@ -2430,8 +2240,7 @@ sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo)
return kill_proc_info(sig, &info, pid);
}
-int
-do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
+int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
{
struct k_sigaction *k;
sigset_t mask;
@@ -2457,6 +2266,7 @@ do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
if (act) {
sigdelsetmask(&act->sa.sa_mask,
sigmask(SIGKILL) | sigmask(SIGSTOP));
+ *k = *act;
/*
* POSIX 3.3.1.3:
* "Setting a signal action to SIG_IGN for a signal that is
@@ -2469,19 +2279,8 @@ do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
* be discarded, whether or not it is blocked"
*/
if (act->sa.sa_handler == SIG_IGN ||
- (act->sa.sa_handler == SIG_DFL &&
- sig_kernel_ignore(sig))) {
- /*
- * This is a fairly rare case, so we only take the
- * tasklist_lock once we're sure we'll need it.
- * Now we must do this little unlock and relock
- * dance to maintain the lock hierarchy.
- */
+ (act->sa.sa_handler == SIG_DFL && sig_kernel_ignore(sig))) {
struct task_struct *t = current;
- spin_unlock_irq(&t->sighand->siglock);
- read_lock(&tasklist_lock);
- spin_lock_irq(&t->sighand->siglock);
- *k = *act;
sigemptyset(&mask);
sigaddset(&mask, sig);
rm_from_queue_full(&mask, &t->signal->shared_pending);
@@ -2490,12 +2289,7 @@ do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
recalc_sigpending_tsk(t);
t = next_thread(t);
} while (t != current);
- spin_unlock_irq(&current->sighand->siglock);
- read_unlock(&tasklist_lock);
- return 0;
}
-
- *k = *act;
}
spin_unlock_irq(&current->sighand->siglock);
diff --git a/kernel/softirq.c b/kernel/softirq.c
index ec8fed42a86..336f92d64e2 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -446,7 +446,7 @@ static void takeover_tasklets(unsigned int cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
-static int __devinit cpu_callback(struct notifier_block *nfb,
+static int cpu_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
{
@@ -484,7 +484,7 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata cpu_nfb = {
+static struct notifier_block cpu_nfb = {
.notifier_call = cpu_callback
};
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index d9b3d5847ed..14c7faf0290 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -104,7 +104,7 @@ static int watchdog(void * __bind_cpu)
/*
* Create/destroy watchdog threads as CPUs come and go:
*/
-static int __devinit
+static int
cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
int hotcpu = (unsigned long)hcpu;
@@ -140,7 +140,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata cpu_nfb = {
+static struct notifier_block cpu_nfb = {
.notifier_call = cpu_callback
};
@@ -152,5 +152,5 @@ __init void spawn_softlockup_task(void)
cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
register_cpu_notifier(&cpu_nfb);
- notifier_chain_register(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
}
diff --git a/kernel/sys.c b/kernel/sys.c
index 38bc73ede2b..0b6ec0e7936 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -95,99 +95,304 @@ int cad_pid = 1;
* and the like.
*/
-static struct notifier_block *reboot_notifier_list;
-static DEFINE_RWLOCK(notifier_lock);
+static BLOCKING_NOTIFIER_HEAD(reboot_notifier_list);
+
+/*
+ * Notifier chain core routines. The exported routines below
+ * are layered on top of these, with appropriate locking added.
+ */
+
+static int notifier_chain_register(struct notifier_block **nl,
+ struct notifier_block *n)
+{
+ while ((*nl) != NULL) {
+ if (n->priority > (*nl)->priority)
+ break;
+ nl = &((*nl)->next);
+ }
+ n->next = *nl;
+ rcu_assign_pointer(*nl, n);
+ return 0;
+}
+
+static int notifier_chain_unregister(struct notifier_block **nl,
+ struct notifier_block *n)
+{
+ while ((*nl) != NULL) {
+ if ((*nl) == n) {
+ rcu_assign_pointer(*nl, n->next);
+ return 0;
+ }
+ nl = &((*nl)->next);
+ }
+ return -ENOENT;
+}
+
+static int __kprobes notifier_call_chain(struct notifier_block **nl,
+ unsigned long val, void *v)
+{
+ int ret = NOTIFY_DONE;
+ struct notifier_block *nb;
+
+ nb = rcu_dereference(*nl);
+ while (nb) {
+ ret = nb->notifier_call(nb, val, v);
+ if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
+ break;
+ nb = rcu_dereference(nb->next);
+ }
+ return ret;
+}
+
+/*
+ * Atomic notifier chain routines. Registration and unregistration
+ * use a mutex, and call_chain is synchronized by RCU (no locks).
+ */
/**
- * notifier_chain_register - Add notifier to a notifier chain
- * @list: Pointer to root list pointer
+ * atomic_notifier_chain_register - Add notifier to an atomic notifier chain
+ * @nh: Pointer to head of the atomic notifier chain
* @n: New entry in notifier chain
*
- * Adds a notifier to a notifier chain.
+ * Adds a notifier to an atomic notifier chain.
*
* Currently always returns zero.
*/
+
+int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
+ struct notifier_block *n)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&nh->lock, flags);
+ ret = notifier_chain_register(&nh->head, n);
+ spin_unlock_irqrestore(&nh->lock, flags);
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
+
+/**
+ * atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain
+ * @nh: Pointer to head of the atomic notifier chain
+ * @n: Entry to remove from notifier chain
+ *
+ * Removes a notifier from an atomic notifier chain.
+ *
+ * Returns zero on success or %-ENOENT on failure.
+ */
+int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
+ struct notifier_block *n)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&nh->lock, flags);
+ ret = notifier_chain_unregister(&nh->head, n);
+ spin_unlock_irqrestore(&nh->lock, flags);
+ synchronize_rcu();
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
+
+/**
+ * atomic_notifier_call_chain - Call functions in an atomic notifier chain
+ * @nh: Pointer to head of the atomic notifier chain
+ * @val: Value passed unmodified to notifier function
+ * @v: Pointer passed unmodified to notifier function
+ *
+ * Calls each function in a notifier chain in turn. The functions
+ * run in an atomic context, so they must not block.
+ * This routine uses RCU to synchronize with changes to the chain.
+ *
+ * If the return value of the notifier can be and'ed
+ * with %NOTIFY_STOP_MASK then atomic_notifier_call_chain
+ * will return immediately, with the return value of
+ * the notifier function which halted execution.
+ * Otherwise the return value is the return value
+ * of the last notifier function called.
+ */
-int notifier_chain_register(struct notifier_block **list, struct notifier_block *n)
+int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
+ unsigned long val, void *v)
{
- write_lock(&notifier_lock);
- while(*list)
- {
- if(n->priority > (*list)->priority)
- break;
- list= &((*list)->next);
- }
- n->next = *list;
- *list=n;
- write_unlock(&notifier_lock);
- return 0;
+ int ret;
+
+ rcu_read_lock();
+ ret = notifier_call_chain(&nh->head, val, v);
+ rcu_read_unlock();
+ return ret;
}
-EXPORT_SYMBOL(notifier_chain_register);
+EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
+
+/*
+ * Blocking notifier chain routines. All access to the chain is
+ * synchronized by an rwsem.
+ */
/**
- * notifier_chain_unregister - Remove notifier from a notifier chain
- * @nl: Pointer to root list pointer
+ * blocking_notifier_chain_register - Add notifier to a blocking notifier chain
+ * @nh: Pointer to head of the blocking notifier chain
* @n: New entry in notifier chain
*
- * Removes a notifier from a notifier chain.
+ * Adds a notifier to a blocking notifier chain.
+ * Must be called in process context.
*
- * Returns zero on success, or %-ENOENT on failure.
+ * Currently always returns zero.
*/
-int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n)
+int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
+ struct notifier_block *n)
{
- write_lock(&notifier_lock);
- while((*nl)!=NULL)
- {
- if((*nl)==n)
- {
- *nl=n->next;
- write_unlock(&notifier_lock);
- return 0;
- }
- nl=&((*nl)->next);
- }
- write_unlock(&notifier_lock);
- return -ENOENT;
+ int ret;
+
+ /*
+ * This code gets used during boot-up, when task switching is
+ * not yet working and interrupts must remain disabled. At
+ * such times we must not call down_write().
+ */
+ if (unlikely(system_state == SYSTEM_BOOTING))
+ return notifier_chain_register(&nh->head, n);
+
+ down_write(&nh->rwsem);
+ ret = notifier_chain_register(&nh->head, n);
+ up_write(&nh->rwsem);
+ return ret;
}
-EXPORT_SYMBOL(notifier_chain_unregister);
+EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
/**
- * notifier_call_chain - Call functions in a notifier chain
- * @n: Pointer to root pointer of notifier chain
+ * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain
+ * @nh: Pointer to head of the blocking notifier chain
+ * @n: Entry to remove from notifier chain
+ *
+ * Removes a notifier from a blocking notifier chain.
+ * Must be called from process context.
+ *
+ * Returns zero on success or %-ENOENT on failure.
+ */
+int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
+ struct notifier_block *n)
+{
+ int ret;
+
+ /*
+ * This code gets used during boot-up, when task switching is
+ * not yet working and interrupts must remain disabled. At
+ * such times we must not call down_write().
+ */
+ if (unlikely(system_state == SYSTEM_BOOTING))
+ return notifier_chain_unregister(&nh->head, n);
+
+ down_write(&nh->rwsem);
+ ret = notifier_chain_unregister(&nh->head, n);
+ up_write(&nh->rwsem);
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
+
+/**
+ * blocking_notifier_call_chain - Call functions in a blocking notifier chain
+ * @nh: Pointer to head of the blocking notifier chain
* @val: Value passed unmodified to notifier function
* @v: Pointer passed unmodified to notifier function
*
- * Calls each function in a notifier chain in turn.
+ * Calls each function in a notifier chain in turn. The functions
+ * run in a process context, so they are allowed to block.
*
- * If the return value of the notifier can be and'd
- * with %NOTIFY_STOP_MASK, then notifier_call_chain
+ * If the return value of the notifier can be and'ed
+ * with %NOTIFY_STOP_MASK then blocking_notifier_call_chain
* will return immediately, with the return value of
* the notifier function which halted execution.
- * Otherwise, the return value is the return value
+ * Otherwise the return value is the return value
* of the last notifier function called.
*/
-int __kprobes notifier_call_chain(struct notifier_block **n, unsigned long val, void *v)
+int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
+ unsigned long val, void *v)
{
- int ret=NOTIFY_DONE;
- struct notifier_block *nb = *n;
+ int ret;
- while(nb)
- {
- ret=nb->notifier_call(nb,val,v);
- if(ret&NOTIFY_STOP_MASK)
- {
- return ret;
- }
- nb=nb->next;
- }
+ down_read(&nh->rwsem);
+ ret = notifier_call_chain(&nh->head, val, v);
+ up_read(&nh->rwsem);
return ret;
}
-EXPORT_SYMBOL(notifier_call_chain);
+EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
+
+/*
+ * Raw notifier chain routines. There is no protection;
+ * the caller must provide it. Use at your own risk!
+ */
+
+/**
+ * raw_notifier_chain_register - Add notifier to a raw notifier chain
+ * @nh: Pointer to head of the raw notifier chain
+ * @n: New entry in notifier chain
+ *
+ * Adds a notifier to a raw notifier chain.
+ * All locking must be provided by the caller.
+ *
+ * Currently always returns zero.
+ */
+
+int raw_notifier_chain_register(struct raw_notifier_head *nh,
+ struct notifier_block *n)
+{
+ return notifier_chain_register(&nh->head, n);
+}
+
+EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
+
+/**
+ * raw_notifier_chain_unregister - Remove notifier from a raw notifier chain
+ * @nh: Pointer to head of the raw notifier chain
+ * @n: Entry to remove from notifier chain
+ *
+ * Removes a notifier from a raw notifier chain.
+ * All locking must be provided by the caller.
+ *
+ * Returns zero on success or %-ENOENT on failure.
+ */
+int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
+ struct notifier_block *n)
+{
+ return notifier_chain_unregister(&nh->head, n);
+}
+
+EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
+
+/**
+ * raw_notifier_call_chain - Call functions in a raw notifier chain
+ * @nh: Pointer to head of the raw notifier chain
+ * @val: Value passed unmodified to notifier function
+ * @v: Pointer passed unmodified to notifier function
+ *
+ * Calls each function in a notifier chain in turn. The functions
+ * run in an undefined context.
+ * All locking must be provided by the caller.
+ *
+ * If the return value of the notifier can be and'ed
+ * with %NOTIFY_STOP_MASK then raw_notifier_call_chain
+ * will return immediately, with the return value of
+ * the notifier function which halted execution.
+ * Otherwise the return value is the return value
+ * of the last notifier function called.
+ */
+
+int raw_notifier_call_chain(struct raw_notifier_head *nh,
+ unsigned long val, void *v)
+{
+ return notifier_call_chain(&nh->head, val, v);
+}
+
+EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
/**
* register_reboot_notifier - Register function to be called at reboot time
@@ -196,13 +401,13 @@ EXPORT_SYMBOL(notifier_call_chain);
* Registers a function with the list of functions
* to be called at reboot time.
*
- * Currently always returns zero, as notifier_chain_register
+ * Currently always returns zero, as blocking_notifier_chain_register
* always returns zero.
*/
int register_reboot_notifier(struct notifier_block * nb)
{
- return notifier_chain_register(&reboot_notifier_list, nb);
+ return blocking_notifier_chain_register(&reboot_notifier_list, nb);
}
EXPORT_SYMBOL(register_reboot_notifier);
@@ -219,7 +424,7 @@ EXPORT_SYMBOL(register_reboot_notifier);
int unregister_reboot_notifier(struct notifier_block * nb)
{
- return notifier_chain_unregister(&reboot_notifier_list, nb);
+ return blocking_notifier_chain_unregister(&reboot_notifier_list, nb);
}
EXPORT_SYMBOL(unregister_reboot_notifier);
@@ -380,7 +585,7 @@ EXPORT_SYMBOL_GPL(emergency_restart);
void kernel_restart_prepare(char *cmd)
{
- notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
+ blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
system_state = SYSTEM_RESTART;
device_shutdown();
}
@@ -430,7 +635,7 @@ EXPORT_SYMBOL_GPL(kernel_kexec);
void kernel_shutdown_prepare(enum system_states state)
{
- notifier_call_chain(&reboot_notifier_list,
+ blocking_notifier_call_chain(&reboot_notifier_list,
(state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL);
system_state = state;
device_shutdown();
@@ -997,69 +1202,24 @@ asmlinkage long sys_times(struct tms __user * tbuf)
*/
if (tbuf) {
struct tms tmp;
+ struct task_struct *tsk = current;
+ struct task_struct *t;
cputime_t utime, stime, cutime, cstime;
-#ifdef CONFIG_SMP
- if (thread_group_empty(current)) {
- /*
- * Single thread case without the use of any locks.
- *
- * We may race with release_task if two threads are
- * executing. However, release task first adds up the
- * counters (__exit_signal) before removing the task
- * from the process tasklist (__unhash_process).
- * __exit_signal also acquires and releases the
- * siglock which results in the proper memory ordering
- * so that the list modifications are always visible
- * after the counters have been updated.
- *
- * If the counters have been updated by the second thread
- * but the thread has not yet been removed from the list
- * then the other branch will be executing which will
- * block on tasklist_lock until the exit handling of the
- * other task is finished.
- *
- * This also implies that the sighand->siglock cannot
- * be held by another processor. So we can also
- * skip acquiring that lock.
- */
- utime = cputime_add(current->signal->utime, current->utime);
- stime = cputime_add(current->signal->utime, current->stime);
- cutime = current->signal->cutime;
- cstime = current->signal->cstime;
- } else
-#endif
- {
-
- /* Process with multiple threads */
- struct task_struct *tsk = current;
- struct task_struct *t;
+ spin_lock_irq(&tsk->sighand->siglock);
+ utime = tsk->signal->utime;
+ stime = tsk->signal->stime;
+ t = tsk;
+ do {
+ utime = cputime_add(utime, t->utime);
+ stime = cputime_add(stime, t->stime);
+ t = next_thread(t);
+ } while (t != tsk);
- read_lock(&tasklist_lock);
- utime = tsk->signal->utime;
- stime = tsk->signal->stime;
- t = tsk;
- do {
- utime = cputime_add(utime, t->utime);
- stime = cputime_add(stime, t->stime);
- t = next_thread(t);
- } while (t != tsk);
+ cutime = tsk->signal->cutime;
+ cstime = tsk->signal->cstime;
+ spin_unlock_irq(&tsk->sighand->siglock);
- /*
- * While we have tasklist_lock read-locked, no dying thread
- * can be updating current->signal->[us]time. Instead,
- * we got their counts included in the live thread loop.
- * However, another thread can come in right now and
- * do a wait call that updates current->signal->c[us]time.
- * To make sure we always see that pair updated atomically,
- * we take the siglock around fetching them.
- */
- spin_lock_irq(&tsk->sighand->siglock);
- cutime = tsk->signal->cutime;
- cstime = tsk->signal->cstime;
- spin_unlock_irq(&tsk->sighand->siglock);
- read_unlock(&tasklist_lock);
- }
tmp.tms_utime = cputime_to_clock_t(utime);
tmp.tms_stime = cputime_to_clock_t(stime);
tmp.tms_cutime = cputime_to_clock_t(cutime);
@@ -1212,18 +1372,29 @@ asmlinkage long sys_getsid(pid_t pid)
asmlinkage long sys_setsid(void)
{
struct task_struct *group_leader = current->group_leader;
- struct pid *pid;
+ pid_t session;
int err = -EPERM;
mutex_lock(&tty_mutex);
write_lock_irq(&tasklist_lock);
- pid = find_pid(PIDTYPE_PGID, group_leader->pid);
- if (pid)
+ /* Fail if I am already a session leader */
+ if (group_leader->signal->leader)
+ goto out;
+
+ session = group_leader->pid;
+ /* Fail if a process group id already exists that equals the
+ * proposed session id.
+ *
+ * Don't check if session id == 1 because kernel threads use this
+ * session id and so the check will always fail and make it so
+ * init cannot successfully call setsid.
+ */
+ if (session > 1 && find_task_by_pid_type(PIDTYPE_PGID, session))
goto out;
group_leader->signal->leader = 1;
- __set_special_pids(group_leader->pid, group_leader->pid);
+ __set_special_pids(session, session);
group_leader->signal->tty = NULL;
group_leader->signal->tty_old_pgrp = 0;
err = process_group(group_leader);
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 1067090db6b..5433195040f 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -42,6 +42,10 @@ cond_syscall(sys_recvmsg);
cond_syscall(sys_socketcall);
cond_syscall(sys_futex);
cond_syscall(compat_sys_futex);
+cond_syscall(sys_set_robust_list);
+cond_syscall(compat_sys_set_robust_list);
+cond_syscall(sys_get_robust_list);
+cond_syscall(compat_sys_get_robust_list);
cond_syscall(sys_epoll_create);
cond_syscall(sys_epoll_ctl);
cond_syscall(sys_epoll_wait);
@@ -116,3 +120,15 @@ cond_syscall(sys32_sysctl);
cond_syscall(ppc_rtas);
cond_syscall(sys_spu_run);
cond_syscall(sys_spu_create);
+
+/* mmu depending weak syscall entries */
+cond_syscall(sys_mprotect);
+cond_syscall(sys_msync);
+cond_syscall(sys_mlock);
+cond_syscall(sys_munlock);
+cond_syscall(sys_mlockall);
+cond_syscall(sys_munlockall);
+cond_syscall(sys_mincore);
+cond_syscall(sys_madvise);
+cond_syscall(sys_mremap);
+cond_syscall(sys_remap_file_pages);
diff --git a/kernel/time.c b/kernel/time.c
index ff8e7019c4c..b00ddc71ced 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -410,7 +410,7 @@ EXPORT_SYMBOL(current_kernel_time);
* current_fs_time - Return FS time
* @sb: Superblock.
*
- * Return the current time truncated to the time granuality supported by
+ * Return the current time truncated to the time granularity supported by
* the fs.
*/
struct timespec current_fs_time(struct super_block *sb)
@@ -421,11 +421,11 @@ struct timespec current_fs_time(struct super_block *sb)
EXPORT_SYMBOL(current_fs_time);
/**
- * timespec_trunc - Truncate timespec to a granuality
+ * timespec_trunc - Truncate timespec to a granularity
* @t: Timespec
- * @gran: Granuality in ns.
+ * @gran: Granularity in ns.
*
- * Truncate a timespec to a granuality. gran must be smaller than a second.
+ * Truncate a timespec to a granularity. gran must be smaller than a second.
* Always rounds down.
*
* This function should be only used for timestamps returned by
diff --git a/kernel/timer.c b/kernel/timer.c
index ab189dd187c..9e49deed468 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -54,7 +54,6 @@ EXPORT_SYMBOL(jiffies_64);
/*
* per-CPU timer vector definitions:
*/
-
#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
#define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)
#define TVN_SIZE (1 << TVN_BITS)
@@ -62,11 +61,6 @@ EXPORT_SYMBOL(jiffies_64);
#define TVN_MASK (TVN_SIZE - 1)
#define TVR_MASK (TVR_SIZE - 1)
-struct timer_base_s {
- spinlock_t lock;
- struct timer_list *running_timer;
-};
-
typedef struct tvec_s {
struct list_head vec[TVN_SIZE];
} tvec_t;
@@ -76,7 +70,8 @@ typedef struct tvec_root_s {
} tvec_root_t;
struct tvec_t_base_s {
- struct timer_base_s t_base;
+ spinlock_t lock;
+ struct timer_list *running_timer;
unsigned long timer_jiffies;
tvec_root_t tv1;
tvec_t tv2;
@@ -86,14 +81,16 @@ struct tvec_t_base_s {
} ____cacheline_aligned_in_smp;
typedef struct tvec_t_base_s tvec_base_t;
-static DEFINE_PER_CPU(tvec_base_t *, tvec_bases);
-static tvec_base_t boot_tvec_bases;
+
+tvec_base_t boot_tvec_bases;
+EXPORT_SYMBOL(boot_tvec_bases);
+static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = { &boot_tvec_bases };
static inline void set_running_timer(tvec_base_t *base,
struct timer_list *timer)
{
#ifdef CONFIG_SMP
- base->t_base.running_timer = timer;
+ base->running_timer = timer;
#endif
}
@@ -139,15 +136,6 @@ static void internal_add_timer(tvec_base_t *base, struct timer_list *timer)
list_add_tail(&timer->entry, vec);
}
-typedef struct timer_base_s timer_base_t;
-/*
- * Used by TIMER_INITIALIZER, we can't use per_cpu(tvec_bases)
- * at compile time, and we need timer->base to lock the timer.
- */
-timer_base_t __init_timer_base
- ____cacheline_aligned_in_smp = { .lock = SPIN_LOCK_UNLOCKED };
-EXPORT_SYMBOL(__init_timer_base);
-
/***
* init_timer - initialize a timer.
* @timer: the timer to be initialized
@@ -158,7 +146,7 @@ EXPORT_SYMBOL(__init_timer_base);
void fastcall init_timer(struct timer_list *timer)
{
timer->entry.next = NULL;
- timer->base = &per_cpu(tvec_bases, raw_smp_processor_id())->t_base;
+ timer->base = per_cpu(tvec_bases, raw_smp_processor_id());
}
EXPORT_SYMBOL(init_timer);
@@ -174,7 +162,7 @@ static inline void detach_timer(struct timer_list *timer,
}
/*
- * We are using hashed locking: holding per_cpu(tvec_bases).t_base.lock
+ * We are using hashed locking: holding per_cpu(tvec_bases).lock
* means that all timers which are tied to this base via timer->base are
* locked, and the base itself is locked too.
*
@@ -185,10 +173,10 @@ static inline void detach_timer(struct timer_list *timer,
* possible to set timer->base = NULL and drop the lock: the timer remains
* locked.
*/
-static timer_base_t *lock_timer_base(struct timer_list *timer,
+static tvec_base_t *lock_timer_base(struct timer_list *timer,
unsigned long *flags)
{
- timer_base_t *base;
+ tvec_base_t *base;
for (;;) {
base = timer->base;
@@ -205,8 +193,7 @@ static timer_base_t *lock_timer_base(struct timer_list *timer,
int __mod_timer(struct timer_list *timer, unsigned long expires)
{
- timer_base_t *base;
- tvec_base_t *new_base;
+ tvec_base_t *base, *new_base;
unsigned long flags;
int ret = 0;
@@ -221,7 +208,7 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
new_base = __get_cpu_var(tvec_bases);
- if (base != &new_base->t_base) {
+ if (base != new_base) {
/*
* We are trying to schedule the timer on the local CPU.
* However we can't change timer's base while it is running,
@@ -229,21 +216,19 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
* handler yet has not finished. This also guarantees that
* the timer is serialized wrt itself.
*/
- if (unlikely(base->running_timer == timer)) {
- /* The timer remains on a former base */
- new_base = container_of(base, tvec_base_t, t_base);
- } else {
+ if (likely(base->running_timer != timer)) {
/* See the comment in lock_timer_base() */
timer->base = NULL;
spin_unlock(&base->lock);
- spin_lock(&new_base->t_base.lock);
- timer->base = &new_base->t_base;
+ base = new_base;
+ spin_lock(&base->lock);
+ timer->base = base;
}
}
timer->expires = expires;
- internal_add_timer(new_base, timer);
- spin_unlock_irqrestore(&new_base->t_base.lock, flags);
+ internal_add_timer(base, timer);
+ spin_unlock_irqrestore(&base->lock, flags);
return ret;
}
@@ -263,10 +248,10 @@ void add_timer_on(struct timer_list *timer, int cpu)
unsigned long flags;
BUG_ON(timer_pending(timer) || !timer->function);
- spin_lock_irqsave(&base->t_base.lock, flags);
- timer->base = &base->t_base;
+ spin_lock_irqsave(&base->lock, flags);
+ timer->base = base;
internal_add_timer(base, timer);
- spin_unlock_irqrestore(&base->t_base.lock, flags);
+ spin_unlock_irqrestore(&base->lock, flags);
}
@@ -319,7 +304,7 @@ EXPORT_SYMBOL(mod_timer);
*/
int del_timer(struct timer_list *timer)
{
- timer_base_t *base;
+ tvec_base_t *base;
unsigned long flags;
int ret = 0;
@@ -346,7 +331,7 @@ EXPORT_SYMBOL(del_timer);
*/
int try_to_del_timer_sync(struct timer_list *timer)
{
- timer_base_t *base;
+ tvec_base_t *base;
unsigned long flags;
int ret = -1;
@@ -410,7 +395,7 @@ static int cascade(tvec_base_t *base, tvec_t *tv, int index)
struct timer_list *tmp;
tmp = list_entry(curr, struct timer_list, entry);
- BUG_ON(tmp->base != &base->t_base);
+ BUG_ON(tmp->base != base);
curr = curr->next;
internal_add_timer(base, tmp);
}
@@ -432,7 +417,7 @@ static inline void __run_timers(tvec_base_t *base)
{
struct timer_list *timer;
- spin_lock_irq(&base->t_base.lock);
+ spin_lock_irq(&base->lock);
while (time_after_eq(jiffies, base->timer_jiffies)) {
struct list_head work_list = LIST_HEAD_INIT(work_list);
struct list_head *head = &work_list;
@@ -458,7 +443,7 @@ static inline void __run_timers(tvec_base_t *base)
set_running_timer(base, timer);
detach_timer(timer, 1);
- spin_unlock_irq(&base->t_base.lock);
+ spin_unlock_irq(&base->lock);
{
int preempt_count = preempt_count();
fn(data);
@@ -471,11 +456,11 @@ static inline void __run_timers(tvec_base_t *base)
BUG();
}
}
- spin_lock_irq(&base->t_base.lock);
+ spin_lock_irq(&base->lock);
}
}
set_running_timer(base, NULL);
- spin_unlock_irq(&base->t_base.lock);
+ spin_unlock_irq(&base->lock);
}
#ifdef CONFIG_NO_IDLE_HZ
@@ -506,7 +491,7 @@ unsigned long next_timer_interrupt(void)
hr_expires += jiffies;
base = __get_cpu_var(tvec_bases);
- spin_lock(&base->t_base.lock);
+ spin_lock(&base->lock);
expires = base->timer_jiffies + (LONG_MAX >> 1);
list = NULL;
@@ -554,7 +539,23 @@ found:
expires = nte->expires;
}
}
- spin_unlock(&base->t_base.lock);
+ spin_unlock(&base->lock);
+
+ /*
+ * It can happen that other CPUs service timer IRQs and increment
+ * jiffies, but we have not yet got a local timer tick to process
+ * the timer wheels. In that case, the expiry time can be before
+ * jiffies, but since the high-resolution timer here is relative to
+ * jiffies, the default expression when high-resolution timers are
+ * not active,
+ *
+ * time_before(MAX_JIFFY_OFFSET + jiffies, expires)
+ *
+ * would falsely evaluate to true. If that is the case, just
+ * return jiffies so that we can immediately fire the local timer
+ */
+ if (time_before(expires, jiffies))
+ return jiffies;
if (time_before(hr_expires, expires))
return hr_expires;
@@ -841,7 +842,7 @@ void update_process_times(int user_tick)
*/
static unsigned long count_active_tasks(void)
{
- return (nr_running() + nr_uninterruptible()) * FIXED_1;
+ return nr_active() * FIXED_1;
}
/*
@@ -1240,29 +1241,37 @@ static int __devinit init_timers_cpu(int cpu)
{
int j;
tvec_base_t *base;
+ static char __devinitdata tvec_base_done[NR_CPUS];
- base = per_cpu(tvec_bases, cpu);
- if (!base) {
+ if (!tvec_base_done[cpu]) {
static char boot_done;
- /*
- * Cannot do allocation in init_timers as that runs before the
- * allocator initializes (and would waste memory if there are
- * more possible CPUs than will ever be installed/brought up).
- */
if (boot_done) {
+ /*
+ * The APs use this path later in boot
+ */
base = kmalloc_node(sizeof(*base), GFP_KERNEL,
cpu_to_node(cpu));
if (!base)
return -ENOMEM;
memset(base, 0, sizeof(*base));
+ per_cpu(tvec_bases, cpu) = base;
} else {
- base = &boot_tvec_bases;
+ /*
+ * This is for the boot CPU - we use compile-time
+ * static initialisation because per-cpu memory isn't
+ * ready yet and because the memory allocators are not
+ * initialised either.
+ */
boot_done = 1;
+ base = &boot_tvec_bases;
}
- per_cpu(tvec_bases, cpu) = base;
+ tvec_base_done[cpu] = 1;
+ } else {
+ base = per_cpu(tvec_bases, cpu);
}
- spin_lock_init(&base->t_base.lock);
+
+ spin_lock_init(&base->lock);
for (j = 0; j < TVN_SIZE; j++) {
INIT_LIST_HEAD(base->tv5.vec + j);
INIT_LIST_HEAD(base->tv4.vec + j);
@@ -1284,7 +1293,7 @@ static void migrate_timer_list(tvec_base_t *new_base, struct list_head *head)
while (!list_empty(head)) {
timer = list_entry(head->next, struct timer_list, entry);
detach_timer(timer, 0);
- timer->base = &new_base->t_base;
+ timer->base = new_base;
internal_add_timer(new_base, timer);
}
}
@@ -1300,11 +1309,11 @@ static void __devinit migrate_timers(int cpu)
new_base = get_cpu_var(tvec_bases);
local_irq_disable();
- spin_lock(&new_base->t_base.lock);
- spin_lock(&old_base->t_base.lock);
+ spin_lock(&new_base->lock);
+ spin_lock(&old_base->lock);
+
+ BUG_ON(old_base->running_timer);
- if (old_base->t_base.running_timer)
- BUG();
for (i = 0; i < TVR_SIZE; i++)
migrate_timer_list(new_base, old_base->tv1.vec + i);
for (i = 0; i < TVN_SIZE; i++) {
@@ -1314,14 +1323,14 @@ static void __devinit migrate_timers(int cpu)
migrate_timer_list(new_base, old_base->tv5.vec + i);
}
- spin_unlock(&old_base->t_base.lock);
- spin_unlock(&new_base->t_base.lock);
+ spin_unlock(&old_base->lock);
+ spin_unlock(&new_base->lock);
local_irq_enable();
put_cpu_var(tvec_bases);
}
#endif /* CONFIG_HOTPLUG_CPU */
-static int __devinit timer_cpu_notify(struct notifier_block *self,
+static int timer_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
long cpu = (long)hcpu;
@@ -1341,7 +1350,7 @@ static int __devinit timer_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata timers_nb = {
+static struct notifier_block timers_nb = {
.notifier_call = timer_cpu_notify,
};
@@ -1471,7 +1480,7 @@ static void time_interpolator_update(long delta_nsec)
*/
if (jiffies % INTERPOLATOR_ADJUST == 0)
{
- if (time_interpolator->skips == 0 && time_interpolator->offset > TICK_NSEC)
+ if (time_interpolator->skips == 0 && time_interpolator->offset > tick_nsec)
time_interpolator->nsec_per_cyc--;
if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0)
time_interpolator->nsec_per_cyc++;
@@ -1495,8 +1504,7 @@ register_time_interpolator(struct time_interpolator *ti)
unsigned long flags;
/* Sanity check */
- if (ti->frequency == 0 || ti->mask == 0)
- BUG();
+ BUG_ON(ti->frequency == 0 || ti->mask == 0);
ti->nsec_per_cyc = ((u64)NSEC_PER_SEC << ti->shift) / ti->frequency;
spin_lock(&time_interpolator_lock);
diff --git a/kernel/uid16.c b/kernel/uid16.c
index aa25605027c..187e2a42387 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -20,43 +20,67 @@
asmlinkage long sys_chown16(const char __user * filename, old_uid_t user, old_gid_t group)
{
- return sys_chown(filename, low2highuid(user), low2highgid(group));
+ long ret = sys_chown(filename, low2highuid(user), low2highgid(group));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_lchown16(const char __user * filename, old_uid_t user, old_gid_t group)
{
- return sys_lchown(filename, low2highuid(user), low2highgid(group));
+ long ret = sys_lchown(filename, low2highuid(user), low2highgid(group));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group)
{
- return sys_fchown(fd, low2highuid(user), low2highgid(group));
+ long ret = sys_fchown(fd, low2highuid(user), low2highgid(group));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid)
{
- return sys_setregid(low2highgid(rgid), low2highgid(egid));
+ long ret = sys_setregid(low2highgid(rgid), low2highgid(egid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_setgid16(old_gid_t gid)
{
- return sys_setgid(low2highgid(gid));
+ long ret = sys_setgid(low2highgid(gid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid)
{
- return sys_setreuid(low2highuid(ruid), low2highuid(euid));
+ long ret = sys_setreuid(low2highuid(ruid), low2highuid(euid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_setuid16(old_uid_t uid)
{
- return sys_setuid(low2highuid(uid));
+ long ret = sys_setuid(low2highuid(uid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid)
{
- return sys_setresuid(low2highuid(ruid), low2highuid(euid),
- low2highuid(suid));
+ long ret = sys_setresuid(low2highuid(ruid), low2highuid(euid),
+ low2highuid(suid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid, old_uid_t __user *suid)
@@ -72,8 +96,11 @@ asmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid,
asmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid)
{
- return sys_setresgid(low2highgid(rgid), low2highgid(egid),
- low2highgid(sgid));
+ long ret = sys_setresgid(low2highgid(rgid), low2highgid(egid),
+ low2highgid(sgid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid, old_gid_t __user *sgid)
@@ -89,12 +116,18 @@ asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid,
asmlinkage long sys_setfsuid16(old_uid_t uid)
{
- return sys_setfsuid(low2highuid(uid));
+ long ret = sys_setfsuid(low2highuid(uid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
asmlinkage long sys_setfsgid16(old_gid_t gid)
{
- return sys_setfsgid(low2highgid(gid));
+ long ret = sys_setfsgid(low2highgid(gid));
+ /* avoid REGPARM breakage on x86: */
+ prevent_tail_call(ret);
+ return ret;
}
static int groups16_to_user(old_gid_t __user *grouplist,
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index e9e464a9037..880fb415a8f 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -547,7 +547,7 @@ static void take_over_work(struct workqueue_struct *wq, unsigned int cpu)
}
/* We're holding the cpucontrol mutex here */
-static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
+static int workqueue_cpu_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
{
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 7e70ab13e19..ccb0c1fdf1b 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -101,7 +101,7 @@ config DEBUG_PREEMPT
config DEBUG_MUTEXES
bool "Mutex debugging, deadlock detection"
- default y
+ default n
depends on DEBUG_KERNEL
help
This allows mutex semantics violations and mutex related deadlocks
@@ -157,22 +157,9 @@ config DEBUG_INFO
If unsure, say N.
-config DEBUG_IOREMAP
- bool "Enable ioremap() debugging"
- depends on DEBUG_KERNEL && PARISC
- help
- Enabling this option will cause the kernel to distinguish between
- ioremapped and physical addresses. It will print a backtrace (at
- most one every 10 seconds), hopefully allowing you to see which
- drivers need work. Fixing all these problems is a prerequisite
- for turning on USE_HPPA_IOREMAP. The warnings are harmless;
- the kernel has enough information to fix the broken drivers
- automatically, but we'd like to make it more efficient by not
- having to do that.
-
config DEBUG_FS
bool "Debug Filesystem"
- depends on DEBUG_KERNEL && SYSFS
+ depends on SYSFS
help
debugfs is a virtual file system that kernel developers use to put
debugging files into. Enable this option to be able to read and
@@ -202,7 +189,7 @@ config FRAME_POINTER
config UNWIND_INFO
bool "Compile the kernel with frame unwind information"
depends on !IA64
- depends on !MODULES || !(MIPS || PARISC || PPC || SUPERH || SPARC64 || V850)
+ depends on !MODULES || !(MIPS || PARISC || PPC || SUPERH || V850)
help
If you say Y here the resulting kernel image will be slightly larger
but not slower, and it will give very useful debugging information.
diff --git a/lib/kobject.c b/lib/kobject.c
index 25204a41a9b..687ab418d29 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -128,6 +128,7 @@ void kobject_init(struct kobject * kobj)
{
kref_init(&kobj->kref);
INIT_LIST_HEAD(&kobj->entry);
+ init_waitqueue_head(&kobj->poll);
kobj->kset = kset_get(kobj->kset);
}
@@ -197,14 +198,14 @@ int kobject_add(struct kobject * kobj)
/* be noisy on error issues */
if (error == -EEXIST)
- printk("kobject_add failed for %s with -EEXIST, "
+ pr_debug("kobject_add failed for %s with -EEXIST, "
"don't try to register things with the "
"same name in the same directory.\n",
kobject_name(kobj));
else
- printk("kobject_add failed for %s (%d)\n",
+ pr_debug("kobject_add failed for %s (%d)\n",
kobject_name(kobj), error);
- dump_stack();
+ /* dump_stack(); */
}
return error;
@@ -421,7 +422,6 @@ struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
return k;
}
-EXPORT_SYMBOL_GPL(kobject_add_dir);
/**
* kset_init - initialize a kset for use
@@ -568,7 +568,7 @@ int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
* @s: subsystem.
* @a: attribute desciptor.
*/
-
+#if 0
void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
{
if (subsys_get(s)) {
@@ -576,6 +576,7 @@ void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
subsys_put(s);
}
}
+#endif /* 0 */
EXPORT_SYMBOL(kobject_init);
EXPORT_SYMBOL(kobject_register);
@@ -587,10 +588,7 @@ EXPORT_SYMBOL(kobject_del);
EXPORT_SYMBOL(kset_register);
EXPORT_SYMBOL(kset_unregister);
-EXPORT_SYMBOL(kset_find_obj);
-EXPORT_SYMBOL(subsystem_init);
EXPORT_SYMBOL(subsystem_register);
EXPORT_SYMBOL(subsystem_unregister);
EXPORT_SYMBOL(subsys_create_file);
-EXPORT_SYMBOL(subsys_remove_file);
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 982226daf93..7f20e7b857c 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -25,11 +25,13 @@
#define BUFFER_SIZE 2048 /* buffer for the variables */
#define NUM_ENVP 32 /* number of env pointers */
-#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
+#if defined(CONFIG_HOTPLUG)
u64 uevent_seqnum;
char uevent_helper[UEVENT_HELPER_PATH_LEN] = "/sbin/hotplug";
static DEFINE_SPINLOCK(sequence_lock);
+#if defined(CONFIG_NET)
static struct sock *uevent_sock;
+#endif
static char *action_to_string(enum kobject_action action)
{
@@ -155,6 +157,7 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
spin_unlock(&sequence_lock);
sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq);
+#if defined(CONFIG_NET)
/* send netlink message */
if (uevent_sock) {
struct sk_buff *skb;
@@ -179,6 +182,7 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
}
}
+#endif
/* call uevent_helper, usually only enabled during early boot */
if (uevent_helper[0]) {
@@ -249,6 +253,7 @@ int add_uevent_var(char **envp, int num_envp, int *cur_index,
}
EXPORT_SYMBOL_GPL(add_uevent_var);
+#if defined(CONFIG_NET)
static int __init kobject_uevent_init(void)
{
uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
@@ -264,5 +269,6 @@ static int __init kobject_uevent_init(void)
}
postcore_initcall(kobject_uevent_init);
+#endif
#endif /* CONFIG_HOTPLUG */
diff --git a/lib/string.c b/lib/string.c
index b3c28a3f633..064f6315b1c 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -362,6 +362,7 @@ size_t strspn(const char *s, const char *accept)
EXPORT_SYMBOL(strspn);
#endif
+#ifndef __HAVE_ARCH_STRCSPN
/**
* strcspn - Calculate the length of the initial substring of @s which does
* not contain letters in @reject
@@ -384,6 +385,7 @@ size_t strcspn(const char *s, const char *reject)
return count;
}
EXPORT_SYMBOL(strcspn);
+#endif
#ifndef __HAVE_ARCH_STRPBRK
/**
@@ -403,6 +405,7 @@ char *strpbrk(const char *cs, const char *ct)
}
return NULL;
}
+EXPORT_SYMBOL(strpbrk);
#endif
#ifndef __HAVE_ARCH_STRSEP
@@ -467,7 +470,7 @@ EXPORT_SYMBOL(memset);
void *memcpy(void *dest, const void *src, size_t count)
{
char *tmp = dest;
- char *s = src;
+ const char *s = src;
while (count--)
*tmp++ = *s++;
diff --git a/mm/Makefile b/mm/Makefile
index f10c753dce6..0b8f73f2ed1 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -10,7 +10,7 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \
obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
page_alloc.o page-writeback.o pdflush.o \
readahead.o swap.o truncate.o vmscan.o \
- prio_tree.o util.o $(mmu-y)
+ prio_tree.o util.o mmzone.o $(mmu-y)
obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o
obj-$(CONFIG_HUGETLBFS) += hugetlb.o
diff --git a/mm/bootmem.c b/mm/bootmem.c
index b55bd39fc5d..d213feded10 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -33,6 +33,7 @@ EXPORT_SYMBOL(max_pfn); /* This is exported so
* dma_get_required_mask(), which uses
* it, can be an inline function */
+static LIST_HEAD(bdata_list);
#ifdef CONFIG_CRASH_DUMP
/*
* If we have booted due to a crash, max_pfn will be a very low value. We need
@@ -52,6 +53,27 @@ unsigned long __init bootmem_bootmap_pages (unsigned long pages)
return mapsize;
}
+/*
+ * link bdata in order
+ */
+static void link_bootmem(bootmem_data_t *bdata)
+{
+ bootmem_data_t *ent;
+ if (list_empty(&bdata_list)) {
+ list_add(&bdata->list, &bdata_list);
+ return;
+ }
+ /* insert in order */
+ list_for_each_entry(ent, &bdata_list, list) {
+ if (bdata->node_boot_start < ent->node_boot_start) {
+ list_add_tail(&bdata->list, &ent->list);
+ return;
+ }
+ }
+ list_add_tail(&bdata->list, &bdata_list);
+ return;
+}
+
/*
* Called once to set up the allocator itself.
@@ -62,13 +84,11 @@ static unsigned long __init init_bootmem_core (pg_data_t *pgdat,
bootmem_data_t *bdata = pgdat->bdata;
unsigned long mapsize = ((end - start)+7)/8;
- pgdat->pgdat_next = pgdat_list;
- pgdat_list = pgdat;
-
mapsize = ALIGN(mapsize, sizeof(long));
bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
bdata->node_boot_start = (start << PAGE_SHIFT);
bdata->node_low_pfn = end;
+ link_bootmem(bdata);
/*
* Initially all pages are reserved - setup_arch() has to
@@ -381,16 +401,22 @@ unsigned long __init free_all_bootmem (void)
return(free_all_bootmem_core(NODE_DATA(0)));
}
-void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal)
+void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align, unsigned long goal)
{
- pg_data_t *pgdat = pgdat_list;
+ bootmem_data_t *bdata;
void *ptr;
- for_each_pgdat(pgdat)
- if ((ptr = __alloc_bootmem_core(pgdat->bdata, size,
- align, goal, 0)))
+ list_for_each_entry(bdata, &bdata_list, list)
+ if ((ptr = __alloc_bootmem_core(bdata, size, align, goal, 0)))
return(ptr);
+ return NULL;
+}
+void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal)
+{
+ void *mem = __alloc_bootmem_nopanic(size,align,goal);
+ if (mem)
+ return mem;
/*
* Whoops, we cannot satisfy the allocation request.
*/
@@ -416,11 +442,11 @@ void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size, unsigne
void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, unsigned long goal)
{
- pg_data_t *pgdat = pgdat_list;
+ bootmem_data_t *bdata;
void *ptr;
- for_each_pgdat(pgdat)
- if ((ptr = __alloc_bootmem_core(pgdat->bdata, size,
+ list_for_each_entry(bdata, &bdata_list, list)
+ if ((ptr = __alloc_bootmem_core(bdata, size,
align, goal, LOW32LIMIT)))
return(ptr);
diff --git a/mm/fadvise.c b/mm/fadvise.c
index 907c39257ca..0a03357a1f8 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -35,17 +35,6 @@
*
* LINUX_FADV_ASYNC_WRITE: push some or all of the dirty pages at the disk.
*
- * LINUX_FADV_WRITE_WAIT, LINUX_FADV_ASYNC_WRITE: push all of the currently
- * dirty pages at the disk.
- *
- * LINUX_FADV_WRITE_WAIT, LINUX_FADV_ASYNC_WRITE, LINUX_FADV_WRITE_WAIT: push
- * all of the currently dirty pages at the disk, wait until they have been
- * written.
- *
- * It should be noted that none of these operations write out the file's
- * metadata. So unless the application is strictly performing overwrites of
- * already-instantiated disk blocks, there are no guarantees here that the data
- * will be available after a crash.
*/
asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
{
@@ -129,15 +118,6 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
invalidate_mapping_pages(mapping, start_index,
end_index);
break;
- case LINUX_FADV_ASYNC_WRITE:
- ret = __filemap_fdatawrite_range(mapping, offset, endbyte,
- WB_SYNC_NONE);
- break;
- case LINUX_FADV_WRITE_WAIT:
- ret = wait_on_page_writeback_range(mapping,
- offset >> PAGE_CACHE_SHIFT,
- endbyte >> PAGE_CACHE_SHIFT);
- break;
default:
ret = -EINVAL;
}
diff --git a/mm/filemap.c b/mm/filemap.c
index 3ef20739e72..fd57442186c 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -697,6 +697,38 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
return ret;
}
+/**
+ * find_get_pages_contig - gang contiguous pagecache lookup
+ * @mapping: The address_space to search
+ * @index: The starting page index
+ * @nr_pages: The maximum number of pages
+ * @pages: Where the resulting pages are placed
+ *
+ * find_get_pages_contig() works exactly like find_get_pages(), except
+ * that the returned number of pages are guaranteed to be contiguous.
+ *
+ * find_get_pages_contig() returns the number of pages which were found.
+ */
+unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index,
+ unsigned int nr_pages, struct page **pages)
+{
+ unsigned int i;
+ unsigned int ret;
+
+ read_lock_irq(&mapping->tree_lock);
+ ret = radix_tree_gang_lookup(&mapping->page_tree,
+ (void **)pages, index, nr_pages);
+ for (i = 0; i < ret; i++) {
+ if (pages[i]->mapping == NULL || pages[i]->index != index)
+ break;
+
+ page_cache_get(pages[i]);
+ index++;
+ }
+ read_unlock_irq(&mapping->tree_lock);
+ return i;
+}
+
/*
* Like find_get_pages, except we only return pages which are tagged with
* `tag'. We update *index to index the next page for the traversal.
diff --git a/mm/highmem.c b/mm/highmem.c
index 55885f64af4..9b274fdf9d0 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -74,8 +74,7 @@ static void flush_all_zero_pkmaps(void)
pkmap_count[i] = 0;
/* sanity check */
- if (pte_none(pkmap_page_table[i]))
- BUG();
+ BUG_ON(pte_none(pkmap_page_table[i]));
/*
* Don't need an atomic fetch-and-clear op here;
@@ -158,8 +157,7 @@ void fastcall *kmap_high(struct page *page)
if (!vaddr)
vaddr = map_new_virtual(page);
pkmap_count[PKMAP_NR(vaddr)]++;
- if (pkmap_count[PKMAP_NR(vaddr)] < 2)
- BUG();
+ BUG_ON(pkmap_count[PKMAP_NR(vaddr)] < 2);
spin_unlock(&kmap_lock);
return (void*) vaddr;
}
@@ -174,8 +172,7 @@ void fastcall kunmap_high(struct page *page)
spin_lock(&kmap_lock);
vaddr = (unsigned long)page_address(page);
- if (!vaddr)
- BUG();
+ BUG_ON(!vaddr);
nr = PKMAP_NR(vaddr);
/*
@@ -220,8 +217,7 @@ static __init int init_emergency_pool(void)
return 0;
page_pool = mempool_create_page_pool(POOL_SIZE, 0);
- if (!page_pool)
- BUG();
+ BUG_ON(!page_pool);
printk("highmem bounce pool size: %d pages\n", POOL_SIZE);
return 0;
@@ -264,8 +260,7 @@ int init_emergency_isa_pool(void)
isa_page_pool = mempool_create(ISA_POOL_SIZE, mempool_alloc_pages_isa,
mempool_free_pages, (void *) 0);
- if (!isa_page_pool)
- BUG();
+ BUG_ON(!isa_page_pool);
printk("isa bounce pool size: %d pages\n", ISA_POOL_SIZE);
return 0;
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ebad6bbb350..832f676ca03 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -334,6 +334,7 @@ static unsigned long set_max_huge_pages(unsigned long count)
return nr_huge_pages;
spin_lock(&hugetlb_lock);
+ count = max(count, reserved_huge_pages);
try_to_free_low(count);
while (count < nr_huge_pages) {
struct page *page = dequeue_huge_page(NULL, 0);
@@ -697,9 +698,10 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
pfn_offset = (vaddr & ~HPAGE_MASK) >> PAGE_SHIFT;
page = pte_page(*pte);
same_page:
- get_page(page);
- if (pages)
+ if (pages) {
+ get_page(page);
pages[i] = page + pfn_offset;
+ }
if (vmas)
vmas[i] = vma;
diff --git a/mm/madvise.c b/mm/madvise.c
index af3d573b014..4e196155a0c 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -168,6 +168,9 @@ static long madvise_remove(struct vm_area_struct *vma,
return -EINVAL;
}
+ if ((vma->vm_flags & (VM_SHARED|VM_WRITE)) != (VM_SHARED|VM_WRITE))
+ return -EACCES;
+
mapping = vma->vm_file->f_mapping;
offset = (loff_t)(start - vma->vm_start)
diff --git a/mm/memory.c b/mm/memory.c
index 8d8f52569f3..0ec7bc64427 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -87,7 +87,7 @@ int randomize_va_space __read_mostly = 1;
static int __init disable_randmaps(char *s)
{
randomize_va_space = 0;
- return 0;
+ return 1;
}
__setup("norandmaps", disable_randmaps);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 1fe76d963ac..70df5c0d957 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -69,12 +69,16 @@ int __add_pages(struct zone *zone, unsigned long phys_start_pfn,
for (i = 0; i < nr_pages; i += PAGES_PER_SECTION) {
err = __add_section(zone, phys_start_pfn + i);
- if (err)
+ /* We want to keep adding the rest of the
+ * sections if the first ones already exist
+ */
+ if (err && (err != -EEXIST))
break;
}
return err;
}
+EXPORT_SYMBOL_GPL(__add_pages);
static void grow_zone_span(struct zone *zone,
unsigned long start_pfn, unsigned long end_pfn)
@@ -87,8 +91,8 @@ static void grow_zone_span(struct zone *zone,
if (start_pfn < zone->zone_start_pfn)
zone->zone_start_pfn = start_pfn;
- if (end_pfn > old_zone_end_pfn)
- zone->spanned_pages = end_pfn - zone->zone_start_pfn;
+ zone->spanned_pages = max(old_zone_end_pfn, end_pfn) -
+ zone->zone_start_pfn;
zone_span_writeunlock(zone);
}
@@ -102,8 +106,8 @@ static void grow_pgdat_span(struct pglist_data *pgdat,
if (start_pfn < pgdat->node_start_pfn)
pgdat->node_start_pfn = start_pfn;
- if (end_pfn > old_pgdat_end_pfn)
- pgdat->node_spanned_pages = end_pfn - pgdat->node_start_pfn;
+ pgdat->node_spanned_pages = max(old_pgdat_end_pfn, end_pfn) -
+ pgdat->node_start_pfn;
}
int online_pages(unsigned long pfn, unsigned long nr_pages)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 4f71cfd29c6..8778f58880c 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -912,7 +912,7 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
/*
* Check if this process has the right to modify the specified
* process. The right exists if the process has administrative
- * capabilities, superuser priviledges or the same
+ * capabilities, superuser privileges or the same
* userid as the target process.
*/
if ((current->euid != task->suid) && (current->euid != task->uid) &&
@@ -1761,7 +1761,6 @@ static void gather_stats(struct page *page, void *private, int pte_dirty)
md->mapcount_max = count;
md->node[page_to_nid(page)]++;
- cond_resched();
}
#ifdef CONFIG_HUGETLB_PAGE
diff --git a/mm/migrate.c b/mm/migrate.c
index 09f6e4aa87f..1c25040693d 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -16,8 +16,7 @@
#include <linux/module.h>
#include <linux/swap.h>
#include <linux/pagemap.h>
-#include <linux/buffer_head.h> /* for try_to_release_page(),
- buffer_heads_over_limit */
+#include <linux/buffer_head.h>
#include <linux/mm_inline.h>
#include <linux/pagevec.h>
#include <linux/rmap.h>
@@ -28,8 +27,6 @@
#include "internal.h"
-#include "internal.h"
-
/* The maximum number of pages to take off the LRU for migration */
#define MIGRATE_CHUNK_SIZE 256
@@ -176,7 +173,6 @@ unlock_retry:
retry:
return -EAGAIN;
}
-EXPORT_SYMBOL(swap_page);
/*
* Remove references for a page and establish the new page with the correct
@@ -234,7 +230,7 @@ int migrate_page_remove_references(struct page *newpage,
if (!page_mapping(page) || page_count(page) != nr_refs ||
*radix_pointer != page) {
write_unlock_irq(&mapping->tree_lock);
- return 1;
+ return -EAGAIN;
}
/*
@@ -443,6 +439,17 @@ redo:
goto unlock_both;
}
+ /* Make sure the dirty bit is up to date */
+ if (try_to_unmap(page, 1) == SWAP_FAIL) {
+ rc = -EPERM;
+ goto unlock_both;
+ }
+
+ if (page_mapcount(page)) {
+ rc = -EAGAIN;
+ goto unlock_both;
+ }
+
/*
* Default handling if a filesystem does not provide
* a migration function. We can only migrate clean
diff --git a/mm/mmap.c b/mm/mmap.c
index 4f5b5709136..e6ee12344b1 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -121,14 +121,26 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
* only call if we're about to fail.
*/
n = nr_free_pages();
+
+ /*
+ * Leave reserved pages. The pages are not for anonymous pages.
+ */
+ if (n <= totalreserve_pages)
+ goto error;
+ else
+ n -= totalreserve_pages;
+
+ /*
+ * Leave the last 3% for root
+ */
if (!cap_sys_admin)
n -= n / 32;
free += n;
if (free > pages)
return 0;
- vm_unacct_memory(pages);
- return -ENOMEM;
+
+ goto error;
}
allowed = (totalram_pages - hugetlb_total_pages())
@@ -150,7 +162,7 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
*/
if (atomic_read(&vm_committed_space) < (long)allowed)
return 0;
-
+error:
vm_unacct_memory(pages);
return -ENOMEM;
@@ -220,6 +232,17 @@ asmlinkage unsigned long sys_brk(unsigned long brk)
if (brk < mm->end_code)
goto out;
+
+ /*
+ * Check against rlimit here. If this check is done later after the test
+ * of oldbrk with newbrk then it can escape the test and let the data
+ * segment grow beyond its set limit the in case where the limit is
+ * not page aligned -Ram Gupta
+ */
+ rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+ if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
+ goto out;
+
newbrk = PAGE_ALIGN(brk);
oldbrk = PAGE_ALIGN(mm->brk);
if (oldbrk == newbrk)
@@ -232,11 +255,6 @@ asmlinkage unsigned long sys_brk(unsigned long brk)
goto out;
}
- /* Check against rlimit.. */
- rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
- if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
- goto out;
-
/* Check against existing mmap mappings. */
if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
goto out;
@@ -294,8 +312,7 @@ void validate_mm(struct mm_struct *mm)
i = browse_rb(&mm->mm_rb);
if (i != mm->map_count)
printk("map_count %d rb %d\n", mm->map_count, i), bug = 1;
- if (bug)
- BUG();
+ BUG_ON(bug);
}
#else
#define validate_mm(mm) do { } while (0)
@@ -432,8 +449,7 @@ __insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
struct rb_node ** rb_link, * rb_parent;
__vma = find_vma_prepare(mm, vma->vm_start,&prev, &rb_link, &rb_parent);
- if (__vma && __vma->vm_start < vma->vm_end)
- BUG();
+ BUG_ON(__vma && __vma->vm_start < vma->vm_end);
__vma_link(mm, vma, prev, rb_link, rb_parent);
mm->map_count++;
}
@@ -813,8 +829,7 @@ try_prev:
* (e.g. stash info in next's anon_vma_node when assigning
* an anon_vma, or when trying vma_merge). Another time.
*/
- if (find_vma_prev(vma->vm_mm, vma->vm_start, &near) != vma)
- BUG();
+ BUG_ON(find_vma_prev(vma->vm_mm, vma->vm_start, &near) != vma);
if (!near)
goto none;
diff --git a/mm/mmzone.c b/mm/mmzone.c
new file mode 100644
index 00000000000..b022370e612
--- /dev/null
+++ b/mm/mmzone.c
@@ -0,0 +1,50 @@
+/*
+ * linux/mm/mmzone.c
+ *
+ * management codes for pgdats and zones.
+ */
+
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/mmzone.h>
+#include <linux/module.h>
+
+struct pglist_data *first_online_pgdat(void)
+{
+ return NODE_DATA(first_online_node);
+}
+
+EXPORT_SYMBOL(first_online_pgdat);
+
+struct pglist_data *next_online_pgdat(struct pglist_data *pgdat)
+{
+ int nid = next_online_node(pgdat->node_id);
+
+ if (nid == MAX_NUMNODES)
+ return NULL;
+ return NODE_DATA(nid);
+}
+EXPORT_SYMBOL(next_online_pgdat);
+
+
+/*
+ * next_zone - helper magic for for_each_zone()
+ */
+struct zone *next_zone(struct zone *zone)
+{
+ pg_data_t *pgdat = zone->zone_pgdat;
+
+ if (zone < pgdat->node_zones + MAX_NR_ZONES - 1)
+ zone++;
+ else {
+ pgdat = next_online_pgdat(pgdat);
+ if (pgdat)
+ zone = pgdat->node_zones;
+ else
+ zone = NULL;
+ }
+ return zone;
+}
+EXPORT_SYMBOL(next_zone);
+
diff --git a/mm/nommu.c b/mm/nommu.c
index db45efac17c..029fadac0fb 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1147,14 +1147,26 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
* only call if we're about to fail.
*/
n = nr_free_pages();
+
+ /*
+ * Leave reserved pages. The pages are not for anonymous pages.
+ */
+ if (n <= totalreserve_pages)
+ goto error;
+ else
+ n -= totalreserve_pages;
+
+ /*
+ * Leave the last 3% for root
+ */
if (!cap_sys_admin)
n -= n / 32;
free += n;
if (free > pages)
return 0;
- vm_unacct_memory(pages);
- return -ENOMEM;
+
+ goto error;
}
allowed = totalram_pages * sysctl_overcommit_ratio / 100;
@@ -1175,7 +1187,7 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
*/
if (atomic_read(&vm_committed_space) < (long)allowed)
return 0;
-
+error:
vm_unacct_memory(pages);
return -ENOMEM;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 78747afad6b..042e6436c3e 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -46,15 +46,25 @@
unsigned long badness(struct task_struct *p, unsigned long uptime)
{
unsigned long points, cpu_time, run_time, s;
- struct list_head *tsk;
+ struct mm_struct *mm;
+ struct task_struct *child;
- if (!p->mm)
+ task_lock(p);
+ mm = p->mm;
+ if (!mm) {
+ task_unlock(p);
return 0;
+ }
/*
* The memory size of the process is the basis for the badness.
*/
- points = p->mm->total_vm;
+ points = mm->total_vm;
+
+ /*
+ * After this unlock we can no longer dereference local variable `mm'
+ */
+ task_unlock(p);
/*
* Processes which fork a lot of child processes are likely
@@ -64,11 +74,11 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
* child is eating the vast majority of memory, adding only half
* to the parents will make the child our kill candidate of choice.
*/
- list_for_each(tsk, &p->children) {
- struct task_struct *chld;
- chld = list_entry(tsk, struct task_struct, sibling);
- if (chld->mm != p->mm && chld->mm)
- points += chld->mm->total_vm/2 + 1;
+ list_for_each_entry(child, &p->children, sibling) {
+ task_lock(child);
+ if (child->mm != mm && child->mm)
+ points += child->mm->total_vm/2 + 1;
+ task_unlock(child);
}
/*
@@ -244,17 +254,24 @@ static void __oom_kill_task(task_t *p, const char *message)
force_sig(SIGKILL, p);
}
-static struct mm_struct *oom_kill_task(task_t *p, const char *message)
+static int oom_kill_task(task_t *p, const char *message)
{
- struct mm_struct *mm = get_task_mm(p);
+ struct mm_struct *mm;
task_t * g, * q;
- if (!mm)
- return NULL;
- if (mm == &init_mm) {
- mmput(mm);
- return NULL;
- }
+ mm = p->mm;
+
+ /* WARNING: mm may not be dereferenced since we did not obtain its
+ * value from get_task_mm(p). This is OK since all we need to do is
+ * compare mm to q->mm below.
+ *
+ * Furthermore, even if mm contains a non-NULL value, p->mm may
+ * change to NULL at any time since we do not hold task_lock(p).
+ * However, this is of no concern to us.
+ */
+
+ if (mm == NULL || mm == &init_mm)
+ return 1;
__oom_kill_task(p, message);
/*
@@ -266,13 +283,12 @@ static struct mm_struct *oom_kill_task(task_t *p, const char *message)
__oom_kill_task(q, message);
while_each_thread(g, q);
- return mm;
+ return 0;
}
-static struct mm_struct *oom_kill_process(struct task_struct *p,
- unsigned long points, const char *message)
+static int oom_kill_process(struct task_struct *p, unsigned long points,
+ const char *message)
{
- struct mm_struct *mm;
struct task_struct *c;
struct list_head *tsk;
@@ -283,9 +299,8 @@ static struct mm_struct *oom_kill_process(struct task_struct *p,
c = list_entry(tsk, struct task_struct, sibling);
if (c->mm == p->mm)
continue;
- mm = oom_kill_task(c, message);
- if (mm)
- return mm;
+ if (!oom_kill_task(c, message))
+ return 0;
}
return oom_kill_task(p, message);
}
@@ -300,7 +315,6 @@ static struct mm_struct *oom_kill_process(struct task_struct *p,
*/
void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
{
- struct mm_struct *mm = NULL;
task_t *p;
unsigned long points = 0;
@@ -320,12 +334,12 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
*/
switch (constrained_alloc(zonelist, gfp_mask)) {
case CONSTRAINT_MEMORY_POLICY:
- mm = oom_kill_process(current, points,
+ oom_kill_process(current, points,
"No available memory (MPOL_BIND)");
break;
case CONSTRAINT_CPUSET:
- mm = oom_kill_process(current, points,
+ oom_kill_process(current, points,
"No available memory in cpuset");
break;
@@ -347,8 +361,7 @@ retry:
panic("Out of memory and no killable processes...\n");
}
- mm = oom_kill_process(p, points, "Out of memory");
- if (!mm)
+ if (oom_kill_process(p, points, "Out of memory"))
goto retry;
break;
@@ -357,8 +370,6 @@ retry:
out:
read_unlock(&tasklist_lock);
cpuset_unlock();
- if (mm)
- mmput(mm);
/*
* Give "p" a good chance of killing itself before we
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 893d7677579..75d7f48b79b 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -72,13 +72,12 @@ int dirty_background_ratio = 10;
int vm_dirty_ratio = 40;
/*
- * The interval between `kupdate'-style writebacks, in centiseconds
- * (hundredths of a second)
+ * The interval between `kupdate'-style writebacks, in jiffies
*/
int dirty_writeback_interval = 5 * HZ;
/*
- * The longest number of centiseconds for which data is allowed to remain dirty
+ * The longest number of jiffies for which data is allowed to remain dirty
*/
int dirty_expire_interval = 30 * HZ;
@@ -258,7 +257,7 @@ static void balance_dirty_pages(struct address_space *mapping)
/**
* balance_dirty_pages_ratelimited_nr - balance dirty memory state
* @mapping: address_space which was dirtied
- * @nr_pages: number of pages which the caller has just dirtied
+ * @nr_pages_dirtied: number of pages which the caller has just dirtied
*
* Processes which are dirtying memory should call in here once for each page
* which was newly dirtied. The function will periodically check the system's
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 338a02bb004..253a450c400 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -39,6 +39,7 @@
#include <linux/mempolicy.h>
#include <asm/tlbflush.h>
+#include <asm/div64.h>
#include "internal.h"
/*
@@ -49,9 +50,9 @@ nodemask_t node_online_map __read_mostly = { { [0] = 1UL } };
EXPORT_SYMBOL(node_online_map);
nodemask_t node_possible_map __read_mostly = NODE_MASK_ALL;
EXPORT_SYMBOL(node_possible_map);
-struct pglist_data *pgdat_list __read_mostly;
unsigned long totalram_pages __read_mostly;
unsigned long totalhigh_pages __read_mostly;
+unsigned long totalreserve_pages __read_mostly;
long nr_swap_pages;
int percpu_pagelist_fraction;
@@ -152,7 +153,8 @@ static void bad_page(struct page *page)
1 << PG_reclaim |
1 << PG_slab |
1 << PG_swapcache |
- 1 << PG_writeback );
+ 1 << PG_writeback |
+ 1 << PG_buddy );
set_page_count(page, 0);
reset_page_mapcount(page);
page->mapping = NULL;
@@ -231,18 +233,20 @@ static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags)
* zone->lock is already acquired when we use these.
* So, we don't need atomic page->flags operations here.
*/
-static inline unsigned long page_order(struct page *page) {
+static inline unsigned long page_order(struct page *page)
+{
return page_private(page);
}
-static inline void set_page_order(struct page *page, int order) {
+static inline void set_page_order(struct page *page, int order)
+{
set_page_private(page, order);
- __SetPagePrivate(page);
+ __SetPageBuddy(page);
}
static inline void rmv_page_order(struct page *page)
{
- __ClearPagePrivate(page);
+ __ClearPageBuddy(page);
set_page_private(page, 0);
}
@@ -281,11 +285,13 @@ __find_combined_index(unsigned long page_idx, unsigned int order)
* This function checks whether a page is free && is the buddy
* we can do coalesce a page and its buddy if
* (a) the buddy is not in a hole &&
- * (b) the buddy is free &&
- * (c) the buddy is on the buddy system &&
- * (d) a page and its buddy have the same order.
- * for recording page's order, we use page_private(page) and PG_private.
+ * (b) the buddy is in the buddy system &&
+ * (c) a page and its buddy have the same order.
*
+ * For recording whether a page is in the buddy system, we use PG_buddy.
+ * Setting, clearing, and testing PG_buddy is serialized by zone->lock.
+ *
+ * For recording page's order, we use page_private(page).
*/
static inline int page_is_buddy(struct page *page, int order)
{
@@ -294,11 +300,11 @@ static inline int page_is_buddy(struct page *page, int order)
return 0;
#endif
- if (PagePrivate(page) &&
- (page_order(page) == order) &&
- page_count(page) == 0)
- return 1;
- return 0;
+ if (PageBuddy(page) && page_order(page) == order) {
+ BUG_ON(page_count(page) != 0);
+ return 1;
+ }
+ return 0;
}
/*
@@ -314,7 +320,7 @@ static inline int page_is_buddy(struct page *page, int order)
* as necessary, plus some accounting needed to play nicely with other
* parts of the VM system.
* At each level, we keep a list of pages, which are heads of continuous
- * free pages of length of (1 << order) and marked with PG_Private.Page's
+ * free pages of length of (1 << order) and marked with PG_buddy. Page's
* order is recorded in page_private(page) field.
* So when we are allocating or freeing one, we can derive the state of the
* other. That is, if we allocate a small block, and both were
@@ -377,7 +383,8 @@ static inline int free_pages_check(struct page *page)
1 << PG_slab |
1 << PG_swapcache |
1 << PG_writeback |
- 1 << PG_reserved ))))
+ 1 << PG_reserved |
+ 1 << PG_buddy ))))
bad_page(page);
if (PageDirty(page))
__ClearPageDirty(page);
@@ -525,7 +532,8 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
1 << PG_slab |
1 << PG_swapcache |
1 << PG_writeback |
- 1 << PG_reserved ))))
+ 1 << PG_reserved |
+ 1 << PG_buddy ))))
bad_page(page);
/*
@@ -943,7 +951,7 @@ restart:
goto got_pg;
do {
- if (cpuset_zone_allowed(*z, gfp_mask))
+ if (cpuset_zone_allowed(*z, gfp_mask|__GFP_HARDWALL))
wakeup_kswapd(*z, order);
} while (*(++z));
@@ -962,7 +970,8 @@ restart:
alloc_flags |= ALLOC_HARDER;
if (gfp_mask & __GFP_HIGH)
alloc_flags |= ALLOC_HIGH;
- alloc_flags |= ALLOC_CPUSET;
+ if (wait)
+ alloc_flags |= ALLOC_CPUSET;
/*
* Go through the zonelist again. Let __GFP_HIGH and allocations
@@ -1201,7 +1210,7 @@ unsigned int nr_free_highpages (void)
pg_data_t *pgdat;
unsigned int pages = 0;
- for_each_pgdat(pgdat)
+ for_each_online_pgdat(pgdat)
pages += pgdat->node_zones[ZONE_HIGHMEM].free_pages;
return pages;
@@ -1343,7 +1352,7 @@ void get_zone_counts(unsigned long *active,
*active = 0;
*inactive = 0;
*free = 0;
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
unsigned long l, m, n;
__get_zone_counts(&l, &m, &n, pgdat);
*active += l;
@@ -1955,7 +1964,7 @@ static inline void free_zone_pagesets(int cpu)
}
}
-static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb,
+static int pageset_cpuup_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
{
@@ -2042,7 +2051,6 @@ static __meminit void init_currently_empty_zone(struct zone *zone,
zone_wait_table_init(zone, size);
pgdat->nr_zones = zone_idx(zone) + 1;
- zone->zone_mem_map = pfn_to_page(zone_start_pfn);
zone->zone_start_pfn = zone_start_pfn;
memmap_init(size, pgdat->node_id, zone_idx(zone), zone_start_pfn);
@@ -2117,14 +2125,22 @@ static void __init alloc_node_mem_map(struct pglist_data *pgdat)
#ifdef CONFIG_FLAT_NODE_MEM_MAP
/* ia64 gets its own node_mem_map, before this, without bootmem */
if (!pgdat->node_mem_map) {
- unsigned long size;
+ unsigned long size, start, end;
struct page *map;
- size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
+ /*
+ * The zone's endpoints aren't required to be MAX_ORDER
+ * aligned but the node_mem_map endpoints must be in order
+ * for the buddy allocator to function correctly.
+ */
+ start = pgdat->node_start_pfn & ~(MAX_ORDER_NR_PAGES - 1);
+ end = pgdat->node_start_pfn + pgdat->node_spanned_pages;
+ end = ALIGN(end, MAX_ORDER_NR_PAGES);
+ size = (end - start) * sizeof(struct page);
map = alloc_remap(pgdat->node_id, size);
if (!map)
map = alloc_bootmem_node(pgdat, size);
- pgdat->node_mem_map = map;
+ pgdat->node_mem_map = map + (pgdat->node_start_pfn - start);
}
#ifdef CONFIG_FLATMEM
/*
@@ -2170,8 +2186,9 @@ static void *frag_start(struct seq_file *m, loff_t *pos)
{
pg_data_t *pgdat;
loff_t node = *pos;
-
- for (pgdat = pgdat_list; pgdat && node; pgdat = pgdat->pgdat_next)
+ for (pgdat = first_online_pgdat();
+ pgdat && node;
+ pgdat = next_online_pgdat(pgdat))
--node;
return pgdat;
@@ -2182,7 +2199,7 @@ static void *frag_next(struct seq_file *m, void *arg, loff_t *pos)
pg_data_t *pgdat = (pg_data_t *)arg;
(*pos)++;
- return pgdat->pgdat_next;
+ return next_online_pgdat(pgdat);
}
static void frag_stop(struct seq_file *m, void *arg)
@@ -2473,6 +2490,38 @@ void __init page_alloc_init(void)
}
/*
+ * calculate_totalreserve_pages - called when sysctl_lower_zone_reserve_ratio
+ * or min_free_kbytes changes.
+ */
+static void calculate_totalreserve_pages(void)
+{
+ struct pglist_data *pgdat;
+ unsigned long reserve_pages = 0;
+ int i, j;
+
+ for_each_online_pgdat(pgdat) {
+ for (i = 0; i < MAX_NR_ZONES; i++) {
+ struct zone *zone = pgdat->node_zones + i;
+ unsigned long max = 0;
+
+ /* Find valid and maximum lowmem_reserve in the zone */
+ for (j = i; j < MAX_NR_ZONES; j++) {
+ if (zone->lowmem_reserve[j] > max)
+ max = zone->lowmem_reserve[j];
+ }
+
+ /* we treat pages_high as reserved pages. */
+ max += zone->pages_high;
+
+ if (max > zone->present_pages)
+ max = zone->present_pages;
+ reserve_pages += max;
+ }
+ }
+ totalreserve_pages = reserve_pages;
+}
+
+/*
* setup_per_zone_lowmem_reserve - called whenever
* sysctl_lower_zone_reserve_ratio changes. Ensures that each zone
* has a correct pages reserved value, so an adequate number of
@@ -2483,7 +2532,7 @@ static void setup_per_zone_lowmem_reserve(void)
struct pglist_data *pgdat;
int j, idx;
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
for (j = 0; j < MAX_NR_ZONES; j++) {
struct zone *zone = pgdat->node_zones + j;
unsigned long present_pages = zone->present_pages;
@@ -2503,6 +2552,9 @@ static void setup_per_zone_lowmem_reserve(void)
}
}
}
+
+ /* update totalreserve_pages */
+ calculate_totalreserve_pages();
}
/*
@@ -2524,9 +2576,11 @@ void setup_per_zone_pages_min(void)
}
for_each_zone(zone) {
- unsigned long tmp;
+ u64 tmp;
+
spin_lock_irqsave(&zone->lru_lock, flags);
- tmp = (pages_min * zone->present_pages) / lowmem_pages;
+ tmp = (u64)pages_min * zone->present_pages;
+ do_div(tmp, lowmem_pages);
if (is_highmem(zone)) {
/*
* __GFP_HIGH and PF_MEMALLOC allocations usually don't
@@ -2553,10 +2607,13 @@ void setup_per_zone_pages_min(void)
zone->pages_min = tmp;
}
- zone->pages_low = zone->pages_min + tmp / 4;
- zone->pages_high = zone->pages_min + tmp / 2;
+ zone->pages_low = zone->pages_min + (tmp >> 2);
+ zone->pages_high = zone->pages_min + (tmp >> 1);
spin_unlock_irqrestore(&zone->lru_lock, flags);
}
+
+ /* update totalreserve_pages */
+ calculate_totalreserve_pages();
}
/*
@@ -2745,3 +2802,44 @@ void *__init alloc_large_system_hash(const char *tablename,
return table;
}
+
+#ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE
+/*
+ * pfn <-> page translation. out-of-line version.
+ * (see asm-generic/memory_model.h)
+ */
+#if defined(CONFIG_FLATMEM)
+struct page *pfn_to_page(unsigned long pfn)
+{
+ return mem_map + (pfn - ARCH_PFN_OFFSET);
+}
+unsigned long page_to_pfn(struct page *page)
+{
+ return (page - mem_map) + ARCH_PFN_OFFSET;
+}
+#elif defined(CONFIG_DISCONTIGMEM)
+struct page *pfn_to_page(unsigned long pfn)
+{
+ int nid = arch_pfn_to_nid(pfn);
+ return NODE_DATA(nid)->node_mem_map + arch_local_page_offset(pfn,nid);
+}
+unsigned long page_to_pfn(struct page *page)
+{
+ struct pglist_data *pgdat = NODE_DATA(page_to_nid(page));
+ return (page - pgdat->node_mem_map) + pgdat->node_start_pfn;
+}
+#elif defined(CONFIG_SPARSEMEM)
+struct page *pfn_to_page(unsigned long pfn)
+{
+ return __section_mem_map_addr(__pfn_to_section(pfn)) + pfn;
+}
+
+unsigned long page_to_pfn(struct page *page)
+{
+ long section_id = page_to_section(page);
+ return page - __section_mem_map_addr(__nr_to_section(section_id));
+}
+#endif /* CONFIG_FLATMEM/DISCONTIGMME/SPARSEMEM */
+EXPORT_SYMBOL(pfn_to_page);
+EXPORT_SYMBOL(page_to_pfn);
+#endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
diff --git a/mm/shmem.c b/mm/shmem.c
index 37eaf42ed2c..1e43c8a865b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -46,6 +46,8 @@
#include <linux/mempolicy.h>
#include <linux/namei.h>
#include <linux/ctype.h>
+#include <linux/migrate.h>
+
#include <asm/uaccess.h>
#include <asm/div64.h>
#include <asm/pgtable.h>
@@ -1778,6 +1780,7 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
if (!simple_empty(dentry))
return -ENOTEMPTY;
+ dentry->d_inode->i_nlink--;
dir->i_nlink--;
return shmem_unlink(dir, dentry);
}
@@ -2100,6 +2103,7 @@ static int shmem_fill_super(struct super_block *sb,
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = TMPFS_MAGIC;
sb->s_op = &shmem_ops;
+ sb->s_time_gran = 1;
inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
if (!inode)
@@ -2173,6 +2177,7 @@ static struct address_space_operations shmem_aops = {
.prepare_write = shmem_prepare_write,
.commit_write = simple_commit_write,
#endif
+ .migratepage = migrate_page,
};
static struct file_operations shmem_file_operations = {
diff --git a/mm/slab.c b/mm/slab.c
index 681837499d7..f1b644eb39d 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -207,11 +207,6 @@ typedef unsigned int kmem_bufctl_t;
#define BUFCTL_ACTIVE (((kmem_bufctl_t)(~0U))-2)
#define SLAB_LIMIT (((kmem_bufctl_t)(~0U))-3)
-/* Max number of objs-per-slab for caches which use off-slab slabs.
- * Needed to avoid a possible looping condition in cache_grow().
- */
-static unsigned long offslab_limit;
-
/*
* struct slab
*
@@ -420,6 +415,7 @@ struct kmem_cache {
unsigned long max_freeable;
unsigned long node_allocs;
unsigned long node_frees;
+ unsigned long node_overflow;
atomic_t allochit;
atomic_t allocmiss;
atomic_t freehit;
@@ -465,6 +461,7 @@ struct kmem_cache {
#define STATS_INC_ERR(x) ((x)->errors++)
#define STATS_INC_NODEALLOCS(x) ((x)->node_allocs++)
#define STATS_INC_NODEFREES(x) ((x)->node_frees++)
+#define STATS_INC_ACOVERFLOW(x) ((x)->node_overflow++)
#define STATS_SET_FREEABLE(x, i) \
do { \
if ((x)->max_freeable < i) \
@@ -484,6 +481,7 @@ struct kmem_cache {
#define STATS_INC_ERR(x) do { } while (0)
#define STATS_INC_NODEALLOCS(x) do { } while (0)
#define STATS_INC_NODEFREES(x) do { } while (0)
+#define STATS_INC_ACOVERFLOW(x) do { } while (0)
#define STATS_SET_FREEABLE(x, i) do { } while (0)
#define STATS_INC_ALLOCHIT(x) do { } while (0)
#define STATS_INC_ALLOCMISS(x) do { } while (0)
@@ -697,6 +695,14 @@ static enum {
FULL
} g_cpucache_up;
+/*
+ * used by boot code to determine if it can use slab based allocator
+ */
+int slab_is_available(void)
+{
+ return g_cpucache_up == FULL;
+}
+
static DEFINE_PER_CPU(struct work_struct, reap_work);
static void free_block(struct kmem_cache *cachep, void **objpp, int len,
@@ -976,7 +982,8 @@ static void __drain_alien_cache(struct kmem_cache *cachep,
* That way we could avoid the overhead of putting the objects
* into the free lists and getting them back later.
*/
- transfer_objects(rl3->shared, ac, ac->limit);
+ if (rl3->shared)
+ transfer_objects(rl3->shared, ac, ac->limit);
free_block(cachep, ac->entry, ac->avail, node);
ac->avail = 0;
@@ -1033,7 +1040,7 @@ static inline void free_alien_cache(struct array_cache **ac_ptr)
#endif
-static int __devinit cpuup_callback(struct notifier_block *nfb,
+static int cpuup_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
long cpu = (long)hcpu;
@@ -1297,8 +1304,7 @@ void __init kmem_cache_init(void)
if (cache_cache.num)
break;
}
- if (!cache_cache.num)
- BUG();
+ BUG_ON(!cache_cache.num);
cache_cache.gfporder = order;
cache_cache.colour = left_over / cache_cache.colour_off;
cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) +
@@ -1345,12 +1351,6 @@ void __init kmem_cache_init(void)
NULL, NULL);
}
- /* Inc off-slab bufctl limit until the ceiling is hit. */
- if (!(OFF_SLAB(sizes->cs_cachep))) {
- offslab_limit = sizes->cs_size - sizeof(struct slab);
- offslab_limit /= sizeof(kmem_bufctl_t);
- }
-
sizes->cs_dmacachep = kmem_cache_create(names->name_dma,
sizes->cs_size,
ARCH_KMALLOC_MINALIGN,
@@ -1454,7 +1454,14 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
int i;
flags |= cachep->gfpflags;
+#ifndef CONFIG_MMU
+ /* nommu uses slab's for process anonymous memory allocations, so
+ * requires __GFP_COMP to properly refcount higher order allocations"
+ */
+ page = alloc_pages_node(nodeid, (flags | __GFP_COMP), cachep->gfporder);
+#else
page = alloc_pages_node(nodeid, flags, cachep->gfporder);
+#endif
if (!page)
return NULL;
addr = page_address(page);
@@ -1762,6 +1769,7 @@ static void set_up_list3s(struct kmem_cache *cachep, int index)
static size_t calculate_slab_order(struct kmem_cache *cachep,
size_t size, size_t align, unsigned long flags)
{
+ unsigned long offslab_limit;
size_t left_over = 0;
int gfporder;
@@ -1773,9 +1781,18 @@ static size_t calculate_slab_order(struct kmem_cache *cachep,
if (!num)
continue;
- /* More than offslab_limit objects will cause problems */
- if ((flags & CFLGS_OFF_SLAB) && num > offslab_limit)
- break;
+ if (flags & CFLGS_OFF_SLAB) {
+ /*
+ * Max number of objs-per-slab for caches which
+ * use off-slab slabs. Needed to avoid a possible
+ * looping condition in cache_grow().
+ */
+ offslab_limit = size - sizeof(struct slab);
+ offslab_limit /= sizeof(kmem_bufctl_t);
+
+ if (num > offslab_limit)
+ break;
+ }
/* Found something acceptable - save it away */
cachep->num = num;
@@ -1974,8 +1991,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
* Always checks flags, a caller might be expecting debug support which
* isn't available.
*/
- if (flags & ~CREATE_MASK)
- BUG();
+ BUG_ON(flags & ~CREATE_MASK);
/*
* Check that size is in terms of words. This is needed to avoid
@@ -2183,11 +2199,14 @@ static void drain_cpu_caches(struct kmem_cache *cachep)
check_irq_on();
for_each_online_node(node) {
l3 = cachep->nodelists[node];
- if (l3) {
+ if (l3 && l3->alien)
+ drain_alien_cache(cachep, l3->alien);
+ }
+
+ for_each_online_node(node) {
+ l3 = cachep->nodelists[node];
+ if (l3)
drain_array(cachep, l3, l3->shared, 1, node);
- if (l3->alien)
- drain_alien_cache(cachep, l3->alien);
- }
}
}
@@ -2206,8 +2225,7 @@ static int __node_shrink(struct kmem_cache *cachep, int node)
slabp = list_entry(l3->slabs_free.prev, struct slab, list);
#if DEBUG
- if (slabp->inuse)
- BUG();
+ BUG_ON(slabp->inuse);
#endif
list_del(&slabp->list);
@@ -2248,8 +2266,7 @@ static int __cache_shrink(struct kmem_cache *cachep)
*/
int kmem_cache_shrink(struct kmem_cache *cachep)
{
- if (!cachep || in_interrupt())
- BUG();
+ BUG_ON(!cachep || in_interrupt());
return __cache_shrink(cachep);
}
@@ -2277,8 +2294,7 @@ int kmem_cache_destroy(struct kmem_cache *cachep)
int i;
struct kmem_list3 *l3;
- if (!cachep || in_interrupt())
- BUG();
+ BUG_ON(!cachep || in_interrupt());
/* Don't let CPUs to come and go */
lock_cpu_hotplug();
@@ -2323,13 +2339,15 @@ EXPORT_SYMBOL(kmem_cache_destroy);
/* Get the memory for a slab management obj. */
static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
- int colour_off, gfp_t local_flags)
+ int colour_off, gfp_t local_flags,
+ int nodeid)
{
struct slab *slabp;
if (OFF_SLAB(cachep)) {
/* Slab management obj is off-slab. */
- slabp = kmem_cache_alloc(cachep->slabp_cache, local_flags);
+ slabp = kmem_cache_alloc_node(cachep->slabp_cache,
+ local_flags, nodeid);
if (!slabp)
return NULL;
} else {
@@ -2339,6 +2357,7 @@ static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
slabp->inuse = 0;
slabp->colouroff = colour_off;
slabp->s_mem = objp + colour_off;
+ slabp->nodeid = nodeid;
return slabp;
}
@@ -2477,8 +2496,7 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
* Be lazy and only check for valid flags here, keeping it out of the
* critical path in kmem_cache_alloc().
*/
- if (flags & ~(SLAB_DMA | SLAB_LEVEL_MASK | SLAB_NO_GROW))
- BUG();
+ BUG_ON(flags & ~(SLAB_DMA | SLAB_LEVEL_MASK | SLAB_NO_GROW));
if (flags & SLAB_NO_GROW)
return 0;
@@ -2525,7 +2543,7 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
goto failed;
/* Get slab management. */
- slabp = alloc_slabmgmt(cachep, objp, offset, local_flags);
+ slabp = alloc_slabmgmt(cachep, objp, offset, local_flags, nodeid);
if (!slabp)
goto opps1;
@@ -3086,9 +3104,11 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp)
if (l3->alien && l3->alien[nodeid]) {
alien = l3->alien[nodeid];
spin_lock(&alien->lock);
- if (unlikely(alien->avail == alien->limit))
+ if (unlikely(alien->avail == alien->limit)) {
+ STATS_INC_ACOVERFLOW(cachep);
__drain_alien_cache(cachep,
alien, nodeid);
+ }
alien->entry[alien->avail++] = objp;
spin_unlock(&alien->lock);
} else {
@@ -3311,7 +3331,7 @@ void *__alloc_percpu(size_t size)
* and we have no way of figuring out how to fix the array
* that we have allocated then....
*/
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
int node = cpu_to_node(i);
if (node_online(node))
@@ -3398,7 +3418,7 @@ void free_percpu(const void *objp)
/*
* We allocate for all cpus so we cannot use for online cpu here.
*/
- for_each_cpu(i)
+ for_each_possible_cpu(i)
kfree(p->ptrs[i]);
kfree(p);
}
@@ -3766,7 +3786,7 @@ static void print_slabinfo_header(struct seq_file *m)
seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
#if STATS
seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> "
- "<error> <maxfreeable> <nodeallocs> <remotefrees>");
+ "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>");
seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
#endif
seq_putc(m, '\n');
@@ -3880,11 +3900,12 @@ static int s_show(struct seq_file *m, void *p)
unsigned long max_freeable = cachep->max_freeable;
unsigned long node_allocs = cachep->node_allocs;
unsigned long node_frees = cachep->node_frees;
+ unsigned long overflows = cachep->node_overflow;
seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu \
- %4lu %4lu %4lu %4lu", allocs, high, grown,
+ %4lu %4lu %4lu %4lu %4lu", allocs, high, grown,
reaped, errors, max_freeable, node_allocs,
- node_frees);
+ node_frees, overflows);
}
/* cpu stats */
{
diff --git a/mm/slob.c b/mm/slob.c
index 9bcc7e2cabf..a68255ba455 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -354,9 +354,7 @@ void *__alloc_percpu(size_t size)
if (!pdata)
return NULL;
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_possible(i))
- continue;
+ for_each_possible_cpu(i) {
pdata->ptrs[i] = kmalloc(size, GFP_KERNEL);
if (!pdata->ptrs[i])
goto unwind_oom;
@@ -383,11 +381,9 @@ free_percpu(const void *objp)
int i;
struct percpu_data *p = (struct percpu_data *) (~(unsigned long) objp);
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_possible(i))
- continue;
+ for_each_possible_cpu(i)
kfree(p->ptrs[i]);
- }
+
kfree(p);
}
EXPORT_SYMBOL(free_percpu);
diff --git a/mm/sparse.c b/mm/sparse.c
index 0a51f36ba3a..100040c0dfb 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -32,7 +32,10 @@ static struct mem_section *sparse_index_alloc(int nid)
unsigned long array_size = SECTIONS_PER_ROOT *
sizeof(struct mem_section);
- section = alloc_bootmem_node(NODE_DATA(nid), array_size);
+ if (slab_is_available())
+ section = kmalloc_node(array_size, GFP_KERNEL, nid);
+ else
+ section = alloc_bootmem_node(NODE_DATA(nid), array_size);
if (section)
memset(section, 0, array_size);
@@ -84,11 +87,8 @@ int __section_nr(struct mem_section* ms)
unsigned long root_nr;
struct mem_section* root;
- for (root_nr = 0;
- root_nr < NR_MEM_SECTIONS;
- root_nr += SECTIONS_PER_ROOT) {
- root = __nr_to_section(root_nr);
-
+ for (root_nr = 0; root_nr < NR_SECTION_ROOTS; root_nr++) {
+ root = __nr_to_section(root_nr * SECTIONS_PER_ROOT);
if (!root)
continue;
@@ -281,9 +281,9 @@ int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
ret = sparse_init_one_section(ms, section_nr, memmap);
- if (ret <= 0)
- __kfree_section_memmap(memmap, nr_pages);
out:
pgdat_resize_unlock(pgdat, &flags);
+ if (ret <= 0)
+ __kfree_section_memmap(memmap, nr_pages);
return ret;
}
diff --git a/mm/swap.c b/mm/swap.c
index 91b7e2026f6..88895c249bc 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -512,7 +512,7 @@ long percpu_counter_sum(struct percpu_counter *fbc)
spin_lock(&fbc->lock);
ret = fbc->count;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
long *pcount = per_cpu_ptr(fbc->counters, cpu);
ret += *pcount;
}
diff --git a/mm/swap_state.c b/mm/swap_state.c
index d7af296833f..e0e1583f32c 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -148,8 +148,7 @@ int add_to_swap(struct page * page, gfp_t gfp_mask)
swp_entry_t entry;
int err;
- if (!PageLocked(page))
- BUG();
+ BUG_ON(!PageLocked(page));
for (;;) {
entry = get_swap_page();
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 39aa9d12961..e5fd5385f0c 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -397,18 +397,24 @@ void free_swap_and_cache(swp_entry_t entry)
p = swap_info_get(entry);
if (p) {
- if (swap_entry_free(p, swp_offset(entry)) == 1)
- page = find_trylock_page(&swapper_space, entry.val);
+ if (swap_entry_free(p, swp_offset(entry)) == 1) {
+ page = find_get_page(&swapper_space, entry.val);
+ if (page && unlikely(TestSetPageLocked(page))) {
+ page_cache_release(page);
+ page = NULL;
+ }
+ }
spin_unlock(&swap_lock);
}
if (page) {
int one_user;
BUG_ON(PagePrivate(page));
- page_cache_get(page);
one_user = (page_count(page) == 2);
/* Only cache user (+us), or swap space full? Free it! */
- if (!PageWriteback(page) && (one_user || vm_swap_full())) {
+ /* Also recheck PageSwapCache after page is locked (above) */
+ if (PageSwapCache(page) && !PageWriteback(page) &&
+ (one_user || vm_swap_full())) {
delete_from_swap_cache(page);
SetPageDirty(page);
}
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 729eb3eec75..c0504f1e34e 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -321,8 +321,7 @@ void __vunmap(void *addr, int deallocate_pages)
int i;
for (i = 0; i < area->nr_pages; i++) {
- if (unlikely(!area->pages[i]))
- BUG();
+ BUG_ON(!area->pages[i]);
__free_page(area->pages[i]);
}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 78865c849f8..440a733fe2e 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1061,7 +1061,7 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, unsigned long nr_pages,
loop_again:
total_scanned = 0;
nr_reclaimed = 0;
- sc.may_writepage = !laptop_mode,
+ sc.may_writepage = !laptop_mode;
sc.nr_mapped = read_page_state(nr_mapped);
inc_page_state(pageoutrun);
@@ -1305,7 +1305,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
current->reclaim_state = &reclaim_state;
repeat:
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
unsigned long freed;
freed = balance_pgdat(pgdat, nr_to_free, 0);
@@ -1328,14 +1328,14 @@ repeat:
not required for correctness. So if the last cpu in a node goes
away, we get changed to run anywhere: as the first one comes back,
restore their cpu bindings. */
-static int __devinit cpu_callback(struct notifier_block *nfb,
+static int cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
pg_data_t *pgdat;
cpumask_t mask;
if (action == CPU_ONLINE) {
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
mask = node_to_cpumask(pgdat->node_id);
if (any_online_cpu(mask) != NR_CPUS)
/* One of our CPUs online: restore mask */
@@ -1351,7 +1351,7 @@ static int __init kswapd_init(void)
pg_data_t *pgdat;
swap_setup();
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
pid_t pid;
pid = kernel_thread(kswapd, pgdat, CLONE_KERNEL);
diff --git a/net/802/tr.c b/net/802/tr.c
index afd8385c0c9..e9dc803f2fe 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -643,6 +643,5 @@ static int __init rif_init(void)
module_init(rif_init);
-EXPORT_SYMBOL(tr_source_route);
EXPORT_SYMBOL(tr_type_trans);
EXPORT_SYMBOL(alloc_trdev);
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 697ac55e29d..7b1eb9a4fc9 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1819,6 +1819,22 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return rc;
}
+
+#ifdef CONFIG_COMPAT
+static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ /*
+ * All Appletalk ioctls except SIOCATALKDIFADDR are standard. And
+ * SIOCATALKDIFADDR is handled by upper layer as well, so there is
+ * nothing to do. Eventually SIOCATALKDIFADDR should be moved
+ * here so there is no generic SIOCPROTOPRIVATE translation in the
+ * system.
+ */
+ return -ENOIOCTLCMD;
+}
+#endif
+
+
static struct net_proto_family atalk_family_ops = {
.family = PF_APPLETALK,
.create = atalk_create,
@@ -1836,6 +1852,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
.getname = atalk_getname,
.poll = datagram_poll,
.ioctl = atalk_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = atalk_compat_ioctl,
+#endif
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt,
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 3ab4e7947ba..72d85298266 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -2,7 +2,6 @@
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
-
#include <linux/config.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -54,24 +53,24 @@ static struct net_device *clip_devs;
static struct atm_vcc *atmarpd;
static struct neigh_table clip_tbl;
static struct timer_list idle_timer;
-static int start_timer = 1;
-
-static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip)
+static int to_atmarpd(enum atmarp_ctrl_type type, int itf, unsigned long ip)
{
struct sock *sk;
struct atmarp_ctrl *ctrl;
struct sk_buff *skb;
- DPRINTK("to_atmarpd(%d)\n",type);
- if (!atmarpd) return -EUNATCH;
+ DPRINTK("to_atmarpd(%d)\n", type);
+ if (!atmarpd)
+ return -EUNATCH;
skb = alloc_skb(sizeof(struct atmarp_ctrl),GFP_ATOMIC);
- if (!skb) return -ENOMEM;
+ if (!skb)
+ return -ENOMEM;
ctrl = (struct atmarp_ctrl *) skb_put(skb,sizeof(struct atmarp_ctrl));
ctrl->type = type;
ctrl->itf_num = itf;
ctrl->ip = ip;
- atm_force_charge(atmarpd,skb->truesize);
+ atm_force_charge(atmarpd, skb->truesize);
sk = sk_atm(atmarpd);
skb_queue_tail(&sk->sk_receive_queue, skb);
@@ -79,26 +78,24 @@ static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip)
return 0;
}
-
-static void link_vcc(struct clip_vcc *clip_vcc,struct atmarp_entry *entry)
+static void link_vcc(struct clip_vcc *clip_vcc, struct atmarp_entry *entry)
{
- DPRINTK("link_vcc %p to entry %p (neigh %p)\n",clip_vcc,entry,
- entry->neigh);
+ DPRINTK("link_vcc %p to entry %p (neigh %p)\n", clip_vcc, entry,
+ entry->neigh);
clip_vcc->entry = entry;
- clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */
+ clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */
clip_vcc->next = entry->vccs;
entry->vccs = clip_vcc;
entry->neigh->used = jiffies;
}
-
static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
{
struct atmarp_entry *entry = clip_vcc->entry;
struct clip_vcc **walk;
if (!entry) {
- printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n",clip_vcc);
+ printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
return;
}
spin_lock_bh(&entry->neigh->dev->xmit_lock); /* block clip_start_xmit() */
@@ -107,24 +104,24 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
if (*walk == clip_vcc) {
int error;
- *walk = clip_vcc->next; /* atomic */
+ *walk = clip_vcc->next; /* atomic */
clip_vcc->entry = NULL;
if (clip_vcc->xoff)
netif_wake_queue(entry->neigh->dev);
if (entry->vccs)
goto out;
- entry->expires = jiffies-1;
- /* force resolution or expiration */
+ entry->expires = jiffies - 1;
+ /* force resolution or expiration */
error = neigh_update(entry->neigh, NULL, NUD_NONE,
NEIGH_UPDATE_F_ADMIN);
if (error)
printk(KERN_CRIT "unlink_clip_vcc: "
- "neigh_update failed with %d\n",error);
+ "neigh_update failed with %d\n", error);
goto out;
}
printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
- "0x%p)\n",entry,clip_vcc);
-out:
+ "0x%p)\n", entry, clip_vcc);
+ out:
spin_unlock_bh(&entry->neigh->dev->xmit_lock);
}
@@ -153,13 +150,13 @@ static int neigh_check_cb(struct neighbour *n)
DPRINTK("destruction postponed with ref %d\n",
atomic_read(&n->refcnt));
- while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
+ while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
dev_kfree_skb(skb);
return 0;
}
- DPRINTK("expired neigh %p\n",n);
+ DPRINTK("expired neigh %p\n", n);
return 1;
}
@@ -167,7 +164,7 @@ static void idle_timer_check(unsigned long dummy)
{
write_lock(&clip_tbl.lock);
__neigh_for_each_release(&clip_tbl, neigh_check_cb);
- mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ);
+ mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ);
write_unlock(&clip_tbl.lock);
}
@@ -177,13 +174,13 @@ static int clip_arp_rcv(struct sk_buff *skb)
DPRINTK("clip_arp_rcv\n");
vcc = ATM_SKB(skb)->vcc;
- if (!vcc || !atm_charge(vcc,skb->truesize)) {
+ if (!vcc || !atm_charge(vcc, skb->truesize)) {
dev_kfree_skb_any(skb);
return 0;
}
- DPRINTK("pushing to %p\n",vcc);
- DPRINTK("using %p\n",CLIP_VCC(vcc)->old_push);
- CLIP_VCC(vcc)->old_push(vcc,skb);
+ DPRINTK("pushing to %p\n", vcc);
+ DPRINTK("using %p\n", CLIP_VCC(vcc)->old_push);
+ CLIP_VCC(vcc)->old_push(vcc, skb);
return 0;
}
@@ -193,34 +190,38 @@ static const unsigned char llc_oui[] = {
0x03, /* Ctrl: Unnumbered Information Command PDU */
0x00, /* OUI: EtherType */
0x00,
- 0x00 };
+ 0x00
+};
-static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
+static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb)
{
struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
DPRINTK("clip push\n");
if (!skb) {
- DPRINTK("removing VCC %p\n",clip_vcc);
- if (clip_vcc->entry) unlink_clip_vcc(clip_vcc);
- clip_vcc->old_push(vcc,NULL); /* pass on the bad news */
+ DPRINTK("removing VCC %p\n", clip_vcc);
+ if (clip_vcc->entry)
+ unlink_clip_vcc(clip_vcc);
+ clip_vcc->old_push(vcc, NULL); /* pass on the bad news */
kfree(clip_vcc);
return;
}
- atm_return(vcc,skb->truesize);
+ atm_return(vcc, skb->truesize);
skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
- /* clip_vcc->entry == NULL if we don't have an IP address yet */
+ /* clip_vcc->entry == NULL if we don't have an IP address yet */
if (!skb->dev) {
dev_kfree_skb_any(skb);
return;
}
ATM_SKB(skb)->vcc = vcc;
skb->mac.raw = skb->data;
- if (!clip_vcc->encap || skb->len < RFC1483LLC_LEN || memcmp(skb->data,
- llc_oui,sizeof(llc_oui))) skb->protocol = htons(ETH_P_IP);
+ if (!clip_vcc->encap
+ || skb->len < RFC1483LLC_LEN
+ || memcmp(skb->data, llc_oui, sizeof (llc_oui)))
+ skb->protocol = htons(ETH_P_IP);
else {
skb->protocol = ((u16 *) skb->data)[3];
- skb_pull(skb,RFC1483LLC_LEN);
+ skb_pull(skb, RFC1483LLC_LEN);
if (skb->protocol == htons(ETH_P_ARP)) {
PRIV(skb->dev)->stats.rx_packets++;
PRIV(skb->dev)->stats.rx_bytes += skb->len;
@@ -235,58 +236,54 @@ static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
netif_rx(skb);
}
-
/*
* Note: these spinlocks _must_not_ block on non-SMP. The only goal is that
* clip_pop is atomic with respect to the critical section in clip_start_xmit.
*/
-
-static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb)
+static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb)
{
struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
struct net_device *dev = skb->dev;
int old;
unsigned long flags;
- DPRINTK("clip_pop(vcc %p)\n",vcc);
- clip_vcc->old_pop(vcc,skb);
+ DPRINTK("clip_pop(vcc %p)\n", vcc);
+ clip_vcc->old_pop(vcc, skb);
/* skb->dev == NULL in outbound ARP packets */
- if (!dev) return;
- spin_lock_irqsave(&PRIV(dev)->xoff_lock,flags);
- if (atm_may_send(vcc,0)) {
- old = xchg(&clip_vcc->xoff,0);
- if (old) netif_wake_queue(dev);
+ if (!dev)
+ return;
+ spin_lock_irqsave(&PRIV(dev)->xoff_lock, flags);
+ if (atm_may_send(vcc, 0)) {
+ old = xchg(&clip_vcc->xoff, 0);
+ if (old)
+ netif_wake_queue(dev);
}
- spin_unlock_irqrestore(&PRIV(dev)->xoff_lock,flags);
+ spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags);
}
-
static void clip_neigh_destroy(struct neighbour *neigh)
{
- DPRINTK("clip_neigh_destroy (neigh %p)\n",neigh);
+ DPRINTK("clip_neigh_destroy (neigh %p)\n", neigh);
if (NEIGH2ENTRY(neigh)->vccs)
printk(KERN_CRIT "clip_neigh_destroy: vccs != NULL !!!\n");
NEIGH2ENTRY(neigh)->vccs = (void *) 0xdeadbeef;
}
-
-static void clip_neigh_solicit(struct neighbour *neigh,struct sk_buff *skb)
+static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb)
{
- DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n",neigh,skb);
- to_atmarpd(act_need,PRIV(neigh->dev)->number,NEIGH2ENTRY(neigh)->ip);
+ DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb);
+ to_atmarpd(act_need, PRIV(neigh->dev)->number, NEIGH2ENTRY(neigh)->ip);
}
-
-static void clip_neigh_error(struct neighbour *neigh,struct sk_buff *skb)
+static void clip_neigh_error(struct neighbour *neigh, struct sk_buff *skb)
{
#ifndef CONFIG_ATM_CLIP_NO_ICMP
- icmp_send(skb,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,0);
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
#endif
kfree_skb(skb);
}
-
static struct neigh_ops clip_neigh_ops = {
.family = AF_INET,
.solicit = clip_neigh_solicit,
@@ -297,7 +294,6 @@ static struct neigh_ops clip_neigh_ops = {
.queue_xmit = dev_queue_xmit,
};
-
static int clip_constructor(struct neighbour *neigh)
{
struct atmarp_entry *entry = NEIGH2ENTRY(neigh);
@@ -305,9 +301,10 @@ static int clip_constructor(struct neighbour *neigh)
struct in_device *in_dev;
struct neigh_parms *parms;
- DPRINTK("clip_constructor (neigh %p, entry %p)\n",neigh,entry);
+ DPRINTK("clip_constructor (neigh %p, entry %p)\n", neigh, entry);
neigh->type = inet_addr_type(entry->ip);
- if (neigh->type != RTN_UNICAST) return -EINVAL;
+ if (neigh->type != RTN_UNICAST)
+ return -EINVAL;
rcu_read_lock();
in_dev = __in_dev_get_rcu(dev);
@@ -326,13 +323,13 @@ static int clip_constructor(struct neighbour *neigh)
neigh->ops->connected_output : neigh->ops->output;
entry->neigh = neigh;
entry->vccs = NULL;
- entry->expires = jiffies-1;
+ entry->expires = jiffies - 1;
return 0;
}
static u32 clip_hash(const void *pkey, const struct net_device *dev)
{
- return jhash_2words(*(u32 *)pkey, dev->ifindex, clip_tbl.hash_rnd);
+ return jhash_2words(*(u32 *) pkey, dev->ifindex, clip_tbl.hash_rnd);
}
static struct neigh_table clip_tbl = {
@@ -366,7 +363,6 @@ static struct neigh_table clip_tbl = {
.gc_thresh3 = 1024,
};
-
/* @@@ copy bh locking from arp.c -- need to bh-enable atm code before */
/*
@@ -376,15 +372,13 @@ static struct neigh_table clip_tbl = {
* clip_setentry.
*/
-
-static int clip_encap(struct atm_vcc *vcc,int mode)
+static int clip_encap(struct atm_vcc *vcc, int mode)
{
CLIP_VCC(vcc)->encap = mode;
return 0;
}
-
-static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
+static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct clip_priv *clip_priv = PRIV(dev);
struct atmarp_entry *entry;
@@ -392,7 +386,7 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
int old;
unsigned long flags;
- DPRINTK("clip_start_xmit (skb %p)\n",skb);
+ DPRINTK("clip_start_xmit (skb %p)\n", skb);
if (!skb->dst) {
printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n");
dev_kfree_skb(skb);
@@ -401,9 +395,9 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
}
if (!skb->dst->neighbour) {
#if 0
- skb->dst->neighbour = clip_find_neighbour(skb->dst,1);
+ skb->dst->neighbour = clip_find_neighbour(skb->dst, 1);
if (!skb->dst->neighbour) {
- dev_kfree_skb(skb); /* lost that one */
+ dev_kfree_skb(skb); /* lost that one */
clip_priv->stats.tx_dropped++;
return 0;
}
@@ -417,73 +411,73 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
if (!entry->vccs) {
if (time_after(jiffies, entry->expires)) {
/* should be resolved */
- entry->expires = jiffies+ATMARP_RETRY_DELAY*HZ;
- to_atmarpd(act_need,PRIV(dev)->number,entry->ip);
+ entry->expires = jiffies + ATMARP_RETRY_DELAY * HZ;
+ to_atmarpd(act_need, PRIV(dev)->number, entry->ip);
}
if (entry->neigh->arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS)
- skb_queue_tail(&entry->neigh->arp_queue,skb);
+ skb_queue_tail(&entry->neigh->arp_queue, skb);
else {
dev_kfree_skb(skb);
clip_priv->stats.tx_dropped++;
}
return 0;
}
- DPRINTK("neigh %p, vccs %p\n",entry,entry->vccs);
+ DPRINTK("neigh %p, vccs %p\n", entry, entry->vccs);
ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
- DPRINTK("using neighbour %p, vcc %p\n",skb->dst->neighbour,vcc);
+ DPRINTK("using neighbour %p, vcc %p\n", skb->dst->neighbour, vcc);
if (entry->vccs->encap) {
void *here;
- here = skb_push(skb,RFC1483LLC_LEN);
- memcpy(here,llc_oui,sizeof(llc_oui));
+ here = skb_push(skb, RFC1483LLC_LEN);
+ memcpy(here, llc_oui, sizeof(llc_oui));
((u16 *) here)[3] = skb->protocol;
}
atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
ATM_SKB(skb)->atm_options = vcc->atm_options;
entry->vccs->last_use = jiffies;
- DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,vcc,vcc->dev);
- old = xchg(&entry->vccs->xoff,1); /* assume XOFF ... */
+ DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev);
+ old = xchg(&entry->vccs->xoff, 1); /* assume XOFF ... */
if (old) {
printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n");
return 0;
}
clip_priv->stats.tx_packets++;
clip_priv->stats.tx_bytes += skb->len;
- (void) vcc->send(vcc,skb);
- if (atm_may_send(vcc,0)) {
+ vcc->send(vcc, skb);
+ if (atm_may_send(vcc, 0)) {
entry->vccs->xoff = 0;
return 0;
}
- spin_lock_irqsave(&clip_priv->xoff_lock,flags);
- netif_stop_queue(dev); /* XOFF -> throttle immediately */
+ spin_lock_irqsave(&clip_priv->xoff_lock, flags);
+ netif_stop_queue(dev); /* XOFF -> throttle immediately */
barrier();
if (!entry->vccs->xoff)
netif_start_queue(dev);
- /* Oh, we just raced with clip_pop. netif_start_queue should be
- good enough, because nothing should really be asleep because
- of the brief netif_stop_queue. If this isn't true or if it
- changes, use netif_wake_queue instead. */
- spin_unlock_irqrestore(&clip_priv->xoff_lock,flags);
+ /* Oh, we just raced with clip_pop. netif_start_queue should be
+ good enough, because nothing should really be asleep because
+ of the brief netif_stop_queue. If this isn't true or if it
+ changes, use netif_wake_queue instead. */
+ spin_unlock_irqrestore(&clip_priv->xoff_lock, flags);
return 0;
}
-
static struct net_device_stats *clip_get_stats(struct net_device *dev)
{
return &PRIV(dev)->stats;
}
-
-static int clip_mkip(struct atm_vcc *vcc,int timeout)
+static int clip_mkip(struct atm_vcc *vcc, int timeout)
{
struct clip_vcc *clip_vcc;
struct sk_buff_head copy;
struct sk_buff *skb;
- if (!vcc->push) return -EBADFD;
- clip_vcc = kmalloc(sizeof(struct clip_vcc),GFP_KERNEL);
- if (!clip_vcc) return -ENOMEM;
- DPRINTK("mkip clip_vcc %p vcc %p\n",clip_vcc,vcc);
+ if (!vcc->push)
+ return -EBADFD;
+ clip_vcc = kmalloc(sizeof(struct clip_vcc), GFP_KERNEL);
+ if (!clip_vcc)
+ return -ENOMEM;
+ DPRINTK("mkip clip_vcc %p vcc %p\n", clip_vcc, vcc);
clip_vcc->vcc = vcc;
vcc->user_back = clip_vcc;
set_bit(ATM_VF_IS_CLIP, &vcc->flags);
@@ -491,7 +485,7 @@ static int clip_mkip(struct atm_vcc *vcc,int timeout)
clip_vcc->xoff = 0;
clip_vcc->encap = 1;
clip_vcc->last_use = jiffies;
- clip_vcc->idle_timeout = timeout*HZ;
+ clip_vcc->idle_timeout = timeout * HZ;
clip_vcc->old_push = vcc->push;
clip_vcc->old_pop = vcc->pop;
vcc->push = clip_push;
@@ -501,27 +495,25 @@ static int clip_mkip(struct atm_vcc *vcc,int timeout)
/* re-process everything received between connection setup and MKIP */
while ((skb = skb_dequeue(&copy)) != NULL)
if (!clip_devs) {
- atm_return(vcc,skb->truesize);
+ atm_return(vcc, skb->truesize);
kfree_skb(skb);
- }
- else {
+ } else {
unsigned int len = skb->len;
- clip_push(vcc,skb);
+ clip_push(vcc, skb);
PRIV(skb->dev)->stats.rx_packets--;
PRIV(skb->dev)->stats.rx_bytes -= len;
}
return 0;
}
-
-static int clip_setentry(struct atm_vcc *vcc,u32 ip)
+static int clip_setentry(struct atm_vcc *vcc, u32 ip)
{
struct neighbour *neigh;
struct atmarp_entry *entry;
int error;
struct clip_vcc *clip_vcc;
- struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1 } } };
+ struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1}} };
struct rtable *rt;
if (vcc->push != clip_push) {
@@ -538,28 +530,29 @@ static int clip_setentry(struct atm_vcc *vcc,u32 ip)
unlink_clip_vcc(clip_vcc);
return 0;
}
- error = ip_route_output_key(&rt,&fl);
- if (error) return error;
- neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1);
+ error = ip_route_output_key(&rt, &fl);
+ if (error)
+ return error;
+ neigh = __neigh_lookup(&clip_tbl, &ip, rt->u.dst.dev, 1);
ip_rt_put(rt);
if (!neigh)
return -ENOMEM;
entry = NEIGH2ENTRY(neigh);
if (entry != clip_vcc->entry) {
- if (!clip_vcc->entry) DPRINTK("setentry: add\n");
+ if (!clip_vcc->entry)
+ DPRINTK("setentry: add\n");
else {
DPRINTK("setentry: update\n");
unlink_clip_vcc(clip_vcc);
}
- link_vcc(clip_vcc,entry);
+ link_vcc(clip_vcc, entry);
}
- error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
- NEIGH_UPDATE_F_OVERRIDE|NEIGH_UPDATE_F_ADMIN);
+ error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
+ NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN);
neigh_release(neigh);
return error;
}
-
static void clip_setup(struct net_device *dev)
{
dev->hard_start_xmit = clip_start_xmit;
@@ -568,15 +561,14 @@ static void clip_setup(struct net_device *dev)
dev->type = ARPHRD_ATM;
dev->hard_header_len = RFC1483LLC_LEN;
dev->mtu = RFC1626_MTU;
- dev->tx_queue_len = 100; /* "normal" queue (packets) */
- /* When using a "real" qdisc, the qdisc determines the queue */
- /* length. tx_queue_len is only used for the default case, */
- /* without any more elaborate queuing. 100 is a reasonable */
- /* compromise between decent burst-tolerance and protection */
- /* against memory hogs. */
+ dev->tx_queue_len = 100; /* "normal" queue (packets) */
+ /* When using a "real" qdisc, the qdisc determines the queue */
+ /* length. tx_queue_len is only used for the default case, */
+ /* without any more elaborate queuing. 100 is a reasonable */
+ /* compromise between decent burst-tolerance and protection */
+ /* against memory hogs. */
}
-
static int clip_create(int number)
{
struct net_device *dev;
@@ -585,19 +577,19 @@ static int clip_create(int number)
if (number != -1) {
for (dev = clip_devs; dev; dev = PRIV(dev)->next)
- if (PRIV(dev)->number == number) return -EEXIST;
- }
- else {
+ if (PRIV(dev)->number == number)
+ return -EEXIST;
+ } else {
number = 0;
for (dev = clip_devs; dev; dev = PRIV(dev)->next)
if (PRIV(dev)->number >= number)
- number = PRIV(dev)->number+1;
+ number = PRIV(dev)->number + 1;
}
dev = alloc_netdev(sizeof(struct clip_priv), "", clip_setup);
if (!dev)
return -ENOMEM;
clip_priv = PRIV(dev);
- sprintf(dev->name,"atm%d",number);
+ sprintf(dev->name, "atm%d", number);
spin_lock_init(&clip_priv->xoff_lock);
clip_priv->number = number;
error = register_netdev(dev);
@@ -607,53 +599,48 @@ static int clip_create(int number)
}
clip_priv->next = clip_devs;
clip_devs = dev;
- DPRINTK("registered (net:%s)\n",dev->name);
+ DPRINTK("registered (net:%s)\n", dev->name);
return number;
}
-
-static int clip_device_event(struct notifier_block *this,unsigned long event,
- void *dev)
+static int clip_device_event(struct notifier_block *this, unsigned long event,
+ void *arg)
{
+ struct net_device *dev = arg;
+
+ if (event == NETDEV_UNREGISTER) {
+ neigh_ifdown(&clip_tbl, dev);
+ return NOTIFY_DONE;
+ }
+
/* ignore non-CLIP devices */
- if (((struct net_device *) dev)->type != ARPHRD_ATM ||
- ((struct net_device *) dev)->hard_start_xmit != clip_start_xmit)
+ if (dev->type != ARPHRD_ATM || dev->hard_start_xmit != clip_start_xmit)
return NOTIFY_DONE;
+
switch (event) {
- case NETDEV_UP:
- DPRINTK("clip_device_event NETDEV_UP\n");
- (void) to_atmarpd(act_up,PRIV(dev)->number,0);
- break;
- case NETDEV_GOING_DOWN:
- DPRINTK("clip_device_event NETDEV_DOWN\n");
- (void) to_atmarpd(act_down,PRIV(dev)->number,0);
- break;
- case NETDEV_CHANGE:
- case NETDEV_CHANGEMTU:
- DPRINTK("clip_device_event NETDEV_CHANGE*\n");
- (void) to_atmarpd(act_change,PRIV(dev)->number,0);
- break;
- case NETDEV_REBOOT:
- case NETDEV_REGISTER:
- case NETDEV_DOWN:
- DPRINTK("clip_device_event %ld\n",event);
- /* ignore */
- break;
- default:
- printk(KERN_WARNING "clip_device_event: unknown event "
- "%ld\n",event);
- break;
+ case NETDEV_UP:
+ DPRINTK("clip_device_event NETDEV_UP\n");
+ to_atmarpd(act_up, PRIV(dev)->number, 0);
+ break;
+ case NETDEV_GOING_DOWN:
+ DPRINTK("clip_device_event NETDEV_DOWN\n");
+ to_atmarpd(act_down, PRIV(dev)->number, 0);
+ break;
+ case NETDEV_CHANGE:
+ case NETDEV_CHANGEMTU:
+ DPRINTK("clip_device_event NETDEV_CHANGE*\n");
+ to_atmarpd(act_change, PRIV(dev)->number, 0);
+ break;
}
return NOTIFY_DONE;
}
-
-static int clip_inet_event(struct notifier_block *this,unsigned long event,
- void *ifa)
+static int clip_inet_event(struct notifier_block *this, unsigned long event,
+ void *ifa)
{
struct in_device *in_dev;
- in_dev = ((struct in_ifaddr *) ifa)->ifa_dev;
+ in_dev = ((struct in_ifaddr *)ifa)->ifa_dev;
if (!in_dev || !in_dev->dev) {
printk(KERN_WARNING "clip_inet_event: no device\n");
return NOTIFY_DONE;
@@ -662,23 +649,20 @@ static int clip_inet_event(struct notifier_block *this,unsigned long event,
* Transitions are of the down-change-up type, so it's sufficient to
* handle the change on up.
*/
- if (event != NETDEV_UP) return NOTIFY_DONE;
- return clip_device_event(this,NETDEV_CHANGE,in_dev->dev);
+ if (event != NETDEV_UP)
+ return NOTIFY_DONE;
+ return clip_device_event(this, NETDEV_CHANGE, in_dev->dev);
}
static struct notifier_block clip_dev_notifier = {
- clip_device_event,
- NULL,
- 0
+ .notifier_call = clip_device_event,
};
static struct notifier_block clip_inet_notifier = {
- clip_inet_event,
- NULL,
- 0
+ .notifier_call = clip_inet_event,
};
@@ -686,14 +670,12 @@ static struct notifier_block clip_inet_notifier = {
static void atmarpd_close(struct atm_vcc *vcc)
{
DPRINTK("atmarpd_close\n");
- atmarpd = NULL; /* assumed to be atomic */
- barrier();
- unregister_inetaddr_notifier(&clip_inet_notifier);
- unregister_netdevice_notifier(&clip_dev_notifier);
- if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
- printk(KERN_ERR "atmarpd_close: closing with requests "
- "pending\n");
+
+ rtnl_lock();
+ atmarpd = NULL;
skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
+ rtnl_unlock();
+
DPRINTK("(done)\n");
module_put(THIS_MODULE);
}
@@ -714,14 +696,14 @@ static struct atm_dev atmarpd_dev = {
static int atm_init_atmarp(struct atm_vcc *vcc)
{
- if (atmarpd) return -EADDRINUSE;
- if (start_timer) {
- start_timer = 0;
- init_timer(&idle_timer);
- idle_timer.expires = jiffies+CLIP_CHECK_INTERVAL*HZ;
- idle_timer.function = idle_timer_check;
- add_timer(&idle_timer);
+ rtnl_lock();
+ if (atmarpd) {
+ rtnl_unlock();
+ return -EADDRINUSE;
}
+
+ mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ);
+
atmarpd = vcc;
set_bit(ATM_VF_META,&vcc->flags);
set_bit(ATM_VF_READY,&vcc->flags);
@@ -731,10 +713,7 @@ static int atm_init_atmarp(struct atm_vcc *vcc)
vcc->push = NULL;
vcc->pop = NULL; /* crash */
vcc->push_oam = NULL; /* crash */
- if (register_netdevice_notifier(&clip_dev_notifier))
- printk(KERN_ERR "register_netdevice_notifier failed\n");
- if (register_inetaddr_notifier(&clip_inet_notifier))
- printk(KERN_ERR "register_inetaddr_notifier failed\n");
+ rtnl_unlock();
return 0;
}
@@ -744,53 +723,53 @@ static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
int err = 0;
switch (cmd) {
- case SIOCMKCLIP:
- case ATMARPD_CTRL:
- case ATMARP_MKIP:
- case ATMARP_SETENTRY:
- case ATMARP_ENCAP:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- break;
- default:
- return -ENOIOCTLCMD;
+ case SIOCMKCLIP:
+ case ATMARPD_CTRL:
+ case ATMARP_MKIP:
+ case ATMARP_SETENTRY:
+ case ATMARP_ENCAP:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ break;
+ default:
+ return -ENOIOCTLCMD;
}
switch (cmd) {
- case SIOCMKCLIP:
- err = clip_create(arg);
- break;
- case ATMARPD_CTRL:
- err = atm_init_atmarp(vcc);
- if (!err) {
- sock->state = SS_CONNECTED;
- __module_get(THIS_MODULE);
- }
- break;
- case ATMARP_MKIP:
- err = clip_mkip(vcc ,arg);
- break;
- case ATMARP_SETENTRY:
- err = clip_setentry(vcc, arg);
- break;
- case ATMARP_ENCAP:
- err = clip_encap(vcc, arg);
- break;
+ case SIOCMKCLIP:
+ err = clip_create(arg);
+ break;
+ case ATMARPD_CTRL:
+ err = atm_init_atmarp(vcc);
+ if (!err) {
+ sock->state = SS_CONNECTED;
+ __module_get(THIS_MODULE);
+ }
+ break;
+ case ATMARP_MKIP:
+ err = clip_mkip(vcc, arg);
+ break;
+ case ATMARP_SETENTRY:
+ err = clip_setentry(vcc, arg);
+ break;
+ case ATMARP_ENCAP:
+ err = clip_encap(vcc, arg);
+ break;
}
return err;
}
static struct atm_ioctl clip_ioctl_ops = {
- .owner = THIS_MODULE,
- .ioctl = clip_ioctl,
+ .owner = THIS_MODULE,
+ .ioctl = clip_ioctl,
};
#ifdef CONFIG_PROC_FS
static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
{
- static int code[] = { 1,2,10,6,1,0 };
- static int e164[] = { 1,8,4,6,1,0 };
+ static int code[] = { 1, 2, 10, 6, 1, 0 };
+ static int e164[] = { 1, 8, 4, 6, 1, 0 };
if (*addr->sas_addr.pub) {
seq_printf(seq, "%s", addr->sas_addr.pub);
@@ -809,7 +788,7 @@ static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
for (i = 0; fields[i]; i++) {
for (j = fields[i]; j; j--)
seq_printf(seq, "%02X", *prv++);
- if (fields[i+1])
+ if (fields[i + 1])
seq_putc(seq, '.');
}
}
@@ -828,8 +807,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev,
svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
(sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC));
- llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
- clip_vcc->encap);
+ llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || clip_vcc->encap);
if (clip_vcc == SEQ_NO_VCC_TOKEN)
exp = entry->neigh->used;
@@ -839,10 +817,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev,
exp = (jiffies - exp) / HZ;
seq_printf(seq, "%-6s%-4s%-4s%5ld ",
- dev->name,
- svc ? "SVC" : "PVC",
- llc ? "LLC" : "NULL",
- exp);
+ dev->name, svc ? "SVC" : "PVC", llc ? "LLC" : "NULL", exp);
off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d",
NIPQUAD(entry->ip));
@@ -860,8 +835,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev,
} else if (!svc) {
seq_printf(seq, "%d.%d.%d\n",
clip_vcc->vcc->dev->number,
- clip_vcc->vcc->vpi,
- clip_vcc->vcc->vci);
+ clip_vcc->vcc->vpi, clip_vcc->vcc->vci);
} else {
svc_addr(seq, &clip_vcc->vcc->remote);
seq_putc(seq, '\n');
@@ -894,7 +868,7 @@ static struct clip_vcc *clip_seq_next_vcc(struct atmarp_entry *e,
}
static void *clip_seq_vcc_walk(struct clip_seq_state *state,
- struct atmarp_entry *e, loff_t *pos)
+ struct atmarp_entry *e, loff_t * pos)
{
struct clip_vcc *vcc = state->vcc;
@@ -911,24 +885,24 @@ static void *clip_seq_vcc_walk(struct clip_seq_state *state,
return vcc;
}
-
+
static void *clip_seq_sub_iter(struct neigh_seq_state *_state,
- struct neighbour *n, loff_t *pos)
+ struct neighbour *n, loff_t * pos)
{
- struct clip_seq_state *state = (struct clip_seq_state *) _state;
+ struct clip_seq_state *state = (struct clip_seq_state *)_state;
return clip_seq_vcc_walk(state, NEIGH2ENTRY(n), pos);
}
-static void *clip_seq_start(struct seq_file *seq, loff_t *pos)
+static void *clip_seq_start(struct seq_file *seq, loff_t * pos)
{
return neigh_seq_start(seq, pos, &clip_tbl, NEIGH_SEQ_NEIGH_ONLY);
}
static int clip_seq_show(struct seq_file *seq, void *v)
{
- static char atm_arp_banner[] =
- "IPitf TypeEncp Idle IP address ATM address\n";
+ static char atm_arp_banner[] =
+ "IPitf TypeEncp Idle IP address ATM address\n";
if (v == SEQ_START_TOKEN) {
seq_puts(seq, atm_arp_banner);
@@ -939,7 +913,7 @@ static int clip_seq_show(struct seq_file *seq, void *v)
atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc);
}
- return 0;
+ return 0;
}
static struct seq_operations arp_seq_ops = {
@@ -988,20 +962,19 @@ static struct file_operations arp_seq_fops = {
static int __init atm_clip_init(void)
{
- neigh_table_init(&clip_tbl);
+ struct proc_dir_entry *p;
+ neigh_table_init_no_netlink(&clip_tbl);
clip_tbl_hook = &clip_tbl;
register_atm_ioctl(&clip_ioctl_ops);
+ register_netdevice_notifier(&clip_dev_notifier);
+ register_inetaddr_notifier(&clip_inet_notifier);
-#ifdef CONFIG_PROC_FS
-{
- struct proc_dir_entry *p;
+ setup_timer(&idle_timer, idle_timer_check, 0);
p = create_proc_entry("arp", S_IRUGO, atm_proc_root);
if (p)
p->proc_fops = &arp_seq_fops;
-}
-#endif
return 0;
}
@@ -1012,13 +985,15 @@ static void __exit atm_clip_exit(void)
remove_proc_entry("arp", atm_proc_root);
+ unregister_inetaddr_notifier(&clip_inet_notifier);
+ unregister_netdevice_notifier(&clip_dev_notifier);
+
deregister_atm_ioctl(&clip_ioctl_ops);
/* First, stop the idle timer, so it stops banging
* on the table.
*/
- if (start_timer == 0)
- del_timer(&idle_timer);
+ del_timer_sync(&idle_timer);
/* Next, purge the table, so that the device
* unregister loop below does not hang due to
@@ -1042,5 +1017,6 @@ static void __exit atm_clip_exit(void)
module_init(atm_clip_init);
module_exit(atm_clip_exit);
-
+MODULE_AUTHOR("Werner Almesberger");
+MODULE_DESCRIPTION("Classical/IP over ATM interface");
MODULE_LICENSE("GPL");
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index dbf9b47681f..a2e0dd047e9 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -228,6 +228,8 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr,
return NULL;
}
+EXPORT_SYMBOL(ax25_find_cb);
+
void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto)
{
ax25_cb *s;
@@ -424,6 +426,26 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
return 0;
}
+static void ax25_fillin_cb_from_dev(ax25_cb *ax25, ax25_dev *ax25_dev)
+{
+ ax25->rtt = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]) / 2;
+ ax25->t1 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]);
+ ax25->t2 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T2]);
+ ax25->t3 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T3]);
+ ax25->n2 = ax25_dev->values[AX25_VALUES_N2];
+ ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN];
+ ax25->idle = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_IDLE]);
+ ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF];
+
+ if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) {
+ ax25->modulus = AX25_EMODULUS;
+ ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW];
+ } else {
+ ax25->modulus = AX25_MODULUS;
+ ax25->window = ax25_dev->values[AX25_VALUES_WINDOW];
+ }
+}
+
/*
* Fill in a created AX.25 created control block with the default
* values for a particular device.
@@ -433,39 +455,28 @@ void ax25_fillin_cb(ax25_cb *ax25, ax25_dev *ax25_dev)
ax25->ax25_dev = ax25_dev;
if (ax25->ax25_dev != NULL) {
- ax25->rtt = ax25_dev->values[AX25_VALUES_T1] / 2;
- ax25->t1 = ax25_dev->values[AX25_VALUES_T1];
- ax25->t2 = ax25_dev->values[AX25_VALUES_T2];
- ax25->t3 = ax25_dev->values[AX25_VALUES_T3];
- ax25->n2 = ax25_dev->values[AX25_VALUES_N2];
- ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN];
- ax25->idle = ax25_dev->values[AX25_VALUES_IDLE];
- ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF];
-
- if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) {
- ax25->modulus = AX25_EMODULUS;
- ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW];
- } else {
- ax25->modulus = AX25_MODULUS;
- ax25->window = ax25_dev->values[AX25_VALUES_WINDOW];
- }
+ ax25_fillin_cb_from_dev(ax25, ax25_dev);
+ return;
+ }
+
+ /*
+ * No device, use kernel / AX.25 spec default values
+ */
+ ax25->rtt = msecs_to_jiffies(AX25_DEF_T1) / 2;
+ ax25->t1 = msecs_to_jiffies(AX25_DEF_T1);
+ ax25->t2 = msecs_to_jiffies(AX25_DEF_T2);
+ ax25->t3 = msecs_to_jiffies(AX25_DEF_T3);
+ ax25->n2 = AX25_DEF_N2;
+ ax25->paclen = AX25_DEF_PACLEN;
+ ax25->idle = msecs_to_jiffies(AX25_DEF_IDLE);
+ ax25->backoff = AX25_DEF_BACKOFF;
+
+ if (AX25_DEF_AXDEFMODE) {
+ ax25->modulus = AX25_EMODULUS;
+ ax25->window = AX25_DEF_EWINDOW;
} else {
- ax25->rtt = AX25_DEF_T1 / 2;
- ax25->t1 = AX25_DEF_T1;
- ax25->t2 = AX25_DEF_T2;
- ax25->t3 = AX25_DEF_T3;
- ax25->n2 = AX25_DEF_N2;
- ax25->paclen = AX25_DEF_PACLEN;
- ax25->idle = AX25_DEF_IDLE;
- ax25->backoff = AX25_DEF_BACKOFF;
-
- if (AX25_DEF_AXDEFMODE) {
- ax25->modulus = AX25_EMODULUS;
- ax25->window = AX25_DEF_EWINDOW;
- } else {
- ax25->modulus = AX25_MODULUS;
- ax25->window = AX25_DEF_WINDOW;
- }
+ ax25->modulus = AX25_MODULUS;
+ ax25->window = AX25_DEF_WINDOW;
}
}
@@ -1979,24 +1990,6 @@ static struct notifier_block ax25_dev_notifier = {
.notifier_call =ax25_device_event,
};
-EXPORT_SYMBOL(ax25_hard_header);
-EXPORT_SYMBOL(ax25_rebuild_header);
-EXPORT_SYMBOL(ax25_findbyuid);
-EXPORT_SYMBOL(ax25_find_cb);
-EXPORT_SYMBOL(ax25_linkfail_register);
-EXPORT_SYMBOL(ax25_linkfail_release);
-EXPORT_SYMBOL(ax25_listen_register);
-EXPORT_SYMBOL(ax25_listen_release);
-EXPORT_SYMBOL(ax25_protocol_register);
-EXPORT_SYMBOL(ax25_protocol_release);
-EXPORT_SYMBOL(ax25_send_frame);
-EXPORT_SYMBOL(ax25_uid_policy);
-EXPORT_SYMBOL(ax25cmp);
-EXPORT_SYMBOL(ax2asc);
-EXPORT_SYMBOL(asc2ax);
-EXPORT_SYMBOL(null_ax25_address);
-EXPORT_SYMBOL(ax25_display_timer);
-
static int __init ax25_init(void)
{
int rc = proto_register(&ax25_proto, 0);
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c
index 0164a155b8c..5f0896ad004 100644
--- a/net/ax25/ax25_addr.c
+++ b/net/ax25/ax25_addr.c
@@ -11,6 +11,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h>
@@ -33,6 +34,8 @@
*/
ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}};
+EXPORT_SYMBOL(null_ax25_address);
+
/*
* ax25 -> ascii conversion
*/
@@ -64,6 +67,8 @@ char *ax2asc(char *buf, ax25_address *a)
}
+EXPORT_SYMBOL(ax2asc);
+
/*
* ascii -> ax25 conversion
*/
@@ -97,6 +102,8 @@ void asc2ax(ax25_address *addr, char *callsign)
addr->ax25_call[6] &= 0x1E;
}
+EXPORT_SYMBOL(asc2ax);
+
/*
* Compare two ax.25 addresses
*/
@@ -116,6 +123,8 @@ int ax25cmp(ax25_address *a, ax25_address *b)
return 2; /* Partial match */
}
+EXPORT_SYMBOL(ax25cmp);
+
/*
* Compare two AX.25 digipeater paths.
*/
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
index 061083efc1d..5961459935e 100644
--- a/net/ax25/ax25_ds_timer.c
+++ b/net/ax25/ax25_ds_timer.c
@@ -61,7 +61,8 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev)
return;
del_timer(&ax25_dev->dama.slave_timer);
- ax25_dev->dama.slave_timeout = ax25_dev->values[AX25_VALUES_DS_TIMEOUT] / 10;
+ ax25_dev->dama.slave_timeout =
+ msecs_to_jiffies(ax25_dev->values[AX25_VALUES_DS_TIMEOUT]) / 10;
ax25_ds_add_timer(ax25_dev);
}
diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c
index d68aff10072..3bb152710b7 100644
--- a/net/ax25/ax25_iface.c
+++ b/net/ax25/ax25_iface.c
@@ -12,6 +12,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
@@ -74,6 +75,8 @@ int ax25_protocol_register(unsigned int pid,
return 1;
}
+EXPORT_SYMBOL(ax25_protocol_register);
+
void ax25_protocol_release(unsigned int pid)
{
struct protocol_struct *s, *protocol;
@@ -106,6 +109,8 @@ void ax25_protocol_release(unsigned int pid)
write_unlock(&protocol_list_lock);
}
+EXPORT_SYMBOL(ax25_protocol_release);
+
int ax25_linkfail_register(void (*func)(ax25_cb *, int))
{
struct linkfail_struct *linkfail;
@@ -123,6 +128,8 @@ int ax25_linkfail_register(void (*func)(ax25_cb *, int))
return 1;
}
+EXPORT_SYMBOL(ax25_linkfail_register);
+
void ax25_linkfail_release(void (*func)(ax25_cb *, int))
{
struct linkfail_struct *s, *linkfail;
@@ -155,6 +162,8 @@ void ax25_linkfail_release(void (*func)(ax25_cb *, int))
spin_unlock_bh(&linkfail_lock);
}
+EXPORT_SYMBOL(ax25_linkfail_release);
+
int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
{
struct listen_struct *listen;
@@ -176,6 +185,8 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
return 1;
}
+EXPORT_SYMBOL(ax25_listen_register);
+
void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
{
struct listen_struct *s, *listen;
@@ -208,6 +219,8 @@ void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
spin_unlock_bh(&listen_lock);
}
+EXPORT_SYMBOL(ax25_listen_release);
+
int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
{
int (*res)(struct sk_buff *, ax25_cb *) = NULL;
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c
index d643dac3ecc..a0b534f80f1 100644
--- a/net/ax25/ax25_ip.c
+++ b/net/ax25/ax25_ip.c
@@ -12,6 +12,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h>
@@ -221,3 +222,5 @@ int ax25_rebuild_header(struct sk_buff *skb)
#endif
+EXPORT_SYMBOL(ax25_hard_header);
+EXPORT_SYMBOL(ax25_rebuild_header);
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index 5fc048dcd39..5d99852b239 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -14,6 +14,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h>
@@ -104,6 +105,8 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax2
return ax25; /* We had to create it */
}
+EXPORT_SYMBOL(ax25_send_frame);
+
/*
* All outgoing AX.25 I frames pass via this routine. Therefore this is
* where the fragmentation of frames takes place. If fragment is set to
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index f04f8630fd2..5ac98250797 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -360,7 +360,7 @@ struct file_operations ax25_route_fops = {
/*
* Find AX.25 route
*
- * Only routes with a refernce rout of zero can be destroyed.
+ * Only routes with a reference count of zero can be destroyed.
*/
static ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
{
diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c
index 7a6b50a1455..ec254057f21 100644
--- a/net/ax25/ax25_timer.c
+++ b/net/ax25/ax25_timer.c
@@ -18,6 +18,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <linux/string.h>
@@ -137,6 +138,8 @@ unsigned long ax25_display_timer(struct timer_list *timer)
return timer->expires - jiffies;
}
+EXPORT_SYMBOL(ax25_display_timer);
+
static void ax25_heartbeat_expiry(unsigned long param)
{
int proto = AX25_PROTO_STD_SIMPLEX;
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index b8b5854bce9..5e9a81e8b21 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -49,6 +49,8 @@ static DEFINE_RWLOCK(ax25_uid_lock);
int ax25_uid_policy = 0;
+EXPORT_SYMBOL(ax25_uid_policy);
+
ax25_uid_assoc *ax25_findbyuid(uid_t uid)
{
ax25_uid_assoc *ax25_uid, *res = NULL;
@@ -67,6 +69,8 @@ ax25_uid_assoc *ax25_findbyuid(uid_t uid)
return res;
}
+EXPORT_SYMBOL(ax25_findbyuid);
+
int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
{
ax25_uid_assoc *ax25_uid;
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index 894a22558d9..bdb64c36df1 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -18,14 +18,14 @@ static int min_backoff[1], max_backoff[] = {2};
static int min_conmode[1], max_conmode[] = {2};
static int min_window[] = {1}, max_window[] = {7};
static int min_ewindow[] = {1}, max_ewindow[] = {63};
-static int min_t1[] = {1}, max_t1[] = {30 * HZ};
-static int min_t2[] = {1}, max_t2[] = {20 * HZ};
-static int min_t3[1], max_t3[] = {3600 * HZ};
-static int min_idle[1], max_idle[] = {65535 * HZ};
+static int min_t1[] = {1}, max_t1[] = {30000};
+static int min_t2[] = {1}, max_t2[] = {20000};
+static int min_t3[1], max_t3[] = {3600000};
+static int min_idle[1], max_idle[] = {65535000};
static int min_n2[] = {1}, max_n2[] = {31};
static int min_paclen[] = {1}, max_paclen[] = {512};
static int min_proto[1], max_proto[] = { AX25_PROTO_MAX };
-static int min_ds_timeout[1], max_ds_timeout[] = {65535 * HZ};
+static int min_ds_timeout[1], max_ds_timeout[] = {65535000};
static struct ctl_table_header *ax25_table_header;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 9106354c781..a49a6975092 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -73,23 +73,23 @@ DEFINE_RWLOCK(hci_cb_list_lock);
struct hci_proto *hci_proto[HCI_MAX_PROTO];
/* HCI notifiers list */
-static struct notifier_block *hci_notifier;
+static ATOMIC_NOTIFIER_HEAD(hci_notifier);
/* ---- HCI notifications ---- */
int hci_register_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&hci_notifier, nb);
+ return atomic_notifier_chain_register(&hci_notifier, nb);
}
int hci_unregister_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&hci_notifier, nb);
+ return atomic_notifier_chain_unregister(&hci_notifier, nb);
}
static void hci_notify(struct hci_dev *hdev, int event)
{
- notifier_call_chain(&hci_notifier, event, hdev);
+ atomic_notifier_call_chain(&hci_notifier, event, hdev);
}
/* ---- HCI requests ---- */
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 6b61323ce23..0c2d13ad69b 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -255,7 +255,7 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
}
if ((err = hci_send_sco(conn->hcon, skb)) < 0)
- goto fail;
+ return err;
return count;
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 22d806cf40c..12da21afb9c 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -55,7 +55,7 @@ static int __init br_init(void)
static void __exit br_deinit(void)
{
- llc_sap_close(br_stp_sap);
+ rcu_assign_pointer(br_stp_sap->rcv_func, NULL);
#ifdef CONFIG_BRIDGE_NETFILTER
br_netfilter_fini();
@@ -67,6 +67,7 @@ static void __exit br_deinit(void)
synchronize_net();
+ llc_sap_put(br_stp_sap);
br_fdb_get_hook = NULL;
br_fdb_put_hook = NULL;
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 2d24fb400e0..56f3aa47e75 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
#include <linux/netfilter_bridge.h>
#include "br_private.h"
@@ -29,10 +30,15 @@ static inline int should_deliver(const struct net_bridge_port *p,
return 1;
}
+static inline unsigned packet_length(const struct sk_buff *skb)
+{
+ return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0);
+}
+
int br_dev_queue_push_xmit(struct sk_buff *skb)
{
/* drop mtu oversized packets except tso */
- if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
+ if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
kfree_skb(skb);
else {
#ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 59eef42d4a4..f5d47bf4f96 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -300,34 +300,22 @@ int br_add_bridge(const char *name)
rtnl_lock();
if (strchr(dev->name, '%')) {
ret = dev_alloc_name(dev, dev->name);
- if (ret < 0)
- goto err1;
+ if (ret < 0) {
+ free_netdev(dev);
+ goto out;
+ }
}
ret = register_netdevice(dev);
if (ret)
- goto err2;
-
- /* network device kobject is not setup until
- * after rtnl_unlock does it's hotplug magic.
- * so hold reference to avoid race.
- */
- dev_hold(dev);
- rtnl_unlock();
+ goto out;
ret = br_sysfs_addbr(dev);
- dev_put(dev);
-
- if (ret)
- unregister_netdev(dev);
+ if (ret)
+ unregister_netdevice(dev);
out:
- return ret;
-
- err2:
- free_netdev(dev);
- err1:
rtnl_unlock();
- goto out;
+ return ret;
}
int br_del_bridge(const char *name)
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index b7766562d72..bfa4d8c333f 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -66,6 +66,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
}
if (is_multicast_ether_addr(dest)) {
+ br->statistics.multicast++;
br_flood_forward(br, skb, !passedup);
if (!passedup)
br_pass_frame_up(br, skb);
@@ -125,9 +126,6 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
struct sk_buff *skb = *pskb;
const unsigned char *dest = eth_hdr(skb)->h_dest;
- if (p->state == BR_STATE_DISABLED)
- goto err;
-
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
goto err;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index f29450b788b..3da9264449f 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -765,6 +765,15 @@ out:
return NF_STOLEN;
}
+static int br_nf_dev_queue_xmit(struct sk_buff *skb)
+{
+ if (skb->protocol == htons(ETH_P_IP) &&
+ skb->len > skb->dev->mtu &&
+ !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
+ return ip_fragment(skb, br_dev_queue_push_xmit);
+ else
+ return br_dev_queue_push_xmit(skb);
+}
/* PF_BRIDGE/POST_ROUTING ********************************************/
static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
@@ -824,7 +833,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
realoutdev = nf_bridge->netoutdev;
#endif
NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
- br_dev_queue_push_xmit);
+ br_nf_dev_queue_xmit);
return NF_STOLEN;
@@ -869,7 +878,7 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
if ((out->hard_start_xmit == br_dev_xmit &&
okfn != br_nf_forward_finish &&
- okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit)
+ okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit)
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
|| ((out->priv_flags & IFF_802_1Q_VLAN) &&
VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c
index 468ebdf4bc1..d42f63f5e9f 100644
--- a/net/bridge/netfilter/ebt_802_3.c
+++ b/net/bridge/netfilter/ebt_802_3.c
@@ -58,16 +58,16 @@ static struct ebt_match filter_802_3 =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_802_3_init(void)
{
return ebt_register_match(&filter_802_3);
}
-static void __exit fini(void)
+static void __exit ebt_802_3_fini(void)
{
ebt_unregister_match(&filter_802_3);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_802_3_init);
+module_exit(ebt_802_3_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c
index 5a1f5e3bff1..a614485828a 100644
--- a/net/bridge/netfilter/ebt_among.c
+++ b/net/bridge/netfilter/ebt_among.c
@@ -213,16 +213,16 @@ static struct ebt_match filter_among = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_among_init(void)
{
return ebt_register_match(&filter_among);
}
-static void __exit fini(void)
+static void __exit ebt_among_fini(void)
{
ebt_unregister_match(&filter_among);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_among_init);
+module_exit(ebt_among_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
index b94c48cb6e4..a6c81d9f73b 100644
--- a/net/bridge/netfilter/ebt_arp.c
+++ b/net/bridge/netfilter/ebt_arp.c
@@ -125,16 +125,16 @@ static struct ebt_match filter_arp =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_arp_init(void)
{
return ebt_register_match(&filter_arp);
}
-static void __exit fini(void)
+static void __exit ebt_arp_fini(void)
{
ebt_unregister_match(&filter_arp);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_arp_init);
+module_exit(ebt_arp_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index b934de90f7c..d19fc4b328d 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -82,16 +82,16 @@ static struct ebt_target reply_target =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_arpreply_init(void)
{
return ebt_register_target(&reply_target);
}
-static void __exit fini(void)
+static void __exit ebt_arpreply_fini(void)
{
ebt_unregister_target(&reply_target);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_arpreply_init);
+module_exit(ebt_arpreply_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
index f5463086c7b..4582659dff0 100644
--- a/net/bridge/netfilter/ebt_dnat.c
+++ b/net/bridge/netfilter/ebt_dnat.c
@@ -61,16 +61,16 @@ static struct ebt_target dnat =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_dnat_init(void)
{
return ebt_register_target(&dnat);
}
-static void __exit fini(void)
+static void __exit ebt_dnat_fini(void)
{
ebt_unregister_target(&dnat);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_dnat_init);
+module_exit(ebt_dnat_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
index dc5d0b2427c..65b665ce57b 100644
--- a/net/bridge/netfilter/ebt_ip.c
+++ b/net/bridge/netfilter/ebt_ip.c
@@ -112,16 +112,16 @@ static struct ebt_match filter_ip =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_ip_init(void)
{
return ebt_register_match(&filter_ip);
}
-static void __exit fini(void)
+static void __exit ebt_ip_fini(void)
{
ebt_unregister_match(&filter_ip);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_ip_init);
+module_exit(ebt_ip_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c
index 637c8844cd5..d48fa5cb26c 100644
--- a/net/bridge/netfilter/ebt_limit.c
+++ b/net/bridge/netfilter/ebt_limit.c
@@ -98,16 +98,16 @@ static struct ebt_match ebt_limit_reg =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_limit_init(void)
{
return ebt_register_match(&ebt_limit_reg);
}
-static void __exit fini(void)
+static void __exit ebt_limit_fini(void)
{
ebt_unregister_match(&ebt_limit_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_limit_init);
+module_exit(ebt_limit_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 288ff1d4ccc..466ed3440b7 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -168,7 +168,7 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
if (info->bitmask & EBT_LOG_NFLOG)
nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
- info->prefix);
+ "%s", info->prefix);
else
ebt_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li,
info->prefix);
@@ -188,7 +188,7 @@ static struct nf_logger ebt_log_logger = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_log_init(void)
{
int ret;
@@ -205,12 +205,12 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ebt_log_fini(void)
{
nf_log_unregister_logger(&ebt_log_logger);
ebt_unregister_watcher(&log);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_log_init);
+module_exit(ebt_log_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index c93d35ab95c..770c0df972a 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -52,16 +52,16 @@ static struct ebt_target mark_target =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_mark_init(void)
{
return ebt_register_target(&mark_target);
}
-static void __exit fini(void)
+static void __exit ebt_mark_fini(void)
{
ebt_unregister_target(&mark_target);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_mark_init);
+module_exit(ebt_mark_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c
index 625102de149..a6413e4b498 100644
--- a/net/bridge/netfilter/ebt_mark_m.c
+++ b/net/bridge/netfilter/ebt_mark_m.c
@@ -47,16 +47,16 @@ static struct ebt_match filter_mark =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_mark_m_init(void)
{
return ebt_register_match(&filter_mark);
}
-static void __exit fini(void)
+static void __exit ebt_mark_m_fini(void)
{
ebt_unregister_match(&filter_mark);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_mark_m_init);
+module_exit(ebt_mark_m_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_pkttype.c b/net/bridge/netfilter/ebt_pkttype.c
index ecd3b42b19b..4fffd70e4da 100644
--- a/net/bridge/netfilter/ebt_pkttype.c
+++ b/net/bridge/netfilter/ebt_pkttype.c
@@ -44,16 +44,16 @@ static struct ebt_match filter_pkttype =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_pkttype_init(void)
{
return ebt_register_match(&filter_pkttype);
}
-static void __exit fini(void)
+static void __exit ebt_pkttype_fini(void)
{
ebt_unregister_match(&filter_pkttype);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_pkttype_init);
+module_exit(ebt_pkttype_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index 1538b438666..9f378eab72d 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -66,16 +66,16 @@ static struct ebt_target redirect_target =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_redirect_init(void)
{
return ebt_register_target(&redirect_target);
}
-static void __exit fini(void)
+static void __exit ebt_redirect_fini(void)
{
ebt_unregister_target(&redirect_target);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_redirect_init);
+module_exit(ebt_redirect_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index 1529bdcb9a4..cbb33e24ca8 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -61,16 +61,16 @@ static struct ebt_target snat =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_snat_init(void)
{
return ebt_register_target(&snat);
}
-static void __exit fini(void)
+static void __exit ebt_snat_fini(void)
{
ebt_unregister_target(&snat);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_snat_init);
+module_exit(ebt_snat_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c
index 0248c67277e..a0bed82145e 100644
--- a/net/bridge/netfilter/ebt_stp.c
+++ b/net/bridge/netfilter/ebt_stp.c
@@ -180,16 +180,16 @@ static struct ebt_match filter_stp =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_stp_init(void)
{
return ebt_register_match(&filter_stp);
}
-static void __exit fini(void)
+static void __exit ebt_stp_fini(void)
{
ebt_unregister_match(&filter_stp);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_stp_init);
+module_exit(ebt_stp_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 802baf755ef..ee5a5176126 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -281,7 +281,7 @@ static struct nf_logger ebt_ulog_logger = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_ulog_init(void)
{
int i, ret = 0;
@@ -316,7 +316,7 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ebt_ulog_fini(void)
{
ebt_ulog_buff_t *ub;
int i;
@@ -337,8 +337,8 @@ static void __exit fini(void)
sock_release(ebtulognl->sk_socket);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_ulog_init);
+module_exit(ebt_ulog_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
MODULE_DESCRIPTION("ebtables userspace logging module for bridged Ethernet"
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index db60d734908..a2b452862b7 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -178,7 +178,7 @@ static struct ebt_match filter_vlan = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_vlan_init(void)
{
DEBUG_MSG("ebtables 802.1Q extension module v"
MODULE_VERS "\n");
@@ -186,10 +186,10 @@ static int __init init(void)
return ebt_register_match(&filter_vlan);
}
-static void __exit fini(void)
+static void __exit ebt_vlan_fini(void)
{
ebt_unregister_match(&filter_vlan);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_vlan_init);
+module_exit(ebt_vlan_fini);
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index 1767c94cd3d..9a6e548e148 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -62,7 +62,7 @@ static int ebt_broute(struct sk_buff **pskb)
return 0; /* bridge it */
}
-static int __init init(void)
+static int __init ebtable_broute_init(void)
{
int ret;
@@ -74,13 +74,13 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ebtable_broute_fini(void)
{
br_should_route_hook = NULL;
synchronize_net();
ebt_unregister_table(&broute_table);
}
-module_init(init);
-module_exit(fini);
+module_init(ebtable_broute_init);
+module_exit(ebtable_broute_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index c18666e0392..3d5bd44f239 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -91,7 +91,7 @@ static struct nf_hook_ops ebt_ops_filter[] = {
},
};
-static int __init init(void)
+static int __init ebtable_filter_init(void)
{
int i, j, ret;
@@ -109,7 +109,7 @@ cleanup:
return ret;
}
-static void __exit fini(void)
+static void __exit ebtable_filter_fini(void)
{
int i;
@@ -118,6 +118,6 @@ static void __exit fini(void)
ebt_unregister_table(&frame_filter);
}
-module_init(init);
-module_exit(fini);
+module_init(ebtable_filter_init);
+module_exit(ebtable_filter_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 828cac2cc4a..04dd42efda1 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -98,7 +98,7 @@ static struct nf_hook_ops ebt_ops_nat[] = {
},
};
-static int __init init(void)
+static int __init ebtable_nat_init(void)
{
int i, ret, j;
@@ -116,7 +116,7 @@ cleanup:
return ret;
}
-static void __exit fini(void)
+static void __exit ebtable_nat_fini(void)
{
int i;
@@ -125,6 +125,6 @@ static void __exit fini(void)
ebt_unregister_table(&frame_nat);
}
-module_init(init);
-module_exit(fini);
+module_init(ebtable_nat_init);
+module_exit(ebtable_nat_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 99795336720..3a13ed64345 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -824,14 +824,14 @@ static int translate_table(struct ebt_replace *repl,
if (udc_cnt) {
/* this will get free'd in do_replace()/ebt_register_table()
if an error occurs */
- newinfo->chainstack = (struct ebt_chainstack **)
- vmalloc((highest_possible_processor_id()+1)
- * sizeof(struct ebt_chainstack));
+ newinfo->chainstack =
+ vmalloc((highest_possible_processor_id()+1)
+ * sizeof(*(newinfo->chainstack)));
if (!newinfo->chainstack)
return -ENOMEM;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
newinfo->chainstack[i] =
- vmalloc(udc_cnt * sizeof(struct ebt_chainstack));
+ vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
if (!newinfo->chainstack[i]) {
while (i)
vfree(newinfo->chainstack[--i]);
@@ -841,8 +841,7 @@ static int translate_table(struct ebt_replace *repl,
}
}
- cl_s = (struct ebt_cl_stack *)
- vmalloc(udc_cnt * sizeof(struct ebt_cl_stack));
+ cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
if (!cl_s)
return -ENOMEM;
i = 0; /* the i'th udc */
@@ -901,7 +900,7 @@ static void get_counters(struct ebt_counter *oldcounters,
sizeof(struct ebt_counter) * nentries);
/* add other counters to those of cpu 0 */
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (cpu == 0)
continue;
counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
@@ -944,8 +943,7 @@ static int do_replace(void __user *user, unsigned int len)
countersize = COUNTER_OFFSET(tmp.nentries) *
(highest_possible_processor_id()+1);
- newinfo = (struct ebt_table_info *)
- vmalloc(sizeof(struct ebt_table_info) + countersize);
+ newinfo = vmalloc(sizeof(*newinfo) + countersize);
if (!newinfo)
return -ENOMEM;
@@ -967,8 +965,7 @@ static int do_replace(void __user *user, unsigned int len)
/* the user wants counters back
the check on the size is done later, when we have the lock */
if (tmp.num_counters) {
- counterstmp = (struct ebt_counter *)
- vmalloc(tmp.num_counters * sizeof(struct ebt_counter));
+ counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
if (!counterstmp) {
ret = -ENOMEM;
goto free_entries;
@@ -1036,7 +1033,7 @@ static int do_replace(void __user *user, unsigned int len)
vfree(table->entries);
if (table->chainstack) {
- for_each_cpu(i)
+ for_each_possible_cpu(i)
vfree(table->chainstack[i]);
vfree(table->chainstack);
}
@@ -1054,7 +1051,7 @@ free_counterstmp:
vfree(counterstmp);
/* can be initialized in translate_table() */
if (newinfo->chainstack) {
- for_each_cpu(i)
+ for_each_possible_cpu(i)
vfree(newinfo->chainstack[i]);
vfree(newinfo->chainstack);
}
@@ -1148,8 +1145,7 @@ int ebt_register_table(struct ebt_table *table)
countersize = COUNTER_OFFSET(table->table->nentries) *
(highest_possible_processor_id()+1);
- newinfo = (struct ebt_table_info *)
- vmalloc(sizeof(struct ebt_table_info) + countersize);
+ newinfo = vmalloc(sizeof(*newinfo) + countersize);
ret = -ENOMEM;
if (!newinfo)
return -ENOMEM;
@@ -1201,7 +1197,7 @@ free_unlock:
mutex_unlock(&ebt_mutex);
free_chainstack:
if (newinfo->chainstack) {
- for_each_cpu(i)
+ for_each_possible_cpu(i)
vfree(newinfo->chainstack[i]);
vfree(newinfo->chainstack);
}
@@ -1224,7 +1220,7 @@ void ebt_unregister_table(struct ebt_table *table)
mutex_unlock(&ebt_mutex);
vfree(table->private->entries);
if (table->private->chainstack) {
- for_each_cpu(i)
+ for_each_possible_cpu(i)
vfree(table->private->chainstack[i]);
vfree(table->private->chainstack);
}
@@ -1247,8 +1243,7 @@ static int update_counters(void __user *user, unsigned int len)
if (hlp.num_counters == 0)
return -EINVAL;
- if ( !(tmp = (struct ebt_counter *)
- vmalloc(hlp.num_counters * sizeof(struct ebt_counter))) ){
+ if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
MEMPRINT("Update_counters && nomemory\n");
return -ENOMEM;
}
@@ -1377,8 +1372,7 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user,
BUGPRINT("Num_counters wrong\n");
return -EINVAL;
}
- counterstmp = (struct ebt_counter *)
- vmalloc(nentries * sizeof(struct ebt_counter));
+ counterstmp = vmalloc(nentries * sizeof(*counterstmp));
if (!counterstmp) {
MEMPRINT("Couldn't copy counters, out of memory\n");
return -ENOMEM;
@@ -1487,7 +1481,7 @@ static struct nf_sockopt_ops ebt_sockopts =
.get = do_ebt_get_ctl,
};
-static int __init init(void)
+static int __init ebtables_init(void)
{
int ret;
@@ -1501,7 +1495,7 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ebtables_fini(void)
{
nf_unregister_sockopt(&ebt_sockopts);
printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
@@ -1516,6 +1510,6 @@ EXPORT_SYMBOL(ebt_unregister_watcher);
EXPORT_SYMBOL(ebt_register_target);
EXPORT_SYMBOL(ebt_unregister_target);
EXPORT_SYMBOL(ebt_do_table);
-module_init(init);
-module_exit(fini);
+module_init(ebtables_init);
+module_exit(ebtables_fini);
MODULE_LICENSE("GPL");
diff --git a/net/compat.c b/net/compat.c
index 8fd37cd7b50..d5d69fa15d0 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -476,8 +476,7 @@ asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
int err;
struct socket *sock;
- /* SO_SET_REPLACE seems to be the same in all levels */
- if (optname == IPT_SO_SET_REPLACE)
+ if (level == SOL_IPV6 && optname == IPT_SO_SET_REPLACE)
return do_netfilter_replace(fd, level, optname,
optval, optlen);
diff --git a/net/core/dev.c b/net/core/dev.c
index 8e1dc305122..4fba549caf2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -127,7 +127,7 @@
* sure which should go first, but I bet it won't make much
* difference if we are running VLANs. The good news is that
* this protocol won't be in the list unless compiled in, so
- * the average user (w/out VLANs) will not be adversly affected.
+ * the average user (w/out VLANs) will not be adversely affected.
* --BLG
*
* 0800 IP
@@ -149,7 +149,7 @@ static struct list_head ptype_base[16]; /* 16 way hashed list */
static struct list_head ptype_all; /* Taps */
/*
- * The @dev_base list is protected by @dev_base_lock and the rtln
+ * The @dev_base list is protected by @dev_base_lock and the rtnl
* semaphore.
*
* Pure readers hold dev_base_lock for reading.
@@ -193,7 +193,7 @@ static inline struct hlist_head *dev_index_hash(int ifindex)
* Our notifier list
*/
-static struct notifier_block *netdev_chain;
+static RAW_NOTIFIER_HEAD(netdev_chain);
/*
* Device drivers call our routines to queue packets here. We empty the
@@ -641,10 +641,12 @@ int dev_valid_name(const char *name)
* @name: name format string
*
* Passed a format string - eg "lt%d" it will try and find a suitable
- * id. Not efficient for many devices, not called a lot. The caller
- * must hold the dev_base or rtnl lock while allocating the name and
- * adding the device in order to avoid duplicates. Returns the number
- * of the unit assigned or a negative errno code.
+ * id. It scans list of devices to build up a free map, then chooses
+ * the first empty slot. The caller must hold the dev_base or rtnl lock
+ * while allocating the name and adding the device in order to avoid
+ * duplicates.
+ * Limited to bits_per_byte * page size devices (ie 32K on most platforms).
+ * Returns the number of the unit assigned or a negative errno code.
*/
int dev_alloc_name(struct net_device *dev, const char *name)
@@ -736,21 +738,22 @@ int dev_change_name(struct net_device *dev, char *newname)
if (!err) {
hlist_del(&dev->name_hlist);
hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
- notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
+ raw_notifier_call_chain(&netdev_chain,
+ NETDEV_CHANGENAME, dev);
}
return err;
}
/**
- * netdev_features_change - device changes fatures
+ * netdev_features_change - device changes features
* @dev: device to cause notification
*
* Called to indicate a device has changed features.
*/
void netdev_features_change(struct net_device *dev)
{
- notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev);
+ raw_notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev);
}
EXPORT_SYMBOL(netdev_features_change);
@@ -765,7 +768,8 @@ EXPORT_SYMBOL(netdev_features_change);
void netdev_state_change(struct net_device *dev)
{
if (dev->flags & IFF_UP) {
- notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
+ raw_notifier_call_chain(&netdev_chain,
+ NETDEV_CHANGE, dev);
rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
}
}
@@ -862,7 +866,7 @@ int dev_open(struct net_device *dev)
/*
* ... and announce new interface.
*/
- notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
+ raw_notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
}
return ret;
}
@@ -885,7 +889,7 @@ int dev_close(struct net_device *dev)
* Tell people we are going down, so that they can
* prepare to death, when device is still operating.
*/
- notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
+ raw_notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
dev_deactivate(dev);
@@ -922,7 +926,7 @@ int dev_close(struct net_device *dev)
/*
* Tell people we are down
*/
- notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
+ raw_notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
return 0;
}
@@ -953,7 +957,7 @@ int register_netdevice_notifier(struct notifier_block *nb)
int err;
rtnl_lock();
- err = notifier_chain_register(&netdev_chain, nb);
+ err = raw_notifier_chain_register(&netdev_chain, nb);
if (!err) {
for (dev = dev_base; dev; dev = dev->next) {
nb->notifier_call(nb, NETDEV_REGISTER, dev);
@@ -981,7 +985,7 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
int err;
rtnl_lock();
- err = notifier_chain_unregister(&netdev_chain, nb);
+ err = raw_notifier_chain_unregister(&netdev_chain, nb);
rtnl_unlock();
return err;
}
@@ -992,12 +996,12 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
* @v: pointer passed unmodified to notifier function
*
* Call all network notifier blocks. Parameters and return value
- * are as for notifier_call_chain().
+ * are as for raw_notifier_call_chain().
*/
int call_netdevice_notifiers(unsigned long val, void *v)
{
- return notifier_call_chain(&netdev_chain, val, v);
+ return raw_notifier_call_chain(&netdev_chain, val, v);
}
/* When > 0 there are consumers of rx skb time stamps */
@@ -1078,6 +1082,70 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
rcu_read_unlock();
}
+
+void __netif_schedule(struct net_device *dev)
+{
+ if (!test_and_set_bit(__LINK_STATE_SCHED, &dev->state)) {
+ unsigned long flags;
+ struct softnet_data *sd;
+
+ local_irq_save(flags);
+ sd = &__get_cpu_var(softnet_data);
+ dev->next_sched = sd->output_queue;
+ sd->output_queue = dev;
+ raise_softirq_irqoff(NET_TX_SOFTIRQ);
+ local_irq_restore(flags);
+ }
+}
+EXPORT_SYMBOL(__netif_schedule);
+
+void __netif_rx_schedule(struct net_device *dev)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ dev_hold(dev);
+ list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
+ if (dev->quota < 0)
+ dev->quota += dev->weight;
+ else
+ dev->quota = dev->weight;
+ __raise_softirq_irqoff(NET_RX_SOFTIRQ);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__netif_rx_schedule);
+
+void dev_kfree_skb_any(struct sk_buff *skb)
+{
+ if (in_irq() || irqs_disabled())
+ dev_kfree_skb_irq(skb);
+ else
+ dev_kfree_skb(skb);
+}
+EXPORT_SYMBOL(dev_kfree_skb_any);
+
+
+/* Hot-plugging. */
+void netif_device_detach(struct net_device *dev)
+{
+ if (test_and_clear_bit(__LINK_STATE_PRESENT, &dev->state) &&
+ netif_running(dev)) {
+ netif_stop_queue(dev);
+ }
+}
+EXPORT_SYMBOL(netif_device_detach);
+
+void netif_device_attach(struct net_device *dev)
+{
+ if (!test_and_set_bit(__LINK_STATE_PRESENT, &dev->state) &&
+ netif_running(dev)) {
+ netif_wake_queue(dev);
+ __netdev_watchdog_up(dev);
+ }
+}
+EXPORT_SYMBOL(netif_device_attach);
+
+
/*
* Invalidate hardware checksum when packet is to be mangled, and
* complete checksum manually on outgoing path.
@@ -2130,7 +2198,7 @@ int netdev_set_master(struct net_device *slave, struct net_device *master)
* @dev: device
* @inc: modifier
*
- * Add or remove promsicuity from a device. While the count in the device
+ * Add or remove promiscuity from a device. While the count in the device
* remains above zero the interface remains promiscuous. Once it hits zero
* the device reverts back to normal filtering operation. A negative inc
* value is used to drop promiscuity on the device.
@@ -2242,7 +2310,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
if (dev->flags & IFF_UP &&
((old_flags ^ dev->flags) &~ (IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
IFF_VOLATILE)))
- notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
+ raw_notifier_call_chain(&netdev_chain,
+ NETDEV_CHANGE, dev);
if ((flags ^ dev->gflags) & IFF_PROMISC) {
int inc = (flags & IFF_PROMISC) ? +1 : -1;
@@ -2286,8 +2355,8 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
else
dev->mtu = new_mtu;
if (!err && dev->flags & IFF_UP)
- notifier_call_chain(&netdev_chain,
- NETDEV_CHANGEMTU, dev);
+ raw_notifier_call_chain(&netdev_chain,
+ NETDEV_CHANGEMTU, dev);
return err;
}
@@ -2303,7 +2372,8 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
return -ENODEV;
err = dev->set_mac_address(dev, sa);
if (!err)
- notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
+ raw_notifier_call_chain(&netdev_chain,
+ NETDEV_CHANGEADDR, dev);
return err;
}
@@ -2359,7 +2429,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
return -EINVAL;
memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
- notifier_call_chain(&netdev_chain,
+ raw_notifier_call_chain(&netdev_chain,
NETDEV_CHANGEADDR, dev);
return 0;
@@ -2630,7 +2700,8 @@ int dev_ioctl(unsigned int cmd, void __user *arg)
/* If command is `set a parameter', or
* `get the encoding parameters', check if
* the user has the right to do it */
- if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE) {
+ if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE
+ || cmd == SIOCGIWENCODEEXT) {
if (!capable(CAP_NET_ADMIN))
return -EPERM;
}
@@ -2708,6 +2779,8 @@ int register_netdevice(struct net_device *dev)
BUG_ON(dev_boot_phase);
ASSERT_RTNL();
+ might_sleep();
+
/* When net_device's are persistent, this will be fatal. */
BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
@@ -2794,6 +2867,11 @@ int register_netdevice(struct net_device *dev)
if (!dev->rebuild_header)
dev->rebuild_header = default_rebuild_header;
+ ret = netdev_register_sysfs(dev);
+ if (ret)
+ goto out_err;
+ dev->reg_state = NETREG_REGISTERED;
+
/*
* Default initial state at registry is that the
* device is present.
@@ -2809,14 +2887,11 @@ int register_netdevice(struct net_device *dev)
hlist_add_head(&dev->name_hlist, head);
hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex));
dev_hold(dev);
- dev->reg_state = NETREG_REGISTERING;
write_unlock_bh(&dev_base_lock);
/* Notify protocols, that a new device appeared. */
- notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
+ raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
- /* Finish registration after unlock */
- net_set_todo(dev);
ret = 0;
out:
@@ -2892,7 +2967,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
rtnl_lock();
/* Rebroadcast unregister notification */
- notifier_call_chain(&netdev_chain,
+ raw_notifier_call_chain(&netdev_chain,
NETDEV_UNREGISTER, dev);
if (test_bit(__LINK_STATE_LINKWATCH_PENDING,
@@ -2939,7 +3014,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
*
* We are invoked by rtnl_unlock() after it drops the semaphore.
* This allows us to deal with problems:
- * 1) We can create/delete sysfs objects which invoke hotplug
+ * 1) We can delete sysfs objects which invoke hotplug
* without deadlocking with linkwatch via keventd.
* 2) Since we run with the RTNL semaphore not held, we can sleep
* safely in order to wait for the netdev refcnt to drop to zero.
@@ -2948,8 +3023,6 @@ static DEFINE_MUTEX(net_todo_run_mutex);
void netdev_run_todo(void)
{
struct list_head list = LIST_HEAD_INIT(list);
- int err;
-
/* Need to guard against multiple cpu's getting out of order. */
mutex_lock(&net_todo_run_mutex);
@@ -2972,40 +3045,29 @@ void netdev_run_todo(void)
= list_entry(list.next, struct net_device, todo_list);
list_del(&dev->todo_list);
- switch(dev->reg_state) {
- case NETREG_REGISTERING:
- err = netdev_register_sysfs(dev);
- if (err)
- printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
- dev->name, err);
- dev->reg_state = NETREG_REGISTERED;
- break;
-
- case NETREG_UNREGISTERING:
- netdev_unregister_sysfs(dev);
- dev->reg_state = NETREG_UNREGISTERED;
-
- netdev_wait_allrefs(dev);
+ if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) {
+ printk(KERN_ERR "network todo '%s' but state %d\n",
+ dev->name, dev->reg_state);
+ dump_stack();
+ continue;
+ }
- /* paranoia */
- BUG_ON(atomic_read(&dev->refcnt));
- BUG_TRAP(!dev->ip_ptr);
- BUG_TRAP(!dev->ip6_ptr);
- BUG_TRAP(!dev->dn_ptr);
+ netdev_unregister_sysfs(dev);
+ dev->reg_state = NETREG_UNREGISTERED;
+ netdev_wait_allrefs(dev);
- /* It must be the very last action,
- * after this 'dev' may point to freed up memory.
- */
- if (dev->destructor)
- dev->destructor(dev);
- break;
+ /* paranoia */
+ BUG_ON(atomic_read(&dev->refcnt));
+ BUG_TRAP(!dev->ip_ptr);
+ BUG_TRAP(!dev->ip6_ptr);
+ BUG_TRAP(!dev->dn_ptr);
- default:
- printk(KERN_ERR "network todo '%s' but state %d\n",
- dev->name, dev->reg_state);
- break;
- }
+ /* It must be the very last action,
+ * after this 'dev' may point to freed up memory.
+ */
+ if (dev->destructor)
+ dev->destructor(dev);
}
out:
@@ -3032,12 +3094,11 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name,
alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
- p = kmalloc(alloc_size, GFP_KERNEL);
+ p = kzalloc(alloc_size, GFP_KERNEL);
if (!p) {
printk(KERN_ERR "alloc_dev: Unable to allocate device.\n");
return NULL;
}
- memset(p, 0, alloc_size);
dev = (struct net_device *)
(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
@@ -3063,7 +3124,7 @@ EXPORT_SYMBOL(alloc_netdev);
void free_netdev(struct net_device *dev)
{
#ifdef CONFIG_SYSFS
- /* Compatiablity with error handling in drivers */
+ /* Compatibility with error handling in drivers */
if (dev->reg_state == NETREG_UNINITIALIZED) {
kfree((char *)dev - dev->padded);
return;
@@ -3148,7 +3209,7 @@ int unregister_netdevice(struct net_device *dev)
/* Notify protocols, that we are about to destroy
this device. They should clean all the things.
*/
- notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
+ raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
/*
* Flush the multicast chain
@@ -3279,7 +3340,7 @@ static int __init net_dev_init(void)
* Initialise the packet receive queues.
*/
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
struct softnet_data *queue;
queue = &per_cpu(softnet_data, i);
diff --git a/net/core/dv.c b/net/core/dv.c
index cf581407538..29ee77f1593 100644
--- a/net/core/dv.c
+++ b/net/core/dv.c
@@ -55,15 +55,12 @@ int alloc_divert_blk(struct net_device *dev)
dev->divert = NULL;
if (dev->type == ARPHRD_ETHER) {
- dev->divert = (struct divert_blk *)
- kmalloc(alloc_size, GFP_KERNEL);
+ dev->divert = kzalloc(alloc_size, GFP_KERNEL);
if (dev->divert == NULL) {
printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n",
dev->name);
return -ENOMEM;
}
-
- memset(dev->divert, 0, sizeof(struct divert_blk));
dev_hold(dev);
}
diff --git a/net/core/filter.c b/net/core/filter.c
index 93fbd01d225..5b4486a60cf 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -34,6 +34,7 @@
#include <linux/timer.h>
#include <asm/system.h>
#include <asm/uaccess.h>
+#include <asm/unaligned.h>
#include <linux/filter.h>
/* No hurry in this branch */
@@ -177,7 +178,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int
load_w:
ptr = load_pointer(skb, k, 4, &tmp);
if (ptr != NULL) {
- A = ntohl(*(u32 *)ptr);
+ A = ntohl(get_unaligned((u32 *)ptr));
continue;
}
break;
@@ -186,7 +187,7 @@ load_w:
load_h:
ptr = load_pointer(skb, k, 2, &tmp);
if (ptr != NULL) {
- A = ntohs(*(u16 *)ptr);
+ A = ntohs(get_unaligned((u16 *)ptr));
continue;
}
break;
diff --git a/net/core/flow.c b/net/core/flow.c
index 55789f832ed..2191af5f26a 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -79,7 +79,7 @@ static void flow_cache_new_hashrnd(unsigned long arg)
{
int i;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
flow_hash_rnd_recalc(i) = 1;
flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
@@ -318,12 +318,10 @@ static void __devinit flow_cache_cpu_prepare(int cpu)
/* NOTHING */;
flow_table(cpu) = (struct flow_cache_entry **)
- __get_free_pages(GFP_KERNEL, order);
+ __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
if (!flow_table(cpu))
panic("NET: failed to allocate flow cache order %lu\n", order);
- memset(flow_table(cpu), 0, PAGE_SIZE << order);
-
flow_hash_rnd_recalc(cpu) = 1;
flow_count(cpu) = 0;
@@ -363,7 +361,7 @@ static int __init flow_cache_init(void)
flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
add_timer(&flow_hash_rnd_timer);
- for_each_cpu(i)
+ for_each_possible_cpu(i)
flow_cache_cpu_prepare(i);
hotcpu_notifier(flow_cache_cpu, 0);
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index b07c029e821..3cad026764f 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -159,11 +159,10 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
if (parm->interval < -2 || parm->interval > 3)
return -EINVAL;
- est = kmalloc(sizeof(*est), GFP_KERNEL);
+ est = kzalloc(sizeof(*est), GFP_KERNEL);
if (est == NULL)
return -ENOBUFS;
- memset(est, 0, sizeof(*est));
est->interval = parm->interval + 2;
est->bstats = bstats;
est->rate_est = rate_est;
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index 341de44c7ed..646937cc2d8 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -170,13 +170,13 @@ void linkwatch_fire_event(struct net_device *dev)
spin_unlock_irqrestore(&lweventlist_lock, flags);
if (!test_and_set_bit(LW_RUNNING, &linkwatch_flags)) {
- unsigned long thisevent = jiffies;
+ unsigned long delay = linkwatch_nextevent - jiffies;
- if (thisevent >= linkwatch_nextevent) {
+ /* If we wrap around we'll delay it by at most HZ. */
+ if (!delay || delay > HZ)
schedule_work(&linkwatch_work);
- } else {
- schedule_delayed_work(&linkwatch_work, linkwatch_nextevent - thisevent);
- }
+ else
+ schedule_delayed_work(&linkwatch_work, delay);
}
}
}
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 0c8666872d1..50a8c73caf9 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -284,14 +284,11 @@ static struct neighbour **neigh_hash_alloc(unsigned int entries)
struct neighbour **ret;
if (size <= PAGE_SIZE) {
- ret = kmalloc(size, GFP_ATOMIC);
+ ret = kzalloc(size, GFP_ATOMIC);
} else {
ret = (struct neighbour **)
- __get_free_pages(GFP_ATOMIC, get_order(size));
+ __get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size));
}
- if (ret)
- memset(ret, 0, size);
-
return ret;
}
@@ -1089,8 +1086,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
if (hh->hh_type == protocol)
break;
- if (!hh && (hh = kmalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
- memset(hh, 0, sizeof(struct hh_cache));
+ if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
rwlock_init(&hh->hh_lock);
hh->hh_type = protocol;
atomic_set(&hh->hh_refcnt, 0);
@@ -1330,8 +1326,7 @@ void neigh_parms_destroy(struct neigh_parms *parms)
kfree(parms);
}
-
-void neigh_table_init(struct neigh_table *tbl)
+void neigh_table_init_no_netlink(struct neigh_table *tbl)
{
unsigned long now = jiffies;
unsigned long phsize;
@@ -1366,13 +1361,11 @@ void neigh_table_init(struct neigh_table *tbl)
tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
- tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL);
+ tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
if (!tbl->hash_buckets || !tbl->phash_buckets)
panic("cannot allocate neighbour cache hashes");
- memset(tbl->phash_buckets, 0, phsize);
-
get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
rwlock_init(&tbl->lock);
@@ -1389,10 +1382,27 @@ void neigh_table_init(struct neigh_table *tbl)
tbl->last_flush = now;
tbl->last_rand = now + tbl->parms.reachable_time * 20;
+}
+
+void neigh_table_init(struct neigh_table *tbl)
+{
+ struct neigh_table *tmp;
+
+ neigh_table_init_no_netlink(tbl);
write_lock(&neigh_tbl_lock);
+ for (tmp = neigh_tables; tmp; tmp = tmp->next) {
+ if (tmp->family == tbl->family)
+ break;
+ }
tbl->next = neigh_tables;
neigh_tables = tbl;
write_unlock(&neigh_tbl_lock);
+
+ if (unlikely(tmp)) {
+ printk(KERN_ERR "NEIGH: Registering multiple tables for "
+ "family %d\n", tbl->family);
+ dump_stack();
+ }
}
int neigh_table_clear(struct neigh_table *tbl)
@@ -1633,7 +1643,7 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
memset(&ndst, 0, sizeof(ndst));
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct neigh_statistics *st;
st = per_cpu_ptr(tbl->stats, cpu);
@@ -2663,6 +2673,7 @@ EXPORT_SYMBOL(neigh_rand_reach_time);
EXPORT_SYMBOL(neigh_resolve_output);
EXPORT_SYMBOL(neigh_table_clear);
EXPORT_SYMBOL(neigh_table_init);
+EXPORT_SYMBOL(neigh_table_init_no_netlink);
EXPORT_SYMBOL(neigh_update);
EXPORT_SYMBOL(neigh_update_hhs);
EXPORT_SYMBOL(pneigh_enqueue);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 21b68464cab..47a6fceb677 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -29,7 +29,7 @@ static const char fmt_ulong[] = "%lu\n";
static inline int dev_isalive(const struct net_device *dev)
{
- return dev->reg_state == NETREG_REGISTERED;
+ return dev->reg_state <= NETREG_REGISTERED;
}
/* use same locking rules as GIF* ioctl's */
@@ -165,7 +165,7 @@ static ssize_t show_operstate(struct class_device *dev, char *buf)
operstate = IF_OPER_DOWN;
read_unlock(&dev_base_lock);
- if (operstate >= sizeof(operstates))
+ if (operstate >= ARRAY_SIZE(operstates))
return -EINVAL; /* should not happen */
return sprintf(buf, "%s\n", operstates[operstate]);
@@ -445,58 +445,33 @@ static struct class net_class = {
void netdev_unregister_sysfs(struct net_device * net)
{
- struct class_device * class_dev = &(net->class_dev);
-
- if (net->get_stats)
- sysfs_remove_group(&class_dev->kobj, &netstat_group);
-
-#ifdef WIRELESS_EXT
- if (net->get_wireless_stats || (net->wireless_handlers &&
- net->wireless_handlers->get_wireless_stats))
- sysfs_remove_group(&class_dev->kobj, &wireless_group);
-#endif
- class_device_del(class_dev);
-
+ class_device_del(&(net->class_dev));
}
/* Create sysfs entries for network device. */
int netdev_register_sysfs(struct net_device *net)
{
struct class_device *class_dev = &(net->class_dev);
- int ret;
+ struct attribute_group **groups = net->sysfs_groups;
+ class_device_initialize(class_dev);
class_dev->class = &net_class;
class_dev->class_data = net;
+ class_dev->groups = groups;
+ BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ);
strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE);
- if ((ret = class_device_register(class_dev)))
- goto out;
- if (net->get_stats &&
- (ret = sysfs_create_group(&class_dev->kobj, &netstat_group)))
- goto out_unreg;
+ if (net->get_stats)
+ *groups++ = &netstat_group;
#ifdef WIRELESS_EXT
- if (net->get_wireless_stats || (net->wireless_handlers &&
- net->wireless_handlers->get_wireless_stats)) {
- ret = sysfs_create_group(&class_dev->kobj, &wireless_group);
- if (ret)
- goto out_cleanup;
- }
- return 0;
-out_cleanup:
- if (net->get_stats)
- sysfs_remove_group(&class_dev->kobj, &netstat_group);
-#else
- return 0;
+ if (net->get_wireless_stats
+ || (net->wireless_handlers && net->wireless_handlers->get_wireless_stats))
+ *groups++ = &wireless_group;
#endif
-out_unreg:
- printk(KERN_WARNING "%s: sysfs attribute registration failed %d\n",
- net->name, ret);
- class_device_unregister(class_dev);
-out:
- return ret;
+ return class_device_add(class_dev);
}
int netdev_sysfs_init(void)
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index 98f0fc923f9..79ebd75fbe4 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -38,20 +38,18 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
{
const int lopt_size = sizeof(struct listen_sock) +
nr_table_entries * sizeof(struct request_sock *);
- struct listen_sock *lopt = kmalloc(lopt_size, GFP_KERNEL);
+ struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL);
if (lopt == NULL)
return -ENOMEM;
- memset(lopt, 0, lopt_size);
-
for (lopt->max_qlen_log = 6;
(1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
lopt->max_qlen_log++);
get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd));
rwlock_init(&queue->syn_wait_lock);
- queue->rskq_accept_head = queue->rskq_accept_head = NULL;
+ queue->rskq_accept_head = NULL;
lopt->nr_table_entries = nr_table_entries;
write_lock_bh(&queue->syn_wait_lock);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 09464fa8d72..fb3770f9c09 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -112,6 +112,14 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
BUG();
}
+void skb_truesize_bug(struct sk_buff *skb)
+{
+ printk(KERN_ERR "SKB BUG: Invalid truesize (%u) "
+ "len=%u, sizeof(sk_buff)=%Zd\n",
+ skb->truesize, skb->len, sizeof(struct sk_buff));
+}
+EXPORT_SYMBOL(skb_truesize_bug);
+
/* Allocate a new skbuff. We do this ourselves so we can fill in a few
* 'private' fields and also do memory statistics to find all the
* [BEEP] leaks.
diff --git a/net/core/sock.c b/net/core/sock.c
index e110b900414..ed2afdb9ea2 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -187,6 +187,99 @@ static void sock_disable_timestamp(struct sock *sk)
}
+int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+ int err = 0;
+ int skb_len;
+
+ /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
+ number of warnings when compiling with -W --ANK
+ */
+ if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
+ (unsigned)sk->sk_rcvbuf) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* It would be deadlock, if sock_queue_rcv_skb is used
+ with socket lock! We assume that users of this
+ function are lock free.
+ */
+ err = sk_filter(sk, skb, 1);
+ if (err)
+ goto out;
+
+ skb->dev = NULL;
+ skb_set_owner_r(skb, sk);
+
+ /* Cache the SKB length before we tack it onto the receive
+ * queue. Once it is added it no longer belongs to us and
+ * may be freed by other threads of control pulling packets
+ * from the queue.
+ */
+ skb_len = skb->len;
+
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_data_ready(sk, skb_len);
+out:
+ return err;
+}
+EXPORT_SYMBOL(sock_queue_rcv_skb);
+
+int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = NET_RX_SUCCESS;
+
+ if (sk_filter(sk, skb, 0))
+ goto discard_and_relse;
+
+ skb->dev = NULL;
+
+ bh_lock_sock(sk);
+ if (!sock_owned_by_user(sk))
+ rc = sk->sk_backlog_rcv(sk, skb);
+ else
+ sk_add_backlog(sk, skb);
+ bh_unlock_sock(sk);
+out:
+ sock_put(sk);
+ return rc;
+discard_and_relse:
+ kfree_skb(skb);
+ goto out;
+}
+EXPORT_SYMBOL(sk_receive_skb);
+
+struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie)
+{
+ struct dst_entry *dst = sk->sk_dst_cache;
+
+ if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
+ sk->sk_dst_cache = NULL;
+ dst_release(dst);
+ return NULL;
+ }
+
+ return dst;
+}
+EXPORT_SYMBOL(__sk_dst_check);
+
+struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie)
+{
+ struct dst_entry *dst = sk_dst_get(sk);
+
+ if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
+ sk_dst_reset(sk);
+ dst_release(dst);
+ return NULL;
+ }
+
+ return dst;
+}
+EXPORT_SYMBOL(sk_dst_check);
+
/*
* This is meant for all protocols to use and covers goings on
* at the socket level. Everything here is generic.
@@ -292,7 +385,21 @@ set_sndbuf:
val = sysctl_rmem_max;
set_rcvbuf:
sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
- /* FIXME: is this lower bound the right one? */
+ /*
+ * We double it on the way in to account for
+ * "struct sk_buff" etc. overhead. Applications
+ * assume that the SO_RCVBUF setting they make will
+ * allow that much actual data to be received on that
+ * socket.
+ *
+ * Applications are unaware that "struct sk_buff" and
+ * other overheads allocate from the receive buffer
+ * during socket buffer allocation.
+ *
+ * And after considering the possible alternatives,
+ * returning the value we actually used in getsockopt
+ * is the most desirable behavior.
+ */
if ((val * 2) < SOCK_MIN_RCVBUF)
sk->sk_rcvbuf = SOCK_MIN_RCVBUF;
else
diff --git a/net/core/stream.c b/net/core/stream.c
index 35e25259fd9..e9489696f69 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -176,6 +176,7 @@ void sk_stream_rfree(struct sk_buff *skb)
{
struct sock *sk = skb->sk;
+ skb_truesize_check(skb);
atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
sk->sk_forward_alloc += skb->truesize;
}
diff --git a/net/core/utils.c b/net/core/utils.c
index fdc4f38bc46..4f96f389243 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -121,7 +121,7 @@ void __init net_random_init(void)
{
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
struct nrnd_state *state = &per_cpu(net_rand_state,i);
__net_srandom(state, i+jiffies);
}
@@ -133,7 +133,7 @@ static int net_random_reseed(void)
unsigned long seed[NR_CPUS];
get_random_bytes(seed, sizeof(seed));
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
struct nrnd_state *state = &per_cpu(net_rand_state,i);
__net_srandom(state, seed[i]);
}
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 81d6995fcfd..d2bc72d318f 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -1726,6 +1726,14 @@ int wireless_rtnetlink_get(struct net_device * dev,
if(!IW_IS_GET(request->cmd))
return -EOPNOTSUPP;
+ /* If command is `get the encoding parameters', check if
+ * the user has the right to do it */
+ if (request->cmd == SIOCGIWENCODE ||
+ request->cmd == SIOCGIWENCODEEXT) {
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ }
+
/* Special cases */
if(request->cmd == SIOCGIWSTATS)
/* Get Wireless Stats */
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
index b5981e5f6b0..8c211c58893 100644
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -452,6 +452,7 @@ found:
(unsigned long long)
avr->dccpavr_ack_ackno);
dccp_ackvec_throw_record(av, avr);
+ break;
}
/*
* If it wasn't received, continue scanning... we might
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index e3dd30d36c8..b39e2a59788 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -204,7 +204,7 @@ static int dccp_feat_reconcile(struct sock *sk, struct dccp_opt_pend *opt,
if (rc) {
kfree(opt->dccpop_sc->dccpoc_val);
kfree(opt->dccpop_sc);
- opt->dccpop_sc = 0;
+ opt->dccpop_sc = NULL;
return rc;
}
@@ -322,7 +322,7 @@ static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk,
opt->dccpop_type = type == DCCPO_CHANGE_L ? DCCPO_CONFIRM_R :
DCCPO_CONFIRM_L;
opt->dccpop_feat = feature;
- opt->dccpop_val = 0;
+ opt->dccpop_val = NULL;
opt->dccpop_len = 0;
/* change feature */
@@ -523,7 +523,7 @@ int dccp_feat_clone(struct sock *oldsk, struct sock *newsk)
* once...
*/
/* the master socket no longer needs to worry about confirms */
- opt->dccpop_sc = 0; /* it's not a memleak---new socket has it */
+ opt->dccpop_sc = NULL; /* it's not a memleak---new socket has it */
/* reset state for a new socket */
opt->dccpop_conf = 0;
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 29047995c69..f2c011fd2ba 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -498,7 +498,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
goto drop;
if (dccp_parse_options(sk, skb))
- goto drop;
+ goto drop_and_free;
dccp_openreq_init(req, &dp, skb);
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 1ff7328b0e1..2e0ee8355c4 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -848,6 +848,7 @@ static int dccp_close_state(struct sock *sk)
void dccp_close(struct sock *sk, long timeout)
{
struct sk_buff *skb;
+ int state;
lock_sock(sk);
@@ -882,6 +883,11 @@ void dccp_close(struct sock *sk, long timeout)
sk_stream_wait_close(sk, timeout);
adjudge_to_death:
+ state = sk->sk_state;
+ sock_hold(sk);
+ sock_orphan(sk);
+ atomic_inc(sk->sk_prot->orphan_count);
+
/*
* It is the last release_sock in its life. It will remove backlog.
*/
@@ -894,8 +900,9 @@ adjudge_to_death:
bh_lock_sock(sk);
BUG_TRAP(!sock_owned_by_user(sk));
- sock_hold(sk);
- sock_orphan(sk);
+ /* Have we already been destroyed by a softirq or backlog? */
+ if (state != DCCP_CLOSED && sk->sk_state == DCCP_CLOSED)
+ goto out;
/*
* The last release_sock may have processed the CLOSE or RESET
@@ -915,12 +922,12 @@ adjudge_to_death:
#endif
}
- atomic_inc(sk->sk_prot->orphan_count);
if (sk->sk_state == DCCP_CLOSED)
inet_csk_destroy_sock(sk);
/* Otherwise, socket is reprieved until protocol close. */
+out:
bh_unlock_sock(sk);
local_bh_enable();
sock_put(sk);
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index cc7b9d9255e..a26ff9f4457 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -68,7 +68,7 @@ __le16 decnet_address = 0;
static DEFINE_RWLOCK(dndev_lock);
static struct net_device *decnet_default_device;
-static struct notifier_block *dnaddr_chain;
+static BLOCKING_NOTIFIER_HEAD(dnaddr_chain);
static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
static void dn_dev_delete(struct net_device *dev);
@@ -446,7 +446,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de
}
rtmsg_ifa(RTM_DELADDR, ifa1);
- notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
+ blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
if (destroy) {
dn_dev_free_ifa(ifa1);
@@ -481,7 +481,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
dn_db->ifa_list = ifa;
rtmsg_ifa(RTM_NEWADDR, ifa);
- notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
+ blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
return 0;
}
@@ -620,7 +620,7 @@ int dn_dev_set_default(struct net_device *dev, int force)
}
write_unlock(&dndev_lock);
if (old)
- dev_put(dev);
+ dev_put(old);
return rv;
}
@@ -1285,12 +1285,12 @@ void dn_dev_devices_on(void)
int register_dnaddr_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&dnaddr_chain, nb);
+ return blocking_notifier_chain_register(&dnaddr_chain, nb);
}
int unregister_dnaddr_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&dnaddr_chain, nb);
+ return blocking_notifier_chain_unregister(&dnaddr_chain, nb);
}
#ifdef CONFIG_PROC_FS
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 7c8692c26bf..66e230c3b32 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -493,7 +493,6 @@ struct elist_cb_state {
static void neigh_elist_cb(struct neighbour *neigh, void *_info)
{
struct elist_cb_state *s = _info;
- struct dn_dev *dn_db;
struct dn_neigh *dn;
if (neigh->dev != s->dev)
@@ -503,10 +502,6 @@ static void neigh_elist_cb(struct neighbour *neigh, void *_info)
if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
return;
- dn_db = (struct dn_dev *) s->dev->dn_ptr;
- if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2))
- return;
-
if (s->t == s->n)
s->rs = dn_find_slot(s->ptr, s->n, dn->priority);
else
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 16a5a31e212..74133ecd770 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -133,7 +133,7 @@ static struct nf_hook_ops dnrmg_ops = {
.priority = NF_DN_PRI_DNRTMSG,
};
-static int __init init(void)
+static int __init dn_rtmsg_init(void)
{
int rv = 0;
@@ -152,7 +152,7 @@ static int __init init(void)
return rv;
}
-static void __exit fini(void)
+static void __exit dn_rtmsg_fini(void)
{
nf_unregister_hook(&dnrmg_ops);
sock_release(dnrmg->sk_socket);
@@ -164,6 +164,6 @@ MODULE_AUTHOR("Steven Whitehouse <steve@chygwyn.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_DNRTMSG);
-module_init(init);
-module_exit(fini);
+module_init(dn_rtmsg_init);
+module_exit(dn_rtmsg_fini);
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index c792994d795..868265619db 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -42,6 +42,7 @@
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <linux/bitops.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -49,6 +50,7 @@
static const struct proto_ops econet_ops;
static struct hlist_head econet_sklist;
static DEFINE_RWLOCK(econet_lock);
+static DEFINE_MUTEX(econet_mutex);
/* Since there are only 256 possible network numbers (or fewer, depends
how you count) it makes sense to use a simple lookup table. */
@@ -124,6 +126,8 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
msg->msg_namelen = sizeof(struct sockaddr_ec);
+ mutex_lock(&econet_mutex);
+
/*
* Call the generic datagram receiver. This handles all sorts
* of horrible races and re-entrancy so we can forget about it
@@ -174,6 +178,7 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
out_free:
skb_free_datagram(sk, skb);
out:
+ mutex_unlock(&econet_mutex);
return err;
}
@@ -184,8 +189,8 @@ out:
static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
- struct sock *sk=sock->sk;
- struct econet_sock *eo = ec_sk(sk);
+ struct sock *sk;
+ struct econet_sock *eo;
/*
* Check legality
@@ -195,11 +200,18 @@ static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
sec->sec_family != AF_ECONET)
return -EINVAL;
+ mutex_lock(&econet_mutex);
+
+ sk = sock->sk;
+ eo = ec_sk(sk);
+
eo->cb = sec->cb;
eo->port = sec->port;
eo->station = sec->addr.station;
eo->net = sec->addr.net;
+ mutex_unlock(&econet_mutex);
+
return 0;
}
@@ -284,6 +296,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
* Get and verify the address.
*/
+ mutex_lock(&econet_mutex);
+
if (saddr == NULL) {
struct econet_sock *eo = ec_sk(sk);
@@ -292,8 +306,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
port = eo->port;
cb = eo->cb;
} else {
- if (msg->msg_namelen < sizeof(struct sockaddr_ec))
+ if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
+ mutex_unlock(&econet_mutex);
return -EINVAL;
+ }
addr.station = saddr->addr.station;
addr.net = saddr->addr.net;
port = saddr->port;
@@ -304,19 +320,21 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
dev = net2dev_map[addr.net];
/* If not directly reachable, use some default */
- if (dev == NULL)
- {
+ if (dev == NULL) {
dev = net2dev_map[0];
/* No interfaces at all? */
- if (dev == NULL)
+ if (dev == NULL) {
+ mutex_unlock(&econet_mutex);
return -ENETDOWN;
+ }
}
- if (len + 15 > dev->mtu)
+ if (len + 15 > dev->mtu) {
+ mutex_unlock(&econet_mutex);
return -EMSGSIZE;
+ }
- if (dev->type == ARPHRD_ECONET)
- {
+ if (dev->type == ARPHRD_ECONET) {
/* Real hardware Econet. We're not worthy etc. */
#ifdef CONFIG_ECONET_NATIVE
unsigned short proto = 0;
@@ -374,6 +392,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
dev_queue_xmit(skb);
dev_put(dev);
+ mutex_unlock(&econet_mutex);
return(len);
out_free:
@@ -384,14 +403,18 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
#else
err = -EPROTOTYPE;
#endif
+ mutex_unlock(&econet_mutex);
+
return err;
}
#ifdef CONFIG_ECONET_AUNUDP
/* AUN virtual Econet. */
- if (udpsock == NULL)
+ if (udpsock == NULL) {
+ mutex_unlock(&econet_mutex);
return -ENETDOWN; /* No socket - can't send */
+ }
/* Make up a UDP datagram and hand it off to some higher intellect. */
@@ -438,8 +461,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
void __user *base = msg->msg_iov[i].iov_base;
size_t len = msg->msg_iov[i].iov_len;
/* Check it now since we switch to KERNEL_DS later. */
- if (!access_ok(VERIFY_READ, base, len))
+ if (!access_ok(VERIFY_READ, base, len)) {
+ mutex_unlock(&econet_mutex);
return -EFAULT;
+ }
iov[i+1].iov_base = base;
iov[i+1].iov_len = len;
size += len;
@@ -447,8 +472,11 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
/* Get a skbuff (no data, just holds our cb information) */
if ((skb = sock_alloc_send_skb(sk, 0,
- msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)
+ msg->msg_flags & MSG_DONTWAIT,
+ &err)) == NULL) {
+ mutex_unlock(&econet_mutex);
return err;
+ }
eb = (struct ec_cb *)&skb->cb;
@@ -475,6 +503,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
#else
err = -EPROTOTYPE;
#endif
+ mutex_unlock(&econet_mutex);
+
return err;
}
@@ -485,18 +515,25 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
- struct sock *sk = sock->sk;
- struct econet_sock *eo = ec_sk(sk);
+ struct sock *sk;
+ struct econet_sock *eo;
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
if (peer)
return -EOPNOTSUPP;
+ mutex_lock(&econet_mutex);
+
+ sk = sock->sk;
+ eo = ec_sk(sk);
+
sec->sec_family = AF_ECONET;
sec->port = eo->port;
sec->addr.station = eo->station;
sec->addr.net = eo->net;
+ mutex_unlock(&econet_mutex);
+
*uaddr_len = sizeof(*sec);
return 0;
}
@@ -522,10 +559,13 @@ static void econet_destroy_timer(unsigned long data)
static int econet_release(struct socket *sock)
{
- struct sock *sk = sock->sk;
+ struct sock *sk;
+ mutex_lock(&econet_mutex);
+
+ sk = sock->sk;
if (!sk)
- return 0;
+ goto out_unlock;
econet_remove_socket(&econet_sklist, sk);
@@ -549,10 +589,14 @@ static int econet_release(struct socket *sock)
sk->sk_timer.expires = jiffies + HZ;
sk->sk_timer.function = econet_destroy_timer;
add_timer(&sk->sk_timer);
- return 0;
+
+ goto out_unlock;
}
sk_free(sk);
+
+out_unlock:
+ mutex_unlock(&econet_mutex);
return 0;
}
@@ -608,6 +652,7 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
struct ec_device *edev;
struct net_device *dev;
struct sockaddr_ec *sec;
+ int err;
/*
* Fetch the caller's info block into kernel space
@@ -621,38 +666,35 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
sec = (struct sockaddr_ec *)&ifr.ifr_addr;
- switch (cmd)
- {
+ mutex_lock(&econet_mutex);
+
+ err = 0;
+ switch (cmd) {
case SIOCSIFADDR:
edev = dev->ec_ptr;
- if (edev == NULL)
- {
+ if (edev == NULL) {
/* Magic up a new one. */
edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL);
if (edev == NULL) {
- printk("af_ec: memory squeeze.\n");
- dev_put(dev);
- return -ENOMEM;
+ err = -ENOMEM;
+ break;
}
memset(edev, 0, sizeof(struct ec_device));
dev->ec_ptr = edev;
- }
- else
+ } else
net2dev_map[edev->net] = NULL;
edev->station = sec->addr.station;
edev->net = sec->addr.net;
net2dev_map[sec->addr.net] = dev;
if (!net2dev_map[0])
net2dev_map[0] = dev;
- dev_put(dev);
- return 0;
+ break;
case SIOCGIFADDR:
edev = dev->ec_ptr;
- if (edev == NULL)
- {
- dev_put(dev);
- return -ENODEV;
+ if (edev == NULL) {
+ err = -ENODEV;
+ break;
}
memset(sec, 0, sizeof(struct sockaddr_ec));
sec->addr.station = edev->station;
@@ -660,12 +702,19 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
sec->sec_family = AF_ECONET;
dev_put(dev);
if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- return -EFAULT;
- return 0;
+ err = -EFAULT;
+ break;
+
+ default:
+ err = -EINVAL;
+ break;
}
+ mutex_unlock(&econet_mutex);
+
dev_put(dev);
- return -EINVAL;
+
+ return err;
}
/*
@@ -699,7 +748,7 @@ static struct net_proto_family econet_family_ops = {
.owner = THIS_MODULE,
};
-static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
+static const struct proto_ops econet_ops = {
.family = PF_ECONET,
.owner = THIS_MODULE,
.release = econet_release,
@@ -720,9 +769,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
.sendpage = sock_no_sendpage,
};
-#include <linux/smp_lock.h>
-SOCKOPS_WRAP(econet, PF_ECONET);
-
#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
/*
* Find the listening socket, if any, for the given data.
diff --git a/net/ethernet/Makefile b/net/ethernet/Makefile
index 69b74a9a0fc..7cef1d8ace2 100644
--- a/net/ethernet/Makefile
+++ b/net/ethernet/Makefile
@@ -3,6 +3,5 @@
#
obj-y += eth.o
-obj-$(CONFIG_SYSCTL) += sysctl_net_ether.o
obj-$(subst m,y,$(CONFIG_IPX)) += pe2.o
obj-$(subst m,y,$(CONFIG_ATALK)) += pe2.o
diff --git a/net/ethernet/sysctl_net_ether.c b/net/ethernet/sysctl_net_ether.c
deleted file mode 100644
index 66b39fc342d..00000000000
--- a/net/ethernet/sysctl_net_ether.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/* -*- linux-c -*-
- * sysctl_net_ether.c: sysctl interface to net Ethernet subsystem.
- *
- * Begun April 1, 1996, Mike Shaver.
- * Added /proc/sys/net/ether directory entry (empty =) ). [MS]
- */
-
-#include <linux/mm.h>
-#include <linux/sysctl.h>
-#include <linux/if_ether.h>
-
-ctl_table ether_table[] = {
- {0}
-};
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index af7f9bbfd18..b885fd18940 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -42,7 +42,7 @@ static const char *ieee80211_modes[] = {
};
#define MAX_CUSTOM_LEN 64
-static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
+static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
char *start, char *stop,
struct ieee80211_network *network)
{
@@ -274,7 +274,7 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
if (ieee->scan_age == 0 ||
time_after(network->last_scanned + ieee->scan_age, jiffies))
- ev = ipw2100_translate_scan(ieee, ev, stop, network);
+ ev = ieee80211_translate_scan(ieee, ev, stop, network);
else
IEEE80211_DEBUG_SCAN("Not showing network '%s ("
MAC_FMT ")' due to age (%dms).\n",
diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
index 6cd9f3427be..f2a27cc6ecb 100644
--- a/net/ieee80211/softmac/Kconfig
+++ b/net/ieee80211/softmac/Kconfig
@@ -1,6 +1,7 @@
config IEEE80211_SOFTMAC
tristate "Software MAC add-on to the IEEE 802.11 networking stack"
depends on IEEE80211 && EXPERIMENTAL
+ select WIRELESS_EXT
---help---
This option enables the hardware independent software MAC addon
for the IEEE 802.11 networking stack.
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index be61de78dfa..57ea9f6f465 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -51,11 +51,12 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.associating = 1;
mac->associated = 0; /* just to make sure */
- spin_unlock_irqrestore(&mac->lock, flags);
/* Set a timer for timeout */
/* FIXME: make timeout configurable */
- schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ);
+ if (likely(mac->running))
+ schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ);
+ spin_unlock_irqrestore(&mac->lock, flags);
}
void
@@ -101,6 +102,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason)
/* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
mac->associated = 0;
mac->associnfo.associating = 0;
+ ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
spin_unlock_irqrestore(&mac->lock, flags);
}
@@ -143,6 +145,12 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne
if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len))
return 0;
+ /* assume that users know what they're doing ...
+ * (note we don't let them select a net we're incompatible with) */
+ if (mac->associnfo.bssfixed) {
+ return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN);
+ }
+
/* if 'ANY' network requested, take any that doesn't have privacy enabled */
if (mac->associnfo.req_essid.len == 0
&& !(net->capability & WLAN_CAPABILITY_PRIVACY))
@@ -175,7 +183,7 @@ ieee80211softmac_assoc_work(void *d)
ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
/* try to find the requested network in our list, if we found one already */
- if (mac->associnfo.bssvalid)
+ if (mac->associnfo.bssvalid || mac->associnfo.bssfixed)
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
/* Search the ieee80211 networks for this network if we didn't find it by bssid,
@@ -240,19 +248,25 @@ ieee80211softmac_assoc_work(void *d)
if (ieee80211softmac_start_scan(mac))
dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
return;
- }
- else {
+ } else {
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.associating = 0;
mac->associated = 0;
spin_unlock_irqrestore(&mac->lock, flags);
dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
+ /* reset the retry counter for the next user request since we
+ * break out and don't reschedule ourselves after this point. */
+ mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
return;
}
}
-
+
+ /* reset the retry counter for the next user request since we
+ * now found a net and will try to associate to it, but not
+ * schedule this function again. */
+ mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
mac->associnfo.bssvalid = 1;
memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN);
/* copy the ESSID for displaying it */
@@ -306,6 +320,9 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
u16 status = le16_to_cpup(&resp->status);
struct ieee80211softmac_network *network = NULL;
unsigned long flags;
+
+ if (unlikely(!mac->running))
+ return -ENODEV;
spin_lock_irqsave(&mac->lock, flags);
@@ -364,15 +381,22 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
{
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
unsigned long flags;
+
+ if (unlikely(!mac->running))
+ return -ENODEV;
+
if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN))
return 0;
+
if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN))
return 0;
+
dprintk(KERN_INFO PFX "got disassoc frame\n");
netif_carrier_off(dev);
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.bssvalid = 0;
mac->associated = 0;
+ ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
schedule_work(&mac->associnfo.work);
spin_unlock_irqrestore(&mac->lock, flags);
@@ -386,11 +410,15 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev,
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
struct ieee80211softmac_network *network;
+ if (unlikely(!mac->running))
+ return -ENODEV;
+
network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3);
if (!network) {
dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
return 0;
}
- ieee80211softmac_assoc(mac, network);
+ schedule_work(&mac->associnfo.work);
+
return 0;
}
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
index 9a0eac6c61e..06e33262466 100644
--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
+++ b/net/ieee80211/softmac/ieee80211softmac_auth.c
@@ -86,6 +86,11 @@ ieee80211softmac_auth_queue(void *data)
/* Lock and set flags */
spin_lock_irqsave(&mac->lock, flags);
+ if (unlikely(!mac->running)) {
+ /* Prevent reschedule on workqueue flush */
+ spin_unlock_irqrestore(&mac->lock, flags);
+ return;
+ }
net->authenticated = 0;
net->authenticating = 1;
/* add a timeout call so we eventually give up waiting for an auth reply */
@@ -124,6 +129,9 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
unsigned long flags;
u8 * data;
+ if (unlikely(!mac->running))
+ return -ENODEV;
+
/* Find correct auth queue item */
spin_lock_irqsave(&mac->lock, flags);
list_for_each(list_ptr, &mac->auth_queue) {
@@ -298,8 +306,6 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
/* can't transmit data right now... */
netif_carrier_off(mac->dev);
- /* let's try to re-associate */
- schedule_work(&mac->associnfo.work);
spin_unlock_irqrestore(&mac->lock, flags);
}
@@ -338,6 +344,9 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
struct ieee80211softmac_network *net = NULL;
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+ if (unlikely(!mac->running))
+ return -ENODEV;
+
if (!deauth) {
dprintk("deauth without deauth packet. eek!\n");
return 0;
@@ -360,5 +369,8 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
}
ieee80211softmac_deauth_from_net(mac, net);
+
+ /* let's try to re-associate */
+ schedule_work(&mac->associnfo.work);
return 0;
}
diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
index 0a52bbda1e4..8cc8f3f0f8e 100644
--- a/net/ieee80211/softmac/ieee80211softmac_event.c
+++ b/net/ieee80211/softmac/ieee80211softmac_event.c
@@ -67,6 +67,7 @@ static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
"authenticating failed",
"authenticating timed out",
"associating failed because no suitable network was found",
+ "disassociated",
};
@@ -128,13 +129,42 @@ void
ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
{
struct ieee80211softmac_event *eventptr, *tmp;
- union iwreq_data wrqu;
- char *msg;
+ struct ieee80211softmac_network *network;
if (event >= 0) {
- msg = event_descriptions[event];
- wrqu.data.length = strlen(msg);
- wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg);
+ union iwreq_data wrqu;
+ int we_event;
+ char *msg = NULL;
+
+ switch(event) {
+ case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
+ network = (struct ieee80211softmac_network *)event_ctx;
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ we_event = SIOCGIWAP;
+ break;
+ case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ memset(&wrqu, '\0', sizeof (union iwreq_data));
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ we_event = SIOCGIWAP;
+ break;
+ case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ memset(&wrqu, '\0', sizeof (union iwreq_data));
+ we_event = SIOCGIWSCAN;
+ break;
+ default:
+ msg = event_descriptions[event];
+ wrqu.data.length = strlen(msg);
+ we_event = IWEVCUSTOM;
+ break;
+ }
+ wireless_send_event(mac->dev, we_event, &wrqu, msg);
}
if (!list_empty(&mac->events))
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index febc51dbb41..cc6cd56c85b 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -180,9 +180,21 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
/* Fill in capability Info */
- (*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ?
- cpu_to_le16(WLAN_CAPABILITY_ESS) :
- cpu_to_le16(WLAN_CAPABILITY_IBSS);
+ switch (mac->ieee->iw_mode) {
+ case IW_MODE_INFRA:
+ (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
+ break;
+ case IW_MODE_ADHOC:
+ (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
+ break;
+ case IW_MODE_AUTO:
+ (*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
+ break;
+ default:
+ /* bleh. we don't ever go to these modes */
+ printk(KERN_ERR PFX "invalid iw_mode!\n");
+ break;
+ }
/* Need to add this
(*pkt)->capability |= mac->ieee->short_slot ?
cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index 6f99f781bff..6252be2c0db 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -45,6 +45,8 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv)
softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
softmac->scaninfo = NULL;
+ softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
+
/* TODO: initialise all the other callbacks in the ieee struct
* (once they're written)
*/
@@ -87,6 +89,8 @@ ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm)
ieee80211softmac_wait_for_scan(sm);
spin_lock_irqsave(&sm->lock, flags);
+ sm->running = 0;
+
/* Free all pending assoc work items */
cancel_delayed_work(&sm->associnfo.work);
@@ -183,20 +187,27 @@ void ieee80211softmac_start(struct net_device *dev)
*/
if (mac->txrates_change)
oldrates = mac->txrates;
- if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
- mac->txrates.default_rate = IEEE80211_OFDM_RATE_54MB;
- change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
- mac->txrates.default_fallback = IEEE80211_OFDM_RATE_24MB;
- change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
- } else if (ieee->modulation & IEEE80211_CCK_MODULATION) {
+ /* FIXME: We don't correctly handle backing down to lower
+ rates, so 801.11g devices start off at 11M for now. People
+ can manually change it if they really need to, but 11M is
+ more reliable. Note similar logic in
+ ieee80211softmac_wx_set_rate() */
+ if (ieee->modulation & IEEE80211_CCK_MODULATION) {
mac->txrates.default_rate = IEEE80211_CCK_RATE_11MB;
change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
mac->txrates.default_fallback = IEEE80211_CCK_RATE_5MB;
change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+ } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
+ mac->txrates.default_rate = IEEE80211_OFDM_RATE_54MB;
+ change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+ mac->txrates.default_fallback = IEEE80211_OFDM_RATE_24MB;
+ change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
} else
assert(0);
if (mac->txrates_change)
mac->txrates_change(dev, change, &oldrates);
+
+ mac->running = 1;
}
EXPORT_SYMBOL_GPL(ieee80211softmac_start);
diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h
index 9ba7dbd161e..65d9816c8ec 100644
--- a/net/ieee80211/softmac/ieee80211softmac_priv.h
+++ b/net/ieee80211/softmac/ieee80211softmac_priv.h
@@ -167,7 +167,7 @@ static inline int ieee80211softmac_scan_sanity_check(struct ieee80211softmac_dev
) || ieee80211softmac_scan_handlers_check_self(sm);
}
-#define IEEE80211SOFTMAC_PROBE_DELAY HZ/2
+#define IEEE80211SOFTMAC_PROBE_DELAY HZ/50
#define IEEE80211SOFTMAC_WORKQUEUE_NAME_LEN (17 + IFNAMSIZ)
struct ieee80211softmac_network {
diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
index bb9ab8b45d0..d31cf77498c 100644
--- a/net/ieee80211/softmac/ieee80211softmac_scan.c
+++ b/net/ieee80211/softmac/ieee80211softmac_scan.c
@@ -47,6 +47,7 @@ ieee80211softmac_start_scan(struct ieee80211softmac_device *sm)
sm->scanning = 1;
spin_unlock_irqrestore(&sm->lock, flags);
+ netif_tx_disable(sm->ieee->dev);
ret = sm->start_scan(sm->dev);
if (ret) {
spin_lock_irqsave(&sm->lock, flags);
@@ -114,7 +115,15 @@ void ieee80211softmac_scan(void *d)
// TODO: is this if correct, or should we do this only if scanning from assoc request?
if (sm->associnfo.req_essid.len)
ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0);
+
+ spin_lock_irqsave(&sm->lock, flags);
+ if (unlikely(!sm->running)) {
+ /* Prevent reschedule on workqueue flush */
+ spin_unlock_irqrestore(&sm->lock, flags);
+ break;
+ }
schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY);
+ spin_unlock_irqrestore(&sm->lock, flags);
return;
} else {
dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel);
@@ -239,6 +248,7 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
if (net)
sm->set_channel(sm->dev, net->channel);
}
+ netif_wake_queue(sm->ieee->dev);
ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
}
EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index e1a9bc6d36f..27edb2b5581 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -27,7 +27,8 @@
#include "ieee80211softmac_priv.h"
#include <net/iw_handler.h>
-
+/* for is_broadcast_ether_addr and is_zero_ether_addr */
+#include <linux/etherdevice.h>
int
ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
@@ -41,13 +42,23 @@ ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
+/* if we're still scanning, return -EAGAIN so that userspace tools
+ * can get the complete scan results, otherwise return 0. */
int
ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra)
{
+ unsigned long flags;
struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
+
+ spin_lock_irqsave(&sm->lock, flags);
+ if (sm->scanning) {
+ spin_unlock_irqrestore(&sm->lock, flags);
+ return -EAGAIN;
+ }
+ spin_unlock_irqrestore(&sm->lock, flags);
return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
}
EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
@@ -73,7 +84,6 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
sm->associnfo.static_essid = 1;
}
}
- sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
/* set our requested ESSID length.
* If applicable, we have already copied the data in */
@@ -135,11 +145,15 @@ ieee80211softmac_wx_set_rate(struct net_device *net_dev,
int err = -EINVAL;
if (in_rate == -1) {
- /* automatic detect */
- if (ieee->modulation & IEEE80211_OFDM_MODULATION)
- in_rate = 54000000;
- else
+ /* FIXME: We don't correctly handle backing down to lower
+ rates, so 801.11g devices start off at 11M for now. People
+ can manually change it if they really need to, but 11M is
+ more reliable. Note similar logic in
+ ieee80211softmac_wx_set_rate() */
+ if (ieee->modulation & IEEE80211_CCK_MODULATION)
in_rate = 11000000;
+ else
+ in_rate = 54000000;
}
switch (in_rate) {
@@ -296,8 +310,6 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
char *extra)
{
struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
- static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned long flags;
/* sanity check */
@@ -306,10 +318,17 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
}
spin_lock_irqsave(&mac->lock, flags);
- if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) ||
- !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) {
- schedule_work(&mac->associnfo.work);
- goto out;
+ if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
+ /* the bssid we have is not to be fixed any longer,
+ * and we should reassociate to the best AP. */
+ mac->associnfo.bssfixed = 0;
+ /* force reassociation */
+ mac->associnfo.bssvalid = 0;
+ if (mac->associated)
+ schedule_work(&mac->associnfo.work);
+ } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
+ /* the bssid we have is no longer fixed */
+ mac->associnfo.bssfixed = 0;
} else {
if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
if (mac->associnfo.associating || mac->associated) {
@@ -319,12 +338,14 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
} else {
/* copy new value in data->ap_addr.sa_data to bssid */
memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
- }
+ }
+ /* tell the other code that this bssid should be used no matter what */
+ mac->associnfo.bssfixed = 1;
/* queue associate if new bssid or (old one again and not associated) */
schedule_work(&mac->associnfo.work);
}
-out:
+ out:
spin_unlock_irqrestore(&mac->lock, flags);
return 0;
}
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 011cca7ae02..e40f7532237 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -235,6 +235,7 @@ config IP_PNP_RARP
# bool ' IP: ARP support' CONFIG_IP_PNP_ARP
config NET_IPIP
tristate "IP: tunneling"
+ select INET_TUNNEL
---help---
Tunneling means encapsulating data of one protocol type within
another protocol and sending it over a channel that understands the
@@ -395,7 +396,7 @@ config INET_ESP
config INET_IPCOMP
tristate "IP: IPComp transformation"
select XFRM
- select INET_TUNNEL
+ select INET_XFRM_TUNNEL
select CRYPTO
select CRYPTO_DEFLATE
---help---
@@ -404,14 +405,14 @@ config INET_IPCOMP
If unsure, say Y.
+config INET_XFRM_TUNNEL
+ tristate
+ select INET_TUNNEL
+ default n
+
config INET_TUNNEL
- tristate "IP: tunnel transformation"
- select XFRM
- ---help---
- Support for generic IP tunnel transformation, which is required by
- the IP tunneling module as well as tunnel mode IPComp.
-
- If unsure, say Y.
+ tristate
+ default n
config INET_DIAG
tristate "INET: socket monitoring interface"
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 35e5f599909..9ef50a0b9d2 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -22,7 +22,8 @@ obj-$(CONFIG_SYN_COOKIES) += syncookies.o
obj-$(CONFIG_INET_AH) += ah4.o
obj-$(CONFIG_INET_ESP) += esp4.o
obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
-obj-$(CONFIG_INET_TUNNEL) += xfrm4_tunnel.o
+obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
+obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
obj-$(CONFIG_IP_PNP) += ipconfig.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index dc206f1f914..0a277453526 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1257,7 +1257,7 @@ out_unregister_udp_proto:
goto out;
}
-module_init(inet_init);
+fs_initcall(inet_init);
/* ------------------------------------------------------------------------ */
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index e16d8b42b95..e2e4771fa4c 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -116,7 +116,7 @@ error:
return err;
}
-static int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
{
int ah_hlen;
struct iphdr *iph;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 041dadde31a..4749d504c62 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -928,7 +928,8 @@ static void parp_redo(struct sk_buff *skb)
* Receive an arp request from the device layer.
*/
-int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
{
struct arphdr *arp;
@@ -1417,7 +1418,6 @@ static int __init arp_proc_init(void)
EXPORT_SYMBOL(arp_broken_ops);
EXPORT_SYMBOL(arp_find);
-EXPORT_SYMBOL(arp_rcv);
EXPORT_SYMBOL(arp_create);
EXPORT_SYMBOL(arp_xmit);
EXPORT_SYMBOL(arp_send);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 44fdf1413e2..54419b27686 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -81,7 +81,7 @@ static struct ipv4_devconf ipv4_devconf_dflt = {
static void rtmsg_ifa(int event, struct in_ifaddr *);
-static struct notifier_block *inetaddr_chain;
+static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
int destroy);
#ifdef CONFIG_SYSCTL
@@ -267,7 +267,8 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
*ifap1 = ifa->ifa_next;
rtmsg_ifa(RTM_DELADDR, ifa);
- notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
+ blocking_notifier_call_chain(&inetaddr_chain,
+ NETDEV_DOWN, ifa);
inet_free_ifa(ifa);
} else {
promote = ifa;
@@ -291,7 +292,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
So that, this order is correct.
*/
rtmsg_ifa(RTM_DELADDR, ifa1);
- notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
+ blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
if (promote) {
@@ -303,7 +304,8 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
promote->ifa_flags &= ~IFA_F_SECONDARY;
rtmsg_ifa(RTM_NEWADDR, promote);
- notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote);
+ blocking_notifier_call_chain(&inetaddr_chain,
+ NETDEV_UP, promote);
for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) {
if (ifa1->ifa_mask != ifa->ifa_mask ||
!inet_ifa_match(ifa1->ifa_address, ifa))
@@ -366,7 +368,7 @@ static int inet_insert_ifa(struct in_ifaddr *ifa)
Notifier will trigger FIB update, so that
listeners of netlink will know about new ifaddr */
rtmsg_ifa(RTM_NEWADDR, ifa);
- notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
+ blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
return 0;
}
@@ -938,12 +940,12 @@ u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scop
int register_inetaddr_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&inetaddr_chain, nb);
+ return blocking_notifier_chain_register(&inetaddr_chain, nb);
}
int unregister_inetaddr_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&inetaddr_chain, nb);
+ return blocking_notifier_chain_unregister(&inetaddr_chain, nb);
}
/* Rename ifa_labels for a device name change. Make some effort to preserve existing
@@ -1554,7 +1556,6 @@ void __init devinet_init(void)
#endif
}
-EXPORT_SYMBOL(devinet_ioctl);
EXPORT_SYMBOL(in_dev_finish_destroy);
EXPORT_SYMBOL(inet_select_addr);
EXPORT_SYMBOL(inetdev_by_index);
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index bf88c620a95..9d1881c07a3 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -133,7 +133,7 @@ error:
* expensive, so we only support truncated data, which is the recommended
* and common case.
*/
-static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
{
struct iphdr *iph;
struct ip_esp_hdr *esph;
@@ -208,9 +208,6 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
struct xfrm_encap_tmpl *encap = x->encap;
struct udphdr *uh;
- if (encap->encap_type != decap->decap_type)
- goto out;
-
uh = (struct udphdr *)(iph + 1);
encap_len = (void*)esph - (void*)uh;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 4e3d3811dea..cdde9639096 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -666,4 +666,3 @@ void __init ip_fib_init(void)
}
EXPORT_SYMBOL(inet_addr_type);
-EXPORT_SYMBOL(ip_rt_ioctl);
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index ccd3efc6a17..95a639f2e3d 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -50,7 +50,7 @@
* Patrick McHardy <kaber@trash.net>
*/
-#define VERSION "0.406"
+#define VERSION "0.407"
#include <linux/config.h>
#include <asm/uaccess.h>
@@ -314,11 +314,6 @@ static void __leaf_free_rcu(struct rcu_head *head)
kfree(container_of(head, struct leaf, rcu));
}
-static inline void free_leaf(struct leaf *leaf)
-{
- call_rcu(&leaf->rcu, __leaf_free_rcu);
-}
-
static void __leaf_info_free_rcu(struct rcu_head *head)
{
kfree(container_of(head, struct leaf_info, rcu));
@@ -357,7 +352,12 @@ static void __tnode_free_rcu(struct rcu_head *head)
static inline void tnode_free(struct tnode *tn)
{
- call_rcu(&tn->rcu, __tnode_free_rcu);
+ if(IS_LEAF(tn)) {
+ struct leaf *l = (struct leaf *) tn;
+ call_rcu_bh(&l->rcu, __leaf_free_rcu);
+ }
+ else
+ call_rcu(&tn->rcu, __tnode_free_rcu);
}
static struct leaf *leaf_new(void)
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 9831fd2c73a..2a0455911ee 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -1107,7 +1107,7 @@ void __init icmp_init(struct net_proto_family *ops)
struct inet_sock *inet;
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
int err;
err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index ef7366fc132..ee9b5515b9a 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -43,8 +43,6 @@ struct inet_bind_bucket *inet_bind_bucket_create(kmem_cache_t *cachep,
return tb;
}
-EXPORT_SYMBOL(inet_bind_bucket_create);
-
/*
* Caller must hold hashbucket lock for this tb with local BH disabled
*/
@@ -64,8 +62,6 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
inet_csk(sk)->icsk_bind_hash = tb;
}
-EXPORT_SYMBOL(inet_bind_hash);
-
/*
* Get rid of any references to a local port held by the given sock.
*/
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index 0923add122b..9f0bb529ab7 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -116,6 +116,7 @@ sr_failed:
too_many_hops:
/* Tell the sender its packet died... */
+ IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
drop:
kfree_skb(skb);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 2a8adda15e1..da734c43917 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -304,13 +304,17 @@ out:
/* Creation primitives. */
-static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
+static struct ipq *ip_frag_intern(struct ipq *qp_in)
{
struct ipq *qp;
#ifdef CONFIG_SMP
struct hlist_node *n;
#endif
+ unsigned int hash;
+
write_lock(&ipfrag_lock);
+ hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
+ qp_in->protocol);
#ifdef CONFIG_SMP
/* With SMP race we have to recheck hash table, because
* such entry could be created on other cpu, while we
@@ -345,7 +349,7 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
}
/* Add an entry to the 'ipq' queue for a newly received IP datagram. */
-static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
+static struct ipq *ip_frag_create(struct iphdr *iph, u32 user)
{
struct ipq *qp;
@@ -371,7 +375,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
spin_lock_init(&qp->lock);
atomic_set(&qp->refcnt, 1);
- return ip_frag_intern(hash, qp);
+ return ip_frag_intern(qp);
out_nomem:
LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n");
@@ -387,11 +391,12 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
__u32 saddr = iph->saddr;
__u32 daddr = iph->daddr;
__u8 protocol = iph->protocol;
- unsigned int hash = ipqhashfn(id, saddr, daddr, protocol);
+ unsigned int hash;
struct ipq *qp;
struct hlist_node *n;
read_lock(&ipfrag_lock);
+ hash = ipqhashfn(id, saddr, daddr, protocol);
hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
if(qp->id == id &&
qp->saddr == saddr &&
@@ -405,7 +410,7 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
}
read_unlock(&ipfrag_lock);
- return ip_frag_create(hash, iph, user);
+ return ip_frag_create(iph, user);
}
/* Is the fragment too far ahead to be part of ipq? */
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 9981dcd68f1..ab99bebdcdc 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -656,7 +656,7 @@ static int ipgre_rcv(struct sk_buff *skb)
read_unlock(&ipgre_lock);
return(0);
}
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
drop:
read_unlock(&ipgre_lock);
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 18d7fad474d..c9026dbf4c9 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -337,7 +337,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb)
* Initialise the virtual path cache for the packet. It describes
* how the packet travels inside Linux networking.
*/
- if (likely(skb->dst == NULL)) {
+ if (skb->dst == NULL) {
int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
skb->dev);
if (unlikely(err)) {
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 9bebad07bf2..cbcae654462 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -209,7 +209,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
void ip_options_fragment(struct sk_buff * skb)
{
- unsigned char * optptr = skb->nh.raw;
+ unsigned char * optptr = skb->nh.raw + sizeof(struct iphdr);
struct ip_options * opt = &(IPCB(skb)->opt);
int l = opt->optlen;
int optlen;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index f75ff1d9655..cff9c3a72da 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -86,8 +86,6 @@
int sysctl_ip_default_ttl = IPDEFTTL;
-static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*));
-
/* Generate a checksum for an outgoing IP datagram. */
__inline__ void ip_send_check(struct iphdr *iph)
{
@@ -421,7 +419,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
* single device frame, and queue such a frame for sending.
*/
-static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
+int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
{
struct iphdr *iph;
int raw = 0;
@@ -673,6 +671,8 @@ fail:
return err;
}
+EXPORT_SYMBOL(ip_fragment);
+
int
ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
{
@@ -904,7 +904,7 @@ alloc_new_skb:
* because we have no idea what fragment will be
* the last.
*/
- if (datalen == length)
+ if (datalen == length + fraggap)
alloclen += rt->u.dst.trailer_len;
if (transhdrlen) {
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index c95020f7c81..95278b22b66 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -81,8 +81,7 @@ out:
return err;
}
-static int ipcomp_input(struct xfrm_state *x,
- struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
{
u8 nexthdr;
int err = 0;
@@ -211,7 +210,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info)
skb->h.icmph->code != ICMP_FRAG_NEEDED)
return;
- spi = ntohl(ntohs(ipch->cpi));
+ spi = htonl(ntohs(ipch->cpi));
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr,
spi, IPPROTO_COMP, AF_INET);
if (!x)
@@ -291,11 +290,8 @@ static void ipcomp_free_scratches(void)
if (!scratches)
return;
- for_each_cpu(i) {
- void *scratch = *per_cpu_ptr(scratches, i);
- if (scratch)
- vfree(scratch);
- }
+ for_each_possible_cpu(i)
+ vfree(*per_cpu_ptr(scratches, i));
free_percpu(scratches);
}
@@ -314,7 +310,7 @@ static void **ipcomp_alloc_scratches(void)
ipcomp_scratches = scratches;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
if (!scratch)
return NULL;
@@ -345,7 +341,7 @@ static void ipcomp_free_tfms(struct crypto_tfm **tfms)
if (!tfms)
return;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
crypto_free_tfm(tfm);
}
@@ -385,7 +381,7 @@ static struct crypto_tfm **ipcomp_alloc_tfms(const char *alg_name)
if (!tfms)
goto error;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
if (!tfm)
goto error;
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 03d13742a4b..ea398ee43f2 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -114,7 +114,6 @@
#include <net/sock.h>
#include <net/ip.h>
#include <net/icmp.h>
-#include <net/protocol.h>
#include <net/ipip.h>
#include <net/inet_ecn.h>
#include <net/xfrm.h>
@@ -274,7 +273,7 @@ static void ipip_tunnel_uninit(struct net_device *dev)
dev_put(dev);
}
-static void ipip_err(struct sk_buff *skb, u32 info)
+static int ipip_err(struct sk_buff *skb, u32 info)
{
#ifndef I_WISH_WORLD_WERE_PERFECT
@@ -286,21 +285,22 @@ static void ipip_err(struct sk_buff *skb, u32 info)
int type = skb->h.icmph->type;
int code = skb->h.icmph->code;
struct ip_tunnel *t;
+ int err;
switch (type) {
default:
case ICMP_PARAMETERPROB:
- return;
+ return 0;
case ICMP_DEST_UNREACH:
switch (code) {
case ICMP_SR_FAILED:
case ICMP_PORT_UNREACH:
/* Impossible event. */
- return;
+ return 0;
case ICMP_FRAG_NEEDED:
/* Soft state for pmtu is maintained by IP core. */
- return;
+ return 0;
default:
/* All others are translated to HOST_UNREACH.
rfc2003 contains "deep thoughts" about NET_UNREACH,
@@ -311,14 +311,18 @@ static void ipip_err(struct sk_buff *skb, u32 info)
break;
case ICMP_TIME_EXCEEDED:
if (code != ICMP_EXC_TTL)
- return;
+ return 0;
break;
}
+ err = -ENOENT;
+
read_lock(&ipip_lock);
t = ipip_tunnel_lookup(iph->daddr, iph->saddr);
if (t == NULL || t->parms.iph.daddr == 0)
goto out;
+
+ err = 0;
if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
goto out;
@@ -329,7 +333,7 @@ static void ipip_err(struct sk_buff *skb, u32 info)
t->err_time = jiffies;
out:
read_unlock(&ipip_lock);
- return;
+ return err;
#else
struct iphdr *iph = (struct iphdr*)dp;
int hlen = iph->ihl<<2;
@@ -344,15 +348,15 @@ out:
struct rtable *rt;
if (len < hlen + sizeof(struct iphdr))
- return;
+ return 0;
eiph = (struct iphdr*)(dp + hlen);
switch (type) {
default:
- return;
+ return 0;
case ICMP_PARAMETERPROB:
if (skb->h.icmph->un.gateway < hlen)
- return;
+ return 0;
/* So... This guy found something strange INSIDE encapsulated
packet. Well, he is fool, but what can we do ?
@@ -366,16 +370,16 @@ out:
case ICMP_SR_FAILED:
case ICMP_PORT_UNREACH:
/* Impossible event. */
- return;
+ return 0;
case ICMP_FRAG_NEEDED:
/* And it is the only really necessary thing :-) */
rel_info = ntohs(skb->h.icmph->un.frag.mtu);
if (rel_info < hlen+68)
- return;
+ return 0;
rel_info -= hlen;
/* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
if (rel_info > ntohs(eiph->tot_len))
- return;
+ return 0;
break;
default:
/* All others are translated to HOST_UNREACH.
@@ -389,14 +393,14 @@ out:
break;
case ICMP_TIME_EXCEEDED:
if (code != ICMP_EXC_TTL)
- return;
+ return 0;
break;
}
/* Prepare fake skb to feed it to icmp_send */
skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2 == NULL)
- return;
+ return 0;
dst_release(skb2->dst);
skb2->dst = NULL;
skb_pull(skb2, skb->data - (u8*)eiph);
@@ -409,7 +413,7 @@ out:
fl.proto = IPPROTO_IPIP;
if (ip_route_output_key(&rt, &key)) {
kfree_skb(skb2);
- return;
+ return 0;
}
skb2->dev = rt->u.dst.dev;
@@ -424,14 +428,14 @@ out:
rt->u.dst.dev->type != ARPHRD_TUNNEL) {
ip_rt_put(rt);
kfree_skb(skb2);
- return;
+ return 0;
}
} else {
ip_rt_put(rt);
if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) ||
skb2->dst->dev->type != ARPHRD_TUNNEL) {
kfree_skb(skb2);
- return;
+ return 0;
}
}
@@ -439,7 +443,7 @@ out:
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
if (rel_info > dst_mtu(skb2->dst)) {
kfree_skb(skb2);
- return;
+ return 0;
}
skb2->dst->ops->update_pmtu(skb2->dst, rel_info);
rel_info = htonl(rel_info);
@@ -453,7 +457,7 @@ out:
icmp_send(skb2, rel_type, rel_code, rel_info);
kfree_skb(skb2);
- return;
+ return 0;
#endif
}
@@ -470,9 +474,6 @@ static int ipip_rcv(struct sk_buff *skb)
struct iphdr *iph;
struct ip_tunnel *tunnel;
- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
- goto out;
-
iph = skb->nh.iph;
read_lock(&ipip_lock);
@@ -504,7 +505,6 @@ static int ipip_rcv(struct sk_buff *skb)
}
read_unlock(&ipip_lock);
-out:
return -1;
}
@@ -855,39 +855,12 @@ static int __init ipip_fb_tunnel_init(struct net_device *dev)
return 0;
}
-#ifdef CONFIG_INET_TUNNEL
static struct xfrm_tunnel ipip_handler = {
.handler = ipip_rcv,
.err_handler = ipip_err,
+ .priority = 1,
};
-static inline int ipip_register(void)
-{
- return xfrm4_tunnel_register(&ipip_handler);
-}
-
-static inline int ipip_unregister(void)
-{
- return xfrm4_tunnel_deregister(&ipip_handler);
-}
-#else
-static struct net_protocol ipip_protocol = {
- .handler = ipip_rcv,
- .err_handler = ipip_err,
- .no_policy = 1,
-};
-
-static inline int ipip_register(void)
-{
- return inet_add_protocol(&ipip_protocol, IPPROTO_IPIP);
-}
-
-static inline int ipip_unregister(void)
-{
- return inet_del_protocol(&ipip_protocol, IPPROTO_IPIP);
-}
-#endif
-
static char banner[] __initdata =
KERN_INFO "IPv4 over IPv4 tunneling driver\n";
@@ -897,7 +870,7 @@ static int __init ipip_init(void)
printk(banner);
- if (ipip_register() < 0) {
+ if (xfrm4_tunnel_register(&ipip_handler)) {
printk(KERN_INFO "ipip init: can't register tunnel\n");
return -EAGAIN;
}
@@ -919,7 +892,7 @@ static int __init ipip_init(void)
err2:
free_netdev(ipip_fb_tunnel_dev);
err1:
- ipip_unregister();
+ xfrm4_tunnel_deregister(&ipip_handler);
goto out;
}
@@ -939,7 +912,7 @@ static void __exit ipip_destroy_tunnels(void)
static void __exit ipip_fini(void)
{
- if (ipip_unregister() < 0)
+ if (xfrm4_tunnel_deregister(&ipip_handler))
printk(KERN_INFO "ipip close: can't deregister tunnel\n");
rtnl_lock();
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index ed42cdc57cd..6a9e34b794b 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -133,7 +133,7 @@ struct ip_rt_info {
u_int8_t tos;
};
-static void queue_save(const struct sk_buff *skb, struct nf_info *info)
+static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
{
struct ip_rt_info *rt_info = nf_info_reroute(info);
@@ -146,7 +146,7 @@ static void queue_save(const struct sk_buff *skb, struct nf_info *info)
}
}
-static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info)
+static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
{
const struct ip_rt_info *rt_info = nf_info_reroute(info);
@@ -161,21 +161,55 @@ static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info)
return 0;
}
-static struct nf_queue_rerouter ip_reroute = {
- .rer_size = sizeof(struct ip_rt_info),
- .save = queue_save,
- .reroute = queue_reroute,
+unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, u_int8_t protocol)
+{
+ struct iphdr *iph = skb->nh.iph;
+ unsigned int csum = 0;
+
+ switch (skb->ip_summed) {
+ case CHECKSUM_HW:
+ if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN)
+ break;
+ if ((protocol == 0 && !(u16)csum_fold(skb->csum)) ||
+ !csum_tcpudp_magic(iph->saddr, iph->daddr,
+ skb->len - dataoff, protocol,
+ skb->csum)) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ break;
+ }
+ /* fall through */
+ case CHECKSUM_NONE:
+ if (protocol == 0)
+ skb->csum = 0;
+ else
+ skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+ skb->len - dataoff,
+ protocol, 0);
+ csum = __skb_checksum_complete(skb);
+ }
+ return csum;
+}
+
+EXPORT_SYMBOL(nf_ip_checksum);
+
+static struct nf_afinfo nf_ip_afinfo = {
+ .family = AF_INET,
+ .checksum = nf_ip_checksum,
+ .saveroute = nf_ip_saveroute,
+ .reroute = nf_ip_reroute,
+ .route_key_size = sizeof(struct ip_rt_info),
};
-static int init(void)
+static int ipv4_netfilter_init(void)
{
- return nf_register_queue_rerouter(PF_INET, &ip_reroute);
+ return nf_register_afinfo(&nf_ip_afinfo);
}
-static void fini(void)
+static void ipv4_netfilter_fini(void)
{
- nf_unregister_queue_rerouter(PF_INET);
+ nf_unregister_afinfo(&nf_ip_afinfo);
}
-module_init(init);
-module_exit(fini);
+module_init(ipv4_netfilter_init);
+module_exit(ipv4_netfilter_fini);
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 882b842c25d..d4072533da2 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -69,6 +69,7 @@ config IP_NF_CONNTRACK_NETLINK
tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK
depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
+ depends on IP_NF_NAT=n || IP_NF_NAT
help
This option enables support for a netlink-based userspace interface
@@ -169,8 +170,8 @@ config IP_NF_PPTP
Documentation/modules.txt. If unsure, say `N'.
config IP_NF_H323
- tristate 'H.323 protocol support'
- depends on IP_NF_CONNTRACK
+ tristate 'H.323 protocol support (EXPERIMENTAL)'
+ depends on IP_NF_CONNTRACK && EXPERIMENTAL
help
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
important VoIP protocols, it is widely used by voice hardware and
@@ -221,16 +222,6 @@ config IP_NF_MATCH_IPRANGE
To compile it as a module, choose M here. If unsure, say N.
-config IP_NF_MATCH_MULTIPORT
- tristate "Multiple port match support"
- depends on IP_NF_IPTABLES
- help
- Multiport matching allows you to match TCP or UDP packets based on
- a series of source or destination ports: normally a rule can only
- match a single range of ports.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP_NF_MATCH_TOS
tristate "TOS match support"
depends on IP_NF_IPTABLES
@@ -272,12 +263,12 @@ config IP_NF_MATCH_DSCP
To compile it as a module, choose M here. If unsure, say N.
-config IP_NF_MATCH_AH_ESP
- tristate "AH/ESP match support"
+config IP_NF_MATCH_AH
+ tristate "AH match support"
depends on IP_NF_IPTABLES
help
- These two match extensions (`ah' and `esp') allow you to match a
- range of SPIs inside AH or ESP headers of IPSec packets.
+ This match extension allows you to match a range of SPIs
+ inside AH header of IPSec packets.
To compile it as a module, choose M here. If unsure, say N.
@@ -354,7 +345,7 @@ config IP_NF_TARGET_LOG
To compile it as a module, choose M here. If unsure, say N.
config IP_NF_TARGET_ULOG
- tristate "ULOG target support (OBSOLETE)"
+ tristate "ULOG target support"
depends on IP_NF_IPTABLES
---help---
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index f2cd9a6c5b9..461cb1eb5de 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -53,13 +53,12 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
# matches
obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
-obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
-obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
+obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index ff0c594a419..d0d19192026 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -646,7 +646,7 @@ static int translate_table(const char *name,
}
/* And one copy for every other CPU */
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
if (newinfo->entries[i] && newinfo->entries[i] != entry0)
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
@@ -696,7 +696,7 @@ static void get_counters(const struct xt_table_info *t,
counters,
&i);
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (cpu == curcpu)
continue;
i = 0;
@@ -948,7 +948,7 @@ static int do_add_counters(void __user *user, unsigned int len)
write_lock_bh(&t->lock);
private = t->private;
- if (private->number != paddc->num_counters) {
+ if (private->number != tmp.num_counters) {
ret = -EINVAL;
goto unlock_up_free;
}
@@ -1166,7 +1166,7 @@ static struct nf_sockopt_ops arpt_sockopts = {
.get = do_arpt_get_ctl,
};
-static int __init init(void)
+static int __init arp_tables_init(void)
{
int ret;
@@ -1187,7 +1187,7 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit arp_tables_fini(void)
{
nf_unregister_sockopt(&arpt_sockopts);
xt_proto_fini(NF_ARP);
@@ -1197,5 +1197,5 @@ EXPORT_SYMBOL(arpt_register_table);
EXPORT_SYMBOL(arpt_unregister_table);
EXPORT_SYMBOL(arpt_do_table);
-module_init(init);
-module_exit(fini);
+module_init(arp_tables_init);
+module_exit(arp_tables_fini);
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index 0f2a95350e2..a58325c1ceb 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -89,7 +89,7 @@ static struct arpt_target arpt_mangle_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init arpt_mangle_init(void)
{
if (arpt_register_target(&arpt_mangle_reg))
return -EINVAL;
@@ -97,10 +97,10 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit arpt_mangle_fini(void)
{
arpt_unregister_target(&arpt_mangle_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(arpt_mangle_init);
+module_exit(arpt_mangle_fini);
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index f6ab45f4868..d7c472faa53 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -179,37 +179,30 @@ static struct nf_hook_ops arpt_ops[] = {
},
};
-static int __init init(void)
+static int __init arptable_filter_init(void)
{
- int ret, i;
+ int ret;
/* Register table */
ret = arpt_register_table(&packet_filter, &initial_table.repl);
if (ret < 0)
return ret;
- for (i = 0; i < ARRAY_SIZE(arpt_ops); i++)
- if ((ret = nf_register_hook(&arpt_ops[i])) < 0)
- goto cleanup_hooks;
+ ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
+ if (ret < 0)
+ goto cleanup_table;
return ret;
-cleanup_hooks:
- while (--i >= 0)
- nf_unregister_hook(&arpt_ops[i]);
-
+cleanup_table:
arpt_unregister_table(&packet_filter);
return ret;
}
-static void __exit fini(void)
+static void __exit arptable_filter_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(arpt_ops); i++)
- nf_unregister_hook(&arpt_ops[i]);
-
+ nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
arpt_unregister_table(&packet_filter);
}
-module_init(init);
-module_exit(fini);
+module_init(arptable_filter_init);
+module_exit(arptable_filter_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index 84e4f79b7ff..a604b1ccfda 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -153,13 +153,13 @@ static struct ip_conntrack_helper amanda_helper = {
},
};
-static void __exit fini(void)
+static void __exit ip_conntrack_amanda_fini(void)
{
ip_conntrack_helper_unregister(&amanda_helper);
kfree(amanda_buffer);
}
-static int __init init(void)
+static int __init ip_conntrack_amanda_init(void)
{
int ret;
@@ -177,5 +177,5 @@ static int __init init(void)
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_amanda_init);
+module_exit(ip_conntrack_amanda_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 9e34034729a..a297da7bbef 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -80,8 +80,8 @@ static int ip_conntrack_vmalloc;
static unsigned int ip_conntrack_next_id;
static unsigned int ip_conntrack_expect_next_id;
#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
-struct notifier_block *ip_conntrack_chain;
-struct notifier_block *ip_conntrack_expect_chain;
+ATOMIC_NOTIFIER_HEAD(ip_conntrack_chain);
+ATOMIC_NOTIFIER_HEAD(ip_conntrack_expect_chain);
DEFINE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache);
@@ -92,7 +92,7 @@ __ip_ct_deliver_cached_events(struct ip_conntrack_ecache *ecache)
{
DEBUGP("ecache: delivering events for %p\n", ecache->ct);
if (is_confirmed(ecache->ct) && !is_dying(ecache->ct) && ecache->events)
- notifier_call_chain(&ip_conntrack_chain, ecache->events,
+ atomic_notifier_call_chain(&ip_conntrack_chain, ecache->events,
ecache->ct);
ecache->events = 0;
ip_conntrack_put(ecache->ct);
@@ -133,7 +133,7 @@ static void ip_ct_event_cache_flush(void)
struct ip_conntrack_ecache *ecache;
int cpu;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
ecache = &per_cpu(ip_conntrack_ecache, cpu);
if (ecache->ct)
ip_conntrack_put(ecache->ct);
@@ -1318,6 +1318,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
.tuple.dst.u.tcp.port;
sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL]
.tuple.dst.ip;
+ memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index e627e585617..3e542bf28a9 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -453,7 +453,7 @@ static struct ip_conntrack_helper ftp[MAX_PORTS];
static char ftp_names[MAX_PORTS][sizeof("ftp-65535")];
/* Not __exit: called from init() */
-static void fini(void)
+static void ip_conntrack_ftp_fini(void)
{
int i;
for (i = 0; i < ports_c; i++) {
@@ -465,7 +465,7 @@ static void fini(void)
kfree(ftp_buffer);
}
-static int __init init(void)
+static int __init ip_conntrack_ftp_init(void)
{
int i, ret;
char *tmpname;
@@ -499,12 +499,12 @@ static int __init init(void)
ret = ip_conntrack_helper_register(&ftp[i]);
if (ret) {
- fini();
+ ip_conntrack_ftp_fini();
return ret;
}
}
return 0;
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_ftp_init);
+module_exit(ip_conntrack_ftp_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index daeb1395faa..518f581d39e 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -9,37 +9,6 @@
* Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* For more information, please see http://nath323.sourceforge.net/
- *
- * Changes:
- * 2006-02-01 - initial version 0.1
- *
- * 2006-02-20 - version 0.2
- * 1. Changed source format to follow kernel conventions
- * 2. Deleted some unnecessary structures
- * 3. Minor fixes
- *
- * 2006-03-10 - version 0.3
- * 1. Added support for multiple TPKTs in one packet (suggested by
- * Patrick McHardy)
- * 2. Avoid excessive stack usage (based on Patrick McHardy's patch)
- * 3. Added support for non-linear skb (based on Patrick McHardy's patch)
- * 4. Fixed missing H.245 module owner (Patrick McHardy)
- * 5. Avoid long RAS expectation chains (Patrick McHardy)
- * 6. Fixed incorrect __exit attribute (Patrick McHardy)
- * 7. Eliminated unnecessary return code
- * 8. Fixed incorrect use of NAT data from conntrack code (suggested by
- * Patrick McHardy)
- * 9. Fixed TTL calculation error in RCF
- * 10. Added TTL support in RRQ
- * 11. Better support for separate TPKT header and data
- *
- * 2006-03-15 - version 0.4
- * 1. Added support for T.120 channels
- * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
- * 3. Splitted ASN.1 code and data (suggested by Patrick McHardy)
- * 4. Sort ASN.1 data to avoid forwarding declarations (suggested by
- * Patrick McHardy)
- * 5. Reset next TPKT data length in get_tpkt_data()
*/
#include <linux/config.h>
@@ -54,8 +23,6 @@
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
#include <linux/moduleparam.h>
-#include "ip_conntrack_helper_h323_asn1.h"
-
#if 0
#define DEBUGP printk
#else
@@ -63,6 +30,10 @@
#endif
/* Parameters */
+static unsigned int default_rrq_ttl = 300;
+module_param(default_rrq_ttl, uint, 0600);
+MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");
+
static int gkrouted_only = 1;
module_param(gkrouted_only, int, 0600);
MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
@@ -191,6 +162,8 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
/* Validate TPKT length */
tpktlen = tpkt[2] * 256 + tpkt[3];
+ if (tpktlen < 4)
+ goto clear_out;
if (tpktlen > tcpdatalen) {
if (tcpdatalen == 4) { /* Separate TPKT header */
/* Netmeeting sends TPKT header and data separately */
@@ -222,8 +195,8 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
}
/****************************************************************************/
-int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
- u_int32_t * ip, u_int16_t * port)
+static int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
+ u_int32_t * ip, u_int16_t * port)
{
unsigned char *p;
@@ -1302,7 +1275,7 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
info->timeout = rrq->timeToLive;
} else
- info->timeout = 0;
+ info->timeout = default_rrq_ttl;
return 0;
}
@@ -1713,18 +1686,17 @@ static int __init init(void)
module_init(init);
module_exit(fini);
-EXPORT_SYMBOL(get_h245_addr);
-EXPORT_SYMBOL(get_h225_addr);
-EXPORT_SYMBOL(ip_conntrack_h245_expect);
-EXPORT_SYMBOL(ip_conntrack_q931_expect);
-EXPORT_SYMBOL(set_h245_addr_hook);
-EXPORT_SYMBOL(set_h225_addr_hook);
-EXPORT_SYMBOL(set_sig_addr_hook);
-EXPORT_SYMBOL(set_ras_addr_hook);
-EXPORT_SYMBOL(nat_rtp_rtcp_hook);
-EXPORT_SYMBOL(nat_t120_hook);
-EXPORT_SYMBOL(nat_h245_hook);
-EXPORT_SYMBOL(nat_q931_hook);
+EXPORT_SYMBOL_GPL(get_h225_addr);
+EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect);
+EXPORT_SYMBOL_GPL(ip_conntrack_q931_expect);
+EXPORT_SYMBOL_GPL(set_h245_addr_hook);
+EXPORT_SYMBOL_GPL(set_h225_addr_hook);
+EXPORT_SYMBOL_GPL(set_sig_addr_hook);
+EXPORT_SYMBOL_GPL(set_ras_addr_hook);
+EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
+EXPORT_SYMBOL_GPL(nat_t120_hook);
+EXPORT_SYMBOL_GPL(nat_h245_hook);
+EXPORT_SYMBOL_GPL(nat_q931_hook);
MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
MODULE_DESCRIPTION("H.323 connection tracking helper");
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
index afa525129b5..26dfecadb33 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
@@ -2,7 +2,7 @@
* ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323
* conntrack/NAT module.
*
- * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
+ * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
*
* This source code is licensed under General Public License version 2.
*
@@ -15,7 +15,7 @@
#else
#include <stdio.h>
#endif
-#include "ip_conntrack_helper_h323_asn1.h"
+#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
/* Trace Flag */
#ifndef H323_TRACE
@@ -528,14 +528,15 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level)
/* Decode */
if ((err = (Decoders[son->type]) (bs, son, base,
- level + 1)) >
- H323_ERROR_STOP)
+ level + 1)) <
+ H323_ERROR_NONE)
return err;
bs->cur = beg + len;
bs->bit = 0;
} else if ((err = (Decoders[son->type]) (bs, son, base,
- level + 1)))
+ level + 1)) <
+ H323_ERROR_NONE)
return err;
}
@@ -554,7 +555,7 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level)
/* Decode the extension components */
for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
- if (son->attr & STOP) {
+ if (i < f->ub && son->attr & STOP) {
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
son->name);
return H323_ERROR_STOP;
@@ -584,8 +585,8 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level)
beg = bs->cur;
if ((err = (Decoders[son->type]) (bs, son, base,
- level + 1)) >
- H323_ERROR_STOP)
+ level + 1)) <
+ H323_ERROR_NONE)
return err;
bs->cur = beg + len;
@@ -660,18 +661,20 @@ int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level)
i <
effective_count ?
base : NULL,
- level + 1)) >
- H323_ERROR_STOP)
+ level + 1)) <
+ H323_ERROR_NONE)
return err;
bs->cur = beg + len;
bs->bit = 0;
} else
- if ((err = (Decoders[son->type]) (bs, son,
- i < effective_count ?
- base : NULL,
- level + 1)))
- return err;
+ if ((err = (Decoders[son->type]) (bs, son,
+ i <
+ effective_count ?
+ base : NULL,
+ level + 1)) <
+ H323_ERROR_NONE)
+ return err;
if (base)
base += son->offset;
@@ -703,6 +706,10 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
type = get_bits(bs, f->sz);
}
+ /* Write Type */
+ if (base)
+ *(unsigned *) base = type;
+
/* Check Range */
if (type >= f->ub) { /* Newer version? */
BYTE_ALIGN(bs);
@@ -712,10 +719,6 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
return H323_ERROR_NONE;
}
- /* Write Type */
- if (base)
- *(unsigned *) base = type;
-
/* Transfer to son level */
son = &f->fields[type];
if (son->attr & STOP) {
@@ -735,13 +738,14 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
}
beg = bs->cur;
- if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) >
- H323_ERROR_STOP)
+ if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) <
+ H323_ERROR_NONE)
return err;
bs->cur = beg + len;
bs->bit = 0;
- } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)))
+ } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) <
+ H323_ERROR_NONE)
return err;
return H323_ERROR_NONE;
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
index d716bba798f..8ccfe17bb25 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -469,8 +469,8 @@ pptp_inbound_pkt(struct sk_buff **pskb,
DEBUGP("%s but no session\n", pptp_msg_name[msg]);
break;
}
- if (info->sstate != PPTP_CALL_IN_REP
- && info->sstate != PPTP_CALL_IN_CONF) {
+ if (info->cstate != PPTP_CALL_IN_REP
+ && info->cstate != PPTP_CALL_IN_CONF) {
DEBUGP("%s but never sent IN_CALL_REPLY\n",
pptp_msg_name[msg]);
break;
@@ -766,7 +766,7 @@ extern void ip_ct_proto_gre_fini(void);
extern int __init ip_ct_proto_gre_init(void);
/* ip_conntrack_pptp initialization */
-static int __init init(void)
+static int __init ip_conntrack_helper_pptp_init(void)
{
int retcode;
@@ -786,15 +786,15 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ip_conntrack_helper_pptp_fini(void)
{
ip_conntrack_helper_unregister(&pptp);
ip_ct_proto_gre_fini();
printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_helper_pptp_init);
+module_exit(ip_conntrack_helper_pptp_fini);
EXPORT_SYMBOL(ip_nat_pptp_hook_outbound);
EXPORT_SYMBOL(ip_nat_pptp_hook_inbound);
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index c51a2cf71b4..a2ac5ce544b 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -242,9 +242,9 @@ static int help(struct sk_buff **pskb,
static struct ip_conntrack_helper irc_helpers[MAX_PORTS];
static char irc_names[MAX_PORTS][sizeof("irc-65535")];
-static void fini(void);
+static void ip_conntrack_irc_fini(void);
-static int __init init(void)
+static int __init ip_conntrack_irc_init(void)
{
int i, ret;
struct ip_conntrack_helper *hlpr;
@@ -288,7 +288,7 @@ static int __init init(void)
if (ret) {
printk("ip_conntrack_irc: ERROR registering port %d\n",
ports[i]);
- fini();
+ ip_conntrack_irc_fini();
return -EBUSY;
}
}
@@ -297,7 +297,7 @@ static int __init init(void)
/* This function is intentionally _NOT_ defined as __exit, because
* it is needed by the init function */
-static void fini(void)
+static void ip_conntrack_irc_fini(void)
{
int i;
for (i = 0; i < ports_c; i++) {
@@ -308,5 +308,5 @@ static void fini(void)
kfree(irc_buffer);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_irc_init);
+module_exit(ip_conntrack_irc_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
index 4e68e16a261..a566a81325b 100644
--- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
+++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
@@ -127,16 +127,16 @@ static struct ip_conntrack_helper helper = {
.help = help,
};
-static int __init init(void)
+static int __init ip_conntrack_netbios_ns_init(void)
{
helper.timeout = timeout;
return ip_conntrack_helper_register(&helper);
}
-static void __exit fini(void)
+static void __exit ip_conntrack_netbios_ns_fini(void)
{
ip_conntrack_helper_unregister(&helper);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_netbios_ns_init);
+module_exit(ip_conntrack_netbios_ns_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 9b6e19bae90..01bd7cab936 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -1658,7 +1658,7 @@ static void __exit ctnetlink_exit(void)
printk("ctnetlink: unregistering from nfnetlink.\n");
#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
- ip_conntrack_unregister_notifier(&ctnl_notifier_exp);
+ ip_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
ip_conntrack_unregister_notifier(&ctnl_notifier);
#endif
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 3021af0910f..d8b14a9010a 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -224,25 +224,14 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
}
/* See ip_conntrack_proto_tcp.c */
- if (hooknum != NF_IP_PRE_ROUTING)
- goto checksum_skipped;
-
- switch (skb->ip_summed) {
- case CHECKSUM_HW:
- if (!(u16)csum_fold(skb->csum))
- break;
- /* fall through */
- case CHECKSUM_NONE:
- skb->csum = 0;
- if (__skb_checksum_complete(skb)) {
- if (LOG_INVALID(IPPROTO_ICMP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
- "ip_ct_icmp: bad ICMP checksum ");
- return -NF_ACCEPT;
- }
+ if (hooknum == NF_IP_PRE_ROUTING &&
+ nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) {
+ if (LOG_INVALID(IPPROTO_ICMP))
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
+ "ip_ct_icmp: bad ICMP checksum ");
+ return -NF_ACCEPT;
}
-checksum_skipped:
/*
* 18 is the highest 'known' ICMP type. Anything else is a mystery
*
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
index be602e8aeab..0416073c560 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -235,12 +235,15 @@ static int do_basic_checks(struct ip_conntrack *conntrack,
flag = 1;
}
- /* Cookie Ack/Echo chunks not the first OR
- Init / Init Ack / Shutdown compl chunks not the only chunks */
- if ((sch->type == SCTP_CID_COOKIE_ACK
+ /*
+ * Cookie Ack/Echo chunks not the first OR
+ * Init / Init Ack / Shutdown compl chunks not the only chunks
+ * OR zero-length.
+ */
+ if (((sch->type == SCTP_CID_COOKIE_ACK
|| sch->type == SCTP_CID_COOKIE_ECHO
|| flag)
- && count !=0 ) {
+ && count !=0) || !sch->length) {
DEBUGP("Basic checks failed\n");
return 1;
}
@@ -609,7 +612,7 @@ static ctl_table ip_ct_net_table[] = {
static struct ctl_table_header *ip_ct_sysctl_header;
#endif
-static int __init init(void)
+static int __init ip_conntrack_proto_sctp_init(void)
{
int ret;
@@ -640,7 +643,7 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ip_conntrack_proto_sctp_fini(void)
{
ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
#ifdef CONFIG_SYSCTL
@@ -649,8 +652,8 @@ static void __exit fini(void)
DEBUGP("SCTP conntrack module unloaded\n");
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_proto_sctp_init);
+module_exit(ip_conntrack_proto_sctp_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kiran Kumar Immidi");
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index e0dc3706354..062b252b58a 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -870,11 +870,8 @@ static int tcp_error(struct sk_buff *skb,
* and moreover root might send raw packets.
*/
/* FIXME: Source route IP option packets --RR */
- if (hooknum == NF_IP_PRE_ROUTING
- && skb->ip_summed != CHECKSUM_UNNECESSARY
- && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
- skb->ip_summed == CHECKSUM_HW ? skb->csum
- : skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
+ if (hooknum == NF_IP_PRE_ROUTING &&
+ nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_tcp: bad TCP checksum ");
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index 55b7d3210ad..70899868783 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -120,11 +120,8 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
* because the semantic of CHECKSUM_HW is different there
* and moreover root might send raw packets.
* FIXME: Source route IP option packets --RR */
- if (hooknum == NF_IP_PRE_ROUTING
- && skb->ip_summed != CHECKSUM_UNNECESSARY
- && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
- skb->ip_summed == CHECKSUM_HW ? skb->csum
- : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
+ if (hooknum == NF_IP_PRE_ROUTING &&
+ nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"ip_ct_udp: bad UDP checksum ");
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 833fcb4be5e..929d61f7be9 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -469,70 +469,63 @@ static unsigned int ip_conntrack_local(unsigned int hooknum,
/* Connection tracking may drop packets, but never alters them, so
make it the first hook. */
-static struct nf_hook_ops ip_conntrack_defrag_ops = {
- .hook = ip_conntrack_defrag,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ip_conntrack_in_ops = {
- .hook = ip_conntrack_in,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
- .hook = ip_conntrack_defrag,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ip_conntrack_local_out_ops = {
- .hook = ip_conntrack_local,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_CONNTRACK,
-};
-
-/* helpers */
-static struct nf_hook_ops ip_conntrack_helper_out_ops = {
- .hook = ip_conntrack_help,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-static struct nf_hook_ops ip_conntrack_helper_in_ops = {
- .hook = ip_conntrack_help,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-/* Refragmenter; last chance. */
-static struct nf_hook_ops ip_conntrack_out_ops = {
- .hook = ip_confirm,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
-};
-
-static struct nf_hook_ops ip_conntrack_local_in_ops = {
- .hook = ip_confirm,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+static struct nf_hook_ops ip_conntrack_ops[] = {
+ {
+ .hook = ip_conntrack_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
+ },
+ {
+ .hook = ip_conntrack_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK,
+ },
+ {
+ .hook = ip_conntrack_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
+ },
+ {
+ .hook = ip_conntrack_local,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_CONNTRACK,
+ },
+ {
+ .hook = ip_conntrack_help,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_HELPER,
+ },
+ {
+ .hook = ip_conntrack_help,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_CONNTRACK_HELPER,
+ },
+ {
+ .hook = ip_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+ },
+ {
+ .hook = ip_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+ },
};
/* Sysctl support */
@@ -783,18 +776,46 @@ static ctl_table ip_ct_net_table[] = {
EXPORT_SYMBOL(ip_ct_log_invalid);
#endif /* CONFIG_SYSCTL */
-static int init_or_cleanup(int init)
+/* FIXME: Allow NULL functions and sub in pointers to generic for
+ them. --RR */
+int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
+{
+ int ret = 0;
+
+ write_lock_bh(&ip_conntrack_lock);
+ if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
+ ret = -EBUSY;
+ goto out;
+ }
+ ip_ct_protos[proto->proto] = proto;
+ out:
+ write_unlock_bh(&ip_conntrack_lock);
+ return ret;
+}
+
+void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
+{
+ write_lock_bh(&ip_conntrack_lock);
+ ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
+ write_unlock_bh(&ip_conntrack_lock);
+
+ /* Somebody could be still looking at the proto in bh. */
+ synchronize_net();
+
+ /* Remove all contrack entries for this protocol */
+ ip_ct_iterate_cleanup(kill_proto, &proto->proto);
+}
+
+static int __init ip_conntrack_standalone_init(void)
{
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc, *proc_exp, *proc_stat;
#endif
int ret = 0;
- if (!init) goto cleanup;
-
ret = ip_conntrack_init();
if (ret < 0)
- goto cleanup_nothing;
+ return ret;
#ifdef CONFIG_PROC_FS
ret = -ENOMEM;
@@ -813,78 +834,25 @@ static int init_or_cleanup(int init)
proc_stat->owner = THIS_MODULE;
#endif
- ret = nf_register_hook(&ip_conntrack_defrag_ops);
+ ret = nf_register_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
if (ret < 0) {
- printk("ip_conntrack: can't register pre-routing defrag hook.\n");
+ printk("ip_conntrack: can't register hooks.\n");
goto cleanup_proc_stat;
}
- ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register local_out defrag hook.\n");
- goto cleanup_defragops;
- }
- ret = nf_register_hook(&ip_conntrack_in_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register pre-routing hook.\n");
- goto cleanup_defraglocalops;
- }
- ret = nf_register_hook(&ip_conntrack_local_out_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register local out hook.\n");
- goto cleanup_inops;
- }
- ret = nf_register_hook(&ip_conntrack_helper_in_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register local in helper hook.\n");
- goto cleanup_inandlocalops;
- }
- ret = nf_register_hook(&ip_conntrack_helper_out_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register postrouting helper hook.\n");
- goto cleanup_helperinops;
- }
- ret = nf_register_hook(&ip_conntrack_out_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register post-routing hook.\n");
- goto cleanup_helperoutops;
- }
- ret = nf_register_hook(&ip_conntrack_local_in_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register local in hook.\n");
- goto cleanup_inoutandlocalops;
- }
#ifdef CONFIG_SYSCTL
ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
if (ip_ct_sysctl_header == NULL) {
printk("ip_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
- goto cleanup_localinops;
+ goto cleanup_hooks;
}
#endif
-
return ret;
- cleanup:
- synchronize_net();
#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(ip_ct_sysctl_header);
- cleanup_localinops:
+ cleanup_hooks:
+ nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
#endif
- nf_unregister_hook(&ip_conntrack_local_in_ops);
- cleanup_inoutandlocalops:
- nf_unregister_hook(&ip_conntrack_out_ops);
- cleanup_helperoutops:
- nf_unregister_hook(&ip_conntrack_helper_out_ops);
- cleanup_helperinops:
- nf_unregister_hook(&ip_conntrack_helper_in_ops);
- cleanup_inandlocalops:
- nf_unregister_hook(&ip_conntrack_local_out_ops);
- cleanup_inops:
- nf_unregister_hook(&ip_conntrack_in_ops);
- cleanup_defraglocalops:
- nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
- cleanup_defragops:
- nf_unregister_hook(&ip_conntrack_defrag_ops);
cleanup_proc_stat:
#ifdef CONFIG_PROC_FS
remove_proc_entry("ip_conntrack", proc_net_stat);
@@ -895,52 +863,26 @@ static int init_or_cleanup(int init)
cleanup_init:
#endif /* CONFIG_PROC_FS */
ip_conntrack_cleanup();
- cleanup_nothing:
- return ret;
-}
-
-/* FIXME: Allow NULL functions and sub in pointers to generic for
- them. --RR */
-int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
-{
- int ret = 0;
-
- write_lock_bh(&ip_conntrack_lock);
- if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
- ret = -EBUSY;
- goto out;
- }
- ip_ct_protos[proto->proto] = proto;
- out:
- write_unlock_bh(&ip_conntrack_lock);
return ret;
}
-void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
+static void __exit ip_conntrack_standalone_fini(void)
{
- write_lock_bh(&ip_conntrack_lock);
- ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
- write_unlock_bh(&ip_conntrack_lock);
-
- /* Somebody could be still looking at the proto in bh. */
synchronize_net();
-
- /* Remove all contrack entries for this protocol */
- ip_ct_iterate_cleanup(kill_proto, &proto->proto);
-}
-
-static int __init init(void)
-{
- return init_or_cleanup(1);
-}
-
-static void __exit fini(void)
-{
- init_or_cleanup(0);
+#ifdef CONFIG_SYSCTL
+ unregister_sysctl_table(ip_ct_sysctl_header);
+#endif
+ nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("ip_conntrack", proc_net_stat);
+ proc_net_remove("ip_conntrack_expect");
+ proc_net_remove("ip_conntrack");
+#endif /* CONFIG_PROC_FS */
+ ip_conntrack_cleanup();
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_standalone_init);
+module_exit(ip_conntrack_standalone_fini);
/* Some modules need us, but don't depend directly on any symbol.
They should call this. */
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index 4ba4463cec2..7e33d3bed5e 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -103,7 +103,7 @@ static int tftp_help(struct sk_buff **pskb,
static struct ip_conntrack_helper tftp[MAX_PORTS];
static char tftp_names[MAX_PORTS][sizeof("tftp-65535")];
-static void fini(void)
+static void ip_conntrack_tftp_fini(void)
{
int i;
@@ -114,7 +114,7 @@ static void fini(void)
}
}
-static int __init init(void)
+static int __init ip_conntrack_tftp_init(void)
{
int i, ret;
char *tmpname;
@@ -148,12 +148,12 @@ static int __init init(void)
if (ret) {
printk("ERROR registering helper for port %d\n",
ports[i]);
- fini();
+ ip_conntrack_tftp_fini();
return(ret);
}
}
return(0);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_tftp_init);
+module_exit(ip_conntrack_tftp_fini);
diff --git a/net/ipv4/netfilter/ip_nat_amanda.c b/net/ipv4/netfilter/ip_nat_amanda.c
index 706c8074f42..3a888715bbf 100644
--- a/net/ipv4/netfilter/ip_nat_amanda.c
+++ b/net/ipv4/netfilter/ip_nat_amanda.c
@@ -68,19 +68,19 @@ static unsigned int help(struct sk_buff **pskb,
return ret;
}
-static void __exit fini(void)
+static void __exit ip_nat_amanda_fini(void)
{
ip_nat_amanda_hook = NULL;
/* Make sure noone calls it, meanwhile. */
synchronize_net();
}
-static int __init init(void)
+static int __init ip_nat_amanda_init(void)
{
BUG_ON(ip_nat_amanda_hook);
ip_nat_amanda_hook = help;
return 0;
}
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_amanda_init);
+module_exit(ip_nat_amanda_fini);
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
index b8daab3c64a..3328fc5c5f5 100644
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ b/net/ipv4/netfilter/ip_nat_ftp.c
@@ -154,14 +154,14 @@ static unsigned int ip_nat_ftp(struct sk_buff **pskb,
return NF_ACCEPT;
}
-static void __exit fini(void)
+static void __exit ip_nat_ftp_fini(void)
{
ip_nat_ftp_hook = NULL;
/* Make sure noone calls it, meanwhile. */
synchronize_net();
}
-static int __init init(void)
+static int __init ip_nat_ftp_init(void)
{
BUG_ON(ip_nat_ftp_hook);
ip_nat_ftp_hook = ip_nat_ftp;
@@ -177,5 +177,5 @@ static int warn_set(const char *val, struct kernel_param *kp)
}
module_param_call(ports, warn_set, NULL, NULL, 0);
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_ftp_init);
+module_exit(ip_nat_ftp_fini);
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
index a0bc883928c..d45663d137a 100644
--- a/net/ipv4/netfilter/ip_nat_helper_h323.c
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -7,24 +7,6 @@
*
* Based on the 'brute force' H.323 NAT module by
* Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * Changes:
- * 2006-02-01 - initial version 0.1
- *
- * 2006-02-20 - version 0.2
- * 1. Changed source format to follow kernel conventions
- * 2. Deleted some unnecessary structures
- * 3. Minor fixes
- *
- * 2006-03-10 - version 0.3
- * 1. Added support for multiple TPKTs in one packet (suggested by
- * Patrick McHardy)
- * 2. Added support for non-linear skb (based on Patrick McHardy's patch)
- * 3. Eliminated unnecessary return code
- *
- * 2006-03-15 - version 0.4
- * 1. Added support for T.120 channels
- * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
*/
#include <linux/module.h>
@@ -41,65 +23,12 @@
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
-#include "ip_conntrack_helper_h323_asn1.h"
-
#if 0
#define DEBUGP printk
#else
#define DEBUGP(format, args...)
#endif
-extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
- u_int32_t * ip, u_int16_t * port);
-extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
- u_int32_t * ip, u_int16_t * port);
-extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
- struct ip_conntrack_expect *this);
-extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
- struct ip_conntrack_expect *this);
-extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
- unsigned char **data, int dataoff,
- H245_TransportAddress * addr,
- u_int32_t ip, u_int16_t port);
-extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
- unsigned char **data, int dataoff,
- TransportAddress * addr,
- u_int32_t ip, u_int16_t port);
-extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
- struct ip_conntrack * ct,
- enum ip_conntrack_info ctinfo,
- unsigned char **data,
- TransportAddress * addr, int count);
-extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
- struct ip_conntrack * ct,
- enum ip_conntrack_info ctinfo,
- unsigned char **data,
- TransportAddress * addr, int count);
-extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
- struct ip_conntrack * ct,
- enum ip_conntrack_info ctinfo,
- unsigned char **data, int dataoff,
- H245_TransportAddress * addr,
- u_int16_t port, u_int16_t rtp_port,
- struct ip_conntrack_expect * rtp_exp,
- struct ip_conntrack_expect * rtcp_exp);
-extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
- enum ip_conntrack_info ctinfo,
- unsigned char **data, int dataoff,
- H245_TransportAddress * addr, u_int16_t port,
- struct ip_conntrack_expect * exp);
-extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
- enum ip_conntrack_info ctinfo,
- unsigned char **data, int dataoff,
- TransportAddress * addr, u_int16_t port,
- struct ip_conntrack_expect * exp);
-extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
- enum ip_conntrack_info ctinfo,
- unsigned char **data, TransportAddress * addr,
- int idx, u_int16_t port,
- struct ip_conntrack_expect * exp);
-
-
/****************************************************************************/
static int set_addr(struct sk_buff **pskb,
unsigned char **data, int dataoff,
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
index b9c016c063b..f3977726ff0 100644
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -370,7 +370,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
extern int __init ip_nat_proto_gre_init(void);
extern void __exit ip_nat_proto_gre_fini(void);
-static int __init init(void)
+static int __init ip_nat_helper_pptp_init(void)
{
int ret;
@@ -396,7 +396,7 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ip_nat_helper_pptp_fini(void)
{
DEBUGP("cleanup_module\n" );
@@ -412,5 +412,5 @@ static void __exit fini(void)
printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_helper_pptp_init);
+module_exit(ip_nat_helper_pptp_fini);
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
index 461c833eaca..a767123e082 100644
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ b/net/ipv4/netfilter/ip_nat_irc.c
@@ -96,14 +96,14 @@ static unsigned int help(struct sk_buff **pskb,
return ret;
}
-static void __exit fini(void)
+static void __exit ip_nat_irc_fini(void)
{
ip_nat_irc_hook = NULL;
/* Make sure noone calls it, meanwhile. */
synchronize_net();
}
-static int __init init(void)
+static int __init ip_nat_irc_init(void)
{
BUG_ON(ip_nat_irc_hook);
ip_nat_irc_hook = help;
@@ -119,5 +119,5 @@ static int warn_set(const char *val, struct kernel_param *kp)
}
module_param_call(ports, warn_set, NULL, NULL, 0);
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_irc_init);
+module_exit(ip_nat_irc_fini);
diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c
index 6c4899d8046..96ceabaec40 100644
--- a/net/ipv4/netfilter/ip_nat_proto_gre.c
+++ b/net/ipv4/netfilter/ip_nat_proto_gre.c
@@ -49,15 +49,15 @@ gre_in_range(const struct ip_conntrack_tuple *tuple,
const union ip_conntrack_manip_proto *min,
const union ip_conntrack_manip_proto *max)
{
- u_int32_t key;
+ __be16 key;
if (maniptype == IP_NAT_MANIP_SRC)
key = tuple->src.u.gre.key;
else
key = tuple->dst.u.gre.key;
- return ntohl(key) >= ntohl(min->gre.key)
- && ntohl(key) <= ntohl(max->gre.key);
+ return ntohs(key) >= ntohs(min->gre.key)
+ && ntohs(key) <= ntohs(max->gre.key);
}
/* generate unique tuple ... */
@@ -81,14 +81,14 @@ gre_unique_tuple(struct ip_conntrack_tuple *tuple,
min = 1;
range_size = 0xffff;
} else {
- min = ntohl(range->min.gre.key);
- range_size = ntohl(range->max.gre.key) - min + 1;
+ min = ntohs(range->min.gre.key);
+ range_size = ntohs(range->max.gre.key) - min + 1;
}
DEBUGP("min = %u, range_size = %u\n", min, range_size);
for (i = 0; i < range_size; i++, key++) {
- *keyptr = htonl(min + key % range_size);
+ *keyptr = htons(min + key % range_size);
if (!ip_nat_used_tuple(tuple, conntrack))
return 1;
}
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index efba8c4e42e..1aba926c1cb 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -279,7 +279,7 @@ static struct ipt_target ipt_dnat_reg = {
.target = ipt_dnat_target,
.targetsize = sizeof(struct ip_nat_multi_range_compat),
.table = "nat",
- .hooks = 1 << NF_IP_PRE_ROUTING,
+ .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
.checkentry = ipt_dnat_checkentry,
};
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index f029da2a60e..c33244263b9 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -768,6 +768,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
len *= sizeof(unsigned long);
*obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
if (*obj == NULL) {
+ kfree(lp);
kfree(id);
if (net_ratelimit())
printk("OOM in bsalg (%d)\n", __LINE__);
@@ -1003,12 +1004,12 @@ static unsigned char snmp_trap_decode(struct asn1_ctx *ctx,
return 1;
+err_addr_free:
+ kfree((unsigned long *)trap->ip_address);
+
err_id_free:
kfree(trap->id);
-err_addr_free:
- kfree((unsigned long *)trap->ip_address);
-
return 0;
}
@@ -1126,11 +1127,10 @@ static int snmp_parse_mangle(unsigned char *msg,
struct snmp_v1_trap trap;
unsigned char ret = snmp_trap_decode(&ctx, &trap, map, check);
- /* Discard trap allocations regardless */
- kfree(trap.id);
- kfree((unsigned long *)trap.ip_address);
-
- if (!ret)
+ if (ret) {
+ kfree(trap.id);
+ kfree((unsigned long *)trap.ip_address);
+ } else
return ret;
} else {
@@ -1324,7 +1324,7 @@ static struct ip_conntrack_helper snmp_trap_helper = {
*
*****************************************************************************/
-static int __init init(void)
+static int __init ip_nat_snmp_basic_init(void)
{
int ret = 0;
@@ -1339,13 +1339,13 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ip_nat_snmp_basic_fini(void)
{
ip_conntrack_helper_unregister(&snmp_helper);
ip_conntrack_helper_unregister(&snmp_trap_helper);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_snmp_basic_init);
+module_exit(ip_nat_snmp_basic_fini);
module_param(debug, bool, 0600);
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 380aef3d786..67e676783da 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -219,8 +219,10 @@ ip_nat_out(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
+#ifdef CONFIG_XFRM
struct ip_conntrack *ct;
enum ip_conntrack_info ctinfo;
+#endif
unsigned int ret;
/* root is playing with raw sockets. */
@@ -299,69 +301,63 @@ ip_nat_adjust(unsigned int hooknum,
/* We must be after connection tracking and before packet filtering. */
-/* Before packet filtering, change destination */
-static struct nf_hook_ops ip_nat_in_ops = {
- .hook = ip_nat_in,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_NAT_DST,
-};
-
-/* After packet filtering, change source */
-static struct nf_hook_ops ip_nat_out_ops = {
- .hook = ip_nat_out,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_NAT_SRC,
-};
-
-/* After conntrack, adjust sequence number */
-static struct nf_hook_ops ip_nat_adjust_out_ops = {
- .hook = ip_nat_adjust,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
-};
-
-/* Before packet filtering, change destination */
-static struct nf_hook_ops ip_nat_local_out_ops = {
- .hook = ip_nat_local_fn,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_NAT_DST,
+static struct nf_hook_ops ip_nat_ops[] = {
+ /* Before packet filtering, change destination */
+ {
+ .hook = ip_nat_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_NAT_DST,
+ },
+ /* After packet filtering, change source */
+ {
+ .hook = ip_nat_out,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_NAT_SRC,
+ },
+ /* After conntrack, adjust sequence number */
+ {
+ .hook = ip_nat_adjust,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
+ },
+ /* Before packet filtering, change destination */
+ {
+ .hook = ip_nat_local_fn,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_NAT_DST,
+ },
+ /* After packet filtering, change source */
+ {
+ .hook = ip_nat_fn,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_NAT_SRC,
+ },
+ /* After conntrack, adjust sequence number */
+ {
+ .hook = ip_nat_adjust,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
+ },
};
-/* After packet filtering, change source for reply packets of LOCAL_OUT DNAT */
-static struct nf_hook_ops ip_nat_local_in_ops = {
- .hook = ip_nat_fn,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_NAT_SRC,
-};
-
-/* After conntrack, adjust sequence number */
-static struct nf_hook_ops ip_nat_adjust_in_ops = {
- .hook = ip_nat_adjust,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
-};
-
-
-static int init_or_cleanup(int init)
+static int __init ip_nat_standalone_init(void)
{
int ret = 0;
need_conntrack();
- if (!init) goto cleanup;
-
#ifdef CONFIG_XFRM
BUG_ON(ip_nat_decode_session != NULL);
ip_nat_decode_session = nat_decode_session;
@@ -371,50 +367,13 @@ static int init_or_cleanup(int init)
printk("ip_nat_init: can't setup rules.\n");
goto cleanup_decode_session;
}
- ret = nf_register_hook(&ip_nat_in_ops);
+ ret = nf_register_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
if (ret < 0) {
- printk("ip_nat_init: can't register in hook.\n");
+ printk("ip_nat_init: can't register hooks.\n");
goto cleanup_rule_init;
}
- ret = nf_register_hook(&ip_nat_out_ops);
- if (ret < 0) {
- printk("ip_nat_init: can't register out hook.\n");
- goto cleanup_inops;
- }
- ret = nf_register_hook(&ip_nat_adjust_in_ops);
- if (ret < 0) {
- printk("ip_nat_init: can't register adjust in hook.\n");
- goto cleanup_outops;
- }
- ret = nf_register_hook(&ip_nat_adjust_out_ops);
- if (ret < 0) {
- printk("ip_nat_init: can't register adjust out hook.\n");
- goto cleanup_adjustin_ops;
- }
- ret = nf_register_hook(&ip_nat_local_out_ops);
- if (ret < 0) {
- printk("ip_nat_init: can't register local out hook.\n");
- goto cleanup_adjustout_ops;
- }
- ret = nf_register_hook(&ip_nat_local_in_ops);
- if (ret < 0) {
- printk("ip_nat_init: can't register local in hook.\n");
- goto cleanup_localoutops;
- }
return ret;
- cleanup:
- nf_unregister_hook(&ip_nat_local_in_ops);
- cleanup_localoutops:
- nf_unregister_hook(&ip_nat_local_out_ops);
- cleanup_adjustout_ops:
- nf_unregister_hook(&ip_nat_adjust_out_ops);
- cleanup_adjustin_ops:
- nf_unregister_hook(&ip_nat_adjust_in_ops);
- cleanup_outops:
- nf_unregister_hook(&ip_nat_out_ops);
- cleanup_inops:
- nf_unregister_hook(&ip_nat_in_ops);
cleanup_rule_init:
ip_nat_rule_cleanup();
cleanup_decode_session:
@@ -425,17 +384,17 @@ static int init_or_cleanup(int init)
return ret;
}
-static int __init init(void)
+static void __exit ip_nat_standalone_fini(void)
{
- return init_or_cleanup(1);
-}
-
-static void __exit fini(void)
-{
- init_or_cleanup(0);
+ nf_unregister_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
+ ip_nat_rule_cleanup();
+#ifdef CONFIG_XFRM
+ ip_nat_decode_session = NULL;
+ synchronize_net();
+#endif
}
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_standalone_init);
+module_exit(ip_nat_standalone_fini);
MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c
index 43c3bd7c118..94a78015451 100644
--- a/net/ipv4/netfilter/ip_nat_tftp.c
+++ b/net/ipv4/netfilter/ip_nat_tftp.c
@@ -53,19 +53,19 @@ static unsigned int help(struct sk_buff **pskb,
return NF_ACCEPT;
}
-static void __exit fini(void)
+static void __exit ip_nat_tftp_fini(void)
{
ip_nat_tftp_hook = NULL;
/* Make sure noone calls it, meanwhile. */
synchronize_net();
}
-static int __init init(void)
+static int __init ip_nat_tftp_init(void)
{
BUG_ON(ip_nat_tftp_hook);
ip_nat_tftp_hook = help;
return 0;
}
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_tftp_init);
+module_exit(ip_nat_tftp_fini);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 1655866c55b..b93f0494362 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -662,15 +662,11 @@ static struct nf_queue_handler nfqh = {
.outfn = &ipq_enqueue_packet,
};
-static int
-init_or_cleanup(int init)
+static int __init ip_queue_init(void)
{
int status = -ENOMEM;
struct proc_dir_entry *proc;
- if (!init)
- goto cleanup;
-
netlink_register_notifier(&ipq_nl_notifier);
ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
THIS_MODULE);
@@ -697,11 +693,6 @@ init_or_cleanup(int init)
}
return status;
-cleanup:
- nf_unregister_queue_handlers(&nfqh);
- synchronize_net();
- ipq_flush(NF_DROP);
-
cleanup_sysctl:
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
@@ -717,20 +708,26 @@ cleanup_netlink_notifier:
return status;
}
-static int __init init(void)
+static void __exit ip_queue_fini(void)
{
-
- return init_or_cleanup(1);
-}
+ nf_unregister_queue_handlers(&nfqh);
+ synchronize_net();
+ ipq_flush(NF_DROP);
-static void __exit fini(void)
-{
- init_or_cleanup(0);
+ unregister_sysctl_table(ipq_sysctl_header);
+ unregister_netdevice_notifier(&ipq_dev_notifier);
+ proc_net_remove(IPQ_PROC_FS_NAME);
+
+ sock_release(ipqnl->sk_socket);
+ mutex_lock(&ipqnl_mutex);
+ mutex_unlock(&ipqnl_mutex);
+
+ netlink_unregister_notifier(&ipq_nl_notifier);
}
MODULE_DESCRIPTION("IPv4 packet queue handler");
MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
MODULE_LICENSE("GPL");
-module_init(init);
-module_exit(fini);
+module_init(ip_queue_init);
+module_exit(ip_queue_fini);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index a7b194c4d79..cee3397ec27 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/icmp.h>
#include <net/ip.h>
+#include <net/compat.h>
#include <asm/uaccess.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
@@ -734,7 +735,7 @@ translate_table(const char *name,
}
/* And one copy for every other CPU */
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
if (newinfo->entries[i] && newinfo->entries[i] != entry0)
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
@@ -787,7 +788,7 @@ get_counters(const struct xt_table_info *t,
counters,
&i);
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (cpu == curcpu)
continue;
i = 0;
@@ -799,17 +800,11 @@ get_counters(const struct xt_table_info *t,
}
}
-static int
-copy_entries_to_user(unsigned int total_size,
- struct ipt_table *table,
- void __user *userptr)
+static inline struct xt_counters * alloc_counters(struct ipt_table *table)
{
- unsigned int off, num, countersize;
- struct ipt_entry *e;
+ unsigned int countersize;
struct xt_counters *counters;
struct xt_table_info *private = table->private;
- int ret = 0;
- void *loc_cpu_entry;
/* We need atomic snapshot of counters: rest doesn't change
(other than comefrom, which userspace doesn't care
@@ -818,13 +813,32 @@ copy_entries_to_user(unsigned int total_size,
counters = vmalloc_node(countersize, numa_node_id());
if (counters == NULL)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
/* First, sum counters... */
write_lock_bh(&table->lock);
get_counters(private, counters);
write_unlock_bh(&table->lock);
+ return counters;
+}
+
+static int
+copy_entries_to_user(unsigned int total_size,
+ struct ipt_table *table,
+ void __user *userptr)
+{
+ unsigned int off, num;
+ struct ipt_entry *e;
+ struct xt_counters *counters;
+ struct xt_table_info *private = table->private;
+ int ret = 0;
+ void *loc_cpu_entry;
+
+ counters = alloc_counters(table);
+ if (IS_ERR(counters))
+ return PTR_ERR(counters);
+
/* choose the copy that is on our node/cpu, ...
* This choice is lazy (because current thread is
* allowed to migrate to another cpu)
@@ -884,25 +898,273 @@ copy_entries_to_user(unsigned int total_size,
return ret;
}
+#ifdef CONFIG_COMPAT
+struct compat_delta {
+ struct compat_delta *next;
+ u_int16_t offset;
+ short delta;
+};
+
+static struct compat_delta *compat_offsets = NULL;
+
+static int compat_add_offset(u_int16_t offset, short delta)
+{
+ struct compat_delta *tmp;
+
+ tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+ tmp->offset = offset;
+ tmp->delta = delta;
+ if (compat_offsets) {
+ tmp->next = compat_offsets->next;
+ compat_offsets->next = tmp;
+ } else {
+ compat_offsets = tmp;
+ tmp->next = NULL;
+ }
+ return 0;
+}
+
+static void compat_flush_offsets(void)
+{
+ struct compat_delta *tmp, *next;
+
+ if (compat_offsets) {
+ for(tmp = compat_offsets; tmp; tmp = next) {
+ next = tmp->next;
+ kfree(tmp);
+ }
+ compat_offsets = NULL;
+ }
+}
+
+static short compat_calc_jump(u_int16_t offset)
+{
+ struct compat_delta *tmp;
+ short delta;
+
+ for(tmp = compat_offsets, delta = 0; tmp; tmp = tmp->next)
+ if (tmp->offset < offset)
+ delta += tmp->delta;
+ return delta;
+}
+
+struct compat_ipt_standard_target
+{
+ struct compat_xt_entry_target target;
+ compat_int_t verdict;
+};
+
+struct compat_ipt_standard
+{
+ struct compat_ipt_entry entry;
+ struct compat_ipt_standard_target target;
+};
+
+#define IPT_ST_LEN XT_ALIGN(sizeof(struct ipt_standard_target))
+#define IPT_ST_COMPAT_LEN COMPAT_XT_ALIGN(sizeof(struct compat_ipt_standard_target))
+#define IPT_ST_OFFSET (IPT_ST_LEN - IPT_ST_COMPAT_LEN)
+
+static int compat_ipt_standard_fn(void *target,
+ void **dstptr, int *size, int convert)
+{
+ struct compat_ipt_standard_target compat_st, *pcompat_st;
+ struct ipt_standard_target st, *pst;
+ int ret;
+
+ ret = 0;
+ switch (convert) {
+ case COMPAT_TO_USER:
+ pst = target;
+ memcpy(&compat_st.target, &pst->target,
+ sizeof(compat_st.target));
+ compat_st.verdict = pst->verdict;
+ if (compat_st.verdict > 0)
+ compat_st.verdict -=
+ compat_calc_jump(compat_st.verdict);
+ compat_st.target.u.user.target_size = IPT_ST_COMPAT_LEN;
+ if (copy_to_user(*dstptr, &compat_st, IPT_ST_COMPAT_LEN))
+ ret = -EFAULT;
+ *size -= IPT_ST_OFFSET;
+ *dstptr += IPT_ST_COMPAT_LEN;
+ break;
+ case COMPAT_FROM_USER:
+ pcompat_st = target;
+ memcpy(&st.target, &pcompat_st->target, IPT_ST_COMPAT_LEN);
+ st.verdict = pcompat_st->verdict;
+ if (st.verdict > 0)
+ st.verdict += compat_calc_jump(st.verdict);
+ st.target.u.user.target_size = IPT_ST_LEN;
+ memcpy(*dstptr, &st, IPT_ST_LEN);
+ *size += IPT_ST_OFFSET;
+ *dstptr += IPT_ST_LEN;
+ break;
+ case COMPAT_CALC_SIZE:
+ *size += IPT_ST_OFFSET;
+ break;
+ default:
+ ret = -ENOPROTOOPT;
+ break;
+ }
+ return ret;
+}
+
+static inline int
+compat_calc_match(struct ipt_entry_match *m, int * size)
+{
+ if (m->u.kernel.match->compat)
+ m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
+ else
+ xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
+ return 0;
+}
+
+static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info,
+ void *base, struct xt_table_info *newinfo)
+{
+ struct ipt_entry_target *t;
+ u_int16_t entry_offset;
+ int off, i, ret;
+
+ off = 0;
+ entry_offset = (void *)e - base;
+ IPT_MATCH_ITERATE(e, compat_calc_match, &off);
+ t = ipt_get_target(e);
+ if (t->u.kernel.target->compat)
+ t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
+ else
+ xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
+ newinfo->size -= off;
+ ret = compat_add_offset(entry_offset, off);
+ if (ret)
+ return ret;
+
+ for (i = 0; i< NF_IP_NUMHOOKS; i++) {
+ if (info->hook_entry[i] && (e < (struct ipt_entry *)
+ (base + info->hook_entry[i])))
+ newinfo->hook_entry[i] -= off;
+ if (info->underflow[i] && (e < (struct ipt_entry *)
+ (base + info->underflow[i])))
+ newinfo->underflow[i] -= off;
+ }
+ return 0;
+}
+
+static int compat_table_info(struct xt_table_info *info,
+ struct xt_table_info *newinfo)
+{
+ void *loc_cpu_entry;
+ int i;
+
+ if (!newinfo || !info)
+ return -EINVAL;
+
+ memset(newinfo, 0, sizeof(struct xt_table_info));
+ newinfo->size = info->size;
+ newinfo->number = info->number;
+ for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ newinfo->hook_entry[i] = info->hook_entry[i];
+ newinfo->underflow[i] = info->underflow[i];
+ }
+ loc_cpu_entry = info->entries[raw_smp_processor_id()];
+ return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
+ compat_calc_entry, info, loc_cpu_entry, newinfo);
+}
+#endif
+
+static int get_info(void __user *user, int *len, int compat)
+{
+ char name[IPT_TABLE_MAXNAMELEN];
+ struct ipt_table *t;
+ int ret;
+
+ if (*len != sizeof(struct ipt_getinfo)) {
+ duprintf("length %u != %u\n", *len,
+ (unsigned int)sizeof(struct ipt_getinfo));
+ return -EINVAL;
+ }
+
+ if (copy_from_user(name, user, sizeof(name)) != 0)
+ return -EFAULT;
+
+ name[IPT_TABLE_MAXNAMELEN-1] = '\0';
+#ifdef CONFIG_COMPAT
+ if (compat)
+ xt_compat_lock(AF_INET);
+#endif
+ t = try_then_request_module(xt_find_table_lock(AF_INET, name),
+ "iptable_%s", name);
+ if (t && !IS_ERR(t)) {
+ struct ipt_getinfo info;
+ struct xt_table_info *private = t->private;
+
+#ifdef CONFIG_COMPAT
+ if (compat) {
+ struct xt_table_info tmp;
+ ret = compat_table_info(private, &tmp);
+ compat_flush_offsets();
+ private = &tmp;
+ }
+#endif
+ info.valid_hooks = t->valid_hooks;
+ memcpy(info.hook_entry, private->hook_entry,
+ sizeof(info.hook_entry));
+ memcpy(info.underflow, private->underflow,
+ sizeof(info.underflow));
+ info.num_entries = private->number;
+ info.size = private->size;
+ strcpy(info.name, name);
+
+ if (copy_to_user(user, &info, *len) != 0)
+ ret = -EFAULT;
+ else
+ ret = 0;
+
+ xt_table_unlock(t);
+ module_put(t->me);
+ } else
+ ret = t ? PTR_ERR(t) : -ENOENT;
+#ifdef CONFIG_COMPAT
+ if (compat)
+ xt_compat_unlock(AF_INET);
+#endif
+ return ret;
+}
+
static int
-get_entries(const struct ipt_get_entries *entries,
- struct ipt_get_entries __user *uptr)
+get_entries(struct ipt_get_entries __user *uptr, int *len)
{
int ret;
+ struct ipt_get_entries get;
struct ipt_table *t;
- t = xt_find_table_lock(AF_INET, entries->name);
+ if (*len < sizeof(get)) {
+ duprintf("get_entries: %u < %d\n", *len,
+ (unsigned int)sizeof(get));
+ return -EINVAL;
+ }
+ if (copy_from_user(&get, uptr, sizeof(get)) != 0)
+ return -EFAULT;
+ if (*len != sizeof(struct ipt_get_entries) + get.size) {
+ duprintf("get_entries: %u != %u\n", *len,
+ (unsigned int)(sizeof(struct ipt_get_entries) +
+ get.size));
+ return -EINVAL;
+ }
+
+ t = xt_find_table_lock(AF_INET, get.name);
if (t && !IS_ERR(t)) {
struct xt_table_info *private = t->private;
duprintf("t->private->number = %u\n",
private->number);
- if (entries->size == private->size)
+ if (get.size == private->size)
ret = copy_entries_to_user(private->size,
t, uptr->entrytable);
else {
duprintf("get_entries: I've got %u not %u!\n",
private->size,
- entries->size);
+ get.size);
ret = -EINVAL;
}
module_put(t->me);
@@ -914,79 +1176,47 @@ get_entries(const struct ipt_get_entries *entries,
}
static int
-do_replace(void __user *user, unsigned int len)
+__do_replace(const char *name, unsigned int valid_hooks,
+ struct xt_table_info *newinfo, unsigned int num_counters,
+ void __user *counters_ptr)
{
int ret;
- struct ipt_replace tmp;
struct ipt_table *t;
- struct xt_table_info *newinfo, *oldinfo;
+ struct xt_table_info *oldinfo;
struct xt_counters *counters;
- void *loc_cpu_entry, *loc_cpu_old_entry;
+ void *loc_cpu_old_entry;
- if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
- return -EFAULT;
-
- /* Hack: Causes ipchains to give correct error msg --RR */
- if (len != sizeof(tmp) + tmp.size)
- return -ENOPROTOOPT;
-
- /* overflow check */
- if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
- SMP_CACHE_BYTES)
- return -ENOMEM;
- if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
- return -ENOMEM;
-
- newinfo = xt_alloc_table_info(tmp.size);
- if (!newinfo)
- return -ENOMEM;
-
- /* choose the copy that is our node/cpu */
- loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
- if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
- tmp.size) != 0) {
- ret = -EFAULT;
- goto free_newinfo;
- }
-
- counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
+ ret = 0;
+ counters = vmalloc(num_counters * sizeof(struct xt_counters));
if (!counters) {
ret = -ENOMEM;
- goto free_newinfo;
+ goto out;
}
- ret = translate_table(tmp.name, tmp.valid_hooks,
- newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
- tmp.hook_entry, tmp.underflow);
- if (ret != 0)
- goto free_newinfo_counters;
-
- duprintf("ip_tables: Translated table\n");
-
- t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name),
- "iptable_%s", tmp.name);
+ t = try_then_request_module(xt_find_table_lock(AF_INET, name),
+ "iptable_%s", name);
if (!t || IS_ERR(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
goto free_newinfo_counters_untrans;
}
/* You lied! */
- if (tmp.valid_hooks != t->valid_hooks) {
+ if (valid_hooks != t->valid_hooks) {
duprintf("Valid hook crap: %08X vs %08X\n",
- tmp.valid_hooks, t->valid_hooks);
+ valid_hooks, t->valid_hooks);
ret = -EINVAL;
goto put_module;
}
- oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
+ oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
if (!oldinfo)
goto put_module;
/* Update module usage count based on number of rules */
duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
oldinfo->number, oldinfo->initial_entries, newinfo->number);
- if ((oldinfo->number > oldinfo->initial_entries) ||
- (newinfo->number <= oldinfo->initial_entries))
+ if ((oldinfo->number > oldinfo->initial_entries) ||
+ (newinfo->number <= oldinfo->initial_entries))
module_put(t->me);
if ((oldinfo->number > oldinfo->initial_entries) &&
(newinfo->number <= oldinfo->initial_entries))
@@ -998,8 +1228,8 @@ do_replace(void __user *user, unsigned int len)
loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
xt_free_table_info(oldinfo);
- if (copy_to_user(tmp.counters, counters,
- sizeof(struct xt_counters) * tmp.num_counters) != 0)
+ if (copy_to_user(counters_ptr, counters,
+ sizeof(struct xt_counters) * num_counters) != 0)
ret = -EFAULT;
vfree(counters);
xt_table_unlock(t);
@@ -1009,9 +1239,62 @@ do_replace(void __user *user, unsigned int len)
module_put(t->me);
xt_table_unlock(t);
free_newinfo_counters_untrans:
- IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
- free_newinfo_counters:
vfree(counters);
+ out:
+ return ret;
+}
+
+static int
+do_replace(void __user *user, unsigned int len)
+{
+ int ret;
+ struct ipt_replace tmp;
+ struct xt_table_info *newinfo;
+ void *loc_cpu_entry;
+
+ if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+ return -EFAULT;
+
+ /* Hack: Causes ipchains to give correct error msg --RR */
+ if (len != sizeof(tmp) + tmp.size)
+ return -ENOPROTOOPT;
+
+ /* overflow check */
+ if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
+ SMP_CACHE_BYTES)
+ return -ENOMEM;
+ if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
+ return -ENOMEM;
+
+ newinfo = xt_alloc_table_info(tmp.size);
+ if (!newinfo)
+ return -ENOMEM;
+
+ /* choose the copy that is our node/cpu */
+ loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+ if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
+ tmp.size) != 0) {
+ ret = -EFAULT;
+ goto free_newinfo;
+ }
+
+ ret = translate_table(tmp.name, tmp.valid_hooks,
+ newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
+ tmp.hook_entry, tmp.underflow);
+ if (ret != 0)
+ goto free_newinfo;
+
+ duprintf("ip_tables: Translated table\n");
+
+ ret = __do_replace(tmp.name, tmp.valid_hooks,
+ newinfo, tmp.num_counters,
+ tmp.counters);
+ if (ret)
+ goto free_newinfo_untrans;
+ return 0;
+
+ free_newinfo_untrans:
+ IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
free_newinfo:
xt_free_table_info(newinfo);
return ret;
@@ -1040,31 +1323,59 @@ add_counter_to_entry(struct ipt_entry *e,
}
static int
-do_add_counters(void __user *user, unsigned int len)
+do_add_counters(void __user *user, unsigned int len, int compat)
{
unsigned int i;
- struct xt_counters_info tmp, *paddc;
+ struct xt_counters_info tmp;
+ struct xt_counters *paddc;
+ unsigned int num_counters;
+ char *name;
+ int size;
+ void *ptmp;
struct ipt_table *t;
struct xt_table_info *private;
int ret = 0;
void *loc_cpu_entry;
+#ifdef CONFIG_COMPAT
+ struct compat_xt_counters_info compat_tmp;
- if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+ if (compat) {
+ ptmp = &compat_tmp;
+ size = sizeof(struct compat_xt_counters_info);
+ } else
+#endif
+ {
+ ptmp = &tmp;
+ size = sizeof(struct xt_counters_info);
+ }
+
+ if (copy_from_user(ptmp, user, size) != 0)
return -EFAULT;
- if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
+#ifdef CONFIG_COMPAT
+ if (compat) {
+ num_counters = compat_tmp.num_counters;
+ name = compat_tmp.name;
+ } else
+#endif
+ {
+ num_counters = tmp.num_counters;
+ name = tmp.name;
+ }
+
+ if (len != size + num_counters * sizeof(struct xt_counters))
return -EINVAL;
- paddc = vmalloc_node(len, numa_node_id());
+ paddc = vmalloc_node(len - size, numa_node_id());
if (!paddc)
return -ENOMEM;
- if (copy_from_user(paddc, user, len) != 0) {
+ if (copy_from_user(paddc, user + size, len - size) != 0) {
ret = -EFAULT;
goto free;
}
- t = xt_find_table_lock(AF_INET, tmp.name);
+ t = xt_find_table_lock(AF_INET, name);
if (!t || IS_ERR(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
goto free;
@@ -1072,7 +1383,7 @@ do_add_counters(void __user *user, unsigned int len)
write_lock_bh(&t->lock);
private = t->private;
- if (private->number != paddc->num_counters) {
+ if (private->number != num_counters) {
ret = -EINVAL;
goto unlock_up_free;
}
@@ -1083,7 +1394,7 @@ do_add_counters(void __user *user, unsigned int len)
IPT_ENTRY_ITERATE(loc_cpu_entry,
private->size,
add_counter_to_entry,
- paddc->counters,
+ paddc,
&i);
unlock_up_free:
write_unlock_bh(&t->lock);
@@ -1095,8 +1406,438 @@ do_add_counters(void __user *user, unsigned int len)
return ret;
}
+#ifdef CONFIG_COMPAT
+struct compat_ipt_replace {
+ char name[IPT_TABLE_MAXNAMELEN];
+ u32 valid_hooks;
+ u32 num_entries;
+ u32 size;
+ u32 hook_entry[NF_IP_NUMHOOKS];
+ u32 underflow[NF_IP_NUMHOOKS];
+ u32 num_counters;
+ compat_uptr_t counters; /* struct ipt_counters * */
+ struct compat_ipt_entry entries[0];
+};
+
+static inline int compat_copy_match_to_user(struct ipt_entry_match *m,
+ void __user **dstptr, compat_uint_t *size)
+{
+ if (m->u.kernel.match->compat)
+ return m->u.kernel.match->compat(m, dstptr, size,
+ COMPAT_TO_USER);
+ else
+ return xt_compat_match(m, dstptr, size, COMPAT_TO_USER);
+}
+
+static int compat_copy_entry_to_user(struct ipt_entry *e,
+ void __user **dstptr, compat_uint_t *size)
+{
+ struct ipt_entry_target __user *t;
+ struct compat_ipt_entry __user *ce;
+ u_int16_t target_offset, next_offset;
+ compat_uint_t origsize;
+ int ret;
+
+ ret = -EFAULT;
+ origsize = *size;
+ ce = (struct compat_ipt_entry __user *)*dstptr;
+ if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
+ goto out;
+
+ *dstptr += sizeof(struct compat_ipt_entry);
+ ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size);
+ target_offset = e->target_offset - (origsize - *size);
+ if (ret)
+ goto out;
+ t = ipt_get_target(e);
+ if (t->u.kernel.target->compat)
+ ret = t->u.kernel.target->compat(t, dstptr, size,
+ COMPAT_TO_USER);
+ else
+ ret = xt_compat_target(t, dstptr, size, COMPAT_TO_USER);
+ if (ret)
+ goto out;
+ ret = -EFAULT;
+ next_offset = e->next_offset - (origsize - *size);
+ if (put_user(target_offset, &ce->target_offset))
+ goto out;
+ if (put_user(next_offset, &ce->next_offset))
+ goto out;
+ return 0;
+out:
+ return ret;
+}
+
+static inline int
+compat_check_calc_match(struct ipt_entry_match *m,
+ const char *name,
+ const struct ipt_ip *ip,
+ unsigned int hookmask,
+ int *size, int *i)
+{
+ struct ipt_match *match;
+
+ match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
+ m->u.user.revision),
+ "ipt_%s", m->u.user.name);
+ if (IS_ERR(match) || !match) {
+ duprintf("compat_check_calc_match: `%s' not found\n",
+ m->u.user.name);
+ return match ? PTR_ERR(match) : -ENOENT;
+ }
+ m->u.kernel.match = match;
+
+ if (m->u.kernel.match->compat)
+ m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
+ else
+ xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
+
+ (*i)++;
+ return 0;
+}
+
+static inline int
+check_compat_entry_size_and_hooks(struct ipt_entry *e,
+ struct xt_table_info *newinfo,
+ unsigned int *size,
+ unsigned char *base,
+ unsigned char *limit,
+ unsigned int *hook_entries,
+ unsigned int *underflows,
+ unsigned int *i,
+ const char *name)
+{
+ struct ipt_entry_target *t;
+ struct ipt_target *target;
+ u_int16_t entry_offset;
+ int ret, off, h, j;
+
+ duprintf("check_compat_entry_size_and_hooks %p\n", e);
+ if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
+ || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
+ duprintf("Bad offset %p, limit = %p\n", e, limit);
+ return -EINVAL;
+ }
+
+ if (e->next_offset < sizeof(struct compat_ipt_entry) +
+ sizeof(struct compat_xt_entry_target)) {
+ duprintf("checking: element %p size %u\n",
+ e, e->next_offset);
+ return -EINVAL;
+ }
+
+ if (!ip_checkentry(&e->ip)) {
+ duprintf("ip_tables: ip check failed %p %s.\n", e, name);
+ return -EINVAL;
+ }
+
+ off = 0;
+ entry_offset = (void *)e - (void *)base;
+ j = 0;
+ ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip,
+ e->comefrom, &off, &j);
+ if (ret != 0)
+ goto out;
+
+ t = ipt_get_target(e);
+ target = try_then_request_module(xt_find_target(AF_INET,
+ t->u.user.name,
+ t->u.user.revision),
+ "ipt_%s", t->u.user.name);
+ if (IS_ERR(target) || !target) {
+ duprintf("check_entry: `%s' not found\n", t->u.user.name);
+ ret = target ? PTR_ERR(target) : -ENOENT;
+ goto out;
+ }
+ t->u.kernel.target = target;
+
+ if (t->u.kernel.target->compat)
+ t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
+ else
+ xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
+ *size += off;
+ ret = compat_add_offset(entry_offset, off);
+ if (ret)
+ goto out;
+
+ /* Check hooks & underflows */
+ for (h = 0; h < NF_IP_NUMHOOKS; h++) {
+ if ((unsigned char *)e - base == hook_entries[h])
+ newinfo->hook_entry[h] = hook_entries[h];
+ if ((unsigned char *)e - base == underflows[h])
+ newinfo->underflow[h] = underflows[h];
+ }
+
+ /* Clear counters and comefrom */
+ e->counters = ((struct ipt_counters) { 0, 0 });
+ e->comefrom = 0;
+
+ (*i)++;
+ return 0;
+out:
+ IPT_MATCH_ITERATE(e, cleanup_match, &j);
+ return ret;
+}
+
+static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
+ void **dstptr, compat_uint_t *size, const char *name,
+ const struct ipt_ip *ip, unsigned int hookmask)
+{
+ struct ipt_entry_match *dm;
+ struct ipt_match *match;
+ int ret;
+
+ dm = (struct ipt_entry_match *)*dstptr;
+ match = m->u.kernel.match;
+ if (match->compat)
+ match->compat(m, dstptr, size, COMPAT_FROM_USER);
+ else
+ xt_compat_match(m, dstptr, size, COMPAT_FROM_USER);
+
+ ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
+ name, hookmask, ip->proto,
+ ip->invflags & IPT_INV_PROTO);
+ if (ret)
+ return ret;
+
+ if (m->u.kernel.match->checkentry
+ && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
+ dm->u.match_size - sizeof(*dm),
+ hookmask)) {
+ duprintf("ip_tables: check failed for `%s'.\n",
+ m->u.kernel.match->name);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
+ unsigned int *size, const char *name,
+ struct xt_table_info *newinfo, unsigned char *base)
+{
+ struct ipt_entry_target *t;
+ struct ipt_target *target;
+ struct ipt_entry *de;
+ unsigned int origsize;
+ int ret, h;
+
+ ret = 0;
+ origsize = *size;
+ de = (struct ipt_entry *)*dstptr;
+ memcpy(de, e, sizeof(struct ipt_entry));
+
+ *dstptr += sizeof(struct compat_ipt_entry);
+ ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
+ name, &de->ip, de->comefrom);
+ if (ret)
+ goto out;
+ de->target_offset = e->target_offset - (origsize - *size);
+ t = ipt_get_target(e);
+ target = t->u.kernel.target;
+ if (target->compat)
+ target->compat(t, dstptr, size, COMPAT_FROM_USER);
+ else
+ xt_compat_target(t, dstptr, size, COMPAT_FROM_USER);
+
+ de->next_offset = e->next_offset - (origsize - *size);
+ for (h = 0; h < NF_IP_NUMHOOKS; h++) {
+ if ((unsigned char *)de - base < newinfo->hook_entry[h])
+ newinfo->hook_entry[h] -= origsize - *size;
+ if ((unsigned char *)de - base < newinfo->underflow[h])
+ newinfo->underflow[h] -= origsize - *size;
+ }
+
+ t = ipt_get_target(de);
+ target = t->u.kernel.target;
+ ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
+ name, e->comefrom, e->ip.proto,
+ e->ip.invflags & IPT_INV_PROTO);
+ if (ret)
+ goto out;
+
+ ret = -EINVAL;
+ if (t->u.kernel.target == &ipt_standard_target) {
+ if (!standard_check(t, *size))
+ goto out;
+ } else if (t->u.kernel.target->checkentry
+ && !t->u.kernel.target->checkentry(name, de, target,
+ t->data, t->u.target_size - sizeof(*t),
+ de->comefrom)) {
+ duprintf("ip_tables: compat: check failed for `%s'.\n",
+ t->u.kernel.target->name);
+ goto out;
+ }
+ ret = 0;
+out:
+ return ret;
+}
+
static int
-do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
+translate_compat_table(const char *name,
+ unsigned int valid_hooks,
+ struct xt_table_info **pinfo,
+ void **pentry0,
+ unsigned int total_size,
+ unsigned int number,
+ unsigned int *hook_entries,
+ unsigned int *underflows)
+{
+ unsigned int i;
+ struct xt_table_info *newinfo, *info;
+ void *pos, *entry0, *entry1;
+ unsigned int size;
+ int ret;
+
+ info = *pinfo;
+ entry0 = *pentry0;
+ size = total_size;
+ info->number = number;
+
+ /* Init all hooks to impossible value. */
+ for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ info->hook_entry[i] = 0xFFFFFFFF;
+ info->underflow[i] = 0xFFFFFFFF;
+ }
+
+ duprintf("translate_compat_table: size %u\n", info->size);
+ i = 0;
+ xt_compat_lock(AF_INET);
+ /* Walk through entries, checking offsets. */
+ ret = IPT_ENTRY_ITERATE(entry0, total_size,
+ check_compat_entry_size_and_hooks,
+ info, &size, entry0,
+ entry0 + total_size,
+ hook_entries, underflows, &i, name);
+ if (ret != 0)
+ goto out_unlock;
+
+ ret = -EINVAL;
+ if (i != number) {
+ duprintf("translate_compat_table: %u not %u entries\n",
+ i, number);
+ goto out_unlock;
+ }
+
+ /* Check hooks all assigned */
+ for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ /* Only hooks which are valid */
+ if (!(valid_hooks & (1 << i)))
+ continue;
+ if (info->hook_entry[i] == 0xFFFFFFFF) {
+ duprintf("Invalid hook entry %u %u\n",
+ i, hook_entries[i]);
+ goto out_unlock;
+ }
+ if (info->underflow[i] == 0xFFFFFFFF) {
+ duprintf("Invalid underflow %u %u\n",
+ i, underflows[i]);
+ goto out_unlock;
+ }
+ }
+
+ ret = -ENOMEM;
+ newinfo = xt_alloc_table_info(size);
+ if (!newinfo)
+ goto out_unlock;
+
+ newinfo->number = number;
+ for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ newinfo->hook_entry[i] = info->hook_entry[i];
+ newinfo->underflow[i] = info->underflow[i];
+ }
+ entry1 = newinfo->entries[raw_smp_processor_id()];
+ pos = entry1;
+ size = total_size;
+ ret = IPT_ENTRY_ITERATE(entry0, total_size,
+ compat_copy_entry_from_user, &pos, &size,
+ name, newinfo, entry1);
+ compat_flush_offsets();
+ xt_compat_unlock(AF_INET);
+ if (ret)
+ goto free_newinfo;
+
+ ret = -ELOOP;
+ if (!mark_source_chains(newinfo, valid_hooks, entry1))
+ goto free_newinfo;
+
+ /* And one copy for every other CPU */
+ for_each_cpu(i)
+ if (newinfo->entries[i] && newinfo->entries[i] != entry1)
+ memcpy(newinfo->entries[i], entry1, newinfo->size);
+
+ *pinfo = newinfo;
+ *pentry0 = entry1;
+ xt_free_table_info(info);
+ return 0;
+
+free_newinfo:
+ xt_free_table_info(newinfo);
+out:
+ return ret;
+out_unlock:
+ xt_compat_unlock(AF_INET);
+ goto out;
+}
+
+static int
+compat_do_replace(void __user *user, unsigned int len)
+{
+ int ret;
+ struct compat_ipt_replace tmp;
+ struct xt_table_info *newinfo;
+ void *loc_cpu_entry;
+
+ if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+ return -EFAULT;
+
+ /* Hack: Causes ipchains to give correct error msg --RR */
+ if (len != sizeof(tmp) + tmp.size)
+ return -ENOPROTOOPT;
+
+ /* overflow check */
+ if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
+ SMP_CACHE_BYTES)
+ return -ENOMEM;
+ if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
+ return -ENOMEM;
+
+ newinfo = xt_alloc_table_info(tmp.size);
+ if (!newinfo)
+ return -ENOMEM;
+
+ /* choose the copy that is our node/cpu */
+ loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+ if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
+ tmp.size) != 0) {
+ ret = -EFAULT;
+ goto free_newinfo;
+ }
+
+ ret = translate_compat_table(tmp.name, tmp.valid_hooks,
+ &newinfo, &loc_cpu_entry, tmp.size,
+ tmp.num_entries, tmp.hook_entry, tmp.underflow);
+ if (ret != 0)
+ goto free_newinfo;
+
+ duprintf("compat_do_replace: Translated table\n");
+
+ ret = __do_replace(tmp.name, tmp.valid_hooks,
+ newinfo, tmp.num_counters,
+ compat_ptr(tmp.counters));
+ if (ret)
+ goto free_newinfo_untrans;
+ return 0;
+
+ free_newinfo_untrans:
+ IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
+ free_newinfo:
+ xt_free_table_info(newinfo);
+ return ret;
+}
+
+static int
+compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
+ unsigned int len)
{
int ret;
@@ -1105,11 +1846,11 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
switch (cmd) {
case IPT_SO_SET_REPLACE:
- ret = do_replace(user, len);
+ ret = compat_do_replace(user, len);
break;
case IPT_SO_SET_ADD_COUNTERS:
- ret = do_add_counters(user, len);
+ ret = do_add_counters(user, len, 1);
break;
default:
@@ -1120,75 +1861,196 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
return ret;
}
+struct compat_ipt_get_entries
+{
+ char name[IPT_TABLE_MAXNAMELEN];
+ compat_uint_t size;
+ struct compat_ipt_entry entrytable[0];
+};
+
+static int compat_copy_entries_to_user(unsigned int total_size,
+ struct ipt_table *table, void __user *userptr)
+{
+ unsigned int off, num;
+ struct compat_ipt_entry e;
+ struct xt_counters *counters;
+ struct xt_table_info *private = table->private;
+ void __user *pos;
+ unsigned int size;
+ int ret = 0;
+ void *loc_cpu_entry;
+
+ counters = alloc_counters(table);
+ if (IS_ERR(counters))
+ return PTR_ERR(counters);
+
+ /* choose the copy that is on our node/cpu, ...
+ * This choice is lazy (because current thread is
+ * allowed to migrate to another cpu)
+ */
+ loc_cpu_entry = private->entries[raw_smp_processor_id()];
+ pos = userptr;
+ size = total_size;
+ ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
+ compat_copy_entry_to_user, &pos, &size);
+ if (ret)
+ goto free_counters;
+
+ /* ... then go back and fix counters and names */
+ for (off = 0, num = 0; off < size; off += e.next_offset, num++) {
+ unsigned int i;
+ struct ipt_entry_match m;
+ struct ipt_entry_target t;
+
+ ret = -EFAULT;
+ if (copy_from_user(&e, userptr + off,
+ sizeof(struct compat_ipt_entry)))
+ goto free_counters;
+ if (copy_to_user(userptr + off +
+ offsetof(struct compat_ipt_entry, counters),
+ &counters[num], sizeof(counters[num])))
+ goto free_counters;
+
+ for (i = sizeof(struct compat_ipt_entry);
+ i < e.target_offset; i += m.u.match_size) {
+ if (copy_from_user(&m, userptr + off + i,
+ sizeof(struct ipt_entry_match)))
+ goto free_counters;
+ if (copy_to_user(userptr + off + i +
+ offsetof(struct ipt_entry_match, u.user.name),
+ m.u.kernel.match->name,
+ strlen(m.u.kernel.match->name) + 1))
+ goto free_counters;
+ }
+
+ if (copy_from_user(&t, userptr + off + e.target_offset,
+ sizeof(struct ipt_entry_target)))
+ goto free_counters;
+ if (copy_to_user(userptr + off + e.target_offset +
+ offsetof(struct ipt_entry_target, u.user.name),
+ t.u.kernel.target->name,
+ strlen(t.u.kernel.target->name) + 1))
+ goto free_counters;
+ }
+ ret = 0;
+free_counters:
+ vfree(counters);
+ return ret;
+}
+
static int
-do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
{
int ret;
+ struct compat_ipt_get_entries get;
+ struct ipt_table *t;
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- switch (cmd) {
- case IPT_SO_GET_INFO: {
- char name[IPT_TABLE_MAXNAMELEN];
- struct ipt_table *t;
+ if (*len < sizeof(get)) {
+ duprintf("compat_get_entries: %u < %u\n",
+ *len, (unsigned int)sizeof(get));
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&get, uptr, sizeof(get)) != 0)
+ return -EFAULT;
+
+ if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
+ duprintf("compat_get_entries: %u != %u\n", *len,
+ (unsigned int)(sizeof(struct compat_ipt_get_entries) +
+ get.size));
+ return -EINVAL;
+ }
- if (*len != sizeof(struct ipt_getinfo)) {
- duprintf("length %u != %u\n", *len,
- sizeof(struct ipt_getinfo));
+ xt_compat_lock(AF_INET);
+ t = xt_find_table_lock(AF_INET, get.name);
+ if (t && !IS_ERR(t)) {
+ struct xt_table_info *private = t->private;
+ struct xt_table_info info;
+ duprintf("t->private->number = %u\n",
+ private->number);
+ ret = compat_table_info(private, &info);
+ if (!ret && get.size == info.size) {
+ ret = compat_copy_entries_to_user(private->size,
+ t, uptr->entrytable);
+ } else if (!ret) {
+ duprintf("compat_get_entries: I've got %u not %u!\n",
+ private->size,
+ get.size);
ret = -EINVAL;
- break;
}
+ compat_flush_offsets();
+ module_put(t->me);
+ xt_table_unlock(t);
+ } else
+ ret = t ? PTR_ERR(t) : -ENOENT;
- if (copy_from_user(name, user, sizeof(name)) != 0) {
- ret = -EFAULT;
- break;
- }
- name[IPT_TABLE_MAXNAMELEN-1] = '\0';
-
- t = try_then_request_module(xt_find_table_lock(AF_INET, name),
- "iptable_%s", name);
- if (t && !IS_ERR(t)) {
- struct ipt_getinfo info;
- struct xt_table_info *private = t->private;
-
- info.valid_hooks = t->valid_hooks;
- memcpy(info.hook_entry, private->hook_entry,
- sizeof(info.hook_entry));
- memcpy(info.underflow, private->underflow,
- sizeof(info.underflow));
- info.num_entries = private->number;
- info.size = private->size;
- memcpy(info.name, name, sizeof(info.name));
-
- if (copy_to_user(user, &info, *len) != 0)
- ret = -EFAULT;
- else
- ret = 0;
- xt_table_unlock(t);
- module_put(t->me);
- } else
- ret = t ? PTR_ERR(t) : -ENOENT;
+ xt_compat_unlock(AF_INET);
+ return ret;
+}
+
+static int
+compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+{
+ int ret;
+
+ switch (cmd) {
+ case IPT_SO_GET_INFO:
+ ret = get_info(user, len, 1);
+ break;
+ case IPT_SO_GET_ENTRIES:
+ ret = compat_get_entries(user, len);
+ break;
+ default:
+ duprintf("compat_do_ipt_get_ctl: unknown request %i\n", cmd);
+ ret = -EINVAL;
}
- break;
+ return ret;
+}
+#endif
- case IPT_SO_GET_ENTRIES: {
- struct ipt_get_entries get;
+static int
+do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
+{
+ int ret;
- if (*len < sizeof(get)) {
- duprintf("get_entries: %u < %u\n", *len, sizeof(get));
- ret = -EINVAL;
- } else if (copy_from_user(&get, user, sizeof(get)) != 0) {
- ret = -EFAULT;
- } else if (*len != sizeof(struct ipt_get_entries) + get.size) {
- duprintf("get_entries: %u != %u\n", *len,
- sizeof(struct ipt_get_entries) + get.size);
- ret = -EINVAL;
- } else
- ret = get_entries(&get, user);
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ switch (cmd) {
+ case IPT_SO_SET_REPLACE:
+ ret = do_replace(user, len);
break;
+
+ case IPT_SO_SET_ADD_COUNTERS:
+ ret = do_add_counters(user, len, 0);
+ break;
+
+ default:
+ duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
+ ret = -EINVAL;
}
+ return ret;
+}
+
+static int
+do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+{
+ int ret;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ switch (cmd) {
+ case IPT_SO_GET_INFO:
+ ret = get_info(user, len, 0);
+ break;
+
+ case IPT_SO_GET_ENTRIES:
+ ret = get_entries(user, len);
+ break;
+
case IPT_SO_GET_REVISION_MATCH:
case IPT_SO_GET_REVISION_TARGET: {
struct ipt_get_revision rev;
@@ -1336,6 +2198,9 @@ static struct ipt_target ipt_standard_target = {
.name = IPT_STANDARD_TARGET,
.targetsize = sizeof(int),
.family = AF_INET,
+#ifdef CONFIG_COMPAT
+ .compat = &compat_ipt_standard_fn,
+#endif
};
static struct ipt_target ipt_error_target = {
@@ -1350,9 +2215,15 @@ static struct nf_sockopt_ops ipt_sockopts = {
.set_optmin = IPT_BASE_CTL,
.set_optmax = IPT_SO_SET_MAX+1,
.set = do_ipt_set_ctl,
+#ifdef CONFIG_COMPAT
+ .compat_set = compat_do_ipt_set_ctl,
+#endif
.get_optmin = IPT_BASE_CTL,
.get_optmax = IPT_SO_GET_MAX+1,
.get = do_ipt_get_ctl,
+#ifdef CONFIG_COMPAT
+ .compat_get = compat_do_ipt_get_ctl,
+#endif
};
static struct ipt_match icmp_matchstruct = {
@@ -1364,7 +2235,7 @@ static struct ipt_match icmp_matchstruct = {
.checkentry = icmp_checkentry,
};
-static int __init init(void)
+static int __init ip_tables_init(void)
{
int ret;
@@ -1386,7 +2257,7 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ip_tables_fini(void)
{
nf_unregister_sockopt(&ipt_sockopts);
@@ -1400,5 +2271,5 @@ static void __exit fini(void)
EXPORT_SYMBOL(ipt_register_table);
EXPORT_SYMBOL(ipt_unregister_table);
EXPORT_SYMBOL(ipt_do_table);
-module_init(init);
-module_exit(fini);
+module_init(ip_tables_init);
+module_exit(ip_tables_fini);
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 61e11edcd6a..aad9d28c8d7 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -725,22 +725,17 @@ static struct file_operations clusterip_proc_fops = {
#endif /* CONFIG_PROC_FS */
-static int init_or_cleanup(int fini)
+static int __init ipt_clusterip_init(void)
{
int ret;
- if (fini)
- goto cleanup;
+ ret = ipt_register_target(&clusterip_tgt);
+ if (ret < 0)
+ return ret;
- if (ipt_register_target(&clusterip_tgt)) {
- ret = -EINVAL;
- goto cleanup_none;
- }
-
- if (nf_register_hook(&cip_arp_ops) < 0) {
- ret = -EINVAL;
+ ret = nf_register_hook(&cip_arp_ops);
+ if (ret < 0)
goto cleanup_target;
- }
#ifdef CONFIG_PROC_FS
clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net);
@@ -753,32 +748,25 @@ static int init_or_cleanup(int fini)
printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n",
CLUSTERIP_VERSION);
-
return 0;
-cleanup:
- printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
- CLUSTERIP_VERSION);
-#ifdef CONFIG_PROC_FS
- remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
-#endif
cleanup_hook:
nf_unregister_hook(&cip_arp_ops);
cleanup_target:
ipt_unregister_target(&clusterip_tgt);
-cleanup_none:
- return -EINVAL;
-}
-
-static int __init init(void)
-{
- return init_or_cleanup(0);
+ return ret;
}
-static void __exit fini(void)
+static void __exit ipt_clusterip_fini(void)
{
- init_or_cleanup(1);
+ printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
+ CLUSTERIP_VERSION);
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
+#endif
+ nf_unregister_hook(&cip_arp_ops);
+ ipt_unregister_target(&clusterip_tgt);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_clusterip_init);
+module_exit(ipt_clusterip_fini);
diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c
index cfb0b90e598..c8e971288df 100644
--- a/net/ipv4/netfilter/ipt_DSCP.c
+++ b/net/ipv4/netfilter/ipt_DSCP.c
@@ -82,15 +82,15 @@ static struct ipt_target ipt_dscp_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_dscp_init(void)
{
return ipt_register_target(&ipt_dscp_reg);
}
-static void __exit fini(void)
+static void __exit ipt_dscp_fini(void)
{
ipt_unregister_target(&ipt_dscp_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_dscp_init);
+module_exit(ipt_dscp_fini);
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index b9b80f90c84..4adf5c9d34f 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -151,15 +151,15 @@ static struct ipt_target ipt_ecn_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ecn_init(void)
{
return ipt_register_target(&ipt_ecn_reg);
}
-static void __exit fini(void)
+static void __exit ipt_ecn_fini(void)
{
ipt_unregister_target(&ipt_ecn_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_ecn_init);
+module_exit(ipt_ecn_fini);
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 750d3221b28..b98f7b08b08 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -428,7 +428,7 @@ ipt_log_target(struct sk_buff **pskb,
if (loginfo->logflags & IPT_LOG_NFLOG)
nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
- loginfo->prefix);
+ "%s", loginfo->prefix);
else
ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
loginfo->prefix);
@@ -471,7 +471,7 @@ static struct nf_logger ipt_log_logger ={
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_log_init(void)
{
if (ipt_register_target(&ipt_log_reg))
return -EINVAL;
@@ -485,11 +485,11 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ipt_log_fini(void)
{
nf_log_unregister_logger(&ipt_log_logger);
ipt_unregister_target(&ipt_log_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_log_init);
+module_exit(ipt_log_fini);
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index e0c321c3bae..8b3e7f99b86 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -175,7 +175,7 @@ static struct ipt_target masquerade = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_masquerade_init(void)
{
int ret;
@@ -191,12 +191,12 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ipt_masquerade_fini(void)
{
ipt_unregister_target(&masquerade);
unregister_netdevice_notifier(&masq_dev_notifier);
unregister_inetaddr_notifier(&masq_inet_notifier);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_masquerade_init);
+module_exit(ipt_masquerade_fini);
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index fba181c2a42..2fcf1075b02 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -98,15 +98,15 @@ static struct ipt_target target_module = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init ipt_netmap_init(void)
{
return ipt_register_target(&target_module);
}
-static void __exit fini(void)
+static void __exit ipt_netmap_fini(void)
{
ipt_unregister_target(&target_module);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_netmap_init);
+module_exit(ipt_netmap_fini);
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index be3da7c4b87..f290463232d 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -112,15 +112,15 @@ static struct ipt_target redirect_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_redirect_init(void)
{
return ipt_register_target(&redirect_reg);
}
-static void __exit fini(void)
+static void __exit ipt_redirect_fini(void)
{
ipt_unregister_target(&redirect_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_redirect_init);
+module_exit(ipt_redirect_fini);
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 9d3b3579f27..0bba3c2bb78 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -106,7 +106,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
struct rtable *rt;
u_int16_t tmp_port;
u_int32_t tmp_addr;
- unsigned int tcplen;
int needs_ack;
int hh_len;
@@ -124,13 +123,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
return;
/* Check checksum */
- tcplen = oldskb->len - iph->ihl * 4;
- if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) ||
- (hook == NF_IP_LOCAL_IN &&
- oldskb->ip_summed != CHECKSUM_UNNECESSARY)) &&
- csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
- oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum :
- skb_checksum(oldskb, iph->ihl * 4, tcplen, 0)))
+ if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
return;
if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
@@ -313,15 +306,15 @@ static struct ipt_target ipt_reject_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_reject_init(void)
{
return ipt_register_target(&ipt_reject_reg);
}
-static void __exit fini(void)
+static void __exit ipt_reject_fini(void)
{
ipt_unregister_target(&ipt_reject_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_reject_init);
+module_exit(ipt_reject_fini);
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index 7e2ebc9d945..7169b09b5a6 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -189,16 +189,16 @@ static struct ipt_target same_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_same_init(void)
{
return ipt_register_target(&same_reg);
}
-static void __exit fini(void)
+static void __exit ipt_same_fini(void)
{
ipt_unregister_target(&same_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_same_init);
+module_exit(ipt_same_fini);
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index c4fc50ec2dd..ef2fe5b3f0d 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -243,15 +243,15 @@ static struct ipt_target ipt_tcpmss_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_tcpmss_init(void)
{
return ipt_register_target(&ipt_tcpmss_reg);
}
-static void __exit fini(void)
+static void __exit ipt_tcpmss_fini(void)
{
ipt_unregister_target(&ipt_tcpmss_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_tcpmss_init);
+module_exit(ipt_tcpmss_fini);
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 9aa7817657f..1c7a5ca399b 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -81,15 +81,15 @@ static struct ipt_target ipt_tos_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_tos_init(void)
{
return ipt_register_target(&ipt_tos_reg);
}
-static void __exit fini(void)
+static void __exit ipt_tos_fini(void)
{
ipt_unregister_target(&ipt_tos_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_tos_init);
+module_exit(ipt_tos_fini);
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index 5009a003d57..f48892ae0be 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -94,15 +94,15 @@ static struct ipt_target ipt_TTL = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ttl_init(void)
{
return ipt_register_target(&ipt_TTL);
}
-static void __exit fini(void)
+static void __exit ipt_ttl_fini(void)
{
ipt_unregister_target(&ipt_TTL);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_ttl_init);
+module_exit(ipt_ttl_fini);
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index a82a32ed0e2..c84cc03389d 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -374,7 +374,7 @@ static struct nf_logger ipt_ulog_logger = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ulog_init(void)
{
int i;
@@ -407,7 +407,7 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ipt_ulog_fini(void)
{
ulog_buff_t *ub;
int i;
@@ -435,5 +435,5 @@ static void __exit fini(void)
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_ulog_init);
+module_exit(ipt_ulog_fini);
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index 5fdf85d0efc..893dae210b0 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -51,15 +51,15 @@ static struct ipt_match addrtype_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init ipt_addrtype_init(void)
{
return ipt_register_match(&addrtype_match);
}
-static void __exit fini(void)
+static void __exit ipt_addrtype_fini(void)
{
ipt_unregister_match(&addrtype_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_addrtype_init);
+module_exit(ipt_addrtype_fini);
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index 35a21fb1f8e..2927135873d 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -96,15 +96,15 @@ static struct ipt_match ah_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ah_init(void)
{
return ipt_register_match(&ah_match);
}
-static void __exit cleanup(void)
+static void __exit ipt_ah_fini(void)
{
ipt_unregister_match(&ah_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ipt_ah_init);
+module_exit(ipt_ah_fini);
diff --git a/net/ipv4/netfilter/ipt_dscp.c b/net/ipv4/netfilter/ipt_dscp.c
index 11963c385de..47177591aeb 100644
--- a/net/ipv4/netfilter/ipt_dscp.c
+++ b/net/ipv4/netfilter/ipt_dscp.c
@@ -39,16 +39,16 @@ static struct ipt_match dscp_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_dscp_init(void)
{
return ipt_register_match(&dscp_match);
}
-static void __exit fini(void)
+static void __exit ipt_dscp_fini(void)
{
ipt_unregister_match(&dscp_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_dscp_init);
+module_exit(ipt_dscp_fini);
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index d7e29f6a38d..b2825041493 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -118,15 +118,15 @@ static struct ipt_match ecn_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ecn_init(void)
{
return ipt_register_match(&ecn_match);
}
-static void __exit fini(void)
+static void __exit ipt_ecn_fini(void)
{
ipt_unregister_match(&ecn_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_ecn_init);
+module_exit(ipt_ecn_fini);
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index ba5e23505e8..7c6836c4646 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -719,15 +719,15 @@ cleanup_nothing:
}
-static int __init init(void)
+static int __init ipt_hashlimit_init(void)
{
return init_or_fini(0);
}
-static void __exit fini(void)
+static void __exit ipt_hashlimit_fini(void)
{
init_or_fini(1);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_hashlimit_init);
+module_exit(ipt_hashlimit_fini);
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index ae70112f5e0..5202edd8d33 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -71,15 +71,15 @@ static struct ipt_match iprange_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init ipt_iprange_init(void)
{
return ipt_register_match(&iprange_match);
}
-static void __exit fini(void)
+static void __exit ipt_iprange_fini(void)
{
ipt_unregister_match(&iprange_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_iprange_init);
+module_exit(ipt_iprange_fini);
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
deleted file mode 100644
index bd07f7c5387..00000000000
--- a/net/ipv4/netfilter/ipt_multiport.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/* Kernel module to match one of a list of TCP/UDP ports: ports are in
- the same place so we can treat them as equal. */
-
-/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/udp.h>
-#include <linux/skbuff.h>
-
-#include <linux/netfilter_ipv4/ipt_multiport.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("iptables multiple port match module");
-
-#if 0
-#define duprintf(format, args...) printk(format , ## args)
-#else
-#define duprintf(format, args...)
-#endif
-
-/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
-ports_match(const u_int16_t *portlist, enum ipt_multiport_flags flags,
- u_int8_t count, u_int16_t src, u_int16_t dst)
-{
- unsigned int i;
- for (i=0; i<count; i++) {
- if (flags != IPT_MULTIPORT_DESTINATION
- && portlist[i] == src)
- return 1;
-
- if (flags != IPT_MULTIPORT_SOURCE
- && portlist[i] == dst)
- return 1;
- }
-
- return 0;
-}
-
-/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
-ports_match_v1(const struct ipt_multiport_v1 *minfo,
- u_int16_t src, u_int16_t dst)
-{
- unsigned int i;
- u_int16_t s, e;
-
- for (i=0; i < minfo->count; i++) {
- s = minfo->ports[i];
-
- if (minfo->pflags[i]) {
- /* range port matching */
- e = minfo->ports[++i];
- duprintf("src or dst matches with %d-%d?\n", s, e);
-
- if (minfo->flags == IPT_MULTIPORT_SOURCE
- && src >= s && src <= e)
- return 1 ^ minfo->invert;
- if (minfo->flags == IPT_MULTIPORT_DESTINATION
- && dst >= s && dst <= e)
- return 1 ^ minfo->invert;
- if (minfo->flags == IPT_MULTIPORT_EITHER
- && ((dst >= s && dst <= e)
- || (src >= s && src <= e)))
- return 1 ^ minfo->invert;
- } else {
- /* exact port matching */
- duprintf("src or dst matches with %d?\n", s);
-
- if (minfo->flags == IPT_MULTIPORT_SOURCE
- && src == s)
- return 1 ^ minfo->invert;
- if (minfo->flags == IPT_MULTIPORT_DESTINATION
- && dst == s)
- return 1 ^ minfo->invert;
- if (minfo->flags == IPT_MULTIPORT_EITHER
- && (src == s || dst == s))
- return 1 ^ minfo->invert;
- }
- }
-
- return minfo->invert;
-}
-
-static int
-match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const struct xt_match *match,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
-{
- u16 _ports[2], *pptr;
- const struct ipt_multiport *multiinfo = matchinfo;
-
- if (offset)
- return 0;
-
- pptr = skb_header_pointer(skb, protoff,
- sizeof(_ports), _ports);
- if (pptr == NULL) {
- /* We've been asked to examine this packet, and we
- * can't. Hence, no choice but to drop.
- */
- duprintf("ipt_multiport:"
- " Dropping evil offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
- }
-
- return ports_match(multiinfo->ports,
- multiinfo->flags, multiinfo->count,
- ntohs(pptr[0]), ntohs(pptr[1]));
-}
-
-static int
-match_v1(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const struct xt_match *match,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
-{
- u16 _ports[2], *pptr;
- const struct ipt_multiport_v1 *multiinfo = matchinfo;
-
- if (offset)
- return 0;
-
- pptr = skb_header_pointer(skb, protoff,
- sizeof(_ports), _ports);
- if (pptr == NULL) {
- /* We've been asked to examine this packet, and we
- * can't. Hence, no choice but to drop.
- */
- duprintf("ipt_multiport:"
- " Dropping evil offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
- }
-
- return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
-}
-
-static struct ipt_match multiport_match = {
- .name = "multiport",
- .revision = 0,
- .match = match,
- .matchsize = sizeof(struct ipt_multiport),
- .me = THIS_MODULE,
-};
-
-static struct ipt_match multiport_match_v1 = {
- .name = "multiport",
- .revision = 1,
- .match = match_v1,
- .matchsize = sizeof(struct ipt_multiport_v1),
- .me = THIS_MODULE,
-};
-
-static int __init init(void)
-{
- int err;
-
- err = ipt_register_match(&multiport_match);
- if (!err) {
- err = ipt_register_match(&multiport_match_v1);
- if (err)
- ipt_unregister_match(&multiport_match);
- }
-
- return err;
-}
-
-static void __exit fini(void)
-{
- ipt_unregister_match(&multiport_match);
- ipt_unregister_match(&multiport_match_v1);
-}
-
-module_init(init);
-module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 3900428771f..5ac6ac023b5 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -78,15 +78,15 @@ static struct ipt_match owner_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_owner_init(void)
{
return ipt_register_match(&owner_match);
}
-static void __exit fini(void)
+static void __exit ipt_owner_fini(void)
{
ipt_unregister_match(&owner_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_owner_init);
+module_exit(ipt_owner_fini);
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 06792ead1da..b847ee409ef 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -821,6 +821,7 @@ checkentry(const char *tablename,
/* Create our proc 'status' entry. */
curr_table->status_proc = create_proc_entry(curr_table->name, ip_list_perms, proc_net_ipt_recent);
if (!curr_table->status_proc) {
+ vfree(hold);
printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for /proc entry.\n");
/* Destroy the created table */
spin_lock_bh(&recent_lock);
@@ -845,7 +846,6 @@ checkentry(const char *tablename,
spin_unlock_bh(&recent_lock);
vfree(curr_table->time_info);
vfree(curr_table->hash_table);
- vfree(hold);
vfree(curr_table->table);
vfree(curr_table);
return 0;
@@ -962,7 +962,7 @@ static struct ipt_match recent_match = {
};
/* Kernel module initialization. */
-static int __init init(void)
+static int __init ipt_recent_init(void)
{
int err, count;
@@ -995,7 +995,7 @@ static int __init init(void)
}
/* Kernel module destruction. */
-static void __exit fini(void)
+static void __exit ipt_recent_fini(void)
{
ipt_unregister_match(&recent_match);
@@ -1003,5 +1003,5 @@ static void __exit fini(void)
}
/* Register our module with the kernel. */
-module_init(init);
-module_exit(fini);
+module_init(ipt_recent_init);
+module_exit(ipt_recent_fini);
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index e404e92ddd0..5549c39c785 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -39,15 +39,15 @@ static struct ipt_match tos_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_multiport_init(void)
{
return ipt_register_match(&tos_match);
}
-static void __exit fini(void)
+static void __exit ipt_multiport_fini(void)
{
ipt_unregister_match(&tos_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_multiport_init);
+module_exit(ipt_multiport_fini);
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index ae7ce4d8d90..a5243bdb87d 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -55,16 +55,16 @@ static struct ipt_match ttl_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ttl_init(void)
{
return ipt_register_match(&ttl_match);
}
-static void __exit fini(void)
+static void __exit ipt_ttl_fini(void)
{
ipt_unregister_match(&ttl_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_ttl_init);
+module_exit(ipt_ttl_fini);
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 212a3079085..7f417484bfb 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -139,7 +139,7 @@ static struct nf_hook_ops ipt_ops[] = {
static int forward = NF_ACCEPT;
module_param(forward, bool, 0000);
-static int __init init(void)
+static int __init iptable_filter_init(void)
{
int ret;
@@ -157,39 +157,22 @@ static int __init init(void)
return ret;
/* Register hooks */
- ret = nf_register_hook(&ipt_ops[0]);
+ ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
if (ret < 0)
goto cleanup_table;
- ret = nf_register_hook(&ipt_ops[1]);
- if (ret < 0)
- goto cleanup_hook0;
-
- ret = nf_register_hook(&ipt_ops[2]);
- if (ret < 0)
- goto cleanup_hook1;
-
return ret;
- cleanup_hook1:
- nf_unregister_hook(&ipt_ops[1]);
- cleanup_hook0:
- nf_unregister_hook(&ipt_ops[0]);
cleanup_table:
ipt_unregister_table(&packet_filter);
-
return ret;
}
-static void __exit fini(void)
+static void __exit iptable_filter_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
- nf_unregister_hook(&ipt_ops[i]);
-
+ nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
ipt_unregister_table(&packet_filter);
}
-module_init(init);
-module_exit(fini);
+module_init(iptable_filter_init);
+module_exit(iptable_filter_fini);
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 3212a5cc4b6..397b95cc026 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -201,7 +201,7 @@ static struct nf_hook_ops ipt_ops[] = {
},
};
-static int __init init(void)
+static int __init iptable_mangle_init(void)
{
int ret;
@@ -211,51 +211,22 @@ static int __init init(void)
return ret;
/* Register hooks */
- ret = nf_register_hook(&ipt_ops[0]);
+ ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
if (ret < 0)
goto cleanup_table;
- ret = nf_register_hook(&ipt_ops[1]);
- if (ret < 0)
- goto cleanup_hook0;
-
- ret = nf_register_hook(&ipt_ops[2]);
- if (ret < 0)
- goto cleanup_hook1;
-
- ret = nf_register_hook(&ipt_ops[3]);
- if (ret < 0)
- goto cleanup_hook2;
-
- ret = nf_register_hook(&ipt_ops[4]);
- if (ret < 0)
- goto cleanup_hook3;
-
return ret;
- cleanup_hook3:
- nf_unregister_hook(&ipt_ops[3]);
- cleanup_hook2:
- nf_unregister_hook(&ipt_ops[2]);
- cleanup_hook1:
- nf_unregister_hook(&ipt_ops[1]);
- cleanup_hook0:
- nf_unregister_hook(&ipt_ops[0]);
cleanup_table:
ipt_unregister_table(&packet_mangler);
-
return ret;
}
-static void __exit fini(void)
+static void __exit iptable_mangle_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
- nf_unregister_hook(&ipt_ops[i]);
-
+ nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
ipt_unregister_table(&packet_mangler);
}
-module_init(init);
-module_exit(fini);
+module_init(iptable_mangle_init);
+module_exit(iptable_mangle_fini);
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index fdb9e9c81e8..7912cce1e1b 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -101,22 +101,22 @@ ipt_hook(unsigned int hook,
/* 'raw' is the very first table. */
static struct nf_hook_ops ipt_ops[] = {
{
- .hook = ipt_hook,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_RAW,
- .owner = THIS_MODULE,
+ .hook = ipt_hook,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_RAW,
+ .owner = THIS_MODULE,
},
{
- .hook = ipt_hook,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_RAW,
- .owner = THIS_MODULE,
+ .hook = ipt_hook,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_RAW,
+ .owner = THIS_MODULE,
},
};
-static int __init init(void)
+static int __init iptable_raw_init(void)
{
int ret;
@@ -126,34 +126,23 @@ static int __init init(void)
return ret;
/* Register hooks */
- ret = nf_register_hook(&ipt_ops[0]);
+ ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
if (ret < 0)
goto cleanup_table;
- ret = nf_register_hook(&ipt_ops[1]);
- if (ret < 0)
- goto cleanup_hook0;
-
return ret;
- cleanup_hook0:
- nf_unregister_hook(&ipt_ops[0]);
cleanup_table:
ipt_unregister_table(&packet_raw);
-
return ret;
}
-static void __exit fini(void)
+static void __exit iptable_raw_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
- nf_unregister_hook(&ipt_ops[i]);
-
+ nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
ipt_unregister_table(&packet_raw);
}
-module_init(init);
-module_exit(fini);
+module_init(iptable_raw_init);
+module_exit(iptable_raw_fini);
MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index c8abc9d859b..77d974443c7 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -210,71 +210,63 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum,
/* Connection tracking may drop packets, but never alters them, so
make it the first hook. */
-static struct nf_hook_ops ipv4_conntrack_defrag_ops = {
- .hook = ipv4_conntrack_defrag,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ipv4_conntrack_in_ops = {
- .hook = ipv4_conntrack_in,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ipv4_conntrack_defrag_local_out_ops = {
- .hook = ipv4_conntrack_defrag,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ipv4_conntrack_local_out_ops = {
- .hook = ipv4_conntrack_local,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_CONNTRACK,
-};
-
-/* helpers */
-static struct nf_hook_ops ipv4_conntrack_helper_out_ops = {
- .hook = ipv4_conntrack_help,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-static struct nf_hook_ops ipv4_conntrack_helper_in_ops = {
- .hook = ipv4_conntrack_help,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-
-/* Refragmenter; last chance. */
-static struct nf_hook_ops ipv4_conntrack_out_ops = {
- .hook = ipv4_confirm,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
-};
-
-static struct nf_hook_ops ipv4_conntrack_local_in_ops = {
- .hook = ipv4_confirm,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+static struct nf_hook_ops ipv4_conntrack_ops[] = {
+ {
+ .hook = ipv4_conntrack_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
+ },
+ {
+ .hook = ipv4_conntrack_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_PRE_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK,
+ },
+ {
+ .hook = ipv4_conntrack_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
+ },
+ {
+ .hook = ipv4_conntrack_local,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_OUT,
+ .priority = NF_IP_PRI_CONNTRACK,
+ },
+ {
+ .hook = ipv4_conntrack_help,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_HELPER,
+ },
+ {
+ .hook = ipv4_conntrack_help,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_CONNTRACK_HELPER,
+ },
+ {
+ .hook = ipv4_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+ },
+ {
+ .hook = ipv4_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
+ },
};
#ifdef CONFIG_SYSCTL
@@ -356,6 +348,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
.tuple.dst.u.tcp.port;
sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL]
.tuple.dst.u3.ip;
+ memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
@@ -440,16 +433,20 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4;
extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp;
-static int init_or_cleanup(int init)
+
+MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
+MODULE_LICENSE("GPL");
+
+static int __init nf_conntrack_l3proto_ipv4_init(void)
{
int ret = 0;
- if (!init) goto cleanup;
+ need_conntrack();
ret = nf_register_sockopt(&so_getorigdst);
if (ret < 0) {
printk(KERN_ERR "Unable to register netfilter socket option\n");
- goto cleanup_nothing;
+ return ret;
}
ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4);
@@ -476,84 +473,26 @@ static int init_or_cleanup(int init)
goto cleanup_icmp;
}
- ret = nf_register_hook(&ipv4_conntrack_defrag_ops);
+ ret = nf_register_hooks(ipv4_conntrack_ops,
+ ARRAY_SIZE(ipv4_conntrack_ops));
if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register pre-routing defrag hook.\n");
+ printk("nf_conntrack_ipv4: can't register hooks.\n");
goto cleanup_ipv4;
}
- ret = nf_register_hook(&ipv4_conntrack_defrag_local_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register local_out defrag hook.\n");
- goto cleanup_defragops;
- }
-
- ret = nf_register_hook(&ipv4_conntrack_in_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register pre-routing hook.\n");
- goto cleanup_defraglocalops;
- }
-
- ret = nf_register_hook(&ipv4_conntrack_local_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register local out hook.\n");
- goto cleanup_inops;
- }
-
- ret = nf_register_hook(&ipv4_conntrack_helper_in_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register local helper hook.\n");
- goto cleanup_inandlocalops;
- }
-
- ret = nf_register_hook(&ipv4_conntrack_helper_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register postrouting helper hook.\n");
- goto cleanup_helperinops;
- }
-
- ret = nf_register_hook(&ipv4_conntrack_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register post-routing hook.\n");
- goto cleanup_helperoutops;
- }
-
- ret = nf_register_hook(&ipv4_conntrack_local_in_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv4: can't register local in hook.\n");
- goto cleanup_inoutandlocalops;
- }
-
#ifdef CONFIG_SYSCTL
nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
if (nf_ct_ipv4_sysctl_header == NULL) {
printk("nf_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
- goto cleanup_localinops;
+ goto cleanup_hooks;
}
#endif
return ret;
- cleanup:
- synchronize_net();
#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
- cleanup_localinops:
+ cleanup_hooks:
+ nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
#endif
- nf_unregister_hook(&ipv4_conntrack_local_in_ops);
- cleanup_inoutandlocalops:
- nf_unregister_hook(&ipv4_conntrack_out_ops);
- cleanup_helperoutops:
- nf_unregister_hook(&ipv4_conntrack_helper_out_ops);
- cleanup_helperinops:
- nf_unregister_hook(&ipv4_conntrack_helper_in_ops);
- cleanup_inandlocalops:
- nf_unregister_hook(&ipv4_conntrack_local_out_ops);
- cleanup_inops:
- nf_unregister_hook(&ipv4_conntrack_in_ops);
- cleanup_defraglocalops:
- nf_unregister_hook(&ipv4_conntrack_defrag_local_out_ops);
- cleanup_defragops:
- nf_unregister_hook(&ipv4_conntrack_defrag_ops);
cleanup_ipv4:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
cleanup_icmp:
@@ -564,25 +503,24 @@ static int init_or_cleanup(int init)
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
cleanup_sockopt:
nf_unregister_sockopt(&so_getorigdst);
- cleanup_nothing:
return ret;
}
-MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
-MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
- need_conntrack();
- return init_or_cleanup(1);
-}
-
-static void __exit fini(void)
+static void __exit nf_conntrack_l3proto_ipv4_fini(void)
{
- init_or_cleanup(0);
+ synchronize_net();
+#ifdef CONFIG_SYSCTL
+ unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
+#endif
+ nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
+ nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
+ nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp);
+ nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4);
+ nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
+ nf_unregister_sockopt(&so_getorigdst);
}
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_l3proto_ipv4_init);
+module_exit(nf_conntrack_l3proto_ipv4_fini);
EXPORT_SYMBOL(nf_ct_ipv4_gather_frags);
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 52dc175be39..4b0d361cc6e 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -235,30 +235,14 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
}
/* See ip_conntrack_proto_tcp.c */
- if (hooknum != NF_IP_PRE_ROUTING)
- goto checksum_skipped;
-
- switch (skb->ip_summed) {
- case CHECKSUM_HW:
- if (!(u16)csum_fold(skb->csum))
- break;
+ if (hooknum == NF_IP_PRE_ROUTING &&
+ nf_ip_checksum(skb, hooknum, dataoff, 0)) {
if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"nf_ct_icmp: bad HW ICMP checksum ");
return -NF_ACCEPT;
- case CHECKSUM_NONE:
- if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
- if (LOG_INVALID(IPPROTO_ICMP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
- NULL,
- "nf_ct_icmp: bad ICMP checksum ");
- return -NF_ACCEPT;
- }
- default:
- break;
}
-checksum_skipped:
/*
* 18 is the highest 'known' ICMP type. Anything else is a mystery
*
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 1b167c4bb3b..d61e2a9d394 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -49,7 +49,7 @@ static int fold_prot_inuse(struct proto *proto)
int res = 0;
int cpu;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
res += proto->stats[cpu].inuse;
return res;
@@ -91,7 +91,7 @@ fold_field(void *mib[], int offt)
unsigned long res = 0;
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt);
res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt);
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 94fcbc5e5a1..cc9423de731 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2741,7 +2741,10 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
/* Reserve room for dummy headers, this skb can pass
through good chunk of routing engine.
*/
- skb->mac.raw = skb->data;
+ skb->mac.raw = skb->nh.raw = skb->data;
+
+ /* Bugfix: need to give ip_route_input enough of an IP header to not gag. */
+ skb->nh.iph->protocol = IPPROTO_ICMP;
skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
if (rta[RTA_SRC - 1])
@@ -3083,7 +3086,7 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
memcpy(dst, src, length);
/* Add the other cpus in, one int at a time */
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
unsigned int j;
src = ((u32 *) IP_RT_ACCT_CPU(i)) + offset;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 87f68e787d0..e2b7b805503 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1468,6 +1468,7 @@ void tcp_close(struct sock *sk, long timeout)
{
struct sk_buff *skb;
int data_was_unread = 0;
+ int state;
lock_sock(sk);
sk->sk_shutdown = SHUTDOWN_MASK;
@@ -1544,6 +1545,11 @@ void tcp_close(struct sock *sk, long timeout)
sk_stream_wait_close(sk, timeout);
adjudge_to_death:
+ state = sk->sk_state;
+ sock_hold(sk);
+ sock_orphan(sk);
+ atomic_inc(sk->sk_prot->orphan_count);
+
/* It is the last release_sock in its life. It will remove backlog. */
release_sock(sk);
@@ -1555,8 +1561,9 @@ adjudge_to_death:
bh_lock_sock(sk);
BUG_TRAP(!sock_owned_by_user(sk));
- sock_hold(sk);
- sock_orphan(sk);
+ /* Have we already been destroyed by a softirq or backlog? */
+ if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE)
+ goto out;
/* This is a (useful) BSD violating of the RFC. There is a
* problem with TCP as specified in that the other end could
@@ -1584,7 +1591,6 @@ adjudge_to_death:
if (tmo > TCP_TIMEWAIT_LEN) {
inet_csk_reset_keepalive_timer(sk, tcp_fin_time(sk));
} else {
- atomic_inc(sk->sk_prot->orphan_count);
tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
goto out;
}
@@ -1603,7 +1609,6 @@ adjudge_to_death:
NET_INC_STATS_BH(LINUX_MIB_TCPABORTONMEMORY);
}
}
- atomic_inc(sk->sk_prot->orphan_count);
if (sk->sk_state == TCP_CLOSE)
inet_csk_destroy_sock(sk);
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index e688c687d62..91c2f41c7f5 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -223,7 +223,7 @@ void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 rtt, u32 in_flight,
/* In dangerous area, increase slowly. */
else if (sysctl_tcp_abc) {
- /* RFC3465: Apppriate Byte Count
+ /* RFC3465: Appropriate Byte Count
* increase once for each full cwnd acked
*/
if (tp->bytes_acked >= tp->snd_cwnd*tp->mss_cache) {
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
index e0e9d1383c7..ba7c63ca5bb 100644
--- a/net/ipv4/tcp_highspeed.c
+++ b/net/ipv4/tcp_highspeed.c
@@ -135,10 +135,11 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt,
/* Do additive increase */
if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
- tp->snd_cwnd_cnt += ca->ai;
+ /* cwnd = cwnd + a(w) / cwnd */
+ tp->snd_cwnd_cnt += ca->ai + 1;
if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
- tp->snd_cwnd++;
tp->snd_cwnd_cnt -= tp->snd_cwnd;
+ tp->snd_cwnd++;
}
}
}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 195d8358455..b5521a9d3dc 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1649,7 +1649,7 @@ static void tcp_update_scoreboard(struct sock *sk, struct tcp_sock *tp)
* Hence, we can detect timed out packets during fast
* retransmit without falling to slow start.
*/
- if (tcp_head_timedout(sk, tp)) {
+ if (!IsReno(tp) && tcp_head_timedout(sk, tp)) {
struct sk_buff *skb;
skb = tp->scoreboard_skb_hint ? tp->scoreboard_skb_hint
@@ -4559,7 +4559,6 @@ discard:
EXPORT_SYMBOL(sysctl_tcp_ecn);
EXPORT_SYMBOL(sysctl_tcp_reordering);
-EXPORT_SYMBOL(sysctl_tcp_abc);
EXPORT_SYMBOL(tcp_parse_options);
EXPORT_SYMBOL(tcp_rcv_established);
EXPORT_SYMBOL(tcp_rcv_state_process);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 9e85c041610..672950e54c4 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1859,5 +1859,4 @@ EXPORT_SYMBOL(tcp_proc_unregister);
#endif
EXPORT_SYMBOL(sysctl_local_port_range);
EXPORT_SYMBOL(sysctl_tcp_low_latency);
-EXPORT_SYMBOL(sysctl_tcp_tw_reuse);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 9d79546d384..f33c9dddaa1 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -59,9 +59,6 @@ int sysctl_tcp_tso_win_divisor = 3;
int sysctl_tcp_mtu_probing = 0;
int sysctl_tcp_base_mss = 512;
-EXPORT_SYMBOL(sysctl_tcp_mtu_probing);
-EXPORT_SYMBOL(sysctl_tcp_base_mss);
-
static void update_send_head(struct sock *sk, struct tcp_sock *tp,
struct sk_buff *skb)
{
@@ -468,7 +465,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
TCP_INC_STATS(TCP_MIB_OUTSEGS);
err = icsk->icsk_af_ops->queue_xmit(skb, 0);
- if (unlikely(err <= 0))
+ if (likely(err <= 0))
return err;
tcp_enter_cwr(sk);
@@ -536,6 +533,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *buff;
int nsize, old_factor;
+ int nlen;
u16 flags;
BUG_ON(len > skb->len);
@@ -554,7 +552,11 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
buff = sk_stream_alloc_skb(sk, nsize, GFP_ATOMIC);
if (buff == NULL)
return -ENOMEM; /* We'll just try again later. */
+
sk_charge_skb(sk, buff);
+ nlen = skb->len - len - nsize;
+ buff->truesize += nlen;
+ skb->truesize -= nlen;
/* Correct the sequence numbers. */
TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
@@ -640,7 +642,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
* eventually). The difference is that pulled data not copied, but
* immediately discarded.
*/
-static unsigned char *__pskb_trim_head(struct sk_buff *skb, int len)
+static void __pskb_trim_head(struct sk_buff *skb, int len)
{
int i, k, eat;
@@ -665,7 +667,6 @@ static unsigned char *__pskb_trim_head(struct sk_buff *skb, int len)
skb->tail = skb->data;
skb->data_len -= len;
skb->len = skb->data_len;
- return skb->tail;
}
int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
@@ -674,12 +675,11 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
return -ENOMEM;
- if (len <= skb_headlen(skb)) {
+ /* If len == headlen, we avoid __skb_pull to preserve alignment. */
+ if (unlikely(len < skb_headlen(skb)))
__skb_pull(skb, len);
- } else {
- if (__pskb_trim_head(skb, len-skb_headlen(skb)) == NULL)
- return -ENOMEM;
- }
+ else
+ __pskb_trim_head(skb, len - skb_headlen(skb));
TCP_SKB_CB(skb)->seq += len;
skb->ip_summed = CHECKSUM_HW;
@@ -1040,7 +1040,8 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
if (unlikely(buff == NULL))
return -ENOMEM;
- buff->truesize = nlen;
+ sk_charge_skb(sk, buff);
+ buff->truesize += nlen;
skb->truesize -= nlen;
/* Correct the sequence numbers. */
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
new file mode 100644
index 00000000000..8d30c48f090
--- /dev/null
+++ b/net/ipv4/tunnel4.c
@@ -0,0 +1,121 @@
+/* tunnel4.c: Generic IP tunnel transformer.
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <net/icmp.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/xfrm.h>
+
+static struct xfrm_tunnel *tunnel4_handlers;
+static DEFINE_MUTEX(tunnel4_mutex);
+
+int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
+{
+ struct xfrm_tunnel **pprev;
+ int ret = -EEXIST;
+ int priority = handler->priority;
+
+ mutex_lock(&tunnel4_mutex);
+
+ for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
+ if ((*pprev)->priority > priority)
+ break;
+ if ((*pprev)->priority == priority)
+ goto err;
+ }
+
+ handler->next = *pprev;
+ *pprev = handler;
+
+ ret = 0;
+
+err:
+ mutex_unlock(&tunnel4_mutex);
+
+ return ret;
+}
+
+EXPORT_SYMBOL(xfrm4_tunnel_register);
+
+int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
+{
+ struct xfrm_tunnel **pprev;
+ int ret = -ENOENT;
+
+ mutex_lock(&tunnel4_mutex);
+
+ for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
+ if (*pprev == handler) {
+ *pprev = handler->next;
+ ret = 0;
+ break;
+ }
+ }
+
+ mutex_unlock(&tunnel4_mutex);
+
+ synchronize_net();
+
+ return ret;
+}
+
+EXPORT_SYMBOL(xfrm4_tunnel_deregister);
+
+static int tunnel4_rcv(struct sk_buff *skb)
+{
+ struct xfrm_tunnel *handler;
+
+ if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+ goto drop;
+
+ for (handler = tunnel4_handlers; handler; handler = handler->next)
+ if (!handler->handler(skb))
+ return 0;
+
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+
+drop:
+ kfree_skb(skb);
+ return 0;
+}
+
+static void tunnel4_err(struct sk_buff *skb, u32 info)
+{
+ struct xfrm_tunnel *handler;
+
+ for (handler = tunnel4_handlers; handler; handler = handler->next)
+ if (!handler->err_handler(skb, info))
+ break;
+}
+
+static struct net_protocol tunnel4_protocol = {
+ .handler = tunnel4_rcv,
+ .err_handler = tunnel4_err,
+ .no_policy = 1,
+};
+
+static int __init tunnel4_init(void)
+{
+ if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
+ printk(KERN_ERR "tunnel4 init: can't add protocol\n");
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+static void __exit tunnel4_fini(void)
+{
+ if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
+ printk(KERN_ERR "tunnel4 close: can't remove protocol\n");
+}
+
+module_init(tunnel4_init);
+module_exit(tunnel4_fini);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 850d919591d..3e174c83bfe 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -37,8 +37,6 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
{
switch (nexthdr) {
case IPPROTO_IPIP:
- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
- return -EINVAL;
*spi = skb->nh.iph->saddr;
*seq = 0;
return 0;
@@ -68,7 +66,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
{
int err;
u32 spi, seq;
- struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
+ struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
struct xfrm_state *x;
int xfrm_nr = 0;
int decaps = 0;
@@ -90,14 +88,16 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
if (unlikely(x->km.state != XFRM_STATE_VALID))
goto drop_unlock;
+ if ((x->encap ? x->encap->encap_type : 0) != encap_type)
+ goto drop_unlock;
+
if (x->props.replay_window && xfrm_replay_check(x, seq))
goto drop_unlock;
if (xfrm_state_check_expire(x))
goto drop_unlock;
- xfrm_vec[xfrm_nr].decap.decap_type = encap_type;
- if (x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb))
+ if (x->type->input(x, skb))
goto drop_unlock;
/* only the first xfrm gets the encap type */
@@ -111,7 +111,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
spin_unlock(&x->lock);
- xfrm_vec[xfrm_nr++].xvec = x;
+ xfrm_vec[xfrm_nr++] = x;
iph = skb->nh.iph;
@@ -153,7 +153,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
goto drop;
- memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
+ memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
+ xfrm_nr * sizeof(xfrm_vec[0]));
skb->sp->len += xfrm_nr;
nf_reset(skb);
@@ -184,7 +185,7 @@ drop_unlock:
xfrm_state_put(x);
drop:
while (--xfrm_nr >= 0)
- xfrm_state_put(xfrm_vec[xfrm_nr].xvec);
+ xfrm_state_put(xfrm_vec[xfrm_nr]);
kfree_skb(skb);
return 0;
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 32ad229b4fe..4ef8efaf6a6 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -62,7 +62,7 @@ static void xfrm4_encap(struct sk_buff *skb)
top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
0 : (iph->frag_off & htons(IP_DF));
if (!top_iph->frag_off)
- __ip_select_ident(top_iph, dst, 0);
+ __ip_select_ident(top_iph, dst->child, 0);
top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index f285bbf296e..8604c747bca 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -221,7 +221,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
u16 *ipcomp_hdr = (u16 *)xprth;
- fl->fl_ipsec_spi = ntohl(ntohs(ipcomp_hdr[1]));
+ fl->fl_ipsec_spi = htonl(ntohs(ipcomp_hdr[1]));
}
break;
default:
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index b08d56b117f..f8ceaa127c8 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -21,69 +21,11 @@ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
return 0;
}
-static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb)
{
return 0;
}
-static struct xfrm_tunnel *ipip_handler;
-static DEFINE_MUTEX(xfrm4_tunnel_mutex);
-
-int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
-{
- int ret;
-
- mutex_lock(&xfrm4_tunnel_mutex);
- ret = 0;
- if (ipip_handler != NULL)
- ret = -EINVAL;
- if (!ret)
- ipip_handler = handler;
- mutex_unlock(&xfrm4_tunnel_mutex);
-
- return ret;
-}
-
-EXPORT_SYMBOL(xfrm4_tunnel_register);
-
-int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
-{
- int ret;
-
- mutex_lock(&xfrm4_tunnel_mutex);
- ret = 0;
- if (ipip_handler != handler)
- ret = -EINVAL;
- if (!ret)
- ipip_handler = NULL;
- mutex_unlock(&xfrm4_tunnel_mutex);
-
- synchronize_net();
-
- return ret;
-}
-
-EXPORT_SYMBOL(xfrm4_tunnel_deregister);
-
-static int ipip_rcv(struct sk_buff *skb)
-{
- struct xfrm_tunnel *handler = ipip_handler;
-
- /* Tunnel devices take precedence. */
- if (handler && handler->handler(skb) == 0)
- return 0;
-
- return xfrm4_rcv(skb);
-}
-
-static void ipip_err(struct sk_buff *skb, u32 info)
-{
- struct xfrm_tunnel *handler = ipip_handler;
-
- if (handler)
- handler->err_handler(skb, info);
-}
-
static int ipip_init_state(struct xfrm_state *x)
{
if (!x->props.mode)
@@ -111,10 +53,15 @@ static struct xfrm_type ipip_type = {
.output = ipip_output
};
-static struct net_protocol ipip_protocol = {
- .handler = ipip_rcv,
- .err_handler = ipip_err,
- .no_policy = 1,
+static int xfrm_tunnel_err(struct sk_buff *skb, u32 info)
+{
+ return -ENOENT;
+}
+
+static struct xfrm_tunnel xfrm_tunnel_handler = {
+ .handler = xfrm4_rcv,
+ .err_handler = xfrm_tunnel_err,
+ .priority = 2,
};
static int __init ipip_init(void)
@@ -123,8 +70,8 @@ static int __init ipip_init(void)
printk(KERN_INFO "ipip init: can't add xfrm type\n");
return -EAGAIN;
}
- if (inet_add_protocol(&ipip_protocol, IPPROTO_IPIP) < 0) {
- printk(KERN_INFO "ipip init: can't add protocol\n");
+ if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) {
+ printk(KERN_INFO "ipip init: can't add xfrm handler\n");
xfrm_unregister_type(&ipip_type, AF_INET);
return -EAGAIN;
}
@@ -133,8 +80,8 @@ static int __init ipip_init(void)
static void __exit ipip_fini(void)
{
- if (inet_del_protocol(&ipip_protocol, IPPROTO_IPIP) < 0)
- printk(KERN_INFO "ipip close: can't remove protocol\n");
+ if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler))
+ printk(KERN_INFO "ipip close: can't remove xfrm handler\n");
if (xfrm_unregister_type(&ipip_type, AF_INET) < 0)
printk(KERN_INFO "ipip close: can't remove xfrm type\n");
}
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index e6f83b6a2b7..f8a107ab559 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -88,7 +88,7 @@ config INET6_IPCOMP
tristate "IPv6: IPComp transformation"
depends on IPV6
select XFRM
- select INET6_TUNNEL
+ select INET6_XFRM_TUNNEL
select CRYPTO
select CRYPTO_DEFLATE
---help---
@@ -97,19 +97,18 @@ config INET6_IPCOMP
If unsure, say Y.
+config INET6_XFRM_TUNNEL
+ tristate
+ select INET6_TUNNEL
+ default n
+
config INET6_TUNNEL
- tristate "IPv6: tunnel transformation"
- depends on IPV6
- select XFRM
- ---help---
- Support for generic IPv6-in-IPv6 tunnel transformation, which is
- required by the IPv6-in-IPv6 tunneling module as well as tunnel mode
- IPComp.
-
- If unsure, say Y.
+ tristate
+ default n
config IPV6_TUNNEL
tristate "IPv6: IPv6-in-IPv6 tunnel"
+ select INET6_TUNNEL
depends on IPV6
---help---
Support for IPv6-in-IPv6 tunnels described in RFC 2473.
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 41877abd22e..a760b0988fb 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -18,7 +18,8 @@ ipv6-objs += $(ipv6-y)
obj-$(CONFIG_INET6_AH) += ah6.o
obj-$(CONFIG_INET6_ESP) += esp6.o
obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o
-obj-$(CONFIG_INET6_TUNNEL) += xfrm6_tunnel.o
+obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o
+obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o
obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 01c62a0d374..445006ee452 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -143,7 +143,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
struct prefix_info *pinfo);
static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev);
-static struct notifier_block *inet6addr_chain;
+static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
struct ipv6_devconf ipv6_devconf = {
.forwarding = 0,
@@ -593,7 +593,7 @@ out2:
read_unlock_bh(&addrconf_lock);
if (likely(err == 0))
- notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
+ atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
else {
kfree(ifa);
ifa = ERR_PTR(err);
@@ -688,7 +688,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
ipv6_ifa_notify(RTM_DELADDR, ifp);
- notifier_call_chain(&inet6addr_chain,NETDEV_DOWN,ifp);
+ atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp);
addrconf_del_timer(ifp);
@@ -3767,12 +3767,12 @@ static void addrconf_sysctl_unregister(struct ipv6_devconf *p)
int register_inet6addr_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&inet6addr_chain, nb);
+ return atomic_notifier_chain_register(&inet6addr_chain, nb);
}
int unregister_inet6addr_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&inet6addr_chain,nb);
+ return atomic_notifier_chain_unregister(&inet6addr_chain,nb);
}
/*
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index cf58251df4b..6778173a3dd 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -229,7 +229,7 @@ error:
return err;
}
-static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
{
/*
* Before process AH
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 3dcaac7a097..22f04607903 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -130,7 +130,7 @@ error:
return err;
}
-static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
{
struct ipv6hdr *iph;
struct ipv6_esp_hdr *esph;
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 2a1e7e45b89..a18d4256372 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -485,15 +485,27 @@ static struct tlvtype_proc tlvprochopopt_lst[] = {
{ -1, }
};
-int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
+int ipv6_parse_hopopts(struct sk_buff *skb)
{
struct inet6_skb_parm *opt = IP6CB(skb);
+ /*
+ * skb->nh.raw is equal to skb->data, and
+ * skb->h.raw - skb->nh.raw is always equal to
+ * sizeof(struct ipv6hdr) by definition of
+ * hop-by-hop options.
+ */
+ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
+ !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
+ kfree_skb(skb);
+ return -1;
+ }
+
opt->hop = sizeof(struct ipv6hdr);
if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
skb->h.raw += (skb->h.raw[1]+1)<<3;
opt->nhoff = sizeof(struct ipv6hdr);
- return sizeof(struct ipv6hdr);
+ return 1;
}
return -1;
}
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 21eb725e885..1044b6fce0d 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -717,7 +717,7 @@ int __init icmpv6_init(struct net_proto_family *ops)
struct sock *sk;
int err, i, j;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
&per_cpu(__icmpv6_socket, i));
if (err < 0) {
@@ -763,7 +763,7 @@ void icmpv6_cleanup(void)
{
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
sock_release(per_cpu(__icmpv6_socket, i));
}
inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index f8f3a37a149..eb2865d5ae2 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -173,6 +173,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
if (err) {
sk->sk_err_soft = -err;
+ kfree_skb(skb);
return err;
}
@@ -181,6 +182,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
sk->sk_route_caps = 0;
+ kfree_skb(skb);
return err;
}
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index bb8ffb8a14c..2ae84c96167 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -23,6 +23,86 @@
#include <net/inet6_hashtables.h>
#include <net/ip.h>
+void __inet6_hash(struct inet_hashinfo *hashinfo,
+ struct sock *sk)
+{
+ struct hlist_head *list;
+ rwlock_t *lock;
+
+ BUG_TRAP(sk_unhashed(sk));
+
+ if (sk->sk_state == TCP_LISTEN) {
+ list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
+ lock = &hashinfo->lhash_lock;
+ inet_listen_wlock(hashinfo);
+ } else {
+ unsigned int hash;
+ sk->sk_hash = hash = inet6_sk_ehashfn(sk);
+ hash &= (hashinfo->ehash_size - 1);
+ list = &hashinfo->ehash[hash].chain;
+ lock = &hashinfo->ehash[hash].lock;
+ write_lock(lock);
+ }
+
+ __sk_add_node(sk, list);
+ sock_prot_inc_use(sk->sk_prot);
+ write_unlock(lock);
+}
+EXPORT_SYMBOL(__inet6_hash);
+
+/*
+ * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
+ * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
+ *
+ * The sockhash lock must be held as a reader here.
+ */
+struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
+ const struct in6_addr *saddr,
+ const u16 sport,
+ const struct in6_addr *daddr,
+ const u16 hnum,
+ const int dif)
+{
+ struct sock *sk;
+ const struct hlist_node *node;
+ const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
+ /* Optimize here for direct hit, only listening connections can
+ * have wildcards anyways.
+ */
+ unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
+ struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
+
+ prefetch(head->chain.first);
+ read_lock(&head->lock);
+ sk_for_each(sk, node, &head->chain) {
+ /* For IPV6 do the cheaper port and family tests first. */
+ if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
+ goto hit; /* You sunk my battleship! */
+ }
+ /* Must check for a TIME_WAIT'er before going to listener hash. */
+ sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
+ const struct inet_timewait_sock *tw = inet_twsk(sk);
+
+ if(*((__u32 *)&(tw->tw_dport)) == ports &&
+ sk->sk_family == PF_INET6) {
+ const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
+
+ if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) &&
+ ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
+ (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
+ goto hit;
+ }
+ }
+ read_unlock(&head->lock);
+ return NULL;
+
+hit:
+ sock_hold(sk);
+ read_unlock(&head->lock);
+ return sk;
+}
+EXPORT_SYMBOL(__inet6_lookup_established);
+
struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
const struct in6_addr *daddr,
const unsigned short hnum, const int dif)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 29f73592e68..aceee252503 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -114,11 +114,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
}
if (hdr->nexthdr == NEXTHDR_HOP) {
- if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) {
+ if (ipv6_parse_hopopts(skb) < 0) {
IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
return 0;
}
- hdr = skb->nh.ipv6h;
}
return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish);
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 48597538db3..a995796b5a5 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -44,7 +44,6 @@
#include <net/ip.h>
#include <net/ipv6.h>
-#include <net/protocol.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
#include <net/ip6_tunnel.h>
@@ -391,7 +390,7 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw)
* to the specifications in RFC 2473.
**/
-static void
+static int
ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __u32 info)
{
@@ -402,6 +401,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
int rel_code = ICMPV6_ADDR_UNREACH;
__u32 rel_info = 0;
__u16 len;
+ int err = -ENOENT;
/* If the packet doesn't contain the original IPv6 header we are
in trouble since we might need the source address for further
@@ -411,6 +411,8 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
if ((t = ip6ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL)
goto out;
+ err = 0;
+
switch (type) {
__u32 teli;
struct ipv6_tlv_tnl_enc_lim *tel;
@@ -492,6 +494,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
}
out:
read_unlock(&ip6ip6_lock);
+ return err;
}
static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
@@ -511,15 +514,11 @@ static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
**/
static int
-ip6ip6_rcv(struct sk_buff **pskb)
+ip6ip6_rcv(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
struct ipv6hdr *ipv6h;
struct ip6_tnl *t;
- if (!pskb_may_pull(skb, sizeof (*ipv6h)))
- goto discard;
-
ipv6h = skb->nh.ipv6h;
read_lock(&ip6ip6_lock);
@@ -527,8 +526,7 @@ ip6ip6_rcv(struct sk_buff **pskb)
if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
read_unlock(&ip6ip6_lock);
- kfree_skb(skb);
- return 0;
+ goto discard;
}
if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) {
@@ -555,9 +553,11 @@ ip6ip6_rcv(struct sk_buff **pskb)
return 0;
}
read_unlock(&ip6ip6_lock);
- icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
-discard:
return 1;
+
+discard:
+ kfree_skb(skb);
+ return 0;
}
static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
@@ -1112,39 +1112,12 @@ ip6ip6_fb_tnl_dev_init(struct net_device *dev)
return 0;
}
-#ifdef CONFIG_INET6_TUNNEL
static struct xfrm6_tunnel ip6ip6_handler = {
.handler = ip6ip6_rcv,
.err_handler = ip6ip6_err,
+ .priority = 1,
};
-static inline int ip6ip6_register(void)
-{
- return xfrm6_tunnel_register(&ip6ip6_handler);
-}
-
-static inline int ip6ip6_unregister(void)
-{
- return xfrm6_tunnel_deregister(&ip6ip6_handler);
-}
-#else
-static struct inet6_protocol xfrm6_tunnel_protocol = {
- .handler = ip6ip6_rcv,
- .err_handler = ip6ip6_err,
- .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
-};
-
-static inline int ip6ip6_register(void)
-{
- return inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
-}
-
-static inline int ip6ip6_unregister(void)
-{
- return inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
-}
-#endif
-
/**
* ip6_tunnel_init - register protocol and reserve needed resources
*
@@ -1155,7 +1128,7 @@ static int __init ip6_tunnel_init(void)
{
int err;
- if (ip6ip6_register() < 0) {
+ if (xfrm6_tunnel_register(&ip6ip6_handler)) {
printk(KERN_ERR "ip6ip6 init: can't register tunnel\n");
return -EAGAIN;
}
@@ -1174,7 +1147,7 @@ static int __init ip6_tunnel_init(void)
}
return 0;
fail:
- ip6ip6_unregister();
+ xfrm6_tunnel_deregister(&ip6ip6_handler);
return err;
}
@@ -1184,7 +1157,7 @@ fail:
static void __exit ip6_tunnel_cleanup(void)
{
- if (ip6ip6_unregister() < 0)
+ if (xfrm6_tunnel_deregister(&ip6ip6_handler))
printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
unregister_netdev(ip6ip6_fb_tnl_dev);
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 028b636687e..48636436028 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -63,7 +63,7 @@ static void **ipcomp6_scratches;
static int ipcomp6_scratch_users;
static LIST_HEAD(ipcomp6_tfms_list);
-static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
{
int err = 0;
u8 nexthdr = 0;
@@ -208,7 +208,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
if (type != ICMPV6_DEST_UNREACH && type != ICMPV6_PKT_TOOBIG)
return;
- spi = ntohl(ntohs(ipcomph->cpi));
+ spi = htonl(ntohs(ipcomph->cpi));
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6);
if (!x)
return;
@@ -228,6 +228,9 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
t->id.proto = IPPROTO_IPV6;
t->id.spi = xfrm6_tunnel_alloc_spi((xfrm_address_t *)&x->props.saddr);
+ if (!t->id.spi)
+ goto error;
+
memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr));
memcpy(&t->sel, &x->sel, sizeof(t->sel));
t->props.family = AF_INET6;
@@ -243,7 +246,9 @@ out:
return t;
error:
+ t->km.state = XFRM_STATE_DEAD;
xfrm_state_put(t);
+ t = NULL;
goto out;
}
@@ -285,7 +290,7 @@ static void ipcomp6_free_scratches(void)
if (!scratches)
return;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
void *scratch = *per_cpu_ptr(scratches, i);
vfree(scratch);
@@ -308,7 +313,7 @@ static void **ipcomp6_alloc_scratches(void)
ipcomp6_scratches = scratches;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
if (!scratch)
return NULL;
@@ -339,7 +344,7 @@ static void ipcomp6_free_tfms(struct crypto_tfm **tfms)
if (!tfms)
return;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
crypto_free_tfm(tfm);
}
@@ -379,7 +384,7 @@ static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name)
if (!tfms)
goto error;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
if (!tfm)
goto error;
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index d750cfc019d..395a417ba95 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -7,6 +7,7 @@
#include <net/ipv6.h>
#include <net/ip6_route.h>
#include <net/xfrm.h>
+#include <net/ip6_checksum.h>
int ip6_route_me_harder(struct sk_buff *skb)
{
@@ -54,7 +55,7 @@ struct ip6_rt_info {
struct in6_addr saddr;
};
-static void save(const struct sk_buff *skb, struct nf_info *info)
+static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info)
{
struct ip6_rt_info *rt_info = nf_info_reroute(info);
@@ -66,7 +67,7 @@ static void save(const struct sk_buff *skb, struct nf_info *info)
}
}
-static int reroute(struct sk_buff **pskb, const struct nf_info *info)
+static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info)
{
struct ip6_rt_info *rt_info = nf_info_reroute(info);
@@ -79,15 +80,50 @@ static int reroute(struct sk_buff **pskb, const struct nf_info *info)
return 0;
}
-static struct nf_queue_rerouter ip6_reroute = {
- .rer_size = sizeof(struct ip6_rt_info),
- .save = &save,
- .reroute = &reroute,
+unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, u_int8_t protocol)
+{
+ struct ipv6hdr *ip6h = skb->nh.ipv6h;
+ unsigned int csum = 0;
+
+ switch (skb->ip_summed) {
+ case CHECKSUM_HW:
+ if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN)
+ break;
+ if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+ skb->len - dataoff, protocol,
+ csum_sub(skb->csum,
+ skb_checksum(skb, 0,
+ dataoff, 0)))) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ break;
+ }
+ /* fall through */
+ case CHECKSUM_NONE:
+ skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+ skb->len - dataoff,
+ protocol,
+ csum_sub(0,
+ skb_checksum(skb, 0,
+ dataoff, 0)));
+ csum = __skb_checksum_complete(skb);
+ }
+ return csum;
+}
+
+EXPORT_SYMBOL(nf_ip6_checksum);
+
+static struct nf_afinfo nf_ip6_afinfo = {
+ .family = AF_INET6,
+ .checksum = nf_ip6_checksum,
+ .saveroute = nf_ip6_saveroute,
+ .reroute = nf_ip6_reroute,
+ .route_key_size = sizeof(struct ip6_rt_info),
};
int __init ipv6_netfilter_init(void)
{
- return nf_register_queue_rerouter(PF_INET6, &ip6_reroute);
+ return nf_register_afinfo(&nf_ip6_afinfo);
}
/* This can be called from inet6_init() on errors, so it cannot
@@ -95,5 +131,5 @@ int __init ipv6_netfilter_init(void)
*/
void ipv6_netfilter_fini(void)
{
- nf_unregister_queue_rerouter(PF_INET6);
+ nf_unregister_afinfo(&nf_ip6_afinfo);
}
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 98f78759f1a..4bc4e5b3379 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -87,16 +87,6 @@ config IP6_NF_MATCH_HL
To compile it as a module, choose M here. If unsure, say N.
-config IP6_NF_MATCH_MULTIPORT
- tristate "Multiple port match support"
- depends on IP6_NF_IPTABLES
- help
- Multiport matching allows you to match TCP or UDP packets based on
- a series of source or destination ports: normally a rule can only
- match a single range of ports.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP6_NF_MATCH_OWNER
tristate "Owner match support"
depends on IP6_NF_IPTABLES
@@ -115,11 +105,11 @@ config IP6_NF_MATCH_IPV6HEADER
To compile it as a module, choose M here. If unsure, say N.
-config IP6_NF_MATCH_AHESP
- tristate "AH/ESP match support"
+config IP6_NF_MATCH_AH
+ tristate "AH match support"
depends on IP6_NF_IPTABLES
help
- This module allows one to match AH and ESP packets.
+ This module allows one to match AH packets.
To compile it as a module, choose M here. If unsure, say N.
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 8436a1a1731..eeeb57d4c9c 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -8,9 +8,8 @@ obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
-obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
+obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
-obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 344eab3b5da..b4b7d441af2 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -658,15 +658,11 @@ static struct nf_queue_handler nfqh = {
.outfn = &ipq_enqueue_packet,
};
-static int
-init_or_cleanup(int init)
+static int __init ip6_queue_init(void)
{
int status = -ENOMEM;
struct proc_dir_entry *proc;
- if (!init)
- goto cleanup;
-
netlink_register_notifier(&ipq_nl_notifier);
ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk,
THIS_MODULE);
@@ -693,11 +689,6 @@ init_or_cleanup(int init)
}
return status;
-cleanup:
- nf_unregister_queue_handlers(&nfqh);
- synchronize_net();
- ipq_flush(NF_DROP);
-
cleanup_sysctl:
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
@@ -713,19 +704,25 @@ cleanup_netlink_notifier:
return status;
}
-static int __init init(void)
+static void __exit ip6_queue_fini(void)
{
-
- return init_or_cleanup(1);
-}
+ nf_unregister_queue_handlers(&nfqh);
+ synchronize_net();
+ ipq_flush(NF_DROP);
-static void __exit fini(void)
-{
- init_or_cleanup(0);
+ unregister_sysctl_table(ipq_sysctl_header);
+ unregister_netdevice_notifier(&ipq_dev_notifier);
+ proc_net_remove(IPQ_PROC_FS_NAME);
+
+ sock_release(ipqnl->sk_socket);
+ mutex_lock(&ipqnl_mutex);
+ mutex_unlock(&ipqnl_mutex);
+
+ netlink_unregister_notifier(&ipq_nl_notifier);
}
MODULE_DESCRIPTION("IPv6 packet queue handler");
MODULE_LICENSE("GPL");
-module_init(init);
-module_exit(fini);
+module_init(ip6_queue_init);
+module_exit(ip6_queue_fini);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index db3c9ae98e9..2e72f89a701 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -288,19 +288,6 @@ ip6t_do_table(struct sk_buff **pskb,
table_base = (void *)private->entries[smp_processor_id()];
e = get_entry(table_base, private->hook_entry[hook]);
-#ifdef CONFIG_NETFILTER_DEBUG
- /* Check noone else using our table */
- if (((struct ip6t_entry *)table_base)->comefrom != 0xdead57ac
- && ((struct ip6t_entry *)table_base)->comefrom != 0xeeeeeeec) {
- printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
- smp_processor_id(),
- table->name,
- &((struct ip6t_entry *)table_base)->comefrom,
- ((struct ip6t_entry *)table_base)->comefrom);
- }
- ((struct ip6t_entry *)table_base)->comefrom = 0x57acc001;
-#endif
-
/* For return from builtin chain */
back = get_entry(table_base, private->underflow[hook]);
@@ -788,7 +775,7 @@ translate_table(const char *name,
}
/* And one copy for every other CPU */
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
if (newinfo->entries[i] && newinfo->entries[i] != entry0)
memcpy(newinfo->entries[i], entry0, newinfo->size);
}
@@ -841,7 +828,7 @@ get_counters(const struct xt_table_info *t,
counters,
&i);
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (cpu == curcpu)
continue;
i = 0;
@@ -1116,7 +1103,7 @@ do_add_counters(void __user *user, unsigned int len)
write_lock_bh(&t->lock);
private = t->private;
- if (private->number != paddc->num_counters) {
+ if (private->number != tmp.num_counters) {
ret = -EINVAL;
goto unlock_up_free;
}
@@ -1406,7 +1393,7 @@ static struct ip6t_match icmp6_matchstruct = {
.family = AF_INET6,
};
-static int __init init(void)
+static int __init ip6_tables_init(void)
{
int ret;
@@ -1429,7 +1416,7 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ip6_tables_fini(void)
{
nf_unregister_sockopt(&ip6t_sockopts);
xt_unregister_match(&icmp6_matchstruct);
@@ -1517,5 +1504,5 @@ EXPORT_SYMBOL(ip6t_do_table);
EXPORT_SYMBOL(ip6t_ext_hdr);
EXPORT_SYMBOL(ipv6_find_hdr);
-module_init(init);
-module_exit(fini);
+module_init(ip6_tables_init);
+module_exit(ip6_tables_fini);
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index da14c6d86bc..b8eff8ee69b 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -93,15 +93,15 @@ static struct ip6t_target ip6t_HL = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init ip6t_hl_init(void)
{
return ip6t_register_target(&ip6t_HL);
}
-static void __exit fini(void)
+static void __exit ip6t_hl_fini(void)
{
ip6t_unregister_target(&ip6t_HL);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_hl_init);
+module_exit(ip6t_hl_fini);
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 07c6bcbe4c5..73c6300109d 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -439,7 +439,7 @@ ip6t_log_target(struct sk_buff **pskb,
if (loginfo->logflags & IP6T_LOG_NFLOG)
nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
- loginfo->prefix);
+ "%s", loginfo->prefix);
else
ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li,
loginfo->prefix);
@@ -483,7 +483,7 @@ static struct nf_logger ip6t_logger = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_log_init(void)
{
if (ip6t_register_target(&ip6t_log_reg))
return -EINVAL;
@@ -497,11 +497,11 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ip6t_log_fini(void)
{
nf_log_unregister_logger(&ip6t_logger);
ip6t_unregister_target(&ip6t_log_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_log_init);
+module_exit(ip6t_log_fini);
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index ddfa38575fe..de1175c27f6 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -255,17 +255,17 @@ static struct ip6t_target ip6t_reject_reg = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init ip6t_reject_init(void)
{
if (ip6t_register_target(&ip6t_reject_reg))
return -EINVAL;
return 0;
}
-static void __exit fini(void)
+static void __exit ip6t_reject_fini(void)
{
ip6t_unregister_target(&ip6t_reject_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_reject_init);
+module_exit(ip6t_reject_fini);
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index 178f6fb1e53..2f7bb20c758 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -122,15 +122,15 @@ static struct ip6t_match ah_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_ah_init(void)
{
return ip6t_register_match(&ah_match);
}
-static void __exit cleanup(void)
+static void __exit ip6t_ah_fini(void)
{
ip6t_unregister_match(&ah_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_ah_init);
+module_exit(ip6t_ah_fini);
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
index e97a7022698..9422413d057 100644
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ b/net/ipv6/netfilter/ip6t_dst.c
@@ -206,15 +206,15 @@ static struct ip6t_match opts_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_dst_init(void)
{
return ip6t_register_match(&opts_match);
}
-static void __exit cleanup(void)
+static void __exit ip6t_dst_fini(void)
{
ip6t_unregister_match(&opts_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_dst_init);
+module_exit(ip6t_dst_fini);
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
deleted file mode 100644
index 540b8bfd505..00000000000
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Kernel module to match ESP parameters. */
-/* (C) 2001-2002 Andras Kis-Szabo <kisza@sch.bme.hu>
- *
- * 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/skbuff.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/types.h>
-#include <net/checksum.h>
-#include <net/ipv6.h>
-
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_esp.h>
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("IPv6 ESP match");
-MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-/* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
-{
- int r=0;
- DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
- min,spi,max);
- r=(spi >= min && spi <= max) ^ invert;
- DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
- return r;
-}
-
-static int
-match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const struct xt_match *match,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
-{
- struct ip_esp_hdr _esp, *eh;
- const struct ip6t_esp *espinfo = matchinfo;
- unsigned int ptr;
-
- /* Make sure this isn't an evil packet */
- /*DEBUGP("ipv6_esp entered \n");*/
-
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP, NULL) < 0)
- return 0;
-
- eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
- if (eh == NULL) {
- *hotdrop = 1;
- return 0;
- }
-
- DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi));
-
- return (eh != NULL)
- && spi_match(espinfo->spis[0], espinfo->spis[1],
- ntohl(eh->spi),
- !!(espinfo->invflags & IP6T_ESP_INV_SPI));
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-checkentry(const char *tablename,
- const void *ip,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int matchinfosize,
- unsigned int hook_mask)
-{
- const struct ip6t_esp *espinfo = matchinfo;
-
- if (espinfo->invflags & ~IP6T_ESP_INV_MASK) {
- DEBUGP("ip6t_esp: unknown flags %X\n",
- espinfo->invflags);
- return 0;
- }
- return 1;
-}
-
-static struct ip6t_match esp_match = {
- .name = "esp",
- .match = match,
- .matchsize = sizeof(struct ip6t_esp),
- .checkentry = checkentry,
- .me = THIS_MODULE,
-};
-
-static int __init init(void)
-{
- return ip6t_register_match(&esp_match);
-}
-
-static void __exit cleanup(void)
-{
- ip6t_unregister_match(&esp_match);
-}
-
-module_init(init);
-module_exit(cleanup);
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index d4b0bad5283..4f6b84c8f4a 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -40,7 +40,7 @@ match(const struct sk_buff *skb,
memset(eui64, 0, sizeof(eui64));
- if (eth_hdr(skb)->h_proto == ntohs(ETH_P_IPV6)) {
+ if (eth_hdr(skb)->h_proto == htons(ETH_P_IPV6)) {
if (skb->nh.ipv6h->version == 0x6) {
memcpy(eui64, eth_hdr(skb)->h_source, 3);
memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3);
@@ -70,15 +70,15 @@ static struct ip6t_match eui64_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_eui64_init(void)
{
return ip6t_register_match(&eui64_match);
}
-static void __exit fini(void)
+static void __exit ip6t_eui64_fini(void)
{
ip6t_unregister_match(&eui64_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_eui64_init);
+module_exit(ip6t_eui64_fini);
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 4c41e14823d..06768c84bd3 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -139,15 +139,15 @@ static struct ip6t_match frag_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_frag_init(void)
{
return ip6t_register_match(&frag_match);
}
-static void __exit cleanup(void)
+static void __exit ip6t_frag_fini(void)
{
ip6t_unregister_match(&frag_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_frag_init);
+module_exit(ip6t_frag_fini);
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index b4a1fdfe6ab..374f1be85c0 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -206,15 +206,15 @@ static struct ip6t_match opts_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_hbh_init(void)
{
return ip6t_register_match(&opts_match);
}
-static void __exit cleanup(void)
+static void __exit ip6t_hbh_fini(void)
{
ip6t_unregister_match(&opts_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_hbh_init);
+module_exit(ip6t_hbh_fini);
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index 374055733b2..44a729e17c4 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -55,16 +55,16 @@ static struct ip6t_match hl_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_hl_init(void)
{
return ip6t_register_match(&hl_match);
}
-static void __exit fini(void)
+static void __exit ip6t_hl_fini(void)
{
ip6t_unregister_match(&hl_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_hl_init);
+module_exit(ip6t_hl_fini);
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
deleted file mode 100644
index 752b65d21c7..00000000000
--- a/net/ipv6/netfilter/ip6t_multiport.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/* Kernel module to match one of a list of TCP/UDP ports: ports are in
- the same place so we can treat them as equal. */
-
-/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/udp.h>
-#include <linux/skbuff.h>
-#include <linux/in.h>
-
-#include <linux/netfilter_ipv6/ip6t_multiport.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("ip6tables match for multiple ports");
-
-#if 0
-#define duprintf(format, args...) printk(format , ## args)
-#else
-#define duprintf(format, args...)
-#endif
-
-/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
-ports_match(const u_int16_t *portlist, enum ip6t_multiport_flags flags,
- u_int8_t count, u_int16_t src, u_int16_t dst)
-{
- unsigned int i;
- for (i=0; i<count; i++) {
- if (flags != IP6T_MULTIPORT_DESTINATION
- && portlist[i] == src)
- return 1;
-
- if (flags != IP6T_MULTIPORT_SOURCE
- && portlist[i] == dst)
- return 1;
- }
-
- return 0;
-}
-
-static int
-match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const struct xt_match *match,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
-{
- u16 _ports[2], *pptr;
- const struct ip6t_multiport *multiinfo = matchinfo;
-
- /* Must not be a fragment. */
- if (offset)
- return 0;
-
- /* Must be big enough to read ports (both UDP and TCP have
- them at the start). */
- pptr = skb_header_pointer(skb, protoff, sizeof(_ports), &_ports[0]);
- if (pptr == NULL) {
- /* We've been asked to examine this packet, and we
- * can't. Hence, no choice but to drop.
- */
- duprintf("ip6t_multiport:"
- " Dropping evil offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
- }
-
- return ports_match(multiinfo->ports,
- multiinfo->flags, multiinfo->count,
- ntohs(pptr[0]), ntohs(pptr[1]));
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-checkentry(const char *tablename,
- const void *info,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
-{
- const struct ip6t_ip6 *ip = info;
- const struct ip6t_multiport *multiinfo = matchinfo;
-
- /* Must specify proto == TCP/UDP, no unknown flags or bad count */
- return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
- && !(ip->invflags & IP6T_INV_PROTO)
- && (multiinfo->flags == IP6T_MULTIPORT_SOURCE
- || multiinfo->flags == IP6T_MULTIPORT_DESTINATION
- || multiinfo->flags == IP6T_MULTIPORT_EITHER)
- && multiinfo->count <= IP6T_MULTI_PORTS;
-}
-
-static struct ip6t_match multiport_match = {
- .name = "multiport",
- .match = match,
- .matchsize = sizeof(struct ip6t_multiport),
- .checkentry = checkentry,
- .me = THIS_MODULE,
-};
-
-static int __init init(void)
-{
- return ip6t_register_match(&multiport_match);
-}
-
-static void __exit fini(void)
-{
- ip6t_unregister_match(&multiport_match);
-}
-
-module_init(init);
-module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index e2cee3bcdef..5d047990cd4 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -79,15 +79,15 @@ static struct ip6t_match owner_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_owner_init(void)
{
return ip6t_register_match(&owner_match);
}
-static void __exit fini(void)
+static void __exit ip6t_owner_fini(void)
{
ip6t_unregister_match(&owner_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_owner_init);
+module_exit(ip6t_owner_fini);
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 4c6b55bb225..fbb0184a41d 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -225,15 +225,15 @@ static struct ip6t_match rt_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_rt_init(void)
{
return ip6t_register_match(&rt_match);
}
-static void __exit cleanup(void)
+static void __exit ip6t_rt_fini(void)
{
ip6t_unregister_match(&rt_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_rt_init);
+module_exit(ip6t_rt_fini);
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index ce4a968e1f7..60976c0c58e 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -159,7 +159,7 @@ static struct nf_hook_ops ip6t_ops[] = {
static int forward = NF_ACCEPT;
module_param(forward, bool, 0000);
-static int __init init(void)
+static int __init ip6table_filter_init(void)
{
int ret;
@@ -177,39 +177,22 @@ static int __init init(void)
return ret;
/* Register hooks */
- ret = nf_register_hook(&ip6t_ops[0]);
+ ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
if (ret < 0)
goto cleanup_table;
- ret = nf_register_hook(&ip6t_ops[1]);
- if (ret < 0)
- goto cleanup_hook0;
-
- ret = nf_register_hook(&ip6t_ops[2]);
- if (ret < 0)
- goto cleanup_hook1;
-
return ret;
- cleanup_hook1:
- nf_unregister_hook(&ip6t_ops[1]);
- cleanup_hook0:
- nf_unregister_hook(&ip6t_ops[0]);
cleanup_table:
ip6t_unregister_table(&packet_filter);
-
return ret;
}
-static void __exit fini(void)
+static void __exit ip6table_filter_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
- nf_unregister_hook(&ip6t_ops[i]);
-
+ nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
ip6t_unregister_table(&packet_filter);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6table_filter_init);
+module_exit(ip6table_filter_fini);
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 30a4627e000..03a13eab1da 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -228,7 +228,7 @@ static struct nf_hook_ops ip6t_ops[] = {
},
};
-static int __init init(void)
+static int __init ip6table_mangle_init(void)
{
int ret;
@@ -238,51 +238,22 @@ static int __init init(void)
return ret;
/* Register hooks */
- ret = nf_register_hook(&ip6t_ops[0]);
+ ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
if (ret < 0)
goto cleanup_table;
- ret = nf_register_hook(&ip6t_ops[1]);
- if (ret < 0)
- goto cleanup_hook0;
-
- ret = nf_register_hook(&ip6t_ops[2]);
- if (ret < 0)
- goto cleanup_hook1;
-
- ret = nf_register_hook(&ip6t_ops[3]);
- if (ret < 0)
- goto cleanup_hook2;
-
- ret = nf_register_hook(&ip6t_ops[4]);
- if (ret < 0)
- goto cleanup_hook3;
-
return ret;
- cleanup_hook3:
- nf_unregister_hook(&ip6t_ops[3]);
- cleanup_hook2:
- nf_unregister_hook(&ip6t_ops[2]);
- cleanup_hook1:
- nf_unregister_hook(&ip6t_ops[1]);
- cleanup_hook0:
- nf_unregister_hook(&ip6t_ops[0]);
cleanup_table:
ip6t_unregister_table(&packet_mangler);
-
return ret;
}
-static void __exit fini(void)
+static void __exit ip6table_mangle_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
- nf_unregister_hook(&ip6t_ops[i]);
-
+ nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
ip6t_unregister_table(&packet_mangler);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6table_mangle_init);
+module_exit(ip6table_mangle_fini);
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index db28ba3855e..61a7c58e99f 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -142,7 +142,7 @@ static struct nf_hook_ops ip6t_ops[] = {
},
};
-static int __init init(void)
+static int __init ip6table_raw_init(void)
{
int ret;
@@ -152,34 +152,23 @@ static int __init init(void)
return ret;
/* Register hooks */
- ret = nf_register_hook(&ip6t_ops[0]);
+ ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
if (ret < 0)
goto cleanup_table;
- ret = nf_register_hook(&ip6t_ops[1]);
- if (ret < 0)
- goto cleanup_hook0;
-
return ret;
- cleanup_hook0:
- nf_unregister_hook(&ip6t_ops[0]);
cleanup_table:
ip6t_unregister_table(&packet_raw);
-
return ret;
}
-static void __exit fini(void)
+static void __exit ip6table_raw_fini(void)
{
- unsigned int i;
-
- for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
- nf_unregister_hook(&ip6t_ops[i]);
-
+ nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
ip6t_unregister_table(&packet_raw);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6table_raw_init);
+module_exit(ip6table_raw_fini);
MODULE_LICENSE("GPL");
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index c16f62934bd..93bae36f266 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -286,55 +286,49 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
return ipv6_conntrack_in(hooknum, pskb, in, out, okfn);
}
-/* Connection tracking may drop packets, but never alters them, so
- make it the first hook. */
-static struct nf_hook_ops ipv6_conntrack_defrag_ops = {
- .hook = ipv6_defrag,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_PRE_ROUTING,
- .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ipv6_conntrack_in_ops = {
- .hook = ipv6_conntrack_in,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_PRE_ROUTING,
- .priority = NF_IP6_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ipv6_conntrack_local_out_ops = {
- .hook = ipv6_conntrack_local,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_LOCAL_OUT,
- .priority = NF_IP6_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ipv6_conntrack_defrag_local_out_ops = {
- .hook = ipv6_defrag,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_LOCAL_OUT,
- .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
-};
-
-/* Refragmenter; last chance. */
-static struct nf_hook_ops ipv6_conntrack_out_ops = {
- .hook = ipv6_confirm,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_POST_ROUTING,
- .priority = NF_IP6_PRI_LAST,
-};
-
-static struct nf_hook_ops ipv6_conntrack_local_in_ops = {
- .hook = ipv6_confirm,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_LOCAL_IN,
- .priority = NF_IP6_PRI_LAST-1,
+static struct nf_hook_ops ipv6_conntrack_ops[] = {
+ {
+ .hook = ipv6_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_PRE_ROUTING,
+ .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
+ },
+ {
+ .hook = ipv6_conntrack_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_PRE_ROUTING,
+ .priority = NF_IP6_PRI_CONNTRACK,
+ },
+ {
+ .hook = ipv6_conntrack_local,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_LOCAL_OUT,
+ .priority = NF_IP6_PRI_CONNTRACK,
+ },
+ {
+ .hook = ipv6_defrag,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_LOCAL_OUT,
+ .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
+ },
+ {
+ .hook = ipv6_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_POST_ROUTING,
+ .priority = NF_IP6_PRI_LAST,
+ },
+ {
+ .hook = ipv6_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_IP6_LOCAL_IN,
+ .priority = NF_IP6_PRI_LAST-1,
+ },
};
#ifdef CONFIG_SYSCTL
@@ -470,16 +464,21 @@ extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6;
extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6;
extern int nf_ct_frag6_init(void);
extern void nf_ct_frag6_cleanup(void);
-static int init_or_cleanup(int init)
+
+MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
+
+static int __init nf_conntrack_l3proto_ipv6_init(void)
{
int ret = 0;
- if (!init) goto cleanup;
+ need_conntrack();
ret = nf_ct_frag6_init();
if (ret < 0) {
printk("nf_conntrack_ipv6: can't initialize frag6.\n");
- goto cleanup_nothing;
+ return ret;
}
ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6);
if (ret < 0) {
@@ -505,71 +504,27 @@ static int init_or_cleanup(int init)
goto cleanup_icmpv6;
}
- ret = nf_register_hook(&ipv6_conntrack_defrag_ops);
+ ret = nf_register_hooks(ipv6_conntrack_ops,
+ ARRAY_SIZE(ipv6_conntrack_ops));
if (ret < 0) {
printk("nf_conntrack_ipv6: can't register pre-routing defrag "
"hook.\n");
goto cleanup_ipv6;
}
-
- ret = nf_register_hook(&ipv6_conntrack_defrag_local_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv6: can't register local_out defrag "
- "hook.\n");
- goto cleanup_defragops;
- }
-
- ret = nf_register_hook(&ipv6_conntrack_in_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv6: can't register pre-routing hook.\n");
- goto cleanup_defraglocalops;
- }
-
- ret = nf_register_hook(&ipv6_conntrack_local_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv6: can't register local out hook.\n");
- goto cleanup_inops;
- }
-
- ret = nf_register_hook(&ipv6_conntrack_out_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv6: can't register post-routing hook.\n");
- goto cleanup_inandlocalops;
- }
-
- ret = nf_register_hook(&ipv6_conntrack_local_in_ops);
- if (ret < 0) {
- printk("nf_conntrack_ipv6: can't register local in hook.\n");
- goto cleanup_inoutandlocalops;
- }
-
#ifdef CONFIG_SYSCTL
nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
if (nf_ct_ipv6_sysctl_header == NULL) {
printk("nf_conntrack: can't register to sysctl.\n");
ret = -ENOMEM;
- goto cleanup_localinops;
+ goto cleanup_hooks;
}
#endif
return ret;
- cleanup:
- synchronize_net();
#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
- cleanup_localinops:
+ cleanup_hooks:
+ nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
#endif
- nf_unregister_hook(&ipv6_conntrack_local_in_ops);
- cleanup_inoutandlocalops:
- nf_unregister_hook(&ipv6_conntrack_out_ops);
- cleanup_inandlocalops:
- nf_unregister_hook(&ipv6_conntrack_local_out_ops);
- cleanup_inops:
- nf_unregister_hook(&ipv6_conntrack_in_ops);
- cleanup_defraglocalops:
- nf_unregister_hook(&ipv6_conntrack_defrag_local_out_ops);
- cleanup_defragops:
- nf_unregister_hook(&ipv6_conntrack_defrag_ops);
cleanup_ipv6:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
cleanup_icmpv6:
@@ -580,24 +535,22 @@ static int init_or_cleanup(int init)
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
cleanup_frag6:
nf_ct_frag6_cleanup();
- cleanup_nothing:
return ret;
}
-MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
-
-static int __init init(void)
-{
- need_conntrack();
- return init_or_cleanup(1);
-}
-
-static void __exit fini(void)
+static void __exit nf_conntrack_l3proto_ipv6_fini(void)
{
- init_or_cleanup(0);
+ synchronize_net();
+#ifdef CONFIG_SYSCTL
+ unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
+#endif
+ nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
+ nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
+ nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6);
+ nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6);
+ nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
+ nf_ct_frag6_cleanup();
}
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_l3proto_ipv6_init);
+module_exit(nf_conntrack_l3proto_ipv6_fini);
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 09945c33305..86c6703265d 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -233,21 +233,13 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff,
return -NF_ACCEPT;
}
- if (hooknum != NF_IP6_PRE_ROUTING)
- goto skipped;
-
- /* Ignore it if the checksum's bogus. */
- if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
- skb->len - dataoff, IPPROTO_ICMPV6,
- skb_checksum(skb, dataoff,
- skb->len - dataoff, 0))) {
+ if (hooknum == NF_IP6_PRE_ROUTING &&
+ nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
"nf_ct_icmpv6: ICMPv6 checksum failed\n");
return -NF_ACCEPT;
}
-skipped:
-
/* is not error message ? */
if (icmp6h->icmp6_type >= 128)
return NF_ACCEPT;
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 4238b1ed886..779ddf77f4d 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -38,7 +38,7 @@ static int fold_prot_inuse(struct proto *proto)
int res = 0;
int cpu;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
res += proto->stats[cpu].inuse;
return res;
@@ -140,7 +140,7 @@ fold_field(void *mib[], int offt)
unsigned long res = 0;
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt);
res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt);
}
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index b67a45fb93e..eef985e010e 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -121,6 +121,10 @@ static __inline__ void fq_unlink(struct frag_queue *fq)
write_unlock(&ip6_frag_lock);
}
+/*
+ * callers should be careful not to use the hash value outside the ipfrag_lock
+ * as doing so could race with ipfrag_hash_rnd being recalculated.
+ */
static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr,
struct in6_addr *daddr)
{
@@ -324,15 +328,16 @@ out:
/* Creation primitives. */
-static struct frag_queue *ip6_frag_intern(unsigned int hash,
- struct frag_queue *fq_in)
+static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in)
{
struct frag_queue *fq;
+ unsigned int hash;
#ifdef CONFIG_SMP
struct hlist_node *n;
#endif
write_lock(&ip6_frag_lock);
+ hash = ip6qhashfn(fq_in->id, &fq_in->saddr, &fq_in->daddr);
#ifdef CONFIG_SMP
hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) {
if (fq->id == fq_in->id &&
@@ -362,7 +367,7 @@ static struct frag_queue *ip6_frag_intern(unsigned int hash,
static struct frag_queue *
-ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr *dst)
+ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst)
{
struct frag_queue *fq;
@@ -379,7 +384,7 @@ ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr
spin_lock_init(&fq->lock);
atomic_set(&fq->refcnt, 1);
- return ip6_frag_intern(hash, fq);
+ return ip6_frag_intern(fq);
oom:
IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
@@ -391,9 +396,10 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
{
struct frag_queue *fq;
struct hlist_node *n;
- unsigned int hash = ip6qhashfn(id, src, dst);
+ unsigned int hash;
read_lock(&ip6_frag_lock);
+ hash = ip6qhashfn(id, src, dst);
hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) {
if (fq->id == id &&
ipv6_addr_equal(src, &fq->saddr) &&
@@ -405,7 +411,7 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
}
read_unlock(&ip6_frag_lock);
- return ip6_frag_create(hash, id, src, dst);
+ return ip6_frag_create(id, src, dst);
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 79078747a64..8a777932786 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -280,10 +280,13 @@ static int inline rt6_check_neigh(struct rt6_info *rt)
{
struct neighbour *neigh = rt->rt6i_nexthop;
int m = 0;
- if (neigh) {
+ if (rt->rt6i_flags & RTF_NONEXTHOP ||
+ !(rt->rt6i_flags & RTF_GATEWAY))
+ m = 1;
+ else if (neigh) {
read_lock_bh(&neigh->lock);
if (neigh->nud_state & NUD_VALID)
- m = 1;
+ m = 2;
read_unlock_bh(&neigh->lock);
}
return m;
@@ -292,15 +295,18 @@ static int inline rt6_check_neigh(struct rt6_info *rt)
static int rt6_score_route(struct rt6_info *rt, int oif,
int strict)
{
- int m = rt6_check_dev(rt, oif);
+ int m, n;
+
+ m = rt6_check_dev(rt, oif);
if (!m && (strict & RT6_SELECT_F_IFACE))
return -1;
#ifdef CONFIG_IPV6_ROUTER_PREF
m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
#endif
- if (rt6_check_neigh(rt))
+ n = rt6_check_neigh(rt);
+ if (n > 1)
m |= 16;
- else if (strict & RT6_SELECT_F_REACHABLE)
+ else if (!n && strict & RT6_SELECT_F_REACHABLE)
return -1;
return m;
}
@@ -317,7 +323,7 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
__FUNCTION__, head, head ? *head : NULL, oif);
for (rt = rt0, metric = rt0->rt6i_metric;
- rt && rt->rt6i_metric == metric;
+ rt && rt->rt6i_metric == metric && (!last || rt != rt0);
rt = rt->u.next) {
int m;
@@ -343,9 +349,12 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
(strict & RT6_SELECT_F_REACHABLE) &&
last && last != rt0) {
/* no entries matched; do round-robin */
+ static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+ spin_lock(&lock);
*head = rt0->u.next;
rt0->u.next = last->u.next;
last->u.next = rt0;
+ spin_unlock(&lock);
}
RT6_TRACE("%s() => %p, score=%d\n",
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index c2d3e17beae..6578c3080f4 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -397,7 +397,7 @@ static int ipip6_rcv(struct sk_buff *skb)
return 0;
}
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
kfree_skb(skb);
read_unlock(&ipip6_lock);
out:
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
new file mode 100644
index 00000000000..0ef9a35798d
--- /dev/null
+++ b/net/ipv6/tunnel6.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C)2003,2004 USAGI/WIDE Project
+ *
+ * This program is free software; 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
+ *
+ * Authors Mitsuru KANDA <mk@linux-ipv6.org>
+ * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
+ */
+
+#include <linux/icmpv6.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <net/ipv6.h>
+#include <net/protocol.h>
+#include <net/xfrm.h>
+
+static struct xfrm6_tunnel *tunnel6_handlers;
+static DEFINE_MUTEX(tunnel6_mutex);
+
+int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
+{
+ struct xfrm6_tunnel **pprev;
+ int ret = -EEXIST;
+ int priority = handler->priority;
+
+ mutex_lock(&tunnel6_mutex);
+
+ for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
+ if ((*pprev)->priority > priority)
+ break;
+ if ((*pprev)->priority == priority)
+ goto err;
+ }
+
+ handler->next = *pprev;
+ *pprev = handler;
+
+ ret = 0;
+
+err:
+ mutex_unlock(&tunnel6_mutex);
+
+ return ret;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_register);
+
+int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
+{
+ struct xfrm6_tunnel **pprev;
+ int ret = -ENOENT;
+
+ mutex_lock(&tunnel6_mutex);
+
+ for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
+ if (*pprev == handler) {
+ *pprev = handler->next;
+ ret = 0;
+ break;
+ }
+ }
+
+ mutex_unlock(&tunnel6_mutex);
+
+ synchronize_net();
+
+ return ret;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_deregister);
+
+static int tunnel6_rcv(struct sk_buff **pskb)
+{
+ struct sk_buff *skb = *pskb;
+ struct xfrm6_tunnel *handler;
+
+ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+ goto drop;
+
+ for (handler = tunnel6_handlers; handler; handler = handler->next)
+ if (!handler->handler(skb))
+ return 0;
+
+ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);
+
+drop:
+ kfree_skb(skb);
+ return 0;
+}
+
+static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int type, int code, int offset, __u32 info)
+{
+ struct xfrm6_tunnel *handler;
+
+ for (handler = tunnel6_handlers; handler; handler = handler->next)
+ if (!handler->err_handler(skb, opt, type, code, offset, info))
+ break;
+}
+
+static struct inet6_protocol tunnel6_protocol = {
+ .handler = tunnel6_rcv,
+ .err_handler = tunnel6_err,
+ .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+};
+
+static int __init tunnel6_init(void)
+{
+ if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) {
+ printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+static void __exit tunnel6_fini(void)
+{
+ if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6))
+ printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
+}
+
+module_init(tunnel6_init);
+module_exit(tunnel6_fini);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 1ca2da68ef6..00cfdee18dc 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -28,12 +28,11 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
IP6_ECN_set_ce(inner_iph);
}
-int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi)
+int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
{
- struct sk_buff *skb = *pskb;
int err;
u32 seq;
- struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
+ struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
struct xfrm_state *x;
int xfrm_nr = 0;
int decaps = 0;
@@ -66,7 +65,7 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi)
if (xfrm_state_check_expire(x))
goto drop_unlock;
- nexthdr = x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb);
+ nexthdr = x->type->input(x, skb);
if (nexthdr <= 0)
goto drop_unlock;
@@ -80,7 +79,7 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi)
spin_unlock(&x->lock);
- xfrm_vec[xfrm_nr++].xvec = x;
+ xfrm_vec[xfrm_nr++] = x;
if (x->props.mode) { /* XXX */
if (nexthdr != IPPROTO_IPV6)
@@ -119,7 +118,8 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi)
if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
goto drop;
- memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
+ memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
+ xfrm_nr * sizeof(xfrm_vec[0]));
skb->sp->len += xfrm_nr;
skb->ip_summed = CHECKSUM_NONE;
@@ -150,7 +150,7 @@ drop_unlock:
xfrm_state_put(x);
drop:
while (--xfrm_nr >= 0)
- xfrm_state_put(xfrm_vec[xfrm_nr].xvec);
+ xfrm_state_put(xfrm_vec[xfrm_nr]);
kfree_skb(skb);
return -1;
}
@@ -159,5 +159,5 @@ EXPORT_SYMBOL(xfrm6_rcv_spi);
int xfrm6_rcv(struct sk_buff **pskb)
{
- return xfrm6_rcv_spi(pskb, 0);
+ return xfrm6_rcv_spi(*pskb, 0);
}
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 91cce8b2d7a..88c840f1beb 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -191,16 +191,18 @@ error:
static inline void
_decode_session6(struct sk_buff *skb, struct flowi *fl)
{
- u16 offset = sizeof(struct ipv6hdr);
+ u16 offset = skb->h.raw - skb->nh.raw;
struct ipv6hdr *hdr = skb->nh.ipv6h;
- struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
- u8 nexthdr = skb->nh.ipv6h->nexthdr;
+ struct ipv6_opt_hdr *exthdr;
+ u8 nexthdr = skb->nh.raw[IP6CB(skb)->nhoff];
memset(fl, 0, sizeof(struct flowi));
ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
+ exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+
switch (nexthdr) {
case NEXTHDR_ROUTING:
case NEXTHDR_HOP:
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 08f9abbdf1d..d37768e5064 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -28,7 +28,6 @@
#include <net/ip.h>
#include <net/xfrm.h>
#include <net/ipv6.h>
-#include <net/protocol.h>
#include <linux/ipv6.h>
#include <linux/icmpv6.h>
#include <linux/mutex.h>
@@ -352,76 +351,23 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
return 0;
}
-static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
return 0;
}
-static struct xfrm6_tunnel *xfrm6_tunnel_handler;
-static DEFINE_MUTEX(xfrm6_tunnel_mutex);
-
-int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
+static int xfrm6_tunnel_rcv(struct sk_buff *skb)
{
- int ret;
-
- mutex_lock(&xfrm6_tunnel_mutex);
- ret = 0;
- if (xfrm6_tunnel_handler != NULL)
- ret = -EINVAL;
- if (!ret)
- xfrm6_tunnel_handler = handler;
- mutex_unlock(&xfrm6_tunnel_mutex);
-
- return ret;
-}
-
-EXPORT_SYMBOL(xfrm6_tunnel_register);
-
-int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
-{
- int ret;
-
- mutex_lock(&xfrm6_tunnel_mutex);
- ret = 0;
- if (xfrm6_tunnel_handler != handler)
- ret = -EINVAL;
- if (!ret)
- xfrm6_tunnel_handler = NULL;
- mutex_unlock(&xfrm6_tunnel_mutex);
-
- synchronize_net();
-
- return ret;
-}
-
-EXPORT_SYMBOL(xfrm6_tunnel_deregister);
-
-static int xfrm6_tunnel_rcv(struct sk_buff **pskb)
-{
- struct sk_buff *skb = *pskb;
- struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
struct ipv6hdr *iph = skb->nh.ipv6h;
u32 spi;
- /* device-like_ip6ip6_handler() */
- if (handler && handler->handler(pskb) == 0)
- return 0;
-
spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
- return xfrm6_rcv_spi(pskb, spi);
+ return xfrm6_rcv_spi(skb, spi);
}
-static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int type, int code, int offset, __u32 info)
{
- struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
-
- /* call here first for device-like ip6ip6 err handling */
- if (handler) {
- handler->err_handler(skb, opt, type, code, offset, info);
- return;
- }
-
/* xfrm6_tunnel native err handling */
switch (type) {
case ICMPV6_DEST_UNREACH:
@@ -462,7 +408,8 @@ static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
default:
break;
}
- return;
+
+ return 0;
}
static int xfrm6_tunnel_init_state(struct xfrm_state *x)
@@ -493,10 +440,10 @@ static struct xfrm_type xfrm6_tunnel_type = {
.output = xfrm6_tunnel_output,
};
-static struct inet6_protocol xfrm6_tunnel_protocol = {
+static struct xfrm6_tunnel xfrm6_tunnel_handler = {
.handler = xfrm6_tunnel_rcv,
- .err_handler = xfrm6_tunnel_err,
- .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+ .err_handler = xfrm6_tunnel_err,
+ .priority = 2,
};
static int __init xfrm6_tunnel_init(void)
@@ -508,16 +455,16 @@ static int __init xfrm6_tunnel_init(void)
"xfrm6_tunnel init: can't add xfrm type\n");
return -EAGAIN;
}
- if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) {
+ if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) {
X6TPRINTK1(KERN_ERR
- "xfrm6_tunnel init(): can't add protocol\n");
+ "xfrm6_tunnel init(): can't add handler\n");
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
return -EAGAIN;
}
if (xfrm6_tunnel_spi_init() < 0) {
X6TPRINTK1(KERN_ERR
"xfrm6_tunnel init: failed to initialize spi\n");
- inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
+ xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
return -EAGAIN;
}
@@ -529,9 +476,9 @@ static void __exit xfrm6_tunnel_fini(void)
X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
xfrm6_tunnel_spi_fini();
- if (inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0)
+ if (xfrm6_tunnel_deregister(&xfrm6_tunnel_handler))
X6TPRINTK1(KERN_ERR
- "xfrm6_tunnel close: can't remove protocol\n");
+ "xfrm6_tunnel close: can't remove handler\n");
if (xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6) < 0)
X6TPRINTK1(KERN_ERR
"xfrm6_tunnel close: can't remove xfrm type\n");
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 0fb513a34d1..811d998725b 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -944,9 +944,9 @@ out:
return rc;
}
-static int ipx_map_frame_type(unsigned char type)
+static __be16 ipx_map_frame_type(unsigned char type)
{
- int rc = 0;
+ __be16 rc = 0;
switch (type) {
case IPX_FRAME_ETHERII: rc = htons(ETH_P_IPX); break;
@@ -1892,6 +1892,29 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return rc;
}
+
+#ifdef CONFIG_COMPAT
+static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ /*
+ * These 4 commands use same structure on 32bit and 64bit. Rest of IPX
+ * commands is handled by generic ioctl code. As these commands are
+ * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic
+ * code.
+ */
+ switch (cmd) {
+ case SIOCAIPXITFCRT:
+ case SIOCAIPXPRISLT:
+ case SIOCIPXCFGDATA:
+ case SIOCIPXNCPCONN:
+ return ipx_ioctl(sock, cmd, arg);
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+#endif
+
+
/*
* Socket family declarations
*/
@@ -1913,6 +1936,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
.getname = ipx_getname,
.poll = datagram_poll,
.ioctl = ipx_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = ipx_compat_ioctl,
+#endif
.listen = sock_no_listen,
.shutdown = sock_no_shutdown, /* FIXME: support shutdown */
.setsockopt = ipx_setsockopt,
diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c
index 67774448efd..a394c6fe19a 100644
--- a/net/ipx/ipx_route.c
+++ b/net/ipx/ipx_route.c
@@ -119,7 +119,7 @@ out:
return rc;
}
-static int ipxrtr_delete(long net)
+static int ipxrtr_delete(__u32 net)
{
struct ipx_route *r, *tmp;
int rc;
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 75944564866..2f37c9f35e2 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -1302,7 +1302,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
if (sk->sk_state != TCP_ESTABLISHED)
return -ENOTCONN;
- /* Check that we don't send out to big frames */
+ /* Check that we don't send out too big frames */
if (len > self->max_data_size) {
IRDA_DEBUG(2, "%s(), Chopping frame from %zd to %d bytes!\n",
__FUNCTION__, len, self->max_data_size);
@@ -1546,7 +1546,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
IRDA_ASSERT(self != NULL, return -1;);
/*
- * Check that we don't send out to big frames. This is an unreliable
+ * Check that we don't send out too big frames. This is an unreliable
* service, so we have no fragmentation and no coalescence
*/
if (len > self->max_data_size) {
@@ -1642,7 +1642,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
}
/*
- * Check that we don't send out to big frames. This is an unreliable
+ * Check that we don't send out too big frames. This is an unreliable
* service, so we have no fragmentation and no coalescence
*/
if (len > self->max_data_size) {
@@ -1830,6 +1830,19 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return 0;
}
+#ifdef CONFIG_COMPAT
+/*
+ * Function irda_ioctl (sock, cmd, arg)
+ */
+static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ /*
+ * All IRDA's ioctl are standard ones.
+ */
+ return -ENOIOCTLCMD;
+}
+#endif
+
/*
* Function irda_setsockopt (sock, level, optname, optval, optlen)
*
@@ -2476,6 +2489,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
.getname = irda_getname,
.poll = irda_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = irda_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
@@ -2497,6 +2513,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.getname = irda_getname,
.poll = datagram_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = irda_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
@@ -2518,6 +2537,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
.getname = irda_getname,
.poll = datagram_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = irda_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
@@ -2540,6 +2562,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
.getname = irda_getname,
.poll = datagram_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = sock_no_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index 254f9074690..2d2e2b1919f 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -544,7 +544,8 @@ static void iriap_getvaluebyclass_response(struct iriap_cb *self,
{
struct sk_buff *tx_skb;
int n;
- __u32 tmp_be32, tmp_be16;
+ __u32 tmp_be32;
+ __be16 tmp_be16;
__u8 *fp;
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c
index c6d169fbdce..82e665c7999 100644
--- a/net/irda/irias_object.c
+++ b/net/irda/irias_object.c
@@ -257,7 +257,6 @@ struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name)
/* Unsafe (locking), attrib might change */
return attrib;
}
-EXPORT_SYMBOL(irias_find_attrib);
/*
* Function irias_add_attribute (obj, attrib)
@@ -484,7 +483,6 @@ struct ias_value *irias_new_string_value(char *string)
return value;
}
-EXPORT_SYMBOL(irias_new_string_value);
/*
* Function irias_new_octseq_value (octets, len)
@@ -519,7 +517,6 @@ struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
memcpy(value->t.oct_seq, octseq , len);
return value;
}
-EXPORT_SYMBOL(irias_new_octseq_value);
struct ias_value *irias_new_missing_value(void)
{
diff --git a/net/irda/irlap.c b/net/irda/irlap.c
index 7029618f571..a16528657b4 100644
--- a/net/irda/irlap.c
+++ b/net/irda/irlap.c
@@ -884,7 +884,8 @@ static void irlap_change_speed(struct irlap_cb *self, __u32 speed, int now)
if (now) {
/* Send down empty frame to trigger speed change */
skb = dev_alloc_skb(0);
- irlap_queue_xmit(self, skb);
+ if (skb)
+ irlap_queue_xmit(self, skb);
}
}
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index 8f3addf0724..d62e0f9b9da 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -118,7 +118,8 @@ static inline int llc_fixup_skb(struct sk_buff *skb)
u16 pdulen = eth_hdr(skb)->h_proto,
data_size = ntohs(pdulen) - llc_len;
- skb_trim(skb, data_size);
+ if (unlikely(pskb_trim_rcsum(skb, data_size)))
+ return 0;
}
return 1;
}
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 332acb37b38..e2893effdfa 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -231,6 +231,15 @@ config NETFILTER_XT_MATCH_DCCP
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+config NETFILTER_XT_MATCH_ESP
+ tristate '"ESP" match support'
+ depends on NETFILTER_XTABLES
+ help
+ This match extension allows you to match a range of SPIs
+ inside ESP header of IPSec packets.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_MATCH_HELPER
tristate '"helper" match support'
depends on NETFILTER_XTABLES
@@ -289,6 +298,16 @@ config NETFILTER_XT_MATCH_POLICY
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_MATCH_MULTIPORT
+ tristate "Multiple port match support"
+ depends on NETFILTER_XTABLES
+ help
+ Multiport matching allows you to match TCP or UDP packets based on
+ a series of source or destination ports: normally a rule can only
+ match a single range of ports.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_MATCH_PHYSDEV
tristate '"physdev" match support'
depends on NETFILTER_XTABLES && BRIDGE_NETFILTER
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 9558727f5e7..95b7e416512 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -35,11 +35,13 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 1ceb1a6c254..8455a32ea5c 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -27,6 +27,29 @@
#include "nf_internals.h"
+static DEFINE_SPINLOCK(afinfo_lock);
+
+struct nf_afinfo *nf_afinfo[NPROTO];
+EXPORT_SYMBOL(nf_afinfo);
+
+int nf_register_afinfo(struct nf_afinfo *afinfo)
+{
+ spin_lock(&afinfo_lock);
+ rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo);
+ spin_unlock(&afinfo_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nf_register_afinfo);
+
+void nf_unregister_afinfo(struct nf_afinfo *afinfo)
+{
+ spin_lock(&afinfo_lock);
+ rcu_assign_pointer(nf_afinfo[afinfo->family], NULL);
+ spin_unlock(&afinfo_lock);
+ synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
+
/* In this code, we can be waiting indefinitely for userspace to
* service a packet if a hook returns NF_QUEUE. We could keep a count
* of skbuffs queued for userspace, and not deregister a hook unless
@@ -63,6 +86,34 @@ void nf_unregister_hook(struct nf_hook_ops *reg)
}
EXPORT_SYMBOL(nf_unregister_hook);
+int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
+{
+ unsigned int i;
+ int err = 0;
+
+ for (i = 0; i < n; i++) {
+ err = nf_register_hook(&reg[i]);
+ if (err)
+ goto err;
+ }
+ return err;
+
+err:
+ if (i > 0)
+ nf_unregister_hooks(reg, i);
+ return err;
+}
+EXPORT_SYMBOL(nf_register_hooks);
+
+void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; i++)
+ nf_unregister_hook(&reg[i]);
+}
+EXPORT_SYMBOL(nf_unregister_hooks);
+
unsigned int nf_iterate(struct list_head *head,
struct sk_buff **skb,
int hook,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 0ae281d9bfc..f9b83f91371 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -90,8 +90,8 @@ static int nf_conntrack_vmalloc;
static unsigned int nf_conntrack_next_id;
static unsigned int nf_conntrack_expect_next_id;
#ifdef CONFIG_NF_CONNTRACK_EVENTS
-struct notifier_block *nf_conntrack_chain;
-struct notifier_block *nf_conntrack_expect_chain;
+ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
+ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain);
DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
@@ -103,7 +103,7 @@ __nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache)
DEBUGP("ecache: delivering events for %p\n", ecache->ct);
if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct)
&& ecache->events)
- notifier_call_chain(&nf_conntrack_chain, ecache->events,
+ atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events,
ecache->ct);
ecache->events = 0;
@@ -146,7 +146,7 @@ static void nf_ct_event_cache_flush(void)
struct nf_conntrack_ecache *ecache;
int cpu;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
ecache = &per_cpu(nf_conntrack_ecache, cpu);
if (ecache->ct)
nf_ct_put(ecache->ct);
@@ -178,9 +178,6 @@ static struct {
/* allocated slab cache + modules which uses this slab cache */
int use;
- /* Initialization */
- int (*init_conntrack)(struct nf_conn *, u_int32_t);
-
} nf_ct_cache[NF_CT_F_NUM];
/* protect members of nf_ct_cache except of "use" */
@@ -208,10 +205,8 @@ nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol)
preempt_disable();
p = __nf_ct_proto_find(l3proto, protocol);
- if (p) {
- if (!try_module_get(p->me))
- p = &nf_conntrack_generic_protocol;
- }
+ if (!try_module_get(p->me))
+ p = &nf_conntrack_generic_protocol;
preempt_enable();
return p;
@@ -229,10 +224,8 @@ nf_ct_l3proto_find_get(u_int16_t l3proto)
preempt_disable();
p = __nf_ct_l3proto_find(l3proto);
- if (p) {
- if (!try_module_get(p->me))
- p = &nf_conntrack_generic_l3proto;
- }
+ if (!try_module_get(p->me))
+ p = &nf_conntrack_generic_l3proto;
preempt_enable();
return p;
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index cd191b0d4ac..e38a4b5a308 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -624,7 +624,7 @@ static struct nf_conntrack_helper ftp[MAX_PORTS][2];
static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")];
/* don't make this __exit, since it's called from __init ! */
-static void fini(void)
+static void nf_conntrack_ftp_fini(void)
{
int i, j;
for (i = 0; i < ports_c; i++) {
@@ -642,7 +642,7 @@ static void fini(void)
kfree(ftp_buffer);
}
-static int __init init(void)
+static int __init nf_conntrack_ftp_init(void)
{
int i, j = -1, ret = 0;
char *tmpname;
@@ -683,7 +683,7 @@ static int __init init(void)
printk("nf_ct_ftp: failed to register helper "
" for pf: %d port: %d\n",
ftp[i][j].tuple.src.l3num, ports[i]);
- fini();
+ nf_conntrack_ftp_fini();
return ret;
}
}
@@ -692,5 +692,5 @@ static int __init init(void)
return 0;
}
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_ftp_init);
+module_exit(nf_conntrack_ftp_fini);
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index 7de4f06c63c..3fc58e454d4 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -94,5 +94,4 @@ struct nf_conntrack_l3proto nf_conntrack_generic_l3proto = {
.print_conntrack = generic_print_conntrack,
.prepare = generic_prepare,
.get_features = generic_get_features,
- .me = THIS_MODULE,
};
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 0e0e9d7b34c..bd10eb944b6 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1022,7 +1022,7 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[])
return err;
}
-#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+#if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK-1])
ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
#endif
@@ -1062,7 +1062,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
return err;
}
-#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+#if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK-1])
ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
#endif
@@ -1687,7 +1687,7 @@ static void __exit ctnetlink_exit(void)
printk("ctnetlink: unregistering from nfnetlink.\n");
#ifdef CONFIG_NF_CONNTRACK_EVENTS
- nf_conntrack_unregister_notifier(&ctnl_notifier_exp);
+ nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
nf_conntrack_unregister_notifier(&ctnl_notifier);
#endif
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index cf798e61e37..0c6da496cfa 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -240,12 +240,15 @@ static int do_basic_checks(struct nf_conn *conntrack,
flag = 1;
}
- /* Cookie Ack/Echo chunks not the first OR
- Init / Init Ack / Shutdown compl chunks not the only chunks */
- if ((sch->type == SCTP_CID_COOKIE_ACK
+ /*
+ * Cookie Ack/Echo chunks not the first OR
+ * Init / Init Ack / Shutdown compl chunks not the only chunks
+ * OR zero-length.
+ */
+ if (((sch->type == SCTP_CID_COOKIE_ACK
|| sch->type == SCTP_CID_COOKIE_ECHO
|| flag)
- && count !=0 ) {
+ && count !=0) || !sch->length) {
DEBUGP("Basic checks failed\n");
return 1;
}
@@ -615,7 +618,7 @@ static ctl_table nf_ct_net_table[] = {
static struct ctl_table_header *nf_ct_sysctl_header;
#endif
-int __init init(void)
+int __init nf_conntrack_proto_sctp_init(void)
{
int ret;
@@ -652,7 +655,7 @@ int __init init(void)
return ret;
}
-void __exit fini(void)
+void __exit nf_conntrack_proto_sctp_fini(void)
{
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp6);
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp4);
@@ -662,8 +665,8 @@ void __exit fini(void)
DEBUGP("SCTP conntrack module unloaded\n");
}
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_proto_sctp_init);
+module_exit(nf_conntrack_proto_sctp_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kiran Kumar Immidi");
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 6492ed66fb3..69899f27d26 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -799,8 +799,7 @@ static int tcp_error(struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
- unsigned int hooknum,
- int(*csum)(const struct sk_buff *,unsigned int))
+ unsigned int hooknum)
{
struct tcphdr _tcph, *th;
unsigned int tcplen = skb->len - dataoff;
@@ -830,9 +829,8 @@ static int tcp_error(struct sk_buff *skb,
*/
/* FIXME: Source route IP option packets --RR */
if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
- (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))
- && skb->ip_summed != CHECKSUM_UNNECESSARY
- && csum(skb, dataoff)) {
+ (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
+ nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: bad TCP checksum ");
@@ -851,44 +849,6 @@ static int tcp_error(struct sk_buff *skb,
return NF_ACCEPT;
}
-static int csum4(const struct sk_buff *skb, unsigned int dataoff)
-{
- return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
- skb->len - dataoff, IPPROTO_TCP,
- skb->ip_summed == CHECKSUM_HW ? skb->csum
- : skb_checksum(skb, dataoff,
- skb->len - dataoff, 0));
-}
-
-static int csum6(const struct sk_buff *skb, unsigned int dataoff)
-{
- return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
- skb->len - dataoff, IPPROTO_TCP,
- skb->ip_summed == CHECKSUM_HW
- ? csum_sub(skb->csum,
- skb_checksum(skb, 0, dataoff, 0))
- : skb_checksum(skb, dataoff, skb->len - dataoff,
- 0));
-}
-
-static int tcp_error4(struct sk_buff *skb,
- unsigned int dataoff,
- enum ip_conntrack_info *ctinfo,
- int pf,
- unsigned int hooknum)
-{
- return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
-}
-
-static int tcp_error6(struct sk_buff *skb,
- unsigned int dataoff,
- enum ip_conntrack_info *ctinfo,
- int pf,
- unsigned int hooknum)
-{
- return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
-}
-
/* Returns verdict for packet, or -1 for invalid. */
static int tcp_packet(struct nf_conn *conntrack,
const struct sk_buff *skb,
@@ -1218,7 +1178,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
.print_conntrack = tcp_print_conntrack,
.packet = tcp_packet,
.new = tcp_new,
- .error = tcp_error4,
+ .error = tcp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
.to_nfattr = tcp_to_nfattr,
@@ -1239,7 +1199,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
.print_conntrack = tcp_print_conntrack,
.packet = tcp_packet,
.new = tcp_new,
- .error = tcp_error6,
+ .error = tcp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
.to_nfattr = tcp_to_nfattr,
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 831d206344e..d93edbfde9e 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -103,8 +103,7 @@ static int udp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
static int udp_error(struct sk_buff *skb, unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf,
- unsigned int hooknum,
- int (*csum)(const struct sk_buff *, unsigned int))
+ unsigned int hooknum)
{
unsigned int udplen = skb->len - dataoff;
struct udphdr _hdr, *hdr;
@@ -136,9 +135,8 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
* and moreover root might send raw packets.
* FIXME: Source route IP option packets --RR */
if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
- (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))
- && skb->ip_summed != CHECKSUM_UNNECESSARY
- && csum(skb, dataoff)) {
+ (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
+ nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_udp: bad UDP checksum ");
@@ -148,44 +146,6 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
return NF_ACCEPT;
}
-static int csum4(const struct sk_buff *skb, unsigned int dataoff)
-{
- return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
- skb->len - dataoff, IPPROTO_UDP,
- skb->ip_summed == CHECKSUM_HW ? skb->csum
- : skb_checksum(skb, dataoff,
- skb->len - dataoff, 0));
-}
-
-static int csum6(const struct sk_buff *skb, unsigned int dataoff)
-{
- return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
- skb->len - dataoff, IPPROTO_UDP,
- skb->ip_summed == CHECKSUM_HW
- ? csum_sub(skb->csum,
- skb_checksum(skb, 0, dataoff, 0))
- : skb_checksum(skb, dataoff, skb->len - dataoff,
- 0));
-}
-
-static int udp_error4(struct sk_buff *skb,
- unsigned int dataoff,
- enum ip_conntrack_info *ctinfo,
- int pf,
- unsigned int hooknum)
-{
- return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
-}
-
-static int udp_error6(struct sk_buff *skb,
- unsigned int dataoff,
- enum ip_conntrack_info *ctinfo,
- int pf,
- unsigned int hooknum)
-{
- return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
-}
-
struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
{
.l3proto = PF_INET,
@@ -197,7 +157,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
.print_conntrack = udp_print_conntrack,
.packet = udp_packet,
.new = udp_new,
- .error = udp_error4,
+ .error = udp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
@@ -216,7 +176,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
.print_conntrack = udp_print_conntrack,
.packet = udp_packet,
.new = udp_new,
- .error = udp_error6,
+ .error = udp_error,
#if defined(CONFIG_NF_CT_NETLINK) || \
defined(CONFIG_NF_CT_NETLINK_MODULE)
.tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 75577e175b3..408960c6a54 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -649,63 +649,6 @@ static ctl_table nf_ct_net_table[] = {
EXPORT_SYMBOL(nf_ct_log_invalid);
#endif /* CONFIG_SYSCTL */
-static int init_or_cleanup(int init)
-{
-#ifdef CONFIG_PROC_FS
- struct proc_dir_entry *proc, *proc_exp, *proc_stat;
-#endif
- int ret = 0;
-
- if (!init) goto cleanup;
-
- ret = nf_conntrack_init();
- if (ret < 0)
- goto cleanup_nothing;
-
-#ifdef CONFIG_PROC_FS
- proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
- if (!proc) goto cleanup_init;
-
- proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
- &exp_file_ops);
- if (!proc_exp) goto cleanup_proc;
-
- proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
- if (!proc_stat)
- goto cleanup_proc_exp;
-
- proc_stat->proc_fops = &ct_cpu_seq_fops;
- proc_stat->owner = THIS_MODULE;
-#endif
-#ifdef CONFIG_SYSCTL
- nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
- if (nf_ct_sysctl_header == NULL) {
- printk("nf_conntrack: can't register to sysctl.\n");
- ret = -ENOMEM;
- goto cleanup_proc_stat;
- }
-#endif
-
- return ret;
-
- cleanup:
-#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(nf_ct_sysctl_header);
- cleanup_proc_stat:
-#endif
-#ifdef CONFIG_PROC_FS
- remove_proc_entry("nf_conntrack", proc_net_stat);
- cleanup_proc_exp:
- proc_net_remove("nf_conntrack_expect");
- cleanup_proc:
- proc_net_remove("nf_conntrack");
- cleanup_init:
-#endif /* CNFIG_PROC_FS */
- nf_conntrack_cleanup();
- cleanup_nothing:
- return ret;
-}
-
int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
{
int ret = 0;
@@ -806,18 +749,72 @@ void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto)
nf_ct_iterate_cleanup(kill_proto, proto);
}
-static int __init init(void)
+static int __init nf_conntrack_standalone_init(void)
{
- return init_or_cleanup(1);
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+#endif
+ int ret = 0;
+
+ ret = nf_conntrack_init();
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_PROC_FS
+ proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
+ if (!proc) goto cleanup_init;
+
+ proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
+ &exp_file_ops);
+ if (!proc_exp) goto cleanup_proc;
+
+ proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
+ if (!proc_stat)
+ goto cleanup_proc_exp;
+
+ proc_stat->proc_fops = &ct_cpu_seq_fops;
+ proc_stat->owner = THIS_MODULE;
+#endif
+#ifdef CONFIG_SYSCTL
+ nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
+ if (nf_ct_sysctl_header == NULL) {
+ printk("nf_conntrack: can't register to sysctl.\n");
+ ret = -ENOMEM;
+ goto cleanup_proc_stat;
+ }
+#endif
+ return ret;
+
+#ifdef CONFIG_SYSCTL
+ cleanup_proc_stat:
+#endif
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("nf_conntrack", proc_net_stat);
+ cleanup_proc_exp:
+ proc_net_remove("nf_conntrack_expect");
+ cleanup_proc:
+ proc_net_remove("nf_conntrack");
+ cleanup_init:
+#endif /* CNFIG_PROC_FS */
+ nf_conntrack_cleanup();
+ return ret;
}
-static void __exit fini(void)
+static void __exit nf_conntrack_standalone_fini(void)
{
- init_or_cleanup(0);
+#ifdef CONFIG_SYSCTL
+ unregister_sysctl_table(nf_ct_sysctl_header);
+#endif
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("nf_conntrack", proc_net_stat);
+ proc_net_remove("nf_conntrack_expect");
+ proc_net_remove("nf_conntrack");
+#endif /* CNFIG_PROC_FS */
+ nf_conntrack_cleanup();
}
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_standalone_init);
+module_exit(nf_conntrack_standalone_fini);
/* Some modules need us, but don't depend directly on any symbol.
They should call this. */
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index d9f0d7ef103..ee8f70889f4 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -17,7 +17,6 @@
* for queueing and must reinject all packets it receives, no matter what.
*/
static struct nf_queue_handler *queue_handler[NPROTO];
-static struct nf_queue_rerouter *queue_rerouter[NPROTO];
static DEFINE_RWLOCK(queue_handler_lock);
@@ -59,32 +58,6 @@ int nf_unregister_queue_handler(int pf)
}
EXPORT_SYMBOL(nf_unregister_queue_handler);
-int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer)
-{
- if (pf >= NPROTO)
- return -EINVAL;
-
- write_lock_bh(&queue_handler_lock);
- rcu_assign_pointer(queue_rerouter[pf], rer);
- write_unlock_bh(&queue_handler_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(nf_register_queue_rerouter);
-
-int nf_unregister_queue_rerouter(int pf)
-{
- if (pf >= NPROTO)
- return -EINVAL;
-
- write_lock_bh(&queue_handler_lock);
- rcu_assign_pointer(queue_rerouter[pf], NULL);
- write_unlock_bh(&queue_handler_lock);
- synchronize_rcu();
- return 0;
-}
-EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
-
void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
{
int pf;
@@ -116,7 +89,7 @@ int nf_queue(struct sk_buff **skb,
struct net_device *physindev = NULL;
struct net_device *physoutdev = NULL;
#endif
- struct nf_queue_rerouter *rerouter;
+ struct nf_afinfo *afinfo;
/* QUEUE == DROP if noone is waiting, to be safe. */
read_lock(&queue_handler_lock);
@@ -126,7 +99,14 @@ int nf_queue(struct sk_buff **skb,
return 1;
}
- info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC);
+ afinfo = nf_get_afinfo(pf);
+ if (!afinfo) {
+ read_unlock(&queue_handler_lock);
+ kfree_skb(*skb);
+ return 1;
+ }
+
+ info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC);
if (!info) {
if (net_ratelimit())
printk(KERN_ERR "OOM queueing packet %p\n",
@@ -158,10 +138,7 @@ int nf_queue(struct sk_buff **skb,
if (physoutdev) dev_hold(physoutdev);
}
#endif
- rerouter = rcu_dereference(queue_rerouter[pf]);
- if (rerouter)
- rerouter->save(*skb, info);
-
+ afinfo->saveroute(*skb, info);
status = queue_handler[pf]->outfn(*skb, info, queuenum,
queue_handler[pf]->data);
@@ -190,7 +167,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
{
struct list_head *elem = &info->elem->list;
struct list_head *i;
- struct nf_queue_rerouter *rerouter;
+ struct nf_afinfo *afinfo;
rcu_read_lock();
@@ -228,8 +205,8 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
}
if (verdict == NF_ACCEPT) {
- rerouter = rcu_dereference(queue_rerouter[info->pf]);
- if (rerouter && rerouter->reroute(&skb, info) < 0)
+ afinfo = nf_get_afinfo(info->pf);
+ if (!afinfo || afinfo->reroute(&skb, info) < 0)
verdict = NF_DROP;
}
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 54cbbaa712d..61cdda4e5d3 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -321,7 +321,7 @@ static int
nfulnl_set_flags(struct nfulnl_instance *inst, u_int16_t flags)
{
spin_lock_bh(&inst->lock);
- inst->flags = ntohs(flags);
+ inst->flags = flags;
spin_unlock_bh(&inst->lock);
return 0;
@@ -902,7 +902,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
if (nfula[NFULA_CFG_FLAGS-1]) {
u_int16_t flags =
*(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_FLAGS-1]);
- nfulnl_set_flags(inst, ntohl(flags));
+ nfulnl_set_flags(inst, ntohs(flags));
}
out_put:
@@ -1033,17 +1033,13 @@ static struct file_operations nful_file_ops = {
#endif /* PROC_FS */
-static int
-init_or_cleanup(int init)
+static int __init nfnetlink_log_init(void)
{
int i, status = -ENOMEM;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_nful;
#endif
- if (!init)
- goto cleanup;
-
for (i = 0; i < INSTANCE_BUCKETS; i++)
INIT_HLIST_HEAD(&instance_table[i]);
@@ -1066,30 +1062,25 @@ init_or_cleanup(int init)
goto cleanup_subsys;
proc_nful->proc_fops = &nful_file_ops;
#endif
-
return status;
-cleanup:
- nf_log_unregister_logger(&nfulnl_logger);
#ifdef CONFIG_PROC_FS
- remove_proc_entry("nfnetlink_log", proc_net_netfilter);
cleanup_subsys:
-#endif
nfnetlink_subsys_unregister(&nfulnl_subsys);
+#endif
cleanup_netlink_notifier:
netlink_unregister_notifier(&nfulnl_rtnl_notifier);
return status;
}
-static int __init init(void)
+static void __exit nfnetlink_log_fini(void)
{
-
- return init_or_cleanup(1);
-}
-
-static void __exit fini(void)
-{
- init_or_cleanup(0);
+ nf_log_unregister_logger(&nfulnl_logger);
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("nfnetlink_log", proc_net_netfilter);
+#endif
+ nfnetlink_subsys_unregister(&nfulnl_subsys);
+ netlink_unregister_notifier(&nfulnl_rtnl_notifier);
}
MODULE_DESCRIPTION("netfilter userspace logging");
@@ -1097,5 +1088,5 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_LICENSE("GPL");
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ULOG);
-module_init(init);
-module_exit(fini);
+module_init(nfnetlink_log_init);
+module_exit(nfnetlink_log_fini);
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index b5701662182..86a4ac33de3 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1071,17 +1071,13 @@ static struct file_operations nfqnl_file_ops = {
#endif /* PROC_FS */
-static int
-init_or_cleanup(int init)
+static int __init nfnetlink_queue_init(void)
{
int i, status = -ENOMEM;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_nfqueue;
#endif
- if (!init)
- goto cleanup;
-
for (i = 0; i < INSTANCE_BUCKETS; i++)
INIT_HLIST_HEAD(&instance_table[i]);
@@ -1101,31 +1097,26 @@ init_or_cleanup(int init)
#endif
register_netdevice_notifier(&nfqnl_dev_notifier);
-
return status;
-cleanup:
- nf_unregister_queue_handlers(&nfqh);
- unregister_netdevice_notifier(&nfqnl_dev_notifier);
#ifdef CONFIG_PROC_FS
- remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
cleanup_subsys:
-#endif
nfnetlink_subsys_unregister(&nfqnl_subsys);
+#endif
cleanup_netlink_notifier:
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
return status;
}
-static int __init init(void)
-{
-
- return init_or_cleanup(1);
-}
-
-static void __exit fini(void)
+static void __exit nfnetlink_queue_fini(void)
{
- init_or_cleanup(0);
+ nf_unregister_queue_handlers(&nfqh);
+ unregister_netdevice_notifier(&nfqnl_dev_notifier);
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
+#endif
+ nfnetlink_subsys_unregister(&nfqnl_subsys);
+ netlink_unregister_notifier(&nfqnl_rtnl_notifier);
}
MODULE_DESCRIPTION("netfilter packet queue handler");
@@ -1133,5 +1124,5 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_LICENSE("GPL");
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_QUEUE);
-module_init(init);
-module_exit(fini);
+module_init(nfnetlink_queue_init);
+module_exit(nfnetlink_queue_fini);
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index a657ab5394c..99293c63ff7 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -38,6 +38,7 @@ struct xt_af {
struct list_head match;
struct list_head target;
struct list_head tables;
+ struct mutex compat_mutex;
};
static struct xt_af *xt;
@@ -272,6 +273,54 @@ int xt_check_match(const struct xt_match *match, unsigned short family,
}
EXPORT_SYMBOL_GPL(xt_check_match);
+#ifdef CONFIG_COMPAT
+int xt_compat_match(void *match, void **dstptr, int *size, int convert)
+{
+ struct xt_match *m;
+ struct compat_xt_entry_match *pcompat_m;
+ struct xt_entry_match *pm;
+ u_int16_t msize;
+ int off, ret;
+
+ ret = 0;
+ m = ((struct xt_entry_match *)match)->u.kernel.match;
+ off = XT_ALIGN(m->matchsize) - COMPAT_XT_ALIGN(m->matchsize);
+ switch (convert) {
+ case COMPAT_TO_USER:
+ pm = (struct xt_entry_match *)match;
+ msize = pm->u.user.match_size;
+ if (copy_to_user(*dstptr, pm, msize)) {
+ ret = -EFAULT;
+ break;
+ }
+ msize -= off;
+ if (put_user(msize, (u_int16_t *)*dstptr))
+ ret = -EFAULT;
+ *size -= off;
+ *dstptr += msize;
+ break;
+ case COMPAT_FROM_USER:
+ pcompat_m = (struct compat_xt_entry_match *)match;
+ pm = (struct xt_entry_match *)*dstptr;
+ msize = pcompat_m->u.user.match_size;
+ memcpy(pm, pcompat_m, msize);
+ msize += off;
+ pm->u.user.match_size = msize;
+ *size += off;
+ *dstptr += msize;
+ break;
+ case COMPAT_CALC_SIZE:
+ *size += off;
+ break;
+ default:
+ ret = -ENOPROTOOPT;
+ break;
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(xt_compat_match);
+#endif
+
int xt_check_target(const struct xt_target *target, unsigned short family,
unsigned int size, const char *table, unsigned int hook_mask,
unsigned short proto, int inv_proto)
@@ -301,6 +350,54 @@ int xt_check_target(const struct xt_target *target, unsigned short family,
}
EXPORT_SYMBOL_GPL(xt_check_target);
+#ifdef CONFIG_COMPAT
+int xt_compat_target(void *target, void **dstptr, int *size, int convert)
+{
+ struct xt_target *t;
+ struct compat_xt_entry_target *pcompat;
+ struct xt_entry_target *pt;
+ u_int16_t tsize;
+ int off, ret;
+
+ ret = 0;
+ t = ((struct xt_entry_target *)target)->u.kernel.target;
+ off = XT_ALIGN(t->targetsize) - COMPAT_XT_ALIGN(t->targetsize);
+ switch (convert) {
+ case COMPAT_TO_USER:
+ pt = (struct xt_entry_target *)target;
+ tsize = pt->u.user.target_size;
+ if (copy_to_user(*dstptr, pt, tsize)) {
+ ret = -EFAULT;
+ break;
+ }
+ tsize -= off;
+ if (put_user(tsize, (u_int16_t *)*dstptr))
+ ret = -EFAULT;
+ *size -= off;
+ *dstptr += tsize;
+ break;
+ case COMPAT_FROM_USER:
+ pcompat = (struct compat_xt_entry_target *)target;
+ pt = (struct xt_entry_target *)*dstptr;
+ tsize = pcompat->u.user.target_size;
+ memcpy(pt, pcompat, tsize);
+ tsize += off;
+ pt->u.user.target_size = tsize;
+ *size += off;
+ *dstptr += tsize;
+ break;
+ case COMPAT_CALC_SIZE:
+ *size += off;
+ break;
+ default:
+ ret = -ENOPROTOOPT;
+ break;
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(xt_compat_target);
+#endif
+
struct xt_table_info *xt_alloc_table_info(unsigned int size)
{
struct xt_table_info *newinfo;
@@ -316,7 +413,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
newinfo->size = size;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (size <= PAGE_SIZE)
newinfo->entries[cpu] = kmalloc_node(size,
GFP_KERNEL,
@@ -339,7 +436,7 @@ void xt_free_table_info(struct xt_table_info *info)
{
int cpu;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (info->size <= PAGE_SIZE)
kfree(info->entries[cpu]);
else
@@ -371,6 +468,19 @@ void xt_table_unlock(struct xt_table *table)
}
EXPORT_SYMBOL_GPL(xt_table_unlock);
+#ifdef CONFIG_COMPAT
+void xt_compat_lock(int af)
+{
+ mutex_lock(&xt[af].compat_mutex);
+}
+EXPORT_SYMBOL_GPL(xt_compat_lock);
+
+void xt_compat_unlock(int af)
+{
+ mutex_unlock(&xt[af].compat_mutex);
+}
+EXPORT_SYMBOL_GPL(xt_compat_unlock);
+#endif
struct xt_table_info *
xt_replace_table(struct xt_table *table,
@@ -419,6 +529,7 @@ int xt_register_table(struct xt_table *table,
/* Simplifies replace_table code. */
table->private = bootstrap;
+ rwlock_init(&table->lock);
if (!xt_replace_table(table, 0, newinfo, &ret))
goto unlock;
@@ -428,7 +539,6 @@ int xt_register_table(struct xt_table *table,
/* save number of initial entries */
private->initial_entries = private->number;
- rwlock_init(&table->lock);
list_prepend(&xt[table->af].tables, table);
ret = 0;
@@ -671,6 +781,9 @@ static int __init xt_init(void)
for (i = 0; i < NPROTO; i++) {
mutex_init(&xt[i].mutex);
+#ifdef CONFIG_COMPAT
+ mutex_init(&xt[i].compat_mutex);
+#endif
INIT_LIST_HEAD(&xt[i].target);
INIT_LIST_HEAD(&xt[i].match);
INIT_LIST_HEAD(&xt[i].tables);
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 3cd2ac90a25..e54e5773001 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -62,7 +62,7 @@ static struct xt_target classify6_reg = {
};
-static int __init init(void)
+static int __init xt_classify_init(void)
{
int ret;
@@ -77,11 +77,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_classify_fini(void)
{
xt_unregister_target(&classify_reg);
xt_unregister_target(&classify6_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_classify_init);
+module_exit(xt_classify_fini);
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 35448b8e688..60c375d36f0 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -115,7 +115,7 @@ static struct xt_target connmark6_reg = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_connmark_init(void)
{
int ret;
@@ -132,11 +132,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_connmark_fini(void)
{
xt_unregister_target(&connmark_reg);
xt_unregister_target(&connmark6_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_connmark_init);
+module_exit(xt_connmark_fini);
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index 73bdd5c80e1..ee9c34edc76 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -145,7 +145,7 @@ static struct xt_target ip6t_mark_reg_v0 = {
.revision = 0,
};
-static int __init init(void)
+static int __init xt_mark_init(void)
{
int err;
@@ -166,12 +166,12 @@ static int __init init(void)
return err;
}
-static void __exit fini(void)
+static void __exit xt_mark_fini(void)
{
xt_unregister_target(&ipt_mark_reg_v0);
xt_unregister_target(&ipt_mark_reg_v1);
xt_unregister_target(&ip6t_mark_reg_v0);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_mark_init);
+module_exit(xt_mark_fini);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 2873e1c60f6..86ccceb61fd 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -61,7 +61,7 @@ static struct xt_target arpt_NFQ_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_nfqueue_init(void)
{
int ret;
ret = xt_register_target(&ipt_NFQ_reg);
@@ -83,12 +83,12 @@ out_ip:
return ret;
}
-static void __exit fini(void)
+static void __exit xt_nfqueue_fini(void)
{
xt_unregister_target(&arpt_NFQ_reg);
xt_unregister_target(&ip6t_NFQ_reg);
xt_unregister_target(&ipt_NFQ_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_nfqueue_init);
+module_exit(xt_nfqueue_fini);
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index cf2ebd76fd6..98f4b5363ce 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -52,7 +52,7 @@ static struct xt_target notrack6_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_notrack_init(void)
{
int ret;
@@ -67,11 +67,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_notrack_fini(void)
{
xt_unregister_target(&notrack6_reg);
xt_unregister_target(&notrack_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_notrack_init);
+module_exit(xt_notrack_fini);
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
index 2637724b498..197609cb06d 100644
--- a/net/netfilter/xt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -45,7 +45,7 @@ static struct xt_match comment6_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_comment_init(void)
{
int ret;
@@ -60,11 +60,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_comment_fini(void)
{
xt_unregister_match(&comment_match);
xt_unregister_match(&comment6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_comment_init);
+module_exit(xt_comment_fini);
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 4985f5ec58c..1396fe2d07c 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -160,7 +160,7 @@ static struct xt_match connbytes6_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_connbytes_init(void)
{
int ret;
ret = xt_register_match(&connbytes_match);
@@ -173,11 +173,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_connbytes_fini(void)
{
xt_unregister_match(&connbytes_match);
xt_unregister_match(&connbytes6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_connbytes_init);
+module_exit(xt_connbytes_fini);
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 7b16f1ee16b..dc26a27cbca 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -102,7 +102,7 @@ static struct xt_match connmark6_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_connmark_init(void)
{
int ret;
@@ -118,11 +118,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_connmark_fini(void)
{
xt_unregister_match(&connmark6_match);
xt_unregister_match(&connmark_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_connmark_init);
+module_exit(xt_connmark_fini);
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 65a84809fd3..145489a4c3f 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -239,7 +239,7 @@ static struct xt_match conntrack_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_conntrack_init(void)
{
int ret;
need_conntrack();
@@ -248,10 +248,10 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_conntrack_fini(void)
{
xt_unregister_match(&conntrack_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_conntrack_init);
+module_exit(xt_conntrack_fini);
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 2f331decd15..dfb10b648e5 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -164,7 +164,7 @@ static struct xt_match dccp6_match =
};
-static int __init init(void)
+static int __init xt_dccp_init(void)
{
int ret;
@@ -191,12 +191,12 @@ out_kfree:
return ret;
}
-static void __exit fini(void)
+static void __exit xt_dccp_fini(void)
{
xt_unregister_match(&dccp6_match);
xt_unregister_match(&dccp_match);
kfree(dccp_optbuf);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_dccp_init);
+module_exit(xt_dccp_fini);
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/netfilter/xt_esp.c
index af0d5ec79cb..9dad6281e0c 100644
--- a/net/ipv4/netfilter/ipt_esp.c
+++ b/net/netfilter/xt_esp.c
@@ -9,16 +9,22 @@
#include <linux/module.h>
#include <linux/skbuff.h>
+#include <linux/in.h>
#include <linux/ip.h>
-#include <linux/netfilter_ipv4/ipt_esp.h>
+#include <linux/netfilter/xt_esp.h>
+#include <linux/netfilter/x_tables.h>
+
#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>");
-MODULE_DESCRIPTION("iptables ESP SPI match module");
+MODULE_DESCRIPTION("x_tables ESP SPI match module");
+MODULE_ALIAS("ipt_esp");
+MODULE_ALIAS("ip6t_esp");
-#ifdef DEBUG_CONNTRACK
+#if 0
#define duprintf(format, args...) printk(format , ## args)
#else
#define duprintf(format, args...)
@@ -28,11 +34,11 @@ MODULE_DESCRIPTION("iptables ESP SPI match module");
static inline int
spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
{
- int r=0;
- duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
- min,spi,max);
- r=(spi >= min && spi <= max) ^ invert;
- duprintf(" result %s\n",r? "PASS" : "FAILED");
+ int r = 0;
+ duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
+ min, spi, max);
+ r = (spi >= min && spi <= max) ^ invert;
+ duprintf(" result %s\n", r ? "PASS" : "FAILED");
return r;
}
@@ -47,14 +53,13 @@ match(const struct sk_buff *skb,
int *hotdrop)
{
struct ip_esp_hdr _esp, *eh;
- const struct ipt_esp *espinfo = matchinfo;
+ const struct xt_esp *espinfo = matchinfo;
/* Must not be a fragment. */
if (offset)
return 0;
- eh = skb_header_pointer(skb, protoff,
- sizeof(_esp), &_esp);
+ eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp);
if (eh == NULL) {
/* We've been asked to examine this packet, and we
* can't. Hence, no choice but to drop.
@@ -64,9 +69,8 @@ match(const struct sk_buff *skb,
return 0;
}
- return spi_match(espinfo->spis[0], espinfo->spis[1],
- ntohl(eh->spi),
- !!(espinfo->invflags & IPT_ESP_INV_SPI));
+ return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi),
+ !!(espinfo->invflags & XT_ESP_INV_SPI));
}
/* Called when user tries to insert an entry of this type. */
@@ -78,34 +82,55 @@ checkentry(const char *tablename,
unsigned int matchinfosize,
unsigned int hook_mask)
{
- const struct ipt_esp *espinfo = matchinfo;
+ const struct xt_esp *espinfo = matchinfo;
- /* Must specify no unknown invflags */
- if (espinfo->invflags & ~IPT_ESP_INV_MASK) {
- duprintf("ipt_esp: unknown flags %X\n", espinfo->invflags);
+ if (espinfo->invflags & ~XT_ESP_INV_MASK) {
+ duprintf("xt_esp: unknown flags %X\n", espinfo->invflags);
return 0;
}
+
return 1;
}
-static struct ipt_match esp_match = {
+static struct xt_match esp_match = {
.name = "esp",
- .match = match,
- .matchsize = sizeof(struct ipt_esp),
+ .family = AF_INET,
.proto = IPPROTO_ESP,
- .checkentry = checkentry,
+ .match = &match,
+ .matchsize = sizeof(struct xt_esp),
+ .checkentry = &checkentry,
.me = THIS_MODULE,
};
-static int __init init(void)
+static struct xt_match esp6_match = {
+ .name = "esp",
+ .family = AF_INET6,
+ .proto = IPPROTO_ESP,
+ .match = &match,
+ .matchsize = sizeof(struct xt_esp),
+ .checkentry = &checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init xt_esp_init(void)
{
- return ipt_register_match(&esp_match);
+ int ret;
+ ret = xt_register_match(&esp_match);
+ if (ret)
+ return ret;
+
+ ret = xt_register_match(&esp6_match);
+ if (ret)
+ xt_unregister_match(&esp_match);
+
+ return ret;
}
-static void __exit cleanup(void)
+static void __exit xt_esp_cleanup(void)
{
- ipt_unregister_match(&esp_match);
+ xt_unregister_match(&esp_match);
+ xt_unregister_match(&esp6_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(xt_esp_init);
+module_exit(xt_esp_cleanup);
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index 101f0005e98..799c2a43e3b 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -182,7 +182,7 @@ static struct xt_match helper6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_helper_init(void)
{
int ret;
need_conntrack();
@@ -198,12 +198,12 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_helper_fini(void)
{
xt_unregister_match(&helper_match);
xt_unregister_match(&helper6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_helper_init);
+module_exit(xt_helper_fini);
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index 38560caef75..109132c9a14 100644
--- a/net/netfilter/xt_length.c
+++ b/net/netfilter/xt_length.c
@@ -68,7 +68,7 @@ static struct xt_match length6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_length_init(void)
{
int ret;
ret = xt_register_match(&length_match);
@@ -81,11 +81,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_length_fini(void)
{
xt_unregister_match(&length_match);
xt_unregister_match(&length6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_length_init);
+module_exit(xt_length_fini);
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index e91c1a444e7..ce7fdb7e4e0 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -153,7 +153,7 @@ static struct xt_match limit6_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_limit_init(void)
{
int ret;
@@ -168,11 +168,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_limit_fini(void)
{
xt_unregister_match(&ipt_limit_reg);
xt_unregister_match(&limit6_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_limit_init);
+module_exit(xt_limit_fini);
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index f4defa28a6e..356290ffe38 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -62,7 +62,7 @@ static struct xt_match mac6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_mac_init(void)
{
int ret;
ret = xt_register_match(&mac_match);
@@ -76,11 +76,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_mac_fini(void)
{
xt_unregister_match(&mac_match);
xt_unregister_match(&mac6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_mac_init);
+module_exit(xt_mac_fini);
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index ce0badfeef9..8b385a34886 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -69,7 +69,7 @@ static struct xt_match mark6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_mark_init(void)
{
int ret;
ret = xt_register_match(&mark_match);
@@ -83,11 +83,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_mark_fini(void)
{
xt_unregister_match(&mark_match);
xt_unregister_match(&mark6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_mark_init);
+module_exit(xt_mark_fini);
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
new file mode 100644
index 00000000000..b56cd2baaac
--- /dev/null
+++ b/net/netfilter/xt_multiport.c
@@ -0,0 +1,314 @@
+/* Kernel module to match one of a list of TCP/UDP ports: ports are in
+ the same place so we can treat them as equal. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+
+#include <linux/netfilter/xt_multiport.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
+MODULE_DESCRIPTION("x_tables multiple port match module");
+MODULE_ALIAS("ipt_multiport");
+MODULE_ALIAS("ip6t_multiport");
+
+#if 0
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+/* Returns 1 if the port is matched by the test, 0 otherwise. */
+static inline int
+ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags,
+ u_int8_t count, u_int16_t src, u_int16_t dst)
+{
+ unsigned int i;
+ for (i = 0; i < count; i++) {
+ if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src)
+ return 1;
+
+ if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Returns 1 if the port is matched by the test, 0 otherwise. */
+static inline int
+ports_match_v1(const struct xt_multiport_v1 *minfo,
+ u_int16_t src, u_int16_t dst)
+{
+ unsigned int i;
+ u_int16_t s, e;
+
+ for (i = 0; i < minfo->count; i++) {
+ s = minfo->ports[i];
+
+ if (minfo->pflags[i]) {
+ /* range port matching */
+ e = minfo->ports[++i];
+ duprintf("src or dst matches with %d-%d?\n", s, e);
+
+ if (minfo->flags == XT_MULTIPORT_SOURCE
+ && src >= s && src <= e)
+ return 1 ^ minfo->invert;
+ if (minfo->flags == XT_MULTIPORT_DESTINATION
+ && dst >= s && dst <= e)
+ return 1 ^ minfo->invert;
+ if (minfo->flags == XT_MULTIPORT_EITHER
+ && ((dst >= s && dst <= e)
+ || (src >= s && src <= e)))
+ return 1 ^ minfo->invert;
+ } else {
+ /* exact port matching */
+ duprintf("src or dst matches with %d?\n", s);
+
+ if (minfo->flags == XT_MULTIPORT_SOURCE
+ && src == s)
+ return 1 ^ minfo->invert;
+ if (minfo->flags == XT_MULTIPORT_DESTINATION
+ && dst == s)
+ return 1 ^ minfo->invert;
+ if (minfo->flags == XT_MULTIPORT_EITHER
+ && (src == s || dst == s))
+ return 1 ^ minfo->invert;
+ }
+ }
+
+ return minfo->invert;
+}
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ int *hotdrop)
+{
+ u16 _ports[2], *pptr;
+ const struct xt_multiport *multiinfo = matchinfo;
+
+ if (offset)
+ return 0;
+
+ pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
+ if (pptr == NULL) {
+ /* We've been asked to examine this packet, and we
+ * can't. Hence, no choice but to drop.
+ */
+ duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
+ *hotdrop = 1;
+ return 0;
+ }
+
+ return ports_match(multiinfo->ports,
+ multiinfo->flags, multiinfo->count,
+ ntohs(pptr[0]), ntohs(pptr[1]));
+}
+
+static int
+match_v1(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ int *hotdrop)
+{
+ u16 _ports[2], *pptr;
+ const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+ if (offset)
+ return 0;
+
+ pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
+ if (pptr == NULL) {
+ /* We've been asked to examine this packet, and we
+ * can't. Hence, no choice but to drop.
+ */
+ duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
+ *hotdrop = 1;
+ return 0;
+ }
+
+ return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
+}
+
+static inline int
+check(u_int16_t proto,
+ u_int8_t ip_invflags,
+ u_int8_t match_flags,
+ u_int8_t count)
+{
+ /* Must specify proto == TCP/UDP, no unknown flags or bad count */
+ return (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
+ && !(ip_invflags & XT_INV_PROTO)
+ && (match_flags == XT_MULTIPORT_SOURCE
+ || match_flags == XT_MULTIPORT_DESTINATION
+ || match_flags == XT_MULTIPORT_EITHER)
+ && count <= XT_MULTI_PORTS;
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+checkentry(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ipt_ip *ip = info;
+ const struct xt_multiport *multiinfo = matchinfo;
+
+ return check(ip->proto, ip->invflags, multiinfo->flags,
+ multiinfo->count);
+}
+
+static int
+checkentry_v1(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ipt_ip *ip = info;
+ const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+ return check(ip->proto, ip->invflags, multiinfo->flags,
+ multiinfo->count);
+}
+
+static int
+checkentry6(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ip6t_ip6 *ip = info;
+ const struct xt_multiport *multiinfo = matchinfo;
+
+ return check(ip->proto, ip->invflags, multiinfo->flags,
+ multiinfo->count);
+}
+
+static int
+checkentry6_v1(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ip6t_ip6 *ip = info;
+ const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+ return check(ip->proto, ip->invflags, multiinfo->flags,
+ multiinfo->count);
+}
+
+static struct xt_match multiport_match = {
+ .name = "multiport",
+ .revision = 0,
+ .matchsize = sizeof(struct xt_multiport),
+ .match = &match,
+ .checkentry = &checkentry,
+ .family = AF_INET,
+ .me = THIS_MODULE,
+};
+
+static struct xt_match multiport_match_v1 = {
+ .name = "multiport",
+ .revision = 1,
+ .matchsize = sizeof(struct xt_multiport_v1),
+ .match = &match_v1,
+ .checkentry = &checkentry_v1,
+ .family = AF_INET,
+ .me = THIS_MODULE,
+};
+
+static struct xt_match multiport6_match = {
+ .name = "multiport",
+ .revision = 0,
+ .matchsize = sizeof(struct xt_multiport),
+ .match = &match,
+ .checkentry = &checkentry6,
+ .family = AF_INET6,
+ .me = THIS_MODULE,
+};
+
+static struct xt_match multiport6_match_v1 = {
+ .name = "multiport",
+ .revision = 1,
+ .matchsize = sizeof(struct xt_multiport_v1),
+ .match = &match_v1,
+ .checkentry = &checkentry6_v1,
+ .family = AF_INET6,
+ .me = THIS_MODULE,
+};
+
+static int __init xt_multiport_init(void)
+{
+ int ret;
+
+ ret = xt_register_match(&multiport_match);
+ if (ret)
+ goto out;
+
+ ret = xt_register_match(&multiport_match_v1);
+ if (ret)
+ goto out_unreg_multi_v0;
+
+ ret = xt_register_match(&multiport6_match);
+ if (ret)
+ goto out_unreg_multi_v1;
+
+ ret = xt_register_match(&multiport6_match_v1);
+ if (ret)
+ goto out_unreg_multi6_v0;
+
+ return ret;
+
+out_unreg_multi6_v0:
+ xt_unregister_match(&multiport6_match);
+out_unreg_multi_v1:
+ xt_unregister_match(&multiport_match_v1);
+out_unreg_multi_v0:
+ xt_unregister_match(&multiport_match);
+out:
+ return ret;
+}
+
+static void __exit xt_multiport_fini(void)
+{
+ xt_unregister_match(&multiport_match);
+ xt_unregister_match(&multiport_match_v1);
+ xt_unregister_match(&multiport6_match);
+ xt_unregister_match(&multiport6_match_v1);
+}
+
+module_init(xt_multiport_init);
+module_exit(xt_multiport_fini);
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 089f4f7e863..5fe4c9df17f 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -134,7 +134,7 @@ static struct xt_match physdev6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_physdev_init(void)
{
int ret;
@@ -149,11 +149,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_physdev_fini(void)
{
xt_unregister_match(&physdev_match);
xt_unregister_match(&physdev6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_physdev_init);
+module_exit(xt_physdev_fini);
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index 8b8bca988ac..3ac703b5cb8 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -49,7 +49,7 @@ static struct xt_match pkttype6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_pkttype_init(void)
{
int ret;
ret = xt_register_match(&pkttype_match);
@@ -63,11 +63,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_pkttype_fini(void)
{
xt_unregister_match(&pkttype_match);
xt_unregister_match(&pkttype6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_pkttype_init);
+module_exit(xt_pkttype_fini);
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 1099cb005fc..a3aa62fbda6 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -71,7 +71,7 @@ match_policy_in(const struct sk_buff *skb, const struct xt_policy_info *info,
return 0;
e = &info->pol[pos];
- if (match_xfrm_state(sp->x[i].xvec, e, family)) {
+ if (match_xfrm_state(sp->xvec[i], e, family)) {
if (!strict)
return 1;
} else if (strict)
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index 5e31a4a835b..a80b7d132b6 100644
--- a/net/netfilter/xt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -49,15 +49,15 @@ static struct xt_match realm_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_realm_init(void)
{
return xt_register_match(&realm_match);
}
-static void __exit fini(void)
+static void __exit xt_realm_fini(void)
{
xt_unregister_match(&realm_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_realm_init);
+module_exit(xt_realm_fini);
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index c6eb24a2fe1..34bd87259a0 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -200,7 +200,7 @@ static struct xt_match sctp6_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_sctp_init(void)
{
int ret;
ret = xt_register_match(&sctp_match);
@@ -214,11 +214,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_sctp_fini(void)
{
xt_unregister_match(&sctp6_match);
xt_unregister_match(&sctp_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_sctp_init);
+module_exit(xt_sctp_fini);
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index e6c0be9d94d..f9e304dc450 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -89,7 +89,7 @@ static struct xt_match state6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_state_init(void)
{
int ret;
@@ -106,11 +106,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_state_fini(void)
{
xt_unregister_match(&state_match);
xt_unregister_match(&state6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_state_init);
+module_exit(xt_state_fini);
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 703d80fccac..79d9ea6964b 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -91,7 +91,7 @@ static struct xt_match string6_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_string_init(void)
{
int ret;
@@ -105,11 +105,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_string_fini(void)
{
xt_unregister_match(&string_match);
xt_unregister_match(&string6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_string_init);
+module_exit(xt_string_fini);
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 70a8858ae3f..cf7d335cadc 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -112,7 +112,7 @@ static struct xt_match tcpmss6_match = {
};
-static int __init init(void)
+static int __init xt_tcpmss_init(void)
{
int ret;
ret = xt_register_match(&tcpmss_match);
@@ -126,11 +126,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_tcpmss_fini(void)
{
xt_unregister_match(&tcpmss6_match);
xt_unregister_match(&tcpmss_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_tcpmss_init);
+module_exit(xt_tcpmss_fini);
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 14a990eb666..1b61dac9c87 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -238,7 +238,7 @@ static struct xt_match udp6_matchstruct = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_tcpudp_init(void)
{
int ret;
ret = xt_register_match(&tcp_matchstruct);
@@ -268,7 +268,7 @@ out_unreg_tcp:
return ret;
}
-static void __exit fini(void)
+static void __exit xt_tcpudp_fini(void)
{
xt_unregister_match(&udp6_matchstruct);
xt_unregister_match(&udp_matchstruct);
@@ -276,5 +276,5 @@ static void __exit fini(void)
xt_unregister_match(&tcp_matchstruct);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_tcpudp_init);
+module_exit(xt_tcpudp_fini);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index d00a9034cb5..3862e73d14d 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -56,12 +56,12 @@
#include <linux/mm.h>
#include <linux/types.h>
#include <linux/audit.h>
+#include <linux/selinux.h>
#include <net/sock.h>
#include <net/scm.h>
#include <net/netlink.h>
-#define Nprintk(a...)
#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)
struct netlink_sock {
@@ -123,7 +123,7 @@ static void netlink_destroy_callback(struct netlink_callback *cb);
static DEFINE_RWLOCK(nl_table_lock);
static atomic_t nl_table_users = ATOMIC_INIT(0);
-static struct notifier_block *netlink_chain;
+static ATOMIC_NOTIFIER_HEAD(netlink_chain);
static u32 netlink_group_mask(u32 group)
{
@@ -469,7 +469,8 @@ static int netlink_release(struct socket *sock)
.protocol = sk->sk_protocol,
.pid = nlk->pid,
};
- notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n);
+ atomic_notifier_call_chain(&netlink_chain,
+ NETLINK_URELEASE, &n);
}
if (nlk->module)
@@ -1156,6 +1157,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
NETLINK_CB(skb).dst_pid = dst_pid;
NETLINK_CB(skb).dst_group = dst_group;
NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
+ selinux_get_task_sid(current, &(NETLINK_CB(skb).sid));
memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
/* What can I do? Netlink is asynchronous, so that
@@ -1695,12 +1697,12 @@ static struct file_operations netlink_seq_fops = {
int netlink_register_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&netlink_chain, nb);
+ return atomic_notifier_chain_register(&netlink_chain, nb);
}
int netlink_unregister_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&netlink_chain, nb);
+ return atomic_notifier_chain_unregister(&netlink_chain, nb);
}
static const struct proto_ops netlink_ops = {
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index d44981f5a61..3669cb953e6 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -425,11 +425,16 @@ static int nr_create(struct socket *sock, int protocol)
nr_init_timers(sk);
- nr->t1 = sysctl_netrom_transport_timeout;
- nr->t2 = sysctl_netrom_transport_acknowledge_delay;
- nr->n2 = sysctl_netrom_transport_maximum_tries;
- nr->t4 = sysctl_netrom_transport_busy_delay;
- nr->idle = sysctl_netrom_transport_no_activity_timeout;
+ nr->t1 =
+ msecs_to_jiffies(sysctl_netrom_transport_timeout);
+ nr->t2 =
+ msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay);
+ nr->n2 =
+ msecs_to_jiffies(sysctl_netrom_transport_maximum_tries);
+ nr->t4 =
+ msecs_to_jiffies(sysctl_netrom_transport_busy_delay);
+ nr->idle =
+ msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout);
nr->window = sysctl_netrom_transport_requested_window_size;
nr->bpqext = 1;
@@ -1365,8 +1370,6 @@ static struct notifier_block nr_dev_notifier = {
static struct net_device **dev_nr;
-static char banner[] __initdata = KERN_INFO "G4KLX NET/ROM for Linux. Version 0.7 for AX25.037 Linux 2.4\n";
-
static int __init nr_proto_init(void)
{
int i;
@@ -1414,7 +1417,6 @@ static int __init nr_proto_init(void)
}
register_netdevice_notifier(&nr_dev_notifier);
- printk(banner);
ax25_protocol_register(AX25_P_NETROM, nr_route_frame);
ax25_linkfail_register(nr_link_failed);
diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c
index 509afddae56..621e5586ab0 100644
--- a/net/netrom/nr_dev.c
+++ b/net/netrom/nr_dev.c
@@ -185,7 +185,6 @@ static struct net_device_stats *nr_get_stats(struct net_device *dev)
void nr_setup(struct net_device *dev)
{
- SET_MODULE_OWNER(dev);
dev->mtu = NR_MAX_PACKET_SIZE;
dev->hard_start_xmit = nr_xmit;
dev->open = nr_open;
diff --git a/net/nonet.c b/net/nonet.c
index 1230f0ae832..92e76640c7c 100644
--- a/net/nonet.c
+++ b/net/nonet.c
@@ -19,7 +19,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
return -ENXIO;
}
-struct file_operations bad_sock_fops = {
+const struct file_operations bad_sock_fops = {
.owner = THIS_MODULE,
.open = sock_no_open,
};
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index ea65396d161..55564efccf1 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -518,11 +518,11 @@ static int rose_create(struct socket *sock, int protocol)
init_timer(&rose->timer);
init_timer(&rose->idletimer);
- rose->t1 = sysctl_rose_call_request_timeout;
- rose->t2 = sysctl_rose_reset_request_timeout;
- rose->t3 = sysctl_rose_clear_request_timeout;
- rose->hb = sysctl_rose_ack_hold_back_timeout;
- rose->idle = sysctl_rose_no_activity_timeout;
+ rose->t1 = msecs_to_jiffies(sysctl_rose_call_request_timeout);
+ rose->t2 = msecs_to_jiffies(sysctl_rose_reset_request_timeout);
+ rose->t3 = msecs_to_jiffies(sysctl_rose_clear_request_timeout);
+ rose->hb = msecs_to_jiffies(sysctl_rose_ack_hold_back_timeout);
+ rose->idle = msecs_to_jiffies(sysctl_rose_no_activity_timeout);
rose->state = ROSE_STATE_0;
@@ -1469,8 +1469,6 @@ static struct notifier_block rose_dev_notifier = {
static struct net_device **dev_rose;
-static const char banner[] = KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62 for AX25.037 Linux 2.4\n";
-
static int __init rose_proto_init(void)
{
int i;
@@ -1519,7 +1517,6 @@ static int __init rose_proto_init(void)
sock_register(&rose_family_ops);
register_netdevice_notifier(&rose_dev_notifier);
- printk(banner);
ax25_protocol_register(AX25_P_ROSE, rose_route_frame);
ax25_linkfail_register(rose_link_failed);
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c
index d297af737d1..2a1bf8e119e 100644
--- a/net/rose/rose_dev.c
+++ b/net/rose/rose_dev.c
@@ -135,7 +135,6 @@ static struct net_device_stats *rose_get_stats(struct net_device *dev)
void rose_setup(struct net_device *dev)
{
- SET_MODULE_OWNER(dev);
dev->mtu = ROSE_MAX_PACKET_SIZE - 2;
dev->hard_start_xmit = rose_xmit;
dev->open = rose_open;
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c
index 09e9e9d04d9..bd86a63960c 100644
--- a/net/rose/rose_link.c
+++ b/net/rose/rose_link.c
@@ -40,7 +40,8 @@ void rose_start_ftimer(struct rose_neigh *neigh)
neigh->ftimer.data = (unsigned long)neigh;
neigh->ftimer.function = &rose_ftimer_expiry;
- neigh->ftimer.expires = jiffies + sysctl_rose_link_fail_timeout;
+ neigh->ftimer.expires =
+ jiffies + msecs_to_jiffies(sysctl_rose_link_fail_timeout);
add_timer(&neigh->ftimer);
}
@@ -51,7 +52,8 @@ static void rose_start_t0timer(struct rose_neigh *neigh)
neigh->t0timer.data = (unsigned long)neigh;
neigh->t0timer.function = &rose_t0timer_expiry;
- neigh->t0timer.expires = jiffies + sysctl_rose_restart_request_timeout;
+ neigh->t0timer.expires =
+ jiffies + msecs_to_jiffies(sysctl_rose_restart_request_timeout);
add_timer(&neigh->t0timer);
}
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 8631b65a731..a22542fa1bc 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -48,8 +48,6 @@ static DEFINE_SPINLOCK(rose_route_list_lock);
struct rose_neigh *rose_loopback_neigh;
-static void rose_remove_neigh(struct rose_neigh *);
-
/*
* Add a new route to a node, and in the process add the node and the
* neighbour if it is new.
@@ -235,11 +233,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
skb_queue_purge(&rose_neigh->queue);
- spin_lock_bh(&rose_neigh_list_lock);
-
if ((s = rose_neigh_list) == rose_neigh) {
rose_neigh_list = rose_neigh->next;
- spin_unlock_bh(&rose_neigh_list_lock);
kfree(rose_neigh->digipeat);
kfree(rose_neigh);
return;
@@ -248,7 +243,6 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
while (s != NULL && s->next != NULL) {
if (s->next == rose_neigh) {
s->next = rose_neigh->next;
- spin_unlock_bh(&rose_neigh_list_lock);
kfree(rose_neigh->digipeat);
kfree(rose_neigh);
return;
@@ -256,7 +250,6 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
s = s->next;
}
- spin_unlock_bh(&rose_neigh_list_lock);
}
/*
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 6056d20ef42..37640c6fc01 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -69,6 +69,11 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
DPRINTK("ipt_init_target: found %s\n", target->name);
t->u.kernel.target = target;
+ ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
+ table, hook, 0, 0);
+ if (ret)
+ return ret;
+
if (t->u.kernel.target->checkentry
&& !t->u.kernel.target->checkentry(table, NULL,
t->u.kernel.target, t->data,
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index fa877f8f652..24c348fa892 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -66,7 +66,7 @@ static __inline__ struct tcf_police * tcf_police_lookup(u32 index)
}
#ifdef CONFIG_NET_CLS_ACT
-static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
+static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
int type, struct tc_action *a)
{
struct tcf_police *p;
@@ -113,7 +113,7 @@ rtattr_failure:
}
static inline int
-tcf_hash_search(struct tc_action *a, u32 index)
+tcf_act_police_hash_search(struct tc_action *a, u32 index)
{
struct tcf_police *p = tcf_police_lookup(index);
@@ -387,9 +387,9 @@ static struct tc_action_ops act_police_ops = {
.act = tcf_act_police,
.dump = tcf_act_police_dump,
.cleanup = tcf_act_police_cleanup,
- .lookup = tcf_hash_search,
+ .lookup = tcf_act_police_hash_search,
.init = tcf_act_police_locate,
- .walk = tcf_generic_walker
+ .walk = tcf_act_police_walker
};
static int __init
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 31eb83717c2..138ea92ed26 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -193,8 +193,10 @@ static void dev_watchdog(unsigned long arg)
netif_running(dev) &&
netif_carrier_ok(dev)) {
if (netif_queue_stopped(dev) &&
- (jiffies - dev->trans_start) > dev->watchdog_timeo) {
- printk(KERN_INFO "NETDEV WATCHDOG: %s: transmit timed out\n", dev->name);
+ time_after(jiffies, dev->trans_start + dev->watchdog_timeo)) {
+
+ printk(KERN_INFO "NETDEV WATCHDOG: %s: transmit timed out\n",
+ dev->name);
dev->tx_timeout(dev);
}
if (!mod_timer(&dev->watchdog_timer, jiffies + dev->watchdog_timeo))
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 91132f6871d..f1c7bd29f2c 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -974,10 +974,10 @@ hfsc_adjust_levels(struct hfsc_class *cl)
do {
level = 0;
list_for_each_entry(p, &cl->children, siblings) {
- if (p->level > level)
- level = p->level;
+ if (p->level >= level)
+ level = p->level + 1;
}
- cl->level = level + 1;
+ cl->level = level;
} while ((cl = cl->cl_parent) != NULL);
}
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 7228d30512c..5a4a4d0ae50 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -167,7 +167,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
if (count == 0) {
sch->qstats.drops++;
kfree_skb(skb);
- return NET_XMIT_DROP;
+ return NET_XMIT_BYPASS;
}
/*
diff --git a/net/sctp/input.c b/net/sctp/input.c
index d117ebc75cf..1662f9cc869 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -73,6 +73,8 @@ static struct sctp_association *__sctp_lookup_association(
const union sctp_addr *peer,
struct sctp_transport **pt);
+static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb);
+
/* Calculate the SCTP checksum of an SCTP packet. */
static inline int sctp_rcv_checksum(struct sk_buff *skb)
@@ -186,7 +188,6 @@ int sctp_rcv(struct sk_buff *skb)
*/
if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb)))
{
- sock_put(sk);
if (asoc) {
sctp_association_put(asoc);
asoc = NULL;
@@ -197,7 +198,6 @@ int sctp_rcv(struct sk_buff *skb)
sk = sctp_get_ctl_sock();
ep = sctp_sk(sk)->ep;
sctp_endpoint_hold(ep);
- sock_hold(sk);
rcvr = &ep->base;
}
@@ -253,25 +253,18 @@ int sctp_rcv(struct sk_buff *skb)
*/
sctp_bh_lock_sock(sk);
- /* It is possible that the association could have moved to a different
- * socket if it is peeled off. If so, update the sk.
- */
- if (sk != rcvr->sk) {
- sctp_bh_lock_sock(rcvr->sk);
- sctp_bh_unlock_sock(sk);
- sk = rcvr->sk;
- }
-
if (sock_owned_by_user(sk))
- sk_add_backlog(sk, skb);
+ sctp_add_backlog(sk, skb);
else
- sctp_backlog_rcv(sk, skb);
+ sctp_inq_push(&chunk->rcvr->inqueue, chunk);
- /* Release the sock and the sock ref we took in the lookup calls.
- * The asoc/ep ref will be released in sctp_backlog_rcv.
- */
sctp_bh_unlock_sock(sk);
- sock_put(sk);
+
+ /* Release the asoc/ep ref we took in the lookup calls. */
+ if (asoc)
+ sctp_association_put(asoc);
+ else
+ sctp_endpoint_put(ep);
return 0;
@@ -280,8 +273,7 @@ discard_it:
return 0;
discard_release:
- /* Release any structures we may be holding. */
- sock_put(sk);
+ /* Release the asoc/ep ref we took in the lookup calls. */
if (asoc)
sctp_association_put(asoc);
else
@@ -290,56 +282,87 @@ discard_release:
goto discard_it;
}
-/* Handle second half of inbound skb processing. If the sock was busy,
- * we may have need to delay processing until later when the sock is
- * released (on the backlog). If not busy, we call this routine
- * directly from the bottom half.
+/* Process the backlog queue of the socket. Every skb on
+ * the backlog holds a ref on an association or endpoint.
+ * We hold this ref throughout the state machine to make
+ * sure that the structure we need is still around.
*/
int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
{
struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
- struct sctp_inq *inqueue = NULL;
+ struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
struct sctp_ep_common *rcvr = NULL;
+ int backloged = 0;
rcvr = chunk->rcvr;
- BUG_TRAP(rcvr->sk == sk);
-
- if (rcvr->dead) {
- sctp_chunk_free(chunk);
- } else {
- inqueue = &chunk->rcvr->inqueue;
- sctp_inq_push(inqueue, chunk);
- }
-
- /* Release the asoc/ep ref we took in the lookup calls in sctp_rcv. */
- if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
- sctp_association_put(sctp_assoc(rcvr));
- else
- sctp_endpoint_put(sctp_ep(rcvr));
-
+ /* If the rcvr is dead then the association or endpoint
+ * has been deleted and we can safely drop the chunk
+ * and refs that we are holding.
+ */
+ if (rcvr->dead) {
+ sctp_chunk_free(chunk);
+ goto done;
+ }
+
+ if (unlikely(rcvr->sk != sk)) {
+ /* In this case, the association moved from one socket to
+ * another. We are currently sitting on the backlog of the
+ * old socket, so we need to move.
+ * However, since we are here in the process context we
+ * need to take make sure that the user doesn't own
+ * the new socket when we process the packet.
+ * If the new socket is user-owned, queue the chunk to the
+ * backlog of the new socket without dropping any refs.
+ * Otherwise, we can safely push the chunk on the inqueue.
+ */
+
+ sk = rcvr->sk;
+ sctp_bh_lock_sock(sk);
+
+ if (sock_owned_by_user(sk)) {
+ sk_add_backlog(sk, skb);
+ backloged = 1;
+ } else
+ sctp_inq_push(inqueue, chunk);
+
+ sctp_bh_unlock_sock(sk);
+
+ /* If the chunk was backloged again, don't drop refs */
+ if (backloged)
+ return 0;
+ } else {
+ sctp_inq_push(inqueue, chunk);
+ }
+
+done:
+ /* Release the refs we took in sctp_add_backlog */
+ if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
+ sctp_association_put(sctp_assoc(rcvr));
+ else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
+ sctp_endpoint_put(sctp_ep(rcvr));
+ else
+ BUG();
+
return 0;
}
-void sctp_backlog_migrate(struct sctp_association *assoc,
- struct sock *oldsk, struct sock *newsk)
+static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
{
- struct sk_buff *skb;
- struct sctp_chunk *chunk;
+ struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
+ struct sctp_ep_common *rcvr = chunk->rcvr;
- skb = oldsk->sk_backlog.head;
- oldsk->sk_backlog.head = oldsk->sk_backlog.tail = NULL;
- while (skb != NULL) {
- struct sk_buff *next = skb->next;
-
- chunk = SCTP_INPUT_CB(skb)->chunk;
- skb->next = NULL;
- if (&assoc->base == chunk->rcvr)
- sk_add_backlog(newsk, skb);
- else
- sk_add_backlog(oldsk, skb);
- skb = next;
- }
+ /* Hold the assoc/ep while hanging on the backlog queue.
+ * This way, we know structures we need will not disappear from us
+ */
+ if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
+ sctp_association_hold(sctp_assoc(rcvr));
+ else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
+ sctp_endpoint_hold(sctp_ep(rcvr));
+ else
+ BUG();
+
+ sk_add_backlog(sk, skb);
}
/* Handle icmp frag needed error. */
@@ -412,7 +435,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
union sctp_addr daddr;
struct sctp_af *af;
struct sock *sk = NULL;
- struct sctp_association *asoc = NULL;
+ struct sctp_association *asoc;
struct sctp_transport *transport = NULL;
*app = NULL; *tpp = NULL;
@@ -453,7 +476,6 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
return sk;
out:
- sock_put(sk);
if (asoc)
sctp_association_put(asoc);
return NULL;
@@ -463,7 +485,6 @@ out:
void sctp_err_finish(struct sock *sk, struct sctp_association *asoc)
{
sctp_bh_unlock_sock(sk);
- sock_put(sk);
if (asoc)
sctp_association_put(asoc);
}
@@ -490,7 +511,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
int type = skb->h.icmph->type;
int code = skb->h.icmph->code;
struct sock *sk;
- struct sctp_association *asoc;
+ struct sctp_association *asoc = NULL;
struct sctp_transport *transport;
struct inet_sock *inet;
char *saveip, *savesctp;
@@ -716,7 +737,6 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
hit:
sctp_endpoint_hold(ep);
- sock_hold(epb->sk);
read_unlock(&head->lock);
return ep;
}
@@ -818,7 +838,6 @@ static struct sctp_association *__sctp_lookup_association(
hit:
*pt = transport;
sctp_association_hold(asoc);
- sock_hold(epb->sk);
read_unlock(&head->lock);
return asoc;
}
@@ -846,7 +865,6 @@ int sctp_has_association(const union sctp_addr *laddr,
struct sctp_transport *transport;
if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) {
- sock_put(asoc->base.sk);
sctp_association_put(asoc);
return 1;
}
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index 297b8951463..cf0c767d43a 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -149,6 +149,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
/* This is the first chunk in the packet. */
chunk->singleton = 1;
ch = (sctp_chunkhdr_t *) chunk->skb->data;
+ chunk->data_accepted = 0;
}
chunk->chunk_hdr = ch;
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index d47a52c303a..5b3b0e0ae7e 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -69,7 +69,7 @@ fold_field(void *mib[], int nr)
unsigned long res = 0;
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
res +=
*((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
sizeof (unsigned long) * nr));
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 8d1dc24bab4..c5beb2ad7ef 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -498,10 +498,6 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
- /* Set sk_err to ECONNRESET on a 1-1 style socket. */
- if (!sctp_style(asoc->base.sk, UDP))
- asoc->base.sk->sk_err = ECONNRESET;
-
/* SEND_FAILED sent later when cleaning up the association. */
asoc->outqueue.error = error;
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
@@ -838,6 +834,15 @@ static void sctp_cmd_del_non_primary(struct sctp_association *asoc)
return;
}
+/* Helper function to set sk_err on a 1-1 style socket. */
+static void sctp_cmd_set_sk_err(struct sctp_association *asoc, int error)
+{
+ struct sock *sk = asoc->base.sk;
+
+ if (!sctp_style(sk, UDP))
+ sk->sk_err = error;
+}
+
/* These three macros allow us to pull the debugging code out of the
* main flow of sctp_do_sm() to keep attention focused on the real
* functionality there.
@@ -1458,6 +1463,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
local_cork = 0;
asoc->peer.retran_path = t;
break;
+ case SCTP_CMD_SET_SK_ERR:
+ sctp_cmd_set_sk_err(asoc, cmd->obj.error);
+ break;
default:
printk(KERN_WARNING "Impossible command: %u, %p\n",
cmd->verb, cmd->obj.ptr);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 2b9a832b29a..8bc279219a7 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -93,7 +93,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);
static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
- __u16 error,
+ __u16 error, int sk_err,
const struct sctp_association *asoc,
struct sctp_transport *transport);
@@ -448,7 +448,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
__u32 init_tag;
struct sctp_chunk *err_chunk;
struct sctp_packet *packet;
- sctp_disposition_t ret;
+ __u16 error;
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -480,11 +480,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
goto nomem;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
- sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
- SCTP_STATE(SCTP_STATE_CLOSED));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
- sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
- return SCTP_DISPOSITION_DELETE_TCB;
+ return sctp_stop_t1_and_abort(commands, SCTP_ERROR_INV_PARAM,
+ ECONNREFUSED, asoc,
+ chunk->transport);
}
/* Verify the INIT chunk before processing it. */
@@ -511,27 +509,16 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
SCTP_PACKET(packet));
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
- sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
- SCTP_STATE(SCTP_STATE_CLOSED));
- sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,
- SCTP_NULL());
- return SCTP_DISPOSITION_CONSUME;
+ error = SCTP_ERROR_INV_PARAM;
} else {
- sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
- SCTP_STATE(SCTP_STATE_CLOSED));
- sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,
- SCTP_NULL());
- return SCTP_DISPOSITION_NOMEM;
+ error = SCTP_ERROR_NO_RESOURCE;
}
} else {
- ret = sctp_sf_tabort_8_4_8(ep, asoc, type, arg,
- commands);
- sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
- SCTP_STATE(SCTP_STATE_CLOSED));
- sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,
- SCTP_NULL());
- return ret;
+ sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+ error = SCTP_ERROR_INV_PARAM;
}
+ return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED,
+ asoc, chunk->transport);
}
/* Tag the variable length parameters. Note that we never
@@ -636,8 +623,9 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
*/
chunk->subh.cookie_hdr =
(struct sctp_signed_cookie *)chunk->skb->data;
- skb_pull(chunk->skb,
- ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t));
+ if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
+ sizeof(sctp_chunkhdr_t)))
+ goto nomem;
/* 5.1 D) Upon reception of the COOKIE ECHO chunk, Endpoint
* "Z" will reply with a COOKIE ACK chunk after building a TCB
@@ -885,6 +873,8 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
struct sctp_transport *transport = (struct sctp_transport *) arg;
if (asoc->overall_error_count >= asoc->max_retrans) {
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ETIMEDOUT));
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_NO_ERROR));
@@ -965,7 +955,8 @@ sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep,
*/
chunk->subh.hb_hdr = (sctp_heartbeathdr_t *) chunk->skb->data;
paylen = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t);
- skb_pull(chunk->skb, paylen);
+ if (!pskb_pull(chunk->skb, paylen))
+ goto nomem;
reply = sctp_make_heartbeat_ack(asoc, chunk,
chunk->subh.hb_hdr, paylen);
@@ -1028,6 +1019,12 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
commands);
hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
+ /* Make sure that the length of the parameter is what we expect */
+ if (ntohs(hbinfo->param_hdr.length) !=
+ sizeof(sctp_sender_hb_info_t)) {
+ return SCTP_DISPOSITION_DISCARD;
+ }
+
from_addr = hbinfo->daddr;
link = sctp_assoc_lookup_paddr(asoc, &from_addr);
@@ -1860,8 +1857,9 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
* are in good shape.
*/
chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data;
- skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
- sizeof(sctp_chunkhdr_t));
+ if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
+ sizeof(sctp_chunkhdr_t)))
+ goto nomem;
/* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie
* of a duplicate COOKIE ECHO match the Verification Tags of the
@@ -2123,6 +2121,8 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
int attempts = asoc->init_err_counter + 1;
if (attempts > asoc->max_init_attempts) {
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ETIMEDOUT));
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
SCTP_U32(SCTP_ERROR_STALE_COOKIE));
return SCTP_DISPOSITION_DELETE_TCB;
@@ -2259,6 +2259,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET));
/* ASSOC_FAILED will DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -2303,7 +2304,8 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
- return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport);
+ return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, asoc,
+ chunk->transport);
}
/*
@@ -2315,7 +2317,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep
void *arg,
sctp_cmd_seq_t *commands)
{
- return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc,
+ return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR,
+ ENOPROTOOPT, asoc,
(struct sctp_transport *)arg);
}
@@ -2340,7 +2343,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
* This is common code called by several sctp_sf_*_abort() functions above.
*/
static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
- __u16 error,
+ __u16 error, int sk_err,
const struct sctp_association *asoc,
struct sctp_transport *transport)
{
@@ -2350,6 +2353,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err));
/* CMD_INIT_FAILED will DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
SCTP_U32(error));
@@ -3333,6 +3337,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_ASCONF_ACK));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -3359,6 +3365,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
* processing the rest of the chunks in the packet.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_ASCONF_ACK));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -3711,9 +3719,13 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) {
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ECONNREFUSED));
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
SCTP_U32(SCTP_ERROR_PROTO_VIOLATION));
} else {
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_PROTO_VIOLATION));
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
@@ -4031,6 +4043,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
* TCB. This is a departure from our typical NOMEM handling.
*/
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ECONNABORTED));
/* Delete the established association. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_USER_ABORT));
@@ -4172,6 +4186,8 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
* TCB. This is a departure from our typical NOMEM handling.
*/
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ECONNREFUSED));
/* Delete the established association. */
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
SCTP_U32(SCTP_ERROR_USER_ABORT));
@@ -4540,6 +4556,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
struct sctp_transport *transport = arg;
if (asoc->overall_error_count >= asoc->max_retrans) {
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ETIMEDOUT));
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_NO_ERROR));
@@ -4659,6 +4677,8 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d"
" max_init_attempts: %d\n",
attempts, asoc->max_init_attempts);
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ETIMEDOUT));
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
SCTP_U32(SCTP_ERROR_NO_ERROR));
return SCTP_DISPOSITION_DELETE_TCB;
@@ -4708,6 +4728,8 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
} else {
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ETIMEDOUT));
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
SCTP_U32(SCTP_ERROR_NO_ERROR));
return SCTP_DISPOSITION_DELETE_TCB;
@@ -4739,6 +4761,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
if (asoc->overall_error_count >= asoc->max_retrans) {
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ETIMEDOUT));
/* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_NO_ERROR));
@@ -4814,6 +4838,8 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
if (asoc->overall_error_count >= asoc->max_retrans) {
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ETIMEDOUT));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_NO_ERROR));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -4867,6 +4893,8 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep,
goto nomem;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ETIMEDOUT));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_NO_ERROR));
@@ -5151,7 +5179,9 @@ static int sctp_eat_data(const struct sctp_association *asoc,
int tmp;
__u32 tsn;
int account_value;
+ struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
struct sock *sk = asoc->base.sk;
+ int rcvbuf_over = 0;
data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data;
skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
@@ -5162,10 +5192,16 @@ static int sctp_eat_data(const struct sctp_association *asoc,
/* ASSERT: Now skb->data is really the user data. */
/*
- * if we are established, and we have used up our receive
- * buffer memory, drop the frame
- */
- if (asoc->state == SCTP_STATE_ESTABLISHED) {
+ * If we are established, and we have used up our receive buffer
+ * memory, think about droping the frame.
+ * Note that we have an opportunity to improve performance here.
+ * If we accept one chunk from an skbuff, we have to keep all the
+ * memory of that skbuff around until the chunk is read into user
+ * space. Therefore, once we accept 1 chunk we may as well accept all
+ * remaining chunks in the skbuff. The data_accepted flag helps us do
+ * that.
+ */
+ if ((asoc->state == SCTP_STATE_ESTABLISHED) && (!chunk->data_accepted)) {
/*
* If the receive buffer policy is 1, then each
* association can allocate up to sk_rcvbuf bytes
@@ -5176,9 +5212,25 @@ static int sctp_eat_data(const struct sctp_association *asoc,
account_value = atomic_read(&asoc->rmem_alloc);
else
account_value = atomic_read(&sk->sk_rmem_alloc);
-
- if (account_value > sk->sk_rcvbuf)
- return SCTP_IERROR_IGNORE_TSN;
+ if (account_value > sk->sk_rcvbuf) {
+ /*
+ * We need to make forward progress, even when we are
+ * under memory pressure, so we always allow the
+ * next tsn after the ctsn ack point to be accepted.
+ * This lets us avoid deadlocks in which we have to
+ * drop frames that would otherwise let us drain the
+ * receive queue.
+ */
+ if ((sctp_tsnmap_get_ctsn(map) + 1) != tsn)
+ return SCTP_IERROR_IGNORE_TSN;
+
+ /*
+ * We're going to accept the frame but we should renege
+ * to make space for it. This will send us down that
+ * path later in this function.
+ */
+ rcvbuf_over = 1;
+ }
}
/* Process ECN based congestion.
@@ -5226,6 +5278,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
datalen -= sizeof(sctp_data_chunk_t);
deliver = SCTP_CMD_CHUNK_ULP;
+ chunk->data_accepted = 1;
/* Think about partial delivery. */
if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) {
@@ -5242,7 +5295,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
* large spill over.
*/
if (!asoc->rwnd || asoc->rwnd_over ||
- (datalen > asoc->rwnd + asoc->frag_point)) {
+ (datalen > asoc->rwnd + asoc->frag_point) ||
+ rcvbuf_over) {
/* If this is the next TSN, consider reneging to make
* room. Note: Playing nice with a confused sender. A
@@ -5250,8 +5304,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
* space and in the future we may want to detect and
* do more drastic reneging.
*/
- if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) &&
- (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) {
+ if (sctp_tsnmap_has_gap(map) &&
+ (sctp_tsnmap_get_ctsn(map) + 1) == tsn) {
SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn);
deliver = SCTP_CMD_RENEGE;
} else {
@@ -5280,6 +5334,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
* processing the rest of the chunks in the packet.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ECONNABORTED));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_NO_DATA));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 75ef1040876..8bcca567615 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -366,9 +366,9 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
/* SCTP_STATE_EMPTY */ \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
/* SCTP_STATE_ESTABLISHED */ \
@@ -380,7 +380,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
} /* TYPE_SCTP_ECN_ECNE */
#define TYPE_SCTP_ECN_CWR { \
@@ -401,7 +401,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
} /* TYPE_SCTP_ECN_CWR */
#define TYPE_SCTP_SHUTDOWN_COMPLETE { \
@@ -647,7 +647,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
/* SCTP_STATE_EMPTY */ \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index b6e4b89539b..174d4d35e95 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1057,6 +1057,7 @@ static int __sctp_connect(struct sock* sk,
inet_sk(sk)->dport = htons(asoc->peer.port);
af = sctp_get_af_specific(to.sa.sa_family);
af->to_sk_daddr(&to, sk);
+ sk->sk_err = 0;
timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
err = sctp_wait_for_connect(asoc, &timeo);
@@ -1228,7 +1229,7 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
ep = sctp_sk(sk)->ep;
- /* Walk all associations on a socket, not on an endpoint. */
+ /* Walk all associations on an endpoint. */
list_for_each_safe(pos, temp, &ep->asocs) {
asoc = list_entry(pos, struct sctp_association, asocs);
@@ -1241,13 +1242,13 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
if (sctp_state(asoc, CLOSED)) {
sctp_unhash_established(asoc);
sctp_association_free(asoc);
+ continue;
+ }
+ }
- } else if (sock_flag(sk, SOCK_LINGER) &&
- !sk->sk_lingertime)
- sctp_primitive_ABORT(asoc, NULL);
- else
- sctp_primitive_SHUTDOWN(asoc, NULL);
- } else
+ if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime)
+ sctp_primitive_ABORT(asoc, NULL);
+ else
sctp_primitive_SHUTDOWN(asoc, NULL);
}
@@ -5317,6 +5318,7 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
*/
sctp_release_sock(sk);
current_timeo = schedule_timeout(current_timeo);
+ BUG_ON(sk != asoc->base.sk);
sctp_lock_sock(sk);
*timeo_p = current_timeo;
@@ -5604,12 +5606,14 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
*/
newsp->type = type;
- spin_lock_bh(&oldsk->sk_lock.slock);
- /* Migrate the backlog from oldsk to newsk. */
- sctp_backlog_migrate(assoc, oldsk, newsk);
- /* Migrate the association to the new socket. */
+ /* Mark the new socket "in-use" by the user so that any packets
+ * that may arrive on the association after we've moved it are
+ * queued to the backlog. This prevents a potential race between
+ * backlog processing on the old socket and new-packet processing
+ * on the new socket.
+ */
+ sctp_lock_sock(newsk);
sctp_assoc_migrate(assoc, newsk);
- spin_unlock_bh(&oldsk->sk_lock.slock);
/* If the association on the newsk is already closed before accept()
* is called, set RCV_SHUTDOWN flag.
@@ -5618,6 +5622,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
newsk->sk_shutdown |= RCV_SHUTDOWN;
newsk->sk_state = SCTP_SS_ESTABLISHED;
+ sctp_release_sock(newsk);
}
/* This proto struct describes the ULP interface for SCTP. */
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 2080b2d28c9..575e556aeb3 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -279,6 +279,7 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag)
{
struct sk_buff *pos;
+ struct sk_buff *new = NULL;
struct sctp_ulpevent *event;
struct sk_buff *pnext, *last;
struct sk_buff *list = skb_shinfo(f_frag)->frag_list;
@@ -297,11 +298,33 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu
*/
if (last)
last->next = pos;
- else
- skb_shinfo(f_frag)->frag_list = pos;
+ else {
+ if (skb_cloned(f_frag)) {
+ /* This is a cloned skb, we can't just modify
+ * the frag_list. We need a new skb to do that.
+ * Instead of calling skb_unshare(), we'll do it
+ * ourselves since we need to delay the free.
+ */
+ new = skb_copy(f_frag, GFP_ATOMIC);
+ if (!new)
+ return NULL; /* try again later */
+
+ new->sk = f_frag->sk;
+
+ skb_shinfo(new)->frag_list = pos;
+ } else
+ skb_shinfo(f_frag)->frag_list = pos;
+ }
/* Remove the first fragment from the reassembly queue. */
__skb_unlink(f_frag, queue);
+
+ /* if we did unshare, then free the old skb and re-assign */
+ if (new) {
+ kfree_skb(f_frag);
+ f_frag = new;
+ }
+
while (pos) {
pnext = pos->next;
diff --git a/net/socket.c b/net/socket.c
index 5211ba27037..02948b622bd 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -119,7 +119,6 @@ static ssize_t sock_writev(struct file *file, const struct iovec *vector,
static ssize_t sock_sendpage(struct file *file, struct page *page,
int offset, size_t size, loff_t *ppos, int more);
-
/*
* Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
* in the operation structures but are done directly via the socketcall() multiplexor.
@@ -141,7 +140,8 @@ static struct file_operations socket_file_ops = {
.fasync = sock_fasync,
.readv = sock_readv,
.writev = sock_writev,
- .sendpage = sock_sendpage
+ .sendpage = sock_sendpage,
+ .splice_write = generic_splice_sendpage,
};
/*
@@ -267,6 +267,8 @@ int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ule
return -EINVAL;
if(len)
{
+ if (audit_sockaddr(klen, kaddr))
+ return -ENOMEM;
if(copy_to_user(uaddr,kaddr,len))
return -EFAULT;
}
@@ -490,6 +492,7 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
struct file *file;
struct socket *sock;
+ *err = -EBADF;
file = fget_light(fd, fput_needed);
if (file) {
sock = sock_from_file(file, err);
@@ -539,7 +542,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
return -ENXIO;
}
-struct file_operations bad_sock_fops = {
+const struct file_operations bad_sock_fops = {
.owner = THIS_MODULE,
.open = sock_no_open,
};
@@ -1414,7 +1417,8 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
newfd = sock_alloc_fd(&newfile);
if (unlikely(newfd < 0)) {
err = newfd;
- goto out_release;
+ sock_release(newsock);
+ goto out_put;
}
err = sock_attach_fd(newsock, newfile);
@@ -1451,10 +1455,8 @@ out_put:
out:
return err;
out_fd:
- put_filp(newfile);
+ fput(newfile);
put_unused_fd(newfd);
-out_release:
- sock_release(newsock);
goto out_put;
}
@@ -2133,7 +2135,7 @@ void socket_seq_show(struct seq_file *seq)
int cpu;
int counter = 0;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
counter += per_cpu(sockets_in_use, cpu);
/* It can be negative, by the way. 8) */
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 900ef31f5a0..519ebc17c02 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -794,7 +794,6 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
out_err:
dprintk("RPC: gss_create_cred failed with error %d\n", err);
- if (cred) gss_destroy_cred(&cred->gc_base);
return ERR_PTR(err);
}
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 97c981fa6b8..76b969e6904 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -212,7 +212,6 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
char *cksumname;
struct crypto_tfm *tfm = NULL; /* XXX add to ctx? */
struct scatterlist sg[1];
- u32 code = GSS_S_FAILURE;
switch (cksumtype) {
case CKSUMTYPE_RSA_MD5:
@@ -221,13 +220,11 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
default:
dprintk("RPC: krb5_make_checksum:"
" unsupported checksum %d", cksumtype);
- goto out;
+ return GSS_S_FAILURE;
}
if (!(tfm = crypto_alloc_tfm(cksumname, CRYPTO_TFM_REQ_MAY_SLEEP)))
- goto out;
+ return GSS_S_FAILURE;
cksum->len = crypto_tfm_alg_digestsize(tfm);
- if ((cksum->data = kmalloc(cksum->len, GFP_KERNEL)) == NULL)
- goto out;
crypto_digest_init(tfm);
sg_set_buf(sg, header, hdrlen);
@@ -235,10 +232,8 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
process_xdr_buf(body, body_offset, body->len - body_offset,
checksummer, tfm);
crypto_digest_final(tfm, cksum->data);
- code = 0;
-out:
crypto_free_tfm(tfm);
- return code;
+ return 0;
}
EXPORT_SYMBOL(make_checksum);
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 23632d84d8d..d51e316c582 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -78,7 +78,8 @@ struct rsi {
static struct cache_head *rsi_table[RSI_HASHMAX];
static struct cache_detail rsi_cache;
-static struct rsi *rsi_lookup(struct rsi *item, int set);
+static struct rsi *rsi_update(struct rsi *new, struct rsi *old);
+static struct rsi *rsi_lookup(struct rsi *item);
static void rsi_free(struct rsi *rsii)
{
@@ -88,13 +89,11 @@ static void rsi_free(struct rsi *rsii)
kfree(rsii->out_token.data);
}
-static void rsi_put(struct cache_head *item, struct cache_detail *cd)
+static void rsi_put(struct kref *ref)
{
- struct rsi *rsii = container_of(item, struct rsi, h);
- if (cache_put(item, cd)) {
- rsi_free(rsii);
- kfree(rsii);
- }
+ struct rsi *rsii = container_of(ref, struct rsi, h.ref);
+ rsi_free(rsii);
+ kfree(rsii);
}
static inline int rsi_hash(struct rsi *item)
@@ -103,8 +102,10 @@ static inline int rsi_hash(struct rsi *item)
^ hash_mem(item->in_token.data, item->in_token.len, RSI_HASHBITS);
}
-static inline int rsi_match(struct rsi *item, struct rsi *tmp)
+static int rsi_match(struct cache_head *a, struct cache_head *b)
{
+ struct rsi *item = container_of(a, struct rsi, h);
+ struct rsi *tmp = container_of(b, struct rsi, h);
return netobj_equal(&item->in_handle, &tmp->in_handle)
&& netobj_equal(&item->in_token, &tmp->in_token);
}
@@ -125,8 +126,11 @@ static inline int dup_netobj(struct xdr_netobj *dst, struct xdr_netobj *src)
return dup_to_netobj(dst, src->data, src->len);
}
-static inline void rsi_init(struct rsi *new, struct rsi *item)
+static void rsi_init(struct cache_head *cnew, struct cache_head *citem)
{
+ struct rsi *new = container_of(cnew, struct rsi, h);
+ struct rsi *item = container_of(citem, struct rsi, h);
+
new->out_handle.data = NULL;
new->out_handle.len = 0;
new->out_token.data = NULL;
@@ -141,8 +145,11 @@ static inline void rsi_init(struct rsi *new, struct rsi *item)
item->in_token.data = NULL;
}
-static inline void rsi_update(struct rsi *new, struct rsi *item)
+static void update_rsi(struct cache_head *cnew, struct cache_head *citem)
{
+ struct rsi *new = container_of(cnew, struct rsi, h);
+ struct rsi *item = container_of(citem, struct rsi, h);
+
BUG_ON(new->out_handle.data || new->out_token.data);
new->out_handle.len = item->out_handle.len;
item->out_handle.len = 0;
@@ -157,6 +164,15 @@ static inline void rsi_update(struct rsi *new, struct rsi *item)
new->minor_status = item->minor_status;
}
+static struct cache_head *rsi_alloc(void)
+{
+ struct rsi *rsii = kmalloc(sizeof(*rsii), GFP_KERNEL);
+ if (rsii)
+ return &rsii->h;
+ else
+ return NULL;
+}
+
static void rsi_request(struct cache_detail *cd,
struct cache_head *h,
char **bpp, int *blen)
@@ -198,6 +214,10 @@ static int rsi_parse(struct cache_detail *cd,
if (dup_to_netobj(&rsii.in_token, buf, len))
goto out;
+ rsip = rsi_lookup(&rsii);
+ if (!rsip)
+ goto out;
+
rsii.h.flags = 0;
/* expiry */
expiry = get_expiry(&mesg);
@@ -240,12 +260,14 @@ static int rsi_parse(struct cache_detail *cd,
goto out;
}
rsii.h.expiry_time = expiry;
- rsip = rsi_lookup(&rsii, 1);
+ rsip = rsi_update(&rsii, rsip);
status = 0;
out:
rsi_free(&rsii);
if (rsip)
- rsi_put(&rsip->h, &rsi_cache);
+ cache_put(&rsip->h, &rsi_cache);
+ else
+ status = -ENOMEM;
return status;
}
@@ -257,9 +279,37 @@ static struct cache_detail rsi_cache = {
.cache_put = rsi_put,
.cache_request = rsi_request,
.cache_parse = rsi_parse,
+ .match = rsi_match,
+ .init = rsi_init,
+ .update = update_rsi,
+ .alloc = rsi_alloc,
};
-static DefineSimpleCacheLookup(rsi, 0)
+static struct rsi *rsi_lookup(struct rsi *item)
+{
+ struct cache_head *ch;
+ int hash = rsi_hash(item);
+
+ ch = sunrpc_cache_lookup(&rsi_cache, &item->h, hash);
+ if (ch)
+ return container_of(ch, struct rsi, h);
+ else
+ return NULL;
+}
+
+static struct rsi *rsi_update(struct rsi *new, struct rsi *old)
+{
+ struct cache_head *ch;
+ int hash = rsi_hash(new);
+
+ ch = sunrpc_cache_update(&rsi_cache, &new->h,
+ &old->h, hash);
+ if (ch)
+ return container_of(ch, struct rsi, h);
+ else
+ return NULL;
+}
+
/*
* The rpcsec_context cache is used to store a context that is
@@ -293,7 +343,8 @@ struct rsc {
static struct cache_head *rsc_table[RSC_HASHMAX];
static struct cache_detail rsc_cache;
-static struct rsc *rsc_lookup(struct rsc *item, int set);
+static struct rsc *rsc_update(struct rsc *new, struct rsc *old);
+static struct rsc *rsc_lookup(struct rsc *item);
static void rsc_free(struct rsc *rsci)
{
@@ -304,14 +355,12 @@ static void rsc_free(struct rsc *rsci)
put_group_info(rsci->cred.cr_group_info);
}
-static void rsc_put(struct cache_head *item, struct cache_detail *cd)
+static void rsc_put(struct kref *ref)
{
- struct rsc *rsci = container_of(item, struct rsc, h);
+ struct rsc *rsci = container_of(ref, struct rsc, h.ref);
- if (cache_put(item, cd)) {
- rsc_free(rsci);
- kfree(rsci);
- }
+ rsc_free(rsci);
+ kfree(rsci);
}
static inline int
@@ -320,15 +369,21 @@ rsc_hash(struct rsc *rsci)
return hash_mem(rsci->handle.data, rsci->handle.len, RSC_HASHBITS);
}
-static inline int
-rsc_match(struct rsc *new, struct rsc *tmp)
+static int
+rsc_match(struct cache_head *a, struct cache_head *b)
{
+ struct rsc *new = container_of(a, struct rsc, h);
+ struct rsc *tmp = container_of(b, struct rsc, h);
+
return netobj_equal(&new->handle, &tmp->handle);
}
-static inline void
-rsc_init(struct rsc *new, struct rsc *tmp)
+static void
+rsc_init(struct cache_head *cnew, struct cache_head *ctmp)
{
+ struct rsc *new = container_of(cnew, struct rsc, h);
+ struct rsc *tmp = container_of(ctmp, struct rsc, h);
+
new->handle.len = tmp->handle.len;
tmp->handle.len = 0;
new->handle.data = tmp->handle.data;
@@ -337,9 +392,12 @@ rsc_init(struct rsc *new, struct rsc *tmp)
new->cred.cr_group_info = NULL;
}
-static inline void
-rsc_update(struct rsc *new, struct rsc *tmp)
+static void
+update_rsc(struct cache_head *cnew, struct cache_head *ctmp)
{
+ struct rsc *new = container_of(cnew, struct rsc, h);
+ struct rsc *tmp = container_of(ctmp, struct rsc, h);
+
new->mechctx = tmp->mechctx;
tmp->mechctx = NULL;
memset(&new->seqdata, 0, sizeof(new->seqdata));
@@ -348,6 +406,16 @@ rsc_update(struct rsc *new, struct rsc *tmp)
tmp->cred.cr_group_info = NULL;
}
+static struct cache_head *
+rsc_alloc(void)
+{
+ struct rsc *rsci = kmalloc(sizeof(*rsci), GFP_KERNEL);
+ if (rsci)
+ return &rsci->h;
+ else
+ return NULL;
+}
+
static int rsc_parse(struct cache_detail *cd,
char *mesg, int mlen)
{
@@ -373,6 +441,10 @@ static int rsc_parse(struct cache_detail *cd,
if (expiry == 0)
goto out;
+ rscp = rsc_lookup(&rsci);
+ if (!rscp)
+ goto out;
+
/* uid, or NEGATIVE */
rv = get_int(&mesg, &rsci.cred.cr_uid);
if (rv == -EINVAL)
@@ -428,12 +500,14 @@ static int rsc_parse(struct cache_detail *cd,
gss_mech_put(gm);
}
rsci.h.expiry_time = expiry;
- rscp = rsc_lookup(&rsci, 1);
+ rscp = rsc_update(&rsci, rscp);
status = 0;
out:
rsc_free(&rsci);
if (rscp)
- rsc_put(&rscp->h, &rsc_cache);
+ cache_put(&rscp->h, &rsc_cache);
+ else
+ status = -ENOMEM;
return status;
}
@@ -444,9 +518,37 @@ static struct cache_detail rsc_cache = {
.name = "auth.rpcsec.context",
.cache_put = rsc_put,
.cache_parse = rsc_parse,
+ .match = rsc_match,
+ .init = rsc_init,
+ .update = update_rsc,
+ .alloc = rsc_alloc,
};
-static DefineSimpleCacheLookup(rsc, 0);
+static struct rsc *rsc_lookup(struct rsc *item)
+{
+ struct cache_head *ch;
+ int hash = rsc_hash(item);
+
+ ch = sunrpc_cache_lookup(&rsc_cache, &item->h, hash);
+ if (ch)
+ return container_of(ch, struct rsc, h);
+ else
+ return NULL;
+}
+
+static struct rsc *rsc_update(struct rsc *new, struct rsc *old)
+{
+ struct cache_head *ch;
+ int hash = rsc_hash(new);
+
+ ch = sunrpc_cache_update(&rsc_cache, &new->h,
+ &old->h, hash);
+ if (ch)
+ return container_of(ch, struct rsc, h);
+ else
+ return NULL;
+}
+
static struct rsc *
gss_svc_searchbyctx(struct xdr_netobj *handle)
@@ -457,7 +559,7 @@ gss_svc_searchbyctx(struct xdr_netobj *handle)
memset(&rsci, 0, sizeof(rsci));
if (dup_to_netobj(&rsci.handle, handle->data, handle->len))
return NULL;
- found = rsc_lookup(&rsci, 0);
+ found = rsc_lookup(&rsci);
rsc_free(&rsci);
if (!found)
return NULL;
@@ -645,6 +747,8 @@ find_gss_auth_domain(struct gss_ctx *ctx, u32 svc)
return auth_domain_find(name);
}
+static struct auth_ops svcauthops_gss;
+
int
svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
{
@@ -655,20 +759,18 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
new = kmalloc(sizeof(*new), GFP_KERNEL);
if (!new)
goto out;
- cache_init(&new->h.h);
+ kref_init(&new->h.ref);
new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL);
if (!new->h.name)
goto out_free_dom;
strcpy(new->h.name, name);
- new->h.flavour = RPC_AUTH_GSS;
+ new->h.flavour = &svcauthops_gss;
new->pseudoflavor = pseudoflavor;
- new->h.h.expiry_time = NEVER;
- test = auth_domain_lookup(&new->h, 1);
- if (test == &new->h) {
- BUG_ON(atomic_dec_and_test(&new->h.h.refcnt));
- } else { /* XXX Duplicate registration? */
+ test = auth_domain_lookup(name, &new->h);
+ if (test != &new->h) { /* XXX Duplicate registration? */
auth_domain_put(&new->h);
+ /* dangling ref-count... */
goto out;
}
return 0;
@@ -895,7 +997,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
goto drop;
}
- rsip = rsi_lookup(&rsikey, 0);
+ rsip = rsi_lookup(&rsikey);
rsi_free(&rsikey);
if (!rsip) {
goto drop;
@@ -970,7 +1072,7 @@ drop:
ret = SVC_DROP;
out:
if (rsci)
- rsc_put(&rsci->h, &rsc_cache);
+ cache_put(&rsci->h, &rsc_cache);
return ret;
}
@@ -1020,18 +1122,20 @@ svcauth_gss_release(struct svc_rqst *rqstp)
integ_len))
BUG();
if (resbuf->page_len == 0
- && resbuf->tail[0].iov_len + RPC_MAX_AUTH_SIZE
+ && resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE
< PAGE_SIZE) {
BUG_ON(resbuf->tail[0].iov_len);
/* Use head for everything */
resv = &resbuf->head[0];
} else if (resbuf->tail[0].iov_base == NULL) {
- /* copied from nfsd4_encode_read */
- svc_take_page(rqstp);
- resbuf->tail[0].iov_base = page_address(rqstp
- ->rq_respages[rqstp->rq_resused-1]);
- rqstp->rq_restailpage = rqstp->rq_resused-1;
+ if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE
+ > PAGE_SIZE)
+ goto out_err;
+ resbuf->tail[0].iov_base =
+ resbuf->head[0].iov_base
+ + resbuf->head[0].iov_len;
resbuf->tail[0].iov_len = 0;
+ rqstp->rq_restailpage = 0;
resv = &resbuf->tail[0];
} else {
resv = &resbuf->tail[0];
@@ -1062,7 +1166,7 @@ out_err:
put_group_info(rqstp->rq_cred.cr_group_info);
rqstp->rq_cred.cr_group_info = NULL;
if (gsd->rsci)
- rsc_put(&gsd->rsci->h, &rsc_cache);
+ cache_put(&gsd->rsci->h, &rsc_cache);
gsd->rsci = NULL;
return stat;
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 0acccfeeb28..7026b0866b7 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -37,16 +37,139 @@
static void cache_defer_req(struct cache_req *req, struct cache_head *item);
static void cache_revisit_request(struct cache_head *item);
-void cache_init(struct cache_head *h)
+static void cache_init(struct cache_head *h)
{
time_t now = get_seconds();
h->next = NULL;
h->flags = 0;
- atomic_set(&h->refcnt, 1);
+ kref_init(&h->ref);
h->expiry_time = now + CACHE_NEW_EXPIRY;
h->last_refresh = now;
}
+struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
+ struct cache_head *key, int hash)
+{
+ struct cache_head **head, **hp;
+ struct cache_head *new = NULL;
+
+ head = &detail->hash_table[hash];
+
+ read_lock(&detail->hash_lock);
+
+ for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
+ struct cache_head *tmp = *hp;
+ if (detail->match(tmp, key)) {
+ cache_get(tmp);
+ read_unlock(&detail->hash_lock);
+ return tmp;
+ }
+ }
+ read_unlock(&detail->hash_lock);
+ /* Didn't find anything, insert an empty entry */
+
+ new = detail->alloc();
+ if (!new)
+ return NULL;
+ cache_init(new);
+
+ write_lock(&detail->hash_lock);
+
+ /* check if entry appeared while we slept */
+ for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
+ struct cache_head *tmp = *hp;
+ if (detail->match(tmp, key)) {
+ cache_get(tmp);
+ write_unlock(&detail->hash_lock);
+ cache_put(new, detail);
+ return tmp;
+ }
+ }
+ detail->init(new, key);
+ new->next = *head;
+ *head = new;
+ detail->entries++;
+ cache_get(new);
+ write_unlock(&detail->hash_lock);
+
+ return new;
+}
+EXPORT_SYMBOL(sunrpc_cache_lookup);
+
+
+static void queue_loose(struct cache_detail *detail, struct cache_head *ch);
+
+static int cache_fresh_locked(struct cache_head *head, time_t expiry)
+{
+ head->expiry_time = expiry;
+ head->last_refresh = get_seconds();
+ return !test_and_set_bit(CACHE_VALID, &head->flags);
+}
+
+static void cache_fresh_unlocked(struct cache_head *head,
+ struct cache_detail *detail, int new)
+{
+ if (new)
+ cache_revisit_request(head);
+ if (test_and_clear_bit(CACHE_PENDING, &head->flags)) {
+ cache_revisit_request(head);
+ queue_loose(detail, head);
+ }
+}
+
+struct cache_head *sunrpc_cache_update(struct cache_detail *detail,
+ struct cache_head *new, struct cache_head *old, int hash)
+{
+ /* The 'old' entry is to be replaced by 'new'.
+ * If 'old' is not VALID, we update it directly,
+ * otherwise we need to replace it
+ */
+ struct cache_head **head;
+ struct cache_head *tmp;
+ int is_new;
+
+ if (!test_bit(CACHE_VALID, &old->flags)) {
+ write_lock(&detail->hash_lock);
+ if (!test_bit(CACHE_VALID, &old->flags)) {
+ if (test_bit(CACHE_NEGATIVE, &new->flags))
+ set_bit(CACHE_NEGATIVE, &old->flags);
+ else
+ detail->update(old, new);
+ is_new = cache_fresh_locked(old, new->expiry_time);
+ write_unlock(&detail->hash_lock);
+ cache_fresh_unlocked(old, detail, is_new);
+ return old;
+ }
+ write_unlock(&detail->hash_lock);
+ }
+ /* We need to insert a new entry */
+ tmp = detail->alloc();
+ if (!tmp) {
+ cache_put(old, detail);
+ return NULL;
+ }
+ cache_init(tmp);
+ detail->init(tmp, old);
+ head = &detail->hash_table[hash];
+
+ write_lock(&detail->hash_lock);
+ if (test_bit(CACHE_NEGATIVE, &new->flags))
+ set_bit(CACHE_NEGATIVE, &tmp->flags);
+ else
+ detail->update(tmp, new);
+ tmp->next = *head;
+ *head = tmp;
+ detail->entries++;
+ cache_get(tmp);
+ is_new = cache_fresh_locked(tmp, new->expiry_time);
+ cache_fresh_locked(old, 0);
+ write_unlock(&detail->hash_lock);
+ cache_fresh_unlocked(tmp, detail, is_new);
+ cache_fresh_unlocked(old, detail, 0);
+ cache_put(old, detail);
+ return tmp;
+}
+EXPORT_SYMBOL(sunrpc_cache_update);
static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h);
/*
@@ -94,7 +217,8 @@ int cache_check(struct cache_detail *detail,
clear_bit(CACHE_PENDING, &h->flags);
if (rv == -EAGAIN) {
set_bit(CACHE_NEGATIVE, &h->flags);
- cache_fresh(detail, h, get_seconds()+CACHE_NEW_EXPIRY);
+ cache_fresh_unlocked(h, detail,
+ cache_fresh_locked(h, get_seconds()+CACHE_NEW_EXPIRY));
rv = -ENOENT;
}
break;
@@ -110,25 +234,11 @@ int cache_check(struct cache_detail *detail,
if (rv == -EAGAIN)
cache_defer_req(rqstp, h);
- if (rv && h)
- detail->cache_put(h, detail);
+ if (rv)
+ cache_put(h, detail);
return rv;
}
-static void queue_loose(struct cache_detail *detail, struct cache_head *ch);
-
-void cache_fresh(struct cache_detail *detail,
- struct cache_head *head, time_t expiry)
-{
-
- head->expiry_time = expiry;
- head->last_refresh = get_seconds();
- if (!test_and_set_bit(CACHE_VALID, &head->flags))
- cache_revisit_request(head);
- if (test_and_clear_bit(CACHE_PENDING, &head->flags))
- queue_loose(detail, head);
-}
-
/*
* caches need to be periodically cleaned.
* For this we maintain a list of cache_detail and
@@ -322,7 +432,7 @@ static int cache_clean(void)
if (test_and_clear_bit(CACHE_PENDING, &ch->flags))
queue_loose(current_detail, ch);
- if (atomic_read(&ch->refcnt) == 1)
+ if (atomic_read(&ch->ref.refcount) == 1)
break;
}
if (ch) {
@@ -337,7 +447,7 @@ static int cache_clean(void)
current_index ++;
spin_unlock(&cache_list_lock);
if (ch)
- d->cache_put(ch, d);
+ cache_put(ch, d);
} else
spin_unlock(&cache_list_lock);
@@ -453,7 +563,7 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item)
/* there was one too many */
dreq->revisit(dreq, 1);
}
- if (test_bit(CACHE_VALID, &item->flags)) {
+ if (!test_bit(CACHE_PENDING, &item->flags)) {
/* must have just been validated... */
cache_revisit_request(item);
}
@@ -614,7 +724,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
!test_bit(CACHE_PENDING, &rq->item->flags)) {
list_del(&rq->q.list);
spin_unlock(&queue_lock);
- cd->cache_put(rq->item, cd);
+ cache_put(rq->item, cd);
kfree(rq->buf);
kfree(rq);
} else
@@ -794,10 +904,10 @@ static void queue_loose(struct cache_detail *detail, struct cache_head *ch)
if (cr->item != ch)
continue;
if (cr->readers != 0)
- break;
+ continue;
list_del(&cr->q.list);
spin_unlock(&queue_lock);
- detail->cache_put(cr->item, detail);
+ cache_put(cr->item, detail);
kfree(cr->buf);
kfree(cr);
return;
@@ -1082,8 +1192,8 @@ static int c_show(struct seq_file *m, void *p)
return cd->cache_show(m, cd, NULL);
ifdebug(CACHE)
- seq_printf(m, "# expiry=%ld refcnt=%d\n",
- cp->expiry_time, atomic_read(&cp->refcnt));
+ seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n",
+ cp->expiry_time, atomic_read(&cp->ref.refcount), cp->flags);
cache_get(cp);
if (cache_check(cd, cp, NULL))
/* cache_check does a cache_put on failure */
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index aa4158be990..cc673dd8433 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -395,7 +395,7 @@ enum {
*/
struct rpc_filelist {
char *name;
- struct file_operations *i_fop;
+ const struct file_operations *i_fop;
int mode;
};
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 790941e8af4..15c2db26767 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -176,7 +176,8 @@ void rpc_count_iostats(struct rpc_task *task)
op_metrics->om_execute += execute;
}
-void _print_name(struct seq_file *seq, unsigned int op, struct rpc_procinfo *procs)
+static void _print_name(struct seq_file *seq, unsigned int op,
+ struct rpc_procinfo *procs)
{
if (procs[op].p_name)
seq_printf(seq, "\t%12s: ", procs[op].p_name);
@@ -225,7 +226,7 @@ EXPORT_SYMBOL(rpc_print_iostats);
* Register/unregister RPC proc files
*/
static inline struct proc_dir_entry *
-do_register(const char *name, void *data, struct file_operations *fops)
+do_register(const char *name, void *data, const struct file_operations *fops)
{
struct proc_dir_entry *ent;
@@ -253,7 +254,7 @@ rpc_proc_unregister(const char *name)
}
struct proc_dir_entry *
-svc_proc_register(struct svc_stat *statp, struct file_operations *fops)
+svc_proc_register(struct svc_stat *statp, const struct file_operations *fops)
{
return do_register(statp->program->pg_name, statp, fops);
}
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 9f737320359..769114f0f88 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -105,8 +105,6 @@ EXPORT_SYMBOL(auth_unix_lookup);
EXPORT_SYMBOL(cache_check);
EXPORT_SYMBOL(cache_flush);
EXPORT_SYMBOL(cache_purge);
-EXPORT_SYMBOL(cache_fresh);
-EXPORT_SYMBOL(cache_init);
EXPORT_SYMBOL(cache_register);
EXPORT_SYMBOL(cache_unregister);
EXPORT_SYMBOL(qword_add);
@@ -142,6 +140,7 @@ EXPORT_SYMBOL(nlm_debug);
extern int register_rpc_pipefs(void);
extern void unregister_rpc_pipefs(void);
+extern struct cache_detail ip_map_cache;
static int __init
init_sunrpc(void)
@@ -158,7 +157,6 @@ init_sunrpc(void)
#ifdef CONFIG_PROC_FS
rpc_proc_init();
#endif
- cache_register(&auth_domain_cache);
cache_register(&ip_map_cache);
out:
return err;
@@ -169,8 +167,6 @@ cleanup_sunrpc(void)
{
unregister_rpc_pipefs();
rpc_destroy_mempool();
- if (cache_unregister(&auth_domain_cache))
- printk(KERN_ERR "sunrpc: failed to unregister auth_domain cache\n");
if (cache_unregister(&ip_map_cache))
printk(KERN_ERR "sunrpc: failed to unregister ip_map cache\n");
#ifdef RPC_DEBUG
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index dda4f0c6351..5b28c617680 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -106,112 +106,56 @@ svc_auth_unregister(rpc_authflavor_t flavor)
EXPORT_SYMBOL(svc_auth_unregister);
/**************************************************
- * cache for domain name to auth_domain
- * Entries are only added by flavours which will normally
- * have a structure that 'inherits' from auth_domain.
- * e.g. when an IP -> domainname is given to auth_unix,
- * and the domain name doesn't exist, it will create a
- * auth_unix_domain and add it to this hash table.
- * If it finds the name does exist, but isn't AUTH_UNIX,
- * it will complain.
+ * 'auth_domains' are stored in a hash table indexed by name.
+ * When the last reference to an 'auth_domain' is dropped,
+ * the object is unhashed and freed.
+ * If auth_domain_lookup fails to find an entry, it will return
+ * it's second argument 'new'. If this is non-null, it will
+ * have been atomically linked into the table.
*/
-/*
- * Auth auth_domain cache is somewhat different to other caches,
- * largely because the entries are possibly of different types:
- * each auth flavour has it's own type.
- * One consequence of this that DefineCacheLookup cannot
- * allocate a new structure as it cannot know the size.
- * Notice that the "INIT" code fragment is quite different
- * from other caches. When auth_domain_lookup might be
- * creating a new domain, the new domain is passed in
- * complete and it is used as-is rather than being copied into
- * another structure.
- */
#define DN_HASHBITS 6
#define DN_HASHMAX (1<<DN_HASHBITS)
#define DN_HASHMASK (DN_HASHMAX-1)
-static struct cache_head *auth_domain_table[DN_HASHMAX];
-
-static void auth_domain_drop(struct cache_head *item, struct cache_detail *cd)
-{
- struct auth_domain *dom = container_of(item, struct auth_domain, h);
- if (cache_put(item,cd))
- authtab[dom->flavour]->domain_release(dom);
-}
-
-
-struct cache_detail auth_domain_cache = {
- .owner = THIS_MODULE,
- .hash_size = DN_HASHMAX,
- .hash_table = auth_domain_table,
- .name = "auth.domain",
- .cache_put = auth_domain_drop,
-};
+static struct hlist_head auth_domain_table[DN_HASHMAX];
+static spinlock_t auth_domain_lock = SPIN_LOCK_UNLOCKED;
void auth_domain_put(struct auth_domain *dom)
{
- auth_domain_drop(&dom->h, &auth_domain_cache);
-}
-
-static inline int auth_domain_hash(struct auth_domain *item)
-{
- return hash_str(item->name, DN_HASHBITS);
-}
-static inline int auth_domain_match(struct auth_domain *tmp, struct auth_domain *item)
-{
- return strcmp(tmp->name, item->name) == 0;
+ if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) {
+ hlist_del(&dom->hash);
+ dom->flavour->domain_release(dom);
+ }
}
struct auth_domain *
-auth_domain_lookup(struct auth_domain *item, int set)
+auth_domain_lookup(char *name, struct auth_domain *new)
{
- struct auth_domain *tmp = NULL;
- struct cache_head **hp, **head;
- head = &auth_domain_cache.hash_table[auth_domain_hash(item)];
-
- if (set)
- write_lock(&auth_domain_cache.hash_lock);
- else
- read_lock(&auth_domain_cache.hash_lock);
- for (hp=head; *hp != NULL; hp = &tmp->h.next) {
- tmp = container_of(*hp, struct auth_domain, h);
- if (!auth_domain_match(tmp, item))
- continue;
- if (!set) {
- cache_get(&tmp->h);
- goto out_noset;
+ struct auth_domain *hp;
+ struct hlist_head *head;
+ struct hlist_node *np;
+
+ head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
+
+ spin_lock(&auth_domain_lock);
+
+ hlist_for_each_entry(hp, np, head, hash) {
+ if (strcmp(hp->name, name)==0) {
+ kref_get(&hp->ref);
+ spin_unlock(&auth_domain_lock);
+ return hp;
}
- *hp = tmp->h.next;
- tmp->h.next = NULL;
- auth_domain_drop(&tmp->h, &auth_domain_cache);
- goto out_set;
}
- /* Didn't find anything */
- if (!set)
- goto out_nada;
- auth_domain_cache.entries++;
-out_set:
- item->h.next = *head;
- *head = &item->h;
- cache_get(&item->h);
- write_unlock(&auth_domain_cache.hash_lock);
- cache_fresh(&auth_domain_cache, &item->h, item->h.expiry_time);
- cache_get(&item->h);
- return item;
-out_nada:
- tmp = NULL;
-out_noset:
- read_unlock(&auth_domain_cache.hash_lock);
- return tmp;
+ if (new) {
+ hlist_add_head(&new->hash, head);
+ kref_get(&new->ref);
+ }
+ spin_unlock(&auth_domain_lock);
+ return new;
}
struct auth_domain *auth_domain_find(char *name)
{
- struct auth_domain *rv, ad;
-
- ad.name = name;
- rv = auth_domain_lookup(&ad, 0);
- return rv;
+ return auth_domain_lookup(name, NULL);
}
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 3e6c694bbad..7e5707e2d6b 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -27,41 +27,35 @@ struct unix_domain {
/* other stuff later */
};
+extern struct auth_ops svcauth_unix;
+
struct auth_domain *unix_domain_find(char *name)
{
- struct auth_domain *rv, ud;
- struct unix_domain *new;
-
- ud.name = name;
-
- rv = auth_domain_lookup(&ud, 0);
-
- foundit:
- if (rv && rv->flavour != RPC_AUTH_UNIX) {
- auth_domain_put(rv);
- return NULL;
- }
- if (rv)
- return rv;
-
- new = kmalloc(sizeof(*new), GFP_KERNEL);
- if (new == NULL)
- return NULL;
- cache_init(&new->h.h);
- new->h.name = kstrdup(name, GFP_KERNEL);
- new->h.flavour = RPC_AUTH_UNIX;
- new->addr_changes = 0;
- new->h.h.expiry_time = NEVER;
-
- rv = auth_domain_lookup(&new->h, 2);
- if (rv == &new->h) {
- if (atomic_dec_and_test(&new->h.h.refcnt)) BUG();
- } else {
- auth_domain_put(&new->h);
- goto foundit;
+ struct auth_domain *rv;
+ struct unix_domain *new = NULL;
+
+ rv = auth_domain_lookup(name, NULL);
+ while(1) {
+ if (rv) {
+ if (new && rv != &new->h)
+ auth_domain_put(&new->h);
+
+ if (rv->flavour != &svcauth_unix) {
+ auth_domain_put(rv);
+ return NULL;
+ }
+ return rv;
+ }
+
+ new = kmalloc(sizeof(*new), GFP_KERNEL);
+ if (new == NULL)
+ return NULL;
+ kref_init(&new->h.ref);
+ new->h.name = kstrdup(name, GFP_KERNEL);
+ new->h.flavour = &svcauth_unix;
+ new->addr_changes = 0;
+ rv = auth_domain_lookup(name, &new->h);
}
-
- return rv;
}
static void svcauth_unix_domain_release(struct auth_domain *dom)
@@ -90,15 +84,15 @@ struct ip_map {
};
static struct cache_head *ip_table[IP_HASHMAX];
-static void ip_map_put(struct cache_head *item, struct cache_detail *cd)
+static void ip_map_put(struct kref *kref)
{
+ struct cache_head *item = container_of(kref, struct cache_head, ref);
struct ip_map *im = container_of(item, struct ip_map,h);
- if (cache_put(item, cd)) {
- if (test_bit(CACHE_VALID, &item->flags) &&
- !test_bit(CACHE_NEGATIVE, &item->flags))
- auth_domain_put(&im->m_client->h);
- kfree(im);
- }
+
+ if (test_bit(CACHE_VALID, &item->flags) &&
+ !test_bit(CACHE_NEGATIVE, &item->flags))
+ auth_domain_put(&im->m_client->h);
+ kfree(im);
}
#if IP_HASHBITS == 8
@@ -112,28 +106,38 @@ static inline int hash_ip(unsigned long ip)
return (hash ^ (hash>>8)) & 0xff;
}
#endif
-
-static inline int ip_map_hash(struct ip_map *item)
-{
- return hash_str(item->m_class, IP_HASHBITS) ^
- hash_ip((unsigned long)item->m_addr.s_addr);
-}
-static inline int ip_map_match(struct ip_map *item, struct ip_map *tmp)
+static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
{
- return strcmp(tmp->m_class, item->m_class) == 0
- && tmp->m_addr.s_addr == item->m_addr.s_addr;
+ struct ip_map *orig = container_of(corig, struct ip_map, h);
+ struct ip_map *new = container_of(cnew, struct ip_map, h);
+ return strcmp(orig->m_class, new->m_class) == 0
+ && orig->m_addr.s_addr == new->m_addr.s_addr;
}
-static inline void ip_map_init(struct ip_map *new, struct ip_map *item)
+static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
{
+ struct ip_map *new = container_of(cnew, struct ip_map, h);
+ struct ip_map *item = container_of(citem, struct ip_map, h);
+
strcpy(new->m_class, item->m_class);
new->m_addr.s_addr = item->m_addr.s_addr;
}
-static inline void ip_map_update(struct ip_map *new, struct ip_map *item)
+static void update(struct cache_head *cnew, struct cache_head *citem)
{
- cache_get(&item->m_client->h.h);
+ struct ip_map *new = container_of(cnew, struct ip_map, h);
+ struct ip_map *item = container_of(citem, struct ip_map, h);
+
+ kref_get(&item->m_client->h.ref);
new->m_client = item->m_client;
new->m_add_change = item->m_add_change;
}
+static struct cache_head *ip_map_alloc(void)
+{
+ struct ip_map *i = kmalloc(sizeof(*i), GFP_KERNEL);
+ if (i)
+ return &i->h;
+ else
+ return NULL;
+}
static void ip_map_request(struct cache_detail *cd,
struct cache_head *h,
@@ -154,7 +158,8 @@ static void ip_map_request(struct cache_detail *cd,
(*bpp)[-1] = '\n';
}
-static struct ip_map *ip_map_lookup(struct ip_map *, int);
+static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
+static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
static int ip_map_parse(struct cache_detail *cd,
char *mesg, int mlen)
@@ -166,7 +171,11 @@ static int ip_map_parse(struct cache_detail *cd,
int len;
int b1,b2,b3,b4;
char c;
- struct ip_map ipm, *ipmp;
+ char class[8];
+ struct in_addr addr;
+ int err;
+
+ struct ip_map *ipmp;
struct auth_domain *dom;
time_t expiry;
@@ -175,7 +184,7 @@ static int ip_map_parse(struct cache_detail *cd,
mesg[mlen-1] = 0;
/* class */
- len = qword_get(&mesg, ipm.m_class, sizeof(ipm.m_class));
+ len = qword_get(&mesg, class, sizeof(class));
if (len <= 0) return -EINVAL;
/* ip address */
@@ -200,25 +209,22 @@ static int ip_map_parse(struct cache_detail *cd,
} else
dom = NULL;
- ipm.m_addr.s_addr =
+ addr.s_addr =
htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
- ipm.h.flags = 0;
- if (dom) {
- ipm.m_client = container_of(dom, struct unix_domain, h);
- ipm.m_add_change = ipm.m_client->addr_changes;
+
+ ipmp = ip_map_lookup(class,addr);
+ if (ipmp) {
+ err = ip_map_update(ipmp,
+ container_of(dom, struct unix_domain, h),
+ expiry);
} else
- set_bit(CACHE_NEGATIVE, &ipm.h.flags);
- ipm.h.expiry_time = expiry;
+ err = -ENOMEM;
- ipmp = ip_map_lookup(&ipm, 1);
- if (ipmp)
- ip_map_put(&ipmp->h, &ip_map_cache);
if (dom)
auth_domain_put(dom);
- if (!ipmp)
- return -ENOMEM;
+
cache_flush();
- return 0;
+ return err;
}
static int ip_map_show(struct seq_file *m,
@@ -262,32 +268,70 @@ struct cache_detail ip_map_cache = {
.cache_request = ip_map_request,
.cache_parse = ip_map_parse,
.cache_show = ip_map_show,
+ .match = ip_map_match,
+ .init = ip_map_init,
+ .update = update,
+ .alloc = ip_map_alloc,
};
-static DefineSimpleCacheLookup(ip_map, 0)
+static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
+{
+ struct ip_map ip;
+ struct cache_head *ch;
+
+ strcpy(ip.m_class, class);
+ ip.m_addr = addr;
+ ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
+ hash_str(class, IP_HASHBITS) ^
+ hash_ip((unsigned long)addr.s_addr));
+
+ if (ch)
+ return container_of(ch, struct ip_map, h);
+ else
+ return NULL;
+}
+static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry)
+{
+ struct ip_map ip;
+ struct cache_head *ch;
+
+ ip.m_client = udom;
+ ip.h.flags = 0;
+ if (!udom)
+ set_bit(CACHE_NEGATIVE, &ip.h.flags);
+ else {
+ ip.m_add_change = udom->addr_changes;
+ /* if this is from the legacy set_client system call,
+ * we need m_add_change to be one higher
+ */
+ if (expiry == NEVER)
+ ip.m_add_change++;
+ }
+ ip.h.expiry_time = expiry;
+ ch = sunrpc_cache_update(&ip_map_cache,
+ &ip.h, &ipm->h,
+ hash_str(ipm->m_class, IP_HASHBITS) ^
+ hash_ip((unsigned long)ipm->m_addr.s_addr));
+ if (!ch)
+ return -ENOMEM;
+ cache_put(ch, &ip_map_cache);
+ return 0;
+}
int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
{
struct unix_domain *udom;
- struct ip_map ip, *ipmp;
+ struct ip_map *ipmp;
- if (dom->flavour != RPC_AUTH_UNIX)
+ if (dom->flavour != &svcauth_unix)
return -EINVAL;
udom = container_of(dom, struct unix_domain, h);
- strcpy(ip.m_class, "nfsd");
- ip.m_addr = addr;
- ip.m_client = udom;
- ip.m_add_change = udom->addr_changes+1;
- ip.h.flags = 0;
- ip.h.expiry_time = NEVER;
-
- ipmp = ip_map_lookup(&ip, 1);
+ ipmp = ip_map_lookup("nfsd", addr);
- if (ipmp) {
- ip_map_put(&ipmp->h, &ip_map_cache);
- return 0;
- } else
+ if (ipmp)
+ return ip_map_update(ipmp, udom, NEVER);
+ else
return -ENOMEM;
}
@@ -295,7 +339,7 @@ int auth_unix_forget_old(struct auth_domain *dom)
{
struct unix_domain *udom;
- if (dom->flavour != RPC_AUTH_UNIX)
+ if (dom->flavour != &svcauth_unix)
return -EINVAL;
udom = container_of(dom, struct unix_domain, h);
udom->addr_changes++;
@@ -310,7 +354,7 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr)
strcpy(key.m_class, "nfsd");
key.m_addr = addr;
- ipm = ip_map_lookup(&key, 0);
+ ipm = ip_map_lookup("nfsd", addr);
if (!ipm)
return NULL;
@@ -323,31 +367,28 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr)
rv = NULL;
} else {
rv = &ipm->m_client->h;
- cache_get(&rv->h);
+ kref_get(&rv->ref);
}
- ip_map_put(&ipm->h, &ip_map_cache);
+ cache_put(&ipm->h, &ip_map_cache);
return rv;
}
void svcauth_unix_purge(void)
{
cache_purge(&ip_map_cache);
- cache_purge(&auth_domain_cache);
}
static int
svcauth_unix_set_client(struct svc_rqst *rqstp)
{
- struct ip_map key, *ipm;
+ struct ip_map *ipm;
rqstp->rq_client = NULL;
if (rqstp->rq_proc == 0)
return SVC_OK;
- strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class);
- key.m_addr = rqstp->rq_addr.sin_addr;
-
- ipm = ip_map_lookup(&key, 0);
+ ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
+ rqstp->rq_addr.sin_addr);
if (ipm == NULL)
return SVC_DENIED;
@@ -361,8 +402,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
return SVC_DENIED;
case 0:
rqstp->rq_client = &ipm->m_client->h;
- cache_get(&rqstp->rq_client->h);
- ip_map_put(&ipm->h, &ip_map_cache);
+ kref_get(&rqstp->rq_client->ref);
+ cache_put(&ipm->h, &ip_map_cache);
break;
}
return SVC_OK;
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index 55538f6b60f..58a1b6b42dd 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -37,14 +37,6 @@ struct ctl_table net_table[] = {
.mode = 0555,
.child = core_table,
},
-#ifdef CONFIG_NET
- {
- .ctl_name = NET_ETHER,
- .procname = "ethernet",
- .mode = 0555,
- .child = ether_table,
- },
-#endif
#ifdef CONFIG_INET
{
.ctl_name = NET_IPV4,
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 953307a9df1..a3bbc891f95 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -229,8 +229,7 @@ static void node_is_down(struct publication *publ)
publ->node, publ->ref, publ->key);
assert(p == publ);
write_unlock_bh(&tipc_nametbl_lock);
- if (publ)
- kfree(publ);
+ kfree(publ);
}
/**
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index 8b9bf4a763b..b1265187b4a 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -55,12 +55,10 @@
#include <asm/uaccess.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/wanpipe.h>
#include <linux/if_wanpipe.h>
#include <linux/pkt_sched.h>
#include <linux/tcp_states.h>
#include <linux/if_wanpipe_common.h>
-#include <linux/sdla_x25.h>
#ifdef CONFIG_INET
#include <net/inet_common.h>
diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c
index 0a92e1da392..71ff3088f6f 100644
--- a/net/x25/x25_timer.c
+++ b/net/x25/x25_timer.c
@@ -114,8 +114,9 @@ static void x25_heartbeat_expiry(unsigned long param)
if (sock_flag(sk, SOCK_DESTROY) ||
(sk->sk_state == TCP_LISTEN &&
sock_flag(sk, SOCK_DEAD))) {
+ bh_unlock_sock(sk);
x25_destroy_socket(sk);
- goto unlock;
+ return;
}
break;
@@ -128,7 +129,6 @@ static void x25_heartbeat_expiry(unsigned long param)
}
restart_heartbeat:
x25_start_heartbeat(sk);
-unlock:
bh_unlock_sock(sk);
}
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 2407a707232..891a6090cc0 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -18,7 +18,7 @@ void __secpath_destroy(struct sec_path *sp)
{
int i;
for (i = 0; i < sp->len; i++)
- xfrm_state_put(sp->x[i].xvec);
+ xfrm_state_put(sp->xvec[i]);
kmem_cache_free(secpath_cachep, sp);
}
EXPORT_SYMBOL(__secpath_destroy);
@@ -37,7 +37,7 @@ struct sec_path *secpath_dup(struct sec_path *src)
memcpy(sp, src, sizeof(*sp));
for (i = 0; i < sp->len; i++)
- xfrm_state_hold(sp->x[i].xvec);
+ xfrm_state_hold(sp->xvec[i]);
}
atomic_set(&sp->refcnt, 1);
return sp;
@@ -62,7 +62,7 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
case IPPROTO_COMP:
if (!pskb_may_pull(skb, sizeof(struct ip_comp_hdr)))
return -EINVAL;
- *spi = ntohl(ntohs(*(u16*)(skb->h.raw + 2)));
+ *spi = htonl(ntohs(*(u16*)(skb->h.raw + 2)));
*seq = 0;
return 0;
default:
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index f5eae9febd2..b469c8b5461 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -57,12 +57,12 @@ int xfrm_register_type(struct xfrm_type *type, unsigned short family)
return -EAFNOSUPPORT;
typemap = afinfo->type_map;
- write_lock(&typemap->lock);
+ write_lock_bh(&typemap->lock);
if (likely(typemap->map[type->proto] == NULL))
typemap->map[type->proto] = type;
else
err = -EEXIST;
- write_unlock(&typemap->lock);
+ write_unlock_bh(&typemap->lock);
xfrm_policy_put_afinfo(afinfo);
return err;
}
@@ -78,12 +78,12 @@ int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
return -EAFNOSUPPORT;
typemap = afinfo->type_map;
- write_lock(&typemap->lock);
+ write_lock_bh(&typemap->lock);
if (unlikely(typemap->map[type->proto] != type))
err = -ENOENT;
else
typemap->map[type->proto] = NULL;
- write_unlock(&typemap->lock);
+ write_unlock_bh(&typemap->lock);
xfrm_policy_put_afinfo(afinfo);
return err;
}
@@ -943,9 +943,9 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
} else
start = -1;
for (; idx < sp->len; idx++) {
- if (xfrm_state_ok(tmpl, sp->x[idx].xvec, family))
+ if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
return ++idx;
- if (sp->x[idx].xvec->props.mode)
+ if (sp->xvec[idx]->props.mode)
break;
}
return start;
@@ -968,7 +968,7 @@ EXPORT_SYMBOL(xfrm_decode_session);
static inline int secpath_has_tunnel(struct sec_path *sp, int k)
{
for (; k < sp->len; k++) {
- if (sp->x[k].xvec->props.mode)
+ if (sp->xvec[k]->props.mode)
return 1;
}
@@ -994,8 +994,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
int i;
for (i=skb->sp->len-1; i>=0; i--) {
- struct sec_decap_state *xvec = &(skb->sp->x[i]);
- if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
+ struct xfrm_state *x = skb->sp->xvec[i];
+ if (!xfrm_selector_match(&x->sel, &fl, family))
return 0;
}
}
@@ -1251,7 +1251,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
return -EINVAL;
if (unlikely(afinfo->family >= NPROTO))
return -EAFNOSUPPORT;
- write_lock(&xfrm_policy_afinfo_lock);
+ write_lock_bh(&xfrm_policy_afinfo_lock);
if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL))
err = -ENOBUFS;
else {
@@ -1268,7 +1268,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
afinfo->garbage_collect = __xfrm_garbage_collect;
xfrm_policy_afinfo[afinfo->family] = afinfo;
}
- write_unlock(&xfrm_policy_afinfo_lock);
+ write_unlock_bh(&xfrm_policy_afinfo_lock);
return err;
}
EXPORT_SYMBOL(xfrm_policy_register_afinfo);
@@ -1280,7 +1280,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
return -EINVAL;
if (unlikely(afinfo->family >= NPROTO))
return -EAFNOSUPPORT;
- write_lock(&xfrm_policy_afinfo_lock);
+ write_lock_bh(&xfrm_policy_afinfo_lock);
if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) {
if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo))
err = -EINVAL;
@@ -1294,7 +1294,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
afinfo->garbage_collect = NULL;
}
}
- write_unlock(&xfrm_policy_afinfo_lock);
+ write_unlock_bh(&xfrm_policy_afinfo_lock);
return err;
}
EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index a8e14dc1b04..93a2f36ad3d 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -805,16 +805,22 @@ void xfrm_replay_notify(struct xfrm_state *x, int event)
case XFRM_REPLAY_UPDATE:
if (x->replay_maxdiff &&
(x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
- (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))
- return;
+ (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
+ if (x->xflags & XFRM_TIME_DEFER)
+ event = XFRM_REPLAY_TIMEOUT;
+ else
+ return;
+ }
break;
case XFRM_REPLAY_TIMEOUT:
if ((x->replay.seq == x->preplay.seq) &&
(x->replay.bitmap == x->preplay.bitmap) &&
- (x->replay.oseq == x->preplay.oseq))
+ (x->replay.oseq == x->preplay.oseq)) {
+ x->xflags |= XFRM_TIME_DEFER;
return;
+ }
break;
}
@@ -825,8 +831,10 @@ void xfrm_replay_notify(struct xfrm_state *x, int event)
km_state_notify(x, &c);
if (x->replay_maxage &&
- !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
+ !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) {
xfrm_state_hold(x);
+ x->xflags &= ~XFRM_TIME_DEFER;
+ }
}
EXPORT_SYMBOL(xfrm_replay_notify);
@@ -836,10 +844,15 @@ static void xfrm_replay_timer_handler(unsigned long data)
spin_lock(&x->lock);
- if (xfrm_aevent_is_on() && x->km.state == XFRM_STATE_VALID)
- xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
+ if (x->km.state == XFRM_STATE_VALID) {
+ if (xfrm_aevent_is_on())
+ xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
+ else
+ x->xflags |= XFRM_TIME_DEFER;
+ }
spin_unlock(&x->lock);
+ xfrm_state_put(x);
}
int xfrm_replay_check(struct xfrm_state *x, u32 seq)
@@ -1048,7 +1061,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
return -EINVAL;
if (unlikely(afinfo->family >= NPROTO))
return -EAFNOSUPPORT;
- write_lock(&xfrm_state_afinfo_lock);
+ write_lock_bh(&xfrm_state_afinfo_lock);
if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
err = -ENOBUFS;
else {
@@ -1056,7 +1069,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
afinfo->state_byspi = xfrm_state_byspi;
xfrm_state_afinfo[afinfo->family] = afinfo;
}
- write_unlock(&xfrm_state_afinfo_lock);
+ write_unlock_bh(&xfrm_state_afinfo_lock);
return err;
}
EXPORT_SYMBOL(xfrm_state_register_afinfo);
@@ -1068,7 +1081,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
return -EINVAL;
if (unlikely(afinfo->family >= NPROTO))
return -EAFNOSUPPORT;
- write_lock(&xfrm_state_afinfo_lock);
+ write_lock_bh(&xfrm_state_afinfo_lock);
if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {
if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
err = -EINVAL;
@@ -1078,7 +1091,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
afinfo->state_bydst = NULL;
}
}
- write_unlock(&xfrm_state_afinfo_lock);
+ write_unlock_bh(&xfrm_state_afinfo_lock);
return err;
}
EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 59620b1554e..b0d067be739 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -87,6 +87,11 @@ cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \
# $(Q)$(MAKE) $(build)=dir
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
+# Prefix -I with $(srctree) if it is not an absolute path
+addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
+# Find all -I options and call addtree
+flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
+
# If quiet is set, only print short version of command
cmd = @$(echo-cmd) $(cmd_$(1))
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 550798f57da..2cb4935e85d 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -99,11 +99,6 @@ __a_flags = $(_a_flags)
__cpp_flags = $(_cpp_flags)
else
-# Prefix -I with $(srctree) if it is not an absolute path
-addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
-# Find all -I options and call addtree
-flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
-
# -I$(obj) locates generated .h files
# $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files
# and locates generated .h files
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
index 75f21d843c1..75f21d843c1 100644..100755
--- a/scripts/bloat-o-meter
+++ b/scripts/bloat-o-meter
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index dadfa20ffec..dadfa20ffec 100644..100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index 6d411169bfa..331c079f029 100644
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -1,22 +1,55 @@
#!/bin/bash
# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
-# Released under the terms of the GNU GPL
-#
-# Generate a newline separated list of entries from the file/directory
-# supplied as an argument.
-#
-# If a file/directory is not supplied then generate a small dummy file.
+# Copyright (c) 2006 Sam Ravnborg <sam@ravnborg.org>
#
-# The output is suitable for gen_init_cpio built from usr/gen_init_cpio.c.
+# Released under the terms of the GNU GPL
#
+# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
+# the cpio archive, and gzip to pack it.
+# The script may also be used to generate the inputfile used for gen_init_cpio
+# This script assumes that gen_init_cpio is located in usr/ directory
+
+# error out on errors
+set -e
+
+usage() {
+cat << EOF
+Usage:
+$0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
+ -o <file> Create gzipped initramfs file named <file> using
+ gen_init_cpio and gzip
+ -u <uid> User ID to map to user ID 0 (root).
+ <uid> is only meaningful if <cpio_source>
+ is a directory.
+ -g <gid> Group ID to map to group ID 0 (root).
+ <gid> is only meaningful if <cpio_source>
+ is a directory.
+ <cpio_source> File list or directory for cpio archive.
+ If <cpio_source> is a .cpio file it will be used
+ as direct input to initramfs.
+ -d Output the default cpio list.
+
+All options except -o and -l may be repeated and are interpreted
+sequentially and immediately. -u and -g states are preserved across
+<cpio_source> options so an explicit "-u 0 -g 0" is required
+to reset the root/group mapping.
+EOF
+}
+
+list_default_initramfs() {
+ # echo usr/kinit/kinit
+ :
+}
default_initramfs() {
- cat <<-EOF
+ cat <<-EOF >> ${output}
# This is a very simple, default initramfs
dir /dev 0755 0 0
nod /dev/console 0600 0 0 c 5 1
dir /root 0700 0 0
+ # file /kinit usr/kinit/kinit 0755 0 0
+ # slink /init kinit 0755 0 0
EOF
}
@@ -42,18 +75,28 @@ filetype() {
return 0
}
+list_print_mtime() {
+ :
+}
+
print_mtime() {
- local argv1="$1"
local my_mtime="0"
- if [ -e "${argv1}" ]; then
- my_mtime=$(find "${argv1}" -printf "%T@\n" | sort -r | head -n 1)
+ if [ -e "$1" ]; then
+ my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
fi
-
- echo "# Last modified: ${my_mtime}"
- echo
+
+ echo "# Last modified: ${my_mtime}" >> ${output}
+ echo "" >> ${output}
+}
+
+list_parse() {
+ echo "$1 \\"
}
+# for each file print a line in following format
+# <filetype> <name> <path to file> <octal mode> <uid> <gid>
+# for links, devices etc the format differs. See gen_init_cpio for details
parse() {
local location="$1"
local name="${location/${srcdir}//}"
@@ -99,80 +142,116 @@ parse() {
;;
esac
- echo "${str}"
+ echo "${str}" >> ${output}
return 0
}
-usage() {
- printf "Usage:\n"
- printf "$0 [ [-u <root_uid>] [-g <root_gid>] [-d | <cpio_source>] ] . . .\n"
- printf "\n"
- printf -- "-u <root_uid> User ID to map to user ID 0 (root).\n"
- printf " <root_uid> is only meaningful if <cpio_source>\n"
- printf " is a directory.\n"
- printf -- "-g <root_gid> Group ID to map to group ID 0 (root).\n"
- printf " <root_gid> is only meaningful if <cpio_source>\n"
- printf " is a directory.\n"
- printf "<cpio_source> File list or directory for cpio archive.\n"
- printf " If <cpio_source> is not provided then a\n"
- printf " a default list will be output.\n"
- printf -- "-d Output the default cpio list. If no <cpio_source>\n"
- printf " is given then the default cpio list will be output.\n"
- printf "\n"
- printf "All options may be repeated and are interpreted sequentially\n"
- printf "and immediately. -u and -g states are preserved across\n"
- printf "<cpio_source> options so an explicit \"-u 0 -g 0\" is required\n"
- printf "to reset the root/group mapping.\n"
+unknown_option() {
+ printf "ERROR: unknown option \"$arg\"\n" >&2
+ printf "If the filename validly begins with '-', " >&2
+ printf "then it must be prefixed\n" >&2
+ printf "by './' so that it won't be interpreted as an option." >&2
+ printf "\n" >&2
+ usage >&2
+ exit 1
}
-build_list() {
- printf "\n#####################\n# $cpio_source\n"
-
- if [ -f "$cpio_source" ]; then
- print_mtime "$cpio_source"
- cat "$cpio_source"
- elif [ -d "$cpio_source" ]; then
- srcdir=$(echo "$cpio_source" | sed -e 's://*:/:g')
- dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
-
- # If $dirlist is only one line, then the directory is empty
- if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
- print_mtime "$cpio_source"
-
- echo "${dirlist}" | \
- while read x; do
- parse ${x}
- done
+list_header() {
+ echo "deps_initramfs := \\"
+}
+
+header() {
+ printf "\n#####################\n# $1\n" >> ${output}
+}
+
+# process one directory (incl sub-directories)
+dir_filelist() {
+ ${dep_list}header "$1"
+
+ srcdir=$(echo "$1" | sed -e 's://*:/:g')
+ dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
+
+ # If $dirlist is only one line, then the directory is empty
+ if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
+ ${dep_list}print_mtime "$1"
+
+ echo "${dirlist}" | \
+ while read x; do
+ ${dep_list}parse ${x}
+ done
+ fi
+}
+
+# if only one file is specified and it is .cpio file then use it direct as fs
+# if a directory is specified then add all files in given direcotry to fs
+# if a regular file is specified assume it is in gen_initramfs format
+input_file() {
+ source="$1"
+ if [ -f "$1" ]; then
+ ${dep_list}header "$1"
+ is_cpio="$(echo "$1" | sed 's/^.*\.cpio/cpio/')"
+ if [ $2 -eq 0 -a ${is_cpio} == "cpio" ]; then
+ cpio_file=$1
+ [ ! -z ${dep_list} ] && echo "$1"
+ return 0
+ fi
+ if [ -z ${dep_list} ]; then
+ print_mtime "$1" >> ${output}
+ cat "$1" >> ${output}
else
- # Failsafe in case directory is empty
- default_initramfs
+ cat "$1" | while read type dir file perm ; do
+ if [ "$type" == "file" ]; then
+ echo "$file \\";
+ fi
+ done
fi
+ elif [ -d "$1" ]; then
+ dir_filelist "$1"
else
- echo " $0: Cannot open '$cpio_source'" >&2
+ echo " ${prog}: Cannot open '$1'" >&2
exit 1
fi
}
-
+prog=$0
root_uid=0
root_gid=0
+dep_list=
+cpio_file=
+cpio_list=
+output="/dev/stdout"
+output_file=""
+arg="$1"
+case "$arg" in
+ "-l") # files included in initramfs - used by kbuild
+ dep_list="list_"
+ shift
+ ;;
+ "-o") # generate gzipped cpio image named $1
+ shift
+ output_file="$1"
+ cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
+ output=${cpio_list}
+ shift
+ ;;
+esac
while [ $# -gt 0 ]; do
arg="$1"
shift
case "$arg" in
- "-u")
+ "-u") # map $1 to uid=0 (root)
root_uid="$1"
shift
;;
- "-g")
+ "-g") # map $1 to gid=0 (root)
root_gid="$1"
shift
;;
- "-d")
+ "-d") # display default initramfs list
default_list="$arg"
- default_initramfs
+ ${dep_list}default_initramfs
;;
"-h")
usage
@@ -181,23 +260,27 @@ while [ $# -gt 0 ]; do
*)
case "$arg" in
"-"*)
- printf "ERROR: unknown option \"$arg\"\n" >&2
- printf "If the filename validly begins with '-', then it must be prefixed\n" >&2
- printf "by './' so that it won't be interpreted as an option." >&2
- printf "\n" >&2
- usage >&2
- exit 1
+ unknown_option
;;
- *)
- cpio_source="$arg"
- build_list
+ *) # input file/dir - process it
+ input_file "$arg" "$#"
;;
esac
;;
esac
done
-# spit out the default cpio list if a source hasn't been specified
-[ -z "$cpio_source" -a -z "$default_list" ] && default_initramfs
-
+# If output_file is set we will generate cpio archive and gzip it
+# we are carefull to delete tmp files
+if [ ! -z ${output_file} ]; then
+ if [ -z ${cpio_file} ]; then
+ cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
+ usr/gen_init_cpio ${cpio_list} > ${cpio_tfile}
+ else
+ cpio_tfile=${cpio_file}
+ fi
+ rm ${cpio_list}
+ cat ${cpio_tfile} | gzip -f -9 - > ${output_file}
+ [ -z ${cpio_file} ] && rm ${cpio_tfile}
+fi
exit 0
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 10eeae53d82..8012d107687 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -5,6 +5,7 @@
#include <ctype.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
@@ -63,20 +64,6 @@ static void check_stdin(void)
}
}
-static char *fgets_check_stream(char *s, int size, FILE *stream)
-{
- char *ret = fgets(s, size, stream);
-
- if (ret == NULL && feof(stream)) {
- printf(_("aborted!\n\n"));
- printf(_("Console input is closed. "));
- printf(_("Run 'make oldconfig' to update configuration.\n\n"));
- exit(1);
- }
-
- return ret;
-}
-
static void conf_askvalue(struct symbol *sym, const char *def)
{
enum symbol_type type = sym_get_type(sym);
@@ -114,7 +101,7 @@ static void conf_askvalue(struct symbol *sym, const char *def)
check_stdin();
case ask_all:
fflush(stdout);
- fgets_check_stream(line, 128, stdin);
+ fgets(line, 128, stdin);
return;
case set_default:
printf("%s\n", def);
@@ -328,8 +315,7 @@ static int conf_choice(struct menu *menu)
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
def_sym = sym_get_choice_value(sym);
cnt = def = 0;
- line[0] = '0';
- line[1] = 0;
+ line[0] = 0;
for (child = menu->list; child; child = child->next) {
if (!menu_is_visible(child))
continue;
@@ -370,7 +356,7 @@ static int conf_choice(struct menu *menu)
check_stdin();
case ask_all:
fflush(stdout);
- fgets_check_stream(line, 128, stdin);
+ fgets(line, 128, stdin);
strip(line);
if (line[0] == '?') {
printf("\n%s\n", menu->sym->help ?
@@ -546,7 +532,7 @@ int main(int ac, char **av)
break;
case 'h':
case '?':
- printf("%s [-o|-s] config\n", av[0]);
+ fprintf(stderr, "See README for usage info\n");
exit(0);
}
}
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 1b8882ddbc7..1b5df589f3a 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -325,7 +325,7 @@ int conf_read(const char *name)
sym->flags |= e->right.sym->flags & SYMBOL_NEW;
}
- sym_change_count = conf_warnings && conf_unsaved;
+ sym_change_count = conf_warnings || conf_unsaved;
return 0;
}
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
index db07ae73e05..be0200e9cda 100644
--- a/scripts/kconfig/lxdialog/checklist.c
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -196,8 +196,8 @@ int dialog_checklist(const char *title, const char *prompt, int height,
print_buttons(dialog, height, width, 0);
- wnoutrefresh(list);
wnoutrefresh(dialog);
+ wnoutrefresh(list);
doupdate();
while (key != ESC) {
@@ -225,12 +225,11 @@ int dialog_checklist(const char *title, const char *prompt, int height,
}
scroll--;
print_item(list, items[scroll * 3 + 1], status[scroll], 0, TRUE);
- wnoutrefresh(list);
-
print_arrows(dialog, choice, item_no,
scroll, box_y, box_x + check_x + 5, list_height);
- wrefresh(dialog);
+ wnoutrefresh(dialog);
+ wrefresh(list);
continue; /* wait for another key press */
} else
@@ -252,12 +251,12 @@ int dialog_checklist(const char *title, const char *prompt, int height,
scroll++;
print_item(list, items[(scroll + max_choice - 1) * 3 + 1],
status[scroll + max_choice - 1], max_choice - 1, TRUE);
- wnoutrefresh(list);
print_arrows(dialog, choice, item_no,
scroll, box_y, box_x + check_x + 5, list_height);
- wrefresh(dialog);
+ wnoutrefresh(dialog);
+ wrefresh(list);
continue; /* wait for another key press */
} else
@@ -271,8 +270,8 @@ int dialog_checklist(const char *title, const char *prompt, int height,
choice = i;
print_item(list, items[(scroll + choice) * 3 + 1],
status[scroll + choice], choice, TRUE);
- wnoutrefresh(list);
- wrefresh(dialog);
+ wnoutrefresh(dialog);
+ wrefresh(list);
}
continue; /* wait for another key press */
}
@@ -306,8 +305,8 @@ int dialog_checklist(const char *title, const char *prompt, int height,
print_item(list, items[(scroll + i) * 3 + 1],
status[scroll + i], i, i == choice);
}
- wnoutrefresh(list);
- wrefresh(dialog);
+ wnoutrefresh(dialog);
+ wrefresh(list);
for (i = 0; i < item_no; i++)
if (status[i])
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
index 09512b54437..bf8052f4fd4 100644
--- a/scripts/kconfig/lxdialog/menubox.c
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -58,8 +58,7 @@
#include "dialog.h"
-#define ITEM_IDENT 1 /* Indent of menu entries. Fixed for all menus */
-static int menu_width;
+static int menu_width, item_x;
/*
* Print menu item
@@ -70,7 +69,7 @@ static void do_print_item(WINDOW * win, const char *item, int choice,
int j;
char *menu_item = malloc(menu_width + 1);
- strncpy(menu_item, item, menu_width - ITEM_IDENT);
+ strncpy(menu_item, item, menu_width - item_x);
menu_item[menu_width] = 0;
j = first_alpha(menu_item, "YyNnMmHh");
@@ -87,13 +86,13 @@ static void do_print_item(WINDOW * win, const char *item, int choice,
wclrtoeol(win);
#endif
wattrset(win, selected ? item_selected_attr : item_attr);
- mvwaddstr(win, choice, ITEM_IDENT, menu_item);
+ mvwaddstr(win, choice, item_x, menu_item);
if (hotkey) {
wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
- mvwaddch(win, choice, ITEM_IDENT + j, menu_item[j]);
+ mvwaddch(win, choice, item_x + j, menu_item[j]);
}
if (selected) {
- wmove(win, choice, ITEM_IDENT + 1);
+ wmove(win, choice, item_x + 1);
}
free(menu_item);
wrefresh(win);
@@ -227,6 +226,8 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
menubox_border_attr, menubox_attr);
+ item_x = (menu_width - 70) / 2;
+
/* Set choice to default item */
for (i = 0; i < item_no; i++)
if (strcmp(current, items[i * 2]) == 0)
@@ -263,10 +264,10 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
wnoutrefresh(menu);
print_arrows(dialog, item_no, scroll,
- box_y, box_x + ITEM_IDENT + 1, menu_height);
+ box_y, box_x + item_x + 1, menu_height);
print_buttons(dialog, height, width, 0);
- wmove(menu, choice, ITEM_IDENT + 1);
+ wmove(menu, choice, item_x + 1);
wrefresh(menu);
while (key != ESC) {
@@ -349,7 +350,7 @@ int dialog_menu(const char *title, const char *prompt, int height, int width,
print_item(scroll + choice, choice, TRUE);
print_arrows(dialog, item_no, scroll,
- box_y, box_x + ITEM_IDENT + 1, menu_height);
+ box_y, box_x + item_x + 1, menu_height);
wnoutrefresh(dialog);
wrefresh(menu);
diff --git a/scripts/mkmakefile b/scripts/mkmakefile
index a22cbedd3b3..7f9d544f9b6 100644
--- a/scripts/mkmakefile
+++ b/scripts/mkmakefile
@@ -10,7 +10,10 @@
# $4 - patchlevel
-cat << EOF
+test ! -r $2/Makefile -o -O $2/Makefile || exit 0
+echo " GEN $2/Makefile"
+
+cat << EOF > $2/Makefile
# Automatically generated by $0: don't edit
VERSION = $3
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 84e21201f3c..37f67c23e11 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -374,10 +374,10 @@ static void do_input(char *alias,
kernel_ulong_t *arr, unsigned int min, unsigned int max)
{
unsigned int i;
- for (i = min; i < max; i++) {
- if (arr[i/BITS_PER_LONG] & (1 << (i%BITS_PER_LONG)))
- sprintf(alias+strlen(alias), "%X,*", i);
- }
+
+ for (i = min; i < max; i++)
+ if (arr[i / BITS_PER_LONG] & (1 << (i%BITS_PER_LONG)))
+ sprintf(alias + strlen(alias), "%X,*", i);
}
/* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
@@ -386,39 +386,37 @@ static int do_input_entry(const char *filename, struct input_device_id *id,
{
sprintf(alias, "input:");
- ADD(alias, "b", id->flags&INPUT_DEVICE_ID_MATCH_BUS, id->id.bustype);
- ADD(alias, "v", id->flags&INPUT_DEVICE_ID_MATCH_VENDOR, id->id.vendor);
- ADD(alias, "p", id->flags&INPUT_DEVICE_ID_MATCH_PRODUCT,
- id->id.product);
- ADD(alias, "e", id->flags&INPUT_DEVICE_ID_MATCH_VERSION,
- id->id.version);
+ ADD(alias, "b", id->flags & INPUT_DEVICE_ID_MATCH_BUS, id->bustype);
+ ADD(alias, "v", id->flags & INPUT_DEVICE_ID_MATCH_VENDOR, id->vendor);
+ ADD(alias, "p", id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT, id->product);
+ ADD(alias, "e", id->flags & INPUT_DEVICE_ID_MATCH_VERSION, id->version);
sprintf(alias + strlen(alias), "-e*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_EVBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_EVBIT)
do_input(alias, id->evbit, 0, EV_MAX);
sprintf(alias + strlen(alias), "k*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_KEYBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
do_input(alias, id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
sprintf(alias + strlen(alias), "r*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_RELBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_RELBIT)
do_input(alias, id->relbit, 0, REL_MAX);
sprintf(alias + strlen(alias), "a*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_ABSBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
do_input(alias, id->absbit, 0, ABS_MAX);
sprintf(alias + strlen(alias), "m*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_MSCIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_MSCIT)
do_input(alias, id->mscbit, 0, MSC_MAX);
sprintf(alias + strlen(alias), "l*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_LEDBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
do_input(alias, id->ledbit, 0, LED_MAX);
sprintf(alias + strlen(alias), "s*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_SNDBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
do_input(alias, id->sndbit, 0, SND_MAX);
sprintf(alias + strlen(alias), "f*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_FFBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_FFBIT)
do_input(alias, id->ffbit, 0, FF_MAX);
sprintf(alias + strlen(alias), "w*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_SWBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_SWBIT)
do_input(alias, id->swbit, 0, SW_MAX);
return 1;
}
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 0b92ddff26f..d0f86ed43f7 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -487,22 +487,24 @@ static int strrcmp(const char *s, const char *sub)
* atsym =__param*
*
* Pattern 2:
- * Many drivers utilise a *_driver container with references to
+ * Many drivers utilise a *driver container with references to
* add, remove, probe functions etc.
* These functions may often be marked __init and we do not want to
* warn here.
* the pattern is identified by:
- * tosec = .init.text | .exit.text
+ * tosec = .init.text | .exit.text | .init.data
* fromsec = .data
- * atsym = *_driver, *_ops, *_probe, *probe_one
+ * atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one
**/
static int secref_whitelist(const char *tosec, const char *fromsec,
- const char *atsym)
+ const char *atsym)
{
int f1 = 1, f2 = 1;
const char **s;
const char *pat2sym[] = {
- "_driver",
+ "driver",
+ "_template", /* scsi uses *_template a lot */
+ "_sht", /* scsi also used *_sht to some extent */
"_ops",
"_probe",
"_probe_one",
@@ -522,7 +524,8 @@ static int secref_whitelist(const char *tosec, const char *fromsec,
/* Check for pattern 2 */
if ((strcmp(tosec, ".init.text") != 0) &&
- (strcmp(tosec, ".exit.text") != 0))
+ (strcmp(tosec, ".exit.text") != 0) &&
+ (strcmp(tosec, ".init.data") != 0))
f2 = 0;
if (strcmp(fromsec, ".data") != 0)
f2 = 0;
@@ -658,7 +661,7 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
warn("%s - Section mismatch: reference to %s:%s from %s "
"before '%s' (at offset -0x%llx)\n",
modname, secname, refsymname, fromsec,
- elf->strtab + before->st_name,
+ elf->strtab + after->st_name,
(long long)r.r_offset);
} else {
warn("%s - Section mismatch: reference to %s:%s from %s "
@@ -694,29 +697,79 @@ static void check_sec_ref(struct module *mod, const char *modname,
/* Walk through all sections */
for (i = 0; i < hdr->e_shnum; i++) {
- Elf_Rela *rela;
- Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset;
- Elf_Rela *stop = (void*)start + sechdrs[i].sh_size;
- const char *name = secstrings + sechdrs[i].sh_name +
- strlen(".rela");
+ const char *name = secstrings + sechdrs[i].sh_name;
+ const char *secname;
+ Elf_Rela r;
+ unsigned int r_sym;
/* We want to process only relocation sections and not .init */
- if (section_ref_ok(name) || (sechdrs[i].sh_type != SHT_RELA))
- continue;
+ if (sechdrs[i].sh_type == SHT_RELA) {
+ Elf_Rela *rela;
+ Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset;
+ Elf_Rela *stop = (void*)start + sechdrs[i].sh_size;
+ name += strlen(".rela");
+ if (section_ref_ok(name))
+ continue;
- for (rela = start; rela < stop; rela++) {
- Elf_Rela r;
- const char *secname;
- r.r_offset = TO_NATIVE(rela->r_offset);
- r.r_info = TO_NATIVE(rela->r_info);
- r.r_addend = TO_NATIVE(rela->r_addend);
- sym = elf->symtab_start + ELF_R_SYM(r.r_info);
- /* Skip special sections */
- if (sym->st_shndx >= SHN_LORESERVE)
+ for (rela = start; rela < stop; rela++) {
+ r.r_offset = TO_NATIVE(rela->r_offset);
+#if KERNEL_ELFCLASS == ELFCLASS64
+ if (hdr->e_machine == EM_MIPS) {
+ r_sym = ELF64_MIPS_R_SYM(rela->r_info);
+ r_sym = TO_NATIVE(r_sym);
+ } else {
+ r.r_info = TO_NATIVE(rela->r_info);
+ r_sym = ELF_R_SYM(r.r_info);
+ }
+#else
+ r.r_info = TO_NATIVE(rela->r_info);
+ r_sym = ELF_R_SYM(r.r_info);
+#endif
+ r.r_addend = TO_NATIVE(rela->r_addend);
+ sym = elf->symtab_start + r_sym;
+ /* Skip special sections */
+ if (sym->st_shndx >= SHN_LORESERVE)
+ continue;
+
+ secname = secstrings +
+ sechdrs[sym->st_shndx].sh_name;
+ if (section(secname))
+ warn_sec_mismatch(modname, name,
+ elf, sym, r);
+ }
+ } else if (sechdrs[i].sh_type == SHT_REL) {
+ Elf_Rel *rel;
+ Elf_Rel *start = (void *)hdr + sechdrs[i].sh_offset;
+ Elf_Rel *stop = (void*)start + sechdrs[i].sh_size;
+ name += strlen(".rel");
+ if (section_ref_ok(name))
continue;
- secname = secstrings + sechdrs[sym->st_shndx].sh_name;
- if (section(secname))
- warn_sec_mismatch(modname, name, elf, sym, r);
+ for (rel = start; rel < stop; rel++) {
+ r.r_offset = TO_NATIVE(rel->r_offset);
+#if KERNEL_ELFCLASS == ELFCLASS64
+ if (hdr->e_machine == EM_MIPS) {
+ r_sym = ELF64_MIPS_R_SYM(rel->r_info);
+ r_sym = TO_NATIVE(r_sym);
+ } else {
+ r.r_info = TO_NATIVE(rel->r_info);
+ r_sym = ELF_R_SYM(r.r_info);
+ }
+#else
+ r.r_info = TO_NATIVE(rel->r_info);
+ r_sym = ELF_R_SYM(r.r_info);
+#endif
+ r.r_addend = 0;
+ sym = elf->symtab_start + r_sym;
+ /* Skip special sections */
+ if (sym->st_shndx >= SHN_LORESERVE)
+ continue;
+
+ secname = secstrings +
+ sechdrs[sym->st_shndx].sh_name;
+ if (section(secname))
+ warn_sec_mismatch(modname, name,
+ elf, sym, r);
+ }
}
}
}
@@ -820,6 +873,7 @@ static int exit_section(const char *name)
* For our future {in}sanity, add a comment that this is the ppc .opd
* section, not the ia64 .opd section.
* ia64 .opd should not point to discarded sections.
+ * [.rodata] like for .init.text we ignore .rodata references -same reason
**/
static int exit_section_ref_ok(const char *name)
{
@@ -829,6 +883,7 @@ static int exit_section_ref_ok(const char *name)
".exit.text",
".exit.data",
".init.text",
+ ".rodata",
".opd", /* See comment [OPD] */
".toc1", /* used by ppc64 */
".altinstructions",
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index b14255c72a3..861d866fcd8 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -21,6 +21,7 @@
#define ELF_ST_BIND ELF32_ST_BIND
#define ELF_ST_TYPE ELF32_ST_TYPE
+#define Elf_Rel Elf32_Rel
#define Elf_Rela Elf32_Rela
#define ELF_R_SYM ELF32_R_SYM
#define ELF_R_TYPE ELF32_R_TYPE
@@ -34,11 +35,31 @@
#define ELF_ST_BIND ELF64_ST_BIND
#define ELF_ST_TYPE ELF64_ST_TYPE
+#define Elf_Rel Elf64_Rel
#define Elf_Rela Elf64_Rela
#define ELF_R_SYM ELF64_R_SYM
#define ELF_R_TYPE ELF64_R_TYPE
#endif
+/* The 64-bit MIPS ELF ABI uses an unusual reloc format. */
+typedef struct
+{
+ Elf32_Word r_sym; /* Symbol index */
+ unsigned char r_ssym; /* Special symbol for 2nd relocation */
+ unsigned char r_type3; /* 3rd relocation type */
+ unsigned char r_type2; /* 2nd relocation type */
+ unsigned char r_type1; /* 1st relocation type */
+} _Elf64_Mips_R_Info;
+
+typedef union
+{
+ Elf64_Xword r_info_number;
+ _Elf64_Mips_R_Info r_info_fields;
+} _Elf64_Mips_R_Info_union;
+
+#define ELF64_MIPS_R_SYM(i) \
+ ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym)
+
#if KERNEL_ELFDATA != HOST_ELFDATA
static inline void __endian(const void *src, void *dest, unsigned int size)
@@ -48,8 +69,6 @@ static inline void __endian(const void *src, void *dest, unsigned int size)
((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1];
}
-
-
#define TO_NATIVE(x) \
({ \
typeof(x) __x; \
diff --git a/scripts/namespace.pl b/scripts/namespace.pl
index f34373853ef..f34373853ef 100644..100755
--- a/scripts/namespace.pl
+++ b/scripts/namespace.pl
diff --git a/scripts/show_delta b/scripts/show_delta
index 48a706ab3d0..48a706ab3d0 100644..100755
--- a/scripts/show_delta
+++ b/scripts/show_delta
diff --git a/scripts/ver_linux b/scripts/ver_linux
index beb43ef7f76..84999f69773 100755
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -39,10 +39,10 @@ tune2fs 2>&1 | grep "^tune2fs" | sed 's/,//' | awk \
fsck.jfs -V 2>&1 | grep version | sed 's/,//' | awk \
'NR==1 {print "jfsutils ", $3}'
-reiserfsck -V 2>&1 | grep reiserfsck | awk \
+reiserfsck -V 2>&1 | grep ^reiserfsck | awk \
'NR==1{print "reiserfsprogs ", $2}'
-fsck.reiser4 -V 2>&1 | grep fsck.reiser4 | awk \
+fsck.reiser4 -V 2>&1 | grep ^fsck.reiser4 | awk \
'NR==1{print "reiser4progs ", $2}'
xfs_db -V 2>&1 | grep version | awk \
diff --git a/security/dummy.c b/security/dummy.c
index fd99429278e..8ccccccc12a 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -563,11 +563,6 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
return 0;
}
-static int dummy_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
-{
- return -EOPNOTSUPP;
-}
-
static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
{
return 0;
@@ -976,7 +971,6 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, task_reparent_to_init);
set_to_dummy_if_null(ops, task_to_inode);
set_to_dummy_if_null(ops, ipc_permission);
- set_to_dummy_if_null(ops, ipc_getsecurity);
set_to_dummy_if_null(ops, msg_msg_alloc_security);
set_to_dummy_if_null(ops, msg_msg_free_security);
set_to_dummy_if_null(ops, msg_queue_alloc_security);
diff --git a/security/keys/key.c b/security/keys/key.c
index a057e3311aa..b6061fa29da 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -785,6 +785,10 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
key_check(keyring);
+ key_ref = ERR_PTR(-ENOTDIR);
+ if (keyring->type != &key_type_keyring)
+ goto error_2;
+
down_write(&keyring->sem);
/* if we're going to allocate a new key, we're going to have
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index d65a180f888..bffa924c1f8 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -437,6 +437,7 @@ EXPORT_SYMBOL(keyring_search);
/*
* search the given keyring only (no recursion)
* - keyring must be locked by caller
+ * - caller must guarantee that the keyring is a keyring
*/
key_ref_t __keyring_search_one(key_ref_t keyring_ref,
const struct key_type *ktype,
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index f6940618e34..217a0bef3c8 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -168,11 +168,12 @@ error:
*/
int install_process_keyring(struct task_struct *tsk)
{
- unsigned long flags;
struct key *keyring;
char buf[20];
int ret;
+ might_sleep();
+
if (!tsk->signal->process_keyring) {
sprintf(buf, "_pid.%u", tsk->tgid);
@@ -183,12 +184,12 @@ int install_process_keyring(struct task_struct *tsk)
}
/* attach keyring */
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ spin_lock_irq(&tsk->sighand->siglock);
if (!tsk->signal->process_keyring) {
tsk->signal->process_keyring = keyring;
keyring = NULL;
}
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ spin_unlock_irq(&tsk->sighand->siglock);
key_put(keyring);
}
@@ -207,38 +208,37 @@ error:
static int install_session_keyring(struct task_struct *tsk,
struct key *keyring)
{
- unsigned long flags;
struct key *old;
char buf[20];
- int ret;
+
+ might_sleep();
/* create an empty session keyring */
if (!keyring) {
sprintf(buf, "_ses.%u", tsk->tgid);
keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
- goto error;
- }
+ if (IS_ERR(keyring))
+ return PTR_ERR(keyring);
}
else {
atomic_inc(&keyring->usage);
}
/* install the keyring */
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
- old = rcu_dereference(tsk->signal->session_keyring);
+ spin_lock_irq(&tsk->sighand->siglock);
+ old = tsk->signal->session_keyring;
rcu_assign_pointer(tsk->signal->session_keyring, keyring);
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ spin_unlock_irq(&tsk->sighand->siglock);
- ret = 0;
+ /* we're using RCU on the pointer, but there's no point synchronising
+ * on it if it didn't previously point to anything */
+ if (old) {
+ synchronize_rcu();
+ key_put(old);
+ }
- /* we're using RCU on the pointer */
- synchronize_rcu();
- key_put(old);
-error:
- return ret;
+ return 0;
} /* end install_session_keyring() */
@@ -311,7 +311,6 @@ void exit_keys(struct task_struct *tsk)
*/
int exec_keys(struct task_struct *tsk)
{
- unsigned long flags;
struct key *old;
/* newly exec'd tasks don't get a thread keyring */
@@ -323,10 +322,10 @@ int exec_keys(struct task_struct *tsk)
key_put(old);
/* discard the process keyring from a newly exec'd task */
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ spin_lock_irq(&tsk->sighand->siglock);
old = tsk->signal->process_keyring;
tsk->signal->process_keyring = NULL;
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ spin_unlock_irq(&tsk->sighand->siglock);
key_put(old);
diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index 688c0a267b6..faf2e02e441 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -4,7 +4,7 @@
obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
-selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o
+selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o exports.o
selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index ac5d69bb337..a300702da52 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -800,7 +800,7 @@ out:
int avc_ss_reset(u32 seqno)
{
struct avc_callback_node *c;
- int i, rc = 0;
+ int i, rc = 0, tmprc;
unsigned long flag;
struct avc_node *node;
@@ -813,15 +813,16 @@ int avc_ss_reset(u32 seqno)
for (c = avc_callbacks; c; c = c->next) {
if (c->events & AVC_CALLBACK_RESET) {
- rc = c->callback(AVC_CALLBACK_RESET,
- 0, 0, 0, 0, NULL);
- if (rc)
- goto out;
+ tmprc = c->callback(AVC_CALLBACK_RESET,
+ 0, 0, 0, 0, NULL);
+ /* save the first error encountered for the return
+ value and continue processing the callbacks */
+ if (!rc)
+ rc = tmprc;
}
}
avc_latest_notif_update(seqno, 0);
-out:
return rc;
}
diff --git a/security/selinux/exports.c b/security/selinux/exports.c
new file mode 100644
index 00000000000..ae4c73eb308
--- /dev/null
+++ b/security/selinux/exports.c
@@ -0,0 +1,74 @@
+/*
+ * SELinux services exported to the rest of the kernel.
+ *
+ * Author: James Morris <jmorris@redhat.com>
+ *
+ * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ * Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ * Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/selinux.h>
+#include <linux/fs.h>
+#include <linux/ipc.h>
+
+#include "security.h"
+#include "objsec.h"
+
+void selinux_task_ctxid(struct task_struct *tsk, u32 *ctxid)
+{
+ struct task_security_struct *tsec = tsk->security;
+ if (selinux_enabled)
+ *ctxid = tsec->sid;
+ else
+ *ctxid = 0;
+}
+
+int selinux_ctxid_to_string(u32 ctxid, char **ctx, u32 *ctxlen)
+{
+ if (selinux_enabled)
+ return security_sid_to_context(ctxid, ctx, ctxlen);
+ else {
+ *ctx = NULL;
+ *ctxlen = 0;
+ }
+
+ return 0;
+}
+
+void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
+{
+ if (selinux_enabled) {
+ struct inode_security_struct *isec = inode->i_security;
+ *sid = isec->sid;
+ return;
+ }
+ *sid = 0;
+}
+
+void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
+{
+ if (selinux_enabled) {
+ struct ipc_security_struct *isec = ipcp->security;
+ *sid = isec->sid;
+ return;
+ }
+ *sid = 0;
+}
+
+void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
+{
+ if (selinux_enabled) {
+ struct task_security_struct *tsec = tsk->security;
+ *sid = tsec->sid;
+ return;
+ }
+ *sid = 0;
+}
+
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b61b9554bc2..90b4cdc0c94 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -101,6 +101,8 @@ static int __init selinux_enabled_setup(char *str)
return 1;
}
__setup("selinux=", selinux_enabled_setup);
+#else
+int selinux_enabled = 1;
#endif
/* Original (dummy) security module. */
@@ -3229,7 +3231,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
goto out;
/* Handle mapped IPv4 packets arriving via IPv6 sockets */
- if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
+ if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
family = PF_INET;
read_lock_bh(&sk->sk_callback_lock);
@@ -4052,13 +4054,6 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
return ipc_has_perm(ipcp, av);
}
-static int selinux_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
-{
- struct ipc_security_struct *isec = ipcp->security;
-
- return selinux_getsecurity(isec->sid, buffer, size);
-}
-
/* module stacking operations */
static int selinux_register_security (const char *name, struct security_operations *ops)
{
@@ -4321,7 +4316,6 @@ static struct security_operations selinux_ops = {
.task_to_inode = selinux_task_to_inode,
.ipc_permission = selinux_ipc_permission,
- .ipc_getsecurity = selinux_ipc_getsecurity,
.msg_msg_alloc_security = selinux_msg_msg_alloc_security,
.msg_msg_free_security = selinux_msg_msg_free_security,
@@ -4428,6 +4422,7 @@ void selinux_complete_init(void)
/* Set up any superblocks initialized prior to the policy load. */
printk(KERN_INFO "SELinux: Setting up existing superblocks.\n");
+ spin_lock(&sb_lock);
spin_lock(&sb_security_lock);
next_sb:
if (!list_empty(&superblock_security_head)) {
@@ -4436,19 +4431,20 @@ next_sb:
struct superblock_security_struct,
list);
struct super_block *sb = sbsec->sb;
- spin_lock(&sb_lock);
sb->s_count++;
- spin_unlock(&sb_lock);
spin_unlock(&sb_security_lock);
+ spin_unlock(&sb_lock);
down_read(&sb->s_umount);
if (sb->s_root)
superblock_doinit(sb, NULL);
drop_super(sb);
+ spin_lock(&sb_lock);
spin_lock(&sb_security_lock);
list_del_init(&sbsec->list);
goto next_sb;
}
spin_unlock(&sb_security_lock);
+ spin_unlock(&sb_lock);
}
/* SELinux requires early initialization in order to label
@@ -4543,6 +4539,7 @@ int selinux_disable(void)
printk(KERN_INFO "SELinux: Disabled at runtime.\n");
selinux_disabled = 1;
+ selinux_enabled = 0;
/* Reset security_ops to the secondary module, dummy or capability. */
security_ops = secondary_ops;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 5f016c98056..063af47bb23 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -29,12 +29,7 @@
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB
-#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
extern int selinux_enabled;
-#else
-#define selinux_enabled 1
-#endif
-
extern int selinux_mls_enabled;
int security_load_policy(void * data, size_t len);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 640d0bfdbc6..7bc5b6440f7 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -8,7 +8,7 @@
*
* Support for enhanced MLS infrastructure.
*
- * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
*/
#include <linux/kernel.h>
@@ -264,7 +264,7 @@ int mls_context_to_sid(char oldc,
if (!selinux_mls_enabled) {
if (def_sid != SECSID_NULL && oldc)
- *scontext += strlen(*scontext);
+ *scontext += strlen(*scontext)+1;
return 0;
}
@@ -385,6 +385,34 @@ out:
}
/*
+ * Set the MLS fields in the security context structure
+ * `context' based on the string representation in
+ * the string `str'. This function will allocate temporary memory with the
+ * given constraints of gfp_mask.
+ */
+int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
+{
+ char *tmpstr, *freestr;
+ int rc;
+
+ if (!selinux_mls_enabled)
+ return -EINVAL;
+
+ /* we need freestr because mls_context_to_sid will change
+ the value of tmpstr */
+ tmpstr = freestr = kstrdup(str, gfp_mask);
+ if (!tmpstr) {
+ rc = -ENOMEM;
+ } else {
+ rc = mls_context_to_sid(':', &tmpstr, context,
+ NULL, SECSID_NULL);
+ kfree(freestr);
+ }
+
+ return rc;
+}
+
+/*
* Copies the effective MLS range from `src' into `dst'.
*/
static inline int mls_scopy_context(struct context *dst,
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 03de697c805..fbb42f07dd7 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -8,7 +8,7 @@
*
* Support for enhanced MLS infrastructure.
*
- * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
*/
#ifndef _SS_MLS_H_
@@ -27,6 +27,8 @@ int mls_context_to_sid(char oldc,
struct sidtab *s,
u32 def_sid);
+int mls_from_string(char *str, struct context *context, gfp_t gfp_mask);
+
int mls_convert_context(struct policydb *oldp,
struct policydb *newp,
struct context *context);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 61492485de8..c284dbb8b8c 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -7,12 +7,13 @@
* Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
*
* Support for enhanced MLS infrastructure.
+ * Support for context based audit filters.
*
* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
*
* Added conditional policy language extensions
*
- * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
* This program is free software; you can redistribute it and/or modify
@@ -593,6 +594,10 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
*scontext_len = strlen(initial_sid_to_string[sid]) + 1;
scontextp = kmalloc(*scontext_len,GFP_ATOMIC);
+ if (!scontextp) {
+ rc = -ENOMEM;
+ goto out;
+ }
strcpy(scontextp, initial_sid_to_string[sid]);
*scontext = scontextp;
goto out;
@@ -1811,3 +1816,235 @@ out:
POLICY_RDUNLOCK;
return rc;
}
+
+struct selinux_audit_rule {
+ u32 au_seqno;
+ struct context au_ctxt;
+};
+
+void selinux_audit_rule_free(struct selinux_audit_rule *rule)
+{
+ if (rule) {
+ context_destroy(&rule->au_ctxt);
+ kfree(rule);
+ }
+}
+
+int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
+ struct selinux_audit_rule **rule)
+{
+ struct selinux_audit_rule *tmprule;
+ struct role_datum *roledatum;
+ struct type_datum *typedatum;
+ struct user_datum *userdatum;
+ int rc = 0;
+
+ *rule = NULL;
+
+ if (!ss_initialized)
+ return -ENOTSUPP;
+
+ switch (field) {
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ /* only 'equals' and 'not equals' fit user, role, and type */
+ if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL)
+ return -EINVAL;
+ break;
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ /* we do not allow a range, indicated by the presense of '-' */
+ if (strchr(rulestr, '-'))
+ return -EINVAL;
+ break;
+ default:
+ /* only the above fields are valid */
+ return -EINVAL;
+ }
+
+ tmprule = kzalloc(sizeof(struct selinux_audit_rule), GFP_KERNEL);
+ if (!tmprule)
+ return -ENOMEM;
+
+ context_init(&tmprule->au_ctxt);
+
+ POLICY_RDLOCK;
+
+ tmprule->au_seqno = latest_granting;
+
+ switch (field) {
+ case AUDIT_SE_USER:
+ userdatum = hashtab_search(policydb.p_users.table, rulestr);
+ if (!userdatum)
+ rc = -EINVAL;
+ else
+ tmprule->au_ctxt.user = userdatum->value;
+ break;
+ case AUDIT_SE_ROLE:
+ roledatum = hashtab_search(policydb.p_roles.table, rulestr);
+ if (!roledatum)
+ rc = -EINVAL;
+ else
+ tmprule->au_ctxt.role = roledatum->value;
+ break;
+ case AUDIT_SE_TYPE:
+ typedatum = hashtab_search(policydb.p_types.table, rulestr);
+ if (!typedatum)
+ rc = -EINVAL;
+ else
+ tmprule->au_ctxt.type = typedatum->value;
+ break;
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC);
+ break;
+ }
+
+ POLICY_RDUNLOCK;
+
+ if (rc) {
+ selinux_audit_rule_free(tmprule);
+ tmprule = NULL;
+ }
+
+ *rule = tmprule;
+
+ return rc;
+}
+
+int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
+ struct selinux_audit_rule *rule,
+ struct audit_context *actx)
+{
+ struct context *ctxt;
+ struct mls_level *level;
+ int match = 0;
+
+ if (!rule) {
+ audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ "selinux_audit_rule_match: missing rule\n");
+ return -ENOENT;
+ }
+
+ POLICY_RDLOCK;
+
+ if (rule->au_seqno < latest_granting) {
+ audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ "selinux_audit_rule_match: stale rule\n");
+ match = -ESTALE;
+ goto out;
+ }
+
+ ctxt = sidtab_search(&sidtab, ctxid);
+ if (!ctxt) {
+ audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ "selinux_audit_rule_match: unrecognized SID %d\n",
+ ctxid);
+ match = -ENOENT;
+ goto out;
+ }
+
+ /* a field/op pair that is not caught here will simply fall through
+ without a match */
+ switch (field) {
+ case AUDIT_SE_USER:
+ switch (op) {
+ case AUDIT_EQUAL:
+ match = (ctxt->user == rule->au_ctxt.user);
+ break;
+ case AUDIT_NOT_EQUAL:
+ match = (ctxt->user != rule->au_ctxt.user);
+ break;
+ }
+ break;
+ case AUDIT_SE_ROLE:
+ switch (op) {
+ case AUDIT_EQUAL:
+ match = (ctxt->role == rule->au_ctxt.role);
+ break;
+ case AUDIT_NOT_EQUAL:
+ match = (ctxt->role != rule->au_ctxt.role);
+ break;
+ }
+ break;
+ case AUDIT_SE_TYPE:
+ switch (op) {
+ case AUDIT_EQUAL:
+ match = (ctxt->type == rule->au_ctxt.type);
+ break;
+ case AUDIT_NOT_EQUAL:
+ match = (ctxt->type != rule->au_ctxt.type);
+ break;
+ }
+ break;
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ level = (op == AUDIT_SE_SEN ?
+ &ctxt->range.level[0] : &ctxt->range.level[1]);
+ switch (op) {
+ case AUDIT_EQUAL:
+ match = mls_level_eq(&rule->au_ctxt.range.level[0],
+ level);
+ break;
+ case AUDIT_NOT_EQUAL:
+ match = !mls_level_eq(&rule->au_ctxt.range.level[0],
+ level);
+ break;
+ case AUDIT_LESS_THAN:
+ match = (mls_level_dom(&rule->au_ctxt.range.level[0],
+ level) &&
+ !mls_level_eq(&rule->au_ctxt.range.level[0],
+ level));
+ break;
+ case AUDIT_LESS_THAN_OR_EQUAL:
+ match = mls_level_dom(&rule->au_ctxt.range.level[0],
+ level);
+ break;
+ case AUDIT_GREATER_THAN:
+ match = (mls_level_dom(level,
+ &rule->au_ctxt.range.level[0]) &&
+ !mls_level_eq(level,
+ &rule->au_ctxt.range.level[0]));
+ break;
+ case AUDIT_GREATER_THAN_OR_EQUAL:
+ match = mls_level_dom(level,
+ &rule->au_ctxt.range.level[0]);
+ break;
+ }
+ }
+
+out:
+ POLICY_RDUNLOCK;
+ return match;
+}
+
+static int (*aurule_callback)(void) = NULL;
+
+static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid,
+ u16 class, u32 perms, u32 *retained)
+{
+ int err = 0;
+
+ if (event == AVC_CALLBACK_RESET && aurule_callback)
+ err = aurule_callback();
+ return err;
+}
+
+static int __init aurule_init(void)
+{
+ int err;
+
+ err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET,
+ SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ if (err)
+ panic("avc_add_callback() failed, error %d\n", err);
+
+ return err;
+}
+__initcall(aurule_init);
+
+void selinux_audit_set_callback(int (*callback)(void))
+{
+ aurule_callback = callback;
+}
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index dfab6c88669..abe99d88137 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -281,7 +281,7 @@ u32 selinux_socket_getpeer_dgram(struct sk_buff *skb)
int i;
for (i = sp->len-1; i >= 0; i--) {
- struct xfrm_state *x = sp->x[i].xvec;
+ struct xfrm_state *x = sp->xvec[i];
if (selinux_authorizable_xfrm(x)) {
struct xfrm_sec_ctx *ctx = x->security;
return ctx->ctx_sid;
@@ -314,7 +314,7 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
* Only need to verify the existence of an authorizable sp.
*/
for (i = 0; i < sp->len; i++) {
- struct xfrm_state *x = sp->x[i].xvec;
+ struct xfrm_state *x = sp->xvec[i];
if (x && selinux_authorizable_xfrm(x))
goto accept;
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 9dd121bb563..4262a1c8773 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -92,8 +92,9 @@ config SND_SEQUENCER_OSS
Many programs still use the OSS API, so say Y.
- To compile this driver as a module, choose M here: the module
- will be called snd-seq-oss.
+ If you choose M in "Sequencer support" (SND_SEQUENCER),
+ this will be compiled as a module. The module will be called
+ snd-seq-oss.
config SND_RTCTIMER
tristate "RTC Timer support"
@@ -141,7 +142,7 @@ config SND_SUPPORT_OLD_API
config SND_VERBOSE_PROCFS
bool "Verbose procfs contents"
- depends on SND
+ depends on SND && PROC_FS
default y
help
Say Y here to include code for verbose procfs contents (provides
@@ -170,3 +171,13 @@ config SND_DEBUG_DETECT
help
Say Y here to enable extra-verbose log messages printed when
detecting devices.
+
+config SND_PCM_XRUN_DEBUG
+ bool "Enable PCM ring buffer overrun/underrun debugging"
+ default n
+ depends on SND_DEBUG && SND_VERBOSE_PROCFS
+ help
+ Say Y to enable the PCM ring buffer overrun/underrun debugging.
+ It is usually not required, but if you have trouble with
+ sound clicking when system is loaded, it may help to determine
+ the process or driver which causes the scheduling gaps.
diff --git a/sound/core/control.c b/sound/core/control.c
index 574745314e7..22565c9b960 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -664,7 +664,7 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
snd_power_lock(ctl->card);
- result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0, NULL);
+ result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
if (result >= 0)
result = snd_ctl_elem_info(ctl, &info);
snd_power_unlock(ctl->card);
@@ -718,7 +718,7 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
return -EFAULT;
}
snd_power_lock(card);
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result >= 0)
result = snd_ctl_elem_read(card, control);
snd_power_unlock(card);
@@ -783,7 +783,7 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
}
card = file->card;
snd_power_lock(card);
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result >= 0)
result = snd_ctl_elem_write(card, file, control);
snd_power_unlock(card);
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 84fef5084e1..3c0161bb5ba 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -109,7 +109,7 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
goto error;
snd_power_lock(ctl->card);
- err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0, NULL);
+ err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
if (err >= 0)
err = snd_ctl_elem_info(ctl, data);
snd_power_unlock(ctl->card);
@@ -294,7 +294,7 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card,
goto error;
snd_power_lock(card);
- err = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+ err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (err >= 0)
err = snd_ctl_elem_read(card, data);
snd_power_unlock(card);
@@ -320,7 +320,7 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
goto error;
snd_power_lock(card);
- err = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+ err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (err >= 0)
err = snd_ctl_elem_write(card, file, data);
snd_power_unlock(card);
diff --git a/sound/core/init.c b/sound/core/init.c
index ad68761abba..39ed2e5bb0a 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -223,7 +223,8 @@ int snd_card_disconnect(struct snd_card *card)
struct snd_monitor_file *mfile;
struct file *file;
struct snd_shutdown_f_ops *s_f_ops;
- struct file_operations *f_ops, *old_f_ops;
+ struct file_operations *f_ops;
+ const struct file_operations *old_f_ops;
int err;
spin_lock(&card->files_lock);
@@ -721,13 +722,12 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
* snd_power_wait - wait until the power-state is changed.
* @card: soundcard structure
* @power_state: expected power state
- * @file: file structure for the O_NONBLOCK check (optional)
*
* Waits until the power-state is changed.
*
* Note: the power lock must be active before call.
*/
-int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file *file)
+int snd_power_wait(struct snd_card *card, unsigned int power_state)
{
wait_queue_t wait;
int result = 0;
@@ -744,12 +744,6 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file
}
if (snd_power_get_state(card) == power_state)
break;
-#if 0 /* block all devices */
- if (file && (file->f_flags & O_NONBLOCK)) {
- result = -EAGAIN;
- break;
- }
-#endif
set_current_state(TASK_UNINTERRUPTIBLE);
snd_power_unlock(card);
schedule_timeout(30 * HZ);
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index f8302b703a3..ac990bf0b48 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -208,9 +208,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
oss_buffer_size = runtime->oss.mmap_bytes;
}
- if (substream->oss.setup &&
- substream->oss.setup->period_size > 16)
- oss_period_size = substream->oss.setup->period_size;
+ if (substream->oss.setup.period_size > 16)
+ oss_period_size = substream->oss.setup.period_size;
else if (runtime->oss.fragshift) {
oss_period_size = 1 << runtime->oss.fragshift;
if (oss_period_size > oss_buffer_size / 2)
@@ -252,10 +251,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
oss_periods = oss_buffer_size / oss_period_size;
- if (substream->oss.setup) {
- if (substream->oss.setup->periods > 1)
- oss_periods = substream->oss.setup->periods;
- }
+ if (substream->oss.setup.periods > 1)
+ oss_periods = substream->oss.setup.periods;
s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL);
if (runtime->oss.maxfrags && s > runtime->oss.maxfrags)
@@ -341,12 +338,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
goto failure;
}
- if (atomic_read(&runtime->mmap_count)) {
+ if (atomic_read(&runtime->mmap_count))
direct = 1;
- } else {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- direct = (setup != NULL && setup->direct);
- }
+ else
+ direct = substream->oss.setup.direct;
_snd_pcm_hw_params_any(sparams);
_snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS);
@@ -482,7 +477,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
1 : runtime->period_size;
sw_params->xfer_align = 1;
if (atomic_read(&runtime->mmap_count) ||
- (substream->oss.setup && substream->oss.setup->nosilence)) {
+ substream->oss.setup.nosilence) {
sw_params->silence_threshold = 0;
sw_params->silence_size = 0;
} else {
@@ -843,7 +838,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
buf += tmp;
bytes -= tmp;
xfer += tmp;
- if ((substream->oss.setup != NULL && substream->oss.setup->partialfrag) ||
+ if (substream->oss.setup.partialfrag ||
runtime->oss.buffer_used == runtime->oss.period_bytes) {
tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr,
runtime->oss.buffer_used - runtime->oss.period_ptr, 1);
@@ -959,12 +954,12 @@ static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file)
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (substream != NULL) {
- snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+ snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
substream->runtime->oss.prepare = 1;
}
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
if (substream != NULL) {
- snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+ snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
substream->runtime->oss.prepare = 1;
}
return 0;
@@ -979,7 +974,7 @@ static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file)
if (substream != NULL) {
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
return err;
- snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
+ snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
}
/* note: all errors from the start action are ignored */
/* OSS apps do not know, how to handle them */
@@ -1108,7 +1103,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
__direct:
saved_f_flags = substream->ffile->f_flags;
substream->ffile->f_flags &= ~O_NONBLOCK;
- err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
substream->ffile->f_flags = saved_f_flags;
if (err < 0)
return err;
@@ -1120,7 +1115,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
return err;
runtime = substream->runtime;
- err = snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
if (err < 0)
return err;
runtime->oss.buffer_used = 0;
@@ -1214,12 +1209,10 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
return err;
- if (atomic_read(&substream->runtime->mmap_count)) {
+ if (atomic_read(&substream->runtime->mmap_count))
direct = 1;
- } else {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- direct = (setup != NULL && setup->direct);
- }
+ else
+ direct = substream->oss.setup.direct;
if (!direct)
return AFMT_MU_LAW | AFMT_U8 |
AFMT_S16_LE | AFMT_S16_BE |
@@ -1249,6 +1242,8 @@ static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int for
if (format != AFMT_QUERY) {
formats = snd_pcm_oss_get_formats(pcm_oss_file);
+ if (formats < 0)
+ return formats;
if (!(formats & format))
format = AFMT_U8;
for (idx = 1; idx >= 0; --idx) {
@@ -1437,7 +1432,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
cmd = SNDRV_PCM_IOCTL_DROP;
runtime->oss.prepare = 1;
}
- err = snd_pcm_kernel_playback_ioctl(psubstream, cmd, NULL);
+ err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);
if (err < 0)
return err;
}
@@ -1458,7 +1453,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
cmd = SNDRV_PCM_IOCTL_DROP;
runtime->oss.prepare = 1;
}
- err = snd_pcm_kernel_capture_ioctl(csubstream, cmd, NULL);
+ err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);
if (err < 0)
return err;
}
@@ -1495,7 +1490,7 @@ static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file)
runtime = substream->runtime;
if (runtime->oss.params || runtime->oss.prepare)
return 0;
- err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
if (err == -EPIPE)
delay = 0; /* hack for broken OSS applications */
else if (err < 0)
@@ -1555,8 +1550,7 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream
} else {
delay = snd_pcm_oss_bytes(substream, delay);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- if (setup && setup->buggyptr)
+ if (substream->oss.setup.buggyptr)
info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
else
info.blocks = (delay + fixup) / runtime->oss.period_bytes;
@@ -1638,37 +1632,46 @@ static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int str
return -EINVAL;
}
-static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, const char *task_name)
+static const char *strip_task_path(const char *path)
{
- const char *ptr, *ptrl;
- struct snd_pcm_oss_setup *setup;
-
- mutex_lock(&pcm->streams[stream].oss.setup_mutex);
- for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
- if (!strcmp(setup->task_name, task_name)) {
- mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
- return setup;
- }
- }
- ptr = ptrl = task_name;
- while (*ptr) {
+ const char *ptr, *ptrl = NULL;
+ for (ptr = path; *ptr; ptr++) {
if (*ptr == '/')
ptrl = ptr + 1;
- ptr++;
}
- if (ptrl == task_name) {
- goto __not_found;
- return NULL;
- }
- for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
- if (!strcmp(setup->task_name, ptrl)) {
- mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
- return setup;
+ return ptrl;
+}
+
+static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream,
+ const char *task_name,
+ struct snd_pcm_oss_setup *rsetup)
+{
+ struct snd_pcm_oss_setup *setup;
+
+ mutex_lock(&pcm->streams[stream].oss.setup_mutex);
+ do {
+ for (setup = pcm->streams[stream].oss.setup_list; setup;
+ setup = setup->next) {
+ if (!strcmp(setup->task_name, task_name))
+ goto out;
}
- }
- __not_found:
+ } while ((task_name = strip_task_path(task_name)) != NULL);
+ out:
+ if (setup)
+ *rsetup = *setup;
mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
- return NULL;
+}
+
+static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime;
+ runtime = substream->runtime;
+ vfree(runtime->oss.buffer);
+ runtime->oss.buffer = NULL;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+ snd_pcm_oss_plugin_clear(substream);
+#endif
+ substream->oss.oss = 0;
}
static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
@@ -1678,7 +1681,11 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime;
substream->oss.oss = 1;
- substream->oss.setup = setup;
+ substream->oss.setup = *setup;
+ if (setup->nonblock)
+ substream->ffile->f_flags |= O_NONBLOCK;
+ else if (setup->block)
+ substream->ffile->f_flags &= ~O_NONBLOCK;
runtime = substream->runtime;
runtime->oss.params = 1;
runtime->oss.trigger = 1;
@@ -1697,18 +1704,7 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
runtime->oss.fragshift = 0;
runtime->oss.maxfrags = 0;
runtime->oss.subdivision = 0;
-}
-
-static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime;
- runtime = substream->runtime;
- vfree(runtime->oss.buffer);
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
- snd_pcm_oss_plugin_clear(substream);
-#endif
- substream->oss.file = NULL;
- substream->oss.oss = 0;
+ substream->pcm_release = snd_pcm_oss_release_substream;
}
static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
@@ -1717,23 +1713,8 @@ static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
snd_assert(pcm_oss_file != NULL, return -ENXIO);
for (cidx = 0; cidx < 2; ++cidx) {
struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
- struct snd_pcm_runtime *runtime;
- if (substream == NULL)
- continue;
- runtime = substream->runtime;
-
- snd_pcm_stream_lock_irq(substream);
- if (snd_pcm_running(substream))
- snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
- snd_pcm_stream_unlock_irq(substream);
- if (substream->ffile != NULL) {
- if (substream->ops->hw_free != NULL)
- substream->ops->hw_free(substream);
- substream->ops->close(substream);
- substream->ffile = NULL;
- }
- snd_pcm_oss_release_substream(substream);
- snd_pcm_release_substream(substream);
+ if (substream)
+ snd_pcm_release_substream(substream);
}
kfree(pcm_oss_file);
return 0;
@@ -1743,12 +1724,11 @@ static int snd_pcm_oss_open_file(struct file *file,
struct snd_pcm *pcm,
struct snd_pcm_oss_file **rpcm_oss_file,
int minor,
- struct snd_pcm_oss_setup *psetup,
- struct snd_pcm_oss_setup *csetup)
+ struct snd_pcm_oss_setup *setup)
{
- int err = 0;
+ int idx, err;
struct snd_pcm_oss_file *pcm_oss_file;
- struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
+ struct snd_pcm_substream *substream;
unsigned int f_mode = file->f_mode;
snd_assert(rpcm_oss_file != NULL, return -EINVAL);
@@ -1761,73 +1741,32 @@ static int snd_pcm_oss_open_file(struct file *file,
if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
f_mode = FMODE_WRITE;
- if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) {
- if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- &psubstream)) < 0) {
+
+ for (idx = 0; idx < 2; idx++) {
+ if (setup[idx].disable)
+ continue;
+ if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (! (f_mode & FMODE_WRITE))
+ continue;
+ } else {
+ if (! (f_mode & FMODE_READ))
+ continue;
+ }
+ err = snd_pcm_open_substream(pcm, idx, file, &substream);
+ if (err < 0) {
snd_pcm_oss_release_file(pcm_oss_file);
return err;
}
- pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream;
- }
- if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) {
- if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE,
- &csubstream)) < 0) {
- if (!(f_mode & FMODE_WRITE) || err != -ENODEV) {
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- } else {
- csubstream = NULL;
- }
- }
- pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE] = csubstream;
+
+ pcm_oss_file->streams[idx] = substream;
+ substream->file = pcm_oss_file;
+ snd_pcm_oss_init_substream(substream, &setup[idx], minor);
}
- if (psubstream == NULL && csubstream == NULL) {
+ if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) {
snd_pcm_oss_release_file(pcm_oss_file);
return -EINVAL;
}
- if (psubstream != NULL) {
- psubstream->oss.file = pcm_oss_file;
- err = snd_pcm_hw_constraints_init(psubstream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraint_init failed\n");
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
- if ((err = psubstream->ops->open(psubstream)) < 0) {
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
- psubstream->ffile = file;
- err = snd_pcm_hw_constraints_complete(psubstream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraint_complete failed\n");
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
- snd_pcm_oss_init_substream(psubstream, psetup, minor);
- }
- if (csubstream != NULL) {
- csubstream->oss.file = pcm_oss_file;
- err = snd_pcm_hw_constraints_init(csubstream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraint_init failed\n");
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
- if ((err = csubstream->ops->open(csubstream)) < 0) {
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
- csubstream->ffile = file;
- err = snd_pcm_hw_constraints_complete(csubstream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraint_complete failed\n");
- snd_pcm_oss_release_file(pcm_oss_file);
- return err;
- }
- snd_pcm_oss_init_substream(csubstream, csetup, minor);
- }
file->private_data = pcm_oss_file;
*rpcm_oss_file = pcm_oss_file;
@@ -1852,7 +1791,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
char task_name[32];
struct snd_pcm *pcm;
struct snd_pcm_oss_file *pcm_oss_file;
- struct snd_pcm_oss_setup *psetup = NULL, *csetup = NULL;
+ struct snd_pcm_oss_setup setup[2];
int nonblock;
wait_queue_t wait;
@@ -1873,23 +1812,15 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
err = -EFAULT;
goto __error;
}
+ memset(setup, 0, sizeof(setup));
if (file->f_mode & FMODE_WRITE)
- psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);
+ snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ task_name, &setup[0]);
if (file->f_mode & FMODE_READ)
- csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);
+ snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ task_name, &setup[1]);
nonblock = !!(file->f_flags & O_NONBLOCK);
- if (psetup && !psetup->disable) {
- if (psetup->nonblock)
- nonblock = 1;
- else if (psetup->block)
- nonblock = 0;
- } else if (csetup && !csetup->disable) {
- if (csetup->nonblock)
- nonblock = 1;
- else if (csetup->block)
- nonblock = 0;
- }
if (!nonblock)
nonblock = nonblock_open;
@@ -1898,7 +1829,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
mutex_lock(&pcm->open_mutex);
while (1) {
err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
- iminor(inode), psetup, csetup);
+ iminor(inode), setup);
if (err >= 0)
break;
if (err == -EAGAIN) {
@@ -2283,7 +2214,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
return 0;
}
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SND_VERBOSE_PROCFS
/*
* /proc interface
*/
@@ -2312,13 +2243,8 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr)
{
- unsigned int idx;
- struct snd_pcm_substream *substream;
struct snd_pcm_oss_setup *setup, *setupn;
- for (idx = 0, substream = pstr->substream;
- idx < pstr->substream_count; idx++, substream = substream->next)
- substream->oss.setup = NULL;
for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL;
setup; setup = setupn) {
setupn = setup->next;
@@ -2379,21 +2305,28 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
}
} while (*str);
if (setup == NULL) {
- setup = kmalloc(sizeof(struct snd_pcm_oss_setup), GFP_KERNEL);
- if (setup) {
- if (pstr->oss.setup_list == NULL) {
- pstr->oss.setup_list = setup;
- } else {
- for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next);
- setup1->next = setup;
- }
- template.task_name = kstrdup(task_name, GFP_KERNEL);
- } else {
+ setup = kmalloc(sizeof(*setup), GFP_KERNEL);
+ if (! setup) {
+ buffer->error = -ENOMEM;
+ mutex_lock(&pstr->oss.setup_mutex);
+ return;
+ }
+ if (pstr->oss.setup_list == NULL)
+ pstr->oss.setup_list = setup;
+ else {
+ for (setup1 = pstr->oss.setup_list;
+ setup1->next; setup1 = setup1->next);
+ setup1->next = setup;
+ }
+ template.task_name = kstrdup(task_name, GFP_KERNEL);
+ if (! template.task_name) {
+ kfree(setup);
buffer->error = -ENOMEM;
+ mutex_lock(&pstr->oss.setup_mutex);
+ return;
}
}
- if (setup)
- *setup = template;
+ *setup = template;
mutex_unlock(&pstr->oss.setup_mutex);
}
}
@@ -2435,10 +2368,10 @@ static void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
}
}
}
-#else /* !CONFIG_PROC_FS */
+#else /* !CONFIG_SND_VERBOSE_PROCFS */
#define snd_pcm_oss_proc_init(pcm)
#define snd_pcm_oss_proc_done(pcm)
-#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_SND_VERBOSE_PROCFS */
/*
* ENTRY functions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 3da6a38c2d0..84b00038236 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -142,7 +142,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
return -ENOIOCTLCMD;
}
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SND_VERBOSE_PROCFS)
+#ifdef CONFIG_SND_VERBOSE_PROCFS
#define STATE(v) [SNDRV_PCM_STATE_##v] = #v
#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v
@@ -196,7 +196,7 @@ static char *snd_pcm_format_names[] = {
FORMAT(U18_3BE),
};
-const char *snd_pcm_format_name(snd_pcm_format_t format)
+static const char *snd_pcm_format_name(snd_pcm_format_t format)
{
return snd_pcm_format_names[format];
}
@@ -436,7 +436,7 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr);
}
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
@@ -480,7 +480,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
}
pstr->proc_info_entry = entry;
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
pstr->proc_root)) != NULL) {
entry->c.text.read_size = 64;
@@ -501,7 +501,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr)
{
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if (pstr->proc_xrun_debug_entry) {
snd_info_unregister(pstr->proc_xrun_debug_entry);
pstr->proc_xrun_debug_entry = NULL;
@@ -599,12 +599,12 @@ static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream)
}
return 0;
}
-#else /* !CONFIG_PROC_FS */
+#else /* !CONFIG_SND_VERBOSE_PROCFS */
static inline int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) { return 0; }
static inline int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { return 0; }
static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) { return 0; }
static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; }
-#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_SND_VERBOSE_PROCFS */
/**
* snd_pcm_new_stream - create a new PCM stream
@@ -777,8 +777,9 @@ static void snd_pcm_tick_timer_func(unsigned long data)
snd_pcm_tick_elapsed(substream);
}
-int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
- struct snd_pcm_substream **rsubstream)
+int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
+ struct file *file,
+ struct snd_pcm_substream **rsubstream)
{
struct snd_pcm_str * pstr;
struct snd_pcm_substream *substream;
@@ -793,7 +794,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
*rsubstream = NULL;
snd_assert(pcm != NULL, return -ENXIO);
pstr = &pcm->streams[stream];
- if (pstr->substream == NULL)
+ if (pstr->substream == NULL || pstr->substream_count == 0)
return -ENODEV;
card = pcm->card;
@@ -807,8 +808,6 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
}
up_read(&card->controls_rwsem);
- if (pstr->substream_count == 0)
- return -ENODEV;
switch (stream) {
case SNDRV_PCM_STREAM_PLAYBACK:
if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
@@ -874,12 +873,13 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
substream->runtime = runtime;
substream->private_data = pcm->private_data;
+ substream->ffile = file;
pstr->substream_opened++;
*rsubstream = substream;
return 0;
}
-void snd_pcm_release_substream(struct snd_pcm_substream *substream)
+void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime;
substream->file = NULL;
@@ -1111,8 +1111,6 @@ EXPORT_SYMBOL(snd_pcm_link_rwlock);
EXPORT_SYMBOL(snd_pcm_suspend);
EXPORT_SYMBOL(snd_pcm_suspend_all);
#endif
-EXPORT_SYMBOL(snd_pcm_kernel_playback_ioctl);
-EXPORT_SYMBOL(snd_pcm_kernel_capture_ioctl);
EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
EXPORT_SYMBOL(snd_pcm_mmap_data);
#if SNDRV_PCM_INFO_MMAP_IOMEM
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index eeba2f06095..eedc6cb038b 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -130,7 +130,7 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
static void xrun(struct snd_pcm_substream *substream)
{
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if (substream->pstr->xrun_debug) {
snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n",
substream->pcm->card->number,
@@ -204,7 +204,7 @@ static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *subs
delta = hw_ptr_interrupt - new_hw_ptr;
if (delta > 0) {
if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if (runtime->periods > 1 && substream->pstr->xrun_debug) {
snd_printd(KERN_ERR "Unexpected hw_pointer value [1] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
if (substream->pstr->xrun_debug > 1)
@@ -249,7 +249,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
delta = old_hw_ptr - new_hw_ptr;
if (delta > 0) {
if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if (runtime->periods > 2 && substream->pstr->xrun_debug) {
snd_printd(KERN_ERR "Unexpected hw_pointer value [2] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
if (substream->pstr->xrun_debug > 1)
@@ -2299,19 +2299,7 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
- snd_assert(substream->ffile != NULL, return -ENXIO);
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- if (substream->oss.oss) {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- if (setup != NULL) {
- if (setup->nonblock)
- nonblock = 1;
- else if (setup->block)
- nonblock = 0;
- }
- }
-#endif
if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
runtime->channels > 1)
@@ -2374,19 +2362,7 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
- snd_assert(substream->ffile != NULL, return -ENXIO);
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- if (substream->oss.oss) {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- if (setup != NULL) {
- if (setup->nonblock)
- nonblock = 1;
- else if (setup->block)
- nonblock = 0;
- }
- }
-#endif
if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
return -EINVAL;
@@ -2596,19 +2572,7 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
- snd_assert(substream->ffile != NULL, return -ENXIO);
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- if (substream->oss.oss) {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- if (setup != NULL) {
- if (setup->nonblock)
- nonblock = 1;
- else if (setup->block)
- nonblock = 0;
- }
- }
-#endif
if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
return -EINVAL;
return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
@@ -2665,20 +2629,7 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
- snd_assert(substream->ffile != NULL, return -ENXIO);
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- if (substream->oss.oss) {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- if (setup != NULL) {
- if (setup->nonblock)
- nonblock = 1;
- else if (setup->block)
- nonblock = 0;
- }
- }
-#endif
-
if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
return -EINVAL;
return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index a0119ae67dc..428f8c169ee 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -100,8 +100,10 @@ static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream
int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
{
snd_pcm_lib_preallocate_dma_free(substream);
+#ifdef CONFIG_SND_VERBOSE_PROCFS
snd_info_unregister(substream->proc_prealloc_entry);
substream->proc_prealloc_entry = NULL;
+#endif
return 0;
}
@@ -124,7 +126,7 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
return 0;
}
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SND_VERBOSE_PROCFS
/*
* read callback for prealloc proc file
*
@@ -203,9 +205,9 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
substream->proc_prealloc_entry = entry;
}
-#else /* !CONFIG_PROC_FS */
+#else /* !CONFIG_SND_VERBOSE_PROCFS */
#define preallocate_info_init(s)
-#endif
+#endif /* CONFIG_SND_VERBOSE_PROCFS */
/*
* pre-allocate the buffer and create a proc file for the substream
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 01f150f0990..0860c5a8450 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1170,7 +1170,7 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream)
int res;
snd_power_lock(card);
- if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
+ if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
snd_power_unlock(card);
return res;
@@ -1198,7 +1198,7 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream)
snd_power_lock(card);
if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result < 0)
goto _unlock;
}
@@ -1313,13 +1313,13 @@ static struct action_ops snd_pcm_action_prepare = {
*
* Prepare the PCM substream to be triggerable.
*/
-int snd_pcm_prepare(struct snd_pcm_substream *substream)
+static int snd_pcm_prepare(struct snd_pcm_substream *substream)
{
int res;
struct snd_card *card = substream->pcm->card;
snd_power_lock(card);
- if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
+ if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0);
snd_power_unlock(card);
return res;
@@ -1410,7 +1410,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
snd_power_lock(card);
if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result < 0) {
snd_power_unlock(card);
return result;
@@ -1533,7 +1533,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
snd_power_lock(card);
if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
if (result < 0)
goto _unlock;
}
@@ -1995,28 +1995,65 @@ static void snd_pcm_remove_file(struct snd_pcm_str *str,
}
}
-static int snd_pcm_release_file(struct snd_pcm_file * pcm_file)
+static void pcm_release_private(struct snd_pcm_substream *substream)
{
- struct snd_pcm_substream *substream;
- struct snd_pcm_runtime *runtime;
- struct snd_pcm_str * str;
+ struct snd_pcm_file *pcm_file = substream->file;
- snd_assert(pcm_file != NULL, return -ENXIO);
- substream = pcm_file->substream;
- snd_assert(substream != NULL, return -ENXIO);
- runtime = substream->runtime;
- str = substream->pstr;
snd_pcm_unlink(substream);
- if (substream->ffile != NULL) {
+ snd_pcm_remove_file(substream->pstr, pcm_file);
+ kfree(pcm_file);
+}
+
+void snd_pcm_release_substream(struct snd_pcm_substream *substream)
+{
+ snd_pcm_drop(substream);
+ if (substream->hw_opened) {
if (substream->ops->hw_free != NULL)
substream->ops->hw_free(substream);
substream->ops->close(substream);
- substream->ffile = NULL;
+ substream->hw_opened = 0;
}
- snd_pcm_remove_file(str, pcm_file);
- snd_pcm_release_substream(substream);
- kfree(pcm_file);
+ if (substream->pcm_release) {
+ substream->pcm_release(substream);
+ substream->pcm_release = NULL;
+ }
+ snd_pcm_detach_substream(substream);
+}
+
+int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
+ struct file *file,
+ struct snd_pcm_substream **rsubstream)
+{
+ struct snd_pcm_substream *substream;
+ int err;
+
+ err = snd_pcm_attach_substream(pcm, stream, file, &substream);
+ if (err < 0)
+ return err;
+ substream->no_mmap_ctrl = 0;
+ err = snd_pcm_hw_constraints_init(substream);
+ if (err < 0) {
+ snd_printd("snd_pcm_hw_constraints_init failed\n");
+ goto error;
+ }
+
+ if ((err = substream->ops->open(substream)) < 0)
+ goto error;
+
+ substream->hw_opened = 1;
+
+ err = snd_pcm_hw_constraints_complete(substream);
+ if (err < 0) {
+ snd_printd("snd_pcm_hw_constraints_complete failed\n");
+ goto error;
+ }
+
+ *rsubstream = substream;
return 0;
+
+ error:
+ snd_pcm_release_substream(substream);
+ return err;
}
static int snd_pcm_open_file(struct file *file,
@@ -2024,52 +2061,29 @@ static int snd_pcm_open_file(struct file *file,
int stream,
struct snd_pcm_file **rpcm_file)
{
- int err = 0;
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
struct snd_pcm_str *str;
+ int err;
snd_assert(rpcm_file != NULL, return -EINVAL);
*rpcm_file = NULL;
+ err = snd_pcm_open_substream(pcm, stream, file, &substream);
+ if (err < 0)
+ return err;
+
pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
if (pcm_file == NULL) {
+ snd_pcm_release_substream(substream);
return -ENOMEM;
}
-
- if ((err = snd_pcm_open_substream(pcm, stream, &substream)) < 0) {
- kfree(pcm_file);
- return err;
- }
-
str = substream->pstr;
substream->file = pcm_file;
- substream->no_mmap_ctrl = 0;
-
+ substream->pcm_release = pcm_release_private;
pcm_file->substream = substream;
-
snd_pcm_add_file(str, pcm_file);
- err = snd_pcm_hw_constraints_init(substream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraints_init failed\n");
- snd_pcm_release_file(pcm_file);
- return err;
- }
-
- if ((err = substream->ops->open(substream)) < 0) {
- snd_pcm_release_file(pcm_file);
- return err;
- }
- substream->ffile = file;
-
- err = snd_pcm_hw_constraints_complete(substream);
- if (err < 0) {
- snd_printd("snd_pcm_hw_constraints_complete failed\n");
- snd_pcm_release_file(pcm_file);
- return err;
- }
-
file->private_data = pcm_file;
*rpcm_file = pcm_file;
return 0;
@@ -2158,10 +2172,9 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
snd_assert(substream != NULL, return -ENXIO);
snd_assert(!atomic_read(&substream->runtime->mmap_count), );
pcm = substream->pcm;
- snd_pcm_drop(substream);
fasync_helper(-1, file, 0, &substream->runtime->fasync);
mutex_lock(&pcm->open_mutex);
- snd_pcm_release_file(pcm_file);
+ snd_pcm_release_substream(substream);
mutex_unlock(&pcm->open_mutex);
wake_up(&pcm->open_wait);
module_put(pcm->card->module);
@@ -2480,11 +2493,6 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
return 0;
}
-static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
- unsigned int cmd, void __user *arg);
-static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
- unsigned int cmd, void __user *arg);
-
static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
@@ -2736,41 +2744,28 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
}
-int snd_pcm_kernel_playback_ioctl(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
-{
- mm_segment_t fs;
- int result;
-
- fs = snd_enter_user();
- result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg);
- snd_leave_user(fs);
- return result;
-}
-
-int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
+int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg)
{
mm_segment_t fs;
int result;
fs = snd_enter_user();
- result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg);
- snd_leave_user(fs);
- return result;
-}
-
-int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
-{
switch (substream->stream) {
case SNDRV_PCM_STREAM_PLAYBACK:
- return snd_pcm_kernel_playback_ioctl(substream, cmd, arg);
+ result = snd_pcm_playback_ioctl1(substream,
+ cmd, (void __user *)arg);
+ break;
case SNDRV_PCM_STREAM_CAPTURE:
- return snd_pcm_kernel_capture_ioctl(substream, cmd, arg);
+ result = snd_pcm_capture_ioctl1(substream,
+ cmd, (void __user *)arg);
+ break;
default:
- return -EINVAL;
+ result = -EINVAL;
+ break;
}
+ snd_leave_user(fs);
+ return result;
}
static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 6b7a3677429..87b47c9564f 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -631,7 +631,8 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
return -EINVAL;
}
if (params->buffer_size != runtime->buffer_size) {
- if ((newbuf = (char *) kmalloc(params->buffer_size, GFP_KERNEL)) == NULL)
+ newbuf = kmalloc(params->buffer_size, GFP_KERNEL);
+ if (!newbuf)
return -ENOMEM;
kfree(runtime->buffer);
runtime->buffer = newbuf;
@@ -657,7 +658,8 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
return -EINVAL;
}
if (params->buffer_size != runtime->buffer_size) {
- if ((newbuf = (char *) kmalloc(params->buffer_size, GFP_KERNEL)) == NULL)
+ newbuf = kmalloc(params->buffer_size, GFP_KERNEL);
+ if (!newbuf)
return -ENOMEM;
kfree(runtime->buffer);
runtime->buffer = newbuf;
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 4d28e521261..108e430b503 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -137,7 +137,7 @@ static int snd_open(struct inode *inode, struct file *file)
{
unsigned int minor = iminor(inode);
struct snd_minor *mptr = NULL;
- struct file_operations *old_fops;
+ const struct file_operations *old_fops;
int err = 0;
if (minor >= ARRAY_SIZE(snd_minors))
@@ -240,7 +240,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
* Retrurns zero if successful, or a negative error code on failure.
*/
int snd_register_device(int type, struct snd_card *card, int dev,
- struct file_operations *f_ops, void *private_data,
+ const struct file_operations *f_ops, void *private_data,
const char *name)
{
int minor;
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index 4023d3b406d..9055c6de958 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -95,7 +95,7 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
}
int snd_register_oss_device(int type, struct snd_card *card, int dev,
- struct file_operations *f_ops, void *private_data,
+ const struct file_operations *f_ops, void *private_data,
const char *name)
{
int minor = snd_oss_kernel_minor(type, card, dev);
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index e35fd5779a9..ae0df549fac 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -675,10 +675,8 @@ static int __init alsa_card_dummy_init(void)
continue;
device = platform_device_register_simple(SND_DUMMY_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
- }
+ if (IS_ERR(device))
+ continue;
devices[i] = device;
cards++;
}
@@ -686,14 +684,10 @@ static int __init alsa_card_dummy_init(void)
#ifdef MODULE
printk(KERN_ERR "Dummy soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_dummy_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_dummy_unregister_all();
- return err;
}
static void __exit alsa_card_dummy_exit(void)
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index 9d10d79e27a..77b06009735 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -59,7 +59,8 @@ module_param_array(irq, int, NULL, 0444);
MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
static struct platform_device *platform_devices[SNDRV_CARDS];
-static int pnp_registered = 0;
+static int pnp_registered;
+static unsigned int snd_mpu401_devices;
static int snd_mpu401_create(int dev, struct snd_card **rcard)
{
@@ -150,7 +151,7 @@ static struct pnp_device_id snd_mpu401_pnpids[] = {
MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids);
-static int __init snd_mpu401_pnp(int dev, struct pnp_dev *device,
+static int __devinit snd_mpu401_pnp(int dev, struct pnp_dev *device,
const struct pnp_device_id *id)
{
if (!pnp_port_valid(device, 0) ||
@@ -197,6 +198,7 @@ static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
}
snd_card_set_dev(card, &pnp_dev->dev);
pnp_set_drvdata(pnp_dev, card);
+ snd_mpu401_devices++;
++dev;
return 0;
}
@@ -234,12 +236,11 @@ static void __init_or_module snd_mpu401_unregister_all(void)
static int __init alsa_card_mpu401_init(void)
{
- int i, err, devices;
+ int i, err;
if ((err = platform_driver_register(&snd_mpu401_driver)) < 0)
return err;
- devices = 0;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i])
@@ -250,30 +251,23 @@ static int __init alsa_card_mpu401_init(void)
#endif
device = platform_device_register_simple(SND_MPU401_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
- }
+ if (IS_ERR(device))
+ continue;
platform_devices[i] = device;
- devices++;
+ snd_mpu401_devices++;
}
- if ((err = pnp_register_driver(&snd_mpu401_pnp_driver)) >= 0) {
+ err = pnp_register_driver(&snd_mpu401_pnp_driver);
+ if (!err)
pnp_registered = 1;
- devices += err;
- }
- if (!devices) {
+ if (!snd_mpu401_devices) {
#ifdef MODULE
printk(KERN_ERR "MPU-401 device not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_mpu401_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_mpu401_unregister_all();
- return err;
}
static void __exit alsa_card_mpu401_exit(void)
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 8687ae3c66b..b49a45cbf67 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -183,7 +183,8 @@ static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input)
*/
-static void snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, int ack)
+static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
+ int ack)
{
unsigned long flags;
int timeout, ok;
@@ -218,9 +219,11 @@ static void snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, int
ok = 1;
}
spin_unlock_irqrestore(&mpu->input_lock, flags);
- if (! ok)
+ if (!ok) {
snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
- // snd_printk("cmd: 0x%x at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
+ return 1;
+ }
+ return 0;
}
/*
@@ -235,12 +238,19 @@ static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream)
if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
return err;
if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
- snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
- snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
+ if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
+ goto error_out;
+ if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+ goto error_out;
}
mpu->substream_input = substream;
set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
return 0;
+
+error_out:
+ if (mpu->open_input && mpu->close_input)
+ mpu->close_input(mpu);
+ return -EIO;
}
static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
@@ -252,39 +262,52 @@ static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
return err;
if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
- snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
- snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
+ if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
+ goto error_out;
+ if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+ goto error_out;
}
mpu->substream_output = substream;
set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
return 0;
+
+error_out:
+ if (mpu->open_output && mpu->close_output)
+ mpu->close_output(mpu);
+ return -EIO;
}
static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream)
{
struct snd_mpu401 *mpu;
+ int err = 0;
mpu = substream->rmidi->private_data;
clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
mpu->substream_input = NULL;
if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
- snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
+ err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
if (mpu->close_input)
mpu->close_input(mpu);
+ if (err)
+ return -EIO;
return 0;
}
static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream)
{
struct snd_mpu401 *mpu;
+ int err = 0;
mpu = substream->rmidi->private_data;
clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
mpu->substream_output = NULL;
if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
- snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
+ err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
if (mpu->close_output)
mpu->close_output(mpu);
+ if (err)
+ return -EIO;
return 0;
}
@@ -316,6 +339,7 @@ static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substrea
snd_mpu401_uart_remove_timer(mpu, 1);
clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
}
+
}
/*
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 1a7fbefe474..c01b4c5118b 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -996,10 +996,8 @@ static int __init alsa_card_serial_init(void)
continue;
device = platform_device_register_simple(SND_SERIAL_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
- }
+ if (IS_ERR(device))
+ continue;
devices[i] = device;
cards++;
}
@@ -1007,14 +1005,10 @@ static int __init alsa_card_serial_init(void)
#ifdef MODULE
printk(KERN_ERR "serial midi soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_serial_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_serial_unregister_all();
- return err;
}
static void __exit alsa_card_serial_exit(void)
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index a3ee306239c..26eb2499d44 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -169,10 +169,8 @@ static int __init alsa_card_virmidi_init(void)
continue;
device = platform_device_register_simple(SND_VIRMIDI_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
- }
+ if (IS_ERR(device))
+ continue;
devices[i] = device;
cards++;
}
@@ -180,14 +178,10 @@ static int __init alsa_card_virmidi_init(void)
#ifdef MODULE
printk(KERN_ERR "Card-VirMIDI soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_virmidi_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_virmidi_unregister_all();
- return err;
}
static void __exit alsa_card_virmidi_exit(void)
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index ff8fef93278..557c4de2296 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -11,6 +11,15 @@ config SND_CS4231_LIB
tristate
select SND_PCM
+config SND_ADLIB
+ tristate "AdLib FM card"
+ select SND_OPL3_LIB
+ help
+ Say Y here to include support for AdLib FM cards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-adlib.
+
config SND_AD1816A
tristate "Analog Devices SoundPort AD1816A"
depends on SND && PNP && ISA
@@ -292,6 +301,20 @@ config SND_OPTI93X
To compile this driver as a module, choose M here: the module
will be called snd-opti93x.
+config SND_MIRO
+ tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver"
+ depends on SND
+ select SND_OPL4_LIB
+ select SND_CS4231_LIB
+ select SND_MPU401_UART
+ select SND_PCM
+ help
+ Say 'Y' or 'M' to include support for Miro miroSOUND PCM1 pro,
+ miroSOUND PCM12 and miroSOUND PCM20 Radio soundcards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-miro.
+
config SND_SB8
tristate "Sound Blaster 1.0/2.0/Pro (8-bit)"
depends on SND
diff --git a/sound/isa/Makefile b/sound/isa/Makefile
index 05724eb7bfe..bb317ccc170 100644
--- a/sound/isa/Makefile
+++ b/sound/isa/Makefile
@@ -3,6 +3,7 @@
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
#
+snd-adlib-objs := adlib.o
snd-als100-objs := als100.o
snd-azt2320-objs := azt2320.o
snd-cmi8330-objs := cmi8330.o
@@ -13,6 +14,7 @@ snd-sgalaxy-objs := sgalaxy.o
snd-sscape-objs := sscape.o
# Toplevel Module Dependency
+obj-$(CONFIG_SND_ADLIB) += snd-adlib.o
obj-$(CONFIG_SND_ALS100) += snd-als100.o
obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o
obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index 7051f7798ed..31f299aed28 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -262,6 +262,8 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard
return 0;
}
+static unsigned int __devinitdata ad1816a_devices;
+
static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card,
const struct pnp_card_device_id *id)
{
@@ -275,6 +277,7 @@ static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card,
if (res < 0)
return res;
dev++;
+ ad1816a_devices++;
return 0;
}
return -ENODEV;
@@ -297,10 +300,13 @@ static struct pnp_card_driver ad1816a_pnpc_driver = {
static int __init alsa_card_ad1816a_init(void)
{
- int cards;
+ int err;
+
+ err = pnp_register_card_driver(&ad1816a_pnpc_driver);
+ if (err)
+ return err;
- cards = pnp_register_card_driver(&ad1816a_pnpc_driver);
- if (cards <= 0) {
+ if (!ad1816a_devices) {
pnp_unregister_card_driver(&ad1816a_pnpc_driver);
#ifdef MODULE
printk(KERN_ERR "no AD1816A based soundcards found.\n");
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 326a057f752..99908e44124 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -193,9 +193,11 @@ static int __init alsa_card_ad1848_init(void)
continue;
device = platform_device_register_simple(SND_AD1848_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -204,14 +206,10 @@ static int __init alsa_card_ad1848_init(void)
#ifdef MODULE
printk(KERN_ERR "AD1848 soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_ad1848_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_ad1848_unregister_all();
- return err;
}
static void __exit alsa_card_ad1848_exit(void)
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
new file mode 100644
index 00000000000..1124344ed94
--- /dev/null
+++ b/sound/isa/adlib.c
@@ -0,0 +1,164 @@
+/*
+ * AdLib FM card driver.
+ */
+
+#include <sound/driver.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/opl3.h>
+
+#define CRD_NAME "AdLib FM"
+#define DRV_NAME "snd_adlib"
+
+MODULE_DESCRIPTION(CRD_NAME);
+MODULE_AUTHOR("Rene Herman");
+MODULE_LICENSE("GPL");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
+static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
+module_param_array(port, long, NULL, 0444);
+MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
+
+static struct platform_device *devices[SNDRV_CARDS];
+
+static void snd_adlib_free(struct snd_card *card)
+{
+ release_and_free_resource(card->private_data);
+}
+
+static int __devinit snd_adlib_probe(struct platform_device *device)
+{
+ struct snd_card *card;
+ struct snd_opl3 *opl3;
+
+ int error, i = device->id;
+
+ if (port[i] == SNDRV_AUTO_PORT) {
+ snd_printk(KERN_ERR DRV_NAME ": please specify port\n");
+ error = -EINVAL;
+ goto out0;
+ }
+
+ card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
+ if (!card) {
+ snd_printk(KERN_ERR DRV_NAME ": could not create card\n");
+ error = -EINVAL;
+ goto out0;
+ }
+
+ card->private_data = request_region(port[i], 4, CRD_NAME);
+ if (!card->private_data) {
+ snd_printk(KERN_ERR DRV_NAME ": could not grab ports\n");
+ error = -EBUSY;
+ goto out1;
+ }
+ card->private_free = snd_adlib_free;
+
+ error = snd_opl3_create(card, port[i], port[i] + 2, OPL3_HW_AUTO, 1, &opl3);
+ if (error < 0) {
+ snd_printk(KERN_ERR DRV_NAME ": could not create OPL\n");
+ goto out1;
+ }
+
+ error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
+ if (error < 0) {
+ snd_printk(KERN_ERR DRV_NAME ": could not create FM\n");
+ goto out1;
+ }
+
+ strcpy(card->driver, DRV_NAME);
+ strcpy(card->shortname, CRD_NAME);
+ sprintf(card->longname, CRD_NAME " at %#lx", port[i]);
+
+ snd_card_set_dev(card, &device->dev);
+
+ error = snd_card_register(card);
+ if (error < 0) {
+ snd_printk(KERN_ERR DRV_NAME ": could not register card\n");
+ goto out1;
+ }
+
+ platform_set_drvdata(device, card);
+ return 0;
+
+out1: snd_card_free(card);
+out0: return error;
+}
+
+static int __devexit snd_adlib_remove(struct platform_device *device)
+{
+ snd_card_free(platform_get_drvdata(device));
+ platform_set_drvdata(device, NULL);
+ return 0;
+}
+
+static struct platform_driver snd_adlib_driver = {
+ .probe = snd_adlib_probe,
+ .remove = __devexit_p(snd_adlib_remove),
+
+ .driver = {
+ .name = DRV_NAME
+ }
+};
+
+static int __init alsa_card_adlib_init(void)
+{
+ int i, cards;
+
+ if (platform_driver_register(&snd_adlib_driver) < 0) {
+ snd_printk(KERN_ERR DRV_NAME ": could not register driver\n");
+ return -ENODEV;
+ }
+
+ for (cards = 0, i = 0; i < SNDRV_CARDS; i++) {
+ struct platform_device *device;
+
+ if (!enable[i])
+ continue;
+
+ device = platform_device_register_simple(DRV_NAME, i, NULL, 0);
+ if (IS_ERR(device))
+ continue;
+
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
+ }
+
+ devices[i] = device;
+ cards++;
+ }
+
+ if (!cards) {
+#ifdef MODULE
+ printk(KERN_ERR CRD_NAME " soundcard not found or device busy\n");
+#endif
+ platform_driver_unregister(&snd_adlib_driver);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static void __exit alsa_card_adlib_exit(void)
+{
+ int i;
+
+ for (i = 0; i < SNDRV_CARDS; i++)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_adlib_driver);
+}
+
+module_init(alsa_card_adlib_init);
+module_exit(alsa_card_adlib_exit);
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index 9b77c17b3f6..a52bd8a14c9 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -199,7 +199,7 @@ static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
return 0;
}
-static int __init snd_card_als100_probe(int dev,
+static int __devinit snd_card_als100_probe(int dev,
struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -281,6 +281,8 @@ static int __init snd_card_als100_probe(int dev,
return 0;
}
+static unsigned int __devinitdata als100_devices;
+
static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
const struct pnp_card_device_id *id)
{
@@ -294,6 +296,7 @@ static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
if (res < 0)
return res;
dev++;
+ als100_devices++;
return 0;
}
return -ENODEV;
@@ -345,10 +348,13 @@ static struct pnp_card_driver als100_pnpc_driver = {
static int __init alsa_card_als100_init(void)
{
- int cards;
+ int err;
+
+ err = pnp_register_card_driver(&als100_pnpc_driver);
+ if (err)
+ return err;
- cards = pnp_register_card_driver(&als100_pnpc_driver);
- if (cards <= 0) {
+ if (!als100_devices) {
pnp_unregister_card_driver(&als100_pnpc_driver);
#ifdef MODULE
snd_printk(KERN_ERR "no ALS100 based soundcards found\n");
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index a530691bf4f..15e59283aac 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -310,6 +310,8 @@ static int __devinit snd_card_azt2320_probe(int dev,
return 0;
}
+static unsigned int __devinitdata azt2320_devices;
+
static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
const struct pnp_card_device_id *id)
{
@@ -323,6 +325,7 @@ static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
if (res < 0)
return res;
dev++;
+ azt2320_devices++;
return 0;
}
return -ENODEV;
@@ -372,10 +375,13 @@ static struct pnp_card_driver azt2320_pnpc_driver = {
static int __init alsa_card_azt2320_init(void)
{
- int cards;
+ int err;
+
+ err = pnp_register_card_driver(&azt2320_pnpc_driver);
+ if (err)
+ return err;
- cards = pnp_register_card_driver(&azt2320_pnpc_driver);
- if (cards <= 0) {
+ if (!azt2320_devices) {
pnp_unregister_card_driver(&azt2320_pnpc_driver);
#ifdef MODULE
snd_printk(KERN_ERR "no AZT2320 based soundcards found\n");
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index fd9bb2575de..3c1e9fd56fe 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -175,7 +175,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids);
#endif
-static struct ad1848_mix_elem snd_cmi8330_controls[] __initdata = {
+static struct ad1848_mix_elem snd_cmi8330_controls[] __devinitdata = {
AD1848_DOUBLE("Master Playback Volume", 0, CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0),
AD1848_SINGLE("Loud Playback Switch", 0, CMI8330_MUTEMUX, 6, 1, 1),
AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1),
@@ -204,7 +204,7 @@ AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",PLAYBACK,SWITCH), 0, CMI8330_MUTEMU
};
#ifdef ENABLE_SB_MIXER
-static struct sbmix_elem cmi8330_sb_mixers[] __initdata = {
+static struct sbmix_elem cmi8330_sb_mixers[] __devinitdata = {
SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31),
SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15),
SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15),
@@ -222,7 +222,7 @@ SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6
SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
};
-static unsigned char cmi8330_sb_init_values[][2] __initdata = {
+static unsigned char cmi8330_sb_init_values[][2] __devinitdata = {
{ SB_DSP4_MASTER_DEV + 0, 0 },
{ SB_DSP4_MASTER_DEV + 1, 0 },
{ SB_DSP4_PCM_DEV + 0, 0 },
@@ -545,7 +545,7 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
return snd_card_register(card);
}
-static int __init snd_cmi8330_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_cmi8330_nonpnp_probe(struct platform_device *pdev)
{
struct snd_card *card;
int err;
@@ -607,6 +607,8 @@ static struct platform_driver snd_cmi8330_driver = {
#ifdef CONFIG_PNP
+static unsigned int __devinitdata cmi8330_pnp_devices;
+
static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -636,6 +638,7 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
}
pnp_set_card_drvdata(pcard, card);
dev++;
+ cmi8330_pnp_devices++;
return 0;
}
@@ -690,15 +693,17 @@ static int __init alsa_card_cmi8330_init(void)
if ((err = platform_driver_register(&snd_cmi8330_driver)) < 0)
return err;
- for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
- if (is_isapnp_selected(i))
+ if (! enable[i] || is_isapnp_selected(i))
continue;
device = platform_device_register_simple(CMI8330_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
cards++;
@@ -706,9 +711,9 @@ static int __init alsa_card_cmi8330_init(void)
#ifdef CONFIG_PNP
err = pnp_register_card_driver(&cmi8330_pnpc_driver);
- if (err >= 0) {
+ if (!err) {
pnp_registered = 1;
- cards += err;
+ cards += cmi8330_pnp_devices;
}
#endif
@@ -716,14 +721,10 @@ static int __init alsa_card_cmi8330_init(void)
#ifdef MODULE
snd_printk(KERN_ERR "CMI8330 not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_cmi8330_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_cmi8330_unregister_all();
- return err;
}
static void __exit alsa_card_cmi8330_exit(void)
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index a30dcd96252..397310f358b 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -209,9 +209,11 @@ static int __init alsa_card_cs4231_init(void)
continue;
device = platform_device_register_simple(SND_CS4231_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -220,14 +222,10 @@ static int __init alsa_card_cs4231_init(void)
#ifdef MODULE
printk(KERN_ERR "CS4231 soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_cs4231_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_cs4231_unregister_all();
- return err;
}
static void __exit alsa_card_cs4231_exit(void)
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 4060918e032..f7fa779347f 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -133,6 +133,7 @@ static int pnpc_registered;
static int pnp_registered;
#endif
#endif /* CONFIG_PNP */
+static unsigned int snd_cs423x_devices;
struct snd_card_cs4236 {
struct snd_cs4231 *chip;
@@ -564,7 +565,7 @@ static int __init snd_cs423x_nonpnp_probe(struct platform_device *pdev)
snd_card_free(card);
return err;
}
-
+
platform_set_drvdata(pdev, card);
return 0;
}
@@ -650,6 +651,7 @@ static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev,
}
pnp_set_drvdata(pdev, card);
dev++;
+ snd_cs423x_devices++;
return 0;
}
@@ -713,6 +715,7 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
}
pnp_set_card_drvdata(pcard, card);
dev++;
+ snd_cs423x_devices++;
return 0;
}
@@ -721,7 +724,7 @@ static void __devexit snd_cs423x_pnpc_remove(struct pnp_card_link * pcard)
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
}
-
+
#ifdef CONFIG_PM
static int snd_cs423x_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state)
{
@@ -766,7 +769,7 @@ static void __init_or_module snd_cs423x_unregister_all(void)
static int __init alsa_card_cs423x_init(void)
{
- int i, err, cards = 0;
+ int i, err;
if ((err = platform_driver_register(&cs423x_nonpnp_driver)) < 0)
return err;
@@ -777,40 +780,34 @@ static int __init alsa_card_cs423x_init(void)
continue;
device = platform_device_register_simple(CS423X_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
- cards++;
+ snd_cs423x_devices++;
}
#ifdef CONFIG_PNP
#ifdef CS4232
- i = pnp_register_driver(&cs4232_pnp_driver);
- if (i >= 0) {
+ err = pnp_register_driver(&cs4232_pnp_driver);
+ if (!err)
pnp_registered = 1;
- cards += i;
- }
#endif
- i = pnp_register_card_driver(&cs423x_pnpc_driver);
- if (i >= 0) {
+ err = pnp_register_card_driver(&cs423x_pnpc_driver);
+ if (!err)
pnpc_registered = 1;
- cards += i;
- }
#endif /* CONFIG_PNP */
- if (!cards) {
+ if (!snd_cs423x_devices) {
#ifdef MODULE
printk(KERN_ERR IDENT " soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_cs423x_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_cs423x_unregister_all();
- return err;
}
static void __exit alsa_card_cs423x_exit(void)
diff --git a/sound/isa/dt019x.c b/sound/isa/dt019x.c
index 50e7bc5ef56..0acb4e5da47 100644
--- a/sound/isa/dt019x.c
+++ b/sound/isa/dt019x.c
@@ -272,6 +272,8 @@ static int __devinit snd_card_dt019x_probe(int dev, struct pnp_card_link *pcard,
return 0;
}
+static unsigned int __devinitdata dt019x_devices;
+
static int __devinit snd_dt019x_pnp_probe(struct pnp_card_link *card,
const struct pnp_card_device_id *pid)
{
@@ -285,6 +287,7 @@ static int __devinit snd_dt019x_pnp_probe(struct pnp_card_link *card,
if (res < 0)
return res;
dev++;
+ dt019x_devices++;
return 0;
}
return -ENODEV;
@@ -336,10 +339,13 @@ static struct pnp_card_driver dt019x_pnpc_driver = {
static int __init alsa_card_dt019x_init(void)
{
- int cards = 0;
+ int err;
+
+ err = pnp_register_card_driver(&dt019x_pnpc_driver);
+ if (err)
+ return err;
- cards = pnp_register_card_driver(&dt019x_pnpc_driver);
- if (cards <= 0) {
+ if (!dt019x_devices) {
pnp_unregister_card_driver(&dt019x_pnpc_driver);
#ifdef MODULE
snd_printk(KERN_ERR "no DT-019X / ALS-007 based soundcards found\n");
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 2b69fc82926..e90689ee162 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -213,9 +213,11 @@ static int __init alsa_card_es1688_init(void)
continue;
device = platform_device_register_simple(ES1688_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -224,14 +226,10 @@ static int __init alsa_card_es1688_init(void)
#ifdef MODULE
printk(KERN_ERR "ESS AudioDrive ES1688 soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_es1688_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_es1688_unregister_all();
- return err;
}
static void __exit alsa_card_es1688_exit(void)
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 721955d2619..e6945db8ed1 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -85,6 +85,8 @@
#include <linux/pnp.h>
#include <linux/isapnp.h>
#include <linux/moduleparam.h>
+#include <linux/delay.h>
+
#include <asm/io.h>
#include <asm/dma.h>
#include <sound/core.h>
@@ -2204,7 +2206,7 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
return snd_card_register(card);
}
-static int __init snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devptr)
+static int __devinit snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devptr)
{
struct snd_card *card;
int err;
@@ -2221,7 +2223,7 @@ static int __init snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devp
return 0;
}
-static int __init snd_es18xx_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev)
{
int dev = pdev->id;
int err;
@@ -2297,6 +2299,8 @@ static struct platform_driver snd_es18xx_nonpnp_driver = {
#ifdef CONFIG_PNP
+static unsigned int __devinitdata es18xx_pnp_devices;
+
static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -2327,6 +2331,7 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard,
pnp_set_card_drvdata(pcard, card);
dev++;
+ es18xx_pnp_devices++;
return 0;
}
@@ -2388,19 +2393,21 @@ static int __init alsa_card_es18xx_init(void)
continue;
device = platform_device_register_simple(ES18XX_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
cards++;
}
#ifdef CONFIG_PNP
- i = pnp_register_card_driver(&es18xx_pnpc_driver);
- if (i >= 0) {
+ err = pnp_register_card_driver(&es18xx_pnpc_driver);
+ if (!err) {
pnp_registered = 1;
- cards += i;
+ cards += es18xx_pnp_devices;
}
#endif
@@ -2408,14 +2415,10 @@ static int __init alsa_card_es18xx_init(void)
#ifdef MODULE
snd_printk(KERN_ERR "ESS AudioDrive ES18xx soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_es18xx_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_es18xx_unregister_all();
- return err;
}
static void __exit alsa_card_es18xx_exit(void)
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index 26dccfea243..37057a37dc3 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -253,9 +253,11 @@ static int __init alsa_card_gusclassic_init(void)
continue;
device = platform_device_register_simple(GUSCLASSIC_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -264,14 +266,10 @@ static int __init alsa_card_gusclassic_init(void)
#ifdef MODULE
printk(KERN_ERR "GUS Classic soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_gusclassic_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_gusclassic_unregister_all();
- return err;
}
static void __exit alsa_card_gusclassic_exit(void)
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index 31dc20501d0..05852fcc613 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -363,9 +363,11 @@ static int __init alsa_card_gusextreme_init(void)
continue;
device = platform_device_register_simple(GUSEXTREME_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -374,14 +376,10 @@ static int __init alsa_card_gusextreme_init(void)
#ifdef MODULE
printk(KERN_ERR "GUS Extreme soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_gusextreme_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_gusextreme_unregister_all();
- return err;
}
static void __exit alsa_card_gusextreme_exit(void)
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index cafb9b67fa7..fcf2c8fe6f9 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -390,9 +390,11 @@ static int __init alsa_card_gusmax_init(void)
continue;
device = platform_device_register_simple(GUSMAX_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -401,14 +403,10 @@ static int __init alsa_card_gusmax_init(void)
#ifdef MODULE
printk(KERN_ERR "GUS MAX soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_gusmax_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_gusmax_unregister_all();
- return err;
}
static void __exit alsa_card_gusmax_exit(void)
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 2cacd0fa687..4298d339e78 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -791,7 +791,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
return 0;
}
-static int __init snd_interwave_nonpnp_probe1(int dev, struct platform_device *devptr)
+static int __devinit snd_interwave_nonpnp_probe1(int dev, struct platform_device *devptr)
{
struct snd_card *card;
int err;
@@ -809,7 +809,7 @@ static int __init snd_interwave_nonpnp_probe1(int dev, struct platform_device *d
return 0;
}
-static int __init snd_interwave_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev)
{
int dev = pdev->id;
int err;
@@ -867,6 +867,7 @@ static struct platform_driver snd_interwave_driver = {
};
#ifdef CONFIG_PNP
+static unsigned int __devinitdata interwave_pnp_devices;
static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
@@ -897,6 +898,7 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
}
pnp_set_card_drvdata(pcard, card);
dev++;
+ interwave_pnp_devices++;
return 0;
}
@@ -945,33 +947,31 @@ static int __init alsa_card_interwave_init(void)
#endif
device = platform_device_register_simple(INTERWAVE_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
cards++;
}
/* ISA PnP cards */
- i = pnp_register_card_driver(&interwave_pnpc_driver);
- if (i >= 0) {
+ err = pnp_register_card_driver(&interwave_pnpc_driver);
+ if (!err) {
pnp_registered = 1;
- cards += i;
+ cards += interwave_pnp_devices;;
}
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "InterWave soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_interwave_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_interwave_unregister_all();
- return err;
}
static void __exit alsa_card_interwave_exit(void)
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 56fcd8a946a..6d889052c32 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -95,6 +95,7 @@ static struct platform_device *platform_devices[SNDRV_CARDS];
static int pnp_registered;
static int pnpc_registered;
#endif
+static unsigned int snd_opl3sa2_devices;
/* control ports */
#define OPL3SA2_PM_CTRL 0x01
@@ -760,6 +761,7 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
}
pnp_set_drvdata(pdev, card);
dev++;
+ snd_opl3sa2_devices++;
return 0;
}
@@ -826,6 +828,7 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
}
pnp_set_card_drvdata(pcard, card);
dev++;
+ snd_opl3sa2_devices++;
return 0;
}
@@ -944,7 +947,7 @@ static void __init_or_module snd_opl3sa2_unregister_all(void)
static int __init alsa_card_opl3sa2_init(void)
{
- int i, err, cards = 0;
+ int i, err;
if ((err = platform_driver_register(&snd_opl3sa2_nonpnp_driver)) < 0)
return err;
@@ -959,39 +962,33 @@ static int __init alsa_card_opl3sa2_init(void)
#endif
device = platform_device_register_simple(OPL3SA2_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
- cards++;
+ snd_opl3sa2_devices++;
}
#ifdef CONFIG_PNP
err = pnp_register_driver(&opl3sa2_pnp_driver);
- if (err >= 0) {
+ if (!err)
pnp_registered = 1;
- cards += err;
- }
err = pnp_register_card_driver(&opl3sa2_pnpc_driver);
- if (err >= 0) {
+ if (!err)
pnpc_registered = 1;
- cards += err;
- }
#endif
- if (!cards) {
+ if (!snd_opl3sa2_devices) {
#ifdef MODULE
snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_opl3sa2_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_opl3sa2_unregister_all();
- return err;
}
static void __exit alsa_card_opl3sa2_exit(void)
diff --git a/sound/isa/opti9xx/Makefile b/sound/isa/opti9xx/Makefile
index 28c64070cd5..0e41bfd5a40 100644
--- a/sound/isa/opti9xx/Makefile
+++ b/sound/isa/opti9xx/Makefile
@@ -6,8 +6,10 @@
snd-opti92x-ad1848-objs := opti92x-ad1848.o
snd-opti92x-cs4231-objs := opti92x-cs4231.o
snd-opti93x-objs := opti93x.o
+snd-miro-objs := miro.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-opti92x-ad1848.o
obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-opti92x-cs4231.o
obj-$(CONFIG_SND_OPTI93X) += snd-opti93x.o
+obj-$(CONFIG_SND_MIRO) += snd-miro.o
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
new file mode 100644
index 00000000000..e6bfcf74c1c
--- /dev/null
+++ b/sound/isa/opti9xx/miro.c
@@ -0,0 +1,1455 @@
+/*
+ * ALSA soundcard driver for Miro miroSOUND PCM1 pro
+ * miroSOUND PCM12
+ * miroSOUND PCM20 Radio
+ *
+ * Copyright (C) 2004-2005 Martin Langer <martin-langer@gmx.de>
+ *
+ * Based on OSS ACI and ALSA OPTi9xx drivers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/moduleparam.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/cs4231.h>
+#include <sound/mpu401.h>
+#include <sound/opl4.h>
+#include <sound/control.h>
+#include <sound/info.h>
+#define SNDRV_LEGACY_FIND_FREE_IRQ
+#define SNDRV_LEGACY_FIND_FREE_DMA
+#include <sound/initval.h>
+#include "miro.h"
+
+MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Miro miroSOUND PCM1 pro, PCM12, PCM20 Radio");
+MODULE_SUPPORTED_DEVICE("{{Miro,miroSOUND PCM1 pro}, "
+ "{Miro,miroSOUND PCM12}, "
+ "{Miro,miroSOUND PCM20 Radio}}");
+
+static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
+static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
+static long port = SNDRV_DEFAULT_PORT1; /* 0x530,0xe80,0xf40,0x604 */
+static long mpu_port = SNDRV_DEFAULT_PORT1; /* 0x300,0x310,0x320,0x330 */
+static long fm_port = SNDRV_DEFAULT_PORT1; /* 0x388 */
+static int irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10,11 */
+static int mpu_irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10 */
+static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
+static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
+static int wss;
+static int ide;
+
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "Index value for miro soundcard.");
+module_param(id, charp, 0444);
+MODULE_PARM_DESC(id, "ID string for miro soundcard.");
+module_param(port, long, 0444);
+MODULE_PARM_DESC(port, "WSS port # for miro driver.");
+module_param(mpu_port, long, 0444);
+MODULE_PARM_DESC(mpu_port, "MPU-401 port # for miro driver.");
+module_param(fm_port, long, 0444);
+MODULE_PARM_DESC(fm_port, "FM Port # for miro driver.");
+module_param(irq, int, 0444);
+MODULE_PARM_DESC(irq, "WSS irq # for miro driver.");
+module_param(mpu_irq, int, 0444);
+MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for miro driver.");
+module_param(dma1, int, 0444);
+MODULE_PARM_DESC(dma1, "1st dma # for miro driver.");
+module_param(dma2, int, 0444);
+MODULE_PARM_DESC(dma2, "2nd dma # for miro driver.");
+module_param(wss, int, 0444);
+MODULE_PARM_DESC(wss, "wss mode");
+module_param(ide, int, 0444);
+MODULE_PARM_DESC(ide, "enable ide port");
+
+#define OPTi9XX_HW_DETECT 0
+#define OPTi9XX_HW_82C928 1
+#define OPTi9XX_HW_82C929 2
+#define OPTi9XX_HW_82C924 3
+#define OPTi9XX_HW_82C925 4
+#define OPTi9XX_HW_82C930 5
+#define OPTi9XX_HW_82C931 6
+#define OPTi9XX_HW_82C933 7
+#define OPTi9XX_HW_LAST OPTi9XX_HW_82C933
+
+#define OPTi9XX_MC_REG(n) n
+
+
+struct snd_miro {
+ unsigned short hardware;
+ unsigned char password;
+ char name[7];
+
+ struct resource *res_mc_base;
+ struct resource *res_aci_port;
+
+ unsigned long mc_base;
+ unsigned long mc_base_size;
+ unsigned long pwd_reg;
+
+ spinlock_t lock;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+
+ long wss_base;
+ int irq;
+ int dma1;
+ int dma2;
+
+ long fm_port;
+
+ long mpu_port;
+ int mpu_irq;
+
+ unsigned long aci_port;
+ int aci_vendor;
+ int aci_product;
+ int aci_version;
+ int aci_amp;
+ int aci_preamp;
+ int aci_solomode;
+
+ struct mutex aci_mutex;
+};
+
+static void snd_miro_proc_init(struct snd_miro * miro);
+
+#define DRIVER_NAME "snd-miro"
+
+static struct platform_device *device;
+
+static char * snd_opti9xx_names[] = {
+ "unkown",
+ "82C928", "82C929",
+ "82C924", "82C925",
+ "82C930", "82C931", "82C933"
+};
+
+/*
+ * ACI control
+ */
+
+static int aci_busy_wait(struct snd_miro * miro)
+{
+ long timeout;
+ unsigned char byte;
+
+ for (timeout = 1; timeout <= ACI_MINTIME+30; timeout++) {
+ if (((byte=inb(miro->aci_port + ACI_REG_BUSY)) & 1) == 0) {
+ if (timeout >= ACI_MINTIME)
+ snd_printd("aci ready in round %ld.\n",
+ timeout-ACI_MINTIME);
+ return byte;
+ }
+ if (timeout >= ACI_MINTIME) {
+ long out=10*HZ;
+ switch (timeout-ACI_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;
+ }
+ }
+ }
+ snd_printk(KERN_ERR "aci_busy_wait() time out\n");
+ return -EBUSY;
+}
+
+static inline int aci_write(struct snd_miro * miro, unsigned char byte)
+{
+ if (aci_busy_wait(miro) >= 0) {
+ outb(byte, miro->aci_port + ACI_REG_COMMAND);
+ return 0;
+ } else {
+ snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte);
+ return -EBUSY;
+ }
+}
+
+static inline int aci_read(struct snd_miro * miro)
+{
+ unsigned char byte;
+
+ if (aci_busy_wait(miro) >= 0) {
+ byte=inb(miro->aci_port + ACI_REG_STATUS);
+ return byte;
+ } else {
+ snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n");
+ return -EBUSY;
+ }
+}
+
+static int aci_cmd(struct snd_miro * miro, int write1, int write2, int write3)
+{
+ int write[] = {write1, write2, write3};
+ int value, i;
+
+ if (mutex_lock_interruptible(&miro->aci_mutex))
+ return -EINTR;
+
+ for (i=0; i<3; i++) {
+ if (write[i]< 0 || write[i] > 255)
+ break;
+ else {
+ value = aci_write(miro, write[i]);
+ if (value < 0)
+ goto out;
+ }
+ }
+
+ value = aci_read(miro);
+
+out: mutex_unlock(&miro->aci_mutex);
+ return value;
+}
+
+static int aci_getvalue(struct snd_miro * miro, unsigned char index)
+{
+ return aci_cmd(miro, ACI_STATUS, index, -1);
+}
+
+static int aci_setvalue(struct snd_miro * miro, unsigned char index, int value)
+{
+ return aci_cmd(miro, index, value, -1);
+}
+
+/*
+ * MIXER part
+ */
+
+static int snd_miro_info_capture(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+
+ return 0;
+}
+
+static int snd_miro_get_capture(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int value;
+
+ if ((value = aci_getvalue(miro, ACI_S_GENERAL)) < 0) {
+ snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n", value);
+ return value;
+ }
+
+ ucontrol->value.integer.value[0] = value & 0x20;
+
+ return 0;
+}
+
+static int snd_miro_put_capture(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int change, value, error;
+
+ value = !(ucontrol->value.integer.value[0]);
+
+ if ((error = aci_setvalue(miro, ACI_SET_SOLOMODE, value)) < 0) {
+ snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n", error);
+ return error;
+ }
+
+ change = (value != miro->aci_solomode);
+ miro->aci_solomode = value;
+
+ return change;
+}
+
+static int snd_miro_info_preamp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 3;
+
+ return 0;
+}
+
+static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int value;
+
+ if (miro->aci_version <= 176) {
+
+ /*
+ OSS says it's not readable with versions < 176.
+ But it doesn't work on my card,
+ which is a PCM12 with aci_version = 176.
+ */
+
+ ucontrol->value.integer.value[0] = miro->aci_preamp;
+ return 0;
+ }
+
+ if ((value = aci_getvalue(miro, ACI_GET_PREAMP)) < 0) {
+ snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n", value);
+ return value;
+ }
+
+ ucontrol->value.integer.value[0] = value;
+
+ return 0;
+}
+
+static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int error, value, change;
+
+ value = ucontrol->value.integer.value[0];
+
+ if ((error = aci_setvalue(miro, ACI_SET_PREAMP, value)) < 0) {
+ snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n", error);
+ return error;
+ }
+
+ change = (value != miro->aci_preamp);
+ miro->aci_preamp = value;
+
+ return change;
+}
+
+static int snd_miro_info_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+
+ return 0;
+}
+
+static int snd_miro_get_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = miro->aci_amp;
+
+ return 0;
+}
+
+static int snd_miro_put_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int error, value, change;
+
+ value = ucontrol->value.integer.value[0];
+
+ if ((error = aci_setvalue(miro, ACI_SET_POWERAMP, value)) < 0) {
+ snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error);
+ return error;
+ }
+
+ change = (value != miro->aci_amp);
+ miro->aci_amp = value;
+
+ return change;
+}
+
+#define MIRO_DOUBLE(ctl_name, ctl_index, get_right_reg, set_right_reg) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = ctl_name, \
+ .index = ctl_index, \
+ .info = snd_miro_info_double, \
+ .get = snd_miro_get_double, \
+ .put = snd_miro_put_double, \
+ .private_value = get_right_reg | (set_right_reg << 8) \
+}
+
+static int snd_miro_info_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ int reg = kcontrol->private_value & 0xff;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+
+ if ((reg >= ACI_GET_EQ1) && (reg <= ACI_GET_EQ7)) {
+
+ /* equalizer elements */
+
+ uinfo->value.integer.min = - 0x7f;
+ uinfo->value.integer.max = 0x7f;
+ } else {
+
+ /* non-equalizer elements */
+
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0x20;
+ }
+
+ return 0;
+}
+
+static int snd_miro_get_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uinfo)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int left_val, right_val;
+
+ int right_reg = kcontrol->private_value & 0xff;
+ int left_reg = right_reg + 1;
+
+ if ((right_val = aci_getvalue(miro, right_reg)) < 0) {
+ snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val);
+ return right_val;
+ }
+
+ if ((left_val = aci_getvalue(miro, left_reg)) < 0) {
+ snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val);
+ return left_val;
+ }
+
+ if ((right_reg >= ACI_GET_EQ1) && (right_reg <= ACI_GET_EQ7)) {
+
+ /* equalizer elements */
+
+ if (left_val < 0x80) {
+ uinfo->value.integer.value[0] = left_val;
+ } else {
+ uinfo->value.integer.value[0] = 0x80 - left_val;
+ }
+
+ if (right_val < 0x80) {
+ uinfo->value.integer.value[1] = right_val;
+ } else {
+ uinfo->value.integer.value[1] = 0x80 - right_val;
+ }
+
+ } else {
+
+ /* non-equalizer elements */
+
+ uinfo->value.integer.value[0] = 0x20 - left_val;
+ uinfo->value.integer.value[1] = 0x20 - right_val;
+ }
+
+ return 0;
+}
+
+static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+ int left, right, left_old, right_old;
+ int setreg_left, setreg_right, getreg_left, getreg_right;
+ int change, error;
+
+ left = ucontrol->value.integer.value[0];
+ right = ucontrol->value.integer.value[1];
+
+ setreg_right = (kcontrol->private_value >> 8) & 0xff;
+ if (setreg_right == ACI_SET_MASTER) {
+ setreg_left = setreg_right + 1;
+ } else {
+ setreg_left = setreg_right + 8;
+ }
+
+ getreg_right = kcontrol->private_value & 0xff;
+ getreg_left = getreg_right + 1;
+
+ if ((left_old = aci_getvalue(miro, getreg_left)) < 0) {
+ snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old);
+ return left_old;
+ }
+
+ if ((right_old = aci_getvalue(miro, getreg_right)) < 0) {
+ snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old);
+ return right_old;
+ }
+
+ if ((getreg_right >= ACI_GET_EQ1) && (getreg_right <= ACI_GET_EQ7)) {
+
+ /* equalizer elements */
+
+ if (left_old > 0x80)
+ left_old = 0x80 - left_old;
+ if (right_old > 0x80)
+ right_old = 0x80 - right_old;
+
+ if (left >= 0) {
+ if ((error = aci_setvalue(miro, setreg_left, left)) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ left, error);
+ return error;
+ }
+ } else {
+ if ((error = aci_setvalue(miro, setreg_left, 0x80 - left)) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ 0x80 - left, error);
+ return error;
+ }
+ }
+
+ if (right >= 0) {
+ if ((error = aci_setvalue(miro, setreg_right, right)) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ right, error);
+ return error;
+ }
+ } else {
+ if ((error = aci_setvalue(miro, setreg_right, 0x80 - right)) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ 0x80 - right, error);
+ return error;
+ }
+ }
+
+ } else {
+
+ /* non-equalizer elements */
+
+ left_old = 0x20 - left_old;
+ right_old = 0x20 - right_old;
+
+ if ((error = aci_setvalue(miro, setreg_left, 0x20 - left)) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ 0x20 - left, error);
+ return error;
+ }
+ if ((error = aci_setvalue(miro, setreg_right, 0x20 - right)) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ 0x20 - right, error);
+ return error;
+ }
+ }
+
+ change = (left != left_old) || (right != right_old);
+
+ return change;
+}
+
+static struct snd_kcontrol_new snd_miro_controls[] = {
+MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER),
+MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC),
+MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE),
+MIRO_DOUBLE("CD Playback Volume", 0, ACI_GET_CD, ACI_SET_CD),
+MIRO_DOUBLE("Synth Playback Volume", 0, ACI_GET_SYNTH, ACI_SET_SYNTH),
+MIRO_DOUBLE("PCM Playback Volume", 1, ACI_GET_PCM, ACI_SET_PCM),
+MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2),
+};
+
+/* Equalizer with seven bands (only PCM20)
+ from -12dB up to +12dB on each band */
+static struct snd_kcontrol_new snd_miro_eq_controls[] = {
+MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1),
+MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2),
+MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3),
+MIRO_DOUBLE("Tone Control - 1 kHz", 0, ACI_GET_EQ4, ACI_SET_EQ4),
+MIRO_DOUBLE("Tone Control - 2.5 kHz", 0, ACI_GET_EQ5, ACI_SET_EQ5),
+MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6),
+MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7),
+};
+
+static struct snd_kcontrol_new snd_miro_radio_control[] = {
+MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1),
+};
+
+static struct snd_kcontrol_new snd_miro_line_control[] = {
+MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1),
+};
+
+static struct snd_kcontrol_new snd_miro_preamp_control[] = {
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic Boost",
+ .index = 1,
+ .info = snd_miro_info_preamp,
+ .get = snd_miro_get_preamp,
+ .put = snd_miro_put_preamp,
+}};
+
+static struct snd_kcontrol_new snd_miro_amp_control[] = {
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Line Boost",
+ .index = 0,
+ .info = snd_miro_info_amp,
+ .get = snd_miro_get_amp,
+ .put = snd_miro_put_amp,
+}};
+
+static struct snd_kcontrol_new snd_miro_capture_control[] = {
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Capture Switch",
+ .index = 0,
+ .info = snd_miro_info_capture,
+ .get = snd_miro_get_capture,
+ .put = snd_miro_put_capture,
+}};
+
+static unsigned char aci_init_values[][2] __initdata = {
+ { ACI_SET_MUTE, 0x00 },
+ { ACI_SET_POWERAMP, 0x00 },
+ { ACI_SET_PREAMP, 0x00 },
+ { ACI_SET_SOLOMODE, 0x00 },
+ { ACI_SET_MIC + 0, 0x20 },
+ { ACI_SET_MIC + 8, 0x20 },
+ { ACI_SET_LINE + 0, 0x20 },
+ { ACI_SET_LINE + 8, 0x20 },
+ { ACI_SET_CD + 0, 0x20 },
+ { ACI_SET_CD + 8, 0x20 },
+ { ACI_SET_PCM + 0, 0x20 },
+ { ACI_SET_PCM + 8, 0x20 },
+ { ACI_SET_LINE1 + 0, 0x20 },
+ { ACI_SET_LINE1 + 8, 0x20 },
+ { ACI_SET_LINE2 + 0, 0x20 },
+ { ACI_SET_LINE2 + 8, 0x20 },
+ { ACI_SET_SYNTH + 0, 0x20 },
+ { ACI_SET_SYNTH + 8, 0x20 },
+ { ACI_SET_MASTER + 0, 0x20 },
+ { ACI_SET_MASTER + 1, 0x20 },
+};
+
+static int __init snd_set_aci_init_values(struct snd_miro *miro)
+{
+ int idx, error;
+
+ /* enable WSS on PCM1 */
+
+ if ((miro->aci_product == 'A') && wss) {
+ if ((error = aci_setvalue(miro, ACI_SET_WSS, wss)) < 0) {
+ snd_printk(KERN_ERR "enabling WSS mode failed\n");
+ return error;
+ }
+ }
+
+ /* enable IDE port */
+
+ if (ide) {
+ if ((error = aci_setvalue(miro, ACI_SET_IDE, ide)) < 0) {
+ snd_printk(KERN_ERR "enabling IDE port failed\n");
+ return error;
+ }
+ }
+
+ /* set common aci values */
+
+ for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++)
+ if ((error = aci_setvalue(miro, aci_init_values[idx][0],
+ aci_init_values[idx][1])) < 0) {
+ snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+ aci_init_values[idx][0], error);
+ return error;
+ }
+
+ miro->aci_amp = 0;
+ miro->aci_preamp = 0;
+ miro->aci_solomode = 1;
+
+ return 0;
+}
+
+static int snd_miro_mixer(struct snd_miro *miro)
+{
+ struct snd_card *card;
+ unsigned int idx;
+ int err;
+
+ snd_assert(miro != NULL && miro->card != NULL, return -EINVAL);
+
+ card = miro->card;
+
+ switch (miro->hardware) {
+ case OPTi9XX_HW_82C924:
+ strcpy(card->mixername, "ACI & OPTi924");
+ break;
+ case OPTi9XX_HW_82C929:
+ strcpy(card->mixername, "ACI & OPTi929");
+ break;
+ default:
+ snd_BUG();
+ break;
+ }
+
+ for (idx = 0; idx < ARRAY_SIZE(snd_miro_controls); idx++) {
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_controls[idx], miro))) < 0)
+ return err;
+ }
+
+ if ((miro->aci_product == 'A') || (miro->aci_product == 'B')) {
+ /* PCM1/PCM12 with power-amp and Line 2 */
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0)
+ return err;
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_amp_control[0], miro))) < 0)
+ return err;
+ }
+
+ if ((miro->aci_product == 'B') || (miro->aci_product == 'C')) {
+ /* PCM12/PCM20 with mic-preamp */
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0)
+ return err;
+ if (miro->aci_version >= 176)
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0)
+ return err;
+ }
+
+ if (miro->aci_product == 'C') {
+ /* PCM20 with radio and 7 band equalizer */
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0)
+ return err;
+ for (idx = 0; idx < ARRAY_SIZE(snd_miro_eq_controls); idx++) {
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_eq_controls[idx], miro))) < 0)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static long snd_legacy_find_free_ioport(long *port_table, long size)
+{
+ while (*port_table != -1) {
+ struct resource *res;
+ if ((res = request_region(*port_table, size,
+ "ALSA test")) != NULL) {
+ release_and_free_resource(res);
+ return *port_table;
+ }
+ port_table++;
+ }
+ return -1;
+}
+
+static int __init snd_miro_init(struct snd_miro *chip, unsigned short hardware)
+{
+ static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
+
+ chip->hardware = hardware;
+ strcpy(chip->name, snd_opti9xx_names[hardware]);
+
+ chip->mc_base_size = opti9xx_mc_size[hardware];
+
+ spin_lock_init(&chip->lock);
+
+ chip->wss_base = -1;
+ chip->irq = -1;
+ chip->dma1 = -1;
+ chip->dma2 = -1;
+ chip->fm_port = -1;
+ chip->mpu_port = -1;
+ chip->mpu_irq = -1;
+
+ switch (hardware) {
+ case OPTi9XX_HW_82C929:
+ chip->mc_base = 0xf8c;
+ chip->password = 0xe3;
+ chip->pwd_reg = 3;
+ break;
+
+ case OPTi9XX_HW_82C924:
+ chip->mc_base = 0xf8c;
+ chip->password = 0xe5;
+ chip->pwd_reg = 3;
+ break;
+
+ default:
+ snd_printk(KERN_ERR "sorry, no support for %d\n", hardware);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static unsigned char snd_miro_read(struct snd_miro *chip,
+ unsigned char reg)
+{
+ unsigned long flags;
+ unsigned char retval = 0xff;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ outb(chip->password, chip->mc_base + chip->pwd_reg);
+
+ switch (chip->hardware) {
+ case OPTi9XX_HW_82C924:
+ if (reg > 7) {
+ outb(reg, chip->mc_base + 8);
+ outb(chip->password, chip->mc_base + chip->pwd_reg);
+ retval = inb(chip->mc_base + 9);
+ break;
+ }
+
+ case OPTi9XX_HW_82C929:
+ retval = inb(chip->mc_base + reg);
+ break;
+
+ default:
+ snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware);
+ }
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return retval;
+}
+
+static void snd_miro_write(struct snd_miro *chip, unsigned char reg,
+ unsigned char value)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ outb(chip->password, chip->mc_base + chip->pwd_reg);
+
+ switch (chip->hardware) {
+ case OPTi9XX_HW_82C924:
+ if (reg > 7) {
+ outb(reg, chip->mc_base + 8);
+ outb(chip->password, chip->mc_base + chip->pwd_reg);
+ outb(value, chip->mc_base + 9);
+ break;
+ }
+
+ case OPTi9XX_HW_82C929:
+ outb(value, chip->mc_base + reg);
+ break;
+
+ default:
+ snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware);
+ }
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+
+#define snd_miro_write_mask(chip, reg, value, mask) \
+ snd_miro_write(chip, reg, \
+ (snd_miro_read(chip, reg) & ~(mask)) | ((value) & (mask)))
+
+/*
+ * Proc Interface
+ */
+
+static void snd_miro_proc_read(struct snd_info_entry * entry,
+ struct snd_info_buffer *buffer)
+{
+ struct snd_miro *miro = (struct snd_miro *) entry->private_data;
+ char* model = "unknown";
+
+ /* miroSOUND PCM1 pro, early PCM12 */
+
+ if ((miro->hardware == OPTi9XX_HW_82C929) &&
+ (miro->aci_vendor == 'm') &&
+ (miro->aci_product == 'A')) {
+ switch(miro->aci_version) {
+ case 3:
+ model = "miroSOUND PCM1 pro";
+ break;
+ default:
+ model = "miroSOUND PCM1 pro / (early) PCM12";
+ break;
+ }
+ }
+
+ /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */
+
+ if ((miro->hardware == OPTi9XX_HW_82C924) &&
+ (miro->aci_vendor == 'm') &&
+ (miro->aci_product == 'B')) {
+ switch(miro->aci_version) {
+ case 4:
+ model = "miroSOUND PCM12";
+ break;
+ case 176:
+ model = "miroSOUND PCM12 (Rev. E)";
+ break;
+ default:
+ model = "miroSOUND PCM12 / PCM12 pnp";
+ break;
+ }
+ }
+
+ /* miroSOUND PCM20 radio */
+
+ if ((miro->hardware == OPTi9XX_HW_82C924) &&
+ (miro->aci_vendor == 'm') &&
+ (miro->aci_product == 'C')) {
+ switch(miro->aci_version) {
+ case 7:
+ model = "miroSOUND PCM20 radio (Rev. E)";
+ break;
+ default:
+ model = "miroSOUND PCM20 radio";
+ break;
+ }
+ }
+
+ snd_iprintf(buffer, "\nGeneral information:\n");
+ snd_iprintf(buffer, " model : %s\n", model);
+ snd_iprintf(buffer, " opti : %s\n", miro->name);
+ snd_iprintf(buffer, " codec : %s\n", miro->pcm->name);
+ snd_iprintf(buffer, " port : 0x%lx\n", miro->wss_base);
+ snd_iprintf(buffer, " irq : %d\n", miro->irq);
+ snd_iprintf(buffer, " dma : %d,%d\n\n", miro->dma1, miro->dma2);
+
+ snd_iprintf(buffer, "MPU-401:\n");
+ snd_iprintf(buffer, " port : 0x%lx\n", miro->mpu_port);
+ snd_iprintf(buffer, " irq : %d\n\n", miro->mpu_irq);
+
+ snd_iprintf(buffer, "ACI information:\n");
+ snd_iprintf(buffer, " vendor : ");
+ switch(miro->aci_vendor) {
+ case 'm':
+ snd_iprintf(buffer, "Miro\n");
+ break;
+ default:
+ snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_vendor);
+ break;
+ }
+
+ snd_iprintf(buffer, " product : ");
+ switch(miro->aci_product) {
+ case 'A':
+ snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n");
+ break;
+ case 'B':
+ snd_iprintf(buffer, "miroSOUND PCM12\n");
+ break;
+ case 'C':
+ snd_iprintf(buffer, "miroSOUND PCM20 radio\n");
+ break;
+ default:
+ snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_product);
+ break;
+ }
+
+ snd_iprintf(buffer, " firmware: %d (0x%x)\n",
+ miro->aci_version, miro->aci_version);
+ snd_iprintf(buffer, " port : 0x%lx-0x%lx\n",
+ miro->aci_port, miro->aci_port+2);
+ snd_iprintf(buffer, " wss : 0x%x\n", wss);
+ snd_iprintf(buffer, " ide : 0x%x\n", ide);
+ snd_iprintf(buffer, " solomode: 0x%x\n", miro->aci_solomode);
+ snd_iprintf(buffer, " amp : 0x%x\n", miro->aci_amp);
+ snd_iprintf(buffer, " preamp : 0x%x\n", miro->aci_preamp);
+}
+
+static void __init snd_miro_proc_init(struct snd_miro * miro)
+{
+ struct snd_info_entry *entry;
+
+ if (! snd_card_proc_new(miro->card, "miro", &entry))
+ snd_info_set_text_ops(entry, miro, 1024, snd_miro_proc_read);
+}
+
+/*
+ * Init
+ */
+
+static int __init snd_miro_configure(struct snd_miro *chip)
+{
+ unsigned char wss_base_bits;
+ unsigned char irq_bits;
+ unsigned char dma_bits;
+ unsigned char mpu_port_bits = 0;
+ unsigned char mpu_irq_bits;
+ unsigned long flags;
+
+ switch (chip->hardware) {
+ case OPTi9XX_HW_82C924:
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
+ break;
+ case OPTi9XX_HW_82C929:
+ /* untested init commands for OPTi929 */
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c);
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
+ break;
+ default:
+ snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
+ return -EINVAL;
+ }
+
+ switch (chip->wss_base) {
+ case 0x530:
+ wss_base_bits = 0x00;
+ break;
+ case 0x604:
+ wss_base_bits = 0x03;
+ break;
+ case 0xe80:
+ wss_base_bits = 0x01;
+ break;
+ case 0xf40:
+ wss_base_bits = 0x02;
+ break;
+ default:
+ snd_printk(KERN_ERR "WSS port 0x%lx not valid\n", chip->wss_base);
+ goto __skip_base;
+ }
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
+
+__skip_base:
+ switch (chip->irq) {
+ case 5:
+ irq_bits = 0x05;
+ break;
+ case 7:
+ irq_bits = 0x01;
+ break;
+ case 9:
+ irq_bits = 0x02;
+ break;
+ case 10:
+ irq_bits = 0x03;
+ break;
+ case 11:
+ irq_bits = 0x04;
+ break;
+ default:
+ snd_printk(KERN_ERR "WSS irq # %d not valid\n", chip->irq);
+ goto __skip_resources;
+ }
+
+ switch (chip->dma1) {
+ case 0:
+ dma_bits = 0x01;
+ break;
+ case 1:
+ dma_bits = 0x02;
+ break;
+ case 3:
+ dma_bits = 0x03;
+ break;
+ default:
+ snd_printk(KERN_ERR "WSS dma1 # %d not valid\n", chip->dma1);
+ goto __skip_resources;
+ }
+
+ if (chip->dma1 == chip->dma2) {
+ snd_printk(KERN_ERR "don't want to share dmas\n");
+ return -EBUSY;
+ }
+
+ switch (chip->dma2) {
+ case 0:
+ case 1:
+ break;
+ default:
+ snd_printk(KERN_ERR "WSS dma2 # %d not valid\n", chip->dma2);
+ goto __skip_resources;
+ }
+ dma_bits |= 0x04;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ outb(irq_bits << 3 | dma_bits, chip->wss_base);
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+__skip_resources:
+ if (chip->hardware > OPTi9XX_HW_82C928) {
+ switch (chip->mpu_port) {
+ case 0:
+ case -1:
+ break;
+ case 0x300:
+ mpu_port_bits = 0x03;
+ break;
+ case 0x310:
+ mpu_port_bits = 0x02;
+ break;
+ case 0x320:
+ mpu_port_bits = 0x01;
+ break;
+ case 0x330:
+ mpu_port_bits = 0x00;
+ break;
+ default:
+ snd_printk(KERN_ERR "MPU-401 port 0x%lx not valid\n",
+ chip->mpu_port);
+ goto __skip_mpu;
+ }
+
+ switch (chip->mpu_irq) {
+ case 5:
+ mpu_irq_bits = 0x02;
+ break;
+ case 7:
+ mpu_irq_bits = 0x03;
+ break;
+ case 9:
+ mpu_irq_bits = 0x00;
+ break;
+ case 10:
+ mpu_irq_bits = 0x01;
+ break;
+ default:
+ snd_printk(KERN_ERR "MPU-401 irq # %d not valid\n",
+ chip->mpu_irq);
+ goto __skip_mpu;
+ }
+
+ snd_miro_write_mask(chip, OPTi9XX_MC_REG(6),
+ (chip->mpu_port <= 0) ? 0x00 :
+ 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3,
+ 0xf8);
+ }
+__skip_mpu:
+
+ return 0;
+}
+
+static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *chip)
+{
+ int i, err;
+ unsigned char value;
+
+ for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) {
+
+ if ((err = snd_miro_init(chip, i)) < 0)
+ return err;
+
+ if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)
+ continue;
+
+ value = snd_miro_read(chip, OPTi9XX_MC_REG(1));
+ if ((value != 0xff) && (value != inb(chip->mc_base + 1)))
+ if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1)))
+ return 1;
+
+ release_and_free_resource(chip->res_mc_base);
+ chip->res_mc_base = NULL;
+
+ }
+
+ return -ENODEV;
+}
+
+static int __init snd_card_miro_aci_detect(struct snd_card *card, struct snd_miro * miro)
+{
+ unsigned char regval;
+ int i;
+
+ mutex_init(&miro->aci_mutex);
+
+ /* get ACI port from OPTi9xx MC 4 */
+
+ miro->mc_base = 0xf8c;
+ regval=inb(miro->mc_base + 4);
+ miro->aci_port = (regval & 0x10) ? 0x344: 0x354;
+
+ if ((miro->res_aci_port = request_region(miro->aci_port, 3, "miro aci")) == NULL) {
+ snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n",
+ miro->aci_port, miro->aci_port+2);
+ return -ENOMEM;
+ }
+
+ /* force ACI into a known state */
+ for (i = 0; i < 3; i++)
+ if (aci_cmd(miro, ACI_ERROR_OP, -1, -1) < 0) {
+ snd_printk(KERN_ERR "can't force aci into known state.\n");
+ return -ENXIO;
+ }
+
+ if ((miro->aci_vendor=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0 ||
+ (miro->aci_product=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0) {
+ snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", miro->aci_port);
+ return -ENXIO;
+ }
+
+ if ((miro->aci_version=aci_cmd(miro, ACI_READ_VERSION, -1, -1)) < 0) {
+ snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n",
+ miro->aci_port);
+ return -ENXIO;
+ }
+
+ if (aci_cmd(miro, ACI_INIT, -1, -1) < 0 ||
+ aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 ||
+ aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) {
+ snd_printk(KERN_ERR "can't initialize aci.\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static void snd_card_miro_free(struct snd_card *card)
+{
+ struct snd_miro *miro = card->private_data;
+
+ release_and_free_resource(miro->res_aci_port);
+ release_and_free_resource(miro->res_mc_base);
+}
+
+static int __init snd_miro_probe(struct platform_device *devptr)
+{
+ static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
+ static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
+ static int possible_irqs[] = {11, 9, 10, 7, -1};
+ static int possible_mpu_irqs[] = {10, 5, 9, 7, -1};
+ static int possible_dma1s[] = {3, 1, 0, -1};
+ static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
+
+ int error;
+ struct snd_miro *miro;
+ struct snd_cs4231 *codec;
+ struct snd_timer *timer;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_rawmidi *rmidi;
+
+ if (!(card = snd_card_new(index, id, THIS_MODULE,
+ sizeof(struct snd_miro))))
+ return -ENOMEM;
+
+ card->private_free = snd_card_miro_free;
+ miro = card->private_data;
+ miro->card = card;
+
+ if ((error = snd_card_miro_aci_detect(card, miro)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to detect aci chip\n");
+ return -ENODEV;
+ }
+
+ /* init proc interface */
+ snd_miro_proc_init(miro);
+
+ if ((error = snd_card_miro_detect(card, miro)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n");
+ return -ENODEV;
+ }
+
+ if (! miro->res_mc_base &&
+ (miro->res_mc_base = request_region(miro->mc_base, miro->mc_base_size,
+ "miro (OPTi9xx MC)")) == NULL) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "request for OPTI9xx MC failed\n");
+ return -ENOMEM;
+ }
+
+ miro->wss_base = port;
+ miro->fm_port = fm_port;
+ miro->mpu_port = mpu_port;
+ miro->irq = irq;
+ miro->mpu_irq = mpu_irq;
+ miro->dma1 = dma1;
+ miro->dma2 = dma2;
+
+ if (miro->wss_base == SNDRV_AUTO_PORT) {
+ if ((miro->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to find a free WSS port\n");
+ return -EBUSY;
+ }
+ }
+
+ if (miro->mpu_port == SNDRV_AUTO_PORT) {
+ if ((miro->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to find a free MPU401 port\n");
+ return -EBUSY;
+ }
+ }
+ if (miro->irq == SNDRV_AUTO_IRQ) {
+ if ((miro->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to find a free IRQ\n");
+ return -EBUSY;
+ }
+ }
+ if (miro->mpu_irq == SNDRV_AUTO_IRQ) {
+ if ((miro->mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n");
+ return -EBUSY;
+ }
+ }
+ if (miro->dma1 == SNDRV_AUTO_DMA) {
+ if ((miro->dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to find a free DMA1\n");
+ return -EBUSY;
+ }
+ }
+ if (miro->dma2 == SNDRV_AUTO_DMA) {
+ if ((miro->dma2 = snd_legacy_find_free_dma(possible_dma2s[miro->dma1 % 4])) < 0) {
+ snd_card_free(card);
+ snd_printk(KERN_ERR "unable to find a free DMA2\n");
+ return -EBUSY;
+ }
+ }
+
+ if ((error = snd_miro_configure(miro))) {
+ snd_card_free(card);
+ return error;
+ }
+
+ if ((error = snd_cs4231_create(card, miro->wss_base + 4, -1,
+ miro->irq, miro->dma1, miro->dma2,
+ CS4231_HW_AD1845,
+ 0,
+ &codec)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+
+ if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+ if ((error = snd_cs4231_mixer(codec)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+ if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+
+ miro->pcm = pcm;
+
+ if ((error = snd_miro_mixer(miro)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+
+ if (miro->aci_vendor == 'm') {
+ /* It looks like a miro sound card. */
+ switch (miro->aci_product) {
+ case 'A':
+ sprintf(card->shortname,
+ "miroSOUND PCM1 pro / PCM12");
+ break;
+ case 'B':
+ sprintf(card->shortname,
+ "miroSOUND PCM12");
+ break;
+ case 'C':
+ sprintf(card->shortname,
+ "miroSOUND PCM20 radio");
+ break;
+ default:
+ sprintf(card->shortname,
+ "unknown miro");
+ snd_printk(KERN_INFO "unknown miro aci id\n");
+ break;
+ }
+ } else {
+ snd_printk(KERN_INFO "found unsupported aci card\n");
+ sprintf(card->shortname, "unknown Cardinal Technologies");
+ }
+
+ strcpy(card->driver, "miro");
+ sprintf(card->longname, "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d",
+ card->shortname, miro->name, pcm->name, miro->wss_base + 4,
+ miro->irq, miro->dma1, miro->dma2);
+
+ if (miro->mpu_port <= 0 || miro->mpu_port == SNDRV_AUTO_PORT)
+ rmidi = NULL;
+ else
+ if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
+ miro->mpu_port, 0, miro->mpu_irq, SA_INTERRUPT,
+ &rmidi)))
+ snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", miro->mpu_port);
+
+ if (miro->fm_port > 0 && miro->fm_port != SNDRV_AUTO_PORT) {
+ struct snd_opl3 *opl3 = NULL;
+ struct snd_opl4 *opl4;
+ if (snd_opl4_create(card, miro->fm_port, miro->fm_port - 8,
+ 2, &opl3, &opl4) < 0)
+ snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n", miro->fm_port);
+ }
+
+ if ((error = snd_set_aci_init_values(miro)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+
+ snd_card_set_dev(card, &devptr->dev);
+
+ if ((error = snd_card_register(card))) {
+ snd_card_free(card);
+ return error;
+ }
+
+ platform_set_drvdata(devptr, card);
+ return 0;
+}
+
+static int __devexit snd_miro_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+static struct platform_driver snd_miro_driver = {
+ .probe = snd_miro_probe,
+ .remove = __devexit_p(snd_miro_remove),
+ /* FIXME: suspend/resume */
+ .driver = {
+ .name = DRIVER_NAME
+ },
+};
+
+static int __init alsa_card_miro_init(void)
+{
+ int error;
+
+ if ((error = platform_driver_register(&snd_miro_driver)) < 0)
+ return error;
+ device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+ if (! IS_ERR(device)) {
+ if (platform_get_drvdata(device))
+ return 0;
+ platform_device_unregister(device);
+ }
+#ifdef MODULE
+ printk(KERN_ERR "no miro soundcard found\n");
+#endif
+ platform_driver_unregister(&snd_miro_driver);
+ return PTR_ERR(device);
+}
+
+static void __exit alsa_card_miro_exit(void)
+{
+ platform_device_unregister(device);
+ platform_driver_unregister(&snd_miro_driver);
+}
+
+module_init(alsa_card_miro_init)
+module_exit(alsa_card_miro_exit)
diff --git a/sound/isa/opti9xx/miro.h b/sound/isa/opti9xx/miro.h
new file mode 100644
index 00000000000..6e1385b8e07
--- /dev/null
+++ b/sound/isa/opti9xx/miro.h
@@ -0,0 +1,73 @@
+#ifndef _MIRO_H_
+#define _MIRO_H_
+
+#define ACI_REG_COMMAND 0 /* write register offset */
+#define ACI_REG_STATUS 1 /* read register offset */
+#define ACI_REG_BUSY 2 /* busy register offset */
+#define ACI_REG_RDS 2 /* PCM20: RDS register offset */
+#define ACI_MINTIME 500 /* ACI time out limit */
+
+#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_SET_PREAMP 0x03
+#define ACI_GET_PREAMP 0x21
+#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_ERROR_OP 0xdf
+
+/* ACI Mixer */
+
+/* These are the values for the right channel GET registers.
+ Add an offset of 0x01 for the left channel register.
+ (left=right+0x01) */
+
+#define ACI_GET_MASTER 0x03
+#define ACI_GET_MIC 0x05
+#define ACI_GET_LINE 0x07
+#define ACI_GET_CD 0x09
+#define ACI_GET_SYNTH 0x0b
+#define ACI_GET_PCM 0x0d
+#define ACI_GET_LINE1 0x10 /* Radio on PCM20 */
+#define ACI_GET_LINE2 0x12
+
+#define ACI_GET_EQ1 0x22 /* from Bass ... */
+#define ACI_GET_EQ2 0x24
+#define ACI_GET_EQ3 0x26
+#define ACI_GET_EQ4 0x28
+#define ACI_GET_EQ5 0x2a
+#define ACI_GET_EQ6 0x2c
+#define ACI_GET_EQ7 0x2e /* ... to Treble */
+
+/* And these are the values for the right channel SET registers.
+ For left channel access you have to add an offset of 0x08.
+ MASTER is an exception, which needs an offset of 0x01 */
+
+#define ACI_SET_MASTER 0x00
+#define ACI_SET_MIC 0x30
+#define ACI_SET_LINE 0x31
+#define ACI_SET_CD 0x34
+#define ACI_SET_SYNTH 0x33
+#define ACI_SET_PCM 0x32
+#define ACI_SET_LINE1 0x35 /* Radio on PCM20 */
+#define ACI_SET_LINE2 0x36
+
+#define ACI_SET_EQ1 0x40 /* from Bass ... */
+#define ACI_SET_EQ2 0x41
+#define ACI_SET_EQ3 0x42
+#define ACI_SET_EQ4 0x43
+#define ACI_SET_EQ5 0x44
+#define ACI_SET_EQ6 0x45
+#define ACI_SET_EQ7 0x46 /* ... to Treble */
+
+#endif /* _MIRO_H_ */
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 65b28cbc0eb..8ee0d70536f 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -2099,8 +2099,11 @@ static int __init alsa_card_opti9xx_init(void)
return error;
device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
if (!IS_ERR(device)) {
- snd_opti9xx_platform_device = device;
- return 0;
+ if (platform_get_drvdata(device)) {
+ snd_opti9xx_platform_device = device;
+ return 0;
+ }
+ platform_device_unregister(device);
}
platform_driver_unregister(&snd_opti9xx_driver);
}
diff --git a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c
index 9da80bfa302..d4d65b84265 100644
--- a/sound/isa/sb/es968.c
+++ b/sound/isa/sb/es968.c
@@ -124,7 +124,7 @@ static int __devinit snd_card_es968_pnp(int dev, struct snd_card_es968 *acard,
return 0;
}
-static int __init snd_card_es968_probe(int dev,
+static int __devinit snd_card_es968_probe(int dev,
struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -182,6 +182,8 @@ static int __init snd_card_es968_probe(int dev,
return 0;
}
+static unsigned int __devinitdata es968_devices;
+
static int __devinit snd_es968_pnp_detect(struct pnp_card_link *card,
const struct pnp_card_device_id *id)
{
@@ -195,6 +197,7 @@ static int __devinit snd_es968_pnp_detect(struct pnp_card_link *card,
if (res < 0)
return res;
dev++;
+ es968_devices++;
return 0;
}
return -ENODEV;
@@ -246,8 +249,11 @@ static struct pnp_card_driver es968_pnpc_driver = {
static int __init alsa_card_es968_init(void)
{
- int cards = pnp_register_card_driver(&es968_pnpc_driver);
- if (cards <= 0) {
+ int err = pnp_register_card_driver(&es968_pnpc_driver);
+ if (err)
+ return err;
+
+ if (!es968_devices) {
pnp_unregister_card_driver(&es968_pnpc_driver);
#ifdef MODULE
snd_printk(KERN_ERR "no ES968 based soundcards found\n");
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 5737ab76160..6333f900eae 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -369,7 +369,7 @@ static struct snd_card *snd_sb16_card_new(int dev)
return card;
}
-static int __init snd_sb16_probe(struct snd_card *card, int dev)
+static int __devinit snd_sb16_probe(struct snd_card *card, int dev)
{
int xirq, xdma8, xdma16;
struct snd_sb *chip;
@@ -518,7 +518,7 @@ static int snd_sb16_resume(struct snd_card *card)
}
#endif
-static int __init snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr)
+static int __devinit snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr)
{
struct snd_card_sb16 *acard;
struct snd_card *card;
@@ -548,7 +548,7 @@ static int __init snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr
}
-static int __init snd_sb16_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev)
{
int dev = pdev->id;
int err;
@@ -629,6 +629,7 @@ static struct platform_driver snd_sb16_nonpnp_driver = {
#ifdef CONFIG_PNP
+static unsigned int __devinitdata sb16_pnp_devices;
static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
@@ -651,6 +652,7 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
}
pnp_set_card_drvdata(pcard, card);
dev++;
+ sb16_pnp_devices++;
return 0;
}
@@ -718,19 +720,21 @@ static int __init alsa_card_sb16_init(void)
continue;
device = platform_device_register_simple(SND_SB16_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
cards++;
}
#ifdef CONFIG_PNP
/* PnP cards at last */
- i = pnp_register_card_driver(&sb16_pnpc_driver);
- if (i >= 0) {
+ err = pnp_register_card_driver(&sb16_pnpc_driver);
+ if (!err) {
pnp_registered = 1;
- cards += i;
+ cards += sb16_pnp_devices;
}
#endif
@@ -743,14 +747,10 @@ static int __init alsa_card_sb16_init(void)
snd_printk(KERN_ERR "In case, if you have AWE card, try snd-sbawe module\n");
#endif
#endif
- err = -ENODEV;
- goto errout;
+ snd_sb16_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_sb16_unregister_all();
- return err;
}
static void __exit alsa_card_sb16_exit(void)
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index 3efa23d303c..141400c0142 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -264,9 +264,11 @@ static int __init alsa_card_sb8_init(void)
continue;
device = platform_device_register_simple(SND_SB8_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -275,14 +277,10 @@ static int __init alsa_card_sb8_init(void)
#ifdef MODULE
snd_printk(KERN_ERR "Sound Blaster soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_sb8_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_sb8_unregister_all();
- return err;
}
static void __exit alsa_card_sb8_exit(void)
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index a60e66afbf9..09c8e8c6b5e 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -366,9 +366,11 @@ static int __init alsa_card_sgalaxy_init(void)
continue;
device = platform_device_register_simple(SND_SGALAXY_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
devices[i] = device;
cards++;
@@ -377,14 +379,10 @@ static int __init alsa_card_sgalaxy_init(void)
#ifdef MODULE
snd_printk(KERN_ERR "Sound Galaxy soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_sgalaxy_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_sgalaxy_unregister_all();
- return err;
}
static void __exit alsa_card_sgalaxy_exit(void)
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 29bba8cc3ef..d2a856f0fde 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -1255,7 +1255,7 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp)
}
-static int __init snd_sscape_probe(struct platform_device *pdev)
+static int __devinit snd_sscape_probe(struct platform_device *pdev)
{
int dev = pdev->id;
struct snd_card *card;
@@ -1427,8 +1427,8 @@ static int __init sscape_manual_probe(void)
dma[i] == SNDRV_AUTO_DMA) {
printk(KERN_INFO
"sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n");
- ret = -ENXIO;
- goto errout;
+ sscape_unregister_all();
+ return -ENXIO;
}
/*
@@ -1436,17 +1436,15 @@ static int __init sscape_manual_probe(void)
*/
device = platform_device_register_simple(SSCAPE_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- ret = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
}
return 0;
-
- errout:
- sscape_unregister_all();
- return ret;
}
static void sscape_exit(void)
@@ -1469,7 +1467,7 @@ static int __init sscape_init(void)
if (ret < 0)
return ret;
#ifdef CONFIG_PNP
- if (pnp_register_card_driver(&sscape_pnpc_driver) >= 0)
+ if (pnp_register_card_driver(&sscape_pnpc_driver) == 0)
pnp_registered = 1;
#endif
return 0;
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index c0115bf9065..7ae86f82c3f 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -589,7 +589,7 @@ snd_wavefront_probe (struct snd_card *card, int dev)
return snd_card_register(card);
}
-static int __init snd_wavefront_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_wavefront_nonpnp_probe(struct platform_device *pdev)
{
int dev = pdev->id;
struct snd_card *card;
@@ -637,6 +637,7 @@ static struct platform_driver snd_wavefront_driver = {
#ifdef CONFIG_PNP
+static unsigned int __devinitdata wavefront_pnp_devices;
static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
@@ -670,6 +671,7 @@ static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
pnp_set_card_drvdata(pcard, card);
dev++;
+ wavefront_pnp_devices++;
return 0;
}
@@ -720,19 +722,21 @@ static int __init alsa_card_wavefront_init(void)
#endif
device = platform_device_register_simple(WAVEFRONT_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
+ if (IS_ERR(device))
+ continue;
+ if (!platform_get_drvdata(device)) {
+ platform_device_unregister(device);
+ continue;
}
platform_devices[i] = device;
cards++;
}
#ifdef CONFIG_PNP
- i = pnp_register_card_driver(&wavefront_pnpc_driver);
- if (i >= 0) {
+ err = pnp_register_card_driver(&wavefront_pnpc_driver);
+ if (!err) {
pnp_registered = 1;
- cards += i;
+ cards += wavefront_pnp_devices;
}
#endif
@@ -740,14 +744,10 @@ static int __init alsa_card_wavefront_init(void)
#ifdef MODULE
printk (KERN_ERR "No WaveFront cards found or devices busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_wavefront_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_wavefront_unregister_all();
- return err;
}
static void __exit alsa_card_wavefront_exit(void)
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 88e52dc84c0..558c6ed443b 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -5,23 +5,9 @@
#
# Prompt user for primary drivers.
-config OBSOLETE_OSS_DRIVER
- 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 since there
- are ALSA drivers for the same hardware.
-
- Please contact Adrian Bunk <bunk@stusta.de> if you had to
- say Y here because your soundcard is not properly supported
- by ALSA.
-
- If unsure, say N.
-
config SOUND_BT878
tristate "BT878 audio dma"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+ depends on SOUND_PRIME && PCI
---help---
Audio DMA support for bt878 based grabber boards. As you might have
already noticed, bt878 is listed with two functions in /proc/pci.
@@ -35,48 +21,9 @@ config SOUND_BT878
To compile this driver as a module, choose M here: the module will
be called btaudio.
-config SOUND_CMPCI
- tristate "C-Media PCI (CMI8338/8738)"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a PCI sound card using the CMI8338
- or the CMI8738 chipset. Data on these chips are available at
- <http://www.cmedia.com.tw/>.
-
- A userspace utility to control some internal registers of these
- chips is available at
- <http://member.nifty.ne.jp/Breeze/softwares/unix/cmictl-e.html>.
-
-config SOUND_CMPCI_FM
- bool "Enable legacy FM"
- depends on SOUND_CMPCI && X86
- help
- Say Y here to enable the legacy FM (frequency-modulation) synthesizer
- support on a card using the CMI8338 or CMI8378 chipset. Even it is
- enabled, you need to set fmio as proper value to enable it.
- Say N here if you don't need this.
-
-config SOUND_CMPCI_MIDI
- bool "Enable legacy MPU-401"
- depends on SOUND_CMPCI && X86
- help
- Say Y here to enable the legacy MPU401 MIDI synthesizer support on a
- card using the CMI8338 or CMI8378 chipset. Even it is enabled,
- you need to set mpuio as proper value to enable it.
- Say N here if you don't need this.
-
-config SOUND_CMPCI_JOYSTICK
- bool "Enable joystick"
- depends on SOUND_CMPCI && X86 && (GAMEPORT=y || SOUND_CMPCI=GAMEPORT)
- help
- Say Y here in order to enable the joystick port on a sound card using
- the CMI8338 or the CMI8738 chipset. You need to config the
- gameport support and set joystick parameter as 1 to use it.
- Say N here if you don't need this.
-
config SOUND_EMU10K1
tristate "Creative SBLive! (EMU10K1)"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+ depends on SOUND_PRIME && PCI
---help---
Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
such as the Creative SBLive!, SB PCI512 or Emu-APS.
@@ -108,13 +55,6 @@ config SOUND_FUSION
series) when wired as native sound drivers with AC97 codecs. If
this driver does not work try the CS4232 driver.
-config SOUND_CS4281
- tristate "Crystal Sound CS4281"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Picture and feature list at
- <http://www.pcbroker.com/crystal4281.html>.
-
config SOUND_BCM_CS4297A
tristate "Crystal Sound CS4297a (for Swarm)"
depends on SOUND_PRIME && SIBYTE_SWARM
@@ -125,22 +65,9 @@ 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_ES1370
- tristate "Ensoniq AudioPCI (ES1370)"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a PCI sound card utilizing the Ensoniq
- ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find
- out if your sound card uses an ES1370 without removing your
- computer's cover, use lspci -n and look for the PCI ID
- 1274:5000. Since Ensoniq was bought by Creative Labs,
- Sound Blaster 64/PCI models are either ES1370 or ES1371 based.
- This driver differs slightly from OSS/Free, so PLEASE READ
- <file:Documentation/sound/oss/es1370>.
-
config SOUND_ES1371
tristate "Creative Ensoniq AudioPCI 97 (ES1371)"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+ depends on SOUND_PRIME && PCI
help
Say Y or M if you have a PCI sound card utilizing the Ensoniq
ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if
@@ -151,33 +78,6 @@ config SOUND_ES1371
slightly from OSS/Free, so PLEASE READ
<file:Documentation/sound/oss/es1371>.
-config SOUND_ESSSOLO1
- tristate "ESS Technology Solo1"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a PCI sound card utilizing the ESS Technology
- Solo1 chip. To find out if your sound card uses a
- Solo1 chip without removing your computer's cover, use
- lspci -n and look for the PCI ID 125D:1969. This driver
- differs slightly from OSS/Free, so PLEASE READ
- <file:Documentation/sound/oss/solo1>.
-
-config SOUND_MAESTRO
- tristate "ESS Maestro, Maestro2, Maestro2E driver"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a sound system driven by ESS's Maestro line
- of PCI sound chips. These include the Maestro 1, Maestro 2, and
- Maestro 2E. See <file:Documentation/sound/oss/Maestro> for more
- details.
-
-config SOUND_MAESTRO3
- tristate "ESS Maestro3/Allegro driver (EXPERIMENTAL)"
- depends on SOUND_PRIME && PCI && EXPERIMENTAL && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a sound system driven by ESS's Maestro 3
- PCI sound chip.
-
config SOUND_ICH
tristate "Intel ICH (i8xx) audio support"
depends on SOUND_PRIME && PCI
@@ -185,24 +85,6 @@ config SOUND_ICH
Support for integral audio in Intel's I/O Controller Hub (ICH)
chipset, as used on the 810/820/840 motherboards.
-config SOUND_HARMONY
- tristate "PA Harmony audio driver"
- depends on GSC_LASI && SOUND_PRIME && OBSOLETE_OSS_DRIVER
- help
- Say 'Y' or 'M' to include support for Harmony soundchip
- on HP 712, 715/new and many other GSC based machines.
-
-config SOUND_SONICVIBES
- tristate "S3 SonicVibes"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a PCI sound card utilizing the S3
- SonicVibes chipset. To find out if your sound card uses a
- SonicVibes chip without removing your computer's cover, use
- lspci -n and look for the PCI ID 5333:CA00. This driver
- differs slightly from OSS/Free, so PLEASE READ
- <file:Documentation/sound/oss/sonicvibes>.
-
config SOUND_VWSND
tristate "SGI Visual Workstation Sound"
depends on SOUND_PRIME && X86_VISWS
@@ -231,10 +113,6 @@ config SOUND_VRC5477
integrated, multi-function controller chip for MIPS CPUs. Works
with the AC97 codec.
-config SOUND_AU1000
- tristate "Au1000 Sound"
- depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && OBSOLETE_OSS_DRIVER
-
config SOUND_AU1550_AC97
tristate "Au1550 AC97 Sound"
depends on SOUND_PRIME && SOC_AU1550
@@ -507,7 +385,7 @@ config MSND_FIFOSIZE
config SOUND_VIA82CXXX
tristate "VIA 82C686 Audio Codec"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+ depends on SOUND_PRIME && PCI
help
Say Y here to include support for the audio codec found on VIA
82Cxxx-based chips. Typically these are built into a motherboard.
@@ -576,18 +454,6 @@ config SOUND_AD1889
Say M here if you have a sound card based on the Analog Devices
AD1889 chip.
-config SOUND_SGALAXY
- tristate "Aztech Sound Galaxy (non-PnP) cards"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- help
- This module initializes the older non Plug and Play sound galaxy
- cards from Aztech. It supports the Waverider Pro 32 - 3D and the
- Galaxy Washington 16.
-
- If you compile the driver into the kernel, you have to add
- "sgalaxy=<io>,<irq>,<dma>,<dma2>,<sgbase>" to the kernel command
- line.
-
config SOUND_ADLIB
tristate "Adlib Cards"
depends on SOUND_OSS
@@ -614,7 +480,7 @@ config SOUND_ACI_MIXER
config SOUND_CS4232
tristate "Crystal CS4232 based (PnP) cards"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+ depends on SOUND_OSS
help
Say Y here if you have a card based on the Crystal CS4232 chip set,
which uses its own Plug and Play protocol.
@@ -626,42 +492,6 @@ config SOUND_CS4232
See <file:Documentation/sound/oss/CS4232> for more information on
configuring this card.
-config SOUND_SSCAPE
- tristate "Ensoniq SoundScape support"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- 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
- and Reveal (Reveal makes also other cards).
-
- If you compile the driver into the kernel, you have to add
- "sscape=<io>,<irq>,<dma>,<mpuio>,<mpuirq>" to the kernel command
- line.
-
-config SOUND_GUS
- tristate "Gravis Ultrasound support"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- help
- Say Y here for any type of Gravis Ultrasound card, including the GUS
- or GUS MAX. See also <file:Documentation/sound/oss/ultrasound> for more
- information on configuring this card with modules.
-
- If you compile the driver into the kernel, you have to add
- "gus=<io>,<irq>,<dma>,<dma2>" to the kernel command line.
-
-config SOUND_GUS16
- bool "16 bit sampling option of GUS (_NOT_ GUS MAX)"
- depends on SOUND_GUS
- help
- Support for Gravis Ulstrasound (GUS) cards (other than the GUS),
- sampling at 16-bit width.
-
-config SOUND_GUSMAX
- bool "GUS MAX support"
- depends on SOUND_GUS
- help
- Support for Gravis Ulstrasound MAX.
-
config SOUND_VMIDI
tristate "Loopback MIDI device support"
depends on SOUND_OSS
@@ -742,7 +572,7 @@ config SOUND_MPU401
config SOUND_NM256
tristate "NM256AV/NM256ZX audio support"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+ depends on SOUND_OSS
help
Say M here to include audio support for the NeoMagic 256AV/256ZX
chipsets. These are the audio chipsets found in the Sony
@@ -752,35 +582,6 @@ config SOUND_NM256
See <file:Documentation/sound/oss/NM256> for further information.
-config SOUND_MAD16
- tristate "OPTi MAD16 and/or Mozart based cards"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- ---help---
- Answer Y if your card has a Mozart (OAK OTI-601) or MAD16 (OPTi
- 82C928 or 82C929 or 82C931) audio interface chip. These chips are
- quite common so it's possible that many no-name cards have one of
- them. In addition the MAD16 chip is used in some cards made by known
- manufacturers such as Turtle Beach (Tropez), Reveal (some models)
- and Diamond (latest ones). Note however that the Tropez sound cards
- have their own driver; if you have one of those, say N here and Y or
- M to "Full support for Turtle Beach WaveFront", below.
-
- If you compile the driver into the kernel, you have to add
- "mad16=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the
- kernel command line.
-
- See also <file:Documentation/sound/oss/Opti> and
- <file:Documentation/sound/oss/MAD16> for more information on setting
- these cards up as modules.
-
-config MAD16_OLDCARD
- bool "Support MIDI in older MAD16 based cards (requires SB)"
- depends on SOUND_MAD16
- help
- Answer Y (or M) if you have an older card based on the C928 or
- Mozart chipset and you want to have MIDI support. If you enable this
- option you also need to enable support for Sound Blaster.
-
config SOUND_PAS
tristate "ProAudioSpectrum 16 support"
depends on SOUND_OSS
@@ -873,53 +674,9 @@ config SOUND_SB
You can say M here to compile this driver as a module; the module is
called sb.
-config SOUND_AWE32_SYNTH
- tristate "AWE32 synth"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- help
- Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or
- similar sound card. See <file:Documentation/sound/oss/README.awe>,
- <file:Documentation/sound/oss/AWE32> and the Soundblaster-AWE
- mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
- for more info.
-
-config SOUND_WAVEFRONT
- tristate "Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards"
- depends on SOUND_OSS && m && OBSOLETE_OSS_DRIVER
- help
- Answer Y or M if you have a Tropez Plus, Tropez or Maui sound card
- and read the files <file:Documentation/sound/oss/Wavefront> and
- <file:Documentation/sound/oss/Tropez+>.
-
-config SOUND_MAUI
- tristate "Limited support for Turtle Beach Wave Front (Maui, Tropez) synthesizers"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- help
- Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez
- sound card.
-
- If you compile the driver into the kernel, you have to add
- "maui=<io>,<irq>" to the kernel command line.
-
-config MAUI_HAVE_BOOT
- bool "Have OSWF.MOT firmware file"
- depends on SOUND_MAUI=y && !STANDALONE
- help
- Turtle Beach Maui and Tropez sound cards have a microcontroller
- which needs to be initialized prior to use. OSWF.MOT is a file
- distributed with the card's DOS/Windows drivers. Answer Y if you
- have this file.
-
-config MAUI_BOOT_FILE
- string "Full pathname of OSWF.MOT firmware file"
- depends on MAUI_HAVE_BOOT
- default "/etc/sound/oswf.mot"
- help
- Enter the full pathname of your OSWF.MOT file, starting from /.
-
config SOUND_YM3812
tristate "Yamaha FM synthesizer (YM3812/OPL-3) support"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+ depends on SOUND_OSS
---help---
Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
Answering Y is usually a safe and recommended choice, however some
@@ -933,18 +690,6 @@ config SOUND_YM3812
If unsure, say Y.
-config SOUND_OPL3SA1
- tristate "Yamaha OPL3-SA1 audio controller"
- depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is
- usually built into motherboards. Read
- <file:Documentation/sound/oss/OPL3-SA> for details.
-
- If you compile the driver into the kernel, you have to add
- "opl3sa=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
- command line.
-
config SOUND_OPL3SA2
tristate "Yamaha OPL3-SA2 and SA3 based PnP cards"
depends on SOUND_OSS
@@ -959,19 +704,6 @@ config SOUND_OPL3SA2
"opl3sa2=<io>,<irq>,<dma>,<dma2>,<mssio>,<mpuio>" to the kernel
command line.
-config SOUND_YMFPCI
- tristate "Yamaha YMF7xx PCI audio (native mode)"
- depends on SOUND_OSS && PCI && OBSOLETE_OSS_DRIVER
- help
- Support for Yamaha cards including the YMF711, YMF715, YMF718,
- YMF719, YMF724, Waveforce 192XG, and Waveforce 192 Digital.
-
-config SOUND_YMFPCI_LEGACY
- bool "Yamaha PCI legacy ports support"
- depends on SOUND_YMFPCI
- help
- Support for YMF7xx PCI cards emulating an MP401.
-
config SOUND_UART6850
tristate "6850 UART support"
depends on SOUND_OSS
@@ -1101,30 +833,6 @@ config SOUND_KAHLUA
tristate "XpressAudio Sound Blaster emulation"
depends on SOUND_SB
-config SOUND_ALI5455
- tristate "ALi5455 audio support"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-
-config SOUND_FORTE
- tristate "ForteMedia FM801 driver"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you want driver support for the ForteMedia FM801 PCI
- audio controller (Abit AU10, Genius Sound Maker, HP Workstation
- zx2000, and others).
-
-config SOUND_RME96XX
- tristate "RME Hammerfall (RME96XX) support"
- depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
- help
- Say Y or M if you have a Hammerfall or Hammerfall light
- multichannel card from RME. If you want to access advanced
- features of the card, read <file:Documentation/sound/oss/rme96xx>.
-
-config SOUND_AD1980
- tristate "AD1980 front/back switch plugin"
- depends on SOUND_PRIME && OBSOLETE_OSS_DRIVER
-
config SOUND_SH_DAC_AUDIO
tristate "SuperH DAC audio support"
depends on SOUND_PRIME && CPU_SH3
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index 49796be955f..e04fa49b0dc 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -2026,7 +2026,8 @@ int ad1848_init (char *name, struct resource *ports, int irq, int dma_playback,
if (irq > 0)
{
devc->dev_no = my_dev;
- if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0)
+ if (request_irq(devc->irq, adintr, 0, devc->name,
+ (void *)(long)my_dev) < 0)
{
printk(KERN_WARNING "ad1848: Unable to allocate IRQ\n");
/* Don't free it either then.. */
@@ -2175,7 +2176,7 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int
if (!share_dma)
{
if (devc->irq > 0) /* There is no point in freeing irq, if it wasn't allocated */
- free_irq(devc->irq, (void *)devc->dev_no);
+ free_irq(devc->irq, (void *)(long)devc->dev_no);
sound_free_dma(dma_playback);
@@ -2204,7 +2205,7 @@ irqreturn_t adintr(int irq, void *dev_id, struct pt_regs *dummy)
unsigned char c930_stat = 0;
int cnt = 0;
- dev = (int)dev_id;
+ dev = (long)dev_id;
devc = (ad1848_info *) audio_devs[dev]->devc;
interrupt_again: /* Jump back here if int status doesn't reset */
@@ -2900,7 +2901,8 @@ static struct pnp_dev *activate_dev(char *devname, char *resname, struct pnp_dev
return(dev);
}
-static struct pnp_dev *ad1848_init_generic(struct pnp_card *bus, struct address_info *hw_config, int slot)
+static struct pnp_dev __init *ad1848_init_generic(struct pnp_card *bus,
+ struct address_info *hw_config, int slot)
{
/* Configure Audio device */
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
index 54dabf86280..a4ca7569e70 100644
--- a/sound/oss/ad1889.c
+++ b/sound/oss/ad1889.c
@@ -75,7 +75,7 @@ static inline void ad1889_set_wav_rate(ad1889_dev_t *dev, int rate)
DBG("Setting WAV rate to %d\n", rate);
dev->state[AD_WAV_STATE].dmabuf.rate = rate;
- AD1889_WRITEW(dev, AD_DSWAS, 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);
@@ -89,14 +89,14 @@ static inline void ad1889_set_wav_fmt(ad1889_dev_t *dev, int fmt)
DBG("Setting WAV format to 0x%x\n", fmt);
- tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+ 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_DSWSMC, tmp);
+ AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
}
static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
@@ -105,13 +105,13 @@ static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
DBG("Setting ADC format to 0x%x\n", fmt);
- tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
+ 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_DSRAMC, tmp);
+ AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
}
static void ad1889_start_wav(ad1889_state_t *state)
@@ -145,21 +145,21 @@ static void ad1889_start_wav(ad1889_state_t *state)
dmabuf->rd_ptr, dmabuf->dma_len);
/* load up the current register set */
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVCC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVICC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVCA, dmabuf->dma_handle);
+ 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_DMAWAVBC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVIBC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVBA, dmabuf->dma_handle);
+ 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_DMACHSS, 0x8);
- tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+ 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_DSWSMC, tmp);
- (void) AD1889_READW(ad1889_dev, AD_DSWSMC); /* flush posted PCI write */
+ AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
+ (void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
dmabuf->enable |= DAC_RUNNING;
@@ -179,10 +179,10 @@ static void ad1889_stop_wav(ad1889_state_t *state)
u16 tmp;
unsigned long cnt = dmabuf->dma_len;
- tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+ tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
tmp &= ~0x0400; /* clear WAEN */
- AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
- (void) AD1889_READW(ad1889_dev, AD_DSWSMC); /* flush posted PCI write */
+ 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);
@@ -211,7 +211,7 @@ static void ad1889_startstop_adc(ad1889_state_t *state, int start)
spin_lock_irqsave(&state->card->lock, flags);
- tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
+ tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
if (start) {
state->dmabuf.enable |= ADC_RUNNING;
tmp |= 0x0004; /* set ADEN */
@@ -219,7 +219,7 @@ static void ad1889_startstop_adc(ad1889_state_t *state, int start)
state->dmabuf.enable &= ~ADC_RUNNING;
tmp &= ~0x0004; /* clear ADEN */
}
- AD1889_WRITEW(ad1889_dev, AD_DSRAMC, tmp);
+ AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
spin_unlock_irqrestore(&state->card->lock, flags);
}
@@ -301,53 +301,53 @@ static int ad1889_read_proc (char *page, char **start, off_t off,
int len, i;
ad1889_dev_t *dev = data;
ad1889_reg_t regs[] = {
- { "WSMC", AD_DSWSMC, 16 },
- { "RAMC", AD_DSRAMC, 16 },
- { "WADA", AD_DSWADA, 16 },
- { "SYDA", AD_DSSYDA, 16 },
- { "WAS", AD_DSWAS, 16 },
- { "RES", AD_DSRES, 16 },
- { "CCS", AD_DSCCS, 16 },
- { "ADCBA", AD_DMAADCBA, 32 },
- { "ADCCA", AD_DMAADCCA, 32 },
- { "ADCBC", AD_DMAADCBC, 32 },
- { "ADCCC", AD_DMAADCCC, 32 },
- { "ADCIBC", AD_DMAADCIBC, 32 },
- { "ADCICC", AD_DMAADCICC, 32 },
- { "ADCCTRL", AD_DMAADCCTRL, 16 },
- { "WAVBA", AD_DMAWAVBA, 32 },
- { "WAVCA", AD_DMAWAVCA, 32 },
- { "WAVBC", AD_DMAWAVBC, 32 },
- { "WAVCC", AD_DMAWAVCC, 32 },
- { "WAVIBC", AD_DMAWAVIBC, 32 },
- { "WAVICC", AD_DMAWAVICC, 32 },
- { "WAVCTRL", AD_DMAWAVCTRL, 16 },
- { "DISR", AD_DMADISR, 32 },
- { "CHSS", AD_DMACHSS, 32 },
- { "IPC", AD_GPIOIPC, 16 },
- { "OP", AD_GPIOOP, 16 },
- { "IP", AD_GPIOIP, 16 },
- { "ACIC", AD_ACIC, 16 },
- { "AC97_RESET", 0x100 + AC97_RESET, 16 },
- { "AC97_MASTER_VOL_STEREO", 0x100 + AC97_MASTER_VOL_STEREO, 16 },
- { "AC97_HEADPHONE_VOL", 0x100 + AC97_HEADPHONE_VOL, 16 },
- { "AC97_MASTER_VOL_MONO", 0x100 + AC97_MASTER_VOL_MONO, 16 },
- { "AC97_MASTER_TONE", 0x100 + AC97_MASTER_TONE, 16 },
- { "AC97_PCBEEP_VOL", 0x100 + AC97_PCBEEP_VOL, 16 },
- { "AC97_PHONE_VOL", 0x100 + AC97_PHONE_VOL, 16 },
- { "AC97_MIC_VOL", 0x100 + AC97_MIC_VOL, 16 },
- { "AC97_LINEIN_VOL", 0x100 + AC97_LINEIN_VOL, 16 },
- { "AC97_CD_VOL", 0x100 + AC97_CD_VOL, 16 },
- { "AC97_VIDEO_VOL", 0x100 + AC97_VIDEO_VOL, 16 },
- { "AC97_AUX_VOL", 0x100 + AC97_AUX_VOL, 16 },
- { "AC97_PCMOUT_VOL", 0x100 + AC97_PCMOUT_VOL, 16 },
- { "AC97_RECORD_SELECT", 0x100 + AC97_RECORD_SELECT, 16 },
- { "AC97_RECORD_GAIN", 0x100 + AC97_RECORD_GAIN, 16 },
- { "AC97_RECORD_GAIN_MIC", 0x100 + AC97_RECORD_GAIN_MIC, 16 },
- { "AC97_GENERAL_PURPOSE", 0x100 + AC97_GENERAL_PURPOSE, 16 },
- { "AC97_3D_CONTROL", 0x100 + AC97_3D_CONTROL, 16 },
- { "AC97_MODEM_RATE", 0x100 + AC97_MODEM_RATE, 16 },
- { "AC97_POWER_CONTROL", 0x100 + AC97_POWER_CONTROL, 16 },
+ { "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 }
};
@@ -400,9 +400,9 @@ static inline unsigned long ad1889_get_dma_addr(ad1889_state_t *state)
}
if (dmabuf->enable & DAC_RUNNING)
- offset = le32_to_cpu(AD1889_READL(state->card, AD_DMAWAVBA));
+ offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_WAVBA));
else
- offset = le32_to_cpu(AD1889_READL(state->card, AD_DMAADCBA));
+ offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_ADCBA));
return (unsigned long)bus_to_virt((unsigned long)offset) - (unsigned long)dmabuf->rawbuf;
}
@@ -639,9 +639,9 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (val > 5400 && val < 48000)
{
if (file->f_mode & FMODE_WRITE)
- AD1889_WRITEW(ad1889_dev, AD_DSWAS, val);
+ AD1889_WRITEW(ad1889_dev, AD_DS_WAS, val);
if (file->f_mode & FMODE_READ)
- AD1889_WRITEW(ad1889_dev, AD_DSRES, val);
+ AD1889_WRITEW(ad1889_dev, AD_DS_RES, val);
}
return 0;
@@ -649,22 +649,22 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (get_user(val, p))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
- val = AD1889_READW(ad1889_dev, AD_DSWSMC);
+ val = AD1889_READW(ad1889_dev, AD_DS_WSMC);
if (val) {
val |= 0x0200; /* set WAST */
} else {
val &= ~0x0200; /* clear WAST */
}
- AD1889_WRITEW(ad1889_dev, AD_DSWSMC, val);
+ AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, val);
}
if (file->f_mode & FMODE_WRITE) {
- val = AD1889_READW(ad1889_dev, AD_DSRAMC);
+ val = AD1889_READW(ad1889_dev, AD_DS_RAMC);
if (val) {
val |= 0x0002; /* set ADST */
} else {
val &= ~0x0002; /* clear ADST */
}
- AD1889_WRITEW(ad1889_dev, AD_DSRAMC, val);
+ AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, val);
}
return 0;
@@ -739,7 +739,7 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
break;
case SOUND_PCM_READ_RATE:
- return put_user(AD1889_READW(ad1889_dev, AD_DSWAS), p);
+ return put_user(AD1889_READW(ad1889_dev, AD_DS_WAS), p);
case SOUND_PCM_READ_CHANNELS:
case SOUND_PCM_READ_BITS:
@@ -769,7 +769,7 @@ static int ad1889_open(struct inode *inode, struct file *file)
ad1889_set_wav_rate(ad1889_dev, 48000);
ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE);
- AD1889_WRITEW(ad1889_dev, AD_DSWADA, 0x0404); /* attenuation */
+ AD1889_WRITEW(ad1889_dev, AD_DS_WADA, 0x0404); /* attenuation */
return nonseekable_open(inode, file);
}
@@ -826,15 +826,15 @@ 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 + 0x100 + reg);
- AD1889_WRITEW(dev, 0x100 + reg, val);
+ //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 + 0x100 + reg);
- return AD1889_READW(dev, 0x100 + reg);
+ //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)
@@ -883,24 +883,24 @@ static int ad1889_aclink_reset(struct pci_dev * pcidev)
int retry = 200;
ad1889_dev_t *dev = pci_get_drvdata(pcidev);
- AD1889_WRITEW(dev, AD_DSCCS, 0x8000); /* turn on clock */
- AD1889_READW(dev, AD_DSCCS);
+ AD1889_WRITEW(dev, AD_DS_CCS, 0x8000); /* turn on clock */
+ AD1889_READW(dev, AD_DS_CCS);
WAIT_10MS();
- stat = AD1889_READW(dev, AD_ACIC);
+ stat = AD1889_READW(dev, AD_AC97_ACIC);
stat |= 0x0002; /* Reset Disable */
- AD1889_WRITEW(dev, AD_ACIC, stat);
- (void) AD1889_READW(dev, AD_ACIC); /* flush posted write */
+ AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
+ (void) AD1889_READW(dev, AD_AC97_ACIC); /* flush posted write */
udelay(10);
- stat = AD1889_READW(dev, AD_ACIC);
+ stat = AD1889_READW(dev, AD_AC97_ACIC);
stat |= 0x0001; /* Interface Enable */
- AD1889_WRITEW(dev, AD_ACIC, stat);
+ AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
do {
- if (AD1889_READW(dev, AD_ACIC) & 0x8000) /* Ready */
+ if (AD1889_READW(dev, AD_AC97_ACIC) & 0x8000) /* Ready */
break;
WAIT_10MS();
retry--;
@@ -908,16 +908,16 @@ static int ad1889_aclink_reset(struct pci_dev * pcidev)
if (!retry) {
printk(KERN_ERR "ad1889_aclink_reset: codec is not ready [0x%x]\n",
- AD1889_READW(dev, AD_ACIC));
+ AD1889_READW(dev, AD_AC97_ACIC));
return -EBUSY;
}
/* TODO reset AC97 codec */
/* TODO set wave/adc pci ctrl status */
- stat = AD1889_READW(dev, AD_ACIC);
+ stat = AD1889_READW(dev, AD_AC97_ACIC);
stat |= 0x0004; /* Audio Stream Output Enable */
- AD1889_WRITEW(dev, AD_ACIC, stat);
+ AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
return 0;
}
@@ -935,10 +935,10 @@ static irqreturn_t ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs)
u32 stat;
ad1889_dev_t *dev = (ad1889_dev_t *)dev_id;
- stat = AD1889_READL(dev, AD_DMADISR);
+ stat = AD1889_READL(dev, AD_DMA_DISR);
/* clear ISR */
- AD1889_WRITEL(dev, AD_DMADISR, stat);
+ AD1889_WRITEL(dev, AD_DMA_DISR, stat);
if (stat & 0x8) { /* WAVI */
DBG("WAV interrupt\n");
@@ -964,15 +964,15 @@ static void ad1889_initcfg(ad1889_dev_t *dev)
u32 tmp32;
/* make sure the interrupt bits are setup the way we want */
- tmp32 = AD1889_READL(dev, AD_DMAWAVCTRL);
+ 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_DMAWAVCTRL, tmp32);
+ AD1889_WRITEL(dev, AD_DMA_WAVCTRL, tmp32);
/* unmute... */
- tmp16 = AD1889_READW(dev, AD_DSWADA);
+ tmp16 = AD1889_READW(dev, AD_DS_WADA);
tmp16 &= ~0x8080;
- AD1889_WRITEW(dev, AD_DSWADA, tmp16);
+ AD1889_WRITEW(dev, AD_DS_WADA, tmp16);
}
static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
@@ -1005,7 +1005,7 @@ static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_devic
goto out1;
}
- dev->regbase = ioremap_nocache(bar, AD_DSIOMEMSIZE);
+ dev->regbase = ioremap_nocache(bar, AD_DS_IOMEMSIZE);
if (!dev->regbase) {
printk(KERN_ERR DEVNAME ": unable to remap iomem\n");
goto out2;
diff --git a/sound/oss/ad1889.h b/sound/oss/ad1889.h
index 861b3213f30..09913765967 100644
--- a/sound/oss/ad1889.h
+++ b/sound/oss/ad1889.h
@@ -1,57 +1,58 @@
#ifndef _AD1889_H_
#define _AD1889_H_
-#define AD_DSWSMC 0x00 /* DMA input wave/syn mixer control */
-#define AD_DSRAMC 0x02 /* DMA output resamp/ADC mixer control */
-#define AD_DSWADA 0x04 /* DMA input wave attenuation */
-#define AD_DSSYDA 0x06 /* DMA input syn attentuation */
-#define AD_DSWAS 0x08 /* wave input sample rate */
-#define AD_DSRES 0x0a /* resampler output sample rate */
-#define AD_DSCCS 0x0c /* chip control/status */
-
-#define AD_DMARESBA 0x40 /* RES base addr */
-#define AD_DMARESCA 0x44 /* RES current addr */
-#define AD_DMARESBC 0x48 /* RES base cnt */
-#define AD_DMARESCC 0x4c /* RES current count */
-#define AD_DMAADCBA 0x50 /* ADC */
-#define AD_DMAADCCA 0x54
-#define AD_DMAADCBC 0x58
-#define AD_DMAADCCC 0x5c
-#define AD_DMASYNBA 0x60 /* SYN */
-#define AD_DMASYNCA 0x64
-#define AD_DMASYNBC 0x68
-#define AD_DMASYNCC 0x6c
-#define AD_DMAWAVBA 0x70 /* WAV */
-#define AD_DMAWAVCA 0x74
-#define AD_DMAWAVBC 0x78
-#define AD_DMAWAVCC 0x7c
-#define AD_DMARESICC 0x80 /* RES interrupt current count */
-#define AD_DMARESIBC 0x84 /* RES interrupt base count */
-#define AD_DMAADCICC 0x88 /* ADC interrupt current count */
-#define AD_DMAADCIBC 0x8c /* ADC interrupt base count */
-#define AD_DMASYNICC 0x90 /* SYN interrupt current count */
-#define AD_DMASYNIBC 0x94 /* SYN interrupt base count */
-#define AD_DMAWAVICC 0x98 /* WAV interrupt current count */
-#define AD_DMAWAVIBC 0x9c /* WAV interrupt base count */
-#define AD_DMARESCTRL 0xa0 /* RES PCI control/status */
-#define AD_DMAADCCTRL 0xa8 /* ADC PCI control/status */
-#define AD_DMASYNCTRL 0xb0 /* SYN PCI control/status */
-#define AD_DMAWAVCTRL 0xb8 /* WAV PCI control/status */
-#define AD_DMADISR 0xc0 /* PCI DMA intr status */
-#define AD_DMACHSS 0xc4 /* PCI DMA channel stop status */
-
-#define AD_GPIOIPC 0xc8 /* IO port ctrl */
-#define AD_GPIOOP 0xca /* IO output status */
-#define AD_GPIOIP 0xcc /* IO input status */
+#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_ACIC 0x180 /* AC Link interface ctrl */
+#define AD_AC97_BASE 0x100 /* ac97 base register */
+#define AD_AC97_ACIC 0x180 /* AC Link interface ctrl */
/* OPL3; BAR1 */
-#define AD_OPLM0AS 0x00 /* Music0 address/status */
-#define AD_OPLM0DATA 0x01 /* Music0 data */
-#define AD_OPLM1A 0x02 /* Music1 address */
-#define AD_OPLM1DATA 0x03 /* Music1 data */
+#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 */
@@ -59,9 +60,9 @@
#define AD_MISC 0x01 /* MIDI status/cmd */
/* 0x02-0xff reserved */
-#define AD_DSIOMEMSIZE 512
-#define AD_OPLMEMSIZE 16
-#define AD_MIDIMEMSIZE 16
+#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
diff --git a/sound/oss/cs4232.c b/sound/oss/cs4232.c
index 7c59e2d4003..c7f86f09c28 100644
--- a/sound/oss/cs4232.c
+++ b/sound/oss/cs4232.c
@@ -360,6 +360,8 @@ static int __initdata synthio = -1;
static int __initdata synthirq = -1;
static int __initdata isapnp = 1;
+static unsigned int cs4232_devices;
+
MODULE_DESCRIPTION("CS4232 based soundcard driver");
MODULE_AUTHOR("Hannu Savolainen, Paul Barton-Davis");
MODULE_LICENSE("GPL");
@@ -421,6 +423,7 @@ static int cs4232_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev
return -ENODEV;
}
pnp_set_drvdata(dev,isapnpcfg);
+ cs4232_devices++;
return 0;
}
@@ -455,10 +458,11 @@ static int __init init_cs4232(void)
#endif
cfg.irq = -1;
- if (isapnp &&
- (pnp_register_driver(&cs4232_driver) > 0)
- )
- return 0;
+ if (isapnp) {
+ pnp_register_driver(&cs4232_driver);
+ if (cs4232_devices)
+ return 0;
+ }
if(io==-1||irq==-1||dma==-1)
{
@@ -503,7 +507,8 @@ static int __init setup_cs4232(char *str)
int ints[7];
/* If we have isapnp cards, no need for options */
- if (pnp_register_driver(&cs4232_driver) > 0)
+ pnp_register_driver(&cs4232_driver);
+ if (cs4232_devices)
return 1;
str = get_options(str, ARRAY_SIZE(ints), ints);
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
index 6ba8d6f45fe..c8e21032689 100644
--- a/sound/oss/dmasound/dmasound_awacs.c
+++ b/sound/oss/dmasound/dmasound_awacs.c
@@ -2798,7 +2798,7 @@ __init setup_beep(void)
DBDMA_ALIGN(beep_dbdma_cmd_space);
/* set up emergency dbdma cmd */
emergency_dbdma_cmd = beep_dbdma_cmd+1 ;
- beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
+ beep_buf = kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
if (beep_buf == NULL) {
printk(KERN_ERR "dmasound_pmac: no memory for beep buffer\n");
kfree(beep_dbdma_cmd_space) ;
@@ -2814,7 +2814,7 @@ int __init dmasound_awacs_init(void)
struct device_node *io = NULL, *info = NULL;
int vol, res;
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return -ENODEV;
awacs_subframe = 0;
diff --git a/sound/oss/dmasound/tas_common.c b/sound/oss/dmasound/tas_common.c
index 81315996c0f..882ae98a41b 100644
--- a/sound/oss/dmasound/tas_common.c
+++ b/sound/oss/dmasound/tas_common.c
@@ -195,8 +195,8 @@ tas_init(int driver_id, const char *driver_name)
printk(KERN_INFO "tas driver [%s])\n", driver_name);
-#ifndef CONFIG_I2C_KEYWEST
- request_module("i2c-keywest");
+#ifndef CONFIG_I2C_POWERMAC
+ request_module("i2c-powermac");
#endif
tas_node = find_devices("deq");
if (tas_node == NULL)
diff --git a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c
index 0cd44a6f7ac..3721c5857b9 100644
--- a/sound/oss/emu10k1/main.c
+++ b/sound/oss/emu10k1/main.c
@@ -94,6 +94,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
+#include <linux/dma-mapping.h>
#include "hwaccess.h"
#include "8010.h"
@@ -119,7 +120,7 @@
/* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */
-#define EMU10K1_DMA_MASK 0x1fffffff /* DMA buffer mask for pci_alloc_consist */
+#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
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
index 959a96794db..25ae8e4a488 100644
--- a/sound/oss/emu10k1/midi.c
+++ b/sound/oss/emu10k1/midi.c
@@ -65,7 +65,8 @@ static int midiin_add_buffer(struct emu10k1_mididevice *midi_dev, struct midi_hd
init_midi_hdr(midihdr);
- if ((midihdr->data = (u8 *) kmalloc(MIDIIN_BUFLEN, GFP_KERNEL)) == NULL) {
+ midihdr->data = kmalloc(MIDIIN_BUFLEN, GFP_KERNEL);
+ if (!midihdr->data) {
ERROR();
kfree(midihdr);
return -1;
@@ -334,7 +335,8 @@ static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer,
midihdr->bytesrecorded = 0;
midihdr->flags = 0;
- if ((midihdr->data = (u8 *) kmalloc(count, GFP_KERNEL)) == NULL) {
+ midihdr->data = kmalloc(count, GFP_KERNEL);
+ if (!midihdr->data) {
ERROR();
kfree(midihdr);
return -EINVAL;
@@ -545,7 +547,8 @@ int emu10k1_seq_midi_out(int dev, unsigned char midi_byte)
midihdr->bytesrecorded = 0;
midihdr->flags = 0;
- if ((midihdr->data = (u8 *) kmalloc(1, GFP_KERNEL)) == NULL) {
+ midihdr->data = kmalloc(1, GFP_KERNEL);
+ if (!midihdr->data) {
ERROR();
kfree(midihdr);
return -EINVAL;
diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c
index 78d3e29ce96..6861563d752 100644
--- a/sound/oss/esssolo1.c
+++ b/sound/oss/esssolo1.c
@@ -2348,7 +2348,7 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device
/* Recording requires 24-bit DMA, so attempt to set dma mask
* to 24 bits first, then 32 bits (playback only) if that fails.
*/
- if (pci_set_dma_mask(pcidev, 0x00ffffff) &&
+ if (pci_set_dma_mask(pcidev, DMA_24BIT_MASK) &&
pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n");
return -ENODEV;
diff --git a/sound/oss/maestro3.c b/sound/oss/maestro3.c
index 66044aff258..4a5e4237a11 100644
--- a/sound/oss/maestro3.c
+++ b/sound/oss/maestro3.c
@@ -2582,15 +2582,9 @@ static int alloc_dsp_suspendmem(struct m3_card *card)
return 0;
}
-static void free_dsp_suspendmem(struct m3_card *card)
-{
- if(card->suspend_mem)
- vfree(card->suspend_mem);
-}
#else
#define alloc_dsp_suspendmem(args...) 0
-#define free_dsp_suspendmem(args...)
#endif
/*
@@ -2717,7 +2711,7 @@ out:
if(ret) {
if(card->iobase)
release_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0));
- free_dsp_suspendmem(card);
+ vfree(card->suspend_mem);
if(card->ac97) {
unregister_sound_mixer(card->ac97->dev_mixer);
kfree(card->ac97);
@@ -2760,7 +2754,7 @@ static void m3_remove(struct pci_dev *pci_dev)
}
release_region(card->iobase, 256);
- free_dsp_suspendmem(card);
+ vfree(card->suspend_mem);
kfree(card);
}
devs = NULL;
diff --git a/sound/oss/msnd.c b/sound/oss/msnd.c
index a7ad2b0a2ac..5dbfc0f9c3c 100644
--- a/sound/oss/msnd.c
+++ b/sound/oss/msnd.c
@@ -95,10 +95,8 @@ void msnd_fifo_init(msnd_fifo *f)
void msnd_fifo_free(msnd_fifo *f)
{
- if (f->data) {
- vfree(f->data);
- f->data = NULL;
- }
+ vfree(f->data);
+ f->data = NULL;
}
int msnd_fifo_alloc(msnd_fifo *f, size_t n)
diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c
index 7de079b202f..6e662ac009a 100644
--- a/sound/oss/nm256_audio.c
+++ b/sound/oss/nm256_audio.c
@@ -960,7 +960,7 @@ static struct ac97_mixer_value_list mixer_defaults[] = {
/* Installs the AC97 mixer into CARD. */
-static int __init
+static int __devinit
nm256_install_mixer (struct nm256_info *card)
{
int mixer;
@@ -995,7 +995,7 @@ nm256_install_mixer (struct nm256_info *card)
* RAM.
*/
-static void __init
+static void __devinit
nm256_peek_for_sig (struct nm256_info *card)
{
u32 port1offset
@@ -1056,7 +1056,7 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
card->playing = 0;
card->recording = 0;
card->rev = rev;
- spin_lock_init(&card->lock);
+ spin_lock_init(&card->lock);
/* Init the memory port info. */
for (x = 0; x < 2; x++) {
diff --git a/sound/oss/sb_card.c b/sound/oss/sb_card.c
index 680b82e1529..4708cbdc314 100644
--- a/sound/oss/sb_card.c
+++ b/sound/oss/sb_card.c
@@ -52,6 +52,7 @@ static int __initdata sm_games = 0; /* Logitech soundman games? */
static struct sb_card_config *legacy = NULL;
#ifdef CONFIG_PNP
+static int pnp_registered;
static int __initdata pnp = 1;
/*
static int __initdata uart401 = 0;
@@ -133,7 +134,7 @@ static void sb_unload(struct sb_card_config *scc)
}
/* Register legacy card with OSS subsystem */
-static int sb_init_legacy(void)
+static int __init sb_init_legacy(void)
{
struct sb_module_options sbmo = {0};
@@ -234,6 +235,8 @@ static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc)
}
}
+static unsigned int sb_pnp_devices;
+
/* Probe callback function for the PnP API */
static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_device_id *card_id)
{
@@ -264,6 +267,7 @@ static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_device
scc->conf.dma, scc->conf.dma2);
pnp_set_card_drvdata(card, scc);
+ sb_pnp_devices++;
return sb_register_oss(scc, &sbmo);
}
@@ -289,6 +293,14 @@ static struct pnp_card_driver sb_pnp_driver = {
MODULE_DEVICE_TABLE(pnp_card, sb_pnp_card_table);
#endif /* CONFIG_PNP */
+static void __init_or_module sb_unregister_all(void)
+{
+#ifdef CONFIG_PNP
+ if (pnp_registered)
+ pnp_unregister_card_driver(&sb_pnp_driver);
+#endif
+}
+
static int __init sb_init(void)
{
int lres = 0;
@@ -307,17 +319,18 @@ static int __init sb_init(void)
#ifdef CONFIG_PNP
if(pnp) {
- pres = pnp_register_card_driver(&sb_pnp_driver);
+ int err = pnp_register_card_driver(&sb_pnp_driver);
+ if (!err)
+ pnp_registered = 1;
+ pres = sb_pnp_devices;
}
#endif
printk(KERN_INFO "sb: Init: Done\n");
/* If either PnP or Legacy registered a card then return
* success */
- if (pres <= 0 && lres <= 0) {
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&sb_pnp_driver);
-#endif
+ if (pres == 0 && lres <= 0) {
+ sb_unregister_all();
return -ENODEV;
}
return 0;
@@ -333,14 +346,10 @@ static void __exit sb_exit(void)
sb_unload(legacy);
}
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&sb_pnp_driver);
-#endif
+ sb_unregister_all();
- if (smw_free) {
- vfree(smw_free);
- smw_free = NULL;
- }
+ vfree(smw_free);
+ smw_free = NULL;
}
module_init(sb_init);
diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c
index 347cd79c250..6815c30e0bc 100644
--- a/sound/oss/sequencer.c
+++ b/sound/oss/sequencer.c
@@ -1671,14 +1671,7 @@ void sequencer_init(void)
void sequencer_unload(void)
{
- if(queue)
- {
- vfree(queue);
- queue=NULL;
- }
- if(iqueue)
- {
- vfree(iqueue);
- iqueue=NULL;
- }
+ vfree(queue);
+ vfree(iqueue);
+ queue = iqueue = NULL;
}
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c
index 8a9917c919c..3f7427cd195 100644
--- a/sound/oss/sh_dac_audio.c
+++ b/sound/oss/sh_dac_audio.c
@@ -289,7 +289,7 @@ static int __init dac_audio_init(void)
in_use = 0;
- data_buffer = (char *)kmalloc(BUFFER_SIZE, GFP_KERNEL);
+ data_buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
if (data_buffer == NULL)
return -ENOMEM;
diff --git a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c
index 4471757b798..42bd276cfc3 100644
--- a/sound/oss/sonicvibes.c
+++ b/sound/oss/sonicvibes.c
@@ -116,6 +116,7 @@
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <linux/gameport.h>
+#include <linux/dma-mapping.h>
#include <linux/mutex.h>
@@ -2535,7 +2536,7 @@ static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id
return -ENODEV;
if (pcidev->irq == 0)
return -ENODEV;
- if (pci_set_dma_mask(pcidev, 0x00ffffff)) {
+ if (pci_set_dma_mask(pcidev, DMA_24BIT_MASK)) {
printk(KERN_WARNING "sonicvibes: architecture does not support 24bit PCI busmaster DMA\n");
return -ENODEV;
}
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 1e2e19305e3..a2081803a82 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -15,6 +15,18 @@ config SND_AD1889
To compile this as a module, choose M here: the module
will be called snd-ad1889.
+config SND_ALS300
+ tristate "Avance Logic ALS300/ALS300+"
+ depends on SND
+ select SND_PCM
+ select SND_AC97_CODEC
+ select SND_OPL3_LIB
+ help
+ Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-als300
+
config SND_ALS4000
tristate "Avance Logic ALS4000"
depends on SND && ISA_DMA_API
@@ -195,8 +207,9 @@ config SND_CS46XX
will be called snd-cs46xx.
config SND_CS46XX_NEW_DSP
- bool "Cirrus Logic (Sound Fusion) New DSP support (EXPERIMENTAL)"
- depends on SND_CS46XX && EXPERIMENTAL
+ bool "Cirrus Logic (Sound Fusion) New DSP support"
+ depends on SND_CS46XX
+ default y
help
Say Y here to use a new DSP image for SPDIF and dual codecs.
@@ -466,6 +479,19 @@ config SND_PCXHR
To compile this driver as a module, choose M here: the module
will be called snd-pcxhr.
+config SND_RIPTIDE
+ tristate "Conexant Riptide"
+ depends on SND
+ depends on FW_LOADER
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_AC97_CODEC
+ help
+ Say 'Y' or 'M' to include support for Conexant Riptide chip.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-riptide
+
config SND_RME32
tristate "RME Digi32, 32/8, 32 PRO"
depends on SND
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index a6c3cd58fe9..cba5105aafe 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -4,6 +4,7 @@
#
snd-ad1889-objs := ad1889.o
+snd-als300-objs := als300.o
snd-als4000-objs := als4000.o
snd-atiixp-objs := atiixp.o
snd-atiixp-modem-objs := atiixp_modem.o
@@ -27,6 +28,7 @@ snd-via82xx-modem-objs := via82xx_modem.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_AD1889) += snd-ad1889.o
+obj-$(CONFIG_SND_ALS300) += snd-als300.o
obj-$(CONFIG_SND_ALS4000) += snd-als4000.o
obj-$(CONFIG_SND_ATIIXP) += snd-atiixp.o
obj-$(CONFIG_SND_ATIIXP_MODEM) += snd-atiixp-modem.o
@@ -62,6 +64,7 @@ obj-$(CONFIG_SND) += \
mixart/ \
nm256/ \
pcxhr/ \
+ riptide/ \
rme9652/ \
trident/ \
ymfpci/ \
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 278319bbdea..d05200741ac 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -160,6 +160,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
{ 0x54584e20, 0xffffffff, "TLC320AD9xC", NULL, NULL },
{ 0x56494161, 0xffffffff, "VIA1612A", NULL, NULL }, // modified ICE1232 with S/PDIF
{ 0x56494170, 0xffffffff, "VIA1617A", patch_vt1617a, NULL }, // modified VT1616 with S/PDIF
+{ 0x56494182, 0xffffffff, "VIA1618", NULL, NULL },
{ 0x57454301, 0xffffffff, "W83971D", NULL, NULL },
{ 0x574d4c00, 0xffffffff, "WM9701A", NULL, NULL },
{ 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL},
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 2aa5a7fdb6e..eece1c7e55a 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -1051,7 +1051,7 @@ snd_ad1889_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_device_id snd_ad1889_ids[] = {
+static struct pci_device_id snd_ad1889_ids[] __devinitdata = {
{ PCI_DEVICE(PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS) },
{ 0, },
};
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index e264136e8fb..e2dbc211890 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -33,6 +33,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/info.h>
@@ -278,7 +279,7 @@ struct snd_ali {
#endif
};
-static struct pci_device_id snd_ali_ids[] = {
+static struct pci_device_id snd_ali_ids[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451), 0, 0, 0},
{0, }
};
@@ -2220,8 +2221,8 @@ static int __devinit snd_ali_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 31 bits */
- if (pci_set_dma_mask(pci, 0x7fffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x7fffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_31BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_31BIT_MASK) < 0) {
snd_printk(KERN_ERR "architecture does not support 31bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
new file mode 100644
index 00000000000..901b08ae917
--- /dev/null
+++ b/sound/pci/als300.c
@@ -0,0 +1,867 @@
+/*
+ * als300.c - driver for Avance Logic ALS300/ALS300+ soundcards.
+ * Copyright (C) 2005 by Ash Willis <ashwillis@programmer.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ *
+ * TODO
+ * 4 channel playback for ALS300+
+ * gameport
+ * mpu401
+ * opl3
+ *
+ * NOTES
+ * The BLOCK_COUNTER registers for the ALS300(+) return a figure related to
+ * the position in the current period, NOT the whole buffer. It is important
+ * to know which period we are in so we can calculate the correct pointer.
+ * This is why we always use 2 periods. We can then use a flip-flop variable
+ * to keep track of what period we are in.
+ */
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/ac97_codec.h>
+#include <sound/opl3.h>
+
+/* snd_als300_set_irq_flag */
+#define IRQ_DISABLE 0
+#define IRQ_ENABLE 1
+
+/* I/O port layout */
+#define AC97_ACCESS 0x00
+#define AC97_READ 0x04
+#define AC97_STATUS 0x06
+#define AC97_DATA_AVAIL (1<<6)
+#define AC97_BUSY (1<<7)
+#define ALS300_IRQ_STATUS 0x07 /* ALS300 Only */
+#define IRQ_PLAYBACK (1<<3)
+#define IRQ_CAPTURE (1<<2)
+#define GCR_DATA 0x08
+#define GCR_INDEX 0x0C
+#define ALS300P_DRAM_IRQ_STATUS 0x0D /* ALS300+ Only */
+#define MPU_IRQ_STATUS 0x0E /* ALS300 Rev. E+, ALS300+ */
+#define ALS300P_IRQ_STATUS 0x0F /* ALS300+ Only */
+
+/* General Control Registers */
+#define PLAYBACK_START 0x80
+#define PLAYBACK_END 0x81
+#define PLAYBACK_CONTROL 0x82
+#define TRANSFER_START (1<<16)
+#define FIFO_PAUSE (1<<17)
+#define RECORD_START 0x83
+#define RECORD_END 0x84
+#define RECORD_CONTROL 0x85
+#define DRAM_WRITE_CONTROL 0x8B
+#define WRITE_TRANS_START (1<<16)
+#define DRAM_MODE_2 (1<<17)
+#define MISC_CONTROL 0x8C
+#define IRQ_SET_BIT (1<<15)
+#define VMUTE_NORMAL (1<<20)
+#define MMUTE_NORMAL (1<<21)
+#define MUS_VOC_VOL 0x8E
+#define PLAYBACK_BLOCK_COUNTER 0x9A
+#define RECORD_BLOCK_COUNTER 0x9B
+
+#define DEBUG_CALLS 1
+#define DEBUG_PLAY_REC 1
+
+#if DEBUG_CALLS
+#define snd_als300_dbgcalls(format, args...) printk(format, ##args)
+#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__)
+#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__)
+#else
+#define snd_als300_dbgcalls(format, args...)
+#define snd_als300_dbgcallenter()
+#define snd_als300_dbgcallleave()
+#endif
+
+#if DEBUG_PLAY_REC
+#define snd_als300_dbgplay(format, args...) printk(KERN_ERR format, ##args)
+#else
+#define snd_als300_dbgplay(format, args...)
+#endif
+
+enum {DEVICE_ALS300, DEVICE_ALS300_PLUS};
+
+MODULE_AUTHOR("Ash Willis <ashwillis@programmer.net>");
+MODULE_DESCRIPTION("Avance Logic ALS300");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS300},{Avance Logic,ALS300+}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+struct snd_als300 {
+ unsigned long port;
+ spinlock_t reg_lock;
+ struct snd_card *card;
+ struct pci_dev *pci;
+
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
+
+ struct snd_ac97 *ac97;
+ struct snd_opl3 *opl3;
+
+ struct resource *res_port;
+
+ int irq;
+
+ int chip_type; /* ALS300 or ALS300+ */
+
+ char revision;
+};
+
+struct snd_als300_substream_data {
+ int period_flipflop;
+ int control_register;
+ int block_counter_register;
+};
+
+static struct pci_device_id snd_als300_ids[] __devinitdata = {
+ { 0x4005, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300 },
+ { 0x4005, 0x0308, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300_PLUS },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, snd_als300_ids);
+
+static inline u32 snd_als300_gcr_read(unsigned long port, unsigned short reg)
+{
+ outb(reg, port+GCR_INDEX);
+ return inl(port+GCR_DATA);
+}
+
+static inline void snd_als300_gcr_write(unsigned long port,
+ unsigned short reg, u32 val)
+{
+ outb(reg, port+GCR_INDEX);
+ outl(val, port+GCR_DATA);
+}
+
+/* Enable/Disable Interrupts */
+static void snd_als300_set_irq_flag(struct snd_als300 *chip, int cmd)
+{
+ u32 tmp = snd_als300_gcr_read(chip->port, MISC_CONTROL);
+ snd_als300_dbgcallenter();
+
+ /* boolean XOR check, since old vs. new hardware have
+ directly reversed bit setting for ENABLE and DISABLE.
+ ALS300+ acts like newer versions of ALS300 */
+ if (((chip->revision > 5 || chip->chip_type == DEVICE_ALS300_PLUS) ^
+ (cmd == IRQ_ENABLE)) == 0)
+ tmp |= IRQ_SET_BIT;
+ else
+ tmp &= ~IRQ_SET_BIT;
+ snd_als300_gcr_write(chip->port, MISC_CONTROL, tmp);
+ snd_als300_dbgcallleave();
+}
+
+static int snd_als300_free(struct snd_als300 *chip)
+{
+ snd_als300_dbgcallenter();
+ snd_als300_set_irq_flag(chip, IRQ_DISABLE);
+ if (chip->irq >= 0)
+ free_irq(chip->irq, (void *)chip);
+ pci_release_regions(chip->pci);
+ pci_disable_device(chip->pci);
+ kfree(chip);
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_dev_free(struct snd_device *device)
+{
+ struct snd_als300 *chip = device->device_data;
+ return snd_als300_free(chip);
+}
+
+static irqreturn_t snd_als300_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ u8 status;
+ struct snd_als300 *chip = dev_id;
+ struct snd_als300_substream_data *data;
+
+ status = inb(chip->port+ALS300_IRQ_STATUS);
+ if (!status) /* shared IRQ, for different device?? Exit ASAP! */
+ return IRQ_NONE;
+
+ /* ACK everything ASAP */
+ outb(status, chip->port+ALS300_IRQ_STATUS);
+ if (status & IRQ_PLAYBACK) {
+ if (chip->pcm && chip->playback_substream) {
+ data = chip->playback_substream->runtime->private_data;
+ data->period_flipflop ^= 1;
+ snd_pcm_period_elapsed(chip->playback_substream);
+ snd_als300_dbgplay("IRQ_PLAYBACK\n");
+ }
+ }
+ if (status & IRQ_CAPTURE) {
+ if (chip->pcm && chip->capture_substream) {
+ data = chip->capture_substream->runtime->private_data;
+ data->period_flipflop ^= 1;
+ snd_pcm_period_elapsed(chip->capture_substream);
+ snd_als300_dbgplay("IRQ_CAPTURE\n");
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ u8 general, mpu, dram;
+ struct snd_als300 *chip = dev_id;
+ struct snd_als300_substream_data *data;
+
+ general = inb(chip->port+ALS300P_IRQ_STATUS);
+ mpu = inb(chip->port+MPU_IRQ_STATUS);
+ dram = inb(chip->port+ALS300P_DRAM_IRQ_STATUS);
+
+ /* shared IRQ, for different device?? Exit ASAP! */
+ if ((general == 0) && ((mpu & 0x80) == 0) && ((dram & 0x01) == 0))
+ return IRQ_NONE;
+
+ if (general & IRQ_PLAYBACK) {
+ if (chip->pcm && chip->playback_substream) {
+ outb(IRQ_PLAYBACK, chip->port+ALS300P_IRQ_STATUS);
+ data = chip->playback_substream->runtime->private_data;
+ data->period_flipflop ^= 1;
+ snd_pcm_period_elapsed(chip->playback_substream);
+ snd_als300_dbgplay("IRQ_PLAYBACK\n");
+ }
+ }
+ if (general & IRQ_CAPTURE) {
+ if (chip->pcm && chip->capture_substream) {
+ outb(IRQ_CAPTURE, chip->port+ALS300P_IRQ_STATUS);
+ data = chip->capture_substream->runtime->private_data;
+ data->period_flipflop ^= 1;
+ snd_pcm_period_elapsed(chip->capture_substream);
+ snd_als300_dbgplay("IRQ_CAPTURE\n");
+ }
+ }
+ /* FIXME: Ack other interrupt types. Not important right now as
+ * those other devices aren't enabled. */
+ return IRQ_HANDLED;
+}
+
+static void __devexit snd_als300_remove(struct pci_dev *pci)
+{
+ snd_als300_dbgcallenter();
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+ snd_als300_dbgcallleave();
+}
+
+static unsigned short snd_als300_ac97_read(struct snd_ac97 *ac97,
+ unsigned short reg)
+{
+ int i;
+ struct snd_als300 *chip = ac97->private_data;
+
+ for (i = 0; i < 1000; i++) {
+ if ((inb(chip->port+AC97_STATUS) & (AC97_BUSY)) == 0)
+ break;
+ udelay(10);
+ }
+ outl((reg << 24) | (1 << 31), chip->port+AC97_ACCESS);
+
+ for (i = 0; i < 1000; i++) {
+ if ((inb(chip->port+AC97_STATUS) & (AC97_DATA_AVAIL)) != 0)
+ break;
+ udelay(10);
+ }
+ return inw(chip->port+AC97_READ);
+}
+
+static void snd_als300_ac97_write(struct snd_ac97 *ac97,
+ unsigned short reg, unsigned short val)
+{
+ int i;
+ struct snd_als300 *chip = ac97->private_data;
+
+ for (i = 0; i < 1000; i++) {
+ if ((inb(chip->port+AC97_STATUS) & (AC97_BUSY)) == 0)
+ break;
+ udelay(10);
+ }
+ outl((reg << 24) | val, chip->port+AC97_ACCESS);
+}
+
+static int snd_als300_ac97(struct snd_als300 *chip)
+{
+ struct snd_ac97_bus *bus;
+ struct snd_ac97_template ac97;
+ int err;
+ static struct snd_ac97_bus_ops ops = {
+ .write = snd_als300_ac97_write,
+ .read = snd_als300_ac97_read,
+ };
+
+ snd_als300_dbgcallenter();
+ if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0)
+ return err;
+
+ memset(&ac97, 0, sizeof(ac97));
+ ac97.private_data = chip;
+
+ snd_als300_dbgcallleave();
+ return snd_ac97_mixer(bus, &ac97, &chip->ac97);
+}
+
+/* hardware definition
+ *
+ * In AC97 mode, we always use 48k/16bit/stereo.
+ * Any request to change data type is ignored by
+ * the card when it is running outside of legacy
+ * mode.
+ */
+static struct snd_pcm_hardware snd_als300_playback_hw =
+{
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S16,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = 64 * 1024,
+ .period_bytes_min = 64,
+ .period_bytes_max = 32 * 1024,
+ .periods_min = 2,
+ .periods_max = 2,
+};
+
+static struct snd_pcm_hardware snd_als300_capture_hw =
+{
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S16,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = 64 * 1024,
+ .period_bytes_min = 64,
+ .period_bytes_max = 32 * 1024,
+ .periods_min = 2,
+ .periods_max = 2,
+};
+
+static int snd_als300_playback_open(struct snd_pcm_substream *substream)
+{
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
+ GFP_KERNEL);
+
+ snd_als300_dbgcallenter();
+ chip->playback_substream = substream;
+ runtime->hw = snd_als300_playback_hw;
+ runtime->private_data = data;
+ data->control_register = PLAYBACK_CONTROL;
+ data->block_counter_register = PLAYBACK_BLOCK_COUNTER;
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_playback_close(struct snd_pcm_substream *substream)
+{
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_als300_substream_data *data;
+
+ data = substream->runtime->private_data;
+ snd_als300_dbgcallenter();
+ kfree(data);
+ chip->playback_substream = NULL;
+ snd_pcm_lib_free_pages(substream);
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_capture_open(struct snd_pcm_substream *substream)
+{
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
+ GFP_KERNEL);
+
+ snd_als300_dbgcallenter();
+ chip->capture_substream = substream;
+ runtime->hw = snd_als300_capture_hw;
+ runtime->private_data = data;
+ data->control_register = RECORD_CONTROL;
+ data->block_counter_register = RECORD_BLOCK_COUNTER;
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_capture_close(struct snd_pcm_substream *substream)
+{
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_als300_substream_data *data;
+
+ data = substream->runtime->private_data;
+ snd_als300_dbgcallenter();
+ kfree(data);
+ chip->capture_substream = NULL;
+ snd_pcm_lib_free_pages(substream);
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_pcm_hw_params(struct snd_pcm_substream *substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+}
+
+static int snd_als300_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int snd_als300_playback_prepare(struct snd_pcm_substream *substream)
+{
+ u32 tmp;
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned short period_bytes = snd_pcm_lib_period_bytes(substream);
+ unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
+
+ snd_als300_dbgcallenter();
+ spin_lock_irq(&chip->reg_lock);
+ tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL);
+ tmp &= ~TRANSFER_START;
+
+ snd_als300_dbgplay("Period bytes: %d Buffer bytes %d\n",
+ period_bytes, buffer_bytes);
+
+ /* set block size */
+ tmp &= 0xffff0000;
+ tmp |= period_bytes - 1;
+ snd_als300_gcr_write(chip->port, PLAYBACK_CONTROL, tmp);
+
+ /* set dma area */
+ snd_als300_gcr_write(chip->port, PLAYBACK_START,
+ runtime->dma_addr);
+ snd_als300_gcr_write(chip->port, PLAYBACK_END,
+ runtime->dma_addr + buffer_bytes - 1);
+ spin_unlock_irq(&chip->reg_lock);
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_capture_prepare(struct snd_pcm_substream *substream)
+{
+ u32 tmp;
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned short period_bytes = snd_pcm_lib_period_bytes(substream);
+ unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
+
+ snd_als300_dbgcallenter();
+ spin_lock_irq(&chip->reg_lock);
+ tmp = snd_als300_gcr_read(chip->port, RECORD_CONTROL);
+ tmp &= ~TRANSFER_START;
+
+ snd_als300_dbgplay("Period bytes: %d Buffer bytes %d\n", period_bytes,
+ buffer_bytes);
+
+ /* set block size */
+ tmp &= 0xffff0000;
+ tmp |= period_bytes - 1;
+
+ /* set dma area */
+ snd_als300_gcr_write(chip->port, RECORD_CONTROL, tmp);
+ snd_als300_gcr_write(chip->port, RECORD_START,
+ runtime->dma_addr);
+ snd_als300_gcr_write(chip->port, RECORD_END,
+ runtime->dma_addr + buffer_bytes - 1);
+ spin_unlock_irq(&chip->reg_lock);
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static int snd_als300_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ u32 tmp;
+ struct snd_als300_substream_data *data;
+ unsigned short reg;
+ int ret = 0;
+
+ data = substream->runtime->private_data;
+ reg = data->control_register;
+
+ snd_als300_dbgcallenter();
+ spin_lock(&chip->reg_lock);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ tmp = snd_als300_gcr_read(chip->port, reg);
+ data->period_flipflop = 1;
+ snd_als300_gcr_write(chip->port, reg, tmp | TRANSFER_START);
+ snd_als300_dbgplay("TRIGGER START\n");
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ tmp = snd_als300_gcr_read(chip->port, reg);
+ snd_als300_gcr_write(chip->port, reg, tmp & ~TRANSFER_START);
+ snd_als300_dbgplay("TRIGGER STOP\n");
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ tmp = snd_als300_gcr_read(chip->port, reg);
+ snd_als300_gcr_write(chip->port, reg, tmp | FIFO_PAUSE);
+ snd_als300_dbgplay("TRIGGER PAUSE\n");
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ tmp = snd_als300_gcr_read(chip->port, reg);
+ snd_als300_gcr_write(chip->port, reg, tmp & ~FIFO_PAUSE);
+ snd_als300_dbgplay("TRIGGER RELEASE\n");
+ break;
+ default:
+ snd_als300_dbgplay("TRIGGER INVALID\n");
+ ret = -EINVAL;
+ }
+ spin_unlock(&chip->reg_lock);
+ snd_als300_dbgcallleave();
+ return ret;
+}
+
+static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream)
+{
+ u16 current_ptr;
+ struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+ struct snd_als300_substream_data *data;
+ unsigned short period_bytes;
+
+ data = substream->runtime->private_data;
+ period_bytes = snd_pcm_lib_period_bytes(substream);
+
+ snd_als300_dbgcallenter();
+ spin_lock(&chip->reg_lock);
+ current_ptr = (u16) snd_als300_gcr_read(chip->port,
+ data->block_counter_register) + 4;
+ spin_unlock(&chip->reg_lock);
+ if (current_ptr > period_bytes)
+ current_ptr = 0;
+ else
+ current_ptr = period_bytes - current_ptr;
+
+ if (data->period_flipflop == 0)
+ current_ptr += period_bytes;
+ snd_als300_dbgplay("Pointer (bytes): %d\n", current_ptr);
+ snd_als300_dbgcallleave();
+ return bytes_to_frames(substream->runtime, current_ptr);
+}
+
+static struct snd_pcm_ops snd_als300_playback_ops = {
+ .open = snd_als300_playback_open,
+ .close = snd_als300_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_als300_pcm_hw_params,
+ .hw_free = snd_als300_pcm_hw_free,
+ .prepare = snd_als300_playback_prepare,
+ .trigger = snd_als300_trigger,
+ .pointer = snd_als300_pointer,
+};
+
+static struct snd_pcm_ops snd_als300_capture_ops = {
+ .open = snd_als300_capture_open,
+ .close = snd_als300_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_als300_pcm_hw_params,
+ .hw_free = snd_als300_pcm_hw_free,
+ .prepare = snd_als300_capture_prepare,
+ .trigger = snd_als300_trigger,
+ .pointer = snd_als300_pointer,
+};
+
+static int __devinit snd_als300_new_pcm(struct snd_als300 *chip)
+{
+ struct snd_pcm *pcm;
+ int err;
+
+ snd_als300_dbgcallenter();
+ err = snd_pcm_new(chip->card, "ALS300", 0, 1, 1, &pcm);
+ if (err < 0)
+ return err;
+ pcm->private_data = chip;
+ strcpy(pcm->name, "ALS300");
+ chip->pcm = pcm;
+
+ /* set operators */
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_als300_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_als300_capture_ops);
+
+ /* pre-allocation of buffers */
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci), 64*1024, 64*1024);
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+static void snd_als300_init(struct snd_als300 *chip)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ snd_als300_dbgcallenter();
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ chip->revision = (snd_als300_gcr_read(chip->port, MISC_CONTROL) >> 16)
+ & 0x0000000F;
+ /* Setup DRAM */
+ tmp = snd_als300_gcr_read(chip->port, DRAM_WRITE_CONTROL);
+ snd_als300_gcr_write(chip->port, DRAM_WRITE_CONTROL,
+ (tmp | DRAM_MODE_2)
+ & ~WRITE_TRANS_START);
+
+ /* Enable IRQ output */
+ snd_als300_set_irq_flag(chip, IRQ_ENABLE);
+
+ /* Unmute hardware devices so their outputs get routed to
+ * the onboard mixer */
+ tmp = snd_als300_gcr_read(chip->port, MISC_CONTROL);
+ snd_als300_gcr_write(chip->port, MISC_CONTROL,
+ tmp | VMUTE_NORMAL | MMUTE_NORMAL);
+
+ /* Reset volumes */
+ snd_als300_gcr_write(chip->port, MUS_VOC_VOL, 0);
+
+ /* Make sure playback transfer is stopped */
+ tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL);
+ snd_als300_gcr_write(chip->port, PLAYBACK_CONTROL,
+ tmp & ~TRANSFER_START);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ snd_als300_dbgcallleave();
+}
+
+static int __devinit snd_als300_create(snd_card_t *card,
+ struct pci_dev *pci, int chip_type,
+ struct snd_als300 **rchip)
+{
+ struct snd_als300 *chip;
+ void *irq_handler;
+ int err;
+
+ static snd_device_ops_t ops = {
+ .dev_free = snd_als300_dev_free,
+ };
+ *rchip = NULL;
+
+ snd_als300_dbgcallenter();
+ if ((err = pci_enable_device(pci)) < 0)
+ return err;
+
+ if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
+ printk(KERN_ERR "error setting 28bit DMA mask\n");
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
+ pci_set_master(pci);
+
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ pci_disable_device(pci);
+ return -ENOMEM;
+ }
+
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+ chip->chip_type = chip_type;
+ spin_lock_init(&chip->reg_lock);
+
+ if ((err = pci_request_regions(pci, "ALS300")) < 0) {
+ kfree(chip);
+ pci_disable_device(pci);
+ return err;
+ }
+ chip->port = pci_resource_start(pci, 0);
+
+ if (chip->chip_type == DEVICE_ALS300_PLUS)
+ irq_handler = snd_als300plus_interrupt;
+ else
+ irq_handler = snd_als300_interrupt;
+
+ if (request_irq(pci->irq, irq_handler, SA_INTERRUPT|SA_SHIRQ,
+ card->shortname, (void *)chip)) {
+ snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
+ snd_als300_free(chip);
+ return -EBUSY;
+ }
+ chip->irq = pci->irq;
+
+
+ snd_als300_init(chip);
+
+ if (snd_als300_ac97(chip) < 0) {
+ snd_printk(KERN_WARNING "Could not create ac97\n");
+ snd_als300_free(chip);
+ return err;
+ }
+
+ if ((err = snd_als300_new_pcm(chip)) < 0) {
+ snd_printk(KERN_WARNING "Could not create PCM\n");
+ snd_als300_free(chip);
+ return err;
+ }
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
+ chip, &ops)) < 0) {
+ snd_als300_free(chip);
+ return err;
+ }
+
+ snd_card_set_dev(card, &pci->dev);
+
+ *rchip = chip;
+ snd_als300_dbgcallleave();
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_als300_suspend(struct pci_dev *pci, pm_message_t state)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_als300 *chip = card->private_data;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(chip->pcm);
+ snd_ac97_suspend(chip->ac97);
+
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ return 0;
+}
+
+static int snd_als300_resume(struct pci_dev *pci)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_als300 *chip = card->private_data;
+
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
+
+ snd_als300_init(chip);
+ snd_ac97_resume(chip->ac97);
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
+static int __devinit snd_als300_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ static int dev;
+ struct snd_card *card;
+ struct snd_als300 *chip;
+ int err, chip_type;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+
+ if (card == NULL)
+ return -ENOMEM;
+
+ chip_type = pci_id->driver_data;
+
+ if ((err = snd_als300_create(card, pci, chip_type, &chip)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ card->private_data = chip;
+
+ strcpy(card->driver, "ALS300");
+ if (chip->chip_type == DEVICE_ALS300_PLUS)
+ /* don't know much about ALS300+ yet
+ * print revision number for now */
+ sprintf(card->shortname, "ALS300+ (Rev. %d)", chip->revision);
+ else
+ sprintf(card->shortname, "ALS300 (Rev. %c)", 'A' +
+ chip->revision - 1);
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ card->shortname, chip->port, chip->irq);
+
+ if ((err = snd_card_register(card)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
+}
+
+static struct pci_driver driver = {
+ .name = "ALS300",
+ .id_table = snd_als300_ids,
+ .probe = snd_als300_probe,
+ .remove = __devexit_p(snd_als300_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_als300_suspend,
+ .resume = snd_als300_resume,
+#endif
+};
+
+static int __init alsa_card_als300_init(void)
+{
+ return pci_register_driver(&driver);
+}
+
+static void __exit alsa_card_als300_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_als300_init)
+module_exit(alsa_card_als300_exit)
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 7b2ff5f4672..60423b1c678 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -70,6 +70,7 @@
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/rawmidi.h>
@@ -115,7 +116,7 @@ struct snd_card_als4000 {
#endif
};
-static struct pci_device_id snd_als4000_ids[] = {
+static struct pci_device_id snd_als4000_ids[] __devinitdata = {
{ 0x4005, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ALS4000 */
{ 0, }
};
@@ -688,8 +689,8 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
return err;
}
/* check, if we can restrict PCI DMA transfers to 24 bits */
- if (pci_set_dma_mask(pci, 0x00ffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) {
snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 12e61885126..d0f759d86d3 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -284,7 +284,7 @@ struct atiixp {
/*
*/
-static struct pci_device_id snd_atiixp_ids[] = {
+static struct pci_device_id snd_atiixp_ids[] __devinitdata = {
{ 0x1002, 0x4341, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */
{ 0x1002, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB300 */
{ 0x1002, 0x4370, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 1d376604464..12a34c39caa 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -262,7 +262,7 @@ struct atiixp_modem {
/*
*/
-static struct pci_device_id snd_atiixp_ids[] = {
+static struct pci_device_id snd_atiixp_ids[] __devinitdata = {
{ 0x1002, 0x434d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */
{ 0x1002, 0x4378, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */
{ 0, }
diff --git a/sound/pci/au88x0/au8810.c b/sound/pci/au88x0/au8810.c
index fce22c7af0e..bd3352998ad 100644
--- a/sound/pci/au88x0/au8810.c
+++ b/sound/pci/au88x0/au8810.c
@@ -1,6 +1,6 @@
#include "au8810.h"
#include "au88x0.h"
-static struct pci_device_id snd_vortex_ids[] = {
+static struct pci_device_id snd_vortex_ids[] __devinitdata = {
{PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1,},
{0,}
diff --git a/sound/pci/au88x0/au8820.c b/sound/pci/au88x0/au8820.c
index d1fbcce0725..7e3fd8372d8 100644
--- a/sound/pci/au88x0/au8820.c
+++ b/sound/pci/au88x0/au8820.c
@@ -1,6 +1,6 @@
#include "au8820.h"
#include "au88x0.h"
-static struct pci_device_id snd_vortex_ids[] = {
+static struct pci_device_id snd_vortex_ids[] __devinitdata = {
{PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_1,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
{0,}
diff --git a/sound/pci/au88x0/au8830.c b/sound/pci/au88x0/au8830.c
index d4f2717c14f..b840f6608a6 100644
--- a/sound/pci/au88x0/au8830.c
+++ b/sound/pci/au88x0/au8830.c
@@ -1,6 +1,6 @@
#include "au8830.h"
#include "au88x0.h"
-static struct pci_device_id snd_vortex_ids[] = {
+static struct pci_device_id snd_vortex_ids[] __devinitdata = {
{PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
{0,}
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index d65ccb1866a..f078b716d2b 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -19,7 +19,6 @@
#ifdef __KERNEL__
#include <sound/driver.h>
-#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <sound/core.h>
@@ -277,14 +276,14 @@ static void vortex_Vort3D_InitializeSource(a3dsrc_t * a, int en);
#endif
/* Driver stuff. */
-static int __devinit vortex_gameport_register(vortex_t * card);
+static int vortex_gameport_register(vortex_t * card);
static void vortex_gameport_unregister(vortex_t * card);
#ifndef CHIP_AU8820
-static int __devinit vortex_eq_init(vortex_t * vortex);
-static int __devexit vortex_eq_free(vortex_t * vortex);
+static int vortex_eq_init(vortex_t * vortex);
+static int vortex_eq_free(vortex_t * vortex);
#endif
/* ALSA stuff. */
-static int __devinit snd_vortex_new_pcm(vortex_t * vortex, int idx, int nr);
-static int __devinit snd_vortex_mixer(vortex_t * vortex);
-static int __devinit snd_vortex_midi(vortex_t * vortex);
+static int snd_vortex_new_pcm(vortex_t * vortex, int idx, int nr);
+static int snd_vortex_mixer(vortex_t * vortex);
+static int snd_vortex_midi(vortex_t * vortex);
#endif
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 9cac02e93b2..4347e6abc1d 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -2658,7 +2658,7 @@ static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode)
/* Initialization */
-static int vortex_core_init(vortex_t * vortex)
+static int __devinit vortex_core_init(vortex_t * vortex)
{
printk(KERN_INFO "Vortex: init.... ");
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c
index 64fbfbbaf81..0c86a31c433 100644
--- a/sound/pci/au88x0/au88x0_eq.c
+++ b/sound/pci/au88x0/au88x0_eq.c
@@ -885,7 +885,7 @@ static char *EqBandLabels[10] __devinitdata = {
};
/* ALSA driver entry points. Init and exit. */
-static int vortex_eq_init(vortex_t * vortex)
+static int __devinit vortex_eq_init(vortex_t * vortex)
{
struct snd_kcontrol *kcontrol;
int err, i;
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index 6a13ca1d545..7b5baa17385 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -506,7 +506,7 @@ static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
int i;
int err, nr_capt;
- if ((chip == 0) || (idx < 0) || (idx > VORTEX_PCM_LAST))
+ if ((chip == 0) || (idx < 0) || (idx >= VORTEX_PCM_LAST))
return -ENODEV;
/* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index e077eb3fbe2..52a36452426 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -104,6 +104,7 @@
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
@@ -215,7 +216,7 @@ struct snd_azf3328 {
int irq;
};
-static const struct pci_device_id snd_azf3328_ids[] = {
+static const struct pci_device_id snd_azf3328_ids[] __devinitdata = {
{ 0x122D, 0x50DC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* PCI168/3328 */
{ 0x122D, 0x80DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 3328 */
{ 0, }
@@ -1669,8 +1670,8 @@ snd_azf3328_create(struct snd_card *card,
chip->irq = -1;
/* check if we can restrict PCI DMA transfers to 24 bits */
- if (pci_set_dma_mask(pci, 0x00ffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) {
snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");
err = -ENXIO;
goto out_err;
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 7b44a8db033..9ee07d4aac1 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -774,7 +774,7 @@ static int __devinit snd_bt87x_create(struct snd_card *card,
.driver_data = rate }
/* driver_data is the default digital_rate value for that device */
-static struct pci_device_id snd_bt87x_ids[] = {
+static struct pci_device_id snd_bt87x_ids[] __devinitdata = {
/* Hauppauge WinTV series */
BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, 32000),
/* Hauppauge WinTV series */
@@ -911,7 +911,7 @@ static void __devexit snd_bt87x_remove(struct pci_dev *pci)
/* default entries for all Bt87x cards - it's not exported */
/* driver_data is set to 0 to call detection */
-static struct pci_device_id snd_bt87x_default_ids[] = {
+static struct pci_device_id snd_bt87x_default_ids[] __devinitdata = {
BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, 0),
BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, 0),
{ }
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 9477838a9c8..fd8bfebfbd5 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1561,7 +1561,7 @@ static void __devexit snd_ca0106_remove(struct pci_dev *pci)
}
// PCI IDs
-static struct pci_device_id snd_ca0106_ids[] = {
+static struct pci_device_id snd_ca0106_ids[] __devinitdata = {
{ 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */
{ 0, }
};
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 2ecbddbbdcf..e5ce2dabd08 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2609,7 +2609,7 @@ static inline void snd_cmipci_proc_init(struct cmipci *cm) {}
#endif
-static struct pci_device_id snd_cmipci_ids[] = {
+static struct pci_device_id snd_cmipci_ids[] __devinitdata = {
{PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 4f65ec56bf3..b3c94d83450 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -494,7 +494,7 @@ struct cs4281 {
static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static struct pci_device_id snd_cs4281_ids[] = {
+static struct pci_device_id snd_cs4281_ids[] __devinitdata = {
{ 0x1013, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4281 */
{ 0, }
};
@@ -1046,7 +1046,7 @@ static int snd_cs4281_put_volume(struct snd_kcontrol *kcontrol,
snd_cs4281_pokeBA0(chip, regL, volL);
change = 1;
}
- if (ucontrol->value.integer.value[0] != volL) {
+ if (ucontrol->value.integer.value[1] != volR) {
volR = CS_VOL_MASK - (ucontrol->value.integer.value[1] & CS_VOL_MASK);
snd_cs4281_pokeBA0(chip, regR, volR);
change = 1;
@@ -1416,7 +1416,7 @@ static int __devinit snd_cs4281_create(struct snd_card *card,
static int snd_cs4281_chip_init(struct cs4281 *chip)
{
unsigned int tmp;
- int timeout;
+ unsigned long end_time;
int retry_count = 2;
/* Having EPPMC.FPDN=1 prevent proper chip initialisation */
@@ -1496,7 +1496,7 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
/*
* Wait for the DLL ready signal from the clock logic.
*/
- timeout = 100;
+ end_time = jiffies + HZ;
do {
/*
* Read the AC97 status register to see if we've seen a CODEC
@@ -1504,8 +1504,8 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
*/
if (snd_cs4281_peekBA0(chip, BA0_CLKCR1) & BA0_CLKCR1_DLLRDY)
goto __ok0;
- msleep(1);
- } while (timeout-- > 0);
+ schedule_timeout_uninterruptible(1);
+ } while (time_after_eq(end_time, jiffies));
snd_printk(KERN_ERR "DLLRDY not seen\n");
return -EIO;
@@ -1522,7 +1522,7 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
/*
* Wait for the codec ready signal from the AC97 codec.
*/
- timeout = 100;
+ end_time = jiffies + HZ;
do {
/*
* Read the AC97 status register to see if we've seen a CODEC
@@ -1530,20 +1530,20 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
*/
if (snd_cs4281_peekBA0(chip, BA0_ACSTS) & BA0_ACSTS_CRDY)
goto __ok1;
- msleep(1);
- } while (timeout-- > 0);
+ schedule_timeout_uninterruptible(1);
+ } while (time_after_eq(end_time, jiffies));
snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS));
return -EIO;
__ok1:
if (chip->dual_codec) {
- timeout = 100;
+ end_time = jiffies + HZ;
do {
if (snd_cs4281_peekBA0(chip, BA0_ACSTS2) & BA0_ACSTS_CRDY)
goto __codec2_ok;
- msleep(1);
- } while (timeout-- > 0);
+ schedule_timeout_uninterruptible(1);
+ } while (time_after_eq(end_time, jiffies));
snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n");
chip->dual_codec = 0;
__codec2_ok: ;
@@ -1561,7 +1561,7 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
* the codec is pumping ADC data across the AC-link.
*/
- timeout = 100;
+ end_time = jiffies + HZ;
do {
/*
* Read the input slot valid register and see if input slots 3
@@ -1569,8 +1569,8 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
*/
if ((snd_cs4281_peekBA0(chip, BA0_ACISV) & (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) == (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4)))
goto __ok2;
- msleep(1);
- } while (timeout-- > 0);
+ schedule_timeout_uninterruptible(1);
+ } while (time_after_eq(end_time, jiffies));
if (--retry_count > 0)
goto __retry;
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index c590602e20c..848d772ae3c 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -65,7 +65,7 @@ MODULE_PARM_DESC(thinkpad, "Force to enable Thinkpad's CLKRUN control.");
module_param_array(mmap_valid, bool, NULL, 0444);
MODULE_PARM_DESC(mmap_valid, "Support OSS mmap.");
-static struct pci_device_id snd_cs46xx_ids[] = {
+static struct pci_device_id snd_cs46xx_ids[] __devinitdata = {
{ 0x1013, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4280 */
{ 0x1013, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4612 */
{ 0x1013, 0x6004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4615 */
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 9fc7f382746..2c1213a35dc 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -45,7 +45,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-static struct pci_device_id snd_cs5535audio_ids[] = {
+static struct pci_device_id snd_cs5535audio_ids[] __devinitdata = {
{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO,
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 2dfa932f782..42b11ba1d21 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -77,7 +77,7 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
/*
* Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400
*/
-static struct pci_device_id snd_emu10k1_ids[] = {
+static struct pci_device_id snd_emu10k1_ids[] __devinitdata = {
{ 0x1102, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* EMU10K1 */
{ 0x1102, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, /* Audigy */
{ 0x1102, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, /* Audigy 2 Value SB0400 */
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 31cb9b48bb5..6bfa08436ef 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -843,8 +843,11 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.spdif_bug = 1,
.ac97_chip = 1} ,
/* Tested by shane-alsa@cm.nu 5th Nov 2005 */
+ /* The 0x20061102 does have SB0350 written on it
+ * Just like 0x20021102
+ */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20061102,
- .driver = "Audigy2", .name = "Audigy 2 [2006]",
+ .driver = "Audigy2", .name = "Audigy 2 [SB0350b]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 2208dbd48be..d51290c1816 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -1595,7 +1595,7 @@ static void __devexit snd_emu10k1x_remove(struct pci_dev *pci)
}
// PCI IDs
-static struct pci_device_id snd_emu10k1x_ids[] = {
+static struct pci_device_id snd_emu10k1x_ids[] __devinitdata = {
{ 0x1102, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Dell OEM version (EMU10K1) */
{ 0, }
};
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index a5533c86b0b..ca9e34e88f6 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -446,7 +446,7 @@ struct ensoniq {
static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static struct pci_device_id snd_audiopci_ids[] = {
+static struct pci_device_id snd_audiopci_ids[] __devinitdata = {
#ifdef CHIP1370
{ 0x1274, 0x5000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ES1370 */
#endif
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 0d556b09ad0..6f9094ca4fb 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -55,6 +55,7 @@
#include <linux/gameport.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
@@ -241,7 +242,7 @@ struct es1938 {
static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static struct pci_device_id snd_es1938_ids[] = {
+static struct pci_device_id snd_es1938_ids[] __devinitdata = {
{ 0x125d, 0x1969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Solo-1 */
{ 0, }
};
@@ -1517,8 +1518,8 @@ static int __devinit snd_es1938_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 24 bits */
- if (pci_set_dma_mask(pci, 0x00ffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) {
snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index dd465a186e1..5ff4175c7b6 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -592,7 +592,7 @@ struct es1968 {
static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static struct pci_device_id snd_es1968_ids[] = {
+static struct pci_device_id snd_es1968_ids[] __devinitdata = {
/* Maestro 1 */
{ 0x1285, 0x0100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO },
/* Maestro 2 */
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 6ab4aefbccf..d72fc28c580 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -199,7 +199,7 @@ struct fm801 {
#endif
};
-static struct pci_device_id snd_fm801_ids[] = {
+static struct pci_device_id snd_fm801_ids[] __devinitdata = {
{ 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */
{ 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */
{ 0, }
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index b42dff7ceed..5bee3b53647 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -295,7 +295,7 @@ static int init_unsol_queue(struct hda_bus *bus)
snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
return -ENOMEM;
}
- unsol->workq = create_workqueue("hda_codec");
+ unsol->workq = create_singlethread_workqueue("hda_codec");
if (! unsol->workq) {
snd_printk(KERN_ERR "hda_codec: can't create workqueue\n");
kfree(unsol);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index c096606970f..e821d65afa1 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -81,6 +81,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, ESB2},"
"{Intel, ICH8},"
"{ATI, SB450},"
+ "{ATI, SB600},"
"{VIA, VT8251},"
"{VIA, VT8237A},"
"{SiS, SIS966},"
@@ -1613,12 +1614,13 @@ static void __devexit azx_remove(struct pci_dev *pci)
}
/* PCI IDs */
-static struct pci_device_id azx_ids[] = {
+static struct pci_device_id azx_ids[] __devinitdata = {
{ 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */
{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */
{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
{ 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
+ { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 32401bd8c22..40f000ba136 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -44,6 +44,7 @@ struct ad198x_spec {
* dig_out_nid and hp_nid are optional
*/
unsigned int cur_eapd;
+ unsigned int need_dac_fix;
/* capture */
unsigned int num_adc_nids;
@@ -798,8 +799,16 @@ static struct hda_board_config ad1986a_cfg_tbl[] = {
{ .modelname = "laptop-eapd", .config = AD1986A_LAPTOP_EAPD },
{ .pci_subvendor = 0x144d, .pci_subdevice = 0xc024,
.config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1153,
+ .config = AD1986A_LAPTOP_EAPD }, /* ASUS M9 */
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1213,
.config = AD1986A_LAPTOP_EAPD }, /* ASUS A6J */
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x11f7,
+ .config = AD1986A_LAPTOP_EAPD }, /* ASUS U5A */
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1297,
+ .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x30af,
+ .config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */
{}
};
@@ -836,10 +845,14 @@ static int patch_ad1986a(struct hda_codec *codec)
case AD1986A_3STACK:
spec->num_mixers = 2;
spec->mixers[1] = ad1986a_3st_mixers;
- spec->num_init_verbs = 2;
+ spec->num_init_verbs = 3;
spec->init_verbs[1] = ad1986a_3st_init_verbs;
+ spec->init_verbs[2] = ad1986a_ch2_init;
spec->channel_mode = ad1986a_modes;
spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
+ spec->need_dac_fix = 1;
+ spec->multiout.max_channels = 2;
+ spec->multiout.num_dacs = 1;
break;
case AD1986A_LAPTOP:
spec->mixers[0] = ad1986a_laptop_mixers;
@@ -1321,10 +1334,8 @@ enum { AD1981_BASIC, AD1981_HP };
static struct hda_board_config ad1981_cfg_tbl[] = {
{ .modelname = "hp", .config = AD1981_HP },
- { .pci_subvendor = 0x103c, .pci_subdevice = 0x30aa,
- .config = AD1981_HP }, /* HP nx6320 */
- { .pci_subvendor = 0x103c, .pci_subdevice = 0x309f,
- .config = AD1981_HP }, /* HP nx9420 AngelFire */
+ /* All HP models */
+ { .pci_subvendor = 0x103c, .config = AD1981_HP },
{ .modelname = "basic", .config = AD1981_BASIC },
{}
};
@@ -1555,6 +1566,8 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *spec = codec->spec;
+ if (spec->need_dac_fix)
+ spec->multiout.num_dacs = spec->multiout.max_channels / 2;
return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
spec->num_channel_mode, &spec->multiout.max_channels);
}
@@ -2610,5 +2623,6 @@ struct hda_codec_preset snd_hda_preset_analog[] = {
{ .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
{ .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
+ { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
{} /* terminator */
};
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 4c6c9ec8ea5..f0e9a9c9078 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -52,6 +52,7 @@ enum {
ALC880_CLEVO,
ALC880_TCL_S700,
ALC880_LG,
+ ALC880_LG_LW,
#ifdef CONFIG_SND_DEBUG
ALC880_TEST,
#endif
@@ -131,6 +132,7 @@ struct alc_spec {
hda_nid_t dig_in_nid; /* digital-in NID; optional */
/* capture source */
+ unsigned int num_mux_defs;
const struct hda_input_mux *input_mux;
unsigned int cur_mux[3];
@@ -172,6 +174,7 @@ struct alc_config_preset {
hda_nid_t dig_in_nid;
unsigned int num_channel_mode;
const struct hda_channel_mode *channel_mode;
+ unsigned int num_mux_defs;
const struct hda_input_mux *input_mux;
void (*unsol_event)(struct hda_codec *, unsigned int);
void (*init_hook)(struct hda_codec *);
@@ -185,7 +188,10 @@ static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- return snd_hda_input_mux_info(spec->input_mux, uinfo);
+ unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
+ if (mux_idx >= spec->num_mux_defs)
+ mux_idx = 0;
+ return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
}
static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
@@ -203,7 +209,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+ unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
+ return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
}
@@ -245,7 +252,8 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
* states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
* are requested. Therefore order this list so that this behaviour will not
* cause problems when mixer clients move through the enum sequentially.
- * NIDs 0x0f and 0x10 have been observed to have this behaviour.
+ * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
+ * March 2006.
*/
static char *alc_pin_mode_names[] = {
"Mic 50pc bias", "Mic 80pc bias",
@@ -255,19 +263,27 @@ static unsigned char alc_pin_mode_values[] = {
PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
};
/* The control can present all 5 options, or it can limit the options based
- * in the pin being assumed to be exclusively an input or an output pin.
+ * in the pin being assumed to be exclusively an input or an output pin. In
+ * addition, "input" pins may or may not process the mic bias option
+ * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
+ * accept requests for bias as of chip versions up to March 2006) and/or
+ * wiring in the computer.
*/
-#define ALC_PIN_DIR_IN 0x00
-#define ALC_PIN_DIR_OUT 0x01
-#define ALC_PIN_DIR_INOUT 0x02
+#define ALC_PIN_DIR_IN 0x00
+#define ALC_PIN_DIR_OUT 0x01
+#define ALC_PIN_DIR_INOUT 0x02
+#define ALC_PIN_DIR_IN_NOMICBIAS 0x03
+#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
-/* Info about the pin modes supported by the three different pin directions.
+/* Info about the pin modes supported by the different pin direction modes.
* For each direction the minimum and maximum values are given.
*/
-static signed char alc_pin_mode_dir_info[3][2] = {
+static signed char alc_pin_mode_dir_info[5][2] = {
{ 0, 2 }, /* ALC_PIN_DIR_IN */
{ 3, 4 }, /* ALC_PIN_DIR_OUT */
{ 0, 4 }, /* ALC_PIN_DIR_INOUT */
+ { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */
+ { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */
};
#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
@@ -329,9 +345,10 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
* input modes.
*
* Dynamically switching the input/output buffers probably
- * reduces noise slightly, particularly on input. However,
- * havingboth input and output buffers enabled
- * simultaneously doesn't seem to be problematic.
+ * reduces noise slightly (particularly on input) so we'll
+ * do it. However, having both input and output buffers
+ * enabled simultaneously doesn't seem to be problematic if
+ * this turns out to be necessary in the future.
*/
if (val <= 2) {
snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE,
@@ -483,6 +500,9 @@ static void setup_preset(struct alc_spec *spec, const struct alc_config_preset *
spec->multiout.dig_out_nid = preset->dig_out_nid;
spec->multiout.hp_nid = preset->hp_nid;
+ spec->num_mux_defs = preset->num_mux_defs;
+ if (! spec->num_mux_defs)
+ spec->num_mux_defs = 1;
spec->input_mux = preset->input_mux;
spec->num_adc_nids = preset->num_adc_nids;
@@ -1427,6 +1447,82 @@ static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res)
}
/*
+ * LG LW20
+ *
+ * Pin assignment:
+ * Speaker-out: 0x14
+ * Mic-In: 0x18
+ * Built-in Mic-In: 0x19 (?)
+ * HP-Out: 0x1b
+ * SPDIF-Out: 0x1e
+ */
+
+/* seems analog CD is not working */
+static struct hda_input_mux alc880_lg_lw_capture_source = {
+ .num_items = 2,
+ .items = {
+ { "Mic", 0x0 },
+ { "Internal Mic", 0x1 },
+ },
+};
+
+static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
+ HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+ { } /* end */
+};
+
+static struct hda_verb alc880_lg_lw_init_verbs[] = {
+ /* set capture source to mic-in */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
+ /* speaker-out */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* HP-out */
+ {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* mic-in to input */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* built-in mic */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* jack sense */
+ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},
+ { }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc880_lg_lw_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x1b, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+ 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+ 0x80, present ? 0x80 : 0);
+}
+
+static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ /* Looks like the unsol event is incompatible with the standard
+ * definition. 4bit tag is placed at 28 bit!
+ */
+ if ((res >> 28) == 0x01)
+ alc880_lg_lw_automute(codec);
+}
+
+/*
* Common callbacks
*/
@@ -2052,6 +2148,7 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0087, .config = ALC880_6ST_DIG },
{ .pci_subvendor = 0x1297, .pci_subdevice = 0xc790, .config = ALC880_6ST_DIG }, /* Shuttle ST20G5 */
{ .pci_subvendor = 0x1509, .pci_subdevice = 0x925d, .config = ALC880_6ST_DIG }, /* FIC P4M-915GD1 */
+ { .pci_subvendor = 0x1695, .pci_subdevice = 0x4012, .config = ALC880_5ST_DIG }, /* Epox EP-5LDA+ GLi */
{ .modelname = "asus", .config = ALC880_ASUS },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
@@ -2078,6 +2175,9 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .modelname = "lg", .config = ALC880_LG },
{ .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG },
+ { .modelname = "lg-lw", .config = ALC880_LG_LW },
+ { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW },
+
#ifdef CONFIG_SND_DEBUG
{ .modelname = "test", .config = ALC880_TEST },
#endif
@@ -2268,6 +2368,19 @@ static struct alc_config_preset alc880_presets[] = {
.unsol_event = alc880_lg_unsol_event,
.init_hook = alc880_lg_automute,
},
+ [ALC880_LG_LW] = {
+ .mixers = { alc880_lg_lw_mixer },
+ .init_verbs = { alc880_volume_init_verbs,
+ alc880_lg_lw_init_verbs },
+ .num_dacs = 1,
+ .dac_nids = alc880_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+ .channel_mode = alc880_2_jack_modes,
+ .input_mux = &alc880_lg_lw_capture_source,
+ .unsol_event = alc880_lg_lw_unsol_event,
+ .init_hook = alc880_lg_lw_automute,
+ },
#ifdef CONFIG_SND_DEBUG
[ALC880_TEST] = {
.mixers = { alc880_test_mixer },
@@ -2593,6 +2706,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
+ spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
return 1;
@@ -2722,30 +2836,56 @@ static struct hda_input_mux alc260_capture_source = {
};
/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
- * headphone jack and the internal CD lines.
+ * headphone jack and the internal CD lines since these are the only pins at
+ * which audio can appear. For flexibility, also allow the option of
+ * recording the mixer output on the second ADC (ADC0 doesn't have a
+ * connection to the mixer output).
*/
-static struct hda_input_mux alc260_fujitsu_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic/Line", 0x0 },
- { "CD", 0x4 },
- { "Headphone", 0x2 },
+static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
+ {
+ .num_items = 3,
+ .items = {
+ { "Mic/Line", 0x0 },
+ { "CD", 0x4 },
+ { "Headphone", 0x2 },
+ },
},
+ {
+ .num_items = 4,
+ .items = {
+ { "Mic/Line", 0x0 },
+ { "CD", 0x4 },
+ { "Headphone", 0x2 },
+ { "Mixer", 0x5 },
+ },
+ },
+
};
-/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configutation to
- * the Fujitsu S702x, but jacks are marked differently. We won't allow
- * retasking the Headphone jack, so it won't be available here.
+/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
+ * the Fujitsu S702x, but jacks are marked differently.
*/
-static struct hda_input_mux alc260_acer_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
+static struct hda_input_mux alc260_acer_capture_sources[2] = {
+ {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ { "Headphone", 0x5 },
+ },
+ },
+ {
+ .num_items = 5,
+ .items = {
+ { "Mic", 0x0 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ { "Headphone", 0x6 },
+ { "Mixer", 0x5 },
+ },
},
};
-
/*
* This is just place-holder, so there's something for alc_build_pcms to look
* at when it calculates the maximum number of channels. ALC260 has no mixer
@@ -2806,6 +2946,9 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
{ } /* end */
};
+/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,
+ * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10.
+ */
static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
@@ -2822,9 +2965,28 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
{ } /* end */
};
+/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current
+ * versions of the ALC260 don't act on requests to enable mic bias from NID
+ * 0x0f (used to drive the headphone jack in these laptops). The ALC260
+ * datasheet doesn't mention this restriction. At this stage it's not clear
+ * whether this behaviour is intentional or is a hardware bug in chip
+ * revisions available in early 2006. Therefore for now allow the
+ * "Headphone Jack Mode" control to span all choices, but if it turns out
+ * that the lack of mic bias for this NID is intentional we could change the
+ * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
+ *
+ * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
+ * don't appear to make the mic bias available from the "line" jack, even
+ * though the NID used for this jack (0x14) can supply it. The theory is
+ * that perhaps Acer have included blocking capacitors between the ALC260
+ * and the output jack. If this turns out to be the case for all such
+ * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
+ * to ALC_PIN_DIR_INOUT_NOMICBIAS.
+ */
static struct snd_kcontrol_new alc260_acer_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
+ ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
@@ -3038,7 +3200,8 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = {
};
/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
- * laptops.
+ * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
+ * audio = 0x16, internal speaker = 0x10.
*/
static struct hda_verb alc260_fujitsu_init_verbs[] = {
/* Disable all GPIOs */
@@ -3185,10 +3348,10 @@ static struct hda_verb alc260_acer_init_verbs[] = {
{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
/* Do similar with the second ADC: mute capture input amp and
- * set ADC connection to line (on line1 pin)
+ * set ADC connection to mic to match ALSA's default state.
*/
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
+ {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
/* Mute all inputs to mixer widget (even unconnected ones) */
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
@@ -3213,26 +3376,35 @@ static hda_nid_t alc260_test_dac_nids[1] = {
static hda_nid_t alc260_test_adc_nids[2] = {
0x04, 0x05,
};
-/* This is a bit messy since the two input muxes in the ALC260 have slight
- * variations in their signal assignments. The ideal way to deal with this
- * is to extend alc_spec.input_mux to allow a different input MUX for each
- * ADC. For the purposes of the test model it's sufficient to just list
- * both options for affected signal indices. The separate input mux
- * functionality only needs to be considered if a model comes along which
- * actually uses signals 0x5, 0x6 and 0x7 for something which makes sense to
- * record.
+/* For testing the ALC260, each input MUX needs its own definition since
+ * the signal assignments are different. This assumes that the first ADC
+ * is NID 0x04.
*/
-static struct hda_input_mux alc260_test_capture_source = {
- .num_items = 8,
- .items = {
- { "MIC1 pin", 0x0 },
- { "MIC2 pin", 0x1 },
- { "LINE1 pin", 0x2 },
- { "LINE2 pin", 0x3 },
- { "CD pin", 0x4 },
- { "LINE-OUT pin (cap1), Mixer (cap2)", 0x5 },
- { "HP-OUT pin (cap1), LINE-OUT pin (cap2)", 0x6 },
- { "HP-OUT pin (cap2 only)", 0x7 },
+static struct hda_input_mux alc260_test_capture_sources[2] = {
+ {
+ .num_items = 7,
+ .items = {
+ { "MIC1 pin", 0x0 },
+ { "MIC2 pin", 0x1 },
+ { "LINE1 pin", 0x2 },
+ { "LINE2 pin", 0x3 },
+ { "CD pin", 0x4 },
+ { "LINE-OUT pin", 0x5 },
+ { "HP-OUT pin", 0x6 },
+ },
+ },
+ {
+ .num_items = 8,
+ .items = {
+ { "MIC1 pin", 0x0 },
+ { "MIC2 pin", 0x1 },
+ { "LINE1 pin", 0x2 },
+ { "LINE2 pin", 0x3 },
+ { "CD pin", 0x4 },
+ { "Mixer", 0x5 },
+ { "LINE-OUT pin", 0x6 },
+ { "HP-OUT pin", 0x7 },
+ },
},
};
static struct snd_kcontrol_new alc260_test_mixer[] = {
@@ -3244,7 +3416,17 @@ static struct snd_kcontrol_new alc260_test_mixer[] = {
HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
- /* Modes for retasking pin widgets */
+ /* Modes for retasking pin widgets
+ * Note: the ALC260 doesn't seem to act on requests to enable mic
+ * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't
+ * mention this restriction. At this stage it's not clear whether
+ * this behaviour is intentional or is a hardware bug in chip
+ * revisions available at least up until early 2006. Therefore for
+ * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
+ * choices, but if it turns out that the lack of mic bias for these
+ * NIDs is intentional we could change their modes from
+ * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
+ */
ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
@@ -3606,6 +3788,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
+ spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
/* check whether NID 0x04 is valid */
@@ -3711,7 +3894,8 @@ static struct alc_config_preset alc260_presets[] = {
.adc_nids = alc260_dual_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
- .input_mux = &alc260_fujitsu_capture_source,
+ .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
+ .input_mux = alc260_fujitsu_capture_sources,
},
[ALC260_ACER] = {
.mixers = { alc260_acer_mixer,
@@ -3723,7 +3907,8 @@ static struct alc_config_preset alc260_presets[] = {
.adc_nids = alc260_dual_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
- .input_mux = &alc260_acer_capture_source,
+ .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
+ .input_mux = alc260_acer_capture_sources,
},
#ifdef CONFIG_SND_DEBUG
[ALC260_TEST] = {
@@ -3736,7 +3921,8 @@ static struct alc_config_preset alc260_presets[] = {
.adc_nids = alc260_test_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
- .input_mux = &alc260_test_capture_source,
+ .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
+ .input_mux = alc260_test_capture_sources,
},
#endif
};
@@ -3828,7 +4014,6 @@ static struct hda_input_mux alc882_capture_source = {
{ "CD", 0x4 },
},
};
-
#define alc882_mux_enum_info alc_mux_enum_info
#define alc882_mux_enum_get alc_mux_enum_get
@@ -4730,6 +4915,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
+ spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
return 1;
@@ -5406,6 +5592,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
+ spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
spec->adc_nids = alc861_adc_nids;
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index b56ca401939..8c440fb9860 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -310,6 +310,9 @@ static struct hda_board_config stac922x_cfg_tbl[] = {
.pci_subdevice = 0x0b0b,
.config = STAC_D945GTP3 }, /* Intel D945PSN - 3 Stack, 9221 A1 */
{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
+ .pci_subdevice = 0x0707,
+ .config = STAC_D945GTP5 }, /* Intel D945PSV - 5 Stack */
+ { .pci_subvendor = PCI_VENDOR_ID_INTEL,
.pci_subdevice = 0x0404,
.config = STAC_D945GTP5 }, /* Intel D945GTP - 5 Stack */
{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
@@ -534,6 +537,22 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
return 0;
}
+static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid)
+{
+ unsigned int pincap = snd_hda_param_read(codec, nid,
+ AC_PAR_PIN_CAP);
+ pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
+ if (pincap & AC_PINCAP_VREF_100)
+ return AC_PINCTL_VREF_100;
+ if (pincap & AC_PINCAP_VREF_80)
+ return AC_PINCTL_VREF_80;
+ if (pincap & AC_PINCAP_VREF_50)
+ return AC_PINCTL_VREF_50;
+ if (pincap & AC_PINCAP_VREF_GRD)
+ return AC_PINCTL_VREF_GRD;
+ return 0;
+}
+
static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type)
{
@@ -571,9 +590,12 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
if (val)
stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
- else
- stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
-
+ else {
+ unsigned int pinctl = AC_PINCTL_IN_EN;
+ if (io_idx) /* set VREF for mic */
+ pinctl |= stac92xx_get_vref(codec, nid);
+ stac92xx_auto_set_pinctl(codec, nid, pinctl);
+ }
return 1;
}
@@ -767,13 +789,8 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin
return 0;
wid_caps = get_wcaps(codec, pin);
- if (wid_caps & AC_WCAP_UNSOL_CAP) {
- /* Enable unsolicited responses on the HP widget */
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- STAC_UNSOL_ENABLE);
+ if (wid_caps & AC_WCAP_UNSOL_CAP)
spec->hp_detect = 1;
- }
nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
for (i = 0; i < cfg->line_outs; i++) {
@@ -896,13 +913,8 @@ static int stac9200_auto_create_hp_ctls(struct hda_codec *codec,
return 0;
wid_caps = get_wcaps(codec, pin);
- if (wid_caps & AC_WCAP_UNSOL_CAP) {
- /* Enable unsolicited responses on the HP widget */
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- STAC_UNSOL_ENABLE);
+ if (wid_caps & AC_WCAP_UNSOL_CAP)
spec->hp_detect = 1;
- }
return 0;
}
@@ -944,6 +956,10 @@ static int stac92xx_init(struct hda_codec *codec)
/* set up pins */
if (spec->hp_detect) {
+ /* Enable unsolicited responses on the HP widget */
+ snd_hda_codec_write(codec, cfg->hp_pin, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ STAC_UNSOL_ENABLE);
/* fake event to set up pins */
codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
} else {
@@ -951,9 +967,13 @@ static int stac92xx_init(struct hda_codec *codec)
stac92xx_auto_init_hp_out(codec);
}
for (i = 0; i < AUTO_PIN_LAST; i++) {
- if (cfg->input_pins[i])
- stac92xx_auto_set_pinctl(codec, cfg->input_pins[i],
- AC_PINCTL_IN_EN);
+ hda_nid_t nid = cfg->input_pins[i];
+ if (nid) {
+ unsigned int pinctl = AC_PINCTL_IN_EN;
+ if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC)
+ pinctl |= stac92xx_get_vref(codec, nid);
+ stac92xx_auto_set_pinctl(codec, nid, pinctl);
+ }
}
if (cfg->dig_out_pin)
stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
@@ -1192,8 +1212,8 @@ static hda_nid_t vaio_mux_nids[] = { 0x15 };
static struct hda_input_mux vaio_mux = {
.num_items = 2,
.items = {
- /* { "HP", 0x0 },
- { "Unknown", 0x1 }, */
+ /* { "HP", 0x0 }, */
+ { "Line", 0x1 },
{ "Mic", 0x2 },
{ "PCM", 0x3 },
}
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 7e6608b14ab..336dc489aee 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -87,7 +87,151 @@
#define CS8415_C_BUFFER 0x20
#define CS8415_ID 0x7F
-static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, unsigned short val) {
+/* PCA9554 registers */
+#define PCA9554_DEV 0x40 /* I2C device address */
+#define PCA9554_IN 0x00 /* input port */
+#define PCA9554_OUT 0x01 /* output port */
+#define PCA9554_INVERT 0x02 /* input invert */
+#define PCA9554_DIR 0x03 /* port directions */
+
+/*
+ * Aureon Universe additional controls using PCA9554
+ */
+
+/*
+ * Send data to pca9554
+ */
+static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
+ unsigned char data)
+{
+ unsigned int tmp;
+ int i, j;
+ unsigned char dev = PCA9554_DEV; /* ID 0100000, write */
+ unsigned char val = 0;
+
+ tmp = snd_ice1712_gpio_read(ice);
+
+ snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
+ AUREON_WM_RW|AUREON_WM_CS|
+ AUREON_CS8415_CS));
+ tmp |= AUREON_WM_RW;
+ tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
+
+ tmp &= ~AUREON_SPI_MOSI;
+ tmp &= ~AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(50);
+
+ /*
+ * send i2c stop condition and start condition
+ * to obtain sane state
+ */
+ tmp |= AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(50);
+ tmp |= AUREON_SPI_MOSI;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(100);
+ tmp &= ~AUREON_SPI_MOSI;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(50);
+ tmp &= ~AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(100);
+ /*
+ * send device address, command and value,
+ * skipping ack cycles inbetween
+ */
+ for (j = 0; j < 3; j++) {
+ switch(j) {
+ case 0: val = dev; break;
+ case 1: val = reg; break;
+ case 2: val = data; break;
+ }
+ for (i = 7; i >= 0; i--) {
+ tmp &= ~AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ if (val & (1 << i))
+ tmp |= AUREON_SPI_MOSI;
+ else
+ tmp &= ~AUREON_SPI_MOSI;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ tmp |= AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ }
+ tmp &= ~AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ tmp |= AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ tmp &= ~AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ }
+ tmp &= ~AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ tmp &= ~AUREON_SPI_MOSI;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(40);
+ tmp |= AUREON_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(50);
+ tmp |= AUREON_SPI_MOSI;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(100);
+}
+
+static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 3;
+ if(uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = ice->spec.aureon.pca9554_out;
+ return 0;
+}
+
+static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+ unsigned char oval, nval;
+ int change;
+
+ snd_ice1712_save_gpio_status(ice);
+
+ oval = ice->spec.aureon.pca9554_out;
+ nval = ucontrol->value.integer.value[0];
+ if ((change = (oval != nval))) {
+ aureon_pca9554_write(ice, PCA9554_OUT, nval);
+ ice->spec.aureon.pca9554_out = nval;
+ }
+ snd_ice1712_restore_gpio_status(ice);
+
+ return change;
+}
+
+
+static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
+ unsigned short val)
+{
unsigned int tmp;
/* Send address to XILINX chip */
@@ -146,7 +290,8 @@ static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short r
/*
* Initialize STAC9744 chip
*/
-static int aureon_ac97_init (struct snd_ice1712 *ice) {
+static int aureon_ac97_init (struct snd_ice1712 *ice)
+{
int i;
static unsigned short ac97_defaults[] = {
0x00, 0x9640,
@@ -1598,7 +1743,15 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
.get = aureon_ac97_vol_get,
.put = aureon_ac97_vol_put,
.private_value = AC97_VIDEO|AUREON_AC97_STEREO
- }
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Aux Source",
+ .info = aureon_universe_inmux_info,
+ .get = aureon_universe_inmux_get,
+ .put = aureon_universe_inmux_put
+ }
+
};
@@ -1856,6 +2009,10 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
}
snd_ice1712_restore_gpio_status(ice);
+
+ /* initialize PCA9554 pin directions & set default input*/
+ aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
+ aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
ice->spec.aureon.master[0] = WM_VOL_MUTE;
ice->spec.aureon.master[1] = WM_VOL_MUTE;
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 672e198317e..c56793b381e 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -57,6 +57,7 @@
#include <linux/slab.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
+
#include <sound/core.h>
#include <sound/cs8427.h>
#include <sound/info.h>
@@ -106,7 +107,7 @@ module_param_array(dxr_enable, int, NULL, 0444);
MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE.");
-static struct pci_device_id snd_ice1712_ids[] = {
+static struct pci_device_id snd_ice1712_ids[] __devinitdata = {
{ PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_ICE_1712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICE1712 */
{ 0, }
};
@@ -2400,7 +2401,7 @@ static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice)
if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && !ice->dxr_enable) {
/* Limit active ADCs and DACs to 6; */
/* Note: DXR extension not supported */
- pci_write_config_byte(ice->pci, 0x60, 0x0a);
+ pci_write_config_byte(ice->pci, 0x60, 0x2a);
} else {
pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]);
}
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index f9b22d4a393..053f8e56fd6 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -373,6 +373,7 @@ struct snd_ice1712 {
unsigned int cs8415_mux;
unsigned short master[2];
unsigned short vol[8];
+ unsigned char pca9554_out;
} aureon;
/* AC97 register cache for Phase28 */
struct phase28_spec {
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index fce616c2761..b1c007e022d 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -86,7 +86,7 @@ MODULE_PARM_DESC(model, "Use the given board model.");
/* Both VT1720 and VT1724 have the same PCI IDs */
-static struct pci_device_id snd_vt1724_ids[] = {
+static struct pci_device_id snd_vt1724_ids[] __devinitdata = {
{ PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_VT1724, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0, }
};
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index ebbf2cf4ca0..0df7602568e 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -413,7 +413,7 @@ struct intel8x0 {
u32 int_sta_mask; /* interrupt status mask */
};
-static struct pci_device_id snd_intel8x0_ids[] = {
+static struct pci_device_id snd_intel8x0_ids[] __devinitdata = {
{ 0x8086, 0x2415, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801AA */
{ 0x8086, 0x2425, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82901AB */
{ 0x8086, 0x2445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801BA */
@@ -1293,6 +1293,7 @@ static int snd_intel8x0_ali_ac97spdifout_close(struct snd_pcm_substream *substre
return 0;
}
+#if 0 // NYI
static int snd_intel8x0_ali_spdifin_open(struct snd_pcm_substream *substream)
{
struct intel8x0 *chip = snd_pcm_substream_chip(substream);
@@ -1308,7 +1309,6 @@ static int snd_intel8x0_ali_spdifin_close(struct snd_pcm_substream *substream)
return 0;
}
-#if 0 // NYI
static int snd_intel8x0_ali_spdifout_open(struct snd_pcm_substream *substream)
{
struct intel8x0 *chip = snd_pcm_substream_chip(substream);
@@ -1435,6 +1435,7 @@ static struct snd_pcm_ops snd_intel8x0_ali_ac97spdifout_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
+#if 0 // NYI
static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = {
.open = snd_intel8x0_ali_spdifin_open,
.close = snd_intel8x0_ali_spdifin_close,
@@ -1446,7 +1447,6 @@ static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-#if 0 // NYI
static struct snd_pcm_ops snd_intel8x0_ali_spdifout_ops = {
.open = snd_intel8x0_ali_spdifout_open,
.close = snd_intel8x0_ali_spdifout_close,
@@ -1582,7 +1582,7 @@ static struct ich_pcm_table ali_pcms[] __devinitdata = {
{
.suffix = "IEC958",
.playback_ops = &snd_intel8x0_ali_ac97spdifout_ops,
- .capture_ops = &snd_intel8x0_ali_spdifin_ops,
+ /* .capture_ops = &snd_intel8x0_ali_spdifin_ops, */
.prealloc_size = 64 * 1024,
.prealloc_max_size = 128 * 1024,
.ac97_idx = ALID_AC97SPDIFOUT,
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 47e26aaa9ad..720635f0cb8 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -224,7 +224,7 @@ struct intel8x0m {
unsigned int pcm_pos_shift;
};
-static struct pci_device_id snd_intel8x0m_ids[] = {
+static struct pci_device_id snd_intel8x0m_ids[] __devinitdata = {
{ 0x8086, 0x2416, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801AA */
{ 0x8086, 0x2426, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82901AB */
{ 0x8086, 0x2446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801BA */
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 4721c096335..e39fad1a420 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -424,7 +424,7 @@ module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable Korg 1212 soundcard.");
MODULE_AUTHOR("Haroldo Gamal <gamal@alternex.com.br>");
-static struct pci_device_id snd_korg1212_ids[] = {
+static struct pci_device_id snd_korg1212_ids[] __devinitdata = {
{
.vendor = 0x10b5,
.device = 0x906d,
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 8bc084956c2..1928e06b6d8 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -830,8 +830,8 @@ struct snd_m3 {
struct snd_pcm *pcm;
struct pci_dev *pci;
- struct m3_quirk *quirk;
- struct m3_hv_quirk *hv_quirk;
+ const struct m3_quirk *quirk;
+ const struct m3_hv_quirk *hv_quirk;
int dacs_active;
int timer_users;
@@ -869,7 +869,7 @@ struct snd_m3 {
/*
* pci ids
*/
-static struct pci_device_id snd_m3_ids[] = {
+static struct pci_device_id snd_m3_ids[] __devinitdata = {
{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO, PCI_ANY_ID, PCI_ANY_ID,
@@ -891,7 +891,7 @@ static struct pci_device_id snd_m3_ids[] = {
MODULE_DEVICE_TABLE(pci, snd_m3_ids);
-static struct m3_quirk m3_quirk_list[] = {
+static const struct m3_quirk m3_quirk_list[] = {
/* panasonic CF-28 "toughbook" */
{
.name = "Panasonic CF-28",
@@ -949,7 +949,7 @@ static struct m3_quirk m3_quirk_list[] = {
};
/* These values came from the Windows driver. */
-static struct m3_hv_quirk m3_hv_quirk_list[] = {
+static const struct m3_hv_quirk m3_hv_quirk_list[] = {
/* Allegro chips */
{ 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
{ 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
@@ -1360,7 +1360,7 @@ static void snd_m3_pcm_setup2(struct snd_m3 *chip, struct m3_dma *s,
}
-static struct play_vals {
+static const struct play_vals {
u16 addr, val;
} pv[] = {
{CDATA_LEFT_VOLUME, ARB_VOLUME},
@@ -1427,7 +1427,7 @@ snd_m3_playback_setup(struct snd_m3 *chip, struct m3_dma *s,
/*
* Native record driver
*/
-static struct rec_vals {
+static const struct rec_vals {
u16 addr, val;
} rv[] = {
{CDATA_LEFT_VOLUME, ARB_VOLUME},
@@ -1597,12 +1597,26 @@ static void snd_m3_update_ptr(struct snd_m3 *chip, struct m3_dma *s)
if (! s->running)
return;
- hwptr = snd_m3_get_pointer(chip, s, subs) % s->dma_size;
- diff = (s->dma_size + hwptr - s->hwptr) % s->dma_size;
+ hwptr = snd_m3_get_pointer(chip, s, subs);
+
+ /* try to avoid expensive modulo divisions */
+ if (hwptr >= s->dma_size)
+ hwptr %= s->dma_size;
+
+ diff = s->dma_size + hwptr - s->hwptr;
+ if (diff >= s->dma_size)
+ diff %= s->dma_size;
+
s->hwptr = hwptr;
s->count += diff;
+
if (s->count >= (signed)s->period_size) {
- s->count %= s->period_size;
+
+ if (s->count < 2 * (signed)s->period_size)
+ s->count -= (signed)s->period_size;
+ else
+ s->count %= s->period_size;
+
spin_unlock(&chip->reg_lock);
snd_pcm_period_elapsed(subs);
spin_lock(&chip->reg_lock);
@@ -1941,6 +1955,7 @@ static int snd_m3_ac97_wait(struct snd_m3 *chip)
do {
if (! (snd_m3_inb(chip, 0x30) & 1))
return 0;
+ cpu_relax();
} while (i-- > 0);
snd_printk(KERN_ERR "ac97 serial bus busy\n");
@@ -1952,16 +1967,18 @@ snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
struct snd_m3 *chip = ac97->private_data;
unsigned long flags;
- unsigned short data;
+ unsigned short data = 0xffff;
if (snd_m3_ac97_wait(chip))
- return 0xffff;
+ goto fail;
spin_lock_irqsave(&chip->ac97_lock, flags);
snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
if (snd_m3_ac97_wait(chip))
- return 0xffff;
+ goto fail_unlock;
data = snd_m3_inw(chip, CODEC_DATA);
+fail_unlock:
spin_unlock_irqrestore(&chip->ac97_lock, flags);
+fail:
return data;
}
@@ -2120,7 +2137,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
* DSP Code images
*/
-static u16 assp_kernel_image[] __devinitdata = {
+static const u16 assp_kernel_image[] __devinitdata = {
0x7980, 0x0030, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x00FB, 0x7980, 0x00DD, 0x7980, 0x03B4,
0x7980, 0x0332, 0x7980, 0x0287, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4,
0x7980, 0x031A, 0x7980, 0x03B4, 0x7980, 0x022F, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4,
@@ -2207,7 +2224,7 @@ static u16 assp_kernel_image[] __devinitdata = {
* Mini sample rate converter code image
* that is to be loaded at 0x400 on the DSP.
*/
-static u16 assp_minisrc_image[] __devinitdata = {
+static const u16 assp_minisrc_image[] __devinitdata = {
0xBF80, 0x101E, 0x906E, 0x006E, 0x8B88, 0x6980, 0xEF88, 0x906F, 0x0D6F, 0x6900, 0xEB08, 0x0412,
0xBC20, 0x696E, 0xB801, 0x906E, 0x7980, 0x0403, 0xB90E, 0x8807, 0xBE43, 0xBF01, 0xBE47, 0xBE41,
@@ -2250,7 +2267,7 @@ static u16 assp_minisrc_image[] __devinitdata = {
*/
#define MINISRC_LPF_LEN 10
-static u16 minisrc_lpf[MINISRC_LPF_LEN] __devinitdata = {
+static const u16 minisrc_lpf[MINISRC_LPF_LEN] __devinitdata = {
0X0743, 0X1104, 0X0A4C, 0XF88D, 0X242C,
0X1023, 0X1AA9, 0X0B60, 0XEFDD, 0X186F
};
@@ -2357,7 +2374,7 @@ static int __devinit snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma
*/
/*
- * align instance address to 256 bytes so that it's
+ * align instance address to 256 bytes so that its
* shifted list address is aligned.
* list address = (mem address >> 1) >> 7;
*/
@@ -2646,8 +2663,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
{
struct snd_m3 *chip;
int i, err;
- struct m3_quirk *quirk;
- struct m3_hv_quirk *hv_quirk;
+ const struct m3_quirk *quirk;
+ const struct m3_hv_quirk *hv_quirk;
static struct snd_device_ops ops = {
.dev_free = snd_m3_dev_free,
};
@@ -2842,12 +2859,12 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
}
#if 0 /* TODO: not supported yet */
- /* TODO enable midi irq and i/o */
+ /* TODO enable MIDI IRQ and I/O */
err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401,
chip->iobase + MPU401_DATA_PORT, 1,
chip->irq, 0, &chip->rmidi);
if (err < 0)
- printk(KERN_WARNING "maestro3: no midi support.\n");
+ printk(KERN_WARNING "maestro3: no MIDI support.\n");
#endif
pci_set_drvdata(pci, card);
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 43ee3b2b948..09cc0786495 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -28,6 +28,7 @@
#include <linux/dma-mapping.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
+
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/info.h>
@@ -60,7 +61,7 @@ MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
/*
*/
-static struct pci_device_id snd_mixart_ids[] = {
+static struct pci_device_id snd_mixart_ids[] __devinitdata = {
{ 0x1057, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* MC8240 */
{ 0, }
};
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index cc297abc9d1..b92d6600deb 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -263,7 +263,7 @@ struct nm256 {
/*
* PCI ids
*/
-static struct pci_device_id snd_nm256_ids[] = {
+static struct pci_device_id snd_nm256_ids[] __devinitdata = {
{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index f679779d96e..dafa2235aba 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -73,7 +73,7 @@ enum {
PCI_ID_LAST
};
-static struct pci_device_id pcxhr_ids[] = {
+static struct pci_device_id pcxhr_ids[] __devinitdata = {
{ 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, }, /* VX882HR */
{ 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, }, /* PCX882HR */
{ 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, }, /* VX881HR */
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
index fdc652c6992..c40f5906268 100644
--- a/sound/pci/pcxhr/pcxhr_core.c
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -274,12 +274,9 @@ int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, const struct firmware *xilin
/* test first xilinx */
chipsc = PCXHR_INPL(mgr, PCXHR_PLX_CHIPSC);
- if (!second) {
- if (chipsc & PCXHR_CHIPSC_GPI_USERI) {
- snd_printdd("no need to load first xilinx\n");
- return 0; /* first xilinx is already present and cannot be reset */
- }
- } else {
+ /* REV01 cards do not support the PCXHR_CHIPSC_GPI_USERI bit anymore */
+ /* this bit will always be 1; no possibility to test presence of first xilinx */
+ if(second) {
if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) {
snd_printk(KERN_ERR "error loading first xilinx\n");
return -EINVAL;
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c
index 03517c10e99..369c19fea98 100644
--- a/sound/pci/pcxhr/pcxhr_hwdep.c
+++ b/sound/pci/pcxhr/pcxhr_hwdep.c
@@ -385,8 +385,8 @@ static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw,
fw.size = dsp->length;
fw.data = vmalloc(fw.size);
if (! fw.data) {
- snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image (%d bytes)\n",
- fw.size);
+ snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image (%lu bytes)\n",
+ (unsigned long)fw.size);
return -ENOMEM;
}
if (copy_from_user(fw.data, dsp->image, dsp->length)) {
diff --git a/sound/pci/riptide/Makefile b/sound/pci/riptide/Makefile
new file mode 100644
index 00000000000..dcd2e64e481
--- /dev/null
+++ b/sound/pci/riptide/Makefile
@@ -0,0 +1,3 @@
+snd-riptide-objs := riptide.o
+
+obj-$(CONFIG_SND_RIPTIDE) += snd-riptide.o
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
new file mode 100644
index 00000000000..d8cc985d724
--- /dev/null
+++ b/sound/pci/riptide/riptide.c
@@ -0,0 +1,2223 @@
+/*
+ * Driver for the Conexant Riptide Soundchip
+ *
+ * Copyright (c) 2004 Peter Gruber <nokos@gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ *
+ */
+/*
+ History:
+ - 02/15/2004 first release
+
+ This Driver is based on the OSS Driver version from Linuxant (riptide-0.6lnxtbeta03111100)
+ credits from the original files:
+
+ MODULE NAME: cnxt_rt.h
+ AUTHOR: K. Lazarev (Transcribed by KNL)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created 02/1/2000 KNL
+
+ MODULE NAME: int_mdl.c
+ AUTHOR: Konstantin Lazarev (Transcribed by KNL)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created 10/01/99 KNL
+
+ MODULE NAME: riptide.h
+ AUTHOR: O. Druzhinin (Transcribed by OLD)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created 10/16/97 OLD
+
+ MODULE NAME: Rp_Cmdif.cpp
+ AUTHOR: O. Druzhinin (Transcribed by OLD)
+ K. Lazarev (Transcribed by KNL)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Adopted from NT4 driver 6/22/99 OLD
+ Ported to Linux 9/01/99 KNL
+
+ MODULE NAME: rt_hw.c
+ AUTHOR: O. Druzhinin (Transcribed by OLD)
+ C. Lazarev (Transcribed by CNL)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created 11/18/97 OLD
+ Hardware functions for RipTide 11/24/97 CNL
+ (ES1) are coded
+ Hardware functions for RipTide 12/24/97 CNL
+ (A0) are coded
+ Hardware functions for RipTide 03/20/98 CNL
+ (A1) are coded
+ Boot loader is included 05/07/98 CNL
+ Redesigned for WDM 07/27/98 CNL
+ Redesigned for Linux 09/01/99 CNL
+
+ MODULE NAME: rt_hw.h
+ AUTHOR: C. Lazarev (Transcribed by CNL)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created 11/18/97 CNL
+
+ MODULE NAME: rt_mdl.c
+ AUTHOR: Konstantin Lazarev (Transcribed by KNL)
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created 10/01/99 KNL
+
+ MODULE NAME: mixer.h
+ AUTHOR: K. Kenney
+ HISTORY: Major Revision Date By
+ ----------------------------- -------- -----
+ Created from MS W95 Sample 11/28/95 KRS
+ RipTide 10/15/97 KRS
+ Adopted for Windows NT driver 01/20/98 CNL
+*/
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/gameport.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <asm/io.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/ac97_codec.h>
+#include <sound/mpu401.h>
+#include <sound/opl3.h>
+#include <sound/initval.h>
+
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK 1
+#endif
+
+MODULE_AUTHOR("Peter Gruber <nokos@gmx.net>");
+MODULE_DESCRIPTION("riptide");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Conexant,Riptide}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
+
+#ifdef SUPPORT_JOYSTICK
+static int joystick_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x200 };
+#endif
+static int mpu_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x330 };
+static int opl3_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x388 };
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for Riptide soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for Riptide soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable Riptide soundcard.");
+#ifdef SUPPORT_JOYSTICK
+module_param_array(joystick_port, int, NULL, 0444);
+MODULE_PARM_DESC(joystick_port, "Joystick port # for Riptide soundcard.");
+#endif
+module_param_array(mpu_port, int, NULL, 0444);
+MODULE_PARM_DESC(mpu_port, "MPU401 port # for Riptide driver.");
+module_param_array(opl3_port, int, NULL, 0444);
+MODULE_PARM_DESC(opl3_port, "OPL3 port # for Riptide driver.");
+
+/*
+ */
+
+#define MPU401_HW_RIPTIDE MPU401_HW_MPU401
+#define OPL3_HW_RIPTIDE OPL3_HW_OPL3
+
+#define PCI_EXT_CapId 0x40
+#define PCI_EXT_NextCapPrt 0x41
+#define PCI_EXT_PWMC 0x42
+#define PCI_EXT_PWSCR 0x44
+#define PCI_EXT_Data00 0x46
+#define PCI_EXT_PMSCR_BSE 0x47
+#define PCI_EXT_SB_Base 0x48
+#define PCI_EXT_FM_Base 0x4a
+#define PCI_EXT_MPU_Base 0x4C
+#define PCI_EXT_Game_Base 0x4E
+#define PCI_EXT_Legacy_Mask 0x50
+#define PCI_EXT_AsicRev 0x52
+#define PCI_EXT_Reserved3 0x53
+
+#define LEGACY_ENABLE_ALL 0x8000 /* legacy device options */
+#define LEGACY_ENABLE_SB 0x4000
+#define LEGACY_ENABLE_FM 0x2000
+#define LEGACY_ENABLE_MPU_INT 0x1000
+#define LEGACY_ENABLE_MPU 0x0800
+#define LEGACY_ENABLE_GAMEPORT 0x0400
+
+#define MAX_WRITE_RETRY 10 /* cmd interface limits */
+#define MAX_ERROR_COUNT 10
+#define CMDIF_TIMEOUT 500000
+#define RESET_TRIES 5
+
+#define READ_PORT_ULONG(p) inl((unsigned long)&(p))
+#define WRITE_PORT_ULONG(p,x) outl(x,(unsigned long)&(p))
+
+#define READ_AUDIO_CONTROL(p) READ_PORT_ULONG(p->audio_control)
+#define WRITE_AUDIO_CONTROL(p,x) WRITE_PORT_ULONG(p->audio_control,x)
+#define UMASK_AUDIO_CONTROL(p,x) WRITE_PORT_ULONG(p->audio_control,READ_PORT_ULONG(p->audio_control)|x)
+#define MASK_AUDIO_CONTROL(p,x) WRITE_PORT_ULONG(p->audio_control,READ_PORT_ULONG(p->audio_control)&x)
+#define READ_AUDIO_STATUS(p) READ_PORT_ULONG(p->audio_status)
+
+#define SET_GRESET(p) UMASK_AUDIO_CONTROL(p,0x0001) /* global reset switch */
+#define UNSET_GRESET(p) MASK_AUDIO_CONTROL(p,~0x0001)
+#define SET_AIE(p) UMASK_AUDIO_CONTROL(p,0x0004) /* interrupt enable */
+#define UNSET_AIE(p) MASK_AUDIO_CONTROL(p,~0x0004)
+#define SET_AIACK(p) UMASK_AUDIO_CONTROL(p,0x0008) /* interrupt acknowledge */
+#define UNSET_AIACKT(p) MASKAUDIO_CONTROL(p,~0x0008)
+#define SET_ECMDAE(p) UMASK_AUDIO_CONTROL(p,0x0010)
+#define UNSET_ECMDAE(p) MASK_AUDIO_CONTROL(p,~0x0010)
+#define SET_ECMDBE(p) UMASK_AUDIO_CONTROL(p,0x0020)
+#define UNSET_ECMDBE(p) MASK_AUDIO_CONTROL(p,~0x0020)
+#define SET_EDATAF(p) UMASK_AUDIO_CONTROL(p,0x0040)
+#define UNSET_EDATAF(p) MASK_AUDIO_CONTROL(p,~0x0040)
+#define SET_EDATBF(p) UMASK_AUDIO_CONTROL(p,0x0080)
+#define UNSET_EDATBF(p) MASK_AUDIO_CONTROL(p,~0x0080)
+#define SET_ESBIRQON(p) UMASK_AUDIO_CONTROL(p,0x0100)
+#define UNSET_ESBIRQON(p) MASK_AUDIO_CONTROL(p,~0x0100)
+#define SET_EMPUIRQ(p) UMASK_AUDIO_CONTROL(p,0x0200)
+#define UNSET_EMPUIRQ(p) MASK_AUDIO_CONTROL(p,~0x0200)
+#define IS_CMDE(a) (READ_PORT_ULONG(a->stat)&0x1) /* cmd empty */
+#define IS_DATF(a) (READ_PORT_ULONG(a->stat)&0x2) /* data filled */
+#define IS_READY(p) (READ_AUDIO_STATUS(p)&0x0001)
+#define IS_DLREADY(p) (READ_AUDIO_STATUS(p)&0x0002)
+#define IS_DLERR(p) (READ_AUDIO_STATUS(p)&0x0004)
+#define IS_GERR(p) (READ_AUDIO_STATUS(p)&0x0008) /* error ! */
+#define IS_CMDAEIRQ(p) (READ_AUDIO_STATUS(p)&0x0010)
+#define IS_CMDBEIRQ(p) (READ_AUDIO_STATUS(p)&0x0020)
+#define IS_DATAFIRQ(p) (READ_AUDIO_STATUS(p)&0x0040)
+#define IS_DATBFIRQ(p) (READ_AUDIO_STATUS(p)&0x0080)
+#define IS_EOBIRQ(p) (READ_AUDIO_STATUS(p)&0x0100) /* interrupt status */
+#define IS_EOSIRQ(p) (READ_AUDIO_STATUS(p)&0x0200)
+#define IS_EOCIRQ(p) (READ_AUDIO_STATUS(p)&0x0400)
+#define IS_UNSLIRQ(p) (READ_AUDIO_STATUS(p)&0x0800)
+#define IS_SBIRQ(p) (READ_AUDIO_STATUS(p)&0x1000)
+#define IS_MPUIRQ(p) (READ_AUDIO_STATUS(p)&0x2000)
+
+#define RESP 0x00000001 /* command flags */
+#define PARM 0x00000002
+#define CMDA 0x00000004
+#define CMDB 0x00000008
+#define NILL 0x00000000
+
+#define LONG0(a) ((u32)a) /* shifts and masks */
+#define BYTE0(a) (LONG0(a)&0xff)
+#define BYTE1(a) (BYTE0(a)<<8)
+#define BYTE2(a) (BYTE0(a)<<16)
+#define BYTE3(a) (BYTE0(a)<<24)
+#define WORD0(a) (LONG0(a)&0xffff)
+#define WORD1(a) (WORD0(a)<<8)
+#define WORD2(a) (WORD0(a)<<16)
+#define TRINIB0(a) (LONG0(a)&0xffffff)
+#define TRINIB1(a) (TRINIB0(a)<<8)
+
+#define RET(a) ((union cmdret *)(a))
+
+#define SEND_GETV(p,b) sendcmd(p,RESP,GETV,0,RET(b)) /* get version */
+#define SEND_GETC(p,b,c) sendcmd(p,PARM|RESP,GETC,c,RET(b))
+#define SEND_GUNS(p,b) sendcmd(p,RESP,GUNS,0,RET(b))
+#define SEND_SCID(p,b) sendcmd(p,RESP,SCID,0,RET(b))
+#define SEND_RMEM(p,b,c,d) sendcmd(p,PARM|RESP,RMEM|BYTE1(b),LONG0(c),RET(d)) /* memory access for firmware write */
+#define SEND_SMEM(p,b,c) sendcmd(p,PARM,SMEM|BYTE1(b),LONG0(c),RET(0)) /* memory access for firmware write */
+#define SEND_WMEM(p,b,c) sendcmd(p,PARM,WMEM|BYTE1(b),LONG0(c),RET(0)) /* memory access for firmware write */
+#define SEND_SDTM(p,b,c) sendcmd(p,PARM|RESP,SDTM|TRINIB1(b),0,RET(c)) /* memory access for firmware write */
+#define SEND_GOTO(p,b) sendcmd(p,PARM,GOTO,LONG0(b),RET(0)) /* memory access for firmware write */
+#define SEND_SETDPLL(p) sendcmd(p,0,ARM_SETDPLL,0,RET(0))
+#define SEND_SSTR(p,b,c) sendcmd(p,PARM,SSTR|BYTE3(b),LONG0(c),RET(0)) /* start stream */
+#define SEND_PSTR(p,b) sendcmd(p,PARM,PSTR,BYTE3(b),RET(0)) /* pause stream */
+#define SEND_KSTR(p,b) sendcmd(p,PARM,KSTR,BYTE3(b),RET(0)) /* stop stream */
+#define SEND_KDMA(p) sendcmd(p,0,KDMA,0,RET(0)) /* stop all dma */
+#define SEND_GPOS(p,b,c,d) sendcmd(p,PARM|RESP,GPOS,BYTE3(c)|BYTE2(b),RET(d)) /* get position in dma */
+#define SEND_SETF(p,b,c,d,e,f,g) sendcmd(p,PARM,SETF|WORD1(b)|BYTE3(c),d|BYTE1(e)|BYTE2(f)|BYTE3(g),RET(0)) /* set sample format at mixer */
+#define SEND_GSTS(p,b,c,d) sendcmd(p,PARM|RESP,GSTS,BYTE3(c)|BYTE2(b),RET(d))
+#define SEND_NGPOS(p,b,c,d) sendcmd(p,PARM|RESP,NGPOS,BYTE3(c)|BYTE2(b),RET(d))
+#define SEND_PSEL(p,b,c) sendcmd(p,PARM,PSEL,BYTE2(b)|BYTE3(c),RET(0)) /* activate lbus path */
+#define SEND_PCLR(p,b,c) sendcmd(p,PARM,PCLR,BYTE2(b)|BYTE3(c),RET(0)) /* deactivate lbus path */
+#define SEND_PLST(p,b) sendcmd(p,PARM,PLST,BYTE3(b),RET(0))
+#define SEND_RSSV(p,b,c,d) sendcmd(p,PARM|RESP,RSSV,BYTE2(b)|BYTE3(c),RET(d))
+#define SEND_LSEL(p,b,c,d,e,f,g,h) sendcmd(p,PARM,LSEL|BYTE1(b)|BYTE2(c)|BYTE3(d),BYTE0(e)|BYTE1(f)|BYTE2(g)|BYTE3(h),RET(0)) /* select paths for internal connections */
+#define SEND_SSRC(p,b,c,d,e) sendcmd(p,PARM,SSRC|BYTE1(b)|WORD2(c),WORD0(d)|WORD2(e),RET(0)) /* configure source */
+#define SEND_SLST(p,b) sendcmd(p,PARM,SLST,BYTE3(b),RET(0))
+#define SEND_RSRC(p,b,c) sendcmd(p,RESP,RSRC|BYTE1(b),0,RET(c)) /* read source config */
+#define SEND_SSRB(p,b,c) sendcmd(p,PARM,SSRB|BYTE1(b),WORD2(c),RET(0))
+#define SEND_SDGV(p,b,c,d,e) sendcmd(p,PARM,SDGV|BYTE2(b)|BYTE3(c),WORD0(d)|WORD2(e),RET(0)) /* set digital mixer */
+#define SEND_RDGV(p,b,c,d) sendcmd(p,PARM|RESP,RDGV|BYTE2(b)|BYTE3(c),0,RET(d)) /* read digital mixer */
+#define SEND_DLST(p,b) sendcmd(p,PARM,DLST,BYTE3(b),RET(0))
+#define SEND_SACR(p,b,c) sendcmd(p,PARM,SACR,WORD0(b)|WORD2(c),RET(0)) /* set AC97 register */
+#define SEND_RACR(p,b,c) sendcmd(p,PARM|RESP,RACR,WORD2(b),RET(c)) /* get AC97 register */
+#define SEND_ALST(p,b) sendcmd(p,PARM,ALST,BYTE3(b),RET(0))
+#define SEND_TXAC(p,b,c,d,e,f) sendcmd(p,PARM,TXAC|BYTE1(b)|WORD2(c),WORD0(d)|BYTE2(e)|BYTE3(f),RET(0))
+#define SEND_RXAC(p,b,c,d) sendcmd(p,PARM|RESP,RXAC,BYTE2(b)|BYTE3(c),RET(d))
+#define SEND_SI2S(p,b) sendcmd(p,PARM,SI2S,WORD2(b),RET(0))
+
+#define EOB_STATUS 0x80000000 /* status flags : block boundary */
+#define EOS_STATUS 0x40000000 /* : stoppped */
+#define EOC_STATUS 0x20000000 /* : stream end */
+#define ERR_STATUS 0x10000000
+#define EMPTY_STATUS 0x08000000
+
+#define IEOB_ENABLE 0x1 /* enable interrupts for status notification above */
+#define IEOS_ENABLE 0x2
+#define IEOC_ENABLE 0x4
+#define RDONCE 0x8
+#define DESC_MAX_MASK 0xff
+
+#define ST_PLAY 0x1 /* stream states */
+#define ST_STOP 0x2
+#define ST_PAUSE 0x4
+
+#define I2S_INTDEC 3 /* config for I2S link */
+#define I2S_MERGER 0
+#define I2S_SPLITTER 0
+#define I2S_MIXER 7
+#define I2S_RATE 44100
+
+#define MODEM_INTDEC 4 /* config for modem link */
+#define MODEM_MERGER 3
+#define MODEM_SPLITTER 0
+#define MODEM_MIXER 11
+
+#define FM_INTDEC 3 /* config for FM/OPL3 link */
+#define FM_MERGER 0
+#define FM_SPLITTER 0
+#define FM_MIXER 9
+
+#define SPLIT_PATH 0x80 /* path splitting flag */
+
+enum FIRMWARE {
+ DATA_REC = 0, EXT_END_OF_FILE, EXT_SEG_ADDR_REC, EXT_GOTO_CMD_REC,
+ EXT_LIN_ADDR_REC,
+};
+
+enum CMDS {
+ GETV = 0x00, GETC, GUNS, SCID, RMEM =
+ 0x10, SMEM, WMEM, SDTM, GOTO, SSTR =
+ 0x20, PSTR, KSTR, KDMA, GPOS, SETF, GSTS, NGPOS, PSEL =
+ 0x30, PCLR, PLST, RSSV, LSEL, SSRC = 0x40, SLST, RSRC, SSRB, SDGV =
+ 0x50, RDGV, DLST, SACR = 0x60, RACR, ALST, TXAC, RXAC, SI2S =
+ 0x70, ARM_SETDPLL = 0x72,
+};
+
+enum E1SOURCE {
+ ARM2LBUS_FIFO0 = 0, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2, ARM2LBUS_FIFO3,
+ ARM2LBUS_FIFO4, ARM2LBUS_FIFO5, ARM2LBUS_FIFO6, ARM2LBUS_FIFO7,
+ ARM2LBUS_FIFO8, ARM2LBUS_FIFO9, ARM2LBUS_FIFO10, ARM2LBUS_FIFO11,
+ ARM2LBUS_FIFO12, ARM2LBUS_FIFO13, ARM2LBUS_FIFO14, ARM2LBUS_FIFO15,
+ INTER0_OUT, INTER1_OUT, INTER2_OUT, INTER3_OUT, INTER4_OUT,
+ INTERM0_OUT, INTERM1_OUT, INTERM2_OUT, INTERM3_OUT, INTERM4_OUT,
+ INTERM5_OUT, INTERM6_OUT, DECIMM0_OUT, DECIMM1_OUT, DECIMM2_OUT,
+ DECIMM3_OUT, DECIM0_OUT, SR3_4_OUT, OPL3_SAMPLE, ASRC0, ASRC1,
+ ACLNK2PADC, ACLNK2MODEM0RX, ACLNK2MIC, ACLNK2MODEM1RX, ACLNK2HNDMIC,
+ DIGITAL_MIXER_OUT0, GAINFUNC0_OUT, GAINFUNC1_OUT, GAINFUNC2_OUT,
+ GAINFUNC3_OUT, GAINFUNC4_OUT, SOFTMODEMTX, SPLITTER0_OUTL,
+ SPLITTER0_OUTR, SPLITTER1_OUTL, SPLITTER1_OUTR, SPLITTER2_OUTL,
+ SPLITTER2_OUTR, SPLITTER3_OUTL, SPLITTER3_OUTR, MERGER0_OUT,
+ MERGER1_OUT, MERGER2_OUT, MERGER3_OUT, ARM2LBUS_FIFO_DIRECT, NO_OUT
+};
+
+enum E2SINK {
+ LBUS2ARM_FIFO0 = 0, LBUS2ARM_FIFO1, LBUS2ARM_FIFO2, LBUS2ARM_FIFO3,
+ LBUS2ARM_FIFO4, LBUS2ARM_FIFO5, LBUS2ARM_FIFO6, LBUS2ARM_FIFO7,
+ INTER0_IN, INTER1_IN, INTER2_IN, INTER3_IN, INTER4_IN, INTERM0_IN,
+ INTERM1_IN, INTERM2_IN, INTERM3_IN, INTERM4_IN, INTERM5_IN, INTERM6_IN,
+ DECIMM0_IN, DECIMM1_IN, DECIMM2_IN, DECIMM3_IN, DECIM0_IN, SR3_4_IN,
+ PDAC2ACLNK, MODEM0TX2ACLNK, MODEM1TX2ACLNK, HNDSPK2ACLNK,
+ DIGITAL_MIXER_IN0, DIGITAL_MIXER_IN1, DIGITAL_MIXER_IN2,
+ DIGITAL_MIXER_IN3, DIGITAL_MIXER_IN4, DIGITAL_MIXER_IN5,
+ DIGITAL_MIXER_IN6, DIGITAL_MIXER_IN7, DIGITAL_MIXER_IN8,
+ DIGITAL_MIXER_IN9, DIGITAL_MIXER_IN10, DIGITAL_MIXER_IN11,
+ GAINFUNC0_IN, GAINFUNC1_IN, GAINFUNC2_IN, GAINFUNC3_IN, GAINFUNC4_IN,
+ SOFTMODEMRX, SPLITTER0_IN, SPLITTER1_IN, SPLITTER2_IN, SPLITTER3_IN,
+ MERGER0_INL, MERGER0_INR, MERGER1_INL, MERGER1_INR, MERGER2_INL,
+ MERGER2_INR, MERGER3_INL, MERGER3_INR, E2SINK_MAX
+};
+
+enum LBUS_SINK {
+ LS_SRC_INTERPOLATOR = 0, LS_SRC_INTERPOLATORM, LS_SRC_DECIMATOR,
+ LS_SRC_DECIMATORM, LS_MIXER_IN, LS_MIXER_GAIN_FUNCTION,
+ LS_SRC_SPLITTER, LS_SRC_MERGER, LS_NONE1, LS_NONE2,
+};
+
+enum RT_CHANNEL_IDS {
+ M0TX = 0, M1TX, TAMTX, HSSPKR, PDAC, DSNDTX0, DSNDTX1, DSNDTX2,
+ DSNDTX3, DSNDTX4, DSNDTX5, DSNDTX6, DSNDTX7, WVSTRTX, COP3DTX, SPARE,
+ M0RX, HSMIC, M1RX, CLEANRX, MICADC, PADC, COPRX1, COPRX2,
+ CHANNEL_ID_COUNTER
+};
+
+enum { SB_CMD = 0, MODEM_CMD, I2S_CMD0, I2S_CMD1, FM_CMD, MAX_CMD };
+
+struct lbuspath {
+ unsigned char *noconv;
+ unsigned char *stereo;
+ unsigned char *mono;
+};
+
+struct cmdport {
+ u32 data1; /* cmd,param */
+ u32 data2; /* param */
+ u32 stat; /* status */
+ u32 pad[5];
+};
+
+struct riptideport {
+ u32 audio_control; /* status registers */
+ u32 audio_status;
+ u32 pad[2];
+ struct cmdport port[2]; /* command ports */
+};
+
+struct cmdif {
+ struct riptideport *hwport;
+ spinlock_t lock;
+ unsigned int cmdcnt; /* cmd statistics */
+ unsigned int cmdtime;
+ unsigned int cmdtimemax;
+ unsigned int cmdtimemin;
+ unsigned int errcnt;
+ int is_reset;
+};
+
+struct riptide_firmware {
+ u16 ASIC;
+ u16 CODEC;
+ u16 AUXDSP;
+ u16 PROG;
+};
+
+union cmdret {
+ u8 retbytes[8];
+ u16 retwords[4];
+ u32 retlongs[2];
+};
+
+union firmware_version {
+ union cmdret ret;
+ struct riptide_firmware firmware;
+};
+
+#define get_pcmhwdev(substream) (struct pcmhw *)(substream->runtime->private_data)
+
+#define PLAYBACK_SUBSTREAMS 3
+struct snd_riptide {
+ struct snd_card *card;
+ struct pci_dev *pci;
+ const struct firmware *fw_entry;
+
+ struct cmdif *cif;
+
+ struct snd_pcm *pcm;
+ struct snd_pcm *pcm_i2s;
+ struct snd_rawmidi *rmidi;
+ struct snd_opl3 *opl3;
+ struct snd_ac97 *ac97;
+ struct snd_ac97_bus *ac97_bus;
+
+ struct snd_pcm_substream *playback_substream[PLAYBACK_SUBSTREAMS];
+ struct snd_pcm_substream *capture_substream;
+
+ int openstreams;
+
+ int irq;
+ unsigned long port;
+ unsigned short mpuaddr;
+ unsigned short opladdr;
+#ifdef SUPPORT_JOYSTICK
+ unsigned short gameaddr;
+#endif
+ struct resource *res_port;
+
+ unsigned short device_id;
+
+ union firmware_version firmware;
+
+ spinlock_t lock;
+ struct tasklet_struct riptide_tq;
+ struct snd_info_entry *proc_entry;
+
+ unsigned long received_irqs;
+ unsigned long handled_irqs;
+#ifdef CONFIG_PM
+ int in_suspend;
+#endif
+};
+
+struct sgd { /* scatter gather desriptor */
+ u32 dwNextLink;
+ u32 dwSegPtrPhys;
+ u32 dwSegLen;
+ u32 dwStat_Ctl;
+};
+
+struct pcmhw { /* pcm descriptor */
+ struct lbuspath paths;
+ unsigned char *lbuspath;
+ unsigned char source;
+ unsigned char intdec[2];
+ unsigned char mixer;
+ unsigned char id;
+ unsigned char state;
+ unsigned int rate;
+ unsigned int channels;
+ snd_pcm_format_t format;
+ struct snd_dma_buffer sgdlist;
+ struct sgd *sgdbuf;
+ unsigned int size;
+ unsigned int pages;
+ unsigned int oldpos;
+ unsigned int pointer;
+};
+
+#define CMDRET_ZERO (union cmdret){{(u32)0, (u32) 0}}
+
+static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm,
+ union cmdret *ret);
+static int getsourcesink(struct cmdif *cif, unsigned char source,
+ unsigned char sink, unsigned char *a,
+ unsigned char *b);
+static int snd_riptide_initialize(struct snd_riptide *chip);
+static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip);
+
+/*
+ */
+
+static struct pci_device_id snd_riptide_ids[] __devinitdata = {
+ {
+ .vendor = 0x127a,.device = 0x4310,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {
+ .vendor = 0x127a,.device = 0x4320,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {
+ .vendor = 0x127a,.device = 0x4330,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {
+ .vendor = 0x127a,.device = 0x4340,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {0,},
+};
+
+#ifdef SUPPORT_JOYSTICK
+static struct pci_device_id snd_riptide_joystick_ids[] __devinitdata = {
+ {
+ .vendor = 0x127a,.device = 0x4312,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {
+ .vendor = 0x127a,.device = 0x4322,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {.vendor = 0x127a,.device = 0x4332,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {.vendor = 0x127a,.device = 0x4342,
+ .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+ },
+ {0,},
+};
+#endif
+
+MODULE_DEVICE_TABLE(pci, snd_riptide_ids);
+
+/*
+ */
+
+static unsigned char lbusin2out[E2SINK_MAX + 1][2] = {
+ {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT,
+ LS_NONE2},
+ {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT,
+ LS_NONE2},
+ {INTER0_OUT, LS_SRC_INTERPOLATOR}, {INTER1_OUT, LS_SRC_INTERPOLATOR},
+ {INTER2_OUT, LS_SRC_INTERPOLATOR}, {INTER3_OUT, LS_SRC_INTERPOLATOR},
+ {INTER4_OUT, LS_SRC_INTERPOLATOR}, {INTERM0_OUT, LS_SRC_INTERPOLATORM},
+ {INTERM1_OUT, LS_SRC_INTERPOLATORM}, {INTERM2_OUT,
+ LS_SRC_INTERPOLATORM},
+ {INTERM3_OUT, LS_SRC_INTERPOLATORM}, {INTERM4_OUT,
+ LS_SRC_INTERPOLATORM},
+ {INTERM5_OUT, LS_SRC_INTERPOLATORM}, {INTERM6_OUT,
+ LS_SRC_INTERPOLATORM},
+ {DECIMM0_OUT, LS_SRC_DECIMATORM}, {DECIMM1_OUT, LS_SRC_DECIMATORM},
+ {DECIMM2_OUT, LS_SRC_DECIMATORM}, {DECIMM3_OUT, LS_SRC_DECIMATORM},
+ {DECIM0_OUT, LS_SRC_DECIMATOR}, {SR3_4_OUT, LS_NONE1}, {NO_OUT,
+ LS_NONE2},
+ {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1},
+ {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+ {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+ {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+ {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+ {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+ {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+ {GAINFUNC0_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC1_OUT,
+ LS_MIXER_GAIN_FUNCTION},
+ {GAINFUNC2_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC3_OUT,
+ LS_MIXER_GAIN_FUNCTION},
+ {GAINFUNC4_OUT, LS_MIXER_GAIN_FUNCTION}, {SOFTMODEMTX, LS_NONE1},
+ {SPLITTER0_OUTL, LS_SRC_SPLITTER}, {SPLITTER1_OUTL, LS_SRC_SPLITTER},
+ {SPLITTER2_OUTL, LS_SRC_SPLITTER}, {SPLITTER3_OUTL, LS_SRC_SPLITTER},
+ {MERGER0_OUT, LS_SRC_MERGER}, {MERGER0_OUT, LS_SRC_MERGER},
+ {MERGER1_OUT, LS_SRC_MERGER},
+ {MERGER1_OUT, LS_SRC_MERGER}, {MERGER2_OUT, LS_SRC_MERGER},
+ {MERGER2_OUT, LS_SRC_MERGER},
+ {MERGER3_OUT, LS_SRC_MERGER}, {MERGER3_OUT, LS_SRC_MERGER}, {NO_OUT,
+ LS_NONE2},
+};
+
+static unsigned char lbus_play_opl3[] = {
+ DIGITAL_MIXER_IN0 + FM_MIXER, 0xff
+};
+static unsigned char lbus_play_modem[] = {
+ DIGITAL_MIXER_IN0 + MODEM_MIXER, 0xff
+};
+static unsigned char lbus_play_i2s[] = {
+ INTER0_IN + I2S_INTDEC, DIGITAL_MIXER_IN0 + I2S_MIXER, 0xff
+};
+static unsigned char lbus_play_out[] = {
+ PDAC2ACLNK, 0xff
+};
+static unsigned char lbus_play_outhp[] = {
+ HNDSPK2ACLNK, 0xff
+};
+static unsigned char lbus_play_noconv1[] = {
+ DIGITAL_MIXER_IN0, 0xff
+};
+static unsigned char lbus_play_stereo1[] = {
+ INTER0_IN, DIGITAL_MIXER_IN0, 0xff
+};
+static unsigned char lbus_play_mono1[] = {
+ INTERM0_IN, DIGITAL_MIXER_IN0, 0xff
+};
+static unsigned char lbus_play_noconv2[] = {
+ DIGITAL_MIXER_IN1, 0xff
+};
+static unsigned char lbus_play_stereo2[] = {
+ INTER1_IN, DIGITAL_MIXER_IN1, 0xff
+};
+static unsigned char lbus_play_mono2[] = {
+ INTERM1_IN, DIGITAL_MIXER_IN1, 0xff
+};
+static unsigned char lbus_play_noconv3[] = {
+ DIGITAL_MIXER_IN2, 0xff
+};
+static unsigned char lbus_play_stereo3[] = {
+ INTER2_IN, DIGITAL_MIXER_IN2, 0xff
+};
+static unsigned char lbus_play_mono3[] = {
+ INTERM2_IN, DIGITAL_MIXER_IN2, 0xff
+};
+static unsigned char lbus_rec_noconv1[] = {
+ LBUS2ARM_FIFO5, 0xff
+};
+static unsigned char lbus_rec_stereo1[] = {
+ DECIM0_IN, LBUS2ARM_FIFO5, 0xff
+};
+static unsigned char lbus_rec_mono1[] = {
+ DECIMM3_IN, LBUS2ARM_FIFO5, 0xff
+};
+
+static unsigned char play_ids[] = { 4, 1, 2, };
+static unsigned char play_sources[] = {
+ ARM2LBUS_FIFO4, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2,
+};
+static struct lbuspath lbus_play_paths[] = {
+ {
+ .noconv = lbus_play_noconv1,
+ .stereo = lbus_play_stereo1,
+ .mono = lbus_play_mono1,
+ },
+ {
+ .noconv = lbus_play_noconv2,
+ .stereo = lbus_play_stereo2,
+ .mono = lbus_play_mono2,
+ },
+ {
+ .noconv = lbus_play_noconv3,
+ .stereo = lbus_play_stereo3,
+ .mono = lbus_play_mono3,
+ },
+};
+static struct lbuspath lbus_rec_path = {
+ .noconv = lbus_rec_noconv1,
+ .stereo = lbus_rec_stereo1,
+ .mono = lbus_rec_mono1,
+};
+
+#define FIRMWARE_VERSIONS 1
+static union firmware_version firmware_versions[] = {
+ {
+ .firmware.ASIC = 3,.firmware.CODEC = 2,
+ .firmware.AUXDSP = 3,.firmware.PROG = 773,
+ },
+};
+
+static u32 atoh(unsigned char *in, unsigned int len)
+{
+ u32 sum = 0;
+ unsigned int mult = 1;
+ unsigned char c;
+
+ while (len) {
+ c = in[len - 1];
+ if ((c >= '0') && (c <= '9'))
+ sum += mult * (c - '0');
+ else if ((c >= 'A') && (c <= 'F'))
+ sum += mult * (c - ('A' - 10));
+ else if ((c >= 'a') && (c <= 'f'))
+ sum += mult * (c - ('a' - 10));
+ mult *= 16;
+ --len;
+ }
+ return sum;
+}
+
+static int senddata(struct cmdif *cif, unsigned char *in, u32 offset)
+{
+ u32 addr;
+ u32 data;
+ u32 i;
+ unsigned char *p;
+
+ i = atoh(&in[1], 2);
+ addr = offset + atoh(&in[3], 4);
+ if (SEND_SMEM(cif, 0, addr) != 0)
+ return -EACCES;
+ p = in + 9;
+ while (i) {
+ data = atoh(p, 8);
+ if (SEND_WMEM(cif, 2,
+ ((data & 0x0f0f0f0f) << 4) | ((data & 0xf0f0f0f0)
+ >> 4)))
+ return -EACCES;
+ i -= 4;
+ p += 8;
+ }
+ return 0;
+}
+
+static int loadfirmware(struct cmdif *cif, unsigned char *img,
+ unsigned int size)
+{
+ unsigned char *in;
+ u32 laddr, saddr, t, val;
+ int err = 0;
+
+ laddr = saddr = 0;
+ while (size > 0 && err == 0) {
+ in = img;
+ if (in[0] == ':') {
+ t = atoh(&in[7], 2);
+ switch (t) {
+ case DATA_REC:
+ err = senddata(cif, in, laddr + saddr);
+ break;
+ case EXT_SEG_ADDR_REC:
+ saddr = atoh(&in[9], 4) << 4;
+ break;
+ case EXT_LIN_ADDR_REC:
+ laddr = atoh(&in[9], 4) << 16;
+ break;
+ case EXT_GOTO_CMD_REC:
+ val = atoh(&in[9], 8);
+ if (SEND_GOTO(cif, val) != 0)
+ err = -EACCES;
+ break;
+ case EXT_END_OF_FILE:
+ size = 0;
+ break;
+ default:
+ break;
+ }
+ while (size > 0) {
+ size--;
+ if (*img++ == '\n')
+ break;
+ }
+ }
+ }
+ snd_printdd("load firmware return %d\n", err);
+ return err;
+}
+
+static void
+alloclbuspath(struct cmdif *cif, unsigned char source,
+ unsigned char *path, unsigned char *mixer, unsigned char *s)
+{
+ while (*path != 0xff) {
+ unsigned char sink, type;
+
+ sink = *path & (~SPLIT_PATH);
+ if (sink != E2SINK_MAX) {
+ snd_printdd("alloc path 0x%x->0x%x\n", source, sink);
+ SEND_PSEL(cif, source, sink);
+ source = lbusin2out[sink][0];
+ type = lbusin2out[sink][1];
+ if (type == LS_MIXER_IN) {
+ if (mixer)
+ *mixer = sink - DIGITAL_MIXER_IN0;
+ }
+ if (type == LS_SRC_DECIMATORM ||
+ type == LS_SRC_DECIMATOR ||
+ type == LS_SRC_INTERPOLATORM ||
+ type == LS_SRC_INTERPOLATOR) {
+ if (s) {
+ if (s[0] != 0xff)
+ s[1] = sink;
+ else
+ s[0] = sink;
+ }
+ }
+ }
+ if (*path++ & SPLIT_PATH) {
+ unsigned char *npath = path;
+
+ while (*npath != 0xff)
+ npath++;
+ alloclbuspath(cif, source + 1, ++npath, mixer, s);
+ }
+ }
+}
+
+static void
+freelbuspath(struct cmdif *cif, unsigned char source, unsigned char *path)
+{
+ while (*path != 0xff) {
+ unsigned char sink;
+
+ sink = *path & (~SPLIT_PATH);
+ if (sink != E2SINK_MAX) {
+ snd_printdd("free path 0x%x->0x%x\n", source, sink);
+ SEND_PCLR(cif, source, sink);
+ source = lbusin2out[sink][0];
+ }
+ if (*path++ & SPLIT_PATH) {
+ unsigned char *npath = path;
+
+ while (*npath != 0xff)
+ npath++;
+ freelbuspath(cif, source + 1, ++npath);
+ }
+ }
+}
+
+static int writearm(struct cmdif *cif, u32 addr, u32 data, u32 mask)
+{
+ union cmdret rptr = CMDRET_ZERO;
+ unsigned int i = MAX_WRITE_RETRY;
+ int flag = 1;
+
+ SEND_RMEM(cif, 0x02, addr, &rptr);
+ rptr.retlongs[0] &= (~mask);
+
+ while (--i) {
+ SEND_SMEM(cif, 0x01, addr);
+ SEND_WMEM(cif, 0x02, (rptr.retlongs[0] | data));
+ SEND_RMEM(cif, 0x02, addr, &rptr);
+ if ((rptr.retlongs[0] & data) == data) {
+ flag = 0;
+ break;
+ } else
+ rptr.retlongs[0] &= ~mask;
+ }
+ snd_printdd("send arm 0x%x 0x%x 0x%x return %d\n", addr, data, mask,
+ flag);
+ return flag;
+}
+
+static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm,
+ union cmdret *ret)
+{
+ int i, j;
+ int err;
+ unsigned int time = 0;
+ unsigned long irqflags;
+ struct riptideport *hwport;
+ struct cmdport *cmdport = NULL;
+
+ snd_assert(cif, return -EINVAL);
+
+ hwport = cif->hwport;
+ if (cif->errcnt > MAX_ERROR_COUNT) {
+ if (cif->is_reset) {
+ snd_printk(KERN_ERR
+ "Riptide: Too many failed cmds, reinitializing\n");
+ if (riptide_reset(cif, NULL) == 0) {
+ cif->errcnt = 0;
+ return -EIO;
+ }
+ }
+ snd_printk(KERN_ERR "Riptide: Initialization failed.\n");
+ return -EINVAL;
+ }
+ if (ret) {
+ ret->retlongs[0] = 0;
+ ret->retlongs[1] = 0;
+ }
+ i = 0;
+ spin_lock_irqsave(&cif->lock, irqflags);
+ while (i++ < CMDIF_TIMEOUT && !IS_READY(cif->hwport))
+ udelay(10);
+ if (i >= CMDIF_TIMEOUT) {
+ err = -EBUSY;
+ goto errout;
+ }
+
+ err = 0;
+ for (j = 0, time = 0; time < CMDIF_TIMEOUT; j++, time += 2) {
+ cmdport = &(hwport->port[j % 2]);
+ if (IS_DATF(cmdport)) { /* free pending data */
+ READ_PORT_ULONG(cmdport->data1);
+ READ_PORT_ULONG(cmdport->data2);
+ }
+ if (IS_CMDE(cmdport)) {
+ if (flags & PARM) /* put data */
+ WRITE_PORT_ULONG(cmdport->data2, parm);
+ WRITE_PORT_ULONG(cmdport->data1, cmd); /* write cmd */
+ if ((flags & RESP) && ret) {
+ while (!IS_DATF(cmdport) &&
+ time++ < CMDIF_TIMEOUT)
+ udelay(10);
+ if (time < CMDIF_TIMEOUT) { /* read response */
+ ret->retlongs[0] =
+ READ_PORT_ULONG(cmdport->data1);
+ ret->retlongs[1] =
+ READ_PORT_ULONG(cmdport->data2);
+ } else {
+ err = -ENOSYS;
+ goto errout;
+ }
+ }
+ break;
+ }
+ udelay(20);
+ }
+ if (time == CMDIF_TIMEOUT) {
+ err = -ENODATA;
+ goto errout;
+ }
+ spin_unlock_irqrestore(&cif->lock, irqflags);
+
+ cif->cmdcnt++; /* update command statistics */
+ cif->cmdtime += time;
+ if (time > cif->cmdtimemax)
+ cif->cmdtimemax = time;
+ if (time < cif->cmdtimemin)
+ cif->cmdtimemin = time;
+ if ((cif->cmdcnt) % 1000 == 0)
+ snd_printdd
+ ("send cmd %d time: %d mintime: %d maxtime %d err: %d\n",
+ cif->cmdcnt, cif->cmdtime, cif->cmdtimemin,
+ cif->cmdtimemax, cif->errcnt);
+ return 0;
+
+ errout:
+ cif->errcnt++;
+ spin_unlock_irqrestore(&cif->lock, irqflags);
+ snd_printdd
+ ("send cmd %d hw: 0x%x flag: 0x%x cmd: 0x%x parm: 0x%x ret: 0x%x 0x%x CMDE: %d DATF: %d failed %d\n",
+ cif->cmdcnt, (int)((void *)&(cmdport->stat) - (void *)hwport),
+ flags, cmd, parm, ret ? ret->retlongs[0] : 0,
+ ret ? ret->retlongs[1] : 0, IS_CMDE(cmdport), IS_DATF(cmdport),
+ err);
+ return err;
+}
+
+static int
+setmixer(struct cmdif *cif, short num, unsigned short rval, unsigned short lval)
+{
+ union cmdret rptr = CMDRET_ZERO;
+ int i = 0;
+
+ snd_printdd("sent mixer %d: 0x%d 0x%d\n", num, rval, lval);
+ do {
+ SEND_SDGV(cif, num, num, rval, lval);
+ SEND_RDGV(cif, num, num, &rptr);
+ if (rptr.retwords[0] == lval && rptr.retwords[1] == rval)
+ return 0;
+ } while (i++ < MAX_WRITE_RETRY);
+ snd_printdd("sent mixer failed\n");
+ return -EIO;
+}
+
+static int getpaths(struct cmdif *cif, unsigned char *o)
+{
+ unsigned char src[E2SINK_MAX];
+ unsigned char sink[E2SINK_MAX];
+ int i, j = 0;
+
+ for (i = 0; i < E2SINK_MAX; i++) {
+ getsourcesink(cif, i, i, &src[i], &sink[i]);
+ if (sink[i] < E2SINK_MAX) {
+ o[j++] = sink[i];
+ o[j++] = i;
+ }
+ }
+ return j;
+}
+
+static int
+getsourcesink(struct cmdif *cif, unsigned char source, unsigned char sink,
+ unsigned char *a, unsigned char *b)
+{
+ union cmdret rptr = CMDRET_ZERO;
+
+ if (SEND_RSSV(cif, source, sink, &rptr) &&
+ SEND_RSSV(cif, source, sink, &rptr))
+ return -EIO;
+ *a = rptr.retbytes[0];
+ *b = rptr.retbytes[1];
+ snd_printdd("getsourcesink 0x%x 0x%x\n", *a, *b);
+ return 0;
+}
+
+static int
+getsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int *rate)
+{
+ unsigned char *s;
+ unsigned int p[2] = { 0, 0 };
+ int i;
+ union cmdret rptr = CMDRET_ZERO;
+
+ s = intdec;
+ for (i = 0; i < 2; i++) {
+ if (*s != 0xff) {
+ if (SEND_RSRC(cif, *s, &rptr) &&
+ SEND_RSRC(cif, *s, &rptr))
+ return -EIO;
+ p[i] += rptr.retwords[1];
+ p[i] *= rptr.retwords[2];
+ p[i] += rptr.retwords[3];
+ p[i] /= 65536;
+ }
+ s++;
+ }
+ if (p[0]) {
+ if (p[1] != p[0])
+ snd_printdd("rates differ %d %d\n", p[0], p[1]);
+ *rate = (unsigned int)p[0];
+ } else
+ *rate = (unsigned int)p[1];
+ snd_printdd("getsampleformat %d %d %d\n", intdec[0], intdec[1], *rate);
+ return 0;
+}
+
+static int
+setsampleformat(struct cmdif *cif,
+ unsigned char mixer, unsigned char id,
+ unsigned char channels, unsigned char format)
+{
+ unsigned char w, ch, sig, order;
+
+ snd_printdd
+ ("setsampleformat mixer: %d id: %d channels: %d format: %d\n",
+ mixer, id, channels, format);
+ ch = channels == 1;
+ w = snd_pcm_format_width(format) == 8;
+ sig = snd_pcm_format_unsigned(format) != 0;
+ order = snd_pcm_format_big_endian(format) != 0;
+
+ if (SEND_SETF(cif, mixer, w, ch, order, sig, id) &&
+ SEND_SETF(cif, mixer, w, ch, order, sig, id)) {
+ snd_printdd("setsampleformat failed\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int
+setsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int rate)
+{
+ u32 D, M, N;
+ union cmdret rptr = CMDRET_ZERO;
+ int i;
+
+ snd_printdd("setsamplerate intdec: %d,%d rate: %d\n", intdec[0],
+ intdec[1], rate);
+ D = 48000;
+ M = ((rate == 48000) ? 47999 : rate) * 65536;
+ N = M % D;
+ M /= D;
+ for (i = 0; i < 2; i++) {
+ if (*intdec != 0xff) {
+ do {
+ SEND_SSRC(cif, *intdec, D, M, N);
+ SEND_RSRC(cif, *intdec, &rptr);
+ } while (rptr.retwords[1] != D &&
+ rptr.retwords[2] != M &&
+ rptr.retwords[3] != N &&
+ i++ < MAX_WRITE_RETRY);
+ if (i == MAX_WRITE_RETRY) {
+ snd_printdd("sent samplerate %d: %d failed\n",
+ *intdec, rate);
+ return -EIO;
+ }
+ }
+ intdec++;
+ }
+ return 0;
+}
+
+static int
+getmixer(struct cmdif *cif, short num, unsigned short *rval,
+ unsigned short *lval)
+{
+ union cmdret rptr = CMDRET_ZERO;
+
+ if (SEND_RDGV(cif, num, num, &rptr) && SEND_RDGV(cif, num, num, &rptr))
+ return -EIO;
+ *rval = rptr.retwords[0];
+ *lval = rptr.retwords[1];
+ snd_printdd("got mixer %d: 0x%d 0x%d\n", num, *rval, *lval);
+ return 0;
+}
+
+static void riptide_handleirq(unsigned long dev_id)
+{
+ struct snd_riptide *chip = (void *)dev_id;
+ struct cmdif *cif = chip->cif;
+ struct snd_pcm_substream *substream[PLAYBACK_SUBSTREAMS + 1];
+ struct snd_pcm_runtime *runtime;
+ struct pcmhw *data = NULL;
+ unsigned int pos, period_bytes;
+ struct sgd *c;
+ int i, j;
+ unsigned int flag;
+
+ if (!cif)
+ return;
+
+ for (i = 0; i < PLAYBACK_SUBSTREAMS; i++)
+ substream[i] = chip->playback_substream[i];
+ substream[i] = chip->capture_substream;
+ for (i = 0; i < PLAYBACK_SUBSTREAMS + 1; i++) {
+ if (substream[i] &&
+ (runtime = substream[i]->runtime) &&
+ (data = runtime->private_data) && data->state != ST_STOP) {
+ pos = 0;
+ for (j = 0; j < data->pages; j++) {
+ c = &data->sgdbuf[j];
+ flag = le32_to_cpu(c->dwStat_Ctl);
+ if (flag & EOB_STATUS)
+ pos += le32_to_cpu(c->dwSegLen);
+ if (flag & EOC_STATUS)
+ pos += le32_to_cpu(c->dwSegLen);
+ if ((flag & EOS_STATUS)
+ && (data->state == ST_PLAY)) {
+ data->state = ST_STOP;
+ snd_printk(KERN_ERR
+ "Riptide: DMA stopped unexpectedly\n");
+ }
+ c->dwStat_Ctl =
+ cpu_to_le32(flag &
+ ~(EOS_STATUS | EOB_STATUS |
+ EOC_STATUS));
+ }
+ data->pointer += pos;
+ pos += data->oldpos;
+ if (data->state != ST_STOP) {
+ period_bytes =
+ frames_to_bytes(runtime,
+ runtime->period_size);
+ snd_printdd
+ ("interrupt 0x%x after 0x%lx of 0x%lx frames in period\n",
+ READ_AUDIO_STATUS(cif->hwport),
+ bytes_to_frames(runtime, pos),
+ runtime->period_size);
+ j = 0;
+ if (pos >= period_bytes) {
+ j++;
+ while (pos >= period_bytes)
+ pos -= period_bytes;
+ }
+ data->oldpos = pos;
+ if (j > 0)
+ snd_pcm_period_elapsed(substream[i]);
+ }
+ }
+ }
+}
+
+#ifdef CONFIG_PM
+static int riptide_suspend(struct pci_dev *pci, pm_message_t state)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_riptide *chip = card->private_data;
+
+ chip->in_suspend = 1;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(chip->pcm);
+ snd_ac97_suspend(chip->ac97);
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ return 0;
+}
+
+static int riptide_resume(struct pci_dev *pci)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_riptide *chip = card->private_data;
+
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
+ snd_riptide_initialize(chip);
+ snd_ac97_resume(chip->ac97);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ chip->in_suspend = 0;
+ return 0;
+}
+#endif
+
+static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip)
+{
+ int timeout, tries;
+ union cmdret rptr = CMDRET_ZERO;
+ union firmware_version firmware;
+ int i, j, err, has_firmware;
+
+ if (!cif)
+ return -EINVAL;
+
+ cif->cmdcnt = 0;
+ cif->cmdtime = 0;
+ cif->cmdtimemax = 0;
+ cif->cmdtimemin = 0xffffffff;
+ cif->errcnt = 0;
+ cif->is_reset = 0;
+
+ tries = RESET_TRIES;
+ has_firmware = 0;
+ while (has_firmware == 0 && tries-- > 0) {
+ for (i = 0; i < 2; i++) {
+ WRITE_PORT_ULONG(cif->hwport->port[i].data1, 0);
+ WRITE_PORT_ULONG(cif->hwport->port[i].data2, 0);
+ }
+ SET_GRESET(cif->hwport);
+ udelay(100);
+ UNSET_GRESET(cif->hwport);
+ udelay(100);
+
+ for (timeout = 100000; --timeout; udelay(10)) {
+ if (IS_READY(cif->hwport) && !IS_GERR(cif->hwport))
+ break;
+ }
+ if (timeout == 0) {
+ snd_printk(KERN_ERR
+ "Riptide: device not ready, audio status: 0x%x ready: %d gerr: %d\n",
+ READ_AUDIO_STATUS(cif->hwport),
+ IS_READY(cif->hwport), IS_GERR(cif->hwport));
+ return -EIO;
+ } else {
+ snd_printdd
+ ("Riptide: audio status: 0x%x ready: %d gerr: %d\n",
+ READ_AUDIO_STATUS(cif->hwport),
+ IS_READY(cif->hwport), IS_GERR(cif->hwport));
+ }
+
+ SEND_GETV(cif, &rptr);
+ for (i = 0; i < 4; i++)
+ firmware.ret.retwords[i] = rptr.retwords[i];
+
+ snd_printdd
+ ("Firmware version: ASIC: %d CODEC %d AUXDSP %d PROG %d\n",
+ firmware.firmware.ASIC, firmware.firmware.CODEC,
+ firmware.firmware.AUXDSP, firmware.firmware.PROG);
+
+ for (j = 0; j < FIRMWARE_VERSIONS; j++) {
+ has_firmware = 1;
+ for (i = 0; i < 4; i++) {
+ if (firmware_versions[j].ret.retwords[i] !=
+ firmware.ret.retwords[i])
+ has_firmware = 0;
+ }
+ if (has_firmware)
+ break;
+ }
+
+ if (chip != NULL && has_firmware == 0) {
+ snd_printdd("Writing Firmware\n");
+ if (!chip->fw_entry) {
+ if ((err =
+ request_firmware(&chip->fw_entry,
+ "riptide.hex",
+ &chip->pci->dev)) != 0) {
+ snd_printk(KERN_ERR
+ "Riptide: Firmware not available %d\n",
+ err);
+ return -EIO;
+ }
+ }
+ err = loadfirmware(cif, chip->fw_entry->data,
+ chip->fw_entry->size);
+ if (err)
+ snd_printk(KERN_ERR
+ "Riptide: Could not load firmware %d\n",
+ err);
+ }
+ }
+
+ SEND_SACR(cif, 0, AC97_RESET);
+ SEND_RACR(cif, AC97_RESET, &rptr);
+ snd_printdd("AC97: 0x%x 0x%x\n", rptr.retlongs[0], rptr.retlongs[1]);
+
+ SEND_PLST(cif, 0);
+ SEND_SLST(cif, 0);
+ SEND_DLST(cif, 0);
+ SEND_ALST(cif, 0);
+ SEND_KDMA(cif);
+
+ writearm(cif, 0x301F8, 1, 1);
+ writearm(cif, 0x301F4, 1, 1);
+
+ SEND_LSEL(cif, MODEM_CMD, 0, 0, MODEM_INTDEC, MODEM_MERGER,
+ MODEM_SPLITTER, MODEM_MIXER);
+ setmixer(cif, MODEM_MIXER, 0x7fff, 0x7fff);
+ alloclbuspath(cif, ARM2LBUS_FIFO13, lbus_play_modem, NULL, NULL);
+
+ SEND_LSEL(cif, FM_CMD, 0, 0, FM_INTDEC, FM_MERGER, FM_SPLITTER,
+ FM_MIXER);
+ setmixer(cif, FM_MIXER, 0x7fff, 0x7fff);
+ writearm(cif, 0x30648 + FM_MIXER * 4, 0x01, 0x00000005);
+ writearm(cif, 0x301A8, 0x02, 0x00000002);
+ writearm(cif, 0x30264, 0x08, 0xffffffff);
+ alloclbuspath(cif, OPL3_SAMPLE, lbus_play_opl3, NULL, NULL);
+
+ SEND_SSRC(cif, I2S_INTDEC, 48000,
+ ((u32) I2S_RATE * 65536) / 48000,
+ ((u32) I2S_RATE * 65536) % 48000);
+ SEND_LSEL(cif, I2S_CMD0, 0, 0, I2S_INTDEC, I2S_MERGER, I2S_SPLITTER,
+ I2S_MIXER);
+ SEND_SI2S(cif, 1);
+ alloclbuspath(cif, ARM2LBUS_FIFO0, lbus_play_i2s, NULL, NULL);
+ alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_out, NULL, NULL);
+ alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_outhp, NULL, NULL);
+
+ SET_AIACK(cif->hwport);
+ SET_AIE(cif->hwport);
+ SET_AIACK(cif->hwport);
+ cif->is_reset = 1;
+ if (chip) {
+ for (i = 0; i < 4; i++)
+ chip->firmware.ret.retwords[i] =
+ firmware.ret.retwords[i];
+ }
+
+ return 0;
+}
+
+static struct snd_pcm_hardware snd_riptide_playback = {
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID),
+ .formats =
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8
+ | SNDRV_PCM_FMTBIT_U16_LE,
+ .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 5500,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (64 * 1024),
+ .period_bytes_min = PAGE_SIZE >> 1,
+ .period_bytes_max = PAGE_SIZE << 8,
+ .periods_min = 2,
+ .periods_max = 64,
+ .fifo_size = 0,
+};
+static struct snd_pcm_hardware snd_riptide_capture = {
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID),
+ .formats =
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8
+ | SNDRV_PCM_FMTBIT_U16_LE,
+ .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 5500,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (64 * 1024),
+ .period_bytes_min = PAGE_SIZE >> 1,
+ .period_bytes_max = PAGE_SIZE << 3,
+ .periods_min = 2,
+ .periods_max = 64,
+ .fifo_size = 0,
+};
+
+static snd_pcm_uframes_t snd_riptide_pointer(struct snd_pcm_substream
+ *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct pcmhw *data = get_pcmhwdev(substream);
+ struct cmdif *cif = chip->cif;
+ union cmdret rptr = CMDRET_ZERO;
+ snd_pcm_uframes_t ret;
+
+ SEND_GPOS(cif, 0, data->id, &rptr);
+ if (data->size && runtime->period_size) {
+ snd_printdd
+ ("pointer stream %d position 0x%x(0x%x in buffer) bytes 0x%lx(0x%lx in period) frames\n",
+ data->id, rptr.retlongs[1], rptr.retlongs[1] % data->size,
+ bytes_to_frames(runtime, rptr.retlongs[1]),
+ bytes_to_frames(runtime,
+ rptr.retlongs[1]) % runtime->period_size);
+ if (rptr.retlongs[1] > data->pointer)
+ ret =
+ bytes_to_frames(runtime,
+ rptr.retlongs[1] % data->size);
+ else
+ ret =
+ bytes_to_frames(runtime,
+ data->pointer % data->size);
+ } else {
+ snd_printdd("stream not started or strange parms (%d %ld)\n",
+ data->size, runtime->period_size);
+ ret = bytes_to_frames(runtime, 0);
+ }
+ return ret;
+}
+
+static int snd_riptide_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ int i, j;
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+ struct cmdif *cif = chip->cif;
+ union cmdret rptr = CMDRET_ZERO;
+
+ spin_lock(&chip->lock);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ if (!(data->state & ST_PLAY)) {
+ SEND_SSTR(cif, data->id, data->sgdlist.addr);
+ SET_AIE(cif->hwport);
+ data->state = ST_PLAY;
+ if (data->mixer != 0xff)
+ setmixer(cif, data->mixer, 0x7fff, 0x7fff);
+ chip->openstreams++;
+ data->oldpos = 0;
+ data->pointer = 0;
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (data->mixer != 0xff)
+ setmixer(cif, data->mixer, 0, 0);
+ setmixer(cif, data->mixer, 0, 0);
+ SEND_KSTR(cif, data->id);
+ data->state = ST_STOP;
+ chip->openstreams--;
+ j = 0;
+ do {
+ i = rptr.retlongs[1];
+ SEND_GPOS(cif, 0, data->id, &rptr);
+ udelay(1);
+ } while (i != rptr.retlongs[1] && j++ < MAX_WRITE_RETRY);
+ if (j >= MAX_WRITE_RETRY)
+ snd_printk(KERN_ERR "Riptide: Could not stop stream!");
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (!(data->state & ST_PAUSE)) {
+ SEND_PSTR(cif, data->id);
+ data->state |= ST_PAUSE;
+ chip->openstreams--;
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (data->state & ST_PAUSE) {
+ SEND_SSTR(cif, data->id, data->sgdlist.addr);
+ data->state &= ~ST_PAUSE;
+ chip->openstreams++;
+ }
+ break;
+ default:
+ spin_unlock(&chip->lock);
+ return -EINVAL;
+ }
+ spin_unlock(&chip->lock);
+ return 0;
+}
+
+static int snd_riptide_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+ struct cmdif *cif = chip->cif;
+ unsigned char *lbuspath = NULL;
+ unsigned int rate, channels;
+ int err = 0;
+ snd_pcm_format_t format;
+
+ snd_assert(cif && data, return -EINVAL);
+
+ snd_printdd("prepare id %d ch: %d f:0x%x r:%d\n", data->id,
+ runtime->channels, runtime->format, runtime->rate);
+
+ spin_lock_irq(&chip->lock);
+ channels = runtime->channels;
+ format = runtime->format;
+ rate = runtime->rate;
+ switch (channels) {
+ case 1:
+ if (rate == 48000 && format == SNDRV_PCM_FORMAT_S16_LE)
+ lbuspath = data->paths.noconv;
+ else
+ lbuspath = data->paths.mono;
+ break;
+ case 2:
+ if (rate == 48000 && format == SNDRV_PCM_FORMAT_S16_LE)
+ lbuspath = data->paths.noconv;
+ else
+ lbuspath = data->paths.stereo;
+ break;
+ }
+ snd_printdd("use sgdlist at 0x%p and buffer at 0x%p\n",
+ data->sgdlist.area, sgbuf);
+ if (data->sgdlist.area && sgbuf) {
+ unsigned int i, j, size, pages, f, pt, period;
+ struct sgd *c, *p = NULL;
+
+ size = frames_to_bytes(runtime, runtime->buffer_size);
+ period = frames_to_bytes(runtime, runtime->period_size);
+ f = PAGE_SIZE;
+ while ((size + (f >> 1) - 1) <= (f << 7) && (f << 1) > period)
+ f = f >> 1;
+ pages = (size + f - 1) / f;
+ data->size = size;
+ data->pages = pages;
+ snd_printdd
+ ("create sgd size: 0x%x pages %d of size 0x%x for period 0x%x\n",
+ size, pages, f, period);
+ pt = 0;
+ j = 0;
+ for (i = 0; i < pages; i++) {
+ c = &data->sgdbuf[i];
+ if (p)
+ p->dwNextLink = cpu_to_le32(data->sgdlist.addr +
+ (i *
+ sizeof(struct
+ sgd)));
+ c->dwNextLink = cpu_to_le32(data->sgdlist.addr);
+ c->dwSegPtrPhys =
+ cpu_to_le32(sgbuf->table[j].addr + pt);
+ pt = (pt + f) % PAGE_SIZE;
+ if (pt == 0)
+ j++;
+ c->dwSegLen = cpu_to_le32(f);
+ c->dwStat_Ctl =
+ cpu_to_le32(IEOB_ENABLE | IEOS_ENABLE |
+ IEOC_ENABLE);
+ p = c;
+ size -= f;
+ }
+ data->sgdbuf[i].dwSegLen = cpu_to_le32(size);
+ }
+ if (lbuspath && lbuspath != data->lbuspath) {
+ if (data->lbuspath)
+ freelbuspath(cif, data->source, data->lbuspath);
+ alloclbuspath(cif, data->source, lbuspath,
+ &data->mixer, data->intdec);
+ data->lbuspath = lbuspath;
+ data->rate = 0;
+ }
+ if (data->rate != rate || data->format != format ||
+ data->channels != channels) {
+ data->rate = rate;
+ data->format = format;
+ data->channels = channels;
+ if (setsampleformat
+ (cif, data->mixer, data->id, channels, format)
+ || setsamplerate(cif, data->intdec, rate))
+ err = -EIO;
+ }
+ spin_unlock_irq(&chip->lock);
+ return err;
+}
+
+static int
+snd_riptide_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+ struct snd_dma_buffer *sgdlist = &data->sgdlist;
+ int err;
+
+ snd_printdd("hw params id %d (sgdlist: 0x%p 0x%lx %d)\n", data->id,
+ sgdlist->area, (unsigned long)sgdlist->addr,
+ (int)sgdlist->bytes);
+ if (sgdlist->area)
+ snd_dma_free_pages(sgdlist);
+ if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ sizeof(struct sgd) * (DESC_MAX_MASK + 1),
+ sgdlist)) < 0) {
+ snd_printk(KERN_ERR "Riptide: failed to alloc %d dma bytes\n",
+ (int)sizeof(struct sgd) * (DESC_MAX_MASK + 1));
+ return err;
+ }
+ data->sgdbuf = (struct sgd *)sgdlist->area;
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+}
+
+static int snd_riptide_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+ struct cmdif *cif = chip->cif;
+
+ if (cif && data) {
+ if (data->lbuspath)
+ freelbuspath(cif, data->source, data->lbuspath);
+ data->lbuspath = NULL;
+ data->source = 0xff;
+ data->intdec[0] = 0xff;
+ data->intdec[1] = 0xff;
+
+ if (data->sgdlist.area) {
+ snd_dma_free_pages(&data->sgdlist);
+ data->sgdlist.area = NULL;
+ }
+ }
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int snd_riptide_playback_open(struct snd_pcm_substream *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct pcmhw *data;
+ int index = substream->number;
+
+ chip->playback_substream[index] = substream;
+ runtime->hw = snd_riptide_playback;
+ data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
+ data->paths = lbus_play_paths[index];
+ data->id = play_ids[index];
+ data->source = play_sources[index];
+ data->intdec[0] = 0xff;
+ data->intdec[1] = 0xff;
+ data->state = ST_STOP;
+ runtime->private_data = data;
+ return snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+}
+
+static int snd_riptide_capture_open(struct snd_pcm_substream *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct pcmhw *data;
+
+ chip->capture_substream = substream;
+ runtime->hw = snd_riptide_capture;
+ data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
+ data->paths = lbus_rec_path;
+ data->id = PADC;
+ data->source = ACLNK2PADC;
+ data->intdec[0] = 0xff;
+ data->intdec[1] = 0xff;
+ data->state = ST_STOP;
+ runtime->private_data = data;
+ return snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+}
+
+static int snd_riptide_playback_close(struct snd_pcm_substream *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+ int index = substream->number;
+
+ substream->runtime->private_data = NULL;
+ chip->playback_substream[index] = NULL;
+ kfree(data);
+ return 0;
+}
+
+static int snd_riptide_capture_close(struct snd_pcm_substream *substream)
+{
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+
+ substream->runtime->private_data = NULL;
+ chip->capture_substream = NULL;
+ kfree(data);
+ return 0;
+}
+
+static struct snd_pcm_ops snd_riptide_playback_ops = {
+ .open = snd_riptide_playback_open,
+ .close = snd_riptide_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_riptide_hw_params,
+ .hw_free = snd_riptide_hw_free,
+ .prepare = snd_riptide_prepare,
+ .page = snd_pcm_sgbuf_ops_page,
+ .trigger = snd_riptide_trigger,
+ .pointer = snd_riptide_pointer,
+};
+static struct snd_pcm_ops snd_riptide_capture_ops = {
+ .open = snd_riptide_capture_open,
+ .close = snd_riptide_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_riptide_hw_params,
+ .hw_free = snd_riptide_hw_free,
+ .prepare = snd_riptide_prepare,
+ .page = snd_pcm_sgbuf_ops_page,
+ .trigger = snd_riptide_trigger,
+ .pointer = snd_riptide_pointer,
+};
+
+static int __devinit
+snd_riptide_pcm(struct snd_riptide *chip, int device, struct snd_pcm **rpcm)
+{
+ struct snd_pcm *pcm;
+ int err;
+
+ if (rpcm)
+ *rpcm = NULL;
+ if ((err =
+ snd_pcm_new(chip->card, "RIPTIDE", device, PLAYBACK_SUBSTREAMS, 1,
+ &pcm)) < 0)
+ return err;
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_riptide_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_riptide_capture_ops);
+ pcm->private_data = chip;
+ pcm->info_flags = 0;
+ strcpy(pcm->name, "RIPTIDE");
+ chip->pcm = pcm;
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+ snd_dma_pci_data(chip->pci),
+ 64 * 1024, 128 * 1024);
+ if (rpcm)
+ *rpcm = pcm;
+ return 0;
+}
+
+static irqreturn_t
+snd_riptide_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct snd_riptide *chip = dev_id;
+ struct cmdif *cif = chip->cif;
+
+ if (cif) {
+ chip->received_irqs++;
+ if (IS_EOBIRQ(cif->hwport) || IS_EOSIRQ(cif->hwport) ||
+ IS_EOCIRQ(cif->hwport)) {
+ chip->handled_irqs++;
+ tasklet_hi_schedule(&chip->riptide_tq);
+ }
+ if (chip->rmidi && IS_MPUIRQ(cif->hwport)) {
+ chip->handled_irqs++;
+ snd_mpu401_uart_interrupt(irq,
+ chip->rmidi->private_data,
+ regs);
+ }
+ SET_AIACK(cif->hwport);
+ }
+ return IRQ_HANDLED;
+}
+
+static void
+snd_riptide_codec_write(struct snd_ac97 *ac97, unsigned short reg,
+ unsigned short val)
+{
+ struct snd_riptide *chip = ac97->private_data;
+ struct cmdif *cif = chip->cif;
+ union cmdret rptr = CMDRET_ZERO;
+ int i = 0;
+
+ snd_assert(cif, return);
+
+ snd_printdd("Write AC97 reg 0x%x 0x%x\n", reg, val);
+ do {
+ SEND_SACR(cif, val, reg);
+ SEND_RACR(cif, reg, &rptr);
+ } while (rptr.retwords[1] != val && i++ < MAX_WRITE_RETRY);
+ if (i == MAX_WRITE_RETRY)
+ snd_printdd("Write AC97 reg failed\n");
+}
+
+static unsigned short snd_riptide_codec_read(struct snd_ac97 *ac97,
+ unsigned short reg)
+{
+ struct snd_riptide *chip = ac97->private_data;
+ struct cmdif *cif = chip->cif;
+ union cmdret rptr = CMDRET_ZERO;
+
+ snd_assert(cif, return 0);
+
+ if (SEND_RACR(cif, reg, &rptr) != 0)
+ SEND_RACR(cif, reg, &rptr);
+ snd_printdd("Read AC97 reg 0x%x got 0x%x\n", reg, rptr.retwords[1]);
+ return rptr.retwords[1];
+}
+
+static int snd_riptide_initialize(struct snd_riptide *chip)
+{
+ struct cmdif *cif;
+ unsigned int device_id;
+ int err;
+
+ snd_assert(chip, return -EINVAL);
+
+ cif = chip->cif;
+ if (!cif) {
+ if ((cif = kzalloc(sizeof(struct cmdif), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+ cif->hwport = (struct riptideport *)chip->port;
+ spin_lock_init(&cif->lock);
+ chip->cif = cif;
+ }
+ cif->is_reset = 0;
+ if ((err = riptide_reset(cif, chip)) != 0)
+ return err;
+ device_id = chip->device_id;
+ switch (device_id) {
+ case 0x4310:
+ case 0x4320:
+ case 0x4330:
+ snd_printdd("Modem enable?\n");
+ SEND_SETDPLL(cif);
+ break;
+ }
+ snd_printdd("Enabling MPU IRQs\n");
+ if (chip->rmidi)
+ SET_EMPUIRQ(cif->hwport);
+ return err;
+}
+
+static int snd_riptide_free(struct snd_riptide *chip)
+{
+ struct cmdif *cif;
+
+ snd_assert(chip, return 0);
+
+ if ((cif = chip->cif)) {
+ SET_GRESET(cif->hwport);
+ udelay(100);
+ UNSET_GRESET(cif->hwport);
+ kfree(chip->cif);
+ }
+ if (chip->fw_entry)
+ release_firmware(chip->fw_entry);
+ release_and_free_resource(chip->res_port);
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+ kfree(chip);
+ return 0;
+}
+
+static int snd_riptide_dev_free(struct snd_device *device)
+{
+ struct snd_riptide *chip = device->device_data;
+
+ return snd_riptide_free(chip);
+}
+
+static int __devinit
+snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
+ struct snd_riptide **rchip)
+{
+ struct snd_riptide *chip;
+ struct riptideport *hwport;
+ int err;
+ static struct snd_device_ops ops = {
+ .dev_free = snd_riptide_dev_free,
+ };
+
+ *rchip = NULL;
+ if ((err = pci_enable_device(pci)) < 0)
+ return err;
+ if (!(chip = kzalloc(sizeof(struct snd_riptide), GFP_KERNEL)))
+ return -ENOMEM;
+
+ spin_lock_init(&chip->lock);
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+ chip->openstreams = 0;
+ chip->port = pci_resource_start(pci, 0);
+ chip->received_irqs = 0;
+ chip->handled_irqs = 0;
+ chip->cif = NULL;
+ tasklet_init(&chip->riptide_tq, riptide_handleirq, (unsigned long)chip);
+
+ if ((chip->res_port =
+ request_region(chip->port, 64, "RIPTIDE")) == NULL) {
+ snd_printk(KERN_ERR
+ "Riptide: unable to grab region 0x%lx-0x%lx\n",
+ chip->port, chip->port + 64 - 1);
+ snd_riptide_free(chip);
+ return -EBUSY;
+ }
+ hwport = (struct riptideport *)chip->port;
+ UNSET_AIE(hwport);
+
+ if (request_irq
+ (pci->irq, snd_riptide_interrupt, SA_INTERRUPT | SA_SHIRQ,
+ "RIPTIDE", chip)) {
+ snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n",
+ pci->irq);
+ snd_riptide_free(chip);
+ return -EBUSY;
+ }
+ chip->irq = pci->irq;
+ chip->device_id = pci->device;
+ pci_set_master(pci);
+ if ((err = snd_riptide_initialize(chip)) < 0) {
+ snd_riptide_free(chip);
+ return err;
+ }
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+ snd_riptide_free(chip);
+ return err;
+ }
+
+ *rchip = chip;
+ return 0;
+}
+
+static void
+snd_riptide_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct snd_riptide *chip = entry->private_data;
+ struct pcmhw *data;
+ int i;
+ struct cmdif *cif = NULL;
+ unsigned char p[256];
+ unsigned short rval = 0, lval = 0;
+ unsigned int rate;
+
+ if (!chip)
+ return;
+
+ snd_iprintf(buffer, "%s\n\n", chip->card->longname);
+ snd_iprintf(buffer, "Device ID: 0x%x\nReceived IRQs: (%ld)%ld\nPorts:",
+ chip->device_id, chip->handled_irqs, chip->received_irqs);
+ for (i = 0; i < 64; i += 4)
+ snd_iprintf(buffer, "%c%02x: %08x",
+ (i % 16) ? ' ' : '\n', i, inl(chip->port + i));
+ if ((cif = chip->cif)) {
+ snd_iprintf(buffer,
+ "\nVersion: ASIC: %d CODEC: %d AUXDSP: %d PROG: %d",
+ chip->firmware.firmware.ASIC,
+ chip->firmware.firmware.CODEC,
+ chip->firmware.firmware.AUXDSP,
+ chip->firmware.firmware.PROG);
+ snd_iprintf(buffer, "\nDigital mixer:");
+ for (i = 0; i < 12; i++) {
+ getmixer(cif, i, &rval, &lval);
+ snd_iprintf(buffer, "\n %d: %d %d", i, rval, lval);
+ }
+ snd_iprintf(buffer,
+ "\nARM Commands num: %d failed: %d time: %d max: %d min: %d",
+ cif->cmdcnt, cif->errcnt,
+ cif->cmdtime, cif->cmdtimemax, cif->cmdtimemin);
+ }
+ snd_iprintf(buffer, "\nOpen streams %d:\n", chip->openstreams);
+ for (i = 0; i < PLAYBACK_SUBSTREAMS; i++) {
+ if (chip->playback_substream[i]
+ && chip->playback_substream[i]->runtime
+ && (data =
+ chip->playback_substream[i]->runtime->private_data)) {
+ snd_iprintf(buffer,
+ "stream: %d mixer: %d source: %d (%d,%d)\n",
+ data->id, data->mixer, data->source,
+ data->intdec[0], data->intdec[1]);
+ if (!(getsamplerate(cif, data->intdec, &rate)))
+ snd_iprintf(buffer, "rate: %d\n", rate);
+ }
+ }
+ if (chip->capture_substream
+ && chip->capture_substream->runtime
+ && (data = chip->capture_substream->runtime->private_data)) {
+ snd_iprintf(buffer,
+ "stream: %d mixer: %d source: %d (%d,%d)\n",
+ data->id, data->mixer,
+ data->source, data->intdec[0], data->intdec[1]);
+ if (!(getsamplerate(cif, data->intdec, &rate)))
+ snd_iprintf(buffer, "rate: %d\n", rate);
+ }
+ snd_iprintf(buffer, "Paths:\n");
+ i = getpaths(cif, p);
+ while (i--) {
+ snd_iprintf(buffer, "%x->%x ", p[i - 1], p[i]);
+ i--;
+ }
+ snd_iprintf(buffer, "\n");
+}
+
+static void __devinit snd_riptide_proc_init(struct snd_riptide *chip)
+{
+ struct snd_info_entry *entry;
+
+ if (!snd_card_proc_new(chip->card, "riptide", &entry))
+ snd_info_set_text_ops(entry, chip, 4096, snd_riptide_proc_read);
+}
+
+static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
+{
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
+ int err = 0;
+ static struct snd_ac97_bus_ops ops = {
+ .write = snd_riptide_codec_write,
+ .read = snd_riptide_codec_read,
+ };
+
+ memset(&ac97, 0, sizeof(ac97));
+ ac97.private_data = chip;
+ ac97.scaps = AC97_SCAP_SKIP_MODEM;
+
+ if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
+ return err;
+
+ chip->ac97_bus = pbus;
+ ac97.pci = chip->pci;
+ if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0)
+ return err;
+ return err;
+}
+
+#ifdef SUPPORT_JOYSTICK
+static int have_joystick;
+static struct pci_dev *riptide_gameport_pci;
+static struct gameport *riptide_gameport;
+
+static int __devinit
+snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id)
+{
+ static int dev;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ if (joystick_port[dev]) {
+ riptide_gameport = gameport_allocate_port();
+ if (riptide_gameport) {
+ if (!request_region
+ (joystick_port[dev], 8, "Riptide gameport")) {
+ snd_printk(KERN_WARNING
+ "Riptide: cannot grab gameport 0x%x\n",
+ joystick_port[dev]);
+ gameport_free_port(riptide_gameport);
+ riptide_gameport = NULL;
+ } else {
+ riptide_gameport_pci = pci;
+ riptide_gameport->io = joystick_port[dev];
+ gameport_register_port(riptide_gameport);
+ }
+ }
+ }
+ dev++;
+ return 0;
+}
+
+static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci)
+{
+ if (riptide_gameport) {
+ if (riptide_gameport_pci == pci) {
+ release_region(riptide_gameport->io, 8);
+ riptide_gameport_pci = NULL;
+ gameport_unregister_port(riptide_gameport);
+ riptide_gameport = NULL;
+ }
+ }
+}
+#endif
+
+static int __devinit
+snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+{
+ static int dev;
+ struct snd_card *card;
+ struct snd_riptide *chip;
+ unsigned short addr;
+ int err = 0;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+ if (card == NULL)
+ return -ENOMEM;
+ if ((err = snd_riptide_create(card, pci, &chip)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ card->private_data = chip;
+ if ((err = snd_riptide_pcm(chip, 0, NULL)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ if ((err = snd_riptide_mixer(chip)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ pci_write_config_word(chip->pci, PCI_EXT_Legacy_Mask, LEGACY_ENABLE_ALL
+ | (opl3_port[dev] ? LEGACY_ENABLE_FM : 0)
+#ifdef SUPPORT_JOYSTICK
+ | (joystick_port[dev] ? LEGACY_ENABLE_GAMEPORT :
+ 0)
+#endif
+ | (mpu_port[dev]
+ ? (LEGACY_ENABLE_MPU_INT | LEGACY_ENABLE_MPU) :
+ 0)
+ | ((chip->irq << 4) & 0xF0));
+ if ((addr = mpu_port[dev]) != 0) {
+ pci_write_config_word(chip->pci, PCI_EXT_MPU_Base, addr);
+ if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_RIPTIDE,
+ addr, 0, chip->irq, 0,
+ &chip->rmidi)) < 0)
+ snd_printk(KERN_WARNING
+ "Riptide: Can't Allocate MPU at 0x%x\n",
+ addr);
+ else
+ chip->mpuaddr = addr;
+ }
+ if ((addr = opl3_port[dev]) != 0) {
+ pci_write_config_word(chip->pci, PCI_EXT_FM_Base, addr);
+ if ((err = snd_opl3_create(card, addr, addr + 2,
+ OPL3_HW_RIPTIDE, 0,
+ &chip->opl3)) < 0)
+ snd_printk(KERN_WARNING
+ "Riptide: Can't Allocate OPL3 at 0x%x\n",
+ addr);
+ else {
+ chip->opladdr = addr;
+ if ((err =
+ snd_opl3_hwdep_new(chip->opl3, 0, 1, NULL)) < 0)
+ snd_printk(KERN_WARNING
+ "Riptide: Can't Allocate OPL3-HWDEP\n");
+ }
+ }
+#ifdef SUPPORT_JOYSTICK
+ if ((addr = joystick_port[dev]) != 0) {
+ pci_write_config_word(chip->pci, PCI_EXT_Game_Base, addr);
+ chip->gameaddr = addr;
+ }
+#endif
+
+ strcpy(card->driver, "RIPTIDE");
+ strcpy(card->shortname, "Riptide");
+#ifdef SUPPORT_JOYSTICK
+ snprintf(card->longname, sizeof(card->longname),
+ "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x gameport 0x%x",
+ card->shortname, chip->port, chip->irq, chip->mpuaddr,
+ chip->opladdr, chip->gameaddr);
+#else
+ snprintf(card->longname, sizeof(card->longname),
+ "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x",
+ card->shortname, chip->port, chip->irq, chip->mpuaddr,
+ chip->opladdr);
+#endif
+ snd_riptide_proc_init(chip);
+ if ((err = snd_card_register(card)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
+}
+
+static void __devexit snd_card_riptide_remove(struct pci_dev *pci)
+{
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_driver driver = {
+ .name = "RIPTIDE",
+ .id_table = snd_riptide_ids,
+ .probe = snd_card_riptide_probe,
+ .remove = __devexit_p(snd_card_riptide_remove),
+#ifdef CONFIG_PM
+ .suspend = riptide_suspend,
+ .resume = riptide_resume,
+#endif
+};
+
+#ifdef SUPPORT_JOYSTICK
+static struct pci_driver joystick_driver = {
+ .name = "Riptide Joystick",
+ .id_table = snd_riptide_joystick_ids,
+ .probe = snd_riptide_joystick_probe,
+ .remove = __devexit_p(snd_riptide_joystick_remove),
+};
+#endif
+
+static int __init alsa_card_riptide_init(void)
+{
+ int err;
+ if ((err = pci_register_driver(&driver)) < 0)
+ return err;
+#if defined(SUPPORT_JOYSTICK)
+ if (pci_register_driver(&joystick_driver) < 0) {
+ have_joystick = 0;
+ snd_printk(KERN_INFO "no joystick found\n");
+ } else
+ have_joystick = 1;
+#endif
+ return 0;
+}
+
+static void __exit alsa_card_riptide_exit(void)
+{
+ pci_unregister_driver(&driver);
+#if defined(SUPPORT_JOYSTICK)
+ if (have_joystick)
+ pci_unregister_driver(&joystick_driver);
+#endif
+}
+
+module_init(alsa_card_riptide_init);
+module_exit(alsa_card_riptide_exit);
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 0cbef5fe6c6..55b1d4838d9 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -227,7 +227,7 @@ struct rme32 {
struct snd_kcontrol *spdif_ctl;
};
-static struct pci_device_id snd_rme32_ids[] = {
+static struct pci_device_id snd_rme32_ids[] __devinitdata = {
{PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
{PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8,
@@ -313,7 +313,7 @@ static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int chann
}
/*
- * SPDIF I/O capabilites (half-duplex mode)
+ * SPDIF I/O capabilities (half-duplex mode)
*/
static struct snd_pcm_hardware snd_rme32_spdif_info = {
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
@@ -339,7 +339,7 @@ static struct snd_pcm_hardware snd_rme32_spdif_info = {
};
/*
- * ADAT I/O capabilites (half-duplex mode)
+ * ADAT I/O capabilities (half-duplex mode)
*/
static struct snd_pcm_hardware snd_rme32_adat_info =
{
@@ -364,7 +364,7 @@ static struct snd_pcm_hardware snd_rme32_adat_info =
};
/*
- * SPDIF I/O capabilites (full-duplex mode)
+ * SPDIF I/O capabilities (full-duplex mode)
*/
static struct snd_pcm_hardware snd_rme32_spdif_fd_info = {
.info = (SNDRV_PCM_INFO_MMAP |
@@ -390,7 +390,7 @@ static struct snd_pcm_hardware snd_rme32_spdif_fd_info = {
};
/*
- * ADAT I/O capabilites (full-duplex mode)
+ * ADAT I/O capabilities (full-duplex mode)
*/
static struct snd_pcm_hardware snd_rme32_adat_fd_info =
{
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 0e694b011dc..3c1bc533d51 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -232,7 +232,7 @@ struct rme96 {
struct snd_kcontrol *spdif_ctl;
};
-static struct pci_device_id snd_rme96_ids[] = {
+static struct pci_device_id snd_rme96_ids[] __devinitdata = {
{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8,
@@ -359,7 +359,7 @@ snd_rme96_capture_copy(struct snd_pcm_substream *substream,
}
/*
- * Digital output capabilites (S/PDIF)
+ * Digital output capabilities (S/PDIF)
*/
static struct snd_pcm_hardware snd_rme96_playback_spdif_info =
{
@@ -388,7 +388,7 @@ static struct snd_pcm_hardware snd_rme96_playback_spdif_info =
};
/*
- * Digital input capabilites (S/PDIF)
+ * Digital input capabilities (S/PDIF)
*/
static struct snd_pcm_hardware snd_rme96_capture_spdif_info =
{
@@ -417,7 +417,7 @@ static struct snd_pcm_hardware snd_rme96_capture_spdif_info =
};
/*
- * Digital output capabilites (ADAT)
+ * Digital output capabilities (ADAT)
*/
static struct snd_pcm_hardware snd_rme96_playback_adat_info =
{
@@ -442,7 +442,7 @@ static struct snd_pcm_hardware snd_rme96_playback_adat_info =
};
/*
- * Digital input capabilites (ADAT)
+ * Digital input capabilities (ADAT)
*/
static struct snd_pcm_hardware snd_rme96_capture_adat_info =
{
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index ebf7a2b86c2..61f82f0d5cc 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -568,7 +568,7 @@ static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_d
}
-static struct pci_device_id snd_hdsp_ids[] = {
+static struct pci_device_id snd_hdsp_ids[] __devinitdata = {
{
.vendor = PCI_VENDOR_ID_XILINX,
.device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP,
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 980b9cd689d..722b9e6ce54 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -426,7 +426,7 @@ static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = {
};
-static struct pci_device_id snd_hdspm_ids[] = {
+static struct pci_device_id snd_hdspm_ids[] __devinitdata = {
{
.vendor = PCI_VENDOR_ID_XILINX,
.device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
@@ -2256,7 +2256,7 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm
}
/* Channel playback mixer as default control
- Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats to big for any alsamixer
+ Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer
they are accesible via special IOCTL on hwdep
and the mixer 2dimensional mixer control */
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index a687eb63236..75d6406303d 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -315,7 +315,7 @@ static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_d
}
-static struct pci_device_id snd_rme9652_ids[] = {
+static struct pci_device_id snd_rme9652_ids[] __devinitdata = {
{
.vendor = 0x10ee,
.device = 0x3fc4,
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 7bbea3738b8..91f8bf3ae9f 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -30,6 +30,7 @@
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -242,7 +243,7 @@ struct sonicvibes {
#endif
};
-static struct pci_device_id snd_sonic_ids[] = {
+static struct pci_device_id snd_sonic_ids[] __devinitdata = {
{ 0x5333, 0xca00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
{ 0, }
};
@@ -1227,8 +1228,8 @@ static int __devinit snd_sonicvibes_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 24 bits */
- if (pci_set_dma_mask(pci, 0x00ffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) {
snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index b4538045049..9624a5f2b87 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -63,7 +63,7 @@ MODULE_PARM_DESC(pcm_channels, "Number of hardware channels assigned for PCM.");
module_param_array(wavetable_size, int, NULL, 0444);
MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth.");
-static struct pci_device_id snd_trident_ids[] = {
+static struct pci_device_id snd_trident_ids[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX),
PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
{PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX),
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 83b7d8aba9e..52178b8ad49 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/gameport.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/info.h>
@@ -3554,8 +3555,8 @@ int __devinit snd_trident_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 30 bits */
- if (pci_set_dma_mask(pci, 0x3fffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x3fffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_30BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_30BIT_MASK) < 0) {
snd_printk(KERN_ERR "architecture does not support 30bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 1957d29c119..39daf62d2ba 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -123,6 +123,7 @@ module_param(enable, bool, 0444);
#define VIA_REV_8233A 0x40 /* 1 rec, 1 multi-pb, spdf */
#define VIA_REV_8235 0x50 /* 2 rec, 4 pb, 1 multi-pb, spdif */
#define VIA_REV_8237 0x60
+#define VIA_REV_8251 0x70
/*
* Direct registers
@@ -395,7 +396,7 @@ struct via82xx {
#endif
};
-static struct pci_device_id snd_via82xx_ids[] = {
+static struct pci_device_id snd_via82xx_ids[] __devinitdata = {
/* 0x1106, 0x3058 */
{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA686, }, /* 686A */
/* 0x1106, 0x3059 */
@@ -862,6 +863,11 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(struct snd_pcm_substream *subst
if (!status)
status = inb(VIADEV_REG(viadev, OFFSET_STATUS));
+ /* An apparent bug in the 8251 is worked around by sending a
+ * REG_CTRL_START. */
+ if (chip->revision == VIA_REV_8251 && (status & VIA_REG_STAT_EOL))
+ snd_via82xx_pcm_trigger(substream, SNDRV_PCM_TRIGGER_START);
+
if (!(status & VIA_REG_STAT_ACTIVE)) {
res = 0;
goto unlock;
@@ -2313,6 +2319,7 @@ static struct via823x_info via823x_cards[] __devinitdata = {
{ VIA_REV_8233A, "VIA 8233A", TYPE_VIA8233A },
{ VIA_REV_8235, "VIA 8235", TYPE_VIA8233 },
{ VIA_REV_8237, "VIA 8237", TYPE_VIA8233 },
+ { VIA_REV_8251, "VIA 8251", TYPE_VIA8233 },
};
/*
@@ -2325,7 +2332,7 @@ struct dxs_whitelist {
short action; /* new dxs_support value */
};
-static int __devinit check_dxs_list(struct pci_dev *pci)
+static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
{
static struct dxs_whitelist whitelist[] = {
{ .subvendor = 0x1005, .subdevice = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
@@ -2333,6 +2340,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .subvendor = 0x1019, .subdevice = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
{ .subvendor = 0x1019, .subdevice = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
{ .subvendor = 0x1019, .subdevice = 0xa101, .action = VIA_DXS_SRC },
+ { .subvendor = 0x1019, .subdevice = 0xaa01, .action = VIA_DXS_SRC }, /* ECS K8T890-A */
{ .subvendor = 0x1025, .subdevice = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
{ .subvendor = 0x1025, .subdevice = 0x0046, .action = VIA_DXS_SRC }, /* Acer Aspire 1524 WLMi */
{ .subvendor = 0x1043, .subdevice = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
@@ -2341,6 +2349,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .subvendor = 0x1043, .subdevice = 0x810d, .action = VIA_DXS_SRC }, /* ASUS */
{ .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC }, /* ASUS A8V Deluxe */
{ .subvendor = 0x1043, .subdevice = 0x8174, .action = VIA_DXS_SRC }, /* ASUS */
+ { .subvendor = 0x1043, .subdevice = 0x81b9, .action = VIA_DXS_SRC }, /* ASUS A8V-MX */
{ .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
{ .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */
{ .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
@@ -2373,6 +2382,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
{ .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
{ .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
+ { .subvendor = 0x1695, .subdevice = 0x300c, .action = VIA_DXS_SRC }, /* EPoX EP-8KRAI */
{ .subvendor = 0x1695, .subdevice = 0x300e, .action = VIA_DXS_SRC }, /* EPoX 9HEAI */
{ .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */
{ .subvendor = 0x1734, .subdevice = 0x1078, .action = VIA_DXS_SRC }, /* FSC Amilo L7300 */
@@ -2403,6 +2413,10 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
}
}
+ /* for newer revision, default to DXS_SRC */
+ if (revision >= VIA_REV_8235)
+ return VIA_DXS_SRC;
+
/*
* not detected, try 48k rate only to be sure.
*/
@@ -2447,7 +2461,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
}
if (chip_type != TYPE_VIA8233A) {
if (dxs_support == VIA_DXS_AUTO)
- dxs_support = check_dxs_list(pci);
+ dxs_support = check_dxs_list(pci, revision);
/* force to use VIA8233 or 8233A model according to
* dxs_support module option
*/
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 22ce4d30992..ef97e50cd6c 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -261,7 +261,7 @@ struct via82xx_modem {
struct snd_info_entry *proc_entry;
};
-static struct pci_device_id snd_via82xx_modem_ids[] = {
+static struct pci_device_id snd_via82xx_modem_ids[] __devinitdata = {
{ 0x1106, 0x3068, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA82XX_MODEM, },
{ 0, }
};
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index c816ddf1b21..0f1ebb010a5 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -60,7 +60,7 @@ enum {
VX_PCI_VX222_NEW
};
-static struct pci_device_id snd_vx222_ids[] = {
+static struct pci_device_id snd_vx222_ids[] __devinitdata = {
{ 0x10b5, 0x9050, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_OLD, }, /* PLX */
{ 0x10b5, 0x9030, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_NEW, }, /* PLX */
{ 0, }
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index db57ce939fa..65ebf5f1933 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -70,7 +70,7 @@ MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch");
module_param_array(rear_swap, bool, NULL, 0444);
MODULE_PARM_DESC(rear_swap, "Swap rear channels (must be enabled for correct IEC958 (S/PDIF)) output");
-static struct pci_device_id snd_ymfpci_ids[] = {
+static struct pci_device_id snd_ymfpci_ids[] __devinitdata = {
{ 0x1073, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF724 */
{ 0x1073, 0x000d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF724F */
{ 0x1073, 0x000a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF740 */
diff --git a/sound/pcmcia/Kconfig b/sound/pcmcia/Kconfig
index 5d1b0b762ef..c9fa1a2bc58 100644
--- a/sound/pcmcia/Kconfig
+++ b/sound/pcmcia/Kconfig
@@ -5,7 +5,7 @@ menu "PCMCIA devices"
config SND_VXPOCKET
tristate "Digigram VXpocket"
- depends on SND && PCMCIA && ISA
+ depends on SND && PCMCIA
select SND_VX_LIB
help
Say Y here to include support for Digigram VXpocket and
@@ -16,7 +16,7 @@ config SND_VXPOCKET
config SND_PDAUDIOCF
tristate "Sound Core PDAudioCF"
- depends on SND && PCMCIA && ISA
+ depends on SND && PCMCIA
select SND_PCM
help
Say Y here to include support for Sound Core PDAudioCF
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 77caf43a310..adfdce7499d 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -57,18 +57,12 @@ static struct snd_card *card_list[SNDRV_CARDS];
/*
* prototypes
*/
-static void pdacf_config(dev_link_t *link);
+static int pdacf_config(struct pcmcia_device *link);
static void snd_pdacf_detach(struct pcmcia_device *p_dev);
-static void pdacf_release(dev_link_t *link)
+static void pdacf_release(struct pcmcia_device *link)
{
- if (link->state & DEV_CONFIG) {
- /* release cs resources */
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
- }
+ pcmcia_disable_device(link);
}
/*
@@ -76,7 +70,7 @@ static void pdacf_release(dev_link_t *link)
*/
static int snd_pdacf_free(struct snd_pdacf *pdacf)
{
- dev_link_t *link = &pdacf->link;
+ struct pcmcia_device *link = pdacf->p_dev;
pdacf_release(link);
@@ -96,10 +90,9 @@ static int snd_pdacf_dev_free(struct snd_device *device)
/*
* snd_pdacf_attach - attach callback for cs
*/
-static int snd_pdacf_attach(struct pcmcia_device *p_dev)
+static int snd_pdacf_probe(struct pcmcia_device *link)
{
int i;
- dev_link_t *link; /* Info for cardmgr */
struct snd_pdacf *pdacf;
struct snd_card *card;
static struct snd_device_ops ops = {
@@ -139,7 +132,7 @@ static int snd_pdacf_attach(struct pcmcia_device *p_dev)
pdacf->index = i;
card_list[i] = card;
- link = &pdacf->link;
+ pdacf->p_dev = link;
link->priv = pdacf;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -156,13 +149,7 @@ static int snd_pdacf_attach(struct pcmcia_device *p_dev)
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
- /* Chain drivers */
- link->next = NULL;
-
- link->handle = p_dev;
- pdacf_config(link);
-
- return 0;
+ return pdacf_config(link);
}
@@ -209,9 +196,8 @@ static int snd_pdacf_assign_resources(struct snd_pdacf *pdacf, int port, int irq
/*
* snd_pdacf_detach - detach callback for cs
*/
-static void snd_pdacf_detach(struct pcmcia_device *p_dev)
+static void snd_pdacf_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct snd_pdacf *chip = link->priv;
snd_printdd(KERN_DEBUG "pdacf_detach called\n");
@@ -230,13 +216,11 @@ static void snd_pdacf_detach(struct pcmcia_device *p_dev)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void pdacf_config(dev_link_t *link)
+static int pdacf_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct snd_pdacf *pdacf = link->priv;
tuple_t tuple;
cisparse_t *parse = NULL;
- config_info_t conf;
u_short buf[32];
int last_fn, last_ret;
@@ -244,7 +228,7 @@ static void pdacf_config(dev_link_t *link)
parse = kmalloc(sizeof(*parse), GFP_KERNEL);
if (! parse) {
snd_printk(KERN_ERR "pdacf_config: cannot allocate\n");
- return;
+ return -ENOMEM;
}
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
@@ -252,71 +236,51 @@ static void pdacf_config(dev_link_t *link)
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
link->conf.ConfigBase = parse->config.base;
link->conf.ConfigIndex = 0x5;
kfree(parse);
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
- link->conf.Vcc = conf.Vcc;
-
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
goto failed;
- link->dev = &pdacf->node;
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ link->dev_node = &pdacf->node;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
+ pcmcia_disable_device(link);
+ return -ENODEV;
}
#ifdef CONFIG_PM
-static int pdacf_suspend(struct pcmcia_device *dev)
+static int pdacf_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
struct snd_pdacf *chip = link->priv;
snd_printdd(KERN_DEBUG "SUSPEND\n");
- link->state |= DEV_SUSPEND;
if (chip) {
snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n");
snd_pdacf_suspend(chip, PMSG_SUSPEND);
}
- snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
-
return 0;
}
-static int pdacf_resume(struct pcmcia_device *dev)
+static int pdacf_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
struct snd_pdacf *chip = link->priv;
snd_printdd(KERN_DEBUG "RESUME\n");
- link->state &= ~DEV_SUSPEND;
-
- snd_printdd(KERN_DEBUG "CARD_RESET\n");
- if (DEV_OK(link)) {
- snd_printdd(KERN_DEBUG "requestconfig...\n");
- pcmcia_request_configuration(link->handle, &link->conf);
+ if (pcmcia_dev_present(link)) {
if (chip) {
snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n");
snd_pdacf_resume(chip);
@@ -343,7 +307,7 @@ static struct pcmcia_driver pdacf_cs_driver = {
.drv = {
.name = "snd-pdaudiocf",
},
- .probe = snd_pdacf_attach,
+ .probe = snd_pdacf_probe,
.remove = snd_pdacf_detach,
.id_table = snd_pdacf_ids,
#ifdef CONFIG_PM
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h
index 2744f189a61..9a14a4f64bd 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.h
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h
@@ -116,7 +116,7 @@ struct snd_pdacf {
void *pcm_area;
/* pcmcia stuff */
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
};
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 66900d20a42..7e0cda2b6ef 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -59,15 +59,9 @@ static unsigned int card_alloc;
/*
*/
-static void vxpocket_release(dev_link_t *link)
+static void vxpocket_release(struct pcmcia_device *link)
{
- if (link->state & DEV_CONFIG) {
- /* release cs resources */
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
- }
+ pcmcia_disable_device(link);
}
/*
@@ -132,9 +126,9 @@ static struct snd_vx_hardware vxp440_hw = {
/*
* create vxpocket instance
*/
-static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
+static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl,
+ struct pcmcia_device *link)
{
- dev_link_t *link; /* Info for cardmgr */
struct vx_core *chip;
struct snd_vxpocket *vxp;
static struct snd_device_ops ops = {
@@ -154,7 +148,7 @@ static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
vxp = (struct snd_vxpocket *)chip;
- link = &vxp->link;
+ vxp->p_dev = link;
link->priv = chip;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -167,7 +161,6 @@ static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
link->irq.Instance = chip;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
@@ -215,9 +208,8 @@ static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void vxpocket_config(dev_link_t *link)
+static int vxpocket_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct vx_core *chip = link->priv;
struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
tuple_t tuple;
@@ -229,24 +221,24 @@ static void vxpocket_config(dev_link_t *link)
parse = kmalloc(sizeof(*parse), GFP_KERNEL);
if (! parse) {
snd_printk(KERN_ERR "vx: cannot allocate\n");
- return;
+ return -ENOMEM;
}
tuple.Attributes = 0;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
/* redefine hardware record according to the VERSION1 string */
tuple.DesiredTuple = CISTPL_VERS_1;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
if (! strcmp(parse->version_1.str + parse->version_1.ofs[1], "VX-POCKET")) {
snd_printdd("VX-pocket is detected\n");
} else {
@@ -257,67 +249,50 @@ static void vxpocket_config(dev_link_t *link)
strcpy(chip->card->driver, vxp440_hw.name);
}
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
- chip->dev = &handle_to_dev(link->handle);
+ chip->dev = &handle_to_dev(link);
snd_card_set_dev(chip->card, chip->dev);
if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
goto failed;
- link->dev = &vxp->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ link->dev_node = &vxp->node;
kfree(parse);
- return;
+ return 9;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
failed:
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
kfree(parse);
+ return -ENODEV;
}
#ifdef CONFIG_PM
-static int vxp_suspend(struct pcmcia_device *dev)
+static int vxp_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
struct vx_core *chip = link->priv;
snd_printdd(KERN_DEBUG "SUSPEND\n");
- link->state |= DEV_SUSPEND;
if (chip) {
snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
snd_vx_suspend(chip, PMSG_SUSPEND);
}
- snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
return 0;
}
-static int vxp_resume(struct pcmcia_device *dev)
+static int vxp_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
struct vx_core *chip = link->priv;
snd_printdd(KERN_DEBUG "RESUME\n");
- link->state &= ~DEV_SUSPEND;
-
- snd_printdd(KERN_DEBUG "CARD_RESET\n");
- if (DEV_OK(link)) {
+ if (pcmcia_dev_present(link)) {
//struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
- snd_printdd(KERN_DEBUG "requestconfig...\n");
- pcmcia_request_configuration(link->handle, &link->conf);
if (chip) {
snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
snd_vx_resume(chip);
@@ -333,7 +308,7 @@ static int vxp_resume(struct pcmcia_device *dev)
/*
*/
-static int vxpocket_attach(struct pcmcia_device *p_dev)
+static int vxpocket_probe(struct pcmcia_device *p_dev)
{
struct snd_card *card;
struct snd_vxpocket *vxp;
@@ -358,7 +333,7 @@ static int vxpocket_attach(struct pcmcia_device *p_dev)
return -ENOMEM;
}
- vxp = snd_vxpocket_new(card, ibl[i]);
+ vxp = snd_vxpocket_new(card, ibl[i], p_dev);
if (! vxp) {
snd_card_free(card);
return -ENODEV;
@@ -368,20 +343,13 @@ static int vxpocket_attach(struct pcmcia_device *p_dev)
vxp->index = i;
card_alloc |= 1 << i;
- /* Chain drivers */
- vxp->link.next = NULL;
-
- vxp->link.handle = p_dev;
- vxp->link.state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- p_dev->instance = &vxp->link;
- vxpocket_config(&vxp->link);
+ vxp->p_dev = p_dev;
- return 0;
+ return vxpocket_config(p_dev);
}
-static void vxpocket_detach(struct pcmcia_device *p_dev)
+static void vxpocket_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
struct snd_vxpocket *vxp;
struct vx_core *chip;
@@ -413,7 +381,7 @@ static struct pcmcia_driver vxp_cs_driver = {
.drv = {
.name = "snd-vxpocket",
},
- .probe = vxpocket_attach,
+ .probe = vxpocket_probe,
.remove = vxpocket_detach,
.id_table = vxp_ids,
#ifdef CONFIG_PM
diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h
index 67efae3f6c8..27ea002294c 100644
--- a/sound/pcmcia/vx/vxpocket.h
+++ b/sound/pcmcia/vx/vxpocket.h
@@ -42,7 +42,7 @@ struct snd_vxpocket {
int index; /* card index */
/* pcmcia stuff */
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
};
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index aa09ebd9ffb..46eebf5610e 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -255,7 +255,7 @@ int __init snd_pmac_daca_init(struct snd_pmac *chip)
#ifdef CONFIG_KMOD
if (current->fs->root)
- request_module("i2c-keywest");
+ request_module("i2c-powermac");
#endif /* CONFIG_KMOD */
mix = kmalloc(sizeof(*mix), GFP_KERNEL);
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index aa57170101f..f0794ef9d1a 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -869,7 +869,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
u32 layout_id = 0;
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return -ENODEV;
chip->subframe = 0;
diff --git a/sound/ppc/toonie.c b/sound/ppc/toonie.c
index 4e595172e42..1ac7c8552f5 100644
--- a/sound/ppc/toonie.c
+++ b/sound/ppc/toonie.c
@@ -335,7 +335,7 @@ static void toonie_cleanup(struct snd_pmac *chip)
chip->mixer_data = NULL;
}
-int snd_pmac_toonie_init(struct snd_pmac *chip)
+int __init snd_pmac_toonie_init(struct snd_pmac *chip)
{
struct pmac_toonie *mix;
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 1146dd882bb..70e4ebc7026 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -1313,7 +1313,7 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip)
#ifdef CONFIG_KMOD
if (current->fs->root)
- request_module("i2c-keywest");
+ request_module("i2c-powermac");
#endif /* CONFIG_KMOD */
mix = kmalloc(sizeof(*mix), GFP_KERNEL);
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 394b53e20cb..6f849720aef 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -53,7 +53,7 @@
struct sound_unit
{
int unit_minor;
- struct file_operations *unit_fops;
+ const struct file_operations *unit_fops;
struct sound_unit *next;
char name[32];
};
@@ -73,7 +73,7 @@ EXPORT_SYMBOL(sound_class);
* join into it. Called with the lock asserted
*/
-static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, struct file_operations *fops, int index, int low, int top)
+static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, const struct file_operations *fops, int index, int low, int top)
{
int n=low;
@@ -153,7 +153,7 @@ static DEFINE_SPINLOCK(sound_loader_lock);
* list. Acquires locks as needed
*/
-static int sound_insert_unit(struct sound_unit **list, struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode, struct device *dev)
+static int sound_insert_unit(struct sound_unit **list, const struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode, struct device *dev)
{
struct sound_unit *s = kmalloc(sizeof(*s), GFP_KERNEL);
int r;
@@ -237,7 +237,7 @@ static struct sound_unit *chains[SOUND_STEP];
* a negative error code is returned.
*/
-int register_sound_special_device(struct file_operations *fops, int unit,
+int register_sound_special_device(const struct file_operations *fops, int unit,
struct device *dev)
{
const int chain = unit % SOUND_STEP;
@@ -301,7 +301,7 @@ int register_sound_special_device(struct file_operations *fops, int unit,
EXPORT_SYMBOL(register_sound_special_device);
-int register_sound_special(struct file_operations *fops, int unit)
+int register_sound_special(const struct file_operations *fops, int unit)
{
return register_sound_special_device(fops, unit, NULL);
}
@@ -318,7 +318,7 @@ EXPORT_SYMBOL(register_sound_special);
* number is returned, on failure a negative error code is returned.
*/
-int register_sound_mixer(struct file_operations *fops, int dev)
+int register_sound_mixer(const struct file_operations *fops, int dev)
{
return sound_insert_unit(&chains[0], fops, dev, 0, 128,
"mixer", S_IRUSR | S_IWUSR, NULL);
@@ -336,7 +336,7 @@ EXPORT_SYMBOL(register_sound_mixer);
* number is returned, on failure a negative error code is returned.
*/
-int register_sound_midi(struct file_operations *fops, int dev)
+int register_sound_midi(const struct file_operations *fops, int dev)
{
return sound_insert_unit(&chains[2], fops, dev, 2, 130,
"midi", S_IRUSR | S_IWUSR, NULL);
@@ -362,7 +362,7 @@ EXPORT_SYMBOL(register_sound_midi);
* and will always allocate them as a matching pair - eg dsp3/audio3
*/
-int register_sound_dsp(struct file_operations *fops, int dev)
+int register_sound_dsp(const struct file_operations *fops, int dev)
{
return sound_insert_unit(&chains[3], fops, dev, 3, 131,
"dsp", S_IWUSR | S_IRUSR, NULL);
@@ -381,7 +381,7 @@ EXPORT_SYMBOL(register_sound_dsp);
*/
-int register_sound_synth(struct file_operations *fops, int dev)
+int register_sound_synth(const struct file_operations *fops, int dev)
{
return sound_insert_unit(&chains[9], fops, dev, 9, 137,
"synth", S_IRUSR | S_IWUSR, NULL);
@@ -501,7 +501,7 @@ int soundcore_open(struct inode *inode, struct file *file)
int chain;
int unit = iminor(inode);
struct sound_unit *s;
- struct file_operations *new_fops = NULL;
+ const struct file_operations *new_fops = NULL;
chain=unit&0x0F;
if(chain==4 || chain==5) /* dsp/audio/dsp16 */
@@ -540,7 +540,7 @@ int soundcore_open(struct inode *inode, struct file *file)
* switching ->f_op in the first place.
*/
int err = 0;
- struct file_operations *old_fops = file->f_op;
+ const struct file_operations *old_fops = file->f_op;
file->f_op = new_fops;
spin_unlock(&sound_loader_lock);
if(file->f_op->open)
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 8d08b34a1cb..ce86283ee0f 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -306,8 +306,8 @@ static int get_relative_value(struct usb_mixer_elem_info *cval, int val)
cval->res = 1;
if (val < cval->min)
return 0;
- else if (val > cval->max)
- return (cval->max - cval->min) / cval->res;
+ else if (val >= cval->max)
+ return (cval->max - cval->min + cval->res - 1) / cval->res;
else
return (val - cval->min) / cval->res;
}
@@ -670,6 +670,36 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
}
if (cval->res == 0)
cval->res = 1;
+
+ /* Additional checks for the proper resolution
+ *
+ * Some devices report smaller resolutions than actually
+ * reacting. They don't return errors but simply clip
+ * to the lower aligned value.
+ */
+ if (cval->min + cval->res < cval->max) {
+ int last_valid_res = cval->res;
+ int saved, test, check;
+ get_cur_mix_value(cval, minchn, &saved);
+ for (;;) {
+ test = saved;
+ if (test < cval->max)
+ test += cval->res;
+ else
+ test -= cval->res;
+ if (test < cval->min || test > cval->max ||
+ set_cur_mix_value(cval, minchn, test) ||
+ get_cur_mix_value(cval, minchn, &check)) {
+ cval->res = last_valid_res;
+ break;
+ }
+ if (test == check)
+ break;
+ cval->res *= 2;
+ }
+ set_cur_mix_value(cval, minchn, saved);
+ }
+
cval->initialized = 1;
}
return 0;
@@ -695,7 +725,8 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
if (! cval->initialized)
get_min_max(cval, 0);
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = (cval->max - cval->min) / cval->res;
+ uinfo->value.integer.max =
+ (cval->max - cval->min + cval->res - 1) / cval->res;
}
return 0;
}
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 0992a0923f1..9351846d7a9 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -1531,6 +1531,15 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
+ USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0014),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "TerraTec",
+ .product_name = "PHASE 26",
+ .ifnum = 3,
+ .type = QUIRK_MIDI_STANDARD_INTERFACE
+ }
+},
+{
USB_DEVICE(0x0ccd, 0x0035),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Miditech",
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index 315855082fe..fe67a92e2a1 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -404,7 +404,7 @@ static void usX2Y_usbpcm_subs_startup(struct snd_usX2Y_substream *subs)
struct usX2Ydev * usX2Y = subs->usX2Y;
usX2Y->prepare_subs = subs;
subs->urb[0]->start_frame = -1;
- smp_wmb(); // Make shure above modifications are seen by i_usX2Y_subs_startup()
+ smp_wmb(); // Make sure above modifications are seen by i_usX2Y_subs_startup()
usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup);
}
diff --git a/usr/Makefile b/usr/Makefile
index e2129cb570b..19d74e6f268 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -1,65 +1,48 @@
+#
+# kbuild file for usr/ - including initramfs image
+#
-obj-y := initramfs_data.o
-
-hostprogs-y := gen_init_cpio
+klibcdirs:;
-clean-files := initramfs_data.cpio.gz initramfs_list
+# Generate builtin.o based on initramfs_data.o
+obj-y := initramfs_data.o
# initramfs_data.o contains the initramfs_data.cpio.gz image.
# The image is included using .incbin, a dependency which is not
# tracked automatically.
$(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE
-ifdef CONFIG_INITRAMFS_ROOT_UID
-gen_initramfs_args += -u $(CONFIG_INITRAMFS_ROOT_UID)
-endif
-
-ifdef CONFIG_INITRAMFS_ROOT_GID
-gen_initramfs_args += -g $(CONFIG_INITRAMFS_ROOT_GID)
-endif
-
-# The $(shell echo $(CONFIG_INITRAMFS_SOURCE)) is to remove the
-# gratuitous begin and end quotes from the Kconfig string type.
-# Internal, escaped quotes in the Kconfig string will loose the
-# escape and become active quotes.
-quotefixed_initramfs_source := $(shell echo $(CONFIG_INITRAMFS_SOURCE))
-
-filechk_initramfs_list = $(CONFIG_SHELL) \
- $(srctree)/scripts/gen_initramfs_list.sh $(gen_initramfs_args) $(quotefixed_initramfs_source)
-
-$(obj)/initramfs_list: $(obj)/Makefile FORCE
- $(call filechk,initramfs_list)
-
-quiet_cmd_cpio = CPIO $@
- cmd_cpio = ./$< $(obj)/initramfs_list > $@
-
-
-# Check if the INITRAMFS_SOURCE is a cpio archive
-ifneq (,$(findstring .cpio,$(quotefixed_initramfs_source)))
-
-# INITRAMFS_SOURCE has a cpio archive - verify that it's a single file
-ifneq (1,$(words $(quotefixed_initramfs_source)))
-$(error Only a single file may be specified in CONFIG_INITRAMFS_SOURCE (="$(quotefixed_initramfs_source)") when a cpio archive is directly specified.)
-endif
-# Now use the cpio archive directly
-initramfs_data_cpio = $(quotefixed_initramfs_source)
-targets += $(quotefixed_initramfs_source)
-
-else
-
-# INITRAMFS_SOURCE is not a cpio archive - create one
-$(obj)/initramfs_data.cpio: $(obj)/gen_init_cpio \
- $(initramfs-y) $(obj)/initramfs_list FORCE
- $(call if_changed,cpio)
-
-targets += initramfs_data.cpio
-initramfs_data_cpio = $(obj)/initramfs_data.cpio
-
+#####
+# Generate the initramfs cpio archive
+
+hostprogs-y := gen_init_cpio
+initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh
+ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
+ $(CONFIG_INITRAMFS_SOURCE),-d)
+ramfs-args := \
+ $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \
+ $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) \
+ $(ramfs-input)
+
+# .initramfs_data.cpio.gz.d is used to identify all files included
+# in initramfs and to detect if any files are added/removed.
+# Removed files are identified by directory timestamp being updated
+# The dependency list is generated by gen_initramfs.sh -l
+ifneq ($(wildcard $(obj)/.initramfs_data.cpio.gz.d),)
+ include $(obj)/.initramfs_data.cpio.gz.d
endif
-
-$(obj)/initramfs_data.cpio.gz: $(initramfs_data_cpio) FORCE
- $(call if_changed,gzip)
-
-targets += initramfs_data.cpio.gz
+quiet_cmd_initfs = GEN $@
+ cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
+
+targets := initramfs_data.cpio.gz
+$(deps_initramfs): klibcdirs
+# We rebuild initramfs_data.cpio.gz if:
+# 1) Any included file is newer then initramfs_data.cpio.gz
+# 2) There are changes in which files are included (added or deleted)
+# 3) If gen_init_cpio are newer than initramfs_data.cpio.gz
+# 4) arguments to gen_initramfs.sh changes
+$(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
+ $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d
+ $(call if_changed,initfs)
diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
index 33dbcbf77c5..83acd6cc0b3 100644
--- a/usr/gen_init_cpio.c
+++ b/usr/gen_init_cpio.c
@@ -471,6 +471,7 @@ int main (int argc, char *argv[])
"ERROR: incorrect format, could not locate file type line %d: '%s'\n",
line_nr, line);
ec = -1;
+ break;
}
if ('\n' == *type) {
@@ -506,7 +507,8 @@ int main (int argc, char *argv[])
line_nr, line);
}
}
- cpio_trailer();
+ if (ec == 0)
+ cpio_trailer();
exit(ec);
}